@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
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Command as CommandPrimitive } from 'cmdk';
3
+ import { Search } from 'lucide-react';
4
+ import * as React from 'react';
5
+ import { cn } from '../lib/cn.js';
6
+ function Command({ className, ...props }) {
7
+ return (_jsx(CommandPrimitive, { "data-slot": "command", className: cn('flex size-full flex-col overflow-hidden', className), ...props }));
8
+ }
9
+ function CommandInput({ className, ...props }) {
10
+ return (_jsxs("div", { "data-slot": "command-input-wrapper", className: "border-border flex h-10 items-center gap-2 border-b px-3", children: [_jsx(Search, { className: "text-muted-foreground size-3.5 shrink-0", "aria-hidden": true }), _jsx(CommandPrimitive.Input, { "data-slot": "command-input", className: cn('placeholder:text-muted-foreground flex h-full w-full bg-transparent text-[13px] outline-none disabled:cursor-not-allowed disabled:opacity-50', className), ...props })] }));
11
+ }
12
+ function CommandList({ className, ...props }) {
13
+ return (_jsx(CommandPrimitive.List, { "data-slot": "command-list", className: cn('max-h-80 scroll-py-1 overflow-x-hidden overflow-y-auto overscroll-contain p-1', className), ...props }));
14
+ }
15
+ function CommandEmpty({ className, ...props }) {
16
+ return (_jsx(CommandPrimitive.Empty, { "data-slot": "command-empty", className: cn('text-muted-foreground py-8 text-center text-xs', className), ...props }));
17
+ }
18
+ function CommandGroup({ className, ...props }) {
19
+ return (_jsx(CommandPrimitive.Group, { "data-slot": "command-group", className: cn('[&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pt-2 [&_[cmdk-group-heading]]:pb-1 [&_[cmdk-group-heading]]:text-[11px] [&_[cmdk-group-heading]]:font-medium', className), ...props }));
20
+ }
21
+ function CommandItem({ className, ...props }) {
22
+ return (_jsx(CommandPrimitive.Item, { "data-slot": "command-item", className: cn('data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-md px-2 py-1.5 text-xs outline-none select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50', className), ...props }));
23
+ }
24
+ export { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList };
@@ -0,0 +1,13 @@
1
+ import { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui';
2
+ import * as React from 'react';
3
+ declare function DropdownMenu(props: React.ComponentProps<typeof DropdownMenuPrimitive.Root>): React.JSX.Element;
4
+ declare function DropdownMenuTrigger(props: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>): React.JSX.Element;
5
+ declare function DropdownMenuContent({ className, sideOffset, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>): React.JSX.Element;
6
+ declare function DropdownMenuGroup(props: React.ComponentProps<typeof DropdownMenuPrimitive.Group>): React.JSX.Element;
7
+ declare function DropdownMenuLabel({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Label>): React.JSX.Element;
8
+ declare function DropdownMenuItem({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Item>): React.JSX.Element;
9
+ declare function DropdownMenuCheckboxItem({ className, children, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>): React.JSX.Element;
10
+ declare function DropdownMenuRadioGroup(props: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>): React.JSX.Element;
11
+ declare function DropdownMenuRadioItem({ className, children, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>): React.JSX.Element;
12
+ declare function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>): React.JSX.Element;
13
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, };
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Check } from 'lucide-react';
3
+ import { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui';
4
+ import * as React from 'react';
5
+ import { cn } from '../lib/cn.js';
6
+ const itemClass = 'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-xs outline-none select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:size-3.5 [&_svg]:shrink-0';
7
+ function DropdownMenu(props) {
8
+ return _jsx(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
9
+ }
10
+ function DropdownMenuTrigger(props) {
11
+ return _jsx(DropdownMenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
12
+ }
13
+ function DropdownMenuContent({ className, sideOffset = 6, ...props }) {
14
+ return (_jsx(DropdownMenuPrimitive.Portal, { children: _jsx(DropdownMenuPrimitive.Content, { "data-slot": "dropdown-menu-content", sideOffset: sideOffset, className: cn('debugger-pop bg-card text-card-foreground border-border z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-40 overflow-x-hidden overflow-y-auto overscroll-contain rounded-lg border p-1 shadow-xl shadow-black/30', className), ...props }) }));
15
+ }
16
+ function DropdownMenuGroup(props) {
17
+ return _jsx(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
18
+ }
19
+ function DropdownMenuLabel({ className, ...props }) {
20
+ return (_jsx(DropdownMenuPrimitive.Label, { "data-slot": "dropdown-menu-label", className: cn('text-muted-foreground px-2 pt-2 pb-1 text-[11px] font-medium', className), ...props }));
21
+ }
22
+ function DropdownMenuItem({ className, ...props }) {
23
+ return (_jsx(DropdownMenuPrimitive.Item, { "data-slot": "dropdown-menu-item", className: cn(itemClass, className), ...props }));
24
+ }
25
+ function DropdownMenuCheckboxItem({ className, children, ...props }) {
26
+ return (_jsxs(DropdownMenuPrimitive.CheckboxItem, { "data-slot": "dropdown-menu-checkbox-item", className: cn(itemClass, 'pl-7', className), ...props, children: [_jsx("span", { className: "absolute left-2 flex size-3.5 items-center justify-center", children: _jsx(DropdownMenuPrimitive.ItemIndicator, { children: _jsx(Check, {}) }) }), children] }));
27
+ }
28
+ function DropdownMenuRadioGroup(props) {
29
+ return _jsx(DropdownMenuPrimitive.RadioGroup, { "data-slot": "dropdown-menu-radio-group", ...props });
30
+ }
31
+ function DropdownMenuRadioItem({ className, children, ...props }) {
32
+ return (_jsxs(DropdownMenuPrimitive.RadioItem, { "data-slot": "dropdown-menu-radio-item", className: cn(itemClass, 'pl-7', className), ...props, children: [_jsx("span", { className: "absolute top-2 left-2 flex size-3.5 items-center justify-center", children: _jsx(DropdownMenuPrimitive.ItemIndicator, { children: _jsx(Check, {}) }) }), children] }));
33
+ }
34
+ function DropdownMenuSeparator({ className, ...props }) {
35
+ return (_jsx(DropdownMenuPrimitive.Separator, { "data-slot": "dropdown-menu-separator", className: cn('bg-border -mx-1 my-1 h-px', className), ...props }));
36
+ }
37
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, };
@@ -0,0 +1,14 @@
1
+ import type { ComponentProps, ReactNode } from 'react';
2
+ /** Every panel header shares this height so the columns read as one surface. */
3
+ declare function PanelHeader({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
4
+ declare function PanelTitle({ className, children, meta, ...props }: ComponentProps<'h2'> & {
5
+ meta?: ReactNode;
6
+ }): import("react").JSX.Element;
7
+ declare function EmptyState({ icon, title, children, className, }: {
8
+ icon?: ReactNode;
9
+ title: string;
10
+ children?: ReactNode;
11
+ className?: string;
12
+ }): import("react").JSX.Element;
13
+ declare function Kbd({ className, ...props }: ComponentProps<'kbd'>): import("react").JSX.Element;
14
+ export { EmptyState, Kbd, PanelHeader, PanelTitle };
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../lib/cn.js';
3
+ /** Every panel header shares this height so the columns read as one surface. */
4
+ function PanelHeader({ className, ...props }) {
5
+ return (_jsx("div", { "data-slot": "panel-header", className: cn('border-border flex h-10 shrink-0 items-center gap-2 border-b px-3', className), ...props }));
6
+ }
7
+ function PanelTitle({ className, children, meta, ...props }) {
8
+ return (_jsxs("h2", { "data-slot": "panel-title", className: cn('flex min-w-0 items-baseline gap-2 text-[13px] font-medium', className), ...props, children: [_jsx("span", { className: "truncate", children: children }), meta !== undefined && meta !== null ? (_jsx("span", { className: "text-muted-foreground shrink-0 font-mono text-[11px] font-normal tabular-nums", children: meta })) : null] }));
9
+ }
10
+ function EmptyState({ icon, title, children, className, }) {
11
+ return (_jsxs("div", { className: cn('flex h-full min-h-32 flex-col items-center justify-center gap-2 px-6 text-center', className), children: [icon ? (_jsx("div", { className: "text-muted-foreground/70 border-border bg-card mb-1 flex size-8 items-center justify-center rounded-lg border [&_svg]:size-4", children: icon })) : null, _jsx("p", { className: "text-foreground text-[13px] font-medium", children: title }), children ? (_jsx("p", { className: "text-muted-foreground max-w-60 text-xs leading-relaxed", children: children })) : null] }));
12
+ }
13
+ function Kbd({ className, ...props }) {
14
+ return (_jsx("kbd", { "data-slot": "kbd", className: cn('border-border bg-background/60 text-muted-foreground pointer-events-none inline-flex h-5 min-w-5 items-center justify-center rounded border px-1 font-sans text-[10px] font-medium', className), ...props }));
15
+ }
16
+ export { EmptyState, Kbd, PanelHeader, PanelTitle };
@@ -0,0 +1,7 @@
1
+ import { Popover as PopoverPrimitive } from 'radix-ui';
2
+ import * as React from 'react';
3
+ declare function Popover(props: React.ComponentProps<typeof PopoverPrimitive.Root>): React.JSX.Element;
4
+ declare function PopoverTrigger(props: React.ComponentProps<typeof PopoverPrimitive.Trigger>): React.JSX.Element;
5
+ declare function PopoverAnchor(props: React.ComponentProps<typeof PopoverPrimitive.Anchor>): React.JSX.Element;
6
+ declare function PopoverContent({ className, align, sideOffset, ...props }: React.ComponentProps<typeof PopoverPrimitive.Content>): React.JSX.Element;
7
+ export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Popover as PopoverPrimitive } from 'radix-ui';
3
+ import * as React from 'react';
4
+ import { cn } from '../lib/cn.js';
5
+ function Popover(props) {
6
+ return _jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
7
+ }
8
+ function PopoverTrigger(props) {
9
+ return _jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
10
+ }
11
+ function PopoverAnchor(props) {
12
+ return _jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
13
+ }
14
+ function PopoverContent({ className, align = 'center', sideOffset = 6, ...props }) {
15
+ return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { "data-slot": "popover-content", align: align, sideOffset: sideOffset, className: cn('debugger-pop bg-card text-card-foreground border-border z-50 w-72 rounded-lg border p-3 shadow-xl shadow-black/30 outline-none', className), ...props }) }));
16
+ }
17
+ export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
@@ -0,0 +1,7 @@
1
+ import type { ComponentProps } from 'react';
2
+ import { Group, Panel, Separator } from 'react-resizable-panels';
3
+ declare function ResizablePanelGroup({ className, ...props }: ComponentProps<typeof Group>): import("react").JSX.Element;
4
+ declare function ResizablePanel(props: ComponentProps<typeof Panel>): import("react").JSX.Element;
5
+ /** A hairline divider with a wider invisible hit area that brightens while hovered or dragged. */
6
+ declare function ResizableHandle({ className, ...props }: ComponentProps<typeof Separator>): import("react").JSX.Element;
7
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Group, Panel, Separator } from 'react-resizable-panels';
3
+ import { cn } from '../lib/cn.js';
4
+ function ResizablePanelGroup({ className, ...props }) {
5
+ return (_jsx(Group, { "data-slot": "resizable-panel-group", className: cn('flex size-full aria-[orientation=vertical]:flex-col', className), ...props }));
6
+ }
7
+ function ResizablePanel(props) {
8
+ return _jsx(Panel, { "data-slot": "resizable-panel", ...props });
9
+ }
10
+ /** A hairline divider with a wider invisible hit area that brightens while hovered or dragged. */
11
+ function ResizableHandle({ className, ...props }) {
12
+ return (_jsx(Separator, { "data-slot": "resizable-handle", className: cn('bg-border relative w-px shrink-0 outline-none after:absolute after:inset-y-0 after:left-1/2 after:w-2 after:-translate-x-1/2', 'data-[separator=active]:bg-ring data-[separator=focus]:bg-ring data-[separator=hover]:bg-ring/60 transition-colors duration-150', className), ...props }));
13
+ }
14
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
@@ -1,7 +1,8 @@
1
1
  import { ScrollArea as ScrollAreaPrimitive } from 'radix-ui';
2
2
  import type { ComponentProps, Ref, UIEventHandler } from 'react';
3
- declare function ScrollArea({ className, children, viewportRef, onViewportScroll, horizontal, ...props }: ComponentProps<typeof ScrollAreaPrimitive.Root> & {
3
+ declare function ScrollArea({ className, children, viewportRef, viewportClassName, onViewportScroll, horizontal, ...props }: ComponentProps<typeof ScrollAreaPrimitive.Root> & {
4
4
  viewportRef?: Ref<HTMLDivElement>;
5
+ viewportClassName?: string;
5
6
  onViewportScroll?: UIEventHandler<HTMLDivElement>;
6
7
  horizontal?: boolean;
7
8
  }): import("react").JSX.Element;
@@ -1,10 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ScrollArea as ScrollAreaPrimitive } from 'radix-ui';
3
3
  import { cn } from '../lib/cn.js';
4
- function ScrollArea({ className, children, viewportRef, onViewportScroll, horizontal = false, ...props }) {
5
- return (_jsxs(ScrollAreaPrimitive.Root, { "data-slot": "scroll-area", type: "always", className: cn('relative overflow-hidden', className), ...props, children: [_jsx(ScrollAreaPrimitive.Viewport, { ref: viewportRef, "data-slot": "scroll-area-viewport", className: "size-full [scrollbar-width:none] rounded-[inherit] [&::-webkit-scrollbar]:hidden", onScroll: onViewportScroll, children: children }), _jsx(ScrollBar, {}), horizontal ? _jsx(ScrollBar, { orientation: "horizontal" }) : null, _jsx(ScrollAreaPrimitive.Corner, {})] }));
4
+ function ScrollArea({ className, children, viewportRef, viewportClassName, onViewportScroll, horizontal = false, ...props }) {
5
+ return (_jsxs(ScrollAreaPrimitive.Root, { "data-slot": "scroll-area", type: "hover", scrollHideDelay: 400, className: cn('relative overflow-hidden', className), ...props, children: [_jsx(ScrollAreaPrimitive.Viewport, { ref: viewportRef, "data-slot": "scroll-area-viewport", className: cn(
6
+ // Radix wraps content in `display: table`, which lets long lines widen the viewport.
7
+ 'size-full overscroll-contain rounded-[inherit] outline-none [&>div]:block!', viewportClassName), onScroll: onViewportScroll, children: children }), _jsx(ScrollBar, {}), horizontal ? _jsx(ScrollBar, { orientation: "horizontal" }) : null, _jsx(ScrollAreaPrimitive.Corner, {})] }));
6
8
  }
7
9
  function ScrollBar({ className, orientation = 'vertical', ...props }) {
8
- return (_jsx(ScrollAreaPrimitive.ScrollAreaScrollbar, { "data-slot": "scroll-area-scrollbar", orientation: orientation, className: cn('flex touch-none p-px select-none', orientation === 'vertical' && 'h-full w-2 border-l border-l-transparent', orientation === 'horizontal' && 'h-2 flex-col border-t border-t-transparent', className), ...props, children: _jsx(ScrollAreaPrimitive.ScrollAreaThumb, { "data-slot": "scroll-area-thumb", className: "bg-border relative flex-1 rounded-full" }) }));
10
+ return (_jsx(ScrollAreaPrimitive.ScrollAreaScrollbar, { "data-slot": "scroll-area-scrollbar", orientation: orientation, className: cn('z-10 flex touch-none p-px transition-opacity duration-150 select-none data-[state=hidden]:opacity-0', orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent', orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent', className), ...props, children: _jsx(ScrollAreaPrimitive.ScrollAreaThumb, { "data-slot": "scroll-area-thumb", className: "bg-foreground/15 hover:bg-foreground/25 relative flex-1 rounded-full transition-colors" }) }));
9
11
  }
10
12
  export { ScrollArea, ScrollBar };
@@ -0,0 +1,10 @@
1
+ import { Select as SelectPrimitive } from 'radix-ui';
2
+ import * as React from 'react';
3
+ declare function Select(props: React.ComponentProps<typeof SelectPrimitive.Root>): React.JSX.Element;
4
+ declare function SelectValue(props: React.ComponentProps<typeof SelectPrimitive.Value>): React.JSX.Element;
5
+ declare function SelectTrigger({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Trigger>): React.JSX.Element;
6
+ declare function SelectContent({ className, children, position, sideOffset, ...props }: React.ComponentProps<typeof SelectPrimitive.Content>): React.JSX.Element;
7
+ declare function SelectItem({ className, children, description, ...props }: React.ComponentProps<typeof SelectPrimitive.Item> & {
8
+ description?: string;
9
+ }): React.JSX.Element;
10
+ export { Select, SelectContent, SelectItem, SelectTrigger, SelectValue };
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Check, ChevronDown } from 'lucide-react';
3
+ import { Select as SelectPrimitive } from 'radix-ui';
4
+ import * as React from 'react';
5
+ import { cn } from '../lib/cn.js';
6
+ function Select(props) {
7
+ return _jsx(SelectPrimitive.Root, { "data-slot": "select", ...props });
8
+ }
9
+ function SelectValue(props) {
10
+ return _jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
11
+ }
12
+ function SelectTrigger({ className, children, ...props }) {
13
+ return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", className: cn('text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring/50 data-[state=open]:bg-accent data-[state=open]:text-foreground flex h-7 items-center gap-1 rounded-md px-2 text-xs whitespace-nowrap transition-colors outline-none focus-visible:ring-[3px] disabled:opacity-50', className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDown, { className: "size-3 opacity-60" }) })] }));
14
+ }
15
+ function SelectContent({ className, children, position = 'popper', sideOffset = 6, ...props }) {
16
+ return (_jsx(SelectPrimitive.Portal, { children: _jsx(SelectPrimitive.Content, { "data-slot": "select-content", position: position, sideOffset: sideOffset, className: cn('debugger-pop bg-card text-card-foreground border-border z-50 min-w-40 overflow-hidden rounded-lg border p-1 shadow-xl shadow-black/30', className), ...props, children: _jsx(SelectPrimitive.Viewport, { children: children }) }) }));
17
+ }
18
+ function SelectItem({ className, children, description, ...props }) {
19
+ return (_jsxs(SelectPrimitive.Item, { "data-slot": "select-item", className: cn('focus:bg-accent relative flex cursor-default flex-col items-start rounded-sm py-1.5 pr-2 pl-7 text-xs outline-none select-none data-disabled:opacity-50', className), ...props, children: [_jsx("span", { className: "absolute top-2 left-2 flex size-3.5 items-center justify-center", children: _jsx(SelectPrimitive.ItemIndicator, { children: _jsx(Check, { className: "size-3.5" }) }) }), _jsx(SelectPrimitive.ItemText, { children: children }), description ? (_jsx("span", { className: "text-muted-foreground text-[11px]", children: description })) : null] }));
20
+ }
21
+ export { Select, SelectContent, SelectItem, SelectTrigger, SelectValue };
@@ -6,10 +6,10 @@ function Tabs({ className, ...props }) {
6
6
  return (_jsx(TabsPrimitive.Root, { "data-slot": "tabs", className: cn('flex flex-col gap-2', className), ...props }));
7
7
  }
8
8
  function TabsList({ className, ...props }) {
9
- return (_jsx(TabsPrimitive.List, { "data-slot": "tabs-list", className: cn('bg-secondary text-muted-foreground inline-flex h-8 w-fit items-center justify-center rounded-md p-0.5', className), ...props }));
9
+ return (_jsx(TabsPrimitive.List, { "data-slot": "tabs-list", className: cn('bg-secondary/70 text-muted-foreground inline-flex h-7 w-fit shrink-0 items-center justify-center rounded-md p-0.5', className), ...props }));
10
10
  }
11
11
  function TabsTrigger({ className, ...props }) {
12
- return (_jsx(TabsPrimitive.Trigger, { "data-slot": "tabs-trigger", className: cn('focus-visible:ring-ring/50 data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex h-7 items-center justify-center rounded-sm px-2.5 text-xs font-medium whitespace-nowrap transition-colors focus-visible:ring-[3px] focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50', className), ...props }));
12
+ return (_jsx(TabsPrimitive.Trigger, { "data-slot": "tabs-trigger", className: cn('focus-visible:ring-ring/50 hover:text-foreground data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex h-6 items-center justify-center rounded-sm px-2 text-[11px] font-medium whitespace-nowrap transition-colors focus-visible:ring-[3px] focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm', className), ...props }));
13
13
  }
14
14
  function TabsContent({ className, ...props }) {
15
15
  return (_jsx(TabsPrimitive.Content, { "data-slot": "tabs-content", className: cn('min-h-0 flex-1 outline-none', className), ...props }));
@@ -0,0 +1,3 @@
1
+ import * as React from 'react';
2
+ declare function Textarea({ className, ...props }: React.ComponentProps<'textarea'>): React.JSX.Element;
3
+ export { Textarea };
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { cn } from '../lib/cn.js';
4
+ function Textarea({ className, ...props }) {
5
+ return (_jsx("textarea", { "data-slot": "textarea", className: cn('border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-2.5 py-2 text-[13px] leading-relaxed transition-[border-color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', className), ...props }));
6
+ }
7
+ export { Textarea };
@@ -120,6 +120,11 @@ export declare const evaluateEffect: NoInfer<import("@swirls/looms/core").Effect
120
120
  readonly attempt: number;
121
121
  readonly deadlineAt: number | null;
122
122
  };
123
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
124
+ readonly type: "runtime.fork.elided";
125
+ readonly payload: {
126
+ readonly type: string;
127
+ };
123
128
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
124
129
  readonly type: "runtime.run.cancelled";
125
130
  readonly payload: {
@@ -131,6 +136,12 @@ export declare const evaluateEffect: NoInfer<import("@swirls/looms/core").Effect
131
136
  readonly output: Schema.Json;
132
137
  readonly error: string | null;
133
138
  };
139
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
140
+ readonly type: "runtime.run.forked";
141
+ readonly payload: {
142
+ readonly sourceRunId: string;
143
+ readonly sourceSeq: number;
144
+ };
134
145
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
135
146
  readonly type: "runtime.run.started";
136
147
  readonly payload: {
@@ -163,6 +174,7 @@ export declare const evaluateEffect: NoInfer<import("@swirls/looms/core").Effect
163
174
  readonly payload: {
164
175
  readonly threadId: string;
165
176
  readonly reason?: string | undefined;
177
+ readonly resumeSeq?: number | undefined;
166
178
  };
167
179
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
168
180
  readonly type: "runtime.thread.completed";
@@ -155,6 +155,11 @@ export declare function evaluator(options?: EvaluatorModuleOptions): import("@sw
155
155
  readonly attempt: number;
156
156
  readonly deadlineAt: number | null;
157
157
  };
158
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
159
+ readonly type: "runtime.fork.elided";
160
+ readonly payload: {
161
+ readonly type: string;
162
+ };
158
163
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
159
164
  readonly type: "runtime.run.cancelled";
160
165
  readonly payload: {
@@ -166,6 +171,12 @@ export declare function evaluator(options?: EvaluatorModuleOptions): import("@sw
166
171
  readonly output: import("effect/Schema").Json;
167
172
  readonly error: string | null;
168
173
  };
174
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
175
+ readonly type: "runtime.run.forked";
176
+ readonly payload: {
177
+ readonly sourceRunId: string;
178
+ readonly sourceSeq: number;
179
+ };
169
180
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
170
181
  readonly type: "runtime.run.started";
171
182
  readonly payload: {
@@ -198,6 +209,7 @@ export declare function evaluator(options?: EvaluatorModuleOptions): import("@sw
198
209
  readonly payload: {
199
210
  readonly threadId: string;
200
211
  readonly reason?: string | undefined;
212
+ readonly resumeSeq?: number | undefined;
201
213
  };
202
214
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
203
215
  readonly type: "runtime.thread.completed";
@@ -438,6 +450,11 @@ export declare function evaluator(options?: EvaluatorModuleOptions): import("@sw
438
450
  readonly attempt: number;
439
451
  readonly deadlineAt: number | null;
440
452
  };
453
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
454
+ readonly type: "runtime.fork.elided";
455
+ readonly payload: {
456
+ readonly type: string;
457
+ };
441
458
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
442
459
  readonly type: "runtime.run.cancelled";
443
460
  readonly payload: {
@@ -449,6 +466,12 @@ export declare function evaluator(options?: EvaluatorModuleOptions): import("@sw
449
466
  readonly output: import("effect/Schema").Json;
450
467
  readonly error: string | null;
451
468
  };
469
+ }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
470
+ readonly type: "runtime.run.forked";
471
+ readonly payload: {
472
+ readonly sourceRunId: string;
473
+ readonly sourceSeq: number;
474
+ };
452
475
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
453
476
  readonly type: "runtime.run.started";
454
477
  readonly payload: {
@@ -481,6 +504,7 @@ export declare function evaluator(options?: EvaluatorModuleOptions): import("@sw
481
504
  readonly payload: {
482
505
  readonly threadId: string;
483
506
  readonly reason?: string | undefined;
507
+ readonly resumeSeq?: number | undefined;
484
508
  };
485
509
  }) | (Omit<import("@swirls/looms/core").EventInput, "payload" | "type"> & {
486
510
  readonly type: "runtime.thread.completed";
@@ -1,6 +1,8 @@
1
- import type { EventEnvelope } from '@swirls/looms/core';
1
+ import { type EventEnvelope } from '@swirls/looms/core';
2
2
  import type { Projector } from './projector';
3
+ /** A run (`actorId === runId`) or one of its threads. Thread ids are unique within a run. */
3
4
  export interface ActorIndexRow {
5
+ runId: string;
4
6
  actorId: string;
5
7
  kind: string | null;
6
8
  status: string | null;
@@ -9,14 +11,15 @@ export interface ActorIndexRow {
9
11
  updatedAt: number;
10
12
  }
11
13
  export interface ReviewIndexRow {
14
+ runId: string;
12
15
  reviewId: string;
13
- actorId: string;
14
16
  status: string;
15
17
  title: string;
16
18
  updatedAt: number;
17
19
  }
18
20
  export type IndexOp = {
19
21
  type: 'upsertActor';
22
+ runId: string;
20
23
  actorId: string;
21
24
  kind: string | null;
22
25
  status: string | null;
@@ -25,32 +28,35 @@ export type IndexOp = {
25
28
  updatedAt: number;
26
29
  } | {
27
30
  type: 'setActorStatus';
31
+ runId: string;
28
32
  actorId: string;
29
33
  status: string;
30
34
  updatedAt: number;
31
35
  } | {
32
36
  type: 'upsertReview';
37
+ runId: string;
33
38
  reviewId: string;
34
- actorId: string;
35
39
  status: string;
36
40
  title: string;
37
41
  updatedAt: number;
38
42
  } | {
39
43
  type: 'setReviewStatus';
44
+ runId: string;
40
45
  reviewId: string;
41
46
  status: string;
42
47
  updatedAt: number;
43
48
  };
44
49
  export interface IndexBackend {
45
50
  applyOps: (ops: ReadonlyArray<IndexOp>) => Promise<void>;
46
- getActor: (actorId: string) => Promise<ActorIndexRow | null>;
47
- listReviews: (actorId?: string) => Promise<ReviewIndexRow[]>;
51
+ getActor: (runId: string, actorId: string) => Promise<ActorIndexRow | null>;
52
+ listReviews: (runId?: string) => Promise<ReviewIndexRow[]>;
48
53
  init?: () => Promise<void>;
49
54
  dispose?: () => Promise<void>;
50
55
  }
51
56
  export interface IndexProjector extends Projector {
52
- getActor: (actorId: string) => Promise<ActorIndexRow | null>;
53
- listReviews: (actorId?: string) => Promise<ReviewIndexRow[]>;
57
+ /** The run's row, or one of its threads when `actorId` is given. */
58
+ getActor: (runId: string, actorId?: string) => Promise<ActorIndexRow | null>;
59
+ listReviews: (runId?: string) => Promise<ReviewIndexRow[]>;
54
60
  }
55
61
  export declare function indexOpsFor(event: EventEnvelope): IndexOp[];
56
62
  export declare function createIndexProjector(name: string, backend: IndexBackend, version?: string): IndexProjector;
@@ -1,4 +1,5 @@
1
1
  import { Predicate } from 'effect';
2
+ import { completedRunStatus } from '@swirls/looms/core';
2
3
  function payloadObject(event) {
3
4
  if (!Predicate.isObject(event.payload)) {
4
5
  return {};
@@ -11,12 +12,15 @@ function readString(obj, key) {
11
12
  }
12
13
  export function indexOpsFor(event) {
13
14
  const payload = payloadObject(event);
15
+ const runId = event.runId;
16
+ const actorId = readString(payload, 'threadId') ?? event.threadId ?? runId;
14
17
  switch (event.type) {
15
18
  case 'runtime.run.started':
16
19
  return [
17
20
  {
18
21
  type: 'upsertActor',
19
- actorId: event.runId,
22
+ runId,
23
+ actorId: runId,
20
24
  kind: readString(payload, 'kind') ?? null,
21
25
  status: 'running',
22
26
  definitionName: readString(payload, 'definitionName') ?? null,
@@ -28,7 +32,8 @@ export function indexOpsFor(event) {
28
32
  return [
29
33
  {
30
34
  type: 'upsertActor',
31
- actorId: readString(payload, 'threadId') ?? event.threadId ?? event.runId,
35
+ runId,
36
+ actorId,
32
37
  kind: readString(payload, 'kind') ?? null,
33
38
  status: 'running',
34
39
  definitionName: readString(payload, 'definitionName') ?? null,
@@ -37,39 +42,28 @@ export function indexOpsFor(event) {
37
42
  },
38
43
  ];
39
44
  case 'runtime.run.completed':
40
- case 'runtime.thread.completed':
41
45
  return [
42
46
  {
43
47
  type: 'setActorStatus',
44
- actorId: readString(payload, 'threadId') ?? event.threadId ?? event.runId,
45
- status: 'completed',
48
+ runId,
49
+ actorId: runId,
50
+ status: completedRunStatus(event.payload),
46
51
  updatedAt: event.ts,
47
52
  },
48
53
  ];
54
+ case 'runtime.thread.completed':
55
+ return [{ type: 'setActorStatus', runId, actorId, status: 'completed', updatedAt: event.ts }];
49
56
  case 'runtime.thread.failed':
50
- return [
51
- {
52
- type: 'setActorStatus',
53
- actorId: readString(payload, 'threadId') ?? event.threadId ?? event.runId,
54
- status: 'failed',
55
- updatedAt: event.ts,
56
- },
57
- ];
57
+ return [{ type: 'setActorStatus', runId, actorId, status: 'failed', updatedAt: event.ts }];
58
+ case 'runtime.run.cancelled':
58
59
  case 'runtime.thread.cancelled':
59
- return [
60
- {
61
- type: 'setActorStatus',
62
- actorId: readString(payload, 'threadId') ?? event.threadId ?? event.runId,
63
- status: 'cancelled',
64
- updatedAt: event.ts,
65
- },
66
- ];
60
+ return [{ type: 'setActorStatus', runId, actorId, status: 'cancelled', updatedAt: event.ts }];
67
61
  case 'approval.requested':
68
62
  return [
69
63
  {
70
64
  type: 'upsertReview',
65
+ runId,
71
66
  reviewId: readString(payload, 'approvalId') ?? 'unknown',
72
- actorId: event.runId,
73
67
  status: 'pending',
74
68
  title: readString(payload, 'title') ?? 'Approval',
75
69
  updatedAt: event.ts,
@@ -79,8 +73,8 @@ export function indexOpsFor(event) {
79
73
  return [
80
74
  {
81
75
  type: 'upsertReview',
76
+ runId,
82
77
  reviewId: readString(payload, 'approvalId') ?? 'unknown',
83
- actorId: event.runId,
84
78
  status: payload.outcome === 'reject' ? 'rejected' : 'approved',
85
79
  title: 'Approval',
86
80
  updatedAt: event.ts,
@@ -90,6 +84,7 @@ export function indexOpsFor(event) {
90
84
  return [
91
85
  {
92
86
  type: 'setReviewStatus',
87
+ runId,
93
88
  reviewId: readString(payload, 'approvalId') ?? 'unknown',
94
89
  status: 'timed_out',
95
90
  updatedAt: event.ts,
@@ -99,7 +94,7 @@ export function indexOpsFor(event) {
99
94
  return [];
100
95
  }
101
96
  }
102
- export function createIndexProjector(name, backend, version = '1') {
97
+ export function createIndexProjector(name, backend, version = '2') {
103
98
  return {
104
99
  name,
105
100
  version,
@@ -109,7 +104,7 @@ export function createIndexProjector(name, backend, version = '1') {
109
104
  const ops = events.flatMap(indexOpsFor);
110
105
  return ops.length === 0 ? Promise.resolve() : backend.applyOps(ops);
111
106
  },
112
- getActor: (actorId) => backend.getActor(actorId),
113
- listReviews: (actorId) => backend.listReviews(actorId),
107
+ getActor: (runId, actorId) => backend.getActor(runId, actorId ?? runId),
108
+ listReviews: (runId) => backend.listReviews(runId),
114
109
  };
115
110
  }
@@ -1,9 +1,13 @@
1
1
  import { createIndexProjector, } from './index-model.js';
2
2
  import { runProjectorSync } from './projector.js';
3
+ function rowKey(runId, id) {
4
+ return `${runId}\0${id}`;
5
+ }
3
6
  function applyOp(actors, reviews, op) {
4
7
  switch (op.type) {
5
8
  case 'upsertActor':
6
- actors.set(op.actorId, {
9
+ actors.set(rowKey(op.runId, op.actorId), {
10
+ runId: op.runId,
7
11
  actorId: op.actorId,
8
12
  kind: op.kind,
9
13
  status: op.status,
@@ -13,8 +17,10 @@ function applyOp(actors, reviews, op) {
13
17
  });
14
18
  return;
15
19
  case 'setActorStatus': {
16
- const existing = actors.get(op.actorId);
17
- actors.set(op.actorId, {
20
+ const key = rowKey(op.runId, op.actorId);
21
+ const existing = actors.get(key);
22
+ actors.set(key, {
23
+ runId: op.runId,
18
24
  actorId: op.actorId,
19
25
  kind: existing?.kind ?? null,
20
26
  status: op.status,
@@ -25,10 +31,11 @@ function applyOp(actors, reviews, op) {
25
31
  return;
26
32
  }
27
33
  case 'upsertReview': {
28
- const existing = reviews.get(op.reviewId);
29
- reviews.set(op.reviewId, {
34
+ const key = rowKey(op.runId, op.reviewId);
35
+ const existing = reviews.get(key);
36
+ reviews.set(key, {
37
+ runId: op.runId,
30
38
  reviewId: op.reviewId,
31
- actorId: op.actorId,
32
39
  status: op.status,
33
40
  title: existing?.title ?? op.title,
34
41
  updatedAt: op.updatedAt,
@@ -36,9 +43,10 @@ function applyOp(actors, reviews, op) {
36
43
  return;
37
44
  }
38
45
  case 'setReviewStatus': {
39
- const existing = reviews.get(op.reviewId);
46
+ const key = rowKey(op.runId, op.reviewId);
47
+ const existing = reviews.get(key);
40
48
  if (existing) {
41
- reviews.set(op.reviewId, { ...existing, status: op.status, updatedAt: op.updatedAt });
49
+ reviews.set(key, { ...existing, status: op.status, updatedAt: op.updatedAt });
42
50
  }
43
51
  return;
44
52
  }
@@ -57,10 +65,10 @@ export function memory() {
57
65
  applyOp(actors, reviews, op);
58
66
  }
59
67
  }),
60
- getActor: (actorId) => runProjectorSync('memory', () => actors.get(actorId) ?? null),
61
- listReviews: (actorId) => runProjectorSync('memory', () => {
68
+ getActor: (runId, actorId) => runProjectorSync('memory', () => actors.get(rowKey(runId, actorId)) ?? null),
69
+ listReviews: (runId) => runProjectorSync('memory', () => {
62
70
  const rows = [...reviews.values()];
63
- return actorId ? rows.filter((row) => row.actorId === actorId) : rows;
71
+ return runId ? rows.filter((row) => row.runId === runId) : rows;
64
72
  }),
65
73
  dispose: () => runProjectorSync('memory', () => {
66
74
  actors.clear();