@wrongstack/core 0.277.2 → 0.280.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/{agent-bridge-BFJ2ODzI.d.ts → agent-bridge-DXC6QDJ4.d.ts} +1 -1
- package/dist/{agent-subagent-runner-BimKihiC.d.ts → agent-subagent-runner-PoqNKiR4.d.ts} +563 -471
- package/dist/{compactor-D3BGw26y.d.ts → compactor-U3agvUIG.d.ts} +1 -1
- package/dist/{config-DAOjriz9.d.ts → config-Cr3312zc.d.ts} +102 -4
- package/dist/coordination/index.d.ts +1087 -998
- package/dist/coordination/index.js +12235 -12052
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +31 -30
- package/dist/defaults/index.js +403 -189
- package/dist/defaults/index.js.map +1 -1
- package/dist/{brain-CCfuEOdp.d.ts → events-Bs2fmldo.d.ts} +117 -112
- package/dist/execution/index.d.ts +27 -19
- package/dist/execution/index.js +216 -63
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +1 -1
- package/dist/execution/prompt-enhancer.js.map +1 -1
- package/dist/extension/index.d.ts +8 -7
- package/dist/{global-mailbox-Dr4cTKqL.d.ts → global-mailbox-Ct7IorLJ.d.ts} +84 -6
- package/dist/{goal-store-C1uH4srH.d.ts → goal-store-C4F6DjC0.d.ts} +1 -1
- package/dist/hq/index.d.ts +504 -7
- package/dist/hq/index.js +1069 -20
- package/dist/hq/index.js.map +1 -1
- package/dist/{index-DJXj-dcr.d.ts → index-kidebiDh.d.ts} +8 -5
- package/dist/{index-cMEmzCVN.d.ts → index-nP09-oP2.d.ts} +2 -2
- package/dist/index.d.ts +153 -76
- package/dist/index.js +5791 -3163
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +7 -6
- package/dist/kernel/index.d.ts +14 -13
- package/dist/kernel/index.js +31 -15
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mailbox-types-DTl7bRH3.d.ts → mailbox-types-BGZWrYTJ.d.ts} +38 -0
- package/dist/{mcp-servers-CFb60-pH.d.ts → mcp-servers-D910X5_r.d.ts} +3 -3
- package/dist/models/index.d.ts +5 -5
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-5Ufn7f2m.d.ts → models-registry-CLkoOcHk.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-CcrcncvG.d.ts → multi-agent-coordinator-CieyUoEL.d.ts} +1 -1
- package/dist/{null-fleet-bus-C9KsYyrI.d.ts → null-fleet-bus-DkdmZJ_W.d.ts} +464 -464
- package/dist/observability/index.d.ts +3 -2
- package/dist/{path-resolver-CEeX9I7O.d.ts → path-resolver-XfZ9eLxG.d.ts} +3 -3
- package/dist/{permission-DbsGOA1C.d.ts → permission-Dx6dIqS2.d.ts} +2 -7
- package/dist/{permission-policy-BpEea3r7.d.ts → permission-policy-C8vJcnX5.d.ts} +2 -2
- package/dist/{pipeline-CEjBjzVA.d.ts → pipeline-BwAP21_4.d.ts} +9 -4
- package/dist/{provider-model-resolve-BpfXp3Jj.d.ts → provider-model-resolve-CwQNZWt_.d.ts} +3 -3
- package/dist/{provider-runner-CnOSr5BN.d.ts → provider-runner-CYHFImzV.d.ts} +3 -3
- package/dist/{retry-policy-Git9WF6d.d.ts → retry-policy-D4feSLk3.d.ts} +1 -1
- package/dist/sdd/index.d.ts +11 -10
- package/dist/sdd/index.js +2 -2
- package/dist/sdd/index.js.map +1 -1
- package/dist/secret-scrubber-3MHDDAtm.d.ts +6 -0
- package/dist/{secret-vault-DDSMHqIm.d.ts → secret-vault-CImt2XrR.d.ts} +1 -1
- package/dist/security/index.d.ts +6 -5
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-Cq72C0Oy.d.ts → selector-Dy-MzKp1.d.ts} +1 -1
- package/dist/{session-event-bridge-DG94B3Bk.d.ts → session-event-bridge-CqdiGnfU.d.ts} +1 -1
- package/dist/{session-reader-BzT-iMQT.d.ts → session-reader-Hk0WbNm9.d.ts} +1 -1
- package/dist/{skill-DGIXCtdv.d.ts → skill-DHniprNl.d.ts} +15 -1
- package/dist/skills/index.d.ts +472 -26
- package/dist/skills/index.js +872 -129
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/index.d.ts +27 -14
- package/dist/storage/index.js +264 -85
- package/dist/storage/index.js.map +1 -1
- package/dist/{strategy-compactor-Bt_ZH6R0.d.ts → strategy-compactor-CQwhbErd.d.ts} +32 -17
- package/dist/{todos-checkpoint-CH1pcua9.d.ts → todos-checkpoint-Bk2uP7Ex.d.ts} +6 -6
- package/dist/{context-DPlA6kid.d.ts → tool-BkOgs_KL.d.ts} +306 -286
- package/dist/{tool-executor-SVFq7IOR.d.ts → tool-executor-SiE1wlZo.d.ts} +9 -9
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/types/index.d.ts +22 -21
- package/dist/types/index.js +7 -9
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +30 -4
- package/dist/utils/index.js +50 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/{worktree-manager-C4YIf1Fa.d.ts → worktree-manager-BjOFF6bt.d.ts} +1 -1
- package/dist/{wstack-paths-_NrRovdr.d.ts → wstack-paths-CMl_cYgq.d.ts} +8 -0
- package/package.json +1 -1
- package/skills/mailbox-bridge/SKILL.md +1 -0
- package/skills/plugin-author/SKILL.md +350 -0
- package/skills/sdd/SKILL.md +134 -134
- package/skills/skill-creator/SKILL.md +45 -7
- package/skills/wrongstack-mailbox/SKILL.md +40 -21
|
@@ -1,141 +1,479 @@
|
|
|
1
|
-
import { c as ToolCallPipelinePayload, d as ToolWrapper, E as ExtensionRegistry, S as SystemPromptContributor, e as ToolRegistry, P as ProviderRegistry, A as AgentPipelines, f as ToolExecutorLike, g as AgentInit, h as AgentInput, R as RunResult } from './index-
|
|
2
|
-
import { C as Container, R as ReadonlyPipeline, a as Renderer } from './pipeline-
|
|
3
|
-
import { E as EventBus, a as EventName, L as Listener } from './
|
|
4
|
-
import { R as RetryPolicy, E as ErrorHandler } from './retry-policy-
|
|
1
|
+
import { c as ToolCallPipelinePayload, d as ToolWrapper, E as ExtensionRegistry, S as SystemPromptContributor, e as ToolRegistry, P as ProviderRegistry, A as AgentPipelines, f as ToolExecutorLike, g as AgentInit, h as AgentInput, R as RunResult } from './index-kidebiDh.js';
|
|
2
|
+
import { C as Container, R as ReadonlyPipeline, a as Renderer } from './pipeline-BwAP21_4.js';
|
|
3
|
+
import { E as EventBus, a as EventName, L as Listener } from './events-Bs2fmldo.js';
|
|
4
|
+
import { R as RetryPolicy, E as ErrorHandler } from './retry-policy-D4feSLk3.js';
|
|
5
5
|
import { L as Logger } from './logger-B63L5bTg.js';
|
|
6
6
|
import { T as Tracer } from './observability-D-HZN_mF.js';
|
|
7
|
-
import { P as PermissionPolicy } from './permission-
|
|
8
|
-
import {
|
|
9
|
-
import { W as WireFamily, H as HookEvent, f as HookMatcher, I as InProcessHook, C as Config } from './config-
|
|
7
|
+
import { P as PermissionPolicy } from './permission-Dx6dIqS2.js';
|
|
8
|
+
import { C as Context, J as JSONSchema, c as Request, d as Response, i as ContentBlock, s as TextBlock, T as Tool, P as Provider, v as RunOptions, U as Usage } from './tool-BkOgs_KL.js';
|
|
9
|
+
import { W as WireFamily, H as HookEvent, f as HookMatcher, I as InProcessHook, C as Config, M as ModelsRegistry, h as ModelRuntimeConfig } from './config-Cr3312zc.js';
|
|
10
|
+
import { b as Mailbox } from './mailbox-types-BGZWrYTJ.js';
|
|
11
|
+
|
|
12
|
+
type BridgeMessageType = 'task' | 'result' | 'progress' | 'error' | 'heartbeat' | 'stop' | 'delegate' | 'budget_threshold';
|
|
13
|
+
interface BridgeMessage<T = unknown> {
|
|
14
|
+
id: string;
|
|
15
|
+
type: BridgeMessageType;
|
|
16
|
+
from: string;
|
|
17
|
+
to?: string | undefined;
|
|
18
|
+
payload: T;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
priority?: 'low' | 'normal' | 'high' | 'critical' | undefined;
|
|
21
|
+
}
|
|
22
|
+
interface AgentBridgeConfig {
|
|
23
|
+
agentId: string;
|
|
24
|
+
coordinatorId: string;
|
|
25
|
+
timeoutMs?: number | undefined;
|
|
26
|
+
bufferSize?: number | undefined;
|
|
27
|
+
}
|
|
28
|
+
interface AgentBridge {
|
|
29
|
+
readonly agentId: string;
|
|
30
|
+
readonly coordinatorId: string;
|
|
31
|
+
send(msg: BridgeMessage): Promise<void>;
|
|
32
|
+
broadcast(msg: BridgeMessage): Promise<void>;
|
|
33
|
+
subscribe(handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
34
|
+
request<T>(msg: BridgeMessage, timeoutMs?: number): Promise<BridgeMessage<T>> | undefined;
|
|
35
|
+
stop(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
interface BridgeTransport {
|
|
38
|
+
send(msg: BridgeMessage, to: string): Promise<void>;
|
|
39
|
+
subscribe(agentId: string, handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
40
|
+
close(agentId: string): Promise<void>;
|
|
41
|
+
}
|
|
10
42
|
|
|
11
43
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `subagentId` so a single subscriber can multiplex across the fleet.
|
|
44
|
+
* A slash command registered with the CLI or available to plugins.
|
|
45
|
+
* Plugins receive a view of the registry via PluginAPI.slashCommands.
|
|
15
46
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `FleetBus.subscribe(id, handler)` to render a per-subagent panel.
|
|
47
|
+
* Commands registered by plugins use a namespaced name: `pluginName:commandName`.
|
|
48
|
+
* This prevents collisions with built-in commands and other plugins.
|
|
19
49
|
*/
|
|
20
|
-
interface
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
50
|
+
interface SlashCommand {
|
|
51
|
+
/** Unique command name. For plugins: `pluginName:commandName`. */
|
|
52
|
+
name: string;
|
|
53
|
+
/** Short aliases — also prefixed automatically: `pluginName:alias`. */
|
|
54
|
+
aliases?: string[] | undefined;
|
|
55
|
+
description: string;
|
|
56
|
+
/**
|
|
57
|
+
* Category used to group commands in the slash picker. Defaults to 'App'
|
|
58
|
+
* when omitted.
|
|
59
|
+
*/
|
|
60
|
+
category?: 'Run' | 'Session' | 'Inspect' | 'Agent' | 'Config' | 'App' | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Optional compact argument hint for interactive menus. This is not parsed
|
|
63
|
+
* by the registry; it only helps TUI/REPL surfaces show the expected shape,
|
|
64
|
+
* for example `[list|install <alias>|disable <name>]`.
|
|
65
|
+
*/
|
|
66
|
+
argsHint?: string | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Optional detailed help shown by `/help <name>`. Use this for usage,
|
|
69
|
+
* arguments, examples, side-effects — anything that doesn't fit in
|
|
70
|
+
* `description`. Renders verbatim, so format with line breaks.
|
|
71
|
+
* If absent, `/help <name>` falls back to `description`.
|
|
72
|
+
*/
|
|
73
|
+
help?: string | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* When true, this command does not appear in the slash-picker list
|
|
76
|
+
* triggered by typing `/` alone. It is still dispatchable and
|
|
77
|
+
* searchable when the user types a matching prefix (e.g. `/f`).
|
|
78
|
+
* Defaults to false.
|
|
79
|
+
*/
|
|
80
|
+
hidden?: boolean | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Execute the command.
|
|
83
|
+
* @param args Everything after the command name (trimmed by dispatch).
|
|
84
|
+
* @param ctx The current agent context.
|
|
85
|
+
* @returns `{ exit: true }` to quit the REPL. `{ message }` to print and
|
|
86
|
+
* continue. `{ runText }` to send a follow-up user-role message to the
|
|
87
|
+
* model immediately (e.g. `/steer <text>` builds a STEERING preamble
|
|
88
|
+
* here and asks the TUI to run it as the next turn). The TUI prints
|
|
89
|
+
* `message` first (if any) so the user sees the slash result before
|
|
90
|
+
* the model's response starts streaming. `{ metadata }` carries
|
|
91
|
+
* structured data for the REPL/TUI to act on (e.g. SDD session state).
|
|
92
|
+
*/
|
|
93
|
+
run(args: string, ctx?: Context | undefined): Promise<{
|
|
94
|
+
exit?: boolean | undefined;
|
|
95
|
+
message?: string | undefined;
|
|
96
|
+
runText?: string | undefined;
|
|
97
|
+
metadata?: Record<string, unknown>;
|
|
98
|
+
} | void>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface ToolRegistryView {
|
|
102
|
+
register(t: Tool): void;
|
|
103
|
+
unregister(name: string): void;
|
|
104
|
+
/** Wrap (decorate) an existing tool. The wrapper gets the current tool and returns the decorated version. */
|
|
105
|
+
wrap(name: string, wrapper: ToolWrapper): void;
|
|
106
|
+
get(name: string): Tool | undefined;
|
|
107
|
+
list(): Tool[];
|
|
108
|
+
}
|
|
109
|
+
interface ProviderFactory {
|
|
24
110
|
type: string;
|
|
25
|
-
|
|
111
|
+
family: WireFamily;
|
|
112
|
+
create(cfg: unknown): Provider;
|
|
113
|
+
}
|
|
114
|
+
interface ProviderRegistryView {
|
|
115
|
+
register(f: ProviderFactory): void;
|
|
116
|
+
unregister(type: string): boolean;
|
|
117
|
+
create(cfg: {
|
|
118
|
+
type: string;
|
|
119
|
+
} & Record<string, unknown>): Provider;
|
|
120
|
+
list(): string[];
|
|
121
|
+
}
|
|
122
|
+
interface MCPRegistryView {
|
|
123
|
+
start(cfg: unknown): Promise<void>;
|
|
124
|
+
stop(name: string): Promise<void>;
|
|
125
|
+
restart(name: string): Promise<void>;
|
|
126
|
+
list(): {
|
|
127
|
+
name: string;
|
|
128
|
+
state: string;
|
|
129
|
+
toolCount: number;
|
|
130
|
+
}[];
|
|
131
|
+
}
|
|
132
|
+
interface SlashCommandRegistryView {
|
|
133
|
+
register(cmd: SlashCommand): void;
|
|
134
|
+
unregister(name: string): boolean;
|
|
135
|
+
get(name: string): SlashCommand | undefined;
|
|
136
|
+
list(): SlashCommand[];
|
|
26
137
|
}
|
|
27
|
-
type FleetHandler = (event: FleetEvent) => void;
|
|
28
138
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* attribution. Detachment is automatic via the returned disposer — call
|
|
32
|
-
* it when a subagent terminates so we don't leak listeners.
|
|
139
|
+
* Read-only view of the session writer. Plugins can append custom events
|
|
140
|
+
* to the JSONL session log and read the transcript path.
|
|
33
141
|
*
|
|
34
|
-
* The
|
|
35
|
-
*
|
|
36
|
-
* compose — if you need a per-subagent + per-type slice, subscribe by
|
|
37
|
-
* type and filter on `event.subagentId` in your handler.
|
|
142
|
+
* The `append` method accepts any JSON-serializable payload — custom
|
|
143
|
+
* event types are persisted verbatim next to the built-in events.
|
|
38
144
|
*/
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
* `onPattern('*')`) to forward all events with subagent attribution, so
|
|
46
|
-
* new kernel event types are automatically forwarded without any manual
|
|
47
|
-
* registration. `subagent.*` events are excluded because they originate
|
|
48
|
-
* from MultiAgentHost on the parent bus, not the subagent's own bus.
|
|
49
|
-
*
|
|
50
|
-
* Returns a disposer that detaches every subscription; call on
|
|
51
|
-
* subagent teardown so the listeners don't outlive the run.
|
|
52
|
-
*/
|
|
53
|
-
attach(subagentId: string, bus: EventBus, taskId?: string): () => void;
|
|
54
|
-
/** Subscribe to every event from one subagent. */
|
|
55
|
-
subscribe(subagentId: string, handler: FleetHandler): () => void;
|
|
56
|
-
/** Subscribe to one event type across all subagents. */
|
|
57
|
-
filter(type: string, handler: FleetHandler): () => void;
|
|
58
|
-
/** Subscribe to literally everything. The fleet roll-up uses this. */
|
|
59
|
-
onAny(handler: FleetHandler): () => void;
|
|
60
|
-
emit(event: FleetEvent): void;
|
|
61
|
-
clear(): void;
|
|
145
|
+
interface SessionWriterView {
|
|
146
|
+
readonly transcriptPath?: string | undefined;
|
|
147
|
+
append(event: Record<string, unknown> & {
|
|
148
|
+
type: string;
|
|
149
|
+
ts: string;
|
|
150
|
+
}): Promise<void>;
|
|
62
151
|
}
|
|
63
152
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
153
|
+
* Metrics sink scoped to a plugin. The host auto-prefixes metric names
|
|
154
|
+
* with `plugin.<pluginName>.` so plugins don't need to namespace
|
|
155
|
+
* manually. Plugins call counter/histogram/gauge directly; the values
|
|
156
|
+
* flow to the host's MetricsSink (Prometheus, OTLP, or noop).
|
|
68
157
|
*/
|
|
69
|
-
interface
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
cacheRead: number;
|
|
74
|
-
cacheWrite: number;
|
|
75
|
-
cost: number;
|
|
76
|
-
};
|
|
77
|
-
perSubagent: Record<string, SubagentUsageSnapshot>;
|
|
78
|
-
}
|
|
79
|
-
interface SubagentUsageSnapshot {
|
|
80
|
-
subagentId: string;
|
|
81
|
-
provider?: string | undefined;
|
|
82
|
-
model?: string | undefined;
|
|
83
|
-
input: number;
|
|
84
|
-
output: number;
|
|
85
|
-
cacheRead: number;
|
|
86
|
-
cacheWrite: number;
|
|
87
|
-
cost: number;
|
|
88
|
-
toolCalls: number;
|
|
89
|
-
iterations: number;
|
|
90
|
-
startedAt: number;
|
|
91
|
-
lastEventAt: number;
|
|
158
|
+
interface MetricsSinkView {
|
|
159
|
+
counter(name: string, value?: number | undefined, labels?: Record<string, string>): void;
|
|
160
|
+
histogram(name: string, value: number, labels?: Record<string, string>): void;
|
|
161
|
+
gauge(name: string, value: number, labels?: Record<string, string>): void;
|
|
92
162
|
}
|
|
93
163
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* each subagent's per-token rates from the models registry.
|
|
164
|
+
* Options for a single `api.llm.complete()` call. Everything is
|
|
165
|
+
* optional — omitted fields fall back first to the plugin's own
|
|
166
|
+
* configured defaults (`config.extensions[<name>].llm`), then to the
|
|
167
|
+
* host session's provider/model.
|
|
99
168
|
*/
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
private readonly unsub;
|
|
106
|
-
constructor(bus: FleetBus, priceLookup?: ((subagentId: string, provider?: string | undefined, model?: string | undefined) => {
|
|
107
|
-
input?: number | undefined;
|
|
108
|
-
output?: number | undefined;
|
|
109
|
-
cacheRead?: number | undefined;
|
|
110
|
-
cacheWrite?: number | undefined;
|
|
111
|
-
} | undefined) | undefined, metaLookup?: ((subagentId: string) => {
|
|
112
|
-
provider?: string | undefined;
|
|
113
|
-
model?: string | undefined;
|
|
114
|
-
} | undefined) | undefined);
|
|
169
|
+
interface PluginLLMOptions {
|
|
170
|
+
/** System prompt for this call. */
|
|
171
|
+
system?: string | undefined;
|
|
172
|
+
/** Model override (e.g. `claude-haiku-4-5`). */
|
|
173
|
+
model?: string | undefined;
|
|
115
174
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
* entities that will never emit events again.
|
|
175
|
+
* Provider override by configured provider name (a key of
|
|
176
|
+
* `config.providers`, e.g. `anthropic`, `openai`, `omniroute`).
|
|
177
|
+
* When omitted the host session's provider is used.
|
|
120
178
|
*/
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
179
|
+
provider?: string | undefined;
|
|
180
|
+
/** Output-token cap. Default 2048, hard-capped by the host. */
|
|
181
|
+
maxTokens?: number | undefined;
|
|
182
|
+
temperature?: number | undefined;
|
|
183
|
+
/** `'json'` asks the provider for a JSON object response. */
|
|
184
|
+
responseFormat?: 'text' | 'json' | undefined;
|
|
185
|
+
/** Abort signal — plugins should pass one for cancellable work. */
|
|
186
|
+
signal?: AbortSignal | undefined;
|
|
187
|
+
}
|
|
188
|
+
interface PluginLLMResult {
|
|
189
|
+
/** Concatenated text blocks of the response. */
|
|
190
|
+
text: string;
|
|
191
|
+
/** The model that actually served the call. */
|
|
192
|
+
model: string;
|
|
193
|
+
/** The provider name the call was routed through. */
|
|
194
|
+
provider: string;
|
|
195
|
+
usage: {
|
|
196
|
+
input: number;
|
|
197
|
+
output: number;
|
|
198
|
+
};
|
|
199
|
+
stopReason: string;
|
|
130
200
|
}
|
|
131
|
-
|
|
132
|
-
type BudgetKind = 'tool_calls' | 'iterations' | 'tokens' | 'timeout' | 'idle_timeout' | 'cost';
|
|
133
201
|
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
202
|
+
* LLM access for plugins, routed through the host's provider layer —
|
|
203
|
+
* plugins never handle API keys themselves. Resolution order for
|
|
204
|
+
* provider/model on each call:
|
|
205
|
+
*
|
|
206
|
+
* 1. `PluginLLMOptions.provider` / `.model` (per call)
|
|
207
|
+
* 2. `config.extensions[<plugin>].llm.provider` / `.model` (per plugin)
|
|
208
|
+
* 3. the host session's active provider/model (default)
|
|
209
|
+
*
|
|
210
|
+
* Exposed as `api.llm` — `undefined` on minimal hosts (tests, the LSP
|
|
211
|
+
* server) that have no provider wired. Always guard:
|
|
212
|
+
* `if (!api.llm) return;`
|
|
213
|
+
*/
|
|
214
|
+
interface PluginLLM {
|
|
215
|
+
/** The effective defaults for this plugin (after config resolution). */
|
|
216
|
+
defaults(): {
|
|
217
|
+
provider: string;
|
|
218
|
+
model: string;
|
|
219
|
+
};
|
|
220
|
+
/** One-shot completion. Throws on provider errors. */
|
|
221
|
+
complete(prompt: string, opts?: PluginLLMOptions): Promise<PluginLLMResult>;
|
|
222
|
+
}
|
|
223
|
+
interface PluginPipelines {
|
|
224
|
+
request: ReadonlyPipeline<Request>;
|
|
225
|
+
response: ReadonlyPipeline<Response>;
|
|
226
|
+
toolCall: ReadonlyPipeline<ToolCallPipelinePayload>;
|
|
227
|
+
userInput: ReadonlyPipeline<{
|
|
228
|
+
content: ContentBlock[];
|
|
229
|
+
text: string;
|
|
230
|
+
ctx: Context;
|
|
231
|
+
}>;
|
|
232
|
+
assistantOutput: ReadonlyPipeline<TextBlock>;
|
|
233
|
+
contextWindow: ReadonlyPipeline<Context>;
|
|
234
|
+
[k: string]: ReadonlyPipeline<any>;
|
|
235
|
+
}
|
|
236
|
+
interface PluginAPI {
|
|
237
|
+
container: Container;
|
|
238
|
+
pipelines: PluginPipelines;
|
|
239
|
+
events: EventBus;
|
|
240
|
+
tools: ToolRegistryView;
|
|
241
|
+
providers: ProviderRegistryView;
|
|
242
|
+
mcp: MCPRegistryView;
|
|
243
|
+
slashCommands: SlashCommandRegistryView;
|
|
244
|
+
/** Live session writer — plugins can append custom events here. */
|
|
245
|
+
session: SessionWriterView;
|
|
246
|
+
/** Scoped metrics sink — counters/histograms/gauges auto-namespaced under `plugin.<name>.` */
|
|
247
|
+
metrics: MetricsSinkView;
|
|
248
|
+
/** Registry for agent lifecycle extensions — hooks like beforeRun, beforeIteration, onError, etc. */
|
|
249
|
+
extensions: ExtensionRegistry;
|
|
250
|
+
/**
|
|
251
|
+
* Register a system prompt contributor. Plugins call this to inject
|
|
252
|
+
* ephemeral TextBlocks into the system prompt on every build.
|
|
253
|
+
* Returns an unregister function.
|
|
254
|
+
*/
|
|
255
|
+
registerSystemPromptContributor(c: SystemPromptContributor): () => void;
|
|
256
|
+
/**
|
|
257
|
+
* Register an in-process lifecycle hook. `matcher` is a tool-name filter for
|
|
258
|
+
* `PreToolUse`/`PostToolUse` (`"Bash"`, `"edit|write"`, `"*"`) and ignored
|
|
259
|
+
* for other events. The hook can block, rewrite tool input, or inject extra
|
|
260
|
+
* context — see `HookOutcome`. Automatically removed when the plugin is
|
|
261
|
+
* uninstalled. Returns an unregister function.
|
|
262
|
+
*/
|
|
263
|
+
registerHook(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook): () => void;
|
|
264
|
+
config: Config;
|
|
265
|
+
log: Logger;
|
|
266
|
+
/**
|
|
267
|
+
* Register a one-time event listener. The handler is automatically removed
|
|
268
|
+
* after the first emission, or when the plugin is uninstalled — whichever
|
|
269
|
+
* comes first.
|
|
270
|
+
*/
|
|
271
|
+
onEvent<K extends EventName>(event: K, handler: Listener<K>): () => void;
|
|
272
|
+
/**
|
|
273
|
+
* Subscribe to all events matching a glob-style pattern.
|
|
274
|
+
* `'tool.*'` matches all tool events. `'*'` matches everything.
|
|
275
|
+
* Returns an unsubscribe function.
|
|
276
|
+
*/
|
|
277
|
+
onPattern(pattern: string, handler: (event: string, payload: unknown) => void): () => void;
|
|
278
|
+
/**
|
|
279
|
+
* Emit a custom event on the agent's EventBus. Use for inter-plugin
|
|
280
|
+
* communication or to surface plugin-specific state to the host.
|
|
281
|
+
*
|
|
282
|
+
* Custom events use a `pluginName:eventName` convention to avoid
|
|
283
|
+
* collisions with built-in events (e.g. `my-plugin:cache_hit`).
|
|
284
|
+
* The payload is passed through to all subscribers.
|
|
285
|
+
*/
|
|
286
|
+
emitCustom(event: string, payload: unknown): void;
|
|
287
|
+
/**
|
|
288
|
+
* Register a callback that fires when the configuration changes at
|
|
289
|
+
* runtime (e.g. via `/config` slash command or programmatic update).
|
|
290
|
+
* The handler receives the new and previous config snapshots.
|
|
291
|
+
* Returns an unsubscribe function.
|
|
292
|
+
*/
|
|
293
|
+
onConfigChange(handler: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
|
|
294
|
+
/**
|
|
295
|
+
* The models registry (models.dev-backed catalog of providers, models,
|
|
296
|
+
* and per-token pricing). Optional — some hosts may not construct one
|
|
297
|
+
* (e.g. minimal CLI invocations, tests). Plugins that need pricing
|
|
298
|
+
* data (cost-tracker, billing reports) should treat this as the
|
|
299
|
+
* preferred source when present and fall back to a bundled table
|
|
300
|
+
* otherwise.
|
|
301
|
+
*/
|
|
302
|
+
modelsRegistry?: ModelsRegistry | undefined;
|
|
303
|
+
/**
|
|
304
|
+
* The host's project-level mailbox. Optional — minimal hosts (tests,
|
|
305
|
+
* standalone CLI invocations, the LSP server) may not construct one.
|
|
306
|
+
* Plugins that publish status to other agents (todo-listener,
|
|
307
|
+
* session-recap) should treat this as the preferred source when present
|
|
308
|
+
* and gracefully no-op otherwise.
|
|
309
|
+
*/
|
|
310
|
+
mailbox?: Mailbox | undefined;
|
|
311
|
+
/**
|
|
312
|
+
* LLM access routed through the host's provider layer. Optional —
|
|
313
|
+
* minimal hosts without a wired provider omit it; plugins must guard
|
|
314
|
+
* (`if (!api.llm) …`). Per-plugin provider/model defaults come from
|
|
315
|
+
* `config.extensions[<name>].llm = { provider, model }`.
|
|
316
|
+
*/
|
|
317
|
+
llm?: PluginLLM | undefined;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Capability declaration — informs the host which subsystems a plugin
|
|
321
|
+
* intends to touch. Used for diagnostics and per-plugin enable/disable UX
|
|
322
|
+
* (e.g. "this plugin registers tools — disable to remove them"). Not
|
|
323
|
+
* enforced at runtime: a plugin that declares `tools: false` can still
|
|
324
|
+
* call `api.tools.register()`, but the host can flag the discrepancy.
|
|
325
|
+
*/
|
|
326
|
+
interface PluginCapabilities {
|
|
327
|
+
/** Will register tools via `api.tools.register()`. */
|
|
328
|
+
tools?: boolean | undefined;
|
|
329
|
+
/** Will register provider factories via `api.providers.register()`. */
|
|
330
|
+
providers?: boolean | undefined;
|
|
331
|
+
/**
|
|
332
|
+
* Pipelines the plugin hooks into. Use the standard names
|
|
333
|
+
* (`request | response | toolCall | userInput | assistantOutput | contextWindow`)
|
|
334
|
+
* or custom pipeline names exposed by other plugins.
|
|
335
|
+
*/
|
|
336
|
+
pipelines?: string[] | undefined;
|
|
337
|
+
/** Will register slash commands via `api.slashCommands.register()`. */
|
|
338
|
+
slashCommands?: boolean | undefined;
|
|
339
|
+
/** Will start MCP servers via `api.mcp.start()`. */
|
|
340
|
+
mcp?: boolean | undefined;
|
|
341
|
+
/**
|
|
342
|
+
* Capabilities required to mutate (wrap, unregister, override) tools
|
|
343
|
+
* the plugin does not own. If empty or omitted, the plugin may only
|
|
344
|
+
* mutate its own tools. Official plugins bypass this check.
|
|
345
|
+
*
|
|
346
|
+
* Example: `['fs.read', 'net.outbound']` allows the plugin to wrap
|
|
347
|
+
* read-only tools, but not `fs.write` or `shell.arbitrary` tools.
|
|
348
|
+
*/
|
|
349
|
+
toolMutateCapabilities?: string[] | undefined;
|
|
350
|
+
/**
|
|
351
|
+
* Will register in-process lifecycle hooks via `api.registerHook()`. When
|
|
352
|
+
* false (or omitted by a non-official plugin), the loader either logs a
|
|
353
|
+
* warning or throws — see `LoadPluginsOptions.enforceCapabilities`.
|
|
354
|
+
* Official plugins are not gated.
|
|
355
|
+
*/
|
|
356
|
+
hooks?: boolean | undefined;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Structured dependency declaration. The string form (`dependsOn: ['foo']`)
|
|
360
|
+
* is shorthand for `[{ name: 'foo' }]` — both work. Use the structured form
|
|
361
|
+
* when you need a version constraint:
|
|
362
|
+
*
|
|
363
|
+
* dependsOn: [{ name: 'wstack-auth', version: '^1.2.0' }]
|
|
364
|
+
*/
|
|
365
|
+
interface PluginDependency {
|
|
366
|
+
name: string;
|
|
367
|
+
/** npm-style semver range. Supports `^`, `~`, exact, and unprefixed. */
|
|
368
|
+
version?: string | undefined;
|
|
369
|
+
}
|
|
370
|
+
interface Plugin {
|
|
371
|
+
name: string;
|
|
372
|
+
version?: string | undefined;
|
|
373
|
+
/** One-line summary for `wstack plugins list` and error messages. */
|
|
374
|
+
description?: string | undefined;
|
|
375
|
+
/** Semver range against the kernel API version (KERNEL_API_VERSION). */
|
|
376
|
+
apiVersion: string;
|
|
377
|
+
/**
|
|
378
|
+
* Capability hints — what subsystems the plugin will register against.
|
|
379
|
+
* Optional; provided for diagnostics and UX. The loader does not enforce
|
|
380
|
+
* these, but mismatch is surfaced via logger at warn level.
|
|
381
|
+
*/
|
|
382
|
+
capabilities?: PluginCapabilities | undefined;
|
|
383
|
+
/**
|
|
384
|
+
* JSON Schema for the options under `Config.plugins[<name>].options`.
|
|
385
|
+
* When present, the loader validates that section before calling `setup`
|
|
386
|
+
* and rejects the plugin with a clear error path on failure.
|
|
387
|
+
*/
|
|
388
|
+
configSchema?: JSONSchema | undefined;
|
|
389
|
+
/**
|
|
390
|
+
* Mandatory plugin dependencies — loading fails if any are absent or
|
|
391
|
+
* version-incompatible. Accepts both the legacy string-array form and
|
|
392
|
+
* the structured form with version constraints.
|
|
393
|
+
*/
|
|
394
|
+
dependsOn?: (string | PluginDependency)[] | undefined;
|
|
395
|
+
/** Optional plugin dependencies — silently skipped if absent. */
|
|
396
|
+
optionalDeps?: (string | PluginDependency)[] | undefined;
|
|
397
|
+
conflictsWith?: string[] | undefined;
|
|
398
|
+
/**
|
|
399
|
+
* Default configuration values, deep-merged under the plugin's options
|
|
400
|
+
* key before `configSchema` validation. User-provided values take
|
|
401
|
+
* precedence over defaults — this is a fallback, not an override.
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* defaultConfig: { ttl: 3600, maxSize: 100 }
|
|
405
|
+
*/
|
|
406
|
+
defaultConfig?: Record<string, unknown>;
|
|
407
|
+
/**
|
|
408
|
+
* Called by the host to activate the plugin. Receives the `PluginAPI`
|
|
409
|
+
* and an optional `AbortSignal` the plugin should respect for
|
|
410
|
+
* cancellation and timeout. `setup` must complete before the plugin is
|
|
411
|
+
* considered loaded; if it times out the plugin is rejected.
|
|
412
|
+
*/
|
|
413
|
+
setup(api: PluginAPI, opts?: {
|
|
414
|
+
signal?: AbortSignal | undefined;
|
|
415
|
+
}): void | Promise<void>;
|
|
416
|
+
/**
|
|
417
|
+
* Called by the host during unload. Receives the same `PluginAPI` instance
|
|
418
|
+
* the plugin saw during `setup` and an optional `AbortSignal`. Teardown
|
|
419
|
+
* is best-effort — a timeout does not prevent other plugins from unloading.
|
|
420
|
+
*/
|
|
421
|
+
teardown?(api: PluginAPI, opts?: {
|
|
422
|
+
signal?: AbortSignal | undefined;
|
|
423
|
+
}): void | Promise<void>;
|
|
424
|
+
/**
|
|
425
|
+
* Optional health check. Called by the host (e.g. `/diag plugins` slash
|
|
426
|
+
* command or health endpoint) to surface plugin status. Return
|
|
427
|
+
* `{ ok: false, message: '...' }` when the plugin is degraded.
|
|
428
|
+
*/
|
|
429
|
+
health?(): Promise<{
|
|
430
|
+
ok: boolean;
|
|
431
|
+
message?: string | undefined;
|
|
432
|
+
}>;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
declare class Agent {
|
|
436
|
+
readonly container: Container;
|
|
437
|
+
readonly tools: ToolRegistry;
|
|
438
|
+
readonly providers: ProviderRegistry;
|
|
439
|
+
readonly events: EventBus;
|
|
440
|
+
readonly pipelines: AgentPipelines;
|
|
441
|
+
readonly ctx: Context;
|
|
442
|
+
/** Max agent-loop iterations per run. Mutable so the TUI `/settings` picker
|
|
443
|
+
* can apply a new value to the live session (takes effect next run). */
|
|
444
|
+
maxIterations: number;
|
|
445
|
+
readonly executionStrategy: 'parallel' | 'sequential' | 'smart';
|
|
446
|
+
readonly perIterationOutputCapBytes: number;
|
|
447
|
+
private readonly plugins;
|
|
448
|
+
readonly toolExecutor: ToolExecutorLike;
|
|
449
|
+
readonly autoExtendLimit: boolean;
|
|
450
|
+
private readonly autonomousContinue;
|
|
451
|
+
readonly tracer: Tracer | undefined;
|
|
452
|
+
readonly extensions: ExtensionRegistry;
|
|
453
|
+
private readonly _toolHandler;
|
|
454
|
+
private readonly _responseHandler;
|
|
455
|
+
private readonly _loopHandler;
|
|
456
|
+
private readonly _logger;
|
|
457
|
+
constructor(init: AgentInit);
|
|
458
|
+
get logger(): Logger;
|
|
459
|
+
get retry(): RetryPolicy;
|
|
460
|
+
get errorHandler(): ErrorHandler;
|
|
461
|
+
get permission(): PermissionPolicy;
|
|
462
|
+
get renderer(): Renderer | undefined;
|
|
463
|
+
disableInteractiveConfirmation(): void;
|
|
464
|
+
register(tool: Tool): void;
|
|
465
|
+
use(plugin: Plugin, api: PluginAPI): Promise<void>;
|
|
466
|
+
teardown(): Promise<void>;
|
|
467
|
+
run(userInput: AgentInput, opts?: RunOptions): Promise<RunResult>;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
type BudgetKind = 'tool_calls' | 'iterations' | 'tokens' | 'timeout' | 'idle_timeout' | 'cost';
|
|
471
|
+
/**
|
|
472
|
+
* Fraction of the wall-clock `timeoutMs` window at which a PROACTIVE extension
|
|
473
|
+
* is negotiated — BEFORE the deadline is actually crossed. The coordinator
|
|
474
|
+
* watchdog (`executeWithTimeout`) arms at `timeoutMs * TIMEOUT_PREEMPT_FRACTION`
|
|
475
|
+
* so a still-progressing subagent gets its ceiling raised while it is below the
|
|
476
|
+
* limit, and never enters a "timed out" state. Reactive enforcement at the real
|
|
139
477
|
* deadline still stands for the no-progress / denied case. Shared so the asking
|
|
140
478
|
* side and any future caller agree on the same lead point.
|
|
141
479
|
*/
|
|
@@ -450,37 +788,6 @@ declare class SubagentBudget {
|
|
|
450
788
|
usage(): BudgetUsage;
|
|
451
789
|
}
|
|
452
790
|
|
|
453
|
-
type BridgeMessageType = 'task' | 'result' | 'progress' | 'error' | 'heartbeat' | 'stop' | 'delegate' | 'budget_threshold';
|
|
454
|
-
interface BridgeMessage<T = unknown> {
|
|
455
|
-
id: string;
|
|
456
|
-
type: BridgeMessageType;
|
|
457
|
-
from: string;
|
|
458
|
-
to?: string | undefined;
|
|
459
|
-
payload: T;
|
|
460
|
-
timestamp: number;
|
|
461
|
-
priority?: 'low' | 'normal' | 'high' | 'critical' | undefined;
|
|
462
|
-
}
|
|
463
|
-
interface AgentBridgeConfig {
|
|
464
|
-
agentId: string;
|
|
465
|
-
coordinatorId: string;
|
|
466
|
-
timeoutMs?: number | undefined;
|
|
467
|
-
bufferSize?: number | undefined;
|
|
468
|
-
}
|
|
469
|
-
interface AgentBridge {
|
|
470
|
-
readonly agentId: string;
|
|
471
|
-
readonly coordinatorId: string;
|
|
472
|
-
send(msg: BridgeMessage): Promise<void>;
|
|
473
|
-
broadcast(msg: BridgeMessage): Promise<void>;
|
|
474
|
-
subscribe(handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
475
|
-
request<T>(msg: BridgeMessage, timeoutMs?: number): Promise<BridgeMessage<T>> | undefined;
|
|
476
|
-
stop(): Promise<void>;
|
|
477
|
-
}
|
|
478
|
-
interface BridgeTransport {
|
|
479
|
-
send(msg: BridgeMessage, to: string): Promise<void>;
|
|
480
|
-
subscribe(agentId: string, handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
481
|
-
close(agentId: string): Promise<void>;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
791
|
interface SubagentConfig {
|
|
485
792
|
id?: string | undefined;
|
|
486
793
|
name: string;
|
|
@@ -552,6 +859,13 @@ interface SubagentConfig {
|
|
|
552
859
|
* → the factory's own default fallback behavior (usually the leader's config).
|
|
553
860
|
*/
|
|
554
861
|
fallbackModels?: string[] | undefined;
|
|
862
|
+
/**
|
|
863
|
+
* Runtime request overrides for THIS subagent. When present, these are merged
|
|
864
|
+
* over the leader's `Config.modelRuntime` before the subagent request pipeline
|
|
865
|
+
* maps reasoning/cache/parameters onto provider requests. Used by the model
|
|
866
|
+
* matrix to give roles their own reasoning effort without changing the leader.
|
|
867
|
+
*/
|
|
868
|
+
modelRuntime?: ModelRuntimeConfig | undefined;
|
|
555
869
|
/**
|
|
556
870
|
* Per-subagent session JSONL path. When omitted the orchestrator-
|
|
557
871
|
* supplied factory derives a path under `<sessionRoot>/<runId>/`.
|
|
@@ -813,346 +1127,124 @@ interface SubagentContext {
|
|
|
813
1127
|
}
|
|
814
1128
|
|
|
815
1129
|
/**
|
|
816
|
-
*
|
|
817
|
-
*
|
|
1130
|
+
* Single fleet-wide event with subagent attribution. Whatever a child
|
|
1131
|
+
* agent emits on its own EventBus gets re-published here, prefixed with
|
|
1132
|
+
* `subagentId` so a single subscriber can multiplex across the fleet.
|
|
818
1133
|
*
|
|
819
|
-
*
|
|
820
|
-
*
|
|
1134
|
+
* The director uses `FleetBus.filter('tool.executed', …)` to see every
|
|
1135
|
+
* tool call across the fleet; the TUI uses
|
|
1136
|
+
* `FleetBus.subscribe(id, handler)` to render a per-subagent panel.
|
|
821
1137
|
*/
|
|
822
|
-
interface
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
aliases?: string[] | undefined;
|
|
827
|
-
description: string;
|
|
828
|
-
/**
|
|
829
|
-
* Category used to group commands in the slash picker. Defaults to 'App'
|
|
830
|
-
* when omitted.
|
|
831
|
-
*/
|
|
832
|
-
category?: 'Run' | 'Session' | 'Inspect' | 'Agent' | 'Config' | 'App' | undefined;
|
|
833
|
-
/**
|
|
834
|
-
* Optional compact argument hint for interactive menus. This is not parsed
|
|
835
|
-
* by the registry; it only helps TUI/REPL surfaces show the expected shape,
|
|
836
|
-
* for example `[list|install <alias>|disable <name>]`.
|
|
837
|
-
*/
|
|
838
|
-
argsHint?: string | undefined;
|
|
839
|
-
/**
|
|
840
|
-
* Optional detailed help shown by `/help <name>`. Use this for usage,
|
|
841
|
-
* arguments, examples, side-effects — anything that doesn't fit in
|
|
842
|
-
* `description`. Renders verbatim, so format with line breaks.
|
|
843
|
-
* If absent, `/help <name>` falls back to `description`.
|
|
844
|
-
*/
|
|
845
|
-
help?: string | undefined;
|
|
846
|
-
/**
|
|
847
|
-
* When true, this command does not appear in the slash-picker list
|
|
848
|
-
* triggered by typing `/` alone. It is still dispatchable and
|
|
849
|
-
* searchable when the user types a matching prefix (e.g. `/f`).
|
|
850
|
-
* Defaults to false.
|
|
851
|
-
*/
|
|
852
|
-
hidden?: boolean | undefined;
|
|
853
|
-
/**
|
|
854
|
-
* Execute the command.
|
|
855
|
-
* @param args Everything after the command name (trimmed by dispatch).
|
|
856
|
-
* @param ctx The current agent context.
|
|
857
|
-
* @returns `{ exit: true }` to quit the REPL. `{ message }` to print and
|
|
858
|
-
* continue. `{ runText }` to send a follow-up user-role message to the
|
|
859
|
-
* model immediately (e.g. `/steer <text>` builds a STEERING preamble
|
|
860
|
-
* here and asks the TUI to run it as the next turn). The TUI prints
|
|
861
|
-
* `message` first (if any) so the user sees the slash result before
|
|
862
|
-
* the model's response starts streaming. `{ metadata }` carries
|
|
863
|
-
* structured data for the REPL/TUI to act on (e.g. SDD session state).
|
|
864
|
-
*/
|
|
865
|
-
run(args: string, ctx?: Context | undefined): Promise<{
|
|
866
|
-
exit?: boolean | undefined;
|
|
867
|
-
message?: string | undefined;
|
|
868
|
-
runText?: string | undefined;
|
|
869
|
-
metadata?: Record<string, unknown>;
|
|
870
|
-
} | void>;
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
interface ToolRegistryView {
|
|
874
|
-
register(t: Tool): void;
|
|
875
|
-
unregister(name: string): void;
|
|
876
|
-
/** Wrap (decorate) an existing tool. The wrapper gets the current tool and returns the decorated version. */
|
|
877
|
-
wrap(name: string, wrapper: ToolWrapper): void;
|
|
878
|
-
get(name: string): Tool | undefined;
|
|
879
|
-
list(): Tool[];
|
|
880
|
-
}
|
|
881
|
-
interface ProviderFactory {
|
|
1138
|
+
interface FleetEvent {
|
|
1139
|
+
subagentId: string;
|
|
1140
|
+
taskId?: string | undefined;
|
|
1141
|
+
ts: number;
|
|
882
1142
|
type: string;
|
|
883
|
-
|
|
884
|
-
create(cfg: unknown): Provider;
|
|
885
|
-
}
|
|
886
|
-
interface ProviderRegistryView {
|
|
887
|
-
register(f: ProviderFactory): void;
|
|
888
|
-
unregister(type: string): boolean;
|
|
889
|
-
create(cfg: {
|
|
890
|
-
type: string;
|
|
891
|
-
} & Record<string, unknown>): Provider;
|
|
892
|
-
list(): string[];
|
|
893
|
-
}
|
|
894
|
-
interface MCPRegistryView {
|
|
895
|
-
start(cfg: unknown): Promise<void>;
|
|
896
|
-
stop(name: string): Promise<void>;
|
|
897
|
-
restart(name: string): Promise<void>;
|
|
898
|
-
list(): {
|
|
899
|
-
name: string;
|
|
900
|
-
state: string;
|
|
901
|
-
toolCount: number;
|
|
902
|
-
}[];
|
|
903
|
-
}
|
|
904
|
-
interface SlashCommandRegistryView {
|
|
905
|
-
register(cmd: SlashCommand): void;
|
|
906
|
-
unregister(name: string): boolean;
|
|
907
|
-
get(name: string): SlashCommand | undefined;
|
|
908
|
-
list(): SlashCommand[];
|
|
1143
|
+
payload: unknown;
|
|
909
1144
|
}
|
|
1145
|
+
type FleetHandler = (event: FleetEvent) => void;
|
|
910
1146
|
/**
|
|
911
|
-
*
|
|
912
|
-
*
|
|
1147
|
+
* Fan-in for per-subagent EventBuses. Each subagent's bus is plugged in
|
|
1148
|
+
* via `attach()`; the FleetBus re-emits every event with subagent
|
|
1149
|
+
* attribution. Detachment is automatic via the returned disposer — call
|
|
1150
|
+
* it when a subagent terminates so we don't leak listeners.
|
|
913
1151
|
*
|
|
914
|
-
* The
|
|
915
|
-
*
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
readonly transcriptPath?: string | undefined;
|
|
919
|
-
append(event: Record<string, unknown> & {
|
|
920
|
-
type: string;
|
|
921
|
-
ts: string;
|
|
922
|
-
}): Promise<void>;
|
|
923
|
-
}
|
|
924
|
-
/**
|
|
925
|
-
* Metrics sink scoped to a plugin. The host auto-prefixes metric names
|
|
926
|
-
* with `plugin.<pluginName>.` so plugins don't need to namespace
|
|
927
|
-
* manually. Plugins call counter/histogram/gauge directly; the values
|
|
928
|
-
* flow to the host's MetricsSink (Prometheus, OTLP, or noop).
|
|
1152
|
+
* The bus exposes two subscription modes: by `subagentId` (everything
|
|
1153
|
+
* from one child) and by `type` (one event-type across the fleet). They
|
|
1154
|
+
* compose — if you need a per-subagent + per-type slice, subscribe by
|
|
1155
|
+
* type and filter on `event.subagentId` in your handler.
|
|
929
1156
|
*/
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
}
|
|
935
|
-
interface PluginPipelines {
|
|
936
|
-
request: ReadonlyPipeline<Request>;
|
|
937
|
-
response: ReadonlyPipeline<Response>;
|
|
938
|
-
toolCall: ReadonlyPipeline<ToolCallPipelinePayload>;
|
|
939
|
-
userInput: ReadonlyPipeline<{
|
|
940
|
-
content: ContentBlock[];
|
|
941
|
-
text: string;
|
|
942
|
-
ctx: Context;
|
|
943
|
-
}>;
|
|
944
|
-
assistantOutput: ReadonlyPipeline<TextBlock>;
|
|
945
|
-
contextWindow: ReadonlyPipeline<Context>;
|
|
946
|
-
[k: string]: ReadonlyPipeline<any>;
|
|
947
|
-
}
|
|
948
|
-
interface PluginAPI {
|
|
949
|
-
container: Container;
|
|
950
|
-
pipelines: PluginPipelines;
|
|
951
|
-
events: EventBus;
|
|
952
|
-
tools: ToolRegistryView;
|
|
953
|
-
providers: ProviderRegistryView;
|
|
954
|
-
mcp: MCPRegistryView;
|
|
955
|
-
slashCommands: SlashCommandRegistryView;
|
|
956
|
-
/** Live session writer — plugins can append custom events here. */
|
|
957
|
-
session: SessionWriterView;
|
|
958
|
-
/** Scoped metrics sink — counters/histograms/gauges auto-namespaced under `plugin.<name>.` */
|
|
959
|
-
metrics: MetricsSinkView;
|
|
960
|
-
/** Registry for agent lifecycle extensions — hooks like beforeRun, beforeIteration, onError, etc. */
|
|
961
|
-
extensions: ExtensionRegistry;
|
|
962
|
-
/**
|
|
963
|
-
* Register a system prompt contributor. Plugins call this to inject
|
|
964
|
-
* ephemeral TextBlocks into the system prompt on every build.
|
|
965
|
-
* Returns an unregister function.
|
|
966
|
-
*/
|
|
967
|
-
registerSystemPromptContributor(c: SystemPromptContributor): () => void;
|
|
968
|
-
/**
|
|
969
|
-
* Register an in-process lifecycle hook. `matcher` is a tool-name filter for
|
|
970
|
-
* `PreToolUse`/`PostToolUse` (`"Bash"`, `"edit|write"`, `"*"`) and ignored
|
|
971
|
-
* for other events. The hook can block, rewrite tool input, or inject extra
|
|
972
|
-
* context — see `HookOutcome`. Automatically removed when the plugin is
|
|
973
|
-
* uninstalled. Returns an unregister function.
|
|
974
|
-
*/
|
|
975
|
-
registerHook(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook): () => void;
|
|
976
|
-
config: Config;
|
|
977
|
-
log: Logger;
|
|
978
|
-
/**
|
|
979
|
-
* Register a one-time event listener. The handler is automatically removed
|
|
980
|
-
* after the first emission, or when the plugin is uninstalled — whichever
|
|
981
|
-
* comes first.
|
|
982
|
-
*/
|
|
983
|
-
onEvent<K extends EventName>(event: K, handler: Listener<K>): () => void;
|
|
984
|
-
/**
|
|
985
|
-
* Subscribe to all events matching a glob-style pattern.
|
|
986
|
-
* `'tool.*'` matches all tool events. `'*'` matches everything.
|
|
987
|
-
* Returns an unsubscribe function.
|
|
988
|
-
*/
|
|
989
|
-
onPattern(pattern: string, handler: (event: string, payload: unknown) => void): () => void;
|
|
1157
|
+
declare class FleetBus {
|
|
1158
|
+
private readonly byId;
|
|
1159
|
+
private readonly byType;
|
|
1160
|
+
private readonly any;
|
|
990
1161
|
/**
|
|
991
|
-
*
|
|
992
|
-
*
|
|
1162
|
+
* Hook a subagent's EventBus into the fleet. Uses `onAny()` (an alias for
|
|
1163
|
+
* `onPattern('*')`) to forward all events with subagent attribution, so
|
|
1164
|
+
* new kernel event types are automatically forwarded without any manual
|
|
1165
|
+
* registration. `subagent.*` events are excluded because they originate
|
|
1166
|
+
* from MultiAgentHost on the parent bus, not the subagent's own bus.
|
|
993
1167
|
*
|
|
994
|
-
*
|
|
995
|
-
*
|
|
996
|
-
* The payload is passed through to all subscribers.
|
|
997
|
-
*/
|
|
998
|
-
emitCustom(event: string, payload: unknown): void;
|
|
999
|
-
/**
|
|
1000
|
-
* Register a callback that fires when the configuration changes at
|
|
1001
|
-
* runtime (e.g. via `/config` slash command or programmatic update).
|
|
1002
|
-
* The handler receives the new and previous config snapshots.
|
|
1003
|
-
* Returns an unsubscribe function.
|
|
1168
|
+
* Returns a disposer that detaches every subscription; call on
|
|
1169
|
+
* subagent teardown so the listeners don't outlive the run.
|
|
1004
1170
|
*/
|
|
1005
|
-
|
|
1171
|
+
attach(subagentId: string, bus: EventBus, taskId?: string): () => void;
|
|
1172
|
+
/** Subscribe to every event from one subagent. */
|
|
1173
|
+
subscribe(subagentId: string, handler: FleetHandler): () => void;
|
|
1174
|
+
/** Subscribe to one event type across all subagents. */
|
|
1175
|
+
filter(type: string, handler: FleetHandler): () => void;
|
|
1176
|
+
/** Subscribe to literally everything. The fleet roll-up uses this. */
|
|
1177
|
+
onAny(handler: FleetHandler): () => void;
|
|
1178
|
+
emit(event: FleetEvent): void;
|
|
1179
|
+
clear(): void;
|
|
1006
1180
|
}
|
|
1007
1181
|
/**
|
|
1008
|
-
*
|
|
1009
|
-
*
|
|
1010
|
-
*
|
|
1011
|
-
*
|
|
1012
|
-
* call `api.tools.register()`, but the host can flag the discrepancy.
|
|
1182
|
+
* Roll-up of token usage + cost across an entire director run. The
|
|
1183
|
+
* director's `fleet` tool returns this so the model can reason
|
|
1184
|
+
* about budget in its next turn ("the researcher already burned $0.40,
|
|
1185
|
+
* lean on summaries for the next task").
|
|
1013
1186
|
*/
|
|
1014
|
-
interface
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
toolMutateCapabilities?: string[] | undefined;
|
|
1038
|
-
/**
|
|
1039
|
-
* Will register in-process lifecycle hooks via `api.registerHook()`. When
|
|
1040
|
-
* false (or omitted by a non-official plugin), the loader either logs a
|
|
1041
|
-
* warning or throws — see `LoadPluginsOptions.enforceCapabilities`.
|
|
1042
|
-
* Official plugins are not gated.
|
|
1043
|
-
*/
|
|
1044
|
-
hooks?: boolean | undefined;
|
|
1187
|
+
interface FleetUsage {
|
|
1188
|
+
total: {
|
|
1189
|
+
input: number;
|
|
1190
|
+
output: number;
|
|
1191
|
+
cacheRead: number;
|
|
1192
|
+
cacheWrite: number;
|
|
1193
|
+
cost: number;
|
|
1194
|
+
};
|
|
1195
|
+
perSubagent: Record<string, SubagentUsageSnapshot>;
|
|
1196
|
+
}
|
|
1197
|
+
interface SubagentUsageSnapshot {
|
|
1198
|
+
subagentId: string;
|
|
1199
|
+
provider?: string | undefined;
|
|
1200
|
+
model?: string | undefined;
|
|
1201
|
+
input: number;
|
|
1202
|
+
output: number;
|
|
1203
|
+
cacheRead: number;
|
|
1204
|
+
cacheWrite: number;
|
|
1205
|
+
cost: number;
|
|
1206
|
+
toolCalls: number;
|
|
1207
|
+
iterations: number;
|
|
1208
|
+
startedAt: number;
|
|
1209
|
+
lastEventAt: number;
|
|
1045
1210
|
}
|
|
1046
1211
|
/**
|
|
1047
|
-
*
|
|
1048
|
-
*
|
|
1049
|
-
*
|
|
1050
|
-
*
|
|
1051
|
-
*
|
|
1212
|
+
* Aggregates provider.response + tool.executed events from the FleetBus
|
|
1213
|
+
* into a live `FleetUsage` snapshot. Costs are computed by the caller
|
|
1214
|
+
* via a `priceLookup(subagentId)` so we don't bake provider-pricing
|
|
1215
|
+
* coupling into core; the CLI/tests supply a function that resolves
|
|
1216
|
+
* each subagent's per-token rates from the models registry.
|
|
1052
1217
|
*/
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
* these, but mismatch is surfaced via logger at warn level.
|
|
1069
|
-
*/
|
|
1070
|
-
capabilities?: PluginCapabilities | undefined;
|
|
1071
|
-
/**
|
|
1072
|
-
* JSON Schema for the options under `Config.plugins[<name>].options`.
|
|
1073
|
-
* When present, the loader validates that section before calling `setup`
|
|
1074
|
-
* and rejects the plugin with a clear error path on failure.
|
|
1075
|
-
*/
|
|
1076
|
-
configSchema?: JSONSchema | undefined;
|
|
1077
|
-
/**
|
|
1078
|
-
* Mandatory plugin dependencies — loading fails if any are absent or
|
|
1079
|
-
* version-incompatible. Accepts both the legacy string-array form and
|
|
1080
|
-
* the structured form with version constraints.
|
|
1081
|
-
*/
|
|
1082
|
-
dependsOn?: (string | PluginDependency)[] | undefined;
|
|
1083
|
-
/** Optional plugin dependencies — silently skipped if absent. */
|
|
1084
|
-
optionalDeps?: (string | PluginDependency)[] | undefined;
|
|
1085
|
-
conflictsWith?: string[] | undefined;
|
|
1086
|
-
/**
|
|
1087
|
-
* Default configuration values, deep-merged under the plugin's options
|
|
1088
|
-
* key before `configSchema` validation. User-provided values take
|
|
1089
|
-
* precedence over defaults — this is a fallback, not an override.
|
|
1090
|
-
*
|
|
1091
|
-
* @example
|
|
1092
|
-
* defaultConfig: { ttl: 3600, maxSize: 100 }
|
|
1093
|
-
*/
|
|
1094
|
-
defaultConfig?: Record<string, unknown>;
|
|
1095
|
-
/**
|
|
1096
|
-
* Called by the host to activate the plugin. Receives the `PluginAPI`
|
|
1097
|
-
* and an optional `AbortSignal` the plugin should respect for
|
|
1098
|
-
* cancellation and timeout. `setup` must complete before the plugin is
|
|
1099
|
-
* considered loaded; if it times out the plugin is rejected.
|
|
1100
|
-
*/
|
|
1101
|
-
setup(api: PluginAPI, opts?: {
|
|
1102
|
-
signal?: AbortSignal | undefined;
|
|
1103
|
-
}): void | Promise<void>;
|
|
1104
|
-
/**
|
|
1105
|
-
* Called by the host during unload. Receives the same `PluginAPI` instance
|
|
1106
|
-
* the plugin saw during `setup` and an optional `AbortSignal`. Teardown
|
|
1107
|
-
* is best-effort — a timeout does not prevent other plugins from unloading.
|
|
1108
|
-
*/
|
|
1109
|
-
teardown?(api: PluginAPI, opts?: {
|
|
1110
|
-
signal?: AbortSignal | undefined;
|
|
1111
|
-
}): void | Promise<void>;
|
|
1218
|
+
declare class FleetUsageAggregator {
|
|
1219
|
+
private readonly priceLookup?;
|
|
1220
|
+
private readonly metaLookup?;
|
|
1221
|
+
private readonly perSubagent;
|
|
1222
|
+
private readonly total;
|
|
1223
|
+
private readonly unsub;
|
|
1224
|
+
constructor(bus: FleetBus, priceLookup?: ((subagentId: string, provider?: string | undefined, model?: string | undefined) => {
|
|
1225
|
+
input?: number | undefined;
|
|
1226
|
+
output?: number | undefined;
|
|
1227
|
+
cacheRead?: number | undefined;
|
|
1228
|
+
cacheWrite?: number | undefined;
|
|
1229
|
+
} | undefined) | undefined, metaLookup?: ((subagentId: string) => {
|
|
1230
|
+
provider?: string | undefined;
|
|
1231
|
+
model?: string | undefined;
|
|
1232
|
+
} | undefined) | undefined);
|
|
1112
1233
|
/**
|
|
1113
|
-
*
|
|
1114
|
-
*
|
|
1115
|
-
*
|
|
1234
|
+
* Remove a terminated subagent's data from the aggregator and subtract its
|
|
1235
|
+
* contribution from the running totals. Call this when a subagent is removed
|
|
1236
|
+
* from the fleet so the aggregator doesn't accumulate unbounded data for
|
|
1237
|
+
* entities that will never emit events again.
|
|
1116
1238
|
*/
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
readonly providers: ProviderRegistry;
|
|
1127
|
-
readonly events: EventBus;
|
|
1128
|
-
readonly pipelines: AgentPipelines;
|
|
1129
|
-
readonly ctx: Context;
|
|
1130
|
-
/** Max agent-loop iterations per run. Mutable so the TUI `/settings` picker
|
|
1131
|
-
* can apply a new value to the live session (takes effect next run). */
|
|
1132
|
-
maxIterations: number;
|
|
1133
|
-
readonly executionStrategy: 'parallel' | 'sequential' | 'smart';
|
|
1134
|
-
readonly perIterationOutputCapBytes: number;
|
|
1135
|
-
private readonly plugins;
|
|
1136
|
-
readonly toolExecutor: ToolExecutorLike;
|
|
1137
|
-
readonly autoExtendLimit: boolean;
|
|
1138
|
-
private readonly autonomousContinue;
|
|
1139
|
-
readonly tracer: Tracer | undefined;
|
|
1140
|
-
readonly extensions: ExtensionRegistry;
|
|
1141
|
-
private readonly _toolHandler;
|
|
1142
|
-
private readonly _responseHandler;
|
|
1143
|
-
private readonly _loopHandler;
|
|
1144
|
-
private readonly _logger;
|
|
1145
|
-
constructor(init: AgentInit);
|
|
1146
|
-
get logger(): Logger;
|
|
1147
|
-
get retry(): RetryPolicy;
|
|
1148
|
-
get errorHandler(): ErrorHandler;
|
|
1149
|
-
get permission(): PermissionPolicy;
|
|
1150
|
-
get renderer(): Renderer | undefined;
|
|
1151
|
-
disableInteractiveConfirmation(): void;
|
|
1152
|
-
register(tool: Tool): void;
|
|
1153
|
-
use(plugin: Plugin, api: PluginAPI): Promise<void>;
|
|
1154
|
-
teardown(): Promise<void>;
|
|
1155
|
-
run(userInput: AgentInput, opts?: RunOptions): Promise<RunResult>;
|
|
1239
|
+
removeSubagent(subagentId: string): void;
|
|
1240
|
+
/** Disposes all fleet-bus subscriptions. Call when the aggregator is no longer needed. */
|
|
1241
|
+
dispose(): void;
|
|
1242
|
+
/** Live snapshot — safe to call from a tool's execute() body. */
|
|
1243
|
+
snapshot(): FleetUsage;
|
|
1244
|
+
private ensure;
|
|
1245
|
+
private onProviderResponse;
|
|
1246
|
+
private onToolExecuted;
|
|
1247
|
+
private onIterationStarted;
|
|
1156
1248
|
}
|
|
1157
1249
|
|
|
1158
1250
|
/**
|
|
@@ -1225,4 +1317,4 @@ interface AgentRunnerOptions {
|
|
|
1225
1317
|
*/
|
|
1226
1318
|
declare function makeAgentSubagentRunner(opts: AgentRunnerOptions): SubagentRunner;
|
|
1227
1319
|
|
|
1228
|
-
export { type
|
|
1320
|
+
export { type SubagentRunOutcome as $, type AgentBridge as A, type BridgeTransport as B, type CoordinatorStatus as C, type DoneCondition as D, type BudgetKind as E, FleetBus as F, type BudgetLimits as G, type BudgetNegotiationMode as H, type BudgetThresholdDecision as I, type BudgetThresholdHandler as J, BudgetThresholdSignal as K, type BudgetUsage as L, type MultiAgentCoordinator as M, type CoordinatorEvents as N, DECISION_TIMEOUT_MS as O, type PluginAPI as P, type FleetEvent as Q, type FleetHandler as R, type SubagentConfig as S, type TaskSpec as T, type PluginLLMOptions as U, type PluginLLMResult as V, SubagentBudget as W, type SubagentContext as X, type SubagentError as Y, type SubagentErrorKind as Z, type SubagentRunContext as _, type BridgeMessage as a, type SubagentUsageSnapshot as a0, TIMEOUT_PREEMPT_FRACTION as a1, type TaskDelegation as a2, makeAgentSubagentRunner as a3, withDisabledToolFiltering as a4, type ProviderFactory as a5, type AgentBridgeConfig as b, type MultiAgentConfig as c, type SubagentRunner as d, type BudgetSessionIdSource as e, type SpawnResult as f, type TaskResult as g, Agent as h, type AgentFactory as i, type FleetUsage as j, FleetUsageAggregator as k, type SlashCommand as l, type PluginPipelines as m, type ToolRegistryView as n, type ProviderRegistryView as o, type MCPRegistryView as p, type SlashCommandRegistryView as q, type SessionWriterView as r, type MetricsSinkView as s, type PluginLLM as t, type PluginCapabilities as u, type PluginDependency as v, type Plugin as w, type AgentFactoryResult as x, type AgentRunnerOptions as y, BudgetExceededError as z };
|