Something went wrong. Try again.
Pi extension for async subagent delegation with truncation, artifacts, and session sharing
Something went wrong. Try again.
4.4 kB · 124 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125import { createHash } from "node:crypto";import * as fs from "node:fs";import type { AgentConfig } from "../agents/agents.ts";
export const AGENT_DEFINITION_PROJECTION_VERSION = 1 as const;export const LAUNCH_BINDING_PROJECTION_VERSION = 1 as const;
function stableJson(value: unknown): string { if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`; if (value && typeof value === "object") { return `{${Object.entries(value as Record<string, unknown>) .filter(([, entry]) => entry !== undefined) .sort(([a], [b]) => a.localeCompare(b)) .map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`) .join(",")}}`; } return JSON.stringify(value);}
function sha256(value: unknown): string { return createHash("sha256").update(stableJson(value)).digest("hex");}
function fileDigest(filePath: string): string | undefined { try { return createHash("sha256").update(fs.readFileSync(filePath)).digest("hex"); } catch { return undefined; }}
/** Public-safe, deterministic evidence for the parsed launch-affecting agent definition. */export function projectAgentDefinition(agent: AgentConfig): Record<string, unknown> { return { version: AGENT_DEFINITION_PROJECTION_VERSION, name: agent.name, localName: agent.localName, packageName: agent.packageName, filePath: agent.filePath, fileContentDigest: fileDigest(agent.filePath), runner: agent.runner, systemPrompt: agent.systemPrompt, systemPromptMode: agent.systemPromptMode, inheritProjectContext: agent.inheritProjectContext, inheritSkills: agent.inheritSkills, model: agent.model, fallbackModels: agent.fallbackModels, thinking: agent.thinking, tools: agent.tools, mcpDirectTools: agent.mcpDirectTools, extensions: agent.extensions, subagentOnlyExtensions: agent.subagentOnlyExtensions, skills: agent.skills, skillPath: agent.skillPath, output: agent.output, defaultReads: agent.defaultReads, defaultProgress: agent.defaultProgress, defaultContext: agent.defaultContext, defaultAsync: agent.defaultAsync, defaultTimeoutMs: agent.defaultTimeoutMs, defaultTurnBudget: agent.defaultTurnBudget, defaultAcceptance: agent.defaultAcceptance, acceptanceRole: agent.acceptanceRole, interactive: agent.interactive, maxSubagentDepth: agent.maxSubagentDepth, completionGuard: agent.completionGuard, toolBudget: agent.toolBudget, memory: agent.memory, };}
export function agentDefinitionDigest(agent: AgentConfig): string { return sha256(projectAgentDefinition(agent));}
export interface LaunchBindingInput { definitionDigest: string; /** Caller task; runtime acceptance/output task annotations are explicitly outside the preflight-known subset. */ task?: string; model?: string; modelCandidates?: string[]; thinking?: string; systemPrompt?: string | null; systemPromptMode?: AgentConfig["systemPromptMode"]; inheritProjectContext: boolean; inheritSkills: boolean; skills?: string[]; tools?: string[]; extensions?: string[]; subagentOnlyExtensions?: string[]; mcpDirectTools?: string[]; outputPath?: string; outputMode?: string; structuredOutputSchema?: unknown;}
/** Canonical projection of the resolved inputs handed to the child. */export function projectLaunchBinding(input: LaunchBindingInput): Record<string, unknown> { return { version: LAUNCH_BINDING_PROJECTION_VERSION, definitionDigest: input.definitionDigest, taskDigest: input.task === undefined ? undefined : sha256(input.task), // The ordered candidate set already contains each attempted model; keeping only // this set makes retries correlate to the same preflight binding. modelCandidates: input.modelCandidates, thinking: input.thinking, systemPromptDigest: input.systemPrompt === undefined || input.systemPrompt === null ? undefined : sha256(input.systemPrompt), systemPromptMode: input.systemPromptMode, inheritProjectContext: input.inheritProjectContext, inheritSkills: input.inheritSkills, skills: input.skills, tools: input.tools, extensions: input.extensions, subagentOnlyExtensions: input.subagentOnlyExtensions, mcpDirectTools: input.mcpDirectTools, outputPath: input.outputPath, outputMode: input.outputMode, structuredOutputSchema: input.structuredOutputSchema, };}
export function launchBindingDigest(input: LaunchBindingInput): string { return sha256(projectLaunchBinding(input));}