@keystrokehq/keystroke 0.1.20 → 0.1.23

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.
Files changed (45) hide show
  1. package/dist/agent.cjs +72 -54
  2. package/dist/agent.cjs.map +1 -1
  3. package/dist/agent.d.cts +2 -2
  4. package/dist/agent.d.mts +2 -2
  5. package/dist/agent.mjs +71 -52
  6. package/dist/agent.mjs.map +1 -1
  7. package/dist/config.d.cts +3 -1
  8. package/dist/config.d.cts.map +1 -1
  9. package/dist/config.d.mts +3 -1
  10. package/dist/config.d.mts.map +1 -1
  11. package/dist/{dist-KpQEao0i.mjs → dist-B1Pjv-cM.mjs} +666 -21
  12. package/dist/dist-B1Pjv-cM.mjs.map +1 -0
  13. package/dist/{dist-BFCT4aiu.cjs → dist-D69ocJ7u.cjs} +728 -23
  14. package/dist/dist-D69ocJ7u.cjs.map +1 -0
  15. package/dist/{index-Dlu1kaci.d.cts → index-BQOZkLWG.d.cts} +10 -34
  16. package/dist/index-BQOZkLWG.d.cts.map +1 -0
  17. package/dist/{index-I9DneAMW.d.mts → index-CGf1NwA4.d.mts} +10 -34
  18. package/dist/index-CGf1NwA4.d.mts.map +1 -0
  19. package/dist/{index-BUYoOHa1.d.mts → index-WHR4qX4x.d.mts} +10 -3
  20. package/dist/index-WHR4qX4x.d.mts.map +1 -0
  21. package/dist/{index-Dzm0OSN4.d.cts → index-wpyFrBvl.d.cts} +10 -3
  22. package/dist/index-wpyFrBvl.d.cts.map +1 -0
  23. package/dist/{token-dA7JRmgB.cjs → token-DZEJHEnH.cjs} +2 -2
  24. package/dist/{token-dA7JRmgB.cjs.map → token-DZEJHEnH.cjs.map} +1 -1
  25. package/dist/{token-shJjdG3B.mjs → token-D_x8iwF8.mjs} +2 -2
  26. package/dist/{token-shJjdG3B.mjs.map → token-D_x8iwF8.mjs.map} +1 -1
  27. package/dist/trigger.cjs +1 -1
  28. package/dist/trigger.d.cts +2 -2
  29. package/dist/trigger.d.mts +2 -2
  30. package/dist/trigger.mjs +1 -1
  31. package/dist/workflow.cjs +3 -1
  32. package/dist/workflow.d.cts +2 -2
  33. package/dist/workflow.d.mts +2 -2
  34. package/dist/workflow.mjs +2 -2
  35. package/package.json +1 -1
  36. package/dist/dist-BFCT4aiu.cjs.map +0 -1
  37. package/dist/dist-BekOBuw8.cjs +0 -665
  38. package/dist/dist-BekOBuw8.cjs.map +0 -1
  39. package/dist/dist-C-1uJk5f.mjs +0 -612
  40. package/dist/dist-C-1uJk5f.mjs.map +0 -1
  41. package/dist/dist-KpQEao0i.mjs.map +0 -1
  42. package/dist/index-BUYoOHa1.d.mts.map +0 -1
  43. package/dist/index-Dlu1kaci.d.cts.map +0 -1
  44. package/dist/index-Dzm0OSN4.d.cts.map +0 -1
  45. package/dist/index-I9DneAMW.d.mts.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"dist-BekOBuw8.cjs","names":["getWorkflowRunHandle","z","withSpan","logSystem","captureConsole","normalizeCredentialList","getActionCredentialRequirements","resolveActionCredentials","runWithMcpCredentialContext","executeAction","AsyncLocalStorage","registerWorkflowRunGetter","getRunSignal"],"sources":["../../workflow/dist/index.mjs"],"sourcesContent":["import { z } from \"zod\";\nimport { executeAction, getActionCredentialRequirements, getRunSignal, getWorkflowRunHandle, normalizeCredentialList, registerWorkflowRunGetter, runWithMcpCredentialContext } from \"@keystrokehq/action\";\nimport { captureConsole, logSystem, withSpan } from \"@keystrokehq/tracing\";\nimport { resolveActionCredentials } from \"@keystrokehq/credentials\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n//#region src/run-canceled-error.ts\nvar RunCanceledError = class extends Error {\n\tconstructor(runId) {\n\t\tsuper(runId ? `Workflow run ${runId} was canceled` : \"Workflow run was canceled\");\n\t\tthis.name = \"RunCanceledError\";\n\t}\n};\nfunction isRunCanceledError(error) {\n\treturn error instanceof RunCanceledError;\n}\n//#endregion\n//#region src/workflow-step-invocation.ts\nfunction executeWorkflowStep(state) {\n\tconst handle = getWorkflowRunHandle();\n\tif (!handle?.workflowRunner) throw new Error(`Workflow \"${state.workflow.slug}\" can only be called as a step inside a running workflow. Run it standalone with executeWorkflow(...).`);\n\treturn handle.workflowRunner(state.workflow, state.input, { id: state.id });\n}\nfunction createWorkflowStepInvocation(state) {\n\treturn {\n\t\tstepId(id) {\n\t\t\treturn createWorkflowStepInvocation({\n\t\t\t\t...state,\n\t\t\t\tid\n\t\t\t});\n\t\t},\n\t\tthen(onfulfilled, onrejected) {\n\t\t\treturn executeWorkflowStep(state).then(onfulfilled, onrejected);\n\t\t}\n\t};\n}\n//#endregion\n//#region src/workflow-definition.ts\nconst zodSchema = z.custom((v) => v instanceof z.ZodType, \"must be a Zod schema\");\n/** Runtime validation for an unbranded workflow definition. */\nconst workflowCoreSchema = z.object({\n\tslug: z.string().trim().min(1),\n\tname: z.string().optional(),\n\tdescription: z.string().optional(),\n\tsubscription: z.object({ mode: z.enum([\"system\", \"subscribable\"]).optional() }).optional(),\n\tinput: zodSchema,\n\toutput: zodSchema,\n\trun: z.function()\n});\nconst WORKFLOW = Symbol.for(\"keystroke.workflow\");\n/**\n* Validates brand + shape via `workflowCoreSchema` so discovery and guards\n* reject malformed definitions.\n*/\nfunction isWorkflow(value) {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tif (!(WORKFLOW in value) || value[WORKFLOW] !== true) return false;\n\treturn workflowCoreSchema.safeParse(value).success;\n}\n//#endregion\n//#region src/define-workflow.ts\nfunction defineWorkflow(def) {\n\tconst result = workflowCoreSchema.safeParse(def);\n\tif (!result.success) throw new Error(`Invalid workflow definition: ${formatIssues(result.error.issues)}`);\n\tconst body = def.run;\n\tconst workflow = {\n\t\t...result.data,\n\t\t[WORKFLOW]: true\n\t};\n\tworkflow.run = ((input, ctx) => {\n\t\tif (ctx !== void 0) return body(input, ctx);\n\t\treturn createWorkflowStepInvocation({\n\t\t\tworkflow,\n\t\t\tinput\n\t\t});\n\t});\n\treturn workflow;\n}\nfunction formatIssues(issues) {\n\treturn issues.map((issue) => {\n\t\treturn `${issue.path.length > 0 ? `${issue.path.join(\".\")}: ` : \"\"}${issue.message}`;\n\t}).join(\"; \");\n}\n//#endregion\n//#region src/replay/error.ts\nfunction serializeWorkflowError(error) {\n\tif (error instanceof Error) return {\n\t\tname: error.name,\n\t\tmessage: error.message\n\t};\n\treturn { message: String(error) };\n}\n/** Rebuild an Error from a recorded error so replay re-raises the same failure. */\nfunction deserializeWorkflowError(data) {\n\tconst serialized = data;\n\tconst error = new Error(serialized?.message ?? \"Workflow step failed\");\n\tif (serialized?.name) error.name = serialized.name;\n\treturn error;\n}\n//#endregion\n//#region src/replay/duration.ts\nconst UNIT_MS = {\n\tms: 1,\n\ts: 1e3,\n\tm: 6e4,\n\th: 36e5,\n\td: 864e5\n};\n/** Resolve a sleep duration to an absolute resume time. */\nfunction resolveResumeAt(duration, now = /* @__PURE__ */ new Date()) {\n\tif (duration instanceof Date) return duration;\n\tif (typeof duration === \"number\") return new Date(now.getTime() + Math.max(0, duration));\n\treturn new Date(now.getTime() + parseDurationToMs(duration));\n}\nfunction parseDurationToMs(value) {\n\tconst match = /^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h|d)$/.exec(value.trim());\n\tif (!match) throw new Error(`Invalid sleep duration \"${value}\". Use a number of ms, a Date, or a string like \"5s\", \"10m\", \"1h\".`);\n\tconst amount = Number(match[1]);\n\tconst unit = match[2];\n\treturn Math.round(amount * UNIT_MS[unit]);\n}\n//#endregion\n//#region src/replay/events-consumer.ts\n/** Indexes replay events by correlationId for O(1) cache-hit checks during replay. */\nvar EventsConsumer = class {\n\tbyCorrelationId = /* @__PURE__ */ new Map();\n\tconstructor(events) {\n\t\tfor (const event of events) {\n\t\t\tif (!event.correlationId) continue;\n\t\t\tconst list = this.byCorrelationId.get(event.correlationId);\n\t\t\tif (list) list.push(event);\n\t\t\telse this.byCorrelationId.set(event.correlationId, [event]);\n\t\t}\n\t}\n\tevents(correlationId) {\n\t\treturn this.byCorrelationId.get(correlationId) ?? [];\n\t}\n\thasEventType(correlationId, type) {\n\t\treturn this.events(correlationId).some((event) => event.type === type);\n\t}\n\t/**\n\t* Cache lookup for a step. Returns the recorded output on a `step_completed`,\n\t* re-raises the recorded error on a terminal `step_failed` (so a permanently\n\t* failed step is not re-executed), and otherwise reports a miss — including\n\t* when only `step_retrying` events exist (the step re-runs on the next pass).\n\t*/\n\tgetStepResult(correlationId) {\n\t\tconst events = this.events(correlationId);\n\t\tconst failed = events.find((event) => event.type === \"step_failed\");\n\t\tif (failed) throw deserializeWorkflowError(failed.data);\n\t\tconst completed = events.find((event) => event.type === \"step_completed\");\n\t\tif (completed) return {\n\t\t\tcompleted: true,\n\t\t\tresult: completed.data\n\t\t};\n\t\treturn { completed: false };\n\t}\n\t/** Number of prior `step_retrying` events recorded for a step (= failed attempts so far). */\n\tcountRetrying(correlationId) {\n\t\treturn this.events(correlationId).filter((event) => event.type === \"step_retrying\").length;\n\t}\n\tisSleepCompleted(correlationId) {\n\t\treturn this.hasEventType(correlationId, \"sleep_completed\");\n\t}\n\t/** Returns the persisted resumeAt for a scheduled-but-not-completed sleep, if any. */\n\tgetSleepResumeAt(correlationId) {\n\t\tconst scheduled = this.events(correlationId).find((event) => event.type === \"sleep_scheduled\");\n\t\tif (!scheduled) return;\n\t\tconst data = scheduled.data;\n\t\treturn data?.resumeAt ? new Date(data.resumeAt) : void 0;\n\t}\n\tgetHookToken(correlationId) {\n\t\treturn (this.events(correlationId).find((event) => event.type === \"hook_created\")?.data)?.token;\n\t}\n\tgetHookResult(correlationId) {\n\t\tconst resumed = this.events(correlationId).find((event) => event.type === \"hook_resumed\");\n\t\tif (!resumed) return { resolved: false };\n\t\treturn {\n\t\t\tresolved: true,\n\t\t\tpayload: resumed.data?.payload\n\t\t};\n\t}\n};\n//#endregion\n//#region src/replay/suspension.ts\n/** A promise that never settles — returned by a suspending primitive so the body parks. */\nfunction createPendingPromise() {\n\treturn new Promise(() => {});\n}\n/**\n* Collects pending items requested within a single tick and resolves once, so\n* parallel suspensions (e.g. Promise.all of two sleeps) batch into one suspension.\n*/\nvar SuspensionCoordinator = class {\n\titems = /* @__PURE__ */ new Map();\n\tscheduled = false;\n\tresolve;\n\tpromise;\n\tconstructor() {\n\t\tthis.promise = new Promise((resolve) => {\n\t\t\tthis.resolve = resolve;\n\t\t});\n\t}\n\trequest(item) {\n\t\tthis.items.set(item.correlationId, item);\n\t\tif (!this.scheduled) {\n\t\t\tthis.scheduled = true;\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tthis.resolve([...this.items.values()]);\n\t\t\t});\n\t\t}\n\t}\n\twaitForSuspension() {\n\t\treturn this.promise;\n\t}\n};\n//#endregion\n//#region src/replay/replay-context.ts\nfunction createReplayState(params) {\n\treturn {\n\t\trunId: params.runId,\n\t\tconsumer: params.consumer,\n\t\tcoordinator: params.coordinator,\n\t\teventLog: params.eventLog,\n\t\tnewEvents: [],\n\t\tnow: params.now ?? /* @__PURE__ */ new Date(),\n\t\thookBaseUrl: params.hookBaseUrl,\n\t\tsleepCounter: 0,\n\t\thookCounter: 0,\n\t\tstepOccurrences: /* @__PURE__ */ new Map(),\n\t\tstepCorrelationIds: /* @__PURE__ */ new Set()\n\t};\n}\n/**\n* Allocate the correlation id for a step. An explicit `.stepId(x)` maps to\n* `step:x` (and must be unique within a run); otherwise the key is\n* `step:<actionKey>#<occurrence>` so that two calls to the same action get\n* distinct, replay-stable ids and inserting an unrelated call never shifts the\n* ids of later calls (unlike a single global ordinal).\n*/\nfunction nextStepCorrelationId(state, actionKey, explicitId) {\n\tif (explicitId !== void 0) {\n\t\tconst correlationId = `step:${explicitId}`;\n\t\tif (state.stepCorrelationIds.has(correlationId)) throw new Error(`Duplicate step id \"${explicitId}\" in workflow run ${state.runId}`);\n\t\tstate.stepCorrelationIds.add(correlationId);\n\t\treturn correlationId;\n\t}\n\tconst occurrence = state.stepOccurrences.get(actionKey) ?? 0;\n\tstate.stepOccurrences.set(actionKey, occurrence + 1);\n\tconst correlationId = `step:${actionKey}#${occurrence}`;\n\tstate.stepCorrelationIds.add(correlationId);\n\treturn correlationId;\n}\nfunction createSleep(state) {\n\treturn function sleep(duration) {\n\t\tconst correlationId = `sleep#${state.sleepCounter++}`;\n\t\tif (state.consumer.isSleepCompleted(correlationId)) return Promise.resolve();\n\t\tconst scheduledResumeAt = state.consumer.getSleepResumeAt(correlationId);\n\t\tconst resumeAt = scheduledResumeAt ?? resolveResumeAt(duration, state.now);\n\t\tif (scheduledResumeAt && resumeAt.getTime() <= state.now.getTime()) {\n\t\t\tstate.newEvents.push({\n\t\t\t\tid: `sleep_completed:${state.runId}:${correlationId}`,\n\t\t\t\trunId: state.runId,\n\t\t\t\ttype: \"sleep_completed\",\n\t\t\t\tcorrelationId\n\t\t\t});\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tif (!scheduledResumeAt) state.newEvents.push({\n\t\t\tid: `sleep_scheduled:${state.runId}:${correlationId}`,\n\t\t\trunId: state.runId,\n\t\t\ttype: \"sleep_scheduled\",\n\t\t\tcorrelationId,\n\t\t\tdata: { resumeAt: resumeAt.toISOString() }\n\t\t});\n\t\tstate.coordinator.request({\n\t\t\tkind: \"sleep\",\n\t\t\tcorrelationId,\n\t\t\tresumeAt\n\t\t});\n\t\treturn createPendingPromise();\n\t};\n}\nfunction createHook(state) {\n\treturn function hook(options) {\n\t\tconst correlationId = `hook#${state.hookCounter++}`;\n\t\tconst token = options?.token ?? state.consumer.getHookToken(correlationId) ?? `hook_${crypto.randomUUID()}`;\n\t\tconst resumeUrl = state.hookBaseUrl ? `${state.hookBaseUrl}/hooks/${token}/resume` : `/hooks/${token}/resume`;\n\t\tconst schema = options?.schema ? z.toJSONSchema(options.schema) : void 0;\n\t\treturn {\n\t\t\ttoken,\n\t\t\tresumeUrl,\n\t\t\tthen(onFulfilled, onRejected) {\n\t\t\t\tconst result = state.consumer.getHookResult(correlationId);\n\t\t\t\tif (result.resolved) {\n\t\t\t\t\tconst payload = options?.schema ? options.schema.parse(result.payload) : result.payload;\n\t\t\t\t\treturn Promise.resolve(payload).then(onFulfilled, onRejected);\n\t\t\t\t}\n\t\t\t\tif (!state.consumer.hasEventType(correlationId, \"hook_created\")) state.newEvents.push({\n\t\t\t\t\tid: `hook_created:${state.runId}:${correlationId}`,\n\t\t\t\t\trunId: state.runId,\n\t\t\t\t\ttype: \"hook_created\",\n\t\t\t\t\tcorrelationId,\n\t\t\t\t\tdata: schema ? {\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t\tschema\n\t\t\t\t\t} : { token }\n\t\t\t\t});\n\t\t\t\tstate.coordinator.request({\n\t\t\t\t\tkind: \"hook\",\n\t\t\t\t\tcorrelationId,\n\t\t\t\t\ttoken,\n\t\t\t\t\t...schema ? { schema } : {}\n\t\t\t\t});\n\t\t\t\treturn createPendingPromise().then(onFulfilled, onRejected);\n\t\t\t}\n\t\t};\n\t};\n}\n//#endregion\n//#region src/run-durable-step.ts\n/**\n* Shared durable-step shell: resolve a stable `correlation_id`, short-circuit\n* from the event log on a cache hit, otherwise execute and append\n* `step_completed` immediately (per-step crash durability). A thrown step\n* appends `step_retrying` (non-fatal, re-run on the next attempt) and\n* rethrows; the terminal `step_failed` is written by the job handler once the\n* queue exhausts retries.\n*/\nasync function runDurableStep(state, options) {\n\tconst { runId, consumer, eventLog } = state;\n\tgetRunSignal().throwIfAborted();\n\tconst correlationId = nextStepCorrelationId(state, options.key, options.id);\n\tconst cached = consumer.getStepResult(correlationId);\n\tconst metadata = {\n\t\trunId,\n\t\t[options.metadataKey]: options.key,\n\t\tcorrelationId\n\t};\n\tif (cached.completed) {\n\t\tawait withSpan({\n\t\t\tkind: options.kind,\n\t\t\tname: options.key,\n\t\t\trefId: `${runId}:${correlationId}`,\n\t\t\tmetadata: {\n\t\t\t\t...metadata,\n\t\t\t\treplayed: true\n\t\t\t}\n\t\t}, async () => {\n\t\t\tawait logSystem(\"info\", options.replayMessage, metadata);\n\t\t});\n\t\treturn options.parseCached ? options.parseCached(cached.result) : cached.result;\n\t}\n\treturn withSpan({\n\t\tkind: options.kind,\n\t\tname: options.key,\n\t\trefId: `${runId}:${correlationId}`,\n\t\tmetadata\n\t}, async () => captureConsole(async () => {\n\t\ttry {\n\t\t\tconst result = await options.execute(correlationId);\n\t\t\tawait eventLog.append({\n\t\t\t\tid: `step_completed:${runId}:${correlationId}`,\n\t\t\t\trunId,\n\t\t\t\ttype: \"step_completed\",\n\t\t\t\tcorrelationId,\n\t\t\t\tdata: result\n\t\t\t});\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tconst attempt = consumer.countRetrying(correlationId);\n\t\t\tawait eventLog.append({\n\t\t\t\tid: `step_retrying:${runId}:${correlationId}:${attempt}`,\n\t\t\t\trunId,\n\t\t\t\ttype: \"step_retrying\",\n\t\t\t\tcorrelationId,\n\t\t\t\tdata: serializeWorkflowError(error)\n\t\t\t});\n\t\t\tstate.failedCorrelationId = correlationId;\n\t\t\tthrow error;\n\t\t}\n\t}));\n}\n//#endregion\n//#region src/create-action-runner.ts\nfunction withCredentialScopeOverride(requirements, scope) {\n\tif (!requirements || !scope) return requirements;\n\treturn normalizeCredentialList(requirements).map((requirement) => ({\n\t\t...requirement,\n\t\tscope\n\t}));\n}\n/** Builds the per-run action runner; durability lives in {@link runDurableStep}. */\nfunction createActionRunner(state, options = {}) {\n\treturn (action, input, runOptions) => runDurableStep(state, {\n\t\tkind: \"action\",\n\t\tkey: action.slug,\n\t\tid: runOptions?.id,\n\t\tmetadataKey: \"actionKey\",\n\t\treplayMessage: \"action replayed from checkpoint\",\n\t\tparseCached: (cached) => action.output.parse(cached),\n\t\texecute: async (correlationId) => {\n\t\t\tconst requirements = withCredentialScopeOverride(getActionCredentialRequirements(action), runOptions?.credentialScope);\n\t\t\tconst credentials = requirements?.length ? await resolveActionCredentials(requirements, {\n\t\t\t\tresolveCredentials: options.resolveCredentials,\n\t\t\t\tcontext: options.credentialContext,\n\t\t\t\toauthAdapter: options.oauthAdapter,\n\t\t\t\tconsumer: {\n\t\t\t\t\tkind: \"action\",\n\t\t\t\t\tname: action.slug,\n\t\t\t\t\tid: correlationId\n\t\t\t\t}\n\t\t\t}) : {};\n\t\t\treturn runWithMcpCredentialContext({\n\t\t\t\t...options.mcpCredentialContext,\n\t\t\t\tconsumerId: correlationId\n\t\t\t}, () => executeAction(action, input, credentials));\n\t\t}\n\t});\n}\n//#endregion\n//#region src/create-agent-step-runner.ts\n/**\n* Builds the per-run agent runner: each `agent.prompt()` in a workflow body\n* becomes a durable step keyed `step:<agentKey>#<occurrence>` (same scheme as\n* actions). The actual prompt execution is delegated to `runAgent`, supplied\n* by the host (server) via `executeWorkflow({ runAgent })`.\n*/\nfunction createAgentStepRunner(state, runAgent) {\n\treturn (agent, input, options) => {\n\t\tconst slug = agent.slug;\n\t\treturn runDurableStep(state, {\n\t\t\tkind: \"agent_session\",\n\t\t\tkey: slug,\n\t\t\tid: options?.id,\n\t\t\tmetadataKey: \"agentKey\",\n\t\t\treplayMessage: \"agent step replayed from checkpoint\",\n\t\t\texecute: (_correlationId) => runAgent(agent, input, options?.runPrompt)\n\t\t});\n\t};\n}\n//#endregion\n//#region src/create-llm-step-runner.ts\n/**\n* Builds the per-run LLM runner: each `promptLlm()` in a workflow body becomes a\n* durable step keyed `step:promptLlm#<occurrence>`. The actual LLM call is\n* delegated to `runLlm`, supplied by the host (server) via `executeWorkflow({ runLlm })`.\n*/\nfunction createLlmStepRunner(state, runLlm) {\n\treturn (opts) => runDurableStep(state, {\n\t\tkind: \"llm\",\n\t\tkey: \"promptLlm\",\n\t\tid: opts.stepId,\n\t\tmetadataKey: \"llmKey\",\n\t\treplayMessage: \"llm step replayed from checkpoint\",\n\t\tparseCached: (cached) => opts.outputSchema ? opts.outputSchema.parse(cached) : cached,\n\t\texecute: (_correlationId) => runLlm(opts)\n\t});\n}\n//#endregion\n//#region src/create-workflow-step-runner.ts\n/**\n* Builds the per-run sub-workflow runner: each `workflow.run(input)` inside a\n* workflow body becomes a durable step keyed `step:<slug>#<occurrence>`. The\n* sub-workflow's body runs inline in the same replay state (its action/agent/\n* LLM steps and `ctx.sleep`/`ctx.hook` stay durable), and its validated output\n* is checkpointed so a replay skips the whole sub-workflow once it completes.\n*/\nfunction createWorkflowStepRunner(state, ctx) {\n\treturn (workflowUnknown, input, options) => {\n\t\tconst workflow = workflowUnknown;\n\t\tconst parsedInput = workflow.input.parse(input);\n\t\treturn runDurableStep(state, {\n\t\t\tkind: \"workflow_run\",\n\t\t\tkey: workflow.slug,\n\t\t\tid: options?.id,\n\t\t\tmetadataKey: \"workflowKey\",\n\t\t\treplayMessage: \"workflow step replayed from checkpoint\",\n\t\t\tparseCached: (cached) => workflow.output.parse(cached),\n\t\t\texecute: async () => {\n\t\t\t\tconst output = await workflow.run(parsedInput, ctx);\n\t\t\t\treturn workflow.output.parse(output);\n\t\t\t}\n\t\t});\n\t};\n}\n//#endregion\n//#region src/run-context.ts\nconst storage = new AsyncLocalStorage();\nregisterWorkflowRunGetter(() => {\n\tconst store = storage.getStore();\n\tif (!store) return;\n\treturn {\n\t\tactionRunner: store.actionRunner,\n\t\tagentRunner: store.agentRunner,\n\t\tllmRunner: store.llmRunner,\n\t\tworkflowRunner: store.workflowRunner\n\t};\n});\nfunction runWithWorkflowContext(store, fn) {\n\treturn storage.run(store, fn);\n}\n//#endregion\n//#region src/replay/memory-event-log.ts\n/** In-memory durable log for inline execution and tests. */\nvar MemoryEventLog = class {\n\tevents = [];\n\tids = /* @__PURE__ */ new Set();\n\tasync append(event) {\n\t\tconst id = event.id ?? crypto.randomUUID();\n\t\tif (this.ids.has(id)) return false;\n\t\tthis.ids.add(id);\n\t\tthis.events.push({\n\t\t\tid,\n\t\t\trunId: event.runId,\n\t\t\tseq: this.events.length,\n\t\t\ttype: event.type,\n\t\t\tcorrelationId: event.correlationId ?? null,\n\t\t\tdata: event.data ?? null\n\t\t});\n\t\treturn true;\n\t}\n\tasync listReplay(runId) {\n\t\treturn this.events.filter((event) => event.runId === runId).map((event) => ({ ...event }));\n\t}\n};\n//#endregion\n//#region src/execute-workflow.ts\n/**\n* The single way to run a workflow: replay its event log from the top, execute\n* un-cached primitives, and either complete/fail or suspend at the first\n* un-satisfied sleep/hook. New events (sleep_scheduled/sleep_completed/\n* hook_created/run_completed/run_failed) are flushed before returning.\n*\n* Durability comes entirely from the log — a suspended run resumes by calling\n* this again with the same `runId` and event log once the sleep is due or the\n* hook is resumed.\n*/\nasync function executeWorkflow(workflow, input, options = {}) {\n\tconst runId = options.runId ?? crypto.randomUUID();\n\tconst eventLog = options.eventLog ?? new MemoryEventLog();\n\tconst signal = getRunSignal();\n\tconst consumer = new EventsConsumer(await eventLog.listReplay(runId));\n\tconst coordinator = new SuspensionCoordinator();\n\tconst state = createReplayState({\n\t\trunId,\n\t\tconsumer,\n\t\tcoordinator,\n\t\teventLog,\n\t\thookBaseUrl: options.hookBaseUrl,\n\t\tnow: options.now\n\t});\n\tconst actionRunner = createActionRunner(state, {\n\t\tresolveCredentials: options.resolveCredentials,\n\t\tcredentialContext: options.credentialContext,\n\t\toauthAdapter: options.oauthAdapter,\n\t\tmcpCredentialContext: { assignmentTarget: {\n\t\t\ttype: \"workflow\",\n\t\t\tkey: workflow.slug\n\t\t} }\n\t});\n\tconst ctx = {\n\t\trunId,\n\t\tsleep: createSleep(state),\n\t\thook: createHook(state),\n\t\t...options.context\n\t};\n\tconst agentRunner = options.runAgent ? createAgentStepRunner(state, options.runAgent) : void 0;\n\tconst llmRunner = options.runLlm ? createLlmStepRunner(state, options.runLlm) : void 0;\n\tconst workflowRunner = createWorkflowStepRunner(state, ctx);\n\tconst validatedInput = workflow.input.parse(input);\n\tconst bodyPromise = runWithWorkflowContext({\n\t\tactionRunner,\n\t\tagentRunner,\n\t\tllmRunner,\n\t\tworkflowRunner,\n\t\trunId\n\t}, () => captureConsole(async () => workflow.run(validatedInput, ctx)));\n\tlet onAbort;\n\tconst waitForAbort = signal.aborted ? Promise.resolve({ type: \"canceled\" }) : new Promise((resolve) => {\n\t\tonAbort = () => resolve({ type: \"canceled\" });\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n\tconst outcome = await Promise.race([\n\t\tbodyPromise.then((output) => ({\n\t\t\ttype: \"done\",\n\t\t\toutput\n\t\t}), (error) => ({\n\t\t\ttype: \"error\",\n\t\t\terror\n\t\t})),\n\t\tcoordinator.waitForSuspension().then((items) => ({\n\t\t\ttype: \"suspended\",\n\t\t\titems\n\t\t})),\n\t\twaitForAbort\n\t]);\n\tif (onAbort) signal.removeEventListener(\"abort\", onAbort);\n\tlet result;\n\tif (outcome.type === \"suspended\") {\n\t\tbodyPromise.catch(() => {});\n\t\tresult = {\n\t\t\tstatus: \"suspended\",\n\t\t\titems: outcome.items\n\t\t};\n\t} else if (outcome.type === \"done\") {\n\t\tconst output = workflow.output.parse(outcome.output);\n\t\tstate.newEvents.push({\n\t\t\tid: `run_completed:${runId}`,\n\t\t\trunId,\n\t\t\ttype: \"run_completed\",\n\t\t\tdata: { output }\n\t\t});\n\t\tresult = {\n\t\t\tstatus: \"completed\",\n\t\t\toutput\n\t\t};\n\t} else if (outcome.type === \"canceled\" || isRunCanceledError(outcome.error)) {\n\t\tbodyPromise.catch(() => {});\n\t\tstate.newEvents.push({\n\t\t\tid: `run_canceled:${runId}`,\n\t\t\trunId,\n\t\t\ttype: \"run_canceled\"\n\t\t});\n\t\tresult = { status: \"canceled\" };\n\t} else result = {\n\t\tstatus: \"failed\",\n\t\terror: outcome.error,\n\t\tfailedCorrelationId: state.failedCorrelationId\n\t};\n\tfor (const event of state.newEvents) await eventLog.append(event);\n\treturn result;\n}\n//#endregion\n//#region src/prompt-llm.ts\nfunction promptLlm(prompt, opts) {\n\tconst handle = getWorkflowRunHandle();\n\tif (!handle?.llmRunner) throw new Error(\"promptLlm must run inside a workflow with an injected llm executor (executeWorkflow({ runLlm })).\");\n\treturn handle.llmRunner({\n\t\tprompt,\n\t\t...opts\n\t});\n}\n//#endregion\nexport { MemoryEventLog, RunCanceledError, defineWorkflow, deserializeWorkflowError, executeWorkflow, isRunCanceledError, isWorkflow, promptLlm, serializeWorkflowError };\n\n//# sourceMappingURL=index.mjs.map"],"mappings":"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"}
