@wrongstack/cli 0.257.0 → 0.257.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/index.js +239 -113
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
package/dist/index.js
CHANGED
|
@@ -5729,15 +5729,14 @@ function gitText(args, cwd) {
|
|
|
5729
5729
|
reject(err);
|
|
5730
5730
|
return;
|
|
5731
5731
|
}
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
if (
|
|
5735
|
-
}
|
|
5736
|
-
child.
|
|
5737
|
-
|
|
5738
|
-
});
|
|
5739
|
-
child.on("
|
|
5740
|
-
child.on("close", (code) => resolve10({ code: code ?? 1, out: out.trim() }));
|
|
5732
|
+
const chunks = [];
|
|
5733
|
+
const emit = (c) => {
|
|
5734
|
+
if (chunks.join("").length < MAX_CMD_OUTPUT) chunks.push(c.toString());
|
|
5735
|
+
};
|
|
5736
|
+
child.stdout?.on("data", emit);
|
|
5737
|
+
child.stderr?.on("data", emit);
|
|
5738
|
+
child.on("error", () => resolve10({ code: 1, out: chunks.join("") }));
|
|
5739
|
+
child.on("close", (code) => resolve10({ code: code ?? 1, out: chunks.join("").trim() }));
|
|
5741
5740
|
});
|
|
5742
5741
|
}
|
|
5743
5742
|
async function isGitRepo(cwd) {
|
|
@@ -5774,7 +5773,7 @@ function runCmd(cmd, args, cwd, shell = false) {
|
|
|
5774
5773
|
}
|
|
5775
5774
|
}
|
|
5776
5775
|
return new Promise((resolve10, reject) => {
|
|
5777
|
-
|
|
5776
|
+
const chunks = [];
|
|
5778
5777
|
let child;
|
|
5779
5778
|
try {
|
|
5780
5779
|
child = spawn(cmd, args, {
|
|
@@ -5792,13 +5791,16 @@ function runCmd(cmd, args, cwd, shell = false) {
|
|
|
5792
5791
|
return;
|
|
5793
5792
|
}
|
|
5794
5793
|
const append = (c) => {
|
|
5795
|
-
|
|
5796
|
-
if (out.length > MAX_CMD_OUTPUT) out = out.slice(-MAX_CMD_OUTPUT);
|
|
5794
|
+
chunks.push(c.toString());
|
|
5797
5795
|
};
|
|
5798
5796
|
child.stdout?.on("data", append);
|
|
5799
5797
|
child.stderr?.on("data", append);
|
|
5800
|
-
child.on("error", (e) => resolve10({ code: 1, out: `${
|
|
5801
|
-
child.on("close", (code) =>
|
|
5798
|
+
child.on("error", (e) => resolve10({ code: 1, out: `${chunks.join("")}${String(e)}` }));
|
|
5799
|
+
child.on("close", (code) => {
|
|
5800
|
+
let out = chunks.join("");
|
|
5801
|
+
if (out.length > MAX_CMD_OUTPUT) out = out.slice(-MAX_CMD_OUTPUT);
|
|
5802
|
+
resolve10({ code: code ?? 1, out: out.trim() });
|
|
5803
|
+
});
|
|
5802
5804
|
});
|
|
5803
5805
|
}
|
|
5804
5806
|
function detectPackageManager(root) {
|
|
@@ -8651,8 +8653,19 @@ function listRoles() {
|
|
|
8651
8653
|
}
|
|
8652
8654
|
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
8653
8655
|
var MAX_OUTPUT_LINES = 500;
|
|
8656
|
+
var WINDOWS_CMD_METACHARACTERS = /[;&|<>^$,(){}[\]!#%'"\\/`]/;
|
|
8657
|
+
function validateCommand(cmd) {
|
|
8658
|
+
if (process.platform !== "win32") return;
|
|
8659
|
+
if (WINDOWS_CMD_METACHARACTERS.test(cmd)) {
|
|
8660
|
+
throw new Error(
|
|
8661
|
+
`Command contains disallowed metacharacters for Windows: ${cmd.match(WINDOWS_CMD_METACHARACTERS)?.[0] ?? "?"}
|
|
8662
|
+
The following characters are not allowed: ; & | < > ^ $ , ( ) { } [ ] ! # % ' " \\ / \` * ?`
|
|
8663
|
+
);
|
|
8664
|
+
}
|
|
8665
|
+
}
|
|
8654
8666
|
function runCommand(cmd, cwd, timeout) {
|
|
8655
8667
|
return new Promise((resolve10) => {
|
|
8668
|
+
validateCommand(cmd);
|
|
8656
8669
|
const opts = {
|
|
8657
8670
|
cwd,
|
|
8658
8671
|
timeout,
|
|
@@ -8733,6 +8746,7 @@ Examples:
|
|
|
8733
8746
|
/dev git diff --stat`
|
|
8734
8747
|
};
|
|
8735
8748
|
}
|
|
8749
|
+
validateCommand(cmd);
|
|
8736
8750
|
const cwd = opts.cwd;
|
|
8737
8751
|
const startedAt = Date.now();
|
|
8738
8752
|
opts.renderer.write(color.dim(`$ ${cmd}`));
|
|
@@ -10430,11 +10444,11 @@ function classifyError(input) {
|
|
|
10430
10444
|
}
|
|
10431
10445
|
function extractCode(s) {
|
|
10432
10446
|
const ts = /\bTS\d+\b|\bCS\d+\b/.exec(s);
|
|
10433
|
-
if (ts) return ts[0];
|
|
10447
|
+
if (ts !== null) return ts[0];
|
|
10434
10448
|
const rust = /\bE\d{4,}\b/.exec(s);
|
|
10435
|
-
if (rust) return rust[0];
|
|
10449
|
+
if (rust !== null) return rust[0];
|
|
10436
10450
|
const c = /\bc\d+\b/i.exec(s);
|
|
10437
|
-
if (c) return c[0];
|
|
10451
|
+
if (c !== null) return c[0];
|
|
10438
10452
|
return void 0;
|
|
10439
10453
|
}
|
|
10440
10454
|
function needsSubagent(c) {
|
|
@@ -12160,8 +12174,20 @@ async function runAdd(name, enable, configured, configPath2, mcpRegistry, all) {
|
|
|
12160
12174
|
}
|
|
12161
12175
|
async function runRemove(name, configured, configPath2, mcpRegistry) {
|
|
12162
12176
|
if (!configured[name]) return `Server "${name}" is not in config.`;
|
|
12163
|
-
|
|
12164
|
-
|
|
12177
|
+
try {
|
|
12178
|
+
await mcpRegistry.stop(name);
|
|
12179
|
+
} catch (err) {
|
|
12180
|
+
console.error(
|
|
12181
|
+
JSON.stringify({
|
|
12182
|
+
level: "warn",
|
|
12183
|
+
event: "mcp.stop_failed_on_remove",
|
|
12184
|
+
server: name,
|
|
12185
|
+
message: err instanceof Error ? err.message : String(err),
|
|
12186
|
+
note: "config entry removed but server may still be running",
|
|
12187
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
12188
|
+
})
|
|
12189
|
+
);
|
|
12190
|
+
}
|
|
12165
12191
|
const full = await readConfig(configPath2);
|
|
12166
12192
|
const mcpServers = {
|
|
12167
12193
|
...full.mcpServers ?? {}
|
|
@@ -12200,8 +12226,20 @@ async function runEnable(name, configured, configPath2, mcpRegistry) {
|
|
|
12200
12226
|
async function runDisable(name, configured, configPath2, mcpRegistry) {
|
|
12201
12227
|
const cfg = configured[name];
|
|
12202
12228
|
if (!cfg) return `Server "${name}" is not in config.`;
|
|
12203
|
-
|
|
12204
|
-
|
|
12229
|
+
try {
|
|
12230
|
+
await mcpRegistry.stop(name);
|
|
12231
|
+
} catch (err) {
|
|
12232
|
+
console.error(
|
|
12233
|
+
JSON.stringify({
|
|
12234
|
+
level: "warn",
|
|
12235
|
+
event: "mcp.stop_failed_on_disable",
|
|
12236
|
+
server: name,
|
|
12237
|
+
message: err instanceof Error ? err.message : String(err),
|
|
12238
|
+
note: "config marked disabled but server may still be running",
|
|
12239
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
12240
|
+
})
|
|
12241
|
+
);
|
|
12242
|
+
}
|
|
12205
12243
|
const full = await readConfig(configPath2);
|
|
12206
12244
|
const mcpServers = {
|
|
12207
12245
|
...full.mcpServers ?? {}
|
|
@@ -21735,22 +21773,22 @@ function renderFleetLine(states, now, columns, version) {
|
|
|
21735
21773
|
const visible = line.replace(/\x1b\[[0-9;]*m/g, "");
|
|
21736
21774
|
if (visible.length > max) {
|
|
21737
21775
|
let count = 0;
|
|
21738
|
-
|
|
21776
|
+
const out = [];
|
|
21739
21777
|
let i = 0;
|
|
21740
21778
|
while (i < line.length && count < max - 1) {
|
|
21741
21779
|
if (line[i] === "\x1B") {
|
|
21742
21780
|
const end = line.indexOf("m", i);
|
|
21743
21781
|
if (end !== -1) {
|
|
21744
|
-
out
|
|
21782
|
+
out.push(line.slice(i, end + 1));
|
|
21745
21783
|
i = end + 1;
|
|
21746
21784
|
continue;
|
|
21747
21785
|
}
|
|
21748
21786
|
}
|
|
21749
|
-
|
|
21787
|
+
if (line[i] !== void 0) out.push(line[i]);
|
|
21750
21788
|
count++;
|
|
21751
21789
|
i++;
|
|
21752
21790
|
}
|
|
21753
|
-
line = out + "\u2026";
|
|
21791
|
+
line = out.join("") + "\u2026";
|
|
21754
21792
|
}
|
|
21755
21793
|
return line;
|
|
21756
21794
|
}
|
|
@@ -23537,31 +23575,35 @@ async function execute(deps) {
|
|
|
23537
23575
|
const metaMode = context.meta?.["mode"];
|
|
23538
23576
|
return typeof metaMode === "string" ? metaMode : modeId ?? "default";
|
|
23539
23577
|
},
|
|
23540
|
-
registerDebugStreamCallback: (cb) => {
|
|
23541
|
-
|
|
23542
|
-
|
|
23578
|
+
registerDebugStreamCallback: async (cb) => {
|
|
23579
|
+
try {
|
|
23580
|
+
const { setDebugStreamCallback } = await import('@wrongstack/providers');
|
|
23581
|
+
setDebugStreamCallback(cb);
|
|
23582
|
+
} catch (err) {
|
|
23583
|
+
console.error(
|
|
23543
23584
|
JSON.stringify({
|
|
23544
23585
|
level: "error",
|
|
23545
23586
|
event: "execution.debug_stream_register_failed",
|
|
23546
23587
|
message: err instanceof Error ? err.message : String(err),
|
|
23547
23588
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
23548
23589
|
})
|
|
23549
|
-
)
|
|
23550
|
-
|
|
23590
|
+
);
|
|
23591
|
+
}
|
|
23551
23592
|
},
|
|
23552
|
-
restoreDebugStreamCallback: () => {
|
|
23553
|
-
|
|
23554
|
-
|
|
23555
|
-
|
|
23556
|
-
|
|
23593
|
+
restoreDebugStreamCallback: async () => {
|
|
23594
|
+
try {
|
|
23595
|
+
const { setDebugStreamCallback, defaultDebugStreamCallback } = await import('@wrongstack/providers');
|
|
23596
|
+
setDebugStreamCallback(defaultDebugStreamCallback);
|
|
23597
|
+
} catch (err) {
|
|
23598
|
+
console.error(
|
|
23557
23599
|
JSON.stringify({
|
|
23558
23600
|
level: "error",
|
|
23559
23601
|
event: "execution.debug_stream_restore_failed",
|
|
23560
23602
|
message: err instanceof Error ? err.message : String(err),
|
|
23561
23603
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
23562
23604
|
})
|
|
23563
|
-
)
|
|
23564
|
-
|
|
23605
|
+
);
|
|
23606
|
+
}
|
|
23565
23607
|
},
|
|
23566
23608
|
restoredMessages,
|
|
23567
23609
|
restoredToolCalls,
|
|
@@ -23616,12 +23658,14 @@ async function execute(deps) {
|
|
|
23616
23658
|
if (oldWriter && oldWriter !== resumed.writer) {
|
|
23617
23659
|
const endedUsage = tokenCounter.total();
|
|
23618
23660
|
void (async () => {
|
|
23661
|
+
let appendOk = false;
|
|
23619
23662
|
try {
|
|
23620
23663
|
await oldWriter.append({
|
|
23621
23664
|
type: "session_end",
|
|
23622
23665
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23623
23666
|
usage: endedUsage
|
|
23624
23667
|
});
|
|
23668
|
+
appendOk = true;
|
|
23625
23669
|
} catch (err) {
|
|
23626
23670
|
console.error(
|
|
23627
23671
|
JSON.stringify({
|
|
@@ -23632,32 +23676,50 @@ async function execute(deps) {
|
|
|
23632
23676
|
})
|
|
23633
23677
|
);
|
|
23634
23678
|
}
|
|
23635
|
-
|
|
23636
|
-
|
|
23637
|
-
|
|
23638
|
-
|
|
23639
|
-
|
|
23640
|
-
|
|
23641
|
-
|
|
23642
|
-
|
|
23643
|
-
|
|
23644
|
-
|
|
23645
|
-
|
|
23679
|
+
if (appendOk) {
|
|
23680
|
+
try {
|
|
23681
|
+
await oldWriter.close();
|
|
23682
|
+
} catch (err) {
|
|
23683
|
+
console.error(
|
|
23684
|
+
JSON.stringify({
|
|
23685
|
+
level: "error",
|
|
23686
|
+
event: "execution.session_close_failed",
|
|
23687
|
+
message: err instanceof Error ? err.message : String(err),
|
|
23688
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
23689
|
+
})
|
|
23690
|
+
);
|
|
23691
|
+
}
|
|
23646
23692
|
}
|
|
23647
23693
|
})();
|
|
23648
23694
|
}
|
|
23649
23695
|
agent.ctx.session = resumed.writer;
|
|
23650
23696
|
tokenCounter.reset();
|
|
23651
|
-
void
|
|
23652
|
-
|
|
23653
|
-
|
|
23654
|
-
|
|
23655
|
-
|
|
23656
|
-
|
|
23657
|
-
|
|
23658
|
-
|
|
23659
|
-
|
|
23660
|
-
|
|
23697
|
+
void (async () => {
|
|
23698
|
+
try {
|
|
23699
|
+
await recoveryLock.clear();
|
|
23700
|
+
} catch (err) {
|
|
23701
|
+
console.error(
|
|
23702
|
+
JSON.stringify({
|
|
23703
|
+
level: "warn",
|
|
23704
|
+
event: "execution.recovery_lock_clear_failed",
|
|
23705
|
+
message: err instanceof Error ? err.message : String(err),
|
|
23706
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
23707
|
+
})
|
|
23708
|
+
);
|
|
23709
|
+
}
|
|
23710
|
+
try {
|
|
23711
|
+
await recoveryLock.write(resumed.writer.id);
|
|
23712
|
+
} catch (err) {
|
|
23713
|
+
console.error(
|
|
23714
|
+
JSON.stringify({
|
|
23715
|
+
level: "error",
|
|
23716
|
+
event: "execution.recovery_lock_update_failed",
|
|
23717
|
+
message: err instanceof Error ? err.message : String(err),
|
|
23718
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
23719
|
+
})
|
|
23720
|
+
);
|
|
23721
|
+
}
|
|
23722
|
+
})();
|
|
23661
23723
|
const { replaySessionEvents } = await import('@wrongstack/tui');
|
|
23662
23724
|
const entries = replaySessionEvents(
|
|
23663
23725
|
resumed.data.events,
|
|
@@ -24003,7 +24065,7 @@ function buildRoutingRunner(config, host) {
|
|
|
24003
24065
|
}
|
|
24004
24066
|
|
|
24005
24067
|
// src/fleet/host.ts
|
|
24006
|
-
var MultiAgentHost = class {
|
|
24068
|
+
var MultiAgentHost = class _MultiAgentHost {
|
|
24007
24069
|
constructor(deps, opts = {}) {
|
|
24008
24070
|
this.deps = deps;
|
|
24009
24071
|
this.opts = opts;
|
|
@@ -24032,6 +24094,19 @@ var MultiAgentHost = class {
|
|
|
24032
24094
|
* actionable error instead of a generic "Director could not be activated".
|
|
24033
24095
|
*/
|
|
24034
24096
|
promotionBlockReason = null;
|
|
24097
|
+
/** Guards `buildDirector` from overwriting a runner set by `spawnACP`. */
|
|
24098
|
+
directorRunnerSet = false;
|
|
24099
|
+
/** Event-bus off-handles registered in `buildDirector` — cleaned up in `dispose()`. */
|
|
24100
|
+
directorOffHandles = [];
|
|
24101
|
+
/** Coordinator task.assigned listener — cleaned up in `dispose()`. */
|
|
24102
|
+
coordinatorOffHandle = null;
|
|
24103
|
+
/** ACP runner cache — keyed by role/subagentId, reused across tasks to avoid
|
|
24104
|
+
* creating a new transport process on every ACP task dispatch. Stores the
|
|
24105
|
+
* pending promise so concurrent calls for the same subagentId share one spawn.
|
|
24106
|
+
* Bounded to 20 entries with LRU eviction to prevent unbounded memory growth. */
|
|
24107
|
+
acpRunnerCache = /* @__PURE__ */ new Map();
|
|
24108
|
+
acpRunnerAccessOrder = [];
|
|
24109
|
+
static ACP_CACHE_MAX = 20;
|
|
24035
24110
|
/**
|
|
24036
24111
|
* Force the lazy build path to run *now* and return the live Director,
|
|
24037
24112
|
* or null when director mode is off. Used by the CLI to register the
|
|
@@ -24113,60 +24188,71 @@ var MultiAgentHost = class {
|
|
|
24113
24188
|
this.fleetManager?.removePendingTask(task.id);
|
|
24114
24189
|
this.emitLifecycleCompleted(task.id, result);
|
|
24115
24190
|
});
|
|
24116
|
-
this.
|
|
24117
|
-
|
|
24118
|
-
|
|
24119
|
-
|
|
24120
|
-
|
|
24121
|
-
|
|
24122
|
-
|
|
24123
|
-
|
|
24124
|
-
});
|
|
24125
|
-
this.director.fleet.filter("budget.extended", (e) => {
|
|
24126
|
-
const payload = e.payload;
|
|
24127
|
-
this.deps.events.emit("subagent.budget_extended", {
|
|
24128
|
-
subagentId: e.subagentId,
|
|
24129
|
-
kind: payload.kind,
|
|
24130
|
-
newLimit: payload.newLimit,
|
|
24131
|
-
totalExtensions: payload.totalExtensions
|
|
24132
|
-
});
|
|
24133
|
-
});
|
|
24134
|
-
this.director.fleet.filter("ctx.pct", (e) => {
|
|
24135
|
-
const payload = e.payload;
|
|
24136
|
-
this.deps.events.emit("subagent.ctx_pct", {
|
|
24137
|
-
subagentId: e.subagentId,
|
|
24138
|
-
load: payload.load,
|
|
24139
|
-
tokens: payload.tokens,
|
|
24140
|
-
maxContext: payload.maxContext
|
|
24141
|
-
});
|
|
24142
|
-
});
|
|
24143
|
-
this.director.fleet.filter("subagent.spawned", (e) => {
|
|
24144
|
-
const payload = e.payload;
|
|
24145
|
-
this.deps.events.emit("subagent.spawned", {
|
|
24146
|
-
subagentId: payload.subagentId,
|
|
24147
|
-
taskId: payload.taskId,
|
|
24148
|
-
name: payload.name,
|
|
24149
|
-
provider: payload.provider,
|
|
24150
|
-
model: payload.model
|
|
24151
|
-
});
|
|
24152
|
-
});
|
|
24153
|
-
this.getCoordinator().on(
|
|
24154
|
-
"task.assigned",
|
|
24155
|
-
({
|
|
24156
|
-
task,
|
|
24157
|
-
subagentId
|
|
24158
|
-
}) => {
|
|
24159
|
-
this.deps.events.emit("subagent.task_started", {
|
|
24160
|
-
subagentId,
|
|
24161
|
-
taskId: task.id,
|
|
24162
|
-
description: task.description
|
|
24191
|
+
this.directorOffHandles.push(
|
|
24192
|
+
this.director.fleet.filter("budget.threshold_reached", (e) => {
|
|
24193
|
+
const payload = e.payload;
|
|
24194
|
+
this.deps.events.emit("subagent.budget_warning", {
|
|
24195
|
+
subagentId: e.subagentId,
|
|
24196
|
+
kind: payload.kind,
|
|
24197
|
+
used: payload.used,
|
|
24198
|
+
limit: payload.limit
|
|
24163
24199
|
});
|
|
24164
|
-
}
|
|
24200
|
+
})
|
|
24201
|
+
);
|
|
24202
|
+
this.directorOffHandles.push(
|
|
24203
|
+
this.director.fleet.filter("budget.extended", (e) => {
|
|
24204
|
+
const payload = e.payload;
|
|
24205
|
+
this.deps.events.emit("subagent.budget_extended", {
|
|
24206
|
+
subagentId: e.subagentId,
|
|
24207
|
+
kind: payload.kind,
|
|
24208
|
+
newLimit: payload.newLimit,
|
|
24209
|
+
totalExtensions: payload.totalExtensions
|
|
24210
|
+
});
|
|
24211
|
+
})
|
|
24212
|
+
);
|
|
24213
|
+
this.directorOffHandles.push(
|
|
24214
|
+
this.director.fleet.filter("ctx.pct", (e) => {
|
|
24215
|
+
const payload = e.payload;
|
|
24216
|
+
this.deps.events.emit("subagent.ctx_pct", {
|
|
24217
|
+
subagentId: e.subagentId,
|
|
24218
|
+
load: payload.load,
|
|
24219
|
+
tokens: payload.tokens,
|
|
24220
|
+
maxContext: payload.maxContext
|
|
24221
|
+
});
|
|
24222
|
+
})
|
|
24165
24223
|
);
|
|
24224
|
+
this.directorOffHandles.push(
|
|
24225
|
+
this.director.fleet.filter("subagent.spawned", (e) => {
|
|
24226
|
+
const payload = e.payload;
|
|
24227
|
+
this.deps.events.emit("subagent.spawned", {
|
|
24228
|
+
subagentId: payload.subagentId,
|
|
24229
|
+
taskId: payload.taskId,
|
|
24230
|
+
name: payload.name,
|
|
24231
|
+
provider: payload.provider,
|
|
24232
|
+
model: payload.model
|
|
24233
|
+
});
|
|
24234
|
+
})
|
|
24235
|
+
);
|
|
24236
|
+
const coordinatorTaskAssignedHandler = ({
|
|
24237
|
+
task,
|
|
24238
|
+
subagentId
|
|
24239
|
+
}) => {
|
|
24240
|
+
this.deps.events.emit("subagent.task_started", {
|
|
24241
|
+
subagentId,
|
|
24242
|
+
taskId: task.id,
|
|
24243
|
+
description: task.description
|
|
24244
|
+
});
|
|
24245
|
+
};
|
|
24246
|
+
const coordinator = this.getCoordinator();
|
|
24247
|
+
coordinator.on("task.assigned", coordinatorTaskAssignedHandler);
|
|
24248
|
+
this.coordinatorOffHandle = () => coordinator.off("task.assigned", coordinatorTaskAssignedHandler);
|
|
24166
24249
|
this.fleetEmitTool = makeFleetEmitTool(this.director);
|
|
24167
24250
|
this.fleetStatusTool = makeFleetStatusTool(this.director);
|
|
24168
24251
|
const runner = await this.buildSubagentRunner(config);
|
|
24169
|
-
this.
|
|
24252
|
+
if (!this.directorRunnerSet) {
|
|
24253
|
+
this.getCoordinator().setRunner(runner);
|
|
24254
|
+
this.directorRunnerSet = true;
|
|
24255
|
+
}
|
|
24170
24256
|
}
|
|
24171
24257
|
/**
|
|
24172
24258
|
* Returns the FleetEmitTool for director-mode subagents, if the director
|
|
@@ -24368,9 +24454,23 @@ var MultiAgentHost = class {
|
|
|
24368
24454
|
return buildRoutingRunner(config, this);
|
|
24369
24455
|
}
|
|
24370
24456
|
async buildACPRunner(subagentId) {
|
|
24457
|
+
const cached = this.acpRunnerCache.get(subagentId);
|
|
24458
|
+
if (cached) {
|
|
24459
|
+
const idx = this.acpRunnerAccessOrder.indexOf(subagentId);
|
|
24460
|
+
if (idx !== -1) this.acpRunnerAccessOrder.splice(idx, 1);
|
|
24461
|
+
this.acpRunnerAccessOrder.push(subagentId);
|
|
24462
|
+
return cached;
|
|
24463
|
+
}
|
|
24371
24464
|
const cmd = ACP_AGENT_COMMANDS[subagentId];
|
|
24372
24465
|
if (!cmd) throw new Error(`Unknown ACP agent: ${subagentId}`);
|
|
24373
|
-
|
|
24466
|
+
while (this.acpRunnerAccessOrder.length >= _MultiAgentHost.ACP_CACHE_MAX) {
|
|
24467
|
+
const oldest = this.acpRunnerAccessOrder.shift();
|
|
24468
|
+
if (oldest) this.acpRunnerCache.delete(oldest);
|
|
24469
|
+
}
|
|
24470
|
+
const p = makeACPSubagentRunner(cmd);
|
|
24471
|
+
this.acpRunnerCache.set(subagentId, p);
|
|
24472
|
+
this.acpRunnerAccessOrder.push(subagentId);
|
|
24473
|
+
return p;
|
|
24374
24474
|
}
|
|
24375
24475
|
/**
|
|
24376
24476
|
* Build a Provider for a subagent. When `overrideId` is supplied (from
|
|
@@ -24413,6 +24513,7 @@ var MultiAgentHost = class {
|
|
|
24413
24513
|
const coordinator = this.getCoordinator();
|
|
24414
24514
|
const acpRunner = await this.buildACPRunner(subagentId);
|
|
24415
24515
|
coordinator.setRunner(acpRunner);
|
|
24516
|
+
this.directorRunnerSet = true;
|
|
24416
24517
|
await coordinator.spawn({
|
|
24417
24518
|
id: subagentId,
|
|
24418
24519
|
name: subagentId,
|
|
@@ -24482,8 +24583,9 @@ var MultiAgentHost = class {
|
|
|
24482
24583
|
*/
|
|
24483
24584
|
async spawnAndWait(description, opts) {
|
|
24484
24585
|
const { taskId } = await this.spawn(description, opts);
|
|
24485
|
-
|
|
24486
|
-
|
|
24586
|
+
const director = this.director;
|
|
24587
|
+
if (!director) throw new Error("Director is not initialized");
|
|
24588
|
+
const results = await director.awaitTasks([taskId]);
|
|
24487
24589
|
const result = results[0];
|
|
24488
24590
|
if (!result) throw new Error(`Task ${taskId} completed but no result returned`);
|
|
24489
24591
|
return result;
|
|
@@ -24697,6 +24799,24 @@ var MultiAgentHost = class {
|
|
|
24697
24799
|
this.getCoordinator().setMaxConcurrent(v);
|
|
24698
24800
|
}
|
|
24699
24801
|
}
|
|
24802
|
+
/**
|
|
24803
|
+
* Clean up all listeners and resources held by the host.
|
|
24804
|
+
* Unregisters all EventBus/FleetBus listeners registered in `buildDirector`
|
|
24805
|
+
* and stops the Director and its coordinator.
|
|
24806
|
+
*
|
|
24807
|
+
* Safe to call multiple times — subsequent calls are no-ops.
|
|
24808
|
+
*/
|
|
24809
|
+
async dispose() {
|
|
24810
|
+
for (const off of this.directorOffHandles) {
|
|
24811
|
+
off();
|
|
24812
|
+
}
|
|
24813
|
+
this.directorOffHandles.length = 0;
|
|
24814
|
+
this.coordinatorOffHandle?.();
|
|
24815
|
+
this.coordinatorOffHandle = null;
|
|
24816
|
+
if (this.director) {
|
|
24817
|
+
await this.director.shutdown();
|
|
24818
|
+
}
|
|
24819
|
+
}
|
|
24700
24820
|
};
|
|
24701
24821
|
|
|
24702
24822
|
// src/session-stats.ts
|
|
@@ -27033,6 +27153,9 @@ Restart WrongStack to load or unload plugin code in this session.`;
|
|
|
27033
27153
|
brainMonitor.stop();
|
|
27034
27154
|
brainQueue.dispose();
|
|
27035
27155
|
void mcpRegistry.stopAll();
|
|
27156
|
+
multiAgentHost.dispose().catch(
|
|
27157
|
+
(err) => logger.warn(`multiAgentHost.dispose() failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
27158
|
+
);
|
|
27036
27159
|
},
|
|
27037
27160
|
onBeforeExit: async () => {
|
|
27038
27161
|
const cwd2 = projectRoot;
|
|
@@ -27314,8 +27437,11 @@ Reply YES to auto-proceed, NO to wait for human input.`
|
|
|
27314
27437
|
brain,
|
|
27315
27438
|
brainSettings,
|
|
27316
27439
|
getBrainLog: () => brainLog,
|
|
27317
|
-
// Clean up SessionStats event listeners when the REPL exits.
|
|
27318
|
-
onDestroy: () =>
|
|
27440
|
+
// Clean up SessionStats event listeners and all EventBus handlers when the REPL exits.
|
|
27441
|
+
onDestroy: () => {
|
|
27442
|
+
teardownHandlers.forEach((fn) => fn());
|
|
27443
|
+
stats.destroy(events);
|
|
27444
|
+
}
|
|
27319
27445
|
});
|
|
27320
27446
|
}
|
|
27321
27447
|
var isMain = import.meta.url === `file://${process.argv[1]?.replace(/\\/g, "/")}` || process.argv[1]?.endsWith("/cli/dist/index.js") || process.argv[1]?.endsWith("\\cli\\dist\\index.js");
|