From a96ed80cd5c3bac5ab8b7e26bf991711ce4c6e2a Mon Sep 17 00:00:00 2001 From: Alex Southwell <4596216+saphid@users.noreply.github.com> Date: Tue, 3 Nov 2026 11:26:14 +1100 Subject: [PATCH 1/2] fix(pi): extension errors name folder extensions instead of "index" Co-Authored-By: Claude Opus 5.5 --- packages/provider-pi/src/server/adapter.test.ts | 9 ++++++++- packages/provider-pi/src/server/adapter.ts | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/provider-pi/src/server/adapter.test.ts b/packages/provider-pi/src/server/adapter.test.ts index 5c94de304020..e30a3ea4ba78 100644 --- a/packages/provider-pi/src/server/adapter.test.ts +++ b/packages/provider-pi/src/server/adapter.test.ts @@ -1548,7 +1548,11 @@ describe("PiAdapterV2", () => { method: "notify", message: "note", }); - yield* fake.emit({ type: "extension_error", extensionPath: "/ext/a.ts", error: "boom" }); + yield* fake.emit({ + type: "extension_error", + extensionPath: "/ext/a/index.ts", + error: "boom", + }); for (const prefix of ["notify:", "extension-error:"]) { const item = yield* takeEvent( (event) => @@ -1556,6 +1560,9 @@ describe("PiAdapterV2", () => { event.turnItem.nativeItemRef?.nativeId?.startsWith(prefix) === true, ); if (item.type === "turn_item.updated") itemIds.add(item.turnItem.id); + if (item.type === "turn_item.updated" && prefix === "extension-error:") { + assert.equal(item.turnItem.title, "a"); + } } } assert.equal(itemIds.size, 4); diff --git a/packages/provider-pi/src/server/adapter.ts b/packages/provider-pi/src/server/adapter.ts index a32a5759ba70..d67a947c2fee 100644 --- a/packages/provider-pi/src/server/adapter.ts +++ b/packages/provider-pi/src/server/adapter.ts @@ -3298,8 +3298,10 @@ function piSubagentOutput(result: unknown): string { function piExtensionDisplayName(extensionPath: string | undefined): string { if (extensionPath === undefined) return "Pi extension"; - const normalized = extensionPath.replace(/\\/g, "/").replace(/\/+$/, ""); - const name = normalized.slice(normalized.lastIndexOf("/") + 1).replace(/\.[^.]+$/, ""); + const segments = extensionPath.replace(/\\/g, "/").split("/").filter(Boolean); + const fileName = segments.at(-1)?.replace(/\.[^.]+$/, "") ?? ""; + // Pi loads a directory extension from its index file; the folder names it. + const name = fileName === "index" ? (segments.at(-2) ?? fileName) : fileName; return name.length === 0 ? "Pi extension" : name; } From d823fa4c4d714662828140d8414a6f6d1830d6f7 Mon Sep 17 00:00:00 2001 From: Alex Southwell <4596216+saphid@users.noreply.github.com> Date: Tue, 3 Nov 2026 12:42:33 +1100 Subject: [PATCH 2/2] test(pi): cover single-file extension names alongside folder index Co-Authored-By: Claude Opus 5.5 --- packages/provider-pi/src/server/adapter.test.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/provider-pi/src/server/adapter.test.ts b/packages/provider-pi/src/server/adapter.test.ts index e30a3ea4ba78..67c2c8f4fc86 100644 --- a/packages/provider-pi/src/server/adapter.test.ts +++ b/packages/provider-pi/src/server/adapter.test.ts @@ -1523,7 +1523,10 @@ describe("PiAdapterV2", () => { it.effect("gives notify and extension-error items distinct ids in each thread", () => Effect.gen(function* () { const itemIds = new Set(); - for (const threadId of [THREAD_ID, ThreadId.make("thread-pi-test-2")]) { + for (const [threadId, extensionPath] of [ + [THREAD_ID, "/ext/a.ts"], + [ThreadId.make("thread-pi-test-2"), "/ext/a/index.ts"], + ] as const) { const fake = yield* makeFakePi; const { runtime, takeEvent } = yield* openRuntime(fake, "default", threadId); const providerThread = yield* runtime.ensureThread({ @@ -1548,11 +1551,7 @@ describe("PiAdapterV2", () => { method: "notify", message: "note", }); - yield* fake.emit({ - type: "extension_error", - extensionPath: "/ext/a/index.ts", - error: "boom", - }); + yield* fake.emit({ type: "extension_error", extensionPath, error: "boom" }); for (const prefix of ["notify:", "extension-error:"]) { const item = yield* takeEvent( (event) =>