@manyoars/oars 0.5.4 → 0.5.5
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/README.md +4 -4
- package/dist/cli.js +18 -7
- package/dist/club.d.ts +2 -0
- package/dist/club.js +10 -4
- package/dist/sessions/archive.js +1 -1
- package/dist/sessions/card-command.d.ts +2 -2
- package/dist/sessions/card-command.js +7 -5
- package/dist/sessions/card-line.d.ts +6 -2
- package/dist/sessions/card-line.js +6 -3
- package/dist/sessions/cell-increments.d.ts +7 -0
- package/dist/sessions/cell-increments.js +25 -10
- package/dist/sessions/cells.d.ts +7 -0
- package/dist/sessions/cells.js +118 -107
- package/dist/sessions/crew-mark.d.ts +6 -0
- package/dist/sessions/crew-mark.js +22 -0
- package/dist/sessions/hook-index.d.ts +2 -1
- package/dist/sessions/hook-index.js +2 -2
- package/dist/sessions/pool-command.d.ts +22 -4
- package/dist/sessions/pool-command.js +516 -82
- package/dist/sessions/pool-delta.d.ts +5 -0
- package/dist/sessions/pool-delta.js +32 -12
- package/dist/sessions/pool-fold.d.ts +22 -0
- package/dist/sessions/pool-fold.js +65 -0
- package/dist/sessions/pool-outbox.d.ts +9 -0
- package/dist/sessions/pool-outbox.js +33 -12
- package/dist/sessions/pool.d.ts +10 -5
- package/dist/sessions/pool.js +16 -15
- package/dist/sessions/read-call-shape.js +3 -2
- package/dist/sessions/read-folds.d.ts +21 -0
- package/dist/sessions/read-folds.js +37 -0
- package/dist/sessions/read-recovery.d.ts +1 -1
- package/dist/sessions/read-recovery.js +6 -5
- package/dist/sessions/read-support.d.ts +4 -1
- package/dist/sessions/recall-consequence.d.ts +2 -1
- package/dist/sessions/recall-consequence.js +1 -2
- package/dist/sessions/recall-reads.d.ts +23 -1
- package/dist/sessions/recall-reads.js +91 -63
- package/dist/sessions/reversion.d.ts +41 -2
- package/dist/sessions/reversion.js +17 -10
- package/dist/sessions/store.d.ts +55 -2
- package/dist/sessions/store.js +312 -61
- package/dist/telemetry/measures.d.ts +5 -0
- package/dist/telemetry/measures.js +16 -2
- package/dist/telemetry/schema.js +3 -1
- package/dist/telemetry/words.d.ts +6 -0
- package/dist/telemetry/words.js +4 -0
- package/package.json +1 -1
|
@@ -109,55 +109,71 @@ export const FIT_FLOORS = { minFailedSessions: 3, minFailedShare: 0.1, minCalls:
|
|
|
109
109
|
* `FIT_FLOORS`: a base rate is still a fact to read on request.
|
|
110
110
|
*/
|
|
111
111
|
export const PUSH_FLOORS = { ...FIT_FLOORS, minFailedShare: 0.5 };
|
|
112
|
-
/**
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
/**
|
|
113
|
+
* `fitReads` as a fold: each `add` tallies one run of sessions into the same shapes, and `finish` applies the floors. Runs come in the whole store's row order, so the tie order of `followed` matches.
|
|
114
|
+
* `keep` narrows which calls are tallied, not what can come next: the call after a kept one is what followed it, wherever the slice ends.
|
|
115
|
+
*/
|
|
116
|
+
export const fitFold = (floors = FIT_FLOORS, keep = () => true) => {
|
|
117
|
+
const harnesses = new Map();
|
|
116
118
|
const shapes = new Map();
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
119
|
+
const add = (store) => {
|
|
120
|
+
const models = modelsByPrompt(store);
|
|
121
|
+
for (const [session, harness] of harnessesOf(store))
|
|
122
|
+
harnesses.set(session, harness);
|
|
123
|
+
for (const calls of callsBySession(store).values()) {
|
|
124
|
+
for (const [position, call] of calls.entries()) {
|
|
125
|
+
if (!keep(call))
|
|
126
|
+
continue;
|
|
127
|
+
const id = toolShapeId(call.tool, call.keys);
|
|
128
|
+
const shape = shapes.get(id) ?? { tool: call.tool, keys: [...call.keys].sort(), calls: 0, failed: 0, sessions: new Set(), following: new Map(), days: [], versions: new Set(), models: new Set() };
|
|
129
|
+
shapes.set(id, shape);
|
|
130
|
+
shape.calls += 1;
|
|
131
|
+
if (call.status !== 'error')
|
|
132
|
+
continue;
|
|
133
|
+
shape.failed += 1;
|
|
134
|
+
shape.sessions.add(call.session);
|
|
135
|
+
shape.days.push(utcDay(call.ts));
|
|
136
|
+
if (call.harnessVersion !== null)
|
|
137
|
+
shape.versions.add(call.harnessVersion);
|
|
138
|
+
const model = models.get(`${call.session}#${String(call.prompt)}`);
|
|
139
|
+
if (model !== undefined)
|
|
140
|
+
shape.models.add(model);
|
|
141
|
+
const next = calls[position + 1];
|
|
142
|
+
if (next !== undefined)
|
|
143
|
+
bump(shape.following, next.tool);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const finish = () => {
|
|
148
|
+
const reads = [];
|
|
149
|
+
for (const [readId, shape] of shapes) {
|
|
150
|
+
if (shape.sessions.size < floors.minFailedSessions || shape.calls < floors.minCalls || shape.failed / shape.calls < floors.minFailedShare)
|
|
126
151
|
continue;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
shape.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
shape.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
152
|
+
reads.push({
|
|
153
|
+
readId,
|
|
154
|
+
family: 'fit',
|
|
155
|
+
tool: shape.tool,
|
|
156
|
+
keys: shape.keys,
|
|
157
|
+
n: shape.sessions.size,
|
|
158
|
+
count: shape.failed,
|
|
159
|
+
calls: shape.calls,
|
|
160
|
+
clusters: 1,
|
|
161
|
+
...dayRange(shape.days),
|
|
162
|
+
harnesses: harnessNames(shape.sessions, harnesses),
|
|
163
|
+
harnessVersions: [...shape.versions].sort(),
|
|
164
|
+
models: [...shape.models].sort(),
|
|
165
|
+
followed: top(shape.following),
|
|
166
|
+
});
|
|
138
167
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
keys: shape.keys,
|
|
149
|
-
n: shape.sessions.size,
|
|
150
|
-
count: shape.failed,
|
|
151
|
-
calls: shape.calls,
|
|
152
|
-
clusters: 1,
|
|
153
|
-
...dayRange(shape.days),
|
|
154
|
-
harnesses: harnessNames(shape.sessions, harnesses),
|
|
155
|
-
harnessVersions: [...shape.versions].sort(),
|
|
156
|
-
models: [...shape.models].sort(),
|
|
157
|
-
followed: top(shape.following),
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
return reads.sort((a, b) => b.count - a.count || a.readId.localeCompare(b.readId));
|
|
168
|
+
return reads.sort((x, y) => y.count - x.count || x.readId.localeCompare(y.readId));
|
|
169
|
+
};
|
|
170
|
+
return { add, finish };
|
|
171
|
+
};
|
|
172
|
+
/** `fitFold` over the whole store at once. `keep` narrows the calls tallied, not what follows them. */
|
|
173
|
+
export const fitReads = (store, floors = FIT_FLOORS, keep = () => true) => {
|
|
174
|
+
const fold = fitFold(floors, keep);
|
|
175
|
+
fold.add(store);
|
|
176
|
+
return fold.finish();
|
|
161
177
|
};
|
|
162
178
|
/** The action of a tool under the first of its harnesses whose table lists it, else under the first harness (the default one when a read names none). */
|
|
163
179
|
export const actionOfShape = (tool, harnesses) => {
|
|
@@ -170,28 +186,40 @@ export const actionOfShape = (tool, harnesses) => {
|
|
|
170
186
|
* 79 of 79 pushes, at 4.5x and 8.6x their action's share: a real signal, not a defect. Open parameter, like the floors.
|
|
171
187
|
*/
|
|
172
188
|
export const PUSH_MIN_LIFT = 2;
|
|
189
|
+
/** The per-action call tally `aboveBaseRate` compares against, as a fold: each `add` tallies one run of sessions, so a refresh never holds every call. */
|
|
190
|
+
export const actionFold = () => {
|
|
191
|
+
const byAction = new Map();
|
|
192
|
+
return {
|
|
193
|
+
add: (store) => {
|
|
194
|
+
const harnesses = harnessesOf(store);
|
|
195
|
+
for (const calls of callsBySession(store).values()) {
|
|
196
|
+
for (const call of calls) {
|
|
197
|
+
const action = actionOfShape(call.tool, [harnesses.get(call.session) ?? harnessOf({})]);
|
|
198
|
+
const tally = byAction.get(action) ?? { calls: 0, failed: 0 };
|
|
199
|
+
byAction.set(action, tally);
|
|
200
|
+
tally.calls += 1;
|
|
201
|
+
if (call.status === 'error')
|
|
202
|
+
tally.failed += 1;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
finish: () => byAction,
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
/** `aboveBaseRate` over a finished action tally. */
|
|
210
|
+
export const aboveActionRate = (byAction, reads, lift = PUSH_MIN_LIFT) => reads.filter((read) => {
|
|
211
|
+
const base = byAction.get(actionOfShape(read.tool, read.harnesses));
|
|
212
|
+
// A fit read always counts its calls (`calls` is null only for entity reads), and its own calls are in the tally, so `base` is there; the fallbacks keep the types honest.
|
|
213
|
+
return base !== undefined && read.calls !== null && read.count * base.calls >= lift * base.failed * read.calls;
|
|
214
|
+
});
|
|
173
215
|
/**
|
|
174
216
|
* The reads whose shape fails at `lift` times the share of its whole action or more, where the action's share counts every call of every shape of it, those under the floors too.
|
|
175
217
|
* A tool no table lists is the action `other` (or `mcp.call`), so it is held to that action's share like any other and can enter the index and fire. Compared in integers, so a tie is exact.
|
|
176
218
|
*/
|
|
177
219
|
export const aboveBaseRate = (store, reads, lift = PUSH_MIN_LIFT) => {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
for (const call of calls) {
|
|
182
|
-
const action = actionOfShape(call.tool, [harnesses.get(call.session) ?? harnessOf({})]);
|
|
183
|
-
const tally = byAction.get(action) ?? { calls: 0, failed: 0 };
|
|
184
|
-
byAction.set(action, tally);
|
|
185
|
-
tally.calls += 1;
|
|
186
|
-
if (call.status === 'error')
|
|
187
|
-
tally.failed += 1;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return reads.filter((read) => {
|
|
191
|
-
const base = byAction.get(actionOfShape(read.tool, read.harnesses));
|
|
192
|
-
// A fit read always counts its calls (`calls` is null only for entity reads), and its own calls are in the tally, so `base` is there; the fallbacks keep the types honest.
|
|
193
|
-
return base !== undefined && read.calls !== null && read.count * base.calls >= lift * base.failed * read.calls;
|
|
194
|
-
});
|
|
220
|
+
const fold = actionFold();
|
|
221
|
+
fold.add(store);
|
|
222
|
+
return aboveActionRate(fold.finish(), reads, lift);
|
|
195
223
|
};
|
|
196
224
|
/** The snapshot a store answers from: its latest deposit. A deposit time compares with a recall's `at`, which is what "older than the recall" needs. */
|
|
197
225
|
export const poolVersionOf = (store) => store.sessions.reduce((latest, session) => (session.at > latest ? session.at : latest), '');
|
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
import type { Store } from './store.js';
|
|
2
2
|
/** Where the nearest later reversion ran: in the prompt that did the work, in a later prompt of that session, or in a later session of the same repository. */
|
|
3
3
|
export type Reversion = 'same-prompt' | 'later-prompt' | 'later-session';
|
|
4
|
+
/** Where a call sits: its session, its position there, the position of a pair inside it (a MultiEdit holds several edits in order), its time, and its prompt. */
|
|
5
|
+
interface Place {
|
|
6
|
+
session: string;
|
|
7
|
+
n: number;
|
|
8
|
+
k: number;
|
|
9
|
+
ts: string | null;
|
|
10
|
+
prompt: number;
|
|
11
|
+
}
|
|
12
|
+
interface Placed extends Place {
|
|
13
|
+
sha: string;
|
|
14
|
+
}
|
|
15
|
+
/** One digest pair of an edit call on a path: `old` is null for a Write, which does not show the text it replaced. */
|
|
16
|
+
interface Written extends Place {
|
|
17
|
+
old: string | null;
|
|
18
|
+
now: string;
|
|
19
|
+
}
|
|
20
|
+
/** A commit call of a session: its position there and its time. */
|
|
21
|
+
interface Commit {
|
|
22
|
+
n: number;
|
|
23
|
+
ts: string | null;
|
|
24
|
+
}
|
|
25
|
+
/** What the calls of the runs folded so far hold: every main-line call's commits, revert words, restored paths, and edit digests, and each session's repository. */
|
|
26
|
+
export interface ReversionIndex {
|
|
27
|
+
repos: Map<string, string | null>;
|
|
28
|
+
commits: Placed[];
|
|
29
|
+
reverts: Placed[];
|
|
30
|
+
committed: Map<string, Commit[]>;
|
|
31
|
+
edited: Map<string, Place[]>;
|
|
32
|
+
written: Map<string, Written[]>;
|
|
33
|
+
restored: Array<Place & {
|
|
34
|
+
target: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
export declare const newReversionIndex: () => ReversionIndex;
|
|
4
38
|
/**
|
|
5
|
-
* Reads every main-line call once: the clean shell calls' commits, revert words (read segments only, since a segment whose result the call's status does not report (`read` false) could have failed behind another command), and
|
|
6
|
-
* restored paths; and every edit that did not fail, with its digests. A subagent's call is not on the main line, so it is not read.
|
|
39
|
+
* Reads every main-line call of one run once: the clean shell calls' commits, revert words (read segments only, since a segment whose result the call's status does not report (`read` false) could have failed behind another command), and
|
|
40
|
+
* restored paths; and every edit that did not fail, with its digests. A subagent's call is not on the main line, so it is not read. Give it the run's own sessions only: a context parent passed here is folded again in its own run. Runs fold in the whole store's order, and the matching waits for `finishReversions`.
|
|
7
41
|
*/
|
|
42
|
+
export declare const foldReversions: (index: ReversionIndex, store: Store) => void;
|
|
43
|
+
/** Matches the folded calls once. Returns the nearest reversion of a prompt's work, or null for none found. */
|
|
44
|
+
export declare const finishReversions: (index: ReversionIndex) => ((session: string, index: number | null) => Reversion | null);
|
|
45
|
+
/** Every main-line call of the store matched at once: the fold of one run, then the finish. */
|
|
8
46
|
export declare const reversionsOf: (store: Store) => ((session: string, index: number | null) => Reversion | null);
|
|
47
|
+
export {};
|
|
@@ -41,18 +41,15 @@ const keptBy = (committed, edit, restore) => {
|
|
|
41
41
|
return before.some((commit) => commit.n > edit.n && commit.n <= restore.n);
|
|
42
42
|
return before.some((commit) => commit.n > edit.n) || (committed.get(restore.session) ?? []).some((commit) => commit.n <= restore.n && !(commit.ts !== null && edit.ts !== null && commit.ts < edit.ts));
|
|
43
43
|
};
|
|
44
|
+
export const newReversionIndex = () => ({ repos: new Map(), commits: [], reverts: [], committed: new Map(), edited: new Map(), written: new Map(), restored: [] });
|
|
44
45
|
/**
|
|
45
|
-
* Reads every main-line call once: the clean shell calls' commits, revert words (read segments only, since a segment whose result the call's status does not report (`read` false) could have failed behind another command), and
|
|
46
|
-
* restored paths; and every edit that did not fail, with its digests. A subagent's call is not on the main line, so it is not read.
|
|
46
|
+
* Reads every main-line call of one run once: the clean shell calls' commits, revert words (read segments only, since a segment whose result the call's status does not report (`read` false) could have failed behind another command), and
|
|
47
|
+
* restored paths; and every edit that did not fail, with its digests. A subagent's call is not on the main line, so it is not read. Give it the run's own sessions only: a context parent passed here is folded again in its own run. Runs fold in the whole store's order, and the matching waits for `finishReversions`.
|
|
47
48
|
*/
|
|
48
|
-
export const
|
|
49
|
-
const repos
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
const committed = new Map();
|
|
53
|
-
const edited = new Map();
|
|
54
|
-
const written = new Map();
|
|
55
|
-
const restored = [];
|
|
49
|
+
export const foldReversions = (index, store) => {
|
|
50
|
+
const { repos, commits, reverts, committed, edited, written, restored } = index;
|
|
51
|
+
for (const session of store.sessions)
|
|
52
|
+
repos.set(session.session, session.repo);
|
|
56
53
|
for (const tool of store.tools) {
|
|
57
54
|
if (tool.side || tool.prompt === null)
|
|
58
55
|
continue;
|
|
@@ -75,6 +72,10 @@ export const reversionsOf = (store) => {
|
|
|
75
72
|
for (const word of revertWords(segment.run))
|
|
76
73
|
reverts.push({ ...at, sha: word });
|
|
77
74
|
}
|
|
75
|
+
};
|
|
76
|
+
/** Matches the folded calls once. Returns the nearest reversion of a prompt's work, or null for none found. */
|
|
77
|
+
export const finishReversions = (index) => {
|
|
78
|
+
const { repos, commits, reverts, committed, edited, written, restored } = index;
|
|
78
79
|
const found = new Map();
|
|
79
80
|
const note = (earlier, later) => {
|
|
80
81
|
const where = whereOf(earlier, later, repos);
|
|
@@ -112,3 +113,9 @@ export const reversionsOf = (store) => {
|
|
|
112
113
|
}
|
|
113
114
|
return (session, index) => found.get(`${session}#${String(index)}`) ?? null;
|
|
114
115
|
};
|
|
116
|
+
/** Every main-line call of the store matched at once: the fold of one run, then the finish. */
|
|
117
|
+
export const reversionsOf = (store) => {
|
|
118
|
+
const index = newReversionIndex();
|
|
119
|
+
foldReversions(index, store);
|
|
120
|
+
return finishReversions(index);
|
|
121
|
+
};
|
package/dist/sessions/store.d.ts
CHANGED
|
@@ -34,6 +34,17 @@ export interface SessionsRuntime {
|
|
|
34
34
|
stderr?: {
|
|
35
35
|
isTTY?: boolean | undefined;
|
|
36
36
|
} | undefined;
|
|
37
|
+
/** A seam for tests: awaited right after a build's scan of the log and before any session is loaded, so a test can change the log in exactly that window. */
|
|
38
|
+
afterScan?: () => Promise<void>;
|
|
39
|
+
/** How many sessions (with their subagents) `refresh` loads and folds at a time; absent means `REFRESH_RUN`. */
|
|
40
|
+
refreshRun?: number;
|
|
41
|
+
/** A seam for tests and proofs: told once what a refresh folded, after its last run. `reversions` is the size of the matching's index. */
|
|
42
|
+
refreshed?: (folded: {
|
|
43
|
+
runs: number;
|
|
44
|
+
reversions: number;
|
|
45
|
+
}) => void;
|
|
46
|
+
/** A seam for proofs: told as `refresh` passes the end of its scan, its last run, the pool fold's finish, and the pool step, so a proof can read the heap at each. */
|
|
47
|
+
refreshStep?: (step: 'scan' | 'runs' | 'finish' | 'pool') => void;
|
|
37
48
|
}
|
|
38
49
|
interface FileState {
|
|
39
50
|
size: number;
|
|
@@ -74,6 +85,8 @@ export interface PoolChoices {
|
|
|
74
85
|
folders: {
|
|
75
86
|
[entry: string]: FolderSend;
|
|
76
87
|
};
|
|
88
|
+
/** The answer to the join's region question (in the EU, the EEA, or the UK), kept so a run stopped between that question and the covenant screen does not ask it again. Null until asked. */
|
|
89
|
+
euEeaUk: 'yes' | 'no' | null;
|
|
77
90
|
}
|
|
78
91
|
export type FolderSend = 'skeleton' | 'off';
|
|
79
92
|
export declare const paths: (storeDir: string) => {
|
|
@@ -304,19 +317,52 @@ export interface Store {
|
|
|
304
317
|
newerCaptures: number;
|
|
305
318
|
}
|
|
306
319
|
/** What one pass over the log keeps: a number or two per session, never the records. */
|
|
307
|
-
interface LogScan {
|
|
320
|
+
export interface LogScan {
|
|
308
321
|
/** Each session's highest rev, over every kind of record. */
|
|
309
322
|
latest: Map<string, number>;
|
|
310
323
|
/** True when some session has a record below its highest rev, which a compaction would drop. */
|
|
311
324
|
superseded: boolean;
|
|
312
325
|
/** Sessions whose newest capture record was written by a newer oars, counted as `loadStore` counts them. */
|
|
313
326
|
newerCaptures: number;
|
|
327
|
+
/** Each subagent's parent, from its session record at its highest rev (a main session has none). */
|
|
328
|
+
parents: Map<string, string>;
|
|
329
|
+
/** Each session's `cv` at its highest rev. */
|
|
330
|
+
cvs: Map<string, string>;
|
|
331
|
+
/** Set when asked for: each session's record lines at its highest rev as flat `[start, length, ...]` byte pairs (the newline included). Only lines this scan saw are in it, so a row appended after the scan is never read through it. */
|
|
332
|
+
spans?: Map<string, number[]>;
|
|
333
|
+
/** With `spans`: the file the scan read (device, inode, and size from `stat` on the handle it read), so a load uses the spans only on that same file. */
|
|
334
|
+
identity?: LogIdentity;
|
|
314
335
|
}
|
|
315
|
-
|
|
336
|
+
/** Which file a scan read: a compaction renames a new file into place, which changes the inode; an append only grows the size. */
|
|
337
|
+
interface LogIdentity {
|
|
338
|
+
dev: bigint;
|
|
339
|
+
ino: bigint;
|
|
340
|
+
size: bigint;
|
|
341
|
+
}
|
|
342
|
+
export declare const scanLog: (file: string, held?: FileHandle, withSpans?: boolean) => Promise<LogScan>;
|
|
343
|
+
/**
|
|
344
|
+
* The order `loadStore` visits sessions in, as one list: the sessions whose capture version cannot be read (version 2, whose prompts and errors the log holds as rows) first, then the rest, each group by where
|
|
345
|
+
* the session's first line at its highest rev starts in the log, subagents and mains alike. Needs a scan made with spans. A run is a contiguous slice of this list.
|
|
346
|
+
*/
|
|
347
|
+
export declare const runOrder: (scan: LogScan) => string[];
|
|
348
|
+
/** True when the line carries a `"session":"<id>"` field of one of `ids`. The writer emits compact JSON, so the field of the line's own session is always found; a nested match only keeps the line for the parse to decide. */
|
|
349
|
+
export declare const namesAny: (line: string, ids: ReadonlySet<string>) => boolean;
|
|
316
350
|
/** What a read keeps beyond the default. */
|
|
317
351
|
export type LoadOptions = {
|
|
318
352
|
/** Keep each session's `messageUsage` entries. Nothing in the store reads them yet, and on a large store they are a third more heap, so a read holds them only when asked. */
|
|
319
353
|
messageUsage?: boolean;
|
|
354
|
+
/** Read only these sessions' rows (main and subagent ids): a build that handles a chunk at a time holds that chunk, not the history. */
|
|
355
|
+
only?: ReadonlySet<string>;
|
|
356
|
+
/** Keep the session records alone, with no prompt, tool, or error rows: enough to gate and place a session without holding its content. */
|
|
357
|
+
sessionsOnly?: boolean;
|
|
358
|
+
/** The revs of an earlier `scanLog`: the read skips its own first pass. A build that reads chunk after chunk scans once; a row written after that scan is not seen, like a session that began after the build did. */
|
|
359
|
+
latest?: ReadonlyMap<string, number>;
|
|
360
|
+
/** With `only`: the byte spans of an earlier `scanLog(file, held, true)`. The read seeks to the lines of the wanted sessions instead of streaming the whole log; a log that is no longer the scanned file is streamed instead, and a torn or short line is skipped, never misread. */
|
|
361
|
+
spans?: ReadonlyMap<string, readonly number[]>;
|
|
362
|
+
/** With `spans`: the scan's `identity`. The spans are used only when the log opened for this read is that file, grown or not; any other file (a compaction renamed one into place) is streamed, as without spans. */
|
|
363
|
+
identity?: LogIdentity;
|
|
364
|
+
/** A seam: called once for every log line the read looks at. */
|
|
365
|
+
lineRead?: () => void;
|
|
320
366
|
};
|
|
321
367
|
/**
|
|
322
368
|
* The store as a reader sees it: for each session only the highest `rev`. A version-3 or later session is derived here from its capture records
|
|
@@ -343,6 +389,13 @@ export declare const readSkeletons: (storeDir: string, only?: string, lean?: boo
|
|
|
343
389
|
skeletons: Skeleton[];
|
|
344
390
|
unreadable: number;
|
|
345
391
|
}>;
|
|
392
|
+
/** `derive`'s prompt sums, folded run by run: the prompts of each run in turn give the same sums, in the same key order, as the prompts of the whole store. */
|
|
393
|
+
export interface DeriveFold {
|
|
394
|
+
add: (prompts: readonly PromptObservation[]) => void;
|
|
395
|
+
/** The error and session parts, which need every error and session record at once, then the whole record. */
|
|
396
|
+
finish: (store: Pick<Store, 'sessions' | 'errors'>, at: string) => DerivedRecords;
|
|
397
|
+
}
|
|
398
|
+
export declare const deriveFold: () => DeriveFold;
|
|
346
399
|
/** The derived records, a pure function of the store. */
|
|
347
400
|
export declare const derive: (store: Store, at: string) => DerivedRecords;
|
|
348
401
|
export declare const signatureRecord: (sig: string, list: readonly ErrorObservation[]) => SignatureRecord;
|