@sprinterai/runtime 0.4.1 → 0.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 (384) hide show
  1. package/dist/adapters/a2a-adapter.d.ts +37 -9
  2. package/dist/adapters/a2a-adapter.d.ts.map +1 -1
  3. package/dist/adapters/a2a-adapter.js +132 -9
  4. package/dist/adapters/a2a-adapter.js.map +1 -1
  5. package/dist/adapters/a2a-adapter.test.d.ts +2 -0
  6. package/dist/adapters/a2a-adapter.test.d.ts.map +1 -0
  7. package/dist/adapters/a2a-adapter.test.js +295 -0
  8. package/dist/adapters/a2a-adapter.test.js.map +1 -0
  9. package/dist/adapters/http-agent-adapter.d.ts +19 -9
  10. package/dist/adapters/http-agent-adapter.d.ts.map +1 -1
  11. package/dist/adapters/http-agent-adapter.js +55 -9
  12. package/dist/adapters/http-agent-adapter.js.map +1 -1
  13. package/dist/adapters/http-agent-adapter.test.d.ts +2 -0
  14. package/dist/adapters/http-agent-adapter.test.d.ts.map +1 -0
  15. package/dist/adapters/http-agent-adapter.test.js +164 -0
  16. package/dist/adapters/http-agent-adapter.test.js.map +1 -0
  17. package/dist/adapters/index.d.ts +8 -8
  18. package/dist/adapters/index.d.ts.map +1 -1
  19. package/dist/adapters/index.js +4 -4
  20. package/dist/adapters/index.js.map +1 -1
  21. package/dist/adapters/mcp-adapter.d.ts +29 -9
  22. package/dist/adapters/mcp-adapter.d.ts.map +1 -1
  23. package/dist/adapters/mcp-adapter.js +43 -8
  24. package/dist/adapters/mcp-adapter.js.map +1 -1
  25. package/dist/adapters/mcp-adapter.test.d.ts +2 -0
  26. package/dist/adapters/mcp-adapter.test.d.ts.map +1 -0
  27. package/dist/adapters/mcp-adapter.test.js +118 -0
  28. package/dist/adapters/mcp-adapter.test.js.map +1 -0
  29. package/dist/adapters/openclaw-adapter.d.ts +34 -8
  30. package/dist/adapters/openclaw-adapter.d.ts.map +1 -1
  31. package/dist/adapters/openclaw-adapter.js +38 -8
  32. package/dist/adapters/openclaw-adapter.js.map +1 -1
  33. package/dist/adapters/openclaw-adapter.test.d.ts +2 -0
  34. package/dist/adapters/openclaw-adapter.test.d.ts.map +1 -0
  35. package/dist/adapters/openclaw-adapter.test.js +77 -0
  36. package/dist/adapters/openclaw-adapter.test.js.map +1 -0
  37. package/dist/agent/agent-registry.test.js +1 -1
  38. package/dist/agent/agent-resolver.d.ts +8 -2
  39. package/dist/agent/agent-resolver.d.ts.map +1 -1
  40. package/dist/agent/agent-resolver.js +7 -1
  41. package/dist/agent/agent-resolver.js.map +1 -1
  42. package/dist/agent/agent-resolver.test.js +21 -3
  43. package/dist/agent/agent-resolver.test.js.map +1 -1
  44. package/dist/agent/delegate.test.js +1 -1
  45. package/dist/agent/execute-agent.d.ts +32 -8
  46. package/dist/agent/execute-agent.d.ts.map +1 -1
  47. package/dist/agent/execute-agent.js +40 -3
  48. package/dist/agent/execute-agent.js.map +1 -1
  49. package/dist/agent/index.d.ts +9 -9
  50. package/dist/agent/index.d.ts.map +1 -1
  51. package/dist/agent/index.js +5 -5
  52. package/dist/agent/index.js.map +1 -1
  53. package/dist/agent/prompt-builder.test.js +1 -1
  54. package/dist/approval/approval-manager.d.ts +19 -0
  55. package/dist/approval/approval-manager.d.ts.map +1 -0
  56. package/dist/approval/approval-manager.js +36 -0
  57. package/dist/approval/approval-manager.js.map +1 -0
  58. package/dist/approval/approval-manager.test.d.ts +2 -0
  59. package/dist/approval/approval-manager.test.d.ts.map +1 -0
  60. package/dist/approval/approval-manager.test.js +239 -0
  61. package/dist/approval/approval-manager.test.js.map +1 -0
  62. package/dist/approval/index.d.ts +3 -0
  63. package/dist/approval/index.d.ts.map +1 -0
  64. package/dist/approval/index.js +2 -0
  65. package/dist/approval/index.js.map +1 -0
  66. package/dist/chat/chat-handler.d.ts +14 -7
  67. package/dist/chat/chat-handler.d.ts.map +1 -1
  68. package/dist/chat/chat-handler.js +56 -11
  69. package/dist/chat/chat-handler.js.map +1 -1
  70. package/dist/chat/chat-handler.test.js +100 -11
  71. package/dist/chat/chat-handler.test.js.map +1 -1
  72. package/dist/chat/index.d.ts +3 -3
  73. package/dist/chat/index.js +2 -2
  74. package/dist/chat/message-utils.d.ts +15 -7
  75. package/dist/chat/message-utils.d.ts.map +1 -1
  76. package/dist/chat/message-utils.js +94 -22
  77. package/dist/chat/message-utils.js.map +1 -1
  78. package/dist/chat/message-utils.test.js +71 -1
  79. package/dist/chat/message-utils.test.js.map +1 -1
  80. package/dist/document/chunk-generator.d.ts +6 -0
  81. package/dist/document/chunk-generator.d.ts.map +1 -0
  82. package/dist/document/chunk-generator.js +107 -0
  83. package/dist/document/chunk-generator.js.map +1 -0
  84. package/dist/document/chunk-generator.test.d.ts +2 -0
  85. package/dist/document/chunk-generator.test.d.ts.map +1 -0
  86. package/dist/document/chunk-generator.test.js +166 -0
  87. package/dist/document/chunk-generator.test.js.map +1 -0
  88. package/dist/document/document-processor.d.ts +27 -0
  89. package/dist/document/document-processor.d.ts.map +1 -0
  90. package/dist/document/document-processor.js +44 -0
  91. package/dist/document/document-processor.js.map +1 -0
  92. package/dist/document/document-processor.test.d.ts +2 -0
  93. package/dist/document/document-processor.test.d.ts.map +1 -0
  94. package/dist/document/document-processor.test.js +197 -0
  95. package/dist/document/document-processor.test.js.map +1 -0
  96. package/dist/document/index.d.ts +5 -0
  97. package/dist/document/index.d.ts.map +1 -0
  98. package/dist/document/index.js +4 -0
  99. package/dist/document/index.js.map +1 -0
  100. package/dist/document/parsers/index.d.ts +2 -0
  101. package/dist/document/parsers/index.d.ts.map +1 -0
  102. package/dist/document/parsers/index.js +2 -0
  103. package/dist/document/parsers/index.js.map +1 -0
  104. package/dist/document/parsers/text-parser.d.ts +4 -0
  105. package/dist/document/parsers/text-parser.d.ts.map +1 -0
  106. package/dist/document/parsers/text-parser.js +23 -0
  107. package/dist/document/parsers/text-parser.js.map +1 -0
  108. package/dist/document/parsers/text-parser.test.d.ts +2 -0
  109. package/dist/document/parsers/text-parser.test.d.ts.map +1 -0
  110. package/dist/document/parsers/text-parser.test.js +64 -0
  111. package/dist/document/parsers/text-parser.test.js.map +1 -0
  112. package/dist/eval/eval-runner.test.js +2 -2
  113. package/dist/eval/index.d.ts +3 -3
  114. package/dist/eval/index.js +2 -2
  115. package/dist/eval/scorers.test.js +1 -1
  116. package/dist/events/event-bus.d.ts +12 -0
  117. package/dist/events/event-bus.d.ts.map +1 -0
  118. package/dist/events/event-bus.js +77 -0
  119. package/dist/events/event-bus.js.map +1 -0
  120. package/dist/events/event-bus.test.d.ts +2 -0
  121. package/dist/events/event-bus.test.d.ts.map +1 -0
  122. package/dist/events/event-bus.test.js +155 -0
  123. package/dist/events/event-bus.test.js.map +1 -0
  124. package/dist/events/index.d.ts +2 -0
  125. package/dist/events/index.d.ts.map +1 -0
  126. package/dist/events/index.js +2 -0
  127. package/dist/events/index.js.map +1 -0
  128. package/dist/guardrail/guardrail-pipeline.test.js +1 -1
  129. package/dist/guardrail/index.d.ts +2 -2
  130. package/dist/guardrail/index.js +1 -1
  131. package/dist/index.d.ts +81 -45
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +55 -27
  134. package/dist/index.js.map +1 -1
  135. package/dist/jobs/in-memory-job-queue.d.ts +20 -0
  136. package/dist/jobs/in-memory-job-queue.d.ts.map +1 -0
  137. package/dist/jobs/in-memory-job-queue.js +120 -0
  138. package/dist/jobs/in-memory-job-queue.js.map +1 -0
  139. package/dist/jobs/in-memory-job-queue.test.d.ts +2 -0
  140. package/dist/jobs/in-memory-job-queue.test.d.ts.map +1 -0
  141. package/dist/jobs/in-memory-job-queue.test.js +146 -0
  142. package/dist/jobs/in-memory-job-queue.test.js.map +1 -0
  143. package/dist/jobs/index.d.ts +4 -0
  144. package/dist/jobs/index.d.ts.map +1 -0
  145. package/dist/jobs/index.js +3 -0
  146. package/dist/jobs/index.js.map +1 -0
  147. package/dist/jobs/job-runner.d.ts +42 -0
  148. package/dist/jobs/job-runner.d.ts.map +1 -0
  149. package/dist/jobs/job-runner.js +119 -0
  150. package/dist/jobs/job-runner.js.map +1 -0
  151. package/dist/jobs/job-runner.test.d.ts +2 -0
  152. package/dist/jobs/job-runner.test.d.ts.map +1 -0
  153. package/dist/jobs/job-runner.test.js +190 -0
  154. package/dist/jobs/job-runner.test.js.map +1 -0
  155. package/dist/memory/index.d.ts +3 -3
  156. package/dist/memory/index.js +2 -2
  157. package/dist/memory/memory-prompt.d.ts +1 -1
  158. package/dist/module/create-runtime.d.ts +21 -6
  159. package/dist/module/create-runtime.d.ts.map +1 -1
  160. package/dist/module/create-runtime.js +7 -7
  161. package/dist/module/create-runtime.js.map +1 -1
  162. package/dist/module/create-runtime.test.js +8 -8
  163. package/dist/module/index.d.ts +5 -4
  164. package/dist/module/index.d.ts.map +1 -1
  165. package/dist/module/index.js +3 -2
  166. package/dist/module/index.js.map +1 -1
  167. package/dist/module/map-supabase-stores.d.ts +33 -0
  168. package/dist/module/map-supabase-stores.d.ts.map +1 -0
  169. package/dist/module/map-supabase-stores.js +28 -0
  170. package/dist/module/map-supabase-stores.js.map +1 -0
  171. package/dist/module/module-loader.d.ts +9 -1
  172. package/dist/module/module-loader.d.ts.map +1 -1
  173. package/dist/module/module-loader.js +40 -1
  174. package/dist/module/module-loader.js.map +1 -1
  175. package/dist/module/module-loader.test.js +38 -1
  176. package/dist/module/module-loader.test.js.map +1 -1
  177. package/dist/notification/digest-scheduler.d.ts +18 -0
  178. package/dist/notification/digest-scheduler.d.ts.map +1 -0
  179. package/dist/notification/digest-scheduler.js +44 -0
  180. package/dist/notification/digest-scheduler.js.map +1 -0
  181. package/dist/notification/digest-scheduler.test.d.ts +2 -0
  182. package/dist/notification/digest-scheduler.test.d.ts.map +1 -0
  183. package/dist/notification/digest-scheduler.test.js +306 -0
  184. package/dist/notification/digest-scheduler.test.js.map +1 -0
  185. package/dist/notification/index.d.ts +5 -0
  186. package/dist/notification/index.d.ts.map +1 -0
  187. package/dist/notification/index.js +3 -0
  188. package/dist/notification/index.js.map +1 -0
  189. package/dist/notification/notification-engine.d.ts +20 -0
  190. package/dist/notification/notification-engine.d.ts.map +1 -0
  191. package/dist/notification/notification-engine.js +78 -0
  192. package/dist/notification/notification-engine.js.map +1 -0
  193. package/dist/notification/notification-engine.test.d.ts +2 -0
  194. package/dist/notification/notification-engine.test.d.ts.map +1 -0
  195. package/dist/notification/notification-engine.test.js +364 -0
  196. package/dist/notification/notification-engine.test.js.map +1 -0
  197. package/dist/providers/index.d.ts +5 -0
  198. package/dist/providers/index.d.ts.map +1 -0
  199. package/dist/providers/index.js +3 -0
  200. package/dist/providers/index.js.map +1 -0
  201. package/dist/providers/model-resolver.d.ts +93 -0
  202. package/dist/providers/model-resolver.d.ts.map +1 -0
  203. package/dist/providers/model-resolver.js +152 -0
  204. package/dist/providers/model-resolver.js.map +1 -0
  205. package/dist/providers/model-resolver.test.d.ts +2 -0
  206. package/dist/providers/model-resolver.test.d.ts.map +1 -0
  207. package/dist/providers/model-resolver.test.js +199 -0
  208. package/dist/providers/model-resolver.test.js.map +1 -0
  209. package/dist/providers/noop-providers.d.ts +6 -0
  210. package/dist/providers/noop-providers.d.ts.map +1 -0
  211. package/dist/providers/noop-providers.js +15 -0
  212. package/dist/providers/noop-providers.js.map +1 -0
  213. package/dist/providers/noop-providers.test.d.ts +2 -0
  214. package/dist/providers/noop-providers.test.d.ts.map +1 -0
  215. package/dist/providers/noop-providers.test.js +63 -0
  216. package/dist/providers/noop-providers.test.js.map +1 -0
  217. package/dist/providers/provider-interfaces.d.ts +65 -0
  218. package/dist/providers/provider-interfaces.d.ts.map +1 -0
  219. package/dist/providers/provider-interfaces.js +2 -0
  220. package/dist/providers/provider-interfaces.js.map +1 -0
  221. package/dist/realtime/index.d.ts +3 -0
  222. package/dist/realtime/index.d.ts.map +1 -0
  223. package/dist/realtime/index.js +2 -0
  224. package/dist/realtime/index.js.map +1 -0
  225. package/dist/realtime/realtime-manager.d.ts +20 -0
  226. package/dist/realtime/realtime-manager.d.ts.map +1 -0
  227. package/dist/realtime/realtime-manager.js +110 -0
  228. package/dist/realtime/realtime-manager.js.map +1 -0
  229. package/dist/realtime/realtime-manager.test.d.ts +2 -0
  230. package/dist/realtime/realtime-manager.test.d.ts.map +1 -0
  231. package/dist/realtime/realtime-manager.test.js +273 -0
  232. package/dist/realtime/realtime-manager.test.js.map +1 -0
  233. package/dist/scoring/compute-score.test.js +1 -1
  234. package/dist/scoring/index.d.ts +2 -2
  235. package/dist/scoring/index.js +1 -1
  236. package/dist/search/cosine-similarity.d.ts +8 -0
  237. package/dist/search/cosine-similarity.d.ts.map +1 -0
  238. package/dist/search/cosine-similarity.js +28 -0
  239. package/dist/search/cosine-similarity.js.map +1 -0
  240. package/dist/search/cosine-similarity.test.d.ts +2 -0
  241. package/dist/search/cosine-similarity.test.d.ts.map +1 -0
  242. package/dist/search/cosine-similarity.test.js +49 -0
  243. package/dist/search/cosine-similarity.test.js.map +1 -0
  244. package/dist/search/hybrid-search.d.ts +47 -0
  245. package/dist/search/hybrid-search.d.ts.map +1 -0
  246. package/dist/search/hybrid-search.js +111 -0
  247. package/dist/search/hybrid-search.js.map +1 -0
  248. package/dist/search/hybrid-search.test.d.ts +2 -0
  249. package/dist/search/hybrid-search.test.d.ts.map +1 -0
  250. package/dist/search/hybrid-search.test.js +238 -0
  251. package/dist/search/hybrid-search.test.js.map +1 -0
  252. package/dist/search/in-memory-search.d.ts +17 -0
  253. package/dist/search/in-memory-search.d.ts.map +1 -0
  254. package/dist/search/in-memory-search.js +59 -0
  255. package/dist/search/in-memory-search.js.map +1 -0
  256. package/dist/search/in-memory-search.test.d.ts +2 -0
  257. package/dist/search/in-memory-search.test.d.ts.map +1 -0
  258. package/dist/search/in-memory-search.test.js +169 -0
  259. package/dist/search/in-memory-search.test.js.map +1 -0
  260. package/dist/search/index.d.ts +6 -0
  261. package/dist/search/index.d.ts.map +1 -0
  262. package/dist/search/index.js +4 -0
  263. package/dist/search/index.js.map +1 -0
  264. package/dist/testing/in-memory-agent-store.d.ts +5 -1
  265. package/dist/testing/in-memory-agent-store.d.ts.map +1 -1
  266. package/dist/testing/in-memory-agent-store.js +19 -0
  267. package/dist/testing/in-memory-agent-store.js.map +1 -1
  268. package/dist/testing/in-memory-agent-store.test.js +1 -1
  269. package/dist/testing/in-memory-chat-store.d.ts.map +1 -1
  270. package/dist/testing/in-memory-chat-store.js +2 -1
  271. package/dist/testing/in-memory-chat-store.js.map +1 -1
  272. package/dist/testing/in-memory-entity-store.d.ts +5 -1
  273. package/dist/testing/in-memory-entity-store.d.ts.map +1 -1
  274. package/dist/testing/in-memory-entity-store.js +69 -4
  275. package/dist/testing/in-memory-entity-store.js.map +1 -1
  276. package/dist/testing/in-memory-entity-store.test.js +1 -1
  277. package/dist/testing/in-memory-memory-store.d.ts +3 -1
  278. package/dist/testing/in-memory-memory-store.d.ts.map +1 -1
  279. package/dist/testing/in-memory-memory-store.js +20 -0
  280. package/dist/testing/in-memory-memory-store.js.map +1 -1
  281. package/dist/testing/in-memory-tool-store.d.ts +13 -2
  282. package/dist/testing/in-memory-tool-store.d.ts.map +1 -1
  283. package/dist/testing/in-memory-tool-store.js +51 -0
  284. package/dist/testing/in-memory-tool-store.js.map +1 -1
  285. package/dist/testing/index.d.ts +7 -7
  286. package/dist/testing/index.js +7 -7
  287. package/dist/tool/ai-bridge.d.ts +1 -0
  288. package/dist/tool/ai-bridge.d.ts.map +1 -1
  289. package/dist/tool/ai-bridge.js +1 -0
  290. package/dist/tool/ai-bridge.js.map +1 -1
  291. package/dist/tool/ai-bridge.test.js +1 -1
  292. package/dist/tool/catalog.d.ts +19 -0
  293. package/dist/tool/catalog.d.ts.map +1 -0
  294. package/dist/tool/catalog.js +88 -0
  295. package/dist/tool/catalog.js.map +1 -0
  296. package/dist/tool/catalog.test.d.ts +2 -0
  297. package/dist/tool/catalog.test.d.ts.map +1 -0
  298. package/dist/tool/catalog.test.js +129 -0
  299. package/dist/tool/catalog.test.js.map +1 -0
  300. package/dist/tool/entity-tools-factory.test.js +2 -2
  301. package/dist/tool/execute-registered-tool.d.ts +17 -0
  302. package/dist/tool/execute-registered-tool.d.ts.map +1 -0
  303. package/dist/tool/execute-registered-tool.js +24 -0
  304. package/dist/tool/execute-registered-tool.js.map +1 -0
  305. package/dist/tool/execute-registered-tool.test.d.ts +2 -0
  306. package/dist/tool/execute-registered-tool.test.d.ts.map +1 -0
  307. package/dist/tool/execute-registered-tool.test.js +73 -0
  308. package/dist/tool/execute-registered-tool.test.js.map +1 -0
  309. package/dist/tool/index.d.ts +11 -7
  310. package/dist/tool/index.d.ts.map +1 -1
  311. package/dist/tool/index.js +7 -5
  312. package/dist/tool/index.js.map +1 -1
  313. package/dist/tool/resolve-tools.d.ts +3 -1
  314. package/dist/tool/resolve-tools.d.ts.map +1 -1
  315. package/dist/tool/resolve-tools.js +1 -1
  316. package/dist/tool/resolve-tools.js.map +1 -1
  317. package/dist/tool/resolve-tools.test.js +1 -1
  318. package/dist/tool/tool-executor.d.ts +3 -2
  319. package/dist/tool/tool-executor.d.ts.map +1 -1
  320. package/dist/tool/tool-executor.js +4 -2
  321. package/dist/tool/tool-executor.js.map +1 -1
  322. package/dist/tool/tool-executor.test.js +2 -2
  323. package/dist/tool/tool-registry.test.js +1 -1
  324. package/dist/tool/zod-to-json-schema.d.ts +7 -0
  325. package/dist/tool/zod-to-json-schema.d.ts.map +1 -0
  326. package/dist/tool/zod-to-json-schema.js +12 -0
  327. package/dist/tool/zod-to-json-schema.js.map +1 -0
  328. package/dist/tool/zod-to-json-schema.test.d.ts +2 -0
  329. package/dist/tool/zod-to-json-schema.test.d.ts.map +1 -0
  330. package/dist/tool/zod-to-json-schema.test.js +127 -0
  331. package/dist/tool/zod-to-json-schema.test.js.map +1 -0
  332. package/dist/webhook/index.d.ts +4 -0
  333. package/dist/webhook/index.d.ts.map +1 -0
  334. package/dist/webhook/index.js +3 -0
  335. package/dist/webhook/index.js.map +1 -0
  336. package/dist/webhook/webhook-delivery.d.ts +12 -0
  337. package/dist/webhook/webhook-delivery.d.ts.map +1 -0
  338. package/dist/webhook/webhook-delivery.js +102 -0
  339. package/dist/webhook/webhook-delivery.js.map +1 -0
  340. package/dist/webhook/webhook-delivery.test.d.ts +2 -0
  341. package/dist/webhook/webhook-delivery.test.d.ts.map +1 -0
  342. package/dist/webhook/webhook-delivery.test.js +284 -0
  343. package/dist/webhook/webhook-delivery.test.js.map +1 -0
  344. package/dist/webhook/webhook-signer.d.ts +14 -0
  345. package/dist/webhook/webhook-signer.d.ts.map +1 -0
  346. package/dist/webhook/webhook-signer.js +31 -0
  347. package/dist/webhook/webhook-signer.js.map +1 -0
  348. package/dist/webhook/webhook-signer.test.d.ts +2 -0
  349. package/dist/webhook/webhook-signer.test.d.ts.map +1 -0
  350. package/dist/webhook/webhook-signer.test.js +74 -0
  351. package/dist/webhook/webhook-signer.test.js.map +1 -0
  352. package/dist/workflow/compile.js +4 -1
  353. package/dist/workflow/compile.js.map +1 -1
  354. package/dist/workflow/compile.test.js +1 -1
  355. package/dist/workflow/evaluate-nodes.d.ts +24 -0
  356. package/dist/workflow/evaluate-nodes.d.ts.map +1 -0
  357. package/dist/workflow/evaluate-nodes.js +126 -0
  358. package/dist/workflow/evaluate-nodes.js.map +1 -0
  359. package/dist/workflow/evaluate-nodes.test.d.ts +2 -0
  360. package/dist/workflow/evaluate-nodes.test.d.ts.map +1 -0
  361. package/dist/workflow/evaluate-nodes.test.js +363 -0
  362. package/dist/workflow/evaluate-nodes.test.js.map +1 -0
  363. package/dist/workflow/index.d.ts +8 -3
  364. package/dist/workflow/index.d.ts.map +1 -1
  365. package/dist/workflow/index.js +4 -2
  366. package/dist/workflow/index.js.map +1 -1
  367. package/dist/workflow/node-executor.d.ts +40 -0
  368. package/dist/workflow/node-executor.d.ts.map +1 -0
  369. package/dist/workflow/node-executor.js +2 -0
  370. package/dist/workflow/node-executor.js.map +1 -0
  371. package/dist/workflow/node-executor.test.d.ts +2 -0
  372. package/dist/workflow/node-executor.test.d.ts.map +1 -0
  373. package/dist/workflow/node-executor.test.js +91 -0
  374. package/dist/workflow/node-executor.test.js.map +1 -0
  375. package/dist/workflow/status.test.js +1 -1
  376. package/dist/workflow/workflow-runner.d.ts +57 -0
  377. package/dist/workflow/workflow-runner.d.ts.map +1 -0
  378. package/dist/workflow/workflow-runner.js +263 -0
  379. package/dist/workflow/workflow-runner.js.map +1 -0
  380. package/dist/workflow/workflow-runner.test.d.ts +2 -0
  381. package/dist/workflow/workflow-runner.test.d.ts.map +1 -0
  382. package/dist/workflow/workflow-runner.test.js +657 -0
  383. package/dist/workflow/workflow-runner.test.js.map +1 -0
  384. package/package.json +9 -4
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=webhook-signer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-signer.test.d.ts","sourceRoot":"","sources":["../../src/webhook/webhook-signer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,74 @@
1
+ import { createHmac } from 'node:crypto';
2
+ import { describe, it, expect } from 'vitest';
3
+ import { signPayload, verifySignature } from './webhook-signer.js';
4
+ describe('webhook-signer', () => {
5
+ const secret = 'test-webhook-secret-key';
6
+ const payload = JSON.stringify({ event: 'entity.created', data: { id: '123' } });
7
+ describe('signPayload', () => {
8
+ it('produces a sha256-prefixed hex signature', () => {
9
+ const sig = signPayload(payload, secret);
10
+ expect(sig).toMatch(/^sha256=[0-9a-f]{64}$/);
11
+ });
12
+ it('matches manual HMAC-SHA256 computation', () => {
13
+ const sig = signPayload(payload, secret);
14
+ const expected = createHmac('sha256', secret).update(payload).digest('hex');
15
+ expect(sig).toBe(`sha256=${expected}`);
16
+ });
17
+ it('produces deterministic output for same input', () => {
18
+ const sig1 = signPayload(payload, secret);
19
+ const sig2 = signPayload(payload, secret);
20
+ expect(sig1).toBe(sig2);
21
+ });
22
+ it('produces different signatures for different payloads', () => {
23
+ const sig1 = signPayload('payload-a', secret);
24
+ const sig2 = signPayload('payload-b', secret);
25
+ expect(sig1).not.toBe(sig2);
26
+ });
27
+ it('produces different signatures for different secrets', () => {
28
+ const sig1 = signPayload(payload, 'secret-a');
29
+ const sig2 = signPayload(payload, 'secret-b');
30
+ expect(sig1).not.toBe(sig2);
31
+ });
32
+ it('handles empty payload', () => {
33
+ const sig = signPayload('', secret);
34
+ expect(sig).toMatch(/^sha256=[0-9a-f]{64}$/);
35
+ });
36
+ it('handles empty secret', () => {
37
+ const sig = signPayload(payload, '');
38
+ expect(sig).toMatch(/^sha256=[0-9a-f]{64}$/);
39
+ });
40
+ });
41
+ describe('verifySignature', () => {
42
+ it('returns true for a valid signature', () => {
43
+ const sig = signPayload(payload, secret);
44
+ expect(verifySignature(payload, sig, secret)).toBe(true);
45
+ });
46
+ it('returns false for a wrong signature', () => {
47
+ expect(verifySignature(payload, 'sha256=0000000000000000000000000000000000000000000000000000000000000000', secret)).toBe(false);
48
+ });
49
+ it('returns false for a completely malformed signature', () => {
50
+ expect(verifySignature(payload, 'not-a-real-signature', secret)).toBe(false);
51
+ });
52
+ it('returns false for wrong secret', () => {
53
+ const sig = signPayload(payload, secret);
54
+ expect(verifySignature(payload, sig, 'wrong-secret')).toBe(false);
55
+ });
56
+ it('returns false for tampered payload', () => {
57
+ const sig = signPayload(payload, secret);
58
+ expect(verifySignature(payload + 'tampered', sig, secret)).toBe(false);
59
+ });
60
+ it('returns false for empty signature', () => {
61
+ expect(verifySignature(payload, '', secret)).toBe(false);
62
+ });
63
+ it('returns false for signature with wrong length', () => {
64
+ expect(verifySignature(payload, 'sha256=abc', secret)).toBe(false);
65
+ });
66
+ it('is consistent across multiple verifications', () => {
67
+ const sig = signPayload(payload, secret);
68
+ for (let i = 0; i < 10; i++) {
69
+ expect(verifySignature(payload, sig, secret)).toBe(true);
70
+ }
71
+ });
72
+ });
73
+ });
74
+ //# sourceMappingURL=webhook-signer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-signer.test.js","sourceRoot":"","sources":["../../src/webhook/webhook-signer.test.ts"],"names":[],"mappings":"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"}
@@ -100,7 +100,10 @@ function sortFieldsByDependency(fields) {
100
100
  if (!fieldSet.has(dep))
101
101
  continue;
102
102
  inDegree.set(name, (inDegree.get(name) ?? 0) + 1);
103
- dependents.get(dep).push(name);
103
+ const depList = dependents.get(dep);
104
+ if (depList) {
105
+ depList.push(name);
106
+ }
104
107
  }
