@wrongstack/core 0.68.0 → 0.77.0
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-D-j6OOBT.d.ts → agent-bridge-EWdqs8v6.d.ts} +1 -1
- package/dist/{agent-subagent-runner-DRZ9-NnR.d.ts → agent-subagent-runner-D8qW8OSC.d.ts} +13 -5
- package/dist/{config--86aHSln.d.ts → config-Dy0CK_o6.d.ts} +44 -1
- package/dist/coordination/index.d.ts +10 -10
- package/dist/coordination/index.js +74 -10
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +17 -17
- package/dist/defaults/index.js +160 -67
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-CIplI98R.d.ts → events-CYaoLN5_.d.ts} +45 -0
- package/dist/execution/index.d.ts +9 -9
- package/dist/execution/index.js +4 -4
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +5 -5
- package/dist/{index-b5uhfTSl.d.ts → index-DIxjTOga.d.ts} +6 -6
- package/dist/{index-DKUvyTvV.d.ts → index-Dsda0uCn.d.ts} +4 -4
- package/dist/index.d.ts +108 -33
- package/dist/index.js +388 -58
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +5 -5
- package/dist/infrastructure/index.js +16 -2
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +7 -7
- package/dist/kernel/index.js.map +1 -1
- package/dist/{logger-bOzkF5LL.d.ts → logger-BppKxDqZ.d.ts} +9 -0
- package/dist/{mcp-servers-DwoNBf6r.d.ts → mcp-servers-T0O6UN_w.d.ts} +1 -1
- package/dist/{mode-CV077NjV.d.ts → mode-BO4SEUIv.d.ts} +7 -0
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.js +18 -9
- package/dist/models/index.js.map +1 -1
- package/dist/{multi-agent-coordinator-CWnH-CiX.d.ts → multi-agent-coordinator-DpbG3wiy.d.ts} +1 -1
- package/dist/{null-fleet-bus-CuN0ObJr.d.ts → null-fleet-bus-u5ys3lW_.d.ts} +28 -9
- package/dist/observability/index.d.ts +1 -1
- package/dist/{parallel-eternal-engine-0UwotoSx.d.ts → parallel-eternal-engine-Dn0P8Pbj.d.ts} +3 -3
- package/dist/{path-resolver-DVkEcIw8.d.ts → path-resolver-B32v2JIq.d.ts} +1 -1
- package/dist/{permission-C1A5whY5.d.ts → permission-V5BLOrY6.d.ts} +0 -4
- package/dist/{permission-policy-B2dK-T5N.d.ts → permission-policy-CBVx-d-8.d.ts} +1 -5
- package/dist/{plan-templates-Bprrzhbu.d.ts → plan-templates-BcUwLlMQ.d.ts} +8 -3
- package/dist/{provider-runner-mXvXGSIw.d.ts → provider-runner-CSi_7l0h.d.ts} +1 -1
- package/dist/sdd/index.d.ts +6 -6
- package/dist/sdd/index.js +3 -3
- package/dist/sdd/index.js.map +1 -1
- package/dist/security/index.d.ts +2 -2
- package/dist/security/index.js +0 -8
- package/dist/security/index.js.map +1 -1
- package/dist/skills/index.js +1 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/index.d.ts +4 -4
- package/dist/storage/index.js +48 -8
- package/dist/storage/index.js.map +1 -1
- package/dist/{system-prompt-b61lOd49.d.ts → system-prompt-CA11g6Jo.d.ts} +1 -1
- package/dist/types/index.d.ts +14 -14
- package/dist/types/index.js +35 -12
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +14 -3
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-eMXnY1_X.d.ts → wstack-paths-D7evAFWM.d.ts} +8 -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 path3 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 = path3.dirname(targetPath);
|
|
36
36
|
await fsp.mkdir(dir, { recursive: true });
|
|
37
|
-
const tmp =
|
|
37
|
+
const tmp = path3.join(dir, `.${path3.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" });
|
|
@@ -162,14 +162,16 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
162
162
|
file;
|
|
163
163
|
bindings;
|
|
164
164
|
pretty;
|
|
165
|
+
stderr;
|
|
165
166
|
constructor(opts = {}) {
|
|
166
167
|
this.level = opts.level ?? process.env.WRONGSTACK_LOG_LEVEL ?? "info";
|
|
167
168
|
this.file = opts.file;
|
|
168
169
|
this.bindings = opts.bindings ?? {};
|
|
169
170
|
this.pretty = opts.pretty ?? true;
|
|
171
|
+
this.stderr = opts.stderr !== false;
|
|
170
172
|
if (this.file) {
|
|
171
173
|
try {
|
|
172
|
-
fs5.mkdirSync(
|
|
174
|
+
fs5.mkdirSync(path3.dirname(this.file), { recursive: true });
|
|
173
175
|
} catch {
|
|
174
176
|
}
|
|
175
177
|
}
|
|
@@ -194,6 +196,7 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
194
196
|
level: this.level,
|
|
195
197
|
file: this.file,
|
|
196
198
|
pretty: this.pretty,
|
|
199
|
+
stderr: this.stderr,
|
|
197
200
|
bindings: { ...this.bindings, ...bindings }
|
|
198
201
|
});
|
|
199
202
|
}
|
|
@@ -213,6 +216,7 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
213
216
|
} catch {
|
|
214
217
|
}
|
|
215
218
|
}
|
|
219
|
+
if (!this.stderr) return;
|
|
216
220
|
if (r <= LEVEL_RANK.warn || this.level === "debug" || this.level === "trace") {
|
|
217
221
|
const head = `${color.dim(ts)} ${COLORS[level](level.toUpperCase().padEnd(5))} ${msg}`;
|
|
218
222
|
if (ctx !== void 0) {
|
|
@@ -331,6 +335,16 @@ function isEmptyMessage(msg) {
|
|
|
331
335
|
}
|
|
332
336
|
|
|
333
337
|
// src/storage/session-store.ts
|
|
338
|
+
function sanitizeModel(model) {
|
|
339
|
+
return model.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
340
|
+
}
|
|
341
|
+
function generateSessionId(startedAt, model) {
|
|
342
|
+
const date = startedAt.slice(0, 10);
|
|
343
|
+
const time = startedAt.slice(11, 19).replace(/:/g, "-");
|
|
344
|
+
const suffix = randomBytes(2).toString("hex");
|
|
345
|
+
const modelPart = model ? `_${sanitizeModel(model)}` : "";
|
|
346
|
+
return `${date}/${time}Z${modelPart}_${suffix}`;
|
|
347
|
+
}
|
|
334
348
|
var DefaultSessionStore = class {
|
|
335
349
|
dir;
|
|
336
350
|
events;
|
|
@@ -342,17 +356,23 @@ var DefaultSessionStore = class {
|
|
|
342
356
|
}
|
|
343
357
|
/** Join session ID to its absolute path within the store directory. */
|
|
344
358
|
sessionPath(id, ext) {
|
|
345
|
-
return
|
|
359
|
+
return path3.join(this.dir, `${id}${ext}`);
|
|
346
360
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
361
|
+
/**
|
|
362
|
+
* Ensure the directory implied by the session ID exists. When the ID
|
|
363
|
+
* contains a date prefix like `2026-06-06/...`, this creates the date
|
|
364
|
+
* subdirectory so sessions group naturally by day.
|
|
365
|
+
*/
|
|
366
|
+
async ensureShardDir(id) {
|
|
367
|
+
const dirPath = path3.dirname(path3.join(this.dir, id));
|
|
368
|
+
await ensureDir(dirPath);
|
|
369
|
+
return dirPath;
|
|
350
370
|
}
|
|
351
371
|
async create(meta) {
|
|
352
372
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
353
|
-
const id = meta.id
|
|
373
|
+
const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt, meta.model ?? meta.provider);
|
|
354
374
|
const shardDir = await this.ensureShardDir(id);
|
|
355
|
-
const file =
|
|
375
|
+
const file = path3.join(shardDir, `${path3.basename(id)}.jsonl`);
|
|
356
376
|
let handle;
|
|
357
377
|
try {
|
|
358
378
|
handle = await fsp.open(file, "a", 384);
|
|
@@ -445,7 +465,7 @@ var DefaultSessionStore = class {
|
|
|
445
465
|
const ids = [];
|
|
446
466
|
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
447
467
|
for (const entry of entries) {
|
|
448
|
-
const full =
|
|
468
|
+
const full = path3.join(dir, entry.name);
|
|
449
469
|
if (entry.isDirectory()) {
|
|
450
470
|
ids.push(...await this.collectSessionIds(full));
|
|
451
471
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -601,7 +621,7 @@ var FileSessionWriter = class {
|
|
|
601
621
|
this.meta = meta;
|
|
602
622
|
this.events = events;
|
|
603
623
|
this.resumed = opts.resumed ?? false;
|
|
604
|
-
this.manifestFile = opts.dir ?
|
|
624
|
+
this.manifestFile = opts.dir ? path3.join(opts.dir, `${id}.summary.json`) : "";
|
|
605
625
|
this.filePath = opts.filePath ?? "";
|
|
606
626
|
this.secretScrubber = opts.secretScrubber;
|
|
607
627
|
this.summary = {
|
|
@@ -883,7 +903,7 @@ init_atomic_write();
|
|
|
883
903
|
var QueueStore = class {
|
|
884
904
|
file;
|
|
885
905
|
constructor(opts) {
|
|
886
|
-
this.file =
|
|
906
|
+
this.file = path3.join(opts.dir, "queue.json");
|
|
887
907
|
}
|
|
888
908
|
async write(items) {
|
|
889
909
|
if (items.length === 0) {
|
|
@@ -953,7 +973,7 @@ var DefaultAttachmentStore = class {
|
|
|
953
973
|
let data = input.data;
|
|
954
974
|
if (this.spoolDir && bytes >= this.spoolThreshold) {
|
|
955
975
|
await fsp.mkdir(this.spoolDir, { recursive: true });
|
|
956
|
-
spooledPath =
|
|
976
|
+
spooledPath = path3.join(this.spoolDir, `${id}.bin`);
|
|
957
977
|
await atomicWrite(spooledPath, input.data, {
|
|
958
978
|
encoding: input.kind === "image" ? "base64" : "utf8"
|
|
959
979
|
});
|
|
@@ -1141,7 +1161,7 @@ ${body.trim()}`);
|
|
|
1141
1161
|
async remember(text, scope = "project-memory") {
|
|
1142
1162
|
return this.runSerialized(scope, async () => {
|
|
1143
1163
|
const file = this.files[scope];
|
|
1144
|
-
await ensureDir(
|
|
1164
|
+
await ensureDir(path3.dirname(file));
|
|
1145
1165
|
let existing = "";
|
|
1146
1166
|
try {
|
|
1147
1167
|
existing = await fsp.readFile(file, "utf8");
|
|
@@ -1479,8 +1499,17 @@ var BEHAVIOR_DEFAULTS = {
|
|
|
1479
1499
|
modelsRegistry: true,
|
|
1480
1500
|
skills: true
|
|
1481
1501
|
},
|
|
1502
|
+
indexing: {
|
|
1503
|
+
onSessionStart: true,
|
|
1504
|
+
onEdit: true,
|
|
1505
|
+
watchExternal: true,
|
|
1506
|
+
debounceMs: 400
|
|
1507
|
+
},
|
|
1482
1508
|
session: { ...DEFAULT_SESSION_LOGGING_CONFIG }
|
|
1483
1509
|
};
|
|
1510
|
+
function envBool(v) {
|
|
1511
|
+
return !/^(0|false|no|off)$/i.test(v.trim());
|
|
1512
|
+
}
|
|
1484
1513
|
var ENV_MAP = {
|
|
1485
1514
|
WRONGSTACK_PROVIDER: (c, v) => {
|
|
1486
1515
|
c.provider = v;
|
|
@@ -1505,8 +1534,23 @@ var ENV_MAP = {
|
|
|
1505
1534
|
WRONGSTACK_LOG_LEVEL: (c, v) => {
|
|
1506
1535
|
if (!c.log) c.log = { level: "info" };
|
|
1507
1536
|
c.log.level = v;
|
|
1537
|
+
},
|
|
1538
|
+
WRONGSTACK_INDEX_ON_START: (c, v) => {
|
|
1539
|
+
c.indexing = { ...defaultIndexing, ...c.indexing, onSessionStart: envBool(v) };
|
|
1540
|
+
},
|
|
1541
|
+
WRONGSTACK_INDEX_ON_EDIT: (c, v) => {
|
|
1542
|
+
c.indexing = { ...defaultIndexing, ...c.indexing, onEdit: envBool(v) };
|
|
1543
|
+
},
|
|
1544
|
+
WRONGSTACK_INDEX_WATCH: (c, v) => {
|
|
1545
|
+
c.indexing = { ...defaultIndexing, ...c.indexing, watchExternal: envBool(v) };
|
|
1508
1546
|
}
|
|
1509
1547
|
};
|
|
1548
|
+
var defaultIndexing = {
|
|
1549
|
+
onSessionStart: true,
|
|
1550
|
+
onEdit: true,
|
|
1551
|
+
watchExternal: true,
|
|
1552
|
+
debounceMs: 400
|
|
1553
|
+
};
|
|
1510
1554
|
function isPrimitiveArray(a) {
|
|
1511
1555
|
return a.every((v) => v === null || typeof v !== "object");
|
|
1512
1556
|
}
|
|
@@ -1765,7 +1809,7 @@ var RecoveryLock = class {
|
|
|
1765
1809
|
sessionStore;
|
|
1766
1810
|
probe;
|
|
1767
1811
|
constructor(opts) {
|
|
1768
|
-
this.file =
|
|
1812
|
+
this.file = path3.join(opts.dir, LOCK_FILE);
|
|
1769
1813
|
this.pid = opts.pid ?? process.pid;
|
|
1770
1814
|
this.hostname = opts.hostname ?? os.hostname();
|
|
1771
1815
|
this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
@@ -1823,7 +1867,7 @@ var RecoveryLock = class {
|
|
|
1823
1867
|
* null return before calling this.
|
|
1824
1868
|
*/
|
|
1825
1869
|
async write(sessionId) {
|
|
1826
|
-
await ensureDir(
|
|
1870
|
+
await ensureDir(path3.dirname(this.file));
|
|
1827
1871
|
const lock = {
|
|
1828
1872
|
v: 1,
|
|
1829
1873
|
sessionId,
|
|
@@ -2407,7 +2451,7 @@ async function loadTodosCheckpoint(filePath) {
|
|
|
2407
2451
|
const parsed = JSON.parse(raw);
|
|
2408
2452
|
if (parsed?.version !== 1 || !Array.isArray(parsed.todos)) return null;
|
|
2409
2453
|
return parsed.todos.filter(
|
|
2410
|
-
(t) => !!t && typeof t.id === "string" && typeof t.content === "string" && typeof t.status === "string"
|
|
2454
|
+
(t) => !!t && typeof t.id === "string" && typeof t.content === "string" && typeof t.status === "string" && (t.activeForm === void 0 || typeof t.activeForm === "string")
|
|
2411
2455
|
);
|
|
2412
2456
|
} catch {
|
|
2413
2457
|
return null;
|
|
@@ -3050,7 +3094,7 @@ var DefaultSecretVault = class {
|
|
|
3050
3094
|
} catch (err) {
|
|
3051
3095
|
if (err.code !== "ENOENT") throw err;
|
|
3052
3096
|
}
|
|
3053
|
-
fs5.mkdirSync(
|
|
3097
|
+
fs5.mkdirSync(path3.dirname(this.keyFile), { recursive: true });
|
|
3054
3098
|
const key = randomBytes(KEY_BYTES);
|
|
3055
3099
|
try {
|
|
3056
3100
|
fs5.writeFileSync(this.keyFile, key, { mode: 384, flag: "wx" });
|
|
@@ -3119,7 +3163,7 @@ async function rewriteConfigEncrypted(configPath, vault, patch) {
|
|
|
3119
3163
|
}
|
|
3120
3164
|
const merged = deepMerge2(current, patch ?? {});
|
|
3121
3165
|
const encrypted = encryptConfigSecrets(merged, vault);
|
|
3122
|
-
await fsp.mkdir(
|
|
3166
|
+
await fsp.mkdir(path3.dirname(configPath), { recursive: true });
|
|
3123
3167
|
await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
3124
3168
|
await restrictFilePermissions(configPath);
|
|
3125
3169
|
}
|
|
@@ -3343,9 +3387,9 @@ function getInputString(input, key) {
|
|
|
3343
3387
|
function pathLooksInsideProject(rawPath, projectRoot) {
|
|
3344
3388
|
if (!projectRoot) return false;
|
|
3345
3389
|
if (rawPath === "~" || rawPath.startsWith("~/") || rawPath.startsWith("~\\")) return false;
|
|
3346
|
-
const resolved =
|
|
3347
|
-
const relative2 =
|
|
3348
|
-
return !!relative2 && !relative2.startsWith("..") && !
|
|
3390
|
+
const resolved = path3.resolve(projectRoot, rawPath);
|
|
3391
|
+
const relative2 = path3.relative(projectRoot, resolved);
|
|
3392
|
+
return !!relative2 && !relative2.startsWith("..") && !path3.isAbsolute(relative2);
|
|
3349
3393
|
}
|
|
3350
3394
|
function tokenizeShell(command) {
|
|
3351
3395
|
return command.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token) => token.replace(/^['"]|['"]$/g, "")) ?? [];
|
|
@@ -3355,7 +3399,7 @@ function pathTokenIsOutsideProject(token, projectRoot) {
|
|
|
3355
3399
|
if (token === "/" || token === "~" || token === "." || token === "..") return token !== ".";
|
|
3356
3400
|
if (token.includes("*")) return true;
|
|
3357
3401
|
if (token.startsWith("..") || token.includes("../") || token.includes("..\\")) return true;
|
|
3358
|
-
if (
|
|
3402
|
+
if (path3.isAbsolute(token) || token.startsWith("~/")) return !pathLooksInsideProject(token, projectRoot);
|
|
3359
3403
|
return false;
|
|
3360
3404
|
}
|
|
3361
3405
|
function hasDangerousDeleteTarget(tokens, start, projectRoot) {
|
|
@@ -3481,14 +3525,6 @@ var DefaultPermissionPolicy = class {
|
|
|
3481
3525
|
getConfirmDestructive() {
|
|
3482
3526
|
return this.confirmDestructive;
|
|
3483
3527
|
}
|
|
3484
|
-
/** @deprecated Use `setYoloDestructive`. */
|
|
3485
|
-
setForceAllYolo(enabled) {
|
|
3486
|
-
this.setYoloDestructive(enabled);
|
|
3487
|
-
}
|
|
3488
|
-
/** @deprecated Use `getYoloDestructive`. */
|
|
3489
|
-
getForceAllYolo() {
|
|
3490
|
-
return this.getYoloDestructive();
|
|
3491
|
-
}
|
|
3492
3528
|
async reload() {
|
|
3493
3529
|
try {
|
|
3494
3530
|
const raw = await fsp.readFile(this.trustFile, "utf8");
|
|
@@ -4019,7 +4055,7 @@ var DefaultSkillLoader = class {
|
|
|
4019
4055
|
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
4020
4056
|
for (const e of entries) {
|
|
4021
4057
|
if (!e.isDirectory()) continue;
|
|
4022
|
-
const skillFile =
|
|
4058
|
+
const skillFile = path3.join(dir, e.name, "SKILL.md");
|
|
4023
4059
|
try {
|
|
4024
4060
|
const raw = await fsp.readFile(skillFile, "utf8");
|
|
4025
4061
|
const meta = parseFrontmatter(raw);
|
|
@@ -5832,7 +5868,7 @@ ${errorDetails}`,
|
|
|
5832
5868
|
const decision = await this.opts.permissionPolicy.evaluate(tool, use.input, ctx);
|
|
5833
5869
|
let effectivePermission = decision.permission;
|
|
5834
5870
|
const policy = this.opts.permissionPolicy;
|
|
5835
|
-
const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true
|
|
5871
|
+
const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true;
|
|
5836
5872
|
if (toolDangerousCaps.length > 0 && effectivePermission === "auto" && !yolo) {
|
|
5837
5873
|
effectivePermission = "confirm";
|
|
5838
5874
|
}
|
|
@@ -6311,8 +6347,8 @@ var AutonomousRunner = class {
|
|
|
6311
6347
|
init_atomic_write();
|
|
6312
6348
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
6313
6349
|
function goalFilePath(projectRoot) {
|
|
6314
|
-
const hash = createHash("sha256").update(
|
|
6315
|
-
return
|
|
6350
|
+
const hash = createHash("sha256").update(path3.resolve(projectRoot)).digest("hex").slice(0, 12);
|
|
6351
|
+
return path3.join(os.homedir(), ".wrongstack", "projects", hash, "goal.json");
|
|
6316
6352
|
}
|
|
6317
6353
|
async function loadGoal(filePath) {
|
|
6318
6354
|
let raw;
|
|
@@ -10312,7 +10348,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
10312
10348
|
}
|
|
10313
10349
|
async spawn(subagent) {
|
|
10314
10350
|
const id = subagent.id || randomUUID();
|
|
10315
|
-
|
|
10351
|
+
const cfg = this.withNickname(subagent, id);
|
|
10316
10352
|
if (this.subagents.has(id)) {
|
|
10317
10353
|
throw new Error(`Subagent id "${id}" already exists \u2014 refusing to overwrite`);
|
|
10318
10354
|
}
|
|
@@ -10327,12 +10363,12 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
10327
10363
|
maxConcurrent: this.config.maxConcurrent ?? 16
|
|
10328
10364
|
};
|
|
10329
10365
|
this.subagents.set(id, {
|
|
10330
|
-
config: { ...
|
|
10366
|
+
config: { ...cfg, id },
|
|
10331
10367
|
context,
|
|
10332
10368
|
status: "idle",
|
|
10333
10369
|
abortController: new AbortController()
|
|
10334
10370
|
});
|
|
10335
|
-
this.emit("subagent.started", { subagent: { ...
|
|
10371
|
+
this.emit("subagent.started", { subagent: { ...cfg, id } });
|
|
10336
10372
|
this.fleetBus?.emit({
|
|
10337
10373
|
subagentId: id,
|
|
10338
10374
|
ts: Date.now(),
|
|
@@ -11562,7 +11598,8 @@ function isGlob(p) {
|
|
|
11562
11598
|
return false;
|
|
11563
11599
|
}
|
|
11564
11600
|
function globToRegex(pat) {
|
|
11565
|
-
let i = 0
|
|
11601
|
+
let i = 0;
|
|
11602
|
+
let re = "^";
|
|
11566
11603
|
while (i < pat.length) {
|
|
11567
11604
|
const c = pat[i];
|
|
11568
11605
|
if (c === "*") {
|
|
@@ -12281,6 +12318,10 @@ A scratchpad shared with the rest of the fleet is mounted at \`${parts.sharedScr
|
|
|
12281
12318
|
- Use stable filenames (one file per concern); overwrite instead of appending so the Director sees the latest state.`
|
|
12282
12319
|
);
|
|
12283
12320
|
}
|
|
12321
|
+
if (parts.skills && parts.skills.trim().length > 0) {
|
|
12322
|
+
sections.push(`Domain knowledge:
|
|
12323
|
+
${parts.skills.trim()}`);
|
|
12324
|
+
}
|
|
12284
12325
|
if (parts.override && parts.override.trim().length > 0) {
|
|
12285
12326
|
sections.push(parts.override.trim());
|
|
12286
12327
|
}
|
|
@@ -13821,7 +13862,7 @@ var Director = class _Director {
|
|
|
13821
13862
|
})),
|
|
13822
13863
|
usage: this.usage.snapshot()
|
|
13823
13864
|
};
|
|
13824
|
-
await fsp.mkdir(
|
|
13865
|
+
await fsp.mkdir(path3.dirname(this.manifestPath), { recursive: true });
|
|
13825
13866
|
await atomicWrite(this.manifestPath, JSON.stringify(manifest, null, 2), { mode: 384 });
|
|
13826
13867
|
return this.manifestPath;
|
|
13827
13868
|
}
|
|
@@ -14027,7 +14068,7 @@ var Director = class _Director {
|
|
|
14027
14068
|
*/
|
|
14028
14069
|
async readSession(subagentId, tail) {
|
|
14029
14070
|
if (!this.sessionsRoot) return null;
|
|
14030
|
-
const filePath =
|
|
14071
|
+
const filePath = path3.join(this.sessionsRoot, this.directorRunId, `${subagentId}.jsonl`);
|
|
14031
14072
|
let raw;
|
|
14032
14073
|
try {
|
|
14033
14074
|
raw = await fsp.readFile(filePath, "utf8");
|
|
@@ -14113,6 +14154,7 @@ var Director = class _Director {
|
|
|
14113
14154
|
role: config.prompt,
|
|
14114
14155
|
task: taskBrief,
|
|
14115
14156
|
sharedScratchpad: this.sharedScratchpadPath ?? void 0,
|
|
14157
|
+
skills: config.skillContent,
|
|
14116
14158
|
override: config.systemPromptOverride
|
|
14117
14159
|
});
|
|
14118
14160
|
}
|
|
@@ -14262,6 +14304,7 @@ function createDelegateTool(opts) {
|
|
|
14262
14304
|
if (typeof i.task !== "string" || !i.task.trim()) {
|
|
14263
14305
|
return { ok: false, error: "`task` is required." };
|
|
14264
14306
|
}
|
|
14307
|
+
const target = i.role ?? i.name ?? "subagent";
|
|
14265
14308
|
try {
|
|
14266
14309
|
let director = await opts.host.ensureDirector();
|
|
14267
14310
|
if (!director) {
|
|
@@ -14322,6 +14365,7 @@ function createDelegateTool(opts) {
|
|
|
14322
14365
|
if (!cfg.timeoutMs) {
|
|
14323
14366
|
cfg.timeoutMs = Math.max(3e4, timeoutMs - SUBAGENT_TIMEOUT_BUFFER_MS);
|
|
14324
14367
|
}
|
|
14368
|
+
opts.events?.emit("delegate.started", { target, task: i.task });
|
|
14325
14369
|
const subagentId = await director.spawn(cfg);
|
|
14326
14370
|
const taskId = await director.assign({
|
|
14327
14371
|
id: `${randomUUID()}`,
|
|
@@ -14356,6 +14400,17 @@ function createDelegateTool(opts) {
|
|
|
14356
14400
|
});
|
|
14357
14401
|
if ("__timeout" in result) {
|
|
14358
14402
|
const partial2 = await readSubagentPartial(opts, subagentId);
|
|
14403
|
+
opts.events?.emit("delegate.completed", {
|
|
14404
|
+
target,
|
|
14405
|
+
task: i.task,
|
|
14406
|
+
ok: false,
|
|
14407
|
+
status: "host_timeout",
|
|
14408
|
+
summary: `[${target}] timed out \u2014 no result within ${Math.round(timeoutMs / 1e3)}s`,
|
|
14409
|
+
durationMs: timeoutMs,
|
|
14410
|
+
iterations: partial2?.events ?? 0,
|
|
14411
|
+
toolCalls: partial2?.toolUsesObserved ?? 0,
|
|
14412
|
+
subagentId
|
|
14413
|
+
});
|
|
14359
14414
|
return {
|
|
14360
14415
|
ok: false,
|
|
14361
14416
|
stopReason: "host_timeout",
|
|
@@ -14372,6 +14427,24 @@ function createDelegateTool(opts) {
|
|
|
14372
14427
|
const retryable = result.error?.retryable;
|
|
14373
14428
|
const backoffMs = result.error?.backoffMs;
|
|
14374
14429
|
const summary = buildDelegateSummary(i.role, result);
|
|
14430
|
+
let costUsd;
|
|
14431
|
+
try {
|
|
14432
|
+
costUsd = dir.snapshot().perSubagent[result.subagentId]?.cost;
|
|
14433
|
+
} catch {
|
|
14434
|
+
costUsd = void 0;
|
|
14435
|
+
}
|
|
14436
|
+
opts.events?.emit("delegate.completed", {
|
|
14437
|
+
target,
|
|
14438
|
+
task: i.task,
|
|
14439
|
+
ok: result.status === "success",
|
|
14440
|
+
status: result.status,
|
|
14441
|
+
summary,
|
|
14442
|
+
durationMs: result.durationMs,
|
|
14443
|
+
iterations: result.iterations,
|
|
14444
|
+
toolCalls: result.toolCalls,
|
|
14445
|
+
costUsd,
|
|
14446
|
+
subagentId: result.subagentId
|
|
14447
|
+
});
|
|
14375
14448
|
return {
|
|
14376
14449
|
ok: result.status === "success",
|
|
14377
14450
|
status: result.status,
|
|
@@ -14393,10 +14466,21 @@ function createDelegateTool(opts) {
|
|
|
14393
14466
|
summary
|
|
14394
14467
|
};
|
|
14395
14468
|
} catch (err) {
|
|
14469
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14470
|
+
opts.events?.emit("delegate.completed", {
|
|
14471
|
+
target,
|
|
14472
|
+
task: i.task,
|
|
14473
|
+
ok: false,
|
|
14474
|
+
status: "error",
|
|
14475
|
+
summary: `[${target}] failed \u2014 ${message}`,
|
|
14476
|
+
durationMs: 0,
|
|
14477
|
+
iterations: 0,
|
|
14478
|
+
toolCalls: 0
|
|
14479
|
+
});
|
|
14396
14480
|
return {
|
|
14397
14481
|
ok: false,
|
|
14398
14482
|
stopReason: "error",
|
|
14399
|
-
error:
|
|
14483
|
+
error: message
|
|
14400
14484
|
};
|
|
14401
14485
|
}
|
|
14402
14486
|
}
|
|
@@ -14483,13 +14567,13 @@ async function readSubagentPartial(opts, subagentId) {
|
|
|
14483
14567
|
if (!opts.sessionsRoot) return void 0;
|
|
14484
14568
|
const candidates = [];
|
|
14485
14569
|
if (opts.directorRunId) {
|
|
14486
|
-
candidates.push(
|
|
14570
|
+
candidates.push(path3.join(opts.sessionsRoot, opts.directorRunId, `${subagentId}.jsonl`));
|
|
14487
14571
|
} else {
|
|
14488
14572
|
try {
|
|
14489
14573
|
const entries = await fsp.readdir(opts.sessionsRoot, { withFileTypes: true });
|
|
14490
14574
|
for (const entry of entries) {
|
|
14491
14575
|
if (entry.isDirectory()) {
|
|
14492
|
-
candidates.push(
|
|
14576
|
+
candidates.push(path3.join(opts.sessionsRoot, entry.name, `${subagentId}.jsonl`));
|
|
14493
14577
|
}
|
|
14494
14578
|
}
|
|
14495
14579
|
} catch {
|
|
@@ -14536,9 +14620,9 @@ function makeDirectorSessionFactory(opts) {
|
|
|
14536
14620
|
let dir;
|
|
14537
14621
|
if (opts.store) {
|
|
14538
14622
|
store = opts.store;
|
|
14539
|
-
dir = opts.sessionsRoot ?
|
|
14623
|
+
dir = opts.sessionsRoot ? path3.join(opts.sessionsRoot, runId) : "(caller-managed)";
|
|
14540
14624
|
} else if (opts.sessionsRoot) {
|
|
14541
|
-
dir =
|
|
14625
|
+
dir = path3.join(opts.sessionsRoot, runId);
|
|
14542
14626
|
store = new DefaultSessionStore({ dir });
|
|
14543
14627
|
} else {
|
|
14544
14628
|
throw new Error("makeDirectorSessionFactory requires either `store` or `sessionsRoot`");
|
|
@@ -14742,7 +14826,7 @@ var DefaultModelsRegistry = class {
|
|
|
14742
14826
|
this.overlay = opts.overlay;
|
|
14743
14827
|
this.overlayUrl = opts.overlayUrl;
|
|
14744
14828
|
this.overlayFile = opts.overlayFile;
|
|
14745
|
-
this.overlayCacheFile = opts.overlayCacheFile ?? (opts.overlayUrl ?
|
|
14829
|
+
this.overlayCacheFile = opts.overlayCacheFile ?? (opts.overlayUrl ? path3.join(path3.dirname(opts.cacheFile), "models-overlay-cache.json") : void 0);
|
|
14746
14830
|
}
|
|
14747
14831
|
async load(opts = {}) {
|
|
14748
14832
|
if (this.payload && !opts.force) return this.payload;
|
|
@@ -14955,7 +15039,7 @@ var DefaultModelsRegistry = class {
|
|
|
14955
15039
|
}
|
|
14956
15040
|
/** Used by `wstack models refresh` to expose where the cache lives. */
|
|
14957
15041
|
cacheLocation() {
|
|
14958
|
-
return
|
|
15042
|
+
return path3.resolve(this.cacheFile);
|
|
14959
15043
|
}
|
|
14960
15044
|
};
|
|
14961
15045
|
function hasEntries(payload) {
|
|
@@ -14989,7 +15073,8 @@ When reviewing code:
|
|
|
14989
15073
|
- Verify test coverage for critical paths
|
|
14990
15074
|
- Ensure naming conventions are followed`,
|
|
14991
15075
|
tags: ["review", "quality", "security"],
|
|
14992
|
-
toolPreferences: ["read", "grep", "git", "diff", "test"]
|
|
15076
|
+
toolPreferences: ["read", "grep", "git", "diff", "test"],
|
|
15077
|
+
suggestedSkills: ["bug-hunter", "security-scanner", "typescript-strict", "testing"]
|
|
14993
15078
|
},
|
|
14994
15079
|
{
|
|
14995
15080
|
id: "code-auditor",
|
|
@@ -15006,7 +15091,8 @@ When auditing code for security:
|
|
|
15006
15091
|
- Assess input validation and output encoding
|
|
15007
15092
|
- Look for timing attacks and information leakage`,
|
|
15008
15093
|
tags: ["security", "audit", "compliance"],
|
|
15009
|
-
toolPreferences: ["grep", "read", "audit", "bash"]
|
|
15094
|
+
toolPreferences: ["grep", "read", "audit", "bash"],
|
|
15095
|
+
suggestedSkills: ["security-scanner", "bug-hunter", "audit-log"]
|
|
15010
15096
|
},
|
|
15011
15097
|
{
|
|
15012
15098
|
id: "architect",
|
|
@@ -15024,7 +15110,8 @@ When designing or reviewing architecture:
|
|
|
15024
15110
|
- Assess API design and contract stability
|
|
15025
15111
|
- Consider operational aspects (monitoring, logging, deployment)`,
|
|
15026
15112
|
tags: ["architecture", "design", "scalability"],
|
|
15027
|
-
toolPreferences: ["read", "glob", "tree", "diff"]
|
|
15113
|
+
toolPreferences: ["read", "glob", "tree", "diff"],
|
|
15114
|
+
suggestedSkills: ["api-design", "refactor-planner", "node-modern", "docker-deploy"]
|
|
15028
15115
|
},
|
|
15029
15116
|
{
|
|
15030
15117
|
id: "debugger",
|
|
@@ -15042,7 +15129,8 @@ When investigating bugs:
|
|
|
15042
15129
|
- Use binary search to isolate the root cause
|
|
15043
15130
|
- Verify fixes with tests before considering done`,
|
|
15044
15131
|
tags: ["debug", "investigation", "error-resolution"],
|
|
15045
|
-
toolPreferences: ["read", "grep", "bash", "logs", "test"]
|
|
15132
|
+
toolPreferences: ["read", "grep", "bash", "logs", "test"],
|
|
15133
|
+
suggestedSkills: ["bug-hunter", "audit-log", "observability"]
|
|
15046
15134
|
},
|
|
15047
15135
|
{
|
|
15048
15136
|
id: "tester",
|
|
@@ -15060,7 +15148,8 @@ When testing or writing tests:
|
|
|
15060
15148
|
- Check for integration test gaps
|
|
15061
15149
|
- Verify test isolation and cleanup`,
|
|
15062
15150
|
tags: ["testing", "qa", "quality"],
|
|
15063
|
-
toolPreferences: ["read", "grep", "test", "bash"]
|
|
15151
|
+
toolPreferences: ["read", "grep", "test", "bash"],
|
|
15152
|
+
suggestedSkills: ["testing", "bug-hunter", "typescript-strict"]
|
|
15064
15153
|
},
|
|
15065
15154
|
{
|
|
15066
15155
|
id: "devops",
|
|
@@ -15078,7 +15167,8 @@ When working on infrastructure:
|
|
|
15078
15167
|
- Assess secrets management
|
|
15079
15168
|
- Check for resource limits and quotas`,
|
|
15080
15169
|
tags: ["devops", "infrastructure", "operations"],
|
|
15081
|
-
toolPreferences: ["read", "bash", "grep", "logs", "git"]
|
|
15170
|
+
toolPreferences: ["read", "bash", "grep", "logs", "git"],
|
|
15171
|
+
suggestedSkills: ["docker-deploy", "observability", "security-scanner"]
|
|
15082
15172
|
},
|
|
15083
15173
|
{
|
|
15084
15174
|
id: "refactorer",
|
|
@@ -15096,7 +15186,8 @@ When refactoring code:
|
|
|
15096
15186
|
- Don't mix formatting changes with logic changes
|
|
15097
15187
|
- Keep performance in mind \u2014 don't regress`,
|
|
15098
15188
|
tags: ["refactor", "modernization", "improvement"],
|
|
15099
|
-
toolPreferences: ["read", "edit", "test", "git", "grep"]
|
|
15189
|
+
toolPreferences: ["read", "edit", "test", "git", "grep"],
|
|
15190
|
+
suggestedSkills: ["refactor-planner", "typescript-strict", "node-modern", "testing"]
|
|
15100
15191
|
},
|
|
15101
15192
|
{
|
|
15102
15193
|
id: "brief",
|
|
@@ -15126,7 +15217,8 @@ Get to the point \u2014 read files, run commands, make changes.
|
|
|
15126
15217
|
- One-liner sufficient? One liner.
|
|
15127
15218
|
- Max 3 sentences per paragraph.`,
|
|
15128
15219
|
tags: ["fast", "concise", "direct"],
|
|
15129
|
-
toolPreferences: ["read", "edit", "bash"]
|
|
15220
|
+
toolPreferences: ["read", "edit", "bash"],
|
|
15221
|
+
suggestedSkills: []
|
|
15130
15222
|
},
|
|
15131
15223
|
{
|
|
15132
15224
|
id: "teach",
|
|
@@ -15191,7 +15283,8 @@ You follow these principles, but always with explanation:
|
|
|
15191
15283
|
|
|
15192
15284
|
Remember: your job is to make the user a better developer, not just to complete tasks faster.`,
|
|
15193
15285
|
tags: ["teaching", "mentor", "learning"],
|
|
15194
|
-
toolPreferences: ["read", "edit", "explain"]
|
|
15286
|
+
toolPreferences: ["read", "edit", "explain"],
|
|
15287
|
+
suggestedSkills: ["prompt-engineering", "skill-creator", "node-modern", "typescript-strict"]
|
|
15195
15288
|
}
|
|
15196
15289
|
];
|
|
15197
15290
|
|
|
@@ -15242,7 +15335,7 @@ var DefaultModeStore = class {
|
|
|
15242
15335
|
}
|
|
15243
15336
|
async loadActiveMode() {
|
|
15244
15337
|
try {
|
|
15245
|
-
const configPath =
|
|
15338
|
+
const configPath = path3.join(this.configDir, "mode.json");
|
|
15246
15339
|
const content = await fsp.readFile(configPath, "utf8");
|
|
15247
15340
|
const data = JSON.parse(content);
|
|
15248
15341
|
this.activeModeId = data.activeMode ?? null;
|
|
@@ -15253,7 +15346,7 @@ var DefaultModeStore = class {
|
|
|
15253
15346
|
async saveActiveMode() {
|
|
15254
15347
|
try {
|
|
15255
15348
|
await fsp.mkdir(this.configDir, { recursive: true });
|
|
15256
|
-
const configPath =
|
|
15349
|
+
const configPath = path3.join(this.configDir, "mode.json");
|
|
15257
15350
|
await atomicWrite(
|
|
15258
15351
|
configPath,
|
|
15259
15352
|
JSON.stringify({ activeMode: this.activeModeId }, null, 2)
|
|
@@ -15268,11 +15361,11 @@ async function loadProjectModes(modesDir) {
|
|
|
15268
15361
|
const entries = await fsp.readdir(modesDir);
|
|
15269
15362
|
for (const entry of entries) {
|
|
15270
15363
|
if (!entry.endsWith(".md") && !entry.endsWith(".txt")) continue;
|
|
15271
|
-
const filePath =
|
|
15364
|
+
const filePath = path3.join(modesDir, entry);
|
|
15272
15365
|
const stat5 = await fsp.stat(filePath);
|
|
15273
15366
|
if (!stat5.isFile()) continue;
|
|
15274
15367
|
const content = await fsp.readFile(filePath, "utf8");
|
|
15275
|
-
const id =
|
|
15368
|
+
const id = path3.basename(entry, path3.extname(entry));
|
|
15276
15369
|
modes.push({
|
|
15277
15370
|
id,
|
|
15278
15371
|
name: id.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
@@ -15288,7 +15381,7 @@ async function loadProjectModes(modesDir) {
|
|
|
15288
15381
|
async function loadUserModes(modesDir) {
|
|
15289
15382
|
const modes = [];
|
|
15290
15383
|
try {
|
|
15291
|
-
const manifestPath =
|
|
15384
|
+
const manifestPath = path3.join(modesDir, "modes.json");
|
|
15292
15385
|
const content = await fsp.readFile(manifestPath, "utf8");
|
|
15293
15386
|
const manifest = JSON.parse(content);
|
|
15294
15387
|
for (const mode of manifest.modes) {
|
|
@@ -16205,7 +16298,7 @@ var SpecStore = class {
|
|
|
16205
16298
|
indexPath;
|
|
16206
16299
|
constructor(opts) {
|
|
16207
16300
|
this.baseDir = opts.baseDir;
|
|
16208
|
-
this.indexPath =
|
|
16301
|
+
this.indexPath = path3.join(this.baseDir, "_index.json");
|
|
16209
16302
|
}
|
|
16210
16303
|
async save(spec) {
|
|
16211
16304
|
await ensureDir(this.baseDir);
|
|
@@ -16274,7 +16367,7 @@ var SpecStore = class {
|
|
|
16274
16367
|
return updated;
|
|
16275
16368
|
}
|
|
16276
16369
|
filePath(id) {
|
|
16277
|
-
return
|
|
16370
|
+
return path3.join(this.baseDir, `${id}.json`);
|
|
16278
16371
|
}
|
|
16279
16372
|
async readIndex() {
|
|
16280
16373
|
try {
|
|
@@ -16331,7 +16424,7 @@ var TaskGraphStore = class {
|
|
|
16331
16424
|
indexPath;
|
|
16332
16425
|
constructor(opts) {
|
|
16333
16426
|
this.baseDir = opts.baseDir;
|
|
16334
|
-
this.indexPath =
|
|
16427
|
+
this.indexPath = path3.join(this.baseDir, "_index.json");
|
|
16335
16428
|
}
|
|
16336
16429
|
async save(graph) {
|
|
16337
16430
|
await ensureDir(this.baseDir);
|
|
@@ -16369,7 +16462,7 @@ var TaskGraphStore = class {
|
|
|
16369
16462
|
}
|
|
16370
16463
|
}
|
|
16371
16464
|
filePath(id) {
|
|
16372
|
-
return
|
|
16465
|
+
return path3.join(this.baseDir, `${id}.json`);
|
|
16373
16466
|
}
|
|
16374
16467
|
async readIndex() {
|
|
16375
16468
|
try {
|