@ai-sdk/harness-pi 1.0.66 → 1.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/index.js +12 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/pi-session.ts +17 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @ai-sdk/harness-pi
|
|
2
2
|
|
|
3
|
+
## 1.0.67
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9ee30bf: fix(harness): pass instructions appended to system / developer prompt instead of using the workaround of first user prompt
|
|
8
|
+
- Updated dependencies [9ee30bf]
|
|
9
|
+
- @ai-sdk/harness@1.0.66
|
|
10
|
+
|
|
3
11
|
## 1.0.66
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -108,7 +108,7 @@ import { resolveSandboxHomeDir } from "@ai-sdk/harness/utils";
|
|
|
108
108
|
import { getAiGatewayAuthFromEnv } from "@ai-sdk/harness/utils";
|
|
109
109
|
|
|
110
110
|
// src/version.ts
|
|
111
|
-
var VERSION = true ? "1.0.
|
|
111
|
+
var VERSION = true ? "1.0.67" : "0.0.0-test";
|
|
112
112
|
|
|
113
113
|
// src/pi-auth.ts
|
|
114
114
|
var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
|
|
@@ -787,17 +787,6 @@ function extractUserText(prompt) {
|
|
|
787
787
|
}
|
|
788
788
|
return parts.join("\n\n");
|
|
789
789
|
}
|
|
790
|
-
function frameInstructions(instructions, userText) {
|
|
791
|
-
return `<session-instructions>
|
|
792
|
-
The block below is operating guidance from the system, not a message from the user \u2014 follow it, but do not mention it or attribute it to the user.
|
|
793
|
-
|
|
794
|
-
${instructions}
|
|
795
|
-
</session-instructions>
|
|
796
|
-
|
|
797
|
-
<user-message>
|
|
798
|
-
${userText}
|
|
799
|
-
</user-message>`;
|
|
800
|
-
}
|
|
801
790
|
function serializeToolOutput(output) {
|
|
802
791
|
if (typeof output === "string") {
|
|
803
792
|
return output;
|
|
@@ -1711,6 +1700,7 @@ async function createPiSession(input) {
|
|
|
1711
1700
|
mcpServers: input.settings.mcpServers
|
|
1712
1701
|
});
|
|
1713
1702
|
const hasMcpServers = Object.keys(mcpServers).length > 0;
|
|
1703
|
+
let sessionInstructions;
|
|
1714
1704
|
const extensionFactories = [
|
|
1715
1705
|
...input.settings.extensionFactories ?? []
|
|
1716
1706
|
];
|
|
@@ -1736,7 +1726,7 @@ async function createPiSession(input) {
|
|
|
1736
1726
|
cwd: sessionWorkDir,
|
|
1737
1727
|
agentDir: hostAgentDir,
|
|
1738
1728
|
settingsManager,
|
|
1739
|
-
appendSystemPromptOverride: () => [],
|
|
1729
|
+
appendSystemPromptOverride: () => sessionInstructions ? [sessionInstructions] : [],
|
|
1740
1730
|
extensionFactories,
|
|
1741
1731
|
...hasExtensionFactories ? {
|
|
1742
1732
|
// DefaultResourceLoader invokes inline factories on every reload.
|
|
@@ -1792,13 +1782,18 @@ async function createPiSession(input) {
|
|
|
1792
1782
|
let sessionFileName;
|
|
1793
1783
|
let stopped = false;
|
|
1794
1784
|
let suspending = false;
|
|
1795
|
-
let instructionsApplied = input.isResume;
|
|
1796
1785
|
const pendingToolResults = /* @__PURE__ */ new Map();
|
|
1797
1786
|
const pendingToolApprovals = /* @__PURE__ */ new Map();
|
|
1798
1787
|
let currentEmit;
|
|
1799
1788
|
let translatorState;
|
|
1800
1789
|
let activeTurn;
|
|
1801
1790
|
const pendingCompactionParts = [];
|
|
1791
|
+
async function applySessionInstructions(instructions) {
|
|
1792
|
+
if (instructions === sessionInstructions) return;
|
|
1793
|
+
sessionInstructions = instructions;
|
|
1794
|
+
await reloadResourcesOnly();
|
|
1795
|
+
piSession?.setActiveToolsByName(piSession.getActiveToolNames());
|
|
1796
|
+
}
|
|
1802
1797
|
const remoteOps = createPiRemoteOps({
|
|
1803
1798
|
sandbox,
|
|
1804
1799
|
paths,
|
|
@@ -2106,13 +2101,9 @@ async function createPiSession(input) {
|
|
|
2106
2101
|
// only resume path is restoring the session file on a fresh/snapshotted
|
|
2107
2102
|
// sandbox, i.e. `rerun`.
|
|
2108
2103
|
doPromptTurn: async (promptOpts) => {
|
|
2109
|
-
|
|
2110
|
-
if (!instructionsApplied && promptOpts.instructions) {
|
|
2111
|
-
text = frameInstructions(promptOpts.instructions, text);
|
|
2112
|
-
}
|
|
2113
|
-
instructionsApplied = true;
|
|
2104
|
+
await applySessionInstructions(promptOpts.instructions);
|
|
2114
2105
|
return runTurn({
|
|
2115
|
-
text,
|
|
2106
|
+
text: extractUserText(promptOpts.prompt),
|
|
2116
2107
|
tools: promptOpts.tools ?? [],
|
|
2117
2108
|
emit: promptOpts.emit,
|
|
2118
2109
|
abortSignal: promptOpts.abortSignal
|
|
@@ -2126,6 +2117,7 @@ async function createPiSession(input) {
|
|
|
2126
2117
|
abortSignal: continueOpts.abortSignal
|
|
2127
2118
|
});
|
|
2128
2119
|
}
|
|
2120
|
+
await applySessionInstructions(continueOpts.instructions);
|
|
2129
2121
|
return runTurn({
|
|
2130
2122
|
text: "",
|
|
2131
2123
|
tools: continueOpts.tools ?? [],
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/pi-harness.ts","../src/pi-resume-state.ts","../src/pi-session.ts","../src/pi-auth.ts","../src/version.ts","../src/pi-events.ts","../src/pi-model-resolver.ts","../src/pi-paths.ts","../src/pi-remote-ops.ts","../src/pi-skills.ts","../src/pi-translate.ts","../src/pi-utils.ts","../src/pi-typebox-adapter.ts","../src/pi-workspace-vfs.ts","../src/pi-workspace-mirror.ts","../src/index.ts"],"sourcesContent":["import {\n commonTool,\n type HarnessV1,\n type HarnessV1BuiltinTool,\n} from '@ai-sdk/harness';\nimport { tool } from '@ai-sdk/provider-utils';\nimport type { ExtensionFactory } from '@earendil-works/pi-coding-agent';\nimport { z } from 'zod/v4';\nimport type { PiAuthOptions } from './pi-auth';\nimport { piResumeStateSchema } from './pi-resume-state';\nimport { createPiSession, type PiThinkingLevel } from './pi-session';\nimport { VERSION } from './version';\n\n/**\n * Value to use in User-Agent and `x-client-app` headers.\n */\nconst PI_CLIENT_APP = `ai-sdk/harness-pi/${VERSION}`;\n\n/**\n * Configuration knobs for `createPi`. Pi runs as an in-process Node library\n * (no bridge), so there's no `port` or `startupTimeoutMs` to set.\n */\nexport type PiHarnessSettings = {\n /** Where Pi sources API keys / gateway credentials from. */\n readonly auth?: PiAuthOptions;\n /**\n * Pi model id (or name). Leaving this unset falls back to the AI Gateway\n * default when `AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN` is set, and to\n * Pi's own resolution otherwise.\n */\n readonly model?: string;\n /**\n * Pi's extended-thinking budget level. Maps directly to the SDK's\n * `thinkingLevel` option on `createAgentSession`.\n */\n readonly thinkingLevel?: PiThinkingLevel;\n /**\n * Directory holding Pi's global agent config (auth.json, models.json,\n * settings.json). When omitted, a per-session temp dir is used. Pass the\n * user's agent dir (e.g. `~/.pi/agent/`) to reuse their CLI auth and\n * model settings.\n */\n readonly agentDir?: string;\n /**\n * MCP server definitions keyed by server name. Each definition uses the\n * underlying runtime's native MCP server configuration format.\n */\n readonly mcpServers?: Record<string, unknown>;\n /**\n * Trusted inline Pi extensions loaded for each harness session.\n *\n * Filesystem-discovered user and project extensions remain disabled.\n */\n readonly extensionFactories?: ReadonlyArray<ExtensionFactory>;\n};\n\nconst PI_BUILTIN_TOOLS = {\n read: commonTool('read', {\n nativeName: 'read',\n toolUseKind: 'readonly',\n description: 'Read file contents.',\n inputSchema: z.object({\n file_path: z.string(),\n }),\n }),\n write: commonTool('write', {\n nativeName: 'write',\n toolUseKind: 'edit',\n description: 'Overwrite or create a file.',\n inputSchema: z.object({\n file_path: z.string(),\n content: z.string(),\n }),\n }),\n edit: commonTool('edit', {\n nativeName: 'edit',\n toolUseKind: 'edit',\n description: 'Edit a file by exact string replacement.',\n inputSchema: z.object({\n file_path: z.string(),\n old_string: z.string(),\n new_string: z.string(),\n }),\n }),\n bash: commonTool('bash', {\n nativeName: 'bash',\n toolUseKind: 'bash',\n description: 'Execute a shell command in the sandbox.',\n inputSchema: z.object({\n command: z.string(),\n timeout: z.number().optional(),\n }),\n }),\n grep: commonTool('grep', {\n nativeName: 'grep',\n toolUseKind: 'readonly',\n description: 'Search file contents with regex.',\n inputSchema: z.object({\n pattern: z.string(),\n path: z.string().optional(),\n glob: z.string().optional(),\n ignoreCase: z.boolean().optional(),\n literal: z.boolean().optional(),\n context: z.number().optional(),\n limit: z.number().optional(),\n }),\n }),\n glob: commonTool('glob', {\n nativeName: 'find',\n toolUseKind: 'readonly',\n description: 'Find files matching a glob pattern.',\n inputSchema: z.object({\n pattern: z.string(),\n path: z.string().optional(),\n limit: z.number().optional(),\n }),\n }),\n ls: {\n ...tool({\n description: 'List directory entries.',\n inputSchema: z.object({\n path: z.string().optional(),\n limit: z.number().optional(),\n }),\n outputSchema: z.unknown(),\n }),\n nativeName: 'ls',\n toolUseKind: 'readonly',\n } as HarnessV1BuiltinTool,\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\nexport function createPi(\n settings: PiHarnessSettings = {},\n): HarnessV1<typeof PI_BUILTIN_TOOLS> {\n return {\n specificationVersion: 'harness-v1',\n harnessId: 'pi',\n builtinTools: PI_BUILTIN_TOOLS,\n supportsBuiltinToolApprovals: true,\n supportsBuiltinToolFiltering: true,\n lifecycleStateSchema: piResumeStateSchema,\n doStart: async startOpts => {\n const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;\n const resumeData = lifecycleState?.data as\n | { sessionFileName?: string }\n | undefined;\n\n return createPiSession({\n sessionId: startOpts.sessionId,\n sandboxSession: startOpts.sandboxSession,\n sessionWorkDir: startOpts.sessionWorkDir,\n skills: startOpts.skills ?? [],\n settings: {\n ...(settings.auth ? { auth: settings.auth } : {}),\n ...(settings.model ? { model: settings.model } : {}),\n ...(settings.thinkingLevel\n ? { thinkingLevel: settings.thinkingLevel }\n : {}),\n ...(settings.mcpServers ? { mcpServers: settings.mcpServers } : {}),\n ...(settings.extensionFactories\n ? { extensionFactories: settings.extensionFactories }\n : {}),\n },\n clientApp: PI_CLIENT_APP,\n isResume: lifecycleState != null,\n permissionMode: startOpts.permissionMode,\n builtinToolFiltering: startOpts.builtinToolFiltering,\n ...(resumeData?.sessionFileName\n ? { resumeSessionFileName: resumeData.sessionFileName }\n : {}),\n ...(startOpts.abortSignal\n ? { abortSignal: startOpts.abortSignal }\n : {}),\n ...(settings.agentDir ? { agentDir: settings.agentDir } : {}),\n });\n },\n };\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport { shellQuote } from '@ai-sdk/harness/utils';\nimport type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nconst PI_SESSION_FILE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*\\.jsonl?$/;\n\nexport function safePiSessionFileName(sessionFileName: string): string {\n if (!PI_SESSION_FILE_NAME_PATTERN.test(sessionFileName)) {\n throw new Error(`Invalid Pi session file name: ${sessionFileName}`);\n }\n return sessionFileName;\n}\n\nconst piSessionFileNameSchema = z\n .string()\n .refine(\n sessionFileName => PI_SESSION_FILE_NAME_PATTERN.test(sessionFileName),\n 'Pi sessionFileName must be a safe .jsonl or .json basename.',\n );\n\n/**\n * Schema for the adapter-specific portion of lifecycle state `data` produced\n * by Pi's resumable lifecycle methods. Carries the basename\n * (including extension) of the Pi session file. The actual session bytes live\n * in the sandbox under `${sessionWorkDir}/.pi-sessions/<sessionFileName>` so\n * they survive cross-process resume via the sandbox snapshot.\n */\nexport const piResumeStateSchema = z.looseObject({\n sessionFileName: piSessionFileNameSchema.optional(),\n});\n\nexport type PiResumeStateData = z.infer<typeof piResumeStateSchema>;\n\nconst PI_SESSIONS_DIR = '.pi-sessions';\n\nfunction resolveContainedHostPath(input: {\n readonly baseDir: string;\n readonly sessionFileName: string;\n}): string {\n const baseDir = path.resolve(input.baseDir);\n const filePath = path.resolve(\n baseDir,\n safePiSessionFileName(input.sessionFileName),\n );\n const relativePath = path.relative(baseDir, filePath);\n if (\n relativePath === '' ||\n relativePath.startsWith('..') ||\n path.isAbsolute(relativePath)\n ) {\n throw new Error(`Invalid Pi session file name: ${input.sessionFileName}`);\n }\n return filePath;\n}\n\nfunction resolveContainedSandboxPath(input: {\n readonly sessionWorkDir: string;\n readonly sessionFileName: string;\n}): string {\n const sessionDir = path.posix.resolve(input.sessionWorkDir, PI_SESSIONS_DIR);\n const filePath = path.posix.resolve(\n sessionDir,\n safePiSessionFileName(input.sessionFileName),\n );\n const relativePath = path.posix.relative(sessionDir, filePath);\n if (\n relativePath === '' ||\n relativePath.startsWith('..') ||\n path.posix.isAbsolute(relativePath)\n ) {\n throw new Error(`Invalid Pi session file name: ${input.sessionFileName}`);\n }\n return filePath;\n}\n\n/**\n * Copy the Pi session file from the host's local mirror to a stable location\n * inside the sandbox workspace. Called during resumable lifecycle methods so\n * the session survives a sandbox snapshot or a process handoff.\n */\nexport async function persistSessionFileToSandbox(args: {\n readonly sandbox: Experimental_SandboxSession;\n readonly sessionWorkDir: string;\n readonly hostSessionDir: string;\n readonly sessionFileName: string;\n readonly abortSignal?: AbortSignal;\n}): Promise<void> {\n const hostPath = resolveContainedHostPath({\n baseDir: args.hostSessionDir,\n sessionFileName: args.sessionFileName,\n });\n const content = await readFile(hostPath);\n const remotePath = resolveContainedSandboxPath({\n sessionWorkDir: args.sessionWorkDir,\n sessionFileName: args.sessionFileName,\n });\n // Ensure the parent dir exists in the sandbox before writing.\n await args.sandbox.run({\n command: `mkdir -p ${shellQuote(path.posix.dirname(remotePath))}`,\n ...(args.abortSignal ? { abortSignal: args.abortSignal } : {}),\n });\n await args.sandbox.writeBinaryFile({\n path: remotePath,\n content,\n ...(args.abortSignal ? { abortSignal: args.abortSignal } : {}),\n });\n}\n\n/**\n * Pull a previously persisted Pi session file from the sandbox into a fresh\n * local mirror dir. Called during `doStart` on the resume path before Pi is\n * initialised. Returns the absolute path of the local session file or\n * `undefined` if the sandbox copy is missing.\n */\nexport async function pullSessionFileFromSandbox(args: {\n readonly sandbox: Experimental_SandboxSession;\n readonly sessionWorkDir: string;\n readonly hostSessionDir: string;\n readonly sessionFileName: string;\n readonly abortSignal?: AbortSignal;\n}): Promise<string | undefined> {\n const remotePath = resolveContainedSandboxPath({\n sessionWorkDir: args.sessionWorkDir,\n sessionFileName: args.sessionFileName,\n });\n const bytes = await args.sandbox.readBinaryFile({\n path: remotePath,\n ...(args.abortSignal ? { abortSignal: args.abortSignal } : {}),\n });\n if (!bytes) return undefined;\n await mkdir(args.hostSessionDir, { recursive: true });\n const hostPath = resolveContainedHostPath({\n baseDir: args.hostSessionDir,\n sessionFileName: args.sessionFileName,\n });\n await writeFile(hostPath, bytes);\n return hostPath;\n}\n","import {\n createAgentSession,\n DefaultResourceLoader,\n defineTool,\n ModelRegistry,\n ModelRuntime,\n SessionManager,\n SettingsManager,\n type AgentSession,\n type AgentToolResult,\n type ExtensionFactory,\n type Skill,\n type ToolDefinition,\n} from '@earendil-works/pi-coding-agent';\nimport { mkdir, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport path from 'node:path';\nimport { Type } from 'typebox';\nimport {\n type HarnessV1BuiltinToolFiltering,\n type HarnessV1ContinueTurnOptions,\n type HarnessV1ContinueTurnState,\n type HarnessV1PromptControl,\n type HarnessV1PromptTurnOptions,\n type HarnessV1NetworkSandboxSession,\n type HarnessV1PermissionMode,\n type HarnessV1ResumeSessionState,\n type HarnessV1Session,\n type HarnessV1Skill,\n type HarnessV1StreamPart,\n type HarnessV1ToolSpec,\n} from '@ai-sdk/harness';\nimport { resolveSandboxHomeDir } from '@ai-sdk/harness/utils';\nimport {\n registerPiProviders,\n resolvePiEnv,\n type PiAuthOptions,\n} from './pi-auth';\nimport { getPiTerminalError, parseNativeEvent } from './pi-events';\nimport { createPiModelResolver } from './pi-model-resolver';\nimport { createPiPathMapper } from './pi-paths';\nimport { createPiRemoteOps, type PiRemoteOps } from './pi-remote-ops';\nimport { writePiSkills } from './pi-skills';\nimport {\n persistSessionFileToSandbox,\n pullSessionFileFromSandbox,\n safePiSessionFileName,\n} from './pi-resume-state';\nimport {\n createPiTranslatorState,\n finishPiApprovalStep,\n translatePiEvent,\n type PiTranslatorState,\n} from './pi-translate';\nimport { toolSpecToTypeBoxParameters } from './pi-typebox-adapter';\nimport {\n extractUserText,\n frameInstructions,\n safePiMetadataSegment,\n serializeToolOutput,\n} from './pi-utils';\nimport { PiWorkspaceVfs } from './pi-workspace-vfs';\nimport { syncHostWorkspaceFromSandbox } from './pi-workspace-mirror';\n\nconst HARNESS_ID = 'pi';\n\n/*\n * pi-mcp-adapter publishes TypeScript source as its package entry point. A\n * non-literal specifier keeps the repository type-check focused on this\n * package's compatibility boundary instead of compiling dependency internals.\n */\nconst PI_MCP_ADAPTER_PACKAGE: string = 'pi-mcp-adapter';\n\ntype PiMcpAdapterModule = {\n createMcpAdapter(options: {\n config: {\n mcpServers: Record<string, unknown>;\n settings: {\n directTools: boolean;\n toolPrefix: string;\n disableProxyTool: boolean;\n };\n };\n }): ExtensionFactory;\n};\n\n/*\n * Pi runs in this Node process, not behind an attachable in-sandbox bridge.\n * During a tool approval pause the Pi turn is still alive and blocked on the\n * custom tool promise, so detach must park that live session for the next\n * same-process resume instead of stopping it and resolving the promise as an\n * error. Cross-process resume still falls back to the persisted session file.\n */\nconst parkedPiSessions = new Map<string, HarnessV1Session>();\n\n/**\n * Whether a discovered resource path belongs to a specific directory.\n */\nfunction isWithinDirectory(parent: string, child: string): boolean {\n const rel = path.relative(parent, child);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n}\n\n/**\n * Whether a discovered resource path belongs to the session workspace — either\n * the sandbox-side working directory the model sees (`sessionWorkDir`) or its\n * host-side mirror (`hostWorkDir`).\n */\nfunction isWithinWorkspace(\n candidate: string,\n sessionWorkDir: string,\n hostWorkDir: string,\n): boolean {\n return (\n isWithinDirectory(sessionWorkDir, candidate) ||\n isWithinDirectory(hostWorkDir, candidate)\n );\n}\n\nfunction createHarnessPiSkills({\n skills,\n sandboxSkillRootDir,\n}: {\n skills: ReadonlyArray<HarnessV1Skill>;\n sandboxSkillRootDir: string;\n}): Skill[] {\n return skills.map(skill => {\n const name = safePiMetadataSegment(skill.name, 'skill');\n const baseDir = path.posix.join(sandboxSkillRootDir, name);\n const filePath = path.posix.join(baseDir, 'SKILL.md');\n return {\n name: skill.name,\n description: skill.description,\n filePath,\n baseDir,\n sourceInfo: {\n path: filePath,\n source: 'harness',\n scope: 'temporary',\n origin: 'top-level',\n baseDir,\n },\n disableModelInvocation: false,\n };\n });\n}\n\nconst PI_NATIVE_BUILTIN_NAMES = [\n 'read',\n 'write',\n 'edit',\n 'bash',\n 'grep',\n 'find',\n 'ls',\n] as const;\n\nconst NATIVE_TO_COMMON: Readonly<Record<string, string>> = {\n find: 'glob',\n};\n\nconst PUBLIC_TO_NATIVE: Readonly<\n Record<string, (typeof PI_NATIVE_BUILTIN_NAMES)[number]>\n> = {\n read: 'read',\n write: 'write',\n edit: 'edit',\n bash: 'bash',\n grep: 'grep',\n glob: 'find',\n ls: 'ls',\n};\n\nconst PI_NATIVE_TOOL_KINDS: Readonly<\n Record<(typeof PI_NATIVE_BUILTIN_NAMES)[number], 'readonly' | 'edit' | 'bash'>\n> = {\n read: 'readonly',\n write: 'edit',\n edit: 'edit',\n bash: 'bash',\n grep: 'readonly',\n find: 'readonly',\n ls: 'readonly',\n};\n\nfunction resolveActivePiBuiltinNames(\n toolFiltering: HarnessV1BuiltinToolFiltering | undefined,\n): ReadonlyArray<(typeof PI_NATIVE_BUILTIN_NAMES)[number]> {\n if (toolFiltering == null) return PI_NATIVE_BUILTIN_NAMES;\n if (toolFiltering.mode === 'allow') {\n return toolFiltering.toolNames\n .map(name => PUBLIC_TO_NATIVE[name])\n .filter(\n (name): name is (typeof PI_NATIVE_BUILTIN_NAMES)[number] =>\n name != null,\n );\n }\n return PI_NATIVE_BUILTIN_NAMES.filter(\n native =>\n !toolFiltering.toolNames.includes(NATIVE_TO_COMMON[native] ?? native),\n );\n}\n\nexport type PiThinkingLevel =\n | 'off'\n | 'minimal'\n | 'low'\n | 'medium'\n | 'high'\n | 'xhigh';\n\nexport interface PiSessionSettings {\n readonly auth?: PiAuthOptions;\n readonly model?: string;\n readonly thinkingLevel?: PiThinkingLevel;\n readonly mcpServers?: Record<string, unknown>;\n readonly extensionFactories?: ReadonlyArray<ExtensionFactory>;\n}\n\nexport interface CreatePiSessionInput {\n readonly sessionId: string;\n readonly sandboxSession: HarnessV1NetworkSandboxSession;\n readonly sessionWorkDir: string;\n readonly skills: ReadonlyArray<HarnessV1Skill>;\n readonly settings: PiSessionSettings;\n readonly clientApp: string;\n readonly isResume: boolean;\n readonly permissionMode?: HarnessV1PermissionMode;\n readonly builtinToolFiltering?: HarnessV1BuiltinToolFiltering;\n readonly resumeSessionFileName?: string;\n readonly abortSignal?: AbortSignal;\n /**\n * Directory holding Pi's global agent config (auth.json, models.json,\n * settings.json). When omitted, a per-session temp dir is used (the\n * harness cannot reuse existing CLI logins). Pass the user's agent dir\n * (e.g. `~/.pi/agent/`) to reuse their CLI auth and model settings.\n */\n readonly agentDir?: string;\n}\n\ninterface PendingToolResult {\n resolve: (value: unknown) => void;\n}\n\ninterface PendingToolApproval {\n resolve: (value: { approved: boolean; reason?: string }) => void;\n}\n\ninterface ActivePiTurn {\n readonly token: object;\n readonly done: Promise<void>;\n}\n\nexport async function createPiSession(\n input: CreatePiSessionInput,\n): Promise<HarnessV1Session> {\n if (input.isResume) {\n const parkedSession = parkedPiSessions.get(input.sessionId);\n if (parkedSession) {\n parkedPiSessions.delete(input.sessionId);\n return {\n ...parkedSession,\n isResume: true,\n };\n }\n }\n\n // Host-side mirror layout under tmpdir. Replace path-separator characters\n // that would otherwise turn a session id like `2026-05-29T17:54:27` into a\n // sub-directory tree on disk.\n const safeSessionId = input.sessionId.replace(/[\\\\/: ]/g, '-');\n const hostRoot = path.join(tmpdir(), 'ai-sdk-harness', 'pi', safeSessionId);\n const hostWorkDir = path.join(hostRoot, 'workspace');\n const hostAgentDir = path.join(hostRoot, 'agent');\n const hostSessionDir = path.join(hostRoot, 'sessions');\n\n // Pi runs in this host process but must behave as though it lives in the\n // sandbox workspace: its working directory is the real `sessionWorkDir`\n // (where `setup()` clones and where the sandbox-backed tools operate), so the\n // paths Pi advertises to the model — most notably the \"Current working\n // directory\" line in its system prompt — resolve inside the sandbox. The\n // workspace VFS maps that sandbox path to the host-side mirror so Pi's own\n // `fs`-based resource loading (`.pi/`, `AGENTS.md`) still works on the host.\n // `sessionWorkDir` is a sandbox path (e.g. `/vercel/sandbox/...`) that does\n // not exist on the host, so it is a safe, collision-free VFS mount point.\n const sessionWorkDir = input.sessionWorkDir;\n\n await mkdir(hostWorkDir, { recursive: true });\n await mkdir(hostAgentDir, { recursive: true });\n await mkdir(hostSessionDir, { recursive: true });\n\n const sandbox = input.sandboxSession.restricted();\n const permissionMode = input.permissionMode ?? 'allow-all';\n let sandboxSkillRootDir: string | undefined;\n let harnessSkills: Skill[] = [];\n\n // Materialise harness-provided skills into sandbox HOME, not the workspace.\n if (input.skills.length > 0) {\n const sandboxHomeDir = await resolveSandboxHomeDir({\n sandbox,\n ...(input.abortSignal ? { abortSignal: input.abortSignal } : {}),\n });\n sandboxSkillRootDir = path.posix.join(sandboxHomeDir, '.agents', 'skills');\n harnessSkills = createHarnessPiSkills({\n skills: input.skills,\n sandboxSkillRootDir,\n });\n await writePiSkills({\n sandbox,\n sandboxHomeDir,\n skills: input.skills,\n ...(input.abortSignal ? { abortSignal: input.abortSignal } : {}),\n });\n }\n\n // On resume: pull the Pi session file out of the sandbox into the fresh\n // host mirror so SessionManager.open can read it.\n let resumeSessionFilePath: string | undefined;\n if (input.isResume && input.resumeSessionFileName) {\n const resumeSessionFileName = safePiSessionFileName(\n input.resumeSessionFileName,\n );\n resumeSessionFilePath = await pullSessionFileFromSandbox({\n sandbox,\n sessionWorkDir: input.sessionWorkDir,\n hostSessionDir,\n sessionFileName: resumeSessionFileName,\n ...(input.abortSignal ? { abortSignal: input.abortSignal } : {}),\n });\n }\n\n // Snapshot sandbox state into the host mirror BEFORE the VFS goes live so\n // Pi sees the workspace as soon as it boots.\n await syncHostWorkspaceFromSandbox({\n sandbox,\n sandboxWorkDir: input.sessionWorkDir,\n hostWorkDir,\n });\n\n // Mount only the workspace: the model's view of the workspace lives at\n // `sessionWorkDir` and is backed by `hostWorkDir`. The agent and session\n // directories stay on the real host filesystem (below) — they are host-only\n // Pi state (auth, model registry, session journal) that must never surface\n // in the sandbox or the workspace mirror.\n const workspaceVfs = new PiWorkspaceVfs();\n workspaceVfs.mount(hostWorkDir, sessionWorkDir);\n\n const paths = createPiPathMapper({\n hostWorkDir,\n sandboxWorkDir: sessionWorkDir,\n readableRoots: sandboxSkillRootDir\n ? [{ sandboxDir: sandboxSkillRootDir }]\n : [],\n });\n\n // Pi auth + model registry are global to this Pi session. These live on the\n // real host filesystem, never in the sandbox/workspace.\n // When `agentDir` is provided, use it instead so the harness can reuse\n // existing CLI logins and model/settings config.\n const agentDir = input.agentDir ?? hostAgentDir;\n const modelRuntime = await ModelRuntime.create({\n authPath: path.join(agentDir, 'auth.json'),\n modelsPath: path.join(agentDir, 'models.json'),\n allowModelNetwork: false,\n });\n const modelRegistry = new ModelRegistry(modelRuntime);\n const settingsManager =\n input.agentDir != null\n ? SettingsManager.create(hostWorkDir, agentDir)\n : SettingsManager.inMemory();\n\n // Run-scoped env (for the model resolver's gateway fallback heuristic).\n const resolverEnv = resolvePiEnv({\n options: input.settings.auth,\n env: process.env,\n });\n await registerPiProviders({\n options: input.settings.auth,\n resolvedEnv: resolverEnv,\n registries: {\n modelRegistry,\n modelRuntime,\n },\n clientApp: input.clientApp,\n });\n const resolveModel = createPiModelResolver({\n modelRegistry,\n env: resolverEnv,\n });\n // Resolve once: deterministic given the configured model. This is the Pi\n // `Model` object handed to `createAgentSession`.\n const resolvedModel = resolveModel(input.settings.model);\n const mcpServers = resolvePiMcpServers({\n mcpServers: input.settings.mcpServers,\n });\n const hasMcpServers = Object.keys(mcpServers).length > 0;\n\n /*\n * Configured MCP servers are served by an inline Pi extension, so they share\n * the extension runtime with the caller-supplied factories: both are loaded\n * by the resource loader below and both are subject to the reload handling\n * that keeps the active runtime alive across resource-only reloads.\n */\n const extensionFactories: ExtensionFactory[] = [\n ...(input.settings.extensionFactories ?? []),\n ];\n if (hasMcpServers) {\n const { createMcpAdapter } = (await import(\n PI_MCP_ADAPTER_PACKAGE\n )) as PiMcpAdapterModule;\n extensionFactories.push(\n createMcpAdapter({\n config: {\n mcpServers,\n settings: {\n directTools: true,\n toolPrefix: 'mcp',\n disableProxyTool: true,\n },\n },\n }),\n );\n }\n const hasExtensionFactories = extensionFactories.length > 0;\n let preserveExtensionsResult = false;\n let currentExtensionsResult:\n | ReturnType<DefaultResourceLoader['getExtensions']>\n | undefined;\n const resourceLoader = new DefaultResourceLoader({\n cwd: sessionWorkDir,\n agentDir: hostAgentDir,\n settingsManager,\n appendSystemPromptOverride: () => [],\n extensionFactories,\n ...(hasExtensionFactories\n ? {\n // DefaultResourceLoader invokes inline factories on every reload.\n // Resource-only reloads retain the active extension runtime, while a\n // genuine Pi session rebuild is allowed to replace that runtime.\n extensionsOverride: extensions => {\n if (preserveExtensionsResult && currentExtensionsResult != null) {\n return currentExtensionsResult;\n }\n currentExtensionsResult = extensions;\n return extensions;\n },\n }\n : {}),\n // Pi runs in the host process, so its default resource discovery reaches\n // the host developer's personal config (`~/.pi/agent/*`, `~/.agents/*`).\n // The harness exposes only explicitly supplied inline extension factories;\n // disable filesystem extension discovery entirely to avoid loading and\n // executing a host developer's personal or project Pi extensions inside\n // the server process. Themes and prompt templates stay disabled. Skills\n // are kept but filtered to workspace project skills plus harness-provided\n // skills whose files live in sandbox HOME.\n noExtensions: true,\n noThemes: true,\n noPromptTemplates: true,\n skillsOverride: base => ({\n ...base,\n skills: [\n ...base.skills.filter(skill =>\n isWithinWorkspace(skill.filePath, sessionWorkDir, hostWorkDir),\n ),\n ...harnessSkills,\n ],\n }),\n });\n await resourceLoader.reload();\n\n async function reloadResourcesOnly(): Promise<void> {\n if (!hasExtensionFactories) {\n await resourceLoader.reload();\n return;\n }\n\n const factories = extensionFactories.splice(0);\n preserveExtensionsResult = true;\n try {\n await resourceLoader.reload();\n } finally {\n preserveExtensionsResult = false;\n extensionFactories.push(...factories);\n }\n }\n\n // Per-session mutable state we hold across prompts.\n let piSession: AgentSession | undefined;\n let unsubscribe: (() => void) | undefined;\n let lastToolsSignature: string | undefined;\n let sessionFileName: string | undefined;\n let stopped = false;\n /*\n * Set by `doSuspendTurn` before it aborts the in-flight host turn at a slice\n * boundary. The turn's catch settles silently when this is set, so the stream\n * closes cleanly (no spurious `error` chunk) — the next slice rerun-continues\n * from the persisted journal.\n */\n let suspending = false;\n /*\n * Instructions are prepended to the first user message of a fresh session\n * only. A resumed session already carried them in its original first\n * message (preserved in the persisted session file), so it starts \"applied\".\n */\n let instructionsApplied = input.isResume;\n const pendingToolResults = new Map<string, PendingToolResult>();\n const pendingToolApprovals = new Map<string, PendingToolApproval>();\n\n // Emit channel set at the start of every doPromptTurn and cleared on end.\n let currentEmit: ((part: HarnessV1StreamPart) => void) | undefined;\n let translatorState: PiTranslatorState | undefined;\n let activeTurn: ActivePiTurn | undefined;\n /*\n * Compaction parts produced while no turn is active. Pi's `compact()` aborts\n * the current turn before it summarizes, so a manually triggered compaction\n * (and any compaction that lands between turns) emits its `compaction_end`\n * after `currentEmit` has been cleared. Buffer those parts and flush them on\n * the next turn's stream so the observation is not lost. Auto-compaction that\n * runs mid-turn still emits inline via `currentEmit`.\n */\n const pendingCompactionParts: HarnessV1StreamPart[] = [];\n\n const remoteOps = createPiRemoteOps({\n sandbox,\n paths,\n onFileChange: (event, relPath) => {\n currentEmit?.({ type: 'file-change', event, path: relPath });\n },\n });\n\n function settlePendingToolResults(reason: string): void {\n for (const pending of pendingToolResults.values()) {\n pending.resolve({ error: reason });\n }\n pendingToolResults.clear();\n }\n\n function settlePendingToolApprovals(reason: string): void {\n for (const pending of pendingToolApprovals.values()) {\n pending.resolve({ approved: false, reason });\n }\n pendingToolApprovals.clear();\n }\n\n async function persistSessionFile(): Promise<void> {\n if (!sessionFileName) return;\n await persistSessionFileToSandbox({\n sandbox,\n sessionWorkDir: input.sessionWorkDir,\n hostSessionDir,\n sessionFileName,\n });\n }\n\n function createPromptControl(input: {\n done: Promise<void>;\n abortSignal?: AbortSignal;\n }): HarnessV1PromptControl {\n const abortHandler = () => {\n piSession?.abort().catch(() => {});\n };\n if (input.abortSignal) {\n input.abortSignal.addEventListener('abort', abortHandler, {\n once: true,\n });\n void input.done.then(\n () => {\n input.abortSignal?.removeEventListener('abort', abortHandler);\n },\n () => {\n input.abortSignal?.removeEventListener('abort', abortHandler);\n },\n );\n }\n\n return {\n async submitToolResult(args) {\n const pending = pendingToolResults.get(args.toolCallId);\n if (!pending) return;\n pendingToolResults.delete(args.toolCallId);\n /*\n * Preserve the original output so the result projection can surface it\n * unchanged. The tool handler stringifies the output for the runtime\n * (so the model reads it), and Pi echoes that text back — without this\n * the consumer-facing result would be the serialized string instead of\n * the original object.\n */\n translatorState?.hostToolResults.set(args.toolCallId, args.output);\n pending.resolve(args.output);\n },\n async submitToolApproval(args) {\n const pending = pendingToolApprovals.get(args.approvalId);\n if (!pending) return;\n pendingToolApprovals.delete(args.approvalId);\n pending.resolve({\n approved: args.approved,\n reason: args.reason,\n });\n },\n async submitUserMessage(text) {\n await piSession?.steer(text);\n },\n done: input.done,\n };\n }\n\n async function requestBuiltinToolApproval(args: {\n toolCallId: string;\n nativeName: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n }): Promise<{ approved: boolean; reason?: string }> {\n if (\n !piBuiltinToolRequiresApproval({\n permissionMode,\n kind: PI_NATIVE_TOOL_KINDS[args.nativeName],\n })\n ) {\n return { approved: true };\n }\n currentEmit?.({\n type: 'tool-approval-request',\n approvalId: args.toolCallId,\n toolCallId: args.toolCallId,\n });\n if (translatorState) {\n for (const part of finishPiApprovalStep(\n translatorState,\n args.toolCallId,\n )) {\n currentEmit?.(part);\n }\n }\n return new Promise(resolve => {\n pendingToolApprovals.set(args.toolCallId, { resolve });\n });\n }\n\n function buildToolDefinitions(userTools: ReadonlyArray<HarnessV1ToolSpec>): {\n customTools: ToolDefinition[];\n builtinNames: string[];\n } {\n const builtinNames = resolveActivePiBuiltinNames(\n input.builtinToolFiltering,\n );\n const customTools: ToolDefinition[] = [\n ...builtinNames.map(native =>\n buildBuiltinToolDefinition({\n native,\n remoteOps,\n requestApproval: requestBuiltinToolApproval,\n }),\n ),\n ...userTools.map(spec =>\n buildUserToolDefinition(spec, pendingToolResults),\n ),\n ];\n return {\n customTools,\n builtinNames: [...builtinNames],\n };\n }\n\n async function disposePiSession(): Promise<void> {\n unsubscribe?.();\n unsubscribe = undefined;\n\n const session = piSession;\n piSession = undefined;\n if (!session) return;\n\n if (hasMcpServers) {\n await session.reload().catch(() => {});\n }\n session.dispose();\n }\n\n async function rebuildPiSession(\n userTools: ReadonlyArray<HarnessV1ToolSpec>,\n isFirstBuild: boolean,\n ): Promise<boolean> {\n let resourcesReloaded = false;\n if (piSession) {\n await disposePiSession();\n // Original adapter waits 25 ms here to let Pi's teardown microtasks\n // settle before the next createAgentSession. Port verbatim.\n // TODO(pi-0.77): verify the race still exists; original SDK had a\n // teardown microtask the host needed to wait on.\n await new Promise(resolve => setTimeout(resolve, 25));\n if (hasExtensionFactories) {\n // dispose() invalidates Pi's current extension runtime, so a replacement\n // AgentSession needs factories to create a fresh runtime before build.\n await resourceLoader.reload();\n resourcesReloaded = true;\n }\n }\n\n const { customTools, builtinNames } = buildToolDefinitions(userTools);\n const toolNames = customTools.map(t => t.name);\n\n // SessionManager: open the resumed file on the first build of a resumed\n // session; create fresh otherwise.\n const sessionManager =\n isFirstBuild && resumeSessionFilePath\n ? SessionManager.open(\n resumeSessionFilePath,\n hostSessionDir,\n sessionWorkDir,\n )\n : SessionManager.create(sessionWorkDir, hostSessionDir);\n\n const { session } = await createAgentSession({\n cwd: sessionWorkDir,\n agentDir: hostAgentDir,\n modelRuntime,\n sessionManager,\n settingsManager,\n resourceLoader,\n customTools,\n ...(hasMcpServers\n ? { noTools: 'builtin' as const }\n : { tools: toolNames }),\n ...(input.settings.thinkingLevel\n ? { thinkingLevel: input.settings.thinkingLevel }\n : {}),\n ...(resolvedModel ? { model: resolvedModel } : {}),\n });\n piSession = session;\n if (hasMcpServers) {\n await piSession.bindExtensions({ mode: 'print' });\n }\n\n // Pick up the actual session file path so doStop can persist it. Pi\n // 0.77 emits `.jsonl` files; older builds used `.json`. Persist the\n // basename verbatim — including the extension — so the resume path can\n // round-trip it without guessing the extension.\n const candidatePath = sessionManager.getSessionFile();\n if (candidatePath) {\n sessionFileName = safePiSessionFileName(path.basename(candidatePath));\n }\n\n translatorState = createPiTranslatorState({\n builtinToolNames: builtinNames,\n hostToolNames: userTools.map(tool => tool.name),\n nativeToCommon: NATIVE_TO_COMMON,\n });\n\n unsubscribe = piSession.subscribe(rawEvent => {\n if (!translatorState) return;\n const event = parseNativeEvent(rawEvent);\n if (!event) return;\n for (const part of translatePiEvent(event, translatorState)) {\n if (currentEmit) {\n currentEmit(part);\n } else if (part.type === 'compaction') {\n // No active turn: defer compaction observations to the next turn.\n pendingCompactionParts.push(part);\n }\n // Other event types outside a turn have no consumer and are dropped.\n }\n });\n return resourcesReloaded;\n }\n\n /*\n * Drive one turn against the Pi session and return the control surface.\n * Shared by `doPromptTurn` (a fresh user prompt) and `doContinueTurn` (an empty\n * prompt that asks Pi to continue its own thread after a rerun resume).\n */\n async function runTurn(turnOpts: {\n text: string;\n tools: ReadonlyArray<HarnessV1ToolSpec>;\n emit: (part: HarnessV1StreamPart) => void;\n abortSignal?: AbortSignal;\n }): Promise<HarnessV1PromptControl> {\n if (stopped) {\n throw new Error('Pi session has been stopped.');\n }\n\n const userTools = turnOpts.tools;\n const signature = JSON.stringify(userTools.map(t => t.name).sort());\n const needsRebuild = piSession == null || signature !== lastToolsSignature;\n let resourcesReloaded = false;\n if (needsRebuild) {\n resourcesReloaded = await rebuildPiSession(userTools, piSession == null);\n lastToolsSignature = signature;\n }\n\n if (!resourcesReloaded) {\n await reloadResourcesOnly();\n }\n await syncHostWorkspaceFromSandbox({\n sandbox,\n sandboxWorkDir: input.sessionWorkDir,\n hostWorkDir,\n });\n\n currentEmit = turnOpts.emit;\n // Fresh translator state for the new turn — keep the tool sets the\n // session was built with.\n translatorState = createPiTranslatorState({\n builtinToolNames: [...PI_NATIVE_BUILTIN_NAMES],\n hostToolNames: userTools.map(tool => tool.name),\n nativeToCommon: NATIVE_TO_COMMON,\n });\n\n turnOpts.emit({ type: 'stream-start' });\n\n const turnPromise = (async () => {\n let terminalError: string | undefined;\n const session = piSession!;\n\n // We subscribed in rebuild, but the translator may need to detect\n // terminal errors too — wrap a second listener that records them.\n const unsubErr = session.subscribe(raw => {\n const ev = parseNativeEvent(raw);\n if (!ev) return;\n const err = getPiTerminalError(ev);\n if (err && !terminalError) {\n terminalError = err;\n }\n });\n\n try {\n await session.prompt(turnOpts.text);\n\n if (terminalError) {\n /*\n * A `doSuspendTurn` aborts the in-flight turn on purpose. Pi surfaces\n * that abort as a *resolved* prompt with a recorded terminal error\n * (\"This operation was aborted\") rather than a thrown exception, so the\n * `catch` guard below never sees it. Swallow it here too — but only if\n * it's actually the abort: the stream then closes cleanly (no spurious\n * `error` chunk) and the next slice rerun-continues from the journal.\n * Any other terminal error mid-suspend is unanticipated and must\n * surface.\n */\n if (suspending && isAbortError(terminalError)) return;\n currentEmit?.({ type: 'error', error: new Error(terminalError) });\n return;\n }\n\n const stats = session.getSessionStats();\n const finishReason = {\n unified: 'stop' as const,\n raw: undefined,\n };\n const usage = {\n inputTokens: {\n total: stats.tokens.input,\n noCache: undefined,\n cacheRead: stats.tokens.cacheRead,\n cacheWrite: stats.tokens.cacheWrite,\n },\n outputTokens: {\n total: stats.tokens.output,\n text: undefined,\n reasoning: undefined,\n },\n };\n currentEmit?.({\n type: 'finish',\n finishReason,\n totalUsage: usage,\n });\n } catch (err) {\n // A `doSuspendTurn` aborts the in-flight turn on purpose — settle silently\n // so the stream closes cleanly without a spurious `error` chunk; the\n // next slice rerun-continues from the persisted journal.\n // Same rule as the resolved-with-terminalError path: only swallow the\n // abort our own suspend caused; surface anything unanticipated.\n if (suspending && isAbortError(err)) return;\n currentEmit?.({ type: 'error', error: err });\n } finally {\n unsubErr();\n }\n })();\n\n const activeTurnToken = {};\n const done = turnPromise.finally(() => {\n if (activeTurn?.token === activeTurnToken) {\n activeTurn = undefined;\n }\n currentEmit = undefined;\n });\n activeTurn = {\n token: activeTurnToken,\n done,\n };\n\n return createPromptControl({\n done,\n abortSignal: turnOpts.abortSignal,\n });\n }\n\n const doStop = async (): Promise<HarnessV1ResumeSessionState> => {\n if (stopped) {\n throw new Error('Pi session has been stopped.');\n }\n stopped = true;\n parkedPiSessions.delete(input.sessionId);\n settlePendingToolResults('Pi session stopped');\n settlePendingToolApprovals('Pi session stopped');\n\n // Persist the Pi session file into the sandbox so a future process\n // can pick it up after `provider.resumeSession({ sessionId })` reattaches.\n if (sessionFileName) {\n try {\n await persistSessionFile();\n } catch {\n // Best-effort: a missing session file means resume returns to a\n // fresh conversation rather than failing stop.\n }\n }\n\n await disposePiSession();\n workspaceVfs.unmount();\n await rm(hostRoot, { recursive: true, force: true });\n\n return {\n type: 'resume-session',\n harnessId: HARNESS_ID,\n specificationVersion: 'harness-v1',\n data: sessionFileName ? { sessionFileName } : {},\n };\n };\n\n const sessionImpl: HarnessV1Session = {\n sessionId: input.sessionId,\n isResume: input.isResume,\n // The model Pi actually resolves to (the configured id, or its default when\n // unset) — `gen_ai.request.model`.\n ...(resolvedModel?.id ? { modelId: resolvedModel.id } : {}),\n\n // Pi has no bridge to attach to and no on-disk event log to replay; its\n // only resume path is restoring the session file on a fresh/snapshotted\n // sandbox, i.e. `rerun`.\n\n doPromptTurn: async (\n promptOpts: HarnessV1PromptTurnOptions,\n ): Promise<HarnessV1PromptControl> => {\n let text = extractUserText(promptOpts.prompt);\n if (!instructionsApplied && promptOpts.instructions) {\n text = frameInstructions(promptOpts.instructions, text);\n }\n instructionsApplied = true;\n\n return runTurn({\n text,\n tools: promptOpts.tools ?? [],\n emit: promptOpts.emit,\n abortSignal: promptOpts.abortSignal,\n });\n },\n\n doContinueTurn: async (\n continueOpts: HarnessV1ContinueTurnOptions,\n ): Promise<HarnessV1PromptControl> => {\n if (activeTurn != null) {\n currentEmit = continueOpts.emit;\n return createPromptControl({\n done: activeTurn.done,\n abortSignal: continueOpts.abortSignal,\n });\n }\n\n /*\n * Pi runs the model on the host, so there is no live turn in the sandbox\n * to attach to — the previous slice's turn died with its process.\n * Rerun-continue: re-drive the agent from the journal restored on resume.\n * An empty prompt asks Pi to continue its own thread. Lossy — any work in\n * flight at the slice boundary is recomputed because a host-resident\n * runtime cannot do a lossless attach.\n */\n return runTurn({\n text: '',\n tools: continueOpts.tools ?? [],\n emit: continueOpts.emit,\n abortSignal: continueOpts.abortSignal,\n });\n },\n\n doCompact: async (customInstructions?: string) => {\n if (stopped) {\n throw new Error('Pi session has been stopped.');\n }\n /*\n * Pi owns the compaction. We just request it; the resulting\n * `compaction_end` event is observed by the session subscription and\n * translated into a `compaction` stream part. The returned\n * `CompactionResult` is intentionally discarded here.\n */\n await piSession?.compact(customInstructions);\n },\n\n doDestroy: async () => {\n if (stopped) return;\n stopped = true;\n parkedPiSessions.delete(input.sessionId);\n settlePendingToolResults('Pi session stopped');\n settlePendingToolApprovals('Pi session stopped');\n await disposePiSession();\n workspaceVfs.unmount();\n await rm(hostRoot, { recursive: true, force: true });\n },\n\n doStop,\n\n doDetach: async (): Promise<HarnessV1ResumeSessionState> => {\n if (activeTurn != null || pendingToolResults.size > 0) {\n parkedPiSessions.set(input.sessionId, sessionImpl);\n if (sessionFileName) {\n try {\n await persistSessionFile();\n } catch {\n /*\n * The parked in-process session is the authoritative continuation\n * path while the live turn is waiting on host input. Persistence is\n * only a fallback for later non-live resumes.\n */\n }\n }\n return {\n type: 'resume-session',\n harnessId: HARNESS_ID,\n specificationVersion: 'harness-v1',\n data: sessionFileName ? { sessionFileName } : {},\n };\n }\n return doStop();\n },\n\n doSuspendTurn: async (): Promise<HarnessV1ContinueTurnState> => {\n if (stopped) {\n throw new Error('Pi session has been stopped.');\n }\n if (\n activeTurn != null &&\n (pendingToolResults.size > 0 || pendingToolApprovals.size > 0)\n ) {\n parkedPiSessions.set(input.sessionId, sessionImpl);\n if (sessionFileName) {\n try {\n await persistSessionFile();\n } catch {\n /*\n * While waiting on host input, the live parked session is the\n * authoritative same-process continuation path. The sandbox copy\n * remains a best-effort fallback for a later cold resume.\n */\n }\n }\n return {\n type: 'continue-turn',\n harnessId: HARNESS_ID,\n specificationVersion: 'harness-v1',\n data: sessionFileName ? { sessionFileName } : {},\n };\n }\n /*\n * Pi's model runs in this host process, which is about to be suspended at\n * the slice boundary — the in-flight turn cannot survive it. Abort it (the\n * turn settles silently via the `suspending` guard so the stream closes\n * cleanly), persist the journal into the sandbox, and tear down host-side\n * resources. The sandbox itself is left running; the next slice pulls the\n * journal after `provider.resumeSession({ sessionId })` and rerun-continues. The\n * tail in flight at the boundary is recomputed — Pi cannot freeze a live\n * turn the way a bridge adapter can.\n */\n suspending = true;\n await Promise.resolve(piSession?.abort()).catch(() => {});\n\n if (sessionFileName) {\n try {\n await persistSessionFile();\n } catch {\n // Best-effort: a missing/failed copy leaves the previously persisted\n // journal in place, so the next slice resumes from a slightly older\n // (still valid) state.\n }\n }\n\n stopped = true;\n parkedPiSessions.delete(input.sessionId);\n settlePendingToolResults('Pi session suspended');\n settlePendingToolApprovals('Pi session suspended');\n await disposePiSession();\n workspaceVfs.unmount();\n await rm(hostRoot, { recursive: true, force: true });\n\n return {\n type: 'continue-turn',\n harnessId: HARNESS_ID,\n specificationVersion: 'harness-v1',\n data: sessionFileName ? { sessionFileName } : {},\n };\n },\n };\n\n return sessionImpl;\n}\n\nfunction resolvePiMcpServers({\n mcpServers,\n}: {\n mcpServers: Record<string, unknown> | undefined;\n}): Record<string, unknown> {\n if (mcpServers == null) return {};\n for (const [name, value] of Object.entries(mcpServers)) {\n if (value == null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(\n `Pi MCP server ${JSON.stringify(name)} must be configured with an object value.`,\n );\n }\n }\n return mcpServers;\n}\n\n/**\n * Whether a terminal error (string from Pi's event stream, or a thrown error)\n * is an abort — the expected result of `doSuspendTurn` aborting the in-flight\n * turn. Only these are safe to swallow while `suspending`; any other error is\n * unanticipated and must surface as an `error` chunk.\n */\nfunction isAbortError(value: unknown): boolean {\n if (value == null) return false;\n if (\n typeof value === 'object' &&\n (value as { name?: unknown }).name === 'AbortError'\n ) {\n return true;\n }\n const text =\n typeof value === 'string'\n ? value\n : value instanceof Error\n ? value.message\n : String(value);\n return /\\baborted\\b|AbortError|operation was aborted/i.test(text);\n}\n\nfunction asPiToolResult(text: string): AgentToolResult<unknown> {\n return {\n content: [{ type: 'text', text }],\n details: undefined,\n };\n}\n\nasync function maybeDenyPiBuiltinTool(input: {\n toolCallId: string;\n nativeName: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n requestApproval: (args: {\n toolCallId: string;\n nativeName: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n }) => Promise<{ approved: boolean; reason?: string }>;\n}): Promise<AgentToolResult<unknown> | undefined> {\n const decision = await input.requestApproval({\n toolCallId: input.toolCallId,\n nativeName: input.nativeName,\n });\n if (decision.approved) return undefined;\n return asPiToolResult(\n serializeToolOutput({\n type: 'execution-denied',\n reason: decision.reason,\n }),\n );\n}\n\nfunction piBuiltinToolRequiresApproval(input: {\n permissionMode: HarnessV1PermissionMode;\n kind: 'readonly' | 'edit' | 'bash';\n}): boolean {\n if (input.permissionMode === 'allow-all') return false;\n if (input.permissionMode === 'allow-edits') return input.kind === 'bash';\n return input.kind === 'edit' || input.kind === 'bash';\n}\n\nfunction buildBuiltinToolDefinition(input: {\n native: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n remoteOps: PiRemoteOps;\n requestApproval: (args: {\n toolCallId: string;\n nativeName: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n }) => Promise<{ approved: boolean; reason?: string }>;\n}): ToolDefinition {\n switch (input.native) {\n case 'read':\n return defineTool({\n name: 'read',\n label: 'read',\n description: 'Read file contents.',\n parameters: Type.Object({ file_path: Type.String() }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'read',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const buf = await input.remoteOps.readBuffer(params.file_path);\n return asPiToolResult(buf.toString('utf8'));\n },\n });\n case 'write':\n return defineTool({\n name: 'write',\n label: 'write',\n description: 'Write content to a file.',\n parameters: Type.Object({\n file_path: Type.String(),\n content: Type.String(),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'write',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n await input.remoteOps.writeFile(params.file_path, params.content);\n return asPiToolResult(`Wrote ${params.file_path}`);\n },\n });\n case 'edit':\n return defineTool({\n name: 'edit',\n label: 'edit',\n description: 'Edit a file by exact-string replacement.',\n parameters: Type.Object({\n file_path: Type.String(),\n old_string: Type.String(),\n new_string: Type.String(),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'edit',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n await input.remoteOps.editFile(\n params.file_path,\n params.old_string,\n params.new_string,\n );\n return asPiToolResult(`Edited ${params.file_path}`);\n },\n });\n case 'bash':\n return defineTool({\n name: 'bash',\n label: 'bash',\n description: 'Execute a shell command.',\n parameters: Type.Object({\n command: Type.String(),\n timeout: Type.Optional(\n Type.Number({ description: 'Timeout in seconds.' }),\n ),\n }),\n async execute(toolCallId, params, signal) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'bash',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const chunks: Buffer[] = [];\n const result = await input.remoteOps.exec(params.command, '.', {\n onData(data) {\n chunks.push(data);\n },\n ...(signal ? { signal } : {}),\n ...(typeof params.timeout === 'number'\n ? { timeout: params.timeout }\n : {}),\n });\n const out = Buffer.concat(chunks).toString('utf8');\n const text = `${out}${\n result.exitCode != null ? `\\n\\n(exit ${result.exitCode})` : ''\n }`.trim();\n return asPiToolResult(text);\n },\n });\n case 'grep':\n return defineTool({\n name: 'grep',\n label: 'grep',\n description: 'Search file contents with regex.',\n parameters: Type.Object({\n pattern: Type.String(),\n path: Type.Optional(Type.String()),\n glob: Type.Optional(Type.String()),\n ignoreCase: Type.Optional(Type.Boolean()),\n literal: Type.Optional(Type.Boolean()),\n context: Type.Optional(Type.Number()),\n limit: Type.Optional(Type.Number()),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'grep',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const out = await input.remoteOps.grepFiles(params.pattern, params);\n return asPiToolResult(out);\n },\n });\n case 'find':\n return defineTool({\n name: 'find',\n label: 'find',\n description: 'Find files matching a glob pattern.',\n parameters: Type.Object({\n pattern: Type.String(),\n path: Type.Optional(Type.String()),\n limit: Type.Optional(Type.Number()),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'find',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const matches = await input.remoteOps.findFiles(\n params.pattern,\n params.path ?? '.',\n params.limit ?? 1_000,\n );\n return asPiToolResult(matches.join('\\n'));\n },\n });\n case 'ls':\n return defineTool({\n name: 'ls',\n label: 'ls',\n description: 'List directory entries.',\n parameters: Type.Object({\n path: Type.Optional(Type.String()),\n limit: Type.Optional(Type.Number()),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'ls',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const entries = await input.remoteOps.listDirectory(\n params.path ?? '.',\n params.limit ?? 500,\n );\n return asPiToolResult(entries.join('\\n'));\n },\n });\n }\n}\n\nfunction buildUserToolDefinition(\n spec: HarnessV1ToolSpec,\n pending: Map<string, PendingToolResult>,\n): ToolDefinition {\n const schema = spec.inputSchema ?? {\n type: 'object',\n properties: {},\n additionalProperties: true,\n };\n return defineTool({\n name: spec.name,\n label: spec.name,\n description: spec.description ?? `User-registered tool ${spec.name}`,\n parameters: toolSpecToTypeBoxParameters(schema),\n async execute(toolCallId) {\n return new Promise<unknown>(resolve => {\n pending.set(toolCallId, { resolve });\n }).then(output => asPiToolResult(serializeToolOutput(output)));\n },\n });\n}\n","import type {\n ModelRegistry,\n ModelRuntime,\n} from '@earendil-works/pi-coding-agent';\nimport { getAiGatewayAuthFromEnv } from '@ai-sdk/harness/utils';\nimport { VERSION } from './version';\n\ntype ProviderConfigInput = Parameters<ModelRegistry['registerProvider']>[1];\n\n/**\n * Pi auth options. Exactly one of `gateway` or `customEnv` is honoured\n * (precedence: explicit `customEnv`, then explicit `gateway`, then ambient\n * gateway from `process.env`). To use multiple providers, use `customEnv`\n * with the standard `<PREFIX>_API_KEY` / `<PREFIX>_BASE_URL` pattern.\n */\nexport type PiAuthOptions = {\n readonly gateway?: {\n readonly apiKey?: string;\n readonly baseUrl?: string;\n };\n /**\n * Resolved environment-variable pairs of the form `<PREFIX>_API_KEY` and\n * (optionally) `<PREFIX>_BASE_URL`. Special-cased prefixes:\n * - `AI_GATEWAY` → registers `vercel-ai-gateway`\n * - `OPENAI` → registers `openai`\n * - `ANTHROPIC` → registers `anthropic` (`ANTHROPIC_AUTH_TOKEN` adds a\n * bearer auth header)\n * Any other `<PREFIX>_API_KEY` with a matching `<PREFIX>_BASE_URL` is\n * registered as the lowercased, dash-separated prefix.\n */\n readonly customEnv?: Record<string, string>;\n};\n\nconst DEFAULT_GATEWAY_BASE_URL = 'https://ai-gateway.vercel.sh';\nconst DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';\nconst DEFAULT_ANTHROPIC_BASE_URL = 'https://api.anthropic.com';\nconst HARNESS_CLIENT_APP = `ai-sdk/harness-pi/${VERSION}`;\n\nfunction createGatewayProviderConfig({\n apiKey,\n baseUrl,\n clientApp,\n}: {\n apiKey: string;\n baseUrl: string;\n clientApp: string;\n}): ProviderConfigInput {\n return {\n apiKey,\n baseUrl,\n authHeader: true,\n headers: {\n 'User-Agent': clientApp,\n 'x-client-app': clientApp,\n },\n };\n}\n\ntype PiRegistries = {\n modelRegistry: ModelRegistry;\n modelRuntime: ModelRuntime;\n};\n\nasync function register({\n registries,\n provider,\n apiKey,\n config,\n}: {\n registries: PiRegistries;\n provider: string;\n apiKey: string;\n config: ProviderConfigInput;\n}): Promise<void> {\n registries.modelRegistry.registerProvider(provider, config);\n await registries.modelRuntime.setRuntimeApiKey(provider, apiKey);\n}\n\nfunction hasConfiguredValue(value: unknown): boolean {\n if (value == null) return false;\n if (typeof value === 'string') return value.length > 0;\n if (typeof value !== 'object') return true;\n return Object.values(value).some(hasConfiguredValue);\n}\n\nexport function resolvePiEnv({\n options,\n env,\n}: {\n options: PiAuthOptions | undefined;\n env: NodeJS.ProcessEnv;\n}): Record<string, string> {\n const customEnvConfigured = hasConfiguredValue(options?.customEnv);\n if (customEnvConfigured) {\n return resolveCustomEnv({ customEnv: options!.customEnv ?? {} });\n }\n\n const gatewayConfigured = hasConfiguredValue(options?.gateway);\n const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env });\n if (gatewayConfigured) {\n const apiKey = options!.gateway?.apiKey ?? gatewayAuthFromEnv.apiKey;\n const baseUrl = options!.gateway?.baseUrl ?? gatewayAuthFromEnv.baseUrl;\n if (apiKey) {\n return { AI_GATEWAY_API_KEY: apiKey, AI_GATEWAY_BASE_URL: baseUrl };\n }\n return {};\n }\n\n // Ambient gateway fallback.\n if (gatewayAuthFromEnv.apiKey) {\n return {\n AI_GATEWAY_API_KEY: gatewayAuthFromEnv.apiKey,\n AI_GATEWAY_BASE_URL: gatewayAuthFromEnv.baseUrl,\n };\n }\n\n return {};\n}\n\nexport async function registerPiProviders({\n options,\n resolvedEnv,\n registries,\n clientApp = HARNESS_CLIENT_APP,\n}: {\n options: PiAuthOptions | undefined;\n resolvedEnv: Record<string, string>;\n registries: PiRegistries;\n clientApp?: string;\n}): Promise<void> {\n if (hasConfiguredValue(options?.customEnv)) {\n await registerCustomProviders({\n customEnv: options!.customEnv ?? {},\n registries,\n clientApp,\n });\n return;\n }\n\n const apiKey = resolvedEnv.AI_GATEWAY_API_KEY;\n const baseUrl = resolvedEnv.AI_GATEWAY_BASE_URL;\n if (!apiKey || !baseUrl) return;\n\n await register({\n registries,\n provider: 'vercel-ai-gateway',\n apiKey,\n config: createGatewayProviderConfig({ apiKey, baseUrl, clientApp }),\n });\n}\n\nfunction resolveCustomEnv({\n customEnv,\n}: {\n customEnv: Record<string, string>;\n}): Record<string, string> {\n const apiKey = customEnv.AI_GATEWAY_API_KEY;\n if (!apiKey) return {};\n\n return {\n AI_GATEWAY_API_KEY: apiKey,\n AI_GATEWAY_BASE_URL:\n customEnv.AI_GATEWAY_BASE_URL ?? DEFAULT_GATEWAY_BASE_URL,\n };\n}\n\nasync function registerCustomProviders({\n customEnv,\n registries,\n clientApp,\n}: {\n customEnv: Record<string, string>;\n registries: PiRegistries;\n clientApp: string;\n}): Promise<void> {\n const gatewayKey = customEnv.AI_GATEWAY_API_KEY;\n if (gatewayKey) {\n const baseUrl = customEnv.AI_GATEWAY_BASE_URL ?? DEFAULT_GATEWAY_BASE_URL;\n await register({\n registries,\n provider: 'vercel-ai-gateway',\n apiKey: gatewayKey,\n config: createGatewayProviderConfig({\n apiKey: gatewayKey,\n baseUrl,\n clientApp,\n }),\n });\n }\n\n if (customEnv.OPENAI_API_KEY) {\n const baseUrl = customEnv.OPENAI_BASE_URL ?? DEFAULT_OPENAI_BASE_URL;\n await register({\n registries,\n provider: 'openai',\n apiKey: customEnv.OPENAI_API_KEY,\n config: {\n apiKey: customEnv.OPENAI_API_KEY,\n baseUrl,\n authHeader: true,\n },\n });\n }\n\n if (customEnv.ANTHROPIC_API_KEY) {\n const baseUrl = customEnv.ANTHROPIC_BASE_URL ?? DEFAULT_ANTHROPIC_BASE_URL;\n await register({\n registries,\n provider: 'anthropic',\n apiKey: customEnv.ANTHROPIC_API_KEY,\n config: {\n apiKey: customEnv.ANTHROPIC_API_KEY,\n baseUrl,\n ...(customEnv.ANTHROPIC_AUTH_TOKEN\n ? {\n headers: {\n authorization: `Bearer ${customEnv.ANTHROPIC_AUTH_TOKEN}`,\n },\n }\n : {}),\n },\n });\n }\n\n for (const [name, apiKey] of Object.entries(customEnv)) {\n if (!name.endsWith('_API_KEY') || !apiKey) {\n continue;\n }\n const prefix = name.slice(0, -'_API_KEY'.length);\n if (\n prefix === 'AI_GATEWAY' ||\n prefix === 'OPENAI' ||\n prefix === 'ANTHROPIC'\n ) {\n continue;\n }\n const provider = prefix.toLowerCase().replace(/_/g, '-');\n const baseUrl = customEnv[`${prefix}_BASE_URL`];\n if (!baseUrl) {\n continue;\n }\n await register({\n registries,\n provider,\n apiKey,\n config: {\n apiKey,\n baseUrl,\n authHeader: true,\n },\n });\n }\n}\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n","import { z } from 'zod/v4';\n\n/**\n * Pi `session.subscribe` emits a discriminated union of events. The exact\n * shape evolves with Pi versions; we accept loose objects and extract only\n * the fields we recognise. The `type` field is required and stringly-typed\n * because Pi may add new types we want to ignore.\n */\nexport const piSessionEventSchema = z.looseObject({\n type: z.string(),\n assistantMessageEvent: z\n .looseObject({\n type: z.string().optional(),\n delta: z.string().optional(),\n })\n .optional(),\n toolCallId: z.string().optional(),\n toolName: z.string().optional(),\n args: z.unknown().optional(),\n input: z.unknown().optional(),\n result: z.unknown().optional(),\n content: z.unknown().optional(),\n isError: z.boolean().optional(),\n // Compaction events (`compaction_start` / `compaction_end`). `result` (a\n // `CompactionResult`) rides the shared `result` field above; `reason`\n // distinguishes manual vs automatic (threshold/overflow) compaction.\n reason: z.string().optional(),\n aborted: z.boolean().optional(),\n error: z\n .union([\n z.string(),\n z.looseObject({\n errorMessage: z.string().optional(),\n stopReason: z.string().optional(),\n }),\n ])\n .optional(),\n message: z\n .looseObject({\n role: z.string().optional(),\n content: z.unknown().optional(),\n stopReason: z.string().optional(),\n errorMessage: z.string().optional(),\n })\n .optional(),\n});\n\nexport type PiSessionEvent = z.infer<typeof piSessionEventSchema>;\n\n/**\n * Decode an unknown raw event into a `PiSessionEvent` if it looks like one.\n * Returns `undefined` if it doesn't parse so the caller can skip it.\n */\nexport function parseNativeEvent(raw: unknown): PiSessionEvent | undefined {\n const parsed = piSessionEventSchema.safeParse(raw);\n return parsed.success ? parsed.data : undefined;\n}\n\n/**\n * Detect whether a Pi event signals a terminal error for the current turn.\n * Returns the error message if so. Mirrors the original adapter's\n * `getPiTerminalError`.\n */\nexport function getPiTerminalError(event: PiSessionEvent): string | undefined {\n const isTerminalStopReason = (value: string | undefined) =>\n value === 'error' || value === 'aborted';\n\n if (typeof event.error === 'string' && event.error.trim()) {\n return event.error.trim();\n }\n\n if (event.error && typeof event.error === 'object') {\n const errorMessage = event.error.errorMessage?.trim();\n if (errorMessage) {\n return errorMessage;\n }\n const stopReason = event.error.stopReason?.trim();\n if (isTerminalStopReason(stopReason)) {\n return stopReason;\n }\n }\n\n const messageError = event.message?.errorMessage?.trim();\n if (messageError) {\n return messageError;\n }\n\n const messageStopReason = event.message?.stopReason?.trim();\n if (isTerminalStopReason(messageStopReason)) {\n return messageStopReason;\n }\n\n if (\n event.isError &&\n typeof event.content === 'string' &&\n event.content.trim()\n ) {\n return event.content.trim();\n }\n\n return undefined;\n}\n\n/** Pull the assistant text from a `turn_end` / `message_end` event payload. */\nexport function extractAssistantText(\n message: PiSessionEvent['message'],\n): string {\n if (!message || message.role !== 'assistant') {\n return '';\n }\n\n if (typeof message.content === 'string') {\n return message.content;\n }\n\n if (!Array.isArray(message.content)) {\n return '';\n }\n\n return message.content\n .flatMap(part => {\n if (!part || typeof part !== 'object') {\n return [];\n }\n const contentPart = part as Record<string, unknown>;\n return contentPart.type === 'text' && typeof contentPart.text === 'string'\n ? [contentPart.text]\n : [];\n })\n .join('');\n}\n","import type { ModelRegistry } from '@earendil-works/pi-coding-agent';\nimport { getAiGatewayAuthFromEnv } from '@ai-sdk/harness/utils';\n\ntype PiModel = ReturnType<ModelRegistry['getAll']>[number];\n\n/**\n * Default model id used when no `model` is configured AND gateway credentials\n * are available in the environment. Looked up from Pi's own model registry —\n * the entry must exist under the `vercel-ai-gateway` provider in\n * `@earendil-works/pi-ai`'s catalog.\n */\nexport const DEFAULT_PI_GATEWAY_MODEL_ID = 'anthropic/claude-sonnet-4.6';\n\n/*\n * A `\"<provider>/<id>\"` reference normally resolves under that provider, not\n * any entry whose flat `id` happens to equal the whole string. Routing proxies\n * (`vercel-ai-gateway`, `openrouter`) can carry another provider's id verbatim\n * as their own flat `id` (e.g. `id: \"xai/grok-4.3\"`), so this tier normally\n * wins over flat matching. An authenticated literal-id match remains usable\n * when the scoped provider is unauthenticated, matching Pi's own resolver.\n * Gateway preference stays first because gateway credentials explicitly opt\n * the harness into routing matching models through the gateway.\n */\nconst findScopedMatch = (\n effectiveId: string,\n models: PiModel[],\n): PiModel | undefined => {\n const slashIndex = effectiveId.indexOf('/');\n if (slashIndex === -1) return undefined;\n\n const prefix = effectiveId.slice(0, slashIndex);\n const bareId = effectiveId.slice(slashIndex + 1);\n return models.find(\n m => m.provider === prefix && (m.id === bareId || m.name === bareId),\n );\n};\n\nexport function createPiModelResolver({\n modelRegistry,\n env = process.env,\n}: {\n modelRegistry: ModelRegistry;\n env?: NodeJS.ProcessEnv;\n}) {\n let cachedModels: PiModel[] | undefined;\n\n const loadModels = (): PiModel[] => {\n if (cachedModels) {\n return cachedModels;\n }\n try {\n cachedModels = modelRegistry.getAll();\n } catch {\n cachedModels = [];\n }\n return cachedModels;\n };\n\n return (modelId: string | undefined): PiModel | undefined => {\n const useGateway = Boolean(getAiGatewayAuthFromEnv({ env }).apiKey);\n const effectiveId =\n modelId ?? (useGateway ? DEFAULT_PI_GATEWAY_MODEL_ID : undefined);\n if (!effectiveId) return undefined;\n\n const models = loadModels();\n const matches = (m: PiModel) =>\n m.id === effectiveId || m.name === effectiveId;\n\n // When gateway creds are present, prefer the gateway-routed entry for the\n // given id. Pi's catalog lists the same model id under multiple providers\n // (e.g. `anthropic/claude-sonnet-4.6` exists under both `openrouter` and\n // `vercel-ai-gateway`); without this preference Pi would dispatch through\n // a provider we didn't register, which fails with \"No API key found\".\n const gatewayMatch = useGateway\n ? models.find(m => m.provider === 'vercel-ai-gateway' && matches(m))\n : undefined;\n if (gatewayMatch) return gatewayMatch;\n\n const scopedMatch = findScopedMatch(effectiveId, models);\n if (scopedMatch && !modelRegistry.hasConfiguredAuth(scopedMatch)) {\n const authenticatedFlatMatches = models.filter(\n m => m.id === effectiveId && modelRegistry.hasConfiguredAuth(m),\n );\n if (authenticatedFlatMatches.length === 1) {\n return authenticatedFlatMatches[0];\n }\n }\n\n return scopedMatch ?? models.find(matches);\n };\n}\n","import { realpathSync } from 'node:fs';\nimport path from 'node:path';\n\nexport interface PiPathMapper {\n /** The host-side mirror directory Pi reads/writes through the workspace VFS. */\n readonly hostWorkDir: string;\n /** The sandbox-side working directory where tools actually operate. */\n readonly sandboxWorkDir: string;\n /**\n * Translate a path the host sees (relative to `hostWorkDir`, or absolute\n * inside it, or already a sandbox path) to the canonical sandbox path. Throws\n * if the path would escape the workspace.\n */\n toSandboxPath(inputPath: string): string;\n /**\n * Translate a path for read-only tools. In addition to the workspace, this\n * allows explicitly configured sandbox roots such as `$HOME/.agents/skills`.\n */\n toReadableSandboxPath(inputPath: string): string;\n /** Verify that a sandbox-side path is still inside `sandboxWorkDir`. */\n assertSandboxPath(inputPath: string): string;\n /**\n * Verify that a sandbox-side path is inside `sandboxWorkDir` or an\n * explicitly configured readable root.\n */\n assertReadableSandboxPath(inputPath: string): string;\n /** Translate any path to its POSIX-relative form under `sandboxWorkDir`. */\n toRelativePath(inputPath: string): string;\n}\n\nexport interface PiReadablePathRoot {\n readonly sandboxDir: string;\n}\n\nexport interface CreatePiPathMapperOptions {\n readonly hostWorkDir: string;\n readonly sandboxWorkDir: string;\n readonly readableRoots?: ReadonlyArray<PiReadablePathRoot>;\n}\n\nfunction isInsidePath(parent: string, candidate: string): boolean {\n const relative = path.relative(parent, candidate);\n return (\n relative === '' ||\n (!relative.startsWith('..') && !path.isAbsolute(relative))\n );\n}\n\nfunction isInsidePosixPath(parent: string, candidate: string): boolean {\n const relative = path.posix.relative(parent, candidate);\n return (\n relative === '' ||\n (!relative.startsWith('..') && !path.posix.isAbsolute(relative))\n );\n}\n\nfunction canonicalizeForContainment(inputPath: string): string {\n try {\n return realpathSync.native(inputPath);\n } catch {\n const parent = path.dirname(inputPath);\n if (parent === inputPath) {\n return inputPath;\n }\n return path.join(\n canonicalizeForContainment(parent),\n path.basename(inputPath),\n );\n }\n}\n\nexport function createPiPathMapper(\n options: CreatePiPathMapperOptions,\n): PiPathMapper {\n const normalizedHost = path.resolve(options.hostWorkDir);\n const normalizedSandbox = path.posix.normalize(options.sandboxWorkDir);\n const canonicalHost = canonicalizeForContainment(normalizedHost);\n const readableRoots =\n options.readableRoots?.map(root => ({\n sandboxDir: path.posix.normalize(root.sandboxDir),\n })) ?? [];\n\n const assertWorkspaceSandboxPath = (inputPath: string): string => {\n const normalizedInput = path.posix.normalize(inputPath);\n if (!isInsidePosixPath(normalizedSandbox, normalizedInput)) {\n throw new Error(`Pi path escapes the workspace: ${inputPath}`);\n }\n return normalizedInput;\n };\n\n const assertReadableSandboxPath = (inputPath: string): string => {\n const normalizedInput = path.posix.normalize(inputPath);\n if (\n !isInsidePosixPath(normalizedSandbox, normalizedInput) &&\n !readableRoots.some(root =>\n isInsidePosixPath(root.sandboxDir, normalizedInput),\n )\n ) {\n throw new Error(`Pi path escapes the readable roots: ${inputPath}`);\n }\n return normalizedInput;\n };\n\n const toWorkspaceSandboxPath = (inputPath: string): string => {\n if (path.posix.isAbsolute(inputPath)) {\n const normalizedInput = path.posix.normalize(inputPath);\n try {\n return assertWorkspaceSandboxPath(normalizedInput);\n } catch {\n // Absolute host paths are handled below.\n }\n }\n\n const resolvedHost = path.isAbsolute(inputPath)\n ? path.resolve(inputPath)\n : path.resolve(normalizedHost, inputPath);\n const canonicalResolvedHost = canonicalizeForContainment(resolvedHost);\n if (\n !isInsidePath(normalizedHost, resolvedHost) ||\n !isInsidePath(canonicalHost, canonicalResolvedHost)\n ) {\n throw new Error(`Pi path escapes the workspace: ${inputPath}`);\n }\n\n const relative = path\n .relative(normalizedHost, resolvedHost)\n .split(path.sep)\n .join('/');\n return relative\n ? path.posix.join(normalizedSandbox, relative)\n : normalizedSandbox;\n };\n\n return {\n hostWorkDir: normalizedHost,\n sandboxWorkDir: normalizedSandbox,\n toSandboxPath(inputPath: string) {\n return toWorkspaceSandboxPath(inputPath);\n },\n toReadableSandboxPath(inputPath: string) {\n if (path.posix.isAbsolute(inputPath)) {\n const normalizedInput = path.posix.normalize(inputPath);\n try {\n return assertReadableSandboxPath(normalizedInput);\n } catch {\n // Absolute host paths are handled by workspace mapping below.\n }\n }\n\n return toWorkspaceSandboxPath(inputPath);\n },\n assertSandboxPath(inputPath: string) {\n return assertWorkspaceSandboxPath(inputPath);\n },\n assertReadableSandboxPath(inputPath: string) {\n return assertReadableSandboxPath(inputPath);\n },\n toRelativePath(inputPath: string) {\n const sandboxPath = path.posix.isAbsolute(inputPath)\n ? path.posix.normalize(inputPath)\n : path.posix.join(\n normalizedSandbox,\n inputPath.split(path.sep).join('/'),\n );\n const relative = path.posix.relative(normalizedSandbox, sandboxPath);\n return relative || '.';\n },\n };\n}\n","import path from 'node:path';\nimport { shellQuote } from '@ai-sdk/harness/utils';\nimport type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';\nimport type { PiPathMapper } from './pi-paths';\n\nexport type PiRemoteFileChangeKind = 'create' | 'modify';\n\nexport interface PiRemoteOpsOptions {\n readonly sandbox: Experimental_SandboxSession;\n readonly paths: PiPathMapper;\n readonly env?: Record<string, string>;\n readonly onFileChange?: (\n event: PiRemoteFileChangeKind,\n relativePath: string,\n content: Buffer,\n ) => void;\n}\n\nexport interface PiRemoteOps {\n readonly paths: PiPathMapper;\n readBuffer(inputPath: string): Promise<Buffer>;\n writeFile(inputPath: string, content: string): Promise<void>;\n editFile(\n inputPath: string,\n oldText: string,\n newText: string,\n ): Promise<string>;\n listDirectory(inputPath?: string, limit?: number): Promise<string[]>;\n findFiles(\n pattern: string,\n inputPath?: string,\n limit?: number,\n ): Promise<string[]>;\n grepFiles(\n pattern: string,\n input: {\n path?: string;\n glob?: string;\n ignoreCase?: boolean;\n literal?: boolean;\n context?: number;\n limit?: number;\n },\n ): Promise<string>;\n access(inputPath: string): Promise<void>;\n exec(\n command: string,\n cwd: string,\n input: {\n onData: (data: Buffer) => void;\n signal?: AbortSignal;\n timeout?: number;\n },\n ): Promise<{ exitCode: number | null }>;\n}\n\ninterface RunShellInput {\n cwd?: string;\n signal?: AbortSignal;\n onData?: (data: Buffer) => void;\n}\n\ninterface RunShellResult {\n exitCode: number | null;\n output: Buffer;\n}\n\nfunction lastOutputLine(output: Buffer): string | undefined {\n return output.toString('utf8').trim().split('\\n').filter(Boolean).at(-1);\n}\n\nexport function createPiRemoteOps(options: PiRemoteOpsOptions): PiRemoteOps {\n const runShell = async (\n command: string,\n input: RunShellInput = {},\n ): Promise<RunShellResult> => {\n // `sandbox.run({ command })` already wraps in `bash -c`; we pass the\n // shell snippet directly. shellQuote is still used inside `command`\n // for path/value interpolation by the callers.\n const result = await options.sandbox.run({\n command,\n ...(input.cwd\n ? { workingDirectory: options.paths.toSandboxPath(input.cwd) }\n : {}),\n ...(options.env ? { env: options.env } : {}),\n ...(input.signal ? { abortSignal: input.signal } : {}),\n });\n\n const combined = `${result.stdout}${result.stderr}`;\n const output = Buffer.from(combined, 'utf8');\n if (output.length > 0) {\n input.onData?.(output);\n }\n\n return {\n exitCode: result.exitCode,\n output,\n };\n };\n\n const resolveExistingSandboxPath = async (\n remotePath: string,\n inputPath: string,\n ): Promise<string> => {\n const result = await runShell(\n [\n `target=${shellQuote(remotePath)}`,\n `if [ ! -e \"$target\" ]; then echo \"__PI_REALPATH_NOT_FOUND__\"; exit 2; fi`,\n `resolved=$(realpath \"$target\" 2>/dev/null) || { echo \"__PI_REALPATH_FAILED__\"; exit 3; }`,\n `printf '%s\\\\n' \"$resolved\"`,\n ].join('; '),\n );\n\n const output = result.output.toString('utf8');\n if (output.includes('__PI_REALPATH_NOT_FOUND__')) {\n throw new Error(`Path not found: ${inputPath}`);\n }\n if (output.includes('__PI_REALPATH_FAILED__') || result.exitCode !== 0) {\n throw new Error(`Unable to resolve path: ${inputPath}`);\n }\n\n const resolvedPath = lastOutputLine(result.output);\n if (!resolvedPath) {\n throw new Error(`Unable to resolve path: ${inputPath}`);\n }\n return resolvedPath;\n };\n\n const resolveReadableSandboxPath = async (\n remotePath: string,\n inputPath: string,\n ): Promise<string> =>\n options.paths.assertReadableSandboxPath(\n await resolveExistingSandboxPath(remotePath, inputPath),\n );\n\n const resolveWritableSandboxPath = async (\n remotePath: string,\n inputPath: string,\n ): Promise<string> => {\n const result = await runShell(\n [\n `target=${shellQuote(remotePath)}`,\n `if [ -e \"$target\" ] || [ -L \"$target\" ]; then resolved=$(realpath \"$target\" 2>/dev/null) || { echo \"__PI_REALPATH_FAILED__\"; exit 3; }; printf '%s\\\\n' \"$resolved\"; exit 0; fi`,\n `dir=$(dirname \"$target\")`,\n `base=$(basename \"$target\")`,\n `missing=\"$base\"`,\n `while [ ! -e \"$dir\" ] && [ ! -L \"$dir\" ]; do parent=$(dirname \"$dir\"); if [ \"$parent\" = \"$dir\" ]; then echo \"__PI_REALPATH_NOT_FOUND__\"; exit 2; fi; missing=\"$(basename \"$dir\")/$missing\"; dir=\"$parent\"; done`,\n `resolved_dir=$(realpath \"$dir\" 2>/dev/null) || { echo \"__PI_REALPATH_FAILED__\"; exit 3; }`,\n `printf '%s/%s\\\\n' \"$resolved_dir\" \"$missing\"`,\n ].join('; '),\n );\n\n const output = result.output.toString('utf8');\n if (\n output.includes('__PI_REALPATH_NOT_FOUND__') ||\n output.includes('__PI_REALPATH_FAILED__') ||\n result.exitCode !== 0\n ) {\n throw new Error(`Unable to resolve path: ${inputPath}`);\n }\n\n const resolvedPath = lastOutputLine(result.output);\n if (!resolvedPath) {\n throw new Error(`Unable to resolve path: ${inputPath}`);\n }\n return options.paths.assertSandboxPath(resolvedPath);\n };\n\n const readBuffer = async (inputPath: string): Promise<Buffer> => {\n const remotePath = options.paths.toReadableSandboxPath(inputPath);\n const resolvedPath = await resolveReadableSandboxPath(\n remotePath,\n inputPath,\n );\n const bytes = await options.sandbox.readBinaryFile({\n path: resolvedPath,\n });\n if (!bytes) {\n throw new Error(`Path not found: ${inputPath}`);\n }\n return Buffer.from(bytes);\n };\n\n const writeFile = async (\n inputPath: string,\n content: string,\n ): Promise<void> => {\n const remotePath = options.paths.toSandboxPath(inputPath);\n const resolvedPath = await resolveWritableSandboxPath(\n remotePath,\n inputPath,\n );\n const previous = await options.sandbox.readBinaryFile({\n path: resolvedPath,\n });\n await runShell(`mkdir -p ${shellQuote(path.posix.dirname(resolvedPath))}`);\n await options.sandbox.writeTextFile({ path: resolvedPath, content });\n options.onFileChange?.(\n previous ? 'modify' : 'create',\n options.paths.toRelativePath(resolvedPath),\n Buffer.from(content, 'utf8'),\n );\n };\n\n const editFile = async (\n inputPath: string,\n oldText: string,\n newText: string,\n ): Promise<string> => {\n const current = (await readBuffer(inputPath)).toString('utf8');\n const index = current.indexOf(oldText);\n if (index === -1) {\n throw new Error(`Text to replace was not found in ${inputPath}`);\n }\n const updated = `${current.slice(0, index)}${newText}${current.slice(\n index + oldText.length,\n )}`;\n await writeFile(inputPath, updated);\n return updated;\n };\n\n const listDirectory = async (\n inputPath: string = '.',\n limit: number = 500,\n ): Promise<string[]> => {\n const remotePath = options.paths.toReadableSandboxPath(inputPath);\n const resolvedPath = await resolveReadableSandboxPath(\n remotePath,\n inputPath,\n );\n const result = await runShell(\n [\n `if [ ! -e ${shellQuote(resolvedPath)} ]; then echo \"__PI_LS_NOT_FOUND__\"; exit 2; fi`,\n `if [ ! -d ${shellQuote(resolvedPath)} ]; then echo \"__PI_LS_NOT_DIR__\"; exit 3; fi`,\n `cd ${shellQuote(resolvedPath)}`,\n 'ls -1Ap',\n ].join('; '),\n );\n\n const output = result.output.toString('utf8').trim();\n if (output.includes('__PI_LS_NOT_FOUND__')) {\n throw new Error(`Path not found: ${inputPath}`);\n }\n if (output.includes('__PI_LS_NOT_DIR__')) {\n throw new Error(`Not a directory: ${inputPath}`);\n }\n\n return output\n .split('\\n')\n .filter(Boolean)\n .map(line => line.replace(/[*=@|]$/, ''))\n .sort((left, right) =>\n left.toLowerCase().localeCompare(right.toLowerCase()),\n )\n .slice(0, limit);\n };\n\n const findFiles = async (\n pattern: string,\n inputPath: string = '.',\n limit: number = 1_000,\n ): Promise<string[]> => {\n const remotePath = options.paths.toReadableSandboxPath(inputPath);\n const resolvedPath = await resolveReadableSandboxPath(\n remotePath,\n inputPath,\n );\n const result = await runShell(\n [\n `if [ ! -e ${shellQuote(resolvedPath)} ]; then echo \"__PI_FIND_NOT_FOUND__\"; exit 2; fi`,\n `if [ -d ${shellQuote(resolvedPath)} ]; then find ${shellQuote(resolvedPath)} -type f -print; else printf '%s\\\\n' ${shellQuote(resolvedPath)}; fi`,\n ].join('; '),\n );\n\n const output = result.output.toString('utf8').trim();\n if (output.includes('__PI_FIND_NOT_FOUND__')) {\n throw new Error(`Path not found: ${inputPath}`);\n }\n\n const searchRoot = resolvedPath;\n return output\n .split('\\n')\n .filter(Boolean)\n .map(absolutePath => {\n if (absolutePath === searchRoot) {\n return path.posix.basename(absolutePath);\n }\n return path.posix.relative(searchRoot, absolutePath);\n })\n .filter(\n candidate =>\n candidate.length > 0 && path.matchesGlob(candidate, pattern),\n )\n .sort((left, right) =>\n left.toLowerCase().localeCompare(right.toLowerCase()),\n )\n .slice(0, limit);\n };\n\n const grepFiles = async (\n pattern: string,\n input: {\n path?: string;\n glob?: string;\n ignoreCase?: boolean;\n literal?: boolean;\n context?: number;\n limit?: number;\n },\n ): Promise<string> => {\n const remotePath = options.paths.toReadableSandboxPath(input.path ?? '.');\n const resolvedPath = await resolveReadableSandboxPath(\n remotePath,\n input.path ?? '.',\n );\n const relativeTarget = options.paths.toRelativePath(resolvedPath);\n const targetPath =\n relativeTarget.startsWith('../') || path.posix.isAbsolute(relativeTarget)\n ? resolvedPath\n : relativeTarget;\n const flags = [\n '-R',\n '-n',\n '--binary-files=without-match',\n ...(input.ignoreCase ? ['-i'] : []),\n ...(input.literal ? ['-F'] : []),\n ...(typeof input.context === 'number' && input.context > 0\n ? ['-C', String(input.context)]\n : []),\n ...(input.glob ? ['--include', input.glob] : []),\n ];\n const limit = Math.max(1, input.limit ?? 100);\n const result = await runShell(\n [\n `if [ ! -e ${shellQuote(resolvedPath)} ]; then echo \"__PI_GREP_NOT_FOUND__\"; exit 2; fi`,\n `cd ${shellQuote(options.paths.sandboxWorkDir)}`,\n `grep ${flags.map(shellQuote).join(' ')} -- ${shellQuote(pattern)} ${shellQuote(targetPath)} 2>/dev/null | head -n ${limit}`,\n ].join('; '),\n );\n\n const output = result.output.toString('utf8').trim();\n if (output.includes('__PI_GREP_NOT_FOUND__')) {\n throw new Error(`Path not found: ${input.path ?? '.'}`);\n }\n\n return output || 'No matches found';\n };\n\n return {\n paths: options.paths,\n readBuffer,\n writeFile,\n editFile,\n listDirectory,\n findFiles,\n grepFiles,\n async access(inputPath: string) {\n await readBuffer(inputPath);\n },\n async exec(command, cwd, input): Promise<{ exitCode: number | null }> {\n const controller = new AbortController();\n // `input.timeout` is expressed in seconds (Pi's `bash` tool contract),\n // so convert to milliseconds for `setTimeout`.\n const timeoutId =\n typeof input.timeout === 'number' && input.timeout > 0\n ? setTimeout(() => controller.abort(), input.timeout * 1000)\n : undefined;\n\n const forwardedSignal = input.signal;\n const onAbort = () => controller.abort();\n forwardedSignal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const result = await runShell(command, {\n cwd,\n signal: controller.signal,\n onData: input.onData,\n });\n return { exitCode: result.exitCode };\n } finally {\n forwardedSignal?.removeEventListener('abort', onAbort);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n },\n };\n}\n","import path from 'node:path';\nimport type { HarnessV1Skill } from '@ai-sdk/harness';\nimport { writeSkills } from '@ai-sdk/harness/utils';\nimport type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';\n\n/**\n * Materialize Pi skills as files under\n * `$HOME/.agents/skills/<name>/SKILL.md` inside the sandbox.\n */\nexport async function writePiSkills(args: {\n readonly sandbox: Experimental_SandboxSession;\n readonly sandboxHomeDir: string;\n readonly skills: ReadonlyArray<HarnessV1Skill>;\n readonly abortSignal?: AbortSignal;\n}): Promise<void> {\n await writeSkills({\n sandbox: args.sandbox,\n rootDir: path.posix.join(args.sandboxHomeDir, '.agents', 'skills'),\n skills: args.skills,\n abortSignal: args.abortSignal,\n invalidSkillNameMessage: ({ name }) => `Invalid Pi skill name: ${name}`,\n invalidSkillFilePathMessage: ({ skillName, filePath }) =>\n `Invalid Pi skill file path for ${skillName}: ${filePath}`,\n });\n}\n","import { randomBytes } from 'node:crypto';\nimport type { HarnessV1StreamPart } from '@ai-sdk/harness';\nimport { secureJsonParse } from '@ai-sdk/provider-utils';\nimport { extractAssistantText, type PiSessionEvent } from './pi-events';\nimport { serializeToolOutput } from './pi-utils';\n\n/**\n * Translator state shared across all events of a single turn. Reset at the\n * start of every `doPromptTurn`. Callers update the same instance and read it to\n * decide when a turn has settled into a steady state (e.g. for gap-filling).\n */\nexport interface PiTranslatorState {\n /**\n * True once a `turn_start` or assistant `message_start` event has been\n * observed. Suppresses spurious deltas that arrive before the turn opens.\n */\n promptStarted: boolean;\n /** Accumulated assistant text from `text_delta` events. */\n streamedAssistantText: string;\n /** Stream-part id for the active text block; synthesized on first delta. */\n currentTextId: string | undefined;\n /**\n * Stream-part id for the active reasoning block; synthesized lazily on\n * first `thinking_delta`.\n */\n currentReasoningId: string | undefined;\n /** Whether a `reasoning-start` event has already been emitted. */\n reasoningStarted: boolean;\n /** Tool-call id → tool name (used to fill in `toolName` on results). */\n observedToolNames: Map<string, string>;\n /** Tool ids requested by the current assistant message but not yet completed. */\n pendingStepToolCallIds: Set<string>;\n /** Whether the current assistant message has opened a visible step. */\n stepOpen: boolean;\n /**\n * Tool-call id → the exact output value the host submitted for a\n * user-registered (host-executed) tool. Pi only echoes the tool result back\n * as serialized text (the tool handler stringifies the output before handing\n * it to the runtime so the model can read it), which would otherwise reach\n * consumers as a string and lose the original object structure. Keeping the\n * submitted value here lets the result projection surface the original object\n * — matching the other adapters — while the model still receives the text.\n * Populated by the session's `submitToolResult`; consumed (and cleared) when\n * the matching `tool_result`/`tool_execution_end` event is translated.\n */\n hostToolResults: Map<string, unknown>;\n dynamicToolCallIds: Set<string>;\n /**\n * Names of tools that Pi executes natively (read/write/edit/bash/grep/\n * find/ls). `tool-call` events for these get `providerExecuted: true`\n * so the harness host doesn't try to dispatch them. User-registered\n * tools are not in this set.\n */\n readonly builtinToolNames: ReadonlySet<string>;\n readonly hostToolNames: ReadonlySet<string>;\n /**\n * Map of native tool name → common name. `find` → `glob`, etc. Pi emits\n * native names on its events; the wire `toolName` is the common name when\n * one exists.\n */\n readonly nativeToCommonNameMap: ReadonlyMap<string, string>;\n}\n\nexport interface PiTranslatorStateOptions {\n readonly builtinToolNames?: ReadonlyArray<string>;\n readonly hostToolNames?: ReadonlyArray<string>;\n readonly nativeToCommon?:\n | ReadonlyMap<string, string>\n | Record<string, string>;\n}\n\nexport function createPiTranslatorState(\n options: PiTranslatorStateOptions = {},\n): PiTranslatorState {\n const map =\n options.nativeToCommon instanceof Map\n ? options.nativeToCommon\n : new Map(Object.entries(options.nativeToCommon ?? {}));\n return {\n promptStarted: false,\n streamedAssistantText: '',\n currentTextId: undefined,\n currentReasoningId: undefined,\n reasoningStarted: false,\n observedToolNames: new Map(),\n pendingStepToolCallIds: new Set(),\n stepOpen: false,\n hostToolResults: new Map(),\n dynamicToolCallIds: new Set(),\n builtinToolNames: new Set(options.builtinToolNames ?? []),\n hostToolNames: new Set(options.hostToolNames ?? []),\n nativeToCommonNameMap: map,\n };\n}\n\nfunction newId(): string {\n return randomBytes(8).toString('hex');\n}\n\n/**\n * Pi's `tool_execution_end` event payload (`result`) is a Pi `AgentToolResult`\n * envelope `{ content: (TextContent | ImageContent)[], details, terminate? }`.\n * The `tool_result` event uses a flat shape with `content` and `details` at\n * the top level. In both cases we extract just the text payload (joined when\n * multiple text parts are present) so the AI SDK consumer sees the raw\n * string the tool produced.\n */\nfunction unwrapPiToolResult(event: PiSessionEvent): never {\n const candidates: unknown[] = [];\n const result = event.result as unknown;\n if (result && typeof result === 'object') {\n const inner = (result as { content?: unknown }).content;\n if (Array.isArray(inner)) candidates.push(inner);\n }\n if (Array.isArray(event.content)) candidates.push(event.content);\n\n for (const content of candidates) {\n if (!Array.isArray(content)) continue;\n const text = content\n .filter(\n (p): p is { type: 'text'; text: string } =>\n !!p &&\n typeof p === 'object' &&\n (p as { type?: unknown }).type === 'text' &&\n typeof (p as { text?: unknown }).text === 'string',\n )\n .map(p => p.text)\n .join('');\n if (text) return text as never;\n }\n\n if (typeof event.result === 'string') return event.result as never;\n if (typeof event.content === 'string') return event.content as never;\n return (event.result ?? event.content ?? null) as never;\n}\n\nfunction parseMcpToolResult(content: unknown): unknown {\n if (typeof content !== 'string') return content;\n try {\n return secureJsonParse(content);\n } catch {\n return content;\n }\n}\n\nfunction resolveToolName(\n state: PiTranslatorState,\n nativeName: string,\n): { wire: string; native: string } {\n const common = state.nativeToCommonNameMap.get(nativeName);\n return { wire: common ?? nativeName, native: nativeName };\n}\n\nfunction finishStep(state: PiTranslatorState): HarnessV1StreamPart[] {\n if (!state.stepOpen || state.pendingStepToolCallIds.size > 0) return [];\n state.stepOpen = false;\n state.pendingStepToolCallIds.clear();\n return [\n {\n type: 'finish-step',\n finishReason: { unified: 'stop', raw: 'stop' },\n usage: {\n inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },\n outputTokens: { total: 0, text: 0, reasoning: 0 },\n },\n harnessMetadata: { pi: { inferredStep: true } },\n },\n ];\n}\n\nexport function finishPiApprovalStep(\n state: PiTranslatorState,\n toolCallId: string,\n): HarnessV1StreamPart[] {\n state.stepOpen = true;\n state.pendingStepToolCallIds.delete(toolCallId);\n return finishStep(state);\n}\n\nfunction extractPiToolCallIds(message: PiSessionEvent['message']): string[] {\n if (!message || message.role !== 'assistant') return [];\n if (!Array.isArray(message.content)) return [];\n return message.content.flatMap(part => {\n if (!part || typeof part !== 'object') return [];\n const block = part as Record<string, unknown>;\n if (block.type !== 'toolCall') return [];\n const id = block.id ?? block.toolCallId;\n return typeof id === 'string' && id.length > 0 ? [id] : [];\n });\n}\n\n/**\n * Translate a single Pi `session.subscribe` event into zero or more\n * `HarnessV1StreamPart`s, updating the translator state in place. Returns\n * an empty array for events that produce no output (e.g. events emitted\n * before `turn_start`).\n *\n * The translator does NOT emit `stream-start`/`finish` — those are\n * lifecycle signals owned by the session layer.\n */\nexport function translatePiEvent(\n event: PiSessionEvent,\n state: PiTranslatorState,\n): HarnessV1StreamPart[] {\n switch (event.type) {\n case 'turn_start':\n case 'message_start': {\n if (\n event.type === 'message_start' &&\n event.message?.role !== 'assistant'\n ) {\n return [];\n }\n state.promptStarted = true;\n if (event.type === 'message_start') {\n state.stepOpen = true;\n state.pendingStepToolCallIds.clear();\n }\n state.streamedAssistantText = '';\n state.currentTextId = undefined;\n state.currentReasoningId = undefined;\n state.reasoningStarted = false;\n return [];\n }\n\n case 'message_update': {\n if (!state.promptStarted) return [];\n const update = event.assistantMessageEvent;\n if (!update) return [];\n if (update.type === 'text_delta' && typeof update.delta === 'string') {\n const parts: HarnessV1StreamPart[] = [];\n // If reasoning was active, close it before opening the text block so\n // consumers can reset block-scoped formatting (ANSI colors, etc.)\n // between sections.\n if (state.reasoningStarted && state.currentReasoningId) {\n parts.push({\n type: 'reasoning-end',\n id: state.currentReasoningId,\n });\n state.reasoningStarted = false;\n state.currentReasoningId = undefined;\n }\n if (!state.currentTextId) {\n state.currentTextId = newId();\n parts.push({ type: 'text-start', id: state.currentTextId });\n }\n state.streamedAssistantText += update.delta;\n parts.push({\n type: 'text-delta',\n id: state.currentTextId,\n delta: update.delta,\n });\n return parts;\n }\n if (\n update.type === 'thinking_delta' &&\n typeof update.delta === 'string'\n ) {\n const parts: HarnessV1StreamPart[] = [];\n // Symmetric to the text branch: close any open text block before\n // starting a fresh reasoning block.\n if (state.currentTextId) {\n parts.push({ type: 'text-end', id: state.currentTextId });\n state.currentTextId = undefined;\n }\n if (!state.currentReasoningId) {\n state.currentReasoningId = newId();\n }\n if (!state.reasoningStarted) {\n state.reasoningStarted = true;\n parts.push({ type: 'reasoning-start', id: state.currentReasoningId });\n }\n parts.push({\n type: 'reasoning-delta',\n id: state.currentReasoningId,\n delta: update.delta,\n });\n return parts;\n }\n return [];\n }\n\n case 'message_end':\n case 'turn_end': {\n if (!state.promptStarted) return [];\n const parts: HarnessV1StreamPart[] = [];\n const fullText = extractAssistantText(event.message);\n if (\n state.currentTextId &&\n fullText.startsWith(state.streamedAssistantText) &&\n fullText.length > state.streamedAssistantText.length\n ) {\n const missing = fullText.slice(state.streamedAssistantText.length);\n state.streamedAssistantText = fullText;\n parts.push({\n type: 'text-delta',\n id: state.currentTextId,\n delta: missing,\n });\n }\n if (state.currentTextId) {\n parts.push({ type: 'text-end', id: state.currentTextId });\n state.currentTextId = undefined;\n }\n if (state.reasoningStarted && state.currentReasoningId) {\n parts.push({ type: 'reasoning-end', id: state.currentReasoningId });\n state.reasoningStarted = false;\n state.currentReasoningId = undefined;\n }\n if (event.type === 'message_end') {\n for (const toolCallId of extractPiToolCallIds(event.message)) {\n state.pendingStepToolCallIds.add(toolCallId);\n }\n } else {\n state.pendingStepToolCallIds.clear();\n parts.push(...finishStep(state));\n }\n return parts;\n }\n\n case 'tool_execution_start': {\n if (!event.toolCallId || !event.toolName) return [];\n const { wire, native } = resolveToolName(state, event.toolName);\n state.observedToolNames.set(event.toolCallId, wire);\n const isMcpTool =\n !state.hostToolNames.has(native) &&\n (native === 'mcp' || native.startsWith('mcp__'));\n const providerExecuted = state.builtinToolNames.has(native) || isMcpTool;\n if (isMcpTool) state.dynamicToolCallIds.add(event.toolCallId);\n const input = serializeToolOutput(event.args ?? event.input ?? {});\n return [\n {\n type: 'tool-call',\n toolCallId: event.toolCallId,\n toolName: wire,\n input,\n ...(wire !== native ? { nativeName: native } : {}),\n ...(providerExecuted ? { providerExecuted: true } : {}),\n ...(isMcpTool ? { dynamic: true } : {}),\n } as HarnessV1StreamPart,\n ];\n }\n\n case 'tool_execution_end':\n case 'tool_result': {\n if (!event.toolCallId) return [];\n const recordedName = state.observedToolNames.get(event.toolCallId);\n const nativeName = event.toolName;\n const wire =\n recordedName ??\n (nativeName ? resolveToolName(state, nativeName).wire : undefined);\n if (!wire) return [];\n const dynamic = state.dynamicToolCallIds.delete(event.toolCallId);\n /*\n * Prefer the exact value the host submitted for user-registered tools\n * (see `hostToolResults`). Built-in tools, whose results Pi produces and\n * reports as text, are not in the map and fall back to unwrapping the\n * event's text payload.\n */\n const result = state.hostToolResults.has(event.toolCallId)\n ? ((state.hostToolResults.get(event.toolCallId) ?? null) as Extract<\n HarnessV1StreamPart,\n { type: 'tool-result' }\n >['result'])\n : dynamic\n ? parseMcpToolResult(unwrapPiToolResult(event))\n : unwrapPiToolResult(event);\n state.hostToolResults.delete(event.toolCallId);\n state.pendingStepToolCallIds.delete(event.toolCallId);\n return [\n {\n type: 'tool-result',\n toolCallId: event.toolCallId,\n toolName: wire,\n result,\n ...(event.isError ? { isError: true } : {}),\n ...(dynamic ? { dynamic: true } : {}),\n } as HarnessV1StreamPart,\n ...finishStep(state),\n ];\n }\n\n case 'compaction_end': {\n /*\n * Pi performs the compaction itself; we observe its result. Skip aborted\n * or result-less compactions (nothing happened). A result with no summary\n * still represents a real compaction, so emit it with a placeholder\n * rather than dropping the event. `reason` is `'manual'` for an explicit\n * `session.compact()` call, `'threshold'`/`'overflow'` for Pi's automatic\n * compaction — both map to `'auto'` on the wire. Pi reports `tokensBefore`\n * but not `tokensAfter`.\n */\n if (event.aborted) return [];\n const result = event.result;\n if (!result || typeof result !== 'object') return [];\n const rawSummary = (result as { summary?: unknown }).summary;\n const summary =\n typeof rawSummary === 'string' ? rawSummary : '(no summary provided)';\n const tokensBefore = (result as { tokensBefore?: unknown }).tokensBefore;\n return [\n {\n type: 'compaction',\n trigger: event.reason === 'manual' ? 'manual' : 'auto',\n summary,\n ...(typeof tokensBefore === 'number' ? { tokensBefore } : {}),\n },\n ];\n }\n\n default:\n return [];\n }\n}\n","import {\n HarnessCapabilityUnsupportedError,\n type HarnessV1Prompt,\n type HarnessV1Skill,\n} from '@ai-sdk/harness';\n\nconst HARNESS_ID = 'pi';\n\n/**\n * Extract a single user text string from a `HarnessV1Prompt`. Pi's\n * `session.prompt(text)` accepts a string; multimodal user content\n * is not supported in this foundational version.\n */\nexport function extractUserText(prompt: HarnessV1Prompt): string {\n if (typeof prompt === 'string') {\n return prompt;\n }\n\n const { content } = prompt;\n if (typeof content === 'string') {\n return content;\n }\n\n const parts: string[] = [];\n for (const part of content) {\n if (part.type !== 'text') {\n throw new HarnessCapabilityUnsupportedError({\n message: `pi: only text user-message parts are supported; got '${part.type}'.`,\n harnessId: HARNESS_ID,\n });\n }\n parts.push(part.text);\n }\n return parts.join('\\n\\n');\n}\n\n/*\n * Frame session instructions and the user's text so the runtime treats the\n * instructions as system-provided operating guidance, not something the user\n * wrote. Without the wrapper the agent can echo the prepended text back as if\n * the user had asked for it, which is confusing since the user never typed it.\n * Applied only to the first user message of a fresh session.\n */\nexport function frameInstructions(\n instructions: string,\n userText: string,\n): string {\n return (\n '<session-instructions>\\n' +\n 'The block below is operating guidance from the system, not a message from the user — follow it, but do not mention it or attribute it to the user.\\n\\n' +\n `${instructions}\\n` +\n '</session-instructions>\\n\\n' +\n `<user-message>\\n${userText}\\n</user-message>`\n );\n}\n\n/** Serialize a tool output to the string Pi feeds back to the model. */\nexport function serializeToolOutput(output: unknown): string {\n if (typeof output === 'string') {\n return output;\n }\n const serialized = JSON.stringify(output);\n return serialized ?? 'null';\n}\n\nexport function getErrorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Validate that a name is safe to use as a filesystem path segment under\n * `.pi/skills/<name>/` or `.pi/agents/<name>.md`. Refuses anything that\n * could be interpreted as a path traversal or contains shell-sensitive\n * characters.\n */\nexport function safePiMetadataSegment(name: string, label: string): string {\n if (!/^[A-Za-z0-9._-]+$/.test(name) || name === '.' || name === '..') {\n throw new Error(`Invalid Pi ${label} name: ${name}`);\n }\n return name;\n}\n\n/** Frontmatter renderer for `.pi/skills/<name>/SKILL.md`. */\nexport function renderPiSkillFile(skill: HarnessV1Skill): string {\n return `---\\nname: ${skill.name}\\ndescription: ${skill.description}\\n---\\n\\n${skill.content}`;\n}\n","import { Type, type TSchema } from 'typebox';\n\n/**\n * Wrap a JSON Schema 7 fragment so Pi's `defineTool({ parameters })` accepts\n * it. Pi v0.77 uses TypeBox at the type level but treats `parameters` as\n * opaque schema metadata at runtime, so `Type.Unsafe(jsonSchema)` is\n * sufficient — no per-property structural conversion is needed.\n */\nexport function toolSpecToTypeBoxParameters(jsonSchema: unknown): TSchema {\n return Type.Unsafe(jsonSchema as object);\n}\n","/**\n * Pi VFS — global Node `fs` monkey-patch that redirects reads/writes against a\n * mount point (the session's sandbox working directory, e.g.\n * `/vercel/sandbox/<harnessId>-<sessionId>/...`) to a real backing directory on\n * the host. The mount point is a sandbox path that does not exist on the host,\n * so the redirect never shadows real host files.\n *\n * The mapping is process-global because Pi's upstream runtime reads and\n * writes through the shared `fs` module. Concurrent mounts are supported as\n * long as each instance uses a distinct mount point (each session's sandbox\n * working directory is unique).\n *\n * Multi-instance invariants:\n * - Multiple `PiWorkspaceVfs` instances may stay mounted concurrently.\n * - Path routing uses longest-prefix matching, so mount points must not\n * overlap.\n * - Extra `fs` patches stay installed while `mountedRoots.size > 0` and are\n * restored only after the final unmount.\n * - Mount and unmount remain synchronous, so Node's single-threaded execution\n * preserves patch/install ordering.\n *\n * Supported logical-path APIs:\n * - Sync: `existsSync`, `readFileSync`, `writeFileSync`, `mkdirSync`,\n * `readdirSync`, `renameSync`, `rmSync`, `openSync`, `statSync`,\n * `realpathSync` (+ `.native`).\n * - Callback: `mkdir`, `realpath`, `stat`, `rmdir`, `utimes`, `writeFile`.\n * - Promises: `fs.promises.mkdir`, `fs.promises.readFile`,\n * `fs.promises.writeFile`.\n *\n * Anything else is intentionally unsupported. If Pi starts using additional\n * `fs` APIs against logical roots, those call sites must be added here\n * deliberately with tests.\n */\n\nimport fs from 'node:fs';\nimport { syncBuiltinESMExports } from 'node:module';\nimport path from 'node:path';\n\ntype MountedRoot = {\n backingRoot: string;\n mountPoint: string;\n};\n\ntype WrappedRealpathSync = typeof fs.realpathSync & {\n native?: typeof fs.realpathSync.native;\n};\n\ntype Mutable<T> = {\n -readonly [K in keyof T]: T[K];\n};\n\nconst mountedRoots = new Map<string, MountedRoot>();\nconst mutableFs = fs as Mutable<typeof fs>;\nconst mutableFsPromises = fs.promises as Mutable<typeof fs.promises>;\n\nconst originalFsSyncMethods = {\n existsSync: fs.existsSync,\n mkdirSync: fs.mkdirSync,\n openSync: fs.openSync,\n readFileSync: fs.readFileSync,\n readdirSync: fs.readdirSync,\n realpathSync: fs.realpathSync,\n renameSync: fs.renameSync,\n rmSync: fs.rmSync,\n statSync: fs.statSync,\n writeFileSync: fs.writeFileSync,\n};\n\nconst originalFsCallbackMethods = {\n mkdir: fs.mkdir,\n realpath: fs.realpath,\n rmdir: fs.rmdir,\n stat: fs.stat,\n utimes: fs.utimes,\n writeFile: fs.writeFile,\n};\n\nconst originalFsPromises = {\n mkdir: fs.promises.mkdir.bind(fs.promises),\n readFile: fs.promises.readFile.bind(fs.promises),\n writeFile: fs.promises.writeFile.bind(fs.promises),\n};\n\nfunction isInsidePath(parent: string, candidate: string): boolean {\n const relative = path.relative(parent, candidate);\n return (\n relative === '' ||\n (!relative.startsWith('..') && !path.isAbsolute(relative))\n );\n}\n\nfunction resolveAbsolutePath(inputPath: string): string {\n return path.isAbsolute(inputPath)\n ? path.normalize(inputPath)\n : path.resolve(inputPath);\n}\n\nfunction findMountedRoot(inputPath: string): MountedRoot | undefined {\n const resolvedPath = resolveAbsolutePath(inputPath);\n let bestMatch: MountedRoot | undefined;\n\n for (const mountedRoot of mountedRoots.values()) {\n if (!isInsidePath(mountedRoot.mountPoint, resolvedPath)) {\n continue;\n }\n if (\n !bestMatch ||\n mountedRoot.mountPoint.length > bestMatch.mountPoint.length\n ) {\n bestMatch = mountedRoot;\n }\n }\n\n return bestMatch;\n}\n\nfunction mapToBackingPath(inputPath: string): string | null {\n const mountedRoot = findMountedRoot(inputPath);\n if (!mountedRoot) {\n return null;\n }\n\n const resolvedPath = resolveAbsolutePath(inputPath);\n const relativePath = path.relative(mountedRoot.mountPoint, resolvedPath);\n return relativePath\n ? path.join(mountedRoot.backingRoot, relativePath)\n : mountedRoot.backingRoot;\n}\n\nfunction mapRealpathResult(inputPath: string, result: string): string {\n const mountedRoot = findMountedRoot(inputPath);\n if (!mountedRoot) {\n return result;\n }\n\n let normalizedBackingRoot = path.resolve(mountedRoot.backingRoot);\n try {\n const realpath =\n originalFsSyncMethods.realpathSync.native ??\n originalFsSyncMethods.realpathSync;\n normalizedBackingRoot = path.resolve(realpath(mountedRoot.backingRoot));\n } catch {\n // Fall back to the configured backing root when canonicalization fails.\n }\n\n const normalizedResult = path.resolve(result);\n if (!isInsidePath(normalizedBackingRoot, normalizedResult)) {\n return result;\n }\n\n const relativePath = path.relative(normalizedBackingRoot, normalizedResult);\n return relativePath\n ? path.join(mountedRoot.mountPoint, relativePath)\n : mountedRoot.mountPoint;\n}\n\nfunction mapRenamePaths(\n sourcePath: string,\n destinationPath: string,\n): [string, string] | null {\n const sourceRoot = findMountedRoot(sourcePath);\n const destinationRoot = findMountedRoot(destinationPath);\n\n if (!sourceRoot && !destinationRoot) {\n return null;\n }\n\n if (\n !sourceRoot ||\n !destinationRoot ||\n sourceRoot.mountPoint !== destinationRoot.mountPoint\n ) {\n throw new Error(\n 'Pi logical VFS paths cannot rename across mount boundaries',\n );\n }\n\n return [\n mapToBackingPath(sourcePath) ?? sourcePath,\n mapToBackingPath(destinationPath) ?? destinationPath,\n ];\n}\n\nfunction wrapSinglePathSync<Fn extends (...args: never[]) => unknown>(\n original: Fn,\n options: {\n mapResult?: (inputPath: string, result: ReturnType<Fn>) => ReturnType<Fn>;\n } = {},\n): Fn {\n return ((...args: Parameters<Fn>) => {\n const [inputPath] = args;\n if (typeof inputPath === 'string') {\n const mappedPath = mapToBackingPath(inputPath);\n if (mappedPath) {\n const result = original(\n ...([mappedPath, ...args.slice(1)] as Parameters<Fn>),\n ) as ReturnType<Fn>;\n return options.mapResult\n ? options.mapResult(inputPath, result)\n : result;\n }\n }\n return original(...args);\n }) as Fn;\n}\n\nfunction wrapRenameSync<Fn extends (...args: never[]) => unknown>(\n original: Fn,\n): Fn {\n return ((...args: Parameters<Fn>) => {\n const [sourcePath, destinationPath] = args;\n if (typeof sourcePath === 'string' && typeof destinationPath === 'string') {\n const mappedPaths = mapRenamePaths(sourcePath, destinationPath);\n if (mappedPaths) {\n return original(\n ...([\n mappedPaths[0],\n mappedPaths[1],\n ...args.slice(2),\n ] as Parameters<Fn>),\n );\n }\n }\n return original(...args);\n }) as Fn;\n}\n\nfunction wrapSinglePathCallback<Fn extends (...args: never[]) => unknown>(\n original: Fn,\n options: {\n mapCallbackResult?: (inputPath: string, result: unknown) => unknown;\n } = {},\n): Fn {\n return ((...args: Parameters<Fn>) => {\n const [inputPath] = args;\n if (typeof inputPath === 'string') {\n const mappedPath = mapToBackingPath(inputPath);\n if (mappedPath) {\n const nextArgs = [mappedPath, ...args.slice(1)] as unknown[];\n const maybeCallback = nextArgs.at(-1);\n if (options.mapCallbackResult && typeof maybeCallback === 'function') {\n nextArgs[nextArgs.length - 1] = (\n error: NodeJS.ErrnoException | null,\n result: unknown,\n ...rest: unknown[]\n ) => {\n const mappedResult = error\n ? result\n : options.mapCallbackResult?.(inputPath, result);\n (maybeCallback as (...callbackArgs: unknown[]) => void)(\n error,\n mappedResult,\n ...rest,\n );\n };\n }\n return original(...(nextArgs as Parameters<Fn>));\n }\n }\n return original(...args);\n }) as Fn;\n}\n\nfunction wrapSinglePathPromise<\n Fn extends (...args: never[]) => Promise<unknown>,\n>(original: Fn): Fn {\n return (async (...args: Parameters<Fn>) => {\n const [inputPath] = args;\n if (typeof inputPath === 'string') {\n const mappedPath = mapToBackingPath(inputPath);\n if (mappedPath) {\n return await original(\n ...([mappedPath, ...args.slice(1)] as Parameters<Fn>),\n );\n }\n }\n return await original(...args);\n }) as Fn;\n}\n\nfunction createWrappedRealpathSync(): WrappedRealpathSync {\n const wrapped = wrapSinglePathSync(originalFsSyncMethods.realpathSync, {\n mapResult: (inputPath, result) =>\n typeof result === 'string'\n ? mapRealpathResult(inputPath, result)\n : result,\n }) as WrappedRealpathSync;\n\n if (originalFsSyncMethods.realpathSync.native) {\n wrapped.native = wrapSinglePathSync(\n originalFsSyncMethods.realpathSync.native,\n {\n mapResult: (inputPath, result) =>\n typeof result === 'string'\n ? mapRealpathResult(inputPath, result)\n : result,\n },\n ) as typeof fs.realpathSync.native;\n }\n\n return wrapped;\n}\n\nconst wrappedFsSyncMethods = {\n existsSync: wrapSinglePathSync(originalFsSyncMethods.existsSync),\n mkdirSync: wrapSinglePathSync(originalFsSyncMethods.mkdirSync),\n openSync: wrapSinglePathSync(originalFsSyncMethods.openSync),\n readFileSync: wrapSinglePathSync(originalFsSyncMethods.readFileSync),\n readdirSync: wrapSinglePathSync(originalFsSyncMethods.readdirSync),\n realpathSync: createWrappedRealpathSync(),\n renameSync: wrapRenameSync(originalFsSyncMethods.renameSync),\n rmSync: wrapSinglePathSync(originalFsSyncMethods.rmSync),\n statSync: wrapSinglePathSync(originalFsSyncMethods.statSync),\n writeFileSync: wrapSinglePathSync(originalFsSyncMethods.writeFileSync),\n};\n\nconst wrappedFsCallbackMethods = {\n mkdir: wrapSinglePathCallback(originalFsCallbackMethods.mkdir),\n realpath: wrapSinglePathCallback(originalFsCallbackMethods.realpath, {\n mapCallbackResult: (inputPath, result) =>\n typeof result === 'string'\n ? mapRealpathResult(inputPath, result)\n : result,\n }),\n rmdir: wrapSinglePathCallback(originalFsCallbackMethods.rmdir),\n stat: wrapSinglePathCallback(originalFsCallbackMethods.stat),\n utimes: wrapSinglePathCallback(originalFsCallbackMethods.utimes),\n writeFile: wrapSinglePathCallback(originalFsCallbackMethods.writeFile),\n};\n\nconst wrappedFsPromises = {\n mkdir: wrapSinglePathPromise(originalFsPromises.mkdir),\n readFile: wrapSinglePathPromise(originalFsPromises.readFile),\n writeFile: wrapSinglePathPromise(originalFsPromises.writeFile),\n};\n\nfunction areExtraFsPatchesInstalled(): boolean {\n return mutableFs.existsSync === wrappedFsSyncMethods.existsSync;\n}\n\nfunction installExtraFsPatches() {\n if (areExtraFsPatchesInstalled()) return;\n\n mutableFs.existsSync = wrappedFsSyncMethods.existsSync;\n mutableFs.mkdirSync = wrappedFsSyncMethods.mkdirSync;\n mutableFs.openSync = wrappedFsSyncMethods.openSync;\n mutableFs.readFileSync = wrappedFsSyncMethods.readFileSync;\n mutableFs.readdirSync = wrappedFsSyncMethods.readdirSync;\n mutableFs.realpathSync = wrappedFsSyncMethods.realpathSync;\n mutableFs.renameSync = wrappedFsSyncMethods.renameSync;\n mutableFs.rmSync = wrappedFsSyncMethods.rmSync;\n mutableFs.statSync = wrappedFsSyncMethods.statSync;\n mutableFs.writeFileSync = wrappedFsSyncMethods.writeFileSync;\n\n mutableFs.mkdir = wrappedFsCallbackMethods.mkdir;\n mutableFs.realpath = wrappedFsCallbackMethods.realpath;\n mutableFs.rmdir = wrappedFsCallbackMethods.rmdir;\n mutableFs.stat = wrappedFsCallbackMethods.stat;\n mutableFs.utimes = wrappedFsCallbackMethods.utimes;\n mutableFs.writeFile = wrappedFsCallbackMethods.writeFile;\n\n mutableFsPromises.mkdir = wrappedFsPromises.mkdir;\n mutableFsPromises.readFile = wrappedFsPromises.readFile;\n mutableFsPromises.writeFile = wrappedFsPromises.writeFile;\n\n syncBuiltinESMExports();\n}\n\nfunction restoreExtraFsPatches() {\n if (!areExtraFsPatchesInstalled()) return;\n\n mutableFs.existsSync = originalFsSyncMethods.existsSync;\n mutableFs.mkdirSync = originalFsSyncMethods.mkdirSync;\n mutableFs.openSync = originalFsSyncMethods.openSync;\n mutableFs.readFileSync = originalFsSyncMethods.readFileSync;\n mutableFs.readdirSync = originalFsSyncMethods.readdirSync;\n mutableFs.realpathSync = originalFsSyncMethods.realpathSync;\n mutableFs.renameSync = originalFsSyncMethods.renameSync;\n mutableFs.rmSync = originalFsSyncMethods.rmSync;\n mutableFs.statSync = originalFsSyncMethods.statSync;\n mutableFs.writeFileSync = originalFsSyncMethods.writeFileSync;\n\n mutableFs.mkdir = originalFsCallbackMethods.mkdir;\n mutableFs.realpath = originalFsCallbackMethods.realpath;\n mutableFs.rmdir = originalFsCallbackMethods.rmdir;\n mutableFs.stat = originalFsCallbackMethods.stat;\n mutableFs.utimes = originalFsCallbackMethods.utimes;\n mutableFs.writeFile = originalFsCallbackMethods.writeFile;\n\n mutableFsPromises.mkdir = originalFsPromises.mkdir;\n mutableFsPromises.readFile = originalFsPromises.readFile;\n mutableFsPromises.writeFile = originalFsPromises.writeFile;\n\n syncBuiltinESMExports();\n}\n\nexport class PiWorkspaceVfs {\n private backingRoot: string | null = null;\n private mountPoint: string | null = null;\n\n private disposeMount(): void {\n if (this.mountPoint) {\n mountedRoots.delete(this.mountPoint);\n }\n this.backingRoot = null;\n this.mountPoint = null;\n }\n\n mount(backingRoot: string, mountPoint: string): void {\n if (this.backingRoot === backingRoot && this.mountPoint === mountPoint) {\n return;\n }\n\n const resolvedBackingRoot = path.resolve(backingRoot);\n const resolvedMountPoint = path.resolve(mountPoint);\n if (this.mountPoint) {\n this.disposeMount();\n }\n\n mountedRoots.set(resolvedMountPoint, {\n backingRoot: resolvedBackingRoot,\n mountPoint: resolvedMountPoint,\n });\n installExtraFsPatches();\n\n this.backingRoot = resolvedBackingRoot;\n this.mountPoint = resolvedMountPoint;\n }\n\n unmount(): void {\n this.disposeMount();\n\n if (mountedRoots.size === 0) {\n restoreExtraFsPatches();\n }\n }\n}\n","import {\n mkdir,\n readFile,\n readdir,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport path from 'node:path';\nimport { shellQuote } from '@ai-sdk/harness/utils';\nimport type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';\n\n/*\n * Pi runs on the host with its working directory pointed at the local mirror,\n * but the only thing it reads from that directory is its own resource\n * configuration: the `.pi` and `.agents` directories (skills, prompts, themes,\n * extensions) and the root-level agent context files (`AGENTS.md`). The model\n * never reads workspace source through the host — file reads, directory\n * listings, and greps all run as tools against the sandbox. Mirroring the whole\n * sandbox workspace to the host would therefore copy files Pi never looks at,\n * one `readBinaryFile` round-trip per file. For a real project that has been\n * cloned and had its dependencies installed (hundreds of thousands of files\n * under `node_modules`) that makes session startup take hours. The mirror is\n * consequently scoped to exactly the paths Pi's resource loader consults.\n *\n * Within those config directories, symlinks are resolved and their targets\n * copied as real files. `.agents/skills` is frequently a symlink to a `skills`\n * directory living elsewhere in the workspace; a mirrored symlink would dangle\n * because its target falls outside the scoped mirror, so the linked content is\n * walked and copied verbatim instead.\n */\nconst PI_CONFIG_DIRS = ['.pi', '.agents'] as const;\nconst PI_CONTEXT_FILENAMES = ['AGENTS.md', 'AGENTS.MD'] as const;\n\nfunction normalizeRelativePath(inputPath: string): string {\n const normalized = inputPath.split(path.posix.sep).join(path.sep);\n const relative = path.normalize(normalized);\n if (\n relative === '' ||\n relative === '.' ||\n path.isAbsolute(relative) ||\n relative === '..' ||\n relative.startsWith(`..${path.sep}`)\n ) {\n throw new Error(\n `Sandbox workspace mirror received an invalid relative path: ${inputPath}`,\n );\n }\n return relative;\n}\n\nasync function readCommandOutput(\n sandbox: Experimental_SandboxSession,\n command: string,\n): Promise<string> {\n const result = await sandbox.run({ command });\n const output = result.stdout || result.stderr;\n if (result.exitCode != null && result.exitCode !== 0) {\n throw new Error(\n output || `Sandbox command failed with exit code ${result.exitCode}`,\n );\n }\n return output;\n}\n\nasync function listRemoteWorkspaceEntries(\n sandbox: Experimental_SandboxSession,\n sandboxWorkDir: string,\n): Promise<{ directories: string[]; files: string[] }> {\n const contextPredicate = PI_CONTEXT_FILENAMES.map(\n name => `-name ${shellQuote(name)}`,\n ).join(' -o ');\n\n // Enumerate only the `.pi`/`.agents` config subtrees plus the root-level\n // context files — never the rest of the workspace. `find -L` dereferences\n // symlinks so that linked targets (e.g. `.agents/skills` pointing elsewhere)\n // are walked and reported through the symlinked path; the resolved file/dir\n // types from `[ -d ]`/`[ -f ]` then tag each entry `d`/`f`, NUL-joined\n // exactly like a full-tree walk so the reconcile below is unchanged.\n const configFinds = PI_CONFIG_DIRS.map(\n dir =>\n ` if [ -d ./${dir} ]; then find -L ./${dir} \\\\( -type d -o -type f \\\\) -print0; fi;`,\n );\n const listCommand = [\n '{',\n ...configFinds,\n ` find . -maxdepth 1 -type f \\\\( ${contextPredicate} \\\\) -print0;`,\n '} |',\n \"while IFS= read -r -d '' entry; do\",\n ' rel=${entry#./}',\n ' if [ -d \"$entry\" ]; then',\n ` printf 'd\\\\t%s\\\\n' \"$rel\"`,\n ' elif [ -f \"$entry\" ]; then',\n ` printf 'f\\\\t%s\\\\n' \"$rel\"`,\n ' fi',\n 'done | LC_ALL=C sort',\n ].join('\\n');\n\n const output = await readCommandOutput(\n sandbox,\n [`cd ${shellQuote(sandboxWorkDir)}`, listCommand].join(' && '),\n );\n\n const directories: string[] = [];\n const files: string[] = [];\n\n for (const line of output.split('\\n').filter(Boolean)) {\n const [kind, rawPath] = line.split('\\t', 2);\n if (!rawPath) continue;\n\n const relativePath = normalizeRelativePath(rawPath);\n if (kind === 'd') directories.push(relativePath);\n else if (kind === 'f') files.push(relativePath);\n }\n\n return { directories, files };\n}\n\nasync function pathKind(\n target: string,\n): Promise<'file' | 'directory' | undefined> {\n try {\n const stats = await stat(target);\n if (stats.isDirectory()) return 'directory';\n if (stats.isFile()) return 'file';\n return undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function collectHostSubtree(\n rootDir: string,\n currentDir: string,\n directories: string[],\n files: string[],\n): Promise<void> {\n const entries = await readdir(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isSymbolicLink()) continue;\n const absolutePath = path.join(currentDir, entry.name);\n const relativePath = path.relative(rootDir, absolutePath);\n if (entry.isDirectory()) {\n directories.push(relativePath);\n await collectHostSubtree(rootDir, absolutePath, directories, files);\n } else if (entry.isFile()) {\n files.push(relativePath);\n }\n }\n}\n\n/**\n * Enumerate the locally-mirrored entries that fall within Pi's scope: the\n * `.pi`/`.agents` config subtrees and the root-level context files. Anything\n * else on the local side (it should not normally exist) is intentionally\n * ignored so the reconcile below neither copies nor deletes it.\n */\nasync function collectHostScopedEntries(\n rootDir: string,\n): Promise<{ directories: string[]; files: string[] }> {\n const directories: string[] = [];\n const files: string[] = [];\n\n for (const dir of PI_CONFIG_DIRS) {\n const configDir = path.join(rootDir, dir);\n if ((await pathKind(configDir)) === 'directory') {\n directories.push(dir);\n await collectHostSubtree(rootDir, configDir, directories, files);\n }\n }\n\n for (const name of PI_CONTEXT_FILENAMES) {\n if ((await pathKind(path.join(rootDir, name))) === 'file') {\n files.push(name);\n }\n }\n\n return { directories, files };\n}\n\nfunction buildRequiredDirectories(\n remoteDirectories: string[],\n remoteFiles: string[],\n): Set<string> {\n const directories = new Set<string>();\n for (const directory of remoteDirectories) {\n directories.add(normalizeRelativePath(directory));\n }\n for (const file of remoteFiles) {\n let current = path.dirname(normalizeRelativePath(file));\n while (current !== '.' && current !== path.sep && current.length > 0) {\n directories.add(current);\n current = path.dirname(current);\n }\n }\n return directories;\n}\n\nexport async function syncHostWorkspaceFromSandbox(args: {\n sandbox: Experimental_SandboxSession;\n sandboxWorkDir: string;\n hostWorkDir: string;\n}): Promise<void> {\n const { sandbox, sandboxWorkDir, hostWorkDir } = args;\n const remoteEntries = await listRemoteWorkspaceEntries(\n sandbox,\n sandboxWorkDir,\n );\n const hostEntries = await collectHostScopedEntries(hostWorkDir);\n const remoteFiles = new Set(remoteEntries.files);\n const requiredDirectories = buildRequiredDirectories(\n remoteEntries.directories,\n remoteEntries.files,\n );\n\n for (const relativePath of hostEntries.files) {\n if (!remoteFiles.has(relativePath)) {\n await rm(path.join(hostWorkDir, relativePath), { force: true });\n }\n }\n\n const removableDirectories = [...hostEntries.directories]\n .filter(p => !requiredDirectories.has(p))\n .sort((a, b) => b.length - a.length);\n for (const relativePath of removableDirectories) {\n await rm(path.join(hostWorkDir, relativePath), {\n recursive: true,\n force: true,\n });\n }\n\n for (const relativePath of [...requiredDirectories].sort(\n (a, b) => a.length - b.length,\n )) {\n await mkdir(path.join(hostWorkDir, relativePath), { recursive: true });\n }\n\n for (const relativePath of remoteEntries.files) {\n const remotePath = path.posix.join(\n sandboxWorkDir,\n relativePath.split(path.sep).join('/'),\n );\n const bytes = await sandbox.readBinaryFile({ path: remotePath });\n if (!bytes) {\n throw new Error(\n `Sandbox workspace file disappeared during mirror sync: ${remotePath}`,\n );\n }\n const content = Buffer.from(bytes);\n\n const hostPath = path.join(hostWorkDir, relativePath);\n let shouldWrite = true;\n try {\n const existing = await readFile(hostPath);\n shouldWrite = !existing.equals(content);\n } catch {\n shouldWrite = true;\n }\n\n if (shouldWrite) {\n await mkdir(path.dirname(hostPath), { recursive: true });\n await writeFile(hostPath, content);\n }\n }\n}\n\nexport async function writeHostWorkspaceFile(\n hostWorkDir: string,\n relativePath: string,\n content: Buffer,\n): Promise<void> {\n const normalizedPath = normalizeRelativePath(relativePath);\n const hostPath = path.join(hostWorkDir, normalizedPath);\n await mkdir(path.dirname(hostPath), { recursive: true });\n await writeFile(hostPath, content);\n}\n","import { createPi } from './pi-harness';\n\n/**\n * Default `pi` harness instance with no overrides — suitable for the common\n * case where Pi's defaults are fine. Equivalent to `createPi()`.\n */\nexport const pi = createPi();\n\nexport { createPi } from './pi-harness';\nexport { VERSION } from './version';\nexport type { PiHarnessSettings } from './pi-harness';\nexport type { PiAuthOptions } from './pi-auth';\n"],"mappings":"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","names":["z","mkdir","rm","path","Type","z","getAiGatewayAuthFromEnv","path","path","shellQuote","writeFile","path","path","isInsidePath","mkdir","readFile","writeFile","path","shellQuote","HARNESS_ID","path","mkdir","input","tool","rm","Type","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/pi-harness.ts","../src/pi-resume-state.ts","../src/pi-session.ts","../src/pi-auth.ts","../src/version.ts","../src/pi-events.ts","../src/pi-model-resolver.ts","../src/pi-paths.ts","../src/pi-remote-ops.ts","../src/pi-skills.ts","../src/pi-translate.ts","../src/pi-utils.ts","../src/pi-typebox-adapter.ts","../src/pi-workspace-vfs.ts","../src/pi-workspace-mirror.ts","../src/index.ts"],"sourcesContent":["import {\n commonTool,\n type HarnessV1,\n type HarnessV1BuiltinTool,\n} from '@ai-sdk/harness';\nimport { tool } from '@ai-sdk/provider-utils';\nimport type { ExtensionFactory } from '@earendil-works/pi-coding-agent';\nimport { z } from 'zod/v4';\nimport type { PiAuthOptions } from './pi-auth';\nimport { piResumeStateSchema } from './pi-resume-state';\nimport { createPiSession, type PiThinkingLevel } from './pi-session';\nimport { VERSION } from './version';\n\n/**\n * Value to use in User-Agent and `x-client-app` headers.\n */\nconst PI_CLIENT_APP = `ai-sdk/harness-pi/${VERSION}`;\n\n/**\n * Configuration knobs for `createPi`. Pi runs as an in-process Node library\n * (no bridge), so there's no `port` or `startupTimeoutMs` to set.\n */\nexport type PiHarnessSettings = {\n /** Where Pi sources API keys / gateway credentials from. */\n readonly auth?: PiAuthOptions;\n /**\n * Pi model id (or name). Leaving this unset falls back to the AI Gateway\n * default when `AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN` is set, and to\n * Pi's own resolution otherwise.\n */\n readonly model?: string;\n /**\n * Pi's extended-thinking budget level. Maps directly to the SDK's\n * `thinkingLevel` option on `createAgentSession`.\n */\n readonly thinkingLevel?: PiThinkingLevel;\n /**\n * Directory holding Pi's global agent config (auth.json, models.json,\n * settings.json). When omitted, a per-session temp dir is used. Pass the\n * user's agent dir (e.g. `~/.pi/agent/`) to reuse their CLI auth and\n * model settings.\n */\n readonly agentDir?: string;\n /**\n * MCP server definitions keyed by server name. Each definition uses the\n * underlying runtime's native MCP server configuration format.\n */\n readonly mcpServers?: Record<string, unknown>;\n /**\n * Trusted inline Pi extensions loaded for each harness session.\n *\n * Filesystem-discovered user and project extensions remain disabled.\n */\n readonly extensionFactories?: ReadonlyArray<ExtensionFactory>;\n};\n\nconst PI_BUILTIN_TOOLS = {\n read: commonTool('read', {\n nativeName: 'read',\n toolUseKind: 'readonly',\n description: 'Read file contents.',\n inputSchema: z.object({\n file_path: z.string(),\n }),\n }),\n write: commonTool('write', {\n nativeName: 'write',\n toolUseKind: 'edit',\n description: 'Overwrite or create a file.',\n inputSchema: z.object({\n file_path: z.string(),\n content: z.string(),\n }),\n }),\n edit: commonTool('edit', {\n nativeName: 'edit',\n toolUseKind: 'edit',\n description: 'Edit a file by exact string replacement.',\n inputSchema: z.object({\n file_path: z.string(),\n old_string: z.string(),\n new_string: z.string(),\n }),\n }),\n bash: commonTool('bash', {\n nativeName: 'bash',\n toolUseKind: 'bash',\n description: 'Execute a shell command in the sandbox.',\n inputSchema: z.object({\n command: z.string(),\n timeout: z.number().optional(),\n }),\n }),\n grep: commonTool('grep', {\n nativeName: 'grep',\n toolUseKind: 'readonly',\n description: 'Search file contents with regex.',\n inputSchema: z.object({\n pattern: z.string(),\n path: z.string().optional(),\n glob: z.string().optional(),\n ignoreCase: z.boolean().optional(),\n literal: z.boolean().optional(),\n context: z.number().optional(),\n limit: z.number().optional(),\n }),\n }),\n glob: commonTool('glob', {\n nativeName: 'find',\n toolUseKind: 'readonly',\n description: 'Find files matching a glob pattern.',\n inputSchema: z.object({\n pattern: z.string(),\n path: z.string().optional(),\n limit: z.number().optional(),\n }),\n }),\n ls: {\n ...tool({\n description: 'List directory entries.',\n inputSchema: z.object({\n path: z.string().optional(),\n limit: z.number().optional(),\n }),\n outputSchema: z.unknown(),\n }),\n nativeName: 'ls',\n toolUseKind: 'readonly',\n } as HarnessV1BuiltinTool,\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\nexport function createPi(\n settings: PiHarnessSettings = {},\n): HarnessV1<typeof PI_BUILTIN_TOOLS> {\n return {\n specificationVersion: 'harness-v1',\n harnessId: 'pi',\n builtinTools: PI_BUILTIN_TOOLS,\n supportsBuiltinToolApprovals: true,\n supportsBuiltinToolFiltering: true,\n lifecycleStateSchema: piResumeStateSchema,\n doStart: async startOpts => {\n const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;\n const resumeData = lifecycleState?.data as\n | { sessionFileName?: string }\n | undefined;\n\n return createPiSession({\n sessionId: startOpts.sessionId,\n sandboxSession: startOpts.sandboxSession,\n sessionWorkDir: startOpts.sessionWorkDir,\n skills: startOpts.skills ?? [],\n settings: {\n ...(settings.auth ? { auth: settings.auth } : {}),\n ...(settings.model ? { model: settings.model } : {}),\n ...(settings.thinkingLevel\n ? { thinkingLevel: settings.thinkingLevel }\n : {}),\n ...(settings.mcpServers ? { mcpServers: settings.mcpServers } : {}),\n ...(settings.extensionFactories\n ? { extensionFactories: settings.extensionFactories }\n : {}),\n },\n clientApp: PI_CLIENT_APP,\n isResume: lifecycleState != null,\n permissionMode: startOpts.permissionMode,\n builtinToolFiltering: startOpts.builtinToolFiltering,\n ...(resumeData?.sessionFileName\n ? { resumeSessionFileName: resumeData.sessionFileName }\n : {}),\n ...(startOpts.abortSignal\n ? { abortSignal: startOpts.abortSignal }\n : {}),\n ...(settings.agentDir ? { agentDir: settings.agentDir } : {}),\n });\n },\n };\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport { shellQuote } from '@ai-sdk/harness/utils';\nimport type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nconst PI_SESSION_FILE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*\\.jsonl?$/;\n\nexport function safePiSessionFileName(sessionFileName: string): string {\n if (!PI_SESSION_FILE_NAME_PATTERN.test(sessionFileName)) {\n throw new Error(`Invalid Pi session file name: ${sessionFileName}`);\n }\n return sessionFileName;\n}\n\nconst piSessionFileNameSchema = z\n .string()\n .refine(\n sessionFileName => PI_SESSION_FILE_NAME_PATTERN.test(sessionFileName),\n 'Pi sessionFileName must be a safe .jsonl or .json basename.',\n );\n\n/**\n * Schema for the adapter-specific portion of lifecycle state `data` produced\n * by Pi's resumable lifecycle methods. Carries the basename\n * (including extension) of the Pi session file. The actual session bytes live\n * in the sandbox under `${sessionWorkDir}/.pi-sessions/<sessionFileName>` so\n * they survive cross-process resume via the sandbox snapshot.\n */\nexport const piResumeStateSchema = z.looseObject({\n sessionFileName: piSessionFileNameSchema.optional(),\n});\n\nexport type PiResumeStateData = z.infer<typeof piResumeStateSchema>;\n\nconst PI_SESSIONS_DIR = '.pi-sessions';\n\nfunction resolveContainedHostPath(input: {\n readonly baseDir: string;\n readonly sessionFileName: string;\n}): string {\n const baseDir = path.resolve(input.baseDir);\n const filePath = path.resolve(\n baseDir,\n safePiSessionFileName(input.sessionFileName),\n );\n const relativePath = path.relative(baseDir, filePath);\n if (\n relativePath === '' ||\n relativePath.startsWith('..') ||\n path.isAbsolute(relativePath)\n ) {\n throw new Error(`Invalid Pi session file name: ${input.sessionFileName}`);\n }\n return filePath;\n}\n\nfunction resolveContainedSandboxPath(input: {\n readonly sessionWorkDir: string;\n readonly sessionFileName: string;\n}): string {\n const sessionDir = path.posix.resolve(input.sessionWorkDir, PI_SESSIONS_DIR);\n const filePath = path.posix.resolve(\n sessionDir,\n safePiSessionFileName(input.sessionFileName),\n );\n const relativePath = path.posix.relative(sessionDir, filePath);\n if (\n relativePath === '' ||\n relativePath.startsWith('..') ||\n path.posix.isAbsolute(relativePath)\n ) {\n throw new Error(`Invalid Pi session file name: ${input.sessionFileName}`);\n }\n return filePath;\n}\n\n/**\n * Copy the Pi session file from the host's local mirror to a stable location\n * inside the sandbox workspace. Called during resumable lifecycle methods so\n * the session survives a sandbox snapshot or a process handoff.\n */\nexport async function persistSessionFileToSandbox(args: {\n readonly sandbox: Experimental_SandboxSession;\n readonly sessionWorkDir: string;\n readonly hostSessionDir: string;\n readonly sessionFileName: string;\n readonly abortSignal?: AbortSignal;\n}): Promise<void> {\n const hostPath = resolveContainedHostPath({\n baseDir: args.hostSessionDir,\n sessionFileName: args.sessionFileName,\n });\n const content = await readFile(hostPath);\n const remotePath = resolveContainedSandboxPath({\n sessionWorkDir: args.sessionWorkDir,\n sessionFileName: args.sessionFileName,\n });\n // Ensure the parent dir exists in the sandbox before writing.\n await args.sandbox.run({\n command: `mkdir -p ${shellQuote(path.posix.dirname(remotePath))}`,\n ...(args.abortSignal ? { abortSignal: args.abortSignal } : {}),\n });\n await args.sandbox.writeBinaryFile({\n path: remotePath,\n content,\n ...(args.abortSignal ? { abortSignal: args.abortSignal } : {}),\n });\n}\n\n/**\n * Pull a previously persisted Pi session file from the sandbox into a fresh\n * local mirror dir. Called during `doStart` on the resume path before Pi is\n * initialised. Returns the absolute path of the local session file or\n * `undefined` if the sandbox copy is missing.\n */\nexport async function pullSessionFileFromSandbox(args: {\n readonly sandbox: Experimental_SandboxSession;\n readonly sessionWorkDir: string;\n readonly hostSessionDir: string;\n readonly sessionFileName: string;\n readonly abortSignal?: AbortSignal;\n}): Promise<string | undefined> {\n const remotePath = resolveContainedSandboxPath({\n sessionWorkDir: args.sessionWorkDir,\n sessionFileName: args.sessionFileName,\n });\n const bytes = await args.sandbox.readBinaryFile({\n path: remotePath,\n ...(args.abortSignal ? { abortSignal: args.abortSignal } : {}),\n });\n if (!bytes) return undefined;\n await mkdir(args.hostSessionDir, { recursive: true });\n const hostPath = resolveContainedHostPath({\n baseDir: args.hostSessionDir,\n sessionFileName: args.sessionFileName,\n });\n await writeFile(hostPath, bytes);\n return hostPath;\n}\n","import {\n createAgentSession,\n DefaultResourceLoader,\n defineTool,\n ModelRegistry,\n ModelRuntime,\n SessionManager,\n SettingsManager,\n type AgentSession,\n type AgentToolResult,\n type ExtensionFactory,\n type Skill,\n type ToolDefinition,\n} from '@earendil-works/pi-coding-agent';\nimport { mkdir, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport path from 'node:path';\nimport { Type } from 'typebox';\nimport {\n type HarnessV1BuiltinToolFiltering,\n type HarnessV1ContinueTurnOptions,\n type HarnessV1ContinueTurnState,\n type HarnessV1PromptControl,\n type HarnessV1PromptTurnOptions,\n type HarnessV1NetworkSandboxSession,\n type HarnessV1PermissionMode,\n type HarnessV1ResumeSessionState,\n type HarnessV1Session,\n type HarnessV1Skill,\n type HarnessV1StreamPart,\n type HarnessV1ToolSpec,\n} from '@ai-sdk/harness';\nimport { resolveSandboxHomeDir } from '@ai-sdk/harness/utils';\nimport {\n registerPiProviders,\n resolvePiEnv,\n type PiAuthOptions,\n} from './pi-auth';\nimport { getPiTerminalError, parseNativeEvent } from './pi-events';\nimport { createPiModelResolver } from './pi-model-resolver';\nimport { createPiPathMapper } from './pi-paths';\nimport { createPiRemoteOps, type PiRemoteOps } from './pi-remote-ops';\nimport { writePiSkills } from './pi-skills';\nimport {\n persistSessionFileToSandbox,\n pullSessionFileFromSandbox,\n safePiSessionFileName,\n} from './pi-resume-state';\nimport {\n createPiTranslatorState,\n finishPiApprovalStep,\n translatePiEvent,\n type PiTranslatorState,\n} from './pi-translate';\nimport { toolSpecToTypeBoxParameters } from './pi-typebox-adapter';\nimport {\n extractUserText,\n safePiMetadataSegment,\n serializeToolOutput,\n} from './pi-utils';\nimport { PiWorkspaceVfs } from './pi-workspace-vfs';\nimport { syncHostWorkspaceFromSandbox } from './pi-workspace-mirror';\n\nconst HARNESS_ID = 'pi';\n\n/*\n * pi-mcp-adapter publishes TypeScript source as its package entry point. A\n * non-literal specifier keeps the repository type-check focused on this\n * package's compatibility boundary instead of compiling dependency internals.\n */\nconst PI_MCP_ADAPTER_PACKAGE: string = 'pi-mcp-adapter';\n\ntype PiMcpAdapterModule = {\n createMcpAdapter(options: {\n config: {\n mcpServers: Record<string, unknown>;\n settings: {\n directTools: boolean;\n toolPrefix: string;\n disableProxyTool: boolean;\n };\n };\n }): ExtensionFactory;\n};\n\n/*\n * Pi runs in this Node process, not behind an attachable in-sandbox bridge.\n * During a tool approval pause the Pi turn is still alive and blocked on the\n * custom tool promise, so detach must park that live session for the next\n * same-process resume instead of stopping it and resolving the promise as an\n * error. Cross-process resume still falls back to the persisted session file.\n */\nconst parkedPiSessions = new Map<string, HarnessV1Session>();\n\n/**\n * Whether a discovered resource path belongs to a specific directory.\n */\nfunction isWithinDirectory(parent: string, child: string): boolean {\n const rel = path.relative(parent, child);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n}\n\n/**\n * Whether a discovered resource path belongs to the session workspace — either\n * the sandbox-side working directory the model sees (`sessionWorkDir`) or its\n * host-side mirror (`hostWorkDir`).\n */\nfunction isWithinWorkspace(\n candidate: string,\n sessionWorkDir: string,\n hostWorkDir: string,\n): boolean {\n return (\n isWithinDirectory(sessionWorkDir, candidate) ||\n isWithinDirectory(hostWorkDir, candidate)\n );\n}\n\nfunction createHarnessPiSkills({\n skills,\n sandboxSkillRootDir,\n}: {\n skills: ReadonlyArray<HarnessV1Skill>;\n sandboxSkillRootDir: string;\n}): Skill[] {\n return skills.map(skill => {\n const name = safePiMetadataSegment(skill.name, 'skill');\n const baseDir = path.posix.join(sandboxSkillRootDir, name);\n const filePath = path.posix.join(baseDir, 'SKILL.md');\n return {\n name: skill.name,\n description: skill.description,\n filePath,\n baseDir,\n sourceInfo: {\n path: filePath,\n source: 'harness',\n scope: 'temporary',\n origin: 'top-level',\n baseDir,\n },\n disableModelInvocation: false,\n };\n });\n}\n\nconst PI_NATIVE_BUILTIN_NAMES = [\n 'read',\n 'write',\n 'edit',\n 'bash',\n 'grep',\n 'find',\n 'ls',\n] as const;\n\nconst NATIVE_TO_COMMON: Readonly<Record<string, string>> = {\n find: 'glob',\n};\n\nconst PUBLIC_TO_NATIVE: Readonly<\n Record<string, (typeof PI_NATIVE_BUILTIN_NAMES)[number]>\n> = {\n read: 'read',\n write: 'write',\n edit: 'edit',\n bash: 'bash',\n grep: 'grep',\n glob: 'find',\n ls: 'ls',\n};\n\nconst PI_NATIVE_TOOL_KINDS: Readonly<\n Record<(typeof PI_NATIVE_BUILTIN_NAMES)[number], 'readonly' | 'edit' | 'bash'>\n> = {\n read: 'readonly',\n write: 'edit',\n edit: 'edit',\n bash: 'bash',\n grep: 'readonly',\n find: 'readonly',\n ls: 'readonly',\n};\n\nfunction resolveActivePiBuiltinNames(\n toolFiltering: HarnessV1BuiltinToolFiltering | undefined,\n): ReadonlyArray<(typeof PI_NATIVE_BUILTIN_NAMES)[number]> {\n if (toolFiltering == null) return PI_NATIVE_BUILTIN_NAMES;\n if (toolFiltering.mode === 'allow') {\n return toolFiltering.toolNames\n .map(name => PUBLIC_TO_NATIVE[name])\n .filter(\n (name): name is (typeof PI_NATIVE_BUILTIN_NAMES)[number] =>\n name != null,\n );\n }\n return PI_NATIVE_BUILTIN_NAMES.filter(\n native =>\n !toolFiltering.toolNames.includes(NATIVE_TO_COMMON[native] ?? native),\n );\n}\n\nexport type PiThinkingLevel =\n | 'off'\n | 'minimal'\n | 'low'\n | 'medium'\n | 'high'\n | 'xhigh';\n\nexport interface PiSessionSettings {\n readonly auth?: PiAuthOptions;\n readonly model?: string;\n readonly thinkingLevel?: PiThinkingLevel;\n readonly mcpServers?: Record<string, unknown>;\n readonly extensionFactories?: ReadonlyArray<ExtensionFactory>;\n}\n\nexport interface CreatePiSessionInput {\n readonly sessionId: string;\n readonly sandboxSession: HarnessV1NetworkSandboxSession;\n readonly sessionWorkDir: string;\n readonly skills: ReadonlyArray<HarnessV1Skill>;\n readonly settings: PiSessionSettings;\n readonly clientApp: string;\n readonly isResume: boolean;\n readonly permissionMode?: HarnessV1PermissionMode;\n readonly builtinToolFiltering?: HarnessV1BuiltinToolFiltering;\n readonly resumeSessionFileName?: string;\n readonly abortSignal?: AbortSignal;\n /**\n * Directory holding Pi's global agent config (auth.json, models.json,\n * settings.json). When omitted, a per-session temp dir is used (the\n * harness cannot reuse existing CLI logins). Pass the user's agent dir\n * (e.g. `~/.pi/agent/`) to reuse their CLI auth and model settings.\n */\n readonly agentDir?: string;\n}\n\ninterface PendingToolResult {\n resolve: (value: unknown) => void;\n}\n\ninterface PendingToolApproval {\n resolve: (value: { approved: boolean; reason?: string }) => void;\n}\n\ninterface ActivePiTurn {\n readonly token: object;\n readonly done: Promise<void>;\n}\n\nexport async function createPiSession(\n input: CreatePiSessionInput,\n): Promise<HarnessV1Session> {\n if (input.isResume) {\n const parkedSession = parkedPiSessions.get(input.sessionId);\n if (parkedSession) {\n parkedPiSessions.delete(input.sessionId);\n return {\n ...parkedSession,\n isResume: true,\n };\n }\n }\n\n // Host-side mirror layout under tmpdir. Replace path-separator characters\n // that would otherwise turn a session id like `2026-05-29T17:54:27` into a\n // sub-directory tree on disk.\n const safeSessionId = input.sessionId.replace(/[\\\\/: ]/g, '-');\n const hostRoot = path.join(tmpdir(), 'ai-sdk-harness', 'pi', safeSessionId);\n const hostWorkDir = path.join(hostRoot, 'workspace');\n const hostAgentDir = path.join(hostRoot, 'agent');\n const hostSessionDir = path.join(hostRoot, 'sessions');\n\n // Pi runs in this host process but must behave as though it lives in the\n // sandbox workspace: its working directory is the real `sessionWorkDir`\n // (where `setup()` clones and where the sandbox-backed tools operate), so the\n // paths Pi advertises to the model — most notably the \"Current working\n // directory\" line in its system prompt — resolve inside the sandbox. The\n // workspace VFS maps that sandbox path to the host-side mirror so Pi's own\n // `fs`-based resource loading (`.pi/`, `AGENTS.md`) still works on the host.\n // `sessionWorkDir` is a sandbox path (e.g. `/vercel/sandbox/...`) that does\n // not exist on the host, so it is a safe, collision-free VFS mount point.\n const sessionWorkDir = input.sessionWorkDir;\n\n await mkdir(hostWorkDir, { recursive: true });\n await mkdir(hostAgentDir, { recursive: true });\n await mkdir(hostSessionDir, { recursive: true });\n\n const sandbox = input.sandboxSession.restricted();\n const permissionMode = input.permissionMode ?? 'allow-all';\n let sandboxSkillRootDir: string | undefined;\n let harnessSkills: Skill[] = [];\n\n // Materialise harness-provided skills into sandbox HOME, not the workspace.\n if (input.skills.length > 0) {\n const sandboxHomeDir = await resolveSandboxHomeDir({\n sandbox,\n ...(input.abortSignal ? { abortSignal: input.abortSignal } : {}),\n });\n sandboxSkillRootDir = path.posix.join(sandboxHomeDir, '.agents', 'skills');\n harnessSkills = createHarnessPiSkills({\n skills: input.skills,\n sandboxSkillRootDir,\n });\n await writePiSkills({\n sandbox,\n sandboxHomeDir,\n skills: input.skills,\n ...(input.abortSignal ? { abortSignal: input.abortSignal } : {}),\n });\n }\n\n // On resume: pull the Pi session file out of the sandbox into the fresh\n // host mirror so SessionManager.open can read it.\n let resumeSessionFilePath: string | undefined;\n if (input.isResume && input.resumeSessionFileName) {\n const resumeSessionFileName = safePiSessionFileName(\n input.resumeSessionFileName,\n );\n resumeSessionFilePath = await pullSessionFileFromSandbox({\n sandbox,\n sessionWorkDir: input.sessionWorkDir,\n hostSessionDir,\n sessionFileName: resumeSessionFileName,\n ...(input.abortSignal ? { abortSignal: input.abortSignal } : {}),\n });\n }\n\n // Snapshot sandbox state into the host mirror BEFORE the VFS goes live so\n // Pi sees the workspace as soon as it boots.\n await syncHostWorkspaceFromSandbox({\n sandbox,\n sandboxWorkDir: input.sessionWorkDir,\n hostWorkDir,\n });\n\n // Mount only the workspace: the model's view of the workspace lives at\n // `sessionWorkDir` and is backed by `hostWorkDir`. The agent and session\n // directories stay on the real host filesystem (below) — they are host-only\n // Pi state (auth, model registry, session journal) that must never surface\n // in the sandbox or the workspace mirror.\n const workspaceVfs = new PiWorkspaceVfs();\n workspaceVfs.mount(hostWorkDir, sessionWorkDir);\n\n const paths = createPiPathMapper({\n hostWorkDir,\n sandboxWorkDir: sessionWorkDir,\n readableRoots: sandboxSkillRootDir\n ? [{ sandboxDir: sandboxSkillRootDir }]\n : [],\n });\n\n // Pi auth + model registry are global to this Pi session. These live on the\n // real host filesystem, never in the sandbox/workspace.\n // When `agentDir` is provided, use it instead so the harness can reuse\n // existing CLI logins and model/settings config.\n const agentDir = input.agentDir ?? hostAgentDir;\n const modelRuntime = await ModelRuntime.create({\n authPath: path.join(agentDir, 'auth.json'),\n modelsPath: path.join(agentDir, 'models.json'),\n allowModelNetwork: false,\n });\n const modelRegistry = new ModelRegistry(modelRuntime);\n const settingsManager =\n input.agentDir != null\n ? SettingsManager.create(hostWorkDir, agentDir)\n : SettingsManager.inMemory();\n\n // Run-scoped env (for the model resolver's gateway fallback heuristic).\n const resolverEnv = resolvePiEnv({\n options: input.settings.auth,\n env: process.env,\n });\n await registerPiProviders({\n options: input.settings.auth,\n resolvedEnv: resolverEnv,\n registries: {\n modelRegistry,\n modelRuntime,\n },\n clientApp: input.clientApp,\n });\n const resolveModel = createPiModelResolver({\n modelRegistry,\n env: resolverEnv,\n });\n // Resolve once: deterministic given the configured model. This is the Pi\n // `Model` object handed to `createAgentSession`.\n const resolvedModel = resolveModel(input.settings.model);\n const mcpServers = resolvePiMcpServers({\n mcpServers: input.settings.mcpServers,\n });\n const hasMcpServers = Object.keys(mcpServers).length > 0;\n\n let sessionInstructions: string | undefined;\n\n /*\n * Configured MCP servers are served by an inline Pi extension, so they share\n * the extension runtime with the caller-supplied factories: both are loaded\n * by the resource loader below and both are subject to the reload handling\n * that keeps the active runtime alive across resource-only reloads.\n */\n const extensionFactories: ExtensionFactory[] = [\n ...(input.settings.extensionFactories ?? []),\n ];\n if (hasMcpServers) {\n const { createMcpAdapter } = (await import(\n PI_MCP_ADAPTER_PACKAGE\n )) as PiMcpAdapterModule;\n extensionFactories.push(\n createMcpAdapter({\n config: {\n mcpServers,\n settings: {\n directTools: true,\n toolPrefix: 'mcp',\n disableProxyTool: true,\n },\n },\n }),\n );\n }\n const hasExtensionFactories = extensionFactories.length > 0;\n let preserveExtensionsResult = false;\n let currentExtensionsResult:\n | ReturnType<DefaultResourceLoader['getExtensions']>\n | undefined;\n\n const resourceLoader = new DefaultResourceLoader({\n cwd: sessionWorkDir,\n agentDir: hostAgentDir,\n settingsManager,\n appendSystemPromptOverride: () =>\n sessionInstructions ? [sessionInstructions] : [],\n extensionFactories,\n ...(hasExtensionFactories\n ? {\n // DefaultResourceLoader invokes inline factories on every reload.\n // Resource-only reloads retain the active extension runtime, while a\n // genuine Pi session rebuild is allowed to replace that runtime.\n extensionsOverride: extensions => {\n if (preserveExtensionsResult && currentExtensionsResult != null) {\n return currentExtensionsResult;\n }\n currentExtensionsResult = extensions;\n return extensions;\n },\n }\n : {}),\n // Pi runs in the host process, so its default resource discovery reaches\n // the host developer's personal config (`~/.pi/agent/*`, `~/.agents/*`).\n // The harness exposes only explicitly supplied inline extension factories;\n // disable filesystem extension discovery entirely to avoid loading and\n // executing a host developer's personal or project Pi extensions inside\n // the server process. Themes and prompt templates stay disabled. Skills\n // are kept but filtered to workspace project skills plus harness-provided\n // skills whose files live in sandbox HOME.\n noExtensions: true,\n noThemes: true,\n noPromptTemplates: true,\n skillsOverride: base => ({\n ...base,\n skills: [\n ...base.skills.filter(skill =>\n isWithinWorkspace(skill.filePath, sessionWorkDir, hostWorkDir),\n ),\n ...harnessSkills,\n ],\n }),\n });\n await resourceLoader.reload();\n\n async function reloadResourcesOnly(): Promise<void> {\n if (!hasExtensionFactories) {\n await resourceLoader.reload();\n return;\n }\n\n const factories = extensionFactories.splice(0);\n preserveExtensionsResult = true;\n try {\n await resourceLoader.reload();\n } finally {\n preserveExtensionsResult = false;\n extensionFactories.push(...factories);\n }\n }\n\n // Per-session mutable state we hold across prompts.\n let piSession: AgentSession | undefined;\n let unsubscribe: (() => void) | undefined;\n let lastToolsSignature: string | undefined;\n let sessionFileName: string | undefined;\n let stopped = false;\n /*\n * Set by `doSuspendTurn` before it aborts the in-flight host turn at a slice\n * boundary. The turn's catch settles silently when this is set, so the stream\n * closes cleanly (no spurious `error` chunk) — the next slice rerun-continues\n * from the persisted journal.\n */\n let suspending = false;\n const pendingToolResults = new Map<string, PendingToolResult>();\n const pendingToolApprovals = new Map<string, PendingToolApproval>();\n\n // Emit channel set at the start of every doPromptTurn and cleared on end.\n let currentEmit: ((part: HarnessV1StreamPart) => void) | undefined;\n let translatorState: PiTranslatorState | undefined;\n let activeTurn: ActivePiTurn | undefined;\n /*\n * Compaction parts produced while no turn is active. Pi's `compact()` aborts\n * the current turn before it summarizes, so a manually triggered compaction\n * (and any compaction that lands between turns) emits its `compaction_end`\n * after `currentEmit` has been cleared. Buffer those parts and flush them on\n * the next turn's stream so the observation is not lost. Auto-compaction that\n * runs mid-turn still emits inline via `currentEmit`.\n */\n const pendingCompactionParts: HarnessV1StreamPart[] = [];\n\n async function applySessionInstructions(\n instructions: string | undefined,\n ): Promise<void> {\n if (instructions === sessionInstructions) return;\n sessionInstructions = instructions;\n await reloadResourcesOnly();\n piSession?.setActiveToolsByName(piSession.getActiveToolNames());\n }\n\n const remoteOps = createPiRemoteOps({\n sandbox,\n paths,\n onFileChange: (event, relPath) => {\n currentEmit?.({ type: 'file-change', event, path: relPath });\n },\n });\n\n function settlePendingToolResults(reason: string): void {\n for (const pending of pendingToolResults.values()) {\n pending.resolve({ error: reason });\n }\n pendingToolResults.clear();\n }\n\n function settlePendingToolApprovals(reason: string): void {\n for (const pending of pendingToolApprovals.values()) {\n pending.resolve({ approved: false, reason });\n }\n pendingToolApprovals.clear();\n }\n\n async function persistSessionFile(): Promise<void> {\n if (!sessionFileName) return;\n await persistSessionFileToSandbox({\n sandbox,\n sessionWorkDir: input.sessionWorkDir,\n hostSessionDir,\n sessionFileName,\n });\n }\n\n function createPromptControl(input: {\n done: Promise<void>;\n abortSignal?: AbortSignal;\n }): HarnessV1PromptControl {\n const abortHandler = () => {\n piSession?.abort().catch(() => {});\n };\n if (input.abortSignal) {\n input.abortSignal.addEventListener('abort', abortHandler, {\n once: true,\n });\n void input.done.then(\n () => {\n input.abortSignal?.removeEventListener('abort', abortHandler);\n },\n () => {\n input.abortSignal?.removeEventListener('abort', abortHandler);\n },\n );\n }\n\n return {\n async submitToolResult(args) {\n const pending = pendingToolResults.get(args.toolCallId);\n if (!pending) return;\n pendingToolResults.delete(args.toolCallId);\n /*\n * Preserve the original output so the result projection can surface it\n * unchanged. The tool handler stringifies the output for the runtime\n * (so the model reads it), and Pi echoes that text back — without this\n * the consumer-facing result would be the serialized string instead of\n * the original object.\n */\n translatorState?.hostToolResults.set(args.toolCallId, args.output);\n pending.resolve(args.output);\n },\n async submitToolApproval(args) {\n const pending = pendingToolApprovals.get(args.approvalId);\n if (!pending) return;\n pendingToolApprovals.delete(args.approvalId);\n pending.resolve({\n approved: args.approved,\n reason: args.reason,\n });\n },\n async submitUserMessage(text) {\n await piSession?.steer(text);\n },\n done: input.done,\n };\n }\n\n async function requestBuiltinToolApproval(args: {\n toolCallId: string;\n nativeName: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n }): Promise<{ approved: boolean; reason?: string }> {\n if (\n !piBuiltinToolRequiresApproval({\n permissionMode,\n kind: PI_NATIVE_TOOL_KINDS[args.nativeName],\n })\n ) {\n return { approved: true };\n }\n currentEmit?.({\n type: 'tool-approval-request',\n approvalId: args.toolCallId,\n toolCallId: args.toolCallId,\n });\n if (translatorState) {\n for (const part of finishPiApprovalStep(\n translatorState,\n args.toolCallId,\n )) {\n currentEmit?.(part);\n }\n }\n return new Promise(resolve => {\n pendingToolApprovals.set(args.toolCallId, { resolve });\n });\n }\n\n function buildToolDefinitions(userTools: ReadonlyArray<HarnessV1ToolSpec>): {\n customTools: ToolDefinition[];\n builtinNames: string[];\n } {\n const builtinNames = resolveActivePiBuiltinNames(\n input.builtinToolFiltering,\n );\n const customTools: ToolDefinition[] = [\n ...builtinNames.map(native =>\n buildBuiltinToolDefinition({\n native,\n remoteOps,\n requestApproval: requestBuiltinToolApproval,\n }),\n ),\n ...userTools.map(spec =>\n buildUserToolDefinition(spec, pendingToolResults),\n ),\n ];\n return {\n customTools,\n builtinNames: [...builtinNames],\n };\n }\n\n async function disposePiSession(): Promise<void> {\n unsubscribe?.();\n unsubscribe = undefined;\n\n const session = piSession;\n piSession = undefined;\n if (!session) return;\n\n if (hasMcpServers) {\n await session.reload().catch(() => {});\n }\n session.dispose();\n }\n\n async function rebuildPiSession(\n userTools: ReadonlyArray<HarnessV1ToolSpec>,\n isFirstBuild: boolean,\n ): Promise<boolean> {\n let resourcesReloaded = false;\n if (piSession) {\n await disposePiSession();\n // Original adapter waits 25 ms here to let Pi's teardown microtasks\n // settle before the next createAgentSession. Port verbatim.\n // TODO(pi-0.77): verify the race still exists; original SDK had a\n // teardown microtask the host needed to wait on.\n await new Promise(resolve => setTimeout(resolve, 25));\n if (hasExtensionFactories) {\n // dispose() invalidates Pi's current extension runtime, so a replacement\n // AgentSession needs factories to create a fresh runtime before build.\n await resourceLoader.reload();\n resourcesReloaded = true;\n }\n }\n\n const { customTools, builtinNames } = buildToolDefinitions(userTools);\n const toolNames = customTools.map(t => t.name);\n\n // SessionManager: open the resumed file on the first build of a resumed\n // session; create fresh otherwise.\n const sessionManager =\n isFirstBuild && resumeSessionFilePath\n ? SessionManager.open(\n resumeSessionFilePath,\n hostSessionDir,\n sessionWorkDir,\n )\n : SessionManager.create(sessionWorkDir, hostSessionDir);\n\n const { session } = await createAgentSession({\n cwd: sessionWorkDir,\n agentDir: hostAgentDir,\n modelRuntime,\n sessionManager,\n settingsManager,\n resourceLoader,\n customTools,\n ...(hasMcpServers\n ? { noTools: 'builtin' as const }\n : { tools: toolNames }),\n ...(input.settings.thinkingLevel\n ? { thinkingLevel: input.settings.thinkingLevel }\n : {}),\n ...(resolvedModel ? { model: resolvedModel } : {}),\n });\n piSession = session;\n if (hasMcpServers) {\n await piSession.bindExtensions({ mode: 'print' });\n }\n\n // Pick up the actual session file path so doStop can persist it. Pi\n // 0.77 emits `.jsonl` files; older builds used `.json`. Persist the\n // basename verbatim — including the extension — so the resume path can\n // round-trip it without guessing the extension.\n const candidatePath = sessionManager.getSessionFile();\n if (candidatePath) {\n sessionFileName = safePiSessionFileName(path.basename(candidatePath));\n }\n\n translatorState = createPiTranslatorState({\n builtinToolNames: builtinNames,\n hostToolNames: userTools.map(tool => tool.name),\n nativeToCommon: NATIVE_TO_COMMON,\n });\n\n unsubscribe = piSession.subscribe(rawEvent => {\n if (!translatorState) return;\n const event = parseNativeEvent(rawEvent);\n if (!event) return;\n for (const part of translatePiEvent(event, translatorState)) {\n if (currentEmit) {\n currentEmit(part);\n } else if (part.type === 'compaction') {\n // No active turn: defer compaction observations to the next turn.\n pendingCompactionParts.push(part);\n }\n // Other event types outside a turn have no consumer and are dropped.\n }\n });\n return resourcesReloaded;\n }\n\n /*\n * Drive one turn against the Pi session and return the control surface.\n * Shared by `doPromptTurn` (a fresh user prompt) and `doContinueTurn` (an empty\n * prompt that asks Pi to continue its own thread after a rerun resume).\n */\n async function runTurn(turnOpts: {\n text: string;\n tools: ReadonlyArray<HarnessV1ToolSpec>;\n emit: (part: HarnessV1StreamPart) => void;\n abortSignal?: AbortSignal;\n }): Promise<HarnessV1PromptControl> {\n if (stopped) {\n throw new Error('Pi session has been stopped.');\n }\n\n const userTools = turnOpts.tools;\n const signature = JSON.stringify(userTools.map(t => t.name).sort());\n const needsRebuild = piSession == null || signature !== lastToolsSignature;\n let resourcesReloaded = false;\n if (needsRebuild) {\n resourcesReloaded = await rebuildPiSession(userTools, piSession == null);\n lastToolsSignature = signature;\n }\n\n if (!resourcesReloaded) {\n await reloadResourcesOnly();\n }\n await syncHostWorkspaceFromSandbox({\n sandbox,\n sandboxWorkDir: input.sessionWorkDir,\n hostWorkDir,\n });\n\n currentEmit = turnOpts.emit;\n // Fresh translator state for the new turn — keep the tool sets the\n // session was built with.\n translatorState = createPiTranslatorState({\n builtinToolNames: [...PI_NATIVE_BUILTIN_NAMES],\n hostToolNames: userTools.map(tool => tool.name),\n nativeToCommon: NATIVE_TO_COMMON,\n });\n\n turnOpts.emit({ type: 'stream-start' });\n\n const turnPromise = (async () => {\n let terminalError: string | undefined;\n const session = piSession!;\n\n // We subscribed in rebuild, but the translator may need to detect\n // terminal errors too — wrap a second listener that records them.\n const unsubErr = session.subscribe(raw => {\n const ev = parseNativeEvent(raw);\n if (!ev) return;\n const err = getPiTerminalError(ev);\n if (err && !terminalError) {\n terminalError = err;\n }\n });\n\n try {\n await session.prompt(turnOpts.text);\n\n if (terminalError) {\n /*\n * A `doSuspendTurn` aborts the in-flight turn on purpose. Pi surfaces\n * that abort as a *resolved* prompt with a recorded terminal error\n * (\"This operation was aborted\") rather than a thrown exception, so the\n * `catch` guard below never sees it. Swallow it here too — but only if\n * it's actually the abort: the stream then closes cleanly (no spurious\n * `error` chunk) and the next slice rerun-continues from the journal.\n * Any other terminal error mid-suspend is unanticipated and must\n * surface.\n */\n if (suspending && isAbortError(terminalError)) return;\n currentEmit?.({ type: 'error', error: new Error(terminalError) });\n return;\n }\n\n const stats = session.getSessionStats();\n const finishReason = {\n unified: 'stop' as const,\n raw: undefined,\n };\n const usage = {\n inputTokens: {\n total: stats.tokens.input,\n noCache: undefined,\n cacheRead: stats.tokens.cacheRead,\n cacheWrite: stats.tokens.cacheWrite,\n },\n outputTokens: {\n total: stats.tokens.output,\n text: undefined,\n reasoning: undefined,\n },\n };\n currentEmit?.({\n type: 'finish',\n finishReason,\n totalUsage: usage,\n });\n } catch (err) {\n // A `doSuspendTurn` aborts the in-flight turn on purpose — settle silently\n // so the stream closes cleanly without a spurious `error` chunk; the\n // next slice rerun-continues from the persisted journal.\n // Same rule as the resolved-with-terminalError path: only swallow the\n // abort our own suspend caused; surface anything unanticipated.\n if (suspending && isAbortError(err)) return;\n currentEmit?.({ type: 'error', error: err });\n } finally {\n unsubErr();\n }\n })();\n\n const activeTurnToken = {};\n const done = turnPromise.finally(() => {\n if (activeTurn?.token === activeTurnToken) {\n activeTurn = undefined;\n }\n currentEmit = undefined;\n });\n activeTurn = {\n token: activeTurnToken,\n done,\n };\n\n return createPromptControl({\n done,\n abortSignal: turnOpts.abortSignal,\n });\n }\n\n const doStop = async (): Promise<HarnessV1ResumeSessionState> => {\n if (stopped) {\n throw new Error('Pi session has been stopped.');\n }\n stopped = true;\n parkedPiSessions.delete(input.sessionId);\n settlePendingToolResults('Pi session stopped');\n settlePendingToolApprovals('Pi session stopped');\n\n // Persist the Pi session file into the sandbox so a future process\n // can pick it up after `provider.resumeSession({ sessionId })` reattaches.\n if (sessionFileName) {\n try {\n await persistSessionFile();\n } catch {\n // Best-effort: a missing session file means resume returns to a\n // fresh conversation rather than failing stop.\n }\n }\n\n await disposePiSession();\n workspaceVfs.unmount();\n await rm(hostRoot, { recursive: true, force: true });\n\n return {\n type: 'resume-session',\n harnessId: HARNESS_ID,\n specificationVersion: 'harness-v1',\n data: sessionFileName ? { sessionFileName } : {},\n };\n };\n\n const sessionImpl: HarnessV1Session = {\n sessionId: input.sessionId,\n isResume: input.isResume,\n // The model Pi actually resolves to (the configured id, or its default when\n // unset) — `gen_ai.request.model`.\n ...(resolvedModel?.id ? { modelId: resolvedModel.id } : {}),\n\n // Pi has no bridge to attach to and no on-disk event log to replay; its\n // only resume path is restoring the session file on a fresh/snapshotted\n // sandbox, i.e. `rerun`.\n\n doPromptTurn: async (\n promptOpts: HarnessV1PromptTurnOptions,\n ): Promise<HarnessV1PromptControl> => {\n await applySessionInstructions(promptOpts.instructions);\n\n return runTurn({\n text: extractUserText(promptOpts.prompt),\n tools: promptOpts.tools ?? [],\n emit: promptOpts.emit,\n abortSignal: promptOpts.abortSignal,\n });\n },\n\n doContinueTurn: async (\n continueOpts: HarnessV1ContinueTurnOptions,\n ): Promise<HarnessV1PromptControl> => {\n if (activeTurn != null) {\n currentEmit = continueOpts.emit;\n return createPromptControl({\n done: activeTurn.done,\n abortSignal: continueOpts.abortSignal,\n });\n }\n\n /*\n * Pi runs the model on the host, so there is no live turn in the sandbox\n * to attach to — the previous slice's turn died with its process.\n * Rerun-continue: re-drive the agent from the journal restored on resume.\n * An empty prompt asks Pi to continue its own thread. Lossy — any work in\n * flight at the slice boundary is recomputed because a host-resident\n * runtime cannot do a lossless attach.\n */\n await applySessionInstructions(continueOpts.instructions);\n return runTurn({\n text: '',\n tools: continueOpts.tools ?? [],\n emit: continueOpts.emit,\n abortSignal: continueOpts.abortSignal,\n });\n },\n\n doCompact: async (customInstructions?: string) => {\n if (stopped) {\n throw new Error('Pi session has been stopped.');\n }\n /*\n * Pi owns the compaction. We just request it; the resulting\n * `compaction_end` event is observed by the session subscription and\n * translated into a `compaction` stream part. The returned\n * `CompactionResult` is intentionally discarded here.\n */\n await piSession?.compact(customInstructions);\n },\n\n doDestroy: async () => {\n if (stopped) return;\n stopped = true;\n parkedPiSessions.delete(input.sessionId);\n settlePendingToolResults('Pi session stopped');\n settlePendingToolApprovals('Pi session stopped');\n await disposePiSession();\n workspaceVfs.unmount();\n await rm(hostRoot, { recursive: true, force: true });\n },\n\n doStop,\n\n doDetach: async (): Promise<HarnessV1ResumeSessionState> => {\n if (activeTurn != null || pendingToolResults.size > 0) {\n parkedPiSessions.set(input.sessionId, sessionImpl);\n if (sessionFileName) {\n try {\n await persistSessionFile();\n } catch {\n /*\n * The parked in-process session is the authoritative continuation\n * path while the live turn is waiting on host input. Persistence is\n * only a fallback for later non-live resumes.\n */\n }\n }\n return {\n type: 'resume-session',\n harnessId: HARNESS_ID,\n specificationVersion: 'harness-v1',\n data: sessionFileName ? { sessionFileName } : {},\n };\n }\n return doStop();\n },\n\n doSuspendTurn: async (): Promise<HarnessV1ContinueTurnState> => {\n if (stopped) {\n throw new Error('Pi session has been stopped.');\n }\n if (\n activeTurn != null &&\n (pendingToolResults.size > 0 || pendingToolApprovals.size > 0)\n ) {\n parkedPiSessions.set(input.sessionId, sessionImpl);\n if (sessionFileName) {\n try {\n await persistSessionFile();\n } catch {\n /*\n * While waiting on host input, the live parked session is the\n * authoritative same-process continuation path. The sandbox copy\n * remains a best-effort fallback for a later cold resume.\n */\n }\n }\n return {\n type: 'continue-turn',\n harnessId: HARNESS_ID,\n specificationVersion: 'harness-v1',\n data: sessionFileName ? { sessionFileName } : {},\n };\n }\n /*\n * Pi's model runs in this host process, which is about to be suspended at\n * the slice boundary — the in-flight turn cannot survive it. Abort it (the\n * turn settles silently via the `suspending` guard so the stream closes\n * cleanly), persist the journal into the sandbox, and tear down host-side\n * resources. The sandbox itself is left running; the next slice pulls the\n * journal after `provider.resumeSession({ sessionId })` and rerun-continues. The\n * tail in flight at the boundary is recomputed — Pi cannot freeze a live\n * turn the way a bridge adapter can.\n */\n suspending = true;\n await Promise.resolve(piSession?.abort()).catch(() => {});\n\n if (sessionFileName) {\n try {\n await persistSessionFile();\n } catch {\n // Best-effort: a missing/failed copy leaves the previously persisted\n // journal in place, so the next slice resumes from a slightly older\n // (still valid) state.\n }\n }\n\n stopped = true;\n parkedPiSessions.delete(input.sessionId);\n settlePendingToolResults('Pi session suspended');\n settlePendingToolApprovals('Pi session suspended');\n await disposePiSession();\n workspaceVfs.unmount();\n await rm(hostRoot, { recursive: true, force: true });\n\n return {\n type: 'continue-turn',\n harnessId: HARNESS_ID,\n specificationVersion: 'harness-v1',\n data: sessionFileName ? { sessionFileName } : {},\n };\n },\n };\n\n return sessionImpl;\n}\n\nfunction resolvePiMcpServers({\n mcpServers,\n}: {\n mcpServers: Record<string, unknown> | undefined;\n}): Record<string, unknown> {\n if (mcpServers == null) return {};\n for (const [name, value] of Object.entries(mcpServers)) {\n if (value == null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(\n `Pi MCP server ${JSON.stringify(name)} must be configured with an object value.`,\n );\n }\n }\n return mcpServers;\n}\n\n/**\n * Whether a terminal error (string from Pi's event stream, or a thrown error)\n * is an abort — the expected result of `doSuspendTurn` aborting the in-flight\n * turn. Only these are safe to swallow while `suspending`; any other error is\n * unanticipated and must surface as an `error` chunk.\n */\nfunction isAbortError(value: unknown): boolean {\n if (value == null) return false;\n if (\n typeof value === 'object' &&\n (value as { name?: unknown }).name === 'AbortError'\n ) {\n return true;\n }\n const text =\n typeof value === 'string'\n ? value\n : value instanceof Error\n ? value.message\n : String(value);\n return /\\baborted\\b|AbortError|operation was aborted/i.test(text);\n}\n\nfunction asPiToolResult(text: string): AgentToolResult<unknown> {\n return {\n content: [{ type: 'text', text }],\n details: undefined,\n };\n}\n\nasync function maybeDenyPiBuiltinTool(input: {\n toolCallId: string;\n nativeName: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n requestApproval: (args: {\n toolCallId: string;\n nativeName: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n }) => Promise<{ approved: boolean; reason?: string }>;\n}): Promise<AgentToolResult<unknown> | undefined> {\n const decision = await input.requestApproval({\n toolCallId: input.toolCallId,\n nativeName: input.nativeName,\n });\n if (decision.approved) return undefined;\n return asPiToolResult(\n serializeToolOutput({\n type: 'execution-denied',\n reason: decision.reason,\n }),\n );\n}\n\nfunction piBuiltinToolRequiresApproval(input: {\n permissionMode: HarnessV1PermissionMode;\n kind: 'readonly' | 'edit' | 'bash';\n}): boolean {\n if (input.permissionMode === 'allow-all') return false;\n if (input.permissionMode === 'allow-edits') return input.kind === 'bash';\n return input.kind === 'edit' || input.kind === 'bash';\n}\n\nfunction buildBuiltinToolDefinition(input: {\n native: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n remoteOps: PiRemoteOps;\n requestApproval: (args: {\n toolCallId: string;\n nativeName: (typeof PI_NATIVE_BUILTIN_NAMES)[number];\n }) => Promise<{ approved: boolean; reason?: string }>;\n}): ToolDefinition {\n switch (input.native) {\n case 'read':\n return defineTool({\n name: 'read',\n label: 'read',\n description: 'Read file contents.',\n parameters: Type.Object({ file_path: Type.String() }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'read',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const buf = await input.remoteOps.readBuffer(params.file_path);\n return asPiToolResult(buf.toString('utf8'));\n },\n });\n case 'write':\n return defineTool({\n name: 'write',\n label: 'write',\n description: 'Write content to a file.',\n parameters: Type.Object({\n file_path: Type.String(),\n content: Type.String(),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'write',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n await input.remoteOps.writeFile(params.file_path, params.content);\n return asPiToolResult(`Wrote ${params.file_path}`);\n },\n });\n case 'edit':\n return defineTool({\n name: 'edit',\n label: 'edit',\n description: 'Edit a file by exact-string replacement.',\n parameters: Type.Object({\n file_path: Type.String(),\n old_string: Type.String(),\n new_string: Type.String(),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'edit',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n await input.remoteOps.editFile(\n params.file_path,\n params.old_string,\n params.new_string,\n );\n return asPiToolResult(`Edited ${params.file_path}`);\n },\n });\n case 'bash':\n return defineTool({\n name: 'bash',\n label: 'bash',\n description: 'Execute a shell command.',\n parameters: Type.Object({\n command: Type.String(),\n timeout: Type.Optional(\n Type.Number({ description: 'Timeout in seconds.' }),\n ),\n }),\n async execute(toolCallId, params, signal) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'bash',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const chunks: Buffer[] = [];\n const result = await input.remoteOps.exec(params.command, '.', {\n onData(data) {\n chunks.push(data);\n },\n ...(signal ? { signal } : {}),\n ...(typeof params.timeout === 'number'\n ? { timeout: params.timeout }\n : {}),\n });\n const out = Buffer.concat(chunks).toString('utf8');\n const text = `${out}${\n result.exitCode != null ? `\\n\\n(exit ${result.exitCode})` : ''\n }`.trim();\n return asPiToolResult(text);\n },\n });\n case 'grep':\n return defineTool({\n name: 'grep',\n label: 'grep',\n description: 'Search file contents with regex.',\n parameters: Type.Object({\n pattern: Type.String(),\n path: Type.Optional(Type.String()),\n glob: Type.Optional(Type.String()),\n ignoreCase: Type.Optional(Type.Boolean()),\n literal: Type.Optional(Type.Boolean()),\n context: Type.Optional(Type.Number()),\n limit: Type.Optional(Type.Number()),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'grep',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const out = await input.remoteOps.grepFiles(params.pattern, params);\n return asPiToolResult(out);\n },\n });\n case 'find':\n return defineTool({\n name: 'find',\n label: 'find',\n description: 'Find files matching a glob pattern.',\n parameters: Type.Object({\n pattern: Type.String(),\n path: Type.Optional(Type.String()),\n limit: Type.Optional(Type.Number()),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'find',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const matches = await input.remoteOps.findFiles(\n params.pattern,\n params.path ?? '.',\n params.limit ?? 1_000,\n );\n return asPiToolResult(matches.join('\\n'));\n },\n });\n case 'ls':\n return defineTool({\n name: 'ls',\n label: 'ls',\n description: 'List directory entries.',\n parameters: Type.Object({\n path: Type.Optional(Type.String()),\n limit: Type.Optional(Type.Number()),\n }),\n async execute(toolCallId, params) {\n const denied = await maybeDenyPiBuiltinTool({\n toolCallId,\n nativeName: 'ls',\n requestApproval: input.requestApproval,\n });\n if (denied) return denied;\n const entries = await input.remoteOps.listDirectory(\n params.path ?? '.',\n params.limit ?? 500,\n );\n return asPiToolResult(entries.join('\\n'));\n },\n });\n }\n}\n\nfunction buildUserToolDefinition(\n spec: HarnessV1ToolSpec,\n pending: Map<string, PendingToolResult>,\n): ToolDefinition {\n const schema = spec.inputSchema ?? {\n type: 'object',\n properties: {},\n additionalProperties: true,\n };\n return defineTool({\n name: spec.name,\n label: spec.name,\n description: spec.description ?? `User-registered tool ${spec.name}`,\n parameters: toolSpecToTypeBoxParameters(schema),\n async execute(toolCallId) {\n return new Promise<unknown>(resolve => {\n pending.set(toolCallId, { resolve });\n }).then(output => asPiToolResult(serializeToolOutput(output)));\n },\n });\n}\n","import type {\n ModelRegistry,\n ModelRuntime,\n} from '@earendil-works/pi-coding-agent';\nimport { getAiGatewayAuthFromEnv } from '@ai-sdk/harness/utils';\nimport { VERSION } from './version';\n\ntype ProviderConfigInput = Parameters<ModelRegistry['registerProvider']>[1];\n\n/**\n * Pi auth options. Exactly one of `gateway` or `customEnv` is honoured\n * (precedence: explicit `customEnv`, then explicit `gateway`, then ambient\n * gateway from `process.env`). To use multiple providers, use `customEnv`\n * with the standard `<PREFIX>_API_KEY` / `<PREFIX>_BASE_URL` pattern.\n */\nexport type PiAuthOptions = {\n readonly gateway?: {\n readonly apiKey?: string;\n readonly baseUrl?: string;\n };\n /**\n * Resolved environment-variable pairs of the form `<PREFIX>_API_KEY` and\n * (optionally) `<PREFIX>_BASE_URL`. Special-cased prefixes:\n * - `AI_GATEWAY` → registers `vercel-ai-gateway`\n * - `OPENAI` → registers `openai`\n * - `ANTHROPIC` → registers `anthropic` (`ANTHROPIC_AUTH_TOKEN` adds a\n * bearer auth header)\n * Any other `<PREFIX>_API_KEY` with a matching `<PREFIX>_BASE_URL` is\n * registered as the lowercased, dash-separated prefix.\n */\n readonly customEnv?: Record<string, string>;\n};\n\nconst DEFAULT_GATEWAY_BASE_URL = 'https://ai-gateway.vercel.sh';\nconst DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';\nconst DEFAULT_ANTHROPIC_BASE_URL = 'https://api.anthropic.com';\nconst HARNESS_CLIENT_APP = `ai-sdk/harness-pi/${VERSION}`;\n\nfunction createGatewayProviderConfig({\n apiKey,\n baseUrl,\n clientApp,\n}: {\n apiKey: string;\n baseUrl: string;\n clientApp: string;\n}): ProviderConfigInput {\n return {\n apiKey,\n baseUrl,\n authHeader: true,\n headers: {\n 'User-Agent': clientApp,\n 'x-client-app': clientApp,\n },\n };\n}\n\ntype PiRegistries = {\n modelRegistry: ModelRegistry;\n modelRuntime: ModelRuntime;\n};\n\nasync function register({\n registries,\n provider,\n apiKey,\n config,\n}: {\n registries: PiRegistries;\n provider: string;\n apiKey: string;\n config: ProviderConfigInput;\n}): Promise<void> {\n registries.modelRegistry.registerProvider(provider, config);\n await registries.modelRuntime.setRuntimeApiKey(provider, apiKey);\n}\n\nfunction hasConfiguredValue(value: unknown): boolean {\n if (value == null) return false;\n if (typeof value === 'string') return value.length > 0;\n if (typeof value !== 'object') return true;\n return Object.values(value).some(hasConfiguredValue);\n}\n\nexport function resolvePiEnv({\n options,\n env,\n}: {\n options: PiAuthOptions | undefined;\n env: NodeJS.ProcessEnv;\n}): Record<string, string> {\n const customEnvConfigured = hasConfiguredValue(options?.customEnv);\n if (customEnvConfigured) {\n return resolveCustomEnv({ customEnv: options!.customEnv ?? {} });\n }\n\n const gatewayConfigured = hasConfiguredValue(options?.gateway);\n const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env });\n if (gatewayConfigured) {\n const apiKey = options!.gateway?.apiKey ?? gatewayAuthFromEnv.apiKey;\n const baseUrl = options!.gateway?.baseUrl ?? gatewayAuthFromEnv.baseUrl;\n if (apiKey) {\n return { AI_GATEWAY_API_KEY: apiKey, AI_GATEWAY_BASE_URL: baseUrl };\n }\n return {};\n }\n\n // Ambient gateway fallback.\n if (gatewayAuthFromEnv.apiKey) {\n return {\n AI_GATEWAY_API_KEY: gatewayAuthFromEnv.apiKey,\n AI_GATEWAY_BASE_URL: gatewayAuthFromEnv.baseUrl,\n };\n }\n\n return {};\n}\n\nexport async function registerPiProviders({\n options,\n resolvedEnv,\n registries,\n clientApp = HARNESS_CLIENT_APP,\n}: {\n options: PiAuthOptions | undefined;\n resolvedEnv: Record<string, string>;\n registries: PiRegistries;\n clientApp?: string;\n}): Promise<void> {\n if (hasConfiguredValue(options?.customEnv)) {\n await registerCustomProviders({\n customEnv: options!.customEnv ?? {},\n registries,\n clientApp,\n });\n return;\n }\n\n const apiKey = resolvedEnv.AI_GATEWAY_API_KEY;\n const baseUrl = resolvedEnv.AI_GATEWAY_BASE_URL;\n if (!apiKey || !baseUrl) return;\n\n await register({\n registries,\n provider: 'vercel-ai-gateway',\n apiKey,\n config: createGatewayProviderConfig({ apiKey, baseUrl, clientApp }),\n });\n}\n\nfunction resolveCustomEnv({\n customEnv,\n}: {\n customEnv: Record<string, string>;\n}): Record<string, string> {\n const apiKey = customEnv.AI_GATEWAY_API_KEY;\n if (!apiKey) return {};\n\n return {\n AI_GATEWAY_API_KEY: apiKey,\n AI_GATEWAY_BASE_URL:\n customEnv.AI_GATEWAY_BASE_URL ?? DEFAULT_GATEWAY_BASE_URL,\n };\n}\n\nasync function registerCustomProviders({\n customEnv,\n registries,\n clientApp,\n}: {\n customEnv: Record<string, string>;\n registries: PiRegistries;\n clientApp: string;\n}): Promise<void> {\n const gatewayKey = customEnv.AI_GATEWAY_API_KEY;\n if (gatewayKey) {\n const baseUrl = customEnv.AI_GATEWAY_BASE_URL ?? DEFAULT_GATEWAY_BASE_URL;\n await register({\n registries,\n provider: 'vercel-ai-gateway',\n apiKey: gatewayKey,\n config: createGatewayProviderConfig({\n apiKey: gatewayKey,\n baseUrl,\n clientApp,\n }),\n });\n }\n\n if (customEnv.OPENAI_API_KEY) {\n const baseUrl = customEnv.OPENAI_BASE_URL ?? DEFAULT_OPENAI_BASE_URL;\n await register({\n registries,\n provider: 'openai',\n apiKey: customEnv.OPENAI_API_KEY,\n config: {\n apiKey: customEnv.OPENAI_API_KEY,\n baseUrl,\n authHeader: true,\n },\n });\n }\n\n if (customEnv.ANTHROPIC_API_KEY) {\n const baseUrl = customEnv.ANTHROPIC_BASE_URL ?? DEFAULT_ANTHROPIC_BASE_URL;\n await register({\n registries,\n provider: 'anthropic',\n apiKey: customEnv.ANTHROPIC_API_KEY,\n config: {\n apiKey: customEnv.ANTHROPIC_API_KEY,\n baseUrl,\n ...(customEnv.ANTHROPIC_AUTH_TOKEN\n ? {\n headers: {\n authorization: `Bearer ${customEnv.ANTHROPIC_AUTH_TOKEN}`,\n },\n }\n : {}),\n },\n });\n }\n\n for (const [name, apiKey] of Object.entries(customEnv)) {\n if (!name.endsWith('_API_KEY') || !apiKey) {\n continue;\n }\n const prefix = name.slice(0, -'_API_KEY'.length);\n if (\n prefix === 'AI_GATEWAY' ||\n prefix === 'OPENAI' ||\n prefix === 'ANTHROPIC'\n ) {\n continue;\n }\n const provider = prefix.toLowerCase().replace(/_/g, '-');\n const baseUrl = customEnv[`${prefix}_BASE_URL`];\n if (!baseUrl) {\n continue;\n }\n await register({\n registries,\n provider,\n apiKey,\n config: {\n apiKey,\n baseUrl,\n authHeader: true,\n },\n });\n }\n}\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n","import { z } from 'zod/v4';\n\n/**\n * Pi `session.subscribe` emits a discriminated union of events. The exact\n * shape evolves with Pi versions; we accept loose objects and extract only\n * the fields we recognise. The `type` field is required and stringly-typed\n * because Pi may add new types we want to ignore.\n */\nexport const piSessionEventSchema = z.looseObject({\n type: z.string(),\n assistantMessageEvent: z\n .looseObject({\n type: z.string().optional(),\n delta: z.string().optional(),\n })\n .optional(),\n toolCallId: z.string().optional(),\n toolName: z.string().optional(),\n args: z.unknown().optional(),\n input: z.unknown().optional(),\n result: z.unknown().optional(),\n content: z.unknown().optional(),\n isError: z.boolean().optional(),\n // Compaction events (`compaction_start` / `compaction_end`). `result` (a\n // `CompactionResult`) rides the shared `result` field above; `reason`\n // distinguishes manual vs automatic (threshold/overflow) compaction.\n reason: z.string().optional(),\n aborted: z.boolean().optional(),\n error: z\n .union([\n z.string(),\n z.looseObject({\n errorMessage: z.string().optional(),\n stopReason: z.string().optional(),\n }),\n ])\n .optional(),\n message: z\n .looseObject({\n role: z.string().optional(),\n content: z.unknown().optional(),\n stopReason: z.string().optional(),\n errorMessage: z.string().optional(),\n })\n .optional(),\n});\n\nexport type PiSessionEvent = z.infer<typeof piSessionEventSchema>;\n\n/**\n * Decode an unknown raw event into a `PiSessionEvent` if it looks like one.\n * Returns `undefined` if it doesn't parse so the caller can skip it.\n */\nexport function parseNativeEvent(raw: unknown): PiSessionEvent | undefined {\n const parsed = piSessionEventSchema.safeParse(raw);\n return parsed.success ? parsed.data : undefined;\n}\n\n/**\n * Detect whether a Pi event signals a terminal error for the current turn.\n * Returns the error message if so. Mirrors the original adapter's\n * `getPiTerminalError`.\n */\nexport function getPiTerminalError(event: PiSessionEvent): string | undefined {\n const isTerminalStopReason = (value: string | undefined) =>\n value === 'error' || value === 'aborted';\n\n if (typeof event.error === 'string' && event.error.trim()) {\n return event.error.trim();\n }\n\n if (event.error && typeof event.error === 'object') {\n const errorMessage = event.error.errorMessage?.trim();\n if (errorMessage) {\n return errorMessage;\n }\n const stopReason = event.error.stopReason?.trim();\n if (isTerminalStopReason(stopReason)) {\n return stopReason;\n }\n }\n\n const messageError = event.message?.errorMessage?.trim();\n if (messageError) {\n return messageError;\n }\n\n const messageStopReason = event.message?.stopReason?.trim();\n if (isTerminalStopReason(messageStopReason)) {\n return messageStopReason;\n }\n\n if (\n event.isError &&\n typeof event.content === 'string' &&\n event.content.trim()\n ) {\n return event.content.trim();\n }\n\n return undefined;\n}\n\n/** Pull the assistant text from a `turn_end` / `message_end` event payload. */\nexport function extractAssistantText(\n message: PiSessionEvent['message'],\n): string {\n if (!message || message.role !== 'assistant') {\n return '';\n }\n\n if (typeof message.content === 'string') {\n return message.content;\n }\n\n if (!Array.isArray(message.content)) {\n return '';\n }\n\n return message.content\n .flatMap(part => {\n if (!part || typeof part !== 'object') {\n return [];\n }\n const contentPart = part as Record<string, unknown>;\n return contentPart.type === 'text' && typeof contentPart.text === 'string'\n ? [contentPart.text]\n : [];\n })\n .join('');\n}\n","import type { ModelRegistry } from '@earendil-works/pi-coding-agent';\nimport { getAiGatewayAuthFromEnv } from '@ai-sdk/harness/utils';\n\ntype PiModel = ReturnType<ModelRegistry['getAll']>[number];\n\n/**\n * Default model id used when no `model` is configured AND gateway credentials\n * are available in the environment. Looked up from Pi's own model registry —\n * the entry must exist under the `vercel-ai-gateway` provider in\n * `@earendil-works/pi-ai`'s catalog.\n */\nexport const DEFAULT_PI_GATEWAY_MODEL_ID = 'anthropic/claude-sonnet-4.6';\n\n/*\n * A `\"<provider>/<id>\"` reference normally resolves under that provider, not\n * any entry whose flat `id` happens to equal the whole string. Routing proxies\n * (`vercel-ai-gateway`, `openrouter`) can carry another provider's id verbatim\n * as their own flat `id` (e.g. `id: \"xai/grok-4.3\"`), so this tier normally\n * wins over flat matching. An authenticated literal-id match remains usable\n * when the scoped provider is unauthenticated, matching Pi's own resolver.\n * Gateway preference stays first because gateway credentials explicitly opt\n * the harness into routing matching models through the gateway.\n */\nconst findScopedMatch = (\n effectiveId: string,\n models: PiModel[],\n): PiModel | undefined => {\n const slashIndex = effectiveId.indexOf('/');\n if (slashIndex === -1) return undefined;\n\n const prefix = effectiveId.slice(0, slashIndex);\n const bareId = effectiveId.slice(slashIndex + 1);\n return models.find(\n m => m.provider === prefix && (m.id === bareId || m.name === bareId),\n );\n};\n\nexport function createPiModelResolver({\n modelRegistry,\n env = process.env,\n}: {\n modelRegistry: ModelRegistry;\n env?: NodeJS.ProcessEnv;\n}) {\n let cachedModels: PiModel[] | undefined;\n\n const loadModels = (): PiModel[] => {\n if (cachedModels) {\n return cachedModels;\n }\n try {\n cachedModels = modelRegistry.getAll();\n } catch {\n cachedModels = [];\n }\n return cachedModels;\n };\n\n return (modelId: string | undefined): PiModel | undefined => {\n const useGateway = Boolean(getAiGatewayAuthFromEnv({ env }).apiKey);\n const effectiveId =\n modelId ?? (useGateway ? DEFAULT_PI_GATEWAY_MODEL_ID : undefined);\n if (!effectiveId) return undefined;\n\n const models = loadModels();\n const matches = (m: PiModel) =>\n m.id === effectiveId || m.name === effectiveId;\n\n // When gateway creds are present, prefer the gateway-routed entry for the\n // given id. Pi's catalog lists the same model id under multiple providers\n // (e.g. `anthropic/claude-sonnet-4.6` exists under both `openrouter` and\n // `vercel-ai-gateway`); without this preference Pi would dispatch through\n // a provider we didn't register, which fails with \"No API key found\".\n const gatewayMatch = useGateway\n ? models.find(m => m.provider === 'vercel-ai-gateway' && matches(m))\n : undefined;\n if (gatewayMatch) return gatewayMatch;\n\n const scopedMatch = findScopedMatch(effectiveId, models);\n if (scopedMatch && !modelRegistry.hasConfiguredAuth(scopedMatch)) {\n const authenticatedFlatMatches = models.filter(\n m => m.id === effectiveId && modelRegistry.hasConfiguredAuth(m),\n );\n if (authenticatedFlatMatches.length === 1) {\n return authenticatedFlatMatches[0];\n }\n }\n\n return scopedMatch ?? models.find(matches);\n };\n}\n","import { realpathSync } from 'node:fs';\nimport path from 'node:path';\n\nexport interface PiPathMapper {\n /** The host-side mirror directory Pi reads/writes through the workspace VFS. */\n readonly hostWorkDir: string;\n /** The sandbox-side working directory where tools actually operate. */\n readonly sandboxWorkDir: string;\n /**\n * Translate a path the host sees (relative to `hostWorkDir`, or absolute\n * inside it, or already a sandbox path) to the canonical sandbox path. Throws\n * if the path would escape the workspace.\n */\n toSandboxPath(inputPath: string): string;\n /**\n * Translate a path for read-only tools. In addition to the workspace, this\n * allows explicitly configured sandbox roots such as `$HOME/.agents/skills`.\n */\n toReadableSandboxPath(inputPath: string): string;\n /** Verify that a sandbox-side path is still inside `sandboxWorkDir`. */\n assertSandboxPath(inputPath: string): string;\n /**\n * Verify that a sandbox-side path is inside `sandboxWorkDir` or an\n * explicitly configured readable root.\n */\n assertReadableSandboxPath(inputPath: string): string;\n /** Translate any path to its POSIX-relative form under `sandboxWorkDir`. */\n toRelativePath(inputPath: string): string;\n}\n\nexport interface PiReadablePathRoot {\n readonly sandboxDir: string;\n}\n\nexport interface CreatePiPathMapperOptions {\n readonly hostWorkDir: string;\n readonly sandboxWorkDir: string;\n readonly readableRoots?: ReadonlyArray<PiReadablePathRoot>;\n}\n\nfunction isInsidePath(parent: string, candidate: string): boolean {\n const relative = path.relative(parent, candidate);\n return (\n relative === '' ||\n (!relative.startsWith('..') && !path.isAbsolute(relative))\n );\n}\n\nfunction isInsidePosixPath(parent: string, candidate: string): boolean {\n const relative = path.posix.relative(parent, candidate);\n return (\n relative === '' ||\n (!relative.startsWith('..') && !path.posix.isAbsolute(relative))\n );\n}\n\nfunction canonicalizeForContainment(inputPath: string): string {\n try {\n return realpathSync.native(inputPath);\n } catch {\n const parent = path.dirname(inputPath);\n if (parent === inputPath) {\n return inputPath;\n }\n return path.join(\n canonicalizeForContainment(parent),\n path.basename(inputPath),\n );\n }\n}\n\nexport function createPiPathMapper(\n options: CreatePiPathMapperOptions,\n): PiPathMapper {\n const normalizedHost = path.resolve(options.hostWorkDir);\n const normalizedSandbox = path.posix.normalize(options.sandboxWorkDir);\n const canonicalHost = canonicalizeForContainment(normalizedHost);\n const readableRoots =\n options.readableRoots?.map(root => ({\n sandboxDir: path.posix.normalize(root.sandboxDir),\n })) ?? [];\n\n const assertWorkspaceSandboxPath = (inputPath: string): string => {\n const normalizedInput = path.posix.normalize(inputPath);\n if (!isInsidePosixPath(normalizedSandbox, normalizedInput)) {\n throw new Error(`Pi path escapes the workspace: ${inputPath}`);\n }\n return normalizedInput;\n };\n\n const assertReadableSandboxPath = (inputPath: string): string => {\n const normalizedInput = path.posix.normalize(inputPath);\n if (\n !isInsidePosixPath(normalizedSandbox, normalizedInput) &&\n !readableRoots.some(root =>\n isInsidePosixPath(root.sandboxDir, normalizedInput),\n )\n ) {\n throw new Error(`Pi path escapes the readable roots: ${inputPath}`);\n }\n return normalizedInput;\n };\n\n const toWorkspaceSandboxPath = (inputPath: string): string => {\n if (path.posix.isAbsolute(inputPath)) {\n const normalizedInput = path.posix.normalize(inputPath);\n try {\n return assertWorkspaceSandboxPath(normalizedInput);\n } catch {\n // Absolute host paths are handled below.\n }\n }\n\n const resolvedHost = path.isAbsolute(inputPath)\n ? path.resolve(inputPath)\n : path.resolve(normalizedHost, inputPath);\n const canonicalResolvedHost = canonicalizeForContainment(resolvedHost);\n if (\n !isInsidePath(normalizedHost, resolvedHost) ||\n !isInsidePath(canonicalHost, canonicalResolvedHost)\n ) {\n throw new Error(`Pi path escapes the workspace: ${inputPath}`);\n }\n\n const relative = path\n .relative(normalizedHost, resolvedHost)\n .split(path.sep)\n .join('/');\n return relative\n ? path.posix.join(normalizedSandbox, relative)\n : normalizedSandbox;\n };\n\n return {\n hostWorkDir: normalizedHost,\n sandboxWorkDir: normalizedSandbox,\n toSandboxPath(inputPath: string) {\n return toWorkspaceSandboxPath(inputPath);\n },\n toReadableSandboxPath(inputPath: string) {\n if (path.posix.isAbsolute(inputPath)) {\n const normalizedInput = path.posix.normalize(inputPath);\n try {\n return assertReadableSandboxPath(normalizedInput);\n } catch {\n // Absolute host paths are handled by workspace mapping below.\n }\n }\n\n return toWorkspaceSandboxPath(inputPath);\n },\n assertSandboxPath(inputPath: string) {\n return assertWorkspaceSandboxPath(inputPath);\n },\n assertReadableSandboxPath(inputPath: string) {\n return assertReadableSandboxPath(inputPath);\n },\n toRelativePath(inputPath: string) {\n const sandboxPath = path.posix.isAbsolute(inputPath)\n ? path.posix.normalize(inputPath)\n : path.posix.join(\n normalizedSandbox,\n inputPath.split(path.sep).join('/'),\n );\n const relative = path.posix.relative(normalizedSandbox, sandboxPath);\n return relative || '.';\n },\n };\n}\n","import path from 'node:path';\nimport { shellQuote } from '@ai-sdk/harness/utils';\nimport type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';\nimport type { PiPathMapper } from './pi-paths';\n\nexport type PiRemoteFileChangeKind = 'create' | 'modify';\n\nexport interface PiRemoteOpsOptions {\n readonly sandbox: Experimental_SandboxSession;\n readonly paths: PiPathMapper;\n readonly env?: Record<string, string>;\n readonly onFileChange?: (\n event: PiRemoteFileChangeKind,\n relativePath: string,\n content: Buffer,\n ) => void;\n}\n\nexport interface PiRemoteOps {\n readonly paths: PiPathMapper;\n readBuffer(inputPath: string): Promise<Buffer>;\n writeFile(inputPath: string, content: string): Promise<void>;\n editFile(\n inputPath: string,\n oldText: string,\n newText: string,\n ): Promise<string>;\n listDirectory(inputPath?: string, limit?: number): Promise<string[]>;\n findFiles(\n pattern: string,\n inputPath?: string,\n limit?: number,\n ): Promise<string[]>;\n grepFiles(\n pattern: string,\n input: {\n path?: string;\n glob?: string;\n ignoreCase?: boolean;\n literal?: boolean;\n context?: number;\n limit?: number;\n },\n ): Promise<string>;\n access(inputPath: string): Promise<void>;\n exec(\n command: string,\n cwd: string,\n input: {\n onData: (data: Buffer) => void;\n signal?: AbortSignal;\n timeout?: number;\n },\n ): Promise<{ exitCode: number | null }>;\n}\n\ninterface RunShellInput {\n cwd?: string;\n signal?: AbortSignal;\n onData?: (data: Buffer) => void;\n}\n\ninterface RunShellResult {\n exitCode: number | null;\n output: Buffer;\n}\n\nfunction lastOutputLine(output: Buffer): string | undefined {\n return output.toString('utf8').trim().split('\\n').filter(Boolean).at(-1);\n}\n\nexport function createPiRemoteOps(options: PiRemoteOpsOptions): PiRemoteOps {\n const runShell = async (\n command: string,\n input: RunShellInput = {},\n ): Promise<RunShellResult> => {\n // `sandbox.run({ command })` already wraps in `bash -c`; we pass the\n // shell snippet directly. shellQuote is still used inside `command`\n // for path/value interpolation by the callers.\n const result = await options.sandbox.run({\n command,\n ...(input.cwd\n ? { workingDirectory: options.paths.toSandboxPath(input.cwd) }\n : {}),\n ...(options.env ? { env: options.env } : {}),\n ...(input.signal ? { abortSignal: input.signal } : {}),\n });\n\n const combined = `${result.stdout}${result.stderr}`;\n const output = Buffer.from(combined, 'utf8');\n if (output.length > 0) {\n input.onData?.(output);\n }\n\n return {\n exitCode: result.exitCode,\n output,\n };\n };\n\n const resolveExistingSandboxPath = async (\n remotePath: string,\n inputPath: string,\n ): Promise<string> => {\n const result = await runShell(\n [\n `target=${shellQuote(remotePath)}`,\n `if [ ! -e \"$target\" ]; then echo \"__PI_REALPATH_NOT_FOUND__\"; exit 2; fi`,\n `resolved=$(realpath \"$target\" 2>/dev/null) || { echo \"__PI_REALPATH_FAILED__\"; exit 3; }`,\n `printf '%s\\\\n' \"$resolved\"`,\n ].join('; '),\n );\n\n const output = result.output.toString('utf8');\n if (output.includes('__PI_REALPATH_NOT_FOUND__')) {\n throw new Error(`Path not found: ${inputPath}`);\n }\n if (output.includes('__PI_REALPATH_FAILED__') || result.exitCode !== 0) {\n throw new Error(`Unable to resolve path: ${inputPath}`);\n }\n\n const resolvedPath = lastOutputLine(result.output);\n if (!resolvedPath) {\n throw new Error(`Unable to resolve path: ${inputPath}`);\n }\n return resolvedPath;\n };\n\n const resolveReadableSandboxPath = async (\n remotePath: string,\n inputPath: string,\n ): Promise<string> =>\n options.paths.assertReadableSandboxPath(\n await resolveExistingSandboxPath(remotePath, inputPath),\n );\n\n const resolveWritableSandboxPath = async (\n remotePath: string,\n inputPath: string,\n ): Promise<string> => {\n const result = await runShell(\n [\n `target=${shellQuote(remotePath)}`,\n `if [ -e \"$target\" ] || [ -L \"$target\" ]; then resolved=$(realpath \"$target\" 2>/dev/null) || { echo \"__PI_REALPATH_FAILED__\"; exit 3; }; printf '%s\\\\n' \"$resolved\"; exit 0; fi`,\n `dir=$(dirname \"$target\")`,\n `base=$(basename \"$target\")`,\n `missing=\"$base\"`,\n `while [ ! -e \"$dir\" ] && [ ! -L \"$dir\" ]; do parent=$(dirname \"$dir\"); if [ \"$parent\" = \"$dir\" ]; then echo \"__PI_REALPATH_NOT_FOUND__\"; exit 2; fi; missing=\"$(basename \"$dir\")/$missing\"; dir=\"$parent\"; done`,\n `resolved_dir=$(realpath \"$dir\" 2>/dev/null) || { echo \"__PI_REALPATH_FAILED__\"; exit 3; }`,\n `printf '%s/%s\\\\n' \"$resolved_dir\" \"$missing\"`,\n ].join('; '),\n );\n\n const output = result.output.toString('utf8');\n if (\n output.includes('__PI_REALPATH_NOT_FOUND__') ||\n output.includes('__PI_REALPATH_FAILED__') ||\n result.exitCode !== 0\n ) {\n throw new Error(`Unable to resolve path: ${inputPath}`);\n }\n\n const resolvedPath = lastOutputLine(result.output);\n if (!resolvedPath) {\n throw new Error(`Unable to resolve path: ${inputPath}`);\n }\n return options.paths.assertSandboxPath(resolvedPath);\n };\n\n const readBuffer = async (inputPath: string): Promise<Buffer> => {\n const remotePath = options.paths.toReadableSandboxPath(inputPath);\n const resolvedPath = await resolveReadableSandboxPath(\n remotePath,\n inputPath,\n );\n const bytes = await options.sandbox.readBinaryFile({\n path: resolvedPath,\n });\n if (!bytes) {\n throw new Error(`Path not found: ${inputPath}`);\n }\n return Buffer.from(bytes);\n };\n\n const writeFile = async (\n inputPath: string,\n content: string,\n ): Promise<void> => {\n const remotePath = options.paths.toSandboxPath(inputPath);\n const resolvedPath = await resolveWritableSandboxPath(\n remotePath,\n inputPath,\n );\n const previous = await options.sandbox.readBinaryFile({\n path: resolvedPath,\n });\n await runShell(`mkdir -p ${shellQuote(path.posix.dirname(resolvedPath))}`);\n await options.sandbox.writeTextFile({ path: resolvedPath, content });\n options.onFileChange?.(\n previous ? 'modify' : 'create',\n options.paths.toRelativePath(resolvedPath),\n Buffer.from(content, 'utf8'),\n );\n };\n\n const editFile = async (\n inputPath: string,\n oldText: string,\n newText: string,\n ): Promise<string> => {\n const current = (await readBuffer(inputPath)).toString('utf8');\n const index = current.indexOf(oldText);\n if (index === -1) {\n throw new Error(`Text to replace was not found in ${inputPath}`);\n }\n const updated = `${current.slice(0, index)}${newText}${current.slice(\n index + oldText.length,\n )}`;\n await writeFile(inputPath, updated);\n return updated;\n };\n\n const listDirectory = async (\n inputPath: string = '.',\n limit: number = 500,\n ): Promise<string[]> => {\n const remotePath = options.paths.toReadableSandboxPath(inputPath);\n const resolvedPath = await resolveReadableSandboxPath(\n remotePath,\n inputPath,\n );\n const result = await runShell(\n [\n `if [ ! -e ${shellQuote(resolvedPath)} ]; then echo \"__PI_LS_NOT_FOUND__\"; exit 2; fi`,\n `if [ ! -d ${shellQuote(resolvedPath)} ]; then echo \"__PI_LS_NOT_DIR__\"; exit 3; fi`,\n `cd ${shellQuote(resolvedPath)}`,\n 'ls -1Ap',\n ].join('; '),\n );\n\n const output = result.output.toString('utf8').trim();\n if (output.includes('__PI_LS_NOT_FOUND__')) {\n throw new Error(`Path not found: ${inputPath}`);\n }\n if (output.includes('__PI_LS_NOT_DIR__')) {\n throw new Error(`Not a directory: ${inputPath}`);\n }\n\n return output\n .split('\\n')\n .filter(Boolean)\n .map(line => line.replace(/[*=@|]$/, ''))\n .sort((left, right) =>\n left.toLowerCase().localeCompare(right.toLowerCase()),\n )\n .slice(0, limit);\n };\n\n const findFiles = async (\n pattern: string,\n inputPath: string = '.',\n limit: number = 1_000,\n ): Promise<string[]> => {\n const remotePath = options.paths.toReadableSandboxPath(inputPath);\n const resolvedPath = await resolveReadableSandboxPath(\n remotePath,\n inputPath,\n );\n const result = await runShell(\n [\n `if [ ! -e ${shellQuote(resolvedPath)} ]; then echo \"__PI_FIND_NOT_FOUND__\"; exit 2; fi`,\n `if [ -d ${shellQuote(resolvedPath)} ]; then find ${shellQuote(resolvedPath)} -type f -print; else printf '%s\\\\n' ${shellQuote(resolvedPath)}; fi`,\n ].join('; '),\n );\n\n const output = result.output.toString('utf8').trim();\n if (output.includes('__PI_FIND_NOT_FOUND__')) {\n throw new Error(`Path not found: ${inputPath}`);\n }\n\n const searchRoot = resolvedPath;\n return output\n .split('\\n')\n .filter(Boolean)\n .map(absolutePath => {\n if (absolutePath === searchRoot) {\n return path.posix.basename(absolutePath);\n }\n return path.posix.relative(searchRoot, absolutePath);\n })\n .filter(\n candidate =>\n candidate.length > 0 && path.matchesGlob(candidate, pattern),\n )\n .sort((left, right) =>\n left.toLowerCase().localeCompare(right.toLowerCase()),\n )\n .slice(0, limit);\n };\n\n const grepFiles = async (\n pattern: string,\n input: {\n path?: string;\n glob?: string;\n ignoreCase?: boolean;\n literal?: boolean;\n context?: number;\n limit?: number;\n },\n ): Promise<string> => {\n const remotePath = options.paths.toReadableSandboxPath(input.path ?? '.');\n const resolvedPath = await resolveReadableSandboxPath(\n remotePath,\n input.path ?? '.',\n );\n const relativeTarget = options.paths.toRelativePath(resolvedPath);\n const targetPath =\n relativeTarget.startsWith('../') || path.posix.isAbsolute(relativeTarget)\n ? resolvedPath\n : relativeTarget;\n const flags = [\n '-R',\n '-n',\n '--binary-files=without-match',\n ...(input.ignoreCase ? ['-i'] : []),\n ...(input.literal ? ['-F'] : []),\n ...(typeof input.context === 'number' && input.context > 0\n ? ['-C', String(input.context)]\n : []),\n ...(input.glob ? ['--include', input.glob] : []),\n ];\n const limit = Math.max(1, input.limit ?? 100);\n const result = await runShell(\n [\n `if [ ! -e ${shellQuote(resolvedPath)} ]; then echo \"__PI_GREP_NOT_FOUND__\"; exit 2; fi`,\n `cd ${shellQuote(options.paths.sandboxWorkDir)}`,\n `grep ${flags.map(shellQuote).join(' ')} -- ${shellQuote(pattern)} ${shellQuote(targetPath)} 2>/dev/null | head -n ${limit}`,\n ].join('; '),\n );\n\n const output = result.output.toString('utf8').trim();\n if (output.includes('__PI_GREP_NOT_FOUND__')) {\n throw new Error(`Path not found: ${input.path ?? '.'}`);\n }\n\n return output || 'No matches found';\n };\n\n return {\n paths: options.paths,\n readBuffer,\n writeFile,\n editFile,\n listDirectory,\n findFiles,\n grepFiles,\n async access(inputPath: string) {\n await readBuffer(inputPath);\n },\n async exec(command, cwd, input): Promise<{ exitCode: number | null }> {\n const controller = new AbortController();\n // `input.timeout` is expressed in seconds (Pi's `bash` tool contract),\n // so convert to milliseconds for `setTimeout`.\n const timeoutId =\n typeof input.timeout === 'number' && input.timeout > 0\n ? setTimeout(() => controller.abort(), input.timeout * 1000)\n : undefined;\n\n const forwardedSignal = input.signal;\n const onAbort = () => controller.abort();\n forwardedSignal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const result = await runShell(command, {\n cwd,\n signal: controller.signal,\n onData: input.onData,\n });\n return { exitCode: result.exitCode };\n } finally {\n forwardedSignal?.removeEventListener('abort', onAbort);\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n },\n };\n}\n","import path from 'node:path';\nimport type { HarnessV1Skill } from '@ai-sdk/harness';\nimport { writeSkills } from '@ai-sdk/harness/utils';\nimport type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';\n\n/**\n * Materialize Pi skills as files under\n * `$HOME/.agents/skills/<name>/SKILL.md` inside the sandbox.\n */\nexport async function writePiSkills(args: {\n readonly sandbox: Experimental_SandboxSession;\n readonly sandboxHomeDir: string;\n readonly skills: ReadonlyArray<HarnessV1Skill>;\n readonly abortSignal?: AbortSignal;\n}): Promise<void> {\n await writeSkills({\n sandbox: args.sandbox,\n rootDir: path.posix.join(args.sandboxHomeDir, '.agents', 'skills'),\n skills: args.skills,\n abortSignal: args.abortSignal,\n invalidSkillNameMessage: ({ name }) => `Invalid Pi skill name: ${name}`,\n invalidSkillFilePathMessage: ({ skillName, filePath }) =>\n `Invalid Pi skill file path for ${skillName}: ${filePath}`,\n });\n}\n","import { randomBytes } from 'node:crypto';\nimport type { HarnessV1StreamPart } from '@ai-sdk/harness';\nimport { secureJsonParse } from '@ai-sdk/provider-utils';\nimport { extractAssistantText, type PiSessionEvent } from './pi-events';\nimport { serializeToolOutput } from './pi-utils';\n\n/**\n * Translator state shared across all events of a single turn. Reset at the\n * start of every `doPromptTurn`. Callers update the same instance and read it to\n * decide when a turn has settled into a steady state (e.g. for gap-filling).\n */\nexport interface PiTranslatorState {\n /**\n * True once a `turn_start` or assistant `message_start` event has been\n * observed. Suppresses spurious deltas that arrive before the turn opens.\n */\n promptStarted: boolean;\n /** Accumulated assistant text from `text_delta` events. */\n streamedAssistantText: string;\n /** Stream-part id for the active text block; synthesized on first delta. */\n currentTextId: string | undefined;\n /**\n * Stream-part id for the active reasoning block; synthesized lazily on\n * first `thinking_delta`.\n */\n currentReasoningId: string | undefined;\n /** Whether a `reasoning-start` event has already been emitted. */\n reasoningStarted: boolean;\n /** Tool-call id → tool name (used to fill in `toolName` on results). */\n observedToolNames: Map<string, string>;\n /** Tool ids requested by the current assistant message but not yet completed. */\n pendingStepToolCallIds: Set<string>;\n /** Whether the current assistant message has opened a visible step. */\n stepOpen: boolean;\n /**\n * Tool-call id → the exact output value the host submitted for a\n * user-registered (host-executed) tool. Pi only echoes the tool result back\n * as serialized text (the tool handler stringifies the output before handing\n * it to the runtime so the model can read it), which would otherwise reach\n * consumers as a string and lose the original object structure. Keeping the\n * submitted value here lets the result projection surface the original object\n * — matching the other adapters — while the model still receives the text.\n * Populated by the session's `submitToolResult`; consumed (and cleared) when\n * the matching `tool_result`/`tool_execution_end` event is translated.\n */\n hostToolResults: Map<string, unknown>;\n dynamicToolCallIds: Set<string>;\n /**\n * Names of tools that Pi executes natively (read/write/edit/bash/grep/\n * find/ls). `tool-call` events for these get `providerExecuted: true`\n * so the harness host doesn't try to dispatch them. User-registered\n * tools are not in this set.\n */\n readonly builtinToolNames: ReadonlySet<string>;\n readonly hostToolNames: ReadonlySet<string>;\n /**\n * Map of native tool name → common name. `find` → `glob`, etc. Pi emits\n * native names on its events; the wire `toolName` is the common name when\n * one exists.\n */\n readonly nativeToCommonNameMap: ReadonlyMap<string, string>;\n}\n\nexport interface PiTranslatorStateOptions {\n readonly builtinToolNames?: ReadonlyArray<string>;\n readonly hostToolNames?: ReadonlyArray<string>;\n readonly nativeToCommon?:\n | ReadonlyMap<string, string>\n | Record<string, string>;\n}\n\nexport function createPiTranslatorState(\n options: PiTranslatorStateOptions = {},\n): PiTranslatorState {\n const map =\n options.nativeToCommon instanceof Map\n ? options.nativeToCommon\n : new Map(Object.entries(options.nativeToCommon ?? {}));\n return {\n promptStarted: false,\n streamedAssistantText: '',\n currentTextId: undefined,\n currentReasoningId: undefined,\n reasoningStarted: false,\n observedToolNames: new Map(),\n pendingStepToolCallIds: new Set(),\n stepOpen: false,\n hostToolResults: new Map(),\n dynamicToolCallIds: new Set(),\n builtinToolNames: new Set(options.builtinToolNames ?? []),\n hostToolNames: new Set(options.hostToolNames ?? []),\n nativeToCommonNameMap: map,\n };\n}\n\nfunction newId(): string {\n return randomBytes(8).toString('hex');\n}\n\n/**\n * Pi's `tool_execution_end` event payload (`result`) is a Pi `AgentToolResult`\n * envelope `{ content: (TextContent | ImageContent)[], details, terminate? }`.\n * The `tool_result` event uses a flat shape with `content` and `details` at\n * the top level. In both cases we extract just the text payload (joined when\n * multiple text parts are present) so the AI SDK consumer sees the raw\n * string the tool produced.\n */\nfunction unwrapPiToolResult(event: PiSessionEvent): never {\n const candidates: unknown[] = [];\n const result = event.result as unknown;\n if (result && typeof result === 'object') {\n const inner = (result as { content?: unknown }).content;\n if (Array.isArray(inner)) candidates.push(inner);\n }\n if (Array.isArray(event.content)) candidates.push(event.content);\n\n for (const content of candidates) {\n if (!Array.isArray(content)) continue;\n const text = content\n .filter(\n (p): p is { type: 'text'; text: string } =>\n !!p &&\n typeof p === 'object' &&\n (p as { type?: unknown }).type === 'text' &&\n typeof (p as { text?: unknown }).text === 'string',\n )\n .map(p => p.text)\n .join('');\n if (text) return text as never;\n }\n\n if (typeof event.result === 'string') return event.result as never;\n if (typeof event.content === 'string') return event.content as never;\n return (event.result ?? event.content ?? null) as never;\n}\n\nfunction parseMcpToolResult(content: unknown): unknown {\n if (typeof content !== 'string') return content;\n try {\n return secureJsonParse(content);\n } catch {\n return content;\n }\n}\n\nfunction resolveToolName(\n state: PiTranslatorState,\n nativeName: string,\n): { wire: string; native: string } {\n const common = state.nativeToCommonNameMap.get(nativeName);\n return { wire: common ?? nativeName, native: nativeName };\n}\n\nfunction finishStep(state: PiTranslatorState): HarnessV1StreamPart[] {\n if (!state.stepOpen || state.pendingStepToolCallIds.size > 0) return [];\n state.stepOpen = false;\n state.pendingStepToolCallIds.clear();\n return [\n {\n type: 'finish-step',\n finishReason: { unified: 'stop', raw: 'stop' },\n usage: {\n inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },\n outputTokens: { total: 0, text: 0, reasoning: 0 },\n },\n harnessMetadata: { pi: { inferredStep: true } },\n },\n ];\n}\n\nexport function finishPiApprovalStep(\n state: PiTranslatorState,\n toolCallId: string,\n): HarnessV1StreamPart[] {\n state.stepOpen = true;\n state.pendingStepToolCallIds.delete(toolCallId);\n return finishStep(state);\n}\n\nfunction extractPiToolCallIds(message: PiSessionEvent['message']): string[] {\n if (!message || message.role !== 'assistant') return [];\n if (!Array.isArray(message.content)) return [];\n return message.content.flatMap(part => {\n if (!part || typeof part !== 'object') return [];\n const block = part as Record<string, unknown>;\n if (block.type !== 'toolCall') return [];\n const id = block.id ?? block.toolCallId;\n return typeof id === 'string' && id.length > 0 ? [id] : [];\n });\n}\n\n/**\n * Translate a single Pi `session.subscribe` event into zero or more\n * `HarnessV1StreamPart`s, updating the translator state in place. Returns\n * an empty array for events that produce no output (e.g. events emitted\n * before `turn_start`).\n *\n * The translator does NOT emit `stream-start`/`finish` — those are\n * lifecycle signals owned by the session layer.\n */\nexport function translatePiEvent(\n event: PiSessionEvent,\n state: PiTranslatorState,\n): HarnessV1StreamPart[] {\n switch (event.type) {\n case 'turn_start':\n case 'message_start': {\n if (\n event.type === 'message_start' &&\n event.message?.role !== 'assistant'\n ) {\n return [];\n }\n state.promptStarted = true;\n if (event.type === 'message_start') {\n state.stepOpen = true;\n state.pendingStepToolCallIds.clear();\n }\n state.streamedAssistantText = '';\n state.currentTextId = undefined;\n state.currentReasoningId = undefined;\n state.reasoningStarted = false;\n return [];\n }\n\n case 'message_update': {\n if (!state.promptStarted) return [];\n const update = event.assistantMessageEvent;\n if (!update) return [];\n if (update.type === 'text_delta' && typeof update.delta === 'string') {\n const parts: HarnessV1StreamPart[] = [];\n // If reasoning was active, close it before opening the text block so\n // consumers can reset block-scoped formatting (ANSI colors, etc.)\n // between sections.\n if (state.reasoningStarted && state.currentReasoningId) {\n parts.push({\n type: 'reasoning-end',\n id: state.currentReasoningId,\n });\n state.reasoningStarted = false;\n state.currentReasoningId = undefined;\n }\n if (!state.currentTextId) {\n state.currentTextId = newId();\n parts.push({ type: 'text-start', id: state.currentTextId });\n }\n state.streamedAssistantText += update.delta;\n parts.push({\n type: 'text-delta',\n id: state.currentTextId,\n delta: update.delta,\n });\n return parts;\n }\n if (\n update.type === 'thinking_delta' &&\n typeof update.delta === 'string'\n ) {\n const parts: HarnessV1StreamPart[] = [];\n // Symmetric to the text branch: close any open text block before\n // starting a fresh reasoning block.\n if (state.currentTextId) {\n parts.push({ type: 'text-end', id: state.currentTextId });\n state.currentTextId = undefined;\n }\n if (!state.currentReasoningId) {\n state.currentReasoningId = newId();\n }\n if (!state.reasoningStarted) {\n state.reasoningStarted = true;\n parts.push({ type: 'reasoning-start', id: state.currentReasoningId });\n }\n parts.push({\n type: 'reasoning-delta',\n id: state.currentReasoningId,\n delta: update.delta,\n });\n return parts;\n }\n return [];\n }\n\n case 'message_end':\n case 'turn_end': {\n if (!state.promptStarted) return [];\n const parts: HarnessV1StreamPart[] = [];\n const fullText = extractAssistantText(event.message);\n if (\n state.currentTextId &&\n fullText.startsWith(state.streamedAssistantText) &&\n fullText.length > state.streamedAssistantText.length\n ) {\n const missing = fullText.slice(state.streamedAssistantText.length);\n state.streamedAssistantText = fullText;\n parts.push({\n type: 'text-delta',\n id: state.currentTextId,\n delta: missing,\n });\n }\n if (state.currentTextId) {\n parts.push({ type: 'text-end', id: state.currentTextId });\n state.currentTextId = undefined;\n }\n if (state.reasoningStarted && state.currentReasoningId) {\n parts.push({ type: 'reasoning-end', id: state.currentReasoningId });\n state.reasoningStarted = false;\n state.currentReasoningId = undefined;\n }\n if (event.type === 'message_end') {\n for (const toolCallId of extractPiToolCallIds(event.message)) {\n state.pendingStepToolCallIds.add(toolCallId);\n }\n } else {\n state.pendingStepToolCallIds.clear();\n parts.push(...finishStep(state));\n }\n return parts;\n }\n\n case 'tool_execution_start': {\n if (!event.toolCallId || !event.toolName) return [];\n const { wire, native } = resolveToolName(state, event.toolName);\n state.observedToolNames.set(event.toolCallId, wire);\n const isMcpTool =\n !state.hostToolNames.has(native) &&\n (native === 'mcp' || native.startsWith('mcp__'));\n const providerExecuted = state.builtinToolNames.has(native) || isMcpTool;\n if (isMcpTool) state.dynamicToolCallIds.add(event.toolCallId);\n const input = serializeToolOutput(event.args ?? event.input ?? {});\n return [\n {\n type: 'tool-call',\n toolCallId: event.toolCallId,\n toolName: wire,\n input,\n ...(wire !== native ? { nativeName: native } : {}),\n ...(providerExecuted ? { providerExecuted: true } : {}),\n ...(isMcpTool ? { dynamic: true } : {}),\n } as HarnessV1StreamPart,\n ];\n }\n\n case 'tool_execution_end':\n case 'tool_result': {\n if (!event.toolCallId) return [];\n const recordedName = state.observedToolNames.get(event.toolCallId);\n const nativeName = event.toolName;\n const wire =\n recordedName ??\n (nativeName ? resolveToolName(state, nativeName).wire : undefined);\n if (!wire) return [];\n const dynamic = state.dynamicToolCallIds.delete(event.toolCallId);\n /*\n * Prefer the exact value the host submitted for user-registered tools\n * (see `hostToolResults`). Built-in tools, whose results Pi produces and\n * reports as text, are not in the map and fall back to unwrapping the\n * event's text payload.\n */\n const result = state.hostToolResults.has(event.toolCallId)\n ? ((state.hostToolResults.get(event.toolCallId) ?? null) as Extract<\n HarnessV1StreamPart,\n { type: 'tool-result' }\n >['result'])\n : dynamic\n ? parseMcpToolResult(unwrapPiToolResult(event))\n : unwrapPiToolResult(event);\n state.hostToolResults.delete(event.toolCallId);\n state.pendingStepToolCallIds.delete(event.toolCallId);\n return [\n {\n type: 'tool-result',\n toolCallId: event.toolCallId,\n toolName: wire,\n result,\n ...(event.isError ? { isError: true } : {}),\n ...(dynamic ? { dynamic: true } : {}),\n } as HarnessV1StreamPart,\n ...finishStep(state),\n ];\n }\n\n case 'compaction_end': {\n /*\n * Pi performs the compaction itself; we observe its result. Skip aborted\n * or result-less compactions (nothing happened). A result with no summary\n * still represents a real compaction, so emit it with a placeholder\n * rather than dropping the event. `reason` is `'manual'` for an explicit\n * `session.compact()` call, `'threshold'`/`'overflow'` for Pi's automatic\n * compaction — both map to `'auto'` on the wire. Pi reports `tokensBefore`\n * but not `tokensAfter`.\n */\n if (event.aborted) return [];\n const result = event.result;\n if (!result || typeof result !== 'object') return [];\n const rawSummary = (result as { summary?: unknown }).summary;\n const summary =\n typeof rawSummary === 'string' ? rawSummary : '(no summary provided)';\n const tokensBefore = (result as { tokensBefore?: unknown }).tokensBefore;\n return [\n {\n type: 'compaction',\n trigger: event.reason === 'manual' ? 'manual' : 'auto',\n summary,\n ...(typeof tokensBefore === 'number' ? { tokensBefore } : {}),\n },\n ];\n }\n\n default:\n return [];\n }\n}\n","import {\n HarnessCapabilityUnsupportedError,\n type HarnessV1Prompt,\n type HarnessV1Skill,\n} from '@ai-sdk/harness';\n\nconst HARNESS_ID = 'pi';\n\n/**\n * Extract a single user text string from a `HarnessV1Prompt`. Pi's\n * `session.prompt(text)` accepts a string; multimodal user content\n * is not supported in this foundational version.\n */\nexport function extractUserText(prompt: HarnessV1Prompt): string {\n if (typeof prompt === 'string') {\n return prompt;\n }\n\n const { content } = prompt;\n if (typeof content === 'string') {\n return content;\n }\n\n const parts: string[] = [];\n for (const part of content) {\n if (part.type !== 'text') {\n throw new HarnessCapabilityUnsupportedError({\n message: `pi: only text user-message parts are supported; got '${part.type}'.`,\n harnessId: HARNESS_ID,\n });\n }\n parts.push(part.text);\n }\n return parts.join('\\n\\n');\n}\n\n/*\n * Frame session instructions and the user's text so the runtime treats the\n * instructions as system-provided operating guidance, not something the user\n * wrote. Without the wrapper the agent can echo the prepended text back as if\n * the user had asked for it, which is confusing since the user never typed it.\n * Applied only to the first user message of a fresh session.\n */\nexport function frameInstructions(\n instructions: string,\n userText: string,\n): string {\n return (\n '<session-instructions>\\n' +\n 'The block below is operating guidance from the system, not a message from the user — follow it, but do not mention it or attribute it to the user.\\n\\n' +\n `${instructions}\\n` +\n '</session-instructions>\\n\\n' +\n `<user-message>\\n${userText}\\n</user-message>`\n );\n}\n\n/** Serialize a tool output to the string Pi feeds back to the model. */\nexport function serializeToolOutput(output: unknown): string {\n if (typeof output === 'string') {\n return output;\n }\n const serialized = JSON.stringify(output);\n return serialized ?? 'null';\n}\n\nexport function getErrorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Validate that a name is safe to use as a filesystem path segment under\n * `.pi/skills/<name>/` or `.pi/agents/<name>.md`. Refuses anything that\n * could be interpreted as a path traversal or contains shell-sensitive\n * characters.\n */\nexport function safePiMetadataSegment(name: string, label: string): string {\n if (!/^[A-Za-z0-9._-]+$/.test(name) || name === '.' || name === '..') {\n throw new Error(`Invalid Pi ${label} name: ${name}`);\n }\n return name;\n}\n\n/** Frontmatter renderer for `.pi/skills/<name>/SKILL.md`. */\nexport function renderPiSkillFile(skill: HarnessV1Skill): string {\n return `---\\nname: ${skill.name}\\ndescription: ${skill.description}\\n---\\n\\n${skill.content}`;\n}\n","import { Type, type TSchema } from 'typebox';\n\n/**\n * Wrap a JSON Schema 7 fragment so Pi's `defineTool({ parameters })` accepts\n * it. Pi v0.77 uses TypeBox at the type level but treats `parameters` as\n * opaque schema metadata at runtime, so `Type.Unsafe(jsonSchema)` is\n * sufficient — no per-property structural conversion is needed.\n */\nexport function toolSpecToTypeBoxParameters(jsonSchema: unknown): TSchema {\n return Type.Unsafe(jsonSchema as object);\n}\n","/**\n * Pi VFS — global Node `fs` monkey-patch that redirects reads/writes against a\n * mount point (the session's sandbox working directory, e.g.\n * `/vercel/sandbox/<harnessId>-<sessionId>/...`) to a real backing directory on\n * the host. The mount point is a sandbox path that does not exist on the host,\n * so the redirect never shadows real host files.\n *\n * The mapping is process-global because Pi's upstream runtime reads and\n * writes through the shared `fs` module. Concurrent mounts are supported as\n * long as each instance uses a distinct mount point (each session's sandbox\n * working directory is unique).\n *\n * Multi-instance invariants:\n * - Multiple `PiWorkspaceVfs` instances may stay mounted concurrently.\n * - Path routing uses longest-prefix matching, so mount points must not\n * overlap.\n * - Extra `fs` patches stay installed while `mountedRoots.size > 0` and are\n * restored only after the final unmount.\n * - Mount and unmount remain synchronous, so Node's single-threaded execution\n * preserves patch/install ordering.\n *\n * Supported logical-path APIs:\n * - Sync: `existsSync`, `readFileSync`, `writeFileSync`, `mkdirSync`,\n * `readdirSync`, `renameSync`, `rmSync`, `openSync`, `statSync`,\n * `realpathSync` (+ `.native`).\n * - Callback: `mkdir`, `realpath`, `stat`, `rmdir`, `utimes`, `writeFile`.\n * - Promises: `fs.promises.mkdir`, `fs.promises.readFile`,\n * `fs.promises.writeFile`.\n *\n * Anything else is intentionally unsupported. If Pi starts using additional\n * `fs` APIs against logical roots, those call sites must be added here\n * deliberately with tests.\n */\n\nimport fs from 'node:fs';\nimport { syncBuiltinESMExports } from 'node:module';\nimport path from 'node:path';\n\ntype MountedRoot = {\n backingRoot: string;\n mountPoint: string;\n};\n\ntype WrappedRealpathSync = typeof fs.realpathSync & {\n native?: typeof fs.realpathSync.native;\n};\n\ntype Mutable<T> = {\n -readonly [K in keyof T]: T[K];\n};\n\nconst mountedRoots = new Map<string, MountedRoot>();\nconst mutableFs = fs as Mutable<typeof fs>;\nconst mutableFsPromises = fs.promises as Mutable<typeof fs.promises>;\n\nconst originalFsSyncMethods = {\n existsSync: fs.existsSync,\n mkdirSync: fs.mkdirSync,\n openSync: fs.openSync,\n readFileSync: fs.readFileSync,\n readdirSync: fs.readdirSync,\n realpathSync: fs.realpathSync,\n renameSync: fs.renameSync,\n rmSync: fs.rmSync,\n statSync: fs.statSync,\n writeFileSync: fs.writeFileSync,\n};\n\nconst originalFsCallbackMethods = {\n mkdir: fs.mkdir,\n realpath: fs.realpath,\n rmdir: fs.rmdir,\n stat: fs.stat,\n utimes: fs.utimes,\n writeFile: fs.writeFile,\n};\n\nconst originalFsPromises = {\n mkdir: fs.promises.mkdir.bind(fs.promises),\n readFile: fs.promises.readFile.bind(fs.promises),\n writeFile: fs.promises.writeFile.bind(fs.promises),\n};\n\nfunction isInsidePath(parent: string, candidate: string): boolean {\n const relative = path.relative(parent, candidate);\n return (\n relative === '' ||\n (!relative.startsWith('..') && !path.isAbsolute(relative))\n );\n}\n\nfunction resolveAbsolutePath(inputPath: string): string {\n return path.isAbsolute(inputPath)\n ? path.normalize(inputPath)\n : path.resolve(inputPath);\n}\n\nfunction findMountedRoot(inputPath: string): MountedRoot | undefined {\n const resolvedPath = resolveAbsolutePath(inputPath);\n let bestMatch: MountedRoot | undefined;\n\n for (const mountedRoot of mountedRoots.values()) {\n if (!isInsidePath(mountedRoot.mountPoint, resolvedPath)) {\n continue;\n }\n if (\n !bestMatch ||\n mountedRoot.mountPoint.length > bestMatch.mountPoint.length\n ) {\n bestMatch = mountedRoot;\n }\n }\n\n return bestMatch;\n}\n\nfunction mapToBackingPath(inputPath: string): string | null {\n const mountedRoot = findMountedRoot(inputPath);\n if (!mountedRoot) {\n return null;\n }\n\n const resolvedPath = resolveAbsolutePath(inputPath);\n const relativePath = path.relative(mountedRoot.mountPoint, resolvedPath);\n return relativePath\n ? path.join(mountedRoot.backingRoot, relativePath)\n : mountedRoot.backingRoot;\n}\n\nfunction mapRealpathResult(inputPath: string, result: string): string {\n const mountedRoot = findMountedRoot(inputPath);\n if (!mountedRoot) {\n return result;\n }\n\n let normalizedBackingRoot = path.resolve(mountedRoot.backingRoot);\n try {\n const realpath =\n originalFsSyncMethods.realpathSync.native ??\n originalFsSyncMethods.realpathSync;\n normalizedBackingRoot = path.resolve(realpath(mountedRoot.backingRoot));\n } catch {\n // Fall back to the configured backing root when canonicalization fails.\n }\n\n const normalizedResult = path.resolve(result);\n if (!isInsidePath(normalizedBackingRoot, normalizedResult)) {\n return result;\n }\n\n const relativePath = path.relative(normalizedBackingRoot, normalizedResult);\n return relativePath\n ? path.join(mountedRoot.mountPoint, relativePath)\n : mountedRoot.mountPoint;\n}\n\nfunction mapRenamePaths(\n sourcePath: string,\n destinationPath: string,\n): [string, string] | null {\n const sourceRoot = findMountedRoot(sourcePath);\n const destinationRoot = findMountedRoot(destinationPath);\n\n if (!sourceRoot && !destinationRoot) {\n return null;\n }\n\n if (\n !sourceRoot ||\n !destinationRoot ||\n sourceRoot.mountPoint !== destinationRoot.mountPoint\n ) {\n throw new Error(\n 'Pi logical VFS paths cannot rename across mount boundaries',\n );\n }\n\n return [\n mapToBackingPath(sourcePath) ?? sourcePath,\n mapToBackingPath(destinationPath) ?? destinationPath,\n ];\n}\n\nfunction wrapSinglePathSync<Fn extends (...args: never[]) => unknown>(\n original: Fn,\n options: {\n mapResult?: (inputPath: string, result: ReturnType<Fn>) => ReturnType<Fn>;\n } = {},\n): Fn {\n return ((...args: Parameters<Fn>) => {\n const [inputPath] = args;\n if (typeof inputPath === 'string') {\n const mappedPath = mapToBackingPath(inputPath);\n if (mappedPath) {\n const result = original(\n ...([mappedPath, ...args.slice(1)] as Parameters<Fn>),\n ) as ReturnType<Fn>;\n return options.mapResult\n ? options.mapResult(inputPath, result)\n : result;\n }\n }\n return original(...args);\n }) as Fn;\n}\n\nfunction wrapRenameSync<Fn extends (...args: never[]) => unknown>(\n original: Fn,\n): Fn {\n return ((...args: Parameters<Fn>) => {\n const [sourcePath, destinationPath] = args;\n if (typeof sourcePath === 'string' && typeof destinationPath === 'string') {\n const mappedPaths = mapRenamePaths(sourcePath, destinationPath);\n if (mappedPaths) {\n return original(\n ...([\n mappedPaths[0],\n mappedPaths[1],\n ...args.slice(2),\n ] as Parameters<Fn>),\n );\n }\n }\n return original(...args);\n }) as Fn;\n}\n\nfunction wrapSinglePathCallback<Fn extends (...args: never[]) => unknown>(\n original: Fn,\n options: {\n mapCallbackResult?: (inputPath: string, result: unknown) => unknown;\n } = {},\n): Fn {\n return ((...args: Parameters<Fn>) => {\n const [inputPath] = args;\n if (typeof inputPath === 'string') {\n const mappedPath = mapToBackingPath(inputPath);\n if (mappedPath) {\n const nextArgs = [mappedPath, ...args.slice(1)] as unknown[];\n const maybeCallback = nextArgs.at(-1);\n if (options.mapCallbackResult && typeof maybeCallback === 'function') {\n nextArgs[nextArgs.length - 1] = (\n error: NodeJS.ErrnoException | null,\n result: unknown,\n ...rest: unknown[]\n ) => {\n const mappedResult = error\n ? result\n : options.mapCallbackResult?.(inputPath, result);\n (maybeCallback as (...callbackArgs: unknown[]) => void)(\n error,\n mappedResult,\n ...rest,\n );\n };\n }\n return original(...(nextArgs as Parameters<Fn>));\n }\n }\n return original(...args);\n }) as Fn;\n}\n\nfunction wrapSinglePathPromise<\n Fn extends (...args: never[]) => Promise<unknown>,\n>(original: Fn): Fn {\n return (async (...args: Parameters<Fn>) => {\n const [inputPath] = args;\n if (typeof inputPath === 'string') {\n const mappedPath = mapToBackingPath(inputPath);\n if (mappedPath) {\n return await original(\n ...([mappedPath, ...args.slice(1)] as Parameters<Fn>),\n );\n }\n }\n return await original(...args);\n }) as Fn;\n}\n\nfunction createWrappedRealpathSync(): WrappedRealpathSync {\n const wrapped = wrapSinglePathSync(originalFsSyncMethods.realpathSync, {\n mapResult: (inputPath, result) =>\n typeof result === 'string'\n ? mapRealpathResult(inputPath, result)\n : result,\n }) as WrappedRealpathSync;\n\n if (originalFsSyncMethods.realpathSync.native) {\n wrapped.native = wrapSinglePathSync(\n originalFsSyncMethods.realpathSync.native,\n {\n mapResult: (inputPath, result) =>\n typeof result === 'string'\n ? mapRealpathResult(inputPath, result)\n : result,\n },\n ) as typeof fs.realpathSync.native;\n }\n\n return wrapped;\n}\n\nconst wrappedFsSyncMethods = {\n existsSync: wrapSinglePathSync(originalFsSyncMethods.existsSync),\n mkdirSync: wrapSinglePathSync(originalFsSyncMethods.mkdirSync),\n openSync: wrapSinglePathSync(originalFsSyncMethods.openSync),\n readFileSync: wrapSinglePathSync(originalFsSyncMethods.readFileSync),\n readdirSync: wrapSinglePathSync(originalFsSyncMethods.readdirSync),\n realpathSync: createWrappedRealpathSync(),\n renameSync: wrapRenameSync(originalFsSyncMethods.renameSync),\n rmSync: wrapSinglePathSync(originalFsSyncMethods.rmSync),\n statSync: wrapSinglePathSync(originalFsSyncMethods.statSync),\n writeFileSync: wrapSinglePathSync(originalFsSyncMethods.writeFileSync),\n};\n\nconst wrappedFsCallbackMethods = {\n mkdir: wrapSinglePathCallback(originalFsCallbackMethods.mkdir),\n realpath: wrapSinglePathCallback(originalFsCallbackMethods.realpath, {\n mapCallbackResult: (inputPath, result) =>\n typeof result === 'string'\n ? mapRealpathResult(inputPath, result)\n : result,\n }),\n rmdir: wrapSinglePathCallback(originalFsCallbackMethods.rmdir),\n stat: wrapSinglePathCallback(originalFsCallbackMethods.stat),\n utimes: wrapSinglePathCallback(originalFsCallbackMethods.utimes),\n writeFile: wrapSinglePathCallback(originalFsCallbackMethods.writeFile),\n};\n\nconst wrappedFsPromises = {\n mkdir: wrapSinglePathPromise(originalFsPromises.mkdir),\n readFile: wrapSinglePathPromise(originalFsPromises.readFile),\n writeFile: wrapSinglePathPromise(originalFsPromises.writeFile),\n};\n\nfunction areExtraFsPatchesInstalled(): boolean {\n return mutableFs.existsSync === wrappedFsSyncMethods.existsSync;\n}\n\nfunction installExtraFsPatches() {\n if (areExtraFsPatchesInstalled()) return;\n\n mutableFs.existsSync = wrappedFsSyncMethods.existsSync;\n mutableFs.mkdirSync = wrappedFsSyncMethods.mkdirSync;\n mutableFs.openSync = wrappedFsSyncMethods.openSync;\n mutableFs.readFileSync = wrappedFsSyncMethods.readFileSync;\n mutableFs.readdirSync = wrappedFsSyncMethods.readdirSync;\n mutableFs.realpathSync = wrappedFsSyncMethods.realpathSync;\n mutableFs.renameSync = wrappedFsSyncMethods.renameSync;\n mutableFs.rmSync = wrappedFsSyncMethods.rmSync;\n mutableFs.statSync = wrappedFsSyncMethods.statSync;\n mutableFs.writeFileSync = wrappedFsSyncMethods.writeFileSync;\n\n mutableFs.mkdir = wrappedFsCallbackMethods.mkdir;\n mutableFs.realpath = wrappedFsCallbackMethods.realpath;\n mutableFs.rmdir = wrappedFsCallbackMethods.rmdir;\n mutableFs.stat = wrappedFsCallbackMethods.stat;\n mutableFs.utimes = wrappedFsCallbackMethods.utimes;\n mutableFs.writeFile = wrappedFsCallbackMethods.writeFile;\n\n mutableFsPromises.mkdir = wrappedFsPromises.mkdir;\n mutableFsPromises.readFile = wrappedFsPromises.readFile;\n mutableFsPromises.writeFile = wrappedFsPromises.writeFile;\n\n syncBuiltinESMExports();\n}\n\nfunction restoreExtraFsPatches() {\n if (!areExtraFsPatchesInstalled()) return;\n\n mutableFs.existsSync = originalFsSyncMethods.existsSync;\n mutableFs.mkdirSync = originalFsSyncMethods.mkdirSync;\n mutableFs.openSync = originalFsSyncMethods.openSync;\n mutableFs.readFileSync = originalFsSyncMethods.readFileSync;\n mutableFs.readdirSync = originalFsSyncMethods.readdirSync;\n mutableFs.realpathSync = originalFsSyncMethods.realpathSync;\n mutableFs.renameSync = originalFsSyncMethods.renameSync;\n mutableFs.rmSync = originalFsSyncMethods.rmSync;\n mutableFs.statSync = originalFsSyncMethods.statSync;\n mutableFs.writeFileSync = originalFsSyncMethods.writeFileSync;\n\n mutableFs.mkdir = originalFsCallbackMethods.mkdir;\n mutableFs.realpath = originalFsCallbackMethods.realpath;\n mutableFs.rmdir = originalFsCallbackMethods.rmdir;\n mutableFs.stat = originalFsCallbackMethods.stat;\n mutableFs.utimes = originalFsCallbackMethods.utimes;\n mutableFs.writeFile = originalFsCallbackMethods.writeFile;\n\n mutableFsPromises.mkdir = originalFsPromises.mkdir;\n mutableFsPromises.readFile = originalFsPromises.readFile;\n mutableFsPromises.writeFile = originalFsPromises.writeFile;\n\n syncBuiltinESMExports();\n}\n\nexport class PiWorkspaceVfs {\n private backingRoot: string | null = null;\n private mountPoint: string | null = null;\n\n private disposeMount(): void {\n if (this.mountPoint) {\n mountedRoots.delete(this.mountPoint);\n }\n this.backingRoot = null;\n this.mountPoint = null;\n }\n\n mount(backingRoot: string, mountPoint: string): void {\n if (this.backingRoot === backingRoot && this.mountPoint === mountPoint) {\n return;\n }\n\n const resolvedBackingRoot = path.resolve(backingRoot);\n const resolvedMountPoint = path.resolve(mountPoint);\n if (this.mountPoint) {\n this.disposeMount();\n }\n\n mountedRoots.set(resolvedMountPoint, {\n backingRoot: resolvedBackingRoot,\n mountPoint: resolvedMountPoint,\n });\n installExtraFsPatches();\n\n this.backingRoot = resolvedBackingRoot;\n this.mountPoint = resolvedMountPoint;\n }\n\n unmount(): void {\n this.disposeMount();\n\n if (mountedRoots.size === 0) {\n restoreExtraFsPatches();\n }\n }\n}\n","import {\n mkdir,\n readFile,\n readdir,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport path from 'node:path';\nimport { shellQuote } from '@ai-sdk/harness/utils';\nimport type { Experimental_SandboxSession } from '@ai-sdk/provider-utils';\n\n/*\n * Pi runs on the host with its working directory pointed at the local mirror,\n * but the only thing it reads from that directory is its own resource\n * configuration: the `.pi` and `.agents` directories (skills, prompts, themes,\n * extensions) and the root-level agent context files (`AGENTS.md`). The model\n * never reads workspace source through the host — file reads, directory\n * listings, and greps all run as tools against the sandbox. Mirroring the whole\n * sandbox workspace to the host would therefore copy files Pi never looks at,\n * one `readBinaryFile` round-trip per file. For a real project that has been\n * cloned and had its dependencies installed (hundreds of thousands of files\n * under `node_modules`) that makes session startup take hours. The mirror is\n * consequently scoped to exactly the paths Pi's resource loader consults.\n *\n * Within those config directories, symlinks are resolved and their targets\n * copied as real files. `.agents/skills` is frequently a symlink to a `skills`\n * directory living elsewhere in the workspace; a mirrored symlink would dangle\n * because its target falls outside the scoped mirror, so the linked content is\n * walked and copied verbatim instead.\n */\nconst PI_CONFIG_DIRS = ['.pi', '.agents'] as const;\nconst PI_CONTEXT_FILENAMES = ['AGENTS.md', 'AGENTS.MD'] as const;\n\nfunction normalizeRelativePath(inputPath: string): string {\n const normalized = inputPath.split(path.posix.sep).join(path.sep);\n const relative = path.normalize(normalized);\n if (\n relative === '' ||\n relative === '.' ||\n path.isAbsolute(relative) ||\n relative === '..' ||\n relative.startsWith(`..${path.sep}`)\n ) {\n throw new Error(\n `Sandbox workspace mirror received an invalid relative path: ${inputPath}`,\n );\n }\n return relative;\n}\n\nasync function readCommandOutput(\n sandbox: Experimental_SandboxSession,\n command: string,\n): Promise<string> {\n const result = await sandbox.run({ command });\n const output = result.stdout || result.stderr;\n if (result.exitCode != null && result.exitCode !== 0) {\n throw new Error(\n output || `Sandbox command failed with exit code ${result.exitCode}`,\n );\n }\n return output;\n}\n\nasync function listRemoteWorkspaceEntries(\n sandbox: Experimental_SandboxSession,\n sandboxWorkDir: string,\n): Promise<{ directories: string[]; files: string[] }> {\n const contextPredicate = PI_CONTEXT_FILENAMES.map(\n name => `-name ${shellQuote(name)}`,\n ).join(' -o ');\n\n // Enumerate only the `.pi`/`.agents` config subtrees plus the root-level\n // context files — never the rest of the workspace. `find -L` dereferences\n // symlinks so that linked targets (e.g. `.agents/skills` pointing elsewhere)\n // are walked and reported through the symlinked path; the resolved file/dir\n // types from `[ -d ]`/`[ -f ]` then tag each entry `d`/`f`, NUL-joined\n // exactly like a full-tree walk so the reconcile below is unchanged.\n const configFinds = PI_CONFIG_DIRS.map(\n dir =>\n ` if [ -d ./${dir} ]; then find -L ./${dir} \\\\( -type d -o -type f \\\\) -print0; fi;`,\n );\n const listCommand = [\n '{',\n ...configFinds,\n ` find . -maxdepth 1 -type f \\\\( ${contextPredicate} \\\\) -print0;`,\n '} |',\n \"while IFS= read -r -d '' entry; do\",\n ' rel=${entry#./}',\n ' if [ -d \"$entry\" ]; then',\n ` printf 'd\\\\t%s\\\\n' \"$rel\"`,\n ' elif [ -f \"$entry\" ]; then',\n ` printf 'f\\\\t%s\\\\n' \"$rel\"`,\n ' fi',\n 'done | LC_ALL=C sort',\n ].join('\\n');\n\n const output = await readCommandOutput(\n sandbox,\n [`cd ${shellQuote(sandboxWorkDir)}`, listCommand].join(' && '),\n );\n\n const directories: string[] = [];\n const files: string[] = [];\n\n for (const line of output.split('\\n').filter(Boolean)) {\n const [kind, rawPath] = line.split('\\t', 2);\n if (!rawPath) continue;\n\n const relativePath = normalizeRelativePath(rawPath);\n if (kind === 'd') directories.push(relativePath);\n else if (kind === 'f') files.push(relativePath);\n }\n\n return { directories, files };\n}\n\nasync function pathKind(\n target: string,\n): Promise<'file' | 'directory' | undefined> {\n try {\n const stats = await stat(target);\n if (stats.isDirectory()) return 'directory';\n if (stats.isFile()) return 'file';\n return undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function collectHostSubtree(\n rootDir: string,\n currentDir: string,\n directories: string[],\n files: string[],\n): Promise<void> {\n const entries = await readdir(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isSymbolicLink()) continue;\n const absolutePath = path.join(currentDir, entry.name);\n const relativePath = path.relative(rootDir, absolutePath);\n if (entry.isDirectory()) {\n directories.push(relativePath);\n await collectHostSubtree(rootDir, absolutePath, directories, files);\n } else if (entry.isFile()) {\n files.push(relativePath);\n }\n }\n}\n\n/**\n * Enumerate the locally-mirrored entries that fall within Pi's scope: the\n * `.pi`/`.agents` config subtrees and the root-level context files. Anything\n * else on the local side (it should not normally exist) is intentionally\n * ignored so the reconcile below neither copies nor deletes it.\n */\nasync function collectHostScopedEntries(\n rootDir: string,\n): Promise<{ directories: string[]; files: string[] }> {\n const directories: string[] = [];\n const files: string[] = [];\n\n for (const dir of PI_CONFIG_DIRS) {\n const configDir = path.join(rootDir, dir);\n if ((await pathKind(configDir)) === 'directory') {\n directories.push(dir);\n await collectHostSubtree(rootDir, configDir, directories, files);\n }\n }\n\n for (const name of PI_CONTEXT_FILENAMES) {\n if ((await pathKind(path.join(rootDir, name))) === 'file') {\n files.push(name);\n }\n }\n\n return { directories, files };\n}\n\nfunction buildRequiredDirectories(\n remoteDirectories: string[],\n remoteFiles: string[],\n): Set<string> {\n const directories = new Set<string>();\n for (const directory of remoteDirectories) {\n directories.add(normalizeRelativePath(directory));\n }\n for (const file of remoteFiles) {\n let current = path.dirname(normalizeRelativePath(file));\n while (current !== '.' && current !== path.sep && current.length > 0) {\n directories.add(current);\n current = path.dirname(current);\n }\n }\n return directories;\n}\n\nexport async function syncHostWorkspaceFromSandbox(args: {\n sandbox: Experimental_SandboxSession;\n sandboxWorkDir: string;\n hostWorkDir: string;\n}): Promise<void> {\n const { sandbox, sandboxWorkDir, hostWorkDir } = args;\n const remoteEntries = await listRemoteWorkspaceEntries(\n sandbox,\n sandboxWorkDir,\n );\n const hostEntries = await collectHostScopedEntries(hostWorkDir);\n const remoteFiles = new Set(remoteEntries.files);\n const requiredDirectories = buildRequiredDirectories(\n remoteEntries.directories,\n remoteEntries.files,\n );\n\n for (const relativePath of hostEntries.files) {\n if (!remoteFiles.has(relativePath)) {\n await rm(path.join(hostWorkDir, relativePath), { force: true });\n }\n }\n\n const removableDirectories = [...hostEntries.directories]\n .filter(p => !requiredDirectories.has(p))\n .sort((a, b) => b.length - a.length);\n for (const relativePath of removableDirectories) {\n await rm(path.join(hostWorkDir, relativePath), {\n recursive: true,\n force: true,\n });\n }\n\n for (const relativePath of [...requiredDirectories].sort(\n (a, b) => a.length - b.length,\n )) {\n await mkdir(path.join(hostWorkDir, relativePath), { recursive: true });\n }\n\n for (const relativePath of remoteEntries.files) {\n const remotePath = path.posix.join(\n sandboxWorkDir,\n relativePath.split(path.sep).join('/'),\n );\n const bytes = await sandbox.readBinaryFile({ path: remotePath });\n if (!bytes) {\n throw new Error(\n `Sandbox workspace file disappeared during mirror sync: ${remotePath}`,\n );\n }\n const content = Buffer.from(bytes);\n\n const hostPath = path.join(hostWorkDir, relativePath);\n let shouldWrite = true;\n try {\n const existing = await readFile(hostPath);\n shouldWrite = !existing.equals(content);\n } catch {\n shouldWrite = true;\n }\n\n if (shouldWrite) {\n await mkdir(path.dirname(hostPath), { recursive: true });\n await writeFile(hostPath, content);\n }\n }\n}\n\nexport async function writeHostWorkspaceFile(\n hostWorkDir: string,\n relativePath: string,\n content: Buffer,\n): Promise<void> {\n const normalizedPath = normalizeRelativePath(relativePath);\n const hostPath = path.join(hostWorkDir, normalizedPath);\n await mkdir(path.dirname(hostPath), { recursive: true });\n await writeFile(hostPath, content);\n}\n","import { createPi } from './pi-harness';\n\n/**\n * Default `pi` harness instance with no overrides — suitable for the common\n * case where Pi's defaults are fine. Equivalent to `createPi()`.\n */\nexport const pi = createPi();\n\nexport { createPi } from './pi-harness';\nexport { VERSION } from './version';\nexport type { PiHarnessSettings } from './pi-harness';\nexport type { PiAuthOptions } from './pi-auth';\n"],"mappings":"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","names":["z","mkdir","rm","path","Type","z","getAiGatewayAuthFromEnv","path","path","shellQuote","writeFile","path","path","isInsidePath","mkdir","readFile","writeFile","path","shellQuote","HARNESS_ID","path","mkdir","input","tool","rm","Type","z"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/harness-pi",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.67",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@earendil-works/pi-coding-agent": "^0.80.10",
|
|
31
31
|
"pi-mcp-adapter": "2.12.1",
|
|
32
32
|
"typebox": "^1.1.38",
|
|
33
|
-
"@ai-sdk/harness": "1.0.
|
|
33
|
+
"@ai-sdk/harness": "1.0.66",
|
|
34
34
|
"@ai-sdk/provider-utils": "5.0.26"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
package/src/pi-session.ts
CHANGED
|
@@ -55,7 +55,6 @@ import {
|
|
|
55
55
|
import { toolSpecToTypeBoxParameters } from './pi-typebox-adapter';
|
|
56
56
|
import {
|
|
57
57
|
extractUserText,
|
|
58
|
-
frameInstructions,
|
|
59
58
|
safePiMetadataSegment,
|
|
60
59
|
serializeToolOutput,
|
|
61
60
|
} from './pi-utils';
|
|
@@ -395,6 +394,8 @@ export async function createPiSession(
|
|
|
395
394
|
});
|
|
396
395
|
const hasMcpServers = Object.keys(mcpServers).length > 0;
|
|
397
396
|
|
|
397
|
+
let sessionInstructions: string | undefined;
|
|
398
|
+
|
|
398
399
|
/*
|
|
399
400
|
* Configured MCP servers are served by an inline Pi extension, so they share
|
|
400
401
|
* the extension runtime with the caller-supplied factories: both are loaded
|
|
@@ -426,11 +427,13 @@ export async function createPiSession(
|
|
|
426
427
|
let currentExtensionsResult:
|
|
427
428
|
| ReturnType<DefaultResourceLoader['getExtensions']>
|
|
428
429
|
| undefined;
|
|
430
|
+
|
|
429
431
|
const resourceLoader = new DefaultResourceLoader({
|
|
430
432
|
cwd: sessionWorkDir,
|
|
431
433
|
agentDir: hostAgentDir,
|
|
432
434
|
settingsManager,
|
|
433
|
-
appendSystemPromptOverride: () =>
|
|
435
|
+
appendSystemPromptOverride: () =>
|
|
436
|
+
sessionInstructions ? [sessionInstructions] : [],
|
|
434
437
|
extensionFactories,
|
|
435
438
|
...(hasExtensionFactories
|
|
436
439
|
? {
|
|
@@ -498,12 +501,6 @@ export async function createPiSession(
|
|
|
498
501
|
* from the persisted journal.
|
|
499
502
|
*/
|
|
500
503
|
let suspending = false;
|
|
501
|
-
/*
|
|
502
|
-
* Instructions are prepended to the first user message of a fresh session
|
|
503
|
-
* only. A resumed session already carried them in its original first
|
|
504
|
-
* message (preserved in the persisted session file), so it starts "applied".
|
|
505
|
-
*/
|
|
506
|
-
let instructionsApplied = input.isResume;
|
|
507
504
|
const pendingToolResults = new Map<string, PendingToolResult>();
|
|
508
505
|
const pendingToolApprovals = new Map<string, PendingToolApproval>();
|
|
509
506
|
|
|
@@ -521,6 +518,15 @@ export async function createPiSession(
|
|
|
521
518
|
*/
|
|
522
519
|
const pendingCompactionParts: HarnessV1StreamPart[] = [];
|
|
523
520
|
|
|
521
|
+
async function applySessionInstructions(
|
|
522
|
+
instructions: string | undefined,
|
|
523
|
+
): Promise<void> {
|
|
524
|
+
if (instructions === sessionInstructions) return;
|
|
525
|
+
sessionInstructions = instructions;
|
|
526
|
+
await reloadResourcesOnly();
|
|
527
|
+
piSession?.setActiveToolsByName(piSession.getActiveToolNames());
|
|
528
|
+
}
|
|
529
|
+
|
|
524
530
|
const remoteOps = createPiRemoteOps({
|
|
525
531
|
sandbox,
|
|
526
532
|
paths,
|
|
@@ -939,14 +945,10 @@ export async function createPiSession(
|
|
|
939
945
|
doPromptTurn: async (
|
|
940
946
|
promptOpts: HarnessV1PromptTurnOptions,
|
|
941
947
|
): Promise<HarnessV1PromptControl> => {
|
|
942
|
-
|
|
943
|
-
if (!instructionsApplied && promptOpts.instructions) {
|
|
944
|
-
text = frameInstructions(promptOpts.instructions, text);
|
|
945
|
-
}
|
|
946
|
-
instructionsApplied = true;
|
|
948
|
+
await applySessionInstructions(promptOpts.instructions);
|
|
947
949
|
|
|
948
950
|
return runTurn({
|
|
949
|
-
text,
|
|
951
|
+
text: extractUserText(promptOpts.prompt),
|
|
950
952
|
tools: promptOpts.tools ?? [],
|
|
951
953
|
emit: promptOpts.emit,
|
|
952
954
|
abortSignal: promptOpts.abortSignal,
|
|
@@ -972,6 +974,7 @@ export async function createPiSession(
|
|
|
972
974
|
* flight at the slice boundary is recomputed because a host-resident
|
|
973
975
|
* runtime cannot do a lossless attach.
|
|
974
976
|
*/
|
|
977
|
+
await applySessionInstructions(continueOpts.instructions);
|
|
975
978
|
return runTurn({
|
|
976
979
|
text: '',
|
|
977
980
|
tools: continueOpts.tools ?? [],
|