@wrongstack/core 0.8.6 → 0.9.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/defaults/index.d.ts +1 -1
- package/dist/defaults/index.js +17 -4
- package/dist/defaults/index.js.map +1 -1
- package/dist/{index-BvZld4Dr.d.ts → index-Dl3PaD7f.d.ts} +9 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +110 -53
- package/dist/index.js.map +1 -1
- package/dist/kernel/index.d.ts +1 -1
- package/dist/{plan-templates-Cqdy6rtM.d.ts → plan-templates-Cc-04Z8o.d.ts} +8 -3
- package/dist/storage/index.d.ts +5 -2
- package/dist/storage/index.js +32 -10
- package/dist/storage/index.js.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/kernel/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { B as BindOptions, C as Container, D as Decorator, F as Factory, M as Middleware, b as MiddlewareHandler, N as NextFn, P as Pipeline, d as PipelineOptions, T as Token } from '../system-prompt-CWA6ml-d.js';
|
|
2
2
|
export { E as EventBus, a as EventLogger, b as EventMap, c as EventName, L as Listener, S as ScopedEventBus } from '../events-yCpJD4wa.js';
|
|
3
|
-
export { R as RunController, b as RunControllerOptions, T as TOKENS } from '../index-
|
|
3
|
+
export { R as RunController, b as RunControllerOptions, T as TOKENS } from '../index-Dl3PaD7f.js';
|
|
4
4
|
import '../context-z2x5gv_V.js';
|
|
5
5
|
import '../compactor-Mw7-rNyb.js';
|
|
6
6
|
import '../config-Bi4Q0fnz.js';
|
|
@@ -331,9 +331,14 @@ declare class RecoveryLock {
|
|
|
331
331
|
*/
|
|
332
332
|
checkAbandoned(): Promise<AbandonedSession | null>;
|
|
333
333
|
/**
|
|
334
|
-
* Claim the lock for the given session.
|
|
335
|
-
*
|
|
336
|
-
* `checkAbandoned`
|
|
334
|
+
* Claim the lock for the given session. Uses exclusive-create (`O_EXCL`)
|
|
335
|
+
* to detect whether another process acquired the lock between our
|
|
336
|
+
* `checkAbandoned()` call and now. If the file already exists, it means
|
|
337
|
+
* another process won the race and we throw instead of silently
|
|
338
|
+
* overwriting their recovery record.
|
|
339
|
+
*
|
|
340
|
+
* The caller MUST have already called `checkAbandoned()` and handled its
|
|
341
|
+
* null return before calling this.
|
|
337
342
|
*/
|
|
338
343
|
write(sessionId: string): Promise<void>;
|
|
339
344
|
/**
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, M as MemoryStoreOptions, j as MigrationContext, k as MigrationResult, P as PersistedQueueItem, l as PlanFile, m as PlanItem, n as PlanTemplate, Q as QueueStore, R as RecoveryLock, o as RecoveryLockOptions, S as SessionAnalyzer, p as SessionStoreOptions, T as TodosCheckpointFile, q as addPlanItem, r as attachPlanCheckpoint, s as attachTodosCheckpoint, t as clearPlan, u as deriveTodosFromPlanItem, v as emptyPlan, w as formatPlan, x as formatPlanTemplates, y as getPlanTemplate, z as listPlanTemplates, B as loadPlan, E as loadTodosCheckpoint, F as removePlanItem, G as runConfigMigrations, H as savePlan, I as saveTodosCheckpoint, J as setPlanItemStatus } from '../plan-templates-
|
|
1
|
+
export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, M as MemoryStoreOptions, j as MigrationContext, k as MigrationResult, P as PersistedQueueItem, l as PlanFile, m as PlanItem, n as PlanTemplate, Q as QueueStore, R as RecoveryLock, o as RecoveryLockOptions, S as SessionAnalyzer, p as SessionStoreOptions, T as TodosCheckpointFile, q as addPlanItem, r as attachPlanCheckpoint, s as attachTodosCheckpoint, t as clearPlan, u as deriveTodosFromPlanItem, v as emptyPlan, w as formatPlan, x as formatPlanTemplates, y as getPlanTemplate, z as listPlanTemplates, B as loadPlan, E as loadTodosCheckpoint, F as removePlanItem, G as runConfigMigrations, H as savePlan, I as saveTodosCheckpoint, J as setPlanItemStatus } from '../plan-templates-Cc-04Z8o.js';
|
|
2
2
|
export { D as DefaultSessionReader } from '../session-reader-DsadjyF9.js';
|
|
3
3
|
import { S as SessionRewinder, C as CheckpointInfo, a as RewindResultExtended } from '../session-rewinder-C9HnMkhP.js';
|
|
4
4
|
export { D as DirectorStateCheckpoint, a as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-BmYi3DGA.js';
|
|
@@ -13,6 +13,8 @@ import '../secret-vault-DoISxaKO.js';
|
|
|
13
13
|
|
|
14
14
|
interface SessionRewinderOptions {
|
|
15
15
|
sessionsDir: string;
|
|
16
|
+
/** The project root directory; used to validate rewind targets stay inside it. */
|
|
17
|
+
projectRoot: string;
|
|
16
18
|
}
|
|
17
19
|
/**
|
|
18
20
|
* Rewind engine that reads session JSONL files and reverts file system
|
|
@@ -20,7 +22,8 @@ interface SessionRewinderOptions {
|
|
|
20
22
|
*/
|
|
21
23
|
declare class DefaultSessionRewinder implements SessionRewinder {
|
|
22
24
|
private readonly sessionsDir;
|
|
23
|
-
|
|
25
|
+
private readonly projectRoot;
|
|
26
|
+
constructor(sessionsDir: string, projectRoot: string);
|
|
24
27
|
listCheckpoints(sessionId: string): Promise<CheckpointInfo[]>;
|
|
25
28
|
rewindToCheckpoint(sessionId: string, checkpointIndex: number): Promise<RewindResultExtended>;
|
|
26
29
|
rewindLastN(sessionId: string, n: number): Promise<RewindResultExtended>;
|
package/dist/storage/index.js
CHANGED
|
@@ -68,7 +68,7 @@ async function renameWithRetry(from, to) {
|
|
|
68
68
|
if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {
|
|
69
69
|
throw err;
|
|
70
70
|
}
|
|
71
|
-
await new Promise((
|
|
71
|
+
await new Promise((resolve3) => setTimeout(resolve3, delays[i]));
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
throw lastErr;
|
|
@@ -1488,9 +1488,14 @@ var RecoveryLock = class {
|
|
|
1488
1488
|
};
|
|
1489
1489
|
}
|
|
1490
1490
|
/**
|
|
1491
|
-
* Claim the lock for the given session.
|
|
1492
|
-
*
|
|
1493
|
-
* `checkAbandoned`
|
|
1491
|
+
* Claim the lock for the given session. Uses exclusive-create (`O_EXCL`)
|
|
1492
|
+
* to detect whether another process acquired the lock between our
|
|
1493
|
+
* `checkAbandoned()` call and now. If the file already exists, it means
|
|
1494
|
+
* another process won the race and we throw instead of silently
|
|
1495
|
+
* overwriting their recovery record.
|
|
1496
|
+
*
|
|
1497
|
+
* The caller MUST have already called `checkAbandoned()` and handled its
|
|
1498
|
+
* null return before calling this.
|
|
1494
1499
|
*/
|
|
1495
1500
|
async write(sessionId) {
|
|
1496
1501
|
await ensureDir(path2.dirname(this.file));
|
|
@@ -1501,7 +1506,15 @@ var RecoveryLock = class {
|
|
|
1501
1506
|
hostname: this.hostname,
|
|
1502
1507
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1503
1508
|
};
|
|
1504
|
-
|
|
1509
|
+
try {
|
|
1510
|
+
await fsp.writeFile(this.file, JSON.stringify(lock), { flag: "wx", mode: 384 });
|
|
1511
|
+
} catch (err) {
|
|
1512
|
+
const code = err.code;
|
|
1513
|
+
if (code === "EEXIST") {
|
|
1514
|
+
throw new Error(`Recovery lock already held by another process`);
|
|
1515
|
+
}
|
|
1516
|
+
throw err;
|
|
1517
|
+
}
|
|
1505
1518
|
}
|
|
1506
1519
|
/**
|
|
1507
1520
|
* Release the lock. Idempotent — silently succeeds if the file is
|
|
@@ -1945,10 +1958,12 @@ var SessionAnalyzer = class {
|
|
|
1945
1958
|
}
|
|
1946
1959
|
};
|
|
1947
1960
|
var DefaultSessionRewinder = class {
|
|
1948
|
-
constructor(sessionsDir) {
|
|
1961
|
+
constructor(sessionsDir, projectRoot) {
|
|
1949
1962
|
this.sessionsDir = sessionsDir;
|
|
1963
|
+
this.projectRoot = projectRoot;
|
|
1950
1964
|
}
|
|
1951
1965
|
sessionsDir;
|
|
1966
|
+
projectRoot;
|
|
1952
1967
|
async listCheckpoints(sessionId) {
|
|
1953
1968
|
const file = path2.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
1954
1969
|
const raw = await fsp.readFile(file, "utf8");
|
|
@@ -2005,7 +2020,7 @@ var DefaultSessionRewinder = class {
|
|
|
2005
2020
|
}
|
|
2006
2021
|
}
|
|
2007
2022
|
}
|
|
2008
|
-
const result = await revertSnapshots(snapshotsToRevert);
|
|
2023
|
+
const result = await revertSnapshots(snapshotsToRevert, this.projectRoot);
|
|
2009
2024
|
const removedEvents = events.length - targetIdx - 1;
|
|
2010
2025
|
return { ...result, toPromptIndex: checkpointIndex, removedEvents };
|
|
2011
2026
|
}
|
|
@@ -2035,7 +2050,7 @@ var DefaultSessionRewinder = class {
|
|
|
2035
2050
|
snapshotsToRevert.push({ promptIndex: event.promptIndex, files: event.files });
|
|
2036
2051
|
}
|
|
2037
2052
|
}
|
|
2038
|
-
const result = await revertSnapshots(snapshotsToRevert.reverse());
|
|
2053
|
+
const result = await revertSnapshots(snapshotsToRevert.reverse(), this.projectRoot);
|
|
2039
2054
|
return { ...result, toPromptIndex: targetIndex, removedEvents: snapshotsToRevert.length };
|
|
2040
2055
|
}
|
|
2041
2056
|
async rewindToStart(sessionId) {
|
|
@@ -2051,7 +2066,7 @@ var DefaultSessionRewinder = class {
|
|
|
2051
2066
|
if (allSnapshots.length === 0) {
|
|
2052
2067
|
return { revertedFiles: [], errors: [], toPromptIndex: 0, removedEvents: 0 };
|
|
2053
2068
|
}
|
|
2054
|
-
const result = await revertSnapshots(allSnapshots.reverse());
|
|
2069
|
+
const result = await revertSnapshots(allSnapshots.reverse(), this.projectRoot);
|
|
2055
2070
|
return { ...result, toPromptIndex: 0, removedEvents: allSnapshots.length };
|
|
2056
2071
|
}
|
|
2057
2072
|
};
|
|
@@ -2069,12 +2084,19 @@ function parseEvents(raw) {
|
|
|
2069
2084
|
}
|
|
2070
2085
|
return events;
|
|
2071
2086
|
}
|
|
2072
|
-
async function revertSnapshots(snapshots) {
|
|
2087
|
+
async function revertSnapshots(snapshots, projectRoot) {
|
|
2073
2088
|
const revertedFiles = [];
|
|
2074
2089
|
const errors = [];
|
|
2075
2090
|
for (const snapshot of snapshots) {
|
|
2076
2091
|
for (const file of snapshot.files) {
|
|
2077
2092
|
try {
|
|
2093
|
+
const absPath = path2.resolve(file.path);
|
|
2094
|
+
const root = path2.resolve(projectRoot);
|
|
2095
|
+
const rel = path2.relative(root, absPath);
|
|
2096
|
+
if (rel.startsWith("..") || path2.isAbsolute(rel)) {
|
|
2097
|
+
errors.push(`${file.path}: path resolves outside project root \u2014 skipping`);
|
|
2098
|
+
continue;
|
|
2099
|
+
}
|
|
2078
2100
|
if (file.action === "deleted") {
|
|
2079
2101
|
if (file.before !== null) {
|
|
2080
2102
|
await atomicWrite(file.path, file.before, { mode: 420 });
|