@swirls/looms 0.0.2 → 0.2.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 (375) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/dist/actor/cell.d.ts +9 -4
  3. package/dist/actor/cell.js +7 -11
  4. package/dist/actor/host.d.ts +7 -3
  5. package/dist/actor/host.js +57 -33
  6. package/dist/actor/index.d.ts +1 -1
  7. package/dist/actor/index.js +1 -1
  8. package/dist/actor/routing.d.ts +12 -1
  9. package/dist/actor/routing.js +57 -51
  10. package/dist/agent/agent-session.d.ts +5 -0
  11. package/dist/agent/agent-session.js +270 -0
  12. package/dist/agent/debugger/agent-chat.d.ts +2 -0
  13. package/dist/agent/debugger/agent-chat.js +176 -0
  14. package/dist/agent/debugger/index.d.ts +5 -0
  15. package/dist/agent/debugger/index.js +19 -0
  16. package/dist/agent/debugger/summarize.d.ts +2 -0
  17. package/dist/agent/debugger/summarize.js +51 -0
  18. package/dist/agent/debugger/token-usage.d.ts +3 -0
  19. package/dist/agent/debugger/token-usage.js +11 -0
  20. package/dist/agent/definitions-store.d.ts +2 -3
  21. package/dist/agent/definitions-store.js +2 -4
  22. package/dist/agent/definitions.d.ts +47 -29
  23. package/dist/agent/definitions.js +39 -12
  24. package/dist/agent/effects.d.ts +359 -2
  25. package/dist/agent/effects.js +60 -34
  26. package/dist/agent/events.d.ts +175 -19
  27. package/dist/agent/events.js +45 -10
  28. package/dist/agent/index.d.ts +1 -0
  29. package/dist/agent/index.js +1 -0
  30. package/dist/agent/llm.d.ts +11 -2
  31. package/dist/agent/llm.js +13 -3
  32. package/dist/agent/module.d.ts +812 -78
  33. package/dist/agent/module.js +16 -4
  34. package/dist/agent/scope.d.ts +174 -18
  35. package/dist/agent/signals.d.ts +26 -1
  36. package/dist/agent/signals.js +79 -0
  37. package/dist/agent/threads.d.ts +3 -33
  38. package/dist/agent/threads.js +20 -25
  39. package/dist/agent/tool-schema.d.ts +1 -17
  40. package/dist/agent/tool-schema.js +3 -43
  41. package/dist/agent/types.d.ts +49 -4
  42. package/dist/agent/types.js +5 -5
  43. package/dist/ai-vercel/index.d.ts +1 -0
  44. package/dist/ai-vercel/index.js +1 -0
  45. package/dist/ai-vercel/messages.js +22 -7
  46. package/dist/ai-vercel/vercel-evaluator.d.ts +36 -0
  47. package/dist/ai-vercel/vercel-evaluator.js +73 -0
  48. package/dist/ai-vercel/vercel-llm.js +64 -44
  49. package/dist/approval/debugger/approvals-view.d.ts +3 -0
  50. package/dist/approval/debugger/approvals-view.js +16 -0
  51. package/dist/approval/debugger/index.d.ts +4 -0
  52. package/dist/approval/debugger/index.js +11 -0
  53. package/dist/approval/debugger/summarize.d.ts +2 -0
  54. package/dist/approval/debugger/summarize.js +17 -0
  55. package/dist/approval/effects.d.ts +89 -0
  56. package/dist/approval/module.d.ts +179 -29
  57. package/dist/approval/projections.d.ts +0 -14
  58. package/dist/approval/projections.js +20 -3
  59. package/dist/approval/signals.d.ts +2 -0
  60. package/dist/approval/signals.js +18 -2
  61. package/dist/cli/cli.js +2 -0
  62. package/dist/cli/commands.js +12 -16
  63. package/dist/client/client.d.ts +1213 -18
  64. package/dist/client/client.js +120 -120
  65. package/dist/client/index.d.ts +1 -1
  66. package/dist/client/index.js +1 -1
  67. package/dist/client/sse.d.ts +13 -0
  68. package/dist/client/sse.js +38 -44
  69. package/dist/cloudflare/alarm-scheduler.d.ts +12 -2
  70. package/dist/cloudflare/alarm-scheduler.js +34 -7
  71. package/dist/cloudflare/durable-object.d.ts +10 -2
  72. package/dist/cloudflare/durable-object.js +59 -28
  73. package/dist/cloudflare/event-store.d.ts +7 -2
  74. package/dist/cloudflare/event-store.js +8 -7
  75. package/dist/cloudflare/index.d.ts +2 -2
  76. package/dist/cloudflare/index.js +2 -2
  77. package/dist/cloudflare/router.d.ts +1 -1
  78. package/dist/cloudflare/router.js +15 -16
  79. package/dist/core/catalog.d.ts +3 -3
  80. package/dist/core/catalog.js +2 -5
  81. package/dist/core/coalesce.js +5 -3
  82. package/dist/core/compose.d.ts +2 -1
  83. package/dist/core/compose.js +19 -2
  84. package/dist/core/debugger-host.d.ts +16 -0
  85. package/dist/core/debugger-host.js +1 -0
  86. package/dist/core/definition-store.d.ts +11 -0
  87. package/dist/core/definition-store.js +6 -0
  88. package/dist/core/effects.d.ts +127 -15
  89. package/dist/core/effects.js +89 -17
  90. package/dist/core/envelope.d.ts +27 -7
  91. package/dist/core/envelope.js +20 -6
  92. package/dist/core/event-codec.d.ts +4 -2
  93. package/dist/core/event-codec.js +10 -5
  94. package/dist/core/event-index.js +1 -3
  95. package/dist/core/fold.d.ts +3 -0
  96. package/dist/core/fold.js +171 -24
  97. package/dist/core/ids.d.ts +5 -0
  98. package/dist/core/ids.js +35 -2
  99. package/dist/core/index.d.ts +7 -1
  100. package/dist/core/index.js +6 -1
  101. package/dist/core/kind.d.ts +22 -0
  102. package/dist/core/kind.js +17 -0
  103. package/dist/core/limits.d.ts +34 -0
  104. package/dist/core/limits.js +46 -0
  105. package/dist/core/match.d.ts +1 -0
  106. package/dist/core/match.js +10 -1
  107. package/dist/core/module-scope.d.ts +22 -20
  108. package/dist/core/module-scope.js +38 -28
  109. package/dist/core/module.d.ts +18 -5
  110. package/dist/core/module.js +4 -0
  111. package/dist/core/projection.d.ts +13 -13
  112. package/dist/core/projection.js +9 -5
  113. package/dist/core/protocol.d.ts +68 -11
  114. package/dist/core/protocol.js +82 -11
  115. package/dist/core/published.d.ts +43 -0
  116. package/dist/core/published.js +44 -0
  117. package/dist/core/replay.d.ts +312 -3
  118. package/dist/core/replay.js +11 -1
  119. package/dist/core/schema.d.ts +11 -20
  120. package/dist/core/schema.js +63 -80
  121. package/dist/core/serialize.js +2 -4
  122. package/dist/core/snapshot-store.d.ts +6 -1
  123. package/dist/core/snapshot-store.js +15 -2
  124. package/dist/core/snapshots.d.ts +5 -1
  125. package/dist/core/snapshots.js +10 -15
  126. package/dist/core/sqlite-store.js +95 -11
  127. package/dist/core/state.d.ts +142 -4
  128. package/dist/core/state.js +78 -0
  129. package/dist/core/store.d.ts +38 -3
  130. package/dist/core/store.js +77 -22
  131. package/dist/core/thread.d.ts +10 -9
  132. package/dist/core/types.d.ts +5 -8
  133. package/dist/core/types.js +28 -24
  134. package/dist/core/validate-event.js +14 -4
  135. package/dist/core/worker-callback.d.ts +17 -0
  136. package/dist/core/worker-callback.js +1 -0
  137. package/dist/debugger/app/assets/index-B3Ah8WAE.css +2 -0
  138. package/dist/debugger/app/assets/index-Qb371t_O.js +22 -0
  139. package/dist/debugger/app/assets/rolldown-runtime-CbXtAM7H.js +1 -0
  140. package/dist/debugger/app/assets/routes-CjtEHgPQ.js +47 -0
  141. package/dist/debugger/app/index.html +14 -0
  142. package/dist/debugger/components/composer.d.ts +17 -0
  143. package/dist/debugger/components/composer.js +25 -0
  144. package/dist/debugger/components/debugger-split.d.ts +2 -1
  145. package/dist/debugger/components/debugger-split.js +2 -2
  146. package/dist/debugger/components/event-inspector.d.ts +2 -1
  147. package/dist/debugger/components/event-inspector.js +25 -16
  148. package/dist/debugger/components/event-stream.d.ts +2 -1
  149. package/dist/debugger/components/event-stream.js +14 -74
  150. package/dist/debugger/components/follow-list.d.ts +19 -0
  151. package/dist/debugger/components/follow-list.js +96 -0
  152. package/dist/debugger/components/json-tree.d.ts +11 -0
  153. package/dist/debugger/components/json-tree.js +120 -0
  154. package/dist/debugger/components/json-view.js +2 -2
  155. package/dist/debugger/components/run-tree.js +53 -20
  156. package/dist/debugger/components/status-dot.d.ts +4 -0
  157. package/dist/debugger/components/status-dot.js +6 -2
  158. package/dist/debugger/context.d.ts +14 -0
  159. package/dist/debugger/context.js +17 -0
  160. package/dist/debugger/contracts.d.ts +7 -4
  161. package/dist/debugger/events/builtin-families.d.ts +3 -0
  162. package/dist/debugger/events/builtin-families.js +9 -0
  163. package/dist/debugger/events/catalog.d.ts +3 -4
  164. package/dist/debugger/events/catalog.js +27 -17
  165. package/dist/debugger/events/protocol-summarize.d.ts +1 -2
  166. package/dist/debugger/events/protocol-summarize.js +42 -24
  167. package/dist/debugger/index.d.ts +20 -6
  168. package/dist/debugger/index.js +19 -5
  169. package/dist/debugger/lib/cn.d.ts +1 -0
  170. package/dist/debugger/lib/cn.js +3 -0
  171. package/dist/debugger/lib/event-meta.d.ts +2 -3
  172. package/dist/debugger/lib/event-meta.js +6 -12
  173. package/dist/debugger/lib/json.d.ts +25 -0
  174. package/dist/debugger/lib/json.js +87 -0
  175. package/dist/debugger/lib/payload.d.ts +7 -0
  176. package/dist/debugger/lib/payload.js +11 -0
  177. package/dist/debugger/lib/time.d.ts +3 -0
  178. package/dist/debugger/lib/time.js +24 -0
  179. package/dist/debugger/plugin.d.ts +36 -0
  180. package/dist/debugger/plugin.js +14 -0
  181. package/dist/debugger/server/index.d.ts +14 -0
  182. package/dist/debugger/server/index.js +114 -0
  183. package/dist/debugger/shell/debugger-shell.d.ts +15 -0
  184. package/dist/debugger/shell/debugger-shell.js +43 -0
  185. package/dist/debugger/shell/definition-key.d.ts +3 -0
  186. package/dist/debugger/shell/definition-key.js +4 -0
  187. package/dist/debugger/shell/events-pane.d.ts +12 -0
  188. package/dist/debugger/shell/events-pane.js +25 -0
  189. package/dist/debugger/shell/projections-panel.d.ts +4 -0
  190. package/dist/debugger/shell/projections-panel.js +59 -0
  191. package/dist/debugger/shell/run-controls.d.ts +4 -0
  192. package/dist/debugger/shell/run-controls.js +72 -0
  193. package/dist/debugger/shell/run-search.d.ts +6 -0
  194. package/dist/debugger/shell/run-search.js +102 -0
  195. package/dist/debugger/shell/run-type-menu.d.ts +6 -0
  196. package/dist/debugger/shell/run-type-menu.js +11 -0
  197. package/dist/debugger/shell/schema-form.d.ts +31 -0
  198. package/dist/debugger/shell/schema-form.js +117 -0
  199. package/dist/debugger/shell/start-form.d.ts +3 -0
  200. package/dist/debugger/shell/start-form.js +75 -0
  201. package/dist/debugger/shell/use-start-run.d.ts +14 -0
  202. package/dist/debugger/shell/use-start-run.js +32 -0
  203. package/dist/debugger/shell/workspace.d.ts +6 -0
  204. package/dist/debugger/shell/workspace.js +15 -0
  205. package/dist/debugger/styles.css +111 -27
  206. package/dist/debugger/ui/button.d.ts +24 -0
  207. package/dist/debugger/ui/button.js +24 -0
  208. package/dist/debugger/ui/command.d.ts +9 -0
  209. package/dist/debugger/ui/command.js +24 -0
  210. package/dist/debugger/ui/dropdown-menu.d.ts +13 -0
  211. package/dist/debugger/ui/dropdown-menu.js +37 -0
  212. package/dist/debugger/ui/panel.d.ts +14 -0
  213. package/dist/debugger/ui/panel.js +16 -0
  214. package/dist/debugger/ui/popover.d.ts +7 -0
  215. package/dist/debugger/ui/popover.js +17 -0
  216. package/dist/debugger/ui/resizable.d.ts +7 -0
  217. package/dist/debugger/ui/resizable.js +14 -0
  218. package/dist/debugger/ui/scroll-area.d.ts +2 -1
  219. package/dist/debugger/ui/scroll-area.js +5 -3
  220. package/dist/debugger/ui/select.d.ts +10 -0
  221. package/dist/debugger/ui/select.js +21 -0
  222. package/dist/debugger/ui/tabs.js +2 -2
  223. package/dist/debugger/ui/textarea.d.ts +3 -0
  224. package/dist/debugger/ui/textarea.js +7 -0
  225. package/dist/evaluator/definitions-store.d.ts +11 -0
  226. package/dist/evaluator/definitions-store.js +8 -0
  227. package/dist/evaluator/definitions.d.ts +18 -0
  228. package/dist/evaluator/definitions.js +4 -0
  229. package/dist/evaluator/effects.d.ts +226 -0
  230. package/dist/evaluator/effects.js +132 -0
  231. package/dist/evaluator/evaluator.d.ts +24 -0
  232. package/dist/evaluator/evaluator.js +67 -0
  233. package/dist/evaluator/events.d.ts +59 -0
  234. package/dist/evaluator/events.js +21 -0
  235. package/dist/evaluator/index.d.ts +11 -0
  236. package/dist/evaluator/index.js +11 -0
  237. package/dist/evaluator/module.d.ts +606 -0
  238. package/dist/evaluator/module.js +25 -0
  239. package/dist/evaluator/projections.d.ts +50 -0
  240. package/dist/evaluator/projections.js +20 -0
  241. package/dist/evaluator/scope.d.ts +59 -0
  242. package/dist/evaluator/scope.js +7 -0
  243. package/dist/evaluator/signals.d.ts +3 -0
  244. package/dist/evaluator/signals.js +17 -0
  245. package/dist/evaluator/threads.d.ts +62 -0
  246. package/dist/evaluator/threads.js +117 -0
  247. package/dist/evaluator/types.d.ts +125 -0
  248. package/dist/evaluator/types.js +51 -0
  249. package/dist/projectors/delivery.d.ts +83 -0
  250. package/dist/projectors/delivery.js +182 -0
  251. package/dist/projectors/index-model.d.ts +1 -1
  252. package/dist/projectors/index-model.js +4 -6
  253. package/dist/projectors/index.d.ts +2 -0
  254. package/dist/projectors/index.js +2 -0
  255. package/dist/projectors/memory.d.ts +1 -1
  256. package/dist/projectors/memory.js +10 -8
  257. package/dist/projectors/postgres.js +44 -58
  258. package/dist/projectors/projector.d.ts +17 -0
  259. package/dist/projectors/projector.js +26 -1
  260. package/dist/projectors/sqlite-delivery.d.ts +4 -0
  261. package/dist/projectors/sqlite-delivery.js +147 -0
  262. package/dist/projectors/sqlite.js +23 -23
  263. package/dist/projectors/with-projectors.d.ts +7 -2
  264. package/dist/projectors/with-projectors.js +27 -28
  265. package/dist/react/notify.js +11 -8
  266. package/dist/react/react.d.ts +2 -3
  267. package/dist/react/react.js +14 -30
  268. package/dist/react/sse.d.ts +1 -1
  269. package/dist/react/sse.js +1 -1
  270. package/dist/react/store.d.ts +3 -3
  271. package/dist/react/store.js +109 -119
  272. package/dist/runtime/cancellation.d.ts +16 -0
  273. package/dist/runtime/cancellation.js +129 -0
  274. package/dist/runtime/deadline-transition-planner.d.ts +31 -0
  275. package/dist/runtime/deadline-transition-planner.js +139 -0
  276. package/dist/runtime/dispatch-effect.d.ts +3 -2
  277. package/dist/runtime/dispatch-effect.js +7 -13
  278. package/dist/runtime/errors.d.ts +51 -0
  279. package/dist/runtime/errors.js +39 -0
  280. package/dist/runtime/{runtime-helpers.d.ts → helpers.d.ts} +24 -4
  281. package/dist/runtime/{runtime-helpers.js → helpers.js} +56 -19
  282. package/dist/runtime/index.d.ts +3 -3
  283. package/dist/runtime/index.js +3 -3
  284. package/dist/runtime/ingress.d.ts +15 -0
  285. package/dist/runtime/ingress.js +42 -0
  286. package/dist/runtime/local-effect-executor.d.ts +21 -0
  287. package/dist/runtime/local-effect-executor.js +137 -0
  288. package/dist/runtime/looms.d.ts +30 -4
  289. package/dist/runtime/looms.js +57 -37
  290. package/dist/runtime/observer.d.ts +45 -0
  291. package/dist/runtime/observer.js +11 -0
  292. package/dist/runtime/repository.d.ts +55 -0
  293. package/dist/runtime/repository.js +293 -0
  294. package/dist/runtime/retry-policy.d.ts +16 -0
  295. package/dist/runtime/retry-policy.js +29 -0
  296. package/dist/runtime/run-execution-context.d.ts +30 -0
  297. package/dist/runtime/run-execution-context.js +56 -0
  298. package/dist/runtime/run-start.d.ts +4 -0
  299. package/dist/runtime/run-start.js +44 -0
  300. package/dist/runtime/runtime.d.ts +6 -87
  301. package/dist/runtime/runtime.js +248 -470
  302. package/dist/runtime/server/auth.d.ts +41 -0
  303. package/dist/runtime/server/auth.js +45 -0
  304. package/dist/runtime/server/debugger-host.d.ts +11 -0
  305. package/dist/runtime/server/debugger-host.js +32 -0
  306. package/dist/runtime/server/fetch-handler.d.ts +18 -0
  307. package/dist/runtime/server/fetch-handler.js +62 -0
  308. package/dist/runtime/server/http.d.ts +38 -0
  309. package/dist/runtime/server/http.js +66 -0
  310. package/dist/runtime/server/route-table.d.ts +55 -0
  311. package/dist/runtime/server/route-table.js +74 -0
  312. package/dist/runtime/server/routes/definitions.d.ts +3 -0
  313. package/dist/runtime/server/routes/definitions.js +20 -0
  314. package/dist/runtime/server/routes/effects.d.ts +3 -0
  315. package/dist/runtime/server/routes/effects.js +59 -0
  316. package/dist/runtime/server/routes/operations.d.ts +3 -0
  317. package/dist/runtime/server/routes/operations.js +14 -0
  318. package/dist/runtime/server/routes/runs.d.ts +3 -0
  319. package/dist/runtime/server/routes/runs.js +199 -0
  320. package/dist/runtime/server.d.ts +4 -8
  321. package/dist/runtime/server.js +6 -211
  322. package/dist/runtime/sse.d.ts +2 -1
  323. package/dist/runtime/sse.js +24 -17
  324. package/dist/runtime/types.d.ts +117 -0
  325. package/dist/runtime/types.js +1 -0
  326. package/dist/runtime/wake-engine.d.ts +20 -0
  327. package/dist/runtime/wake-engine.js +311 -0
  328. package/dist/runtime/wake-scheduler.d.ts +3 -4
  329. package/dist/runtime/wake-scheduler.js +25 -31
  330. package/dist/runtime/worker-callbacks.d.ts +16 -0
  331. package/dist/runtime/worker-callbacks.js +167 -0
  332. package/dist/runtime/worker-effect-dispatch.d.ts +36 -0
  333. package/dist/runtime/worker-effect-dispatch.js +126 -0
  334. package/dist/s2/config.d.ts +1 -1
  335. package/dist/s2/config.js +1 -1
  336. package/dist/s2/lite.js +70 -82
  337. package/dist/s2/pagination.d.ts +15 -0
  338. package/dist/s2/pagination.js +36 -0
  339. package/dist/s2/projector.js +6 -5
  340. package/dist/s2/snapshot-store.js +188 -161
  341. package/dist/s2/store.d.ts +3 -21
  342. package/dist/s2/store.js +71 -165
  343. package/dist/testing/index.d.ts +15 -0
  344. package/dist/testing/index.js +53 -16
  345. package/dist/workflow/debugger/index.d.ts +4 -0
  346. package/dist/workflow/debugger/index.js +11 -0
  347. package/dist/workflow/debugger/nodes-view.d.ts +3 -0
  348. package/dist/workflow/debugger/nodes-view.js +13 -0
  349. package/dist/workflow/debugger/summarize.d.ts +2 -0
  350. package/dist/workflow/debugger/summarize.js +30 -0
  351. package/dist/workflow/definitions-store.d.ts +2 -3
  352. package/dist/workflow/definitions-store.js +2 -2
  353. package/dist/workflow/definitions.d.ts +78 -22
  354. package/dist/workflow/definitions.js +80 -14
  355. package/dist/workflow/effects.d.ts +453 -107
  356. package/dist/workflow/effects.js +214 -115
  357. package/dist/workflow/events.d.ts +149 -5
  358. package/dist/workflow/events.js +27 -5
  359. package/dist/workflow/graph.d.ts +56 -0
  360. package/dist/workflow/graph.js +207 -0
  361. package/dist/workflow/index.d.ts +1 -0
  362. package/dist/workflow/index.js +1 -0
  363. package/dist/workflow/module.d.ts +1047 -266
  364. package/dist/workflow/projections.d.ts +14 -12
  365. package/dist/workflow/projections.js +30 -8
  366. package/dist/workflow/scope.d.ts +146 -4
  367. package/dist/workflow/threads.d.ts +383 -155
  368. package/dist/workflow/threads.js +308 -110
  369. package/package.json +26 -2
  370. package/dist/debugger/events/domain-summarize.d.ts +0 -3
  371. package/dist/debugger/events/domain-summarize.js +0 -107
  372. package/dist/debugger/events/family.d.ts +0 -8
  373. package/dist/debugger/events/family.js +0 -44
  374. package/dist/runtime/events-api.d.ts +0 -4
  375. package/dist/runtime/events-api.js +0 -84
