@skaile/workspaces 1.5.0 → 1.6.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 CHANGED
@@ -1,5 +1,58 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#346](https://github.com/skaile-ai/workspaces/pull/346) [`b878750`](https://github.com/skaile-ai/workspaces/commit/b878750cb8a99c317a074e88acad3f9e102b6df2) Thanks [@henkbla](https://github.com/henkbla)! - `runner`: carry an embedded app's `origin: {kind:'app', appId}` end-to-end instead of
8
+ relabelling it to `client`.
9
+
10
+ The platform gateway used to forward an app's capabilities to the runner relabelled as
11
+ `origin:'client'`, because the origin-trust guard rejected an `app` origin from any
12
+ source but a (non-existent) direct app connection. That relabel worked, but it erased
13
+ the app's identity before anything downstream could use it: the per-app audit slice the
14
+ design calls for was impossible, `ORIGIN_PROMPT_ORDER`'s `app` row and
15
+ `isUserInvokable`'s `app` row were unreachable, and the agent could not tell which app
16
+ owned which action.
17
+
18
+ **Trust-guard change.** `source: 'client'` may now declare `origin.kind: 'app'` as well
19
+ as `'client'`. The platform gateway is the only client peer; it binds every app
20
+ registration to the socket it arrived on before forwarding, and the runner cannot verify
21
+ an `appId` in any case. The guard that actually enforces something is unchanged and
22
+ still live: `source: 'agent'` may never claim an `app` origin, so a skill, connector, or
23
+ flow cannot impersonate an app.
24
+
25
+ **Audit.** A capability handler's logger is now built with an `appId`-qualified instance
26
+ for app origins: `capability:app:<appId>.<name>`. Exported as `capabilityLogInstance()`.
27
+
28
+ `side: 'app'` needs no separate dispatch path — `buildClientCapabilityHandler` already
29
+ round-trips the invocation to the platform, which routes it to the app connection.
30
+
31
+ **Compatibility.** A platform that forwards `app`-origin capabilities requires a runner
32
+ built from this version or later; an older runner drops them with an origin-mismatch
33
+ warning. The runner ships in the agent container image, so the image and the platform's
34
+ `@skaile/workspaces` pin must move together. No wire-type change — `origin.kind:'app'`
35
+ and `side:'app'` have been in the protocol since 3.4.0; this only widens who may declare
36
+ them.
37
+
38
+ ### Patch Changes
39
+
40
+ - [#342](https://github.com/skaile-ai/workspaces/pull/342) [`9b362db`](https://github.com/skaile-ai/workspaces/commit/9b362dbd33f58658caa1eed56278b4e2198783de) Thanks [@henkbla](https://github.com/henkbla)! - `runner`: `CapabilityRegistry.hydrate()` no longer restores embedded-app capabilities.
41
+
42
+ App capabilities are the app SDK's responsibility to re-register — it reconnects and
43
+ replays them on session resume. Hydrating them would leave the agent handler-less stubs
44
+ for an app whose back-connection is gone after a wake: tools it can see and never call.
45
+
46
+ The existing `origin.kind !== 'client'` skip could not catch them. The platform gateway
47
+ forwards an app's capabilities to the runner relabelled `origin:'client'`, so they look
48
+ like ordinary client capabilities by the time they reach the registry. `hydrate()` now
49
+ also skips the reserved `app.` namespace, which the gateway enforces on registration and
50
+ which therefore survives the relabel.
51
+
52
+ Latent fix: `serialize()` / `hydrate()` have no callers today (the runner does not yet
53
+ write a capability snapshot), so nothing changes at runtime. It closes the trap before
54
+ capability snapshotting lands.
55
+
3
56
  ## 1.5.0
4
57
 
5
58
  ### Minor Changes
@@ -389,5 +389,5 @@ function walkForSkill(dir, skillId) {
389
389
  }
390
390
 
391
391
  export { resumeFlow, runFlow };
392
- //# sourceMappingURL=chunk-CNSNN7N6.js.map
393
- //# sourceMappingURL=chunk-CNSNN7N6.js.map
392
+ //# sourceMappingURL=chunk-BEO6KN7P.js.map
393
+ //# sourceMappingURL=chunk-BEO6KN7P.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../factory-assets/connectors/flow/run-flow.ts"],"names":["c"],"mappings":"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","file":"chunk-CNSNN7N6.js","sourcesContent":["/**\n * runFlow / resumeFlow — CLI entry helpers for the flow connector.\n *\n * Moved from `runner/src/runner.ts` to `factory-assets/connectors/flow/run-flow.ts`\n * in Phase 3 of the flow-connector extraction (2026-05-08). Behaviour is\n * byte-identical to the previous runner-side implementation; only the log\n * source changes from `runner:flow:<runId>` to `flow-connector:run:<runId>`.\n *\n * The runner re-exports these symbols with a deprecation warning for one\n * release. CLI consumers should switch to\n * `import { runFlow, resumeFlow } from \"@skaile/workspaces/factory-assets/connectors/flow/run-flow\"`.\n *\n * Internal runner helpers (FlowOrchestrator, bootstrapRunnerLogStore,\n * createAgentSession, resolveDriverPaths, session helpers) are loaded lazily\n * via dynamic `await import(\"@skaile/workspaces/runner\")` inside\n * `loadRunnerModule()` below. The lazy load avoids a static package-level\n * cycle (runner → connectors → factory-assets → runner) — the cycle exists at\n * the workspace level but never resolves at module-load time because\n * factory-assets only ever calls `import` from inside an async function body.\n * The string-literal specifier preserves `bun --compile` and tsup static\n * analysis.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AgentEvent } from \"@skaile/workspaces/bridge\";\nimport {\n resolveAgentDir,\n resolveSettings,\n resolveSkWorkspaceConfig,\n} from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport { parseSkillFrontmatter, validateFlowVersions } from \"@skaile/workspaces/resolver\";\nimport { initTelemetry } from \"@skaile/workspaces/telemetry\";\nimport type { FlowExecution } from \"@skaile/workspaces/types\";\nimport { FlowAdapter } from \"./adapter.js\";\nimport { loadFlow } from \"./engine/index.js\";\nimport {\n buildOrchestratorPrompt,\n renderStimulusPrompt,\n type TurnStimulus,\n} from \"./prompt-fragments.js\";\n\n/**\n * Lazy `import(\"@skaile/workspaces/runner\")` accessor. Cached on first call so\n * subsequent `runFlow` invocations don't re-evaluate the runner module.\n *\n * Dynamic ESM import is used (not `require`) so vitest and other ESM\n * bundlers honour their alias resolution — `require` would side-step the\n * configured aliases and pick up two distinct module instances when run\n * under vitest. The string-literal specifier ensures bun --compile keeps\n * the dependency (per the static-import-or-die rule in\n * connectors/CLAUDE.md).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _runnerModule: any | undefined;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function loadRunnerModule(): Promise<any> {\n if (_runnerModule) return _runnerModule;\n _runnerModule = await import(\"@skaile/workspaces/runner\");\n return _runnerModule;\n}\n\n/** Type-only re-export of SessionState so the runner tombstone shim still works. */\nexport type SessionState = import(\"@skaile/workspaces/runner\").SessionState;\n\n/** Maximum agent session duration (4 hours). Configurable via {@link RunOptions.sessionTimeoutMs}. */\nconst DEFAULT_SESSION_TIMEOUT_MS = 4 * 60 * 60 * 1000; // 4 hours\n\n/**\n * Options for {@link runFlow}.\n *\n * Wraps `FlowOrchestrator` with autonomous mode turned on by default so\n * interactive approval/input gates don't block a terminal run.\n *\n * @docLink packages/factory-assets/flow#run-flow\n */\nexport interface RunOptions {\n /** The working directory for the project being orchestrated. */\n projectDir: string;\n /** Absolute path to the `.flow.yaml` or `.flow.json` definition file. */\n flowPath: string;\n /**\n * Directory containing `agent.yaml`, `SOUL.md`, `RULES.md`, `knowledge/`.\n * Resolved from `skaile.yaml` via `resolveAgentDir` when absent.\n */\n agentDir?: string;\n /**\n * Agent driver backend. Defaults to `settings.driver` (`\"omp\"` or `\"claude-sdk\"`).\n */\n driver?: string;\n /**\n * LLM provider override (e.g. `\"anthropic\"`, `\"openrouter\"`).\n * Falls back to `settings.provider` when absent.\n */\n provider?: string;\n /**\n * Model name override. Falls back to `settings.model` when absent.\n */\n model?: string;\n /**\n * Path to a specific `settings.json` to load instead of the default\n * layered resolution chain (project → parent → global → built-in defaults).\n */\n settingsFile?: string;\n /**\n * When `true`, prints the initial flow state without starting the agent\n * and returns immediately.\n */\n dryRun?: boolean;\n /**\n * Per-session timeout in milliseconds. Defaults to\n * {@link DEFAULT_SESSION_TIMEOUT_MS} (4 hours).\n */\n sessionTimeoutMs?: number;\n /** Optional human-readable label shown in the session list. */\n sessionLabel?: string;\n /** Autonomous mode for CLI runs — defaults to true so interactive approval gates are skipped. */\n autonomousMode?: boolean;\n /**\n * Called for each {@link AgentEvent} emitted during the run\n * (e.g. `text`, `tool_call`, `state_changed`).\n */\n onEvent?: (event: AgentEvent) => void;\n /**\n * Called for each diagnostic log line. Defaults to `process.stdout`.\n */\n onLog?: (line: string) => void;\n}\n\n/**\n * Options for resuming an existing CLI session.\n *\n * Reconnects the driver's conversation thread (conversation history is\n * preserved via the stored `driverSessionId`) but restarts flow execution\n * from scratch — flow state is not persisted in CLI mode. For governed,\n * resumable flow runs use a host that persists flow state (e.g. the Skaile\n * platform).\n *\n * @docLink packages/factory-assets/flow#resume-flow\n */\nexport interface ResumeOptions {\n /** The working directory for the project being orchestrated. */\n projectDir: string;\n /**\n * Specific run ID to resume. When absent, the current session pointer\n * at `<projectDir>/.skaile/current` is used.\n */\n sessionId?: string;\n /**\n * Agent definition directory override. Defaults to the directory stored\n * in the session file.\n */\n agentDir?: string;\n /**\n * When `true`, prints the initial flow state without starting the agent\n * and returns immediately.\n */\n dryRun?: boolean;\n /**\n * Per-session timeout in milliseconds. Defaults to\n * {@link DEFAULT_SESSION_TIMEOUT_MS} (4 hours).\n */\n sessionTimeoutMs?: number;\n /**\n * Called for each {@link AgentEvent} emitted during the run.\n */\n onEvent?: RunOptions[\"onEvent\"];\n /**\n * Called for each diagnostic log line. Defaults to `process.stdout`.\n */\n onLog?: RunOptions[\"onLog\"];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Start a new flow session from the CLI.\n *\n * Wraps `FlowOrchestrator` with autonomous mode turned on by default so\n * interactive approval/input gates don't block a terminal run. The\n * runner remains idle between turns — for the CLI use case, a single\n * turn should carry the flow to completion in autonomous mode. Non-CLI\n * hosts (Skaile platform, Pichi) use the orchestrator directly via the\n * serve command surface and drive gates through user actions.\n *\n * @docLink packages/factory-assets/flow#run-flow\n */\nexport async function runFlow(opts: RunOptions): Promise<void> {\n const runner = await loadRunnerModule();\n const {\n bootstrapRunnerLogStore,\n createAgentSession,\n createSessionStimulusBus,\n resolveDriverPaths,\n newSession,\n saveSession,\n touchSession,\n } = runner;\n\n const flow = loadFlow(opts.flowPath);\n const agentDir = opts.agentDir ?? resolveAgentDir(opts.projectDir);\n const settings = await resolveSettings(opts.projectDir, {\n driver: opts.driver,\n provider: opts.provider,\n model: opts.model,\n });\n\n const session = newSession({\n flowId: flow.id,\n projectDir: opts.projectDir,\n agentDir,\n driver: settings.driver ?? \"omp\",\n provider: settings.provider,\n model: settings.model,\n label: opts.sessionLabel,\n });\n\n await saveSession(opts.projectDir, session);\n\n // Bootstrap structured logging — registers a process-singleton LogStore.\n // OnLogBridgeSink mirrors entries to opts.onLog when caller provides one,\n // preserving back-compat with CLI hosts that consume plain text lines.\n const wsConfigEarly = resolveSkWorkspaceConfig(opts.projectDir);\n const { dispose: disposeLogStore } = bootstrapRunnerLogStore({\n sessionId: session.runId,\n projectDir: opts.projectDir,\n yamlBlock: (wsConfigEarly as { logging?: unknown }).logging,\n onLog: opts.onLog,\n });\n const flowLog = createLogger({\n kind: \"flow-connector\",\n subkind: \"run\",\n instance: session.runId,\n });\n const log = (line: string) => flowLog.info(line);\n\n try {\n // ── Dry run ────────────────────────────────────────────────────────────\n if (opts.dryRun) {\n const adapter = new FlowAdapter();\n const handle = await adapter.connect(\n {\n id: \"flow\",\n driver: \"flow\",\n access: \"read-only\" as const,\n options: { flow, seed: { runId: session.runId, startedBy: \"cli\" } },\n },\n {}, // flow needs no connect context\n );\n const state = adapter.getExecution(handle);\n const available = Object.values(state.nodes)\n .filter((n) => n.status === \"available\")\n .map((n) => n.id);\n log(`[dry-run] Flow: ${flow.name} (${flow.id})`);\n log(`[dry-run] Available: ${available.join(\", \") || \"(none)\"}`);\n await adapter.disconnect(handle);\n return;\n }\n\n await validatePinnedVersions(flow, opts.projectDir, log);\n\n // ── Telemetry initialization ────────────────────────────────────────────\n const wsConfig = wsConfigEarly;\n const telemetry = await initTelemetry(wsConfig.telemetry);\n const flowTrace = telemetry.startTrace({\n name: `flow:${flow.id}`,\n kind: \"flow_run\",\n attributes: {\n \"skaile.flow.id\": flow.id,\n \"skaile.flow.run_id\": session.runId,\n },\n });\n\n // ── Agent session setup ─────────────────────────────────────────────────\n const driverPaths = resolveDriverPaths(settings);\n const agentSession = await createAgentSession({\n projectDir: opts.projectDir,\n agentDir: session.agentDir,\n driver: session.driver,\n model: session.model,\n provider: session.provider,\n resumeSessionId: session.driverSessionId,\n projectClaudeMd: path.join(opts.projectDir, \"CLAUDE.md\"),\n promptsDir: path.join(opts.projectDir, driverPaths.promptsDir),\n sessionId: session.runId,\n onLog: log,\n telemetry,\n trace: flowTrace,\n wsConfig,\n });\n const { driver } = agentSession;\n const updatedSession = { ...session };\n\n // Track driver session ID so future resumes can reconnect the SDK thread.\n driver.on(\"agent-event\", () => {\n const runtimeSessionId = driver.runtimeSessionId;\n if (!runtimeSessionId || runtimeSessionId === updatedSession.driverSessionId) return;\n updatedSession.driverSessionId = runtimeSessionId;\n void saveSession(opts.projectDir, updatedSession).catch(() => {});\n });\n\n // ── FlowAdapter + stimulus bus ─────────────────────────────────────────\n //\n // Phase 4 of the flow-connector extraction: SessionStimulusBus is the sole\n // turn driver. The legacy FlowOrchestrator + onStateChange subscription\n // are gone — every turn is initiated either by the bus (after an adapter\n // mutation observed via `useBusForStimulus: true`) or by an explicit\n // `bus.signal()` call from this function (the initial flow_started turn).\n //\n // The bus's `driveTurn` callback receives the stimulus paragraph the\n // adapter rendered (not the full orchestrator prompt). It rebuilds the\n // five-section orchestrator prompt around that fragment using\n // `buildOrchestratorPrompt` so the agent sees the same flow context the\n // legacy orchestrator produced.\n const flowConnectorId = \"flow\";\n const turnTimeoutMs = opts.sessionTimeoutMs ?? DEFAULT_SESSION_TIMEOUT_MS;\n\n // Forward declaration so `driveTurn` can read the live execution\n // snapshot. Assigned just below, before the bus can fire.\n let flowAdapterRef: FlowAdapter | null = null;\n let flowHandleRef: import(\"@skaile/workspaces/connectors\").ConnectorHandle | null = null;\n\n const stimulusBus = createSessionStimulusBus({\n driveTurn: async (\n promptFragment: string,\n metas: Array<Record<string, unknown>>,\n ): Promise<void> => {\n // The adapter signal carries `meta.kind` per stimulus. Use that to\n // reconstruct the typed `TurnStimulus`; for compound batches, fall\n // back to `state_changed` (the union element that means \"look at\n // current state and continue\").\n const lastKind = metas[metas.length - 1]?.kind;\n let stimulus: TurnStimulus;\n if (lastKind === \"flow_started\") {\n stimulus = { kind: \"flow_started\" };\n } else if (\n lastKind === \"user_message\" &&\n typeof metas[metas.length - 1]?.text === \"string\"\n ) {\n const meta = metas[metas.length - 1] as Record<string, unknown>;\n stimulus = {\n kind: \"user_message\",\n text: String(meta.text ?? \"\"),\n senderId: String(meta.senderId ?? \"user\"),\n };\n } else {\n stimulus = { kind: \"state_changed\" };\n }\n // The fragment passed in by the bus is the adapter's\n // `renderStimulusPrompt(stim)` joined across coalesced signals.\n // For the initial / explicit-stimulus path, we build the full prompt\n // around the fragment via `buildOrchestratorPrompt`. The fragment is\n // discarded in favour of the structured stimulus to keep the prompt\n // shape stable; the structured form already contains everything the\n // fragment encoded.\n void promptFragment;\n if (!flowAdapterRef || !flowHandleRef) {\n throw new Error(\"driveTurn fired before FlowAdapter was wired\");\n }\n const fullPrompt = buildOrchestratorPrompt(\n flow,\n flowAdapterRef.getExecution(flowHandleRef),\n stimulus,\n );\n await awaitAgentEnd(driver, fullPrompt, opts.onEvent, turnTimeoutMs);\n },\n log: flowLog,\n });\n\n const flowAdapter = new FlowAdapter();\n const flowHandle = await flowAdapter.connect(\n {\n id: flowConnectorId,\n driver: \"flow\",\n access: \"read-write\" as const,\n options: {\n flow,\n seed: {\n runId: session.runId,\n startedBy: \"cli\",\n autonomousMode: opts.autonomousMode ?? true,\n },\n stimulusBus,\n useBusForStimulus: true,\n },\n },\n {}, // flow needs no connect context\n );\n flowAdapterRef = flowAdapter;\n flowHandleRef = flowHandle;\n\n // Forward state_changed events to the caller. The bus computes a\n // turn-kicking stimulus on each adapter mutation; the host-facing\n // event stream still observes the full snapshot via onChange.\n flowAdapter.onStateChange(flowHandle, (state: FlowExecution) => {\n opts.onEvent?.({\n type: \"state_changed\",\n store: `flow:${state.runId}`,\n state: state as unknown as Record<string, unknown>,\n } as unknown as AgentEvent);\n });\n\n // ── Execute ────────────────────────────────────────────────────────────\n flowLog.info(\"starting flow\", {\n flowId: flow.id,\n flowName: flow.name,\n runId: session.runId,\n });\n\n try {\n // Kick the initial flow_started turn explicitly. Subsequent turns are\n // driven by the bus signaling whenever the adapter mutates.\n const initialStimulus: TurnStimulus = { kind: \"flow_started\" };\n await stimulusBus.signal(flowConnectorId, {\n promptFragment: renderStimulusPrompt(initialStimulus),\n meta: { kind: initialStimulus.kind },\n });\n\n const finalState = flowAdapter.getExecution(flowHandle);\n if (finalState.done) {\n flowLog.info(\"flow complete\", { flowId: flow.id, flowName: flow.name });\n } else if (finalState.status === \"failed\") {\n flowLog.error(\"flow failed\", undefined, { flowId: flow.id, flowName: flow.name });\n } else {\n flowLog.warn(\"flow paused after one turn\", {\n flowId: flow.id,\n status: finalState.status,\n note: \"CLI mode does not interact with approval/input gates\",\n });\n }\n } finally {\n driver.kill();\n const lastState = flowAdapter.getExecution(flowHandle);\n await saveSession(\n opts.projectDir,\n touchSession({\n ...updatedSession,\n driverSessionId: driver.runtimeSessionId ?? updatedSession.driverSessionId,\n status: lastState.status === \"complete\" ? \"complete\" : \"paused\",\n }),\n ).catch(() => {});\n await flowAdapter.disconnect(flowHandle).catch(() => {});\n await agentSession.dispose();\n telemetry.endTrace(flowTrace, {\n status: flowAdapter.getExecution(flowHandle).status === \"complete\" ? \"ok\" : \"error\",\n });\n await telemetry.flush().catch(() => {});\n }\n } finally {\n disposeLogStore();\n }\n}\n\n/**\n * Resume an existing session from the CLI.\n *\n * With the Phase 2 turn-based model, flow state is NOT persisted to\n * local session files — only the driver session ID is kept. The CLI\n * can resume the agent's conversation thread, but the flow execution\n * itself starts from scratch because the runner has no durable store\n * for per-run state.\n *\n * For a governed, resumable flow run, use a host that persists flow\n * state (e.g. the Skaile platform). CLI resume is retained as a\n * driver-level convenience only: we load the session, restart the\n * flow, and the SDK will reconnect to the prior conversation thread.\n *\n * @docLink packages/factory-assets/flow#resume-flow\n */\nexport async function resumeFlow(opts: ResumeOptions): Promise<void> {\n const runner = await loadRunnerModule();\n const { loadSession, loadSessionById, bootstrapRunnerLogStore } = runner;\n\n const session = opts.sessionId\n ? await loadSessionById(opts.projectDir, opts.sessionId)\n : await loadSession(opts.projectDir);\n\n if (!session) {\n const hint = opts.sessionId\n ? `session ${opts.sessionId}`\n : `current session in ${opts.projectDir}/.skaile`;\n throw new Error(`No session found (${hint}) — run 'start' first`);\n }\n\n const flowPath = resolveFlowPath(session.flowId, opts.projectDir);\n\n // Bootstrap a transient logger for the resume diagnostics. The inner\n // runFlow() call will register its own LogStore for the new run. Keep\n // OnLogBridgeSink wiring so callers passing onLog still see this line.\n const wsConfigEarly = resolveSkWorkspaceConfig(opts.projectDir);\n const { dispose: disposeLogStore } = bootstrapRunnerLogStore({\n sessionId: session.runId,\n projectDir: opts.projectDir,\n yamlBlock: (wsConfigEarly as { logging?: unknown }).logging,\n onLog: opts.onLog,\n });\n const flowLog = createLogger({\n kind: \"flow-connector\",\n subkind: \"run\",\n instance: session.runId,\n });\n flowLog.info(\"resuming session\", {\n runId: session.runId,\n flowId: session.flowId,\n note: \"CLI mode does not persist flow state — flow restarts from scratch; driver thread resumes\",\n });\n\n try {\n await runFlow({\n projectDir: opts.projectDir,\n flowPath,\n agentDir: opts.agentDir ?? session.agentDir,\n driver: session.driver,\n model: session.model,\n provider: session.provider,\n sessionLabel: session.label,\n dryRun: opts.dryRun,\n sessionTimeoutMs: opts.sessionTimeoutMs,\n onEvent: opts.onEvent,\n onLog: opts.onLog,\n });\n } finally {\n disposeLogStore();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function validatePinnedVersions(\n flow: Awaited<ReturnType<typeof loadFlow>>,\n projectDir: string,\n log: (line: string) => void,\n): Promise<void> {\n const pinnedNodes = flow.nodes.filter((n) => n.type === \"skill\" && n.data?.version);\n if (pinnedNodes.length === 0) return;\n\n const skillVersions = new Map<string, string>();\n const aiResourcesDir = findAiResourcesDir(projectDir);\n if (aiResourcesDir) {\n for (const node of pinnedNodes) {\n const skillId = node.data?.skill ?? node.id;\n if (skillVersions.has(skillId)) continue;\n const skillPath = findSkillMd(aiResourcesDir, skillId);\n if (skillPath) {\n const content = fs.readFileSync(skillPath, \"utf-8\");\n const fm = parseSkillFrontmatter(content);\n skillVersions.set(skillId, fm.metadata?.version ?? fm.version ?? \"\");\n }\n }\n }\n\n const versionNodes = pinnedNodes.map((n) => ({\n nodeId: n.id,\n skillId: n.data?.skill ?? n.id,\n requestedVersion: n.data?.version,\n }));\n\n const checks = validateFlowVersions(versionNodes, skillVersions);\n const failures = checks.filter((c) => !c.satisfied);\n if (failures.length > 0) {\n const lines = failures.map(\n (f) => ` ${f.nodeId}: wants ${f.requested}, found ${f.actual || \"(none)\"}`,\n );\n throw new Error(`Skill version mismatch:\\n${lines.join(\"\\n\")}`);\n }\n for (const c of checks.filter((c) => c.satisfied)) {\n log(` Version OK: ${c.skillId} ${c.actual} satisfies ${c.requested}`);\n }\n}\n\nfunction resolveFlowPath(flowId: string, projectDir: string): string {\n const armInstalled = path.join(projectDir, \".skaile\", \"flows\", flowId, `${flowId}.flow.yaml`);\n if (fs.existsSync(armInstalled)) return armInstalled;\n\n const manual = path.join(projectDir, \".skaile\", \"flows\", `${flowId}.flow.yaml`);\n if (fs.existsSync(manual)) return manual;\n\n let dir = projectDir;\n for (let i = 0; i < 6; i++) {\n const aiResources = path.join(dir, \"ai-assets\");\n if (fs.existsSync(aiResources)) {\n for (const domain of fs.readdirSync(aiResources)) {\n const flowsDir = path.join(aiResources, domain, \"flows\");\n const candidate = path.join(flowsDir, `${flowId}.flow.yaml`);\n if (fs.existsSync(candidate)) return candidate;\n const legacy = path.join(flowsDir, `${flowId}.json`);\n if (fs.existsSync(legacy)) return legacy;\n }\n throw new Error(`Flow not found: ${flowId} (searched .skaile/flows/ and ${aiResources})`);\n }\n dir = path.dirname(dir);\n }\n throw new Error(\n `Flow not found: ${flowId} (no .skaile/flows/ entry and could not locate ai-assets from ${projectDir})`,\n );\n}\n\n/** Walk up from projectDir to find ai-assets/ */\nfunction findAiResourcesDir(projectDir: string): string | null {\n let dir = projectDir;\n for (let i = 0; i < 6; i++) {\n const candidate = path.join(dir, \"ai-assets\");\n if (fs.existsSync(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/** Find SKILL.md for a given skill ID by walking ai-assets domains */\nfunction findSkillMd(aiResourcesDir: string, skillId: string): string | null {\n for (const domain of fs.readdirSync(aiResourcesDir, { withFileTypes: true })) {\n if (!domain.isDirectory()) continue;\n const skillsDir = path.join(aiResourcesDir, domain.name, \"skills\");\n if (!fs.existsSync(skillsDir)) continue;\n const found = walkForSkill(skillsDir, skillId);\n if (found) return found;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Turn-wait helper\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal driver surface needed by the bus's `driveTurn` callback. Mirrors\n * the slice the legacy `FlowOrchestrator` consumed (`prompt` + `on` +\n * `removeAllListeners`) so we can keep the wait helper private to this\n * module without pulling in a runtime dep on `@skaile/workspaces/bridge`.\n */\ninterface TurnDriverSurface {\n prompt(message: string): Promise<void>;\n on(event: \"agent-event\", handler: (event: AgentEvent) => void): void;\n removeAllListeners(event: \"agent-event\"): void;\n}\n\n/**\n * Send a prompt to the driver and resolve when the agent emits\n * `agent_end` (or reject on `error`). Identical contract to the legacy\n * `awaitAgentEnd` helper from `flow-orchestrator.ts`. Phase 4 lifts the\n * helper into `run-flow.ts` because the bus now owns turn driving.\n */\nfunction awaitAgentEnd(\n driver: TurnDriverSurface,\n prompt: string,\n onEvent: ((event: AgentEvent) => void) | undefined,\n timeoutMs: number,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n\n const done = (err?: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n driver.removeAllListeners(\"agent-event\");\n if (err) reject(err);\n else resolve();\n };\n\n const timer = setTimeout(\n () => done(new Error(`Flow turn timed out after ${timeoutMs / 1000}s`)),\n timeoutMs,\n );\n\n driver.on(\"agent-event\", (event: AgentEvent) => {\n onEvent?.(event);\n if (event.type === \"agent_end\") done();\n else if (event.type === \"error\") {\n const msg =\n (event as { error?: string; message?: string }).error ??\n (event as { message?: string }).message ??\n \"Agent error\";\n done(new Error(msg));\n }\n });\n\n driver.prompt(prompt).catch(done);\n });\n}\n\nfunction walkForSkill(dir: string, skillId: string): string | null {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const full = path.join(dir, entry.name);\n const skillMd = path.join(full, \"SKILL.md\");\n if (fs.existsSync(skillMd)) {\n if (entry.name === skillId) return skillMd;\n } else {\n const found = walkForSkill(full, skillId);\n if (found) return found;\n }\n }\n return null;\n}\n"]}
1
+ {"version":3,"sources":["../factory-assets/connectors/flow/run-flow.ts"],"names":["c"],"mappings":";;;;;;;;;;;AAuDA,IAAI,aAAA;AAEJ,eAAe,gBAAA,GAAiC;AAC9C,EAAA,IAAI,eAAe,OAAO,aAAA;AAC1B,EAAA,aAAA,GAAgB,MAAM,OAAO,mBAA2B,CAAA;AACxD,EAAA,OAAO,aAAA;AACT;AAMA,IAAM,0BAAA,GAA6B,CAAA,GAAI,EAAA,GAAK,EAAA,GAAK,GAAA;AA2HjD,eAAsB,QAAQ,IAAA,EAAiC;AAC7D,EAAA,MAAM,MAAA,GAAS,MAAM,gBAAA,EAAiB;AACtC,EAAA,MAAM;AAAA,IACJ,uBAAA;AAAA,IACA,kBAAA;AAAA,IACA,wBAAA;AAAA,IACA,kBAAA;AAAA,IACA,UAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,IAAA,CAAK,QAAQ,CAAA;AACnC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,IAAY,eAAA,CAAgB,KAAK,UAAU,CAAA;AACjE,EAAA,MAAM,QAAA,GAAW,MAAM,eAAA,CAAgB,IAAA,CAAK,UAAA,EAAY;AAAA,IACtD,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,OAAO,IAAA,CAAK;AAAA,GACb,CAAA;AAED,EAAA,MAAM,UAAU,UAAA,CAAW;AAAA,IACzB,QAAQ,IAAA,CAAK,EAAA;AAAA,IACb,YAAY,IAAA,CAAK,UAAA;AAAA,IACjB,QAAA;AAAA,IACA,MAAA,EAAQ,SAAS,MAAA,IAAU,KAAA;AAAA,IAC3B,UAAU,QAAA,CAAS,QAAA;AAAA,IACnB,OAAO,QAAA,CAAS,KAAA;AAAA,IAChB,OAAO,IAAA,CAAK;AAAA,GACb,CAAA;AAED,EAAA,MAAM,WAAA,CAAY,IAAA,CAAK,UAAA,EAAY,OAAO,CAAA;AAK1C,EAAA,MAAM,aAAA,GAAgB,wBAAA,CAAyB,IAAA,CAAK,UAAU,CAAA;AAC9D,EAAA,MAAM,EAAE,OAAA,EAAS,eAAA,EAAgB,GAAI,uBAAA,CAAwB;AAAA,IAC3D,WAAW,OAAA,CAAQ,KAAA;AAAA,IACnB,YAAY,IAAA,CAAK,UAAA;AAAA,IACjB,WAAY,aAAA,CAAwC,OAAA;AAAA,IACpD,OAAO,IAAA,CAAK;AAAA,GACb,CAAA;AACD,EAAA,MAAM,UAAU,YAAA,CAAa;AAAA,IAC3B,IAAA,EAAM,gBAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IACT,UAAU,OAAA,CAAQ;AAAA,GACnB,CAAA;AACD,EAAA,MAAM,GAAA,GAAM,CAAC,IAAA,KAAiB,OAAA,CAAQ,KAAK,IAAI,CAAA;AAE/C,EAAA,IAAI;AAEF,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,MAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,OAAA;AAAA,QAC3B;AAAA,UACE,EAAA,EAAI,MAAA;AAAA,UACJ,MAAA,EAAQ,MAAA;AAAA,UACR,MAAA,EAAQ,WAAA;AAAA,UACR,OAAA,EAAS,EAAE,IAAA,EAAM,IAAA,EAAM,EAAE,OAAO,OAAA,CAAQ,KAAA,EAAO,SAAA,EAAW,KAAA,EAAM;AAAE,SACpE;AAAA,QACA;AAAC;AAAA,OACH;AACA,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,YAAA,CAAa,MAAM,CAAA;AACzC,MAAA,MAAM,YAAY,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,KAAK,EACxC,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,WAAW,CAAA,CACtC,IAAI,CAAC,CAAA,KAAM,EAAE,EAAE,CAAA;AAClB,MAAA,GAAA,CAAI,mBAAmB,IAAA,CAAK,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,EAAE,CAAA,CAAA,CAAG,CAAA;AAC/C,MAAA,GAAA,CAAI,wBAAwB,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA,IAAK,QAAQ,CAAA,CAAE,CAAA;AAC9D,MAAA,MAAM,OAAA,CAAQ,WAAW,MAAM,CAAA;AAC/B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,sBAAA,CAAuB,IAAA,EAAM,IAAA,CAAK,UAAA,EAAY,GAAG,CAAA;AAGvD,IAAA,MAAM,QAAA,GAAW,aAAA;AACjB,IAAA,MAAM,SAAA,GAAY,MAAM,aAAA,CAAc,QAAA,CAAS,SAAS,CAAA;AACxD,IAAA,MAAM,SAAA,GAAY,UAAU,UAAA,CAAW;AAAA,MACrC,IAAA,EAAM,CAAA,KAAA,EAAQ,IAAA,CAAK,EAAE,CAAA,CAAA;AAAA,MACrB,IAAA,EAAM,UAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,kBAAkB,IAAA,CAAK,EAAA;AAAA,QACvB,sBAAsB,OAAA,CAAQ;AAAA;AAChC,KACD,CAAA;AAGD,IAAA,MAAM,WAAA,GAAc,mBAAmB,QAAQ,CAAA;AAC/C,IAAA,MAAM,YAAA,GAAe,MAAM,kBAAA,CAAmB;AAAA,MAC5C,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,iBAAiB,OAAA,CAAQ,eAAA;AAAA,MACzB,eAAA,EAAiB,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,YAAY,WAAW,CAAA;AAAA,MACvD,YAAY,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,YAAY,UAAU,CAAA;AAAA,MAC7D,WAAW,OAAA,CAAQ,KAAA;AAAA,MACnB,KAAA,EAAO,GAAA;AAAA,MACP,SAAA;AAAA,MACA,KAAA,EAAO,SAAA;AAAA,MACP;AAAA,KACD,CAAA;AACD,IAAA,MAAM,EAAE,QAAO,GAAI,YAAA;AACnB,IAAA,MAAM,cAAA,GAAiB,EAAE,GAAG,OAAA,EAAQ;AAGpC,IAAA,MAAA,CAAO,EAAA,CAAG,eAAe,MAAM;AAC7B,MAAA,MAAM,mBAAmB,MAAA,CAAO,gBAAA;AAChC,MAAA,IAAI,CAAC,gBAAA,IAAoB,gBAAA,KAAqB,cAAA,CAAe,eAAA,EAAiB;AAC9E,MAAA,cAAA,CAAe,eAAA,GAAkB,gBAAA;AACjC,MAAA,KAAK,YAAY,IAAA,CAAK,UAAA,EAAY,cAAc,CAAA,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IAClE,CAAC,CAAA;AAeD,IAAA,MAAM,eAAA,GAAkB,MAAA;AACxB,IAAA,MAAM,aAAA,GAAgB,KAAK,gBAAA,IAAoB,0BAAA;AAI/C,IAAA,IAAI,cAAA,GAAqC,IAAA;AACzC,IAAA,IAAI,aAAA,GAAgF,IAAA;AAEpF,IAAA,MAAM,cAAc,wBAAA,CAAyB;AAAA,MAC3C,SAAA,EAAW,OACT,cAAA,EACA,KAAA,KACkB;AAKlB,QAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA,EAAG,IAAA;AAC1C,QAAA,IAAI,QAAA;AACJ,QAAA,IAAI,aAAa,cAAA,EAAgB;AAC/B,UAAA,QAAA,GAAW,EAAE,MAAM,cAAA,EAAe;AAAA,QACpC,CAAA,MAAA,IACE,QAAA,KAAa,cAAA,IACb,OAAO,KAAA,CAAM,MAAM,MAAA,GAAS,CAAC,CAAA,EAAG,IAAA,KAAS,QAAA,EACzC;AACA,UAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AACnC,UAAA,QAAA,GAAW;AAAA,YACT,IAAA,EAAM,cAAA;AAAA,YACN,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,IAAA,IAAQ,EAAE,CAAA;AAAA,YAC5B,QAAA,EAAU,MAAA,CAAO,IAAA,CAAK,QAAA,IAAY,MAAM;AAAA,WAC1C;AAAA,QACF,CAAA,MAAO;AACL,UAAA,QAAA,GAAW,EAAE,MAAM,eAAA,EAAgB;AAAA,QACrC;AAQA,QAAA,KAAK,cAAA;AACL,QAAA,IAAI,CAAC,cAAA,IAAkB,CAAC,aAAA,EAAe;AACrC,UAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,QAChE;AACA,QAAA,MAAM,UAAA,GAAa,uBAAA;AAAA,UACjB,IAAA;AAAA,UACA,cAAA,CAAe,aAAa,aAAa,CAAA;AAAA,UACzC;AAAA,SACF;AACA,QAAA,MAAM,aAAA,CAAc,MAAA,EAAQ,UAAA,EAAY,IAAA,CAAK,SAAS,aAAa,CAAA;AAAA,MACrE,CAAA;AAAA,MACA,GAAA,EAAK;AAAA,KACN,CAAA;AAED,IAAA,MAAM,WAAA,GAAc,IAAI,WAAA,EAAY;AACpC,IAAA,MAAM,UAAA,GAAa,MAAM,WAAA,CAAY,OAAA;AAAA,MACnC;AAAA,QACE,EAAA,EAAI,eAAA;AAAA,QACJ,MAAA,EAAQ,MAAA;AAAA,QACR,MAAA,EAAQ,YAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,IAAA;AAAA,UACA,IAAA,EAAM;AAAA,YACJ,OAAO,OAAA,CAAQ,KAAA;AAAA,YACf,SAAA,EAAW,KAAA;AAAA,YACX,cAAA,EAAgB,KAAK,cAAA,IAAkB;AAAA,WACzC;AAAA,UACA,WAAA;AAAA,UACA,iBAAA,EAAmB;AAAA;AACrB,OACF;AAAA,MACA;AAAC;AAAA,KACH;AACA,IAAA,cAAA,GAAiB,WAAA;AACjB,IAAA,aAAA,GAAgB,UAAA;AAKhB,IAAA,WAAA,CAAY,aAAA,CAAc,UAAA,EAAY,CAAC,KAAA,KAAyB;AAC9D,MAAA,IAAA,CAAK,OAAA,GAAU;AAAA,QACb,IAAA,EAAM,eAAA;AAAA,QACN,KAAA,EAAO,CAAA,KAAA,EAAQ,KAAA,CAAM,KAAK,CAAA,CAAA;AAAA,QAC1B;AAAA,OACwB,CAAA;AAAA,IAC5B,CAAC,CAAA;AAGD,IAAA,OAAA,CAAQ,KAAK,eAAA,EAAiB;AAAA,MAC5B,QAAQ,IAAA,CAAK,EAAA;AAAA,MACb,UAAU,IAAA,CAAK,IAAA;AAAA,MACf,OAAO,OAAA,CAAQ;AAAA,KAChB,CAAA;AAED,IAAA,IAAI;AAGF,MAAA,MAAM,eAAA,GAAgC,EAAE,IAAA,EAAM,cAAA,EAAe;AAC7D,MAAA,MAAM,WAAA,CAAY,OAAO,eAAA,EAAiB;AAAA,QACxC,cAAA,EAAgB,qBAAqB,eAAe,CAAA;AAAA,QACpD,IAAA,EAAM,EAAE,IAAA,EAAM,eAAA,CAAgB,IAAA;AAAK,OACpC,CAAA;AAED,MAAA,MAAM,UAAA,GAAa,WAAA,CAAY,YAAA,CAAa,UAAU,CAAA;AACtD,MAAA,IAAI,WAAW,IAAA,EAAM;AACnB,QAAA,OAAA,CAAQ,IAAA,CAAK,iBAAiB,EAAE,MAAA,EAAQ,KAAK,EAAA,EAAI,QAAA,EAAU,IAAA,CAAK,IAAA,EAAM,CAAA;AAAA,MACxE,CAAA,MAAA,IAAW,UAAA,CAAW,MAAA,KAAW,QAAA,EAAU;AACzC,QAAA,OAAA,CAAQ,KAAA,CAAM,aAAA,EAAe,KAAA,CAAA,EAAW,EAAE,MAAA,EAAQ,KAAK,EAAA,EAAI,QAAA,EAAU,IAAA,CAAK,IAAA,EAAM,CAAA;AAAA,MAClF,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,KAAK,4BAAA,EAA8B;AAAA,UACzC,QAAQ,IAAA,CAAK,EAAA;AAAA,UACb,QAAQ,UAAA,CAAW,MAAA;AAAA,UACnB,IAAA,EAAM;AAAA,SACP,CAAA;AAAA,MACH;AAAA,IACF,CAAA,SAAE;AACA,MAAA,MAAA,CAAO,IAAA,EAAK;AACZ,MAAA,MAAM,SAAA,GAAY,WAAA,CAAY,YAAA,CAAa,UAAU,CAAA;AACrD,MAAA,MAAM,WAAA;AAAA,QACJ,IAAA,CAAK,UAAA;AAAA,QACL,YAAA,CAAa;AAAA,UACX,GAAG,cAAA;AAAA,UACH,eAAA,EAAiB,MAAA,CAAO,gBAAA,IAAoB,cAAA,CAAe,eAAA;AAAA,UAC3D,MAAA,EAAQ,SAAA,CAAU,MAAA,KAAW,UAAA,GAAa,UAAA,GAAa;AAAA,SACxD;AAAA,OACH,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAChB,MAAA,MAAM,WAAA,CAAY,UAAA,CAAW,UAAU,CAAA,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AACvD,MAAA,MAAM,aAAa,OAAA,EAAQ;AAC3B,MAAA,SAAA,CAAU,SAAS,SAAA,EAAW;AAAA,QAC5B,QAAQ,WAAA,CAAY,YAAA,CAAa,UAAU,CAAA,CAAE,MAAA,KAAW,aAAa,IAAA,GAAO;AAAA,OAC7E,CAAA;AACD,MAAA,MAAM,SAAA,CAAU,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACxC;AAAA,EACF,CAAA,SAAE;AACA,IAAA,eAAA,EAAgB;AAAA,EAClB;AACF;AAkBA,eAAsB,WAAW,IAAA,EAAoC;AACnE,EAAA,MAAM,MAAA,GAAS,MAAM,gBAAA,EAAiB;AACtC,EAAA,MAAM,EAAE,WAAA,EAAa,eAAA,EAAiB,uBAAA,EAAwB,GAAI,MAAA;AAElE,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,GACjB,MAAM,eAAA,CAAgB,IAAA,CAAK,UAAA,EAAY,IAAA,CAAK,SAAS,CAAA,GACrD,MAAM,WAAA,CAAY,KAAK,UAAU,CAAA;AAErC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,GACd,CAAA,QAAA,EAAW,KAAK,SAAS,CAAA,CAAA,GACzB,CAAA,mBAAA,EAAsB,IAAA,CAAK,UAAU,CAAA,QAAA,CAAA;AACzC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,IAAI,CAAA,0BAAA,CAAuB,CAAA;AAAA,EAClE;AAEA,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,OAAA,CAAQ,MAAA,EAAQ,KAAK,UAAU,CAAA;AAKhE,EAAA,MAAM,aAAA,GAAgB,wBAAA,CAAyB,IAAA,CAAK,UAAU,CAAA;AAC9D,EAAA,MAAM,EAAE,OAAA,EAAS,eAAA,EAAgB,GAAI,uBAAA,CAAwB;AAAA,IAC3D,WAAW,OAAA,CAAQ,KAAA;AAAA,IACnB,YAAY,IAAA,CAAK,UAAA;AAAA,IACjB,WAAY,aAAA,CAAwC,OAAA;AAAA,IACpD,OAAO,IAAA,CAAK;AAAA,GACb,CAAA;AACD,EAAA,MAAM,UAAU,YAAA,CAAa;AAAA,IAC3B,IAAA,EAAM,gBAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IACT,UAAU,OAAA,CAAQ;AAAA,GACnB,CAAA;AACD,EAAA,OAAA,CAAQ,KAAK,kBAAA,EAAoB;AAAA,IAC/B,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,CAAQ;AAAA,MACZ,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,QAAA;AAAA,MACA,QAAA,EAAU,IAAA,CAAK,QAAA,IAAY,OAAA,CAAQ,QAAA;AAAA,MACnC,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,cAAc,OAAA,CAAQ,KAAA;AAAA,MACtB,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,kBAAkB,IAAA,CAAK,gBAAA;AAAA,MACvB,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,OAAO,IAAA,CAAK;AAAA,KACb,CAAA;AAAA,EACH,CAAA,SAAE;AACA,IAAA,eAAA,EAAgB;AAAA,EAClB;AACF;AAMA,eAAe,sBAAA,CACb,IAAA,EACA,UAAA,EACA,GAAA,EACe;AACf,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,OAAA,IAAW,CAAA,CAAE,IAAA,EAAM,OAAO,CAAA;AAClF,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAE9B,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAoB;AAC9C,EAAA,MAAM,cAAA,GAAiB,mBAAmB,UAAU,CAAA;AACpD,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,KAAA,MAAW,QAAQ,WAAA,EAAa;AAC9B,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,EAAM,KAAA,IAAS,IAAA,CAAK,EAAA;AACzC,MAAA,IAAI,aAAA,CAAc,GAAA,CAAI,OAAO,CAAA,EAAG;AAChC,MAAA,MAAM,SAAA,GAAY,WAAA,CAAY,cAAA,EAAgB,OAAO,CAAA;AACrD,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,MAAM,OAAA,GAAU,EAAA,CAAG,YAAA,CAAa,SAAA,EAAW,OAAO,CAAA;AAClD,QAAA,MAAM,EAAA,GAAK,sBAAsB,OAAO,CAAA;AACxC,QAAA,aAAA,CAAc,IAAI,OAAA,EAAS,EAAA,CAAG,UAAU,OAAA,IAAW,EAAA,CAAG,WAAW,EAAE,CAAA;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAC3C,QAAQ,CAAA,CAAE,EAAA;AAAA,IACV,OAAA,EAAS,CAAA,CAAE,IAAA,EAAM,KAAA,IAAS,CAAA,CAAE,EAAA;AAAA,IAC5B,gBAAA,EAAkB,EAAE,IAAA,EAAM;AAAA,GAC5B,CAAE,CAAA;AAEF,EAAA,MAAM,MAAA,GAAS,oBAAA,CAAqB,YAAA,EAAc,aAAa,CAAA;AAC/D,EAAA,MAAM,WAAW,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,EAAE,SAAS,CAAA;AAClD,EAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,IAAA,MAAM,QAAQ,QAAA,CAAS,GAAA;AAAA,MACrB,CAAC,CAAA,KAAM,CAAA,EAAA,EAAK,CAAA,CAAE,MAAM,CAAA,QAAA,EAAW,CAAA,CAAE,SAAS,CAAA,QAAA,EAAW,CAAA,CAAE,MAAA,IAAU,QAAQ,CAAA;AAAA,KAC3E;AACA,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA;AAAA,EAA4B,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,EAChE;AACA,EAAA,KAAA,MAAW,KAAK,MAAA,CAAO,MAAA,CAAO,CAACA,EAAAA,KAAMA,EAAAA,CAAE,SAAS,CAAA,EAAG;AACjD,IAAA,GAAA,CAAI,CAAA,cAAA,EAAiB,EAAE,OAAO,CAAA,CAAA,EAAI,EAAE,MAAM,CAAA,WAAA,EAAc,CAAA,CAAE,SAAS,CAAA,CAAE,CAAA;AAAA,EACvE;AACF;AAEA,SAAS,eAAA,CAAgB,QAAgB,UAAA,EAA4B;AACnE,EAAA,MAAM,YAAA,GAAe,KAAK,IAAA,CAAK,UAAA,EAAY,WAAW,OAAA,EAAS,MAAA,EAAQ,CAAA,EAAG,MAAM,CAAA,UAAA,CAAY,CAAA;AAC5F,EAAA,IAAI,EAAA,CAAG,UAAA,CAAW,YAAY,CAAA,EAAG,OAAO,YAAA;AAExC,EAAA,MAAM,MAAA,GAAS,KAAK,IAAA,CAAK,UAAA,EAAY,WAAW,OAAA,EAAS,CAAA,EAAG,MAAM,CAAA,UAAA,CAAY,CAAA;AAC9E,EAAA,IAAI,EAAA,CAAG,UAAA,CAAW,MAAM,CAAA,EAAG,OAAO,MAAA;AAElC,EAAA,IAAI,GAAA,GAAM,UAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC1B,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,WAAW,CAAA;AAC9C,IAAA,IAAI,EAAA,CAAG,UAAA,CAAW,WAAW,CAAA,EAAG;AAC9B,MAAA,KAAA,MAAW,MAAA,IAAU,EAAA,CAAG,WAAA,CAAY,WAAW,CAAA,EAAG;AAChD,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,QAAQ,OAAO,CAAA;AACvD,QAAA,MAAM,YAAY,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,CAAA,EAAG,MAAM,CAAA,UAAA,CAAY,CAAA;AAC3D,QAAA,IAAI,EAAA,CAAG,UAAA,CAAW,SAAS,CAAA,EAAG,OAAO,SAAA;AACrC,QAAA,MAAM,SAAS,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,CAAA,EAAG,MAAM,CAAA,KAAA,CAAO,CAAA;AACnD,QAAA,IAAI,EAAA,CAAG,UAAA,CAAW,MAAM,CAAA,EAAG,OAAO,MAAA;AAAA,MACpC;AACA,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,MAAM,CAAA,8BAAA,EAAiC,WAAW,CAAA,CAAA,CAAG,CAAA;AAAA,IAC1F;AACA,IAAA,GAAA,GAAM,IAAA,CAAK,QAAQ,GAAG,CAAA;AAAA,EACxB;AACA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,gBAAA,EAAmB,MAAM,CAAA,8DAAA,EAAiE,UAAU,CAAA,CAAA;AAAA,GACtG;AACF;AAGA,SAAS,mBAAmB,UAAA,EAAmC;AAC7D,EAAA,IAAI,GAAA,GAAM,UAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC1B,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,WAAW,CAAA;AAC5C,IAAA,IAAI,EAAA,CAAG,UAAA,CAAW,SAAS,CAAA,EAAG,OAAO,SAAA;AACrC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC/B,IAAA,IAAI,WAAW,GAAA,EAAK;AACpB,IAAA,GAAA,GAAM,MAAA;AAAA,EACR;AACA,EAAA,OAAO,IAAA;AACT;AAGA,SAAS,WAAA,CAAY,gBAAwB,OAAA,EAAgC;AAC3E,EAAA,KAAA,MAAW,MAAA,IAAU,GAAG,WAAA,CAAY,cAAA,EAAgB,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA,EAAG;AAC5E,IAAA,IAAI,CAAC,MAAA,CAAO,WAAA,EAAY,EAAG;AAC3B,IAAA,MAAM,YAAY,IAAA,CAAK,IAAA,CAAK,cAAA,EAAgB,MAAA,CAAO,MAAM,QAAQ,CAAA;AACjE,IAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,SAAS,CAAA,EAAG;AAC/B,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,SAAA,EAAW,OAAO,CAAA;AAC7C,IAAA,IAAI,OAAO,OAAO,KAAA;AAAA,EACpB;AACA,EAAA,OAAO,IAAA;AACT;AAwBA,SAAS,aAAA,CACP,MAAA,EACA,MAAA,EACA,OAAA,EACA,SAAA,EACe;AACf,EAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC5C,IAAA,IAAI,OAAA,GAAU,KAAA;AAEd,IAAA,MAAM,IAAA,GAAO,CAAC,GAAA,KAAgB;AAC5B,MAAA,IAAI,OAAA,EAAS;AACb,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,MAAA,CAAO,mBAAmB,aAAa,CAAA;AACvC,MAAA,IAAI,GAAA,SAAY,GAAG,CAAA;AAAA,WACd,OAAA,EAAQ;AAAA,IACf,CAAA;AAEA,IAAA,MAAM,KAAA,GAAQ,UAAA;AAAA,MACZ,MAAM,KAAK,IAAI,KAAA,CAAM,6BAA6B,SAAA,GAAY,GAAI,GAAG,CAAC,CAAA;AAAA,MACtE;AAAA,KACF;AAEA,IAAA,MAAA,CAAO,EAAA,CAAG,aAAA,EAAe,CAAC,KAAA,KAAsB;AAC9C,MAAA,OAAA,GAAU,KAAK,CAAA;AACf,MAAA,IAAI,KAAA,CAAM,IAAA,KAAS,WAAA,EAAa,IAAA,EAAK;AAAA,WAAA,IAC5B,KAAA,CAAM,SAAS,OAAA,EAAS;AAC/B,QAAA,MAAM,GAAA,GACH,KAAA,CAA+C,KAAA,IAC/C,KAAA,CAA+B,OAAA,IAChC,aAAA;AACF,QAAA,IAAA,CAAK,IAAI,KAAA,CAAM,GAAG,CAAC,CAAA;AAAA,MACrB;AAAA,IACF,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,CAAE,KAAA,CAAM,IAAI,CAAA;AAAA,EAClC,CAAC,CAAA;AACH;AAEA,SAAS,YAAA,CAAa,KAAa,OAAA,EAAgC;AACjE,EAAA,KAAA,MAAW,KAAA,IAAS,GAAG,WAAA,CAAY,GAAA,EAAK,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA,EAAG;AAChE,IAAA,IAAI,CAAC,KAAA,CAAM,WAAA,EAAY,EAAG;AAC1B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,MAAM,IAAI,CAAA;AACtC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,UAAU,CAAA;AAC1C,IAAA,IAAI,EAAA,CAAG,UAAA,CAAW,OAAO,CAAA,EAAG;AAC1B,MAAA,IAAI,KAAA,CAAM,IAAA,KAAS,OAAA,EAAS,OAAO,OAAA;AAAA,IACrC,CAAA,MAAO;AACL,MAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,IAAA,EAAM,OAAO,CAAA;AACxC,MAAA,IAAI,OAAO,OAAO,KAAA;AAAA,IACpB;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT","file":"chunk-BEO6KN7P.js","sourcesContent":["/**\n * runFlow / resumeFlow — CLI entry helpers for the flow connector.\n *\n * Moved from `runner/src/runner.ts` to `factory-assets/connectors/flow/run-flow.ts`\n * in Phase 3 of the flow-connector extraction (2026-05-08). Behaviour is\n * byte-identical to the previous runner-side implementation; only the log\n * source changes from `runner:flow:<runId>` to `flow-connector:run:<runId>`.\n *\n * The runner re-exports these symbols with a deprecation warning for one\n * release. CLI consumers should switch to\n * `import { runFlow, resumeFlow } from \"@skaile/workspaces/factory-assets/connectors/flow/run-flow\"`.\n *\n * Internal runner helpers (FlowOrchestrator, bootstrapRunnerLogStore,\n * createAgentSession, resolveDriverPaths, session helpers) are loaded lazily\n * via dynamic `await import(\"@skaile/workspaces/runner\")` inside\n * `loadRunnerModule()` below. The lazy load avoids a static package-level\n * cycle (runner → connectors → factory-assets → runner) — the cycle exists at\n * the workspace level but never resolves at module-load time because\n * factory-assets only ever calls `import` from inside an async function body.\n * The string-literal specifier preserves `bun --compile` and tsup static\n * analysis.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AgentEvent } from \"@skaile/workspaces/bridge\";\nimport {\n resolveAgentDir,\n resolveSettings,\n resolveSkWorkspaceConfig,\n} from \"@skaile/workspaces/core\";\nimport { createLogger } from \"@skaile/workspaces/core/logging\";\nimport { parseSkillFrontmatter, validateFlowVersions } from \"@skaile/workspaces/resolver\";\nimport { initTelemetry } from \"@skaile/workspaces/telemetry\";\nimport type { FlowExecution } from \"@skaile/workspaces/types\";\nimport { FlowAdapter } from \"./adapter.js\";\nimport { loadFlow } from \"./engine/index.js\";\nimport {\n buildOrchestratorPrompt,\n renderStimulusPrompt,\n type TurnStimulus,\n} from \"./prompt-fragments.js\";\n\n/**\n * Lazy `import(\"@skaile/workspaces/runner\")` accessor. Cached on first call so\n * subsequent `runFlow` invocations don't re-evaluate the runner module.\n *\n * Dynamic ESM import is used (not `require`) so vitest and other ESM\n * bundlers honour their alias resolution — `require` would side-step the\n * configured aliases and pick up two distinct module instances when run\n * under vitest. The string-literal specifier ensures bun --compile keeps\n * the dependency (per the static-import-or-die rule in\n * connectors/CLAUDE.md).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _runnerModule: any | undefined;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function loadRunnerModule(): Promise<any> {\n if (_runnerModule) return _runnerModule;\n _runnerModule = await import(\"@skaile/workspaces/runner\");\n return _runnerModule;\n}\n\n/** Type-only re-export of SessionState so the runner tombstone shim still works. */\nexport type SessionState = import(\"@skaile/workspaces/runner\").SessionState;\n\n/** Maximum agent session duration (4 hours). Configurable via {@link RunOptions.sessionTimeoutMs}. */\nconst DEFAULT_SESSION_TIMEOUT_MS = 4 * 60 * 60 * 1000; // 4 hours\n\n/**\n * Options for {@link runFlow}.\n *\n * Wraps `FlowOrchestrator` with autonomous mode turned on by default so\n * interactive approval/input gates don't block a terminal run.\n *\n * @docLink packages/factory-assets/flow#run-flow\n */\nexport interface RunOptions {\n /** The working directory for the project being orchestrated. */\n projectDir: string;\n /** Absolute path to the `.flow.yaml` or `.flow.json` definition file. */\n flowPath: string;\n /**\n * Directory containing `agent.yaml`, `SOUL.md`, `RULES.md`, `knowledge/`.\n * Resolved from `skaile.yaml` via `resolveAgentDir` when absent.\n */\n agentDir?: string;\n /**\n * Agent driver backend. Defaults to `settings.driver` (`\"omp\"` or `\"claude-sdk\"`).\n */\n driver?: string;\n /**\n * LLM provider override (e.g. `\"anthropic\"`, `\"openrouter\"`).\n * Falls back to `settings.provider` when absent.\n */\n provider?: string;\n /**\n * Model name override. Falls back to `settings.model` when absent.\n */\n model?: string;\n /**\n * Path to a specific `settings.json` to load instead of the default\n * layered resolution chain (project → parent → global → built-in defaults).\n */\n settingsFile?: string;\n /**\n * When `true`, prints the initial flow state without starting the agent\n * and returns immediately.\n */\n dryRun?: boolean;\n /**\n * Per-session timeout in milliseconds. Defaults to\n * {@link DEFAULT_SESSION_TIMEOUT_MS} (4 hours).\n */\n sessionTimeoutMs?: number;\n /** Optional human-readable label shown in the session list. */\n sessionLabel?: string;\n /** Autonomous mode for CLI runs — defaults to true so interactive approval gates are skipped. */\n autonomousMode?: boolean;\n /**\n * Called for each {@link AgentEvent} emitted during the run\n * (e.g. `text`, `tool_call`, `state_changed`).\n */\n onEvent?: (event: AgentEvent) => void;\n /**\n * Called for each diagnostic log line. Defaults to `process.stdout`.\n */\n onLog?: (line: string) => void;\n}\n\n/**\n * Options for resuming an existing CLI session.\n *\n * Reconnects the driver's conversation thread (conversation history is\n * preserved via the stored `driverSessionId`) but restarts flow execution\n * from scratch — flow state is not persisted in CLI mode. For governed,\n * resumable flow runs use a host that persists flow state (e.g. the Skaile\n * platform).\n *\n * @docLink packages/factory-assets/flow#resume-flow\n */\nexport interface ResumeOptions {\n /** The working directory for the project being orchestrated. */\n projectDir: string;\n /**\n * Specific run ID to resume. When absent, the current session pointer\n * at `<projectDir>/.skaile/current` is used.\n */\n sessionId?: string;\n /**\n * Agent definition directory override. Defaults to the directory stored\n * in the session file.\n */\n agentDir?: string;\n /**\n * When `true`, prints the initial flow state without starting the agent\n * and returns immediately.\n */\n dryRun?: boolean;\n /**\n * Per-session timeout in milliseconds. Defaults to\n * {@link DEFAULT_SESSION_TIMEOUT_MS} (4 hours).\n */\n sessionTimeoutMs?: number;\n /**\n * Called for each {@link AgentEvent} emitted during the run.\n */\n onEvent?: RunOptions[\"onEvent\"];\n /**\n * Called for each diagnostic log line. Defaults to `process.stdout`.\n */\n onLog?: RunOptions[\"onLog\"];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Start a new flow session from the CLI.\n *\n * Wraps `FlowOrchestrator` with autonomous mode turned on by default so\n * interactive approval/input gates don't block a terminal run. The\n * runner remains idle between turns — for the CLI use case, a single\n * turn should carry the flow to completion in autonomous mode. Non-CLI\n * hosts (Skaile platform, Pichi) use the orchestrator directly via the\n * serve command surface and drive gates through user actions.\n *\n * @docLink packages/factory-assets/flow#run-flow\n */\nexport async function runFlow(opts: RunOptions): Promise<void> {\n const runner = await loadRunnerModule();\n const {\n bootstrapRunnerLogStore,\n createAgentSession,\n createSessionStimulusBus,\n resolveDriverPaths,\n newSession,\n saveSession,\n touchSession,\n } = runner;\n\n const flow = loadFlow(opts.flowPath);\n const agentDir = opts.agentDir ?? resolveAgentDir(opts.projectDir);\n const settings = await resolveSettings(opts.projectDir, {\n driver: opts.driver,\n provider: opts.provider,\n model: opts.model,\n });\n\n const session = newSession({\n flowId: flow.id,\n projectDir: opts.projectDir,\n agentDir,\n driver: settings.driver ?? \"omp\",\n provider: settings.provider,\n model: settings.model,\n label: opts.sessionLabel,\n });\n\n await saveSession(opts.projectDir, session);\n\n // Bootstrap structured logging — registers a process-singleton LogStore.\n // OnLogBridgeSink mirrors entries to opts.onLog when caller provides one,\n // preserving back-compat with CLI hosts that consume plain text lines.\n const wsConfigEarly = resolveSkWorkspaceConfig(opts.projectDir);\n const { dispose: disposeLogStore } = bootstrapRunnerLogStore({\n sessionId: session.runId,\n projectDir: opts.projectDir,\n yamlBlock: (wsConfigEarly as { logging?: unknown }).logging,\n onLog: opts.onLog,\n });\n const flowLog = createLogger({\n kind: \"flow-connector\",\n subkind: \"run\",\n instance: session.runId,\n });\n const log = (line: string) => flowLog.info(line);\n\n try {\n // ── Dry run ────────────────────────────────────────────────────────────\n if (opts.dryRun) {\n const adapter = new FlowAdapter();\n const handle = await adapter.connect(\n {\n id: \"flow\",\n driver: \"flow\",\n access: \"read-only\" as const,\n options: { flow, seed: { runId: session.runId, startedBy: \"cli\" } },\n },\n {}, // flow needs no connect context\n );\n const state = adapter.getExecution(handle);\n const available = Object.values(state.nodes)\n .filter((n) => n.status === \"available\")\n .map((n) => n.id);\n log(`[dry-run] Flow: ${flow.name} (${flow.id})`);\n log(`[dry-run] Available: ${available.join(\", \") || \"(none)\"}`);\n await adapter.disconnect(handle);\n return;\n }\n\n await validatePinnedVersions(flow, opts.projectDir, log);\n\n // ── Telemetry initialization ────────────────────────────────────────────\n const wsConfig = wsConfigEarly;\n const telemetry = await initTelemetry(wsConfig.telemetry);\n const flowTrace = telemetry.startTrace({\n name: `flow:${flow.id}`,\n kind: \"flow_run\",\n attributes: {\n \"skaile.flow.id\": flow.id,\n \"skaile.flow.run_id\": session.runId,\n },\n });\n\n // ── Agent session setup ─────────────────────────────────────────────────\n const driverPaths = resolveDriverPaths(settings);\n const agentSession = await createAgentSession({\n projectDir: opts.projectDir,\n agentDir: session.agentDir,\n driver: session.driver,\n model: session.model,\n provider: session.provider,\n resumeSessionId: session.driverSessionId,\n projectClaudeMd: path.join(opts.projectDir, \"CLAUDE.md\"),\n promptsDir: path.join(opts.projectDir, driverPaths.promptsDir),\n sessionId: session.runId,\n onLog: log,\n telemetry,\n trace: flowTrace,\n wsConfig,\n });\n const { driver } = agentSession;\n const updatedSession = { ...session };\n\n // Track driver session ID so future resumes can reconnect the SDK thread.\n driver.on(\"agent-event\", () => {\n const runtimeSessionId = driver.runtimeSessionId;\n if (!runtimeSessionId || runtimeSessionId === updatedSession.driverSessionId) return;\n updatedSession.driverSessionId = runtimeSessionId;\n void saveSession(opts.projectDir, updatedSession).catch(() => {});\n });\n\n // ── FlowAdapter + stimulus bus ─────────────────────────────────────────\n //\n // Phase 4 of the flow-connector extraction: SessionStimulusBus is the sole\n // turn driver. The legacy FlowOrchestrator + onStateChange subscription\n // are gone — every turn is initiated either by the bus (after an adapter\n // mutation observed via `useBusForStimulus: true`) or by an explicit\n // `bus.signal()` call from this function (the initial flow_started turn).\n //\n // The bus's `driveTurn` callback receives the stimulus paragraph the\n // adapter rendered (not the full orchestrator prompt). It rebuilds the\n // five-section orchestrator prompt around that fragment using\n // `buildOrchestratorPrompt` so the agent sees the same flow context the\n // legacy orchestrator produced.\n const flowConnectorId = \"flow\";\n const turnTimeoutMs = opts.sessionTimeoutMs ?? DEFAULT_SESSION_TIMEOUT_MS;\n\n // Forward declaration so `driveTurn` can read the live execution\n // snapshot. Assigned just below, before the bus can fire.\n let flowAdapterRef: FlowAdapter | null = null;\n let flowHandleRef: import(\"@skaile/workspaces/connectors\").ConnectorHandle | null = null;\n\n const stimulusBus = createSessionStimulusBus({\n driveTurn: async (\n promptFragment: string,\n metas: Array<Record<string, unknown>>,\n ): Promise<void> => {\n // The adapter signal carries `meta.kind` per stimulus. Use that to\n // reconstruct the typed `TurnStimulus`; for compound batches, fall\n // back to `state_changed` (the union element that means \"look at\n // current state and continue\").\n const lastKind = metas[metas.length - 1]?.kind;\n let stimulus: TurnStimulus;\n if (lastKind === \"flow_started\") {\n stimulus = { kind: \"flow_started\" };\n } else if (\n lastKind === \"user_message\" &&\n typeof metas[metas.length - 1]?.text === \"string\"\n ) {\n const meta = metas[metas.length - 1] as Record<string, unknown>;\n stimulus = {\n kind: \"user_message\",\n text: String(meta.text ?? \"\"),\n senderId: String(meta.senderId ?? \"user\"),\n };\n } else {\n stimulus = { kind: \"state_changed\" };\n }\n // The fragment passed in by the bus is the adapter's\n // `renderStimulusPrompt(stim)` joined across coalesced signals.\n // For the initial / explicit-stimulus path, we build the full prompt\n // around the fragment via `buildOrchestratorPrompt`. The fragment is\n // discarded in favour of the structured stimulus to keep the prompt\n // shape stable; the structured form already contains everything the\n // fragment encoded.\n void promptFragment;\n if (!flowAdapterRef || !flowHandleRef) {\n throw new Error(\"driveTurn fired before FlowAdapter was wired\");\n }\n const fullPrompt = buildOrchestratorPrompt(\n flow,\n flowAdapterRef.getExecution(flowHandleRef),\n stimulus,\n );\n await awaitAgentEnd(driver, fullPrompt, opts.onEvent, turnTimeoutMs);\n },\n log: flowLog,\n });\n\n const flowAdapter = new FlowAdapter();\n const flowHandle = await flowAdapter.connect(\n {\n id: flowConnectorId,\n driver: \"flow\",\n access: \"read-write\" as const,\n options: {\n flow,\n seed: {\n runId: session.runId,\n startedBy: \"cli\",\n autonomousMode: opts.autonomousMode ?? true,\n },\n stimulusBus,\n useBusForStimulus: true,\n },\n },\n {}, // flow needs no connect context\n );\n flowAdapterRef = flowAdapter;\n flowHandleRef = flowHandle;\n\n // Forward state_changed events to the caller. The bus computes a\n // turn-kicking stimulus on each adapter mutation; the host-facing\n // event stream still observes the full snapshot via onChange.\n flowAdapter.onStateChange(flowHandle, (state: FlowExecution) => {\n opts.onEvent?.({\n type: \"state_changed\",\n store: `flow:${state.runId}`,\n state: state as unknown as Record<string, unknown>,\n } as unknown as AgentEvent);\n });\n\n // ── Execute ────────────────────────────────────────────────────────────\n flowLog.info(\"starting flow\", {\n flowId: flow.id,\n flowName: flow.name,\n runId: session.runId,\n });\n\n try {\n // Kick the initial flow_started turn explicitly. Subsequent turns are\n // driven by the bus signaling whenever the adapter mutates.\n const initialStimulus: TurnStimulus = { kind: \"flow_started\" };\n await stimulusBus.signal(flowConnectorId, {\n promptFragment: renderStimulusPrompt(initialStimulus),\n meta: { kind: initialStimulus.kind },\n });\n\n const finalState = flowAdapter.getExecution(flowHandle);\n if (finalState.done) {\n flowLog.info(\"flow complete\", { flowId: flow.id, flowName: flow.name });\n } else if (finalState.status === \"failed\") {\n flowLog.error(\"flow failed\", undefined, { flowId: flow.id, flowName: flow.name });\n } else {\n flowLog.warn(\"flow paused after one turn\", {\n flowId: flow.id,\n status: finalState.status,\n note: \"CLI mode does not interact with approval/input gates\",\n });\n }\n } finally {\n driver.kill();\n const lastState = flowAdapter.getExecution(flowHandle);\n await saveSession(\n opts.projectDir,\n touchSession({\n ...updatedSession,\n driverSessionId: driver.runtimeSessionId ?? updatedSession.driverSessionId,\n status: lastState.status === \"complete\" ? \"complete\" : \"paused\",\n }),\n ).catch(() => {});\n await flowAdapter.disconnect(flowHandle).catch(() => {});\n await agentSession.dispose();\n telemetry.endTrace(flowTrace, {\n status: flowAdapter.getExecution(flowHandle).status === \"complete\" ? \"ok\" : \"error\",\n });\n await telemetry.flush().catch(() => {});\n }\n } finally {\n disposeLogStore();\n }\n}\n\n/**\n * Resume an existing session from the CLI.\n *\n * With the Phase 2 turn-based model, flow state is NOT persisted to\n * local session files — only the driver session ID is kept. The CLI\n * can resume the agent's conversation thread, but the flow execution\n * itself starts from scratch because the runner has no durable store\n * for per-run state.\n *\n * For a governed, resumable flow run, use a host that persists flow\n * state (e.g. the Skaile platform). CLI resume is retained as a\n * driver-level convenience only: we load the session, restart the\n * flow, and the SDK will reconnect to the prior conversation thread.\n *\n * @docLink packages/factory-assets/flow#resume-flow\n */\nexport async function resumeFlow(opts: ResumeOptions): Promise<void> {\n const runner = await loadRunnerModule();\n const { loadSession, loadSessionById, bootstrapRunnerLogStore } = runner;\n\n const session = opts.sessionId\n ? await loadSessionById(opts.projectDir, opts.sessionId)\n : await loadSession(opts.projectDir);\n\n if (!session) {\n const hint = opts.sessionId\n ? `session ${opts.sessionId}`\n : `current session in ${opts.projectDir}/.skaile`;\n throw new Error(`No session found (${hint}) — run 'start' first`);\n }\n\n const flowPath = resolveFlowPath(session.flowId, opts.projectDir);\n\n // Bootstrap a transient logger for the resume diagnostics. The inner\n // runFlow() call will register its own LogStore for the new run. Keep\n // OnLogBridgeSink wiring so callers passing onLog still see this line.\n const wsConfigEarly = resolveSkWorkspaceConfig(opts.projectDir);\n const { dispose: disposeLogStore } = bootstrapRunnerLogStore({\n sessionId: session.runId,\n projectDir: opts.projectDir,\n yamlBlock: (wsConfigEarly as { logging?: unknown }).logging,\n onLog: opts.onLog,\n });\n const flowLog = createLogger({\n kind: \"flow-connector\",\n subkind: \"run\",\n instance: session.runId,\n });\n flowLog.info(\"resuming session\", {\n runId: session.runId,\n flowId: session.flowId,\n note: \"CLI mode does not persist flow state — flow restarts from scratch; driver thread resumes\",\n });\n\n try {\n await runFlow({\n projectDir: opts.projectDir,\n flowPath,\n agentDir: opts.agentDir ?? session.agentDir,\n driver: session.driver,\n model: session.model,\n provider: session.provider,\n sessionLabel: session.label,\n dryRun: opts.dryRun,\n sessionTimeoutMs: opts.sessionTimeoutMs,\n onEvent: opts.onEvent,\n onLog: opts.onLog,\n });\n } finally {\n disposeLogStore();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function validatePinnedVersions(\n flow: Awaited<ReturnType<typeof loadFlow>>,\n projectDir: string,\n log: (line: string) => void,\n): Promise<void> {\n const pinnedNodes = flow.nodes.filter((n) => n.type === \"skill\" && n.data?.version);\n if (pinnedNodes.length === 0) return;\n\n const skillVersions = new Map<string, string>();\n const aiResourcesDir = findAiResourcesDir(projectDir);\n if (aiResourcesDir) {\n for (const node of pinnedNodes) {\n const skillId = node.data?.skill ?? node.id;\n if (skillVersions.has(skillId)) continue;\n const skillPath = findSkillMd(aiResourcesDir, skillId);\n if (skillPath) {\n const content = fs.readFileSync(skillPath, \"utf-8\");\n const fm = parseSkillFrontmatter(content);\n skillVersions.set(skillId, fm.metadata?.version ?? fm.version ?? \"\");\n }\n }\n }\n\n const versionNodes = pinnedNodes.map((n) => ({\n nodeId: n.id,\n skillId: n.data?.skill ?? n.id,\n requestedVersion: n.data?.version,\n }));\n\n const checks = validateFlowVersions(versionNodes, skillVersions);\n const failures = checks.filter((c) => !c.satisfied);\n if (failures.length > 0) {\n const lines = failures.map(\n (f) => ` ${f.nodeId}: wants ${f.requested}, found ${f.actual || \"(none)\"}`,\n );\n throw new Error(`Skill version mismatch:\\n${lines.join(\"\\n\")}`);\n }\n for (const c of checks.filter((c) => c.satisfied)) {\n log(` Version OK: ${c.skillId} ${c.actual} satisfies ${c.requested}`);\n }\n}\n\nfunction resolveFlowPath(flowId: string, projectDir: string): string {\n const armInstalled = path.join(projectDir, \".skaile\", \"flows\", flowId, `${flowId}.flow.yaml`);\n if (fs.existsSync(armInstalled)) return armInstalled;\n\n const manual = path.join(projectDir, \".skaile\", \"flows\", `${flowId}.flow.yaml`);\n if (fs.existsSync(manual)) return manual;\n\n let dir = projectDir;\n for (let i = 0; i < 6; i++) {\n const aiResources = path.join(dir, \"ai-assets\");\n if (fs.existsSync(aiResources)) {\n for (const domain of fs.readdirSync(aiResources)) {\n const flowsDir = path.join(aiResources, domain, \"flows\");\n const candidate = path.join(flowsDir, `${flowId}.flow.yaml`);\n if (fs.existsSync(candidate)) return candidate;\n const legacy = path.join(flowsDir, `${flowId}.json`);\n if (fs.existsSync(legacy)) return legacy;\n }\n throw new Error(`Flow not found: ${flowId} (searched .skaile/flows/ and ${aiResources})`);\n }\n dir = path.dirname(dir);\n }\n throw new Error(\n `Flow not found: ${flowId} (no .skaile/flows/ entry and could not locate ai-assets from ${projectDir})`,\n );\n}\n\n/** Walk up from projectDir to find ai-assets/ */\nfunction findAiResourcesDir(projectDir: string): string | null {\n let dir = projectDir;\n for (let i = 0; i < 6; i++) {\n const candidate = path.join(dir, \"ai-assets\");\n if (fs.existsSync(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/** Find SKILL.md for a given skill ID by walking ai-assets domains */\nfunction findSkillMd(aiResourcesDir: string, skillId: string): string | null {\n for (const domain of fs.readdirSync(aiResourcesDir, { withFileTypes: true })) {\n if (!domain.isDirectory()) continue;\n const skillsDir = path.join(aiResourcesDir, domain.name, \"skills\");\n if (!fs.existsSync(skillsDir)) continue;\n const found = walkForSkill(skillsDir, skillId);\n if (found) return found;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Turn-wait helper\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal driver surface needed by the bus's `driveTurn` callback. Mirrors\n * the slice the legacy `FlowOrchestrator` consumed (`prompt` + `on` +\n * `removeAllListeners`) so we can keep the wait helper private to this\n * module without pulling in a runtime dep on `@skaile/workspaces/bridge`.\n */\ninterface TurnDriverSurface {\n prompt(message: string): Promise<void>;\n on(event: \"agent-event\", handler: (event: AgentEvent) => void): void;\n removeAllListeners(event: \"agent-event\"): void;\n}\n\n/**\n * Send a prompt to the driver and resolve when the agent emits\n * `agent_end` (or reject on `error`). Identical contract to the legacy\n * `awaitAgentEnd` helper from `flow-orchestrator.ts`. Phase 4 lifts the\n * helper into `run-flow.ts` because the bus now owns turn driving.\n */\nfunction awaitAgentEnd(\n driver: TurnDriverSurface,\n prompt: string,\n onEvent: ((event: AgentEvent) => void) | undefined,\n timeoutMs: number,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n\n const done = (err?: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n driver.removeAllListeners(\"agent-event\");\n if (err) reject(err);\n else resolve();\n };\n\n const timer = setTimeout(\n () => done(new Error(`Flow turn timed out after ${timeoutMs / 1000}s`)),\n timeoutMs,\n );\n\n driver.on(\"agent-event\", (event: AgentEvent) => {\n onEvent?.(event);\n if (event.type === \"agent_end\") done();\n else if (event.type === \"error\") {\n const msg =\n (event as { error?: string; message?: string }).error ??\n (event as { message?: string }).message ??\n \"Agent error\";\n done(new Error(msg));\n }\n });\n\n driver.prompt(prompt).catch(done);\n });\n}\n\nfunction walkForSkill(dir: string, skillId: string): string | null {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const full = path.join(dir, entry.name);\n const skillMd = path.join(full, \"SKILL.md\");\n if (fs.existsSync(skillMd)) {\n if (entry.name === skillId) return skillMd;\n } else {\n const found = walkForSkill(full, skillId);\n if (found) return found;\n }\n }\n return null;\n}\n"]}
@@ -2193,6 +2193,10 @@ function audienceOf(cap) {
2193
2193
  function hasAudience(cap, target) {
2194
2194
  return audienceOf(cap).includes(target);
2195
2195
  }
2196
+ var APP_CAPABILITY_PREFIX = "app.";
2197
+ function capabilityLogInstance(cap) {
2198
+ return cap.origin.kind === "app" ? `${cap.origin.appId}.${cap.name}` : cap.name;
2199
+ }
2196
2200
  var ORIGIN_PROMPT_ORDER = [
2197
2201
  "framework",
2198
2202
  "client",
@@ -2255,9 +2259,14 @@ var CapabilityRegistry = class {
2255
2259
  *
2256
2260
  * Allowed combinations:
2257
2261
  * - source `'agent'`: origins `framework | agent | flow | skill | mcp | connector | mount`
2258
- * - source `'client'`: origin `client` only
2262
+ * never `client`, and never `app` (an in-process registrant must not be
2263
+ * able to impersonate an embedded app)
2264
+ * - source `'client'`: origins `client` or `app`. The platform gateway is the
2265
+ * only client peer; it forwards an embedded app's capabilities after binding
2266
+ * each to the connection it arrived on. The runner cannot verify an `appId`.
2259
2267
  * - source `{ kind: 'app', appId }`: origin `app` only, and the origin's
2260
- * `appId` must match the source `appId`
2268
+ * `appId` must match the source `appId`. For a direct app→runner connection;
2269
+ * unused today.
2261
2270
  *
2262
2271
  * @param cap - capability to register (typically built via {@link defineCapability})
2263
2272
  * @param source - which side is doing the registration
@@ -2369,10 +2378,16 @@ var CapabilityRegistry = class {
2369
2378
  * hibernation by this method — agent-side ones come back via the
2370
2379
  * skill / flow / connector / mount adapters. Snapshot entries from other
2371
2380
  * origins are skipped on hydrate.
2381
+ *
2382
+ * Embedded-app capabilities carry an `app` origin, so the `client`-origin
2383
+ * check already excludes them; the reserved-prefix skip below is a backstop
2384
+ * against a capability that reaches the registry with a relabelled origin.
2372
2385
  */
2373
2386
  hydrate(snapshot) {
2387
+ let hydrated = 0;
2374
2388
  for (const cap of snapshot) {
2375
2389
  if (cap.origin.kind !== "client") continue;
2390
+ if (cap.name.startsWith(APP_CAPABILITY_PREFIX)) continue;
2376
2391
  const stub = {
2377
2392
  ...cap,
2378
2393
  inputZod: HYDRATED_PASSTHROUGH_ZOD,
@@ -2380,8 +2395,9 @@ var CapabilityRegistry = class {
2380
2395
  handler: HYDRATED_REJECT_HANDLER
2381
2396
  };
2382
2397
  this.byName.set(cap.name, stub);
2398
+ hydrated++;
2383
2399
  }
2384
- this.logger.info("capability registry hydrated", { count: snapshot.length });
2400
+ this.logger.info("capability registry hydrated", { count: hydrated, total: snapshot.length });
2385
2401
  }
2386
2402
  /**
2387
2403
  * Invoke a registered capability. Validates the input against the Zod
@@ -2399,7 +2415,7 @@ var CapabilityRegistry = class {
2399
2415
  const log = createLogger({
2400
2416
  kind: "capability",
2401
2417
  subkind: cap.origin.kind,
2402
- instance: cap.name
2418
+ instance: capabilityLogInstance(cap)
2403
2419
  });
2404
2420
  log.info("invoking", { input });
2405
2421
  try {
@@ -2415,7 +2431,7 @@ var CapabilityRegistry = class {
2415
2431
  /** True when `source` is allowed to register the given `origin`. */
2416
2432
  isOriginAllowed(source, origin) {
2417
2433
  if (source === "client") {
2418
- return origin.kind === "client";
2434
+ return origin.kind === "client" || origin.kind === "app";
2419
2435
  }
2420
2436
  if (source === "agent") {
2421
2437
  return origin.kind !== "client" && origin.kind !== "app";
@@ -5908,6 +5924,6 @@ function touchSession(state) {
5908
5924
  return { ...state, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
5909
5925
  }
5910
5926
 
5911
- export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildConnectorTokenMediator, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, builtinCapabilities, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, connectorRefreshKind, createAgentSession, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureGitConfigInclude, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, installPreInitRingSink, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveMixin, runAgentChat, saveSession, setCurrentSession, startAgentServer, touchSession, writeClaudeCodeCredentialsFile };
5912
- //# sourceMappingURL=chunk-BGIC25VK.js.map
5913
- //# sourceMappingURL=chunk-BGIC25VK.js.map
5927
+ export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildConnectorTokenMediator, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, builtinCapabilities, capabilityLogInstance, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, connectorRefreshKind, createAgentSession, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureGitConfigInclude, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, installPreInitRingSink, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveMixin, runAgentChat, saveSession, setCurrentSession, startAgentServer, touchSession, writeClaudeCodeCredentialsFile };
5928
+ //# sourceMappingURL=chunk-CBA2XIBF.js.map
5929
+ //# sourceMappingURL=chunk-CBA2XIBF.js.map