@earendil-works/pi-durable 0.99.2 → 1.0.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 +7 -0
- package/README.md +196 -74
- package/dist/env/index.d.ts +5 -0
- package/dist/env/index.d.ts.map +1 -1
- package/dist/env/index.js.map +1 -1
- package/dist/env/node.d.ts +2 -0
- package/dist/env/node.d.ts.map +1 -1
- package/dist/env/node.js +2 -0
- package/dist/env/node.js.map +1 -1
- package/dist/harness/agent.d.ts +31 -0
- package/dist/harness/agent.d.ts.map +1 -0
- package/dist/harness/agent.js +209 -0
- package/dist/harness/agent.js.map +1 -0
- package/dist/harness/compaction.d.ts.map +1 -1
- package/dist/harness/compaction.js +8 -11
- package/dist/harness/compaction.js.map +1 -1
- package/dist/harness/define.d.ts +18 -0
- package/dist/harness/define.d.ts.map +1 -0
- package/dist/harness/define.js +25 -0
- package/dist/harness/define.js.map +1 -0
- package/dist/harness/events.d.ts +5 -5
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +6 -6
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/generation.d.ts +2 -4
- package/dist/harness/generation.d.ts.map +1 -1
- package/dist/harness/generation.js +39 -43
- package/dist/harness/generation.js.map +1 -1
- package/dist/harness/harness.d.ts.map +1 -1
- package/dist/harness/harness.js +68 -154
- package/dist/harness/harness.js.map +1 -1
- package/dist/harness/inbox.d.ts +4 -2
- package/dist/harness/inbox.d.ts.map +1 -1
- package/dist/harness/inbox.js +3 -5
- package/dist/harness/inbox.js.map +1 -1
- package/dist/harness/prompt.d.ts +1 -3
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +1 -11
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/registry.d.ts +2 -3
- package/dist/harness/registry.d.ts.map +1 -1
- package/dist/harness/registry.js +66 -283
- package/dist/harness/registry.js.map +1 -1
- package/dist/harness/scheduler.d.ts +7 -2
- package/dist/harness/scheduler.d.ts.map +1 -1
- package/dist/harness/scheduler.js +41 -27
- package/dist/harness/scheduler.js.map +1 -1
- package/dist/harness/submissions.d.ts +4 -4
- package/dist/harness/submissions.d.ts.map +1 -1
- package/dist/harness/submissions.js +7 -4
- package/dist/harness/submissions.js.map +1 -1
- package/dist/harness/task-graph.d.ts +49 -0
- package/dist/harness/task-graph.d.ts.map +1 -0
- package/dist/harness/task-graph.js +163 -0
- package/dist/harness/task-graph.js.map +1 -0
- package/dist/harness/tool.d.ts +1 -1
- package/dist/harness/tool.d.ts.map +1 -1
- package/dist/harness/tool.js +9 -6
- package/dist/harness/tool.js.map +1 -1
- package/dist/harness/types.d.ts +171 -140
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/view.d.ts +1 -1
- package/dist/harness/view.d.ts.map +1 -1
- package/dist/harness/view.js +2 -7
- package/dist/harness/view.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/session/session.d.ts.map +1 -1
- package/dist/session/session.js +5 -1
- package/dist/session/session.js.map +1 -1
- package/dist/session/transaction.d.ts +2 -2
- package/dist/session/transaction.d.ts.map +1 -1
- package/dist/session/transaction.js +7 -4
- package/dist/session/transaction.js.map +1 -1
- package/dist/storage/sqlite/database.d.ts +26 -19
- package/dist/storage/sqlite/database.d.ts.map +1 -1
- package/dist/storage/sqlite/database.js.map +1 -1
- package/dist/storage/sqlite/index.d.ts +1 -1
- package/dist/storage/sqlite/index.d.ts.map +1 -1
- package/dist/storage/sqlite/index.js.map +1 -1
- package/dist/storage/sqlite/migrations.js +6 -6
- package/dist/storage/sqlite/migrations.js.map +1 -1
- package/dist/storage/sqlite/node.d.ts +23 -7
- package/dist/storage/sqlite/node.d.ts.map +1 -1
- package/dist/storage/sqlite/node.js +129 -47
- package/dist/storage/sqlite/node.js.map +1 -1
- package/dist/storage/sqlite/storage.d.ts +12 -0
- package/dist/storage/sqlite/storage.d.ts.map +1 -1
- package/dist/storage/sqlite/storage.js +121 -129
- package/dist/storage/sqlite/storage.js.map +1 -1
- package/dist/tools/bash.d.ts +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +3 -2
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts +3 -3
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +5 -4
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/file-mutation-queue.d.ts +5 -1
- package/dist/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/tools/file-mutation-queue.js +39 -33
- package/dist/tools/file-mutation-queue.js.map +1 -1
- package/dist/tools/index.d.ts +18 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +10 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/read.d.ts +3 -3
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +4 -3
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/write.d.ts +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +3 -2
- package/dist/tools/write.js.map +1 -1
- package/dist/types.d.ts +15 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +25 -15
- package/dist/harness/config.d.ts +0 -29
- package/dist/harness/config.d.ts.map +0 -1
- package/dist/harness/config.js +0 -24
- package/dist/harness/config.js.map +0 -1
- package/docs/chord-delta-findings.md +0 -358
- package/docs/pico-v5-chord-usage.md +0 -373
- package/docs/pico-v5-handoff.md +0 -861
- package/docs/pico-v5.md +0 -4174
package/dist/harness/harness.js
CHANGED
|
@@ -2,14 +2,15 @@ import { withAbortSignal, withoutAbortSignal } from "@earendil-works/chord/conte
|
|
|
2
2
|
import { ResetEntry } from "../entries.js";
|
|
3
3
|
import { SessionImpl } from "../session/session.js";
|
|
4
4
|
import { ROOT_CONVERSATION_ID } from "../types.js";
|
|
5
|
+
import { AgentDoc, configure, createAgent, resolveAgent, resolveSettings } from "./agent.js";
|
|
5
6
|
import { createCompaction } from "./compaction.js";
|
|
6
|
-
import { ConversationConfig, DEFAULT_COMPACTION_POLICY, DEFAULT_RETRY_POLICY, } from "./config.js";
|
|
7
7
|
import { readContext } from "./context.js";
|
|
8
|
-
import { withdrawQueuedInputs } from "./inbox.js";
|
|
9
|
-
import { settleSchedulerOutcome } from "./live.js";
|
|
10
|
-
import {
|
|
8
|
+
import { InboxDoc, withdrawQueuedInputs } from "./inbox.js";
|
|
9
|
+
import { LiveDoc, settleSchedulerOutcome } from "./live.js";
|
|
10
|
+
import { BUILTIN_TASKS } from "./registry.js";
|
|
11
11
|
import { TaskScheduler } from "./scheduler.js";
|
|
12
12
|
import { Submissions } from "./submissions.js";
|
|
13
|
+
import { TaskGraphView } from "./task-graph.js";
|
|
13
14
|
import { addUsageState, UsageDoc } from "./usage.js";
|
|
14
15
|
import { scanAll } from "./util.js";
|
|
15
16
|
import { ConversationViews } from "./view.js";
|
|
@@ -21,98 +22,11 @@ class ConversationImpl {
|
|
|
21
22
|
this.id = id;
|
|
22
23
|
this.#host = host;
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
-
return
|
|
25
|
+
agent(context) {
|
|
26
|
+
return this.#host.harness.resolveAgent(this.id, undefined, context);
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
return this.#
|
|
29
|
-
if (model === undefined)
|
|
30
|
-
delete config.model;
|
|
31
|
-
else
|
|
32
|
-
config.model = { provider: model.provider, modelId: model.modelId };
|
|
33
|
-
}, context);
|
|
34
|
-
}
|
|
35
|
-
async getThinkingLevel(context) {
|
|
36
|
-
return (await this.#config(context)).thinkingLevel;
|
|
37
|
-
}
|
|
38
|
-
setThinkingLevel(level, context) {
|
|
39
|
-
return this.#editConfig((config) => {
|
|
40
|
-
config.thinkingLevel = level;
|
|
41
|
-
}, context);
|
|
42
|
-
}
|
|
43
|
-
async getActiveTools(context) {
|
|
44
|
-
return (await this.#config(context)).activeTools;
|
|
45
|
-
}
|
|
46
|
-
setActiveTools(names, context) {
|
|
47
|
-
return this.#editConfig((config) => {
|
|
48
|
-
if (new Set(names).size !== names.length)
|
|
49
|
-
throw new Error("Active tools list a name more than once");
|
|
50
|
-
requireRegistered(this.#host.registry.snapshot(), names, config.activeTools);
|
|
51
|
-
config.activeTools = [...names];
|
|
52
|
-
}, context);
|
|
53
|
-
}
|
|
54
|
-
async getStreamOptions(context) {
|
|
55
|
-
return (await this.#config(context)).streamOptions ?? {};
|
|
56
|
-
}
|
|
57
|
-
setStreamOptions(options, context) {
|
|
58
|
-
return this.#editConfig((config) => {
|
|
59
|
-
config.streamOptions = options;
|
|
60
|
-
}, context);
|
|
61
|
-
}
|
|
62
|
-
async getRetryPolicy(context) {
|
|
63
|
-
return (await this.#config(context)).retry ?? { ...DEFAULT_RETRY_POLICY };
|
|
64
|
-
}
|
|
65
|
-
setRetryPolicy(policy, context) {
|
|
66
|
-
return this.#editConfig((config) => {
|
|
67
|
-
if (policy === undefined)
|
|
68
|
-
delete config.retry;
|
|
69
|
-
else
|
|
70
|
-
config.retry = policy;
|
|
71
|
-
}, context);
|
|
72
|
-
}
|
|
73
|
-
async getToolExecution(context) {
|
|
74
|
-
return (await this.#config(context)).toolExecution ?? "parallel";
|
|
75
|
-
}
|
|
76
|
-
setToolExecution(mode, context) {
|
|
77
|
-
return this.#editConfig((config) => {
|
|
78
|
-
if (mode === undefined)
|
|
79
|
-
delete config.toolExecution;
|
|
80
|
-
else
|
|
81
|
-
config.toolExecution = mode;
|
|
82
|
-
}, context);
|
|
83
|
-
}
|
|
84
|
-
async getSteeringMode(context) {
|
|
85
|
-
return (await this.#config(context)).steeringMode ?? "one-at-a-time";
|
|
86
|
-
}
|
|
87
|
-
setSteeringMode(mode, context) {
|
|
88
|
-
return this.#editConfig((config) => {
|
|
89
|
-
if (mode === undefined)
|
|
90
|
-
delete config.steeringMode;
|
|
91
|
-
else
|
|
92
|
-
config.steeringMode = mode;
|
|
93
|
-
}, context);
|
|
94
|
-
}
|
|
95
|
-
async getFollowUpMode(context) {
|
|
96
|
-
return (await this.#config(context)).followUpMode ?? "one-at-a-time";
|
|
97
|
-
}
|
|
98
|
-
setFollowUpMode(mode, context) {
|
|
99
|
-
return this.#editConfig((config) => {
|
|
100
|
-
if (mode === undefined)
|
|
101
|
-
delete config.followUpMode;
|
|
102
|
-
else
|
|
103
|
-
config.followUpMode = mode;
|
|
104
|
-
}, context);
|
|
105
|
-
}
|
|
106
|
-
async getCompaction(context) {
|
|
107
|
-
return (await this.#config(context)).compaction ?? { ...DEFAULT_COMPACTION_POLICY };
|
|
108
|
-
}
|
|
109
|
-
setCompaction(policy, context) {
|
|
110
|
-
return this.#editConfig((config) => {
|
|
111
|
-
if (policy === undefined)
|
|
112
|
-
delete config.compaction;
|
|
113
|
-
else
|
|
114
|
-
config.compaction = policy;
|
|
115
|
-
}, context);
|
|
28
|
+
configure(change, context) {
|
|
29
|
+
return this.#host.harness.commitWith((tx) => configure(tx, this.id, change), context);
|
|
116
30
|
}
|
|
117
31
|
submit(submission, context) {
|
|
118
32
|
return this.#host.submissions.submit(this.id, submission, context);
|
|
@@ -144,7 +58,7 @@ class ConversationImpl {
|
|
|
144
58
|
return this.#host.harness.readOnLine(() => this.#host.storage.scanEntries(bounded, limit, cursor, context));
|
|
145
59
|
}
|
|
146
60
|
fork(at, options, context) {
|
|
147
|
-
return this.#host.create({ kind: "fork", parentId: this.id, at, ownership: options.ownership }, options
|
|
61
|
+
return this.#host.create({ kind: "fork", parentId: this.id, at, ownership: options.ownership }, options, context);
|
|
148
62
|
}
|
|
149
63
|
abort(context, options) {
|
|
150
64
|
this.#host.tasks.resume();
|
|
@@ -160,38 +74,34 @@ class ConversationImpl {
|
|
|
160
74
|
watch(context) {
|
|
161
75
|
return this.#host.views.watch(this.id, context);
|
|
162
76
|
}
|
|
163
|
-
async #config(context) {
|
|
164
|
-
return ((await this.#host.harness.snapshot(ConversationConfig, this.id, context)) ??
|
|
165
|
-
ConversationConfig.definition.initial());
|
|
166
|
-
}
|
|
167
|
-
#editConfig(edit, context) {
|
|
168
|
-
return this.#host.harness.commitWith(async (tx) => {
|
|
169
|
-
edit(await tx.doc(ConversationConfig, this.id));
|
|
170
|
-
}, context);
|
|
171
|
-
}
|
|
172
77
|
}
|
|
173
78
|
/** Session kernel extended with conversation handles and a registry. */
|
|
174
79
|
class HarnessImpl extends SessionImpl {
|
|
175
80
|
#storage;
|
|
176
|
-
#
|
|
81
|
+
#options;
|
|
82
|
+
#report;
|
|
177
83
|
#host;
|
|
178
84
|
#tasks;
|
|
179
85
|
#submissions;
|
|
180
|
-
#
|
|
86
|
+
#taskGraph;
|
|
181
87
|
#closed = false;
|
|
182
88
|
constructor(storage, options, context) {
|
|
183
89
|
super(storage);
|
|
184
90
|
this.#storage = storage;
|
|
185
|
-
this.#
|
|
91
|
+
this.#options = options;
|
|
92
|
+
this.#report = options.onReport ?? (() => { });
|
|
186
93
|
const now = options.now ?? Date.now;
|
|
94
|
+
const settings = () => resolveSettings(options.settings);
|
|
187
95
|
this.#tasks = new TaskScheduler({
|
|
188
96
|
session: this,
|
|
189
97
|
storage,
|
|
190
98
|
registry: options.registry,
|
|
191
99
|
models: options.models,
|
|
192
|
-
|
|
100
|
+
agent: (id, snapshot, callContext) => this.resolveAgent(id, snapshot, callContext),
|
|
101
|
+
settings,
|
|
102
|
+
env: (id, callContext) => this.buildEnv(id, callContext),
|
|
193
103
|
now,
|
|
194
|
-
report:
|
|
104
|
+
report: this.#report,
|
|
195
105
|
settleOutcome: settleSchedulerOutcome,
|
|
196
106
|
withdrawInputs: withdrawQueuedInputs,
|
|
197
107
|
conversation: async (id, binding, callContext) => {
|
|
@@ -200,18 +110,32 @@ class HarnessImpl extends SessionImpl {
|
|
|
200
110
|
},
|
|
201
111
|
context: withoutAbortSignal(context),
|
|
202
112
|
});
|
|
203
|
-
this.#submissions = new Submissions(this, storage, now, () => this.#tasks.resume());
|
|
113
|
+
this.#submissions = new Submissions(this, storage, now, settings, () => this.#tasks.resume());
|
|
114
|
+
this.#taskGraph = new TaskGraphView(this, storage);
|
|
204
115
|
this.#host = {
|
|
205
116
|
harness: this,
|
|
206
117
|
storage,
|
|
207
|
-
registry: options.registry,
|
|
208
118
|
tasks: this.#tasks,
|
|
209
119
|
submissions: this.#submissions,
|
|
210
120
|
views: new ConversationViews(this, storage),
|
|
211
121
|
now,
|
|
212
|
-
create: (target,
|
|
122
|
+
create: (target, createOptions, context) => this.#create(target, createOptions, context),
|
|
213
123
|
};
|
|
214
124
|
}
|
|
125
|
+
/** Resolve a conversation's committed `pi.agent` against `snapshot`, or the current one, and the current settings. */
|
|
126
|
+
async resolveAgent(id, snapshot, context) {
|
|
127
|
+
const registry = snapshot ?? this.#options.registry.snapshot();
|
|
128
|
+
const state = await this.snapshot(AgentDoc, id, context);
|
|
129
|
+
return resolveAgent(state, registry, resolveSettings(this.#options.settings), this.#report);
|
|
130
|
+
}
|
|
131
|
+
/** Build a conversation's environment from its current `cwd`; `undefined` without an `env` option. */
|
|
132
|
+
async buildEnv(id, context) {
|
|
133
|
+
const build = this.#options.env;
|
|
134
|
+
if (build === undefined)
|
|
135
|
+
return undefined;
|
|
136
|
+
const cwd = (await this.snapshot(AgentDoc, id, context))?.cwd;
|
|
137
|
+
return build({ conversationId: id, ...(cwd === undefined ? {} : { cwd }), read: this }, context);
|
|
138
|
+
}
|
|
215
139
|
/** Reconcile surviving `running` tasks to `pending`; part of open. */
|
|
216
140
|
openTasks(context) {
|
|
217
141
|
return this.#tasks.open(context);
|
|
@@ -225,11 +149,10 @@ class HarnessImpl extends SessionImpl {
|
|
|
225
149
|
}
|
|
226
150
|
inspect(context) {
|
|
227
151
|
return this.readOnLine(async () => {
|
|
228
|
-
const
|
|
229
|
-
const { scheduling, tasks } = await this.#tasks.inspect(snapshot);
|
|
152
|
+
const { scheduling, tasks } = await this.#tasks.inspect(this.#options.registry.snapshot());
|
|
230
153
|
const scan = (status) => scanAll((cursor) => this.#storage.scanSubmissions({ status }, SCAN_PAGE_SIZE, cursor, context));
|
|
231
154
|
const submissions = [...(await scan("queued")), ...(await scan("placed"))].sort((a, b) => a.id - b.id);
|
|
232
|
-
return { scheduling, tasks, submissions
|
|
155
|
+
return { scheduling, tasks, submissions };
|
|
233
156
|
});
|
|
234
157
|
}
|
|
235
158
|
submission(id, context) {
|
|
@@ -260,8 +183,14 @@ class HarnessImpl extends SessionImpl {
|
|
|
260
183
|
}
|
|
261
184
|
return total;
|
|
262
185
|
}
|
|
186
|
+
taskGraph(context) {
|
|
187
|
+
return this.#taskGraph.state(context);
|
|
188
|
+
}
|
|
189
|
+
watchTaskGraph(context) {
|
|
190
|
+
return this.#taskGraph.watch(context);
|
|
191
|
+
}
|
|
263
192
|
root(context, options) {
|
|
264
|
-
return this.#create({ kind: "root" }, options
|
|
193
|
+
return this.#create({ kind: "root" }, options ?? {}, context);
|
|
265
194
|
}
|
|
266
195
|
async conversation(id, context) {
|
|
267
196
|
this.#assertOpen();
|
|
@@ -269,7 +198,7 @@ class HarnessImpl extends SessionImpl {
|
|
|
269
198
|
return record === undefined ? undefined : new ConversationImpl(record.id, this.#host);
|
|
270
199
|
}
|
|
271
200
|
createConversation(options, context) {
|
|
272
|
-
return this.#create({ kind: "independent", ownership: options.ownership }, options
|
|
201
|
+
return this.#create({ kind: "independent", ownership: options.ownership }, options, context);
|
|
273
202
|
}
|
|
274
203
|
close(context) {
|
|
275
204
|
this.#closed = true;
|
|
@@ -279,7 +208,7 @@ class HarnessImpl extends SessionImpl {
|
|
|
279
208
|
beforeClose() {
|
|
280
209
|
return this.#tasks.join();
|
|
281
210
|
}
|
|
282
|
-
async #create(target,
|
|
211
|
+
async #create(target, options, context) {
|
|
283
212
|
this.#assertOpen();
|
|
284
213
|
const id = await this.commitWith(async (tx) => {
|
|
285
214
|
if (target.kind === "root" && (await tx.conversation(ROOT_CONVERSATION_ID)) !== undefined) {
|
|
@@ -290,33 +219,24 @@ class HarnessImpl extends SessionImpl {
|
|
|
290
219
|
: target.kind === "fork"
|
|
291
220
|
? await tx.forkConversation(target.parentId, target.at, { ownership: target.ownership })
|
|
292
221
|
: await tx.createConversation({ ownership: target.ownership });
|
|
293
|
-
if (
|
|
294
|
-
await
|
|
222
|
+
if (options.agent !== undefined)
|
|
223
|
+
await configure(tx, record.id, options.agent);
|
|
224
|
+
if (options.init !== undefined)
|
|
225
|
+
await options.init(tx, record.id);
|
|
295
226
|
return record.id;
|
|
296
227
|
}, context);
|
|
297
228
|
return new ConversationImpl(id, this.#host);
|
|
298
229
|
}
|
|
299
|
-
/**
|
|
230
|
+
/**
|
|
231
|
+
* The built-in creation hook, in every commit that creates or forks a conversation: empty `pi.live`, `pi.inbox`, and
|
|
232
|
+
* `pi.usage`, the conversation's `pi.agent` (see `createAgent()`), then `HarnessOptions.conversationCreated`.
|
|
233
|
+
*/
|
|
300
234
|
async conversationCreated(tx, record) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
async #runInit(tx, id, init) {
|
|
307
|
-
const snapshot = this.#snapshotOf(tx);
|
|
308
|
-
const baseline = [...(await tx.doc(ConversationConfig, id)).activeTools];
|
|
309
|
-
await init(tx, id);
|
|
310
|
-
requireRegistered(snapshot, (await tx.doc(ConversationConfig, id)).activeTools, baseline);
|
|
311
|
-
}
|
|
312
|
-
/** One registry snapshot per commit, shared by its conversation setups and `init` checks. */
|
|
313
|
-
#snapshotOf(tx) {
|
|
314
|
-
let snapshot = this.#snapshots.get(tx);
|
|
315
|
-
if (snapshot === undefined) {
|
|
316
|
-
snapshot = this.#registry.snapshot();
|
|
317
|
-
this.#snapshots.set(tx, snapshot);
|
|
318
|
-
}
|
|
319
|
-
return snapshot;
|
|
235
|
+
await tx.doc(LiveDoc, record.id);
|
|
236
|
+
await tx.doc(InboxDoc, record.id);
|
|
237
|
+
await tx.doc(UsageDoc, record.id);
|
|
238
|
+
await createAgent(tx, record);
|
|
239
|
+
await this.#options.conversationCreated?.(tx, record);
|
|
320
240
|
}
|
|
321
241
|
#assertOpen() {
|
|
322
242
|
if (this.#closed)
|
|
@@ -354,31 +274,25 @@ function boundConversation(id, binding, submissions, tasks) {
|
|
|
354
274
|
waitForIdle: bound((callContext) => tasks.waitForIdle(id, callContext)),
|
|
355
275
|
};
|
|
356
276
|
}
|
|
357
|
-
/** Reject names newly added relative to `previous` that `snapshot` does not register; existing names are never rechecked. */
|
|
358
|
-
function requireRegistered(snapshot, names, previous) {
|
|
359
|
-
const existing = new Set(previous);
|
|
360
|
-
const registered = new Set(snapshot.toolNames());
|
|
361
|
-
const missing = names.filter((name) => !existing.has(name) && !registered.has(name));
|
|
362
|
-
if (missing.length > 0)
|
|
363
|
-
throw new Error(`Tools are not registered: ${missing.join(", ")}`);
|
|
364
|
-
}
|
|
365
277
|
export const Harness = {
|
|
366
278
|
/** Open a Harness over storage. The registry may keep changing while the Harness runs. */
|
|
367
279
|
async open(storage, options, context) {
|
|
368
280
|
context.abortSignal?.throwIfAborted();
|
|
369
281
|
const snapshot = options.registry.snapshot();
|
|
370
|
-
const missing = BUILTIN_TASKS.filter((task) => snapshot.task(task.definition.name) === undefined)
|
|
371
|
-
if (!snapshot.conversationSetups().some(({ key }) => key === BUILTIN_SETUP_KEY))
|
|
372
|
-
missing.push("conversation setup pi");
|
|
282
|
+
const missing = BUILTIN_TASKS.filter((task) => snapshot.task(task.definition.name) === undefined);
|
|
373
283
|
if (missing.length > 0) {
|
|
374
|
-
|
|
284
|
+
const names = missing.map((task) => task.definition.name).join(", ");
|
|
285
|
+
throw new Error(`Registry lacks built-in tasks ${names}; create it with createRegistry()`);
|
|
375
286
|
}
|
|
376
287
|
const harness = new HarnessImpl(storage, options, context);
|
|
377
288
|
try {
|
|
378
289
|
await harness.openTasks(context);
|
|
379
290
|
}
|
|
380
291
|
catch (error) {
|
|
381
|
-
|
|
292
|
+
// The caller's context may be what failed open: close without it, and rethrow the open error.
|
|
293
|
+
await harness
|
|
294
|
+
.close(withoutAbortSignal(context))
|
|
295
|
+
.catch((closeError) => options.onReport?.(closeError));
|
|
382
296
|
throw error;
|
|
383
297
|
}
|
|
384
298
|
return harness;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/harness/harness.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AttachedReplicatedState, Context, Draft, JsonValue } from \"@earendil-works/chord\";\nimport { withAbortSignal, withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport type { ModelThinkingLevel } from \"@earendil-works/pi-ai\";\nimport { ResetEntry } from \"../entries.ts\";\nimport { SessionImpl } from \"../session/session.ts\";\nimport type { Transaction } from \"../session/transaction.ts\";\nimport type {\n\tConversationId,\n\tConversationOwnership,\n\tConversationRecord,\n\tCursor,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tPage,\n\tStorage,\n\tSubmissionId,\n\tTaskId,\n\tTaskRecord,\n\tTx,\n\tWatchHandle,\n} from \"../types.ts\";\nimport { ROOT_CONVERSATION_ID } from \"../types.ts\";\nimport { createCompaction } from \"./compaction.ts\";\nimport {\n\tConversationConfig,\n\ttype ConversationConfigState,\n\tDEFAULT_COMPACTION_POLICY,\n\tDEFAULT_RETRY_POLICY,\n} from \"./config.ts\";\nimport { readContext } from \"./context.ts\";\nimport { withdrawQueuedInputs } from \"./inbox.ts\";\nimport { settleSchedulerOutcome } from \"./live.ts\";\nimport { BUILTIN_SETUP_KEY, BUILTIN_TASKS } from \"./registry.ts\";\nimport { type InvocationBinding, TaskScheduler } from \"./scheduler.ts\";\nimport { Submissions } from \"./submissions.ts\";\nimport type {\n\tCompactionPolicy,\n\tCompactionResult,\n\tContextView,\n\tConversation,\n\tConversationAbortOptions,\n\tConversationCreateOptions,\n\tConversationHandle,\n\tConversationInit,\n\tConversationRetryPolicy,\n\tConversationStreamOptions,\n\tHarnessInspection,\n\tHarnessOptions,\n\tHarness as HarnessType,\n\tModelRef,\n\tQueueMode,\n\tRegistryReader,\n\tRegistrySnapshot,\n\tSettledTask,\n\tSubmission,\n\tSubmissionDraft,\n\tToolExecutionMode,\n\tToolRegistration,\n} from \"./types.ts\";\nimport { addUsageState, UsageDoc, type UsageState } from \"./usage.ts\";\nimport { scanAll } from \"./util.ts\";\nimport { type ConversationView, ConversationViews } from \"./view.ts\";\n\nconst SCAN_PAGE_SIZE = 256;\n\ntype CreateTarget =\n\t| { readonly kind: \"root\" }\n\t| { readonly kind: \"independent\"; readonly ownership: ConversationOwnership }\n\t| {\n\t\t\treadonly kind: \"fork\";\n\t\t\treadonly parentId: ConversationId;\n\t\t\treadonly at: EntryId;\n\t\t\treadonly ownership: ConversationOwnership;\n\t };\n\n/** Harness-private services used by Conversation handles. */\ntype ConversationHost<Tool extends ToolRegistration> = {\n\treadonly harness: HarnessImpl<Tool>;\n\treadonly storage: Storage;\n\treadonly registry: RegistryReader<Tool>;\n\treadonly tasks: TaskScheduler;\n\treadonly submissions: Submissions;\n\treadonly views: ConversationViews;\n\treadonly now: () => number;\n\tcreate(target: CreateTarget, init: ConversationInit | undefined, context: Context): Promise<Conversation>;\n};\n\nclass ConversationImpl<Tool extends ToolRegistration> implements Conversation {\n\treadonly id: ConversationId;\n\treadonly #host: ConversationHost<Tool>;\n\n\tconstructor(id: ConversationId, host: ConversationHost<Tool>) {\n\t\tthis.id = id;\n\t\tthis.#host = host;\n\t}\n\n\tasync getModel(context: Context): Promise<ModelRef | undefined> {\n\t\treturn (await this.#config(context)).model;\n\t}\n\n\tsetModel(model: ModelRef | undefined, context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tif (model === undefined) delete config.model;\n\t\t\telse config.model = { provider: model.provider, modelId: model.modelId };\n\t\t}, context);\n\t}\n\n\tasync getThinkingLevel(context: Context): Promise<ModelThinkingLevel> {\n\t\treturn (await this.#config(context)).thinkingLevel;\n\t}\n\n\tsetThinkingLevel(level: ModelThinkingLevel, context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tconfig.thinkingLevel = level;\n\t\t}, context);\n\t}\n\n\tasync getActiveTools(context: Context): Promise<readonly string[]> {\n\t\treturn (await this.#config(context)).activeTools;\n\t}\n\n\tsetActiveTools(names: readonly string[], context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tif (new Set(names).size !== names.length) throw new Error(\"Active tools list a name more than once\");\n\t\t\trequireRegistered(this.#host.registry.snapshot(), names, config.activeTools);\n\t\t\tconfig.activeTools = [...names];\n\t\t}, context);\n\t}\n\n\tasync getStreamOptions(context: Context): Promise<ConversationStreamOptions> {\n\t\treturn (await this.#config(context)).streamOptions ?? {};\n\t}\n\n\tsetStreamOptions(options: ConversationStreamOptions, context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tconfig.streamOptions = options;\n\t\t}, context);\n\t}\n\n\tasync getRetryPolicy(context: Context): Promise<ConversationRetryPolicy> {\n\t\treturn (await this.#config(context)).retry ?? { ...DEFAULT_RETRY_POLICY };\n\t}\n\n\tsetRetryPolicy(policy: ConversationRetryPolicy | undefined, context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tif (policy === undefined) delete config.retry;\n\t\t\telse config.retry = policy;\n\t\t}, context);\n\t}\n\n\tasync getToolExecution(context: Context): Promise<ToolExecutionMode> {\n\t\treturn (await this.#config(context)).toolExecution ?? \"parallel\";\n\t}\n\n\tsetToolExecution(mode: ToolExecutionMode | undefined, context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tif (mode === undefined) delete config.toolExecution;\n\t\t\telse config.toolExecution = mode;\n\t\t}, context);\n\t}\n\n\tasync getSteeringMode(context: Context): Promise<QueueMode> {\n\t\treturn (await this.#config(context)).steeringMode ?? \"one-at-a-time\";\n\t}\n\n\tsetSteeringMode(mode: QueueMode | undefined, context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tif (mode === undefined) delete config.steeringMode;\n\t\t\telse config.steeringMode = mode;\n\t\t}, context);\n\t}\n\n\tasync getFollowUpMode(context: Context): Promise<QueueMode> {\n\t\treturn (await this.#config(context)).followUpMode ?? \"one-at-a-time\";\n\t}\n\n\tsetFollowUpMode(mode: QueueMode | undefined, context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tif (mode === undefined) delete config.followUpMode;\n\t\t\telse config.followUpMode = mode;\n\t\t}, context);\n\t}\n\n\tasync getCompaction(context: Context): Promise<CompactionPolicy> {\n\t\treturn (await this.#config(context)).compaction ?? { ...DEFAULT_COMPACTION_POLICY };\n\t}\n\n\tsetCompaction(policy: CompactionPolicy | undefined, context: Context): Promise<void> {\n\t\treturn this.#editConfig((config) => {\n\t\t\tif (policy === undefined) delete config.compaction;\n\t\t\telse config.compaction = policy;\n\t\t}, context);\n\t}\n\n\tsubmit(submission: SubmissionDraft, context: Context): Promise<Submission> {\n\t\treturn this.#host.submissions.submit(this.id, submission, context);\n\t}\n\n\tcompact(instructions: string | undefined, context: Context): Promise<TaskId<CompactionResult>> {\n\t\tthis.#host.tasks.resume();\n\t\tconst input = { reason: \"manual\", ...(instructions === undefined ? {} : { instructions }) } as const;\n\t\treturn this.#host.harness.commitWith((tx) => createCompaction(tx, this.id, input), context);\n\t}\n\n\tasync reset(handoff: string | undefined, context: Context): Promise<void> {\n\t\tconst model =\n\t\t\thandoff === undefined\n\t\t\t\t? {}\n\t\t\t\t: { model: [{ role: \"user\", content: handoff, timestamp: this.#host.now() } as const] };\n\t\tconst entry = { kind: ResetEntry.kind, head: \"self\", ...model } as const;\n\t\tawait this.#host.submissions.submit(this.id, { type: \"write\", entry }, context);\n\t}\n\n\tcommit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T> {\n\t\treturn this.#host.harness.commitWith(change, context, { conversationId: this.id });\n\t}\n\n\tcontext(context: Context): Promise<ContextView> {\n\t\treturn readContext(this.#host.harness, this.#host.storage, this.id, context);\n\t}\n\n\tentries(\n\t\tquery: Omit<EntryQuery, \"conversationId\">,\n\t\tlimit: number,\n\t\tcursor: Cursor | undefined,\n\t\tcontext: Context,\n\t): Promise<Page<EntryRecord, Cursor>> {\n\t\tconst bounded: EntryQuery = {\n\t\t\tconversationId: this.id,\n\t\t\t...(query.minEntryId === undefined ? {} : { minEntryId: query.minEntryId }),\n\t\t\t...(query.maxEntryId === undefined ? {} : { maxEntryId: query.maxEntryId }),\n\t\t};\n\t\treturn this.#host.harness.readOnLine(() => this.#host.storage.scanEntries(bounded, limit, cursor, context));\n\t}\n\n\tfork(at: EntryId, options: ConversationCreateOptions, context: Context): Promise<Conversation> {\n\t\treturn this.#host.create(\n\t\t\t{ kind: \"fork\", parentId: this.id, at, ownership: options.ownership },\n\t\t\toptions.init,\n\t\t\tcontext,\n\t\t);\n\t}\n\n\tabort(context: Context, options?: ConversationAbortOptions): Promise<void> {\n\t\tthis.#host.tasks.resume();\n\t\treturn this.#host.tasks.abortConversation(this.id, options?.background === true, context);\n\t}\n\n\twaitForIdle(context: Context): Promise<void> {\n\t\tthis.#host.tasks.resume();\n\t\treturn this.#host.tasks.waitForIdle(this.id, context);\n\t}\n\n\tviewState(context: Context): Promise<AttachedReplicatedState<ConversationView>> {\n\t\treturn this.#host.views.state(this.id, context);\n\t}\n\n\twatch(context: Context): Promise<WatchHandle<ConversationView>> {\n\t\treturn this.#host.views.watch(this.id, context);\n\t}\n\n\tasync #config(context: Context): Promise<Readonly<ConversationConfigState>> {\n\t\treturn (\n\t\t\t(await this.#host.harness.snapshot(ConversationConfig, this.id, context)) ??\n\t\t\tConversationConfig.definition.initial()\n\t\t);\n\t}\n\n\t#editConfig(edit: (config: Draft<ConversationConfigState>) => void, context: Context): Promise<void> {\n\t\treturn this.#host.harness.commitWith(async (tx) => {\n\t\t\tedit(await tx.doc(ConversationConfig, this.id));\n\t\t}, context);\n\t}\n}\n\n/** Session kernel extended with conversation handles and a registry. */\nclass HarnessImpl<Tool extends ToolRegistration> extends SessionImpl implements HarnessType {\n\treadonly #storage: Storage;\n\treadonly #registry: RegistryReader<Tool>;\n\treadonly #host: ConversationHost<Tool>;\n\treadonly #tasks: TaskScheduler;\n\treadonly #submissions: Submissions;\n\treadonly #snapshots = new WeakMap<Transaction, RegistrySnapshot<Tool>>();\n\t#closed = false;\n\n\tconstructor(storage: Storage, options: HarnessOptions<Tool>, context: Context) {\n\t\tsuper(storage);\n\t\tthis.#storage = storage;\n\t\tthis.#registry = options.registry;\n\t\tconst now = options.now ?? Date.now;\n\t\tthis.#tasks = new TaskScheduler({\n\t\t\tsession: this,\n\t\t\tstorage,\n\t\t\tregistry: options.registry,\n\t\t\tmodels: options.models,\n\t\t\tenv: options.env,\n\t\t\tnow,\n\t\t\treport: options.onReport ?? (() => {}),\n\t\t\tsettleOutcome: settleSchedulerOutcome,\n\t\t\twithdrawInputs: withdrawQueuedInputs,\n\t\t\tconversation: async (id, binding, callContext) => {\n\t\t\t\tconst record = await this.readOnLine(() => storage.conversation(id, callContext));\n\t\t\t\treturn record === undefined ? undefined : boundConversation(id, binding, this.#submissions, this.#tasks);\n\t\t\t},\n\t\t\tcontext: withoutAbortSignal(context),\n\t\t});\n\t\tthis.#submissions = new Submissions(this, storage, now, () => this.#tasks.resume());\n\t\tthis.#host = {\n\t\t\tharness: this,\n\t\t\tstorage,\n\t\t\tregistry: options.registry,\n\t\t\ttasks: this.#tasks,\n\t\t\tsubmissions: this.#submissions,\n\t\t\tviews: new ConversationViews(this, storage),\n\t\t\tnow,\n\t\t\tcreate: (target, init, context) => this.#create(target, init, context),\n\t\t};\n\t}\n\n\t/** Reconcile surviving `running` tasks to `pending`; part of open. */\n\topenTasks(context: Context): Promise<void> {\n\t\treturn this.#tasks.open(context);\n\t}\n\n\tresume(): void {\n\t\tthis.#assertOpen();\n\t\tthis.#tasks.resume();\n\t}\n\n\tgetTask<R>(id: TaskId<R>, context: Context): Promise<TaskRecord<JsonValue, JsonValue, R> | undefined> {\n\t\treturn this.readOnLine(() => this.#storage.task(id, context)) as Promise<\n\t\t\tTaskRecord<JsonValue, JsonValue, R> | undefined\n\t\t>;\n\t}\n\n\tinspect(context: Context): Promise<HarnessInspection> {\n\t\treturn this.readOnLine(async () => {\n\t\t\tconst snapshot = this.#registry.snapshot();\n\t\t\tconst { scheduling, tasks } = await this.#tasks.inspect(snapshot);\n\t\t\tconst scan = (status: \"queued\" | \"placed\") =>\n\t\t\t\tscanAll((cursor) => this.#storage.scanSubmissions({ status }, SCAN_PAGE_SIZE, cursor, context));\n\t\t\tconst submissions = [...(await scan(\"queued\")), ...(await scan(\"placed\"))].sort((a, b) => a.id - b.id);\n\t\t\treturn { scheduling, tasks, submissions, registry: snapshot.failures() };\n\t\t});\n\t}\n\n\tsubmission(id: SubmissionId, context: Context): Promise<Submission | undefined> {\n\t\treturn this.#submissions.get(id, context);\n\t}\n\n\tabortSubmission(\n\t\tid: SubmissionId,\n\t\tcontext: Context,\n\t\tconversationId?: ConversationId,\n\t): Promise<\"aborted\" | \"already_placed\" | \"settled\" | \"not_found\"> {\n\t\treturn this.#submissions.abort(id, context, conversationId);\n\t}\n\n\tabortTask(id: TaskId, context: Context): Promise<\"marked\" | \"terminal\"> {\n\t\treturn this.#tasks.abort(id, context);\n\t}\n\n\twaitForTask<R>(id: TaskId<R>, context: Context): Promise<SettledTask<R>> {\n\t\tthis.#tasks.resume();\n\t\treturn this.#tasks.waitForTask(id, context) as Promise<SettledTask<R>>;\n\t}\n\n\twaitForIdle(context: Context): Promise<void> {\n\t\tthis.#tasks.resume();\n\t\treturn this.#tasks.waitForIdle(undefined, context);\n\t}\n\n\t/** Sum every conversation's committed `pi.usage`. Each document is read at its own point; totals only grow. */\n\tasync usage(context: Context): Promise<UsageState> {\n\t\tconst conversations = await this.readOnLine(() =>\n\t\t\tscanAll((cursor) => this.#storage.scanConversations({}, SCAN_PAGE_SIZE, cursor, context)),\n\t\t);\n\t\tconst total = UsageDoc.definition.initial();\n\t\tfor (const { id } of conversations) {\n\t\t\tconst state = await this.snapshot(UsageDoc, id, context);\n\t\t\tif (state !== undefined) addUsageState(total, state);\n\t\t}\n\t\treturn total;\n\t}\n\n\troot(context: Context, options?: { readonly init?: ConversationInit }): Promise<Conversation> {\n\t\treturn this.#create({ kind: \"root\" }, options?.init, context);\n\t}\n\n\tasync conversation(id: ConversationId, context: Context): Promise<Conversation | undefined> {\n\t\tthis.#assertOpen();\n\t\tconst record = await this.readOnLine(() => this.#storage.conversation(id, context));\n\t\treturn record === undefined ? undefined : new ConversationImpl(record.id, this.#host);\n\t}\n\n\tcreateConversation(options: ConversationCreateOptions, context: Context): Promise<Conversation> {\n\t\treturn this.#create({ kind: \"independent\", ownership: options.ownership }, options.init, context);\n\t}\n\n\toverride close(context: Context): Promise<void> {\n\t\tthis.#closed = true;\n\t\treturn super.close(context);\n\t}\n\n\t/** Join task invocations after admission is sealed and before Storage closes; writes no task outcome. */\n\tprotected override beforeClose(): Promise<void> {\n\t\treturn this.#tasks.join();\n\t}\n\n\tasync #create(target: CreateTarget, init: ConversationInit | undefined, context: Context): Promise<Conversation> {\n\t\tthis.#assertOpen();\n\t\tconst id = await this.commitWith(async (tx) => {\n\t\t\tif (target.kind === \"root\" && (await tx.conversation(ROOT_CONVERSATION_ID)) !== undefined) {\n\t\t\t\treturn ROOT_CONVERSATION_ID;\n\t\t\t}\n\t\t\tconst record =\n\t\t\t\ttarget.kind === \"root\"\n\t\t\t\t\t? await tx.createRootConversation()\n\t\t\t\t\t: target.kind === \"fork\"\n\t\t\t\t\t\t? await tx.forkConversation(target.parentId, target.at, { ownership: target.ownership })\n\t\t\t\t\t\t: await tx.createConversation({ ownership: target.ownership });\n\t\t\tif (init !== undefined) await this.#runInit(tx, record.id, init);\n\t\t\treturn record.id;\n\t\t}, context);\n\t\treturn new ConversationImpl(id, this.#host);\n\t}\n\n\t/** Run every registered conversation setup, built-ins first, in each commit that creates or forks a conversation. */\n\tprotected override async conversationCreated(tx: Transaction, record: ConversationRecord): Promise<void> {\n\t\tconst snapshot = this.#snapshotOf(tx);\n\t\tfor (const { setup } of snapshot.conversationSetups()) await setup(tx, record, snapshot);\n\t}\n\n\t/** Run `init` in the creating commit; its writes are trusted, but names it newly activates must be registered. */\n\tasync #runInit(tx: Transaction, id: ConversationId, init: ConversationInit): Promise<void> {\n\t\tconst snapshot = this.#snapshotOf(tx);\n\t\tconst baseline = [...(await tx.doc(ConversationConfig, id)).activeTools];\n\t\tawait init(tx, id);\n\t\trequireRegistered(snapshot, (await tx.doc(ConversationConfig, id)).activeTools, baseline);\n\t}\n\n\t/** One registry snapshot per commit, shared by its conversation setups and `init` checks. */\n\t#snapshotOf(tx: Transaction): RegistrySnapshot<Tool> {\n\t\tlet snapshot = this.#snapshots.get(tx);\n\t\tif (snapshot === undefined) {\n\t\t\tsnapshot = this.#registry.snapshot();\n\t\t\tthis.#snapshots.set(tx, snapshot);\n\t\t}\n\t\treturn snapshot;\n\t}\n\n\t#assertOpen(): void {\n\t\tif (this.#closed) throw new Error(\"Harness is closed\");\n\t}\n}\n\n/**\n * Invocation-bound handle for tasks and tools. Every operation, and every operation of a submission it returns, first\n * checks the invocation and runs under its signal, so it rejects once the invocation ends; admitted work stays durable.\n */\nfunction boundConversation(\n\tid: ConversationId,\n\tbinding: InvocationBinding,\n\tsubmissions: Submissions,\n\ttasks: TaskScheduler,\n): ConversationHandle {\n\tconst bind = (context: Context): Context => withAbortSignal(binding.signal, context);\n\tconst bound = <T>(operation: (context: Context) => Promise<T>) => {\n\t\treturn async (context: Context): Promise<T> => {\n\t\t\tbinding.check();\n\t\t\treturn operation(bind(context));\n\t\t};\n\t};\n\treturn {\n\t\tid,\n\t\tsubmit: async (draft, context) => {\n\t\t\tbinding.check();\n\t\t\tconst submission = await submissions.submit(id, draft, bind(context));\n\t\t\treturn {\n\t\t\t\tid: submission.id,\n\t\t\t\tstatus: bound((callContext) => submission.status(callContext)),\n\t\t\t\twait: bound((callContext) => submission.wait(callContext)),\n\t\t\t\tabort: bound((callContext) => submission.abort(callContext)),\n\t\t\t};\n\t\t},\n\t\tabort: async (context, options) => {\n\t\t\tbinding.check();\n\t\t\treturn tasks.abortConversation(id, options?.background === true, bind(context));\n\t\t},\n\t\twaitForIdle: bound((callContext) => tasks.waitForIdle(id, callContext)),\n\t};\n}\n\n/** Reject names newly added relative to `previous` that `snapshot` does not register; existing names are never rechecked. */\nfunction requireRegistered<Tool extends ToolRegistration>(\n\tsnapshot: RegistrySnapshot<Tool>,\n\tnames: readonly string[],\n\tprevious: readonly string[],\n): void {\n\tconst existing = new Set(previous);\n\tconst registered = new Set(snapshot.toolNames());\n\tconst missing = names.filter((name) => !existing.has(name) && !registered.has(name));\n\tif (missing.length > 0) throw new Error(`Tools are not registered: ${missing.join(\", \")}`);\n}\n\n/** Durable agent harness over one Session. */\nexport type Harness = HarnessType;\n\nexport const Harness = {\n\t/** Open a Harness over storage. The registry may keep changing while the Harness runs. */\n\tasync open<Tool extends ToolRegistration>(\n\t\tstorage: Storage,\n\t\toptions: HarnessOptions<Tool>,\n\t\tcontext: Context,\n\t): Promise<Harness> {\n\t\tcontext.abortSignal?.throwIfAborted();\n\t\tconst snapshot = options.registry.snapshot();\n\t\tconst missing = BUILTIN_TASKS.filter((task) => snapshot.task(task.definition.name) === undefined).map(\n\t\t\t(task) => `task ${task.definition.name}`,\n\t\t);\n\t\tif (!snapshot.conversationSetups().some(({ key }) => key === BUILTIN_SETUP_KEY))\n\t\t\tmissing.push(\"conversation setup pi\");\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Registry lacks built-in ${missing.join(\", \")}; create it with createRegistry()`);\n\t\t}\n\t\tconst harness = new HarnessImpl(storage, options, context);\n\t\ttry {\n\t\t\tawait harness.openTasks(context);\n\t\t} catch (error) {\n\t\t\tawait harness.close(context);\n\t\t\tthrow error;\n\t\t}\n\t\treturn harness;\n\t},\n};\n"]}
|
|
1
|
+
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/harness/harness.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AttachedReplicatedState, Context, JsonValue } from \"@earendil-works/chord\";\nimport { withAbortSignal, withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport { ResetEntry } from \"../entries.ts\";\nimport type { ExecutionEnv } from \"../env/index.ts\";\nimport { SessionImpl } from \"../session/session.ts\";\nimport type { Transaction } from \"../session/transaction.ts\";\nimport type {\n\tConversationId,\n\tConversationOwnership,\n\tConversationRecord,\n\tCursor,\n\tEntryId,\n\tEntryQuery,\n\tEntryRecord,\n\tPage,\n\tStorage,\n\tSubmissionId,\n\tTaskId,\n\tTaskRecord,\n\tTx,\n} from \"../types.ts\";\nimport { ROOT_CONVERSATION_ID } from \"../types.ts\";\nimport { AgentDoc, configure, createAgent, resolveAgent, resolveSettings } from \"./agent.ts\";\nimport { createCompaction } from \"./compaction.ts\";\nimport { readContext } from \"./context.ts\";\nimport { InboxDoc, withdrawQueuedInputs } from \"./inbox.ts\";\nimport { LiveDoc, settleSchedulerOutcome } from \"./live.ts\";\nimport { BUILTIN_TASKS } from \"./registry.ts\";\nimport { type InvocationBinding, TaskScheduler } from \"./scheduler.ts\";\nimport { Submissions } from \"./submissions.ts\";\nimport { type TaskGraph, TaskGraphView, type TaskGraphWatch } from \"./task-graph.ts\";\nimport type {\n\tAgent,\n\tAgentChange,\n\tCompactionResult,\n\tContextView,\n\tConversation,\n\tConversationAbortOptions,\n\tConversationCreateOptions,\n\tConversationHandle,\n\tConversationInit,\n\tConversationWatch,\n\tHarnessInspection,\n\tHarnessOptions,\n\tHarness as HarnessType,\n\tRegistrySnapshot,\n\tSettledTask,\n\tSubmission,\n\tSubmissionDraft,\n\tToolRegistration,\n} from \"./types.ts\";\nimport { addUsageState, UsageDoc, type UsageState } from \"./usage.ts\";\nimport { scanAll } from \"./util.ts\";\nimport { type ConversationView, ConversationViews } from \"./view.ts\";\n\nconst SCAN_PAGE_SIZE = 256;\n\ntype CreateTarget =\n\t| { readonly kind: \"root\" }\n\t| { readonly kind: \"independent\"; readonly ownership: ConversationOwnership }\n\t| {\n\t\t\treadonly kind: \"fork\";\n\t\t\treadonly parentId: ConversationId;\n\t\t\treadonly at: EntryId;\n\t\t\treadonly ownership: ConversationOwnership;\n\t };\n\n/** What the conveniences apply in the creating commit, after the creation hook. */\ntype CreateOptions = { readonly agent?: AgentChange; readonly init?: ConversationInit };\n\n/** Harness-private services used by Conversation handles. */\ntype ConversationHost<Tool extends ToolRegistration> = {\n\treadonly harness: HarnessImpl<Tool>;\n\treadonly storage: Storage;\n\treadonly tasks: TaskScheduler;\n\treadonly submissions: Submissions;\n\treadonly views: ConversationViews;\n\treadonly now: () => number;\n\tcreate(target: CreateTarget, options: CreateOptions, context: Context): Promise<Conversation>;\n};\n\nclass ConversationImpl<Tool extends ToolRegistration> implements Conversation {\n\treadonly id: ConversationId;\n\treadonly #host: ConversationHost<Tool>;\n\n\tconstructor(id: ConversationId, host: ConversationHost<Tool>) {\n\t\tthis.id = id;\n\t\tthis.#host = host;\n\t}\n\n\tagent(context: Context): Promise<Agent> {\n\t\treturn this.#host.harness.resolveAgent(this.id, undefined, context);\n\t}\n\n\tconfigure(change: AgentChange, context: Context): Promise<void> {\n\t\treturn this.#host.harness.commitWith((tx) => configure(tx, this.id, change), context);\n\t}\n\n\tsubmit(submission: SubmissionDraft, context: Context): Promise<Submission> {\n\t\treturn this.#host.submissions.submit(this.id, submission, context);\n\t}\n\n\tcompact(instructions: string | undefined, context: Context): Promise<TaskId<CompactionResult>> {\n\t\tthis.#host.tasks.resume();\n\t\tconst input = { reason: \"manual\", ...(instructions === undefined ? {} : { instructions }) } as const;\n\t\treturn this.#host.harness.commitWith((tx) => createCompaction(tx, this.id, input), context);\n\t}\n\n\tasync reset(handoff: string | undefined, context: Context): Promise<void> {\n\t\tconst model =\n\t\t\thandoff === undefined\n\t\t\t\t? {}\n\t\t\t\t: { model: [{ role: \"user\", content: handoff, timestamp: this.#host.now() } as const] };\n\t\tconst entry = { kind: ResetEntry.kind, head: \"self\", ...model } as const;\n\t\tawait this.#host.submissions.submit(this.id, { type: \"write\", entry }, context);\n\t}\n\n\tcommit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T> {\n\t\treturn this.#host.harness.commitWith(change, context, { conversationId: this.id });\n\t}\n\n\tcontext(context: Context): Promise<ContextView> {\n\t\treturn readContext(this.#host.harness, this.#host.storage, this.id, context);\n\t}\n\n\tentries(\n\t\tquery: Omit<EntryQuery, \"conversationId\">,\n\t\tlimit: number,\n\t\tcursor: Cursor | undefined,\n\t\tcontext: Context,\n\t): Promise<Page<EntryRecord, Cursor>> {\n\t\tconst bounded: EntryQuery = {\n\t\t\tconversationId: this.id,\n\t\t\t...(query.minEntryId === undefined ? {} : { minEntryId: query.minEntryId }),\n\t\t\t...(query.maxEntryId === undefined ? {} : { maxEntryId: query.maxEntryId }),\n\t\t};\n\t\treturn this.#host.harness.readOnLine(() => this.#host.storage.scanEntries(bounded, limit, cursor, context));\n\t}\n\n\tfork(at: EntryId, options: ConversationCreateOptions, context: Context): Promise<Conversation> {\n\t\treturn this.#host.create({ kind: \"fork\", parentId: this.id, at, ownership: options.ownership }, options, context);\n\t}\n\n\tabort(context: Context, options?: ConversationAbortOptions): Promise<void> {\n\t\tthis.#host.tasks.resume();\n\t\treturn this.#host.tasks.abortConversation(this.id, options?.background === true, context);\n\t}\n\n\twaitForIdle(context: Context): Promise<void> {\n\t\tthis.#host.tasks.resume();\n\t\treturn this.#host.tasks.waitForIdle(this.id, context);\n\t}\n\n\tviewState(context: Context): Promise<AttachedReplicatedState<ConversationView>> {\n\t\treturn this.#host.views.state(this.id, context);\n\t}\n\n\twatch(context: Context): Promise<ConversationWatch> {\n\t\treturn this.#host.views.watch(this.id, context);\n\t}\n}\n\n/** Session kernel extended with conversation handles and a registry. */\nclass HarnessImpl<Tool extends ToolRegistration> extends SessionImpl implements HarnessType {\n\treadonly #storage: Storage;\n\treadonly #options: HarnessOptions<Tool>;\n\treadonly #report: (error: unknown) => void;\n\treadonly #host: ConversationHost<Tool>;\n\treadonly #tasks: TaskScheduler;\n\treadonly #submissions: Submissions;\n\treadonly #taskGraph: TaskGraphView;\n\t#closed = false;\n\n\tconstructor(storage: Storage, options: HarnessOptions<Tool>, context: Context) {\n\t\tsuper(storage);\n\t\tthis.#storage = storage;\n\t\tthis.#options = options;\n\t\tthis.#report = options.onReport ?? (() => {});\n\t\tconst now = options.now ?? Date.now;\n\t\tconst settings = () => resolveSettings(options.settings);\n\t\tthis.#tasks = new TaskScheduler({\n\t\t\tsession: this,\n\t\t\tstorage,\n\t\t\tregistry: options.registry,\n\t\t\tmodels: options.models,\n\t\t\tagent: (id, snapshot, callContext) => this.resolveAgent(id, snapshot as RegistrySnapshot<Tool>, callContext),\n\t\t\tsettings,\n\t\t\tenv: (id, callContext) => this.buildEnv(id, callContext),\n\t\t\tnow,\n\t\t\treport: this.#report,\n\t\t\tsettleOutcome: settleSchedulerOutcome,\n\t\t\twithdrawInputs: withdrawQueuedInputs,\n\t\t\tconversation: async (id, binding, callContext) => {\n\t\t\t\tconst record = await this.readOnLine(() => storage.conversation(id, callContext));\n\t\t\t\treturn record === undefined ? undefined : boundConversation(id, binding, this.#submissions, this.#tasks);\n\t\t\t},\n\t\t\tcontext: withoutAbortSignal(context),\n\t\t});\n\t\tthis.#submissions = new Submissions(this, storage, now, settings, () => this.#tasks.resume());\n\t\tthis.#taskGraph = new TaskGraphView(this, storage);\n\t\tthis.#host = {\n\t\t\tharness: this,\n\t\t\tstorage,\n\t\t\ttasks: this.#tasks,\n\t\t\tsubmissions: this.#submissions,\n\t\t\tviews: new ConversationViews(this, storage),\n\t\t\tnow,\n\t\t\tcreate: (target, createOptions, context) => this.#create(target, createOptions, context),\n\t\t};\n\t}\n\n\t/** Resolve a conversation's committed `pi.agent` against `snapshot`, or the current one, and the current settings. */\n\tasync resolveAgent(\n\t\tid: ConversationId,\n\t\tsnapshot: RegistrySnapshot<Tool> | undefined,\n\t\tcontext: Context,\n\t): Promise<Agent<Tool>> {\n\t\tconst registry = snapshot ?? this.#options.registry.snapshot();\n\t\tconst state = await this.snapshot(AgentDoc, id, context);\n\t\treturn resolveAgent(state, registry, resolveSettings(this.#options.settings), this.#report);\n\t}\n\n\t/** Build a conversation's environment from its current `cwd`; `undefined` without an `env` option. */\n\tasync buildEnv(id: ConversationId, context: Context): Promise<ExecutionEnv | undefined> {\n\t\tconst build = this.#options.env;\n\t\tif (build === undefined) return undefined;\n\t\tconst cwd = (await this.snapshot(AgentDoc, id, context))?.cwd;\n\t\treturn build({ conversationId: id, ...(cwd === undefined ? {} : { cwd }), read: this }, context);\n\t}\n\n\t/** Reconcile surviving `running` tasks to `pending`; part of open. */\n\topenTasks(context: Context): Promise<void> {\n\t\treturn this.#tasks.open(context);\n\t}\n\n\tresume(): void {\n\t\tthis.#assertOpen();\n\t\tthis.#tasks.resume();\n\t}\n\n\tgetTask<R>(id: TaskId<R>, context: Context): Promise<TaskRecord<JsonValue, JsonValue, R> | undefined> {\n\t\treturn this.readOnLine(() => this.#storage.task(id, context)) as Promise<\n\t\t\tTaskRecord<JsonValue, JsonValue, R> | undefined\n\t\t>;\n\t}\n\n\tinspect(context: Context): Promise<HarnessInspection> {\n\t\treturn this.readOnLine(async () => {\n\t\t\tconst { scheduling, tasks } = await this.#tasks.inspect(this.#options.registry.snapshot());\n\t\t\tconst scan = (status: \"queued\" | \"placed\") =>\n\t\t\t\tscanAll((cursor) => this.#storage.scanSubmissions({ status }, SCAN_PAGE_SIZE, cursor, context));\n\t\t\tconst submissions = [...(await scan(\"queued\")), ...(await scan(\"placed\"))].sort((a, b) => a.id - b.id);\n\t\t\treturn { scheduling, tasks, submissions };\n\t\t});\n\t}\n\n\tsubmission(id: SubmissionId, context: Context): Promise<Submission | undefined> {\n\t\treturn this.#submissions.get(id, context);\n\t}\n\n\tabortSubmission(\n\t\tid: SubmissionId,\n\t\tcontext: Context,\n\t\tconversationId?: ConversationId,\n\t): Promise<\"aborted\" | \"already_placed\" | \"settled\" | \"not_found\"> {\n\t\treturn this.#submissions.abort(id, context, conversationId);\n\t}\n\n\tabortTask(id: TaskId, context: Context): Promise<\"marked\" | \"terminal\"> {\n\t\treturn this.#tasks.abort(id, context);\n\t}\n\n\twaitForTask<R>(id: TaskId<R>, context: Context): Promise<SettledTask<R>> {\n\t\tthis.#tasks.resume();\n\t\treturn this.#tasks.waitForTask(id, context) as Promise<SettledTask<R>>;\n\t}\n\n\twaitForIdle(context: Context): Promise<void> {\n\t\tthis.#tasks.resume();\n\t\treturn this.#tasks.waitForIdle(undefined, context);\n\t}\n\n\t/** Sum every conversation's committed `pi.usage`. Each document is read at its own point; totals only grow. */\n\tasync usage(context: Context): Promise<UsageState> {\n\t\tconst conversations = await this.readOnLine(() =>\n\t\t\tscanAll((cursor) => this.#storage.scanConversations({}, SCAN_PAGE_SIZE, cursor, context)),\n\t\t);\n\t\tconst total = UsageDoc.definition.initial();\n\t\tfor (const { id } of conversations) {\n\t\t\tconst state = await this.snapshot(UsageDoc, id, context);\n\t\t\tif (state !== undefined) addUsageState(total, state);\n\t\t}\n\t\treturn total;\n\t}\n\n\ttaskGraph(context: Context): Promise<AttachedReplicatedState<TaskGraph>> {\n\t\treturn this.#taskGraph.state(context);\n\t}\n\n\twatchTaskGraph(context: Context): Promise<TaskGraphWatch> {\n\t\treturn this.#taskGraph.watch(context);\n\t}\n\n\troot(\n\t\tcontext: Context,\n\t\toptions?: { readonly agent?: AgentChange; readonly init?: ConversationInit },\n\t): Promise<Conversation> {\n\t\treturn this.#create({ kind: \"root\" }, options ?? {}, context);\n\t}\n\n\tasync conversation(id: ConversationId, context: Context): Promise<Conversation | undefined> {\n\t\tthis.#assertOpen();\n\t\tconst record = await this.readOnLine(() => this.#storage.conversation(id, context));\n\t\treturn record === undefined ? undefined : new ConversationImpl(record.id, this.#host);\n\t}\n\n\tcreateConversation(options: ConversationCreateOptions, context: Context): Promise<Conversation> {\n\t\treturn this.#create({ kind: \"independent\", ownership: options.ownership }, options, context);\n\t}\n\n\toverride close(context: Context): Promise<void> {\n\t\tthis.#closed = true;\n\t\treturn super.close(context);\n\t}\n\n\t/** Join task invocations after admission is sealed and before Storage closes; writes no task outcome. */\n\tprotected override beforeClose(): Promise<void> {\n\t\treturn this.#tasks.join();\n\t}\n\n\tasync #create(target: CreateTarget, options: CreateOptions, context: Context): Promise<Conversation> {\n\t\tthis.#assertOpen();\n\t\tconst id = await this.commitWith(async (tx) => {\n\t\t\tif (target.kind === \"root\" && (await tx.conversation(ROOT_CONVERSATION_ID)) !== undefined) {\n\t\t\t\treturn ROOT_CONVERSATION_ID;\n\t\t\t}\n\t\t\tconst record =\n\t\t\t\ttarget.kind === \"root\"\n\t\t\t\t\t? await tx.createRootConversation()\n\t\t\t\t\t: target.kind === \"fork\"\n\t\t\t\t\t\t? await tx.forkConversation(target.parentId, target.at, { ownership: target.ownership })\n\t\t\t\t\t\t: await tx.createConversation({ ownership: target.ownership });\n\t\t\tif (options.agent !== undefined) await configure(tx, record.id, options.agent);\n\t\t\tif (options.init !== undefined) await options.init(tx, record.id);\n\t\t\treturn record.id;\n\t\t}, context);\n\t\treturn new ConversationImpl(id, this.#host);\n\t}\n\n\t/**\n\t * The built-in creation hook, in every commit that creates or forks a conversation: empty `pi.live`, `pi.inbox`, and\n\t * `pi.usage`, the conversation's `pi.agent` (see `createAgent()`), then `HarnessOptions.conversationCreated`.\n\t */\n\tprotected override async conversationCreated(tx: Transaction, record: ConversationRecord): Promise<void> {\n\t\tawait tx.doc(LiveDoc, record.id);\n\t\tawait tx.doc(InboxDoc, record.id);\n\t\tawait tx.doc(UsageDoc, record.id);\n\t\tawait createAgent(tx, record);\n\t\tawait this.#options.conversationCreated?.(tx, record);\n\t}\n\n\t#assertOpen(): void {\n\t\tif (this.#closed) throw new Error(\"Harness is closed\");\n\t}\n}\n\n/**\n * Invocation-bound handle for tasks and tools. Every operation, and every operation of a submission it returns, first\n * checks the invocation and runs under its signal, so it rejects once the invocation ends; admitted work stays durable.\n */\nfunction boundConversation(\n\tid: ConversationId,\n\tbinding: InvocationBinding,\n\tsubmissions: Submissions,\n\ttasks: TaskScheduler,\n): ConversationHandle {\n\tconst bind = (context: Context): Context => withAbortSignal(binding.signal, context);\n\tconst bound = <T>(operation: (context: Context) => Promise<T>) => {\n\t\treturn async (context: Context): Promise<T> => {\n\t\t\tbinding.check();\n\t\t\treturn operation(bind(context));\n\t\t};\n\t};\n\treturn {\n\t\tid,\n\t\tsubmit: async (draft, context) => {\n\t\t\tbinding.check();\n\t\t\tconst submission = await submissions.submit(id, draft, bind(context));\n\t\t\treturn {\n\t\t\t\tid: submission.id,\n\t\t\t\tstatus: bound((callContext) => submission.status(callContext)),\n\t\t\t\twait: bound((callContext) => submission.wait(callContext)),\n\t\t\t\tabort: bound((callContext) => submission.abort(callContext)),\n\t\t\t};\n\t\t},\n\t\tabort: async (context, options) => {\n\t\t\tbinding.check();\n\t\t\treturn tasks.abortConversation(id, options?.background === true, bind(context));\n\t\t},\n\t\twaitForIdle: bound((callContext) => tasks.waitForIdle(id, callContext)),\n\t};\n}\n\n/** Durable agent harness over one Session. */\nexport type Harness = HarnessType;\n\nexport const Harness = {\n\t/** Open a Harness over storage. The registry may keep changing while the Harness runs. */\n\tasync open<Tool extends ToolRegistration>(\n\t\tstorage: Storage,\n\t\toptions: HarnessOptions<Tool>,\n\t\tcontext: Context,\n\t): Promise<Harness> {\n\t\tcontext.abortSignal?.throwIfAborted();\n\t\tconst snapshot = options.registry.snapshot();\n\t\tconst missing = BUILTIN_TASKS.filter((task) => snapshot.task(task.definition.name) === undefined);\n\t\tif (missing.length > 0) {\n\t\t\tconst names = missing.map((task) => task.definition.name).join(\", \");\n\t\t\tthrow new Error(`Registry lacks built-in tasks ${names}; create it with createRegistry()`);\n\t\t}\n\t\tconst harness = new HarnessImpl(storage, options, context);\n\t\ttry {\n\t\t\tawait harness.openTasks(context);\n\t\t} catch (error) {\n\t\t\t// The caller's context may be what failed open: close without it, and rethrow the open error.\n\t\t\tawait harness\n\t\t\t\t.close(withoutAbortSignal(context))\n\t\t\t\t.catch((closeError: unknown) => options.onReport?.(closeError));\n\t\t\tthrow error;\n\t\t}\n\t\treturn harness;\n\t},\n};\n"]}
|
package/dist/harness/inbox.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Draft, JsonRepresentation } from "@earendil-works/chord";
|
|
2
2
|
import type { ConversationId, EntryDraft, EntryId, JsonObject, SubmissionId, Tx } from "../types.ts";
|
|
3
|
-
import type { QueueMode, UserInput } from "./types.ts";
|
|
3
|
+
import type { QueueMode, Settings, UserInput } from "./types.ts";
|
|
4
4
|
/** A queued submission: user input for a run, or a passive entry write. */
|
|
5
5
|
export type InboxItem = {
|
|
6
6
|
id: SubmissionId;
|
|
@@ -18,6 +18,8 @@ export type InboxState = {
|
|
|
18
18
|
items: InboxItem[];
|
|
19
19
|
};
|
|
20
20
|
export declare const InboxDoc: import("../types.ts").ConversationDocToken<InboxState>;
|
|
21
|
+
/** The settings a boundary reads, on the Session line. */
|
|
22
|
+
export type QueueModes = Pick<Settings, "steeringMode" | "followUpMode">;
|
|
21
23
|
/** What a boundary reads before the commit's first table write, and the newest head it has seen so far. */
|
|
22
24
|
export type Boundary = {
|
|
23
25
|
readonly conversationId: ConversationId;
|
|
@@ -36,7 +38,7 @@ export type BoundaryResult = {
|
|
|
36
38
|
* Read what a boundary needs. Table reads must precede the commit's first table write, so callers prepare the
|
|
37
39
|
* boundary at the start of their commit.
|
|
38
40
|
*/
|
|
39
|
-
export declare function prepareBoundary(tx: Tx, conversationId: ConversationId): Promise<Boundary>;
|
|
41
|
+
export declare function prepareBoundary(tx: Tx, conversationId: ConversationId, modes: QueueModes): Promise<Boundary>;
|
|
40
42
|
/**
|
|
41
43
|
* Place the queued items a boundary selects (spec §6): every write, the first or all steers, and at `final` the first
|
|
42
44
|
* or all follow-ups. A selected reset turns a `postTools` boundary into `final`. Writes are placed first and user
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/harness/inbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/harness/inbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAGvE,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEjE,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAClB;IAAE,EAAE,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAA;CAAE;AAC1F,wDAAwD;GACtD;IAAE,EAAE,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC;AAE1D,4FAA4F;AAC5F,MAAM,MAAM,UAAU,GAAG;IAAE,KAAK,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC;AAEhD,eAAO,MAAM,QAAQ,wDAQnB,CAAC;AAEH,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,GAAG,cAAc,CAAC,CAAC;AAEzE,2GAA2G;AAC3G,MAAM,MAAM,QAAQ,GAAG;IACtB,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IACjC,4GAA4G;IAC5G,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;CAC1B,CAAC;AAEF,iGAAiG;AACjG,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAEzF;;;GAGG;AACH,wBAAsB,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAUlH;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAClC,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,QAAQ,EAClB,EAAE,EAAE,WAAW,GAAG,OAAO,EACzB,GAAG,EAAE,MAAM,GACT,OAAO,CAAC,cAAc,CAAC,CAoCzB;AAED,iHAAiH;AACjH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAEtE;AAED,+EAA+E;AAC/E,wBAAsB,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7G;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhG"}
|
package/dist/harness/inbox.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { defineDoc } from "../documents.js";
|
|
2
2
|
import { UserEntry } from "../entries.js";
|
|
3
|
-
import { ConversationConfig } from "./config.js";
|
|
4
3
|
export const InboxDoc = defineDoc({
|
|
5
4
|
kind: "pi.inbox",
|
|
6
5
|
version: 1,
|
|
@@ -14,15 +13,14 @@ export const InboxDoc = defineDoc({
|
|
|
14
13
|
* Read what a boundary needs. Table reads must precede the commit's first table write, so callers prepare the
|
|
15
14
|
* boundary at the start of their commit.
|
|
16
15
|
*/
|
|
17
|
-
export async function prepareBoundary(tx, conversationId) {
|
|
16
|
+
export async function prepareBoundary(tx, conversationId, modes) {
|
|
18
17
|
const head = (await tx.latestHeadMarker(conversationId))?.head;
|
|
19
18
|
const inbox = await tx.doc(InboxDoc, conversationId);
|
|
20
|
-
const config = await tx.doc(ConversationConfig, conversationId);
|
|
21
19
|
return {
|
|
22
20
|
conversationId,
|
|
23
21
|
inbox,
|
|
24
|
-
steeringMode:
|
|
25
|
-
followUpMode:
|
|
22
|
+
steeringMode: modes.steeringMode,
|
|
23
|
+
followUpMode: modes.followUpMode,
|
|
26
24
|
head,
|
|
27
25
|
};
|
|
28
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/harness/inbox.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Draft, JsonRepresentation } from \"@earendil-works/chord\";\nimport { defineDoc } from \"../documents.ts\";\nimport { UserEntry } from \"../entries.ts\";\nimport type { ConversationId, EntryDraft, EntryId, JsonObject, SubmissionId, Tx } from \"../types.ts\";\nimport { ConversationConfig } from \"./config.ts\";\nimport type { QueueMode, UserInput } from \"./types.ts\";\n\n/** A queued submission: user input for a run, or a passive entry write. */\nexport type InboxItem =\n\t| { id: SubmissionId; mode: \"steer\" | \"followUp\"; content: JsonRepresentation<UserInput> }\n\t/** `entry` is an `EntryDraft`, stored as plain JSON. */\n\t| { id: SubmissionId; mode: \"write\"; entry: JsonObject };\n\n/** Built-in queue of one conversation's submissions waiting for a boundary, in ID order. */\nexport type InboxState = { items: InboxItem[] };\n\nexport const InboxDoc = defineDoc<InboxState>({\n\tkind: \"pi.inbox\",\n\tversion: 1,\n\tscope: \"conversation\",\n\thistory: \"latest\",\n\tfork: \"initial\",\n\tinitial: () => ({ items: [] }),\n\tcheckpointWhen: (value) => value.items.length === 0,\n});\n\n/** What a boundary reads before the commit's first table write, and the newest head it has seen so far. */\nexport type Boundary = {\n\treadonly conversationId: ConversationId;\n\treadonly inbox: Draft<InboxState>;\n\treadonly steeringMode: QueueMode;\n\treadonly followUpMode: QueueMode;\n\t/** Start of the active range, the newest head marker's `head`; advanced by heads written in this commit. */\n\thead: EntryId | undefined;\n};\n\n/** Selected user items, in ID order, and whether a `head: \"self\"` write (a reset) was placed. */\nexport type BoundaryResult = { readonly users: SubmissionId[]; readonly reset: boolean };\n\n/**\n * Read what a boundary needs. Table reads must precede the commit's first table write, so callers prepare the\n * boundary at the start of their commit.\n */\nexport async function prepareBoundary(tx: Tx, conversationId: ConversationId): Promise<Boundary> {\n\tconst head = (await tx.latestHeadMarker(conversationId))?.head;\n\tconst inbox = await tx.doc(InboxDoc, conversationId);\n\tconst config = await tx.doc(ConversationConfig, conversationId);\n\treturn {\n\t\tconversationId,\n\t\tinbox,\n\t\tsteeringMode: config.steeringMode ?? \"one-at-a-time\",\n\t\tfollowUpMode: config.followUpMode ?? \"one-at-a-time\",\n\t\thead,\n\t};\n}\n\n/**\n * Place the queued items a boundary selects (spec §6): every write, the first or all steers, and at `final` the first\n * or all follow-ups. A selected reset turns a `postTools` boundary into `final`. Writes are placed first and user\n * items after them, each in ID order, so user items queued before a reset run in the new context. A write whose head\n * targets an entry before the active range, including a range started earlier in this commit, is stale. Selected and\n * stale items are removed positionally.\n */\nexport async function applyBoundary(\n\ttx: Tx,\n\tboundary: Boundary,\n\tat: \"postTools\" | \"final\",\n\tnow: number,\n): Promise<BoundaryResult> {\n\tconst { conversationId, inbox } = boundary;\n\tconst items = inbox.items;\n\tconst reset = items.some((item) => item.mode === \"write\" && item.entry.head === \"self\");\n\tconst final = at === \"final\" || reset;\n\tconst pick = (mode: \"steer\" | \"followUp\", queueMode: QueueMode): number[] => {\n\t\tconst indexes = items.flatMap((item, index) => (item.mode === mode ? [index] : []));\n\t\treturn queueMode === \"all\" ? indexes : indexes.slice(0, 1);\n\t};\n\tconst writes = items.flatMap((item, index) => (item.mode === \"write\" ? [index] : []));\n\tconst users = [...pick(\"steer\", boundary.steeringMode), ...(final ? pick(\"followUp\", boundary.followUpMode) : [])];\n\tusers.sort((a, b) => a - b);\n\n\t// `appendEntry()` copies the drafts' values; the items are removed only afterwards.\n\tfor (const index of writes) {\n\t\tconst item = items[index] as Draft<Extract<InboxItem, { mode: \"write\" }>>;\n\t\tconst draft = item.entry as unknown as EntryDraft;\n\t\tif (isStale(boundary, draft)) {\n\t\t\ttx.settleSubmission(item.id, { status: \"unanswered\", reason: \"stale\" });\n\t\t\tcontinue;\n\t\t}\n\t\tconst entry = await tx.appendEntry(conversationId, draft);\n\t\tif (draft.head !== undefined) boundary.head = draft.head === \"self\" ? entry.id : draft.head;\n\t\ttx.placeSubmission(item.id, entry.id);\n\t}\n\tconst placed: SubmissionId[] = [];\n\tfor (const index of users) {\n\t\tconst item = items[index] as Draft<Extract<InboxItem, { mode: \"steer\" | \"followUp\" }>>;\n\t\tconst message = { role: \"user\", content: item.content as UserInput, timestamp: now } as const;\n\t\tconst entry = await tx.appendEntry(UserEntry, conversationId, { model: [message] });\n\t\ttx.placeSubmission(item.id, entry.id);\n\t\tplaced.push(item.id);\n\t}\n\tconst removed = [...writes, ...users].sort((a, b) => b - a);\n\tfor (const index of removed) items.splice(index, 1);\n\treturn { users: placed, reset };\n}\n\n/** Whether a head write targets an entry before the active range, so placing it would bring back cut history. */\nexport function isStale(boundary: Boundary, entry: EntryDraft): boolean {\n\treturn typeof entry.head === \"number\" && boundary.head !== undefined && entry.head < boundary.head;\n}\n\n/** Remove a withdrawn submission's item; the caller settles the submission. */\nexport async function removeInboxItem(tx: Tx, conversationId: ConversationId, id: SubmissionId): Promise<void> {\n\tconst items = (await tx.doc(InboxDoc, conversationId)).items;\n\tconst index = items.findIndex((item) => item.id === id);\n\tif (index >= 0) items.splice(index, 1);\n}\n\n/**\n * Withdraw every queued input of a conversation, as `Conversation.abort()` and abort cascades do: each settles\n * `unanswered` with `aborted` and leaves the inbox; queued writes stay for later placement.\n */\nexport async function withdrawQueuedInputs(tx: Tx, conversationId: ConversationId): Promise<void> {\n\tconst items = (await tx.doc(InboxDoc, conversationId)).items;\n\tfor (let index = items.length - 1; index >= 0; index--) {\n\t\tconst item = items[index]!;\n\t\tif (item.mode === \"write\") continue;\n\t\ttx.settleSubmission(item.id, { status: \"unanswered\", reason: \"aborted\" });\n\t\titems.splice(index, 1);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/harness/inbox.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Draft, JsonRepresentation } from \"@earendil-works/chord\";\nimport { defineDoc } from \"../documents.ts\";\nimport { UserEntry } from \"../entries.ts\";\nimport type { ConversationId, EntryDraft, EntryId, JsonObject, SubmissionId, Tx } from \"../types.ts\";\nimport type { QueueMode, Settings, UserInput } from \"./types.ts\";\n\n/** A queued submission: user input for a run, or a passive entry write. */\nexport type InboxItem =\n\t| { id: SubmissionId; mode: \"steer\" | \"followUp\"; content: JsonRepresentation<UserInput> }\n\t/** `entry` is an `EntryDraft`, stored as plain JSON. */\n\t| { id: SubmissionId; mode: \"write\"; entry: JsonObject };\n\n/** Built-in queue of one conversation's submissions waiting for a boundary, in ID order. */\nexport type InboxState = { items: InboxItem[] };\n\nexport const InboxDoc = defineDoc<InboxState>({\n\tkind: \"pi.inbox\",\n\tversion: 1,\n\tscope: \"conversation\",\n\thistory: \"latest\",\n\tfork: \"initial\",\n\tinitial: () => ({ items: [] }),\n\tcheckpointWhen: (value) => value.items.length === 0,\n});\n\n/** The settings a boundary reads, on the Session line. */\nexport type QueueModes = Pick<Settings, \"steeringMode\" | \"followUpMode\">;\n\n/** What a boundary reads before the commit's first table write, and the newest head it has seen so far. */\nexport type Boundary = {\n\treadonly conversationId: ConversationId;\n\treadonly inbox: Draft<InboxState>;\n\treadonly steeringMode: QueueMode;\n\treadonly followUpMode: QueueMode;\n\t/** Start of the active range, the newest head marker's `head`; advanced by heads written in this commit. */\n\thead: EntryId | undefined;\n};\n\n/** Selected user items, in ID order, and whether a `head: \"self\"` write (a reset) was placed. */\nexport type BoundaryResult = { readonly users: SubmissionId[]; readonly reset: boolean };\n\n/**\n * Read what a boundary needs. Table reads must precede the commit's first table write, so callers prepare the\n * boundary at the start of their commit.\n */\nexport async function prepareBoundary(tx: Tx, conversationId: ConversationId, modes: QueueModes): Promise<Boundary> {\n\tconst head = (await tx.latestHeadMarker(conversationId))?.head;\n\tconst inbox = await tx.doc(InboxDoc, conversationId);\n\treturn {\n\t\tconversationId,\n\t\tinbox,\n\t\tsteeringMode: modes.steeringMode,\n\t\tfollowUpMode: modes.followUpMode,\n\t\thead,\n\t};\n}\n\n/**\n * Place the queued items a boundary selects (spec §6): every write, the first or all steers, and at `final` the first\n * or all follow-ups. A selected reset turns a `postTools` boundary into `final`. Writes are placed first and user\n * items after them, each in ID order, so user items queued before a reset run in the new context. A write whose head\n * targets an entry before the active range, including a range started earlier in this commit, is stale. Selected and\n * stale items are removed positionally.\n */\nexport async function applyBoundary(\n\ttx: Tx,\n\tboundary: Boundary,\n\tat: \"postTools\" | \"final\",\n\tnow: number,\n): Promise<BoundaryResult> {\n\tconst { conversationId, inbox } = boundary;\n\tconst items = inbox.items;\n\tconst reset = items.some((item) => item.mode === \"write\" && item.entry.head === \"self\");\n\tconst final = at === \"final\" || reset;\n\tconst pick = (mode: \"steer\" | \"followUp\", queueMode: QueueMode): number[] => {\n\t\tconst indexes = items.flatMap((item, index) => (item.mode === mode ? [index] : []));\n\t\treturn queueMode === \"all\" ? indexes : indexes.slice(0, 1);\n\t};\n\tconst writes = items.flatMap((item, index) => (item.mode === \"write\" ? [index] : []));\n\tconst users = [...pick(\"steer\", boundary.steeringMode), ...(final ? pick(\"followUp\", boundary.followUpMode) : [])];\n\tusers.sort((a, b) => a - b);\n\n\t// `appendEntry()` copies the drafts' values; the items are removed only afterwards.\n\tfor (const index of writes) {\n\t\tconst item = items[index] as Draft<Extract<InboxItem, { mode: \"write\" }>>;\n\t\tconst draft = item.entry as unknown as EntryDraft;\n\t\tif (isStale(boundary, draft)) {\n\t\t\ttx.settleSubmission(item.id, { status: \"unanswered\", reason: \"stale\" });\n\t\t\tcontinue;\n\t\t}\n\t\tconst entry = await tx.appendEntry(conversationId, draft);\n\t\tif (draft.head !== undefined) boundary.head = draft.head === \"self\" ? entry.id : draft.head;\n\t\ttx.placeSubmission(item.id, entry.id);\n\t}\n\tconst placed: SubmissionId[] = [];\n\tfor (const index of users) {\n\t\tconst item = items[index] as Draft<Extract<InboxItem, { mode: \"steer\" | \"followUp\" }>>;\n\t\tconst message = { role: \"user\", content: item.content as UserInput, timestamp: now } as const;\n\t\tconst entry = await tx.appendEntry(UserEntry, conversationId, { model: [message] });\n\t\ttx.placeSubmission(item.id, entry.id);\n\t\tplaced.push(item.id);\n\t}\n\tconst removed = [...writes, ...users].sort((a, b) => b - a);\n\tfor (const index of removed) items.splice(index, 1);\n\treturn { users: placed, reset };\n}\n\n/** Whether a head write targets an entry before the active range, so placing it would bring back cut history. */\nexport function isStale(boundary: Boundary, entry: EntryDraft): boolean {\n\treturn typeof entry.head === \"number\" && boundary.head !== undefined && entry.head < boundary.head;\n}\n\n/** Remove a withdrawn submission's item; the caller settles the submission. */\nexport async function removeInboxItem(tx: Tx, conversationId: ConversationId, id: SubmissionId): Promise<void> {\n\tconst items = (await tx.doc(InboxDoc, conversationId)).items;\n\tconst index = items.findIndex((item) => item.id === id);\n\tif (index >= 0) items.splice(index, 1);\n}\n\n/**\n * Withdraw every queued input of a conversation, as `Conversation.abort()` and abort cascades do: each settles\n * `unanswered` with `aborted` and leaves the inbox; queued writes stay for later placement.\n */\nexport async function withdrawQueuedInputs(tx: Tx, conversationId: ConversationId): Promise<void> {\n\tconst items = (await tx.doc(InboxDoc, conversationId)).items;\n\tfor (let index = items.length - 1; index >= 0; index--) {\n\t\tconst item = items[index]!;\n\t\tif (item.mode === \"write\") continue;\n\t\ttx.settleSubmission(item.id, { status: \"unanswered\", reason: \"aborted\" });\n\t\titems.splice(index, 1);\n\t}\n}\n"]}
|