@wrongstack/core 0.51.3 → 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-CjbD-i7-.d.ts → agent-bridge-B5rxWrg3.d.ts} +1 -1
- package/dist/{agent-subagent-runner-DfvlBx5N.d.ts → agent-subagent-runner-Zc3f37Sg.d.ts} +3 -3
- package/dist/{compactor-D1RHFRmF.d.ts → compactor-0vjZ8KTk.d.ts} +1 -1
- package/dist/{config-ZRCf7sTu.d.ts → config-BdDuaZmB.d.ts} +143 -2
- package/dist/{context-7u93AcGD.d.ts → context-iFMEO2rN.d.ts} +9 -8
- package/dist/coordination/index.d.ts +12 -12
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +22 -22
- package/dist/defaults/index.js +285 -108
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-Bt44ikPN.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-BeRsj7YX.d.ts → goal-store-iHltMi5n.d.ts} +1 -1
- package/dist/{index-mAWBdLyJ.d.ts → index-Bc6BiP5q.d.ts} +77 -6
- package/dist/{index-OzA1XjHL.d.ts → index-CWdW_CJt.d.ts} +10 -8
- package/dist/index.d.ts +58 -34
- package/dist/index.js +587 -100
- 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-DONdo-XM.d.ts → mcp-servers-CwqQDMYy.d.ts} +3 -3
- package/dist/models/index.d.ts +3 -3
- package/dist/models/index.js +31 -16
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-gwMAo6E3.d.ts → models-registry-Cuq1C8V9.d.ts} +7 -0
- package/dist/{multi-agent-Ba9Ni2hC.d.ts → multi-agent-SASYOrWA.d.ts} +2 -2
- package/dist/{multi-agent-coordinator-BuKq0q89.d.ts → multi-agent-coordinator-CNUJYq7U.d.ts} +2 -2
- package/dist/{null-fleet-bus-C0xd73YP.d.ts → null-fleet-bus-DRoJ0uOY.d.ts} +7 -7
- package/dist/observability/index.d.ts +2 -2
- package/dist/{path-resolver-nkmdiFgi.d.ts → path-resolver-C5sPVne8.d.ts} +2 -2
- package/dist/{permission-B6sldrSp.d.ts → permission-Ld-i5ugf.d.ts} +13 -1
- package/dist/{permission-policy-CtNscWOA.d.ts → permission-policy-CL-mPufp.d.ts} +14 -7
- package/dist/{plan-templates-BmDdJ7UL.d.ts → plan-templates-ThBHOjaM.d.ts} +4 -4
- package/dist/{provider-runner-BGro2qQB.d.ts → provider-runner-DJQa211J.d.ts} +3 -3
- package/dist/{retry-policy-KF18W4dg.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-DmXxpFyM.d.ts → selector-DxhW7ML3.d.ts} +1 -1
- package/dist/{session-reader-bfgsy2a0.d.ts → session-reader-q2ThszgG.d.ts} +1 -1
- package/dist/storage/index.d.ts +6 -6
- package/dist/storage/index.js +57 -37
- package/dist/storage/index.js.map +1 -1
- package/dist/{system-prompt-CM6zOhd2.d.ts → system-prompt-7LHyBbIf.d.ts} +32 -2
- package/dist/{tool-executor-p4tP9tGF.d.ts → tool-executor-CIjpGaRA.d.ts} +5 -4
- package/dist/types/index.d.ts +15 -15
- package/dist/types/index.js +93 -22
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +14 -2
- package/dist/utils/index.js +18 -1
- package/dist/utils/index.js.map +1 -1
- 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`");
|
|
@@ -14525,6 +14687,7 @@ function stripUndefined(obj) {
|
|
|
14525
14687
|
// src/models/models-registry.ts
|
|
14526
14688
|
var DEFAULT_URL = "https://models.dev/api.json";
|
|
14527
14689
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
14690
|
+
var DEFAULT_REFRESH_TIMEOUT_MS = 15e3;
|
|
14528
14691
|
var FAMILY_BY_NPM = {
|
|
14529
14692
|
"@ai-sdk/anthropic": "anthropic",
|
|
14530
14693
|
"@ai-sdk/google-vertex/anthropic": "anthropic",
|
|
@@ -14561,6 +14724,7 @@ var DefaultModelsRegistry = class {
|
|
|
14561
14724
|
fetchImpl;
|
|
14562
14725
|
seed;
|
|
14563
14726
|
maxStaleAgeMs;
|
|
14727
|
+
refreshTimeoutMs;
|
|
14564
14728
|
overlay;
|
|
14565
14729
|
overlayUrl;
|
|
14566
14730
|
overlayFile;
|
|
@@ -14573,10 +14737,11 @@ var DefaultModelsRegistry = class {
|
|
|
14573
14737
|
this.seed = opts.seed;
|
|
14574
14738
|
const maxStaleSeconds = opts.maxStaleAgeSeconds ?? 7 * 24 * 3600;
|
|
14575
14739
|
this.maxStaleAgeMs = maxStaleSeconds * 1e3;
|
|
14740
|
+
this.refreshTimeoutMs = opts.refreshTimeoutMs ?? DEFAULT_REFRESH_TIMEOUT_MS;
|
|
14576
14741
|
this.overlay = opts.overlay;
|
|
14577
14742
|
this.overlayUrl = opts.overlayUrl;
|
|
14578
14743
|
this.overlayFile = opts.overlayFile;
|
|
14579
|
-
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);
|
|
14580
14745
|
}
|
|
14581
14746
|
async load(opts = {}) {
|
|
14582
14747
|
if (this.payload && !opts.force) return this.payload;
|
|
@@ -14624,22 +14789,34 @@ var DefaultModelsRegistry = class {
|
|
|
14624
14789
|
}
|
|
14625
14790
|
/** Fetch + cache the models.dev base. Throws on failure (used by `refresh`). */
|
|
14626
14791
|
async refreshBase() {
|
|
14627
|
-
const
|
|
14628
|
-
|
|
14629
|
-
|
|
14630
|
-
|
|
14631
|
-
|
|
14632
|
-
|
|
14633
|
-
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14792
|
+
const controller = new AbortController();
|
|
14793
|
+
const timeout = setTimeout(() => controller.abort(), this.refreshTimeoutMs);
|
|
14794
|
+
try {
|
|
14795
|
+
const res = await this.fetchImpl(this.url, {
|
|
14796
|
+
method: "GET",
|
|
14797
|
+
headers: { accept: "application/json" },
|
|
14798
|
+
signal: controller.signal
|
|
14799
|
+
});
|
|
14800
|
+
clearTimeout(timeout);
|
|
14801
|
+
if (!res.ok) {
|
|
14802
|
+
throw new Error(`ModelsRegistry: HTTP ${res.status} fetching ${this.url}`);
|
|
14803
|
+
}
|
|
14804
|
+
const json = await res.json();
|
|
14805
|
+
this.fetchedAt = /* @__PURE__ */ new Date();
|
|
14806
|
+
const envelope = {
|
|
14807
|
+
fetchedAt: this.fetchedAt.toISOString(),
|
|
14808
|
+
url: this.url,
|
|
14809
|
+
payload: json
|
|
14810
|
+
};
|
|
14811
|
+
await atomicWrite(this.cacheFile, JSON.stringify(envelope));
|
|
14812
|
+
return json;
|
|
14813
|
+
} catch (err) {
|
|
14814
|
+
clearTimeout(timeout);
|
|
14815
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
14816
|
+
throw new Error(`ModelsRegistry: fetch timed out after ${this.refreshTimeoutMs}ms`);
|
|
14817
|
+
}
|
|
14818
|
+
throw err;
|
|
14819
|
+
}
|
|
14643
14820
|
}
|
|
14644
14821
|
/**
|
|
14645
14822
|
* Resolve the curated overlay, memoised. Order: in-memory `overlay` →
|
|
@@ -14777,7 +14954,7 @@ var DefaultModelsRegistry = class {
|
|
|
14777
14954
|
}
|
|
14778
14955
|
/** Used by `wstack models refresh` to expose where the cache lives. */
|
|
14779
14956
|
cacheLocation() {
|
|
14780
|
-
return
|
|
14957
|
+
return path16.resolve(this.cacheFile);
|
|
14781
14958
|
}
|
|
14782
14959
|
};
|
|
14783
14960
|
function hasEntries(payload) {
|
|
@@ -15064,7 +15241,7 @@ var DefaultModeStore = class {
|
|
|
15064
15241
|
}
|
|
15065
15242
|
async loadActiveMode() {
|
|
15066
15243
|
try {
|
|
15067
|
-
const configPath =
|
|
15244
|
+
const configPath = path16.join(this.configDir, "mode.json");
|
|
15068
15245
|
const content = await fsp.readFile(configPath, "utf8");
|
|
15069
15246
|
const data = JSON.parse(content);
|
|
15070
15247
|
this.activeModeId = data.activeMode ?? null;
|
|
@@ -15075,7 +15252,7 @@ var DefaultModeStore = class {
|
|
|
15075
15252
|
async saveActiveMode() {
|
|
15076
15253
|
try {
|
|
15077
15254
|
await fsp.mkdir(this.configDir, { recursive: true });
|
|
15078
|
-
const configPath =
|
|
15255
|
+
const configPath = path16.join(this.configDir, "mode.json");
|
|
15079
15256
|
await atomicWrite(
|
|
15080
15257
|
configPath,
|
|
15081
15258
|
JSON.stringify({ activeMode: this.activeModeId }, null, 2)
|
|
@@ -15090,11 +15267,11 @@ async function loadProjectModes(modesDir) {
|
|
|
15090
15267
|
const entries = await fsp.readdir(modesDir);
|
|
15091
15268
|
for (const entry of entries) {
|
|
15092
15269
|
if (!entry.endsWith(".md") && !entry.endsWith(".txt")) continue;
|
|
15093
|
-
const filePath =
|
|
15270
|
+
const filePath = path16.join(modesDir, entry);
|
|
15094
15271
|
const stat5 = await fsp.stat(filePath);
|
|
15095
15272
|
if (!stat5.isFile()) continue;
|
|
15096
15273
|
const content = await fsp.readFile(filePath, "utf8");
|
|
15097
|
-
const id =
|
|
15274
|
+
const id = path16.basename(entry, path16.extname(entry));
|
|
15098
15275
|
modes.push({
|
|
15099
15276
|
id,
|
|
15100
15277
|
name: id.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
@@ -15110,7 +15287,7 @@ async function loadProjectModes(modesDir) {
|
|
|
15110
15287
|
async function loadUserModes(modesDir) {
|
|
15111
15288
|
const modes = [];
|
|
15112
15289
|
try {
|
|
15113
|
-
const manifestPath =
|
|
15290
|
+
const manifestPath = path16.join(modesDir, "modes.json");
|
|
15114
15291
|
const content = await fsp.readFile(manifestPath, "utf8");
|
|
15115
15292
|
const manifest = JSON.parse(content);
|
|
15116
15293
|
for (const mode of manifest.modes) {
|
|
@@ -16027,7 +16204,7 @@ var SpecStore = class {
|
|
|
16027
16204
|
indexPath;
|
|
16028
16205
|
constructor(opts) {
|
|
16029
16206
|
this.baseDir = opts.baseDir;
|
|
16030
|
-
this.indexPath =
|
|
16207
|
+
this.indexPath = path16.join(this.baseDir, "_index.json");
|
|
16031
16208
|
}
|
|
16032
16209
|
async save(spec) {
|
|
16033
16210
|
await ensureDir(this.baseDir);
|
|
@@ -16096,7 +16273,7 @@ var SpecStore = class {
|
|
|
16096
16273
|
return updated;
|
|
16097
16274
|
}
|
|
16098
16275
|
filePath(id) {
|
|
16099
|
-
return
|
|
16276
|
+
return path16.join(this.baseDir, `${id}.json`);
|
|
16100
16277
|
}
|
|
16101
16278
|
async readIndex() {
|
|
16102
16279
|
try {
|
|
@@ -16153,7 +16330,7 @@ var TaskGraphStore = class {
|
|
|
16153
16330
|
indexPath;
|
|
16154
16331
|
constructor(opts) {
|
|
16155
16332
|
this.baseDir = opts.baseDir;
|
|
16156
|
-
this.indexPath =
|
|
16333
|
+
this.indexPath = path16.join(this.baseDir, "_index.json");
|
|
16157
16334
|
}
|
|
16158
16335
|
async save(graph) {
|
|
16159
16336
|
await ensureDir(this.baseDir);
|
|
@@ -16191,7 +16368,7 @@ var TaskGraphStore = class {
|
|
|
16191
16368
|
}
|
|
16192
16369
|
}
|
|
16193
16370
|
filePath(id) {
|
|
16194
|
-
return
|
|
16371
|
+
return path16.join(this.baseDir, `${id}.json`);
|
|
16195
16372
|
}
|
|
16196
16373
|
async readIndex() {
|
|
16197
16374
|
try {
|
|
@@ -16436,9 +16613,9 @@ var AISpecBuilder = class {
|
|
|
16436
16613
|
if (!this.sessionPath) return;
|
|
16437
16614
|
try {
|
|
16438
16615
|
const fsp16 = await import('fs/promises');
|
|
16439
|
-
const
|
|
16616
|
+
const path19 = await import('path');
|
|
16440
16617
|
const { atomicWrite: atomicWrite2 } = await Promise.resolve().then(() => (init_atomic_write(), atomic_write_exports));
|
|
16441
|
-
await fsp16.mkdir(
|
|
16618
|
+
await fsp16.mkdir(path19.dirname(this.sessionPath), { recursive: true });
|
|
16442
16619
|
await atomicWrite2(this.sessionPath, JSON.stringify(this.session, null, 2));
|
|
16443
16620
|
} catch {
|
|
16444
16621
|
}
|
|
@@ -17148,15 +17325,15 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
|
|
|
17148
17325
|
maxId = id;
|
|
17149
17326
|
}
|
|
17150
17327
|
}
|
|
17151
|
-
const
|
|
17328
|
+
const path19 = [];
|
|
17152
17329
|
let current = maxId;
|
|
17153
17330
|
const visited = /* @__PURE__ */ new Set();
|
|
17154
17331
|
while (current && !visited.has(current)) {
|
|
17155
17332
|
visited.add(current);
|
|
17156
|
-
|
|
17333
|
+
path19.unshift(current);
|
|
17157
17334
|
current = prev.get(current) ?? null;
|
|
17158
17335
|
}
|
|
17159
|
-
return
|
|
17336
|
+
return path19;
|
|
17160
17337
|
}
|
|
17161
17338
|
function computeParallelGroups(graph, blockedByMap) {
|
|
17162
17339
|
const groups = [];
|
|
@@ -17706,7 +17883,7 @@ var SddParallelRun = class {
|
|
|
17706
17883
|
"\u2500\u2500 EXECUTION PROTOCOL \u2500\u2500",
|
|
17707
17884
|
"\u2022 Execute the assigned SDD task end-to-end using multiple tool calls.",
|
|
17708
17885
|
"\u2022 Mark the task [done] in the tracker when complete.",
|
|
17709
|
-
"\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.",
|
|
17710
17887
|
"\u2022 Keep output concise \u2014 summarize changes, do not transcribe files."
|
|
17711
17888
|
].join("\n");
|
|
17712
17889
|
const spawns = subagentIds.map(
|
|
@@ -17949,9 +18126,9 @@ var DefaultHealthRegistry = class {
|
|
|
17949
18126
|
}
|
|
17950
18127
|
async runOne(check) {
|
|
17951
18128
|
let timer = null;
|
|
17952
|
-
const timeout = new Promise((
|
|
18129
|
+
const timeout = new Promise((resolve5) => {
|
|
17953
18130
|
timer = setTimeout(
|
|
17954
|
-
() =>
|
|
18131
|
+
() => resolve5({ status: "unhealthy", detail: `timeout after ${this.timeoutMs}ms` }),
|
|
17955
18132
|
this.timeoutMs
|
|
17956
18133
|
);
|
|
17957
18134
|
});
|
|
@@ -18134,7 +18311,7 @@ async function startMetricsServer(opts) {
|
|
|
18134
18311
|
const tls = opts.tls;
|
|
18135
18312
|
const useHttps = !!(tls?.cert && tls?.key);
|
|
18136
18313
|
const host = opts.host ?? "127.0.0.1";
|
|
18137
|
-
const
|
|
18314
|
+
const path19 = opts.path ?? "/metrics";
|
|
18138
18315
|
const healthPath = opts.healthPath ?? "/healthz";
|
|
18139
18316
|
const healthRegistry = opts.healthRegistry;
|
|
18140
18317
|
const listener = (req, res) => {
|
|
@@ -18144,7 +18321,7 @@ async function startMetricsServer(opts) {
|
|
|
18144
18321
|
return;
|
|
18145
18322
|
}
|
|
18146
18323
|
const url = req.url.split("?")[0];
|
|
18147
|
-
if (url ===
|
|
18324
|
+
if (url === path19) {
|
|
18148
18325
|
let body;
|
|
18149
18326
|
try {
|
|
18150
18327
|
body = renderPrometheus(opts.sink.snapshot());
|
|
@@ -18190,14 +18367,14 @@ async function startMetricsServer(opts) {
|
|
|
18190
18367
|
const { createServer } = await import('http');
|
|
18191
18368
|
server = createServer(listener);
|
|
18192
18369
|
}
|
|
18193
|
-
await new Promise((
|
|
18370
|
+
await new Promise((resolve5, reject) => {
|
|
18194
18371
|
const onError = (err) => {
|
|
18195
18372
|
server.off("listening", onListening);
|
|
18196
18373
|
reject(err);
|
|
18197
18374
|
};
|
|
18198
18375
|
const onListening = () => {
|
|
18199
18376
|
server.off("error", onError);
|
|
18200
|
-
|
|
18377
|
+
resolve5();
|
|
18201
18378
|
};
|
|
18202
18379
|
server.once("error", onError);
|
|
18203
18380
|
server.once("listening", onListening);
|
|
@@ -18208,9 +18385,9 @@ async function startMetricsServer(opts) {
|
|
|
18208
18385
|
const protocol = useHttps ? "https" : "http";
|
|
18209
18386
|
return {
|
|
18210
18387
|
port: boundPort,
|
|
18211
|
-
url: `${protocol}://${host}:${boundPort}${
|
|
18212
|
-
close: () => new Promise((
|
|
18213
|
-
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());
|
|
18214
18391
|
})
|
|
18215
18392
|
};
|
|
18216
18393
|
}
|
|
@@ -18759,7 +18936,7 @@ var context7Server = () => ({
|
|
|
18759
18936
|
name: "context7",
|
|
18760
18937
|
description: "Codebase-aware documentation and Q&A (context7.ai)",
|
|
18761
18938
|
transport: "streamable-http",
|
|
18762
|
-
url: "https://
|
|
18939
|
+
url: "https://mcp.context7.com/mcp",
|
|
18763
18940
|
permission: "confirm"
|
|
18764
18941
|
});
|
|
18765
18942
|
var braveSearchServer = () => ({
|