diff --git a/packages/opencode/src/acp/content.ts b/packages/opencode/src/acp/content.ts index 5f149d85f0f2..bbbbecbb7bc5 100644 --- a/packages/opencode/src/acp/content.ts +++ b/packages/opencode/src/acp/content.ts @@ -76,7 +76,19 @@ export function contentBlockToParts(block: ContentBlock): PromptPart[] { case "resource": if ("text" in block.resource) { - return [{ type: "text", text: block.resource.text }] + const { uri, text } = block.resource + let source = uri + try { + if (uri.startsWith("zed://")) { + source = new URL(uri).searchParams.get("path") ?? uri + } else if (uri.startsWith("file://")) { + const u = new URL(uri) + source = u.pathname + u.hash + } + } catch { + // keep uri as-is + } + return [{ type: "text", text: `${source}\n${text}` }] } if (block.resource.mimeType) { return [ diff --git a/packages/opencode/test/acp/content.test.ts b/packages/opencode/test/acp/content.test.ts index 90f62f9d1892..d75f42668d41 100644 --- a/packages/opencode/test/acp/content.test.ts +++ b/packages/opencode/test/acp/content.test.ts @@ -99,7 +99,7 @@ describe("acp content conversion", () => { ]) }) - test("resource with text becomes a text part", () => { + test("resource with text includes file path prefix so LLM knows the source", () => { expect( contentBlockToParts({ type: "resource", @@ -109,7 +109,31 @@ describe("acp content conversion", () => { text: "context", }, }), - ).toEqual([{ type: "text", text: "context" }]) + ).toEqual([{ type: "text", text: "/tmp/context.txt\ncontext" }]) + }) + + test("resource with zed:// uri decodes path for the prefix", () => { + expect( + contentBlockToParts({ + type: "resource", + resource: { + uri: "zed://workspace?path=/home/user/project/src/main.ts", + text: "export function main() {}", + }, + }), + ).toEqual([{ type: "text", text: "/home/user/project/src/main.ts\nexport function main() {}" }]) + }) + + test("resource with file:// uri preserves line-range fragment in prefix", () => { + expect( + contentBlockToParts({ + type: "resource", + resource: { + uri: "file:///src/app.ts#L10-L20", + text: "const x = 1", + }, + }), + ).toEqual([{ type: "text", text: "/src/app.ts#L10-L20\nconst x = 1" }]) }) test("resource with blob and mimeType becomes a data URL file part", () => { diff --git a/packages/ui/src/components/file.tsx b/packages/ui/src/components/file.tsx index 8c8096375a39..fb9a5b91cfd7 100644 --- a/packages/ui/src/components/file.tsx +++ b/packages/ui/src/components/file.tsx @@ -52,7 +52,6 @@ const VIRTUALIZE_BYTES = 500_000 const codeMetrics = { ...DEFAULT_VIRTUAL_FILE_METRICS, lineHeight: 24, - spacing: 0, } satisfies Partial type SharedProps = { diff --git a/packages/ui/src/pierre/virtualizer.ts b/packages/ui/src/pierre/virtualizer.ts index 235a3fd67734..369d36eab585 100644 --- a/packages/ui/src/pierre/virtualizer.ts +++ b/packages/ui/src/pierre/virtualizer.ts @@ -16,7 +16,6 @@ const cache = new WeakMap() export const virtualMetrics: Partial = { lineHeight: 24, hunkSeparatorHeight: 24, - spacing: 0, } function scrollable(value: string) {