@skaile/workspaces 2.9.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +17 -6
- package/dist/{asset-feeds-EO2QDJ4C.js → asset-feeds-3XCKB542.js} +4 -4
- package/dist/{asset-feeds-EO2QDJ4C.js.map → asset-feeds-3XCKB542.js.map} +1 -1
- package/dist/asset-manager/index.js +1 -1
- package/dist/bridge/drivers/claude-sdk.js +6 -206
- package/dist/bridge/drivers/claude-sdk.js.map +1 -1
- package/dist/bridge/drivers/codex.js +2 -2
- package/dist/bridge/drivers/continue.js +2 -2
- package/dist/bridge/drivers/echo.js +1 -1
- package/dist/bridge/drivers/gemini.js +4 -4
- package/dist/bridge/drivers/goose.js +2 -2
- package/dist/bridge/drivers/omp.js +1 -1
- package/dist/bridge/drivers/opencode.js +2 -2
- package/dist/bridge/drivers/qwen.js +4 -4
- package/dist/bridge/index.js +14 -4
- package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
- package/dist/bridge/src/drivers/resume-probe.d.ts +54 -0
- package/dist/bridge/src/drivers/resume-probe.d.ts.map +1 -0
- package/dist/bridge/src/drivers/scrub-transcript.d.ts +17 -0
- package/dist/bridge/src/drivers/scrub-transcript.d.ts.map +1 -1
- package/dist/bridge/src/index.d.ts +1 -0
- package/dist/bridge/src/index.d.ts.map +1 -1
- package/dist/bridge/src/models.d.ts +59 -0
- package/dist/bridge/src/models.d.ts.map +1 -1
- package/dist/{chunk-ZR2X4SIG.js → chunk-2U4ISGE2.js} +5 -5
- package/dist/{chunk-ZR2X4SIG.js.map → chunk-2U4ISGE2.js.map} +1 -1
- package/dist/chunk-46LE3GNY.js +296 -0
- package/dist/chunk-46LE3GNY.js.map +1 -0
- package/dist/{chunk-INHE5U74.js → chunk-5QGMEPUX.js} +8 -12
- package/dist/chunk-5QGMEPUX.js.map +1 -0
- package/dist/{chunk-TU7JDHKS.js → chunk-7HXS7WZF.js} +2 -2
- package/dist/{chunk-TU7JDHKS.js.map → chunk-7HXS7WZF.js.map} +1 -1
- package/dist/{chunk-OHLKWUO3.js → chunk-7KFN2EPR.js} +12 -4
- package/dist/chunk-7KFN2EPR.js.map +1 -0
- package/dist/{chunk-YFAED6OB.js → chunk-BENN6MO4.js} +4 -4
- package/dist/{chunk-YFAED6OB.js.map → chunk-BENN6MO4.js.map} +1 -1
- package/dist/{chunk-AGFAOSCZ.js → chunk-F5VREBV2.js} +8 -5
- package/dist/chunk-F5VREBV2.js.map +1 -0
- package/dist/{chunk-L3TS7ZO4.js → chunk-FP7DNGX6.js} +3 -3
- package/dist/{chunk-L3TS7ZO4.js.map → chunk-FP7DNGX6.js.map} +1 -1
- package/dist/{chunk-E5VGAW4E.js → chunk-H26KDA7J.js} +230 -9
- package/dist/chunk-H26KDA7J.js.map +1 -0
- package/dist/{chunk-VNIKF66R.js → chunk-HA2H3FLE.js} +4 -4
- package/dist/{chunk-VNIKF66R.js.map → chunk-HA2H3FLE.js.map} +1 -1
- package/dist/{chunk-5LA4XI4Y.js → chunk-HNR2IT34.js} +27 -13
- package/dist/chunk-HNR2IT34.js.map +1 -0
- package/dist/{chunk-BIKTLLLD.js → chunk-MJ6EME7A.js} +6 -6
- package/dist/{chunk-BIKTLLLD.js.map → chunk-MJ6EME7A.js.map} +1 -1
- package/dist/{chunk-ZXJKWA44.js → chunk-N4GFUWWC.js} +3 -3
- package/dist/{chunk-ZXJKWA44.js.map → chunk-N4GFUWWC.js.map} +1 -1
- package/dist/{chunk-UTHMTZEH.js → chunk-PT2ZUW2E.js} +2 -2
- package/dist/{chunk-UTHMTZEH.js.map → chunk-PT2ZUW2E.js.map} +1 -1
- package/dist/{chunk-XXDQHZJY.js → chunk-PUEHYNBT.js} +3 -3
- package/dist/{chunk-XXDQHZJY.js.map → chunk-PUEHYNBT.js.map} +1 -1
- package/dist/{chunk-HY3MBSNC.js → chunk-QFO4IYBZ.js} +2 -2
- package/dist/{chunk-HY3MBSNC.js.map → chunk-QFO4IYBZ.js.map} +1 -1
- package/dist/{chunk-UAIR3K6X.js → chunk-S5FV6ISY.js} +8 -5
- package/dist/chunk-S5FV6ISY.js.map +1 -0
- package/dist/{chunk-AFUOORJE.js → chunk-TARN55L3.js} +6 -6
- package/dist/{chunk-AFUOORJE.js.map → chunk-TARN55L3.js.map} +1 -1
- package/dist/{chunk-BMQKMOQY.js → chunk-V34ZEXSE.js} +61 -3
- package/dist/chunk-V34ZEXSE.js.map +1 -0
- package/dist/{chunk-QVFCDSRH.js → chunk-VBMY3VCW.js} +3 -3
- package/dist/{chunk-QVFCDSRH.js.map → chunk-VBMY3VCW.js.map} +1 -1
- package/dist/{chunk-XHSS3YHV.js → chunk-X73AMPOT.js} +16 -7
- package/dist/chunk-X73AMPOT.js.map +1 -0
- package/dist/{chunk-4PSDPZUG.js → chunk-ZGTM4BOU.js} +2 -2
- package/dist/{chunk-4PSDPZUG.js.map → chunk-ZGTM4BOU.js.map} +1 -1
- package/dist/cli/index.js +38 -38
- package/dist/connectors/index.js +11 -5
- package/dist/{ensure-sources-6ZOD45TO.js → ensure-sources-AST427RF.js} +4 -4
- package/dist/{ensure-sources-6ZOD45TO.js.map → ensure-sources-AST427RF.js.map} +1 -1
- package/dist/factory-assets/connectors/box.js +11 -5
- package/dist/factory-assets/connectors/deploy.js +11 -5
- package/dist/factory-assets/connectors/devserver.js +11 -5
- package/dist/factory-assets/connectors/flow/CONNECTOR.md +47 -6
- package/dist/factory-assets/connectors/flow/adapter.d.ts +5 -0
- package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/adapter.js +11 -5
- package/dist/factory-assets/connectors/flow/contract/flow.v2.schema.json +0 -6
- package/dist/factory-assets/connectors/flow/contract/normalize.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/contract/schema.d.ts +0 -4
- package/dist/factory-assets/connectors/flow/contract/schema.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/contract.js +2 -2
- package/dist/factory-assets/connectors/flow/engine/bindings.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/engine/node-shape.d.ts +7 -1
- package/dist/factory-assets/connectors/flow/engine/node-shape.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/engine/types.d.ts +12 -12
- package/dist/factory-assets/connectors/flow/engine/types.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/engine.js +3 -3
- package/dist/factory-assets/connectors/flow/index.d.ts +1 -0
- package/dist/factory-assets/connectors/flow/index.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/inline-sub-flow-host.d.ts +3 -0
- package/dist/factory-assets/connectors/flow/inline-sub-flow-host.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts +14 -0
- package/dist/factory-assets/connectors/flow/prompt-fragments.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/prompt-fragments.js +2 -2
- package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
- package/dist/factory-assets/connectors/flow/run-flow.js +12 -6
- package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts +99 -0
- package/dist/factory-assets/connectors/flow/subprompt-runner.d.ts.map +1 -0
- package/dist/factory-assets/connectors/flow.js +11 -5
- package/dist/factory-assets/connectors/git.js +11 -5
- package/dist/factory-assets/connectors/gmail.js +11 -5
- package/dist/factory-assets/connectors/googledrive.js +11 -5
- package/dist/factory-assets/connectors/local.js +11 -5
- package/dist/factory-assets/connectors/mattermost.js +11 -5
- package/dist/factory-assets/connectors/memory.js +11 -5
- package/dist/factory-assets/connectors/minio.js +11 -5
- package/dist/factory-assets/connectors/postgres.js +11 -5
- package/dist/factory-assets/connectors/s3.js +11 -5
- package/dist/factory-assets/connectors/sharepoint.js +11 -5
- package/dist/factory-assets/connectors/sqlite.js +11 -5
- package/dist/factory-assets/connectors/static-server.js +11 -5
- package/dist/factory-assets/connectors/tunnel.js +11 -5
- package/dist/factory-assets/connectors/webdav.js +11 -5
- package/dist/factory-assets/connectors/xstate-store.js +11 -5
- package/dist/factory-assets/connectors/xstate.js +11 -5
- package/dist/{flows-7N5AUUIS.js → flows-LQSVM45J.js} +3 -3
- package/dist/{flows-7N5AUUIS.js.map → flows-LQSVM45J.js.map} +1 -1
- package/dist/{helpers-HWLCANAK.js → helpers-IZDG57TR.js} +4 -4
- package/dist/{helpers-HWLCANAK.js.map → helpers-IZDG57TR.js.map} +1 -1
- package/dist/{library-publish-GSAIZCO3.js → library-publish-XGJ7IOU2.js} +9 -9
- package/dist/{library-publish-GSAIZCO3.js.map → library-publish-XGJ7IOU2.js.map} +1 -1
- package/dist/{open-library-ZB2STYC6.js → open-library-YDS66KLH.js} +8 -8
- package/dist/{open-library-ZB2STYC6.js.map → open-library-YDS66KLH.js.map} +1 -1
- package/dist/{project-EJFCLSHS.js → project-NR53RZOT.js} +5 -5
- package/dist/{project-EJFCLSHS.js.map → project-NR53RZOT.js.map} +1 -1
- package/dist/runner/index.js +15 -15
- package/dist/runner/src/serve.d.ts.map +1 -1
- package/dist/sdk/asset-manager.js +1 -1
- package/dist/sdk/bridge.js +14 -4
- package/dist/sdk/flow.js +3 -3
- package/dist/sdk/index.js +15 -15
- package/dist/sdk/runner.js +15 -15
- package/dist/{setup-RHWARBBB.js → setup-I5SLLHRA.js} +6 -6
- package/dist/{setup-RHWARBBB.js.map → setup-I5SLLHRA.js.map} +1 -1
- package/dist/{source-ILV6ZKWM.js → source-DDZKKQH2.js} +9 -9
- package/dist/{source-ILV6ZKWM.js.map → source-DDZKKQH2.js.map} +1 -1
- package/dist/{source-manifest-publish-QE2IFDRW.js → source-manifest-publish-OTVKHRX3.js} +10 -10
- package/dist/{source-manifest-publish-QE2IFDRW.js.map → source-manifest-publish-OTVKHRX3.js.map} +1 -1
- package/dist/tui/index.js +15 -15
- package/dist/types/src/lifecycle.d.ts +12 -0
- package/dist/types/src/lifecycle.d.ts.map +1 -1
- package/dist/workspace-plugin/adapters/mcp.js +1 -1
- package/dist/workspace-plugin/adapters/omp.js +3 -3
- package/dist/workspace-plugin/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-5LA4XI4Y.js.map +0 -1
- package/dist/chunk-AGFAOSCZ.js.map +0 -1
- package/dist/chunk-BMQKMOQY.js.map +0 -1
- package/dist/chunk-E5VGAW4E.js.map +0 -1
- package/dist/chunk-INHE5U74.js.map +0 -1
- package/dist/chunk-ISQWMBKD.js +0 -74
- package/dist/chunk-ISQWMBKD.js.map +0 -1
- package/dist/chunk-OHLKWUO3.js.map +0 -1
- package/dist/chunk-UAIR3K6X.js.map +0 -1
- package/dist/chunk-XHSS3YHV.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../bridge/src/logger.ts","../bridge/src/types.ts","../bridge/src/registry.ts"],"names":[],"mappings":"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","file":"chunk-HY3MBSNC.js","sourcesContent":["/**\n * Bridge-layer logger factory.\n *\n * Each driver creates its own Logger via `getBridgeLogger(subkind)` at\n * construction time. Falls back to an off-mode Logger (stdout only) when\n * no LogStore is registered — see @skaile/workspaces/core/logging for details.\n */\n\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type { Logger } from \"@skaile/workspaces/types\";\n\n/**\n * Construct a bridge-scoped Logger for a given driver subkind.\n *\n * Creates a `Logger` with `kind: \"bridge\"` and the specified `subkind`. Falls back to\n * an off-mode Logger (stdout only) when no `LogStore` is registered — see\n * `@skaile/workspaces/core/logging` for details. Each driver calls this once at construction\n * time; never re-construct per call.\n *\n * @param subkind - Driver id, e.g. `\"claude-sdk\"`, `\"omp\"`, `\"echo\"`, `\"codex\"`.\n * @returns A `Logger` scoped to `bridge:<subkind>`.\n * @docLink packages/bridge/api-reference#logger\n */\nexport function getBridgeLogger(subkind: string): Logger {\n return createLogger({ kind: \"bridge\", subkind });\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Span, TelemetryProvider, Trace } from \"@skaile/workspaces/telemetry\";\nimport type {\n Capability,\n CredentialMint,\n FlowExecution,\n RenderInvokedEvent,\n TokenUsage,\n} from \"@skaile/workspaces/types\";\nimport type { ModelEntry } from \"./models.js\";\n\n/**\n * Test-only hook injected by the runner so a no-LLM driver (the echo driver's\n * scripted-flow mode) can read flow state and drive flow-adapter mutations\n * without an SDK/MCP round-trip. The runner wires this in `createActiveFlow`\n * from the active FlowAdapter + handle.\n *\n * This is an internal runner↔driver interface — NOT part of any wire\n * protocol or flow contract. Production drivers ignore it.\n *\n * @see packages/bridge/drivers/echo — scripted-flow mode\n * @since 3.6.0\n */\nexport interface FlowTestDriverHook {\n /** Current flow execution snapshot, or `null` when no flow is active. */\n getState(): FlowExecution | null;\n /**\n * Execute a flow-adapter operation (`start_node`, `request_approval`,\n * `complete_node`, `request_input`, `skip_node`, `fail_node`, …). Returns\n * the adapter's JSON string result (or rejects on an illegal transition).\n */\n execute(op: string, args: Record<string, unknown>): Promise<string>;\n /**\n * Node IDs marked as mandatory approval gates. The scripted policy resolves\n * `auto` to `request_approval` for these even in autonomous mode, so hosts\n * can drive a mandatory gate deterministically. Optional — absent hooks\n * behave as if no node is mandatory.\n */\n mandatoryGates?(): string[];\n}\n\n/**\n * Minimal LLM tool descriptor used by the capability dispatch path. Mirrors\n * the runner's `LLMTool` shape so drivers can consume registry output without\n * importing `@skaile/workspaces/runner` (which would create a circular dep).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-tool\n */\nexport interface BridgeCapabilityTool {\n /** Capability name; used as the LLM-visible tool name. */\n name: string;\n /** Human/LLM-readable description. */\n description: string;\n /** JSON Schema for the tool's input parameters. */\n parameters: Record<string, unknown>;\n}\n\n/**\n * Render-cap event emission callback used by the bridge when the LLM invokes\n * a capability that carries a `render` spec. The runner provides the actual\n * sink (transport.send / sendEvent); the bridge only emits.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-render-emit\n */\nexport type BridgeRenderEmit = (event: RenderInvokedEvent) => void;\n\n/**\n * Text-event emission callback for render-capability fallbacks. When a\n * `RenderCapability` carries `render.fallback` and the LLM invokes it, the\n * bridge substitutes `{{prop}}` placeholders (top-level keys of `props`,\n * optional dotted-path traversal `{{user.name}}`) and pushes the rendered\n * string through this callback so clients without a render layer still see\n * a textual representation. No-op when `fallback` is absent.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-text-emit\n */\nexport type BridgeTextEmit = (text: string) => void;\n\n/**\n * Bundle of capability dispatch hooks. Registered into the driver via\n * `AgentConfig.capabilities`; the driver routes registered LLM tool calls\n * back into `invoke()` instead of using its native dispatch path.\n *\n * The runner constructs this from a `CapabilityRegistry` instance and threads\n * it through `createAgentSession()`. Drivers that don't yet implement\n * capability dispatch ignore the field — legacy v1 paths stay intact.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-hooks\n */\nexport interface BridgeCapabilityHooks {\n /** Build the LLM tool descriptor list from the registry. Called per turn so registration changes take effect. */\n composeTools(): BridgeCapabilityTool[];\n /** Resolve a wire-format Capability descriptor by name. Used by the bridge to inspect `fireAndForget` / `render`. */\n resolve(name: string): Capability | null;\n /** Validate input + dispatch through the registry. Logging is wired by the registry. */\n invoke(name: string, input: unknown): Promise<unknown>;\n /** Emit a render-invoked event. The runner forwards via the WebSocket transport. */\n emitRender?: BridgeRenderEmit;\n /** Emit a text fallback for render capabilities with `render.fallback`. */\n emitText?: BridgeTextEmit;\n /** Session id passed through to the runner's per-handler logger. */\n sessionId: string;\n}\n\n/**\n * Static metadata for a registered agent driver backend.\n *\n * Returned by {@link listDrivers} and exposed on every {@link AgentDriver} instance\n * via `driverInfo`.\n *\n * @docLink packages/bridge/concepts#driver-info\n */\nexport interface DriverInfo {\n /** Stable machine identifier used to look up the driver in the registry (e.g. `\"omp\"`, `\"claude-sdk\"`). */\n id: string;\n /** Human-readable display name shown in UIs and logs. */\n name: string;\n /** `true` when the driver can target any LLM provider; `false` for Anthropic-only drivers. */\n modelAgnostic: boolean;\n /**\n * `true` when the driver supports mid-stream abort via `abort()` without killing the process.\n * Drivers that return `false` can only be stopped via `kill()`.\n */\n supportsInBandAbort: boolean;\n}\n\n/**\n * Codex-specific tuning options passed through `DriverOptions.codex`.\n *\n * @remarks These are forwarded verbatim to the Codex driver and have no effect on other drivers.\n * @docLink packages/bridge/concepts#codex-driver-options\n */\nexport interface CodexDriverOptions {\n /** Controls whether Codex may auto-apply edits without user approval. */\n approvalPolicy?: \"never\" | \"on-request\" | \"on-failure\" | \"untrusted\";\n /** Filesystem sandbox level for the Codex process. */\n sandboxMode?: \"read-only\" | \"workspace-write\" | \"danger-full-access\";\n /** Reasoning budget passed to the model. */\n reasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n /** When `true`, the Codex sandbox is allowed to make outbound network requests. */\n networkAccessEnabled?: boolean;\n /** Extra directories made accessible to the Codex sandbox in addition to `cwd`. */\n additionalDirectories?: string[];\n}\n\n/**\n * Driver-specific configuration bag.\n *\n * Fields are keyed by driver ID so that callers can pass driver-specific options\n * through the common {@link AgentConfig} without breaking other drivers.\n *\n * @docLink packages/bridge/concepts#driver-options\n */\nexport interface DriverOptions {\n /** Codex-specific options. Ignored by all other drivers. */\n codex?: CodexDriverOptions;\n}\n\n/**\n * Configuration passed to a driver when it is created via {@link createDriver}.\n *\n * All fields are shared across drivers; driver-specific behaviour is documented\n * per field. Fields that are silently ignored by a driver are marked accordingly.\n *\n * @docLink packages/bridge/concepts#agent-config\n */\nexport interface AgentConfig {\n /** Absolute path to the working directory the agent operates in. */\n cwd: string;\n /**\n * LLM provider name (e.g. `\"anthropic\"`, `\"openai\"`, `\"google\"`).\n * Combined with `model` as `provider/model` for omp's `--model` flag.\n * Ignored by claude-sdk (always Anthropic).\n */\n provider?: string;\n /**\n * LLM model identifier (e.g. `\"claude-sonnet-4-5\"`, `\"gpt-4o\"`).\n * For omp: passed as `--model [provider/]model`.\n * For claude-sdk: passed as the `model` query option.\n */\n model?: string;\n /**\n * Provider API keys keyed by provider name (e.g. `{ anthropic: \"sk-...\" }`).\n * Drivers inject the relevant key into the environment or SDK options.\n */\n apiKeys?: Record<string, string>;\n /**\n * Additional environment variables merged into the child process environment.\n * For omp: merged with `process.env` before spawn. For claude-sdk: accessed\n * via `env.ANTHROPIC_API_KEY` as an alternative to `apiKeys.anthropic`.\n */\n env?: Record<string, string>;\n /**\n * AI cloud transport for claude-sdk: `default | bedrock | vertex | azure |\n * gateway`. Absent (or `\"default\"`) preserves today's behavior — the\n * provider's native API. Typed as `string` for forward compatibility; the\n * driver falls back to `default` on unrecognized values (with a warning).\n * Ignored by all other drivers.\n *\n * @since 1.3.0\n */\n cloud?: string;\n /**\n * Non-secret transport settings for the selected `cloud` (camelCase — the\n * skaile.yaml `cloud_config` wire shape is snake_case and converted once at\n * the settings/serve boundary). Ignored when `cloud` is absent/default.\n *\n * @since 1.3.0\n */\n cloudConfig?: { region?: string; projectId?: string; resource?: string; baseUrl?: string };\n /**\n * Resolved credential env bundle for the selected `cloud` — runner-provided\n * (platform `session_init` secrets, or runner-materialized file paths such\n * as the Vertex service-account file). Values are secrets: never logged.\n *\n * @since 1.3.0\n */\n cloudSecrets?: Record<string, string>;\n /** Inline system prompt — written to .omp/system.md and passed via --append-system-prompt (omp driver) */\n systemPrompt?: string;\n /** Path to project .omp/ directory (PI_CODING_AGENT_DIR for omp driver) */\n agentDir?: string;\n /** SSH key path — injected as GIT_SSH_COMMAND */\n sshKeyPath?: string;\n /** Pre-assign a UUID as the session ID for a new session (claude-sdk: passed as sessionId option) */\n sessionId?: string;\n /** Resume this specific past session by UUID instead of starting fresh (claude-sdk: passed as resume option) */\n resumeSessionId?: string;\n /** Maximum agentic turns per query (claude-sdk: passed as maxTurns option) */\n maxTurns?: number;\n /** Agent name — selects a deployed sub-agent definition as the main agent identity.\n * claude-sdk: passed as `agent` option to query() → reads .claude/agents/<name>.md natively.\n * omp: ignored (omp uses agentDir/PI_CODING_AGENT_DIR instead). */\n agentName?: string;\n /** In-process SDK MCP servers for custom tool injection (Claude SDK only, ignored by other drivers) */\n mcpServers?: Record<string, unknown>;\n /** Tool restrictions from agent.yaml — applied to the main agent session */\n tools?: {\n /** Tool names that the agent is allowed to invoke. An empty array means no restriction. */\n allowed?: string[];\n /** Tool names that the agent is explicitly forbidden from invoking. */\n denied?: string[];\n };\n /** Thinking mode for Claude models: adaptive (Claude decides), enabled (always think), disabled (no thinking). */\n thinking?: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Reasoning effort level for Claude models. */\n effort?: \"low\" | \"medium\" | \"high\" | \"max\";\n /** Driver-specific configuration bag. */\n driverOptions?: DriverOptions;\n /**\n * Protocol v2 capability dispatch hooks. When present, the driver uses the\n * registry as the source of LLM tool definitions and routes invocations\n * through `capabilities.invoke()`. Absent → legacy v1 path (existing\n * mcpServers / native dispatch).\n *\n * @since 2.0.0\n */\n capabilities?: BridgeCapabilityHooks;\n /**\n * The platform's `AIProviderConfig.id` for the AI credential currently\n * provisioned into this driver. The runner reads this off `AgentConfig`\n * during 401 mediation and passes it as `configId` in\n * `request_access_token { kind: 'ai-credentials' }`. The driver itself\n * does not consume this field — only the runner uses it.\n *\n * Set by the platform agent-gateway in `ConfigureCommandV2` for mediated\n * sessions. Standalone runners (CLI / forge / Claude plugin) leave it\n * undefined; the runner falls back to surfacing the auth error to the\n * user without mediating.\n *\n * Spec: `_devlog/specs/2026-05-07-unified-credential-mediation.md`\n * § \"Wire `aiProviderConfigId` end-to-end\".\n *\n * @since 3.3.0\n */\n aiProviderConfigId?: string;\n /**\n * Optional callback invoked by the driver when the underlying agent\n * surfaces an `authentication_error`. In Protocol v3 the runner mediates\n * the refresh via the `host.refresh_credential` capability and returns a\n * typed {@link CredentialMint}. The driver inspects the discriminator:\n *\n * - `mint.ok === true`: a fresh credential is now provisioned. The\n * driver re-attempts the in-flight prompt once.\n * - `mint.ok === false`: refresh failed (`code` carries a stable reason\n * such as `revoked`, `not-configured`, `provider-error`,\n * `backend-error`). The driver surfaces the original `AuthError` to\n * the caller.\n *\n * `args.configId` carries the platform `AIProviderConfig.id` the driver\n * was provisioned with (mirrors {@link AgentConfig.aiProviderConfigId}).\n * The runner uses it to scope the refresh to the correct AI credential.\n *\n * When omitted, the driver throws `AuthError` immediately as before\n * (standalone CLI / forge mode — there is no platform mediator to ask).\n *\n * Centralising auth-retry inside the driver means every consumer of\n * `driver.prompt(...)` (serve handler, compaction orchestrator, flow\n * orchestrator, …) gets self-healing for free — there is no per-call-site\n * wrapping.\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`\n * § \"host.refresh_credential capability\".\n *\n * @since 3.4.0\n */\n onAuthError?: (args: { configId: string }) => Promise<CredentialMint>;\n /**\n * Test-only flow driver hook. When present, the echo driver's scripted-flow\n * mode uses it to advance flow nodes deterministically (no LLM). The runner\n * injects it in `createActiveFlow`; every other driver ignores it.\n *\n * @see FlowTestDriverHook\n * @since 3.6.0\n */\n flowTestDriver?: FlowTestDriverHook;\n}\n\n/**\n * A single message in an agent conversation.\n *\n * Emitted as part of {@link AgentEvent} variants (`message_start`, `message_update`, `message_end`).\n *\n * @docLink packages/bridge/concepts#agent-message\n */\nexport interface AgentMessage {\n /** Originator of the message. */\n role: \"user\" | \"assistant\" | \"tool\";\n /** Message body — either a plain string or a list of typed content blocks. */\n content: string | ContentBlock[];\n /** Tool invocations made by the assistant in this message. */\n toolCalls?: ToolCall[];\n /** For `role === \"tool\"`: the name of the tool whose result this message carries. */\n toolName?: string;\n /** For `role === \"tool\"`: `true` when the tool returned an error. */\n isError?: boolean;\n /** Optional structured payload for tool results. */\n data?: unknown;\n}\n\n/**\n * A typed block within an {@link AgentMessage}'s content array.\n *\n * Mirrors the Anthropic content block schema but is driver-agnostic.\n *\n * @docLink packages/bridge/concepts#content-block\n */\nexport interface ContentBlock {\n /** Block discriminant. */\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"thinking\";\n /** Present for `text` and `thinking` blocks. */\n text?: string;\n /** Tool use / tool result correlation ID. */\n id?: string;\n /** Tool name (present on `tool_use` blocks). */\n name?: string;\n /** Tool input arguments (present on `tool_use` blocks). */\n input?: any;\n /** Serialised tool result content (present on `tool_result` blocks). */\n content?: string;\n}\n\n/**\n * A single tool invocation made by the agent within a message.\n *\n * @docLink packages/bridge/concepts#tool-call\n */\nexport interface ToolCall {\n /** Correlation ID used to match the call with its result. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments passed to the tool. */\n input: any;\n}\n\n/**\n * Error classification for agent failures.\n *\n * Used to determine whether a failure is retryable and to surface actionable\n * hints to the user. See `bridge/CLAUDE.md` for the full category-to-behaviour matrix.\n *\n * @see AgentError\n * @docLink packages/bridge/concepts#error-category\n */\nexport type ErrorCategory =\n | \"auth\"\n | \"account\"\n | \"rate_limit\"\n | \"model\"\n | \"network\"\n | \"config\"\n | \"process\"\n | \"validation\"\n | \"unknown\";\n\n/**\n * Structured error payload emitted inside the `error` {@link AgentEvent}.\n *\n * Consumers should inspect `retryable` before deciding to surface a retry button,\n * and `hint` to provide an actionable message to the user.\n *\n * @docLink packages/bridge/concepts#agent-error\n */\nexport interface AgentError {\n /** Human-readable error description. */\n message: string;\n /** Coarse failure classification used for retry logic and telemetry. */\n category: ErrorCategory;\n /** HTTP status code if the error originated from an API response. */\n statusCode?: number;\n /** `true` when the caller may safely retry the same operation. */\n retryable: boolean;\n /** Short actionable advice suitable for display in the UI. */\n hint?: string;\n}\n\n/**\n * Metadata for a slash command exposed by the active agent runtime.\n *\n * @docLink packages/bridge/concepts#slash-command-info\n */\nexport interface SlashCommandInfo {\n /** Command name without the leading slash (e.g. `\"compact\"`). */\n name: string;\n /** One-line description shown in command pickers. */\n description: string;\n /** Placeholder text describing what argument the command expects. */\n argumentHint?: string;\n}\n\n/**\n * Discriminated union of all events emitted by a driver on the `'agent-event'` channel.\n *\n * @remarks\n * Consumers listen via `driver.on('agent-event', (event: AgentEvent) => ...)`.\n * The `[k: string]: any` index signature on most variants allows drivers to attach\n * driver-specific fields (e.g. `_textDelta`) without breaking the union.\n *\n * @docLink packages/bridge/concepts#agent-event\n */\nexport type AgentEvent =\n | { type: \"message_start\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_update\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_end\"; message: AgentMessage; [k: string]: any }\n | { type: \"turn_end\"; toolResults?: AgentMessage[]; [k: string]: any }\n | { type: \"agent_end\"; [k: string]: any }\n | {\n type: \"result\";\n subtype: string;\n summary?: string;\n costUsd?: number;\n /** Per-turn token usage when the driver tracks it. Added in 3.1.0. */\n tokens?: TokenUsage;\n errors?: string[];\n [k: string]: any;\n }\n | { type: \"error\"; error: string; detail?: AgentError; fatal?: boolean; [k: string]: any }\n | { type: \"tool_call\"; name?: string; tool?: { name: string }; [k: string]: any }\n | { type: \"tool_execution_end\"; toolName?: string; [k: string]: any }\n | { type: \"commands_available\"; commands: SlashCommandInfo[] }\n | { type: \"session_info\"; driverSessionId: string; sessionFile?: string }\n | { type: \"ui_render\"; [k: string]: any }\n | { type: \"ui_render_update\"; [k: string]: any }\n | { type: \"ui_clear\"; [k: string]: any }\n // Phase 3 (resume cascade) — driver-emitted resume outcome.\n | {\n type: \"resume_failed\";\n resumeSessionId: string;\n reason: \"signature_mismatch\" | \"model_mismatch\" | \"jsonl_lost\" | \"jsonl_poisoned\";\n [k: string]: any;\n };\n\n/**\n * Abstract base class for agent driver backends.\n *\n * Wraps an LLM coding agent behind a single `prompt()` interface.\n * All drivers emit `'agent-event'` with {@link AgentEvent} payloads.\n *\n * @remarks\n * Subclasses must implement `start`, `prompt`, `abort`, `kill`, and `isRunning`.\n * Implementations should never emit an event name other than `'agent-event'` as\n * the public streaming channel — internal events (`'ready'`, `'exit'`, etc.) are\n * driver-private.\n *\n * @example\n * ```ts\n * const driver = createDriver('omp', config);\n * driver.on('agent-event', (event) => console.log(event.type));\n * await driver.start();\n * await driver.prompt('Refactor the auth module');\n * driver.kill();\n * ```\n *\n * @docLink packages/bridge/concepts#agent-driver\n */\nexport abstract class AgentDriver extends EventEmitter {\n /** Static metadata describing this driver's capabilities. */\n abstract readonly driverInfo: DriverInfo;\n\n /**\n * Initialises the driver backend — spawns the child process (omp) or loads\n * the SDK module (claude-sdk). Resolves when the backend is ready to accept\n * prompts. Idempotent: calling `start()` on an already-running driver is a no-op.\n *\n * @throws {Error} When the backend binary is missing or the SDK cannot be loaded.\n */\n abstract start(): Promise<void>;\n\n /**\n * Sends a user message to the agent and resolves when the agent's turn completes\n * (i.e. after the `agent_end` event has been emitted).\n *\n * @param message - Plain-text user prompt to send to the agent.\n * @throws {Error} When the driver is not running or the underlying backend reports a fatal error.\n */\n abstract prompt(message: string): Promise<void>;\n\n /**\n * Sends an in-band abort signal to the agent, requesting it to stop the current\n * turn without terminating the process. The driver remains usable after `abort()`.\n *\n * @remarks Only meaningful when `driverInfo.supportsInBandAbort` is `true`.\n * For other drivers, prefer `kill()` followed by creating a new driver instance.\n */\n abstract abort(): Promise<void>;\n\n /**\n * Terminates the agent backend immediately (SIGTERM for subprocess drivers,\n * `close()` for in-process drivers). The driver instance must not be reused\n * after `kill()`.\n */\n abstract kill(): void;\n\n /** `true` when the backend is alive and able to accept new prompts. */\n abstract get isRunning(): boolean;\n\n /** Optional provider-native session/thread identifier for resume support. */\n get runtimeSessionId(): string | undefined {\n return undefined;\n }\n\n /** Slash commands discovered from the agent runtime. Override in drivers that support introspection. */\n getSlashCommands(): SlashCommandInfo[] {\n return [];\n }\n\n // ── Interactive questions (AskUserQuestion) ──────────────────────────────\n\n /**\n * `true` while the driver is paused on an interactive question and waiting\n * for the user's answer rather than a new prompt. The runner routes a\n * `reply` command to {@link answerQuestion} instead of {@link prompt} when\n * this returns `true`. Drivers without interactive-question support return\n * `false` (the default), so a `reply` falls back to `prompt`.\n */\n hasPendingQuestion(): boolean {\n return false;\n }\n\n /**\n * Deliver the user's answer to the question the driver is currently paused\n * on. This resumes the in-flight turn — it does NOT start a new one. When a\n * single tool call asks several questions, the driver resolves the underlying\n * call only once every sub-question has an answer.\n *\n * @param answer - The user's reply text (an option label, free text, or for\n * multi-select a comma-joined list).\n * @param question - The sub-question this answers, verbatim from the\n * `question` event that asked it. Supply it whenever the host lets the user\n * answer out of order — without it the answer fills the next unanswered\n * slot in order, which silently mismatches a non-sequential reply.\n * @returns `true` when the answer was consumed by a pending question; `false`\n * when no question was pending (caller should treat the reply as a prompt).\n */\n answerQuestion(answer: string, question?: string): boolean {\n void answer;\n void question;\n return false;\n }\n\n // ── Live reconfiguration ────────────────────────────────────────────────\n\n /**\n * Live-update driver configuration. The new values take effect on the next\n * prompt() call. Only model/thinking/effort are reconfigurable mid-session.\n *\n * Subclasses that store config locally should override this to apply the\n * patch to their own config field. The base implementation is a no-op.\n */\n reconfigure(patch: Partial<Pick<AgentConfig, \"model\" | \"thinking\" | \"effort\">>): void {\n // No-op — subclasses override to apply to their own config.\n void patch;\n }\n\n /**\n * Returns the model identifier currently configured on this driver.\n * Subclasses that store config locally should override this.\n */\n getModel(): string | undefined {\n return undefined;\n }\n\n // ── Compaction support ──────────────────────────────────────────────────\n\n /**\n * Returns the token usage from the most recent completed turn.\n * Returns `null` if usage data is unavailable (e.g. driver doesn't track it).\n *\n * Widened in 3.1.0 to return the full `TokenUsage` shape (input / output /\n * cache-read / cache-creation / reasoning). All fields are optional so\n * drivers can populate just what their provider reports. Existing callers\n * that read only `inputTokens` / `outputTokens` keep working — those fields\n * are still present and carry the same semantics as before.\n */\n getTokenUsage(): TokenUsage | null {\n return null;\n }\n\n /**\n * Returns the model's context window size in tokens.\n * Returns `null` if unknown.\n */\n getContextWindow(): number | null {\n return null;\n }\n\n /**\n * Returns the list of models available to this driver without starting a session.\n * Drivers that can enumerate their own models override this method.\n * Returns an empty array by default.\n */\n async listModels(): Promise<ModelEntry[]> {\n return [];\n }\n\n /**\n * Closes the current conversation session and prepares for a fresh start.\n * The next `prompt()` call will begin a new session without prior history.\n * The driver remains usable after `resetSession()`.\n */\n abstract resetSession(): Promise<void>;\n\n // ── Telemetry ─────────────────────────────────────────────────────────────\n\n protected _telemetry?: TelemetryProvider;\n protected _activeTrace?: Trace;\n protected _activeTurnSpan?: Span;\n private _turnStartTime?: number;\n\n /**\n * Attach a telemetry provider and active trace to this driver.\n * Called by the runner after creating the driver but before start().\n */\n setTelemetry(provider: TelemetryProvider, trace: Trace): void {\n this._telemetry = provider;\n this._activeTrace = trace;\n }\n\n /**\n * Begin a turn span. Called by the runner before prompt().\n * Pass a parent span (e.g. the turn span from the orchestrator) for nesting.\n * Returns the span so the runner can annotate it further.\n */\n beginTurnSpan(\n parent?: Trace | Span,\n attrs?: Record<string, string | number | boolean>,\n ): Span | undefined {\n if (!this._telemetry || !this._activeTrace) return undefined;\n this._turnStartTime = Date.now();\n this._activeTurnSpan = this._telemetry.startSpan(parent ?? this._activeTrace, {\n name: \"llm_generation\",\n kind: \"llm_generation\",\n attributes: attrs,\n });\n return this._activeTurnSpan;\n }\n\n /**\n * End the current turn span with generation data.\n * Called by the runner after agent_end. Model and provider are passed\n * explicitly — the driver base class does not access config directly.\n */\n endTurnSpan(result?: {\n model?: string;\n provider?: string;\n inputTokens?: number;\n outputTokens?: number;\n stopReason?: string;\n error?: string;\n }): void {\n if (!this._telemetry || !this._activeTurnSpan) return;\n const durationMs = this._turnStartTime ? Date.now() - this._turnStartTime : 0;\n\n if (result?.inputTokens !== undefined || result?.outputTokens !== undefined) {\n this._telemetry.logGeneration(this._activeTurnSpan, {\n model: result?.model ?? \"unknown\",\n provider: result?.provider ?? \"unknown\",\n inputTokens: result.inputTokens,\n outputTokens: result.outputTokens,\n durationMs,\n stopReason: result.stopReason,\n });\n }\n\n this._telemetry.endSpan(this._activeTurnSpan, {\n status: result?.error ? \"error\" : \"ok\",\n error: result?.error,\n attributes: { \"skaile.turn.duration_ms\": durationMs },\n });\n\n this._activeTurnSpan = undefined;\n this._turnStartTime = undefined;\n }\n}\n\n/**\n * Factory function signature registered in the driver registry.\n *\n * @param config - Configuration for the new driver instance.\n * @returns A freshly constructed (not yet started) {@link AgentDriver}.\n * @docLink packages/bridge/concepts#driver-factory\n */\nexport type DriverFactory = (config: AgentConfig) => AgentDriver;\n","import type { DriverContext } from \"@skaile/workspaces/plugin-registry\";\nimport { type PluginRegistry, pluginRegistry } from \"@skaile/workspaces/plugin-registry\";\nimport type { ModelEntry } from \"./models.js\";\nimport type { AgentConfig, AgentDriver, DriverInfo } from \"./types.js\";\n\n// Build-time backend gating. `bun build --compile --define:__INCLUDE_*__=...`\n// folds these to literal booleans so an excluded backend's driver module and\n// its SDK are dead-code-stripped from the binary. Under tsup / vitest / bun\n// run-on-source no `--define` runs and the `typeof` guard defaults to `true` —\n// every backend is available (the SDKs stay optional peers).\ndeclare const __INCLUDE_CLAUDE_SDK__: boolean;\ndeclare const __INCLUDE_CODEX__: boolean;\nconst INCLUDE_CLAUDE_SDK =\n typeof __INCLUDE_CLAUDE_SDK__ === \"undefined\" ? true : __INCLUDE_CLAUDE_SDK__;\nconst INCLUDE_CODEX = typeof __INCLUDE_CODEX__ === \"undefined\" ? true : __INCLUDE_CODEX__;\n\n/**\n * Static capability metadata for every built-in backend.\n *\n * Pure data — this object imports no driver module and references no backend\n * SDK. {@link listDrivers} returns it (merged with any third-party drivers)\n * so selection UIs can enumerate every backend without loading a single\n * driver module. The matching driver module's `DriverTarget` is registered\n * into the plugin registry by {@link registerBuiltinDrivers}.\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport const BUILTIN_DRIVER_CATALOG: Record<string, DriverInfo> = {\n omp: {\n id: \"omp\",\n name: \"omp (oh-my-pi)\",\n modelAgnostic: true,\n supportsInBandAbort: true,\n },\n \"claude-sdk\": {\n id: \"claude-sdk\",\n name: \"Claude Agent SDK\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n },\n codex: {\n id: \"codex\",\n name: \"OpenAI Codex\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n },\n echo: {\n id: \"echo\",\n name: \"Echo (E2E mock)\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n gemini: {\n id: \"gemini\",\n name: \"Gemini CLI\",\n modelAgnostic: false,\n supportsInBandAbort: false,\n },\n qwen: {\n id: \"qwen\",\n name: \"Qwen Code\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n opencode: {\n id: \"opencode\",\n name: \"OpenCode\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n goose: {\n id: \"goose\",\n name: \"Goose\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n continue: {\n id: \"continue\",\n name: \"Continue CLI\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n};\n\n/**\n * Back-compat alias for {@link BUILTIN_DRIVER_CATALOG}. Consumers and tests that\n * predate the plugin-registry refactor still import `DRIVER_CATALOG`.\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport const DRIVER_CATALOG = BUILTIN_DRIVER_CATALOG;\n\nlet _driversRegistered = false;\n\n/**\n * Register every built-in driver's `DriverTarget` into the plugin registry.\n *\n * This is the single id → module map in bridge core. Every specifier is a\n * literal string so `bun --compile` can statically bundle the driver module\n * (and, transitively, its SDK). The in-process-SDK backends (`claude-sdk`,\n * `codex`) are wrapped in build-constant guards so an excluded backend's\n * `await import` folds to dead code in the compiled binary. `omp` and `echo`\n * carry no SDK weight and are always available.\n *\n * **Static import discipline.** Every `import()` specifier below must be a\n * string literal — never aliased through a variable. Indirection defeats\n * `bun --compile`'s static analysis and silently drops the module from the\n * binary.\n *\n * Idempotent: guarded by a module flag so a second call is a no-op (a duplicate\n * `register` would otherwise throw `RegistrationError`).\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function registerBuiltinDrivers(\n registry: PluginRegistry = pluginRegistry,\n): Promise<void> {\n if (registry === pluginRegistry && _driversRegistered) return;\n\n if (!registry.get(\"driver\", \"omp\")) {\n const m = await import(\"@skaile/workspaces/drivers/omp\");\n registry.register(\"driver\", m.ompDriverTarget);\n }\n if (!registry.get(\"driver\", \"echo\")) {\n const m = await import(\"@skaile/workspaces/drivers/echo\");\n registry.register(\"driver\", m.echoDriverTarget);\n }\n if (INCLUDE_CLAUDE_SDK && !registry.get(\"driver\", \"claude-sdk\")) {\n const m = await import(\"@skaile/workspaces/drivers/claude-sdk\");\n registry.register(\"driver\", m.claudeSdkDriverTarget);\n }\n if (INCLUDE_CODEX && !registry.get(\"driver\", \"codex\")) {\n const m = await import(\"@skaile/workspaces/drivers/codex\");\n registry.register(\"driver\", m.codexDriverTarget);\n }\n // Subprocess CLI backends spawn an external binary the user installs\n // separately — no bundled SDK to dead-code-strip, so (like omp/echo) they\n // carry no build constant and are always registered.\n if (!registry.get(\"driver\", \"gemini\")) {\n const m = await import(\"@skaile/workspaces/drivers/gemini\");\n registry.register(\"driver\", m.geminiDriverTarget);\n }\n if (!registry.get(\"driver\", \"qwen\")) {\n const m = await import(\"@skaile/workspaces/drivers/qwen\");\n registry.register(\"driver\", m.qwenDriverTarget);\n }\n if (!registry.get(\"driver\", \"opencode\")) {\n const m = await import(\"@skaile/workspaces/drivers/opencode\");\n registry.register(\"driver\", m.opencodeDriverTarget);\n }\n if (!registry.get(\"driver\", \"goose\")) {\n const m = await import(\"@skaile/workspaces/drivers/goose\");\n registry.register(\"driver\", m.gooseDriverTarget);\n }\n if (!registry.get(\"driver\", \"continue\")) {\n const m = await import(\"@skaile/workspaces/drivers/continue\");\n registry.register(\"driver\", m.continueDriverTarget);\n }\n\n if (registry === pluginRegistry) _driversRegistered = true;\n}\n\n/**\n * Creates a new driver instance for the given backend id.\n *\n * Ensures the built-in driver targets are registered (idempotent), then looks\n * up the target in the plugin registry and calls its `create()`. The returned\n * driver has not been started yet — call `driver.start()` before sending\n * prompts.\n *\n * @param id - Registered driver identifier (e.g. `\"omp\"`, `\"claude-sdk\"`).\n * @param config - Configuration forwarded to the driver constructor.\n * @param ctx - Optional driver context (logger / abort signal). Defaults to `{}`.\n * @returns A freshly constructed (not yet started) {@link AgentDriver}.\n * @throws {Error} When `id` is a known backend excluded from this build, or\n * when `id` does not match any registered driver at all.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function createDriver(\n id: string,\n config: AgentConfig,\n ctx?: DriverContext,\n): Promise<AgentDriver> {\n const target = await resolveDriverTarget(id);\n return target.create(config, ctx ?? {});\n}\n\n/**\n * Resolve a registered driver target by id, ensuring the built-ins are\n * registered first. Throws the canonical \"not bundled\" / \"unknown driver\"\n * errors so every caller (`createDriver`, `listModelsForDriver`) reports an\n * unrecognized id the same way instead of silently degrading.\n *\n * @throws {Error} When `id` is a known backend excluded from this build, or\n * when `id` does not match any registered driver at all.\n */\nasync function resolveDriverTarget(id: string) {\n await registerBuiltinDrivers();\n const target = pluginRegistry.get(\"driver\", id);\n if (!target) {\n if (id in BUILTIN_DRIVER_CATALOG) {\n throw new Error(`Agent driver \"${id}\" is not bundled in this build.`);\n }\n throw new Error(\n `Unknown agent driver: \"${id}\". Available: ${listDrivers()\n .map((d) => d.id)\n .join(\", \")}`,\n );\n }\n return target;\n}\n\n/**\n * Returns the capability metadata for every available driver.\n *\n * Enumerates every built-in backend from {@link BUILTIN_DRIVER_CATALOG} without\n * loading a single driver module or backend SDK, then merges in any third-party\n * driver targets registered into the plugin registry that are not already in\n * the catalog. Use this to populate driver selection UIs.\n *\n * @returns Array of {@link DriverInfo} objects, one per available driver.\n * @docLink packages/bridge/api-reference#registry\n */\nexport function listDrivers(): DriverInfo[] {\n const merged = new Map<string, DriverInfo>();\n for (const info of Object.values(BUILTIN_DRIVER_CATALOG)) {\n merged.set(info.id, info);\n }\n for (const meta of pluginRegistry.list(\"driver\")) {\n if (!merged.has(meta.id)) {\n // Third-party drivers carry no DriverInfo row; read the capability flags\n // off the registered target (defaulting to conservative false) so a\n // model-agnostic / in-band-abort backend can still advertise them.\n const target = pluginRegistry.get(\"driver\", meta.id);\n merged.set(meta.id, {\n id: meta.id,\n name: meta.displayName,\n modelAgnostic: target?.modelAgnostic ?? false,\n supportsInBandAbort: target?.supportsInBandAbort ?? false,\n });\n }\n }\n return [...merged.values()];\n}\n\n/**\n * List models available to a specific driver without starting a full agent session.\n *\n * Ensures the built-in driver targets are registered (idempotent), then\n * delegates to the target's optional `listModels()`. API keys are forwarded so\n * drivers can authenticate against provider REST APIs if needed. Throws on an\n * unknown / not-bundled id (same contract as {@link createDriver}); returns `[]`\n * only when the target exists but exposes no `listModels`.\n *\n * @param driverId - Registered driver id (e.g. `\"omp\"`, `\"claude-sdk\"`, `\"codex\"`).\n * @param apiKeys - Provider API keys keyed by provider name (e.g. `{ anthropic: \"sk-...\" }`).\n * Pass `settings.apiKeys ?? {}` from forge-assistant's resolved settings.\n * @throws {Error} When `driverId` is unknown or excluded from this build.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function listModelsForDriver(\n driverId: string,\n apiKeys: Record<string, string>,\n): Promise<ModelEntry[]> {\n const target = await resolveDriverTarget(driverId);\n return (await target.listModels?.(apiKeys)) ?? [];\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../bridge/src/logger.ts","../bridge/src/types.ts","../bridge/src/registry.ts"],"names":[],"mappings":"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","file":"chunk-QFO4IYBZ.js","sourcesContent":["/**\n * Bridge-layer logger factory.\n *\n * Each driver creates its own Logger via `getBridgeLogger(subkind)` at\n * construction time. Falls back to an off-mode Logger (stdout only) when\n * no LogStore is registered — see @skaile/workspaces/core/logging for details.\n */\n\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport type { Logger } from \"@skaile/workspaces/types\";\n\n/**\n * Construct a bridge-scoped Logger for a given driver subkind.\n *\n * Creates a `Logger` with `kind: \"bridge\"` and the specified `subkind`. Falls back to\n * an off-mode Logger (stdout only) when no `LogStore` is registered — see\n * `@skaile/workspaces/core/logging` for details. Each driver calls this once at construction\n * time; never re-construct per call.\n *\n * @param subkind - Driver id, e.g. `\"claude-sdk\"`, `\"omp\"`, `\"echo\"`, `\"codex\"`.\n * @returns A `Logger` scoped to `bridge:<subkind>`.\n * @docLink packages/bridge/api-reference#logger\n */\nexport function getBridgeLogger(subkind: string): Logger {\n return createLogger({ kind: \"bridge\", subkind });\n}\n","import { EventEmitter } from \"node:events\";\nimport type { Span, TelemetryProvider, Trace } from \"@skaile/workspaces/telemetry\";\nimport type {\n Capability,\n CredentialMint,\n FlowExecution,\n RenderInvokedEvent,\n TokenUsage,\n} from \"@skaile/workspaces/types\";\nimport type { ModelEntry } from \"./models.js\";\n\n/**\n * Test-only hook injected by the runner so a no-LLM driver (the echo driver's\n * scripted-flow mode) can read flow state and drive flow-adapter mutations\n * without an SDK/MCP round-trip. The runner wires this in `createActiveFlow`\n * from the active FlowAdapter + handle.\n *\n * This is an internal runner↔driver interface — NOT part of any wire\n * protocol or flow contract. Production drivers ignore it.\n *\n * @see packages/bridge/drivers/echo — scripted-flow mode\n * @since 3.6.0\n */\nexport interface FlowTestDriverHook {\n /** Current flow execution snapshot, or `null` when no flow is active. */\n getState(): FlowExecution | null;\n /**\n * Execute a flow-adapter operation (`start_node`, `request_approval`,\n * `complete_node`, `request_input`, `skip_node`, `fail_node`, …). Returns\n * the adapter's JSON string result (or rejects on an illegal transition).\n */\n execute(op: string, args: Record<string, unknown>): Promise<string>;\n /**\n * Node IDs marked as mandatory approval gates. The scripted policy resolves\n * `auto` to `request_approval` for these even in autonomous mode, so hosts\n * can drive a mandatory gate deterministically. Optional — absent hooks\n * behave as if no node is mandatory.\n */\n mandatoryGates?(): string[];\n}\n\n/**\n * Minimal LLM tool descriptor used by the capability dispatch path. Mirrors\n * the runner's `LLMTool` shape so drivers can consume registry output without\n * importing `@skaile/workspaces/runner` (which would create a circular dep).\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-tool\n */\nexport interface BridgeCapabilityTool {\n /** Capability name; used as the LLM-visible tool name. */\n name: string;\n /** Human/LLM-readable description. */\n description: string;\n /** JSON Schema for the tool's input parameters. */\n parameters: Record<string, unknown>;\n}\n\n/**\n * Render-cap event emission callback used by the bridge when the LLM invokes\n * a capability that carries a `render` spec. The runner provides the actual\n * sink (transport.send / sendEvent); the bridge only emits.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-render-emit\n */\nexport type BridgeRenderEmit = (event: RenderInvokedEvent) => void;\n\n/**\n * Text-event emission callback for render-capability fallbacks. When a\n * `RenderCapability` carries `render.fallback` and the LLM invokes it, the\n * bridge substitutes `{{prop}}` placeholders (top-level keys of `props`,\n * optional dotted-path traversal `{{user.name}}`) and pushes the rendered\n * string through this callback so clients without a render layer still see\n * a textual representation. No-op when `fallback` is absent.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-text-emit\n */\nexport type BridgeTextEmit = (text: string) => void;\n\n/**\n * Bundle of capability dispatch hooks. Registered into the driver via\n * `AgentConfig.capabilities`; the driver routes registered LLM tool calls\n * back into `invoke()` instead of using its native dispatch path.\n *\n * The runner constructs this from a `CapabilityRegistry` instance and threads\n * it through `createAgentSession()`. Drivers that don't yet implement\n * capability dispatch ignore the field — legacy v1 paths stay intact.\n *\n * @category Capabilities\n * @since 2.0.0\n * @docLink packages/bridge/concepts#bridge-capability-hooks\n */\nexport interface BridgeCapabilityHooks {\n /** Build the LLM tool descriptor list from the registry. Called per turn so registration changes take effect. */\n composeTools(): BridgeCapabilityTool[];\n /** Resolve a wire-format Capability descriptor by name. Used by the bridge to inspect `fireAndForget` / `render`. */\n resolve(name: string): Capability | null;\n /** Validate input + dispatch through the registry. Logging is wired by the registry. */\n invoke(name: string, input: unknown): Promise<unknown>;\n /** Emit a render-invoked event. The runner forwards via the WebSocket transport. */\n emitRender?: BridgeRenderEmit;\n /** Emit a text fallback for render capabilities with `render.fallback`. */\n emitText?: BridgeTextEmit;\n /** Session id passed through to the runner's per-handler logger. */\n sessionId: string;\n}\n\n/**\n * Static metadata for a registered agent driver backend.\n *\n * Returned by {@link listDrivers} and exposed on every {@link AgentDriver} instance\n * via `driverInfo`.\n *\n * @docLink packages/bridge/concepts#driver-info\n */\nexport interface DriverInfo {\n /** Stable machine identifier used to look up the driver in the registry (e.g. `\"omp\"`, `\"claude-sdk\"`). */\n id: string;\n /** Human-readable display name shown in UIs and logs. */\n name: string;\n /** `true` when the driver can target any LLM provider; `false` for Anthropic-only drivers. */\n modelAgnostic: boolean;\n /**\n * `true` when the driver supports mid-stream abort via `abort()` without killing the process.\n * Drivers that return `false` can only be stopped via `kill()`.\n */\n supportsInBandAbort: boolean;\n}\n\n/**\n * Codex-specific tuning options passed through `DriverOptions.codex`.\n *\n * @remarks These are forwarded verbatim to the Codex driver and have no effect on other drivers.\n * @docLink packages/bridge/concepts#codex-driver-options\n */\nexport interface CodexDriverOptions {\n /** Controls whether Codex may auto-apply edits without user approval. */\n approvalPolicy?: \"never\" | \"on-request\" | \"on-failure\" | \"untrusted\";\n /** Filesystem sandbox level for the Codex process. */\n sandboxMode?: \"read-only\" | \"workspace-write\" | \"danger-full-access\";\n /** Reasoning budget passed to the model. */\n reasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n /** When `true`, the Codex sandbox is allowed to make outbound network requests. */\n networkAccessEnabled?: boolean;\n /** Extra directories made accessible to the Codex sandbox in addition to `cwd`. */\n additionalDirectories?: string[];\n}\n\n/**\n * Driver-specific configuration bag.\n *\n * Fields are keyed by driver ID so that callers can pass driver-specific options\n * through the common {@link AgentConfig} without breaking other drivers.\n *\n * @docLink packages/bridge/concepts#driver-options\n */\nexport interface DriverOptions {\n /** Codex-specific options. Ignored by all other drivers. */\n codex?: CodexDriverOptions;\n}\n\n/**\n * Configuration passed to a driver when it is created via {@link createDriver}.\n *\n * All fields are shared across drivers; driver-specific behaviour is documented\n * per field. Fields that are silently ignored by a driver are marked accordingly.\n *\n * @docLink packages/bridge/concepts#agent-config\n */\nexport interface AgentConfig {\n /** Absolute path to the working directory the agent operates in. */\n cwd: string;\n /**\n * LLM provider name (e.g. `\"anthropic\"`, `\"openai\"`, `\"google\"`).\n * Combined with `model` as `provider/model` for omp's `--model` flag.\n * Ignored by claude-sdk (always Anthropic).\n */\n provider?: string;\n /**\n * LLM model identifier (e.g. `\"claude-sonnet-4-5\"`, `\"gpt-4o\"`).\n * For omp: passed as `--model [provider/]model`.\n * For claude-sdk: passed as the `model` query option.\n */\n model?: string;\n /**\n * Provider API keys keyed by provider name (e.g. `{ anthropic: \"sk-...\" }`).\n * Drivers inject the relevant key into the environment or SDK options.\n */\n apiKeys?: Record<string, string>;\n /**\n * Additional environment variables merged into the child process environment.\n * For omp: merged with `process.env` before spawn. For claude-sdk: accessed\n * via `env.ANTHROPIC_API_KEY` as an alternative to `apiKeys.anthropic`.\n */\n env?: Record<string, string>;\n /**\n * AI cloud transport for claude-sdk: `default | bedrock | vertex | azure |\n * gateway`. Absent (or `\"default\"`) preserves today's behavior — the\n * provider's native API. Typed as `string` for forward compatibility; the\n * driver falls back to `default` on unrecognized values (with a warning).\n * Ignored by all other drivers.\n *\n * @since 1.3.0\n */\n cloud?: string;\n /**\n * Non-secret transport settings for the selected `cloud` (camelCase — the\n * skaile.yaml `cloud_config` wire shape is snake_case and converted once at\n * the settings/serve boundary). Ignored when `cloud` is absent/default.\n *\n * @since 1.3.0\n */\n cloudConfig?: { region?: string; projectId?: string; resource?: string; baseUrl?: string };\n /**\n * Resolved credential env bundle for the selected `cloud` — runner-provided\n * (platform `session_init` secrets, or runner-materialized file paths such\n * as the Vertex service-account file). Values are secrets: never logged.\n *\n * @since 1.3.0\n */\n cloudSecrets?: Record<string, string>;\n /** Inline system prompt — written to .omp/system.md and passed via --append-system-prompt (omp driver) */\n systemPrompt?: string;\n /** Path to project .omp/ directory (PI_CODING_AGENT_DIR for omp driver) */\n agentDir?: string;\n /** SSH key path — injected as GIT_SSH_COMMAND */\n sshKeyPath?: string;\n /** Pre-assign a UUID as the session ID for a new session (claude-sdk: passed as sessionId option) */\n sessionId?: string;\n /** Resume this specific past session by UUID instead of starting fresh (claude-sdk: passed as resume option) */\n resumeSessionId?: string;\n /** Maximum agentic turns per query (claude-sdk: passed as maxTurns option) */\n maxTurns?: number;\n /** Agent name — selects a deployed sub-agent definition as the main agent identity.\n * claude-sdk: passed as `agent` option to query() → reads .claude/agents/<name>.md natively.\n * omp: ignored (omp uses agentDir/PI_CODING_AGENT_DIR instead). */\n agentName?: string;\n /** In-process SDK MCP servers for custom tool injection (Claude SDK only, ignored by other drivers) */\n mcpServers?: Record<string, unknown>;\n /** Tool restrictions from agent.yaml — applied to the main agent session */\n tools?: {\n /** Tool names that the agent is allowed to invoke. An empty array means no restriction. */\n allowed?: string[];\n /** Tool names that the agent is explicitly forbidden from invoking. */\n denied?: string[];\n };\n /** Thinking mode for Claude models: adaptive (Claude decides), enabled (always think), disabled (no thinking). */\n thinking?: \"adaptive\" | \"enabled\" | \"disabled\";\n /** Reasoning effort level for Claude models. */\n effort?: \"low\" | \"medium\" | \"high\" | \"max\";\n /** Driver-specific configuration bag. */\n driverOptions?: DriverOptions;\n /**\n * Protocol v2 capability dispatch hooks. When present, the driver uses the\n * registry as the source of LLM tool definitions and routes invocations\n * through `capabilities.invoke()`. Absent → legacy v1 path (existing\n * mcpServers / native dispatch).\n *\n * @since 2.0.0\n */\n capabilities?: BridgeCapabilityHooks;\n /**\n * The platform's `AIProviderConfig.id` for the AI credential currently\n * provisioned into this driver. The runner reads this off `AgentConfig`\n * during 401 mediation and passes it as `configId` in\n * `request_access_token { kind: 'ai-credentials' }`. The driver itself\n * does not consume this field — only the runner uses it.\n *\n * Set by the platform agent-gateway in `ConfigureCommandV2` for mediated\n * sessions. Standalone runners (CLI / forge / Claude plugin) leave it\n * undefined; the runner falls back to surfacing the auth error to the\n * user without mediating.\n *\n * Spec: `_devlog/specs/2026-05-07-unified-credential-mediation.md`\n * § \"Wire `aiProviderConfigId` end-to-end\".\n *\n * @since 3.3.0\n */\n aiProviderConfigId?: string;\n /**\n * Optional callback invoked by the driver when the underlying agent\n * surfaces an `authentication_error`. In Protocol v3 the runner mediates\n * the refresh via the `host.refresh_credential` capability and returns a\n * typed {@link CredentialMint}. The driver inspects the discriminator:\n *\n * - `mint.ok === true`: a fresh credential is now provisioned. The\n * driver re-attempts the in-flight prompt once.\n * - `mint.ok === false`: refresh failed (`code` carries a stable reason\n * such as `revoked`, `not-configured`, `provider-error`,\n * `backend-error`). The driver surfaces the original `AuthError` to\n * the caller.\n *\n * `args.configId` carries the platform `AIProviderConfig.id` the driver\n * was provisioned with (mirrors {@link AgentConfig.aiProviderConfigId}).\n * The runner uses it to scope the refresh to the correct AI credential.\n *\n * When omitted, the driver throws `AuthError` immediately as before\n * (standalone CLI / forge mode — there is no platform mediator to ask).\n *\n * Centralising auth-retry inside the driver means every consumer of\n * `driver.prompt(...)` (serve handler, compaction orchestrator, flow\n * orchestrator, …) gets self-healing for free — there is no per-call-site\n * wrapping.\n *\n * Spec: `_devlog/specs/2026-05-10-deterministic-session-bootstrap.md`\n * § \"host.refresh_credential capability\".\n *\n * @since 3.4.0\n */\n onAuthError?: (args: { configId: string }) => Promise<CredentialMint>;\n /**\n * Test-only flow driver hook. When present, the echo driver's scripted-flow\n * mode uses it to advance flow nodes deterministically (no LLM). The runner\n * injects it in `createActiveFlow`; every other driver ignores it.\n *\n * @see FlowTestDriverHook\n * @since 3.6.0\n */\n flowTestDriver?: FlowTestDriverHook;\n}\n\n/**\n * A single message in an agent conversation.\n *\n * Emitted as part of {@link AgentEvent} variants (`message_start`, `message_update`, `message_end`).\n *\n * @docLink packages/bridge/concepts#agent-message\n */\nexport interface AgentMessage {\n /** Originator of the message. */\n role: \"user\" | \"assistant\" | \"tool\";\n /** Message body — either a plain string or a list of typed content blocks. */\n content: string | ContentBlock[];\n /** Tool invocations made by the assistant in this message. */\n toolCalls?: ToolCall[];\n /** For `role === \"tool\"`: the name of the tool whose result this message carries. */\n toolName?: string;\n /** For `role === \"tool\"`: `true` when the tool returned an error. */\n isError?: boolean;\n /** Optional structured payload for tool results. */\n data?: unknown;\n}\n\n/**\n * A typed block within an {@link AgentMessage}'s content array.\n *\n * Mirrors the Anthropic content block schema but is driver-agnostic.\n *\n * @docLink packages/bridge/concepts#content-block\n */\nexport interface ContentBlock {\n /** Block discriminant. */\n type: \"text\" | \"tool_use\" | \"tool_result\" | \"thinking\";\n /** Present for `text` and `thinking` blocks. */\n text?: string;\n /** Tool use / tool result correlation ID. */\n id?: string;\n /** Tool name (present on `tool_use` blocks). */\n name?: string;\n /** Tool input arguments (present on `tool_use` blocks). */\n input?: any;\n /** Serialised tool result content (present on `tool_result` blocks). */\n content?: string;\n}\n\n/**\n * A single tool invocation made by the agent within a message.\n *\n * @docLink packages/bridge/concepts#tool-call\n */\nexport interface ToolCall {\n /** Correlation ID used to match the call with its result. */\n id: string;\n /** Name of the tool being invoked. */\n name: string;\n /** Arguments passed to the tool. */\n input: any;\n}\n\n/**\n * Error classification for agent failures.\n *\n * Used to determine whether a failure is retryable and to surface actionable\n * hints to the user. See `bridge/CLAUDE.md` for the full category-to-behaviour matrix.\n *\n * @see AgentError\n * @docLink packages/bridge/concepts#error-category\n */\nexport type ErrorCategory =\n | \"auth\"\n | \"account\"\n | \"rate_limit\"\n | \"model\"\n | \"network\"\n | \"config\"\n | \"process\"\n | \"validation\"\n | \"unknown\";\n\n/**\n * Structured error payload emitted inside the `error` {@link AgentEvent}.\n *\n * Consumers should inspect `retryable` before deciding to surface a retry button,\n * and `hint` to provide an actionable message to the user.\n *\n * @docLink packages/bridge/concepts#agent-error\n */\nexport interface AgentError {\n /** Human-readable error description. */\n message: string;\n /** Coarse failure classification used for retry logic and telemetry. */\n category: ErrorCategory;\n /** HTTP status code if the error originated from an API response. */\n statusCode?: number;\n /** `true` when the caller may safely retry the same operation. */\n retryable: boolean;\n /** Short actionable advice suitable for display in the UI. */\n hint?: string;\n}\n\n/**\n * Metadata for a slash command exposed by the active agent runtime.\n *\n * @docLink packages/bridge/concepts#slash-command-info\n */\nexport interface SlashCommandInfo {\n /** Command name without the leading slash (e.g. `\"compact\"`). */\n name: string;\n /** One-line description shown in command pickers. */\n description: string;\n /** Placeholder text describing what argument the command expects. */\n argumentHint?: string;\n}\n\n/**\n * Discriminated union of all events emitted by a driver on the `'agent-event'` channel.\n *\n * @remarks\n * Consumers listen via `driver.on('agent-event', (event: AgentEvent) => ...)`.\n * The `[k: string]: any` index signature on most variants allows drivers to attach\n * driver-specific fields (e.g. `_textDelta`) without breaking the union.\n *\n * @docLink packages/bridge/concepts#agent-event\n */\nexport type AgentEvent =\n | { type: \"message_start\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_update\"; message: AgentMessage; [k: string]: any }\n | { type: \"message_end\"; message: AgentMessage; [k: string]: any }\n | { type: \"turn_end\"; toolResults?: AgentMessage[]; [k: string]: any }\n | { type: \"agent_end\"; [k: string]: any }\n | {\n type: \"result\";\n subtype: string;\n summary?: string;\n costUsd?: number;\n /** Per-turn token usage when the driver tracks it. Added in 3.1.0. */\n tokens?: TokenUsage;\n errors?: string[];\n [k: string]: any;\n }\n | { type: \"error\"; error: string; detail?: AgentError; fatal?: boolean; [k: string]: any }\n | { type: \"tool_call\"; name?: string; tool?: { name: string }; [k: string]: any }\n | { type: \"tool_execution_end\"; toolName?: string; [k: string]: any }\n | { type: \"commands_available\"; commands: SlashCommandInfo[] }\n | { type: \"session_info\"; driverSessionId: string; sessionFile?: string }\n | { type: \"ui_render\"; [k: string]: any }\n | { type: \"ui_render_update\"; [k: string]: any }\n | { type: \"ui_clear\"; [k: string]: any }\n // Phase 3 (resume cascade) — driver-emitted resume outcome.\n | {\n type: \"resume_failed\";\n resumeSessionId: string;\n reason: \"signature_mismatch\" | \"model_mismatch\" | \"jsonl_lost\" | \"jsonl_poisoned\";\n [k: string]: any;\n };\n\n/**\n * Abstract base class for agent driver backends.\n *\n * Wraps an LLM coding agent behind a single `prompt()` interface.\n * All drivers emit `'agent-event'` with {@link AgentEvent} payloads.\n *\n * @remarks\n * Subclasses must implement `start`, `prompt`, `abort`, `kill`, and `isRunning`.\n * Implementations should never emit an event name other than `'agent-event'` as\n * the public streaming channel — internal events (`'ready'`, `'exit'`, etc.) are\n * driver-private.\n *\n * @example\n * ```ts\n * const driver = createDriver('omp', config);\n * driver.on('agent-event', (event) => console.log(event.type));\n * await driver.start();\n * await driver.prompt('Refactor the auth module');\n * driver.kill();\n * ```\n *\n * @docLink packages/bridge/concepts#agent-driver\n */\nexport abstract class AgentDriver extends EventEmitter {\n /** Static metadata describing this driver's capabilities. */\n abstract readonly driverInfo: DriverInfo;\n\n /**\n * Initialises the driver backend — spawns the child process (omp) or loads\n * the SDK module (claude-sdk). Resolves when the backend is ready to accept\n * prompts. Idempotent: calling `start()` on an already-running driver is a no-op.\n *\n * @throws {Error} When the backend binary is missing or the SDK cannot be loaded.\n */\n abstract start(): Promise<void>;\n\n /**\n * Sends a user message to the agent and resolves when the agent's turn completes\n * (i.e. after the `agent_end` event has been emitted).\n *\n * @param message - Plain-text user prompt to send to the agent.\n * @throws {Error} When the driver is not running or the underlying backend reports a fatal error.\n */\n abstract prompt(message: string): Promise<void>;\n\n /**\n * Sends an in-band abort signal to the agent, requesting it to stop the current\n * turn without terminating the process. The driver remains usable after `abort()`.\n *\n * @remarks Only meaningful when `driverInfo.supportsInBandAbort` is `true`.\n * For other drivers, prefer `kill()` followed by creating a new driver instance.\n */\n abstract abort(): Promise<void>;\n\n /**\n * Terminates the agent backend immediately (SIGTERM for subprocess drivers,\n * `close()` for in-process drivers). The driver instance must not be reused\n * after `kill()`.\n */\n abstract kill(): void;\n\n /** `true` when the backend is alive and able to accept new prompts. */\n abstract get isRunning(): boolean;\n\n /** Optional provider-native session/thread identifier for resume support. */\n get runtimeSessionId(): string | undefined {\n return undefined;\n }\n\n /** Slash commands discovered from the agent runtime. Override in drivers that support introspection. */\n getSlashCommands(): SlashCommandInfo[] {\n return [];\n }\n\n // ── Interactive questions (AskUserQuestion) ──────────────────────────────\n\n /**\n * `true` while the driver is paused on an interactive question and waiting\n * for the user's answer rather than a new prompt. The runner routes a\n * `reply` command to {@link answerQuestion} instead of {@link prompt} when\n * this returns `true`. Drivers without interactive-question support return\n * `false` (the default), so a `reply` falls back to `prompt`.\n */\n hasPendingQuestion(): boolean {\n return false;\n }\n\n /**\n * Deliver the user's answer to the question the driver is currently paused\n * on. This resumes the in-flight turn — it does NOT start a new one. When a\n * single tool call asks several questions, the driver resolves the underlying\n * call only once every sub-question has an answer.\n *\n * @param answer - The user's reply text (an option label, free text, or for\n * multi-select a comma-joined list).\n * @param question - The sub-question this answers, verbatim from the\n * `question` event that asked it. Supply it whenever the host lets the user\n * answer out of order — without it the answer fills the next unanswered\n * slot in order, which silently mismatches a non-sequential reply.\n * @returns `true` when the answer was consumed by a pending question; `false`\n * when no question was pending (caller should treat the reply as a prompt).\n */\n answerQuestion(answer: string, question?: string): boolean {\n void answer;\n void question;\n return false;\n }\n\n // ── Live reconfiguration ────────────────────────────────────────────────\n\n /**\n * Live-update driver configuration. The new values take effect on the next\n * prompt() call. Only model/thinking/effort are reconfigurable mid-session.\n *\n * Subclasses that store config locally should override this to apply the\n * patch to their own config field. The base implementation is a no-op.\n */\n reconfigure(patch: Partial<Pick<AgentConfig, \"model\" | \"thinking\" | \"effort\">>): void {\n // No-op — subclasses override to apply to their own config.\n void patch;\n }\n\n /**\n * Returns the model identifier currently configured on this driver.\n * Subclasses that store config locally should override this.\n */\n getModel(): string | undefined {\n return undefined;\n }\n\n // ── Compaction support ──────────────────────────────────────────────────\n\n /**\n * Returns the token usage from the most recent completed turn.\n * Returns `null` if usage data is unavailable (e.g. driver doesn't track it).\n *\n * Widened in 3.1.0 to return the full `TokenUsage` shape (input / output /\n * cache-read / cache-creation / reasoning). All fields are optional so\n * drivers can populate just what their provider reports. Existing callers\n * that read only `inputTokens` / `outputTokens` keep working — those fields\n * are still present and carry the same semantics as before.\n */\n getTokenUsage(): TokenUsage | null {\n return null;\n }\n\n /**\n * Returns the model's context window size in tokens.\n * Returns `null` if unknown.\n */\n getContextWindow(): number | null {\n return null;\n }\n\n /**\n * Returns the list of models available to this driver without starting a session.\n * Drivers that can enumerate their own models override this method.\n * Returns an empty array by default.\n */\n async listModels(): Promise<ModelEntry[]> {\n return [];\n }\n\n /**\n * Closes the current conversation session and prepares for a fresh start.\n * The next `prompt()` call will begin a new session without prior history.\n * The driver remains usable after `resetSession()`.\n */\n abstract resetSession(): Promise<void>;\n\n // ── Telemetry ─────────────────────────────────────────────────────────────\n\n protected _telemetry?: TelemetryProvider;\n protected _activeTrace?: Trace;\n protected _activeTurnSpan?: Span;\n private _turnStartTime?: number;\n\n /**\n * Attach a telemetry provider and active trace to this driver.\n * Called by the runner after creating the driver but before start().\n */\n setTelemetry(provider: TelemetryProvider, trace: Trace): void {\n this._telemetry = provider;\n this._activeTrace = trace;\n }\n\n /**\n * Begin a turn span. Called by the runner before prompt().\n * Pass a parent span (e.g. the turn span from the orchestrator) for nesting.\n * Returns the span so the runner can annotate it further.\n */\n beginTurnSpan(\n parent?: Trace | Span,\n attrs?: Record<string, string | number | boolean>,\n ): Span | undefined {\n if (!this._telemetry || !this._activeTrace) return undefined;\n this._turnStartTime = Date.now();\n this._activeTurnSpan = this._telemetry.startSpan(parent ?? this._activeTrace, {\n name: \"llm_generation\",\n kind: \"llm_generation\",\n attributes: attrs,\n });\n return this._activeTurnSpan;\n }\n\n /**\n * End the current turn span with generation data.\n * Called by the runner after agent_end. Model and provider are passed\n * explicitly — the driver base class does not access config directly.\n */\n endTurnSpan(result?: {\n model?: string;\n provider?: string;\n inputTokens?: number;\n outputTokens?: number;\n stopReason?: string;\n error?: string;\n }): void {\n if (!this._telemetry || !this._activeTurnSpan) return;\n const durationMs = this._turnStartTime ? Date.now() - this._turnStartTime : 0;\n\n if (result?.inputTokens !== undefined || result?.outputTokens !== undefined) {\n this._telemetry.logGeneration(this._activeTurnSpan, {\n model: result?.model ?? \"unknown\",\n provider: result?.provider ?? \"unknown\",\n inputTokens: result.inputTokens,\n outputTokens: result.outputTokens,\n durationMs,\n stopReason: result.stopReason,\n });\n }\n\n this._telemetry.endSpan(this._activeTurnSpan, {\n status: result?.error ? \"error\" : \"ok\",\n error: result?.error,\n attributes: { \"skaile.turn.duration_ms\": durationMs },\n });\n\n this._activeTurnSpan = undefined;\n this._turnStartTime = undefined;\n }\n}\n\n/**\n * Factory function signature registered in the driver registry.\n *\n * @param config - Configuration for the new driver instance.\n * @returns A freshly constructed (not yet started) {@link AgentDriver}.\n * @docLink packages/bridge/concepts#driver-factory\n */\nexport type DriverFactory = (config: AgentConfig) => AgentDriver;\n","import type { DriverContext } from \"@skaile/workspaces/plugin-registry\";\nimport { type PluginRegistry, pluginRegistry } from \"@skaile/workspaces/plugin-registry\";\nimport type { ModelEntry } from \"./models.js\";\nimport type { AgentConfig, AgentDriver, DriverInfo } from \"./types.js\";\n\n// Build-time backend gating. `bun build --compile --define:__INCLUDE_*__=...`\n// folds these to literal booleans so an excluded backend's driver module and\n// its SDK are dead-code-stripped from the binary. Under tsup / vitest / bun\n// run-on-source no `--define` runs and the `typeof` guard defaults to `true` —\n// every backend is available (the SDKs stay optional peers).\ndeclare const __INCLUDE_CLAUDE_SDK__: boolean;\ndeclare const __INCLUDE_CODEX__: boolean;\nconst INCLUDE_CLAUDE_SDK =\n typeof __INCLUDE_CLAUDE_SDK__ === \"undefined\" ? true : __INCLUDE_CLAUDE_SDK__;\nconst INCLUDE_CODEX = typeof __INCLUDE_CODEX__ === \"undefined\" ? true : __INCLUDE_CODEX__;\n\n/**\n * Static capability metadata for every built-in backend.\n *\n * Pure data — this object imports no driver module and references no backend\n * SDK. {@link listDrivers} returns it (merged with any third-party drivers)\n * so selection UIs can enumerate every backend without loading a single\n * driver module. The matching driver module's `DriverTarget` is registered\n * into the plugin registry by {@link registerBuiltinDrivers}.\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport const BUILTIN_DRIVER_CATALOG: Record<string, DriverInfo> = {\n omp: {\n id: \"omp\",\n name: \"omp (oh-my-pi)\",\n modelAgnostic: true,\n supportsInBandAbort: true,\n },\n \"claude-sdk\": {\n id: \"claude-sdk\",\n name: \"Claude Agent SDK\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n },\n codex: {\n id: \"codex\",\n name: \"OpenAI Codex\",\n modelAgnostic: false,\n supportsInBandAbort: true,\n },\n echo: {\n id: \"echo\",\n name: \"Echo (E2E mock)\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n gemini: {\n id: \"gemini\",\n name: \"Gemini CLI\",\n modelAgnostic: false,\n supportsInBandAbort: false,\n },\n qwen: {\n id: \"qwen\",\n name: \"Qwen Code\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n opencode: {\n id: \"opencode\",\n name: \"OpenCode\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n goose: {\n id: \"goose\",\n name: \"Goose\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n continue: {\n id: \"continue\",\n name: \"Continue CLI\",\n modelAgnostic: true,\n supportsInBandAbort: false,\n },\n};\n\n/**\n * Back-compat alias for {@link BUILTIN_DRIVER_CATALOG}. Consumers and tests that\n * predate the plugin-registry refactor still import `DRIVER_CATALOG`.\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport const DRIVER_CATALOG = BUILTIN_DRIVER_CATALOG;\n\nlet _driversRegistered = false;\n\n/**\n * Register every built-in driver's `DriverTarget` into the plugin registry.\n *\n * This is the single id → module map in bridge core. Every specifier is a\n * literal string so `bun --compile` can statically bundle the driver module\n * (and, transitively, its SDK). The in-process-SDK backends (`claude-sdk`,\n * `codex`) are wrapped in build-constant guards so an excluded backend's\n * `await import` folds to dead code in the compiled binary. `omp` and `echo`\n * carry no SDK weight and are always available.\n *\n * **Static import discipline.** Every `import()` specifier below must be a\n * string literal — never aliased through a variable. Indirection defeats\n * `bun --compile`'s static analysis and silently drops the module from the\n * binary.\n *\n * Idempotent: guarded by a module flag so a second call is a no-op (a duplicate\n * `register` would otherwise throw `RegistrationError`).\n *\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function registerBuiltinDrivers(\n registry: PluginRegistry = pluginRegistry,\n): Promise<void> {\n if (registry === pluginRegistry && _driversRegistered) return;\n\n if (!registry.get(\"driver\", \"omp\")) {\n const m = await import(\"@skaile/workspaces/drivers/omp\");\n registry.register(\"driver\", m.ompDriverTarget);\n }\n if (!registry.get(\"driver\", \"echo\")) {\n const m = await import(\"@skaile/workspaces/drivers/echo\");\n registry.register(\"driver\", m.echoDriverTarget);\n }\n if (INCLUDE_CLAUDE_SDK && !registry.get(\"driver\", \"claude-sdk\")) {\n const m = await import(\"@skaile/workspaces/drivers/claude-sdk\");\n registry.register(\"driver\", m.claudeSdkDriverTarget);\n }\n if (INCLUDE_CODEX && !registry.get(\"driver\", \"codex\")) {\n const m = await import(\"@skaile/workspaces/drivers/codex\");\n registry.register(\"driver\", m.codexDriverTarget);\n }\n // Subprocess CLI backends spawn an external binary the user installs\n // separately — no bundled SDK to dead-code-strip, so (like omp/echo) they\n // carry no build constant and are always registered.\n if (!registry.get(\"driver\", \"gemini\")) {\n const m = await import(\"@skaile/workspaces/drivers/gemini\");\n registry.register(\"driver\", m.geminiDriverTarget);\n }\n if (!registry.get(\"driver\", \"qwen\")) {\n const m = await import(\"@skaile/workspaces/drivers/qwen\");\n registry.register(\"driver\", m.qwenDriverTarget);\n }\n if (!registry.get(\"driver\", \"opencode\")) {\n const m = await import(\"@skaile/workspaces/drivers/opencode\");\n registry.register(\"driver\", m.opencodeDriverTarget);\n }\n if (!registry.get(\"driver\", \"goose\")) {\n const m = await import(\"@skaile/workspaces/drivers/goose\");\n registry.register(\"driver\", m.gooseDriverTarget);\n }\n if (!registry.get(\"driver\", \"continue\")) {\n const m = await import(\"@skaile/workspaces/drivers/continue\");\n registry.register(\"driver\", m.continueDriverTarget);\n }\n\n if (registry === pluginRegistry) _driversRegistered = true;\n}\n\n/**\n * Creates a new driver instance for the given backend id.\n *\n * Ensures the built-in driver targets are registered (idempotent), then looks\n * up the target in the plugin registry and calls its `create()`. The returned\n * driver has not been started yet — call `driver.start()` before sending\n * prompts.\n *\n * @param id - Registered driver identifier (e.g. `\"omp\"`, `\"claude-sdk\"`).\n * @param config - Configuration forwarded to the driver constructor.\n * @param ctx - Optional driver context (logger / abort signal). Defaults to `{}`.\n * @returns A freshly constructed (not yet started) {@link AgentDriver}.\n * @throws {Error} When `id` is a known backend excluded from this build, or\n * when `id` does not match any registered driver at all.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function createDriver(\n id: string,\n config: AgentConfig,\n ctx?: DriverContext,\n): Promise<AgentDriver> {\n const target = await resolveDriverTarget(id);\n return target.create(config, ctx ?? {});\n}\n\n/**\n * Resolve a registered driver target by id, ensuring the built-ins are\n * registered first. Throws the canonical \"not bundled\" / \"unknown driver\"\n * errors so every caller (`createDriver`, `listModelsForDriver`) reports an\n * unrecognized id the same way instead of silently degrading.\n *\n * @throws {Error} When `id` is a known backend excluded from this build, or\n * when `id` does not match any registered driver at all.\n */\nasync function resolveDriverTarget(id: string) {\n await registerBuiltinDrivers();\n const target = pluginRegistry.get(\"driver\", id);\n if (!target) {\n if (id in BUILTIN_DRIVER_CATALOG) {\n throw new Error(`Agent driver \"${id}\" is not bundled in this build.`);\n }\n throw new Error(\n `Unknown agent driver: \"${id}\". Available: ${listDrivers()\n .map((d) => d.id)\n .join(\", \")}`,\n );\n }\n return target;\n}\n\n/**\n * Returns the capability metadata for every available driver.\n *\n * Enumerates every built-in backend from {@link BUILTIN_DRIVER_CATALOG} without\n * loading a single driver module or backend SDK, then merges in any third-party\n * driver targets registered into the plugin registry that are not already in\n * the catalog. Use this to populate driver selection UIs.\n *\n * @returns Array of {@link DriverInfo} objects, one per available driver.\n * @docLink packages/bridge/api-reference#registry\n */\nexport function listDrivers(): DriverInfo[] {\n const merged = new Map<string, DriverInfo>();\n for (const info of Object.values(BUILTIN_DRIVER_CATALOG)) {\n merged.set(info.id, info);\n }\n for (const meta of pluginRegistry.list(\"driver\")) {\n if (!merged.has(meta.id)) {\n // Third-party drivers carry no DriverInfo row; read the capability flags\n // off the registered target (defaulting to conservative false) so a\n // model-agnostic / in-band-abort backend can still advertise them.\n const target = pluginRegistry.get(\"driver\", meta.id);\n merged.set(meta.id, {\n id: meta.id,\n name: meta.displayName,\n modelAgnostic: target?.modelAgnostic ?? false,\n supportsInBandAbort: target?.supportsInBandAbort ?? false,\n });\n }\n }\n return [...merged.values()];\n}\n\n/**\n * List models available to a specific driver without starting a full agent session.\n *\n * Ensures the built-in driver targets are registered (idempotent), then\n * delegates to the target's optional `listModels()`. API keys are forwarded so\n * drivers can authenticate against provider REST APIs if needed. Throws on an\n * unknown / not-bundled id (same contract as {@link createDriver}); returns `[]`\n * only when the target exists but exposes no `listModels`.\n *\n * @param driverId - Registered driver id (e.g. `\"omp\"`, `\"claude-sdk\"`, `\"codex\"`).\n * @param apiKeys - Provider API keys keyed by provider name (e.g. `{ anthropic: \"sk-...\" }`).\n * Pass `settings.apiKeys ?? {}` from forge-assistant's resolved settings.\n * @throws {Error} When `driverId` is unknown or excluded from this build.\n * @docLink packages/bridge/api-reference#registry\n */\nexport async function listModelsForDriver(\n driverId: string,\n apiKeys: Record<string, string>,\n): Promise<ModelEntry[]> {\n const target = await resolveDriverTarget(driverId);\n return (await target.listModels?.(apiKeys)) ?? [];\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { resolveFlowBindings, stableFlowJson, evaluateFlowExpression, FlowExpressionError, parseFlowDefinition, inspectFlowExpression, collectFlowBindingExpressions } from './chunk-
|
|
2
|
-
import { isAgentNode, nodeBindings, isRouterNode, nodeIsOptional, nodeSkillId, nodeLabel, isActiveRuntimeNode } from './chunk-
|
|
1
|
+
import { resolveFlowBindings, stableFlowJson, evaluateFlowExpression, FlowExpressionError, parseFlowDefinition, inspectFlowExpression, collectFlowBindingExpressions } from './chunk-5QGMEPUX.js';
|
|
2
|
+
import { isAgentNode, isSubpromptNode, nodeBindings, isRouterNode, nodeIsOptional, nodeSkillId, nodeLabel, isActiveRuntimeNode } from './chunk-F5VREBV2.js';
|
|
3
3
|
import { assetSearchDirs } from './chunk-ZAP2BDHG.js';
|
|
4
4
|
import * as z2 from 'zod';
|
|
5
5
|
import * as path from 'path';
|
|
@@ -23,7 +23,10 @@ function buildFlowExpressionContext(flow, snapshots) {
|
|
|
23
23
|
}
|
|
24
24
|
function resolveNodeBindings(flow, node, snapshots, flowInputOrigins = {}) {
|
|
25
25
|
const origins = Object.fromEntries(
|
|
26
|
-
flow.nodes.map((producer) => [
|
|
26
|
+
flow.nodes.map((producer) => [
|
|
27
|
+
producer.id,
|
|
28
|
+
isAgentNode(producer) || isSubpromptNode(producer) ? "agent" : "runtime"
|
|
29
|
+
])
|
|
27
30
|
);
|
|
28
31
|
return resolveFlowBindings(
|
|
29
32
|
nodeBindings(node),
|
|
@@ -832,5 +835,5 @@ function loadAllFlows(aiResourcesRoot) {
|
|
|
832
835
|
}
|
|
833
836
|
|
|
834
837
|
export { FlowManifestSchema, appendAttempt, availableRouterFrontier, buildFlowExpressionContext, computeFlowState, computeFlowStateFromSnapshots, computeSkippable, countFailedAttempts, deriveCheckEvidence, evaluateRouterSelection, flowKindProvider, getConsumedOutputSchema, hasAutomaticRetryBudget, interpolateNodeInstruction, isActiveExecutionExpired, isBlocking, loadAllFlows, loadFlow, loadFlowsFromDir, nextAttemptNumber, persistedRouterSelection, planRouterSkips, remainingActiveExecutionMs, resolveAvailableRouter, resolveNextNodes, resolveNodeBindings, routerSelectionOutput, unsettledRouterBranchIds, validateConsumedNodeOutput, validateFlow };
|
|
835
|
-
//# sourceMappingURL=chunk-
|
|
836
|
-
//# sourceMappingURL=chunk-
|
|
838
|
+
//# sourceMappingURL=chunk-S5FV6ISY.js.map
|
|
839
|
+
//# sourceMappingURL=chunk-S5FV6ISY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../factory-assets/connectors/flow/engine/bindings.ts","../factory-assets/connectors/flow/engine/router-settlement.ts","../factory-assets/connectors/flow/engine/engine.ts","../factory-assets/connectors/flow/engine/output-schema.ts","../factory-assets/connectors/flow/engine/node-deadline.ts","../factory-assets/connectors/flow/engine/node-attempts.ts","../factory-assets/connectors/flow/engine/check-provenance.ts","../factory-assets/connectors/flow/engine/flow-manifest.ts","../factory-assets/connectors/flow/engine/flow-kind-provider.ts","../factory-assets/connectors/flow/engine/loader.ts"],"names":["path","z","process","parseYaml"],"mappings":"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","file":"chunk-S5FV6ISY.js","sourcesContent":["import {\n resolveFlowBindings,\n stableFlowJson,\n type BindingOrigin,\n type FlowExpressionContext,\n type ResolvedNodeBindings,\n} from \"../contract/expression.js\";\nimport { isAgentNode, isSubpromptNode, nodeBindings } from \"./node-shape.js\";\nimport type { FlowDefinition, FlowNode, NodeExecutionSnapshot } from \"./types.js\";\n\n/** Build the bounded expression context from immutable definition and snapshot state. */\nexport function buildFlowExpressionContext(\n flow: FlowDefinition,\n snapshots: Map<string, NodeExecutionSnapshot>,\n): FlowExpressionContext {\n const nodes: FlowExpressionContext[\"nodes\"] = {};\n for (const node of flow.nodes) {\n const snapshot = snapshots.get(node.id);\n const output =\n snapshot?.status === \"complete\" && snapshot.output?.fields\n ? { fields: snapshot.output.fields }\n : undefined;\n nodes[node.id] = { status: snapshot?.status ?? \"not_started\", output };\n }\n return {\n flow: { input: flow.defaults?.run_input ?? {} },\n defaults: flow.defaults,\n nodes,\n };\n}\n\n/** Resolve one node's named inputs and derive their runtime/agent origins. */\nexport function resolveNodeBindings(\n flow: FlowDefinition,\n node: FlowNode,\n snapshots: Map<string, NodeExecutionSnapshot>,\n flowInputOrigins: Record<string, BindingOrigin[]> = {},\n): ResolvedNodeBindings {\n // A subprompt's output is model-generated the same as an agent's, even though\n // the runtime (not the session agent) makes the call — so a downstream check\n // must derive \"asserted\", never \"verified\", over it. See engine/check-provenance.ts.\n const origins = Object.fromEntries(\n flow.nodes.map((producer) => [\n producer.id,\n isAgentNode(producer) || isSubpromptNode(producer) ? \"agent\" : \"runtime\",\n ]),\n ) as Record<string, \"agent\" | \"runtime\">;\n return resolveFlowBindings(\n nodeBindings(node),\n buildFlowExpressionContext(flow, snapshots),\n origins,\n flowInputOrigins,\n );\n}\n\n/** Interpolate named, already-resolved binding values into an agent instruction. */\nexport function interpolateNodeInstruction(\n instruction: string,\n values: Record<string, unknown>,\n): string {\n return instruction.replace(/\\$\\{([A-Za-z_][A-Za-z0-9_-]*)\\}/g, (_placeholder, name: string) => {\n if (!Object.hasOwn(values, name)) {\n throw new Error(`Node instruction binding ${name} is missing`);\n }\n const value = values[name];\n return typeof value === \"string\" ? value : stableFlowJson(value);\n });\n}\n","import type { NodeOutput } from \"@skaile/workspaces/types\";\nimport { evaluateFlowExpression, FlowExpressionError } from \"../contract/expression.js\";\nimport { buildFlowExpressionContext } from \"./bindings.js\";\nimport { isRouterNode } from \"./node-shape.js\";\nimport type { FlowDefinition, FlowNode, NodeExecutionSnapshot } from \"./types.js\";\n\nconst ROUTER_SELECTION_MARKER = \"\\n\\n[skaile:flow-router-selection:\";\n\n/** One deterministic router choice being settled in the current atomic batch. */\nexport interface RouterSettlement {\n routerNodeId: string;\n selectedTarget: string | null;\n}\n\n/** Internal result of evaluating one already-admitted router. */\nexport type RouterSelection =\n | { selectedTarget: string | null }\n | { unresolved: \"not-ready\" | \"no-match\" };\n\nfunction pendingProducerOutput(\n flow: FlowDefinition,\n snapshots: Map<string, NodeExecutionSnapshot>,\n missingPath: string | undefined,\n): boolean {\n if (!missingPath) return false;\n const segments = missingPath.split(\".\");\n if (\n segments.length < 5 ||\n segments[0] !== \"nodes\" ||\n segments[2] !== \"output\" ||\n segments[3] !== \"fields\"\n ) {\n return false;\n }\n const producer = flow.nodes.find(({ id }) => id === segments[1]);\n if (!producer?.contract?.output?.fields) return false;\n return snapshots.get(producer.id)?.status !== \"complete\";\n}\n\n/** Evaluate ordered routes for a router whose availability was already established. */\nexport function evaluateRouterSelection(\n flow: FlowDefinition,\n router: FlowNode,\n snapshots: Map<string, NodeExecutionSnapshot>,\n): RouterSelection {\n if (!isRouterNode(router)) return { unresolved: \"no-match\" };\n const context = buildFlowExpressionContext(flow, snapshots);\n for (const route of router.run.routes) {\n try {\n if (evaluateFlowExpression(route.when, context)) {\n return { selectedTarget: route.target };\n }\n } catch (error) {\n if (\n error instanceof FlowExpressionError &&\n pendingProducerOutput(flow, snapshots, error.missingPath)\n ) {\n return { unresolved: \"not-ready\" };\n }\n throw error;\n }\n }\n return { unresolved: \"no-match\" };\n}\n\n/** Encode a router choice in the existing durable node-output envelope. */\nexport function routerSelectionOutput(selectedTarget: string | null): NodeOutput {\n const summary =\n selectedTarget === null\n ? \"Router completed without selecting a target.\"\n : `Router selected ${selectedTarget}.`;\n return {\n summary: `${summary}${ROUTER_SELECTION_MARKER}${JSON.stringify(selectedTarget)}]`,\n artifacts: [],\n };\n}\n\nfunction routeTargets(router: FlowNode): string[] {\n if (!isRouterNode(router)) return [];\n return [...new Set(router.run.routes.flatMap(({ target }) => (target === null ? [] : [target])))];\n}\n\ninterface RouterOwnershipIndex {\n routers: FlowNode[];\n outgoing: Map<string, string[]>;\n}\n\n/** Index router-to-router ownership through route targets and hard-flow descendants. */\nfunction routerOwnershipIndex(\n flow: FlowDefinition,\n snapshots: Map<string, NodeExecutionSnapshot>,\n): RouterOwnershipIndex {\n const routers = flow.nodes.filter(\n (node) =>\n isRouterNode(node) &&\n ![\"complete\", \"failed\", \"skipped\"].includes(snapshots.get(node.id)?.status ?? \"not_started\"),\n );\n const routerIds = new Set(routers.map(({ id }) => id));\n const hardOutgoing = new Map<string, string[]>();\n for (const edge of flow.edges) {\n if (edge.type !== \"flow\") continue;\n const targets = hardOutgoing.get(edge.source) ?? [];\n targets.push(edge.target);\n hardOutgoing.set(edge.source, targets);\n }\n\n const outgoing = new Map<string, string[]>();\n for (const router of routers) {\n const owned = new Set<string>();\n const visited = new Set<string>();\n const queue = routeTargets(router);\n for (let index = 0; index < queue.length; index++) {\n const nodeId = queue[index];\n if (visited.has(nodeId)) continue;\n visited.add(nodeId);\n if (routerIds.has(nodeId)) owned.add(nodeId);\n queue.push(...(hardOutgoing.get(nodeId) ?? []));\n }\n outgoing.set(router.id, [...owned]);\n }\n return { routers, outgoing };\n}\n\n/**\n * Return every member of each source router-ownership SCC.\n *\n * Route ownership is deliberately not a dependency arc and may cycle even though hard flow is\n * acyclic. Source SCC members are ungated so normal hard-edge/precondition admission and ordered\n * decidability select the settlement frontier. Ordinary parent components remain ahead of nested\n * children, while self-targeting and mutually targeting routers cannot deadlock admission. The\n * graph is preindexed and both SCC passes are iterative.\n */\nfunction routerOwnershipSourceComponents(\n flow: FlowDefinition,\n snapshots: Map<string, NodeExecutionSnapshot>,\n): string[][] {\n const { routers, outgoing } = routerOwnershipIndex(flow, snapshots);\n const reverse = new Map<string, string[]>();\n for (const router of routers) reverse.set(router.id, []);\n for (const [source, targets] of outgoing) {\n for (const target of targets) reverse.get(target)?.push(source);\n }\n\n const visited = new Set<string>();\n const finished: string[] = [];\n for (const router of routers) {\n if (visited.has(router.id)) continue;\n const stack: Array<{ nodeId: string; exiting: boolean }> = [\n { nodeId: router.id, exiting: false },\n ];\n while (stack.length > 0) {\n const frame = stack.pop();\n if (!frame) break;\n if (frame.exiting) {\n finished.push(frame.nodeId);\n continue;\n }\n if (visited.has(frame.nodeId)) continue;\n visited.add(frame.nodeId);\n stack.push({ nodeId: frame.nodeId, exiting: true });\n const targets = outgoing.get(frame.nodeId) ?? [];\n for (let index = targets.length - 1; index >= 0; index--) {\n if (!visited.has(targets[index])) {\n stack.push({ nodeId: targets[index], exiting: false });\n }\n }\n }\n }\n\n const componentByRouter = new Map<string, number>();\n const components: string[][] = [];\n for (let index = finished.length - 1; index >= 0; index--) {\n const start = finished[index];\n if (componentByRouter.has(start)) continue;\n const componentId = components.length;\n const component: string[] = [];\n const stack = [start];\n componentByRouter.set(start, componentId);\n while (stack.length > 0) {\n const nodeId = stack.pop();\n if (!nodeId) break;\n component.push(nodeId);\n for (const source of reverse.get(nodeId) ?? []) {\n if (componentByRouter.has(source)) continue;\n componentByRouter.set(source, componentId);\n stack.push(source);\n }\n }\n components.push(component);\n }\n\n const incomingComponents = new Set<number>();\n for (const [source, targets] of outgoing) {\n const sourceComponent = componentByRouter.get(source);\n for (const target of targets) {\n const targetComponent = componentByRouter.get(target);\n if (\n sourceComponent !== undefined &&\n targetComponent !== undefined &&\n sourceComponent !== targetComponent\n ) {\n incomingComponents.add(targetComponent);\n }\n }\n }\n\n const definitionOrder = new Map(flow.nodes.map((node, index) => [node.id, index]));\n const sourceComponents = components.filter(\n (_, componentId) => !incomingComponents.has(componentId),\n );\n for (const component of sourceComponents) {\n component.sort(\n (left, right) =>\n (definitionOrder.get(left) ?? Number.MAX_SAFE_INTEGER) -\n (definitionOrder.get(right) ?? Number.MAX_SAFE_INTEGER),\n );\n }\n return sourceComponents.sort(\n (left, right) =>\n (definitionOrder.get(left[0]) ?? Number.MAX_SAFE_INTEGER) -\n (definitionOrder.get(right[0]) ?? Number.MAX_SAFE_INTEGER),\n );\n}\n\n/** Decode and validate a completed router's engine-owned selection summary. */\nexport function persistedRouterSelection(\n router: FlowNode,\n snapshot: NodeExecutionSnapshot | undefined,\n): { selectedTarget: string | null } | undefined {\n if (!isRouterNode(router) || snapshot?.status !== \"complete\") return undefined;\n const summary = snapshot.output?.summary;\n const markerIndex = summary?.lastIndexOf(ROUTER_SELECTION_MARKER) ?? -1;\n if (!summary || markerIndex < 0 || !summary.endsWith(\"]\")) return undefined;\n let selectedTarget: unknown;\n try {\n selectedTarget = JSON.parse(summary.slice(markerIndex + ROUTER_SELECTION_MARKER.length, -1));\n } catch {\n return undefined;\n }\n if (\n selectedTarget !== null &&\n (typeof selectedTarget !== \"string\" || !routeTargets(router).includes(selectedTarget))\n ) {\n return undefined;\n }\n if (selectedTarget === null && !router.run.routes.some(({ target }) => target === null)) {\n return undefined;\n }\n return summary === routerSelectionOutput(selectedTarget).summary ? { selectedTarget } : undefined;\n}\n\nfunction edgeKey(source: string, target: string): string {\n return `${source}\\u0000${target}`;\n}\n\n/**\n * Plan exclusive branch skips for all known router choices as one coordinated settlement.\n *\n * Only hard `flow` edges participate. The graph is indexed once, then each distinct losing\n * target performs a linear adjacency walk; optional and parallel edges can neither spread nor\n * preserve exclusivity. A selected route, a still-live unsettled router, shared convergence, or\n * an incoming hard predecessor outside the losing region protects that node and its descendants.\n */\nexport function planRouterSkips(\n flow: FlowDefinition,\n snapshots: Map<string, NodeExecutionSnapshot>,\n settlements: readonly RouterSettlement[],\n): string[] {\n const routers = flow.nodes.filter(isRouterNode);\n const currentSelections = new Map(\n settlements.map(({ routerNodeId, selectedTarget }) => [routerNodeId, selectedTarget]),\n );\n const knownSelections = new Map<string, string | null>();\n for (const router of routers) {\n if (currentSelections.has(router.id)) {\n knownSelections.set(router.id, currentSelections.get(router.id) ?? null);\n continue;\n }\n const persisted = persistedRouterSelection(router, snapshots.get(router.id));\n if (persisted) knownSelections.set(router.id, persisted.selectedTarget);\n }\n\n const outgoing = new Map<string, string[]>();\n const incoming = new Map<string, string[]>();\n for (const edge of flow.edges) {\n if (edge.type !== \"flow\") continue;\n const targets = outgoing.get(edge.source) ?? [];\n targets.push(edge.target);\n outgoing.set(edge.source, targets);\n const sources = incoming.get(edge.target) ?? [];\n sources.push(edge.source);\n incoming.set(edge.target, sources);\n }\n\n const losingRoots = new Set<string>();\n const selectedRoots = new Set<string>();\n const losingRouteEdges = new Set<string>();\n for (const router of routers) {\n if (!knownSelections.has(router.id)) continue;\n const selectedTarget = knownSelections.get(router.id) ?? null;\n if (selectedTarget !== null) selectedRoots.add(selectedTarget);\n for (const target of routeTargets(router)) {\n if (target === selectedTarget) continue;\n losingRoots.add(target);\n losingRouteEdges.add(edgeKey(router.id, target));\n }\n }\n\n const candidateOrigins = new Map<string, Set<string>>();\n for (const root of losingRoots) {\n const visited = new Set<string>();\n const queue = [root];\n for (let index = 0; index < queue.length; index++) {\n const nodeId = queue[index];\n if (visited.has(nodeId)) continue;\n visited.add(nodeId);\n const origins = candidateOrigins.get(nodeId) ?? new Set<string>();\n origins.add(root);\n candidateOrigins.set(nodeId, origins);\n for (const target of outgoing.get(nodeId) ?? []) queue.push(target);\n }\n }\n const candidates = new Set(candidateOrigins.keys());\n\n const protectionQueue = [...selectedRoots];\n for (const [nodeId, origins] of candidateOrigins) {\n if (origins.size >= 2) protectionQueue.push(nodeId);\n for (const source of incoming.get(nodeId) ?? []) {\n if (candidates.has(source)) continue;\n if (losingRouteEdges.has(edgeKey(source, nodeId))) continue;\n if ([\"failed\", \"skipped\"].includes(snapshots.get(source)?.status ?? \"not_started\")) continue;\n protectionQueue.push(nodeId);\n break;\n }\n }\n\n const unknownSelections = new Map<string, string[]>();\n for (const router of routers) {\n if (knownSelections.has(router.id)) continue;\n const status = snapshots.get(router.id)?.status ?? \"not_started\";\n if (status === \"failed\" || status === \"skipped\") continue;\n const targets = routeTargets(router);\n unknownSelections.set(router.id, targets);\n if (!candidates.has(router.id)) protectionQueue.push(...targets);\n }\n\n const protectedNodes = new Set<string>();\n for (let index = 0; index < protectionQueue.length; index++) {\n const nodeId = protectionQueue[index];\n if (protectedNodes.has(nodeId)) continue;\n protectedNodes.add(nodeId);\n protectionQueue.push(...(outgoing.get(nodeId) ?? []));\n protectionQueue.push(...(unknownSelections.get(nodeId) ?? []));\n }\n\n return flow.nodes.flatMap((node) =>\n candidates.has(node.id) && !protectedNodes.has(node.id) ? [node.id] : [],\n );\n}\n\n/**\n * Return every possible target branch gated by an unsettled router.\n *\n * Gating follows hard `flow` descendants only. A selected route, shared convergence, or another\n * live hard predecessor protects a node, matching settlement pruning without mutating snapshots.\n */\nexport function unsettledRouterBranchIds(\n flow: FlowDefinition,\n snapshots: Map<string, NodeExecutionSnapshot>,\n): Set<string> {\n const unsettled = flow.nodes.filter(\n (node) =>\n isRouterNode(node) &&\n ![\"complete\", \"failed\", \"skipped\"].includes(snapshots.get(node.id)?.status ?? \"not_started\"),\n );\n const branches = new Set(\n planRouterSkips(\n flow,\n snapshots,\n unsettled.map(({ id }) => ({ routerNodeId: id, selectedTarget: null })),\n ),\n );\n for (const component of routerOwnershipSourceComponents(flow, snapshots)) {\n for (const routerId of component) branches.delete(routerId);\n }\n return branches;\n}\n\n/**\n * Return one actually available, decidable router per source ownership component.\n *\n * Every source-component member remains ungated for normal admission. Within a settlement wave,\n * definition order chooses the first member that is both available and decidable; unresolved or\n * blocked peers cannot starve it. Limiting each component to one choice prevents a router from\n * completing atomically after that same wave makes its branch losing. Independent source\n * components can still settle together.\n */\nexport function availableRouterFrontier(\n flow: FlowDefinition,\n snapshots: Map<string, NodeExecutionSnapshot>,\n): FlowNode[] {\n const nodesById = new Map(flow.nodes.map((node) => [node.id, node]));\n return routerOwnershipSourceComponents(flow, snapshots).flatMap((component) => {\n for (const routerId of component) {\n const node = nodesById.get(routerId);\n if (!node || snapshots.get(routerId)?.status !== \"available\") continue;\n if (\"unresolved\" in evaluateRouterSelection(flow, node, snapshots)) continue;\n return [node];\n }\n return [];\n });\n}\n","import type {\n FlowDefinition,\n FlowEdge,\n FlowNode,\n FlowState,\n NodeExecutionSnapshot,\n NodePreconditionFailure,\n NodeState,\n NodeStatus,\n} from \"./types.js\";\nimport { evaluateFlowExpression, type FlowExpressionContext } from \"../contract/expression.js\";\nimport { buildFlowExpressionContext } from \"./bindings.js\";\nimport {\n isActiveRuntimeNode,\n isRouterNode,\n nodeIsOptional,\n nodeLabel,\n nodeSkillId,\n} from \"./node-shape.js\";\nimport {\n evaluateRouterSelection,\n planRouterSkips,\n unsettledRouterBranchIds,\n} from \"./router-settlement.js\";\n\n// ---------------------------------------------------------------------------\n// Core engine — stateless, pure functions\n// ---------------------------------------------------------------------------\n\n/** Return nodes with state owned by the current runtime. */\nfunction activeRuntimeNodes(flow: FlowDefinition): FlowNode[] {\n return flow.nodes.filter(isActiveRuntimeNode);\n}\n\n/** Evaluate every authored admission condition without mutating runtime state. */\nfunction failedPreconditions(\n node: FlowNode,\n context: FlowExpressionContext,\n): NodePreconditionFailure[] {\n const failures: NodePreconditionFailure[] = [];\n for (const requirement of node.contract?.requires ?? []) {\n const message = requirement.message ?? `Precondition failed: ${requirement.expr}`;\n try {\n if (!evaluateFlowExpression(requirement.expr, context)) {\n failures.push({ expression: requirement.expr, message, reason: \"false\" });\n }\n } catch (error) {\n failures.push({\n expression: requirement.expr,\n message,\n reason: \"error\",\n detail: error instanceof Error ? error.message : \"Flow expression evaluation failed\",\n });\n }\n }\n return failures;\n}\n\n/** Build adjacency: target → sources[] (incoming edges per node) */\nfunction buildIncoming(edges: FlowEdge[]): Map<string, FlowEdge[]> {\n const map = new Map<string, FlowEdge[]>();\n for (const edge of edges) {\n if (!map.has(edge.target)) map.set(edge.target, []);\n map.get(edge.target)!.push(edge);\n }\n return map;\n}\n\n/** Build adjacency: source → targets[] (outgoing edges per node) */\nfunction buildOutgoing(edges: FlowEdge[]): Map<string, FlowEdge[]> {\n const map = new Map<string, FlowEdge[]>();\n for (const edge of edges) {\n if (!map.has(edge.source)) map.set(edge.source, []);\n map.get(edge.source)!.push(edge);\n }\n return map;\n}\n\n/** Result of resolving one available router against the current expression context. */\nexport interface RouterResolution {\n /** First matching route target. `null` means every branch loses. */\n selectedTarget: string | null;\n /** Exclusive nodes belonging only to unselected route targets, in definition order. */\n skippedNodeIds: string[];\n}\n\n/** Available router that cannot make a deterministic choice from the current snapshot. */\nexport interface UnresolvedRouterResolution {\n /** Why the router remains available for a later drain pass. */\n unresolved: \"not-ready\" | \"no-match\";\n}\n\n/**\n * Resolve the first matching route for a router that is currently available.\n *\n * Route conditions use the same bounded context as node preconditions and bindings. Resolution\n * is deliberately separate from state computation: unavailable routers return `undefined`\n * without evaluating any route. Losing route targets and their exclusive downstream paths are\n * returned for the caller to mark skipped. Exclusivity follows hard `flow` edges only and keeps\n * selected routes, unsettled-router targets, shared convergence, and externally reachable nodes\n * live. A declared producer output that is not complete yet returns a retryable unresolved result;\n * malformed expressions still throw their path-bearing evaluator error.\n *\n * @param flow - Parsed flow containing the router and branch graph.\n * @param routerNodeId - Router execution identity.\n * @param snapshots - Current node snapshots used for admission and expression values.\n * @returns The selected target and losing nodes, an unresolved reason while available but not\n * decidable, or `undefined` while the router is unavailable.\n */\nexport function resolveAvailableRouter(\n flow: FlowDefinition,\n routerNodeId: string,\n snapshots: Map<string, NodeExecutionSnapshot>,\n): RouterResolution | UnresolvedRouterResolution | undefined {\n const router = flow.nodes.find((node) => node.id === routerNodeId);\n if (!router || !isRouterNode(router)) return undefined;\n const state = computeFlowStateFromSnapshots(flow, snapshots);\n if (!state.available.includes(routerNodeId)) return undefined;\n\n const selected = evaluateRouterSelection(flow, router, snapshots);\n if (\"unresolved\" in selected) return selected;\n\n return {\n selectedTarget: selected.selectedTarget,\n skippedNodeIds: planRouterSkips(flow, snapshots, [\n { routerNodeId, selectedTarget: selected.selectedTarget },\n ]),\n };\n}\n\n/**\n * Compute the full {@link FlowState} from a flow definition and caller-supplied node ID sets.\n *\n * This is the primary engine function. It is stateless and side-effect-free — calling it\n * twice with the same arguments always returns an equivalent result.\n *\n * Edge semantics applied during computation:\n * - `'flow'` — hard dependency: target cannot start until source is `complete` or `skipped`.\n * - `'parallel'` — soft dependency: target may run while source is still running.\n * - `'optional'` — advisory: target can start regardless of source state.\n *\n * A node is `available` when every incoming `'flow'`-type edge has a complete or skipped source\n * and every authored precondition evaluates true.\n * A node is `not_started` when at least one hard predecessor is still pending.\n * The flow is `done` when every non-optional node is `complete` or `skipped`.\n *\n * This set-based overload has statuses but no completed output fields. Use\n * {@link computeFlowStateFromSnapshots} when a precondition reads node output.\n *\n * Prefer {@link computeFlowStateFromSnapshots} for callers that track full `NodeExecution`\n * state (interaction statuses such as `awaiting_approval`, `awaiting_input`, `failed`).\n *\n * @param flow - The parsed flow definition.\n * @param completedIds - Set of node IDs that have finished successfully.\n * @param runningIds - Set of node IDs currently executing. Defaults to an empty set.\n * @param skippedIds - Set of node IDs that were explicitly skipped. Skipped nodes count\n * as satisfied for downstream dependency checks. Defaults to an empty set.\n * @returns A {@link FlowState} describing every active runtime node.\n * @docLink packages/flow-engine/concepts#compute-flow-state\n */\nexport function computeFlowState(\n flow: FlowDefinition,\n completedIds: Set<string>,\n runningIds: Set<string> = new Set(),\n skippedIds: Set<string> = new Set(),\n): FlowState {\n const nodes = activeRuntimeNodes(flow);\n const incoming = buildIncoming(flow.edges);\n const snapshots = new Map<string, NodeExecutionSnapshot>();\n for (const node of nodes) {\n const status: NodeStatus = completedIds.has(node.id)\n ? \"complete\"\n : runningIds.has(node.id)\n ? \"running\"\n : skippedIds.has(node.id)\n ? \"skipped\"\n : \"not_started\";\n snapshots.set(node.id, { status });\n }\n const gatedBranches = unsettledRouterBranchIds(flow, snapshots);\n const context = buildFlowExpressionContext(flow, snapshots);\n\n const nodeStates: NodeState[] = nodes.map((node) => {\n const optional = nodeIsOptional(node);\n const skillId = nodeSkillId(node);\n const label = nodeLabel(node);\n\n if (completedIds.has(node.id)) {\n return {\n nodeId: node.id,\n skillId,\n label,\n status: \"complete\",\n optional,\n canRun: false,\n blockers: [],\n failedPreconditions: [],\n };\n }\n if (runningIds.has(node.id)) {\n return {\n nodeId: node.id,\n skillId,\n label,\n status: \"running\",\n optional,\n canRun: false,\n blockers: [],\n failedPreconditions: [],\n };\n }\n if (skippedIds.has(node.id)) {\n return {\n nodeId: node.id,\n skillId,\n label,\n status: \"skipped\",\n optional,\n canRun: false,\n blockers: [],\n failedPreconditions: [],\n };\n }\n\n if (gatedBranches.has(node.id)) {\n return {\n nodeId: node.id,\n skillId,\n label,\n status: \"not_started\",\n optional,\n canRun: false,\n blockers: [],\n failedPreconditions: [],\n };\n }\n\n const edges = incoming.get(node.id) ?? [];\n\n // Hard blockers: flow-type edges whose source is neither complete nor skipped\n const hardBlockers = edges\n .filter((e) => e.type === \"flow\")\n .filter((e) => !completedIds.has(e.source) && !skippedIds.has(e.source))\n .map((e) => e.source);\n\n const preconditionFailures = failedPreconditions(node, context);\n const canRun = hardBlockers.length === 0 && preconditionFailures.length === 0;\n\n let status: NodeStatus;\n if (!canRun) {\n status = \"not_started\";\n } else {\n status = \"available\";\n }\n\n return {\n nodeId: node.id,\n skillId,\n label,\n status,\n optional,\n canRun,\n blockers: hardBlockers,\n failedPreconditions: preconditionFailures,\n };\n });\n\n const _stateMap = new Map(nodeStates.map((s) => [s.nodeId, s]));\n\n const available = nodeStates.filter((s) => s.status === \"available\").map((s) => s.nodeId);\n const completed = nodeStates.filter((s) => s.status === \"complete\").map((s) => s.nodeId);\n const focus = nodeStates\n .filter(\n (s) =>\n s.status === \"running\" || s.status === \"awaiting_approval\" || s.status === \"awaiting_input\",\n )\n .map((s) => s.nodeId);\n\n // Flow is done when all required nodes are complete or skipped\n const requiredNodes = nodes.filter((n) => !nodeIsOptional(n));\n const done = requiredNodes.every((n) => completedIds.has(n.id) || skippedIds.has(n.id));\n\n return { flowId: flow.id, nodes: nodeStates, available, completed, focus, done };\n}\n\n/**\n * Snapshot-based variant of {@link computeFlowState}.\n *\n * Accepts a map of `NodeExecutionSnapshot` values carrying the current status and\n * interaction metadata for every node the caller knows about. Nodes absent from the\n * map are treated as `not_started`.\n *\n * This is the preferred API for the turn-based runner, which has a full `FlowExecution`\n * and needs to convey richer statuses (`awaiting_approval`, `awaiting_input`, `failed`)\n * back to the engine so downstream availability is computed correctly.\n *\n * Engine semantics:\n * - A node is `available` when all its incoming `'flow'`-type predecessors are `complete`\n * or `skipped`. Any other upstream status — including `awaiting_approval`,\n * `awaiting_input`, and `failed` — is treated as blocking. Every authored precondition\n * must also evaluate true against the snapshot expression context.\n * - A `failed` optional node does **not** block its dependents.\n * - The flow is `done` when every non-optional node is `complete` or `skipped`. A single\n * required node stuck in `failed` keeps `done` false.\n *\n * @param flow - The parsed flow definition.\n * @param snapshots - Map from node ID to its current {@link NodeExecutionSnapshot}.\n * Missing entries default to `not_started` with no interaction metadata.\n * @returns A {@link FlowState} describing every active runtime node,\n * including interaction fields (`approval`, `input`, `output`, `error`) copied\n * from the matching snapshot.\n * @docLink packages/flow-engine/concepts#compute-flow-state-from-snapshots\n */\nexport function computeFlowStateFromSnapshots(\n flow: FlowDefinition,\n snapshots: Map<string, NodeExecutionSnapshot>,\n): FlowState {\n const nodes = activeRuntimeNodes(flow);\n const incoming = buildIncoming(flow.edges);\n const gatedBranches = unsettledRouterBranchIds(flow, snapshots);\n const context = buildFlowExpressionContext(flow, snapshots);\n\n /** Resolve the effective status for a node — defaulting to `not_started`. */\n const statusFor = (nodeId: string): NodeStatus => snapshots.get(nodeId)?.status ?? \"not_started\";\n\n /** A predecessor \"passes\" when it is complete or skipped. */\n const passed = (nodeId: string): boolean => {\n const s = statusFor(nodeId);\n return s === \"complete\" || s === \"skipped\";\n };\n\n const nodeStates: NodeState[] = nodes.map((node) => {\n const snapshot = snapshots.get(node.id);\n const optional = nodeIsOptional(node);\n const skillId = nodeSkillId(node);\n const label = nodeLabel(node);\n const status = snapshot?.status ?? \"not_started\";\n\n const edges = incoming.get(node.id) ?? [];\n const flowPreds = edges.filter((e) => e.type === \"flow\");\n const hardBlockers = flowPreds.filter((e) => !passed(e.source)).map((e) => e.source);\n\n const isAdmissionState = status === \"not_started\" || status === \"available\";\n const preconditionFailures = isAdmissionState ? failedPreconditions(node, context) : [];\n\n // Recompute admission in both directions after fresh start or hydrate.\n let effectiveStatus: NodeStatus = status;\n if (isAdmissionState && gatedBranches.has(node.id)) {\n effectiveStatus = \"not_started\";\n } else if (isAdmissionState) {\n effectiveStatus =\n hardBlockers.length === 0 && preconditionFailures.length === 0\n ? \"available\"\n : \"not_started\";\n }\n\n return {\n nodeId: node.id,\n skillId,\n label,\n status: effectiveStatus,\n optional,\n canRun:\n hardBlockers.length === 0 &&\n preconditionFailures.length === 0 &&\n effectiveStatus === \"available\",\n blockers: hardBlockers,\n failedPreconditions: preconditionFailures,\n approval: snapshot?.approval,\n input: snapshot?.input,\n output: snapshot?.output,\n error: snapshot?.error,\n };\n });\n\n const available = nodeStates.filter((s) => s.status === \"available\").map((s) => s.nodeId);\n const completed = nodeStates.filter((s) => s.status === \"complete\").map((s) => s.nodeId);\n const focus = nodeStates\n .filter(\n (s) =>\n s.status === \"running\" || s.status === \"awaiting_approval\" || s.status === \"awaiting_input\",\n )\n .map((s) => s.nodeId);\n\n const requiredNodes = nodes.filter((n) => !nodeIsOptional(n));\n const done = requiredNodes.every((n) => {\n const s = statusFor(n.id);\n return s === \"complete\" || s === \"skipped\";\n });\n\n return { flowId: flow.id, nodes: nodeStates, available, completed, focus, done };\n}\n\n/**\n * Returns `true` when the given status prevents downstream nodes from starting.\n *\n * Only `'complete'` and `'skipped'` satisfy a hard (`'flow'`-type) edge dependency.\n * All other statuses — including `'awaiting_approval'`, `'awaiting_input'`, and\n * `'failed'` — are considered blocking.\n *\n * Use this helper in the FlowAdapter and the turn-based orchestrator instead of\n * hard-coding the two-value whitelist inline.\n *\n * @param status - The {@link NodeStatus} to evaluate.\n * @returns `true` if the status prevents dependents from becoming `available`.\n * @docLink packages/flow-engine/concepts#is-blocking\n */\nexport function isBlocking(status: NodeStatus): boolean {\n return status !== \"complete\" && status !== \"skipped\";\n}\n\n/**\n * Returns the IDs of nodes that become newly `available` after a specific node completes.\n *\n * More efficient than recomputing the full {@link FlowState} when only the downstream\n * impact of a single completion is needed. Only the direct successors of `justCompleted`\n * are evaluated — the rest of the graph is untouched.\n *\n * @param flow - The parsed flow definition.\n * @param justCompleted - ID of the node that just finished (will be added to the\n * effective completed set before evaluating successors).\n * @param completedIds - Set of node IDs already known to be complete before this call.\n * @param skippedIds - Set of node IDs that were explicitly skipped. Defaults to an empty set.\n * @returns Array of node IDs whose hard dependencies are now fully satisfied and that\n * were not already available before `justCompleted` finished. Unlike executable-node-filtered\n * helpers, this walks raw edge targets and does not filter by node type — if a `group`,\n * `sub-flow`, or `router` node is a direct successor, its ID can appear here. Callers that\n * dispatch these IDs are responsible for filtering inert nodes.\n * @docLink packages/flow-engine/concepts#resolve-next-nodes\n */\nexport function resolveNextNodes(\n flow: FlowDefinition,\n justCompleted: string,\n completedIds: Set<string>,\n skippedIds: Set<string> = new Set(),\n): string[] {\n const outgoing = buildOutgoing(flow.edges);\n const incoming = buildIncoming(flow.edges);\n const candidates = (outgoing.get(justCompleted) ?? []).map((e) => e.target);\n\n const nextCompleted = new Set([...completedIds, justCompleted]);\n const result: string[] = [];\n\n for (const candidateId of candidates) {\n const edges = incoming.get(candidateId) ?? [];\n const hardBlockers = edges\n .filter((e) => e.type === \"flow\")\n .filter((e) => !nextCompleted.has(e.source) && !skippedIds.has(e.source));\n if (hardBlockers.length === 0) {\n result.push(candidateId);\n }\n }\n\n return result;\n}\n\n/**\n * Returns the IDs of optional nodes that have not yet started and can be safely skipped.\n *\n * A node is skippable when it is:\n * 1. Not yet complete (absent from `completedIds`).\n * 2. Marked `optional` (`FlowNode.data.optional === true`).\n * 3. Not connected via a `'flow'`-type edge to any non-optional downstream node\n * (i.e. skipping it cannot starve a required node of a hard dependency).\n *\n * The runner may call this to present the user with a list of nodes they can bypass\n * without breaking the flow's required path.\n *\n * @param flow - The parsed flow definition.\n * @param completedIds - Set of node IDs that have already completed (excluded from results).\n * @returns Array of node IDs that are safe to skip at this point in the execution.\n * @docLink packages/flow-engine/concepts#compute-skippable\n */\nexport function computeSkippable(flow: FlowDefinition, completedIds: Set<string>): string[] {\n const nodes = activeRuntimeNodes(flow);\n const outgoing = buildOutgoing(flow.edges);\n\n return nodes\n .filter((n) => !completedIds.has(n.id))\n .filter(nodeIsOptional)\n .filter((n) => {\n // A node is skippable if none of its outgoing flow-type edges go to a required node\n const deps = (outgoing.get(n.id) ?? []).filter((e) => e.type === \"flow\");\n return deps.every((e) => {\n const target = flow.nodes.find((t) => t.id === e.target);\n return target ? nodeIsOptional(target) : false;\n });\n })\n .map((n) => n.id);\n}\n","import * as z from \"zod\";\nimport { collectFlowBindingExpressions, inspectFlowExpression } from \"../contract/expression.js\";\nimport type { FlowDefinition, FlowNode } from \"./types.js\";\n\n/** Result of validating fields at a producer's consumed-output boundary. */\nexport interface NodeOutputValidationResult {\n /** Whether the fields may be exposed to downstream consumers. */\n valid: boolean;\n /** Stable, path-bearing failures. Empty when validation is not required. */\n issues: string[];\n}\n\nfunction consumerExpressions(node: FlowNode): string[] {\n const expressions = (node.contract?.requires ?? []).map(({ expr }) => expr);\n expressions.push(...collectFlowBindingExpressions(node.contract?.input));\n if (node.run?.kind === \"router\") {\n expressions.push(...node.run.routes.map(({ when }) => when));\n }\n return expressions;\n}\n\nfunction readsProducerOutput(node: FlowNode, producerId: string): boolean {\n return consumerExpressions(node).some((expression) =>\n inspectFlowExpression(expression, false).some(({ path }) =>\n path.startsWith(`nodes.${producerId}.output.fields.`),\n ),\n );\n}\n\n/**\n * Return a producer's declared fields schema only when another node reads it.\n *\n * Consumption is deliberately limited to preconditions, named bindings, and\n * router conditions. Status reads and unreferenced declarations remain prose-only.\n */\nexport function getConsumedOutputSchema(\n flow: FlowDefinition,\n producerId: string,\n): Record<string, unknown> | undefined {\n const producer = flow.nodes.find(({ id }) => id === producerId);\n const schema = producer?.contract?.output?.fields;\n if (!schema) return undefined;\n return flow.nodes.some(\n (consumer) => consumer.id !== producerId && readsProducerOutput(consumer, producerId),\n )\n ? schema\n : undefined;\n}\n\n/** Validate proposed fields only when a downstream deterministic consumer requires them. */\nexport function validateConsumedNodeOutput(\n flow: FlowDefinition,\n producerId: string,\n fields: Record<string, unknown> | undefined,\n): NodeOutputValidationResult {\n const schema = getConsumedOutputSchema(flow, producerId);\n if (!schema) return { valid: true, issues: [] };\n\n try {\n const validator = z.fromJSONSchema(schema as Parameters<typeof z.fromJSONSchema>[0]);\n const parsed = validator.safeParse(fields ?? {});\n if (parsed.success) return { valid: true, issues: [] };\n return {\n valid: false,\n issues: parsed.error.issues\n .map((issue) => {\n const suffix = issue.path.map(String).join(\".\");\n return `fields${suffix ? `.${suffix}` : \"\"}: ${issue.message}`;\n })\n .sort(),\n };\n } catch (error) {\n return {\n valid: false,\n issues: [\n `fields: invalid authored JSON Schema: ${\n error instanceof Error ? error.message : String(error)\n }`,\n ],\n };\n }\n}\n","/**\n * Pure derived-deadline arithmetic for `control.timeoutSec`.\n *\n * \"Active execution only\" is the scope every node-timeout ruling shares: the\n * clock runs from `startedAt` but stops counting while the node was parked\n * for a human decision. Rather than persist a separate \"paused\" duration,\n * this module recomputes the deadline on demand from `startedAt` plus the\n * already-durable `approvalHistory` / `inputHistory` — so it is correct\n * immediately after `hydrate()` or a reconnect with no extra wiring, and a\n * live timer is never the source of truth.\n *\n * @docLink packages/flow-engine/concepts#node-deadline\n */\n\nimport type { NodeExecution } from \"@skaile/workspaces/types\";\n\n/** Milliseconds spent parked in a resolved approval/input wait since `sinceMs`. */\nfunction pausedIntervalMs(execution: NodeExecution, sinceMs: number): number {\n let total = 0;\n for (const approval of execution.approvalHistory) {\n const startMs = Date.parse(approval.requestedAt);\n if (!Number.isFinite(startMs) || startMs < sinceMs) continue;\n if (!approval.decidedAt) continue; // still open — status wouldn't be \"running\" here\n const endMs = Date.parse(approval.decidedAt);\n if (Number.isFinite(endMs) && endMs > startMs) total += endMs - startMs;\n }\n for (const input of execution.inputHistory) {\n const startMs = Date.parse(input.requestedAt);\n if (!Number.isFinite(startMs) || startMs < sinceMs) continue;\n if (!input.providedAt) continue;\n const endMs = Date.parse(input.providedAt);\n if (Number.isFinite(endMs) && endMs > startMs) total += endMs - startMs;\n }\n return total;\n}\n\n/**\n * Milliseconds remaining before `execution`'s active-execution deadline, given\n * `timeoutSec`. Negative once the deadline has passed. `undefined` when no\n * timeout applies — `timeoutSec` is unset, or the node has no `startedAt` to\n * measure from (e.g. it hasn't actually started).\n *\n * Active time is wall-clock since `startedAt` minus every *resolved*\n * approval/input interval recorded at or after that `startedAt` (an\n * interval opened before a retry's fresh `startedAt` never counts against\n * the new attempt; a still-open interval never counts because the node\n * would not be `running` while parked).\n *\n * @param execution - Current node snapshot. Only `startedAt`, `approvalHistory`,\n * and `inputHistory` are read.\n * @param timeoutSec - Authored `control.timeoutSec`, or `undefined` for no timeout.\n * @param nowMs - Caller-supplied wall clock (`Date.now()` in production, injectable\n * for tests).\n * @docLink packages/flow-engine/concepts#remaining-active-execution-ms\n */\nexport function remainingActiveExecutionMs(\n execution: NodeExecution,\n timeoutSec: number | undefined,\n nowMs: number,\n): number | undefined {\n if (timeoutSec === undefined || !execution.startedAt) return undefined;\n const startedAtMs = Date.parse(execution.startedAt);\n if (!Number.isFinite(startedAtMs)) return undefined;\n const pausedMs = pausedIntervalMs(execution, startedAtMs);\n const deadlineMs = startedAtMs + timeoutSec * 1000 + pausedMs;\n return deadlineMs - nowMs;\n}\n\n/**\n * Whether `execution` has exceeded its derived active-execution deadline.\n * `false` when no timeout applies. Convenience wrapper over\n * {@link remainingActiveExecutionMs} for call sites that only need the\n * boolean.\n *\n * @docLink packages/flow-engine/concepts#is-active-execution-expired\n */\nexport function isActiveExecutionExpired(\n execution: NodeExecution,\n timeoutSec: number | undefined,\n nowMs: number,\n): boolean {\n const remaining = remainingActiveExecutionMs(execution, timeoutSec, nowMs);\n return remaining !== undefined && remaining <= 0;\n}\n","/**\n * Pure bookkeeping for `NodeExecution.outputHistory` and the bounded\n * automatic-retry budget derived from `control.retries`.\n *\n * `retries: N` means the first attempt plus N automatic retries — so an\n * automatic retry remains available while fewer than N attempts have\n * already failed. The budget is derived from `outputHistory` itself (a\n * count of prior `'failed'` entries) rather than a separate durable\n * counter, so it composes for free with hydration and needs no new field.\n *\n * The manual `retryNode` operator override never pushes an entry here (it\n * only flips `status` back to `available`). The agent's own\n * `doFailNode(recoverable: true)` self-retry DOES push an entry — every\n * actual start closes out an attempt — but marks it `selfRetry` so\n * `countFailedAttempts` excludes it: neither self-retry nor the manual\n * override consumes the automatic budget this module tracks.\n *\n * @docLink packages/flow-engine/concepts#node-attempts\n */\n\nimport type {\n CheckEvidence,\n NodeError,\n NodeExecutionAttempt,\n NodeOutput,\n} from \"@skaile/workspaces/types\";\n\n/** Next 1-based attempt number given the attempts already recorded. */\nexport function nextAttemptNumber(history: NodeExecutionAttempt[] | undefined): number {\n if (!history || history.length === 0) return 1;\n return Math.max(...history.map((entry) => entry.attempt)) + 1;\n}\n\n/** Rarely-set trailing facts about one appended attempt. */\nexport interface AppendAttemptOptions {\n /** True for the agent's own `doFailNode(recoverable: true)` self-retry: the\n * entry still records a genuine start-to-failure attempt, but is excluded\n * from {@link countFailedAttempts} so it never consumes the automatic\n * `control.retries` budget. */\n selfRetry?: boolean;\n /** Derived check evidence, when this attempt belongs to a `check` node that\n * actually produced a verdict (pass or fail). Omit for every other node\n * kind and for a check's infrastructure failure, which produced no verdict\n * to attach. */\n check?: CheckEvidence;\n}\n\n/**\n * Appends one terminal attempt to `history`, numbered `max(attempt) + 1`.\n * Never mutates `history` — returns a fresh array so callers can assign it\n * straight onto a cloned `NodeExecution`.\n *\n * @param history - Existing attempt history, oldest first (or `undefined`).\n * @param result - True outcome of this attempt — independent of any\n * compatibility status degrade the caller applies separately (e.g. an\n * optional node's failed execution still records `'failed'` here even\n * though its `NodeExecution.status` becomes `'skipped'`).\n * @param startedAtIso - This attempt's actual start time.\n * @param completedAtIso - This attempt's terminal outcome time.\n * @param options - See {@link AppendAttemptOptions}. Both fields default to absent.\n * @docLink packages/flow-engine/concepts#append-attempt\n */\nexport function appendAttempt(\n history: NodeExecutionAttempt[] | undefined,\n result: NodeExecutionAttempt[\"result\"],\n startedAtIso: string,\n completedAtIso: string,\n output: NodeOutput | undefined,\n error: NodeError | undefined,\n options: AppendAttemptOptions = {},\n): NodeExecutionAttempt[] {\n const attempt: NodeExecutionAttempt = {\n attempt: nextAttemptNumber(history),\n result,\n startedAt: startedAtIso,\n completedAt: completedAtIso,\n ...(output !== undefined ? { output } : {}),\n ...(error !== undefined ? { error } : {}),\n ...(options.selfRetry ? { selfRetry: true } : {}),\n ...(options.check !== undefined ? { check: options.check } : {}),\n };\n return [...(history ?? []), attempt];\n}\n\n/**\n * Count of attempts in `history` whose true outcome was `'failed'`,\n * excluding self-retry entries (see {@link appendAttempt}) — this feeds only\n * the automatic-retry budget, which self-retry sits outside of.\n */\nexport function countFailedAttempts(history: NodeExecutionAttempt[] | undefined): number {\n if (!history) return 0;\n return history.filter((entry) => entry.result === \"failed\" && !entry.selfRetry).length;\n}\n\n/**\n * Whether an automatic retry remains, given how many attempts have already\n * failed and the authored `control.retries` budget. `retries: N` allows the\n * first attempt plus N automatic retries — so a retry remains available\n * while `priorFailedAttempts < N`. No `retries` (or `0`) means no automatic\n * retry ever.\n *\n * @docLink packages/flow-engine/concepts#has-automatic-retry-budget\n */\nexport function hasAutomaticRetryBudget(\n priorFailedAttempts: number,\n retries: number | undefined,\n): boolean {\n if (!retries) return false;\n return priorFailedAttempts < retries;\n}\n","/**\n * Pure derivation of a `check` node's evidence payload — what was compared,\n * where each value came from, and whether that makes the verdict\n * runtime-`\"verified\"` or agent-`\"asserted\"`.\n *\n * Ruling: re-running a check is not required to reproduce the same answer,\n * so there is no snapshot materialization, no hashing, and no reproducibility\n * guarantee here — this module records integrity of *what was observed*, not\n * a promise that observing it again would agree. Provenance is derived\n * exclusively from {@link BindingOrigin.obtainedBy}, the flow engine's\n * existing (and only) provenance mechanism, so it can never be influenced by\n * how a flow author names a binding. The check is one-hop only — see\n * {@link CheckEvidence} for what that does and does not claim.\n *\n * No I/O and no clock: `observedAt` is supplied by the caller so this stays\n * trivially testable and replayable.\n *\n * @docLink packages/flow-engine/concepts#check-provenance\n */\n\nimport type {\n BindingOrigin,\n CheckComparedValue,\n CheckEvidence,\n CheckInputCurrency,\n CheckProvenance,\n} from \"@skaile/workspaces/types\";\nimport type { ResolvedNodeBindings } from \"../contract/expression.js\";\n\n/** The check's process facts, captured alongside its verdict so a persisted attempt is self-describing. */\nexport interface CheckProcessRecord {\n runtime: \"shell\" | \"node\" | \"python\";\n command: string;\n cwd?: string;\n successExit: number[];\n exitStatus: number;\n passed: boolean;\n}\n\nconst FLOW_LOCAL_SOURCES = new Set<BindingOrigin[\"source\"]>([\"literal\", \"default\", \"flow-input\"]);\n\n/**\n * Derive one check's evidence from its already-resolved bindings and its\n * process outcome. `provenance` and `inputs` are computed only from\n * `bindings.origins` — never from `bindings.values` or their names — so\n * authoring a binding literally named `provenance` or `verified` cannot\n * influence the verdict.\n *\n * `provenance` is `\"verified\"` iff every origin of every compared value has\n * `obtainedBy: \"runtime\"`, `\"asserted\"` if any does not, and **absent** when\n * there are no compared values — neither label is honest about an empty set.\n * `inputs` is `\"live\"` — the floor for any check that runs a process —\n * unless there is at least one compared value and every one of them has\n * origins that are all `literal`/`default`/`flow-input`, in which case it is\n * `\"flow-local\"`.\n */\nexport function deriveCheckEvidence(\n bindings: ResolvedNodeBindings,\n process: CheckProcessRecord,\n observedAt: string,\n): CheckEvidence {\n const values: CheckComparedValue[] = Object.entries(bindings.values).map(([name, value]) => {\n const origins = bindings.origins[name] ?? [];\n const obtainedBy = origins.some((origin) => origin.obtainedBy === \"agent\")\n ? \"agent\"\n : \"runtime\";\n return { name, value, origins, obtainedBy };\n });\n const provenance: CheckProvenance | undefined =\n values.length === 0\n ? undefined\n : values.every((compared) => compared.obtainedBy === \"runtime\")\n ? \"verified\"\n : \"asserted\";\n const inputs: CheckInputCurrency =\n values.length > 0 &&\n values.every((compared) =>\n compared.origins.every((origin) => FLOW_LOCAL_SOURCES.has(origin.source)),\n )\n ? \"flow-local\"\n : \"live\";\n return {\n values,\n ...(provenance !== undefined ? { provenance } : {}),\n inputs,\n observedAt,\n ...process,\n };\n}\n","/**\n * Flow manifest schema and validation.\n *\n * Moved from @skaile/workspaces/types/manifests/flow.ts in Phase 1.7.3.\n * This is now the canonical location for flow manifest validation.\n */\n\nimport * as z from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Validation result (inline — avoids importing from types/manifests/_shared)\n// ---------------------------------------------------------------------------\n\nexport interface ManifestValidationSuccess<T> {\n ok: true;\n data: T;\n}\n\nexport interface ManifestValidationFailure {\n ok: false;\n errors: Array<{ path: string; message: string }>;\n}\n\nexport type ManifestValidationResult<T> = ManifestValidationSuccess<T> | ManifestValidationFailure;\n\n// ---------------------------------------------------------------------------\n// Schema\n// ---------------------------------------------------------------------------\n\nconst FlowNodeSchema = z.looseObject({\n id: z.string().min(1),\n skill: z.string().optional(),\n type: z.string().optional(),\n label: z.string().optional(),\n description: z.string().optional(),\n data: z\n .looseObject({\n optional: z.boolean().optional(),\n // Mandatory approval gate — autonomous mode cannot skip it.\n approval: z.looseObject({ mandatory: z.boolean().optional() }).optional(),\n })\n .refine((d) => !(d.optional === true && d.approval?.mandatory === true), {\n // A mandatory gate can never be skipped, so optional+mandatory is a\n // contradiction — reject it rather than silently letting mandatory win.\n message: \"a node cannot be both optional and a mandatory approval gate\",\n })\n .optional(),\n});\n\nconst FlowEdgeSchema = z.looseObject({\n id: z.string().optional(),\n source: z.string().min(1),\n target: z.string().min(1),\n condition: z.string().optional(),\n});\n\nexport const FlowManifestSchema = z.looseObject({\n id: z.string().min(1),\n version: z.string().optional(),\n name: z.string().min(1),\n description: z.string().optional(),\n metadata: z\n .looseObject({\n tags: z.array(z.string()).optional(),\n stage: z.string().optional(),\n icon: z.string().optional(),\n category: z.string().optional(),\n onboarding: z.record(z.string(), z.unknown()).optional(),\n })\n .optional(),\n globals: z.record(z.string(), z.unknown()).optional(),\n modes: z.record(z.string(), z.unknown()).optional(),\n tier_presets: z.record(z.string(), z.record(z.string(), z.unknown())).optional(),\n artifact_handoff: z.unknown().optional(),\n entry: z.string().optional(),\n nodes: z.array(FlowNodeSchema).optional(),\n edges: z.array(FlowEdgeSchema).optional(),\n});\n\nexport type FlowManifest = z.infer<typeof FlowManifestSchema>;\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nexport function validateFlow(data: unknown): ManifestValidationResult<FlowManifest> {\n const result = FlowManifestSchema.safeParse(data);\n if (result.success) {\n return { ok: true, data: result.data };\n }\n return {\n ok: false,\n errors: result.error.issues.map((issue) => ({\n path: issue.path.join(\".\"),\n message: issue.message,\n })),\n };\n}\n","/**\n * Flow asset kind provider.\n *\n * Exported from @skaile/workspaces/factory-assets/connectors/flow/engine for explicit registration\n * by the CLI at bootstrap. Discovery does NOT auto-include this provider\n * (discovery must stay a leaf — no flow-engine imports).\n *\n * Implements IAssetKindProvider with flow-specific:\n * - Discovery patterns: *.flow.yaml, *.flow.json\n * - Manifest validation via FlowManifestSchema\n * - Requires extraction: nodes[].run.assets plus legacy skill/sub-flow references\n * - File filter: just the manifest file (flows are single-file)\n */\n\nimport * as path from \"node:path\";\nimport type {\n AssetKindFileFilter,\n AssetKindRequiresEdge,\n IAssetKindProvider,\n} from \"@skaile/workspaces/plugins\";\nimport { validateFlow } from \"./flow-manifest.js\";\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport const flowKindProvider: IAssetKindProvider = {\n kind: \"flow\",\n displayName: \"Flow\",\n providerVersion: \"1.1.0\",\n discoveryPatterns: [\"**/*.flow.yaml\", \"**/*.flow.json\"],\n\n matchesPath(relativePath: string): boolean {\n return relativePath.endsWith(\".flow.yaml\") || relativePath.endsWith(\".flow.json\");\n },\n\n validateManifest(data: unknown) {\n return validateFlow(data);\n },\n\n defaultFileFilter(manifestPath: string): AssetKindFileFilter {\n return {\n assetRoot: path.dirname(manifestPath),\n files: [path.basename(manifestPath)],\n };\n },\n\n extractRequires(assetRef: string, manifest: Record<string, unknown>): AssetKindRequiresEdge[] {\n const edges: AssetKindRequiresEdge[] = [];\n const seen = new Set<string>();\n const add = (to: string, field: string): void => {\n if (seen.has(to)) return;\n seen.add(to);\n edges.push({ from: assetRef, to, field });\n };\n\n const nodes = manifest.nodes;\n if (Array.isArray(nodes)) {\n for (const node of nodes) {\n if (typeof node !== \"object\" || node === null) continue;\n const n = node as Record<string, unknown>;\n const data = (\n typeof n.data === \"object\" && n.data !== null ? (n.data as Record<string, unknown>) : {}\n ) as Record<string, unknown>;\n const run =\n typeof n.run === \"object\" && n.run !== null ? (n.run as Record<string, unknown>) : {};\n\n if (Array.isArray(run.assets)) {\n for (const asset of run.assets) {\n if (typeof asset === \"string\") add(asset, \"nodes[].run.assets\");\n }\n }\n\n if (run.kind === \"sub-flow\" && typeof run.flow === \"string\") {\n const flowRef = run.flow.startsWith(\"flow:\") ? run.flow : `flow:${run.flow}`;\n add(flowRef, \"nodes[].run.flow\");\n }\n\n const skill = typeof data.skill === \"string\" ? data.skill : n.skill;\n if (typeof skill === \"string\") {\n add(skill, \"nodes[].data.skill\");\n }\n\n const subFlow = typeof data.flow === \"string\" ? data.flow : n.flow;\n if (typeof subFlow === \"string\") {\n add(subFlow.startsWith(\"flow:\") ? subFlow : `flow:${subFlow}`, \"nodes[].data.flow\");\n }\n }\n }\n\n return edges;\n },\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { assetSearchDirs } from \"@skaile/workspaces/core\";\nimport { parse as parseYaml } from \"yaml\";\nimport { parseFlowDefinition } from \"../contract/normalize.js\";\nimport type { FlowDefinition } from \"./types.js\";\n\n/**\n * Load a single {@link FlowDefinition} from a YAML or JSON file on disk.\n *\n * Format detection is based on file extension:\n * - `.yaml` / `.yml` — parsed with the `yaml` library.\n * - Everything else — parsed as JSON.\n *\n * @param filePath - Absolute path to the flow file.\n * @returns The parsed {@link FlowDefinition}.\n * @throws {Error} If the file does not exist, cannot be read, or fails to parse.\n * @docLink packages/flow-engine/concepts#flow-loading\n */\nexport function loadFlow(filePath: string): FlowDefinition {\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const ext = path.extname(filePath).toLowerCase();\n const authored = ext === \".yaml\" || ext === \".yml\" ? parseYaml(raw) : JSON.parse(raw);\n const parsed = parseFlowDefinition(authored);\n if (!parsed.ok) {\n const details = parsed.errors\n .map((issue) => ` ${issue.path || \"<root>\"}: ${issue.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid flow definition:\\n${details}`);\n }\n return parsed.data;\n}\n\n/**\n * Load all `*.flow.yaml` and legacy `*.flow.json` / `*.json` flow files from a directory.\n *\n * Files that fail to parse are skipped with a warning written to `stderr` — they do not\n * cause the function to throw. Files whose name starts with `_` are skipped entirely\n * (treated as drafts or disabled flows). Files missing the required `id`, `nodes`, or\n * `edges` fields are also discarded silently.\n *\n * @param dirPath - Absolute path to the directory to scan.\n * @returns Array of successfully parsed {@link FlowDefinition} objects. Empty if the\n * directory does not exist or contains no valid flow files.\n * @docLink packages/flow-engine/concepts#flow-loading\n */\nexport function loadFlowsFromDir(dirPath: string): FlowDefinition[] {\n if (!fs.existsSync(dirPath)) return [];\n\n const files = fs.readdirSync(dirPath).filter((f) => {\n if (f.startsWith(\"_\")) return false;\n return f.endsWith(\".flow.yaml\") || f.endsWith(\".flow.json\") || f.endsWith(\".json\");\n });\n\n const flows: FlowDefinition[] = [];\n\n for (const file of files) {\n try {\n const def = loadFlow(path.join(dirPath, file));\n if (def.id && def.nodes && def.edges) {\n flows.push(def);\n }\n } catch (err) {\n process.stderr.write(`[agent-flow-engine] skipping ${file}: ${(err as Error).message}\\n`);\n }\n }\n\n return flows;\n}\n\n/**\n * Discover and load all flow definitions from every domain under an `ai-assets` root.\n *\n * Walks the top-level subdirectories of `aiResourcesRoot`, looks for a `flows/`\n * subdirectory inside each domain, and delegates to {@link loadFlowsFromDir} for\n * each one found. Files prefixed with `_` are skipped (draft/disabled).\n *\n * @param aiResourcesRoot - Absolute path to the `ai-assets/` directory (or equivalent\n * resource root). Typically the `ai-assets/` folder at the monorepo root.\n * @returns Flat array of all successfully parsed {@link FlowDefinition} objects across\n * all domains. Empty if the root directory does not exist.\n * @docLink packages/flow-engine/concepts#flow-loading\n */\nexport function loadAllFlows(aiResourcesRoot: string): FlowDefinition[] {\n if (!fs.existsSync(aiResourcesRoot)) return [];\n\n // `assetSearchDirs` covers both the flat (`<root>/flows/`) and domain-nested\n // (`<root>/<domain>/flows/`) layouts via the one shared layout primitive.\n // De-dupe by id (first dir wins) so a root that happens to define a flow in\n // both layouts surfaces it once.\n const byId = new Map<string, FlowDefinition>();\n for (const { dir } of assetSearchDirs(aiResourcesRoot, \"flows\")) {\n for (const flow of loadFlowsFromDir(dir)) {\n if (!byId.has(flow.id)) byId.set(flow.id, flow);\n }\n }\n return [...byId.values()];\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { openLibraryManager, createFullRegistry } from './chunk-
|
|
2
|
-
import { logErr, logInfo, logWarn, logOk, S } from './chunk-
|
|
1
|
+
import { openLibraryManager, createFullRegistry } from './chunk-BENN6MO4.js';
|
|
2
|
+
import { logErr, logInfo, logWarn, logOk, S } from './chunk-VBMY3VCW.js';
|
|
3
3
|
import { getStoreManifestsDir, LocalCatalogSource, writeCuratedManifest } from './chunk-3HVASHBF.js';
|
|
4
4
|
import { computeDeterministicHash, discoverAssetsInTree } from './chunk-NU4E7C5I.js';
|
|
5
5
|
import { WorkspaceYamlEditor } from './chunk-P43HBWKK.js';
|
|
@@ -313,12 +313,12 @@ function addSourceManifestCommands(src) {
|
|
|
313
313
|
).option("-C, --project-dir <dir>", "Project directory", process.cwd()).option("--publisher <name>", "Override the publisher (--overwrite only)").option("--dev", "Include assets under the source's dev_paths", false).option("--overwrite", "Discard curation and re-scan the full inventory", false).action((arg, opts) => runRebuild(arg, opts));
|
|
314
314
|
manifest.command("verify <src>").description("Verify hashes, deps, and schema (read-only)").option("-C, --project-dir <dir>", "Project directory", process.cwd()).option("--strict", "Fail on advisory checks (warnings force a nonzero exit)", false).action((arg, opts) => runVerify(arg, opts));
|
|
315
315
|
manifest.command("publish <src>").description("Push the curated sidecar manifest and publish it to the store").option("-C, --project-dir <dir>", "Project directory", process.cwd()).option("--as <namespace>", "Publisher namespace (default: your store username)").option("--sidecar-repo <url>", "Public GitHub repo you own to hold the curated manifest").option("--ref <gitref>", "Foreign source ref to ingest (branch/sha; default: main)").option("--dry-run", "Print the publish plan without pushing or calling the store", false).action(async (arg, opts) => {
|
|
316
|
-
const { runPublish } = await import('./source-manifest-publish-
|
|
316
|
+
const { runPublish } = await import('./source-manifest-publish-OTVKHRX3.js');
|
|
317
317
|
await runPublish(arg, opts);
|
|
318
318
|
});
|
|
319
319
|
manifest.command("propose <src>").description("Open a PR to upstream with the sidecar manifest").action(() => notWired("propose"));
|
|
320
320
|
manifest.command("yank <src>").description("Retract the source's published assets from the store").option("-C, --project-dir <dir>", "Project directory", process.cwd()).option("--asset <ref>", "Yank only the asset matching this ref/name").action(async (arg, opts) => {
|
|
321
|
-
const { runYank } = await import('./source-manifest-publish-
|
|
321
|
+
const { runYank } = await import('./source-manifest-publish-OTVKHRX3.js');
|
|
322
322
|
await runYank(arg, opts);
|
|
323
323
|
});
|
|
324
324
|
}
|
|
@@ -684,5 +684,5 @@ function makeSourceCommand() {
|
|
|
684
684
|
}
|
|
685
685
|
|
|
686
686
|
export { autoSyncForSearch, ensureClone, findCacheKeyCollision, indexingHadFailures, legacySourceConfigHint, makeSourceCommand, normalizeSourceUrl, readProjectSources, resolveSourceArg, sourceClonePath, sourceMatchesKey, syncProjectSources };
|
|
687
|
-
//# sourceMappingURL=chunk-
|
|
688
|
-
//# sourceMappingURL=chunk-
|
|
687
|
+
//# sourceMappingURL=chunk-TARN55L3.js.map
|
|
688
|
+
//# sourceMappingURL=chunk-TARN55L3.js.map
|