@ny4n/durable 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +711 -2
- package/dist/documents.d.ts +66 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +98 -0
- package/dist/documents.js.map +1 -0
- package/dist/entries.d.ts +31 -0
- package/dist/entries.d.ts.map +1 -0
- package/dist/entries.js +31 -0
- package/dist/entries.js.map +1 -0
- package/dist/env/decode.d.ts +16 -0
- package/dist/env/decode.d.ts.map +1 -0
- package/dist/env/decode.js +28 -0
- package/dist/env/decode.js.map +1 -0
- package/dist/env/index.d.ts +263 -0
- package/dist/env/index.d.ts.map +1 -0
- package/dist/env/index.js +49 -0
- package/dist/env/index.js.map +1 -0
- package/dist/env/line-scan.d.ts +13 -0
- package/dist/env/line-scan.d.ts.map +1 -0
- package/dist/env/line-scan.js +147 -0
- package/dist/env/line-scan.js.map +1 -0
- package/dist/env/node-watch.d.ts +29 -0
- package/dist/env/node-watch.d.ts.map +1 -0
- package/dist/env/node-watch.js +485 -0
- package/dist/env/node-watch.js.map +1 -0
- package/dist/env/node.d.ts +56 -0
- package/dist/env/node.d.ts.map +1 -0
- package/dist/env/node.js +1166 -0
- package/dist/env/node.js.map +1 -0
- package/dist/errors.d.ts +32 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +53 -0
- package/dist/errors.js.map +1 -0
- package/dist/harness/agent.d.ts +33 -0
- package/dist/harness/agent.d.ts.map +1 -0
- package/dist/harness/agent.js +235 -0
- package/dist/harness/agent.js.map +1 -0
- package/dist/harness/assistant.d.ts +15 -0
- package/dist/harness/assistant.d.ts.map +1 -0
- package/dist/harness/assistant.js +23 -0
- package/dist/harness/assistant.js.map +1 -0
- package/dist/harness/compaction.d.ts +56 -0
- package/dist/harness/compaction.d.ts.map +1 -0
- package/dist/harness/compaction.js +384 -0
- package/dist/harness/compaction.js.map +1 -0
- package/dist/harness/context.d.ts +63 -0
- package/dist/harness/context.d.ts.map +1 -0
- package/dist/harness/context.js +221 -0
- package/dist/harness/context.js.map +1 -0
- package/dist/harness/define.d.ts +18 -0
- package/dist/harness/define.d.ts.map +1 -0
- package/dist/harness/define.js +25 -0
- package/dist/harness/define.js.map +1 -0
- package/dist/harness/events.d.ts +180 -0
- package/dist/harness/events.d.ts.map +1 -0
- package/dist/harness/events.js +370 -0
- package/dist/harness/events.js.map +1 -0
- package/dist/harness/generation.d.ts +54 -0
- package/dist/harness/generation.d.ts.map +1 -0
- package/dist/harness/generation.js +514 -0
- package/dist/harness/generation.js.map +1 -0
- package/dist/harness/harness.d.ts +17 -0
- package/dist/harness/harness.d.ts.map +1 -0
- package/dist/harness/harness.js +332 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/harness/inbox.d.ts +59 -0
- package/dist/harness/inbox.d.ts.map +1 -0
- package/dist/harness/inbox.js +97 -0
- package/dist/harness/inbox.js.map +1 -0
- package/dist/harness/json.d.ts +10 -0
- package/dist/harness/json.d.ts.map +1 -0
- package/dist/harness/json.js +33 -0
- package/dist/harness/json.js.map +1 -0
- package/dist/harness/live.d.ts +142 -0
- package/dist/harness/live.d.ts.map +1 -0
- package/dist/harness/live.js +149 -0
- package/dist/harness/live.js.map +1 -0
- package/dist/harness/output.d.ts +69 -0
- package/dist/harness/output.d.ts.map +1 -0
- package/dist/harness/output.js +318 -0
- package/dist/harness/output.js.map +1 -0
- package/dist/harness/prompt.d.ts +27 -0
- package/dist/harness/prompt.d.ts.map +1 -0
- package/dist/harness/prompt.js +131 -0
- package/dist/harness/prompt.js.map +1 -0
- package/dist/harness/provider.d.ts +14 -0
- package/dist/harness/provider.d.ts.map +1 -0
- package/dist/harness/provider.js +30 -0
- package/dist/harness/provider.js.map +1 -0
- package/dist/harness/registry.d.ts +6 -0
- package/dist/harness/registry.d.ts.map +1 -0
- package/dist/harness/registry.js +101 -0
- package/dist/harness/registry.js.map +1 -0
- package/dist/harness/run.d.ts +17 -0
- package/dist/harness/run.d.ts.map +1 -0
- package/dist/harness/run.js +26 -0
- package/dist/harness/run.js.map +1 -0
- package/dist/harness/scheduler.d.ts +106 -0
- package/dist/harness/scheduler.d.ts.map +1 -0
- package/dist/harness/scheduler.js +1743 -0
- package/dist/harness/scheduler.js.map +1 -0
- package/dist/harness/submissions.d.ts +29 -0
- package/dist/harness/submissions.d.ts.map +1 -0
- package/dist/harness/submissions.js +175 -0
- package/dist/harness/submissions.js.map +1 -0
- package/dist/harness/task-graph.d.ts +49 -0
- package/dist/harness/task-graph.d.ts.map +1 -0
- package/dist/harness/task-graph.js +168 -0
- package/dist/harness/task-graph.js.map +1 -0
- package/dist/harness/tool.d.ts +76 -0
- package/dist/harness/tool.d.ts.map +1 -0
- package/dist/harness/tool.js +736 -0
- package/dist/harness/tool.js.map +1 -0
- package/dist/harness/types.d.ts +713 -0
- package/dist/harness/types.d.ts.map +1 -0
- package/dist/harness/types.js +2 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/harness/usage.d.ts +18 -0
- package/dist/harness/usage.d.ts.map +1 -0
- package/dist/harness/usage.js +57 -0
- package/dist/harness/usage.js.map +1 -0
- package/dist/harness/util.d.ts +19 -0
- package/dist/harness/util.d.ts.map +1 -0
- package/dist/harness/util.js +58 -0
- package/dist/harness/util.js.map +1 -0
- package/dist/harness/view.d.ts +47 -0
- package/dist/harness/view.d.ts.map +1 -0
- package/dist/harness/view.js +206 -0
- package/dist/harness/view.js.map +1 -0
- package/dist/ids.d.ts +6 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +9 -0
- package/dist/ids.js.map +1 -0
- package/dist/images/cloudflare.d.ts +4 -0
- package/dist/images/cloudflare.d.ts.map +1 -0
- package/dist/images/cloudflare.js +9 -0
- package/dist/images/cloudflare.js.map +1 -0
- package/dist/images/exif.d.ts +3 -0
- package/dist/images/exif.d.ts.map +1 -0
- package/dist/images/exif.js +71 -0
- package/dist/images/exif.js.map +1 -0
- package/dist/images/index.d.ts +18 -0
- package/dist/images/index.d.ts.map +1 -0
- package/dist/images/index.js +125 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/node-worker.d.ts +17 -0
- package/dist/images/node-worker.d.ts.map +1 -0
- package/dist/images/node-worker.js +16 -0
- package/dist/images/node-worker.js.map +1 -0
- package/dist/images/node.d.ts +21 -0
- package/dist/images/node.d.ts.map +1 -0
- package/dist/images/node.js +121 -0
- package/dist/images/node.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/session/forks.d.ts +10 -0
- package/dist/session/forks.d.ts.map +1 -0
- package/dist/session/forks.js +42 -0
- package/dist/session/forks.js.map +1 -0
- package/dist/session/observation.d.ts +42 -0
- package/dist/session/observation.d.ts.map +1 -0
- package/dist/session/observation.js +281 -0
- package/dist/session/observation.js.map +1 -0
- package/dist/session/session.d.ts +133 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +811 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/transaction.d.ts +119 -0
- package/dist/session/transaction.d.ts.map +1 -0
- package/dist/session/transaction.js +795 -0
- package/dist/session/transaction.js.map +1 -0
- package/dist/storage/jsonl/index.d.ts +2 -0
- package/dist/storage/jsonl/index.d.ts.map +1 -0
- package/dist/storage/jsonl/index.js +2 -0
- package/dist/storage/jsonl/index.js.map +1 -0
- package/dist/storage/jsonl/node.d.ts +6 -0
- package/dist/storage/jsonl/node.d.ts.map +1 -0
- package/dist/storage/jsonl/node.js +8 -0
- package/dist/storage/jsonl/node.js.map +1 -0
- package/dist/storage/jsonl/storage.d.ts +143 -0
- package/dist/storage/jsonl/storage.d.ts.map +1 -0
- package/dist/storage/jsonl/storage.js +682 -0
- package/dist/storage/jsonl/storage.js.map +1 -0
- package/dist/storage/memory.d.ts +62 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +733 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/scan.d.ts +18 -0
- package/dist/storage/scan.d.ts.map +1 -0
- package/dist/storage/scan.js +29 -0
- package/dist/storage/scan.js.map +1 -0
- package/dist/storage/sqlite/cloudflare.d.ts +46 -0
- package/dist/storage/sqlite/cloudflare.d.ts.map +1 -0
- package/dist/storage/sqlite/cloudflare.js +106 -0
- package/dist/storage/sqlite/cloudflare.js.map +1 -0
- package/dist/storage/sqlite/database.d.ts +37 -0
- package/dist/storage/sqlite/database.d.ts.map +1 -0
- package/dist/storage/sqlite/database.js +2 -0
- package/dist/storage/sqlite/database.js.map +1 -0
- package/dist/storage/sqlite/index.d.ts +4 -0
- package/dist/storage/sqlite/index.d.ts.map +1 -0
- package/dist/storage/sqlite/index.js +3 -0
- package/dist/storage/sqlite/index.js.map +1 -0
- package/dist/storage/sqlite/migrations.d.ts +11 -0
- package/dist/storage/sqlite/migrations.d.ts.map +1 -0
- package/dist/storage/sqlite/migrations.js +111 -0
- package/dist/storage/sqlite/migrations.js.map +1 -0
- package/dist/storage/sqlite/node.d.ts +41 -0
- package/dist/storage/sqlite/node.d.ts.map +1 -0
- package/dist/storage/sqlite/node.js +179 -0
- package/dist/storage/sqlite/node.js.map +1 -0
- package/dist/storage/sqlite/storage.d.ts +65 -0
- package/dist/storage/sqlite/storage.d.ts.map +1 -0
- package/dist/storage/sqlite/storage.js +670 -0
- package/dist/storage/sqlite/storage.js.map +1 -0
- package/dist/tasks.d.ts +6 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +5 -0
- package/dist/tasks.js.map +1 -0
- package/dist/testing/assertions.d.ts +5 -0
- package/dist/testing/assertions.d.ts.map +1 -0
- package/dist/testing/assertions.js +25 -0
- package/dist/testing/assertions.js.map +1 -0
- package/dist/testing/env-conformance.d.ts +7 -0
- package/dist/testing/env-conformance.d.ts.map +1 -0
- package/dist/testing/env-conformance.js +431 -0
- package/dist/testing/env-conformance.js.map +1 -0
- package/dist/testing/index.d.ts +7 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +6 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/runner.d.ts +12 -0
- package/dist/testing/runner.d.ts.map +1 -0
- package/dist/testing/runner.js +23 -0
- package/dist/testing/runner.js.map +1 -0
- package/dist/testing/storage-benchmark.d.ts +41 -0
- package/dist/testing/storage-benchmark.d.ts.map +1 -0
- package/dist/testing/storage-benchmark.js +350 -0
- package/dist/testing/storage-benchmark.js.map +1 -0
- package/dist/testing/storage-conformance.d.ts +4 -0
- package/dist/testing/storage-conformance.d.ts.map +1 -0
- package/dist/testing/storage-conformance.js +1213 -0
- package/dist/testing/storage-conformance.js.map +1 -0
- package/dist/testing/types.d.ts +37 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +2 -0
- package/dist/testing/types.js.map +1 -0
- package/dist/tools/bash.d.ts +55 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +138 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit-diff.d.ts +89 -0
- package/dist/tools/edit-diff.d.ts.map +1 -0
- package/dist/tools/edit-diff.js +386 -0
- package/dist/tools/edit-diff.js.map +1 -0
- package/dist/tools/edit.d.ts +18 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +117 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/env.d.ts +5 -0
- package/dist/tools/env.d.ts.map +1 -0
- package/dist/tools/env.js +7 -0
- package/dist/tools/env.js.map +1 -0
- package/dist/tools/file-mutation-queue.d.ts +9 -0
- package/dist/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/tools/file-mutation-queue.js +52 -0
- package/dist/tools/file-mutation-queue.js.map +1 -0
- package/dist/tools/image-processor.d.ts +47 -0
- package/dist/tools/image-processor.d.ts.map +1 -0
- package/dist/tools/image-processor.js +30 -0
- package/dist/tools/image-processor.js.map +1 -0
- package/dist/tools/image.d.ts +20 -0
- package/dist/tools/image.d.ts.map +1 -0
- package/dist/tools/image.js +178 -0
- package/dist/tools/image.js.map +1 -0
- package/dist/tools/index.d.ts +46 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +23 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/path-utils.d.ts +5 -0
- package/dist/tools/path-utils.d.ts.map +1 -0
- package/dist/tools/path-utils.js +26 -0
- package/dist/tools/path-utils.js.map +1 -0
- package/dist/tools/read.d.ts +25 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +235 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/write.d.ts +10 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +31 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/truncate.d.ts +64 -0
- package/dist/truncate.d.ts.map +1 -0
- package/dist/truncate.js +154 -0
- package/dist/truncate.js.map +1 -0
- package/dist/types.d.ts +932 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +140 -5
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assign `value` at `target[key]` leaf by leaf. Chord records a container assignment as one full set and only emits an
|
|
3
|
+
* append when a string leaf is reassigned with a longer string, so writing the partial whole would store and publish the
|
|
4
|
+
* complete message on every flush.
|
|
5
|
+
*/
|
|
6
|
+
export function assignJson(target, key, value) {
|
|
7
|
+
const slots = target;
|
|
8
|
+
const current = slots[key];
|
|
9
|
+
if (isRecord(current) && isRecord(value)) {
|
|
10
|
+
for (const name of Object.keys(current))
|
|
11
|
+
if (!Object.hasOwn(value, name))
|
|
12
|
+
delete current[name];
|
|
13
|
+
for (const [name, child] of Object.entries(value))
|
|
14
|
+
assignJson(current, name, child);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(current) && Array.isArray(value) && current.length <= value.length) {
|
|
18
|
+
const items = current;
|
|
19
|
+
for (let index = 0; index < value.length; index++) {
|
|
20
|
+
if (index < items.length)
|
|
21
|
+
assignJson(items, index, value[index]);
|
|
22
|
+
else
|
|
23
|
+
items.push(value[index]);
|
|
24
|
+
}
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (current !== value)
|
|
28
|
+
slots[key] = value;
|
|
29
|
+
}
|
|
30
|
+
function isRecord(value) {
|
|
31
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/harness/json.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,MAAqB,EAAE,GAAoB,EAAE,KAAgB;IACvF,MAAM,KAAK,GAAG,MAA4C,CAAC;IAC3D,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC;gBAAE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/F,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACpF,OAAO;IACR,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACtF,MAAM,KAAK,GAAG,OAAsB,CAAC;QACrC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;YACnD,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM;gBAAE,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAE,CAAC,CAAC;;gBAC7D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAE,CAAC,CAAC;QAChC,CAAC;QACD,OAAO;IACR,CAAC;IACD,IAAI,OAAO,KAAK,KAAK;QAAE,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAC3C,CAAC;AAED,SAAS,QAAQ,CAAC,KAA4B;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import type { JsonValue } from \"@ny4n/chord\";\n\ntype JsonContainer = Record<string, JsonValue> | JsonValue[];\n\n/**\n * Assign `value` at `target[key]` leaf by leaf. Chord records a container assignment as one full set and only emits an\n * append when a string leaf is reassigned with a longer string, so writing the partial whole would store and publish the\n * complete message on every flush.\n */\nexport function assignJson(target: JsonContainer, key: string | number, value: JsonValue): void {\n\tconst slots = target as Record<string | number, JsonValue>;\n\tconst current = slots[key];\n\tif (isRecord(current) && isRecord(value)) {\n\t\tfor (const name of Object.keys(current)) if (!Object.hasOwn(value, name)) delete current[name];\n\t\tfor (const [name, child] of Object.entries(value)) assignJson(current, name, child);\n\t\treturn;\n\t}\n\tif (Array.isArray(current) && Array.isArray(value) && current.length <= value.length) {\n\t\tconst items = current as JsonValue[];\n\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\tif (index < items.length) assignJson(items, index, value[index]!);\n\t\t\telse items.push(value[index]!);\n\t\t}\n\t\treturn;\n\t}\n\tif (current !== value) slots[key] = value;\n}\n\nfunction isRecord(value: JsonValue | undefined): value is Record<string, JsonValue> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { AssistantMessage, Usage } from "@ny4n/ai/contracts";
|
|
2
|
+
import type { Draft, JsonRepresentation, JsonValue } from "@ny4n/chord";
|
|
3
|
+
import type { Transaction } from "../session/transaction.ts";
|
|
4
|
+
import type { EntryId, JsonObject, SubmissionId, SubmissionSettlement, TaskId, TaskRecord, Tx } from "../types.ts";
|
|
5
|
+
import type { SchedulerOutcome } from "./scheduler.ts";
|
|
6
|
+
import type { CompactionReason, CompactionResult, ToolDiagnostic } from "./types.ts";
|
|
7
|
+
/** What a running tool call publishes, shared by model-issued and nested calls. */
|
|
8
|
+
type SlotProgress = {
|
|
9
|
+
callId: string;
|
|
10
|
+
name: string;
|
|
11
|
+
status: "pending" | "running" | "done";
|
|
12
|
+
/** Retained running output and what the bounds dropped. */
|
|
13
|
+
output?: string;
|
|
14
|
+
droppedBytes?: number;
|
|
15
|
+
droppedLines?: number;
|
|
16
|
+
/** Last `details()` value. */
|
|
17
|
+
details?: JsonValue;
|
|
18
|
+
/** Diagnostics recorded through `api.diagnostic()`. */
|
|
19
|
+
diagnostics?: ToolDiagnostic[];
|
|
20
|
+
};
|
|
21
|
+
/** Presentation of one tool call of the current round. */
|
|
22
|
+
export type ToolSlot = SlotProgress & {
|
|
23
|
+
/**
|
|
24
|
+
* Absent for a call not started yet (sequential round) and for a call its request did not offer, which starts `done`
|
|
25
|
+
* with the `entry` generation wrote.
|
|
26
|
+
*/
|
|
27
|
+
taskId?: TaskId;
|
|
28
|
+
/** Result entry once done; absent when the tool task faulted or was orphaned. */
|
|
29
|
+
entry?: EntryId;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Presentation of one nested call: a call a running tool made through `executeTool()`. `callId` is
|
|
33
|
+
* `<parentCallId>/<key>`, the call's ID in tool events and unique because keys contain no `/`. The Harness relates
|
|
34
|
+
* slots by task ID: `taskId` is the call's tool task, `parentTaskId` the calling one, model-issued or nested.
|
|
35
|
+
*/
|
|
36
|
+
export type NestedToolSlot = SlotProgress & {
|
|
37
|
+
parentCallId: string;
|
|
38
|
+
parentTaskId: TaskId;
|
|
39
|
+
taskId: TaskId;
|
|
40
|
+
/**
|
|
41
|
+
* What the call was made with, replaced by the arguments it runs with, after repair, `beforeTool`, and coercion,
|
|
42
|
+
* once it starts executing. A model-issued call's arguments are in its assistant entry instead.
|
|
43
|
+
*/
|
|
44
|
+
arguments: JsonObject;
|
|
45
|
+
/** Once done: how the call ended, for a status line. The result itself is in the caller's `NestedCallDoc`. */
|
|
46
|
+
summary?: NestedToolSummary;
|
|
47
|
+
};
|
|
48
|
+
/** How a nested call ended: an error flag, its execution time, its spend, and up to 500 characters of error text. */
|
|
49
|
+
export type NestedToolSummary = {
|
|
50
|
+
isError: boolean;
|
|
51
|
+
durationMs?: number;
|
|
52
|
+
usage?: JsonRepresentation<Usage>;
|
|
53
|
+
error?: string;
|
|
54
|
+
};
|
|
55
|
+
/** Presentation of one live compaction task (spec §8.7). */
|
|
56
|
+
export type CompactionStatus = {
|
|
57
|
+
taskId: TaskId<CompactionResult>;
|
|
58
|
+
reason: CompactionReason;
|
|
59
|
+
/** Whether a generation waits for it: a compaction the generation owns. */
|
|
60
|
+
blocking: boolean;
|
|
61
|
+
attempt: number;
|
|
62
|
+
/** Durable backoff before the next summarization attempt. */
|
|
63
|
+
retry?: {
|
|
64
|
+
at: number;
|
|
65
|
+
error: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
/** Built-in live conversation state: run control and presentation of the current generation and tool round. */
|
|
69
|
+
export type LiveState = {
|
|
70
|
+
/** Run control: the task that settles the run's inputs, and those inputs; present exactly while busy. */
|
|
71
|
+
run?: {
|
|
72
|
+
taskId: TaskId;
|
|
73
|
+
inputs: SubmissionId[];
|
|
74
|
+
};
|
|
75
|
+
/** Presentation of the current generation attempt. */
|
|
76
|
+
generation?: {
|
|
77
|
+
attempt: number;
|
|
78
|
+
/** Committed throttled partial of the in-flight response. */
|
|
79
|
+
message?: JsonRepresentation<AssistantMessage>;
|
|
80
|
+
/** Durable backoff before the next attempt. */
|
|
81
|
+
retry?: {
|
|
82
|
+
at: number;
|
|
83
|
+
error: string;
|
|
84
|
+
};
|
|
85
|
+
/** Provider-side deferred response being polled. */
|
|
86
|
+
deferred?: {
|
|
87
|
+
pollAt: number;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
/** The current tool round in call order, from the tool-calling answer until the generation's `tools` phase ends it. */
|
|
91
|
+
tools?: ToolSlot[];
|
|
92
|
+
/**
|
|
93
|
+
* Nested calls of running tool calls, in creation order, so a parent precedes its children and task IDs ascend. A
|
|
94
|
+
* call's nested slots are removed when the call settles.
|
|
95
|
+
*/
|
|
96
|
+
nestedTools?: NestedToolSlot[];
|
|
97
|
+
/** Live compaction tasks in task ID order; absent when none. */
|
|
98
|
+
compactions?: CompactionStatus[];
|
|
99
|
+
};
|
|
100
|
+
export declare const LiveDoc: import("../types.ts").ConversationDocToken<LiveState>;
|
|
101
|
+
/**
|
|
102
|
+
* End the run owned by `taskId`: settle each of its inputs and remove `run`. Always removes `generation`, `tools`, and
|
|
103
|
+
* `nestedTools`, whose presentation belongs to the ending run.
|
|
104
|
+
*/
|
|
105
|
+
export declare function endRun(tx: Tx, live: Draft<LiveState>, taskId: TaskId, settlement: SubmissionSettlement): void;
|
|
106
|
+
/** Add the status of a compaction task created in this commit; statuses stay in task ID order. */
|
|
107
|
+
export declare function addCompactionStatus(live: Draft<LiveState>, status: CompactionStatus): void;
|
|
108
|
+
/** The status of compaction task `taskId`, if listed. */
|
|
109
|
+
export declare function compactionStatus(live: Draft<LiveState>, taskId: TaskId): Draft<CompactionStatus> | undefined;
|
|
110
|
+
/** Remove the status of compaction task `taskId`, and the list once empty. */
|
|
111
|
+
export declare function removeCompactionStatus(live: Draft<LiveState>, taskId: TaskId): void;
|
|
112
|
+
/**
|
|
113
|
+
* The slot of tool task `taskId`, model-issued or nested, if `nyan.live` still lists it. Nested slots are found by binary
|
|
114
|
+
* search: a tool may make thousands of nested calls, each of which looks up its slot in several commits, and every
|
|
115
|
+
* element a search reads costs a node in the draft's change tracker. Their task IDs ascend: each slot is appended in
|
|
116
|
+
* the commit that creates its task, task IDs ascend in commit order, and removal keeps the order.
|
|
117
|
+
*/
|
|
118
|
+
export declare function toolSlot(live: Draft<LiveState>, taskId: TaskId): Draft<ToolSlot | NestedToolSlot> | undefined;
|
|
119
|
+
/**
|
|
120
|
+
* Mark a slot done and clear its running output; the caller sets a model-issued call's result `entry`, or a nested
|
|
121
|
+
* call's `summary`. Neither is set when the task faulted or was orphaned.
|
|
122
|
+
*/
|
|
123
|
+
export declare function finishSlot(slot: Draft<ToolSlot | NestedToolSlot>): void;
|
|
124
|
+
/** Remove the nested slots below tool task `taskId`, transitively; the list holds parents before their children. */
|
|
125
|
+
export declare function removeNestedSlots(live: Draft<LiveState>, taskId: TaskId): void;
|
|
126
|
+
/** Remove what a tool published while running; its result entry or a rerun replaces it. */
|
|
127
|
+
export declare function clearProgress(slot: Draft<SlotProgress>): void;
|
|
128
|
+
/**
|
|
129
|
+
* Harness cleanup for a terminal outcome the scheduler writes itself (`faulted` or `orphaned`). A run task ends its
|
|
130
|
+
* run; a tool task's slot is marked done without an entry, and context derivation synthesizes the missing result; a
|
|
131
|
+
* compaction task's status is removed.
|
|
132
|
+
* Ignores other kinds so it never creates `nyan.live` elsewhere. The scheduler calls this without knowing task kinds;
|
|
133
|
+
* the Harness passes it in (spec §5.4).
|
|
134
|
+
* REMINDER: a committed generation partial becomes an aborted assistant entry here, exactly as in the generation abort
|
|
135
|
+
* handler, so the transcript keeps what the model produced and `nyan.usage` counts its spend. The scheduler's commit has
|
|
136
|
+
* no task scope, so that entry has no `byTaskId`. Faults come from task bugs
|
|
137
|
+
* or malformed provider data (a non-JSON value in a response), or a commit the Storage rejected without effect; an
|
|
138
|
+
* uncertain storage failure poisons the Session instead and writes no outcome.
|
|
139
|
+
*/
|
|
140
|
+
export declare function settleSchedulerOutcome(tx: Transaction, record: TaskRecord<JsonValue, JsonValue, JsonValue>, outcome: SchedulerOutcome): Promise<void>;
|
|
141
|
+
export {};
|
|
142
|
+
//# sourceMappingURL=live.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/harness/live.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { defineDoc } from "../documents.js";
|
|
2
|
+
import { convertPartial } from "./assistant.js";
|
|
3
|
+
export const LiveDoc = defineDoc({
|
|
4
|
+
kind: "nyan.live",
|
|
5
|
+
version: 1,
|
|
6
|
+
scope: "conversation",
|
|
7
|
+
history: "latest",
|
|
8
|
+
fork: "initial",
|
|
9
|
+
initial: () => ({}),
|
|
10
|
+
// REMINDER: a complete base whenever nothing runs (spec §8.2): no generation and no running tool slot. That holds
|
|
11
|
+
// while idle, in the commit handing a generation over to its tool round, and between tools, so the delta chain
|
|
12
|
+
// spans at most one generation or the overlapping execution of one round's tools. A slot holds output only while
|
|
13
|
+
// running, so every base is small; a nested call's result lives in its caller's task documents, never here. Do not
|
|
14
|
+
// add a delta-count bound; the tool output benchmark checks this rule.
|
|
15
|
+
checkpointWhen: (value) => value.generation === undefined &&
|
|
16
|
+
!(value.tools ?? []).some((slot) => slot.status === "running") &&
|
|
17
|
+
!(value.nestedTools ?? []).some((slot) => slot.status === "running"),
|
|
18
|
+
});
|
|
19
|
+
/** Built-in task kinds that can own `nyan.live.run`. */
|
|
20
|
+
const RUN_TASK_KINDS = new Set(["nyan.generation"]);
|
|
21
|
+
const TOOL_TASK_KIND = "nyan.tool";
|
|
22
|
+
const COMPACTION_TASK_KIND = "nyan.compaction";
|
|
23
|
+
/**
|
|
24
|
+
* End the run owned by `taskId`: settle each of its inputs and remove `run`. Always removes `generation`, `tools`, and
|
|
25
|
+
* `nestedTools`, whose presentation belongs to the ending run.
|
|
26
|
+
*/
|
|
27
|
+
export function endRun(tx, live, taskId, settlement) {
|
|
28
|
+
if (live.run?.taskId === taskId) {
|
|
29
|
+
for (const id of live.run.inputs)
|
|
30
|
+
tx.settleSubmission(id, settlement);
|
|
31
|
+
delete live.run;
|
|
32
|
+
}
|
|
33
|
+
delete live.generation;
|
|
34
|
+
delete live.tools;
|
|
35
|
+
delete live.nestedTools;
|
|
36
|
+
}
|
|
37
|
+
/** Add the status of a compaction task created in this commit; statuses stay in task ID order. */
|
|
38
|
+
export function addCompactionStatus(live, status) {
|
|
39
|
+
live.compactions ??= [];
|
|
40
|
+
live.compactions.push(status);
|
|
41
|
+
}
|
|
42
|
+
/** The status of compaction task `taskId`, if listed. */
|
|
43
|
+
export function compactionStatus(live, taskId) {
|
|
44
|
+
return live.compactions?.find((status) => status.taskId === taskId);
|
|
45
|
+
}
|
|
46
|
+
/** Remove the status of compaction task `taskId`, and the list once empty. */
|
|
47
|
+
export function removeCompactionStatus(live, taskId) {
|
|
48
|
+
const statuses = live.compactions;
|
|
49
|
+
if (statuses === undefined)
|
|
50
|
+
return;
|
|
51
|
+
const index = statuses.findIndex((status) => status.taskId === taskId);
|
|
52
|
+
if (index >= 0)
|
|
53
|
+
statuses.splice(index, 1);
|
|
54
|
+
if (statuses.length === 0)
|
|
55
|
+
delete live.compactions;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The slot of tool task `taskId`, model-issued or nested, if `nyan.live` still lists it. Nested slots are found by binary
|
|
59
|
+
* search: a tool may make thousands of nested calls, each of which looks up its slot in several commits, and every
|
|
60
|
+
* element a search reads costs a node in the draft's change tracker. Their task IDs ascend: each slot is appended in
|
|
61
|
+
* the commit that creates its task, task IDs ascend in commit order, and removal keeps the order.
|
|
62
|
+
*/
|
|
63
|
+
export function toolSlot(live, taskId) {
|
|
64
|
+
const slot = live.tools?.find((each) => each.taskId === taskId);
|
|
65
|
+
if (slot !== undefined || live.nestedTools === undefined)
|
|
66
|
+
return slot;
|
|
67
|
+
const nested = live.nestedTools;
|
|
68
|
+
let low = 0;
|
|
69
|
+
let high = nested.length - 1;
|
|
70
|
+
while (low <= high) {
|
|
71
|
+
const middle = (low + high) >>> 1;
|
|
72
|
+
const candidate = nested[middle];
|
|
73
|
+
if (candidate.taskId === taskId)
|
|
74
|
+
return candidate;
|
|
75
|
+
if (candidate.taskId < taskId)
|
|
76
|
+
low = middle + 1;
|
|
77
|
+
else
|
|
78
|
+
high = middle - 1;
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Mark a slot done and clear its running output; the caller sets a model-issued call's result `entry`, or a nested
|
|
84
|
+
* call's `summary`. Neither is set when the task faulted or was orphaned.
|
|
85
|
+
*/
|
|
86
|
+
export function finishSlot(slot) {
|
|
87
|
+
slot.status = "done";
|
|
88
|
+
clearProgress(slot);
|
|
89
|
+
}
|
|
90
|
+
/** Remove the nested slots below tool task `taskId`, transitively; the list holds parents before their children. */
|
|
91
|
+
export function removeNestedSlots(live, taskId) {
|
|
92
|
+
const nested = live.nestedTools;
|
|
93
|
+
if (nested === undefined)
|
|
94
|
+
return;
|
|
95
|
+
const removed = new Set([taskId]);
|
|
96
|
+
for (const slot of nested)
|
|
97
|
+
if (removed.has(slot.parentTaskId))
|
|
98
|
+
removed.add(slot.taskId);
|
|
99
|
+
for (let index = nested.length - 1; index >= 0; index--) {
|
|
100
|
+
if (removed.has(nested[index].parentTaskId))
|
|
101
|
+
nested.splice(index, 1);
|
|
102
|
+
}
|
|
103
|
+
if (nested.length === 0)
|
|
104
|
+
delete live.nestedTools;
|
|
105
|
+
}
|
|
106
|
+
/** Remove what a tool published while running; its result entry or a rerun replaces it. */
|
|
107
|
+
export function clearProgress(slot) {
|
|
108
|
+
delete slot.output;
|
|
109
|
+
delete slot.droppedBytes;
|
|
110
|
+
delete slot.droppedLines;
|
|
111
|
+
delete slot.details;
|
|
112
|
+
delete slot.diagnostics;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Harness cleanup for a terminal outcome the scheduler writes itself (`faulted` or `orphaned`). A run task ends its
|
|
116
|
+
* run; a tool task's slot is marked done without an entry, and context derivation synthesizes the missing result; a
|
|
117
|
+
* compaction task's status is removed.
|
|
118
|
+
* Ignores other kinds so it never creates `nyan.live` elsewhere. The scheduler calls this without knowing task kinds;
|
|
119
|
+
* the Harness passes it in (spec §5.4).
|
|
120
|
+
* REMINDER: a committed generation partial becomes an aborted assistant entry here, exactly as in the generation abort
|
|
121
|
+
* handler, so the transcript keeps what the model produced and `nyan.usage` counts its spend. The scheduler's commit has
|
|
122
|
+
* no task scope, so that entry has no `byTaskId`. Faults come from task bugs
|
|
123
|
+
* or malformed provider data (a non-JSON value in a response), or a commit the Storage rejected without effect; an
|
|
124
|
+
* uncertain storage failure poisons the Session instead and writes no outcome.
|
|
125
|
+
*/
|
|
126
|
+
export async function settleSchedulerOutcome(tx, record, outcome) {
|
|
127
|
+
if (record.kind === TOOL_TASK_KIND) {
|
|
128
|
+
const live = await tx.doc(LiveDoc, record.conversationId);
|
|
129
|
+
const slot = toolSlot(live, record.id);
|
|
130
|
+
if (slot !== undefined)
|
|
131
|
+
finishSlot(slot);
|
|
132
|
+
removeNestedSlots(live, record.id);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (record.kind === COMPACTION_TASK_KIND) {
|
|
136
|
+
removeCompactionStatus(await tx.doc(LiveDoc, record.conversationId), record.id);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (!RUN_TASK_KINDS.has(record.kind))
|
|
140
|
+
return;
|
|
141
|
+
const live = await tx.doc(LiveDoc, record.conversationId);
|
|
142
|
+
if (live.run?.taskId !== record.id)
|
|
143
|
+
return;
|
|
144
|
+
await convertPartial(tx, live, record.conversationId);
|
|
145
|
+
endRun(tx, live, record.id, outcome.status === "faulted"
|
|
146
|
+
? { status: "unanswered", reason: "faulted", detail: outcome.error.message }
|
|
147
|
+
: { status: "unanswered", reason: outcome.reason });
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/harness/live.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage, Usage } from \"@ny4n/ai/contracts\";\nimport type { Draft, JsonRepresentation, JsonValue } from \"@ny4n/chord\";\nimport { defineDoc } from \"../documents.ts\";\nimport type { Transaction } from \"../session/transaction.ts\";\nimport type { EntryId, JsonObject, SubmissionId, SubmissionSettlement, TaskId, TaskRecord, Tx } from \"../types.ts\";\nimport { convertPartial } from \"./assistant.ts\";\nimport type { SchedulerOutcome } from \"./scheduler.ts\";\nimport type { CompactionReason, CompactionResult, ToolDiagnostic } from \"./types.ts\";\n\n/** What a running tool call publishes, shared by model-issued and nested calls. */\ntype SlotProgress = {\n\tcallId: string;\n\tname: string;\n\tstatus: \"pending\" | \"running\" | \"done\";\n\t/** Retained running output and what the bounds dropped. */\n\toutput?: string;\n\tdroppedBytes?: number;\n\tdroppedLines?: number;\n\t/** Last `details()` value. */\n\tdetails?: JsonValue;\n\t/** Diagnostics recorded through `api.diagnostic()`. */\n\tdiagnostics?: ToolDiagnostic[];\n};\n\n/** Presentation of one tool call of the current round. */\nexport type ToolSlot = SlotProgress & {\n\t/**\n\t * Absent for a call not started yet (sequential round) and for a call its request did not offer, which starts `done`\n\t * with the `entry` generation wrote.\n\t */\n\ttaskId?: TaskId;\n\t/** Result entry once done; absent when the tool task faulted or was orphaned. */\n\tentry?: EntryId;\n};\n\n/**\n * Presentation of one nested call: a call a running tool made through `executeTool()`. `callId` is\n * `<parentCallId>/<key>`, the call's ID in tool events and unique because keys contain no `/`. The Harness relates\n * slots by task ID: `taskId` is the call's tool task, `parentTaskId` the calling one, model-issued or nested.\n */\nexport type NestedToolSlot = SlotProgress & {\n\tparentCallId: string;\n\tparentTaskId: TaskId;\n\ttaskId: TaskId;\n\t/**\n\t * What the call was made with, replaced by the arguments it runs with, after repair, `beforeTool`, and coercion,\n\t * once it starts executing. A model-issued call's arguments are in its assistant entry instead.\n\t */\n\targuments: JsonObject;\n\t/** Once done: how the call ended, for a status line. The result itself is in the caller's `NestedCallDoc`. */\n\tsummary?: NestedToolSummary;\n};\n\n/** How a nested call ended: an error flag, its execution time, its spend, and up to 500 characters of error text. */\nexport type NestedToolSummary = {\n\tisError: boolean;\n\tdurationMs?: number;\n\tusage?: JsonRepresentation<Usage>;\n\terror?: string;\n};\n\n/** Presentation of one live compaction task (spec §8.7). */\nexport type CompactionStatus = {\n\ttaskId: TaskId<CompactionResult>;\n\treason: CompactionReason;\n\t/** Whether a generation waits for it: a compaction the generation owns. */\n\tblocking: boolean;\n\tattempt: number;\n\t/** Durable backoff before the next summarization attempt. */\n\tretry?: { at: number; error: string };\n};\n\n/** Built-in live conversation state: run control and presentation of the current generation and tool round. */\nexport type LiveState = {\n\t/** Run control: the task that settles the run's inputs, and those inputs; present exactly while busy. */\n\trun?: { taskId: TaskId; inputs: SubmissionId[] };\n\t/** Presentation of the current generation attempt. */\n\tgeneration?: {\n\t\tattempt: number;\n\t\t/** Committed throttled partial of the in-flight response. */\n\t\tmessage?: JsonRepresentation<AssistantMessage>;\n\t\t/** Durable backoff before the next attempt. */\n\t\tretry?: { at: number; error: string };\n\t\t/** Provider-side deferred response being polled. */\n\t\tdeferred?: { pollAt: number };\n\t};\n\t/** The current tool round in call order, from the tool-calling answer until the generation's `tools` phase ends it. */\n\ttools?: ToolSlot[];\n\t/**\n\t * Nested calls of running tool calls, in creation order, so a parent precedes its children and task IDs ascend. A\n\t * call's nested slots are removed when the call settles.\n\t */\n\tnestedTools?: NestedToolSlot[];\n\t/** Live compaction tasks in task ID order; absent when none. */\n\tcompactions?: CompactionStatus[];\n};\n\nexport const LiveDoc = defineDoc<LiveState>({\n\tkind: \"nyan.live\",\n\tversion: 1,\n\tscope: \"conversation\",\n\thistory: \"latest\",\n\tfork: \"initial\",\n\tinitial: () => ({}),\n\t// REMINDER: a complete base whenever nothing runs (spec §8.2): no generation and no running tool slot. That holds\n\t// while idle, in the commit handing a generation over to its tool round, and between tools, so the delta chain\n\t// spans at most one generation or the overlapping execution of one round's tools. A slot holds output only while\n\t// running, so every base is small; a nested call's result lives in its caller's task documents, never here. Do not\n\t// add a delta-count bound; the tool output benchmark checks this rule.\n\tcheckpointWhen: (value) =>\n\t\tvalue.generation === undefined &&\n\t\t!(value.tools ?? []).some((slot) => slot.status === \"running\") &&\n\t\t!(value.nestedTools ?? []).some((slot) => slot.status === \"running\"),\n});\n\n/** Built-in task kinds that can own `nyan.live.run`. */\nconst RUN_TASK_KINDS: ReadonlySet<string> = new Set([\"nyan.generation\"]);\nconst TOOL_TASK_KIND = \"nyan.tool\";\nconst COMPACTION_TASK_KIND = \"nyan.compaction\";\n\n/**\n * End the run owned by `taskId`: settle each of its inputs and remove `run`. Always removes `generation`, `tools`, and\n * `nestedTools`, whose presentation belongs to the ending run.\n */\nexport function endRun(tx: Tx, live: Draft<LiveState>, taskId: TaskId, settlement: SubmissionSettlement): void {\n\tif (live.run?.taskId === taskId) {\n\t\tfor (const id of live.run.inputs) tx.settleSubmission(id, settlement);\n\t\tdelete live.run;\n\t}\n\tdelete live.generation;\n\tdelete live.tools;\n\tdelete live.nestedTools;\n}\n\n/** Add the status of a compaction task created in this commit; statuses stay in task ID order. */\nexport function addCompactionStatus(live: Draft<LiveState>, status: CompactionStatus): void {\n\tlive.compactions ??= [];\n\tlive.compactions.push(status);\n}\n\n/** The status of compaction task `taskId`, if listed. */\nexport function compactionStatus(live: Draft<LiveState>, taskId: TaskId): Draft<CompactionStatus> | undefined {\n\treturn live.compactions?.find((status) => status.taskId === taskId);\n}\n\n/** Remove the status of compaction task `taskId`, and the list once empty. */\nexport function removeCompactionStatus(live: Draft<LiveState>, taskId: TaskId): void {\n\tconst statuses = live.compactions;\n\tif (statuses === undefined) return;\n\tconst index = statuses.findIndex((status) => status.taskId === taskId);\n\tif (index >= 0) statuses.splice(index, 1);\n\tif (statuses.length === 0) delete live.compactions;\n}\n\n/**\n * The slot of tool task `taskId`, model-issued or nested, if `nyan.live` still lists it. Nested slots are found by binary\n * search: a tool may make thousands of nested calls, each of which looks up its slot in several commits, and every\n * element a search reads costs a node in the draft's change tracker. Their task IDs ascend: each slot is appended in\n * the commit that creates its task, task IDs ascend in commit order, and removal keeps the order.\n */\nexport function toolSlot(live: Draft<LiveState>, taskId: TaskId): Draft<ToolSlot | NestedToolSlot> | undefined {\n\tconst slot = live.tools?.find((each) => each.taskId === taskId);\n\tif (slot !== undefined || live.nestedTools === undefined) return slot;\n\tconst nested = live.nestedTools;\n\tlet low = 0;\n\tlet high = nested.length - 1;\n\twhile (low <= high) {\n\t\tconst middle = (low + high) >>> 1;\n\t\tconst candidate = nested[middle]!;\n\t\tif (candidate.taskId === taskId) return candidate;\n\t\tif (candidate.taskId < taskId) low = middle + 1;\n\t\telse high = middle - 1;\n\t}\n\treturn undefined;\n}\n\n/**\n * Mark a slot done and clear its running output; the caller sets a model-issued call's result `entry`, or a nested\n * call's `summary`. Neither is set when the task faulted or was orphaned.\n */\nexport function finishSlot(slot: Draft<ToolSlot | NestedToolSlot>): void {\n\tslot.status = \"done\";\n\tclearProgress(slot);\n}\n\n/** Remove the nested slots below tool task `taskId`, transitively; the list holds parents before their children. */\nexport function removeNestedSlots(live: Draft<LiveState>, taskId: TaskId): void {\n\tconst nested = live.nestedTools;\n\tif (nested === undefined) return;\n\tconst removed = new Set<TaskId>([taskId]);\n\tfor (const slot of nested) if (removed.has(slot.parentTaskId)) removed.add(slot.taskId);\n\tfor (let index = nested.length - 1; index >= 0; index--) {\n\t\tif (removed.has(nested[index]!.parentTaskId)) nested.splice(index, 1);\n\t}\n\tif (nested.length === 0) delete live.nestedTools;\n}\n\n/** Remove what a tool published while running; its result entry or a rerun replaces it. */\nexport function clearProgress(slot: Draft<SlotProgress>): void {\n\tdelete slot.output;\n\tdelete slot.droppedBytes;\n\tdelete slot.droppedLines;\n\tdelete slot.details;\n\tdelete slot.diagnostics;\n}\n\n/**\n * Harness cleanup for a terminal outcome the scheduler writes itself (`faulted` or `orphaned`). A run task ends its\n * run; a tool task's slot is marked done without an entry, and context derivation synthesizes the missing result; a\n * compaction task's status is removed.\n * Ignores other kinds so it never creates `nyan.live` elsewhere. The scheduler calls this without knowing task kinds;\n * the Harness passes it in (spec §5.4).\n * REMINDER: a committed generation partial becomes an aborted assistant entry here, exactly as in the generation abort\n * handler, so the transcript keeps what the model produced and `nyan.usage` counts its spend. The scheduler's commit has\n * no task scope, so that entry has no `byTaskId`. Faults come from task bugs\n * or malformed provider data (a non-JSON value in a response), or a commit the Storage rejected without effect; an\n * uncertain storage failure poisons the Session instead and writes no outcome.\n */\nexport async function settleSchedulerOutcome(\n\ttx: Transaction,\n\trecord: TaskRecord<JsonValue, JsonValue, JsonValue>,\n\toutcome: SchedulerOutcome,\n): Promise<void> {\n\tif (record.kind === TOOL_TASK_KIND) {\n\t\tconst live = await tx.doc(LiveDoc, record.conversationId);\n\t\tconst slot = toolSlot(live, record.id);\n\t\tif (slot !== undefined) finishSlot(slot);\n\t\tremoveNestedSlots(live, record.id);\n\t\treturn;\n\t}\n\tif (record.kind === COMPACTION_TASK_KIND) {\n\t\tremoveCompactionStatus(await tx.doc(LiveDoc, record.conversationId), record.id);\n\t\treturn;\n\t}\n\tif (!RUN_TASK_KINDS.has(record.kind)) return;\n\tconst live = await tx.doc(LiveDoc, record.conversationId);\n\tif (live.run?.taskId !== record.id) return;\n\tawait convertPartial(tx, live, record.conversationId);\n\tendRun(\n\t\ttx,\n\t\tlive,\n\t\trecord.id,\n\t\toutcome.status === \"faulted\"\n\t\t\t? { status: \"unanswered\", reason: \"faulted\", detail: outcome.error.message }\n\t\t\t: { status: \"unanswered\", reason: outcome.reason },\n\t);\n}\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ShellOutputSkip } from "../env/index.ts";
|
|
2
|
+
/** Retention limits of one tool's output. */
|
|
3
|
+
export type OutputLimits = {
|
|
4
|
+
readonly maxBytes: number;
|
|
5
|
+
readonly maxLines: number;
|
|
6
|
+
readonly retain: "head" | "tail";
|
|
7
|
+
};
|
|
8
|
+
/** Retained output and what the limits dropped. */
|
|
9
|
+
export type BoundedOutput = {
|
|
10
|
+
readonly text: string;
|
|
11
|
+
readonly droppedBytes: number;
|
|
12
|
+
readonly droppedLines: number;
|
|
13
|
+
};
|
|
14
|
+
/** An exact slice of the input within the limits, and what it left out. */
|
|
15
|
+
export type OutputSlice = {
|
|
16
|
+
readonly text: string;
|
|
17
|
+
readonly bytes: number;
|
|
18
|
+
readonly droppedBytes: number;
|
|
19
|
+
readonly droppedLines: number;
|
|
20
|
+
};
|
|
21
|
+
/** Remove control characters that break display and transcripts; tabs and newlines stay. */
|
|
22
|
+
export declare function sanitizeOutput(text: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Bound `text` to whole lines within the limits: the first lines for `head`, the last lines for `tail`. The result is an
|
|
25
|
+
* exact slice, trailing newline included. A single line longer than `maxBytes` is cut at the byte limit on a character
|
|
26
|
+
* boundary.
|
|
27
|
+
*/
|
|
28
|
+
export declare function boundOutput(text: string, limits: OutputLimits): OutputSlice;
|
|
29
|
+
/** The last character boundary at or before `index`. */
|
|
30
|
+
export declare function characterEnd(bytes: Uint8Array, index: number): number;
|
|
31
|
+
/**
|
|
32
|
+
* Bounded running output of one tool call. Accepting a chunk costs time proportional to the chunk: head retention stops
|
|
33
|
+
* storing once the window is full, and tail retention drops stored text the window no longer needs when it snapshots.
|
|
34
|
+
* Counts of the whole stream are kept so the dropped totals stay exact.
|
|
35
|
+
*/
|
|
36
|
+
export declare class OutputBuffer {
|
|
37
|
+
#private;
|
|
38
|
+
constructor(limits: OutputLimits);
|
|
39
|
+
/** Bytes currently held; bounded by the limits plus one chunk. */
|
|
40
|
+
get storedBytes(): number;
|
|
41
|
+
/**
|
|
42
|
+
* Accept a chunk; returns whether anything was accepted. `skipped` is output omitted right before the chunk, which
|
|
43
|
+
* must be more than the tail window by at least one byte or line (`ShellOutputInfo.skipped`); only tail retention
|
|
44
|
+
* accepts it.
|
|
45
|
+
*/
|
|
46
|
+
push(chunk: string | Uint8Array, skipped?: ShellOutputSkip): boolean;
|
|
47
|
+
/** Flush an incomplete trailing character as a replacement character; call when the stream ends. */
|
|
48
|
+
end(): void;
|
|
49
|
+
/** Retained, sanitized output and what the limits dropped from the whole stream. */
|
|
50
|
+
snapshot(): BoundedOutput;
|
|
51
|
+
}
|
|
52
|
+
/** Each progress commit also buys a pause proportional to what it wrote. */
|
|
53
|
+
export declare const PROGRESS_BYTES_PER_SECOND: number;
|
|
54
|
+
/**
|
|
55
|
+
* Adaptive progress commits: the first change after an idle period commits at once; each commit then delays the next
|
|
56
|
+
* by at least `minIntervalMs` and by its written size at 100 KiB/s. At most one commit is in flight; changes made
|
|
57
|
+
* meanwhile coalesce into the next one.
|
|
58
|
+
*/
|
|
59
|
+
export declare class Progress {
|
|
60
|
+
#private;
|
|
61
|
+
constructor(write: () => Promise<number>, onError: (error: unknown) => void, minIntervalMs: number);
|
|
62
|
+
/** Schedule a commit. */
|
|
63
|
+
mark(): void;
|
|
64
|
+
/** Schedule a commit; the promise settles with the commit that includes this change. */
|
|
65
|
+
markAndWait(): Promise<void>;
|
|
66
|
+
/** Stop committing and wait for the commit in flight; returns the waiters the final commit must settle. */
|
|
67
|
+
stop(): Promise<PromiseWithResolvers<void>[]>;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/harness/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,6CAA6C;AAC7C,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAEtH,mDAAmD;AACnD,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpH,2EAA2E;AAC3E,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B,CAAC;AAQF,4FAA4F;AAC5F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,WAAW,CAU3E;AA0CD,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrE;AAgBD;;;;GAIG;AACH,qBAAa,YAAY;;IAkBxB,YAAY,MAAM,EAAE,YAAY,EAE/B;IAED,kEAAkE;IAClE,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;;;OAIG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAanE;IAaD,oGAAoG;IACpG,GAAG,IAAI,IAAI,CAEV;IAgCD,oFAAoF;IACpF,QAAQ,IAAI,aAAa,CAoBxB;CACD;AAiCD,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,QAAa,CAAC;AAEpD;;;;GAIG;AACH,qBAAa,QAAQ;;IAWpB,YAAY,KAAK,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EAAE,aAAa,EAAE,MAAM,EAIjG;IAED,yBAAyB;IACzB,IAAI,IAAI,IAAI,CAGX;IAED,wFAAwF;IACxF,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAK3B;IAED,2GAA2G;IACrG,IAAI,IAAI,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC,CAMlD;CAmCD"}
|