@swirls/looms 0.1.0 → 0.3.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 (224) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/actor/host.js +4 -5
  3. package/dist/actor/index.d.ts +1 -1
  4. package/dist/actor/index.js +1 -1
  5. package/dist/actor/routing.d.ts +5 -0
  6. package/dist/actor/routing.js +14 -0
  7. package/dist/agent/agent-session.js +1 -0
  8. package/dist/agent/debugger/agent-chat.d.ts +2 -0
  9. package/dist/agent/debugger/agent-chat.js +210 -0
  10. package/dist/agent/debugger/index.d.ts +5 -0
  11. package/dist/agent/debugger/index.js +19 -0
  12. package/dist/agent/debugger/summarize.d.ts +2 -0
  13. package/dist/agent/debugger/summarize.js +53 -0
  14. package/dist/agent/debugger/token-usage.d.ts +3 -0
  15. package/dist/agent/debugger/token-usage.js +11 -0
  16. package/dist/agent/definitions.d.ts +3 -11
  17. package/dist/agent/definitions.js +5 -6
  18. package/dist/agent/effects.d.ts +30 -0
  19. package/dist/agent/events.d.ts +2 -0
  20. package/dist/agent/events.js +2 -0
  21. package/dist/agent/llm.js +1 -8
  22. package/dist/agent/module.d.ts +604 -534
  23. package/dist/agent/module.js +11 -7
  24. package/dist/agent/projections.d.ts +5 -0
  25. package/dist/agent/projections.js +43 -2
  26. package/dist/agent/scope.d.ts +2 -0
  27. package/dist/agent/signals.d.ts +7 -0
  28. package/dist/agent/signals.js +25 -16
  29. package/dist/agent/threads.js +35 -21
  30. package/dist/agent/tool-schema.d.ts +1 -17
  31. package/dist/agent/tool-schema.js +3 -42
  32. package/dist/agent/transcript.d.ts +7 -0
  33. package/dist/agent/transcript.js +19 -0
  34. package/dist/agent/types.d.ts +10 -0
  35. package/dist/agent/types.js +4 -0
  36. package/dist/ai-vercel/index.d.ts +1 -1
  37. package/dist/ai-vercel/vercel-evaluator.d.ts +21 -8
  38. package/dist/ai-vercel/vercel-evaluator.js +7 -2
  39. package/dist/approval/debugger/approvals-view.d.ts +3 -0
  40. package/dist/approval/debugger/approvals-view.js +18 -0
  41. package/dist/approval/debugger/index.d.ts +4 -0
  42. package/dist/approval/debugger/index.js +11 -0
  43. package/dist/approval/debugger/summarize.d.ts +2 -0
  44. package/dist/approval/debugger/summarize.js +17 -0
  45. package/dist/approval/effects.d.ts +12 -0
  46. package/dist/approval/module.d.ts +24 -0
  47. package/dist/client/client.d.ts +310 -0
  48. package/dist/client/client.js +20 -2
  49. package/dist/cloudflare/router.d.ts +1 -1
  50. package/dist/cloudflare/router.js +6 -8
  51. package/dist/core/compose.js +1 -0
  52. package/dist/core/debugger-host.d.ts +16 -0
  53. package/dist/core/debugger-host.js +1 -0
  54. package/dist/core/effects.d.ts +7 -0
  55. package/dist/core/effects.js +1 -0
  56. package/dist/core/fold.js +12 -6
  57. package/dist/core/fork.d.ts +35 -0
  58. package/dist/core/fork.js +129 -0
  59. package/dist/core/index.d.ts +3 -0
  60. package/dist/core/index.js +2 -0
  61. package/dist/core/module-scope.d.ts +1 -0
  62. package/dist/core/module.d.ts +4 -2
  63. package/dist/core/projection.js +1 -0
  64. package/dist/core/protocol.d.ts +10 -1
  65. package/dist/core/protocol.js +11 -0
  66. package/dist/core/published.d.ts +43 -0
  67. package/dist/core/published.js +44 -0
  68. package/dist/core/replay.d.ts +8 -0
  69. package/dist/core/schema.d.ts +3 -1
  70. package/dist/core/schema.js +38 -0
  71. package/dist/core/snapshot-store.d.ts +4 -0
  72. package/dist/core/snapshot-store.js +7 -0
  73. package/dist/core/snapshots.js +3 -17
  74. package/dist/core/sqlite-store.js +39 -0
  75. package/dist/core/state.d.ts +14 -0
  76. package/dist/core/state.js +25 -2
  77. package/dist/core/store.d.ts +1 -0
  78. package/dist/debugger/app/assets/index-BevQYa-U.js +22 -0
  79. package/dist/debugger/app/assets/index-CgDzWJg7.css +2 -0
  80. package/dist/debugger/app/assets/rolldown-runtime-CbXtAM7H.js +1 -0
  81. package/dist/debugger/app/assets/routes-B17Om93i.js +47 -0
  82. package/dist/debugger/app/index.html +14 -0
  83. package/dist/debugger/components/composer.d.ts +20 -0
  84. package/dist/debugger/components/composer.js +26 -0
  85. package/dist/debugger/components/debugger-split.d.ts +2 -1
  86. package/dist/debugger/components/debugger-split.js +2 -2
  87. package/dist/debugger/components/event-inspector.d.ts +2 -1
  88. package/dist/debugger/components/event-inspector.js +25 -16
  89. package/dist/debugger/components/event-stream.d.ts +2 -1
  90. package/dist/debugger/components/event-stream.js +12 -71
  91. package/dist/debugger/components/follow-list.d.ts +19 -0
  92. package/dist/debugger/components/follow-list.js +96 -0
  93. package/dist/debugger/components/json-tree.d.ts +11 -0
  94. package/dist/debugger/components/json-tree.js +120 -0
  95. package/dist/debugger/components/json-view.js +2 -2
  96. package/dist/debugger/components/run-tree.js +50 -20
  97. package/dist/debugger/components/status-dot.d.ts +4 -0
  98. package/dist/debugger/components/status-dot.js +6 -2
  99. package/dist/debugger/context.d.ts +14 -0
  100. package/dist/debugger/context.js +17 -0
  101. package/dist/debugger/contracts.d.ts +7 -4
  102. package/dist/debugger/events/builtin-families.d.ts +3 -0
  103. package/dist/debugger/events/builtin-families.js +9 -0
  104. package/dist/debugger/events/catalog.d.ts +3 -4
  105. package/dist/debugger/events/catalog.js +25 -17
  106. package/dist/debugger/events/protocol-summarize.d.ts +1 -2
  107. package/dist/debugger/events/protocol-summarize.js +36 -37
  108. package/dist/debugger/index.d.ts +20 -6
  109. package/dist/debugger/index.js +19 -5
  110. package/dist/debugger/lib/cn.d.ts +1 -0
  111. package/dist/debugger/lib/cn.js +3 -0
  112. package/dist/debugger/lib/event-counts.d.ts +2 -2
  113. package/dist/debugger/lib/event-counts.js +5 -9
  114. package/dist/debugger/lib/event-meta.d.ts +2 -3
  115. package/dist/debugger/lib/event-meta.js +6 -11
  116. package/dist/debugger/lib/json.d.ts +25 -0
  117. package/dist/debugger/lib/json.js +87 -0
  118. package/dist/debugger/lib/payload.d.ts +7 -0
  119. package/dist/debugger/lib/payload.js +11 -0
  120. package/dist/debugger/lib/time.d.ts +3 -0
  121. package/dist/debugger/lib/time.js +24 -0
  122. package/dist/debugger/plugin.d.ts +36 -0
  123. package/dist/debugger/plugin.js +14 -0
  124. package/dist/debugger/server/index.d.ts +14 -0
  125. package/dist/debugger/server/index.js +114 -0
  126. package/dist/debugger/shell/debugger-shell.d.ts +15 -0
  127. package/dist/debugger/shell/debugger-shell.js +43 -0
  128. package/dist/debugger/shell/definition-key.d.ts +3 -0
  129. package/dist/debugger/shell/definition-key.js +4 -0
  130. package/dist/debugger/shell/events-pane.d.ts +12 -0
  131. package/dist/debugger/shell/events-pane.js +25 -0
  132. package/dist/debugger/shell/projections-panel.d.ts +4 -0
  133. package/dist/debugger/shell/projections-panel.js +59 -0
  134. package/dist/debugger/shell/run-controls.d.ts +5 -0
  135. package/dist/debugger/shell/run-controls.js +99 -0
  136. package/dist/debugger/shell/run-search.d.ts +6 -0
  137. package/dist/debugger/shell/run-search.js +100 -0
  138. package/dist/debugger/shell/run-type-menu.d.ts +6 -0
  139. package/dist/debugger/shell/run-type-menu.js +11 -0
  140. package/dist/debugger/shell/schema-form.d.ts +31 -0
  141. package/dist/debugger/shell/schema-form.js +117 -0
  142. package/dist/debugger/shell/start-form.d.ts +3 -0
  143. package/dist/debugger/shell/start-form.js +75 -0
  144. package/dist/debugger/shell/use-start-run.d.ts +14 -0
  145. package/dist/debugger/shell/use-start-run.js +32 -0
  146. package/dist/debugger/shell/workspace.d.ts +6 -0
  147. package/dist/debugger/shell/workspace.js +15 -0
  148. package/dist/debugger/styles.css +111 -27
  149. package/dist/debugger/ui/button.d.ts +24 -0
  150. package/dist/debugger/ui/button.js +24 -0
  151. package/dist/debugger/ui/command.d.ts +9 -0
  152. package/dist/debugger/ui/command.js +24 -0
  153. package/dist/debugger/ui/dropdown-menu.d.ts +13 -0
  154. package/dist/debugger/ui/dropdown-menu.js +37 -0
  155. package/dist/debugger/ui/panel.d.ts +14 -0
  156. package/dist/debugger/ui/panel.js +16 -0
  157. package/dist/debugger/ui/popover.d.ts +7 -0
  158. package/dist/debugger/ui/popover.js +17 -0
  159. package/dist/debugger/ui/resizable.d.ts +7 -0
  160. package/dist/debugger/ui/resizable.js +14 -0
  161. package/dist/debugger/ui/scroll-area.d.ts +2 -1
  162. package/dist/debugger/ui/scroll-area.js +5 -3
  163. package/dist/debugger/ui/select.d.ts +10 -0
  164. package/dist/debugger/ui/select.js +21 -0
  165. package/dist/debugger/ui/tabs.js +2 -2
  166. package/dist/debugger/ui/textarea.d.ts +3 -0
  167. package/dist/debugger/ui/textarea.js +7 -0
  168. package/dist/evaluator/effects.d.ts +12 -0
  169. package/dist/evaluator/module.d.ts +24 -0
  170. package/dist/projectors/index-model.d.ts +13 -7
  171. package/dist/projectors/index-model.js +21 -26
  172. package/dist/projectors/memory.js +19 -11
  173. package/dist/projectors/postgres.js +20 -19
  174. package/dist/projectors/schema.js +20 -18
  175. package/dist/projectors/sqlite.js +32 -27
  176. package/dist/react/materialize.js +16 -11
  177. package/dist/react/react.d.ts +6 -2
  178. package/dist/react/react.js +5 -2
  179. package/dist/react/store.d.ts +1 -1
  180. package/dist/react/store.js +1 -1
  181. package/dist/react/tables.d.ts +3 -2
  182. package/dist/runtime/cancellation.js +14 -27
  183. package/dist/runtime/errors.d.ts +39 -0
  184. package/dist/runtime/errors.js +32 -0
  185. package/dist/runtime/helpers.d.ts +2 -0
  186. package/dist/runtime/helpers.js +23 -1
  187. package/dist/runtime/index.d.ts +1 -1
  188. package/dist/runtime/index.js +1 -1
  189. package/dist/runtime/looms.d.ts +13 -1
  190. package/dist/runtime/looms.js +5 -2
  191. package/dist/runtime/repository.js +16 -1
  192. package/dist/runtime/run-start.js +1 -3
  193. package/dist/runtime/runtime.d.ts +1 -1
  194. package/dist/runtime/runtime.js +60 -18
  195. package/dist/runtime/server/auth.d.ts +1 -0
  196. package/dist/runtime/server/auth.js +5 -0
  197. package/dist/runtime/server/debugger-host.d.ts +11 -0
  198. package/dist/runtime/server/debugger-host.js +32 -0
  199. package/dist/runtime/server/fetch-handler.d.ts +5 -1
  200. package/dist/runtime/server/fetch-handler.js +24 -13
  201. package/dist/runtime/server/http.d.ts +3 -0
  202. package/dist/runtime/server/http.js +21 -2
  203. package/dist/runtime/server/routes/definitions.d.ts +3 -0
  204. package/dist/runtime/server/routes/definitions.js +20 -0
  205. package/dist/runtime/server/routes/runs.js +43 -3
  206. package/dist/runtime/server.d.ts +3 -1
  207. package/dist/runtime/server.js +3 -1
  208. package/dist/runtime/types.d.ts +11 -1
  209. package/dist/runtime/wake-engine.js +5 -2
  210. package/dist/s2/snapshot-store.js +45 -7
  211. package/dist/workflow/debugger/index.d.ts +4 -0
  212. package/dist/workflow/debugger/index.js +11 -0
  213. package/dist/workflow/debugger/nodes-view.d.ts +3 -0
  214. package/dist/workflow/debugger/nodes-view.js +13 -0
  215. package/dist/workflow/debugger/summarize.d.ts +2 -0
  216. package/dist/workflow/debugger/summarize.js +30 -0
  217. package/dist/workflow/effects.d.ts +24 -0
  218. package/dist/workflow/effects.js +1 -0
  219. package/dist/workflow/module.d.ts +48 -0
  220. package/package.json +20 -1
  221. package/dist/debugger/events/domain-summarize.d.ts +0 -3
  222. package/dist/debugger/events/domain-summarize.js +0 -107
  223. package/dist/debugger/events/family.d.ts +0 -8
  224. package/dist/debugger/events/family.js +0 -44
