@wrongstack/core 0.7.8 → 0.8.2
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-hXRN-GO_.d.ts → agent-bridge-DPxcUVkn.d.ts} +1 -1
- package/dist/{agent-subagent-runner-B2zguWzh.d.ts → agent-subagent-runner-Cav3yEJM.d.ts} +9 -10
- package/dist/coordination/index.d.ts +9 -9
- package/dist/coordination/index.js +393 -179
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +13 -13
- package/dist/defaults/index.js +261 -64
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-D4pGukpI.d.ts → events-DyhxkstG.d.ts} +33 -0
- package/dist/execution/index.d.ts +24 -7
- package/dist/execution/index.js +158 -37
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +3 -3
- package/dist/{index-BtNRyJft.d.ts → index-oYZeWsuJ.d.ts} +2 -2
- package/dist/index.d.ts +16 -16
- package/dist/index.js +365 -68
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +2 -2
- package/dist/kernel/index.d.ts +3 -3
- package/dist/kernel/index.js +23 -0
- package/dist/kernel/index.js.map +1 -1
- package/dist/{multi-agent-7OK4pEKW.d.ts → multi-agent-CRMznZmf.d.ts} +64 -30
- package/dist/{multi-agent-coordinator-3Ypfg-hr.d.ts → multi-agent-coordinator-IQKrMfXz.d.ts} +11 -1
- package/dist/{null-fleet-bus-BZUrXVcd.d.ts → null-fleet-bus-sKnVwEd8.d.ts} +92 -6
- package/dist/observability/index.d.ts +1 -1
- package/dist/{path-resolver-DPUjF10O.d.ts → path-resolver-1CIYbH2Q.d.ts} +1 -1
- package/dist/{permission-policy-D5Gj1o2K.d.ts → permission-policy-BBa1M1xc.d.ts} +10 -1
- package/dist/{plan-templates-C-IOLJ8Q.d.ts → plan-templates-BnlpEkX8.d.ts} +1 -1
- package/dist/{provider-runner-iST8U3ni.d.ts → provider-runner-BrA0XR-l.d.ts} +1 -1
- package/dist/sdd/index.d.ts +5 -5
- package/dist/sdd/index.js +114 -28
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-scrubber-DXkhwuka.d.ts → secret-scrubber-C0n1EqrC.d.ts} +1 -1
- package/dist/{secret-scrubber-nI8qjaqW.d.ts → secret-scrubber-CyE1-EMG.d.ts} +1 -1
- package/dist/security/index.d.ts +3 -3
- package/dist/security/index.js +29 -3
- package/dist/security/index.js.map +1 -1
- package/dist/storage/index.d.ts +2 -2
- package/dist/{tool-executor-CSwXjifK.d.ts → tool-executor-QwfWnQZ8.d.ts} +1 -1
- package/dist/types/index.d.ts +9 -9
- package/package.json +1 -1
package/dist/{multi-agent-coordinator-3Ypfg-hr.d.ts → multi-agent-coordinator-IQKrMfXz.d.ts}
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as SubagentConfig, l as MultiAgentCoordinator, M as MultiAgentConfig, t as SubagentRunner, S as SpawnResult, v as TaskSpec, B as BridgeMessage, A as AgentBridge, k as CoordinatorStatus, u as TaskResult } from './multi-agent-CRMznZmf.js';
|
|
2
|
+
import { F as FleetBus } from './agent-subagent-runner-Cav3yEJM.js';
|
|
2
3
|
import { EventEmitter } from 'node:events';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -175,6 +176,7 @@ declare class DefaultMultiAgentCoordinator extends EventEmitter implements Multi
|
|
|
175
176
|
readonly coordinatorId: string;
|
|
176
177
|
readonly config: MultiAgentConfig;
|
|
177
178
|
private runner?;
|
|
179
|
+
private fleetBus?;
|
|
178
180
|
private readonly subagents;
|
|
179
181
|
private pendingTasks;
|
|
180
182
|
private completedResults;
|
|
@@ -196,6 +198,12 @@ declare class DefaultMultiAgentCoordinator extends EventEmitter implements Multi
|
|
|
196
198
|
* the coordinator's owning Director is built.
|
|
197
199
|
*/
|
|
198
200
|
setRunner(runner: SubagentRunner): void;
|
|
201
|
+
/**
|
|
202
|
+
* Wire a FleetBus for director-mode event emission. Call after the
|
|
203
|
+
* FleetManager is constructed so the coordinator can emit lifecycle
|
|
204
|
+
* events the TUI and monitoring tools subscribe to.
|
|
205
|
+
*/
|
|
206
|
+
setFleetBus(fleet: FleetBus): void;
|
|
199
207
|
/**
|
|
200
208
|
* Change the in-flight dispatch ceiling at runtime. Lowering does NOT
|
|
201
209
|
* preempt running tasks — already-dispatched subagents finish their
|
|
@@ -226,6 +234,8 @@ declare class DefaultMultiAgentCoordinator extends EventEmitter implements Multi
|
|
|
226
234
|
pending: number;
|
|
227
235
|
completed: number;
|
|
228
236
|
};
|
|
237
|
+
/** Emit a reactive coordinator.stats event on FleetBus so the TUI can subscribe. */
|
|
238
|
+
private emitCoordinatorStats;
|
|
229
239
|
getStatus(): CoordinatorStatus;
|
|
230
240
|
/** Expose snapshot of completed results — useful for callers awaiting all done. */
|
|
231
241
|
results(): readonly TaskResult[];
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { c as AgentPhase, b as AgentDefinition } from './multi-agent-coordinator-
|
|
2
|
-
import {
|
|
1
|
+
import { c as AgentPhase, b as AgentDefinition, d as DefaultMultiAgentCoordinator, f as DispatchClassifier } from './multi-agent-coordinator-IQKrMfXz.js';
|
|
2
|
+
import { n as SubagentConfig, u as TaskResult, k as CoordinatorStatus, v as TaskSpec, M as MultiAgentConfig, t as SubagentRunner } from './multi-agent-CRMznZmf.js';
|
|
3
3
|
import { B as SessionWriter, Q as Tool, y as SessionStore } from './context-z2x5gv_V.js';
|
|
4
4
|
import { a as DirectorStateSnapshot } from './director-state-BmYi3DGA.js';
|
|
5
|
-
import { I as InMemoryAgentBridge } from './agent-bridge-
|
|
6
|
-
import { F as FleetBus, e as FleetUsage, f as FleetUsageAggregator } from './agent-subagent-runner-
|
|
7
|
-
import { E as EventBus } from './events-
|
|
5
|
+
import { I as InMemoryAgentBridge } from './agent-bridge-DPxcUVkn.js';
|
|
6
|
+
import { F as FleetBus, e as FleetUsage, f as FleetUsageAggregator } from './agent-subagent-runner-Cav3yEJM.js';
|
|
7
|
+
import { E as EventBus } from './events-DyhxkstG.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Agent catalog aggregator.
|
|
@@ -176,6 +176,11 @@ interface IFleetManager {
|
|
|
176
176
|
* or null when no manifest path is configured.
|
|
177
177
|
*/
|
|
178
178
|
writeManifest(): Promise<string | null>;
|
|
179
|
+
/**
|
|
180
|
+
* Bypass the debounce timer and write the manifest immediately.
|
|
181
|
+
* Clears any pending debounce timer before writing.
|
|
182
|
+
*/
|
|
183
|
+
flushManifest(): Promise<void>;
|
|
179
184
|
/**
|
|
180
185
|
* Aggregate fleet-wide status: pending tasks with descriptions and
|
|
181
186
|
* live subagent snapshot from the coordinator. Used by
|
|
@@ -204,6 +209,44 @@ interface IFleetManager {
|
|
|
204
209
|
* pending list stays accurate.
|
|
205
210
|
*/
|
|
206
211
|
removePendingTask(taskId: string): void;
|
|
212
|
+
/**
|
|
213
|
+
* Wire the coordinator so `getFleetStats()` can delegate to it.
|
|
214
|
+
* Called by `Director` after constructing the coordinator so
|
|
215
|
+
* FleetManager's stats reflect live subagent data.
|
|
216
|
+
*/
|
|
217
|
+
setCoordinator(coordinator: {
|
|
218
|
+
getStats(): {
|
|
219
|
+
total: number;
|
|
220
|
+
running: number;
|
|
221
|
+
idle: number;
|
|
222
|
+
stopped: number;
|
|
223
|
+
inFlight: number;
|
|
224
|
+
pending: number;
|
|
225
|
+
completed: number;
|
|
226
|
+
};
|
|
227
|
+
}): void;
|
|
228
|
+
/**
|
|
229
|
+
* Coordinator stats snapshot for the TUI and monitoring tools.
|
|
230
|
+
* Returns actionable counts (total/running/idle/stopped/inFlight/
|
|
231
|
+
* pending/completed) plus per-subagent status details.
|
|
232
|
+
* Delegates to the coordinator when available; returns zeros
|
|
233
|
+
* if the coordinator has not yet been set.
|
|
234
|
+
*/
|
|
235
|
+
getFleetStats(): {
|
|
236
|
+
total: number;
|
|
237
|
+
running: number;
|
|
238
|
+
idle: number;
|
|
239
|
+
stopped: number;
|
|
240
|
+
inFlight: number;
|
|
241
|
+
pending: number;
|
|
242
|
+
completed: number;
|
|
243
|
+
subagentStatuses: {
|
|
244
|
+
subagentId: string;
|
|
245
|
+
taskId: string;
|
|
246
|
+
status: string;
|
|
247
|
+
assigned: boolean;
|
|
248
|
+
}[];
|
|
249
|
+
};
|
|
207
250
|
}
|
|
208
251
|
|
|
209
252
|
/** Options for constructing a FleetManager. */
|
|
@@ -271,8 +314,16 @@ declare class FleetManager implements IFleetManager {
|
|
|
271
314
|
private readonly pendingTasks;
|
|
272
315
|
private readonly subagentMeta;
|
|
273
316
|
private readonly priceLookups;
|
|
317
|
+
/** The coordinator (wired via setCoordinator by Director after construction). */
|
|
318
|
+
private coordinator;
|
|
274
319
|
constructor(opts?: FleetManagerOptions);
|
|
275
320
|
get fleetBus(): FleetBus;
|
|
321
|
+
/**
|
|
322
|
+
* Wire the coordinator after Director construction. The coordinator
|
|
323
|
+
* is not available when FleetManager is constructed standalone.
|
|
324
|
+
* Once set, `getFleetStats()` delegates to `coordinator.getStats()`.
|
|
325
|
+
*/
|
|
326
|
+
setCoordinator(coordinator: DefaultMultiAgentCoordinator): void;
|
|
276
327
|
snapshot(): FleetUsage;
|
|
277
328
|
getSubagentMeta(id: string): {
|
|
278
329
|
provider?: string;
|
|
@@ -313,12 +364,33 @@ declare class FleetManager implements IFleetManager {
|
|
|
313
364
|
/**
|
|
314
365
|
* Debounced manifest write. Call after any state mutation
|
|
315
366
|
* (spawn, assign, complete) so a burst collapses into one write.
|
|
367
|
+
* When `manifestDebounceMs` is 0, writes are synchronous (no debounce).
|
|
316
368
|
*/
|
|
317
369
|
scheduleManifest(): void;
|
|
370
|
+
/**
|
|
371
|
+
* Bypass the debounce timer and write the manifest immediately.
|
|
372
|
+
* Clears any pending debounce timer before writing.
|
|
373
|
+
*/
|
|
374
|
+
flushManifest(): Promise<void>;
|
|
318
375
|
/** Best-effort session event writer. Swallows failures. */
|
|
319
376
|
private appendSessionEvent;
|
|
320
377
|
addPendingTask(taskId: string, subagentId: string, description: string): void;
|
|
321
378
|
removePendingTask(taskId: string): void;
|
|
379
|
+
getFleetStats(): {
|
|
380
|
+
total: number;
|
|
381
|
+
running: number;
|
|
382
|
+
idle: number;
|
|
383
|
+
stopped: number;
|
|
384
|
+
inFlight: number;
|
|
385
|
+
pending: number;
|
|
386
|
+
completed: number;
|
|
387
|
+
subagentStatuses: {
|
|
388
|
+
subagentId: string;
|
|
389
|
+
taskId: string;
|
|
390
|
+
status: string;
|
|
391
|
+
assigned: boolean;
|
|
392
|
+
}[];
|
|
393
|
+
};
|
|
322
394
|
getFleetStatus(): {
|
|
323
395
|
pending: {
|
|
324
396
|
taskId: string;
|
|
@@ -492,6 +564,17 @@ interface DirectorOptions {
|
|
|
492
564
|
* (same behavior as before this field was added).
|
|
493
565
|
*/
|
|
494
566
|
fleetManager?: FleetManager;
|
|
567
|
+
/**
|
|
568
|
+
* Optional LLM classifier for the smart dispatcher. When set, the
|
|
569
|
+
* `spawn_subagent` tool can accept a free-form `description` field
|
|
570
|
+
* and the director will automatically route to the best-matching
|
|
571
|
+
* catalog agent using `dispatchAgent()`. When omitted, routing is
|
|
572
|
+
* pure heuristic (no provider call) — sufficient for most tasks.
|
|
573
|
+
*
|
|
574
|
+
* Build from a `complete(prompt) => string` function using
|
|
575
|
+
* `makeLLMClassifier(complete)` from the dispatcher module.
|
|
576
|
+
*/
|
|
577
|
+
dispatchClassifier?: DispatchClassifier;
|
|
495
578
|
}
|
|
496
579
|
/**
|
|
497
580
|
* Thrown by `Director.spawn()` when a configured spawn cap (`maxSpawns`,
|
|
@@ -612,6 +695,8 @@ declare class Director implements ICoordinator {
|
|
|
612
695
|
* default cap.
|
|
613
696
|
*/
|
|
614
697
|
private taskCompletedListener;
|
|
698
|
+
/** Optional LLM classifier for smart dispatch. Passed from options. */
|
|
699
|
+
readonly dispatchClassifier?: DispatchClassifier;
|
|
615
700
|
constructor(opts: DirectorOptions);
|
|
616
701
|
/**
|
|
617
702
|
* Record a granted budget extension and broadcast it on the FleetBus so
|
|
@@ -625,7 +710,8 @@ declare class Director implements ICoordinator {
|
|
|
625
710
|
* must not break a fleet run because the session JSONL handle closed. */
|
|
626
711
|
private appendSessionEvent;
|
|
627
712
|
/** Debounced manifest writer. A burst of spawn/assign/complete events
|
|
628
|
-
* collapses into one write. Set `manifestDebounceMs` to 0 to
|
|
713
|
+
* collapses into one write. Set `manifestDebounceMs` to 0 to write
|
|
714
|
+
* synchronously (no debounce); set to negative to disable entirely. */
|
|
629
715
|
private scheduleManifest;
|
|
630
716
|
/**
|
|
631
717
|
* Spawn a subagent. Identical to the coordinator's `spawn()` but
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { e as MetricsSink, M as MetricLabels, f as MetricsSnapshot, b as HealthRegistry, H as HealthCheck, A as AggregateHealth, T as Tracer, S as Span } from '../observability-BhnVLBLS.js';
|
|
2
|
-
import { E as EventBus } from '../events-
|
|
2
|
+
import { E as EventBus } from '../events-DyhxkstG.js';
|
|
3
3
|
import '../context-z2x5gv_V.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as EventBus } from './events-
|
|
1
|
+
import { E as EventBus } from './events-DyhxkstG.js';
|
|
2
2
|
import { b as ModelsRegistry, R as ResolvedModel } from './models-registry-BcYJDKLm.js';
|
|
3
3
|
import { O as TokenCounter, $ as Usage, C as CacheStats } from './context-z2x5gv_V.js';
|
|
4
4
|
import { P as PathResolver } from './path-resolver-CPRj4bFY.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Q as Tool, d as Context } from './context-z2x5gv_V.js';
|
|
2
2
|
import { I as InputReader } from './input-reader-E-ffP2ee.js';
|
|
3
|
-
import { a as PermissionPolicy, P as PermissionDecision } from './secret-scrubber-
|
|
3
|
+
import { a as PermissionPolicy, P as PermissionDecision } from './secret-scrubber-CyE1-EMG.js';
|
|
4
4
|
|
|
5
5
|
interface PermissionPolicyOptions {
|
|
6
6
|
trustFile: string;
|
|
@@ -100,6 +100,15 @@ declare class DefaultPermissionPolicy implements PermissionPolicy {
|
|
|
100
100
|
* subagent capability override, not a deny-bypass).
|
|
101
101
|
*/
|
|
102
102
|
declare class AutoApprovePermissionPolicy implements PermissionPolicy {
|
|
103
|
+
/**
|
|
104
|
+
* Tools that are too dangerous to auto-approve even in a delegated
|
|
105
|
+
* subagent context. Subagents run non-interactively under a director
|
|
106
|
+
* and cannot answer prompts, but inherited authorization does not
|
|
107
|
+
* imply blanket permission for destructive or privilege-escalating
|
|
108
|
+
* operations. These tools remain at their declared `permission`
|
|
109
|
+
* level so the leader must explicitly allow them per-spawn.
|
|
110
|
+
*/
|
|
111
|
+
private static readonly DENY;
|
|
103
112
|
evaluate(tool: Tool): Promise<PermissionDecision>;
|
|
104
113
|
trust(): Promise<void>;
|
|
105
114
|
deny(): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as EventBus } from './events-
|
|
1
|
+
import { E as EventBus } from './events-DyhxkstG.js';
|
|
2
2
|
import { y as SessionStore, x as SessionMetadata, B as SessionWriter, r as ResumedSession, S as SessionData, z as SessionSummary, c as ContentBlock, w as SessionEvent, N as TodoItem, f as ConversationState } from './context-z2x5gv_V.js';
|
|
3
3
|
import { e as AttachmentStore, A as AddAttachmentInput, d as AttachmentRef, a as Attachment } from './session-reader-DsadjyF9.js';
|
|
4
4
|
import { b as MemoryStore, a as MemoryScope } from './memory-CEXuo7sz.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as EventBus } from './events-
|
|
1
|
+
import { E as EventBus } from './events-DyhxkstG.js';
|
|
2
2
|
import { a as Logger } from './logger-DDd5C--Z.js';
|
|
3
3
|
import { T as Tracer } from './observability-BhnVLBLS.js';
|
|
4
4
|
import { m as Provider, p as Request, d as Context, q as Response } from './context-z2x5gv_V.js';
|
package/dist/sdd/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { h as Specification, S as SpecAnalysis, g as SpecValidationResult, l as TaskGraph, m as TaskNode, k as TaskFilter, p as TaskSort, o as TaskProgress, r as TaskType, n as TaskPriority, e as SpecStatus, f as SpecTemplate, b as SpecRequirement } from '../task-graph-D1YQbpxF.js';
|
|
2
|
-
import { E as EventBus } from '../events-
|
|
3
|
-
import { D as DoneCondition,
|
|
4
|
-
import { c as Agent } from '../index-
|
|
5
|
-
import { A as AgentFactory } from '../agent-subagent-runner-
|
|
2
|
+
import { E as EventBus } from '../events-DyhxkstG.js';
|
|
3
|
+
import { D as DoneCondition, u as TaskResult } from '../multi-agent-CRMznZmf.js';
|
|
4
|
+
import { c as Agent } from '../index-oYZeWsuJ.js';
|
|
5
|
+
import { A as AgentFactory } from '../agent-subagent-runner-Cav3yEJM.js';
|
|
6
6
|
import '../context-z2x5gv_V.js';
|
|
7
7
|
import '../logger-DDd5C--Z.js';
|
|
8
8
|
import '../system-prompt-CWA6ml-d.js';
|
|
9
9
|
import '../observability-BhnVLBLS.js';
|
|
10
|
-
import '../secret-scrubber-
|
|
10
|
+
import '../secret-scrubber-CyE1-EMG.js';
|
|
11
11
|
import '../config-Bi4Q0fnz.js';
|
|
12
12
|
import '../models-registry-BcYJDKLm.js';
|
|
13
13
|
|
package/dist/sdd/index.js
CHANGED
|
@@ -2627,29 +2627,35 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2627
2627
|
* same kind are no-ops — without this dedup, every `recordIteration`
|
|
2628
2628
|
* after the limit is reached spawns a fresh decision Promise (until
|
|
2629
2629
|
* the first one lands and patches limits), flooding the FleetBus
|
|
2630
|
-
* with redundant threshold events. Cleared in `
|
|
2630
|
+
* with redundant threshold events. Cleared in `negotiateExtension`'s
|
|
2631
2631
|
* `finally`.
|
|
2632
2632
|
*/
|
|
2633
2633
|
pendingExtensions = /* @__PURE__ */ new Set();
|
|
2634
2634
|
/**
|
|
2635
|
-
* Hard cap on how long `
|
|
2635
|
+
* Hard cap on how long `negotiateExtension` waits for the coordinator to
|
|
2636
2636
|
* respond before defaulting to 'stop'. Without this fallback an absent
|
|
2637
2637
|
* or hung listener (Director not built / event filter detached mid-run)
|
|
2638
|
-
* leaves the budget over-limit and never enforces anything
|
|
2639
|
-
* `checkLimit` returns synchronously via `void this.checkLimitAsync`.
|
|
2640
|
-
* Raised from 30s to 60s to give subagents more headroom before
|
|
2641
|
-
* the threshold negotiation times out and triggers a hard stop.
|
|
2638
|
+
* leaves the budget over-limit and never enforces anything.
|
|
2642
2639
|
*/
|
|
2643
2640
|
static DECISION_TIMEOUT_MS = 6e4;
|
|
2644
2641
|
/**
|
|
2645
2642
|
* Injected by the runner when wiring the budget to its EventBus.
|
|
2646
|
-
* Used
|
|
2643
|
+
* Used to emit `budget.threshold_reached` events in `'auto'` mode.
|
|
2647
2644
|
*/
|
|
2648
2645
|
_events;
|
|
2646
|
+
/**
|
|
2647
|
+
* Negotiation mode — controls whether a threshold hit tries to emit
|
|
2648
|
+
* `budget.threshold_reached` and wait for a coordinator decision, or
|
|
2649
|
+
* falls straight through to a synchronous hard stop.
|
|
2650
|
+
*
|
|
2651
|
+
* `'auto'` (default) — emit on the EventBus and wait; times out to 'stop'.
|
|
2652
|
+
* `'sync'` — throw `BudgetExceededError` immediately regardless of listeners.
|
|
2653
|
+
*/
|
|
2654
|
+
_mode;
|
|
2649
2655
|
/**
|
|
2650
2656
|
* Optional callback for soft-limit handling. When set, the budget will
|
|
2651
|
-
*
|
|
2652
|
-
*
|
|
2657
|
+
* invoke it rather than throw immediately. The handler decides whether to
|
|
2658
|
+
* throw synchronously, continue, or ask the coordinator for an extension.
|
|
2653
2659
|
*/
|
|
2654
2660
|
get onThreshold() {
|
|
2655
2661
|
return this._onThreshold;
|
|
@@ -2657,7 +2663,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2657
2663
|
set onThreshold(fn) {
|
|
2658
2664
|
this._onThreshold = fn;
|
|
2659
2665
|
}
|
|
2660
|
-
|
|
2666
|
+
/** Returns the current negotiation mode. */
|
|
2667
|
+
get mode() {
|
|
2668
|
+
return this._mode;
|
|
2669
|
+
}
|
|
2670
|
+
constructor(limits = {}, mode = "auto") {
|
|
2671
|
+
this._mode = mode;
|
|
2661
2672
|
this.limits = { ...limits };
|
|
2662
2673
|
}
|
|
2663
2674
|
start() {
|
|
@@ -2673,16 +2684,23 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2673
2684
|
return false;
|
|
2674
2685
|
}
|
|
2675
2686
|
/**
|
|
2676
|
-
* Synchronous budget check
|
|
2677
|
-
*
|
|
2678
|
-
*
|
|
2679
|
-
*
|
|
2680
|
-
*
|
|
2687
|
+
* Synchronous budget check. Always throws synchronously so callers (especially
|
|
2688
|
+
* test event handlers using `expect().toThrow()`) get an unhandled rejection
|
|
2689
|
+
* when the budget is exceeded without a handler.
|
|
2690
|
+
*
|
|
2691
|
+
* Decision table:
|
|
2692
|
+
* - no `onThreshold` handler → throw `BudgetExceededError` (hard stop, always)
|
|
2693
|
+
* - `mode === 'sync'` → throw `BudgetExceededError` (hard stop, always)
|
|
2694
|
+
* - `mode === 'auto'` + no listener → throw `BudgetExceededError` (hard stop; no one to ask)
|
|
2695
|
+
* - `mode === 'auto'` + listener → throw `BudgetThresholdSignal` with async decision promise
|
|
2681
2696
|
*/
|
|
2682
2697
|
checkLimit(kind, used, limit) {
|
|
2683
2698
|
if (!this._onThreshold) {
|
|
2684
2699
|
throw new BudgetExceededError(kind, limit, used);
|
|
2685
2700
|
}
|
|
2701
|
+
if (this._mode === "sync") {
|
|
2702
|
+
throw new BudgetExceededError(kind, limit, used);
|
|
2703
|
+
}
|
|
2686
2704
|
const bus = this._events;
|
|
2687
2705
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
2688
2706
|
throw new BudgetExceededError(kind, limit, used);
|
|
@@ -2699,8 +2717,8 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2699
2717
|
* `pendingExtensions` slot in `finally`.
|
|
2700
2718
|
*
|
|
2701
2719
|
* The 'continue' return from a sync handler is treated as
|
|
2702
|
-
* `{ extend: {} }` — keep going without patching
|
|
2703
|
-
*
|
|
2720
|
+
* `{ extend: {} }` — keep going without patching; next overrun fires
|
|
2721
|
+
* a fresh signal.
|
|
2704
2722
|
*/
|
|
2705
2723
|
async negotiateExtension(kind, used, limit) {
|
|
2706
2724
|
try {
|
|
@@ -2708,11 +2726,6 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2708
2726
|
kind,
|
|
2709
2727
|
used,
|
|
2710
2728
|
limit,
|
|
2711
|
-
// Inject a requestDecision helper the handler can call to emit the
|
|
2712
|
-
// budget.threshold_reached event and wait for the coordinator's verdict.
|
|
2713
|
-
// A hard fallback timer guarantees the promise eventually resolves
|
|
2714
|
-
// even if no listener responds — without it, an absent/detached
|
|
2715
|
-
// Director would leave the budget permanently in "asking" state.
|
|
2716
2729
|
requestDecision: () => {
|
|
2717
2730
|
const bus = this._events;
|
|
2718
2731
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
@@ -2796,12 +2809,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2796
2809
|
}
|
|
2797
2810
|
}
|
|
2798
2811
|
/**
|
|
2799
|
-
* Wall-clock budget check. Unlike other limits, timeout
|
|
2800
|
-
*
|
|
2801
|
-
*
|
|
2802
|
-
*
|
|
2803
|
-
*
|
|
2804
|
-
*
|
|
2812
|
+
* Wall-clock budget check. Unlike other limits, timeout check passes through
|
|
2813
|
+
* `checkLimit` and is subject to the same negotiation-mode decision table.
|
|
2814
|
+
* In practice, `'sync'` mode (the usual test configuration) means a timeout
|
|
2815
|
+
* immediately throws `BudgetExceededError`. In production with a coordinator,
|
|
2816
|
+
* a timeout emits `budget.threshold_reached` so the Director can decide whether
|
|
2817
|
+
* to extend or abort.
|
|
2805
2818
|
*/
|
|
2806
2819
|
checkTimeout() {
|
|
2807
2820
|
if (this.startTime === null || this.limits.timeoutMs === void 0) return;
|
|
@@ -5366,6 +5379,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5366
5379
|
coordinatorId;
|
|
5367
5380
|
config;
|
|
5368
5381
|
runner;
|
|
5382
|
+
fleetBus;
|
|
5369
5383
|
subagents = /* @__PURE__ */ new Map();
|
|
5370
5384
|
pendingTasks = [];
|
|
5371
5385
|
completedResults = [];
|
|
@@ -5394,6 +5408,14 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5394
5408
|
setRunner(runner) {
|
|
5395
5409
|
this.runner = runner;
|
|
5396
5410
|
}
|
|
5411
|
+
/**
|
|
5412
|
+
* Wire a FleetBus for director-mode event emission. Call after the
|
|
5413
|
+
* FleetManager is constructed so the coordinator can emit lifecycle
|
|
5414
|
+
* events the TUI and monitoring tools subscribe to.
|
|
5415
|
+
*/
|
|
5416
|
+
setFleetBus(fleet) {
|
|
5417
|
+
this.fleetBus = fleet;
|
|
5418
|
+
}
|
|
5397
5419
|
/**
|
|
5398
5420
|
* Change the in-flight dispatch ceiling at runtime. Lowering does NOT
|
|
5399
5421
|
* preempt running tasks — already-dispatched subagents finish their
|
|
@@ -5429,6 +5451,18 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5429
5451
|
abortController: new AbortController()
|
|
5430
5452
|
});
|
|
5431
5453
|
this.emit("subagent.started", { subagent: { ...subagent, id } });
|
|
5454
|
+
this.fleetBus?.emit({
|
|
5455
|
+
subagentId: id,
|
|
5456
|
+
ts: Date.now(),
|
|
5457
|
+
type: "subagent.assigned",
|
|
5458
|
+
payload: {
|
|
5459
|
+
subagentId: id,
|
|
5460
|
+
name: subagent.name,
|
|
5461
|
+
provider: subagent.provider,
|
|
5462
|
+
model: subagent.model
|
|
5463
|
+
}
|
|
5464
|
+
});
|
|
5465
|
+
this.emitCoordinatorStats();
|
|
5432
5466
|
return { subagentId: id, agentId: id };
|
|
5433
5467
|
}
|
|
5434
5468
|
async assign(task) {
|
|
@@ -5461,6 +5495,13 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5461
5495
|
subagent.currentTask = void 0;
|
|
5462
5496
|
subagent.context.parentBridge = null;
|
|
5463
5497
|
this.emit("subagent.stopped", { subagentId, reason: "stopped by coordinator" });
|
|
5498
|
+
this.fleetBus?.emit({
|
|
5499
|
+
subagentId,
|
|
5500
|
+
ts: Date.now(),
|
|
5501
|
+
type: "subagent.stopped",
|
|
5502
|
+
payload: { subagentId, reason: "stopped by coordinator" }
|
|
5503
|
+
});
|
|
5504
|
+
this.emitCoordinatorStats();
|
|
5464
5505
|
}
|
|
5465
5506
|
async stopAll() {
|
|
5466
5507
|
this.drainPendingAsAborted("Coordinator stopAll() drained the pending queue");
|
|
@@ -5492,6 +5533,22 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5492
5533
|
completed: this.completedResults.length
|
|
5493
5534
|
};
|
|
5494
5535
|
}
|
|
5536
|
+
/** Emit a reactive coordinator.stats event on FleetBus so the TUI can subscribe. */
|
|
5537
|
+
emitCoordinatorStats() {
|
|
5538
|
+
const stats = this.getStats();
|
|
5539
|
+
const subagentStatuses = Array.from(this.subagents.entries()).map(([id, s]) => ({
|
|
5540
|
+
subagentId: id,
|
|
5541
|
+
taskId: s.currentTask ?? "",
|
|
5542
|
+
status: s.status,
|
|
5543
|
+
assigned: s.context.parentBridge !== null
|
|
5544
|
+
}));
|
|
5545
|
+
this.fleetBus?.emit({
|
|
5546
|
+
subagentId: this.coordinatorId,
|
|
5547
|
+
ts: Date.now(),
|
|
5548
|
+
type: "coordinator.stats",
|
|
5549
|
+
payload: { ...stats, subagentStatuses }
|
|
5550
|
+
});
|
|
5551
|
+
}
|
|
5495
5552
|
getStatus() {
|
|
5496
5553
|
return {
|
|
5497
5554
|
coordinatorId: this.coordinatorId,
|
|
@@ -5666,7 +5723,15 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5666
5723
|
subagent.currentTask = task.id;
|
|
5667
5724
|
task.subagentId = subagentId;
|
|
5668
5725
|
subagent.context.tasks.push(task);
|
|
5726
|
+
this.fleetBus?.emit({
|
|
5727
|
+
subagentId,
|
|
5728
|
+
taskId: task.id,
|
|
5729
|
+
ts: Date.now(),
|
|
5730
|
+
type: "subagent.running",
|
|
5731
|
+
payload: { subagentId, taskId: task.id }
|
|
5732
|
+
});
|
|
5669
5733
|
this.emit("task.assigned", { task, subagentId });
|
|
5734
|
+
this.emitCoordinatorStats();
|
|
5670
5735
|
const rawMaxIterations = subagent.config.maxIterations;
|
|
5671
5736
|
const rawMaxToolCalls = subagent.config.maxToolCalls;
|
|
5672
5737
|
const rawMaxTokens = subagent.config.maxTokens;
|
|
@@ -5810,13 +5875,34 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5810
5875
|
if (subagent.abortController.signal.aborted) {
|
|
5811
5876
|
subagent.abortController = new AbortController();
|
|
5812
5877
|
}
|
|
5878
|
+
this.fleetBus?.emit({
|
|
5879
|
+
subagentId: result.subagentId,
|
|
5880
|
+
ts: Date.now(),
|
|
5881
|
+
type: "subagent.idle",
|
|
5882
|
+
payload: { subagentId: result.subagentId }
|
|
5883
|
+
});
|
|
5813
5884
|
}
|
|
5814
5885
|
this.terminating.delete(result.subagentId);
|
|
5815
5886
|
this.emit("task.completed", {
|
|
5816
5887
|
task: subagent?.context.tasks.find((t) => t.id === result.taskId) ?? { id: result.taskId },
|
|
5817
5888
|
result
|
|
5818
5889
|
});
|
|
5890
|
+
this.fleetBus?.emit({
|
|
5891
|
+
subagentId: result.subagentId,
|
|
5892
|
+
taskId: result.taskId,
|
|
5893
|
+
ts: Date.now(),
|
|
5894
|
+
type: "subagent.completed",
|
|
5895
|
+
payload: {
|
|
5896
|
+
subagentId: result.subagentId,
|
|
5897
|
+
taskId: result.taskId,
|
|
5898
|
+
status: result.status,
|
|
5899
|
+
iterations: result.iterations,
|
|
5900
|
+
toolCalls: result.toolCalls,
|
|
5901
|
+
durationMs: result.durationMs
|
|
5902
|
+
}
|
|
5903
|
+
});
|
|
5819
5904
|
this.tryDispatchNext();
|
|
5905
|
+
this.emitCoordinatorStats();
|
|
5820
5906
|
if (this.isDone()) {
|
|
5821
5907
|
this.emit("done", {
|
|
5822
5908
|
results: this.completedResults,
|