chopin-ai 0.2.0 → 0.3.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/README.md +1 -2
- package/dist/agent.d.ts +5 -5
- package/dist/agent.js +7 -11
- package/dist/agent.js.map +1 -1
- package/dist/bin.js +7 -2
- package/dist/bin.js.map +1 -1
- package/dist/chat.js +7 -0
- package/dist/chat.js.map +1 -1
- package/dist/credentials.d.ts +5 -1
- package/dist/credentials.js +18 -0
- package/dist/credentials.js.map +1 -1
- package/dist/header.d.ts +1 -0
- package/dist/header.js +7 -1
- package/dist/header.js.map +1 -1
- package/dist/home.d.ts +22 -3
- package/dist/home.js +11 -3
- package/dist/home.js.map +1 -1
- package/dist/project.d.ts +19 -2
- package/dist/project.js +111 -26
- package/dist/project.js.map +1 -1
- package/dist/rsi/control.d.ts +34 -0
- package/dist/rsi/control.js +142 -0
- package/dist/rsi/control.js.map +1 -0
- package/dist/rsi/evolve.d.ts +15 -0
- package/dist/rsi/evolve.js +314 -0
- package/dist/rsi/evolve.js.map +1 -0
- package/dist/rsi/export.d.ts +6 -0
- package/dist/rsi/export.js +25 -0
- package/dist/rsi/export.js.map +1 -0
- package/dist/rsi/harvest.d.ts +87 -0
- package/dist/rsi/harvest.js +274 -0
- package/dist/rsi/harvest.js.map +1 -0
- package/dist/rsi/held.d.ts +29 -0
- package/dist/rsi/held.js +45 -0
- package/dist/rsi/held.js.map +1 -0
- package/dist/rsi/lifecycle.d.ts +8 -0
- package/dist/rsi/lifecycle.js +25 -0
- package/dist/rsi/lifecycle.js.map +1 -0
- package/dist/rsi/models.d.ts +25 -0
- package/dist/rsi/models.js +71 -0
- package/dist/rsi/models.js.map +1 -0
- package/dist/rsi/records.d.ts +14 -0
- package/dist/rsi/records.js +20 -0
- package/dist/rsi/records.js.map +1 -0
- package/dist/rsi/round.d.ts +62 -0
- package/dist/rsi/round.js +333 -0
- package/dist/rsi/round.js.map +1 -0
- package/dist/rsi/schedule.d.ts +14 -0
- package/dist/rsi/schedule.js +42 -0
- package/dist/rsi/schedule.js.map +1 -0
- package/dist/rsi/summary.d.ts +5 -0
- package/dist/rsi/summary.js +41 -0
- package/dist/rsi/summary.js.map +1 -0
- package/dist/serve.js +52 -29
- package/dist/serve.js.map +1 -1
- package/dist/transcript.js +6 -1
- package/dist/transcript.js.map +1 -1
- package/package.json +11 -12
- package/dist/browser.d.ts +0 -2
- package/dist/browser.js +0 -9
- package/dist/browser.js.map +0 -1
- package/dist/web.d.ts +0 -3
- package/dist/web.js +0 -20
- package/dist/web.js.map +0 -1
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { appendFile, mkdir, readdir, readFile, stat } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { classify, CLASSIFIER_VERSION, correctedStep, failureStep, fromMessagesJsonl, groupFailures, kindAliases, kindKey, parseTranscript, proposeCorrections, redactTranscript, signals, signatureKey, } from "@chopin-ai/core";
|
|
5
|
+
import { writeWhole } from "../home.js";
|
|
6
|
+
const SEEN = `seen-v${CLASSIFIER_VERSION}.json`;
|
|
7
|
+
const CORRECTIONS_READ = "corrections-read.json";
|
|
8
|
+
const KINDS = `kinds-v${CLASSIFIER_VERSION}.json`;
|
|
9
|
+
/** Sessions older than this are not read; what they would teach has been learned or no longer applies. */
|
|
10
|
+
const RECENT_MS = 30 * 24 * 60 * 60_000;
|
|
11
|
+
/** Every session log the loop may learn from: each chopin project's exported transcripts, and the configured logs. */
|
|
12
|
+
export async function sessionSources(chopinHome, logDirectories, now = Date.now()) {
|
|
13
|
+
const projects = join(chopinHome, "projects");
|
|
14
|
+
const exported = (await names(projects)).map((project) => join(projects, project, "rsi", "transcripts"));
|
|
15
|
+
const found = [
|
|
16
|
+
...(await Promise.all(exported.map((dir) => files(dir, "acp")))).flat(),
|
|
17
|
+
...(await Promise.all(logDirectories.map((dir) => files(dir, "messages")))).flat(),
|
|
18
|
+
];
|
|
19
|
+
const dated = await Promise.all(found.map(async (source) => ({ source, at: (await stat(source.path)).mtimeMs })));
|
|
20
|
+
// Newest first, so a pass cut short by the budget has learned from the latest work.
|
|
21
|
+
return dated.filter(({ at }) => at > now - RECENT_MS).sort((a, b) => b.at - a.at).map(({ source }) => source);
|
|
22
|
+
}
|
|
23
|
+
/** A short digest of a criterion text, which keys the verdicts judged by it. */
|
|
24
|
+
export function digest(text) {
|
|
25
|
+
return createHash("sha256").update(text).digest("hex").slice(0, 16);
|
|
26
|
+
}
|
|
27
|
+
/** What the loop has gathered: the failures found, the corrections proposed, and which logs it has read as they were. */
|
|
28
|
+
export class Evidence {
|
|
29
|
+
root;
|
|
30
|
+
constructor(root) {
|
|
31
|
+
this.root = root;
|
|
32
|
+
}
|
|
33
|
+
/** The failures named by the current rules; ones named by earlier rules are kept but no longer counted. */
|
|
34
|
+
async failures() {
|
|
35
|
+
return (await this.#lines("failures.jsonl")).filter((failure) => failure.classifier === CLASSIFIER_VERSION);
|
|
36
|
+
}
|
|
37
|
+
async addFailure(failure) {
|
|
38
|
+
await this.#append("failures.jsonl", failure);
|
|
39
|
+
}
|
|
40
|
+
/** Signals the current rules judged no failure, by session and line, so they are not asked about again. */
|
|
41
|
+
async dismissed() {
|
|
42
|
+
return new Set((await this.#lines("dismissed.jsonl"))
|
|
43
|
+
.filter((line) => line.classifier === CLASSIFIER_VERSION).map((line) => line.at));
|
|
44
|
+
}
|
|
45
|
+
async dismiss(session, line) {
|
|
46
|
+
await this.#append("dismissed.jsonl", { at: `${session}:${line}`, classifier: CLASSIFIER_VERSION });
|
|
47
|
+
}
|
|
48
|
+
/** The kinds of failure, each under the name its other names are merged into. */
|
|
49
|
+
async kinds() {
|
|
50
|
+
const { aliases } = await this.#kindNames();
|
|
51
|
+
return groupFailures(await this.failures(), new Map(Object.entries(aliases)));
|
|
52
|
+
}
|
|
53
|
+
/** Looks for kinds that are other names for one mechanism again, once a kind not looked at before has come in. */
|
|
54
|
+
async mergeKinds(complete) {
|
|
55
|
+
const named = [...await this.failures(), ...await this.pendingCorrections()];
|
|
56
|
+
const kinds = [...new Set(named.map((failure) => kindKey(failure.signature)))];
|
|
57
|
+
const before = await this.#kindNames();
|
|
58
|
+
if (kinds.every((kind) => before.reviewed.includes(kind)))
|
|
59
|
+
return;
|
|
60
|
+
const aliases = await kindAliases(kinds, complete, { reviewed: before.reviewed, aliases: new Map(Object.entries(before.aliases)) });
|
|
61
|
+
const reviewed = [...new Set([...before.reviewed, ...kinds])];
|
|
62
|
+
await this.#write(KINDS, { reviewed, aliases: Object.fromEntries(aliases) });
|
|
63
|
+
}
|
|
64
|
+
corrections() {
|
|
65
|
+
return this.#lines("corrections.jsonl");
|
|
66
|
+
}
|
|
67
|
+
async addCorrection(correction) {
|
|
68
|
+
await this.#append("corrections.jsonl", correction);
|
|
69
|
+
}
|
|
70
|
+
/** Corrections named by the current rules that the user has not answered yet. */
|
|
71
|
+
async pendingCorrections() {
|
|
72
|
+
const latest = new Map((await this.corrections()).map((correction) => [`${correction.session}:${correction.line}`, correction]));
|
|
73
|
+
return [...latest.values()].filter((correction) => correction.confirmed === undefined && correction.classifier === CLASSIFIER_VERSION);
|
|
74
|
+
}
|
|
75
|
+
/** The pending corrections by kind, under the same names failures are merged into, the most sessions first. */
|
|
76
|
+
async correctionKinds() {
|
|
77
|
+
const pending = await this.pendingCorrections();
|
|
78
|
+
const byPoint = new Map(pending.map((correction) => [`${correction.session}:${correction.line}`, correction]));
|
|
79
|
+
const { aliases } = await this.#kindNames();
|
|
80
|
+
return groupFailures(pending, new Map(Object.entries(aliases))).map((found) => ({
|
|
81
|
+
key: found.key, sessions: found.sessions, corrections: found.failures.map((failure) => byPoint.get(`${failure.session}:${failure.line}`)),
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
/** Records the user's answer on a correction; the latest answer for a line wins. */
|
|
85
|
+
async answerCorrection(correction, confirmed) {
|
|
86
|
+
await this.#append("corrections.jsonl", { ...correction, confirmed });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* What the user said to correct each step they confirmed a correction of, by session and line: the strongest
|
|
90
|
+
* evidence a failure has, and the criterion it is judged by.
|
|
91
|
+
*/
|
|
92
|
+
async confirmedCorrections() {
|
|
93
|
+
const latest = new Map((await this.corrections()).map((correction) => [`${correction.session}:${correction.line}`, correction]));
|
|
94
|
+
const byStep = new Map();
|
|
95
|
+
for (const correction of latest.values()) {
|
|
96
|
+
if (correction.confirmed !== true)
|
|
97
|
+
continue;
|
|
98
|
+
const step = `${correction.session}:${correction.step}`;
|
|
99
|
+
byStep.set(step, [...byStep.get(step) ?? [], correction.summary]);
|
|
100
|
+
}
|
|
101
|
+
return new Map([...byStep].map(([step, summaries]) => [step, summaries.join("; ")]));
|
|
102
|
+
}
|
|
103
|
+
/** The criteria a kind's failures are judged by, as a digest: empty when none was named by the user's correction. */
|
|
104
|
+
async criteria(found) {
|
|
105
|
+
const corrections = await this.confirmedCorrections();
|
|
106
|
+
const named = found.failures.flatMap((failure) => corrections.get(`${failure.session}:${failure.line}`) ?? []).sort();
|
|
107
|
+
return named.length === 0 ? "" : digest(named.join("\n"));
|
|
108
|
+
}
|
|
109
|
+
/** The user's answer on every correction of a kind; confirmed ones become failures at the steps they correct. */
|
|
110
|
+
async answerKind(kind, confirmed) {
|
|
111
|
+
for (const correction of kind.corrections) {
|
|
112
|
+
await this.answerCorrection(correction, confirmed);
|
|
113
|
+
if (confirmed)
|
|
114
|
+
await this.addFailure({ session: correction.session, line: correction.step, signature: correction.signature, classifier: correction.classifier });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Whether each failure recurred when the given layer version continued its session on `model`, by point. */
|
|
118
|
+
async recurrence(version, model) {
|
|
119
|
+
const lines = await this.#lines("recurrence.jsonl");
|
|
120
|
+
return new Map(lines.filter((line) => line.version === version && line.model === model).map((line) => [line.point, line.recurred]));
|
|
121
|
+
}
|
|
122
|
+
async addRecurrence(point, version, model, recurred) {
|
|
123
|
+
await this.#append("recurrence.jsonl", { point, version, model, recurred });
|
|
124
|
+
}
|
|
125
|
+
/** The kinds of failure a kept change answers, globally or in a project; a kind whose change was undone is open again. */
|
|
126
|
+
async answered() {
|
|
127
|
+
const answered = new Set();
|
|
128
|
+
for (const line of await this.#lines("answered.jsonl")) {
|
|
129
|
+
if (line.reopened === true)
|
|
130
|
+
answered.delete(line.failure);
|
|
131
|
+
else
|
|
132
|
+
answered.add(line.failure);
|
|
133
|
+
}
|
|
134
|
+
return answered;
|
|
135
|
+
}
|
|
136
|
+
async addAnswered(failure) {
|
|
137
|
+
await this.#append("answered.jsonl", { failure });
|
|
138
|
+
}
|
|
139
|
+
async reopen(failure) {
|
|
140
|
+
await this.#append("answered.jsonl", { failure, reopened: true });
|
|
141
|
+
}
|
|
142
|
+
/** Which logs were read as they were, under the current rules; new rules read every log again. */
|
|
143
|
+
seen() {
|
|
144
|
+
return this.#json(SEEN, {});
|
|
145
|
+
}
|
|
146
|
+
markSeen(seen) {
|
|
147
|
+
return this.#write(SEEN, seen);
|
|
148
|
+
}
|
|
149
|
+
/** How many lines of each log were asked about corrections, which no change of rules asks about again. */
|
|
150
|
+
correctionsRead() {
|
|
151
|
+
return this.#json(CORRECTIONS_READ, {});
|
|
152
|
+
}
|
|
153
|
+
markCorrectionsRead(read) {
|
|
154
|
+
return this.#write(CORRECTIONS_READ, read);
|
|
155
|
+
}
|
|
156
|
+
#kindNames() {
|
|
157
|
+
return this.#json(KINDS, { reviewed: [], aliases: {} });
|
|
158
|
+
}
|
|
159
|
+
/** A JSON file's value, or `fallback` until the file is written. */
|
|
160
|
+
async #json(file, fallback) {
|
|
161
|
+
return readFile(join(this.root, file), "utf8").then((text) => JSON.parse(text), () => fallback);
|
|
162
|
+
}
|
|
163
|
+
async #write(file, value) {
|
|
164
|
+
await mkdir(this.root, { recursive: true, mode: 0o700 });
|
|
165
|
+
await writeWhole(join(this.root, file), JSON.stringify(value), 0o600);
|
|
166
|
+
}
|
|
167
|
+
async #append(file, value) {
|
|
168
|
+
await mkdir(this.root, { recursive: true, mode: 0o700 });
|
|
169
|
+
await appendFile(join(this.root, file), `${JSON.stringify(value)}\n`, { mode: 0o600 });
|
|
170
|
+
}
|
|
171
|
+
async #lines(file) {
|
|
172
|
+
const text = await readFile(join(this.root, file), "utf8").catch((error) => {
|
|
173
|
+
if (error.code === "ENOENT")
|
|
174
|
+
return "";
|
|
175
|
+
throw error;
|
|
176
|
+
});
|
|
177
|
+
return text.split("\n").filter((line) => line !== "").map((line) => JSON.parse(line));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** A session's entries as the loop reads them: converted to ACP when needed, and redacted. */
|
|
181
|
+
export async function readSession(source, secrets) {
|
|
182
|
+
const text = await readFile(source.path, "utf8");
|
|
183
|
+
return redactTranscript(source.kind === "acp" ? parseTranscript(text) : fromMessagesJsonl(text), secrets);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Reads every log that changed since it was last read: names each failure in it with the regular model, and asks it
|
|
187
|
+
* which of the user's messages correct the agent, naming each as a failure too, so the user confirms them by kind. A
|
|
188
|
+
* failure or correction already gathered is not asked about again.
|
|
189
|
+
*/
|
|
190
|
+
export async function harvest(evidence, sources, complete, secrets, onRead = () => { }) {
|
|
191
|
+
const seen = await evidence.seen();
|
|
192
|
+
const correctionsRead = await evidence.correctionsRead();
|
|
193
|
+
const failures = await evidence.failures();
|
|
194
|
+
const known = new Map();
|
|
195
|
+
const count = (signature) => {
|
|
196
|
+
const key = signatureKey(signature);
|
|
197
|
+
known.set(key, { signature, count: (known.get(key)?.count ?? 0) + 1 });
|
|
198
|
+
};
|
|
199
|
+
for (const failure of failures)
|
|
200
|
+
count(failure.signature);
|
|
201
|
+
const common = () => [...known.values()].sort((a, b) => b.count - a.count).map(({ signature }) => signature);
|
|
202
|
+
const had = new Set([...failures.map((failure) => `${failure.session}:${failure.line}`), ...await evidence.dismissed()]);
|
|
203
|
+
const asked = new Set((await evidence.corrections()).map((correction) => `${correction.session}:${correction.line}`));
|
|
204
|
+
const found = { read: 0, failures: 0, corrections: 0 };
|
|
205
|
+
for (const source of sources) {
|
|
206
|
+
const info = await stat(source.path);
|
|
207
|
+
const stamp = `${info.mtimeMs}:${info.size}`;
|
|
208
|
+
if (seen[source.path] === stamp)
|
|
209
|
+
continue;
|
|
210
|
+
const entries = await readSession(source, secrets);
|
|
211
|
+
const from = correctionsRead[source.path] ?? 0;
|
|
212
|
+
const start = { failures: found.failures, corrections: found.corrections };
|
|
213
|
+
// A log counts as read only once every signal in it got an answer, so an unreadable reply is asked again.
|
|
214
|
+
let answeredAll = true;
|
|
215
|
+
for (const signal of signals(entries)) {
|
|
216
|
+
const line = failureStep(entries, signal) ?? signal.line;
|
|
217
|
+
if (had.has(`${source.path}:${line}`))
|
|
218
|
+
continue;
|
|
219
|
+
const signature = await classify(entries, signal, common(), complete, source.kind === "messages");
|
|
220
|
+
if (signature === undefined) {
|
|
221
|
+
answeredAll = false;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
had.add(`${source.path}:${line}`);
|
|
225
|
+
if (signature === "not_a_failure") {
|
|
226
|
+
await evidence.dismiss(source.path, line);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
count(signature);
|
|
230
|
+
await evidence.addFailure({ session: source.path, line, signature, classifier: CLASSIFIER_VERSION });
|
|
231
|
+
found.failures += 1;
|
|
232
|
+
}
|
|
233
|
+
for (const candidate of await proposeCorrections(entries, complete, from)) {
|
|
234
|
+
if (asked.has(`${source.path}:${candidate.line}`))
|
|
235
|
+
continue;
|
|
236
|
+
asked.add(`${source.path}:${candidate.line}`);
|
|
237
|
+
// Named on its own; merging joins it to a failure's kind only when the mechanism is the same.
|
|
238
|
+
const signal = { kind: "corrected", line: candidate.line, summary: candidate.summary };
|
|
239
|
+
const signature = await classify(entries, signal, [], complete, source.kind === "messages");
|
|
240
|
+
if (signature === undefined || signature === "not_a_failure")
|
|
241
|
+
continue;
|
|
242
|
+
count(signature);
|
|
243
|
+
const step = correctedStep(entries, candidate.line) ?? candidate.line;
|
|
244
|
+
await evidence.addCorrection({ ...candidate, session: source.path, step, signature, classifier: CLASSIFIER_VERSION });
|
|
245
|
+
found.corrections += 1;
|
|
246
|
+
}
|
|
247
|
+
correctionsRead[source.path] = entries.length;
|
|
248
|
+
await evidence.markCorrectionsRead(correctionsRead);
|
|
249
|
+
if (answeredAll)
|
|
250
|
+
seen[source.path] = stamp;
|
|
251
|
+
await evidence.markSeen(seen);
|
|
252
|
+
found.read += 1;
|
|
253
|
+
onRead(source, { failures: found.failures - start.failures, corrections: found.corrections - start.corrections });
|
|
254
|
+
}
|
|
255
|
+
await evidence.mergeKinds(complete);
|
|
256
|
+
return found;
|
|
257
|
+
}
|
|
258
|
+
async function names(dir) {
|
|
259
|
+
return readdir(dir).catch((error) => {
|
|
260
|
+
if (error.code === "ENOENT")
|
|
261
|
+
return [];
|
|
262
|
+
throw error;
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
async function files(dir, kind) {
|
|
266
|
+
const entries = await readdir(dir, { withFileTypes: true, recursive: true }).catch((error) => {
|
|
267
|
+
if (error.code === "ENOENT")
|
|
268
|
+
return [];
|
|
269
|
+
throw error;
|
|
270
|
+
});
|
|
271
|
+
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl"))
|
|
272
|
+
.map((entry) => ({ path: join(entry.parentPath, entry.name), kind }));
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=harvest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest.js","sourceRoot":"","sources":["../../src/rsi/harvest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Proposal } from "@chopin-ai/core";
|
|
2
|
+
/** A proposal the audit could not settle, held for the user, and what the user decided on it. */
|
|
3
|
+
export interface HeldProposal {
|
|
4
|
+
id: string;
|
|
5
|
+
/** The kind of failure it answers. */
|
|
6
|
+
failure: string;
|
|
7
|
+
proposal: Proposal;
|
|
8
|
+
/** Why the audit asked for a person. */
|
|
9
|
+
reasons: string[];
|
|
10
|
+
decision?: "approved" | "refused" | "tested";
|
|
11
|
+
at: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Proposals held for the user as JSON Lines, the latest line for a proposal winning. An approved one replaces the
|
|
15
|
+
* audit only: it still goes through the gate in a later round, and is marked tested once it has.
|
|
16
|
+
*/
|
|
17
|
+
export declare class HeldProposals {
|
|
18
|
+
#private;
|
|
19
|
+
readonly path: string;
|
|
20
|
+
constructor(path: string);
|
|
21
|
+
/** Every proposal in its latest state. */
|
|
22
|
+
all(): Promise<HeldProposal[]>;
|
|
23
|
+
/** Proposals waiting for the user. */
|
|
24
|
+
waiting(): Promise<HeldProposal[]>;
|
|
25
|
+
/** The approved proposal for a kind of failure that no round has tested yet. */
|
|
26
|
+
approved(failure: string): Promise<HeldProposal | undefined>;
|
|
27
|
+
hold(held: Omit<HeldProposal, "at" | "decision">): Promise<void>;
|
|
28
|
+
decide(held: HeldProposal, decision: NonNullable<HeldProposal["decision"]>): Promise<void>;
|
|
29
|
+
}
|
package/dist/rsi/held.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { appendFile, mkdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Proposals held for the user as JSON Lines, the latest line for a proposal winning. An approved one replaces the
|
|
5
|
+
* audit only: it still goes through the gate in a later round, and is marked tested once it has.
|
|
6
|
+
*/
|
|
7
|
+
export class HeldProposals {
|
|
8
|
+
path;
|
|
9
|
+
constructor(path) {
|
|
10
|
+
this.path = path;
|
|
11
|
+
}
|
|
12
|
+
/** Every proposal in its latest state. */
|
|
13
|
+
async all() {
|
|
14
|
+
const text = await readFile(this.path, "utf8").catch((error) => {
|
|
15
|
+
if (error.code === "ENOENT")
|
|
16
|
+
return "";
|
|
17
|
+
throw error;
|
|
18
|
+
});
|
|
19
|
+
const latest = new Map();
|
|
20
|
+
for (const line of text.split("\n").filter((line) => line !== "")) {
|
|
21
|
+
const held = JSON.parse(line);
|
|
22
|
+
latest.set(held.id, held);
|
|
23
|
+
}
|
|
24
|
+
return [...latest.values()];
|
|
25
|
+
}
|
|
26
|
+
/** Proposals waiting for the user. */
|
|
27
|
+
async waiting() {
|
|
28
|
+
return (await this.all()).filter((held) => held.decision === undefined);
|
|
29
|
+
}
|
|
30
|
+
/** The approved proposal for a kind of failure that no round has tested yet. */
|
|
31
|
+
async approved(failure) {
|
|
32
|
+
return (await this.all()).find((held) => held.failure === failure && held.decision === "approved");
|
|
33
|
+
}
|
|
34
|
+
async hold(held) {
|
|
35
|
+
await this.#append({ ...held, at: new Date().toISOString() });
|
|
36
|
+
}
|
|
37
|
+
async decide(held, decision) {
|
|
38
|
+
await this.#append({ ...held, decision, at: new Date().toISOString() });
|
|
39
|
+
}
|
|
40
|
+
async #append(held) {
|
|
41
|
+
await mkdir(dirname(this.path), { recursive: true, mode: 0o700 });
|
|
42
|
+
await appendFile(this.path, `${JSON.stringify(held)}\n`, { mode: 0o600 });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=held.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"held.js","sourceRoot":"","sources":["../../src/rsi/held.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC;;;GAGG;AACH,MAAM,OAAO,aAAa;IACf,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,GAAG;QACP,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAA4B,EAAE,EAAE;YACpF,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,EAAE,CAAC;YACvC,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;QAC/C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAAC;YAC9C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,OAAO;QACX,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;IAC1E,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,QAAQ,CAAC,OAAe;QAC5B,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;IACrG,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAA2C;QACpD,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAkB,EAAE,QAA+C;QAC9E,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAkB;QAC9B,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type LayerVersions } from "@chopin-ai/core";
|
|
2
|
+
import { type Source } from "./harvest.js";
|
|
3
|
+
/**
|
|
4
|
+
* Archives the loop's skills that no recent session read, once they are older than the unused period; pinned ones
|
|
5
|
+
* stay. Instructions are left alone, since every session loads them and none records whether it followed one.
|
|
6
|
+
* Returns the ids archived; an archived item comes back with `chopin evolve undo`'s reverse, a new version.
|
|
7
|
+
*/
|
|
8
|
+
export declare function archiveUnused(versions: LayerVersions, sources: readonly Source[], secrets: readonly string[], now?: number): Promise<string[]>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { layerUsage } from "@chopin-ai/core";
|
|
2
|
+
import { readSession } from "./harvest.js";
|
|
3
|
+
/** How long a skill the loop added may go unread before it is archived. */
|
|
4
|
+
const UNUSED_MS = 30 * 24 * 60 * 60_000;
|
|
5
|
+
/**
|
|
6
|
+
* Archives the loop's skills that no recent session read, once they are older than the unused period; pinned ones
|
|
7
|
+
* stay. Instructions are left alone, since every session loads them and none records whether it followed one.
|
|
8
|
+
* Returns the ids archived; an archived item comes back with `chopin evolve undo`'s reverse, a new version.
|
|
9
|
+
*/
|
|
10
|
+
export async function archiveUnused(versions, sources, secrets, now = Date.now()) {
|
|
11
|
+
const items = await versions.items(await versions.current());
|
|
12
|
+
const old = items.filter((item) => item.kind === "skill" && !item.archived && !item.pinned && now - Date.parse(item.added) >= UNUSED_MS);
|
|
13
|
+
if (old.length === 0)
|
|
14
|
+
return [];
|
|
15
|
+
const read = new Set();
|
|
16
|
+
for (const source of sources) {
|
|
17
|
+
for (const name of layerUsage(await readSession(source, secrets), []).skills.keys())
|
|
18
|
+
read.add(name);
|
|
19
|
+
}
|
|
20
|
+
const unused = old.filter((item) => item.skill !== undefined && !read.has(item.skill)).map((item) => item.id);
|
|
21
|
+
if (unused.length > 0)
|
|
22
|
+
await versions.commit((all) => all.map((item) => (unused.includes(item.id) ? { ...item, archived: true } : item)));
|
|
23
|
+
return unused;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/rsi/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAe,MAAM,cAAc,CAAC;AAExD,2EAA2E;AAC3E,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAuB,EAAE,OAA0B,EAAE,OAA0B,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACnI,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,CAAC;IACzI,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,MAAM,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtG,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9G,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1I,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Api, type AssistantMessage, type Model, type Models } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { Complete } from "@chopin-ai/core";
|
|
3
|
+
/** What the loop has spent, as JSON Lines of US dollars at list prices, and the most it may spend in a week. */
|
|
4
|
+
export declare class Budget {
|
|
5
|
+
readonly path: string;
|
|
6
|
+
readonly weeklyUsd: number;
|
|
7
|
+
constructor(path: string, weeklyUsd: number);
|
|
8
|
+
/** Spent over the last seven days. */
|
|
9
|
+
spent(now?: number): Promise<number>;
|
|
10
|
+
charge(usd: number, now?: number): Promise<void>;
|
|
11
|
+
/** Throws once the week's budget is spent, so the loop stops before its next call. */
|
|
12
|
+
check(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export declare class BudgetSpent extends Error {
|
|
15
|
+
constructor(spent: number, weekly: number);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* One model call of the loop: refused once the budget is spent, tried again on a transient failure, and charged for
|
|
19
|
+
* every attempt. A call that still fails throws, so no judge ever reads a failed reply as the model's answer.
|
|
20
|
+
*/
|
|
21
|
+
export declare function paidCall(budget: Budget, call: () => Promise<AssistantMessage>): Promise<AssistantMessage>;
|
|
22
|
+
/** One prompt, one reply, from `model`, as a paid call. */
|
|
23
|
+
export declare function completer(models: Models, model: Model<Api>, budget: Budget): Complete;
|
|
24
|
+
/** The model `provider/id` names among `models`. */
|
|
25
|
+
export declare function namedModel(models: Models, name: string): Model<Api>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { appendFile, mkdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { retryAssistantCall } from "@earendil-works/pi-ai";
|
|
4
|
+
const WEEK_MS = 7 * 24 * 60 * 60_000;
|
|
5
|
+
/** What the loop has spent, as JSON Lines of US dollars at list prices, and the most it may spend in a week. */
|
|
6
|
+
export class Budget {
|
|
7
|
+
path;
|
|
8
|
+
weeklyUsd;
|
|
9
|
+
constructor(path, weeklyUsd) {
|
|
10
|
+
this.path = path;
|
|
11
|
+
this.weeklyUsd = weeklyUsd;
|
|
12
|
+
}
|
|
13
|
+
/** Spent over the last seven days. */
|
|
14
|
+
async spent(now = Date.now()) {
|
|
15
|
+
const text = await readFile(this.path, "utf8").catch((error) => {
|
|
16
|
+
if (error.code === "ENOENT")
|
|
17
|
+
return "";
|
|
18
|
+
throw error;
|
|
19
|
+
});
|
|
20
|
+
return text.split("\n").filter((line) => line !== "").map((line) => JSON.parse(line))
|
|
21
|
+
.filter((charge) => now - charge.at < WEEK_MS).reduce((sum, charge) => sum + charge.usd, 0);
|
|
22
|
+
}
|
|
23
|
+
async charge(usd, now = Date.now()) {
|
|
24
|
+
await mkdir(dirname(this.path), { recursive: true });
|
|
25
|
+
await appendFile(this.path, `${JSON.stringify({ at: now, usd })}\n`);
|
|
26
|
+
}
|
|
27
|
+
/** Throws once the week's budget is spent, so the loop stops before its next call. */
|
|
28
|
+
async check() {
|
|
29
|
+
const spent = await this.spent();
|
|
30
|
+
if (spent >= this.weeklyUsd)
|
|
31
|
+
throw new BudgetSpent(spent, this.weeklyUsd);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export class BudgetSpent extends Error {
|
|
35
|
+
constructor(spent, weekly) {
|
|
36
|
+
super(`the loop has spent $${spent.toFixed(2)} of its $${weekly.toFixed(2)} for the week`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Transient failures, such as a dropped connection, are tried again for about a minute. */
|
|
40
|
+
const RETRY = { enabled: true, maxRetries: 5, baseDelayMs: 2_000 };
|
|
41
|
+
/**
|
|
42
|
+
* One model call of the loop: refused once the budget is spent, tried again on a transient failure, and charged for
|
|
43
|
+
* every attempt. A call that still fails throws, so no judge ever reads a failed reply as the model's answer.
|
|
44
|
+
*/
|
|
45
|
+
export async function paidCall(budget, call) {
|
|
46
|
+
await budget.check();
|
|
47
|
+
const reply = await retryAssistantCall(async () => {
|
|
48
|
+
const attempt = await call();
|
|
49
|
+
await budget.charge(attempt.usage.cost.total);
|
|
50
|
+
return attempt;
|
|
51
|
+
}, RETRY, undefined);
|
|
52
|
+
if (reply.stopReason === "error" || reply.stopReason === "aborted")
|
|
53
|
+
throw new Error(reply.errorMessage ?? `the model's call ended: ${reply.stopReason}`);
|
|
54
|
+
return reply;
|
|
55
|
+
}
|
|
56
|
+
/** One prompt, one reply, from `model`, as a paid call. */
|
|
57
|
+
export function completer(models, model, budget) {
|
|
58
|
+
return async (prompt) => {
|
|
59
|
+
const reply = await paidCall(budget, () => models.completeSimple(model, { messages: [{ role: "user", content: prompt, timestamp: Date.now() }] }));
|
|
60
|
+
return reply.content.flatMap((block) => (block.type === "text" ? [block.text] : [])).join("\n");
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** The model `provider/id` names among `models`. */
|
|
64
|
+
export function namedModel(models, name) {
|
|
65
|
+
const slash = name.indexOf("/");
|
|
66
|
+
const model = slash <= 0 ? undefined : models.getModel(name.slice(0, slash), name.slice(slash + 1));
|
|
67
|
+
if (model === undefined)
|
|
68
|
+
throw new Error(`no model ${name}; it is named as provider/model, signed in with /login`);
|
|
69
|
+
return model;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/rsi/models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AdmissionLedger, Calibration, LayerVersions, Rejections } from "@chopin-ai/core";
|
|
2
|
+
import { Evidence } from "./harvest.js";
|
|
3
|
+
import { HeldProposals } from "./held.js";
|
|
4
|
+
/** The loop's records, by where they are kept. */
|
|
5
|
+
export declare function records(): {
|
|
6
|
+
evidence: Evidence;
|
|
7
|
+
versions: LayerVersions;
|
|
8
|
+
ledger: AdmissionLedger;
|
|
9
|
+
rejections: Rejections;
|
|
10
|
+
calibration: Calibration;
|
|
11
|
+
certificates: string;
|
|
12
|
+
spend: string;
|
|
13
|
+
held: HeldProposals;
|
|
14
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { AdmissionLedger, Calibration, LayerVersions, Rejections } from "@chopin-ai/core";
|
|
3
|
+
import { rsiDirectory } from "../home.js";
|
|
4
|
+
import { Evidence } from "./harvest.js";
|
|
5
|
+
import { HeldProposals } from "./held.js";
|
|
6
|
+
/** The loop's records, by where they are kept. */
|
|
7
|
+
export function records() {
|
|
8
|
+
const root = rsiDirectory();
|
|
9
|
+
return {
|
|
10
|
+
evidence: new Evidence(join(root, "evidence")),
|
|
11
|
+
versions: new LayerVersions(join(root, "layer")),
|
|
12
|
+
ledger: new AdmissionLedger(join(root, "ledger.jsonl")),
|
|
13
|
+
rejections: new Rejections(join(root, "rejections.jsonl")),
|
|
14
|
+
calibration: new Calibration(join(root, "calibration.jsonl")),
|
|
15
|
+
certificates: join(root, "certificates"),
|
|
16
|
+
spend: join(root, "spend.jsonl"),
|
|
17
|
+
held: new HeldProposals(join(root, "held.jsonl")),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/rsi/records.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,kDAAkD;AAClD,MAAM,UAAU,OAAO;IACrB,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,OAAO;QACL,QAAQ,EAAE,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC9C,QAAQ,EAAE,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,EAAE,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACvD,UAAU,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;QAC1D,WAAW,EAAE,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;QAC7D,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC;QACxC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;QAChC,IAAI,EAAE,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;KAClD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type AdmissionLedger, type Certificate, type Complete, type Layer, type LayerVersions, type Rejections, type TranscriptEntry } from "@chopin-ai/core";
|
|
2
|
+
import { type Evidence, type Source } from "./harvest.js";
|
|
3
|
+
import type { HeldProposals } from "./held.js";
|
|
4
|
+
/** Whether a round has lost enough of the points it tried, and so many of them, to probe the provider. */
|
|
5
|
+
export declare function tripsBreaker(lost: number, attempted: number): boolean;
|
|
6
|
+
/** Everything a round works with; the models and the continuation are passed in, so a test can stand in for them. */
|
|
7
|
+
export interface RoundSetup {
|
|
8
|
+
evidence: Evidence;
|
|
9
|
+
sources: readonly Source[];
|
|
10
|
+
versions: LayerVersions;
|
|
11
|
+
/** The versions of the project a session belongs to, for changes that hold only there; none when it cannot be told. */
|
|
12
|
+
projectOf: (session: string) => {
|
|
13
|
+
key: string;
|
|
14
|
+
versions: LayerVersions;
|
|
15
|
+
} | undefined;
|
|
16
|
+
/** The hand-written layer the loop's items are laid over. */
|
|
17
|
+
base: Layer;
|
|
18
|
+
ledger: AdmissionLedger;
|
|
19
|
+
rejections: Rejections;
|
|
20
|
+
/** Where certificates are written. */
|
|
21
|
+
certificates: string;
|
|
22
|
+
propose: Complete;
|
|
23
|
+
judge: Complete;
|
|
24
|
+
/** The agent's next step at a decision point, with `layer`, from the session up to it. */
|
|
25
|
+
continueStep: (layer: Layer, prefix: readonly TranscriptEntry[]) => Promise<string>;
|
|
26
|
+
/** Practices the user has ruled out, for the auditor. */
|
|
27
|
+
rules: string;
|
|
28
|
+
/** The model continuations run on, as `provider/model`. */
|
|
29
|
+
model: string;
|
|
30
|
+
secrets: readonly string[];
|
|
31
|
+
limit?: number;
|
|
32
|
+
random?: () => number;
|
|
33
|
+
/** Told of each decision point a round leaves out because a call on it failed. */
|
|
34
|
+
report?: (error: unknown) => void;
|
|
35
|
+
held: HeldProposals;
|
|
36
|
+
/** Whether a proposal the audit cannot settle waits for the user, rather than being refused. */
|
|
37
|
+
holdForReview?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type RoundOutcome = {
|
|
40
|
+
failure: string;
|
|
41
|
+
outcome: "kept";
|
|
42
|
+
version: number;
|
|
43
|
+
certificate: Certificate;
|
|
44
|
+
} | {
|
|
45
|
+
failure: string;
|
|
46
|
+
outcome: "refused";
|
|
47
|
+
reason: string;
|
|
48
|
+
certificate?: Certificate;
|
|
49
|
+
} | {
|
|
50
|
+
failure: string;
|
|
51
|
+
outcome: "set_aside";
|
|
52
|
+
reason: string;
|
|
53
|
+
} | {
|
|
54
|
+
failure: string;
|
|
55
|
+
outcome: "held";
|
|
56
|
+
reason: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Runs a round for every kind of failure that recurred, has no change kept for it yet, and is not set aside: first
|
|
60
|
+
* the kinds the user confirmed a correction of, then the rest, each in order of how many sessions it came from.
|
|
61
|
+
*/
|
|
62
|
+
export declare function runRounds(setup: RoundSetup, onOutcome?: (outcome: RoundOutcome) => void): Promise<RoundOutcome[]>;
|