@wrongstack/core 0.275.1 → 0.276.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-bridge-D9JkPvJ0.d.ts → agent-bridge-D7A-eu3C.d.ts} +1 -1
- package/dist/{agent-subagent-runner-CArSFKFl.d.ts → agent-subagent-runner-CEuw4ATz.d.ts} +16 -10
- package/dist/{brain-DCkB5_e7.d.ts → brain-BLOyN5ZP.d.ts} +127 -1
- package/dist/{compactor-CzSvxM1g.d.ts → compactor-DcBpaJsI.d.ts} +1 -1
- package/dist/{config-BzFRKkg7.d.ts → config-Bf5mj-ad.d.ts} +20 -2
- package/dist/{context-BrLe8pJy.d.ts → context-CLnUMW5g.d.ts} +40 -2
- package/dist/coordination/index.d.ts +43 -24
- package/dist/coordination/index.js +849 -648
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +28 -28
- package/dist/defaults/index.js +1636 -845
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +16 -16
- package/dist/execution/index.js +218 -49
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +1 -1
- package/dist/extension/index.d.ts +7 -7
- package/dist/extension/index.js.map +1 -1
- package/dist/{global-mailbox-CXkugtNQ.d.ts → global-mailbox-Iqfkgmwu.d.ts} +3 -3
- package/dist/{goal-store-DUwdbdoY.d.ts → goal-store-DGb6b5Ed.d.ts} +1 -1
- package/dist/hq/index.d.ts +6 -6
- package/dist/hq/index.js +178 -75
- package/dist/hq/index.js.map +1 -1
- package/dist/{index-CtlizLTK.d.ts → index-Cn0NOshr.d.ts} +10 -5
- package/dist/{index-neOCEy6q.d.ts → index-L4RZN9jJ.d.ts} +2 -2
- package/dist/index.d.ts +56 -48
- package/dist/index.js +2789 -1546
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/infrastructure/index.js +26 -7
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +20 -12
- package/dist/kernel/index.js +55 -9
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mailbox-types-_7gaY0Rl.d.ts → mailbox-types-DTl7bRH3.d.ts} +3 -1
- package/dist/{mcp-servers-MLL6bMlv.d.ts → mcp-servers-CuZGf9fI.d.ts} +4 -4
- package/dist/models/index.d.ts +5 -5
- package/dist/models/index.js +223 -139
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-CrkcxQ-g.d.ts → models-registry-8XOdxWQu.d.ts} +16 -1
- package/dist/{multi-agent-coordinator-Dc_HuG9p.d.ts → multi-agent-coordinator-CiRtKVTk.d.ts} +8 -1
- package/dist/{null-fleet-bus-BMZwMin7.d.ts → null-fleet-bus-d9G-bVy9.d.ts} +26 -22
- package/dist/observability/index.d.ts +2 -2
- package/dist/{path-resolver-uVK4BatM.d.ts → path-resolver-BhIb6mtd.d.ts} +8 -3
- package/dist/{permission-CJR1qfOi.d.ts → permission-BCbQDR2s.d.ts} +1 -1
- package/dist/{permission-policy-DLVKKk4w.d.ts → permission-policy-C0ikndX_.d.ts} +2 -18
- package/dist/{pipeline-BYR-Vdau.d.ts → pipeline-Dl6XbfE7.d.ts} +10 -6
- package/dist/{provider-model-resolve-iREK_1lG.d.ts → provider-model-resolve-B70epO19.d.ts} +3 -3
- package/dist/{provider-runner-i7SQXZuC.d.ts → provider-runner-DZ808MSM.d.ts} +3 -3
- package/dist/{retry-policy-BmY5ooh3.d.ts → retry-policy-Dt3_z8Aj.d.ts} +1 -1
- package/dist/sdd/index.d.ts +19 -10
- package/dist/sdd/index.js +411 -240
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-C9leEMzr.d.ts → secret-vault-BUJ2d1gB.d.ts} +1 -1
- package/dist/security/index.d.ts +5 -5
- package/dist/security/index.js +30 -6
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-qjpee9BF.d.ts → selector-BCkWgdwy.d.ts} +1 -1
- package/dist/{session-event-bridge-m7y--I-H.d.ts → session-event-bridge-CMvIO59_.d.ts} +1 -1
- package/dist/{session-reader-BjLH4V9n.d.ts → session-reader-C8aiChUu.d.ts} +1 -1
- package/dist/skills/index.js +1 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/index.d.ts +68 -30
- package/dist/storage/index.js +839 -528
- package/dist/storage/index.js.map +1 -1
- package/dist/{strategy-compactor-C2bmlWYg.d.ts → strategy-compactor-DI1OHVbB.d.ts} +10 -10
- package/dist/{todos-checkpoint-oDS9IBNS.d.ts → todos-checkpoint-Ddd2CGr0.d.ts} +56 -9
- package/dist/{tool-executor-D4YdaJ-M.d.ts → tool-executor-Bmd5Ygoo.d.ts} +45 -10
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/types/index.d.ts +20 -20
- package/dist/types/index.js +331 -98
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +16 -3
- package/dist/utils/index.js +159 -83
- package/dist/utils/index.js.map +1 -1
- package/dist/{worktree-manager-A1Efnvs0.d.ts → worktree-manager-DBdl_5rs.d.ts} +4 -1
- package/instructions/agents/shadow-agent.md +3 -3
- package/instructions/coordination/director-preamble.md +3 -3
- package/instructions/modes/research-web.md +4 -4
- package/package.json +1 -1
- package/skills/research-web/SKILL.md +26 -26
- package/skills/research-web/SKILL.save.md +1 -1
package/dist/defaults/index.js
CHANGED
|
@@ -2,11 +2,11 @@ import * as crypto2 from 'crypto';
|
|
|
2
2
|
import { randomBytes, randomUUID, createCipheriv, createDecipheriv, createHash, scryptSync } from 'crypto';
|
|
3
3
|
import * as fsp7 from 'fs/promises';
|
|
4
4
|
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
5
|
-
import * as
|
|
5
|
+
import * as path4 from 'path';
|
|
6
6
|
import { isAbsolute, join, resolve, sep } from 'path';
|
|
7
7
|
import * as os from 'os';
|
|
8
8
|
import { hostname } from 'os';
|
|
9
|
-
import * as
|
|
9
|
+
import * as fs12 from 'fs';
|
|
10
10
|
import { readFileSync, statSync, createReadStream, existsSync } from 'fs';
|
|
11
11
|
import { fileURLToPath } from 'url';
|
|
12
12
|
import { EventEmitter } from 'events';
|
|
@@ -29,6 +29,19 @@ var __export = (target, all) => {
|
|
|
29
29
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
// src/utils/assert-never.ts
|
|
33
|
+
function assertNever(x, message) {
|
|
34
|
+
const err = new Error(
|
|
35
|
+
`Unhandled case: ${JSON.stringify(x)}`
|
|
36
|
+
);
|
|
37
|
+
err.name = "AssertNeverError";
|
|
38
|
+
throw err;
|
|
39
|
+
}
|
|
40
|
+
var init_assert_never = __esm({
|
|
41
|
+
"src/utils/assert-never.ts"() {
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
32
45
|
// src/utils/atomic-write.ts
|
|
33
46
|
var atomic_write_exports = {};
|
|
34
47
|
__export(atomic_write_exports, {
|
|
@@ -37,9 +50,9 @@ __export(atomic_write_exports, {
|
|
|
37
50
|
withFileLock: () => withFileLock
|
|
38
51
|
});
|
|
39
52
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
40
|
-
const dir =
|
|
53
|
+
const dir = path4.dirname(targetPath);
|
|
41
54
|
await fsp7.mkdir(dir, { recursive: true });
|
|
42
|
-
const tmp =
|
|
55
|
+
const tmp = path4.join(dir, `.${path4.basename(targetPath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
43
56
|
try {
|
|
44
57
|
if (typeof content === "string") {
|
|
45
58
|
await fsp7.writeFile(tmp, content, { flag: "wx", encoding: opts.encoding ?? "utf8" });
|
|
@@ -57,8 +70,8 @@ async function atomicWrite(targetPath, content, opts = {}) {
|
|
|
57
70
|
}
|
|
58
71
|
let mode;
|
|
59
72
|
try {
|
|
60
|
-
const
|
|
61
|
-
mode =
|
|
73
|
+
const stat10 = await fsp7.stat(targetPath);
|
|
74
|
+
mode = stat10.mode & 511;
|
|
62
75
|
} catch {
|
|
63
76
|
mode = opts.mode;
|
|
64
77
|
}
|
|
@@ -84,9 +97,9 @@ async function ensureDir(dir) {
|
|
|
84
97
|
await fsp7.mkdir(dir, { recursive: true });
|
|
85
98
|
}
|
|
86
99
|
async function withFileLock(targetPath, fn, opts = {}) {
|
|
87
|
-
const dir =
|
|
100
|
+
const dir = path4.dirname(targetPath);
|
|
88
101
|
await fsp7.mkdir(dir, { recursive: true });
|
|
89
|
-
const lockPath =
|
|
102
|
+
const lockPath = path4.join(dir, `.${path4.basename(targetPath)}.lock`);
|
|
90
103
|
const timeoutMs = opts.timeoutMs ?? 5e3;
|
|
91
104
|
const staleMs = opts.staleMs ?? 3e4;
|
|
92
105
|
const started = Date.now();
|
|
@@ -104,8 +117,8 @@ async function withFileLock(targetPath, fn, opts = {}) {
|
|
|
104
117
|
}
|
|
105
118
|
if (code !== "EEXIST") throw err;
|
|
106
119
|
try {
|
|
107
|
-
const
|
|
108
|
-
if (Date.now() -
|
|
120
|
+
const stat10 = await fsp7.stat(lockPath);
|
|
121
|
+
if (Date.now() - stat10.mtimeMs > staleMs) {
|
|
109
122
|
await fsp7.unlink(lockPath);
|
|
110
123
|
continue;
|
|
111
124
|
}
|
|
@@ -113,9 +126,14 @@ async function withFileLock(targetPath, fn, opts = {}) {
|
|
|
113
126
|
continue;
|
|
114
127
|
}
|
|
115
128
|
if (Date.now() - started >= timeoutMs) {
|
|
116
|
-
throw new
|
|
129
|
+
throw new FsError({
|
|
130
|
+
message: `Timed out waiting for file lock: ${targetPath}`,
|
|
131
|
+
code: "FS_ATOMIC_WRITE_FAILED",
|
|
132
|
+
path: targetPath,
|
|
133
|
+
context: { timeoutMs }
|
|
134
|
+
});
|
|
117
135
|
}
|
|
118
|
-
await new Promise((
|
|
136
|
+
await new Promise((resolve12) => setTimeout(resolve12, 25));
|
|
119
137
|
}
|
|
120
138
|
}
|
|
121
139
|
try {
|
|
@@ -148,7 +166,7 @@ async function renameWithRetry(from, to) {
|
|
|
148
166
|
if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {
|
|
149
167
|
throw err;
|
|
150
168
|
}
|
|
151
|
-
await new Promise((
|
|
169
|
+
await new Promise((resolve12) => setTimeout(resolve12, delays[i]));
|
|
152
170
|
}
|
|
153
171
|
}
|
|
154
172
|
throw lastErr;
|
|
@@ -156,64 +174,12 @@ async function renameWithRetry(from, to) {
|
|
|
156
174
|
var TRANSIENT_RENAME_CODES;
|
|
157
175
|
var init_atomic_write = __esm({
|
|
158
176
|
"src/utils/atomic-write.ts"() {
|
|
177
|
+
init_errors();
|
|
159
178
|
TRANSIENT_RENAME_CODES = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES", "ENOTEMPTY"]);
|
|
160
179
|
}
|
|
161
180
|
});
|
|
162
181
|
|
|
163
|
-
// src/utils/assert-never.ts
|
|
164
|
-
function assertNever(x, message) {
|
|
165
|
-
const err = new Error(
|
|
166
|
-
`Unhandled case: ${JSON.stringify(x)}`
|
|
167
|
-
);
|
|
168
|
-
err.name = "AssertNeverError";
|
|
169
|
-
throw err;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// src/utils/index.ts
|
|
173
|
-
init_atomic_write();
|
|
174
|
-
|
|
175
182
|
// src/utils/child-env.ts
|
|
176
|
-
var ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
177
|
-
"PATH",
|
|
178
|
-
"HOME",
|
|
179
|
-
"USER",
|
|
180
|
-
"USERNAME",
|
|
181
|
-
"LOGNAME",
|
|
182
|
-
"SHELL",
|
|
183
|
-
"LANG",
|
|
184
|
-
"LC_ALL",
|
|
185
|
-
"LC_CTYPE",
|
|
186
|
-
"TERM",
|
|
187
|
-
"TZ",
|
|
188
|
-
"TMPDIR",
|
|
189
|
-
"TEMP",
|
|
190
|
-
"TMP",
|
|
191
|
-
"PWD",
|
|
192
|
-
"OLDPWD",
|
|
193
|
-
"COMSPEC",
|
|
194
|
-
"SYSTEMROOT",
|
|
195
|
-
"SYSTEMDRIVE",
|
|
196
|
-
"WINDIR",
|
|
197
|
-
"PROGRAMFILES",
|
|
198
|
-
"PROGRAMFILES(X86)",
|
|
199
|
-
"PROGRAMDATA",
|
|
200
|
-
"APPDATA",
|
|
201
|
-
"LOCALAPPDATA",
|
|
202
|
-
"USERPROFILE",
|
|
203
|
-
"PUBLIC",
|
|
204
|
-
"PATHEXT"
|
|
205
|
-
]);
|
|
206
|
-
var SECRET_NAME_PARTS = [
|
|
207
|
-
"TOKEN",
|
|
208
|
-
"SECRET",
|
|
209
|
-
"PASSWORD",
|
|
210
|
-
"PASSWD",
|
|
211
|
-
"AUTH",
|
|
212
|
-
"CRED",
|
|
213
|
-
"BEARER",
|
|
214
|
-
"COOKIE",
|
|
215
|
-
"PRIVATE"
|
|
216
|
-
];
|
|
217
183
|
function looksSecret(name) {
|
|
218
184
|
const upper = name.toUpperCase();
|
|
219
185
|
for (const p of SECRET_NAME_PARTS) {
|
|
@@ -230,8 +196,6 @@ function looksSecret(name) {
|
|
|
230
196
|
function valueHasEmbeddedCredential(value) {
|
|
231
197
|
return /\b[a-z][a-z0-9+.-]*:\/\/[^/\s:@]*:[^/\s@]+@/i.test(value);
|
|
232
198
|
}
|
|
233
|
-
var NODE_OPTIONS_INJECTION_FLAG = /^(?:--require|-r|--import|--loader|--experimental-loader)$/;
|
|
234
|
-
var NODE_OPTIONS_INJECTION_FLAG_EQ = /^(?:--require|-r|--import|--loader|--experimental-loader)=/;
|
|
235
199
|
function sanitizeNodeOptions(value) {
|
|
236
200
|
const tokens = value.split(/\s+/).filter(Boolean);
|
|
237
201
|
const kept = [];
|
|
@@ -291,55 +255,123 @@ function buildChildEnv(optsOrSessionId) {
|
|
|
291
255
|
if (opts.sessionId) out["WRONGSTACK_SESSION_ID"] = opts.sessionId;
|
|
292
256
|
return out;
|
|
293
257
|
}
|
|
258
|
+
var ALLOWED_KEYS, SECRET_NAME_PARTS, NODE_OPTIONS_INJECTION_FLAG, NODE_OPTIONS_INJECTION_FLAG_EQ;
|
|
259
|
+
var init_child_env = __esm({
|
|
260
|
+
"src/utils/child-env.ts"() {
|
|
261
|
+
ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
262
|
+
"PATH",
|
|
263
|
+
"HOME",
|
|
264
|
+
"USER",
|
|
265
|
+
"USERNAME",
|
|
266
|
+
"LOGNAME",
|
|
267
|
+
"SHELL",
|
|
268
|
+
"LANG",
|
|
269
|
+
"LC_ALL",
|
|
270
|
+
"LC_CTYPE",
|
|
271
|
+
"TERM",
|
|
272
|
+
"TZ",
|
|
273
|
+
"TMPDIR",
|
|
274
|
+
"TEMP",
|
|
275
|
+
"TMP",
|
|
276
|
+
"PWD",
|
|
277
|
+
"OLDPWD",
|
|
278
|
+
"COMSPEC",
|
|
279
|
+
"SYSTEMROOT",
|
|
280
|
+
"SYSTEMDRIVE",
|
|
281
|
+
"WINDIR",
|
|
282
|
+
"PROGRAMFILES",
|
|
283
|
+
"PROGRAMFILES(X86)",
|
|
284
|
+
"PROGRAMDATA",
|
|
285
|
+
"APPDATA",
|
|
286
|
+
"LOCALAPPDATA",
|
|
287
|
+
"USERPROFILE",
|
|
288
|
+
"PUBLIC",
|
|
289
|
+
"PATHEXT"
|
|
290
|
+
]);
|
|
291
|
+
SECRET_NAME_PARTS = [
|
|
292
|
+
"TOKEN",
|
|
293
|
+
"SECRET",
|
|
294
|
+
"PASSWORD",
|
|
295
|
+
"PASSWD",
|
|
296
|
+
"AUTH",
|
|
297
|
+
"CRED",
|
|
298
|
+
"BEARER",
|
|
299
|
+
"COOKIE",
|
|
300
|
+
"PRIVATE"
|
|
301
|
+
];
|
|
302
|
+
NODE_OPTIONS_INJECTION_FLAG = /^(?:--require|-r|--import|--loader|--experimental-loader)$/;
|
|
303
|
+
NODE_OPTIONS_INJECTION_FLAG_EQ = /^(?:--require|-r|--import|--loader|--experimental-loader)=/;
|
|
304
|
+
}
|
|
305
|
+
});
|
|
294
306
|
|
|
295
307
|
// src/utils/term.ts
|
|
296
|
-
var hasStdout = () => typeof process !== "undefined" && !!process.stdout;
|
|
297
308
|
function isStdoutTTY() {
|
|
298
309
|
return hasStdout() && Boolean(process.stdout.isTTY);
|
|
299
310
|
}
|
|
300
311
|
function writeTo(s, stream) {
|
|
301
312
|
if (!stream || typeof stream.write !== "function") return false;
|
|
302
|
-
|
|
313
|
+
const guard = activeOutputGuard;
|
|
314
|
+
if (!guard) {
|
|
303
315
|
stream.write(s);
|
|
304
316
|
return true;
|
|
305
317
|
}
|
|
318
|
+
guard.suspend();
|
|
319
|
+
stream.write(s);
|
|
320
|
+
guard.resume();
|
|
321
|
+
return true;
|
|
306
322
|
}
|
|
307
323
|
function writeErr(s, stream = process.stderr) {
|
|
308
324
|
return writeTo(s, stream);
|
|
309
325
|
}
|
|
326
|
+
var hasStdout, activeOutputGuard;
|
|
327
|
+
var init_term = __esm({
|
|
328
|
+
"src/utils/term.ts"() {
|
|
329
|
+
hasStdout = () => typeof process !== "undefined" && !!process.stdout;
|
|
330
|
+
activeOutputGuard = null;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
310
333
|
|
|
311
334
|
// src/utils/color.ts
|
|
312
|
-
var isColorTty = () => {
|
|
313
|
-
if (envFlag(process.env.NO_COLOR)) return false;
|
|
314
|
-
if (envFlag(process.env.FORCE_COLOR)) return true;
|
|
315
|
-
return isStdoutTTY();
|
|
316
|
-
};
|
|
317
335
|
function envFlag(value) {
|
|
318
336
|
if (value === void 0) return false;
|
|
319
337
|
if (value.trim() === "") return false;
|
|
320
338
|
return !/^(0|false|no|off)$/i.test(value.trim());
|
|
321
339
|
}
|
|
322
|
-
var COLOR
|
|
323
|
-
var
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
340
|
+
var isColorTty, COLOR, wrap, color;
|
|
341
|
+
var init_color = __esm({
|
|
342
|
+
"src/utils/color.ts"() {
|
|
343
|
+
init_term();
|
|
344
|
+
isColorTty = () => {
|
|
345
|
+
if (envFlag(process.env.NO_COLOR)) return false;
|
|
346
|
+
if (envFlag(process.env.FORCE_COLOR)) return true;
|
|
347
|
+
return isStdoutTTY();
|
|
348
|
+
};
|
|
349
|
+
COLOR = isColorTty();
|
|
350
|
+
wrap = (open4, close) => (s) => COLOR ? `\x1B[${open4}m${s}\x1B[${close}m` : s;
|
|
351
|
+
color = {
|
|
352
|
+
reset: wrap("0", "0"),
|
|
353
|
+
bold: wrap("1", "22"),
|
|
354
|
+
dim: wrap("2", "22"),
|
|
355
|
+
italic: wrap("3", "23"),
|
|
356
|
+
underline: wrap("4", "24"),
|
|
357
|
+
red: wrap("31", "39"),
|
|
358
|
+
green: wrap("32", "39"),
|
|
359
|
+
yellow: wrap("33", "39"),
|
|
360
|
+
blue: wrap("34", "39"),
|
|
361
|
+
magenta: wrap("35", "39"),
|
|
362
|
+
cyan: wrap("36", "39"),
|
|
363
|
+
gray: wrap("90", "39"),
|
|
364
|
+
amber: wrap("38;5;214", "39"),
|
|
365
|
+
pink: wrap("38;5;205", "39"),
|
|
366
|
+
bgRed: wrap("41", "49"),
|
|
367
|
+
bgGreen: wrap("42", "49")
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
var init_config_json = __esm({
|
|
372
|
+
"src/utils/config-json.ts"() {
|
|
373
|
+
}
|
|
374
|
+
});
|
|
343
375
|
function createContextEvidenceState() {
|
|
344
376
|
return {
|
|
345
377
|
sessionGoals: [],
|
|
@@ -412,17 +444,14 @@ function ensureEvidence(ctx) {
|
|
|
412
444
|
}
|
|
413
445
|
return ctx.contextEvidence;
|
|
414
446
|
}
|
|
447
|
+
var MAX_DIGEST_CHARS;
|
|
448
|
+
var init_context_evidence = __esm({
|
|
449
|
+
"src/utils/context-evidence.ts"() {
|
|
450
|
+
MAX_DIGEST_CHARS = 4e3;
|
|
451
|
+
}
|
|
452
|
+
});
|
|
415
453
|
|
|
416
454
|
// src/utils/deep-merge.ts
|
|
417
|
-
var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set([
|
|
418
|
-
"__proto__",
|
|
419
|
-
"constructor",
|
|
420
|
-
"prototype",
|
|
421
|
-
"__defineGetter__",
|
|
422
|
-
"__defineSetter__",
|
|
423
|
-
"__lookupGetter__",
|
|
424
|
-
"__lookupSetter__"
|
|
425
|
-
]);
|
|
426
455
|
function isPrimitiveArray(a) {
|
|
427
456
|
return a.every((v) => v === null || typeof v !== "object" && typeof v !== "function");
|
|
428
457
|
}
|
|
@@ -471,11 +500,35 @@ function deepMerge(base, patch, options = {}) {
|
|
|
471
500
|
}
|
|
472
501
|
return out;
|
|
473
502
|
}
|
|
503
|
+
var FORBIDDEN_PROTO_KEYS;
|
|
504
|
+
var init_deep_merge = __esm({
|
|
505
|
+
"src/utils/deep-merge.ts"() {
|
|
506
|
+
FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set([
|
|
507
|
+
"__proto__",
|
|
508
|
+
"constructor",
|
|
509
|
+
"prototype",
|
|
510
|
+
"__defineGetter__",
|
|
511
|
+
"__defineSetter__",
|
|
512
|
+
"__lookupGetter__",
|
|
513
|
+
"__lookupSetter__"
|
|
514
|
+
]);
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
// src/utils/diff.ts
|
|
519
|
+
var init_diff = __esm({
|
|
520
|
+
"src/utils/diff.ts"() {
|
|
521
|
+
}
|
|
522
|
+
});
|
|
474
523
|
|
|
475
524
|
// src/utils/error.ts
|
|
476
525
|
function toErrorMessage(err) {
|
|
477
526
|
return err instanceof Error ? err.message : String(err);
|
|
478
527
|
}
|
|
528
|
+
var init_error = __esm({
|
|
529
|
+
"src/utils/error.ts"() {
|
|
530
|
+
}
|
|
531
|
+
});
|
|
479
532
|
|
|
480
533
|
// src/utils/expect-defined.ts
|
|
481
534
|
function expectDefined(value, label) {
|
|
@@ -486,9 +539,10 @@ function expectDefined(value, label) {
|
|
|
486
539
|
}
|
|
487
540
|
return value;
|
|
488
541
|
}
|
|
489
|
-
var
|
|
490
|
-
|
|
491
|
-
|
|
542
|
+
var init_expect_defined = __esm({
|
|
543
|
+
"src/utils/expect-defined.ts"() {
|
|
544
|
+
}
|
|
545
|
+
});
|
|
492
546
|
function isGlob(p) {
|
|
493
547
|
for (const c of p) {
|
|
494
548
|
if (GLOB_CHARS.has(c)) return true;
|
|
@@ -573,8 +627,8 @@ async function expandGlob(pattern) {
|
|
|
573
627
|
for (const e of entries) {
|
|
574
628
|
const full = `${dir}${SEP}${e}`;
|
|
575
629
|
try {
|
|
576
|
-
const
|
|
577
|
-
if (
|
|
630
|
+
const stat10 = await fsp7.stat(full);
|
|
631
|
+
if (stat10.isDirectory()) await walk3(full, rest);
|
|
578
632
|
} catch {
|
|
579
633
|
}
|
|
580
634
|
}
|
|
@@ -591,8 +645,8 @@ async function expandGlob(pattern) {
|
|
|
591
645
|
if (entries.includes(seg)) {
|
|
592
646
|
const full = `${dir}${SEP}${seg}`;
|
|
593
647
|
try {
|
|
594
|
-
const
|
|
595
|
-
if (
|
|
648
|
+
const stat10 = await fsp7.stat(full);
|
|
649
|
+
if (stat10.isDirectory()) await walk3(full, rest);
|
|
596
650
|
} catch {
|
|
597
651
|
}
|
|
598
652
|
}
|
|
@@ -601,14 +655,20 @@ async function expandGlob(pattern) {
|
|
|
601
655
|
await walk3(base === "." ? "." : base, relPat);
|
|
602
656
|
return [...results];
|
|
603
657
|
}
|
|
658
|
+
var GLOB_CHARS, IS_WINDOWS, SEP;
|
|
659
|
+
var init_glob_expand = __esm({
|
|
660
|
+
"src/utils/glob-expand.ts"() {
|
|
661
|
+
init_expect_defined();
|
|
662
|
+
GLOB_CHARS = /* @__PURE__ */ new Set(["*", "?", "["]);
|
|
663
|
+
IS_WINDOWS = process.platform === "win32";
|
|
664
|
+
SEP = IS_WINDOWS ? "\\" : "/";
|
|
665
|
+
}
|
|
666
|
+
});
|
|
604
667
|
|
|
605
668
|
// src/utils/glob-match.ts
|
|
606
669
|
function escapeRegex(s) {
|
|
607
670
|
return s.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
608
671
|
}
|
|
609
|
-
var COMPILED_GLOB_CACHE = /* @__PURE__ */ new Map();
|
|
610
|
-
var CACHE_MAX_SIZE = 2e3;
|
|
611
|
-
var NEVER_MATCH = /[^\s\S]/;
|
|
612
672
|
function getCachedGlob(pattern) {
|
|
613
673
|
const cached = COMPILED_GLOB_CACHE.get(pattern);
|
|
614
674
|
if (cached) return cached;
|
|
@@ -627,7 +687,6 @@ function getCachedGlob(pattern) {
|
|
|
627
687
|
COMPILED_GLOB_CACHE.set(pattern, re);
|
|
628
688
|
return re;
|
|
629
689
|
}
|
|
630
|
-
var MAX_GLOB_PATTERN_LEN = 1024;
|
|
631
690
|
function compileGlob(pattern) {
|
|
632
691
|
if (pattern.length > MAX_GLOB_PATTERN_LEN) {
|
|
633
692
|
throw new Error(`Glob pattern exceeds ${MAX_GLOB_PATTERN_LEN} characters`);
|
|
@@ -683,6 +742,16 @@ function matchGlob(pattern, input) {
|
|
|
683
742
|
function matchAny(patterns, input) {
|
|
684
743
|
return patterns.some((p) => matchGlob(p, input));
|
|
685
744
|
}
|
|
745
|
+
var COMPILED_GLOB_CACHE, CACHE_MAX_SIZE, NEVER_MATCH, MAX_GLOB_PATTERN_LEN;
|
|
746
|
+
var init_glob_match = __esm({
|
|
747
|
+
"src/utils/glob-match.ts"() {
|
|
748
|
+
init_expect_defined();
|
|
749
|
+
COMPILED_GLOB_CACHE = /* @__PURE__ */ new Map();
|
|
750
|
+
CACHE_MAX_SIZE = 2e3;
|
|
751
|
+
NEVER_MATCH = /[^\s\S]/;
|
|
752
|
+
MAX_GLOB_PATTERN_LEN = 1024;
|
|
753
|
+
}
|
|
754
|
+
});
|
|
686
755
|
|
|
687
756
|
// src/utils/json-repair.ts
|
|
688
757
|
function completePartialObject(s) {
|
|
@@ -759,7 +828,6 @@ function repairTruncated(s) {
|
|
|
759
828
|
}
|
|
760
829
|
return result;
|
|
761
830
|
}
|
|
762
|
-
var VALID_ESCAPE = /* @__PURE__ */ new Set(['"', "\\", "/", "b", "f", "n", "r", "t", "u"]);
|
|
763
831
|
function endsWithInvalidEscape(str) {
|
|
764
832
|
const last = str[str.length - 1];
|
|
765
833
|
if (str[str.length - 2] !== "\\" || last === void 0) return false;
|
|
@@ -775,6 +843,13 @@ function tryParse(s) {
|
|
|
775
843
|
return { ok: false };
|
|
776
844
|
}
|
|
777
845
|
}
|
|
846
|
+
var VALID_ESCAPE;
|
|
847
|
+
var init_json_repair = __esm({
|
|
848
|
+
"src/utils/json-repair.ts"() {
|
|
849
|
+
init_expect_defined();
|
|
850
|
+
VALID_ESCAPE = /* @__PURE__ */ new Set(['"', "\\", "/", "b", "f", "n", "r", "t", "u"]);
|
|
851
|
+
}
|
|
852
|
+
});
|
|
778
853
|
|
|
779
854
|
// src/utils/json-schema-validate.ts
|
|
780
855
|
function validateAgainstSchema(value, schema) {
|
|
@@ -782,7 +857,6 @@ function validateAgainstSchema(value, schema) {
|
|
|
782
857
|
walk(value, schema, "", errors, 0);
|
|
783
858
|
return { ok: errors.length === 0, errors };
|
|
784
859
|
}
|
|
785
|
-
var MAX_SCHEMA_DEPTH = 64;
|
|
786
860
|
function walk(value, schema, path32, errors, depth) {
|
|
787
861
|
if (depth > MAX_SCHEMA_DEPTH) {
|
|
788
862
|
errors.push({
|
|
@@ -879,6 +953,12 @@ function deepEqual(a, b) {
|
|
|
879
953
|
}
|
|
880
954
|
return false;
|
|
881
955
|
}
|
|
956
|
+
var MAX_SCHEMA_DEPTH;
|
|
957
|
+
var init_json_schema_validate = __esm({
|
|
958
|
+
"src/utils/json-schema-validate.ts"() {
|
|
959
|
+
MAX_SCHEMA_DEPTH = 64;
|
|
960
|
+
}
|
|
961
|
+
});
|
|
882
962
|
|
|
883
963
|
// src/utils/merge-models-payload.ts
|
|
884
964
|
function mergeModelsPayload(base, overlay) {
|
|
@@ -942,6 +1022,10 @@ function stripUndefined(obj) {
|
|
|
942
1022
|
}
|
|
943
1023
|
return out;
|
|
944
1024
|
}
|
|
1025
|
+
var init_merge_models_payload = __esm({
|
|
1026
|
+
"src/utils/merge-models-payload.ts"() {
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
945
1029
|
|
|
946
1030
|
// src/utils/message-invariants.ts
|
|
947
1031
|
function repairToolUseAdjacency(messages) {
|
|
@@ -1034,15 +1118,19 @@ function isEmptyMessage(msg) {
|
|
|
1034
1118
|
if (typeof msg.content === "string") return msg.content.trim().length === 0;
|
|
1035
1119
|
return msg.content.length === 0;
|
|
1036
1120
|
}
|
|
1121
|
+
var init_message_invariants = __esm({
|
|
1122
|
+
"src/utils/message-invariants.ts"() {
|
|
1123
|
+
init_expect_defined();
|
|
1124
|
+
}
|
|
1125
|
+
});
|
|
1126
|
+
|
|
1127
|
+
// src/utils/newline-normalize.ts
|
|
1128
|
+
var init_newline_normalize = __esm({
|
|
1129
|
+
"src/utils/newline-normalize.ts"() {
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1037
1132
|
|
|
1038
1133
|
// src/utils/regex-guard.ts
|
|
1039
|
-
var MAX_PATTERN_LEN = 512;
|
|
1040
|
-
var DANGEROUS_PATTERNS = [
|
|
1041
|
-
/(\([^)]*[+*][^)]*\))[+*]/,
|
|
1042
|
-
// (a+)+, (.*)+, etc
|
|
1043
|
-
/(\(\?:[^)]*[+*][^)]*\))[+*]/
|
|
1044
|
-
// same, with non-capturing group
|
|
1045
|
-
];
|
|
1046
1134
|
function compileUserRegex(pattern, flags) {
|
|
1047
1135
|
if (typeof pattern !== "string") {
|
|
1048
1136
|
return { ok: false, reason: "pattern must be a string" };
|
|
@@ -1070,6 +1158,18 @@ function compileUserRegex(pattern, flags) {
|
|
|
1070
1158
|
};
|
|
1071
1159
|
}
|
|
1072
1160
|
}
|
|
1161
|
+
var MAX_PATTERN_LEN, DANGEROUS_PATTERNS;
|
|
1162
|
+
var init_regex_guard = __esm({
|
|
1163
|
+
"src/utils/regex-guard.ts"() {
|
|
1164
|
+
MAX_PATTERN_LEN = 512;
|
|
1165
|
+
DANGEROUS_PATTERNS = [
|
|
1166
|
+
/(\([^)]*[+*][^)]*\))[+*]/,
|
|
1167
|
+
// (a+)+, (.*)+, etc
|
|
1168
|
+
/(\(\?:[^)]*[+*][^)]*\))[+*]/
|
|
1169
|
+
// same, with non-capturing group
|
|
1170
|
+
];
|
|
1171
|
+
}
|
|
1172
|
+
});
|
|
1073
1173
|
|
|
1074
1174
|
// src/utils/safe-json.ts
|
|
1075
1175
|
function safeParse(input, maxBytes = 5e6) {
|
|
@@ -1085,15 +1185,44 @@ function safeParse(input, maxBytes = 5e6) {
|
|
|
1085
1185
|
};
|
|
1086
1186
|
}
|
|
1087
1187
|
}
|
|
1188
|
+
var init_safe_json = __esm({
|
|
1189
|
+
"src/utils/safe-json.ts"() {
|
|
1190
|
+
init_error();
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
function sessionScopedPath(dir, sessionId, suffix) {
|
|
1194
|
+
if (!sessionId || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
1195
|
+
throw invalid(sessionId);
|
|
1196
|
+
}
|
|
1197
|
+
const resolved = path4.resolve(dir, `${sessionId}${suffix}`);
|
|
1198
|
+
const rel = path4.relative(path4.resolve(dir), resolved);
|
|
1199
|
+
if (rel.startsWith("..") || path4.isAbsolute(rel)) {
|
|
1200
|
+
throw invalid(sessionId);
|
|
1201
|
+
}
|
|
1202
|
+
return resolved;
|
|
1203
|
+
}
|
|
1204
|
+
function invalid(sessionId) {
|
|
1205
|
+
return new FsError({
|
|
1206
|
+
message: `Invalid sessionId: ${sessionId}`,
|
|
1207
|
+
code: ERROR_CODES.FS_DELETE_FAILED,
|
|
1208
|
+
path: sessionId,
|
|
1209
|
+
context: { reason: "path_traversal" }
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
var init_session_scoped_path = __esm({
|
|
1213
|
+
"src/utils/session-scoped-path.ts"() {
|
|
1214
|
+
init_errors();
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1088
1217
|
|
|
1089
1218
|
// src/utils/slug.ts
|
|
1090
1219
|
function slugify(name, fallback = "prompt", maxLen = 64) {
|
|
1091
1220
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, maxLen).replace(/-+$/g, "") || fallback;
|
|
1092
1221
|
}
|
|
1093
|
-
var
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1222
|
+
var init_slug = __esm({
|
|
1223
|
+
"src/utils/slug.ts"() {
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1097
1226
|
function encodeTime(now, len) {
|
|
1098
1227
|
let mod;
|
|
1099
1228
|
let str = "";
|
|
@@ -1115,19 +1244,47 @@ function encodeRandom(len) {
|
|
|
1115
1244
|
function ulid(seedTime = Date.now()) {
|
|
1116
1245
|
return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN);
|
|
1117
1246
|
}
|
|
1247
|
+
var ENCODING, ENCODING_LEN, TIME_LEN, RANDOM_LEN;
|
|
1248
|
+
var init_ulid = __esm({
|
|
1249
|
+
"src/utils/ulid.ts"() {
|
|
1250
|
+
ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
1251
|
+
ENCODING_LEN = ENCODING.length;
|
|
1252
|
+
TIME_LEN = 10;
|
|
1253
|
+
RANDOM_LEN = 16;
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1118
1256
|
|
|
1119
1257
|
// src/utils/sleep.ts
|
|
1120
1258
|
function sleep(ms) {
|
|
1121
|
-
return new Promise((
|
|
1259
|
+
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
1122
1260
|
}
|
|
1261
|
+
var init_sleep = __esm({
|
|
1262
|
+
"src/utils/sleep.ts"() {
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1123
1265
|
|
|
1124
1266
|
// src/utils/string.ts
|
|
1125
1267
|
function truncate(s, max) {
|
|
1126
1268
|
return s.length <= max ? s : `${s.slice(0, max - 1)}\u2026`;
|
|
1127
1269
|
}
|
|
1270
|
+
var init_string = __esm({
|
|
1271
|
+
"src/utils/string.ts"() {
|
|
1272
|
+
}
|
|
1273
|
+
});
|
|
1274
|
+
|
|
1275
|
+
// src/utils/task-format.ts
|
|
1276
|
+
var init_task_format = __esm({
|
|
1277
|
+
"src/utils/task-format.ts"() {
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
// src/utils/todos-format.ts
|
|
1282
|
+
var init_todos_format = __esm({
|
|
1283
|
+
"src/utils/todos-format.ts"() {
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1128
1286
|
|
|
1129
1287
|
// src/utils/tool-subject.ts
|
|
1130
|
-
var GLOB_METACHARACTERS = /[*?[\]]/g;
|
|
1131
1288
|
function escapeGlobSubject(value) {
|
|
1132
1289
|
return value.replace(GLOB_METACHARACTERS, (char) => `\\${char}`);
|
|
1133
1290
|
}
|
|
@@ -1160,11 +1317,14 @@ function subjectForToolInput(toolName, input, subjectKey) {
|
|
|
1160
1317
|
}
|
|
1161
1318
|
return void 0;
|
|
1162
1319
|
}
|
|
1320
|
+
var GLOB_METACHARACTERS;
|
|
1321
|
+
var init_tool_subject = __esm({
|
|
1322
|
+
"src/utils/tool-subject.ts"() {
|
|
1323
|
+
GLOB_METACHARACTERS = /[*?[\]]/g;
|
|
1324
|
+
}
|
|
1325
|
+
});
|
|
1163
1326
|
|
|
1164
1327
|
// src/utils/tool-wire-compact.ts
|
|
1165
|
-
var TOOL_DESCRIPTION_MAX_CHARS = 640;
|
|
1166
|
-
var SCHEMA_DESCRIPTION_MAX_CHARS = 180;
|
|
1167
|
-
var compactCache = /* @__PURE__ */ new WeakMap();
|
|
1168
1328
|
function compactToolDefinitionForWire(tool, opts = {}) {
|
|
1169
1329
|
const useDefaultOptions = opts.descriptionMaxChars === void 0 && opts.schemaDescriptionMaxChars === void 0;
|
|
1170
1330
|
if (useDefaultOptions && typeof tool === "object" && tool !== null) {
|
|
@@ -1230,11 +1390,16 @@ function findSemanticBoundary(text, limit) {
|
|
|
1230
1390
|
function isRecord(value) {
|
|
1231
1391
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
1232
1392
|
}
|
|
1393
|
+
var TOOL_DESCRIPTION_MAX_CHARS, SCHEMA_DESCRIPTION_MAX_CHARS, compactCache;
|
|
1394
|
+
var init_tool_wire_compact = __esm({
|
|
1395
|
+
"src/utils/tool-wire-compact.ts"() {
|
|
1396
|
+
TOOL_DESCRIPTION_MAX_CHARS = 640;
|
|
1397
|
+
SCHEMA_DESCRIPTION_MAX_CHARS = 180;
|
|
1398
|
+
compactCache = /* @__PURE__ */ new WeakMap();
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1233
1401
|
|
|
1234
1402
|
// src/utils/token-estimate.ts
|
|
1235
|
-
var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
|
|
1236
|
-
var CALIBRATION_GLOBAL_KEY = "__global__";
|
|
1237
|
-
var _cals = /* @__PURE__ */ new Map();
|
|
1238
1403
|
function calState(key) {
|
|
1239
1404
|
let state = _cals.get(key);
|
|
1240
1405
|
if (!state) {
|
|
@@ -1243,21 +1408,6 @@ function calState(key) {
|
|
|
1243
1408
|
}
|
|
1244
1409
|
return state;
|
|
1245
1410
|
}
|
|
1246
|
-
var MIN_SAMPLES_FOR_CALIBRATION = 3;
|
|
1247
|
-
var MODEL_FAMILY_RATIO = {
|
|
1248
|
-
// Anthropic: ~3.8-4.0 chars/token depending on model
|
|
1249
|
-
claude: 3.8,
|
|
1250
|
-
// OpenAI: ~4.0 chars/token
|
|
1251
|
-
"gpt-4": 4,
|
|
1252
|
-
"gpt-3.5": 4,
|
|
1253
|
-
// Google: ~3.5 chars/token
|
|
1254
|
-
gemini: 3.5,
|
|
1255
|
-
// DeepSeek: ~3.5 chars/token
|
|
1256
|
-
deepseek: 3.5
|
|
1257
|
-
};
|
|
1258
|
-
var ESTIMATE_CACHE = /* @__PURE__ */ new Map();
|
|
1259
|
-
var _estimateCacheOrder = [];
|
|
1260
|
-
var ESTIMATE_CACHE_MAX_SIZE = 5e4;
|
|
1261
1411
|
function getCachedEstimate(key, compute) {
|
|
1262
1412
|
const existing = ESTIMATE_CACHE.get(key);
|
|
1263
1413
|
if (existing !== void 0) return existing;
|
|
@@ -1404,17 +1554,32 @@ function getModelFamilyRatio(calibrationKey) {
|
|
|
1404
1554
|
}
|
|
1405
1555
|
return null;
|
|
1406
1556
|
}
|
|
1557
|
+
var RoughTokenEstimate, CALIBRATION_GLOBAL_KEY, _cals, MIN_SAMPLES_FOR_CALIBRATION, MODEL_FAMILY_RATIO, ESTIMATE_CACHE, _estimateCacheOrder, ESTIMATE_CACHE_MAX_SIZE;
|
|
1558
|
+
var init_token_estimate = __esm({
|
|
1559
|
+
"src/utils/token-estimate.ts"() {
|
|
1560
|
+
init_tool_wire_compact();
|
|
1561
|
+
RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
|
|
1562
|
+
CALIBRATION_GLOBAL_KEY = "__global__";
|
|
1563
|
+
_cals = /* @__PURE__ */ new Map();
|
|
1564
|
+
MIN_SAMPLES_FOR_CALIBRATION = 3;
|
|
1565
|
+
MODEL_FAMILY_RATIO = {
|
|
1566
|
+
// Anthropic: ~3.8-4.0 chars/token depending on model
|
|
1567
|
+
claude: 3.8,
|
|
1568
|
+
// OpenAI: ~4.0 chars/token
|
|
1569
|
+
"gpt-4": 4,
|
|
1570
|
+
"gpt-3.5": 4,
|
|
1571
|
+
// Google: ~3.5 chars/token
|
|
1572
|
+
gemini: 3.5,
|
|
1573
|
+
// DeepSeek: ~3.5 chars/token
|
|
1574
|
+
deepseek: 3.5
|
|
1575
|
+
};
|
|
1576
|
+
ESTIMATE_CACHE = /* @__PURE__ */ new Map();
|
|
1577
|
+
_estimateCacheOrder = [];
|
|
1578
|
+
ESTIMATE_CACHE_MAX_SIZE = 5e4;
|
|
1579
|
+
}
|
|
1580
|
+
});
|
|
1407
1581
|
|
|
1408
1582
|
// src/utils/tool-output-serializer.ts
|
|
1409
|
-
var DEFAULT_LIST_LIMIT = 500;
|
|
1410
|
-
var LOG_ENTRY_LIMIT = 200;
|
|
1411
|
-
var INLINE_LIMIT = 240;
|
|
1412
|
-
var GREP_FILE_LIMIT = 80;
|
|
1413
|
-
var GREP_MATCHES_PER_FILE = 3;
|
|
1414
|
-
var DIFF_INLINE_LINE_LIMIT = 260;
|
|
1415
|
-
var DIFF_HUNK_LIMIT = 8;
|
|
1416
|
-
var DIFF_HUNK_CONTEXT = 14;
|
|
1417
|
-
var GREP_LINE_RE = /^(.+?):(\d+):(.*)$/;
|
|
1418
1583
|
function createToolOutputSerializer(opts = {}) {
|
|
1419
1584
|
const capBytes = opts.perIterationOutputCapBytes ?? 1e5;
|
|
1420
1585
|
function serialize(value, context = {}) {
|
|
@@ -2062,9 +2227,22 @@ function isRecord2(value) {
|
|
|
2062
2227
|
function isScalar(value) {
|
|
2063
2228
|
return value === null || ["string", "number", "boolean"].includes(typeof value);
|
|
2064
2229
|
}
|
|
2230
|
+
var DEFAULT_LIST_LIMIT, LOG_ENTRY_LIMIT, INLINE_LIMIT, GREP_FILE_LIMIT, GREP_MATCHES_PER_FILE, DIFF_INLINE_LINE_LIMIT, DIFF_HUNK_LIMIT, DIFF_HUNK_CONTEXT, GREP_LINE_RE;
|
|
2231
|
+
var init_tool_output_serializer = __esm({
|
|
2232
|
+
"src/utils/tool-output-serializer.ts"() {
|
|
2233
|
+
DEFAULT_LIST_LIMIT = 500;
|
|
2234
|
+
LOG_ENTRY_LIMIT = 200;
|
|
2235
|
+
INLINE_LIMIT = 240;
|
|
2236
|
+
GREP_FILE_LIMIT = 80;
|
|
2237
|
+
GREP_MATCHES_PER_FILE = 3;
|
|
2238
|
+
DIFF_INLINE_LINE_LIMIT = 260;
|
|
2239
|
+
DIFF_HUNK_LIMIT = 8;
|
|
2240
|
+
DIFF_HUNK_CONTEXT = 14;
|
|
2241
|
+
GREP_LINE_RE = /^(.+?):(\d+):(.*)$/;
|
|
2242
|
+
}
|
|
2243
|
+
});
|
|
2065
2244
|
|
|
2066
2245
|
// src/utils/tool-result-render-mode.ts
|
|
2067
|
-
var DEFAULT_TOOL_RESULT_RENDER_MODE = "extend";
|
|
2068
2246
|
function normalizeToolResultRenderMode(value) {
|
|
2069
2247
|
if (typeof value !== "string") return void 0;
|
|
2070
2248
|
const raw = value.trim().toLowerCase();
|
|
@@ -2075,12 +2253,18 @@ function normalizeToolResultRenderMode(value) {
|
|
|
2075
2253
|
function resolveToolResultRenderMode(modes, toolName) {
|
|
2076
2254
|
return normalizeToolResultRenderMode(modes?.[toolName]) ?? DEFAULT_TOOL_RESULT_RENDER_MODE;
|
|
2077
2255
|
}
|
|
2256
|
+
var DEFAULT_TOOL_RESULT_RENDER_MODE;
|
|
2257
|
+
var init_tool_result_render_mode = __esm({
|
|
2258
|
+
"src/utils/tool-result-render-mode.ts"() {
|
|
2259
|
+
DEFAULT_TOOL_RESULT_RENDER_MODE = "extend";
|
|
2260
|
+
}
|
|
2261
|
+
});
|
|
2078
2262
|
function projectHash(absRoot) {
|
|
2079
|
-
return createHash("sha256").update(
|
|
2263
|
+
return createHash("sha256").update(path4.resolve(absRoot)).digest("hex").slice(0, 12);
|
|
2080
2264
|
}
|
|
2081
2265
|
function projectSlug(absRoot) {
|
|
2082
|
-
const base = slugify2(
|
|
2083
|
-
const hash = createHash("sha256").update(
|
|
2266
|
+
const base = slugify2(path4.basename(absRoot));
|
|
2267
|
+
const hash = createHash("sha256").update(path4.resolve(absRoot)).digest("hex").slice(0, 6);
|
|
2084
2268
|
return `${base}-${hash}`;
|
|
2085
2269
|
}
|
|
2086
2270
|
function slugify2(name) {
|
|
@@ -2088,170 +2272,91 @@ function slugify2(name) {
|
|
|
2088
2272
|
}
|
|
2089
2273
|
function wstackGlobalRoot() {
|
|
2090
2274
|
const fromEnv = process.env["WRONGSTACK_HOME"];
|
|
2091
|
-
if (fromEnv && fromEnv.trim().length > 0) return
|
|
2092
|
-
return
|
|
2275
|
+
if (fromEnv && fromEnv.trim().length > 0) return path4.resolve(fromEnv);
|
|
2276
|
+
return path4.join(os.homedir(), ".wrongstack");
|
|
2093
2277
|
}
|
|
2094
2278
|
function resolveWstackPaths(opts) {
|
|
2095
|
-
const globalRoot = opts.globalRoot ?? (opts.userHome ?
|
|
2279
|
+
const globalRoot = opts.globalRoot ?? (opts.userHome ? path4.join(opts.userHome, ".wrongstack") : wstackGlobalRoot());
|
|
2096
2280
|
const hash = projectHash(opts.projectRoot);
|
|
2097
2281
|
const slug = projectSlug(opts.projectRoot);
|
|
2098
|
-
const projectDir =
|
|
2282
|
+
const projectDir = path4.join(globalRoot, "projects", slug);
|
|
2099
2283
|
return {
|
|
2100
2284
|
globalRoot,
|
|
2101
2285
|
configDir: globalRoot,
|
|
2102
|
-
globalConfig:
|
|
2103
|
-
secretsKey:
|
|
2104
|
-
globalMemory:
|
|
2105
|
-
globalSkills:
|
|
2106
|
-
globalDesignKits:
|
|
2107
|
-
globalPrompts:
|
|
2108
|
-
globalInstructions:
|
|
2109
|
-
promptUsage:
|
|
2110
|
-
cacheDir:
|
|
2111
|
-
modelsCache:
|
|
2112
|
-
modelsOverlayCache:
|
|
2113
|
-
historyFile:
|
|
2114
|
-
logFile:
|
|
2286
|
+
globalConfig: path4.join(globalRoot, "config.json"),
|
|
2287
|
+
secretsKey: path4.join(globalRoot, ".key"),
|
|
2288
|
+
globalMemory: path4.join(globalRoot, "memory.md"),
|
|
2289
|
+
globalSkills: path4.join(globalRoot, "skills"),
|
|
2290
|
+
globalDesignKits: path4.join(globalRoot, "design-kits"),
|
|
2291
|
+
globalPrompts: path4.join(globalRoot, "prompts"),
|
|
2292
|
+
globalInstructions: path4.join(globalRoot, "instructions"),
|
|
2293
|
+
promptUsage: path4.join(globalRoot, "prompt-usage.json"),
|
|
2294
|
+
cacheDir: path4.join(globalRoot, "cache"),
|
|
2295
|
+
modelsCache: path4.join(globalRoot, "cache", "models.dev.json"),
|
|
2296
|
+
modelsOverlayCache: path4.join(globalRoot, "cache", "models-overlay.json"),
|
|
2297
|
+
historyFile: path4.join(globalRoot, "history"),
|
|
2298
|
+
logFile: path4.join(globalRoot, "logs", "wrongstack.log"),
|
|
2115
2299
|
projectDir,
|
|
2116
|
-
projectCodebaseIndex:
|
|
2117
|
-
projectMemory:
|
|
2118
|
-
projectSessions:
|
|
2119
|
-
projectTrust:
|
|
2120
|
-
projectMeta:
|
|
2121
|
-
projectLocalConfig:
|
|
2122
|
-
inProjectConfig:
|
|
2123
|
-
inProjectAgentsFile:
|
|
2124
|
-
inProjectSkills:
|
|
2125
|
-
inProjectPrompts:
|
|
2126
|
-
inProjectInstructions:
|
|
2127
|
-
inProjectDesignKits:
|
|
2128
|
-
inProjectWorktrees:
|
|
2300
|
+
projectCodebaseIndex: path4.join(projectDir, "codebase-index"),
|
|
2301
|
+
projectMemory: path4.join(projectDir, "memory.md"),
|
|
2302
|
+
projectSessions: path4.join(projectDir, "sessions"),
|
|
2303
|
+
projectTrust: path4.join(projectDir, "trust.json"),
|
|
2304
|
+
projectMeta: path4.join(projectDir, "meta.json"),
|
|
2305
|
+
projectLocalConfig: path4.join(projectDir, "config.local.json"),
|
|
2306
|
+
inProjectConfig: path4.join(opts.projectRoot, ".wrongstack", "config.json"),
|
|
2307
|
+
inProjectAgentsFile: path4.join(opts.projectRoot, ".wrongstack", "AGENTS.md"),
|
|
2308
|
+
inProjectSkills: path4.join(opts.projectRoot, ".wrongstack", "skills"),
|
|
2309
|
+
inProjectPrompts: path4.join(opts.projectRoot, ".wrongstack", "prompts"),
|
|
2310
|
+
inProjectInstructions: path4.join(opts.projectRoot, ".wrongstack", "instructions"),
|
|
2311
|
+
inProjectDesignKits: path4.join(opts.projectRoot, ".wrongstack", "design-kits"),
|
|
2312
|
+
inProjectWorktrees: path4.join(opts.projectRoot, ".wrongstack", "worktrees"),
|
|
2129
2313
|
projectHash: hash,
|
|
2130
2314
|
projectSlug: slug,
|
|
2131
|
-
projectGoal:
|
|
2132
|
-
projectSpecs:
|
|
2133
|
-
projectTaskGraphs:
|
|
2134
|
-
projectSddSession:
|
|
2135
|
-
projectPlan:
|
|
2136
|
-
projectAutophase:
|
|
2137
|
-
projectSddBoards:
|
|
2138
|
-
syncConfig:
|
|
2139
|
-
projectStatus: (projectHash2) =>
|
|
2315
|
+
projectGoal: path4.join(projectDir, "goal.json"),
|
|
2316
|
+
projectSpecs: path4.join(projectDir, "specs"),
|
|
2317
|
+
projectTaskGraphs: path4.join(projectDir, "task-graphs"),
|
|
2318
|
+
projectSddSession: path4.join(projectDir, "sdd-session.json"),
|
|
2319
|
+
projectPlan: path4.join(projectDir, "plan.json"),
|
|
2320
|
+
projectAutophase: path4.join(projectDir, "autophase"),
|
|
2321
|
+
projectSddBoards: path4.join(projectDir, "sdd-boards"),
|
|
2322
|
+
syncConfig: path4.join(globalRoot, "sync.json"),
|
|
2323
|
+
projectStatus: (projectHash2) => path4.join(globalRoot, "projects", projectHash2, "status.json")
|
|
2140
2324
|
};
|
|
2141
2325
|
}
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
var ERROR_CODES = {
|
|
2145
|
-
// Provider
|
|
2146
|
-
PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
|
|
2147
|
-
PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
|
|
2148
|
-
PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
|
|
2149
|
-
PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
|
|
2150
|
-
PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
|
|
2151
|
-
PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR",
|
|
2152
|
-
PROVIDER_CONTEXT_OVERFLOW: "PROVIDER_CONTEXT_OVERFLOW",
|
|
2153
|
-
// Tool
|
|
2154
|
-
TOOL_NOT_FOUND: "TOOL_NOT_FOUND",
|
|
2155
|
-
TOOL_PERMISSION_DENIED: "TOOL_PERMISSION_DENIED",
|
|
2156
|
-
TOOL_EXECUTION_FAILED: "TOOL_EXECUTION_FAILED",
|
|
2157
|
-
TOOL_TIMEOUT: "TOOL_TIMEOUT",
|
|
2158
|
-
TOOL_INPUT_INVALID: "TOOL_INPUT_INVALID",
|
|
2159
|
-
// Config
|
|
2160
|
-
CONFIG_INVALID: "CONFIG_INVALID",
|
|
2161
|
-
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
2162
|
-
CONFIG_PARSE_FAILED: "CONFIG_PARSE_FAILED",
|
|
2163
|
-
CONFIG_MIGRATION_NEEDED: "CONFIG_MIGRATION_NEEDED",
|
|
2164
|
-
// Plugin
|
|
2165
|
-
PLUGIN_LOAD_FAILED: "PLUGIN_LOAD_FAILED",
|
|
2166
|
-
PLUGIN_API_MISMATCH: "PLUGIN_API_MISMATCH",
|
|
2167
|
-
PLUGIN_MISSING_DEPENDENCY: "PLUGIN_MISSING_DEPENDENCY",
|
|
2168
|
-
// Agent
|
|
2169
|
-
AGENT_ITERATION_LIMIT: "AGENT_ITERATION_LIMIT",
|
|
2170
|
-
AGENT_CONTEXT_OVERFLOW: "AGENT_CONTEXT_OVERFLOW",
|
|
2171
|
-
AGENT_ABORTED: "AGENT_ABORTED",
|
|
2172
|
-
AGENT_RUN_FAILED: "AGENT_RUN_FAILED",
|
|
2173
|
-
// Session
|
|
2174
|
-
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
2175
|
-
SESSION_CORRUPTED: "SESSION_CORRUPTED",
|
|
2176
|
-
SESSION_WRITE_FAILED: "SESSION_WRITE_FAILED",
|
|
2177
|
-
// Container / Registry
|
|
2178
|
-
CONTAINER_TOKEN_ALREADY_BOUND: "CONTAINER_TOKEN_ALREADY_BOUND",
|
|
2179
|
-
CONTAINER_TOKEN_NOT_BOUND: "CONTAINER_TOKEN_NOT_BOUND",
|
|
2180
|
-
CONTAINER_CIRCULAR_DEPENDENCY: "CONTAINER_CIRCULAR_DEPENDENCY",
|
|
2181
|
-
REGISTRY_DUPLICATE: "REGISTRY_DUPLICATE",
|
|
2182
|
-
REGISTRY_NOT_FOUND: "REGISTRY_NOT_FOUND",
|
|
2183
|
-
REGISTRY_INVALID: "REGISTRY_INVALID",
|
|
2184
|
-
// File system
|
|
2185
|
-
FS_READ_FAILED: "FS_READ_FAILED",
|
|
2186
|
-
FS_WRITE_FAILED: "FS_WRITE_FAILED",
|
|
2187
|
-
FS_MKDIR_FAILED: "FS_MKDIR_FAILED",
|
|
2188
|
-
FS_DELETE_FAILED: "FS_DELETE_FAILED",
|
|
2189
|
-
FS_ATOMIC_WRITE_FAILED: "FS_ATOMIC_WRITE_FAILED",
|
|
2190
|
-
// SDD (Spec-Driven Development)
|
|
2191
|
-
SDD_VALIDATION_FAILED: "SDD_VALIDATION_FAILED",
|
|
2192
|
-
SDD_PARSE_FAILED: "SDD_PARSE_FAILED",
|
|
2193
|
-
SDD_INVALID_STATE: "SDD_INVALID_STATE",
|
|
2194
|
-
SDD_NOT_READY: "SDD_NOT_READY",
|
|
2195
|
-
// General
|
|
2196
|
-
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
2197
|
-
UNKNOWN: "UNKNOWN"
|
|
2198
|
-
};
|
|
2199
|
-
var WrongStackError = class extends Error {
|
|
2200
|
-
code;
|
|
2201
|
-
subsystem;
|
|
2202
|
-
severity;
|
|
2203
|
-
recoverable;
|
|
2204
|
-
context;
|
|
2205
|
-
constructor(opts) {
|
|
2206
|
-
super(opts.message, { cause: opts.cause });
|
|
2207
|
-
this.name = "WrongStackError";
|
|
2208
|
-
this.code = opts.code;
|
|
2209
|
-
this.subsystem = opts.subsystem;
|
|
2210
|
-
this.severity = opts.severity ?? "error";
|
|
2211
|
-
this.recoverable = opts.recoverable ?? false;
|
|
2212
|
-
this.context = opts.context;
|
|
2326
|
+
var init_wstack_paths = __esm({
|
|
2327
|
+
"src/utils/wstack-paths.ts"() {
|
|
2213
2328
|
}
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2329
|
+
});
|
|
2330
|
+
|
|
2331
|
+
// src/utils/index.ts
|
|
2332
|
+
var init_utils = __esm({
|
|
2333
|
+
"src/utils/index.ts"() {
|
|
2334
|
+
init_assert_never();
|
|
2335
|
+
init_atomic_write();
|
|
2336
|
+
init_child_env();
|
|
2337
|
+
init_color();
|
|
2338
|
+
init_config_json();
|
|
2339
|
+
init_diff();
|
|
2340
|
+
init_error();
|
|
2341
|
+
init_expect_defined();
|
|
2342
|
+
init_glob_match();
|
|
2343
|
+
init_newline_normalize();
|
|
2344
|
+
init_safe_json();
|
|
2345
|
+
init_sleep();
|
|
2346
|
+
init_string();
|
|
2347
|
+
init_task_format();
|
|
2348
|
+
init_term();
|
|
2349
|
+
init_todos_format();
|
|
2350
|
+
init_tool_subject();
|
|
2351
|
+
init_wstack_paths();
|
|
2221
2352
|
}
|
|
2222
|
-
};
|
|
2353
|
+
});
|
|
2354
|
+
|
|
2355
|
+
// src/types/errors.ts
|
|
2223
2356
|
function formatContext(ctx) {
|
|
2224
2357
|
const parts = Object.entries(ctx).filter(([, v]) => v !== void 0).slice(0, 3).map(([k, v]) => `${k}=${String(v)}`);
|
|
2225
2358
|
return parts.length > 0 ? `[${parts.join(" ")}]` : "";
|
|
2226
2359
|
}
|
|
2227
|
-
var ConfigError = class extends WrongStackError {
|
|
2228
|
-
constructor(opts) {
|
|
2229
|
-
super({
|
|
2230
|
-
message: opts.message,
|
|
2231
|
-
code: opts.code,
|
|
2232
|
-
subsystem: "config",
|
|
2233
|
-
severity: "fatal",
|
|
2234
|
-
recoverable: false,
|
|
2235
|
-
context: opts.context,
|
|
2236
|
-
cause: opts.cause
|
|
2237
|
-
});
|
|
2238
|
-
this.name = "ConfigError";
|
|
2239
|
-
}
|
|
2240
|
-
};
|
|
2241
|
-
var AgentError = class extends WrongStackError {
|
|
2242
|
-
constructor(opts) {
|
|
2243
|
-
super({
|
|
2244
|
-
message: opts.message,
|
|
2245
|
-
code: opts.code,
|
|
2246
|
-
subsystem: "agent",
|
|
2247
|
-
severity: opts.code === ERROR_CODES.AGENT_ABORTED ? "warning" : "error",
|
|
2248
|
-
recoverable: opts.recoverable ?? opts.code === ERROR_CODES.AGENT_ITERATION_LIMIT,
|
|
2249
|
-
context: opts.context,
|
|
2250
|
-
cause: opts.cause
|
|
2251
|
-
});
|
|
2252
|
-
this.name = "AgentError";
|
|
2253
|
-
}
|
|
2254
|
-
};
|
|
2255
2360
|
function toWrongStackError(err, code = ERROR_CODES.AGENT_RUN_FAILED) {
|
|
2256
2361
|
if (err instanceof WrongStackError) return err;
|
|
2257
2362
|
const message = toErrorMessage(err);
|
|
@@ -2261,66 +2366,201 @@ function toWrongStackError(err, code = ERROR_CODES.AGENT_RUN_FAILED) {
|
|
|
2261
2366
|
cause: err
|
|
2262
2367
|
});
|
|
2263
2368
|
}
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2369
|
+
function isWrongStackError(err) {
|
|
2370
|
+
return err instanceof WrongStackError;
|
|
2371
|
+
}
|
|
2372
|
+
var ERROR_CODES, WrongStackError, ToolError, ConfigError, AgentError, SddError, FsError, FetchError, ToolValidationError;
|
|
2373
|
+
var init_errors = __esm({
|
|
2374
|
+
"src/types/errors.ts"() {
|
|
2375
|
+
init_utils();
|
|
2376
|
+
ERROR_CODES = {
|
|
2377
|
+
// Provider
|
|
2378
|
+
PROVIDER_RATE_LIMITED: "PROVIDER_RATE_LIMITED",
|
|
2379
|
+
PROVIDER_AUTH_FAILED: "PROVIDER_AUTH_FAILED",
|
|
2380
|
+
PROVIDER_OVERLOADED: "PROVIDER_OVERLOADED",
|
|
2381
|
+
PROVIDER_INVALID_REQUEST: "PROVIDER_INVALID_REQUEST",
|
|
2382
|
+
PROVIDER_SERVER_ERROR: "PROVIDER_SERVER_ERROR",
|
|
2383
|
+
PROVIDER_NETWORK_ERROR: "PROVIDER_NETWORK_ERROR",
|
|
2384
|
+
PROVIDER_CONTEXT_OVERFLOW: "PROVIDER_CONTEXT_OVERFLOW",
|
|
2385
|
+
// Tool
|
|
2386
|
+
TOOL_NOT_FOUND: "TOOL_NOT_FOUND",
|
|
2387
|
+
TOOL_PERMISSION_DENIED: "TOOL_PERMISSION_DENIED",
|
|
2388
|
+
TOOL_EXECUTION_FAILED: "TOOL_EXECUTION_FAILED",
|
|
2389
|
+
TOOL_TIMEOUT: "TOOL_TIMEOUT",
|
|
2390
|
+
TOOL_INPUT_INVALID: "TOOL_INPUT_INVALID",
|
|
2391
|
+
// Config
|
|
2392
|
+
CONFIG_INVALID: "CONFIG_INVALID",
|
|
2393
|
+
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
2394
|
+
CONFIG_PARSE_FAILED: "CONFIG_PARSE_FAILED",
|
|
2395
|
+
CONFIG_MIGRATION_NEEDED: "CONFIG_MIGRATION_NEEDED",
|
|
2396
|
+
// Plugin
|
|
2397
|
+
PLUGIN_LOAD_FAILED: "PLUGIN_LOAD_FAILED",
|
|
2398
|
+
PLUGIN_API_MISMATCH: "PLUGIN_API_MISMATCH",
|
|
2399
|
+
PLUGIN_MISSING_DEPENDENCY: "PLUGIN_MISSING_DEPENDENCY",
|
|
2400
|
+
// Agent
|
|
2401
|
+
AGENT_ITERATION_LIMIT: "AGENT_ITERATION_LIMIT",
|
|
2402
|
+
AGENT_CONTEXT_OVERFLOW: "AGENT_CONTEXT_OVERFLOW",
|
|
2403
|
+
AGENT_ABORTED: "AGENT_ABORTED",
|
|
2404
|
+
AGENT_RUN_FAILED: "AGENT_RUN_FAILED",
|
|
2405
|
+
// Session
|
|
2406
|
+
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
2407
|
+
SESSION_CORRUPTED: "SESSION_CORRUPTED",
|
|
2408
|
+
SESSION_WRITE_FAILED: "SESSION_WRITE_FAILED",
|
|
2409
|
+
// Container / Registry
|
|
2410
|
+
CONTAINER_TOKEN_ALREADY_BOUND: "CONTAINER_TOKEN_ALREADY_BOUND",
|
|
2411
|
+
CONTAINER_TOKEN_NOT_BOUND: "CONTAINER_TOKEN_NOT_BOUND",
|
|
2412
|
+
CONTAINER_CIRCULAR_DEPENDENCY: "CONTAINER_CIRCULAR_DEPENDENCY",
|
|
2413
|
+
REGISTRY_DUPLICATE: "REGISTRY_DUPLICATE",
|
|
2414
|
+
REGISTRY_NOT_FOUND: "REGISTRY_NOT_FOUND",
|
|
2415
|
+
REGISTRY_INVALID: "REGISTRY_INVALID",
|
|
2416
|
+
// File system
|
|
2417
|
+
FS_READ_FAILED: "FS_READ_FAILED",
|
|
2418
|
+
FS_WRITE_FAILED: "FS_WRITE_FAILED",
|
|
2419
|
+
FS_MKDIR_FAILED: "FS_MKDIR_FAILED",
|
|
2420
|
+
FS_DELETE_FAILED: "FS_DELETE_FAILED",
|
|
2421
|
+
FS_ATOMIC_WRITE_FAILED: "FS_ATOMIC_WRITE_FAILED",
|
|
2422
|
+
// SDD (Spec-Driven Development)
|
|
2423
|
+
SDD_VALIDATION_FAILED: "SDD_VALIDATION_FAILED",
|
|
2424
|
+
SDD_PARSE_FAILED: "SDD_PARSE_FAILED",
|
|
2425
|
+
SDD_INVALID_STATE: "SDD_INVALID_STATE",
|
|
2426
|
+
SDD_NOT_READY: "SDD_NOT_READY",
|
|
2427
|
+
// General
|
|
2428
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
2429
|
+
PARSE_FAILED: "PARSE_FAILED",
|
|
2430
|
+
UNKNOWN: "UNKNOWN"
|
|
2431
|
+
};
|
|
2432
|
+
WrongStackError = class extends Error {
|
|
2433
|
+
code;
|
|
2434
|
+
subsystem;
|
|
2435
|
+
severity;
|
|
2436
|
+
recoverable;
|
|
2437
|
+
context;
|
|
2438
|
+
constructor(opts) {
|
|
2439
|
+
super(opts.message, { cause: opts.cause });
|
|
2440
|
+
this.name = "WrongStackError";
|
|
2441
|
+
this.code = opts.code;
|
|
2442
|
+
this.subsystem = opts.subsystem;
|
|
2443
|
+
this.severity = opts.severity ?? "error";
|
|
2444
|
+
this.recoverable = opts.recoverable ?? false;
|
|
2445
|
+
this.context = opts.context;
|
|
2446
|
+
}
|
|
2447
|
+
/**
|
|
2448
|
+
* Render a one-line user-facing description.
|
|
2449
|
+
* Subclasses should override for domain-specific formatting.
|
|
2450
|
+
*/
|
|
2451
|
+
describe() {
|
|
2452
|
+
const ctx = this.context ? ` ${formatContext(this.context)}` : "";
|
|
2453
|
+
return `${this.code}: ${this.message}${ctx}`;
|
|
2454
|
+
}
|
|
2455
|
+
};
|
|
2456
|
+
ToolError = class extends WrongStackError {
|
|
2457
|
+
toolName;
|
|
2458
|
+
constructor(opts) {
|
|
2459
|
+
super({
|
|
2460
|
+
message: opts.message,
|
|
2461
|
+
code: opts.code,
|
|
2462
|
+
subsystem: "tool",
|
|
2463
|
+
recoverable: opts.recoverable,
|
|
2464
|
+
context: { tool: opts.toolName, ...opts.context },
|
|
2465
|
+
cause: opts.cause
|
|
2466
|
+
});
|
|
2467
|
+
this.name = "ToolError";
|
|
2468
|
+
this.toolName = opts.toolName;
|
|
2469
|
+
}
|
|
2470
|
+
};
|
|
2471
|
+
ConfigError = class extends WrongStackError {
|
|
2472
|
+
constructor(opts) {
|
|
2473
|
+
super({
|
|
2474
|
+
message: opts.message,
|
|
2475
|
+
code: opts.code,
|
|
2476
|
+
subsystem: "config",
|
|
2477
|
+
severity: "fatal",
|
|
2478
|
+
recoverable: false,
|
|
2479
|
+
context: opts.context,
|
|
2480
|
+
cause: opts.cause
|
|
2481
|
+
});
|
|
2482
|
+
this.name = "ConfigError";
|
|
2483
|
+
}
|
|
2484
|
+
};
|
|
2485
|
+
AgentError = class extends WrongStackError {
|
|
2486
|
+
constructor(opts) {
|
|
2487
|
+
super({
|
|
2488
|
+
message: opts.message,
|
|
2489
|
+
code: opts.code,
|
|
2490
|
+
subsystem: "agent",
|
|
2491
|
+
severity: opts.code === ERROR_CODES.AGENT_ABORTED ? "warning" : "error",
|
|
2492
|
+
recoverable: opts.recoverable ?? opts.code === ERROR_CODES.AGENT_ITERATION_LIMIT,
|
|
2493
|
+
context: opts.context,
|
|
2494
|
+
cause: opts.cause
|
|
2495
|
+
});
|
|
2496
|
+
this.name = "AgentError";
|
|
2497
|
+
}
|
|
2498
|
+
};
|
|
2499
|
+
SddError = class extends WrongStackError {
|
|
2500
|
+
constructor(opts) {
|
|
2501
|
+
super({
|
|
2502
|
+
message: opts.message,
|
|
2503
|
+
code: opts.code,
|
|
2504
|
+
subsystem: "sdd",
|
|
2505
|
+
severity: opts.code === ERROR_CODES.SDD_PARSE_FAILED ? "warning" : "error",
|
|
2506
|
+
recoverable: opts.code === ERROR_CODES.SDD_NOT_READY,
|
|
2507
|
+
context: opts.context,
|
|
2508
|
+
cause: opts.cause
|
|
2509
|
+
});
|
|
2510
|
+
this.name = "SddError";
|
|
2511
|
+
}
|
|
2512
|
+
};
|
|
2513
|
+
FsError = class extends WrongStackError {
|
|
2514
|
+
path;
|
|
2515
|
+
constructor(opts) {
|
|
2516
|
+
super({
|
|
2517
|
+
message: opts.message,
|
|
2518
|
+
code: opts.code,
|
|
2519
|
+
subsystem: "fs",
|
|
2520
|
+
severity: "error",
|
|
2521
|
+
recoverable: opts.code !== ERROR_CODES.FS_READ_FAILED,
|
|
2522
|
+
context: { path: opts.path, ...opts.context },
|
|
2523
|
+
cause: opts.cause
|
|
2524
|
+
});
|
|
2525
|
+
this.name = "FsError";
|
|
2526
|
+
this.path = opts.path;
|
|
2527
|
+
}
|
|
2528
|
+
};
|
|
2529
|
+
FetchError = class extends WrongStackError {
|
|
2530
|
+
status;
|
|
2531
|
+
constructor(opts) {
|
|
2532
|
+
super({
|
|
2533
|
+
message: opts.message,
|
|
2534
|
+
code: ERROR_CODES.VALIDATION_ERROR,
|
|
2535
|
+
subsystem: "general",
|
|
2536
|
+
severity: "error",
|
|
2537
|
+
recoverable: opts.status === 429 || opts.status >= 500,
|
|
2538
|
+
context: { status: opts.status, ...opts.context },
|
|
2539
|
+
cause: opts.cause
|
|
2540
|
+
});
|
|
2541
|
+
this.name = "FetchError";
|
|
2542
|
+
this.status = opts.status;
|
|
2543
|
+
}
|
|
2544
|
+
};
|
|
2545
|
+
ToolValidationError = class extends WrongStackError {
|
|
2546
|
+
constructor(opts) {
|
|
2547
|
+
super({
|
|
2548
|
+
message: opts.message,
|
|
2549
|
+
code: ERROR_CODES.VALIDATION_ERROR,
|
|
2550
|
+
subsystem: "general",
|
|
2551
|
+
severity: "error",
|
|
2552
|
+
recoverable: false,
|
|
2553
|
+
context: { field: opts.field, ...opts.context },
|
|
2554
|
+
cause: opts.cause
|
|
2555
|
+
});
|
|
2556
|
+
this.name = "ToolValidationError";
|
|
2557
|
+
}
|
|
2558
|
+
};
|
|
2322
2559
|
}
|
|
2323
|
-
};
|
|
2560
|
+
});
|
|
2561
|
+
|
|
2562
|
+
// src/coordination/agent-bridge.ts
|
|
2563
|
+
init_errors();
|
|
2324
2564
|
|
|
2325
2565
|
// src/coordination/in-memory-transport.ts
|
|
2326
2566
|
var InMemoryBridgeTransport = class {
|
|
@@ -2424,7 +2664,7 @@ var InMemoryAgentBridge = class {
|
|
|
2424
2664
|
});
|
|
2425
2665
|
}
|
|
2426
2666
|
this.inflightGuards.add(correlationId);
|
|
2427
|
-
return new Promise((
|
|
2667
|
+
return new Promise((resolve12, reject) => {
|
|
2428
2668
|
const timer = setTimeout(() => {
|
|
2429
2669
|
this.inflightGuards.delete(correlationId);
|
|
2430
2670
|
this.pendingRequests.delete(correlationId);
|
|
@@ -2443,7 +2683,7 @@ var InMemoryAgentBridge = class {
|
|
|
2443
2683
|
return;
|
|
2444
2684
|
}
|
|
2445
2685
|
this.pendingRequests.set(correlationId, {
|
|
2446
|
-
resolve:
|
|
2686
|
+
resolve: resolve12,
|
|
2447
2687
|
reject,
|
|
2448
2688
|
timer
|
|
2449
2689
|
});
|
|
@@ -2485,6 +2725,9 @@ function createMessage(type, from, payload, to) {
|
|
|
2485
2725
|
};
|
|
2486
2726
|
}
|
|
2487
2727
|
|
|
2728
|
+
// src/coordination/agent-subagent-runner.ts
|
|
2729
|
+
init_errors();
|
|
2730
|
+
|
|
2488
2731
|
// src/coordination/subagent-budget.ts
|
|
2489
2732
|
var TIMEOUT_PREEMPT_FRACTION = 0.85;
|
|
2490
2733
|
var DECISION_TIMEOUT_MS = 6e4;
|
|
@@ -2556,6 +2799,7 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2556
2799
|
*/
|
|
2557
2800
|
lastActivityTime = null;
|
|
2558
2801
|
_onThreshold;
|
|
2802
|
+
_sessionId;
|
|
2559
2803
|
/**
|
|
2560
2804
|
* Hard cap on how long `_negotiateExtension` waits for the coordinator to
|
|
2561
2805
|
* respond before defaulting to 'stop'. Without this fallback an absent
|
|
@@ -2624,10 +2868,15 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2624
2868
|
get mode() {
|
|
2625
2869
|
return this._mode;
|
|
2626
2870
|
}
|
|
2627
|
-
constructor(limits = {}, mode = "auto") {
|
|
2871
|
+
constructor(limits = {}, mode = "auto", options = {}) {
|
|
2628
2872
|
this._mode = mode;
|
|
2873
|
+
this._sessionId = options.sessionId;
|
|
2629
2874
|
this.limits = { ...limits };
|
|
2630
2875
|
}
|
|
2876
|
+
currentSessionId() {
|
|
2877
|
+
const value = typeof this._sessionId === "function" ? this._sessionId() : this._sessionId;
|
|
2878
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
2879
|
+
}
|
|
2631
2880
|
start() {
|
|
2632
2881
|
this.startTime = Date.now();
|
|
2633
2882
|
this.lastActivityTime = this.startTime;
|
|
@@ -2786,16 +3035,18 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
2786
3035
|
if (!bus?.hasListenerFor("budget.threshold_reached")) {
|
|
2787
3036
|
return Promise.resolve("stop");
|
|
2788
3037
|
}
|
|
2789
|
-
return new Promise((
|
|
3038
|
+
return new Promise((resolve12) => {
|
|
2790
3039
|
let resolved = false;
|
|
2791
3040
|
const respond = (d) => {
|
|
2792
3041
|
if (resolved) return;
|
|
2793
3042
|
resolved = true;
|
|
2794
3043
|
clearTimeout(fallback);
|
|
2795
|
-
|
|
3044
|
+
resolve12(d);
|
|
2796
3045
|
};
|
|
2797
3046
|
const fallback = setTimeout(() => respond("stop"), _SubagentBudget.DECISION_TIMEOUT_MS);
|
|
3047
|
+
const sessionId = this.currentSessionId();
|
|
2798
3048
|
bus.emit("budget.threshold_reached", {
|
|
3049
|
+
...sessionId ? { sessionId } : {},
|
|
2799
3050
|
kind: entry.kind,
|
|
2800
3051
|
used: entry.used,
|
|
2801
3052
|
limit: entry.limit,
|
|
@@ -3194,24 +3445,24 @@ function agentPrompt(id) {
|
|
|
3194
3445
|
const fileName = `${id}.md`;
|
|
3195
3446
|
for (const dir of agentPromptDirCandidates()) {
|
|
3196
3447
|
try {
|
|
3197
|
-
return readFileSync(
|
|
3448
|
+
return readFileSync(path4.join(dir, fileName), "utf8").trimEnd();
|
|
3198
3449
|
} catch {
|
|
3199
3450
|
}
|
|
3200
3451
|
}
|
|
3201
3452
|
return "";
|
|
3202
3453
|
}
|
|
3203
3454
|
function agentPromptDirCandidates() {
|
|
3204
|
-
const here =
|
|
3455
|
+
const here = path4.dirname(fileURLToPath(import.meta.url));
|
|
3205
3456
|
const explicitDir = process.env["WRONGSTACK_AGENT_INSTRUCTIONS_DIR"];
|
|
3206
|
-
const globalRoot = process.env["WRONGSTACK_HOME"] ||
|
|
3457
|
+
const globalRoot = process.env["WRONGSTACK_HOME"] || path4.join(os.homedir(), ".wrongstack");
|
|
3207
3458
|
const candidates = [
|
|
3208
|
-
...explicitDir ? [
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3459
|
+
...explicitDir ? [path4.resolve(explicitDir)] : [],
|
|
3460
|
+
path4.join(globalRoot, "instructions", "agents"),
|
|
3461
|
+
path4.resolve(here, "../../../../instructions/agents"),
|
|
3462
|
+
path4.resolve(here, "../../../instructions/agents"),
|
|
3463
|
+
path4.resolve(here, "../../instructions/agents"),
|
|
3464
|
+
path4.resolve(here, "../instructions/agents"),
|
|
3465
|
+
path4.resolve(here, "instructions/agents")
|
|
3215
3466
|
];
|
|
3216
3467
|
return candidates.sort((a, b) => Number(!isDirectory(a)) - Number(!isDirectory(b)));
|
|
3217
3468
|
}
|
|
@@ -4874,6 +5125,8 @@ FLEET_ROSTER_BUDGETS["goose"] = { timeoutMs: 10 * 60 * 60 * 1e3, maxIterations:
|
|
|
4874
5125
|
});
|
|
4875
5126
|
|
|
4876
5127
|
// src/coordination/delegate-tool.ts
|
|
5128
|
+
init_safe_json();
|
|
5129
|
+
init_error();
|
|
4877
5130
|
function createDelegateTool(opts) {
|
|
4878
5131
|
const defaultTimeoutMs = opts.defaultTimeoutMs ?? 30 * 60 * 1e3;
|
|
4879
5132
|
const rosterIds = opts.roster ? Object.keys(opts.roster) : [];
|
|
@@ -4946,6 +5199,7 @@ function createDelegateTool(opts) {
|
|
|
4946
5199
|
mutating: false,
|
|
4947
5200
|
inputSchema,
|
|
4948
5201
|
async execute(input) {
|
|
5202
|
+
const sessionId = opts.directorRunId;
|
|
4949
5203
|
const i = input ?? {};
|
|
4950
5204
|
if (typeof i.task !== "string" || !i.task.trim()) {
|
|
4951
5205
|
return { ok: false, error: "`task` is required." };
|
|
@@ -5011,7 +5265,7 @@ function createDelegateTool(opts) {
|
|
|
5011
5265
|
if (!cfg.timeoutMs) {
|
|
5012
5266
|
cfg.timeoutMs = Math.max(3e4, timeoutMs - SUBAGENT_TIMEOUT_BUFFER_MS);
|
|
5013
5267
|
}
|
|
5014
|
-
opts.events?.emit("delegate.started", { target, task: i.task });
|
|
5268
|
+
opts.events?.emit("delegate.started", { sessionId, target, task: i.task });
|
|
5015
5269
|
const subagentId = await director.spawn(cfg);
|
|
5016
5270
|
const taskId = await director.assign({
|
|
5017
5271
|
id: `${randomUUID()}`,
|
|
@@ -5019,7 +5273,7 @@ function createDelegateTool(opts) {
|
|
|
5019
5273
|
subagentId
|
|
5020
5274
|
});
|
|
5021
5275
|
const dir = director;
|
|
5022
|
-
const result = await new Promise((
|
|
5276
|
+
const result = await new Promise((resolve12) => {
|
|
5023
5277
|
let settled = false;
|
|
5024
5278
|
let timer;
|
|
5025
5279
|
const finish = (value) => {
|
|
@@ -5029,7 +5283,7 @@ function createDelegateTool(opts) {
|
|
|
5029
5283
|
offTool();
|
|
5030
5284
|
offIter();
|
|
5031
5285
|
offProgress();
|
|
5032
|
-
|
|
5286
|
+
resolve12(value);
|
|
5033
5287
|
};
|
|
5034
5288
|
const arm = () => {
|
|
5035
5289
|
if (timer) clearTimeout(timer);
|
|
@@ -5047,6 +5301,7 @@ function createDelegateTool(opts) {
|
|
|
5047
5301
|
if ("__timeout" in result) {
|
|
5048
5302
|
const partial2 = await readSubagentPartial(opts, subagentId);
|
|
5049
5303
|
opts.events?.emit("delegate.completed", {
|
|
5304
|
+
sessionId,
|
|
5050
5305
|
target,
|
|
5051
5306
|
task: i.task,
|
|
5052
5307
|
ok: false,
|
|
@@ -5070,6 +5325,7 @@ function createDelegateTool(opts) {
|
|
|
5070
5325
|
if ("__emptyResult" in result) {
|
|
5071
5326
|
const partial2 = await readSubagentPartial(opts, subagentId);
|
|
5072
5327
|
opts.events?.emit("delegate.completed", {
|
|
5328
|
+
sessionId,
|
|
5073
5329
|
target,
|
|
5074
5330
|
task: i.task,
|
|
5075
5331
|
ok: false,
|
|
@@ -5103,6 +5359,7 @@ function createDelegateTool(opts) {
|
|
|
5103
5359
|
costUsd = void 0;
|
|
5104
5360
|
}
|
|
5105
5361
|
opts.events?.emit("delegate.completed", {
|
|
5362
|
+
sessionId,
|
|
5106
5363
|
target,
|
|
5107
5364
|
task: i.task,
|
|
5108
5365
|
ok: result.status === "success",
|
|
@@ -5137,6 +5394,7 @@ function createDelegateTool(opts) {
|
|
|
5137
5394
|
} catch (err) {
|
|
5138
5395
|
const message = toErrorMessage(err);
|
|
5139
5396
|
opts.events?.emit("delegate.completed", {
|
|
5397
|
+
sessionId,
|
|
5140
5398
|
target,
|
|
5141
5399
|
task: i.task,
|
|
5142
5400
|
ok: false,
|
|
@@ -5236,13 +5494,13 @@ async function readSubagentPartial(opts, subagentId) {
|
|
|
5236
5494
|
if (!opts.sessionsRoot) return void 0;
|
|
5237
5495
|
const candidates = [];
|
|
5238
5496
|
if (opts.directorRunId) {
|
|
5239
|
-
candidates.push(
|
|
5497
|
+
candidates.push(path4.join(opts.sessionsRoot, opts.directorRunId, `${subagentId}.jsonl`));
|
|
5240
5498
|
} else {
|
|
5241
5499
|
try {
|
|
5242
5500
|
const entries = await fsp7.readdir(opts.sessionsRoot, { withFileTypes: true });
|
|
5243
5501
|
for (const entry of entries) {
|
|
5244
5502
|
if (entry.isDirectory()) {
|
|
5245
|
-
candidates.push(
|
|
5503
|
+
candidates.push(path4.join(opts.sessionsRoot, entry.name, `${subagentId}.jsonl`));
|
|
5246
5504
|
}
|
|
5247
5505
|
}
|
|
5248
5506
|
} catch {
|
|
@@ -5288,6 +5546,7 @@ async function readSubagentPartial(opts, subagentId) {
|
|
|
5288
5546
|
|
|
5289
5547
|
// src/storage/director-state.ts
|
|
5290
5548
|
init_atomic_write();
|
|
5549
|
+
init_error();
|
|
5291
5550
|
async function loadDirectorState(filePath) {
|
|
5292
5551
|
let raw;
|
|
5293
5552
|
try {
|
|
@@ -5469,6 +5728,11 @@ var DirectorStateCheckpoint = class {
|
|
|
5469
5728
|
|
|
5470
5729
|
// src/coordination/director.ts
|
|
5471
5730
|
init_atomic_write();
|
|
5731
|
+
init_error();
|
|
5732
|
+
init_safe_json();
|
|
5733
|
+
|
|
5734
|
+
// src/coordination/collab-debug.ts
|
|
5735
|
+
init_glob_expand();
|
|
5472
5736
|
var DEFAULT_MAX_TARGET_FILES = 30;
|
|
5473
5737
|
var CollabSession = class extends EventEmitter {
|
|
5474
5738
|
sessionId;
|
|
@@ -5557,7 +5821,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
5557
5821
|
}
|
|
5558
5822
|
for (const filePath of allFiles) {
|
|
5559
5823
|
try {
|
|
5560
|
-
const [content,
|
|
5824
|
+
const [content, stat10] = await Promise.all([
|
|
5561
5825
|
fsp7.readFile(filePath, "utf8"),
|
|
5562
5826
|
fsp7.stat(filePath)
|
|
5563
5827
|
]);
|
|
@@ -5567,8 +5831,8 @@ var CollabSession = class extends EventEmitter {
|
|
|
5567
5831
|
path: filePath,
|
|
5568
5832
|
content,
|
|
5569
5833
|
language,
|
|
5570
|
-
snapshotMtimeMs:
|
|
5571
|
-
snapshotSizeBytes:
|
|
5834
|
+
snapshotMtimeMs: stat10.mtimeMs,
|
|
5835
|
+
snapshotSizeBytes: stat10.size
|
|
5572
5836
|
});
|
|
5573
5837
|
} catch {
|
|
5574
5838
|
this.snapshot.files.push({ path: filePath, content: "", language: void 0 });
|
|
@@ -5724,7 +5988,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
5724
5988
|
id: `${role}-${this.sessionId}`,
|
|
5725
5989
|
name: role,
|
|
5726
5990
|
role,
|
|
5727
|
-
tools: ["fleet_emit", "
|
|
5991
|
+
tools: ["fleet_emit", "fleet", "read", "grep", "glob", "bash", "write"],
|
|
5728
5992
|
maxIterations: budget.maxIterations,
|
|
5729
5993
|
maxToolCalls: budget.maxToolCalls,
|
|
5730
5994
|
timeoutMs: budget.timeoutMs
|
|
@@ -5981,9 +6245,9 @@ Emit each evaluation immediately. Do not wait until you have read all reports.`;
|
|
|
5981
6245
|
for (const file of this.snapshot.files) {
|
|
5982
6246
|
if (file.snapshotMtimeMs === void 0 && file.snapshotSizeBytes === void 0) continue;
|
|
5983
6247
|
try {
|
|
5984
|
-
const
|
|
5985
|
-
const mtimeChanged = file.snapshotMtimeMs !== void 0 &&
|
|
5986
|
-
const sizeChanged = file.snapshotSizeBytes !== void 0 &&
|
|
6248
|
+
const stat10 = await fsp7.stat(file.path);
|
|
6249
|
+
const mtimeChanged = file.snapshotMtimeMs !== void 0 && stat10.mtimeMs > file.snapshotMtimeMs + 1;
|
|
6250
|
+
const sizeChanged = file.snapshotSizeBytes !== void 0 && stat10.size !== file.snapshotSizeBytes;
|
|
5987
6251
|
if (mtimeChanged || sizeChanged) {
|
|
5988
6252
|
warnings.push(`${file.path} changed after the collab snapshot was captured.`);
|
|
5989
6253
|
}
|
|
@@ -6060,7 +6324,7 @@ Emit each evaluation immediately. Do not wait until you have read all reports.`;
|
|
|
6060
6324
|
function readBundledInstructionText(relativePath) {
|
|
6061
6325
|
for (const root of instructionRootCandidates()) {
|
|
6062
6326
|
try {
|
|
6063
|
-
return readFileSync(
|
|
6327
|
+
return readFileSync(path4.join(root, relativePath), "utf8").trimEnd();
|
|
6064
6328
|
} catch {
|
|
6065
6329
|
}
|
|
6066
6330
|
}
|
|
@@ -6073,11 +6337,11 @@ function renderInstructionTemplate(template, values) {
|
|
|
6073
6337
|
);
|
|
6074
6338
|
}
|
|
6075
6339
|
function instructionRootCandidates() {
|
|
6076
|
-
const here =
|
|
6340
|
+
const here = path4.dirname(fileURLToPath(import.meta.url));
|
|
6077
6341
|
const candidates = [
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6342
|
+
path4.resolve(here, "../../instructions"),
|
|
6343
|
+
path4.resolve(here, "../instructions"),
|
|
6344
|
+
path4.resolve(here, "instructions")
|
|
6081
6345
|
];
|
|
6082
6346
|
return candidates.sort((a, b) => Number(!isDirectory2(a)) - Number(!isDirectory2(b)));
|
|
6083
6347
|
}
|
|
@@ -6151,6 +6415,7 @@ function rosterSummaryFromConfigs(roster) {
|
|
|
6151
6415
|
}
|
|
6152
6416
|
|
|
6153
6417
|
// src/coordination/dispatcher.ts
|
|
6418
|
+
init_safe_json();
|
|
6154
6419
|
var DEFAULT_DISPATCH_ROLE = "executor";
|
|
6155
6420
|
var FALLBACK_DEFINITION = {
|
|
6156
6421
|
config: { role: "unknown", name: "Unknown Agent" },
|
|
@@ -6272,6 +6537,9 @@ function makeLLMClassifier(complete) {
|
|
|
6272
6537
|
};
|
|
6273
6538
|
}
|
|
6274
6539
|
|
|
6540
|
+
// src/coordination/director-tools.ts
|
|
6541
|
+
init_error();
|
|
6542
|
+
|
|
6275
6543
|
// src/security/capabilities.ts
|
|
6276
6544
|
var ToolCapabilities = {
|
|
6277
6545
|
/** Can execute arbitrary commands in the user's shell (the `bash` tool). */
|
|
@@ -6574,96 +6842,91 @@ function makeTerminateAllTool(director) {
|
|
|
6574
6842
|
}
|
|
6575
6843
|
};
|
|
6576
6844
|
}
|
|
6577
|
-
function
|
|
6578
|
-
return {
|
|
6579
|
-
name: "fleet_status",
|
|
6580
|
-
description: "Snapshot of the fleet \u2014 every subagent's current status, coordinator counts (total/running/idle/stopped), pending task descriptions, and usage rollup.",
|
|
6581
|
-
permission: "auto",
|
|
6582
|
-
mutating: false,
|
|
6583
|
-
capabilities: [ToolCapabilities.COORDINATION_FLEET_READ],
|
|
6584
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
6585
|
-
async execute() {
|
|
6586
|
-
const base = director.status();
|
|
6587
|
-
const fm = director.fleetManager;
|
|
6588
|
-
const stats = fm?.getFleetStats();
|
|
6589
|
-
const fleetStatus = fm?.getFleetStatus();
|
|
6590
|
-
return {
|
|
6591
|
-
subagents: base.subagents,
|
|
6592
|
-
coordinatorStats: stats ? { total: stats.total, running: stats.running, idle: stats.idle, stopped: stats.stopped } : void 0,
|
|
6593
|
-
pending: fleetStatus?.pending ?? [],
|
|
6594
|
-
usage: fm?.snapshot()
|
|
6595
|
-
};
|
|
6596
|
-
}
|
|
6597
|
-
};
|
|
6598
|
-
}
|
|
6599
|
-
function makeFleetUsageTool(director) {
|
|
6845
|
+
function makeFleetTool(director) {
|
|
6600
6846
|
return {
|
|
6601
|
-
name: "
|
|
6602
|
-
description: "
|
|
6603
|
-
|
|
6604
|
-
mutating: false,
|
|
6605
|
-
capabilities: [ToolCapabilities.COORDINATION_FLEET_READ],
|
|
6606
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
6607
|
-
async execute() {
|
|
6608
|
-
return director.snapshot();
|
|
6609
|
-
}
|
|
6610
|
-
};
|
|
6611
|
-
}
|
|
6612
|
-
function makeFleetSessionTool(director) {
|
|
6613
|
-
return {
|
|
6614
|
-
name: "fleet_session",
|
|
6615
|
-
description: "Read a subagent's JSONL transcript and extract its last assistant text, stop reason, and tool-use count. Use this to see what a running or timed-out subagent actually produced.",
|
|
6847
|
+
name: "fleet",
|
|
6848
|
+
description: 'Fleet observation tool. Use `action` to select what you need: "status" \u2014 snapshot of all subagents + coordinator counts + pending tasks; "usage" \u2014 token + cost breakdown per subagent and totals; "health" \u2014 per-subagent budget pressure, last activity, and status; "session" \u2014 read a subagent\'s JSONL transcript (requires subagentId).',
|
|
6849
|
+
usageHint: 'action: "status" (default) | "usage" | "health" | "session".\nFor "session", pass subagentId (required) and optional tail (trailing JSONL lines).',
|
|
6616
6850
|
permission: "auto",
|
|
6617
6851
|
mutating: false,
|
|
6618
6852
|
capabilities: [ToolCapabilities.COORDINATION_FLEET_READ],
|
|
6619
6853
|
inputSchema: {
|
|
6620
6854
|
type: "object",
|
|
6621
6855
|
properties: {
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6856
|
+
action: {
|
|
6857
|
+
type: "string",
|
|
6858
|
+
enum: ["status", "usage", "health", "session"],
|
|
6859
|
+
description: "Observation to retrieve (default: status)."
|
|
6860
|
+
},
|
|
6861
|
+
subagentId: {
|
|
6862
|
+
type: "string",
|
|
6863
|
+
description: 'Subagent id (required for action: "session").'
|
|
6864
|
+
},
|
|
6865
|
+
tail: {
|
|
6866
|
+
type: "number",
|
|
6867
|
+
description: 'Number of trailing JSONL lines (action: "session" only). Omit for the full transcript.'
|
|
6868
|
+
}
|
|
6869
|
+
}
|
|
6626
6870
|
},
|
|
6627
6871
|
async execute(input) {
|
|
6628
|
-
const i = input;
|
|
6629
|
-
const
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
}
|
|
6637
|
-
};
|
|
6638
|
-
}
|
|
6639
|
-
function makeFleetHealthTool(director) {
|
|
6640
|
-
return {
|
|
6641
|
-
name: "fleet_health",
|
|
6642
|
-
description: "Per-subagent health report: budget pressure (pct of limits consumed), last activity timestamp, and current status. Use to decide whether to assign more work to a subagent or spawn a fresh one.",
|
|
6643
|
-
permission: "auto",
|
|
6644
|
-
mutating: false,
|
|
6645
|
-
capabilities: [ToolCapabilities.COORDINATION_FLEET_READ],
|
|
6646
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
6647
|
-
async execute() {
|
|
6648
|
-
const status = director.status();
|
|
6649
|
-
const snapshot = director.snapshot();
|
|
6650
|
-
const subagents = status.subagents ?? [];
|
|
6651
|
-
const perSubagent = snapshot.perSubagent ?? {};
|
|
6652
|
-
return {
|
|
6653
|
-
subagents: subagents.map((s) => {
|
|
6654
|
-
const usage = perSubagent[s.id];
|
|
6872
|
+
const i = input ?? {};
|
|
6873
|
+
const action = i.action ?? "status";
|
|
6874
|
+
switch (action) {
|
|
6875
|
+
case "status": {
|
|
6876
|
+
const base = director.status();
|
|
6877
|
+
const fm = director.fleetManager;
|
|
6878
|
+
const stats = fm?.getFleetStats();
|
|
6879
|
+
const fleetStatus = fm?.getFleetStatus();
|
|
6655
6880
|
return {
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
toolCalls: usage?.toolCalls,
|
|
6662
|
-
costUsd: usage?.cost
|
|
6663
|
-
}
|
|
6881
|
+
action: "status",
|
|
6882
|
+
subagents: base.subagents,
|
|
6883
|
+
coordinatorStats: stats ? { total: stats.total, running: stats.running, idle: stats.idle, stopped: stats.stopped } : void 0,
|
|
6884
|
+
pending: fleetStatus?.pending ?? [],
|
|
6885
|
+
usage: fm?.snapshot()
|
|
6664
6886
|
};
|
|
6665
|
-
}
|
|
6666
|
-
|
|
6887
|
+
}
|
|
6888
|
+
case "usage": {
|
|
6889
|
+
return { action: "usage", ...director.snapshot() };
|
|
6890
|
+
}
|
|
6891
|
+
case "health": {
|
|
6892
|
+
const status = director.status();
|
|
6893
|
+
const snapshot = director.snapshot();
|
|
6894
|
+
const subagents = status.subagents ?? [];
|
|
6895
|
+
const perSubagent = snapshot.perSubagent ?? {};
|
|
6896
|
+
return {
|
|
6897
|
+
action: "health",
|
|
6898
|
+
subagents: subagents.map((s) => {
|
|
6899
|
+
const usage = perSubagent[s.id];
|
|
6900
|
+
return {
|
|
6901
|
+
id: s.id,
|
|
6902
|
+
status: s.status,
|
|
6903
|
+
lastEventAt: usage?.lastEventAt,
|
|
6904
|
+
budgetPressure: {
|
|
6905
|
+
iterations: usage?.iterations,
|
|
6906
|
+
toolCalls: usage?.toolCalls,
|
|
6907
|
+
costUsd: usage?.cost
|
|
6908
|
+
}
|
|
6909
|
+
};
|
|
6910
|
+
})
|
|
6911
|
+
};
|
|
6912
|
+
}
|
|
6913
|
+
case "session": {
|
|
6914
|
+
const subagentId = i.subagentId;
|
|
6915
|
+
if (!subagentId) {
|
|
6916
|
+
return { action: "session", error: 'fleet: subagentId is required for action: "session"' };
|
|
6917
|
+
}
|
|
6918
|
+
const result = await director.readSession(subagentId, i.tail);
|
|
6919
|
+
if (!result) {
|
|
6920
|
+
return {
|
|
6921
|
+
action: "session",
|
|
6922
|
+
error: `fleet: transcript unavailable for "${subagentId}". Is sessionsRoot configured?`
|
|
6923
|
+
};
|
|
6924
|
+
}
|
|
6925
|
+
return { action: "session", ...result };
|
|
6926
|
+
}
|
|
6927
|
+
default:
|
|
6928
|
+
return { error: `fleet: unknown action "${action}". Valid: status, usage, health, session.` };
|
|
6929
|
+
}
|
|
6667
6930
|
}
|
|
6668
6931
|
};
|
|
6669
6932
|
}
|
|
@@ -7039,6 +7302,8 @@ function hashStr(s) {
|
|
|
7039
7302
|
}
|
|
7040
7303
|
|
|
7041
7304
|
// src/types/provider.ts
|
|
7305
|
+
init_errors();
|
|
7306
|
+
init_string();
|
|
7042
7307
|
var ProviderError = class extends WrongStackError {
|
|
7043
7308
|
status;
|
|
7044
7309
|
retryable;
|
|
@@ -7146,6 +7411,8 @@ function resolveModelMatrix(matrix, role) {
|
|
|
7146
7411
|
}
|
|
7147
7412
|
|
|
7148
7413
|
// src/coordination/coordinator/error-classifier.ts
|
|
7414
|
+
init_errors();
|
|
7415
|
+
init_error();
|
|
7149
7416
|
function classifySubagentError(err, hints = {}) {
|
|
7150
7417
|
if (err instanceof AgentError && err.cause) {
|
|
7151
7418
|
return classifySubagentError(err.cause, hints);
|
|
@@ -7332,6 +7599,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7332
7599
|
coordinatorId;
|
|
7333
7600
|
config;
|
|
7334
7601
|
runner;
|
|
7602
|
+
sessionId;
|
|
7335
7603
|
fleetBus;
|
|
7336
7604
|
subagents = /* @__PURE__ */ new Map();
|
|
7337
7605
|
/**
|
|
@@ -7366,6 +7634,11 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7366
7634
|
this.coordinatorId = config.coordinatorId;
|
|
7367
7635
|
this.config = config;
|
|
7368
7636
|
this.runner = options.runner;
|
|
7637
|
+
this.sessionId = options.sessionId;
|
|
7638
|
+
}
|
|
7639
|
+
currentSessionId() {
|
|
7640
|
+
const value = typeof this.sessionId === "function" ? this.sessionId() : this.sessionId;
|
|
7641
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
7369
7642
|
}
|
|
7370
7643
|
/**
|
|
7371
7644
|
* Replace the runner after construction. Used when the runner depends
|
|
@@ -7524,11 +7797,16 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7524
7797
|
status: s.status,
|
|
7525
7798
|
assigned: s.context.parentBridge !== null
|
|
7526
7799
|
}));
|
|
7800
|
+
const sessionId = this.currentSessionId();
|
|
7527
7801
|
this.fleetBus?.emit({
|
|
7528
7802
|
subagentId: this.coordinatorId,
|
|
7529
7803
|
ts: Date.now(),
|
|
7530
7804
|
type: "coordinator.stats",
|
|
7531
|
-
payload: {
|
|
7805
|
+
payload: {
|
|
7806
|
+
...sessionId ? { sessionId } : {},
|
|
7807
|
+
...stats,
|
|
7808
|
+
subagentStatuses
|
|
7809
|
+
}
|
|
7532
7810
|
});
|
|
7533
7811
|
}
|
|
7534
7812
|
getStatus() {
|
|
@@ -7560,7 +7838,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7560
7838
|
taskIds.map((id) => {
|
|
7561
7839
|
const cached = this.completedResults.find((r) => r.taskId === id);
|
|
7562
7840
|
if (cached) return cached;
|
|
7563
|
-
return new Promise((
|
|
7841
|
+
return new Promise((resolve12, reject) => {
|
|
7564
7842
|
const timeout = setTimeout(() => {
|
|
7565
7843
|
this.off("task.completed", handler);
|
|
7566
7844
|
reject(new Error(`awaitTasks timed out waiting for task "${id}"`));
|
|
@@ -7569,7 +7847,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7569
7847
|
if (result.taskId === id) {
|
|
7570
7848
|
clearTimeout(timeout);
|
|
7571
7849
|
this.off("task.completed", handler);
|
|
7572
|
-
|
|
7850
|
+
resolve12(result);
|
|
7573
7851
|
}
|
|
7574
7852
|
};
|
|
7575
7853
|
this.on("task.completed", handler);
|
|
@@ -7731,16 +8009,20 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7731
8009
|
const rawTimeoutMs = subagent.config.timeoutMs;
|
|
7732
8010
|
const rawIdleTimeoutMs = subagent.config.idleTimeoutMs;
|
|
7733
8011
|
const configWithRosterDefaults = applyRosterBudget(subagent.config);
|
|
7734
|
-
const budget = new SubagentBudget(
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
8012
|
+
const budget = new SubagentBudget(
|
|
8013
|
+
{
|
|
8014
|
+
maxIterations: rawMaxIterations ?? this.config.defaultBudget?.maxIterations ?? configWithRosterDefaults.maxIterations,
|
|
8015
|
+
maxToolCalls: rawMaxToolCalls ?? this.config.defaultBudget?.maxToolCalls ?? configWithRosterDefaults.maxToolCalls,
|
|
8016
|
+
maxTokens: rawMaxTokens ?? this.config.defaultBudget?.maxTokens ?? configWithRosterDefaults.maxTokens,
|
|
8017
|
+
maxCostUsd: rawMaxCostUsd ?? this.config.defaultBudget?.maxCostUsd ?? configWithRosterDefaults.maxCostUsd,
|
|
8018
|
+
// Wall-clock cap is opt-in (explicit config / defaultBudget only); the
|
|
8019
|
+
// roster no longer supplies one. Idle is the default reaper.
|
|
8020
|
+
timeoutMs: rawTimeoutMs ?? this.config.defaultBudget?.timeoutMs ?? configWithRosterDefaults.timeoutMs,
|
|
8021
|
+
idleTimeoutMs: rawIdleTimeoutMs ?? this.config.defaultBudget?.idleTimeoutMs ?? configWithRosterDefaults.idleTimeoutMs
|
|
8022
|
+
},
|
|
8023
|
+
"auto",
|
|
8024
|
+
{ sessionId: () => this.currentSessionId() }
|
|
8025
|
+
);
|
|
7744
8026
|
subagent.activeBudget = budget;
|
|
7745
8027
|
if (!this.runner) {
|
|
7746
8028
|
return;
|
|
@@ -7837,13 +8119,15 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7837
8119
|
}
|
|
7838
8120
|
return new Promise((resolveDecision) => {
|
|
7839
8121
|
let settled = false;
|
|
7840
|
-
const
|
|
8122
|
+
const resolve12 = (d) => {
|
|
7841
8123
|
if (settled) return;
|
|
7842
8124
|
settled = true;
|
|
7843
8125
|
resolveDecision(d);
|
|
7844
8126
|
};
|
|
7845
|
-
const fallback = setTimeout(() =>
|
|
8127
|
+
const fallback = setTimeout(() => resolve12("stop"), DECISION_TIMEOUT_MS);
|
|
8128
|
+
const sessionId = this.currentSessionId();
|
|
7846
8129
|
budget._events?.emit("budget.threshold_reached", {
|
|
8130
|
+
...sessionId ? { sessionId } : {},
|
|
7847
8131
|
kind: "timeout",
|
|
7848
8132
|
used,
|
|
7849
8133
|
limit,
|
|
@@ -7858,11 +8142,11 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7858
8142
|
// disagreeing, resolves as a stop). Async grants still resolve.
|
|
7859
8143
|
extend: (extra) => {
|
|
7860
8144
|
clearTimeout(fallback);
|
|
7861
|
-
queueMicrotask(() =>
|
|
8145
|
+
queueMicrotask(() => resolve12({ extend: extra }));
|
|
7862
8146
|
},
|
|
7863
8147
|
deny: () => {
|
|
7864
8148
|
clearTimeout(fallback);
|
|
7865
|
-
|
|
8149
|
+
resolve12("stop");
|
|
7866
8150
|
}
|
|
7867
8151
|
});
|
|
7868
8152
|
});
|
|
@@ -7877,7 +8161,9 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
7877
8161
|
const wallExceeded = wallLimit !== void 0 && elapsed >= wallLimit;
|
|
7878
8162
|
const idleExceeded = idleLimit !== void 0 && budget.idleMs() >= idleLimit;
|
|
7879
8163
|
if (idleExceeded && !wallExceeded) {
|
|
8164
|
+
const sessionId = this.currentSessionId();
|
|
7880
8165
|
budget._events?.emit("budget.threshold_reached", {
|
|
8166
|
+
...sessionId ? { sessionId } : {},
|
|
7881
8167
|
kind: "idle_timeout",
|
|
7882
8168
|
used: budget.idleMs(),
|
|
7883
8169
|
limit: idleLimit ?? 0,
|
|
@@ -8168,6 +8454,10 @@ var Director = class _Director {
|
|
|
8168
8454
|
const resolved = typeof this.maxContext === "function" ? this.maxContext() : this.maxContext;
|
|
8169
8455
|
return resolved && resolved > 0 ? resolved : 128e3;
|
|
8170
8456
|
}
|
|
8457
|
+
currentSessionId() {
|
|
8458
|
+
const value = typeof this.sessionIdSource === "function" ? this.sessionIdSource() : this.sessionIdSource;
|
|
8459
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
8460
|
+
}
|
|
8171
8461
|
/** Optional Brain arbiter for director-level policy decisions. */
|
|
8172
8462
|
brain;
|
|
8173
8463
|
/**
|
|
@@ -8227,6 +8517,7 @@ var Director = class _Director {
|
|
|
8227
8517
|
stateCheckpoint;
|
|
8228
8518
|
/** Optional session writer for emitting task_* / agent_* lifecycle events. */
|
|
8229
8519
|
sessionWriter;
|
|
8520
|
+
sessionIdSource;
|
|
8230
8521
|
/** Debounce timer for periodic manifest writes. */
|
|
8231
8522
|
manifestTimer = null;
|
|
8232
8523
|
manifestDebounceMs;
|
|
@@ -8234,7 +8525,7 @@ var Director = class _Director {
|
|
|
8234
8525
|
maxFleetCostUsd;
|
|
8235
8526
|
/** Max auto-extensions per subagent per budget kind before denying. */
|
|
8236
8527
|
maxBudgetExtensions;
|
|
8237
|
-
/** Sessions root for direct subagent JSONL reads (
|
|
8528
|
+
/** Sessions root for direct subagent JSONL reads (fleet tool, action: session). */
|
|
8238
8529
|
sessionsRoot;
|
|
8239
8530
|
/** Director run id for JSONL path resolution. */
|
|
8240
8531
|
directorRunId;
|
|
@@ -8310,6 +8601,7 @@ var Director = class _Director {
|
|
|
8310
8601
|
this.maxSpawnDepth = opts.maxSpawnDepth ?? 2;
|
|
8311
8602
|
this.spawnDepth = opts.spawnDepth ?? 0;
|
|
8312
8603
|
this.sessionWriter = opts.sessionWriter ?? null;
|
|
8604
|
+
this.sessionIdSource = opts.sessionId ?? (() => opts.sessionWriter?.id);
|
|
8313
8605
|
this.manifestDebounceMs = opts.manifestDebounceMs ?? 2e3;
|
|
8314
8606
|
this.dispatchClassifier = opts.dispatchClassifier;
|
|
8315
8607
|
this.maxFleetCostUsd = opts.directorBudget?.maxCostUsd ?? Number.POSITIVE_INFINITY;
|
|
@@ -8356,7 +8648,7 @@ var Director = class _Director {
|
|
|
8356
8648
|
}
|
|
8357
8649
|
this.coordinator = new DefaultMultiAgentCoordinator(
|
|
8358
8650
|
{ ...opts.config, coordinatorId: this.id },
|
|
8359
|
-
{ runner: opts.runner }
|
|
8651
|
+
{ runner: opts.runner, sessionId: () => this.currentSessionId() }
|
|
8360
8652
|
);
|
|
8361
8653
|
this.coordinator.setFleetBus(this.fleet);
|
|
8362
8654
|
this.fleetManager?.setCoordinator(this.coordinator);
|
|
@@ -8484,6 +8776,7 @@ var Director = class _Director {
|
|
|
8484
8776
|
if (this.brain) {
|
|
8485
8777
|
void this.brain.decide({
|
|
8486
8778
|
id: `director-budget-${e.subagentId}-${payload.kind}`,
|
|
8779
|
+
sessionId: this.currentSessionId(),
|
|
8487
8780
|
source: "director",
|
|
8488
8781
|
question: `Should the director extend the ${payload.kind} budget for subagent ${e.subagentId}?`,
|
|
8489
8782
|
context: [
|
|
@@ -8933,7 +9226,7 @@ var Director = class _Director {
|
|
|
8933
9226
|
})),
|
|
8934
9227
|
usage: this.usage.snapshot()
|
|
8935
9228
|
};
|
|
8936
|
-
await fsp7.mkdir(
|
|
9229
|
+
await fsp7.mkdir(path4.dirname(this.manifestPath), { recursive: true });
|
|
8937
9230
|
await atomicWrite(this.manifestPath, JSON.stringify(manifest, null, 2), { mode: 384 });
|
|
8938
9231
|
return this.manifestPath;
|
|
8939
9232
|
}
|
|
@@ -9077,11 +9370,11 @@ var Director = class _Director {
|
|
|
9077
9370
|
if (cached) return cached;
|
|
9078
9371
|
const existing = this.taskWaiters.get(id);
|
|
9079
9372
|
if (existing) return existing.promise;
|
|
9080
|
-
let
|
|
9373
|
+
let resolve12;
|
|
9081
9374
|
const promise = new Promise((res) => {
|
|
9082
|
-
|
|
9375
|
+
resolve12 = res;
|
|
9083
9376
|
});
|
|
9084
|
-
this.taskWaiters.set(id, { promise, resolve:
|
|
9377
|
+
this.taskWaiters.set(id, { promise, resolve: resolve12 });
|
|
9085
9378
|
return promise;
|
|
9086
9379
|
})
|
|
9087
9380
|
);
|
|
@@ -9164,7 +9457,7 @@ var Director = class _Director {
|
|
|
9164
9457
|
*/
|
|
9165
9458
|
async readSession(subagentId, tail) {
|
|
9166
9459
|
if (!this.sessionsRoot) return null;
|
|
9167
|
-
const filePath =
|
|
9460
|
+
const filePath = path4.join(this.sessionsRoot, this.directorRunId, `${subagentId}.jsonl`);
|
|
9168
9461
|
let raw;
|
|
9169
9462
|
try {
|
|
9170
9463
|
raw = await fsp7.readFile(filePath, "utf8");
|
|
@@ -9280,10 +9573,7 @@ var Director = class _Director {
|
|
|
9280
9573
|
makeRollUpTool(this),
|
|
9281
9574
|
makeTerminateTool(this),
|
|
9282
9575
|
makeTerminateAllTool(this),
|
|
9283
|
-
|
|
9284
|
-
makeFleetUsageTool(this),
|
|
9285
|
-
makeFleetSessionTool(this),
|
|
9286
|
-
makeFleetHealthTool(this),
|
|
9576
|
+
makeFleetTool(this),
|
|
9287
9577
|
makeCollabDebugTool(this),
|
|
9288
9578
|
makeFleetEmitTool(this),
|
|
9289
9579
|
makeWorkCompleteTool(this)
|
|
@@ -9335,9 +9625,13 @@ var Director = class _Director {
|
|
|
9335
9625
|
|
|
9336
9626
|
// src/storage/session-store.ts
|
|
9337
9627
|
init_atomic_write();
|
|
9628
|
+
init_message_invariants();
|
|
9629
|
+
init_utils();
|
|
9630
|
+
init_session_scoped_path();
|
|
9338
9631
|
|
|
9339
9632
|
// src/storage/file-session-writer.ts
|
|
9340
9633
|
init_atomic_write();
|
|
9634
|
+
init_utils();
|
|
9341
9635
|
|
|
9342
9636
|
// src/storage/session-helpers.ts
|
|
9343
9637
|
function userInputTitle(content) {
|
|
@@ -9354,7 +9648,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
9354
9648
|
this.meta = meta;
|
|
9355
9649
|
this.events = events;
|
|
9356
9650
|
this.resumed = opts.resumed ?? false;
|
|
9357
|
-
this.manifestFile = opts.dir ?
|
|
9651
|
+
this.manifestFile = opts.dir ? path4.join(opts.dir, `${path4.basename(id)}.summary.json`) : "";
|
|
9358
9652
|
this.filePath = opts.filePath ?? "";
|
|
9359
9653
|
this.secretScrubber = opts.secretScrubber;
|
|
9360
9654
|
this.onCloseCb = opts.onClose;
|
|
@@ -9723,6 +10017,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
9723
10017
|
promptPreview
|
|
9724
10018
|
});
|
|
9725
10019
|
this.events?.emit("checkpoint.written", {
|
|
10020
|
+
sessionId: this.id,
|
|
9726
10021
|
promptIndex,
|
|
9727
10022
|
promptPreview,
|
|
9728
10023
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9892,6 +10187,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
9892
10187
|
revertedFiles: []
|
|
9893
10188
|
});
|
|
9894
10189
|
this.events?.emit("session.rewound", {
|
|
10190
|
+
sessionId: this.id,
|
|
9895
10191
|
toPromptIndex: targetPromptIndex,
|
|
9896
10192
|
revertedFiles: [],
|
|
9897
10193
|
removedEvents: removedCount
|
|
@@ -9931,7 +10227,7 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
9931
10227
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9932
10228
|
context
|
|
9933
10229
|
});
|
|
9934
|
-
this.events?.emit("in_flight.started", { context, ts: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10230
|
+
this.events?.emit("in_flight.started", { sessionId: this.id, context, ts: (/* @__PURE__ */ new Date()).toISOString() });
|
|
9935
10231
|
}
|
|
9936
10232
|
/**
|
|
9937
10233
|
* Close the in-flight marker. Idempotent in spirit
|
|
@@ -9946,18 +10242,16 @@ var FileSessionWriter = class _FileSessionWriter {
|
|
|
9946
10242
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9947
10243
|
reason
|
|
9948
10244
|
});
|
|
9949
|
-
this.events?.emit("in_flight.ended", { reason, ts: (/* @__PURE__ */ new Date()).toISOString() });
|
|
10245
|
+
this.events?.emit("in_flight.ended", { sessionId: this.id, reason, ts: (/* @__PURE__ */ new Date()).toISOString() });
|
|
9950
10246
|
}
|
|
9951
10247
|
};
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
function generateSessionId(startedAt,
|
|
10248
|
+
|
|
10249
|
+
// src/storage/session-id.ts
|
|
10250
|
+
init_ulid();
|
|
10251
|
+
function generateSessionId(startedAt, _model) {
|
|
9956
10252
|
const date = startedAt.slice(0, 10);
|
|
9957
|
-
const
|
|
9958
|
-
|
|
9959
|
-
const modelPart = model ? `_${sanitizeModel(model)}` : "";
|
|
9960
|
-
return `${date}/${time}Z${modelPart}_${suffix}`;
|
|
10253
|
+
const seedTime = Number.isNaN(Date.parse(startedAt)) ? Date.now() : Date.parse(startedAt);
|
|
10254
|
+
return `${date}/sess_${ulid(seedTime)}`;
|
|
9961
10255
|
}
|
|
9962
10256
|
|
|
9963
10257
|
// src/storage/session-summary.ts
|
|
@@ -10088,17 +10382,17 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10088
10382
|
}
|
|
10089
10383
|
/** Absolute path to the session index file. */
|
|
10090
10384
|
get indexFile() {
|
|
10091
|
-
return
|
|
10385
|
+
return path4.join(this.dir, "_index.jsonl");
|
|
10092
10386
|
}
|
|
10093
10387
|
/** Join session ID to its absolute path within the store directory. */
|
|
10094
10388
|
sessionPath(id, ext) {
|
|
10095
|
-
return
|
|
10389
|
+
return sessionScopedPath(this.dir, id, ext);
|
|
10096
10390
|
}
|
|
10097
10391
|
shardManifestPath(shardKey) {
|
|
10098
|
-
return shardKey ?
|
|
10392
|
+
return shardKey ? path4.join(this.dir, shardKey, "_manifest.json") : path4.join(this.dir, "_manifest.json");
|
|
10099
10393
|
}
|
|
10100
10394
|
shardKeyForSessionId(id) {
|
|
10101
|
-
const dirName =
|
|
10395
|
+
const dirName = path4.dirname(id);
|
|
10102
10396
|
return dirName === "." ? "" : dirName;
|
|
10103
10397
|
}
|
|
10104
10398
|
invalidateShardManifestBySessionId(id) {
|
|
@@ -10110,15 +10404,15 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10110
10404
|
* subdirectory so sessions group naturally by day.
|
|
10111
10405
|
*/
|
|
10112
10406
|
async ensureShardDir(id) {
|
|
10113
|
-
const dirPath =
|
|
10407
|
+
const dirPath = path4.dirname(sessionScopedPath(this.dir, id, ""));
|
|
10114
10408
|
await ensureDir(dirPath);
|
|
10115
10409
|
return dirPath;
|
|
10116
10410
|
}
|
|
10117
10411
|
async create(meta) {
|
|
10118
10412
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
10119
|
-
const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt
|
|
10413
|
+
const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt);
|
|
10120
10414
|
const shardDir = await this.ensureShardDir(id);
|
|
10121
|
-
const file =
|
|
10415
|
+
const file = this.sessionPath(id, ".jsonl");
|
|
10122
10416
|
const t0 = Date.now();
|
|
10123
10417
|
let handle;
|
|
10124
10418
|
try {
|
|
@@ -10180,7 +10474,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10180
10474
|
// Shard directory (sessions/<date>/) — must match create() so the
|
|
10181
10475
|
// .summary.json sidecar lands next to the JSONL instead of the
|
|
10182
10476
|
// sessions root (where summaryFor() would never find it).
|
|
10183
|
-
dir:
|
|
10477
|
+
dir: path4.dirname(file),
|
|
10184
10478
|
filePath: file,
|
|
10185
10479
|
secretScrubber: this.secretScrubber,
|
|
10186
10480
|
onClose: (s) => this.appendToIndex(s)
|
|
@@ -10200,6 +10494,26 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10200
10494
|
}
|
|
10201
10495
|
}
|
|
10202
10496
|
async load(id) {
|
|
10497
|
+
return this.loadInternal(id, { full: true });
|
|
10498
|
+
}
|
|
10499
|
+
/**
|
|
10500
|
+
* Fast-path loader that skips message reconstruction and adjacency repair.
|
|
10501
|
+
*
|
|
10502
|
+
* Use this for callers that only need the raw event stream + session
|
|
10503
|
+
* metadata — e.g. session listers, analytics, audit, and the TUI's
|
|
10504
|
+
* "events only" views. It avoids the message array build and
|
|
10505
|
+
* repairToolUseAdjacency cost on large session files (a long agent
|
|
10506
|
+
* run can have 50k+ events; rebuilding messages is O(events) and
|
|
10507
|
+
* allocates per-block, so skipping it is a meaningful win).
|
|
10508
|
+
*
|
|
10509
|
+
* The returned data.messages is an empty array; data.toolCallEnds
|
|
10510
|
+
* is computed from the raw events. usage is the sum across all
|
|
10511
|
+
* llm_response events — same as full load().
|
|
10512
|
+
*/
|
|
10513
|
+
async loadEventsOnly(id) {
|
|
10514
|
+
return this.loadInternal(id, { full: false });
|
|
10515
|
+
}
|
|
10516
|
+
async loadInternal(id, mode) {
|
|
10203
10517
|
const file = this.sessionPath(id, ".jsonl");
|
|
10204
10518
|
const t0 = Date.now();
|
|
10205
10519
|
let outcome = "success";
|
|
@@ -10207,93 +10521,113 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10207
10521
|
let cacheHit = false;
|
|
10208
10522
|
try {
|
|
10209
10523
|
const s = await fsp7.stat(file);
|
|
10210
|
-
const
|
|
10524
|
+
const stat10 = { mtimeMs: s.mtimeMs, size: s.size };
|
|
10211
10525
|
const cached = this._loadCache.get(id);
|
|
10212
|
-
if (cached && cached.mtimeMs ===
|
|
10526
|
+
if (cached && cached.mtimeMs === stat10.mtimeMs && cached.size === stat10.size) {
|
|
10213
10527
|
cacheHit = true;
|
|
10214
10528
|
this._loadCache.delete(id);
|
|
10215
10529
|
this._loadCache.set(id, cached);
|
|
10216
|
-
return cached.data;
|
|
10530
|
+
if (mode.full) return cached.data;
|
|
10531
|
+
return { ...cached.data, messages: [] };
|
|
10217
10532
|
}
|
|
10218
|
-
const raw = await fsp7.readFile(file, "utf8");
|
|
10219
|
-
const lines = raw.split("\n").filter((l) => l.trim());
|
|
10220
10533
|
const events = [];
|
|
10221
10534
|
let sessionStartEvent;
|
|
10222
10535
|
let sessionEndEvent;
|
|
10223
10536
|
let sessionModel;
|
|
10224
10537
|
let sessionProvider;
|
|
10225
10538
|
let sessionPendingToolUses;
|
|
10226
|
-
const messages = [];
|
|
10227
|
-
const openToolUses = /* @__PURE__ */ new Set();
|
|
10539
|
+
const messages = mode.full ? [] : void 0;
|
|
10540
|
+
const openToolUses = mode.full ? /* @__PURE__ */ new Set() : void 0;
|
|
10228
10541
|
let usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
}
|
|
10244
|
-
if (ev.type === "user_input") {
|
|
10245
|
-
openToolUses.clear();
|
|
10246
|
-
messages.push({ role: "user", content: ev.content, ts: ev.ts });
|
|
10247
|
-
} else if (ev.type === "llm_response") {
|
|
10248
|
-
messages.push({ role: "assistant", content: ev.content, ts: ev.ts });
|
|
10249
|
-
for (const b of ev.content) {
|
|
10250
|
-
if (b.type === "tool_use") openToolUses.add(b.id);
|
|
10542
|
+
const stream = createReadStream(file, { encoding: "utf8" });
|
|
10543
|
+
const rl = createInterface({ input: stream, crlfDelay: Infinity });
|
|
10544
|
+
try {
|
|
10545
|
+
for await (const line of rl) {
|
|
10546
|
+
if (!line.trim()) continue;
|
|
10547
|
+
try {
|
|
10548
|
+
const parsed = JSON.parse(line);
|
|
10549
|
+
if (parsed !== null && typeof parsed === "object" && typeof parsed.type === "string" && typeof parsed.ts === "string") {
|
|
10550
|
+
const ev = parsed;
|
|
10551
|
+
events.push(ev);
|
|
10552
|
+
if (ev.type === "session_start" && !sessionStartEvent) {
|
|
10553
|
+
sessionStartEvent = ev;
|
|
10554
|
+
sessionModel = ev.model;
|
|
10555
|
+
sessionProvider = ev.provider;
|
|
10251
10556
|
}
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
cacheRead: (usage.cacheRead ?? 0) + (ev.usage.cacheRead ?? 0),
|
|
10256
|
-
cacheWrite: (usage.cacheWrite ?? 0) + (ev.usage.cacheWrite ?? 0)
|
|
10257
|
-
};
|
|
10258
|
-
} else if (ev.type === "tool_result") {
|
|
10259
|
-
if (!openToolUses.has(ev.id)) {
|
|
10260
|
-
this.events?.emit("session.damaged", {
|
|
10261
|
-
sessionId: id,
|
|
10262
|
-
detail: `Orphan tool_result "${ev.id}" has no matching tool_use`
|
|
10263
|
-
});
|
|
10264
|
-
continue;
|
|
10557
|
+
if (ev.type === "session_end") {
|
|
10558
|
+
sessionEndEvent = ev;
|
|
10559
|
+
sessionPendingToolUses = ev.pendingToolUses;
|
|
10265
10560
|
}
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10561
|
+
if (mode.full && messages !== void 0 && openToolUses !== void 0) {
|
|
10562
|
+
if (ev.type === "user_input") {
|
|
10563
|
+
openToolUses.clear();
|
|
10564
|
+
messages.push({ role: "user", content: ev.content, ts: ev.ts });
|
|
10565
|
+
} else if (ev.type === "llm_response") {
|
|
10566
|
+
messages.push({ role: "assistant", content: ev.content, ts: ev.ts });
|
|
10567
|
+
for (const b of ev.content) {
|
|
10568
|
+
if (b.type === "tool_use") openToolUses.add(b.id);
|
|
10569
|
+
}
|
|
10570
|
+
usage = {
|
|
10571
|
+
input: usage.input + (ev.usage.input ?? 0),
|
|
10572
|
+
output: usage.output + (ev.usage.output ?? 0),
|
|
10573
|
+
cacheRead: (usage.cacheRead ?? 0) + (ev.usage.cacheRead ?? 0),
|
|
10574
|
+
cacheWrite: (usage.cacheWrite ?? 0) + (ev.usage.cacheWrite ?? 0)
|
|
10575
|
+
};
|
|
10576
|
+
} else if (ev.type === "tool_result") {
|
|
10577
|
+
if (!openToolUses.has(ev.id)) {
|
|
10578
|
+
this.events?.emit("session.damaged", {
|
|
10579
|
+
sessionId: id,
|
|
10580
|
+
detail: `Orphan tool_result "${ev.id}" has no matching tool_use`
|
|
10581
|
+
});
|
|
10582
|
+
continue;
|
|
10583
|
+
}
|
|
10584
|
+
openToolUses.delete(ev.id);
|
|
10585
|
+
const resultBlock = {
|
|
10586
|
+
type: "tool_result",
|
|
10587
|
+
tool_use_id: ev.id,
|
|
10588
|
+
content: typeof ev.content === "string" ? ev.content : JSON.stringify(ev.content),
|
|
10589
|
+
is_error: ev.isError
|
|
10590
|
+
};
|
|
10591
|
+
const last = messages[messages.length - 1];
|
|
10592
|
+
const lastIsToolResultUser = last?.role === "user" && Array.isArray(last.content) && last.content.every((b) => b.type === "tool_result");
|
|
10593
|
+
if (lastIsToolResultUser && Array.isArray(last.content)) {
|
|
10594
|
+
last.content.push(resultBlock);
|
|
10595
|
+
} else {
|
|
10596
|
+
messages.push({ role: "user", content: [resultBlock], ts: ev.ts });
|
|
10597
|
+
}
|
|
10598
|
+
}
|
|
10599
|
+
} else if (ev.type === "llm_response") {
|
|
10600
|
+
usage = {
|
|
10601
|
+
input: usage.input + (ev.usage.input ?? 0),
|
|
10602
|
+
output: usage.output + (ev.usage.output ?? 0),
|
|
10603
|
+
cacheRead: (usage.cacheRead ?? 0) + (ev.usage.cacheRead ?? 0),
|
|
10604
|
+
cacheWrite: (usage.cacheWrite ?? 0) + (ev.usage.cacheWrite ?? 0)
|
|
10605
|
+
};
|
|
10279
10606
|
}
|
|
10280
10607
|
}
|
|
10608
|
+
} catch {
|
|
10281
10609
|
}
|
|
10282
|
-
} catch {
|
|
10283
10610
|
}
|
|
10611
|
+
} finally {
|
|
10612
|
+
rl.close();
|
|
10613
|
+
stream.close();
|
|
10284
10614
|
}
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10615
|
+
let finalMessages = [];
|
|
10616
|
+
if (mode.full && messages !== void 0 && openToolUses !== void 0) {
|
|
10617
|
+
if (openToolUses.size > 0) {
|
|
10618
|
+
this.events?.emit("session.damaged", {
|
|
10619
|
+
sessionId: id,
|
|
10620
|
+
detail: `${openToolUses.size} tool_use blocks without matching results - replay repaired`
|
|
10621
|
+
});
|
|
10622
|
+
}
|
|
10623
|
+
const repaired = repairToolUseAdjacency(messages);
|
|
10624
|
+
if (repaired.report.changed) {
|
|
10625
|
+
this.events?.emit("session.damaged", {
|
|
10626
|
+
sessionId: id,
|
|
10627
|
+
detail: `Repaired replay adjacency: removed ${repaired.report.removedToolUses.length} tool_use, ${repaired.report.removedToolResults.length} tool_result, ${repaired.report.removedMessages} empty messages`
|
|
10628
|
+
});
|
|
10629
|
+
}
|
|
10630
|
+
finalMessages = repaired.messages;
|
|
10297
10631
|
}
|
|
10298
10632
|
const meta = {
|
|
10299
10633
|
id,
|
|
@@ -10304,27 +10638,29 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10304
10638
|
pendingToolUses: sessionPendingToolUses
|
|
10305
10639
|
};
|
|
10306
10640
|
const toolCallEnds = extractToolCallEnds(events);
|
|
10307
|
-
const data = { metadata: meta, events, messages:
|
|
10308
|
-
if (
|
|
10309
|
-
|
|
10310
|
-
|
|
10311
|
-
|
|
10641
|
+
const data = { metadata: meta, events, messages: finalMessages, usage, toolCallEnds };
|
|
10642
|
+
if (mode.full) {
|
|
10643
|
+
if (this._loadCache.size >= _DefaultSessionStore.LOAD_CACHE_MAX_ENTRIES) {
|
|
10644
|
+
const oldest = this._loadCache.keys().next().value;
|
|
10645
|
+
if (oldest !== void 0) {
|
|
10646
|
+
this._loadCache.delete(oldest);
|
|
10647
|
+
}
|
|
10312
10648
|
}
|
|
10649
|
+
this._loadCache.set(id, { mtimeMs: stat10.mtimeMs, size: stat10.size, data });
|
|
10313
10650
|
}
|
|
10314
|
-
this._loadCache.set(id, { mtimeMs: stat9.mtimeMs, size: stat9.size, data });
|
|
10315
10651
|
return data;
|
|
10316
10652
|
} catch (err) {
|
|
10317
10653
|
outcome = "failure";
|
|
10318
10654
|
errorMsg = toErrorMessage(err);
|
|
10319
10655
|
throw err;
|
|
10320
10656
|
} finally {
|
|
10321
|
-
this.emitRead(id, file, "load", outcome, Date.now() - t0, errorMsg);
|
|
10657
|
+
this.emitRead(id, file, mode.full ? "load" : "load_events_only", outcome, Date.now() - t0, errorMsg);
|
|
10322
10658
|
if (cacheHit) {
|
|
10323
10659
|
this.events?.emit("storage.cache_hit", {
|
|
10324
10660
|
sessionId: id,
|
|
10325
10661
|
store: "session",
|
|
10326
10662
|
filePath: file,
|
|
10327
|
-
operation: "load",
|
|
10663
|
+
operation: mode.full ? "load" : "load_events_only",
|
|
10328
10664
|
durationMs: Date.now() - t0
|
|
10329
10665
|
});
|
|
10330
10666
|
}
|
|
@@ -10352,14 +10688,14 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10352
10688
|
const limit = opts?.limit;
|
|
10353
10689
|
const signal = opts?.signal;
|
|
10354
10690
|
const out = [];
|
|
10355
|
-
let
|
|
10691
|
+
let stat10;
|
|
10356
10692
|
try {
|
|
10357
|
-
|
|
10693
|
+
stat10 = await fsp7.stat(file);
|
|
10358
10694
|
} catch (err) {
|
|
10359
10695
|
if (err.code === "ENOENT") return [];
|
|
10360
10696
|
throw err;
|
|
10361
10697
|
}
|
|
10362
|
-
if (
|
|
10698
|
+
if (stat10.size === 0) return [];
|
|
10363
10699
|
let fh;
|
|
10364
10700
|
try {
|
|
10365
10701
|
fh = await fsp7.open(file, "r");
|
|
@@ -10472,14 +10808,20 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10472
10808
|
async appendToIndex(summary) {
|
|
10473
10809
|
try {
|
|
10474
10810
|
await ensureDir(this.dir);
|
|
10475
|
-
|
|
10476
|
-
await
|
|
10477
|
-
|
|
10478
|
-
|
|
10479
|
-
|
|
10480
|
-
|
|
10481
|
-
|
|
10482
|
-
this.indexAppendCount
|
|
10811
|
+
let shouldCompact = false;
|
|
10812
|
+
await withFileLock(this.indexFile, async () => {
|
|
10813
|
+
const line = JSON.stringify(summary) + "\n";
|
|
10814
|
+
await fsp7.appendFile(this.indexFile, line, "utf8");
|
|
10815
|
+
this._indexCache = null;
|
|
10816
|
+
this.invalidateShardManifestBySessionId(summary.id);
|
|
10817
|
+
this.indexAppendCount++;
|
|
10818
|
+
if (this.indexAppendCount >= _DefaultSessionStore.COMPACT_EVERY) {
|
|
10819
|
+
shouldCompact = true;
|
|
10820
|
+
this.indexAppendCount = 0;
|
|
10821
|
+
}
|
|
10822
|
+
});
|
|
10823
|
+
if (shouldCompact) {
|
|
10824
|
+
await withFileLock(this.indexFile, () => this.compactIndexInner());
|
|
10483
10825
|
}
|
|
10484
10826
|
} catch {
|
|
10485
10827
|
}
|
|
@@ -10488,30 +10830,28 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10488
10830
|
async writeTombstone(id) {
|
|
10489
10831
|
try {
|
|
10490
10832
|
await ensureDir(this.dir);
|
|
10491
|
-
|
|
10492
|
-
|
|
10493
|
-
|
|
10494
|
-
|
|
10495
|
-
|
|
10833
|
+
await withFileLock(this.indexFile, async () => {
|
|
10834
|
+
const line = JSON.stringify({ action: "delete", id }) + "\n";
|
|
10835
|
+
await fsp7.appendFile(this.indexFile, line, "utf8");
|
|
10836
|
+
this._indexCache = null;
|
|
10837
|
+
this.invalidateShardManifestBySessionId(id);
|
|
10838
|
+
this.indexAppendCount++;
|
|
10839
|
+
});
|
|
10496
10840
|
} catch {
|
|
10497
10841
|
}
|
|
10498
10842
|
}
|
|
10499
10843
|
/**
|
|
10500
10844
|
* Compact the index: read all entries, drop tombstones, deduplicate
|
|
10501
|
-
* (keep latest per session), and rewrite.
|
|
10845
|
+
* (keep latest per session), and rewrite atomically. Acquires the index
|
|
10846
|
+
* file lock so a concurrent append (this process or another wstack in the
|
|
10847
|
+
* same project) can't be overwritten by the rewrite.
|
|
10502
10848
|
*/
|
|
10503
10849
|
async compactIndex() {
|
|
10504
10850
|
const t0 = Date.now();
|
|
10505
10851
|
let outcome = "success";
|
|
10506
10852
|
let errorMsg;
|
|
10507
10853
|
try {
|
|
10508
|
-
|
|
10509
|
-
if (entries.length === 0) return;
|
|
10510
|
-
const tmp = `${this.indexFile}.compact.tmp`;
|
|
10511
|
-
const lines = entries.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
10512
|
-
await fsp7.writeFile(tmp, lines, "utf8");
|
|
10513
|
-
await fsp7.rename(tmp, this.indexFile);
|
|
10514
|
-
this._indexCache = null;
|
|
10854
|
+
await withFileLock(this.indexFile, () => this.compactIndexInner());
|
|
10515
10855
|
} catch (err) {
|
|
10516
10856
|
outcome = "failure";
|
|
10517
10857
|
errorMsg = toErrorMessage(err);
|
|
@@ -10519,21 +10859,34 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10519
10859
|
this.emitWrite("~compact~", this.indexFile, "compact", outcome, Date.now() - t0, void 0, errorMsg);
|
|
10520
10860
|
}
|
|
10521
10861
|
}
|
|
10862
|
+
/**
|
|
10863
|
+
* Lock-free compaction body. The caller MUST already hold the index file
|
|
10864
|
+
* lock (via withFileLock(this.indexFile, ...)). Uses atomicWrite for the
|
|
10865
|
+
* rewrite so the temp file gets a random suffix (no collision between two
|
|
10866
|
+
* compactions) and the Windows transient-EPERM rename retry.
|
|
10867
|
+
*/
|
|
10868
|
+
async compactIndexInner() {
|
|
10869
|
+
const entries = await this.readIndex();
|
|
10870
|
+
if (entries.length === 0) return;
|
|
10871
|
+
const lines = entries.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
10872
|
+
await atomicWrite(this.indexFile, lines, { mode: 384 });
|
|
10873
|
+
this._indexCache = null;
|
|
10874
|
+
}
|
|
10522
10875
|
/**
|
|
10523
10876
|
* Read the index file and return deduplicated session summaries.
|
|
10524
10877
|
* Entries with a matching tombstone are filtered out.
|
|
10525
10878
|
* Returns empty array when the index doesn't exist or is corrupt.
|
|
10526
10879
|
*/
|
|
10527
10880
|
async readIndex() {
|
|
10528
|
-
let
|
|
10881
|
+
let stat10;
|
|
10529
10882
|
try {
|
|
10530
10883
|
const s = await fsp7.stat(this.indexFile);
|
|
10531
|
-
|
|
10884
|
+
stat10 = { mtimeMs: s.mtimeMs, size: s.size };
|
|
10532
10885
|
} catch {
|
|
10533
10886
|
this._indexCache = null;
|
|
10534
10887
|
return [];
|
|
10535
10888
|
}
|
|
10536
|
-
if (this._indexCache !== null && this._indexCache.mtimeMs ===
|
|
10889
|
+
if (this._indexCache !== null && this._indexCache.mtimeMs === stat10.mtimeMs && this._indexCache.size === stat10.size) {
|
|
10537
10890
|
return [...this._indexCache.summaries];
|
|
10538
10891
|
}
|
|
10539
10892
|
let raw;
|
|
@@ -10566,7 +10919,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10566
10919
|
if (a.startedAt > b.startedAt) return -1;
|
|
10567
10920
|
return a.id.localeCompare(b.id);
|
|
10568
10921
|
});
|
|
10569
|
-
this._indexCache = { ...
|
|
10922
|
+
this._indexCache = { ...stat10, summaries };
|
|
10570
10923
|
return [...summaries];
|
|
10571
10924
|
}
|
|
10572
10925
|
/**
|
|
@@ -10577,11 +10930,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10577
10930
|
const ids = await this.collectSessionIds(this.dir);
|
|
10578
10931
|
const summaries = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null)));
|
|
10579
10932
|
const valid = summaries.filter((s) => s !== null);
|
|
10580
|
-
const tmp = `${this.indexFile}.tmp`;
|
|
10581
10933
|
const lines = valid.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
10582
|
-
await
|
|
10583
|
-
|
|
10584
|
-
|
|
10934
|
+
await withFileLock(this.indexFile, async () => {
|
|
10935
|
+
await atomicWrite(this.indexFile, lines, { mode: 384 });
|
|
10936
|
+
this._indexCache = null;
|
|
10937
|
+
});
|
|
10585
10938
|
return valid.length;
|
|
10586
10939
|
}
|
|
10587
10940
|
async listFromDirectoryScan(limit) {
|
|
@@ -10657,7 +11010,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10657
11010
|
return entry;
|
|
10658
11011
|
}
|
|
10659
11012
|
async collectSessionFilesInShard(shardKey) {
|
|
10660
|
-
const dir = shardKey ?
|
|
11013
|
+
const dir = shardKey ? path4.join(this.dir, shardKey) : this.dir;
|
|
10661
11014
|
const entries = await this.collectSessionFiles(dir, shardKey);
|
|
10662
11015
|
return shardKey ? entries.filter((entry) => entry.id.startsWith(`${shardKey}/`)) : entries.filter((entry) => !entry.id.includes("/"));
|
|
10663
11016
|
}
|
|
@@ -10680,13 +11033,13 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10680
11033
|
if (entry.name === "_index.jsonl") continue;
|
|
10681
11034
|
const base = entry.name.replace(/\.jsonl$/, "");
|
|
10682
11035
|
const id = prefix ? `${prefix}/${base}` : base;
|
|
10683
|
-
files.push({ id, filePath:
|
|
11036
|
+
files.push({ id, filePath: path4.join(dir, entry.name) });
|
|
10684
11037
|
}
|
|
10685
11038
|
}
|
|
10686
11039
|
const childFileArrays = await Promise.all(
|
|
10687
11040
|
dirEntries.map((entry) => {
|
|
10688
11041
|
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
10689
|
-
return this.collectSessionFiles(
|
|
11042
|
+
return this.collectSessionFiles(path4.join(dir, entry.name), childPrefix, depth + 1);
|
|
10690
11043
|
})
|
|
10691
11044
|
);
|
|
10692
11045
|
return [...childFileArrays.flat(), ...files];
|
|
@@ -10719,7 +11072,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10719
11072
|
const childIdArrays = await Promise.all(
|
|
10720
11073
|
dirEntries.map((entry) => {
|
|
10721
11074
|
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
10722
|
-
return this.collectSessionIds(
|
|
11075
|
+
return this.collectSessionIds(path4.join(dir, entry.name), childPrefix, depth + 1);
|
|
10723
11076
|
})
|
|
10724
11077
|
);
|
|
10725
11078
|
return [...childIdArrays.flat(), ...fileIds];
|
|
@@ -10733,8 +11086,8 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10733
11086
|
if (fromManifest) return fromManifest;
|
|
10734
11087
|
try {
|
|
10735
11088
|
const full = this.sessionPath(id, ".jsonl");
|
|
10736
|
-
const
|
|
10737
|
-
const summary = await this.summarize(id,
|
|
11089
|
+
const stat10 = await fsp7.stat(full);
|
|
11090
|
+
const summary = await this.summarize(id, stat10.mtime.toISOString());
|
|
10738
11091
|
await atomicWrite(manifest, JSON.stringify(summary), { mode: 384 }).catch((err) => {
|
|
10739
11092
|
const msg = toErrorMessage(err);
|
|
10740
11093
|
this.emitError(id, manifest, "summary_fallback", msg, true);
|
|
@@ -10777,18 +11130,18 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10777
11130
|
async summaryHeaderFor(ref) {
|
|
10778
11131
|
let mtime = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
10779
11132
|
try {
|
|
10780
|
-
const
|
|
10781
|
-
if (!
|
|
11133
|
+
const stat10 = await fsp7.stat(ref.filePath);
|
|
11134
|
+
if (!stat10.isFile()) {
|
|
10782
11135
|
return {
|
|
10783
11136
|
id: ref.id,
|
|
10784
11137
|
title: "(damaged)",
|
|
10785
|
-
startedAt:
|
|
11138
|
+
startedAt: stat10.mtime.toISOString(),
|
|
10786
11139
|
model: "unknown",
|
|
10787
11140
|
provider: "unknown",
|
|
10788
11141
|
tokenTotal: 0
|
|
10789
11142
|
};
|
|
10790
11143
|
}
|
|
10791
|
-
mtime =
|
|
11144
|
+
mtime = stat10.mtime.toISOString();
|
|
10792
11145
|
} catch {
|
|
10793
11146
|
return null;
|
|
10794
11147
|
}
|
|
@@ -10836,14 +11189,15 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10836
11189
|
async deleteSession(id) {
|
|
10837
11190
|
const jsonlPath = this.sessionPath(id, ".jsonl");
|
|
10838
11191
|
const summaryPath = this.sessionPath(id, ".summary.json");
|
|
10839
|
-
const shardDir =
|
|
10840
|
-
const base =
|
|
10841
|
-
const sessDir =
|
|
11192
|
+
const shardDir = path4.dirname(jsonlPath);
|
|
11193
|
+
const base = path4.basename(id);
|
|
11194
|
+
const sessDir = path4.join(shardDir, base);
|
|
10842
11195
|
const deletions = [
|
|
10843
11196
|
fsp7.unlink(jsonlPath),
|
|
10844
11197
|
fsp7.unlink(summaryPath),
|
|
10845
|
-
fsp7.unlink(
|
|
10846
|
-
fsp7.unlink(
|
|
11198
|
+
fsp7.unlink(sessionScopedPath(this.dir, id, ".plan.json")),
|
|
11199
|
+
fsp7.unlink(sessionScopedPath(this.dir, id, ".tasks.json")),
|
|
11200
|
+
fsp7.unlink(sessionScopedPath(this.dir, id, ".todos.json"))
|
|
10847
11201
|
];
|
|
10848
11202
|
const results = await Promise.allSettled(deletions);
|
|
10849
11203
|
for (const r of results) {
|
|
@@ -10879,17 +11233,17 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10879
11233
|
let deleted = 0;
|
|
10880
11234
|
let activeSessionId = null;
|
|
10881
11235
|
try {
|
|
10882
|
-
const raw = await fsp7.readFile(
|
|
11236
|
+
const raw = await fsp7.readFile(path4.join(this.dir, "active.json"), "utf8");
|
|
10883
11237
|
const active = JSON.parse(raw);
|
|
10884
11238
|
activeSessionId = active.sessionId ?? null;
|
|
10885
11239
|
} catch {
|
|
10886
11240
|
}
|
|
10887
11241
|
const isPrunableJsonl = (name) => name.endsWith(".jsonl") && name !== "_index.jsonl" && name !== "_mailbox.jsonl" && !name.endsWith(".replay.jsonl") && !name.endsWith(".audit.jsonl");
|
|
10888
11242
|
const pruneFile = async (dir, name, prefix) => {
|
|
10889
|
-
const jsonlPath =
|
|
11243
|
+
const jsonlPath = path4.join(dir, name);
|
|
10890
11244
|
try {
|
|
10891
|
-
const
|
|
10892
|
-
if (
|
|
11245
|
+
const stat10 = await fsp7.stat(jsonlPath);
|
|
11246
|
+
if (stat10.mtimeMs >= cutoff) return;
|
|
10893
11247
|
} catch {
|
|
10894
11248
|
return;
|
|
10895
11249
|
}
|
|
@@ -10906,7 +11260,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10906
11260
|
continue;
|
|
10907
11261
|
}
|
|
10908
11262
|
if (!entry.isDirectory()) continue;
|
|
10909
|
-
const dateDir =
|
|
11263
|
+
const dateDir = path4.join(this.dir, entry.name);
|
|
10910
11264
|
const files = await fsp7.readdir(dateDir, { withFileTypes: true }).catch(() => []);
|
|
10911
11265
|
for (const file of files) {
|
|
10912
11266
|
if (!file.isFile() || !isPrunableJsonl(file.name)) continue;
|
|
@@ -10918,7 +11272,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
10918
11272
|
}
|
|
10919
11273
|
for (const entry of entries) {
|
|
10920
11274
|
if (!entry.isDirectory()) continue;
|
|
10921
|
-
const dateDir =
|
|
11275
|
+
const dateDir = path4.join(this.dir, entry.name);
|
|
10922
11276
|
try {
|
|
10923
11277
|
const remaining = await fsp7.readdir(dateDir);
|
|
10924
11278
|
if (remaining.length === 0) {
|
|
@@ -11049,9 +11403,9 @@ function makeDirectorSessionFactory(opts) {
|
|
|
11049
11403
|
let dir;
|
|
11050
11404
|
if (opts.store) {
|
|
11051
11405
|
store = opts.store;
|
|
11052
|
-
dir = opts.sessionsRoot ?
|
|
11406
|
+
dir = opts.sessionsRoot ? path4.join(opts.sessionsRoot, runId) : "(caller-managed)";
|
|
11053
11407
|
} else if (opts.sessionsRoot) {
|
|
11054
|
-
dir =
|
|
11408
|
+
dir = path4.join(opts.sessionsRoot, runId);
|
|
11055
11409
|
store = new DefaultSessionStore({ dir });
|
|
11056
11410
|
} else {
|
|
11057
11411
|
throw new Error("makeDirectorSessionFactory requires either `store` or `sessionsRoot`");
|
|
@@ -11078,6 +11432,9 @@ function makeDirectorSessionFactory(opts) {
|
|
|
11078
11432
|
var NULL_FLEET_BUS = new FleetBus();
|
|
11079
11433
|
|
|
11080
11434
|
// src/execution/auto-compaction-middleware.ts
|
|
11435
|
+
init_errors();
|
|
11436
|
+
init_token_estimate();
|
|
11437
|
+
init_context_evidence();
|
|
11081
11438
|
var LEVEL_RANK = { warn: 0, soft: 1, hard: 2 };
|
|
11082
11439
|
var MAX_DIGEST_LOG_CHARS = 4e3;
|
|
11083
11440
|
function truncateDigest(digest) {
|
|
@@ -11274,6 +11631,7 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
11274
11631
|
const report = await this.compactor.compact(ctx, { aggressive });
|
|
11275
11632
|
this.recordAttempt(pressure.level, pressure.tokens, report);
|
|
11276
11633
|
this.events?.emit("compaction.fired", {
|
|
11634
|
+
sessionId: ctx.session.id,
|
|
11277
11635
|
level: pressure.level,
|
|
11278
11636
|
tokens: pressure.tokens,
|
|
11279
11637
|
load: pressure.load,
|
|
@@ -11308,6 +11666,7 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
11308
11666
|
`Auto-compaction left context above the hard threshold after ${pressure.level} compaction`
|
|
11309
11667
|
);
|
|
11310
11668
|
this.events?.emit("compaction.failed", {
|
|
11669
|
+
sessionId: ctx.session.id,
|
|
11311
11670
|
err: error,
|
|
11312
11671
|
aggressive,
|
|
11313
11672
|
level: pressure.level,
|
|
@@ -11335,6 +11694,7 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
11335
11694
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
11336
11695
|
const fatal = this.failureMode === "throw" || this.failureMode === "throw_on_hard" && pressure.level === "hard";
|
|
11337
11696
|
this.events?.emit("compaction.failed", {
|
|
11697
|
+
sessionId: ctx.session.id,
|
|
11338
11698
|
err: error,
|
|
11339
11699
|
aggressive,
|
|
11340
11700
|
level: pressure.level,
|
|
@@ -11395,6 +11755,9 @@ function adaptThresholdsForSignals(thresholds, signals) {
|
|
|
11395
11755
|
}
|
|
11396
11756
|
|
|
11397
11757
|
// src/execution/autonomous-runner.ts
|
|
11758
|
+
init_errors();
|
|
11759
|
+
init_assert_never();
|
|
11760
|
+
init_regex_guard();
|
|
11398
11761
|
var DoneConditionChecker = class {
|
|
11399
11762
|
constructor(condition) {
|
|
11400
11763
|
this.condition = condition;
|
|
@@ -11573,6 +11936,9 @@ var AutonomousRunner = class {
|
|
|
11573
11936
|
|
|
11574
11937
|
// src/storage/goal-store.ts
|
|
11575
11938
|
init_atomic_write();
|
|
11939
|
+
init_error();
|
|
11940
|
+
init_wstack_paths();
|
|
11941
|
+
init_errors();
|
|
11576
11942
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
11577
11943
|
function goalFilePath(projectRoot) {
|
|
11578
11944
|
return resolveWstackPaths({ projectRoot }).projectGoal;
|
|
@@ -11769,12 +12135,30 @@ ${journalTail.join("\n")}` : "Recent journal: (none \u2014 this is the first ite
|
|
|
11769
12135
|
};
|
|
11770
12136
|
}
|
|
11771
12137
|
|
|
12138
|
+
// src/execution/compactor.ts
|
|
12139
|
+
init_token_estimate();
|
|
12140
|
+
init_message_invariants();
|
|
12141
|
+
init_context_evidence();
|
|
12142
|
+
|
|
11772
12143
|
// src/types/blocks.ts
|
|
11773
12144
|
function isTextBlock(b) {
|
|
11774
12145
|
return b.type === "text";
|
|
11775
12146
|
}
|
|
11776
12147
|
|
|
11777
12148
|
// src/execution/compaction-core.ts
|
|
12149
|
+
init_token_estimate();
|
|
12150
|
+
var FAILURE_PATTERN = /(error|fail|exception|timeout|enonet|eacces|eperm|enoent|abort)/i;
|
|
12151
|
+
var CORRECTION_PATTERN = /\b(wrong|no\b|stop\b|don'?t\b|actually|fix that|undo|revert|forget|ignore|skip)\b/i;
|
|
12152
|
+
var ERROR_LANG_PATTERN = /\b(error|exception|fatal|critical|crash|panic|abort|segfault|core dump|undefined is not|null pointer|typeerror|referenceerror|syntaxerror)\b/i;
|
|
12153
|
+
var SECURITY_PATTERN = /\b(security|vulnerability|injection|xss|csrf|secret|apikey|api.key|hardcoded|leak|exploit|cve)\b/i;
|
|
12154
|
+
var ARCHITECTURE_PATTERN = /\b(architecture|design|approach|strategy|pattern|refactor|migrate|restructure|decision|trade.?off)\b/i;
|
|
12155
|
+
var BOILERPLATE_PATTERN = /\b(files_with_matches|count|found \d+ match|directory tree|\.\.\. and \d+ more)\b/i;
|
|
12156
|
+
var PATH_HINT_PATTERN = /(?:(?:[A-Za-z]:)?[./\\]?[\w@.-]+(?:[\\/][\w@(). -]+)+\.[A-Za-z0-9]{1,12})/g;
|
|
12157
|
+
var PATH_BACKSLASH_PATTERN = /\\/g;
|
|
12158
|
+
var PATH_TRIM_PATTERN = /^["'`]+|["'`),;:]+$/g;
|
|
12159
|
+
var ERROR_LINE_PATTERN = /\b(error|exception|failed|failure|fatal|panic|timeout|denied|enoent|eacces|eperm)\b/i;
|
|
12160
|
+
var NEWLINE_SPLIT_PATTERN = /\r?\n/;
|
|
12161
|
+
var WHITESPACE_COLLAPSE_PATTERN = /\s+/g;
|
|
11778
12162
|
function compactionDebugEnabled() {
|
|
11779
12163
|
return process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1";
|
|
11780
12164
|
}
|
|
@@ -12010,9 +12394,8 @@ function summarizeToolResultElision(block, tokens) {
|
|
|
12010
12394
|
function extractPathHints(content) {
|
|
12011
12395
|
const text = typeof content === "string" ? content : JSON.stringify(content);
|
|
12012
12396
|
const out = /* @__PURE__ */ new Set();
|
|
12013
|
-
const
|
|
12014
|
-
|
|
12015
|
-
const clean = match[0]?.replace(/\\/g, "/").replace(/^["'`]+|["'`),;:]+$/g, "");
|
|
12397
|
+
for (const match of text.matchAll(PATH_HINT_PATTERN)) {
|
|
12398
|
+
const clean = match[0]?.replace(PATH_BACKSLASH_PATTERN, "/").replace(PATH_TRIM_PATTERN, "");
|
|
12016
12399
|
if (clean && clean.length <= 220) out.add(clean);
|
|
12017
12400
|
if (out.size >= 5) break;
|
|
12018
12401
|
}
|
|
@@ -12020,12 +12403,9 @@ function extractPathHints(content) {
|
|
|
12020
12403
|
}
|
|
12021
12404
|
function firstErrorLine(content) {
|
|
12022
12405
|
const text = typeof content === "string" ? content : JSON.stringify(content);
|
|
12023
|
-
for (const line of text.split(
|
|
12024
|
-
if (
|
|
12025
|
-
|
|
12026
|
-
))
|
|
12027
|
-
continue;
|
|
12028
|
-
const trimmed = line.replace(/\s+/g, " ").trim();
|
|
12406
|
+
for (const line of text.split(NEWLINE_SPLIT_PATTERN)) {
|
|
12407
|
+
if (!ERROR_LINE_PATTERN.test(line)) continue;
|
|
12408
|
+
const trimmed = line.replace(WHITESPACE_COLLAPSE_PATTERN, " ").trim();
|
|
12029
12409
|
if (trimmed) return trimmed.slice(0, 180);
|
|
12030
12410
|
}
|
|
12031
12411
|
return void 0;
|
|
@@ -12072,9 +12452,9 @@ function scoreMessage(m, context) {
|
|
|
12072
12452
|
if (hasToolUse2(m) || hasResult) return 0;
|
|
12073
12453
|
}
|
|
12074
12454
|
if (context?.failureCounts && m.role === "user" && hasToolUse2(m) === false) {
|
|
12075
|
-
const
|
|
12076
|
-
if (
|
|
12077
|
-
const errKey =
|
|
12455
|
+
const failureMatch = FAILURE_PATTERN.exec(text);
|
|
12456
|
+
if (failureMatch) {
|
|
12457
|
+
const errKey = failureMatch[0]?.toLowerCase() ?? "error";
|
|
12078
12458
|
const count = (context.failureCounts.get(errKey) ?? 0) + 1;
|
|
12079
12459
|
context.failureCounts.set(errKey, count);
|
|
12080
12460
|
if (count >= 5) return 0;
|
|
@@ -12082,29 +12462,21 @@ function scoreMessage(m, context) {
|
|
|
12082
12462
|
}
|
|
12083
12463
|
}
|
|
12084
12464
|
if (m.role === "user") {
|
|
12085
|
-
if (
|
|
12086
|
-
text
|
|
12087
|
-
)) {
|
|
12465
|
+
if (CORRECTION_PATTERN.test(text)) {
|
|
12088
12466
|
return 5;
|
|
12089
12467
|
}
|
|
12090
12468
|
}
|
|
12091
|
-
if (
|
|
12092
|
-
text
|
|
12093
|
-
)) {
|
|
12469
|
+
if (ERROR_LANG_PATTERN.test(text)) {
|
|
12094
12470
|
return 5;
|
|
12095
12471
|
}
|
|
12096
|
-
if (
|
|
12097
|
-
text
|
|
12098
|
-
)) {
|
|
12472
|
+
if (SECURITY_PATTERN.test(text)) {
|
|
12099
12473
|
return 5;
|
|
12100
12474
|
}
|
|
12101
|
-
if (m.role === "assistant" &&
|
|
12102
|
-
text
|
|
12103
|
-
)) {
|
|
12475
|
+
if (m.role === "assistant" && ARCHITECTURE_PATTERN.test(text)) {
|
|
12104
12476
|
return 5;
|
|
12105
12477
|
}
|
|
12106
12478
|
if (hasLargeToolResult(m)) return 1;
|
|
12107
|
-
if (m.role === "user" && !hasToolUse2(m) &&
|
|
12479
|
+
if (m.role === "user" && !hasToolUse2(m) && BOILERPLATE_PATTERN.test(text)) {
|
|
12108
12480
|
return 1;
|
|
12109
12481
|
}
|
|
12110
12482
|
return 3;
|
|
@@ -12114,6 +12486,11 @@ function buildSmartDigest(messages) {
|
|
|
12114
12486
|
const failureCounts = /* @__PURE__ */ new Map();
|
|
12115
12487
|
let noiseCount = 0;
|
|
12116
12488
|
for (const m of messages) {
|
|
12489
|
+
const isPureToolIO = Array.isArray(m.content) && m.content.length > 0 && !hasToolUse2(m) && m.content.every((b) => b.type === "tool_result");
|
|
12490
|
+
if (isPureToolIO) {
|
|
12491
|
+
noiseCount++;
|
|
12492
|
+
continue;
|
|
12493
|
+
}
|
|
12117
12494
|
const score = scoreMessage(m, { failureCounts });
|
|
12118
12495
|
const text = extractText(m);
|
|
12119
12496
|
const toolCount = countToolBlocks(m);
|
|
@@ -12370,6 +12747,7 @@ var DESIGN_STACKS = ["web", "react-native", "flutter", "swiftui", "compose"];
|
|
|
12370
12747
|
function isDesignStack(v) {
|
|
12371
12748
|
return DESIGN_STACKS.includes(v);
|
|
12372
12749
|
}
|
|
12750
|
+
init_wstack_paths();
|
|
12373
12751
|
var KIT_FILE = "KIT.md";
|
|
12374
12752
|
var TOKENS_FILE = "tokens.json";
|
|
12375
12753
|
var FOUNDATIONS_ID = "_foundations";
|
|
@@ -12482,7 +12860,7 @@ var DefaultDesignKitLoader = class {
|
|
|
12482
12860
|
}
|
|
12483
12861
|
for (const e of entries) {
|
|
12484
12862
|
if (!e.isDirectory()) continue;
|
|
12485
|
-
const kitFile =
|
|
12863
|
+
const kitFile = path4.join(dir, e.name, KIT_FILE);
|
|
12486
12864
|
try {
|
|
12487
12865
|
const raw = await fsp7.readFile(kitFile, "utf8");
|
|
12488
12866
|
const fm = parseKitFrontmatter(raw);
|
|
@@ -12556,7 +12934,7 @@ var DefaultDesignKitLoader = class {
|
|
|
12556
12934
|
const m = await this.find(id);
|
|
12557
12935
|
let tokens;
|
|
12558
12936
|
if (m) {
|
|
12559
|
-
const tokensPath =
|
|
12937
|
+
const tokensPath = path4.join(path4.dirname(m.path), TOKENS_FILE);
|
|
12560
12938
|
try {
|
|
12561
12939
|
const raw = await fsp7.readFile(tokensPath, "utf8");
|
|
12562
12940
|
const parsed = JSON.parse(raw);
|
|
@@ -12583,12 +12961,12 @@ var DefaultDesignKitLoader = class {
|
|
|
12583
12961
|
};
|
|
12584
12962
|
function resolveBundledDesignKitsDir() {
|
|
12585
12963
|
try {
|
|
12586
|
-
const here =
|
|
12964
|
+
const here = path4.dirname(fileURLToPath(import.meta.url));
|
|
12587
12965
|
const candidates = [
|
|
12588
|
-
|
|
12589
|
-
|
|
12590
|
-
|
|
12591
|
-
|
|
12966
|
+
path4.join(here, "design-kits"),
|
|
12967
|
+
path4.join(here, "..", "design-kits"),
|
|
12968
|
+
path4.join(here, "..", "..", "design-kits"),
|
|
12969
|
+
path4.join(here, "..", "..", "..", "design-kits")
|
|
12592
12970
|
];
|
|
12593
12971
|
for (const c of candidates) {
|
|
12594
12972
|
if (existsSync(c)) return c;
|
|
@@ -12615,7 +12993,7 @@ function _resetDesignKitLoaderMemo() {
|
|
|
12615
12993
|
}
|
|
12616
12994
|
var DESIGN_DIR = ".design";
|
|
12617
12995
|
function designProjectDir(projectRoot) {
|
|
12618
|
-
return
|
|
12996
|
+
return path4.join(projectRoot, DESIGN_DIR);
|
|
12619
12997
|
}
|
|
12620
12998
|
var RULE_FILES = ["rules.md", "RULES.md", "design.md"];
|
|
12621
12999
|
var rulesCache = /* @__PURE__ */ new Map();
|
|
@@ -12624,7 +13002,7 @@ async function loadProjectDesignRules(projectRoot) {
|
|
|
12624
13002
|
let rules;
|
|
12625
13003
|
for (const name of RULE_FILES) {
|
|
12626
13004
|
try {
|
|
12627
|
-
const txt = await fsp7.readFile(
|
|
13005
|
+
const txt = await fsp7.readFile(path4.join(designProjectDir(projectRoot), name), "utf8");
|
|
12628
13006
|
if (txt.trim()) {
|
|
12629
13007
|
rules = txt.trim();
|
|
12630
13008
|
break;
|
|
@@ -12645,7 +13023,7 @@ function parseOverrides(value) {
|
|
|
12645
13023
|
}
|
|
12646
13024
|
async function loadActiveKit(projectRoot) {
|
|
12647
13025
|
try {
|
|
12648
|
-
const raw = await fsp7.readFile(
|
|
13026
|
+
const raw = await fsp7.readFile(path4.join(designProjectDir(projectRoot), "active.json"), "utf8");
|
|
12649
13027
|
const parsed = JSON.parse(raw);
|
|
12650
13028
|
if (parsed && typeof parsed.kit === "string") {
|
|
12651
13029
|
return {
|
|
@@ -12679,7 +13057,7 @@ function applyTokenOverrides(tokens, overrides) {
|
|
|
12679
13057
|
async function ensureDesignDir(projectRoot) {
|
|
12680
13058
|
const dir = designProjectDir(projectRoot);
|
|
12681
13059
|
await fsp7.mkdir(dir, { recursive: true });
|
|
12682
|
-
const gi =
|
|
13060
|
+
const gi = path4.join(dir, ".gitignore");
|
|
12683
13061
|
if (!existsSync(gi)) {
|
|
12684
13062
|
try {
|
|
12685
13063
|
await fsp7.writeFile(gi, "*\n");
|
|
@@ -12693,11 +13071,11 @@ async function recordKitChoice(projectRoot, kit, stack, source, isoTime, overrid
|
|
|
12693
13071
|
const dir = await ensureDesignDir(projectRoot);
|
|
12694
13072
|
const record = { kit, stack: stack ?? null };
|
|
12695
13073
|
if (overrides && Object.keys(overrides).length > 0) record.overrides = overrides;
|
|
12696
|
-
await fsp7.writeFile(
|
|
13074
|
+
await fsp7.writeFile(path4.join(dir, "active.json"), `${JSON.stringify(record, null, 2)}
|
|
12697
13075
|
`);
|
|
12698
13076
|
const line = `- ${isoTime} \xB7 kit=${kit}${stack ? ` stack=${stack}` : ""} \xB7 via=${source}
|
|
12699
13077
|
`;
|
|
12700
|
-
await fsp7.appendFile(
|
|
13078
|
+
await fsp7.appendFile(path4.join(dir, "decisions.md"), line);
|
|
12701
13079
|
} catch {
|
|
12702
13080
|
}
|
|
12703
13081
|
}
|
|
@@ -12713,11 +13091,11 @@ async function recordOverrides(projectRoot, patch, isoTime) {
|
|
|
12713
13091
|
const dir = await ensureDesignDir(projectRoot);
|
|
12714
13092
|
const record = { kit: active.kit, stack: active.stack ?? null };
|
|
12715
13093
|
if (Object.keys(merged).length > 0) record.overrides = merged;
|
|
12716
|
-
await fsp7.writeFile(
|
|
13094
|
+
await fsp7.writeFile(path4.join(dir, "active.json"), `${JSON.stringify(record, null, 2)}
|
|
12717
13095
|
`);
|
|
12718
13096
|
const keys = Object.keys(patch).join(",");
|
|
12719
13097
|
await fsp7.appendFile(
|
|
12720
|
-
|
|
13098
|
+
path4.join(dir, "decisions.md"),
|
|
12721
13099
|
`- ${isoTime} \xB7 kit=${active.kit} \xB7 override=${keys} \xB7 via=set
|
|
12722
13100
|
`
|
|
12723
13101
|
);
|
|
@@ -12727,7 +13105,7 @@ async function recordOverrides(projectRoot, patch, isoTime) {
|
|
|
12727
13105
|
}
|
|
12728
13106
|
async function clearPersistedActiveKit(projectRoot) {
|
|
12729
13107
|
try {
|
|
12730
|
-
await fsp7.rm(
|
|
13108
|
+
await fsp7.rm(path4.join(designProjectDir(projectRoot), "active.json"), { force: true });
|
|
12731
13109
|
} catch {
|
|
12732
13110
|
}
|
|
12733
13111
|
}
|
|
@@ -12900,14 +13278,14 @@ var SKIP_DIR = /* @__PURE__ */ new Set([
|
|
|
12900
13278
|
".design"
|
|
12901
13279
|
]);
|
|
12902
13280
|
async function walkUiFiles(root, max = 200) {
|
|
12903
|
-
const { default:
|
|
13281
|
+
const { default: fs16 } = await import('fs/promises');
|
|
12904
13282
|
const { default: nodePath } = await import('path');
|
|
12905
13283
|
const found = [];
|
|
12906
13284
|
async function rec(dir, depth) {
|
|
12907
13285
|
if (found.length >= max || depth > 8) return;
|
|
12908
13286
|
let entries;
|
|
12909
13287
|
try {
|
|
12910
|
-
entries = await
|
|
13288
|
+
entries = await fs16.readdir(dir, { withFileTypes: true });
|
|
12911
13289
|
} catch {
|
|
12912
13290
|
return;
|
|
12913
13291
|
}
|
|
@@ -12925,13 +13303,13 @@ async function walkUiFiles(root, max = 200) {
|
|
|
12925
13303
|
return found;
|
|
12926
13304
|
}
|
|
12927
13305
|
async function runDesignVerify(projectRoot, tokens, explicitFiles) {
|
|
12928
|
-
const { default:
|
|
13306
|
+
const { default: fs16 } = await import('fs/promises');
|
|
12929
13307
|
const { default: nodePath } = await import('path');
|
|
12930
13308
|
const abs = explicitFiles && explicitFiles.length > 0 ? explicitFiles.map((f) => nodePath.isAbsolute(f) ? f : nodePath.join(projectRoot, f)) : await walkUiFiles(projectRoot);
|
|
12931
13309
|
const files = [];
|
|
12932
13310
|
for (const a of abs) {
|
|
12933
13311
|
try {
|
|
12934
|
-
files.push({ path: nodePath.relative(projectRoot, a), text: await
|
|
13312
|
+
files.push({ path: nodePath.relative(projectRoot, a), text: await fs16.readFile(a, "utf8") });
|
|
12935
13313
|
} catch {
|
|
12936
13314
|
}
|
|
12937
13315
|
}
|
|
@@ -13062,10 +13440,10 @@ function makeDesignVerifyToolCallMiddleware() {
|
|
|
13062
13440
|
const p = typeof input?.path === "string" ? input.path : "";
|
|
13063
13441
|
if (!p || !detectFrontendFile(p)) return out;
|
|
13064
13442
|
const ctx = out.ctx;
|
|
13065
|
-
const { default:
|
|
13443
|
+
const { default: fs16 } = await import('fs/promises');
|
|
13066
13444
|
const { default: nodePath } = await import('path');
|
|
13067
13445
|
const abs = nodePath.isAbsolute(p) ? p : nodePath.join(ctx.projectRoot, p);
|
|
13068
|
-
const text = await
|
|
13446
|
+
const text = await fs16.readFile(abs, "utf8").catch(() => "");
|
|
13069
13447
|
if (!text) return out;
|
|
13070
13448
|
const loader = getDesignKitLoader(ctx.projectRoot);
|
|
13071
13449
|
const rawTokens = await loader.readTokens(state.activeKit);
|
|
@@ -13365,7 +13743,7 @@ function buildRecoveryStrategies(opts) {
|
|
|
13365
13743
|
label: "downgrade_model",
|
|
13366
13744
|
async attempt(err, ctx) {
|
|
13367
13745
|
if (!(err instanceof ProviderError)) return null;
|
|
13368
|
-
if (err.status !==
|
|
13746
|
+
if (err.status !== 529 && err.status < 500) return null;
|
|
13369
13747
|
return null;
|
|
13370
13748
|
}
|
|
13371
13749
|
}
|
|
@@ -13414,6 +13792,8 @@ var DefaultErrorHandler = class {
|
|
|
13414
13792
|
return null;
|
|
13415
13793
|
}
|
|
13416
13794
|
};
|
|
13795
|
+
init_sleep();
|
|
13796
|
+
init_error();
|
|
13417
13797
|
|
|
13418
13798
|
// src/execution/autonomy-brain.ts
|
|
13419
13799
|
function formatDecisionSummary(decision, request) {
|
|
@@ -14044,6 +14424,7 @@ Deliverables: ${goal.deliverables.length} total, progress ${goal.progress ?? "un
|
|
|
14044
14424
|
try {
|
|
14045
14425
|
const decision = await this.opts.brain.decide({
|
|
14046
14426
|
id: `goal-done-${goal.iterations}`,
|
|
14427
|
+
sessionId: this.opts.agent.ctx.session?.id,
|
|
14047
14428
|
source: "system",
|
|
14048
14429
|
question: `Brainstorm returned DONE ${this.consecutiveBrainstormDone}x. Is the goal truly complete?`,
|
|
14049
14430
|
context: [
|
|
@@ -14119,6 +14500,8 @@ function buildGoalPreamble(goal, deliverables) {
|
|
|
14119
14500
|
}
|
|
14120
14501
|
|
|
14121
14502
|
// src/execution/intelligent-compactor.ts
|
|
14503
|
+
init_token_estimate();
|
|
14504
|
+
init_message_invariants();
|
|
14122
14505
|
var IntelligentCompactor = class {
|
|
14123
14506
|
provider;
|
|
14124
14507
|
warnThreshold;
|
|
@@ -14253,6 +14636,11 @@ var IntelligentCompactor = class {
|
|
|
14253
14636
|
return [{ type: "text", text: lines.join("\n") }];
|
|
14254
14637
|
}
|
|
14255
14638
|
};
|
|
14639
|
+
|
|
14640
|
+
// src/execution/parallel-eternal-engine.ts
|
|
14641
|
+
init_expect_defined();
|
|
14642
|
+
init_error();
|
|
14643
|
+
init_sleep();
|
|
14256
14644
|
var GOAL_COMPLETE_MARKER2 = /^\s*\[goal[_\s-]?complete\]\s*$/im;
|
|
14257
14645
|
var ParallelEternalEngine = class {
|
|
14258
14646
|
constructor(opts) {
|
|
@@ -14678,6 +15066,12 @@ ${lastFew}` : "No prior iterations.",
|
|
|
14678
15066
|
await saveGoal(this.goalPath, { ...current, engineState: state }, this.opts.events);
|
|
14679
15067
|
}
|
|
14680
15068
|
};
|
|
15069
|
+
|
|
15070
|
+
// src/core/provider-runner.ts
|
|
15071
|
+
init_errors();
|
|
15072
|
+
|
|
15073
|
+
// src/core/streaming-response-builder.ts
|
|
15074
|
+
init_json_repair();
|
|
14681
15075
|
var STREAM_DRAIN_TIMEOUT_MS = 500;
|
|
14682
15076
|
function buildResponse(state) {
|
|
14683
15077
|
const content = [];
|
|
@@ -14823,13 +15217,14 @@ function handleMessageStop(state, ev) {
|
|
|
14823
15217
|
}
|
|
14824
15218
|
async function streamProviderToResponse(provider, req, signal, ctx, events, logger) {
|
|
14825
15219
|
const state = createStreamingState(req.model);
|
|
15220
|
+
const sessionId = ctx.session?.id;
|
|
14826
15221
|
logger.debug("Stream started", { providerId: provider.id, model: req.model });
|
|
14827
15222
|
const TEXT_BATCH_SIZE = 4;
|
|
14828
15223
|
let pendingText = "";
|
|
14829
15224
|
let pendingCount = 0;
|
|
14830
15225
|
const flushText = () => {
|
|
14831
15226
|
if (pendingCount > 0) {
|
|
14832
|
-
events.emit("provider.text_delta", { ctx, text: pendingText });
|
|
15227
|
+
events.emit("provider.text_delta", { sessionId, ctx, text: pendingText });
|
|
14833
15228
|
pendingText = "";
|
|
14834
15229
|
pendingCount = 0;
|
|
14835
15230
|
}
|
|
@@ -14862,7 +15257,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
14862
15257
|
const idVal = ev.id;
|
|
14863
15258
|
const nameVal = ev.name;
|
|
14864
15259
|
handleToolUseStart(state, { id: idVal, name: nameVal });
|
|
14865
|
-
const emittedPayload = { ctx, id: idVal ?? "unknown", name: nameVal ?? "unknown" };
|
|
15260
|
+
const emittedPayload = { sessionId, ctx, id: idVal ?? "unknown", name: nameVal ?? "unknown" };
|
|
14866
15261
|
events.emit("provider.tool_use_start", emittedPayload);
|
|
14867
15262
|
break;
|
|
14868
15263
|
}
|
|
@@ -14873,7 +15268,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
14873
15268
|
flushText();
|
|
14874
15269
|
const stoppedName = state.tools.get(ev.id)?.name ?? "unknown";
|
|
14875
15270
|
handleToolUseStop(state, ev);
|
|
14876
|
-
events.emit("provider.tool_use_stop", { ctx, id: ev.id, name: stoppedName });
|
|
15271
|
+
events.emit("provider.tool_use_stop", { sessionId, ctx, id: ev.id, name: stoppedName });
|
|
14877
15272
|
break;
|
|
14878
15273
|
}
|
|
14879
15274
|
case "thinking_start":
|
|
@@ -14882,7 +15277,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
14882
15277
|
case "thinking_delta":
|
|
14883
15278
|
flushText();
|
|
14884
15279
|
handleThinkingDelta(state, ev.text);
|
|
14885
|
-
events.emit("provider.thinking_delta", { ctx, text: ev.text });
|
|
15280
|
+
events.emit("provider.thinking_delta", { sessionId, ctx, text: ev.text });
|
|
14886
15281
|
break;
|
|
14887
15282
|
case "thinking_signature":
|
|
14888
15283
|
handleThinkingSignature(state, ev.signature);
|
|
@@ -14914,6 +15309,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
14914
15309
|
});
|
|
14915
15310
|
flushText();
|
|
14916
15311
|
events.emit("provider.stream_error", {
|
|
15312
|
+
sessionId,
|
|
14917
15313
|
ctx,
|
|
14918
15314
|
eventType: String(evAny.type),
|
|
14919
15315
|
msg: errMsg
|
|
@@ -14942,8 +15338,8 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
14942
15338
|
});
|
|
14943
15339
|
await Promise.race([
|
|
14944
15340
|
drainPromise,
|
|
14945
|
-
new Promise((
|
|
14946
|
-
drainTimer = setTimeout(
|
|
15341
|
+
new Promise((resolve12) => {
|
|
15342
|
+
drainTimer = setTimeout(resolve12, STREAM_DRAIN_TIMEOUT_MS);
|
|
14947
15343
|
})
|
|
14948
15344
|
]);
|
|
14949
15345
|
} finally {
|
|
@@ -15014,6 +15410,7 @@ async function runProviderWithRetry(opts) {
|
|
|
15014
15410
|
if (!canRetry) {
|
|
15015
15411
|
if (isProviderErr) {
|
|
15016
15412
|
events.emit("provider.error", {
|
|
15413
|
+
sessionId: ctx.session.id,
|
|
15017
15414
|
providerId: err.providerId,
|
|
15018
15415
|
status: err.status,
|
|
15019
15416
|
description,
|
|
@@ -15043,6 +15440,7 @@ async function runProviderWithRetry(opts) {
|
|
|
15043
15440
|
});
|
|
15044
15441
|
if (isProviderErr) {
|
|
15045
15442
|
events.emit("provider.retry", {
|
|
15443
|
+
sessionId: ctx.session.id,
|
|
15046
15444
|
providerId: err.providerId,
|
|
15047
15445
|
attempt: attemptNum,
|
|
15048
15446
|
delayMs: delay,
|
|
@@ -15050,7 +15448,7 @@ async function runProviderWithRetry(opts) {
|
|
|
15050
15448
|
description
|
|
15051
15449
|
});
|
|
15052
15450
|
}
|
|
15053
|
-
await new Promise((
|
|
15451
|
+
await new Promise((resolve12, reject) => {
|
|
15054
15452
|
let settled = false;
|
|
15055
15453
|
const cleanup = () => {
|
|
15056
15454
|
clearTimeout(t);
|
|
@@ -15066,7 +15464,7 @@ async function runProviderWithRetry(opts) {
|
|
|
15066
15464
|
if (settled) return;
|
|
15067
15465
|
settled = true;
|
|
15068
15466
|
cleanup();
|
|
15069
|
-
|
|
15467
|
+
resolve12();
|
|
15070
15468
|
}, delay);
|
|
15071
15469
|
if (signal.aborted) {
|
|
15072
15470
|
onAbort();
|
|
@@ -15117,6 +15515,8 @@ var DefaultRetryPolicy = class {
|
|
|
15117
15515
|
};
|
|
15118
15516
|
|
|
15119
15517
|
// src/models/llm-selector.ts
|
|
15518
|
+
init_expect_defined();
|
|
15519
|
+
init_token_estimate();
|
|
15120
15520
|
var DEFAULT_SYSTEM_PROMPT = readBundledInstructionText("llm/llm-selector.md");
|
|
15121
15521
|
function formatMessages(messages, maxTokens = 2048) {
|
|
15122
15522
|
const lines = [];
|
|
@@ -15287,6 +15687,8 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
|
|
|
15287
15687
|
};
|
|
15288
15688
|
|
|
15289
15689
|
// src/execution/selective-compactor.ts
|
|
15690
|
+
init_token_estimate();
|
|
15691
|
+
init_message_invariants();
|
|
15290
15692
|
var SelectiveCompactor = class {
|
|
15291
15693
|
provider;
|
|
15292
15694
|
selector;
|
|
@@ -15549,7 +15951,7 @@ var DefaultSkillLoader = class {
|
|
|
15549
15951
|
const entries = await fsp7.readdir(dir, { withFileTypes: true });
|
|
15550
15952
|
for (const e of entries) {
|
|
15551
15953
|
if (!e.isDirectory()) continue;
|
|
15552
|
-
const skillFile =
|
|
15954
|
+
const skillFile = path4.join(dir, e.name, "SKILL.md");
|
|
15553
15955
|
try {
|
|
15554
15956
|
const raw = await fsp7.readFile(skillFile, "utf8");
|
|
15555
15957
|
const meta = parseFrontmatter(raw);
|
|
@@ -15620,7 +16022,7 @@ var DefaultSkillLoader = class {
|
|
|
15620
16022
|
if (cached !== void 0) return cached;
|
|
15621
16023
|
const m = await this.find(name);
|
|
15622
16024
|
if (!m) throw new Error(`Skill "${name}" not found`);
|
|
15623
|
-
const savePath =
|
|
16025
|
+
const savePath = path4.join(path4.dirname(m.path), "SKILL.save.md");
|
|
15624
16026
|
let result;
|
|
15625
16027
|
try {
|
|
15626
16028
|
result = await fsp7.readFile(savePath, "utf8");
|
|
@@ -15690,6 +16092,8 @@ function parseDescriptionFromText(desc) {
|
|
|
15690
16092
|
|
|
15691
16093
|
// src/storage/prompt-store.ts
|
|
15692
16094
|
init_atomic_write();
|
|
16095
|
+
init_slug();
|
|
16096
|
+
init_ulid();
|
|
15693
16097
|
var SCHEMA_VERSION = 2;
|
|
15694
16098
|
function migratePromptEntry(raw) {
|
|
15695
16099
|
if (!raw || typeof raw !== "object") return null;
|
|
@@ -15755,7 +16159,7 @@ var DefaultPromptStore = class {
|
|
|
15755
16159
|
if (!file.endsWith(".json")) continue;
|
|
15756
16160
|
try {
|
|
15757
16161
|
const raw = JSON.parse(
|
|
15758
|
-
await fsp7.readFile(
|
|
16162
|
+
await fsp7.readFile(path4.join(this.dir, file), "utf8")
|
|
15759
16163
|
);
|
|
15760
16164
|
const migrated = migratePromptEntry(raw.entry);
|
|
15761
16165
|
if (migrated) entries.push(migrated);
|
|
@@ -15769,7 +16173,7 @@ var DefaultPromptStore = class {
|
|
|
15769
16173
|
);
|
|
15770
16174
|
}
|
|
15771
16175
|
async get(id) {
|
|
15772
|
-
const file =
|
|
16176
|
+
const file = path4.join(this.dir, `${id}.json`);
|
|
15773
16177
|
try {
|
|
15774
16178
|
const raw = JSON.parse(await fsp7.readFile(file, "utf8"));
|
|
15775
16179
|
return migratePromptEntry(raw.entry);
|
|
@@ -15779,12 +16183,12 @@ var DefaultPromptStore = class {
|
|
|
15779
16183
|
}
|
|
15780
16184
|
async save(entry) {
|
|
15781
16185
|
await ensureDir(this.dir);
|
|
15782
|
-
const file =
|
|
16186
|
+
const file = path4.join(this.dir, `${entry.id}.json`);
|
|
15783
16187
|
const raw = { version: SCHEMA_VERSION, entry };
|
|
15784
16188
|
await atomicWrite(file, JSON.stringify(raw, null, 2));
|
|
15785
16189
|
}
|
|
15786
16190
|
async delete(id) {
|
|
15787
|
-
const file =
|
|
16191
|
+
const file = path4.join(this.dir, `${id}.json`);
|
|
15788
16192
|
try {
|
|
15789
16193
|
await fsp7.unlink(file);
|
|
15790
16194
|
return true;
|
|
@@ -15873,7 +16277,7 @@ var DefaultPromptLoader = class {
|
|
|
15873
16277
|
constructor(opts) {
|
|
15874
16278
|
this.projectStore = typeof opts.paths.inProjectPrompts === "string" ? new DefaultPromptStore(opts.paths.inProjectPrompts) : void 0;
|
|
15875
16279
|
this.userStore = typeof opts.paths.globalPrompts === "string" ? new DefaultPromptStore(opts.paths.globalPrompts) : void 0;
|
|
15876
|
-
this.builtinDir = opts.bundledDir ?
|
|
16280
|
+
this.builtinDir = opts.bundledDir ? path4.join(opts.bundledDir, "prompts") : void 0;
|
|
15877
16281
|
}
|
|
15878
16282
|
async list() {
|
|
15879
16283
|
if (this.cache) return this.cache;
|
|
@@ -16005,7 +16409,7 @@ async function walkJson(dir) {
|
|
|
16005
16409
|
return out;
|
|
16006
16410
|
}
|
|
16007
16411
|
for (const e of entries) {
|
|
16008
|
-
const full =
|
|
16412
|
+
const full = path4.join(dir, e.name);
|
|
16009
16413
|
if (e.isDirectory()) {
|
|
16010
16414
|
out.push(...await walkJson(full));
|
|
16011
16415
|
} else if (e.name.endsWith(".json") && e.name !== "index.json" && e.name !== "schema.json") {
|
|
@@ -16051,7 +16455,7 @@ function isSubsequence(needle, hay) {
|
|
|
16051
16455
|
function renderPrompt(entry, values = {}) {
|
|
16052
16456
|
const declared = new Map((entry.variables ?? []).map((v) => [v.name, v]));
|
|
16053
16457
|
const missing = [];
|
|
16054
|
-
const
|
|
16458
|
+
const invalid2 = [];
|
|
16055
16459
|
const text = entry.content.replace(/\{\{\s*([\w.-]+)\s*\}\}/g, (whole, rawName) => {
|
|
16056
16460
|
const name = rawName.trim();
|
|
16057
16461
|
if (Object.hasOwn(values, name) && values[name] !== void 0) {
|
|
@@ -16069,10 +16473,10 @@ function renderPrompt(entry, values = {}) {
|
|
|
16069
16473
|
}
|
|
16070
16474
|
}
|
|
16071
16475
|
if (v.enum && v.enum.length > 0 && Object.hasOwn(values, v.name) && values[v.name] !== void 0 && values[v.name] !== "" && !v.enum.includes(values[v.name])) {
|
|
16072
|
-
|
|
16476
|
+
invalid2.push(v.name);
|
|
16073
16477
|
}
|
|
16074
16478
|
}
|
|
16075
|
-
return { text, missing, invalid };
|
|
16479
|
+
return { text, missing, invalid: invalid2 };
|
|
16076
16480
|
}
|
|
16077
16481
|
function escapeRegExp(s) {
|
|
16078
16482
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -16146,11 +16550,19 @@ function readPolicy(ctx) {
|
|
|
16146
16550
|
if (typeof candidate.preserveK !== "number" || !candidate.thresholds) return null;
|
|
16147
16551
|
return candidate;
|
|
16148
16552
|
}
|
|
16553
|
+
init_error();
|
|
16554
|
+
init_expect_defined();
|
|
16555
|
+
init_json_schema_validate();
|
|
16556
|
+
init_tool_subject();
|
|
16557
|
+
init_tool_output_serializer();
|
|
16558
|
+
init_wstack_paths();
|
|
16559
|
+
init_errors();
|
|
16149
16560
|
|
|
16150
16561
|
// src/types/tool-markers.ts
|
|
16151
16562
|
var MALFORMED_ARG_MARKERS = ["__raw", "__raw_arguments", "_raw"];
|
|
16152
16563
|
|
|
16153
16564
|
// src/execution/tool-executor.ts
|
|
16565
|
+
init_tool_result_render_mode();
|
|
16154
16566
|
var ToolExecutor = class _ToolExecutor {
|
|
16155
16567
|
constructor(registry, opts) {
|
|
16156
16568
|
this.registry = registry;
|
|
@@ -16200,6 +16612,64 @@ var ToolExecutor = class _ToolExecutor {
|
|
|
16200
16612
|
const mode = resolveToolResultRenderMode(modes, toolName);
|
|
16201
16613
|
renderer.setResultRenderMode(toolName, mode);
|
|
16202
16614
|
}
|
|
16615
|
+
toolLogBase(ctx, use, toolName, durationMs) {
|
|
16616
|
+
return {
|
|
16617
|
+
event: "tool.execution",
|
|
16618
|
+
traceId: ctx.traceId,
|
|
16619
|
+
sessionId: ctx.session.id,
|
|
16620
|
+
agentId: ctx.agentId ?? "<unknown>",
|
|
16621
|
+
toolName,
|
|
16622
|
+
toolUseId: use.id,
|
|
16623
|
+
durationMs
|
|
16624
|
+
};
|
|
16625
|
+
}
|
|
16626
|
+
logToolSuccess(ctx, use, toolName, durationMs, outputChars) {
|
|
16627
|
+
this.opts.events?.emit("tool.completed", {
|
|
16628
|
+
name: toolName,
|
|
16629
|
+
id: use.id,
|
|
16630
|
+
sessionId: ctx.session.id,
|
|
16631
|
+
...ctx.traceId ? { traceId: ctx.traceId } : {},
|
|
16632
|
+
agentId: ctx.agentId ?? "<unknown>",
|
|
16633
|
+
durationMs,
|
|
16634
|
+
outputChars
|
|
16635
|
+
});
|
|
16636
|
+
this.opts.logger?.info("tool execution completed", {
|
|
16637
|
+
...this.toolLogBase(ctx, use, toolName, durationMs),
|
|
16638
|
+
outcome: "success",
|
|
16639
|
+
isError: false,
|
|
16640
|
+
outputChars
|
|
16641
|
+
});
|
|
16642
|
+
}
|
|
16643
|
+
logToolFailure(ctx, use, toolName, durationMs, err) {
|
|
16644
|
+
const { category, retryable, detail } = classifyToolError(err);
|
|
16645
|
+
const structured = isWrongStackError(err);
|
|
16646
|
+
const structuredError = structured ? {
|
|
16647
|
+
errorCode: err.code,
|
|
16648
|
+
errorSubsystem: err.subsystem,
|
|
16649
|
+
errorSeverity: err.severity
|
|
16650
|
+
} : {};
|
|
16651
|
+
this.opts.events?.emit("tool.failed", {
|
|
16652
|
+
name: toolName,
|
|
16653
|
+
id: use.id,
|
|
16654
|
+
sessionId: ctx.session.id,
|
|
16655
|
+
...ctx.traceId ? { traceId: ctx.traceId } : {},
|
|
16656
|
+
agentId: ctx.agentId ?? "<unknown>",
|
|
16657
|
+
durationMs,
|
|
16658
|
+
category,
|
|
16659
|
+
retryable,
|
|
16660
|
+
...detail ? { detail } : {},
|
|
16661
|
+
...structuredError
|
|
16662
|
+
});
|
|
16663
|
+
this.opts.logger?.warn("tool execution failed", {
|
|
16664
|
+
...this.toolLogBase(ctx, use, toolName, durationMs),
|
|
16665
|
+
outcome: "failure",
|
|
16666
|
+
isError: true,
|
|
16667
|
+
errorCategory: category,
|
|
16668
|
+
retryable,
|
|
16669
|
+
errorDetail: detail,
|
|
16670
|
+
...structuredError
|
|
16671
|
+
});
|
|
16672
|
+
}
|
|
16203
16673
|
/**
|
|
16204
16674
|
* Execute a batch of tool uses using the configured strategy.
|
|
16205
16675
|
* Returns the execution results and the remaining output budget.
|
|
@@ -16330,7 +16800,8 @@ ${errorDetails}`,
|
|
|
16330
16800
|
"tool.has_dangerous_capabilities": toolCapsForAudit.length > 0
|
|
16331
16801
|
});
|
|
16332
16802
|
try {
|
|
16333
|
-
|
|
16803
|
+
const producedText = await this.produceToolOutput(tool, use, ctx, budget);
|
|
16804
|
+
let { block: result, bytes } = this.settleToolOutput(tool, use, producedText, budget);
|
|
16334
16805
|
budget -= bytes;
|
|
16335
16806
|
if (this.opts.hookRunner?.has("PostToolUse")) {
|
|
16336
16807
|
const post = await this.opts.hookRunner.postToolUse(
|
|
@@ -16347,13 +16818,18 @@ ${post.additionalContext}`;
|
|
|
16347
16818
|
budget = Math.max(0, budget - Buffer.byteLength(appended, "utf8"));
|
|
16348
16819
|
}
|
|
16349
16820
|
}
|
|
16821
|
+
const outputChars = typeof result.content === "string" ? result.content.length : 0;
|
|
16350
16822
|
span?.setAttribute("tool.is_error", !!result.is_error);
|
|
16351
|
-
span?.setAttribute(
|
|
16352
|
-
|
|
16353
|
-
typeof result.content === "string" ? result.content.length : 0
|
|
16354
|
-
);
|
|
16823
|
+
span?.setAttribute("tool.output_bytes", outputChars);
|
|
16824
|
+
this.logToolSuccess(ctx, use, tool.name, Date.now() - start, outputChars);
|
|
16355
16825
|
return { result, tool, durationMs: Date.now() - start };
|
|
16356
16826
|
} catch (err) {
|
|
16827
|
+
if (isWrongStackError(err)) {
|
|
16828
|
+
if (err instanceof Error) span?.recordError(err);
|
|
16829
|
+
span?.setAttribute("tool.is_error", true);
|
|
16830
|
+
this.logToolFailure(ctx, use, tool.name, Date.now() - start, err);
|
|
16831
|
+
throw err;
|
|
16832
|
+
}
|
|
16357
16833
|
const msg = toErrorMessage(err);
|
|
16358
16834
|
const scrubbed = this.opts.secretScrubber.scrub(msg);
|
|
16359
16835
|
const { category, retryable, detail } = classifyToolError(err);
|
|
@@ -16371,6 +16847,7 @@ ${post.additionalContext}`;
|
|
|
16371
16847
|
span?.setAttribute("tool.error_category", category);
|
|
16372
16848
|
span?.setAttribute("tool.error_retryable", retryable);
|
|
16373
16849
|
if (detail) span?.setAttribute("tool.error_detail", detail);
|
|
16850
|
+
this.logToolFailure(ctx, use, tool.name, Date.now() - start, err);
|
|
16374
16851
|
return { result, tool, durationMs: Date.now() - start };
|
|
16375
16852
|
} finally {
|
|
16376
16853
|
span?.end();
|
|
@@ -16380,7 +16857,8 @@ ${post.additionalContext}`;
|
|
|
16380
16857
|
try {
|
|
16381
16858
|
return await runOne(use);
|
|
16382
16859
|
} catch (err) {
|
|
16383
|
-
const
|
|
16860
|
+
const isStructured = isWrongStackError(err);
|
|
16861
|
+
const msg = isStructured ? err.describe() : toErrorMessage(err);
|
|
16384
16862
|
const scrubbed = this.opts.secretScrubber.scrub(msg);
|
|
16385
16863
|
const { category, retryable, detail } = classifyToolError(err);
|
|
16386
16864
|
const tool = this.registry.get(use.name);
|
|
@@ -16390,7 +16868,7 @@ ${post.additionalContext}`;
|
|
|
16390
16868
|
const result = {
|
|
16391
16869
|
type: "tool_result",
|
|
16392
16870
|
tool_use_id: use.id,
|
|
16393
|
-
content: `Tool "${use.name}" execution failed: ${scrubbed}`,
|
|
16871
|
+
content: isStructured ? scrubbed : `Tool "${use.name}" execution failed: ${scrubbed}`,
|
|
16394
16872
|
is_error: true
|
|
16395
16873
|
};
|
|
16396
16874
|
budget = this.budgetForString(result.content, budget);
|
|
@@ -16433,7 +16911,23 @@ ${post.additionalContext}`;
|
|
|
16433
16911
|
* to call a tool" and "tool.executed".
|
|
16434
16912
|
*/
|
|
16435
16913
|
async executeTool(tool, use, ctx, budget) {
|
|
16914
|
+
const text = await this.produceToolOutput(tool, use, ctx, budget);
|
|
16915
|
+
return this.settleToolOutput(tool, use, text, budget);
|
|
16916
|
+
}
|
|
16917
|
+
/**
|
|
16918
|
+
* Async "produce" phase: run the tool, serialize, scrub, and spill an
|
|
16919
|
+
* oversized output to a disk artifact. Returns the pre-cap text. This is
|
|
16920
|
+
* the long-running, concurrency-safe part — it touches NO shared budget
|
|
16921
|
+
* state, so multiple invocations can run in parallel without racing.
|
|
16922
|
+
*
|
|
16923
|
+
* The `budgetHint` only gates the disk-spill threshold (a heuristic for
|
|
16924
|
+
* "is this output large enough to persist"); it is NOT the output cap.
|
|
16925
|
+
* The authoritative cap is applied synchronously in settleToolOutput()
|
|
16926
|
+
* against the live budget.
|
|
16927
|
+
*/
|
|
16928
|
+
async produceToolOutput(tool, use, ctx, budgetHint) {
|
|
16436
16929
|
this.opts.events?.emit("tool.started", {
|
|
16930
|
+
sessionId: ctx.session.id,
|
|
16437
16931
|
name: tool.name,
|
|
16438
16932
|
id: use.id,
|
|
16439
16933
|
input: use.input
|
|
@@ -16442,8 +16936,20 @@ ${post.additionalContext}`;
|
|
|
16442
16936
|
const output = await this.runWithTimeout(tool, use.input, ctx.signal, ctx, use.id);
|
|
16443
16937
|
const text = this.serializer.serialize(output, { toolName: tool.name, input: use.input, tool });
|
|
16444
16938
|
const scrubbed = this.opts.secretScrubber.scrub(text);
|
|
16445
|
-
|
|
16446
|
-
|
|
16939
|
+
return maybePersistLargeToolOutput(tool.name, scrubbed, budgetHint);
|
|
16940
|
+
}
|
|
16941
|
+
/**
|
|
16942
|
+
* Synchronous "settle" phase: enforce the output cap against the CURRENT
|
|
16943
|
+
* budget, render, and build the result block. This MUST stay synchronous
|
|
16944
|
+
* (no awaits) so that, in the parallel/smart strategies, two tools settling
|
|
16945
|
+
* one after another against the shared closure budget can't interleave a
|
|
16946
|
+
* stale read with a write. The first to settle consumes its bytes; the next
|
|
16947
|
+
* settles against the reduced budget; once the budget hits 0, enforceCap
|
|
16948
|
+
* truncates — making the per-iteration cap genuinely CUMULATIVE across
|
|
16949
|
+
* parallel tools instead of degrading into a per-tool cap.
|
|
16950
|
+
*/
|
|
16951
|
+
settleToolOutput(tool, use, text, budget) {
|
|
16952
|
+
const { text: capped, newBudget } = this.serializer.enforceCap(text, budget);
|
|
16447
16953
|
this.hintRenderMode(tool.name);
|
|
16448
16954
|
this.opts.renderer?.writeToolResult(tool.name, capped, false);
|
|
16449
16955
|
return {
|
|
@@ -16496,7 +17002,12 @@ ${post.additionalContext}`;
|
|
|
16496
17002
|
let finalOutput;
|
|
16497
17003
|
let sawFinal = false;
|
|
16498
17004
|
if (!tool.executeStream) {
|
|
16499
|
-
throw new
|
|
17005
|
+
throw new ToolError({
|
|
17006
|
+
message: `Tool "${tool.name}" does not support streaming execution`,
|
|
17007
|
+
code: "TOOL_EXECUTION_FAILED",
|
|
17008
|
+
toolName: tool.name,
|
|
17009
|
+
context: { reason: "streaming_not_supported" }
|
|
17010
|
+
});
|
|
16500
17011
|
}
|
|
16501
17012
|
const stream = tool.executeStream(input, ctx, { signal });
|
|
16502
17013
|
const iter = stream[Symbol.asyncIterator]();
|
|
@@ -16506,6 +17017,7 @@ ${post.additionalContext}`;
|
|
|
16506
17017
|
let lastProgressEmitAt = 0;
|
|
16507
17018
|
const emitProgress = (ev) => {
|
|
16508
17019
|
this.opts.events?.emit("tool.progress", {
|
|
17020
|
+
sessionId: ctx.session.id,
|
|
16509
17021
|
name: tool.name,
|
|
16510
17022
|
id: toolUseId ?? "<unknown>",
|
|
16511
17023
|
event: ev
|
|
@@ -16561,7 +17073,12 @@ ${progressTail}`;
|
|
|
16561
17073
|
await iter.return?.(void 0);
|
|
16562
17074
|
}
|
|
16563
17075
|
if (!sawFinal) {
|
|
16564
|
-
throw new
|
|
17076
|
+
throw new ToolError({
|
|
17077
|
+
message: `tool "${tool.name}" executeStream completed without a 'final' event`,
|
|
17078
|
+
code: "TOOL_EXECUTION_FAILED",
|
|
17079
|
+
toolName: tool.name,
|
|
17080
|
+
context: { reason: "missing_final_event" }
|
|
17081
|
+
});
|
|
16565
17082
|
}
|
|
16566
17083
|
return finalOutput;
|
|
16567
17084
|
}
|
|
@@ -16685,6 +17202,15 @@ function classifyToolError(err) {
|
|
|
16685
17202
|
if (err instanceof Error && err.message.includes("validation")) {
|
|
16686
17203
|
return { category: "validation" /* VALIDATION */, retryable: false, detail: "validation" };
|
|
16687
17204
|
}
|
|
17205
|
+
if (err instanceof WrongStackError) {
|
|
17206
|
+
const wse = err;
|
|
17207
|
+
const category = wse.severity === "warning" ? "transient" /* TRANSIENT */ : "fatal" /* FATAL */;
|
|
17208
|
+
return {
|
|
17209
|
+
category,
|
|
17210
|
+
retryable: wse.recoverable,
|
|
17211
|
+
detail: `${wse.code} [${wse.subsystem}]`
|
|
17212
|
+
};
|
|
17213
|
+
}
|
|
16688
17214
|
return {
|
|
16689
17215
|
category: "fatal" /* FATAL */,
|
|
16690
17216
|
retryable: false,
|
|
@@ -16712,11 +17238,11 @@ async function maybePersistLargeToolOutput(toolName, content, budget) {
|
|
|
16712
17238
|
return content;
|
|
16713
17239
|
}
|
|
16714
17240
|
try {
|
|
16715
|
-
const dir =
|
|
17241
|
+
const dir = path4.join(wstackGlobalRoot(), "tool-output");
|
|
16716
17242
|
await fsp7.mkdir(dir, { recursive: true });
|
|
16717
17243
|
const safeTool = toolName.replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40) || "tool";
|
|
16718
17244
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
16719
|
-
const filePath =
|
|
17245
|
+
const filePath = path4.join(dir, `${stamp}-${safeTool}-${randomUUID()}.log`);
|
|
16720
17246
|
await fsp7.writeFile(filePath, content, "utf8");
|
|
16721
17247
|
return content + `
|
|
16722
17248
|
[full tool output: ${bytes} bytes at ${filePath}; read/grep that file selectively instead of re-running or requesting more output]`;
|
|
@@ -16726,6 +17252,8 @@ async function maybePersistLargeToolOutput(toolName, content, budget) {
|
|
|
16726
17252
|
}
|
|
16727
17253
|
|
|
16728
17254
|
// src/infrastructure/context-manager.ts
|
|
17255
|
+
init_message_invariants();
|
|
17256
|
+
init_token_estimate();
|
|
16729
17257
|
var CONTEXT_MANAGER_TOOL_NAME = "context_manager";
|
|
16730
17258
|
function roughEstimate(messages) {
|
|
16731
17259
|
return estimateMessageTokens(messages);
|
|
@@ -16981,6 +17509,10 @@ function createContextManagerTool(opts = {}) {
|
|
|
16981
17509
|
};
|
|
16982
17510
|
}
|
|
16983
17511
|
var contextManagerTool = createContextManagerTool();
|
|
17512
|
+
|
|
17513
|
+
// src/infrastructure/logger.ts
|
|
17514
|
+
init_color();
|
|
17515
|
+
init_term();
|
|
16984
17516
|
var LEVEL_RANK2 = {
|
|
16985
17517
|
error: 0,
|
|
16986
17518
|
warn: 1,
|
|
@@ -17044,7 +17576,7 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
17044
17576
|
this.stderr = opts.stderr !== false;
|
|
17045
17577
|
this.maxFileBytes = opts.maxFileBytes ?? 10 * 1024 * 1024;
|
|
17046
17578
|
if (this.file) {
|
|
17047
|
-
const dir =
|
|
17579
|
+
const dir = path4.dirname(this.file);
|
|
17048
17580
|
this._tail = this._tail.then(async () => {
|
|
17049
17581
|
await fsp7.mkdir(dir, { recursive: true });
|
|
17050
17582
|
}).catch(() => void 0);
|
|
@@ -17346,18 +17878,18 @@ init_atomic_write();
|
|
|
17346
17878
|
function modePrompt(id) {
|
|
17347
17879
|
for (const dir of modePromptDirCandidates()) {
|
|
17348
17880
|
try {
|
|
17349
|
-
return readFileSync(
|
|
17881
|
+
return readFileSync(path4.join(dir, `${id}.md`), "utf8").trimEnd();
|
|
17350
17882
|
} catch {
|
|
17351
17883
|
}
|
|
17352
17884
|
}
|
|
17353
17885
|
return "";
|
|
17354
17886
|
}
|
|
17355
17887
|
function modePromptDirCandidates() {
|
|
17356
|
-
const here =
|
|
17888
|
+
const here = path4.dirname(fileURLToPath(import.meta.url));
|
|
17357
17889
|
const candidates = [
|
|
17358
|
-
|
|
17359
|
-
|
|
17360
|
-
|
|
17890
|
+
path4.resolve(here, "../../instructions/modes"),
|
|
17891
|
+
path4.resolve(here, "../instructions/modes"),
|
|
17892
|
+
path4.resolve(here, "instructions/modes")
|
|
17361
17893
|
];
|
|
17362
17894
|
return candidates.sort((a, b) => Number(!isDirectory3(a)) - Number(!isDirectory3(b)));
|
|
17363
17895
|
}
|
|
@@ -17474,7 +18006,7 @@ var DEFAULT_MODES = [
|
|
|
17474
18006
|
description: "Current-data research \u2014 search web, verify, inject findings into context",
|
|
17475
18007
|
prompt: modePrompt("research-web"),
|
|
17476
18008
|
tags: ["research", "web", "current-data", "up-to-date"],
|
|
17477
|
-
toolPreferences: ["
|
|
18009
|
+
toolPreferences: ["search/fetch", "search/fetch", "search", "fetch", "context_manager"],
|
|
17478
18010
|
suggestedSkills: ["research-web", "tech-stack", "node-modern", "security-scanner", "react-modern"]
|
|
17479
18011
|
}
|
|
17480
18012
|
];
|
|
@@ -17526,7 +18058,7 @@ var DefaultModeStore = class {
|
|
|
17526
18058
|
}
|
|
17527
18059
|
async loadActiveMode() {
|
|
17528
18060
|
try {
|
|
17529
|
-
const configPath =
|
|
18061
|
+
const configPath = path4.join(this.configDir, "mode.json");
|
|
17530
18062
|
const content = await fsp7.readFile(configPath, "utf8");
|
|
17531
18063
|
const data = JSON.parse(content);
|
|
17532
18064
|
this.activeModeId = data.activeMode ?? null;
|
|
@@ -17537,7 +18069,7 @@ var DefaultModeStore = class {
|
|
|
17537
18069
|
async saveActiveMode() {
|
|
17538
18070
|
try {
|
|
17539
18071
|
await fsp7.mkdir(this.configDir, { recursive: true });
|
|
17540
|
-
const configPath =
|
|
18072
|
+
const configPath = path4.join(this.configDir, "mode.json");
|
|
17541
18073
|
await atomicWrite(
|
|
17542
18074
|
configPath,
|
|
17543
18075
|
JSON.stringify({ activeMode: this.activeModeId }, null, 2)
|
|
@@ -17552,11 +18084,11 @@ async function loadProjectModes(modesDir) {
|
|
|
17552
18084
|
const entries = await fsp7.readdir(modesDir);
|
|
17553
18085
|
for (const entry of entries) {
|
|
17554
18086
|
if (!entry.endsWith(".md") && !entry.endsWith(".txt")) continue;
|
|
17555
|
-
const filePath =
|
|
17556
|
-
const
|
|
17557
|
-
if (!
|
|
18087
|
+
const filePath = path4.join(modesDir, entry);
|
|
18088
|
+
const stat10 = await fsp7.stat(filePath);
|
|
18089
|
+
if (!stat10.isFile()) continue;
|
|
17558
18090
|
const content = await fsp7.readFile(filePath, "utf8");
|
|
17559
|
-
const id =
|
|
18091
|
+
const id = path4.basename(entry, path4.extname(entry));
|
|
17560
18092
|
modes.push({
|
|
17561
18093
|
id,
|
|
17562
18094
|
name: id.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
@@ -17572,7 +18104,7 @@ async function loadProjectModes(modesDir) {
|
|
|
17572
18104
|
async function loadUserModes(modesDir) {
|
|
17573
18105
|
const modes = [];
|
|
17574
18106
|
try {
|
|
17575
|
-
const manifestPath =
|
|
18107
|
+
const manifestPath = path4.join(modesDir, "modes.json");
|
|
17576
18108
|
const content = await fsp7.readFile(manifestPath, "utf8");
|
|
17577
18109
|
const manifest = JSON.parse(content);
|
|
17578
18110
|
for (const mode of manifest.modes) {
|
|
@@ -17585,6 +18117,9 @@ async function loadUserModes(modesDir) {
|
|
|
17585
18117
|
|
|
17586
18118
|
// src/models/models-registry.ts
|
|
17587
18119
|
init_atomic_write();
|
|
18120
|
+
init_error();
|
|
18121
|
+
init_merge_models_payload();
|
|
18122
|
+
init_errors();
|
|
17588
18123
|
var DEFAULT_URL = "https://models.dev/api.json";
|
|
17589
18124
|
var ENV_URL_KEY = "WRONGSTACK_MODELS_DEV_URL";
|
|
17590
18125
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -17618,6 +18153,14 @@ var DefaultModelsRegistry = class {
|
|
|
17618
18153
|
payload;
|
|
17619
18154
|
/** Memoised overlay payload (in-memory / fetched / file). */
|
|
17620
18155
|
overlayPayload;
|
|
18156
|
+
/**
|
|
18157
|
+
* Extra providers injected at runtime via `mergeOverlay()` — e.g. an
|
|
18158
|
+
* openai-compatible server (omniroute, LiteLLM, …) auto-discovered from its
|
|
18159
|
+
* `/v1/models` endpoint at boot. Applied LAST (on top of base + curated
|
|
18160
|
+
* overlay) and re-applied across `refresh()` so the discovered catalog
|
|
18161
|
+
* survives a models.dev refetch.
|
|
18162
|
+
*/
|
|
18163
|
+
extraOverlay;
|
|
17621
18164
|
fetchedAt;
|
|
17622
18165
|
cacheFile;
|
|
17623
18166
|
url;
|
|
@@ -17642,7 +18185,7 @@ var DefaultModelsRegistry = class {
|
|
|
17642
18185
|
this.overlay = opts.overlay;
|
|
17643
18186
|
this.overlayUrl = opts.overlayUrl;
|
|
17644
18187
|
this.overlayFile = opts.overlayFile;
|
|
17645
|
-
this.overlayCacheFile = opts.overlayCacheFile ?? (opts.overlayUrl ?
|
|
18188
|
+
this.overlayCacheFile = opts.overlayCacheFile ?? (opts.overlayUrl ? path4.join(path4.dirname(opts.cacheFile), "models-overlay-cache.json") : void 0);
|
|
17646
18189
|
}
|
|
17647
18190
|
async load(opts = {}) {
|
|
17648
18191
|
if (this.payload && !opts.force) return this.payload;
|
|
@@ -17653,9 +18196,22 @@ var DefaultModelsRegistry = class {
|
|
|
17653
18196
|
}
|
|
17654
18197
|
const overlay = await this.loadOverlay(opts);
|
|
17655
18198
|
const base = await this.loadBase(opts, Object.keys(overlay).length > 0);
|
|
17656
|
-
this.payload = mergeModelsPayload(base, overlay);
|
|
18199
|
+
this.payload = this.withExtraOverlay(mergeModelsPayload(base, overlay));
|
|
17657
18200
|
return this.payload;
|
|
17658
18201
|
}
|
|
18202
|
+
/**
|
|
18203
|
+
* Merge an additional provider payload on top of the resolved catalog. Used
|
|
18204
|
+
* for runtime-discovered openai-compatible providers. Remembered so it is
|
|
18205
|
+
* re-applied across `refresh()`. A no-op for an empty payload.
|
|
18206
|
+
*/
|
|
18207
|
+
mergeOverlay(payload) {
|
|
18208
|
+
if (!hasEntries(payload)) return;
|
|
18209
|
+
this.extraOverlay = this.extraOverlay ? mergeModelsPayload(this.extraOverlay, payload) : payload;
|
|
18210
|
+
if (this.payload) this.payload = mergeModelsPayload(this.payload, this.extraOverlay);
|
|
18211
|
+
}
|
|
18212
|
+
withExtraOverlay(payload) {
|
|
18213
|
+
return this.extraOverlay ? mergeModelsPayload(payload, this.extraOverlay) : payload;
|
|
18214
|
+
}
|
|
17659
18215
|
/**
|
|
17660
18216
|
* Load the models.dev base payload: fresh cache → network → stale cache.
|
|
17661
18217
|
* On total failure, degrade to `{}` (so a non-empty overlay still drives
|
|
@@ -17704,7 +18260,11 @@ var DefaultModelsRegistry = class {
|
|
|
17704
18260
|
});
|
|
17705
18261
|
clearTimeout(timeout);
|
|
17706
18262
|
if (!res.ok) {
|
|
17707
|
-
throw new
|
|
18263
|
+
throw new FetchError({
|
|
18264
|
+
message: `ModelsRegistry: HTTP ${res.status} fetching ${this.url}`,
|
|
18265
|
+
status: res.status,
|
|
18266
|
+
context: { url: this.url, op: "refreshModels" }
|
|
18267
|
+
});
|
|
17708
18268
|
}
|
|
17709
18269
|
const json = await res.json();
|
|
17710
18270
|
this.fetchedAt = /* @__PURE__ */ new Date();
|
|
@@ -17718,7 +18278,11 @@ var DefaultModelsRegistry = class {
|
|
|
17718
18278
|
} catch (err) {
|
|
17719
18279
|
clearTimeout(timeout);
|
|
17720
18280
|
if (err instanceof Error && err.name === "AbortError") {
|
|
17721
|
-
throw new
|
|
18281
|
+
throw new FetchError({
|
|
18282
|
+
message: `ModelsRegistry: fetch timed out after ${this.refreshTimeoutMs}ms`,
|
|
18283
|
+
status: 408,
|
|
18284
|
+
context: { url: this.url, op: "refreshModels", timedOut: true }
|
|
18285
|
+
});
|
|
17722
18286
|
}
|
|
17723
18287
|
throw err;
|
|
17724
18288
|
}
|
|
@@ -17754,7 +18318,11 @@ var DefaultModelsRegistry = class {
|
|
|
17754
18318
|
method: "GET",
|
|
17755
18319
|
headers: { accept: "application/json" }
|
|
17756
18320
|
});
|
|
17757
|
-
if (!res.ok) throw new
|
|
18321
|
+
if (!res.ok) throw new FetchError({
|
|
18322
|
+
message: `HTTP ${res.status}`,
|
|
18323
|
+
status: res.status,
|
|
18324
|
+
context: { url: this.url, op: "refreshModels" }
|
|
18325
|
+
});
|
|
17758
18326
|
const json = await res.json();
|
|
17759
18327
|
const envelope = {
|
|
17760
18328
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -17788,7 +18356,7 @@ var DefaultModelsRegistry = class {
|
|
|
17788
18356
|
async refresh() {
|
|
17789
18357
|
const base = await this.refreshBase();
|
|
17790
18358
|
const overlay = await this.loadOverlay({ force: true });
|
|
17791
|
-
this.payload = mergeModelsPayload(base, overlay);
|
|
18359
|
+
this.payload = this.withExtraOverlay(mergeModelsPayload(base, overlay));
|
|
17792
18360
|
return this.payload;
|
|
17793
18361
|
}
|
|
17794
18362
|
async listProviders() {
|
|
@@ -17866,7 +18434,7 @@ var DefaultModelsRegistry = class {
|
|
|
17866
18434
|
}
|
|
17867
18435
|
/** Used by `wstack models refresh` to expose where the cache lives. */
|
|
17868
18436
|
cacheLocation() {
|
|
17869
|
-
return
|
|
18437
|
+
return path4.resolve(this.cacheFile);
|
|
17870
18438
|
}
|
|
17871
18439
|
};
|
|
17872
18440
|
function formatAge(seconds) {
|
|
@@ -18048,6 +18616,7 @@ var NoopMetricsSink = class {
|
|
|
18048
18616
|
};
|
|
18049
18617
|
|
|
18050
18618
|
// src/observability/health.ts
|
|
18619
|
+
init_error();
|
|
18051
18620
|
var SEVERITY = {
|
|
18052
18621
|
healthy: 0,
|
|
18053
18622
|
degraded: 1,
|
|
@@ -18080,9 +18649,9 @@ var DefaultHealthRegistry = class {
|
|
|
18080
18649
|
}
|
|
18081
18650
|
async runOne(check) {
|
|
18082
18651
|
let timer = null;
|
|
18083
|
-
const timeout = new Promise((
|
|
18652
|
+
const timeout = new Promise((resolve12) => {
|
|
18084
18653
|
timer = setTimeout(
|
|
18085
|
-
() =>
|
|
18654
|
+
() => resolve12({ status: "unhealthy", detail: `timeout after ${this.timeoutMs}ms` }),
|
|
18086
18655
|
this.timeoutMs
|
|
18087
18656
|
);
|
|
18088
18657
|
});
|
|
@@ -18205,6 +18774,7 @@ function wireMetricsToEvents(events, sink) {
|
|
|
18205
18774
|
}
|
|
18206
18775
|
|
|
18207
18776
|
// src/observability/prometheus.ts
|
|
18777
|
+
init_error();
|
|
18208
18778
|
var NUMBER_FORMAT_INFINITY = "NaN";
|
|
18209
18779
|
function escapeLabelValue(v) {
|
|
18210
18780
|
return v.replace(/\\/g, "\\\\").replace(/\n/g, "\\n").replace(/"/g, '\\"');
|
|
@@ -18321,14 +18891,14 @@ async function startMetricsServer(opts) {
|
|
|
18321
18891
|
const { createServer } = await import('http');
|
|
18322
18892
|
server = createServer(listener);
|
|
18323
18893
|
}
|
|
18324
|
-
await new Promise((
|
|
18894
|
+
await new Promise((resolve12, reject) => {
|
|
18325
18895
|
const onError = (err) => {
|
|
18326
18896
|
server.off("listening", onListening);
|
|
18327
18897
|
reject(err);
|
|
18328
18898
|
};
|
|
18329
18899
|
const onListening = () => {
|
|
18330
18900
|
server.off("error", onError);
|
|
18331
|
-
|
|
18901
|
+
resolve12();
|
|
18332
18902
|
};
|
|
18333
18903
|
server.once("error", onError);
|
|
18334
18904
|
server.once("listening", onListening);
|
|
@@ -18340,8 +18910,8 @@ async function startMetricsServer(opts) {
|
|
|
18340
18910
|
return {
|
|
18341
18911
|
port: boundPort,
|
|
18342
18912
|
url: `${protocol}://${host}:${boundPort}${path32}`,
|
|
18343
|
-
close: () => new Promise((
|
|
18344
|
-
server.close((err) => err ? reject(err) :
|
|
18913
|
+
close: () => new Promise((resolve12, reject) => {
|
|
18914
|
+
server.close((err) => err ? reject(err) : resolve12());
|
|
18345
18915
|
})
|
|
18346
18916
|
};
|
|
18347
18917
|
}
|
|
@@ -18607,6 +19177,9 @@ function startOtlpTraceExporter(opts) {
|
|
|
18607
19177
|
};
|
|
18608
19178
|
}
|
|
18609
19179
|
|
|
19180
|
+
// src/sdd/critical-path.ts
|
|
19181
|
+
init_expect_defined();
|
|
19182
|
+
|
|
18610
19183
|
// src/types/task-graph.ts
|
|
18611
19184
|
function computeTaskProgress(graph) {
|
|
18612
19185
|
let completed = 0;
|
|
@@ -19518,13 +20091,22 @@ var SddBoardProjector = class _SddBoardProjector {
|
|
|
19518
20091
|
this.timer = null;
|
|
19519
20092
|
}
|
|
19520
20093
|
const snap = this.build();
|
|
19521
|
-
|
|
20094
|
+
const sessionId = this.currentSessionId();
|
|
20095
|
+
this.o.events.emit("sdd.board.snapshot", {
|
|
20096
|
+
...sessionId ? { sessionId } : {},
|
|
20097
|
+
runId: this.o.runId,
|
|
20098
|
+
snapshot: snap
|
|
20099
|
+
});
|
|
19522
20100
|
if (this.o.store) {
|
|
19523
20101
|
const store = this.o.store;
|
|
19524
20102
|
this.lastSave = this.lastSave.then(() => store.saveSnapshot(snap)).catch(() => {
|
|
19525
20103
|
});
|
|
19526
20104
|
}
|
|
19527
20105
|
}
|
|
20106
|
+
currentSessionId() {
|
|
20107
|
+
const value = typeof this.o.sessionId === "function" ? this.o.sessionId() : this.o.sessionId;
|
|
20108
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
20109
|
+
}
|
|
19528
20110
|
};
|
|
19529
20111
|
|
|
19530
20112
|
// src/sdd/sdd-board-store.ts
|
|
@@ -19534,16 +20116,16 @@ var SddBoardStore = class {
|
|
|
19534
20116
|
indexPath;
|
|
19535
20117
|
constructor(opts) {
|
|
19536
20118
|
this.baseDir = opts.baseDir;
|
|
19537
|
-
this.indexPath =
|
|
20119
|
+
this.indexPath = path4.join(this.baseDir, "_index.json");
|
|
19538
20120
|
}
|
|
19539
20121
|
snapshotPath(runId) {
|
|
19540
|
-
return
|
|
20122
|
+
return path4.join(this.baseDir, `${this.safe(runId)}.json`);
|
|
19541
20123
|
}
|
|
19542
20124
|
eventsPath(runId) {
|
|
19543
|
-
return
|
|
20125
|
+
return path4.join(this.baseDir, `${this.safe(runId)}.events.jsonl`);
|
|
19544
20126
|
}
|
|
19545
20127
|
controlPath(runId) {
|
|
19546
|
-
return
|
|
20128
|
+
return path4.join(this.baseDir, `${this.safe(runId)}.control.jsonl`);
|
|
19547
20129
|
}
|
|
19548
20130
|
async saveSnapshot(snapshot) {
|
|
19549
20131
|
await ensureDir(this.baseDir);
|
|
@@ -19649,6 +20231,9 @@ var SddBoardStore = class {
|
|
|
19649
20231
|
};
|
|
19650
20232
|
|
|
19651
20233
|
// src/sdd/spec-builder.ts
|
|
20234
|
+
init_expect_defined();
|
|
20235
|
+
init_error();
|
|
20236
|
+
init_errors();
|
|
19652
20237
|
function buildQuestioningPrompt(session, min, max) {
|
|
19653
20238
|
const answered = session.answers.length;
|
|
19654
20239
|
const remaining = Math.max(0, min - answered);
|
|
@@ -20202,6 +20787,8 @@ var AISpecBuilder = class {
|
|
|
20202
20787
|
};
|
|
20203
20788
|
|
|
20204
20789
|
// src/sdd/task-tracker.ts
|
|
20790
|
+
init_errors();
|
|
20791
|
+
init_error();
|
|
20205
20792
|
var TaskTracker = class {
|
|
20206
20793
|
constructor(opts) {
|
|
20207
20794
|
this.opts = opts;
|
|
@@ -21026,10 +21613,15 @@ function isExplanatoryText(text) {
|
|
|
21026
21613
|
const lower = text.toLowerCase();
|
|
21027
21614
|
return lower.startsWith("i'") || lower.startsWith("i will") || lower.startsWith("let me") || lower.startsWith("here's my") || lower.startsWith("here is my") || lower.startsWith("i'm going to") || lower.startsWith("first, let me") || lower.startsWith("sure") || lower.startsWith("of course") || lower.startsWith("okay") || lower.startsWith("ok,") || lower.startsWith("sounds good") || lower.startsWith("no problem") || text.split("\n").length < 3 && !text.includes(".");
|
|
21028
21615
|
}
|
|
21616
|
+
|
|
21617
|
+
// src/worktree/worktree-manager.ts
|
|
21618
|
+
init_child_env();
|
|
21619
|
+
init_error();
|
|
21029
21620
|
var MAX_SLUG = 40;
|
|
21030
21621
|
var WorktreeManager = class {
|
|
21031
21622
|
projectRoot;
|
|
21032
21623
|
events;
|
|
21624
|
+
sessionIdSource;
|
|
21033
21625
|
gitBin;
|
|
21034
21626
|
runGit;
|
|
21035
21627
|
/** Keyed by ownerId. */
|
|
@@ -21038,6 +21630,7 @@ var WorktreeManager = class {
|
|
|
21038
21630
|
constructor(opts) {
|
|
21039
21631
|
this.projectRoot = resolve(opts.projectRoot);
|
|
21040
21632
|
this.events = opts.events;
|
|
21633
|
+
this.sessionIdSource = opts.sessionId;
|
|
21041
21634
|
this.gitBin = opts.gitBin ?? "git";
|
|
21042
21635
|
this.runGit = opts.run ?? ((args, cwd) => this.defaultRun(args, cwd));
|
|
21043
21636
|
}
|
|
@@ -21631,7 +22224,15 @@ ${check.stderr}`);
|
|
|
21631
22224
|
if (patch) Object.assign(handle, patch);
|
|
21632
22225
|
}
|
|
21633
22226
|
emit(event, payload) {
|
|
21634
|
-
this.
|
|
22227
|
+
const sessionId = this.currentSessionId();
|
|
22228
|
+
this.events?.emit(
|
|
22229
|
+
event,
|
|
22230
|
+
sessionId && payload && typeof payload === "object" ? { ...payload, sessionId } : payload
|
|
22231
|
+
);
|
|
22232
|
+
}
|
|
22233
|
+
currentSessionId() {
|
|
22234
|
+
const value = typeof this.sessionIdSource === "function" ? this.sessionIdSource() : this.sessionIdSource;
|
|
22235
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
21635
22236
|
}
|
|
21636
22237
|
defaultRun(args, cwd) {
|
|
21637
22238
|
return new Promise((res) => {
|
|
@@ -21784,6 +22385,10 @@ async function applySddLifecycle(op, opts) {
|
|
|
21784
22385
|
}
|
|
21785
22386
|
}
|
|
21786
22387
|
|
|
22388
|
+
// src/sdd/sdd-parallel-run.ts
|
|
22389
|
+
init_expect_defined();
|
|
22390
|
+
init_errors();
|
|
22391
|
+
|
|
21787
22392
|
// src/sdd/sdd-task-decomposer.ts
|
|
21788
22393
|
var SddTaskDecomposer = class {
|
|
21789
22394
|
constructor(tracker, _graph, opts = {}) {
|
|
@@ -21902,6 +22507,7 @@ var SddParallelRun = class {
|
|
|
21902
22507
|
this.maxFailedSweeps = Math.max(0, opts.maxFailedRetrySweeps ?? 2);
|
|
21903
22508
|
this.runId = opts.runId ?? `sdd-${randomUUID().slice(0, 8)}`;
|
|
21904
22509
|
this.events = opts.events;
|
|
22510
|
+
this.sessionIdSource = opts.sessionId;
|
|
21905
22511
|
this.maxTotalWaves = opts.maxTotalWaves ?? opts.graph.nodes.size * (this.maxRetries + 2) + 10;
|
|
21906
22512
|
this.maxWallClockMs = opts.maxWallClockMs;
|
|
21907
22513
|
this.maxRecoveryRounds = Math.max(0, opts.maxRecoveryRounds ?? 0);
|
|
@@ -21930,6 +22536,7 @@ var SddParallelRun = class {
|
|
|
21930
22536
|
retryMap = /* @__PURE__ */ new Map();
|
|
21931
22537
|
runId;
|
|
21932
22538
|
events;
|
|
22539
|
+
sessionIdSource;
|
|
21933
22540
|
maxTotalWaves;
|
|
21934
22541
|
maxWallClockMs;
|
|
21935
22542
|
maxRecoveryRounds;
|
|
@@ -21962,7 +22569,15 @@ var SddParallelRun = class {
|
|
|
21962
22569
|
round = 0;
|
|
21963
22570
|
/** Type-safe emit on the optional EventBus (no-op when unwired). */
|
|
21964
22571
|
emit(event, payload) {
|
|
21965
|
-
this.
|
|
22572
|
+
const sessionId = this.currentSessionId();
|
|
22573
|
+
this.events?.emit(
|
|
22574
|
+
event,
|
|
22575
|
+
sessionId ? { ...payload, sessionId } : payload
|
|
22576
|
+
);
|
|
22577
|
+
}
|
|
22578
|
+
currentSessionId() {
|
|
22579
|
+
const value = typeof this.sessionIdSource === "function" ? this.sessionIdSource() : this.sessionIdSource;
|
|
22580
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
21966
22581
|
}
|
|
21967
22582
|
// -------------------------------------------------------------------
|
|
21968
22583
|
// Public API
|
|
@@ -23094,7 +23709,7 @@ var SpecStore = class {
|
|
|
23094
23709
|
indexPath;
|
|
23095
23710
|
constructor(opts) {
|
|
23096
23711
|
this.baseDir = opts.baseDir;
|
|
23097
|
-
this.indexPath =
|
|
23712
|
+
this.indexPath = path4.join(this.baseDir, "_index.json");
|
|
23098
23713
|
}
|
|
23099
23714
|
async save(spec) {
|
|
23100
23715
|
await ensureDir(this.baseDir);
|
|
@@ -23163,7 +23778,7 @@ var SpecStore = class {
|
|
|
23163
23778
|
return updated;
|
|
23164
23779
|
}
|
|
23165
23780
|
filePath(id) {
|
|
23166
|
-
return
|
|
23781
|
+
return path4.join(this.baseDir, `${id}.json`);
|
|
23167
23782
|
}
|
|
23168
23783
|
async readIndex() {
|
|
23169
23784
|
try {
|
|
@@ -23316,6 +23931,7 @@ function templateToMarkdown(template, title) {
|
|
|
23316
23931
|
}
|
|
23317
23932
|
|
|
23318
23933
|
// src/sdd/spec-versioning.ts
|
|
23934
|
+
init_assert_never();
|
|
23319
23935
|
var SpecVersioning = class {
|
|
23320
23936
|
versions = /* @__PURE__ */ new Map();
|
|
23321
23937
|
/** Record a new version of a spec. */
|
|
@@ -23487,6 +24103,7 @@ function startSddRun(opts) {
|
|
|
23487
24103
|
graph: opts.graph,
|
|
23488
24104
|
agent: opts.agent,
|
|
23489
24105
|
projectRoot: opts.projectRoot,
|
|
24106
|
+
sessionId: opts.sessionId,
|
|
23490
24107
|
parallelSlots: opts.parallelSlots,
|
|
23491
24108
|
taskTimeoutMs: opts.taskTimeoutMs,
|
|
23492
24109
|
taskIdleTimeoutMs: opts.taskIdleTimeoutMs,
|
|
@@ -23509,6 +24126,7 @@ function startSddRun(opts) {
|
|
|
23509
24126
|
tracker: opts.tracker,
|
|
23510
24127
|
events: opts.events,
|
|
23511
24128
|
store: opts.boardStore,
|
|
24129
|
+
sessionId: opts.sessionId,
|
|
23512
24130
|
specId: opts.graph.specId,
|
|
23513
24131
|
defaultModel: opts.defaultModel,
|
|
23514
24132
|
defaultProvider: opts.defaultProvider,
|
|
@@ -23585,6 +24203,7 @@ function startSddRun(opts) {
|
|
|
23585
24203
|
}
|
|
23586
24204
|
|
|
23587
24205
|
// src/sdd/task-flow.ts
|
|
24206
|
+
init_errors();
|
|
23588
24207
|
var TaskFlow = class {
|
|
23589
24208
|
constructor(opts) {
|
|
23590
24209
|
this.opts = opts;
|
|
@@ -23793,7 +24412,7 @@ var TaskGraphStore = class {
|
|
|
23793
24412
|
indexPath;
|
|
23794
24413
|
constructor(opts) {
|
|
23795
24414
|
this.baseDir = opts.baseDir;
|
|
23796
|
-
this.indexPath =
|
|
24415
|
+
this.indexPath = path4.join(this.baseDir, "_index.json");
|
|
23797
24416
|
}
|
|
23798
24417
|
async save(graph) {
|
|
23799
24418
|
await ensureDir(this.baseDir);
|
|
@@ -23831,7 +24450,7 @@ var TaskGraphStore = class {
|
|
|
23831
24450
|
}
|
|
23832
24451
|
}
|
|
23833
24452
|
filePath(id) {
|
|
23834
|
-
return
|
|
24453
|
+
return path4.join(this.baseDir, `${id}.json`);
|
|
23835
24454
|
}
|
|
23836
24455
|
async readIndex() {
|
|
23837
24456
|
try {
|
|
@@ -23872,6 +24491,7 @@ var TaskGraphStore = class {
|
|
|
23872
24491
|
};
|
|
23873
24492
|
|
|
23874
24493
|
// src/sdd/task-visualizer.ts
|
|
24494
|
+
init_string();
|
|
23875
24495
|
var STATUS_ICON = {
|
|
23876
24496
|
pending: "\u25CB",
|
|
23877
24497
|
in_progress: "\u25D0",
|
|
@@ -24027,7 +24647,7 @@ function makeCommandVerifier(options = {}) {
|
|
|
24027
24647
|
return async function verifyTask(info) {
|
|
24028
24648
|
const cmd = info.task.metadata?.[metadataKey];
|
|
24029
24649
|
if (typeof cmd !== "string" || !cmd.trim()) return { ok: true };
|
|
24030
|
-
return await new Promise((
|
|
24650
|
+
return await new Promise((resolve12) => {
|
|
24031
24651
|
const isWindows = process.platform === "win32";
|
|
24032
24652
|
const [shell, ...shellArgs] = isWindows ? ["cmd", "/d", "/c"] : ["sh", "-c"];
|
|
24033
24653
|
const child = spawn(shell, [...shellArgs, cmd], {
|
|
@@ -24040,24 +24660,25 @@ function makeCommandVerifier(options = {}) {
|
|
|
24040
24660
|
const timer = setTimeout(() => {
|
|
24041
24661
|
timedOut = true;
|
|
24042
24662
|
child.kill();
|
|
24043
|
-
|
|
24663
|
+
resolve12({ ok: false, reason: `verification timed out: ${cmd}` });
|
|
24044
24664
|
}, timeoutMs);
|
|
24045
24665
|
child.on("exit", (code) => {
|
|
24046
24666
|
clearTimeout(timer);
|
|
24047
24667
|
if (timedOut) return;
|
|
24048
|
-
|
|
24668
|
+
resolve12(
|
|
24049
24669
|
code === 0 ? { ok: true } : { ok: false, reason: `verification failed (exit ${code}): ${cmd}` }
|
|
24050
24670
|
);
|
|
24051
24671
|
});
|
|
24052
24672
|
child.on("error", (err) => {
|
|
24053
24673
|
clearTimeout(timer);
|
|
24054
24674
|
if (timedOut) return;
|
|
24055
|
-
|
|
24675
|
+
resolve12({ ok: false, reason: `verification spawn error: ${String(err)}` });
|
|
24056
24676
|
});
|
|
24057
24677
|
});
|
|
24058
24678
|
};
|
|
24059
24679
|
}
|
|
24060
24680
|
init_atomic_write();
|
|
24681
|
+
init_glob_match();
|
|
24061
24682
|
|
|
24062
24683
|
// src/utils/lru-cache.ts
|
|
24063
24684
|
var LruCache = class {
|
|
@@ -24093,6 +24714,10 @@ var LruCache = class {
|
|
|
24093
24714
|
return this.store.size;
|
|
24094
24715
|
}
|
|
24095
24716
|
};
|
|
24717
|
+
|
|
24718
|
+
// src/security/permission-policy.ts
|
|
24719
|
+
init_safe_json();
|
|
24720
|
+
init_tool_subject();
|
|
24096
24721
|
var DESTRUCTIVE_BASH_PATTERNS = [
|
|
24097
24722
|
/\bgit\s+(?:clean\s+-[^\s]*[xdf]|reset\s+--hard)\b/i,
|
|
24098
24723
|
/\b(?:drop|truncate)\s+(?:table|database|schema)\b/i,
|
|
@@ -24115,9 +24740,9 @@ function getInputString(input, key) {
|
|
|
24115
24740
|
function pathLooksInsideProject(rawPath, projectRoot) {
|
|
24116
24741
|
if (!projectRoot) return false;
|
|
24117
24742
|
if (rawPath === "~" || rawPath.startsWith("~/") || rawPath.startsWith("~\\")) return false;
|
|
24118
|
-
const resolved =
|
|
24119
|
-
const
|
|
24120
|
-
return !!
|
|
24743
|
+
const resolved = path4.resolve(projectRoot, rawPath);
|
|
24744
|
+
const relative4 = path4.relative(projectRoot, resolved);
|
|
24745
|
+
return !!relative4 && !relative4.startsWith("..") && !path4.isAbsolute(relative4);
|
|
24121
24746
|
}
|
|
24122
24747
|
function tokenizeShell(command) {
|
|
24123
24748
|
return command.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token) => token.replace(/^['"]|['"]$/g, "")) ?? [];
|
|
@@ -24127,7 +24752,7 @@ function pathTokenIsOutsideProject(token, projectRoot) {
|
|
|
24127
24752
|
if (token === "/" || token === "~" || token === "." || token === "..") return token !== ".";
|
|
24128
24753
|
if (token.includes("*")) return true;
|
|
24129
24754
|
if (token.startsWith("..") || token.includes("../") || token.includes("..\\")) return true;
|
|
24130
|
-
if (
|
|
24755
|
+
if (path4.isAbsolute(token) || token.startsWith("~/")) return !pathLooksInsideProject(token, projectRoot);
|
|
24131
24756
|
return false;
|
|
24132
24757
|
}
|
|
24133
24758
|
function hasDangerousDeleteTarget(tokens, start, projectRoot) {
|
|
@@ -24597,13 +25222,27 @@ var PATTERNS = [
|
|
|
24597
25222
|
// Min 12 chars: some OAuth providers issue shorter-lived tokens (< 20
|
|
24598
25223
|
// chars). A 12-char base64 string has ~71 bits of entropy — above the
|
|
24599
25224
|
// threshold where random strings are unlikely to produce false matches.
|
|
24600
|
-
|
|
25225
|
+
// The trailing boundary is a NON-consuming lookahead: two adjacent bearer
|
|
25226
|
+
// tokens sharing a single delimiter (`Bearer a… Bearer b…`) must both be
|
|
25227
|
+
// redacted. A consuming trailing delimiter would eat the separator the
|
|
25228
|
+
// next match needs for its leading anchor, leaking the second token.
|
|
25229
|
+
regex: /(?:^|[^A-Za-z0-9_.~+/-])Bearer\s+[A-Za-z0-9._~+/-]{12,512}=*(?=$|[^A-Za-z0-9_.~+/-])/g
|
|
24601
25230
|
},
|
|
24602
25231
|
{
|
|
24603
25232
|
type: "high_entropy_env",
|
|
24604
25233
|
// Anchored with alternation instead of lookbehind to avoid backtracking.
|
|
24605
25234
|
// Value bounded at 512 chars.
|
|
24606
|
-
|
|
25235
|
+
// The trailing boundary is a NON-consuming lookahead so two secrets
|
|
25236
|
+
// separated by a single delimiter (one space OR one newline, e.g.
|
|
25237
|
+
// `printenv` / `.env` dumps: `API_KEY=… \n SESSION_TOKEN=…`) are BOTH
|
|
25238
|
+
// redacted. A consuming trailing `\s` would swallow the separator the
|
|
25239
|
+
// next match needs for its leading anchor, so every other secret would
|
|
25240
|
+
// leak in plaintext.
|
|
25241
|
+
// The leading delimiter is CAPTURED (group 1) and re-emitted by the
|
|
25242
|
+
// replacement so the separator between adjacent secrets is preserved
|
|
25243
|
+
// rather than collapsed. Capture groups are therefore: 1=leading
|
|
25244
|
+
// delimiter, 2=key name, 3=value.
|
|
25245
|
+
regex: /(^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?=\s|$)/g
|
|
24607
25246
|
}
|
|
24608
25247
|
];
|
|
24609
25248
|
var SIMPLE_PATTERNS = PATTERNS.filter((p) => p.type !== "high_entropy_env");
|
|
@@ -24611,6 +25250,7 @@ var COMBINED_REGEX = new RegExp(SIMPLE_PATTERNS.map((p) => `(${p.regex.source})`
|
|
|
24611
25250
|
var HIGH_ENTROPY_REGEX = PATTERNS.find((p) => p.type === "high_entropy_env").regex;
|
|
24612
25251
|
var COMBINED_REPLACEMENTS = SIMPLE_PATTERNS.map((p) => `[REDACTED:${p.type}]`);
|
|
24613
25252
|
var SCRUB_CHUNK_BYTES = 64 * 1024;
|
|
25253
|
+
var SCRUB_OVERLAP_BYTES = 1024;
|
|
24614
25254
|
function hasCredentialAnchors(text) {
|
|
24615
25255
|
return text.includes("-----BEGIN") || // Private keys (most unique → cheap reject)
|
|
24616
25256
|
text.includes("sk-") || // Anthropic + OpenAI keys
|
|
@@ -24645,8 +25285,16 @@ var DefaultSecretScrubber = class {
|
|
|
24645
25285
|
while (i < text.length) {
|
|
24646
25286
|
let end = Math.min(i + SCRUB_CHUNK_BYTES, text.length);
|
|
24647
25287
|
if (end < text.length) {
|
|
24648
|
-
const
|
|
24649
|
-
|
|
25288
|
+
const limit = Math.min(end + SCRUB_OVERLAP_BYTES, text.length);
|
|
25289
|
+
let safe = -1;
|
|
25290
|
+
for (let j = end; j < limit; j++) {
|
|
25291
|
+
const ch = text.charCodeAt(j);
|
|
25292
|
+
if (ch === 32 || ch === 9 || ch === 10 || ch === 13) {
|
|
25293
|
+
safe = j;
|
|
25294
|
+
break;
|
|
25295
|
+
}
|
|
25296
|
+
}
|
|
25297
|
+
end = safe === -1 ? end : safe + 1;
|
|
24650
25298
|
}
|
|
24651
25299
|
out.push(this.scrubOne(text.slice(i, end)));
|
|
24652
25300
|
i = end;
|
|
@@ -24664,8 +25312,8 @@ var DefaultSecretScrubber = class {
|
|
|
24664
25312
|
return replacement !== void 0 ? replacement : match;
|
|
24665
25313
|
}
|
|
24666
25314
|
);
|
|
24667
|
-
out = out.replace(HIGH_ENTROPY_REGEX, (_match,
|
|
24668
|
-
return `${
|
|
25315
|
+
out = out.replace(HIGH_ENTROPY_REGEX, (_match, lead, key, _value) => {
|
|
25316
|
+
return `${lead}${key}=[REDACTED:high_entropy_env]`;
|
|
24669
25317
|
});
|
|
24670
25318
|
return out;
|
|
24671
25319
|
}
|
|
@@ -24694,6 +25342,9 @@ var DefaultSecretScrubber = class {
|
|
|
24694
25342
|
}
|
|
24695
25343
|
};
|
|
24696
25344
|
|
|
25345
|
+
// src/security/secret-vault.ts
|
|
25346
|
+
init_errors();
|
|
25347
|
+
|
|
24697
25348
|
// src/types/secret-vault.ts
|
|
24698
25349
|
var ENCRYPTED_PREFIX_PATTERN = /^enc:v(\d+):/;
|
|
24699
25350
|
function encryptedPrefixForVersion(version) {
|
|
@@ -24702,6 +25353,7 @@ function encryptedPrefixForVersion(version) {
|
|
|
24702
25353
|
|
|
24703
25354
|
// src/security/secret-vault.ts
|
|
24704
25355
|
init_atomic_write();
|
|
25356
|
+
init_deep_merge();
|
|
24705
25357
|
var KEY_BYTES = 32;
|
|
24706
25358
|
var IV_BYTES = 12;
|
|
24707
25359
|
var TAG_BYTES = 16;
|
|
@@ -24789,8 +25441,8 @@ function unwrapDataKey(buf, keyFile) {
|
|
|
24789
25441
|
function checkKeyFilePermissions(keyFile) {
|
|
24790
25442
|
if (process.platform === "win32") return;
|
|
24791
25443
|
try {
|
|
24792
|
-
const
|
|
24793
|
-
const actualMode =
|
|
25444
|
+
const stat10 = fs12.statSync(keyFile);
|
|
25445
|
+
const actualMode = stat10.mode & 511;
|
|
24794
25446
|
if (actualMode !== KEY_FILE_MODE) {
|
|
24795
25447
|
console.warn(JSON.stringify({
|
|
24796
25448
|
level: "warn",
|
|
@@ -24878,16 +25530,16 @@ var DefaultSecretVault = class {
|
|
|
24878
25530
|
const oldVersion = this._keyVersion;
|
|
24879
25531
|
const newKey = randomBytes(KEY_BYTES);
|
|
24880
25532
|
const newVersion = oldVersion + 1;
|
|
24881
|
-
|
|
25533
|
+
fs12.mkdirSync(path4.dirname(this.keyFile), { recursive: true });
|
|
24882
25534
|
const passphrase = getVaultPassphrase();
|
|
24883
25535
|
if (passphrase) {
|
|
24884
|
-
|
|
25536
|
+
fs12.writeFileSync(this.keyFile, wrapDataKey(newKey, newVersion, passphrase), { mode: 384 });
|
|
24885
25537
|
} else {
|
|
24886
25538
|
const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);
|
|
24887
25539
|
KEY_FILE_MAGIC.copy(keyFileBuf, 0);
|
|
24888
25540
|
keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;
|
|
24889
25541
|
newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);
|
|
24890
|
-
|
|
25542
|
+
fs12.writeFileSync(this.keyFile, keyFileBuf, { mode: 384 });
|
|
24891
25543
|
}
|
|
24892
25544
|
checkKeyFilePermissions(this.keyFile);
|
|
24893
25545
|
this.key = newKey;
|
|
@@ -24905,7 +25557,7 @@ var DefaultSecretVault = class {
|
|
|
24905
25557
|
const passphrase = getVaultPassphrase();
|
|
24906
25558
|
if (!passphrase || !this.key) return;
|
|
24907
25559
|
try {
|
|
24908
|
-
|
|
25560
|
+
fs12.writeFileSync(this.keyFile, wrapDataKey(this.key, this._keyVersion, passphrase), {
|
|
24909
25561
|
mode: 384
|
|
24910
25562
|
});
|
|
24911
25563
|
checkKeyFilePermissions(this.keyFile);
|
|
@@ -24915,7 +25567,7 @@ var DefaultSecretVault = class {
|
|
|
24915
25567
|
loadOrCreateKey() {
|
|
24916
25568
|
if (this.key) return this.key;
|
|
24917
25569
|
try {
|
|
24918
|
-
const buf =
|
|
25570
|
+
const buf = fs12.readFileSync(this.keyFile);
|
|
24919
25571
|
if (isWrappedKeyFile(buf)) {
|
|
24920
25572
|
const { key: key2, version } = unwrapDataKey(buf, this.keyFile);
|
|
24921
25573
|
this.key = key2;
|
|
@@ -24962,15 +25614,15 @@ var DefaultSecretVault = class {
|
|
|
24962
25614
|
} catch (err) {
|
|
24963
25615
|
if (err.code !== "ENOENT") throw err;
|
|
24964
25616
|
}
|
|
24965
|
-
|
|
25617
|
+
fs12.mkdirSync(path4.dirname(this.keyFile), { recursive: true });
|
|
24966
25618
|
const key = randomBytes(KEY_BYTES);
|
|
24967
25619
|
const passphrase = getVaultPassphrase();
|
|
24968
25620
|
const initialBytes = passphrase ? wrapDataKey(key, 1, passphrase) : key;
|
|
24969
25621
|
try {
|
|
24970
|
-
|
|
25622
|
+
fs12.writeFileSync(this.keyFile, initialBytes, { mode: 384, flag: "wx" });
|
|
24971
25623
|
} catch (err) {
|
|
24972
25624
|
if (err.code !== "EEXIST") throw err;
|
|
24973
|
-
const buf =
|
|
25625
|
+
const buf = fs12.readFileSync(this.keyFile);
|
|
24974
25626
|
if (isWrappedKeyFile(buf)) {
|
|
24975
25627
|
const { key: winnerKey, version } = unwrapDataKey(buf, this.keyFile);
|
|
24976
25628
|
this.key = winnerKey;
|
|
@@ -25061,7 +25713,7 @@ async function rewriteConfigEncrypted(configPath, vault, patch) {
|
|
|
25061
25713
|
}
|
|
25062
25714
|
const merged = deepMerge(current, patch ?? {});
|
|
25063
25715
|
const encrypted = encryptConfigSecrets(merged, vault);
|
|
25064
|
-
await fsp7.mkdir(
|
|
25716
|
+
await fsp7.mkdir(path4.dirname(configPath), { recursive: true });
|
|
25065
25717
|
await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
25066
25718
|
await restrictFilePermissions(configPath);
|
|
25067
25719
|
}
|
|
@@ -25164,7 +25816,7 @@ var DefaultAttachmentStore = class {
|
|
|
25164
25816
|
let data = input.data;
|
|
25165
25817
|
if (this.spoolDir && bytes >= this.spoolThreshold) {
|
|
25166
25818
|
await fsp7.mkdir(this.spoolDir, { recursive: true });
|
|
25167
|
-
spooledPath =
|
|
25819
|
+
spooledPath = path4.join(this.spoolDir, `${id}.bin`);
|
|
25168
25820
|
await atomicWrite(spooledPath, input.data, {
|
|
25169
25821
|
encoding: input.kind === "image" ? "base64" : "utf8"
|
|
25170
25822
|
});
|
|
@@ -25282,6 +25934,7 @@ function mergeAdjacentText(blocks) {
|
|
|
25282
25934
|
return out;
|
|
25283
25935
|
}
|
|
25284
25936
|
init_atomic_write();
|
|
25937
|
+
init_error();
|
|
25285
25938
|
|
|
25286
25939
|
// src/types/context-window.ts
|
|
25287
25940
|
var DEFAULT_CONTEXT_WINDOW_MODE_ID = "balanced";
|
|
@@ -25338,6 +25991,9 @@ function isContextWindowModeId(id) {
|
|
|
25338
25991
|
var DEFAULT_TUI_THINKING_WORD = "thinking";
|
|
25339
25992
|
|
|
25340
25993
|
// src/storage/config-loader.ts
|
|
25994
|
+
init_errors();
|
|
25995
|
+
init_safe_json();
|
|
25996
|
+
init_deep_merge();
|
|
25341
25997
|
function storageErrorString(err) {
|
|
25342
25998
|
if (err instanceof Error) {
|
|
25343
25999
|
const code = err.code;
|
|
@@ -25656,8 +26312,8 @@ function stripUnsafeInProjectFields(inProject, sourcePath, warn = (msg) => conso
|
|
|
25656
26312
|
return out;
|
|
25657
26313
|
}
|
|
25658
26314
|
function samePath(a, b) {
|
|
25659
|
-
let ra =
|
|
25660
|
-
let rb =
|
|
26315
|
+
let ra = path4.resolve(a);
|
|
26316
|
+
let rb = path4.resolve(b);
|
|
25661
26317
|
if (process.platform === "win32" || process.platform === "darwin") {
|
|
25662
26318
|
ra = ra.toLowerCase();
|
|
25663
26319
|
rb = rb.toLowerCase();
|
|
@@ -25944,8 +26600,8 @@ var DefaultConfigLoader = class {
|
|
|
25944
26600
|
const t0 = Date.now();
|
|
25945
26601
|
let mtimeMs = null;
|
|
25946
26602
|
try {
|
|
25947
|
-
const
|
|
25948
|
-
mtimeMs =
|
|
26603
|
+
const stat10 = await fsp7.stat(file);
|
|
26604
|
+
mtimeMs = stat10.mtimeMs;
|
|
25949
26605
|
const cached = this.jsonCache.get(file);
|
|
25950
26606
|
if (cached && cached.mtimeMs === mtimeMs) {
|
|
25951
26607
|
return structuredClone(cached.value);
|
|
@@ -26138,6 +26794,8 @@ function runConfigMigrations(input, targetVersion, migrations) {
|
|
|
26138
26794
|
var DEFAULT_CONFIG_MIGRATIONS = [];
|
|
26139
26795
|
|
|
26140
26796
|
// src/storage/config-store.ts
|
|
26797
|
+
init_errors();
|
|
26798
|
+
init_error();
|
|
26141
26799
|
function stripEphemeralFields(cfg) {
|
|
26142
26800
|
const env = cfg._envSource;
|
|
26143
26801
|
if (!env?.size) return cfg;
|
|
@@ -26208,6 +26866,9 @@ function deepFreeze(obj) {
|
|
|
26208
26866
|
return Object.freeze(obj);
|
|
26209
26867
|
}
|
|
26210
26868
|
|
|
26869
|
+
// src/storage/memory-store.ts
|
|
26870
|
+
init_error();
|
|
26871
|
+
|
|
26211
26872
|
// src/types/memory.ts
|
|
26212
26873
|
var MEMORY_TYPE_LABELS = {
|
|
26213
26874
|
fact: "Fact",
|
|
@@ -26288,9 +26949,80 @@ function isMemoryType(s) {
|
|
|
26288
26949
|
function isPriority(s) {
|
|
26289
26950
|
return s === "critical" || s === "high" || s === "medium" || s === "low";
|
|
26290
26951
|
}
|
|
26952
|
+
function buildInvertedIndex(entries) {
|
|
26953
|
+
const wordMap = /* @__PURE__ */ new Map();
|
|
26954
|
+
const tagMap = /* @__PURE__ */ new Map();
|
|
26955
|
+
const indexed = new Array(entries.length);
|
|
26956
|
+
for (let i = 0; i < entries.length; i++) {
|
|
26957
|
+
const e = entries[i];
|
|
26958
|
+
const words = e.text.toLowerCase().split(/\s+/).filter((w) => w.length > 0);
|
|
26959
|
+
const tags = (e.tags ?? []).map((t) => t.toLowerCase());
|
|
26960
|
+
indexed[i] = { entry: e, words, tags };
|
|
26961
|
+
for (const w of words) {
|
|
26962
|
+
const arr = wordMap.get(w);
|
|
26963
|
+
if (arr) arr.push(i);
|
|
26964
|
+
else wordMap.set(w, [i]);
|
|
26965
|
+
}
|
|
26966
|
+
for (const t of tags) {
|
|
26967
|
+
const arr = tagMap.get(t);
|
|
26968
|
+
if (arr) arr.push(i);
|
|
26969
|
+
else tagMap.set(t, [i]);
|
|
26970
|
+
}
|
|
26971
|
+
}
|
|
26972
|
+
return { wordMap, tagMap, entries: indexed, mtimeMs: 0 };
|
|
26973
|
+
}
|
|
26974
|
+
var MIN_SUBSTRING_NEEDLE_LEN = 3;
|
|
26975
|
+
function searchIndex(index, query, limit) {
|
|
26976
|
+
const needles = query.toLowerCase().split(/\s+/).filter((n) => n.length > 0);
|
|
26977
|
+
if (needles.length === 0) return [];
|
|
26978
|
+
const scores = /* @__PURE__ */ new Map();
|
|
26979
|
+
for (const n of needles) {
|
|
26980
|
+
let matched = false;
|
|
26981
|
+
const wordExact = index.wordMap.get(n);
|
|
26982
|
+
if (wordExact) {
|
|
26983
|
+
for (const idx of wordExact) scores.set(idx, (scores.get(idx) ?? 0) + 1);
|
|
26984
|
+
matched = true;
|
|
26985
|
+
}
|
|
26986
|
+
const tagExact = index.tagMap.get(n);
|
|
26987
|
+
if (tagExact) {
|
|
26988
|
+
for (const idx of tagExact) scores.set(idx, (scores.get(idx) ?? 0) + 2);
|
|
26989
|
+
matched = true;
|
|
26990
|
+
}
|
|
26991
|
+
if (matched || n.length < MIN_SUBSTRING_NEEDLE_LEN) continue;
|
|
26992
|
+
for (const [word, indices] of index.wordMap) {
|
|
26993
|
+
if (word.includes(n) || n.includes(word)) {
|
|
26994
|
+
for (const idx of indices) {
|
|
26995
|
+
scores.set(idx, (scores.get(idx) ?? 0) + 1);
|
|
26996
|
+
}
|
|
26997
|
+
}
|
|
26998
|
+
}
|
|
26999
|
+
for (const [tag, indices] of index.tagMap) {
|
|
27000
|
+
if (tag.includes(n) || n.includes(tag)) {
|
|
27001
|
+
for (const idx of indices) {
|
|
27002
|
+
scores.set(idx, (scores.get(idx) ?? 0) + 2);
|
|
27003
|
+
}
|
|
27004
|
+
}
|
|
27005
|
+
}
|
|
27006
|
+
}
|
|
27007
|
+
if (scores.size === 0) return [];
|
|
27008
|
+
const scored = Array.from(scores.entries());
|
|
27009
|
+
scored.sort((a, b) => b[1] - a[1]);
|
|
27010
|
+
const result = [];
|
|
27011
|
+
const max = limit ? Math.min(limit, scored.length) : scored.length;
|
|
27012
|
+
for (let i = 0; i < max; i++) {
|
|
27013
|
+
result.push(index.entries[scored[i][0]].entry);
|
|
27014
|
+
}
|
|
27015
|
+
return result;
|
|
27016
|
+
}
|
|
26291
27017
|
var FileMemoryBackend = class {
|
|
26292
27018
|
kind = "file";
|
|
26293
27019
|
files;
|
|
27020
|
+
/** Cache of parsed entries per file path. */
|
|
27021
|
+
entryCache = /* @__PURE__ */ new Map();
|
|
27022
|
+
/** Inverted index per file path. */
|
|
27023
|
+
indexCache = /* @__PURE__ */ new Map();
|
|
27024
|
+
/** File mtime cache for invalidation. */
|
|
27025
|
+
mtimeCache = /* @__PURE__ */ new Map();
|
|
26294
27026
|
constructor(opts) {
|
|
26295
27027
|
this.files = {
|
|
26296
27028
|
"project-agents": opts.paths.inProjectAgentsFile,
|
|
@@ -26301,9 +27033,56 @@ var FileMemoryBackend = class {
|
|
|
26301
27033
|
resolveFile(filePath, scope) {
|
|
26302
27034
|
return filePath || this.files[scope];
|
|
26303
27035
|
}
|
|
27036
|
+
async getMtime(file) {
|
|
27037
|
+
try {
|
|
27038
|
+
const stat10 = await fsp7.stat(file);
|
|
27039
|
+
return stat10.mtimeMs;
|
|
27040
|
+
} catch {
|
|
27041
|
+
return 0;
|
|
27042
|
+
}
|
|
27043
|
+
}
|
|
27044
|
+
invalidateCache(file) {
|
|
27045
|
+
this.entryCache.delete(file);
|
|
27046
|
+
this.indexCache.delete(file);
|
|
27047
|
+
this.mtimeCache.delete(file);
|
|
27048
|
+
}
|
|
27049
|
+
/**
|
|
27050
|
+
* Load (and cache) the parsed entries for a file. Callers that have already
|
|
27051
|
+
* stat'd the file this tick (e.g. `getIndex`) can pass the known `mtime` to
|
|
27052
|
+
* avoid a redundant `fs.stat` — otherwise it's fetched here.
|
|
27053
|
+
*/
|
|
27054
|
+
async loadEntries(file, scope, mtime) {
|
|
27055
|
+
const resolvedMtime = mtime ?? await this.getMtime(file);
|
|
27056
|
+
const cachedMtime = this.mtimeCache.get(file);
|
|
27057
|
+
if (cachedMtime === resolvedMtime && this.entryCache.has(file)) {
|
|
27058
|
+
return this.entryCache.get(file);
|
|
27059
|
+
}
|
|
27060
|
+
const raw = await this.readAll(scope, file);
|
|
27061
|
+
if (!raw.trim()) {
|
|
27062
|
+
this.entryCache.set(file, []);
|
|
27063
|
+
this.mtimeCache.set(file, resolvedMtime);
|
|
27064
|
+
return [];
|
|
27065
|
+
}
|
|
27066
|
+
const entries = parseEntries(raw, scope);
|
|
27067
|
+
this.entryCache.set(file, entries);
|
|
27068
|
+
this.mtimeCache.set(file, resolvedMtime);
|
|
27069
|
+
return entries;
|
|
27070
|
+
}
|
|
27071
|
+
async getIndex(file, scope) {
|
|
27072
|
+
const mtime = await this.getMtime(file);
|
|
27073
|
+
const cached = this.indexCache.get(file);
|
|
27074
|
+
if (cached && cached.mtimeMs === mtime) {
|
|
27075
|
+
return cached;
|
|
27076
|
+
}
|
|
27077
|
+
const entries = await this.loadEntries(file, scope, mtime);
|
|
27078
|
+
const index = buildInvertedIndex(entries);
|
|
27079
|
+
index.mtimeMs = mtime;
|
|
27080
|
+
this.indexCache.set(file, index);
|
|
27081
|
+
return index;
|
|
27082
|
+
}
|
|
26304
27083
|
async remember(scope, entry, filePath) {
|
|
26305
27084
|
const file = this.resolveFile(filePath, scope);
|
|
26306
|
-
await ensureDir(
|
|
27085
|
+
await ensureDir(path4.dirname(file));
|
|
26307
27086
|
let existing = "";
|
|
26308
27087
|
try {
|
|
26309
27088
|
existing = await fsp7.readFile(file, "utf8");
|
|
@@ -26317,6 +27096,7 @@ var FileMemoryBackend = class {
|
|
|
26317
27096
|
const next = existing.trim() ? existing.replace(/\n+$/, "") + line : `# Agent Memory
|
|
26318
27097
|
${line}`;
|
|
26319
27098
|
await atomicWrite(file, next);
|
|
27099
|
+
this.invalidateCache(file);
|
|
26320
27100
|
}
|
|
26321
27101
|
async forget(scope, query, filePath) {
|
|
26322
27102
|
const file = this.resolveFile(filePath, scope);
|
|
@@ -26353,6 +27133,7 @@ ${line}`;
|
|
|
26353
27133
|
await atomicWrite(file, lines.join("\n"));
|
|
26354
27134
|
}
|
|
26355
27135
|
}
|
|
27136
|
+
this.invalidateCache(file);
|
|
26356
27137
|
return removed;
|
|
26357
27138
|
});
|
|
26358
27139
|
}
|
|
@@ -26365,30 +27146,19 @@ ${line}`;
|
|
|
26365
27146
|
}
|
|
26366
27147
|
}
|
|
26367
27148
|
async list(scope, filePath, limit) {
|
|
26368
|
-
const
|
|
26369
|
-
|
|
26370
|
-
const entries = parseEntries(raw, scope);
|
|
27149
|
+
const file = this.resolveFile(filePath, scope);
|
|
27150
|
+
const entries = await this.loadEntries(file, scope);
|
|
26371
27151
|
return limit ? entries.slice(0, limit) : entries;
|
|
26372
27152
|
}
|
|
26373
27153
|
async search(scope, query, filePath, limit) {
|
|
26374
|
-
const
|
|
26375
|
-
const
|
|
26376
|
-
|
|
26377
|
-
const words = e.text.toLowerCase().split(/\s+/);
|
|
26378
|
-
let score = 0;
|
|
26379
|
-
for (const n of needle) {
|
|
26380
|
-
if (words.some((w) => w.includes(n))) score += 1;
|
|
26381
|
-
if (e.tags?.some((t) => t.toLowerCase().includes(n))) score += 2;
|
|
26382
|
-
}
|
|
26383
|
-
return { entry: e, score };
|
|
26384
|
-
});
|
|
26385
|
-
scored.sort((a, b) => b.score - a.score);
|
|
26386
|
-
const matched = scored.filter((s) => s.score > 0).map((s) => s.entry);
|
|
26387
|
-
return limit ? matched.slice(0, limit) : matched;
|
|
27154
|
+
const file = this.resolveFile(filePath, scope);
|
|
27155
|
+
const index = await this.getIndex(file, scope);
|
|
27156
|
+
return searchIndex(index, query, limit);
|
|
26388
27157
|
}
|
|
26389
27158
|
async clear(scope, filePath) {
|
|
26390
27159
|
const file = this.resolveFile(filePath, scope);
|
|
26391
27160
|
await atomicWrite(file, "");
|
|
27161
|
+
this.invalidateCache(file);
|
|
26392
27162
|
}
|
|
26393
27163
|
async consolidate(scope, filePath) {
|
|
26394
27164
|
const file = this.resolveFile(filePath, scope);
|
|
@@ -26423,18 +27193,19 @@ ${line}`;
|
|
|
26423
27193
|
} catch {
|
|
26424
27194
|
return 0;
|
|
26425
27195
|
}
|
|
27196
|
+
this.invalidateCache(file);
|
|
26426
27197
|
return removed;
|
|
26427
27198
|
}
|
|
26428
27199
|
};
|
|
26429
27200
|
async function pruneConsolidateBackups(file) {
|
|
26430
|
-
const dir =
|
|
26431
|
-
const base =
|
|
27201
|
+
const dir = path4.dirname(file);
|
|
27202
|
+
const base = path4.basename(file);
|
|
26432
27203
|
const prefix = `${base}.bak.`;
|
|
26433
27204
|
const backups = (await fsp7.readdir(dir)).filter((name) => name.startsWith(prefix)).sort().reverse();
|
|
26434
27205
|
await Promise.all(
|
|
26435
27206
|
backups.slice(MAX_MEMORY_CONSOLIDATE_BACKUPS).map(async (name) => {
|
|
26436
27207
|
try {
|
|
26437
|
-
await fsp7.unlink(
|
|
27208
|
+
await fsp7.unlink(path4.join(dir, name));
|
|
26438
27209
|
} catch {
|
|
26439
27210
|
}
|
|
26440
27211
|
})
|
|
@@ -26489,9 +27260,10 @@ var DefaultMemoryStore = class {
|
|
|
26489
27260
|
/** Result cache for scoreRelevant() — keyed by scope + context hash, TTL 30s. */
|
|
26490
27261
|
_scoreCache = /* @__PURE__ */ new Map();
|
|
26491
27262
|
/**
|
|
26492
|
-
* Per-entry cached lowercase strings —
|
|
26493
|
-
*
|
|
26494
|
-
*
|
|
27263
|
+
* Per-entry cached lowercase strings — lazily allocated once and reused
|
|
27264
|
+
* across scoreRelevant() calls so repeated scoring of the same entries skips
|
|
27265
|
+
* re-lowercasing. Keyed by entry object identity; cleared (set to null) on
|
|
27266
|
+
* every mutation (remember/forget/consolidate/clear) via invalidateScoreCaches().
|
|
26495
27267
|
*/
|
|
26496
27268
|
_cachedLower = null;
|
|
26497
27269
|
constructor(opts) {
|
|
@@ -26641,7 +27413,7 @@ ${body.trim()}`);
|
|
|
26641
27413
|
const t0 = Date.now();
|
|
26642
27414
|
try {
|
|
26643
27415
|
await this.backend.remember(scope, entry, filePath);
|
|
26644
|
-
this.
|
|
27416
|
+
this.invalidateScoreCaches();
|
|
26645
27417
|
const dur = Date.now() - t0;
|
|
26646
27418
|
this.events?.emit("storage.write", {
|
|
26647
27419
|
sessionId: "~memory~",
|
|
@@ -26692,6 +27464,15 @@ ${body.trim()}`);
|
|
|
26692
27464
|
});
|
|
26693
27465
|
});
|
|
26694
27466
|
}
|
|
27467
|
+
/**
|
|
27468
|
+
* Drop the relevance caches after a mutation. Both the per-context score
|
|
27469
|
+
* cache and the per-entry lowercase cache are keyed on entry objects that a
|
|
27470
|
+
* mutation invalidates, so they must be cleared together when entries change.
|
|
27471
|
+
*/
|
|
27472
|
+
invalidateScoreCaches() {
|
|
27473
|
+
this._scoreCache.clear();
|
|
27474
|
+
this._cachedLower = null;
|
|
27475
|
+
}
|
|
26695
27476
|
/**
|
|
26696
27477
|
* Score and rank memories by relevance to the current context.
|
|
26697
27478
|
* Returns entries with score >= MIN_RELEVANCE_SCORE, sorted highest first.
|
|
@@ -26709,18 +27490,19 @@ ${body.trim()}`);
|
|
|
26709
27490
|
const taskWords = ctx.currentTask.toLowerCase().split(/\s+/).filter((w) => w.length > 2);
|
|
26710
27491
|
const skillWords = (ctx.activeSkills ?? []).flatMap((s) => s.split("-"));
|
|
26711
27492
|
const toolWords = (ctx.toolNames ?? []).flatMap((t) => t.toLowerCase().split("_"));
|
|
26712
|
-
this._cachedLower
|
|
27493
|
+
this._cachedLower ??= /* @__PURE__ */ new WeakMap();
|
|
27494
|
+
const lowerCache = this._cachedLower;
|
|
26713
27495
|
const scored = [];
|
|
26714
27496
|
for (const entry of all) {
|
|
26715
27497
|
let score = 0;
|
|
26716
27498
|
const reasons = [];
|
|
26717
|
-
let cachedLower =
|
|
27499
|
+
let cachedLower = lowerCache.get(entry);
|
|
26718
27500
|
if (!cachedLower) {
|
|
26719
27501
|
cachedLower = {
|
|
26720
27502
|
textLower: entry.text.toLowerCase(),
|
|
26721
27503
|
tagsLower: (entry.tags ?? []).map((t) => t.toLowerCase())
|
|
26722
27504
|
};
|
|
26723
|
-
|
|
27505
|
+
lowerCache.set(entry, cachedLower);
|
|
26724
27506
|
}
|
|
26725
27507
|
const { textLower, tagsLower } = cachedLower;
|
|
26726
27508
|
let taskHits = 0;
|
|
@@ -26818,7 +27600,7 @@ ${body.trim()}`);
|
|
|
26818
27600
|
let removed = 0;
|
|
26819
27601
|
try {
|
|
26820
27602
|
removed = await this.backend.forget(scope, query, filePath);
|
|
26821
|
-
this.
|
|
27603
|
+
this.invalidateScoreCaches();
|
|
26822
27604
|
const dur = Date.now() - t0;
|
|
26823
27605
|
this.events?.emit("storage.write", {
|
|
26824
27606
|
sessionId: "~memory~",
|
|
@@ -26862,7 +27644,7 @@ ${body.trim()}`);
|
|
|
26862
27644
|
let removed = 0;
|
|
26863
27645
|
try {
|
|
26864
27646
|
removed = await this.backend.consolidate(scope, filePath);
|
|
26865
|
-
this.
|
|
27647
|
+
this.invalidateScoreCaches();
|
|
26866
27648
|
const dur = Date.now() - t0;
|
|
26867
27649
|
this.events?.emit("storage.write", {
|
|
26868
27650
|
sessionId: "~memory~",
|
|
@@ -26904,7 +27686,7 @@ ${body.trim()}`);
|
|
|
26904
27686
|
const t0 = Date.now();
|
|
26905
27687
|
try {
|
|
26906
27688
|
await this.backend.clear(scope, filePath);
|
|
26907
|
-
this.
|
|
27689
|
+
this.invalidateScoreCaches();
|
|
26908
27690
|
const dur = Date.now() - t0;
|
|
26909
27691
|
this.events?.emit("storage.write", {
|
|
26910
27692
|
sessionId: "~memory~",
|
|
@@ -26971,6 +27753,7 @@ ${body.trim()}`);
|
|
|
26971
27753
|
})
|
|
26972
27754
|
)
|
|
26973
27755
|
);
|
|
27756
|
+
this.invalidateScoreCaches();
|
|
26974
27757
|
}
|
|
26975
27758
|
/**
|
|
26976
27759
|
* Return a new MemoryStore proxy that carries `traceId` on every storage
|
|
@@ -27009,6 +27792,7 @@ function labelOf(scope) {
|
|
|
27009
27792
|
|
|
27010
27793
|
// src/storage/plan-store.ts
|
|
27011
27794
|
init_atomic_write();
|
|
27795
|
+
init_error();
|
|
27012
27796
|
async function loadPlan(filePath, events) {
|
|
27013
27797
|
const t0 = Date.now();
|
|
27014
27798
|
let raw;
|
|
@@ -27304,6 +28088,7 @@ ${cat}:`);
|
|
|
27304
28088
|
|
|
27305
28089
|
// src/storage/queue-store.ts
|
|
27306
28090
|
init_atomic_write();
|
|
28091
|
+
init_error();
|
|
27307
28092
|
var QueueStore = class {
|
|
27308
28093
|
file;
|
|
27309
28094
|
// Use `| undefined` (not `?`) so exactOptionalPropertyTypes doesn't
|
|
@@ -27311,7 +28096,7 @@ var QueueStore = class {
|
|
|
27311
28096
|
events;
|
|
27312
28097
|
traceId;
|
|
27313
28098
|
constructor(opts) {
|
|
27314
|
-
this.file =
|
|
28099
|
+
this.file = path4.join(opts.dir, "queue.json");
|
|
27315
28100
|
this.events = opts.events;
|
|
27316
28101
|
this.traceId = opts.traceId;
|
|
27317
28102
|
}
|
|
@@ -27488,7 +28273,7 @@ var RecoveryLock = class {
|
|
|
27488
28273
|
sessionStore;
|
|
27489
28274
|
probe;
|
|
27490
28275
|
constructor(opts) {
|
|
27491
|
-
this.file =
|
|
28276
|
+
this.file = path4.join(opts.dir, LOCK_FILE);
|
|
27492
28277
|
this.pid = opts.pid ?? process.pid;
|
|
27493
28278
|
this.hostname = opts.hostname ?? os.hostname();
|
|
27494
28279
|
this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
@@ -27549,7 +28334,7 @@ var RecoveryLock = class {
|
|
|
27549
28334
|
* null return before calling this.
|
|
27550
28335
|
*/
|
|
27551
28336
|
async write(sessionId) {
|
|
27552
|
-
await ensureDir(
|
|
28337
|
+
await ensureDir(path4.dirname(this.file));
|
|
27553
28338
|
const lock = {
|
|
27554
28339
|
v: 1,
|
|
27555
28340
|
sessionId,
|
|
@@ -27829,6 +28614,11 @@ function resolveSessionLoggingConfig(cfg) {
|
|
|
27829
28614
|
}
|
|
27830
28615
|
};
|
|
27831
28616
|
}
|
|
28617
|
+
|
|
28618
|
+
// src/storage/session-reader.ts
|
|
28619
|
+
init_expect_defined();
|
|
28620
|
+
init_regex_guard();
|
|
28621
|
+
init_session_scoped_path();
|
|
27832
28622
|
var DefaultSessionReader = class _DefaultSessionReader {
|
|
27833
28623
|
store;
|
|
27834
28624
|
eventCache = /* @__PURE__ */ new Map();
|
|
@@ -27843,11 +28633,11 @@ var DefaultSessionReader = class _DefaultSessionReader {
|
|
|
27843
28633
|
if (!rootDir) {
|
|
27844
28634
|
return await this.store.load(sessionId);
|
|
27845
28635
|
}
|
|
27846
|
-
const sessionPath =
|
|
28636
|
+
const sessionPath = sessionScopedPath(rootDir, sessionId, ".jsonl");
|
|
27847
28637
|
let mtimeMs = null;
|
|
27848
28638
|
try {
|
|
27849
|
-
const
|
|
27850
|
-
mtimeMs =
|
|
28639
|
+
const stat10 = await fsp7.stat(sessionPath);
|
|
28640
|
+
mtimeMs = stat10.mtimeMs;
|
|
27851
28641
|
} catch {
|
|
27852
28642
|
this.eventCache.delete(sessionId);
|
|
27853
28643
|
this.eventCacheMtimes.delete(sessionId);
|
|
@@ -28206,6 +28996,7 @@ function renderPlainText(meta, events) {
|
|
|
28206
28996
|
|
|
28207
28997
|
// src/storage/todos-checkpoint.ts
|
|
28208
28998
|
init_atomic_write();
|
|
28999
|
+
init_error();
|
|
28209
29000
|
async function loadTodosCheckpoint(filePath, events, traceId) {
|
|
28210
29001
|
const t0 = Date.now();
|
|
28211
29002
|
let raw;
|
|
@@ -28346,6 +29137,6 @@ function attachTodosCheckpoint(state, filePath, sessionId, events, traceId) {
|
|
|
28346
29137
|
};
|
|
28347
29138
|
}
|
|
28348
29139
|
|
|
28349
|
-
export { AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutonomousRunner, BUG_HUNTER_AGENT, BudgetExceededError, CODEX_MODELS, ConfigMigrationError, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultDesignKitLoader, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPermissionPolicy, DefaultPromptLoader, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultTaskStore, Director, DirectorStateCheckpoint, DoneConditionChecker, EternalAutonomyEngine, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FleetBus, FleetSpawnBudgetError, FleetUsageAggregator, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, IntelligentCompactor, LLMSelector, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, SddBoardProjector, SddBoardStore, SddInterviewDriver, SddParallelRun, SddRunRegistry, SddSupervisor, SddTaskDecomposer, SelectiveCompactor, SessionAnalyzer, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, SubagentBudget, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, ToolExecutor, _resetDesignKitLoaderMemo, _resetDesignRulesCache, activateDesign, addPlanItem, allServers, analyzeCriticalPath, applyRosterBudget, applySddLifecycle, applyTokenOverrides, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, braveSearchServer, buildBoardSnapshot, buildBoardTasks, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, classifyFamily, cleanupSddWorktrees, cleanupStaleSddWorktrees, clearActiveKit, clearPersistedActiveKit, clearPlan, codexModelMeta, colorToHex, composeDirectorPrompt, composeSubagentPrompt, context7Server, contextManagerTool, createAutoExecutor, createContextManagerTool, createDelegateTool, createMessage, createSessionEventBridge, createStrategyCompactor, decryptConfigSecrets, deriveTodosFromPlanItem, describeCatalogModel, designProjectDir, destroySddProject, detectFrontendFile, detectFrontendIntent, dispatchAgent, emptyPlan, encryptConfigSecrets, everArtServer, extractVerificationCommand, filesystemServer, formatPlan, formatPlanTemplates, getAgentDefinition, getDesignKitLoader, getDesignState, getPlanTemplate, getTemplate, githubServer, googleMapsServer, hasConflictMarkers, installDesignStudioMiddleware, isColorToken, isExplanatoryText, listPlanTemplates, listTemplates, loadActiveKit, loadDirectorState, loadPlan, loadProjectDesignRules, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeCommandVerifier, makeDesignDetectToolCallMiddleware, makeDesignDetectUserInputMiddleware, makeDesignStudioRequestMiddleware, makeDesignVerifyToolCallMiddleware, makeDirectorSessionFactory, makeFleetEmitTool,
|
|
29140
|
+
export { AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutonomousRunner, BUG_HUNTER_AGENT, BudgetExceededError, CODEX_MODELS, ConfigMigrationError, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultDesignKitLoader, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPermissionPolicy, DefaultPromptLoader, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultTaskStore, Director, DirectorStateCheckpoint, DoneConditionChecker, EternalAutonomyEngine, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FleetBus, FleetSpawnBudgetError, FleetUsageAggregator, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, IntelligentCompactor, LLMSelector, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, SddBoardProjector, SddBoardStore, SddInterviewDriver, SddParallelRun, SddRunRegistry, SddSupervisor, SddTaskDecomposer, SelectiveCompactor, SessionAnalyzer, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, SubagentBudget, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, ToolExecutor, _resetDesignKitLoaderMemo, _resetDesignRulesCache, activateDesign, addPlanItem, allServers, analyzeCriticalPath, applyRosterBudget, applySddLifecycle, applyTokenOverrides, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, braveSearchServer, buildBoardSnapshot, buildBoardTasks, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, classifyFamily, cleanupSddWorktrees, cleanupStaleSddWorktrees, clearActiveKit, clearPersistedActiveKit, clearPlan, codexModelMeta, colorToHex, composeDirectorPrompt, composeSubagentPrompt, context7Server, contextManagerTool, createAutoExecutor, createContextManagerTool, createDelegateTool, createMessage, createSessionEventBridge, createStrategyCompactor, decryptConfigSecrets, deriveTodosFromPlanItem, describeCatalogModel, designProjectDir, destroySddProject, detectFrontendFile, detectFrontendIntent, dispatchAgent, emptyPlan, encryptConfigSecrets, everArtServer, extractVerificationCommand, filesystemServer, formatPlan, formatPlanTemplates, getAgentDefinition, getDesignKitLoader, getDesignState, getPlanTemplate, getTemplate, githubServer, googleMapsServer, hasConflictMarkers, installDesignStudioMiddleware, isColorToken, isExplanatoryText, listPlanTemplates, listTemplates, loadActiveKit, loadDirectorState, loadPlan, loadProjectDesignRules, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeCommandVerifier, makeDesignDetectToolCallMiddleware, makeDesignDetectUserInputMiddleware, makeDesignStudioRequestMiddleware, makeDesignVerifyToolCallMiddleware, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetTool, makeLLMClassifier, makeLlmConflictResolver, makeLlmSubtaskGenerator, makePreferSideConflictResolver, makeRollUpTool, makeSpawnTool, makeTerminateTool, materializeTokens, migratePlaintextSecrets, miniMaxVisionServer, oklchToHex, parseOklch, playwrightServer, recordKitChoice, recordOverrides, removePlanItem, renderProgress, renderPrometheus, renderPrompt, renderSpecAnalysis, renderTaskGraph, renderTaskList, resolveAuditLevel, resolveBundledDesignKitsDir, resolveConflictText, resolveProviderModelList, resolveSessionLoggingConfig, rewriteConfigEncrypted, rollbackSddRunFromDisk, rosterSummaryFromConfigs, runConfigMigrations, runDesignVerify, savePlan, saveTodosCheckpoint, scoreAgents, sentinelServer, setActiveKit, setDesignOverrides, setPlanItemStatus, shortIdMap, slackServer, sshManagerServer, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, startSddRun, templateToMarkdown, verifyFiles, wireMetricsToEvents, zaiVisionServer };
|
|
28350
29141
|
//# sourceMappingURL=index.js.map
|
|
28351
29142
|
//# sourceMappingURL=index.js.map
|