@@ -1,612 +0,0 @@
1
- import { _ as normalizeCredentialList } from "./dist-_i6Rguqn.mjs";
2
- import { _ as runWithMcpCredentialContext, a as getActionCredentialRequirements, c as getRunSignal, i as executeAction, l as getWorkflowRunHandle, m as registerWorkflowRunGetter } from "./dist-CAZlfg_P.mjs";
3
- import { B as withSpan, L as captureConsole, o as resolveActionCredentials, z as logSystem } from "./dist-KpQEao0i.mjs";
4
- import { z } from "zod";
5
- import { AsyncLocalStorage } from "node:async_hooks";
6
- //#region ../workflow/dist/index.mjs
7
- var RunCanceledError = class extends Error {
8
- constructor(runId) {
9
- super(runId ? `Workflow run ${runId} was canceled` : "Workflow run was canceled");
10
- this.name = "RunCanceledError";
11
- }
12
- };
13
- function isRunCanceledError(error) {
14
- return error instanceof RunCanceledError;
15
- }
16
- function executeWorkflowStep(state) {
17
- const handle = getWorkflowRunHandle();
18
- if (!handle?.workflowRunner) throw new Error(`Workflow "${state.workflow.slug}" can only be called as a step inside a running workflow. Run it standalone with executeWorkflow(...).`);
19
- return handle.workflowRunner(state.workflow, state.input, { id: state.id });
20
- }
21
- function createWorkflowStepInvocation(state) {
22
- return {
23
- stepId(id) {
24
- return createWorkflowStepInvocation({
25
- ...state,
26
- id
27
- });
28
- },
29
- then(onfulfilled, onrejected) {
30
- return executeWorkflowStep(state).then(onfulfilled, onrejected);
31
- }
32
- };
33
- }
34
- const zodSchema = z.custom((v) => v instanceof z.ZodType, "must be a Zod schema");
35
- /** Runtime validation for an unbranded workflow definition. */
36
- const workflowCoreSchema = z.object({
37
- slug: z.string().trim().min(1),
38
- name: z.string().optional(),
39
- description: z.string().optional(),
40
- subscription: z.object({ mode: z.enum(["system", "subscribable"]).optional() }).optional(),
41
- input: zodSchema,
42
- output: zodSchema,
43
- run: z.function()
44
- });
45
- const WORKFLOW = Symbol.for("keystroke.workflow");
46
- /**
47
- * Validates brand + shape via `workflowCoreSchema` so discovery and guards
48
- * reject malformed definitions.
49
- */
50
- function isWorkflow(value) {
51
- if (typeof value !== "object" || value === null) return false;
52
- if (!(WORKFLOW in value) || value[WORKFLOW] !== true) return false;
53
- return workflowCoreSchema.safeParse(value).success;
54
- }
55
- function defineWorkflow(def) {
56
- const result = workflowCoreSchema.safeParse(def);
57
- if (!result.success) throw new Error(`Invalid workflow definition: ${formatIssues(result.error.issues)}`);
58
- const body = def.run;
59
- const workflow = {
60
- ...result.data,
61
- [WORKFLOW]: true
62
- };
63
- workflow.run = ((input, ctx) => {
64
- if (ctx !== void 0) return body(input, ctx);
65
- return createWorkflowStepInvocation({
66
- workflow,
67
- input
68
- });
69
- });
70
- return workflow;
71
- }
72
- function formatIssues(issues) {
73
- return issues.map((issue) => {
74
- return `${issue.path.length > 0 ? `${issue.path.join(".")}: ` : ""}${issue.message}`;
75
- }).join("; ");
76
- }
77
- function serializeWorkflowError(error) {
78
- if (error instanceof Error) return {
79
- name: error.name,
80
- message: error.message
81
- };
82
- return { message: String(error) };
83
- }
84
- /** Rebuild an Error from a recorded error so replay re-raises the same failure. */
85
- function deserializeWorkflowError(data) {
86
- const serialized = data;
87
- const error = new Error(serialized?.message ?? "Workflow step failed");
88
- if (serialized?.name) error.name = serialized.name;
89
- return error;
90
- }
91
- const UNIT_MS = {
92
- ms: 1,
93
- s: 1e3,
94
- m: 6e4,
95
- h: 36e5,
96
- d: 864e5
97
- };
98
- /** Resolve a sleep duration to an absolute resume time. */
99
- function resolveResumeAt(duration, now = /* @__PURE__ */ new Date()) {
100
- if (duration instanceof Date) return duration;
101
- if (typeof duration === "number") return new Date(now.getTime() + Math.max(0, duration));
102
- return new Date(now.getTime() + parseDurationToMs(duration));
103
- }
104
- function parseDurationToMs(value) {
105
- const match = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)$/.exec(value.trim());
106
- if (!match) throw new Error(`Invalid sleep duration "${value}". Use a number of ms, a Date, or a string like "5s", "10m", "1h".`);
107
- const amount = Number(match[1]);
108
- const unit = match[2];
109
- return Math.round(amount * UNIT_MS[unit]);
110
- }
111
- /** Indexes replay events by correlationId for O(1) cache-hit checks during replay. */
112
- var EventsConsumer = class {
113
- byCorrelationId = /* @__PURE__ */ new Map();
114
- constructor(events) {
115
- for (const event of events) {
116
- if (!event.correlationId) continue;
117
- const list = this.byCorrelationId.get(event.correlationId);
118
- if (list) list.push(event);
119
- else this.byCorrelationId.set(event.correlationId, [event]);
120
- }
121
- }
122
- events(correlationId) {
123
- return this.byCorrelationId.get(correlationId) ?? [];
124
- }
125
- hasEventType(correlationId, type) {
126
- return this.events(correlationId).some((event) => event.type === type);
127
- }
128
- /**
129
- * Cache lookup for a step. Returns the recorded output on a `step_completed`,
130
- * re-raises the recorded error on a terminal `step_failed` (so a permanently
131
- * failed step is not re-executed), and otherwise reports a miss — including
132
- * when only `step_retrying` events exist (the step re-runs on the next pass).
133
- */
134
- getStepResult(correlationId) {
135
- const events = this.events(correlationId);
136
- const failed = events.find((event) => event.type === "step_failed");
137
- if (failed) throw deserializeWorkflowError(failed.data);
138
- const completed = events.find((event) => event.type === "step_completed");
139
- if (completed) return {
140
- completed: true,
141
- result: completed.data
142
- };
143
- return { completed: false };
144
- }
145
- /** Number of prior `step_retrying` events recorded for a step (= failed attempts so far). */
146
- countRetrying(correlationId) {
147
- return this.events(correlationId).filter((event) => event.type === "step_retrying").length;
148
- }
149
- isSleepCompleted(correlationId) {
150
- return this.hasEventType(correlationId, "sleep_completed");
151
- }
152
- /** Returns the persisted resumeAt for a scheduled-but-not-completed sleep, if any. */
153
- getSleepResumeAt(correlationId) {
154
- const scheduled = this.events(correlationId).find((event) => event.type === "sleep_scheduled");
155
- if (!scheduled) return;
156
- const data = scheduled.data;
157
- return data?.resumeAt ? new Date(data.resumeAt) : void 0;
158
- }
159
- getHookToken(correlationId) {
160
- return (this.events(correlationId).find((event) => event.type === "hook_created")?.data)?.token;
161
- }
162
- getHookResult(correlationId) {
163
- const resumed = this.events(correlationId).find((event) => event.type === "hook_resumed");
164
- if (!resumed) return { resolved: false };
165
- return {
166
- resolved: true,
167
- payload: resumed.data?.payload
168
- };
169
- }
170
- };
171
- /** A promise that never settles — returned by a suspending primitive so the body parks. */
172
- function createPendingPromise() {
173
- return new Promise(() => {});
174
- }
175
- /**
176
- * Collects pending items requested within a single tick and resolves once, so
177
- * parallel suspensions (e.g. Promise.all of two sleeps) batch into one suspension.
178
- */
179
- var SuspensionCoordinator = class {
180
- items = /* @__PURE__ */ new Map();
181
- scheduled = false;
182
- resolve;
183
- promise;
184
- constructor() {
185
- this.promise = new Promise((resolve) => {
186
- this.resolve = resolve;
187
- });
188
- }
189
- request(item) {
190
- this.items.set(item.correlationId, item);
191
- if (!this.scheduled) {
192
- this.scheduled = true;
193
- queueMicrotask(() => {
194
- this.resolve([...this.items.values()]);
195
- });
196
- }
197
- }
198
- waitForSuspension() {
199
- return this.promise;
200
- }
201
- };
202
- function createReplayState(params) {
203
- return {
204
- runId: params.runId,
205
- consumer: params.consumer,
206
- coordinator: params.coordinator,
207
- eventLog: params.eventLog,
208
- newEvents: [],
209
- now: params.now ?? /* @__PURE__ */ new Date(),
210
- hookBaseUrl: params.hookBaseUrl,
211
- sleepCounter: 0,
212
- hookCounter: 0,
213
- stepOccurrences: /* @__PURE__ */ new Map(),
214
- stepCorrelationIds: /* @__PURE__ */ new Set()
215
- };
216
- }
217
- /**
218
- * Allocate the correlation id for a step. An explicit `.stepId(x)` maps to
219
- * `step:x` (and must be unique within a run); otherwise the key is
220
- * `step:<actionKey>#<occurrence>` so that two calls to the same action get
221
- * distinct, replay-stable ids and inserting an unrelated call never shifts the
222
- * ids of later calls (unlike a single global ordinal).
223
- */
224
- function nextStepCorrelationId(state, actionKey, explicitId) {
225
- if (explicitId !== void 0) {
226
- const correlationId = `step:${explicitId}`;
227
- if (state.stepCorrelationIds.has(correlationId)) throw new Error(`Duplicate step id "${explicitId}" in workflow run ${state.runId}`);
228
- state.stepCorrelationIds.add(correlationId);
229
- return correlationId;
230
- }
231
- const occurrence = state.stepOccurrences.get(actionKey) ?? 0;
232
- state.stepOccurrences.set(actionKey, occurrence + 1);
233
- const correlationId = `step:${actionKey}#${occurrence}`;
234
- state.stepCorrelationIds.add(correlationId);
235
- return correlationId;
236
- }
237
- function createSleep(state) {
238
- return function sleep(duration) {
239
- const correlationId = `sleep#${state.sleepCounter++}`;
240
- if (state.consumer.isSleepCompleted(correlationId)) return Promise.resolve();
241
- const scheduledResumeAt = state.consumer.getSleepResumeAt(correlationId);
242
- const resumeAt = scheduledResumeAt ?? resolveResumeAt(duration, state.now);
243
- if (scheduledResumeAt && resumeAt.getTime() <= state.now.getTime()) {
244
- state.newEvents.push({
245
- id: `sleep_completed:${state.runId}:${correlationId}`,
246
- runId: state.runId,
247
- type: "sleep_completed",
248
- correlationId
249
- });
250
- return Promise.resolve();
251
- }
252
- if (!scheduledResumeAt) state.newEvents.push({
253
- id: `sleep_scheduled:${state.runId}:${correlationId}`,
254
- runId: state.runId,
255
- type: "sleep_scheduled",
256
- correlationId,
257
- data: { resumeAt: resumeAt.toISOString() }
258
- });
259
- state.coordinator.request({
260
- kind: "sleep",
261
- correlationId,
262
- resumeAt
263
- });
264
- return createPendingPromise();
265
- };
266
- }
267
- function createHook(state) {
268
- return function hook(options) {
269
- const correlationId = `hook#${state.hookCounter++}`;
270
- const token = options?.token ?? state.consumer.getHookToken(correlationId) ?? `hook_${crypto.randomUUID()}`;
271
- const resumeUrl = state.hookBaseUrl ? `${state.hookBaseUrl}/hooks/${token}/resume` : `/hooks/${token}/resume`;
272
- const schema = options?.schema ? z.toJSONSchema(options.schema) : void 0;
273
- return {
274
- token,
275
- resumeUrl,
276
- then(onFulfilled, onRejected) {
277
- const result = state.consumer.getHookResult(correlationId);
278
- if (result.resolved) {
279
- const payload = options?.schema ? options.schema.parse(result.payload) : result.payload;
280
- return Promise.resolve(payload).then(onFulfilled, onRejected);
281
- }
282
- if (!state.consumer.hasEventType(correlationId, "hook_created")) state.newEvents.push({
283
- id: `hook_created:${state.runId}:${correlationId}`,
284
- runId: state.runId,
285
- type: "hook_created",
286
- correlationId,
287
- data: schema ? {
288
- token,
289
- schema
290
- } : { token }
291
- });
292
- state.coordinator.request({
293
- kind: "hook",
294
- correlationId,
295
- token,
296
- ...schema ? { schema } : {}
297
- });
298
- return createPendingPromise().then(onFulfilled, onRejected);
299
- }
300
- };
301
- };
302
- }
303
- /**
304
- * Shared durable-step shell: resolve a stable `correlation_id`, short-circuit
305
- * from the event log on a cache hit, otherwise execute and append
306
- * `step_completed` immediately (per-step crash durability). A thrown step
307
- * appends `step_retrying` (non-fatal, re-run on the next attempt) and
308
- * rethrows; the terminal `step_failed` is written by the job handler once the
309
- * queue exhausts retries.
310
- */
311
- async function runDurableStep(state, options) {
312
- const { runId, consumer, eventLog } = state;
313
- getRunSignal().throwIfAborted();
314
- const correlationId = nextStepCorrelationId(state, options.key, options.id);
315
- const cached = consumer.getStepResult(correlationId);
316
- const metadata = {
317
- runId,
318
- [options.metadataKey]: options.key,
319
- correlationId
320
- };
321
- if (cached.completed) {
322
- await withSpan({
323
- kind: options.kind,
324
- name: options.key,
325
- refId: `${runId}:${correlationId}`,
326
- metadata: {
327
- ...metadata,
328
- replayed: true
329
- }
330
- }, async () => {
331
- await logSystem("info", options.replayMessage, metadata);
332
- });
333
- return options.parseCached ? options.parseCached(cached.result) : cached.result;
334
- }
335
- return withSpan({
336
- kind: options.kind,
337
- name: options.key,
338
- refId: `${runId}:${correlationId}`,
339
- metadata
340
- }, async () => captureConsole(async () => {
341
- try {
342
- const result = await options.execute(correlationId);
343
- await eventLog.append({
344
- id: `step_completed:${runId}:${correlationId}`,
345
- runId,
346
- type: "step_completed",
347
- correlationId,
348
- data: result
349
- });
350
- return result;
351
- } catch (error) {
352
- const attempt = consumer.countRetrying(correlationId);
353
- await eventLog.append({
354
- id: `step_retrying:${runId}:${correlationId}:${attempt}`,
355
- runId,
356
- type: "step_retrying",
357
- correlationId,
358
- data: serializeWorkflowError(error)
359
- });
360
- state.failedCorrelationId = correlationId;
361
- throw error;
362
- }
363
- }));
364
- }
365
- function withCredentialScopeOverride(requirements, scope) {
366
- if (!requirements || !scope) return requirements;
367
- return normalizeCredentialList(requirements).map((requirement) => ({
368
- ...requirement,
369
- scope
370
- }));
371
- }
372
- /** Builds the per-run action runner; durability lives in {@link runDurableStep}. */
373
- function createActionRunner(state, options = {}) {
374
- return (action, input, runOptions) => runDurableStep(state, {
375
- kind: "action",
376
- key: action.slug,
377
- id: runOptions?.id,
378
- metadataKey: "actionKey",
379
- replayMessage: "action replayed from checkpoint",
380
- parseCached: (cached) => action.output.parse(cached),
381
- execute: async (correlationId) => {
382
- const requirements = withCredentialScopeOverride(getActionCredentialRequirements(action), runOptions?.credentialScope);
383
- const credentials = requirements?.length ? await resolveActionCredentials(requirements, {
384
- resolveCredentials: options.resolveCredentials,
385
- context: options.credentialContext,
386
- oauthAdapter: options.oauthAdapter,
387
- consumer: {
388
- kind: "action",
389
- name: action.slug,
390
- id: correlationId
391
- }
392
- }) : {};
393
- return runWithMcpCredentialContext({
394
- ...options.mcpCredentialContext,
395
- consumerId: correlationId
396
- }, () => executeAction(action, input, credentials));
397
- }
398
- });
399
- }
400
- /**
401
- * Builds the per-run agent runner: each `agent.prompt()` in a workflow body
402
- * becomes a durable step keyed `step:<agentKey>#<occurrence>` (same scheme as
403
- * actions). The actual prompt execution is delegated to `runAgent`, supplied
404
- * by the host (server) via `executeWorkflow({ runAgent })`.
405
- */
406
- function createAgentStepRunner(state, runAgent) {
407
- return (agent, input, options) => {
408
- const slug = agent.slug;
409
- return runDurableStep(state, {
410
- kind: "agent_session",
411
- key: slug,
412
- id: options?.id,
413
- metadataKey: "agentKey",
414
- replayMessage: "agent step replayed from checkpoint",
415
- execute: (_correlationId) => runAgent(agent, input, options?.runPrompt)
416
- });
417
- };
418
- }
419
- /**
420
- * Builds the per-run LLM runner: each `promptLlm()` in a workflow body becomes a
421
- * durable step keyed `step:promptLlm#<occurrence>`. The actual LLM call is
422
- * delegated to `runLlm`, supplied by the host (server) via `executeWorkflow({ runLlm })`.
423
- */
424
- function createLlmStepRunner(state, runLlm) {
425
- return (opts) => runDurableStep(state, {
426
- kind: "llm",
427
- key: "promptLlm",
428
- id: opts.stepId,
429
- metadataKey: "llmKey",
430
- replayMessage: "llm step replayed from checkpoint",
431
- parseCached: (cached) => opts.outputSchema ? opts.outputSchema.parse(cached) : cached,
432
- execute: (_correlationId) => runLlm(opts)
433
- });
434
- }
435
- /**
436
- * Builds the per-run sub-workflow runner: each `workflow.run(input)` inside a
437
- * workflow body becomes a durable step keyed `step:<slug>#<occurrence>`. The
438
- * sub-workflow's body runs inline in the same replay state (its action/agent/
439
- * LLM steps and `ctx.sleep`/`ctx.hook` stay durable), and its validated output
440
- * is checkpointed so a replay skips the whole sub-workflow once it completes.
441
- */
442
- function createWorkflowStepRunner(state, ctx) {
443
- return (workflowUnknown, input, options) => {
444
- const workflow = workflowUnknown;
445
- const parsedInput = workflow.input.parse(input);
446
- return runDurableStep(state, {
447
- kind: "workflow_run",
448
- key: workflow.slug,
449
- id: options?.id,
450
- metadataKey: "workflowKey",
451
- replayMessage: "workflow step replayed from checkpoint",
452
- parseCached: (cached) => workflow.output.parse(cached),
453
- execute: async () => {
454
- const output = await workflow.run(parsedInput, ctx);
455
- return workflow.output.parse(output);
456
- }
457
- });
458
- };
459
- }
460
- const storage = new AsyncLocalStorage();
461
- registerWorkflowRunGetter(() => {
462
- const store = storage.getStore();
463
- if (!store) return;
464
- return {
465
- actionRunner: store.actionRunner,
466
- agentRunner: store.agentRunner,
467
- llmRunner: store.llmRunner,
468
- workflowRunner: store.workflowRunner
469
- };
470
- });
471
- function runWithWorkflowContext(store, fn) {
472
- return storage.run(store, fn);
473
- }
474
- /** In-memory durable log for inline execution and tests. */
475
- var MemoryEventLog = class {
476
- events = [];
477
- ids = /* @__PURE__ */ new Set();
478
- async append(event) {
479
- const id = event.id ?? crypto.randomUUID();
480
- if (this.ids.has(id)) return false;
481
- this.ids.add(id);
482
- this.events.push({
483
- id,
484
- runId: event.runId,
485
- seq: this.events.length,
486
- type: event.type,
487
- correlationId: event.correlationId ?? null,
488
- data: event.data ?? null
489
- });
490
- return true;
491
- }
492
- async listReplay(runId) {
493
- return this.events.filter((event) => event.runId === runId).map((event) => ({ ...event }));
494
- }
495
- };
496
- /**
497
- * The single way to run a workflow: replay its event log from the top, execute
498
- * un-cached primitives, and either complete/fail or suspend at the first
499
- * un-satisfied sleep/hook. New events (sleep_scheduled/sleep_completed/
500
- * hook_created/run_completed/run_failed) are flushed before returning.
501
- *
502
- * Durability comes entirely from the log — a suspended run resumes by calling
503
- * this again with the same `runId` and event log once the sleep is due or the
504
- * hook is resumed.
505
- */
506
- async function executeWorkflow(workflow, input, options = {}) {
507
- const runId = options.runId ?? crypto.randomUUID();
508
- const eventLog = options.eventLog ?? new MemoryEventLog();
509
- const signal = getRunSignal();
510
- const consumer = new EventsConsumer(await eventLog.listReplay(runId));
511
- const coordinator = new SuspensionCoordinator();
512
- const state = createReplayState({
513
- runId,
514
- consumer,
515
- coordinator,
516
- eventLog,
517
- hookBaseUrl: options.hookBaseUrl,
518
- now: options.now
519
- });
520
- const actionRunner = createActionRunner(state, {
521
- resolveCredentials: options.resolveCredentials,
522
- credentialContext: options.credentialContext,
523
- oauthAdapter: options.oauthAdapter,
524
- mcpCredentialContext: { assignmentTarget: {
525
- type: "workflow",
526
- key: workflow.slug
527
- } }
528
- });
529
- const ctx = {
530
- runId,
531
- sleep: createSleep(state),
532
- hook: createHook(state),
533
- ...options.context
534
- };
535
- const agentRunner = options.runAgent ? createAgentStepRunner(state, options.runAgent) : void 0;
536
- const llmRunner = options.runLlm ? createLlmStepRunner(state, options.runLlm) : void 0;
537
- const workflowRunner = createWorkflowStepRunner(state, ctx);
538
- const validatedInput = workflow.input.parse(input);
539
- const bodyPromise = runWithWorkflowContext({
540
- actionRunner,
541
- agentRunner,
542
- llmRunner,
543
- workflowRunner,
544
- runId
545
- }, () => captureConsole(async () => workflow.run(validatedInput, ctx)));
546
- let onAbort;
547
- const waitForAbort = signal.aborted ? Promise.resolve({ type: "canceled" }) : new Promise((resolve) => {
548
- onAbort = () => resolve({ type: "canceled" });
549
- signal.addEventListener("abort", onAbort, { once: true });
550
- });
551
- const outcome = await Promise.race([
552
- bodyPromise.then((output) => ({
553
- type: "done",
554
- output
555
- }), (error) => ({
556
- type: "error",
557
- error
558
- })),
559
- coordinator.waitForSuspension().then((items) => ({
560
- type: "suspended",
561
- items
562
- })),
563
- waitForAbort
564
- ]);
565
- if (onAbort) signal.removeEventListener("abort", onAbort);
566
- let result;
567
- if (outcome.type === "suspended") {
568
- bodyPromise.catch(() => {});
569
- result = {
570
- status: "suspended",
571
- items: outcome.items
572
- };
573
- } else if (outcome.type === "done") {
574
- const output = workflow.output.parse(outcome.output);
575
- state.newEvents.push({
576
- id: `run_completed:${runId}`,
577
- runId,
578
- type: "run_completed",
579
- data: { output }
580
- });
581
- result = {
582
- status: "completed",
583
- output
584
- };
585
- } else if (outcome.type === "canceled" || isRunCanceledError(outcome.error)) {
586
- bodyPromise.catch(() => {});
587
- state.newEvents.push({
588
- id: `run_canceled:${runId}`,
589
- runId,
590
- type: "run_canceled"
591
- });
592
- result = { status: "canceled" };
593
- } else result = {
594
- status: "failed",
595
- error: outcome.error,
596
- failedCorrelationId: state.failedCorrelationId
597
- };
598
- for (const event of state.newEvents) await eventLog.append(event);
599
- return result;
600
- }
601
- function promptLlm(prompt, opts) {
602
- const handle = getWorkflowRunHandle();
603
- if (!handle?.llmRunner) throw new Error("promptLlm must run inside a workflow with an injected llm executor (executeWorkflow({ runLlm })).");
604
- return handle.llmRunner({
605
- prompt,
606
- ...opts
607
- });
608
- }
609
- //#endregion
610
- export { executeWorkflow as a, promptLlm as c, deserializeWorkflowError as i, serializeWorkflowError as l, RunCanceledError as n, isRunCanceledError as o, defineWorkflow as r, isWorkflow as s, MemoryEventLog as t };
611
-
612
- //# sourceMappingURL=dist-C-1uJk5f.mjs.map