import type { ImageContent } from "@earendil-works/pi-ai"; import type { FabricScope } from "../protocol.js"; import type { FabricKernel } from "../runtime/kernel.js"; import type { FabricThinking } from "../thinking.js"; import type { FabricAgentLineage, FabricWritePolicy } from "./child-env.js"; import type { FabricTraceContextV1 } from "./trace-context.js"; import type { AgentChildQuestionResponse, AgentUsage } from "./types.js"; export type BuiltInFabricAgentRunner = "pi" | "pi-durable" | "claude" | "veda"; /** * What a runner honors. Fabric refuses a request that needs an undeclared * capability before admission, budget, or worktree side effects. */ export interface FabricRunnerCapabilities { /** The child runs Fabric itself (`recursive: true`, fabric_exec in full code mode). */ recursiveFabric: boolean; steer: boolean; followUp: boolean; /** Long-lived sessions for persistent actors. */ persistentSessions: boolean; /** Explicit `kernel` choices. */ kernels: boolean; /** Session seeds: trajectory handoff and `seed: "branch"`. */ handoff: boolean; modelDiscovery: boolean; imageInput: boolean; compaction: boolean; /** Routed child dialogs (`agents.childQuestions: "route"`). */ questions: boolean; /** Hosted runs that can park and resume (`sleep`/`wake`). */ sleep: boolean; /** Write confinement (`readOnly`, `writableRoots`, `shell`). */ writePolicy: boolean; } export interface FabricRunnerModelInfo { runner: string; provider: string; id: string; name: string; key: string; [key: string]: unknown; } export interface FabricRunnerModelContext { cwd: string; refresh: boolean; } /** Launch facts shared by worker and hosted runners. All values are JSON. */ export interface FabricRunnerLaunchContext { /** Fabric run id. Hosted runners use it as the idempotency key. */ id: string; name: string; task: string; cwd: string; runDirectory: string; residency: "session" | "durable"; /** Run deadline in epoch milliseconds. */ deadlineAt: number; depth: number; lineage: FabricAgentLineage; /** W3C trace context an extension supplied for this run; export it as TRACEPARENT/TRACESTATE. */ traceContext?: FabricTraceContextV1; tools: readonly string[]; model?: string; thinking?: FabricThinking; kernel?: FabricKernel; recursive?: boolean; /** Present only for runners declaring `imageInput`. */ images?: readonly ImageContent[]; schema?: Record; systemPrompt?: string; /** Pi session file seeding the run; present only for runners declaring `handoff`. */ sessionFile?: string; /** Effective confinement; present only for runners declaring `writePolicy`. */ writePolicy?: FabricWritePolicy; actorId?: string; actorName?: string; /** Host-issued scope narrowed for this run (`pi-fabric/scope`); absent for unscoped sessions. */ scope?: Readonly; } export interface FabricWorkerLaunchContext extends FabricRunnerLaunchContext { files: { taskFile: string; statusFile: string; lifecycleFile: string; logFile: string; steerFile: string; schemaFile?: string; imagesFile?: string; }; /** Fabric's own Pi/Claude/Veda worker launch, for adapters that wrap it. */ fabricWorker: { workerPath: string; workerArguments: readonly string[]; }; } export interface FabricWorkerLaunch { workerPath: string; workerArguments: string[]; } export interface FabricHostedRunContext extends FabricRunnerLaunchContext { /** Equal to `id`; submitting twice with one key must start at most one run. */ idempotencyKey: string; } export type FabricHostedLiveness = "running" | "sleeping" | "settled" | "cancelled" | "interrupted" | "unknown"; export type FabricRunStopReason = "requested" | "timeout" | "shutdown"; export interface FabricHostedProgress { turns?: number; toolCalls?: number; /** null clears the current tool. */ currentTool?: string | null; /** Latest assistant text; Fabric keeps a bounded tail. */ text?: string; } /** Events appended to the run's transcript log (`events.jsonl`). */ export type FabricTranscriptEvent = { type: "message_end"; message: { role: "user" | "assistant"; content: string | Array<{ type: "text"; text: string; }>; }; } | { type: "tool_execution_start"; toolCallId?: string; toolName: string; args?: unknown; } | { type: "tool_execution_end"; toolCallId?: string; toolName: string; result?: unknown; isError?: boolean; } | { type: "extension_error"; error: string; }; export interface FabricRunnerQuestion { method: "select" | "confirm" | "input" | "editor"; title: string; message?: string; options?: string[]; placeholder?: string; prefill?: string; timeoutMs?: number; } export type FabricRunnerAnswer = AgentChildQuestionResponse; export interface FabricHostedReporter { progress(update: FabricHostedProgress): void; /** Cumulative usage for the whole run; Fabric records the increase. */ usage(total: AgentUsage): void; transcript(event: FabricTranscriptEvent): void; /** Routed like a Pi child dialog: direct UI when available, else a decision. */ question(question: FabricRunnerQuestion): Promise; finish(result: { status: "completed" | "failed" | "stopped"; output: string; structured?: unknown; }): void; /** Fabric never retries; `retryable` is reported to the caller only. */ fail(failure: { error: string; retryable?: boolean; }): void; } interface FabricRunnerBase { readonly id: string; readonly label: string; readonly capabilities: Readonly; /** * Absolute path of an ES module that registers this adapter when imported. * Required for `residency: "durable"`: the resident host imports it before * launching or re-attaching the run. */ readonly residentModule?: string; models?(context: FabricRunnerModelContext): readonly FabricRunnerModelInfo[] | Promise; defaultModel?(): string | undefined; normalizeModel?(model: string): string | Promise; mapTools?(tools: readonly string[]): readonly string[] | Promise; } /** Fabric spawns `workerPath` under the selected transport; see "Worker protocol". */ export interface FabricWorkerRunner extends FabricRunnerBase { readonly kind: "worker"; launch(context: FabricWorkerLaunchContext): FabricWorkerLaunch | Promise; /** Called before the transport kills the process. */ stop?(run: { id: string; runDirectory: string; }): void | Promise; } /** The adapter owns execution (for example a daemon); Fabric spawns no process. */ export interface FabricHostedRunner extends FabricRunnerBase { readonly kind: "hosted"; /** Pure: returns a JSON locator (at most 8 KiB) that Fabric persists before `start`. */ prepare(context: FabricHostedRunContext): unknown; start(locator: unknown, context: FabricHostedRunContext, reporter: FabricHostedReporter): void | Promise; attach(locator: unknown, context: FabricHostedRunContext, reporter: FabricHostedReporter): void | Promise; liveness(locator: unknown): FabricHostedLiveness | Promise; stop(locator: unknown, reason: FabricRunStopReason): { confirmed: boolean; } | Promise<{ confirmed: boolean; }>; abort?(locator: unknown, reason: FabricRunStopReason): void | Promise; sleep?(locator: unknown): void | Promise; wake?(locator: unknown): void | Promise; steer?(locator: unknown, message: string, data?: unknown): void | Promise; followUp?(locator: unknown, message: string, data?: unknown): void | Promise; } export type FabricRunnerAdapter = FabricWorkerRunner | FabricHostedRunner; /** Canonical built-in runner ids; src/config.ts inlines the same set. */ export declare const BUILT_IN_RUNNER_IDS: ReadonlySet; /** Canonical runner id syntax; eager modules inline an identical copy. */ export declare const RUNNER_ID_PATTERN: RegExp; export declare const isFabricRunnerId: (value: unknown) => value is string; /** * Register a runner for this process. Registration is process-local: a durable * run needs the adapter registered in the resident host too (`residentModule`). * Returns an unregister function. */ export declare const registerAgentRunner: (adapter: FabricRunnerAdapter) => (() => void); export declare const getAgentRunner: (id: string) => FabricRunnerAdapter | undefined; export declare const listAgentRunners: () => readonly FabricRunnerAdapter[]; export declare const requireAgentRunner: (id: unknown) => FabricRunnerAdapter; export {}; //# sourceMappingURL=runner-registry.d.ts.map