@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
|
@@ -397,6 +397,26 @@ interface EventMap {
|
|
|
397
397
|
revertedFiles: string[];
|
|
398
398
|
removedEvents: number;
|
|
399
399
|
};
|
|
400
|
+
/**
|
|
401
|
+
* Fired by the multi-agent coordinator on FleetBus whenever subagent
|
|
402
|
+
* counts change (spawn/stop/complete). The TUI subscribes to render
|
|
403
|
+
* live fleet counters without polling.
|
|
404
|
+
*/
|
|
405
|
+
'coordinator.stats': {
|
|
406
|
+
total: number;
|
|
407
|
+
running: number;
|
|
408
|
+
idle: number;
|
|
409
|
+
stopped: number;
|
|
410
|
+
inFlight: number;
|
|
411
|
+
pending: number;
|
|
412
|
+
completed: number;
|
|
413
|
+
subagentStatuses: {
|
|
414
|
+
subagentId: string;
|
|
415
|
+
taskId: string;
|
|
416
|
+
status: string;
|
|
417
|
+
assigned: boolean;
|
|
418
|
+
}[];
|
|
419
|
+
};
|
|
400
420
|
error: {
|
|
401
421
|
err: Error;
|
|
402
422
|
phase: string;
|
|
@@ -415,6 +435,14 @@ declare class EventBus {
|
|
|
415
435
|
on<E extends EventName>(event: E, fn: Listener<E>): () => void;
|
|
416
436
|
off<E extends EventName>(event: E, fn: Listener<E>): void;
|
|
417
437
|
once<E extends EventName>(event: E, fn: Listener<E>): () => void;
|
|
438
|
+
/**
|
|
439
|
+
* Subscribe to all events, regardless of name. Short-hand for
|
|
440
|
+
* `onPattern('*')`. Use for logging, debugging, or forwarding every
|
|
441
|
+
* event to another bus (as FleetBus does).
|
|
442
|
+
*
|
|
443
|
+
* Returns an unsubscribe function.
|
|
444
|
+
*/
|
|
445
|
+
onAny(fn: (event: string, payload: unknown) => void): () => void;
|
|
418
446
|
/**
|
|
419
447
|
* Subscribe to all events whose name matches a glob-style prefix.
|
|
420
448
|
* `'tool.*'` matches `tool.started`, `tool.executed`, `tool.progress`, etc.
|
|
@@ -496,6 +524,11 @@ declare class ScopedEventBus extends EventBus {
|
|
|
496
524
|
* our registration entry under a different key).
|
|
497
525
|
*/
|
|
498
526
|
once<E extends EventName>(event: E, fn: Listener<E>): () => void;
|
|
527
|
+
/**
|
|
528
|
+
* Subscribe to all events. Alias for `onPattern('*')` — the listener is
|
|
529
|
+
* tracked so that `teardown()` will remove it automatically.
|
|
530
|
+
*/
|
|
531
|
+
onAny(fn: (event: string, payload: unknown) => void): () => void;
|
|
499
532
|
/**
|
|
500
533
|
* Identical to `EventBus.onPattern` but the listener is tracked so that
|
|
501
534
|
* `teardown()` will remove it automatically.
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-
|
|
1
|
+
export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, H as HybridCompactor, T as ToolExecutor } from '../tool-executor-QwfWnQZ8.js';
|
|
2
2
|
import { m as Provider, d as Context } from '../context-z2x5gv_V.js';
|
|
3
3
|
import { a as Compactor, C as CompactReport } from '../compactor-Mw7-rNyb.js';
|
|
4
4
|
import { M as MessageSelector } from '../selector-DkvgYVS4.js';
|
|
5
|
-
import { E as EventBus } from '../events-
|
|
5
|
+
import { E as EventBus } from '../events-DyhxkstG.js';
|
|
6
6
|
import { b as MiddlewareHandler } from '../system-prompt-CWA6ml-d.js';
|
|
7
7
|
import { e as ContextWindowAggressiveOn, i as ContextWindowPolicy } from '../config-Bi4Q0fnz.js';
|
|
8
|
-
import { c as Agent, R as RunResult, w as SystemPromptContributor } from '../index-
|
|
9
|
-
import { D as DoneCondition } from '../multi-agent-
|
|
8
|
+
import { c as Agent, R as RunResult, w as SystemPromptContributor } from '../index-oYZeWsuJ.js';
|
|
9
|
+
import { D as DoneCondition } from '../multi-agent-CRMznZmf.js';
|
|
10
10
|
import { J as JournalEntry } from '../goal-store-C7jcumEh.js';
|
|
11
|
-
import { A as AgentFactory } from '../agent-subagent-runner-
|
|
12
|
-
import { f as DispatchClassifier, d as DefaultMultiAgentCoordinator } from '../multi-agent-coordinator-
|
|
11
|
+
import { A as AgentFactory } from '../agent-subagent-runner-Cav3yEJM.js';
|
|
12
|
+
import { f as DispatchClassifier, d as DefaultMultiAgentCoordinator } from '../multi-agent-coordinator-IQKrMfXz.js';
|
|
13
13
|
import { a as SkillLoader, b as SkillManifest, S as SkillEntry } from '../skill-CxuWrsKK.js';
|
|
14
14
|
import { a as WstackPaths } from '../wstack-paths-gCrJ631C.js';
|
|
15
15
|
import '../retry-policy-OwtKNxo8.js';
|
|
16
16
|
import '../models-registry-BcYJDKLm.js';
|
|
17
17
|
import '../logger-DDd5C--Z.js';
|
|
18
18
|
import '../observability-BhnVLBLS.js';
|
|
19
|
-
import '../secret-scrubber-
|
|
19
|
+
import '../secret-scrubber-CyE1-EMG.js';
|
|
20
20
|
import 'node:events';
|
|
21
21
|
|
|
22
22
|
interface SkillLoaderOptions {
|
|
@@ -210,6 +210,16 @@ declare class AutoCompactionMiddleware {
|
|
|
210
210
|
* short conversations, causing premature compaction triggers.
|
|
211
211
|
*/
|
|
212
212
|
private static readonly OVERHEAD_FACTOR;
|
|
213
|
+
/**
|
|
214
|
+
* Once a compaction attempt reduces nothing (preserveK protects everything,
|
|
215
|
+
* no oversized tool_results remain to elide), retrying on every iteration
|
|
216
|
+
* just spams `compaction.fired` events without making progress. We remember
|
|
217
|
+
* the no-op and skip until either the pressure level escalates or context
|
|
218
|
+
* has grown by at least this many tokens since the failed attempt.
|
|
219
|
+
*/
|
|
220
|
+
private static readonly NOOP_RETRY_DELTA_TOKENS;
|
|
221
|
+
/** Tracks the most recent no-op attempt so we can avoid re-firing per turn. */
|
|
222
|
+
private lastNoopAttempt;
|
|
213
223
|
/**
|
|
214
224
|
* @param compactor Compactor to use for compaction.
|
|
215
225
|
* @param maxContext Provider's max context window in tokens.
|
|
@@ -230,6 +240,13 @@ declare class AutoCompactionMiddleware {
|
|
|
230
240
|
* denominator when the active model changes. */
|
|
231
241
|
setMaxContext(maxContext: number): void;
|
|
232
242
|
handler(): MiddlewareHandler<Context>;
|
|
243
|
+
/**
|
|
244
|
+
* Returns true when the previous compaction at the same or higher pressure
|
|
245
|
+
* level reduced nothing and context has not grown materially since. Prevents
|
|
246
|
+
* a stuck preserveK window from spamming compaction events every iteration.
|
|
247
|
+
*/
|
|
248
|
+
private shouldSkipNoopRetry;
|
|
249
|
+
private recordAttempt;
|
|
233
250
|
private compact;
|
|
234
251
|
}
|
|
235
252
|
|
package/dist/execution/index.js
CHANGED
|
@@ -1004,6 +1004,7 @@ var FsError = class extends WrongStackError {
|
|
|
1004
1004
|
};
|
|
1005
1005
|
|
|
1006
1006
|
// src/execution/auto-compaction-middleware.ts
|
|
1007
|
+
var LEVEL_RANK = { warn: 0, soft: 1, hard: 2 };
|
|
1007
1008
|
var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
1008
1009
|
name = "AutoCompaction";
|
|
1009
1010
|
compactor;
|
|
@@ -1024,6 +1025,16 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
1024
1025
|
* short conversations, causing premature compaction triggers.
|
|
1025
1026
|
*/
|
|
1026
1027
|
static OVERHEAD_FACTOR = 1.3;
|
|
1028
|
+
/**
|
|
1029
|
+
* Once a compaction attempt reduces nothing (preserveK protects everything,
|
|
1030
|
+
* no oversized tool_results remain to elide), retrying on every iteration
|
|
1031
|
+
* just spams `compaction.fired` events without making progress. We remember
|
|
1032
|
+
* the no-op and skip until either the pressure level escalates or context
|
|
1033
|
+
* has grown by at least this many tokens since the failed attempt.
|
|
1034
|
+
*/
|
|
1035
|
+
static NOOP_RETRY_DELTA_TOKENS = 2e3;
|
|
1036
|
+
/** Tracks the most recent no-op attempt so we can avoid re-firing per turn. */
|
|
1037
|
+
lastNoopAttempt = null;
|
|
1027
1038
|
/**
|
|
1028
1039
|
* @param compactor Compactor to use for compaction.
|
|
1029
1040
|
* @param maxContext Provider's max context window in tokens.
|
|
@@ -1065,19 +1076,44 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
1065
1076
|
hard: this.hardThreshold
|
|
1066
1077
|
};
|
|
1067
1078
|
const aggressiveOn = policy?.aggressiveOn ?? this.aggressiveOn;
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1079
|
+
const level = load >= thresholds.hard ? "hard" : load >= thresholds.soft ? "soft" : load >= thresholds.warn ? "warn" : null;
|
|
1080
|
+
if (!level) {
|
|
1081
|
+
this.lastNoopAttempt = null;
|
|
1082
|
+
return next(ctx);
|
|
1083
|
+
}
|
|
1084
|
+
if (this.shouldSkipNoopRetry(level, tokens)) {
|
|
1085
|
+
return next(ctx);
|
|
1074
1086
|
}
|
|
1087
|
+
const aggressive = level === "hard" ? true : level === "soft" ? aggressiveOn !== "hard" : aggressiveOn === "warn";
|
|
1088
|
+
await this.compact(ctx, aggressive, { level, tokens, load });
|
|
1075
1089
|
return next(ctx);
|
|
1076
1090
|
};
|
|
1077
1091
|
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Returns true when the previous compaction at the same or higher pressure
|
|
1094
|
+
* level reduced nothing and context has not grown materially since. Prevents
|
|
1095
|
+
* a stuck preserveK window from spamming compaction events every iteration.
|
|
1096
|
+
*/
|
|
1097
|
+
shouldSkipNoopRetry(level, tokens) {
|
|
1098
|
+
const stuck = this.lastNoopAttempt;
|
|
1099
|
+
if (!stuck) return false;
|
|
1100
|
+
if (LEVEL_RANK[level] > LEVEL_RANK[stuck.level]) return false;
|
|
1101
|
+
const delta = tokens - stuck.tokens;
|
|
1102
|
+
return delta < _AutoCompactionMiddleware.NOOP_RETRY_DELTA_TOKENS;
|
|
1103
|
+
}
|
|
1104
|
+
recordAttempt(level, tokens, report) {
|
|
1105
|
+
const reduced = report.before > report.after;
|
|
1106
|
+
const repaired = !!report.repaired;
|
|
1107
|
+
if (reduced || repaired) {
|
|
1108
|
+
this.lastNoopAttempt = null;
|
|
1109
|
+
} else {
|
|
1110
|
+
this.lastNoopAttempt = { level, tokens };
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1078
1113
|
async compact(ctx, aggressive, pressure) {
|
|
1079
1114
|
try {
|
|
1080
1115
|
const report = await this.compactor.compact(ctx, { aggressive });
|
|
1116
|
+
this.recordAttempt(pressure.level, pressure.tokens, report);
|
|
1081
1117
|
this.events?.emit("compaction.fired", {
|
|
1082
1118
|
level: pressure.level,
|
|
1083
1119
|
tokens: pressure.tokens,
|
|
@@ -2393,29 +2429,35 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2393
2429
|
* same kind are no-ops — without this dedup, every `recordIteration`
|
|
2394
2430
|
* after the limit is reached spawns a fresh decision Promise (until
|
|
2395
2431
|
* the first one lands and patches limits), flooding the FleetBus
|
|
2396
|
-
* with redundant threshold events. Cleared in `
|
|
2432
|
+
* with redundant threshold events. Cleared in `negotiateExtension`'s
|
|
2397
2433
|
* `finally`.
|
|
2398
2434
|
*/
|
|
2399
2435
|
pendingExtensions = /* @__PURE__ */ new Set();
|
|
2400
2436
|
/**
|
|
2401
|
-
* Hard cap on how long `
|
|
2437
|
+
* Hard cap on how long `negotiateExtension` waits for the coordinator to
|
|
2402
2438
|
* respond before defaulting to 'stop'. Without this fallback an absent
|
|
2403
2439
|
* or hung listener (Director not built / event filter detached mid-run)
|
|
2404
|
-
* leaves the budget over-limit and never enforces anything
|
|
2405
|
-
* `checkLimit` returns synchronously via `void this.checkLimitAsync`.
|
|
2406
|
-
* Raised from 30s to 60s to give subagents more headroom before
|
|
2407
|
-
* the threshold negotiation times out and triggers a hard stop.
|
|
2440
|
+
* leaves the budget over-limit and never enforces anything.
|
|
2408
2441
|
*/
|
|
2409
2442
|
static DECISION_TIMEOUT_MS = 6e4;
|
|
2410
2443
|
/**
|
|
2411
2444
|
* Injected by the runner when wiring the budget to its EventBus.
|
|
2412
|
-
* Used
|
|
2445
|
+
* Used to emit `budget.threshold_reached` events in `'auto'` mode.
|
|
2413
2446
|
*/
|
|
2414
2447
|
_events;
|
|
2448
|
+
/**
|
|
2449
|
+
* Negotiation mode — controls whether a threshold hit tries to emit
|
|
2450
|
+
* `budget.threshold_reached` and wait for a coordinator decision, or
|
|
2451
|
+
* falls straight through to a synchronous hard stop.
|
|
2452
|
+
*
|
|
2453
|
+
* `'auto'` (default) — emit on the EventBus and wait; times out to 'stop'.
|
|
2454
|
+
* `'sync'` — throw `BudgetExceededError` immediately regardless of listeners.
|
|
2455
|
+
*/
|
|
2456
|
+
_mode;
|
|
2415
2457
|
/**
|
|
2416
2458
|
* Optional callback for soft-limit handling. When set, the budget will
|
|
2417
|
-
*
|
|
2418
|
-
*
|
|
2459
|
+
* invoke it rather than throw immediately. The handler decides whether to
|
|
2460
|
+
* throw synchronously, continue, or ask the coordinator for an extension.
|
|
2419
2461
|
*/
|
|
2420
2462
|
get onThreshold() {
|
|
2421
2463
|
return this._onThreshold;
|
|
@@ -2423,7 +2465,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2423
2465
|
set onThreshold(fn) {
|
|
2424
2466
|
this._onThreshold = fn;
|
|
2425
2467
|
}
|
|
2426
|
-
|
|
2468
|
+
/** Returns the current negotiation mode. */
|
|
2469
|
+
get mode() {
|
|
2470
|
+
return this._mode;
|
|
2471
|
+
}
|
|
2472
|
+
constructor(limits = {}, mode = "auto") {
|
|
2473
|
+
this._mode = mode;
|
|
2427
2474
|
this.limits = { ...limits };
|
|
2428
2475
|
}
|
|
2429
2476
|
start() {
|
|
@@ -2439,16 +2486,23 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2439
2486
|
return false;
|
|
2440
2487
|
}
|
|
2441
2488
|
/**
|
|
2442
|
-
* Synchronous budget check
|
|
2443
|
-
*
|
|
2444
|
-
*
|
|
2445
|
-
*
|
|
2446
|
-
*
|
|
2489
|
+
* Synchronous budget check. Always throws synchronously so callers (especially
|
|
2490
|
+
* test event handlers using `expect().toThrow()`) get an unhandled rejection
|
|
2491
|
+
* when the budget is exceeded without a handler.
|
|
2492
|
+
*
|
|
2493
|
+
* Decision table:
|
|
2494
|
+
* - no `onThreshold` handler → throw `BudgetExceededError` (hard stop, always)
|
|
2495
|
+
* - `mode === 'sync'` → throw `BudgetExceededError` (hard stop, always)
|
|
2496
|
+
* - `mode === 'auto'` + no listener → throw `BudgetExceededError` (hard stop; no one to ask)
|
|
2497
|
+
* - `mode === 'auto'` + listener → throw `BudgetThresholdSignal` with async decision promise
|
|
2447
2498
|
*/
|
|
2448
2499
|
checkLimit(kind, used, limit) {
|
|
2449
2500
|
if (!this._onThreshold) {
|
|
2450
2501
|
throw new BudgetExceededError(kind, limit, used);
|
|
2451
2502
|
}
|
|
2503
|
+
if (this._mode === "sync") {
|
|
2504
|
+
throw new BudgetExceededError(kind, limit, used);
|
|
2505
|
+
}
|
|
2452
2506
|
const bus = this._events;
|
|
2453
2507
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
2454
2508
|
throw new BudgetExceededError(kind, limit, used);
|
|
@@ -2465,8 +2519,8 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2465
2519
|
* `pendingExtensions` slot in `finally`.
|
|
2466
2520
|
*
|
|
2467
2521
|
* The 'continue' return from a sync handler is treated as
|
|
2468
|
-
* `{ extend: {} }` — keep going without patching
|
|
2469
|
-
*
|
|
2522
|
+
* `{ extend: {} }` — keep going without patching; next overrun fires
|
|
2523
|
+
* a fresh signal.
|
|
2470
2524
|
*/
|
|
2471
2525
|
async negotiateExtension(kind, used, limit) {
|
|
2472
2526
|
try {
|
|
@@ -2474,11 +2528,6 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2474
2528
|
kind,
|
|
2475
2529
|
used,
|
|
2476
2530
|
limit,
|
|
2477
|
-
// Inject a requestDecision helper the handler can call to emit the
|
|
2478
|
-
// budget.threshold_reached event and wait for the coordinator's verdict.
|
|
2479
|
-
// A hard fallback timer guarantees the promise eventually resolves
|
|
2480
|
-
// even if no listener responds — without it, an absent/detached
|
|
2481
|
-
// Director would leave the budget permanently in "asking" state.
|
|
2482
2531
|
requestDecision: () => {
|
|
2483
2532
|
const bus = this._events;
|
|
2484
2533
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
@@ -2562,12 +2611,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2562
2611
|
}
|
|
2563
2612
|
}
|
|
2564
2613
|
/**
|
|
2565
|
-
* Wall-clock budget check. Unlike other limits, timeout
|
|
2566
|
-
*
|
|
2567
|
-
*
|
|
2568
|
-
*
|
|
2569
|
-
*
|
|
2570
|
-
*
|
|
2614
|
+
* Wall-clock budget check. Unlike other limits, timeout check passes through
|
|
2615
|
+
* `checkLimit` and is subject to the same negotiation-mode decision table.
|
|
2616
|
+
* In practice, `'sync'` mode (the usual test configuration) means a timeout
|
|
2617
|
+
* immediately throws `BudgetExceededError`. In production with a coordinator,
|
|
2618
|
+
* a timeout emits `budget.threshold_reached` so the Director can decide whether
|
|
2619
|
+
* to extend or abort.
|
|
2571
2620
|
*/
|
|
2572
2621
|
checkTimeout() {
|
|
2573
2622
|
if (this.startTime === null || this.limits.timeoutMs === void 0) return;
|
|
@@ -4934,8 +4983,7 @@ function scoreAgents(task, catalog = AGENT_CATALOG) {
|
|
|
4934
4983
|
const hay = normalize(task);
|
|
4935
4984
|
const out = [];
|
|
4936
4985
|
for (const def of Object.values(catalog)) {
|
|
4937
|
-
|
|
4938
|
-
if (!role) continue;
|
|
4986
|
+
if (!def?.config?.role) continue;
|
|
4939
4987
|
let score = 0;
|
|
4940
4988
|
const matched = [];
|
|
4941
4989
|
for (const kw of def.capability.keywords) {
|
|
@@ -4947,7 +4995,7 @@ function scoreAgents(task, catalog = AGENT_CATALOG) {
|
|
|
4947
4995
|
}
|
|
4948
4996
|
}
|
|
4949
4997
|
if (score > 0) {
|
|
4950
|
-
out.push({ role, name: def.config.name, score, matched });
|
|
4998
|
+
out.push({ role: def.config.role, name: def.config.name, score, matched });
|
|
4951
4999
|
}
|
|
4952
5000
|
}
|
|
4953
5001
|
out.sort((a, b) => b.score - a.score);
|
|
@@ -5189,6 +5237,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5189
5237
|
coordinatorId;
|
|
5190
5238
|
config;
|
|
5191
5239
|
runner;
|
|
5240
|
+
fleetBus;
|
|
5192
5241
|
subagents = /* @__PURE__ */ new Map();
|
|
5193
5242
|
pendingTasks = [];
|
|
5194
5243
|
completedResults = [];
|
|
@@ -5217,6 +5266,14 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5217
5266
|
setRunner(runner) {
|
|
5218
5267
|
this.runner = runner;
|
|
5219
5268
|
}
|
|
5269
|
+
/**
|
|
5270
|
+
* Wire a FleetBus for director-mode event emission. Call after the
|
|
5271
|
+
* FleetManager is constructed so the coordinator can emit lifecycle
|
|
5272
|
+
* events the TUI and monitoring tools subscribe to.
|
|
5273
|
+
*/
|
|
5274
|
+
setFleetBus(fleet) {
|
|
5275
|
+
this.fleetBus = fleet;
|
|
5276
|
+
}
|
|
5220
5277
|
/**
|
|
5221
5278
|
* Change the in-flight dispatch ceiling at runtime. Lowering does NOT
|
|
5222
5279
|
* preempt running tasks — already-dispatched subagents finish their
|
|
@@ -5252,6 +5309,18 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5252
5309
|
abortController: new AbortController()
|
|
5253
5310
|
});
|
|
5254
5311
|
this.emit("subagent.started", { subagent: { ...subagent, id } });
|
|
5312
|
+
this.fleetBus?.emit({
|
|
5313
|
+
subagentId: id,
|
|
5314
|
+
ts: Date.now(),
|
|
5315
|
+
type: "subagent.assigned",
|
|
5316
|
+
payload: {
|
|
5317
|
+
subagentId: id,
|
|
5318
|
+
name: subagent.name,
|
|
5319
|
+
provider: subagent.provider,
|
|
5320
|
+
model: subagent.model
|
|
5321
|
+
}
|
|
5322
|
+
});
|
|
5323
|
+
this.emitCoordinatorStats();
|
|
5255
5324
|
return { subagentId: id, agentId: id };
|
|
5256
5325
|
}
|
|
5257
5326
|
async assign(task) {
|
|
@@ -5284,6 +5353,13 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5284
5353
|
subagent.currentTask = void 0;
|
|
5285
5354
|
subagent.context.parentBridge = null;
|
|
5286
5355
|
this.emit("subagent.stopped", { subagentId, reason: "stopped by coordinator" });
|
|
5356
|
+
this.fleetBus?.emit({
|
|
5357
|
+
subagentId,
|
|
5358
|
+
ts: Date.now(),
|
|
5359
|
+
type: "subagent.stopped",
|
|
5360
|
+
payload: { subagentId, reason: "stopped by coordinator" }
|
|
5361
|
+
});
|
|
5362
|
+
this.emitCoordinatorStats();
|
|
5287
5363
|
}
|
|
5288
5364
|
async stopAll() {
|
|
5289
5365
|
this.drainPendingAsAborted("Coordinator stopAll() drained the pending queue");
|
|
@@ -5315,6 +5391,22 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5315
5391
|
completed: this.completedResults.length
|
|
5316
5392
|
};
|
|
5317
5393
|
}
|
|
5394
|
+
/** Emit a reactive coordinator.stats event on FleetBus so the TUI can subscribe. */
|
|
5395
|
+
emitCoordinatorStats() {
|
|
5396
|
+
const stats = this.getStats();
|
|
5397
|
+
const subagentStatuses = Array.from(this.subagents.entries()).map(([id, s]) => ({
|
|
5398
|
+
subagentId: id,
|
|
5399
|
+
taskId: s.currentTask ?? "",
|
|
5400
|
+
status: s.status,
|
|
5401
|
+
assigned: s.context.parentBridge !== null
|
|
5402
|
+
}));
|
|
5403
|
+
this.fleetBus?.emit({
|
|
5404
|
+
subagentId: this.coordinatorId,
|
|
5405
|
+
ts: Date.now(),
|
|
5406
|
+
type: "coordinator.stats",
|
|
5407
|
+
payload: { ...stats, subagentStatuses }
|
|
5408
|
+
});
|
|
5409
|
+
}
|
|
5318
5410
|
getStatus() {
|
|
5319
5411
|
return {
|
|
5320
5412
|
coordinatorId: this.coordinatorId,
|
|
@@ -5489,7 +5581,15 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5489
5581
|
subagent.currentTask = task.id;
|
|
5490
5582
|
task.subagentId = subagentId;
|
|
5491
5583
|
subagent.context.tasks.push(task);
|
|
5584
|
+
this.fleetBus?.emit({
|
|
5585
|
+
subagentId,
|
|
5586
|
+
taskId: task.id,
|
|
5587
|
+
ts: Date.now(),
|
|
5588
|
+
type: "subagent.running",
|
|
5589
|
+
payload: { subagentId, taskId: task.id }
|
|
5590
|
+
});
|
|
5492
5591
|
this.emit("task.assigned", { task, subagentId });
|
|
5592
|
+
this.emitCoordinatorStats();
|
|
5493
5593
|
const rawMaxIterations = subagent.config.maxIterations;
|
|
5494
5594
|
const rawMaxToolCalls = subagent.config.maxToolCalls;
|
|
5495
5595
|
const rawMaxTokens = subagent.config.maxTokens;
|
|
@@ -5633,13 +5733,34 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
5633
5733
|
if (subagent.abortController.signal.aborted) {
|
|
5634
5734
|
subagent.abortController = new AbortController();
|
|
5635
5735
|
}
|
|
5736
|
+
this.fleetBus?.emit({
|
|
5737
|
+
subagentId: result.subagentId,
|
|
5738
|
+
ts: Date.now(),
|
|
5739
|
+
type: "subagent.idle",
|
|
5740
|
+
payload: { subagentId: result.subagentId }
|
|
5741
|
+
});
|
|
5636
5742
|
}
|
|
5637
5743
|
this.terminating.delete(result.subagentId);
|
|
5638
5744
|
this.emit("task.completed", {
|
|
5639
5745
|
task: subagent?.context.tasks.find((t) => t.id === result.taskId) ?? { id: result.taskId },
|
|
5640
5746
|
result
|
|
5641
5747
|
});
|
|
5748
|
+
this.fleetBus?.emit({
|
|
5749
|
+
subagentId: result.subagentId,
|
|
5750
|
+
taskId: result.taskId,
|
|
5751
|
+
ts: Date.now(),
|
|
5752
|
+
type: "subagent.completed",
|
|
5753
|
+
payload: {
|
|
5754
|
+
subagentId: result.subagentId,
|
|
5755
|
+
taskId: result.taskId,
|
|
5756
|
+
status: result.status,
|
|
5757
|
+
iterations: result.iterations,
|
|
5758
|
+
toolCalls: result.toolCalls,
|
|
5759
|
+
durationMs: result.durationMs
|
|
5760
|
+
}
|
|
5761
|
+
});
|
|
5642
5762
|
this.tryDispatchNext();
|
|
5763
|
+
this.emitCoordinatorStats();
|
|
5643
5764
|
if (this.isDone()) {
|
|
5644
5765
|
this.emit("done", {
|
|
5645
5766
|
results: this.completedResults,
|