@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/defaults/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as fs5 from 'fs';
|
|
2
2
|
import * as path3 from 'path';
|
|
3
3
|
import * as crypto2 from 'crypto';
|
|
4
4
|
import { randomBytes, randomUUID, createCipheriv, createDecipheriv } from 'crypto';
|
|
@@ -62,7 +62,7 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
62
62
|
this.pretty = opts.pretty ?? true;
|
|
63
63
|
if (this.file) {
|
|
64
64
|
try {
|
|
65
|
-
|
|
65
|
+
fs5.mkdirSync(path3.dirname(this.file), { recursive: true });
|
|
66
66
|
} catch {
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -101,7 +101,7 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
101
101
|
}
|
|
102
102
|
if (this.file) {
|
|
103
103
|
try {
|
|
104
|
-
|
|
104
|
+
fs5.appendFileSync(this.file, `${JSON.stringify(entry)}
|
|
105
105
|
`);
|
|
106
106
|
} catch {
|
|
107
107
|
}
|
|
@@ -192,6 +192,98 @@ async function renameWithRetry(from, to) {
|
|
|
192
192
|
throw lastErr;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
// src/utils/message-invariants.ts
|
|
196
|
+
function repairToolUseAdjacency(messages) {
|
|
197
|
+
const removedToolUses = [];
|
|
198
|
+
const removedToolResults = [];
|
|
199
|
+
let removedMessages = 0;
|
|
200
|
+
let changed = false;
|
|
201
|
+
const out = [];
|
|
202
|
+
for (let i = 0; i < messages.length; i++) {
|
|
203
|
+
const original = messages[i];
|
|
204
|
+
let msg = original;
|
|
205
|
+
if (hasToolUse(msg)) {
|
|
206
|
+
const nextIds = toolResultIds(messages[i + 1]);
|
|
207
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
208
|
+
const next = [];
|
|
209
|
+
for (const block of blocks) {
|
|
210
|
+
if (block.type === "tool_use" && !nextIds.has(block.id)) {
|
|
211
|
+
removedToolUses.push(block.id);
|
|
212
|
+
changed = true;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
next.push(block);
|
|
216
|
+
}
|
|
217
|
+
return next;
|
|
218
|
+
});
|
|
219
|
+
msg = filtered ?? msg;
|
|
220
|
+
}
|
|
221
|
+
if (hasToolResult(msg)) {
|
|
222
|
+
const allowed = toolUseIds(out[out.length - 1]);
|
|
223
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
224
|
+
const next = [];
|
|
225
|
+
for (const block of blocks) {
|
|
226
|
+
if (block.type === "tool_result" && !allowed.has(block.tool_use_id)) {
|
|
227
|
+
removedToolResults.push(block.tool_use_id);
|
|
228
|
+
changed = true;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
next.push(block);
|
|
232
|
+
}
|
|
233
|
+
return next;
|
|
234
|
+
});
|
|
235
|
+
msg = filtered ?? msg;
|
|
236
|
+
}
|
|
237
|
+
if (isEmptyMessage(msg)) {
|
|
238
|
+
removedMessages++;
|
|
239
|
+
changed = true;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
out.push(msg);
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
messages: changed ? out : messages,
|
|
246
|
+
report: { changed, removedToolUses, removedToolResults, removedMessages }
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function hasToolUse(msg) {
|
|
250
|
+
return contentBlocks(msg).some((b) => b.type === "tool_use");
|
|
251
|
+
}
|
|
252
|
+
function hasToolResult(msg) {
|
|
253
|
+
return contentBlocks(msg).some((b) => b.type === "tool_result");
|
|
254
|
+
}
|
|
255
|
+
function toolUseIds(msg) {
|
|
256
|
+
const ids = /* @__PURE__ */ new Set();
|
|
257
|
+
if (!msg || msg.role !== "assistant") return ids;
|
|
258
|
+
for (const block of contentBlocks(msg)) {
|
|
259
|
+
if (block.type === "tool_use") ids.add(block.id);
|
|
260
|
+
}
|
|
261
|
+
return ids;
|
|
262
|
+
}
|
|
263
|
+
function toolResultIds(msg) {
|
|
264
|
+
const ids = /* @__PURE__ */ new Set();
|
|
265
|
+
if (!msg || msg.role !== "user") return ids;
|
|
266
|
+
for (const block of contentBlocks(msg)) {
|
|
267
|
+
if (block.type === "tool_result") ids.add(block.tool_use_id);
|
|
268
|
+
}
|
|
269
|
+
return ids;
|
|
270
|
+
}
|
|
271
|
+
function contentBlocks(msg) {
|
|
272
|
+
return msg && Array.isArray(msg.content) ? msg.content : [];
|
|
273
|
+
}
|
|
274
|
+
function mapContent(msg, fn) {
|
|
275
|
+
if (!Array.isArray(msg.content)) return msg;
|
|
276
|
+
const next = fn(msg.content);
|
|
277
|
+
if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {
|
|
278
|
+
return msg;
|
|
279
|
+
}
|
|
280
|
+
return { ...msg, content: next };
|
|
281
|
+
}
|
|
282
|
+
function isEmptyMessage(msg) {
|
|
283
|
+
if (typeof msg.content === "string") return msg.content.trim().length === 0;
|
|
284
|
+
return msg.content.length === 0;
|
|
285
|
+
}
|
|
286
|
+
|
|
195
287
|
// src/storage/session-store.ts
|
|
196
288
|
var DefaultSessionStore = class {
|
|
197
289
|
dir;
|
|
@@ -394,11 +486,17 @@ var DefaultSessionStore = class {
|
|
|
394
486
|
if (openToolUses.size > 0) {
|
|
395
487
|
this.events?.emit("session.damaged", {
|
|
396
488
|
sessionId,
|
|
397
|
-
detail: `${openToolUses.size} tool_use blocks without matching results
|
|
489
|
+
detail: `${openToolUses.size} tool_use blocks without matching results - replay repaired`
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
const repaired = repairToolUseAdjacency(messages);
|
|
493
|
+
if (repaired.report.changed) {
|
|
494
|
+
this.events?.emit("session.damaged", {
|
|
495
|
+
sessionId,
|
|
496
|
+
detail: `Repaired replay adjacency: removed ${repaired.report.removedToolUses.length} tool_use, ${repaired.report.removedToolResults.length} tool_result, ${repaired.report.removedMessages} empty messages`
|
|
398
497
|
});
|
|
399
|
-
return { messages, usage };
|
|
400
498
|
}
|
|
401
|
-
return { messages, usage };
|
|
499
|
+
return { messages: repaired.messages, usage };
|
|
402
500
|
}
|
|
403
501
|
};
|
|
404
502
|
var FileSessionWriter = class {
|
|
@@ -424,6 +522,7 @@ var FileSessionWriter = class {
|
|
|
424
522
|
startedAt;
|
|
425
523
|
meta;
|
|
426
524
|
closed = false;
|
|
525
|
+
closing = false;
|
|
427
526
|
manifestFile;
|
|
428
527
|
summary;
|
|
429
528
|
tokenIn = 0;
|
|
@@ -439,9 +538,7 @@ var FileSessionWriter = class {
|
|
|
439
538
|
resumed;
|
|
440
539
|
appendFailCount = 0;
|
|
441
540
|
lastAppendWarnAt = 0;
|
|
442
|
-
async
|
|
443
|
-
if (this.initDone || this.closed) return;
|
|
444
|
-
this.initDone = true;
|
|
541
|
+
async writeSessionStartLazy() {
|
|
445
542
|
const record = `${JSON.stringify({
|
|
446
543
|
type: this.resumed ? "session_resumed" : "session_start",
|
|
447
544
|
ts: this.startedAt,
|
|
@@ -460,7 +557,8 @@ var FileSessionWriter = class {
|
|
|
460
557
|
async append(event) {
|
|
461
558
|
if (this.closed) return;
|
|
462
559
|
if (!this.initDone) {
|
|
463
|
-
|
|
560
|
+
this.initDone = true;
|
|
561
|
+
await this.writeSessionStartLazy();
|
|
464
562
|
}
|
|
465
563
|
this.observeForSummary(event);
|
|
466
564
|
try {
|
|
@@ -501,7 +599,8 @@ var FileSessionWriter = class {
|
|
|
501
599
|
}
|
|
502
600
|
}
|
|
503
601
|
async close() {
|
|
504
|
-
if (this.
|
|
602
|
+
if (this.closing) return;
|
|
603
|
+
this.closing = true;
|
|
505
604
|
this.closed = true;
|
|
506
605
|
if (this.manifestFile) {
|
|
507
606
|
try {
|
|
@@ -904,80 +1003,7 @@ function deepFreeze(obj) {
|
|
|
904
1003
|
return Object.freeze(obj);
|
|
905
1004
|
}
|
|
906
1005
|
|
|
907
|
-
// src/
|
|
908
|
-
var ENCRYPTED_PREFIX = "enc:v1:";
|
|
909
|
-
|
|
910
|
-
// src/security/secret-vault.ts
|
|
911
|
-
var KEY_BYTES = 32;
|
|
912
|
-
var IV_BYTES = 12;
|
|
913
|
-
var TAG_BYTES = 16;
|
|
914
|
-
var ALGO = "aes-256-gcm";
|
|
915
|
-
var DefaultSecretVault = class {
|
|
916
|
-
keyFile;
|
|
917
|
-
key;
|
|
918
|
-
constructor(opts) {
|
|
919
|
-
this.keyFile = opts.keyFile;
|
|
920
|
-
}
|
|
921
|
-
isEncrypted(value) {
|
|
922
|
-
return typeof value === "string" && value.startsWith(ENCRYPTED_PREFIX);
|
|
923
|
-
}
|
|
924
|
-
encrypt(plaintext) {
|
|
925
|
-
if (this.isEncrypted(plaintext)) return plaintext;
|
|
926
|
-
const key = this.loadOrCreateKey();
|
|
927
|
-
const iv = randomBytes(IV_BYTES);
|
|
928
|
-
const cipher = createCipheriv(ALGO, key, iv);
|
|
929
|
-
const ct = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
930
|
-
const tag = cipher.getAuthTag();
|
|
931
|
-
return `${ENCRYPTED_PREFIX}${iv.toString("base64")}:${tag.toString("base64")}:${ct.toString("base64")}`;
|
|
932
|
-
}
|
|
933
|
-
decrypt(value) {
|
|
934
|
-
if (!this.isEncrypted(value)) return value;
|
|
935
|
-
const rest = value.slice(ENCRYPTED_PREFIX.length);
|
|
936
|
-
const parts = rest.split(":");
|
|
937
|
-
if (parts.length !== 3) {
|
|
938
|
-
throw new Error("SecretVault: malformed encrypted value");
|
|
939
|
-
}
|
|
940
|
-
const [ivB64, tagB64, ctB64] = parts;
|
|
941
|
-
const iv = Buffer.from(ivB64, "base64");
|
|
942
|
-
const tag = Buffer.from(tagB64, "base64");
|
|
943
|
-
const ct = Buffer.from(ctB64, "base64");
|
|
944
|
-
if (iv.length !== IV_BYTES) throw new Error("SecretVault: bad IV length");
|
|
945
|
-
if (tag.length !== TAG_BYTES) throw new Error("SecretVault: bad tag length");
|
|
946
|
-
const key = this.loadOrCreateKey();
|
|
947
|
-
const decipher = createDecipheriv(ALGO, key, iv);
|
|
948
|
-
decipher.setAuthTag(tag);
|
|
949
|
-
const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
|
|
950
|
-
return pt.toString("utf8");
|
|
951
|
-
}
|
|
952
|
-
loadOrCreateKey() {
|
|
953
|
-
if (this.key) return this.key;
|
|
954
|
-
try {
|
|
955
|
-
const buf = fs4.readFileSync(this.keyFile);
|
|
956
|
-
if (buf.length !== KEY_BYTES) {
|
|
957
|
-
throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);
|
|
958
|
-
}
|
|
959
|
-
this.key = buf;
|
|
960
|
-
return this.key;
|
|
961
|
-
} catch (err) {
|
|
962
|
-
if (err.code !== "ENOENT") throw err;
|
|
963
|
-
}
|
|
964
|
-
fs4.mkdirSync(path3.dirname(this.keyFile), { recursive: true });
|
|
965
|
-
const key = randomBytes(KEY_BYTES);
|
|
966
|
-
try {
|
|
967
|
-
fs4.writeFileSync(this.keyFile, key, { mode: 384, flag: "wx" });
|
|
968
|
-
} catch (err) {
|
|
969
|
-
if (err.code !== "EEXIST") throw err;
|
|
970
|
-
const buf = fs4.readFileSync(this.keyFile);
|
|
971
|
-
if (buf.length !== KEY_BYTES) {
|
|
972
|
-
throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);
|
|
973
|
-
}
|
|
974
|
-
this.key = buf;
|
|
975
|
-
return this.key;
|
|
976
|
-
}
|
|
977
|
-
this.key = key;
|
|
978
|
-
return key;
|
|
979
|
-
}
|
|
980
|
-
};
|
|
1006
|
+
// src/security/config-secrets.ts
|
|
981
1007
|
function decryptConfigSecrets(cfg, vault) {
|
|
982
1008
|
return walk(cfg, vault, (v, key) => {
|
|
983
1009
|
try {
|
|
@@ -991,9 +1017,6 @@ function decryptConfigSecrets(cfg, vault) {
|
|
|
991
1017
|
}
|
|
992
1018
|
});
|
|
993
1019
|
}
|
|
994
|
-
function encryptConfigSecrets(cfg, vault) {
|
|
995
|
-
return walk(cfg, vault, (v) => vault.encrypt(v));
|
|
996
|
-
}
|
|
997
1020
|
function walk(node, vault, transform) {
|
|
998
1021
|
if (node === null || node === void 0) return node;
|
|
999
1022
|
if (typeof node !== "object") return node;
|
|
@@ -1019,77 +1042,56 @@ function isSecretField(name) {
|
|
|
1019
1042
|
if (NON_SECRET_OVERRIDES.has(lc)) return false;
|
|
1020
1043
|
return SECRET_KEY_PATTERN.test(lc);
|
|
1021
1044
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
} else if (typeof v === "object" && v !== null) {
|
|
1073
|
-
out[k] = walkCount(v, vault, counter);
|
|
1074
|
-
} else {
|
|
1075
|
-
out[k] = v;
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
return out;
|
|
1079
|
-
}
|
|
1080
|
-
var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1081
|
-
function deepMerge(a, b) {
|
|
1082
|
-
const out = { ...a };
|
|
1083
|
-
for (const [k, v] of Object.entries(b)) {
|
|
1084
|
-
if (FORBIDDEN_PROTO_KEYS.has(k)) continue;
|
|
1085
|
-
const existing = out[k];
|
|
1086
|
-
if (v !== null && typeof v === "object" && !Array.isArray(v) && existing !== null && typeof existing === "object" && !Array.isArray(existing)) {
|
|
1087
|
-
out[k] = deepMerge(existing, v);
|
|
1088
|
-
} else {
|
|
1089
|
-
out[k] = v;
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
return out;
|
|
1045
|
+
|
|
1046
|
+
// src/types/context-window.ts
|
|
1047
|
+
var DEFAULT_CONTEXT_WINDOW_MODE_ID = "balanced";
|
|
1048
|
+
var CONTEXT_WINDOW_MODES = Object.freeze([
|
|
1049
|
+
{
|
|
1050
|
+
id: "balanced",
|
|
1051
|
+
name: "Balanced",
|
|
1052
|
+
description: "Default rolling compaction: recent work stays verbatim, old tool output is trimmed.",
|
|
1053
|
+
thresholds: { warn: 0.6, soft: 0.75, hard: 0.9 },
|
|
1054
|
+
aggressiveOn: "soft",
|
|
1055
|
+
preserveK: 10,
|
|
1056
|
+
eliseThreshold: 2e3,
|
|
1057
|
+
targetLoad: 0.65
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
id: "frugal",
|
|
1061
|
+
name: "Frugal",
|
|
1062
|
+
description: "Token-saver mode: compacts early and keeps a tighter verbatim tail.",
|
|
1063
|
+
thresholds: { warn: 0.45, soft: 0.6, hard: 0.75 },
|
|
1064
|
+
aggressiveOn: "warn",
|
|
1065
|
+
preserveK: 6,
|
|
1066
|
+
eliseThreshold: 700,
|
|
1067
|
+
targetLoad: 0.5
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
id: "deep",
|
|
1071
|
+
name: "Deep",
|
|
1072
|
+
description: "Long-reasoning mode: delays compaction and keeps more recent turns intact.",
|
|
1073
|
+
thresholds: { warn: 0.72, soft: 0.86, hard: 0.96 },
|
|
1074
|
+
aggressiveOn: "hard",
|
|
1075
|
+
preserveK: 18,
|
|
1076
|
+
eliseThreshold: 5e3,
|
|
1077
|
+
targetLoad: 0.78
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
id: "archival",
|
|
1081
|
+
name: "Archival",
|
|
1082
|
+
description: "Decision-preserving mode: compacts steadily while keeping summaries prominent.",
|
|
1083
|
+
thresholds: { warn: 0.55, soft: 0.7, hard: 0.84 },
|
|
1084
|
+
aggressiveOn: "soft",
|
|
1085
|
+
preserveK: 8,
|
|
1086
|
+
eliseThreshold: 1200,
|
|
1087
|
+
targetLoad: 0.58
|
|
1088
|
+
}
|
|
1089
|
+
]);
|
|
1090
|
+
function listContextWindowModes() {
|
|
1091
|
+
return CONTEXT_WINDOW_MODES.map((m) => ({ ...m, thresholds: { ...m.thresholds } }));
|
|
1092
|
+
}
|
|
1093
|
+
function isContextWindowModeId(id) {
|
|
1094
|
+
return CONTEXT_WINDOW_MODES.some((m) => m.id === id);
|
|
1093
1095
|
}
|
|
1094
1096
|
|
|
1095
1097
|
// src/utils/safe-json.ts
|
|
@@ -1111,6 +1113,7 @@ function safeParse(input, maxBytes = 5e6) {
|
|
|
1111
1113
|
var BEHAVIOR_DEFAULTS = {
|
|
1112
1114
|
version: 1,
|
|
1113
1115
|
context: {
|
|
1116
|
+
mode: DEFAULT_CONTEXT_WINDOW_MODE_ID,
|
|
1114
1117
|
warnThreshold: 0.6,
|
|
1115
1118
|
softThreshold: 0.75,
|
|
1116
1119
|
hardThreshold: 0.9,
|
|
@@ -1156,13 +1159,13 @@ var ENV_MAP = {
|
|
|
1156
1159
|
function isPrimitiveArray(a) {
|
|
1157
1160
|
return a.every((v) => v === null || typeof v !== "object");
|
|
1158
1161
|
}
|
|
1159
|
-
var
|
|
1160
|
-
function
|
|
1162
|
+
var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1163
|
+
function deepMerge(base, patch) {
|
|
1161
1164
|
if (typeof base !== "object" || base === null) return patch ?? base;
|
|
1162
1165
|
if (typeof patch !== "object" || patch === null) return base;
|
|
1163
1166
|
const out = { ...base };
|
|
1164
1167
|
for (const [k, v] of Object.entries(patch)) {
|
|
1165
|
-
if (
|
|
1168
|
+
if (FORBIDDEN_PROTO_KEYS.has(k)) continue;
|
|
1166
1169
|
const existing = out[k];
|
|
1167
1170
|
if (Array.isArray(v)) {
|
|
1168
1171
|
if (Array.isArray(existing) && isPrimitiveArray(v) && isPrimitiveArray(existing)) {
|
|
@@ -1176,7 +1179,7 @@ function deepMerge2(base, patch) {
|
|
|
1176
1179
|
}
|
|
1177
1180
|
}
|
|
1178
1181
|
} else if (typeof v === "object" && v !== null && typeof existing === "object" && existing !== null) {
|
|
1179
|
-
out[k] =
|
|
1182
|
+
out[k] = deepMerge(existing, v);
|
|
1180
1183
|
} else if (v !== void 0) {
|
|
1181
1184
|
out[k] = v;
|
|
1182
1185
|
}
|
|
@@ -1200,8 +1203,8 @@ var DefaultConfigLoader = class {
|
|
|
1200
1203
|
this.readJson(this.paths.globalConfig),
|
|
1201
1204
|
this.readJson(this.paths.projectLocalConfig)
|
|
1202
1205
|
]);
|
|
1203
|
-
cfg =
|
|
1204
|
-
cfg =
|
|
1206
|
+
cfg = deepMerge(cfg, global);
|
|
1207
|
+
cfg = deepMerge(cfg, local);
|
|
1205
1208
|
for (const [key, fn] of Object.entries(ENV_MAP)) {
|
|
1206
1209
|
const v = process.env[key];
|
|
1207
1210
|
if (v) fn(cfg, v);
|
|
@@ -1215,14 +1218,14 @@ var DefaultConfigLoader = class {
|
|
|
1215
1218
|
try {
|
|
1216
1219
|
const patch = await src.read();
|
|
1217
1220
|
if (patch && Object.keys(patch).length > 0) {
|
|
1218
|
-
cfg =
|
|
1221
|
+
cfg = deepMerge(cfg, patch);
|
|
1219
1222
|
}
|
|
1220
1223
|
} catch (err) {
|
|
1221
1224
|
console.warn(`Config source "${src.name}" failed`, err);
|
|
1222
1225
|
}
|
|
1223
1226
|
}
|
|
1224
1227
|
if (opts.cliFlags) {
|
|
1225
|
-
cfg =
|
|
1228
|
+
cfg = deepMerge(cfg, opts.cliFlags);
|
|
1226
1229
|
}
|
|
1227
1230
|
if (this.vault) {
|
|
1228
1231
|
cfg = decryptConfigSecrets(cfg, this.vault);
|
|
@@ -1285,6 +1288,10 @@ var DefaultConfigLoader = class {
|
|
|
1285
1288
|
if (c.warnThreshold >= c.softThreshold || c.softThreshold >= c.hardThreshold) {
|
|
1286
1289
|
throw new Error("Config: context thresholds must satisfy warn < soft < hard");
|
|
1287
1290
|
}
|
|
1291
|
+
if (c.mode !== void 0 && !isContextWindowModeId(c.mode)) {
|
|
1292
|
+
const known = listContextWindowModes().map((m) => m.id).join(", ");
|
|
1293
|
+
throw new Error(`Config: context.mode must be one of: ${known}`);
|
|
1294
|
+
}
|
|
1288
1295
|
}
|
|
1289
1296
|
validateIdentity(cfg) {
|
|
1290
1297
|
if (!cfg.provider) {
|
|
@@ -1861,24 +1868,35 @@ async function saveTodosCheckpoint(filePath, sessionId, todos) {
|
|
|
1861
1868
|
function attachTodosCheckpoint(state, filePath, sessionId) {
|
|
1862
1869
|
let timer = null;
|
|
1863
1870
|
let pending = null;
|
|
1871
|
+
let writeChain = Promise.resolve();
|
|
1872
|
+
const enqueueWrite = (todos) => {
|
|
1873
|
+
writeChain = writeChain.then(() => saveTodosCheckpoint(filePath, sessionId, todos));
|
|
1874
|
+
return writeChain;
|
|
1875
|
+
};
|
|
1864
1876
|
const flush = () => {
|
|
1865
1877
|
timer = null;
|
|
1866
1878
|
if (pending) {
|
|
1867
|
-
|
|
1879
|
+
const todos = pending;
|
|
1868
1880
|
pending = null;
|
|
1881
|
+
return enqueueWrite(todos);
|
|
1869
1882
|
}
|
|
1883
|
+
return writeChain;
|
|
1870
1884
|
};
|
|
1871
1885
|
const unsubscribe = state.onChange((change) => {
|
|
1872
1886
|
if (change.kind !== "todos_replaced") return;
|
|
1873
1887
|
pending = change.todos;
|
|
1874
1888
|
if (timer) clearTimeout(timer);
|
|
1875
|
-
timer = setTimeout(
|
|
1889
|
+
timer = setTimeout(() => {
|
|
1890
|
+
void flush();
|
|
1891
|
+
}, 150);
|
|
1876
1892
|
});
|
|
1877
|
-
return () => {
|
|
1893
|
+
return async () => {
|
|
1878
1894
|
unsubscribe();
|
|
1879
1895
|
if (timer) {
|
|
1880
1896
|
clearTimeout(timer);
|
|
1881
|
-
flush();
|
|
1897
|
+
await flush();
|
|
1898
|
+
} else {
|
|
1899
|
+
await writeChain;
|
|
1882
1900
|
}
|
|
1883
1901
|
};
|
|
1884
1902
|
}
|
|
@@ -2134,56 +2152,244 @@ var PATTERNS = [
|
|
|
2134
2152
|
// Value-side word boundary + length gate to avoid matching short random strings
|
|
2135
2153
|
regex: /\b([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,})['"]?(?!\s*[A-Za-z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))/g
|
|
2136
2154
|
}
|
|
2137
|
-
];
|
|
2138
|
-
var SCRUB_CHUNK_BYTES = 64 * 1024;
|
|
2139
|
-
var DefaultSecretScrubber = class {
|
|
2140
|
-
scrub(text) {
|
|
2141
|
-
if (!text) return text;
|
|
2142
|
-
if (text.length <= SCRUB_CHUNK_BYTES) {
|
|
2143
|
-
return this.scrubOne(text);
|
|
2144
|
-
}
|
|
2145
|
-
const out = [];
|
|
2146
|
-
let i = 0;
|
|
2147
|
-
while (i < text.length) {
|
|
2148
|
-
let end = Math.min(i + SCRUB_CHUNK_BYTES, text.length);
|
|
2149
|
-
if (end < text.length) {
|
|
2150
|
-
const nl = text.lastIndexOf("\n", end);
|
|
2151
|
-
if (nl > i + SCRUB_CHUNK_BYTES / 2) end = nl + 1;
|
|
2152
|
-
}
|
|
2153
|
-
out.push(this.scrubOne(text.slice(i, end)));
|
|
2154
|
-
i = end;
|
|
2155
|
-
}
|
|
2156
|
-
return out.join("");
|
|
2155
|
+
];
|
|
2156
|
+
var SCRUB_CHUNK_BYTES = 64 * 1024;
|
|
2157
|
+
var DefaultSecretScrubber = class {
|
|
2158
|
+
scrub(text) {
|
|
2159
|
+
if (!text) return text;
|
|
2160
|
+
if (text.length <= SCRUB_CHUNK_BYTES) {
|
|
2161
|
+
return this.scrubOne(text);
|
|
2162
|
+
}
|
|
2163
|
+
const out = [];
|
|
2164
|
+
let i = 0;
|
|
2165
|
+
while (i < text.length) {
|
|
2166
|
+
let end = Math.min(i + SCRUB_CHUNK_BYTES, text.length);
|
|
2167
|
+
if (end < text.length) {
|
|
2168
|
+
const nl = text.lastIndexOf("\n", end);
|
|
2169
|
+
if (nl > i + SCRUB_CHUNK_BYTES / 2) end = nl + 1;
|
|
2170
|
+
}
|
|
2171
|
+
out.push(this.scrubOne(text.slice(i, end)));
|
|
2172
|
+
i = end;
|
|
2173
|
+
}
|
|
2174
|
+
return out.join("");
|
|
2175
|
+
}
|
|
2176
|
+
scrubOne(text) {
|
|
2177
|
+
let out = text;
|
|
2178
|
+
for (const p of PATTERNS) {
|
|
2179
|
+
out = out.replace(p.regex, (_match, group1, group2) => {
|
|
2180
|
+
if (p.type === "high_entropy_env" && group1 && group2) {
|
|
2181
|
+
return `${group1}=[REDACTED:${p.type}]`;
|
|
2182
|
+
}
|
|
2183
|
+
return `[REDACTED:${p.type}]`;
|
|
2184
|
+
});
|
|
2185
|
+
}
|
|
2186
|
+
return out;
|
|
2187
|
+
}
|
|
2188
|
+
scrubObject(obj) {
|
|
2189
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
2190
|
+
const visit = (v) => {
|
|
2191
|
+
if (typeof v === "string") return this.scrub(v);
|
|
2192
|
+
if (v === null || typeof v !== "object") return v;
|
|
2193
|
+
if (seen.has(v)) return v;
|
|
2194
|
+
seen.add(v);
|
|
2195
|
+
if (Array.isArray(v)) return v.map(visit);
|
|
2196
|
+
const out = {};
|
|
2197
|
+
for (const [k, val] of Object.entries(v)) {
|
|
2198
|
+
out[k] = visit(val);
|
|
2199
|
+
}
|
|
2200
|
+
return out;
|
|
2201
|
+
};
|
|
2202
|
+
return visit(obj);
|
|
2203
|
+
}
|
|
2204
|
+
};
|
|
2205
|
+
|
|
2206
|
+
// src/types/secret-vault.ts
|
|
2207
|
+
var ENCRYPTED_PREFIX = "enc:v1:";
|
|
2208
|
+
|
|
2209
|
+
// src/security/secret-vault.ts
|
|
2210
|
+
var KEY_BYTES = 32;
|
|
2211
|
+
var IV_BYTES = 12;
|
|
2212
|
+
var TAG_BYTES = 16;
|
|
2213
|
+
var ALGO = "aes-256-gcm";
|
|
2214
|
+
var DefaultSecretVault = class {
|
|
2215
|
+
keyFile;
|
|
2216
|
+
key;
|
|
2217
|
+
constructor(opts) {
|
|
2218
|
+
this.keyFile = opts.keyFile;
|
|
2219
|
+
}
|
|
2220
|
+
isEncrypted(value) {
|
|
2221
|
+
return typeof value === "string" && value.startsWith(ENCRYPTED_PREFIX);
|
|
2222
|
+
}
|
|
2223
|
+
encrypt(plaintext) {
|
|
2224
|
+
if (this.isEncrypted(plaintext)) return plaintext;
|
|
2225
|
+
const key = this.loadOrCreateKey();
|
|
2226
|
+
const iv = randomBytes(IV_BYTES);
|
|
2227
|
+
const cipher = createCipheriv(ALGO, key, iv);
|
|
2228
|
+
const ct = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
2229
|
+
const tag = cipher.getAuthTag();
|
|
2230
|
+
return `${ENCRYPTED_PREFIX}${iv.toString("base64")}:${tag.toString("base64")}:${ct.toString("base64")}`;
|
|
2231
|
+
}
|
|
2232
|
+
decrypt(value) {
|
|
2233
|
+
if (!this.isEncrypted(value)) return value;
|
|
2234
|
+
const rest = value.slice(ENCRYPTED_PREFIX.length);
|
|
2235
|
+
const parts = rest.split(":");
|
|
2236
|
+
if (parts.length !== 3) {
|
|
2237
|
+
throw new Error("SecretVault: malformed encrypted value");
|
|
2238
|
+
}
|
|
2239
|
+
const [ivB64, tagB64, ctB64] = parts;
|
|
2240
|
+
const iv = Buffer.from(ivB64, "base64");
|
|
2241
|
+
const tag = Buffer.from(tagB64, "base64");
|
|
2242
|
+
const ct = Buffer.from(ctB64, "base64");
|
|
2243
|
+
if (iv.length !== IV_BYTES) throw new Error("SecretVault: bad IV length");
|
|
2244
|
+
if (tag.length !== TAG_BYTES) throw new Error("SecretVault: bad tag length");
|
|
2245
|
+
const key = this.loadOrCreateKey();
|
|
2246
|
+
const decipher = createDecipheriv(ALGO, key, iv);
|
|
2247
|
+
decipher.setAuthTag(tag);
|
|
2248
|
+
const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
|
|
2249
|
+
return pt.toString("utf8");
|
|
2250
|
+
}
|
|
2251
|
+
loadOrCreateKey() {
|
|
2252
|
+
if (this.key) return this.key;
|
|
2253
|
+
try {
|
|
2254
|
+
const buf = fs5.readFileSync(this.keyFile);
|
|
2255
|
+
if (buf.length !== KEY_BYTES) {
|
|
2256
|
+
throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);
|
|
2257
|
+
}
|
|
2258
|
+
this.key = buf;
|
|
2259
|
+
return this.key;
|
|
2260
|
+
} catch (err) {
|
|
2261
|
+
if (err.code !== "ENOENT") throw err;
|
|
2262
|
+
}
|
|
2263
|
+
fs5.mkdirSync(path3.dirname(this.keyFile), { recursive: true });
|
|
2264
|
+
const key = randomBytes(KEY_BYTES);
|
|
2265
|
+
try {
|
|
2266
|
+
fs5.writeFileSync(this.keyFile, key, { mode: 384, flag: "wx" });
|
|
2267
|
+
} catch (err) {
|
|
2268
|
+
if (err.code !== "EEXIST") throw err;
|
|
2269
|
+
const buf = fs5.readFileSync(this.keyFile);
|
|
2270
|
+
if (buf.length !== KEY_BYTES) {
|
|
2271
|
+
throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);
|
|
2272
|
+
}
|
|
2273
|
+
this.key = buf;
|
|
2274
|
+
return this.key;
|
|
2275
|
+
}
|
|
2276
|
+
this.key = key;
|
|
2277
|
+
return key;
|
|
2278
|
+
}
|
|
2279
|
+
};
|
|
2280
|
+
function decryptConfigSecrets2(cfg, vault) {
|
|
2281
|
+
return walk2(cfg, vault, (v, key) => {
|
|
2282
|
+
try {
|
|
2283
|
+
return vault.decrypt(v);
|
|
2284
|
+
} catch (err) {
|
|
2285
|
+
console.warn(
|
|
2286
|
+
`[secret-vault] Failed to decrypt "${key}":`,
|
|
2287
|
+
err instanceof Error ? err.message : err
|
|
2288
|
+
);
|
|
2289
|
+
return "";
|
|
2290
|
+
}
|
|
2291
|
+
});
|
|
2292
|
+
}
|
|
2293
|
+
function encryptConfigSecrets(cfg, vault) {
|
|
2294
|
+
return walk2(cfg, vault, (v) => vault.encrypt(v));
|
|
2295
|
+
}
|
|
2296
|
+
function walk2(node, vault, transform) {
|
|
2297
|
+
if (node === null || node === void 0) return node;
|
|
2298
|
+
if (typeof node !== "object") return node;
|
|
2299
|
+
if (Array.isArray(node)) {
|
|
2300
|
+
return node.map((item) => walk2(item, vault, transform));
|
|
2301
|
+
}
|
|
2302
|
+
const out = {};
|
|
2303
|
+
for (const [k, v] of Object.entries(node)) {
|
|
2304
|
+
if (typeof v === "string" && isSecretField2(k)) {
|
|
2305
|
+
out[k] = transform(v, k);
|
|
2306
|
+
} else if (typeof v === "object" && v !== null) {
|
|
2307
|
+
out[k] = walk2(v, vault, transform);
|
|
2308
|
+
} else {
|
|
2309
|
+
out[k] = v;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
return out;
|
|
2313
|
+
}
|
|
2314
|
+
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;
|
|
2315
|
+
var NON_SECRET_OVERRIDES2 = /* @__PURE__ */ new Set(["publickey", "public_key"]);
|
|
2316
|
+
function isSecretField2(name) {
|
|
2317
|
+
const lc = name.toLowerCase();
|
|
2318
|
+
if (NON_SECRET_OVERRIDES2.has(lc)) return false;
|
|
2319
|
+
return SECRET_KEY_PATTERN2.test(lc);
|
|
2320
|
+
}
|
|
2321
|
+
async function rewriteConfigEncrypted(configPath, vault, patch) {
|
|
2322
|
+
let current = {};
|
|
2323
|
+
try {
|
|
2324
|
+
const raw = await fsp.readFile(configPath, "utf8");
|
|
2325
|
+
current = JSON.parse(raw);
|
|
2326
|
+
} catch {
|
|
2327
|
+
}
|
|
2328
|
+
const merged = deepMerge2(current, patch ?? {});
|
|
2329
|
+
const encrypted = encryptConfigSecrets(merged, vault);
|
|
2330
|
+
await fsp.mkdir(path3.dirname(configPath), { recursive: true });
|
|
2331
|
+
await fsp.writeFile(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
2332
|
+
try {
|
|
2333
|
+
await fsp.chmod(configPath, 384);
|
|
2334
|
+
} catch {
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
async function migratePlaintextSecrets(configPath, vault) {
|
|
2338
|
+
let raw;
|
|
2339
|
+
try {
|
|
2340
|
+
raw = await fsp.readFile(configPath, "utf8");
|
|
2341
|
+
} catch {
|
|
2342
|
+
return { migrated: 0, file: configPath };
|
|
2343
|
+
}
|
|
2344
|
+
let parsed;
|
|
2345
|
+
try {
|
|
2346
|
+
parsed = JSON.parse(raw);
|
|
2347
|
+
} catch {
|
|
2348
|
+
return { migrated: 0, file: configPath };
|
|
2349
|
+
}
|
|
2350
|
+
const counter = { n: 0 };
|
|
2351
|
+
const migrated = walkCount(parsed, vault, counter);
|
|
2352
|
+
if (counter.n === 0) return { migrated: 0, file: configPath };
|
|
2353
|
+
await fsp.writeFile(configPath, JSON.stringify(migrated, null, 2), { mode: 384 });
|
|
2354
|
+
try {
|
|
2355
|
+
await fsp.chmod(configPath, 384);
|
|
2356
|
+
} catch {
|
|
2157
2357
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2358
|
+
return { migrated: counter.n, file: configPath };
|
|
2359
|
+
}
|
|
2360
|
+
function walkCount(node, vault, counter) {
|
|
2361
|
+
if (node === null || node === void 0) return node;
|
|
2362
|
+
if (typeof node !== "object") return node;
|
|
2363
|
+
if (Array.isArray(node)) {
|
|
2364
|
+
return node.map((item) => walkCount(item, vault, counter));
|
|
2365
|
+
}
|
|
2366
|
+
const out = {};
|
|
2367
|
+
for (const [k, v] of Object.entries(node)) {
|
|
2368
|
+
if (typeof v === "string" && isSecretField2(k) && !vault.isEncrypted(v) && v.length > 0) {
|
|
2369
|
+
out[k] = vault.encrypt(v);
|
|
2370
|
+
counter.n++;
|
|
2371
|
+
} else if (typeof v === "object" && v !== null) {
|
|
2372
|
+
out[k] = walkCount(v, vault, counter);
|
|
2373
|
+
} else {
|
|
2374
|
+
out[k] = v;
|
|
2167
2375
|
}
|
|
2168
|
-
return out;
|
|
2169
2376
|
}
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
};
|
|
2184
|
-
return visit(obj);
|
|
2377
|
+
return out;
|
|
2378
|
+
}
|
|
2379
|
+
var FORBIDDEN_PROTO_KEYS2 = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
2380
|
+
function deepMerge2(a, b) {
|
|
2381
|
+
const out = { ...a };
|
|
2382
|
+
for (const [k, v] of Object.entries(b)) {
|
|
2383
|
+
if (FORBIDDEN_PROTO_KEYS2.has(k)) continue;
|
|
2384
|
+
const existing = out[k];
|
|
2385
|
+
if (v !== null && typeof v === "object" && !Array.isArray(v) && existing !== null && typeof existing === "object" && !Array.isArray(existing)) {
|
|
2386
|
+
out[k] = deepMerge2(existing, v);
|
|
2387
|
+
} else {
|
|
2388
|
+
out[k] = v;
|
|
2389
|
+
}
|
|
2185
2390
|
}
|
|
2186
|
-
|
|
2391
|
+
return out;
|
|
2392
|
+
}
|
|
2187
2393
|
|
|
2188
2394
|
// src/utils/glob-match.ts
|
|
2189
2395
|
function escapeRegex(s) {
|
|
@@ -3084,20 +3290,36 @@ var HybridCompactor = class {
|
|
|
3084
3290
|
async compact(ctx, opts = {}) {
|
|
3085
3291
|
const beforeTokens = this.estimateMessages(ctx.messages);
|
|
3086
3292
|
const reductions = [];
|
|
3087
|
-
const
|
|
3293
|
+
const policy = readContextWindowPolicy(ctx);
|
|
3294
|
+
const preserveK = policy?.preserveK ?? this.preserveK;
|
|
3295
|
+
const eliseThreshold = policy?.eliseThreshold ?? this.eliseThreshold;
|
|
3296
|
+
const phase1Saved = this.eliseOldToolResults(ctx, preserveK, eliseThreshold);
|
|
3088
3297
|
if (phase1Saved > 0) reductions.push({ phase: "elision", saved: phase1Saved });
|
|
3089
3298
|
if (opts.aggressive) {
|
|
3090
|
-
const phase2Saved = this.collapseAncientTurns(ctx);
|
|
3299
|
+
const phase2Saved = this.collapseAncientTurns(ctx, preserveK);
|
|
3091
3300
|
if (phase2Saved > 0) reductions.push({ phase: "summary", saved: phase2Saved });
|
|
3092
3301
|
}
|
|
3302
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
3303
|
+
if (repaired.report.changed) {
|
|
3304
|
+
ctx.state.replaceMessages(repaired.messages);
|
|
3305
|
+
}
|
|
3093
3306
|
const afterTokens = this.estimateMessages(ctx.messages);
|
|
3094
|
-
return {
|
|
3307
|
+
return {
|
|
3308
|
+
before: beforeTokens,
|
|
3309
|
+
after: afterTokens,
|
|
3310
|
+
reductions,
|
|
3311
|
+
repaired: repaired.report.changed ? {
|
|
3312
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
3313
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
3314
|
+
removedMessages: repaired.report.removedMessages
|
|
3315
|
+
} : void 0
|
|
3316
|
+
};
|
|
3095
3317
|
}
|
|
3096
|
-
eliseOldToolResults(ctx) {
|
|
3318
|
+
eliseOldToolResults(ctx, preserveK = this.preserveK, eliseThreshold = this.eliseThreshold) {
|
|
3097
3319
|
const messages = ctx.messages;
|
|
3098
3320
|
let pairCount = 0;
|
|
3099
3321
|
let preserveStart = messages.length;
|
|
3100
|
-
for (let i = messages.length - 1; i >= 0 && pairCount <
|
|
3322
|
+
for (let i = messages.length - 1; i >= 0 && pairCount < preserveK; i--) {
|
|
3101
3323
|
const m = messages[i];
|
|
3102
3324
|
if (!m) continue;
|
|
3103
3325
|
if (m.role === "user" || m.role === "assistant") {
|
|
@@ -3121,7 +3343,7 @@ var HybridCompactor = class {
|
|
|
3121
3343
|
const newContent = msg.content.map((b) => {
|
|
3122
3344
|
if (b.type !== "tool_result") return b;
|
|
3123
3345
|
const tokens = estimateToolResultTokens(b.content);
|
|
3124
|
-
if (tokens <
|
|
3346
|
+
if (tokens < eliseThreshold) return b;
|
|
3125
3347
|
saved += tokens;
|
|
3126
3348
|
const elided = {
|
|
3127
3349
|
type: "tool_result",
|
|
@@ -3141,9 +3363,9 @@ var HybridCompactor = class {
|
|
|
3141
3363
|
if (changed) ctx.state.replaceMessages(nextMessages);
|
|
3142
3364
|
return saved;
|
|
3143
3365
|
}
|
|
3144
|
-
collapseAncientTurns(ctx) {
|
|
3366
|
+
collapseAncientTurns(ctx, preserveK = this.preserveK) {
|
|
3145
3367
|
const messages = ctx.messages;
|
|
3146
|
-
const cutTarget = Math.max(0, messages.length -
|
|
3368
|
+
const cutTarget = Math.max(0, messages.length - preserveK * 2);
|
|
3147
3369
|
if (cutTarget <= 0) return 0;
|
|
3148
3370
|
let boundary = -1;
|
|
3149
3371
|
for (let i = cutTarget; i < messages.length; i++) {
|
|
@@ -3184,6 +3406,15 @@ var HybridCompactor = class {
|
|
|
3184
3406
|
return total;
|
|
3185
3407
|
}
|
|
3186
3408
|
};
|
|
3409
|
+
function readContextWindowPolicy(ctx) {
|
|
3410
|
+
const policy = ctx.meta?.["contextWindowPolicy"];
|
|
3411
|
+
if (!policy || typeof policy !== "object") return null;
|
|
3412
|
+
const candidate = policy;
|
|
3413
|
+
if (typeof candidate.preserveK !== "number" || typeof candidate.eliseThreshold !== "number") {
|
|
3414
|
+
return null;
|
|
3415
|
+
}
|
|
3416
|
+
return candidate;
|
|
3417
|
+
}
|
|
3187
3418
|
function hasTextContent(m) {
|
|
3188
3419
|
if (typeof m.content === "string") return m.content.trim().length > 0;
|
|
3189
3420
|
return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
|
|
@@ -3230,8 +3461,19 @@ var IntelligentCompactor = class {
|
|
|
3230
3461
|
const saved2 = this.lightweightCompact(ctx);
|
|
3231
3462
|
if (saved2 > 0) reductions.push({ phase: "elision", saved: saved2 });
|
|
3232
3463
|
}
|
|
3464
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
3465
|
+
if (repaired.report.changed) ctx.state.replaceMessages(repaired.messages);
|
|
3233
3466
|
const afterTokens = this.estimateTokens(ctx.messages);
|
|
3234
|
-
return {
|
|
3467
|
+
return {
|
|
3468
|
+
before: beforeTokens,
|
|
3469
|
+
after: afterTokens,
|
|
3470
|
+
reductions,
|
|
3471
|
+
repaired: repaired.report.changed ? {
|
|
3472
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
3473
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
3474
|
+
removedMessages: repaired.report.removedMessages
|
|
3475
|
+
} : void 0
|
|
3476
|
+
};
|
|
3235
3477
|
}
|
|
3236
3478
|
async summarizeAncientTurns(ctx) {
|
|
3237
3479
|
const messages = ctx.messages;
|
|
@@ -3271,8 +3513,8 @@ var IntelligentCompactor = class {
|
|
|
3271
3513
|
const m = messages[i];
|
|
3272
3514
|
if (!m) continue;
|
|
3273
3515
|
if (m.role === "assistant") {
|
|
3274
|
-
const
|
|
3275
|
-
if (!
|
|
3516
|
+
const hasToolUse2 = Array.isArray(m.content) ? m.content.some((b) => b.type === "tool_use") : false;
|
|
3517
|
+
if (!hasToolUse2) {
|
|
3276
3518
|
return i + 1;
|
|
3277
3519
|
}
|
|
3278
3520
|
} else if (m.role !== "user") ; else {
|
|
@@ -3578,8 +3820,9 @@ var SelectiveCompactor = class {
|
|
|
3578
3820
|
if (!shouldCompact) {
|
|
3579
3821
|
const saved = this.eliseOldToolResults(ctx);
|
|
3580
3822
|
if (saved > 0) reductions.push({ phase: "elision", saved });
|
|
3823
|
+
const repair2 = this.repairProtocolAdjacency(ctx);
|
|
3581
3824
|
const afterTokens2 = this.estimateTokens(ctx.messages);
|
|
3582
|
-
return { before: beforeTokens, after: afterTokens2, reductions };
|
|
3825
|
+
return { before: beforeTokens, after: afterTokens2, reductions, repaired: repair2 };
|
|
3583
3826
|
}
|
|
3584
3827
|
const savedElision = this.eliseOldToolResults(ctx);
|
|
3585
3828
|
if (savedElision > 0) reductions.push({ phase: "elision", saved: savedElision });
|
|
@@ -3589,8 +3832,18 @@ var SelectiveCompactor = class {
|
|
|
3589
3832
|
const savedSelective = await this.runSelector(ctx, targetBudget);
|
|
3590
3833
|
if (savedSelective > 0) reductions.push({ phase: "selective", saved: savedSelective });
|
|
3591
3834
|
}
|
|
3835
|
+
const repair = this.repairProtocolAdjacency(ctx);
|
|
3592
3836
|
const afterTokens = this.estimateTokens(ctx.messages);
|
|
3593
|
-
return { before: beforeTokens, after: afterTokens, reductions };
|
|
3837
|
+
return { before: beforeTokens, after: afterTokens, reductions, repaired: repair };
|
|
3838
|
+
}
|
|
3839
|
+
repairProtocolAdjacency(ctx) {
|
|
3840
|
+
const repaired = repairToolUseAdjacency(ctx.messages);
|
|
3841
|
+
if (repaired.report.changed) ctx.state.replaceMessages(repaired.messages);
|
|
3842
|
+
return repaired.report.changed ? {
|
|
3843
|
+
removedToolUses: repaired.report.removedToolUses,
|
|
3844
|
+
removedToolResults: repaired.report.removedToolResults,
|
|
3845
|
+
removedMessages: repaired.report.removedMessages
|
|
3846
|
+
} : void 0;
|
|
3594
3847
|
}
|
|
3595
3848
|
/**
|
|
3596
3849
|
* Run the LLM selector to decide what to keep vs collapse.
|
|
@@ -3778,6 +4031,7 @@ var AutoCompactionMiddleware = class {
|
|
|
3778
4031
|
aggressiveOn;
|
|
3779
4032
|
events;
|
|
3780
4033
|
failureMode;
|
|
4034
|
+
policyProvider;
|
|
3781
4035
|
/**
|
|
3782
4036
|
* @param compactor Compactor to use for compaction.
|
|
3783
4037
|
* @param maxContext Provider's max context window in tokens.
|
|
@@ -3800,17 +4054,25 @@ var AutoCompactionMiddleware = class {
|
|
|
3800
4054
|
this.aggressiveOn = opts.aggressiveOn ?? "soft";
|
|
3801
4055
|
this.events = opts.events;
|
|
3802
4056
|
this.failureMode = opts.failureMode ?? "throw_on_hard";
|
|
4057
|
+
this.policyProvider = opts.policyProvider;
|
|
3803
4058
|
}
|
|
3804
4059
|
handler() {
|
|
3805
4060
|
return async (ctx, next) => {
|
|
3806
4061
|
const tokens = this.estimator(ctx);
|
|
3807
4062
|
const load = tokens / this.maxContext;
|
|
3808
|
-
|
|
4063
|
+
const policy = this.policyProvider?.(ctx);
|
|
4064
|
+
const thresholds = policy?.thresholds ?? {
|
|
4065
|
+
warn: this.warnThreshold,
|
|
4066
|
+
soft: this.softThreshold,
|
|
4067
|
+
hard: this.hardThreshold
|
|
4068
|
+
};
|
|
4069
|
+
const aggressiveOn = policy?.aggressiveOn ?? this.aggressiveOn;
|
|
4070
|
+
if (load >= thresholds.hard) {
|
|
3809
4071
|
await this.compact(ctx, true, { level: "hard", tokens, load });
|
|
3810
|
-
} else if (load >=
|
|
3811
|
-
await this.compact(ctx,
|
|
3812
|
-
} else if (load >=
|
|
3813
|
-
await this.compact(ctx,
|
|
4072
|
+
} else if (load >= thresholds.soft) {
|
|
4073
|
+
await this.compact(ctx, aggressiveOn !== "hard", { level: "soft", tokens, load });
|
|
4074
|
+
} else if (load >= thresholds.warn) {
|
|
4075
|
+
await this.compact(ctx, aggressiveOn === "warn", { level: "warn", tokens, load });
|
|
3814
4076
|
}
|
|
3815
4077
|
return next(ctx);
|
|
3816
4078
|
};
|
|
@@ -4413,6 +4675,7 @@ var InMemoryAgentBridge = class {
|
|
|
4413
4675
|
this.stopped = true;
|
|
4414
4676
|
for (const [, p] of this.pendingRequests) {
|
|
4415
4677
|
clearTimeout(p.timer);
|
|
4678
|
+
p.reject(new Error("Bridge stopped"));
|
|
4416
4679
|
}
|
|
4417
4680
|
this.pendingRequests.clear();
|
|
4418
4681
|
this.inflightGuards.clear();
|
|
@@ -5186,41 +5449,214 @@ function classifySubagentError(err, hints = {}) {
|
|
|
5186
5449
|
return { kind: "context_overflow", message: baseMessage, retryable: false, cause };
|
|
5187
5450
|
}
|
|
5188
5451
|
return {
|
|
5189
|
-
kind: "unknown",
|
|
5190
|
-
message: baseMessage,
|
|
5191
|
-
retryable: false,
|
|
5192
|
-
cause
|
|
5452
|
+
kind: "unknown",
|
|
5453
|
+
message: baseMessage,
|
|
5454
|
+
retryable: false,
|
|
5455
|
+
cause
|
|
5456
|
+
};
|
|
5457
|
+
}
|
|
5458
|
+
function providerErrorToSubagentError(err, message, cause) {
|
|
5459
|
+
const status = err.status;
|
|
5460
|
+
if (status === 429 || err.body?.type === "rate_limit_error") {
|
|
5461
|
+
return {
|
|
5462
|
+
kind: "provider_rate_limit",
|
|
5463
|
+
message,
|
|
5464
|
+
retryable: true,
|
|
5465
|
+
// Conservative default: 5s. Provider-specific code can override
|
|
5466
|
+
// by emitting an error whose body carries an explicit hint.
|
|
5467
|
+
backoffMs: 5e3,
|
|
5468
|
+
cause
|
|
5469
|
+
};
|
|
5470
|
+
}
|
|
5471
|
+
if (status === 401 || status === 403 || err.body?.type === "authentication_error") {
|
|
5472
|
+
return { kind: "provider_auth", message, retryable: false, cause };
|
|
5473
|
+
}
|
|
5474
|
+
if (status === 408 || status === 0) {
|
|
5475
|
+
return { kind: "provider_timeout", message, retryable: true, cause };
|
|
5476
|
+
}
|
|
5477
|
+
if (status >= 500 && status < 600) {
|
|
5478
|
+
return {
|
|
5479
|
+
kind: "provider_5xx",
|
|
5480
|
+
message,
|
|
5481
|
+
retryable: true,
|
|
5482
|
+
backoffMs: 3e3,
|
|
5483
|
+
cause
|
|
5484
|
+
};
|
|
5485
|
+
}
|
|
5486
|
+
return { kind: "unknown", message, retryable: err.retryable, cause };
|
|
5487
|
+
}
|
|
5488
|
+
function makeSpawnTool(director, roster) {
|
|
5489
|
+
const inputSchema = {
|
|
5490
|
+
type: "object",
|
|
5491
|
+
properties: {
|
|
5492
|
+
role: { type: "string", description: "Roster role id (preferred). When set, the spawn uses the matching config from the roster and ignores other fields." },
|
|
5493
|
+
name: { type: "string", description: "Display name for the subagent. Required when not using roster." },
|
|
5494
|
+
provider: { type: "string", description: 'Provider id (e.g. "anthropic", "openai"). Defaults to the leader provider when omitted.' },
|
|
5495
|
+
model: { type: "string", description: "Model id within the provider. Defaults to the leader model when omitted." },
|
|
5496
|
+
systemPromptOverride: { type: "string", description: "Extra prompt text appended after the role-base prompt." },
|
|
5497
|
+
maxIterations: { type: "number" },
|
|
5498
|
+
maxToolCalls: { type: "number" },
|
|
5499
|
+
maxCostUsd: { type: "number" }
|
|
5500
|
+
},
|
|
5501
|
+
required: []
|
|
5502
|
+
};
|
|
5503
|
+
return {
|
|
5504
|
+
name: "spawn_subagent",
|
|
5505
|
+
description: "Create a new subagent under this director. Returns the subagent id.",
|
|
5506
|
+
usageHint: "Either pass `role` (matches the roster) OR pass `name` + optional `provider`/`model`. Returns `{ subagentId }`.",
|
|
5507
|
+
permission: "auto",
|
|
5508
|
+
mutating: false,
|
|
5509
|
+
inputSchema,
|
|
5510
|
+
async execute(input) {
|
|
5511
|
+
const i = input ?? {};
|
|
5512
|
+
const role = typeof i.role === "string" ? i.role : void 0;
|
|
5513
|
+
const base = role && roster ? roster[role] : void 0;
|
|
5514
|
+
if (role && !base) {
|
|
5515
|
+
return { error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}` };
|
|
5516
|
+
}
|
|
5517
|
+
const cfg = { ...base ?? { name: i.name ?? "subagent" } };
|
|
5518
|
+
if (typeof i.name === "string") cfg.name = i.name;
|
|
5519
|
+
if (typeof i.provider === "string") cfg.provider = i.provider;
|
|
5520
|
+
if (typeof i.model === "string") cfg.model = i.model;
|
|
5521
|
+
if (typeof i.systemPromptOverride === "string") cfg.systemPromptOverride = i.systemPromptOverride;
|
|
5522
|
+
if (typeof i.maxIterations === "number") cfg.maxIterations = i.maxIterations;
|
|
5523
|
+
if (typeof i.maxToolCalls === "number") cfg.maxToolCalls = i.maxToolCalls;
|
|
5524
|
+
if (typeof i.maxCostUsd === "number") cfg.maxCostUsd = i.maxCostUsd;
|
|
5525
|
+
try {
|
|
5526
|
+
const subagentId = await director.spawn(cfg);
|
|
5527
|
+
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name };
|
|
5528
|
+
} catch (err) {
|
|
5529
|
+
if (err instanceof DirectorBudgetError) {
|
|
5530
|
+
return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
|
|
5531
|
+
}
|
|
5532
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
5533
|
+
}
|
|
5534
|
+
}
|
|
5535
|
+
};
|
|
5536
|
+
}
|
|
5537
|
+
function makeAssignTool(director) {
|
|
5538
|
+
const inputSchema = {
|
|
5539
|
+
type: "object",
|
|
5540
|
+
properties: {
|
|
5541
|
+
subagentId: { type: "string", description: "Target subagent id. Required." },
|
|
5542
|
+
description: { type: "string", description: "The task in natural language \u2014 what you want this subagent to do." },
|
|
5543
|
+
maxToolCalls: { type: "number", description: "Optional per-task tool-call budget override." },
|
|
5544
|
+
timeoutMs: { type: "number", description: "Optional per-task timeout in ms." }
|
|
5545
|
+
},
|
|
5546
|
+
required: ["subagentId", "description"]
|
|
5547
|
+
};
|
|
5548
|
+
return {
|
|
5549
|
+
name: "assign_task",
|
|
5550
|
+
description: "Hand a task to a previously spawned subagent. Returns the task id.",
|
|
5551
|
+
permission: "auto",
|
|
5552
|
+
mutating: false,
|
|
5553
|
+
inputSchema,
|
|
5554
|
+
async execute(input) {
|
|
5555
|
+
const i = input;
|
|
5556
|
+
const task = { id: randomUUID(), description: i.description, subagentId: i.subagentId, maxToolCalls: i.maxToolCalls, timeoutMs: i.timeoutMs };
|
|
5557
|
+
const taskId = await director.assign(task);
|
|
5558
|
+
return { taskId, subagentId: i.subagentId };
|
|
5559
|
+
}
|
|
5560
|
+
};
|
|
5561
|
+
}
|
|
5562
|
+
function makeAwaitTasksTool(director) {
|
|
5563
|
+
return {
|
|
5564
|
+
name: "await_tasks",
|
|
5565
|
+
description: "Block until every named task completes. Returns the array of TaskResult.",
|
|
5566
|
+
permission: "auto",
|
|
5567
|
+
mutating: false,
|
|
5568
|
+
inputSchema: { type: "object", properties: { taskIds: { type: "array", items: { type: "string" }, description: "One or more task ids returned by `assign_task`." } }, required: ["taskIds"] },
|
|
5569
|
+
async execute(input) {
|
|
5570
|
+
const i = input;
|
|
5571
|
+
const results = await director.awaitTasks(i.taskIds);
|
|
5572
|
+
return { results };
|
|
5573
|
+
}
|
|
5574
|
+
};
|
|
5575
|
+
}
|
|
5576
|
+
function makeAskTool(director) {
|
|
5577
|
+
return {
|
|
5578
|
+
name: "ask_subagent",
|
|
5579
|
+
description: "Synchronously ask a subagent a question. Blocks until the subagent replies via the bridge.",
|
|
5580
|
+
permission: "auto",
|
|
5581
|
+
mutating: false,
|
|
5582
|
+
inputSchema: {
|
|
5583
|
+
type: "object",
|
|
5584
|
+
properties: {
|
|
5585
|
+
subagentId: { type: "string", description: "Subagent to ask. Must be a previously spawned id." },
|
|
5586
|
+
question: { type: "string", description: "The question or instruction." },
|
|
5587
|
+
timeoutMs: { type: "number", description: "Optional timeout in ms (default 30s)." }
|
|
5588
|
+
},
|
|
5589
|
+
required: ["subagentId", "question"]
|
|
5590
|
+
},
|
|
5591
|
+
async execute(input) {
|
|
5592
|
+
const i = input;
|
|
5593
|
+
try {
|
|
5594
|
+
const answer = await director.ask(i.subagentId, { question: i.question }, i.timeoutMs);
|
|
5595
|
+
return { ok: true, answer };
|
|
5596
|
+
} catch (err) {
|
|
5597
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5600
|
+
};
|
|
5601
|
+
}
|
|
5602
|
+
function makeRollUpTool(director) {
|
|
5603
|
+
return {
|
|
5604
|
+
name: "roll_up",
|
|
5605
|
+
description: "Aggregate completed task results into a single formatted summary.",
|
|
5606
|
+
permission: "auto",
|
|
5607
|
+
mutating: false,
|
|
5608
|
+
inputSchema: {
|
|
5609
|
+
type: "object",
|
|
5610
|
+
properties: {
|
|
5611
|
+
taskIds: { type: "array", items: { type: "string" }, description: "Completed task ids to aggregate." },
|
|
5612
|
+
style: { type: "string", enum: ["markdown", "json"], description: "Output flavor \u2014 markdown (default) or json." }
|
|
5613
|
+
},
|
|
5614
|
+
required: ["taskIds"]
|
|
5615
|
+
},
|
|
5616
|
+
async execute(input) {
|
|
5617
|
+
const i = input;
|
|
5618
|
+
const summary = director.rollUp(i.taskIds, i.style ?? "markdown");
|
|
5619
|
+
return { summary, count: i.taskIds.length };
|
|
5620
|
+
}
|
|
5621
|
+
};
|
|
5622
|
+
}
|
|
5623
|
+
function makeTerminateTool(director) {
|
|
5624
|
+
return {
|
|
5625
|
+
name: "terminate_subagent",
|
|
5626
|
+
description: "Forcibly abort a subagent.",
|
|
5627
|
+
permission: "auto",
|
|
5628
|
+
mutating: true,
|
|
5629
|
+
inputSchema: { type: "object", properties: { subagentId: { type: "string", description: "Subagent to abort." } }, required: ["subagentId"] },
|
|
5630
|
+
async execute(input) {
|
|
5631
|
+
const i = input;
|
|
5632
|
+
await director.terminate(i.subagentId);
|
|
5633
|
+
return { ok: true };
|
|
5634
|
+
}
|
|
5635
|
+
};
|
|
5636
|
+
}
|
|
5637
|
+
function makeFleetStatusTool(director) {
|
|
5638
|
+
return {
|
|
5639
|
+
name: "fleet_status",
|
|
5640
|
+
description: "Snapshot of the fleet \u2014 every subagent's current status, pending vs. completed task counts.",
|
|
5641
|
+
permission: "auto",
|
|
5642
|
+
mutating: false,
|
|
5643
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
5644
|
+
async execute() {
|
|
5645
|
+
return director.status();
|
|
5646
|
+
}
|
|
5193
5647
|
};
|
|
5194
5648
|
}
|
|
5195
|
-
function
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
};
|
|
5207
|
-
}
|
|
5208
|
-
if (status === 401 || status === 403 || err.body?.type === "authentication_error") {
|
|
5209
|
-
return { kind: "provider_auth", message, retryable: false, cause };
|
|
5210
|
-
}
|
|
5211
|
-
if (status === 408 || status === 0) {
|
|
5212
|
-
return { kind: "provider_timeout", message, retryable: true, cause };
|
|
5213
|
-
}
|
|
5214
|
-
if (status >= 500 && status < 600) {
|
|
5215
|
-
return {
|
|
5216
|
-
kind: "provider_5xx",
|
|
5217
|
-
message,
|
|
5218
|
-
retryable: true,
|
|
5219
|
-
backoffMs: 3e3,
|
|
5220
|
-
cause
|
|
5221
|
-
};
|
|
5222
|
-
}
|
|
5223
|
-
return { kind: "unknown", message, retryable: err.retryable, cause };
|
|
5649
|
+
function makeFleetUsageTool(director) {
|
|
5650
|
+
return {
|
|
5651
|
+
name: "fleet_usage",
|
|
5652
|
+
description: "Token + cost breakdown across the fleet, per-subagent and totals.",
|
|
5653
|
+
permission: "auto",
|
|
5654
|
+
mutating: false,
|
|
5655
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
5656
|
+
async execute() {
|
|
5657
|
+
return director.snapshot();
|
|
5658
|
+
}
|
|
5659
|
+
};
|
|
5224
5660
|
}
|
|
5225
5661
|
|
|
5226
5662
|
// src/coordination/director.ts
|
|
@@ -5780,242 +6216,6 @@ var Director = class {
|
|
|
5780
6216
|
return t;
|
|
5781
6217
|
}
|
|
5782
6218
|
};
|
|
5783
|
-
function makeSpawnTool(director, roster) {
|
|
5784
|
-
const inputSchema = {
|
|
5785
|
-
type: "object",
|
|
5786
|
-
properties: {
|
|
5787
|
-
role: {
|
|
5788
|
-
type: "string",
|
|
5789
|
-
description: "Roster role id (preferred). When set, the spawn uses the matching config from the roster and ignores other fields."
|
|
5790
|
-
},
|
|
5791
|
-
name: {
|
|
5792
|
-
type: "string",
|
|
5793
|
-
description: "Display name for the subagent. Required when not using roster."
|
|
5794
|
-
},
|
|
5795
|
-
provider: {
|
|
5796
|
-
type: "string",
|
|
5797
|
-
description: 'Provider id (e.g. "anthropic", "openai"). Defaults to the leader provider when omitted.'
|
|
5798
|
-
},
|
|
5799
|
-
model: {
|
|
5800
|
-
type: "string",
|
|
5801
|
-
description: "Model id within the provider. Defaults to the leader model when omitted."
|
|
5802
|
-
},
|
|
5803
|
-
systemPromptOverride: {
|
|
5804
|
-
type: "string",
|
|
5805
|
-
description: "Extra prompt text appended after the role-base prompt."
|
|
5806
|
-
},
|
|
5807
|
-
maxIterations: { type: "number" },
|
|
5808
|
-
maxToolCalls: { type: "number" },
|
|
5809
|
-
maxCostUsd: { type: "number" }
|
|
5810
|
-
},
|
|
5811
|
-
required: []
|
|
5812
|
-
};
|
|
5813
|
-
return {
|
|
5814
|
-
name: "spawn_subagent",
|
|
5815
|
-
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.",
|
|
5816
|
-
usageHint: "Either pass `role` (matches the roster) OR pass `name` + optional `provider`/`model`. Returns `{ subagentId }`.",
|
|
5817
|
-
permission: "auto",
|
|
5818
|
-
mutating: false,
|
|
5819
|
-
inputSchema,
|
|
5820
|
-
async execute(input) {
|
|
5821
|
-
const i = input ?? {};
|
|
5822
|
-
const role = typeof i.role === "string" ? i.role : void 0;
|
|
5823
|
-
const base = role && roster ? roster[role] : void 0;
|
|
5824
|
-
if (role && !base) {
|
|
5825
|
-
return {
|
|
5826
|
-
error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}`
|
|
5827
|
-
};
|
|
5828
|
-
}
|
|
5829
|
-
const cfg = {
|
|
5830
|
-
...base ?? { name: i.name ?? "subagent" }
|
|
5831
|
-
};
|
|
5832
|
-
if (typeof i.name === "string") cfg.name = i.name;
|
|
5833
|
-
if (typeof i.provider === "string") cfg.provider = i.provider;
|
|
5834
|
-
if (typeof i.model === "string") cfg.model = i.model;
|
|
5835
|
-
if (typeof i.systemPromptOverride === "string")
|
|
5836
|
-
cfg.systemPromptOverride = i.systemPromptOverride;
|
|
5837
|
-
if (typeof i.maxIterations === "number") cfg.maxIterations = i.maxIterations;
|
|
5838
|
-
if (typeof i.maxToolCalls === "number") cfg.maxToolCalls = i.maxToolCalls;
|
|
5839
|
-
if (typeof i.maxCostUsd === "number") cfg.maxCostUsd = i.maxCostUsd;
|
|
5840
|
-
try {
|
|
5841
|
-
const subagentId = await director.spawn(cfg);
|
|
5842
|
-
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name };
|
|
5843
|
-
} catch (err) {
|
|
5844
|
-
if (err instanceof DirectorBudgetError) {
|
|
5845
|
-
return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
|
|
5846
|
-
}
|
|
5847
|
-
return { error: err instanceof Error ? err.message : String(err) };
|
|
5848
|
-
}
|
|
5849
|
-
}
|
|
5850
|
-
};
|
|
5851
|
-
}
|
|
5852
|
-
function makeAssignTool(director) {
|
|
5853
|
-
const inputSchema = {
|
|
5854
|
-
type: "object",
|
|
5855
|
-
properties: {
|
|
5856
|
-
subagentId: { type: "string", description: "Target subagent id. Required." },
|
|
5857
|
-
description: {
|
|
5858
|
-
type: "string",
|
|
5859
|
-
description: "The task in natural language \u2014 what you want this subagent to do."
|
|
5860
|
-
},
|
|
5861
|
-
maxToolCalls: { type: "number", description: "Optional per-task tool-call budget override." },
|
|
5862
|
-
timeoutMs: { type: "number", description: "Optional per-task timeout in ms." }
|
|
5863
|
-
},
|
|
5864
|
-
required: ["subagentId", "description"]
|
|
5865
|
-
};
|
|
5866
|
-
return {
|
|
5867
|
-
name: "assign_task",
|
|
5868
|
-
description: "Hand a task to a previously spawned subagent. Returns the task id \u2014 pass it to `await_tasks` to block on completion.",
|
|
5869
|
-
permission: "auto",
|
|
5870
|
-
mutating: false,
|
|
5871
|
-
inputSchema,
|
|
5872
|
-
async execute(input) {
|
|
5873
|
-
const i = input;
|
|
5874
|
-
const task = {
|
|
5875
|
-
id: randomUUID(),
|
|
5876
|
-
description: i.description,
|
|
5877
|
-
subagentId: i.subagentId,
|
|
5878
|
-
maxToolCalls: i.maxToolCalls,
|
|
5879
|
-
timeoutMs: i.timeoutMs
|
|
5880
|
-
};
|
|
5881
|
-
const taskId = await director.assign(task);
|
|
5882
|
-
return { taskId, subagentId: i.subagentId };
|
|
5883
|
-
}
|
|
5884
|
-
};
|
|
5885
|
-
}
|
|
5886
|
-
function makeAwaitTasksTool(director) {
|
|
5887
|
-
const inputSchema = {
|
|
5888
|
-
type: "object",
|
|
5889
|
-
properties: {
|
|
5890
|
-
taskIds: {
|
|
5891
|
-
type: "array",
|
|
5892
|
-
items: { type: "string" },
|
|
5893
|
-
description: "One or more task ids returned by `assign_task`. The call blocks until every id resolves."
|
|
5894
|
-
}
|
|
5895
|
-
},
|
|
5896
|
-
required: ["taskIds"]
|
|
5897
|
-
};
|
|
5898
|
-
return {
|
|
5899
|
-
name: "await_tasks",
|
|
5900
|
-
description: "Block until every named task completes. Returns the array of TaskResult \u2014 use this to gather subagent output before deciding the next step.",
|
|
5901
|
-
permission: "auto",
|
|
5902
|
-
mutating: false,
|
|
5903
|
-
inputSchema,
|
|
5904
|
-
async execute(input) {
|
|
5905
|
-
const i = input;
|
|
5906
|
-
const results = await director.awaitTasks(i.taskIds);
|
|
5907
|
-
return { results };
|
|
5908
|
-
}
|
|
5909
|
-
};
|
|
5910
|
-
}
|
|
5911
|
-
function makeAskTool(director) {
|
|
5912
|
-
const inputSchema = {
|
|
5913
|
-
type: "object",
|
|
5914
|
-
properties: {
|
|
5915
|
-
subagentId: {
|
|
5916
|
-
type: "string",
|
|
5917
|
-
description: "Subagent to ask. Must be a previously spawned id."
|
|
5918
|
-
},
|
|
5919
|
-
question: {
|
|
5920
|
-
type: "string",
|
|
5921
|
-
description: "The question or instruction. Sent as the bridge message payload."
|
|
5922
|
-
},
|
|
5923
|
-
timeoutMs: { type: "number", description: "Optional timeout in ms (default 30s)." }
|
|
5924
|
-
},
|
|
5925
|
-
required: ["subagentId", "question"]
|
|
5926
|
-
};
|
|
5927
|
-
return {
|
|
5928
|
-
name: "ask_subagent",
|
|
5929
|
-
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.",
|
|
5930
|
-
permission: "auto",
|
|
5931
|
-
mutating: false,
|
|
5932
|
-
inputSchema,
|
|
5933
|
-
async execute(input) {
|
|
5934
|
-
const i = input;
|
|
5935
|
-
try {
|
|
5936
|
-
const answer = await director.ask(i.subagentId, { question: i.question }, i.timeoutMs);
|
|
5937
|
-
return { ok: true, answer };
|
|
5938
|
-
} catch (err) {
|
|
5939
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
5940
|
-
}
|
|
5941
|
-
}
|
|
5942
|
-
};
|
|
5943
|
-
}
|
|
5944
|
-
function makeRollUpTool(director) {
|
|
5945
|
-
const inputSchema = {
|
|
5946
|
-
type: "object",
|
|
5947
|
-
properties: {
|
|
5948
|
-
taskIds: {
|
|
5949
|
-
type: "array",
|
|
5950
|
-
items: { type: "string" },
|
|
5951
|
-
description: "Completed task ids to aggregate. Pass the ids returned by previous `assign_task` calls."
|
|
5952
|
-
},
|
|
5953
|
-
style: {
|
|
5954
|
-
type: "string",
|
|
5955
|
-
enum: ["markdown", "json"],
|
|
5956
|
-
description: "Output flavor \u2014 markdown (default) for in-prompt summarization, json for structured downstream processing."
|
|
5957
|
-
}
|
|
5958
|
-
},
|
|
5959
|
-
required: ["taskIds"]
|
|
5960
|
-
};
|
|
5961
|
-
return {
|
|
5962
|
-
name: "roll_up",
|
|
5963
|
-
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.",
|
|
5964
|
-
permission: "auto",
|
|
5965
|
-
mutating: false,
|
|
5966
|
-
inputSchema,
|
|
5967
|
-
async execute(input) {
|
|
5968
|
-
const i = input;
|
|
5969
|
-
const summary = director.rollUp(i.taskIds, i.style ?? "markdown");
|
|
5970
|
-
return { summary, count: i.taskIds.length };
|
|
5971
|
-
}
|
|
5972
|
-
};
|
|
5973
|
-
}
|
|
5974
|
-
function makeTerminateTool(director) {
|
|
5975
|
-
const inputSchema = {
|
|
5976
|
-
type: "object",
|
|
5977
|
-
properties: {
|
|
5978
|
-
subagentId: { type: "string", description: "Subagent to abort." }
|
|
5979
|
-
},
|
|
5980
|
-
required: ["subagentId"]
|
|
5981
|
-
};
|
|
5982
|
-
return {
|
|
5983
|
-
name: "terminate_subagent",
|
|
5984
|
-
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".',
|
|
5985
|
-
permission: "auto",
|
|
5986
|
-
mutating: true,
|
|
5987
|
-
inputSchema,
|
|
5988
|
-
async execute(input) {
|
|
5989
|
-
const i = input;
|
|
5990
|
-
await director.terminate(i.subagentId);
|
|
5991
|
-
return { ok: true };
|
|
5992
|
-
}
|
|
5993
|
-
};
|
|
5994
|
-
}
|
|
5995
|
-
function makeFleetStatusTool(director) {
|
|
5996
|
-
return {
|
|
5997
|
-
name: "fleet_status",
|
|
5998
|
-
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.",
|
|
5999
|
-
permission: "auto",
|
|
6000
|
-
mutating: false,
|
|
6001
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
6002
|
-
async execute() {
|
|
6003
|
-
return director.status();
|
|
6004
|
-
}
|
|
6005
|
-
};
|
|
6006
|
-
}
|
|
6007
|
-
function makeFleetUsageTool(director) {
|
|
6008
|
-
return {
|
|
6009
|
-
name: "fleet_usage",
|
|
6010
|
-
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.",
|
|
6011
|
-
permission: "auto",
|
|
6012
|
-
mutating: false,
|
|
6013
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
6014
|
-
async execute() {
|
|
6015
|
-
return director.snapshot();
|
|
6016
|
-
}
|
|
6017
|
-
};
|
|
6018
|
-
}
|
|
6019
6219
|
function createDelegateTool(opts) {
|
|
6020
6220
|
const defaultTimeoutMs = opts.defaultTimeoutMs ?? 4 * 60 * 60 * 1e3;
|
|
6021
6221
|
const rosterIds = opts.roster ? Object.keys(opts.roster) : [];
|
|
@@ -8553,13 +8753,13 @@ function roughEstimate(messages) {
|
|
|
8553
8753
|
function createContextManagerTool(opts = {}) {
|
|
8554
8754
|
return {
|
|
8555
8755
|
name: CONTEXT_MANAGER_TOOL_NAME,
|
|
8556
|
-
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.',
|
|
8756
|
+
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.',
|
|
8557
8757
|
inputSchema: {
|
|
8558
8758
|
type: "object",
|
|
8559
8759
|
properties: {
|
|
8560
8760
|
action: {
|
|
8561
8761
|
type: "string",
|
|
8562
|
-
enum: ["check", "summary", "prune", "add_note", "compact"],
|
|
8762
|
+
enum: ["check", "summary", "prune", "add_note", "compact", "repair"],
|
|
8563
8763
|
description: "The context operation to perform."
|
|
8564
8764
|
},
|
|
8565
8765
|
from: {
|
|
@@ -8587,12 +8787,15 @@ function createContextManagerTool(opts = {}) {
|
|
|
8587
8787
|
const messages = ctx.messages;
|
|
8588
8788
|
const beforeTokens = roughEstimate(messages);
|
|
8589
8789
|
const applyMessages = (next) => {
|
|
8790
|
+
const repaired = repairToolUseAdjacency(next);
|
|
8791
|
+
const finalMessages = repaired.messages;
|
|
8590
8792
|
if (ctx.state) {
|
|
8591
|
-
ctx.state.replaceMessages(
|
|
8793
|
+
ctx.state.replaceMessages(finalMessages);
|
|
8592
8794
|
} else {
|
|
8593
8795
|
messages.length = 0;
|
|
8594
|
-
messages.splice(0, 0, ...
|
|
8796
|
+
messages.splice(0, 0, ...finalMessages);
|
|
8595
8797
|
}
|
|
8798
|
+
return repaired.report;
|
|
8596
8799
|
};
|
|
8597
8800
|
switch (input.action) {
|
|
8598
8801
|
case "check": {
|
|
@@ -8609,6 +8812,22 @@ function createContextManagerTool(opts = {}) {
|
|
|
8609
8812
|
})
|
|
8610
8813
|
};
|
|
8611
8814
|
}
|
|
8815
|
+
case "repair": {
|
|
8816
|
+
const repair = applyMessages([...messages]);
|
|
8817
|
+
const afterTokens = roughEstimate(ctx.messages);
|
|
8818
|
+
return {
|
|
8819
|
+
action: "repair",
|
|
8820
|
+
beforeTokens,
|
|
8821
|
+
afterTokens,
|
|
8822
|
+
messageCount: ctx.messages.length,
|
|
8823
|
+
repaired: repair.changed ? {
|
|
8824
|
+
removedToolUses: repair.removedToolUses,
|
|
8825
|
+
removedToolResults: repair.removedToolResults,
|
|
8826
|
+
removedMessages: repair.removedMessages
|
|
8827
|
+
} : void 0,
|
|
8828
|
+
notes: repair.changed ? "Context tool-call adjacency repaired." : "Context tool-call adjacency already valid."
|
|
8829
|
+
};
|
|
8830
|
+
}
|
|
8612
8831
|
case "compact": {
|
|
8613
8832
|
if (!opts.compactor) {
|
|
8614
8833
|
return {
|
|
@@ -8619,11 +8838,19 @@ function createContextManagerTool(opts = {}) {
|
|
|
8619
8838
|
};
|
|
8620
8839
|
}
|
|
8621
8840
|
const report = await opts.compactor.compact(ctx);
|
|
8841
|
+
const repair = applyMessages([...ctx.messages]);
|
|
8842
|
+
const afterTokens = repair.changed ? roughEstimate(ctx.messages) : report.after;
|
|
8843
|
+
const repaired = report.repaired ?? (repair.changed ? repair : void 0);
|
|
8622
8844
|
return {
|
|
8623
8845
|
action: "compact",
|
|
8624
8846
|
beforeTokens,
|
|
8625
|
-
afterTokens
|
|
8626
|
-
messageCount: messages.length
|
|
8847
|
+
afterTokens,
|
|
8848
|
+
messageCount: ctx.messages.length,
|
|
8849
|
+
repaired: repaired ? {
|
|
8850
|
+
removedToolUses: repaired.removedToolUses,
|
|
8851
|
+
removedToolResults: repaired.removedToolResults,
|
|
8852
|
+
removedMessages: repaired.removedMessages
|
|
8853
|
+
} : void 0
|
|
8627
8854
|
};
|
|
8628
8855
|
}
|
|
8629
8856
|
case "prune": {
|
|
@@ -8639,14 +8866,19 @@ function createContextManagerTool(opts = {}) {
|
|
|
8639
8866
|
}
|
|
8640
8867
|
const copy = [...messages];
|
|
8641
8868
|
const removed = copy.splice(from, to - from + 1);
|
|
8642
|
-
applyMessages(copy);
|
|
8643
|
-
const afterTokens = roughEstimate(
|
|
8869
|
+
const repair = applyMessages(copy);
|
|
8870
|
+
const afterTokens = roughEstimate(ctx.messages);
|
|
8644
8871
|
return {
|
|
8645
8872
|
action: "prune",
|
|
8646
8873
|
beforeTokens,
|
|
8647
8874
|
afterTokens,
|
|
8648
|
-
messageCount:
|
|
8649
|
-
removedCount: removed.length
|
|
8875
|
+
messageCount: ctx.messages.length,
|
|
8876
|
+
removedCount: removed.length,
|
|
8877
|
+
repaired: repair.changed ? {
|
|
8878
|
+
removedToolUses: repair.removedToolUses,
|
|
8879
|
+
removedToolResults: repair.removedToolResults,
|
|
8880
|
+
removedMessages: repair.removedMessages
|
|
8881
|
+
} : void 0
|
|
8650
8882
|
};
|
|
8651
8883
|
}
|
|
8652
8884
|
case "add_note": {
|
|
@@ -8658,14 +8890,19 @@ function createContextManagerTool(opts = {}) {
|
|
|
8658
8890
|
};
|
|
8659
8891
|
const copy = [...messages];
|
|
8660
8892
|
copy.splice(afterIdx, 0, noteMsg);
|
|
8661
|
-
applyMessages(copy);
|
|
8662
|
-
const afterTokens = roughEstimate(
|
|
8893
|
+
const repair = applyMessages(copy);
|
|
8894
|
+
const afterTokens = roughEstimate(ctx.messages);
|
|
8663
8895
|
return {
|
|
8664
8896
|
action: "add_note",
|
|
8665
8897
|
beforeTokens,
|
|
8666
8898
|
afterTokens,
|
|
8667
|
-
messageCount:
|
|
8668
|
-
summary: noteText
|
|
8899
|
+
messageCount: ctx.messages.length,
|
|
8900
|
+
summary: noteText,
|
|
8901
|
+
repaired: repair.changed ? {
|
|
8902
|
+
removedToolUses: repair.removedToolUses,
|
|
8903
|
+
removedToolResults: repair.removedToolResults,
|
|
8904
|
+
removedMessages: repair.removedMessages
|
|
8905
|
+
} : void 0
|
|
8669
8906
|
};
|
|
8670
8907
|
}
|
|
8671
8908
|
case "summary": {
|
|
@@ -8686,14 +8923,19 @@ function createContextManagerTool(opts = {}) {
|
|
|
8686
8923
|
};
|
|
8687
8924
|
const copy = [...messages];
|
|
8688
8925
|
copy.splice(from, to - from + 1, summaryMsg);
|
|
8689
|
-
applyMessages(copy);
|
|
8690
|
-
const afterTokens = roughEstimate(
|
|
8926
|
+
const repair = applyMessages(copy);
|
|
8927
|
+
const afterTokens = roughEstimate(ctx.messages);
|
|
8691
8928
|
return {
|
|
8692
8929
|
action: "summary",
|
|
8693
8930
|
beforeTokens,
|
|
8694
8931
|
afterTokens,
|
|
8695
|
-
messageCount:
|
|
8696
|
-
summary: summaryText
|
|
8932
|
+
messageCount: ctx.messages.length,
|
|
8933
|
+
summary: summaryText,
|
|
8934
|
+
repaired: repair.changed ? {
|
|
8935
|
+
removedToolUses: repair.removedToolUses,
|
|
8936
|
+
removedToolResults: repair.removedToolResults,
|
|
8937
|
+
removedMessages: repair.removedMessages
|
|
8938
|
+
} : void 0
|
|
8697
8939
|
};
|
|
8698
8940
|
}
|
|
8699
8941
|
default:
|
|
@@ -8797,6 +9039,41 @@ var sentinelServer = () => ({
|
|
|
8797
9039
|
permission: "deny"
|
|
8798
9040
|
// security tool — require explicit confirmation
|
|
8799
9041
|
});
|
|
9042
|
+
var zaiVisionServer = () => ({
|
|
9043
|
+
name: "zai-vision",
|
|
9044
|
+
description: "Z.AI Vision MCP \u2014 image analysis and screenshot understanding",
|
|
9045
|
+
transport: "stdio",
|
|
9046
|
+
command: "npx",
|
|
9047
|
+
args: ["-y", "@z_ai/mcp-server@latest"],
|
|
9048
|
+
env: {
|
|
9049
|
+
Z_AI_API_KEY: process.env.Z_AI_API_KEY ?? "",
|
|
9050
|
+
Z_AI_MODE: process.env.Z_AI_MODE ?? "ZAI"
|
|
9051
|
+
},
|
|
9052
|
+
allowedTools: [
|
|
9053
|
+
"image_analysis",
|
|
9054
|
+
"extract_text_from_screenshot",
|
|
9055
|
+
"diagnose_error_screenshot",
|
|
9056
|
+
"understand_technical_diagram",
|
|
9057
|
+
"analyze_data_visualization",
|
|
9058
|
+
"ui_diff_check"
|
|
9059
|
+
],
|
|
9060
|
+
permission: "auto"
|
|
9061
|
+
});
|
|
9062
|
+
var miniMaxVisionServer = () => ({
|
|
9063
|
+
name: "minimax-vision",
|
|
9064
|
+
description: "MiniMax MCP \u2014 image understanding via understand_image",
|
|
9065
|
+
transport: "stdio",
|
|
9066
|
+
command: "uvx",
|
|
9067
|
+
args: ["minimax-coding-plan-mcp", "-y"],
|
|
9068
|
+
env: {
|
|
9069
|
+
MINIMAX_API_KEY: process.env.MINIMAX_API_KEY ?? "",
|
|
9070
|
+
MINIMAX_MCP_BASE_PATH: process.env.MINIMAX_MCP_BASE_PATH ?? "./.wrongstack/minimax-output",
|
|
9071
|
+
MINIMAX_API_HOST: process.env.MINIMAX_API_HOST ?? "https://api.minimax.io",
|
|
9072
|
+
MINIMAX_API_RESOURCE_MODE: process.env.MINIMAX_API_RESOURCE_MODE ?? "url"
|
|
9073
|
+
},
|
|
9074
|
+
allowedTools: ["understand_image"],
|
|
9075
|
+
permission: "auto"
|
|
9076
|
+
});
|
|
8800
9077
|
var allServers = () => ({
|
|
8801
9078
|
filesystem: { ...filesystemServer(), enabled: false },
|
|
8802
9079
|
github: { ...githubServer(), enabled: false },
|
|
@@ -8807,9 +9084,11 @@ var allServers = () => ({
|
|
|
8807
9084
|
slack: { ...slackServer(), enabled: false },
|
|
8808
9085
|
aws: { ...awsServer(), enabled: false },
|
|
8809
9086
|
"google-maps": { ...googleMapsServer(), enabled: false },
|
|
8810
|
-
sentinel: { ...sentinelServer(), enabled: false }
|
|
9087
|
+
sentinel: { ...sentinelServer(), enabled: false },
|
|
9088
|
+
"zai-vision": { ...zaiVisionServer(), enabled: false },
|
|
9089
|
+
"minimax-vision": { ...miniMaxVisionServer(), enabled: false }
|
|
8811
9090
|
});
|
|
8812
9091
|
|
|
8813
|
-
export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutonomousRunner, BUG_HUNTER_AGENT, BudgetExceededError, ConfigMigrationError, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPermissionPolicy, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultTaskStore, Director, DirectorBudgetError, DirectorStateCheckpoint, DoneConditionChecker, FLEET_ROSTER, FleetBus, FleetUsageAggregator, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, IntelligentCompactor, LLMSelector, NoopMetricsSink, NoopTracer, OTelTracer, PROMETHEUS_CONTENT_TYPE, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, SECURITY_SCANNER_AGENT, SelectiveCompactor, SessionAnalyzer, SpecDrivenDev, SpecParser, SubagentBudget, TaskFlow, TaskGenerator, TaskTracker, ToolExecutor, addPlanItem, allServers, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, braveSearchServer, buildOtlpMetricsRequest, buildOtlpTracesRequest, classifyFamily, clearPlan, composeDirectorPrompt, composeSubagentPrompt, context7Server, contextManagerTool, createContextManagerTool, createDelegateTool, createMessage, decryptConfigSecrets, emptyPlan, encryptConfigSecrets, everArtServer, filesystemServer, formatPlan, githubServer, googleMapsServer, loadDirectorState, loadPlan, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeDirectorSessionFactory, migratePlaintextSecrets, removePlanItem, renderPrometheus, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, savePlan, saveTodosCheckpoint, sentinelServer, setPlanItemStatus, slackServer, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, wireMetricsToEvents };
|
|
9092
|
+
export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutonomousRunner, BUG_HUNTER_AGENT, BudgetExceededError, ConfigMigrationError, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPermissionPolicy, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultTaskStore, Director, DirectorBudgetError, DirectorStateCheckpoint, DoneConditionChecker, FLEET_ROSTER, FleetBus, FleetUsageAggregator, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, IntelligentCompactor, LLMSelector, NoopMetricsSink, NoopTracer, OTelTracer, PROMETHEUS_CONTENT_TYPE, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, SECURITY_SCANNER_AGENT, SelectiveCompactor, SessionAnalyzer, SpecDrivenDev, SpecParser, SubagentBudget, TaskFlow, TaskGenerator, TaskTracker, ToolExecutor, addPlanItem, allServers, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, braveSearchServer, buildOtlpMetricsRequest, buildOtlpTracesRequest, classifyFamily, clearPlan, composeDirectorPrompt, composeSubagentPrompt, context7Server, contextManagerTool, createContextManagerTool, createDelegateTool, createMessage, decryptConfigSecrets2 as decryptConfigSecrets, emptyPlan, encryptConfigSecrets, everArtServer, filesystemServer, formatPlan, githubServer, googleMapsServer, loadDirectorState, loadPlan, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeDirectorSessionFactory, migratePlaintextSecrets, miniMaxVisionServer, removePlanItem, renderPrometheus, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, savePlan, saveTodosCheckpoint, sentinelServer, setPlanItemStatus, slackServer, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, wireMetricsToEvents, zaiVisionServer };
|
|
8814
9093
|
//# sourceMappingURL=index.js.map
|
|
8815
9094
|
//# sourceMappingURL=index.js.map
|