/** * Pi Loop Extension - Type Definitions * * Core types for loop definitions, runs, nodes, gates, transitions, and evidence. */ // --------------------------------------------------------------------------- // Loop Definition // --------------------------------------------------------------------------- export type NodeKind = "code" | "llm" | "room" | "gate" | "evaluator" | "approval" | "wait" | "side_effect" | "finalizer"; export type NodeStatus = "pending" | "running" | "completed" | "failed" | "skipped"; export type RunStatus = "running" | "paused" | "completed" | "failed" | "cancelled" | "needs_attention"; export type GateVerdict = "pass" | "correctable" | "uncertain" | "terminal"; export type TransitionTarget = | { type: "node"; nodeId: string } | { type: "retry" } | { type: "approval" } | { type: "evaluator" } | { type: "finalizer" } | { type: "fail" } | { type: "complete" }; export interface TransitionRule { fromGateVerdict: GateVerdict; target: TransitionTarget; feedback?: string; // optional feedback to include in steering } export interface RetryPolicy { maxAttempts: number; backoffMs?: number; onExhausted?: "fail" | "approval" | "needs_attention"; } export interface Budget { maxAttempts?: number; maxWallClockMs?: number; maxTurns?: number; maxToolCalls?: number; maxRepeatedCommandCount?: number; maxSteeringEvents?: number; maxCost?: number; } export interface ToolPolicy { allowedTools: string[]; prohibitedTools?: string[]; prohibitedPatterns?: string[]; // regex patterns for prohibited commands } export interface SteeringRule { trigger: { type: "repeated_command_failure" | "no_tool_use" | "too_many_edits_no_validation" | "reading_too_broad" | "forbidden_action" | "context_too_large" | "stalled"; maxCount?: number; idleTurns?: number; idleMs?: number; }; message: string; } export interface InputField { name: string; type: "string" | "number" | "boolean" | "select"; description: string; required?: boolean; default?: unknown; options?: string[]; // for select type } export interface RoomWorkerDefinition { id: string; label?: string; role?: string; model?: { provider: string; id: string; thinking?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh"; }; allowedTools?: string[]; prompt?: string; concurrency?: number; } export interface RoomDefinition { /** Registered room handler name. The handler owns packet building, worker execution, reduction, and artifacts. */ handler: string; workers?: RoomWorkerDefinition[]; concurrency?: number; packetStrategy?: "all" | "per_l1" | "per_l2" | "custom"; reducer?: string; } export interface NodeDefinition { id: string; kind: NodeKind; label: string; goal: string; allowedTools?: string[]; prohibitedActions?: string[]; expectedOutput?: string; successCriteria?: string[]; timeout?: number; // ms retryPolicy?: RetryPolicy; steeringRules?: SteeringRule[]; input?: InputField[]; model?: { provider: string; id: string; thinking?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh"; }; /** For code nodes: the handler function name (registered on the runtime) */ handler?: string; /** For room nodes: worker-room configuration and registered handler name */ room?: RoomDefinition; /** For LLM nodes: the instruction template sent to the agent */ instruction?: string; } export interface LoopDefinition { id: string; version: string; label: string; description: string; trigger: { type: "command" | "event" | "auto"; commandName?: string; inputShape?: InputField[]; }; nodes: NodeDefinition[]; transitions: TransitionRule[][]; // one array per node, indexed by node position budgets?: Budget; toolPolicies?: Record; // nodeId -> policy finalOutput?: Record; } // --------------------------------------------------------------------------- // Run State // --------------------------------------------------------------------------- export interface TokenUsageMetrics { input: number; output: number; cacheRead: number; cacheWrite: number; totalTokens: number; cost: number; } export interface NodeAttemptMetrics { durationMs?: number; tokens?: TokenUsageMetrics; childWorkers?: Array<{ workerId: string; page?: number; attempt?: number; durationMs?: number; tokens?: TokenUsageMetrics; sessionFile?: string; }>; } export interface NodeAttempt { attemptNumber: number; startedAt: number; endedAt?: number; result?: NodeResult; steeringEvents: SteeringEvent[]; toolCalls: ToolCallRecord[]; status: NodeStatus; metrics?: NodeAttemptMetrics; } export interface SteeringEvent { timestamp: number; message: string; triggerType: string; } export interface ToolCallRecord { toolName: string; input: unknown; timestamp: number; isError?: boolean; duration?: number; } export interface NodeResult { status: "ready_for_validation" | "completed" | "failed" | "skipped"; summary?: string; artifacts?: Record; changedFiles?: string[]; commandsRun?: string[]; risks?: string[]; confidence?: "low" | "medium" | "high"; message?: string; // raw report message } export interface GateResult { verdict: GateVerdict; feedback?: string; details?: Record; failedCriteria?: string[]; passedCriteria?: string[]; } export interface RunState { id: string; loopId: string; status: RunStatus; currentNodeIndex: number; currentAttemptNumber: number; nodes: NodeInstanceState[]; startedAt: number; updatedAt: number; completedAt?: number; artifacts: Record; evidence: EvidenceSummary; input?: Record; totalTurns: number; totalToolCalls: number; steeringEventsTotal: number; } export interface NodeInstanceState { nodeDef: NodeDefinition; status: NodeStatus; attempts: NodeAttempt[]; startedAt?: number; completedAt?: number; gateResult?: GateResult; result?: NodeResult; } export interface EvidenceSummary { toolCalls: ToolCallRecord[]; commandsRun: Array<{ command: string; exitCode?: number; timestamp: number }>; filesRead: string[]; filesChanged: string[]; errorCount: number; repeatedCommands: Record; warnings: string[]; timestamps: { startedAt: number; lastActivity: number; }; } // --------------------------------------------------------------------------- // Session Storage Types // --------------------------------------------------------------------------- export interface LoopSessionEntry { version: 1; run: RunState; } // --------------------------------------------------------------------------- // Loop Report (from the loop_report tool) // --------------------------------------------------------------------------- export interface LoopReport { runId: string; nodeId: string; status: "ready_for_validation" | "completed" | "failed"; summary: string; artifacts?: Record; changedFiles?: string[]; commandsRun?: string[]; risks?: string[]; confidence?: "low" | "medium" | "high"; } // --------------------------------------------------------------------------- // Demo Loop Definition // --------------------------------------------------------------------------- export function createDemoLoopDefinition(): LoopDefinition { return { id: "demo", version: "1.0.0", label: "Demo Loop", description: "A minimal demo loop: code -> gate -> finalizer", trigger: { type: "command", commandName: "demo", inputShape: [ { name: "message", type: "string", description: "A message to process", required: false, default: "hello" }, ], }, nodes: [ { id: "prepare", kind: "code", label: "Prepare", goal: "Prepare the input data for processing", handler: "prepareHandler", expectedOutput: "A normalized message artifact", successCriteria: ["Artifact contains a 'message' field"], }, { id: "validate", kind: "gate", label: "Validate", goal: "Verify the prepared data meets requirements", successCriteria: ["Message is non-empty", "Message is a string"], }, { id: "finish", kind: "finalizer", label: "Finish", goal: "Complete the loop and write the final result", }, ], transitions: [ // Transitions for node 0 (prepare) [ { fromGateVerdict: "pass", target: { type: "node", nodeId: "validate" } }, { fromGateVerdict: "correctable", target: { type: "retry" }, feedback: "Fix the output" }, { fromGateVerdict: "terminal", target: { type: "fail" } }, ], // Transitions for node 1 (validate) [ { fromGateVerdict: "pass", target: { type: "node", nodeId: "finish" } }, { fromGateVerdict: "correctable", target: { type: "retry" }, feedback: "Fix validation issues" }, { fromGateVerdict: "terminal", target: { type: "fail" } }, ], // Transitions for node 2 (finish) [ { fromGateVerdict: "pass", target: { type: "complete" } }, { fromGateVerdict: "terminal", target: { type: "fail" } }, ], ], }; } /** * Create a demo LLM loop definition that exercises the supervised LLM node. */ export function createDemoLlmLoopDefinition(): LoopDefinition { return { id: "demo-llm", version: "1.0.0", label: "Demo LLM Loop", description: "A demo loop with a supervised LLM node: analyze -> gate -> finalizer", trigger: { type: "command", commandName: "demo-llm", inputShape: [ { name: "question", type: "string", description: "A question to analyze", required: false, default: "What is the capital of France?" }, ], }, nodes: [ { id: "analyze", kind: "llm", label: "Analyze", goal: "Analyze the question and prepare a response", allowedTools: ["read", "bash", "grep", "find", "ls", "loop_report"], instruction: `You are in a supervised LLM node of a loop. Your goal: {goal} Analyze the input question thoroughly. You may use tools to research if needed. When you are ready, submit your findings using the loop_report tool. In your report include: - summary: your findings - confidence: "low", "medium", or "high" - any commands you ran - any risks you see`, successCriteria: ["Report contains a summary", "Confidence level is provided"], }, { id: "verify", kind: "gate", label: "Verify Analysis", goal: "Verify the analysis report is complete", successCriteria: ["Report summary exists", "Confidence is provided", "No errors in execution"], }, { id: "complete", kind: "finalizer", label: "Complete", goal: "Finalize the loop and present results", }, ], transitions: [ [ { fromGateVerdict: "pass", target: { type: "node", nodeId: "verify" } }, { fromGateVerdict: "correctable", target: { type: "retry" }, feedback: "Provide a more complete report" }, { fromGateVerdict: "terminal", target: { type: "fail" } }, ], [ { fromGateVerdict: "pass", target: { type: "node", nodeId: "complete" } }, { fromGateVerdict: "correctable", target: { type: "retry" }, feedback: "Fix validation issues" }, { fromGateVerdict: "terminal", target: { type: "fail" } }, ], [ { fromGateVerdict: "pass", target: { type: "complete" } }, { fromGateVerdict: "terminal", target: { type: "fail" } }, ], ], }; }