From f42b776b8e4d0a34eb2ef37a2e89181c66e242ed Mon Sep 17 00:00:00 2001 From: Kashyab Ambarani Date: Tue, 22 Sep 2026 15:05:44 -0700 Subject: [PATCH] fix: require Pi 0.86 and test transcript context mapping --- .gitignore | 1 + README.md | 10 +++++--- package.json | 7 +++--- test/context-map.test.mjs | 49 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 test/context-map.test.mjs diff --git a/.gitignore b/.gitignore index 3bb8d1a..881646a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ package-lock.json .DS_Store *.log .env +.reference/ diff --git a/README.md b/README.md index 9d57e62..1686f96 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ Those models are available through the local Devin CLI. This package uses that C ## Requirements -- Pi Coding Agent 0.80+ +- Pi Coding Agent 0.86+ - A signed-in [Devin CLI](https://docs.devin.ai/cli) (`devin auth status`) -- Node 18+ +- Node 22.19+ (required by Pi 0.86) The CLI binary is resolved in this order: @@ -35,12 +35,16 @@ From git: pi install git:github.com/kashyab12/pi-devin ``` -After npm publish: +From npm: ```bash pi install npm:pi-devin ``` +The published `pi-devin@0.1.2` predates Pi 0.86 support. For Pi 0.86+, use the git install above until a newer npm release is available. + +`pi-devin-local` is a separate npm package maintained in the [mizorewww/pi-devin fork](https://github.com/mizorewww/pi-devin). Changes merged here do not update that package. Install only one: both packages register the `devin` provider, so their registrations can overwrite each other. + Local checkout: ```bash diff --git a/package.json b/package.json index f108db7..4af8261 100644 --- a/package.json +++ b/package.json @@ -29,17 +29,18 @@ "LICENSE" ], "scripts": { + "test": "node --test test/*.test.mjs", "typecheck": "tsc --noEmit" }, "peerDependencies": { - "@earendil-works/pi-ai": "*", - "@earendil-works/pi-coding-agent": "*" + "@earendil-works/pi-ai": ">=0.86.0", + "@earendil-works/pi-coding-agent": ">=0.86.0" }, "devDependencies": { "@types/node": "^24.13.3", "typescript": "^5.9.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=22.19.0" } } diff --git a/test/context-map.test.mjs b/test/context-map.test.mjs new file mode 100644 index 0000000..e9c99bb --- /dev/null +++ b/test/context-map.test.mjs @@ -0,0 +1,49 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { normalizeContext } from "@earendil-works/pi-ai"; +import { mapContextToChat } from "../src/context-map.ts"; + +const tool = (name) => ({ + name, + description: name, + parameters: { type: "object", properties: {} }, +}); + +// Regression for #7: Pi 0.86 moves prompt and tools into system messages. +test("preserves the prompt and tools from a normalized transcript", () => { + const read = tool("read"); + const context = normalizeContext({ + systemPrompt: "Inspect the repository.", + tools: [read], + messages: [{ role: "user", content: "Read README", timestamp: 1 }], + }); + assert.deepEqual(mapContextToChat(context), { + messages: [ + { role: "system", content: "Inspect the repository." }, + { role: "user", content: "Read README" }, + ], + tools: [read], + }); +}); + +test("applies later instruction, section, and tool changes", () => { + const bash = tool("bash"); + const context = { + messages: [ + { role: "system", content: "Inspect the repository.", sections: { policy: "Old policy", obsolete: "Remove me" }, toolsAdded: [tool("read")], timestamp: 0 }, + { role: "user", content: "Continue", timestamp: 1 }, + { role: "system", content: "Use bash.", sections: { policy: "Do not edit.", obsolete: null }, toolsRemoved: [{ name: "read" }], toolsAdded: [bash], timestamp: 2 }, + ], + }; + assert.deepEqual(mapContextToChat(context), { + messages: [ + { role: "system", content: "Inspect the repository.\n\nUse bash.\n\nDo not edit." }, + { role: "user", content: "Continue" }, + ], + tools: [bash], + }); +}); + +test("accepts an empty transcript", () => { + assert.deepEqual(mapContextToChat(normalizeContext({ messages: [] })), { messages: [], tools: [] }); +});