105
108
  }
106
109
  const layers = [];
@@ -1 +1 @@
1
- {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/workflow/compile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/workflow/compile.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { compileEntityWorkflowDefinition, getWorkflowLayers } from './compile';
2
+ import { compileEntityWorkflowDefinition, getWorkflowLayers } from './compile.js';
3
3
  function makeEntityType(fields) {
4
4
  return {
5
5
  id: 'et-1',
@@ -0,0 +1,24 @@
1
+ import type { WorkflowNodeRunRecord, WorkflowNodeStatus } from '@sprinterai/core';
2
+ /** A status update to apply to a node run. */
3
+ export interface NodeStatusUpdate {
4
+ nodeRunId: string;
5
+ nodeKey: string;
6
+ previousStatus: WorkflowNodeStatus;
7
+ newStatus: WorkflowNodeStatus;
8
+ }
9
+ /**
10
+ * Evaluate node statuses based on entity content and dependency state.
11
+ *
12
+ * This implements the core scheduling logic:
13
+ * - `wait_human` nodes: completed if field populated, waiting_human if deps met, blocked otherwise
14
+ * - `agent_task` nodes: completed if field populated (unless force), pending if deps met, blocked otherwise
15
+ * - Terminal/in-progress nodes are not re-evaluated (unless force clears completed status)
16
+ *
17
+ * Uses multi-pass convergence: evaluates all nodes, applies changes to a virtual
18
+ * status map, and re-evaluates until no more changes occur. This ensures downstream
19
+ * nodes see their dependencies' new statuses within the same evaluation call.
20
+ *
21
+ * Returns only the nodes whose status changed from their original status.
22
+ */
23
+ export declare function evaluateNodeStatuses(nodeRuns: WorkflowNodeRunRecord[], entityContent: Record<string, unknown>, force?: boolean): NodeStatusUpdate[];
24
+ //# sourceMappingURL=evaluate-nodes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate-nodes.d.ts","sourceRoot":"","sources":["../../src/workflow/evaluate-nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAElF,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,kBAAkB,CAAC;IACnC,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAoCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,qBAAqB,EAAE,EACjC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,KAAK,CAAC,EAAE,OAAO,GACd,gBAAgB,EAAE,CAgEpB"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * In-progress statuses that should not be re-evaluated.
3
+ * A running node stays running until the executor finishes.
4
+ */
5
+ const IN_PROGRESS_STATUSES = new Set(['running']);
6
+ /**
7
+ * Check if a field has a non-empty value in entity content.
8
+ * null, undefined, empty string, and empty arrays are considered empty.
9
+ */
10
+ function fieldHasValue(entityContent, fieldName) {
11
+ const value = entityContent[fieldName];
12
+ if (value === null || value === undefined || value === '')
13
+ return false;
14
+ if (Array.isArray(value) && value.length === 0)
15
+ return false;
16
+ return true;
17
+ }
18
+ /**
19
+ * Check whether all dependencies of a node are satisfied (completed)
20
+ * using the resolved status map (which reflects in-progress evaluation).
21
+ */
22
+ function areDependenciesSatisfied(node, resolvedStatuses) {
23
+ const deps = node.depends_on;
24
+ if (!deps || deps.length === 0)
25
+ return true;
26
+ return deps.every((depKey) => {
27
+ const depStatus = resolvedStatuses.get(depKey);
28
+ return depStatus === 'completed';
29
+ });
30
+ }
31
+ /**
32
+ * Evaluate node statuses based on entity content and dependency state.
33
+ *
34
+ * This implements the core scheduling logic:
35
+ * - `wait_human` nodes: completed if field populated, waiting_human if deps met, blocked otherwise
36
+ * - `agent_task` nodes: completed if field populated (unless force), pending if deps met, blocked otherwise
37
+ * - Terminal/in-progress nodes are not re-evaluated (unless force clears completed status)
38
+ *
39
+ * Uses multi-pass convergence: evaluates all nodes, applies changes to a virtual
40
+ * status map, and re-evaluates until no more changes occur. This ensures downstream
41
+ * nodes see their dependencies' new statuses within the same evaluation call.
42
+ *
43
+ * Returns only the nodes whose status changed from their original status.
44
+ */
45
+ export function evaluateNodeStatuses(nodeRuns, entityContent, force) {
46
+ if (nodeRuns.length === 0)
47
+ return [];
48
+ // Build lookup maps
49
+ const nodesByKey = new Map();
50
+ const originalStatuses = new Map();
51
+ const resolvedStatuses = new Map();
52
+ for (const node of nodeRuns) {
53
+ nodesByKey.set(node.node_key, node);
54
+ originalStatuses.set(node.node_key, node.status);
55
+ resolvedStatuses.set(node.node_key, node.status);
56
+ }
57
+ // Multi-pass: keep evaluating until no more changes
58
+ const maxPasses = nodeRuns.length + 1; // At most N passes for N-deep dependency chains
59
+ for (let pass = 0; pass < maxPasses; pass++) {
60
+ let changed = false;
61
+ for (const node of nodeRuns) {
62
+ const currentResolved = resolvedStatuses.get(node.node_key);
63
+ // Running nodes are never re-evaluated -- they're in-flight
64
+ if (IN_PROGRESS_STATUSES.has(currentResolved)) {
65
+ continue;
66
+ }
67
+ // Failed/skipped nodes are terminal -- never re-evaluated
68
+ if (currentResolved === 'failed' || currentResolved === 'skipped') {
69
+ continue;
70
+ }
71
+ // Completed nodes stay completed unless force is specified
72
+ if (currentResolved === 'completed' && !force) {
73
+ continue;
74
+ }
75
+ const newStatus = evaluateSingleNode(node, entityContent, resolvedStatuses, force);
76
+ if (newStatus !== currentResolved) {
77
+ resolvedStatuses.set(node.node_key, newStatus);
78
+ changed = true;
79
+ }
80
+ }
81
+ if (!changed)
82
+ break;
83
+ }
84
+ // Build updates: compare original vs resolved
85
+ const updates = [];
86
+ for (const node of nodeRuns) {
87
+ const original = originalStatuses.get(node.node_key);
88
+ const resolved = resolvedStatuses.get(node.node_key);
89
+ if (resolved !== original) {
90
+ updates.push({
91
+ nodeRunId: node.id,
92
+ nodeKey: node.node_key,
93
+ previousStatus: original,
94
+ newStatus: resolved,
95
+ });
96
+ }
97
+ }
98
+ return updates;
99
+ }
100
+ /**
101
+ * Evaluate the desired status for a single node.
102
+ */
103
+ function evaluateSingleNode(node, entityContent, resolvedStatuses, force) {
104
+ const hasFieldValue = node.field_name ? fieldHasValue(entityContent, node.field_name) : false;
105
+ const depsSatisfied = areDependenciesSatisfied(node, resolvedStatuses);
106
+ if (node.node_type === 'wait_human') {
107
+ // Human-input nodes complete when the field is populated
108
+ if (hasFieldValue)
109
+ return 'completed';
110
+ // If deps are met, wait for human input
111
+ if (depsSatisfied)
112
+ return 'waiting_human';
113
+ // Otherwise blocked
114
+ return 'blocked';
115
+ }
116
+ // agent_task (and legacy types)
117
+ // If field already has a value and we're not forcing, mark completed
118
+ if (hasFieldValue && !force)
119
+ return 'completed';
120
+ // If deps are met, mark pending (ready to be claimed)
121
+ if (depsSatisfied)
122
+ return 'pending';
123
+ // Otherwise blocked
124
+ return 'blocked';
125
+ }
126
+ //# sourceMappingURL=evaluate-nodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate-nodes.js","sourceRoot":"","sources":["../../src/workflow/evaluate-nodes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=evaluate-nodes.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate-nodes.test.d.ts","sourceRoot":"","sources":["../../src/workflow/evaluate-nodes.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,363 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { evaluateNodeStatuses } from './evaluate-nodes.js';
3
+ function makeNodeRun(overrides) {
4
+ const { node_key, ...rest } = overrides;
5
+ return {
6
+ id: `nr-${node_key}`,
7
+ workflow_run_id: 'run-1',
8
+ entity_id: 'ent-1',
9
+ tenant_id: 'ten-1',
10
+ node_key,
11
+ node_type: 'agent_task',
12
+ label: node_key,
13
+ field_name: null,
14
+ block_id: null,
15
+ output_type: 'field',
16
+ status: 'pending',
17
+ assignee_type: 'agent',
18
+ assignee_agent_slug: null,
19
+ depends_on: null,
20
+ instructions: null,
21
+ metadata: null,
22
+ error_message: null,
23
+ claimed_by: null,
24
+ claimed_at: null,
25
+ attempt_count: 0,
26
+ started_at: null,
27
+ completed_at: null,
28
+ duration_ms: null,
29
+ created_at: new Date().toISOString(),
30
+ ...rest,
31
+ };
32
+ }
33
+ describe('evaluateNodeStatuses', () => {
34
+ describe('agent_task nodes', () => {
35
+ it('marks nodes pending when no deps and no existing value', () => {
36
+ const nodes = [
37
+ makeNodeRun({
38
+ node_key: 'agent_task:title',
39
+ field_name: 'title',
40
+ status: 'blocked',
41
+ }),
42
+ ];
43
+ const updates = evaluateNodeStatuses(nodes, {});
44
+ expect(updates).toHaveLength(1);
45
+ expect(updates[0].newStatus).toBe('pending');
46
+ });
47
+ it('marks nodes completed when field already has value', () => {
48
+ const nodes = [
49
+ makeNodeRun({
50
+ node_key: 'agent_task:title',
51
+ field_name: 'title',
52
+ status: 'pending',
53
+ }),
54
+ ];
55
+ const updates = evaluateNodeStatuses(nodes, { title: 'My Title' });
56
+ expect(updates).toHaveLength(1);
57
+ expect(updates[0].newStatus).toBe('completed');
58
+ });
59
+ it('keeps nodes blocked when deps not satisfied', () => {
60
+ const nodes = [
61
+ makeNodeRun({
62
+ node_key: 'agent_task:title',
63
+ field_name: 'title',
64
+ status: 'completed',
65
+ }),
66
+ makeNodeRun({
67
+ node_key: 'agent_task:summary',
68
+ field_name: 'summary',
69
+ status: 'blocked',
70
+ depends_on: ['agent_task:title'],
71
+ }),
72
+ ];
73
+ // title dep is completed but summary field empty -> pending (deps satisfied)
74
+ const updates = evaluateNodeStatuses(nodes, { title: 'value' });
75
+ expect(updates).toHaveLength(1);
76
+ expect(updates[0].nodeKey).toBe('agent_task:summary');
77
+ expect(updates[0].newStatus).toBe('pending');
78
+ });
79
+ it('stays blocked when dependency is not completed', () => {
80
+ const nodes = [
81
+ makeNodeRun({
82
+ node_key: 'agent_task:title',
83
+ field_name: 'title',
84
+ status: 'pending',
85
+ }),
86
+ makeNodeRun({
87
+ node_key: 'agent_task:summary',
88
+ field_name: 'summary',
89
+ status: 'blocked',
90
+ depends_on: ['agent_task:title'],
91
+ }),
92
+ ];
93
+ const updates = evaluateNodeStatuses(nodes, {});
94
+ // title stays pending (no change), summary stays blocked (no change)
95
+ expect(updates).toHaveLength(0);
96
+ });
97
+ it('does not re-evaluate running nodes', () => {
98
+ const nodes = [
99
+ makeNodeRun({
100
+ node_key: 'agent_task:title',
101
+ field_name: 'title',
102
+ status: 'running',
103
+ }),
104
+ ];
105
+ const updates = evaluateNodeStatuses(nodes, { title: 'already populated' });
106
+ expect(updates).toHaveLength(0);
107
+ });
108
+ it('does not re-evaluate failed nodes', () => {
109
+ const nodes = [
110
+ makeNodeRun({
111
+ node_key: 'agent_task:title',
112
+ field_name: 'title',
113
+ status: 'failed',
114
+ }),
115
+ ];
116
+ const updates = evaluateNodeStatuses(nodes, {});
117
+ expect(updates).toHaveLength(0);
118
+ });
119
+ it('does not re-evaluate skipped nodes', () => {
120
+ const nodes = [
121
+ makeNodeRun({
122
+ node_key: 'agent_task:title',
123
+ field_name: 'title',
124
+ status: 'skipped',
125
+ }),
126
+ ];
127
+ const updates = evaluateNodeStatuses(nodes, {});
128
+ expect(updates).toHaveLength(0);
129
+ });
130
+ it('does not re-evaluate completed nodes without force', () => {
131
+ const nodes = [
132
+ makeNodeRun({
133
+ node_key: 'agent_task:title',
134
+ field_name: 'title',
135
+ status: 'completed',
136
+ }),
137
+ ];
138
+ const updates = evaluateNodeStatuses(nodes, { title: 'value' });
139
+ expect(updates).toHaveLength(0);
140
+ });
141
+ it('force allows re-evaluating completed nodes to pending', () => {
142
+ const nodes = [
143
+ makeNodeRun({
144
+ node_key: 'agent_task:title',
145
+ field_name: 'title',
146
+ status: 'completed',
147
+ }),
148
+ ];
149
+ // With force=true and field populated, the node should still become pending
150
+ // because force overrides the "field has value => completed" logic
151
+ const updates = evaluateNodeStatuses(nodes, { title: 'value' }, true);
152
+ // With force, field has value check is bypassed -> deps satisfied -> pending
153
+ expect(updates).toHaveLength(1);
154
+ expect(updates[0].newStatus).toBe('pending');
155
+ });
156
+ it('force re-evaluates completed nodes to pending when field has value', () => {
157
+ const nodes = [
158
+ makeNodeRun({
159
+ node_key: 'agent_task:title',
160
+ field_name: 'title',
161
+ status: 'completed',
162
+ }),
163
+ ];
164
+ const updates = evaluateNodeStatuses(nodes, {}, true);
165
+ expect(updates).toHaveLength(1);
166
+ expect(updates[0].newStatus).toBe('pending');
167
+ });
168
+ });
169
+ describe('wait_human nodes', () => {
170
+ it('marks waiting_human when deps satisfied and no field value', () => {
171
+ const nodes = [
172
+ makeNodeRun({
173
+ node_key: 'wait_human:notes',
174
+ node_type: 'wait_human',
175
+ field_name: 'notes',
176
+ status: 'blocked',
177
+ }),
178
+ ];
179
+ const updates = evaluateNodeStatuses(nodes, {});
180
+ expect(updates).toHaveLength(1);
181
+ expect(updates[0].newStatus).toBe('waiting_human');
182
+ });
183
+ it('marks completed when field has value', () => {
184
+ const nodes = [
185
+ makeNodeRun({
186
+ node_key: 'wait_human:notes',
187
+ node_type: 'wait_human',
188
+ field_name: 'notes',
189
+ status: 'waiting_human',
190
+ }),
191
+ ];
192
+ const updates = evaluateNodeStatuses(nodes, { notes: 'User provided notes' });
193
+ expect(updates).toHaveLength(1);
194
+ expect(updates[0].newStatus).toBe('completed');
195
+ });
196
+ it('stays blocked when deps not met', () => {
197
+ const nodes = [
198
+ makeNodeRun({
199
+ node_key: 'agent_task:title',
200
+ field_name: 'title',
201
+ status: 'pending',
202
+ }),
203
+ makeNodeRun({
204
+ node_key: 'wait_human:notes',
205
+ node_type: 'wait_human',
206
+ field_name: 'notes',
207
+ status: 'blocked',
208
+ depends_on: ['agent_task:title'],
209
+ }),
210
+ ];
211
+ const updates = evaluateNodeStatuses(nodes, {});
212
+ // notes stays blocked
213
+ expect(updates).toHaveLength(0);
214
+ });
215
+ });
216
+ describe('empty field value detection', () => {
217
+ it('treats null as empty', () => {
218
+ const nodes = [
219
+ makeNodeRun({
220
+ node_key: 'agent_task:title',
221
+ field_name: 'title',
222
+ status: 'blocked',
223
+ }),
224
+ ];
225
+ const updates = evaluateNodeStatuses(nodes, { title: null });
226
+ expect(updates[0].newStatus).toBe('pending');
227
+ });
228
+ it('treats undefined as empty', () => {
229
+ const nodes = [
230
+ makeNodeRun({
231
+ node_key: 'agent_task:title',
232
+ field_name: 'title',
233
+ status: 'blocked',
234
+ }),
235
+ ];
236
+ const updates = evaluateNodeStatuses(nodes, { title: undefined });
237
+ expect(updates[0].newStatus).toBe('pending');
238
+ });
239
+ it('treats empty string as empty', () => {
240
+ const nodes = [
241
+ makeNodeRun({
242
+ node_key: 'agent_task:title',
243
+ field_name: 'title',
244
+ status: 'blocked',
245
+ }),
246
+ ];
247
+ const updates = evaluateNodeStatuses(nodes, { title: '' });
248
+ expect(updates[0].newStatus).toBe('pending');
249
+ });
250
+ it('treats empty array as empty', () => {
251
+ const nodes = [
252
+ makeNodeRun({
253
+ node_key: 'agent_task:tags',
254
+ field_name: 'tags',
255
+ status: 'blocked',
256
+ }),
257
+ ];
258
+ const updates = evaluateNodeStatuses(nodes, { tags: [] });
259
+ expect(updates[0].newStatus).toBe('pending');
260
+ });
261
+ it('treats non-empty array as populated', () => {
262
+ const nodes = [
263
+ makeNodeRun({
264
+ node_key: 'agent_task:tags',
265
+ field_name: 'tags',
266
+ status: 'pending',
267
+ }),
268
+ ];
269
+ const updates = evaluateNodeStatuses(nodes, { tags: ['a'] });
270
+ expect(updates[0].newStatus).toBe('completed');
271
+ });
272
+ it('treats zero as populated', () => {
273
+ const nodes = [
274
+ makeNodeRun({
275
+ node_key: 'agent_task:count',
276
+ field_name: 'count',
277
+ status: 'pending',
278
+ }),
279
+ ];
280
+ const updates = evaluateNodeStatuses(nodes, { count: 0 });
281
+ expect(updates[0].newStatus).toBe('completed');
282
+ });
283
+ it('treats false as populated', () => {
284
+ const nodes = [
285
+ makeNodeRun({
286
+ node_key: 'agent_task:active',
287
+ field_name: 'active',
288
+ status: 'pending',
289
+ }),
290
+ ];
291
+ const updates = evaluateNodeStatuses(nodes, { active: false });
292
+ expect(updates[0].newStatus).toBe('completed');
293
+ });
294
+ });
295
+ describe('complex dependency graphs', () => {
296
+ it('handles diamond dependencies (A -> B, A -> C, B+C -> D)', () => {
297
+ const nodes = [
298
+ makeNodeRun({
299
+ node_key: 'agent_task:a',
300
+ field_name: 'a',
301
+ status: 'completed',
302
+ }),
303
+ makeNodeRun({
304
+ node_key: 'agent_task:b',
305
+ field_name: 'b',
306
+ status: 'blocked',
307
+ depends_on: ['agent_task:a'],
308
+ }),
309
+ makeNodeRun({
310
+ node_key: 'agent_task:c',
311
+ field_name: 'c',
312
+ status: 'blocked',
313
+ depends_on: ['agent_task:a'],
314
+ }),
315
+ makeNodeRun({
316
+ node_key: 'agent_task:d',
317
+ field_name: 'd',
318
+ status: 'blocked',
319
+ depends_on: ['agent_task:b', 'agent_task:c'],
320
+ }),
321
+ ];
322
+ const updates = evaluateNodeStatuses(nodes, { a: 'done' });
323
+ // b and c should become pending, d stays blocked
324
+ const updateMap = new Map(updates.map((u) => [u.nodeKey, u.newStatus]));
325
+ expect(updateMap.get('agent_task:b')).toBe('pending');
326
+ expect(updateMap.get('agent_task:c')).toBe('pending');
327
+ expect(updateMap.has('agent_task:d')).toBe(false); // stays blocked
328
+ });
329
+ it('handles nodes without field_name', () => {
330
+ const nodes = [
331
+ makeNodeRun({
332
+ node_key: 'agent_task:process',
333
+ field_name: null,
334
+ status: 'blocked',
335
+ output_type: 'none',
336
+ }),
337
+ ];
338
+ // No field_name means hasFieldValue is false -> deps satisfied -> pending
339
+ const updates = evaluateNodeStatuses(nodes, {});
340
+ expect(updates).toHaveLength(1);
341
+ expect(updates[0].newStatus).toBe('pending');
342
+ });
343
+ });
344
+ describe('no changes', () => {
345
+ it('returns empty array when no status changes needed', () => {
346
+ const nodes = [
347
+ makeNodeRun({
348
+ node_key: 'agent_task:title',
349
+ field_name: 'title',
350
+ status: 'pending',
351
+ }),
352
+ ];
353
+ // pending with no deps and no field value -> stays pending
354
+ const updates = evaluateNodeStatuses(nodes, {});
355
+ expect(updates).toHaveLength(0);
356
+ });
357
+ it('returns empty for empty input', () => {
358
+ const updates = evaluateNodeStatuses([], {});
359
+ expect(updates).toHaveLength(0);
360
+ });
361
+ });
362
+ });
363
+ //# sourceMappingURL=evaluate-nodes.test.js.map