@namzu/sdk 20.0.0 → 20.1.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/CHANGELOG.md +61 -0
- package/dist/contracts/a2a.d.ts +2 -2
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +11 -0
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/public-runtime.d.ts +3 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +7 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/store/index.d.ts +3 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +12 -0
- package/dist/store/index.js.map +1 -1
- package/dist/store/run/checkpoint-disk.d.ts +56 -2
- package/dist/store/run/checkpoint-disk.d.ts.map +1 -1
- package/dist/store/run/checkpoint-disk.js +83 -2
- package/dist/store/run/checkpoint-disk.js.map +1 -1
- package/dist/store/run/checkpoint-memory.d.ts +31 -0
- package/dist/store/run/checkpoint-memory.d.ts.map +1 -0
- package/dist/store/run/checkpoint-memory.js +83 -0
- package/dist/store/run/checkpoint-memory.js.map +1 -0
- package/dist/store/run/disk.d.ts +53 -0
- package/dist/store/run/disk.d.ts.map +1 -1
- package/dist/store/run/disk.js +73 -30
- package/dist/store/run/disk.js.map +1 -1
- package/dist/store/run/listing.d.ts +75 -0
- package/dist/store/run/listing.d.ts.map +1 -0
- package/dist/store/run/listing.js +183 -0
- package/dist/store/run/listing.js.map +1 -0
- package/dist/types/run/checkpoint-store.d.ts +210 -1
- package/dist/types/run/checkpoint-store.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/manager/run/persistence.ts +18 -4
- package/src/public-runtime.ts +13 -0
- package/src/store/index.ts +18 -0
- package/src/store/run/checkpoint-disk.ts +128 -4
- package/src/store/run/checkpoint-memory.ts +101 -0
- package/src/store/run/disk.ts +72 -27
- package/src/store/run/listing.ts +229 -0
- package/src/types/run/checkpoint-store.ts +221 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { assertContiguousListingScope, paginateDurableRuns, toDurableRunEntry } from './listing.js';
|
|
2
|
+
/**
|
|
3
|
+
* Process-local {@link CheckpointStore}, keyed by the full five-layer scope.
|
|
4
|
+
*
|
|
5
|
+
* Shipped rather than left as a test fixture for two reasons. It is the
|
|
6
|
+
* reference a host reads when writing a backend of its own — the disk store
|
|
7
|
+
* is path-addressed and answers "what does an attribution-keyed store look
|
|
8
|
+
* like" with a directory layout, which is the wrong lesson. And it is the
|
|
9
|
+
* only implementation that can hold more than one tenant at once, because
|
|
10
|
+
* the disk layout has no tenant in it: a test that two tenants' listings
|
|
11
|
+
* stay separate is not expressible against disk, and a rule that cannot be
|
|
12
|
+
* tested on the store a host will actually inject is a rule on paper.
|
|
13
|
+
*
|
|
14
|
+
* Not durable, deliberately: it is for tests, for a single-process host that
|
|
15
|
+
* genuinely wants checkpoints to die with the process, and as the parity
|
|
16
|
+
* partner that proves the listing contract is not a filesystem in disguise.
|
|
17
|
+
*/
|
|
18
|
+
export class InMemoryCheckpointStore {
|
|
19
|
+
/** `tenant/project/session/run` → checkpoint id → checkpoint. */
|
|
20
|
+
runs = new Map();
|
|
21
|
+
/** Same key → the run's scope, so a listing can rebuild an addressable entry. */
|
|
22
|
+
scopes = new Map();
|
|
23
|
+
key(scope) {
|
|
24
|
+
return [scope.tenantId, scope.projectId, scope.sessionId, scope.runId].join('/');
|
|
25
|
+
}
|
|
26
|
+
async writeCheckpoint(scope, checkpoint) {
|
|
27
|
+
const key = this.key(scope);
|
|
28
|
+
let run = this.runs.get(key);
|
|
29
|
+
if (!run) {
|
|
30
|
+
run = new Map();
|
|
31
|
+
this.runs.set(key, run);
|
|
32
|
+
}
|
|
33
|
+
// The run's scope is kept beside its checkpoints because the key is a
|
|
34
|
+
// joined string and a listing has to hand back the parts — above all
|
|
35
|
+
// `parentRunId`, which is what makes a sub-run's row addressable.
|
|
36
|
+
//
|
|
37
|
+
// Written on every call rather than only the first, and that is
|
|
38
|
+
// simplicity, not defence: a run's scope is fixed when the run is
|
|
39
|
+
// constructed, so the two cannot differ, and a `has` guard here would
|
|
40
|
+
// be a branch no input can take.
|
|
41
|
+
this.scopes.set(key, {
|
|
42
|
+
tenantId: scope.tenantId,
|
|
43
|
+
projectId: scope.projectId,
|
|
44
|
+
sessionId: scope.sessionId,
|
|
45
|
+
runId: scope.runId,
|
|
46
|
+
...(scope.parentRunId ? { parentRunId: scope.parentRunId } : {}),
|
|
47
|
+
});
|
|
48
|
+
run.set(checkpoint.id, checkpoint);
|
|
49
|
+
}
|
|
50
|
+
async readCheckpoint(scope, checkpointId) {
|
|
51
|
+
return this.runs.get(this.key(scope))?.get(checkpointId) ?? null;
|
|
52
|
+
}
|
|
53
|
+
async listCheckpoints(scope) {
|
|
54
|
+
const run = this.runs.get(this.key(scope));
|
|
55
|
+
if (!run)
|
|
56
|
+
return [];
|
|
57
|
+
return [...run.values()].sort((a, b) => a.createdAt - b.createdAt);
|
|
58
|
+
}
|
|
59
|
+
async deleteCheckpoint(scope, checkpointId) {
|
|
60
|
+
this.runs.get(this.key(scope))?.delete(checkpointId);
|
|
61
|
+
}
|
|
62
|
+
async listDurableRuns(scope, options) {
|
|
63
|
+
assertContiguousListingScope(scope, 'InMemoryCheckpointStore.listDurableRuns');
|
|
64
|
+
const now = options?.now ?? Date.now();
|
|
65
|
+
const entries = [];
|
|
66
|
+
for (const [key, checkpoints] of this.runs) {
|
|
67
|
+
const runScope = this.scopes.get(key);
|
|
68
|
+
if (!runScope)
|
|
69
|
+
continue;
|
|
70
|
+
if (runScope.tenantId !== scope.tenantId)
|
|
71
|
+
continue;
|
|
72
|
+
if (scope.projectId !== undefined && runScope.projectId !== scope.projectId)
|
|
73
|
+
continue;
|
|
74
|
+
if (scope.sessionId !== undefined && runScope.sessionId !== scope.sessionId)
|
|
75
|
+
continue;
|
|
76
|
+
const entry = toDurableRunEntry(runScope, [...checkpoints.values()], now);
|
|
77
|
+
if (entry)
|
|
78
|
+
entries.push(entry);
|
|
79
|
+
}
|
|
80
|
+
return paginateDurableRuns(entries, options);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=checkpoint-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint-memory.js","sourceRoot":"","sources":["../../../src/store/run/checkpoint-memory.ts"],"names":[],"mappings":"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"}
|
package/dist/store/run/disk.d.ts
CHANGED
|
@@ -40,6 +40,29 @@ export declare class RunDiskStore {
|
|
|
40
40
|
readCheckpoint(checkpointId: CheckpointId): Promise<IterationCheckpoint | null>;
|
|
41
41
|
listCheckpoints(): Promise<IterationCheckpoint[]>;
|
|
42
42
|
deleteCheckpoint(checkpointId: CheckpointId): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* @deprecated Superseded by
|
|
45
|
+
* {@link import('../../types/run/checkpoint-store.js').CheckpointStore.listDurableRuns},
|
|
46
|
+
* reached through {@link import('./listing.js').listDurableRuns}.
|
|
47
|
+
* Removed in the next major.
|
|
48
|
+
*
|
|
49
|
+
* Three things are wrong with `index.json` as the answer to "which runs
|
|
50
|
+
* are there":
|
|
51
|
+
*
|
|
52
|
+
* 1. Its entries carry no tenant, project or session, so a row cannot be
|
|
53
|
+
* turned back into an addressable scope — nothing can be resumed or
|
|
54
|
+
* swept from it.
|
|
55
|
+
* 2. `addToIndex` skips every sub-run, so an inbox built on it drops
|
|
56
|
+
* every approval raised by delegated work, and the symptom looks like
|
|
57
|
+
* a hung specialist rather than a blind listing.
|
|
58
|
+
* 3. It is a catalogue of runs that STARTED, not of runs with durable
|
|
59
|
+
* state, so it cannot tell a run something could resume from one that
|
|
60
|
+
* left nothing behind.
|
|
61
|
+
*
|
|
62
|
+
* Deprecated for one minor rather than deleted outright: this is public
|
|
63
|
+
* surface and a consumer calling it today gets real data back, so the
|
|
64
|
+
* deprecate-before-you-remove rule applies.
|
|
65
|
+
*/
|
|
43
66
|
static listRuns(baseDir: string): Promise<Array<{
|
|
44
67
|
id: string;
|
|
45
68
|
agentName: string;
|
|
@@ -49,4 +72,34 @@ export declare class RunDiskStore {
|
|
|
49
72
|
}>>;
|
|
50
73
|
addToIndex(run: Run): Promise<void>;
|
|
51
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Every checkpoint stored under one run directory, ascending by `createdAt`.
|
|
77
|
+
*
|
|
78
|
+
* A free function rather than a method because the scope-level listing walks
|
|
79
|
+
* run directories it has never bound a {@link RunDiskStore} to — and binding
|
|
80
|
+
* one would CREATE the directory, which is not something a read should do.
|
|
81
|
+
* Sharing the function is what keeps the two read paths from disagreeing
|
|
82
|
+
* about what a damaged file means.
|
|
83
|
+
*
|
|
84
|
+
* An unreadable checkpoint used to be logged and skipped, so this returned a
|
|
85
|
+
* silently short list that four callers treat as complete. A missing NEWEST
|
|
86
|
+
* checkpoint quietly resumes from an older point and re-runs a whole
|
|
87
|
+
* iteration of tool calls; a missing PARKED one reports "not parked" and
|
|
88
|
+
* drops an approval a human already granted, because the file is the only
|
|
89
|
+
* durable record of a park. Pruning under-deletes too: a file the keep-count
|
|
90
|
+
* cannot see is immortal. The by-id read next door was already strict, and
|
|
91
|
+
* two read paths disagreeing about whether damage matters is how the lenient
|
|
92
|
+
* one gets trusted.
|
|
93
|
+
*
|
|
94
|
+
* The same reasoning carries up to the listing, which is why the throw
|
|
95
|
+
* propagates there rather than dropping the run: a damaged checkpoint that
|
|
96
|
+
* removed a run from an approval inbox is the missing-park failure again,
|
|
97
|
+
* one level up.
|
|
98
|
+
*
|
|
99
|
+
* A missing `checkpoints/` directory is the only absence that reads as
|
|
100
|
+
* empty — the run genuinely has none. A file that disappears BETWEEN the
|
|
101
|
+
* directory listing and its read throws, where the old shape returned the
|
|
102
|
+
* empty array and discarded every checkpoint it had already parsed.
|
|
103
|
+
*/
|
|
104
|
+
export declare function readCheckpointsIn(runDir: string): Promise<IterationCheckpoint[]>;
|
|
52
105
|
//# sourceMappingURL=disk.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disk.d.ts","sourceRoot":"","sources":["../../../src/store/run/disk.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAClF,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAe7E,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CACzB;AAED,qBAAa,YAAY;IACxB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,SAAS,CAAmC;gBAExC,MAAM,EAAE,cAAc;IAKlC,OAAO,CAAC,WAAW;IAOb,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7D,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjD;;;;;;;;;;;;;;OAcG;IACG,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IA0C/D,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BrC,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASnD,SAAS,IAAI,MAAM,GAAG,IAAI;IAIpB,eAAe,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/D,cAAc,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAW/E,eAAe,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"disk.d.ts","sourceRoot":"","sources":["../../../src/store/run/disk.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAClF,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAe7E,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CACzB;AAED,qBAAa,YAAY;IACxB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,SAAS,CAAmC;gBAExC,MAAM,EAAE,cAAc;IAKlC,OAAO,CAAC,WAAW;IAOb,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7D,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjD;;;;;;;;;;;;;;OAcG;IACG,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IA0C/D,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BrC,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASnD,SAAS,IAAI,MAAM,GAAG,IAAI;IAIpB,eAAe,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/D,cAAc,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAW/E,eAAe,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAIjD,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IASjE;;;;;;;;;;;;;;;;;;;;;;OAsBG;WACU,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAC9C,KAAK,CAAC;QACL,EAAE,EAAE,MAAM,CAAA;QACV,SAAS,EAAE,MAAM,CAAA;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,SAAS,EAAE,MAAM,CAAA;QACjB,OAAO,CAAC,EAAE,MAAM,CAAA;KAChB,CAAC,CACF;IAWK,UAAU,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CA8CzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAiBtF"}
|
package/dist/store/run/disk.js
CHANGED
|
@@ -169,36 +169,7 @@ export class RunDiskStore {
|
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
async listCheckpoints() {
|
|
172
|
-
|
|
173
|
-
const cpDir = join(dir, 'checkpoints');
|
|
174
|
-
try {
|
|
175
|
-
const files = await readdir(cpDir);
|
|
176
|
-
const checkpoints = [];
|
|
177
|
-
for (const file of files) {
|
|
178
|
-
if (!file.endsWith('.json'))
|
|
179
|
-
continue;
|
|
180
|
-
// An unreadable checkpoint used to be logged and skipped, so
|
|
181
|
-
// this returned a silently short list that four callers treat
|
|
182
|
-
// as complete. A missing NEWEST checkpoint quietly resumes
|
|
183
|
-
// from an older point and re-runs a whole iteration of tool
|
|
184
|
-
// calls; a missing PARKED one reports "not parked" and drops
|
|
185
|
-
// an approval a human already granted, because the file is
|
|
186
|
-
// the only durable record of a park. Pruning under-deletes
|
|
187
|
-
// too: a file the keep-count cannot see is immortal.
|
|
188
|
-
//
|
|
189
|
-
// The by-id read next door was already strict. Two read paths
|
|
190
|
-
// disagreeing about whether damage matters is how the lenient
|
|
191
|
-
// one gets trusted.
|
|
192
|
-
const content = await readFile(join(cpDir, file), 'utf-8');
|
|
193
|
-
checkpoints.push(parseCheckpoint(content, file));
|
|
194
|
-
}
|
|
195
|
-
return checkpoints.sort((a, b) => a.createdAt - b.createdAt);
|
|
196
|
-
}
|
|
197
|
-
catch (err) {
|
|
198
|
-
if (isFileNotFound(err))
|
|
199
|
-
return [];
|
|
200
|
-
throw err;
|
|
201
|
-
}
|
|
172
|
+
return readCheckpointsIn(this.requireInit());
|
|
202
173
|
}
|
|
203
174
|
async deleteCheckpoint(checkpointId) {
|
|
204
175
|
const dir = this.requireInit();
|
|
@@ -210,6 +181,29 @@ export class RunDiskStore {
|
|
|
210
181
|
throw err;
|
|
211
182
|
}
|
|
212
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* @deprecated Superseded by
|
|
186
|
+
* {@link import('../../types/run/checkpoint-store.js').CheckpointStore.listDurableRuns},
|
|
187
|
+
* reached through {@link import('./listing.js').listDurableRuns}.
|
|
188
|
+
* Removed in the next major.
|
|
189
|
+
*
|
|
190
|
+
* Three things are wrong with `index.json` as the answer to "which runs
|
|
191
|
+
* are there":
|
|
192
|
+
*
|
|
193
|
+
* 1. Its entries carry no tenant, project or session, so a row cannot be
|
|
194
|
+
* turned back into an addressable scope — nothing can be resumed or
|
|
195
|
+
* swept from it.
|
|
196
|
+
* 2. `addToIndex` skips every sub-run, so an inbox built on it drops
|
|
197
|
+
* every approval raised by delegated work, and the symptom looks like
|
|
198
|
+
* a hung specialist rather than a blind listing.
|
|
199
|
+
* 3. It is a catalogue of runs that STARTED, not of runs with durable
|
|
200
|
+
* state, so it cannot tell a run something could resume from one that
|
|
201
|
+
* left nothing behind.
|
|
202
|
+
*
|
|
203
|
+
* Deprecated for one minor rather than deleted outright: this is public
|
|
204
|
+
* surface and a consumer calling it today gets real data back, so the
|
|
205
|
+
* deprecate-before-you-remove rule applies.
|
|
206
|
+
*/
|
|
213
207
|
static async listRuns(baseDir) {
|
|
214
208
|
try {
|
|
215
209
|
const indexPath = join(baseDir, 'index.json');
|
|
@@ -267,6 +261,55 @@ export class RunDiskStore {
|
|
|
267
261
|
}
|
|
268
262
|
}
|
|
269
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Every checkpoint stored under one run directory, ascending by `createdAt`.
|
|
266
|
+
*
|
|
267
|
+
* A free function rather than a method because the scope-level listing walks
|
|
268
|
+
* run directories it has never bound a {@link RunDiskStore} to — and binding
|
|
269
|
+
* one would CREATE the directory, which is not something a read should do.
|
|
270
|
+
* Sharing the function is what keeps the two read paths from disagreeing
|
|
271
|
+
* about what a damaged file means.
|
|
272
|
+
*
|
|
273
|
+
* An unreadable checkpoint used to be logged and skipped, so this returned a
|
|
274
|
+
* silently short list that four callers treat as complete. A missing NEWEST
|
|
275
|
+
* checkpoint quietly resumes from an older point and re-runs a whole
|
|
276
|
+
* iteration of tool calls; a missing PARKED one reports "not parked" and
|
|
277
|
+
* drops an approval a human already granted, because the file is the only
|
|
278
|
+
* durable record of a park. Pruning under-deletes too: a file the keep-count
|
|
279
|
+
* cannot see is immortal. The by-id read next door was already strict, and
|
|
280
|
+
* two read paths disagreeing about whether damage matters is how the lenient
|
|
281
|
+
* one gets trusted.
|
|
282
|
+
*
|
|
283
|
+
* The same reasoning carries up to the listing, which is why the throw
|
|
284
|
+
* propagates there rather than dropping the run: a damaged checkpoint that
|
|
285
|
+
* removed a run from an approval inbox is the missing-park failure again,
|
|
286
|
+
* one level up.
|
|
287
|
+
*
|
|
288
|
+
* A missing `checkpoints/` directory is the only absence that reads as
|
|
289
|
+
* empty — the run genuinely has none. A file that disappears BETWEEN the
|
|
290
|
+
* directory listing and its read throws, where the old shape returned the
|
|
291
|
+
* empty array and discarded every checkpoint it had already parsed.
|
|
292
|
+
*/
|
|
293
|
+
export async function readCheckpointsIn(runDir) {
|
|
294
|
+
const cpDir = join(runDir, 'checkpoints');
|
|
295
|
+
let files;
|
|
296
|
+
try {
|
|
297
|
+
files = await readdir(cpDir);
|
|
298
|
+
}
|
|
299
|
+
catch (err) {
|
|
300
|
+
if (isFileNotFound(err))
|
|
301
|
+
return [];
|
|
302
|
+
throw err;
|
|
303
|
+
}
|
|
304
|
+
const checkpoints = [];
|
|
305
|
+
for (const file of files) {
|
|
306
|
+
if (!file.endsWith('.json'))
|
|
307
|
+
continue;
|
|
308
|
+
const content = await readFile(join(cpDir, file), 'utf-8');
|
|
309
|
+
checkpoints.push(parseCheckpoint(content, file));
|
|
310
|
+
}
|
|
311
|
+
return checkpoints.sort((a, b) => a.createdAt - b.createdAt);
|
|
312
|
+
}
|
|
270
313
|
async function atomicWriteJson(filePath, value) {
|
|
271
314
|
await atomicWriteFile(filePath, JSON.stringify(stamp(SCHEMA, value), null, 2));
|
|
272
315
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disk.js","sourceRoot":"","sources":["../../../src/store/run/disk.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"disk.js","sourceRoot":"","sources":["../../../src/store/run/disk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared machinery for {@link CheckpointStore.listDurableRuns}.
|
|
3
|
+
*
|
|
4
|
+
* Every rule the listing promises — the contiguous-prefix refusal, the park
|
|
5
|
+
* precedence, the ordering, the paging — lives here and is used by BOTH
|
|
6
|
+
* shipped implementations. A rule implemented twice is a rule that holds in
|
|
7
|
+
* one store and not the other, and the whole point of a store contract is
|
|
8
|
+
* that a host can swap the backend without swapping the semantics.
|
|
9
|
+
*/
|
|
10
|
+
import type { IterationCheckpoint } from '../../types/hitl/index.js';
|
|
11
|
+
import type { CheckpointListingScope, CheckpointRunScope, CheckpointStore, DurableRunEntry, DurableRunPage, ListDurableRunsOptions, ParkSummary } from '../../types/run/checkpoint-store.js';
|
|
12
|
+
/** Page size when the caller names none. */
|
|
13
|
+
export declare const DEFAULT_DURABLE_RUN_LIMIT = 100;
|
|
14
|
+
/**
|
|
15
|
+
* Refuse a listing scope with a hole in it.
|
|
16
|
+
*
|
|
17
|
+
* `{ tenantId, sessionId }` reads as "that session under whichever project
|
|
18
|
+
* holds it". A flat backend can answer it; a hierarchical one cannot look up
|
|
19
|
+
* a session without its project. Answering differently per backend is the
|
|
20
|
+
* one thing the contract exists to prevent, so neither answers: the caller
|
|
21
|
+
* names the project it means.
|
|
22
|
+
*/
|
|
23
|
+
export declare function assertContiguousListingScope(scope: CheckpointListingScope, caller: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* The one park that describes what a run is doing now, out of every park it
|
|
26
|
+
* ever recorded.
|
|
27
|
+
*
|
|
28
|
+
* Precedence: newest `outstanding`, else newest `expired`, else newest
|
|
29
|
+
* `resolved`.
|
|
30
|
+
*
|
|
31
|
+
* `outstanding` wins because that is the question an inbox is asking, and
|
|
32
|
+
* because the answer has to be the SAME checkpoint `findPendingCheckpoint`
|
|
33
|
+
* returns. A run can hold several parks — it parks, a human answers, it runs
|
|
34
|
+
* on, it parks again — and it can hold an outstanding one that is older than
|
|
35
|
+
* a resolved one only in the reverse case, where an earlier park expired
|
|
36
|
+
* unanswered and the run was resumed past it. Ranking by recency alone would
|
|
37
|
+
* then hand an inbox a resolved checkpoint and report the live park as
|
|
38
|
+
* nothing.
|
|
39
|
+
*
|
|
40
|
+
* @param checkpoints the run's checkpoints, any order.
|
|
41
|
+
*/
|
|
42
|
+
export declare function summarizePark(checkpoints: readonly IterationCheckpoint[], now: number): ParkSummary | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Project one run's checkpoints into a listing entry.
|
|
45
|
+
*
|
|
46
|
+
* Returns `null` for a run with no checkpoints: the listing is of runs with
|
|
47
|
+
* DURABLE state, and a run with nothing stored has nothing a sweeper could
|
|
48
|
+
* resume. A disk walk hits this case for real — a sub-run's directory is
|
|
49
|
+
* created as a bare shell under its own id before anything is written to it.
|
|
50
|
+
*/
|
|
51
|
+
export declare function toDurableRunEntry(scope: CheckpointRunScope, checkpoints: readonly IterationCheckpoint[], now: number): DurableRunEntry | null;
|
|
52
|
+
/**
|
|
53
|
+
* Apply the park filter, the contract's ordering and the cursor to a set of
|
|
54
|
+
* entries an implementation has gathered.
|
|
55
|
+
*
|
|
56
|
+
* Both shipped stores gather differently — one walks a directory tree, one
|
|
57
|
+
* reads a map — and then hand the result here, so "ordered by `runId`, page
|
|
58
|
+
* ends where the next begins" is one implementation rather than two.
|
|
59
|
+
*/
|
|
60
|
+
export declare function paginateDurableRuns(entries: readonly DurableRunEntry[], options?: ListDurableRunsOptions): DurableRunPage;
|
|
61
|
+
/**
|
|
62
|
+
* Every run with durable state under a scope, refusing when the store cannot
|
|
63
|
+
* answer.
|
|
64
|
+
*
|
|
65
|
+
* The refusal is the point. `listDurableRuns` is optional on the contract so
|
|
66
|
+
* that adding it did not break every host that had already implemented the
|
|
67
|
+
* interface — and an optional capability reached without a check degrades
|
|
68
|
+
* into a wrong answer: a store that cannot list would hand an approval inbox
|
|
69
|
+
* an empty page, and "nothing is waiting on a human" is not what "I cannot
|
|
70
|
+
* tell" means. A host that gets this error knows to supply a backend that
|
|
71
|
+
* implements the listing; a host that got `[]` would ship an inbox that
|
|
72
|
+
* silently never fires.
|
|
73
|
+
*/
|
|
74
|
+
export declare function listDurableRuns(store: CheckpointStore, scope: CheckpointListingScope, options?: ListDurableRunsOptions): Promise<DurableRunPage>;
|
|
75
|
+
//# sourceMappingURL=listing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listing.d.ts","sourceRoot":"","sources":["../../../src/store/run/listing.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,2BAA2B,CAAA;AACrF,OAAO,KAAK,EACX,sBAAsB,EACtB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,cAAc,EACd,sBAAsB,EAEtB,WAAW,EACX,MAAM,qCAAqC,CAAA;AAE5C,4CAA4C;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAQhG;AAmCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC5B,WAAW,EAAE,SAAS,mBAAmB,EAAE,EAC3C,GAAG,EAAE,MAAM,GACT,WAAW,GAAG,SAAS,CAkBzB;AAQD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,kBAAkB,EACzB,WAAW,EAAE,SAAS,mBAAmB,EAAE,EAC3C,GAAG,EAAE,MAAM,GACT,eAAe,GAAG,IAAI,CAqBxB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,OAAO,CAAC,EAAE,sBAAsB,GAC9B,cAAc,CA2BhB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACpC,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,sBAAsB,EAC7B,OAAO,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAAC,cAAc,CAAC,CAWzB"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared machinery for {@link CheckpointStore.listDurableRuns}.
|
|
3
|
+
*
|
|
4
|
+
* Every rule the listing promises — the contiguous-prefix refusal, the park
|
|
5
|
+
* precedence, the ordering, the paging — lives here and is used by BOTH
|
|
6
|
+
* shipped implementations. A rule implemented twice is a rule that holds in
|
|
7
|
+
* one store and not the other, and the whole point of a store contract is
|
|
8
|
+
* that a host can swap the backend without swapping the semantics.
|
|
9
|
+
*/
|
|
10
|
+
import { NamzuError } from '../../types/errors/index.js';
|
|
11
|
+
/** Page size when the caller names none. */
|
|
12
|
+
export const DEFAULT_DURABLE_RUN_LIMIT = 100;
|
|
13
|
+
/**
|
|
14
|
+
* Refuse a listing scope with a hole in it.
|
|
15
|
+
*
|
|
16
|
+
* `{ tenantId, sessionId }` reads as "that session under whichever project
|
|
17
|
+
* holds it". A flat backend can answer it; a hierarchical one cannot look up
|
|
18
|
+
* a session without its project. Answering differently per backend is the
|
|
19
|
+
* one thing the contract exists to prevent, so neither answers: the caller
|
|
20
|
+
* names the project it means.
|
|
21
|
+
*/
|
|
22
|
+
export function assertContiguousListingScope(scope, caller) {
|
|
23
|
+
if (scope.sessionId !== undefined && scope.projectId === undefined) {
|
|
24
|
+
throw new NamzuError({
|
|
25
|
+
code: 'invalid_config',
|
|
26
|
+
message: `${caller}: listing scope has a hole — \`sessionId\` was supplied without \`projectId\`. A run listing scope is a contiguous prefix of tenant → project → session; name the project the session belongs to.`,
|
|
27
|
+
details: { tenantId: scope.tenantId, sessionId: scope.sessionId },
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Whether a park's absolute deadline has passed. No deadline never expires. */
|
|
32
|
+
function isPastDeadline(pending, now) {
|
|
33
|
+
return pending.deadlineAt !== undefined && now >= pending.deadlineAt;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Which of the three states a recorded park is in.
|
|
37
|
+
*
|
|
38
|
+
* `resolved` is checked FIRST: a park that was answered after its deadline
|
|
39
|
+
* passed is answered, not expired. Reading the deadline first would report
|
|
40
|
+
* a decision a human actually made as an expiry nobody made, and the
|
|
41
|
+
* checkpoint is the evidence record for exactly that question.
|
|
42
|
+
*/
|
|
43
|
+
function parkStateOf(pending, now) {
|
|
44
|
+
if (pending.resolvedAt !== undefined)
|
|
45
|
+
return 'resolved';
|
|
46
|
+
return isPastDeadline(pending, now) ? 'expired' : 'outstanding';
|
|
47
|
+
}
|
|
48
|
+
function toParkSummary(cp, pending, now) {
|
|
49
|
+
return {
|
|
50
|
+
state: parkStateOf(pending, now),
|
|
51
|
+
checkpointId: cp.id,
|
|
52
|
+
requestType: pending.request.type,
|
|
53
|
+
parkedAt: pending.parkedAt,
|
|
54
|
+
...(pending.deadlineAt !== undefined ? { deadlineAt: pending.deadlineAt } : {}),
|
|
55
|
+
...(pending.resolvedAt !== undefined ? { resolvedAt: pending.resolvedAt } : {}),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The one park that describes what a run is doing now, out of every park it
|
|
60
|
+
* ever recorded.
|
|
61
|
+
*
|
|
62
|
+
* Precedence: newest `outstanding`, else newest `expired`, else newest
|
|
63
|
+
* `resolved`.
|
|
64
|
+
*
|
|
65
|
+
* `outstanding` wins because that is the question an inbox is asking, and
|
|
66
|
+
* because the answer has to be the SAME checkpoint `findPendingCheckpoint`
|
|
67
|
+
* returns. A run can hold several parks — it parks, a human answers, it runs
|
|
68
|
+
* on, it parks again — and it can hold an outstanding one that is older than
|
|
69
|
+
* a resolved one only in the reverse case, where an earlier park expired
|
|
70
|
+
* unanswered and the run was resumed past it. Ranking by recency alone would
|
|
71
|
+
* then hand an inbox a resolved checkpoint and report the live park as
|
|
72
|
+
* nothing.
|
|
73
|
+
*
|
|
74
|
+
* @param checkpoints the run's checkpoints, any order.
|
|
75
|
+
*/
|
|
76
|
+
export function summarizePark(checkpoints, now) {
|
|
77
|
+
let best;
|
|
78
|
+
let bestRank = -1;
|
|
79
|
+
let bestParkedAt = Number.NEGATIVE_INFINITY;
|
|
80
|
+
for (const cp of checkpoints) {
|
|
81
|
+
const pending = cp.pending;
|
|
82
|
+
if (!pending)
|
|
83
|
+
continue;
|
|
84
|
+
const summary = toParkSummary(cp, pending, now);
|
|
85
|
+
const rank = PARK_RANK[summary.state];
|
|
86
|
+
if (rank > bestRank || (rank === bestRank && pending.parkedAt > bestParkedAt)) {
|
|
87
|
+
best = summary;
|
|
88
|
+
bestRank = rank;
|
|
89
|
+
bestParkedAt = pending.parkedAt;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return best;
|
|
93
|
+
}
|
|
94
|
+
const PARK_RANK = {
|
|
95
|
+
resolved: 0,
|
|
96
|
+
expired: 1,
|
|
97
|
+
outstanding: 2,
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Project one run's checkpoints into a listing entry.
|
|
101
|
+
*
|
|
102
|
+
* Returns `null` for a run with no checkpoints: the listing is of runs with
|
|
103
|
+
* DURABLE state, and a run with nothing stored has nothing a sweeper could
|
|
104
|
+
* resume. A disk walk hits this case for real — a sub-run's directory is
|
|
105
|
+
* created as a bare shell under its own id before anything is written to it.
|
|
106
|
+
*/
|
|
107
|
+
export function toDurableRunEntry(scope, checkpoints, now) {
|
|
108
|
+
if (checkpoints.length === 0)
|
|
109
|
+
return null;
|
|
110
|
+
let latest = checkpoints[0];
|
|
111
|
+
for (const cp of checkpoints) {
|
|
112
|
+
if (cp.createdAt > latest.createdAt)
|
|
113
|
+
latest = cp;
|
|
114
|
+
}
|
|
115
|
+
const park = summarizePark(checkpoints, now);
|
|
116
|
+
return {
|
|
117
|
+
tenantId: scope.tenantId,
|
|
118
|
+
projectId: scope.projectId,
|
|
119
|
+
sessionId: scope.sessionId,
|
|
120
|
+
runId: scope.runId,
|
|
121
|
+
...(scope.parentRunId ? { parentRunId: scope.parentRunId } : {}),
|
|
122
|
+
checkpointCount: checkpoints.length,
|
|
123
|
+
latestCheckpointId: latest.id,
|
|
124
|
+
latestCheckpointAt: latest.createdAt,
|
|
125
|
+
...(park ? { park } : {}),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Apply the park filter, the contract's ordering and the cursor to a set of
|
|
130
|
+
* entries an implementation has gathered.
|
|
131
|
+
*
|
|
132
|
+
* Both shipped stores gather differently — one walks a directory tree, one
|
|
133
|
+
* reads a map — and then hand the result here, so "ordered by `runId`, page
|
|
134
|
+
* ends where the next begins" is one implementation rather than two.
|
|
135
|
+
*/
|
|
136
|
+
export function paginateDurableRuns(entries, options) {
|
|
137
|
+
const wanted = options?.park;
|
|
138
|
+
const filtered = wanted && wanted.length > 0
|
|
139
|
+
? entries.filter((e) => e.park !== undefined && wanted.includes(e.park.state))
|
|
140
|
+
: entries;
|
|
141
|
+
// Ordered by `runId` because it is the only per-run key that cannot move
|
|
142
|
+
// under a paging caller — see the contract comment on `listDurableRuns`.
|
|
143
|
+
const ordered = [...filtered].sort((a, b) => (a.runId < b.runId ? -1 : a.runId > b.runId ? 1 : 0));
|
|
144
|
+
const after = options?.cursor;
|
|
145
|
+
const start = after === undefined ? 0 : ordered.findIndex((e) => e.runId > after);
|
|
146
|
+
const from = start < 0 ? ordered.length : start;
|
|
147
|
+
const limit = Math.max(1, Math.trunc(options?.limit ?? DEFAULT_DURABLE_RUN_LIMIT));
|
|
148
|
+
const page = ordered.slice(from, from + limit);
|
|
149
|
+
const exhausted = from + page.length >= ordered.length;
|
|
150
|
+
return {
|
|
151
|
+
entries: page,
|
|
152
|
+
// No cursor when there is nothing behind it, so `while (cursor)`
|
|
153
|
+
// terminates rather than fetching one empty page to find out.
|
|
154
|
+
...(exhausted || page.length === 0
|
|
155
|
+
? {}
|
|
156
|
+
: { cursor: page[page.length - 1].runId }),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Every run with durable state under a scope, refusing when the store cannot
|
|
161
|
+
* answer.
|
|
162
|
+
*
|
|
163
|
+
* The refusal is the point. `listDurableRuns` is optional on the contract so
|
|
164
|
+
* that adding it did not break every host that had already implemented the
|
|
165
|
+
* interface — and an optional capability reached without a check degrades
|
|
166
|
+
* into a wrong answer: a store that cannot list would hand an approval inbox
|
|
167
|
+
* an empty page, and "nothing is waiting on a human" is not what "I cannot
|
|
168
|
+
* tell" means. A host that gets this error knows to supply a backend that
|
|
169
|
+
* implements the listing; a host that got `[]` would ship an inbox that
|
|
170
|
+
* silently never fires.
|
|
171
|
+
*/
|
|
172
|
+
export async function listDurableRuns(store, scope, options) {
|
|
173
|
+
if (typeof store.listDurableRuns !== 'function') {
|
|
174
|
+
throw new NamzuError({
|
|
175
|
+
code: 'capability_unavailable',
|
|
176
|
+
message: 'listDurableRuns: the injected checkpoint store does not implement `listDurableRuns`, so it cannot enumerate runs above a run id. Refusing rather than reporting an empty listing, which would read as "no runs are parked" when the truth is that this store cannot tell. Supply a store that implements it (the built-in disk and in-memory stores both do).',
|
|
177
|
+
details: { tenantId: scope.tenantId },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
assertContiguousListingScope(scope, 'listDurableRuns');
|
|
181
|
+
return store.listDurableRuns(scope, options);
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=listing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listing.js","sourceRoot":"","sources":["../../../src/store/run/listing.ts"],"names":[],"mappings":"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"}
|