@@ -1,6 +1,6 @@
1
1
  import { AppendInput, AppendRecord, S2, S2Endpoints, S2Error } from '@s2-dev/streamstore';
2
2
  import { Effect, Layer, Option, Schema, Stream } from 'effect';
3
- import { createKeyedSerializer, assertSnapshotByteLimit, RunStateSchema, SnapshotStoreError, SnapshotPayloadTooLargeError, SnapshotStoreTag, } from '@swirls/looms/core';
3
+ import { createKeyedSerializer, assertSnapshotByteLimit, RunStateSchema, RunSummarySchema, SnapshotStoreError, SnapshotPayloadTooLargeError, SnapshotStoreTag, } from '@swirls/looms/core';
4
4
  import { S2ConfigSchema } from './config.js';
5
5
  import { paginateS2Stream } from './pagination.js';
6
6
  const DEFAULT_PREFIX = 'snapshots';
@@ -18,6 +18,9 @@ const SnapshotFrameSchema = Schema.Struct({
18
18
  const SnapshotFrameJson = Schema.fromJsonString(SnapshotFrameSchema);
19
19
  const decodeFrame = Schema.decodeSync(SnapshotFrameJson);
20
20
  const encodeFrame = Schema.encodeSync(SnapshotFrameJson);
21
+ const HeaderJson = Schema.fromJsonString(RunSummarySchema);
22
+ const decodeHeader = Schema.decodeUnknownOption(HeaderJson);
23
+ const encodeHeader = Schema.encodeSync(HeaderJson);
21
24
  export function frameSnapshot(snapshot, maxChunkBytes = DEFAULT_MAX_CHUNK_BYTES) {
22
25
  const json = JSON.stringify(snapshot.state);
23
26
  const chunks = Math.max(1, Math.ceil(json.length / maxChunkBytes));
@@ -41,9 +44,7 @@ export function assembleSnapshot(frames) {
41
44
  throw new SnapshotStoreError('Cannot assemble snapshot from empty frames');
42
45
  }
43
46
  const first = frames[0];
44
- // Oxlint's immutable alternative requires ES2023; sorting a fresh copy is safe on ES2022.
45
- // oxlint-disable-next-line unicorn/no-array-sort
46
- const ordered = [...frames].sort((a, b) => a.chunk - b.chunk);
47
+ const ordered = frames.toSorted((a, b) => a.chunk - b.chunk);
47
48
  for (const frame of ordered) {
48
49
  if (frame.cursor !== first.cursor ||
49
50
  frame.chunks !== first.chunks ||
@@ -160,9 +161,7 @@ function groupCompleteSnapshots(records) {
160
161
  continue;
161
162
  }
162
163
  }
163
- // `assembled` is function-local, so in-place sorting cannot mutate caller-owned data.
164
- // oxlint-disable-next-line unicorn/no-array-sort
165
- return assembled.sort((a, b) => a.cursor - b.cursor);
164
+ return assembled.toSorted((a, b) => a.cursor - b.cursor);
166
165
  }
167
166
  export function s2SnapshotStore(config) {
168
167
  const parsed = Schema.decodeSync(S2ConfigSchema)(config);
@@ -171,7 +170,9 @@ export function s2SnapshotStore(config) {
171
170
  const prefix = parsed.snapshotPrefix ?? DEFAULT_PREFIX;
172
171
  const appends = createKeyedSerializer();
173
172
  const ensured = new Set();
173
+ const headers = new Map();
174
174
  let basinEnsured = false;
175
+ let headersLoaded = false;
175
176
  const streamName = (runId) => `${prefix}/${runId}`;
176
177
  const ensureBasin = Effect.suspend(() => {
177
178
  if (basinEnsured) {
@@ -297,6 +298,43 @@ export function s2SnapshotStore(config) {
297
298
  catch: (cause) => toSnapshotError(cause, `Failed to prune snapshots for ${runId}`),
298
299
  });
299
300
  }),
301
+ saveHeader: (header) => Effect.gen(function* () {
302
+ const stream = yield* ensureStream('__headers');
303
+ yield* Effect.tryPromise({
304
+ try: () => appends.run('__headers', () => stream.append(AppendInput.create([AppendRecord.string({ body: encodeHeader(header) })]))),
305
+ catch: (cause) => toSnapshotError(cause, `Failed to save run header for ${header.runId}`),
306
+ });
307
+ headers.set(header.runId, header);
308
+ }),
309
+ listHeaders: Effect.gen(function* () {
310
+ if (headersLoaded) {
311
+ return [...headers.values()];
312
+ }
313
+ const stream = yield* ensureStream('__headers');
314
+ const records = yield* paginateS2Stream((cursor, count) => Effect.tryPromise({
315
+ try: () => stream.read({
316
+ start: { from: { seqNum: cursor }, clamp: true },
317
+ stop: { limits: { count } },
318
+ ignoreCommandRecords: true,
319
+ }),
320
+ catch: (cause) => toSnapshotError(cause, 'Failed to read run headers'),
321
+ }).pipe(Effect.catchIf((error) => error.cause instanceof S2Error &&
322
+ (error.cause.status === 404 || error.cause.status === 416), () => Effect.succeed(null)))).pipe(Stream.runCollect);
323
+ const loaded = new Map();
324
+ for (const record of records) {
325
+ const decoded = decodeHeader(record.body);
326
+ if (Option.isSome(decoded)) {
327
+ loaded.set(decoded.value.runId, decoded.value);
328
+ }
329
+ }
330
+ for (const [runId, header] of loaded) {
331
+ if (!headers.has(runId)) {
332
+ headers.set(runId, header);
333
+ }
334
+ }
335
+ headersLoaded = true;
336
+ return [...headers.values()];
337
+ }),
300
338
  };
301
339
  return service;
302
340
  }
@@ -0,0 +1,4 @@
1
+ import type { DebuggerPlugin } from '@swirls/looms/debugger';
2
+ import { WorkflowNodesView } from './nodes-view';
3
+ export declare const workflowDebugger: DebuggerPlugin;
4
+ export { WorkflowNodesView };
@@ -0,0 +1,11 @@
1
+ import { nodes } from '../projections.js';
2
+ import { WorkflowNodesView } from './nodes-view.js';
3
+ import { summarizeWorkflowEvent } from './summarize.js';
4
+ export const workflowDebugger = {
5
+ name: 'workflow',
6
+ families: [
7
+ { family: 'workflow', color: 'oklch(0.76 0.12 300)', summarize: summarizeWorkflowEvent },
8
+ ],
9
+ projections: [{ name: nodes.name, component: WorkflowNodesView }],
10
+ };
11
+ export { WorkflowNodesView };
@@ -0,0 +1,3 @@
1
+ export declare function WorkflowNodesView({ runId }: {
2
+ runId: string;
3
+ }): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { asJson } from '@swirls/looms/core';
3
+ import { JsonTree, StatusBadge } from '@swirls/looms/debugger';
4
+ import { useProjection, useRunStore } from '@swirls/looms/react';
5
+ import { nodes } from '../projections.js';
6
+ export function WorkflowNodesView({ runId }) {
7
+ const state = useProjection(useRunStore(runId), nodes);
8
+ const entries = Object.entries(state.nodes);
9
+ if (entries.length === 0) {
10
+ return _jsx("p", { className: "text-muted-foreground text-xs", children: "No nodes yet." });
11
+ }
12
+ return (_jsx("ul", { className: "grid gap-2", children: entries.map(([id, node]) => (_jsxs("li", { className: "border-border bg-card/60 rounded-lg border p-2.5 text-xs", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "min-w-0 flex-1 truncate font-mono font-medium", children: id }), _jsx(StatusBadge, { status: node.status })] }), node.result !== null ? (_jsx(JsonTree, { value: asJson(node.result), className: "mt-1.5" })) : null, node.error ? _jsx("p", { className: "text-status-failed mt-1.5", children: node.error }) : null] }, id))) }));
13
+ }
@@ -0,0 +1,2 @@
1
+ import { type DebuggerEvent, type EventSummary } from '@swirls/looms/debugger';
2
+ export declare function summarizeWorkflowEvent(event: DebuggerEvent): EventSummary | undefined;
@@ -0,0 +1,30 @@
1
+ import { compactJson, jsonFields, jsonText, } from '@swirls/looms/debugger';
2
+ export function summarizeWorkflowEvent(event) {
3
+ const payload = jsonFields(event.payload);
4
+ switch (event.type) {
5
+ case 'workflow.node.started':
6
+ return { title: 'node started', detail: jsonText(payload.nodeId) };
7
+ case 'workflow.node.finished':
8
+ return {
9
+ title: jsonText(payload.error) ? 'node failed' : 'node finished',
10
+ detail: jsonText(payload.error) ??
11
+ `${jsonText(payload.nodeId) ?? ''} ${compactJson(payload.result ?? null)}`,
12
+ };
13
+ case 'workflow.node.skipped':
14
+ return {
15
+ title: 'node skipped',
16
+ detail: `${jsonText(payload.nodeId) ?? ''} · ${jsonText(payload.reason) ?? ''}`,
17
+ };
18
+ case 'workflow.spawn.requested':
19
+ return {
20
+ title: 'workflow spawn',
21
+ detail: `${jsonText(payload.definitionName) ?? 'unknown'} from ${jsonText(payload.nodeId) ?? ''}`,
22
+ };
23
+ case 'workflow.sleep.requested':
24
+ return { title: 'sleep', detail: jsonText(payload.nodeId) };
25
+ case 'workflow.effects.requested':
26
+ return { title: 'workflow effects', detail: jsonText(payload.nodeId) };
27
+ default:
28
+ return undefined;
29
+ }
30
+ }
@@ -104,6 +104,11 @@ export declare const scheduleEffect: NoInfer<import("@swirls/looms/core").Effect
104
104
  readonly attempt: number;