@@ -0,0 +1,126 @@
1
+ import { Effect, Predicate } from 'effect';
2
+ import { createEvent, isPrimitiveEffect, } from '@swirls/looms/core';
3
+ import { RuntimeExecutionError } from './errors.js';
4
+ import { workerTask } from './helpers.js';
5
+ function workerClaims(worker, runId, item) {
6
+ if (!worker.handles && !worker.canDispatch) {
7
+ return undefined;
8
+ }
9
+ const { handles } = worker;
10
+ const handled = Predicate.isFunction(handles)
11
+ ? handles(item.effect.type)
12
+ : (handles?.includes(item.effect.type) ?? false);
13
+ return handled || (worker.canDispatch?.(workerTask(runId, item, 0)) ?? false);
14
+ }
15
+ const WORKER_ATTEMPT_STATUSES = new Set([
16
+ 'queued',
17
+ 'dispatched',
18
+ 'started',
19
+ 'heartbeat',
20
+ 'cancel_requested',
21
+ 'timed_out',
22
+ 'ambiguous',
23
+ ]);
24
+ /**
25
+ * Decides where an outstanding effect runs. An attempt already in flight keeps
26
+ * its durable placement. Otherwise an explicit `execution` wins, then a worker
27
+ * claim; effects with a local handler run in process and handler-less effects
28
+ * go to the worker.
29
+ */
30
+ export function isWorkerEffect(input) {
31
+ const { item, execution, worker } = input;
32
+ if (isPrimitiveEffect(item.effect)) {
33
+ return false;
34
+ }
35
+ if (execution?.status === 'running') {
36
+ return false;
37
+ }
38
+ if (execution && WORKER_ATTEMPT_STATUSES.has(execution.status)) {
39
+ return true;
40
+ }
41
+ const definition = input.registry.effects.get(item.effect.type);
42
+ if (definition?.execution) {
43
+ return definition.execution === 'worker';
44
+ }
45
+ const claim = worker ? workerClaims(worker, input.runId, item) : undefined;
46
+ if (claim) {
47
+ return true;
48
+ }
49
+ if (definition) {
50
+ return !definition.hasHandler;
51
+ }
52
+ return worker !== undefined && claim !== false;
53
+ }
54
+ export function planWorkerEffects(input) {
55
+ return input.state.outstandingEffects
56
+ .filter((item) => {
57
+ const execution = input.state.effectExecutions[item.effectId];
58
+ if (!isWorkerEffect({ ...input, item, execution })) {
59
+ return false;
60
+ }
61
+ return (!execution ||
62
+ execution.status === 'queued' ||
63
+ (execution.status === 'retry_wait' &&
64
+ execution.nextAttemptAt !== null &&
65
+ execution.nextAttemptAt <= input.now + 5));
66
+ })
67
+ .map((item) => {
68
+ const existing = input.state.effectExecutions[item.effectId];
69
+ const attempt = existing?.status === 'queued' ? existing.attempt : (existing?.attempt ?? 0) + 1;
70
+ const retry = input.registry.effects.get(item.effect.type)?.retry;
71
+ return {
72
+ item,
73
+ attempt,
74
+ queuedEvent: existing?.status === 'queued'
75
+ ? undefined
76
+ : createEvent(input.runId, {
77
+ type: 'runtime.effect.queued',
78
+ payload: { effectId: item.effectId, attempt, deadlineAt: null },
79
+ threadId: item.threadId,
80
+ causationId: item.causingEventId,
81
+ origin: { type: 'system' },
82
+ }),
83
+ task: workerTask(input.runId, item, attempt),
84
+ scheduleToStartDeadlineAt: retry?.scheduleToStartTimeoutMs
85
+ ? input.now + retry.scheduleToStartTimeoutMs
86
+ : null,
87
+ };
88
+ });
89
+ }
90
+ /**
91
+ * Hand a planned attempt to the worker. A rejected dispatch may still have reached the worker, so
92
+ * with a schedule-to-start deadline it is recorded as dispatched and recovered by that timeout;
93
+ * without one it is parked as ambiguous for an operator.
94
+ */
95
+ export function dispatchWorkerEffect(runId, plan, worker) {
96
+ const dispatched = createEvent(runId, {
97
+ type: 'runtime.effect.dispatched',
98
+ payload: {
99
+ effectId: plan.item.effectId,
100
+ attempt: plan.attempt,
101
+ deadlineAt: plan.scheduleToStartDeadlineAt,
102
+ },
103
+ threadId: plan.item.threadId,
104
+ causationId: plan.item.causingEventId,
105
+ origin: { type: 'system' },
106
+ });
107
+ const ambiguous = (error) => createEvent(runId, {
108
+ type: 'runtime.effect.ambiguous',
109
+ payload: { effectId: plan.item.effectId, attempt: plan.attempt, error },
110
+ threadId: plan.item.threadId,
111
+ causationId: plan.item.causingEventId,
112
+ origin: { type: 'system' },
113
+ });
114
+ if (!worker) {
115
+ return Effect.succeed(ambiguous(`no effect worker is configured for "${plan.item.effect.type}"`));
116
+ }
117
+ return Effect.tryPromise({
118
+ try: () => Promise.resolve(worker.dispatch(plan.task)),
119
+ catch: (cause) => new RuntimeExecutionError(cause instanceof Error ? cause.message : String(cause)),
120
+ }).pipe(Effect.match({
121
+ onFailure: (error) => plan.scheduleToStartDeadlineAt === null
122
+ ? ambiguous(`worker dispatch outcome is ambiguous: ${error.message}`)
123
+ : dispatched,
124
+ onSuccess: () => dispatched,
125
+ }));
126
+ }
@@ -14,7 +14,7 @@ export declare const S2ConfigSchema: Schema.Struct<{
14
14
  }>]>>;
