@wrongstack/core 0.3.1 → 0.3.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/{compactor-BUU6Zm_3.d.ts → compactor-DpJBI1YH.d.ts} +7 -1
- package/dist/{config-CKLYPkCi.d.ts → config-D2qvAxVd.d.ts} +38 -1
- package/dist/coordination/index.d.ts +3 -3
- package/dist/coordination/index.js +283 -244
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +7 -7
- package/dist/defaults/index.js +803 -524
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-CNB9PALO.d.ts → events-BHIQs4o1.d.ts} +7 -0
- package/dist/execution/index.d.ts +10 -7
- package/dist/execution/index.js +166 -18
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +3 -3
- package/dist/extension/index.js +14 -7
- package/dist/extension/index.js.map +1 -1
- package/dist/{index-BDb0cAMP.d.ts → index-hWNybrNZ.d.ts} +3 -5
- package/dist/index.d.ts +12 -12
- package/dist/index.js +629 -299
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +5 -5
- package/dist/infrastructure/index.js +191 -20
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +4 -4
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-DR35ojJZ.d.ts → mcp-servers-C2OopXOn.d.ts} +20 -4
- package/dist/observability/index.d.ts +1 -1
- package/dist/{path-resolver-Cl_q0u-R.d.ts → path-resolver--59rCou3.d.ts} +1 -1
- package/dist/{provider-runner-BXuADQqQ.d.ts → provider-runner-B39miKRw.d.ts} +1 -1
- package/dist/sdd/index.d.ts +1 -1
- package/dist/storage/index.d.ts +4 -3
- package/dist/storage/index.js +180 -13
- package/dist/storage/index.js.map +1 -1
- package/dist/{tool-executor-DKu4A6nB.d.ts → tool-executor-HsBLGRaA.d.ts} +2 -2
- package/dist/types/index.d.ts +7 -7
- package/dist/types/index.js +206 -9
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +23 -2
- package/dist/utils/index.js +93 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1166,6 +1166,98 @@ function estimateTextTokens(text) {
|
|
|
1166
1166
|
return RoughTokenEstimate(text);
|
|
1167
1167
|
}
|
|
1168
1168
|
|
|
1169
|
+
// src/utils/message-invariants.ts
|
|
1170
|
+
function repairToolUseAdjacency(messages) {
|
|
1171
|
+
const removedToolUses = [];
|
|
1172
|
+
const removedToolResults = [];
|
|
1173
|
+
let removedMessages = 0;
|
|
1174
|
+
let changed = false;
|
|
1175
|
+
const out = [];
|
|
1176
|
+
for (let i = 0; i < messages.length; i++) {
|
|
1177
|
+
const original = messages[i];
|
|
1178
|
+
let msg = original;
|
|
1179
|
+
if (hasToolUse(msg)) {
|
|
1180
|
+
const nextIds = toolResultIds(messages[i + 1]);
|
|
1181
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
1182
|
+
const next = [];
|
|
1183
|
+
for (const block of blocks) {
|
|
1184
|
+
if (block.type === "tool_use" && !nextIds.has(block.id)) {
|
|
1185
|
+
removedToolUses.push(block.id);
|
|
1186
|
+
changed = true;
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1189
|
+
next.push(block);
|
|
1190
|
+
}
|
|
1191
|
+
return next;
|
|
1192
|
+
});
|
|
1193
|
+
msg = filtered ?? msg;
|
|
1194
|
+
}
|
|
1195
|
+
if (hasToolResult(msg)) {
|
|
1196
|
+
const allowed = toolUseIds(out[out.length - 1]);
|
|
1197
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
1198
|
+
const next = [];
|
|
1199
|
+
for (const block of blocks) {
|
|
1200
|
+
if (block.type === "tool_result" && !allowed.has(block.tool_use_id)) {
|
|
1201
|
+
removedToolResults.push(block.tool_use_id);
|
|
1202
|
+
changed = true;
|
|
1203
|
+
continue;
|
|
1204
|
+
}
|
|
1205
|
+
next.push(block);
|
|
1206
|
+
}
|
|
1207
|
+
return next;
|
|
1208
|
+
});
|
|
1209
|
+
msg = filtered ?? msg;
|
|
1210
|
+
}
|
|
1211
|
+
if (isEmptyMessage(msg)) {
|
|
1212
|
+
removedMessages++;
|
|
1213
|
+
changed = true;
|
|
1214
|
+
continue;
|
|
1215
|
+
}
|
|
1216
|
+
out.push(msg);
|
|
1217
|
+
}
|
|
1218
|
+
return {
|
|
1219
|
+
messages: changed ? out : messages,
|
|
1220
|
+
report: { changed, removedToolUses, removedToolResults, removedMessages }
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
function hasToolUse(msg) {
|
|
1224
|
+
return contentBlocks(msg).some((b) => b.type === "tool_use");
|
|
1225
|
+
}
|
|
1226
|
+
function hasToolResult(msg) {
|
|
1227
|
+
return contentBlocks(msg).some((b) => b.type === "tool_result");
|
|
1228
|
+
}
|
|
1229
|
+
function toolUseIds(msg) {
|
|
1230
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1231
|
+
if (!msg || msg.role !== "assistant") return ids;
|
|
1232
|
+
for (const block of contentBlocks(msg)) {
|
|
1233
|
+
if (block.type === "tool_use") ids.add(block.id);
|
|
1234
|
+
}
|
|
1235
|
+
return ids;
|
|
1236
|
+
}
|
|
1237
|
+
function toolResultIds(msg) {
|
|
1238
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1239
|
+
if (!msg || msg.role !== "user") return ids;
|
|
1240
|
+
for (const block of contentBlocks(msg)) {
|
|
1241
|
+
if (block.type === "tool_result") ids.add(block.tool_use_id);
|
|
1242
|
+
}
|
|
1243
|
+
return ids;
|
|
1244
|
+
}
|
|
1245
|
+
function contentBlocks(msg) {
|
|
1246
|
+
return msg && Array.isArray(msg.content) ? msg.content : [];
|
|
1247
|
+
}
|
|
1248
|
+
function mapContent(msg, fn) {
|
|
1249
|
+
if (!Array.isArray(msg.content)) return msg;
|
|
1250
|
+
const next = fn(msg.content);
|
|
1251
|
+
if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {
|
|
1252
|
+
return msg;
|
|
1253
|
+
}
|
|
1254
|
+
return { ...msg, content: next };
|
|
1255
|
+
}
|
|
1256
|
+
function isEmptyMessage(msg) {
|
|
1257
|
+
if (typeof msg.content === "string") return msg.content.trim().length === 0;
|
|
1258
|
+
return msg.content.length === 0;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1169
1261
|
// src/execution/compactor.ts
|
|
1170
1262
|
var HybridCompactor = class {
|
|
1171
1263
|
preserveK;
|
|
@@ -1179,20 +1271,36 @@ var HybridCompactor = class {
|
|
|
1179
1271
|
async compact(ctx, opts = {}) {
|
|
1180
1272
|
const beforeTokens = this.estimateMessages(ctx.messages);
|
|
1181
1273
|
const reductions = [];
|
|
1182
|
-
const
|
|
1274
|
+
const policy = readContextWindowPolicy(ctx);
|
|
1275
|
+
const preserveK = policy?.preserveK ?? this.preserveK;
|
|
1276
|
+
const eliseThreshold = policy?.eliseThreshold ?? this.eliseThreshold;
|
|
1277
|
+
const phase1Saved = this.eliseOldToolResults(ctx, preserveK, eliseThreshold);
|
|
1183
1278
|
if (phase1Saved > 0) reductions.push({ phase: "elision", saved: phase1Saved });
|
|
1184
1279
|
if (opts.aggressive) {
|
|
1185
|
-
const phase2Saved = this.collapseAncientTurns(ctx);
|
|
1280
|
+
const phase2Saved = this.collapseAncientTurns(ctx, preserveK);
|
|
1186
1281
|
if (phase2Saved > 0) reductions.push({ phase: "summary", saved: phase2Saved });
|
|
1187
1282
|
}
|
|
1283
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
1284
|
+
if (repaired.report.changed) {
|
|
1285
|
+
ctx.state.replaceMessages(repaired.messages);
|
|
1286
|
+
}
|
|
1188
1287
|
const afterTokens = this.estimateMessages(ctx.messages);
|
|
1189
|
-
return {
|
|
1288
|
+
return {
|
|
1289
|
+
before: beforeTokens,
|
|
1290
|
+
after: afterTokens,
|
|
1291
|
+
reductions,
|
|
1292
|
+
repaired: repaired.report.changed ? {
|
|
1293
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
1294
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
1295
|
+
removedMessages: repaired.report.removedMessages
|
|
1296
|
+
} : void 0
|
|
1297
|
+
};
|
|
1190
1298
|
}
|
|
1191
|
-
eliseOldToolResults(ctx) {
|
|
1299
|
+
eliseOldToolResults(ctx, preserveK = this.preserveK, eliseThreshold = this.eliseThreshold) {
|
|
1192
1300
|
const messages = ctx.messages;
|
|
1193
1301
|
let pairCount = 0;
|
|
1194
1302
|
let preserveStart = messages.length;
|
|
1195
|
-
for (let i = messages.length - 1; i >= 0 && pairCount <
|
|
1303
|
+
for (let i = messages.length - 1; i >= 0 && pairCount < preserveK; i--) {
|
|
1196
1304
|
const m = messages[i];
|
|
1197
1305
|
if (!m) continue;
|
|
1198
1306
|
if (m.role === "user" || m.role === "assistant") {
|
|
@@ -1216,7 +1324,7 @@ var HybridCompactor = class {
|
|
|
1216
1324
|
const newContent = msg.content.map((b) => {
|
|
1217
1325
|
if (b.type !== "tool_result") return b;
|
|
1218
1326
|
const tokens = estimateToolResultTokens(b.content);
|
|
1219
|
-
if (tokens <
|
|
1327
|
+
if (tokens < eliseThreshold) return b;
|
|
1220
1328
|
saved += tokens;
|
|
1221
1329
|
const elided = {
|
|
1222
1330
|
type: "tool_result",
|
|
@@ -1236,9 +1344,9 @@ var HybridCompactor = class {
|
|
|
1236
1344
|
if (changed) ctx.state.replaceMessages(nextMessages);
|
|
1237
1345
|
return saved;
|
|
1238
1346
|
}
|
|
1239
|
-
collapseAncientTurns(ctx) {
|
|
1347
|
+
collapseAncientTurns(ctx, preserveK = this.preserveK) {
|
|
1240
1348
|
const messages = ctx.messages;
|
|
1241
|
-
const cutTarget = Math.max(0, messages.length -
|
|
1349
|
+
const cutTarget = Math.max(0, messages.length - preserveK * 2);
|
|
1242
1350
|
if (cutTarget <= 0) return 0;
|
|
1243
1351
|
let boundary = -1;
|
|
1244
1352
|
for (let i = cutTarget; i < messages.length; i++) {
|
|
@@ -1279,6 +1387,15 @@ var HybridCompactor = class {
|
|
|
1279
1387
|
return total;
|
|
1280
1388
|
}
|
|
1281
1389
|
};
|
|
1390
|
+
function readContextWindowPolicy(ctx) {
|
|
1391
|
+
const policy = ctx.meta?.["contextWindowPolicy"];
|
|
1392
|
+
if (!policy || typeof policy !== "object") return null;
|
|
1393
|
+
const candidate = policy;
|
|
1394
|
+
if (typeof candidate.preserveK !== "number" || typeof candidate.eliseThreshold !== "number") {
|
|
1395
|
+
return null;
|
|
1396
|
+
}
|
|
1397
|
+
return candidate;
|
|
1398
|
+
}
|
|
1282
1399
|
function hasTextContent(m) {
|
|
1283
1400
|
if (typeof m.content === "string") return m.content.trim().length > 0;
|
|
1284
1401
|
return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
|
|
@@ -1944,6 +2061,85 @@ When refactoring code:
|
|
|
1944
2061
|
}
|
|
1945
2062
|
];
|
|
1946
2063
|
|
|
2064
|
+
// src/types/context-window.ts
|
|
2065
|
+
var DEFAULT_CONTEXT_WINDOW_MODE_ID = "balanced";
|
|
2066
|
+
var CONTEXT_WINDOW_MODES = Object.freeze([
|
|
2067
|
+
{
|
|
2068
|
+
id: "balanced",
|
|
2069
|
+
name: "Balanced",
|
|
2070
|
+
description: "Default rolling compaction: recent work stays verbatim, old tool output is trimmed.",
|
|
2071
|
+
thresholds: { warn: 0.6, soft: 0.75, hard: 0.9 },
|
|
2072
|
+
aggressiveOn: "soft",
|
|
2073
|
+
preserveK: 10,
|
|
2074
|
+
eliseThreshold: 2e3,
|
|
2075
|
+
targetLoad: 0.65
|
|
2076
|
+
},
|
|
2077
|
+
{
|
|
2078
|
+
id: "frugal",
|
|
2079
|
+
name: "Frugal",
|
|
2080
|
+
description: "Token-saver mode: compacts early and keeps a tighter verbatim tail.",
|
|
2081
|
+
thresholds: { warn: 0.45, soft: 0.6, hard: 0.75 },
|
|
2082
|
+
aggressiveOn: "warn",
|
|
2083
|
+
preserveK: 6,
|
|
2084
|
+
eliseThreshold: 700,
|
|
2085
|
+
targetLoad: 0.5
|
|
2086
|
+
},
|
|
2087
|
+
{
|
|
2088
|
+
id: "deep",
|
|
2089
|
+
name: "Deep",
|
|
2090
|
+
description: "Long-reasoning mode: delays compaction and keeps more recent turns intact.",
|
|
2091
|
+
thresholds: { warn: 0.72, soft: 0.86, hard: 0.96 },
|
|
2092
|
+
aggressiveOn: "hard",
|
|
2093
|
+
preserveK: 18,
|
|
2094
|
+
eliseThreshold: 5e3,
|
|
2095
|
+
targetLoad: 0.78
|
|
2096
|
+
},
|
|
2097
|
+
{
|
|
2098
|
+
id: "archival",
|
|
2099
|
+
name: "Archival",
|
|
2100
|
+
description: "Decision-preserving mode: compacts steadily while keeping summaries prominent.",
|
|
2101
|
+
thresholds: { warn: 0.55, soft: 0.7, hard: 0.84 },
|
|
2102
|
+
aggressiveOn: "soft",
|
|
2103
|
+
preserveK: 8,
|
|
2104
|
+
eliseThreshold: 1200,
|
|
2105
|
+
targetLoad: 0.58
|
|
2106
|
+
}
|
|
2107
|
+
]);
|
|
2108
|
+
function listContextWindowModes() {
|
|
2109
|
+
return CONTEXT_WINDOW_MODES.map((m) => ({ ...m, thresholds: { ...m.thresholds } }));
|
|
2110
|
+
}
|
|
2111
|
+
function getContextWindowMode(id) {
|
|
2112
|
+
if (!id) return null;
|
|
2113
|
+
const mode = CONTEXT_WINDOW_MODES.find((m) => m.id === id);
|
|
2114
|
+
return mode ? { ...mode, thresholds: { ...mode.thresholds } } : null;
|
|
2115
|
+
}
|
|
2116
|
+
function isContextWindowModeId(id) {
|
|
2117
|
+
return CONTEXT_WINDOW_MODES.some((m) => m.id === id);
|
|
2118
|
+
}
|
|
2119
|
+
function resolveContextWindowPolicy(config = {}, overrideMode) {
|
|
2120
|
+
const requested = overrideMode ?? config.mode ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;
|
|
2121
|
+
const mode = getContextWindowMode(requested) ?? getContextWindowMode(DEFAULT_CONTEXT_WINDOW_MODE_ID);
|
|
2122
|
+
if (mode.id !== DEFAULT_CONTEXT_WINDOW_MODE_ID) {
|
|
2123
|
+
return mode;
|
|
2124
|
+
}
|
|
2125
|
+
return {
|
|
2126
|
+
...mode,
|
|
2127
|
+
thresholds: {
|
|
2128
|
+
warn: config.warnThreshold ?? mode.thresholds.warn,
|
|
2129
|
+
soft: config.softThreshold ?? mode.thresholds.soft,
|
|
2130
|
+
hard: config.hardThreshold ?? mode.thresholds.hard
|
|
2131
|
+
},
|
|
2132
|
+
preserveK: config.preserveK ?? mode.preserveK,
|
|
2133
|
+
eliseThreshold: config.eliseThreshold ?? mode.eliseThreshold
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2136
|
+
function formatContextWindowModeList(activeId) {
|
|
2137
|
+
return CONTEXT_WINDOW_MODES.map((m) => {
|
|
2138
|
+
const marker = m.id === activeId ? "*" : " ";
|
|
2139
|
+
return `${marker} ${m.id.padEnd(9)} ${m.name} - ${m.description}`;
|
|
2140
|
+
}).join("\n");
|
|
2141
|
+
}
|
|
2142
|
+
|
|
1947
2143
|
// src/coordination/in-memory-transport.ts
|
|
1948
2144
|
var InMemoryBridgeTransport = class {
|
|
1949
2145
|
subs = /* @__PURE__ */ new Map();
|
|
@@ -2063,6 +2259,7 @@ var InMemoryAgentBridge = class {
|
|
|
2063
2259
|
this.stopped = true;
|
|
2064
2260
|
for (const [, p] of this.pendingRequests) {
|
|
2065
2261
|
clearTimeout(p.timer);
|
|
2262
|
+
p.reject(new Error("Bridge stopped"));
|
|
2066
2263
|
}
|
|
2067
2264
|
this.pendingRequests.clear();
|
|
2068
2265
|
this.inflightGuards.clear();
|
|
@@ -3493,11 +3690,17 @@ var DefaultSessionStore = class {
|
|
|
3493
3690
|
if (openToolUses.size > 0) {
|
|
3494
3691
|
this.events?.emit("session.damaged", {
|
|
3495
3692
|
sessionId,
|
|
3496
|
-
detail: `${openToolUses.size} tool_use blocks without matching results
|
|
3693
|
+
detail: `${openToolUses.size} tool_use blocks without matching results - replay repaired`
|
|
3694
|
+
});
|
|
3695
|
+
}
|
|
3696
|
+
const repaired = repairToolUseAdjacency(messages);
|
|
3697
|
+
if (repaired.report.changed) {
|
|
3698
|
+
this.events?.emit("session.damaged", {
|
|
3699
|
+
sessionId,
|
|
3700
|
+
detail: `Repaired replay adjacency: removed ${repaired.report.removedToolUses.length} tool_use, ${repaired.report.removedToolResults.length} tool_result, ${repaired.report.removedMessages} empty messages`
|
|
3497
3701
|
});
|
|
3498
|
-
return { messages, usage };
|
|
3499
3702
|
}
|
|
3500
|
-
return { messages, usage };
|
|
3703
|
+
return { messages: repaired.messages, usage };
|
|
3501
3704
|
}
|
|
3502
3705
|
};
|
|
3503
3706
|
var FileSessionWriter = class {
|
|
@@ -3523,6 +3726,7 @@ var FileSessionWriter = class {
|
|
|
3523
3726
|
startedAt;
|
|
3524
3727
|
meta;
|
|
3525
3728
|
closed = false;
|
|
3729
|
+
closing = false;
|
|
3526
3730
|
manifestFile;
|
|
3527
3731
|
summary;
|
|
3528
3732
|
tokenIn = 0;
|
|
@@ -3538,9 +3742,7 @@ var FileSessionWriter = class {
|
|
|
3538
3742
|
resumed;
|
|
3539
3743
|
appendFailCount = 0;
|
|
3540
3744
|
lastAppendWarnAt = 0;
|
|
3541
|
-
async
|
|
3542
|
-
if (this.initDone || this.closed) return;
|
|
3543
|
-
this.initDone = true;
|
|
3745
|
+
async writeSessionStartLazy() {
|
|
3544
3746
|
const record = `${JSON.stringify({
|
|
3545
3747
|
type: this.resumed ? "session_resumed" : "session_start",
|
|
3546
3748
|
ts: this.startedAt,
|
|
@@ -3559,7 +3761,8 @@ var FileSessionWriter = class {
|
|
|
3559
3761
|
async append(event) {
|
|
3560
3762
|
if (this.closed) return;
|
|
3561
3763
|
if (!this.initDone) {
|
|
3562
|
-
|
|
3764
|
+
this.initDone = true;
|
|
3765
|
+
await this.writeSessionStartLazy();
|
|
3563
3766
|
}
|
|
3564
3767
|
this.observeForSummary(event);
|
|
3565
3768
|
try {
|
|
@@ -3600,7 +3803,8 @@ var FileSessionWriter = class {
|
|
|
3600
3803
|
}
|
|
3601
3804
|
}
|
|
3602
3805
|
async close() {
|
|
3603
|
-
if (this.
|
|
3806
|
+
if (this.closing) return;
|
|
3807
|
+
this.closing = true;
|
|
3604
3808
|
this.closed = true;
|
|
3605
3809
|
if (this.manifestFile) {
|
|
3606
3810
|
try {
|
|
@@ -4002,9 +4206,52 @@ function deepFreeze(obj) {
|
|
|
4002
4206
|
}
|
|
4003
4207
|
return Object.freeze(obj);
|
|
4004
4208
|
}
|
|
4209
|
+
|
|
4210
|
+
// src/security/config-secrets.ts
|
|
4211
|
+
function decryptConfigSecrets2(cfg, vault) {
|
|
4212
|
+
return walk3(cfg, vault, (v, key) => {
|
|
4213
|
+
try {
|
|
4214
|
+
return vault.decrypt(v);
|
|
4215
|
+
} catch (err) {
|
|
4216
|
+
console.warn(
|
|
4217
|
+
`[secret-vault] Failed to decrypt "${key}":`,
|
|
4218
|
+
err instanceof Error ? err.message : err
|
|
4219
|
+
);
|
|
4220
|
+
return "";
|
|
4221
|
+
}
|
|
4222
|
+
});
|
|
4223
|
+
}
|
|
4224
|
+
function walk3(node, vault, transform) {
|
|
4225
|
+
if (node === null || node === void 0) return node;
|
|
4226
|
+
if (typeof node !== "object") return node;
|
|
4227
|
+
if (Array.isArray(node)) {
|
|
4228
|
+
return node.map((item) => walk3(item, vault, transform));
|
|
4229
|
+
}
|
|
4230
|
+
const out = {};
|
|
4231
|
+
for (const [k, v] of Object.entries(node)) {
|
|
4232
|
+
if (typeof v === "string" && isSecretField2(k)) {
|
|
4233
|
+
out[k] = transform(v, k);
|
|
4234
|
+
} else if (typeof v === "object" && v !== null) {
|
|
4235
|
+
out[k] = walk3(v, vault, transform);
|
|
4236
|
+
} else {
|
|
4237
|
+
out[k] = v;
|
|
4238
|
+
}
|
|
4239
|
+
}
|
|
4240
|
+
return out;
|
|
4241
|
+
}
|
|
4242
|
+
var SECRET_KEY_PATTERN2 = /(?:apikey|api_key|authtoken|auth_token|bearer|secret|password|passwd|pwd|refreshtoken|refresh_token|sessionkey|session_key|access[_-]?token|private[_-]?key)/i;
|
|
4243
|
+
var NON_SECRET_OVERRIDES2 = /* @__PURE__ */ new Set(["publickey", "public_key"]);
|
|
4244
|
+
function isSecretField2(name) {
|
|
4245
|
+
const lc = name.toLowerCase();
|
|
4246
|
+
if (NON_SECRET_OVERRIDES2.has(lc)) return false;
|
|
4247
|
+
return SECRET_KEY_PATTERN2.test(lc);
|
|
4248
|
+
}
|
|
4249
|
+
|
|
4250
|
+
// src/storage/config-loader.ts
|
|
4005
4251
|
var BEHAVIOR_DEFAULTS = {
|
|
4006
4252
|
version: 1,
|
|
4007
4253
|
context: {
|
|
4254
|
+
mode: DEFAULT_CONTEXT_WINDOW_MODE_ID,
|
|
4008
4255
|
warnThreshold: 0.6,
|
|
4009
4256
|
softThreshold: 0.75,
|
|
4010
4257
|
hardThreshold: 0.9,
|
|
@@ -4119,7 +4366,7 @@ var DefaultConfigLoader = class {
|
|
|
4119
4366
|
cfg = deepMerge2(cfg, opts.cliFlags);
|
|
4120
4367
|
}
|
|
4121
4368
|
if (this.vault) {
|
|
4122
|
-
cfg =
|
|
4369
|
+
cfg = decryptConfigSecrets2(cfg, this.vault);
|
|
4123
4370
|
}
|
|
4124
4371
|
if (cfg.providers) {
|
|
4125
4372
|
for (const pcfg of Object.values(cfg.providers)) {
|
|
@@ -4179,6 +4426,10 @@ var DefaultConfigLoader = class {
|
|
|
4179
4426
|
if (c.warnThreshold >= c.softThreshold || c.softThreshold >= c.hardThreshold) {
|
|
4180
4427
|
throw new Error("Config: context thresholds must satisfy warn < soft < hard");
|
|
4181
4428
|
}
|
|
4429
|
+
if (c.mode !== void 0 && !isContextWindowModeId(c.mode)) {
|
|
4430
|
+
const known = listContextWindowModes().map((m) => m.id).join(", ");
|
|
4431
|
+
throw new Error(`Config: context.mode must be one of: ${known}`);
|
|
4432
|
+
}
|
|
4182
4433
|
}
|
|
4183
4434
|
validateIdentity(cfg) {
|
|
4184
4435
|
if (!cfg.provider) {
|
|
@@ -4499,24 +4750,35 @@ async function saveTodosCheckpoint(filePath, sessionId, todos) {
|
|
|
4499
4750
|
function attachTodosCheckpoint(state, filePath, sessionId) {
|
|
4500
4751
|
let timer = null;
|
|
4501
4752
|
let pending = null;
|
|
4753
|
+
let writeChain = Promise.resolve();
|
|
4754
|
+
const enqueueWrite = (todos) => {
|
|
4755
|
+
writeChain = writeChain.then(() => saveTodosCheckpoint(filePath, sessionId, todos));
|
|
4756
|
+
return writeChain;
|
|
4757
|
+
};
|
|
4502
4758
|
const flush = () => {
|
|
4503
4759
|
timer = null;
|
|
4504
4760
|
if (pending) {
|
|
4505
|
-
|
|
4761
|
+
const todos = pending;
|
|
4506
4762
|
pending = null;
|
|
4763
|
+
return enqueueWrite(todos);
|
|
4507
4764
|
}
|
|
4765
|
+
return writeChain;
|
|
4508
4766
|
};
|
|
4509
4767
|
const unsubscribe = state.onChange((change) => {
|
|
4510
4768
|
if (change.kind !== "todos_replaced") return;
|
|
4511
4769
|
pending = change.todos;
|
|
4512
4770
|
if (timer) clearTimeout(timer);
|
|
4513
|
-
timer = setTimeout(
|
|
4771
|
+
timer = setTimeout(() => {
|
|
4772
|
+
void flush();
|
|
4773
|
+
}, 150);
|
|
4514
4774
|
});
|
|
4515
|
-
return () => {
|
|
4775
|
+
return async () => {
|
|
4516
4776
|
unsubscribe();
|
|
4517
4777
|
if (timer) {
|
|
4518
4778
|
clearTimeout(timer);
|
|
4519
|
-
flush();
|
|
4779
|
+
await flush();
|
|
4780
|
+
} else {
|
|
4781
|
+
await writeChain;
|
|
4520
4782
|
}
|
|
4521
4783
|
};
|
|
4522
4784
|
}
|
|
@@ -5310,8 +5572,19 @@ var IntelligentCompactor = class {
|
|
|
5310
5572
|
const saved2 = this.lightweightCompact(ctx);
|
|
5311
5573
|
if (saved2 > 0) reductions.push({ phase: "elision", saved: saved2 });
|
|
5312
5574
|
}
|
|
5575
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
5576
|
+
if (repaired.report.changed) ctx.state.replaceMessages(repaired.messages);
|
|
5313
5577
|
const afterTokens = this.estimateTokens(ctx.messages);
|
|
5314
|
-
return {
|
|
5578
|
+
return {
|
|
5579
|
+
before: beforeTokens,
|
|
5580
|
+
after: afterTokens,
|
|
5581
|
+
reductions,
|
|
5582
|
+
repaired: repaired.report.changed ? {
|
|
5583
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
5584
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
5585
|
+
removedMessages: repaired.report.removedMessages
|
|
5586
|
+
} : void 0
|
|
5587
|
+
};
|
|
5315
5588
|
}
|
|
5316
5589
|
async summarizeAncientTurns(ctx) {
|
|
5317
5590
|
const messages = ctx.messages;
|
|
@@ -5351,8 +5624,8 @@ var IntelligentCompactor = class {
|
|
|
5351
5624
|
const m = messages[i];
|
|
5352
5625
|
if (!m) continue;
|
|
5353
5626
|
if (m.role === "assistant") {
|
|
5354
|
-
const
|
|
5355
|
-
if (!
|
|
5627
|
+
const hasToolUse2 = Array.isArray(m.content) ? m.content.some((b) => b.type === "tool_use") : false;
|
|
5628
|
+
if (!hasToolUse2) {
|
|
5356
5629
|
return i + 1;
|
|
5357
5630
|
}
|
|
5358
5631
|
} else if (m.role !== "user") ; else {
|
|
@@ -5658,8 +5931,9 @@ var SelectiveCompactor = class {
|
|
|
5658
5931
|
if (!shouldCompact) {
|
|
5659
5932
|
const saved = this.eliseOldToolResults(ctx);
|
|
5660
5933
|
if (saved > 0) reductions.push({ phase: "elision", saved });
|
|
5934
|
+
const repair2 = this.repairProtocolAdjacency(ctx);
|
|
5661
5935
|
const afterTokens2 = this.estimateTokens(ctx.messages);
|
|
5662
|
-
return { before: beforeTokens, after: afterTokens2, reductions };
|
|
5936
|
+
return { before: beforeTokens, after: afterTokens2, reductions, repaired: repair2 };
|
|
5663
5937
|
}
|
|
5664
5938
|
const savedElision = this.eliseOldToolResults(ctx);
|
|
5665
5939
|
if (savedElision > 0) reductions.push({ phase: "elision", saved: savedElision });
|
|
@@ -5669,8 +5943,18 @@ var SelectiveCompactor = class {
|
|
|
5669
5943
|
const savedSelective = await this.runSelector(ctx, targetBudget);
|
|
5670
5944
|
if (savedSelective > 0) reductions.push({ phase: "selective", saved: savedSelective });
|
|
5671
5945
|
}
|
|
5946
|
+
const repair = this.repairProtocolAdjacency(ctx);
|
|
5672
5947
|
const afterTokens = this.estimateTokens(ctx.messages);
|
|
5673
|
-
return { before: beforeTokens, after: afterTokens, reductions };
|
|
5948
|
+
return { before: beforeTokens, after: afterTokens, reductions, repaired: repair };
|
|
5949
|
+
}
|
|
5950
|
+
repairProtocolAdjacency(ctx) {
|
|
5951
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
5952
|
+
if (repaired.report.changed) ctx.state.replaceMessages(repaired.messages);
|
|
5953
|
+
return repaired.report.changed ? {
|
|
5954
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
5955
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
5956
|
+
removedMessages: repaired.report.removedMessages
|
|
5957
|
+
} : void 0;
|
|
5674
5958
|
}
|
|
5675
5959
|
/**
|
|
5676
5960
|
* Run the LLM selector to decide what to keep vs collapse.
|
|
@@ -5858,6 +6142,7 @@ var AutoCompactionMiddleware = class {
|
|
|
5858
6142
|
aggressiveOn;
|
|
5859
6143
|
events;
|
|
5860
6144
|
failureMode;
|
|
6145
|
+
policyProvider;
|
|
5861
6146
|
/**
|
|
5862
6147
|
* @param compactor Compactor to use for compaction.
|
|
5863
6148
|
* @param maxContext Provider's max context window in tokens.
|
|
@@ -5880,17 +6165,25 @@ var AutoCompactionMiddleware = class {
|
|
|
5880
6165
|
this.aggressiveOn = opts.aggressiveOn ?? "soft";
|
|
5881
6166
|
this.events = opts.events;
|
|
5882
6167
|
this.failureMode = opts.failureMode ?? "throw_on_hard";
|
|
6168
|
+
this.policyProvider = opts.policyProvider;
|
|
5883
6169
|
}
|
|
5884
6170
|
handler() {
|
|
5885
6171
|
return async (ctx, next) => {
|
|
5886
6172
|
const tokens = this.estimator(ctx);
|
|
5887
6173
|
const load = tokens / this.maxContext;
|
|
5888
|
-
|
|
6174
|
+
const policy = this.policyProvider?.(ctx);
|
|
6175
|
+
const thresholds = policy?.thresholds ?? {
|
|
6176
|
+
warn: this.warnThreshold,
|
|
6177
|
+
soft: this.softThreshold,
|
|
6178
|
+
hard: this.hardThreshold
|
|
6179
|
+
};
|
|
6180
|
+
const aggressiveOn = policy?.aggressiveOn ?? this.aggressiveOn;
|
|
6181
|
+
if (load >= thresholds.hard) {
|
|
5889
6182
|
await this.compact(ctx, true, { level: "hard", tokens, load });
|
|
5890
|
-
} else if (load >=
|
|
5891
|
-
await this.compact(ctx,
|
|
5892
|
-
} else if (load >=
|
|
5893
|
-
await this.compact(ctx,
|
|
6183
|
+
} else if (load >= thresholds.soft) {
|
|
6184
|
+
await this.compact(ctx, aggressiveOn !== "hard", { level: "soft", tokens, load });
|
|
6185
|
+
} else if (load >= thresholds.warn) {
|
|
6186
|
+
await this.compact(ctx, aggressiveOn === "warn", { level: "warn", tokens, load });
|
|
5894
6187
|
}
|
|
5895
6188
|
return next(ctx);
|
|
5896
6189
|
};
|
|
@@ -6858,6 +7151,179 @@ function providerErrorToSubagentError(err, message, cause) {
|
|
|
6858
7151
|
}
|
|
6859
7152
|
return { kind: "unknown", message, retryable: err.retryable, cause };
|
|
6860
7153
|
}
|
|
7154
|
+
function makeSpawnTool(director, roster) {
|
|
7155
|
+
const inputSchema = {
|
|
7156
|
+
type: "object",
|
|
7157
|
+
properties: {
|
|
7158
|
+
role: { type: "string", description: "Roster role id (preferred). When set, the spawn uses the matching config from the roster and ignores other fields." },
|
|
7159
|
+
name: { type: "string", description: "Display name for the subagent. Required when not using roster." },
|
|
7160
|
+
provider: { type: "string", description: 'Provider id (e.g. "anthropic", "openai"). Defaults to the leader provider when omitted.' },
|
|
7161
|
+
model: { type: "string", description: "Model id within the provider. Defaults to the leader model when omitted." },
|
|
7162
|
+
systemPromptOverride: { type: "string", description: "Extra prompt text appended after the role-base prompt." },
|
|
7163
|
+
maxIterations: { type: "number" },
|
|
7164
|
+
maxToolCalls: { type: "number" },
|
|
7165
|
+
maxCostUsd: { type: "number" }
|
|
7166
|
+
},
|
|
7167
|
+
required: []
|
|
7168
|
+
};
|
|
7169
|
+
return {
|
|
7170
|
+
name: "spawn_subagent",
|
|
7171
|
+
description: "Create a new subagent under this director. Returns the subagent id.",
|
|
7172
|
+
usageHint: "Either pass `role` (matches the roster) OR pass `name` + optional `provider`/`model`. Returns `{ subagentId }`.",
|
|
7173
|
+
permission: "auto",
|
|
7174
|
+
mutating: false,
|
|
7175
|
+
inputSchema,
|
|
7176
|
+
async execute(input) {
|
|
7177
|
+
const i = input ?? {};
|
|
7178
|
+
const role = typeof i.role === "string" ? i.role : void 0;
|
|
7179
|
+
const base = role && roster ? roster[role] : void 0;
|
|
7180
|
+
if (role && !base) {
|
|
7181
|
+
return { error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}` };
|
|
7182
|
+
}
|
|
7183
|
+
const cfg = { ...base ?? { name: i.name ?? "subagent" } };
|
|
7184
|
+
if (typeof i.name === "string") cfg.name = i.name;
|
|
7185
|
+
if (typeof i.provider === "string") cfg.provider = i.provider;
|
|
7186
|
+
if (typeof i.model === "string") cfg.model = i.model;
|
|
7187
|
+
if (typeof i.systemPromptOverride === "string") cfg.systemPromptOverride = i.systemPromptOverride;
|
|
7188
|
+
if (typeof i.maxIterations === "number") cfg.maxIterations = i.maxIterations;
|
|
7189
|
+
if (typeof i.maxToolCalls === "number") cfg.maxToolCalls = i.maxToolCalls;
|
|
7190
|
+
if (typeof i.maxCostUsd === "number") cfg.maxCostUsd = i.maxCostUsd;
|
|
7191
|
+
try {
|
|
7192
|
+
const subagentId = await director.spawn(cfg);
|
|
7193
|
+
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name };
|
|
7194
|
+
} catch (err) {
|
|
7195
|
+
if (err instanceof DirectorBudgetError) {
|
|
7196
|
+
return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
|
|
7197
|
+
}
|
|
7198
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
7199
|
+
}
|
|
7200
|
+
}
|
|
7201
|
+
};
|
|
7202
|
+
}
|
|
7203
|
+
function makeAssignTool(director) {
|
|
7204
|
+
const inputSchema = {
|
|
7205
|
+
type: "object",
|
|
7206
|
+
properties: {
|
|
7207
|
+
subagentId: { type: "string", description: "Target subagent id. Required." },
|
|
7208
|
+
description: { type: "string", description: "The task in natural language \u2014 what you want this subagent to do." },
|
|
7209
|
+
maxToolCalls: { type: "number", description: "Optional per-task tool-call budget override." },
|
|
7210
|
+
timeoutMs: { type: "number", description: "Optional per-task timeout in ms." }
|
|
7211
|
+
},
|
|
7212
|
+
required: ["subagentId", "description"]
|
|
7213
|
+
};
|
|
7214
|
+
return {
|
|
7215
|
+
name: "assign_task",
|
|
7216
|
+
description: "Hand a task to a previously spawned subagent. Returns the task id.",
|
|
7217
|
+
permission: "auto",
|
|
7218
|
+
mutating: false,
|
|
7219
|
+
inputSchema,
|
|
7220
|
+
async execute(input) {
|
|
7221
|
+
const i = input;
|
|
7222
|
+
const task = { id: randomUUID(), description: i.description, subagentId: i.subagentId, maxToolCalls: i.maxToolCalls, timeoutMs: i.timeoutMs };
|
|
7223
|
+
const taskId = await director.assign(task);
|
|
7224
|
+
return { taskId, subagentId: i.subagentId };
|
|
7225
|
+
}
|
|
7226
|
+
};
|
|
7227
|
+
}
|
|
7228
|
+
function makeAwaitTasksTool(director) {
|
|
7229
|
+
return {
|
|
7230
|
+
name: "await_tasks",
|
|
7231
|
+
description: "Block until every named task completes. Returns the array of TaskResult.",
|
|
7232
|
+
permission: "auto",
|
|
7233
|
+
mutating: false,
|
|
7234
|
+
inputSchema: { type: "object", properties: { taskIds: { type: "array", items: { type: "string" }, description: "One or more task ids returned by `assign_task`." } }, required: ["taskIds"] },
|
|
7235
|
+
async execute(input) {
|
|
7236
|
+
const i = input;
|
|
7237
|
+
const results = await director.awaitTasks(i.taskIds);
|
|
7238
|
+
return { results };
|
|
7239
|
+
}
|
|
7240
|
+
};
|
|
7241
|
+
}
|
|
7242
|
+
function makeAskTool(director) {
|
|
7243
|
+
return {
|
|
7244
|
+
name: "ask_subagent",
|
|
7245
|
+
description: "Synchronously ask a subagent a question. Blocks until the subagent replies via the bridge.",
|
|
7246
|
+
permission: "auto",
|
|
7247
|
+
mutating: false,
|
|
7248
|
+
inputSchema: {
|
|
7249
|
+
type: "object",
|
|
7250
|
+
properties: {
|
|
7251
|
+
subagentId: { type: "string", description: "Subagent to ask. Must be a previously spawned id." },
|
|
7252
|
+
question: { type: "string", description: "The question or instruction." },
|
|
7253
|
+
timeoutMs: { type: "number", description: "Optional timeout in ms (default 30s)." }
|
|
7254
|
+
},
|
|
7255
|
+
required: ["subagentId", "question"]
|
|
7256
|
+
},
|
|
7257
|
+
async execute(input) {
|
|
7258
|
+
const i = input;
|
|
7259
|
+
try {
|
|
7260
|
+
const answer = await director.ask(i.subagentId, { question: i.question }, i.timeoutMs);
|
|
7261
|
+
return { ok: true, answer };
|
|
7262
|
+
} catch (err) {
|
|
7263
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
7264
|
+
}
|
|
7265
|
+
}
|
|
7266
|
+
};
|
|
7267
|
+
}
|
|
7268
|
+
function makeRollUpTool(director) {
|
|
7269
|
+
return {
|
|
7270
|
+
name: "roll_up",
|
|
7271
|
+
description: "Aggregate completed task results into a single formatted summary.",
|
|
7272
|
+
permission: "auto",
|
|
7273
|
+
mutating: false,
|
|
7274
|
+
inputSchema: {
|
|
7275
|
+
type: "object",
|
|
7276
|
+
properties: {
|
|
7277
|
+
taskIds: { type: "array", items: { type: "string" }, description: "Completed task ids to aggregate." },
|
|
7278
|
+
style: { type: "string", enum: ["markdown", "json"], description: "Output flavor \u2014 markdown (default) or json." }
|
|
7279
|
+
},
|
|
7280
|
+
required: ["taskIds"]
|
|
7281
|
+
},
|
|
7282
|
+
async execute(input) {
|
|
7283
|
+
const i = input;
|
|
7284
|
+
const summary = director.rollUp(i.taskIds, i.style ?? "markdown");
|
|
7285
|
+
return { summary, count: i.taskIds.length };
|
|
7286
|
+
}
|
|
7287
|
+
};
|
|
7288
|
+
}
|
|
7289
|
+
function makeTerminateTool(director) {
|
|
7290
|
+
return {
|
|
7291
|
+
name: "terminate_subagent",
|
|
7292
|
+
description: "Forcibly abort a subagent.",
|
|
7293
|
+
permission: "auto",
|
|
7294
|
+
mutating: true,
|
|
7295
|
+
inputSchema: { type: "object", properties: { subagentId: { type: "string", description: "Subagent to abort." } }, required: ["subagentId"] },
|
|
7296
|
+
async execute(input) {
|
|
7297
|
+
const i = input;
|
|
7298
|
+
await director.terminate(i.subagentId);
|
|
7299
|
+
return { ok: true };
|
|
7300
|
+
}
|
|
7301
|
+
};
|
|
7302
|
+
}
|
|
7303
|
+
function makeFleetStatusTool(director) {
|
|
7304
|
+
return {
|
|
7305
|
+
name: "fleet_status",
|
|
7306
|
+
description: "Snapshot of the fleet \u2014 every subagent's current status, pending vs. completed task counts.",
|
|
7307
|
+
permission: "auto",
|
|
7308
|
+
mutating: false,
|
|
7309
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
7310
|
+
async execute() {
|
|
7311
|
+
return director.status();
|
|
7312
|
+
}
|
|
7313
|
+
};
|
|
7314
|
+
}
|
|
7315
|
+
function makeFleetUsageTool(director) {
|
|
7316
|
+
return {
|
|
7317
|
+
name: "fleet_usage",
|
|
7318
|
+
description: "Token + cost breakdown across the fleet, per-subagent and totals.",
|
|
7319
|
+
permission: "auto",
|
|
7320
|
+
mutating: false,
|
|
7321
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
7322
|
+
async execute() {
|
|
7323
|
+
return director.snapshot();
|
|
7324
|
+
}
|
|
7325
|
+
};
|
|
7326
|
+
}
|
|
6861
7327
|
|
|
6862
7328
|
// src/coordination/director.ts
|
|
6863
7329
|
var DirectorBudgetError = class extends Error {
|
|
@@ -7416,242 +7882,6 @@ var Director = class {
|
|
|
7416
7882
|
return t2;
|
|
7417
7883
|
}
|
|
7418
7884
|
};
|
|
7419
|
-
function makeSpawnTool(director, roster) {
|
|
7420
|
-
const inputSchema = {
|
|
7421
|
-
type: "object",
|
|
7422
|
-
properties: {
|
|
7423
|
-
role: {
|
|
7424
|
-
type: "string",
|
|
7425
|
-
description: "Roster role id (preferred). When set, the spawn uses the matching config from the roster and ignores other fields."
|
|
7426
|
-
},
|
|
7427
|
-
name: {
|
|
7428
|
-
type: "string",
|
|
7429
|
-
description: "Display name for the subagent. Required when not using roster."
|
|
7430
|
-
},
|
|
7431
|
-
provider: {
|
|
7432
|
-
type: "string",
|
|
7433
|
-
description: 'Provider id (e.g. "anthropic", "openai"). Defaults to the leader provider when omitted.'
|
|
7434
|
-
},
|
|
7435
|
-
model: {
|
|
7436
|
-
type: "string",
|
|
7437
|
-
description: "Model id within the provider. Defaults to the leader model when omitted."
|
|
7438
|
-
},
|
|
7439
|
-
systemPromptOverride: {
|
|
7440
|
-
type: "string",
|
|
7441
|
-
description: "Extra prompt text appended after the role-base prompt."
|
|
7442
|
-
},
|
|
7443
|
-
maxIterations: { type: "number" },
|
|
7444
|
-
maxToolCalls: { type: "number" },
|
|
7445
|
-
maxCostUsd: { type: "number" }
|
|
7446
|
-
},
|
|
7447
|
-
required: []
|
|
7448
|
-
};
|
|
7449
|
-
return {
|
|
7450
|
-
name: "spawn_subagent",
|
|
7451
|
-
description: "Create a new subagent under this director. Returns the subagent id. Use this when you need a worker with a specific provider, model, or role to handle a piece of the plan.",
|
|
7452
|
-
usageHint: "Either pass `role` (matches the roster) OR pass `name` + optional `provider`/`model`. Returns `{ subagentId }`.",
|
|
7453
|
-
permission: "auto",
|
|
7454
|
-
mutating: false,
|
|
7455
|
-
inputSchema,
|
|
7456
|
-
async execute(input) {
|
|
7457
|
-
const i = input ?? {};
|
|
7458
|
-
const role = typeof i.role === "string" ? i.role : void 0;
|
|
7459
|
-
const base = role && roster ? roster[role] : void 0;
|
|
7460
|
-
if (role && !base) {
|
|
7461
|
-
return {
|
|
7462
|
-
error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}`
|
|
7463
|
-
};
|
|
7464
|
-
}
|
|
7465
|
-
const cfg = {
|
|
7466
|
-
...base ?? { name: i.name ?? "subagent" }
|
|
7467
|
-
};
|
|
7468
|
-
if (typeof i.name === "string") cfg.name = i.name;
|
|
7469
|
-
if (typeof i.provider === "string") cfg.provider = i.provider;
|
|
7470
|
-
if (typeof i.model === "string") cfg.model = i.model;
|
|
7471
|
-
if (typeof i.systemPromptOverride === "string")
|
|
7472
|
-
cfg.systemPromptOverride = i.systemPromptOverride;
|
|
7473
|
-
if (typeof i.maxIterations === "number") cfg.maxIterations = i.maxIterations;
|
|
7474
|
-
if (typeof i.maxToolCalls === "number") cfg.maxToolCalls = i.maxToolCalls;
|
|
7475
|
-
if (typeof i.maxCostUsd === "number") cfg.maxCostUsd = i.maxCostUsd;
|
|
7476
|
-
try {
|
|
7477
|
-
const subagentId = await director.spawn(cfg);
|
|
7478
|
-
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name };
|
|
7479
|
-
} catch (err) {
|
|
7480
|
-
if (err instanceof DirectorBudgetError) {
|
|
7481
|
-
return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
|
|
7482
|
-
}
|
|
7483
|
-
return { error: err instanceof Error ? err.message : String(err) };
|
|
7484
|
-
}
|
|
7485
|
-
}
|
|
7486
|
-
};
|
|
7487
|
-
}
|
|
7488
|
-
function makeAssignTool(director) {
|
|
7489
|
-
const inputSchema = {
|
|
7490
|
-
type: "object",
|
|
7491
|
-
properties: {
|
|
7492
|
-
subagentId: { type: "string", description: "Target subagent id. Required." },
|
|
7493
|
-
description: {
|
|
7494
|
-
type: "string",
|
|
7495
|
-
description: "The task in natural language \u2014 what you want this subagent to do."
|
|
7496
|
-
},
|
|
7497
|
-
maxToolCalls: { type: "number", description: "Optional per-task tool-call budget override." },
|
|
7498
|
-
timeoutMs: { type: "number", description: "Optional per-task timeout in ms." }
|
|
7499
|
-
},
|
|
7500
|
-
required: ["subagentId", "description"]
|
|
7501
|
-
};
|
|
7502
|
-
return {
|
|
7503
|
-
name: "assign_task",
|
|
7504
|
-
description: "Hand a task to a previously spawned subagent. Returns the task id \u2014 pass it to `await_tasks` to block on completion.",
|
|
7505
|
-
permission: "auto",
|
|
7506
|
-
mutating: false,
|
|
7507
|
-
inputSchema,
|
|
7508
|
-
async execute(input) {
|
|
7509
|
-
const i = input;
|
|
7510
|
-
const task = {
|
|
7511
|
-
id: randomUUID(),
|
|
7512
|
-
description: i.description,
|
|
7513
|
-
subagentId: i.subagentId,
|
|
7514
|
-
maxToolCalls: i.maxToolCalls,
|
|
7515
|
-
timeoutMs: i.timeoutMs
|
|
7516
|
-
};
|
|
7517
|
-
const taskId = await director.assign(task);
|
|
7518
|
-
return { taskId, subagentId: i.subagentId };
|
|
7519
|
-
}
|
|
7520
|
-
};
|
|
7521
|
-
}
|
|
7522
|
-
function makeAwaitTasksTool(director) {
|
|
7523
|
-
const inputSchema = {
|
|
7524
|
-
type: "object",
|
|
7525
|
-
properties: {
|
|
7526
|
-
taskIds: {
|
|
7527
|
-
type: "array",
|
|
7528
|
-
items: { type: "string" },
|
|
7529
|
-
description: "One or more task ids returned by `assign_task`. The call blocks until every id resolves."
|
|
7530
|
-
}
|
|
7531
|
-
},
|
|
7532
|
-
required: ["taskIds"]
|
|
7533
|
-
};
|
|
7534
|
-
return {
|
|
7535
|
-
name: "await_tasks",
|
|
7536
|
-
description: "Block until every named task completes. Returns the array of TaskResult \u2014 use this to gather subagent output before deciding the next step.",
|
|
7537
|
-
permission: "auto",
|
|
7538
|
-
mutating: false,
|
|
7539
|
-
inputSchema,
|
|
7540
|
-
async execute(input) {
|
|
7541
|
-
const i = input;
|
|
7542
|
-
const results = await director.awaitTasks(i.taskIds);
|
|
7543
|
-
return { results };
|
|
7544
|
-
}
|
|
7545
|
-
};
|
|
7546
|
-
}
|
|
7547
|
-
function makeAskTool(director) {
|
|
7548
|
-
const inputSchema = {
|
|
7549
|
-
type: "object",
|
|
7550
|
-
properties: {
|
|
7551
|
-
subagentId: {
|
|
7552
|
-
type: "string",
|
|
7553
|
-
description: "Subagent to ask. Must be a previously spawned id."
|
|
7554
|
-
},
|
|
7555
|
-
question: {
|
|
7556
|
-
type: "string",
|
|
7557
|
-
description: "The question or instruction. Sent as the bridge message payload."
|
|
7558
|
-
},
|
|
7559
|
-
timeoutMs: { type: "number", description: "Optional timeout in ms (default 30s)." }
|
|
7560
|
-
},
|
|
7561
|
-
required: ["subagentId", "question"]
|
|
7562
|
-
};
|
|
7563
|
-
return {
|
|
7564
|
-
name: "ask_subagent",
|
|
7565
|
-
description: "Synchronously ask a subagent a question. Blocks until the subagent replies via the bridge (or the timeout fires). Use this when you need a one-shot answer without spawning a fresh task.",
|
|
7566
|
-
permission: "auto",
|
|
7567
|
-
mutating: false,
|
|
7568
|
-
inputSchema,
|
|
7569
|
-
async execute(input) {
|
|
7570
|
-
const i = input;
|
|
7571
|
-
try {
|
|
7572
|
-
const answer = await director.ask(i.subagentId, { question: i.question }, i.timeoutMs);
|
|
7573
|
-
return { ok: true, answer };
|
|
7574
|
-
} catch (err) {
|
|
7575
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
7576
|
-
}
|
|
7577
|
-
}
|
|
7578
|
-
};
|
|
7579
|
-
}
|
|
7580
|
-
function makeRollUpTool(director) {
|
|
7581
|
-
const inputSchema = {
|
|
7582
|
-
type: "object",
|
|
7583
|
-
properties: {
|
|
7584
|
-
taskIds: {
|
|
7585
|
-
type: "array",
|
|
7586
|
-
items: { type: "string" },
|
|
7587
|
-
description: "Completed task ids to aggregate. Pass the ids returned by previous `assign_task` calls."
|
|
7588
|
-
},
|
|
7589
|
-
style: {
|
|
7590
|
-
type: "string",
|
|
7591
|
-
enum: ["markdown", "json"],
|
|
7592
|
-
description: "Output flavor \u2014 markdown (default) for in-prompt summarization, json for structured downstream processing."
|
|
7593
|
-
}
|
|
7594
|
-
},
|
|
7595
|
-
required: ["taskIds"]
|
|
7596
|
-
};
|
|
7597
|
-
return {
|
|
7598
|
-
name: "roll_up",
|
|
7599
|
-
description: "Aggregate completed task results into a single formatted summary. Use this after `await_tasks` to fold subagent outputs back into the director's context before deciding the next step.",
|
|
7600
|
-
permission: "auto",
|
|
7601
|
-
mutating: false,
|
|
7602
|
-
inputSchema,
|
|
7603
|
-
async execute(input) {
|
|
7604
|
-
const i = input;
|
|
7605
|
-
const summary = director.rollUp(i.taskIds, i.style ?? "markdown");
|
|
7606
|
-
return { summary, count: i.taskIds.length };
|
|
7607
|
-
}
|
|
7608
|
-
};
|
|
7609
|
-
}
|
|
7610
|
-
function makeTerminateTool(director) {
|
|
7611
|
-
const inputSchema = {
|
|
7612
|
-
type: "object",
|
|
7613
|
-
properties: {
|
|
7614
|
-
subagentId: { type: "string", description: "Subagent to abort." }
|
|
7615
|
-
},
|
|
7616
|
-
required: ["subagentId"]
|
|
7617
|
-
};
|
|
7618
|
-
return {
|
|
7619
|
-
name: "terminate_subagent",
|
|
7620
|
-
description: 'Forcibly abort a subagent. Use sparingly \u2014 prefer waiting on the natural budget to expire. The current task (if any) ends with status "stopped".',
|
|
7621
|
-
permission: "auto",
|
|
7622
|
-
mutating: true,
|
|
7623
|
-
inputSchema,
|
|
7624
|
-
async execute(input) {
|
|
7625
|
-
const i = input;
|
|
7626
|
-
await director.terminate(i.subagentId);
|
|
7627
|
-
return { ok: true };
|
|
7628
|
-
}
|
|
7629
|
-
};
|
|
7630
|
-
}
|
|
7631
|
-
function makeFleetStatusTool(director) {
|
|
7632
|
-
return {
|
|
7633
|
-
name: "fleet_status",
|
|
7634
|
-
description: "Snapshot of the fleet \u2014 every subagent's current status, pending vs. completed task counts, and the running total iteration count. Cheap; call freely.",
|
|
7635
|
-
permission: "auto",
|
|
7636
|
-
mutating: false,
|
|
7637
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
7638
|
-
async execute() {
|
|
7639
|
-
return director.status();
|
|
7640
|
-
}
|
|
7641
|
-
};
|
|
7642
|
-
}
|
|
7643
|
-
function makeFleetUsageTool(director) {
|
|
7644
|
-
return {
|
|
7645
|
-
name: "fleet_usage",
|
|
7646
|
-
description: "Token + cost breakdown across the fleet, per-subagent and totals. Use this to reason about which workers to assign costly tasks to or when to wrap up to stay within budget.",
|
|
7647
|
-
permission: "auto",
|
|
7648
|
-
mutating: false,
|
|
7649
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
7650
|
-
async execute() {
|
|
7651
|
-
return director.snapshot();
|
|
7652
|
-
}
|
|
7653
|
-
};
|
|
7654
|
-
}
|
|
7655
7885
|
function createDelegateTool(opts) {
|
|
7656
7886
|
const defaultTimeoutMs = opts.defaultTimeoutMs ?? 4 * 60 * 60 * 1e3;
|
|
7657
7887
|
const rosterIds = opts.roster ? Object.keys(opts.roster) : [];
|
|
@@ -9837,13 +10067,13 @@ function roughEstimate(messages) {
|
|
|
9837
10067
|
function createContextManagerTool(opts = {}) {
|
|
9838
10068
|
return {
|
|
9839
10069
|
name: CONTEXT_MANAGER_TOOL_NAME,
|
|
9840
|
-
description: 'Inspect or reorganize the conversation context window. Use "check" to see token budget. Use "summary" to collapse a message range into a concise note (provide "text" for custom summary). Use "prune" to remove specific messages by index. Use "add_note" to inject a summary note. Use "compact" to run aggressive compaction.',
|
|
10070
|
+
description: 'Inspect or reorganize the conversation context window. Use "check" to see token budget. Use "summary" to collapse a message range into a concise note (provide "text" for custom summary). Use "prune" to remove specific messages by index. Use "add_note" to inject a summary note. Use "compact" to run aggressive compaction. Use "repair" to remove orphan tool_use/tool_result blocks after manual context surgery.',
|
|
9841
10071
|
inputSchema: {
|
|
9842
10072
|
type: "object",
|
|
9843
10073
|
properties: {
|
|
9844
10074
|
action: {
|
|
9845
10075
|
type: "string",
|
|
9846
|
-
enum: ["check", "summary", "prune", "add_note", "compact"],
|
|
10076
|
+
enum: ["check", "summary", "prune", "add_note", "compact", "repair"],
|
|
9847
10077
|
description: "The context operation to perform."
|
|
9848
10078
|
},
|
|
9849
10079
|
from: {
|
|
@@ -9871,12 +10101,15 @@ function createContextManagerTool(opts = {}) {
|
|
|
9871
10101
|
const messages = ctx.messages;
|
|
9872
10102
|
const beforeTokens = roughEstimate(messages);
|
|
9873
10103
|
const applyMessages = (next) => {
|
|
10104
|
+
const repaired = repairToolUseAdjacency(next);
|
|
10105
|
+
const finalMessages = repaired.messages;
|
|
9874
10106
|
if (ctx.state) {
|
|
9875
|
-
ctx.state.replaceMessages(
|
|
10107
|
+
ctx.state.replaceMessages(finalMessages);
|
|
9876
10108
|
} else {
|
|
9877
10109
|
messages.length = 0;
|
|
9878
|
-
messages.splice(0, 0, ...
|
|
10110
|
+
messages.splice(0, 0, ...finalMessages);
|
|
9879
10111
|
}
|
|
10112
|
+
return repaired.report;
|
|
9880
10113
|
};
|
|
9881
10114
|
switch (input.action) {
|
|
9882
10115
|
case "check": {
|
|
@@ -9893,6 +10126,22 @@ function createContextManagerTool(opts = {}) {
|
|
|
9893
10126
|
})
|
|
9894
10127
|
};
|
|
9895
10128
|
}
|
|
10129
|
+
case "repair": {
|
|
10130
|
+
const repair = applyMessages([...messages]);
|
|
10131
|
+
const afterTokens = roughEstimate(ctx.messages);
|
|
10132
|
+
return {
|
|
10133
|
+
action: "repair",
|
|
10134
|
+
beforeTokens,
|
|
10135
|
+
afterTokens,
|
|
10136
|
+
messageCount: ctx.messages.length,
|
|
10137
|
+
repaired: repair.changed ? {
|
|
10138
|
+
removedToolUses: repair.removedToolUses,
|
|
10139
|
+
removedToolResults: repair.removedToolResults,
|
|
10140
|
+
removedMessages: repair.removedMessages
|
|
10141
|
+
} : void 0,
|
|
10142
|
+
notes: repair.changed ? "Context tool-call adjacency repaired." : "Context tool-call adjacency already valid."
|
|
10143
|
+
};
|
|
10144
|
+
}
|
|
9896
10145
|
case "compact": {
|
|
9897
10146
|
if (!opts.compactor) {
|
|
9898
10147
|
return {
|
|
@@ -9903,11 +10152,19 @@ function createContextManagerTool(opts = {}) {
|
|
|
9903
10152
|
};
|
|
9904
10153
|
}
|
|
9905
10154
|
const report = await opts.compactor.compact(ctx);
|
|
10155
|
+
const repair = applyMessages([...ctx.messages]);
|
|
10156
|
+
const afterTokens = repair.changed ? roughEstimate(ctx.messages) : report.after;
|
|
10157
|
+
const repaired = report.repaired ?? (repair.changed ? repair : void 0);
|
|
9906
10158
|
return {
|
|
9907
10159
|
action: "compact",
|
|
9908
10160
|
beforeTokens,
|
|
9909
|
-
afterTokens
|
|
9910
|
-
messageCount: messages.length
|
|
10161
|
+
afterTokens,
|
|
10162
|
+
messageCount: ctx.messages.length,
|
|
10163
|
+
repaired: repaired ? {
|
|
10164
|
+
removedToolUses: repaired.removedToolUses,
|
|
10165
|
+
removedToolResults: repaired.removedToolResults,
|
|
10166
|
+
removedMessages: repaired.removedMessages
|
|
10167
|
+
} : void 0
|
|
9911
10168
|
};
|
|
9912
10169
|
}
|
|
9913
10170
|
case "prune": {
|
|
@@ -9923,14 +10180,19 @@ function createContextManagerTool(opts = {}) {
|
|
|
9923
10180
|
}
|
|
9924
10181
|
const copy = [...messages];
|
|
9925
10182
|
const removed = copy.splice(from, to - from + 1);
|
|
9926
|
-
applyMessages(copy);
|
|
9927
|
-
const afterTokens = roughEstimate(
|
|
10183
|
+
const repair = applyMessages(copy);
|
|
10184
|
+
const afterTokens = roughEstimate(ctx.messages);
|
|
9928
10185
|
return {
|
|
9929
10186
|
action: "prune",
|
|
9930
10187
|
beforeTokens,
|
|
9931
10188
|
afterTokens,
|
|
9932
|
-
messageCount:
|
|
9933
|
-
removedCount: removed.length
|
|
10189
|
+
messageCount: ctx.messages.length,
|
|
10190
|
+
removedCount: removed.length,
|
|
10191
|
+
repaired: repair.changed ? {
|
|
10192
|
+
removedToolUses: repair.removedToolUses,
|
|
10193
|
+
removedToolResults: repair.removedToolResults,
|
|
10194
|
+
removedMessages: repair.removedMessages
|
|
10195
|
+
} : void 0
|
|
9934
10196
|
};
|
|
9935
10197
|
}
|
|
9936
10198
|
case "add_note": {
|
|
@@ -9942,14 +10204,19 @@ function createContextManagerTool(opts = {}) {
|
|
|
9942
10204
|
};
|
|
9943
10205
|
const copy = [...messages];
|
|
9944
10206
|
copy.splice(afterIdx, 0, noteMsg);
|
|
9945
|
-
applyMessages(copy);
|
|
9946
|
-
const afterTokens = roughEstimate(
|
|
10207
|
+
const repair = applyMessages(copy);
|
|
10208
|
+
const afterTokens = roughEstimate(ctx.messages);
|
|
9947
10209
|
return {
|
|
9948
10210
|
action: "add_note",
|
|
9949
10211
|
beforeTokens,
|
|
9950
10212
|
afterTokens,
|
|
9951
|
-
messageCount:
|
|
9952
|
-
summary: noteText
|
|
10213
|
+
messageCount: ctx.messages.length,
|
|
10214
|
+
summary: noteText,
|
|
10215
|
+
repaired: repair.changed ? {
|
|
10216
|
+
removedToolUses: repair.removedToolUses,
|
|
10217
|
+
removedToolResults: repair.removedToolResults,
|
|
10218
|
+
removedMessages: repair.removedMessages
|
|
10219
|
+
} : void 0
|
|
9953
10220
|
};
|
|
9954
10221
|
}
|
|
9955
10222
|
case "summary": {
|
|
@@ -9970,14 +10237,19 @@ function createContextManagerTool(opts = {}) {
|
|
|
9970
10237
|
};
|
|
9971
10238
|
const copy = [...messages];
|
|
9972
10239
|
copy.splice(from, to - from + 1, summaryMsg);
|
|
9973
|
-
applyMessages(copy);
|
|
9974
|
-
const afterTokens = roughEstimate(
|
|
10240
|
+
const repair = applyMessages(copy);
|
|
10241
|
+
const afterTokens = roughEstimate(ctx.messages);
|
|
9975
10242
|
return {
|
|
9976
10243
|
action: "summary",
|
|
9977
10244
|
beforeTokens,
|
|
9978
10245
|
afterTokens,
|
|
9979
|
-
messageCount:
|
|
9980
|
-
summary: summaryText
|
|
10246
|
+
messageCount: ctx.messages.length,
|
|
10247
|
+
summary: summaryText,
|
|
10248
|
+
repaired: repair.changed ? {
|
|
10249
|
+
removedToolUses: repair.removedToolUses,
|
|
10250
|
+
removedToolResults: repair.removedToolResults,
|
|
10251
|
+
removedMessages: repair.removedMessages
|
|
10252
|
+
} : void 0
|
|
9981
10253
|
};
|
|
9982
10254
|
}
|
|
9983
10255
|
default:
|
|
@@ -10081,6 +10353,41 @@ var sentinelServer = () => ({
|
|
|
10081
10353
|
permission: "deny"
|
|
10082
10354
|
// security tool — require explicit confirmation
|
|
10083
10355
|
});
|
|
10356
|
+
var zaiVisionServer = () => ({
|
|
10357
|
+
name: "zai-vision",
|
|
10358
|
+
description: "Z.AI Vision MCP \u2014 image analysis and screenshot understanding",
|
|
10359
|
+
transport: "stdio",
|
|
10360
|
+
command: "npx",
|
|
10361
|
+
args: ["-y", "@z_ai/mcp-server@latest"],
|
|
10362
|
+
env: {
|
|
10363
|
+
Z_AI_API_KEY: process.env.Z_AI_API_KEY ?? "",
|
|
10364
|
+
Z_AI_MODE: process.env.Z_AI_MODE ?? "ZAI"
|
|
10365
|
+
},
|
|
10366
|
+
allowedTools: [
|
|
10367
|
+
"image_analysis",
|
|
10368
|
+
"extract_text_from_screenshot",
|
|
10369
|
+
"diagnose_error_screenshot",
|
|
10370
|
+
"understand_technical_diagram",
|
|
10371
|
+
"analyze_data_visualization",
|
|
10372
|
+
"ui_diff_check"
|
|
10373
|
+
],
|
|
10374
|
+
permission: "auto"
|
|
10375
|
+
});
|
|
10376
|
+
var miniMaxVisionServer = () => ({
|
|
10377
|
+
name: "minimax-vision",
|
|
10378
|
+
description: "MiniMax MCP \u2014 image understanding via understand_image",
|
|
10379
|
+
transport: "stdio",
|
|
10380
|
+
command: "uvx",
|
|
10381
|
+
args: ["minimax-coding-plan-mcp", "-y"],
|
|
10382
|
+
env: {
|
|
10383
|
+
MINIMAX_API_KEY: process.env.MINIMAX_API_KEY ?? "",
|
|
10384
|
+
MINIMAX_MCP_BASE_PATH: process.env.MINIMAX_MCP_BASE_PATH ?? "./.wrongstack/minimax-output",
|
|
10385
|
+
MINIMAX_API_HOST: process.env.MINIMAX_API_HOST ?? "https://api.minimax.io",
|
|
10386
|
+
MINIMAX_API_RESOURCE_MODE: process.env.MINIMAX_API_RESOURCE_MODE ?? "url"
|
|
10387
|
+
},
|
|
10388
|
+
allowedTools: ["understand_image"],
|
|
10389
|
+
permission: "auto"
|
|
10390
|
+
});
|
|
10084
10391
|
var allServers = () => ({
|
|
10085
10392
|
filesystem: { ...filesystemServer(), enabled: false },
|
|
10086
10393
|
github: { ...githubServer(), enabled: false },
|
|
@@ -10091,7 +10398,9 @@ var allServers = () => ({
|
|
|
10091
10398
|
slack: { ...slackServer(), enabled: false },
|
|
10092
10399
|
aws: { ...awsServer(), enabled: false },
|
|
10093
10400
|
"google-maps": { ...googleMapsServer(), enabled: false },
|
|
10094
|
-
sentinel: { ...sentinelServer(), enabled: false }
|
|
10401
|
+
sentinel: { ...sentinelServer(), enabled: false },
|
|
10402
|
+
"zai-vision": { ...zaiVisionServer(), enabled: false },
|
|
10403
|
+
"minimax-vision": { ...miniMaxVisionServer(), enabled: false }
|
|
10095
10404
|
});
|
|
10096
10405
|
|
|
10097
10406
|
// src/extension/registry.ts
|
|
@@ -10194,7 +10503,8 @@ var ExtensionRegistry = class {
|
|
|
10194
10503
|
}
|
|
10195
10504
|
// ── Hook runners ─────────────────────────────────────────────────
|
|
10196
10505
|
async runBeforeRun(...args) {
|
|
10197
|
-
|
|
10506
|
+
const snapshot = [...this.extensions];
|
|
10507
|
+
for (const ext of snapshot) {
|
|
10198
10508
|
if (!ext.beforeRun) continue;
|
|
10199
10509
|
try {
|
|
10200
10510
|
await ext.beforeRun(...args);
|
|
@@ -10204,7 +10514,8 @@ var ExtensionRegistry = class {
|
|
|
10204
10514
|
}
|
|
10205
10515
|
}
|
|
10206
10516
|
async runAfterRun(...args) {
|
|
10207
|
-
|
|
10517
|
+
const snapshot = [...this.extensions];
|
|
10518
|
+
for (const ext of snapshot) {
|
|
10208
10519
|
if (!ext.afterRun) continue;
|
|
10209
10520
|
try {
|
|
10210
10521
|
await ext.afterRun(...args);
|
|
@@ -10214,7 +10525,8 @@ var ExtensionRegistry = class {
|
|
|
10214
10525
|
}
|
|
10215
10526
|
}
|
|
10216
10527
|
async runBeforeIteration(...args) {
|
|
10217
|
-
|
|
10528
|
+
const snapshot = [...this.extensions];
|
|
10529
|
+
for (const ext of snapshot) {
|
|
10218
10530
|
if (!ext.beforeIteration) continue;
|
|
10219
10531
|
try {
|
|
10220
10532
|
await ext.beforeIteration(...args);
|
|
@@ -10224,7 +10536,8 @@ var ExtensionRegistry = class {
|
|
|
10224
10536
|
}
|
|
10225
10537
|
}
|
|
10226
10538
|
async runAfterIteration(...args) {
|
|
10227
|
-
|
|
10539
|
+
const snapshot = [...this.extensions];
|
|
10540
|
+
for (const ext of snapshot) {
|
|
10228
10541
|
if (!ext.afterIteration) continue;
|
|
10229
10542
|
try {
|
|
10230
10543
|
await ext.afterIteration(...args);
|
|
@@ -10238,7 +10551,8 @@ var ExtensionRegistry = class {
|
|
|
10238
10551
|
* result wins; subsequent hooks are skipped.
|
|
10239
10552
|
*/
|
|
10240
10553
|
async runOnError(...args) {
|
|
10241
|
-
|
|
10554
|
+
const snapshot = [...this.extensions];
|
|
10555
|
+
for (const ext of snapshot) {
|
|
10242
10556
|
if (!ext.onError) continue;
|
|
10243
10557
|
try {
|
|
10244
10558
|
const result = await ext.onError(...args);
|
|
@@ -10273,7 +10587,8 @@ var ExtensionRegistry = class {
|
|
|
10273
10587
|
}
|
|
10274
10588
|
async runBeforeToolExecution(...args) {
|
|
10275
10589
|
let toolUses = args[1];
|
|
10276
|
-
|
|
10590
|
+
const snapshot = [...this.extensions];
|
|
10591
|
+
for (const ext of snapshot) {
|
|
10277
10592
|
if (!ext.beforeToolExecution) continue;
|
|
10278
10593
|
try {
|
|
10279
10594
|
toolUses = await ext.beforeToolExecution(args[0], toolUses);
|
|
@@ -10284,7 +10599,8 @@ var ExtensionRegistry = class {
|
|
|
10284
10599
|
return toolUses;
|
|
10285
10600
|
}
|
|
10286
10601
|
async runAfterToolExecution(...args) {
|
|
10287
|
-
|
|
10602
|
+
const snapshot = [...this.extensions];
|
|
10603
|
+
for (const ext of snapshot) {
|
|
10288
10604
|
if (!ext.afterToolExecution) continue;
|
|
10289
10605
|
try {
|
|
10290
10606
|
await ext.afterToolExecution(...args);
|
|
@@ -10609,6 +10925,17 @@ var Agent = class {
|
|
|
10609
10925
|
* Build request and run through request pipeline.
|
|
10610
10926
|
*/
|
|
10611
10927
|
async buildAndRunRequestPipeline(opts) {
|
|
10928
|
+
const repaired = repairToolUseAdjacency(this.ctx.messages);
|
|
10929
|
+
if (repaired.report.changed) {
|
|
10930
|
+
this.ctx.state.replaceMessages(repaired.messages);
|
|
10931
|
+
this.events.emit("context.repaired", {
|
|
10932
|
+
ctx: this.ctx,
|
|
10933
|
+
...repaired.report
|
|
10934
|
+
});
|
|
10935
|
+
this.logger.warn(
|
|
10936
|
+
`Repaired context tool adjacency: removed ${repaired.report.removedToolUses.length} tool_use block(s), ${repaired.report.removedToolResults.length} tool_result block(s), ${repaired.report.removedMessages} empty message(s)`
|
|
10937
|
+
);
|
|
10938
|
+
}
|
|
10612
10939
|
const baseReq = {
|
|
10613
10940
|
model: opts.model ?? this.ctx.model,
|
|
10614
10941
|
system: this.ctx.systemPrompt,
|
|
@@ -10665,13 +10992,13 @@ var Agent = class {
|
|
|
10665
10992
|
* single tool.
|
|
10666
10993
|
*/
|
|
10667
10994
|
async executeTools(toolUses) {
|
|
10668
|
-
|
|
10995
|
+
const selectedToolUses = await this.extensions.runBeforeToolExecution(this.ctx, toolUses);
|
|
10669
10996
|
const { outputs } = await this.toolExecutor.executeBatch(
|
|
10670
|
-
|
|
10997
|
+
selectedToolUses,
|
|
10671
10998
|
this.ctx,
|
|
10672
10999
|
this.executionStrategy
|
|
10673
11000
|
);
|
|
10674
|
-
const useById = new Map(
|
|
11001
|
+
const useById = new Map(selectedToolUses.map((u) => [u.id, u]));
|
|
10675
11002
|
for (const { result, tool, durationMs } of outputs) {
|
|
10676
11003
|
if (result.type === "tool_confirm_pending") {
|
|
10677
11004
|
const decision = await this.waitForConfirm({
|
|
@@ -11870,7 +12197,7 @@ var DefaultPluginAPI = class {
|
|
|
11870
12197
|
} : noopSlashCommands;
|
|
11871
12198
|
}
|
|
11872
12199
|
onEvent(event, handler) {
|
|
11873
|
-
const off = this.events.
|
|
12200
|
+
const off = this.events.on(event, handler);
|
|
11874
12201
|
this.pluginCleanupFns.push(off);
|
|
11875
12202
|
return off;
|
|
11876
12203
|
}
|
|
@@ -11947,6 +12274,7 @@ function scopedMetrics(sink, pluginName) {
|
|
|
11947
12274
|
}
|
|
11948
12275
|
|
|
11949
12276
|
// src/plugin/loader.ts
|
|
12277
|
+
var pluginApiMap = /* @__PURE__ */ new WeakMap();
|
|
11950
12278
|
var KERNEL_API_VERSION = "0.1.10";
|
|
11951
12279
|
function parseSemver(v) {
|
|
11952
12280
|
const parts = v.replace(/^[^0-9]*/, "").split(".").map((s) => Number.parseInt(s, 10) || 0);
|
|
@@ -12103,6 +12431,7 @@ async function loadPlugins(plugins, opts) {
|
|
|
12103
12431
|
const rawApi = opts.apiFactory(plugin);
|
|
12104
12432
|
const api = plugin.capabilities ? wrapApiForCapabilityCheck(plugin, rawApi, opts.log, opts.enforceCapabilities) : rawApi;
|
|
12105
12433
|
await plugin.setup(api);
|
|
12434
|
+
pluginApiMap.set(plugin, api);
|
|
12106
12435
|
loaded.push(plugin);
|
|
12107
12436
|
opts.log.info(`Plugin "${plugin.name}" loaded`);
|
|
12108
12437
|
} catch (err) {
|
|
@@ -12117,8 +12446,9 @@ async function unloadPlugins(loadedPlugins, opts) {
|
|
|
12117
12446
|
for (const plugin of ordered) {
|
|
12118
12447
|
if (typeof plugin.teardown !== "function") continue;
|
|
12119
12448
|
try {
|
|
12120
|
-
const api = opts.apiFactory(plugin);
|
|
12449
|
+
const api = pluginApiMap.get(plugin) ?? opts.apiFactory(plugin);
|
|
12121
12450
|
await plugin.teardown(api);
|
|
12451
|
+
pluginApiMap.delete(plugin);
|
|
12122
12452
|
opts.log.info(`Plugin "${plugin.name}" torn down`);
|
|
12123
12453
|
} catch (err) {
|
|
12124
12454
|
opts.log.error(`Plugin "${plugin.name}" teardown failed`, err);
|
|
@@ -12205,6 +12535,6 @@ function wrapApiForCapabilityCheck(plugin, api, log, enforce = false) {
|
|
|
12205
12535
|
});
|
|
12206
12536
|
}
|
|
12207
12537
|
|
|
12208
|
-
export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, Agent, AgentError, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutonomousRunner, BUG_HUNTER_AGENT, BudgetExceededError, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorBudgetError, DirectorStateCheckpoint, DoneConditionChecker, EventBus, ExtensionRegistry, FLEET_ROSTER, FleetBus, FleetUsageAggregator, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, NoopMetricsSink, NoopTracer, OTelTracer, PROMETHEUS_CONTENT_TYPE, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, RunController, SECURITY_SCANNER_AGENT, SelectiveCompactor, SessionAnalyzer, SessionError, SlashCommandRegistry, SpecDrivenDev, SpecParser, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskTracker, ToolError, ToolExecutor, ToolRegistry, WrongStackError, addPlanItem, allServers, asBlocks, asText, atomicWrite, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, braveSearchServer, buildChildEnv, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildRecoveryStrategies, classifyFamily, clearPlan, color, compileGlob, composeDirectorPrompt, composeSubagentPrompt, computeTaskProgress, context7Server, contextManagerTool, createContextManagerTool, createDefaultPipelines, createDelegateTool, createMessage, createToolOutputSerializer, decryptConfigSecrets, detectNewlineStyle, emptyPlan, encryptConfigSecrets, ensureDir, estimateTextTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, extractRunEnv, filesystemServer, findCriticalPath, formatPlan, formatTodosList, githubServer, googleMapsServer, isAgentError, isConfigError, isImageBlock, isPluginError, isSessionError, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isWrongStackError, loadDirectorState, loadPlan, loadPlugins, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeDirectorSessionFactory, matchAny, matchGlob, migratePlaintextSecrets, normalizeToLf, projectHash, removePlanItem, renderPrometheus, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, safeParse, safeStringify, sanitizeJsonString, savePlan, saveTodosCheckpoint, sentinelServer, setPlanItemStatus, slackServer, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, wrapAsState };
|
|
12538
|
+
export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, Agent, AgentError, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutonomousRunner, BUG_HUNTER_AGENT, BudgetExceededError, CONTEXT_WINDOW_MODES, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorBudgetError, DirectorStateCheckpoint, DoneConditionChecker, EventBus, ExtensionRegistry, FLEET_ROSTER, FleetBus, FleetUsageAggregator, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, NoopMetricsSink, NoopTracer, OTelTracer, PROMETHEUS_CONTENT_TYPE, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, RunController, SECURITY_SCANNER_AGENT, SelectiveCompactor, SessionAnalyzer, SessionError, SlashCommandRegistry, SpecDrivenDev, SpecParser, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskTracker, ToolError, ToolExecutor, ToolRegistry, WrongStackError, addPlanItem, allServers, asBlocks, asText, atomicWrite, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, braveSearchServer, buildChildEnv, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildRecoveryStrategies, classifyFamily, clearPlan, color, compileGlob, composeDirectorPrompt, composeSubagentPrompt, computeTaskProgress, context7Server, contextManagerTool, createContextManagerTool, createDefaultPipelines, createDelegateTool, createMessage, createToolOutputSerializer, decryptConfigSecrets, detectNewlineStyle, emptyPlan, encryptConfigSecrets, ensureDir, estimateTextTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, extractRunEnv, filesystemServer, findCriticalPath, formatContextWindowModeList, formatPlan, formatTodosList, getContextWindowMode, githubServer, googleMapsServer, isAgentError, isConfigError, isContextWindowModeId, isImageBlock, isPluginError, isSessionError, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isWrongStackError, listContextWindowModes, loadDirectorState, loadPlan, loadPlugins, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeDirectorSessionFactory, matchAny, matchGlob, migratePlaintextSecrets, miniMaxVisionServer, normalizeToLf, projectHash, removePlanItem, renderPrometheus, repairToolUseAdjacency, resolveContextWindowPolicy, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, safeParse, safeStringify, sanitizeJsonString, savePlan, saveTodosCheckpoint, sentinelServer, setPlanItemStatus, slackServer, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, wrapAsState, zaiVisionServer };
|
|
12209
12539
|
//# sourceMappingURL=index.js.map
|
|
12210
12540
|
//# sourceMappingURL=index.js.map
|