@wrongstack/core 0.87.0 → 0.89.3
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-C9P_HPez.d.ts → agent-bridge-DbVe1dHT.d.ts} +1 -1
- package/dist/{agent-subagent-runner-2Aq0jOSj.d.ts → agent-subagent-runner-C6eqID1t.d.ts} +477 -476
- package/dist/{events-DnRqXaZ3.d.ts → brain-s9DyD_Vf.d.ts} +185 -92
- package/dist/{compactor-CJq7LQev.d.ts → compactor-DXLxLcmU.d.ts} +2 -2
- package/dist/{config-_DZ7dN-T.d.ts → config-84VaZpH6.d.ts} +45 -38
- package/dist/{context-ToHAp4-U.d.ts → context-CNRYfhUv.d.ts} +1 -1
- package/dist/coordination/index.d.ts +16 -17
- package/dist/coordination/index.js +208 -93
- package/dist/coordination/index.js.map +1 -1
- package/dist/{default-config-DEXI4jsl.d.ts → default-config-CXsDvOmP.d.ts} +3 -1
- package/dist/defaults/index.d.ts +32 -34
- package/dist/defaults/index.js +744 -274
- package/dist/defaults/index.js.map +1 -1
- package/dist/{director-state-CgIc30qi.d.ts → director-state-BfeCUbmk.d.ts} +1 -1
- package/dist/execution/index.d.ts +18 -19
- package/dist/execution/index.js +79 -64
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +9 -10
- package/dist/extension/index.js +8 -6
- package/dist/extension/index.js.map +1 -1
- package/dist/{index-BNOLadHw.d.ts → index-CqrroYcU.d.ts} +13 -15
- package/dist/{index-N0_c4bHQ.d.ts → index-D3Nax3YU.d.ts} +11 -10
- package/dist/index.d.ts +191 -178
- package/dist/index.js +1419 -526
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +9 -9
- package/dist/infrastructure/index.js +16 -5
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +14 -16
- package/dist/kernel/index.js +17 -0
- package/dist/kernel/index.js.map +1 -1
- package/dist/{logger-B72yyPc6.d.ts → logger-B63L5bTg.d.ts} +1 -1
- package/dist/{logger-C_27pj9i.d.ts → logger-B9J5puGM.d.ts} +1 -1
- package/dist/{mcp-servers-Dck3T85_.d.ts → mcp-servers-D3E5ixAR.d.ts} +3 -3
- package/dist/{mode-CHo2XtHs.d.ts → mode-ARA3HrkY.d.ts} +1 -1
- package/dist/models/index.d.ts +5 -5
- package/dist/models/index.js +8 -6
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-Be3osGt5.d.ts → models-registry-B6_KfS65.d.ts} +1 -1
- package/dist/{models-registry-Boz639EI.d.ts → models-registry-DU64QxQa.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-DllpCVkF.d.ts → multi-agent-coordinator-DHNrjPaA.d.ts} +2 -2
- package/dist/{null-fleet-bus-BY0AN-sr.d.ts → null-fleet-bus-BzzciAc4.d.ts} +39 -32
- package/dist/observability/index.d.ts +3 -3
- package/dist/{observability-CoSNZdhX.d.ts → observability-D-HZN_mF.d.ts} +1 -1
- package/dist/{parallel-eternal-engine-D402RASp.d.ts → parallel-eternal-engine-CTpcrb9O.d.ts} +34 -33
- package/dist/{path-resolver-UPFTsDyD.d.ts → path-resolver-B7hgMAVe.d.ts} +3 -3
- package/dist/{permission-14CChMmO.d.ts → permission-BDv7z0mk.d.ts} +7 -2
- package/dist/{permission-policy-gW5htOo1.d.ts → permission-policy-dF74EpDp.d.ts} +2 -2
- package/dist/{system-prompt-C0rLCeyn.d.ts → pipeline-C1Ad9OjI.d.ts} +73 -73
- package/dist/{plan-templates-DRvPgkfZ.d.ts → plan-templates-CNphsz0n.d.ts} +79 -11
- package/dist/{provider-runner-COAJM8tC.d.ts → provider-runner-cqvlB_oS.d.ts} +5 -5
- package/dist/{retry-policy-DSu6O6rD.d.ts → retry-policy-BcmuT_V0.d.ts} +2 -2
- package/dist/sdd/index.d.ts +12 -33
- package/dist/sdd/index.js +110 -50
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-scrubber-yGBFQYju.d.ts → secret-vault-DrOhc2i5.d.ts} +7 -7
- package/dist/security/index.d.ts +4 -5
- package/dist/security/index.js +22 -4
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-11-fm95U.d.ts → selector-C7wcdqMA.d.ts} +1 -1
- package/dist/{session-event-bridge-D0u-x576.d.ts → session-event-bridge-IVzs2GpE.d.ts} +1 -1
- package/dist/{session-reader-BQU-toaN.d.ts → session-reader-DDz1Ek4V.d.ts} +2 -2
- package/dist/{skill-BJeF2DwY.d.ts → skill-BJxzIyyN.d.ts} +1 -1
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.js +3 -9
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/index.d.ts +134 -14
- package/dist/storage/index.js +982 -248
- package/dist/storage/index.js.map +1 -1
- package/dist/{task-graph-CikNdRTG.d.ts → task-graph-DJBqO0EY.d.ts} +1 -1
- package/dist/types/index.d.ts +26 -28
- package/dist/types/index.js +62 -37
- package/dist/types/index.js.map +1 -1
- package/dist/utils/expect-defined.d.ts +7 -0
- package/dist/utils/expect-defined.js +11 -0
- package/dist/utils/expect-defined.js.map +1 -0
- package/dist/utils/index.d.ts +11 -20
- package/dist/utils/index.js +61 -43
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-BQMvEllz.d.ts → wstack-paths-_lqjzErq.d.ts} +1 -1
- package/package.json +5 -1
- package/dist/memory-CEXuo7sz.d.ts +0 -16
- package/dist/secret-scrubber-3MHDDAtm.d.ts +0 -6
|
@@ -1,387 +1,176 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { C as Container,
|
|
3
|
-
import { E as EventBus,
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { T as Tracer } from './observability-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { W as WireFamily } from './models-registry-
|
|
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-D3Nax3YU.js';
|
|
2
|
+
import { C as Container, R as ReadonlyPipeline, a as Renderer } from './pipeline-C1Ad9OjI.js';
|
|
3
|
+
import { E as EventBus, a as EventName, L as Listener } from './brain-s9DyD_Vf.js';
|
|
4
|
+
import { R as RetryPolicy, E as ErrorHandler } from './retry-policy-BcmuT_V0.js';
|
|
5
|
+
import { L as Logger } from './logger-B63L5bTg.js';
|
|
6
|
+
import { T as Tracer } from './observability-D-HZN_mF.js';
|
|
7
|
+
import { P as PermissionPolicy } from './permission-BDv7z0mk.js';
|
|
8
|
+
import { U as Usage, C as Context, J as JSONSchema, R as Request, b as Response, g as ContentBlock, l as TextBlock, T as Tool, P as Provider, o as RunOptions } from './context-CNRYfhUv.js';
|
|
9
|
+
import { H as HookEvent, a as HookMatcher, I as InProcessHook, C as Config } from './config-84VaZpH6.js';
|
|
10
|
+
import { W as WireFamily } from './models-registry-B6_KfS65.js';
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
readonly extensions: ExtensionRegistry;
|
|
28
|
-
private readonly _toolHandler;
|
|
29
|
-
private readonly _responseHandler;
|
|
30
|
-
private readonly _loopHandler;
|
|
31
|
-
constructor(init: AgentInit);
|
|
32
|
-
get logger(): Logger;
|
|
33
|
-
get retry(): RetryPolicy;
|
|
34
|
-
get errorHandler(): ErrorHandler;
|
|
35
|
-
get permission(): PermissionPolicy;
|
|
36
|
-
get renderer(): Renderer | undefined;
|
|
37
|
-
disableInteractiveConfirmation(): void;
|
|
38
|
-
register(tool: Tool): void;
|
|
39
|
-
use(plugin: Plugin, api: PluginAPI): Promise<void>;
|
|
40
|
-
teardown(): Promise<void>;
|
|
41
|
-
run(userInput: AgentInput, opts?: RunOptions): Promise<RunResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Single fleet-wide event with subagent attribution. Whatever a child
|
|
14
|
+
* agent emits on its own EventBus gets re-published here, prefixed with
|
|
15
|
+
* `subagentId` so a single subscriber can multiplex across the fleet.
|
|
16
|
+
*
|
|
17
|
+
* The director uses `FleetBus.filter('tool.executed', …)` to see every
|
|
18
|
+
* tool call across the fleet; the TUI uses
|
|
19
|
+
* `FleetBus.subscribe(id, handler)` to render a per-subagent panel.
|
|
20
|
+
*/
|
|
21
|
+
interface FleetEvent {
|
|
22
|
+
subagentId: string;
|
|
23
|
+
taskId?: string | undefined;
|
|
24
|
+
ts: number;
|
|
25
|
+
type: string;
|
|
26
|
+
payload: unknown;
|
|
42
27
|
}
|
|
43
|
-
|
|
28
|
+
type FleetHandler = (event: FleetEvent) => void;
|
|
44
29
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
30
|
+
* Fan-in for per-subagent EventBuses. Each subagent's bus is plugged in
|
|
31
|
+
* via `attach()`; the FleetBus re-emits every event with subagent
|
|
32
|
+
* attribution. Detachment is automatic via the returned disposer — call
|
|
33
|
+
* it when a subagent terminates so we don't leak listeners.
|
|
47
34
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
35
|
+
* The bus exposes two subscription modes: by `subagentId` (everything
|
|
36
|
+
* from one child) and by `type` (one event-type across the fleet). They
|
|
37
|
+
* compose — if you need a per-subagent + per-type slice, subscribe by
|
|
38
|
+
* type and filter on `event.subagentId` in your handler.
|
|
50
39
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
aliases?: string[] | undefined;
|
|
56
|
-
description: string;
|
|
40
|
+
declare class FleetBus {
|
|
41
|
+
private readonly byId;
|
|
42
|
+
private readonly byType;
|
|
43
|
+
private readonly any;
|
|
57
44
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
45
|
+
* Hook a subagent's EventBus into the fleet. Uses `onAny()` (an alias for
|
|
46
|
+
* `onPattern('*')`) to forward all events with subagent attribution, so
|
|
47
|
+
* new kernel event types are automatically forwarded without any manual
|
|
48
|
+
* registration. `subagent.*` events are excluded because they originate
|
|
49
|
+
* from MultiAgentHost on the parent bus, not the subagent's own bus.
|
|
50
|
+
*
|
|
51
|
+
* Returns a disposer that detaches every subscription; call on
|
|
52
|
+
* subagent teardown so the listeners don't outlive the run.
|
|
60
53
|
*/
|
|
61
|
-
|
|
54
|
+
attach(subagentId: string, bus: EventBus, taskId?: string): () => void;
|
|
55
|
+
/** Subscribe to every event from one subagent. */
|
|
56
|
+
subscribe(subagentId: string, handler: FleetHandler): () => void;
|
|
57
|
+
/** Subscribe to one event type across all subagents. */
|
|
58
|
+
filter(type: string, handler: FleetHandler): () => void;
|
|
59
|
+
/** Subscribe to literally everything. The fleet roll-up uses this. */
|
|
60
|
+
onAny(handler: FleetHandler): () => void;
|
|
61
|
+
emit(event: FleetEvent): void;
|
|
62
|
+
clear(): void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Roll-up of token usage + cost across an entire director run. The
|
|
66
|
+
* director's `fleet_status` tool returns this so the model can reason
|
|
67
|
+
* about budget in its next turn ("the researcher already burned $0.40,
|
|
68
|
+
* lean on summaries for the next task").
|
|
69
|
+
*/
|
|
70
|
+
interface FleetUsage {
|
|
71
|
+
total: {
|
|
72
|
+
input: number;
|
|
73
|
+
output: number;
|
|
74
|
+
cacheRead: number;
|
|
75
|
+
cacheWrite: number;
|
|
76
|
+
cost: number;
|
|
77
|
+
};
|
|
78
|
+
perSubagent: Record<string, SubagentUsageSnapshot>;
|
|
79
|
+
}
|
|
80
|
+
interface SubagentUsageSnapshot {
|
|
81
|
+
subagentId: string;
|
|
82
|
+
provider?: string | undefined;
|
|
83
|
+
model?: string | undefined;
|
|
84
|
+
input: number;
|
|
85
|
+
output: number;
|
|
86
|
+
cacheRead: number;
|
|
87
|
+
cacheWrite: number;
|
|
88
|
+
cost: number;
|
|
89
|
+
toolCalls: number;
|
|
90
|
+
iterations: number;
|
|
91
|
+
startedAt: number;
|
|
92
|
+
lastEventAt: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Aggregates provider.response + tool.executed events from the FleetBus
|
|
96
|
+
* into a live `FleetUsage` snapshot. Costs are computed by the caller
|
|
97
|
+
* via a `priceLookup(subagentId)` so we don't bake provider-pricing
|
|
98
|
+
* coupling into core; the CLI/tests supply a function that resolves
|
|
99
|
+
* each subagent's per-token rates from the models registry.
|
|
100
|
+
*/
|
|
101
|
+
declare class FleetUsageAggregator {
|
|
102
|
+
private readonly priceLookup?;
|
|
103
|
+
private readonly metaLookup?;
|
|
104
|
+
private readonly perSubagent;
|
|
105
|
+
private readonly total;
|
|
106
|
+
private readonly unsub;
|
|
107
|
+
constructor(bus: FleetBus, priceLookup?: ((subagentId: string, provider?: string | undefined, model?: string | undefined) => {
|
|
108
|
+
input?: number | undefined;
|
|
109
|
+
output?: number | undefined;
|
|
110
|
+
cacheRead?: number | undefined;
|
|
111
|
+
cacheWrite?: number | undefined;
|
|
112
|
+
} | undefined) | undefined, metaLookup?: ((subagentId: string) => {
|
|
113
|
+
provider?: string | undefined;
|
|
114
|
+
model?: string | undefined;
|
|
115
|
+
} | undefined) | undefined);
|
|
62
116
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
117
|
+
* Remove a terminated subagent's data from the aggregator and subtract its
|
|
118
|
+
* contribution from the running totals. Call this when a subagent is removed
|
|
119
|
+
* from the fleet so the aggregator doesn't accumulate unbounded data for
|
|
120
|
+
* entities that will never emit events again.
|
|
66
121
|
*/
|
|
67
|
-
|
|
122
|
+
removeSubagent(subagentId: string): void;
|
|
123
|
+
/** Disposes all fleet-bus subscriptions. Call when the aggregator is no longer needed. */
|
|
124
|
+
dispose(): void;
|
|
125
|
+
/** Live snapshot — safe to call from a tool's execute() body. */
|
|
126
|
+
snapshot(): FleetUsage;
|
|
127
|
+
private ensure;
|
|
128
|
+
private onProviderResponse;
|
|
129
|
+
private onToolExecuted;
|
|
130
|
+
private onIterationStarted;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
type BudgetKind = 'tool_calls' | 'iterations' | 'tokens' | 'timeout' | 'idle_timeout' | 'cost';
|
|
134
|
+
declare class BudgetExceededError extends Error {
|
|
135
|
+
readonly kind: BudgetKind;
|
|
136
|
+
readonly limit: number;
|
|
137
|
+
readonly observed: number;
|
|
138
|
+
constructor(kind: BudgetKind, limit: number, observed: number);
|
|
139
|
+
}
|
|
140
|
+
interface BudgetLimits {
|
|
141
|
+
maxIterations?: number | undefined;
|
|
142
|
+
maxToolCalls?: number | undefined;
|
|
143
|
+
maxTokens?: number | undefined;
|
|
144
|
+
/** Estimated USD cost ceiling. */
|
|
145
|
+
maxCostUsd?: number | undefined;
|
|
68
146
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
147
|
+
* Hard wall-clock timeout measured from `start()`. Off by default — set it
|
|
148
|
+
* explicitly only when a task must finish within an absolute window. For
|
|
149
|
+
* the everyday "don't kill an agent that's still working" guard, prefer
|
|
150
|
+
* `idleTimeoutMs`, which resets on activity.
|
|
73
151
|
*/
|
|
74
|
-
|
|
152
|
+
timeoutMs?: number | undefined;
|
|
75
153
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* model immediately (e.g. `/steer <text>` builds a STEERING preamble
|
|
82
|
-
* here and asks the TUI to run it as the next turn). The TUI prints
|
|
83
|
-
* `message` first (if any) so the user sees the slash result before
|
|
84
|
-
* the model's response starts streaming. `{ metadata }` carries
|
|
85
|
-
* structured data for the REPL/TUI to act on (e.g. SDD session state).
|
|
154
|
+
* Idle timeout: the maximum gap (ms) between activity signals (iterations,
|
|
155
|
+
* tool calls, token usage, streamed progress) before the subagent is
|
|
156
|
+
* considered hung and reaped. Unlike `timeoutMs`, an actively-working
|
|
157
|
+
* agent continuously resets this clock via `markActivity()`, so it never
|
|
158
|
+
* trips on a long-but-productive run — only on a genuine stall.
|
|
86
159
|
*/
|
|
87
|
-
|
|
88
|
-
exit?: boolean | undefined;
|
|
89
|
-
message?: string | undefined;
|
|
90
|
-
runText?: string | undefined;
|
|
91
|
-
metadata?: Record<string, unknown>;
|
|
92
|
-
} | void>;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
interface ToolRegistryView {
|
|
96
|
-
register(t: Tool): void;
|
|
97
|
-
unregister(name: string): void;
|
|
98
|
-
/** Wrap (decorate) an existing tool. The wrapper gets the current tool and returns the decorated version. */
|
|
99
|
-
wrap(name: string, wrapper: ToolWrapper): void;
|
|
100
|
-
get(name: string): Tool | undefined;
|
|
101
|
-
list(): Tool[];
|
|
102
|
-
}
|
|
103
|
-
interface ProviderFactory {
|
|
104
|
-
type: string;
|
|
105
|
-
family: WireFamily;
|
|
106
|
-
create(cfg: unknown): Provider;
|
|
107
|
-
}
|
|
108
|
-
interface ProviderRegistryView {
|
|
109
|
-
register(f: ProviderFactory): void;
|
|
110
|
-
create(cfg: {
|
|
111
|
-
type: string;
|
|
112
|
-
} & Record<string, unknown>): Provider;
|
|
113
|
-
list(): string[];
|
|
114
|
-
}
|
|
115
|
-
interface MCPRegistryView {
|
|
116
|
-
start(cfg: unknown): Promise<void>;
|
|
117
|
-
stop(name: string): Promise<void>;
|
|
118
|
-
restart(name: string): Promise<void>;
|
|
119
|
-
list(): {
|
|
120
|
-
name: string;
|
|
121
|
-
state: string;
|
|
122
|
-
toolCount: number;
|
|
123
|
-
}[];
|
|
124
|
-
}
|
|
125
|
-
interface SlashCommandRegistryView {
|
|
126
|
-
register(cmd: SlashCommand): void;
|
|
127
|
-
unregister(name: string): boolean;
|
|
128
|
-
get(name: string): SlashCommand | undefined;
|
|
129
|
-
list(): SlashCommand[];
|
|
160
|
+
idleTimeoutMs?: number | undefined;
|
|
130
161
|
}
|
|
131
162
|
/**
|
|
132
|
-
*
|
|
133
|
-
* to the JSONL session log and read the transcript path.
|
|
163
|
+
* Controls how the budget behaves when `onThreshold` is set and a limit is hit.
|
|
134
164
|
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Metrics sink scoped to a plugin. The host auto-prefixes metric names
|
|
147
|
-
* with `plugin.<pluginName>.` so plugins don't need to namespace
|
|
148
|
-
* manually. Plugins call counter/histogram/gauge directly; the values
|
|
149
|
-
* flow to the host's MetricsSink (Prometheus, OTLP, or noop).
|
|
150
|
-
*/
|
|
151
|
-
interface MetricsSinkView {
|
|
152
|
-
counter(name: string, value?: number | undefined, labels?: Record<string, string>): void;
|
|
153
|
-
histogram(name: string, value: number, labels?: Record<string, string>): void;
|
|
154
|
-
gauge(name: string, value: number, labels?: Record<string, string>): void;
|
|
155
|
-
}
|
|
156
|
-
interface PluginPipelines {
|
|
157
|
-
request: ReadonlyPipeline<Request>;
|
|
158
|
-
response: ReadonlyPipeline<Response>;
|
|
159
|
-
toolCall: ReadonlyPipeline<ToolCallPipelinePayload>;
|
|
160
|
-
userInput: ReadonlyPipeline<{
|
|
161
|
-
content: ContentBlock[];
|
|
162
|
-
text: string;
|
|
163
|
-
ctx: Context;
|
|
164
|
-
}>;
|
|
165
|
-
assistantOutput: ReadonlyPipeline<TextBlock>;
|
|
166
|
-
contextWindow: ReadonlyPipeline<Context>;
|
|
167
|
-
[k: string]: ReadonlyPipeline<any>;
|
|
168
|
-
}
|
|
169
|
-
interface PluginAPI {
|
|
170
|
-
container: Container;
|
|
171
|
-
pipelines: PluginPipelines;
|
|
172
|
-
events: EventBus;
|
|
173
|
-
tools: ToolRegistryView;
|
|
174
|
-
providers: ProviderRegistryView;
|
|
175
|
-
mcp: MCPRegistryView;
|
|
176
|
-
slashCommands: SlashCommandRegistryView;
|
|
177
|
-
/** Live session writer — plugins can append custom events here. */
|
|
178
|
-
session: SessionWriterView;
|
|
179
|
-
/** Scoped metrics sink — counters/histograms/gauges auto-namespaced under `plugin.<name>.` */
|
|
180
|
-
metrics: MetricsSinkView;
|
|
181
|
-
/** Registry for agent lifecycle extensions — hooks like beforeRun, beforeIteration, onError, etc. */
|
|
182
|
-
extensions: ExtensionRegistry;
|
|
183
|
-
/**
|
|
184
|
-
* Register a system prompt contributor. Plugins call this to inject
|
|
185
|
-
* ephemeral TextBlocks into the system prompt on every build.
|
|
186
|
-
* Returns an unregister function.
|
|
187
|
-
*/
|
|
188
|
-
registerSystemPromptContributor(c: SystemPromptContributor): () => void;
|
|
189
|
-
/**
|
|
190
|
-
* Register an in-process lifecycle hook. `matcher` is a tool-name filter for
|
|
191
|
-
* `PreToolUse`/`PostToolUse` (`"Bash"`, `"edit|write"`, `"*"`) and ignored
|
|
192
|
-
* for other events. The hook can block, rewrite tool input, or inject extra
|
|
193
|
-
* context — see `HookOutcome`. Automatically removed when the plugin is
|
|
194
|
-
* uninstalled. Returns an unregister function.
|
|
195
|
-
*/
|
|
196
|
-
registerHook(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook): () => void;
|
|
197
|
-
config: Config;
|
|
198
|
-
log: Logger;
|
|
199
|
-
/**
|
|
200
|
-
* Register a one-time event listener. The handler is automatically removed
|
|
201
|
-
* after the first emission, or when the plugin is uninstalled — whichever
|
|
202
|
-
* comes first.
|
|
203
|
-
*/
|
|
204
|
-
onEvent<K extends EventName>(event: K, handler: Listener<K>): () => void;
|
|
205
|
-
/**
|
|
206
|
-
* Subscribe to all events matching a glob-style pattern.
|
|
207
|
-
* `'tool.*'` matches all tool events. `'*'` matches everything.
|
|
208
|
-
* Returns an unsubscribe function.
|
|
209
|
-
*/
|
|
210
|
-
onPattern(pattern: string, handler: (event: string, payload: unknown) => void): () => void;
|
|
211
|
-
/**
|
|
212
|
-
* Emit a custom event on the agent's EventBus. Use for inter-plugin
|
|
213
|
-
* communication or to surface plugin-specific state to the host.
|
|
214
|
-
*
|
|
215
|
-
* Custom events use a `pluginName:eventName` convention to avoid
|
|
216
|
-
* collisions with built-in events (e.g. `my-plugin:cache_hit`).
|
|
217
|
-
* The payload is passed through to all subscribers.
|
|
218
|
-
*/
|
|
219
|
-
emitCustom(event: string, payload: unknown): void;
|
|
220
|
-
/**
|
|
221
|
-
* Register a callback that fires when the configuration changes at
|
|
222
|
-
* runtime (e.g. via `/config` slash command or programmatic update).
|
|
223
|
-
* The handler receives the new and previous config snapshots.
|
|
224
|
-
* Returns an unsubscribe function.
|
|
225
|
-
*/
|
|
226
|
-
onConfigChange(handler: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Capability declaration — informs the host which subsystems a plugin
|
|
230
|
-
* intends to touch. Used for diagnostics and per-plugin enable/disable UX
|
|
231
|
-
* (e.g. "this plugin registers tools — disable to remove them"). Not
|
|
232
|
-
* enforced at runtime: a plugin that declares `tools: false` can still
|
|
233
|
-
* call `api.tools.register()`, but the host can flag the discrepancy.
|
|
234
|
-
*/
|
|
235
|
-
interface PluginCapabilities {
|
|
236
|
-
/** Will register tools via `api.tools.register()`. */
|
|
237
|
-
tools?: boolean | undefined;
|
|
238
|
-
/** Will register provider factories via `api.providers.register()`. */
|
|
239
|
-
providers?: boolean | undefined;
|
|
240
|
-
/**
|
|
241
|
-
* Pipelines the plugin hooks into. Use the standard names
|
|
242
|
-
* (`request | response | toolCall | userInput | assistantOutput | contextWindow`)
|
|
243
|
-
* or custom pipeline names exposed by other plugins.
|
|
244
|
-
*/
|
|
245
|
-
pipelines?: string[] | undefined;
|
|
246
|
-
/** Will register slash commands via `api.slashCommands.register()`. */
|
|
247
|
-
slashCommands?: boolean | undefined;
|
|
248
|
-
/** Will start MCP servers via `api.mcp.start()`. */
|
|
249
|
-
mcp?: boolean | undefined;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Structured dependency declaration. The string form (`dependsOn: ['foo']`)
|
|
253
|
-
* is shorthand for `[{ name: 'foo' }]` — both work. Use the structured form
|
|
254
|
-
* when you need a version constraint:
|
|
255
|
-
*
|
|
256
|
-
* dependsOn: [{ name: 'wstack-auth', version: '^1.2.0' }]
|
|
257
|
-
*/
|
|
258
|
-
interface PluginDependency {
|
|
259
|
-
name: string;
|
|
260
|
-
/** npm-style semver range. Supports `^`, `~`, exact, and unprefixed. */
|
|
261
|
-
version?: string | undefined;
|
|
262
|
-
}
|
|
263
|
-
interface Plugin {
|
|
264
|
-
name: string;
|
|
265
|
-
version?: string | undefined;
|
|
266
|
-
/** One-line summary for `wstack plugins list` and error messages. */
|
|
267
|
-
description?: string | undefined;
|
|
268
|
-
/** Semver range against the kernel API version (KERNEL_API_VERSION). */
|
|
269
|
-
apiVersion: string;
|
|
270
|
-
/**
|
|
271
|
-
* Capability hints — what subsystems the plugin will register against.
|
|
272
|
-
* Optional; provided for diagnostics and UX. The loader does not enforce
|
|
273
|
-
* these, but mismatch is surfaced via logger at warn level.
|
|
274
|
-
*/
|
|
275
|
-
capabilities?: PluginCapabilities | undefined;
|
|
276
|
-
/**
|
|
277
|
-
* JSON Schema for the options under `Config.plugins[<name>].options`.
|
|
278
|
-
* When present, the loader validates that section before calling `setup`
|
|
279
|
-
* and rejects the plugin with a clear error path on failure.
|
|
280
|
-
*/
|
|
281
|
-
configSchema?: JSONSchema | undefined;
|
|
282
|
-
/**
|
|
283
|
-
* Mandatory plugin dependencies — loading fails if any are absent or
|
|
284
|
-
* version-incompatible. Accepts both the legacy string-array form and
|
|
285
|
-
* the structured form with version constraints.
|
|
286
|
-
*/
|
|
287
|
-
dependsOn?: (string | PluginDependency)[] | undefined;
|
|
288
|
-
/** Optional plugin dependencies — silently skipped if absent. */
|
|
289
|
-
optionalDeps?: (string | PluginDependency)[] | undefined;
|
|
290
|
-
conflictsWith?: string[] | undefined;
|
|
291
|
-
/**
|
|
292
|
-
* Default configuration values, deep-merged under the plugin's options
|
|
293
|
-
* key before `configSchema` validation. User-provided values take
|
|
294
|
-
* precedence over defaults — this is a fallback, not an override.
|
|
295
|
-
*
|
|
296
|
-
* @example
|
|
297
|
-
* defaultConfig: { ttl: 3600, maxSize: 100 }
|
|
298
|
-
*/
|
|
299
|
-
defaultConfig?: Record<string, unknown>;
|
|
300
|
-
setup(api: PluginAPI): void | Promise<void>;
|
|
301
|
-
teardown?(api: PluginAPI): void | Promise<void>;
|
|
302
|
-
/**
|
|
303
|
-
* Optional health check. Called by the host (e.g. `/diag plugins` slash
|
|
304
|
-
* command or health endpoint) to surface plugin status. Return
|
|
305
|
-
* `{ ok: false, message: '...' }` when the plugin is degraded.
|
|
306
|
-
*/
|
|
307
|
-
health?(): Promise<{
|
|
308
|
-
ok: boolean;
|
|
309
|
-
message?: string | undefined;
|
|
310
|
-
}>;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
type BridgeMessageType = 'task' | 'result' | 'progress' | 'error' | 'heartbeat' | 'stop' | 'delegate' | 'budget_threshold';
|
|
314
|
-
interface BridgeMessage<T = unknown> {
|
|
315
|
-
id: string;
|
|
316
|
-
type: BridgeMessageType;
|
|
317
|
-
from: string;
|
|
318
|
-
to?: string | undefined;
|
|
319
|
-
payload: T;
|
|
320
|
-
timestamp: number;
|
|
321
|
-
priority?: 'low' | 'normal' | 'high' | 'critical' | undefined;
|
|
322
|
-
}
|
|
323
|
-
interface AgentBridgeConfig {
|
|
324
|
-
agentId: string;
|
|
325
|
-
coordinatorId: string;
|
|
326
|
-
timeoutMs?: number | undefined;
|
|
327
|
-
bufferSize?: number | undefined;
|
|
328
|
-
}
|
|
329
|
-
interface AgentBridge {
|
|
330
|
-
readonly agentId: string;
|
|
331
|
-
readonly coordinatorId: string;
|
|
332
|
-
send(msg: BridgeMessage): Promise<void>;
|
|
333
|
-
broadcast(msg: BridgeMessage): Promise<void>;
|
|
334
|
-
subscribe(handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
335
|
-
request<T>(msg: BridgeMessage, timeoutMs?: number): Promise<BridgeMessage<T>> | undefined;
|
|
336
|
-
stop(): Promise<void>;
|
|
337
|
-
}
|
|
338
|
-
interface BridgeTransport {
|
|
339
|
-
send(msg: BridgeMessage, to: string): Promise<void>;
|
|
340
|
-
subscribe(agentId: string, handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
341
|
-
close(agentId: string): Promise<void>;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
type BudgetKind = 'tool_calls' | 'iterations' | 'tokens' | 'timeout' | 'idle_timeout' | 'cost';
|
|
345
|
-
declare class BudgetExceededError extends Error {
|
|
346
|
-
readonly kind: BudgetKind;
|
|
347
|
-
readonly limit: number;
|
|
348
|
-
readonly observed: number;
|
|
349
|
-
constructor(kind: BudgetKind, limit: number, observed: number);
|
|
350
|
-
}
|
|
351
|
-
interface BudgetLimits {
|
|
352
|
-
maxIterations?: number | undefined;
|
|
353
|
-
maxToolCalls?: number | undefined;
|
|
354
|
-
maxTokens?: number | undefined;
|
|
355
|
-
/** Estimated USD cost ceiling. */
|
|
356
|
-
maxCostUsd?: number | undefined;
|
|
357
|
-
/**
|
|
358
|
-
* Hard wall-clock timeout measured from `start()`. Off by default — set it
|
|
359
|
-
* explicitly only when a task must finish within an absolute window. For
|
|
360
|
-
* the everyday "don't kill an agent that's still working" guard, prefer
|
|
361
|
-
* `idleTimeoutMs`, which resets on activity.
|
|
362
|
-
*/
|
|
363
|
-
timeoutMs?: number | undefined;
|
|
364
|
-
/**
|
|
365
|
-
* Idle timeout: the maximum gap (ms) between activity signals (iterations,
|
|
366
|
-
* tool calls, token usage, streamed progress) before the subagent is
|
|
367
|
-
* considered hung and reaped. Unlike `timeoutMs`, an actively-working
|
|
368
|
-
* agent continuously resets this clock via `markActivity()`, so it never
|
|
369
|
-
* trips on a long-but-productive run — only on a genuine stall.
|
|
370
|
-
*/
|
|
371
|
-
idleTimeoutMs?: number | undefined;
|
|
372
|
-
}
|
|
373
|
-
/**
|
|
374
|
-
* Controls how the budget behaves when `onThreshold` is set and a limit is hit.
|
|
375
|
-
*
|
|
376
|
-
* `'auto'` — emit `budget.threshold_reached` on the EventBus and wait for a
|
|
377
|
-
* coordinator response (extend/stop). If no listener responds within
|
|
378
|
-
* `DECISION_TIMEOUT_MS` the decision defaults to `'stop'`.
|
|
379
|
-
* `'sync'` — do not emit any event; treat the threshold as a hard stop and
|
|
380
|
-
* throw `BudgetExceededError` synchronously. Useful for fire-and-forget
|
|
381
|
-
* subagents that have an `onThreshold` handler for logging/metrics but are
|
|
382
|
-
* not wired into a coordinator.
|
|
383
|
-
*
|
|
384
|
-
* @default 'auto'
|
|
165
|
+
* `'auto'` — emit `budget.threshold_reached` on the EventBus and wait for a
|
|
166
|
+
* coordinator response (extend/stop). If no listener responds within
|
|
167
|
+
* `DECISION_TIMEOUT_MS` the decision defaults to `'stop'`.
|
|
168
|
+
* `'sync'` — do not emit any event; treat the threshold as a hard stop and
|
|
169
|
+
* throw `BudgetExceededError` synchronously. Useful for fire-and-forget
|
|
170
|
+
* subagents that have an `onThreshold` handler for logging/metrics but are
|
|
171
|
+
* not wired into a coordinator.
|
|
172
|
+
*
|
|
173
|
+
* @default 'auto'
|
|
385
174
|
*/
|
|
386
175
|
type BudgetNegotiationMode = 'auto' | 'sync';
|
|
387
176
|
interface BudgetUsage {
|
|
@@ -578,14 +367,45 @@ declare class SubagentBudget {
|
|
|
578
367
|
usage(): BudgetUsage;
|
|
579
368
|
}
|
|
580
369
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
370
|
+
type BridgeMessageType = 'task' | 'result' | 'progress' | 'error' | 'heartbeat' | 'stop' | 'delegate' | 'budget_threshold';
|
|
371
|
+
interface BridgeMessage<T = unknown> {
|
|
372
|
+
id: string;
|
|
373
|
+
type: BridgeMessageType;
|
|
374
|
+
from: string;
|
|
375
|
+
to?: string | undefined;
|
|
376
|
+
payload: T;
|
|
377
|
+
timestamp: number;
|
|
378
|
+
priority?: 'low' | 'normal' | 'high' | 'critical' | undefined;
|
|
379
|
+
}
|
|
380
|
+
interface AgentBridgeConfig {
|
|
381
|
+
agentId: string;
|
|
382
|
+
coordinatorId: string;
|
|
383
|
+
timeoutMs?: number | undefined;
|
|
384
|
+
bufferSize?: number | undefined;
|
|
385
|
+
}
|
|
386
|
+
interface AgentBridge {
|
|
387
|
+
readonly agentId: string;
|
|
388
|
+
readonly coordinatorId: string;
|
|
389
|
+
send(msg: BridgeMessage): Promise<void>;
|
|
390
|
+
broadcast(msg: BridgeMessage): Promise<void>;
|
|
391
|
+
subscribe(handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
392
|
+
request<T>(msg: BridgeMessage, timeoutMs?: number): Promise<BridgeMessage<T>> | undefined;
|
|
393
|
+
stop(): Promise<void>;
|
|
394
|
+
}
|
|
395
|
+
interface BridgeTransport {
|
|
396
|
+
send(msg: BridgeMessage, to: string): Promise<void>;
|
|
397
|
+
subscribe(agentId: string, handler: (msg: BridgeMessage) => void | Promise<void>): () => void;
|
|
398
|
+
close(agentId: string): Promise<void>;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
interface SubagentConfig {
|
|
402
|
+
id?: string | undefined;
|
|
403
|
+
name: string;
|
|
404
|
+
role?: string | undefined;
|
|
405
|
+
prompt?: string | undefined;
|
|
406
|
+
maxIterations?: number | undefined;
|
|
407
|
+
maxToolCalls?: number | undefined;
|
|
408
|
+
maxTokens?: number | undefined;
|
|
589
409
|
maxCostUsd?: number | undefined;
|
|
590
410
|
/** Hard wall-clock cap (ms) from start. Opt-in; prefer `idleTimeoutMs`. */
|
|
591
411
|
timeoutMs?: number | undefined;
|
|
@@ -876,123 +696,304 @@ interface SubagentContext {
|
|
|
876
696
|
}
|
|
877
697
|
|
|
878
698
|
/**
|
|
879
|
-
*
|
|
880
|
-
*
|
|
881
|
-
* `subagentId` so a single subscriber can multiplex across the fleet.
|
|
699
|
+
* A slash command registered with the CLI or available to plugins.
|
|
700
|
+
* Plugins receive a view of the registry via PluginAPI.slashCommands.
|
|
882
701
|
*
|
|
883
|
-
*
|
|
884
|
-
*
|
|
885
|
-
* `FleetBus.subscribe(id, handler)` to render a per-subagent panel.
|
|
702
|
+
* Commands registered by plugins use a namespaced name: `pluginName:commandName`.
|
|
703
|
+
* This prevents collisions with built-in commands and other plugins.
|
|
886
704
|
*/
|
|
887
|
-
interface
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
705
|
+
interface SlashCommand {
|
|
706
|
+
/** Unique command name. For plugins: `pluginName:commandName`. */
|
|
707
|
+
name: string;
|
|
708
|
+
/** Short aliases — also prefixed automatically: `pluginName:alias`. */
|
|
709
|
+
aliases?: string[] | undefined;
|
|
710
|
+
description: string;
|
|
711
|
+
/**
|
|
712
|
+
* Category used to group commands in the slash picker. Defaults to 'App'
|
|
713
|
+
* when omitted.
|
|
714
|
+
*/
|
|
715
|
+
category?: 'Run' | 'Session' | 'Inspect' | 'Agent' | 'Config' | 'App' | undefined;
|
|
716
|
+
/**
|
|
717
|
+
* Optional compact argument hint for interactive menus. This is not parsed
|
|
718
|
+
* by the registry; it only helps TUI/REPL surfaces show the expected shape,
|
|
719
|
+
* for example `[list|install <alias>|disable <name>]`.
|
|
720
|
+
*/
|
|
721
|
+
argsHint?: string | undefined;
|
|
722
|
+
/**
|
|
723
|
+
* Optional detailed help shown by `/help <name>`. Use this for usage,
|
|
724
|
+
* arguments, examples, side-effects — anything that doesn't fit in
|
|
725
|
+
* `description`. Renders verbatim, so format with line breaks.
|
|
726
|
+
* If absent, `/help <name>` falls back to `description`.
|
|
727
|
+
*/
|
|
728
|
+
help?: string | undefined;
|
|
729
|
+
/**
|
|
730
|
+
* Execute the command.
|
|
731
|
+
* @param args Everything after the command name (trimmed by dispatch).
|
|
732
|
+
* @param ctx The current agent context.
|
|
733
|
+
* @returns `{ exit: true }` to quit the REPL. `{ message }` to print and
|
|
734
|
+
* continue. `{ runText }` to send a follow-up user-role message to the
|
|
735
|
+
* model immediately (e.g. `/steer <text>` builds a STEERING preamble
|
|
736
|
+
* here and asks the TUI to run it as the next turn). The TUI prints
|
|
737
|
+
* `message` first (if any) so the user sees the slash result before
|
|
738
|
+
* the model's response starts streaming. `{ metadata }` carries
|
|
739
|
+
* structured data for the REPL/TUI to act on (e.g. SDD session state).
|
|
740
|
+
*/
|
|
741
|
+
run(args: string, ctx: Context): Promise<{
|
|
742
|
+
exit?: boolean | undefined;
|
|
743
|
+
message?: string | undefined;
|
|
744
|
+
runText?: string | undefined;
|
|
745
|
+
metadata?: Record<string, unknown>;
|
|
746
|
+
} | void>;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
interface ToolRegistryView {
|
|
750
|
+
register(t: Tool): void;
|
|
751
|
+
unregister(name: string): void;
|
|
752
|
+
/** Wrap (decorate) an existing tool. The wrapper gets the current tool and returns the decorated version. */
|
|
753
|
+
wrap(name: string, wrapper: ToolWrapper): void;
|
|
754
|
+
get(name: string): Tool | undefined;
|
|
755
|
+
list(): Tool[];
|
|
756
|
+
}
|
|
757
|
+
interface ProviderFactory {
|
|
891
758
|
type: string;
|
|
892
|
-
|
|
759
|
+
family: WireFamily;
|
|
760
|
+
create(cfg: unknown): Provider;
|
|
761
|
+
}
|
|
762
|
+
interface ProviderRegistryView {
|
|
763
|
+
register(f: ProviderFactory): void;
|
|
764
|
+
create(cfg: {
|
|
765
|
+
type: string;
|
|
766
|
+
} & Record<string, unknown>): Provider;
|
|
767
|
+
list(): string[];
|
|
768
|
+
}
|
|
769
|
+
interface MCPRegistryView {
|
|
770
|
+
start(cfg: unknown): Promise<void>;
|
|
771
|
+
stop(name: string): Promise<void>;
|
|
772
|
+
restart(name: string): Promise<void>;
|
|
773
|
+
list(): {
|
|
774
|
+
name: string;
|
|
775
|
+
state: string;
|
|
776
|
+
toolCount: number;
|
|
777
|
+
}[];
|
|
778
|
+
}
|
|
779
|
+
interface SlashCommandRegistryView {
|
|
780
|
+
register(cmd: SlashCommand): void;
|
|
781
|
+
unregister(name: string): boolean;
|
|
782
|
+
get(name: string): SlashCommand | undefined;
|
|
783
|
+
list(): SlashCommand[];
|
|
893
784
|
}
|
|
894
|
-
type FleetHandler = (event: FleetEvent) => void;
|
|
895
785
|
/**
|
|
896
|
-
*
|
|
897
|
-
*
|
|
898
|
-
* attribution. Detachment is automatic via the returned disposer — call
|
|
899
|
-
* it when a subagent terminates so we don't leak listeners.
|
|
786
|
+
* Read-only view of the session writer. Plugins can append custom events
|
|
787
|
+
* to the JSONL session log and read the transcript path.
|
|
900
788
|
*
|
|
901
|
-
* The
|
|
902
|
-
*
|
|
903
|
-
* compose — if you need a per-subagent + per-type slice, subscribe by
|
|
904
|
-
* type and filter on `event.subagentId` in your handler.
|
|
789
|
+
* The `append` method accepts any JSON-serializable payload — custom
|
|
790
|
+
* event types are persisted verbatim next to the built-in events.
|
|
905
791
|
*/
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
792
|
+
interface SessionWriterView {
|
|
793
|
+
readonly transcriptPath?: string | undefined;
|
|
794
|
+
append(event: Record<string, unknown> & {
|
|
795
|
+
type: string;
|
|
796
|
+
ts: string;
|
|
797
|
+
}): Promise<void>;
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Metrics sink scoped to a plugin. The host auto-prefixes metric names
|
|
801
|
+
* with `plugin.<pluginName>.` so plugins don't need to namespace
|
|
802
|
+
* manually. Plugins call counter/histogram/gauge directly; the values
|
|
803
|
+
* flow to the host's MetricsSink (Prometheus, OTLP, or noop).
|
|
804
|
+
*/
|
|
805
|
+
interface MetricsSinkView {
|
|
806
|
+
counter(name: string, value?: number | undefined, labels?: Record<string, string>): void;
|
|
807
|
+
histogram(name: string, value: number, labels?: Record<string, string>): void;
|
|
808
|
+
gauge(name: string, value: number, labels?: Record<string, string>): void;
|
|
809
|
+
}
|
|
810
|
+
interface PluginPipelines {
|
|
811
|
+
request: ReadonlyPipeline<Request>;
|
|
812
|
+
response: ReadonlyPipeline<Response>;
|
|
813
|
+
toolCall: ReadonlyPipeline<ToolCallPipelinePayload>;
|
|
814
|
+
userInput: ReadonlyPipeline<{
|
|
815
|
+
content: ContentBlock[];
|
|
816
|
+
text: string;
|
|
817
|
+
ctx: Context;
|
|
818
|
+
}>;
|
|
819
|
+
assistantOutput: ReadonlyPipeline<TextBlock>;
|
|
820
|
+
contextWindow: ReadonlyPipeline<Context>;
|
|
821
|
+
[k: string]: ReadonlyPipeline<any>;
|
|
822
|
+
}
|
|
823
|
+
interface PluginAPI {
|
|
824
|
+
container: Container;
|
|
825
|
+
pipelines: PluginPipelines;
|
|
826
|
+
events: EventBus;
|
|
827
|
+
tools: ToolRegistryView;
|
|
828
|
+
providers: ProviderRegistryView;
|
|
829
|
+
mcp: MCPRegistryView;
|
|
830
|
+
slashCommands: SlashCommandRegistryView;
|
|
831
|
+
/** Live session writer — plugins can append custom events here. */
|
|
832
|
+
session: SessionWriterView;
|
|
833
|
+
/** Scoped metrics sink — counters/histograms/gauges auto-namespaced under `plugin.<name>.` */
|
|
834
|
+
metrics: MetricsSinkView;
|
|
835
|
+
/** Registry for agent lifecycle extensions — hooks like beforeRun, beforeIteration, onError, etc. */
|
|
836
|
+
extensions: ExtensionRegistry;
|
|
910
837
|
/**
|
|
911
|
-
*
|
|
912
|
-
*
|
|
913
|
-
*
|
|
914
|
-
|
|
915
|
-
|
|
838
|
+
* Register a system prompt contributor. Plugins call this to inject
|
|
839
|
+
* ephemeral TextBlocks into the system prompt on every build.
|
|
840
|
+
* Returns an unregister function.
|
|
841
|
+
*/
|
|
842
|
+
registerSystemPromptContributor(c: SystemPromptContributor): () => void;
|
|
843
|
+
/**
|
|
844
|
+
* Register an in-process lifecycle hook. `matcher` is a tool-name filter for
|
|
845
|
+
* `PreToolUse`/`PostToolUse` (`"Bash"`, `"edit|write"`, `"*"`) and ignored
|
|
846
|
+
* for other events. The hook can block, rewrite tool input, or inject extra
|
|
847
|
+
* context — see `HookOutcome`. Automatically removed when the plugin is
|
|
848
|
+
* uninstalled. Returns an unregister function.
|
|
849
|
+
*/
|
|
850
|
+
registerHook(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook): () => void;
|
|
851
|
+
config: Config;
|
|
852
|
+
log: Logger;
|
|
853
|
+
/**
|
|
854
|
+
* Register a one-time event listener. The handler is automatically removed
|
|
855
|
+
* after the first emission, or when the plugin is uninstalled — whichever
|
|
856
|
+
* comes first.
|
|
857
|
+
*/
|
|
858
|
+
onEvent<K extends EventName>(event: K, handler: Listener<K>): () => void;
|
|
859
|
+
/**
|
|
860
|
+
* Subscribe to all events matching a glob-style pattern.
|
|
861
|
+
* `'tool.*'` matches all tool events. `'*'` matches everything.
|
|
862
|
+
* Returns an unsubscribe function.
|
|
863
|
+
*/
|
|
864
|
+
onPattern(pattern: string, handler: (event: string, payload: unknown) => void): () => void;
|
|
865
|
+
/**
|
|
866
|
+
* Emit a custom event on the agent's EventBus. Use for inter-plugin
|
|
867
|
+
* communication or to surface plugin-specific state to the host.
|
|
916
868
|
*
|
|
917
|
-
*
|
|
918
|
-
*
|
|
869
|
+
* Custom events use a `pluginName:eventName` convention to avoid
|
|
870
|
+
* collisions with built-in events (e.g. `my-plugin:cache_hit`).
|
|
871
|
+
* The payload is passed through to all subscribers.
|
|
919
872
|
*/
|
|
920
|
-
|
|
921
|
-
/**
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
873
|
+
emitCustom(event: string, payload: unknown): void;
|
|
874
|
+
/**
|
|
875
|
+
* Register a callback that fires when the configuration changes at
|
|
876
|
+
* runtime (e.g. via `/config` slash command or programmatic update).
|
|
877
|
+
* The handler receives the new and previous config snapshots.
|
|
878
|
+
* Returns an unsubscribe function.
|
|
879
|
+
*/
|
|
880
|
+
onConfigChange(handler: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
|
|
928
881
|
}
|
|
929
882
|
/**
|
|
930
|
-
*
|
|
931
|
-
*
|
|
932
|
-
*
|
|
933
|
-
*
|
|
883
|
+
* Capability declaration — informs the host which subsystems a plugin
|
|
884
|
+
* intends to touch. Used for diagnostics and per-plugin enable/disable UX
|
|
885
|
+
* (e.g. "this plugin registers tools — disable to remove them"). Not
|
|
886
|
+
* enforced at runtime: a plugin that declares `tools: false` can still
|
|
887
|
+
* call `api.tools.register()`, but the host can flag the discrepancy.
|
|
934
888
|
*/
|
|
935
|
-
interface
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
output: number;
|
|
951
|
-
cacheRead: number;
|
|
952
|
-
cacheWrite: number;
|
|
953
|
-
cost: number;
|
|
954
|
-
toolCalls: number;
|
|
955
|
-
iterations: number;
|
|
956
|
-
startedAt: number;
|
|
957
|
-
lastEventAt: number;
|
|
889
|
+
interface PluginCapabilities {
|
|
890
|
+
/** Will register tools via `api.tools.register()`. */
|
|
891
|
+
tools?: boolean | undefined;
|
|
892
|
+
/** Will register provider factories via `api.providers.register()`. */
|
|
893
|
+
providers?: boolean | undefined;
|
|
894
|
+
/**
|
|
895
|
+
* Pipelines the plugin hooks into. Use the standard names
|
|
896
|
+
* (`request | response | toolCall | userInput | assistantOutput | contextWindow`)
|
|
897
|
+
* or custom pipeline names exposed by other plugins.
|
|
898
|
+
*/
|
|
899
|
+
pipelines?: string[] | undefined;
|
|
900
|
+
/** Will register slash commands via `api.slashCommands.register()`. */
|
|
901
|
+
slashCommands?: boolean | undefined;
|
|
902
|
+
/** Will start MCP servers via `api.mcp.start()`. */
|
|
903
|
+
mcp?: boolean | undefined;
|
|
958
904
|
}
|
|
959
905
|
/**
|
|
960
|
-
*
|
|
961
|
-
*
|
|
962
|
-
*
|
|
963
|
-
*
|
|
964
|
-
*
|
|
906
|
+
* Structured dependency declaration. The string form (`dependsOn: ['foo']`)
|
|
907
|
+
* is shorthand for `[{ name: 'foo' }]` — both work. Use the structured form
|
|
908
|
+
* when you need a version constraint:
|
|
909
|
+
*
|
|
910
|
+
* dependsOn: [{ name: 'wstack-auth', version: '^1.2.0' }]
|
|
965
911
|
*/
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
provider?: string | undefined;
|
|
979
|
-
model?: string | undefined;
|
|
980
|
-
} | undefined) | undefined);
|
|
912
|
+
interface PluginDependency {
|
|
913
|
+
name: string;
|
|
914
|
+
/** npm-style semver range. Supports `^`, `~`, exact, and unprefixed. */
|
|
915
|
+
version?: string | undefined;
|
|
916
|
+
}
|
|
917
|
+
interface Plugin {
|
|
918
|
+
name: string;
|
|
919
|
+
version?: string | undefined;
|
|
920
|
+
/** One-line summary for `wstack plugins list` and error messages. */
|
|
921
|
+
description?: string | undefined;
|
|
922
|
+
/** Semver range against the kernel API version (KERNEL_API_VERSION). */
|
|
923
|
+
apiVersion: string;
|
|
981
924
|
/**
|
|
982
|
-
*
|
|
983
|
-
*
|
|
984
|
-
*
|
|
985
|
-
* entities that will never emit events again.
|
|
925
|
+
* Capability hints — what subsystems the plugin will register against.
|
|
926
|
+
* Optional; provided for diagnostics and UX. The loader does not enforce
|
|
927
|
+
* these, but mismatch is surfaced via logger at warn level.
|
|
986
928
|
*/
|
|
987
|
-
|
|
988
|
-
/**
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
929
|
+
capabilities?: PluginCapabilities | undefined;
|
|
930
|
+
/**
|
|
931
|
+
* JSON Schema for the options under `Config.plugins[<name>].options`.
|
|
932
|
+
* When present, the loader validates that section before calling `setup`
|
|
933
|
+
* and rejects the plugin with a clear error path on failure.
|
|
934
|
+
*/
|
|
935
|
+
configSchema?: JSONSchema | undefined;
|
|
936
|
+
/**
|
|
937
|
+
* Mandatory plugin dependencies — loading fails if any are absent or
|
|
938
|
+
* version-incompatible. Accepts both the legacy string-array form and
|
|
939
|
+
* the structured form with version constraints.
|
|
940
|
+
*/
|
|
941
|
+
dependsOn?: (string | PluginDependency)[] | undefined;
|
|
942
|
+
/** Optional plugin dependencies — silently skipped if absent. */
|
|
943
|
+
optionalDeps?: (string | PluginDependency)[] | undefined;
|
|
944
|
+
conflictsWith?: string[] | undefined;
|
|
945
|
+
/**
|
|
946
|
+
* Default configuration values, deep-merged under the plugin's options
|
|
947
|
+
* key before `configSchema` validation. User-provided values take
|
|
948
|
+
* precedence over defaults — this is a fallback, not an override.
|
|
949
|
+
*
|
|
950
|
+
* @example
|
|
951
|
+
* defaultConfig: { ttl: 3600, maxSize: 100 }
|
|
952
|
+
*/
|
|
953
|
+
defaultConfig?: Record<string, unknown>;
|
|
954
|
+
setup(api: PluginAPI): void | Promise<void>;
|
|
955
|
+
teardown?(api: PluginAPI): void | Promise<void>;
|
|
956
|
+
/**
|
|
957
|
+
* Optional health check. Called by the host (e.g. `/diag plugins` slash
|
|
958
|
+
* command or health endpoint) to surface plugin status. Return
|
|
959
|
+
* `{ ok: false, message: '...' }` when the plugin is degraded.
|
|
960
|
+
*/
|
|
961
|
+
health?(): Promise<{
|
|
962
|
+
ok: boolean;
|
|
963
|
+
message?: string | undefined;
|
|
964
|
+
}>;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
declare class Agent {
|
|
968
|
+
readonly container: Container;
|
|
969
|
+
readonly tools: ToolRegistry;
|
|
970
|
+
readonly providers: ProviderRegistry;
|
|
971
|
+
readonly events: EventBus;
|
|
972
|
+
readonly pipelines: AgentPipelines;
|
|
973
|
+
readonly ctx: Context;
|
|
974
|
+
readonly maxIterations: number;
|
|
975
|
+
readonly executionStrategy: 'parallel' | 'sequential' | 'smart';
|
|
976
|
+
readonly perIterationOutputCapBytes: number;
|
|
977
|
+
private readonly plugins;
|
|
978
|
+
readonly toolExecutor: ToolExecutorLike;
|
|
979
|
+
readonly autoExtendLimit: boolean;
|
|
980
|
+
private readonly autonomousContinue;
|
|
981
|
+
readonly tracer: Tracer | undefined;
|
|
982
|
+
readonly extensions: ExtensionRegistry;
|
|
983
|
+
private readonly _toolHandler;
|
|
984
|
+
private readonly _responseHandler;
|
|
985
|
+
private readonly _loopHandler;
|
|
986
|
+
constructor(init: AgentInit);
|
|
987
|
+
get logger(): Logger;
|
|
988
|
+
get retry(): RetryPolicy;
|
|
989
|
+
get errorHandler(): ErrorHandler;
|
|
990
|
+
get permission(): PermissionPolicy;
|
|
991
|
+
get renderer(): Renderer | undefined;
|
|
992
|
+
disableInteractiveConfirmation(): void;
|
|
993
|
+
register(tool: Tool): void;
|
|
994
|
+
use(plugin: Plugin, api: PluginAPI): Promise<void>;
|
|
995
|
+
teardown(): Promise<void>;
|
|
996
|
+
run(userInput: AgentInput, opts?: RunOptions): Promise<RunResult>;
|
|
996
997
|
}
|
|
997
998
|
|
|
998
999
|
/**
|
|
@@ -1052,4 +1053,4 @@ interface AgentRunnerOptions {
|
|
|
1052
1053
|
*/
|
|
1053
1054
|
declare function makeAgentSubagentRunner(opts: AgentRunnerOptions): SubagentRunner;
|
|
1054
1055
|
|
|
1055
|
-
export {
|
|
1056
|
+
export { type AgentBridge as A, type BridgeTransport as B, type CoordinatorStatus as C, type PluginPipelines as D, type ToolRegistryView as E, FleetBus as F, type ProviderRegistryView as G, type MCPRegistryView as H, type SlashCommandRegistryView as I, type SessionWriterView as J, type MetricsSinkView as K, type Plugin as L, type MultiAgentCoordinator as M, type CoordinatorEvents as N, type DoneCondition as O, type PluginAPI as P, type PluginCapabilities as Q, type PluginDependency as R, type SubagentConfig as S, type TaskSpec as T, type SubagentContext as U, type SubagentError as V, type SubagentErrorKind as W, type SubagentRunContext as X, type SubagentRunOutcome as Y, type TaskDelegation as Z, type ProviderFactory as _, type BridgeMessage as a, type AgentBridgeConfig as b, type MultiAgentConfig as c, type SubagentRunner as d, type SpawnResult as e, type TaskResult as f, Agent as g, type AgentFactory as h, type AgentFactoryResult as i, type AgentRunnerOptions as j, BudgetExceededError as k, type BudgetKind as l, type BudgetLimits as m, type BudgetNegotiationMode as n, type BudgetThresholdDecision as o, type BudgetThresholdHandler as p, BudgetThresholdSignal as q, type BudgetUsage as r, type FleetEvent as s, type FleetHandler as t, type FleetUsage as u, FleetUsageAggregator as v, SubagentBudget as w, type SubagentUsageSnapshot as x, makeAgentSubagentRunner as y, type SlashCommand as z };
|