@theokit/sdk 1.5.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.
Files changed (369) hide show
  1. package/CHANGELOG.md +1571 -0
  2. package/LICENSE +201 -0
  3. package/README.md +80 -0
  4. package/bin/theokit-migrate-config.mjs +269 -0
  5. package/bin/theokit-migrate-memory.mjs +116 -0
  6. package/dist/agent-builder.d.ts +52 -0
  7. package/dist/agent-factory.d.ts +39 -0
  8. package/dist/agent.d.ts +175 -0
  9. package/dist/batch.d.ts +11 -0
  10. package/dist/budget.d.ts +48 -0
  11. package/dist/cache.d.ts +74 -0
  12. package/dist/cron-1yxL3K2S.d.cts +221 -0
  13. package/dist/cron-BYVdYzob.d.ts +221 -0
  14. package/dist/cron.cjs +14655 -0
  15. package/dist/cron.cjs.map +1 -0
  16. package/dist/cron.d.cts +3 -0
  17. package/dist/cron.d.ts +71 -0
  18. package/dist/cron.js +14652 -0
  19. package/dist/cron.js.map +1 -0
  20. package/dist/define-tool.d.ts +35 -0
  21. package/dist/errors-CK8brCJ1.d.cts +448 -0
  22. package/dist/errors-CvAeEWgE.d.ts +448 -0
  23. package/dist/errors.cjs +255 -0
  24. package/dist/errors.cjs.map +1 -0
  25. package/dist/errors.d.cts +3 -0
  26. package/dist/errors.d.ts +356 -0
  27. package/dist/errors.js +238 -0
  28. package/dist/errors.js.map +1 -0
  29. package/dist/eval.cjs +14826 -0
  30. package/dist/eval.cjs.map +1 -0
  31. package/dist/eval.d.cts +35 -0
  32. package/dist/eval.d.ts +35 -0
  33. package/dist/eval.js +14821 -0
  34. package/dist/eval.js.map +1 -0
  35. package/dist/generate-object.d.ts +67 -0
  36. package/dist/handoff.d.ts +55 -0
  37. package/dist/index.cjs +17127 -0
  38. package/dist/index.cjs.map +1 -0
  39. package/dist/index.d.cts +1878 -0
  40. package/dist/index.d.ts +24 -0
  41. package/dist/index.js +17095 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/internal/agent-loop/loop-types.d.ts +29 -0
  44. package/dist/internal/agent-loop/loop.d.ts +2 -0
  45. package/dist/internal/agent-loop/message-builders.d.ts +6 -0
  46. package/dist/internal/agent-loop/tool-dispatch.d.ts +4 -0
  47. package/dist/internal/agent-loop/usage-and-cost.d.ts +25 -0
  48. package/dist/internal/budget/calendar-window.d.ts +19 -0
  49. package/dist/internal/budget/compute-cost.d.ts +28 -0
  50. package/dist/internal/budget/enforcement.d.ts +32 -0
  51. package/dist/internal/budget/ledger.d.ts +25 -0
  52. package/dist/internal/budget/normalize-usage.d.ts +27 -0
  53. package/dist/internal/budget/pricing-registry.d.ts +36 -0
  54. package/dist/internal/budget/registry.d.ts +16 -0
  55. package/dist/internal/budget/usage-accumulator.d.ts +31 -0
  56. package/dist/internal/cache/cosine.d.ts +14 -0
  57. package/dist/internal/cache/embed-helper.d.ts +15 -0
  58. package/dist/internal/cache/key.d.ts +15 -0
  59. package/dist/internal/cache/lookup.d.ts +28 -0
  60. package/dist/internal/cache/store-handler.d.ts +24 -0
  61. package/dist/internal/cache/store-json.d.ts +48 -0
  62. package/dist/internal/cache/store.d.ts +54 -0
  63. package/dist/internal/cache/telemetry.d.ts +20 -0
  64. package/dist/internal/cache/ttl.d.ts +11 -0
  65. package/dist/internal/catalog/fixtures.d.ts +16 -0
  66. package/dist/internal/catalog/local-models.d.ts +24 -0
  67. package/dist/internal/cron/run-job.d.ts +1 -0
  68. package/dist/internal/cron/scheduler.d.ts +1 -0
  69. package/dist/internal/cron/store.d.ts +1 -0
  70. package/dist/internal/cron/validate.d.ts +1 -0
  71. package/dist/internal/env.d.ts +1 -0
  72. package/dist/internal/errors/mappers/anthropic.d.ts +30 -0
  73. package/dist/internal/errors/mappers/bedrock.d.ts +16 -0
  74. package/dist/internal/errors/mappers/ollama.d.ts +41 -0
  75. package/dist/internal/errors/mappers/openai-compatible.d.ts +25 -0
  76. package/dist/internal/errors/mappers/shared.d.ts +10 -0
  77. package/dist/internal/errors/mappers/vertex.d.ts +15 -0
  78. package/dist/internal/eval/aggregate.d.ts +9 -0
  79. package/dist/internal/eval/dataset-iter.d.ts +9 -0
  80. package/dist/internal/eval/runner.d.ts +9 -0
  81. package/dist/internal/eval/single-flight.d.ts +16 -0
  82. package/dist/internal/eval/telemetry.d.ts +23 -0
  83. package/dist/internal/fixture-mode.d.ts +16 -0
  84. package/dist/internal/handoff/dispatcher.d.ts +29 -0
  85. package/dist/internal/handoff/registry.d.ts +23 -0
  86. package/dist/internal/handoff/telemetry.d.ts +18 -0
  87. package/dist/internal/handoff/tool-injector.d.ts +34 -0
  88. package/dist/internal/http.d.ts +1 -0
  89. package/dist/internal/ids.d.ts +1 -0
  90. package/dist/internal/judge/judge-call.d.ts +35 -0
  91. package/dist/internal/judge/parse-verdict.d.ts +11 -0
  92. package/dist/internal/judge/types.d.ts +17 -0
  93. package/dist/internal/llm/anthropic-shared.d.ts +89 -0
  94. package/dist/internal/llm/anthropic.d.ts +9 -0
  95. package/dist/internal/llm/bedrock-anthropic.d.ts +36 -0
  96. package/dist/internal/llm/bedrock-token-cache.d.ts +18 -0
  97. package/dist/internal/llm/credential-pool-context.d.ts +11 -0
  98. package/dist/internal/llm/credential-pool-types.d.ts +22 -0
  99. package/dist/internal/llm/credential-pool.d.ts +18 -0
  100. package/dist/internal/llm/fallback-client.d.ts +1 -0
  101. package/dist/internal/llm/fault-injection.d.ts +50 -0
  102. package/dist/internal/llm/finish.d.ts +1 -0
  103. package/dist/internal/llm/model-identifier.d.ts +24 -0
  104. package/dist/internal/llm/ollama-native.d.ts +27 -0
  105. package/dist/internal/llm/openai.d.ts +9 -0
  106. package/dist/internal/llm/pool-aware-client.d.ts +16 -0
  107. package/dist/internal/llm/router.d.ts +17 -0
  108. package/dist/internal/llm/sse.d.ts +9 -0
  109. package/dist/internal/llm/stream-relay.d.ts +17 -0
  110. package/dist/internal/llm/types.d.ts +70 -0
  111. package/dist/internal/llm/vertex-anthropic.d.ts +40 -0
  112. package/dist/internal/llm/vertex-auth.d.ts +30 -0
  113. package/dist/internal/llm/vertex-gemini.d.ts +28 -0
  114. package/dist/internal/llm/vertex-router.d.ts +21 -0
  115. package/dist/internal/mcp/client.d.ts +16 -0
  116. package/dist/internal/memory/active-memory-cache.d.ts +10 -0
  117. package/dist/internal/memory/active-memory.d.ts +45 -0
  118. package/dist/internal/memory/adapters/catalog.d.ts +1 -0
  119. package/dist/internal/memory/adapters/deepinfra-embedding.d.ts +2 -0
  120. package/dist/internal/memory/adapters/mistral-embedding.d.ts +2 -0
  121. package/dist/internal/memory/adapters/ollama-embedding.d.ts +34 -0
  122. package/dist/internal/memory/adapters/openai-compatible.d.ts +23 -0
  123. package/dist/internal/memory/adapters/openai-embedding.d.ts +2 -0
  124. package/dist/internal/memory/adapters/openrouter-embedding.d.ts +2 -0
  125. package/dist/internal/memory/adapters/voyage-embedding.d.ts +2 -0
  126. package/dist/internal/memory/atomic-write.d.ts +7 -0
  127. package/dist/internal/memory/chunk-markdown.d.ts +2 -0
  128. package/dist/internal/memory/circuit-breaker.d.ts +22 -0
  129. package/dist/internal/memory/cwd-mutex.d.ts +1 -0
  130. package/dist/internal/memory/dreaming/diary.d.ts +4 -0
  131. package/dist/internal/memory/dreaming/phases.d.ts +15 -0
  132. package/dist/internal/memory/dreaming/run.d.ts +10 -0
  133. package/dist/internal/memory/embedding-adapter.d.ts +42 -0
  134. package/dist/internal/memory/embedding-cache.d.ts +1 -0
  135. package/dist/internal/memory/index-db.d.ts +10 -0
  136. package/dist/internal/memory/index-manager-dispatch.d.ts +23 -0
  137. package/dist/internal/memory/index-manager.d.ts +68 -0
  138. package/dist/internal/memory/index-schema.d.ts +21 -0
  139. package/dist/internal/memory/lance-index.d.ts +32 -0
  140. package/dist/internal/memory/lance-memory-adapter.d.ts +43 -0
  141. package/dist/internal/memory/markdown-store.d.ts +16 -0
  142. package/dist/internal/memory/memory-index.d.ts +52 -0
  143. package/dist/internal/memory/migrate-sqlite-to-lance.d.ts +15 -0
  144. package/dist/internal/memory/migration.d.ts +9 -0
  145. package/dist/internal/memory/reader.d.ts +8 -0
  146. package/dist/internal/memory/session-loader.d.ts +1 -0
  147. package/dist/internal/memory/session-summary-writer.d.ts +2 -0
  148. package/dist/internal/memory/sqlite-vec-loader.d.ts +3 -0
  149. package/dist/internal/memory/tools.d.ts +14 -0
  150. package/dist/internal/memory/transcript-store.d.ts +1 -0
  151. package/dist/internal/memory/types.d.ts +17 -0
  152. package/dist/internal/memory/vec-index.d.ts +28 -0
  153. package/dist/internal/memory/wiki-loader.d.ts +2 -0
  154. package/dist/internal/observability/tracer-loader.d.ts +20 -0
  155. package/dist/internal/persistence/atomic-write.d.ts +1 -0
  156. package/dist/internal/persistence/conversation-storage-fs.d.ts +37 -0
  157. package/dist/internal/persistence/conversation-storage-memory.d.ts +24 -0
  158. package/dist/internal/persistence/cwd-mutex.d.ts +1 -0
  159. package/dist/internal/persistence/file-lock.d.ts +14 -0
  160. package/dist/internal/persistence/fts5-sanitize.d.ts +16 -0
  161. package/dist/internal/persistence/markdown-config-loader.d.ts +35 -0
  162. package/dist/internal/persistence/paths.d.ts +19 -0
  163. package/dist/internal/persistence/persistence-schema.d.ts +17 -0
  164. package/dist/internal/persistence/schema-version.d.ts +13 -0
  165. package/dist/internal/persistence/sqlite-wal.d.ts +10 -0
  166. package/dist/internal/personality/context.d.ts +17 -0
  167. package/dist/internal/personality/registry.d.ts +17 -0
  168. package/dist/internal/personality/store.d.ts +27 -0
  169. package/dist/internal/personality/switch.d.ts +36 -0
  170. package/dist/internal/personality/types.d.ts +18 -0
  171. package/dist/internal/plugins/context.d.ts +31 -0
  172. package/dist/internal/plugins/manager.d.ts +37 -0
  173. package/dist/internal/plugins/types.d.ts +102 -0
  174. package/dist/internal/providers/builtin/anthropic.d.ts +2 -0
  175. package/dist/internal/providers/builtin/bedrock.d.ts +25 -0
  176. package/dist/internal/providers/builtin/gemini.d.ts +10 -0
  177. package/dist/internal/providers/builtin/index.d.ts +19 -0
  178. package/dist/internal/providers/builtin/llamacpp.d.ts +1 -0
  179. package/dist/internal/providers/builtin/lmstudio.d.ts +1 -0
  180. package/dist/internal/providers/builtin/ollama.d.ts +17 -0
  181. package/dist/internal/providers/builtin/openai.d.ts +2 -0
  182. package/dist/internal/providers/builtin/openrouter.d.ts +2 -0
  183. package/dist/internal/providers/builtin/vertex.d.ts +27 -0
  184. package/dist/internal/providers/discovery.d.ts +14 -0
  185. package/dist/internal/providers/index.d.ts +8 -0
  186. package/dist/internal/providers/registry.d.ts +12 -0
  187. package/dist/internal/providers/types.d.ts +27 -0
  188. package/dist/internal/runtime/abort-utils.d.ts +21 -0
  189. package/dist/internal/runtime/agent-factory-registry.d.ts +16 -0
  190. package/dist/internal/runtime/agent-registry-store.d.ts +61 -0
  191. package/dist/internal/runtime/agent-registry.d.ts +34 -0
  192. package/dist/internal/runtime/agent-session-store.d.ts +3 -0
  193. package/dist/internal/runtime/agent-session.d.ts +2 -0
  194. package/dist/internal/runtime/async-local-storage.d.ts +20 -0
  195. package/dist/internal/runtime/async-semaphore.d.ts +24 -0
  196. package/dist/internal/runtime/budget.d.ts +36 -0
  197. package/dist/internal/runtime/cloud-agent.d.ts +1 -0
  198. package/dist/internal/runtime/cloud-config-serializer.d.ts +3 -0
  199. package/dist/internal/runtime/cloud-payload-types.d.ts +56 -0
  200. package/dist/internal/runtime/cloud-run.d.ts +1 -0
  201. package/dist/internal/runtime/cloud-tool-parity.d.ts +1 -0
  202. package/dist/internal/runtime/context-aggregator.d.ts +26 -0
  203. package/dist/internal/runtime/context-discovery-runner.d.ts +27 -0
  204. package/dist/internal/runtime/context-discovery.d.ts +21 -0
  205. package/dist/internal/runtime/context-frontmatter.d.ts +16 -0
  206. package/dist/internal/runtime/context-import-resolver.d.ts +24 -0
  207. package/dist/internal/runtime/context-loaders.d.ts +42 -0
  208. package/dist/internal/runtime/context-manager.d.ts +11 -0
  209. package/dist/internal/runtime/context-mdc-parser.d.ts +24 -0
  210. package/dist/internal/runtime/default-model.d.ts +1 -0
  211. package/dist/internal/runtime/fixture-events.d.ts +12 -0
  212. package/dist/internal/runtime/fixture-responder.d.ts +1 -0
  213. package/dist/internal/runtime/fixture-run-base.d.ts +45 -0
  214. package/dist/internal/runtime/fixture-scripts.d.ts +21 -0
  215. package/dist/internal/runtime/fixture-types.d.ts +1 -0
  216. package/dist/internal/runtime/fork-agent.d.ts +15 -0
  217. package/dist/internal/runtime/hooks-executor.d.ts +35 -0
  218. package/dist/internal/runtime/hooks-frontmatter.d.ts +26 -0
  219. package/dist/internal/runtime/hooks-source.d.ts +22 -0
  220. package/dist/internal/runtime/live-agent-registry.d.ts +87 -0
  221. package/dist/internal/runtime/local-agent-bootstrap.d.ts +37 -0
  222. package/dist/internal/runtime/local-agent-dispatch.d.ts +57 -0
  223. package/dist/internal/runtime/local-agent-invalidate.d.ts +8 -0
  224. package/dist/internal/runtime/local-agent-memory-direct.d.ts +12 -0
  225. package/dist/internal/runtime/local-agent-memory-hooks.d.ts +41 -0
  226. package/dist/internal/runtime/local-agent-memory.d.ts +1 -0
  227. package/dist/internal/runtime/local-agent-personality-extensions.d.ts +19 -0
  228. package/dist/internal/runtime/local-agent-plugins.d.ts +13 -0
  229. package/dist/internal/runtime/local-agent-runtime-extensions.d.ts +13 -0
  230. package/dist/internal/runtime/local-agent-task-wrap.d.ts +11 -0
  231. package/dist/internal/runtime/local-agent.d.ts +1 -0
  232. package/dist/internal/runtime/local-run.d.ts +1 -0
  233. package/dist/internal/runtime/memory-store.d.ts +4 -0
  234. package/dist/internal/runtime/plugin-frontmatter.d.ts +17 -0
  235. package/dist/internal/runtime/plugins-manager.d.ts +1 -0
  236. package/dist/internal/runtime/post-run-lifecycle.d.ts +1 -0
  237. package/dist/internal/runtime/providers-manager.d.ts +1 -0
  238. package/dist/internal/runtime/real-cloud-run.d.ts +2 -0
  239. package/dist/internal/runtime/real-local-run.d.ts +2 -0
  240. package/dist/internal/runtime/run-registry.d.ts +5 -0
  241. package/dist/internal/runtime/run-until.d.ts +22 -0
  242. package/dist/internal/runtime/shell-tool.d.ts +7 -0
  243. package/dist/internal/runtime/skill-frontmatter.d.ts +1 -0
  244. package/dist/internal/runtime/skills-manager.d.ts +1 -0
  245. package/dist/internal/runtime/spawn-collect.d.ts +8 -0
  246. package/dist/internal/runtime/subagents-loader.d.ts +1 -0
  247. package/dist/internal/runtime/system-prompt/escape.d.ts +1 -0
  248. package/dist/internal/runtime/system-prompt/local-assembly.d.ts +1 -0
  249. package/dist/internal/runtime/system-prompt/pipeline.d.ts +1 -0
  250. package/dist/internal/runtime/system-prompt/providers/active-memory-provider.d.ts +1 -0
  251. package/dist/internal/runtime/system-prompt/providers/base-provider.d.ts +1 -0
  252. package/dist/internal/runtime/system-prompt/providers/context-provider.d.ts +1 -0
  253. package/dist/internal/runtime/system-prompt/providers/memory-provider.d.ts +1 -0
  254. package/dist/internal/runtime/system-prompt/providers/skills-provider.d.ts +1 -0
  255. package/dist/internal/runtime/system-prompt/safe-call.d.ts +1 -0
  256. package/dist/internal/runtime/system-prompt/types.d.ts +5 -0
  257. package/dist/internal/runtime/system-prompt.d.ts +1 -0
  258. package/dist/internal/runtime/validate-agent-options.d.ts +1 -0
  259. package/dist/internal/runtime/workspace-dir.d.ts +9 -0
  260. package/dist/internal/runtime/yaml-frontmatter.d.ts +20 -0
  261. package/dist/internal/scorers/llm-judge.d.ts +24 -0
  262. package/dist/internal/security/index.d.ts +11 -0
  263. package/dist/internal/security/path-guard.d.ts +56 -0
  264. package/dist/internal/security/redact.d.ts +21 -0
  265. package/dist/internal/structured-output-helpers.d.ts +54 -0
  266. package/dist/internal/task/registry.d.ts +61 -0
  267. package/dist/internal/task/ring-buffer.d.ts +10 -0
  268. package/dist/internal/task/store.d.ts +59 -0
  269. package/dist/internal/task/subscribe.d.ts +15 -0
  270. package/dist/internal/task/telemetry.d.ts +27 -0
  271. package/dist/internal/telemetry/adapter-registry.d.ts +2 -0
  272. package/dist/internal/telemetry/adapters/langfuse.d.ts +2 -0
  273. package/dist/internal/telemetry/adapters/posthog.d.ts +2 -0
  274. package/dist/internal/telemetry/adapters/sentry.d.ts +2 -0
  275. package/dist/internal/telemetry/safe-require.d.ts +1 -0
  276. package/dist/internal/telemetry/tracer.d.ts +18 -0
  277. package/dist/internal/tool-dispatch/repair-middleware.d.ts +34 -0
  278. package/dist/internal/tool-dispatch/strip-think.d.ts +22 -0
  279. package/dist/internal/tool-registry/personality-filter.d.ts +37 -0
  280. package/dist/internal/workflow/ctx.d.ts +19 -0
  281. package/dist/internal/workflow/error-shape.d.ts +7 -0
  282. package/dist/internal/workflow/executor.d.ts +15 -0
  283. package/dist/internal/workflow/index.d.ts +12 -0
  284. package/dist/internal/workflow/retry-policy.d.ts +14 -0
  285. package/dist/internal/workflow/run-id.d.ts +9 -0
  286. package/dist/internal/workflow/single-flight.d.ts +18 -0
  287. package/dist/internal/workflow/snapshot-store.d.ts +23 -0
  288. package/dist/internal/workflow/step-agent.d.ts +12 -0
  289. package/dist/internal/workflow/step-branch.d.ts +10 -0
  290. package/dist/internal/workflow/step-dowhile.d.ts +8 -0
  291. package/dist/internal/workflow/step-fn.d.ts +10 -0
  292. package/dist/internal/workflow/step-foreach.d.ts +11 -0
  293. package/dist/internal/workflow/step-parallel.d.ts +17 -0
  294. package/dist/internal/workflow/step-sleep.d.ts +7 -0
  295. package/dist/internal/workflow/telemetry.d.ts +23 -0
  296. package/dist/internal/zod/to-json-schema.d.ts +21 -0
  297. package/dist/memory-adapter-helpers.d.ts +28 -0
  298. package/dist/memory.d.ts +123 -0
  299. package/dist/migrate.d.ts +33 -0
  300. package/dist/path-safety.cjs +126 -0
  301. package/dist/path-safety.cjs.map +1 -0
  302. package/dist/path-safety.d.cts +15 -0
  303. package/dist/path-safety.d.ts +15 -0
  304. package/dist/path-safety.js +120 -0
  305. package/dist/path-safety.js.map +1 -0
  306. package/dist/run-DkCD5DeO.d.cts +2181 -0
  307. package/dist/run-DkCD5DeO.d.ts +2181 -0
  308. package/dist/scorers.d.ts +75 -0
  309. package/dist/security.d.ts +67 -0
  310. package/dist/stream-object.d.ts +74 -0
  311. package/dist/task-store.cjs +237 -0
  312. package/dist/task-store.cjs.map +1 -0
  313. package/dist/task-store.d.cts +8 -0
  314. package/dist/task-store.d.ts +8 -0
  315. package/dist/task-store.js +233 -0
  316. package/dist/task-store.js.map +1 -0
  317. package/dist/task.d.ts +87 -0
  318. package/dist/theokit.d.ts +84 -0
  319. package/dist/tools/_path-scope.d.cts +8 -0
  320. package/dist/tools/_path-scope.d.ts +8 -0
  321. package/dist/tools/_subprocess.d.cts +28 -0
  322. package/dist/tools/_subprocess.d.ts +28 -0
  323. package/dist/tools/git-diff.d.cts +22 -0
  324. package/dist/tools/git-diff.d.ts +22 -0
  325. package/dist/tools/index.d.cts +29 -0
  326. package/dist/tools/index.d.ts +29 -0
  327. package/dist/tools/list-dir.d.cts +26 -0
  328. package/dist/tools/list-dir.d.ts +26 -0
  329. package/dist/tools/read-file.d.cts +31 -0
  330. package/dist/tools/read-file.d.ts +31 -0
  331. package/dist/tools/run-vitest.d.cts +46 -0
  332. package/dist/tools/run-vitest.d.ts +46 -0
  333. package/dist/tools/search-text.d.cts +32 -0
  334. package/dist/tools/search-text.d.ts +32 -0
  335. package/dist/tools.cjs +690 -0
  336. package/dist/tools.cjs.map +1 -0
  337. package/dist/tools.js +683 -0
  338. package/dist/tools.js.map +1 -0
  339. package/dist/trajectory-helpers.d.ts +31 -0
  340. package/dist/types/agent.d.ts +771 -0
  341. package/dist/types/batch.d.ts +112 -0
  342. package/dist/types/budget.d.ts +88 -0
  343. package/dist/types/cache.d.ts +76 -0
  344. package/dist/types/context.d.ts +93 -0
  345. package/dist/types/conversation-storage.d.ts +76 -0
  346. package/dist/types/conversation.d.ts +90 -0
  347. package/dist/types/cron.d.ts +150 -0
  348. package/dist/types/eval.d.ts +132 -0
  349. package/dist/types/goal-events.d.ts +95 -0
  350. package/dist/types/handoff.d.ts +135 -0
  351. package/dist/types/index.d.ts +20 -0
  352. package/dist/types/mcp.d.ts +64 -0
  353. package/dist/types/memory-adapter.d.ts +175 -0
  354. package/dist/types/messages.d.ts +154 -0
  355. package/dist/types/providers.d.ts +102 -0
  356. package/dist/types/run.d.ts +215 -0
  357. package/dist/types/task.d.ts +131 -0
  358. package/dist/types/theokit.d.ts +61 -0
  359. package/dist/types/trajectory.d.ts +49 -0
  360. package/dist/types/updates.d.ts +148 -0
  361. package/dist/types/usage.d.ts +61 -0
  362. package/dist/types/workflow.d.ts +217 -0
  363. package/dist/workflow.cjs +2405 -0
  364. package/dist/workflow.cjs.map +1 -0
  365. package/dist/workflow.d.cts +97 -0
  366. package/dist/workflow.d.ts +97 -0
  367. package/dist/workflow.js +2398 -0
  368. package/dist/workflow.js.map +1 -0
  369. package/package.json +183 -0
