@swirls/looms 0.1.0 → 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.
- package/CHANGELOG.md +15 -0
- package/dist/actor/host.js +2 -1
- package/dist/agent/debugger/agent-chat.d.ts +2 -0
- package/dist/agent/debugger/agent-chat.js +176 -0
- package/dist/agent/debugger/index.d.ts +5 -0
- package/dist/agent/debugger/index.js +19 -0
- package/dist/agent/debugger/summarize.d.ts +2 -0
- package/dist/agent/debugger/summarize.js +51 -0
- package/dist/agent/debugger/token-usage.d.ts +3 -0
- package/dist/agent/debugger/token-usage.js +11 -0
- package/dist/agent/definitions.d.ts +3 -11
- package/dist/agent/definitions.js +5 -6
- package/dist/agent/signals.d.ts +2 -0
- package/dist/agent/signals.js +18 -16
- package/dist/agent/tool-schema.d.ts +1 -17
- package/dist/agent/tool-schema.js +3 -42
- package/dist/ai-vercel/index.d.ts +1 -1
- package/dist/ai-vercel/vercel-evaluator.d.ts +21 -8
- package/dist/ai-vercel/vercel-evaluator.js +7 -2
- package/dist/approval/debugger/approvals-view.d.ts +3 -0
- package/dist/approval/debugger/approvals-view.js +16 -0
- package/dist/approval/debugger/index.d.ts +4 -0
- package/dist/approval/debugger/index.js +11 -0
- package/dist/approval/debugger/summarize.d.ts +2 -0
- package/dist/approval/debugger/summarize.js +17 -0
- package/dist/client/client.d.ts +18 -0
- package/dist/client/client.js +3 -1
- package/dist/cloudflare/router.d.ts +1 -1
- package/dist/cloudflare/router.js +2 -2
- package/dist/core/compose.js +1 -0
- package/dist/core/debugger-host.d.ts +16 -0
- package/dist/core/debugger-host.js +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +1 -0
- package/dist/core/module.d.ts +2 -0
- package/dist/core/published.d.ts +43 -0
- package/dist/core/published.js +44 -0
- package/dist/core/schema.d.ts +3 -1
- package/dist/core/schema.js +38 -0
- package/dist/core/snapshot-store.d.ts +4 -0
- package/dist/core/snapshot-store.js +7 -0
- package/dist/core/sqlite-store.js +39 -0
- package/dist/debugger/app/assets/index-B3Ah8WAE.css +2 -0
- package/dist/debugger/app/assets/index-Qb371t_O.js +22 -0
- package/dist/debugger/app/assets/rolldown-runtime-CbXtAM7H.js +1 -0
- package/dist/debugger/app/assets/routes-CjtEHgPQ.js +47 -0
- package/dist/debugger/app/index.html +14 -0
- package/dist/debugger/components/composer.d.ts +17 -0
- package/dist/debugger/components/composer.js +25 -0
- package/dist/debugger/components/debugger-split.d.ts +2 -1
- package/dist/debugger/components/debugger-split.js +2 -2
- package/dist/debugger/components/event-inspector.d.ts +2 -1
- package/dist/debugger/components/event-inspector.js +25 -16
- package/dist/debugger/components/event-stream.d.ts +2 -1
- package/dist/debugger/components/event-stream.js +12 -71
- package/dist/debugger/components/follow-list.d.ts +19 -0
- package/dist/debugger/components/follow-list.js +96 -0
- package/dist/debugger/components/json-tree.d.ts +11 -0
- package/dist/debugger/components/json-tree.js +120 -0
- package/dist/debugger/components/json-view.js +2 -2
- package/dist/debugger/components/run-tree.js +53 -20
- package/dist/debugger/components/status-dot.d.ts +4 -0
- package/dist/debugger/components/status-dot.js +6 -2
- package/dist/debugger/context.d.ts +14 -0
- package/dist/debugger/context.js +17 -0
- package/dist/debugger/contracts.d.ts +7 -4
- package/dist/debugger/events/builtin-families.d.ts +3 -0
- package/dist/debugger/events/builtin-families.js +9 -0
- package/dist/debugger/events/catalog.d.ts +3 -4
- package/dist/debugger/events/catalog.js +27 -17
- package/dist/debugger/events/protocol-summarize.d.ts +1 -2
- package/dist/debugger/events/protocol-summarize.js +29 -37
- package/dist/debugger/index.d.ts +20 -6
- package/dist/debugger/index.js +19 -5
- package/dist/debugger/lib/cn.d.ts +1 -0
- package/dist/debugger/lib/cn.js +3 -0
- package/dist/debugger/lib/event-meta.d.ts +2 -3
- package/dist/debugger/lib/event-meta.js +6 -11
- package/dist/debugger/lib/json.d.ts +25 -0
- package/dist/debugger/lib/json.js +87 -0
- package/dist/debugger/lib/payload.d.ts +7 -0
- package/dist/debugger/lib/payload.js +11 -0
- package/dist/debugger/lib/time.d.ts +3 -0
- package/dist/debugger/lib/time.js +24 -0
- package/dist/debugger/plugin.d.ts +36 -0
- package/dist/debugger/plugin.js +14 -0
- package/dist/debugger/server/index.d.ts +14 -0
- package/dist/debugger/server/index.js +114 -0
- package/dist/debugger/shell/debugger-shell.d.ts +15 -0
- package/dist/debugger/shell/debugger-shell.js +43 -0
- package/dist/debugger/shell/definition-key.d.ts +3 -0
- package/dist/debugger/shell/definition-key.js +4 -0
- package/dist/debugger/shell/events-pane.d.ts +12 -0
- package/dist/debugger/shell/events-pane.js +25 -0
- package/dist/debugger/shell/projections-panel.d.ts +4 -0
- package/dist/debugger/shell/projections-panel.js +59 -0
- package/dist/debugger/shell/run-controls.d.ts +4 -0
- package/dist/debugger/shell/run-controls.js +72 -0
- package/dist/debugger/shell/run-search.d.ts +6 -0
- package/dist/debugger/shell/run-search.js +102 -0
- package/dist/debugger/shell/run-type-menu.d.ts +6 -0
- package/dist/debugger/shell/run-type-menu.js +11 -0
- package/dist/debugger/shell/schema-form.d.ts +31 -0
- package/dist/debugger/shell/schema-form.js +117 -0
- package/dist/debugger/shell/start-form.d.ts +3 -0
- package/dist/debugger/shell/start-form.js +75 -0
- package/dist/debugger/shell/use-start-run.d.ts +14 -0
- package/dist/debugger/shell/use-start-run.js +32 -0
- package/dist/debugger/shell/workspace.d.ts +6 -0
- package/dist/debugger/shell/workspace.js +15 -0
- package/dist/debugger/styles.css +111 -27
- package/dist/debugger/ui/button.d.ts +24 -0
- package/dist/debugger/ui/button.js +24 -0
- package/dist/debugger/ui/command.d.ts +9 -0
- package/dist/debugger/ui/command.js +24 -0
- package/dist/debugger/ui/dropdown-menu.d.ts +13 -0
- package/dist/debugger/ui/dropdown-menu.js +37 -0
- package/dist/debugger/ui/panel.d.ts +14 -0
- package/dist/debugger/ui/panel.js +16 -0
- package/dist/debugger/ui/popover.d.ts +7 -0
- package/dist/debugger/ui/popover.js +17 -0
- package/dist/debugger/ui/resizable.d.ts +7 -0
- package/dist/debugger/ui/resizable.js +14 -0
- package/dist/debugger/ui/scroll-area.d.ts +2 -1
- package/dist/debugger/ui/scroll-area.js +5 -3
- package/dist/debugger/ui/select.d.ts +10 -0
- package/dist/debugger/ui/select.js +21 -0
- package/dist/debugger/ui/tabs.js +2 -2
- package/dist/debugger/ui/textarea.d.ts +3 -0
- package/dist/debugger/ui/textarea.js +7 -0
- package/dist/react/store.d.ts +1 -1
- package/dist/react/store.js +1 -1
- package/dist/runtime/looms.d.ts +9 -1
- package/dist/runtime/looms.js +4 -2
- package/dist/runtime/repository.js +16 -1
- package/dist/runtime/runtime.js +16 -1
- package/dist/runtime/server/auth.d.ts +1 -0
- package/dist/runtime/server/auth.js +5 -0
- package/dist/runtime/server/debugger-host.d.ts +11 -0
- package/dist/runtime/server/debugger-host.js +32 -0
- package/dist/runtime/server/fetch-handler.d.ts +5 -1
- package/dist/runtime/server/fetch-handler.js +24 -13
- package/dist/runtime/server/http.d.ts +1 -0
- package/dist/runtime/server/http.js +4 -0
- package/dist/runtime/server/routes/definitions.d.ts +3 -0
- package/dist/runtime/server/routes/definitions.js +20 -0
- package/dist/runtime/server/routes/runs.js +8 -1
- package/dist/runtime/server.d.ts +3 -1
- package/dist/runtime/server.js +3 -1
- package/dist/runtime/types.d.ts +3 -1
- package/dist/s2/snapshot-store.js +43 -1
- package/dist/workflow/debugger/index.d.ts +4 -0
- package/dist/workflow/debugger/index.js +11 -0
- package/dist/workflow/debugger/nodes-view.d.ts +3 -0
- package/dist/workflow/debugger/nodes-view.js +13 -0
- package/dist/workflow/debugger/summarize.d.ts +2 -0
- package/dist/workflow/debugger/summarize.js +30 -0
- package/package.json +20 -1
- package/dist/debugger/events/domain-summarize.d.ts +0 -3
- package/dist/debugger/events/domain-summarize.js +0 -107
- package/dist/debugger/events/family.d.ts +0 -8
- package/dist/debugger/events/family.js +0 -44
|
@@ -1,24 +1,54 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
3
|
+
import { ChevronRight } from 'lucide-react';
|
|
4
|
+
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
4
5
|
import { cn, shortId } from '../lib/cn.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import { PanelHeader, PanelTitle } from '../ui/panel.js';
|
|
7
|
+
import { ScrollArea } from '../ui/scroll-area.js';
|
|
8
|
+
import { StatusBadge, StatusDot } from './status-dot.js';
|
|
9
|
+
const ROW_HEIGHT = 28;
|
|
10
|
+
const INDENT = 14;
|
|
11
|
+
function flatten(root, collapsed) {
|
|
12
|
+
const rows = [];
|
|
13
|
+
if (!root) {
|
|
14
|
+
return rows;
|
|
15
|
+
}
|
|
16
|
+
const stack = [{ node: root, depth: 0 }];
|
|
17
|
+
while (stack.length > 0) {
|
|
18
|
+
const next = stack.pop();
|
|
19
|
+
if (!next) {
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
rows.push(next);
|
|
23
|
+
if (!collapsed.has(next.node.threadId)) {
|
|
24
|
+
for (let index = next.node.children.length - 1; index >= 0; index--) {
|
|
25
|
+
const child = next.node.children[index];
|
|
26
|
+
if (child) {
|
|
27
|
+
stack.push({ node: child, depth: next.depth + 1 });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return rows;
|
|
33
|
+
}
|
|
34
|
+
function NodeRow({ row, selected, count, collapsed, onToggle, onSelect, }) {
|
|
35
|
+
const { node, depth } = row;
|
|
8
36
|
const hasChildren = node.children.length > 0;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const handleToggle = useCallback(() => {
|
|
12
|
-
onToggle(node.threadId);
|
|
13
|
-
}, [onToggle, node.threadId]);
|
|
14
|
-
const handleSelect = useCallback(() => {
|
|
15
|
-
onSelect(node.threadId);
|
|
16
|
-
}, [onSelect, node.threadId]);
|
|
17
|
-
return (_jsxs("li", { className: "relative", children: [_jsxs("div", { className: cn('flex items-center gap-1 rounded-md py-0.5 pr-1 text-xs transition-colors', selected === node.threadId ? 'bg-accent font-medium' : 'hover:bg-accent/50'), style: { paddingLeft: 8 + depth * 14 }, children: [hasChildren ? (_jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground size-4 shrink-0", onClick: handleToggle, "aria-label": isCollapsed ? 'Expand thread' : 'Collapse thread', children: isCollapsed ? _jsx(ChevronRight, { className: "size-3" }) : _jsx(ChevronDown, { className: "size-3" }) })) : (_jsx("span", { className: "size-4 shrink-0" })), _jsxs("button", { type: "button", className: "flex min-w-0 flex-1 items-center gap-1.5 text-left", onClick: handleSelect, children: [_jsx(StatusDot, { status: node.status }), _jsxs("span", { className: "truncate", children: [_jsx("span", { className: "text-foreground font-medium", children: node.definitionName }), _jsxs("span", { className: "text-muted-foreground ml-1 font-mono text-[10px]", children: ["(", node.kind, ")"] })] }), _jsx("span", { className: cn('shrink-0 text-[10px]', statusClass(node.status)), children: node.status }), _jsx("span", { className: "text-muted-foreground ml-auto shrink-0 font-mono text-[10px]", children: count })] })] }), hasChildren && !isCollapsed ? (_jsx("ul", { className: "relative", children: node.children.map((child) => (_jsx(NodeRow, { node: child, depth: depth + 1, selected: selected, counts: counts, collapsed: collapsed, onToggle: onToggle, onSelect: onSelect }, child.threadId))) })) : null] }));
|
|
18
|
-
});
|
|
37
|
+
return (_jsxs("div", { className: cn('group/row relative flex h-7 items-center rounded-md pr-2 text-xs', selected ? 'bg-accent text-foreground' : 'hover:bg-accent/50'), style: { paddingLeft: 4 + depth * INDENT }, title: `${node.definitionName} · ${node.kind} · ${node.status}`, children: [Array.from({ length: depth }, (_, level) => (_jsx("span", { "aria-hidden": true, className: "bg-border absolute inset-y-0 w-px", style: { left: 12 + level * INDENT } }, level))), hasChildren ? (_jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground hover:bg-background/40 flex size-4 shrink-0 items-center justify-center rounded-sm", onClick: () => onToggle(node.threadId), "aria-label": collapsed ? 'Expand thread' : 'Collapse thread', "aria-expanded": !collapsed, children: _jsx(ChevronRight, { className: cn('ease-snappy size-3 transition-transform duration-100', !collapsed && 'rotate-90') }) })) : (_jsx("span", { className: "size-4 shrink-0" })), _jsxs("button", { type: "button", className: "flex h-full min-w-0 flex-1 items-center gap-2 pl-1 text-left", onClick: () => onSelect(node.threadId), children: [_jsx(StatusDot, { status: node.status }), _jsxs("span", { className: "min-w-0 truncate", children: [_jsx("span", { className: "font-medium", children: node.definitionName }), _jsx("span", { className: "text-muted-foreground ml-1.5 font-mono text-[10px]", children: node.kind })] }), _jsx("span", { className: "text-muted-foreground ml-auto shrink-0 font-mono text-[10px] tabular-nums", children: count })] })] }));
|
|
38
|
+
}
|
|
19
39
|
export function RunTree({ runId, runStatus, tree, eventCounts, totalEventCount, selectedThread, onSelectThread, formatRunLabel = shortId, showHeading = true, }) {
|
|
20
|
-
const [collapsed, setCollapsed] = useState(new Set());
|
|
40
|
+
const [collapsed, setCollapsed] = useState(() => new Set());
|
|
21
41
|
const runCount = totalEventCount ?? eventCounts.get('run') ?? 0;
|
|
42
|
+
const rows = useMemo(() => flatten(tree.root, collapsed), [tree.root, collapsed]);
|
|
43
|
+
const parentRef = useRef(null);
|
|
44
|
+
const virtualizer = useVirtualizer({
|
|
45
|
+
count: rows.length,
|
|
46
|
+
getScrollElement: () => parentRef.current,
|
|
47
|
+
estimateSize: () => ROW_HEIGHT,
|
|
48
|
+
overscan: 12,
|
|
49
|
+
getItemKey: (index) => rows[index]?.node.threadId ?? index,
|
|
50
|
+
useFlushSync: false,
|
|
51
|
+
});
|
|
22
52
|
const toggle = useCallback((id) => {
|
|
23
53
|
setCollapsed((prev) => {
|
|
24
54
|
const next = new Set(prev);
|
|
@@ -31,8 +61,11 @@ export function RunTree({ runId, runStatus, tree, eventCounts, totalEventCount,
|
|
|
31
61
|
return next;
|
|
32
62
|
});
|
|
33
63
|
}, []);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
64
|
+
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [showHeading ? (_jsxs(PanelHeader, { children: [_jsx(PanelTitle, { children: "Run tree" }), _jsx(StatusBadge, { status: runStatus, className: "ml-auto" })] })) : null, _jsx("div", { className: "px-2 pt-2", children: _jsxs("button", { type: "button", onClick: () => onSelectThread(undefined), className: cn('flex h-7 w-full items-center gap-2 rounded-md px-2 text-left text-xs', !selectedThread ? 'bg-accent text-foreground' : 'hover:bg-accent/50'), children: [_jsx("span", { className: "text-muted-foreground", children: "All threads" }), _jsx("span", { className: "text-muted-foreground/70 truncate font-mono text-[10px]", children: formatRunLabel(runId) }), _jsx("span", { className: "text-muted-foreground ml-auto font-mono text-[10px] tabular-nums", children: runCount })] }) }), rows.length === 0 ? (_jsx("p", { className: "text-muted-foreground px-4 py-2 text-xs", children: "Waiting for threads\u2026" })) : (_jsx(ScrollArea, { viewportRef: parentRef, className: "min-h-0 flex-1", children: _jsx("div", { className: "relative mx-2 mb-2", style: { height: virtualizer.getTotalSize() }, children: virtualizer.getVirtualItems().map((item) => {
|
|
65
|
+
const row = rows[item.index];
|
|
66
|
+
if (!row) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return (_jsx("div", { className: "absolute top-0 left-0 w-full", style: { transform: `translateY(${item.start}px)`, height: ROW_HEIGHT }, children: _jsx(NodeRow, { row: row, selected: selectedThread === row.node.threadId, count: eventCounts.get(row.node.threadId) ?? 0, collapsed: collapsed.has(row.node.threadId), onToggle: toggle, onSelect: onSelectThread }) }, item.key));
|
|
70
|
+
}) }) }))] }));
|
|
38
71
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../lib/cn.js';
|
|
3
|
+
import { statusClass, statusDotClass } from '../lib/status.js';
|
|
3
4
|
export function StatusDot({ status }) {
|
|
4
5
|
return _jsx("span", { className: statusDotClass(status), "aria-hidden": true });
|
|
5
6
|
}
|
|
7
|
+
export function StatusBadge({ status, className }) {
|
|
8
|
+
return (_jsxs("span", { className: cn('inline-flex h-5 shrink-0 items-center gap-1.5 rounded-full bg-current/10 px-2 text-[11px] font-medium', statusClass(status), className), children: [_jsx(StatusDot, { status: status }), status] }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type LoomsClient } from '@swirls/looms/client';
|
|
3
|
+
import type { DebuggerPlugin } from './plugin';
|
|
4
|
+
export interface DebuggerContextValue {
|
|
5
|
+
readonly client: LoomsClient;
|
|
6
|
+
readonly plugins: readonly DebuggerPlugin[];
|
|
7
|
+
}
|
|
8
|
+
/** Supplies one Looms host to both the API client and the run stores. */
|
|
9
|
+
export declare function DebuggerProvider({ endpoint, plugins, children, }: {
|
|
10
|
+
endpoint?: string;
|
|
11
|
+
plugins: readonly DebuggerPlugin[];
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
14
|
+
export declare function useDebugger(): DebuggerContextValue;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
3
|
+
import { createLoomsClient } from '@swirls/looms/client';
|
|
4
|
+
import { LoomsProvider } from '@swirls/looms/react';
|
|
5
|
+
const DebuggerContext = createContext(null);
|
|
6
|
+
/** Supplies one Looms host to both the API client and the run stores. */
|
|
7
|
+
export function DebuggerProvider({ endpoint = '', plugins, children, }) {
|
|
8
|
+
const value = useMemo(() => ({ client: createLoomsClient({ baseUrl: endpoint }), plugins }), [endpoint, plugins]);
|
|
9
|
+
return (_jsx(LoomsProvider, { endpoint: endpoint, children: _jsx(DebuggerContext.Provider, { value: value, children: children }) }));
|
|
10
|
+
}
|
|
11
|
+
export function useDebugger() {
|
|
12
|
+
const value = useContext(DebuggerContext);
|
|
13
|
+
if (!value) {
|
|
14
|
+
throw new Error('useDebugger must be used within DebuggerProvider');
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { EventEnvelope, JsonValue, ReplayStep, ThreadTree } from '@swirls/looms/core';
|
|
2
|
-
|
|
2
|
+
export type EventSummary = {
|
|
3
|
+
title: string;
|
|
4
|
+
detail?: string;
|
|
5
|
+
};
|
|
3
6
|
export type DebuggerEvent<TType extends string = string> = Pick<EventEnvelope<TType>, 'id' | 'runId' | 'seq' | 'ts' | 'type' | 'payload' | 'threadId' | 'causationId' | 'ephemeral'> & Partial<Pick<EventEnvelope<TType>, 'parentThreadId' | 'correlationId' | 'effectId' | 'origin'>>;
|
|
4
7
|
export type EventStreamCatalog<TEvent extends DebuggerEvent = DebuggerEvent> = {
|
|
5
8
|
families: readonly string[];
|
|
6
9
|
familyOf: (type: string) => string;
|
|
7
|
-
|
|
10
|
+
familyColor: (family: string) => string;
|
|
8
11
|
summarize: (event: TEvent) => EventSummary;
|
|
9
|
-
searchText
|
|
12
|
+
searchText: (event: TEvent) => string;
|
|
10
13
|
};
|
|
11
14
|
export type ReplayLoader = (input: {
|
|
12
15
|
runId: string;
|
|
@@ -19,4 +22,4 @@ export type RunTreeModel = {
|
|
|
19
22
|
eventCounts: Map<string, number>;
|
|
20
23
|
totalEventCount?: number;
|
|
21
24
|
};
|
|
22
|
-
export type {
|
|
25
|
+
export type { JsonValue, ReplayStep, ThreadTree };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { DebuggerEvent, EventStreamCatalog } from '../contracts';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function createDefaultCatalog<TEvent extends DebuggerEvent = DebuggerEvent>(): EventStreamCatalog<TEvent>;
|
|
2
|
+
import type { DebuggerPlugin } from '../plugin';
|
|
3
|
+
/** Each event type belongs to the family view with the longest matching prefix. */
|
|
4
|
+
export declare function createEventCatalog<TEvent extends DebuggerEvent = DebuggerEvent>(plugins?: readonly DebuggerPlugin[]): EventStreamCatalog<TEvent>;
|
|
6
5
|
export declare const defaultEventCatalog: EventStreamCatalog;
|
|
@@ -1,27 +1,37 @@
|
|
|
1
1
|
import { compactJson } from '../lib/cn.js';
|
|
2
|
-
import {
|
|
3
|
-
import { DEFAULT_FAMILIES, familyClass, familyFromPrefix } from './family.js';
|
|
2
|
+
import { builtinFamilies, runtimeFamily } from './builtin-families.js';
|
|
4
3
|
import { summarizeProtocolEvent } from './protocol-summarize.js';
|
|
5
|
-
|
|
6
|
-
return
|
|
7
|
-
summarizeDomainEvent(event) ?? {
|
|
8
|
-
title: event.type,
|
|
9
|
-
detail: compactJson(event.payload),
|
|
10
|
-
});
|
|
4
|
+
function prefixOf(view) {
|
|
5
|
+
return view.prefix ?? `${view.family}.`;
|
|
11
6
|
}
|
|
12
|
-
|
|
13
|
-
const summary = summarize(event);
|
|
7
|
+
function searchText(event, summary) {
|
|
14
8
|
return [event.type, event.threadId ?? '', summary.title, summary.detail ?? '', event.id]
|
|
15
9
|
.join(' ')
|
|
16
10
|
.toLowerCase();
|
|
17
11
|
}
|
|
18
|
-
|
|
12
|
+
/** Each event type belongs to the family view with the longest matching prefix. */
|
|
13
|
+
export function createEventCatalog(plugins = []) {
|
|
14
|
+
const views = [...plugins.flatMap((plugin) => plugin.families ?? []), ...builtinFamilies];
|
|
15
|
+
// ES2022 has no Array#toSorted. `views` is a fresh array.
|
|
16
|
+
// oxlint-disable-next-line unicorn/no-array-sort
|
|
17
|
+
const byPrefix = views.sort((left, right) => prefixOf(right).length - prefixOf(left).length);
|
|
18
|
+
const colors = new Map(views.map((view) => [view.family, view.color]));
|
|
19
|
+
function viewOf(type) {
|
|
20
|
+
return byPrefix.find((view) => type.startsWith(prefixOf(view))) ?? runtimeFamily;
|
|
21
|
+
}
|
|
22
|
+
function summarize(event) {
|
|
23
|
+
return (summarizeProtocolEvent(event) ??
|
|
24
|
+
viewOf(event.type).summarize?.(event) ?? {
|
|
25
|
+
title: event.type,
|
|
26
|
+
detail: compactJson(event.payload),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
19
29
|
return {
|
|
20
|
-
families:
|
|
21
|
-
familyOf:
|
|
22
|
-
|
|
23
|
-
summarize
|
|
24
|
-
searchText: (event) => searchText(event),
|
|
30
|
+
families: [...new Set(views.map((view) => view.family))],
|
|
31
|
+
familyOf: (type) => viewOf(type).family,
|
|
32
|
+
familyColor: (family) => colors.get(family) ?? runtimeFamily.color,
|
|
33
|
+
summarize,
|
|
34
|
+
searchText: (event) => searchText(event, summarize(event)),
|
|
25
35
|
};
|
|
26
36
|
}
|
|
27
|
-
export const defaultEventCatalog =
|
|
37
|
+
export const defaultEventCatalog = createEventCatalog();
|
|
@@ -1,45 +1,37 @@
|
|
|
1
|
-
import { isJsonNumber,
|
|
1
|
+
import { isJsonNumber, isJsonString, isProtocolType } from '@swirls/looms/core';
|
|
2
2
|
import { compactJson } from '../lib/cn.js';
|
|
3
|
-
|
|
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
|
-
}
|
|
3
|
+
import { jsonFields, jsonNumberText, jsonText } from '../lib/payload.js';
|
|
12
4
|
export function summarizeProtocolEvent(event) {
|
|
13
5
|
if (!isProtocolType(event.type)) {
|
|
14
6
|
return undefined;
|
|
15
7
|
}
|
|
16
|
-
const payload =
|
|
8
|
+
const payload = jsonFields(event.payload);
|
|
17
9
|
switch (event.type) {
|
|
18
10
|
case 'runtime.run.started':
|
|
19
11
|
return {
|
|
20
12
|
title: 'run started',
|
|
21
|
-
detail: `${
|
|
13
|
+
detail: `${jsonText(payload.kind) ?? 'run'}:${jsonText(payload.definitionName) ?? 'unknown'}`,
|
|
22
14
|
};
|
|
23
15
|
case 'runtime.run.completed':
|
|
24
16
|
return {
|
|
25
|
-
title:
|
|
26
|
-
detail:
|
|
17
|
+
title: jsonText(payload.error) ? 'run failed' : 'run completed',
|
|
18
|
+
detail: jsonText(payload.error) ?? compactJson(payload.output ?? null),
|
|
27
19
|
};
|
|
28
20
|
case 'runtime.run.cancelled':
|
|
29
|
-
return { title: 'run cancelled', detail:
|
|
21
|
+
return { title: 'run cancelled', detail: jsonText(payload.reason) };
|
|
30
22
|
case 'runtime.thread.started':
|
|
31
23
|
return {
|
|
32
24
|
title: 'thread started',
|
|
33
|
-
detail: `${
|
|
25
|
+
detail: `${jsonText(payload.kind) ?? 'thread'}:${jsonText(payload.definitionName) ?? 'unknown'}`,
|
|
34
26
|
};
|
|
35
27
|
case 'runtime.thread.completed':
|
|
36
28
|
return { title: 'thread completed', detail: compactJson(payload.output ?? null) };
|
|
37
29
|
case 'runtime.thread.failed':
|
|
38
|
-
return { title: 'thread failed', detail:
|
|
30
|
+
return { title: 'thread failed', detail: jsonText(payload.error) };
|
|
39
31
|
case 'runtime.thread.cancelled':
|
|
40
|
-
return { title: 'thread cancelled', detail:
|
|
32
|
+
return { title: 'thread cancelled', detail: jsonText(payload.reason) };
|
|
41
33
|
case 'runtime.wait.registered': {
|
|
42
|
-
const on =
|
|
34
|
+
const on = jsonFields(payload.on ?? null);
|
|
43
35
|
const type = on.type;
|
|
44
36
|
const detail = isJsonString(type)
|
|
45
37
|
? type
|
|
@@ -51,46 +43,46 @@ export function summarizeProtocolEvent(event) {
|
|
|
51
43
|
return { title: 'wait registered', detail };
|
|
52
44
|
}
|
|
53
45
|
case 'runtime.wait.satisfied': {
|
|
54
|
-
const waited =
|
|
55
|
-
return { title: 'wait satisfied', detail:
|
|
46
|
+
const waited = jsonFields(payload.event ?? null);
|
|
47
|
+
return { title: 'wait satisfied', detail: jsonText(waited.type) };
|
|
56
48
|
}
|
|
57
49
|
case 'runtime.timer.set':
|
|
58
|
-
return { title: 'timer set', detail:
|
|
50
|
+
return { title: 'timer set', detail: jsonNumberText(payload.wakeAt) };
|
|
59
51
|
case 'runtime.timer.fired':
|
|
60
52
|
return { title: 'timer fired' };
|
|
61
53
|
case 'runtime.effect.failed':
|
|
62
|
-
return { title: 'effect failed', detail:
|
|
54
|
+
return { title: 'effect failed', detail: jsonText(payload.error) };
|
|
63
55
|
case 'runtime.effect.attempt.started':
|
|
64
|
-
return { title: 'effect attempt started', detail:
|
|
56
|
+
return { title: 'effect attempt started', detail: jsonNumberText(payload.attempt) };
|
|
65
57
|
case 'runtime.effect.queued':
|
|
66
|
-
return { title: 'effect queued', detail:
|
|
58
|
+
return { title: 'effect queued', detail: jsonNumberText(payload.attempt) };
|
|
67
59
|
case 'runtime.effect.dispatched':
|
|
68
|
-
return { title: 'effect dispatched', detail:
|
|
60
|
+
return { title: 'effect dispatched', detail: jsonNumberText(payload.attempt) };
|
|
69
61
|
case 'runtime.effect.worker.started':
|
|
70
|
-
return { title: 'worker started effect', detail:
|
|
62
|
+
return { title: 'worker started effect', detail: jsonNumberText(payload.attempt) };
|
|
71
63
|
case 'runtime.effect.heartbeat':
|
|
72
|
-
return { title: 'effect heartbeat', detail:
|
|
64
|
+
return { title: 'effect heartbeat', detail: jsonNumberText(payload.attempt) };
|
|
73
65
|
case 'runtime.effect.completed':
|
|
74
|
-
return { title: 'effect completed', detail:
|
|
66
|
+
return { title: 'effect completed', detail: jsonNumberText(payload.attempt) };
|
|
75
67
|
case 'runtime.effect.cancel.requested':
|
|
76
|
-
return { title: 'effect cancellation requested', detail:
|
|
68
|
+
return { title: 'effect cancellation requested', detail: jsonNumberText(payload.attempt) };
|
|
77
69
|
case 'runtime.effect.cancelled':
|
|
78
|
-
return { title: 'effect cancelled', detail:
|
|
70
|
+
return { title: 'effect cancelled', detail: jsonNumberText(payload.attempt) };
|
|
79
71
|
case 'runtime.effect.timed_out':
|
|
80
|
-
return { title: 'effect timed out', detail:
|
|
72
|
+
return { title: 'effect timed out', detail: jsonText(payload.timeout) };
|
|
81
73
|
case 'runtime.effect.ambiguous':
|
|
82
|
-
return { title: 'effect outcome ambiguous', detail:
|
|
74
|
+
return { title: 'effect outcome ambiguous', detail: jsonText(payload.error) };
|
|
83
75
|
case 'runtime.effect.retry.scheduled':
|
|
84
|
-
return { title: 'effect retry scheduled', detail:
|
|
76
|
+
return { title: 'effect retry scheduled', detail: jsonText(payload.error) };
|
|
85
77
|
case 'runtime.snapshot.taken':
|
|
86
|
-
return { title: 'snapshot', detail: `seq ${
|
|
78
|
+
return { title: 'snapshot', detail: `seq ${jsonNumberText(payload.seq) ?? ''}` };
|
|
87
79
|
case 'runtime.signal.received':
|
|
88
80
|
return { title: 'signal', detail: compactJson(event.payload) };
|
|
89
81
|
case 'runtime.thread.cancel.requested':
|
|
90
|
-
return { title: 'thread cancellation requested', detail:
|
|
82
|
+
return { title: 'thread cancellation requested', detail: jsonText(payload.threadId) };
|
|
91
83
|
default: {
|
|
92
84
|
const exhaustiveType = event.type;
|
|
93
|
-
return { title: 'event', detail: compactJson(
|
|
85
|
+
return { title: 'event', detail: compactJson(jsonFields(exhaustiveType)) };
|
|
94
86
|
}
|
|
95
87
|
}
|
|
96
88
|
}
|
package/dist/debugger/index.d.ts
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
-
export type { DebuggerEvent,
|
|
2
|
-
export {
|
|
1
|
+
export type { DebuggerEvent, EventStreamCatalog, EventSummary, ReplayLoader, ReplayStep, RunTreeModel, ThreadTree, } from './contracts';
|
|
2
|
+
export { createEventCatalog, defaultEventCatalog } from './events/catalog';
|
|
3
3
|
export { summarizeProtocolEvent } from './events/protocol-summarize';
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
4
|
+
export { DebuggerProvider, useDebugger, type DebuggerContextValue } from './context';
|
|
5
|
+
export { projectionFor, workspaceFor, type DebuggerPlugin, type EventFamilyView, type ProjectionView, type WorkspaceContext, type WorkspaceView, } from './plugin';
|
|
6
|
+
export { DebuggerShell, type DebuggerSelection } from './shell/debugger-shell';
|
|
7
|
+
export { StartForm } from './shell/start-form';
|
|
8
|
+
export { useStartRun, type StartRun } from './shell/use-start-run';
|
|
9
|
+
export { formInput, inputForm, messageInput, type FormField, type FormValues, type InputForm, } from './shell/schema-form';
|
|
10
|
+
export { cn, compactJson, errorMessage, shortId } from './lib/cn';
|
|
11
|
+
export { jsonFields, jsonNumberText, jsonText } from './lib/payload';
|
|
7
12
|
export { statusClass, statusDotClass, type StatusKind } from './lib/status';
|
|
8
13
|
export { countEventsByThread, runStatusFromEvents, startedAtFromEvents } from './lib/event-counts';
|
|
9
14
|
export { projectRunView, type ProjectedRunView } from './lib/project-run';
|
|
10
|
-
export { StatusDot } from './components/status-dot';
|
|
15
|
+
export { StatusBadge, StatusDot } from './components/status-dot';
|
|
11
16
|
export { JsonView } from './components/json-view';
|
|
17
|
+
export { JsonTree } from './components/json-tree';
|
|
18
|
+
export { parseStructuredJson } from './lib/json';
|
|
19
|
+
export { FollowList } from './components/follow-list';
|
|
20
|
+
export { Composer } from './components/composer';
|
|
12
21
|
export { RunTree } from './components/run-tree';
|
|
13
22
|
export { EventStream } from './components/event-stream';
|
|
14
23
|
export { EventInspector } from './components/event-inspector';
|
|
15
24
|
export { DebuggerSplit } from './components/debugger-split';
|
|
25
|
+
export { Button, type ButtonSize, type ButtonVariant } from './ui/button';
|
|
16
26
|
export { Checkbox } from './ui/checkbox';
|
|
27
|
+
export { Input } from './ui/input';
|
|
28
|
+
export { Textarea } from './ui/textarea';
|
|
29
|
+
export { EmptyState, Kbd, PanelHeader, PanelTitle } from './ui/panel';
|
|
30
|
+
export { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
|
|
17
31
|
export { ScrollArea, ScrollBar } from './ui/scroll-area';
|
package/dist/debugger/index.js
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createEventCatalog, defaultEventCatalog } from './events/catalog.js';
|
|
2
2
|
export { summarizeProtocolEvent } from './events/protocol-summarize.js';
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
3
|
+
export { DebuggerProvider, useDebugger } from './context.js';
|
|
4
|
+
export { projectionFor, workspaceFor, } from './plugin.js';
|
|
5
|
+
export { DebuggerShell } from './shell/debugger-shell.js';
|
|
6
|
+
export { StartForm } from './shell/start-form.js';
|
|
7
|
+
export { useStartRun } from './shell/use-start-run.js';
|
|
8
|
+
export { formInput, inputForm, messageInput, } from './shell/schema-form.js';
|
|
9
|
+
export { cn, compactJson, errorMessage, shortId } from './lib/cn.js';
|
|
10
|
+
export { jsonFields, jsonNumberText, jsonText } from './lib/payload.js';
|
|
6
11
|
export { statusClass, statusDotClass } from './lib/status.js';
|
|
7
12
|
export { countEventsByThread, runStatusFromEvents, startedAtFromEvents } from './lib/event-counts.js';
|
|
8
13
|
export { projectRunView } from './lib/project-run.js';
|
|
9
|
-
export { StatusDot } from './components/status-dot.js';
|
|
14
|
+
export { StatusBadge, StatusDot } from './components/status-dot.js';
|
|
10
15
|
export { JsonView } from './components/json-view.js';
|
|
16
|
+
export { JsonTree } from './components/json-tree.js';
|
|
17
|
+
export { parseStructuredJson } from './lib/json.js';
|
|
18
|
+
export { FollowList } from './components/follow-list.js';
|
|
19
|
+
export { Composer } from './components/composer.js';
|
|
11
20
|
export { RunTree } from './components/run-tree.js';
|
|
12
21
|
export { EventStream } from './components/event-stream.js';
|
|
13
22
|
export { EventInspector } from './components/event-inspector.js';
|
|
14
23
|
export { DebuggerSplit } from './components/debugger-split.js';
|
|
24
|
+
export { Button } from './ui/button.js';
|
|
15
25
|
export { Checkbox } from './ui/checkbox.js';
|
|
26
|
+
export { Input } from './ui/input.js';
|
|
27
|
+
export { Textarea } from './ui/textarea.js';
|
|
28
|
+
export { EmptyState, Kbd, PanelHeader, PanelTitle } from './ui/panel.js';
|
|
29
|
+
export { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select.js';
|
|
16
30
|
export { ScrollArea, ScrollBar } from './ui/scroll-area.js';
|
|
@@ -3,3 +3,4 @@ import type { JsonValue } from '@swirls/looms/core';
|
|
|
3
3
|
export declare function cn(...inputs: ClassValue[]): string;
|
|
4
4
|
export declare function shortId(id: string): string;
|
|
5
5
|
export declare function compactJson(value: JsonValue): string;
|
|
6
|
+
export declare function errorMessage(cause: unknown): string;
|
package/dist/debugger/lib/cn.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { DebuggerEvent, EventStreamCatalog } from '../contracts';
|
|
2
|
-
import type { EventSummary } from '../events/family';
|
|
1
|
+
import type { DebuggerEvent, EventStreamCatalog, EventSummary } from '../contracts';
|
|
3
2
|
export interface CachedEventMeta {
|
|
4
3
|
summary: EventSummary;
|
|
5
4
|
searchText: string;
|
|
6
5
|
family: string;
|
|
7
6
|
}
|
|
8
|
-
export declare function getEventMeta<TEvent extends DebuggerEvent>(event: TEvent, catalog
|
|
7
|
+
export declare function getEventMeta<TEvent extends DebuggerEvent>(event: TEvent, catalog: EventStreamCatalog<TEvent>): CachedEventMeta;
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
import { searchText, summarizeEvent } from '../events/catalog.js';
|
|
2
1
|
const metaCache = new WeakMap();
|
|
3
2
|
export function getEventMeta(event, catalog) {
|
|
4
3
|
const existing = metaCache.get(event);
|
|
5
4
|
if (existing && existing.catalog === catalog) {
|
|
6
5
|
return existing.meta;
|
|
7
6
|
}
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
metaCache.set(event, {
|
|
15
|
-
catalog,
|
|
16
|
-
meta,
|
|
17
|
-
});
|
|
7
|
+
const meta = {
|
|
8
|
+
summary: catalog.summarize(event),
|
|
9
|
+
searchText: catalog.searchText(event),
|
|
10
|
+
family: catalog.familyOf(event.type),
|
|
11
|
+
};
|
|
12
|
+
metaCache.set(event, { catalog, meta });
|
|
18
13
|
return meta;
|
|
19
14
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type JsonObject, type JsonValue } from '@swirls/looms/core';
|
|
2
|
+
export type JsonNode = {
|
|
3
|
+
readonly kind: 'object';
|
|
4
|
+
readonly value: JsonObject;
|
|
5
|
+
} | {
|
|
6
|
+
readonly kind: 'array';
|
|
7
|
+
readonly value: readonly JsonValue[];
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: 'string';
|
|
10
|
+
readonly value: string;
|
|
11
|
+
} | {
|
|
12
|
+
readonly kind: 'number';
|
|
13
|
+
readonly value: number;
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: 'boolean';
|
|
16
|
+
readonly value: boolean;
|
|
17
|
+
} | {
|
|
18
|
+
readonly kind: 'null';
|
|
19
|
+
};
|
|
20
|
+
export declare function jsonNode(value: JsonValue): JsonNode;
|
|
21
|
+
/** Parses text that holds a JSON object or array; plain strings and scalars stay text. */
|
|
22
|
+
export declare function parseStructuredJson(text: string): JsonObject | readonly JsonValue[] | undefined;
|
|
23
|
+
export declare function jsonEntries(node: JsonNode): readonly (readonly [string, JsonValue])[];
|
|
24
|
+
/** One-line summary shown beside a collapsed object or array. */
|
|
25
|
+
export declare function jsonPreview(node: JsonNode, budget?: number): string;
|