@wrongstack/core 0.104.0 → 0.109.1
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/defaults/index.d.ts +2 -2
- package/dist/defaults/index.js +103 -51
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +2 -2
- package/dist/execution/index.js +57 -7
- package/dist/execution/index.js.map +1 -1
- package/dist/{goal-store-ht0VmR1A.d.ts → goal-store-CV9Yz2X_.d.ts} +11 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +74 -75
- package/dist/index.js.map +1 -1
- package/dist/{parallel-eternal-engine-CUtmM_0V.d.ts → parallel-eternal-engine-B2CbsKpc.d.ts} +3 -2
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +104 -54
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/package.json +1 -1
package/dist/{parallel-eternal-engine-CUtmM_0V.d.ts → parallel-eternal-engine-B2CbsKpc.d.ts}
RENAMED
|
@@ -5,7 +5,7 @@ import { M as ModelsRegistry } from './models-registry-B6_KfS65.js';
|
|
|
5
5
|
import { T as ToolExecutorOptions, a as ToolExecutorStrategy, b as ToolBatchResult } from './index-DIKEcfgC.js';
|
|
6
6
|
import { g as Agent, h as AgentFactory } from './agent-subagent-runner-DukQLUcS.js';
|
|
7
7
|
import { b as BrainArbiter } from './brain-Dfv4Y82E.js';
|
|
8
|
-
import { J as JournalEntry } from './goal-store-
|
|
8
|
+
import { J as JournalEntry } from './goal-store-CV9Yz2X_.js';
|
|
9
9
|
import { D as DispatchClassifier, a as DefaultMultiAgentCoordinator } from './multi-agent-coordinator-51LvnXkD.js';
|
|
10
10
|
|
|
11
11
|
declare class DefaultRetryPolicy implements RetryPolicy {
|
|
@@ -412,7 +412,8 @@ interface ParallelEternalOptions {
|
|
|
412
412
|
projectRoot: string;
|
|
413
413
|
/**
|
|
414
414
|
* Override the resolved goal.json path. Defaults to
|
|
415
|
-
* `goalFilePath(projectRoot)`
|
|
415
|
+
* `goalFilePath(projectRoot)` — the canonical per-project goal file under
|
|
416
|
+
* `~/.wrongstack/projects/<slug>/`, shared with `/goal` and the TUI.
|
|
416
417
|
* Primarily for tests that want an isolated goal file under a temp dir.
|
|
417
418
|
*/
|
|
418
419
|
goalPath?: string | undefined;
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { D as DefaultSessionReader, f as DefaultSessionReaderOptions, S as Sessi
|
|
|
7
7
|
import { S as SessionRewinder, C as CheckpointInfo, a as RewindResultExtended } from '../session-rewinder-C9HnMkhP.js';
|
|
8
8
|
import { T as TaskItem } from '../task-format-vGOIftmK.js';
|
|
9
9
|
export { a as DirectorStateCheckpoint, D as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-BfeCUbmk.js';
|
|
10
|
-
export { G as GoalFile, J as JournalEntry, M as MAX_JOURNAL_ENTRIES, a as MAX_PROGRESS_HISTORY, P as ProgressSnapshot, b as appendJournal, e as emptyGoal, f as formatGoal, g as goalFilePath, l as loadGoal, p as parseProgressFromText, r as recordProgress, s as saveGoal, c as setProgress, d as summarizeUsage } from '../goal-store-
|
|
10
|
+
export { G as GoalFile, J as JournalEntry, M as MAX_JOURNAL_ENTRIES, a as MAX_PROGRESS_HISTORY, P as ProgressSnapshot, b as appendJournal, e as emptyGoal, f as formatGoal, g as goalFilePath, l as loadGoal, p as parseProgressFromText, r as recordProgress, s as saveGoal, c as setProgress, d as summarizeUsage } from '../goal-store-CV9Yz2X_.js';
|
|
11
11
|
import { W as WstackPaths } from '../wstack-paths-_lqjzErq.js';
|
|
12
12
|
import { w as SyncCategory, g as SyncConfig } from '../config-BSU-6vah.js';
|
|
13
13
|
export { A as AuditLevel, C as CORE_RECONSTRUCT_EVENTS, a as STANDARD_AUDIT_EVENTS, S as SessionEventBridge, b as SessionEventBridgeOptions, c as SessionSamplingOptions, T as ToolProgressSamplingOptions, d as createSessionEventBridge, r as resolveAuditLevel, e as resolveSessionLoggingConfig } from '../session-event-bridge-BpJ5trO9.js';
|
package/dist/storage/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomBytes, randomUUID, createHash } from 'crypto';
|
|
2
2
|
import * as fsp from 'fs/promises';
|
|
3
|
-
import * as
|
|
3
|
+
import * as path12 from 'path';
|
|
4
4
|
import * as os from 'os';
|
|
5
5
|
import { hostname } from 'os';
|
|
6
6
|
|
|
@@ -12,9 +12,9 @@ function expectDefined(value, label) {
|
|
|
12
12
|
return value;
|
|
13
13
|
}
|
|
14
14
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
15
|
-
const dir =
|
|
15
|
+
const dir = path12.dirname(targetPath);
|
|
16
16
|
await fsp.mkdir(dir, { recursive: true });
|
|
17
|
-
const tmp =
|
|
17
|
+
const tmp = path12.join(dir, `.${path12.basename(targetPath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
18
18
|
try {
|
|
19
19
|
if (typeof content === "string") {
|
|
20
20
|
await fsp.writeFile(tmp, content, { flag: "wx", encoding: opts.encoding ?? "utf8" });
|
|
@@ -53,9 +53,9 @@ async function ensureDir(dir) {
|
|
|
53
53
|
await fsp.mkdir(dir, { recursive: true });
|
|
54
54
|
}
|
|
55
55
|
async function withFileLock(targetPath, fn, opts = {}) {
|
|
56
|
-
const dir =
|
|
56
|
+
const dir = path12.dirname(targetPath);
|
|
57
57
|
await fsp.mkdir(dir, { recursive: true });
|
|
58
|
-
const lockPath =
|
|
58
|
+
const lockPath = path12.join(dir, `.${path12.basename(targetPath)}.lock`);
|
|
59
59
|
const timeoutMs = opts.timeoutMs ?? 5e3;
|
|
60
60
|
const staleMs = opts.staleMs ?? 3e4;
|
|
61
61
|
const started = Date.now();
|
|
@@ -233,11 +233,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
233
233
|
}
|
|
234
234
|
/** Absolute path to the session index file. */
|
|
235
235
|
get indexFile() {
|
|
236
|
-
return
|
|
236
|
+
return path12.join(this.dir, "_index.jsonl");
|
|
237
237
|
}
|
|
238
238
|
/** Join session ID to its absolute path within the store directory. */
|
|
239
239
|
sessionPath(id, ext) {
|
|
240
|
-
return
|
|
240
|
+
return path12.join(this.dir, `${id}${ext}`);
|
|
241
241
|
}
|
|
242
242
|
/**
|
|
243
243
|
* Ensure the directory implied by the session ID exists. When the ID
|
|
@@ -245,7 +245,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
245
245
|
* subdirectory so sessions group naturally by day.
|
|
246
246
|
*/
|
|
247
247
|
async ensureShardDir(id) {
|
|
248
|
-
const dirPath =
|
|
248
|
+
const dirPath = path12.dirname(path12.join(this.dir, id));
|
|
249
249
|
await ensureDir(dirPath);
|
|
250
250
|
return dirPath;
|
|
251
251
|
}
|
|
@@ -253,7 +253,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
253
253
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
254
254
|
const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt, meta.model ?? meta.provider);
|
|
255
255
|
const shardDir = await this.ensureShardDir(id);
|
|
256
|
-
const file =
|
|
256
|
+
const file = path12.join(shardDir, `${path12.basename(id)}.jsonl`);
|
|
257
257
|
let handle;
|
|
258
258
|
try {
|
|
259
259
|
handle = await fsp.open(file, "a", 384);
|
|
@@ -461,7 +461,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
461
461
|
continue;
|
|
462
462
|
if (entry.isDirectory()) {
|
|
463
463
|
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
464
|
-
ids.push(...await this.collectSessionIds(
|
|
464
|
+
ids.push(...await this.collectSessionIds(path12.join(dir, entry.name), childPrefix, depth + 1));
|
|
465
465
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
466
466
|
if (entry.name === "_index.jsonl") continue;
|
|
467
467
|
const base = entry.name.replace(/\.jsonl$/, "");
|
|
@@ -495,12 +495,12 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
495
495
|
async deleteSession(id) {
|
|
496
496
|
await fsp.unlink(this.sessionPath(id, ".jsonl")).catch(() => void 0);
|
|
497
497
|
await fsp.unlink(this.sessionPath(id, ".summary.json")).catch(() => void 0);
|
|
498
|
-
const shardDir =
|
|
499
|
-
const base =
|
|
498
|
+
const shardDir = path12.dirname(path12.join(this.dir, id));
|
|
499
|
+
const base = path12.basename(id);
|
|
500
500
|
for (const ext of [".plan.json", ".todos.json"]) {
|
|
501
|
-
await fsp.unlink(
|
|
501
|
+
await fsp.unlink(path12.join(shardDir, `${base}${ext}`)).catch(() => void 0);
|
|
502
502
|
}
|
|
503
|
-
const sessDir =
|
|
503
|
+
const sessDir = path12.join(shardDir, base);
|
|
504
504
|
await fsp.rm(sessDir, { recursive: true, force: true }).catch(() => void 0);
|
|
505
505
|
await this.writeTombstone(id);
|
|
506
506
|
}
|
|
@@ -512,7 +512,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
512
512
|
let deleted = 0;
|
|
513
513
|
let activeSessionId = null;
|
|
514
514
|
try {
|
|
515
|
-
const raw = await fsp.readFile(
|
|
515
|
+
const raw = await fsp.readFile(path12.join(this.dir, "active.json"), "utf8");
|
|
516
516
|
const active = JSON.parse(raw);
|
|
517
517
|
activeSessionId = active.sessionId ?? null;
|
|
518
518
|
} catch {
|
|
@@ -520,11 +520,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
520
520
|
const entries = await fsp.readdir(this.dir, { withFileTypes: true }).catch(() => []);
|
|
521
521
|
for (const entry of entries) {
|
|
522
522
|
if (!entry.isDirectory()) continue;
|
|
523
|
-
const dateDir =
|
|
523
|
+
const dateDir = path12.join(this.dir, entry.name);
|
|
524
524
|
const files = await fsp.readdir(dateDir, { withFileTypes: true }).catch(() => []);
|
|
525
525
|
for (const file of files) {
|
|
526
526
|
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
527
|
-
const jsonlPath =
|
|
527
|
+
const jsonlPath = path12.join(dateDir, file.name);
|
|
528
528
|
try {
|
|
529
529
|
const stat5 = await fsp.stat(jsonlPath);
|
|
530
530
|
if (stat5.mtimeMs >= cutoff) continue;
|
|
@@ -542,7 +542,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
542
542
|
}
|
|
543
543
|
for (const entry of entries) {
|
|
544
544
|
if (!entry.isDirectory()) continue;
|
|
545
|
-
const dateDir =
|
|
545
|
+
const dateDir = path12.join(this.dir, entry.name);
|
|
546
546
|
try {
|
|
547
547
|
const remaining = await fsp.readdir(dateDir);
|
|
548
548
|
if (remaining.length === 0) {
|
|
@@ -707,7 +707,7 @@ var FileSessionWriter = class {
|
|
|
707
707
|
this.meta = meta;
|
|
708
708
|
this.events = events;
|
|
709
709
|
this.resumed = opts.resumed ?? false;
|
|
710
|
-
this.manifestFile = opts.dir ?
|
|
710
|
+
this.manifestFile = opts.dir ? path12.join(opts.dir, `${path12.basename(id)}.summary.json`) : "";
|
|
711
711
|
this.filePath = opts.filePath ?? "";
|
|
712
712
|
this.secretScrubber = opts.secretScrubber;
|
|
713
713
|
this.onCloseCb = opts.onClose;
|
|
@@ -1027,7 +1027,7 @@ function userInputTitle(content) {
|
|
|
1027
1027
|
var QueueStore = class {
|
|
1028
1028
|
file;
|
|
1029
1029
|
constructor(opts) {
|
|
1030
|
-
this.file =
|
|
1030
|
+
this.file = path12.join(opts.dir, "queue.json");
|
|
1031
1031
|
}
|
|
1032
1032
|
async write(items) {
|
|
1033
1033
|
if (items.length === 0) {
|
|
@@ -1094,7 +1094,7 @@ var DefaultAttachmentStore = class {
|
|
|
1094
1094
|
let data = input.data;
|
|
1095
1095
|
if (this.spoolDir && bytes >= this.spoolThreshold) {
|
|
1096
1096
|
await fsp.mkdir(this.spoolDir, { recursive: true });
|
|
1097
|
-
spooledPath =
|
|
1097
|
+
spooledPath = path12.join(this.spoolDir, `${id}.bin`);
|
|
1098
1098
|
await atomicWrite(spooledPath, input.data, {
|
|
1099
1099
|
encoding: input.kind === "image" ? "base64" : "utf8"
|
|
1100
1100
|
});
|
|
@@ -1305,7 +1305,7 @@ var FileMemoryBackend = class {
|
|
|
1305
1305
|
}
|
|
1306
1306
|
async remember(scope, entry, filePath) {
|
|
1307
1307
|
const file = this.resolveFile(filePath, scope);
|
|
1308
|
-
await ensureDir(
|
|
1308
|
+
await ensureDir(path12.dirname(file));
|
|
1309
1309
|
let existing = "";
|
|
1310
1310
|
try {
|
|
1311
1311
|
existing = await fsp.readFile(file, "utf8");
|
|
@@ -2643,7 +2643,7 @@ var RecoveryLock = class {
|
|
|
2643
2643
|
sessionStore;
|
|
2644
2644
|
probe;
|
|
2645
2645
|
constructor(opts) {
|
|
2646
|
-
this.file =
|
|
2646
|
+
this.file = path12.join(opts.dir, LOCK_FILE);
|
|
2647
2647
|
this.pid = opts.pid ?? process.pid;
|
|
2648
2648
|
this.hostname = opts.hostname ?? os.hostname();
|
|
2649
2649
|
this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
@@ -2701,7 +2701,7 @@ var RecoveryLock = class {
|
|
|
2701
2701
|
* null return before calling this.
|
|
2702
2702
|
*/
|
|
2703
2703
|
async write(sessionId) {
|
|
2704
|
-
await ensureDir(
|
|
2704
|
+
await ensureDir(path12.dirname(this.file));
|
|
2705
2705
|
const lock = {
|
|
2706
2706
|
v: 1,
|
|
2707
2707
|
sessionId,
|
|
@@ -3188,7 +3188,7 @@ var AnnotationsStore = class {
|
|
|
3188
3188
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3189
3189
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3190
3190
|
}
|
|
3191
|
-
return
|
|
3191
|
+
return path12.join(this.dir, `${sessionId}.annotations.json`);
|
|
3192
3192
|
}
|
|
3193
3193
|
async readFile(sessionId) {
|
|
3194
3194
|
const fp = this.filePath(sessionId);
|
|
@@ -3345,7 +3345,7 @@ var ReplayLogStore = class {
|
|
|
3345
3345
|
out.push({
|
|
3346
3346
|
sessionId,
|
|
3347
3347
|
entryCount: all.length,
|
|
3348
|
-
path:
|
|
3348
|
+
path: path12.join(this.dir, name)
|
|
3349
3349
|
});
|
|
3350
3350
|
}
|
|
3351
3351
|
return out.sort((a, b) => a.sessionId.localeCompare(b.sessionId));
|
|
@@ -3355,7 +3355,7 @@ var ReplayLogStore = class {
|
|
|
3355
3355
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3356
3356
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3357
3357
|
}
|
|
3358
|
-
return
|
|
3358
|
+
return path12.join(this.dir, `${sessionId}.replay.jsonl`);
|
|
3359
3359
|
}
|
|
3360
3360
|
async readAll(sessionId) {
|
|
3361
3361
|
const fp = this.filePath(sessionId);
|
|
@@ -3544,7 +3544,7 @@ var SessionRecovery = class {
|
|
|
3544
3544
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3545
3545
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3546
3546
|
}
|
|
3547
|
-
return
|
|
3547
|
+
return path12.join(this.dir, `${sessionId}.jsonl`);
|
|
3548
3548
|
}
|
|
3549
3549
|
};
|
|
3550
3550
|
var GENESIS_PREV = "0".repeat(64);
|
|
@@ -3667,7 +3667,7 @@ var ToolAuditLog = class {
|
|
|
3667
3667
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3668
3668
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3669
3669
|
}
|
|
3670
|
-
return
|
|
3670
|
+
return path12.join(this.dir, `${sessionId}.audit.jsonl`);
|
|
3671
3671
|
}
|
|
3672
3672
|
async readAll(sessionId) {
|
|
3673
3673
|
const fp = this.filePath(sessionId);
|
|
@@ -3852,7 +3852,7 @@ var DefaultSessionRewinder = class {
|
|
|
3852
3852
|
sessionsDir;
|
|
3853
3853
|
projectRoot;
|
|
3854
3854
|
async listCheckpoints(sessionId) {
|
|
3855
|
-
const file =
|
|
3855
|
+
const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3856
3856
|
const raw = await fsp.readFile(file, "utf8");
|
|
3857
3857
|
const events = parseEvents(raw);
|
|
3858
3858
|
const fileCountMap = /* @__PURE__ */ new Map();
|
|
@@ -3877,7 +3877,7 @@ var DefaultSessionRewinder = class {
|
|
|
3877
3877
|
return checkpoints;
|
|
3878
3878
|
}
|
|
3879
3879
|
async rewindToCheckpoint(sessionId, checkpointIndex) {
|
|
3880
|
-
const file =
|
|
3880
|
+
const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3881
3881
|
const raw = await fsp.readFile(file, "utf8");
|
|
3882
3882
|
const events = parseEvents(raw);
|
|
3883
3883
|
let targetIdx = -1;
|
|
@@ -3912,7 +3912,7 @@ var DefaultSessionRewinder = class {
|
|
|
3912
3912
|
return { ...result, toPromptIndex: checkpointIndex, removedEvents };
|
|
3913
3913
|
}
|
|
3914
3914
|
async rewindLastN(sessionId, n) {
|
|
3915
|
-
const file =
|
|
3915
|
+
const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3916
3916
|
const raw = await fsp.readFile(file, "utf8");
|
|
3917
3917
|
const events = parseEvents(raw);
|
|
3918
3918
|
const checkpoints = [];
|
|
@@ -3941,7 +3941,7 @@ var DefaultSessionRewinder = class {
|
|
|
3941
3941
|
return { ...result, toPromptIndex: targetIndex, removedEvents: snapshotsToRevert.length };
|
|
3942
3942
|
}
|
|
3943
3943
|
async rewindToStart(sessionId) {
|
|
3944
|
-
const file =
|
|
3944
|
+
const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3945
3945
|
const raw = await fsp.readFile(file, "utf8");
|
|
3946
3946
|
const events = parseEvents(raw);
|
|
3947
3947
|
const allSnapshots = [];
|
|
@@ -3977,10 +3977,10 @@ async function revertSnapshots(snapshots, projectRoot) {
|
|
|
3977
3977
|
for (const snapshot of snapshots) {
|
|
3978
3978
|
for (const file of snapshot.files) {
|
|
3979
3979
|
try {
|
|
3980
|
-
const absPath =
|
|
3981
|
-
const root =
|
|
3982
|
-
const rel =
|
|
3983
|
-
if (rel.startsWith("..") ||
|
|
3980
|
+
const absPath = path12.resolve(file.path);
|
|
3981
|
+
const root = path12.resolve(projectRoot);
|
|
3982
|
+
const rel = path12.relative(root, absPath);
|
|
3983
|
+
if (rel.startsWith("..") || path12.isAbsolute(rel)) {
|
|
3984
3984
|
errors.push(`${file.path}: path resolves outside project root \u2014 skipping`);
|
|
3985
3985
|
continue;
|
|
3986
3986
|
}
|
|
@@ -4560,6 +4560,57 @@ var color = {
|
|
|
4560
4560
|
bgRed: wrap("41", "49"),
|
|
4561
4561
|
bgGreen: wrap("42", "49")
|
|
4562
4562
|
};
|
|
4563
|
+
function projectHash(absRoot) {
|
|
4564
|
+
return createHash("sha256").update(path12.resolve(absRoot)).digest("hex").slice(0, 12);
|
|
4565
|
+
}
|
|
4566
|
+
function projectSlug(absRoot) {
|
|
4567
|
+
const base = slugify(path12.basename(absRoot));
|
|
4568
|
+
const hash = createHash("sha256").update(path12.resolve(absRoot)).digest("hex").slice(0, 6);
|
|
4569
|
+
return `${base}-${hash}`;
|
|
4570
|
+
}
|
|
4571
|
+
function slugify(name) {
|
|
4572
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "project";
|
|
4573
|
+
}
|
|
4574
|
+
function resolveWstackPaths(opts) {
|
|
4575
|
+
const home = opts.userHome ?? os.homedir();
|
|
4576
|
+
const globalRoot = opts.globalRoot ?? path12.join(home, ".wrongstack");
|
|
4577
|
+
const hash = projectHash(opts.projectRoot);
|
|
4578
|
+
const slug = projectSlug(opts.projectRoot);
|
|
4579
|
+
const projectDir = path12.join(globalRoot, "projects", slug);
|
|
4580
|
+
return {
|
|
4581
|
+
globalRoot,
|
|
4582
|
+
configDir: globalRoot,
|
|
4583
|
+
globalConfig: path12.join(globalRoot, "config.json"),
|
|
4584
|
+
secretsKey: path12.join(globalRoot, ".key"),
|
|
4585
|
+
globalMemory: path12.join(globalRoot, "memory.md"),
|
|
4586
|
+
globalSkills: path12.join(globalRoot, "skills"),
|
|
4587
|
+
globalPrompts: path12.join(globalRoot, "prompts"),
|
|
4588
|
+
cacheDir: path12.join(globalRoot, "cache"),
|
|
4589
|
+
modelsCache: path12.join(globalRoot, "cache", "models.dev.json"),
|
|
4590
|
+
modelsOverlayCache: path12.join(globalRoot, "cache", "models-overlay.json"),
|
|
4591
|
+
historyFile: path12.join(globalRoot, "history"),
|
|
4592
|
+
logFile: path12.join(globalRoot, "logs", "wrongstack.log"),
|
|
4593
|
+
projectDir,
|
|
4594
|
+
projectCodebaseIndex: path12.join(projectDir, "codebase-index"),
|
|
4595
|
+
projectMemory: path12.join(projectDir, "memory.md"),
|
|
4596
|
+
projectSessions: path12.join(projectDir, "sessions"),
|
|
4597
|
+
projectTrust: path12.join(projectDir, "trust.json"),
|
|
4598
|
+
projectMeta: path12.join(projectDir, "meta.json"),
|
|
4599
|
+
projectLocalConfig: path12.join(projectDir, "config.local.json"),
|
|
4600
|
+
inProjectAgentsFile: path12.join(opts.projectRoot, ".wrongstack", "AGENTS.md"),
|
|
4601
|
+
inProjectSkills: path12.join(opts.projectRoot, ".wrongstack", "skills"),
|
|
4602
|
+
inProjectWorktrees: path12.join(opts.projectRoot, ".wrongstack", "worktrees"),
|
|
4603
|
+
projectHash: hash,
|
|
4604
|
+
projectSlug: slug,
|
|
4605
|
+
projectGoal: path12.join(projectDir, "goal.json"),
|
|
4606
|
+
projectSpecs: path12.join(projectDir, "specs"),
|
|
4607
|
+
projectTaskGraphs: path12.join(projectDir, "task-graphs"),
|
|
4608
|
+
projectSddSession: path12.join(projectDir, "sdd-session.json"),
|
|
4609
|
+
projectPlan: path12.join(projectDir, "plan.json"),
|
|
4610
|
+
projectAutophase: path12.join(projectDir, "autophase"),
|
|
4611
|
+
syncConfig: path12.join(globalRoot, "sync.json")
|
|
4612
|
+
};
|
|
4613
|
+
}
|
|
4563
4614
|
|
|
4564
4615
|
// src/types/errors.ts
|
|
4565
4616
|
var ERROR_CODES = {
|
|
@@ -4614,8 +4665,7 @@ var FsError = class extends WrongStackError {
|
|
|
4614
4665
|
// src/storage/goal-store.ts
|
|
4615
4666
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
4616
4667
|
function goalFilePath(projectRoot) {
|
|
4617
|
-
|
|
4618
|
-
return path2.join(os.homedir(), ".wrongstack", "projects", hash, "goal.json");
|
|
4668
|
+
return resolveWstackPaths({ projectRoot }).projectGoal;
|
|
4619
4669
|
}
|
|
4620
4670
|
async function loadGoal(filePath) {
|
|
4621
4671
|
let raw;
|
|
@@ -4801,7 +4851,7 @@ var DefaultPromptStore = class {
|
|
|
4801
4851
|
if (!file.endsWith(".json")) continue;
|
|
4802
4852
|
try {
|
|
4803
4853
|
const raw = JSON.parse(
|
|
4804
|
-
await fsp.readFile(
|
|
4854
|
+
await fsp.readFile(path12.join(this.dir, file), "utf8")
|
|
4805
4855
|
);
|
|
4806
4856
|
entries.push(raw.entry);
|
|
4807
4857
|
} catch {
|
|
@@ -4814,7 +4864,7 @@ var DefaultPromptStore = class {
|
|
|
4814
4864
|
);
|
|
4815
4865
|
}
|
|
4816
4866
|
async get(id) {
|
|
4817
|
-
const file =
|
|
4867
|
+
const file = path12.join(this.dir, `${id}.json`);
|
|
4818
4868
|
try {
|
|
4819
4869
|
const raw = JSON.parse(await fsp.readFile(file, "utf8"));
|
|
4820
4870
|
return raw.entry;
|
|
@@ -4824,12 +4874,12 @@ var DefaultPromptStore = class {
|
|
|
4824
4874
|
}
|
|
4825
4875
|
async save(entry) {
|
|
4826
4876
|
await ensureDir(this.dir);
|
|
4827
|
-
const file =
|
|
4877
|
+
const file = path12.join(this.dir, `${entry.id}.json`);
|
|
4828
4878
|
const raw = { version: 1, entry };
|
|
4829
4879
|
await atomicWrite(file, JSON.stringify(raw, null, 2));
|
|
4830
4880
|
}
|
|
4831
4881
|
async delete(id) {
|
|
4832
|
-
const file =
|
|
4882
|
+
const file = path12.join(this.dir, `${id}.json`);
|
|
4833
4883
|
try {
|
|
4834
4884
|
await fsp.unlink(file);
|
|
4835
4885
|
return true;
|
|
@@ -4863,7 +4913,7 @@ var CloudSync = class {
|
|
|
4863
4913
|
this.paths = paths;
|
|
4864
4914
|
this.getConfig = getConfig;
|
|
4865
4915
|
this.setConfig = setConfig;
|
|
4866
|
-
this.statePath =
|
|
4916
|
+
this.statePath = path12.join(paths.globalRoot, "sync-state.json");
|
|
4867
4917
|
}
|
|
4868
4918
|
paths;
|
|
4869
4919
|
getConfig;
|
|
@@ -4970,7 +5020,7 @@ var CloudSync = class {
|
|
|
4970
5020
|
const rel = segments.slice(2).join("/");
|
|
4971
5021
|
const destPath = resolvePulledCategoryPath(cat, localPath, rel, entry.path);
|
|
4972
5022
|
const blobData = await this.getBlob(token, owner, repoName, entry.sha);
|
|
4973
|
-
await fsp.mkdir(
|
|
5023
|
+
await fsp.mkdir(path12.dirname(destPath), { recursive: true });
|
|
4974
5024
|
await fsp.writeFile(destPath, Buffer.from(blobData, "base64"));
|
|
4975
5025
|
}
|
|
4976
5026
|
const localRev = await this.hashLocalCategories(cfg.categories);
|
|
@@ -5077,7 +5127,7 @@ var CloudSync = class {
|
|
|
5077
5127
|
const files = await this.walkDir(localPath, localPath);
|
|
5078
5128
|
for (const file of files) {
|
|
5079
5129
|
const content = await fsp.readFile(file, "utf8");
|
|
5080
|
-
const rel =
|
|
5130
|
+
const rel = path12.relative(localPath, file).replace(/\\/g, "/");
|
|
5081
5131
|
entries.push({ path: `data/${cat}/${rel}`, content, mode: "100644" });
|
|
5082
5132
|
hashes.push(content);
|
|
5083
5133
|
}
|
|
@@ -5134,7 +5184,7 @@ var CloudSync = class {
|
|
|
5134
5184
|
const results = [];
|
|
5135
5185
|
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
5136
5186
|
for (const entry of entries) {
|
|
5137
|
-
const full =
|
|
5187
|
+
const full = path12.join(dir, entry.name);
|
|
5138
5188
|
if (entry.isDirectory()) {
|
|
5139
5189
|
results.push(...await this.walkDir(full, base));
|
|
5140
5190
|
} else {
|
|
@@ -5151,15 +5201,15 @@ function resolvePulledCategoryPath(cat, localPath, rel, remotePath) {
|
|
|
5151
5201
|
return localPath;
|
|
5152
5202
|
}
|
|
5153
5203
|
if (!rel) return localPath;
|
|
5154
|
-
const normalizedRel =
|
|
5155
|
-
const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${
|
|
5156
|
-
if (
|
|
5204
|
+
const normalizedRel = path12.normalize(rel);
|
|
5205
|
+
const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${path12.sep}`);
|
|
5206
|
+
if (path12.isAbsolute(normalizedRel) || traversesUp) {
|
|
5157
5207
|
throw new Error(`Refusing CloudSync path traversal: ${remotePath}`);
|
|
5158
5208
|
}
|
|
5159
|
-
const dest =
|
|
5160
|
-
const root =
|
|
5161
|
-
const relative3 =
|
|
5162
|
-
if (relative3.startsWith("..") ||
|
|
5209
|
+
const dest = path12.resolve(localPath, normalizedRel);
|
|
5210
|
+
const root = path12.resolve(localPath);
|
|
5211
|
+
const relative3 = path12.relative(root, dest);
|
|
5212
|
+
if (relative3.startsWith("..") || path12.isAbsolute(relative3)) {
|
|
5163
5213
|
throw new Error(`Refusing CloudSync path outside category root: ${remotePath}`);
|
|
5164
5214
|
}
|
|
5165
5215
|
return dest;
|