import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import type { AgentRequest, AgentSession } from "../engine/types.ts"; import { type ModelRegistry } from "./pi-agent-messages.ts"; import { type SubagentSpawner } from "./subagent-process.ts"; export type AgentStarter = (request: AgentRequest) => AgentSession; /** What to spawn (the spawner's first two arguments) for a background subagent, given the CLI args after the binary name. */ export type PiInvocationResolver = (args: readonly string[]) => { command: string; args: readonly string[]; }; /** * Respawn the CURRENTLY RUNNING harness process itself, so a background subagent always lands in the * same host it was launched from (same provider registry, same auth) — never a different product. * Three cases, in order, matching upstream's `getPiInvocation`: * 1. Dev/interpreter invocation (`node`/`bun script.ts ...`): `process.argv[1]` is a real file on * disk → respawn `[process.execPath, thatScript, ...args]`. * 2. A compiled single-file executable (e.g. kimchi's built binary, or `pi`'s): `process.execPath`'s * basename is not a generic runtime name → respawn `process.execPath` directly. * 3. Last resort — matches the previous hardcoded behaviour: literal `"pi"` on `PATH`. */ export declare function resolvePiInvocation(args: readonly string[]): { command: string; args: readonly string[]; }; export declare function inheritedPermissionArgs(argv?: readonly string[]): string[]; /** * The `-e`/`--extension` flags the CURRENT process was launched with, which a step child needs too if it * is to register this extension's output tools (step-output-tools.ts). * * Same allowlist discipline, and the same direction of safety, as {@link inheritedPermissionArgs}: a flag * has to be in the parent's own argv to be forwarded. A harness that loaded this extension some other way * (an installed package the child discovers on its own) needs nothing here; one that loaded it by path and * forwards nothing gets no tools in the child, and every step under an output contract then FAILS — * there is no text channel behind it, so this is a hard dependency, not a graceful degradation. */ export declare function inheritedExtensionArgs(argv?: readonly string[]): string[]; /** * Create the PI agent bridge. Call once per extension instance (registers one `agent_end` listener), * then obtain a per-invocation `AgentStarter` bound to the command's model registry AND to the * directory that invocation's sessions belong in. The directory arrives at BIND time, not here: this * runs at extension LOAD, when no `ctx` — and therefore no session directory — exists yet, while every * `ExtensionCommandContext`/`ExtensionContext` the harness hands a handler carries one. * * `invocationResolver` defaults to {@link resolvePiInvocation}; tests inject a fixed stub instead of * depending on the live process's own argv/execPath. `spawnSubagent` defaults to * {@link subagentSpawner} — a real child process — and is the seam tests drive a scripted * stdout/stderr through. */ export declare function createPiAgentBridge(pi: ExtensionAPI, invocationResolver?: PiInvocationResolver, spawnSubagent?: SubagentSpawner): (modelRegistry: ModelRegistry, sessionsDir: string) => AgentStarter; //# sourceMappingURL=pi-agent.d.ts.map