@@ -0,0 +1,2405 @@
1
+ 'use strict';
2
+
3
+ var promises = require('fs/promises');
4
+ var path = require('path');
5
+ var module$1 = require('module');
6
+ var fs = require('fs');
7
+ var async_hooks = require('async_hooks');
8
+ var crypto = require('crypto');
9
+ var zod = require('zod');
10
+
11
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
12
+ var __defProp = Object.defineProperty;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __esm = (fn2, res) => function __init() {
15
+ return fn2 && (res = (0, fn2[__getOwnPropNames(fn2)[0]])(fn2 = 0)), res;
16
+ };
17
+ var __export = (target, all) => {
18
+ for (var name in all)
19
+ __defProp(target, name, { get: all[name], enumerable: true });
20
+ };
21
+
22
+ // src/errors.ts
23
+ var TheokitAgentError, ConfigurationError, UnsupportedRunOperationError, InvalidTaskIdError, TaskNotFoundError;
24
+ var init_errors = __esm({
25
+ "src/errors.ts"() {
26
+ TheokitAgentError = class extends Error {
27
+ name = "TheokitAgentError";
28
+ isRetryable;
29
+ code;
30
+ protoErrorCode;
31
+ metadata;
32
+ constructor(message, options = {}) {
33
+ super(message, options.cause !== void 0 ? { cause: options.cause } : void 0);
34
+ this.isRetryable = options.isRetryable ?? false;
35
+ if (options.code !== void 0) this.code = options.code;
36
+ if (options.protoErrorCode !== void 0) this.protoErrorCode = options.protoErrorCode;
37
+ if (options.metadata !== void 0) this.metadata = options.metadata;
38
+ }
39
+ };
40
+ ConfigurationError = class extends TheokitAgentError {
41
+ name = "ConfigurationError";
42
+ constructor(message, options = {}) {
43
+ super(message, { ...options, isRetryable: false });
44
+ }
45
+ };
46
+ UnsupportedRunOperationError = class extends TheokitAgentError {
47
+ name = "UnsupportedRunOperationError";
48
+ operation;
49
+ constructor(message, operation, options = {}) {
50
+ super(message, {
51
+ ...options,
52
+ isRetryable: false,
53
+ code: options.code ?? "unsupported_run_operation"
54
+ });
55
+ this.operation = operation;
56
+ }
57
+ };
58
+ InvalidTaskIdError = class extends TheokitAgentError {
59
+ name = "InvalidTaskIdError";
60
+ taskId;
61
+ constructor(message, taskId, options = {}) {
62
+ super(message, {
63
+ ...options,
64
+ isRetryable: false,
65
+ code: "invalid_task_id"
66
+ });
67
+ this.taskId = taskId;
68
+ }
69
+ };
70
+ TaskNotFoundError = class extends TheokitAgentError {
71
+ name = "TaskNotFoundError";
72
+ taskId;
73
+ constructor(taskId, options = {}) {
74
+ super(`Task not found: ${taskId}`, {
75
+ ...options,
76
+ isRetryable: false,
77
+ code: "task_not_found"
78
+ });
79
+ this.taskId = taskId;
80
+ }
81
+ };
82
+ }
83
+ });
84
+
85
+ // src/types/workflow.ts
86
+ exports.WorkflowDuplicateStepIdError = void 0; exports.WorkflowAlreadyRunningError = void 0; exports.WorkflowSnapshotNotFoundError = void 0; exports.WorkflowMaxIterationsExceededError = void 0; exports.WorkflowNotSerializableError = void 0; exports.WorkflowResumeStepNotFoundError = void 0; exports.WorkflowParallelError = void 0; exports.WorkflowCompensateNotImplementedError = void 0;
87
+ var init_workflow = __esm({
88
+ "src/types/workflow.ts"() {
89
+ exports.WorkflowDuplicateStepIdError = class extends Error {
90
+ constructor(stepId) {
91
+ super(`Duplicate step id "${stepId}" in workflow.`);
92
+ this.stepId = stepId;
93
+ }
94
+ stepId;
95
+ name = "WorkflowDuplicateStepIdError";
96
+ };
97
+ exports.WorkflowAlreadyRunningError = class extends Error {
98
+ constructor(workflowName, runId) {
99
+ super(`Workflow "${workflowName}" run "${runId}" already in-flight.`);
100
+ this.workflowName = workflowName;
101
+ this.runId = runId;
102
+ }
103
+ workflowName;
104
+ runId;
105
+ name = "WorkflowAlreadyRunningError";
106
+ };
107
+ exports.WorkflowSnapshotNotFoundError = class extends Error {
108
+ constructor(runId) {
109
+ super(`No snapshot found for runId "${runId}". Configure persistence to enable resume.`);
110
+ this.runId = runId;
111
+ }
112
+ runId;
113
+ name = "WorkflowSnapshotNotFoundError";
114
+ };
115
+ exports.WorkflowMaxIterationsExceededError = class extends Error {
116
+ constructor(stepId, maxIterations) {
117
+ super(`Step "${stepId}" exceeded max iterations (${maxIterations}).`);
118
+ this.stepId = stepId;
119
+ this.maxIterations = maxIterations;
120
+ }
121
+ stepId;
122
+ maxIterations;
123
+ name = "WorkflowMaxIterationsExceededError";
124
+ };
125
+ exports.WorkflowNotSerializableError = class extends Error {
126
+ constructor(stepId, underlying) {
127
+ super(
128
+ `Workflow snapshot at step "${stepId}" failed to serialize as JSON: ${underlying.message}. Persisted snapshots support only JSON-serializable values (no BigInt, no circular refs, no class instances with cycles).`
129
+ );
130
+ this.stepId = stepId;
131
+ this.underlying = underlying;
132
+ }
133
+ stepId;
134
+ underlying;
135
+ name = "WorkflowNotSerializableError";
136
+ };
137
+ exports.WorkflowResumeStepNotFoundError = class extends Error {
138
+ constructor(stepId, workflowName) {
139
+ super(
140
+ `Cannot resume: step "${stepId}" not found in workflow "${workflowName}". The Workflow definition diverged from the snapshot.`
141
+ );
142
+ this.stepId = stepId;
143
+ this.workflowName = workflowName;
144
+ }
145
+ stepId;
146
+ workflowName;
147
+ name = "WorkflowResumeStepNotFoundError";
148
+ };
149
+ exports.WorkflowParallelError = class extends AggregateError {
150
+ constructor(errors, stepId) {
151
+ super(errors, `${errors.length} branch(es) failed in parallel step "${stepId}".`);
152
+ this.stepId = stepId;
153
+ }
154
+ stepId;
155
+ name = "WorkflowParallelError";
156
+ };
157
+ exports.WorkflowCompensateNotImplementedError = class extends Error {
158
+ constructor(stepId) {
159
+ super(
160
+ `Step "${stepId}" defines compensate, but saga engine is deferred to v1.2. Remove compensate or implement rollback manually.`
161
+ );
162
+ this.stepId = stepId;
163
+ }
164
+ stepId;
165
+ name = "WorkflowCompensateNotImplementedError";
166
+ };
167
+ }
168
+ });
169
+ async function replaceFileAtomic(filePath, content) {
170
+ const tmp = `${filePath}.${process.pid}.${Math.random().toString(36).slice(2, 10)}.tmp`;
171
+ const handle = await promises.open(tmp, "w");
172
+ try {
173
+ await handle.writeFile(content, "utf8");
174
+ await handle.sync();
175
+ } finally {
176
+ await handle.close();
177
+ }
178
+ try {
179
+ await promises.rename(tmp, filePath);
180
+ } catch (cause) {
181
+ await promises.unlink(tmp).catch(() => void 0);
182
+ throw cause;
183
+ }
184
+ }
185
+ async function atomicWriteText(filePath, content) {
186
+ await promises.mkdir(path.dirname(filePath), { recursive: true });
187
+ await replaceFileAtomic(filePath, content);
188
+ }
189
+ var init_atomic_write = __esm({
190
+ "src/internal/persistence/atomic-write.ts"() {
191
+ }
192
+ });
193
+ function getSnapshotStoreFor(options) {
194
+ if (options.persistence?.backend === "json") {
195
+ const dir = options.persistence.dir;
196
+ let store = jsonStores.get(dir);
197
+ if (store === void 0) {
198
+ store = new JsonFileWorkflowSnapshotStore(dir);
199
+ jsonStores.set(dir, store);
200
+ }
201
+ return store;
202
+ }
203
+ return memoryStore;
204
+ }
205
+ function __resetSnapshotStoresForTests() {
206
+ jsonStores.clear();
207
+ memoryStore.map.clear();
208
+ }
209
+ var InMemoryWorkflowSnapshotStore, JsonFileWorkflowSnapshotStore, memoryStore, jsonStores;
210
+ var init_snapshot_store = __esm({
211
+ "src/internal/workflow/snapshot-store.ts"() {
212
+ init_workflow();
213
+ init_atomic_write();
214
+ InMemoryWorkflowSnapshotStore = class {
215
+ map = /* @__PURE__ */ new Map();
216
+ async save(snapshot) {
217
+ try {
218
+ JSON.stringify(snapshot);
219
+ } catch (err) {
220
+ throw new exports.WorkflowNotSerializableError(
221
+ snapshot.currentStepId,
222
+ err instanceof Error ? err : new Error(String(err))
223
+ );
224
+ }
225
+ this.map.set(snapshot.runId, snapshot);
226
+ }
227
+ async load(runId) {
228
+ return this.map.get(runId);
229
+ }
230
+ async delete(runId) {
231
+ this.map.delete(runId);
232
+ }
233
+ async list(workflowName) {
234
+ return [...this.map.values()].filter((s) => workflowName === void 0 || s.workflowName === workflowName).map((s) => ({
235
+ runId: s.runId,
236
+ workflowName: s.workflowName,
237
+ suspendedAt: s.suspendedAt
238
+ }));
239
+ }
240
+ };
241
+ JsonFileWorkflowSnapshotStore = class {
242
+ constructor(dir) {
243
+ this.dir = dir;
244
+ }
245
+ dir;
246
+ filePath(runId) {
247
+ return path.join(this.dir, `${runId}.json`);
248
+ }
249
+ async save(snapshot) {
250
+ let serialized;
251
+ try {
252
+ serialized = JSON.stringify(snapshot);
253
+ } catch (err) {
254
+ throw new exports.WorkflowNotSerializableError(
255
+ snapshot.currentStepId,
256
+ err instanceof Error ? err : new Error(String(err))
257
+ );
258
+ }
259
+ await promises.mkdir(this.dir, { recursive: true });
260
+ await atomicWriteText(this.filePath(snapshot.runId), serialized);
261
+ }
262
+ async load(runId) {
263
+ try {
264
+ const raw = await promises.readFile(this.filePath(runId), "utf8");
265
+ return JSON.parse(raw);
266
+ } catch (err) {
267
+ if (err.code === "ENOENT") return void 0;
268
+ throw err;
269
+ }
270
+ }
271
+ async delete(runId) {
272
+ try {
273
+ await (await import('fs/promises')).unlink(this.filePath(runId));
274
+ } catch (err) {
275
+ if (err.code !== "ENOENT") throw err;
276
+ }
277
+ }
278
+ async readEntriesOrEmpty() {
279
+ try {
280
+ return await promises.readdir(this.dir);
281
+ } catch (err) {
282
+ if (err.code === "ENOENT") return [];
283
+ throw err;
284
+ }
285
+ }
286
+ async readSnapshotSafe(file) {
287
+ try {
288
+ const raw = await promises.readFile(path.join(this.dir, file), "utf8");
289
+ return JSON.parse(raw);
290
+ } catch {
291
+ return void 0;
292
+ }
293
+ }
294
+ async list(workflowName) {
295
+ const entries = await this.readEntriesOrEmpty();
296
+ const results = [];
297
+ for (const file of entries) {
298
+ if (!file.endsWith(".json")) continue;
299
+ const snap = await this.readSnapshotSafe(file);
300
+ if (snap === void 0) continue;
301
+ if (workflowName !== void 0 && snap.workflowName !== workflowName) continue;
302
+ results.push({
303
+ runId: snap.runId,
304
+ workflowName: snap.workflowName,
305
+ suspendedAt: snap.suspendedAt
306
+ });
307
+ }
308
+ return results;
309
+ }
310
+ };
311
+ memoryStore = new InMemoryWorkflowSnapshotStore();
312
+ jsonStores = /* @__PURE__ */ new Map();
313
+ }
314
+ });
315
+
316
+ // src/internal/workflow/ctx.ts
317
+ function makeStepContext(runId, signal) {
318
+ return {
319
+ runId,
320
+ signal,
321
+ log: {
322
+ debug: (msg, attrs) => emit("debug", runId, msg, attrs),
323
+ info: (msg, attrs) => emit("info", runId, msg, attrs),
324
+ warn: (msg, attrs) => emit("warn", runId, msg, attrs)
325
+ },
326
+ suspend: async (payload) => {
327
+ throw new WorkflowSuspendedSentinel(payload);
328
+ }
329
+ };
330
+ }
331
+ function emit(level, runId, msg, attrs) {
332
+ const tag = `[workflow ${runId}]`;
333
+ if (attrs !== void 0) {
334
+ if (level === "warn") console.warn(tag, msg, attrs);
335
+ else console.log(tag, msg, attrs);
336
+ } else {
337
+ if (level === "warn") console.warn(tag, msg);
338
+ else console.log(tag, msg);
339
+ }
340
+ }
341
+ function combineSignals(...signals) {
342
+ const valid = signals.filter((s) => s !== void 0);
343
+ if (valid.length === 0) return new AbortController().signal;
344
+ if (valid.length === 1) return valid[0];
345
+ const ctrl = new AbortController();
346
+ for (const s of valid) {
347
+ if (s.aborted) {
348
+ ctrl.abort(s.reason);
349
+ break;
350
+ }
351
+ s.addEventListener("abort", () => ctrl.abort(s.reason), { once: true });
352
+ }
353
+ return ctrl.signal;
354
+ }
355
+ var WorkflowSuspendedSentinel;
356
+ var init_ctx = __esm({
357
+ "src/internal/workflow/ctx.ts"() {
358
+ WorkflowSuspendedSentinel = class extends Error {
359
+ constructor(payload) {
360
+ super("__workflow_suspended__");
361
+ this.payload = payload;
362
+ }
363
+ payload;
364
+ name = "WorkflowSuspendedSentinel";
365
+ };
366
+ }
367
+ });
368
+
369
+ // src/internal/workflow/error-shape.ts
370
+ function errToShape(err) {
371
+ if (err instanceof Error) {
372
+ return { name: err.name, message: err.message };
373
+ }
374
+ return { name: "Error", message: String(err) };
375
+ }
376
+ var init_error_shape = __esm({
377
+ "src/internal/workflow/error-shape.ts"() {
378
+ }
379
+ });
380
+
381
+ // src/internal/workflow/run-id.ts
382
+ function mintRunId() {
383
+ return `wfr-${globalThis.crypto.randomUUID().replace(/-/g, "").slice(0, 8)}`;
384
+ }
385
+ var init_run_id = __esm({
386
+ "src/internal/workflow/run-id.ts"() {
387
+ }
388
+ });
389
+
390
+ // src/internal/workflow/single-flight.ts
391
+ function key(workflowId, runId) {
392
+ return `${workflowId}:${runId}`;
393
+ }
394
+ function acquireSingleFlight(workflowId, runId, workflowName) {
395
+ const k = key(workflowId, runId);
396
+ if (registry.has(k)) {
397
+ throw new exports.WorkflowAlreadyRunningError(workflowName, runId);
398
+ }
399
+ const controller = new AbortController();
400
+ registry.set(k, { controller });
401
+ return {
402
+ signal: controller.signal,
403
+ release: () => {
404
+ registry.delete(k);
405
+ }
406
+ };
407
+ }
408
+ var registry;
409
+ var init_single_flight = __esm({
410
+ "src/internal/workflow/single-flight.ts"() {
411
+ init_workflow();
412
+ registry = /* @__PURE__ */ new Map();
413
+ }
414
+ });
415
+
416
+ // src/internal/workflow/retry-policy.ts
417
+ function backoffConfigFromPolicy(policy) {
418
+ return {
419
+ max: policy.maxAttempts,
420
+ init: policy.initialBackoffMs ?? 1e3,
421
+ coef: policy.backoffCoefficient ?? 2,
422
+ cap: policy.maximumBackoffMs ?? 3e4,
423
+ nonRetryable: new Set(policy.nonRetryableErrors ?? DEFAULT_NON_RETRYABLE)
424
+ };
425
+ }
426
+ function throwIfAborted(signal) {
427
+ if (signal.aborted) {
428
+ throw new DOMException(String(signal.reason ?? "Aborted"), "AbortError");
429
+ }
430
+ }
431
+ function shouldRethrow(err, attempt, cfg) {
432
+ const errName = err instanceof Error ? err.name : "Error";
433
+ return cfg.nonRetryable.has(errName) || attempt === cfg.max;
434
+ }
435
+ async function tryOnce(fn2, attempt, cfg, signal) {
436
+ try {
437
+ const value = await fn2();
438
+ return { value, attempts: attempt };
439
+ } catch (err) {
440
+ if (shouldRethrow(err, attempt, cfg)) throw err;
441
+ await abortableSleep(Math.min(cfg.init * cfg.coef ** (attempt - 1), cfg.cap), signal);
442
+ return { kind: "retry" };
443
+ }
444
+ }
445
+ async function withRetry(fn2, policy, signal) {
446
+ const cfg = backoffConfigFromPolicy(policy);
447
+ for (let attempt = 1; attempt <= cfg.max; attempt += 1) {
448
+ throwIfAborted(signal);
449
+ const result = await tryOnce(fn2, attempt, cfg, signal);
450
+ if ("value" in result) return result;
451
+ }
452
+ throw new Error("withRetry: exhausted attempts without throwing");
453
+ }
454
+ async function abortableSleep(ms, signal) {
455
+ if (signal.aborted) {
456
+ throw new DOMException(String(signal.reason ?? "Aborted"), "AbortError");
457
+ }
458
+ return new Promise((resolve2, reject) => {
459
+ const timer = setTimeout(() => {
460
+ cleanup();
461
+ resolve2();
462
+ }, ms);
463
+ const onAbort = () => {
464
+ clearTimeout(timer);
465
+ cleanup();
466
+ reject(new DOMException(String(signal.reason ?? "Aborted"), "AbortError"));
467
+ };
468
+ const cleanup = () => {
469
+ signal.removeEventListener("abort", onAbort);
470
+ };
471
+ signal.addEventListener("abort", onAbort, { once: true });
472
+ });
473
+ }
474
+ var DEFAULT_NON_RETRYABLE;
475
+ var init_retry_policy = __esm({
476
+ "src/internal/workflow/retry-policy.ts"() {
477
+ DEFAULT_NON_RETRYABLE = ["AbortError", "WorkflowSnapshotNotFoundError", "ConfigurationError"];
478
+ }
479
+ });
480
+
481
+ // src/internal/workflow/step-agent.ts
482
+ async function runAgentStep(step, input, ctx) {
483
+ const startedAt = Date.now();
484
+ const agentId = step.agent.agentId;
485
+ if (typeof agentId === "string" && agentId.startsWith("bc-")) {
486
+ return {
487
+ stepId: step.id,
488
+ kind: "agent",
489
+ status: "failed",
490
+ attempts: 0,
491
+ durationMs: Date.now() - startedAt,
492
+ error: errToShape(
493
+ new UnsupportedRunOperationError(
494
+ `Workflow agent steps not supported on CloudAgent yet (D244). agent="${agentId}", step="${step.id}"`,
495
+ "workflow"
496
+ )
497
+ )
498
+ };
499
+ }
500
+ let prompt;
501
+ try {
502
+ prompt = typeof step.promptTemplate === "string" ? step.promptTemplate : step.promptTemplate(input);
503
+ } catch (err) {
504
+ return {
505
+ stepId: step.id,
506
+ kind: "agent",
507
+ status: "failed",
508
+ attempts: 0,
509
+ durationMs: Date.now() - startedAt,
510
+ error: errToShape(err)
511
+ };
512
+ }
513
+ if (typeof prompt !== "string" || prompt.length === 0) {
514
+ return {
515
+ stepId: step.id,
516
+ kind: "agent",
517
+ status: "failed",
518
+ attempts: 0,
519
+ durationMs: Date.now() - startedAt,
520
+ error: errToShape(
521
+ new Error(`agentStep "${step.id}": rendered prompt must be a non-empty string`)
522
+ )
523
+ };
524
+ }
525
+ const exec = async () => {
526
+ const run = await step.agent.send(prompt);
527
+ const result = await run.wait();
528
+ if (result.status === "finished") {
529
+ return result.result ?? "";
530
+ }
531
+ if (result.status === "error") {
532
+ throw result.error ?? new Error("agent.send errored");
533
+ }
534
+ throw new Error(`Unexpected agent status: ${result.status}`);
535
+ };
536
+ try {
537
+ const { value, attempts } = step.retry !== void 0 ? await withRetry(exec, step.retry, ctx.signal) : { value: await exec(), attempts: 1 };
538
+ return {
539
+ stepId: step.id,
540
+ kind: "agent",
541
+ status: "completed",
542
+ attempts,
543
+ durationMs: Date.now() - startedAt,
544
+ output: value
545
+ };
546
+ } catch (err) {
547
+ if (err instanceof WorkflowSuspendedSentinel) throw err;
548
+ return {
549
+ stepId: step.id,
550
+ kind: "agent",
551
+ status: "failed",
552
+ attempts: 1,
553
+ durationMs: Date.now() - startedAt,
554
+ error: errToShape(err)
555
+ };
556
+ }
557
+ }
558
+ var init_step_agent = __esm({
559
+ "src/internal/workflow/step-agent.ts"() {
560
+ init_errors();
561
+ init_ctx();
562
+ init_error_shape();
563
+ init_retry_policy();
564
+ }
565
+ });
566
+
567
+ // src/internal/security/redact.ts
568
+ function readEnvOnce() {
569
+ const raw = process.env.THEOKIT_REDACT_SECRETS;
570
+ if (raw === void 0) return true;
571
+ return ["1", "true", "yes", "on"].includes(raw.toLowerCase());
572
+ }
573
+ function maskToken(token) {
574
+ if (token.length < 18) return "***";
575
+ return `${token.slice(0, 6)}...${token.slice(-4)}`;
576
+ }
577
+ function coerceToString(value) {
578
+ if (typeof value === "string") return value;
579
+ if (value === null || value === void 0) return null;
580
+ if (typeof value === "object") {
581
+ try {
582
+ const s = JSON.stringify(value);
583
+ return s === void 0 ? null : s;
584
+ } catch {
585
+ return "[unredactable: circular]";
586
+ }
587
+ }
588
+ return String(value);
589
+ }
590
+ function redactSecrets(text, opts) {
591
+ const coerced = coerceToString(text);
592
+ if (coerced === null) return "";
593
+ if (!REDACT_ENABLED) return coerced;
594
+ let s = coerced;
595
+ for (const re of BUILTIN_PATTERNS) {
596
+ s = s.replace(re, (m) => maskToken(m));
597
+ }
598
+ for (const re of _extraPatterns) {
599
+ s = s.replace(re, (m) => maskToken(m));
600
+ }
601
+ {
602
+ s = s.replace(BEARER_PATTERN, (_, prefix) => `${prefix}***`);
603
+ s = s.replace(PARAM_PATTERN, (_, prefix) => `${prefix}***`);
604
+ }
605
+ return s;
606
+ }
607
+ var REDACT_ENABLED, warnedOptOut, BUILTIN_PATTERNS, BEARER_PATTERN, PARAM_PATTERN, _extraPatterns;
608
+ var init_redact = __esm({
609
+ "src/internal/security/redact.ts"() {
610
+ REDACT_ENABLED = readEnvOnce();
611
+ warnedOptOut = false;
612
+ if (!REDACT_ENABLED && !warnedOptOut) {
613
+ process.stderr.write(
614
+ "[theokit-sdk] Secret redaction is DISABLED via THEOKIT_REDACT_SECRETS. Credentials may leak into errors, telemetry, logs, transcripts.\n"
615
+ );
616
+ warnedOptOut = true;
617
+ }
618
+ BUILTIN_PATTERNS = [
619
+ /sk-ant-[A-Za-z0-9_-]{10,}/g,
620
+ // Anthropic
621
+ /sk-proj-[A-Za-z0-9_-]{10,}/g,
622
+ // OpenAI project key (must precede sk- generic)
623
+ /sk-[A-Za-z0-9_-]{10,}/g,
624
+ // OpenAI / OpenRouter / DeepInfra. {10,} body floor —
625
+ // real keys are 40+ chars; 10-char floor still skips `sk-test` (4) and
626
+ // `sk-test-key` (8). codeFile mode protects placeholders/examples.
627
+ /ghp_[A-Za-z0-9]{36}/g,
628
+ // GitHub PAT classic (exact length)
629
+ /github_pat_[A-Za-z0-9_]{82}/g,
630
+ // GitHub PAT fine-grained
631
+ /glpat-[A-Za-z0-9_-]{20}/g,
632
+ // GitLab PAT
633
+ /AKIA[A-Z0-9]{16}/g,
634
+ // AWS access key
635
+ /AIza[A-Za-z0-9_-]{35}/g,
636
+ // Google API key
637
+ /xox[bpasr]-[A-Za-z0-9-]{10,}/g,
638
+ //Slack tokens
639
+ /sntrys_[A-Za-z0-9]{40,}/g,
640
+ // Sentry user auth
641
+ /sk_live_[A-Za-z0-9]{20,}/g,
642
+ // Stripe secret
643
+ /rk_live_[A-Za-z0-9]{20,}/g
644
+ // Stripe restricted
645
+ ];
646
+ BEARER_PATTERN = /\b(Bearer\s+)([A-Za-z0-9_\-.+/=]{8,})/g;
647
+ PARAM_PATTERN = /(\b(?:access_token|api_key|api-key|password|secret|x-api-key)\b["']?\s*[:=]\s*["']?)([A-Za-z0-9_\-.+/]+)/gi;
648
+ _extraPatterns = [];
649
+ }
650
+ });
651
+
652
+ // src/internal/workflow/step-branch.ts
653
+ async function runBranchStep(step, input, ctx, options, prevStepResults, dispatch) {
654
+ const startedAt = Date.now();
655
+ for (let i = 0; i < step.predicates.length; i += 1) {
656
+ const pair = step.predicates[i];
657
+ const [predicate, branch] = pair;
658
+ let matched = false;
659
+ try {
660
+ matched = await Promise.resolve(predicate(input));
661
+ } catch (err) {
662
+ const errText = err instanceof Error ? err.message : String(err);
663
+ console.warn(
664
+ redactSecrets(
665
+ `[workflow] branch "${step.id}" predicate ${i} threw, treating as no-match: ${errText}`
666
+ )
667
+ );
668
+ }
669
+ if (matched) {
670
+ const r = await runInnerSequence(branch, input, ctx, options, prevStepResults, dispatch);
671
+ return {
672
+ ...r,
673
+ stepId: step.id,
674
+ kind: "branch",
675
+ durationMs: Date.now() - startedAt
676
+ };
677
+ }
678
+ }
679
+ if (step.fallback !== void 0) {
680
+ const r = await runInnerSequence(step.fallback, input, ctx, options, prevStepResults, dispatch);
681
+ return {
682
+ ...r,
683
+ stepId: step.id,
684
+ kind: "branch",
685
+ durationMs: Date.now() - startedAt
686
+ };
687
+ }
688
+ return {
689
+ stepId: step.id,
690
+ kind: "branch",
691
+ status: "skipped",
692
+ attempts: 0,
693
+ durationMs: Date.now() - startedAt,
694
+ output: input
695
+ };
696
+ }
697
+ async function runInnerSequence(branch, input, ctx, options, prevStepResults, dispatch) {
698
+ let acc = input;
699
+ let lastAttempts = 1;
700
+ for (const inner of branch) {
701
+ const r = await dispatch(inner, acc, ctx, options, prevStepResults);
702
+ lastAttempts = r.attempts;
703
+ if (r.status === "failed") {
704
+ return {
705
+ stepId: inner.id,
706
+ kind: "branch",
707
+ status: "failed",
708
+ attempts: r.attempts,
709
+ durationMs: 0,
710
+ error: r.error ?? errToShape(new Error("branch inner step failed"))
711
+ };
712
+ }
713
+ acc = r.output;
714
+ }
715
+ return {
716
+ stepId: "__branch-completed__",
717
+ kind: "branch",
718
+ status: "completed",
719
+ attempts: lastAttempts,
720
+ durationMs: 0,
721
+ output: acc
722
+ };
723
+ }
724
+ var init_step_branch = __esm({
725
+ "src/internal/workflow/step-branch.ts"() {
726
+ init_redact();
727
+ init_error_shape();
728
+ }
729
+ });
730
+
731
+ // src/internal/workflow/step-dowhile.ts
732
+ async function runDowhileStep(step, input, ctx, options, prevStepResults, dispatch) {
733
+ const startedAt = Date.now();
734
+ const maxIter = step.maxIterations ?? 100;
735
+ let acc = input;
736
+ let i = 0;
737
+ while (true) {
738
+ if (i >= maxIter) {
739
+ return {
740
+ stepId: step.id,
741
+ kind: "dowhile",
742
+ status: "failed",
743
+ attempts: i,
744
+ durationMs: Date.now() - startedAt,
745
+ error: errToShape(new exports.WorkflowMaxIterationsExceededError(step.id, maxIter))
746
+ };
747
+ }
748
+ const r = await dispatch(step.step, acc, ctx, options, prevStepResults);
749
+ if (r.status === "failed") {
750
+ return {
751
+ stepId: step.id,
752
+ kind: "dowhile",
753
+ status: "failed",
754
+ attempts: i + 1,
755
+ durationMs: Date.now() - startedAt,
756
+ error: r.error
757
+ };
758
+ }
759
+ acc = r.output;
760
+ i += 1;
761
+ let shouldContinue = false;
762
+ try {
763
+ shouldContinue = await Promise.resolve(step.condFn(acc, i));
764
+ } catch (err) {
765
+ return {
766
+ stepId: step.id,
767
+ kind: "dowhile",
768
+ status: "failed",
769
+ attempts: i,
770
+ durationMs: Date.now() - startedAt,
771
+ error: errToShape(err)
772
+ };
773
+ }
774
+ if (!shouldContinue) break;
775
+ }
776
+ return {
777
+ stepId: step.id,
778
+ kind: "dowhile",
779
+ status: "completed",
780
+ attempts: i,
781
+ durationMs: Date.now() - startedAt,
782
+ output: acc
783
+ };
784
+ }
785
+ var init_step_dowhile = __esm({
786
+ "src/internal/workflow/step-dowhile.ts"() {
787
+ init_workflow();
788
+ init_error_shape();
789
+ }
790
+ });
791
+
792
+ // src/internal/workflow/step-fn.ts
793
+ function failedFnResult(stepId, attempts, startedAt, err) {
794
+ return {
795
+ stepId,
796
+ kind: "fn",
797
+ status: "failed",
798
+ attempts,
799
+ durationMs: Date.now() - startedAt,
800
+ error: errToShape(err)
801
+ };
802
+ }
803
+ function validate(schema, value) {
804
+ if (schema === void 0) return void 0;
805
+ schema.parse(value);
806
+ return void 0;
807
+ }
808
+ async function execWithRetry(step, input, ctx) {
809
+ const exec = async () => step.fn(input, ctx);
810
+ if (step.retry !== void 0) return withRetry(exec, step.retry, ctx.signal);
811
+ return { value: await exec(), attempts: 1 };
812
+ }
813
+ async function runFnStep(step, input, ctx) {
814
+ const startedAt = Date.now();
815
+ if (step.compensate !== void 0) {
816
+ return failedFnResult(
817
+ step.id,
818
+ 0,
819
+ startedAt,
820
+ new exports.WorkflowCompensateNotImplementedError(step.id)
821
+ );
822
+ }
823
+ try {
824
+ validate(step.inputSchema, input);
825
+ } catch (err) {
826
+ return failedFnResult(step.id, 0, startedAt, err);
827
+ }
828
+ try {
829
+ const { value, attempts } = await execWithRetry(step, input, ctx);
830
+ try {
831
+ validate(step.outputSchema, value);
832
+ } catch (err) {
833
+ return failedFnResult(step.id, attempts, startedAt, err);
834
+ }
835
+ return {
836
+ stepId: step.id,
837
+ kind: "fn",
838
+ status: "completed",
839
+ attempts,
840
+ durationMs: Date.now() - startedAt,
841
+ output: value
842
+ };
843
+ } catch (err) {
844
+ if (err instanceof WorkflowSuspendedSentinel) throw err;
845
+ return failedFnResult(step.id, 1, startedAt, err);
846
+ }
847
+ }
848
+ var init_step_fn = __esm({
849
+ "src/internal/workflow/step-fn.ts"() {
850
+ init_workflow();
851
+ init_ctx();
852
+ init_error_shape();
853
+ init_retry_policy();
854
+ }
855
+ });
856
+
857
+ // src/internal/runtime/async-semaphore.ts
858
+ function createSemaphore(permits) {
859
+ if (!Number.isInteger(permits) || permits < 1) {
860
+ throw new ConfigurationError(
861
+ `async-semaphore: permits must be a positive integer, got ${permits}`,
862
+ { code: "invalid_concurrency" }
863
+ );
864
+ }
865
+ let active = 0;
866
+ const queue = [];
867
+ function tryGrant() {
868
+ if (active < permits && queue.length > 0) {
869
+ const resolve2 = queue.shift();
870
+ if (resolve2 !== void 0) {
871
+ active += 1;
872
+ resolve2();
873
+ }
874
+ }
875
+ }
876
+ return {
877
+ inFlight: () => active,
878
+ pending: () => queue.length + active,
879
+ async acquire() {
880
+ await new Promise((resolve2) => {
881
+ queue.push(resolve2);
882
+ tryGrant();
883
+ });
884
+ let released = false;
885
+ return () => {
886
+ if (released) return;
887
+ released = true;
888
+ active -= 1;
889
+ tryGrant();
890
+ };
891
+ }
892
+ };
893
+ }
894
+ var init_async_semaphore = __esm({
895
+ "src/internal/runtime/async-semaphore.ts"() {
896
+ init_errors();
897
+ }
898
+ });
899
+
900
+ // src/internal/workflow/step-foreach.ts
901
+ async function runForeachStep(step, _input, ctx, options, prevStepResults, dispatch) {
902
+ const startedAt = Date.now();
903
+ const sourceResult = prevStepResults.find((r) => r.stepId === step.iterableFrom);
904
+ if (sourceResult === void 0) {
905
+ return {
906
+ stepId: step.id,
907
+ kind: "foreach",
908
+ status: "failed",
909
+ attempts: 0,
910
+ durationMs: Date.now() - startedAt,
911
+ error: errToShape(
912
+ new Error(
913
+ `foreach.iterableFrom "${step.iterableFrom}" not found in top-level steps. It must reference an earlier top-level step ID \u2014 nested step IDs inside parallel/branch/foreach blocks are not visible here.`
914
+ )
915
+ )
916
+ };
917
+ }
918
+ const items = sourceResult.output;
919
+ if (!Array.isArray(items)) {
920
+ return {
921
+ stepId: step.id,
922
+ kind: "foreach",
923
+ status: "failed",
924
+ attempts: 0,
925
+ durationMs: Date.now() - startedAt,
926
+ error: errToShape(
927
+ new Error(
928
+ `foreach.iterableFrom "${step.iterableFrom}" output must be Array, got ${typeof items}.`
929
+ )
930
+ )
931
+ };
932
+ }
933
+ if (items.length === 0) {
934
+ return {
935
+ stepId: step.id,
936
+ kind: "foreach",
937
+ status: "completed",
938
+ attempts: 1,
939
+ durationMs: Date.now() - startedAt,
940
+ output: []
941
+ };
942
+ }
943
+ const concurrency = step.concurrency ?? 4;
944
+ const sem = createSemaphore(Math.max(1, Math.min(concurrency, items.length)));
945
+ const failures = [];
946
+ const outputs = new Array(items.length);
947
+ await Promise.all(
948
+ items.map(async (item, idx) => {
949
+ const release = await sem.acquire();
950
+ try {
951
+ const r = await dispatch(step.step, item, ctx, options, prevStepResults);
952
+ if (r.status === "failed") {
953
+ failures.push(new Error(`foreach item ${idx} failed: ${r.error?.message ?? "unknown"}`));
954
+ } else {
955
+ outputs[idx] = r.output;
956
+ }
957
+ } finally {
958
+ release();
959
+ }
960
+ })
961
+ );
962
+ if (failures.length > 0) {
963
+ return {
964
+ stepId: step.id,
965
+ kind: "foreach",
966
+ status: "failed",
967
+ attempts: 1,
968
+ durationMs: Date.now() - startedAt,
969
+ error: errToShape(
970
+ new AggregateError(failures, `foreach "${step.id}" had ${failures.length} failure(s)`)
971
+ )
972
+ };
973
+ }
974
+ return {
975
+ stepId: step.id,
976
+ kind: "foreach",
977
+ status: "completed",
978
+ attempts: 1,
979
+ durationMs: Date.now() - startedAt,
980
+ output: outputs
981
+ };
982
+ }
983
+ var init_step_foreach = __esm({
984
+ "src/internal/workflow/step-foreach.ts"() {
985
+ init_async_semaphore();
986
+ init_error_shape();
987
+ }
988
+ });
989
+
990
+ // src/internal/workflow/step-parallel.ts
991
+ async function runParallelStep(step, input, ctx, options, _prevStepResults, dispatch) {
992
+ const startedAt = Date.now();
993
+ const policy = step.errorPolicy ?? "fail-fast";
994
+ const branchCount = step.branches.length;
995
+ if (branchCount === 0) {
996
+ return {
997
+ stepId: step.id,
998
+ kind: "parallel",
999
+ status: "completed",
1000
+ attempts: 1,
1001
+ durationMs: Date.now() - startedAt,
1002
+ output: []
1003
+ };
1004
+ }
1005
+ const concurrency = step.concurrency ?? branchCount;
1006
+ const sem = createSemaphore(Math.max(1, Math.min(concurrency, branchCount)));
1007
+ const failFastCtrl = policy === "fail-fast" ? new AbortController() : void 0;
1008
+ const branchSignal = policy === "fail-fast" ? mergeSignals(ctx.signal, failFastCtrl.signal) : ctx.signal;
1009
+ const semBranchPromises = step.branches.map(async (branch, branchIdx) => {
1010
+ const release = await sem.acquire();
1011
+ try {
1012
+ return await runBranch(
1013
+ branch,
1014
+ input,
1015
+ { ...ctx, signal: branchSignal },
1016
+ options,
1017
+ dispatch,
1018
+ branchIdx
1019
+ );
1020
+ } finally {
1021
+ release();
1022
+ }
1023
+ });
1024
+ if (policy === "fail-fast") {
1025
+ try {
1026
+ const outputs2 = await Promise.all(semBranchPromises);
1027
+ return {
1028
+ stepId: step.id,
1029
+ kind: "parallel",
1030
+ status: "completed",
1031
+ attempts: 1,
1032
+ durationMs: Date.now() - startedAt,
1033
+ output: outputs2
1034
+ };
1035
+ } catch (err) {
1036
+ failFastCtrl?.abort(err);
1037
+ const settled2 = await Promise.allSettled(semBranchPromises);
1038
+ const errors = settled2.filter((s) => s.status === "rejected").map((s) => s.reason instanceof Error ? s.reason : new Error(String(s.reason)));
1039
+ return {
1040
+ stepId: step.id,
1041
+ kind: "parallel",
1042
+ status: "failed",
1043
+ attempts: 1,
1044
+ durationMs: Date.now() - startedAt,
1045
+ error: errToShape(new exports.WorkflowParallelError(errors, step.id)),
1046
+ output: void 0
1047
+ };
1048
+ }
1049
+ }
1050
+ const settled = await Promise.allSettled(semBranchPromises);
1051
+ const outputs = settled.map(
1052
+ (s) => s.status === "fulfilled" ? { ok: true, value: s.value } : { ok: false, error: errToShape(s.reason) }
1053
+ );
1054
+ return {
1055
+ stepId: step.id,
1056
+ kind: "parallel",
1057
+ status: "completed",
1058
+ attempts: 1,
1059
+ durationMs: Date.now() - startedAt,
1060
+ output: outputs
1061
+ };
1062
+ }
1063
+ async function runBranch(branch, input, ctx, options, dispatch, branchIdx) {
1064
+ let acc = input;
1065
+ for (const inner of branch) {
1066
+ const r = await dispatch(inner, acc, ctx, options, []);
1067
+ if (r.status === "failed") {
1068
+ throw new Error(
1069
+ `parallel branch ${branchIdx} step "${inner.id}" failed: ${r.error?.message ?? "unknown"}`
1070
+ );
1071
+ }
1072
+ acc = r.output;
1073
+ }
1074
+ return acc;
1075
+ }
1076
+ function mergeSignals(a, b) {
1077
+ if (a.aborted) return a;
1078
+ if (b.aborted) return b;
1079
+ const ctrl = new AbortController();
1080
+ const onAbortA = () => ctrl.abort(a.reason);
1081
+ const onAbortB = () => ctrl.abort(b.reason);
1082
+ a.addEventListener("abort", onAbortA, { once: true });
1083
+ b.addEventListener("abort", onAbortB, { once: true });
1084
+ return ctrl.signal;
1085
+ }
1086
+ var init_step_parallel = __esm({
1087
+ "src/internal/workflow/step-parallel.ts"() {
1088
+ init_workflow();
1089
+ init_async_semaphore();
1090
+ init_error_shape();
1091
+ }
1092
+ });
1093
+
1094
+ // src/internal/workflow/step-sleep.ts
1095
+ async function runSleepStep(step, input, ctx) {
1096
+ const startedAt = Date.now();
1097
+ try {
1098
+ await abortableSleep(step.durationMs, ctx.signal);
1099
+ return {
1100
+ stepId: step.id,
1101
+ kind: "sleep",
1102
+ status: "completed",
1103
+ attempts: 1,
1104
+ durationMs: Date.now() - startedAt,
1105
+ output: input
1106
+ // sleep is a pass-through
1107
+ };
1108
+ } catch (err) {
1109
+ return {
1110
+ stepId: step.id,
1111
+ kind: "sleep",
1112
+ status: "failed",
1113
+ attempts: 1,
1114
+ durationMs: Date.now() - startedAt,
1115
+ error: errToShape(err)
1116
+ };
1117
+ }
1118
+ }
1119
+ var init_step_sleep = __esm({
1120
+ "src/internal/workflow/step-sleep.ts"() {
1121
+ init_error_shape();
1122
+ init_retry_policy();
1123
+ }
1124
+ });
1125
+ function getTracer(name, version = "1.0.0") {
1126
+ const cached = tracerCache.get(name);
1127
+ if (cached !== void 0) return cached.tracer ?? void 0;
1128
+ try {
1129
+ const r = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('workflow.cjs', document.baseURI).href)));
1130
+ const otel = r("@opentelemetry/api");
1131
+ if (otel.trace?.getTracer === void 0) {
1132
+ tracerCache.set(name, { tracer: null });
1133
+ return void 0;
1134
+ }
1135
+ const tracer = otel.trace.getTracer(name, version);
1136
+ tracerCache.set(name, { tracer });
1137
+ return tracer;
1138
+ } catch {
1139
+ tracerCache.set(name, { tracer: null });
1140
+ return void 0;
1141
+ }
1142
+ }
1143
+ var noopSpan, tracerCache;
1144
+ var init_tracer_loader = __esm({
1145
+ "src/internal/observability/tracer-loader.ts"() {
1146
+ noopSpan = {
1147
+ setAttribute: () => noopSpan,
1148
+ end: () => void 0
1149
+ };
1150
+ tracerCache = /* @__PURE__ */ new Map();
1151
+ }
1152
+ });
1153
+
1154
+ // src/internal/workflow/telemetry.ts
1155
+ function startWorkflowRunSpan(info) {
1156
+ const tracer = getTracer(TRACER_NAME);
1157
+ if (tracer === void 0) return noopSpan;
1158
+ return tracer.startSpan("workflow.run", {
1159
+ attributes: {
1160
+ "workflow.name": info.workflowName,
1161
+ "workflow.run_id": info.runId
1162
+ }
1163
+ });
1164
+ }
1165
+ function startWorkflowStepSpan(info) {
1166
+ const tracer = getTracer(TRACER_NAME);
1167
+ if (tracer === void 0) return noopSpan;
1168
+ return tracer.startSpan(`workflow.step.${info.stepId}`, {
1169
+ attributes: {
1170
+ "step.id": info.stepId,
1171
+ "step.kind": info.kind,
1172
+ "step.attempt": info.attempt
1173
+ }
1174
+ });
1175
+ }
1176
+ var TRACER_NAME;
1177
+ var init_telemetry = __esm({
1178
+ "src/internal/workflow/telemetry.ts"() {
1179
+ init_tracer_loader();
1180
+ TRACER_NAME = "@theokit/sdk/workflow";
1181
+ }
1182
+ });
1183
+
1184
+ // src/internal/workflow/executor.ts
1185
+ var executor_exports = {};
1186
+ __export(executor_exports, {
1187
+ dispatchStep: () => dispatchStep,
1188
+ executeWorkflow: () => executeWorkflow,
1189
+ resumeWorkflow: () => resumeWorkflow
1190
+ });
1191
+ async function handleSuspend(err, ctx) {
1192
+ try {
1193
+ await saveSnapshot({
1194
+ runId: ctx.runId,
1195
+ workflowName: ctx.options.name,
1196
+ currentStepId: ctx.step.id,
1197
+ suspendedPayload: err.payload,
1198
+ stepResults: ctx.stepResults,
1199
+ accumulatedInput: ctx.acc,
1200
+ options: ctx.options
1201
+ });
1202
+ } catch (snapErr) {
1203
+ ctx.stepSpan.setAttribute("step.status", "failed");
1204
+ ctx.stepSpan.end();
1205
+ return {
1206
+ kind: "failed",
1207
+ run: assembleRun({
1208
+ runId: ctx.runId,
1209
+ name: ctx.name,
1210
+ status: "failed",
1211
+ stepResults: ctx.stepResults,
1212
+ startedAt: ctx.startedAt,
1213
+ error: errToShape(snapErr)
1214
+ })
1215
+ };
1216
+ }
1217
+ ctx.stepSpan.setAttribute("step.status", "suspended");
1218
+ ctx.stepSpan.end();
1219
+ return {
1220
+ kind: "suspended",
1221
+ run: assembleRun({
1222
+ runId: ctx.runId,
1223
+ name: ctx.name,
1224
+ status: "suspended",
1225
+ stepResults: [
1226
+ ...ctx.stepResults,
1227
+ {
1228
+ stepId: ctx.step.id,
1229
+ kind: ctx.step.kind,
1230
+ status: "suspended",
1231
+ attempts: 1,
1232
+ durationMs: 0,
1233
+ output: void 0
1234
+ }
1235
+ ],
1236
+ startedAt: ctx.startedAt
1237
+ })
1238
+ };
1239
+ }
1240
+ async function runOneStep(args) {
1241
+ const stepSpan = startWorkflowStepSpan({
1242
+ stepId: args.step.id,
1243
+ kind: args.step.kind,
1244
+ attempt: 1
1245
+ });
1246
+ let result;
1247
+ try {
1248
+ result = await dispatchStep(args.step, args.acc, args.ctx, args.options, args.stepResults);
1249
+ } catch (err) {
1250
+ if (err instanceof WorkflowSuspendedSentinel) {
1251
+ const outcome = await handleSuspend(err, { ...args, stepSpan });
1252
+ return { kind: "terminal", run: outcome.run };
1253
+ }
1254
+ result = {
1255
+ stepId: args.step.id,
1256
+ kind: args.step.kind,
1257
+ status: "failed",
1258
+ attempts: 1,
1259
+ durationMs: 0,
1260
+ error: errToShape(err)
1261
+ };
1262
+ }
1263
+ stepSpan.setAttribute("step.status", result.status);
1264
+ stepSpan.setAttribute("step.attempts", result.attempts);
1265
+ stepSpan.end();
1266
+ return { kind: "ok", result };
1267
+ }
1268
+ function abortRun(name, runId, startedAt, stepResults, signal) {
1269
+ return assembleRun({
1270
+ runId,
1271
+ name,
1272
+ status: "cancelled",
1273
+ stepResults,
1274
+ startedAt,
1275
+ error: { name: "AbortError", message: String(signal.reason ?? "Aborted") }
1276
+ });
1277
+ }
1278
+ async function runStepsLoop(params) {
1279
+ const { options, steps, ctx, runId, startedAt, signal } = params;
1280
+ const stepResults = [];
1281
+ let acc = params.input;
1282
+ for (const step of steps) {
1283
+ if (signal.aborted) return abortRun(options.name, runId, startedAt, stepResults, signal);
1284
+ const outcome = await runOneStep({
1285
+ step,
1286
+ acc,
1287
+ ctx,
1288
+ options,
1289
+ stepResults,
1290
+ runId,
1291
+ name: options.name,
1292
+ startedAt
1293
+ });
1294
+ if (outcome.kind === "terminal") return outcome.run;
1295
+ stepResults.push(outcome.result);
1296
+ if (outcome.result.status === "failed") {
1297
+ return assembleRun({
1298
+ runId,
1299
+ name: options.name,
1300
+ status: "failed",
1301
+ stepResults,
1302
+ startedAt,
1303
+ error: outcome.result.error
1304
+ });
1305
+ }
1306
+ acc = outcome.result.output;
1307
+ }
1308
+ return assembleRun({
1309
+ runId,
1310
+ name: options.name,
1311
+ status: "completed",
1312
+ output: acc,
1313
+ stepResults,
1314
+ startedAt
1315
+ });
1316
+ }
1317
+ async function executeWorkflow(options, steps, input, runOpts) {
1318
+ const runId = runOpts?.runId ?? mintRunId();
1319
+ const workflowId = options.workflowId ?? `wf-anon`;
1320
+ const flight = acquireSingleFlight(workflowId, runId, options.name);
1321
+ const startedAt = Date.now();
1322
+ const signal = combineSignals(runOpts?.signal, flight.signal);
1323
+ const runSpan = startWorkflowRunSpan({ workflowName: options.name, runId });
1324
+ if (signal.aborted) {
1325
+ flight.release();
1326
+ runSpan.setAttribute("workflow.status", "cancelled");
1327
+ runSpan.end();
1328
+ return abortRun(options.name, runId, startedAt, [], signal);
1329
+ }
1330
+ const ctx = makeStepContext(runId, signal);
1331
+ try {
1332
+ return await runStepsLoop({
1333
+ options,
1334
+ steps,
1335
+ input,
1336
+ ctx,
1337
+ runId,
1338
+ startedAt,
1339
+ signal
1340
+ });
1341
+ } finally {
1342
+ runSpan.end();
1343
+ flight.release();
1344
+ }
1345
+ }
1346
+ async function dispatchStep(step, input, ctx, options, prevStepResults) {
1347
+ switch (step.kind) {
1348
+ case "fn":
1349
+ return runFnStep(step, input, ctx);
1350
+ case "agent":
1351
+ return runAgentStep(step, input, ctx);
1352
+ case "parallel":
1353
+ return runParallelStep(step, input, ctx, options, prevStepResults, dispatchStep);
1354
+ case "branch":
1355
+ return runBranchStep(step, input, ctx, options, prevStepResults, dispatchStep);
1356
+ case "foreach":
1357
+ return runForeachStep(step, input, ctx, options, prevStepResults, dispatchStep);
1358
+ case "dowhile":
1359
+ return runDowhileStep(step, input, ctx, options, prevStepResults, dispatchStep);
1360
+ case "sleep":
1361
+ return runSleepStep(step, input, ctx);
1362
+ case "suspend":
1363
+ throw new WorkflowSuspendedSentinel(void 0);
1364
+ default: {
1365
+ const _exhaustive = step;
1366
+ throw new Error(`Unknown step kind: ${_exhaustive.kind}`);
1367
+ }
1368
+ }
1369
+ }
1370
+ function assembleRun(params) {
1371
+ const endedAt = Date.now();
1372
+ return {
1373
+ id: params.runId,
1374
+ name: params.name,
1375
+ status: params.status,
1376
+ startedAt: params.startedAt,
1377
+ endedAt,
1378
+ stepResults: params.stepResults,
1379
+ ...params.output !== void 0 ? { output: params.output } : {},
1380
+ ...params.error !== void 0 ? { error: params.error } : {}
1381
+ };
1382
+ }
1383
+ async function saveSnapshot(p) {
1384
+ const snapshot = {
1385
+ _schemaVersion: 1,
1386
+ runId: p.runId,
1387
+ workflowName: p.workflowName,
1388
+ currentStepId: p.currentStepId,
1389
+ suspendedPayload: p.suspendedPayload,
1390
+ stepResults: p.stepResults,
1391
+ accumulatedInput: p.accumulatedInput,
1392
+ suspendedAt: Date.now()
1393
+ };
1394
+ const store = getSnapshotStoreFor(p.options);
1395
+ await store.save(snapshot);
1396
+ }
1397
+ async function resumeWorkflow(opts) {
1398
+ const wfInternal = opts.workflow;
1399
+ const options = wfInternal.__options;
1400
+ const steps = wfInternal.__steps;
1401
+ if (options === void 0 || steps === void 0) {
1402
+ throw new Error("Workflow.resume requires an instance from Workflow.create().commit()");
1403
+ }
1404
+ const store = getSnapshotStoreFor(options);
1405
+ const snapshot = await store.load(opts.runId);
1406
+ if (snapshot === void 0) {
1407
+ throw new exports.WorkflowSnapshotNotFoundError(opts.runId);
1408
+ }
1409
+ const stepIdx = steps.findIndex((s) => s.id === snapshot.currentStepId);
1410
+ if (stepIdx < 0) {
1411
+ throw new exports.WorkflowResumeStepNotFoundError(snapshot.currentStepId, snapshot.workflowName);
1412
+ }
1413
+ const suspendStep = steps[stepIdx];
1414
+ if (suspendStep !== void 0 && suspendStep.kind === "suspend" && suspendStep.payloadSchema !== void 0) {
1415
+ suspendStep.payloadSchema.parse(opts.payload);
1416
+ }
1417
+ const resumeInput = opts.payload !== void 0 ? opts.payload : snapshot.accumulatedInput;
1418
+ const remainingSteps = steps.slice(stepIdx + 1);
1419
+ await store.delete(opts.runId);
1420
+ return executeWorkflow(options, remainingSteps, resumeInput, {
1421
+ signal: opts.signal,
1422
+ runId: opts.runId
1423
+ });
1424
+ }
1425
+ var init_executor = __esm({
1426
+ "src/internal/workflow/executor.ts"() {
1427
+ init_workflow();
1428
+ init_ctx();
1429
+ init_error_shape();
1430
+ init_run_id();
1431
+ init_single_flight();
1432
+ init_snapshot_store();
1433
+ init_step_agent();
1434
+ init_step_branch();
1435
+ init_step_dowhile();
1436
+ init_step_fn();
1437
+ init_step_foreach();
1438
+ init_step_parallel();
1439
+ init_step_sleep();
1440
+ init_telemetry();
1441
+ }
1442
+ });
1443
+
1444
+ // src/types/task.ts
1445
+ function isValidTaskId(id, allowReserved) {
1446
+ if (!TASK_ID_GRAMMAR.test(id)) return false;
1447
+ if (allowReserved) return true;
1448
+ for (const prefix of RESERVED_PREFIXES) {
1449
+ if (id.startsWith(prefix)) return false;
1450
+ }
1451
+ return true;
1452
+ }
1453
+ var TASK_ID_GRAMMAR, RESERVED_PREFIXES;
1454
+ var init_task = __esm({
1455
+ "src/types/task.ts"() {
1456
+ TASK_ID_GRAMMAR = /^[a-z0-9][a-z0-9_-]*$/;
1457
+ RESERVED_PREFIXES = ["wf-", "b-", "cron-"];
1458
+ }
1459
+ });
1460
+
1461
+ // src/internal/task/ring-buffer.ts
1462
+ var RingBuffer;
1463
+ var init_ring_buffer = __esm({
1464
+ "src/internal/task/ring-buffer.ts"() {
1465
+ RingBuffer = class {
1466
+ constructor(cap) {
1467
+ this.cap = cap;
1468
+ if (!Number.isInteger(cap) || cap < 1) {
1469
+ throw new Error(`RingBuffer capacity must be a positive integer, got ${cap}`);
1470
+ }
1471
+ }
1472
+ cap;
1473
+ buf = [];
1474
+ truncated = false;
1475
+ push(item) {
1476
+ if (this.buf.length >= this.cap) {
1477
+ this.buf.shift();
1478
+ this.truncated = true;
1479
+ }
1480
+ this.buf.push(item);
1481
+ }
1482
+ drain() {
1483
+ return { items: this.buf.slice(), truncated: this.truncated };
1484
+ }
1485
+ size() {
1486
+ return this.buf.length;
1487
+ }
1488
+ wasTruncated() {
1489
+ return this.truncated;
1490
+ }
1491
+ };
1492
+ }
1493
+ });
1494
+ function assertValidIdForStore(id) {
1495
+ if (!isValidTaskId(
1496
+ id,
1497
+ /* allowReserved */
1498
+ true
1499
+ )) {
1500
+ throw new InvalidTaskIdError(`store rejects invalid task id: ${id}`, id);
1501
+ }
1502
+ }
1503
+ function terminalTimestamp(h) {
1504
+ if (h.state === "finished") return h.finishedAt;
1505
+ if (h.state === "error") return h.erroredAt;
1506
+ if (h.state === "cancelled") return h.cancelledAt;
1507
+ return void 0;
1508
+ }
1509
+ function isTerminal(state2) {
1510
+ return state2 === "finished" || state2 === "error" || state2 === "cancelled";
1511
+ }
1512
+ function matchesState(h, filter) {
1513
+ if (filter.state === void 0) return true;
1514
+ const states = Array.isArray(filter.state) ? filter.state : [filter.state];
1515
+ return states.includes(h.state);
1516
+ }
1517
+ function matchesKind(h, filter) {
1518
+ if (filter.kind === void 0) return true;
1519
+ const kinds = Array.isArray(filter.kind) ? filter.kind : [filter.kind];
1520
+ return kinds.includes(h.kind);
1521
+ }
1522
+ function matchesTime(h, filter) {
1523
+ if (filter.submittedAfter !== void 0 && h.submittedAt <= filter.submittedAfter) return false;
1524
+ if (filter.submittedBefore !== void 0 && h.submittedAt >= filter.submittedBefore) return false;
1525
+ return true;
1526
+ }
1527
+ function matchesFilter(h, filter) {
1528
+ return matchesState(h, filter) && matchesKind(h, filter) && matchesTime(h, filter);
1529
+ }
1530
+ function applyFilter(values, filter) {
1531
+ const limit = filter.limit ?? DEFAULT_LIST_LIMIT;
1532
+ const out = [];
1533
+ for (const h of values) {
1534
+ if (matchesFilter(h, filter)) {
1535
+ out.push(h);
1536
+ if (out.length >= limit) break;
1537
+ }
1538
+ }
1539
+ return out;
1540
+ }
1541
+ function getTaskStoreFor(options) {
1542
+ if (options.backend === "memory") return new InMemoryTaskStore();
1543
+ return new JsonFileTaskStore(options.dir);
1544
+ }
1545
+ var JSON_LOAD_CAP, DEFAULT_LIST_LIMIT, InMemoryTaskStore, JsonFileTaskStore;
1546
+ var init_store = __esm({
1547
+ "src/internal/task/store.ts"() {
1548
+ init_errors();
1549
+ init_task();
1550
+ init_atomic_write();
1551
+ JSON_LOAD_CAP = 256;
1552
+ DEFAULT_LIST_LIMIT = 100;
1553
+ InMemoryTaskStore = class {
1554
+ map = /* @__PURE__ */ new Map();
1555
+ async insert(handle) {
1556
+ assertValidIdForStore(handle.id);
1557
+ this.map.set(handle.id, handle);
1558
+ }
1559
+ async update(id, mutate) {
1560
+ assertValidIdForStore(id);
1561
+ const existing = this.map.get(id);
1562
+ if (existing === void 0) return void 0;
1563
+ const next = mutate(existing);
1564
+ this.map.set(id, next);
1565
+ return next;
1566
+ }
1567
+ async get(id) {
1568
+ assertValidIdForStore(id);
1569
+ return this.map.get(id);
1570
+ }
1571
+ async list(filter) {
1572
+ return applyFilter(this.map.values(), filter);
1573
+ }
1574
+ async delete(id) {
1575
+ assertValidIdForStore(id);
1576
+ return this.map.delete(id);
1577
+ }
1578
+ async evictTerminalOlderThan(epochMs) {
1579
+ let count = 0;
1580
+ for (const [id, h] of this.map.entries()) {
1581
+ if (!isTerminal(h.state)) continue;
1582
+ const ts = terminalTimestamp(h);
1583
+ if (ts !== void 0 && ts < epochMs) {
1584
+ this.map.delete(id);
1585
+ count++;
1586
+ }
1587
+ }
1588
+ return count;
1589
+ }
1590
+ };
1591
+ JsonFileTaskStore = class {
1592
+ constructor(dir) {
1593
+ this.dir = dir;
1594
+ try {
1595
+ fs.mkdirSync(dir, { recursive: true });
1596
+ } catch (err) {
1597
+ if (err.code !== "EEXIST") throw err;
1598
+ }
1599
+ }
1600
+ dir;
1601
+ filePath(id) {
1602
+ return path.join(this.dir, `${id}.json`);
1603
+ }
1604
+ async insert(handle) {
1605
+ assertValidIdForStore(handle.id);
1606
+ await atomicWriteText(this.filePath(handle.id), JSON.stringify(handle));
1607
+ }
1608
+ async update(id, mutate) {
1609
+ assertValidIdForStore(id);
1610
+ const existing = await this.get(id);
1611
+ if (existing === void 0) return void 0;
1612
+ const next = mutate(existing);
1613
+ await atomicWriteText(this.filePath(id), JSON.stringify(next));
1614
+ return next;
1615
+ }
1616
+ async get(id) {
1617
+ assertValidIdForStore(id);
1618
+ try {
1619
+ const raw = await promises.readFile(this.filePath(id), "utf8");
1620
+ return JSON.parse(raw);
1621
+ } catch (err) {
1622
+ const code = err.code;
1623
+ if (code === "ENOENT") return void 0;
1624
+ process.stderr.write(`[task-store] failed to read ${id}: ${err.message}
1625
+ `);
1626
+ return void 0;
1627
+ }
1628
+ }
1629
+ async list(filter) {
1630
+ let entries;
1631
+ try {
1632
+ entries = fs.readdirSync(this.dir);
1633
+ } catch (err) {
1634
+ if (err.code === "ENOENT") return [];
1635
+ throw err;
1636
+ }
1637
+ const candidates = entries.filter((name) => name.endsWith(".json") && !name.includes(".tmp")).slice(0, JSON_LOAD_CAP);
1638
+ const loaded = await Promise.all(
1639
+ candidates.map(async (name) => {
1640
+ const id = name.slice(0, -".json".length);
1641
+ if (!isValidTaskId(id, true)) return void 0;
1642
+ return this.get(id);
1643
+ })
1644
+ );
1645
+ const handles = loaded.filter((h) => h !== void 0);
1646
+ return applyFilter(handles, filter);
1647
+ }
1648
+ async delete(id) {
1649
+ assertValidIdForStore(id);
1650
+ try {
1651
+ await promises.unlink(this.filePath(id));
1652
+ return true;
1653
+ } catch (err) {
1654
+ if (err.code === "ENOENT") return false;
1655
+ throw err;
1656
+ }
1657
+ }
1658
+ async evictTerminalOlderThan(epochMs) {
1659
+ const handles = await this.list({ state: ["finished", "error", "cancelled"], limit: 256 });
1660
+ let count = 0;
1661
+ for (const h of handles) {
1662
+ const ts = terminalTimestamp(h);
1663
+ if (ts !== void 0 && ts < epochMs) {
1664
+ if (await this.delete(h.id)) count++;
1665
+ }
1666
+ }
1667
+ return count;
1668
+ }
1669
+ };
1670
+ }
1671
+ });
1672
+
1673
+ // src/internal/task/subscribe.ts
1674
+ function isTerminalEvent(event) {
1675
+ return event.type === "finished" || event.type === "errored" || event.type === "cancelled";
1676
+ }
1677
+ function drainBuffered(buffer) {
1678
+ const { items, truncated } = buffer.drain();
1679
+ const queue = items.slice();
1680
+ if (truncated && queue.length > 0) {
1681
+ const first = queue[0];
1682
+ if (first !== void 0 && first.type === "submitted") {
1683
+ queue[0] = { ...first, truncated: true };
1684
+ }
1685
+ }
1686
+ return queue;
1687
+ }
1688
+ function buildSubscribe(deps) {
1689
+ return function subscribe2(id) {
1690
+ if (!isValidTaskId(id, true)) throw new TaskNotFoundError(id);
1691
+ const buffer = deps.getBuffer(id);
1692
+ if (buffer === void 0) throw new TaskNotFoundError(id);
1693
+ return {
1694
+ [Symbol.asyncIterator]() {
1695
+ return new TaskIterator(buffer, id, deps);
1696
+ }
1697
+ };
1698
+ };
1699
+ }
1700
+ var TaskIterator;
1701
+ var init_subscribe = __esm({
1702
+ "src/internal/task/subscribe.ts"() {
1703
+ init_errors();
1704
+ init_task();
1705
+ TaskIterator = class {
1706
+ constructor(buffer, id, deps) {
1707
+ this.id = id;
1708
+ this.deps = deps;
1709
+ this.queue = drainBuffered(buffer);
1710
+ this.callback = (e) => this.deliver(e);
1711
+ deps.getOrCreateSubscriberSet(id).add(this.callback);
1712
+ }
1713
+ id;
1714
+ deps;
1715
+ queue;
1716
+ pendingResolve;
1717
+ done = false;
1718
+ callback;
1719
+ deliver(e) {
1720
+ if (this.done) return;
1721
+ if (this.pendingResolve !== void 0) {
1722
+ const r = this.pendingResolve;
1723
+ this.pendingResolve = void 0;
1724
+ r({ value: e, done: false });
1725
+ } else {
1726
+ this.queue.push(e);
1727
+ }
1728
+ }
1729
+ cleanup() {
1730
+ if (this.done) return;
1731
+ this.done = true;
1732
+ this.deps.removeSubscriber(this.id, this.callback);
1733
+ if (this.pendingResolve !== void 0) {
1734
+ const r = this.pendingResolve;
1735
+ this.pendingResolve = void 0;
1736
+ r({ value: void 0, done: true });
1737
+ }
1738
+ }
1739
+ dequeue() {
1740
+ const event = this.queue.shift();
1741
+ if (event === void 0) return void 0;
1742
+ if (isTerminalEvent(event)) queueMicrotask(() => this.cleanup());
1743
+ return { value: event, done: false };
1744
+ }
1745
+ next() {
1746
+ if (this.done) return Promise.resolve({ value: void 0, done: true });
1747
+ const queued = this.dequeue();
1748
+ if (queued !== void 0) return Promise.resolve(queued);
1749
+ return new Promise((resolve2) => {
1750
+ this.pendingResolve = resolve2;
1751
+ });
1752
+ }
1753
+ return() {
1754
+ this.cleanup();
1755
+ return Promise.resolve({ value: void 0, done: true });
1756
+ }
1757
+ };
1758
+ }
1759
+ });
1760
+
1761
+ // src/internal/task/telemetry.ts
1762
+ function startTaskSubmitSpan(info) {
1763
+ const tracer = getTracer(TRACER_NAME2);
1764
+ if (tracer === void 0) return noopSpan;
1765
+ return tracer.startSpan("task.submit", {
1766
+ attributes: {
1767
+ "task.id": info.taskId,
1768
+ "task.kind": info.kind
1769
+ }
1770
+ });
1771
+ }
1772
+ function startTaskTransitionSpan(info) {
1773
+ const tracer = getTracer(TRACER_NAME2);
1774
+ if (tracer === void 0) return noopSpan;
1775
+ return tracer.startSpan("task.transition", {
1776
+ attributes: {
1777
+ "task.id": info.taskId,
1778
+ "task.state.from": info.from,
1779
+ "task.state.to": info.to
1780
+ }
1781
+ });
1782
+ }
1783
+ function startTaskCancelSpan(info) {
1784
+ const tracer = getTracer(TRACER_NAME2);
1785
+ if (tracer === void 0) return noopSpan;
1786
+ return tracer.startSpan("task.cancel", {
1787
+ attributes: {
1788
+ "task.id": info.taskId,
1789
+ "task.cancel.via": info.via,
1790
+ ...info.reason !== void 0 ? { "task.cancel.reason": info.reason } : {}
1791
+ }
1792
+ });
1793
+ }
1794
+ var TRACER_NAME2;
1795
+ var init_telemetry2 = __esm({
1796
+ "src/internal/task/telemetry.ts"() {
1797
+ init_tracer_loader();
1798
+ TRACER_NAME2 = "@theokit/sdk/task";
1799
+ }
1800
+ });
1801
+
1802
+ // src/internal/task/registry.ts
1803
+ var registry_exports = {};
1804
+ __export(registry_exports, {
1805
+ __getCancelRequestedForTests: () => __getCancelRequestedForTests,
1806
+ __getSubscribersCountForTests: () => __getSubscribersCountForTests,
1807
+ __resetTaskRegistryForTests: () => __resetTaskRegistryForTests,
1808
+ cancel: () => cancel,
1809
+ configure: () => configure,
1810
+ evictNow: () => evictNow,
1811
+ get: () => get,
1812
+ list: () => list,
1813
+ submit: () => submit,
1814
+ subscribe: () => subscribe
1815
+ });
1816
+ function buildState(opts) {
1817
+ const store = opts.store === void 0 ? new InMemoryTaskStore() : getTaskStoreFor(opts.store);
1818
+ return {
1819
+ store,
1820
+ semaphore: createSemaphore(opts.maxConcurrent ?? DEFAULT_CONCURRENCY),
1821
+ aborters: /* @__PURE__ */ new Map(),
1822
+ buffers: /* @__PURE__ */ new Map(),
1823
+ subscribers: /* @__PURE__ */ new Map(),
1824
+ retentionMs: opts.retentionMs ?? DEFAULT_RETENTION_MS,
1825
+ firstSubmitSeen: false
1826
+ };
1827
+ }
1828
+ function __resetTaskRegistryForTests() {
1829
+ if (state.evictTimer !== void 0) clearInterval(state.evictTimer);
1830
+ state = buildState({});
1831
+ }
1832
+ function __getSubscribersCountForTests(taskId) {
1833
+ return state.subscribers.get(taskId)?.size ?? 0;
1834
+ }
1835
+ function __getCancelRequestedForTests(_taskId) {
1836
+ return void 0;
1837
+ }
1838
+ function configure(opts) {
1839
+ if (state.firstSubmitSeen) {
1840
+ process.stderr.write(
1841
+ "[task] configure() ignored \u2014 registry already in use; reset via __resetTaskRegistryForTests()\n"
1842
+ );
1843
+ return;
1844
+ }
1845
+ if (state.evictTimer !== void 0) clearInterval(state.evictTimer);
1846
+ state = buildState(opts);
1847
+ }
1848
+ function emitToSubscribers(taskId, event) {
1849
+ const buffer = state.buffers.get(taskId);
1850
+ if (buffer !== void 0) buffer.push(event);
1851
+ const subs = state.subscribers.get(taskId);
1852
+ if (subs === void 0) return;
1853
+ for (const cb of subs) {
1854
+ try {
1855
+ cb(event);
1856
+ } catch (err) {
1857
+ process.stderr.write(`[task] subscriber threw: ${err.message}
1858
+ `);
1859
+ }
1860
+ }
1861
+ }
1862
+ async function safeUpdate(taskId, mutate) {
1863
+ try {
1864
+ return await state.store.update(taskId, mutate);
1865
+ } catch (err) {
1866
+ process.stderr.write(`[task] store.update failed for ${taskId}: ${err.message}
1867
+ `);
1868
+ return void 0;
1869
+ }
1870
+ }
1871
+ function startEvictTimerIfNeeded() {
1872
+ if (state.evictTimer !== void 0) return;
1873
+ state.evictTimer = setInterval(() => {
1874
+ const cutoff = Date.now() - state.retentionMs;
1875
+ void state.store.evictTerminalOlderThan(cutoff).then((count) => {
1876
+ if (count === 0) return;
1877
+ for (const id of state.buffers.keys()) {
1878
+ void state.store.get(id).then((h) => {
1879
+ if (h === void 0) {
1880
+ state.buffers.delete(id);
1881
+ state.subscribers.delete(id);
1882
+ state.aborters.delete(id);
1883
+ }
1884
+ });
1885
+ }
1886
+ }).catch(() => {
1887
+ });
1888
+ }, EVICTION_INTERVAL_MS).unref();
1889
+ }
1890
+ function buildSubmittedEvent(handle) {
1891
+ return {
1892
+ type: "submitted",
1893
+ taskId: handle.id,
1894
+ kind: handle.kind,
1895
+ submittedAt: handle.submittedAt,
1896
+ ...handle.meta !== void 0 ? { meta: handle.meta } : {}
1897
+ };
1898
+ }
1899
+ async function shortCircuitAborted(handle, signal) {
1900
+ const cancelled = {
1901
+ ...handle,
1902
+ state: "cancelled",
1903
+ cancelledAt: Date.now()
1904
+ };
1905
+ await state.store.insert(cancelled);
1906
+ state.buffers.set(handle.id, new RingBuffer(RING_CAP));
1907
+ emitToSubscribers(handle.id, buildSubmittedEvent(cancelled));
1908
+ emitToSubscribers(handle.id, {
1909
+ type: "cancelled",
1910
+ taskId: handle.id,
1911
+ cancelledAt: cancelled.cancelledAt ?? Date.now(),
1912
+ reason: signal.reason instanceof Error ? signal.reason.message : "pre-aborted"
1913
+ });
1914
+ return cancelled;
1915
+ }
1916
+ async function transition(taskId, next, patch) {
1917
+ const before = await state.store.get(taskId);
1918
+ const span = startTaskTransitionSpan({
1919
+ taskId,
1920
+ from: before?.state ?? "unknown",
1921
+ to: next
1922
+ });
1923
+ try {
1924
+ await safeUpdate(taskId, (h) => ({ ...h, state: next, ...patch }));
1925
+ } finally {
1926
+ span.end();
1927
+ }
1928
+ }
1929
+ async function buildAndInsertQueued(internal, resolvedId) {
1930
+ const submittedAt = Date.now();
1931
+ const handle = {
1932
+ id: resolvedId,
1933
+ kind: internal.kind,
1934
+ state: "queued",
1935
+ submittedAt,
1936
+ ...internal.meta !== void 0 ? { meta: internal.meta } : {}
1937
+ };
1938
+ await state.store.insert(handle);
1939
+ state.buffers.set(resolvedId, new RingBuffer(RING_CAP));
1940
+ emitToSubscribers(resolvedId, buildSubmittedEvent(handle));
1941
+ return handle;
1942
+ }
1943
+ function resolveIdInternal(internal) {
1944
+ if (internal.id === void 0) return crypto.randomUUID();
1945
+ if (!isValidTaskId(internal.id, internal.allowReservedPrefix ?? false)) {
1946
+ throw new InvalidTaskIdError(`invalid task id: ${internal.id}`, internal.id);
1947
+ }
1948
+ return internal.id;
1949
+ }
1950
+ async function runWorkAndFinalize(taskId, aborter, work) {
1951
+ const ctx = {
1952
+ signal: aborter.signal,
1953
+ emit(payload) {
1954
+ void checkCancelRequestedAt(taskId, aborter);
1955
+ emitToSubscribers(taskId, {
1956
+ type: "progress",
1957
+ taskId,
1958
+ at: Date.now(),
1959
+ payload
1960
+ });
1961
+ }
1962
+ };
1963
+ try {
1964
+ const result = await reentryAls.run(true, () => Promise.resolve().then(() => work(ctx)));
1965
+ if (aborter.signal.aborted) {
1966
+ const cancelledAt = Date.now();
1967
+ await transition(taskId, "cancelled", { cancelledAt });
1968
+ emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
1969
+ return;
1970
+ }
1971
+ const finishedAt = Date.now();
1972
+ await transition(taskId, "finished", { finishedAt, result });
1973
+ emitToSubscribers(taskId, { type: "finished", taskId, finishedAt, result });
1974
+ } catch (err) {
1975
+ if (aborter.signal.aborted) {
1976
+ const cancelledAt = Date.now();
1977
+ await transition(taskId, "cancelled", { cancelledAt });
1978
+ emitToSubscribers(taskId, { type: "cancelled", taskId, cancelledAt });
1979
+ return;
1980
+ }
1981
+ const erroredAt = Date.now();
1982
+ const error = err instanceof Error ? { code: err.code ?? "work_threw", message: err.message } : { code: "work_threw", message: String(err) };
1983
+ await transition(taskId, "error", { erroredAt, error });
1984
+ emitToSubscribers(taskId, { type: "errored", taskId, erroredAt, error });
1985
+ }
1986
+ }
1987
+ async function checkCancelRequestedAt(taskId, aborter) {
1988
+ if (aborter.signal.aborted) return;
1989
+ try {
1990
+ const handle = await state.store.get(taskId);
1991
+ if (handle?.cancelRequested === true) {
1992
+ aborter.abort("cancelRequested");
1993
+ }
1994
+ } catch {
1995
+ }
1996
+ }
1997
+ async function acquireSlot() {
1998
+ if (reentryAls.getStore() === true) {
1999
+ return () => {
2000
+ };
2001
+ }
2002
+ return state.semaphore.acquire();
2003
+ }
2004
+ async function submit(internal) {
2005
+ state.firstSubmitSeen = true;
2006
+ startEvictTimerIfNeeded();
2007
+ const resolvedId = resolveIdInternal(internal);
2008
+ const submitSpan = startTaskSubmitSpan({ taskId: resolvedId, kind: internal.kind });
2009
+ const existing = await state.store.get(resolvedId);
2010
+ if (existing !== void 0) {
2011
+ submitSpan.end();
2012
+ return existing;
2013
+ }
2014
+ const queuedHandle = await buildAndInsertQueued(internal, resolvedId);
2015
+ submitSpan.end();
2016
+ if (internal.signal?.aborted === true) {
2017
+ return shortCircuitAborted(queuedHandle, internal.signal);
2018
+ }
2019
+ const aborter = new AbortController();
2020
+ state.aborters.set(resolvedId, aborter);
2021
+ if (internal.signal !== void 0) {
2022
+ internal.signal.addEventListener("abort", () => aborter.abort(internal.signal?.reason), {
2023
+ once: true
2024
+ });
2025
+ }
2026
+ const release = await acquireSlot();
2027
+ void (async () => {
2028
+ try {
2029
+ await checkCancelRequestedAt(resolvedId, aborter);
2030
+ if (aborter.signal.aborted) {
2031
+ const cancelledAt = Date.now();
2032
+ await transition(resolvedId, "cancelled", { cancelledAt });
2033
+ emitToSubscribers(resolvedId, { type: "cancelled", taskId: resolvedId, cancelledAt });
2034
+ return;
2035
+ }
2036
+ const startedAt = Date.now();
2037
+ await transition(resolvedId, "running", { startedAt });
2038
+ emitToSubscribers(resolvedId, { type: "started", taskId: resolvedId, startedAt });
2039
+ await runWorkAndFinalize(resolvedId, aborter, internal.work);
2040
+ } finally {
2041
+ release();
2042
+ state.aborters.delete(resolvedId);
2043
+ }
2044
+ })();
2045
+ return queuedHandle;
2046
+ }
2047
+ async function list(filter = {}) {
2048
+ return state.store.list(filter);
2049
+ }
2050
+ async function get(id) {
2051
+ if (!isValidTaskId(id, true)) return void 0;
2052
+ return state.store.get(id);
2053
+ }
2054
+ async function cancel(id, reason) {
2055
+ if (!isValidTaskId(id, true)) return { cancelled: false, alreadyTerminal: false };
2056
+ const handle = await state.store.get(id);
2057
+ if (handle === void 0) return { cancelled: false, alreadyTerminal: false };
2058
+ if (handle.state === "finished" || handle.state === "error" || handle.state === "cancelled") {
2059
+ return { cancelled: false, alreadyTerminal: true };
2060
+ }
2061
+ const span = startTaskCancelSpan({
2062
+ taskId: id,
2063
+ ...reason !== void 0 ? { reason } : {},
2064
+ via: "api"
2065
+ });
2066
+ try {
2067
+ return await cancelInternal(id, handle.state, reason);
2068
+ } finally {
2069
+ span.end();
2070
+ }
2071
+ }
2072
+ async function cancelInternal(id, currentState, reason) {
2073
+ if (currentState === "queued") {
2074
+ const cancelledAt = Date.now();
2075
+ await transition(id, "cancelled", { cancelledAt });
2076
+ emitToSubscribers(id, {
2077
+ type: "cancelled",
2078
+ taskId: id,
2079
+ cancelledAt,
2080
+ ...reason !== void 0 ? { reason } : {}
2081
+ });
2082
+ state.aborters.delete(id);
2083
+ return { cancelled: true, alreadyTerminal: false };
2084
+ }
2085
+ const aborter = state.aborters.get(id);
2086
+ if (aborter !== void 0) aborter.abort(reason ?? "cancelled");
2087
+ return { cancelled: true, alreadyTerminal: false };
2088
+ }
2089
+ async function evictNow(now = Date.now()) {
2090
+ return state.store.evictTerminalOlderThan(now - state.retentionMs);
2091
+ }
2092
+ var DEFAULT_CONCURRENCY, DEFAULT_RETENTION_MS, EVICTION_INTERVAL_MS, RING_CAP, reentryAls, state, subscribe;
2093
+ var init_registry = __esm({
2094
+ "src/internal/task/registry.ts"() {
2095
+ init_errors();
2096
+ init_task();
2097
+ init_async_semaphore();
2098
+ init_ring_buffer();
2099
+ init_store();
2100
+ init_subscribe();
2101
+ init_telemetry2();
2102
+ DEFAULT_CONCURRENCY = 8;
2103
+ DEFAULT_RETENTION_MS = 60 * 60 * 1e3;
2104
+ EVICTION_INTERVAL_MS = 5 * 60 * 1e3;
2105
+ RING_CAP = 64;
2106
+ reentryAls = new async_hooks.AsyncLocalStorage();
2107
+ state = buildState({});
2108
+ subscribe = buildSubscribe({
2109
+ getBuffer: (id) => state.buffers.get(id),
2110
+ getOrCreateSubscriberSet: (id) => {
2111
+ let subs = state.subscribers.get(id);
2112
+ if (subs === void 0) {
2113
+ subs = /* @__PURE__ */ new Set();
2114
+ state.subscribers.set(id, subs);
2115
+ }
2116
+ return subs;
2117
+ },
2118
+ removeSubscriber: (id, cb) => {
2119
+ const set = state.subscribers.get(id);
2120
+ set?.delete(cb);
2121
+ if (set !== void 0 && set.size === 0) state.subscribers.delete(id);
2122
+ }
2123
+ });
2124
+ }
2125
+ });
2126
+ var PersistenceSchema = zod.z.object({
2127
+ backend: zod.z.enum(["memory", "json"]),
2128
+ dir: zod.z.string().optional()
2129
+ }).refine((p) => p.backend !== "json" || typeof p.dir === "string" && p.dir.length > 0, {
2130
+ message: 'persistence.dir is required when backend = "json"'
2131
+ }).optional();
2132
+
2133
+ // src/internal/security/path-guard.ts
2134
+ init_errors();
2135
+ var IDENTIFIER_PATTERN = /^[a-z0-9][a-z0-9\-_]*$/i;
2136
+ function sanitizeIdentifier(input, options) {
2137
+ const maxLen = options?.maxLen;
2138
+ if (input.length === 0 || input.length > maxLen) {
2139
+ throw new ConfigurationError(`Identifier length out of range (1-${maxLen}): "${input}"`, {
2140
+ code: "invalid_identifier"
2141
+ });
2142
+ }
2143
+ if (!IDENTIFIER_PATTERN.test(input)) {
2144
+ throw new ConfigurationError(`Identifier contains invalid characters: "${input}"`, {
2145
+ code: "invalid_identifier"
2146
+ });
2147
+ }
2148
+ return input.toLowerCase();
2149
+ }
2150
+
2151
+ // src/workflow.ts
2152
+ init_workflow();
2153
+ init_snapshot_store();
2154
+ init_workflow();
2155
+ var RetryPolicySchema = zod.z.object({
2156
+ // EC-3 absorbed: maxAttempts MUST be a finite int in [1, 20].
2157
+ maxAttempts: zod.z.number().int("retry.maxAttempts must be integer").min(1, "retry.maxAttempts must be >= 1").max(20, "retry.maxAttempts must be <= 20"),
2158
+ initialBackoffMs: zod.z.number().int().min(0).optional(),
2159
+ backoffCoefficient: zod.z.number().min(1).optional(),
2160
+ maximumBackoffMs: zod.z.number().int().min(0).optional(),
2161
+ nonRetryableErrors: zod.z.array(zod.z.string()).optional()
2162
+ });
2163
+ var WorkflowOptionsSchema = zod.z.object({
2164
+ name: zod.z.string().min(1).max(128),
2165
+ persistence: PersistenceSchema
2166
+ });
2167
+ var WorkflowBuilder = class {
2168
+ /** @internal */
2169
+ constructor(options) {
2170
+ this.options = options;
2171
+ }
2172
+ options;
2173
+ _steps = [];
2174
+ _committed = false;
2175
+ /** @internal — only the executor reads this. */
2176
+ get __steps() {
2177
+ return this._steps;
2178
+ }
2179
+ // biome-ignore lint/suspicious/noThenProperty: D233 locks the Mastra-style `.then(step)` builder DSL. The method is fluent, never awaited.
2180
+ then(step) {
2181
+ this.assertNotCommitted();
2182
+ validateStepId(step.id);
2183
+ this._steps.push(step);
2184
+ return this;
2185
+ }
2186
+ parallel(branches, opts) {
2187
+ this.assertNotCommitted();
2188
+ const id = opts?.id ?? `parallel_${this._steps.length}`;
2189
+ validateStepId(id);
2190
+ for (const branch of branches) {
2191
+ for (const inner of branch) validateStepId(inner.id);
2192
+ }
2193
+ const step = {
2194
+ kind: "parallel",
2195
+ id,
2196
+ branches,
2197
+ ...opts?.concurrency !== void 0 ? { concurrency: opts.concurrency } : {},
2198
+ ...opts?.errorPolicy !== void 0 ? { errorPolicy: opts.errorPolicy } : {}
2199
+ };
2200
+ this._steps.push(step);
2201
+ return this;
2202
+ }
2203
+ branch(predicates, opts) {
2204
+ this.assertNotCommitted();
2205
+ const id = opts?.id ?? `branch_${this._steps.length}`;
2206
+ validateStepId(id);
2207
+ const step = {
2208
+ kind: "branch",
2209
+ id,
2210
+ predicates,
2211
+ ...opts?.fallback !== void 0 ? { fallback: opts.fallback } : {}
2212
+ };
2213
+ this._steps.push(step);
2214
+ return this;
2215
+ }
2216
+ foreach(iterableFrom, step, opts) {
2217
+ this.assertNotCommitted();
2218
+ const id = opts?.id ?? `foreach_${this._steps.length}`;
2219
+ validateStepId(id);
2220
+ validateStepId(iterableFrom);
2221
+ validateStepId(step.id);
2222
+ const node = {
2223
+ kind: "foreach",
2224
+ id,
2225
+ iterableFrom,
2226
+ step,
2227
+ ...opts?.concurrency !== void 0 ? { concurrency: opts.concurrency } : {}
2228
+ };
2229
+ this._steps.push(node);
2230
+ return this;
2231
+ }
2232
+ dowhile(step, condFn, opts) {
2233
+ this.assertNotCommitted();
2234
+ const id = opts?.id ?? `dowhile_${this._steps.length}`;
2235
+ validateStepId(id);
2236
+ validateStepId(step.id);
2237
+ const node = {
2238
+ kind: "dowhile",
2239
+ id,
2240
+ step,
2241
+ condFn,
2242
+ ...opts?.maxIterations !== void 0 ? { maxIterations: opts.maxIterations } : {}
2243
+ };
2244
+ this._steps.push(node);
2245
+ return this;
2246
+ }
2247
+ sleep(durationMs, id) {
2248
+ this.assertNotCommitted();
2249
+ const stepId = id ?? `sleep_${this._steps.length}`;
2250
+ validateStepId(stepId);
2251
+ if (!Number.isFinite(durationMs) || durationMs < 0) {
2252
+ throw new Error(`sleep durationMs must be finite non-negative: ${durationMs}`);
2253
+ }
2254
+ const step = { kind: "sleep", id: stepId, durationMs };
2255
+ this._steps.push(step);
2256
+ return this;
2257
+ }
2258
+ suspend(opts) {
2259
+ this.assertNotCommitted();
2260
+ const id = opts?.id ?? `suspend_${this._steps.length}`;
2261
+ validateStepId(id);
2262
+ const step = {
2263
+ kind: "suspend",
2264
+ id,
2265
+ ...opts?.payloadSchema !== void 0 ? { payloadSchema: opts.payloadSchema } : {}
2266
+ };
2267
+ this._steps.push(step);
2268
+ return this;
2269
+ }
2270
+ commit() {
2271
+ this.assertNotCommitted();
2272
+ this.validateUniqueIds();
2273
+ this._committed = true;
2274
+ const workflowId = `wf-${mintShortId()}`;
2275
+ return new Workflow({ ...this.options, workflowId }, [...this._steps]);
2276
+ }
2277
+ validateUniqueIds() {
2278
+ const seen = /* @__PURE__ */ new Set();
2279
+ walkStepsValidating(this._steps, seen);
2280
+ }
2281
+ assertNotCommitted() {
2282
+ if (this._committed) {
2283
+ throw new Error("Workflow already committed; create a fresh Workflow.create(...) call.");
2284
+ }
2285
+ }
2286
+ };
2287
+ var Workflow = class {
2288
+ /** @internal */
2289
+ constructor(_options, _steps) {
2290
+ this._options = _options;
2291
+ this._steps = _steps;
2292
+ }
2293
+ _options;
2294
+ _steps;
2295
+ /** @internal — only the executor reads these. */
2296
+ get __options() {
2297
+ return this._options;
2298
+ }
2299
+ /** @internal */
2300
+ get __steps() {
2301
+ return this._steps;
2302
+ }
2303
+ /**
2304
+ * Construct a workflow builder. Validate options via Zod and return a
2305
+ * `WorkflowBuilder` for fluent chaining. Call `.commit()` to obtain the
2306
+ * immutable `Workflow`.
2307
+ */
2308
+ static create(options) {
2309
+ WorkflowOptionsSchema.parse(options);
2310
+ return new WorkflowBuilder(options);
2311
+ }
2312
+ /**
2313
+ * Run this workflow with the given input. Returns a populated
2314
+ * `WorkflowRun`. Errors inside a step DO NOT throw — they propagate via
2315
+ * `run.status === "failed"`.
2316
+ */
2317
+ async run(input, opts) {
2318
+ const { executeWorkflow: executeWorkflow2 } = await Promise.resolve().then(() => (init_executor(), executor_exports));
2319
+ const result = await executeWorkflow2(this._options, this._steps, input, opts);
2320
+ if (opts?.task !== void 0) {
2321
+ const { submit: taskSubmit } = await Promise.resolve().then(() => (init_registry(), registry_exports));
2322
+ const taskOpts = opts.task === true ? {} : opts.task;
2323
+ const id = taskOpts.id ?? `wf-${result.id}`;
2324
+ await taskSubmit({
2325
+ kind: "workflow",
2326
+ work: async (ctx) => {
2327
+ ctx.emit({ status: result.status, runId: result.id });
2328
+ return { status: result.status, runId: result.id, output: result.output };
2329
+ },
2330
+ id,
2331
+ meta: {
2332
+ workflowName: this._options.name,
2333
+ runId: result.id,
2334
+ status: result.status,
2335
+ ...taskOpts.meta ?? {}
2336
+ },
2337
+ allowReservedPrefix: true
2338
+ });
2339
+ }
2340
+ return result;
2341
+ }
2342
+ /**
2343
+ * Resume a suspended workflow from its snapshot. Throws
2344
+ * `WorkflowSnapshotNotFoundError` if `runId` is unknown.
2345
+ */
2346
+ static async resume(opts) {
2347
+ const { resumeWorkflow: resumeWorkflow2 } = await Promise.resolve().then(() => (init_executor(), executor_exports));
2348
+ return resumeWorkflow2(opts);
2349
+ }
2350
+ };
2351
+ function fn(id, step, opts) {
2352
+ validateStepId(id);
2353
+ if (opts?.retry !== void 0) RetryPolicySchema.parse(opts.retry);
2354
+ return {
2355
+ kind: "fn",
2356
+ id,
2357
+ fn: step,
2358
+ ...opts?.inputSchema !== void 0 ? { inputSchema: opts.inputSchema } : {},
2359
+ ...opts?.outputSchema !== void 0 ? { outputSchema: opts.outputSchema } : {},
2360
+ ...opts?.retry !== void 0 ? { retry: opts.retry } : {}
2361
+ };
2362
+ }
2363
+ function agentStep(id, agent, promptTemplate, opts) {
2364
+ validateStepId(id);
2365
+ if (opts?.retry !== void 0) RetryPolicySchema.parse(opts.retry);
2366
+ return {
2367
+ kind: "agent",
2368
+ id,
2369
+ agent,
2370
+ promptTemplate,
2371
+ ...opts?.retry !== void 0 ? { retry: opts.retry } : {}
2372
+ };
2373
+ }
2374
+ function validateStepId(id) {
2375
+ sanitizeIdentifier(id, { maxLen: 64 });
2376
+ }
2377
+ function mintShortId() {
2378
+ return globalThis.crypto.randomUUID().replace(/-/g, "").slice(0, 8);
2379
+ }
2380
+ function nestedStepsOf(s) {
2381
+ if (s.kind === "parallel") return s.branches;
2382
+ if (s.kind === "branch") {
2383
+ const groups = s.predicates.map(([, branch]) => branch);
2384
+ return s.fallback !== void 0 ? [...groups, s.fallback] : groups;
2385
+ }
2386
+ if (s.kind === "foreach" || s.kind === "dowhile") return [[s.step]];
2387
+ return [];
2388
+ }
2389
+ function walkStepsValidating(steps, seen) {
2390
+ for (const s of steps) {
2391
+ if (seen.has(s.id)) throw new exports.WorkflowDuplicateStepIdError(s.id);
2392
+ seen.add(s.id);
2393
+ for (const nested of nestedStepsOf(s)) {
2394
+ walkStepsValidating(nested, seen);
2395
+ }
2396
+ }
2397
+ }
2398
+
2399
+ exports.Workflow = Workflow;
2400
+ exports.WorkflowBuilder = WorkflowBuilder;
2401
+ exports.__resetSnapshotStoresForTests = __resetSnapshotStoresForTests;
2402
+ exports.agentStep = agentStep;
2403
+ exports.fn = fn;
2404
+ //# sourceMappingURL=workflow.cjs.map
2405
+ //# sourceMappingURL=workflow.cjs.map