import { DEFAULT_SEAT_PROFILE, type SeatProfile } from "./channel-profile.js"; const PI_SDK_PACKAGE = "@earendil-works/pi-coding-agent"; /** Complete, serializable input required to run one embedded seat again. */ export type SeatSpec

= { provider: string; model: string; lens: string; lensPrompt: string; /** Diff base for change review. Repository audits omit it. */ baseRef?: string; scopingNote?: string; /** Untrusted records rendered after the role prompt, never in the binding scope. */ dataAppendix?: string; worktree: string; extraExtensionPaths?: string[]; profile?: P; expectedIds?: string[]; cycle?: number; }; export type SeatTool = { name: string }; export type SdkSession = { prompt: (text: string) => Promise; abort: () => Promise; dispose: () => void; getSessionStats: () => { tokens: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number; }; cost: number; }; }; export type SdkSeatSession = { session: SdkSession }; type PiSdk = { ModelRuntime: { create: () => Promise<{ getModel: (provider: string, model: string) => unknown; getAuth: (model: unknown) => Promise; }>; }; SettingsManager: { inMemory: (settings?: unknown) => unknown }; SessionManager: { inMemory: (cwd?: string) => unknown }; DefaultResourceLoader: new ( options: Record, ) => { reload: () => Promise; getExtensions: () => { errors: Array<{ error: string }> }; }; getAgentDir: () => string; createAgentSession: ( options: Record, ) => Promise; }; export type SdkSeatSessionInput = { spec: SeatSpec; tools: SeatTool[]; confinementGuard: (event: { toolName: string; input: Record; }) => { block: true; reason: string } | undefined; sdk?: PiSdk; }; /** Test seam and dynamic peer resolution for Pi's extension runtime. */ async function loadPiSdk(): Promise { return (await import(PI_SDK_PACKAGE)) as PiSdk; } function profileFor(spec: SeatSpec): SeatProfile { return spec.profile ?? DEFAULT_SEAT_PROFILE; } /** * Opens one isolated in-memory SDK session. All ambient resources are * suppressed, while explicit external extensions remain available through the * loader's temporary extension path mechanism. No host UI binding is made, * so model output cannot be written to host interactive streams. */ export async function createSdkSeatSession( input: SdkSeatSessionInput, ): Promise { const sdk = input.sdk ?? (await loadPiSdk()); const runtime = await sdk.ModelRuntime.create(); const model = runtime.getModel(input.spec.provider, input.spec.model); if (model === undefined) { throw new Error( `seat model is not configured: ${input.spec.provider}/${input.spec.model}`, ); } const auth = await runtime.getAuth(model); if (auth === undefined) { throw new Error( `seat model is not authenticated: ${input.spec.provider}/${input.spec.model}`, ); } const profile = profileFor(input.spec); const settingsManager = sdk.SettingsManager.inMemory({}); const loader = new sdk.DefaultResourceLoader({ cwd: input.spec.worktree, agentDir: sdk.getAgentDir(), settingsManager, additionalExtensionPaths: input.spec.extraExtensionPaths ?? [], noExtensions: true, noSkills: true, noPromptTemplates: true, noThemes: true, noContextFiles: true, systemPrompt: profile.systemPrompt, extensionFactories: [ (pi: { on: (event: string, handler: unknown) => void }) => pi.on("tool_call", input.confinementGuard), ], }); await loader.reload(); const extensionErrors = loader.getExtensions().errors; if (extensionErrors.length > 0) { throw new Error( `seat extension failed to load: ${extensionErrors[0].error}`, ); } return sdk.createAgentSession({ cwd: input.spec.worktree, modelRuntime: runtime, model, settingsManager, sessionManager: sdk.SessionManager.inMemory(input.spec.worktree), resourceLoader: loader, noTools: "all", tools: [...profile.tools], customTools: input.tools, }); }