@wrenautomation/aerie 0.5.2 → 0.6.1
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/dist/bin.js +5329 -4757
- package/dist/bin.js.map +4 -4
- package/dist/cli-intake.d.ts +3 -0
- package/dist/cli-intake.js +100 -0
- package/dist/cli-intake.js.map +1 -0
- package/dist/cli.js +23 -6
- package/dist/cli.js.map +1 -1
- package/dist/intake/index.d.ts +150 -0
- package/dist/intake/index.js +312 -0
- package/dist/intake/index.js.map +1 -0
- package/dist/peers-coord.js +139 -4
- package/dist/peers-coord.js.map +2 -2
- package/dist/run/route.d.ts +3 -4
- package/dist/run/route.js +3 -3
- package/dist/run/route.js.map +1 -1
- package/dist/run/worker.js +1 -0
- package/dist/run/worker.js.map +1 -1
- package/dist/schema.d.ts +272 -0
- package/dist/schema.js +29 -0
- package/dist/schema.js.map +1 -1
- package/dist/sidecar.d.ts +7 -0
- package/dist/sidecar.js +28 -0
- package/dist/sidecar.js.map +1 -0
- package/dist/store.d.ts +41 -1
- package/dist/store.js +133 -1
- package/dist/store.js.map +1 -1
- package/drizzle/0009_intake.sql +20 -0
- package/drizzle/meta/0009_snapshot.json +1775 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +3 -1
- package/skills/aerie-orchestrate/SKILL.md +60 -0
- package/skills/aerie-sidecar/SKILL.md +44 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intake (D19): words → checked tasks. Any split (a session's, a model's) passes the same checks: each task quotes
|
|
3
|
+
* the source, missed sentences are listed, areas exist, close titles are marked. No split maker: one "Split intake"
|
|
4
|
+
* task for a session.
|
|
5
|
+
*/
|
|
6
|
+
import Fuse from "fuse.js";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { AerieError } from "../db.js";
|
|
9
|
+
import { withDeadline } from "../deadline.js";
|
|
10
|
+
import { route } from "../run/route.js";
|
|
11
|
+
export const INBOX = "inbox";
|
|
12
|
+
export const MAYBE_DUP = "maybe-dup";
|
|
13
|
+
export const SplitTask = z.object({
|
|
14
|
+
title: z.string().min(3),
|
|
15
|
+
description: z.string().optional(),
|
|
16
|
+
/** an area path from the list */
|
|
17
|
+
area: z.string().optional(),
|
|
18
|
+
labels: z.array(z.string()).optional(),
|
|
19
|
+
priority: z.enum(["high", "medium", "low"]).optional(),
|
|
20
|
+
/** the source words this task comes from, copied exactly */
|
|
21
|
+
span: z.string().min(1),
|
|
22
|
+
why: z.string(),
|
|
23
|
+
});
|
|
24
|
+
export const Split = z.object({
|
|
25
|
+
tasks: z.array(SplitTask),
|
|
26
|
+
/** choices only the speaker can make; `tasks` = indexes of the tasks each blocks */
|
|
27
|
+
questions: z
|
|
28
|
+
.array(z.object({
|
|
29
|
+
question: z.string(),
|
|
30
|
+
options: z.array(z.object({ key: z.string(), text: z.string() })).optional(),
|
|
31
|
+
tasks: z.array(z.number().int()).optional(),
|
|
32
|
+
}))
|
|
33
|
+
.optional(),
|
|
34
|
+
});
|
|
35
|
+
// ── check ──
|
|
36
|
+
/** whisper clip marks (`[01:00] `) */
|
|
37
|
+
const CLIP_MARK = /^\[\d{1,2}:\d{2}(?::\d{2})?\]\s*/gm;
|
|
38
|
+
export const unmark = (w) => w.replace(CLIP_MARK, "").trim();
|
|
39
|
+
/** case, whitespace, quote marks and dashes the same; edge punctuation off */
|
|
40
|
+
export function normal(w) {
|
|
41
|
+
return unmark(w)
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.replace(/[‘’`´]/g, "'")
|
|
44
|
+
.replace(/[“”„]/g, '"')
|
|
45
|
+
.replace(/[–—]/g, "-")
|
|
46
|
+
.replace(/\s+/g, " ")
|
|
47
|
+
.trim()
|
|
48
|
+
.replace(/^[\s"'.,;:!?-]+|[\s"'.,;:!?-]+$/g, "");
|
|
49
|
+
}
|
|
50
|
+
const sentences = (w) => unmark(w)
|
|
51
|
+
.split(/(?<=[.!?])\s+|\n+/)
|
|
52
|
+
.map((x) => x.trim())
|
|
53
|
+
.filter(Boolean);
|
|
54
|
+
/** covered chars that make a sentence covered (or half of it, if shorter) */
|
|
55
|
+
const COVERS = 20;
|
|
56
|
+
export function check(words, split, o) {
|
|
57
|
+
const src = normal(words);
|
|
58
|
+
const covered = new Uint8Array(src.length);
|
|
59
|
+
const out = { ok: [], failedSpans: [], missed: [] };
|
|
60
|
+
const areas = new Set(o.areas);
|
|
61
|
+
const fuse = new Fuse(o.open, { keys: ["title"], includeScore: true, threshold: 0.3 });
|
|
62
|
+
split.tasks.forEach((task, at) => {
|
|
63
|
+
const span = normal(task.span);
|
|
64
|
+
const i = span ? src.indexOf(span) : -1;
|
|
65
|
+
if (i < 0) {
|
|
66
|
+
out.failedSpans.push({ at, title: task.title, span: task.span });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
covered.fill(1, i, i + span.length);
|
|
70
|
+
const area = task.area && areas.has(task.area) ? task.area : o.hint && areas.has(o.hint) ? o.hint : INBOX;
|
|
71
|
+
const best = fuse.search(task.title, { limit: 1 })[0];
|
|
72
|
+
out.ok.push({
|
|
73
|
+
task,
|
|
74
|
+
at,
|
|
75
|
+
area,
|
|
76
|
+
dup: best && (best.score ?? 1) <= 0.25
|
|
77
|
+
? { id: best.item.id, title: best.item.title, score: best.score ?? 0 }
|
|
78
|
+
: undefined,
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
let from = 0;
|
|
82
|
+
for (const raw of sentences(words)) {
|
|
83
|
+
const n = normal(raw);
|
|
84
|
+
if (n.split(" ").length < 4)
|
|
85
|
+
continue;
|
|
86
|
+
const i = src.indexOf(n, from);
|
|
87
|
+
if (i < 0)
|
|
88
|
+
continue;
|
|
89
|
+
from = i + n.length;
|
|
90
|
+
let hit = 0;
|
|
91
|
+
for (let j = i; j < i + n.length; j++)
|
|
92
|
+
hit += covered[j] ?? 0;
|
|
93
|
+
// a task span inside a long sentence covers it; the rest is context
|
|
94
|
+
if (hit < Math.min(n.length / 2, COVERS))
|
|
95
|
+
out.missed.push(raw);
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
// ── split by a model ──
|
|
100
|
+
export function splitPrompt(words, areas) {
|
|
101
|
+
return [
|
|
102
|
+
"Split what this person said into tasks for a task board.",
|
|
103
|
+
"Rules:",
|
|
104
|
+
"- One task per separate piece of work. Do not merge two jobs; do not split one job.",
|
|
105
|
+
'- title: a short command ("Fix the login redirect"), at most 80 characters.',
|
|
106
|
+
"- span: copy the exact words from the source this task comes from. Copy, never reword.",
|
|
107
|
+
"- area: one path from the list, or leave it out when none fits.",
|
|
108
|
+
"- why: one short line on why this is a task.",
|
|
109
|
+
"- questions: only choices the speaker must make before work can start; tasks = indexes of the tasks each blocks.",
|
|
110
|
+
"- Leave out chatter that asks for no work.",
|
|
111
|
+
"",
|
|
112
|
+
"Areas:",
|
|
113
|
+
...areas.map((a) => `- ${a.path}${a.description ? `: ${a.description}` : ""}`),
|
|
114
|
+
"",
|
|
115
|
+
"Source:",
|
|
116
|
+
unmark(words),
|
|
117
|
+
].join("\n");
|
|
118
|
+
}
|
|
119
|
+
export async function splitWithModel(words, areas, spec, o = {}) {
|
|
120
|
+
const { modelFromSpec } = await import("@wrenautomation/models/spec");
|
|
121
|
+
const m = modelFromSpec(spec, { ...process.env, ...o.env });
|
|
122
|
+
const { value, usage } = await withDeadline(o.timeoutMs ?? 120_000, o.signal, (signal) => m.ask(splitPrompt(words, areas), Split, { signal, purpose: "aerie-intake" }));
|
|
123
|
+
return { split: value, model: m.id, usage };
|
|
124
|
+
}
|
|
125
|
+
/** `read`'s 60 s clips through the local ear (whisper.cpp), else Cohere on its keys. */
|
|
126
|
+
export async function hear(file, o = {}) {
|
|
127
|
+
const { hearSpeech, speechHere } = await import("@wrenautomation/read/video");
|
|
128
|
+
const { mkdtemp, rm } = await import("node:fs/promises");
|
|
129
|
+
const { tmpdir } = await import("node:os");
|
|
130
|
+
const { join } = await import("node:path");
|
|
131
|
+
const cohere = (process.env.COHERE_API_KEY ?? "").split(",").filter(Boolean);
|
|
132
|
+
const ear = speechHere(cohere);
|
|
133
|
+
if (!ear)
|
|
134
|
+
throw new AerieError("no ear: install whisper.cpp and its model, or set COHERE_API_KEY");
|
|
135
|
+
const dir = await mkdtemp(join(tmpdir(), "aerie-hear-"));
|
|
136
|
+
const t0 = performance.now();
|
|
137
|
+
try {
|
|
138
|
+
const text = await hearSpeech(file, dir, o.ffmpeg ?? "ffmpeg", ear, {
|
|
139
|
+
language: o.language ?? "en",
|
|
140
|
+
seconds: 0,
|
|
141
|
+
});
|
|
142
|
+
return { words: unmark(text), model: ear.id, ms: Math.round(performance.now() - t0) };
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
await rm(dir, { recursive: true, force: true });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export async function intake(a, input, by, o = {}) {
|
|
149
|
+
let row = null;
|
|
150
|
+
let words = input.words ?? "";
|
|
151
|
+
let heard;
|
|
152
|
+
if (input.into !== undefined) {
|
|
153
|
+
row = (await a.intakes({ ids: [input.into] }))[0] ?? null;
|
|
154
|
+
if (!row)
|
|
155
|
+
throw new AerieError(`no intake ${input.into}`, 404);
|
|
156
|
+
if (row.taskIds.length && row.splitBy !== "none")
|
|
157
|
+
throw new AerieError(`intake ${row.id} is split (${row.taskIds.join(", ")})`, 409);
|
|
158
|
+
words = row.words;
|
|
159
|
+
}
|
|
160
|
+
else if (input.audio && !words.trim()) {
|
|
161
|
+
heard = await (o.hear ?? hear)(input.audio);
|
|
162
|
+
words = heard.words;
|
|
163
|
+
}
|
|
164
|
+
if (!words.trim())
|
|
165
|
+
throw new AerieError("no words: pass text, --file or --audio");
|
|
166
|
+
if (!row && !input.dryRun)
|
|
167
|
+
row = await a.addIntake({
|
|
168
|
+
kind: input.kind,
|
|
169
|
+
words,
|
|
170
|
+
audio: input.audio,
|
|
171
|
+
heard: heard ? { model: heard.model, ms: heard.ms, usd: heard.usd } : undefined,
|
|
172
|
+
why: input.why,
|
|
173
|
+
}, by);
|
|
174
|
+
const areas = await a.areas();
|
|
175
|
+
const res = {
|
|
176
|
+
intake: row?.id ?? null,
|
|
177
|
+
words,
|
|
178
|
+
splitBy: "none",
|
|
179
|
+
filed: [],
|
|
180
|
+
failedSpans: [],
|
|
181
|
+
missed: [],
|
|
182
|
+
questions: [],
|
|
183
|
+
routed: [],
|
|
184
|
+
};
|
|
185
|
+
let split;
|
|
186
|
+
let raw;
|
|
187
|
+
if (input.split !== undefined) {
|
|
188
|
+
const p = Split.safeParse(input.split);
|
|
189
|
+
if (!p.success)
|
|
190
|
+
throw new AerieError(`split: ${p.error.issues.map((i) => `${i.path.join(".")} ${i.message}`).join("; ")}`);
|
|
191
|
+
split = p.data;
|
|
192
|
+
raw = input.split;
|
|
193
|
+
res.splitBy = "session";
|
|
194
|
+
}
|
|
195
|
+
else if (o.model) {
|
|
196
|
+
try {
|
|
197
|
+
const m = await splitWithModel(words, areas, o.model, { timeoutMs: o.timeoutMs });
|
|
198
|
+
split = m.split;
|
|
199
|
+
raw = { answer: m.split, model: m.model, usage: m.usage };
|
|
200
|
+
res.splitBy = m.model;
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
res.error = `${o.model}: ${e.message}`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (!split) {
|
|
207
|
+
// nothing lost: the words wait for a session as one task
|
|
208
|
+
if (input.dryRun || !row)
|
|
209
|
+
return res;
|
|
210
|
+
const t = await a.create({
|
|
211
|
+
title: `Split intake ${row.id}`,
|
|
212
|
+
description: [
|
|
213
|
+
`Split these words into tasks: \`aerie intake --into ${row.id} --split -\` (JSON on stdin).`,
|
|
214
|
+
res.error
|
|
215
|
+
? `The model failed: ${res.error}`
|
|
216
|
+
: "No split model is set (setting intake_model).",
|
|
217
|
+
"",
|
|
218
|
+
unmark(words),
|
|
219
|
+
].join("\n"),
|
|
220
|
+
area: input.area && areas.some((x) => x.path === input.area) ? input.area : INBOX,
|
|
221
|
+
labels: ["intake"],
|
|
222
|
+
}, by, { why: `intake ${row.id}: no split` });
|
|
223
|
+
if (o.coord && o.lane)
|
|
224
|
+
await o.coord.queueAdd([t.id], { lane: o.lane });
|
|
225
|
+
await a.setIntake(row.id, {
|
|
226
|
+
splitBy: "none",
|
|
227
|
+
checks: res.error ? { error: res.error } : {},
|
|
228
|
+
taskIds: [t.id],
|
|
229
|
+
});
|
|
230
|
+
res.waiting = t.id;
|
|
231
|
+
return res;
|
|
232
|
+
}
|
|
233
|
+
const open = (await a.list({})).filter((t) => t.status !== "Done");
|
|
234
|
+
const c = check(words, split, { areas: areas.map((x) => x.path), hint: input.area, open });
|
|
235
|
+
res.failedSpans = c.failedSpans;
|
|
236
|
+
res.missed = c.missed;
|
|
237
|
+
const byAt = new Map();
|
|
238
|
+
for (const k of c.ok) {
|
|
239
|
+
const entry = {
|
|
240
|
+
id: null,
|
|
241
|
+
title: k.task.title,
|
|
242
|
+
area: k.area,
|
|
243
|
+
dup: k.dup?.id,
|
|
244
|
+
span: k.task.span,
|
|
245
|
+
};
|
|
246
|
+
if (!input.dryRun && row) {
|
|
247
|
+
const t = await a.create({
|
|
248
|
+
title: k.task.title,
|
|
249
|
+
description: [
|
|
250
|
+
...(k.task.description ? [k.task.description, ""] : []),
|
|
251
|
+
`Source (intake ${row.id}): "${k.task.span}"`,
|
|
252
|
+
...(k.dup ? [`Maybe the same as ${k.dup.id} (${k.dup.title}).`] : []),
|
|
253
|
+
].join("\n"),
|
|
254
|
+
area: k.area,
|
|
255
|
+
labels: [...(k.task.labels ?? []), ...(k.dup ? [MAYBE_DUP] : [])],
|
|
256
|
+
...(k.task.priority ? { priority: k.task.priority } : {}),
|
|
257
|
+
}, by, { why: k.task.why });
|
|
258
|
+
await a.log(t.id, by, "filed", { intake: row.id, span: k.task.span, dup: k.dup ?? null }, k.task.why);
|
|
259
|
+
entry.id = t.id;
|
|
260
|
+
byAt.set(k.at, t.id);
|
|
261
|
+
}
|
|
262
|
+
res.filed.push(entry);
|
|
263
|
+
}
|
|
264
|
+
if (!input.dryRun && row) {
|
|
265
|
+
for (const q of split.questions ?? []) {
|
|
266
|
+
const blocks = (q.tasks ?? []).map((i) => byAt.get(i)).filter((x) => !!x);
|
|
267
|
+
const d = await a.ask({ question: q.question, options: q.options ?? [], blocks }, by);
|
|
268
|
+
res.questions.push(d.id);
|
|
269
|
+
}
|
|
270
|
+
const ids = res.filed.map((f) => f.id).filter((x) => !!x);
|
|
271
|
+
// the "Split intake" task this answers is done
|
|
272
|
+
const waiting = input.into !== undefined ? row.taskIds : [];
|
|
273
|
+
for (const w of waiting) {
|
|
274
|
+
const t = await a.get(w);
|
|
275
|
+
if (t && t.status !== "Done")
|
|
276
|
+
await a.edit(w, { status: "Done", finalSummary: `Split into ${ids.join(", ") || "no tasks"}` }, by, {
|
|
277
|
+
why: `intake ${row.id} split`,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
await a.setIntake(row.id, {
|
|
281
|
+
splitBy: res.splitBy,
|
|
282
|
+
split: raw,
|
|
283
|
+
checks: {
|
|
284
|
+
failedSpans: c.failedSpans,
|
|
285
|
+
missed: c.missed,
|
|
286
|
+
dups: c.ok.filter((k) => k.dup).map((k) => k.dup),
|
|
287
|
+
},
|
|
288
|
+
taskIds: ids,
|
|
289
|
+
});
|
|
290
|
+
if (input.route)
|
|
291
|
+
for (const id of ids) {
|
|
292
|
+
// a route failure keeps the task filed in To Do; the answer says why
|
|
293
|
+
if (!o.coord)
|
|
294
|
+
res.routed.push({
|
|
295
|
+
id,
|
|
296
|
+
runner: null,
|
|
297
|
+
lane: null,
|
|
298
|
+
error: "no board: route needs Postgres",
|
|
299
|
+
});
|
|
300
|
+
else
|
|
301
|
+
try {
|
|
302
|
+
const r = await route(a, o.coord, id, by, o.pick);
|
|
303
|
+
res.routed.push({ id, runner: r.runner, lane: r.lane });
|
|
304
|
+
}
|
|
305
|
+
catch (e) {
|
|
306
|
+
res.routed.push({ id, runner: null, lane: null, error: e.message });
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return res;
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/intake/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAe,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGrD,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC;AAC7B,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AAErC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,iCAAiC;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE;IACtD,4DAA4D;IAC5D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;CAChB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;IACzB,oFAAoF;IACpF,SAAS,EAAE,CAAC;SACT,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;QACP,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;QAC5E,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE;KAC5C,CAAC,CACH;SACA,QAAQ,EAAE;CACd,CAAC,CAAC;AAGH,cAAc;AACd,sCAAsC;AACtC,MAAM,SAAS,GAAG,oCAAoC,CAAC;AACvD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAErE,8EAA8E;AAC9E,MAAM,UAAU,MAAM,CAAC,CAAS;IAC9B,OAAO,MAAM,CAAC,CAAC,CAAC;SACb,WAAW,EAAE;SACb,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE;SACN,OAAO,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,CAAS,EAAE,EAAE,CAC9B,MAAM,CAAC,CAAC,CAAC;KACN,KAAK,CAAC,mBAAmB,CAAC;KAC1B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;KACpB,MAAM,CAAC,OAAO,CAAC,CAAC;AAiBrB,6EAA6E;AAC7E,MAAM,MAAM,GAAG,EAAE,CAAC;AAElB,MAAM,UAAU,KAAK,CACnB,KAAa,EACb,KAAY,EACZ,CAAqE;IAErE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAW,EAAE,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IACvF,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACjE,OAAO;QACT,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/F,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC;YACV,IAAI;YACJ,EAAE;YACF,IAAI;YACJ,GAAG,EACD,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI;gBAC/B,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE;gBACtE,CAAC,CAAC,SAAS;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QACtC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS;QACpB,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;QACpB,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9D,oEAAoE;QACpE,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,CAAC;YAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,KAAqD;IAC9F,OAAO;QACL,0DAA0D;QAC1D,QAAQ;QACR,qFAAqF;QACrF,6EAA6E;QAC7E,wFAAwF;QACxF,iEAAiE;QACjE,8CAA8C;QAC9C,kHAAkH;QAClH,4CAA4C;QAC5C,EAAE;QACF,QAAQ;QACR,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC9E,EAAE;QACF,SAAS;QACT,MAAM,CAAC,KAAK,CAAC;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,KAAqD,EACrD,IAAY,EACZ,IAII,EAAE;IAEN,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;IACtE,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,CAAC,CAAC,CAAC,SAAS,IAAI,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CACvF,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAC7E,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;AAC9C,CAAC;AAUD,wFAAwF;AACxF,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,IAAY,EACZ,IAA4C,EAAE;IAE9C,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAC9E,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACzD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG;QACN,MAAM,IAAI,UAAU,CAAC,kEAAkE,CAAC,CAAC;IAC3F,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;IACzD,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,IAAI,QAAQ,EAAE,GAAG,EAAE;YAClE,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI;YAC5B,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACxF,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAiDD,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,CAAa,EACb,KAAkB,EAClB,EAAU,EACV,IAAmB,EAAE;IAErB,IAAI,GAAG,GAAkB,IAAI,CAAC;IAC9B,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;IAC9B,IAAI,KAAwB,CAAC;IAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC1D,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,UAAU,CAAC,aAAa,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/D,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,MAAM;YAC9C,MAAM,IAAI,UAAU,CAAC,UAAU,GAAG,CAAC,EAAE,cAAc,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACrF,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IACpB,CAAC;SAAM,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QACxC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5C,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACtB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;IAClF,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM;QACvB,GAAG,GAAG,MAAM,CAAC,CAAC,SAAS,CACrB;YACE,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK;YACL,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS;YAC/E,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,EACD,EAAE,CACH,CAAC;IACJ,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAiB;QACxB,MAAM,EAAE,GAAG,EAAE,EAAE,IAAI,IAAI;QACvB,KAAK;QACL,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,EAAE;QACT,WAAW,EAAE,EAAE;QACf,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,EAAE;QACb,MAAM,EAAE,EAAE;KACX,CAAC;IAEF,IAAI,KAAwB,CAAC;IAC7B,IAAI,GAAY,CAAC;IACjB,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC,CAAC,OAAO;YACZ,MAAM,IAAI,UAAU,CAClB,UAAU,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACrF,CAAC;QACJ,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QACf,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;QAClB,GAAG,CAAC,OAAO,GAAG,SAAS,CAAC;IAC1B,CAAC;SAAM,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAClF,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;YAChB,GAAG,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;YAC1D,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC;QACxB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,KAAK,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,yDAAyD;QACzD,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG;YAAE,OAAO,GAAG,CAAC;QACrC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CACtB;YACE,KAAK,EAAE,gBAAgB,GAAG,CAAC,EAAE,EAAE;YAC/B,WAAW,EAAE;gBACX,uDAAuD,GAAG,CAAC,EAAE,+BAA+B;gBAC5F,GAAG,CAAC,KAAK;oBACP,CAAC,CAAC,qBAAqB,GAAG,CAAC,KAAK,EAAE;oBAClC,CAAC,CAAC,+CAA+C;gBACnD,EAAE;gBACF,MAAM,CAAC,KAAK,CAAC;aACd,CAAC,IAAI,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;YACjF,MAAM,EAAE,CAAC,QAAQ,CAAC;SACnB,EACD,EAAE,EACF,EAAE,GAAG,EAAE,UAAU,GAAG,CAAC,EAAE,YAAY,EAAE,CACtC,CAAC;QACF,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI;YAAE,MAAM,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxE,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE;YACxB,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;YAC7C,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChB,CAAC,CAAC;QACH,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;QACnB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3F,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC;IAChC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACtB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG;YACZ,EAAE,EAAE,IAAqB;YACzB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;YACnB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE;YACd,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;SAClB,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CACtB;gBACE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;gBACnB,WAAW,EAAE;oBACX,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvD,kBAAkB,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG;oBAC7C,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBACtE,CAAC,IAAI,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1D,EACD,EAAE,EACF,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CACpB,CAAC;YACF,MAAM,CAAC,CAAC,GAAG,CACT,CAAC,CAAC,EAAE,EACJ,EAAE,EACF,OAAO,EACP,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,EACzD,CAAC,CAAC,IAAI,CAAC,GAAG,CACX,CAAC;YACF,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;YAChB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACvB,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvF,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;YACtF,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;QACD,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,+CAA+C;QAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;gBAC1B,MAAM,CAAC,CAAC,IAAI,CACV,CAAC,EACD,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,EAAE,EAC9E,EAAE,EACF;oBACE,GAAG,EAAE,UAAU,GAAG,CAAC,EAAE,QAAQ;iBAC9B,CACF,CAAC;QACN,CAAC;QACD,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE;YACxB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,KAAK,EAAE,GAAG;YACV,MAAM,EAAE;gBACN,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;aAClD;YACD,OAAO,EAAE,GAAG;SACb,CAAC,CAAC;QACH,IAAI,KAAK,CAAC,KAAK;YACb,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;gBACrB,qEAAqE;gBACrE,IAAI,CAAC,CAAC,CAAC,KAAK;oBACV,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;wBACd,EAAE;wBACF,MAAM,EAAE,IAAI;wBACZ,IAAI,EAAE,IAAI;wBACV,KAAK,EAAE,gCAAgC;qBACxC,CAAC,CAAC;;oBAEH,IAAI,CAAC;wBACH,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;wBAClD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC1D,CAAC;oBAAC,OAAO,CAAC,EAAE,CAAC;wBACX,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;oBACjF,CAAC;YACL,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/peers-coord.js
CHANGED
|
@@ -8378,7 +8378,7 @@ function oneOf(name, col, values) {
|
|
|
8378
8378
|
const list = values.map((v) => `'${v.replaceAll("'", "''")}'`).join(", ");
|
|
8379
8379
|
return check(name, sql.raw(`"${col.name}" IN (${list})`));
|
|
8380
8380
|
}
|
|
8381
|
-
var aerie, ACTOR_KINDS, AREA_ROLES, TASK_ROLES, LAYOUTS, PLACES, at, area, actor, areaRole, task, taskArea, taskActor, taskHolder, view, tsvector, taskEvent, milestone, mirrorFile, setting, coordGen, coordLease, coordClosing, coordTask, coordQueue, decision, routeRule;
|
|
8381
|
+
var aerie, ACTOR_KINDS, AREA_ROLES, TASK_ROLES, LAYOUTS, PLACES, at, area, actor, areaRole, task, taskArea, taskActor, taskHolder, view, tsvector, taskEvent, milestone, mirrorFile, setting, coordGen, coordLease, coordClosing, coordTask, coordQueue, decision, routeRule, intake;
|
|
8382
8382
|
var init_schema2 = __esm({
|
|
8383
8383
|
"src/schema.ts"() {
|
|
8384
8384
|
"use strict";
|
|
@@ -8708,7 +8708,11 @@ var init_schema2 = __esm({
|
|
|
8708
8708
|
answer: text(),
|
|
8709
8709
|
answeredBy: text("answered_by"),
|
|
8710
8710
|
answeredAt: at("answered_at"),
|
|
8711
|
-
why: text()
|
|
8711
|
+
why: text(),
|
|
8712
|
+
/** `ask`; `run-failed` = the worker's own (its keys william, session act only on it) */
|
|
8713
|
+
kind: text().notNull().default("ask"),
|
|
8714
|
+
/** [{ at, by, brief, recommendation, why }]: each brief a rewrite replaced */
|
|
8715
|
+
history: jsonb().notNull().default([])
|
|
8712
8716
|
},
|
|
8713
8717
|
(t) => [
|
|
8714
8718
|
primaryKey({ columns: [t.id], name: "pk_decision" }),
|
|
@@ -8750,6 +8754,34 @@ var init_schema2 = __esm({
|
|
|
8750
8754
|
check("route_rule_lane_check", sql`runner <> 'session' or lane is not null`)
|
|
8751
8755
|
]
|
|
8752
8756
|
);
|
|
8757
|
+
intake = aerie.table(
|
|
8758
|
+
"intake",
|
|
8759
|
+
{
|
|
8760
|
+
id: serial().notNull(),
|
|
8761
|
+
kind: text().notNull(),
|
|
8762
|
+
by: text().notNull(),
|
|
8763
|
+
at: at("at").notNull().defaultNow(),
|
|
8764
|
+
/** the words: typed, or what the ear heard */
|
|
8765
|
+
words: text().notNull(),
|
|
8766
|
+
/** voice: the file as given */
|
|
8767
|
+
audio: text(),
|
|
8768
|
+
/** voice: { model, ms, usd } */
|
|
8769
|
+
heard: jsonb(),
|
|
8770
|
+
/** `session` (--split), a models spec, or `none` */
|
|
8771
|
+
splitBy: text("split_by"),
|
|
8772
|
+
/** the split as made, whole: the model's answer or the session's JSON */
|
|
8773
|
+
split: jsonb(),
|
|
8774
|
+
/** { failedSpans, missed, dups } */
|
|
8775
|
+
checks: jsonb(),
|
|
8776
|
+
taskIds: text("task_ids").array().notNull().default(sql`'{}'::text[]`),
|
|
8777
|
+
why: text()
|
|
8778
|
+
},
|
|
8779
|
+
(t) => [
|
|
8780
|
+
primaryKey({ columns: [t.id], name: "pk_intake" }),
|
|
8781
|
+
index("intake_at_idx").on(t.at),
|
|
8782
|
+
oneOf("intake_kind_check", t.kind, ["text", "chat", "voice"])
|
|
8783
|
+
]
|
|
8784
|
+
);
|
|
8753
8785
|
}
|
|
8754
8786
|
});
|
|
8755
8787
|
|
|
@@ -9357,7 +9389,9 @@ function aerieStore(o) {
|
|
|
9357
9389
|
answer: r.answer ?? void 0,
|
|
9358
9390
|
answeredBy: r.answeredBy ?? void 0,
|
|
9359
9391
|
answeredAt: toIso(r.answeredAt),
|
|
9360
|
-
why: r.why ?? void 0
|
|
9392
|
+
why: r.why ?? void 0,
|
|
9393
|
+
kind: r.kind,
|
|
9394
|
+
history: r.history
|
|
9361
9395
|
}));
|
|
9362
9396
|
}
|
|
9363
9397
|
async function ask(d, by) {
|
|
@@ -9375,7 +9409,8 @@ function aerieStore(o) {
|
|
|
9375
9409
|
areaId: d.area ? await ensureArea(tx, d.area) : null,
|
|
9376
9410
|
askedBy: by,
|
|
9377
9411
|
askedAt: now(),
|
|
9378
|
-
due: d.due ?? null
|
|
9412
|
+
due: d.due ?? null,
|
|
9413
|
+
kind: d.kind ?? "ask"
|
|
9379
9414
|
}).returning({ id: decision.id });
|
|
9380
9415
|
return r?.id;
|
|
9381
9416
|
});
|
|
@@ -9404,6 +9439,101 @@ function aerieStore(o) {
|
|
|
9404
9439
|
}
|
|
9405
9440
|
return (await decisions({ ids: [id] }))[0];
|
|
9406
9441
|
}
|
|
9442
|
+
async function briefDecision(id, p, by) {
|
|
9443
|
+
const [d] = await decisions({ ids: [id] });
|
|
9444
|
+
if (!d) throw new AerieError(`no decision ${id}`, 404);
|
|
9445
|
+
if (d.answeredAt) throw new AerieError(`decision ${id} is answered (${d.answer})`, 409);
|
|
9446
|
+
if (p.recommendation && !d.options.some((x) => x.key === p.recommendation))
|
|
9447
|
+
throw new AerieError(`recommendation ${p.recommendation} is not an option`);
|
|
9448
|
+
const was = {
|
|
9449
|
+
at: now(),
|
|
9450
|
+
by,
|
|
9451
|
+
brief: d.brief,
|
|
9452
|
+
recommendation: d.recommendation,
|
|
9453
|
+
why: p.why
|
|
9454
|
+
};
|
|
9455
|
+
await write(by, async (tx) => {
|
|
9456
|
+
await tx.update(decision).set({
|
|
9457
|
+
...p.brief !== void 0 ? { brief: p.brief } : {},
|
|
9458
|
+
...p.recommendation !== void 0 ? { recommendation: p.recommendation } : {},
|
|
9459
|
+
history: [...d.history, was]
|
|
9460
|
+
}).where(and(eq(decision.id, id), isNull(decision.answeredAt)));
|
|
9461
|
+
});
|
|
9462
|
+
return (await decisions({ ids: [id] }))[0];
|
|
9463
|
+
}
|
|
9464
|
+
async function mergeDecisions(keep, drop, by, why) {
|
|
9465
|
+
const all = await decisions({ ids: [keep, ...drop] });
|
|
9466
|
+
const k = all.find((x) => x.id === keep);
|
|
9467
|
+
if (!k) throw new AerieError(`no decision ${keep}`, 404);
|
|
9468
|
+
const keys = (d) => d.options.map((o2) => o2.key).sort().join(",");
|
|
9469
|
+
for (const id of drop) {
|
|
9470
|
+
const d = all.find((x) => x.id === id);
|
|
9471
|
+
if (!d) throw new AerieError(`no decision ${id}`, 404);
|
|
9472
|
+
if (id === keep) throw new AerieError(`decision ${id} cannot merge into itself`);
|
|
9473
|
+
if (d.answeredAt || k.answeredAt)
|
|
9474
|
+
throw new AerieError(`decision ${d.answeredAt ? id : keep} is answered`, 409);
|
|
9475
|
+
if (d.kind !== k.kind || keys(d) !== keys(k))
|
|
9476
|
+
throw new AerieError(
|
|
9477
|
+
`decision ${id} differs from ${keep} (kind ${d.kind}/${k.kind}, options ${keys(d)}/${keys(k)})`
|
|
9478
|
+
);
|
|
9479
|
+
}
|
|
9480
|
+
const blocks = [
|
|
9481
|
+
.../* @__PURE__ */ new Set([
|
|
9482
|
+
...k.blocks,
|
|
9483
|
+
...drop.flatMap((id) => all.find((x) => x.id === id)?.blocks ?? [])
|
|
9484
|
+
])
|
|
9485
|
+
];
|
|
9486
|
+
await write(by, async (tx) => {
|
|
9487
|
+
await tx.update(decision).set({ blocks }).where(eq(decision.id, keep));
|
|
9488
|
+
await tx.update(decision).set({
|
|
9489
|
+
answer: "merged",
|
|
9490
|
+
answeredBy: by,
|
|
9491
|
+
answeredAt: now(),
|
|
9492
|
+
why: `merged into ${keep}${why ? `: ${why}` : ""}`
|
|
9493
|
+
}).where(and(inArray(decision.id, drop), isNull(decision.answeredAt)));
|
|
9494
|
+
});
|
|
9495
|
+
return (await decisions({ ids: [keep] }))[0];
|
|
9496
|
+
}
|
|
9497
|
+
const intakeOf = (r) => ({
|
|
9498
|
+
id: r.id,
|
|
9499
|
+
kind: r.kind,
|
|
9500
|
+
by: r.by,
|
|
9501
|
+
at: toIso(r.at),
|
|
9502
|
+
words: r.words,
|
|
9503
|
+
audio: r.audio ?? void 0,
|
|
9504
|
+
heard: r.heard ?? void 0,
|
|
9505
|
+
splitBy: r.splitBy ?? void 0,
|
|
9506
|
+
split: r.split ?? void 0,
|
|
9507
|
+
checks: r.checks ?? void 0,
|
|
9508
|
+
taskIds: r.taskIds,
|
|
9509
|
+
why: r.why ?? void 0
|
|
9510
|
+
});
|
|
9511
|
+
async function addIntake(i, by) {
|
|
9512
|
+
const [r] = await db.insert(intake).values({
|
|
9513
|
+
kind: i.kind,
|
|
9514
|
+
by,
|
|
9515
|
+
at: now(),
|
|
9516
|
+
words: i.words,
|
|
9517
|
+
audio: i.audio ?? null,
|
|
9518
|
+
heard: i.heard ?? null,
|
|
9519
|
+
why: i.why ?? null
|
|
9520
|
+
}).returning();
|
|
9521
|
+
return intakeOf(r);
|
|
9522
|
+
}
|
|
9523
|
+
async function setIntake(id, p) {
|
|
9524
|
+
const [r] = await db.update(intake).set({
|
|
9525
|
+
...p.splitBy !== void 0 ? { splitBy: p.splitBy } : {},
|
|
9526
|
+
...p.split !== void 0 ? { split: p.split } : {},
|
|
9527
|
+
...p.checks !== void 0 ? { checks: p.checks } : {},
|
|
9528
|
+
...p.taskIds !== void 0 ? { taskIds: p.taskIds } : {}
|
|
9529
|
+
}).where(eq(intake.id, id)).returning();
|
|
9530
|
+
if (!r) throw new AerieError(`no intake ${id}`, 404);
|
|
9531
|
+
return intakeOf(r);
|
|
9532
|
+
}
|
|
9533
|
+
async function intakes(o2 = {}) {
|
|
9534
|
+
const rows2 = await db.select().from(intake).where(o2.ids ? inArray(intake.id, o2.ids) : void 0).orderBy(desc(intake.id)).limit(o2.limit ?? 50);
|
|
9535
|
+
return rows2.map(intakeOf);
|
|
9536
|
+
}
|
|
9407
9537
|
async function put(tx, t, areaId, place) {
|
|
9408
9538
|
const values = {
|
|
9409
9539
|
id: t.id,
|
|
@@ -9771,6 +9901,11 @@ function aerieStore(o) {
|
|
|
9771
9901
|
).orderBy(sql`ts_rank(${taskEvent.words}, ${q}) desc`, sql`${taskEvent.seq} desc`).limit(o2.limit ?? 50);
|
|
9772
9902
|
}
|
|
9773
9903
|
return {
|
|
9904
|
+
briefDecision,
|
|
9905
|
+
mergeDecisions,
|
|
9906
|
+
addIntake,
|
|
9907
|
+
setIntake,
|
|
9908
|
+
intakes,
|
|
9774
9909
|
get,
|
|
9775
9910
|
list,
|
|
9776
9911
|
routeRules,
|