@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,270 @@
1
+ import { Predicate } from 'effect';
2
+ import { cancel, createWaitId, deterministicThreadId, emit, spawn, wait, } from '@swirls/looms/core';
3
+ import { agentModule } from './scope.js';
4
+ function objectPayload(event) {
5
+ return Predicate.isObject(event.payload) ? event.payload : {};
6
+ }
7
+ function messageFrom(value) {
8
+ const payload = Predicate.isObject(value) ? value : {};
9
+ return Predicate.isString(payload.messageId) && Predicate.isString(payload.text)
10
+ ? {
11
+ messageId: payload.messageId,
12
+ text: payload.text,
13
+ delivery: payload.delivery === 'steer' ||
14
+ payload.delivery === 'followUp' ||
15
+ payload.delivery === 'nextTurn'
16
+ ? payload.delivery
17
+ : undefined,
18
+ }
19
+ : null;
20
+ }
21
+ function consumedIds(event) {
22
+ const payload = objectPayload(event);
23
+ const embedded = Predicate.isObject(payload.event) ? payload.event : {};
24
+ const embeddedPayload = Predicate.isObject(embedded.payload) ? embedded.payload : {};
25
+ const output = Predicate.isObject(embeddedPayload.output) ? embeddedPayload.output : {};
26
+ const ids = output.consumedSteerMessageIds;
27
+ return Array.isArray(ids) ? ids.filter(Predicate.isString) : [];
28
+ }
29
+ function closureStatus(event) {
30
+ const payload = objectPayload(event);
31
+ const embedded = Predicate.isObject(payload.event) ? payload.event : {};
32
+ const embeddedPayload = Predicate.isObject(embedded.payload) ? embedded.payload : {};
33
+ const status = embedded.type === 'runtime.thread.completed'
34
+ ? 'completed'
35
+ : embedded.type === 'runtime.thread.cancelled'
36
+ ? 'cancelled'
37
+ : 'failed';
38
+ const error = Predicate.isString(embeddedPayload.error) ? embeddedPayload.error : undefined;
39
+ return { status, error };
40
+ }
41
+ function close(messageId, status, error) {
42
+ return error === undefined ? { messageId, status } : { messageId, status, error };
43
+ }
44
+ export function createAgentSessionThread(definitions) {
45
+ return agentModule.thread({
46
+ kind: 'agent-session',
47
+ initialState: (ctx) => {
48
+ const definition = definitions.get(ctx.definitionName, ctx.definitionVersion);
49
+ return {
50
+ definitionName: ctx.definitionName,
51
+ definitionVersion: ctx.definitionVersion,
52
+ pendingMessages: [],
53
+ nextTurnMessages: [],
54
+ processedMessageIds: [],
55
+ activeTurn: null,
56
+ pendingSteerDeliveries: [],
57
+ pendingClosures: [],
58
+ lastSequence: 0,
59
+ idleTimeoutMs: definition?.idleTimeoutMs ?? 0,
60
+ idleDeadlineAt: null,
61
+ parked: false,
62
+ cancelling: false,
63
+ };
64
+ },
65
+ step(state, event) {
66
+ switch (event.type) {
67
+ case 'runtime.thread.started': {
68
+ const initial = messageFrom(objectPayload(event).input);
69
+ const idleDeadlineAt = state.idleTimeoutMs > 0 ? event.ts + state.idleTimeoutMs : null;
70
+ if (!initial || state.processedMessageIds.includes(initial.messageId)) {
71
+ return { ...state, idleDeadlineAt };
72
+ }
73
+ return {
74
+ ...state,
75
+ pendingMessages: [initial],
76
+ processedMessageIds: [initial.messageId],
77
+ idleDeadlineAt,
78
+ };
79
+ }
80
+ case 'agent.session.message.submitted': {
81
+ const payload = objectPayload(event);
82
+ const message = messageFrom(payload);
83
+ if (!message || state.processedMessageIds.includes(message.messageId)) {
84
+ return state;
85
+ }
86
+ const processedMessageIds = [...state.processedMessageIds, message.messageId];
87
+ const idleDeadlineAt = state.idleTimeoutMs > 0 ? event.ts + state.idleTimeoutMs : null;
88
+ if (message.delivery === 'nextTurn') {
89
+ return {
90
+ ...state,
91
+ nextTurnMessages: [...state.nextTurnMessages, message],
92
+ processedMessageIds,
93
+ idleDeadlineAt,
94
+ parked: false,
95
+ };
96
+ }
97
+ const queued = message.delivery === 'steer' && state.activeTurn
98
+ ? { ...message, steeredIntoMessageId: state.activeTurn.messageId }
99
+ : message;
100
+ return {
101
+ ...state,
102
+ pendingMessages: [...state.pendingMessages, queued],
103
+ pendingSteerDeliveries: queued.steeredIntoMessageId &&
104
+ state.activeTurn &&
105
+ payload.activeChildThreadId !== state.activeTurn.childThreadId
106
+ ? [...state.pendingSteerDeliveries, queued]
107
+ : state.pendingSteerDeliveries,
108
+ processedMessageIds,
109
+ idleDeadlineAt,
110
+ parked: false,
111
+ };
112
+ }
113
+ case 'agent.session.turn.started': {
114
+ const messageId = event.payload.messageId;
115
+ const admitted = state.pendingMessages.find((message) => message.messageId === messageId);
116
+ const text = [...state.nextTurnMessages, ...(admitted ? [admitted] : [])]
117
+ .map((message) => message.text)
118
+ .join('\n');
119
+ return {
120
+ ...state,
121
+ pendingMessages: state.pendingMessages.filter((message) => message.messageId !== messageId),
122
+ activeTurn: {
123
+ messageId,
124
+ childThreadId: event.payload.childThreadId,
125
+ text,
126
+ },
127
+ nextTurnMessages: [],
128
+ lastSequence: state.lastSequence + 1,
129
+ cancelling: false,
130
+ };
131
+ }
132
+ case 'agent.session.steer.delivered':
133
+ return {
134
+ ...state,
135
+ pendingSteerDeliveries: state.pendingSteerDeliveries.filter((message) => message.messageId !== event.payload.messageId),
136
+ };
137
+ case 'agent.session.turn.closed':
138
+ return {
139
+ ...state,
140
+ pendingClosures: state.pendingClosures.filter((closure) => closure.messageId !== event.payload.messageId),
141
+ };
142
+ case 'agent.session.cancel.requested':
143
+ case 'runtime.thread.cancel.requested':
144
+ return state.activeTurn ? { ...state, cancelling: true } : state;
145
+ case 'runtime.wait.satisfied': {
146
+ const payload = objectPayload(event);
147
+ const tag = Predicate.isObject(payload.tag) ? payload.tag : {};
148
+ if (tag.kind === 'agent-session-idle') {
149
+ if (tag.deadlineAt === state.idleDeadlineAt && state.activeTurn === null) {
150
+ return { ...state, parked: true, idleDeadlineAt: null };
151
+ }
152
+ return state;
153
+ }
154
+ if (tag.kind !== 'agent-session-turn' || !state.activeTurn) {
155
+ return state;
156
+ }
157
+ const active = state.activeTurn;
158
+ const consumed = new Set(consumedIds(event));
159
+ const result = closureStatus(event);
160
+ const pendingClosures = [
161
+ ...state.pendingClosures,
162
+ close(active.messageId, result.status, result.error),
163
+ ...[...consumed].map((messageId) => close(messageId, result.status, result.error)),
164
+ ];
165
+ return {
166
+ ...state,
167
+ pendingMessages: state.pendingMessages.flatMap((message) => {
168
+ if (consumed.has(message.messageId)) {
169
+ return [];
170
+ }
171
+ return message.steeredIntoMessageId === active.messageId
172
+ ? [{ ...message, steeredIntoMessageId: undefined }]
173
+ : [message];
174
+ }),
175
+ pendingSteerDeliveries: state.pendingSteerDeliveries.filter((message) => !consumed.has(message.messageId) &&
176
+ message.steeredIntoMessageId !== active.messageId),
177
+ pendingClosures,
178
+ activeTurn: null,
179
+ lastSequence: state.lastSequence + 1,
180
+ cancelling: false,
181
+ idleDeadlineAt: state.idleTimeoutMs > 0 ? event.ts + state.idleTimeoutMs : null,
182
+ };
183
+ }
184
+ default:
185
+ return state;
186
+ }
187
+ },
188
+ effects(state, ctx) {
189
+ const effects = [];
190
+ for (const closure of state.pendingClosures) {
191
+ effects.push(emit(agentModule.input('session.turn.closed', { messageId: closure.messageId, status: closure.status, error: closure.error }, { threadId: ctx.threadId }), `session_close_${closure.messageId}`));
192
+ }
193
+ for (const message of state.pendingSteerDeliveries) {
194
+ if (!state.activeTurn || message.steeredIntoMessageId !== state.activeTurn.messageId) {
195
+ continue;
196
+ }
197
+ effects.push(emit(agentModule.input('steered', {
198
+ turn: 0,
199
+ messageId: message.messageId,
200
+ message: { role: 'user', content: message.text },
201
+ interrupt: true,
202
+ }, { threadId: state.activeTurn.childThreadId }), `session_steer_${message.messageId}`), emit(agentModule.input('session.steer.delivered', { messageId: message.messageId, activeMessageId: state.activeTurn.messageId }, { threadId: ctx.threadId }), `session_steer_delivered_${message.messageId}`));
203
+ }
204
+ if (state.activeTurn) {
205
+ const { childThreadId: turnThreadId, messageId, text } = state.activeTurn;
206
+ const definition = definitions.get(state.definitionName, state.definitionVersion);
207
+ if (state.cancelling) {
208
+ effects.push(cancel(turnThreadId));
209
+ }
210
+ else if (definition) {
211
+ effects.push(spawn({
212
+ childThreadId: turnThreadId,
213
+ kind: 'agent',
214
+ definitionName: definition.agent.name,
215
+ definitionVersion: definition.agent.version,
216
+ input: { text },
217
+ }));
218
+ }
219
+ // The turn wait must survive cancellation: the child's cancelled event is what closes it.
220
+ effects.push(wait({
221
+ waitId: createWaitId(ctx.threadId, `turn_${messageId}`),
222
+ on: {
223
+ type: [
224
+ 'runtime.thread.completed',
225
+ 'runtime.thread.failed',
226
+ 'runtime.thread.cancelled',
227
+ ],
228
+ match: { threadId: turnThreadId },
229
+ },
230
+ tag: { kind: 'agent-session-turn', messageId },
231
+ }));
232
+ return effects;
233
+ }
234
+ const next = state.pendingMessages.find((message) => message.steeredIntoMessageId === undefined);
235
+ if (next) {
236
+ effects.push(emit(agentModule.input('session.turn.started', {
237
+ messageId: next.messageId,
238
+ childThreadId: deterministicThreadId(ctx.threadId, 'turn', next.messageId),
239
+ }, { threadId: ctx.threadId }), `session_admit_${next.messageId}`));
240
+ return effects;
241
+ }
242
+ if (state.parked || state.idleTimeoutMs === 0 || state.idleDeadlineAt === null) {
243
+ effects.push(wait({
244
+ waitId: createWaitId(ctx.threadId, 'mailbox'),
245
+ on: { type: 'agent.session.message.submitted', match: { threadId: ctx.threadId } },
246
+ tag: { kind: 'agent-session-mailbox' },
247
+ }));
248
+ }
249
+ else {
250
+ effects.push(wait({
251
+ waitId: createWaitId(ctx.threadId, `idle_${state.idleDeadlineAt}`),
252
+ on: { timerAt: state.idleDeadlineAt },
253
+ tag: { kind: 'agent-session-idle', deadlineAt: state.idleDeadlineAt },
254
+ }));
255
+ }
256
+ return effects;
257
+ },
258
+ });
259
+ }
260
+ export function agentSessionSnapshot(state) {
261
+ return {
262
+ activeTurnId: state.activeTurn?.messageId ?? null,
263
+ activeChildThreadId: state.activeTurn?.childThreadId ?? null,
264
+ pendingMessageCount: state.pendingMessages.length,
265
+ nextTurnHeldCount: state.nextTurnMessages.length,
266
+ processedMessageIds: state.processedMessageIds,
267
+ lastSequence: state.lastSequence,
268
+ parked: state.parked,
269
+ };
270
+ }
@@ -0,0 +1,2 @@
1
+ import { type WorkspaceContext } from '@swirls/looms/debugger';
2
+ export declare function AgentChat(context: WorkspaceContext): import("react").JSX.Element;
@@ -0,0 +1,176 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Bot, CornerDownRight, MessageSquare, Settings2, User, Wrench } from 'lucide-react';
3
+ import { useMemo, useState } from 'react';
4
+ import { createEventId, isJsonObject, isJsonString } from '@swirls/looms/core';
5
+ import { cn, Composer, EmptyState, errorMessage, FollowList, inputForm, JsonTree, messageInput, parseStructuredJson, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, shortId, useDebugger, useStartRun, } from '@swirls/looms/debugger';
6
+ import { createFold, useEventFold, useProjection, useRunStore, useRunSummary } from '@swirls/looms/react';
7
+ import { conversation } from '../projections.js';
8
+ import { agentSessionMessageEvents, userMessage } from '../signals.js';
9
+ /** Child thread of the session turn that is still open, from the events the store already has. */
10
+ function activeSessionChild(events) {
11
+ let child;
12
+ for (const event of events) {
13
+ if (!isJsonObject(event.payload)) {
14
+ continue;
15
+ }
16
+ if (event.type === 'agent.session.turn.started' && isJsonString(event.payload.childThreadId)) {
17
+ child = event.payload.childThreadId;
18
+ continue;
19
+ }
20
+ const tag = event.payload.tag;
21
+ if (event.type === 'runtime.wait.satisfied' &&
22
+ isJsonObject(tag) &&
23
+ tag.kind === 'agent-session-turn') {
24
+ child = undefined;
25
+ }
26
+ }
27
+ return child;
28
+ }
29
+ const streamingFold = createFold({
30
+ name: 'agentStreamingText',
31
+ initialState: { lastMessageSeq: -1, turnStarted: false, parts: [] },
32
+ includeEphemeral: true,
33
+ reduce(state, event) {
34
+ if (event.type === 'agent.message') {
35
+ return { lastMessageSeq: event.seq, turnStarted: false, parts: [] };
36
+ }
37
+ if (event.seq <= state.lastMessageSeq) {
38
+ return state;
39
+ }
40
+ if (event.type === 'agent.turn.started') {
41
+ return { ...state, turnStarted: true };
42
+ }
43
+ if (event.type === 'agent.turn.text_delta' &&
44
+ isJsonObject(event.payload) &&
45
+ isJsonString(event.payload.delta)) {
46
+ return {
47
+ ...state,
48
+ turnStarted: true,
49
+ parts: state.parts.concat(event.payload.delta),
50
+ };
51
+ }
52
+ return state;
53
+ },
54
+ });
55
+ const deliveryOptions = [
56
+ { value: 'followUp', label: 'Follow up', description: 'Queue after the current turn' },
57
+ { value: 'steer', label: 'Steer', description: 'Redirect the active turn' },
58
+ { value: 'nextTurn', label: 'Next turn', description: 'Hold until the next turn starts' },
59
+ ];
60
+ function RoleLabel({ icon, children }) {
61
+ return (_jsxs("div", { className: "text-muted-foreground mb-1.5 flex items-center gap-1.5 text-[11px] font-medium [&_svg]:size-3", children: [icon, children] }));
62
+ }
63
+ function MessageText({ content, className }) {
64
+ const structured = useMemo(() => parseStructuredJson(content), [content]);
65
+ if (structured !== undefined) {
66
+ return _jsx(JsonTree, { value: structured, defaultExpandDepth: 2 });
67
+ }
68
+ return (_jsx("div", { className: cn('text-[13px] leading-relaxed break-words whitespace-pre-wrap', className), children: content }));
69
+ }
70
+ function ToolCard({ icon, name, meta, children, }) {
71
+ return (_jsxs("div", { className: "border-border bg-card/60 overflow-hidden rounded-lg border", children: [_jsxs("div", { className: "border-border/70 flex h-7 items-center gap-1.5 border-b px-2.5 text-[11px] [&_svg]:size-3", children: [_jsx("span", { className: "text-muted-foreground", children: icon }), _jsx("span", { className: "font-mono font-medium", children: name }), meta ? (_jsx("span", { className: "text-muted-foreground ml-auto truncate font-mono text-[10px]", children: meta })) : null] }), _jsx("div", { className: "px-2.5 py-1.5", children: children })] }));
72
+ }
73
+ function ToolCallCard({ call }) {
74
+ return (_jsx(ToolCard, { icon: _jsx(Wrench, {}), name: call.name, meta: shortId(call.id), children: _jsx(JsonTree, { value: call.arguments, defaultExpandDepth: 2 }) }));
75
+ }
76
+ function MessageItem({ line, toolName }) {
77
+ switch (line.role) {
78
+ case 'user':
79
+ return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(User, {}), children: "User" }), _jsx("div", { className: "bg-secondary w-fit max-w-full rounded-lg px-3 py-2", children: _jsx(MessageText, { content: line.content }) })] }));
80
+ case 'assistant':
81
+ return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(Bot, {}), children: "Assistant" }), _jsxs("div", { className: "grid gap-2", children: [line.content ? _jsx(MessageText, { content: line.content }) : null, line.toolCalls?.map((call) => (_jsx(ToolCallCard, { call: call }, call.id)))] })] }));
82
+ case 'tool':
83
+ return (_jsx(ToolCard, { icon: _jsx(CornerDownRight, {}), name: `${line.name ?? toolName ?? 'tool'} result`, meta: line.toolCallId ? shortId(line.toolCallId) : undefined, children: _jsx(MessageText, { content: line.content }) }));
84
+ case 'system':
85
+ return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(Settings2, {}), children: "System" }), _jsx(MessageText, { content: line.content, className: "text-muted-foreground" })] }));
86
+ default: {
87
+ const exhaustive = line.role;
88
+ return exhaustive;
89
+ }
90
+ }
91
+ }
92
+ function StreamingItem({ text }) {
93
+ return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(Bot, {}), children: "Assistant" }), _jsxs("div", { className: "text-[13px] leading-relaxed break-words whitespace-pre-wrap", children: [text, _jsx("span", { "aria-label": "Generating", className: "bg-foreground/70 ml-0.5 inline-block h-3.5 w-1.5 animate-pulse rounded-[1px] align-[-2px]" })] })] }));
94
+ }
95
+ function Transcript({ runId }) {
96
+ const store = useRunStore(runId);
97
+ const convo = useProjection(store, conversation);
98
+ const streaming = useEventFold(store, streamingFold);
99
+ const stream = streaming.turnStarted ? streaming.parts.join('') : null;
100
+ const toolNames = useMemo(() => {
101
+ const names = new Map();
102
+ for (const line of convo.lines) {
103
+ for (const call of line.toolCalls ?? []) {
104
+ names.set(call.id, call.name);
105
+ }
106
+ }
107
+ return names;
108
+ }, [convo.lines]);
109
+ const items = useMemo(() => {
110
+ const lines = convo.lines.map((line, index) => ({
111
+ kind: 'line',
112
+ line,
113
+ index,
114
+ }));
115
+ return stream === null ? lines : [...lines, { kind: 'stream', text: stream }];
116
+ }, [convo.lines, stream]);
117
+ return (_jsx(FollowList, { items: items, estimateSize: 96, overscan: 4, paddingStart: 8, paddingEnd: 12, getKey: (item) => (item.kind === 'stream' ? 'stream' : item.index), empty: _jsx("p", { className: "text-muted-foreground p-6 text-center text-xs", children: "Waiting for messages\u2026" }), renderItem: (item) => (_jsx("div", { className: "px-4 py-2", children: item.kind === 'stream' ? (_jsx(StreamingItem, { text: item.text })) : (_jsx(MessageItem, { line: item.line, toolName: item.line.toolCallId ? toolNames.get(item.line.toolCallId) : undefined })) })) }));
118
+ }
119
+ function DeliverySelect({ value, onChange, }) {
120
+ return (_jsxs(Select, { value: value, onValueChange: (next) => {
121
+ const option = deliveryOptions.find((candidate) => candidate.value === next);
122
+ if (option) {
123
+ onChange(option.value);
124
+ }
125
+ }, children: [_jsx(SelectTrigger, { "aria-label": "Delivery", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { align: "start", className: "w-60", children: deliveryOptions.map((option) => (_jsx(SelectItem, { value: option.value, description: option.description, children: option.label }, option.value))) })] }));
126
+ }
127
+ export function AgentChat(context) {
128
+ const { definition, runId } = context;
129
+ const { client } = useDebugger();
130
+ const [draft, setDraft] = useState('');
131
+ const [delivery, setDelivery] = useState('followUp');
132
+ const { start, pending, error } = useStartRun(context);
133
+ const session = definition.kind === 'agent-session';
134
+ const form = inputForm(definition.inputSchema);
135
+ function send() {
136
+ const content = draft.trim();
137
+ const input = session ? null : messageInput(form, content);
138
+ if (!content || input === undefined) {
139
+ return;
140
+ }
141
+ setDraft('');
142
+ start(input, session
143
+ ? (started) => client.signal(started.runId, agentSessionMessageEvents(createEventId(), content, { threadId: started.threadId }))
144
+ : undefined);
145
+ }
146
+ return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [runId ? (_jsx(Transcript, { runId: runId })) : (_jsx("div", { className: "min-h-0 flex-1", children: _jsx(EmptyState, { icon: _jsx(MessageSquare, {}), title: `Talk to ${definition.name}`, children: "Your first message starts a new run." }) })), runId ? (_jsx(FollowUp, { runId: runId, session: session, delivery: delivery, setDelivery: setDelivery, startError: error })) : (_jsx(Composer, { value: draft, onChange: setDraft, onSubmit: send, pending: pending, placeholder: `Message ${definition.name}…`, submitLabel: "Start", error: error }))] }));
147
+ }
148
+ function FollowUp({ runId, session, delivery, setDelivery, startError, }) {
149
+ const store = useRunStore(runId);
150
+ const { rootThreadId } = useRunSummary(store);
151
+ const [draft, setDraft] = useState('');
152
+ const [pending, setPending] = useState(false);
153
+ const [error, setError] = useState(null);
154
+ function send() {
155
+ const content = draft.trim();
156
+ if (!content || !rootThreadId) {
157
+ return;
158
+ }
159
+ setPending(true);
160
+ setError(null);
161
+ const events = session
162
+ ? agentSessionMessageEvents(createEventId(), content, {
163
+ delivery,
164
+ threadId: rootThreadId,
165
+ activeChildThreadId: delivery === 'steer' ? activeSessionChild(store.events()) : undefined,
166
+ })
167
+ : [userMessage(content, { threadId: rootThreadId })];
168
+ const [only] = events;
169
+ const commit = events.length === 1 && only ? store.commit(only) : store.commit(events);
170
+ commit
171
+ .then(() => setDraft(''))
172
+ .catch((cause) => setError(errorMessage(cause)))
173
+ .finally(() => setPending(false));
174
+ }
175
+ return (_jsx(Composer, { value: draft, onChange: setDraft, onSubmit: send, pending: pending, disabled: !rootThreadId, placeholder: "Send a follow-up\u2026", error: error ?? startError, toolbar: session ? _jsx(DeliverySelect, { value: delivery, onChange: setDelivery }) : null }));
176
+ }
@@ -0,0 +1,5 @@
1
+ import { type DebuggerPlugin } from '@swirls/looms/debugger';
2
+ import { AgentChat } from './agent-chat';
3
+ import { TokenUsageView } from './token-usage';
4
+ export declare const agentDebugger: DebuggerPlugin;
5
+ export { AgentChat, TokenUsageView };
@@ -0,0 +1,19 @@
1
+ import { inputForm, messageInput } from '@swirls/looms/debugger';
2
+ import { tokenUsage } from '../projections.js';
3
+ import { AgentChat } from './agent-chat.js';
4
+ import { summarizeAgentEvent } from './summarize.js';
5
+ import { TokenUsageView } from './token-usage.js';
6
+ function isChat(definition) {
7
+ return messageInput(inputForm(definition.inputSchema), '') !== undefined;
8
+ }
9
+ export const agentDebugger = {
10
+ name: 'agent',
11
+ families: [{ family: 'agent', color: 'oklch(0.74 0.12 240)', summarize: summarizeAgentEvent }],
12
+ workspace: {
13
+ kinds: ['agent', 'agent-session'],
14
+ matches: (definition) => definition.kind === 'agent-session' || isChat(definition),
15
+ component: AgentChat,
16
+ },
17
+ projections: [{ name: tokenUsage.name, component: TokenUsageView }],
18
+ };
19
+ export { AgentChat, TokenUsageView };
@@ -0,0 +1,2 @@
1
+ import { type DebuggerEvent, type EventSummary } from '@swirls/looms/debugger';
2
+ export declare function summarizeAgentEvent(event: DebuggerEvent): EventSummary | undefined;
@@ -0,0 +1,51 @@
1
+ import { isJsonObject, isJsonString } from '@swirls/looms/core';
2
+ import { compactJson, jsonFields, jsonNumberText, jsonText, } from '@swirls/looms/debugger';
3
+ function messageContent(payload) {
4
+ const message = jsonFields(payload).message;
5
+ return isJsonObject(message) && isJsonString(message.content) ? message.content : undefined;
6
+ }
7
+ function toolCallSummary(payload) {
8
+ const call = jsonFields(payload).toolCall;
9
+ if (!isJsonObject(call)) {
10
+ return { name: 'tool', args: null };
11
+ }
12
+ return {
13
+ name: isJsonString(call.name) ? call.name : 'tool',
14
+ args: call.arguments ?? null,
15
+ };
16
+ }
17
+ export function summarizeAgentEvent(event) {
18
+ const payload = jsonFields(event.payload);
19
+ switch (event.type) {
20
+ case 'agent.message.received':
21
+ return { title: 'user message', detail: messageContent(event.payload) };
22
+ case 'agent.turn.started':
23
+ return { title: 'turn started', detail: `turn ${jsonNumberText(payload.turn) ?? ''}` };
24
+ case 'agent.turn.text_delta':
25
+ return { title: 'text delta', detail: jsonText(payload.delta) };
26
+ case 'agent.message':
27
+ return { title: 'agent message', detail: messageContent(event.payload) };
28
+ case 'agent.tool_call.requested': {
29
+ const call = toolCallSummary(event.payload);
30
+ return { title: `tool ${call.name}`, detail: compactJson(call.args) };
31
+ }
32
+ case 'agent.tool.result':
33
+ return {
34
+ title: jsonText(payload.error)
35
+ ? `tool error ${jsonText(payload.name)}`
36
+ : `tool result ${jsonText(payload.name)}`,
37
+ detail: jsonText(payload.error) ?? compactJson(payload.result ?? null),
38
+ };
39
+ case 'agent.steered':
40
+ return { title: 'steered', detail: messageContent(event.payload) };
41
+ case 'agent.spawn.requested':
42
+ return {
43
+ title: 'agent spawn',
44
+ detail: `${jsonText(payload.kind) ?? 'agent'}:${jsonText(payload.definitionName) ?? 'unknown'}`,
45
+ };
46
+ case 'agent.effects.requested':
47
+ return { title: 'agent effects', detail: jsonText(payload.toolCallId) };
48
+ default:
49
+ return undefined;
50
+ }
51
+ }
@@ -0,0 +1,3 @@
1
+ export declare function TokenUsageView({ runId }: {
2
+ runId: string;
3
+ }): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useProjection, useRunStore } from '@swirls/looms/react';
3
+ import { tokenUsage } from '../projections.js';
4
+ const format = new Intl.NumberFormat();
5
+ function Stat({ label, value }) {
6
+ return (_jsxs("div", { className: "border-border bg-card/60 rounded-lg border px-2.5 py-2", children: [_jsx("p", { className: "text-muted-foreground text-[11px]", children: label }), _jsx("p", { className: "font-mono text-[13px] font-medium tabular-nums", children: format.format(value) })] }));
7
+ }
8
+ export function TokenUsageView({ runId }) {
9
+ const state = useProjection(useRunStore(runId), tokenUsage);
10
+ return (_jsxs("div", { className: "grid grid-cols-3 gap-2", children: [_jsx(Stat, { label: "Input", value: state.input }), _jsx(Stat, { label: "Output", value: state.output }), _jsx(Stat, { label: "Total", value: state.input + state.output })] }));
11
+ }
@@ -1,8 +1,7 @@
1
1
  import { Context, Layer } from 'effect';
