@ai-sdk/harness-pi 1.0.22 → 1.0.23
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 +10 -0
- package/dist/index.js +58 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/pi-session.ts +9 -4
- package/src/pi-translate.ts +58 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @ai-sdk/harness-pi
|
|
2
2
|
|
|
3
|
+
## 1.0.23
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 91fe6d8: fix(harness): emit `finish-step` stream parts correctly per the underlying model steps
|
|
8
|
+
- Updated dependencies [39c8276]
|
|
9
|
+
- Updated dependencies [91fe6d8]
|
|
10
|
+
- Updated dependencies [0be5014]
|
|
11
|
+
- @ai-sdk/harness@1.0.23
|
|
12
|
+
|
|
3
13
|
## 1.0.22
|
|
4
14
|
|
|
5
15
|
### 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.23" : "0.0.0-test";
|
|
112
112
|
|
|
113
113
|
// src/pi-auth.ts
|
|
114
114
|
var DEFAULT_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
|
|
@@ -678,6 +678,8 @@ function createPiTranslatorState(options = {}) {
|
|
|
678
678
|
currentReasoningId: void 0,
|
|
679
679
|
reasoningStarted: false,
|
|
680
680
|
observedToolNames: /* @__PURE__ */ new Map(),
|
|
681
|
+
pendingStepToolCallIds: /* @__PURE__ */ new Set(),
|
|
682
|
+
stepOpen: false,
|
|
681
683
|
hostToolResults: /* @__PURE__ */ new Map(),
|
|
682
684
|
builtinToolNames: new Set(options.builtinToolNames ?? []),
|
|
683
685
|
nativeToCommonNameMap: map
|
|
@@ -709,6 +711,38 @@ function resolveToolName(state, nativeName) {
|
|
|
709
711
|
const common = state.nativeToCommonNameMap.get(nativeName);
|
|
710
712
|
return { wire: common ?? nativeName, native: nativeName };
|
|
711
713
|
}
|
|
714
|
+
function finishStep(state) {
|
|
715
|
+
if (!state.stepOpen || state.pendingStepToolCallIds.size > 0) return [];
|
|
716
|
+
state.stepOpen = false;
|
|
717
|
+
state.pendingStepToolCallIds.clear();
|
|
718
|
+
return [
|
|
719
|
+
{
|
|
720
|
+
type: "finish-step",
|
|
721
|
+
finishReason: { unified: "stop", raw: "stop" },
|
|
722
|
+
usage: {
|
|
723
|
+
inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
|
|
724
|
+
outputTokens: { total: 0, text: 0, reasoning: 0 }
|
|
725
|
+
},
|
|
726
|
+
harnessMetadata: { pi: { inferredStep: true } }
|
|
727
|
+
}
|
|
728
|
+
];
|
|
729
|
+
}
|
|
730
|
+
function finishPiApprovalStep(state, toolCallId) {
|
|
731
|
+
state.stepOpen = true;
|
|
732
|
+
state.pendingStepToolCallIds.delete(toolCallId);
|
|
733
|
+
return finishStep(state);
|
|
734
|
+
}
|
|
735
|
+
function extractPiToolCallIds(message) {
|
|
736
|
+
if (!message || message.role !== "assistant") return [];
|
|
737
|
+
if (!Array.isArray(message.content)) return [];
|
|
738
|
+
return message.content.flatMap((part) => {
|
|
739
|
+
if (!part || typeof part !== "object") return [];
|
|
740
|
+
const block = part;
|
|
741
|
+
if (block.type !== "toolCall") return [];
|
|
742
|
+
const id = block.id ?? block.toolCallId;
|
|
743
|
+
return typeof id === "string" && id.length > 0 ? [id] : [];
|
|
744
|
+
});
|
|
745
|
+
}
|
|
712
746
|
function translatePiEvent(event, state) {
|
|
713
747
|
switch (event.type) {
|
|
714
748
|
case "turn_start":
|
|
@@ -717,6 +751,10 @@ function translatePiEvent(event, state) {
|
|
|
717
751
|
return [];
|
|
718
752
|
}
|
|
719
753
|
state.promptStarted = true;
|
|
754
|
+
if (event.type === "message_start") {
|
|
755
|
+
state.stepOpen = true;
|
|
756
|
+
state.pendingStepToolCallIds.clear();
|
|
757
|
+
}
|
|
720
758
|
state.streamedAssistantText = "";
|
|
721
759
|
state.currentTextId = void 0;
|
|
722
760
|
state.currentReasoningId = void 0;
|
|
@@ -794,6 +832,14 @@ function translatePiEvent(event, state) {
|
|
|
794
832
|
state.reasoningStarted = false;
|
|
795
833
|
state.currentReasoningId = void 0;
|
|
796
834
|
}
|
|
835
|
+
if (event.type === "message_end") {
|
|
836
|
+
for (const toolCallId of extractPiToolCallIds(event.message)) {
|
|
837
|
+
state.pendingStepToolCallIds.add(toolCallId);
|
|
838
|
+
}
|
|
839
|
+
} else {
|
|
840
|
+
state.pendingStepToolCallIds.clear();
|
|
841
|
+
parts.push(...finishStep(state));
|
|
842
|
+
}
|
|
797
843
|
return parts;
|
|
798
844
|
}
|
|
799
845
|
case "tool_execution_start": {
|
|
@@ -822,6 +868,7 @@ function translatePiEvent(event, state) {
|
|
|
822
868
|
if (!wire) return [];
|
|
823
869
|
const result = state.hostToolResults.has(event.toolCallId) ? state.hostToolResults.get(event.toolCallId) ?? null : unwrapPiToolResult(event);
|
|
824
870
|
state.hostToolResults.delete(event.toolCallId);
|
|
871
|
+
state.pendingStepToolCallIds.delete(event.toolCallId);
|
|
825
872
|
return [
|
|
826
873
|
{
|
|
827
874
|
type: "tool-result",
|
|
@@ -829,7 +876,8 @@ function translatePiEvent(event, state) {
|
|
|
829
876
|
toolName: wire,
|
|
830
877
|
result,
|
|
831
878
|
...event.isError ? { isError: true } : {}
|
|
832
|
-
}
|
|
879
|
+
},
|
|
880
|
+
...finishStep(state)
|
|
833
881
|
];
|
|
834
882
|
}
|
|
835
883
|
case "compaction_end": {
|
|
@@ -1611,6 +1659,14 @@ async function createPiSession(input) {
|
|
|
1611
1659
|
approvalId: args.toolCallId,
|
|
1612
1660
|
toolCallId: args.toolCallId
|
|
1613
1661
|
});
|
|
1662
|
+
if (translatorState) {
|
|
1663
|
+
for (const part of finishPiApprovalStep(
|
|
1664
|
+
translatorState,
|
|
1665
|
+
args.toolCallId
|
|
1666
|
+
)) {
|
|
1667
|
+
currentEmit?.(part);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1614
1670
|
return new Promise((resolve) => {
|
|
1615
1671
|
pendingToolApprovals.set(args.toolCallId, { resolve });
|
|
1616
1672
|
});
|
|
@@ -1745,7 +1801,6 @@ async function createPiSession(input) {
|
|
|
1745
1801
|
reasoning: void 0
|
|
1746
1802
|
}
|
|
1747
1803
|
};
|
|
1748
|
-
currentEmit?.({ type: "finish-step", finishReason, usage });
|
|
1749
1804
|
currentEmit?.({
|
|
1750
1805
|
type: "finish",
|
|
1751
1806
|
finishReason,
|
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 { 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\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 },\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 });\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 AuthStorage,\n createAgentSession,\n DefaultResourceLoader,\n defineTool,\n ModelRegistry,\n SessionManager,\n SettingsManager,\n type AgentSession,\n type AgentToolResult,\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 { resolvePiEnv, type PiAuthOptions } 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 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 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}\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\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 (`hostAgentDir`), never in the sandbox/workspace.\n const authStorage = AuthStorage.create(path.join(hostAgentDir, 'auth.json'));\n const modelRegistry = ModelRegistry.create(\n authStorage,\n path.join(hostAgentDir, 'models.json'),\n );\n const settingsManager = 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 registries: {\n authStorage,\n modelRegistry,\n },\n clientApp: input.clientApp,\n });\n const resolveModel = createPiModelResolver(modelRegistry, resolverEnv);\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\n const resourceLoader = new DefaultResourceLoader({\n cwd: sessionWorkDir,\n agentDir: hostAgentDir,\n settingsManager,\n appendSystemPromptOverride: () => [],\n extensionFactories: [],\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 does not expose extensions, themes, or prompt templates, so\n // disable those entirely — this also avoids loading and executing a host\n // developer's personal Pi extensions inside the server process. Skills are\n // 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 // 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 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 rebuildPiSession(\n userTools: ReadonlyArray<HarnessV1ToolSpec>,\n isFirstBuild: boolean,\n ): Promise<void> {\n if (piSession) {\n unsubscribe?.();\n unsubscribe = undefined;\n piSession.dispose();\n piSession = undefined;\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 }\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 authStorage,\n modelRegistry,\n sessionManager,\n settingsManager,\n resourceLoader,\n customTools,\n tools: toolNames,\n ...(input.settings.thinkingLevel\n ? { thinkingLevel: input.settings.thinkingLevel }\n : {}),\n ...(resolvedModel ? { model: resolvedModel } : {}),\n });\n piSession = session;\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 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 }\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 if (needsRebuild) {\n await rebuildPiSession(userTools, piSession == null);\n lastToolsSignature = signature;\n }\n\n await resourceLoader.reload();\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 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 // `finish-step` populates the step's finishReason + usage (the\n // agent's result builder reads this); `finish` marks the turn end\n // with totalUsage.\n currentEmit?.({ type: 'finish-step', finishReason, usage });\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 unsubscribe?.();\n unsubscribe = undefined;\n piSession?.dispose();\n piSession = undefined;\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 unsubscribe?.();\n unsubscribe = undefined;\n piSession?.dispose();\n piSession = undefined;\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 unsubscribe?.();\n unsubscribe = undefined;\n piSession?.dispose();\n piSession = undefined;\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\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 AuthStorage,\n ModelRegistry,\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\nfunction register(\n registries: { authStorage: AuthStorage; modelRegistry: ModelRegistry },\n provider: string,\n apiKey: string,\n config: ProviderConfigInput,\n): void {\n registries.authStorage.setRuntimeApiKey(provider, apiKey);\n registries.modelRegistry.registerProvider(provider, config);\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 registries,\n clientApp = HARNESS_CLIENT_APP,\n}: {\n options: PiAuthOptions | undefined;\n env: NodeJS.ProcessEnv;\n registries: { authStorage: AuthStorage; modelRegistry: ModelRegistry };\n clientApp?: string;\n}): Record<string, string> {\n const customEnvConfigured = hasConfiguredValue(options?.customEnv);\n if (customEnvConfigured) {\n return applyCustomEnv({\n customEnv: options!.customEnv ?? {},\n registries,\n clientApp,\n });\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 register(\n registries,\n 'vercel-ai-gateway',\n apiKey,\n createGatewayProviderConfig({\n apiKey,\n baseUrl,\n clientApp,\n }),\n );\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 register(\n registries,\n 'vercel-ai-gateway',\n gatewayAuthFromEnv.apiKey,\n createGatewayProviderConfig({\n apiKey: gatewayAuthFromEnv.apiKey,\n baseUrl: gatewayAuthFromEnv.baseUrl,\n clientApp,\n }),\n );\n return {\n AI_GATEWAY_API_KEY: gatewayAuthFromEnv.apiKey,\n AI_GATEWAY_BASE_URL: gatewayAuthFromEnv.baseUrl,\n };\n }\n\n return {};\n}\n\nfunction applyCustomEnv({\n customEnv,\n registries,\n clientApp,\n}: {\n customEnv: Record<string, string>;\n registries: { authStorage: AuthStorage; modelRegistry: ModelRegistry };\n clientApp: string;\n}): Record<string, string> {\n const out: Record<string, string> = {};\n\n const gatewayKey = customEnv.AI_GATEWAY_API_KEY;\n if (gatewayKey) {\n const baseUrl = customEnv.AI_GATEWAY_BASE_URL ?? DEFAULT_GATEWAY_BASE_URL;\n register(\n registries,\n 'vercel-ai-gateway',\n gatewayKey,\n createGatewayProviderConfig({\n apiKey: gatewayKey,\n baseUrl,\n clientApp,\n }),\n );\n out.AI_GATEWAY_API_KEY = gatewayKey;\n out.AI_GATEWAY_BASE_URL = baseUrl;\n }\n\n if (customEnv.OPENAI_API_KEY) {\n const baseUrl = customEnv.OPENAI_BASE_URL ?? DEFAULT_OPENAI_BASE_URL;\n register(registries, 'openai', customEnv.OPENAI_API_KEY, {\n apiKey: customEnv.OPENAI_API_KEY,\n baseUrl,\n authHeader: true,\n });\n }\n\n if (customEnv.ANTHROPIC_API_KEY) {\n const baseUrl = customEnv.ANTHROPIC_BASE_URL ?? DEFAULT_ANTHROPIC_BASE_URL;\n register(registries, 'anthropic', customEnv.ANTHROPIC_API_KEY, {\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 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 register(registries, provider, apiKey, {\n apiKey,\n baseUrl,\n authHeader: true,\n });\n }\n\n return out;\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\nexport function createPiModelResolver(\n modelRegistry: ModelRegistry,\n env: NodeJS.ProcessEnv = process.env,\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 return (\n (useGateway &&\n models.find(m => m.provider === 'vercel-ai-gateway' && matches(m))) ||\n models.find(matches)\n );\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 /** 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 toWorkspaceSandboxPath = (inputPath: string): string => {\n if (path.posix.isAbsolute(inputPath)) {\n const normalizedInput = path.posix.normalize(inputPath);\n if (isInsidePosixPath(normalizedSandbox, normalizedInput)) {\n return normalizedInput;\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 if (\n isInsidePosixPath(normalizedSandbox, normalizedInput) ||\n readableRoots.some(root =>\n isInsidePosixPath(root.sandboxDir, normalizedInput),\n )\n ) {\n return normalizedInput;\n }\n }\n\n return toWorkspaceSandboxPath(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\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 readBuffer = async (inputPath: string): Promise<Buffer> => {\n const bytes = await options.sandbox.readBinaryFile({\n path: options.paths.toReadableSandboxPath(inputPath),\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 previous = await options.sandbox.readBinaryFile({ path: remotePath });\n await runShell(`mkdir -p ${shellQuote(path.posix.dirname(remotePath))}`);\n await options.sandbox.writeTextFile({ path: remotePath, content });\n options.onFileChange?.(\n previous ? 'modify' : 'create',\n options.paths.toRelativePath(remotePath),\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 result = await runShell(\n [\n `if [ ! -e ${shellQuote(remotePath)} ]; then echo \"__PI_LS_NOT_FOUND__\"; exit 2; fi`,\n `if [ ! -d ${shellQuote(remotePath)} ]; then echo \"__PI_LS_NOT_DIR__\"; exit 3; fi`,\n `cd ${shellQuote(remotePath)}`,\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 result = await runShell(\n [\n `if [ ! -e ${shellQuote(remotePath)} ]; then echo \"__PI_FIND_NOT_FOUND__\"; exit 2; fi`,\n `if [ -d ${shellQuote(remotePath)} ]; then find ${shellQuote(remotePath)} -type f -print; else printf '%s\\\\n' ${shellQuote(remotePath)}; 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 = remotePath;\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 relativeTarget = options.paths.toRelativePath(remotePath);\n const targetPath =\n relativeTarget.startsWith('../') || path.posix.isAbsolute(relativeTarget)\n ? remotePath\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(remotePath)} ]; 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 { 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 /**\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 /**\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 /**\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 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 hostToolResults: new Map(),\n builtinToolNames: new Set(options.builtinToolNames ?? []),\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 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\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 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 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 providerExecuted = state.builtinToolNames.has(native);\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 } 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 /*\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 : unwrapPiToolResult(event);\n state.hostToolResults.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 } as HarnessV1StreamPart,\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","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 { 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\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 },\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 });\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 AuthStorage,\n createAgentSession,\n DefaultResourceLoader,\n defineTool,\n ModelRegistry,\n SessionManager,\n SettingsManager,\n type AgentSession,\n type AgentToolResult,\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 { resolvePiEnv, type PiAuthOptions } 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 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}\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\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 (`hostAgentDir`), never in the sandbox/workspace.\n const authStorage = AuthStorage.create(path.join(hostAgentDir, 'auth.json'));\n const modelRegistry = ModelRegistry.create(\n authStorage,\n path.join(hostAgentDir, 'models.json'),\n );\n const settingsManager = 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 registries: {\n authStorage,\n modelRegistry,\n },\n clientApp: input.clientApp,\n });\n const resolveModel = createPiModelResolver(modelRegistry, resolverEnv);\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\n const resourceLoader = new DefaultResourceLoader({\n cwd: sessionWorkDir,\n agentDir: hostAgentDir,\n settingsManager,\n appendSystemPromptOverride: () => [],\n extensionFactories: [],\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 does not expose extensions, themes, or prompt templates, so\n // disable those entirely — this also avoids loading and executing a host\n // developer's personal Pi extensions inside the server process. Skills are\n // 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 // 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 rebuildPiSession(\n userTools: ReadonlyArray<HarnessV1ToolSpec>,\n isFirstBuild: boolean,\n ): Promise<void> {\n if (piSession) {\n unsubscribe?.();\n unsubscribe = undefined;\n piSession.dispose();\n piSession = undefined;\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 }\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 authStorage,\n modelRegistry,\n sessionManager,\n settingsManager,\n resourceLoader,\n customTools,\n tools: toolNames,\n ...(input.settings.thinkingLevel\n ? { thinkingLevel: input.settings.thinkingLevel }\n : {}),\n ...(resolvedModel ? { model: resolvedModel } : {}),\n });\n piSession = session;\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 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 }\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 if (needsRebuild) {\n await rebuildPiSession(userTools, piSession == null);\n lastToolsSignature = signature;\n }\n\n await resourceLoader.reload();\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 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 unsubscribe?.();\n unsubscribe = undefined;\n piSession?.dispose();\n piSession = undefined;\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 unsubscribe?.();\n unsubscribe = undefined;\n piSession?.dispose();\n piSession = undefined;\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 unsubscribe?.();\n unsubscribe = undefined;\n piSession?.dispose();\n piSession = undefined;\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\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 AuthStorage,\n ModelRegistry,\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\nfunction register(\n registries: { authStorage: AuthStorage; modelRegistry: ModelRegistry },\n provider: string,\n apiKey: string,\n config: ProviderConfigInput,\n): void {\n registries.authStorage.setRuntimeApiKey(provider, apiKey);\n registries.modelRegistry.registerProvider(provider, config);\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 registries,\n clientApp = HARNESS_CLIENT_APP,\n}: {\n options: PiAuthOptions | undefined;\n env: NodeJS.ProcessEnv;\n registries: { authStorage: AuthStorage; modelRegistry: ModelRegistry };\n clientApp?: string;\n}): Record<string, string> {\n const customEnvConfigured = hasConfiguredValue(options?.customEnv);\n if (customEnvConfigured) {\n return applyCustomEnv({\n customEnv: options!.customEnv ?? {},\n registries,\n clientApp,\n });\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 register(\n registries,\n 'vercel-ai-gateway',\n apiKey,\n createGatewayProviderConfig({\n apiKey,\n baseUrl,\n clientApp,\n }),\n );\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 register(\n registries,\n 'vercel-ai-gateway',\n gatewayAuthFromEnv.apiKey,\n createGatewayProviderConfig({\n apiKey: gatewayAuthFromEnv.apiKey,\n baseUrl: gatewayAuthFromEnv.baseUrl,\n clientApp,\n }),\n );\n return {\n AI_GATEWAY_API_KEY: gatewayAuthFromEnv.apiKey,\n AI_GATEWAY_BASE_URL: gatewayAuthFromEnv.baseUrl,\n };\n }\n\n return {};\n}\n\nfunction applyCustomEnv({\n customEnv,\n registries,\n clientApp,\n}: {\n customEnv: Record<string, string>;\n registries: { authStorage: AuthStorage; modelRegistry: ModelRegistry };\n clientApp: string;\n}): Record<string, string> {\n const out: Record<string, string> = {};\n\n const gatewayKey = customEnv.AI_GATEWAY_API_KEY;\n if (gatewayKey) {\n const baseUrl = customEnv.AI_GATEWAY_BASE_URL ?? DEFAULT_GATEWAY_BASE_URL;\n register(\n registries,\n 'vercel-ai-gateway',\n gatewayKey,\n createGatewayProviderConfig({\n apiKey: gatewayKey,\n baseUrl,\n clientApp,\n }),\n );\n out.AI_GATEWAY_API_KEY = gatewayKey;\n out.AI_GATEWAY_BASE_URL = baseUrl;\n }\n\n if (customEnv.OPENAI_API_KEY) {\n const baseUrl = customEnv.OPENAI_BASE_URL ?? DEFAULT_OPENAI_BASE_URL;\n register(registries, 'openai', customEnv.OPENAI_API_KEY, {\n apiKey: customEnv.OPENAI_API_KEY,\n baseUrl,\n authHeader: true,\n });\n }\n\n if (customEnv.ANTHROPIC_API_KEY) {\n const baseUrl = customEnv.ANTHROPIC_BASE_URL ?? DEFAULT_ANTHROPIC_BASE_URL;\n register(registries, 'anthropic', customEnv.ANTHROPIC_API_KEY, {\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 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 register(registries, provider, apiKey, {\n apiKey,\n baseUrl,\n authHeader: true,\n });\n }\n\n return out;\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\nexport function createPiModelResolver(\n modelRegistry: ModelRegistry,\n env: NodeJS.ProcessEnv = process.env,\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 return (\n (useGateway &&\n models.find(m => m.provider === 'vercel-ai-gateway' && matches(m))) ||\n models.find(matches)\n );\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 /** 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 toWorkspaceSandboxPath = (inputPath: string): string => {\n if (path.posix.isAbsolute(inputPath)) {\n const normalizedInput = path.posix.normalize(inputPath);\n if (isInsidePosixPath(normalizedSandbox, normalizedInput)) {\n return normalizedInput;\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 if (\n isInsidePosixPath(normalizedSandbox, normalizedInput) ||\n readableRoots.some(root =>\n isInsidePosixPath(root.sandboxDir, normalizedInput),\n )\n ) {\n return normalizedInput;\n }\n }\n\n return toWorkspaceSandboxPath(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\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 readBuffer = async (inputPath: string): Promise<Buffer> => {\n const bytes = await options.sandbox.readBinaryFile({\n path: options.paths.toReadableSandboxPath(inputPath),\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 previous = await options.sandbox.readBinaryFile({ path: remotePath });\n await runShell(`mkdir -p ${shellQuote(path.posix.dirname(remotePath))}`);\n await options.sandbox.writeTextFile({ path: remotePath, content });\n options.onFileChange?.(\n previous ? 'modify' : 'create',\n options.paths.toRelativePath(remotePath),\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 result = await runShell(\n [\n `if [ ! -e ${shellQuote(remotePath)} ]; then echo \"__PI_LS_NOT_FOUND__\"; exit 2; fi`,\n `if [ ! -d ${shellQuote(remotePath)} ]; then echo \"__PI_LS_NOT_DIR__\"; exit 3; fi`,\n `cd ${shellQuote(remotePath)}`,\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 result = await runShell(\n [\n `if [ ! -e ${shellQuote(remotePath)} ]; then echo \"__PI_FIND_NOT_FOUND__\"; exit 2; fi`,\n `if [ -d ${shellQuote(remotePath)} ]; then find ${shellQuote(remotePath)} -type f -print; else printf '%s\\\\n' ${shellQuote(remotePath)}; 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 = remotePath;\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 relativeTarget = options.paths.toRelativePath(remotePath);\n const targetPath =\n relativeTarget.startsWith('../') || path.posix.isAbsolute(relativeTarget)\n ? remotePath\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(remotePath)} ]; 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 { 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 /**\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 /**\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 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 builtinToolNames: new Set(options.builtinToolNames ?? []),\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 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 providerExecuted = state.builtinToolNames.has(native);\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 } 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 /*\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 : 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 } 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","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.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@earendil-works/pi-coding-agent": "^0.79.0",
|
|
30
30
|
"typebox": "^1.1.38",
|
|
31
|
-
"@ai-sdk/harness": "1.0.
|
|
31
|
+
"@ai-sdk/harness": "1.0.23",
|
|
32
32
|
"@ai-sdk/provider-utils": "5.0.7"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
package/src/pi-session.ts
CHANGED
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
} from './pi-resume-state';
|
|
44
44
|
import {
|
|
45
45
|
createPiTranslatorState,
|
|
46
|
+
finishPiApprovalStep,
|
|
46
47
|
translatePiEvent,
|
|
47
48
|
type PiTranslatorState,
|
|
48
49
|
} from './pi-translate';
|
|
@@ -507,6 +508,14 @@ export async function createPiSession(
|
|
|
507
508
|
approvalId: args.toolCallId,
|
|
508
509
|
toolCallId: args.toolCallId,
|
|
509
510
|
});
|
|
511
|
+
if (translatorState) {
|
|
512
|
+
for (const part of finishPiApprovalStep(
|
|
513
|
+
translatorState,
|
|
514
|
+
args.toolCallId,
|
|
515
|
+
)) {
|
|
516
|
+
currentEmit?.(part);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
510
519
|
return new Promise(resolve => {
|
|
511
520
|
pendingToolApprovals.set(args.toolCallId, { resolve });
|
|
512
521
|
});
|
|
@@ -706,10 +715,6 @@ export async function createPiSession(
|
|
|
706
715
|
reasoning: undefined,
|
|
707
716
|
},
|
|
708
717
|
};
|
|
709
|
-
// `finish-step` populates the step's finishReason + usage (the
|
|
710
|
-
// agent's result builder reads this); `finish` marks the turn end
|
|
711
|
-
// with totalUsage.
|
|
712
|
-
currentEmit?.({ type: 'finish-step', finishReason, usage });
|
|
713
718
|
currentEmit?.({
|
|
714
719
|
type: 'finish',
|
|
715
720
|
finishReason,
|
package/src/pi-translate.ts
CHANGED
|
@@ -27,6 +27,10 @@ export interface PiTranslatorState {
|
|
|
27
27
|
reasoningStarted: boolean;
|
|
28
28
|
/** Tool-call id → tool name (used to fill in `toolName` on results). */
|
|
29
29
|
observedToolNames: Map<string, string>;
|
|
30
|
+
/** Tool ids requested by the current assistant message but not yet completed. */
|
|
31
|
+
pendingStepToolCallIds: Set<string>;
|
|
32
|
+
/** Whether the current assistant message has opened a visible step. */
|
|
33
|
+
stepOpen: boolean;
|
|
30
34
|
/**
|
|
31
35
|
* Tool-call id → the exact output value the host submitted for a
|
|
32
36
|
* user-registered (host-executed) tool. Pi only echoes the tool result back
|
|
@@ -75,6 +79,8 @@ export function createPiTranslatorState(
|
|
|
75
79
|
currentReasoningId: undefined,
|
|
76
80
|
reasoningStarted: false,
|
|
77
81
|
observedToolNames: new Map(),
|
|
82
|
+
pendingStepToolCallIds: new Set(),
|
|
83
|
+
stepOpen: false,
|
|
78
84
|
hostToolResults: new Map(),
|
|
79
85
|
builtinToolNames: new Set(options.builtinToolNames ?? []),
|
|
80
86
|
nativeToCommonNameMap: map,
|
|
@@ -130,6 +136,44 @@ function resolveToolName(
|
|
|
130
136
|
return { wire: common ?? nativeName, native: nativeName };
|
|
131
137
|
}
|
|
132
138
|
|
|
139
|
+
function finishStep(state: PiTranslatorState): HarnessV1StreamPart[] {
|
|
140
|
+
if (!state.stepOpen || state.pendingStepToolCallIds.size > 0) return [];
|
|
141
|
+
state.stepOpen = false;
|
|
142
|
+
state.pendingStepToolCallIds.clear();
|
|
143
|
+
return [
|
|
144
|
+
{
|
|
145
|
+
type: 'finish-step',
|
|
146
|
+
finishReason: { unified: 'stop', raw: 'stop' },
|
|
147
|
+
usage: {
|
|
148
|
+
inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
|
|
149
|
+
outputTokens: { total: 0, text: 0, reasoning: 0 },
|
|
150
|
+
},
|
|
151
|
+
harnessMetadata: { pi: { inferredStep: true } },
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function finishPiApprovalStep(
|
|
157
|
+
state: PiTranslatorState,
|
|
158
|
+
toolCallId: string,
|
|
159
|
+
): HarnessV1StreamPart[] {
|
|
160
|
+
state.stepOpen = true;
|
|
161
|
+
state.pendingStepToolCallIds.delete(toolCallId);
|
|
162
|
+
return finishStep(state);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function extractPiToolCallIds(message: PiSessionEvent['message']): string[] {
|
|
166
|
+
if (!message || message.role !== 'assistant') return [];
|
|
167
|
+
if (!Array.isArray(message.content)) return [];
|
|
168
|
+
return message.content.flatMap(part => {
|
|
169
|
+
if (!part || typeof part !== 'object') return [];
|
|
170
|
+
const block = part as Record<string, unknown>;
|
|
171
|
+
if (block.type !== 'toolCall') return [];
|
|
172
|
+
const id = block.id ?? block.toolCallId;
|
|
173
|
+
return typeof id === 'string' && id.length > 0 ? [id] : [];
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
133
177
|
/**
|
|
134
178
|
* Translate a single Pi `session.subscribe` event into zero or more
|
|
135
179
|
* `HarnessV1StreamPart`s, updating the translator state in place. Returns
|
|
@@ -153,6 +197,10 @@ export function translatePiEvent(
|
|
|
153
197
|
return [];
|
|
154
198
|
}
|
|
155
199
|
state.promptStarted = true;
|
|
200
|
+
if (event.type === 'message_start') {
|
|
201
|
+
state.stepOpen = true;
|
|
202
|
+
state.pendingStepToolCallIds.clear();
|
|
203
|
+
}
|
|
156
204
|
state.streamedAssistantText = '';
|
|
157
205
|
state.currentTextId = undefined;
|
|
158
206
|
state.currentReasoningId = undefined;
|
|
@@ -244,6 +292,14 @@ export function translatePiEvent(
|
|
|
244
292
|
state.reasoningStarted = false;
|
|
245
293
|
state.currentReasoningId = undefined;
|
|
246
294
|
}
|
|
295
|
+
if (event.type === 'message_end') {
|
|
296
|
+
for (const toolCallId of extractPiToolCallIds(event.message)) {
|
|
297
|
+
state.pendingStepToolCallIds.add(toolCallId);
|
|
298
|
+
}
|
|
299
|
+
} else {
|
|
300
|
+
state.pendingStepToolCallIds.clear();
|
|
301
|
+
parts.push(...finishStep(state));
|
|
302
|
+
}
|
|
247
303
|
return parts;
|
|
248
304
|
}
|
|
249
305
|
|
|
@@ -287,6 +343,7 @@ export function translatePiEvent(
|
|
|
287
343
|
>['result'])
|
|
288
344
|
: unwrapPiToolResult(event);
|
|
289
345
|
state.hostToolResults.delete(event.toolCallId);
|
|
346
|
+
state.pendingStepToolCallIds.delete(event.toolCallId);
|
|
290
347
|
return [
|
|
291
348
|
{
|
|
292
349
|
type: 'tool-result',
|
|
@@ -295,6 +352,7 @@ export function translatePiEvent(
|
|
|
295
352
|
result,
|
|
296
353
|
...(event.isError ? { isError: true } : {}),
|
|
297
354
|
} as HarnessV1StreamPart,
|
|
355
|
+
...finishStep(state),
|
|
298
356
|
];
|
|
299
357
|
}
|
|
300
358
|
|