15
15
  readonly streamConfig: Schema.optional<Schema.Struct<{
16
16
  readonly retentionPolicy: Schema.optional<Schema.Union<readonly [Schema.Struct<{
17
- readonly ageSecs: Schema.Number;
17
+ readonly ageSecs: Schema.Finite;
18
18
  }>, Schema.Struct<{
19
19
  readonly infinite: Schema.Struct<{}>;
20
20
  }>]>>;
package/dist/s2/config.js CHANGED
@@ -17,7 +17,7 @@ export const S2ConfigSchema = Schema.Struct({
17
17
  ])),
18
18
  streamConfig: Schema.optional(Schema.Struct({
19
19
  retentionPolicy: Schema.optional(Schema.Union([
20
- Schema.Struct({ ageSecs: Schema.Number }),
20
+ Schema.Struct({ ageSecs: Schema.Finite }),
21
21
  Schema.Struct({ infinite: Schema.Struct({}) }),
22
22
  ])),
23
23
  storageClass: Schema.optional(Schema.Literals(['standard', 'express'])),
package/dist/s2/lite.js CHANGED
@@ -3,7 +3,14 @@ import * as fs from 'node:fs';
3
3
  import * as net from 'node:net';
4
4
  import * as os from 'node:os';
5
5
  import * as path from 'node:path';
6
+ import { Clock, Data, Effect } from 'effect';
6
7
  import { s2 } from './store.js';
8
+ class S2LiteError extends Data.TaggedError('S2LiteError') {
9
+ constructor(message, cause) {
10
+ super({ cause, message });
11
+ this.name = 'S2LiteError';
12
+ }
13
+ }
7
14
  export function findS2Binary(env) {
8
15
  // 1. Check PATH
9
16
  const pathDirs = (env.PATH ?? '').split(path.delimiter);
@@ -48,103 +55,84 @@ export function findS2Binary(env) {
48
55
  return undefined;
49
56
  }
50
57
  export function isPortOpen(port, host = '127.0.0.1') {
51
- return new Promise((resolve) => {
58
+ return Effect.runPromise(Effect.callback((resume) => {
52
59
  const socket = new net.Socket();
53
- socket.setTimeout(200);
54
- socket.once('connect', () => {
55
- socket.destroy();
56
- resolve(true);
57
- });
58
- socket.once('timeout', () => {
59
- socket.destroy();
60
- resolve(false);
61
- });
62
- socket.once('error', () => {
60
+ const complete = (open) => {
63
61
  socket.destroy();
64
- resolve(false);
65
- });
62
+ resume(Effect.succeed(open));
63
+ };
64
+ socket.setTimeout(200);
65
+ socket.once('connect', () => complete(true));
66
+ socket.once('timeout', () => complete(false));
67
+ socket.once('error', () => complete(false));
66
68
  socket.connect(port, host);
67
- });
69
+ return Effect.sync(() => socket.destroy());
70
+ }));
68
71
  }
69
72
  let activeProcess = null;
70
- export async function startS2Lite(options = {}) {
71
- const port = options.port ?? 8080;
72
- const endpoint = `http://127.0.0.1:${port}`;
73
- // 1. Check if an s2-lite instance is already responding on this port.
74
- const alreadyRunning = await isPortOpen(port);
75
- if (alreadyRunning) {
76
- return {
77
- port,
78
- endpoint,
79
- stop: () => {
80
- // Did not spawn this process, no-op stop.
81
- },
82
- };
83
- }
84
- // 2. Locate the s2 binary.
85
- const binaryPath = options.binaryPath ?? findS2Binary(options.env ?? {});
86
- if (!binaryPath) {
87
- throw new Error(`s2 CLI binary not found on PATH or in standard locations.
73
+ export function startS2Lite(options = {}) {
74
+ return Effect.runPromise(Effect.gen(function* () {
75
+ const port = options.port ?? 8080;
76
+ const endpoint = `http://127.0.0.1:${port}`;
77
+ if (yield* Effect.promise(() => isPortOpen(port))) {
78
+ return { port, endpoint, stop: () => undefined };
79
+ }
80
+ const binaryPath = options.binaryPath ?? findS2Binary(options.env ?? {});
81
+ if (!binaryPath) {
82
+ return yield* new S2LiteError(`s2 CLI binary not found on PATH or in standard locations.
88
83
  To install s2-lite for local development:
89
84
  flox activate # installs into $FLOX_ENV_CACHE/s2 (preferred)
90
85
  bun run setup:s2 # scripts/install-s2-cli.sh
91
86
  https://s2.dev/docs/cli/installation`);
92
- }
93
- // 3. Spawn s2 lite.
94
- // SAFETY: child_process.spawn returns child process matching S2ChildProcess.
95
- const child = childProcess.spawn(binaryPath, ['lite', '--port', String(port)], {
96
- stdio: ['ignore', 'pipe', 'pipe'],
97
- detached: false,
98
- });
99
- activeProcess = child;
100
- const cleanup = () => {
101
- if (activeProcess === child) {
102
- activeProcess = null;
103
87
  }
104
- try {
105
- child.kill('SIGTERM');
106
- }
107
- catch {
108
- // Process may already have exited.
109
- }
110
- };
111
- process.once('exit', cleanup);
112
- process.once('SIGINT', cleanup);
113
- process.once('SIGTERM', cleanup);
114
- let stderrOutput = '';
115
- child.stderr?.on('data', (chunk) => {
116
- stderrOutput += chunk.toString();
117
- });
118
- // 4. Poll until the port responds or the process exits unexpectedly.
119
- const deadline = Date.now() + 5000;
120
- while (Date.now() < deadline) {
121
- if (child.exitCode !== null) {
122
- throw new Error(`s2 lite process exited with code ${child.exitCode} before becoming ready: ${stderrOutput}`);
123
- }
124
- const ready = await isPortOpen(port);
125
- if (ready) {
126
- return {
127
- port,
128
- endpoint,
129
- stop: cleanup,
130
- };
88
+ const child = yield* Effect.try({
89
+ try: () => childProcess.spawn(binaryPath, ['lite', '--port', String(port)], {
90
+ stdio: ['ignore', 'pipe', 'pipe'],
91
+ detached: false,
92
+ }),
93
+ catch: (cause) => new S2LiteError('Failed to start s2 lite', cause),
94
+ });
95
+ activeProcess = child;
96
+ const cleanup = () => {
97
+ if (activeProcess === child) {
98
+ activeProcess = null;
99
+ }
100
+ try {
101
+ child.kill('SIGTERM');
102
+ }
103
+ catch {
104
+ // The process may already have exited.
105
+ }
106
+ };
107
+ process.once('exit', cleanup);
108
+ process.once('SIGINT', cleanup);
109
+ process.once('SIGTERM', cleanup);
110
+ let stderrOutput = '';
111
+ child.stderr?.on('data', (chunk) => {
112
+ stderrOutput += chunk.toString();
113
+ });
114
+ const deadline = (yield* Clock.currentTimeMillis) + 5_000;
115
+ while ((yield* Clock.currentTimeMillis) < deadline) {
116
+ if (child.exitCode !== null) {
117
+ return yield* new S2LiteError(`s2 lite process exited with code ${child.exitCode} before becoming ready: ${stderrOutput}`);
118
+ }
119
+ if (yield* Effect.promise(() => isPortOpen(port))) {
120
+ return { port, endpoint, stop: cleanup };
121
+ }
122
+ yield* Effect.sleep(50);
131
123
  }
132
- await new Promise((r) => setTimeout(r, 50));
133
- }
134
- cleanup();
135
- throw new Error(`Timed out waiting for s2 lite to start on port ${port}: ${stderrOutput}`);
124
+ cleanup();
125
+ return yield* new S2LiteError(`Timed out waiting for s2 lite to start on port ${port}: ${stderrOutput}`);
126
+ }));
136
127
  }
137
128
  /**
138
129
  * Returns a factory function for createLooms that automatically starts local s2-lite
139
130
  * and connects an S2 EventStore to it.
140
131
  */
141
132
  export function s2Lite(options = {}) {
142
- return async () => {
143
- const started = await startS2Lite(options);
144
- return s2({
145
- basin: options.basin ?? 'looms-demo',
146
- accessToken: options.accessToken ?? 's2_local',
147
- endpoint: started.endpoint,
148
- });
149
- };
133
+ return () => startS2Lite(options).then((started) => s2({
134
+ basin: options.basin ?? 'looms-demo',
135
+ accessToken: options.accessToken ?? 's2_local',
136
+ endpoint: started.endpoint,
137
+ }));
150
138
  }
@@ -0,0 +1,15 @@
1
+ import { Effect, Stream } from 'effect';
2
+ export interface S2ReadBatchLike<T> {
3
+ readonly records: ReadonlyArray<T>;
4
+ readonly tail?: {
5
+ readonly seqNum: number;
6
+ } | null;
7
+ }
8
+ export interface ReadAllPagesOptions {
9
+ readonly fromSeq?: number;
10
+ readonly limit?: number;
11
+ readonly maxPageSize?: number;
12
+ }
13
+ export declare function paginateS2Stream<T extends {
14
+ readonly seqNum: number;
15
+ }, E>(fetchPage: (cursor: number, count: number) => Effect.Effect<S2ReadBatchLike<T> | null, E>, options?: ReadAllPagesOptions): Stream.Stream<T, E>;
@@ -0,0 +1,36 @@
1
+ import { Effect, Option, Stream } from 'effect';
2
+ export function paginateS2Stream(fetchPage, options) {
3
+ const fromSeq = options?.fromSeq ?? 0;
4
+ const userLimit = options?.limit;
5
+ const maxPageSize = options?.maxPageSize ?? 1000;
6
+ if (userLimit !== undefined && userLimit <= 0) {
7
+ return Stream.empty;
8
+ }
9
+ const baseStream = Stream.paginate({ cursor: fromSeq, remaining: userLimit }, (state) => Effect.gen(function* () {
10
+ if (state.remaining !== undefined && state.remaining <= 0) {
11
+ return [[], Option.none()];
12
+ }
13
+ const count = state.remaining !== undefined ? Math.min(maxPageSize, state.remaining) : maxPageSize;
14
+ const page = yield* fetchPage(state.cursor, count);
15
+ if (!page || page.records.length === 0) {
16
+ return [[], Option.none()];
17
+ }
18
+ const records = page.records.filter((record) => record.seqNum >= fromSeq);
19
+ const nextRemaining = state.remaining !== undefined ? state.remaining - records.length : undefined;
20
+ const lastRecord = page.records[page.records.length - 1];
21
+ if (!lastRecord || (nextRemaining !== undefined && nextRemaining <= 0)) {
22
+ return [records, Option.none()];
23
+ }
24
+ const nextCursor = Math.max(state.cursor + 1, lastRecord.seqNum + 1);
25
+ if (nextCursor <= state.cursor) {
26
+ return [records, Option.none()];
27
+ }
28
+ // Byte-capped pages can be shorter than requested while more records remain.
29
+ const shortPage = page.records.length < count;
30
+ const reachedTail = !shortPage && page.tail?.seqNum !== undefined && nextCursor >= page.tail.seqNum;
31
+ return reachedTail
32
+ ? [records, Option.none()]
33
+ : [records, Option.some({ cursor: nextCursor, remaining: nextRemaining })];
34
+ }));
35
+ return userLimit !== undefined ? baseStream.pipe(Stream.take(userLimit)) : baseStream;
36
+ }
@@ -10,9 +10,10 @@ export function s2Projector(config) {
10
10
  const store = s2(config);
11
11
  return {
12
12
  name: 's2',
13
- project: async (events) => {
13
+ version: '1',
14
+ project: (events) => {
14
15
  if (events.length === 0) {
15
- return;
16
+ return Promise.resolve();
16
17
  }
17
18
  const byRun = new Map();
18
19
  for (const event of events) {
@@ -20,9 +21,9 @@ export function s2Projector(config) {
20
21
  batch.push(event);
21
22
  byRun.set(event.runId, batch);
22
23
  }
23
- for (const [runId, batch] of byRun) {
24
- await Effect.runPromise(store.append(runId, batch));
25
- }
24
+ return Effect.runPromise(Effect.forEach(byRun, ([runId, batch]) => store.append(runId, batch), {
25
+ discard: true,
26
+ }));
26
27
  },
27
28
  };
28
29
  }