fix(api): include attachment metadata in heartbeat-context response

Agents receiving issue context via GET /issues/:id/heartbeat-context
had no way to discover file attachments — the endpoint returned issue
metadata, ancestors, project, goal, and comment cursor but omitted
attachments entirely. Users attaching files through the UI would then
see agents ask for documents that were already uploaded.

Fetch attachments in parallel with the existing queries and append a
lightweight summary (id, filename, contentType, byteSize, contentPath)
to the response so agents can detect and retrieve attached files on
their first heartbeat without an extra round-trip.

Closes #2536
This commit is contained in:
plind-dm
2026-04-03 01:53:57 +09:00
parent 36376968af
commit 1350753f5f
2 changed files with 12 additions and 1 deletions
@@ -10,6 +10,7 @@ const mockIssueService = vi.hoisted(() => ({
findMentionedProjectIds: vi.fn(),
getCommentCursor: vi.fn(),
getComment: vi.fn(),
listAttachments: vi.fn(),
}));
const mockProjectService = vi.hoisted(() => ({
@@ -129,6 +130,7 @@ describe("issue goal context routes", () => {
latestCommentAt: null,
});
mockIssueService.getComment.mockResolvedValue(null);
mockIssueService.listAttachments.mockResolvedValue([]);
mockProjectService.getById.mockResolvedValue({
id: legacyProjectLinkedIssue.projectId,
companyId: "company-1",
+10 -1
View File
@@ -448,11 +448,12 @@ export function issueRoutes(db: Db, storage: StorageService) {
? req.query.wakeCommentId.trim()
: null;
const [{ project, goal }, ancestors, commentCursor, wakeComment] = await Promise.all([
const [{ project, goal }, ancestors, commentCursor, wakeComment, attachments] = await Promise.all([
resolveIssueProjectAndGoal(issue),
svc.getAncestors(issue.id),
svc.getCommentCursor(issue.id),
wakeCommentId ? svc.getComment(wakeCommentId) : null,
svc.listAttachments(issue.id),
]);
res.json({
@@ -499,6 +500,14 @@ export function issueRoutes(db: Db, storage: StorageService) {
wakeComment && wakeComment.issueId === issue.id
? wakeComment
: null,
attachments: attachments.map((a) => ({
id: a.id,
filename: a.originalFilename,
contentType: a.contentType,
byteSize: a.byteSize,
contentPath: `/api/attachments/${a.id}/content`,
createdAt: a.createdAt,
})),
});
});