@ny4n/durable 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -0
- package/README.md +41 -5
- package/dist/codemode/codemode.d.ts +132 -0
- package/dist/codemode/codemode.d.ts.map +1 -0
- package/dist/codemode/codemode.js +791 -0
- package/dist/codemode/codemode.js.map +1 -0
- package/dist/codemode/describe.d.ts +38 -0
- package/dist/codemode/describe.d.ts.map +1 -0
- package/dist/codemode/describe.js +117 -0
- package/dist/codemode/describe.js.map +1 -0
- package/dist/codemode/index.d.ts +3 -0
- package/dist/codemode/index.d.ts.map +1 -0
- package/dist/codemode/index.js +3 -0
- package/dist/codemode/index.js.map +1 -0
- package/dist/codemode/output.d.ts +39 -0
- package/dist/codemode/output.d.ts.map +1 -0
- package/dist/codemode/output.js +160 -0
- package/dist/codemode/output.js.map +1 -0
- package/dist/harness/agent.d.ts +4 -2
- package/dist/harness/agent.d.ts.map +1 -1
- package/dist/harness/agent.js +56 -26
- package/dist/harness/agent.js.map +1 -1
- package/dist/harness/compaction.d.ts +6 -1
- package/dist/harness/compaction.d.ts.map +1 -1
- package/dist/harness/compaction.js +10 -7
- package/dist/harness/compaction.js.map +1 -1
- package/dist/harness/events.d.ts +8 -2
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +4 -1
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/generation.d.ts +2 -0
- package/dist/harness/generation.d.ts.map +1 -1
- package/dist/harness/generation.js +25 -4
- package/dist/harness/generation.js.map +1 -1
- package/dist/harness/inbox.d.ts +16 -4
- package/dist/harness/inbox.d.ts.map +1 -1
- package/dist/harness/inbox.js +26 -3
- package/dist/harness/inbox.js.map +1 -1
- package/dist/harness/live.d.ts +15 -1
- package/dist/harness/live.d.ts.map +1 -1
- package/dist/harness/live.js +10 -2
- package/dist/harness/live.js.map +1 -1
- package/dist/harness/scheduler.d.ts.map +1 -1
- package/dist/harness/scheduler.js +72 -10
- package/dist/harness/scheduler.js.map +1 -1
- package/dist/harness/submissions.d.ts +7 -4
- package/dist/harness/submissions.d.ts.map +1 -1
- package/dist/harness/submissions.js +29 -10
- package/dist/harness/submissions.js.map +1 -1
- package/dist/harness/tool.d.ts.map +1 -1
- package/dist/harness/tool.js +13 -1
- package/dist/harness/tool.js.map +1 -1
- package/dist/harness/types.d.ts +38 -11
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tool-search/index.d.ts +2 -0
- package/dist/tool-search/index.d.ts.map +1 -0
- package/dist/tool-search/index.js +2 -0
- package/dist/tool-search/index.js.map +1 -0
- package/dist/tool-search/tool-search.d.ts +18 -0
- package/dist/tool-search/tool-search.d.ts.map +1 -0
- package/dist/tool-search/tool-search.js +62 -0
- package/dist/tool-search/tool-search.js.map +1 -0
- package/package.json +16 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/codemode/output.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A script's result as the model reads it, copied from the coding agent's code mode: a \"Script completed/failed\"\n * header with the wall time, the script's text items (`==> text N/M <==` when there are several), its `console` lines\n * in one `<console_output>` block, the returned value, and on failure the error with the calls already made. Text past\n * the token budget is cut to its start and end, with the complete text in a temp file; images are saved to temp files\n * too, with their path next to them, because a script has no other way to hand their bytes on.\n */\nimport type { ImageContent, TextContent } from \"@ny4n/ai/contracts\";\nimport type { CodemodeOutputItem, CodemodeResult } from \"@ny4n/codemode/portable\";\n\ntype Item = TextContent | ImageContent;\n\n/** Writes a file of the result under a fixed name; its path, or why it could not be written. */\nexport type OutputFile = (name: string, data: string | Uint8Array) => Promise<{ path: string } | { error: string }>;\n\n/** The tool's output limits, which the Harness enforces by cutting without a spill file: results stay inside them. */\ntype Limits = { readonly maxBytes: number; readonly maxLines: number };\n/** Lines of the result besides the script's text: the header, markers, notes. */\nconst LINE_MARGIN = 100;\n\n/** Default token budget for script output. */\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 10_000;\n/** Characters per token when estimating. */\nconst CHARS_PER_TOKEN = 4;\n\n/** File extensions of the image types `image()` accepts. */\nconst IMAGE_EXTENSIONS: Record<string, string> = {\n\t\"image/png\": \".png\",\n\t\"image/jpeg\": \".jpg\",\n\t\"image/gif\": \".gif\",\n\t\"image/webp\": \".webp\",\n};\n\n/** Like the script's `text()`: strings as is, other values as compact JSON. */\nfunction valueText(value: unknown): string {\n\tif (typeof value === \"string\") return value;\n\treturn JSON.stringify(value) ?? String(value);\n}\n\n/**\n * Lay out the script's output so the model can tell items apart: with more than one text item, each starts with a\n * `==> text N/M <==` line; `console` lines follow all other output in one `<console_output>` block.\n */\nfunction formatItems(output: readonly CodemodeOutputItem[]): Item[] {\n\tconst total = output.filter((item) => item.type === \"text\" && !item.console).length;\n\tconst items: Item[] = [];\n\tconst consoleLines: string[] = [];\n\tlet index = 0;\n\tfor (const item of output) {\n\t\tif (item.type === \"image\") items.push(item);\n\t\telse if (item.console) consoleLines.push(item.text);\n\t\telse {\n\t\t\tindex++;\n\t\t\titems.push({ type: \"text\", text: total > 1 ? `==> text ${index}/${total} <==\\n${item.text}` : item.text });\n\t\t}\n\t}\n\tif (consoleLines.length > 0) {\n\t\titems.push({ type: \"text\", text: `<console_output>\\n${consoleLines.join(\"\\n\")}\\n</console_output>` });\n\t}\n\treturn items;\n}\n\n/**\n * Join adjacent text items into one, each part starting on its own line. The separator check looks at the last\n * non-empty part, not the joined text: reading the end of a growing concatenation makes V8 copy it on every item, which\n * is quadratic.\n */\nfunction joinAdjacentText(items: readonly Item[]): Item[] {\n\tconst joined: Item[] = [];\n\tlet parts: string[] = [];\n\tlet lastPart = \"\";\n\tconst flush = () => {\n\t\tif (parts.length > 0) joined.push({ type: \"text\", text: parts.join(\"\") });\n\t\tparts = [];\n\t\tlastPart = \"\";\n\t};\n\tfor (const item of items) {\n\t\tif (item.type !== \"text\") {\n\t\t\tflush();\n\t\t\tjoined.push(item);\n\t\t\tcontinue;\n\t\t}\n\t\tif (lastPart !== \"\" && !lastPart.endsWith(\"\\n\")) {\n\t\t\tparts.push(\"\\n\");\n\t\t\tlastPart = \"\\n\";\n\t\t}\n\t\tparts.push(item.text);\n\t\tif (item.text !== \"\") lastPart = item.text;\n\t}\n\tflush();\n\treturn joined;\n}\n\n/**\n * Apply the token budget: when the combined text exceeds it, the text items become one item that keeps the start and\n * end of the text, and images follow it. The complete text is written to a temp file.\n */\nasync function truncate(\n\titems: readonly Item[],\n\tmaxTokens: number,\n\tlimits: Limits,\n\twrite: OutputFile,\n): Promise<{ items: Item[]; fullOutputPath?: string }> {\n\tconst texts = items.filter((item): item is TextContent => item.type === \"text\").map((item) => item.text);\n\tconst combined = texts.join(\"\\n\");\n\t// Within the limits too: a UTF-16 unit is at most 3 UTF-8 bytes, and the rest of the result is a few short lines.\n\tconst budget = Math.min(maxTokens * CHARS_PER_TOKEN, Math.floor(limits.maxBytes / 4));\n\tconst lineBudget = Math.floor((limits.maxLines - LINE_MARGIN) / 2);\n\tconst lines = combined.split(\"\\n\").length;\n\tif (texts.length === 0 || (combined.length <= budget && lines <= 2 * lineBudget)) return { items: [...items] };\n\tconst headChars = Math.floor(budget / 2);\n\tconst tailChars = budget - headChars;\n\tconst head = combined.slice(0, headChars).split(\"\\n\").slice(0, lineBudget).join(\"\\n\");\n\tconst tail = tailChars > 0 ? combined.slice(-tailChars).split(\"\\n\").slice(-lineBudget).join(\"\\n\") : \"\";\n\tconst removed = combined.length - head.length - tail.length;\n\tlet text = `Warning: truncated output (original token count: ${Math.ceil(combined.length / CHARS_PER_TOKEN)})\\nTotal output lines: ${combined.split(\"\\n\").length}\\n\\n${head}…${Math.ceil(removed / CHARS_PER_TOKEN)} tokens truncated…${tail}`;\n\tconst spilled = await write(\"output.txt\", combined);\n\ttext +=\n\t\t\"path\" in spilled\n\t\t\t? `\\n\\n[Full output: ${spilled.path} (read with offset/limit)]`\n\t\t\t: `\\n\\n[Could not save the full output: ${spilled.error}]`;\n\treturn {\n\t\titems: [{ type: \"text\", text }, ...items.filter((item) => item.type === \"image\")],\n\t\t...(\"path\" in spilled ? { fullOutputPath: spilled.path } : {}),\n\t};\n}\n\n/** Save each image to a file and put a text item with its path before it; an image shown twice is saved once. */\nasync function saveImages(items: readonly Item[], write: OutputFile): Promise<Item[]> {\n\tconst labels = new Map<string, Promise<string>>();\n\tconst label = async ({ data, mimeType }: ImageContent, index: number): Promise<string> => {\n\t\tconst bytes = Uint8Array.from(atob(data), (char) => char.charCodeAt(0));\n\t\tconst kind = `${mimeType}, ${bytes.length} bytes`;\n\t\t// A failed write must not discard the result of a script whose calls already ran: it becomes part of the label.\n\t\tconst saved = await write(`image-${index}${IMAGE_EXTENSIONS[mimeType] ?? \".bin\"}`, bytes);\n\t\treturn \"path\" in saved\n\t\t\t? `[Image saved to ${saved.path} (${kind})]`\n\t\t\t: `[Image (${kind}) could not be saved: ${saved.error}]`;\n\t};\n\tconst result = await Promise.all(\n\t\titems.map(async (item): Promise<Item[]> => {\n\t\t\tif (item.type !== \"image\") return [item];\n\t\t\tlet pending = labels.get(item.data);\n\t\t\tif (pending === undefined) {\n\t\t\t\tpending = label(item, labels.size + 1);\n\t\t\t\tlabels.set(item.data, pending);\n\t\t\t}\n\t\t\treturn [{ type: \"text\", text: await pending }, item];\n\t\t}),\n\t);\n\treturn result.flat();\n}\n\nfunction formatError(\n\tresult: Extract<CodemodeResult, { ok: false }>,\n\tcalls: readonly { name: string; status: string }[],\n) {\n\tconst { error } = result;\n\tconst head =\n\t\terror.kind === \"script\"\n\t\t\t? (error.stack ?? `${error.name ?? \"Error\"}: ${error.message}`)\n\t\t\t: error.kind === \"timeout\"\n\t\t\t\t? `Script timed out: ${error.message}`\n\t\t\t\t: error.kind === \"aborted\"\n\t\t\t\t\t? `Script aborted: ${error.message}`\n\t\t\t\t\t: `Script sandbox failed: ${error.message}`;\n\tconst summary =\n\t\tcalls.length === 0\n\t\t\t? \"No tool calls were made.\"\n\t\t\t: `Tool calls made before the failure (they are not undone): ${calls.map((call) => `${call.name} (${call.status})`).join(\", \")}`;\n\treturn `${head}\\n\\n${summary}`;\n}\n\n/** The tool result's content for a script's result, and the path of the complete text when it was cut. */\nexport async function formatResult(\n\tresult: CodemodeResult,\n\toptions: {\n\t\treadonly wallMs: number;\n\t\treadonly maxOutputTokens: number;\n\t\treadonly calls: readonly { name: string; status: string }[];\n\t\treadonly limits: Limits;\n\t\treadonly write: OutputFile;\n\t},\n): Promise<{ content: Item[]; fullOutputPath?: string }> {\n\tconst output = [...result.output];\n\tif (result.ok && result.value !== undefined) output.push({ type: \"text\", text: valueText(result.value) });\n\tconst items = formatItems(output);\n\tif (!result.ok) items.push({ type: \"text\", text: `Script error:\\n${formatError(result, options.calls)}` });\n\tconst truncated = await truncate(joinAdjacentText(items), options.maxOutputTokens, options.limits, options.write);\n\t// After truncation, which joins the text items and moves images after them, so each path stays next to its image.\n\tconst content = joinAdjacentText(await saveImages(truncated.items, options.write));\n\tconst header = `${result.ok ? \"Script completed\" : \"Script failed\"}\\nWall time ${(options.wallMs / 1000).toFixed(1)} seconds\\nOutput:\\n`;\n\treturn {\n\t\tcontent: [{ type: \"text\", text: header }, ...content],\n\t\t...(truncated.fullOutputPath === undefined ? {} : { fullOutputPath: truncated.fullOutputPath }),\n\t};\n}\n"]}
|
package/dist/harness/agent.d.ts
CHANGED
|
@@ -13,8 +13,10 @@ export declare function resolveSettings(settings: HarnessSettings | undefined):
|
|
|
13
13
|
export declare function configure(tx: Tx, conversationId: ConversationId, change: AgentChange): Promise<void>;
|
|
14
14
|
/**
|
|
15
15
|
* `addTools` of a tool round, applied to `tools` and `modelTools`, so the next request offers the tools: an array gets
|
|
16
|
-
* each name it lacks appended, `{ remove }` loses the names
|
|
17
|
-
*
|
|
16
|
+
* each name it lacks appended, and `{ remove }` loses the names. An unset `tools` already enables every tool, so nothing
|
|
17
|
+
* is written for it. An unset or object `modelTools` also gets each name appended to its `add`, which loads deferred
|
|
18
|
+
* tools and has no effect for others. By name, without the registry: a tool that is not registered now, such as one of
|
|
19
|
+
* an MCP server that is reconnecting, is offered once it is again.
|
|
18
20
|
*/
|
|
19
21
|
export declare function addTools(tx: Tx, conversationId: ConversationId, added: readonly string[]): Promise<void>;
|
|
20
22
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/harness/agent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EACX,KAAK,EACL,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,uBAAuB,EAEvB,eAAe,EACf,cAAc,EAEd,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,oBAAoB,EAAE,uBAKlC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,gBAKvC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,cAGrC,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,6FAA6F;AAC7F,eAAO,MAAM,QAAQ,kEAQnB,CAAC;AAKH,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,SAAS,GAAG,QAAQ,CAkB/E;AAED,8HAA8H;AAC9H,wBAAsB,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1G;AAED
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/harness/agent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EACX,KAAK,EACL,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,uBAAuB,EAEvB,eAAe,EACf,cAAc,EAEd,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,oBAAoB,EAAE,uBAKlC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,gBAKvC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,cAGrC,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,6FAA6F;AAC7F,eAAO,MAAM,QAAQ,kEAQnB,CAAC;AAKH,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,SAAS,GAAG,QAAQ,CAkB/E;AAED,8HAA8H;AAC9H,wBAAsB,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1G;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB9G;AAmDD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzF;AAED,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAMnE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,SAAS,gBAAgB,EACzD,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,EACvC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAChC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAC9B,KAAK,CAAC,IAAI,CAAC,CAuDb"}
|
package/dist/harness/agent.js
CHANGED
|
@@ -58,27 +58,36 @@ export async function configure(tx, conversationId, change) {
|
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
60
|
* `addTools` of a tool round, applied to `tools` and `modelTools`, so the next request offers the tools: an array gets
|
|
61
|
-
* each name it lacks appended, `{ remove }` loses the names
|
|
62
|
-
*
|
|
61
|
+
* each name it lacks appended, and `{ remove }` loses the names. An unset `tools` already enables every tool, so nothing
|
|
62
|
+
* is written for it. An unset or object `modelTools` also gets each name appended to its `add`, which loads deferred
|
|
63
|
+
* tools and has no effect for others. By name, without the registry: a tool that is not registered now, such as one of
|
|
64
|
+
* an MCP server that is reconnecting, is offered once it is again.
|
|
63
65
|
*/
|
|
64
66
|
export async function addTools(tx, conversationId, added) {
|
|
65
67
|
const state = await tx.doc(AgentDoc, conversationId);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
const tools = state.tools;
|
|
69
|
+
if (Array.isArray(tools)) {
|
|
70
|
+
for (const name of added)
|
|
71
|
+
if (!tools.includes(name))
|
|
72
|
+
tools.push(name);
|
|
73
|
+
}
|
|
74
|
+
else if (tools?.remove.some((name) => added.includes(name))) {
|
|
75
|
+
state.tools = { remove: tools.remove.filter((name) => !added.includes(name)) };
|
|
76
|
+
}
|
|
77
|
+
const modelTools = state.modelTools;
|
|
78
|
+
if (Array.isArray(modelTools)) {
|
|
79
|
+
for (const name of added)
|
|
80
|
+
if (!modelTools.includes(name))
|
|
81
|
+
modelTools.push(name);
|
|
82
|
+
return;
|
|
81
83
|
}
|
|
84
|
+
// Assigned whole; a document write of an equal value records no change.
|
|
85
|
+
const remove = (modelTools?.remove ?? []).filter((name) => !added.includes(name));
|
|
86
|
+
const add = [...(modelTools?.add ?? [])];
|
|
87
|
+
for (const name of added)
|
|
88
|
+
if (!add.includes(name))
|
|
89
|
+
add.push(name);
|
|
90
|
+
state.modelTools = { ...(remove.length === 0 ? {} : { remove }), add };
|
|
82
91
|
}
|
|
83
92
|
function applyChange(state, change) {
|
|
84
93
|
const set = (key, value) => {
|
|
@@ -100,14 +109,17 @@ function applyChange(state, change) {
|
|
|
100
109
|
...(extensions.add === undefined ? {} : { add: names(extensions.add) }),
|
|
101
110
|
...(extensions.remove === undefined ? {} : { remove: names(extensions.remove) }),
|
|
102
111
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
const tools = change.tools;
|
|
113
|
+
set("tools", tools === undefined || tools === null ? tools : isList(tools) ? names(tools) : { remove: names(tools.remove) });
|
|
114
|
+
const modelTools = change.modelTools;
|
|
115
|
+
set("modelTools", modelTools === undefined || modelTools === null
|
|
116
|
+
? modelTools
|
|
117
|
+
: isList(modelTools)
|
|
118
|
+
? names(modelTools)
|
|
119
|
+
: {
|
|
120
|
+
...(modelTools.remove === undefined ? {} : { remove: names(modelTools.remove) }),
|
|
121
|
+
...(modelTools.add === undefined ? {} : { add: names(modelTools.add) }),
|
|
122
|
+
});
|
|
111
123
|
set("instructions", change.instructions);
|
|
112
124
|
set("cwd", change.cwd);
|
|
113
125
|
}
|
|
@@ -166,7 +178,10 @@ export function resolveAgent(state, snapshot, settings, report) {
|
|
|
166
178
|
}
|
|
167
179
|
const enabled = filterTools([...composed.values()], state?.tools);
|
|
168
180
|
const callableBy = (caller) => (tool) => tool.callers === undefined || tool.callers.includes(caller);
|
|
169
|
-
const
|
|
181
|
+
const modelCallable = enabled.filter(callableBy("model"));
|
|
182
|
+
const tools = offeredTools(modelCallable, state?.modelTools);
|
|
183
|
+
const offered = new Set(tools);
|
|
184
|
+
const deferred = modelCallable.filter((tool) => tool.deferred === true && !offered.has(tool));
|
|
170
185
|
const callable = enabled.filter(callableBy("tools"));
|
|
171
186
|
const instructions = state?.instructions;
|
|
172
187
|
const agentSections = [...sections.values()];
|
|
@@ -178,12 +193,27 @@ export function resolveAgent(state, snapshot, settings, report) {
|
|
|
178
193
|
extensions,
|
|
179
194
|
tools,
|
|
180
195
|
callable,
|
|
196
|
+
deferred,
|
|
181
197
|
sections: agentSections,
|
|
182
198
|
...(instructions === undefined ? {} : { instructions }),
|
|
183
199
|
...(state?.cwd === undefined ? {} : { cwd: state.cwd }),
|
|
184
200
|
};
|
|
185
201
|
return agent;
|
|
186
202
|
}
|
|
203
|
+
/** The tools offered to the model, as `AgentState.modelTools` describes. */
|
|
204
|
+
function offeredTools(tools, filter) {
|
|
205
|
+
if (Array.isArray(filter))
|
|
206
|
+
return filterTools(tools, filter);
|
|
207
|
+
const removed = new Set(filter?.remove ?? []);
|
|
208
|
+
const kept = tools.filter((tool) => tool.deferred !== true && !removed.has(tool.name));
|
|
209
|
+
// Loaded deferred tools follow in load order, so loading one appends to the declared tools.
|
|
210
|
+
const byName = new Map(tools.map((tool) => [tool.name, tool]));
|
|
211
|
+
const loaded = [...new Set(filter?.add ?? [])].flatMap((name) => {
|
|
212
|
+
const tool = byName.get(name);
|
|
213
|
+
return tool?.deferred === true && !removed.has(name) ? [tool] : [];
|
|
214
|
+
});
|
|
215
|
+
return [...kept, ...loaded];
|
|
216
|
+
}
|
|
187
217
|
/** `tools` through a stored filter: an array selects exactly its names, in its order; `{ remove }` drops names. */
|
|
188
218
|
function filterTools(tools, filter) {
|
|
189
219
|
if (filter === undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/harness/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import { copyJson, type Draft } from \"@ny4n/chord\";\nimport { defineDoc } from \"../documents.ts\";\nimport { documentRetention } from \"../session/session.ts\";\nimport type { ConversationId, ConversationRecord, Tx } from \"../types.ts\";\nimport type {\n\tAgent,\n\tAgentChange,\n\tAgentState,\n\tCompactionPolicy,\n\tConversationRetryPolicy,\n\tExtension,\n\tHarnessSettings,\n\tProgressPolicy,\n\tPromptSection,\n\tRegistrySnapshot,\n\tSettings,\n\tToolRegistration,\n} from \"./types.ts\";\n\nexport const DEFAULT_RETRY_POLICY: ConversationRetryPolicy = {\n\tenabled: true,\n\tmaxRetries: 3,\n\tbaseDelayMs: 2000,\n\tmaxAgentDelayMs: 60000,\n};\n\nexport const DEFAULT_COMPACTION_POLICY: CompactionPolicy = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tkeepRecentTokens: 20000,\n\tbackgroundTokens: 32768,\n};\n\nexport const DEFAULT_PROGRESS_POLICY: ProgressPolicy = {\n\tpartialIntervalMs: 100,\n\toutputIntervalMs: 100,\n};\n\n/** The reserved section key of the agent's `instructions`. */\nexport const INSTRUCTIONS_KEY = \"instructions\";\n\n/** Built-in agent document; rewindable so forks start from the agent at their fork entry. */\nexport const AgentDoc = defineDoc<AgentState>({\n\tkind: \"nyan.agent\",\n\tversion: 1,\n\tscope: \"conversation\",\n\thistory: \"rewindable\",\n\tfork: \"asOf\",\n\tinitial: () => ({}),\n\tcheckpointWhen: () => true,\n});\n\n/** Default `settings.contextRetentionMs`: ten minutes. */\nconst DEFAULT_CONTEXT_RETENTION_MS = 600_000;\n\n/** Resolve the host settings: every field over its built-in default, object fields merged. */\nexport function resolveSettings(settings: HarnessSettings | undefined): Settings {\n\tconst extensions = settings?.extensions;\n\treturn {\n\t\t...(extensions === undefined ? {} : { extensions }),\n\t\tstream: { ...settings?.stream },\n\t\tretry: { ...DEFAULT_RETRY_POLICY, ...settings?.retry },\n\t\tcompaction: { ...DEFAULT_COMPACTION_POLICY, ...settings?.compaction },\n\t\t// Field by field, so an explicitly undefined interval keeps its default.\n\t\tprogress: {\n\t\t\tpartialIntervalMs: settings?.progress?.partialIntervalMs ?? DEFAULT_PROGRESS_POLICY.partialIntervalMs,\n\t\t\toutputIntervalMs: settings?.progress?.outputIntervalMs ?? DEFAULT_PROGRESS_POLICY.outputIntervalMs,\n\t\t},\n\t\ttoolExecution: settings?.toolExecution ?? \"parallel\",\n\t\tsteeringMode: settings?.steeringMode ?? \"one-at-a-time\",\n\t\tfollowUpMode: settings?.followUpMode ?? \"one-at-a-time\",\n\t\tcontextRetentionMs: settings?.contextRetentionMs ?? DEFAULT_CONTEXT_RETENTION_MS,\n\t\tdocumentRetentionMs: documentRetention(settings?.documentRetentionMs),\n\t};\n}\n\n/** Apply one change to `nyan.agent`: a given field replaces the stored one, `null` clears it, `undefined` changes nothing. */\nexport async function configure(tx: Tx, conversationId: ConversationId, change: AgentChange): Promise<void> {\n\tconst state = await tx.doc(AgentDoc, conversationId);\n\tapplyChange(state, change);\n}\n\n/**\n * `addTools` of a tool round, applied to `tools` and `modelTools`, so the next request offers the tools: an array gets\n * each name it lacks appended, `{ remove }` loses the names, and an unset filter already lets every tool through, so\n * nothing is written.\n */\nexport async function addTools(tx: Tx, conversationId: ConversationId, added: readonly string[]): Promise<void> {\n\tconst state = await tx.doc(AgentDoc, conversationId);\n\tfor (const field of [\"tools\", \"modelTools\"] as const) {\n\t\tconst filter = state[field];\n\t\tif (filter === undefined) continue;\n\t\tif (Array.isArray(filter)) {\n\t\t\tfor (const name of added) if (!filter.includes(name)) filter.push(name);\n\t\t} else {\n\t\t\tconst remove = (filter as { remove: string[] }).remove;\n\t\t\tif (remove.some((name) => added.includes(name))) {\n\t\t\t\tstate[field] = { remove: remove.filter((name) => !added.includes(name)) };\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction applyChange(state: Draft<AgentState>, change: AgentChange): void {\n\tconst set = <K extends keyof AgentState>(key: K, value: AgentState[K] | null | undefined) => {\n\t\tif (value === undefined) return;\n\t\tif (value === null) delete state[key];\n\t\telse state[key] = value as Draft<AgentState>[K];\n\t};\n\tset(\"model\", change.model === undefined || change.model === null ? change.model : { ...change.model });\n\tset(\"thinkingLevel\", change.thinkingLevel);\n\tconst extensions = change.extensions;\n\tset(\n\t\t\"extensions\",\n\t\textensions === undefined || extensions === null\n\t\t\t? extensions\n\t\t\t: isList(extensions)\n\t\t\t\t? names(extensions)\n\t\t\t\t: {\n\t\t\t\t\t\t...(extensions.add === undefined ? {} : { add: names(extensions.add) }),\n\t\t\t\t\t\t...(extensions.remove === undefined ? {} : { remove: names(extensions.remove) }),\n\t\t\t\t\t},\n\t);\n\tfor (const field of [\"tools\", \"modelTools\"] as const) {\n\t\tconst filter = change[field];\n\t\tset(\n\t\t\tfield,\n\t\t\tfilter === undefined || filter === null\n\t\t\t\t? filter\n\t\t\t\t: isList(filter)\n\t\t\t\t\t? names(filter)\n\t\t\t\t\t: { remove: names(filter.remove) },\n\t\t);\n\t}\n\tset(\"instructions\", change.instructions);\n\tset(\"cwd\", change.cwd);\n}\n\nfunction isList<T>(value: readonly T[] | object): value is readonly T[] {\n\treturn Array.isArray(value);\n}\n\nfunction names(items: readonly { readonly name: string }[]): string[] {\n\treturn items.map((item) => item.name);\n}\n\n/**\n * Built-in part of every Harness commit that creates or forks a conversation, for `nyan.agent`: a fork keeps its `asOf`\n * copy; a new task-owned conversation copies the stored agent of its owner task's conversation; a new ownerless one\n * starts empty.\n */\nexport async function createAgent(tx: Tx, conversation: ConversationRecord): Promise<void> {\n\tif (conversation.parent !== undefined) return;\n\tconst agent = await tx.doc(AgentDoc, conversation.id);\n\tif (conversation.owner === undefined) return;\n\tconst owner = await tx.doc(AgentDoc, conversation.owner.conversationId);\n\tObject.assign(agent, copyJson(owner) as AgentState);\n}\n\n/** Handlers of the selected extensions' hooks for a task name, in extension order. */\nexport function agentHooks(agent: Agent, taskName: string): object[] {\n\tconst handlers: object[] = [];\n\tfor (const extension of agent.extensions) {\n\t\tfor (const hook of extension.hooks ?? []) if (hook.task === taskName) handlers.push(hook.handlers);\n\t}\n\treturn handlers;\n}\n\n/**\n * Resolve an agent from its stored state (absent: every field unset), a registry snapshot, and resolved settings. A\n * wrapper that throws or renames drops its target and is reported; a wrapper without a target does nothing.\n */\nexport function resolveAgent<Tool extends ToolRegistration>(\n\tstate: Readonly<AgentState> | undefined,\n\tsnapshot: RegistrySnapshot<Tool>,\n\tsettings: Settings,\n\treport: (error: unknown) => void,\n): Agent<Tool> {\n\tconst extensions = selectExtensions(state?.extensions, snapshot, settings);\n\n\tconst composed = new Map<string, Tool>();\n\tfor (const extension of extensions) for (const tool of extension.tools ?? []) composed.set(tool.name, tool);\n\tconst sections = new Map<string, PromptSection<Tool>>();\n\tfor (const extension of extensions) {\n\t\tfor (const section of extension.sections ?? []) sections.set(section.key, section);\n\t}\n\tfor (const extension of extensions) {\n\t\tfor (const wrap of extension.wraps ?? []) {\n\t\t\tif (\"tool\" in wrap)\n\t\t\t\tapplyWrap(\n\t\t\t\t\tcomposed,\n\t\t\t\t\twrap.tool,\n\t\t\t\t\t(tool) => wrap.wrap(tool),\n\t\t\t\t\t(tool) => tool.name,\n\t\t\t\t\treport,\n\t\t\t\t);\n\t\t\telse\n\t\t\t\tapplyWrap(\n\t\t\t\t\tsections,\n\t\t\t\t\twrap.section,\n\t\t\t\t\t(section) => wrap.wrap(section),\n\t\t\t\t\t(section) => section.key,\n\t\t\t\t\treport,\n\t\t\t\t);\n\t\t}\n\t}\n\n\tconst enabled = filterTools([...composed.values()], state?.tools);\n\tconst callableBy = (caller: \"model\" | \"tools\") => (tool: Tool) =>\n\t\ttool.callers === undefined || tool.callers.includes(caller);\n\tconst tools = filterTools(enabled.filter(callableBy(\"model\")), state?.modelTools);\n\tconst callable = enabled.filter(callableBy(\"tools\"));\n\n\tconst instructions = state?.instructions;\n\tconst agentSections = [...sections.values()];\n\tif (instructions !== undefined) agentSections.push({ key: INSTRUCTIONS_KEY, render: () => instructions });\n\n\tconst agent: Agent<Tool> = {\n\t\t...(state?.model === undefined ? {} : { model: state.model }),\n\t\tthinkingLevel: state?.thinkingLevel ?? \"off\",\n\t\textensions,\n\t\ttools,\n\t\tcallable,\n\t\tsections: agentSections,\n\t\t...(instructions === undefined ? {} : { instructions }),\n\t\t...(state?.cwd === undefined ? {} : { cwd: state.cwd }),\n\t};\n\treturn agent;\n}\n\n/** `tools` through a stored filter: an array selects exactly its names, in its order; `{ remove }` drops names. */\nfunction filterTools<Tool extends ToolRegistration>(tools: Tool[], filter: AgentState[\"tools\"]): Tool[] {\n\tif (filter === undefined) return tools;\n\tif (Array.isArray(filter)) {\n\t\tconst byName = new Map(tools.map((tool) => [tool.name, tool]));\n\t\treturn [...new Set(filter)].flatMap((name) => {\n\t\t\tconst tool = byName.get(name);\n\t\t\treturn tool === undefined ? [] : [tool];\n\t\t});\n\t}\n\tconst removed = new Set((filter as { remove: string[] }).remove);\n\treturn tools.filter((tool) => !removed.has(tool.name));\n}\n\n/** Selected installed extensions: the stored array, or the default selection edited by `{ add, remove }`. */\nfunction selectExtensions<Tool extends ToolRegistration>(\n\tstored: AgentState[\"extensions\"],\n\tsnapshot: RegistrySnapshot<Tool>,\n\tsettings: Settings,\n): Extension<Tool>[] {\n\tlet selected: string[];\n\tif (Array.isArray(stored)) selected = stored;\n\telse {\n\t\tconst base = settings.extensions?.map((extension) => extension.name) ?? snapshot.installed().map((e) => e.name);\n\t\tconst edit = stored as { add?: string[]; remove?: string[] } | undefined;\n\t\tconst removed = new Set(edit?.remove ?? []);\n\t\tselected = [...base, ...(edit?.add ?? [])].filter((name) => !removed.has(name));\n\t}\n\tconst extensions: Extension<Tool>[] = [];\n\tfor (const name of new Set(selected)) {\n\t\tconst extension = snapshot.extension(name);\n\t\tif (extension !== undefined) extensions.push(extension);\n\t}\n\treturn extensions;\n}\n\nfunction applyWrap<T>(\n\titems: Map<string, T>,\n\ttarget: string,\n\twrap: (item: T) => T,\n\tnameOf: (item: T) => string,\n\treport: (error: unknown) => void,\n): void {\n\tconst item = items.get(target);\n\tif (item === undefined) return;\n\ttry {\n\t\tconst wrapped = wrap(item);\n\t\tif (nameOf(wrapped) !== target) throw new Error(`Wrapper renamed ${target} to ${nameOf(wrapped)}`);\n\t\titems.set(target, wrapped);\n\t} catch (error) {\n\t\titems.delete(target);\n\t\treport(error);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/harness/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import { copyJson, type Draft } from \"@ny4n/chord\";\nimport { defineDoc } from \"../documents.ts\";\nimport { documentRetention } from \"../session/session.ts\";\nimport type { ConversationId, ConversationRecord, Tx } from \"../types.ts\";\nimport type {\n\tAgent,\n\tAgentChange,\n\tAgentState,\n\tCompactionPolicy,\n\tConversationRetryPolicy,\n\tExtension,\n\tHarnessSettings,\n\tProgressPolicy,\n\tPromptSection,\n\tRegistrySnapshot,\n\tSettings,\n\tToolRegistration,\n} from \"./types.ts\";\n\nexport const DEFAULT_RETRY_POLICY: ConversationRetryPolicy = {\n\tenabled: true,\n\tmaxRetries: 3,\n\tbaseDelayMs: 2000,\n\tmaxAgentDelayMs: 60000,\n};\n\nexport const DEFAULT_COMPACTION_POLICY: CompactionPolicy = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tkeepRecentTokens: 20000,\n\tbackgroundTokens: 32768,\n};\n\nexport const DEFAULT_PROGRESS_POLICY: ProgressPolicy = {\n\tpartialIntervalMs: 100,\n\toutputIntervalMs: 100,\n};\n\n/** The reserved section key of the agent's `instructions`. */\nexport const INSTRUCTIONS_KEY = \"instructions\";\n\n/** Built-in agent document; rewindable so forks start from the agent at their fork entry. */\nexport const AgentDoc = defineDoc<AgentState>({\n\tkind: \"nyan.agent\",\n\tversion: 1,\n\tscope: \"conversation\",\n\thistory: \"rewindable\",\n\tfork: \"asOf\",\n\tinitial: () => ({}),\n\tcheckpointWhen: () => true,\n});\n\n/** Default `settings.contextRetentionMs`: ten minutes. */\nconst DEFAULT_CONTEXT_RETENTION_MS = 600_000;\n\n/** Resolve the host settings: every field over its built-in default, object fields merged. */\nexport function resolveSettings(settings: HarnessSettings | undefined): Settings {\n\tconst extensions = settings?.extensions;\n\treturn {\n\t\t...(extensions === undefined ? {} : { extensions }),\n\t\tstream: { ...settings?.stream },\n\t\tretry: { ...DEFAULT_RETRY_POLICY, ...settings?.retry },\n\t\tcompaction: { ...DEFAULT_COMPACTION_POLICY, ...settings?.compaction },\n\t\t// Field by field, so an explicitly undefined interval keeps its default.\n\t\tprogress: {\n\t\t\tpartialIntervalMs: settings?.progress?.partialIntervalMs ?? DEFAULT_PROGRESS_POLICY.partialIntervalMs,\n\t\t\toutputIntervalMs: settings?.progress?.outputIntervalMs ?? DEFAULT_PROGRESS_POLICY.outputIntervalMs,\n\t\t},\n\t\ttoolExecution: settings?.toolExecution ?? \"parallel\",\n\t\tsteeringMode: settings?.steeringMode ?? \"one-at-a-time\",\n\t\tfollowUpMode: settings?.followUpMode ?? \"one-at-a-time\",\n\t\tcontextRetentionMs: settings?.contextRetentionMs ?? DEFAULT_CONTEXT_RETENTION_MS,\n\t\tdocumentRetentionMs: documentRetention(settings?.documentRetentionMs),\n\t};\n}\n\n/** Apply one change to `nyan.agent`: a given field replaces the stored one, `null` clears it, `undefined` changes nothing. */\nexport async function configure(tx: Tx, conversationId: ConversationId, change: AgentChange): Promise<void> {\n\tconst state = await tx.doc(AgentDoc, conversationId);\n\tapplyChange(state, change);\n}\n\n/**\n * `addTools` of a tool round, applied to `tools` and `modelTools`, so the next request offers the tools: an array gets\n * each name it lacks appended, and `{ remove }` loses the names. An unset `tools` already enables every tool, so nothing\n * is written for it. An unset or object `modelTools` also gets each name appended to its `add`, which loads deferred\n * tools and has no effect for others. By name, without the registry: a tool that is not registered now, such as one of\n * an MCP server that is reconnecting, is offered once it is again.\n */\nexport async function addTools(tx: Tx, conversationId: ConversationId, added: readonly string[]): Promise<void> {\n\tconst state = await tx.doc(AgentDoc, conversationId);\n\tconst tools = state.tools;\n\tif (Array.isArray(tools)) {\n\t\tfor (const name of added) if (!tools.includes(name)) tools.push(name);\n\t} else if (tools?.remove.some((name) => added.includes(name))) {\n\t\tstate.tools = { remove: tools.remove.filter((name) => !added.includes(name)) };\n\t}\n\tconst modelTools = state.modelTools;\n\tif (Array.isArray(modelTools)) {\n\t\tfor (const name of added) if (!modelTools.includes(name)) modelTools.push(name);\n\t\treturn;\n\t}\n\t// Assigned whole; a document write of an equal value records no change.\n\tconst remove = (modelTools?.remove ?? []).filter((name) => !added.includes(name));\n\tconst add = [...(modelTools?.add ?? [])];\n\tfor (const name of added) if (!add.includes(name)) add.push(name);\n\tstate.modelTools = { ...(remove.length === 0 ? {} : { remove }), add };\n}\n\nfunction applyChange(state: Draft<AgentState>, change: AgentChange): void {\n\tconst set = <K extends keyof AgentState>(key: K, value: AgentState[K] | null | undefined) => {\n\t\tif (value === undefined) return;\n\t\tif (value === null) delete state[key];\n\t\telse state[key] = value as Draft<AgentState>[K];\n\t};\n\tset(\"model\", change.model === undefined || change.model === null ? change.model : { ...change.model });\n\tset(\"thinkingLevel\", change.thinkingLevel);\n\tconst extensions = change.extensions;\n\tset(\n\t\t\"extensions\",\n\t\textensions === undefined || extensions === null\n\t\t\t? extensions\n\t\t\t: isList(extensions)\n\t\t\t\t? names(extensions)\n\t\t\t\t: {\n\t\t\t\t\t\t...(extensions.add === undefined ? {} : { add: names(extensions.add) }),\n\t\t\t\t\t\t...(extensions.remove === undefined ? {} : { remove: names(extensions.remove) }),\n\t\t\t\t\t},\n\t);\n\tconst tools = change.tools;\n\tset(\n\t\t\"tools\",\n\t\ttools === undefined || tools === null ? tools : isList(tools) ? names(tools) : { remove: names(tools.remove) },\n\t);\n\tconst modelTools = change.modelTools;\n\tset(\n\t\t\"modelTools\",\n\t\tmodelTools === undefined || modelTools === null\n\t\t\t? modelTools\n\t\t\t: isList(modelTools)\n\t\t\t\t? names(modelTools)\n\t\t\t\t: {\n\t\t\t\t\t\t...(modelTools.remove === undefined ? {} : { remove: names(modelTools.remove) }),\n\t\t\t\t\t\t...(modelTools.add === undefined ? {} : { add: names(modelTools.add) }),\n\t\t\t\t\t},\n\t);\n\tset(\"instructions\", change.instructions);\n\tset(\"cwd\", change.cwd);\n}\n\nfunction isList<T>(value: readonly T[] | object): value is readonly T[] {\n\treturn Array.isArray(value);\n}\n\nfunction names(items: readonly { readonly name: string }[]): string[] {\n\treturn items.map((item) => item.name);\n}\n\n/**\n * Built-in part of every Harness commit that creates or forks a conversation, for `nyan.agent`: a fork keeps its `asOf`\n * copy; a new task-owned conversation copies the stored agent of its owner task's conversation; a new ownerless one\n * starts empty.\n */\nexport async function createAgent(tx: Tx, conversation: ConversationRecord): Promise<void> {\n\tif (conversation.parent !== undefined) return;\n\tconst agent = await tx.doc(AgentDoc, conversation.id);\n\tif (conversation.owner === undefined) return;\n\tconst owner = await tx.doc(AgentDoc, conversation.owner.conversationId);\n\tObject.assign(agent, copyJson(owner) as AgentState);\n}\n\n/** Handlers of the selected extensions' hooks for a task name, in extension order. */\nexport function agentHooks(agent: Agent, taskName: string): object[] {\n\tconst handlers: object[] = [];\n\tfor (const extension of agent.extensions) {\n\t\tfor (const hook of extension.hooks ?? []) if (hook.task === taskName) handlers.push(hook.handlers);\n\t}\n\treturn handlers;\n}\n\n/**\n * Resolve an agent from its stored state (absent: every field unset), a registry snapshot, and resolved settings. A\n * wrapper that throws or renames drops its target and is reported; a wrapper without a target does nothing.\n */\nexport function resolveAgent<Tool extends ToolRegistration>(\n\tstate: Readonly<AgentState> | undefined,\n\tsnapshot: RegistrySnapshot<Tool>,\n\tsettings: Settings,\n\treport: (error: unknown) => void,\n): Agent<Tool> {\n\tconst extensions = selectExtensions(state?.extensions, snapshot, settings);\n\n\tconst composed = new Map<string, Tool>();\n\tfor (const extension of extensions) for (const tool of extension.tools ?? []) composed.set(tool.name, tool);\n\tconst sections = new Map<string, PromptSection<Tool>>();\n\tfor (const extension of extensions) {\n\t\tfor (const section of extension.sections ?? []) sections.set(section.key, section);\n\t}\n\tfor (const extension of extensions) {\n\t\tfor (const wrap of extension.wraps ?? []) {\n\t\t\tif (\"tool\" in wrap)\n\t\t\t\tapplyWrap(\n\t\t\t\t\tcomposed,\n\t\t\t\t\twrap.tool,\n\t\t\t\t\t(tool) => wrap.wrap(tool),\n\t\t\t\t\t(tool) => tool.name,\n\t\t\t\t\treport,\n\t\t\t\t);\n\t\t\telse\n\t\t\t\tapplyWrap(\n\t\t\t\t\tsections,\n\t\t\t\t\twrap.section,\n\t\t\t\t\t(section) => wrap.wrap(section),\n\t\t\t\t\t(section) => section.key,\n\t\t\t\t\treport,\n\t\t\t\t);\n\t\t}\n\t}\n\n\tconst enabled = filterTools([...composed.values()], state?.tools);\n\tconst callableBy = (caller: \"model\" | \"tools\") => (tool: Tool) =>\n\t\ttool.callers === undefined || tool.callers.includes(caller);\n\tconst modelCallable = enabled.filter(callableBy(\"model\"));\n\tconst tools = offeredTools(modelCallable, state?.modelTools);\n\tconst offered = new Set(tools);\n\tconst deferred = modelCallable.filter((tool) => tool.deferred === true && !offered.has(tool));\n\tconst callable = enabled.filter(callableBy(\"tools\"));\n\n\tconst instructions = state?.instructions;\n\tconst agentSections = [...sections.values()];\n\tif (instructions !== undefined) agentSections.push({ key: INSTRUCTIONS_KEY, render: () => instructions });\n\n\tconst agent: Agent<Tool> = {\n\t\t...(state?.model === undefined ? {} : { model: state.model }),\n\t\tthinkingLevel: state?.thinkingLevel ?? \"off\",\n\t\textensions,\n\t\ttools,\n\t\tcallable,\n\t\tdeferred,\n\t\tsections: agentSections,\n\t\t...(instructions === undefined ? {} : { instructions }),\n\t\t...(state?.cwd === undefined ? {} : { cwd: state.cwd }),\n\t};\n\treturn agent;\n}\n\n/** The tools offered to the model, as `AgentState.modelTools` describes. */\nfunction offeredTools<Tool extends ToolRegistration>(tools: Tool[], filter: AgentState[\"modelTools\"]): Tool[] {\n\tif (Array.isArray(filter)) return filterTools(tools, filter);\n\tconst removed = new Set(filter?.remove ?? []);\n\tconst kept = tools.filter((tool) => tool.deferred !== true && !removed.has(tool.name));\n\t// Loaded deferred tools follow in load order, so loading one appends to the declared tools.\n\tconst byName = new Map(tools.map((tool) => [tool.name, tool]));\n\tconst loaded = [...new Set(filter?.add ?? [])].flatMap((name) => {\n\t\tconst tool = byName.get(name);\n\t\treturn tool?.deferred === true && !removed.has(name) ? [tool] : [];\n\t});\n\treturn [...kept, ...loaded];\n}\n\n/** `tools` through a stored filter: an array selects exactly its names, in its order; `{ remove }` drops names. */\nfunction filterTools<Tool extends ToolRegistration>(tools: Tool[], filter: AgentState[\"tools\"]): Tool[] {\n\tif (filter === undefined) return tools;\n\tif (Array.isArray(filter)) {\n\t\tconst byName = new Map(tools.map((tool) => [tool.name, tool]));\n\t\treturn [...new Set(filter)].flatMap((name) => {\n\t\t\tconst tool = byName.get(name);\n\t\t\treturn tool === undefined ? [] : [tool];\n\t\t});\n\t}\n\tconst removed = new Set((filter as { remove: string[] }).remove);\n\treturn tools.filter((tool) => !removed.has(tool.name));\n}\n\n/** Selected installed extensions: the stored array, or the default selection edited by `{ add, remove }`. */\nfunction selectExtensions<Tool extends ToolRegistration>(\n\tstored: AgentState[\"extensions\"],\n\tsnapshot: RegistrySnapshot<Tool>,\n\tsettings: Settings,\n): Extension<Tool>[] {\n\tlet selected: string[];\n\tif (Array.isArray(stored)) selected = stored;\n\telse {\n\t\tconst base = settings.extensions?.map((extension) => extension.name) ?? snapshot.installed().map((e) => e.name);\n\t\tconst edit = stored as { add?: string[]; remove?: string[] } | undefined;\n\t\tconst removed = new Set(edit?.remove ?? []);\n\t\tselected = [...base, ...(edit?.add ?? [])].filter((name) => !removed.has(name));\n\t}\n\tconst extensions: Extension<Tool>[] = [];\n\tfor (const name of new Set(selected)) {\n\t\tconst extension = snapshot.extension(name);\n\t\tif (extension !== undefined) extensions.push(extension);\n\t}\n\treturn extensions;\n}\n\nfunction applyWrap<T>(\n\titems: Map<string, T>,\n\ttarget: string,\n\twrap: (item: T) => T,\n\tnameOf: (item: T) => string,\n\treport: (error: unknown) => void,\n): void {\n\tconst item = items.get(target);\n\tif (item === undefined) return;\n\ttry {\n\t\tconst wrapped = wrap(item);\n\t\tif (nameOf(wrapped) !== target) throw new Error(`Wrapper renamed ${target} to ${nameOf(wrapped)}`);\n\t\titems.set(target, wrapped);\n\t} catch (error) {\n\t\titems.delete(target);\n\t\treport(error);\n\t}\n}\n"]}
|
|
@@ -51,6 +51,11 @@ export declare function summarizedMessages(view: ContextView, cut: number): Mess
|
|
|
51
51
|
* every message.
|
|
52
52
|
*/
|
|
53
53
|
export declare function estimateContext(view: ContextView, extra: readonly Message[]): number;
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Messages as plain text, so the summarizer reads a transcript instead of continuing it. System messages are omitted.
|
|
56
|
+
* Thinking is omitted too: providers return summaries of the real reasoning, and replayed thinking is often not part of
|
|
57
|
+
* the live context (a block that does not match its request is dropped), so including it can make the request larger
|
|
58
|
+
* than the context it summarizes. Visible text, tool calls, and tool results record what happened.
|
|
59
|
+
*/
|
|
55
60
|
export declare function serializeConversation(messages: readonly Message[]): string;
|
|
56
61
|
//# sourceMappingURL=compaction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/harness/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,OAAO,EAAE,kBAAkB,EAAuB,MAAM,oBAAoB,CAAC;AAM7G,OAAO,KAAK,EACX,cAAc,EAEd,OAAO,EAGP,MAAM,EAEN,EAAE,EACF,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/harness/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,OAAO,EAAE,kBAAkB,EAAuB,MAAM,oBAAoB,CAAC;AAM7G,OAAO,KAAK,EACX,cAAc,EAEd,OAAO,EAGP,MAAM,EAEN,EAAE,EACF,MAAM,aAAa,CAAC;AAYrB,OAAO,KAAK,EACX,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,yBAAyB,EACzB,QAAQ,EACR,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,eAAe,GAAG;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAElF,wCAAwC;AACxC,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,CAAC;IAChB,aAAa,EAAE,kBAAkB,CAAC;IAClC,aAAa,EAAE,yBAAyB,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;IACd,uDAAuD;IACvD,SAAS,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAC7B;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,GACnB,CAAC;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG,cAAc,CAAC,GACzC,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,cAAc,CAAC,CAAC;AAiDxD;;;;GAIG;AACH,eAAO,MAAM,cAAc,sGA6HzB,CAAC;AAEH;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,EAAE,EAAE,EAAE,EACN,cAAc,EAAE,cAAc,EAC9B,KAAK,EAAE,eAAe,EACtB,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAQnC;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAkBzF;AAwBD,iHAAiH;AACjH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,EAAE,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAepF;AA4BD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAyB1E"}
|
|
@@ -3,7 +3,7 @@ import { isRetryableAssistantError, retryDelayMs } from "@ny4n/ai/utils/retry";
|
|
|
3
3
|
import { CompactionEntry } from "../entries.js";
|
|
4
4
|
import { defineTask } from "../tasks.js";
|
|
5
5
|
import { orderToolResults } from "./context.js";
|
|
6
|
-
import { addCompactionStatus, compactionStatus, LiveDoc, removeCompactionStatus } from "./live.js";
|
|
6
|
+
import { addCompactionStatus, compactionStatus, failCompactionStatus, LiveDoc, removeCompactionStatus, } from "./live.js";
|
|
7
7
|
import { ensureProviderSessionId } from "./provider.js";
|
|
8
8
|
import { admitSubmission } from "./submissions.js";
|
|
9
9
|
import { recordUsage } from "./usage.js";
|
|
@@ -146,8 +146,8 @@ export const CompactionTask = defineTask({
|
|
|
146
146
|
status.retry = { at: until, error: message.errorMessage ?? "" };
|
|
147
147
|
return { status: "running", checkpoint: { phase: "retry", ...request, until } };
|
|
148
148
|
}
|
|
149
|
-
removeCompactionStatus(live, runtime.taskId);
|
|
150
149
|
const text = summaryFailure(message);
|
|
150
|
+
failCompactionStatus(live, runtime.taskId, text);
|
|
151
151
|
return {
|
|
152
152
|
status: "terminal",
|
|
153
153
|
outcome: { status: "failed", error: { message: text, detail: { reason: "model_error" } } },
|
|
@@ -295,7 +295,12 @@ function summaryPrompt(messages, instructions) {
|
|
|
295
295
|
const focus = instructions === undefined ? "" : `\n\nAdditional focus: ${instructions}`;
|
|
296
296
|
return `<conversation>\n${serializeConversation(messages)}\n</conversation>\n\n${SUMMARIZATION_PROMPT}${focus}`;
|
|
297
297
|
}
|
|
298
|
-
/**
|
|
298
|
+
/**
|
|
299
|
+
* Messages as plain text, so the summarizer reads a transcript instead of continuing it. System messages are omitted.
|
|
300
|
+
* Thinking is omitted too: providers return summaries of the real reasoning, and replayed thinking is often not part of
|
|
301
|
+
* the live context (a block that does not match its request is dropped), so including it can make the request larger
|
|
302
|
+
* than the context it summarizes. Visible text, tool calls, and tool results record what happened.
|
|
303
|
+
*/
|
|
299
304
|
export function serializeConversation(messages) {
|
|
300
305
|
const parts = [];
|
|
301
306
|
for (const message of messages) {
|
|
@@ -305,7 +310,6 @@ export function serializeConversation(messages) {
|
|
|
305
310
|
parts.push(`[User]: ${text}`);
|
|
306
311
|
}
|
|
307
312
|
else if (message.role === "assistant") {
|
|
308
|
-
const thinking = message.content.flatMap((content) => (content.type === "thinking" ? [content.thinking] : []));
|
|
309
313
|
const text = message.content.flatMap((content) => (content.type === "text" ? [content.text] : []));
|
|
310
314
|
const calls = message.content.flatMap((content) => content.type === "toolCall"
|
|
311
315
|
? [
|
|
@@ -314,8 +318,6 @@ export function serializeConversation(messages) {
|
|
|
314
318
|
.join(", ")})`,
|
|
315
319
|
]
|
|
316
320
|
: []);
|
|
317
|
-
if (thinking.length > 0)
|
|
318
|
-
parts.push(`[Assistant thinking]: ${thinking.join("\n")}`);
|
|
319
321
|
if (text.length > 0)
|
|
320
322
|
parts.push(`[Assistant]: ${text.join("\n")}`);
|
|
321
323
|
if (calls.length > 0)
|
|
@@ -353,6 +355,7 @@ async function place(runtime, firstKept, summary, context) {
|
|
|
353
355
|
*/
|
|
354
356
|
async function placeSummary(tx, runtime, current, live, firstKept, summary) {
|
|
355
357
|
removeCompactionStatus(live, runtime.taskId);
|
|
358
|
+
delete live.compactionFailure;
|
|
356
359
|
const text = `${SUMMARY_PREFIX}${summary}${SUMMARY_SUFFIX}`;
|
|
357
360
|
const entry = {
|
|
358
361
|
kind: CompactionEntry.kind,
|
|
@@ -377,7 +380,7 @@ async function complete(runtime, context) {
|
|
|
377
380
|
async function failNoModel(runtime, ref, context) {
|
|
378
381
|
const message = ref === undefined ? "No model is configured" : `Model ${ref.provider}/${ref.modelId} is not available`;
|
|
379
382
|
await runtime.commit(async (tx) => {
|
|
380
|
-
|
|
383
|
+
failCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId, message);
|
|
381
384
|
return { status: "terminal", outcome: { status: "failed", error: { message, detail: { reason: "no_model" } } } };
|
|
382
385
|
}, context);
|
|
383
386
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../src/harness/compaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAWzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,OAAO,EAAkB,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnH,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AASnD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAyBzC,kEAAkE;AAClE,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC,MAAM,cAAc,GACnB,qGAAqG,CAAC;AACvG,MAAM,cAAc,GAAG,cAAc,CAAC;AAEtC,MAAM,2BAA2B,GAAG;;2HAEuF,CAAC;AAE5H,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0FA+B6D,CAAC;AAE3F;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAA2E;IAClH,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACpC,MAAM,EAAE;QACP,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YACxC,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;YACnC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;YAClC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;YACxB,MAAM,KAAK,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACjG,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YACxF,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC;YACnC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;YAC5D,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;YACrD,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACzD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAE,CAAC,EAAE,CAAC;YACxC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;YAC5C,MAAM,UAAU,GAAG;gBAClB,MAAM;gBACN,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBACnC,QAAQ,EAAE,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC;gBACvC,SAAS;gBACT,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;aACvD,CAAC;YACF,IAAI,QAA+E,CAAC;YACpF,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACxD,IAAI,QAAQ,KAAK,SAAS;oBAAE,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YACjF,CAAC,CAAC,CAAC;YACH,IAAI,QAAQ,KAAK,SAAS,IAAI,SAAS,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACvF,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxF,MAAM,OAAO,GAAmB;gBAC/B,OAAO,EAAE,CAAC;gBACV,KAAK,EAAE,GAAG;gBACV,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,aAAa,EAAE,QAAQ,CAAC,MAAM;gBAC9B,SAAS,EAAE,IAAI,CAAC,GAAG,CAClB,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC,EACtC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAChE;gBACD,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;gBAC1F,SAAS;aACT,CAAC;YACF,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9G,CAAC;QACD,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YAC3C,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;YACvD,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;YAClG,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACjE,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YACnE,2EAA2E;YAC3E,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAClF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;YACtE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAc;gBAC3B,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,EAAE,SAAS,EAAE,GAAG,EAAE;gBACxE;oBACC,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;oBACxG,SAAS,EAAE,GAAG;iBACd;aACD,CAAC;YACF,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,GAAG,aAAa,CAAC;YAC5D,MAAM,OAAO,GAAwB;gBACpC,GAAG,SAAS;gBACZ,cAAc,EAAE,MAAM;gBACtB,SAAS;gBACT,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,SAAS,EAAE,MAAM,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC;gBAC1D,GAAG,CAAC,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;aAChE,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;YAClF,iGAAiG;YACjG,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YACtC,MAAM,KAAK,GACV,OAAO,CAAC,UAAU,KAAK,OAAO;gBAC9B,yBAAyB,CAAC,OAAO,CAAC;gBAClC,MAAM,CAAC,OAAO;gBACd,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC;YAC9B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,OAAO,EAAiB,EAAE;gBACzD,MAAM,WAAW,CAChB,EAAE,EACF,OAAO,CAAC,cAAc,EACtB,QAAQ,EACR,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,EAAE,EACtC,OAAO,CAAC,KAAK,CACb,CAAC;gBACF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;gBAC3D,IAAI,OAAO,KAAK,SAAS;oBAAE,OAAO,YAAY,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;gBAC/F,IAAI,KAAK,EAAE,CAAC;oBACX,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;oBACtD,IAAI,MAAM,KAAK,SAAS;wBAAE,MAAM,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;oBAC1F,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;gBACjF,CAAC;gBACD,sBAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC7C,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;gBACrC,OAAO;oBACN,MAAM,EAAE,UAAU;oBAClB,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE;iBAC1F,CAAC;YACH,CAAC,EAAE,OAAO,CAAC,CAAC;QACb,CAAC;QACD,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YACvC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;YAC9D,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC;YACpC,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBACjC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/F,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBAC1B,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;oBACzB,OAAO,MAAM,CAAC,KAAK,CAAC;gBACrB,CAAC;gBACD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;YACvF,CAAC,EAAE,OAAO,CAAC,CAAC;QACb,CAAC;KACD;IACD,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QACxC,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACjC,sBAAsB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACtF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC;QAC/D,CAAC,EAAE,OAAO,CAAC,CAAC;IACb,CAAC;CACD,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,EAAM,EACN,cAA8B,EAC9B,KAAsB,EACtB,KAAc;IAEd,MAAM,SAAS,GACd,KAAK,KAAK,SAAS,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,cAAc,EAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACtG,MAAM,UAAU,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,cAAc,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC,CAAC;IACrG,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,KAAK,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAC3F,mBAAmB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;IACnE,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,IAAiB,EAAE,gBAAwB;IACpE,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/D,IAAI,WAAW,CAAC,aAAa,EAAE,KAAK,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,GAAuB,CAAC;IAC5B,KAAK,IAAI,KAAK,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;QACpE,KAAK,MAAM,OAAO,IAAI,aAAa,CAAC,KAAK,CAAE;YAAE,IAAI,IAAI,qBAAqB,CAAC,OAAO,CAAC,CAAC;QACpF,IAAI,IAAI,GAAG,gBAAgB;YAAE,SAAS;QACtC,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9E,MAAM;IACP,CAAC;IACD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,KAAK,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,GAAG,EAAE,KAAK,EAAE;QAAE,IAAI,aAAa,CAAC,KAAK,CAAE,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;IAC/F,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,aAA2C,EAAE,KAAa;IAC9E,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAE,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,KAAK,EAAE,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,KAAK,EAAE,IAAI,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACzC,qHAAqH;IACrH,IAAI,KAAK,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC3C,KAAK,IAAI,MAAM,GAAG,KAAK,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;QACpD,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAE,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;QAC7F,IAAI,SAAS,KAAK,SAAS;YAAE,SAAS;QACtC,KAAK,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3G,MAAM;IACP,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,KAAK,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/D,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,aAAa,CAAC,KAAK,CAAE,CAAC,OAAO,EAAE,EAAE,CAAC;YACnE,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,QAAQ,GAAG,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YACjF,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;gBAAE,OAAO,KAAK,CAAC;QAClF,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,iHAAiH;AACjH,MAAM,UAAU,kBAAkB,CAAC,IAAiB,EAAE,GAAW;IAChE,OAAO,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAiB,EAAE,KAAyB;IAC3E,IAAI,QAAsC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,MAAM,CAAC,iBAAiB,CAAC;IACxD,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,QAAQ,KAAK,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC;QACzF,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAE,CAAC,EAAE,IAAI,KAAK;YAAE,SAAS;QAC/C,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAE,CAAC,QAAQ,CAC7C,CAAC,OAAO,EAA+B,EAAE,CACxC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,sBAAsB,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAC1E,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClF,IAAI,MAAM,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACjF,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC1F,KAAK,MAAM,OAAO,IAAI,KAAK;QAAE,MAAM,IAAI,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AACf,CAAC;AAED,gGAAgG;AAChG,SAAS,WAAW,CAAC,OAAyB;IAC7C,IAAI,OAAO,CAAC,UAAU,KAAK,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC;QAClG,OAAO,SAAS,CAAC;IAClB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO;SAC1B,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SACrE,IAAI,CAAC,IAAI,CAAC;SACV,IAAI,EAAE,CAAC;IACT,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,SAAS,cAAc,CAAC,OAAyB;IAChD,IAAI,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACxE,OAAO,yBAAyB,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAC9E,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,8DAA8D,CAAC;IAC3G,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC;QAAE,OAAO,wCAAwC,CAAC;IACpH,OAAO,gCAAgC,CAAC;AACzC,CAAC;AAED,oGAAoG;AACpG,SAAS,aAAa,CAAC,QAA4B,EAAE,YAAgC;IACpF,MAAM,KAAK,GAAG,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,yBAAyB,YAAY,EAAE,CAAC;IACxF,OAAO,mBAAmB,qBAAqB,CAAC,QAAQ,CAAC,wBAAwB,oBAAoB,GAAG,KAAK,EAAE,CAAC;AACjH,CAAC;AAED,0HAA0H;AAC1H,MAAM,UAAU,qBAAqB,CAAC,QAA4B;IACjE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/G,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnG,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CACjD,OAAO,CAAC,IAAI,KAAK,UAAU;gBAC1B,CAAC,CAAC;oBACA,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;yBAClD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;yBACxD,IAAI,CAAC,IAAI,CAAC,GAAG;iBACf;gBACF,CAAC,CAAC,EAAE,CACL,CAAC;YACF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,yBAAyB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpF,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjF,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,WAAW,CAAC,OAA8E;IAClG,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,OAAO;SACZ,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC3F,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAgB;IAC/C,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC,MAAM,GAAG,QAAQ,6BAA6B,CAAC;AAClG,CAAC;AAED,4DAA4D;AAC5D,KAAK,UAAU,KAAK,CAAC,OAAgB,EAAE,SAAkB,EAAE,OAAe,EAAE,OAAgB;IAC3F,MAAM,OAAO,CAAC,MAAM,CACnB,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,CACrB,YAAY,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EACtG,OAAO,CACP,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,YAAY,CAC1B,EAAM,EACN,OAAgB,EAChB,OAA6E,EAC7E,IAAsB,EACtB,SAAkB,EAClB,OAAe;IAEf,sBAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,GAAG,cAAc,GAAG,OAAO,GAAG,cAAc,EAAE,CAAC;IAC5D,MAAM,KAAK,GAAG;QACb,IAAI,EAAE,eAAe,CAAC,IAAI;QAC1B,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;QACtF,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE;KACjB,CAAC;IACvB,MAAM,MAAM,GACX,OAAO,CAAC,KAAK,KAAK,SAAS;QAC1B,CAAC,CAAC;YACA,YAAY,EAAE,MAAM,eAAe,CAClC,EAAE,EACF,OAAO,CAAC,cAAc,EACtB,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,EACnE,OAAO,CAAC,GAAG,EAAE,EACb,OAAO,CAAC,QAAQ,CAChB;SACD;QACF,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAC1E,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;AACzE,CAAC;AAED,wDAAwD;AACxD,KAAK,UAAU,QAAQ,CAAC,OAAgB,EAAE,OAAgB;IACzD,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACjC,sBAAsB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACtF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;IAC7E,CAAC,EAAE,OAAO,CAAC,CAAC;AACb,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAgB,EAAE,GAAyB,EAAE,OAAgB;IACvF,MAAM,OAAO,GACZ,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,mBAAmB,CAAC;IACxG,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACjC,sBAAsB,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACtF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC;IAClH,CAAC,EAAE,OAAO,CAAC,CAAC;AACb,CAAC","sourcesContent":["import type { AssistantMessage, Message, ModelThinkingLevel, SimpleStreamOptions } from \"@ny4n/ai/contracts\";\nimport { calculateContextTokens, estimateMessageTokens } from \"@ny4n/ai/utils/estimate\";\nimport { isRetryableAssistantError, retryDelayMs } from \"@ny4n/ai/utils/retry\";\nimport type { Context, Draft } from \"@ny4n/chord\";\nimport { CompactionEntry } from \"../entries.ts\";\nimport { defineTask } from \"../tasks.ts\";\nimport type {\n\tConversationId,\n\tEntryDraft,\n\tEntryId,\n\tNextTaskState,\n\tRunningTask,\n\tTaskId,\n\tTaskRuntime,\n\tTx,\n} from \"../types.ts\";\nimport { orderToolResults } from \"./context.ts\";\nimport { addCompactionStatus, compactionStatus, LiveDoc, type LiveState, removeCompactionStatus } from \"./live.ts\";\nimport { ensureProviderSessionId } from \"./provider.ts\";\nimport { admitSubmission } from \"./submissions.ts\";\nimport type {\n\tCompactionHooks,\n\tCompactionReason,\n\tCompactionResult,\n\tContextView,\n\tConversationStreamOptions,\n\tModelRef,\n} from \"./types.ts\";\nimport { recordUsage } from \"./usage.ts\";\n\nexport type CompactionInput = { reason: CompactionReason; instructions?: string };\n\n/** The pinned summarization request. */\nexport type SummaryRequest = {\n\tattempt: number;\n\tmodel: ModelRef;\n\tthinkingLevel: ModelThinkingLevel;\n\tstreamOptions: ConversationStreamOptions;\n\tmaxTokens: number;\n\t/** Newest entry of the context the range was selected from. */\n\ttail: EntryId;\n\t/** First entry kept verbatim; the summary's `head`. */\n\tfirstKept: EntryId;\n};\n\nexport type CompactionCheckpoint =\n\t| { phase: \"select\" }\n\t| ({ phase: \"summarize\" } & SummaryRequest)\n\t| ({ phase: \"retry\"; until: number } & SummaryRequest);\n\ntype Runtime = TaskRuntime<CompactionInput, CompactionCheckpoint, CompactionResult, CompactionHooks>;\ntype Next = NextTaskState<CompactionCheckpoint, CompactionResult>;\n\n/** Longest tool result text a serialized summary source keeps. */\nconst TOOL_RESULT_MAX_CHARS = 2000;\n\nconst SUMMARY_PREFIX =\n\t\"The conversation history before this point was compacted into the following summary:\\n\\n<summary>\\n\";\nconst SUMMARY_SUFFIX = \"\\n</summary>\";\n\nconst SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;\n\nconst SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work. If the conversation starts with an earlier summary, preserve its information and fold the newer messages into it.\n\nUse this EXACT format:\n\n## Goal\n[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned by user]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Current work]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Next Steps\n1. [Ordered list of what should happen next]\n\n## Critical Context\n- [Any data, examples, or references needed to continue]\n- [Or \"(none)\" if not applicable]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\n/**\n * Built-in compaction task (spec §8.7): select an old prefix of the model context, summarize it, and place a summary\n * entry whose `head` is the first kept entry. A compaction the generation owns blocks it and appends directly; a\n * conversation-owned one places its summary through a write submission.\n */\nexport const CompactionTask = defineTask<CompactionInput, CompactionCheckpoint, CompactionResult, CompactionHooks>({\n\tname: \"nyan.compaction\",\n\tversion: 1,\n\tinitial: () => ({ phase: \"select\" }),\n\tphases: {\n\t\tselect: async (task, runtime, context) => {\n\t\t\tconst { conversationId } = runtime;\n\t\t\tconst agent = await runtime.agent(context);\n\t\t\tconst settings = runtime.settings;\n\t\t\tconst ref = agent.model;\n\t\t\tconst model = ref === undefined ? undefined : runtime.models.getModel(ref.provider, ref.modelId);\n\t\t\tif (ref === undefined || model === undefined) return failNoModel(runtime, ref, context);\n\t\t\tconst policy = settings.compaction;\n\t\t\tconst view = await runtime.context(conversationId, context);\n\t\t\tconst cut = selectCut(view, policy.keepRecentTokens);\n\t\t\tif (cut === undefined) return complete(runtime, context);\n\t\t\tconst firstKept = view.entries[cut]!.id;\n\t\t\tconst { reason, instructions } = task.input;\n\t\t\tconst compaction = {\n\t\t\t\treason,\n\t\t\t\tentries: view.entries.slice(0, cut),\n\t\t\t\tmessages: summarizedMessages(view, cut),\n\t\t\t\tfirstKept,\n\t\t\t\t...(instructions === undefined ? {} : { instructions }),\n\t\t\t};\n\t\t\tlet decision: { readonly decline: true } | { readonly summary: string } | undefined;\n\t\t\tawait runtime.hooks.each(\"beforeCompact\", async (hook) => {\n\t\t\t\tif (decision === undefined) decision = await hook(compaction, runtime, context);\n\t\t\t});\n\t\t\tif (decision !== undefined && \"decline\" in decision) return complete(runtime, context);\n\t\t\tif (decision !== undefined) return place(runtime, firstKept, decision.summary, context);\n\t\t\tconst request: SummaryRequest = {\n\t\t\t\tattempt: 1,\n\t\t\t\tmodel: ref,\n\t\t\t\tthinkingLevel: agent.thinkingLevel,\n\t\t\t\tstreamOptions: settings.stream,\n\t\t\t\tmaxTokens: Math.min(\n\t\t\t\t\tMath.floor(0.8 * policy.reserveTokens),\n\t\t\t\t\tmodel.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY,\n\t\t\t\t),\n\t\t\t\ttail: view.entries.reduce((tail, entry) => (entry.id > tail ? entry.id : tail), firstKept),\n\t\t\t\tfirstKept,\n\t\t\t};\n\t\t\tawait runtime.commit(() => ({ status: \"running\", checkpoint: { phase: \"summarize\", ...request } }), context);\n\t\t},\n\t\tsummarize: async (task, runtime, context) => {\n\t\t\tconst { phase: _, ...request } = task.state.checkpoint;\n\t\t\tconst { model: ref, thinkingLevel, streamOptions, maxTokens, tail, firstKept, attempt } = request;\n\t\t\tconst model = runtime.models.getModel(ref.provider, ref.modelId);\n\t\t\tif (model === undefined) return failNoModel(runtime, ref, context);\n\t\t\t// The context at `tail` is immutable, so this is the range `select` chose.\n\t\t\tconst view = await runtime.context(runtime.conversationId, context, { at: tail });\n\t\t\tconst cut = view.entries.findIndex((entry) => entry.id === firstKept);\n\t\t\tconst now = runtime.now();\n\t\t\tconst messages: Message[] = [\n\t\t\t\t{ role: \"system\", content: SUMMARIZATION_SYSTEM_PROMPT, timestamp: now },\n\t\t\t\t{\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: [{ type: \"text\", text: summaryPrompt(summarizedMessages(view, cut), task.input.instructions) }],\n\t\t\t\t\ttimestamp: now,\n\t\t\t\t},\n\t\t\t];\n\t\t\tconst { deferred: _deferred, ...forwarded } = streamOptions;\n\t\t\tconst options: SimpleStreamOptions = {\n\t\t\t\t...forwarded,\n\t\t\t\tcacheRetention: \"none\",\n\t\t\t\tmaxTokens,\n\t\t\t\tsignal: runtime.signal,\n\t\t\t\tsessionId: await ensureProviderSessionId(runtime, context),\n\t\t\t\t...(thinkingLevel === \"off\" ? {} : { reasoning: thinkingLevel }),\n\t\t\t};\n\t\t\tconst message = await runtime.models.completeSimple(model, { messages }, options);\n\t\t\t// An abort mark or close: the abort invocation or the reopened task handles the committed state.\n\t\t\truntime.signal.throwIfAborted();\n\t\t\tconst summary = summaryText(message);\n\t\t\tconst policy = runtime.settings.retry;\n\t\t\tconst retry =\n\t\t\t\tmessage.stopReason === \"error\" &&\n\t\t\t\tisRetryableAssistantError(message) &&\n\t\t\t\tpolicy.enabled &&\n\t\t\t\tattempt <= policy.maxRetries;\n\t\t\tconst until = retry ? runtime.now() + retryDelayMs(policy, attempt) : 0;\n\t\t\tawait runtime.commit(async (tx, current): Promise<Next> => {\n\t\t\t\tawait recordUsage(\n\t\t\t\t\ttx,\n\t\t\t\t\truntime.conversationId,\n\t\t\t\t\t\"models\",\n\t\t\t\t\t`${message.provider}/${message.model}`,\n\t\t\t\t\tmessage.usage,\n\t\t\t\t);\n\t\t\t\tconst live = await tx.doc(LiveDoc, runtime.conversationId);\n\t\t\t\tif (summary !== undefined) return placeSummary(tx, runtime, current, live, firstKept, summary);\n\t\t\t\tif (retry) {\n\t\t\t\t\tconst status = compactionStatus(live, runtime.taskId);\n\t\t\t\t\tif (status !== undefined) status.retry = { at: until, error: message.errorMessage ?? \"\" };\n\t\t\t\t\treturn { status: \"running\", checkpoint: { phase: \"retry\", ...request, until } };\n\t\t\t\t}\n\t\t\t\tremoveCompactionStatus(live, runtime.taskId);\n\t\t\t\tconst text = summaryFailure(message);\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"terminal\",\n\t\t\t\t\toutcome: { status: \"failed\", error: { message: text, detail: { reason: \"model_error\" } } },\n\t\t\t\t};\n\t\t\t}, context);\n\t\t},\n\t\tretry: async (task, runtime, context) => {\n\t\t\tconst { phase: _, until, ...request } = task.state.checkpoint;\n\t\t\tawait runtime.sleep(until, context);\n\t\t\tconst attempt = request.attempt + 1;\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tconst status = compactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\t\tif (status !== undefined) {\n\t\t\t\t\tstatus.attempt = attempt;\n\t\t\t\t\tdelete status.retry;\n\t\t\t\t}\n\t\t\t\treturn { status: \"running\", checkpoint: { phase: \"summarize\", ...request, attempt } };\n\t\t\t}, context);\n\t\t},\n\t},\n\tabort: async (_task, runtime, context) => {\n\t\tawait runtime.commit(async (tx) => {\n\t\t\tremoveCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\treturn { status: \"terminal\", outcome: { status: \"aborted\" } };\n\t\t}, context);\n\t},\n});\n\n/**\n * Create a compaction task with its status in this commit. `owner` is the generation that waits for it (a blocking\n * compaction); without one it is conversation-owned, and `background` unless it is manual.\n */\nexport async function createCompaction(\n\ttx: Tx,\n\tconversationId: ConversationId,\n\tinput: CompactionInput,\n\towner?: TaskId,\n): Promise<TaskId<CompactionResult>> {\n\tconst ownership =\n\t\towner === undefined ? ({ kind: \"conversation\" } as const) : { kind: \"task\" as const, taskId: owner };\n\tconst background = owner === undefined && input.reason !== \"manual\";\n\tconst taskId = await tx.createTask(CompactionTask, input, { ownership, conversationId, background });\n\tconst status = { taskId, reason: input.reason, blocking: owner !== undefined, attempt: 1 };\n\taddCompactionStatus(await tx.doc(LiveDoc, conversationId), status);\n\treturn taskId;\n}\n\n/**\n * Index in `view.entries` of the first entry a summary keeps, or `undefined` when there is nothing to compact\n * (spec §8.7). Walks back from the tail until `keepRecentTokens` are kept, then cuts at the first candidate at or after\n * that entry: an entry whose contribution starts with a user or assistant message, never a tool result, and never a\n * user entry that a result of the preceding assistant's calls still follows.\n */\nexport function selectCut(view: ContextView, keepRecentTokens: number): number | undefined {\n\tconst { contributions } = view;\n\tconst start = view.head === undefined ? 0 : 1;\n\tconst candidates: number[] = [];\n\tfor (let index = start; index < contributions.length; index++) {\n\t\tif (isCandidate(contributions, index)) candidates.push(index);\n\t}\n\tlet kept = 0;\n\tlet cut: number | undefined;\n\tfor (let index = contributions.length - 1; index >= start; index--) {\n\t\tfor (const message of contributions[index]!) kept += estimateMessageTokens(message);\n\t\tif (kept < keepRecentTokens) continue;\n\t\tcut = candidates.find((candidate) => candidate >= index) ?? candidates.at(-1);\n\t\tbreak;\n\t}\n\tif (cut === undefined) return undefined;\n\tfor (let index = start; index < cut; index++) if (contributions[index]!.length > 0) return cut;\n\treturn undefined;\n}\n\nfunction isCandidate(contributions: ContextView[\"contributions\"], index: number): boolean {\n\tconst first = contributions[index]![0];\n\tif (first?.role === \"assistant\") return true;\n\tif (first?.role !== \"user\") return false;\n\t// A result of the preceding assistant's calls that follows this entry, before the next assistant, belongs before it.\n\tlet calls: ReadonlySet<string> = new Set();\n\tfor (let before = index - 1; before >= 0; before--) {\n\t\tconst assistant = contributions[before]!.findLast((message) => message.role === \"assistant\");\n\t\tif (assistant === undefined) continue;\n\t\tcalls = new Set(assistant.content.flatMap((content) => (content.type === \"toolCall\" ? [content.id] : [])));\n\t\tbreak;\n\t}\n\tif (calls.size === 0) return true;\n\tfor (let after = index; after < contributions.length; after++) {\n\t\tfor (const [position, message] of contributions[after]!.entries()) {\n\t\t\tif (message.role === \"assistant\" && (after > index || position > 0)) return true;\n\t\t\tif (message.role === \"toolResult\" && calls.has(message.toolCallId)) return false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/** Model messages of the entries before `cut`: the head marker first, ordered like model context (spec §2.1). */\nexport function summarizedMessages(view: ContextView, cut: number): Message[] {\n\treturn orderToolResults(view.contributions.slice(0, cut).flat());\n}\n\n/**\n * Size of a request over `view` followed by `extra` (spec §8.3): the usage of the newest assistant appended after the\n * head marker, whose request included the marker, plus estimates of the messages after it; without one, estimates of\n * every message.\n */\nexport function estimateContext(view: ContextView, extra: readonly Message[]): number {\n\tlet measured: AssistantMessage | undefined;\n\tconst after = view.head?.id ?? Number.NEGATIVE_INFINITY;\n\tfor (let index = view.entries.length - 1; index >= 0 && measured === undefined; index--) {\n\t\tif (view.entries[index]!.id <= after) continue;\n\t\tmeasured = view.contributions[index]!.findLast(\n\t\t\t(message): message is AssistantMessage =>\n\t\t\t\tmessage.role === \"assistant\" && calculateContextTokens(message.usage) > 0,\n\t\t);\n\t}\n\tconst from = measured === undefined ? 0 : view.messages.lastIndexOf(measured) + 1;\n\tlet tokens = measured === undefined ? 0 : calculateContextTokens(measured.usage);\n\tfor (const message of view.messages.slice(from)) tokens += estimateMessageTokens(message);\n\tfor (const message of extra) tokens += estimateMessageTokens(message);\n\treturn tokens;\n}\n\n/** The summary of a clean `stop` with text and no tool call; anything else is not a summary. */\nfunction summaryText(message: AssistantMessage): string | undefined {\n\tif (message.stopReason !== \"stop\" || message.content.some((content) => content.type === \"toolCall\"))\n\t\treturn undefined;\n\tconst text = message.content\n\t\t.flatMap((content) => (content.type === \"text\" ? [content.text] : []))\n\t\t.join(\"\\n\")\n\t\t.trim();\n\treturn text.length === 0 ? undefined : text;\n}\n\nfunction summaryFailure(message: AssistantMessage): string {\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") {\n\t\treturn `Summarization failed: ${message.errorMessage ?? message.stopReason}`;\n\t}\n\tif (message.stopReason === \"length\") return \"Summarization hit the token limit; the summary is incomplete\";\n\tif (message.content.some((content) => content.type === \"toolCall\")) return \"Summarization attempted to call a tool\";\n\treturn \"Summarization produced no text\";\n}\n\n/** The summarizer's user message: the serialized conversation, the prompt, and any instructions. */\nfunction summaryPrompt(messages: readonly Message[], instructions: string | undefined): string {\n\tconst focus = instructions === undefined ? \"\" : `\\n\\nAdditional focus: ${instructions}`;\n\treturn `<conversation>\\n${serializeConversation(messages)}\\n</conversation>\\n\\n${SUMMARIZATION_PROMPT}${focus}`;\n}\n\n/** Messages as plain text, so the summarizer reads a transcript instead of continuing it. System messages are omitted. */\nexport function serializeConversation(messages: readonly Message[]): string {\n\tconst parts: string[] = [];\n\tfor (const message of messages) {\n\t\tif (message.role === \"user\") {\n\t\t\tconst text = contentText(message.content);\n\t\t\tif (text.length > 0) parts.push(`[User]: ${text}`);\n\t\t} else if (message.role === \"assistant\") {\n\t\t\tconst thinking = message.content.flatMap((content) => (content.type === \"thinking\" ? [content.thinking] : []));\n\t\t\tconst text = message.content.flatMap((content) => (content.type === \"text\" ? [content.text] : []));\n\t\t\tconst calls = message.content.flatMap((content) =>\n\t\t\t\tcontent.type === \"toolCall\"\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t`${content.name}(${Object.entries(content.arguments)\n\t\t\t\t\t\t\t\t.map(([key, value]) => `${key}=${JSON.stringify(value)}`)\n\t\t\t\t\t\t\t\t.join(\", \")})`,\n\t\t\t\t\t\t]\n\t\t\t\t\t: [],\n\t\t\t);\n\t\t\tif (thinking.length > 0) parts.push(`[Assistant thinking]: ${thinking.join(\"\\n\")}`);\n\t\t\tif (text.length > 0) parts.push(`[Assistant]: ${text.join(\"\\n\")}`);\n\t\t\tif (calls.length > 0) parts.push(`[Assistant tool calls]: ${calls.join(\"; \")}`);\n\t\t} else if (message.role === \"toolResult\") {\n\t\t\tconst text = contentText(message.content);\n\t\t\tif (text.length > 0) parts.push(`[Tool result]: ${truncate(text, TOOL_RESULT_MAX_CHARS)}`);\n\t\t}\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction contentText(content: string | readonly { readonly type: string; readonly text?: string }[]): string {\n\tif (typeof content === \"string\") return content;\n\treturn content\n\t\t.flatMap((block) => (block.type === \"text\" && block.text !== undefined ? [block.text] : []))\n\t\t.join(\"\\n\");\n}\n\nfunction truncate(text: string, maxChars: number): string {\n\tif (text.length <= maxChars) return text;\n\treturn `${text.slice(0, maxChars)}\\n\\n[... ${text.length - maxChars} more characters truncated]`;\n}\n\n/** Place a summary supplied by a hook in its own commit. */\nasync function place(runtime: Runtime, firstKept: EntryId, summary: string, context: Context): Promise<void> {\n\tawait runtime.commit(\n\t\tasync (tx, current) =>\n\t\t\tplaceSummary(tx, runtime, current, await tx.doc(LiveDoc, runtime.conversationId), firstKept, summary),\n\t\tcontext,\n\t);\n}\n\n/**\n * Place the summary entry and complete (spec §8.7). A blocking compaction, owned by its generation, appends it: the\n * generation holds the run and waits. A conversation-owned one admits it as a write submission, placed at once when\n * idle, otherwise at the next boundary, or settled `stale`.\n * REMINDER: nothing else may append to a busy conversation, so every non-blocking summary goes through admission.\n */\nasync function placeSummary(\n\ttx: Tx,\n\truntime: Runtime,\n\tcurrent: RunningTask<CompactionInput, CompactionCheckpoint, CompactionResult>,\n\tlive: Draft<LiveState>,\n\tfirstKept: EntryId,\n\tsummary: string,\n): Promise<Next> {\n\tremoveCompactionStatus(live, runtime.taskId);\n\tconst text = `${SUMMARY_PREFIX}${summary}${SUMMARY_SUFFIX}`;\n\tconst entry = {\n\t\tkind: CompactionEntry.kind,\n\t\thead: firstKept,\n\t\tmodel: [{ role: \"user\", content: [{ type: \"text\", text }], timestamp: runtime.now() }],\n\t\tdata: { reason: current.input.reason },\n\t} satisfies EntryDraft;\n\tconst result: CompactionResult =\n\t\tcurrent.owner === undefined\n\t\t\t? {\n\t\t\t\t\tsubmissionId: await admitSubmission(\n\t\t\t\t\t\ttx,\n\t\t\t\t\t\truntime.conversationId,\n\t\t\t\t\t\t{ type: \"write\", requestId: `compaction:${runtime.taskId}`, entry },\n\t\t\t\t\t\truntime.now(),\n\t\t\t\t\t\truntime.settings,\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: { entryId: (await tx.appendEntry(runtime.conversationId, entry)).id };\n\treturn { status: \"terminal\", outcome: { status: \"completed\", result } };\n}\n\n/** Remove the status and complete without a summary. */\nasync function complete(runtime: Runtime, context: Context): Promise<void> {\n\tawait runtime.commit(async (tx) => {\n\t\tremoveCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\treturn { status: \"terminal\", outcome: { status: \"completed\", result: {} } };\n\t}, context);\n}\n\nasync function failNoModel(runtime: Runtime, ref: ModelRef | undefined, context: Context): Promise<void> {\n\tconst message =\n\t\tref === undefined ? \"No model is configured\" : `Model ${ref.provider}/${ref.modelId} is not available`;\n\tawait runtime.commit(async (tx) => {\n\t\tremoveCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\treturn { status: \"terminal\", outcome: { status: \"failed\", error: { message, detail: { reason: \"no_model\" } } } };\n\t}, context);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../src/harness/compaction.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage, Message, ModelThinkingLevel, SimpleStreamOptions } from \"@ny4n/ai/contracts\";\nimport { calculateContextTokens, estimateMessageTokens } from \"@ny4n/ai/utils/estimate\";\nimport { isRetryableAssistantError, retryDelayMs } from \"@ny4n/ai/utils/retry\";\nimport type { Context, Draft } from \"@ny4n/chord\";\nimport { CompactionEntry } from \"../entries.ts\";\nimport { defineTask } from \"../tasks.ts\";\nimport type {\n\tConversationId,\n\tEntryDraft,\n\tEntryId,\n\tNextTaskState,\n\tRunningTask,\n\tTaskId,\n\tTaskRuntime,\n\tTx,\n} from \"../types.ts\";\nimport { orderToolResults } from \"./context.ts\";\nimport {\n\taddCompactionStatus,\n\tcompactionStatus,\n\tfailCompactionStatus,\n\tLiveDoc,\n\ttype LiveState,\n\tremoveCompactionStatus,\n} from \"./live.ts\";\nimport { ensureProviderSessionId } from \"./provider.ts\";\nimport { admitSubmission } from \"./submissions.ts\";\nimport type {\n\tCompactionHooks,\n\tCompactionReason,\n\tCompactionResult,\n\tContextView,\n\tConversationStreamOptions,\n\tModelRef,\n} from \"./types.ts\";\nimport { recordUsage } from \"./usage.ts\";\n\nexport type CompactionInput = { reason: CompactionReason; instructions?: string };\n\n/** The pinned summarization request. */\nexport type SummaryRequest = {\n\tattempt: number;\n\tmodel: ModelRef;\n\tthinkingLevel: ModelThinkingLevel;\n\tstreamOptions: ConversationStreamOptions;\n\tmaxTokens: number;\n\t/** Newest entry of the context the range was selected from. */\n\ttail: EntryId;\n\t/** First entry kept verbatim; the summary's `head`. */\n\tfirstKept: EntryId;\n};\n\nexport type CompactionCheckpoint =\n\t| { phase: \"select\" }\n\t| ({ phase: \"summarize\" } & SummaryRequest)\n\t| ({ phase: \"retry\"; until: number } & SummaryRequest);\n\ntype Runtime = TaskRuntime<CompactionInput, CompactionCheckpoint, CompactionResult, CompactionHooks>;\ntype Next = NextTaskState<CompactionCheckpoint, CompactionResult>;\n\n/** Longest tool result text a serialized summary source keeps. */\nconst TOOL_RESULT_MAX_CHARS = 2000;\n\nconst SUMMARY_PREFIX =\n\t\"The conversation history before this point was compacted into the following summary:\\n\\n<summary>\\n\";\nconst SUMMARY_SUFFIX = \"\\n</summary>\";\n\nconst SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;\n\nconst SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work. If the conversation starts with an earlier summary, preserve its information and fold the newer messages into it.\n\nUse this EXACT format:\n\n## Goal\n[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned by user]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Current work]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Next Steps\n1. [Ordered list of what should happen next]\n\n## Critical Context\n- [Any data, examples, or references needed to continue]\n- [Or \"(none)\" if not applicable]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\n/**\n * Built-in compaction task (spec §8.7): select an old prefix of the model context, summarize it, and place a summary\n * entry whose `head` is the first kept entry. A compaction the generation owns blocks it and appends directly; a\n * conversation-owned one places its summary through a write submission.\n */\nexport const CompactionTask = defineTask<CompactionInput, CompactionCheckpoint, CompactionResult, CompactionHooks>({\n\tname: \"nyan.compaction\",\n\tversion: 1,\n\tinitial: () => ({ phase: \"select\" }),\n\tphases: {\n\t\tselect: async (task, runtime, context) => {\n\t\t\tconst { conversationId } = runtime;\n\t\t\tconst agent = await runtime.agent(context);\n\t\t\tconst settings = runtime.settings;\n\t\t\tconst ref = agent.model;\n\t\t\tconst model = ref === undefined ? undefined : runtime.models.getModel(ref.provider, ref.modelId);\n\t\t\tif (ref === undefined || model === undefined) return failNoModel(runtime, ref, context);\n\t\t\tconst policy = settings.compaction;\n\t\t\tconst view = await runtime.context(conversationId, context);\n\t\t\tconst cut = selectCut(view, policy.keepRecentTokens);\n\t\t\tif (cut === undefined) return complete(runtime, context);\n\t\t\tconst firstKept = view.entries[cut]!.id;\n\t\t\tconst { reason, instructions } = task.input;\n\t\t\tconst compaction = {\n\t\t\t\treason,\n\t\t\t\tentries: view.entries.slice(0, cut),\n\t\t\t\tmessages: summarizedMessages(view, cut),\n\t\t\t\tfirstKept,\n\t\t\t\t...(instructions === undefined ? {} : { instructions }),\n\t\t\t};\n\t\t\tlet decision: { readonly decline: true } | { readonly summary: string } | undefined;\n\t\t\tawait runtime.hooks.each(\"beforeCompact\", async (hook) => {\n\t\t\t\tif (decision === undefined) decision = await hook(compaction, runtime, context);\n\t\t\t});\n\t\t\tif (decision !== undefined && \"decline\" in decision) return complete(runtime, context);\n\t\t\tif (decision !== undefined) return place(runtime, firstKept, decision.summary, context);\n\t\t\tconst request: SummaryRequest = {\n\t\t\t\tattempt: 1,\n\t\t\t\tmodel: ref,\n\t\t\t\tthinkingLevel: agent.thinkingLevel,\n\t\t\t\tstreamOptions: settings.stream,\n\t\t\t\tmaxTokens: Math.min(\n\t\t\t\t\tMath.floor(0.8 * policy.reserveTokens),\n\t\t\t\t\tmodel.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY,\n\t\t\t\t),\n\t\t\t\ttail: view.entries.reduce((tail, entry) => (entry.id > tail ? entry.id : tail), firstKept),\n\t\t\t\tfirstKept,\n\t\t\t};\n\t\t\tawait runtime.commit(() => ({ status: \"running\", checkpoint: { phase: \"summarize\", ...request } }), context);\n\t\t},\n\t\tsummarize: async (task, runtime, context) => {\n\t\t\tconst { phase: _, ...request } = task.state.checkpoint;\n\t\t\tconst { model: ref, thinkingLevel, streamOptions, maxTokens, tail, firstKept, attempt } = request;\n\t\t\tconst model = runtime.models.getModel(ref.provider, ref.modelId);\n\t\t\tif (model === undefined) return failNoModel(runtime, ref, context);\n\t\t\t// The context at `tail` is immutable, so this is the range `select` chose.\n\t\t\tconst view = await runtime.context(runtime.conversationId, context, { at: tail });\n\t\t\tconst cut = view.entries.findIndex((entry) => entry.id === firstKept);\n\t\t\tconst now = runtime.now();\n\t\t\tconst messages: Message[] = [\n\t\t\t\t{ role: \"system\", content: SUMMARIZATION_SYSTEM_PROMPT, timestamp: now },\n\t\t\t\t{\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: [{ type: \"text\", text: summaryPrompt(summarizedMessages(view, cut), task.input.instructions) }],\n\t\t\t\t\ttimestamp: now,\n\t\t\t\t},\n\t\t\t];\n\t\t\tconst { deferred: _deferred, ...forwarded } = streamOptions;\n\t\t\tconst options: SimpleStreamOptions = {\n\t\t\t\t...forwarded,\n\t\t\t\tcacheRetention: \"none\",\n\t\t\t\tmaxTokens,\n\t\t\t\tsignal: runtime.signal,\n\t\t\t\tsessionId: await ensureProviderSessionId(runtime, context),\n\t\t\t\t...(thinkingLevel === \"off\" ? {} : { reasoning: thinkingLevel }),\n\t\t\t};\n\t\t\tconst message = await runtime.models.completeSimple(model, { messages }, options);\n\t\t\t// An abort mark or close: the abort invocation or the reopened task handles the committed state.\n\t\t\truntime.signal.throwIfAborted();\n\t\t\tconst summary = summaryText(message);\n\t\t\tconst policy = runtime.settings.retry;\n\t\t\tconst retry =\n\t\t\t\tmessage.stopReason === \"error\" &&\n\t\t\t\tisRetryableAssistantError(message) &&\n\t\t\t\tpolicy.enabled &&\n\t\t\t\tattempt <= policy.maxRetries;\n\t\t\tconst until = retry ? runtime.now() + retryDelayMs(policy, attempt) : 0;\n\t\t\tawait runtime.commit(async (tx, current): Promise<Next> => {\n\t\t\t\tawait recordUsage(\n\t\t\t\t\ttx,\n\t\t\t\t\truntime.conversationId,\n\t\t\t\t\t\"models\",\n\t\t\t\t\t`${message.provider}/${message.model}`,\n\t\t\t\t\tmessage.usage,\n\t\t\t\t);\n\t\t\t\tconst live = await tx.doc(LiveDoc, runtime.conversationId);\n\t\t\t\tif (summary !== undefined) return placeSummary(tx, runtime, current, live, firstKept, summary);\n\t\t\t\tif (retry) {\n\t\t\t\t\tconst status = compactionStatus(live, runtime.taskId);\n\t\t\t\t\tif (status !== undefined) status.retry = { at: until, error: message.errorMessage ?? \"\" };\n\t\t\t\t\treturn { status: \"running\", checkpoint: { phase: \"retry\", ...request, until } };\n\t\t\t\t}\n\t\t\t\tconst text = summaryFailure(message);\n\t\t\t\tfailCompactionStatus(live, runtime.taskId, text);\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"terminal\",\n\t\t\t\t\toutcome: { status: \"failed\", error: { message: text, detail: { reason: \"model_error\" } } },\n\t\t\t\t};\n\t\t\t}, context);\n\t\t},\n\t\tretry: async (task, runtime, context) => {\n\t\t\tconst { phase: _, until, ...request } = task.state.checkpoint;\n\t\t\tawait runtime.sleep(until, context);\n\t\t\tconst attempt = request.attempt + 1;\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tconst status = compactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\t\tif (status !== undefined) {\n\t\t\t\t\tstatus.attempt = attempt;\n\t\t\t\t\tdelete status.retry;\n\t\t\t\t}\n\t\t\t\treturn { status: \"running\", checkpoint: { phase: \"summarize\", ...request, attempt } };\n\t\t\t}, context);\n\t\t},\n\t},\n\tabort: async (_task, runtime, context) => {\n\t\tawait runtime.commit(async (tx) => {\n\t\t\tremoveCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\treturn { status: \"terminal\", outcome: { status: \"aborted\" } };\n\t\t}, context);\n\t},\n});\n\n/**\n * Create a compaction task with its status in this commit. `owner` is the generation that waits for it (a blocking\n * compaction); without one it is conversation-owned, and `background` unless it is manual.\n */\nexport async function createCompaction(\n\ttx: Tx,\n\tconversationId: ConversationId,\n\tinput: CompactionInput,\n\towner?: TaskId,\n): Promise<TaskId<CompactionResult>> {\n\tconst ownership =\n\t\towner === undefined ? ({ kind: \"conversation\" } as const) : { kind: \"task\" as const, taskId: owner };\n\tconst background = owner === undefined && input.reason !== \"manual\";\n\tconst taskId = await tx.createTask(CompactionTask, input, { ownership, conversationId, background });\n\tconst status = { taskId, reason: input.reason, blocking: owner !== undefined, attempt: 1 };\n\taddCompactionStatus(await tx.doc(LiveDoc, conversationId), status);\n\treturn taskId;\n}\n\n/**\n * Index in `view.entries` of the first entry a summary keeps, or `undefined` when there is nothing to compact\n * (spec §8.7). Walks back from the tail until `keepRecentTokens` are kept, then cuts at the first candidate at or after\n * that entry: an entry whose contribution starts with a user or assistant message, never a tool result, and never a\n * user entry that a result of the preceding assistant's calls still follows.\n */\nexport function selectCut(view: ContextView, keepRecentTokens: number): number | undefined {\n\tconst { contributions } = view;\n\tconst start = view.head === undefined ? 0 : 1;\n\tconst candidates: number[] = [];\n\tfor (let index = start; index < contributions.length; index++) {\n\t\tif (isCandidate(contributions, index)) candidates.push(index);\n\t}\n\tlet kept = 0;\n\tlet cut: number | undefined;\n\tfor (let index = contributions.length - 1; index >= start; index--) {\n\t\tfor (const message of contributions[index]!) kept += estimateMessageTokens(message);\n\t\tif (kept < keepRecentTokens) continue;\n\t\tcut = candidates.find((candidate) => candidate >= index) ?? candidates.at(-1);\n\t\tbreak;\n\t}\n\tif (cut === undefined) return undefined;\n\tfor (let index = start; index < cut; index++) if (contributions[index]!.length > 0) return cut;\n\treturn undefined;\n}\n\nfunction isCandidate(contributions: ContextView[\"contributions\"], index: number): boolean {\n\tconst first = contributions[index]![0];\n\tif (first?.role === \"assistant\") return true;\n\tif (first?.role !== \"user\") return false;\n\t// A result of the preceding assistant's calls that follows this entry, before the next assistant, belongs before it.\n\tlet calls: ReadonlySet<string> = new Set();\n\tfor (let before = index - 1; before >= 0; before--) {\n\t\tconst assistant = contributions[before]!.findLast((message) => message.role === \"assistant\");\n\t\tif (assistant === undefined) continue;\n\t\tcalls = new Set(assistant.content.flatMap((content) => (content.type === \"toolCall\" ? [content.id] : [])));\n\t\tbreak;\n\t}\n\tif (calls.size === 0) return true;\n\tfor (let after = index; after < contributions.length; after++) {\n\t\tfor (const [position, message] of contributions[after]!.entries()) {\n\t\t\tif (message.role === \"assistant\" && (after > index || position > 0)) return true;\n\t\t\tif (message.role === \"toolResult\" && calls.has(message.toolCallId)) return false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/** Model messages of the entries before `cut`: the head marker first, ordered like model context (spec §2.1). */\nexport function summarizedMessages(view: ContextView, cut: number): Message[] {\n\treturn orderToolResults(view.contributions.slice(0, cut).flat());\n}\n\n/**\n * Size of a request over `view` followed by `extra` (spec §8.3): the usage of the newest assistant appended after the\n * head marker, whose request included the marker, plus estimates of the messages after it; without one, estimates of\n * every message.\n */\nexport function estimateContext(view: ContextView, extra: readonly Message[]): number {\n\tlet measured: AssistantMessage | undefined;\n\tconst after = view.head?.id ?? Number.NEGATIVE_INFINITY;\n\tfor (let index = view.entries.length - 1; index >= 0 && measured === undefined; index--) {\n\t\tif (view.entries[index]!.id <= after) continue;\n\t\tmeasured = view.contributions[index]!.findLast(\n\t\t\t(message): message is AssistantMessage =>\n\t\t\t\tmessage.role === \"assistant\" && calculateContextTokens(message.usage) > 0,\n\t\t);\n\t}\n\tconst from = measured === undefined ? 0 : view.messages.lastIndexOf(measured) + 1;\n\tlet tokens = measured === undefined ? 0 : calculateContextTokens(measured.usage);\n\tfor (const message of view.messages.slice(from)) tokens += estimateMessageTokens(message);\n\tfor (const message of extra) tokens += estimateMessageTokens(message);\n\treturn tokens;\n}\n\n/** The summary of a clean `stop` with text and no tool call; anything else is not a summary. */\nfunction summaryText(message: AssistantMessage): string | undefined {\n\tif (message.stopReason !== \"stop\" || message.content.some((content) => content.type === \"toolCall\"))\n\t\treturn undefined;\n\tconst text = message.content\n\t\t.flatMap((content) => (content.type === \"text\" ? [content.text] : []))\n\t\t.join(\"\\n\")\n\t\t.trim();\n\treturn text.length === 0 ? undefined : text;\n}\n\nfunction summaryFailure(message: AssistantMessage): string {\n\tif (message.stopReason === \"error\" || message.stopReason === \"aborted\") {\n\t\treturn `Summarization failed: ${message.errorMessage ?? message.stopReason}`;\n\t}\n\tif (message.stopReason === \"length\") return \"Summarization hit the token limit; the summary is incomplete\";\n\tif (message.content.some((content) => content.type === \"toolCall\")) return \"Summarization attempted to call a tool\";\n\treturn \"Summarization produced no text\";\n}\n\n/** The summarizer's user message: the serialized conversation, the prompt, and any instructions. */\nfunction summaryPrompt(messages: readonly Message[], instructions: string | undefined): string {\n\tconst focus = instructions === undefined ? \"\" : `\\n\\nAdditional focus: ${instructions}`;\n\treturn `<conversation>\\n${serializeConversation(messages)}\\n</conversation>\\n\\n${SUMMARIZATION_PROMPT}${focus}`;\n}\n\n/**\n * Messages as plain text, so the summarizer reads a transcript instead of continuing it. System messages are omitted.\n * Thinking is omitted too: providers return summaries of the real reasoning, and replayed thinking is often not part of\n * the live context (a block that does not match its request is dropped), so including it can make the request larger\n * than the context it summarizes. Visible text, tool calls, and tool results record what happened.\n */\nexport function serializeConversation(messages: readonly Message[]): string {\n\tconst parts: string[] = [];\n\tfor (const message of messages) {\n\t\tif (message.role === \"user\") {\n\t\t\tconst text = contentText(message.content);\n\t\t\tif (text.length > 0) parts.push(`[User]: ${text}`);\n\t\t} else if (message.role === \"assistant\") {\n\t\t\tconst text = message.content.flatMap((content) => (content.type === \"text\" ? [content.text] : []));\n\t\t\tconst calls = message.content.flatMap((content) =>\n\t\t\t\tcontent.type === \"toolCall\"\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t`${content.name}(${Object.entries(content.arguments)\n\t\t\t\t\t\t\t\t.map(([key, value]) => `${key}=${JSON.stringify(value)}`)\n\t\t\t\t\t\t\t\t.join(\", \")})`,\n\t\t\t\t\t\t]\n\t\t\t\t\t: [],\n\t\t\t);\n\t\t\tif (text.length > 0) parts.push(`[Assistant]: ${text.join(\"\\n\")}`);\n\t\t\tif (calls.length > 0) parts.push(`[Assistant tool calls]: ${calls.join(\"; \")}`);\n\t\t} else if (message.role === \"toolResult\") {\n\t\t\tconst text = contentText(message.content);\n\t\t\tif (text.length > 0) parts.push(`[Tool result]: ${truncate(text, TOOL_RESULT_MAX_CHARS)}`);\n\t\t}\n\t}\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction contentText(content: string | readonly { readonly type: string; readonly text?: string }[]): string {\n\tif (typeof content === \"string\") return content;\n\treturn content\n\t\t.flatMap((block) => (block.type === \"text\" && block.text !== undefined ? [block.text] : []))\n\t\t.join(\"\\n\");\n}\n\nfunction truncate(text: string, maxChars: number): string {\n\tif (text.length <= maxChars) return text;\n\treturn `${text.slice(0, maxChars)}\\n\\n[... ${text.length - maxChars} more characters truncated]`;\n}\n\n/** Place a summary supplied by a hook in its own commit. */\nasync function place(runtime: Runtime, firstKept: EntryId, summary: string, context: Context): Promise<void> {\n\tawait runtime.commit(\n\t\tasync (tx, current) =>\n\t\t\tplaceSummary(tx, runtime, current, await tx.doc(LiveDoc, runtime.conversationId), firstKept, summary),\n\t\tcontext,\n\t);\n}\n\n/**\n * Place the summary entry and complete (spec §8.7). A blocking compaction, owned by its generation, appends it: the\n * generation holds the run and waits. A conversation-owned one admits it as a write submission, placed at once when\n * idle, otherwise at the next boundary, or settled `stale`.\n * REMINDER: nothing else may append to a busy conversation, so every non-blocking summary goes through admission.\n */\nasync function placeSummary(\n\ttx: Tx,\n\truntime: Runtime,\n\tcurrent: RunningTask<CompactionInput, CompactionCheckpoint, CompactionResult>,\n\tlive: Draft<LiveState>,\n\tfirstKept: EntryId,\n\tsummary: string,\n): Promise<Next> {\n\tremoveCompactionStatus(live, runtime.taskId);\n\tdelete live.compactionFailure;\n\tconst text = `${SUMMARY_PREFIX}${summary}${SUMMARY_SUFFIX}`;\n\tconst entry = {\n\t\tkind: CompactionEntry.kind,\n\t\thead: firstKept,\n\t\tmodel: [{ role: \"user\", content: [{ type: \"text\", text }], timestamp: runtime.now() }],\n\t\tdata: { reason: current.input.reason },\n\t} satisfies EntryDraft;\n\tconst result: CompactionResult =\n\t\tcurrent.owner === undefined\n\t\t\t? {\n\t\t\t\t\tsubmissionId: await admitSubmission(\n\t\t\t\t\t\ttx,\n\t\t\t\t\t\truntime.conversationId,\n\t\t\t\t\t\t{ type: \"write\", requestId: `compaction:${runtime.taskId}`, entry },\n\t\t\t\t\t\truntime.now(),\n\t\t\t\t\t\truntime.settings,\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: { entryId: (await tx.appendEntry(runtime.conversationId, entry)).id };\n\treturn { status: \"terminal\", outcome: { status: \"completed\", result } };\n}\n\n/** Remove the status and complete without a summary. */\nasync function complete(runtime: Runtime, context: Context): Promise<void> {\n\tawait runtime.commit(async (tx) => {\n\t\tremoveCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\treturn { status: \"terminal\", outcome: { status: \"completed\", result: {} } };\n\t}, context);\n}\n\nasync function failNoModel(runtime: Runtime, ref: ModelRef | undefined, context: Context): Promise<void> {\n\tconst message =\n\t\tref === undefined ? \"No model is configured\" : `Model ${ref.provider}/${ref.modelId} is not available`;\n\tawait runtime.commit(async (tx) => {\n\t\tfailCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId, message);\n\t\treturn { status: \"terminal\", outcome: { status: \"failed\", error: { message, detail: { reason: \"no_model\" } } } };\n\t}, context);\n}\n"]}
|
package/dist/harness/events.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AssistantMessage, Message, Usage } from "@ny4n/ai/contracts";
|
|
|
2
2
|
import type { Context, JsonValue } from "@ny4n/chord";
|
|
3
3
|
import type { ConversationId, EntryRecord, JsonObject, SubmissionId, SubmissionRecord, TaskId, WatchEnd } from "../types.ts";
|
|
4
4
|
import type { InboxItem } from "./inbox.ts";
|
|
5
|
-
import type { CompactionStatus, NestedToolSlot, ToolSlot } from "./live.ts";
|
|
5
|
+
import type { CompactionFailure, CompactionStatus, NestedToolSlot, ToolSlot } from "./live.ts";
|
|
6
6
|
import type { AgentState, CompactionReason, Harness, NestedToolExecutionResult, ToolDiagnostic } from "./types.ts";
|
|
7
7
|
import { type UsageState } from "./usage.ts";
|
|
8
8
|
type Block = AssistantMessage["content"][number];
|
|
@@ -55,6 +55,8 @@ export type SnapshotEvent = {
|
|
|
55
55
|
nestedTools: readonly NestedToolSlot[];
|
|
56
56
|
/** `nyan.live.compactions`: live compactions with their attempt and retry backoff. */
|
|
57
57
|
compactions: readonly CompactionStatus[];
|
|
58
|
+
/** `nyan.live.compactionFailure`: the newest compaction failure since a compaction last produced a summary. */
|
|
59
|
+
compactionFailure?: CompactionFailure;
|
|
58
60
|
inbox: readonly QueuedItem[];
|
|
59
61
|
/** `nyan.agent`; `{}` when absent. */
|
|
60
62
|
agent: AgentState;
|
|
@@ -144,11 +146,15 @@ export type AgentEvent = SnapshotEvent | {
|
|
|
144
146
|
reason: CompactionReason;
|
|
145
147
|
blocking: boolean;
|
|
146
148
|
}
|
|
147
|
-
/**
|
|
149
|
+
/**
|
|
150
|
+
* The task's receipt tells whether it produced a summary; the summary entry has its own events. `error` is set when
|
|
151
|
+
* the compaction failed, faulted, or was orphaned, as in `nyan.live.compactionFailure`.
|
|
152
|
+
*/
|
|
148
153
|
| {
|
|
149
154
|
type: "compaction_end";
|
|
150
155
|
taskId: TaskId;
|
|
151
156
|
reason: CompactionReason;
|
|
157
|
+
error?: string;
|
|
152
158
|
};
|
|
153
159
|
/**
|
|
154
160
|
* Which call a tool event is about. `toolCallId` is the call's ID in the transcript and in tool events: the provider's
|