105
105
  readonly deadlineAt: number | null;
106
106
  };
107
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
108
+ readonly type: "runtime.fork.elided";
109
+ readonly payload: {
110
+ readonly type: string;
111
+ };
107
112
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
108
113
  readonly type: "runtime.run.cancelled";
109
114
  readonly payload: {
@@ -115,6 +120,12 @@ export declare const scheduleEffect: NoInfer<import("@swirls/looms/core").Effect
115
120
  readonly output: Schema.Json;
116
121
  readonly error: string | null;
117
122
  };
123
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
124
+ readonly type: "runtime.run.forked";
125
+ readonly payload: {
126
+ readonly sourceRunId: string;
127
+ readonly sourceSeq: number;
128
+ };
118
129
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
119
130
  readonly type: "runtime.run.started";
120
131
  readonly payload: {
@@ -147,6 +158,7 @@ export declare const scheduleEffect: NoInfer<import("@swirls/looms/core").Effect
147
158
  readonly payload: {
148
159
  readonly threadId: string;
149
160
  readonly reason?: string | undefined;
161
+ readonly resumeSeq?: number | undefined;
150
162
  };
151
163
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
152
164
  readonly type: "runtime.thread.completed";
@@ -431,6 +443,11 @@ export declare const runNodeEffect: NoInfer<import("@swirls/looms/core").EffectD
431
443
  readonly attempt: number;
432
444
  readonly deadlineAt: number | null;
433
445
  };
