diff --git a/CLAUDE.md b/CLAUDE.md index a1e8cfe..de569e3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,7 +30,7 @@ Roundhouse is a chat-gateway between chat platforms (via Vercel Chat SDK) and a - `turn_end` / `agent_end` → flush so the next turn starts a fresh message If `promptStream` is missing, `agent.prompt()` is called and the full text is split/posted via `postWithFallback` (markdown-first, plaintext fallback). -**Pi adapter nuance — private event queue drain.** `src/agents/pi.ts` awaits `session._agentEventQueue` (a private field of `@mariozechner/pi-coding-agent`'s `AgentSession`) after every `prompt()` / `agent.continue()`. Without this drain, extension `agent_end` handlers (e.g. pi-lgtm's review) haven't finished and their `followUp` messages or `custom_message` events race against the `unsubscribe()` in the `finally` block, causing lost review bubbles. The field access is wrapped in `if (queue)` — if upstream renames it, behavior silently reverts to the pre-fix race. See the big comment in `drainSessionEvents()` for context before touching it. +**Pi adapter nuance — private event queue drain.** `src/agents/pi.ts` awaits `session._agentEventQueue` (a private field of `@earendil-works/pi-coding-agent`'s `AgentSession`) after every `prompt()` / `agent.continue()`. Without this drain, extension `agent_end` handlers (e.g. pi-lgtm's review) haven't finished and their `followUp` messages or `custom_message` events race against the `unsubscribe()` in the `finally` block, causing lost review bubbles. The field access is wrapped in `if (queue)` — if upstream renames it, behavior silently reverts to the pre-fix race. See the big comment in `drainSessionEvents()` for context before touching it. **Pi adapter nuance — subscribers must outlive extension-triggered runs.** `runPromptAndFollowUps` loops on *both* `session.isStreaming` (awaits `agent.waitForIdle()`) and `agent.hasQueuedMessages()` (awaits `agent.continue()`). When an extension calls `pi.sendMessage(..., { triggerTurn: true, deliverAs: "followUp" })` inside its `agent_end` handler, pi's `sendCustomMessage` picks one of two branches depending on `isStreaming` at that moment: if still streaming it queues via `agent.followUp()` (caught by `hasQueuedMessages`); if already idle it bypasses the queue and calls `agent.prompt(appMessage)` directly as fire-and-forget, kicking off a new run that is *only* visible via `isStreaming`. The pi CLI is immune because its subscriber stays attached across runs; our per-prompt subscriber must loop on both conditions or we unsubscribe mid-run and Telegram sees the review bubble followed by silence. Don't collapse the loop to a single condition. diff --git a/package-lock.json b/package-lock.json index 5336eae..aaf2521 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "@inceptionstack/roundhouse", - "version": "0.5.4", + "version": "0.5.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@inceptionstack/roundhouse", - "version": "0.5.4", + "version": "0.5.10", "license": "MIT", "dependencies": { "@chat-adapter/state-memory": "^4.26.0", "@chat-adapter/telegram": "^4.26.0", - "@mariozechner/pi-coding-agent": "^0.69.0", + "@earendil-works/pi-coding-agent": "^0.74.0", "chat": "^4.26.0", "croner": "^10.0.1", "p-queue": "^9.2.0", @@ -25,26 +25,6 @@ "vitest": "^4.1.5" } }, - "node_modules/@anthropic-ai/sdk": { - "version": "0.90.0", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.90.0.tgz", - "integrity": "sha512-MzZtPabJF1b0FTDl6Z6H5ljphPwACLGP13lu8MTiB8jXaW/YXlpOp+Po2cVou3MPM5+f5toyLnul9whKCy7fBg==", - "license": "MIT", - "dependencies": { - "json-schema-to-ts": "^3.1.1" - }, - "bin": { - "anthropic-ai-sdk": "bin/cli" - }, - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } - } - }, "node_modules/@aws-crypto/crc32": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", @@ -843,6 +823,134 @@ "chat": "4.26.0" } }, + "node_modules/@earendil-works/pi-agent-core": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.74.0.tgz", + "integrity": "sha512-6GMR7/wwjEJ1EsXLWEz03QOWin4AMrJ/AZoMpgm5DJ6GHsF6q6GOhQbj5Zip4dow3vo/TmBAVqM+vmGfrjGAFQ==", + "license": "MIT", + "dependencies": { + "@earendil-works/pi-ai": "^0.74.0", + "typebox": "^1.1.24" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-ai": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.74.0.tgz", + "integrity": "sha512-7M7qcrZY/KEkH4wFkX3eqzvmKru4O88wezNKoN0KD2m4aAOmp9tdW2xCmUgSTSWlKB7b2Xw9QtAgrzHtg6t6iw==", + "license": "MIT", + "dependencies": { + "@anthropic-ai/sdk": "^0.91.1", + "@aws-sdk/client-bedrock-runtime": "^3.1030.0", + "@google/genai": "^1.40.0", + "@mistralai/mistralai": "^2.2.0", + "chalk": "^5.6.2", + "openai": "6.26.0", + "partial-json": "^0.1.7", + "proxy-agent": "^6.5.0", + "typebox": "^1.1.24", + "undici": "^7.19.1", + "zod-to-json-schema": "^3.24.6" + }, + "bin": { + "pi-ai": "dist/cli.js" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-ai/node_modules/@anthropic-ai/sdk": { + "version": "0.91.1", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.91.1.tgz", + "integrity": "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==", + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "^3.1.1" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@earendil-works/pi-coding-agent": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-coding-agent/-/pi-coding-agent-0.74.0.tgz", + "integrity": "sha512-Q5GikbB5vRBrsrrf/uvet53rPSQ1sn5I5mO+l7sIobdXYpS04/X2oOc2UHFm90fNdkl3yU+ANTZL0zOtHbnqRw==", + "license": "MIT", + "dependencies": { + "@earendil-works/pi-agent-core": "^0.74.0", + "@earendil-works/pi-ai": "^0.74.0", + "@earendil-works/pi-tui": "^0.74.0", + "@silvia-odwyer/photon-node": "^0.3.4", + "chalk": "^5.5.0", + "cli-highlight": "^2.1.11", + "diff": "^8.0.2", + "extract-zip": "^2.0.1", + "file-type": "^21.1.1", + "glob": "^13.0.1", + "hosted-git-info": "^9.0.2", + "ignore": "^7.0.5", + "jiti": "^2.7.0", + "marked": "^15.0.12", + "minimatch": "^10.2.3", + "proper-lockfile": "^4.1.2", + "strip-ansi": "^7.1.0", + "typebox": "^1.1.24", + "undici": "^7.19.1", + "uuid": "^14.0.0", + "yaml": "^2.8.2" + }, + "bin": { + "pi": "dist/cli.js" + }, + "engines": { + "node": ">=20.6.0" + }, + "optionalDependencies": { + "@mariozechner/clipboard": "^0.3.5" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/uuid": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", + "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/@earendil-works/pi-tui": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.74.0.tgz", + "integrity": "sha512-1aIfXZp7D/z+1VlZX8BZcs6pgO8rjmil7kwyhctNDsWvce3Yfl8GVgu4eq+I0Mjhr8Cj+ipBiv9CLIzdoyCOIQ==", + "license": "MIT", + "dependencies": { + "@types/mime-types": "^2.1.4", + "chalk": "^5.5.0", + "get-east-asian-width": "^1.3.0", + "marked": "^15.0.12", + "mime-types": "^3.0.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "optionalDependencies": { + "koffi": "^2.9.0" + } + }, "node_modules/@emnapi/core": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", @@ -1324,9 +1432,9 @@ "license": "MIT" }, "node_modules/@mariozechner/clipboard": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@mariozechner/clipboard/-/clipboard-0.3.2.tgz", - "integrity": "sha512-IHQpksNjo7EAtGuHFU+tbWDp5LarH3HU/8WiB9O70ZEoBPHOg0/6afwSLK0QyNMMmx4Bpi/zl6+DcBXe95nWYA==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard/-/clipboard-0.3.5.tgz", + "integrity": "sha512-D3F+UrU9CR7roJt0zDLp6Oc+4/KlLDIrN4frH+6V90SJNW2KKUec1oCQIPaaDjCqeOsQyX9dyqYbImIQIM45PA==", "license": "MIT", "optional": true, "engines": { @@ -1502,114 +1610,6 @@ "node": ">= 10" } }, - "node_modules/@mariozechner/jiti": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@mariozechner/jiti/-/jiti-2.6.5.tgz", - "integrity": "sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==", - "license": "MIT", - "dependencies": { - "std-env": "^3.10.0", - "yoctocolors": "^2.1.2" - }, - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/@mariozechner/pi-agent-core": { - "version": "0.69.0", - "resolved": "https://registry.npmjs.org/@mariozechner/pi-agent-core/-/pi-agent-core-0.69.0.tgz", - "integrity": "sha512-dYZjee7QEIwVVbDGCGriiLjDT34IdMlXMjMp4drVKcLEuVc+BztyODwu3w4ZORVvwaySGGlF9UALjJKUVoXiug==", - "license": "MIT", - "dependencies": { - "@mariozechner/pi-ai": "^0.69.0", - "typebox": "^1.1.24" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@mariozechner/pi-ai": { - "version": "0.69.0", - "resolved": "https://registry.npmjs.org/@mariozechner/pi-ai/-/pi-ai-0.69.0.tgz", - "integrity": "sha512-bl838sr57zx/apkiTeNPFQgbBkGXN4HHhm2oghzSRohJIBrR+H001bTeco7Osuke+EZTxO3V5Aev2qlZdUa2xw==", - "license": "MIT", - "dependencies": { - "@anthropic-ai/sdk": "^0.90.0", - "@aws-sdk/client-bedrock-runtime": "^3.1030.0", - "@google/genai": "^1.40.0", - "@mistralai/mistralai": "^2.2.0", - "chalk": "^5.6.2", - "openai": "6.26.0", - "partial-json": "^0.1.7", - "proxy-agent": "^6.5.0", - "typebox": "^1.1.24", - "undici": "^7.19.1", - "zod-to-json-schema": "^3.24.6" - }, - "bin": { - "pi-ai": "dist/cli.js" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@mariozechner/pi-coding-agent": { - "version": "0.69.0", - "resolved": "https://registry.npmjs.org/@mariozechner/pi-coding-agent/-/pi-coding-agent-0.69.0.tgz", - "integrity": "sha512-/EFn43RO2TtMgZI4fMXNepIvbWm2GqhhaLIHBkrO7tRbRCzgvDYkw9sMLKhdf1Ihom2CjC3T/fzQRIPasRSIrQ==", - "license": "MIT", - "dependencies": { - "@mariozechner/jiti": "^2.6.2", - "@mariozechner/pi-agent-core": "^0.69.0", - "@mariozechner/pi-ai": "^0.69.0", - "@mariozechner/pi-tui": "^0.69.0", - "@silvia-odwyer/photon-node": "^0.3.4", - "chalk": "^5.5.0", - "cli-highlight": "^2.1.11", - "diff": "^8.0.2", - "extract-zip": "^2.0.1", - "file-type": "^21.1.1", - "glob": "^13.0.1", - "hosted-git-info": "^9.0.2", - "ignore": "^7.0.5", - "marked": "^15.0.12", - "minimatch": "^10.2.3", - "proper-lockfile": "^4.1.2", - "strip-ansi": "^7.1.0", - "typebox": "^1.1.24", - "undici": "^7.19.1", - "uuid": "^11.1.0", - "yaml": "^2.8.2" - }, - "bin": { - "pi": "dist/cli.js" - }, - "engines": { - "node": ">=20.6.0" - }, - "optionalDependencies": { - "@mariozechner/clipboard": "^0.3.2" - } - }, - "node_modules/@mariozechner/pi-tui": { - "version": "0.69.0", - "resolved": "https://registry.npmjs.org/@mariozechner/pi-tui/-/pi-tui-0.69.0.tgz", - "integrity": "sha512-/82SOMzCA1srivwfcSO8r9XLdAgJNcgpWzNZY33IqqvGev8Q4iWY/hA1wAkLB0l7PKJJ4Dh57xS4IGHbyVM7lA==", - "license": "MIT", - "dependencies": { - "@types/mime-types": "^2.1.4", - "chalk": "^5.5.0", - "get-east-asian-width": "^1.3.0", - "marked": "^15.0.12", - "mime-types": "^3.0.1" - }, - "engines": { - "node": ">=20.0.0" - }, - "optionalDependencies": { - "koffi": "^2.9.0" - } - }, "node_modules/@mistralai/mistralai": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-2.2.1.tgz", @@ -3881,6 +3881,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/json-bigint": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", @@ -5690,12 +5699,6 @@ "dev": true, "license": "MIT" }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "license": "MIT" - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6017,19 +6020,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -6385,18 +6375,6 @@ "fd-slicer": "~1.1.0" } }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/zod": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", diff --git a/package.json b/package.json index f37ef9a..3506e1b 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "dependencies": { "@chat-adapter/state-memory": "^4.26.0", "@chat-adapter/telegram": "^4.26.0", - "@mariozechner/pi-coding-agent": "^0.69.0", + "@earendil-works/pi-coding-agent": "^0.74.0", "chat": "^4.26.0", "croner": "^10.0.1", "p-queue": "^9.2.0", diff --git a/pi/extensions/web-search.ts b/pi/extensions/web-search.ts index 41725ec..8c6bb17 100644 --- a/pi/extensions/web-search.ts +++ b/pi/extensions/web-search.ts @@ -1,4 +1,4 @@ -import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; +import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { Type } from "typebox"; export default function (pi: ExtensionAPI) { diff --git a/src/agents/pi/message-format.ts b/src/agents/pi/message-format.ts index 0c00367..0d5c2a2 100644 --- a/src/agents/pi/message-format.ts +++ b/src/agents/pi/message-format.ts @@ -6,7 +6,7 @@ */ import type { AgentMessage } from "../../types"; -import type { AgentSessionEvent } from "@mariozechner/pi-coding-agent"; +import type { AgentSessionEvent } from "@earendil-works/pi-coding-agent"; /** * Convert custom message content (string or array of parts) to plain text. diff --git a/src/agents/pi/pi-adapter.ts b/src/agents/pi/pi-adapter.ts index 3ec58ba..0ea71bd 100644 --- a/src/agents/pi/pi-adapter.ts +++ b/src/agents/pi/pi-adapter.ts @@ -24,7 +24,7 @@ import { SessionManager, type AgentSession, type AgentSessionEvent, -} from "@mariozechner/pi-coding-agent"; +} from "@earendil-works/pi-coding-agent"; import type { AgentAdapter, AgentAdapterFactory, AgentMessage, AgentResponse, AgentStreamEvent, MessageContext } from "../../types"; import { formatMessage, extractCustomMessage, customContentToText } from "./message-format"; @@ -66,7 +66,7 @@ export const createPiAgentAdapter: AgentAdapterFactory = (config) => { // // WARNING: _agentEventQueue is a private field of AgentSession (not part // of the public pi-coding-agent API). Tested against - // @mariozechner/pi-coding-agent version bundled via `latest` in + // @earendil-works/pi-coding-agent version bundled via `latest` in // package.json at the time of this commit. If upstream renames or changes // this field, extension custom messages (e.g. pi-lgtm review bubbles) // will stop reaching Telegram. The `if (queue)` check fails silently @@ -558,7 +558,7 @@ export const createPiAgentAdapter: AgentAdapterFactory = (config) => { // Read agent version let version = "unknown"; try { - const piPkgPath = join(__piAdapterDir, "..", "..", "..", "node_modules", "@mariozechner", "pi-coding-agent", "package.json"); + const piPkgPath = join(__piAdapterDir, "..", "..", "..", "node_modules", "@earendil-works", "pi-coding-agent", "package.json"); version = JSON.parse(readFileSync(piPkgPath, "utf8")).version; } catch {} diff --git a/src/agents/registry.ts b/src/agents/registry.ts index 3699f91..054fb70 100644 --- a/src/agents/registry.ts +++ b/src/agents/registry.ts @@ -69,12 +69,12 @@ const piDefinition: AgentDefinition = { packages: [ { name: "Pi coding agent", - packageName: "@mariozechner/pi-coding-agent", + packageName: "@earendil-works/pi-coding-agent", install: "global", binary: "pi", }, ], - sdkPackage: "@mariozechner/pi-coding-agent", + sdkPackage: "@earendil-works/pi-coding-agent", configDefaults: {}, configDirs: [resolve(homedir(), ".pi", "agent")], // configure and installExtension are set by setup.ts since they need diff --git a/src/cli/doctor/checks/agent.ts b/src/cli/doctor/checks/agent.ts index 92ed292..f285d53 100644 --- a/src/cli/doctor/checks/agent.ts +++ b/src/cli/doctor/checks/agent.ts @@ -12,7 +12,7 @@ export const agentChecks: DoctorCheck[] = [ { id: "pi-sdk", category: "agent", name: "Pi SDK", async run() { - const PI_PKG = join("@mariozechner", "pi-coding-agent", "package.json"); + const PI_PKG = join("@earendil-works", "pi-coding-agent", "package.json"); const searchPaths = [ join(process.cwd(), "node_modules", PI_PKG), ]; @@ -31,8 +31,8 @@ export const agentChecks: DoctorCheck[] = [ } return { id: "pi-sdk", category: "agent", name: "Pi SDK", status: "fail" as const, summary: "not found", - details: ["@mariozechner/pi-coding-agent not installed"], - fix: { description: "Install pi SDK", command: "npm install @mariozechner/pi-coding-agent" }, + details: ["@earendil-works/pi-coding-agent not installed"], + fix: { description: "Install pi SDK", command: "npm install -g @earendil-works/pi-coding-agent" }, }; }, }, diff --git a/test/telegram-setup.test.ts b/test/telegram-setup.test.ts index df250e2..56b2253 100644 --- a/test/telegram-setup.test.ts +++ b/test/telegram-setup.test.ts @@ -249,7 +249,7 @@ describe("agent registry", () => { expect(def.name).toBe("Pi"); expect(def.available).toBe(true); expect(def.packages.length).toBeGreaterThan(0); - expect(def.packages[0].packageName).toBe("@mariozechner/pi-coding-agent"); + expect(def.packages[0].packageName).toBe("@earendil-works/pi-coding-agent"); }); it("getAgentDefinition throws for unknown type", async () => { @@ -269,7 +269,7 @@ describe("agent registry", () => { it("getAgentSdkPackage returns pi package name", async () => { const { getAgentSdkPackage } = await import("../src/agents/registry"); - expect(getAgentSdkPackage("pi")).toBe("@mariozechner/pi-coding-agent"); + expect(getAgentSdkPackage("pi")).toBe("@earendil-works/pi-coding-agent"); }); });