@wrongstack/core 0.109.1 → 0.141.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-mOxbpFcg.d.ts → agent-bridge-r9y6gdn4.d.ts} +1 -1
- package/dist/{agent-subagent-runner-DukQLUcS.d.ts → agent-subagent-runner-1GeQE_L0.d.ts} +7 -8
- package/dist/{brain-Dfv4Y82E.d.ts → brain-Cp_3GIS2.d.ts} +14 -3
- package/dist/{compactor-DXLxLcmU.d.ts → compactor-BueGt7LG.d.ts} +9 -1
- package/dist/{config-BSU-6vah.d.ts → config-BaVThgnT.d.ts} +104 -3
- package/dist/{context-CNRYfhUv.d.ts → context-C7G_MtLV.d.ts} +38 -1
- package/dist/coordination/index.d.ts +12 -13
- package/dist/coordination/index.js +229 -17
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +26 -27
- package/dist/defaults/index.js +886 -721
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +15 -16
- package/dist/execution/index.js +535 -322
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +6 -7
- package/dist/{goal-preamble-CI8lxeY1.d.ts → goal-preamble-iuIUTQwk.d.ts} +48 -18
- package/dist/{index-BWRN6wOb.d.ts → index-BZdezm3g.d.ts} +9 -10
- package/dist/{index-DIKEcfgC.d.ts → index-CPweVoFM.d.ts} +7 -6
- package/dist/index.d.ts +51 -52
- package/dist/index.js +752 -545
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -7
- package/dist/infrastructure/index.js +64 -19
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +10 -11
- package/dist/kernel/index.js.map +1 -1
- package/dist/llm-selector-CP72f1lC.d.ts +58 -0
- package/dist/{mcp-servers-CXCsANdY.d.ts → mcp-servers-Bl5LTvQg.d.ts} +3 -3
- package/dist/{mode-ARA3HrkY.d.ts → mode-CZlO9iU1.d.ts} +1 -1
- package/dist/models/index.d.ts +157 -53
- package/dist/models/index.js +475 -20
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-DU64QxQa.d.ts → models-registry-D90K9UnM.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-51LvnXkD.d.ts → multi-agent-coordinator-QWEzJDlm.d.ts} +1 -1
- package/dist/{null-fleet-bus-D09hMzFQ.d.ts → null-fleet-bus-BUyfqh23.d.ts} +13 -10
- package/dist/observability/index.d.ts +2 -2
- package/dist/{parallel-eternal-engine-B2CbsKpc.d.ts → parallel-eternal-engine-Dj2SYzha.d.ts} +24 -11
- package/dist/{path-resolver-DDJiMAtX.d.ts → path-resolver-DRjQBkoO.d.ts} +3 -3
- package/dist/{permission-BDv7z0mk.d.ts → permission-B7nKnEvQ.d.ts} +1 -1
- package/dist/{permission-policy-dF74EpDp.d.ts → permission-policy-8-6zBmfA.d.ts} +2 -13
- package/dist/{pipeline-BqiA_UMr.d.ts → pipeline-BG7UgbDc.d.ts} +2 -2
- package/dist/{plan-templates-BdDxl9cI.d.ts → plan-templates-CkKNPU3I.d.ts} +6 -6
- package/dist/{provider-runner-BUunikwY.d.ts → provider-runner-BNpuIyOL.d.ts} +3 -3
- package/dist/{retry-policy-BcmuT_V0.d.ts → retry-policy-rutAfVeR.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -9
- package/dist/sdd/index.js +208 -1
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-DrOhc2i5.d.ts → secret-vault-BTcC_T5v.d.ts} +3 -2
- package/dist/security/index.d.ts +5 -7
- package/dist/security/index.js +4 -35
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-C7wcdqMA.d.ts → selector-4vDFZKt3.d.ts} +1 -1
- package/dist/{session-event-bridge-BpJ5trO9.d.ts → session-event-bridge-DWlvglC2.d.ts} +2 -2
- package/dist/{session-reader-DDz1Ek4V.d.ts → session-reader-BAtCxdaw.d.ts} +1 -1
- package/dist/storage/index.d.ts +14 -15
- package/dist/storage/index.js +140 -134
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +19 -20
- package/dist/types/index.js +186 -102
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +38 -15
- package/dist/utils/index.js +62 -33
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-_lqjzErq.d.ts → wstack-paths-DD50Omgn.d.ts} +3 -0
- package/package.json +2 -2
- package/dist/models-registry-B6_KfS65.d.ts +0 -95
package/dist/storage/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomBytes, randomUUID, createHash } from 'crypto';
|
|
2
2
|
import * as fsp from 'fs/promises';
|
|
3
|
-
import * as
|
|
3
|
+
import * as path13 from 'path';
|
|
4
|
+
import 'fs';
|
|
4
5
|
import * as os from 'os';
|
|
5
6
|
import { hostname } from 'os';
|
|
6
7
|
|
|
@@ -12,9 +13,9 @@ function expectDefined(value, label) {
|
|
|
12
13
|
return value;
|
|
13
14
|
}
|
|
14
15
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
15
|
-
const dir =
|
|
16
|
+
const dir = path13.dirname(targetPath);
|
|
16
17
|
await fsp.mkdir(dir, { recursive: true });
|
|
17
|
-
const tmp =
|
|
18
|
+
const tmp = path13.join(dir, `.${path13.basename(targetPath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
18
19
|
try {
|
|
19
20
|
if (typeof content === "string") {
|
|
20
21
|
await fsp.writeFile(tmp, content, { flag: "wx", encoding: opts.encoding ?? "utf8" });
|
|
@@ -53,9 +54,9 @@ async function ensureDir(dir) {
|
|
|
53
54
|
await fsp.mkdir(dir, { recursive: true });
|
|
54
55
|
}
|
|
55
56
|
async function withFileLock(targetPath, fn, opts = {}) {
|
|
56
|
-
const dir =
|
|
57
|
+
const dir = path13.dirname(targetPath);
|
|
57
58
|
await fsp.mkdir(dir, { recursive: true });
|
|
58
|
-
const lockPath =
|
|
59
|
+
const lockPath = path13.join(dir, `.${path13.basename(targetPath)}.lock`);
|
|
59
60
|
const timeoutMs = opts.timeoutMs ?? 5e3;
|
|
60
61
|
const staleMs = opts.staleMs ?? 3e4;
|
|
61
62
|
const started = Date.now();
|
|
@@ -233,11 +234,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
233
234
|
}
|
|
234
235
|
/** Absolute path to the session index file. */
|
|
235
236
|
get indexFile() {
|
|
236
|
-
return
|
|
237
|
+
return path13.join(this.dir, "_index.jsonl");
|
|
237
238
|
}
|
|
238
239
|
/** Join session ID to its absolute path within the store directory. */
|
|
239
240
|
sessionPath(id, ext) {
|
|
240
|
-
return
|
|
241
|
+
return path13.join(this.dir, `${id}${ext}`);
|
|
241
242
|
}
|
|
242
243
|
/**
|
|
243
244
|
* Ensure the directory implied by the session ID exists. When the ID
|
|
@@ -245,7 +246,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
245
246
|
* subdirectory so sessions group naturally by day.
|
|
246
247
|
*/
|
|
247
248
|
async ensureShardDir(id) {
|
|
248
|
-
const dirPath =
|
|
249
|
+
const dirPath = path13.dirname(path13.join(this.dir, id));
|
|
249
250
|
await ensureDir(dirPath);
|
|
250
251
|
return dirPath;
|
|
251
252
|
}
|
|
@@ -253,7 +254,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
253
254
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
254
255
|
const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt, meta.model ?? meta.provider);
|
|
255
256
|
const shardDir = await this.ensureShardDir(id);
|
|
256
|
-
const file =
|
|
257
|
+
const file = path13.join(shardDir, `${path13.basename(id)}.jsonl`);
|
|
257
258
|
let handle;
|
|
258
259
|
try {
|
|
259
260
|
handle = await fsp.open(file, "a", 384);
|
|
@@ -271,8 +272,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
271
272
|
onClose: (s) => this.appendToIndex(s)
|
|
272
273
|
});
|
|
273
274
|
} catch (err) {
|
|
274
|
-
await handle.close().catch(() => {
|
|
275
|
-
});
|
|
275
|
+
await handle.close().catch((e) => console.warn(`[session-store] handle.close() failed: ${e}`));
|
|
276
276
|
throw err;
|
|
277
277
|
}
|
|
278
278
|
}
|
|
@@ -303,8 +303,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
303
303
|
);
|
|
304
304
|
return { writer, data };
|
|
305
305
|
} catch (err) {
|
|
306
|
-
await handle.close().catch(() => {
|
|
307
|
-
});
|
|
306
|
+
await handle.close().catch((e) => console.warn(`[session-store] handle.close() failed: ${e}`));
|
|
308
307
|
throw err;
|
|
309
308
|
}
|
|
310
309
|
}
|
|
@@ -461,7 +460,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
461
460
|
continue;
|
|
462
461
|
if (entry.isDirectory()) {
|
|
463
462
|
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
464
|
-
ids.push(...await this.collectSessionIds(
|
|
463
|
+
ids.push(...await this.collectSessionIds(path13.join(dir, entry.name), childPrefix, depth + 1));
|
|
465
464
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
466
465
|
if (entry.name === "_index.jsonl") continue;
|
|
467
466
|
const base = entry.name.replace(/\.jsonl$/, "");
|
|
@@ -493,15 +492,15 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
493
492
|
* sidecars, and the session directory (fleet.json, shared/, subagents/).
|
|
494
493
|
*/
|
|
495
494
|
async deleteSession(id) {
|
|
496
|
-
await fsp.unlink(this.sessionPath(id, ".jsonl")).catch(() =>
|
|
497
|
-
await fsp.unlink(this.sessionPath(id, ".summary.json")).catch(() =>
|
|
498
|
-
const shardDir =
|
|
499
|
-
const base =
|
|
495
|
+
await fsp.unlink(this.sessionPath(id, ".jsonl")).catch((err) => console.warn(`[session-store] delete .jsonl failed: ${err}`));
|
|
496
|
+
await fsp.unlink(this.sessionPath(id, ".summary.json")).catch((err) => console.warn(`[session-store] delete .summary.json failed: ${err}`));
|
|
497
|
+
const shardDir = path13.dirname(path13.join(this.dir, id));
|
|
498
|
+
const base = path13.basename(id);
|
|
500
499
|
for (const ext of [".plan.json", ".todos.json"]) {
|
|
501
|
-
await fsp.unlink(
|
|
500
|
+
await fsp.unlink(path13.join(shardDir, `${base}${ext}`)).catch((err) => console.warn(`[session-store] delete ${ext} failed: ${err}`));
|
|
502
501
|
}
|
|
503
|
-
const sessDir =
|
|
504
|
-
await fsp.rm(sessDir, { recursive: true, force: true }).catch(() =>
|
|
502
|
+
const sessDir = path13.join(shardDir, base);
|
|
503
|
+
await fsp.rm(sessDir, { recursive: true, force: true }).catch((err) => console.warn(`[session-store] delete session dir failed: ${err}`));
|
|
505
504
|
await this.writeTombstone(id);
|
|
506
505
|
}
|
|
507
506
|
async delete(id) {
|
|
@@ -512,7 +511,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
512
511
|
let deleted = 0;
|
|
513
512
|
let activeSessionId = null;
|
|
514
513
|
try {
|
|
515
|
-
const raw = await fsp.readFile(
|
|
514
|
+
const raw = await fsp.readFile(path13.join(this.dir, "active.json"), "utf8");
|
|
516
515
|
const active = JSON.parse(raw);
|
|
517
516
|
activeSessionId = active.sessionId ?? null;
|
|
518
517
|
} catch {
|
|
@@ -520,11 +519,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
520
519
|
const entries = await fsp.readdir(this.dir, { withFileTypes: true }).catch(() => []);
|
|
521
520
|
for (const entry of entries) {
|
|
522
521
|
if (!entry.isDirectory()) continue;
|
|
523
|
-
const dateDir =
|
|
522
|
+
const dateDir = path13.join(this.dir, entry.name);
|
|
524
523
|
const files = await fsp.readdir(dateDir, { withFileTypes: true }).catch(() => []);
|
|
525
524
|
for (const file of files) {
|
|
526
525
|
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
527
|
-
const jsonlPath =
|
|
526
|
+
const jsonlPath = path13.join(dateDir, file.name);
|
|
528
527
|
try {
|
|
529
528
|
const stat5 = await fsp.stat(jsonlPath);
|
|
530
529
|
if (stat5.mtimeMs >= cutoff) continue;
|
|
@@ -542,7 +541,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
542
541
|
}
|
|
543
542
|
for (const entry of entries) {
|
|
544
543
|
if (!entry.isDirectory()) continue;
|
|
545
|
-
const dateDir =
|
|
544
|
+
const dateDir = path13.join(this.dir, entry.name);
|
|
546
545
|
try {
|
|
547
546
|
const remaining = await fsp.readdir(dateDir);
|
|
548
547
|
if (remaining.length === 0) {
|
|
@@ -707,7 +706,7 @@ var FileSessionWriter = class {
|
|
|
707
706
|
this.meta = meta;
|
|
708
707
|
this.events = events;
|
|
709
708
|
this.resumed = opts.resumed ?? false;
|
|
710
|
-
this.manifestFile = opts.dir ?
|
|
709
|
+
this.manifestFile = opts.dir ? path13.join(opts.dir, `${path13.basename(id)}.summary.json`) : "";
|
|
711
710
|
this.filePath = opts.filePath ?? "";
|
|
712
711
|
this.secretScrubber = opts.secretScrubber;
|
|
713
712
|
this.onCloseCb = opts.onClose;
|
|
@@ -1027,7 +1026,7 @@ function userInputTitle(content) {
|
|
|
1027
1026
|
var QueueStore = class {
|
|
1028
1027
|
file;
|
|
1029
1028
|
constructor(opts) {
|
|
1030
|
-
this.file =
|
|
1029
|
+
this.file = path13.join(opts.dir, "queue.json");
|
|
1031
1030
|
}
|
|
1032
1031
|
async write(items) {
|
|
1033
1032
|
if (items.length === 0) {
|
|
@@ -1094,7 +1093,7 @@ var DefaultAttachmentStore = class {
|
|
|
1094
1093
|
let data = input.data;
|
|
1095
1094
|
if (this.spoolDir && bytes >= this.spoolThreshold) {
|
|
1096
1095
|
await fsp.mkdir(this.spoolDir, { recursive: true });
|
|
1097
|
-
spooledPath =
|
|
1096
|
+
spooledPath = path13.join(this.spoolDir, `${id}.bin`);
|
|
1098
1097
|
await atomicWrite(spooledPath, input.data, {
|
|
1099
1098
|
encoding: input.kind === "image" ? "base64" : "utf8"
|
|
1100
1099
|
});
|
|
@@ -1305,7 +1304,7 @@ var FileMemoryBackend = class {
|
|
|
1305
1304
|
}
|
|
1306
1305
|
async remember(scope, entry, filePath) {
|
|
1307
1306
|
const file = this.resolveFile(filePath, scope);
|
|
1308
|
-
await ensureDir(
|
|
1307
|
+
await ensureDir(path13.dirname(file));
|
|
1309
1308
|
let existing = "";
|
|
1310
1309
|
try {
|
|
1311
1310
|
existing = await fsp.readFile(file, "utf8");
|
|
@@ -1322,39 +1321,41 @@ ${line}`;
|
|
|
1322
1321
|
}
|
|
1323
1322
|
async forget(scope, query, filePath) {
|
|
1324
1323
|
const file = this.resolveFile(filePath, scope);
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
const
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1324
|
+
return withFileLock(file, async () => {
|
|
1325
|
+
let existing;
|
|
1326
|
+
try {
|
|
1327
|
+
existing = await fsp.readFile(file, "utf8");
|
|
1328
|
+
} catch {
|
|
1329
|
+
return 0;
|
|
1330
|
+
}
|
|
1331
|
+
const needle = query.toLowerCase();
|
|
1332
|
+
const idMatcher = /mem_\d+_\w+/;
|
|
1333
|
+
let removed = 0;
|
|
1334
|
+
const lines = existing.split("\n").filter((line) => {
|
|
1335
|
+
const trimmed = line.trim();
|
|
1336
|
+
if (!trimmed.startsWith("- ")) return true;
|
|
1337
|
+
if (idMatcher.test(query)) {
|
|
1338
|
+
const entryIdMatch = /mem_\d+_\w+/.exec(trimmed);
|
|
1339
|
+
if (entryIdMatch && entryIdMatch[0] === query) {
|
|
1340
|
+
removed++;
|
|
1341
|
+
return false;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
if (trimmed.toLowerCase().includes(needle)) {
|
|
1340
1345
|
removed++;
|
|
1341
1346
|
return false;
|
|
1342
1347
|
}
|
|
1348
|
+
return true;
|
|
1349
|
+
});
|
|
1350
|
+
if (removed > 0) {
|
|
1351
|
+
if (lines.length === 0 || lines.length === 1 && !lines[0]?.trim()) {
|
|
1352
|
+
await atomicWrite(file, "");
|
|
1353
|
+
} else {
|
|
1354
|
+
await atomicWrite(file, lines.join("\n"));
|
|
1355
|
+
}
|
|
1343
1356
|
}
|
|
1344
|
-
|
|
1345
|
-
removed++;
|
|
1346
|
-
return false;
|
|
1347
|
-
}
|
|
1348
|
-
return true;
|
|
1357
|
+
return removed;
|
|
1349
1358
|
});
|
|
1350
|
-
if (removed > 0) {
|
|
1351
|
-
if (lines.length === 0 || lines.length === 1 && !lines[0]?.trim()) {
|
|
1352
|
-
await atomicWrite(file, "");
|
|
1353
|
-
} else {
|
|
1354
|
-
await atomicWrite(file, lines.join("\n"));
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
return removed;
|
|
1358
1359
|
}
|
|
1359
1360
|
async readAll(scope, filePath) {
|
|
1360
1361
|
const file = this.resolveFile(filePath, scope);
|
|
@@ -1715,8 +1716,8 @@ ${body.trim()}`);
|
|
|
1715
1716
|
if (!this.persistBackup || scope === "project-agents") return;
|
|
1716
1717
|
try {
|
|
1717
1718
|
const content = await this.backend.readAll(scope, this.files[scope]);
|
|
1718
|
-
const { writeFile: writeFile6, mkdir:
|
|
1719
|
-
await
|
|
1719
|
+
const { writeFile: writeFile6, mkdir: mkdir6 } = await import('fs/promises');
|
|
1720
|
+
await mkdir6(this.backupDir, { recursive: true });
|
|
1720
1721
|
await writeFile6(`${this.backupDir}/${scope}.md`, content, "utf8");
|
|
1721
1722
|
} catch {
|
|
1722
1723
|
}
|
|
@@ -2067,7 +2068,7 @@ var SessionMemoryConsolidator = class {
|
|
|
2067
2068
|
for (const op of parsed.operations) {
|
|
2068
2069
|
switch (op.action) {
|
|
2069
2070
|
case "add": {
|
|
2070
|
-
if (op.text
|
|
2071
|
+
if (op.text?.trim()) {
|
|
2071
2072
|
await this.memoryStore.remember(op.text.trim(), void 0, {
|
|
2072
2073
|
type: op.type,
|
|
2073
2074
|
tags: op.tags,
|
|
@@ -2172,16 +2173,14 @@ function deepFreeze(obj) {
|
|
|
2172
2173
|
}
|
|
2173
2174
|
return Object.freeze(obj);
|
|
2174
2175
|
}
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
function decryptConfigSecrets(cfg, vault) {
|
|
2176
|
+
function decryptConfigSecrets(cfg, vault, opts) {
|
|
2177
|
+
const warn = ((msg) => console.warn(msg));
|
|
2178
2178
|
return walk(cfg, vault, (v, key) => {
|
|
2179
2179
|
try {
|
|
2180
2180
|
return vault.decrypt(v);
|
|
2181
2181
|
} catch (err) {
|
|
2182
|
-
|
|
2183
|
-
`[secret-vault] Failed to decrypt "${key}"
|
|
2184
|
-
err instanceof Error ? err.message : err
|
|
2182
|
+
warn(
|
|
2183
|
+
`[secret-vault] Failed to decrypt "${key}": ${err instanceof Error ? err.message : err}`
|
|
2185
2184
|
);
|
|
2186
2185
|
return "";
|
|
2187
2186
|
}
|
|
@@ -2439,12 +2438,14 @@ var DefaultConfigLoader = class {
|
|
|
2439
2438
|
}
|
|
2440
2439
|
async load(opts = {}) {
|
|
2441
2440
|
let cfg = { ...BEHAVIOR_DEFAULTS };
|
|
2442
|
-
const [global, local] = await Promise.all([
|
|
2441
|
+
const [global, local, inProject] = await Promise.all([
|
|
2443
2442
|
this.readJson(this.paths.globalConfig),
|
|
2444
|
-
this.readJson(this.paths.projectLocalConfig)
|
|
2443
|
+
this.readJson(this.paths.projectLocalConfig),
|
|
2444
|
+
this.readJson(this.paths.inProjectConfig)
|
|
2445
2445
|
]);
|
|
2446
2446
|
cfg = deepMerge(cfg, global);
|
|
2447
2447
|
cfg = deepMerge(cfg, local);
|
|
2448
|
+
cfg = deepMerge(cfg, inProject);
|
|
2448
2449
|
for (const [key, fn] of Object.entries(ENV_MAP)) {
|
|
2449
2450
|
const v = process.env[key];
|
|
2450
2451
|
if (v) fn(cfg, v);
|
|
@@ -2643,7 +2644,7 @@ var RecoveryLock = class {
|
|
|
2643
2644
|
sessionStore;
|
|
2644
2645
|
probe;
|
|
2645
2646
|
constructor(opts) {
|
|
2646
|
-
this.file =
|
|
2647
|
+
this.file = path13.join(opts.dir, LOCK_FILE);
|
|
2647
2648
|
this.pid = opts.pid ?? process.pid;
|
|
2648
2649
|
this.hostname = opts.hostname ?? os.hostname();
|
|
2649
2650
|
this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
@@ -2701,7 +2702,7 @@ var RecoveryLock = class {
|
|
|
2701
2702
|
* null return before calling this.
|
|
2702
2703
|
*/
|
|
2703
2704
|
async write(sessionId) {
|
|
2704
|
-
await ensureDir(
|
|
2705
|
+
await ensureDir(path13.dirname(this.file));
|
|
2705
2706
|
const lock = {
|
|
2706
2707
|
v: 1,
|
|
2707
2708
|
sessionId,
|
|
@@ -3188,7 +3189,7 @@ var AnnotationsStore = class {
|
|
|
3188
3189
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3189
3190
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3190
3191
|
}
|
|
3191
|
-
return
|
|
3192
|
+
return path13.join(this.dir, `${sessionId}.annotations.json`);
|
|
3192
3193
|
}
|
|
3193
3194
|
async readFile(sessionId) {
|
|
3194
3195
|
const fp = this.filePath(sessionId);
|
|
@@ -3345,7 +3346,7 @@ var ReplayLogStore = class {
|
|
|
3345
3346
|
out.push({
|
|
3346
3347
|
sessionId,
|
|
3347
3348
|
entryCount: all.length,
|
|
3348
|
-
path:
|
|
3349
|
+
path: path13.join(this.dir, name)
|
|
3349
3350
|
});
|
|
3350
3351
|
}
|
|
3351
3352
|
return out.sort((a, b) => a.sessionId.localeCompare(b.sessionId));
|
|
@@ -3355,7 +3356,7 @@ var ReplayLogStore = class {
|
|
|
3355
3356
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3356
3357
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3357
3358
|
}
|
|
3358
|
-
return
|
|
3359
|
+
return path13.join(this.dir, `${sessionId}.replay.jsonl`);
|
|
3359
3360
|
}
|
|
3360
3361
|
async readAll(sessionId) {
|
|
3361
3362
|
const fp = this.filePath(sessionId);
|
|
@@ -3544,7 +3545,7 @@ var SessionRecovery = class {
|
|
|
3544
3545
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3545
3546
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3546
3547
|
}
|
|
3547
|
-
return
|
|
3548
|
+
return path13.join(this.dir, `${sessionId}.jsonl`);
|
|
3548
3549
|
}
|
|
3549
3550
|
};
|
|
3550
3551
|
var GENESIS_PREV = "0".repeat(64);
|
|
@@ -3667,7 +3668,7 @@ var ToolAuditLog = class {
|
|
|
3667
3668
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3668
3669
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3669
3670
|
}
|
|
3670
|
-
return
|
|
3671
|
+
return path13.join(this.dir, `${sessionId}.audit.jsonl`);
|
|
3671
3672
|
}
|
|
3672
3673
|
async readAll(sessionId) {
|
|
3673
3674
|
const fp = this.filePath(sessionId);
|
|
@@ -3852,7 +3853,7 @@ var DefaultSessionRewinder = class {
|
|
|
3852
3853
|
sessionsDir;
|
|
3853
3854
|
projectRoot;
|
|
3854
3855
|
async listCheckpoints(sessionId) {
|
|
3855
|
-
const file =
|
|
3856
|
+
const file = path13.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3856
3857
|
const raw = await fsp.readFile(file, "utf8");
|
|
3857
3858
|
const events = parseEvents(raw);
|
|
3858
3859
|
const fileCountMap = /* @__PURE__ */ new Map();
|
|
@@ -3877,7 +3878,7 @@ var DefaultSessionRewinder = class {
|
|
|
3877
3878
|
return checkpoints;
|
|
3878
3879
|
}
|
|
3879
3880
|
async rewindToCheckpoint(sessionId, checkpointIndex) {
|
|
3880
|
-
const file =
|
|
3881
|
+
const file = path13.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3881
3882
|
const raw = await fsp.readFile(file, "utf8");
|
|
3882
3883
|
const events = parseEvents(raw);
|
|
3883
3884
|
let targetIdx = -1;
|
|
@@ -3912,7 +3913,7 @@ var DefaultSessionRewinder = class {
|
|
|
3912
3913
|
return { ...result, toPromptIndex: checkpointIndex, removedEvents };
|
|
3913
3914
|
}
|
|
3914
3915
|
async rewindLastN(sessionId, n) {
|
|
3915
|
-
const file =
|
|
3916
|
+
const file = path13.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3916
3917
|
const raw = await fsp.readFile(file, "utf8");
|
|
3917
3918
|
const events = parseEvents(raw);
|
|
3918
3919
|
const checkpoints = [];
|
|
@@ -3941,7 +3942,7 @@ var DefaultSessionRewinder = class {
|
|
|
3941
3942
|
return { ...result, toPromptIndex: targetIndex, removedEvents: snapshotsToRevert.length };
|
|
3942
3943
|
}
|
|
3943
3944
|
async rewindToStart(sessionId) {
|
|
3944
|
-
const file =
|
|
3945
|
+
const file = path13.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3945
3946
|
const raw = await fsp.readFile(file, "utf8");
|
|
3946
3947
|
const events = parseEvents(raw);
|
|
3947
3948
|
const allSnapshots = [];
|
|
@@ -3977,10 +3978,10 @@ async function revertSnapshots(snapshots, projectRoot) {
|
|
|
3977
3978
|
for (const snapshot of snapshots) {
|
|
3978
3979
|
for (const file of snapshot.files) {
|
|
3979
3980
|
try {
|
|
3980
|
-
const absPath =
|
|
3981
|
-
const root =
|
|
3982
|
-
const rel =
|
|
3983
|
-
if (rel.startsWith("..") ||
|
|
3981
|
+
const absPath = path13.resolve(file.path);
|
|
3982
|
+
const root = path13.resolve(projectRoot);
|
|
3983
|
+
const rel = path13.relative(root, absPath);
|
|
3984
|
+
if (rel.startsWith("..") || path13.isAbsolute(rel)) {
|
|
3984
3985
|
errors.push(`${file.path}: path resolves outside project root \u2014 skipping`);
|
|
3985
3986
|
continue;
|
|
3986
3987
|
}
|
|
@@ -4561,11 +4562,11 @@ var color = {
|
|
|
4561
4562
|
bgGreen: wrap("42", "49")
|
|
4562
4563
|
};
|
|
4563
4564
|
function projectHash(absRoot) {
|
|
4564
|
-
return createHash("sha256").update(
|
|
4565
|
+
return createHash("sha256").update(path13.resolve(absRoot)).digest("hex").slice(0, 12);
|
|
4565
4566
|
}
|
|
4566
4567
|
function projectSlug(absRoot) {
|
|
4567
|
-
const base = slugify(
|
|
4568
|
-
const hash = createHash("sha256").update(
|
|
4568
|
+
const base = slugify(path13.basename(absRoot));
|
|
4569
|
+
const hash = createHash("sha256").update(path13.resolve(absRoot)).digest("hex").slice(0, 6);
|
|
4569
4570
|
return `${base}-${hash}`;
|
|
4570
4571
|
}
|
|
4571
4572
|
function slugify(name) {
|
|
@@ -4573,42 +4574,43 @@ function slugify(name) {
|
|
|
4573
4574
|
}
|
|
4574
4575
|
function resolveWstackPaths(opts) {
|
|
4575
4576
|
const home = opts.userHome ?? os.homedir();
|
|
4576
|
-
const globalRoot = opts.globalRoot ??
|
|
4577
|
+
const globalRoot = opts.globalRoot ?? path13.join(home, ".wrongstack");
|
|
4577
4578
|
const hash = projectHash(opts.projectRoot);
|
|
4578
4579
|
const slug = projectSlug(opts.projectRoot);
|
|
4579
|
-
const projectDir =
|
|
4580
|
+
const projectDir = path13.join(globalRoot, "projects", slug);
|
|
4580
4581
|
return {
|
|
4581
4582
|
globalRoot,
|
|
4582
4583
|
configDir: globalRoot,
|
|
4583
|
-
globalConfig:
|
|
4584
|
-
secretsKey:
|
|
4585
|
-
globalMemory:
|
|
4586
|
-
globalSkills:
|
|
4587
|
-
globalPrompts:
|
|
4588
|
-
cacheDir:
|
|
4589
|
-
modelsCache:
|
|
4590
|
-
modelsOverlayCache:
|
|
4591
|
-
historyFile:
|
|
4592
|
-
logFile:
|
|
4584
|
+
globalConfig: path13.join(globalRoot, "config.json"),
|
|
4585
|
+
secretsKey: path13.join(globalRoot, ".key"),
|
|
4586
|
+
globalMemory: path13.join(globalRoot, "memory.md"),
|
|
4587
|
+
globalSkills: path13.join(globalRoot, "skills"),
|
|
4588
|
+
globalPrompts: path13.join(globalRoot, "prompts"),
|
|
4589
|
+
cacheDir: path13.join(globalRoot, "cache"),
|
|
4590
|
+
modelsCache: path13.join(globalRoot, "cache", "models.dev.json"),
|
|
4591
|
+
modelsOverlayCache: path13.join(globalRoot, "cache", "models-overlay.json"),
|
|
4592
|
+
historyFile: path13.join(globalRoot, "history"),
|
|
4593
|
+
logFile: path13.join(globalRoot, "logs", "wrongstack.log"),
|
|
4593
4594
|
projectDir,
|
|
4594
|
-
projectCodebaseIndex:
|
|
4595
|
-
projectMemory:
|
|
4596
|
-
projectSessions:
|
|
4597
|
-
projectTrust:
|
|
4598
|
-
projectMeta:
|
|
4599
|
-
projectLocalConfig:
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4595
|
+
projectCodebaseIndex: path13.join(projectDir, "codebase-index"),
|
|
4596
|
+
projectMemory: path13.join(projectDir, "memory.md"),
|
|
4597
|
+
projectSessions: path13.join(projectDir, "sessions"),
|
|
4598
|
+
projectTrust: path13.join(projectDir, "trust.json"),
|
|
4599
|
+
projectMeta: path13.join(projectDir, "meta.json"),
|
|
4600
|
+
projectLocalConfig: path13.join(projectDir, "config.local.json"),
|
|
4601
|
+
inProjectConfig: path13.join(opts.projectRoot, ".wrongstack", "config.json"),
|
|
4602
|
+
inProjectAgentsFile: path13.join(opts.projectRoot, ".wrongstack", "AGENTS.md"),
|
|
4603
|
+
inProjectSkills: path13.join(opts.projectRoot, ".wrongstack", "skills"),
|
|
4604
|
+
inProjectWorktrees: path13.join(opts.projectRoot, ".wrongstack", "worktrees"),
|
|
4603
4605
|
projectHash: hash,
|
|
4604
4606
|
projectSlug: slug,
|
|
4605
|
-
projectGoal:
|
|
4606
|
-
projectSpecs:
|
|
4607
|
-
projectTaskGraphs:
|
|
4608
|
-
projectSddSession:
|
|
4609
|
-
projectPlan:
|
|
4610
|
-
projectAutophase:
|
|
4611
|
-
syncConfig:
|
|
4607
|
+
projectGoal: path13.join(projectDir, "goal.json"),
|
|
4608
|
+
projectSpecs: path13.join(projectDir, "specs"),
|
|
4609
|
+
projectTaskGraphs: path13.join(projectDir, "task-graphs"),
|
|
4610
|
+
projectSddSession: path13.join(projectDir, "sdd-session.json"),
|
|
4611
|
+
projectPlan: path13.join(projectDir, "plan.json"),
|
|
4612
|
+
projectAutophase: path13.join(projectDir, "autophase"),
|
|
4613
|
+
syncConfig: path13.join(globalRoot, "sync.json")
|
|
4612
4614
|
};
|
|
4613
4615
|
}
|
|
4614
4616
|
|
|
@@ -4671,16 +4673,20 @@ async function loadGoal(filePath) {
|
|
|
4671
4673
|
let raw;
|
|
4672
4674
|
try {
|
|
4673
4675
|
raw = await fsp.readFile(filePath, "utf8");
|
|
4674
|
-
} catch {
|
|
4675
|
-
|
|
4676
|
+
} catch (err) {
|
|
4677
|
+
const code = err.code;
|
|
4678
|
+
if (code === "ENOENT") return null;
|
|
4679
|
+
throw err;
|
|
4676
4680
|
}
|
|
4677
4681
|
try {
|
|
4678
4682
|
const parsed = JSON.parse(raw);
|
|
4679
4683
|
if (parsed?.version !== 1 || typeof parsed.goal !== "string" || !Array.isArray(parsed.journal)) {
|
|
4684
|
+
console.warn(`[goal-store] Corrupt goal.json at ${filePath} \u2014 invalid schema. Consider deleting it and re-creating.`);
|
|
4680
4685
|
return null;
|
|
4681
4686
|
}
|
|
4682
4687
|
return parsed;
|
|
4683
4688
|
} catch {
|
|
4689
|
+
console.warn(`[goal-store] Corrupt goal.json at ${filePath} \u2014 JSON parse failed. Consider deleting it and re-creating.`);
|
|
4684
4690
|
return null;
|
|
4685
4691
|
}
|
|
4686
4692
|
}
|
|
@@ -4807,9 +4813,9 @@ function parseProgressFromText(text) {
|
|
|
4807
4813
|
const re = /\[progress:\s*(\d{1,3})%\]\s*(?:[—\-]\s*(.+))?/i;
|
|
4808
4814
|
const m = text.match(re);
|
|
4809
4815
|
if (!m) return null;
|
|
4810
|
-
const progress = Math.min(100, Math.max(0, Number.parseInt(m[1], 10)));
|
|
4816
|
+
const progress = Math.min(100, Math.max(0, Number.parseInt(m[1] ?? "0", 10)));
|
|
4811
4817
|
const note = m[2]?.trim() || void 0;
|
|
4812
|
-
return { progress, note };
|
|
4818
|
+
return note === void 0 ? { progress } : { progress, note };
|
|
4813
4819
|
}
|
|
4814
4820
|
function recordProgress(goal, progress, note) {
|
|
4815
4821
|
const clamped = Math.min(100, Math.max(0, progress));
|
|
@@ -4829,7 +4835,7 @@ function computeTrend(history) {
|
|
|
4829
4835
|
const recent = history.slice(-5);
|
|
4830
4836
|
const deltas = [];
|
|
4831
4837
|
for (let i = 1; i < recent.length; i++) {
|
|
4832
|
-
deltas.push(recent[i]
|
|
4838
|
+
deltas.push((recent[i]?.progress ?? 0) - (recent[i - 1]?.progress ?? 0));
|
|
4833
4839
|
}
|
|
4834
4840
|
if (deltas.length < 2) return void 0;
|
|
4835
4841
|
const avgDelta = deltas.reduce((a, b) => a + b, 0) / deltas.length;
|
|
@@ -4851,7 +4857,7 @@ var DefaultPromptStore = class {
|
|
|
4851
4857
|
if (!file.endsWith(".json")) continue;
|
|
4852
4858
|
try {
|
|
4853
4859
|
const raw = JSON.parse(
|
|
4854
|
-
await fsp.readFile(
|
|
4860
|
+
await fsp.readFile(path13.join(this.dir, file), "utf8")
|
|
4855
4861
|
);
|
|
4856
4862
|
entries.push(raw.entry);
|
|
4857
4863
|
} catch {
|
|
@@ -4864,7 +4870,7 @@ var DefaultPromptStore = class {
|
|
|
4864
4870
|
);
|
|
4865
4871
|
}
|
|
4866
4872
|
async get(id) {
|
|
4867
|
-
const file =
|
|
4873
|
+
const file = path13.join(this.dir, `${id}.json`);
|
|
4868
4874
|
try {
|
|
4869
4875
|
const raw = JSON.parse(await fsp.readFile(file, "utf8"));
|
|
4870
4876
|
return raw.entry;
|
|
@@ -4874,12 +4880,12 @@ var DefaultPromptStore = class {
|
|
|
4874
4880
|
}
|
|
4875
4881
|
async save(entry) {
|
|
4876
4882
|
await ensureDir(this.dir);
|
|
4877
|
-
const file =
|
|
4883
|
+
const file = path13.join(this.dir, `${entry.id}.json`);
|
|
4878
4884
|
const raw = { version: 1, entry };
|
|
4879
4885
|
await atomicWrite(file, JSON.stringify(raw, null, 2));
|
|
4880
4886
|
}
|
|
4881
4887
|
async delete(id) {
|
|
4882
|
-
const file =
|
|
4888
|
+
const file = path13.join(this.dir, `${id}.json`);
|
|
4883
4889
|
try {
|
|
4884
4890
|
await fsp.unlink(file);
|
|
4885
4891
|
return true;
|
|
@@ -4913,7 +4919,7 @@ var CloudSync = class {
|
|
|
4913
4919
|
this.paths = paths;
|
|
4914
4920
|
this.getConfig = getConfig;
|
|
4915
4921
|
this.setConfig = setConfig;
|
|
4916
|
-
this.statePath =
|
|
4922
|
+
this.statePath = path13.join(paths.globalRoot, "sync-state.json");
|
|
4917
4923
|
}
|
|
4918
4924
|
paths;
|
|
4919
4925
|
getConfig;
|
|
@@ -5020,7 +5026,7 @@ var CloudSync = class {
|
|
|
5020
5026
|
const rel = segments.slice(2).join("/");
|
|
5021
5027
|
const destPath = resolvePulledCategoryPath(cat, localPath, rel, entry.path);
|
|
5022
5028
|
const blobData = await this.getBlob(token, owner, repoName, entry.sha);
|
|
5023
|
-
await fsp.mkdir(
|
|
5029
|
+
await fsp.mkdir(path13.dirname(destPath), { recursive: true });
|
|
5024
5030
|
await fsp.writeFile(destPath, Buffer.from(blobData, "base64"));
|
|
5025
5031
|
}
|
|
5026
5032
|
const localRev = await this.hashLocalCategories(cfg.categories);
|
|
@@ -5127,7 +5133,7 @@ var CloudSync = class {
|
|
|
5127
5133
|
const files = await this.walkDir(localPath, localPath);
|
|
5128
5134
|
for (const file of files) {
|
|
5129
5135
|
const content = await fsp.readFile(file, "utf8");
|
|
5130
|
-
const rel =
|
|
5136
|
+
const rel = path13.relative(localPath, file).replace(/\\/g, "/");
|
|
5131
5137
|
entries.push({ path: `data/${cat}/${rel}`, content, mode: "100644" });
|
|
5132
5138
|
hashes.push(content);
|
|
5133
5139
|
}
|
|
@@ -5184,7 +5190,7 @@ var CloudSync = class {
|
|
|
5184
5190
|
const results = [];
|
|
5185
5191
|
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
5186
5192
|
for (const entry of entries) {
|
|
5187
|
-
const full =
|
|
5193
|
+
const full = path13.join(dir, entry.name);
|
|
5188
5194
|
if (entry.isDirectory()) {
|
|
5189
5195
|
results.push(...await this.walkDir(full, base));
|
|
5190
5196
|
} else {
|
|
@@ -5201,15 +5207,15 @@ function resolvePulledCategoryPath(cat, localPath, rel, remotePath) {
|
|
|
5201
5207
|
return localPath;
|
|
5202
5208
|
}
|
|
5203
5209
|
if (!rel) return localPath;
|
|
5204
|
-
const normalizedRel =
|
|
5205
|
-
const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${
|
|
5206
|
-
if (
|
|
5210
|
+
const normalizedRel = path13.normalize(rel);
|
|
5211
|
+
const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${path13.sep}`);
|
|
5212
|
+
if (path13.isAbsolute(normalizedRel) || traversesUp) {
|
|
5207
5213
|
throw new Error(`Refusing CloudSync path traversal: ${remotePath}`);
|
|
5208
5214
|
}
|
|
5209
|
-
const dest =
|
|
5210
|
-
const root =
|
|
5211
|
-
const relative3 =
|
|
5212
|
-
if (relative3.startsWith("..") ||
|
|
5215
|
+
const dest = path13.resolve(localPath, normalizedRel);
|
|
5216
|
+
const root = path13.resolve(localPath);
|
|
5217
|
+
const relative3 = path13.relative(root, dest);
|
|
5218
|
+
if (relative3.startsWith("..") || path13.isAbsolute(relative3)) {
|
|
5213
5219
|
throw new Error(`Refusing CloudSync path outside category root: ${remotePath}`);
|
|
5214
5220
|
}
|
|
5215
5221
|
return dest;
|