@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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @swirls/looms
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6ed3a5f: `vercelEvaluator({ provider, model })` resolves model ids through an AI SDK provider such as `createTypeSafeAi({ apiKey })`, so callers can use their own TypeSafe key instead of the AI Gateway.
|
|
8
|
+
- 6ed3a5f: Serve a debugger UI from `createLooms` with `debuggerUi()` from `@swirls/looms/debugger/server`. Modules ship their own debugger views from `@swirls/looms/agent/debugger`, `@swirls/looms/workflow/debugger`, and `@swirls/looms/approval/debugger`. `GET /definitions` lists the definitions and projections that UI can start and inspect, and `GET /runs/summaries` returns each run's status and definition.
|
|
9
|
+
|
|
10
|
+
`@swirls/looms/debugger` also exports the building blocks the hosted UI uses, so module views can match it: `JsonTree` (collapsible JSON that expands JSON held in strings), `FollowList` (a virtualized list that follows new items), `Composer`, `Button`, `Input`, `Textarea`, `Select`, `PanelHeader`, `PanelTitle`, `EmptyState`, `Kbd`, and `StatusBadge`. To render `DebuggerShell` in your own app, import `@swirls/looms/debugger/styles.css` after Tailwind CSS v4. The stylesheet brings its theme and scans the kit and the built-in module views.
|
|
11
|
+
|
|
12
|
+
Breaking changes:
|
|
13
|
+
|
|
14
|
+
- Tool helpers and tool definitions no longer accept `inputSchema`. Pass `input` and the JSON Schema is derived from it.
|
|
15
|
+
- `@swirls/looms/debugger` no longer exports `EventFamily`, `DEFAULT_FAMILIES`, `familyClass`, `familyFromPrefix`, `summarizeDomainEvent`, `summarizeEvent`, `searchText`, or `createDefaultCatalog`. Build a catalog with `createEventCatalog(plugins)` or use `defaultEventCatalog`.
|
|
16
|
+
- `EventStreamCatalog.familyClass` is now `familyColor`, which returns a CSS color, and `searchText` is required.
|
|
17
|
+
|
|
3
18
|
## 0.1.0
|
|
4
19
|
|
|
5
20
|
### Minor Changes
|
package/dist/actor/host.js
CHANGED
|
@@ -76,7 +76,8 @@ export function createLocalActorHost(options) {
|
|
|
76
76
|
if (url.pathname === '/health') {
|
|
77
77
|
return Promise.resolve(Response.json({ ok: true }));
|
|
78
78
|
}
|
|
79
|
-
if (req.method === 'GET' &&
|
|
79
|
+
if (req.method === 'GET' &&
|
|
80
|
+
(url.pathname === '/runs' || url.pathname === '/runs/summaries')) {
|
|
80
81
|
return Promise.resolve(Response.json({
|
|
81
82
|
error: 'Global run listing is not supported in the actor host without a global index',
|
|
82
83
|
}, { status: 501 }));
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Bot, CornerDownRight, MessageSquare, Settings2, User, Wrench } from 'lucide-react';
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
|
+
import { createEventId, isJsonObject, isJsonString } from '@swirls/looms/core';
|
|
5
|
+
import { cn, Composer, EmptyState, errorMessage, FollowList, inputForm, JsonTree, messageInput, parseStructuredJson, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, shortId, useDebugger, useStartRun, } from '@swirls/looms/debugger';
|
|
6
|
+
import { createFold, useEventFold, useProjection, useRunStore, useRunSummary } from '@swirls/looms/react';
|
|
7
|
+
import { conversation } from '../projections.js';
|
|
8
|
+
import { agentSessionMessageEvents, userMessage } from '../signals.js';
|
|
9
|
+
/** Child thread of the session turn that is still open, from the events the store already has. */
|
|
10
|
+
function activeSessionChild(events) {
|
|
11
|
+
let child;
|
|
12
|
+
for (const event of events) {
|
|
13
|
+
if (!isJsonObject(event.payload)) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (event.type === 'agent.session.turn.started' && isJsonString(event.payload.childThreadId)) {
|
|
17
|
+
child = event.payload.childThreadId;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const tag = event.payload.tag;
|
|
21
|
+
if (event.type === 'runtime.wait.satisfied' &&
|
|
22
|
+
isJsonObject(tag) &&
|
|
23
|
+
tag.kind === 'agent-session-turn') {
|
|
24
|
+
child = undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return child;
|
|
28
|
+
}
|
|
29
|
+
const streamingFold = createFold({
|
|
30
|
+
name: 'agentStreamingText',
|
|
31
|
+
initialState: { lastMessageSeq: -1, turnStarted: false, parts: [] },
|
|
32
|
+
includeEphemeral: true,
|
|
33
|
+
reduce(state, event) {
|
|
34
|
+
if (event.type === 'agent.message') {
|
|
35
|
+
return { lastMessageSeq: event.seq, turnStarted: false, parts: [] };
|
|
36
|
+
}
|
|
37
|
+
if (event.seq <= state.lastMessageSeq) {
|
|
38
|
+
return state;
|
|
39
|
+
}
|
|
40
|
+
if (event.type === 'agent.turn.started') {
|
|
41
|
+
return { ...state, turnStarted: true };
|
|
42
|
+
}
|
|
43
|
+
if (event.type === 'agent.turn.text_delta' &&
|
|
44
|
+
isJsonObject(event.payload) &&
|
|
45
|
+
isJsonString(event.payload.delta)) {
|
|
46
|
+
return {
|
|
47
|
+
...state,
|
|
48
|
+
turnStarted: true,
|
|
49
|
+
parts: state.parts.concat(event.payload.delta),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return state;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
const deliveryOptions = [
|
|
56
|
+
{ value: 'followUp', label: 'Follow up', description: 'Queue after the current turn' },
|
|
57
|
+
{ value: 'steer', label: 'Steer', description: 'Redirect the active turn' },
|
|
58
|
+
{ value: 'nextTurn', label: 'Next turn', description: 'Hold until the next turn starts' },
|
|
59
|
+
];
|
|
60
|
+
function RoleLabel({ icon, children }) {
|
|
61
|
+
return (_jsxs("div", { className: "text-muted-foreground mb-1.5 flex items-center gap-1.5 text-[11px] font-medium [&_svg]:size-3", children: [icon, children] }));
|
|
62
|
+
}
|
|
63
|
+
function MessageText({ content, className }) {
|
|
64
|
+
const structured = useMemo(() => parseStructuredJson(content), [content]);
|
|
65
|
+
if (structured !== undefined) {
|
|
66
|
+
return _jsx(JsonTree, { value: structured, defaultExpandDepth: 2 });
|
|
67
|
+
}
|
|
68
|
+
return (_jsx("div", { className: cn('text-[13px] leading-relaxed break-words whitespace-pre-wrap', className), children: content }));
|
|
69
|
+
}
|
|
70
|
+
function ToolCard({ icon, name, meta, children, }) {
|
|
71
|
+
return (_jsxs("div", { className: "border-border bg-card/60 overflow-hidden rounded-lg border", children: [_jsxs("div", { className: "border-border/70 flex h-7 items-center gap-1.5 border-b px-2.5 text-[11px] [&_svg]:size-3", children: [_jsx("span", { className: "text-muted-foreground", children: icon }), _jsx("span", { className: "font-mono font-medium", children: name }), meta ? (_jsx("span", { className: "text-muted-foreground ml-auto truncate font-mono text-[10px]", children: meta })) : null] }), _jsx("div", { className: "px-2.5 py-1.5", children: children })] }));
|
|
72
|
+
}
|
|
73
|
+
function ToolCallCard({ call }) {
|
|
74
|
+
return (_jsx(ToolCard, { icon: _jsx(Wrench, {}), name: call.name, meta: shortId(call.id), children: _jsx(JsonTree, { value: call.arguments, defaultExpandDepth: 2 }) }));
|
|
75
|
+
}
|
|
76
|
+
function MessageItem({ line, toolName }) {
|
|
77
|
+
switch (line.role) {
|
|
78
|
+
case 'user':
|
|
79
|
+
return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(User, {}), children: "User" }), _jsx("div", { className: "bg-secondary w-fit max-w-full rounded-lg px-3 py-2", children: _jsx(MessageText, { content: line.content }) })] }));
|
|
80
|
+
case 'assistant':
|
|
81
|
+
return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(Bot, {}), children: "Assistant" }), _jsxs("div", { className: "grid gap-2", children: [line.content ? _jsx(MessageText, { content: line.content }) : null, line.toolCalls?.map((call) => (_jsx(ToolCallCard, { call: call }, call.id)))] })] }));
|
|
82
|
+
case 'tool':
|
|
83
|
+
return (_jsx(ToolCard, { icon: _jsx(CornerDownRight, {}), name: `${line.name ?? toolName ?? 'tool'} result`, meta: line.toolCallId ? shortId(line.toolCallId) : undefined, children: _jsx(MessageText, { content: line.content }) }));
|
|
84
|
+
case 'system':
|
|
85
|
+
return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(Settings2, {}), children: "System" }), _jsx(MessageText, { content: line.content, className: "text-muted-foreground" })] }));
|
|
86
|
+
default: {
|
|
87
|
+
const exhaustive = line.role;
|
|
88
|
+
return exhaustive;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function StreamingItem({ text }) {
|
|
93
|
+
return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(Bot, {}), children: "Assistant" }), _jsxs("div", { className: "text-[13px] leading-relaxed break-words whitespace-pre-wrap", children: [text, _jsx("span", { "aria-label": "Generating", className: "bg-foreground/70 ml-0.5 inline-block h-3.5 w-1.5 animate-pulse rounded-[1px] align-[-2px]" })] })] }));
|
|
94
|
+
}
|
|
95
|
+
function Transcript({ runId }) {
|
|
96
|
+
const store = useRunStore(runId);
|
|
97
|
+
const convo = useProjection(store, conversation);
|
|
98
|
+
const streaming = useEventFold(store, streamingFold);
|
|
99
|
+
const stream = streaming.turnStarted ? streaming.parts.join('') : null;
|
|
100
|
+
const toolNames = useMemo(() => {
|
|
101
|
+
const names = new Map();
|
|
102
|
+
for (const line of convo.lines) {
|
|
103
|
+
for (const call of line.toolCalls ?? []) {
|
|
104
|
+
names.set(call.id, call.name);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return names;
|
|
108
|
+
}, [convo.lines]);
|
|
109
|
+
const items = useMemo(() => {
|
|
110
|
+
const lines = convo.lines.map((line, index) => ({
|
|
111
|
+
kind: 'line',
|
|
112
|
+
line,
|
|
113
|
+
index,
|
|
114
|
+
}));
|
|
115
|
+
return stream === null ? lines : [...lines, { kind: 'stream', text: stream }];
|
|
116
|
+
}, [convo.lines, stream]);
|
|
117
|
+
return (_jsx(FollowList, { items: items, estimateSize: 96, overscan: 4, paddingStart: 8, paddingEnd: 12, getKey: (item) => (item.kind === 'stream' ? 'stream' : item.index), empty: _jsx("p", { className: "text-muted-foreground p-6 text-center text-xs", children: "Waiting for messages\u2026" }), renderItem: (item) => (_jsx("div", { className: "px-4 py-2", children: item.kind === 'stream' ? (_jsx(StreamingItem, { text: item.text })) : (_jsx(MessageItem, { line: item.line, toolName: item.line.toolCallId ? toolNames.get(item.line.toolCallId) : undefined })) })) }));
|
|
118
|
+
}
|
|
119
|
+
function DeliverySelect({ value, onChange, }) {
|
|
120
|
+
return (_jsxs(Select, { value: value, onValueChange: (next) => {
|
|
121
|
+
const option = deliveryOptions.find((candidate) => candidate.value === next);
|
|
122
|
+
if (option) {
|
|
123
|
+
onChange(option.value);
|
|
124
|
+
}
|
|
125
|
+
}, children: [_jsx(SelectTrigger, { "aria-label": "Delivery", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { align: "start", className: "w-60", children: deliveryOptions.map((option) => (_jsx(SelectItem, { value: option.value, description: option.description, children: option.label }, option.value))) })] }));
|
|
126
|
+
}
|
|
127
|
+
export function AgentChat(context) {
|
|
128
|
+
const { definition, runId } = context;
|
|
129
|
+
const { client } = useDebugger();
|
|
130
|
+
const [draft, setDraft] = useState('');
|
|
131
|
+
const [delivery, setDelivery] = useState('followUp');
|
|
132
|
+
const { start, pending, error } = useStartRun(context);
|
|
133
|
+
const session = definition.kind === 'agent-session';
|
|
134
|
+
const form = inputForm(definition.inputSchema);
|
|
135
|
+
function send() {
|
|
136
|
+
const content = draft.trim();
|
|
137
|
+
const input = session ? null : messageInput(form, content);
|
|
138
|
+
if (!content || input === undefined) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
setDraft('');
|
|
142
|
+
start(input, session
|
|
143
|
+
? (started) => client.signal(started.runId, agentSessionMessageEvents(createEventId(), content, { threadId: started.threadId }))
|
|
144
|
+
: undefined);
|
|
145
|
+
}
|
|
146
|
+
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [runId ? (_jsx(Transcript, { runId: runId })) : (_jsx("div", { className: "min-h-0 flex-1", children: _jsx(EmptyState, { icon: _jsx(MessageSquare, {}), title: `Talk to ${definition.name}`, children: "Your first message starts a new run." }) })), runId ? (_jsx(FollowUp, { runId: runId, session: session, delivery: delivery, setDelivery: setDelivery, startError: error })) : (_jsx(Composer, { value: draft, onChange: setDraft, onSubmit: send, pending: pending, placeholder: `Message ${definition.name}…`, submitLabel: "Start", error: error }))] }));
|
|
147
|
+
}
|
|
148
|
+
function FollowUp({ runId, session, delivery, setDelivery, startError, }) {
|
|
149
|
+
const store = useRunStore(runId);
|
|
150
|
+
const { rootThreadId } = useRunSummary(store);
|
|
151
|
+
const [draft, setDraft] = useState('');
|
|
152
|
+
const [pending, setPending] = useState(false);
|
|
153
|
+
const [error, setError] = useState(null);
|
|
154
|
+
function send() {
|
|
155
|
+
const content = draft.trim();
|
|
156
|
+
if (!content || !rootThreadId) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
setPending(true);
|
|
160
|
+
setError(null);
|
|
161
|
+
const events = session
|
|
162
|
+
? agentSessionMessageEvents(createEventId(), content, {
|
|
163
|
+
delivery,
|
|
164
|
+
threadId: rootThreadId,
|
|
165
|
+
activeChildThreadId: delivery === 'steer' ? activeSessionChild(store.events()) : undefined,
|
|
166
|
+
})
|
|
167
|
+
: [userMessage(content, { threadId: rootThreadId })];
|
|
168
|
+
const [only] = events;
|
|
169
|
+
const commit = events.length === 1 && only ? store.commit(only) : store.commit(events);
|
|
170
|
+
commit
|
|
171
|
+
.then(() => setDraft(''))
|
|
172
|
+
.catch((cause) => setError(errorMessage(cause)))
|
|
173
|
+
.finally(() => setPending(false));
|
|
174
|
+
}
|
|
175
|
+
return (_jsx(Composer, { value: draft, onChange: setDraft, onSubmit: send, pending: pending, disabled: !rootThreadId, placeholder: "Send a follow-up\u2026", error: error ?? startError, toolbar: session ? _jsx(DeliverySelect, { value: delivery, onChange: setDelivery }) : null }));
|
|
176
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { inputForm, messageInput } from '@swirls/looms/debugger';
|
|
2
|
+
import { tokenUsage } from '../projections.js';
|
|
3
|
+
import { AgentChat } from './agent-chat.js';
|
|
4
|
+
import { summarizeAgentEvent } from './summarize.js';
|
|
5
|
+
import { TokenUsageView } from './token-usage.js';
|
|
6
|
+
function isChat(definition) {
|
|
7
|
+
return messageInput(inputForm(definition.inputSchema), '') !== undefined;
|
|
8
|
+
}
|
|
9
|
+
export const agentDebugger = {
|
|
10
|
+
name: 'agent',
|
|
11
|
+
families: [{ family: 'agent', color: 'oklch(0.74 0.12 240)', summarize: summarizeAgentEvent }],
|
|
12
|
+
workspace: {
|
|
13
|
+
kinds: ['agent', 'agent-session'],
|
|
14
|
+
matches: (definition) => definition.kind === 'agent-session' || isChat(definition),
|
|
15
|
+
component: AgentChat,
|
|
16
|
+
},
|
|
17
|
+
projections: [{ name: tokenUsage.name, component: TokenUsageView }],
|
|
18
|
+
};
|
|
19
|
+
export { AgentChat, TokenUsageView };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { isJsonObject, isJsonString } from '@swirls/looms/core';
|
|
2
|
+
import { compactJson, jsonFields, jsonNumberText, jsonText, } from '@swirls/looms/debugger';
|
|
3
|
+
function messageContent(payload) {
|
|
4
|
+
const message = jsonFields(payload).message;
|
|
5
|
+
return isJsonObject(message) && isJsonString(message.content) ? message.content : undefined;
|
|
6
|
+
}
|
|
7
|
+
function toolCallSummary(payload) {
|
|
8
|
+
const call = jsonFields(payload).toolCall;
|
|
9
|
+
if (!isJsonObject(call)) {
|
|
10
|
+
return { name: 'tool', args: null };
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
name: isJsonString(call.name) ? call.name : 'tool',
|
|
14
|
+
args: call.arguments ?? null,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function summarizeAgentEvent(event) {
|
|
18
|
+
const payload = jsonFields(event.payload);
|
|
19
|
+
switch (event.type) {
|
|
20
|
+
case 'agent.message.received':
|
|
21
|
+
return { title: 'user message', detail: messageContent(event.payload) };
|
|
22
|
+
case 'agent.turn.started':
|
|
23
|
+
return { title: 'turn started', detail: `turn ${jsonNumberText(payload.turn) ?? ''}` };
|
|
24
|
+
case 'agent.turn.text_delta':
|
|
25
|
+
return { title: 'text delta', detail: jsonText(payload.delta) };
|
|
26
|
+
case 'agent.message':
|
|
27
|
+
return { title: 'agent message', detail: messageContent(event.payload) };
|
|
28
|
+
case 'agent.tool_call.requested': {
|
|
29
|
+
const call = toolCallSummary(event.payload);
|
|
30
|
+
return { title: `tool ${call.name}`, detail: compactJson(call.args) };
|
|
31
|
+
}
|
|
32
|
+
case 'agent.tool.result':
|
|
33
|
+
return {
|
|
34
|
+
title: jsonText(payload.error)
|
|
35
|
+
? `tool error ${jsonText(payload.name)}`
|
|
36
|
+
: `tool result ${jsonText(payload.name)}`,
|
|
37
|
+
detail: jsonText(payload.error) ?? compactJson(payload.result ?? null),
|
|
38
|
+
};
|
|
39
|
+
case 'agent.steered':
|
|
40
|
+
return { title: 'steered', detail: messageContent(event.payload) };
|
|
41
|
+
case 'agent.spawn.requested':
|
|
42
|
+
return {
|
|
43
|
+
title: 'agent spawn',
|
|
44
|
+
detail: `${jsonText(payload.kind) ?? 'agent'}:${jsonText(payload.definitionName) ?? 'unknown'}`,
|
|
45
|
+
};
|
|
46
|
+
case 'agent.effects.requested':
|
|
47
|
+
return { title: 'agent effects', detail: jsonText(payload.toolCallId) };
|
|
48
|
+
default:
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useProjection, useRunStore } from '@swirls/looms/react';
|
|
3
|
+
import { tokenUsage } from '../projections.js';
|
|
4
|
+
const format = new Intl.NumberFormat();
|
|
5
|
+
function Stat({ label, value }) {
|
|
6
|
+
return (_jsxs("div", { className: "border-border bg-card/60 rounded-lg border px-2.5 py-2", children: [_jsx("p", { className: "text-muted-foreground text-[11px]", children: label }), _jsx("p", { className: "font-mono text-[13px] font-medium tabular-nums", children: format.format(value) })] }));
|
|
7
|
+
}
|
|
8
|
+
export function TokenUsageView({ runId }) {
|
|
9
|
+
const state = useProjection(useRunStore(runId), tokenUsage);
|
|
10
|
+
return (_jsxs("div", { className: "grid grid-cols-3 gap-2", children: [_jsx(Stat, { label: "Input", value: state.input }), _jsx(Stat, { label: "Output", value: state.output }), _jsx(Stat, { label: "Total", value: state.input + state.output })] }));
|
|
11
|
+
}
|
|
@@ -13,7 +13,6 @@ export interface FunctionTool<TName extends string = string, TInput = JsonValue,
|
|
|
13
13
|
readonly name: TName;
|
|
14
14
|
readonly description: string;
|
|
15
15
|
readonly input?: StandardSchemaV1<any, TInput> | Schema.ConstraintDecoder<TInput>;
|
|
16
|
-
readonly inputSchema?: JsonValue;
|
|
17
16
|
handler(input: TInput, ctx: ToolContext): Promise<TOutput> | TOutput;
|
|
18
17
|
}
|
|
19
18
|
export interface ThreadTool {
|
|
@@ -21,7 +20,6 @@ export interface ThreadTool {
|
|
|
21
20
|
readonly name: string;
|
|
22
21
|
readonly description: string;
|
|
23
22
|
readonly input?: SchemaInput;
|
|
24
|
-
readonly inputSchema?: JsonValue;
|
|
25
23
|
readonly childKind: string;
|
|
26
24
|
readonly childName: string;
|
|
27
25
|
readonly childVersion: string;
|
|
@@ -37,7 +35,6 @@ export interface EffectsTool {
|
|
|
37
35
|
readonly name: string;
|
|
38
36
|
readonly description: string;
|
|
39
37
|
readonly input?: SchemaInput;
|
|
40
|
-
readonly inputSchema?: JsonValue;
|
|
41
38
|
effects(input: JsonValue): RuntimeEffect[];
|
|
42
39
|
waitOn?: {
|
|
43
40
|
type: string | readonly string[];
|
|
@@ -76,6 +73,7 @@ export interface AgentDefinition<TName extends string = string, TInput = JsonVal
|
|
|
76
73
|
readonly kind: 'agent';
|
|
77
74
|
readonly name: TName;
|
|
78
75
|
readonly version: string;
|
|
76
|
+
readonly description?: string;
|
|
79
77
|
readonly model?: string;
|
|
80
78
|
readonly instructions: string;
|
|
81
79
|
readonly input?: StandardSchemaV1<any, TInput> | Schema.ConstraintDecoder<TInput>;
|
|
@@ -90,6 +88,7 @@ export interface AgentSessionDefinition<TName extends string = string> {
|
|
|
90
88
|
readonly kind: 'agent-session';
|
|
91
89
|
readonly name: TName;
|
|
92
90
|
readonly version: string;
|
|
91
|
+
readonly description?: string;
|
|
93
92
|
/** The agent definition is pinned when the session definition is created. */
|
|
94
93
|
readonly agent: Pick<AgentDefinition, 'kind' | 'name' | 'version'>;
|
|
95
94
|
/** Max idle milliseconds before parking. Zero waits indefinitely. */
|
|
@@ -97,6 +96,7 @@ export interface AgentSessionDefinition<TName extends string = string> {
|
|
|
97
96
|
}
|
|
98
97
|
export declare function defineAgentSession<TName extends string>(def: {
|
|
99
98
|
readonly name: TName;
|
|
99
|
+
readonly description?: string;
|
|
100
100
|
readonly agent: Pick<AgentDefinition, 'kind' | 'name' | 'version'>;
|
|
101
101
|
readonly version?: string;
|
|
102
102
|
readonly idleTimeoutMs?: number;
|
|
@@ -111,7 +111,6 @@ export declare function asThreadTool(def: {
|
|
|
111
111
|
name?: string;
|
|
112
112
|
description?: string;
|
|
113
113
|
input?: SchemaInput;
|
|
114
|
-
inputSchema?: JsonValue;
|
|
115
114
|
child: {
|
|
116
115
|
kind: string;
|
|
117
116
|
name: string;
|
|
@@ -123,14 +122,12 @@ export declare function asAgentTool(def: {
|
|
|
123
122
|
name?: string;
|
|
124
123
|
description?: string;
|
|
125
124
|
input?: SchemaInput;
|
|
126
|
-
inputSchema?: JsonValue;
|
|
127
125
|
agent: {
|
|
128
126
|
kind: 'agent';
|
|
129
127
|
name: string;
|
|
130
128
|
version?: string;
|
|
131
129
|
instructions?: string;
|
|
132
130
|
input?: SchemaInput;
|
|
133
|
-
inputSchema?: JsonValue;
|
|
134
131
|
};
|
|
135
132
|
mapInput?: (input: JsonValue) => JsonValue;
|
|
136
133
|
}): ThreadTool;
|
|
@@ -139,13 +136,11 @@ type EvaluatorToolTarget = {
|
|
|
139
136
|
name: string;
|
|
140
137
|
description?: string;
|
|
141
138
|
input?: SchemaInput;
|
|
142
|
-
inputSchema?: JsonValue;
|
|
143
139
|
};
|
|
144
140
|
export declare function asEvaluatorTool(def: {
|
|
145
141
|
name?: string;
|
|
146
142
|
description?: string;
|
|
147
143
|
input?: SchemaInput;
|
|
148
|
-
inputSchema?: JsonValue;
|
|
149
144
|
evaluator: EvaluatorToolTarget;
|
|
150
145
|
mapInput?: (input: JsonValue) => JsonValue;
|
|
151
146
|
}): ThreadTool;
|
|
@@ -153,14 +148,12 @@ export declare function asWorkflowTool(def: {
|
|
|
153
148
|
name?: string;
|
|
154
149
|
description?: string;
|
|
155
150
|
input?: SchemaInput;
|
|
156
|
-
inputSchema?: JsonValue;
|
|
157
151
|
workflow: {
|
|
158
152
|
kind: 'workflow';
|
|
159
153
|
name: string;
|
|
160
154
|
version?: string;
|
|
161
155
|
description?: string;
|
|
162
156
|
input?: SchemaInput;
|
|
163
|
-
inputSchema?: JsonValue;
|
|
164
157
|
};
|
|
165
158
|
mapInput?: (input: JsonValue) => JsonValue;
|
|
166
159
|
}): ThreadTool;
|
|
@@ -168,7 +161,6 @@ export declare function asEffectsTool(def: {
|
|
|
168
161
|
name: string;
|
|
169
162
|
description: string;
|
|
170
163
|
input?: SchemaInput;
|
|
171
|
-
inputSchema?: JsonValue;
|
|
172
164
|
effects: (input: JsonValue) => RuntimeEffect[];
|
|
173
165
|
waitOn?: {
|
|
174
166
|
type: string | readonly string[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_DEFINITION_VERSION, } from '@swirls/looms/core';
|
|
2
2
|
export function defineAgentSession(def) {
|
|
3
|
-
|
|
3
|
+
const definition = {
|
|
4
4
|
kind: 'agent-session',
|
|
5
5
|
name: def.name,
|
|
6
6
|
version: def.version ?? DEFAULT_DEFINITION_VERSION,
|
|
@@ -11,6 +11,10 @@ export function defineAgentSession(def) {
|
|
|
11
11
|
},
|
|
12
12
|
idleTimeoutMs: Math.max(0, def.idleTimeoutMs ?? 0),
|
|
13
13
|
};
|
|
14
|
+
if (def.description === undefined) {
|
|
15
|
+
return definition;
|
|
16
|
+
}
|
|
17
|
+
return { ...definition, description: def.description };
|
|
14
18
|
}
|
|
15
19
|
export function normalizeTools(tools = []) {
|
|
16
20
|
return tools.map((entry) => {
|
|
@@ -51,7 +55,6 @@ export function asThreadTool(def) {
|
|
|
51
55
|
name: def.name ?? def.child.name,
|
|
52
56
|
description: def.description ?? def.child.name,
|
|
53
57
|
input: def.input,
|
|
54
|
-
inputSchema: def.inputSchema,
|
|
55
58
|
childKind: def.child.kind,
|
|
56
59
|
childName: def.child.name,
|
|
57
60
|
childVersion: def.child.version ?? DEFAULT_DEFINITION_VERSION,
|
|
@@ -64,7 +67,6 @@ export function asAgentTool(def) {
|
|
|
64
67
|
name: def.name,
|
|
65
68
|
description: def.description ?? def.agent.instructions,
|
|
66
69
|
input: def.input ?? def.agent.input,
|
|
67
|
-
inputSchema: def.inputSchema ?? def.agent.inputSchema,
|
|
68
70
|
child: { kind: 'agent', name: def.agent.name, version: def.agent.version },
|
|
69
71
|
mapInput: def.mapInput,
|
|
70
72
|
});
|
|
@@ -74,7 +76,6 @@ export function asEvaluatorTool(def) {
|
|
|
74
76
|
name: def.name,
|
|
75
77
|
description: def.description ?? def.evaluator.description,
|
|
76
78
|
input: def.input ?? def.evaluator.input,
|
|
77
|
-
inputSchema: def.inputSchema ?? def.evaluator.inputSchema,
|
|
78
79
|
child: { kind: 'evaluator', name: def.evaluator.name },
|
|
79
80
|
mapInput: def.mapInput,
|
|
80
81
|
});
|
|
@@ -84,7 +85,6 @@ export function asWorkflowTool(def) {
|
|
|
84
85
|
name: def.name,
|
|
85
86
|
description: def.description ?? def.workflow.description,
|
|
86
87
|
input: def.input ?? def.workflow.input,
|
|
87
|
-
inputSchema: def.inputSchema ?? def.workflow.inputSchema,
|
|
88
88
|
child: { kind: 'workflow', name: def.workflow.name, version: def.workflow.version },
|
|
89
89
|
mapInput: def.mapInput,
|
|
90
90
|
});
|
|
@@ -95,7 +95,6 @@ export function asEffectsTool(def) {
|
|
|
95
95
|
name: def.name,
|
|
96
96
|
description: def.description,
|
|
97
97
|
input: def.input,
|
|
98
|
-
inputSchema: def.inputSchema,
|
|
99
98
|
effects: def.effects,
|
|
100
99
|
waitOn: def.waitOn,
|
|
101
100
|
};
|
package/dist/agent/signals.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ interface AgentSessionSignalClient<Result> {
|
|
|
35
35
|
signal(runId: string, events: ReadonlyArray<EventInput>): Promise<Result>;
|
|
36
36
|
cancel?(runId: string, threadId?: string): Promise<Result>;
|
|
37
37
|
}
|
|
38
|
+
/** Events for one session message. A steer aimed at `activeChildThreadId` interrupts that turn in the same batch. */
|
|
39
|
+
export declare function agentSessionMessageEvents(messageId: string, text: string, options?: AgentSessionMessageOptions): EventInput[];
|
|
38
40
|
export declare function sendAgentSessionMessage<Result>(client: AgentSessionSignalClient<Result>, runId: string, messageId: string, text: string, options?: Omit<AgentSessionMessageOptions, 'activeChildThreadId'>): Promise<Result>;
|
|
39
41
|
export declare function cancelActiveAgentTurn<Result>(client: AgentSessionSignalClient<Result>, runId: string, options?: AgentSignalOptions): Promise<Result | Awaited<ReturnType<AgentSessionSignalClient<Result>['getRun']>>>;
|
|
40
42
|
export {};
|
package/dist/agent/signals.js
CHANGED
|
@@ -54,26 +54,28 @@ function activeTurnFrom(value) {
|
|
|
54
54
|
}
|
|
55
55
|
: null;
|
|
56
56
|
}
|
|
57
|
+
/** Events for one session message. A steer aimed at `activeChildThreadId` interrupts that turn in the same batch. */
|
|
58
|
+
export function agentSessionMessageEvents(messageId, text, options = {}) {
|
|
59
|
+
const events = [submitAgentMessage(messageId, text, options)];
|
|
60
|
+
if (options.delivery === 'steer' && options.activeChildThreadId) {
|
|
61
|
+
events.push(agentModule.input('steered', {
|
|
62
|
+
turn: 0,
|
|
63
|
+
messageId,
|
|
64
|
+
message: { role: 'user', content: text },
|
|
65
|
+
interrupt: true,
|
|
66
|
+
}, { threadId: options.activeChildThreadId }));
|
|
67
|
+
}
|
|
68
|
+
return events;
|
|
69
|
+
}
|
|
57
70
|
export function sendAgentSessionMessage(client, runId, messageId, text, options = {}) {
|
|
58
71
|
return client.getRun(runId).then((run) => {
|
|
59
72
|
const threadId = options.threadId ?? run.rootThreadId ?? undefined;
|
|
60
73
|
const active = options.delivery === 'steer' && threadId ? activeTurnFrom(run.threads[threadId]?.state) : null;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}),
|
|
67
|
-
];
|
|
68
|
-
if (active) {
|
|
69
|
-
events.push(agentModule.input('steered', {
|
|
70
|
-
turn: 0,
|
|
71
|
-
messageId,
|
|
72
|
-
message: { role: 'user', content: text },
|
|
73
|
-
interrupt: true,
|
|
74
|
-
}, { threadId: active.childThreadId }));
|
|
75
|
-
}
|
|
76
|
-
return client.signal(runId, events);
|
|
74
|
+
return client.signal(runId, agentSessionMessageEvents(messageId, text, {
|
|
75
|
+
...options,
|
|
76
|
+
threadId,
|
|
77
|
+
activeChildThreadId: active?.childThreadId,
|
|
78
|
+
}));
|
|
77
79
|
});
|
|
78
80
|
}
|
|
79
81
|
export function cancelActiveAgentTurn(client, runId, options = {}) {
|
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { JsonValue, SchemaInput } from '@swirls/looms/core';
|
|
1
|
+
import { type JsonValue } from '@swirls/looms/core';
|
|
3
2
|
import { type AgentToolEntry, type ToolLike } from './definitions';
|
|
4
3
|
import type { LlmToolSpec } from './llm';
|
|
5
|
-
interface StandardJsonSchemaConverter {
|
|
6
|
-
readonly input: (options: {
|
|
7
|
-
target: string;
|
|
8
|
-
}) => JsonValue;
|
|
9
|
-
}
|
|
10
|
-
interface StandardJsonSchemaHolder {
|
|
11
|
-
readonly '~standard': {
|
|
12
|
-
readonly jsonSchema?: {
|
|
13
|
-
readonly input?: StandardJsonSchemaConverter['input'];
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
type SchemaCandidate = SchemaInput | StandardJsonSchemaHolder | Schema.Codec<JsonValue>;
|
|
18
4
|
export declare function toolJsonSchema(tool: ToolLike): JsonValue;
|
|
19
5
|
export declare function toolSpecs(tools?: ReadonlyArray<AgentToolEntry>): LlmToolSpec[];
|
|
20
|
-
export declare function jsonSchemaFromStandard(schema: SchemaCandidate | null | undefined): JsonValue;
|
|
21
|
-
export {};
|
|
@@ -1,43 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsonSchemaOfInput } from '@swirls/looms/core';
|
|
2
2
|
import { normalizeTools } from './definitions.js';
|
|
3
3
|
const EMPTY_OBJECT_SCHEMA = { type: 'object' };
|
|
4
|
-
function
|
|
5
|
-
return '~standard' in value;
|
|
6
|
-
}
|
|
7
|
-
function fromStandardJsonSchema(schema) {
|
|
8
|
-
if (!isStandardJsonSchemaHolder(schema)) {
|
|
9
|
-
return undefined;
|
|
10
|
-
}
|
|
11
|
-
const input = schema['~standard'].jsonSchema?.input;
|
|
12
|
-
if (!input) {
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
|
-
try {
|
|
16
|
-
return input({ target: 'draft-2020-12' });
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
function fromEffectSchema(schema) {
|
|
23
|
-
if (!Schema.isSchema(schema)) {
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
try {
|
|
27
|
-
const standard = Schema.toStandardJSONSchemaV1(schema);
|
|
28
|
-
return fromStandardJsonSchema(standard);
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
return undefined;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function fromInputCandidate(input) {
|
|
35
|
-
if (!input) {
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
return fromStandardJsonSchema(input) ?? fromEffectSchema(input);
|
|
39
|
-
}
|
|
40
|
-
function toolInputCandidate(tool) {
|
|
4
|
+
function toolInput(tool) {
|
|
41
5
|
switch (tool.kind) {
|
|
42
6
|
case 'function':
|
|
43
7
|
return tool.input;
|
|
@@ -52,7 +16,7 @@ function toolInputCandidate(tool) {
|
|
|
52
16
|
}
|
|
53
17
|
}
|
|
54
18
|
export function toolJsonSchema(tool) {
|
|
55
|
-
return
|
|
19
|
+
return jsonSchemaOfInput(toolInput(tool)) ?? EMPTY_OBJECT_SCHEMA;
|
|
56
20
|
}
|
|
57
21
|
export function toolSpecs(tools = []) {
|
|
58
22
|
return normalizeTools(tools).map((tool) => ({
|
|
@@ -61,6 +25,3 @@ export function toolSpecs(tools = []) {
|
|
|
61
25
|
inputJsonSchema: toolJsonSchema(tool),
|
|
62
26
|
}));
|
|
63
27
|
}
|
|
64
|
-
export function jsonSchemaFromStandard(schema) {
|
|
65
|
-
return fromInputCandidate(schema ?? undefined) ?? EMPTY_OBJECT_SCHEMA;
|
|
66
|
-
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { vercelLlm, type VercelLlmOptions } from './vercel-llm';
|
|
2
|
-
export { toEvaluatorAnswers, vercelEvaluator, type VercelEvaluatorOptions, } from './vercel-evaluator';
|
|
2
|
+
export { toEvaluatorAnswers, vercelEvaluator, type EvaluationModelProvider, type VercelEvaluatorOptions, } from './vercel-evaluator';
|
|
3
3
|
export { toLoomsToolCalls, toModelMessages } from './messages';
|