@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.
- package/CHANGELOG.md +37 -0
- package/dist/actor/host.js +4 -5
- package/dist/actor/index.d.ts +1 -1
- package/dist/actor/index.js +1 -1
- package/dist/actor/routing.d.ts +5 -0
- package/dist/actor/routing.js +14 -0
- package/dist/agent/agent-session.js +1 -0
- package/dist/agent/debugger/agent-chat.d.ts +2 -0
- package/dist/agent/debugger/agent-chat.js +210 -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 +53 -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/effects.d.ts +30 -0
- package/dist/agent/events.d.ts +2 -0
- package/dist/agent/events.js +2 -0
- package/dist/agent/llm.js +1 -8
- package/dist/agent/module.d.ts +604 -534
- package/dist/agent/module.js +11 -7
- package/dist/agent/projections.d.ts +5 -0
- package/dist/agent/projections.js +43 -2
- package/dist/agent/scope.d.ts +2 -0
- package/dist/agent/signals.d.ts +7 -0
- package/dist/agent/signals.js +25 -16
- package/dist/agent/threads.js +35 -21
- package/dist/agent/tool-schema.d.ts +1 -17
- package/dist/agent/tool-schema.js +3 -42
- package/dist/agent/transcript.d.ts +7 -0
- package/dist/agent/transcript.js +19 -0
- package/dist/agent/types.d.ts +10 -0
- package/dist/agent/types.js +4 -0
- 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 +18 -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/approval/effects.d.ts +12 -0
- package/dist/approval/module.d.ts +24 -0
- package/dist/client/client.d.ts +310 -0
- package/dist/client/client.js +20 -2
- package/dist/cloudflare/router.d.ts +1 -1
- package/dist/cloudflare/router.js +6 -8
- 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/effects.d.ts +7 -0
- package/dist/core/effects.js +1 -0
- package/dist/core/fold.js +12 -6
- package/dist/core/fork.d.ts +35 -0
- package/dist/core/fork.js +129 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +2 -0
- package/dist/core/module-scope.d.ts +1 -0
- package/dist/core/module.d.ts +4 -2
- package/dist/core/projection.js +1 -0
- package/dist/core/protocol.d.ts +10 -1
- package/dist/core/protocol.js +11 -0
- package/dist/core/published.d.ts +43 -0
- package/dist/core/published.js +44 -0
- package/dist/core/replay.d.ts +8 -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/snapshots.js +3 -17
- package/dist/core/sqlite-store.js +39 -0
- package/dist/core/state.d.ts +14 -0
- package/dist/core/state.js +25 -2
- package/dist/core/store.d.ts +1 -0
- package/dist/debugger/app/assets/index-BevQYa-U.js +22 -0
- package/dist/debugger/app/assets/index-CgDzWJg7.css +2 -0
- package/dist/debugger/app/assets/rolldown-runtime-CbXtAM7H.js +1 -0
- package/dist/debugger/app/assets/routes-B17Om93i.js +47 -0
- package/dist/debugger/app/index.html +14 -0
- package/dist/debugger/components/composer.d.ts +20 -0
- package/dist/debugger/components/composer.js +26 -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 +50 -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 +25 -17
- package/dist/debugger/events/protocol-summarize.d.ts +1 -2
- package/dist/debugger/events/protocol-summarize.js +36 -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-counts.d.ts +2 -2
- package/dist/debugger/lib/event-counts.js +5 -9
- 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 +5 -0
- package/dist/debugger/shell/run-controls.js +99 -0
- package/dist/debugger/shell/run-search.d.ts +6 -0
- package/dist/debugger/shell/run-search.js +100 -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/evaluator/effects.d.ts +12 -0
- package/dist/evaluator/module.d.ts +24 -0
- package/dist/projectors/index-model.d.ts +13 -7
- package/dist/projectors/index-model.js +21 -26
- package/dist/projectors/memory.js +19 -11
- package/dist/projectors/postgres.js +20 -19
- package/dist/projectors/schema.js +20 -18
- package/dist/projectors/sqlite.js +32 -27
- package/dist/react/materialize.js +16 -11
- package/dist/react/react.d.ts +6 -2
- package/dist/react/react.js +5 -2
- package/dist/react/store.d.ts +1 -1
- package/dist/react/store.js +1 -1
- package/dist/react/tables.d.ts +3 -2
- package/dist/runtime/cancellation.js +14 -27
- package/dist/runtime/errors.d.ts +39 -0
- package/dist/runtime/errors.js +32 -0
- package/dist/runtime/helpers.d.ts +2 -0
- package/dist/runtime/helpers.js +23 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/looms.d.ts +13 -1
- package/dist/runtime/looms.js +5 -2
- package/dist/runtime/repository.js +16 -1
- package/dist/runtime/run-start.js +1 -3
- package/dist/runtime/runtime.d.ts +1 -1
- package/dist/runtime/runtime.js +60 -18
- 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 +3 -0
- package/dist/runtime/server/http.js +21 -2
- 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 +43 -3
- package/dist/runtime/server.d.ts +3 -1
- package/dist/runtime/server.js +3 -1
- package/dist/runtime/types.d.ts +11 -1
- package/dist/runtime/wake-engine.js +5 -2
- package/dist/s2/snapshot-store.js +45 -7
- 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/dist/workflow/effects.d.ts +24 -0
- package/dist/workflow/effects.js +1 -0
- package/dist/workflow/module.d.ts +48 -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,42 @@
|
|
|
1
1
|
# @swirls/looms
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 331ff55: `stopAgentTurn()` builds an `agent.turn.stopped` signal that ends the turn in progress without ending the run. A conversational agent aborts its in-flight model call or tool, cancels child threads its tool calls started, answers open tool calls with a stopped result, and waits for the next message. An agent session cancels its active turn and stays open. The debugger chat shows a Stop button while a turn is running.
|
|
8
|
+
|
|
9
|
+
An interrupting `steer` now ends the turn the same way before it starts the next one, so it no longer leaves tool calls unanswered or tool children running.
|
|
10
|
+
|
|
11
|
+
Cancelling a thread now cancels every live thread below it, and a signal interrupt also aborts in-flight work in the named thread's descendants.
|
|
12
|
+
|
|
13
|
+
The new `turnActivity` projection reports whether the root agent thread has a turn in progress.
|
|
14
|
+
|
|
15
|
+
- 8da450e: `POST /runs/:id/cancel` and `client.cancel(runId, threadId?)` cancel a run or thread over HTTP. The debugger's Cancel button now uses it, so cancelling an in-flight agent turn stops the run instead of retrying the turn. Cancel stays available while a wake is running. `POST /runs/:id/wake` and `client.wake()` return `appended`, the number of events the run gained during the wake, and the debugger's Wake button reports it. Client run tables, the debugger, and projector indexes now mark a cancelled run as `cancelled` instead of `running`, and projector indexes mark a run that completed with an error as `failed` instead of `completed`. `RunRow.status` and `RunSummary.status` are typed as `RunStatus`, and `completedRunStatus()` reads the outcome of a `runtime.run.completed` payload.
|
|
16
|
+
|
|
17
|
+
Signals sent to a completed, failed, or cancelled run now reject with `RunTerminalError` (HTTP 409) instead of being appended and ignored. Retrying a signal whose `idempotencyKey` was already accepted still succeeds. `useRunSummary` exposes `finished`, and the debugger disables the agent follow-up composer and approval decisions on finished runs.
|
|
18
|
+
|
|
19
|
+
- 6230fe1: `looms.fork(runId)`, `POST /runs/:id/fork`, and `client.fork()` start a new run that continues where a failed or cancelled run stopped. The fork copies the source's history up to the point it finished, keeping thread ids and sequence numbers, records `runtime.run.forked`, and re-issues the effects outstanding there. A cancelled agent re-runs the model call the cancel cut off; a failed run retries the effect whose failure ended it. Effects can declare `deterministic: true` so a fork retries the work behind them instead; workflow scheduling does. Forking a missing run rejects with `RunNotFoundError` (404 over HTTP). Actor and Durable Object hosts return 501. The debugger shows Continue on failed and cancelled runs, and `useRunSummary` reports `resumable` for them.
|
|
20
|
+
|
|
21
|
+
`runtime.thread.cancelled` records `resumeSeq` on the thread a cancel targeted: the run's last seq before the cancellation began.
|
|
22
|
+
|
|
23
|
+
- 275e6a8: The projector index is keyed by run, so runs that share thread or approval ids stay apart. `getActor(runId, actorId?)` returns the run row by default or one of its threads, review rows carry `runId` instead of `actorId`, and the tables are now `looms_run_actors` and `looms_run_reviews`. The built-in index projectors moved to version 2, so delivery rebuilds them; the old `looms_actors` and `looms_reviews` tables are no longer written.
|
|
24
|
+
|
|
25
|
+
## 0.2.0
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- 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.
|
|
30
|
+
- 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.
|
|
31
|
+
|
|
32
|
+
`@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.
|
|
33
|
+
|
|
34
|
+
Breaking changes:
|
|
35
|
+
|
|
36
|
+
- Tool helpers and tool definitions no longer accept `inputSchema`. Pass `input` and the JSON Schema is derived from it.
|
|
37
|
+
- `@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`.
|
|
38
|
+
- `EventStreamCatalog.familyClass` is now `familyColor`, which returns a CSS color, and `searchText` is required.
|
|
39
|
+
|
|
3
40
|
## 0.1.0
|
|
4
41
|
|
|
5
42
|
### Minor Changes
|
package/dist/actor/host.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Data, Effect } from 'effect';
|
|
|
2
2
|
import { EventStoreTag } from '@swirls/looms/core';
|
|
3
3
|
import { createTimeoutScheduler, isLoomsApiPath } from '@swirls/looms/runtime';
|
|
4
4
|
import { createActorCell } from './cell.js';
|
|
5
|
-
import { resolveRunTarget, RunTargetError } from './routing.js';
|
|
5
|
+
import { crossRunResponse, resolveRunTarget, RunTargetError } from './routing.js';
|
|
6
6
|
class ActorWakeError extends Data.TaggedError('ActorWakeError') {
|
|
7
7
|
constructor(cause) {
|
|
8
8
|
super({
|
|
@@ -76,10 +76,9 @@ export function createLocalActorHost(options) {
|
|
|
76
76
|
if (url.pathname === '/health') {
|
|
77
77
|
return Promise.resolve(Response.json({ ok: true }));
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}, { status: 501 }));
|
|
79
|
+
const unsupported = crossRunResponse(req, 'the actor host');
|
|
80
|
+
if (unsupported) {
|
|
81
|
+
return Promise.resolve(unsupported);
|
|
83
82
|
}
|
|
84
83
|
return Effect.runPromise(Effect.gen(function* () {
|
|
85
84
|
const { runId, request } = yield* Effect.tryPromise({
|
package/dist/actor/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { createActorCell, type ActorCell, type ActorCellOptions } from './cell';
|
|
2
|
-
export { runIdFromRequest, resolveRunTarget, RunTargetError, type ResolvedRunTarget, } from './routing';
|
|
2
|
+
export { crossRunResponse, runIdFromRequest, resolveRunTarget, RunTargetError, type ResolvedRunTarget, } from './routing';
|
|
3
3
|
export { createLocalActorHost, type LocalActorHost, type LocalActorHostOptions } from './host';
|
package/dist/actor/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { createActorCell } from './cell.js';
|
|
2
|
-
export { runIdFromRequest, resolveRunTarget, RunTargetError, } from './routing.js';
|
|
2
|
+
export { crossRunResponse, runIdFromRequest, resolveRunTarget, RunTargetError, } from './routing.js';
|
|
3
3
|
export { createLocalActorHost } from './host.js';
|
package/dist/actor/routing.d.ts
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
* Inspects `x-looms-run-id` and `/runs/:runId/*`.
|
|
4
4
|
*/
|
|
5
5
|
export declare function runIdFromRequest(req: Request): string | null;
|
|
6
|
+
/**
|
|
7
|
+
* A 501 for requests that span runs, which a host with one cell per run cannot answer: listing
|
|
8
|
+
* runs needs a global index, and a fork writes a second run. `host` names the backend.
|
|
9
|
+
*/
|
|
10
|
+
export declare function crossRunResponse(req: Request, host: string): Response | null;
|
|
6
11
|
export interface ResolvedRunTarget {
|
|
7
12
|
readonly runId: string;
|
|
8
13
|
readonly request: Request;
|
package/dist/actor/routing.js
CHANGED
|
@@ -22,6 +22,20 @@ export function runIdFromRequest(req) {
|
|
|
22
22
|
}
|
|
23
23
|
return null;
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* A 501 for requests that span runs, which a host with one cell per run cannot answer: listing
|
|
27
|
+
* runs needs a global index, and a fork writes a second run. `host` names the backend.
|
|
28
|
+
*/
|
|
29
|
+
export function crossRunResponse(req, host) {
|
|
30
|
+
const { pathname } = new URL(req.url);
|
|
31
|
+
if (req.method === 'GET' && (pathname === '/runs' || pathname === '/runs/summaries')) {
|
|
32
|
+
return Response.json({ error: `Global run listing is not supported in ${host} without a global index` }, { status: 501 });
|
|
33
|
+
}
|
|
34
|
+
if (req.method === 'POST' && /^\/runs\/[^/]+\/fork$/.test(pathname)) {
|
|
35
|
+
return Response.json({ error: `Forking runs is not supported in ${host}; each run lives in its own cell` }, { status: 501 });
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
25
39
|
export class RunTargetError extends Data.TaggedError('RunTargetError') {
|
|
26
40
|
constructor(method, path) {
|
|
27
41
|
super({
|
|
@@ -140,6 +140,7 @@ export function createAgentSessionThread(definitions) {
|
|
|
140
140
|
pendingClosures: state.pendingClosures.filter((closure) => closure.messageId !== event.payload.messageId),
|
|
141
141
|
};
|
|
142
142
|
case 'agent.session.cancel.requested':
|
|
143
|
+
case 'agent.turn.stopped':
|
|
143
144
|
case 'runtime.thread.cancel.requested':
|
|
144
145
|
return state.activeTurn ? { ...state, cancelling: true } : state;
|
|
145
146
|
case 'runtime.wait.satisfied': {
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Bot, CornerDownRight, GitFork, MessageSquare, Settings2, User, Wrench } from 'lucide-react';
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
|
+
import { createEventId, isJsonObject, isJsonString, } from '@swirls/looms/core';
|
|
5
|
+
import { Button, 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, turnActivity } from '../projections.js';
|
|
8
|
+
import { agentSessionMessageEvents, stopAgentTurn, 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
|
+
event.type === 'agent.turn.stopped' ||
|
|
36
|
+
event.type === 'runtime.thread.cancelled') {
|
|
37
|
+
return { lastMessageSeq: event.seq, turnStarted: false, parts: [] };
|
|
38
|
+
}
|
|
39
|
+
if (event.seq <= state.lastMessageSeq) {
|
|
40
|
+
return state;
|
|
41
|
+
}
|
|
42
|
+
if (event.type === 'agent.turn.started') {
|
|
43
|
+
return { ...state, turnStarted: true };
|
|
44
|
+
}
|
|
45
|
+
if (event.type === 'agent.turn.text_delta' &&
|
|
46
|
+
isJsonObject(event.payload) &&
|
|
47
|
+
isJsonString(event.payload.delta)) {
|
|
48
|
+
return {
|
|
49
|
+
...state,
|
|
50
|
+
turnStarted: true,
|
|
51
|
+
parts: state.parts.concat(event.payload.delta),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return state;
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const deliveryOptions = [
|
|
58
|
+
{ value: 'followUp', label: 'Follow up', description: 'Queue after the current turn' },
|
|
59
|
+
{ value: 'steer', label: 'Steer', description: 'Redirect the active turn' },
|
|
60
|
+
{ value: 'nextTurn', label: 'Next turn', description: 'Hold until the next turn starts' },
|
|
61
|
+
];
|
|
62
|
+
function RoleLabel({ icon, children }) {
|
|
63
|
+
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] }));
|
|
64
|
+
}
|
|
65
|
+
function MessageText({ content, className }) {
|
|
66
|
+
const structured = useMemo(() => parseStructuredJson(content), [content]);
|
|
67
|
+
if (structured !== undefined) {
|
|
68
|
+
return _jsx(JsonTree, { value: structured, defaultExpandDepth: 2 });
|
|
69
|
+
}
|
|
70
|
+
return (_jsx("div", { className: cn('text-[13px] leading-relaxed break-words whitespace-pre-wrap', className), children: content }));
|
|
71
|
+
}
|
|
72
|
+
function ToolCard({ icon, name, meta, children, }) {
|
|
73
|
+
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 })] }));
|
|
74
|
+
}
|
|
75
|
+
function ToolCallCard({ call }) {
|
|
76
|
+
return (_jsx(ToolCard, { icon: _jsx(Wrench, {}), name: call.name, meta: shortId(call.id), children: _jsx(JsonTree, { value: call.arguments, defaultExpandDepth: 2 }) }));
|
|
77
|
+
}
|
|
78
|
+
function MessageItem({ line, toolName }) {
|
|
79
|
+
switch (line.role) {
|
|
80
|
+
case 'user':
|
|
81
|
+
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 }) })] }));
|
|
82
|
+
case 'assistant':
|
|
83
|
+
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)))] })] }));
|
|
84
|
+
case 'tool':
|
|
85
|
+
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 }) }));
|
|
86
|
+
case 'system':
|
|
87
|
+
return (_jsxs(_Fragment, { children: [_jsx(RoleLabel, { icon: _jsx(Settings2, {}), children: "System" }), _jsx(MessageText, { content: line.content, className: "text-muted-foreground" })] }));
|
|
88
|
+
default: {
|
|
89
|
+
const exhaustive = line.role;
|
|
90
|
+
return exhaustive;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function StreamingItem({ text }) {
|
|
95
|
+
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]" })] })] }));
|
|
96
|
+
}
|
|
97
|
+
function Transcript({ runId }) {
|
|
98
|
+
const store = useRunStore(runId);
|
|
99
|
+
const convo = useProjection(store, conversation);
|
|
100
|
+
const streaming = useEventFold(store, streamingFold);
|
|
101
|
+
const stream = streaming.turnStarted ? streaming.parts.join('') : null;
|
|
102
|
+
const toolNames = useMemo(() => {
|
|
103
|
+
const names = new Map();
|
|
104
|
+
for (const line of convo.lines) {
|
|
105
|
+
for (const call of line.toolCalls ?? []) {
|
|
106
|
+
names.set(call.id, call.name);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return names;
|
|
110
|
+
}, [convo.lines]);
|
|
111
|
+
const items = useMemo(() => {
|
|
112
|
+
const lines = convo.lines.map((line, index) => ({
|
|
113
|
+
kind: 'line',
|
|
114
|
+
line,
|
|
115
|
+
index,
|
|
116
|
+
}));
|
|
117
|
+
return stream === null ? lines : [...lines, { kind: 'stream', text: stream }];
|
|
118
|
+
}, [convo.lines, stream]);
|
|
119
|
+
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 })) })) }));
|
|
120
|
+
}
|
|
121
|
+
function DeliverySelect({ value, onChange, }) {
|
|
122
|
+
return (_jsxs(Select, { value: value, onValueChange: (next) => {
|
|
123
|
+
const option = deliveryOptions.find((candidate) => candidate.value === next);
|
|
124
|
+
if (option) {
|
|
125
|
+
onChange(option.value);
|
|
126
|
+
}
|
|
127
|
+
}, 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))) })] }));
|
|
128
|
+
}
|
|
129
|
+
export function AgentChat(context) {
|
|
130
|
+
const { definition, runId } = context;
|
|
131
|
+
const { client } = useDebugger();
|
|
132
|
+
const [draft, setDraft] = useState('');
|
|
133
|
+
const [delivery, setDelivery] = useState('followUp');
|
|
134
|
+
const { start, pending, error } = useStartRun(context);
|
|
135
|
+
const session = definition.kind === 'agent-session';
|
|
136
|
+
const form = inputForm(definition.inputSchema);
|
|
137
|
+
function send() {
|
|
138
|
+
const content = draft.trim();
|
|
139
|
+
const input = session ? null : messageInput(form, content);
|
|
140
|
+
if (!content || input === undefined) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
setDraft('');
|
|
144
|
+
start(input, session
|
|
145
|
+
? (started) => client.signal(started.runId, agentSessionMessageEvents(createEventId(), content, { threadId: started.threadId }))
|
|
146
|
+
: undefined);
|
|
147
|
+
}
|
|
148
|
+
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, onForked: context.onStarted })) : (_jsx(Composer, { value: draft, onChange: setDraft, onSubmit: send, pending: pending, placeholder: `Message ${definition.name}…`, submitLabel: "Start", error: error }))] }));
|
|
149
|
+
}
|
|
150
|
+
function FollowUp({ onForked, ...props }) {
|
|
151
|
+
const { status, resumable } = useRunSummary(useRunStore(props.runId));
|
|
152
|
+
return resumable ? (_jsx(ContinueRun, { runId: props.runId, status: status, onForked: onForked })) : (_jsx(Reply, { ...props }));
|
|
153
|
+
}
|
|
154
|
+
function ContinueRun({ runId, status, onForked, }) {
|
|
155
|
+
const { client } = useDebugger();
|
|
156
|
+
const [pending, setPending] = useState(false);
|
|
157
|
+
const [error, setError] = useState(null);
|
|
158
|
+
function continueInNewRun() {
|
|
159
|
+
setPending(true);
|
|
160
|
+
setError(null);
|
|
161
|
+
client
|
|
162
|
+
.fork(runId)
|
|
163
|
+
.then((forked) => onForked(forked.runId))
|
|
164
|
+
.catch((cause) => setError(errorMessage(cause)))
|
|
165
|
+
.finally(() => setPending(false));
|
|
166
|
+
}
|
|
167
|
+
return (_jsxs("div", { className: "border-border shrink-0 border-t p-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("p", { className: "text-muted-foreground min-w-0 flex-1 text-xs", children: ["Run ", status, ". Continue from where it stopped in a new run."] }), _jsxs(Button, { size: "sm", variant: "outline", disabled: pending, onClick: continueInNewRun, children: [_jsx(GitFork, {}), "Continue in new run"] })] }), error ? _jsx("p", { className: "text-status-failed mt-2 text-[11px]", children: error }) : null] }));
|
|
168
|
+
}
|
|
169
|
+
function Reply({ runId, session, delivery, setDelivery, startError }) {
|
|
170
|
+
const store = useRunStore(runId);
|
|
171
|
+
const { rootThreadId, status, finished } = useRunSummary(store);
|
|
172
|
+
const turn = useProjection(store, turnActivity);
|
|
173
|
+
const [draft, setDraft] = useState('');
|
|
174
|
+
const [pending, setPending] = useState(false);
|
|
175
|
+
const [stopping, setStopping] = useState(false);
|
|
176
|
+
const [error, setError] = useState(null);
|
|
177
|
+
function stop() {
|
|
178
|
+
if (!rootThreadId) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
setStopping(true);
|
|
182
|
+
setError(null);
|
|
183
|
+
store
|
|
184
|
+
.commit(stopAgentTurn({ threadId: rootThreadId }))
|
|
185
|
+
.catch((cause) => setError(errorMessage(cause)))
|
|
186
|
+
.finally(() => setStopping(false));
|
|
187
|
+
}
|
|
188
|
+
function send() {
|
|
189
|
+
const content = draft.trim();
|
|
190
|
+
if (!content || !rootThreadId || finished) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
setPending(true);
|
|
194
|
+
setError(null);
|
|
195
|
+
const events = session
|
|
196
|
+
? agentSessionMessageEvents(createEventId(), content, {
|
|
197
|
+
delivery,
|
|
198
|
+
threadId: rootThreadId,
|
|
199
|
+
activeChildThreadId: delivery === 'steer' ? activeSessionChild(store.events()) : undefined,
|
|
200
|
+
})
|
|
201
|
+
: [userMessage(content, { threadId: rootThreadId })];
|
|
202
|
+
const [only] = events;
|
|
203
|
+
const commit = events.length === 1 && only ? store.commit(only) : store.commit(events);
|
|
204
|
+
commit
|
|
205
|
+
.then(() => setDraft(''))
|
|
206
|
+
.catch((cause) => setError(errorMessage(cause)))
|
|
207
|
+
.finally(() => setPending(false));
|
|
208
|
+
}
|
|
209
|
+
return (_jsx(Composer, { value: draft, onChange: setDraft, onSubmit: send, onStop: turn.active && !finished ? stop : undefined, stopping: stopping, pending: pending, disabled: !rootThreadId || finished, placeholder: finished ? `Run ${status}. Start a new run to continue.` : 'Send a follow-up…', error: error ?? startError, toolbar: session ? _jsx(DeliverySelect, { value: delivery, onChange: setDelivery }) : null }));
|
|
210
|
+
}
|
|
@@ -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,53 @@
|
|
|
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.turn.stopped':
|
|
42
|
+
return { title: 'turn stopped' };
|
|
43
|
+
case 'agent.spawn.requested':
|
|
44
|
+
return {
|
|
45
|
+
title: 'agent spawn',
|
|
46
|
+
detail: `${jsonText(payload.kind) ?? 'agent'}:${jsonText(payload.definitionName) ?? 'unknown'}`,
|
|
47
|
+
};
|
|
48
|
+
case 'agent.effects.requested':
|
|
49
|
+
return { title: 'agent effects', detail: jsonText(payload.toolCallId) };
|
|
50
|
+
default:
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -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
|
};
|