2
+ import { type DefinitionStore } from '@swirls/looms/core';
2
3
  import type { AgentDefinition } from './definitions';
3
- export interface AgentDefinitionStore {
4
- get(name: string): AgentDefinition | undefined;
5
- }
4
+ export type AgentDefinitionStore = DefinitionStore<AgentDefinition>;
6
5
  declare const AgentDefinitionsTag_base: Context.ServiceClass<AgentDefinitionsTag, "looms/AgentDefinitions", AgentDefinitionStore>;
7
6
  export declare class AgentDefinitionsTag extends AgentDefinitionsTag_base {
8
7
  }
@@ -1,10 +1,8 @@
1
1
  import { Context, Layer } from 'effect';
2
+ import { makeDefinitionStore } from '@swirls/looms/core';
2
3
  export class AgentDefinitionsTag extends Context.Service()('looms/AgentDefinitions') {
3
4
  }
4
5
  export function makeAgentDefinitionStore(definitions) {
5
- const map = new Map(definitions.map((def) => [def.name, def]));
6
- return {
7
- get: (name) => map.get(name),
8
- };
6
+ return makeDefinitionStore('agent', definitions);
9
7
  }
10
8
  export const AgentDefinitionsLive = (definitions) => Layer.succeed(AgentDefinitionsTag, makeAgentDefinitionStore(definitions));