@wrongstack/core 0.54.1 → 0.63.4
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-Dnhw4tnM.d.ts → agent-bridge-B5rxWrg3.d.ts} +1 -1
- package/dist/{agent-subagent-runner-By7jruZ_.d.ts → agent-subagent-runner-Zc3f37Sg.d.ts} +3 -3
- package/dist/{compactor-Duhsf0ge.d.ts → compactor-0vjZ8KTk.d.ts} +1 -1
- package/dist/{config-bht0txXS.d.ts → config-BdDuaZmB.d.ts} +112 -2
- package/dist/{context-DtPKqKYV.d.ts → context-iFMEO2rN.d.ts} +8 -8
- package/dist/coordination/index.d.ts +12 -12
- package/dist/defaults/index.d.ts +21 -21
- package/dist/defaults/index.js +254 -92
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-CbHTS4ZZ.d.ts → events-k8CHjcrN.d.ts} +20 -1
- package/dist/execution/index.d.ts +14 -14
- package/dist/execution/index.js +70 -10
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +7 -7
- package/dist/{goal-store-DwcTDDiX.d.ts → goal-store-iHltMi5n.d.ts} +1 -1
- package/dist/{index-CI271MjL.d.ts → index-Bc6BiP5q.d.ts} +77 -6
- package/dist/{index-ge5F2dnc.d.ts → index-CWdW_CJt.d.ts} +10 -8
- package/dist/index.d.ts +56 -32
- package/dist/index.js +520 -85
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/infrastructure/index.js +1 -1
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +9 -9
- package/dist/kernel/index.js +3 -1
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-DE6gzBry.d.ts → mcp-servers-CwqQDMYy.d.ts} +3 -3
- package/dist/models/index.d.ts +2 -2
- package/dist/{multi-agent-BmC_xiog.d.ts → multi-agent-SASYOrWA.d.ts} +2 -2
- package/dist/{multi-agent-coordinator-CjNX4uBD.d.ts → multi-agent-coordinator-CNUJYq7U.d.ts} +2 -2
- package/dist/{null-fleet-bus-BNiSlTna.d.ts → null-fleet-bus-DRoJ0uOY.d.ts} +7 -7
- package/dist/observability/index.d.ts +2 -2
- package/dist/{path-resolver-Bax85amb.d.ts → path-resolver-C5sPVne8.d.ts} +2 -2
- package/dist/{permission-Drm7LpPo.d.ts → permission-Ld-i5ugf.d.ts} +13 -1
- package/dist/{permission-policy-CU6sqWxF.d.ts → permission-policy-CL-mPufp.d.ts} +14 -7
- package/dist/{plan-templates-CLRcurWN.d.ts → plan-templates-ThBHOjaM.d.ts} +4 -4
- package/dist/{provider-runner-BikCxGCx.d.ts → provider-runner-DJQa211J.d.ts} +3 -3
- package/dist/{retry-policy-Chtlvr5b.d.ts → retry-policy-BfBScewS.d.ts} +1 -1
- package/dist/sdd/index.d.ts +9 -9
- package/dist/sdd/index.js +1 -1
- package/dist/sdd/index.js.map +1 -1
- package/dist/security/index.d.ts +3 -3
- package/dist/security/index.js +115 -13
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-BvSPdJj6.d.ts → selector-DxhW7ML3.d.ts} +1 -1
- package/dist/{session-reader-BGhzMir4.d.ts → session-reader-q2ThszgG.d.ts} +1 -1
- package/dist/storage/index.d.ts +6 -6
- package/dist/{system-prompt-dtzV_mLm.d.ts → system-prompt-7LHyBbIf.d.ts} +32 -2
- package/dist/{tool-executor-CgU0yWpB.d.ts → tool-executor-CIjpGaRA.d.ts} +5 -4
- package/dist/types/index.d.ts +14 -14
- package/dist/types/index.js +62 -6
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/package.json +1 -1
package/dist/defaults/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as crypto2 from 'crypto';
|
|
2
2
|
import { randomBytes, randomUUID, createCipheriv, createDecipheriv, createHash } from 'crypto';
|
|
3
3
|
import * as fsp from 'fs/promises';
|
|
4
|
-
import * as
|
|
4
|
+
import * as path16 from 'path';
|
|
5
5
|
import { isAbsolute, resolve } from 'path';
|
|
6
6
|
import * as fs5 from 'fs';
|
|
7
7
|
import * as os from 'os';
|
|
@@ -32,9 +32,9 @@ __export(atomic_write_exports, {
|
|
|
32
32
|
ensureDir: () => ensureDir
|
|
33
33
|
});
|
|
34
34
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
35
|
-
const dir =
|
|
35
|
+
const dir = path16.dirname(targetPath);
|
|
36
36
|
await fsp.mkdir(dir, { recursive: true });
|
|
37
|
-
const tmp =
|
|
37
|
+
const tmp = path16.join(dir, `.${path16.basename(targetPath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
38
38
|
try {
|
|
39
39
|
if (typeof content === "string") {
|
|
40
40
|
await fsp.writeFile(tmp, content, { flag: "wx", encoding: opts.encoding ?? "utf8" });
|
|
@@ -89,7 +89,7 @@ async function renameWithRetry(from, to) {
|
|
|
89
89
|
if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {
|
|
90
90
|
throw err;
|
|
91
91
|
}
|
|
92
|
-
await new Promise((
|
|
92
|
+
await new Promise((resolve5) => setTimeout(resolve5, delays[i]));
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
throw lastErr;
|
|
@@ -169,7 +169,7 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
169
169
|
this.pretty = opts.pretty ?? true;
|
|
170
170
|
if (this.file) {
|
|
171
171
|
try {
|
|
172
|
-
fs5.mkdirSync(
|
|
172
|
+
fs5.mkdirSync(path16.dirname(this.file), { recursive: true });
|
|
173
173
|
} catch {
|
|
174
174
|
}
|
|
175
175
|
}
|
|
@@ -342,7 +342,7 @@ var DefaultSessionStore = class {
|
|
|
342
342
|
}
|
|
343
343
|
/** Join session ID to its absolute path within the store directory. */
|
|
344
344
|
sessionPath(id, ext) {
|
|
345
|
-
return
|
|
345
|
+
return path16.join(this.dir, `${id}${ext}`);
|
|
346
346
|
}
|
|
347
347
|
async ensureShardDir(_id) {
|
|
348
348
|
await ensureDir(this.dir);
|
|
@@ -352,7 +352,7 @@ var DefaultSessionStore = class {
|
|
|
352
352
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
353
353
|
const id = meta.id ?? `${startedAt.replace(/[:.]/g, "-")}-${randomBytes(2).toString("hex")}`;
|
|
354
354
|
const shardDir = await this.ensureShardDir(id);
|
|
355
|
-
const file =
|
|
355
|
+
const file = path16.join(shardDir, `${id}.jsonl`);
|
|
356
356
|
let handle;
|
|
357
357
|
try {
|
|
358
358
|
handle = await fsp.open(file, "a", 384);
|
|
@@ -445,7 +445,7 @@ var DefaultSessionStore = class {
|
|
|
445
445
|
const ids = [];
|
|
446
446
|
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
447
447
|
for (const entry of entries) {
|
|
448
|
-
const full =
|
|
448
|
+
const full = path16.join(dir, entry.name);
|
|
449
449
|
if (entry.isDirectory()) {
|
|
450
450
|
ids.push(...await this.collectSessionIds(full));
|
|
451
451
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -601,7 +601,7 @@ var FileSessionWriter = class {
|
|
|
601
601
|
this.meta = meta;
|
|
602
602
|
this.events = events;
|
|
603
603
|
this.resumed = opts.resumed ?? false;
|
|
604
|
-
this.manifestFile = opts.dir ?
|
|
604
|
+
this.manifestFile = opts.dir ? path16.join(opts.dir, `${id}.summary.json`) : "";
|
|
605
605
|
this.filePath = opts.filePath ?? "";
|
|
606
606
|
this.secretScrubber = opts.secretScrubber;
|
|
607
607
|
this.summary = {
|
|
@@ -883,7 +883,7 @@ init_atomic_write();
|
|
|
883
883
|
var QueueStore = class {
|
|
884
884
|
file;
|
|
885
885
|
constructor(opts) {
|
|
886
|
-
this.file =
|
|
886
|
+
this.file = path16.join(opts.dir, "queue.json");
|
|
887
887
|
}
|
|
888
888
|
async write(items) {
|
|
889
889
|
if (items.length === 0) {
|
|
@@ -953,7 +953,7 @@ var DefaultAttachmentStore = class {
|
|
|
953
953
|
let data = input.data;
|
|
954
954
|
if (this.spoolDir && bytes >= this.spoolThreshold) {
|
|
955
955
|
await fsp.mkdir(this.spoolDir, { recursive: true });
|
|
956
|
-
spooledPath =
|
|
956
|
+
spooledPath = path16.join(this.spoolDir, `${id}.bin`);
|
|
957
957
|
await atomicWrite(spooledPath, input.data, {
|
|
958
958
|
encoding: input.kind === "image" ? "base64" : "utf8"
|
|
959
959
|
});
|
|
@@ -1141,7 +1141,7 @@ ${body.trim()}`);
|
|
|
1141
1141
|
async remember(text, scope = "project-memory") {
|
|
1142
1142
|
return this.runSerialized(scope, async () => {
|
|
1143
1143
|
const file = this.files[scope];
|
|
1144
|
-
await ensureDir(
|
|
1144
|
+
await ensureDir(path16.dirname(file));
|
|
1145
1145
|
let existing = "";
|
|
1146
1146
|
try {
|
|
1147
1147
|
existing = await fsp.readFile(file, "utf8");
|
|
@@ -1765,7 +1765,7 @@ var RecoveryLock = class {
|
|
|
1765
1765
|
sessionStore;
|
|
1766
1766
|
probe;
|
|
1767
1767
|
constructor(opts) {
|
|
1768
|
-
this.file =
|
|
1768
|
+
this.file = path16.join(opts.dir, LOCK_FILE);
|
|
1769
1769
|
this.pid = opts.pid ?? process.pid;
|
|
1770
1770
|
this.hostname = opts.hostname ?? os.hostname();
|
|
1771
1771
|
this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
@@ -1823,7 +1823,7 @@ var RecoveryLock = class {
|
|
|
1823
1823
|
* null return before calling this.
|
|
1824
1824
|
*/
|
|
1825
1825
|
async write(sessionId) {
|
|
1826
|
-
await ensureDir(
|
|
1826
|
+
await ensureDir(path16.dirname(this.file));
|
|
1827
1827
|
const lock = {
|
|
1828
1828
|
v: 1,
|
|
1829
1829
|
sessionId,
|
|
@@ -3050,7 +3050,7 @@ var DefaultSecretVault = class {
|
|
|
3050
3050
|
} catch (err) {
|
|
3051
3051
|
if (err.code !== "ENOENT") throw err;
|
|
3052
3052
|
}
|
|
3053
|
-
fs5.mkdirSync(
|
|
3053
|
+
fs5.mkdirSync(path16.dirname(this.keyFile), { recursive: true });
|
|
3054
3054
|
const key = randomBytes(KEY_BYTES);
|
|
3055
3055
|
try {
|
|
3056
3056
|
fs5.writeFileSync(this.keyFile, key, { mode: 384, flag: "wx" });
|
|
@@ -3119,7 +3119,7 @@ async function rewriteConfigEncrypted(configPath, vault, patch) {
|
|
|
3119
3119
|
}
|
|
3120
3120
|
const merged = deepMerge2(current, patch ?? {});
|
|
3121
3121
|
const encrypted = encryptConfigSecrets(merged, vault);
|
|
3122
|
-
await fsp.mkdir(
|
|
3122
|
+
await fsp.mkdir(path16.dirname(configPath), { recursive: true });
|
|
3123
3123
|
await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
3124
3124
|
await restrictFilePermissions(configPath);
|
|
3125
3125
|
}
|
|
@@ -3321,6 +3321,87 @@ function matchGlob(pattern, input) {
|
|
|
3321
3321
|
function matchAny(patterns, input) {
|
|
3322
3322
|
return patterns.some((p) => matchGlob(p, input));
|
|
3323
3323
|
}
|
|
3324
|
+
var DESTRUCTIVE_BASH_PATTERNS = [
|
|
3325
|
+
/\bgit\s+(?:clean\s+-[^\s]*[xdf]|reset\s+--hard)\b/i,
|
|
3326
|
+
/\b(?:drop|truncate)\s+(?:table|database|schema)\b/i,
|
|
3327
|
+
/\bdelete\s+from\b/i,
|
|
3328
|
+
/\b(?:mkfs|format|diskpart|shutdown|reboot)\b/i,
|
|
3329
|
+
/\bchmod\s+-R\s+777\b/i,
|
|
3330
|
+
/\bchown\s+-R\b/i,
|
|
3331
|
+
/\b(?:curl|wget)\b.*\|\s*(?:sh|bash|zsh|pwsh|powershell)\b/i,
|
|
3332
|
+
/\b(?:powershell|pwsh)\b.*(?:-encodedcommand|-enc)\b/i,
|
|
3333
|
+
/:\(\)\s*\{\s*:\|:&\s*}\s*;/
|
|
3334
|
+
];
|
|
3335
|
+
var PROJECT_ESCAPE_PATTERN = /(?:^|[\s"'])\.\.(?:[\\/]|$)/;
|
|
3336
|
+
var ABSOLUTE_PATH_PATTERN = /(?:^|[\s"'])(?:~[\\/]|\/[A-Za-z0-9_.-]|[A-Za-z]:[\\/])/;
|
|
3337
|
+
var SHELL_OPERATORS = /* @__PURE__ */ new Set(["&&", "||", "|", ";", ">", ">>", "<", "2>", "2>>"]);
|
|
3338
|
+
function getInputString(input, key) {
|
|
3339
|
+
if (!input || typeof input !== "object") return void 0;
|
|
3340
|
+
const value = input[key];
|
|
3341
|
+
return typeof value === "string" ? value : void 0;
|
|
3342
|
+
}
|
|
3343
|
+
function pathLooksInsideProject(rawPath, projectRoot) {
|
|
3344
|
+
if (!projectRoot) return false;
|
|
3345
|
+
if (rawPath === "~" || rawPath.startsWith("~/") || rawPath.startsWith("~\\")) return false;
|
|
3346
|
+
const resolved = path16.resolve(projectRoot, rawPath);
|
|
3347
|
+
const relative2 = path16.relative(projectRoot, resolved);
|
|
3348
|
+
return !!relative2 && !relative2.startsWith("..") && !path16.isAbsolute(relative2);
|
|
3349
|
+
}
|
|
3350
|
+
function tokenizeShell(command) {
|
|
3351
|
+
return command.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token) => token.replace(/^['"]|['"]$/g, "")) ?? [];
|
|
3352
|
+
}
|
|
3353
|
+
function pathTokenIsOutsideProject(token, projectRoot) {
|
|
3354
|
+
if (!token || SHELL_OPERATORS.has(token) || token.startsWith("-")) return false;
|
|
3355
|
+
if (token === "/" || token === "~" || token === "." || token === "..") return token !== ".";
|
|
3356
|
+
if (token.includes("*")) return true;
|
|
3357
|
+
if (token.startsWith("..") || token.includes("../") || token.includes("..\\")) return true;
|
|
3358
|
+
if (path16.isAbsolute(token) || token.startsWith("~/")) return !pathLooksInsideProject(token, projectRoot);
|
|
3359
|
+
return false;
|
|
3360
|
+
}
|
|
3361
|
+
function hasDangerousDeleteTarget(tokens, start, projectRoot) {
|
|
3362
|
+
const targets = tokens.slice(start).filter((token) => !token.startsWith("-") && !SHELL_OPERATORS.has(token));
|
|
3363
|
+
if (targets.length === 0) return true;
|
|
3364
|
+
return targets.some((target) => pathTokenIsOutsideProject(target, projectRoot));
|
|
3365
|
+
}
|
|
3366
|
+
function hasDestructiveDelete(command, projectRoot) {
|
|
3367
|
+
const tokens = tokenizeShell(command);
|
|
3368
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
3369
|
+
const token = tokens[i]?.toLowerCase();
|
|
3370
|
+
if (!token) continue;
|
|
3371
|
+
if (token === "rm") {
|
|
3372
|
+
const args = tokens.slice(i + 1);
|
|
3373
|
+
const recursiveOrForce = args.some(
|
|
3374
|
+
(arg) => /^-[^-]*[rf]/i.test(arg) || arg === "--recursive" || arg === "--force"
|
|
3375
|
+
);
|
|
3376
|
+
if (recursiveOrForce && hasDangerousDeleteTarget(tokens, i + 1, projectRoot)) return true;
|
|
3377
|
+
}
|
|
3378
|
+
if (token === "rmdir" || token === "rd") {
|
|
3379
|
+
const args = tokens.slice(i + 1);
|
|
3380
|
+
const recursive = args.some((arg) => arg.toLowerCase() === "/s");
|
|
3381
|
+
if (recursive && hasDangerousDeleteTarget(tokens, i + 1, projectRoot)) return true;
|
|
3382
|
+
}
|
|
3383
|
+
if (token === "del" || token === "erase") {
|
|
3384
|
+
if (hasDangerousDeleteTarget(tokens, i + 1, projectRoot)) return true;
|
|
3385
|
+
}
|
|
3386
|
+
if (token === "remove-item") {
|
|
3387
|
+
const args = tokens.slice(i + 1).map((arg) => arg.toLowerCase());
|
|
3388
|
+
const recursiveOrForce = args.includes("-recurse") || args.includes("-force");
|
|
3389
|
+
if (recursiveOrForce && hasDangerousDeleteTarget(tokens, i + 1, projectRoot)) return true;
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
return false;
|
|
3393
|
+
}
|
|
3394
|
+
function isClearlyDestructiveBashCommand(command, projectRoot) {
|
|
3395
|
+
const trimmed = command.trim();
|
|
3396
|
+
if (!trimmed) return false;
|
|
3397
|
+
if (hasDestructiveDelete(trimmed, projectRoot)) return true;
|
|
3398
|
+
if (DESTRUCTIVE_BASH_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
|
|
3399
|
+
if (/\bcd\s+(?:\.\.|~|\/|[A-Za-z]:[\\/])/i.test(trimmed)) return true;
|
|
3400
|
+
if (PROJECT_ESCAPE_PATTERN.test(trimmed)) return true;
|
|
3401
|
+
const absolute = trimmed.match(ABSOLUTE_PATH_PATTERN)?.[0]?.trim().replace(/^['"]|['"]$/g, "");
|
|
3402
|
+
if (absolute && !pathLooksInsideProject(absolute, projectRoot)) return true;
|
|
3403
|
+
return false;
|
|
3404
|
+
}
|
|
3324
3405
|
|
|
3325
3406
|
// src/security/permission-policy.ts
|
|
3326
3407
|
var DefaultPermissionPolicy = class {
|
|
@@ -3328,7 +3409,7 @@ var DefaultPermissionPolicy = class {
|
|
|
3328
3409
|
loaded = false;
|
|
3329
3410
|
trustFile;
|
|
3330
3411
|
yolo;
|
|
3331
|
-
|
|
3412
|
+
yoloDestructive;
|
|
3332
3413
|
/**
|
|
3333
3414
|
* Session-scoped "soft deny" map. When the user presses 'n' (block once),
|
|
3334
3415
|
* the tool+pattern is added here. If the LLM retries in the same session,
|
|
@@ -3361,7 +3442,7 @@ var DefaultPermissionPolicy = class {
|
|
|
3361
3442
|
constructor(opts) {
|
|
3362
3443
|
this.trustFile = opts.trustFile;
|
|
3363
3444
|
this.yolo = opts.yolo ?? false;
|
|
3364
|
-
this.
|
|
3445
|
+
this.yoloDestructive = opts.yoloDestructive ?? opts.forceAllYolo ?? false;
|
|
3365
3446
|
this.promptDelegate = opts.promptDelegate;
|
|
3366
3447
|
}
|
|
3367
3448
|
/**
|
|
@@ -3381,13 +3462,21 @@ var DefaultPermissionPolicy = class {
|
|
|
3381
3462
|
getYolo() {
|
|
3382
3463
|
return this.yolo;
|
|
3383
3464
|
}
|
|
3384
|
-
/** Toggle
|
|
3465
|
+
/** Toggle the destructive YOLO override at runtime. */
|
|
3466
|
+
setYoloDestructive(enabled) {
|
|
3467
|
+
this.yoloDestructive = enabled;
|
|
3468
|
+
}
|
|
3469
|
+
/** Check whether the destructive YOLO override is active. */
|
|
3470
|
+
getYoloDestructive() {
|
|
3471
|
+
return this.yoloDestructive;
|
|
3472
|
+
}
|
|
3473
|
+
/** @deprecated Use `setYoloDestructive`. */
|
|
3385
3474
|
setForceAllYolo(enabled) {
|
|
3386
|
-
this.
|
|
3475
|
+
this.setYoloDestructive(enabled);
|
|
3387
3476
|
}
|
|
3388
|
-
/**
|
|
3477
|
+
/** @deprecated Use `getYoloDestructive`. */
|
|
3389
3478
|
getForceAllYolo() {
|
|
3390
|
-
return this.
|
|
3479
|
+
return this.getYoloDestructive();
|
|
3391
3480
|
}
|
|
3392
3481
|
async reload() {
|
|
3393
3482
|
try {
|
|
@@ -3434,7 +3523,8 @@ var DefaultPermissionPolicy = class {
|
|
|
3434
3523
|
return { permission: "auto", source: "trust" };
|
|
3435
3524
|
}
|
|
3436
3525
|
if (this.yolo) {
|
|
3437
|
-
|
|
3526
|
+
const destructive = this.isDestructiveYoloCall(tool, input, ctx);
|
|
3527
|
+
if (destructive && !this.yoloDestructive) {
|
|
3438
3528
|
if (this.promptDelegate) {
|
|
3439
3529
|
const decision = await this.promptDelegate(tool, input, subject ?? tool.name);
|
|
3440
3530
|
if (decision === "always") {
|
|
@@ -3486,6 +3576,18 @@ var DefaultPermissionPolicy = class {
|
|
|
3486
3576
|
}
|
|
3487
3577
|
return { permission: "confirm", source: "default" };
|
|
3488
3578
|
}
|
|
3579
|
+
isDestructiveYoloCall(tool, input, ctx) {
|
|
3580
|
+
if (tool.name === "bash") {
|
|
3581
|
+
const command = getInputString(input, "command");
|
|
3582
|
+
return command ? isClearlyDestructiveBashCommand(command, ctx.projectRoot) : true;
|
|
3583
|
+
}
|
|
3584
|
+
if (tool.name === "write" || tool.name === "edit" || tool.name === "replace" || tool.name === "patch") {
|
|
3585
|
+
const targetPath = getInputString(input, "path") ?? getInputString(input, "file");
|
|
3586
|
+
if (!targetPath || !ctx.projectRoot) return false;
|
|
3587
|
+
return !pathLooksInsideProject(targetPath, ctx.projectRoot);
|
|
3588
|
+
}
|
|
3589
|
+
return tool.riskTier === "destructive";
|
|
3590
|
+
}
|
|
3489
3591
|
async trust(rule) {
|
|
3490
3592
|
if (!this.loaded) await this.reload();
|
|
3491
3593
|
const entry = this.policy[rule.tool] ?? {};
|
|
@@ -3803,7 +3905,7 @@ var DefaultRetryPolicy = class {
|
|
|
3803
3905
|
};
|
|
3804
3906
|
|
|
3805
3907
|
// src/execution/error-handler.ts
|
|
3806
|
-
var CONTEXT_OVERFLOW_RE = /context|too long|tokens/i;
|
|
3908
|
+
var CONTEXT_OVERFLOW_RE = /context|too long|tokens|exceeds the context window|context window/i;
|
|
3807
3909
|
function buildRecoveryStrategies(opts) {
|
|
3808
3910
|
return [
|
|
3809
3911
|
{
|
|
@@ -3811,7 +3913,7 @@ function buildRecoveryStrategies(opts) {
|
|
|
3811
3913
|
compactor: opts?.compactor,
|
|
3812
3914
|
async attempt(err, ctx) {
|
|
3813
3915
|
if (!(err instanceof ProviderError)) return null;
|
|
3814
|
-
if (err.status !== 413 && !
|
|
3916
|
+
if (err.status !== 413 && !isContextOverflowError(err)) return null;
|
|
3815
3917
|
if (this.compactor) {
|
|
3816
3918
|
try {
|
|
3817
3919
|
const report = await this.compactor.compact(ctx, { aggressive: true });
|
|
@@ -3845,6 +3947,14 @@ function buildRecoveryStrategies(opts) {
|
|
|
3845
3947
|
];
|
|
3846
3948
|
}
|
|
3847
3949
|
var DEFAULT_RECOVERY_STRATEGIES = buildRecoveryStrategies();
|
|
3950
|
+
function isContextOverflowError(err) {
|
|
3951
|
+
return CONTEXT_OVERFLOW_RE.test([
|
|
3952
|
+
err.message,
|
|
3953
|
+
err.body?.message,
|
|
3954
|
+
err.body?.type,
|
|
3955
|
+
err.body?.raw
|
|
3956
|
+
].filter(Boolean).join("\n"));
|
|
3957
|
+
}
|
|
3848
3958
|
var DefaultErrorHandler = class {
|
|
3849
3959
|
strategies;
|
|
3850
3960
|
constructor(strategies = DEFAULT_RECOVERY_STRATEGIES) {
|
|
@@ -3861,7 +3971,7 @@ var DefaultErrorHandler = class {
|
|
|
3861
3971
|
if (err.status === 429) return { kind: "rate_limit", retryable: true };
|
|
3862
3972
|
if (err.status === 529) return { kind: "overloaded", retryable: true };
|
|
3863
3973
|
if (err.status >= 500) return { kind: "server", retryable: true };
|
|
3864
|
-
if (err.status === 413 ||
|
|
3974
|
+
if (err.status === 413 || isContextOverflowError(err)) {
|
|
3865
3975
|
return { kind: "context_overflow", retryable: false };
|
|
3866
3976
|
}
|
|
3867
3977
|
if (err.status >= 400) return { kind: "client", retryable: false };
|
|
@@ -3900,7 +4010,7 @@ var DefaultSkillLoader = class {
|
|
|
3900
4010
|
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
3901
4011
|
for (const e of entries) {
|
|
3902
4012
|
if (!e.isDirectory()) continue;
|
|
3903
|
-
const skillFile =
|
|
4013
|
+
const skillFile = path16.join(dir, e.name, "SKILL.md");
|
|
3904
4014
|
try {
|
|
3905
4015
|
const raw = await fsp.readFile(skillFile, "utf8");
|
|
3906
4016
|
const meta = parseFrontmatter(raw);
|
|
@@ -4312,8 +4422,8 @@ async function streamProviderToResponse(provider, req, signal, ctx, events) {
|
|
|
4312
4422
|
try {
|
|
4313
4423
|
await Promise.race([
|
|
4314
4424
|
Promise.resolve(iter.return?.()),
|
|
4315
|
-
new Promise((
|
|
4316
|
-
drainTimer = setTimeout(
|
|
4425
|
+
new Promise((resolve5) => {
|
|
4426
|
+
drainTimer = setTimeout(resolve5, 500);
|
|
4317
4427
|
})
|
|
4318
4428
|
]);
|
|
4319
4429
|
} finally {
|
|
@@ -4374,7 +4484,7 @@ async function runProviderWithRetry(opts) {
|
|
|
4374
4484
|
description
|
|
4375
4485
|
});
|
|
4376
4486
|
}
|
|
4377
|
-
await new Promise((
|
|
4487
|
+
await new Promise((resolve5, reject) => {
|
|
4378
4488
|
let settled = false;
|
|
4379
4489
|
const onAbort = () => {
|
|
4380
4490
|
if (settled) return;
|
|
@@ -4387,7 +4497,7 @@ async function runProviderWithRetry(opts) {
|
|
|
4387
4497
|
settled = true;
|
|
4388
4498
|
clearTimeout(t);
|
|
4389
4499
|
signal.removeEventListener("abort", onAbort);
|
|
4390
|
-
|
|
4500
|
+
resolve5();
|
|
4391
4501
|
}, delay);
|
|
4392
4502
|
if (signal.aborted) {
|
|
4393
4503
|
onAbort();
|
|
@@ -5488,11 +5598,11 @@ function validateAgainstSchema(value, schema) {
|
|
|
5488
5598
|
walk3(value, schema, "", errors);
|
|
5489
5599
|
return { ok: errors.length === 0, errors };
|
|
5490
5600
|
}
|
|
5491
|
-
function walk3(value, schema,
|
|
5601
|
+
function walk3(value, schema, path19, errors) {
|
|
5492
5602
|
if (schema.enum !== void 0) {
|
|
5493
5603
|
if (!schema.enum.some((e) => deepEqual(e, value))) {
|
|
5494
5604
|
errors.push({
|
|
5495
|
-
path:
|
|
5605
|
+
path: path19 || "<root>",
|
|
5496
5606
|
message: `expected one of ${JSON.stringify(schema.enum)}, got ${JSON.stringify(value)}`
|
|
5497
5607
|
});
|
|
5498
5608
|
return;
|
|
@@ -5501,7 +5611,7 @@ function walk3(value, schema, path18, errors) {
|
|
|
5501
5611
|
if (typeof schema.type === "string") {
|
|
5502
5612
|
if (!checkType(value, schema.type)) {
|
|
5503
5613
|
errors.push({
|
|
5504
|
-
path:
|
|
5614
|
+
path: path19 || "<root>",
|
|
5505
5615
|
message: `expected ${schema.type}, got ${describeType(value)}`
|
|
5506
5616
|
});
|
|
5507
5617
|
return;
|
|
@@ -5511,19 +5621,19 @@ function walk3(value, schema, path18, errors) {
|
|
|
5511
5621
|
const obj = value;
|
|
5512
5622
|
for (const req of schema.required ?? []) {
|
|
5513
5623
|
if (!(req in obj)) {
|
|
5514
|
-
errors.push({ path: joinPath(
|
|
5624
|
+
errors.push({ path: joinPath(path19, req), message: "required property missing" });
|
|
5515
5625
|
}
|
|
5516
5626
|
}
|
|
5517
5627
|
if (schema.properties) {
|
|
5518
5628
|
for (const [key, subSchema] of Object.entries(schema.properties)) {
|
|
5519
5629
|
if (key in obj) {
|
|
5520
|
-
walk3(obj[key], subSchema, joinPath(
|
|
5630
|
+
walk3(obj[key], subSchema, joinPath(path19, key), errors);
|
|
5521
5631
|
}
|
|
5522
5632
|
}
|
|
5523
5633
|
}
|
|
5524
5634
|
}
|
|
5525
5635
|
if (schema.type === "array" && Array.isArray(value) && schema.items) {
|
|
5526
|
-
value.forEach((item, i) => walk3(item, schema.items, `${
|
|
5636
|
+
value.forEach((item, i) => walk3(item, schema.items, `${path19}[${i}]`, errors));
|
|
5527
5637
|
}
|
|
5528
5638
|
}
|
|
5529
5639
|
function checkType(value, type) {
|
|
@@ -5649,8 +5759,9 @@ var ToolExecutor = class {
|
|
|
5649
5759
|
*/
|
|
5650
5760
|
async executeBatch(toolUses, ctx, strategy) {
|
|
5651
5761
|
let budget = this.opts.perIterationOutputCapBytes ?? 1e5;
|
|
5652
|
-
const runOne = async (
|
|
5762
|
+
const runOne = async (use0) => {
|
|
5653
5763
|
const start = Date.now();
|
|
5764
|
+
let use = use0;
|
|
5654
5765
|
const tool = this.registry.get(use.name);
|
|
5655
5766
|
if (!tool) {
|
|
5656
5767
|
const result = this.unknownToolResult(use, () => this.registry.list().map((t) => t.name));
|
|
@@ -5683,10 +5794,36 @@ Please call the tool again with arguments that match its inputSchema. You can us
|
|
|
5683
5794
|
budget = this.decrementBudget(result, budget);
|
|
5684
5795
|
return { result, tool, durationMs: Date.now() - start };
|
|
5685
5796
|
}
|
|
5797
|
+
if (this.opts.hookRunner?.has("PreToolUse")) {
|
|
5798
|
+
const pre = await this.opts.hookRunner.preToolUse(tool.name, use.input, ctx);
|
|
5799
|
+
if (pre.block) {
|
|
5800
|
+
const result = this.blockedByHookResult(use, pre.reason);
|
|
5801
|
+
budget = this.decrementBudget(result, budget);
|
|
5802
|
+
return { result, tool, durationMs: Date.now() - start };
|
|
5803
|
+
}
|
|
5804
|
+
if (pre.input) {
|
|
5805
|
+
const reval = validateAgainstSchema(pre.input, tool.inputSchema);
|
|
5806
|
+
if (!reval.ok) {
|
|
5807
|
+
const errorDetails = reval.errors.map((e) => ` - ${e.path || "input"}: ${e.message}`).join("\n");
|
|
5808
|
+
const result = {
|
|
5809
|
+
type: "tool_result",
|
|
5810
|
+
tool_use_id: use.id,
|
|
5811
|
+
content: `A PreToolUse hook rewrote the arguments for "${tool.name}" into an invalid shape.
|
|
5812
|
+
|
|
5813
|
+
Validation errors:
|
|
5814
|
+
${errorDetails}`,
|
|
5815
|
+
is_error: true
|
|
5816
|
+
};
|
|
5817
|
+
budget = this.decrementBudget(result, budget);
|
|
5818
|
+
return { result, tool, durationMs: Date.now() - start };
|
|
5819
|
+
}
|
|
5820
|
+
use = { ...use, input: pre.input };
|
|
5821
|
+
}
|
|
5822
|
+
}
|
|
5686
5823
|
const decision = await this.opts.permissionPolicy.evaluate(tool, use.input, ctx);
|
|
5687
5824
|
let effectivePermission = decision.permission;
|
|
5688
5825
|
const policy = this.opts.permissionPolicy;
|
|
5689
|
-
const yolo = policy.getYolo?.() === true || policy.getForceAllYolo?.() === true;
|
|
5826
|
+
const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true || policy.getForceAllYolo?.() === true;
|
|
5690
5827
|
if (toolDangerousCaps.length > 0 && effectivePermission === "auto" && !yolo) {
|
|
5691
5828
|
effectivePermission = "confirm";
|
|
5692
5829
|
}
|
|
@@ -5729,7 +5866,20 @@ Please call the tool again with arguments that match its inputSchema. You can us
|
|
|
5729
5866
|
"tool.has_dangerous_capabilities": toolCapsForAudit.length > 0
|
|
5730
5867
|
});
|
|
5731
5868
|
try {
|
|
5732
|
-
|
|
5869
|
+
let result = await this.executeTool(tool, use, ctx, budget);
|
|
5870
|
+
if (this.opts.hookRunner?.has("PostToolUse")) {
|
|
5871
|
+
const post = await this.opts.hookRunner.postToolUse(
|
|
5872
|
+
tool.name,
|
|
5873
|
+
use.input,
|
|
5874
|
+
{ content: String(result.content), isError: !!result.is_error },
|
|
5875
|
+
ctx
|
|
5876
|
+
);
|
|
5877
|
+
if (post.additionalContext) {
|
|
5878
|
+
result = { ...result, content: `${result.content}
|
|
5879
|
+
|
|
5880
|
+
${post.additionalContext}` };
|
|
5881
|
+
}
|
|
5882
|
+
}
|
|
5733
5883
|
budget = this.decrementBudget(result, budget);
|
|
5734
5884
|
span?.setAttribute("tool.is_error", !!result.is_error);
|
|
5735
5885
|
span?.setAttribute(
|
|
@@ -5918,6 +6068,14 @@ ${excerpt}`;
|
|
|
5918
6068
|
is_error: true
|
|
5919
6069
|
};
|
|
5920
6070
|
}
|
|
6071
|
+
blockedByHookResult(use, reason) {
|
|
6072
|
+
return {
|
|
6073
|
+
type: "tool_result",
|
|
6074
|
+
tool_use_id: use.id,
|
|
6075
|
+
content: `Tool "${use.name}" was blocked by a PreToolUse hook: ${reason ?? "no reason given"}`,
|
|
6076
|
+
is_error: true
|
|
6077
|
+
};
|
|
6078
|
+
}
|
|
5921
6079
|
decrementBudget(result, budget) {
|
|
5922
6080
|
const contentBytes = typeof result.content === "string" ? Buffer.byteLength(result.content, "utf8") : Buffer.byteLength(JSON.stringify(result.content), "utf8");
|
|
5923
6081
|
return Math.max(0, budget - contentBytes);
|
|
@@ -6144,8 +6302,8 @@ var AutonomousRunner = class {
|
|
|
6144
6302
|
init_atomic_write();
|
|
6145
6303
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
6146
6304
|
function goalFilePath(projectRoot) {
|
|
6147
|
-
const hash = createHash("sha256").update(
|
|
6148
|
-
return
|
|
6305
|
+
const hash = createHash("sha256").update(path16.resolve(projectRoot)).digest("hex").slice(0, 12);
|
|
6306
|
+
return path16.join(os.homedir(), ".wrongstack", "projects", hash, "goal.json");
|
|
6149
6307
|
}
|
|
6150
6308
|
async function loadGoal(filePath) {
|
|
6151
6309
|
let raw;
|
|
@@ -6631,7 +6789,8 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
6631
6789
|
" \u2022 When this iteration's Task is finished (real artifact / passing",
|
|
6632
6790
|
" test / applied diff / clean output), emit `[done]` on its own line.",
|
|
6633
6791
|
" \u2022 Do not stop on the first obstacle \u2014 try at least 3 distinct",
|
|
6634
|
-
" approaches before giving up. YOLO is active
|
|
6792
|
+
" approaches before giving up. YOLO is active for normal project work;",
|
|
6793
|
+
" destructive-gated confirmations still belong to the permission flow.",
|
|
6635
6794
|
"",
|
|
6636
6795
|
"2. UPDATE TODO STATE (when Source is `todo`)",
|
|
6637
6796
|
" \u2022 Mark this todo `in_progress` via the todos tool before tool work.",
|
|
@@ -6760,7 +6919,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
6760
6919
|
}
|
|
6761
6920
|
};
|
|
6762
6921
|
function sleep(ms) {
|
|
6763
|
-
return new Promise((
|
|
6922
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
6764
6923
|
}
|
|
6765
6924
|
|
|
6766
6925
|
// src/coordination/subagent-budget.ts
|
|
@@ -6976,12 +7135,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6976
7135
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
6977
7136
|
return Promise.resolve("stop");
|
|
6978
7137
|
}
|
|
6979
|
-
return new Promise((
|
|
7138
|
+
return new Promise((resolve5) => {
|
|
6980
7139
|
let resolved = false;
|
|
6981
7140
|
const respond = (d) => {
|
|
6982
7141
|
if (resolved) return;
|
|
6983
7142
|
resolved = true;
|
|
6984
|
-
|
|
7143
|
+
resolve5(d);
|
|
6985
7144
|
};
|
|
6986
7145
|
const fallback = setTimeout(
|
|
6987
7146
|
() => respond("stop"),
|
|
@@ -10208,7 +10367,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
10208
10367
|
taskIds.map((id) => {
|
|
10209
10368
|
const cached = this.completedResults.find((r) => r.taskId === id);
|
|
10210
10369
|
if (cached) return cached;
|
|
10211
|
-
return new Promise((
|
|
10370
|
+
return new Promise((resolve5, reject) => {
|
|
10212
10371
|
const timeout = setTimeout(() => {
|
|
10213
10372
|
this.off("task.completed", handler);
|
|
10214
10373
|
reject(new Error(`awaitTasks timed out waiting for task "${id}"`));
|
|
@@ -10217,7 +10376,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
10217
10376
|
if (result.taskId === id) {
|
|
10218
10377
|
clearTimeout(timeout);
|
|
10219
10378
|
this.off("task.completed", handler);
|
|
10220
|
-
|
|
10379
|
+
resolve5(result);
|
|
10221
10380
|
}
|
|
10222
10381
|
};
|
|
10223
10382
|
this.on("task.completed", handler);
|
|
@@ -10720,7 +10879,7 @@ function providerErrorToSubagentError(err, message, cause) {
|
|
|
10720
10879
|
|
|
10721
10880
|
// src/execution/parallel-eternal-engine.ts
|
|
10722
10881
|
function sleep2(ms) {
|
|
10723
|
-
return new Promise((
|
|
10882
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
10724
10883
|
}
|
|
10725
10884
|
var GOAL_COMPLETE_MARKER2 = /^\s*\[goal[_\s-]?complete\]\s*$/im;
|
|
10726
10885
|
var ParallelEternalEngine = class {
|
|
@@ -10899,7 +11058,8 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
10899
11058
|
"\u2500\u2500 EXECUTION PROTOCOL \u2500\u2500",
|
|
10900
11059
|
"\u2022 Execute the assigned task end-to-end using multiple tool calls.",
|
|
10901
11060
|
"\u2022 Emit `[done]` on its own line when the task is complete.",
|
|
10902
|
-
"\u2022 Do not ask
|
|
11061
|
+
"\u2022 Do not ask before routine in-project tool use \u2014 YOLO is active for normal project work.",
|
|
11062
|
+
"\u2022 If a destructive-gated confirmation appears, wait for the permission flow.",
|
|
10903
11063
|
"\u2022 If the overall Mission is accomplished, emit `[GOAL_COMPLETE]` followed by a verification recipe.",
|
|
10904
11064
|
"\u2022 Keep output concise \u2014 summarize findings, do not transcribe files."
|
|
10905
11065
|
].join("\n");
|
|
@@ -11156,8 +11316,10 @@ ${journalTail.join("\n")}` : "Recent journal: (none \u2014 this is the first ite
|
|
|
11156
11316
|
" decide.",
|
|
11157
11317
|
"",
|
|
11158
11318
|
"### Operating principles",
|
|
11159
|
-
"- YOLO is active
|
|
11160
|
-
"
|
|
11319
|
+
"- YOLO is active for normal project work. Proceed with routine",
|
|
11320
|
+
" in-project tool use without pre-confirming; pick the best path and execute it.",
|
|
11321
|
+
" If the permission system raises a destructive-gated confirmation, wait",
|
|
11322
|
+
" for that flow instead of trying to bypass it.",
|
|
11161
11323
|
"- Use tools freely; multiple calls per turn are normal and expected.",
|
|
11162
11324
|
"- When working on a todo, mark it `in_progress` via the todos tool",
|
|
11163
11325
|
" before tool work and `completed` (or `cancelled` with a reason)",
|
|
@@ -11346,7 +11508,7 @@ var InMemoryAgentBridge = class {
|
|
|
11346
11508
|
);
|
|
11347
11509
|
}
|
|
11348
11510
|
this.inflightGuards.add(correlationId);
|
|
11349
|
-
return new Promise((
|
|
11511
|
+
return new Promise((resolve5, reject) => {
|
|
11350
11512
|
const timer = setTimeout(() => {
|
|
11351
11513
|
this.inflightGuards.delete(correlationId);
|
|
11352
11514
|
this.pendingRequests.delete(correlationId);
|
|
@@ -11358,7 +11520,7 @@ var InMemoryAgentBridge = class {
|
|
|
11358
11520
|
return;
|
|
11359
11521
|
}
|
|
11360
11522
|
this.pendingRequests.set(correlationId, {
|
|
11361
|
-
resolve:
|
|
11523
|
+
resolve: resolve5,
|
|
11362
11524
|
reject,
|
|
11363
11525
|
timer
|
|
11364
11526
|
});
|
|
@@ -13658,7 +13820,7 @@ var Director = class _Director {
|
|
|
13658
13820
|
})),
|
|
13659
13821
|
usage: this.usage.snapshot()
|
|
13660
13822
|
};
|
|
13661
|
-
await fsp.mkdir(
|
|
13823
|
+
await fsp.mkdir(path16.dirname(this.manifestPath), { recursive: true });
|
|
13662
13824
|
await atomicWrite(this.manifestPath, JSON.stringify(manifest, null, 2), { mode: 384 });
|
|
13663
13825
|
return this.manifestPath;
|
|
13664
13826
|
}
|
|
@@ -13777,11 +13939,11 @@ var Director = class _Director {
|
|
|
13777
13939
|
if (cached) return cached;
|
|
13778
13940
|
const existing = this.taskWaiters.get(id);
|
|
13779
13941
|
if (existing) return existing.promise;
|
|
13780
|
-
let
|
|
13942
|
+
let resolve5;
|
|
13781
13943
|
const promise = new Promise((res) => {
|
|
13782
|
-
|
|
13944
|
+
resolve5 = res;
|
|
13783
13945
|
});
|
|
13784
|
-
this.taskWaiters.set(id, { promise, resolve:
|
|
13946
|
+
this.taskWaiters.set(id, { promise, resolve: resolve5 });
|
|
13785
13947
|
return promise;
|
|
13786
13948
|
})
|
|
13787
13949
|
);
|
|
@@ -13864,7 +14026,7 @@ var Director = class _Director {
|
|
|
13864
14026
|
*/
|
|
13865
14027
|
async readSession(subagentId, tail) {
|
|
13866
14028
|
if (!this.sessionsRoot) return null;
|
|
13867
|
-
const filePath =
|
|
14029
|
+
const filePath = path16.join(this.sessionsRoot, this.directorRunId, `${subagentId}.jsonl`);
|
|
13868
14030
|
let raw;
|
|
13869
14031
|
try {
|
|
13870
14032
|
raw = await fsp.readFile(filePath, "utf8");
|
|
@@ -14166,7 +14328,7 @@ function createDelegateTool(opts) {
|
|
|
14166
14328
|
subagentId
|
|
14167
14329
|
});
|
|
14168
14330
|
const dir = director;
|
|
14169
|
-
const result = await new Promise((
|
|
14331
|
+
const result = await new Promise((resolve5) => {
|
|
14170
14332
|
let settled = false;
|
|
14171
14333
|
let timer;
|
|
14172
14334
|
const finish = (value) => {
|
|
@@ -14176,7 +14338,7 @@ function createDelegateTool(opts) {
|
|
|
14176
14338
|
offTool();
|
|
14177
14339
|
offIter();
|
|
14178
14340
|
offProgress();
|
|
14179
|
-
|
|
14341
|
+
resolve5(value);
|
|
14180
14342
|
};
|
|
14181
14343
|
const arm = () => {
|
|
14182
14344
|
if (timer) clearTimeout(timer);
|
|
@@ -14320,13 +14482,13 @@ async function readSubagentPartial(opts, subagentId) {
|
|
|
14320
14482
|
if (!opts.sessionsRoot) return void 0;
|
|
14321
14483
|
const candidates = [];
|
|
14322
14484
|
if (opts.directorRunId) {
|
|
14323
|
-
candidates.push(
|
|
14485
|
+
candidates.push(path16.join(opts.sessionsRoot, opts.directorRunId, `${subagentId}.jsonl`));
|
|
14324
14486
|
} else {
|
|
14325
14487
|
try {
|
|
14326
14488
|
const entries = await fsp.readdir(opts.sessionsRoot, { withFileTypes: true });
|
|
14327
14489
|
for (const entry of entries) {
|
|
14328
14490
|
if (entry.isDirectory()) {
|
|
14329
|
-
candidates.push(
|
|
14491
|
+
candidates.push(path16.join(opts.sessionsRoot, entry.name, `${subagentId}.jsonl`));
|
|
14330
14492
|
}
|
|
14331
14493
|
}
|
|
14332
14494
|
} catch {
|
|
@@ -14373,9 +14535,9 @@ function makeDirectorSessionFactory(opts) {
|
|
|
14373
14535
|
let dir;
|
|
14374
14536
|
if (opts.store) {
|
|
14375
14537
|
store = opts.store;
|
|
14376
|
-
dir = opts.sessionsRoot ?
|
|
14538
|
+
dir = opts.sessionsRoot ? path16.join(opts.sessionsRoot, runId) : "(caller-managed)";
|
|
14377
14539
|
} else if (opts.sessionsRoot) {
|
|
14378
|
-
dir =
|
|
14540
|
+
dir = path16.join(opts.sessionsRoot, runId);
|
|
14379
14541
|
store = new DefaultSessionStore({ dir });
|
|
14380
14542
|
} else {
|
|
14381
14543
|
throw new Error("makeDirectorSessionFactory requires either `store` or `sessionsRoot`");
|
|
@@ -14579,7 +14741,7 @@ var DefaultModelsRegistry = class {
|
|
|
14579
14741
|
this.overlay = opts.overlay;
|
|
14580
14742
|
this.overlayUrl = opts.overlayUrl;
|
|
14581
14743
|
this.overlayFile = opts.overlayFile;
|
|
14582
|
-
this.overlayCacheFile = opts.overlayCacheFile ?? (opts.overlayUrl ?
|
|
14744
|
+
this.overlayCacheFile = opts.overlayCacheFile ?? (opts.overlayUrl ? path16.join(path16.dirname(opts.cacheFile), "models-overlay-cache.json") : void 0);
|
|
14583
14745
|
}
|
|
14584
14746
|
async load(opts = {}) {
|
|
14585
14747
|
if (this.payload && !opts.force) return this.payload;
|
|
@@ -14792,7 +14954,7 @@ var DefaultModelsRegistry = class {
|
|
|
14792
14954
|
}
|
|
14793
14955
|
/** Used by `wstack models refresh` to expose where the cache lives. */
|
|
14794
14956
|
cacheLocation() {
|
|
14795
|
-
return
|
|
14957
|
+
return path16.resolve(this.cacheFile);
|
|
14796
14958
|
}
|
|
14797
14959
|
};
|
|
14798
14960
|
function hasEntries(payload) {
|
|
@@ -15079,7 +15241,7 @@ var DefaultModeStore = class {
|
|
|
15079
15241
|
}
|
|
15080
15242
|
async loadActiveMode() {
|
|
15081
15243
|
try {
|
|
15082
|
-
const configPath =
|
|
15244
|
+
const configPath = path16.join(this.configDir, "mode.json");
|
|
15083
15245
|
const content = await fsp.readFile(configPath, "utf8");
|
|
15084
15246
|
const data = JSON.parse(content);
|
|
15085
15247
|
this.activeModeId = data.activeMode ?? null;
|
|
@@ -15090,7 +15252,7 @@ var DefaultModeStore = class {
|
|
|
15090
15252
|
async saveActiveMode() {
|
|
15091
15253
|
try {
|
|
15092
15254
|
await fsp.mkdir(this.configDir, { recursive: true });
|
|
15093
|
-
const configPath =
|
|
15255
|
+
const configPath = path16.join(this.configDir, "mode.json");
|
|
15094
15256
|
await atomicWrite(
|
|
15095
15257
|
configPath,
|
|
15096
15258
|
JSON.stringify({ activeMode: this.activeModeId }, null, 2)
|
|
@@ -15105,11 +15267,11 @@ async function loadProjectModes(modesDir) {
|
|
|
15105
15267
|
const entries = await fsp.readdir(modesDir);
|
|
15106
15268
|
for (const entry of entries) {
|
|
15107
15269
|
if (!entry.endsWith(".md") && !entry.endsWith(".txt")) continue;
|
|
15108
|
-
const filePath =
|
|
15270
|
+
const filePath = path16.join(modesDir, entry);
|
|
15109
15271
|
const stat5 = await fsp.stat(filePath);
|
|
15110
15272
|
if (!stat5.isFile()) continue;
|
|
15111
15273
|
const content = await fsp.readFile(filePath, "utf8");
|
|
15112
|
-
const id =
|
|
15274
|
+
const id = path16.basename(entry, path16.extname(entry));
|
|
15113
15275
|
modes.push({
|
|
15114
15276
|
id,
|
|
15115
15277
|
name: id.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
@@ -15125,7 +15287,7 @@ async function loadProjectModes(modesDir) {
|
|
|
15125
15287
|
async function loadUserModes(modesDir) {
|
|
15126
15288
|
const modes = [];
|
|
15127
15289
|
try {
|
|
15128
|
-
const manifestPath =
|
|
15290
|
+
const manifestPath = path16.join(modesDir, "modes.json");
|
|
15129
15291
|
const content = await fsp.readFile(manifestPath, "utf8");
|
|
15130
15292
|
const manifest = JSON.parse(content);
|
|
15131
15293
|
for (const mode of manifest.modes) {
|
|
@@ -16042,7 +16204,7 @@ var SpecStore = class {
|
|
|
16042
16204
|
indexPath;
|
|
16043
16205
|
constructor(opts) {
|
|
16044
16206
|
this.baseDir = opts.baseDir;
|
|
16045
|
-
this.indexPath =
|
|
16207
|
+
this.indexPath = path16.join(this.baseDir, "_index.json");
|
|
16046
16208
|
}
|
|
16047
16209
|
async save(spec) {
|
|
16048
16210
|
await ensureDir(this.baseDir);
|
|
@@ -16111,7 +16273,7 @@ var SpecStore = class {
|
|
|
16111
16273
|
return updated;
|
|
16112
16274
|
}
|
|
16113
16275
|
filePath(id) {
|
|
16114
|
-
return
|
|
16276
|
+
return path16.join(this.baseDir, `${id}.json`);
|
|
16115
16277
|
}
|
|
16116
16278
|
async readIndex() {
|
|
16117
16279
|
try {
|
|
@@ -16168,7 +16330,7 @@ var TaskGraphStore = class {
|
|
|
16168
16330
|
indexPath;
|
|
16169
16331
|
constructor(opts) {
|
|
16170
16332
|
this.baseDir = opts.baseDir;
|
|
16171
|
-
this.indexPath =
|
|
16333
|
+
this.indexPath = path16.join(this.baseDir, "_index.json");
|
|
16172
16334
|
}
|
|
16173
16335
|
async save(graph) {
|
|
16174
16336
|
await ensureDir(this.baseDir);
|
|
@@ -16206,7 +16368,7 @@ var TaskGraphStore = class {
|
|
|
16206
16368
|
}
|
|
16207
16369
|
}
|
|
16208
16370
|
filePath(id) {
|
|
16209
|
-
return
|
|
16371
|
+
return path16.join(this.baseDir, `${id}.json`);
|
|
16210
16372
|
}
|
|
16211
16373
|
async readIndex() {
|
|
16212
16374
|
try {
|
|
@@ -16451,9 +16613,9 @@ var AISpecBuilder = class {
|
|
|
16451
16613
|
if (!this.sessionPath) return;
|
|
16452
16614
|
try {
|
|
16453
16615
|
const fsp16 = await import('fs/promises');
|
|
16454
|
-
const
|
|
16616
|
+
const path19 = await import('path');
|
|
16455
16617
|
const { atomicWrite: atomicWrite2 } = await Promise.resolve().then(() => (init_atomic_write(), atomic_write_exports));
|
|
16456
|
-
await fsp16.mkdir(
|
|
16618
|
+
await fsp16.mkdir(path19.dirname(this.sessionPath), { recursive: true });
|
|
16457
16619
|
await atomicWrite2(this.sessionPath, JSON.stringify(this.session, null, 2));
|
|
16458
16620
|
} catch {
|
|
16459
16621
|
}
|
|
@@ -17163,15 +17325,15 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
|
|
|
17163
17325
|
maxId = id;
|
|
17164
17326
|
}
|
|
17165
17327
|
}
|
|
17166
|
-
const
|
|
17328
|
+
const path19 = [];
|
|
17167
17329
|
let current = maxId;
|
|
17168
17330
|
const visited = /* @__PURE__ */ new Set();
|
|
17169
17331
|
while (current && !visited.has(current)) {
|
|
17170
17332
|
visited.add(current);
|
|
17171
|
-
|
|
17333
|
+
path19.unshift(current);
|
|
17172
17334
|
current = prev.get(current) ?? null;
|
|
17173
17335
|
}
|
|
17174
|
-
return
|
|
17336
|
+
return path19;
|
|
17175
17337
|
}
|
|
17176
17338
|
function computeParallelGroups(graph, blockedByMap) {
|
|
17177
17339
|
const groups = [];
|
|
@@ -17721,7 +17883,7 @@ var SddParallelRun = class {
|
|
|
17721
17883
|
"\u2500\u2500 EXECUTION PROTOCOL \u2500\u2500",
|
|
17722
17884
|
"\u2022 Execute the assigned SDD task end-to-end using multiple tool calls.",
|
|
17723
17885
|
"\u2022 Mark the task [done] in the tracker when complete.",
|
|
17724
|
-
"\u2022 Do not ask for
|
|
17886
|
+
"\u2022 Do not ask before routine in-project tool use; if a permission gate appears, wait for that flow.",
|
|
17725
17887
|
"\u2022 Keep output concise \u2014 summarize changes, do not transcribe files."
|
|
17726
17888
|
].join("\n");
|
|
17727
17889
|
const spawns = subagentIds.map(
|
|
@@ -17964,9 +18126,9 @@ var DefaultHealthRegistry = class {
|
|
|
17964
18126
|
}
|
|
17965
18127
|
async runOne(check) {
|
|
17966
18128
|
let timer = null;
|
|
17967
|
-
const timeout = new Promise((
|
|
18129
|
+
const timeout = new Promise((resolve5) => {
|
|
17968
18130
|
timer = setTimeout(
|
|
17969
|
-
() =>
|
|
18131
|
+
() => resolve5({ status: "unhealthy", detail: `timeout after ${this.timeoutMs}ms` }),
|
|
17970
18132
|
this.timeoutMs
|
|
17971
18133
|
);
|
|
17972
18134
|
});
|
|
@@ -18149,7 +18311,7 @@ async function startMetricsServer(opts) {
|
|
|
18149
18311
|
const tls = opts.tls;
|
|
18150
18312
|
const useHttps = !!(tls?.cert && tls?.key);
|
|
18151
18313
|
const host = opts.host ?? "127.0.0.1";
|
|
18152
|
-
const
|
|
18314
|
+
const path19 = opts.path ?? "/metrics";
|
|
18153
18315
|
const healthPath = opts.healthPath ?? "/healthz";
|
|
18154
18316
|
const healthRegistry = opts.healthRegistry;
|
|
18155
18317
|
const listener = (req, res) => {
|
|
@@ -18159,7 +18321,7 @@ async function startMetricsServer(opts) {
|
|
|
18159
18321
|
return;
|
|
18160
18322
|
}
|
|
18161
18323
|
const url = req.url.split("?")[0];
|
|
18162
|
-
if (url ===
|
|
18324
|
+
if (url === path19) {
|
|
18163
18325
|
let body;
|
|
18164
18326
|
try {
|
|
18165
18327
|
body = renderPrometheus(opts.sink.snapshot());
|
|
@@ -18205,14 +18367,14 @@ async function startMetricsServer(opts) {
|
|
|
18205
18367
|
const { createServer } = await import('http');
|
|
18206
18368
|
server = createServer(listener);
|
|
18207
18369
|
}
|
|
18208
|
-
await new Promise((
|
|
18370
|
+
await new Promise((resolve5, reject) => {
|
|
18209
18371
|
const onError = (err) => {
|
|
18210
18372
|
server.off("listening", onListening);
|
|
18211
18373
|
reject(err);
|
|
18212
18374
|
};
|
|
18213
18375
|
const onListening = () => {
|
|
18214
18376
|
server.off("error", onError);
|
|
18215
|
-
|
|
18377
|
+
resolve5();
|
|
18216
18378
|
};
|
|
18217
18379
|
server.once("error", onError);
|
|
18218
18380
|
server.once("listening", onListening);
|
|
@@ -18223,9 +18385,9 @@ async function startMetricsServer(opts) {
|
|
|
18223
18385
|
const protocol = useHttps ? "https" : "http";
|
|
18224
18386
|
return {
|
|
18225
18387
|
port: boundPort,
|
|
18226
|
-
url: `${protocol}://${host}:${boundPort}${
|
|
18227
|
-
close: () => new Promise((
|
|
18228
|
-
server.close((err) => err ? reject(err) :
|
|
18388
|
+
url: `${protocol}://${host}:${boundPort}${path19}`,
|
|
18389
|
+
close: () => new Promise((resolve5, reject) => {
|
|
18390
|
+
server.close((err) => err ? reject(err) : resolve5());
|
|
18229
18391
|
})
|
|
18230
18392
|
};
|
|
18231
18393
|
}
|
|
@@ -18774,7 +18936,7 @@ var context7Server = () => ({
|
|
|
18774
18936
|
name: "context7",
|
|
18775
18937
|
description: "Codebase-aware documentation and Q&A (context7.ai)",
|
|
18776
18938
|
transport: "streamable-http",
|
|
18777
|
-
url: "https://
|
|
18939
|
+
url: "https://mcp.context7.com/mcp",
|
|
18778
18940
|
permission: "confirm"
|
|
18779
18941
|
});
|
|
18780
18942
|
var braveSearchServer = () => ({
|