446
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
447
+ readonly type: "runtime.fork.elided";
448
+ readonly payload: {
449
+ readonly type: string;
450
+ };
434
451
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
435
452
  readonly type: "runtime.run.cancelled";
436
453
  readonly payload: {
@@ -442,6 +459,12 @@ export declare const runNodeEffect: NoInfer<import("@swirls/looms/core").EffectD
442
459
  readonly output: Schema.Json;
443
460
  readonly error: string | null;
444
461
  };
462
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
463
+ readonly type: "runtime.run.forked";
464
+ readonly payload: {
465
+ readonly sourceRunId: string;
466
+ readonly sourceSeq: number;
467
+ };
445
468
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
446
469
  readonly type: "runtime.run.started";
447
470
  readonly payload: {
@@ -474,6 +497,7 @@ export declare const runNodeEffect: NoInfer<import("@swirls/looms/core").EffectD
474
497
  readonly payload: {
475
498
  readonly threadId: string;
476
499
  readonly reason?: string | undefined;
500
+ readonly resumeSeq?: number | undefined;
477
501
  };
478
502
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
479
503
  readonly type: "runtime.thread.completed";
@@ -46,6 +46,7 @@ function threadFailed(threadId, error) {
46
46
  export const scheduleEffect = workflowModule.effect({
47
47
  type: 'workflow.schedule',
48
48
  input: ScheduleInput,
49
+ deterministic: true,
49
50
  execute: (input, ctx) => Effect.gen(function* () {
50
51
  const workflows = yield* WorkflowDefinitionsTag;
51
52
  const definition = input.definitionName
@@ -203,6 +203,11 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
203
203
  readonly attempt: number;
204
204
  readonly deadlineAt: number | null;
205
205
  };
206
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
207
+ readonly type: "runtime.fork.elided";
208
+ readonly payload: {
209
+ readonly type: string;
210
+ };
206
211
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
207
212
  readonly type: "runtime.run.cancelled";
208
213
  readonly payload: {
@@ -214,6 +219,12 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
214
219
  readonly output: import("effect/Schema").Json;
215
220
  readonly error: string | null;
216
221
  };
222
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
223
+ readonly type: "runtime.run.forked";
224
+ readonly payload: {
225
+ readonly sourceRunId: string;
226
+ readonly sourceSeq: number;
227
+ };
217
228
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
218
229
  readonly type: "runtime.run.started";
219
230
  readonly payload: {
@@ -246,6 +257,7 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
246
257
  readonly payload: {
247
258
  readonly threadId: string;
248
259
  readonly reason?: string | undefined;
260
+ readonly resumeSeq?: number | undefined;
249
261
  };
250
262
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
251
263
  readonly type: "runtime.thread.completed";
@@ -526,6 +538,11 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
526
538
  readonly attempt: number;
527
539
  readonly deadlineAt: number | null;
528
540
  };
541
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
542
+ readonly type: "runtime.fork.elided";
543
+ readonly payload: {
544
+ readonly type: string;
545
+ };
529
546
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
530
547
  readonly type: "runtime.run.cancelled";
531
548
  readonly payload: {
@@ -537,6 +554,12 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
537
554
  readonly output: import("effect/Schema").Json;
538
555
  readonly error: string | null;
539
556
  };
557
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
558
+ readonly type: "runtime.run.forked";
559
+ readonly payload: {
560
+ readonly sourceRunId: string;
561
+ readonly sourceSeq: number;
562
+ };
540
563
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
541
564
  readonly type: "runtime.run.started";
542
565
  readonly payload: {
@@ -569,6 +592,7 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
569
592
  readonly payload: {
570
593
  readonly threadId: string;
571
594
  readonly reason?: string | undefined;
595
+ readonly resumeSeq?: number | undefined;
572
596
  };
573
597
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
574
598
  readonly type: "runtime.thread.completed";
@@ -1003,6 +1027,11 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
1003
1027
  readonly attempt: number;
1004
1028
  readonly deadlineAt: number | null;
1005
1029
  };
1030
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1031
+ readonly type: "runtime.fork.elided";
1032
+ readonly payload: {
1033
+ readonly type: string;
1034
+ };
1006
1035
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1007
1036
  readonly type: "runtime.run.cancelled";
1008
1037
  readonly payload: {
@@ -1014,6 +1043,12 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
1014
1043
  readonly output: import("effect/Schema").Json;
1015
1044
  readonly error: string | null;
1016
1045
  };
1046
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1047
+ readonly type: "runtime.run.forked";
1048
+ readonly payload: {
1049
+ readonly sourceRunId: string;
1050
+ readonly sourceSeq: number;
1051
+ };
1017
1052
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1018
1053
  readonly type: "runtime.run.started";
1019
1054
  readonly payload: {
@@ -1046,6 +1081,7 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
1046
1081
  readonly payload: {
1047
1082
  readonly threadId: string;
1048
1083
  readonly reason?: string | undefined;
1084
+ readonly resumeSeq?: number | undefined;
1049
1085
  };
1050
1086
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1051
1087
  readonly type: "runtime.thread.completed";
@@ -1326,6 +1362,11 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
1326
1362
  readonly attempt: number;
1327
1363
  readonly deadlineAt: number | null;
1328
1364
  };
1365
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1366
+ readonly type: "runtime.fork.elided";
1367
+ readonly payload: {
1368
+ readonly type: string;
1369
+ };
1329
1370
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1330
1371
  readonly type: "runtime.run.cancelled";
1331
1372
  readonly payload: {
@@ -1337,6 +1378,12 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
1337
1378
  readonly output: import("effect/Schema").Json;
1338
1379
  readonly error: string | null;
1339
1380
  };
1381
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1382
+ readonly type: "runtime.run.forked";
1383
+ readonly payload: {
1384
+ readonly sourceRunId: string;
1385
+ readonly sourceSeq: number;
1386
+ };
1340
1387
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1341
1388
  readonly type: "runtime.run.started";
1342
1389
  readonly payload: {
@@ -1369,6 +1416,7 @@ export declare function workflow(options?: WorkflowModuleOptions): import("@swir
1369
1416
  readonly payload: {
1370
1417
  readonly threadId: string;
1371
1418
  readonly reason?: string | undefined;
1419
+ readonly resumeSeq?: number | undefined;
1372
1420
  };
1373
1421
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
1374
1422
  readonly type: "runtime.thread.completed";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swirls/looms",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Pluggable event-sourced runtime for durable agents and workflows",
5
5
  "homepage": "https://github.com/ByteSliceHQ/looms#readme",
6
6
  "bugs": {
@@ -37,6 +37,10 @@
37
37
  "types": "./dist/agent/index.d.ts",
38
38
  "import": "./dist/agent/index.js"
39
39
  },
40
+ "./agent/debugger": {
41
+ "types": "./dist/agent/debugger/index.d.ts",
42
+ "import": "./dist/agent/debugger/index.js"
43
+ },
40
44
  "./ai-vercel": {
41
45
  "types": "./dist/ai-vercel/index.d.ts",
42
46
  "import": "./dist/ai-vercel/index.js"
@@ -45,6 +49,10 @@
45
49
  "types": "./dist/approval/index.d.ts",
46
50
  "import": "./dist/approval/index.js"
47
51
  },
52
+ "./approval/debugger": {
53
+ "types": "./dist/approval/debugger/index.d.ts",
54
+ "import": "./dist/approval/debugger/index.js"
55
+ },
48
56
  "./cli": {
49
57
  "types": "./dist/cli/index.d.ts",
50
58
  "import": "./dist/cli/index.js"
@@ -65,6 +73,10 @@
65
73
  "types": "./dist/debugger/index.d.ts",
66
74
  "import": "./dist/debugger/index.js"
67
75
  },
76
+ "./debugger/server": {
77
+ "types": "./dist/debugger/server/index.d.ts",
78
+ "import": "./dist/debugger/server/index.js"
79
+ },
68
80
  "./evaluator": {
69
81
  "types": "./dist/evaluator/index.d.ts",
70
82
  "import": "./dist/evaluator/index.js"
@@ -93,6 +105,10 @@
93
105
  "types": "./dist/workflow/index.d.ts",
94
106
  "import": "./dist/workflow/index.js"
95
107
  },
108
+ "./workflow/debugger": {
109
+ "types": "./dist/workflow/debugger/index.d.ts",
110
+ "import": "./dist/workflow/debugger/index.js"
111
+ },
96
112
  "./core/sqlite-store": {
97
113
  "types": "./dist/core/sqlite-store.d.ts",
98
114
  "import": "./dist/core/sqlite-store.js"
@@ -132,9 +148,11 @@
132
148
  "@standard-schema/spec": "^1.1.0",
133
149
  "@tanstack/react-virtual": "^3.14.11",
134
150
  "clsx": "^2.1.1",
151
+ "cmdk": "^1.1.1",
135
152
  "effect": "4.0.0-rc.112",
136
153
  "lucide-react": "^1.43.0",
137
154
  "radix-ui": "^1.6.7",
155
+ "react-resizable-panels": "^4.13.3",
138
156
  "tailwind-merge": "^3.6.0"
139
157
  },
140
158
  "devDependencies": {
@@ -148,6 +166,7 @@
148
166
  "@looms/cloudflare": "workspace:*",
149
167
  "@looms/core": "workspace:*",
150
168
  "@looms/debugger": "workspace:*",
169
+ "@looms/debugger-app": "workspace:*",
151
170
  "@looms/evaluator": "workspace:*",
152
171
  "@looms/projectors": "workspace:*",
153
172
  "@looms/react": "workspace:*",
@@ -1,3 +0,0 @@
1
- import type { DebuggerEvent } from '../contracts';
2
- import type { EventSummary } from './family';
3
- export declare function summarizeDomainEvent(event: DebuggerEvent): EventSummary | undefined;
@@ -1,107 +0,0 @@
1
- import { isJsonNumber, isJsonObject, isJsonString } from '@swirls/looms/core';
2
- import { compactJson } from '../lib/cn.js';
3
- function obj(value) {
4
- return isJsonObject(value) ? value : {};
5
- }
6
- function text(value) {
7
- return isJsonString(value) ? value : undefined;
8
- }
9
- function numeric(value) {
10
- return isJsonNumber(value) ? String(value) : undefined;
11
- }
12
- function messageContent(payload) {
13
- const message = obj(payload ?? null).message;
14
- return isJsonObject(message) && isJsonString(message.content) ? message.content : undefined;
15
- }
16
- function toolCallSummary(payload) {
17
- const call = obj(payload ?? null).toolCall;
18
- if (!isJsonObject(call)) {
19
- return { name: 'tool', args: null };
20
- }
21
- const summary = {
22
- name: isJsonString(call.name) ? call.name : 'tool',
23
- args: call.arguments ?? null,
24
- };
25
- return summary;
26
- }
27
- export function summarizeDomainEvent(event) {
28
- const payload = obj(event.payload);
29
- switch (event.type) {
30
- case 'agent.message.received':
31
- return { title: 'user message', detail: messageContent(event.payload) };
32
- case 'agent.turn.started':
33
- return { title: 'turn started', detail: `turn ${numeric(payload.turn) ?? ''}` };
34
- case 'agent.turn.text_delta':
35
- return { title: 'text delta', detail: text(payload.delta) };
36
- case 'agent.message':
37
- return { title: 'agent message', detail: messageContent(event.payload) };
38
- case 'agent.tool_call.requested': {
39
- const call = toolCallSummary(event.payload);
40
- return { title: `tool ${call.name}`, detail: compactJson(call.args) };
41
- }
42
- case 'agent.tool.result':
43
- return {
44
- title: text(payload.error)
45
- ? `tool error ${text(payload.name)}`
46
- : `tool result ${text(payload.name)}`,
47
- detail: text(payload.error) ?? compactJson(payload.result ?? null),
48
- };
49
- case 'agent.steered':
50
- return { title: 'steered', detail: messageContent(event.payload) };
51
- case 'agent.spawn.requested':
52
- return {
53
- title: 'agent spawn',
54
- detail: `${text(payload.kind) ?? 'agent'}:${text(payload.definitionName) ?? 'unknown'}`,
55
- };
56
- case 'agent.effects.requested':
57
- return { title: 'agent effects', detail: text(payload.toolCallId) };
58
- case 'workflow.node.started':
59
- return { title: 'node started', detail: text(payload.nodeId) };
60
- case 'workflow.node.finished':
61
- return {
62
- title: text(payload.error) ? 'node failed' : 'node finished',
63
- detail: text(payload.error) ??
64
- `${text(payload.nodeId) ?? ''} ${compactJson(payload.result ?? null)}`,
65
- };
66
- case 'workflow.node.skipped':
67
- return {
68
- title: 'node skipped',
69
- detail: `${text(payload.nodeId) ?? ''} · ${text(payload.reason) ?? ''}`,
70
- };
71
- case 'workflow.spawn.requested':
72
- return {
73
- title: 'workflow spawn',
74
- detail: `${text(payload.definitionName) ?? 'unknown'} from ${text(payload.nodeId) ?? ''}`,
75
- };
76
- case 'workflow.sleep.requested':
77
- return { title: 'sleep', detail: text(payload.nodeId) };
78
- case 'workflow.effects.requested':
79
- return { title: 'workflow effects', detail: text(payload.nodeId) };
80
- case 'approval.requested':
81
- return { title: 'approval requested', detail: text(payload.title) };
82
- case 'approval.decided':
83
- return {
84
- title: `approval ${text(payload.outcome) ?? 'decided'}`,
85
- detail: text(payload.approvalId),
86
- };
87
- case 'approval.timed_out':
88
- return { title: 'approval timed out', detail: text(payload.approvalId) };
89
- case 'payments.charge.requested':
90
- return {
91
- title: 'charge requested',
92
- detail: `${numeric(payload.amount) ?? ''} ${text(payload.currency) ?? ''}`.trim(),
93
- };
94
- case 'payments.charge.authorized':
95
- return {
96
- title: 'charge authorized',
97
- detail: `${numeric(payload.amount) ?? ''} ${text(payload.currency) ?? ''}`.trim(),
98
- };
99
- case 'payments.charge.declined':
100
- return {
101
- title: 'charge declined',
102
- detail: `${numeric(payload.amount) ?? ''} ${text(payload.currency) ?? ''} · ${text(payload.reason) ?? ''}`.trim(),
103
- };
104
- default:
105
- return undefined;
106
- }
107
- }
@@ -1,8 +0,0 @@
1
- export declare const DEFAULT_FAMILIES: readonly ['runtime', 'agent', 'workflow', 'approval', 'payments', 'wait'];
2
- export type EventFamily = (typeof DEFAULT_FAMILIES)[number];
3
- export type EventSummary = {
4
- title: string;
5
- detail?: string;
6
- };
7
- export declare function familyFromPrefix(type: string): EventFamily;
8
- export declare function familyClass(family: string): string;
@@ -1,44 +0,0 @@
1
- export const DEFAULT_FAMILIES = [
2
- 'runtime',
3
- 'agent',
4
- 'workflow',
5
- 'approval',
6
- 'payments',
7
- 'wait',
8
- ];
9
- export function familyFromPrefix(type) {
10
- if (type.startsWith('agent.')) {
11
- return 'agent';
12
- }
13
- if (type.startsWith('workflow.')) {
14
- return 'workflow';
15
- }
16
- if (type.startsWith('approval.')) {
17
- return 'approval';
18
- }
19
- if (type.startsWith('payments.')) {
20
- return 'payments';
21
- }
22
- if (type.startsWith('runtime.wait')) {
23
- return 'wait';
24
- }
25
- return 'runtime';
26
- }
27
- export function familyClass(family) {
28
- switch (family) {
29
- case 'agent':
30
- return 'bg-family-agent';
31
- case 'workflow':
32
- return 'bg-family-workflow';
33
- case 'approval':
34
- return 'bg-family-approval';
35
- case 'payments':
36
- return 'bg-family-payments';
37
- case 'wait':
38
- return 'bg-family-wait';
39
- case 'runtime':
40
- return 'bg-family-runtime';
41
- default:
42
- return 'bg-family-runtime';
43
- }
44
- }