diff options
| author | Shoubhit Dash <[email protected]> | 2026-04-01 16:11:57 +0530 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-04-01 16:11:57 +0530 |
| commit | a3a6cf1c075c40c87980dda181d586a1d06ea304 (patch) | |
| tree | 71b3c3d7144f7c38eb73d7e173852858313fc4bf /packages/app/src/components | |
| parent | 47a676111a3532aebed01110494742e536b7e5b4 (diff) | |
| download | opencode-a3a6cf1c075c40c87980dda181d586a1d06ea304.tar.gz opencode-a3a6cf1c075c40c87980dda181d586a1d06ea304.zip | |
feat(comments): support file mentions (#20447)
Diffstat (limited to 'packages/app/src/components')
| -rw-r--r-- | packages/app/src/components/prompt-input/build-request-parts.test.ts | 24 | ||||
| -rw-r--r-- | packages/app/src/components/prompt-input/build-request-parts.ts | 26 |
2 files changed, 50 insertions, 0 deletions
diff --git a/packages/app/src/components/prompt-input/build-request-parts.test.ts b/packages/app/src/components/prompt-input/build-request-parts.test.ts index ce09ae921..06c377331 100644 --- a/packages/app/src/components/prompt-input/build-request-parts.test.ts +++ b/packages/app/src/components/prompt-input/build-request-parts.test.ts @@ -100,6 +100,30 @@ describe("buildRequestParts", () => { expect(synthetic).toHaveLength(1) }) + test("adds file parts for @mentions inside comment text", () => { + const result = buildRequestParts({ + prompt: [{ type: "text", content: "look", start: 0, end: 4 }], + context: [ + { + key: "ctx:comment-mention", + type: "file", + path: "src/review.ts", + comment: "Compare with @src/shared.ts and @src/review.ts.", + }, + ], + images: [], + text: "look", + messageID: "msg_comment_mentions", + sessionID: "ses_comment_mentions", + sessionDirectory: "/repo", + }) + + const files = result.requestParts.filter((part) => part.type === "file") + expect(files).toHaveLength(2) + expect(files.some((part) => part.type === "file" && part.url === "file:///repo/src/review.ts")).toBe(true) + expect(files.some((part) => part.type === "file" && part.url === "file:///repo/src/shared.ts")).toBe(true) + }) + test("handles Windows paths correctly (simulated on macOS)", () => { const prompt: Prompt = [{ type: "file", path: "src\\foo.ts", content: "@src\\foo.ts", start: 0, end: 11 }] diff --git a/packages/app/src/components/prompt-input/build-request-parts.ts b/packages/app/src/components/prompt-input/build-request-parts.ts index 4146fb484..a1076e60c 100644 --- a/packages/app/src/components/prompt-input/build-request-parts.ts +++ b/packages/app/src/components/prompt-input/build-request-parts.ts @@ -39,6 +39,16 @@ const absolute = (directory: string, path: string) => { const fileQuery = (selection: FileSelection | undefined) => selection ? `?start=${selection.startLine}&end=${selection.endLine}` : "" +const mention = /(^|[\s([{"'])@(\S+)/g + +const parseCommentMentions = (comment: string) => { + return Array.from(comment.matchAll(mention)).flatMap((match) => { + const path = (match[2] ?? "").replace(/[.,!?;:)}\]"']+$/, "") + if (!path) return [] + return [path] + }) +} + const isFileAttachment = (part: Prompt[number]): part is FileAttachmentPart => part.type === "file" const isAgentAttachment = (part: Prompt[number]): part is AgentPart => part.type === "agent" @@ -138,6 +148,21 @@ export function buildRequestParts(input: BuildRequestPartsInput) { if (!comment) return [filePart] + const mentions = parseCommentMentions(comment).flatMap((path) => { + const url = `file://${encodeFilePath(absolute(input.sessionDirectory, path))}` + if (used.has(url)) return [] + used.add(url) + return [ + { + id: Identifier.ascending("part"), + type: "file", + mime: "text/plain", + url, + filename: getFilename(path), + } satisfies PromptRequestPart, + ] + }) + return [ { id: Identifier.ascending("part"), @@ -153,6 +178,7 @@ export function buildRequestParts(input: BuildRequestPartsInput) { }), } satisfies PromptRequestPart, filePart, + ...mentions, ] }) |
