@earendil-works/pi-durable 0.87.1 → 0.99.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 +46 -4
- package/dist/documents.d.ts +66 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +98 -0
- package/dist/documents.js.map +1 -0
- package/dist/entries.d.ts +13 -0
- package/dist/entries.d.ts.map +1 -0
- package/dist/entries.js +18 -0
- package/dist/entries.js.map +1 -0
- package/dist/env/index.d.ts +131 -0
- package/dist/env/index.d.ts.map +1 -0
- package/dist/env/index.js +45 -0
- package/dist/env/index.js.map +1 -0
- package/dist/env/node.d.ts +45 -0
- package/dist/env/node.d.ts.map +1 -0
- package/dist/env/node.js +908 -0
- package/dist/env/node.js.map +1 -0
- package/dist/env/utils/adaptive-publisher.d.ts +24 -0
- package/dist/env/utils/adaptive-publisher.d.ts.map +1 -0
- package/dist/env/utils/adaptive-publisher.js +79 -0
- package/dist/env/utils/adaptive-publisher.js.map +1 -0
- package/dist/env/utils/output-capture.d.ts +31 -0
- package/dist/env/utils/output-capture.d.ts.map +1 -0
- package/dist/env/utils/output-capture.js +238 -0
- package/dist/env/utils/output-capture.js.map +1 -0
- package/dist/env/utils/truncate.d.ts +71 -0
- package/dist/env/utils/truncate.d.ts.map +1 -0
- package/dist/env/utils/truncate.js +294 -0
- package/dist/env/utils/truncate.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +24 -0
- package/dist/errors.js.map +1 -0
- package/dist/harness/config.d.ts +20 -0
- package/dist/harness/config.d.ts.map +1 -0
- package/dist/harness/config.js +18 -0
- package/dist/harness/config.js.map +1 -0
- package/dist/harness/context.d.ts +27 -0
- package/dist/harness/context.d.ts.map +1 -0
- package/dist/harness/context.js +109 -0
- package/dist/harness/context.js.map +1 -0
- package/dist/harness/generation.d.ts +36 -0
- package/dist/harness/generation.d.ts.map +1 -0
- package/dist/harness/generation.js +266 -0
- package/dist/harness/generation.js.map +1 -0
- package/dist/harness/harness.d.ts +10 -0
- package/dist/harness/harness.d.ts.map +1 -0
- package/dist/harness/harness.js +266 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/harness/live.d.ts +40 -0
- package/dist/harness/live.d.ts.map +1 -0
- package/dist/harness/live.js +41 -0
- package/dist/harness/live.js.map +1 -0
- package/dist/harness/prompt.d.ts +24 -0
- package/dist/harness/prompt.d.ts.map +1 -0
- package/dist/harness/prompt.js +88 -0
- package/dist/harness/prompt.js.map +1 -0
- package/dist/harness/registry.d.ts +7 -0
- package/dist/harness/registry.d.ts.map +1 -0
- package/dist/harness/registry.js +309 -0
- package/dist/harness/registry.js.map +1 -0
- package/dist/harness/scheduler.d.ts +63 -0
- package/dist/harness/scheduler.d.ts.map +1 -0
- package/dist/harness/scheduler.js +605 -0
- package/dist/harness/scheduler.js.map +1 -0
- package/dist/harness/submissions.d.ts +24 -0
- package/dist/harness/submissions.d.ts.map +1 -0
- package/dist/harness/submissions.js +133 -0
- package/dist/harness/submissions.js.map +1 -0
- package/dist/harness/types.d.ts +358 -0
- package/dist/harness/types.d.ts.map +1 -0
- package/dist/harness/types.js +2 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/harness/util.d.ts +14 -0
- package/dist/harness/util.d.ts.map +1 -0
- package/dist/harness/util.js +55 -0
- package/dist/harness/util.js.map +1 -0
- package/dist/ids.d.ts +6 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +9 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/session/forks.d.ts +10 -0
- package/dist/session/forks.d.ts.map +1 -0
- package/dist/session/forks.js +42 -0
- package/dist/session/forks.js.map +1 -0
- package/dist/session/observation.d.ts +28 -0
- package/dist/session/observation.d.ts.map +1 -0
- package/dist/session/observation.js +280 -0
- package/dist/session/observation.js.map +1 -0
- package/dist/session/session.d.ts +59 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +380 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/transaction.d.ts +105 -0
- package/dist/session/transaction.d.ts.map +1 -0
- package/dist/session/transaction.js +718 -0
- package/dist/session/transaction.js.map +1 -0
- package/dist/storage/jsonl/index.d.ts +2 -0
- package/dist/storage/jsonl/index.d.ts.map +1 -0
- package/dist/storage/jsonl/index.js +2 -0
- package/dist/storage/jsonl/index.js.map +1 -0
- package/dist/storage/jsonl/node.d.ts +6 -0
- package/dist/storage/jsonl/node.d.ts.map +1 -0
- package/dist/storage/jsonl/node.js +8 -0
- package/dist/storage/jsonl/node.js.map +1 -0
- package/dist/storage/jsonl/storage.d.ts +115 -0
- package/dist/storage/jsonl/storage.d.ts.map +1 -0
- package/dist/storage/jsonl/storage.js +681 -0
- package/dist/storage/jsonl/storage.js.map +1 -0
- package/dist/storage/memory.d.ts +31 -14
- package/dist/storage/memory.d.ts.map +1 -1
- package/dist/storage/memory.js +208 -61
- package/dist/storage/memory.js.map +1 -1
- package/dist/storage/sqlite/database.d.ts +5 -1
- 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.map +1 -1
- package/dist/storage/sqlite/migrations.d.ts +1 -1
- package/dist/storage/sqlite/migrations.d.ts.map +1 -1
- package/dist/storage/sqlite/migrations.js +8 -1
- package/dist/storage/sqlite/migrations.js.map +1 -1
- package/dist/storage/sqlite/node.d.ts.map +1 -1
- package/dist/storage/sqlite/node.js +2 -2
- package/dist/storage/sqlite/node.js.map +1 -1
- package/dist/storage/sqlite/storage.d.ts +20 -14
- package/dist/storage/sqlite/storage.d.ts.map +1 -1
- package/dist/storage/sqlite/storage.js +159 -55
- package/dist/storage/sqlite/storage.js.map +1 -1
- package/dist/tasks.d.ts +6 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +5 -0
- package/dist/tasks.js.map +1 -0
- package/dist/testing/assertions.d.ts +5 -0
- package/dist/testing/assertions.d.ts.map +1 -0
- package/dist/testing/assertions.js +25 -0
- package/dist/testing/assertions.js.map +1 -0
- package/dist/testing/index.d.ts +6 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/runner.d.ts +10 -0
- package/dist/testing/runner.d.ts.map +1 -0
- package/dist/testing/runner.js +14 -0
- package/dist/testing/runner.js.map +1 -0
- package/dist/testing/storage-benchmark.d.ts +41 -0
- package/dist/testing/storage-benchmark.d.ts.map +1 -0
- package/dist/testing/storage-benchmark.js +351 -0
- package/dist/testing/storage-benchmark.js.map +1 -0
- package/dist/testing/storage-conformance.d.ts +4 -0
- package/dist/testing/storage-conformance.d.ts.map +1 -0
- package/dist/testing/storage-conformance.js +1122 -0
- package/dist/testing/storage-conformance.js.map +1 -0
- package/dist/testing/types.d.ts +19 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +2 -0
- package/dist/testing/types.js.map +1 -0
- package/dist/types.d.ts +422 -54
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/docs/chord-delta-findings.md +1 -1
- package/docs/pico-v5-chord-usage.md +47 -60
- package/docs/pico-v5-handoff.md +469 -264
- package/docs/pico-v5.md +1523 -639
- package/package.json +30 -5
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { withoutAbortSignal } from "@earendil-works/chord/context";
|
|
2
|
+
import { SessionImpl } from "../session/session.js";
|
|
3
|
+
import { ROOT_CONVERSATION_ID } from "../types.js";
|
|
4
|
+
import { ConversationConfig, DEFAULT_RETRY_POLICY } from "./config.js";
|
|
5
|
+
import { readContext } from "./context.js";
|
|
6
|
+
import { settleSchedulerOutcome } from "./live.js";
|
|
7
|
+
import { BUILTIN_SETUP_KEY, BUILTIN_TASKS } from "./registry.js";
|
|
8
|
+
import { TaskScheduler } from "./scheduler.js";
|
|
9
|
+
import { Submissions } from "./submissions.js";
|
|
10
|
+
import { scanAll } from "./util.js";
|
|
11
|
+
const SCAN_PAGE_SIZE = 256;
|
|
12
|
+
class ConversationImpl {
|
|
13
|
+
id;
|
|
14
|
+
#host;
|
|
15
|
+
constructor(id, host) {
|
|
16
|
+
this.id = id;
|
|
17
|
+
this.#host = host;
|
|
18
|
+
}
|
|
19
|
+
async getModel(context) {
|
|
20
|
+
return (await this.#config(context)).model;
|
|
21
|
+
}
|
|
22
|
+
setModel(model, context) {
|
|
23
|
+
return this.#editConfig((config) => {
|
|
24
|
+
if (model === undefined)
|
|
25
|
+
delete config.model;
|
|
26
|
+
else
|
|
27
|
+
config.model = { provider: model.provider, modelId: model.modelId };
|
|
28
|
+
}, context);
|
|
29
|
+
}
|
|
30
|
+
async getThinkingLevel(context) {
|
|
31
|
+
return (await this.#config(context)).thinkingLevel;
|
|
32
|
+
}
|
|
33
|
+
setThinkingLevel(level, context) {
|
|
34
|
+
return this.#editConfig((config) => {
|
|
35
|
+
config.thinkingLevel = level;
|
|
36
|
+
}, context);
|
|
37
|
+
}
|
|
38
|
+
async getActiveTools(context) {
|
|
39
|
+
return (await this.#config(context)).activeTools;
|
|
40
|
+
}
|
|
41
|
+
setActiveTools(names, context) {
|
|
42
|
+
return this.#editConfig((config) => {
|
|
43
|
+
if (new Set(names).size !== names.length)
|
|
44
|
+
throw new Error("Active tools list a name more than once");
|
|
45
|
+
requireRegistered(this.#host.registry.snapshot(), names, config.activeTools);
|
|
46
|
+
config.activeTools = [...names];
|
|
47
|
+
}, context);
|
|
48
|
+
}
|
|
49
|
+
async getStreamOptions(context) {
|
|
50
|
+
return (await this.#config(context)).streamOptions ?? {};
|
|
51
|
+
}
|
|
52
|
+
setStreamOptions(options, context) {
|
|
53
|
+
return this.#editConfig((config) => {
|
|
54
|
+
config.streamOptions = options;
|
|
55
|
+
}, context);
|
|
56
|
+
}
|
|
57
|
+
async getRetryPolicy(context) {
|
|
58
|
+
return (await this.#config(context)).retry ?? { ...DEFAULT_RETRY_POLICY };
|
|
59
|
+
}
|
|
60
|
+
setRetryPolicy(policy, context) {
|
|
61
|
+
return this.#editConfig((config) => {
|
|
62
|
+
if (policy === undefined)
|
|
63
|
+
delete config.retry;
|
|
64
|
+
else
|
|
65
|
+
config.retry = policy;
|
|
66
|
+
}, context);
|
|
67
|
+
}
|
|
68
|
+
submit(submission, context) {
|
|
69
|
+
return this.#host.submissions.submit(this.id, submission, context);
|
|
70
|
+
}
|
|
71
|
+
commit(change, context) {
|
|
72
|
+
return this.#host.harness.commitWith(change, context, { conversationId: this.id });
|
|
73
|
+
}
|
|
74
|
+
context(context) {
|
|
75
|
+
return readContext(this.#host.harness, this.#host.storage, this.id, context);
|
|
76
|
+
}
|
|
77
|
+
entries(query, limit, cursor, context) {
|
|
78
|
+
const bounded = {
|
|
79
|
+
conversationId: this.id,
|
|
80
|
+
...(query.minEntryId === undefined ? {} : { minEntryId: query.minEntryId }),
|
|
81
|
+
...(query.maxEntryId === undefined ? {} : { maxEntryId: query.maxEntryId }),
|
|
82
|
+
};
|
|
83
|
+
return this.#host.harness.readOnLine(() => this.#host.storage.scanEntries(bounded, limit, cursor, context));
|
|
84
|
+
}
|
|
85
|
+
fork(at, options, context) {
|
|
86
|
+
return this.#host.create({ kind: "fork", parentId: this.id, at, ownership: options.ownership }, options.init, context);
|
|
87
|
+
}
|
|
88
|
+
waitForIdle(context) {
|
|
89
|
+
this.#host.tasks.resume();
|
|
90
|
+
return this.#host.tasks.waitForIdle(this.id, context);
|
|
91
|
+
}
|
|
92
|
+
async #config(context) {
|
|
93
|
+
return ((await this.#host.harness.snapshot(ConversationConfig, this.id, context)) ??
|
|
94
|
+
ConversationConfig.definition.initial());
|
|
95
|
+
}
|
|
96
|
+
#editConfig(edit, context) {
|
|
97
|
+
return this.#host.harness.commitWith(async (tx) => {
|
|
98
|
+
edit(await tx.doc(ConversationConfig, this.id));
|
|
99
|
+
}, context);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Session kernel extended with conversation handles and a registry. */
|
|
103
|
+
class HarnessImpl extends SessionImpl {
|
|
104
|
+
#storage;
|
|
105
|
+
#registry;
|
|
106
|
+
#host;
|
|
107
|
+
#tasks;
|
|
108
|
+
#submissions;
|
|
109
|
+
#snapshots = new WeakMap();
|
|
110
|
+
#closed = false;
|
|
111
|
+
constructor(storage, options, context) {
|
|
112
|
+
super(storage);
|
|
113
|
+
this.#storage = storage;
|
|
114
|
+
this.#registry = options.registry;
|
|
115
|
+
const now = options.now ?? Date.now;
|
|
116
|
+
this.#tasks = new TaskScheduler({
|
|
117
|
+
session: this,
|
|
118
|
+
storage,
|
|
119
|
+
registry: options.registry,
|
|
120
|
+
models: options.models,
|
|
121
|
+
now,
|
|
122
|
+
report: options.onReport ?? (() => { }),
|
|
123
|
+
settleOutcome: settleSchedulerOutcome,
|
|
124
|
+
context: withoutAbortSignal(context),
|
|
125
|
+
});
|
|
126
|
+
this.#submissions = new Submissions(this, storage, now, () => this.#tasks.resume());
|
|
127
|
+
this.#host = {
|
|
128
|
+
harness: this,
|
|
129
|
+
storage,
|
|
130
|
+
registry: options.registry,
|
|
131
|
+
tasks: this.#tasks,
|
|
132
|
+
submissions: this.#submissions,
|
|
133
|
+
create: (target, init, context) => this.#create(target, init, context),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/** Reconcile surviving `running` tasks to `pending`; part of open. */
|
|
137
|
+
openTasks(context) {
|
|
138
|
+
return this.#tasks.open(context);
|
|
139
|
+
}
|
|
140
|
+
resume() {
|
|
141
|
+
this.#assertOpen();
|
|
142
|
+
this.#tasks.resume();
|
|
143
|
+
}
|
|
144
|
+
getTask(id, context) {
|
|
145
|
+
return this.readOnLine(() => this.#storage.task(id, context));
|
|
146
|
+
}
|
|
147
|
+
inspect(context) {
|
|
148
|
+
return this.readOnLine(async () => {
|
|
149
|
+
const snapshot = this.#registry.snapshot();
|
|
150
|
+
const { scheduling, tasks } = this.#tasks.inspect(snapshot);
|
|
151
|
+
const scan = (status) => scanAll((cursor) => this.#storage.scanSubmissions({ status }, SCAN_PAGE_SIZE, cursor, context));
|
|
152
|
+
const submissions = [...(await scan("queued")), ...(await scan("placed"))].sort((a, b) => a.id - b.id);
|
|
153
|
+
return { scheduling, tasks, submissions, registry: snapshot.failures() };
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
submission(id, context) {
|
|
157
|
+
return this.#submissions.get(id, context);
|
|
158
|
+
}
|
|
159
|
+
abortSubmission(id, context, conversationId) {
|
|
160
|
+
return this.#submissions.abort(id, context, conversationId);
|
|
161
|
+
}
|
|
162
|
+
abortTask(id, context) {
|
|
163
|
+
return this.#tasks.abort(id, context);
|
|
164
|
+
}
|
|
165
|
+
waitForTask(id, context) {
|
|
166
|
+
this.#tasks.resume();
|
|
167
|
+
return this.#tasks.waitForTask(id, context);
|
|
168
|
+
}
|
|
169
|
+
waitForIdle(context) {
|
|
170
|
+
this.#tasks.resume();
|
|
171
|
+
return this.#tasks.waitForIdle(undefined, context);
|
|
172
|
+
}
|
|
173
|
+
root(context, options) {
|
|
174
|
+
return this.#create({ kind: "root" }, options?.init, context);
|
|
175
|
+
}
|
|
176
|
+
async conversation(id, context) {
|
|
177
|
+
this.#assertOpen();
|
|
178
|
+
const record = await this.readOnLine(() => this.#storage.conversation(id, context));
|
|
179
|
+
return record === undefined ? undefined : new ConversationImpl(record.id, this.#host);
|
|
180
|
+
}
|
|
181
|
+
createConversation(options, context) {
|
|
182
|
+
return this.#create({ kind: "independent", ownership: options.ownership }, options.init, context);
|
|
183
|
+
}
|
|
184
|
+
close(context) {
|
|
185
|
+
this.#closed = true;
|
|
186
|
+
return super.close(context);
|
|
187
|
+
}
|
|
188
|
+
/** Join task invocations after admission is sealed and before Storage closes; writes no task outcome. */
|
|
189
|
+
beforeClose() {
|
|
190
|
+
return this.#tasks.join();
|
|
191
|
+
}
|
|
192
|
+
async #create(target, init, context) {
|
|
193
|
+
this.#assertOpen();
|
|
194
|
+
const id = await this.commitWith(async (tx) => {
|
|
195
|
+
if (target.kind === "root" && (await tx.conversation(ROOT_CONVERSATION_ID)) !== undefined) {
|
|
196
|
+
return ROOT_CONVERSATION_ID;
|
|
197
|
+
}
|
|
198
|
+
const record = target.kind === "root"
|
|
199
|
+
? await tx.createRootConversation()
|
|
200
|
+
: target.kind === "fork"
|
|
201
|
+
? await tx.forkConversation(target.parentId, target.at, { ownership: target.ownership })
|
|
202
|
+
: await tx.createConversation({ ownership: target.ownership });
|
|
203
|
+
if (init !== undefined)
|
|
204
|
+
await this.#runInit(tx, record.id, init);
|
|
205
|
+
return record.id;
|
|
206
|
+
}, context);
|
|
207
|
+
return new ConversationImpl(id, this.#host);
|
|
208
|
+
}
|
|
209
|
+
/** Run every registered conversation setup, built-ins first, in each commit that creates or forks a conversation. */
|
|
210
|
+
async conversationCreated(tx, record) {
|
|
211
|
+
const snapshot = this.#snapshotOf(tx);
|
|
212
|
+
for (const { setup } of snapshot.conversationSetups())
|
|
213
|
+
await setup(tx, record, snapshot);
|
|
214
|
+
}
|
|
215
|
+
/** Run `init` in the creating commit; its writes are trusted, but names it newly activates must be registered. */
|
|
216
|
+
async #runInit(tx, id, init) {
|
|
217
|
+
const snapshot = this.#snapshotOf(tx);
|
|
218
|
+
const baseline = [...(await tx.doc(ConversationConfig, id)).activeTools];
|
|
219
|
+
await init(tx, id);
|
|
220
|
+
requireRegistered(snapshot, (await tx.doc(ConversationConfig, id)).activeTools, baseline);
|
|
221
|
+
}
|
|
222
|
+
/** One registry snapshot per commit, shared by its conversation setups and `init` checks. */
|
|
223
|
+
#snapshotOf(tx) {
|
|
224
|
+
let snapshot = this.#snapshots.get(tx);
|
|
225
|
+
if (snapshot === undefined) {
|
|
226
|
+
snapshot = this.#registry.snapshot();
|
|
227
|
+
this.#snapshots.set(tx, snapshot);
|
|
228
|
+
}
|
|
229
|
+
return snapshot;
|
|
230
|
+
}
|
|
231
|
+
#assertOpen() {
|
|
232
|
+
if (this.#closed)
|
|
233
|
+
throw new Error("Harness is closed");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/** Reject names newly added relative to `previous` that `snapshot` does not register; existing names are never rechecked. */
|
|
237
|
+
function requireRegistered(snapshot, names, previous) {
|
|
238
|
+
const existing = new Set(previous);
|
|
239
|
+
const registered = new Set(snapshot.toolNames());
|
|
240
|
+
const missing = names.filter((name) => !existing.has(name) && !registered.has(name));
|
|
241
|
+
if (missing.length > 0)
|
|
242
|
+
throw new Error(`Tools are not registered: ${missing.join(", ")}`);
|
|
243
|
+
}
|
|
244
|
+
export const Harness = {
|
|
245
|
+
/** Open a Harness over storage. The registry may keep changing while the Harness runs. */
|
|
246
|
+
async open(storage, options, context) {
|
|
247
|
+
context.abortSignal?.throwIfAborted();
|
|
248
|
+
const snapshot = options.registry.snapshot();
|
|
249
|
+
const missing = BUILTIN_TASKS.filter((task) => snapshot.task(task.definition.name) === undefined).map((task) => `task ${task.definition.name}`);
|
|
250
|
+
if (!snapshot.conversationSetups().some(({ key }) => key === BUILTIN_SETUP_KEY))
|
|
251
|
+
missing.push("conversation setup pi");
|
|
252
|
+
if (missing.length > 0) {
|
|
253
|
+
throw new Error(`Registry lacks built-in ${missing.join(", ")}; create it with createRegistry()`);
|
|
254
|
+
}
|
|
255
|
+
const harness = new HarnessImpl(storage, options, context);
|
|
256
|
+
try {
|
|
257
|
+
await harness.openTasks(context);
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
await harness.close(context);
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
return harness;
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
//# sourceMappingURL=harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/harness/harness.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAiBpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAgC,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAmB/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,cAAc,GAAG,GAAG,CAAC;AAsB3B,MAAM,gBAAgB;IACZ,EAAE,CAAiB;IACnB,KAAK,CAAyB;IAEvC,YAAY,EAAkB,EAAE,IAA4B;QAC3D,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAgB;QAC9B,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAC5C,CAAC;IAED,QAAQ,CAAC,KAA2B,EAAE,OAAgB;QACrD,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,EAAE;YAClC,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC,KAAK,CAAC;;gBACxC,MAAM,CAAC,KAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC1E,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAgB;QACtC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;IACpD,CAAC;IAED,gBAAgB,CAAC,KAAyB,EAAE,OAAgB;QAC3D,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,EAAE;YAClC,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC;QAC9B,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAgB;QACpC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IAClD,CAAC;IAED,cAAc,CAAC,KAAwB,EAAE,OAAgB;QACxD,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,EAAE;YAClC,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YACrG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;YAC7E,MAAM,CAAC,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QACjC,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAgB;QACtC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC;IAC1D,CAAC;IAED,gBAAgB,CAAC,OAAkC,EAAE,OAAgB;QACpE,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,EAAE;YAClC,MAAM,CAAC,aAAa,GAAG,OAAO,CAAC;QAChC,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAgB;QACpC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAC3E,CAAC;IAED,cAAc,CAAC,MAA2C,EAAE,OAAgB;QAC3E,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,EAAE;YAClC,IAAI,MAAM,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC,KAAK,CAAC;;gBACzC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;QAC5B,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;IAED,MAAM,CAAC,UAA2B,EAAE,OAAgB;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,CAAI,MAAkC,EAAE,OAAgB;QAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,CAAC,OAAgB;QACvB,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,CACN,KAAyC,EACzC,KAAa,EACb,MAA0B,EAC1B,OAAgB;QAEhB,MAAM,OAAO,GAAe;YAC3B,cAAc,EAAE,IAAI,CAAC,EAAE;YACvB,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;YAC3E,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;SAC3E,CAAC;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7G,CAAC;IAED,IAAI,CAAC,EAAW,EAAE,OAAkC,EAAE,OAAgB;QACrE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CACvB,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,EACrE,OAAO,CAAC,IAAI,EACZ,OAAO,CACP,CAAC;IACH,CAAC;IAED,WAAW,CAAC,OAAgB;QAC3B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAgB;QAC7B,OAAO,CACN,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACzE,kBAAkB,CAAC,UAAU,CAAC,OAAO,EAAE,CACvC,CAAC;IACH,CAAC;IAED,WAAW,CAAC,IAAsD,EAAE,OAAgB;QACnF,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACjD,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACjD,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;CACD;AAED,wEAAwE;AACxE,MAAM,WAA2C,SAAQ,WAAW;IAC1D,QAAQ,CAAU;IAClB,SAAS,CAAuB;IAChC,KAAK,CAAyB;IAC9B,MAAM,CAAgB;IACtB,YAAY,CAAc;IAC1B,UAAU,GAAG,IAAI,OAAO,EAAuC,CAAC;IACzE,OAAO,GAAG,KAAK,CAAC;IAEhB,YAAY,OAAgB,EAAE,OAA6B,EAAE,OAAgB;QAC5E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,IAAI,aAAa,CAAC;YAC/B,OAAO,EAAE,IAAI;YACb,OAAO;YACP,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,GAAG;YACH,MAAM,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;YACtC,aAAa,EAAE,sBAAsB;YACrC,OAAO,EAAE,kBAAkB,CAAC,OAAO,CAAC;SACpC,CAAC,CAAC;QACH,IAAI,CAAC,YAAY,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACpF,IAAI,CAAC,KAAK,GAAG;YACZ,OAAO,EAAE,IAAI;YACb,OAAO;YACP,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,MAAM,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC;SACtE,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,SAAS,CAAC,OAAgB;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,MAAM;QACL,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IACtB,CAAC;IAED,OAAO,CAAI,EAAa,EAAE,OAAgB;QACzC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAE3D,CAAC;IACH,CAAC;IAED,OAAO,CAAC,OAAgB;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE;YACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC3C,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC5D,MAAM,IAAI,GAAG,CAAC,MAA2B,EAAE,EAAE,CAC5C,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;YACjG,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;YACvG,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC1E,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,EAAgB,EAAE,OAAgB;QAC5C,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,eAAe,CACd,EAAgB,EAChB,OAAgB,EAChB,cAA+B;QAE/B,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;IAC7D,CAAC;IAED,SAAS,CAAC,EAAU,EAAE,OAAgB;QACrC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,WAAW,CAAI,EAAa,EAAE,OAAgB;QAC7C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,CAA4B,CAAC;IACxE,CAAC;IAED,WAAW,CAAC,OAAgB;QAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,CAAC,OAAgB,EAAE,OAA8C;QACpE,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAkB,EAAE,OAAgB;QACtD,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QACpF,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACvF,CAAC;IAED,kBAAkB,CAAC,OAAkC,EAAE,OAAgB;QACtE,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnG,CAAC;IAEQ,KAAK,CAAC,OAAgB;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,yGAAyG;IACtF,WAAW;QAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAoB,EAAE,IAAkC,EAAE,OAAgB;QACvF,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7C,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC3F,OAAO,oBAAoB,CAAC;YAC7B,CAAC;YACD,MAAM,MAAM,GACX,MAAM,CAAC,IAAI,KAAK,MAAM;gBACrB,CAAC,CAAC,MAAM,EAAE,CAAC,sBAAsB,EAAE;gBACnC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM;oBACvB,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;oBACxF,CAAC,CAAC,MAAM,EAAE,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;YAClE,IAAI,IAAI,KAAK,SAAS;gBAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACjE,OAAO,MAAM,CAAC,EAAE,CAAC;QAClB,CAAC,EAAE,OAAO,CAAC,CAAC;QACZ,OAAO,IAAI,gBAAgB,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IAED,qHAAqH;IAClG,KAAK,CAAC,mBAAmB,CAAC,EAAe,EAAE,MAA0B;QACvF,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACtC,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,QAAQ,CAAC,kBAAkB,EAAE;YAAE,MAAM,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1F,CAAC;IAED,kHAAkH;IAClH,KAAK,CAAC,QAAQ,CAAC,EAAe,EAAE,EAAkB,EAAE,IAAsB;QACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACzE,MAAM,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnB,iBAAiB,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC3F,CAAC;IAED,6FAA6F;IAC7F,WAAW,CAAC,EAAe;QAC1B,IAAI,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACrC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,WAAW;QACV,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACxD,CAAC;CACD;AAED,6HAA6H;AAC7H,SAAS,iBAAiB,CACzB,QAAgC,EAChC,KAAwB,EACxB,QAA2B;IAE3B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACrF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC5F,CAAC;AAKD,MAAM,CAAC,MAAM,OAAO,GAAG;IACtB,0FAA0F;IAC1F,KAAK,CAAC,IAAI,CACT,OAAgB,EAChB,OAA6B,EAC7B,OAAgB;QAEhB,OAAO,CAAC,WAAW,EAAE,cAAc,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,GAAG,CACpG,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CACxC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,KAAK,iBAAiB,CAAC;YAC9E,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACvC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACnG,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC;YACJ,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,MAAM,KAAK,CAAC;QACb,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;CACD,CAAC","sourcesContent":["import type { Context, Draft, JsonValue } from \"@earendil-works/chord\";\nimport { withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport type { ModelThinkingLevel } from \"@earendil-works/pi-ai\";\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 { ConversationConfig, type ConversationConfigState, DEFAULT_RETRY_POLICY } from \"./config.ts\";\nimport { readContext } from \"./context.ts\";\nimport { settleSchedulerOutcome } from \"./live.ts\";\nimport { BUILTIN_SETUP_KEY, BUILTIN_TASKS } from \"./registry.ts\";\nimport { TaskScheduler } from \"./scheduler.ts\";\nimport { Submissions } from \"./submissions.ts\";\nimport type {\n\tContextView,\n\tConversation,\n\tConversationCreateOptions,\n\tConversationInit,\n\tConversationRetryPolicy,\n\tConversationStreamOptions,\n\tHarnessInspection,\n\tHarnessOptions,\n\tHarness as HarnessType,\n\tModelRef,\n\tRegistryReader,\n\tRegistrySnapshot,\n\tSettledTask,\n\tSubmission,\n\tSubmissionDraft,\n\tToolRegistration,\n} from \"./types.ts\";\nimport { scanAll } from \"./util.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\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\tsubmit(submission: SubmissionDraft, context: Context): Promise<Submission> {\n\t\treturn this.#host.submissions.submit(this.id, submission, 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\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\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\tnow,\n\t\t\treport: options.onReport ?? (() => {}),\n\t\t\tsettleOutcome: settleSchedulerOutcome,\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\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 } = 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\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/** 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"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Draft, JsonRepresentation, JsonValue } from "@earendil-works/chord";
|
|
2
|
+
import type { AssistantMessage } from "@earendil-works/pi-ai";
|
|
3
|
+
import type { Transaction } from "../session/transaction.ts";
|
|
4
|
+
import type { SubmissionId, SubmissionSettlement, TaskId, TaskRecord, Tx } from "../types.ts";
|
|
5
|
+
import type { SchedulerOutcome } from "./scheduler.ts";
|
|
6
|
+
/** Built-in live conversation state: run control and presentation of the current generation. */
|
|
7
|
+
export type LiveState = {
|
|
8
|
+
/** Run control: the task responsible for the run and its placed inputs; present exactly while busy. */
|
|
9
|
+
run?: {
|
|
10
|
+
taskId: TaskId;
|
|
11
|
+
inputs: SubmissionId[];
|
|
12
|
+
};
|
|
13
|
+
/** Presentation of the current generation attempt. */
|
|
14
|
+
generation?: {
|
|
15
|
+
attempt: number;
|
|
16
|
+
/** Committed throttled partial of the in-flight response. */
|
|
17
|
+
message?: JsonRepresentation<AssistantMessage>;
|
|
18
|
+
/** Durable backoff before the next attempt. */
|
|
19
|
+
retry?: {
|
|
20
|
+
at: number;
|
|
21
|
+
error: string;
|
|
22
|
+
};
|
|
23
|
+
/** Provider-side deferred response being polled. */
|
|
24
|
+
deferred?: {
|
|
25
|
+
pollAt: number;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export declare const LiveDoc: import("../types.ts").ConversationDocToken<LiveState>;
|
|
30
|
+
/**
|
|
31
|
+
* End the run owned by `taskId`: settle each of its inputs and remove `run`. Always removes `generation`, whose
|
|
32
|
+
* presentation belongs to the ending task.
|
|
33
|
+
*/
|
|
34
|
+
export declare function endRun(tx: Tx, live: Draft<LiveState>, taskId: TaskId, settlement: SubmissionSettlement): void;
|
|
35
|
+
/**
|
|
36
|
+
* Harness cleanup for a terminal outcome the scheduler writes itself (`faulted` or `orphaned`). Ignores non-run task
|
|
37
|
+
* kinds so it never creates `pi.live` elsewhere. Committed partials are discarded without a transcript entry.
|
|
38
|
+
*/
|
|
39
|
+
export declare function settleSchedulerOutcome(tx: Transaction, record: TaskRecord<JsonValue, JsonValue, JsonValue>, outcome: SchedulerOutcome): Promise<void>;
|
|
40
|
+
//# sourceMappingURL=live.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/harness/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAC9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,gGAAgG;AAChG,MAAM,MAAM,SAAS,GAAG;IACvB,uGAAuG;IACvG,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC;IACjD,sDAAsD;IACtD,UAAU,CAAC,EAAE;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,6DAA6D;QAC7D,OAAO,CAAC,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;QAC/C,+CAA+C;QAC/C,KAAK,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACtC,oDAAoD;QACpD,QAAQ,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAC9B,CAAC;CACF,CAAC;AAEF,eAAO,MAAM,OAAO,uDAUlB,CAAC;AAKH;;;GAGG;AACH,wBAAgB,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,oBAAoB,GAAG,IAAI,CAM7G;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC3C,EAAE,EAAE,WAAW,EACf,MAAM,EAAE,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EACnD,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CAYf"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { defineDoc } from "../documents.js";
|
|
2
|
+
export const LiveDoc = defineDoc({
|
|
3
|
+
kind: "pi.live",
|
|
4
|
+
version: 1,
|
|
5
|
+
scope: "conversation",
|
|
6
|
+
history: "latest",
|
|
7
|
+
fork: "initial",
|
|
8
|
+
initial: () => ({}),
|
|
9
|
+
// A complete base whenever nothing is in flight, so the delta chain spans at most one generation, including its
|
|
10
|
+
// retries and deferred polls, or one tool round.
|
|
11
|
+
checkpointWhen: (value) => value.generation === undefined,
|
|
12
|
+
});
|
|
13
|
+
/** Built-in task kinds that can own `pi.live.run`. */
|
|
14
|
+
const RUN_TASK_KINDS = new Set(["pi.generation"]);
|
|
15
|
+
/**
|
|
16
|
+
* End the run owned by `taskId`: settle each of its inputs and remove `run`. Always removes `generation`, whose
|
|
17
|
+
* presentation belongs to the ending task.
|
|
18
|
+
*/
|
|
19
|
+
export function endRun(tx, live, taskId, settlement) {
|
|
20
|
+
if (live.run?.taskId === taskId) {
|
|
21
|
+
for (const id of live.run.inputs)
|
|
22
|
+
tx.settleSubmission(id, settlement);
|
|
23
|
+
delete live.run;
|
|
24
|
+
}
|
|
25
|
+
delete live.generation;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Harness cleanup for a terminal outcome the scheduler writes itself (`faulted` or `orphaned`). Ignores non-run task
|
|
29
|
+
* kinds so it never creates `pi.live` elsewhere. Committed partials are discarded without a transcript entry.
|
|
30
|
+
*/
|
|
31
|
+
export async function settleSchedulerOutcome(tx, record, outcome) {
|
|
32
|
+
if (!RUN_TASK_KINDS.has(record.kind))
|
|
33
|
+
return;
|
|
34
|
+
const live = await tx.doc(LiveDoc, record.conversationId);
|
|
35
|
+
if (live.run?.taskId !== record.id)
|
|
36
|
+
return;
|
|
37
|
+
endRun(tx, live, record.id, outcome.status === "faulted"
|
|
38
|
+
? { status: "unanswered", reason: "faulted", detail: outcome.error.message }
|
|
39
|
+
: { status: "unanswered", reason: outcome.reason });
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/harness/live.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAqB5C,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAY;IAC3C,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,CAAC;IACV,KAAK,EAAE,cAAc;IACrB,OAAO,EAAE,QAAQ;IACjB,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;IACnB,gHAAgH;IAChH,iDAAiD;IACjD,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS;CACzD,CAAC,CAAC;AAEH,sDAAsD;AACtD,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;AAEvE;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,EAAM,EAAE,IAAsB,EAAE,MAAc,EAAE,UAAgC;IACtG,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;QACjC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC,GAAG,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC,UAAU,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,EAAe,EACf,MAAmD,EACnD,OAAyB;IAEzB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO;IAC7C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAC1D,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,EAAE;QAAE,OAAO;IAC3C,MAAM,CACL,EAAE,EACF,IAAI,EACJ,MAAM,CAAC,EAAE,EACT,OAAO,CAAC,MAAM,KAAK,SAAS;QAC3B,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE;QAC5E,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CACnD,CAAC;AACH,CAAC","sourcesContent":["import type { Draft, JsonRepresentation, JsonValue } from \"@earendil-works/chord\";\nimport type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { defineDoc } from \"../documents.ts\";\nimport type { Transaction } from \"../session/transaction.ts\";\nimport type { SubmissionId, SubmissionSettlement, TaskId, TaskRecord, Tx } from \"../types.ts\";\nimport type { SchedulerOutcome } from \"./scheduler.ts\";\n\n/** Built-in live conversation state: run control and presentation of the current generation. */\nexport type LiveState = {\n\t/** Run control: the task responsible for the run and its placed inputs; present exactly while busy. */\n\trun?: { taskId: TaskId; inputs: SubmissionId[] };\n\t/** Presentation of the current generation attempt. */\n\tgeneration?: {\n\t\tattempt: number;\n\t\t/** Committed throttled partial of the in-flight response. */\n\t\tmessage?: JsonRepresentation<AssistantMessage>;\n\t\t/** Durable backoff before the next attempt. */\n\t\tretry?: { at: number; error: string };\n\t\t/** Provider-side deferred response being polled. */\n\t\tdeferred?: { pollAt: number };\n\t};\n};\n\nexport const LiveDoc = defineDoc<LiveState>({\n\tkind: \"pi.live\",\n\tversion: 1,\n\tscope: \"conversation\",\n\thistory: \"latest\",\n\tfork: \"initial\",\n\tinitial: () => ({}),\n\t// A complete base whenever nothing is in flight, so the delta chain spans at most one generation, including its\n\t// retries and deferred polls, or one tool round.\n\tcheckpointWhen: (value) => value.generation === undefined,\n});\n\n/** Built-in task kinds that can own `pi.live.run`. */\nconst RUN_TASK_KINDS: ReadonlySet<string> = new Set([\"pi.generation\"]);\n\n/**\n * End the run owned by `taskId`: settle each of its inputs and remove `run`. Always removes `generation`, whose\n * presentation belongs to the ending task.\n */\nexport function endRun(tx: Tx, live: Draft<LiveState>, taskId: TaskId, settlement: SubmissionSettlement): void {\n\tif (live.run?.taskId === taskId) {\n\t\tfor (const id of live.run.inputs) tx.settleSubmission(id, settlement);\n\t\tdelete live.run;\n\t}\n\tdelete live.generation;\n}\n\n/**\n * Harness cleanup for a terminal outcome the scheduler writes itself (`faulted` or `orphaned`). Ignores non-run task\n * kinds so it never creates `pi.live` elsewhere. Committed partials are discarded without a transcript entry.\n */\nexport async function settleSchedulerOutcome(\n\ttx: Transaction,\n\trecord: TaskRecord<JsonValue, JsonValue, JsonValue>,\n\toutcome: SchedulerOutcome,\n): Promise<void> {\n\tif (!RUN_TASK_KINDS.has(record.kind)) return;\n\tconst live = await tx.doc(LiveDoc, record.conversationId);\n\tif (live.run?.taskId !== record.id) return;\n\tendRun(\n\t\ttx,\n\t\tlive,\n\t\trecord.id,\n\t\toutcome.status === \"faulted\"\n\t\t\t? { status: \"unanswered\", reason: \"faulted\", detail: outcome.error.message }\n\t\t\t: { status: \"unanswered\", reason: outcome.reason },\n\t);\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Context } from "@earendil-works/chord";
|
|
2
|
+
import type { Message } from "@earendil-works/pi-ai";
|
|
3
|
+
import type { TypedEntryDraft } from "../types.ts";
|
|
4
|
+
import type { ContextView, PromptInput, PromptSection, ToolRegistration } from "./types.ts";
|
|
5
|
+
/** Sections in effect after replaying system messages in order: set in place, `null` deletes, re-adding appends. */
|
|
6
|
+
export declare function replaySections(messages: readonly Message[]): Map<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* Render sections in registry order. `undefined` omits a section; tagged text is wrapped as `<key>\n...\n</key>`. A
|
|
9
|
+
* section that throws keeps its shown text, if any, and is reported; errors after `context` is aborted propagate.
|
|
10
|
+
*/
|
|
11
|
+
export declare function renderSections<Tool extends ToolRegistration>(sections: readonly PromptSection<Tool>[], input: PromptInput<Tool>, shown: ReadonlyMap<string, string>, report: (error: unknown) => void, context: Context): Promise<Map<string, string>>;
|
|
12
|
+
type SystemDraft = TypedEntryDraft<never>;
|
|
13
|
+
/**
|
|
14
|
+
* Plan the `pi.system` entries that make the replayed sections of `view` equal `desired` in values and order.
|
|
15
|
+
*
|
|
16
|
+
* - A head marker with no later `pi.system` entry in context: one complete baseline that omits every retained earlier
|
|
17
|
+
* `pi.system` entry, written even when it restates the replayed values.
|
|
18
|
+
* - Otherwise, when a minimal patch would leave a different order: remove every shown section, then re-add every
|
|
19
|
+
* desired section in order.
|
|
20
|
+
* - Otherwise the minimal patch of changed values and `null` removals, or nothing.
|
|
21
|
+
*/
|
|
22
|
+
export declare function planSystemEntries(view: ContextView, desired: ReadonlyMap<string, string>, timestamp: number): SystemDraft[];
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/harness/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,uBAAuB,CAAC;AAEpE,OAAO,KAAK,EAAe,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE5F,oHAAoH;AACpH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAUhF;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,SAAS,gBAAgB,EACjE,QAAQ,EAAE,SAAS,aAAa,CAAC,IAAI,CAAC,EAAE,EACxC,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,EACxB,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EAChC,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAiB9B;AAED,KAAK,WAAW,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;AAE1C;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,SAAS,EAAE,MAAM,GACf,WAAW,EAAE,CA8Bf"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { SystemEntry } from "../entries.js";
|
|
2
|
+
/** Sections in effect after replaying system messages in order: set in place, `null` deletes, re-adding appends. */
|
|
3
|
+
export function replaySections(messages) {
|
|
4
|
+
const shown = new Map();
|
|
5
|
+
for (const message of messages) {
|
|
6
|
+
if (message.role !== "system" || message.sections === undefined)
|
|
7
|
+
continue;
|
|
8
|
+
for (const [key, value] of Object.entries(message.sections)) {
|
|
9
|
+
if (value === null)
|
|
10
|
+
shown.delete(key);
|
|
11
|
+
else
|
|
12
|
+
shown.set(key, value);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return shown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Render sections in registry order. `undefined` omits a section; tagged text is wrapped as `<key>\n...\n</key>`. A
|
|
19
|
+
* section that throws keeps its shown text, if any, and is reported; errors after `context` is aborted propagate.
|
|
20
|
+
*/
|
|
21
|
+
export async function renderSections(sections, input, shown, report, context) {
|
|
22
|
+
const desired = new Map();
|
|
23
|
+
for (const section of sections) {
|
|
24
|
+
let text;
|
|
25
|
+
try {
|
|
26
|
+
text = await section.render(input, context);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (context.abortSignal?.aborted)
|
|
30
|
+
throw error;
|
|
31
|
+
report(error);
|
|
32
|
+
const kept = shown.get(section.key);
|
|
33
|
+
if (kept !== undefined)
|
|
34
|
+
desired.set(section.key, kept);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (text === undefined)
|
|
38
|
+
continue;
|
|
39
|
+
desired.set(section.key, section.tag === false ? text : `<${section.key}>\n${text}\n</${section.key}>`);
|
|
40
|
+
}
|
|
41
|
+
return desired;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Plan the `pi.system` entries that make the replayed sections of `view` equal `desired` in values and order.
|
|
45
|
+
*
|
|
46
|
+
* - A head marker with no later `pi.system` entry in context: one complete baseline that omits every retained earlier
|
|
47
|
+
* `pi.system` entry, written even when it restates the replayed values.
|
|
48
|
+
* - Otherwise, when a minimal patch would leave a different order: remove every shown section, then re-add every
|
|
49
|
+
* desired section in order.
|
|
50
|
+
* - Otherwise the minimal patch of changed values and `null` removals, or nothing.
|
|
51
|
+
*/
|
|
52
|
+
export function planSystemEntries(view, desired, timestamp) {
|
|
53
|
+
const head = view.head;
|
|
54
|
+
if (head !== undefined && !view.entries.some((entry) => SystemEntry.is(entry) && entry.id > head.id)) {
|
|
55
|
+
const edits = view.entries
|
|
56
|
+
.filter((entry) => SystemEntry.is(entry))
|
|
57
|
+
.map((entry) => ({ target: entry.id, action: "omit" }));
|
|
58
|
+
const baseline = systemEntry(Object.fromEntries(desired), timestamp);
|
|
59
|
+
return [edits.length === 0 ? baseline : { ...baseline, edits }];
|
|
60
|
+
}
|
|
61
|
+
const shown = replaySections(view.messages);
|
|
62
|
+
const patchedOrder = [
|
|
63
|
+
...[...shown.keys()].filter((key) => desired.has(key)),
|
|
64
|
+
...[...desired.keys()].filter((key) => !shown.has(key)),
|
|
65
|
+
];
|
|
66
|
+
const desiredOrder = [...desired.keys()];
|
|
67
|
+
if (patchedOrder.some((key, index) => key !== desiredOrder[index])) {
|
|
68
|
+
return [
|
|
69
|
+
systemEntry(Object.fromEntries([...shown.keys()].map((key) => [key, null])), timestamp),
|
|
70
|
+
systemEntry(Object.fromEntries(desired), timestamp),
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
const patch = {};
|
|
74
|
+
for (const [key, value] of shown) {
|
|
75
|
+
const next = desired.get(key);
|
|
76
|
+
if (next !== value)
|
|
77
|
+
patch[key] = next ?? null;
|
|
78
|
+
}
|
|
79
|
+
for (const [key, value] of desired)
|
|
80
|
+
if (!shown.has(key))
|
|
81
|
+
patch[key] = value;
|
|
82
|
+
return Object.keys(patch).length === 0 ? [] : [systemEntry(patch, timestamp)];
|
|
83
|
+
}
|
|
84
|
+
function systemEntry(sections, timestamp) {
|
|
85
|
+
const message = { role: "system", content: "", sections, timestamp };
|
|
86
|
+
return { model: [message] };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/harness/prompt.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Context } from \"@earendil-works/chord\";\nimport type { Message, SystemMessage } from \"@earendil-works/pi-ai\";\nimport { SystemEntry } from \"../entries.ts\";\nimport type { ContextEdit, TypedEntryDraft } from \"../types.ts\";\nimport type { ContextView, PromptInput, PromptSection, ToolRegistration } from \"./types.ts\";\n\n/** Sections in effect after replaying system messages in order: set in place, `null` deletes, re-adding appends. */\nexport function replaySections(messages: readonly Message[]): Map<string, string> {\n\tconst shown = new Map<string, string>();\n\tfor (const message of messages) {\n\t\tif (message.role !== \"system\" || message.sections === undefined) continue;\n\t\tfor (const [key, value] of Object.entries(message.sections)) {\n\t\t\tif (value === null) shown.delete(key);\n\t\t\telse shown.set(key, value);\n\t\t}\n\t}\n\treturn shown;\n}\n\n/**\n * Render sections in registry order. `undefined` omits a section; tagged text is wrapped as `<key>\\n...\\n</key>`. A\n * section that throws keeps its shown text, if any, and is reported; errors after `context` is aborted propagate.\n */\nexport async function renderSections<Tool extends ToolRegistration>(\n\tsections: readonly PromptSection<Tool>[],\n\tinput: PromptInput<Tool>,\n\tshown: ReadonlyMap<string, string>,\n\treport: (error: unknown) => void,\n\tcontext: Context,\n): Promise<Map<string, string>> {\n\tconst desired = new Map<string, string>();\n\tfor (const section of sections) {\n\t\tlet text: string | undefined;\n\t\ttry {\n\t\t\ttext = await section.render(input, context);\n\t\t} catch (error) {\n\t\t\tif (context.abortSignal?.aborted) throw error;\n\t\t\treport(error);\n\t\t\tconst kept = shown.get(section.key);\n\t\t\tif (kept !== undefined) desired.set(section.key, kept);\n\t\t\tcontinue;\n\t\t}\n\t\tif (text === undefined) continue;\n\t\tdesired.set(section.key, section.tag === false ? text : `<${section.key}>\\n${text}\\n</${section.key}>`);\n\t}\n\treturn desired;\n}\n\ntype SystemDraft = TypedEntryDraft<never>;\n\n/**\n * Plan the `pi.system` entries that make the replayed sections of `view` equal `desired` in values and order.\n *\n * - A head marker with no later `pi.system` entry in context: one complete baseline that omits every retained earlier\n * `pi.system` entry, written even when it restates the replayed values.\n * - Otherwise, when a minimal patch would leave a different order: remove every shown section, then re-add every\n * desired section in order.\n * - Otherwise the minimal patch of changed values and `null` removals, or nothing.\n */\nexport function planSystemEntries(\n\tview: ContextView,\n\tdesired: ReadonlyMap<string, string>,\n\ttimestamp: number,\n): SystemDraft[] {\n\tconst head = view.head;\n\tif (head !== undefined && !view.entries.some((entry) => SystemEntry.is(entry) && entry.id > head.id)) {\n\t\tconst edits: ContextEdit[] = view.entries\n\t\t\t.filter((entry) => SystemEntry.is(entry))\n\t\t\t.map((entry) => ({ target: entry.id, action: \"omit\" }));\n\t\tconst baseline = systemEntry(Object.fromEntries(desired), timestamp);\n\t\treturn [edits.length === 0 ? baseline : { ...baseline, edits }];\n\t}\n\n\tconst shown = replaySections(view.messages);\n\tconst patchedOrder = [\n\t\t...[...shown.keys()].filter((key) => desired.has(key)),\n\t\t...[...desired.keys()].filter((key) => !shown.has(key)),\n\t];\n\tconst desiredOrder = [...desired.keys()];\n\tif (patchedOrder.some((key, index) => key !== desiredOrder[index])) {\n\t\treturn [\n\t\t\tsystemEntry(Object.fromEntries([...shown.keys()].map((key) => [key, null])), timestamp),\n\t\t\tsystemEntry(Object.fromEntries(desired), timestamp),\n\t\t];\n\t}\n\n\tconst patch: Record<string, string | null> = {};\n\tfor (const [key, value] of shown) {\n\t\tconst next = desired.get(key);\n\t\tif (next !== value) patch[key] = next ?? null;\n\t}\n\tfor (const [key, value] of desired) if (!shown.has(key)) patch[key] = value;\n\treturn Object.keys(patch).length === 0 ? [] : [systemEntry(patch, timestamp)];\n}\n\nfunction systemEntry(sections: Record<string, string | null>, timestamp: number): SystemDraft {\n\tconst message: SystemMessage = { role: \"system\", content: \"\", sections, timestamp };\n\treturn { model: [message] };\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AnyTask, Registry, ToolRegistration } from "./types.ts";
|
|
2
|
+
/** Built-in task definitions every registry starts with; they cannot be disposed or replaced. */
|
|
3
|
+
export declare const BUILTIN_TASKS: readonly AnyTask[];
|
|
4
|
+
export declare const BUILTIN_SETUP_KEY = "pi";
|
|
5
|
+
/** Create an application-owned registry holding only the built-ins. */
|
|
6
|
+
export declare function createRegistry<Tool extends ToolRegistration = ToolRegistration>(): Registry<Tool>;
|
|
7
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/harness/registry.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,OAAO,EAQP,QAAQ,EAGR,gBAAgB,EAEhB,MAAM,YAAY,CAAC;AAIpB,iGAAiG;AACjG,eAAO,MAAM,aAAa,EAAE,SAAS,OAAO,EAAqB,CAAC;AAElE,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAgUtC,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,IAAI,SAAS,gBAAgB,GAAG,gBAAgB,KAAK,QAAQ,CAAC,IAAI,CAAC,CAMjG"}
|