9290370b9250d90457c286d90ef0a85f9cc91430
- Author
- TheEdgeOfRage <git@theedgeofrage.com>
- Committer
- TheEdgeOfRage <git@theedgeofrage.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/dot_pi/private_agent/extensions/handoff/index.ts b/dot_pi/private_agent/extensions/handoff/index.ts
2deleted file mode 100644
3index 88c4eca5e6f7fb70a5476dd65c5cf93f51826ec1..0000000000000000000000000000000000000000
4--- a/dot_pi/private_agent/extensions/handoff/index.ts
5+++ /dev/null
6@@ -1,145 +0,0 @@
7-import type {
8- ExtensionAPI,
9- SessionEntry,
10-} from "@earendil-works/pi-coding-agent";
11-
12-const HANDOFF_AGENT_START_TIMEOUT_MS = 30_000;
13-const HANDOFF_CONTEXT_INSTRUCTIONS =
14- "If the handoff contains specific instructions to reingest context, use available session or tree inspection capabilities to recover the needed context from that branch, then resume.";
15-
16-function buildContinueFromHandoffPrompt(
17- sessionFile: string | undefined,
18- sourceLeafEntryId: string,
19-): string {
20- const sourceBranchInstructions =
21- sessionFile === undefined
22- ? `The source branch ends at session tree entry ${JSON.stringify(sourceLeafEntryId)}. ${HANDOFF_CONTEXT_INSTRUCTIONS}`
23- : `The source branch ends at session tree entry ${JSON.stringify(sourceLeafEntryId)} in ${JSON.stringify(sessionFile)}. ${HANDOFF_CONTEXT_INSTRUCTIONS}`;
24-
25- return `Open the handoff document identified in the branch summary. Resume the work by performing its next unfinished step.\n\n${sourceBranchInstructions}`;
26-}
27-
28-function findFirstUserMessageEntryId(
29- entries: readonly SessionEntry[],
30-): string | undefined {
31- for (const entry of entries) {
32- if (entry.type === "message" && entry.message.role === "user") {
33- return entry.id;
34- }
35- }
36- return undefined;
37-}
38-
39-function buildHandoffSkillCommand(focus: string): string {
40- return focus.length === 0 ? "/skill:handoff" : `/skill:handoff ${focus}`;
41-}
42-
43-function buildBranchSummaryInstructions(focus: string): string {
44- const focusInstruction =
45- focus.length === 0 ? "" : ` The next turn's focus is: ${focus}`;
46-
47diff --git a/dot_pi/private_agent/extensions/handoff/package.json b/dot_pi/private_agent/extensions/handoff/package.json
48deleted file mode 100644
49index 8e9126e6e0b286c43ee054f08faae323cfc58d42..0000000000000000000000000000000000000000
50--- a/dot_pi/private_agent/extensions/handoff/package.json
51+++ /dev/null
52@@ -1,24 +0,0 @@
53-{
54- "name": "pi-handoff-extension",
55- "private": true,
56- "version": "0.1.0",
57- "type": "module",
58- "scripts": {
59- "check": "npm run typecheck && npm test",
60- "test": "node --import tsx --test \"test/**/*.test.ts\"",
61- "typecheck": "tsc --noEmit"
62- },
63- "pi": {
64- "extensions": [
65- "./index.ts"
66- ]
67- },
68- "peerDependencies": {
69- "@earendil-works/pi-coding-agent": "*"
70- },
71- "devDependencies": {
72- "@types/node": "^24.5.2",
73- "tsx": "^4.20.5",
74- "typescript": "^5.9.2"
75- }
76-}
77diff --git a/dot_pi/private_agent/extensions/handoff/test/handoff.test.ts b/dot_pi/private_agent/extensions/handoff/test/handoff.test.ts
78deleted file mode 100644
79index c3d45bcc852a4608baf204cc622105341b6f11e5..0000000000000000000000000000000000000000
80--- a/dot_pi/private_agent/extensions/handoff/test/handoff.test.ts
81+++ /dev/null
82@@ -1,202 +0,0 @@
83-import assert from "node:assert/strict";
84-import { mkdtemp, rm } from "node:fs/promises";
85-import { tmpdir } from "node:os";
86-import { dirname, join } from "node:path";
87-import { fileURLToPath } from "node:url";
88-import test from "node:test";
89-
90-import { InMemoryCredentialStore, type UserMessage } from "@earendil-works/pi-ai";
91-import {
92- discoverAndLoadExtensions,
93- ExtensionRunner,
94- ModelRegistry,
95- ModelRuntime,
96- SessionManager,
97- type ExtensionCommandContextActions,
98-} from "@earendil-works/pi-coding-agent";
99-
100-const extensionPath = join(dirname(fileURLToPath(import.meta.url)), "..", "index.ts");
101-
102-function userMessage(text: string): UserMessage {
103- return {
104- role: "user",
105- content: [{ type: "text", text }],
106- timestamp: Date.now(),
107- };
108-}
109-
110-async function createHandoffHarness(cwd: string) {
111- const credentials = new InMemoryCredentialStore();
112- const modelRuntime = await ModelRuntime.create({
113- credentials,
114- modelsPath: null,
115- allowModelNetwork: false,
116- });
117- const model = modelRuntime.getModels()[0];
118- assert.ok(model, "the bundled model catalog should not be empty");
119- await credentials.modify(model.provider, async () => ({ type: "api_key", key: "test-key" }));
120-
121- const sessionManager = SessionManager.create(cwd, join(cwd, ".sessions"));
122- const loaded = await discoverAndLoadExtensions([extensionPath], cwd, join(cwd, ".agent"));
123- assert.deepEqual(loaded.errors, []);
124-
125- const modelRegistry = new ModelRegistry(modelRuntime);
126- const runner = new ExtensionRunner(
127- loaded.extensions,
128- loaded.runtime,
129- cwd,
130- sessionManager,
131- modelRegistry,
132- );
133- const sentUserMessages: Array<{
134- readonly content: string;
135- readonly options?: {
136- readonly deliverAs?: "steer" | "followUp";
137- readonly expandPromptTemplates?: boolean;
138- };
139- }> = [];
140- loaded.runtime.sendUserMessage = (content, options) => {
141- if (typeof content !== "string") {
142- throw new Error("Handoff test received unexpected image content");
143- }
144- sentUserMessages.push({ content, ...(options ? { options } : {}) });
145- if (content.startsWith("/skill:handoff")) {
146- queueMicrotask(() => void runner.emit({ type: "agent_start" }));
147- }
148- };
149-
150- runner.bindCore(loaded.runtime, {
151- getModel: () => model,
152- getScopedModels: () => [],
153- isIdle: () => true,
154- isProjectTrusted: () => true,
155- getSignal: () => undefined,
156- abort: () => undefined,
157- hasPendingMessages: () => false,
158- shutdown: () => undefined,
159- getContextUsage: () => undefined,
160- compact: () => undefined,
161- getSystemPrompt: () => "",
162- });
163-
164- const navigations: Array<{
165- readonly targetId: string;
166- readonly options?: {
167- readonly summarize?: boolean;
168- readonly customInstructions?: string;
169- readonly replaceInstructions?: boolean;
170- readonly label?: string;
171- };
172- }> = [];
173- let waitForIdleCalls = 0;
174- const commandActions: ExtensionCommandContextActions = {
175- waitForIdle: async () => {
176- waitForIdleCalls += 1;
177- },
178- newSession: async () => ({ cancelled: false }),
179- fork: async () => ({ cancelled: false }),
180- navigateTree: async (targetId, options) => {
181- navigations.push({ targetId, ...(options ? { options } : {}) });
182diff --git a/dot_pi/private_agent/extensions/handoff/tsconfig.json b/dot_pi/private_agent/extensions/handoff/tsconfig.json
183deleted file mode 100644
184index 4a1c8070805e97432f99eb11246752e790f28738..0000000000000000000000000000000000000000
185--- a/dot_pi/private_agent/extensions/handoff/tsconfig.json
186+++ /dev/null
187@@ -1,18 +0,0 @@
188-{
189- "compilerOptions": {
190- "target": "ESNext",
191- "module": "NodeNext",
192- "moduleResolution": "NodeNext",
193- "lib": ["ESNext"],
194- "allowImportingTsExtensions": true,
195- "noEmit": true,
196- "strict": true,
197- "exactOptionalPropertyTypes": true,
198- "noUncheckedIndexedAccess": true,
199- "noImplicitOverride": true,
200- "noFallthroughCasesInSwitch": true,
201- "skipLibCheck": true,
202- "types": ["node"]
203- },
204- "include": ["./index.ts", "./test/**/*.ts"]
205-}