@signal9/era-ui 4.15.4 → 4.16.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/dist/ai/swarm/context.d.ts +7 -1
- package/dist/ai/swarm/index.d.ts +1 -1
- package/dist/ai/swarm/index.js +1 -1
- package/dist/ai/swarm/swarm-artifact.svelte +24 -2
- package/dist/ai/swarm/swarm-node.svelte +35 -3
- package/dist/ai/swarm/swarm-root.svelte +7 -1
- package/dist/ai/swarm/swarm-root.svelte.d.ts +3 -1
- package/dist/ai/swarm/swarm-sandbox.svelte +30 -2
- package/dist/ai/swarm/swarm.d.ts +219 -5
- package/dist/ai/swarm/swarm.js +149 -0
- package/dist/apps/llm-shell/llm-shell.svelte +15 -1
- package/dist/apps/llm-shell/llm-shell.svelte.d.ts +6 -0
- package/dist/apps/llm-shell/llm-swarm.svelte +9 -2
- package/dist/apps/llm-shell/llm-swarm.svelte.d.ts +2 -0
- package/dist/apps/notes/notes.svelte +9 -4
- package/dist/era-ui.css +1 -1
- package/dist/generated-docs/llms-full.txt +33 -0
- package/dist/generated-docs/llms.txt +1 -0
- package/dist/generated-docs/manifest.json +12 -1
- package/dist/generated-docs/utilities.json +10 -0
- package/dist/generated-docs/utilities.md +32 -0
- package/dist/styles/index.css +25 -0
- package/dist/ui/combobox/combobox-input.svelte +2 -2
- package/dist/ui/input/input.svelte +6 -3
- package/dist/ui/pin-input/pin-input-cell.svelte +4 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SwarmAgent } from './swarm.js';
|
|
1
|
+
import type { SwarmAgent, SwarmContentRenderers } from './swarm.js';
|
|
2
2
|
/**
|
|
3
3
|
* What `Swarm.Root` shares with every part below it.
|
|
4
4
|
*
|
|
@@ -21,6 +21,12 @@ export interface SwarmContext {
|
|
|
21
21
|
readonly onOpen?: (agent: SwarmAgent) => void;
|
|
22
22
|
/** Cancel an agent (the host decides whether that means its subtree too). */
|
|
23
23
|
readonly onCancel?: (agent: SwarmAgent) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Inline renderers for artifact payloads, one per content kind — see
|
|
26
|
+
* `SwarmContentRenderers`. Registered once here so every artifact in the
|
|
27
|
+
* tree resolves the same registry without prop drilling.
|
|
28
|
+
*/
|
|
29
|
+
readonly renderers?: SwarmContentRenderers;
|
|
24
30
|
}
|
|
25
31
|
export declare function setSwarmContext(ctx: SwarmContext): void;
|
|
26
32
|
export declare function getSwarmContext(): SwarmContext;
|
package/dist/ai/swarm/index.d.ts
CHANGED
|
@@ -13,5 +13,5 @@ export { default as Footer } from './swarm-footer.svelte';
|
|
|
13
13
|
export { default as Dot, SWARM_DOT } from './swarm-dot.svelte';
|
|
14
14
|
export { default as Role, SWARM_ROLE } from './swarm-role.svelte';
|
|
15
15
|
export { SwarmController } from './swarm.svelte.js';
|
|
16
|
-
export { buildSwarmTree, isSwarmAgentActive, flattenSwarmTree, summarizeSwarm, summarizeBarrier, swarmElapsed, formatSwarmAge, formatSwarmDuration, type SwarmAgent, type SwarmAgentStatus, type SwarmArtifact, type SwarmBarrier, type SwarmBarrierStatus, type SwarmConnection, type SwarmCounts, type SwarmEvent, type SwarmNode, type SwarmPlan, type SwarmPlanStatus, type SwarmRole, type SwarmSandbox, type SwarmSnapshot } from './swarm.js';
|
|
16
|
+
export { buildSwarmTree, isSwarmAgentActive, isSwarmAgentRetrying, isSwarmSandboxFork, flattenSwarmTree, parseSwarmContent, summarizeSwarm, summarizeBarrier, summarizeSwarmRoots, swarmArtifactContent, swarmElapsed, swarmSandboxForkOf, swarmSubtree, formatSwarmAge, formatSwarmDuration, formatSwarmRetry, type SwarmAgent, type SwarmAgentProgress, type SwarmAgentStatus, type SwarmArtifact, type SwarmBarrier, type SwarmBarrierStatus, type SwarmChartContent, type SwarmComponentContent, type SwarmConnection, type SwarmContentKind, type SwarmContentOf, type SwarmContentRenderers, type SwarmCounts, type SwarmEvent, type SwarmEventKind, type SwarmExecContent, type SwarmExecEvent, type SwarmExecSegment, type SwarmJsonContent, type SwarmMarkdownContent, type SwarmNode, type SwarmPlan, type SwarmPlanStatus, type SwarmRichContent, type SwarmRole, type SwarmRootSummary, type SwarmSandbox, type SwarmSandboxForkId, type SwarmSandboxStatus, type SwarmSnapshot } from './swarm.js';
|
|
17
17
|
export type { SwarmContext } from './context.js';
|
package/dist/ai/swarm/index.js
CHANGED
|
@@ -13,4 +13,4 @@ export { default as Footer } from './swarm-footer.svelte';
|
|
|
13
13
|
export { default as Dot, SWARM_DOT } from './swarm-dot.svelte';
|
|
14
14
|
export { default as Role, SWARM_ROLE } from './swarm-role.svelte';
|
|
15
15
|
export { SwarmController } from './swarm.svelte.js';
|
|
16
|
-
export { buildSwarmTree, isSwarmAgentActive, flattenSwarmTree, summarizeSwarm, summarizeBarrier, swarmElapsed, formatSwarmAge, formatSwarmDuration } from './swarm.js';
|
|
16
|
+
export { buildSwarmTree, isSwarmAgentActive, isSwarmAgentRetrying, isSwarmSandboxFork, flattenSwarmTree, parseSwarmContent, summarizeSwarm, summarizeBarrier, summarizeSwarmRoots, swarmArtifactContent, swarmElapsed, swarmSandboxForkOf, swarmSubtree, formatSwarmAge, formatSwarmDuration, formatSwarmRetry } from './swarm.js';
|
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
import { Card } from '../../ui/card/index.js';
|
|
4
4
|
import { cn } from '../../utils/index.js';
|
|
5
5
|
import { getSwarmContext } from './context.js';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
formatSwarmAge,
|
|
8
|
+
swarmArtifactContent,
|
|
9
|
+
type SwarmArtifact,
|
|
10
|
+
type SwarmRichContent
|
|
11
|
+
} from './swarm.js';
|
|
12
|
+
import type { Snippet } from 'svelte';
|
|
7
13
|
|
|
8
14
|
let {
|
|
9
15
|
artifact,
|
|
@@ -17,6 +23,15 @@
|
|
|
17
23
|
const age = $derived(
|
|
18
24
|
artifact.createdAt != null ? formatSwarmAge(artifact.createdAt, ctx.now) : null
|
|
19
25
|
);
|
|
26
|
+
|
|
27
|
+
// The payload's classified body, and the host's renderer for it, if both
|
|
28
|
+
// exist. The cast erases the per-kind narrowing the registry's mapped type
|
|
29
|
+
// enforces at REGISTRATION — the lookup pairs each snippet with content of
|
|
30
|
+
// its own kind by construction, TS just can't see across the indexed access.
|
|
31
|
+
const content = $derived(swarmArtifactContent(artifact));
|
|
32
|
+
const render = $derived(
|
|
33
|
+
content ? (ctx.renderers?.[content.kind] as Snippet<[SwarmRichContent]> | undefined) : undefined
|
|
34
|
+
);
|
|
20
35
|
</script>
|
|
21
36
|
|
|
22
37
|
<!-- What a branch actually produced: the merged finding, the report, the diff.
|
|
@@ -37,5 +52,12 @@
|
|
|
37
52
|
<span class="shrink-0 font-mono text-body text-muted tabular-nums">{age}</span>
|
|
38
53
|
{/if}
|
|
39
54
|
</div>
|
|
40
|
-
|
|
55
|
+
{#if content && render}
|
|
56
|
+
<!-- The host's inline renderer for this payload kind — a chart, a terminal,
|
|
57
|
+
an embedded component. The summary stays out of the way: the rich body
|
|
58
|
+
IS the artifact, and the one-liner under it would say it twice. -->
|
|
59
|
+
{@render render(content)}
|
|
60
|
+
{:else}
|
|
61
|
+
<p class="text-body leading-body text-muted">{artifact.summary}</p>
|
|
62
|
+
{/if}
|
|
41
63
|
</Card>
|
|
@@ -8,7 +8,13 @@
|
|
|
8
8
|
import Role from './swarm-role.svelte';
|
|
9
9
|
import Sandbox from './swarm-sandbox.svelte';
|
|
10
10
|
import Actions, { swarmActions } from './swarm-actions.svelte';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
formatSwarmDuration,
|
|
13
|
+
formatSwarmRetry,
|
|
14
|
+
isSwarmAgentRetrying,
|
|
15
|
+
swarmElapsed,
|
|
16
|
+
type SwarmAgent
|
|
17
|
+
} from './swarm.js';
|
|
12
18
|
|
|
13
19
|
let {
|
|
14
20
|
agent,
|
|
@@ -160,12 +166,26 @@
|
|
|
160
166
|
active
|
|
161
167
|
? 'bg-hover text-bright'
|
|
162
168
|
: 'text-fg hover:bg-(--era-highlight) hover:shadow-(--era-highlight-shadow)',
|
|
163
|
-
|
|
169
|
+
// Scoped to the DIRECT parent, not the group: every node in the tree is
|
|
170
|
+
// a group/node, and a named group matches ANY ancestor — focusing a
|
|
171
|
+
// parent row was outlining every visible child row. `:focus-visible > &`
|
|
172
|
+
// can only mean this row's own treeitem.
|
|
173
|
+
'[:focus-visible>&]:outline [:focus-visible>&]:-outline-offset-1 [:focus-visible>&]:outline-primary'
|
|
164
174
|
)}
|
|
165
175
|
>
|
|
166
176
|
{#if hasChildren}
|
|
177
|
+
<!-- Rotation keys off the component's own bound `open`, NOT the
|
|
178
|
+
group-data-[state=open]/node selector it used to ride: nested nodes
|
|
179
|
+
all share the group name, and a named group matches ANY ancestor —
|
|
180
|
+
so the moment a parent expanded (which it must, for a child to be
|
|
181
|
+
visible at all), every child chevron rotated and stayed rotated.
|
|
182
|
+
`open` is bind:open on this node's own Collapsible.Root — the same
|
|
183
|
+
single source of truth, without the ancestry. -->
|
|
167
184
|
<ChevronRight
|
|
168
|
-
class=
|
|
185
|
+
class={cn(
|
|
186
|
+
'size-(--era-h-xs) shrink-0 text-muted transition-transform duration-(--era-duration) ease-(--era-ease)',
|
|
187
|
+
open && 'rotate-90'
|
|
188
|
+
)}
|
|
169
189
|
aria-hidden="true"
|
|
170
190
|
/>
|
|
171
191
|
{:else}
|
|
@@ -215,6 +235,18 @@
|
|
|
215
235
|
<Sandbox sandbox={agent.sandbox} />
|
|
216
236
|
{/if}
|
|
217
237
|
|
|
238
|
+
{#if isSwarmAgentRetrying(agent.progress)}
|
|
239
|
+
<!-- The retry ladder, visible: the runtime is waiting out a provider
|
|
240
|
+
outage, and a live countdown is the difference between "stuck" and
|
|
241
|
+
"resuming in 8s". Warning ink — it is a degraded state, not an
|
|
242
|
+
error. Ticks with ctx.now like every clock here. -->
|
|
243
|
+
<span class="shrink-0 font-mono text-body text-warning tabular-nums">
|
|
244
|
+
{formatSwarmRetry(agent.progress, ctx.now)}
|
|
245
|
+
</span>
|
|
246
|
+
{:else if agent.progress?.phase === 'waiting'}
|
|
247
|
+
<span class="shrink-0 font-mono text-body text-muted">{agent.progress.label}</span>
|
|
248
|
+
{/if}
|
|
249
|
+
|
|
218
250
|
{#if elapsed != null}
|
|
219
251
|
<span class="shrink-0 font-mono text-body text-muted tabular-nums">
|
|
220
252
|
{formatSwarmDuration(elapsed)}
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
4
|
import { cn } from '../../utils/index.js';
|
|
5
5
|
import { setSwarmContext } from './context.js';
|
|
6
|
-
import type { SwarmAgent } from './swarm.js';
|
|
6
|
+
import type { SwarmAgent, SwarmContentRenderers } from './swarm.js';
|
|
7
7
|
|
|
8
8
|
let {
|
|
9
9
|
ref = $bindable(null),
|
|
10
10
|
now = Date.now(),
|
|
11
11
|
onOpen,
|
|
12
12
|
onCancel,
|
|
13
|
+
renderers,
|
|
13
14
|
children,
|
|
14
15
|
class: className,
|
|
15
16
|
...restProps
|
|
@@ -21,6 +22,8 @@
|
|
|
21
22
|
onOpen?: (agent: SwarmAgent) => void;
|
|
22
23
|
/** Cancel an agent. Nodes show the affordance only while one is still active. */
|
|
23
24
|
onCancel?: (agent: SwarmAgent) => void;
|
|
25
|
+
/** Inline renderers for artifact payloads (charts, exec output, components). */
|
|
26
|
+
renderers?: SwarmContentRenderers;
|
|
24
27
|
children?: Snippet;
|
|
25
28
|
} = $props();
|
|
26
29
|
|
|
@@ -35,6 +38,9 @@
|
|
|
35
38
|
},
|
|
36
39
|
get onCancel() {
|
|
37
40
|
return onCancel;
|
|
41
|
+
},
|
|
42
|
+
get renderers() {
|
|
43
|
+
return renderers;
|
|
38
44
|
}
|
|
39
45
|
});
|
|
40
46
|
</script>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
import type { SwarmAgent } from './swarm.js';
|
|
3
|
+
import type { SwarmAgent, SwarmContentRenderers } from './swarm.js';
|
|
4
4
|
type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
5
5
|
ref?: HTMLDivElement | null;
|
|
6
6
|
/** Epoch ms for every elapsed readout. Tick it in `$state` for live counters. */
|
|
@@ -9,6 +9,8 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
9
9
|
onOpen?: (agent: SwarmAgent) => void;
|
|
10
10
|
/** Cancel an agent. Nodes show the affordance only while one is still active. */
|
|
11
11
|
onCancel?: (agent: SwarmAgent) => void;
|
|
12
|
+
/** Inline renderers for artifact payloads (charts, exec output, components). */
|
|
13
|
+
renderers?: SwarmContentRenderers;
|
|
12
14
|
children?: Snippet;
|
|
13
15
|
};
|
|
14
16
|
declare const SwarmRoot: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
<script lang="ts">
|
|
17
17
|
import Box from '@lucide/svelte/icons/box';
|
|
18
|
+
import Camera from '@lucide/svelte/icons/camera';
|
|
19
|
+
import GitBranch from '@lucide/svelte/icons/git-branch';
|
|
18
20
|
import { cn } from '../../utils/index.js';
|
|
21
|
+
import { swarmSandboxForkOf } from './swarm.js';
|
|
19
22
|
|
|
20
23
|
let {
|
|
21
24
|
sandbox,
|
|
@@ -27,6 +30,18 @@
|
|
|
27
30
|
label?: boolean;
|
|
28
31
|
class?: string;
|
|
29
32
|
} = $props();
|
|
33
|
+
|
|
34
|
+
const forkOf = $derived(swarmSandboxForkOf(sandbox));
|
|
35
|
+
const title = $derived(
|
|
36
|
+
[
|
|
37
|
+
`sandbox ${sandbox.id ?? ''} (${sandbox.status})`,
|
|
38
|
+
forkOf && `forked from ${forkOf}`,
|
|
39
|
+
sandbox.checkpoint && 'checkpoint',
|
|
40
|
+
sandbox.busy && 'command running'
|
|
41
|
+
]
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.join(' — ')
|
|
44
|
+
);
|
|
30
45
|
</script>
|
|
31
46
|
|
|
32
47
|
<!-- Deliberately a signal of its own, never folded into the status dot: an agent
|
|
@@ -38,8 +53,21 @@
|
|
|
38
53
|
SANDBOX_TONE[sandbox.status],
|
|
39
54
|
className
|
|
40
55
|
)}
|
|
41
|
-
title
|
|
56
|
+
{title}
|
|
42
57
|
>
|
|
43
|
-
|
|
58
|
+
<!-- busy: the box PULSES rather than gaining a second glyph — "a command is
|
|
59
|
+
streaming through this VM" is motion, and motion is what says it. -->
|
|
60
|
+
<Box
|
|
61
|
+
class={cn('size-(--era-h-xs) shrink-0', sandbox.busy && 'animate-pulse')}
|
|
62
|
+
aria-hidden="true"
|
|
63
|
+
/>
|
|
64
|
+
{#if sandbox.checkpoint}
|
|
65
|
+
<!-- A paused VM kept as a restore point — the camera badge, as the
|
|
66
|
+
reference console draws it. -->
|
|
67
|
+
<Camera class="size-(--era-icon-xxs) shrink-0" aria-hidden="true" />
|
|
68
|
+
{:else if forkOf}
|
|
69
|
+
<!-- Live-forked from a parent VM; the lineage is in the title. -->
|
|
70
|
+
<GitBranch class="size-(--era-icon-xxs) shrink-0" aria-hidden="true" />
|
|
71
|
+
{/if}
|
|
44
72
|
{#if label}<span class="truncate">{sandbox.status}</span>{/if}
|
|
45
73
|
</span>
|
package/dist/ai/swarm/swarm.d.ts
CHANGED
|
@@ -53,12 +53,87 @@ export type SwarmBarrierStatus = 'open' | 'done' | 'failed' | 'cancelled';
|
|
|
53
53
|
* `Swarm.Footer`) for exactly that reason.
|
|
54
54
|
*/
|
|
55
55
|
export type SwarmConnection = 'idle' | 'loading' | 'live' | 'reconnecting' | 'error';
|
|
56
|
-
/**
|
|
56
|
+
/** A sandbox VM's lifecycle. `paused` includes checkpoints — see `checkpoint`. */
|
|
57
|
+
export type SwarmSandboxStatus = 'running' | 'paused' | 'terminated';
|
|
58
|
+
/**
|
|
59
|
+
* The id convention live-forked VMs carry: `<parent>-fk-<hex>`. A template
|
|
60
|
+
* literal type rather than a boolean field, because the LINEAGE is in the id —
|
|
61
|
+
* `swarmSandboxForkOf` recovers the parent from it with no extra data.
|
|
62
|
+
*/
|
|
63
|
+
export type SwarmSandboxForkId = `${string}-fk-${string}`;
|
|
64
|
+
/** Whether a sandbox id names a live fork of another VM. */
|
|
65
|
+
export declare function isSwarmSandboxFork(id: string): id is SwarmSandboxForkId;
|
|
66
|
+
/** The parent VM a forked sandbox was cloned from, or null for a fresh VM. */
|
|
67
|
+
export declare function swarmSandboxForkOf(sandbox: SwarmSandbox): string | null;
|
|
68
|
+
/**
|
|
69
|
+
* The VM an agent executes in, when it has one.
|
|
70
|
+
*
|
|
71
|
+
* Everything beyond `status` is optional because sandbox truth is usually a
|
|
72
|
+
* SEPARATE, slower channel than the swarm's own event stream (the reference
|
|
73
|
+
* implementation snapshots it on a poll and deliberately never journals it) —
|
|
74
|
+
* a host reports what it knows and the parts render what is there.
|
|
75
|
+
*/
|
|
57
76
|
export interface SwarmSandbox {
|
|
58
|
-
/** Provider id, shown on hover. */
|
|
77
|
+
/** Provider id, shown on hover. Fork lineage is readable from it — see `SwarmSandboxForkId`. */
|
|
59
78
|
id?: string;
|
|
60
|
-
status:
|
|
79
|
+
status: SwarmSandboxStatus;
|
|
80
|
+
/** Parent VM this one was live-forked from. Omit to derive from the id. */
|
|
81
|
+
forkOf?: string | null;
|
|
82
|
+
/** A paused VM kept as a restore point (rendered with the checkpoint badge). */
|
|
83
|
+
checkpoint?: boolean;
|
|
84
|
+
/** A command is streaming through this VM right now. */
|
|
85
|
+
busy?: boolean;
|
|
86
|
+
/** Epoch ms the grace-window VM will be reaped, for a countdown. */
|
|
87
|
+
expiresAt?: number | null;
|
|
88
|
+
}
|
|
89
|
+
/** One chunk of live process output from a sandbox exec. */
|
|
90
|
+
export interface SwarmExecSegment {
|
|
91
|
+
stream: 'stdout' | 'stderr';
|
|
92
|
+
data: string;
|
|
61
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* The exec stream's wire shape: interleaved output, then exactly one exit.
|
|
96
|
+
* `hint` is a sandbox-side diagnostic (timeout, missing interpreter) — NOT
|
|
97
|
+
* process output, which is why it is on the exit and not in the segments.
|
|
98
|
+
*/
|
|
99
|
+
export type SwarmExecEvent = {
|
|
100
|
+
type: 'output';
|
|
101
|
+
segments: SwarmExecSegment[];
|
|
102
|
+
} | {
|
|
103
|
+
type: 'exit';
|
|
104
|
+
exitCode: number;
|
|
105
|
+
hint?: string;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* A transient runtime phase on a live agent — the retry ladder made visible.
|
|
109
|
+
*
|
|
110
|
+
* Discriminated on `phase` so the retrying arm can REQUIRE its countdown
|
|
111
|
+
* fields: a "retrying" chip with no resume time is exactly the half-state this
|
|
112
|
+
* type exists to make unrepresentable.
|
|
113
|
+
*/
|
|
114
|
+
export type SwarmAgentProgress = {
|
|
115
|
+
phase: 'retrying';
|
|
116
|
+
/** Retry attempt number, 1-based. */
|
|
117
|
+
attempt: number;
|
|
118
|
+
/** Epoch ms when the runtime resumes after the backoff. */
|
|
119
|
+
resumeAt: number;
|
|
120
|
+
/** What is being waited out ("provider overloaded"). */
|
|
121
|
+
label?: string;
|
|
122
|
+
} | {
|
|
123
|
+
phase: 'waiting';
|
|
124
|
+
label: string;
|
|
125
|
+
};
|
|
126
|
+
/** Narrow an agent's progress to the retrying arm (gates the countdown chip). */
|
|
127
|
+
export declare function isSwarmAgentRetrying(progress: SwarmAgentProgress | null | undefined): progress is Extract<SwarmAgentProgress, {
|
|
128
|
+
phase: 'retrying';
|
|
129
|
+
}>;
|
|
130
|
+
/**
|
|
131
|
+
* The countdown a retrying agent renders: `attempt 2 — resuming in 8s`.
|
|
132
|
+
* Same clock rule as everything here — `now` is an argument.
|
|
133
|
+
*/
|
|
134
|
+
export declare function formatSwarmRetry(progress: Extract<SwarmAgentProgress, {
|
|
135
|
+
phase: 'retrying';
|
|
136
|
+
}>, now: number): string;
|
|
62
137
|
/** One agent in the swarm. */
|
|
63
138
|
export interface SwarmAgent {
|
|
64
139
|
id: string;
|
|
@@ -76,6 +151,18 @@ export interface SwarmAgent {
|
|
|
76
151
|
result?: string;
|
|
77
152
|
/** Fan-in gate this agent reports into. */
|
|
78
153
|
barrierId?: string | null;
|
|
154
|
+
/** The plan this agent belongs to, when the host tracks more than one. */
|
|
155
|
+
planId?: string | null;
|
|
156
|
+
/**
|
|
157
|
+
* The host's execution handle — what sandbox operations (exec, terminate,
|
|
158
|
+
* lifecycle) are keyed by in most runtimes. Opaque to era.
|
|
159
|
+
*/
|
|
160
|
+
executionId?: string | null;
|
|
161
|
+
/**
|
|
162
|
+
* Transient runtime phase (a provider-retry countdown, a named wait).
|
|
163
|
+
* Cleared with `null`; rendered inline on the row while present.
|
|
164
|
+
*/
|
|
165
|
+
progress?: SwarmAgentProgress | null;
|
|
79
166
|
/**
|
|
80
167
|
* The agent's own transcript, when it has one. This GATES the open
|
|
81
168
|
* affordance: a row or card shows the open button only when the host has both
|
|
@@ -121,6 +208,12 @@ export interface SwarmArtifact {
|
|
|
121
208
|
kind: string;
|
|
122
209
|
title?: string;
|
|
123
210
|
summary: string;
|
|
211
|
+
/**
|
|
212
|
+
* The artifact's full structured body — what `summary` is a compression of.
|
|
213
|
+
* Parsed structurally by `parseSwarmContent` for inline rich rendering
|
|
214
|
+
* (charts, exec output, embedded components); see `SwarmContentRenderers`.
|
|
215
|
+
*/
|
|
216
|
+
payload?: Record<string, unknown> | null;
|
|
124
217
|
/** Epoch ms. */
|
|
125
218
|
createdAt?: number;
|
|
126
219
|
}
|
|
@@ -142,6 +235,8 @@ export interface SwarmCounts {
|
|
|
142
235
|
cancelled: number;
|
|
143
236
|
/** blocked + queued + running — everything that has not landed yet. */
|
|
144
237
|
active: number;
|
|
238
|
+
/** done + failed + cancelled — the determinate progress bar's value. */
|
|
239
|
+
settled: number;
|
|
145
240
|
/** Agents holding a VM that is not terminated. */
|
|
146
241
|
sandboxes: number;
|
|
147
242
|
}
|
|
@@ -206,10 +301,18 @@ export declare function formatSwarmDuration(ms: number): string;
|
|
|
206
301
|
* differ the moment an event updates an agent already in the map, which is most
|
|
207
302
|
* events, and confusing the two silently re-requests or skips history.
|
|
208
303
|
*/
|
|
304
|
+
/**
|
|
305
|
+
* The event labels the reference journal emits, template-literal-typed so a
|
|
306
|
+
* status change is spelled from the same union the status field uses — and
|
|
307
|
+
* widened with `(string & {})`, the intersection trick that keeps arbitrary
|
|
308
|
+
* producer strings assignable WITHOUT collapsing the union (a bare `| string`
|
|
309
|
+
* would swallow the literals and take autocomplete with it).
|
|
310
|
+
*/
|
|
311
|
+
export type SwarmEventKind = 'agent.spawned' | `agent.${SwarmAgentStatus}` | `plan.${'created' | 'updated'}` | `barrier.${'created' | 'updated'}` | 'artifact.published' | (string & {});
|
|
209
312
|
export interface SwarmEvent {
|
|
210
313
|
seq: number;
|
|
211
|
-
/**
|
|
212
|
-
kind?:
|
|
314
|
+
/** Producer label — see `SwarmEventKind`. Passed through untouched. */
|
|
315
|
+
kind?: SwarmEventKind;
|
|
213
316
|
agent?: SwarmAgent;
|
|
214
317
|
plan?: SwarmPlan;
|
|
215
318
|
barrier?: SwarmBarrier;
|
|
@@ -224,3 +327,114 @@ export interface SwarmSnapshot {
|
|
|
224
327
|
barriers?: SwarmBarrier[];
|
|
225
328
|
artifacts?: SwarmArtifact[];
|
|
226
329
|
}
|
|
330
|
+
/**
|
|
331
|
+
* Tabular data with a visualization spec — the chart shape the reference
|
|
332
|
+
* runtime streams (`viz.type` names the mark, `data` is columnar rows).
|
|
333
|
+
* era ships no chart renderer; the HOST registers one (see
|
|
334
|
+
* `SwarmContentRenderers`) and receives this, fully typed.
|
|
335
|
+
*/
|
|
336
|
+
export interface SwarmChartContent {
|
|
337
|
+
kind: 'chart';
|
|
338
|
+
viz: {
|
|
339
|
+
type: string;
|
|
340
|
+
} & Record<string, unknown>;
|
|
341
|
+
data: {
|
|
342
|
+
columns: string[];
|
|
343
|
+
rows: Record<string, unknown>[];
|
|
344
|
+
rowCount?: number;
|
|
345
|
+
};
|
|
346
|
+
title?: string;
|
|
347
|
+
}
|
|
348
|
+
/** A finished command's output — the sandbox exec result, inline. */
|
|
349
|
+
export interface SwarmExecContent {
|
|
350
|
+
kind: 'exec';
|
|
351
|
+
exitCode: number;
|
|
352
|
+
stdout: string;
|
|
353
|
+
stderr: string;
|
|
354
|
+
/** Sandbox-side diagnostic (timeout, missing interpreter) — not process output. */
|
|
355
|
+
hint?: string;
|
|
356
|
+
command?: string;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* An embedded component by registry name — the "spawn an app inline" shape.
|
|
360
|
+
* Generic over its props so a host with a typed registry can narrow `props`
|
|
361
|
+
* per component id; the default keeps it structural.
|
|
362
|
+
*/
|
|
363
|
+
export interface SwarmComponentContent<P extends Record<string, unknown> = Record<string, unknown>> {
|
|
364
|
+
kind: 'component';
|
|
365
|
+
/** Registry id the host resolves to a Svelte component. */
|
|
366
|
+
component: string;
|
|
367
|
+
props?: P;
|
|
368
|
+
/** Render in place (true) vs. "opens elsewhere" affordance (false). */
|
|
369
|
+
inline?: boolean;
|
|
370
|
+
}
|
|
371
|
+
/** Prose — rendered by the host's markdown pipeline. */
|
|
372
|
+
export interface SwarmMarkdownContent {
|
|
373
|
+
kind: 'markdown';
|
|
374
|
+
text: string;
|
|
375
|
+
}
|
|
376
|
+
/** The structured fallback: anything JSON-shaped the parsers above declined. */
|
|
377
|
+
export interface SwarmJsonContent {
|
|
378
|
+
kind: 'json';
|
|
379
|
+
data: unknown;
|
|
380
|
+
}
|
|
381
|
+
/** Everything an artifact payload can render as, discriminated on `kind`. */
|
|
382
|
+
export type SwarmRichContent = SwarmChartContent | SwarmExecContent | SwarmComponentContent | SwarmMarkdownContent | SwarmJsonContent;
|
|
383
|
+
export type SwarmContentKind = SwarmRichContent['kind'];
|
|
384
|
+
/** The union member for one kind — `SwarmContentOf<'chart'>` is `SwarmChartContent`. */
|
|
385
|
+
export type SwarmContentOf<K extends SwarmContentKind> = Extract<SwarmRichContent, {
|
|
386
|
+
kind: K;
|
|
387
|
+
}>;
|
|
388
|
+
/**
|
|
389
|
+
* The host's inline renderers, one optional snippet per content kind, each
|
|
390
|
+
* typed to exactly its member of the union — a mapped type over the
|
|
391
|
+
* discriminant, so registering a `chart` snippet that expects exec output is a
|
|
392
|
+
* compile error, not a runtime surprise.
|
|
393
|
+
*
|
|
394
|
+
* Registered once on `Swarm.Root` and read through context by every artifact
|
|
395
|
+
* in the tree — the era analogue of the reference app's component registry.
|
|
396
|
+
* Kinds without a renderer fall back to the artifact's summary text.
|
|
397
|
+
*/
|
|
398
|
+
export type SwarmContentRenderers = {
|
|
399
|
+
[K in SwarmContentKind]?: import('svelte').Snippet<[SwarmContentOf<K>]>;
|
|
400
|
+
};
|
|
401
|
+
/**
|
|
402
|
+
* Classify a payload STRUCTURALLY — by the fields it carries, never by a tool
|
|
403
|
+
* name or a declared type tag (producers rename tools; shapes are the
|
|
404
|
+
* contract). Detection order mirrors the reference implementation: exec
|
|
405
|
+
* (exitCode + stdout) → chart (viz.type + data.columns[]) → component
|
|
406
|
+
* (component string) → markdown (a lone text/markdown field) → json.
|
|
407
|
+
* Returns null only for empty input, so a renderer switch is total.
|
|
408
|
+
*/
|
|
409
|
+
export declare function parseSwarmContent(payload: unknown): SwarmRichContent | null;
|
|
410
|
+
/** An artifact's rich body, when it has one — `parseSwarmContent` over `payload`. */
|
|
411
|
+
export declare function swarmArtifactContent(artifact: SwarmArtifact): SwarmRichContent | null;
|
|
412
|
+
/**
|
|
413
|
+
* One swarm summarized to a list row — what a hunts/runs table renders.
|
|
414
|
+
* The reference app's "hunt" IS this: a swarm root plus aggregate counts,
|
|
415
|
+
* under a domain label.
|
|
416
|
+
*/
|
|
417
|
+
export interface SwarmRootSummary {
|
|
418
|
+
rootId: string;
|
|
419
|
+
/** The root agent's task — the row's title. */
|
|
420
|
+
title: string;
|
|
421
|
+
/** The root agent's own status. */
|
|
422
|
+
status: SwarmAgentStatus;
|
|
423
|
+
counts: SwarmCounts;
|
|
424
|
+
/** Epoch ms of the newest agent activity, for the "updated" cell. */
|
|
425
|
+
updatedAt?: number;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Summarize each delegation tree in a flat agent list to a table row.
|
|
429
|
+
* Rows come back in first-seen order; the caller sorts.
|
|
430
|
+
*/
|
|
431
|
+
export declare function summarizeSwarmRoots(agents: SwarmAgent[]): SwarmRootSummary[];
|
|
432
|
+
/**
|
|
433
|
+
* An agent and every transitive descendant, in tree order.
|
|
434
|
+
*
|
|
435
|
+
* The cascade selector: the reference runtime cancels SUBTREES (and cancels
|
|
436
|
+
* dependents when a dependency fails), so a host wiring `onCancel` calls this
|
|
437
|
+
* to know what a cancellation will take with it — and to filter it to
|
|
438
|
+
* `isSwarmAgentActive` for the confirm prompt's count.
|
|
439
|
+
*/
|
|
440
|
+
export declare function swarmSubtree(agents: SwarmAgent[], agentId: string): SwarmAgent[];
|