{"version":3,"file":"scripted-workflow.d.ts","sourceRoot":"","sources":["../../../src/workflows/scripted-workflow.ts"],"names":[],"mappings":"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","sourcesContent":["import { Worker } from \"node:worker_threads\";\n\nconst KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\n\nconst WORKER_SOURCE = String.raw`\nconst { parentPort } = require(\"node:worker_threads\");\nconst vm = require(\"node:vm\");\nconst { inspect } = require(\"node:util\");\n\nlet nextCallId = 0;\nconst pending = new Map();\nconst runKeyPattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\n\nfunction stableRunJson(value) {\n  if (Array.isArray(value)) return \"[\" + value.map(stableRunJson).join(\",\") + \"]\";\n  if (value && typeof value === \"object\") return \"{\" + Object.keys(value).sort().map((key) => JSON.stringify(key) + \":\" + stableRunJson(value[key])).join(\",\") + \"}\";\n  return JSON.stringify(value) ?? \"undefined\";\n}\n\nfunction hostCall(method, args) {\n  return new Promise((resolve, reject) => {\n    const callId = ++nextCallId;\n    pending.set(callId, { resolve, reject });\n    parentPort.postMessage({ type: \"call\", callId, method, args });\n  });\n}\n\nfunction formatRef(result) {\n  if (!result || typeof result !== \"object\") throw new Error(\"runs.ref(result) requires a run result object.\");\n  const parts = [\"run \" + (result.key || \"unknown\")];\n  if (result.runId) parts.push(\"id=\" + String(result.runId).slice(0, 8));\n  return \"[\" + parts.join(\"; \") + \"]\";\n}\n\nconst runFingerprints = new Map();\n\nfunction validateRunCall(key, params, label, fingerprints) {\n  if (typeof key !== \"string\" || !runKeyPattern.test(key)) throw new Error(label + \" has an invalid key.\");\n  if (!params || typeof params !== \"object\" || Array.isArray(params)) throw new Error(label + \" requires a params object.\");\n  if (Object.prototype.hasOwnProperty.call(params, \"action\") || Object.prototype.hasOwnProperty.call(params, \"workflowScript\") || Object.prototype.hasOwnProperty.call(params, \"tasks\") || Object.prototype.hasOwnProperty.call(params, \"chain\") || Object.prototype.hasOwnProperty.call(params, \"parallel\") || Object.prototype.hasOwnProperty.call(params, \"concurrency\") || Object.prototype.hasOwnProperty.call(params, \"chainDir\")) {\n    const hint = label === \"runs.run\" ? \"; use runs.all(...) and JavaScript control flow for orchestration.\" : \".\";\n    throw new Error(label + \" accepts one child via { agent, task } and execution controls only\" + hint);\n  }\n  if (params.worktree !== undefined && typeof params.worktree !== \"boolean\") throw new Error(label + \" worktree must be true or false.\");\n  if (params.gate !== undefined && (typeof params.gate !== \"string\" || !params.gate.trim())) throw new Error(label + \" gate must be a non-empty command string.\");\n  if (params.gate !== undefined && params.acceptance !== undefined) throw new Error(label + \" gate cannot be combined with acceptance; use one gate command or acceptance.verify.\");\n  if (params.gate !== undefined && params.resume !== undefined) throw new Error(label + \" gate is not supported with retained resume.\");\n  if (params.resume !== undefined && (typeof params.resume !== \"string\" || !params.resume.trim())) throw new Error(label + \" resume must be a non-empty retained run id.\");\n  if (params.resume !== undefined && params.agent !== undefined) throw new Error(label + \" resume and agent are mutually exclusive.\");\n  if (params.resume !== undefined && (typeof params.task !== \"string\" || !params.task.trim())) throw new Error(label + \" resume requires a non-empty task follow-up.\");\n  assertJsonValue(params, label + \" params\");\n  const fingerprint = stableRunJson(params);\n  const existing = fingerprints.get(key);\n  if (existing !== undefined && existing !== fingerprint) throw new Error(\"Duplicate workflow key '\" + key + \"' used with incompatible launch params.\");\n  fingerprints.set(key, fingerprint);\n}\n\nconst runs = Object.freeze({\n  run(key, params) {\n    validateRunCall(key, params, \"runs.run\", runFingerprints);\n    return hostCall(\"run\", { key, params });\n  },\n  all(items) {\n    if (!Array.isArray(items)) throw new Error(\"runs.all(items) requires an array.\");\n    const fingerprints = new Map(runFingerprints);\n    const calls = [];\n    for (let index = 0; index < items.length; index++) {\n      if (!Object.prototype.hasOwnProperty.call(items, index)) throw new Error(\"runs.all items must not contain sparse entries.\");\n      const item = items[index];\n      if (!item || typeof item !== \"object\" || Array.isArray(item)) throw new Error(\"runs.all item \" + index + \" must be an object.\");\n      const { key, ...params } = item;\n      validateRunCall(key, params, \"runs.all item \" + index, fingerprints);\n      calls.push({ key, params });\n    }\n    for (const { key, params } of calls) runFingerprints.set(key, stableRunJson(params));\n    return Promise.all(calls.map(({ key, params }) => hostCall(\"run\", { key, params, collectFailure: true })));\n  },\n  status(keyOrRunId) { return hostCall(\"status\", { keyOrRunId }); },\n  ref: formatRef,\n  refs(results) {\n    if (!Array.isArray(results)) throw new Error(\"runs.refs(results) requires an array.\");\n    return results.map(formatRef).join(\"\\n\");\n  },\n});\n\nfunction validateStateKey(key) {\n  if (typeof key !== \"string\" || !runKeyPattern.test(key)) throw new Error(\"state key must be 1-128 characters using letters, numbers, '.', '_' or '-', and start with a letter or number.\");\n  return key;\n}\n\nconst state = Object.freeze({\n  get(key) { return hostCall(\"state.get\", { key: validateStateKey(key) }); },\n  set(key, value) {\n    const validKey = validateStateKey(key);\n    assertJsonValue(value, \"state.set('\" + validKey + \"') value\");\n    return hostCall(\"state.set\", { key: validKey, value });\n  },\n});\n\nlet contextObjectPrototype;\n\nconst capturedConsole = Object.freeze(Object.fromEntries(\n  [\"log\", \"info\", \"warn\", \"error\"].map((level) => [level, (...args) => {\n    parentPort.postMessage({ type: \"console\", level, text: args.map((value) => typeof value === \"string\" ? value : inspect(value, { depth: 4, breakLength: 120 })).join(\" \") });\n  }]),\n));\n\nfunction assertJsonValue(value, path = \"emit\", seen = new Set()) {\n  if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return;\n  if (typeof value === \"number\") {\n    if (!Number.isFinite(value)) throw new Error(path + \" must contain only finite JSON numbers.\");\n    return;\n  }\n  if (typeof value !== \"object\") throw new Error(path + \" must be a JSON value; received \" + typeof value + \".\");\n  if (seen.has(value)) throw new Error(path + \" must not contain cycles.\");\n  seen.add(value);\n  if (Array.isArray(value)) {\n    for (let index = 0; index < value.length; index++) {\n      if (!Object.prototype.hasOwnProperty.call(value, index)) throw new Error(path + \" must not contain sparse array entries.\");\n      assertJsonValue(value[index], path + \"[\" + index + \"]\", seen);\n    }\n  } else {\n    const prototype = Object.getPrototypeOf(value);\n    if (prototype !== null && prototype !== Object.prototype && prototype !== contextObjectPrototype) throw new Error(path + \" must contain only plain JSON objects.\");\n    if (Object.getOwnPropertySymbols(value).length > 0) throw new Error(path + \" must not contain symbol keys.\");\n    for (const [key, entry] of Object.entries(value)) assertJsonValue(entry, path + \".\" + key, seen);\n  }\n  seen.delete(value);\n}\n\nparentPort.on(\"message\", async (message) => {\n  if (message.type === \"response\") {\n    const entry = pending.get(message.callId);\n    if (!entry) return;\n    pending.delete(message.callId);\n    if (message.ok) entry.resolve(message.value);\n    else entry.reject(new Error(message.error));\n    return;\n  }\n  if (message.type !== \"start\") return;\n  try {\n    const sandbox = { runs, emit(value) { assertJsonValue(value); parentPort.postMessage({ type: \"emit\", value }); }, console: capturedConsole };\n    if (message.stateEnabled) sandbox.state = state;\n    const context = vm.createContext(sandbox, { codeGeneration: { strings: false, wasm: false } });\n    contextObjectPrototype = vm.runInContext(\"Object.prototype\", context);\n    const compiled = new vm.Script(\"(async () => {\\n\" + message.script + \"\\n})()\", { filename: \"workflow-script.js\" });\n    const value = await compiled.runInContext(context);\n    const persistedValue = value === undefined ? null : value;\n    assertJsonValue(persistedValue, \"return\");\n    parentPort.postMessage({ type: \"complete\", value: persistedValue });\n  } catch (error) {\n    parentPort.postMessage({ type: \"error\", error: error && error.stack ? error.stack : String(error) });\n  }\n});\n`;\n\nexport interface WorkflowScriptChildResult {\n\tkey: string;\n\tok: boolean;\n\trunId?: string;\n\toutput: string;\n\terror?: string;\n\tstructuredOutput?: unknown;\n\tartifactPaths: string[];\n\tresults?: unknown[];\n}\n\nexport interface WorkflowScriptTraceEntry {\n\toperation: \"run\" | \"status\";\n\tkey: string;\n\tstate: \"started\" | \"completed\" | \"failed\" | \"reused\";\n\trunId?: string;\n\tdurationMs?: number;\n\tphase?: string;\n\tlabel?: string;\n\terror?: string;\n}\n\nexport interface WorkflowScriptResult {\n\tvalue: unknown;\n\temits: unknown[];\n\tconsole: Array<{ level: \"log\" | \"info\" | \"warn\" | \"error\"; text: string }>;\n\ttrace: WorkflowScriptTraceEntry[];\n\tchildren: WorkflowScriptChildResult[];\n}\n\nexport class WorkflowScriptError extends Error {\n\treadonly partial: Omit<WorkflowScriptResult, \"value\">;\n\n\tconstructor(message: string, partial: Omit<WorkflowScriptResult, \"value\">) {\n\t\tsuper(message);\n\t\tthis.name = \"WorkflowScriptError\";\n\t\tthis.partial = partial;\n\t}\n}\n\nexport interface RunWorkflowScriptOptions {\n\tscript: string;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tlaunch: (key: string, params: Record<string, unknown>, signal: AbortSignal) => Promise<WorkflowScriptChildResult>;\n\tstatus: (keyOrRunId: string, signal: AbortSignal) => Promise<WorkflowScriptChildResult>;\n\tstate?: {\n\t\tget: (key: string) => unknown | Promise<unknown>;\n\t\tset: (key: string, value: unknown) => void | Promise<void>;\n\t};\n\tonTrace?: (trace: WorkflowScriptTraceEntry[]) => void;\n\tonEmit?: (emits: unknown[]) => void;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isPlainJsonObject(value: unknown): value is Record<string, unknown> {\n\tif (!isRecord(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === null || prototype === Object.prototype;\n}\n\nfunction omitUndefinedWorkflowValues(value: unknown, seen = new Set<object>()): unknown {\n\tif (value === null || typeof value !== \"object\") return value;\n\tif (seen.has(value)) return value;\n\tseen.add(value);\n\tconst normalized = Array.isArray(value)\n\t\t? value.map((entry) => (entry === undefined ? null : omitUndefinedWorkflowValues(entry, seen)))\n\t\t: isPlainJsonObject(value)\n\t\t\t? Object.fromEntries(\n\t\t\t\t\tObject.entries(value).flatMap(([key, entry]) =>\n\t\t\t\t\t\tentry === undefined ? [] : [[key, omitUndefinedWorkflowValues(entry, seen)]],\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t: value;\n\tseen.delete(value);\n\treturn normalized;\n}\n\nexport function assertWorkflowJsonValue(value: unknown, path = \"value\", seen = new Set<object>()): void {\n\tif (value === null || typeof value === \"string\" || typeof value === \"boolean\") return;\n\tif (typeof value === \"number\") {\n\t\tif (!Number.isFinite(value)) throw new Error(`${path} must contain only finite JSON numbers.`);\n\t\treturn;\n\t}\n\tif (typeof value !== \"object\") throw new Error(`${path} must be a JSON value; received ${typeof value}.`);\n\tif (seen.has(value)) throw new Error(`${path} must not contain cycles.`);\n\tseen.add(value);\n\tif (Array.isArray(value)) {\n\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\tif (!Object.hasOwn(value, index)) throw new Error(`${path} must not contain sparse array entries.`);\n\t\t\tassertWorkflowJsonValue(value[index], `${path}[${index}]`, seen);\n\t\t}\n\t} else {\n\t\tconst prototype = Object.getPrototypeOf(value);\n\t\tif (prototype !== null && prototype !== Object.prototype)\n\t\t\tthrow new Error(`${path} must contain only plain JSON objects.`);\n\t\tif (Object.getOwnPropertySymbols(value).length > 0) throw new Error(`${path} must not contain symbol keys.`);\n\t\tfor (const [key, entry] of Object.entries(value)) assertWorkflowJsonValue(entry, `${path}.${key}`, seen);\n\t}\n\tseen.delete(value);\n}\n\nexport function formatWorkflowJsonPreview(value: unknown, maxLength: number): string | undefined {\n\ttry {\n\t\tassertWorkflowJsonValue(value);\n\t\tconst serialized = JSON.stringify(value);\n\t\treturn typeof serialized === \"string\" ? serialized.slice(0, maxLength) : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport interface SimpleWorkflowRunPreview {\n\tagent?: string;\n\ttask?: string;\n}\n\n/** Display-only preview for the exact simple `return runs.run(key, {...})` form. */\nexport function previewSimpleWorkflowRun(script: string | undefined): SimpleWorkflowRunPreview | undefined {\n\tconst body = script?.match(\n\t\t/^\\s*return\\s+(?:await\\s+)?runs\\.run\\s*\\(\\s*(?:\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|`[^`$\\\\]*`)\\s*,\\s*\\{([\\s\\S]*)\\}\\s*\\)\\s*;?\\s*$/,\n\t)?.[1];\n\tif (body === undefined) return undefined;\n\tconst readProperty = (name: \"agent\" | \"task\"): string | undefined => {\n\t\tconst match = body.match(\n\t\t\tnew RegExp(\n\t\t\t\t`(?:^|,)\\\\s*(?:${name}|[\"']${name}[\"'])\\\\s*:\\\\s*(\"(?:\\\\\\\\.|[^\"\\\\\\\\])*\"|'(?:\\\\\\\\.|[^'\\\\\\\\])*'|\\u0060[^\\u0060$\\\\\\\\]*\\u0060)`,\n\t\t\t),\n\t\t);\n\t\tif (!match?.[1]) return undefined;\n\t\tconst literal = match[1];\n\t\tif (literal.startsWith('\"')) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(literal) as string;\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t\tif (literal.slice(1, -1).includes(\"\\\\\")) return undefined;\n\t\treturn literal.slice(1, -1);\n\t};\n\tconst agent = readProperty(\"agent\");\n\tconst task = readProperty(\"task\");\n\treturn { ...(agent !== undefined ? { agent } : {}), ...(task !== undefined ? { task } : {}) };\n}\n\nfunction stableJson(value: unknown): string {\n\tif (Array.isArray(value)) return `[${value.map(stableJson).join(\",\")}]`;\n\tif (isRecord(value))\n\t\treturn `{${Object.keys(value)\n\t\t\t.sort()\n\t\t\t.map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`)\n\t\t\t.join(\",\")}}`;\n\treturn JSON.stringify(value) ?? \"undefined\";\n}\n\nfunction validateKey(value: unknown, owner = \"runs.run\"): string {\n\tif (typeof value !== \"string\" || !KEY_PATTERN.test(value)) {\n\t\tthrow new Error(\n\t\t\t`${owner} key must be 1-128 characters using letters, numbers, '.', '_' or '-', and start with a letter or number.`,\n\t\t);\n\t}\n\treturn value;\n}\n\nfunction workflowStringMetadata(params: Record<string, unknown>): Pick<WorkflowScriptTraceEntry, \"phase\" | \"label\"> {\n\treturn {\n\t\t...(typeof params.phase === \"string\" && params.phase.trim() ? { phase: params.phase.trim() } : {}),\n\t\t...(typeof params.label === \"string\" && params.label.trim() ? { label: params.label.trim() } : {}),\n\t};\n}\n\nexport async function runWorkflowScript(options: RunWorkflowScriptOptions): Promise<WorkflowScriptResult> {\n\tif (!options.script.trim()) throw new Error(\"workflowScript must not be empty.\");\n\tif (options.timeoutMs !== undefined && (!Number.isInteger(options.timeoutMs) || options.timeoutMs < 1))\n\t\tthrow new Error(\"workflow script timeout must be a positive integer.\");\n\n\tconst worker = new Worker(WORKER_SOURCE, { eval: true });\n\tconst emits: unknown[] = [];\n\tconst consoleEntries: WorkflowScriptResult[\"console\"] = [];\n\tconst trace: WorkflowScriptTraceEntry[] = [];\n\tconst children = new Map<string, WorkflowScriptChildResult>();\n\tconst childOrder: string[] = [];\n\tconst launches = new Map<string, { fingerprint: string; promise: Promise<WorkflowScriptChildResult> }>();\n\tconst childController = new AbortController();\n\tlet settled = false;\n\n\tconst partial = (): Omit<WorkflowScriptResult, \"value\"> => ({\n\t\temits,\n\t\tconsole: consoleEntries,\n\t\ttrace,\n\t\tchildren: childOrder.flatMap((key) => {\n\t\t\tconst child = children.get(key);\n\t\t\treturn child ? [child] : [];\n\t\t}),\n\t});\n\tconst traceChanged = () => options.onTrace?.([...trace]);\n\n\treturn await new Promise<WorkflowScriptResult>((resolve, reject) => {\n\t\tconst finish = (outcome: { value: unknown } | { error: Error }) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t\tvoid worker.terminate();\n\t\t\tchildController.abort(\n\t\t\t\t\"error\" in outcome\n\t\t\t\t\t? outcome.error\n\t\t\t\t\t: new Error(\"Workflow script completed; unawaited child launches are aborted.\"),\n\t\t\t);\n\t\t\tif (\"error\" in outcome) reject(new WorkflowScriptError(outcome.error.message, partial()));\n\t\t\telse resolve({ value: outcome.value, ...partial() });\n\t\t};\n\t\tconst onAbort = () => finish({ error: new Error(\"Workflow script aborted.\") });\n\t\tconst timer =\n\t\t\toptions.timeoutMs === undefined\n\t\t\t\t? undefined\n\t\t\t\t: setTimeout(\n\t\t\t\t\t\t() => finish({ error: new Error(`Workflow script timed out after ${options.timeoutMs}ms.`) }),\n\t\t\t\t\t\toptions.timeoutMs,\n\t\t\t\t\t);\n\t\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\tif (options.signal?.aborted) return onAbort();\n\n\t\tworker.on(\"error\", (error) =>\n\t\t\tfinish({\n\t\t\t\terror: new Error(`Workflow worker failed: ${error instanceof Error ? error.message : String(error)}`),\n\t\t\t}),\n\t\t);\n\t\tworker.on(\"exit\", (code) => {\n\t\t\tif (!settled && code !== 0) finish({ error: new Error(`Workflow worker exited with code ${code}.`) });\n\t\t});\n\t\tworker.on(\"message\", (message: Record<string, unknown>) => {\n\t\t\tif (message.type === \"emit\") {\n\t\t\t\ttry {\n\t\t\t\t\tassertWorkflowJsonValue(message.value, \"emit\");\n\t\t\t\t} catch (error) {\n\t\t\t\t\tfinish({\n\t\t\t\t\t\terror: new Error(\n\t\t\t\t\t\t\t`Workflow emit could not be persisted: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\temits.push(message.value);\n\t\t\t\ttry {\n\t\t\t\t\toptions.onEmit?.([...emits]);\n\t\t\t\t} catch (error) {\n\t\t\t\t\temits.pop();\n\t\t\t\t\tfinish({\n\t\t\t\t\t\terror: new Error(\n\t\t\t\t\t\t\t`Workflow emit could not be persisted: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (message.type === \"console\") {\n\t\t\t\tconst level = message.level;\n\t\t\t\tif (\n\t\t\t\t\t(level === \"log\" || level === \"info\" || level === \"warn\" || level === \"error\") &&\n\t\t\t\t\ttypeof message.text === \"string\"\n\t\t\t\t)\n\t\t\t\t\tconsoleEntries.push({ level, text: message.text });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (message.type === \"complete\") {\n\t\t\t\ttry {\n\t\t\t\t\tassertWorkflowJsonValue(message.value, \"return\");\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn finish({\n\t\t\t\t\t\terror: new Error(\n\t\t\t\t\t\t\t`Workflow return could not be persisted: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn finish({ value: message.value });\n\t\t\t}\n\t\t\tif (message.type === \"error\")\n\t\t\t\treturn finish({\n\t\t\t\t\terror: new Error(typeof message.error === \"string\" ? message.error : \"Workflow script failed.\"),\n\t\t\t\t});\n\t\t\tif (\n\t\t\t\tmessage.type !== \"call\" ||\n\t\t\t\ttypeof message.callId !== \"number\" ||\n\t\t\t\ttypeof message.method !== \"string\" ||\n\t\t\t\t!isRecord(message.args)\n\t\t\t)\n\t\t\t\treturn;\n\n\t\t\tconst respond = (promise: Promise<unknown>) => {\n\t\t\t\tvoid promise.then(\n\t\t\t\t\t(value) =>\n\t\t\t\t\t\tworker.postMessage({\n\t\t\t\t\t\t\ttype: \"response\",\n\t\t\t\t\t\t\tcallId: message.callId,\n\t\t\t\t\t\t\tok: true,\n\t\t\t\t\t\t\tvalue: omitUndefinedWorkflowValues(value),\n\t\t\t\t\t\t}),\n\t\t\t\t\t(error: unknown) =>\n\t\t\t\t\t\tworker.postMessage({\n\t\t\t\t\t\t\ttype: \"response\",\n\t\t\t\t\t\t\tcallId: message.callId,\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tif (message.method === \"state.get\" || message.method === \"state.set\") {\n\t\t\t\tif (!options.state)\n\t\t\t\t\treturn respond(Promise.reject(new Error(\"Workflow state is unavailable without a mission.\")));\n\t\t\t\tlet key: string;\n\t\t\t\ttry {\n\t\t\t\t\tkey = validateKey(message.args.key, \"state\");\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn respond(Promise.reject(error));\n\t\t\t\t}\n\t\t\t\tif (message.method === \"state.get\") return respond(Promise.resolve().then(() => options.state!.get(key)));\n\t\t\t\tconst value = message.args.value;\n\t\t\t\ttry {\n\t\t\t\t\tassertWorkflowJsonValue(value, `state.set('${key}') value`);\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn respond(Promise.reject(error));\n\t\t\t\t}\n\t\t\t\treturn respond(Promise.resolve().then(() => options.state!.set(key, value)));\n\t\t\t}\n\n\t\t\tif (message.method === \"status\") {\n\t\t\t\tconst keyOrRunId = message.args.keyOrRunId;\n\t\t\t\tif (typeof keyOrRunId !== \"string\" || !keyOrRunId.trim())\n\t\t\t\t\treturn respond(Promise.reject(new Error(\"runs.status(keyOrRunId) requires a non-empty string.\")));\n\t\t\t\tconst known = children.get(keyOrRunId);\n\t\t\t\tconst target = known?.runId ?? keyOrRunId;\n\t\t\t\ttrace.push({\n\t\t\t\t\toperation: \"status\",\n\t\t\t\t\tkey: keyOrRunId,\n\t\t\t\t\tstate: \"started\",\n\t\t\t\t\t...(known?.runId ? { runId: known.runId } : {}),\n\t\t\t\t});\n\t\t\t\ttraceChanged();\n\t\t\t\trespond(\n\t\t\t\t\toptions.status(target, childController.signal).then((result) => {\n\t\t\t\t\t\ttrace.push({\n\t\t\t\t\t\t\toperation: \"status\",\n\t\t\t\t\t\t\tkey: keyOrRunId,\n\t\t\t\t\t\t\tstate: result.ok ? \"completed\" : \"failed\",\n\t\t\t\t\t\t\t...(result.runId ? { runId: result.runId } : {}),\n\t\t\t\t\t\t\t...(!result.ok ? { error: result.output } : {}),\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttraceChanged();\n\t\t\t\t\t\tif (!result.ok) throw new Error(`Status '${keyOrRunId}' failed: ${result.output}`);\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (message.method !== \"run\")\n\t\t\t\treturn respond(Promise.reject(new Error(`Unknown runs API method '${message.method}'.`)));\n\n\t\t\tlet key: string;\n\t\t\ttry {\n\t\t\t\tkey = validateKey(message.args.key);\n\t\t\t} catch (error) {\n\t\t\t\treturn respond(Promise.reject(error));\n\t\t\t}\n\t\t\tconst params = message.args.params;\n\t\t\tif (!isRecord(params))\n\t\t\t\treturn respond(Promise.reject(new Error(`runs.run('${key}', params) requires a params object.`)));\n\t\t\tif (params.action !== undefined)\n\t\t\t\treturn respond(\n\t\t\t\t\tPromise.reject(\n\t\t\t\t\t\tnew Error(`runs.run('${key}') accepts execution params only; management action is not allowed.`),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\tif (params.workflowScript !== undefined)\n\t\t\t\treturn respond(Promise.reject(new Error(`runs.run('${key}') cannot start a nested workflow script.`)));\n\t\t\tif (\n\t\t\t\tparams.tasks !== undefined ||\n\t\t\t\tparams.chain !== undefined ||\n\t\t\t\tparams.parallel !== undefined ||\n\t\t\t\tparams.concurrency !== undefined ||\n\t\t\t\tparams.chainDir !== undefined\n\t\t\t) {\n\t\t\t\treturn respond(\n\t\t\t\t\tPromise.reject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`runs.run('${key}') accepts one child via { agent, task }; use runs.all(...) and JavaScript control flow for orchestration.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (params.worktree !== undefined && typeof params.worktree !== \"boolean\") {\n\t\t\t\treturn respond(Promise.reject(new Error(`runs.run('${key}') worktree must be true or false.`)));\n\t\t\t}\n\t\t\tif (params.gate !== undefined && (typeof params.gate !== \"string\" || !params.gate.trim())) {\n\t\t\t\treturn respond(Promise.reject(new Error(`runs.run('${key}') gate must be a non-empty command string.`)));\n\t\t\t}\n\t\t\tif (params.gate !== undefined && params.acceptance !== undefined) {\n\t\t\t\treturn respond(\n\t\t\t\t\tPromise.reject(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`runs.run('${key}') gate cannot be combined with acceptance; use one gate command or acceptance.verify.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (params.gate !== undefined && params.resume !== undefined) {\n\t\t\t\treturn respond(Promise.reject(new Error(`runs.run('${key}') gate is not supported with retained resume.`)));\n\t\t\t}\n\t\t\tif (params.resume !== undefined && (typeof params.resume !== \"string\" || !params.resume.trim())) {\n\t\t\t\treturn respond(Promise.reject(new Error(`runs.run('${key}') resume must be a non-empty retained run id.`)));\n\t\t\t}\n\t\t\tif (params.resume !== undefined && params.agent !== undefined) {\n\t\t\t\treturn respond(Promise.reject(new Error(`runs.run('${key}') resume and agent are mutually exclusive.`)));\n\t\t\t}\n\t\t\tif (params.resume !== undefined && (typeof params.task !== \"string\" || !params.task.trim())) {\n\t\t\t\treturn respond(Promise.reject(new Error(`runs.run('${key}') resume requires a non-empty task follow-up.`)));\n\t\t\t}\n\t\t\tconst collectFailure = message.args.collectFailure === true;\n\t\t\tconst deliver = (promise: Promise<WorkflowScriptChildResult>) =>\n\t\t\t\tcollectFailure\n\t\t\t\t\t? promise\n\t\t\t\t\t: promise.then((result) => {\n\t\t\t\t\t\t\tif (!result.ok) throw new Error(`Run '${key}' failed: ${result.error ?? result.output}`);\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t});\n\t\t\tconst fingerprint = stableJson(params);\n\t\t\tconst existing = launches.get(key);\n\t\t\tif (existing) {\n\t\t\t\tif (existing.fingerprint !== fingerprint)\n\t\t\t\t\treturn respond(\n\t\t\t\t\t\tPromise.reject(new Error(`Duplicate workflow key '${key}' used with incompatible launch params.`)),\n\t\t\t\t\t);\n\t\t\t\ttrace.push({ operation: \"run\", key, state: \"reused\", ...workflowStringMetadata(params) });\n\t\t\t\ttraceChanged();\n\t\t\t\treturn respond(deliver(existing.promise));\n\t\t\t}\n\n\t\t\tconst startedAt = Date.now();\n\t\t\tchildOrder.push(key);\n\t\t\ttrace.push({ operation: \"run\", key, state: \"started\", ...workflowStringMetadata(params) });\n\t\t\ttraceChanged();\n\t\t\tconst promise = Promise.resolve()\n\t\t\t\t.then(() => options.launch(key, { ...params, async: params.async ?? false }, childController.signal))\n\t\t\t\t.then(\n\t\t\t\t\t(result) => {\n\t\t\t\t\t\tconst normalized = !result.ok && !result.error ? { ...result, error: result.output } : result;\n\t\t\t\t\t\tchildren.set(key, normalized);\n\t\t\t\t\t\ttrace.push({\n\t\t\t\t\t\t\toperation: \"run\",\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tstate: normalized.ok ? \"completed\" : \"failed\",\n\t\t\t\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t\t\t\t\t...workflowStringMetadata(params),\n\t\t\t\t\t\t\t...(normalized.runId ? { runId: normalized.runId } : {}),\n\t\t\t\t\t\t\t...(!normalized.ok ? { error: normalized.error ?? normalized.output } : {}),\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttraceChanged();\n\t\t\t\t\t\treturn normalized;\n\t\t\t\t\t},\n\t\t\t\t\t(error: unknown) => {\n\t\t\t\t\t\tconst text = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tconst failure: WorkflowScriptChildResult = {\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tok: false,\n\t\t\t\t\t\t\toutput: text,\n\t\t\t\t\t\t\terror: text,\n\t\t\t\t\t\t\tartifactPaths: [],\n\t\t\t\t\t\t};\n\t\t\t\t\t\tchildren.set(key, failure);\n\t\t\t\t\t\ttrace.push({\n\t\t\t\t\t\t\toperation: \"run\",\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tstate: \"failed\",\n\t\t\t\t\t\t\tdurationMs: Date.now() - startedAt,\n\t\t\t\t\t\t\t...workflowStringMetadata(params),\n\t\t\t\t\t\t\terror: text,\n\t\t\t\t\t\t});\n\t\t\t\t\t\ttraceChanged();\n\t\t\t\t\t\treturn failure;\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\tlaunches.set(key, { fingerprint, promise });\n\t\t\trespond(deliver(promise));\n\t\t});\n\n\t\tworker.postMessage({ type: \"start\", script: options.script, stateEnabled: options.state !== undefined });\n\t});\n}\n"]}