9290370b9250d90457c286d90ef0a85f9cc91430

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

Remove pi handoff extension

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-}