@earendil-works/pi-durable 0.99.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +196 -74
  3. package/dist/env/index.d.ts +5 -0
  4. package/dist/env/index.d.ts.map +1 -1
  5. package/dist/env/index.js.map +1 -1
  6. package/dist/env/node.d.ts +2 -0
  7. package/dist/env/node.d.ts.map +1 -1
  8. package/dist/env/node.js +2 -0
  9. package/dist/env/node.js.map +1 -1
  10. package/dist/harness/agent.d.ts +31 -0
  11. package/dist/harness/agent.d.ts.map +1 -0
  12. package/dist/harness/agent.js +209 -0
  13. package/dist/harness/agent.js.map +1 -0
  14. package/dist/harness/compaction.d.ts.map +1 -1
  15. package/dist/harness/compaction.js +8 -11
  16. package/dist/harness/compaction.js.map +1 -1
  17. package/dist/harness/define.d.ts +18 -0
  18. package/dist/harness/define.d.ts.map +1 -0
  19. package/dist/harness/define.js +25 -0
  20. package/dist/harness/define.js.map +1 -0
  21. package/dist/harness/events.d.ts +5 -5
  22. package/dist/harness/events.d.ts.map +1 -1
  23. package/dist/harness/events.js +6 -6
  24. package/dist/harness/events.js.map +1 -1
  25. package/dist/harness/generation.d.ts +2 -4
  26. package/dist/harness/generation.d.ts.map +1 -1
  27. package/dist/harness/generation.js +39 -43
  28. package/dist/harness/generation.js.map +1 -1
  29. package/dist/harness/harness.d.ts.map +1 -1
  30. package/dist/harness/harness.js +68 -154
  31. package/dist/harness/harness.js.map +1 -1
  32. package/dist/harness/inbox.d.ts +4 -2
  33. package/dist/harness/inbox.d.ts.map +1 -1
  34. package/dist/harness/inbox.js +3 -5
  35. package/dist/harness/inbox.js.map +1 -1
  36. package/dist/harness/prompt.d.ts +1 -3
  37. package/dist/harness/prompt.d.ts.map +1 -1
  38. package/dist/harness/prompt.js +1 -11
  39. package/dist/harness/prompt.js.map +1 -1
  40. package/dist/harness/registry.d.ts +2 -3
  41. package/dist/harness/registry.d.ts.map +1 -1
  42. package/dist/harness/registry.js +66 -283
  43. package/dist/harness/registry.js.map +1 -1
  44. package/dist/harness/scheduler.d.ts +7 -2
  45. package/dist/harness/scheduler.d.ts.map +1 -1
  46. package/dist/harness/scheduler.js +41 -27
  47. package/dist/harness/scheduler.js.map +1 -1
  48. package/dist/harness/submissions.d.ts +4 -4
  49. package/dist/harness/submissions.d.ts.map +1 -1
  50. package/dist/harness/submissions.js +7 -4
  51. package/dist/harness/submissions.js.map +1 -1
  52. package/dist/harness/task-graph.d.ts +49 -0
  53. package/dist/harness/task-graph.d.ts.map +1 -0
  54. package/dist/harness/task-graph.js +163 -0
  55. package/dist/harness/task-graph.js.map +1 -0
  56. package/dist/harness/tool.d.ts +1 -1
  57. package/dist/harness/tool.d.ts.map +1 -1
  58. package/dist/harness/tool.js +9 -6
  59. package/dist/harness/tool.js.map +1 -1
  60. package/dist/harness/types.d.ts +171 -140
  61. package/dist/harness/types.d.ts.map +1 -1
  62. package/dist/harness/types.js.map +1 -1
  63. package/dist/harness/view.d.ts +1 -1
  64. package/dist/harness/view.d.ts.map +1 -1
  65. package/dist/harness/view.js +2 -7
  66. package/dist/harness/view.js.map +1 -1
  67. package/dist/index.d.ts +4 -2
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +2 -1
  70. package/dist/index.js.map +1 -1
  71. package/dist/session/session.d.ts.map +1 -1
  72. package/dist/session/session.js +5 -1
  73. package/dist/session/session.js.map +1 -1
  74. package/dist/session/transaction.d.ts +2 -2
  75. package/dist/session/transaction.d.ts.map +1 -1
  76. package/dist/session/transaction.js +7 -4
  77. package/dist/session/transaction.js.map +1 -1
  78. package/dist/storage/sqlite/database.d.ts +26 -19
  79. package/dist/storage/sqlite/database.d.ts.map +1 -1
  80. package/dist/storage/sqlite/database.js.map +1 -1
  81. package/dist/storage/sqlite/index.d.ts +1 -1
  82. package/dist/storage/sqlite/index.d.ts.map +1 -1
  83. package/dist/storage/sqlite/index.js.map +1 -1
  84. package/dist/storage/sqlite/migrations.js +6 -6
  85. package/dist/storage/sqlite/migrations.js.map +1 -1
  86. package/dist/storage/sqlite/node.d.ts +23 -7
  87. package/dist/storage/sqlite/node.d.ts.map +1 -1
  88. package/dist/storage/sqlite/node.js +129 -47
  89. package/dist/storage/sqlite/node.js.map +1 -1
  90. package/dist/storage/sqlite/storage.d.ts +12 -0
  91. package/dist/storage/sqlite/storage.d.ts.map +1 -1
  92. package/dist/storage/sqlite/storage.js +121 -129
  93. package/dist/storage/sqlite/storage.js.map +1 -1
  94. package/dist/tools/bash.d.ts +1 -1
  95. package/dist/tools/bash.d.ts.map +1 -1
  96. package/dist/tools/bash.js +3 -2
  97. package/dist/tools/bash.js.map +1 -1
  98. package/dist/tools/edit.d.ts +3 -3
  99. package/dist/tools/edit.d.ts.map +1 -1
  100. package/dist/tools/edit.js +5 -4
  101. package/dist/tools/edit.js.map +1 -1
  102. package/dist/tools/file-mutation-queue.d.ts +5 -1
  103. package/dist/tools/file-mutation-queue.d.ts.map +1 -1
  104. package/dist/tools/file-mutation-queue.js +39 -33
  105. package/dist/tools/file-mutation-queue.js.map +1 -1
  106. package/dist/tools/index.d.ts +18 -0
  107. package/dist/tools/index.d.ts.map +1 -1
  108. package/dist/tools/index.js +10 -0
  109. package/dist/tools/index.js.map +1 -1
  110. package/dist/tools/read.d.ts +3 -3
  111. package/dist/tools/read.d.ts.map +1 -1
  112. package/dist/tools/read.js +4 -3
  113. package/dist/tools/read.js.map +1 -1
  114. package/dist/tools/write.d.ts +1 -1
  115. package/dist/tools/write.d.ts.map +1 -1
  116. package/dist/tools/write.js +3 -2
  117. package/dist/tools/write.js.map +1 -1
  118. package/dist/types.d.ts +15 -4
  119. package/dist/types.d.ts.map +1 -1
  120. package/dist/types.js.map +1 -1
  121. package/package.json +25 -15
  122. package/dist/harness/config.d.ts +0 -29
  123. package/dist/harness/config.d.ts.map +0 -1
  124. package/dist/harness/config.js +0 -24
  125. package/dist/harness/config.js.map +0 -1
  126. package/docs/chord-delta-findings.md +0 -358
  127. package/docs/pico-v5-chord-usage.md +0 -373
  128. package/docs/pico-v5-handoff.md +0 -861
  129. package/docs/pico-v5.md +0 -4174
@@ -1 +1 @@
1
- {"version":3,"file":"submissions.js","sourceRoot":"","sources":["../../src/harness/submissions.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Context, copyJson, type JsonRepresentation } from \"@earendil-works/chord\";\nimport { UserEntry } from \"../entries.ts\";\nimport { ConversationBusy } from \"../errors.ts\";\nimport type { SessionImpl } from \"../session/session.ts\";\nimport type { Transaction } from \"../session/transaction.ts\";\nimport type {\n\tCommitPublication,\n\tConversationId,\n\tJsonObject,\n\tStorage,\n\tSubmissionId,\n\tSubmissionRecord,\n} from \"../types.ts\";\nimport { startRun } from \"./generation.ts\";\nimport { applyBoundary, InboxDoc, isStale, prepareBoundary, removeInboxItem } from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.ts\";\nimport type { SettledSubmissionRecord, Submission, SubmissionDraft, UserInput } from \"./types.ts\";\nimport { closedError, Waiters } from \"./util.ts\";\n\ntype AbortResult = \"aborted\" | \"already_placed\" | \"settled\";\n\n/** Admission, waits, and withdrawal of the durable submissions of one Harness. */\nexport class Submissions {\n\treadonly #session: SessionImpl;\n\treadonly #storage: Storage;\n\treadonly #now: () => number;\n\t/** Enable task scheduling; submitting or waiting asks for progress. */\n\treadonly #resume: () => void;\n\treadonly #waiters = new Waiters<SubmissionId, SettledSubmissionRecord>();\n\t#closed = false;\n\n\tconstructor(session: SessionImpl, storage: Storage, now: () => number, resume: () => void) {\n\t\tthis.#session = session;\n\t\tthis.#storage = storage;\n\t\tthis.#now = now;\n\t\tthis.#resume = resume;\n\t\tsession.subscribeCommits((publication) => this.#observe(publication));\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tthis.#waiters.rejectAll(closedError());\n\t\t});\n\t}\n\n\t/** Admit a submission in one commit; see `admitSubmission()`. */\n\tasync submit(conversationId: ConversationId, draft: SubmissionDraft, context: Context): Promise<Submission> {\n\t\tthis.#resume();\n\t\tconst id = await this.#session.commitWith(\n\t\t\t(tx) => admitSubmission(tx, conversationId, draft, this.#now()),\n\t\t\tcontext,\n\t\t);\n\t\treturn new SubmissionHandle(id, this);\n\t}\n\n\t/** Handle for an existing submission, or `undefined`. */\n\tasync get(id: SubmissionId, context: Context): Promise<Submission | undefined> {\n\t\tconst record = await this.#session.readOnLine(() => this.#storage.submission(id, context));\n\t\treturn record === undefined ? undefined : new SubmissionHandle(record.id, this);\n\t}\n\n\tasync status(id: SubmissionId, context: Context): Promise<SubmissionRecord> {\n\t\tconst record = await this.#session.readOnLine(() => this.#storage.submission(id, context));\n\t\tif (record === undefined) throw new Error(`Submission ${id} does not exist`);\n\t\treturn record;\n\t}\n\n\tasync wait(id: SubmissionId, context: Context): Promise<SettledSubmissionRecord> {\n\t\tthis.#resume();\n\t\t// Check and register on the line so no settling publication falls between them.\n\t\tconst found = await this.#session.readOnLine(async () => {\n\t\t\tconst record = await this.#storage.submission(id, context);\n\t\t\tif (record === undefined) throw new Error(`Submission ${id} does not exist`);\n\t\t\tif (isSettled(record)) return { promise: Promise.resolve(record) };\n\t\t\t// Close rejects registered waiters synchronously and may begin during the read.\n\t\t\tif (this.#closed) throw closedError();\n\t\t\treturn { promise: this.#waiters.add(id, context) };\n\t\t});\n\t\treturn found.promise;\n\t}\n\n\t/** Withdraw a queued submission and remove its inbox item; placed inputs and settled submissions are reported. */\n\tabort(id: SubmissionId, context: Context, conversationId?: ConversationId): Promise<AbortResult | \"not_found\"> {\n\t\treturn this.#session.commitWith(async (tx) => {\n\t\t\tconst record = await tx.submission(id);\n\t\t\tif (record === undefined || (conversationId !== undefined && record.conversationId !== conversationId)) {\n\t\t\t\treturn \"not_found\";\n\t\t\t}\n\t\t\tif (record.status === \"queued\") {\n\t\t\t\ttx.settleSubmission(id, { status: \"unanswered\", reason: \"aborted\" });\n\t\t\t\tawait removeInboxItem(tx, record.conversationId, id);\n\t\t\t\treturn \"aborted\";\n\t\t\t}\n\t\t\treturn record.status === \"placed\" ? \"already_placed\" : \"settled\";\n\t\t}, context);\n\t}\n\n\t#observe(publication: CommitPublication): void {\n\t\tfor (const change of publication.changes) {\n\t\t\tif (change.type !== \"submission\" || !isSettled(change.value)) continue;\n\t\t\tthis.#waiters.resolve(change.value.id, change.value);\n\t\t}\n\t}\n}\n\nclass SubmissionHandle implements Submission {\n\treadonly id: SubmissionId;\n\treadonly #submissions: Submissions;\n\n\tconstructor(id: SubmissionId, submissions: Submissions) {\n\t\tthis.id = id;\n\t\tthis.#submissions = submissions;\n\t}\n\n\tstatus(context: Context): Promise<SubmissionRecord> {\n\t\treturn this.#submissions.status(this.id, context);\n\t}\n\n\twait(context: Context): Promise<SettledSubmissionRecord> {\n\t\treturn this.#submissions.wait(this.id, context);\n\t}\n\n\tasync abort(context: Context): Promise<AbortResult> {\n\t\tconst result = await this.#submissions.abort(this.id, context);\n\t\tif (result === \"not_found\") throw new Error(`Submission ${this.id} does not exist`);\n\t\treturn result;\n\t}\n}\n\nfunction isSettled(record: SubmissionRecord): record is SettledSubmissionRecord {\n\treturn record.status === \"done\" || record.status === \"unanswered\";\n}\n\n/**\n * Admit a submission inside a commit (spec §6); `Conversation.submit()` and conversation-owned compactions share it. A\n * known request ID returns its existing submission without writing. A busy conversation queues it in `pi.inbox`, or\n * rejects `whenBusy: \"reject\"` input with `ConversationBusy`. An idle conversation with queued items queues it behind\n * them and runs a final boundary. Otherwise idle input places a user entry and starts a run, and an idle write appends\n * its entry and settles `done`, or `stale` when its head reaches before the active range.\n */\nexport async function admitSubmission(\n\ttx: Transaction,\n\tconversationId: ConversationId,\n\tdraft: SubmissionDraft,\n\tnow: number,\n): Promise<SubmissionId> {\n\tif (draft.requestId !== undefined) {\n\t\tconst existing = await tx.submissionByRequest(conversationId, draft.requestId);\n\t\tif (existing !== undefined) {\n\t\t\tif (existing.type !== draft.type) {\n\t\t\t\tthrow new Error(`Request ${draft.requestId} already identifies a submission of type ${existing.type}`);\n\t\t\t}\n\t\t\treturn existing.id;\n\t\t}\n\t}\n\tconst live = await tx.doc(LiveDoc, conversationId);\n\tconst busy = live.run !== undefined;\n\tif (busy && draft.type === \"input\" && draft.whenBusy === \"reject\") throw new ConversationBusy(conversationId);\n\tconst requestId = draft.requestId === undefined ? {} : { requestId: draft.requestId };\n\t// A boundary reads the table, so it is prepared before the first table write; a busy one needs none.\n\tconst boundary = busy ? undefined : await prepareBoundary(tx, conversationId);\n\tif (boundary === undefined || boundary.inbox.items.length > 0) {\n\t\tconst { id } = await tx.createSubmission({\n\t\t\tconversationId,\n\t\t\t...requestId,\n\t\t\ttype: draft.type,\n\t\t\tstatus: \"queued\",\n\t\t});\n\t\t// Hosts may leave optional fields `undefined`; drafts take strict JSON.\n\t\tconst value = copyJson(draft.type === \"write\" ? draft.entry : draft.content, {\n\t\t\tomitUndefinedProperties: true,\n\t\t});\n\t\tconst items = (boundary?.inbox ?? (await tx.doc(InboxDoc, conversationId))).items;\n\t\tif (draft.type === \"write\") items.push({ id, mode: \"write\", entry: value as JsonObject });\n\t\telse {\n\t\t\tconst mode = draft.whenBusy === \"steer\" ? \"steer\" : \"followUp\";\n\t\t\titems.push({ id, mode, content: value as JsonRepresentation<UserInput> });\n\t\t}\n\t\tif (boundary === undefined) return id;\n\t\tconst { users } = await applyBoundary(tx, boundary, \"final\", now);\n\t\tif (users.length > 0) await startRun(tx, conversationId, live, users);\n\t\treturn id;\n\t}\n\tif (draft.type === \"write\") {\n\t\tif (isStale(boundary, draft.entry)) {\n\t\t\tconst stale = { status: \"unanswered\", reason: \"stale\" } as const;\n\t\t\treturn (await tx.createSubmission({ conversationId, ...requestId, type: \"write\", ...stale })).id;\n\t\t}\n\t\tconst entry = await tx.appendEntry(conversationId, draft.entry);\n\t\tconst write = { conversationId, ...requestId, type: \"write\", status: \"done\", entry: entry.id } as const;\n\t\treturn (await tx.createSubmission(write)).id;\n\t}\n\tconst message = { role: \"user\", content: draft.content, timestamp: now } as const;\n\tconst entry = await tx.appendEntry(UserEntry, conversationId, { model: [message] });\n\tconst input = { conversationId, ...requestId, type: \"input\", status: \"placed\", entry: entry.id } as const;\n\tconst { id } = await tx.createSubmission(input);\n\tawait startRun(tx, conversationId, live, [id]);\n\treturn id;\n}\n"]}
1
+ {"version":3,"file":"submissions.js","sourceRoot":"","sources":["../../src/harness/submissions.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Context, copyJson, type JsonRepresentation } from \"@earendil-works/chord\";\nimport { UserEntry } from \"../entries.ts\";\nimport { ConversationBusy } from \"../errors.ts\";\nimport type { SessionImpl } from \"../session/session.ts\";\nimport type {\n\tCommitPublication,\n\tConversationId,\n\tJsonObject,\n\tStorage,\n\tSubmissionId,\n\tSubmissionRecord,\n\tTx,\n} from \"../types.ts\";\nimport { startRun } from \"./generation.ts\";\nimport { applyBoundary, InboxDoc, isStale, prepareBoundary, type QueueModes, removeInboxItem } from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.ts\";\nimport type { SettledSubmissionRecord, Submission, SubmissionDraft, UserInput } from \"./types.ts\";\nimport { closedError, Waiters } from \"./util.ts\";\n\ntype AbortResult = \"aborted\" | \"already_placed\" | \"settled\";\n\n/** Admission, waits, and withdrawal of the durable submissions of one Harness. */\nexport class Submissions {\n\treadonly #session: SessionImpl;\n\treadonly #storage: Storage;\n\treadonly #now: () => number;\n\t/** Read at each admission, on the Session line. */\n\treadonly #queueModes: () => QueueModes;\n\t/** Enable task scheduling; submitting or waiting asks for progress. */\n\treadonly #resume: () => void;\n\treadonly #waiters = new Waiters<SubmissionId, SettledSubmissionRecord>();\n\t#closed = false;\n\n\tconstructor(\n\t\tsession: SessionImpl,\n\t\tstorage: Storage,\n\t\tnow: () => number,\n\t\tqueueModes: () => QueueModes,\n\t\tresume: () => void,\n\t) {\n\t\tthis.#session = session;\n\t\tthis.#storage = storage;\n\t\tthis.#now = now;\n\t\tthis.#queueModes = queueModes;\n\t\tthis.#resume = resume;\n\t\tsession.subscribeCommits((publication) => this.#observe(publication));\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tthis.#waiters.rejectAll(closedError());\n\t\t});\n\t}\n\n\t/** Admit a submission in one commit; see `admitSubmission()`. */\n\tasync submit(conversationId: ConversationId, draft: SubmissionDraft, context: Context): Promise<Submission> {\n\t\tthis.#resume();\n\t\tconst id = await this.#session.commitWith(\n\t\t\t(tx) => admitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes()),\n\t\t\tcontext,\n\t\t);\n\t\treturn new SubmissionHandle(id, this);\n\t}\n\n\t/** Handle for an existing submission, or `undefined`. */\n\tasync get(id: SubmissionId, context: Context): Promise<Submission | undefined> {\n\t\tconst record = await this.#session.readOnLine(() => this.#storage.submission(id, context));\n\t\treturn record === undefined ? undefined : new SubmissionHandle(record.id, this);\n\t}\n\n\tasync status(id: SubmissionId, context: Context): Promise<SubmissionRecord> {\n\t\tconst record = await this.#session.readOnLine(() => this.#storage.submission(id, context));\n\t\tif (record === undefined) throw new Error(`Submission ${id} does not exist`);\n\t\treturn record;\n\t}\n\n\tasync wait(id: SubmissionId, context: Context): Promise<SettledSubmissionRecord> {\n\t\tthis.#resume();\n\t\t// Check and register on the line so no settling publication falls between them.\n\t\tconst found = await this.#session.readOnLine(async () => {\n\t\t\tconst record = await this.#storage.submission(id, context);\n\t\t\tif (record === undefined) throw new Error(`Submission ${id} does not exist`);\n\t\t\tif (isSettled(record)) return { promise: Promise.resolve(record) };\n\t\t\t// Close rejects registered waiters synchronously and may begin during the read.\n\t\t\tif (this.#closed) throw closedError();\n\t\t\treturn { promise: this.#waiters.add(id, context) };\n\t\t});\n\t\treturn found.promise;\n\t}\n\n\t/** Withdraw a queued submission and remove its inbox item; placed inputs and settled submissions are reported. */\n\tabort(id: SubmissionId, context: Context, conversationId?: ConversationId): Promise<AbortResult | \"not_found\"> {\n\t\treturn this.#session.commitWith(async (tx) => {\n\t\t\tconst record = await tx.submission(id);\n\t\t\tif (record === undefined || (conversationId !== undefined && record.conversationId !== conversationId)) {\n\t\t\t\treturn \"not_found\";\n\t\t\t}\n\t\t\tif (record.status === \"queued\") {\n\t\t\t\ttx.settleSubmission(id, { status: \"unanswered\", reason: \"aborted\" });\n\t\t\t\tawait removeInboxItem(tx, record.conversationId, id);\n\t\t\t\treturn \"aborted\";\n\t\t\t}\n\t\t\treturn record.status === \"placed\" ? \"already_placed\" : \"settled\";\n\t\t}, context);\n\t}\n\n\t#observe(publication: CommitPublication): void {\n\t\tfor (const change of publication.changes) {\n\t\t\tif (change.type !== \"submission\" || !isSettled(change.value)) continue;\n\t\t\tthis.#waiters.resolve(change.value.id, change.value);\n\t\t}\n\t}\n}\n\nclass SubmissionHandle implements Submission {\n\treadonly id: SubmissionId;\n\treadonly #submissions: Submissions;\n\n\tconstructor(id: SubmissionId, submissions: Submissions) {\n\t\tthis.id = id;\n\t\tthis.#submissions = submissions;\n\t}\n\n\tstatus(context: Context): Promise<SubmissionRecord> {\n\t\treturn this.#submissions.status(this.id, context);\n\t}\n\n\twait(context: Context): Promise<SettledSubmissionRecord> {\n\t\treturn this.#submissions.wait(this.id, context);\n\t}\n\n\tasync abort(context: Context): Promise<AbortResult> {\n\t\tconst result = await this.#submissions.abort(this.id, context);\n\t\tif (result === \"not_found\") throw new Error(`Submission ${this.id} does not exist`);\n\t\treturn result;\n\t}\n}\n\nfunction isSettled(record: SubmissionRecord): record is SettledSubmissionRecord {\n\treturn record.status === \"done\" || record.status === \"unanswered\";\n}\n\n/**\n * Admit a submission inside a commit (spec §6); `Conversation.submit()` and conversation-owned compactions share it. A\n * known request ID returns its existing submission without writing. A busy conversation queues it in `pi.inbox`, or\n * rejects `whenBusy: \"reject\"` input with `ConversationBusy`. An idle conversation with queued items queues it behind\n * them and runs a final boundary. Otherwise idle input places a user entry and starts a run, and an idle write appends\n * its entry and settles `done`, or `stale` when its head reaches before the active range.\n */\nexport async function admitSubmission(\n\ttx: Tx,\n\tconversationId: ConversationId,\n\tdraft: SubmissionDraft,\n\tnow: number,\n\tqueueModes: QueueModes,\n): Promise<SubmissionId> {\n\tif (draft.requestId !== undefined) {\n\t\tconst existing = await tx.submissionByRequest(conversationId, draft.requestId);\n\t\tif (existing !== undefined) {\n\t\t\tif (existing.type !== draft.type) {\n\t\t\t\tthrow new Error(`Request ${draft.requestId} already identifies a submission of type ${existing.type}`);\n\t\t\t}\n\t\t\treturn existing.id;\n\t\t}\n\t}\n\tconst live = await tx.doc(LiveDoc, conversationId);\n\tconst busy = live.run !== undefined;\n\tif (busy && draft.type === \"input\" && draft.whenBusy === \"reject\") throw new ConversationBusy(conversationId);\n\tconst requestId = draft.requestId === undefined ? {} : { requestId: draft.requestId };\n\t// A boundary reads the table, so it is prepared before the first table write; a busy one needs none.\n\tconst boundary = busy ? undefined : await prepareBoundary(tx, conversationId, queueModes);\n\tif (boundary === undefined || boundary.inbox.items.length > 0) {\n\t\tconst { id } = await tx.createSubmission({\n\t\t\tconversationId,\n\t\t\t...requestId,\n\t\t\ttype: draft.type,\n\t\t\tstatus: \"queued\",\n\t\t});\n\t\t// Hosts may leave optional fields `undefined`; drafts take strict JSON.\n\t\tconst value = copyJson(draft.type === \"write\" ? draft.entry : draft.content, {\n\t\t\tomitUndefinedProperties: true,\n\t\t});\n\t\tconst items = (boundary?.inbox ?? (await tx.doc(InboxDoc, conversationId))).items;\n\t\tif (draft.type === \"write\") items.push({ id, mode: \"write\", entry: value as JsonObject });\n\t\telse {\n\t\t\tconst mode = draft.whenBusy === \"steer\" ? \"steer\" : \"followUp\";\n\t\t\titems.push({ id, mode, content: value as JsonRepresentation<UserInput> });\n\t\t}\n\t\tif (boundary === undefined) return id;\n\t\tconst { users } = await applyBoundary(tx, boundary, \"final\", now);\n\t\tif (users.length > 0) await startRun(tx, conversationId, live, users);\n\t\treturn id;\n\t}\n\tif (draft.type === \"write\") {\n\t\tif (isStale(boundary, draft.entry)) {\n\t\t\tconst stale = { status: \"unanswered\", reason: \"stale\" } as const;\n\t\t\treturn (await tx.createSubmission({ conversationId, ...requestId, type: \"write\", ...stale })).id;\n\t\t}\n\t\tconst entry = await tx.appendEntry(conversationId, draft.entry);\n\t\tconst write = { conversationId, ...requestId, type: \"write\", status: \"done\", entry: entry.id } as const;\n\t\treturn (await tx.createSubmission(write)).id;\n\t}\n\tconst message = { role: \"user\", content: draft.content, timestamp: now } as const;\n\tconst entry = await tx.appendEntry(UserEntry, conversationId, { model: [message] });\n\tconst input = { conversationId, ...requestId, type: \"input\", status: \"placed\", entry: entry.id } as const;\n\tconst { id } = await tx.createSubmission(input);\n\tawait startRun(tx, conversationId, live, [id]);\n\treturn id;\n}\n"]}
@@ -0,0 +1,49 @@
1
+ import { type AttachedReplicatedState, type Context, type JsonValue } from "@earendil-works/chord";
2
+ import type { SessionImpl } from "../session/session.ts";
3
+ import type { ConversationId, JoinPolicy, Storage, TaskId, TaskOutcome, WatchHandle } from "../types.ts";
4
+ /** A live task's durable status without its checkpoint and outcome payloads (spec §9.5). */
5
+ export type TaskGraphState = {
6
+ readonly status: "pending" | "running";
7
+ readonly phase: string;
8
+ } | {
9
+ readonly status: "waiting";
10
+ readonly phase: string;
11
+ readonly on: readonly TaskId[];
12
+ readonly policy: JoinPolicy;
13
+ }
14
+ /** Outcome held until its ordinary owned work drains. */
15
+ | {
16
+ readonly status: "completing";
17
+ readonly outcome: TaskOutcome<JsonValue>["status"];
18
+ };
19
+ export type TaskGraphNode = {
20
+ readonly id: TaskId;
21
+ readonly kind: string;
22
+ readonly conversationId: ConversationId;
23
+ /** Owner task; absent for a conversation-owned task. */
24
+ readonly owner?: TaskId;
25
+ readonly background: boolean;
26
+ readonly abortRequested: boolean;
27
+ readonly state: TaskGraphState;
28
+ /** Conversations this task owns, in ID order. */
29
+ readonly conversations: readonly ConversationId[];
30
+ };
31
+ /** Every live task of the Session (spec §9.5). */
32
+ export type TaskGraph = {
33
+ /** Every live task, keyed by its decimal ID. */
34
+ readonly tasks: Readonly<Record<string, TaskGraphNode>>;
35
+ };
36
+ export type TaskGraphWatch = WatchHandle<TaskGraph>;
37
+ /**
38
+ * The Harness's task graph mount: built on the Session line by its first observer and dropped with its last. It
39
+ * advances from the Session's commit publications, which are durable.
40
+ */
41
+ export declare class TaskGraphView {
42
+ #private;
43
+ constructor(session: SessionImpl, storage: Storage);
44
+ /** A disposable read-only Chord state of the graph. */
45
+ state(context: Context): Promise<AttachedReplicatedState<TaskGraph>>;
46
+ /** A serialized exact-frame watch of the graph; cancelling `context` stops it. */
47
+ watch(context: Context): Promise<TaskGraphWatch>;
48
+ }
49
+ //# sourceMappingURL=task-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-graph.d.ts","sourceRoot":"","sources":["../../src/harness/task-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,uBAAuB,CAAC;AAIpH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAEX,cAAc,EACd,UAAU,EACV,OAAO,EACP,MAAM,EACN,WAAW,EAEX,WAAW,EACX,MAAM,aAAa,CAAC;AAGrB,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClE;IACA,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC3B;AACH,yDAAyD;GACvD;IAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC;AAEzF,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,iDAAiD;IACjD,QAAQ,CAAC,aAAa,EAAE,SAAS,cAAc,EAAE,CAAC;CAClD,CAAC;AAEF,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG;IACvB,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;AASpD;;;GAGG;AACH,qBAAa,aAAa;;IAMzB,YAAY,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAWjD;IAED,uDAAuD;IACjD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAWzE;IAED,kFAAkF;IAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAYrD;CAyCD"}
@@ -0,0 +1,163 @@
1
+ import { replicatedState } from "@earendil-works/chord";
2
+ import { withoutAbortSignal } from "@earendil-works/chord/context";
3
+ import { applyImmutable } from "@earendil-works/chord/delta";
4
+ import { CommittedStateSource, CommittedWatch } from "../session/observation.js";
5
+ import { closedError, scanAll } from "./util.js";
6
+ const LIVE_STATUSES = ["pending", "running", "waiting", "completing"];
7
+ const SCAN_PAGE_SIZE = 256;
8
+ /**
9
+ * The Harness's task graph mount: built on the Session line by its first observer and dropped with its last. It
10
+ * advances from the Session's commit publications, which are durable.
11
+ */
12
+ export class TaskGraphView {
13
+ #session;
14
+ #storage;
15
+ #mount;
16
+ #closed = false;
17
+ constructor(session, storage) {
18
+ this.#session = session;
19
+ this.#storage = storage;
20
+ session.subscribeCommits((publication, context) => {
21
+ if (this.#mount !== undefined)
22
+ advance(this.#mount, publication, context);
23
+ });
24
+ session.subscribeClose(() => {
25
+ this.#closed = true;
26
+ for (const observer of [...(this.#mount?.observers ?? [])])
27
+ observer.closeSession();
28
+ this.#mount = undefined;
29
+ });
30
+ }
31
+ /** A disposable read-only Chord state of the graph. */
32
+ async state(context) {
33
+ const { observer, detach } = await this.#attach((value, release) => new CommittedStateSource(value, release), context);
34
+ try {
35
+ return replicatedState(observer);
36
+ }
37
+ catch (error) {
38
+ detach();
39
+ throw error;
40
+ }
41
+ }
42
+ /** A serialized exact-frame watch of the graph; cancelling `context` stops it. */
43
+ async watch(context) {
44
+ const { observer } = await this.#attach((value, release) => new CommittedWatch(value, release), context);
45
+ const signal = context.abortSignal;
46
+ if (signal?.aborted) {
47
+ observer.cancel();
48
+ throw signal.reason;
49
+ }
50
+ if (signal !== undefined)
51
+ observer.observeCancellation(signal);
52
+ return observer;
53
+ }
54
+ /** Register an observer created from the current revision, atomically on the Session line. */
55
+ #attach(create, context) {
56
+ return this.#session.readOnLine(async () => {
57
+ const mount = this.#mount ?? { value: await this.#build(context), observers: new Set() };
58
+ const detach = () => {
59
+ mount.observers.delete(observer);
60
+ if (mount.observers.size === 0 && this.#mount === mount)
61
+ this.#mount = undefined;
62
+ };
63
+ const observer = create(mount.value, detach);
64
+ // Close or cancellation may begin while the mount builds; register nothing then.
65
+ if (this.#closed)
66
+ throw closedError();
67
+ context.abortSignal?.throwIfAborted();
68
+ this.#mount = mount;
69
+ mount.observers.add(observer);
70
+ return { observer, detach };
71
+ });
72
+ }
73
+ async #build(context) {
74
+ const tasks = {};
75
+ const records = [];
76
+ for (const status of LIVE_STATUSES) {
77
+ records.push(...(await scanAll((cursor) => this.#storage.scanTasks({ status }, SCAN_PAGE_SIZE, cursor, context))));
78
+ }
79
+ records.sort((a, b) => a.id - b.id);
80
+ for (const record of records) {
81
+ const owned = await scanAll((cursor) => this.#storage.scanConversations({ ownerTaskId: record.id }, SCAN_PAGE_SIZE, cursor, context));
82
+ const conversations = owned.map((conversation) => conversation.id).sort((a, b) => a - b);
83
+ tasks[String(record.id)] = nodeOf(record, conversations);
84
+ }
85
+ return { tasks };
86
+ }
87
+ }
88
+ /** Derive the mount's operations from one publication, apply them, and hand the revision to every observer. */
89
+ function advance(mount, publication, context) {
90
+ const ops = [];
91
+ // Nodes this publication set or deleted, over the mount's value.
92
+ const changed = new Map();
93
+ const node = (key) => changed.has(key) ? changed.get(key) : mount.value.tasks[key];
94
+ for (const change of publication.changes) {
95
+ if (change.type !== "task")
96
+ continue;
97
+ const record = change.value;
98
+ const key = String(record.id);
99
+ const previous = node(key);
100
+ if (record.state.status === "terminal") {
101
+ if (previous === undefined)
102
+ continue;
103
+ ops.push(["d", ["tasks", key]]);
104
+ changed.set(key, undefined);
105
+ continue;
106
+ }
107
+ const next = nodeOf(record, previous?.conversations ?? []);
108
+ if (previous !== undefined && JSON.stringify(next) === JSON.stringify(previous))
109
+ continue;
110
+ ops.push(["s", ["tasks", key], next]);
111
+ changed.set(key, next);
112
+ }
113
+ // After the tasks, so a conversation created with its owner task in one commit finds the owner's node. Change order
114
+ // within a publication is unspecified, so each owner's list is sorted again.
115
+ const created = new Map();
116
+ for (const change of publication.changes) {
117
+ if (change.type !== "conversation" || change.value.owner === undefined)
118
+ continue;
119
+ const key = String(change.value.owner.taskId);
120
+ if (node(key) !== undefined)
121
+ created.set(key, [...(created.get(key) ?? []), change.value.id]);
122
+ }
123
+ for (const [key, ids] of created) {
124
+ const conversations = [...node(key).conversations, ...ids].sort((a, b) => a - b);
125
+ ops.push(["s", ["tasks", key, "conversations"], conversations]);
126
+ }
127
+ if (ops.length === 0)
128
+ return;
129
+ mount.value = applyImmutable(mount.value, ops);
130
+ const frameContext = withoutAbortSignal(context);
131
+ for (const observer of [...mount.observers])
132
+ observer.advance(mount.value, ops, frameContext);
133
+ }
134
+ function nodeOf(record, conversations) {
135
+ return {
136
+ id: record.id,
137
+ kind: record.kind,
138
+ conversationId: record.conversationId,
139
+ ...(record.owner === undefined ? {} : { owner: record.owner }),
140
+ background: record.background,
141
+ abortRequested: record.abortRequested,
142
+ state: stateOf(record),
143
+ conversations,
144
+ };
145
+ }
146
+ function stateOf(record) {
147
+ const state = record.state;
148
+ switch (state.status) {
149
+ case "pending":
150
+ case "running":
151
+ return { status: state.status, phase: phaseOf(state.checkpoint) };
152
+ case "waiting":
153
+ return { status: "waiting", phase: phaseOf(state.checkpoint), on: [...state.on], policy: state.policy };
154
+ // Terminal records never reach here: they leave the graph.
155
+ case "completing":
156
+ case "terminal":
157
+ return { status: "completing", outcome: state.outcome.status };
158
+ }
159
+ }
160
+ function phaseOf(checkpoint) {
161
+ return checkpoint.phase;
162
+ }
163
+ //# sourceMappingURL=task-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-graph.js","sourceRoot":"","sources":["../../src/harness/task-graph.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AttachedReplicatedState, type Context, type JsonValue, replicatedState } from \"@earendil-works/chord\";\nimport { withoutAbortSignal } from \"@earendil-works/chord/context\";\nimport { applyImmutable, type Op } from \"@earendil-works/chord/delta\";\nimport { CommittedStateSource, CommittedWatch } from \"../session/observation.ts\";\nimport type { SessionImpl } from \"../session/session.ts\";\nimport type {\n\tCommitPublication,\n\tConversationId,\n\tJoinPolicy,\n\tStorage,\n\tTaskId,\n\tTaskOutcome,\n\tTaskRecord,\n\tWatchHandle,\n} from \"../types.ts\";\nimport { closedError, scanAll } from \"./util.ts\";\n\n/** A live task's durable status without its checkpoint and outcome payloads (spec §9.5). */\nexport type TaskGraphState =\n\t| { readonly status: \"pending\" | \"running\"; readonly phase: string }\n\t| {\n\t\t\treadonly status: \"waiting\";\n\t\t\treadonly phase: string;\n\t\t\treadonly on: readonly TaskId[];\n\t\t\treadonly policy: JoinPolicy;\n\t }\n\t/** Outcome held until its ordinary owned work drains. */\n\t| { readonly status: \"completing\"; readonly outcome: TaskOutcome<JsonValue>[\"status\"] };\n\nexport type TaskGraphNode = {\n\treadonly id: TaskId;\n\treadonly kind: string;\n\treadonly conversationId: ConversationId;\n\t/** Owner task; absent for a conversation-owned task. */\n\treadonly owner?: TaskId;\n\treadonly background: boolean;\n\treadonly abortRequested: boolean;\n\treadonly state: TaskGraphState;\n\t/** Conversations this task owns, in ID order. */\n\treadonly conversations: readonly ConversationId[];\n};\n\n/** Every live task of the Session (spec §9.5). */\nexport type TaskGraph = {\n\t/** Every live task, keyed by its decimal ID. */\n\treadonly tasks: Readonly<Record<string, TaskGraphNode>>;\n};\n\nexport type TaskGraphWatch = WatchHandle<TaskGraph>;\n\ntype AnyTaskRecord = TaskRecord<JsonValue, JsonValue, JsonValue>;\ntype Observer = CommittedStateSource<TaskGraph> | CommittedWatch<TaskGraph>;\ntype Mount = { value: TaskGraph; readonly observers: Set<Observer> };\n\nconst LIVE_STATUSES = [\"pending\", \"running\", \"waiting\", \"completing\"] as const;\nconst SCAN_PAGE_SIZE = 256;\n\n/**\n * The Harness's task graph mount: built on the Session line by its first observer and dropped with its last. It\n * advances from the Session's commit publications, which are durable.\n */\nexport class TaskGraphView {\n\treadonly #session: SessionImpl;\n\treadonly #storage: Storage;\n\t#mount: Mount | undefined;\n\t#closed = false;\n\n\tconstructor(session: SessionImpl, storage: Storage) {\n\t\tthis.#session = session;\n\t\tthis.#storage = storage;\n\t\tsession.subscribeCommits((publication, context) => {\n\t\t\tif (this.#mount !== undefined) advance(this.#mount, publication, context);\n\t\t});\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tfor (const observer of [...(this.#mount?.observers ?? [])]) observer.closeSession();\n\t\t\tthis.#mount = undefined;\n\t\t});\n\t}\n\n\t/** A disposable read-only Chord state of the graph. */\n\tasync state(context: Context): Promise<AttachedReplicatedState<TaskGraph>> {\n\t\tconst { observer, detach } = await this.#attach(\n\t\t\t(value, release) => new CommittedStateSource<TaskGraph>(value, release),\n\t\t\tcontext,\n\t\t);\n\t\ttry {\n\t\t\treturn replicatedState(observer);\n\t\t} catch (error) {\n\t\t\tdetach();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/** A serialized exact-frame watch of the graph; cancelling `context` stops it. */\n\tasync watch(context: Context): Promise<TaskGraphWatch> {\n\t\tconst { observer } = await this.#attach(\n\t\t\t(value, release) => new CommittedWatch<TaskGraph>(value, release),\n\t\t\tcontext,\n\t\t);\n\t\tconst signal = context.abortSignal;\n\t\tif (signal?.aborted) {\n\t\t\tobserver.cancel();\n\t\t\tthrow signal.reason;\n\t\t}\n\t\tif (signal !== undefined) observer.observeCancellation(signal);\n\t\treturn observer;\n\t}\n\n\t/** Register an observer created from the current revision, atomically on the Session line. */\n\t#attach<O extends Observer>(\n\t\tcreate: (value: TaskGraph, release: () => void) => O,\n\t\tcontext: Context,\n\t): Promise<{ observer: O; detach: () => void }> {\n\t\treturn this.#session.readOnLine(async () => {\n\t\t\tconst mount = this.#mount ?? { value: await this.#build(context), observers: new Set<Observer>() };\n\t\t\tconst detach = (): void => {\n\t\t\t\tmount.observers.delete(observer);\n\t\t\t\tif (mount.observers.size === 0 && this.#mount === mount) this.#mount = undefined;\n\t\t\t};\n\t\t\tconst observer = create(mount.value, detach);\n\t\t\t// Close or cancellation may begin while the mount builds; register nothing then.\n\t\t\tif (this.#closed) throw closedError();\n\t\t\tcontext.abortSignal?.throwIfAborted();\n\t\t\tthis.#mount = mount;\n\t\t\tmount.observers.add(observer);\n\t\t\treturn { observer, detach };\n\t\t});\n\t}\n\n\tasync #build(context: Context): Promise<TaskGraph> {\n\t\tconst tasks: Record<string, TaskGraphNode> = {};\n\t\tconst records: AnyTaskRecord[] = [];\n\t\tfor (const status of LIVE_STATUSES) {\n\t\t\trecords.push(\n\t\t\t\t...(await scanAll((cursor) => this.#storage.scanTasks({ status }, SCAN_PAGE_SIZE, cursor, context))),\n\t\t\t);\n\t\t}\n\t\trecords.sort((a, b) => a.id - b.id);\n\t\tfor (const record of records) {\n\t\t\tconst owned = await scanAll((cursor) =>\n\t\t\t\tthis.#storage.scanConversations({ ownerTaskId: record.id }, SCAN_PAGE_SIZE, cursor, context),\n\t\t\t);\n\t\t\tconst conversations = owned.map((conversation) => conversation.id).sort((a, b) => a - b);\n\t\t\ttasks[String(record.id)] = nodeOf(record, conversations);\n\t\t}\n\t\treturn { tasks };\n\t}\n}\n\n/** Derive the mount's operations from one publication, apply them, and hand the revision to every observer. */\nfunction advance(mount: Mount, publication: CommitPublication, context: Context): void {\n\tconst ops: Op[] = [];\n\t// Nodes this publication set or deleted, over the mount's value.\n\tconst changed = new Map<string, TaskGraphNode | undefined>();\n\tconst node = (key: string): TaskGraphNode | undefined =>\n\t\tchanged.has(key) ? changed.get(key) : mount.value.tasks[key];\n\tfor (const change of publication.changes) {\n\t\tif (change.type !== \"task\") continue;\n\t\tconst record = change.value;\n\t\tconst key = String(record.id);\n\t\tconst previous = node(key);\n\t\tif (record.state.status === \"terminal\") {\n\t\t\tif (previous === undefined) continue;\n\t\t\tops.push([\"d\", [\"tasks\", key]]);\n\t\t\tchanged.set(key, undefined);\n\t\t\tcontinue;\n\t\t}\n\t\tconst next = nodeOf(record, previous?.conversations ?? []);\n\t\tif (previous !== undefined && JSON.stringify(next) === JSON.stringify(previous)) continue;\n\t\tops.push([\"s\", [\"tasks\", key], next as unknown as JsonValue]);\n\t\tchanged.set(key, next);\n\t}\n\t// After the tasks, so a conversation created with its owner task in one commit finds the owner's node. Change order\n\t// within a publication is unspecified, so each owner's list is sorted again.\n\tconst created = new Map<string, ConversationId[]>();\n\tfor (const change of publication.changes) {\n\t\tif (change.type !== \"conversation\" || change.value.owner === undefined) continue;\n\t\tconst key = String(change.value.owner.taskId);\n\t\tif (node(key) !== undefined) created.set(key, [...(created.get(key) ?? []), change.value.id]);\n\t}\n\tfor (const [key, ids] of created) {\n\t\tconst conversations = [...node(key)!.conversations, ...ids].sort((a, b) => a - b);\n\t\tops.push([\"s\", [\"tasks\", key, \"conversations\"], conversations]);\n\t}\n\tif (ops.length === 0) return;\n\tmount.value = applyImmutable(mount.value, ops);\n\tconst frameContext = withoutAbortSignal(context);\n\tfor (const observer of [...mount.observers]) observer.advance(mount.value, ops, frameContext);\n}\n\nfunction nodeOf(record: AnyTaskRecord, conversations: readonly ConversationId[]): TaskGraphNode {\n\treturn {\n\t\tid: record.id,\n\t\tkind: record.kind,\n\t\tconversationId: record.conversationId,\n\t\t...(record.owner === undefined ? {} : { owner: record.owner }),\n\t\tbackground: record.background,\n\t\tabortRequested: record.abortRequested,\n\t\tstate: stateOf(record),\n\t\tconversations,\n\t};\n}\n\nfunction stateOf(record: AnyTaskRecord): TaskGraphState {\n\tconst state = record.state;\n\tswitch (state.status) {\n\t\tcase \"pending\":\n\t\tcase \"running\":\n\t\t\treturn { status: state.status, phase: phaseOf(state.checkpoint) };\n\t\tcase \"waiting\":\n\t\t\treturn { status: \"waiting\", phase: phaseOf(state.checkpoint), on: [...state.on], policy: state.policy };\n\t\t// Terminal records never reach here: they leave the graph.\n\t\tcase \"completing\":\n\t\tcase \"terminal\":\n\t\t\treturn { status: \"completing\", outcome: state.outcome.status };\n\t}\n}\n\nfunction phaseOf(checkpoint: JsonValue): string {\n\treturn (checkpoint as { readonly phase: string }).phase;\n}\n"]}
@@ -19,7 +19,7 @@ export type ToolTaskResult = {
19
19
  control?: ToolControl;
20
20
  };
21
21
  /**
22
- * Built-in tool task: resolves the called tool from its phase snapshot, validates, runs `beforeTool`, records intent,
22
+ * Built-in tool task: resolves the called tool among its phase agent's tools, validates, runs `beforeTool`, records intent,
23
23
  * executes, runs `afterTool`, and appends the result, all in one `call` handler so nothing separates resolution from
24
24
  * settlement. `execute` is reached only by recovery and applies the replay rule.
25
25
  */
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/harness/tool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAA6B,QAAQ,EAAqB,MAAM,uBAAuB,CAAC;AAKpG,OAAO,KAAK,EACX,cAAc,EACd,OAAO,EACP,UAAU,EACV,IAAI,EAIJ,EAAE,EACF,UAAU,EACV,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,EACX,WAAW,EACX,cAAc,EAEd,mBAAmB,EACnB,SAAS,EAET,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,aAAa,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,kBAAkB,GAC3B;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;AACnB,2FAA2F;GACzF;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAKzE;;;;GAIG;AACH,eAAO,MAAM,QAAQ,oEAoEnB,CAAC;AAmSH,oGAAoG;AACpG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAE/E;AAmBD;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,EAAE,EAAE,EAAE,EACN,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,mBAAmB,EAC3B,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC;IAAE,WAAW,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC,CAAC,CAgBxD"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/harness/tool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAA6B,QAAQ,EAAqB,MAAM,uBAAuB,CAAC;AAKpG,OAAO,KAAK,EACX,cAAc,EACd,OAAO,EACP,UAAU,EACV,IAAI,EAIJ,EAAE,EACF,UAAU,EACV,MAAM,aAAa,CAAC;AAIrB,OAAO,KAAK,EACX,WAAW,EACX,cAAc,EAEd,mBAAmB,EACnB,SAAS,EAET,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,aAAa,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,kBAAkB,GAC3B;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;AACnB,2FAA2F;GACzF;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAC;AAE1E,MAAM,MAAM,cAAc,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAKzE;;;;GAIG;AACH,eAAO,MAAM,QAAQ,oEAoEnB,CAAC;AAsSH,oGAAoG;AACpG,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAE/E;AAmBD;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,EAAE,EAAE,EAAE,EACN,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,mBAAmB,EAC3B,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC;IAAE,WAAW,EAAE,cAAc,EAAE,CAAA;CAAE,CAAC,CAAC,CAgBxD"}
@@ -10,7 +10,7 @@ import { clearProgress, finishSlot, LiveDoc, toolSlot } from "./live.js";
10
10
  import { boundOutput, OutputBuffer, Progress } from "./output.js";
11
11
  import { recordUsage } from "./usage.js";
12
12
  /**
13
- * Built-in tool task: resolves the called tool from its phase snapshot, validates, runs `beforeTool`, records intent,
13
+ * Built-in tool task: resolves the called tool among its phase agent's tools, validates, runs `beforeTool`, records intent,
14
14
  * executes, runs `afterTool`, and appends the result, all in one `call` handler so nothing separates resolution from
15
15
  * settlement. `execute` is reached only by recovery and applies the replay rule.
16
16
  */
@@ -21,7 +21,7 @@ export const ToolTask = defineTask({
21
21
  phases: {
22
22
  call: async (task, runtime, context) => {
23
23
  const call = await readCall(runtime, task.input, context);
24
- const tool = runtime.registry.tool(call.name);
24
+ const tool = (await runtime.agent(context)).tools.find((each) => each.name === call.name);
25
25
  if (tool === undefined) {
26
26
  const error = harnessError("tool_unavailable", `Tool ${call.name} is not available`);
27
27
  return settle(runtime, call, COMPLETED, () => error, context);
@@ -69,7 +69,7 @@ export const ToolTask = defineTask({
69
69
  execute: async (task, runtime, context) => {
70
70
  const { arguments: args, replay } = task.state.checkpoint;
71
71
  const call = await readCall(runtime, task.input, context);
72
- const tool = runtime.registry.tool(call.name);
72
+ const tool = (await runtime.agent(context)).tools.find((each) => each.name === call.name);
73
73
  if (replay === "safe" && tool?.replay === "safe") {
74
74
  // The rerun reports from scratch; clear what the interrupted attempt published.
75
75
  await runtime.commit(async (tx) => {
@@ -144,7 +144,8 @@ async function run(runtime, call, tool, args, context) {
144
144
  taskId: runtime.taskId,
145
145
  conversationId: runtime.conversationId,
146
146
  callId: call.id,
147
- env: runtime.env,
147
+ registry: runtime.registry,
148
+ agent: runtime.agent,
148
149
  output: (chunk) => {
149
150
  assertLive();
150
151
  if (reported.output.push(chunk))
@@ -191,7 +192,9 @@ async function run(runtime, call, tool, args, context) {
191
192
  let result;
192
193
  let ending = COMPLETED;
193
194
  try {
194
- result = await tool.execute(args, api, context);
195
+ // Built for this call, so a rerun after recovery gets the conversation's environment at that time.
196
+ const env = await runtime.env(context);
197
+ result = await tool.execute(args, { ...api, env }, context);
195
198
  }
196
199
  catch (error) {
197
200
  if (runtime.signal.aborted) {
@@ -201,7 +204,7 @@ async function run(runtime, call, tool, args, context) {
201
204
  throw error;
202
205
  }
203
206
  result = { isError: true, diagnostics: [toolDiagnostic("tool_error", errorText(error))] };
204
- // A throw ends the task `failed`, which cancels what the call owned; it no longer supervises it. The error text
207
+ // A throw, from `execute()` or from building the environment, ends the task `failed`, which cancels what the call owned; it no longer supervises it. The error text
205
208
  // is already in the result entry.
206
209
  ending = { status: "failed", message: `Tool ${call.name} threw` };
207
210
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/harness/tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,QAAQ,EAAkB,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAEtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAYtF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAiB,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAqB,QAAQ,EAAE,MAAM,aAAa,CAAC;AASrF,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAczC;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAA+D;IAChG,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAClC,MAAM,EAAE;QACP,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YACtC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,KAAK,GAAG,YAAY,CAAC,kBAAkB,EAAE,QAAQ,IAAI,CAAC,IAAI,mBAAmB,CAAC,CAAC;gBACrF,OAAO,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,SAAuB,CAAC,CAAC;YAC7D,MAAM,OAAO,GAAG,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YACrF,IAAI,OAAO,IAAI,OAAO;gBAAE,OAAO,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;YACvG,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YACxB,IAAI,KAAyB,CAAC;YAC9B,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACrD,IAAI,KAAK,KAAK,SAAS;oBAAE,OAAO;gBAChC,IAAI,CAAC;oBACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;oBAC5E,IAAI,QAAQ,EAAE,KAAK,KAAK,SAAS;wBAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;yBACrD,IAAI,QAAQ,EAAE,SAAS,KAAK,SAAS;wBAAE,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC;gBACvE,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO;wBAAE,MAAM,KAAK,CAAC;oBACxC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;gBAC1B,CAAC;YACF,CAAC,CAAC,CAAC;YACH,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,EAAE,sBAAsB,KAAK,EAAE,CAAC,CAAC;gBACvE,OAAO,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACjE,CAAC;YACD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAC7C,IAAI,OAAO,IAAI,SAAS;gBAAE,OAAO,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;YAC3G,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC;YAC7B,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBACrF,IAAI,IAAI,KAAK,SAAS;oBAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;gBAChD,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,QAAQ,EAAW,CAAC;gBAChG,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;YAClD,CAAC,EAAE,OAAO,CAAC,CAAC;YACZ,MAAM,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,gGAAgG;QAChG,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;YACzC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;YAC1D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;gBAClD,gFAAgF;gBAChF,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;oBACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;oBACrF,IAAI,IAAI,KAAK,SAAS;wBAAE,aAAa,CAAC,IAAI,CAAC,CAAC;oBAC5C,OAAO,SAAS,CAAC;gBAClB,CAAC,EAAE,OAAO,CAAC,CAAC;gBACZ,OAAO,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,OAAO,GAAG,QAAQ,IAAI,CAAC,IAAI,6CAA6C,CAAC;YAC/E,2GAA2G;YAC3G,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAW,CAAC;YACtD,MAAM,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QAChG,CAAC;KACD;IACD,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,QAAQ,IAAI,CAAC,IAAI,cAAc,CAAC;QAChD,MAAM,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3G,CAAC;CACD,CAAC,CAAC;AAEH,qDAAqD;AACrD,KAAK,UAAU,QAAQ,CAAC,OAAgB,EAAE,KAAoB,EAAE,OAAgB;IAC/E,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,IAAI,GACT,OAAO,EAAE,IAAI,KAAK,WAAW;QAC5B,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CACpB,CAAC,OAAO,EAAuB,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,EAAE,KAAK,KAAK,CAAC,MAAM,CAC5F;QACF,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,IAAI,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,SAAS,qBAAqB,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACrG,OAAO,IAAI,CAAC;AACb,CAAC;AAKD,0FAA0F;AAC1F,SAAS,OAAO,CAAC,IAAsB,EAAE,IAAgB;IACxD,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACzD,IAAI,CAAC;QACJ,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAe,EAAE,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IACpC,CAAC;AACF,CAAC;AAED,2EAA2E;AAC3E,SAAS,QAAQ,CAAC,IAAsB,EAAE,IAAc,EAAE,IAAgB;IACzE,IAAI,CAAC;QACJ,OAAO,EAAE,IAAI,EAAE,qBAAqB,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAe,EAAE,CAAC;IAC1F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;IACpC,CAAC;AACF,CAAC;AAED,SAAS,OAAO,CAAC,OAAe;IAC/B,OAAO,YAAY,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AAUD,wEAAwE;AACxE,KAAK,UAAU,GAAG,CACjB,OAAgB,EAChB,IAAc,EACd,IAAsB,EACtB,IAAgB,EAChB,OAAgB;IAEhB,MAAM,MAAM,GAAiB;QAC5B,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,IAAI,iBAAiB;QAC1D,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,IAAI,iBAAiB;QAC1D,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,IAAI,MAAM;KAC3C,CAAC;IACF,MAAM,QAAQ,GAAa,EAAE,MAAM,EAAE,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAC7G,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7D,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,MAAM,UAAU,GAAG,GAAS,EAAE;QAC7B,IAAI,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC,EAAE,cAAc,CAAC,CAAC;IAChE,CAAC,CAAC;IACF,MAAM,GAAG,GAAqB;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,UAAU,EAAE,CAAC;YACb,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClD,CAAC;QACD,UAAU,EAAE,CAAC,UAAU,EAAE,EAAE;YAC1B,UAAU,EAAE,CAAC;YACb,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAmB,CAAC,CAAC;YACrG,QAAQ,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;YACxC,UAAU,EAAE,CAAC;YACb,cAAc,CAAC,WAAW,EAAE,cAAc,EAAE,CAAC;YAC7C,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAC,CAAC;YACtE,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;YACzC,2FAA2F;YAC3F,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC1B,OAAO,gBAAgB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE;YACvC,IAAI,MAAsD,CAAC;YAC3D,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBACjC,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC1B,OAAO,SAAS,CAAC;YAClB,CAAC,EAAE,aAAa,CAAC,CAAC;YAClB,OAAO,MAA4C,CAAC;QACrD,CAAC;QACD,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,UAAU,EAAE,KAAK,EAChB,IAAsB,EACtB,KAAQ,EACR,OAA4C,EAC5C,WAAoB,EACC,EAAE;YACvB,IAAI,EAAyB,CAAC;YAC9B,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBACjC,EAAE,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;gBAC/C,OAAO,SAAS,CAAC;YAClB,CAAC,EAAE,WAAW,CAAC,CAAC;YAChB,OAAO,EAAG,CAAC;QACZ,CAAC;QACD,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC1B,CAAC;IAEF,IAAI,MAA2B,CAAC;IAChC,IAAI,MAAM,GAAG,SAAS,CAAC;IACvB,IAAI,CAAC;QACJ,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC5B,KAAK,GAAG,IAAI,CAAC;YACb,KAAK,MAAM,MAAM,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE;gBAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjE,MAAM,KAAK,CAAC;QACb,CAAC;QACD,MAAM,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,cAAc,CAAC,YAAY,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,gHAAgH;QAChH,kCAAkC;QAClC,MAAM,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;IACnE,CAAC;IACD,KAAK,GAAG,IAAI,CAAC;IACb,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IACtB,gGAAgG;IAChG,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACtC,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5E,MAAM,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,KAAK,MAAM,MAAM,IAAI,OAAO;YAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnD,MAAM,KAAK,CAAC;IACb,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,OAAO;QAAE,MAAM,CAAC,OAAO,EAAE,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,OAAgB,EAAE,QAAkB,EAAE,OAAgB;IAC9E,IAAI,OAAO,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,SAAkC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACxF,OAAO,IAAI,QAAQ,CAClB,KAAK,IAAI,EAAE;QACV,4FAA4F;QAC5F,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;QAC7G,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QACnF,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC;QAC3D,iHAAiH;QACjH,2EAA2E;QAC3E,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;gBACpD,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM;gBACrB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAChD,KAAK,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,cAAc;YAAE,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC;QACrF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACrE,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACrF,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YACzC,uGAAuG;YACvG,sGAAsG;YACtG,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,KAAK,QAAQ,CAAC,IAAI;gBAAE,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC;YACvE,IAAI,QAAQ,CAAC,YAAY,GAAG,CAAC;gBAAE,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC;YACzE,IAAI,QAAQ,CAAC,YAAY,GAAG,CAAC;gBAAE,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC;YACzE,iGAAiG;YACjG,IAAI,cAAc,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBACrD,UAAU,CAAC,IAA4C,EAAE,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACtF,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;oBAAE,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;gBAC1D,KAAK,MAAM,UAAU,IAAI,KAAK;oBAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACnE,CAAC;YACD,OAAO,SAAS,CAAC;QAClB,CAAC,EAAE,OAAO,CAAC,CAAC;QACZ,OAAO,GAAG,OAAO,CAAC;QAClB,OAAO,KAAK,CAAC;IACd,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;QACT,8FAA8F;QAC9F,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC,CACD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,WAAW,CACzB,OAAgB,EAChB,IAAc,EACd,MAA2B,EAC3B,QAAkB,EAClB,OAAgB;IAEhB,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACvF,MAAM,OAAO,GACZ,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAChH,IAAI,KAAK,GAAwB;QAChC,GAAG,MAAM;QACT,OAAO;QACP,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO;QACzE,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;KACrE,CAAC;IACF,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACpD,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC;IAC9D,CAAC,CAAC,CAAC;IACH,mFAAmF;IACnF,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,YAAY,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QACtF,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnE,IAAI,OAAO,CAAC,YAAY,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACvF,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;AACxG,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,MAAM,CACpB,OAAgB,EAChB,IAAc,EACd,MAAc,EACd,KAAoE,EACpE,OAAgB;IAEhB,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,EAAE,EAAE,OAAO,CAAC,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9F,IAAI,IAAI,KAAK,SAAS;YAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAC9B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACpF,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;YAC1C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC1F,CAAC;QACD,oGAAoG;QACpG,MAAM,OAAO,GACZ,MAAM,CAAC,OAAO,KAAK,SAAS;YAC3B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAoB,EAAE,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAgB,EAAE,CAAC;QACzG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC;IAClG,CAAC,EAAE,OAAO,CAAC,CAAC;AACb,CAAC;AAQD,MAAM,SAAS,GAAW,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AAElD,wFAAwF;AACxF,SAAS,QAAQ,CAAC,IAAoC,EAAE,IAAY,EAAE,OAAe;IACpF,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,IAAI,EAAE,YAAY,IAAI,CAAC,CAAC;IAC7C,IAAI,YAAY,GAAG,CAAC;QAAE,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3G,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAChD,OAAO;QACN,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QACtG,OAAO,EAAE,IAAI;QACb,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACjE,WAAW;KACX,CAAC;AACH,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAe;IACzD,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;AACrF,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,OAAe;IACpD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC7C,CAAC;AAED,wGAAwG;AACxG,SAAS,SAAS,CACjB,OAAyE,EACzE,MAAwB;IAExB,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IAC9F,OAAO;QACN,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,mBAAmB,IAAI,KAAK,OAAO,CAAC,YAAY,WAAW,OAAO,CAAC,YAAY,gBAAgB;KACxG,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,EAAM,EACN,cAA8B,EAC9B,IAAc,EACd,MAA2B,EAC3B,SAAiB;IAEjB,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;IACpD,MAAM,OAAO,GAAY,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IACrD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACjG,MAAM,OAAO,GAAG;QACf,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE,IAAI,CAAC,EAAE;QACnB,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,OAAO;QACP,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QACpE,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9D,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;QAChC,SAAS;KACY,CAAC;IACvB,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,WAAW,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACxG,OAAO,EAAE,CAAC,WAAW,CAAC,eAAe,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;AACrG,CAAC;AAED,SAAS,iBAAiB,CAAC,WAAsC;IAChE,OAAO,cAAc,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;AACjI,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CACpB,OAAgB,EAChB,MAAoB;IAEpB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAuB,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAClF,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7E,IAAI,OAAO,CAAC,YAAY,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IACrF,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aACvC,IAAI,IAAI,KAAK,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;AACpG,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAChC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["import { type Context, copyJson, type JsonValue } from \"@earendil-works/chord\";\nimport { awaitWithContext } from \"@earendil-works/chord/context\";\nimport { overlap } from \"@earendil-works/chord/delta\";\nimport type { ImageContent, TextContent, ToolCall, ToolResultMessage } from \"@earendil-works/pi-ai\";\nimport { validateToolArguments } from \"@earendil-works/pi-ai/utils/validation\";\nimport { AssistantEntry, ToolResultEntry } from \"../entries.ts\";\nimport { defineTask } from \"../tasks.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, utf8ByteLength } from \"../truncate.ts\";\nimport type {\n\tConversationId,\n\tEntryId,\n\tJsonObject,\n\tTask,\n\tTaskId,\n\tTaskOptions,\n\tTaskRuntime,\n\tTx,\n\tTypedEntry,\n} from \"../types.ts\";\nimport { assignJson } from \"./json.ts\";\nimport { clearProgress, finishSlot, LiveDoc, type ToolSlot, toolSlot } from \"./live.ts\";\nimport { boundOutput, OutputBuffer, type OutputLimits, Progress } from \"./output.ts\";\nimport type {\n\tToolControl,\n\tToolDiagnostic,\n\tToolExecutionApi,\n\tToolExecutionResult,\n\tToolHooks,\n\tToolRegistration,\n} from \"./types.ts\";\nimport { recordUsage } from \"./usage.ts\";\n\nexport type ToolTaskInput = { assistant: EntryId; callId: string };\n\nexport type ToolTaskCheckpoint =\n\t| { phase: \"call\" }\n\t/** Durable intent: the final arguments and the replay policy recorded before execution. */\n\t| { phase: \"execute\"; arguments: JsonObject; replay: \"safe\" | \"unsafe\" };\n\nexport type ToolTaskResult = { entryId: EntryId; control?: ToolControl };\n\ntype Runtime = TaskRuntime<ToolTaskInput, ToolTaskCheckpoint, ToolTaskResult, ToolHooks>;\ntype Content = (TextContent | ImageContent)[];\n\n/**\n * Built-in tool task: resolves the called tool from its phase snapshot, validates, runs `beforeTool`, records intent,\n * executes, runs `afterTool`, and appends the result, all in one `call` handler so nothing separates resolution from\n * settlement. `execute` is reached only by recovery and applies the replay rule.\n */\nexport const ToolTask = defineTask<ToolTaskInput, ToolTaskCheckpoint, ToolTaskResult, ToolHooks>({\n\tname: \"pi.tool\",\n\tversion: 1,\n\tinitial: () => ({ phase: \"call\" }),\n\tphases: {\n\t\tcall: async (task, runtime, context) => {\n\t\t\tconst call = await readCall(runtime, task.input, context);\n\t\t\tconst tool = runtime.registry.tool(call.name);\n\t\t\tif (tool === undefined) {\n\t\t\t\tconst error = harnessError(\"tool_unavailable\", `Tool ${call.name} is not available`);\n\t\t\t\treturn settle(runtime, call, COMPLETED, () => error, context);\n\t\t\t}\n\t\t\tconst prepared = prepare(tool, call.arguments as JsonObject);\n\t\t\tconst checked = \"error\" in prepared ? prepared : validate(tool, call, prepared.args);\n\t\t\tif (\"error\" in checked) return settle(runtime, call, COMPLETED, () => invalid(checked.error), context);\n\t\t\tlet args = checked.args;\n\t\t\tlet block: string | undefined;\n\t\t\tawait runtime.hooks.each(\"beforeTool\", async (hook) => {\n\t\t\t\tif (block !== undefined) return;\n\t\t\t\ttry {\n\t\t\t\t\tconst decision = await hook({ ...call, arguments: args }, runtime, context);\n\t\t\t\t\tif (decision?.block !== undefined) block = decision.block;\n\t\t\t\t\telse if (decision?.arguments !== undefined) args = decision.arguments;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (runtime.signal.aborted) throw error;\n\t\t\t\t\tblock = errorText(error);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (block !== undefined) {\n\t\t\t\tconst blocked = harnessError(\"blocked\", `Tool call blocked: ${block}`);\n\t\t\t\treturn settle(runtime, call, COMPLETED, () => blocked, context);\n\t\t\t}\n\t\t\tconst validated = validate(tool, call, args);\n\t\t\tif (\"error\" in validated) return settle(runtime, call, COMPLETED, () => invalid(validated.error), context);\n\t\t\tconst final = validated.args;\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tconst slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\t\tif (slot !== undefined) slot.status = \"running\";\n\t\t\t\tconst intent = { phase: \"execute\", arguments: final, replay: tool.replay ?? \"unsafe\" } as const;\n\t\t\t\treturn { status: \"running\", checkpoint: intent };\n\t\t\t}, context);\n\t\t\tawait run(runtime, call, tool, final, context);\n\t\t},\n\t\t/** Recovery after intent: rerun only when the stored and the current policy both say `safe`. */\n\t\texecute: async (task, runtime, context) => {\n\t\t\tconst { arguments: args, replay } = task.state.checkpoint;\n\t\t\tconst call = await readCall(runtime, task.input, context);\n\t\t\tconst tool = runtime.registry.tool(call.name);\n\t\t\tif (replay === \"safe\" && tool?.replay === \"safe\") {\n\t\t\t\t// The rerun reports from scratch; clear what the interrupted attempt published.\n\t\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\t\tconst slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\t\t\tif (slot !== undefined) clearProgress(slot);\n\t\t\t\t\treturn undefined;\n\t\t\t\t}, context);\n\t\t\t\treturn run(runtime, call, tool, args, context);\n\t\t\t}\n\t\t\tconst message = `Tool ${call.name} was interrupted and may have partially run`;\n\t\t\t// `failed` records cancellation intent, so the call's owned conversations, left unsupervised, are aborted.\n\t\t\tconst ending = { status: \"failed\", message } as const;\n\t\t\tawait settle(runtime, call, ending, (slot) => fromSlot(slot, \"interrupted\", message), context);\n\t\t},\n\t},\n\tabort: async (task, runtime, context) => {\n\t\tconst call = await readCall(runtime, task.input, context);\n\t\tconst message = `Tool ${call.name} was aborted`;\n\t\tawait settle(runtime, call, { status: \"aborted\" }, (slot) => fromSlot(slot, \"aborted\", message), context);\n\t},\n});\n\n/** The tool call `callId` of the assistant entry. */\nasync function readCall(runtime: Runtime, input: ToolTaskInput, context: Context): Promise<ToolCall> {\n\tconst entry = await runtime.entry(AssistantEntry, input.assistant, context);\n\tconst message = entry?.model?.[0];\n\tconst call =\n\t\tmessage?.role === \"assistant\"\n\t\t\t? message.content.find(\n\t\t\t\t\t(content): content is ToolCall => content.type === \"toolCall\" && content.id === input.callId,\n\t\t\t\t)\n\t\t\t: undefined;\n\tif (call === undefined) throw new Error(`Entry ${input.assistant} has no tool call ${input.callId}`);\n\treturn call;\n}\n\n/** Arguments, or why they are invalid. */\ntype Checked = { readonly args: JsonObject } | { readonly error: string };\n\n/** The call's arguments as repaired by the tool; a throwing repair makes them invalid. */\nfunction prepare(tool: ToolRegistration, args: JsonObject): Checked {\n\tif (tool.prepareArguments === undefined) return { args };\n\ttry {\n\t\treturn { args: tool.prepareArguments(args) as JsonObject };\n\t} catch (error) {\n\t\treturn { error: errorText(error) };\n\t}\n}\n\n/** Arguments validated and coerced against the implementation's schema. */\nfunction validate(tool: ToolRegistration, call: ToolCall, args: JsonObject): Checked {\n\ttry {\n\t\treturn { args: validateToolArguments(tool, { ...call, arguments: args }) as JsonObject };\n\t} catch (error) {\n\t\treturn { error: errorText(error) };\n\t}\n}\n\nfunction invalid(message: string): ToolExecutionResult {\n\treturn harnessError(\"invalid_arguments\", message);\n}\n\n/** What a running tool reported through its api: output, the last details, and diagnostics. */\ntype Reported = {\n\treadonly output: OutputBuffer;\n\treadonly limits: OutputLimits;\n\treadonly diagnostics: ToolDiagnostic[];\n\tdetails: JsonValue | undefined;\n};\n\n/** Execute with the resolved implementation, then settle its result. */\nasync function run(\n\truntime: Runtime,\n\tcall: ToolCall,\n\ttool: ToolRegistration,\n\targs: JsonObject,\n\tcontext: Context,\n): Promise<void> {\n\tconst limits: OutputLimits = {\n\t\tmaxBytes: tool.outputLimits?.maxBytes ?? DEFAULT_MAX_BYTES,\n\t\tmaxLines: tool.outputLimits?.maxLines ?? DEFAULT_MAX_LINES,\n\t\tretain: tool.outputLimits?.retain ?? \"head\",\n\t};\n\tconst reported: Reported = { output: new OutputBuffer(limits), limits, diagnostics: [], details: undefined };\n\tconst progress = publishProgress(runtime, reported, context);\n\tlet ended = false;\n\tconst assertLive = (): void => {\n\t\tif (ended) throw new Error(`Tool call ${call.id} has settled`);\n\t};\n\tconst api: ToolExecutionApi = {\n\t\ttaskId: runtime.taskId,\n\t\tconversationId: runtime.conversationId,\n\t\tcallId: call.id,\n\t\tenv: runtime.env,\n\t\toutput: (chunk) => {\n\t\t\tassertLive();\n\t\t\tif (reported.output.push(chunk)) progress.mark();\n\t\t},\n\t\tdiagnostic: (diagnostic) => {\n\t\t\tassertLive();\n\t\t\treported.diagnostics.push(copyJson(diagnostic, { omitUndefinedProperties: true }) as ToolDiagnostic);\n\t\t\tprogress.mark();\n\t\t},\n\t\tdetails: async (value, detailsContext) => {\n\t\t\tassertLive();\n\t\t\tdetailsContext.abortSignal?.throwIfAborted();\n\t\t\treported.details = copyJson(value, { omitUndefinedProperties: true });\n\t\t\tconst committed = progress.markAndWait();\n\t\t\t// Cancelling the wait leaves the update in place; the commit's own outcome stays observed.\n\t\t\tcommitted.catch(() => {});\n\t\t\treturn awaitWithContext(committed, detailsContext);\n\t\t},\n\t\tcommit: async (change, commitContext) => {\n\t\t\tlet result: Awaited<ReturnType<typeof change>> | undefined;\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tresult = await change(tx);\n\t\t\t\treturn undefined;\n\t\t\t}, commitContext);\n\t\t\treturn result as Awaited<ReturnType<typeof change>>;\n\t\t},\n\t\tmemo: runtime.memo,\n\t\tcreateTask: async <I, S extends { phase: string }, R, H extends object>(\n\t\t\ttask: Task<I, S, R, H>,\n\t\t\tinput: I,\n\t\t\toptions: Omit<TaskOptions, \"conversationId\">,\n\t\t\ttaskContext: Context,\n\t\t): Promise<TaskId<R>> => {\n\t\t\tlet id: TaskId<R> | undefined;\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tid = await tx.createTask(task, input, options);\n\t\t\t\treturn undefined;\n\t\t\t}, taskContext);\n\t\t\treturn id!;\n\t\t},\n\t\tgetTask: runtime.getTask,\n\t\twaitForTask: runtime.waitForTask,\n\t\tconversation: runtime.conversation,\n\t\tsnapshot: runtime.snapshot,\n\t\tsnapshotAsOf: runtime.snapshotAsOf,\n\t\twatchDoc: runtime.watchDoc,\n\t};\n\n\tlet result: ToolExecutionResult;\n\tlet ending = COMPLETED;\n\ttry {\n\t\tresult = await tool.execute(args, api, context);\n\t} catch (error) {\n\t\tif (runtime.signal.aborted) {\n\t\t\tended = true;\n\t\t\tfor (const waiter of await progress.stop()) waiter.reject(error);\n\t\t\tthrow error;\n\t\t}\n\t\tresult = { isError: true, diagnostics: [toolDiagnostic(\"tool_error\", errorText(error))] };\n\t\t// A throw ends the task `failed`, which cancels what the call owned; it no longer supervises it. The error text\n\t\t// is already in the result entry.\n\t\tending = { status: \"failed\", message: `Tool ${call.name} threw` };\n\t}\n\tended = true;\n\treported.output.end();\n\t// Details still waiting for a progress commit settle with the terminal commit, the final flush.\n\tconst pending = await progress.stop();\n\ttry {\n\t\tconst settled = await finalResult(runtime, call, result, reported, context);\n\t\tawait settle(runtime, call, ending, () => settled, context);\n\t} catch (error) {\n\t\tfor (const waiter of pending) waiter.reject(error);\n\t\tthrow error;\n\t}\n\tfor (const waiter of pending) waiter.resolve();\n}\n\n/**\n * Throttled commits of what the tool reported into its `pi.live.tools` slot, each writing only what changed since the\n * last one.\n */\nfunction publishProgress(runtime: Runtime, reported: Reported, context: Context): Progress {\n\tlet written = { text: \"\", details: undefined as JsonValue | undefined, diagnostics: 0 };\n\treturn new Progress(\n\t\tasync () => {\n\t\t\t// Capture everything synchronously: the tool keeps reporting while the commit is in flight.\n\t\t\tconst snapshot = reported.output.snapshot();\n\t\t\tconst current = { text: snapshot.text, details: reported.details, diagnostics: reported.diagnostics.length };\n\t\t\tconst added = reported.diagnostics.slice(written.diagnostics, current.diagnostics);\n\t\t\tconst detailsChanged = current.details !== written.details;\n\t\t\t// What the commit writes, as Chord diffs the string: an append, a trim plus an append of what follows the shared\n\t\t\t// part, or the whole window when its bounded overlap search finds nothing.\n\t\t\tlet bytes = 0;\n\t\t\tif (snapshot.text !== written.text) {\n\t\t\t\tconst shared = snapshot.text.startsWith(written.text)\n\t\t\t\t\t? written.text.length\n\t\t\t\t\t: overlap(written.text, snapshot.text, 65_536);\n\t\t\t\tbytes += utf8ByteLength(snapshot.text.slice(shared));\n\t\t\t}\n\t\t\tif (detailsChanged) bytes += utf8ByteLength(JSON.stringify(current.details ?? null));\n\t\t\tif (added.length > 0) bytes += utf8ByteLength(JSON.stringify(added));\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tconst slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\t\tif (slot === undefined) return undefined;\n\t\t\t\t// REMINDER: assign `output` as one string field. Chord then diffs it into an append, or a trim plus an\n\t\t\t\t// append for a sliding tail; replacing the slot object would record the whole window on every commit.\n\t\t\t\tif ((slot.output ?? \"\") !== snapshot.text) slot.output = snapshot.text;\n\t\t\t\tif (snapshot.droppedBytes > 0) slot.droppedBytes = snapshot.droppedBytes;\n\t\t\t\tif (snapshot.droppedLines > 0) slot.droppedLines = snapshot.droppedLines;\n\t\t\t\t// Diff details leaf by leaf and append new diagnostics, so each commit writes only what changed.\n\t\t\t\tif (detailsChanged && current.details !== undefined) {\n\t\t\t\t\tassignJson(slot as unknown as Record<string, JsonValue>, \"details\", current.details);\n\t\t\t\t}\n\t\t\t\tif (added.length > 0) {\n\t\t\t\t\tif (slot.diagnostics === undefined) slot.diagnostics = [];\n\t\t\t\t\tfor (const diagnostic of added) slot.diagnostics.push(diagnostic);\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}, context);\n\t\t\twritten = current;\n\t\t\treturn bytes;\n\t\t},\n\t\t(error) => {\n\t\t\t// Rejections after an abort mark or close are expected; the committed state stays consistent.\n\t\t\tif (!runtime.signal.aborted) runtime.report(error);\n\t\t},\n\t);\n}\n\n/**\n * The settled result: the tool's result with the retained output and last details as fallbacks, its diagnostics after\n * those reported through the api, `afterTool` applied, and explicit text bounded, with the Harness's truncation\n * diagnostic last.\n */\nasync function finalResult(\n\truntime: Runtime,\n\tcall: ToolCall,\n\tresult: ToolExecutionResult,\n\treported: Reported,\n\tcontext: Context,\n): Promise<ToolExecutionResult> {\n\tconst harness: ToolDiagnostic[] = [];\n\tconst retained = result.content === undefined ? reported.output.snapshot() : undefined;\n\tconst content: Content =\n\t\tretained === undefined ? result.content! : retained.text === \"\" ? [] : [{ type: \"text\", text: retained.text }];\n\tlet final: ToolExecutionResult = {\n\t\t...result,\n\t\tcontent,\n\t\tdetails: result.details === undefined ? reported.details : result.details,\n\t\tdiagnostics: [...reported.diagnostics, ...(result.diagnostics ?? [])],\n\t};\n\tawait runtime.hooks.each(\"afterTool\", async (hook) => {\n\t\tfinal = (await hook(call, final, runtime, context)) ?? final;\n\t});\n\t// The retained output's truncation applies only while afterTool kept that content.\n\tif (retained !== undefined && retained.droppedBytes > 0 && final.content === content) {\n\t\tharness.push(truncated(retained, reported.limits.retain));\n\t}\n\tconst bounded = boundContent(final.content ?? [], reported.limits);\n\tif (bounded.droppedBytes > 0) harness.push(truncated(bounded, reported.limits.retain));\n\treturn { ...final, content: bounded.content, diagnostics: [...(final.diagnostics ?? []), ...harness] };\n}\n\n/**\n * Commit the tool's terminal state: append its result entry, mark its slot done, and complete or end aborted with the\n * entry ID. `build` receives the slot so interruption and abort can report the durable partial output.\n */\nasync function settle(\n\truntime: Runtime,\n\tcall: ToolCall,\n\tending: Ending,\n\tbuild: (slot: Readonly<ToolSlot> | undefined) => ToolExecutionResult,\n\tcontext: Context,\n): Promise<void> {\n\tawait runtime.commit(async (tx) => {\n\t\tconst slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\tconst result = build(slot);\n\t\tconst entry = await appendToolResult(tx, runtime.conversationId, call, result, runtime.now());\n\t\tif (slot !== undefined) finishSlot(slot, entry.id);\n\t\tconst entryId = entry.id;\n\t\tif (ending.status === \"aborted\")\n\t\t\treturn { status: \"terminal\", outcome: { status: \"aborted\", result: { entryId } } };\n\t\tif (ending.status === \"failed\") {\n\t\t\tconst error = { message: ending.message };\n\t\t\treturn { status: \"terminal\", outcome: { status: \"failed\", error, result: { entryId } } };\n\t\t}\n\t\t// Tools build control objects freely; drop keys set to undefined so the task result is strict JSON.\n\t\tconst control =\n\t\t\tresult.control === undefined\n\t\t\t\t? {}\n\t\t\t\t: { control: copyJson(result.control as JsonValue, { omitUndefinedProperties: true }) as ToolControl };\n\t\treturn { status: \"terminal\", outcome: { status: \"completed\", result: { entryId, ...control } } };\n\t}, context);\n}\n\n/**\n * How a tool task ends; the result entry is appended either way. `failed` (execution threw or was interrupted)\n * records cancellation intent for the conversations the call owns; a result with `isError` still completes.\n */\ntype Ending = { readonly status: \"completed\" | \"aborted\" } | { readonly status: \"failed\"; readonly message: string };\n\nconst COMPLETED: Ending = { status: \"completed\" };\n\n/** An error result from the slot's durable partial output, details, and diagnostics. */\nfunction fromSlot(slot: Readonly<ToolSlot> | undefined, code: string, message: string): ToolExecutionResult {\n\tconst diagnostics = [...(slot?.diagnostics ?? [])];\n\tconst droppedBytes = slot?.droppedBytes ?? 0;\n\tif (droppedBytes > 0) diagnostics.push(truncated({ droppedBytes, droppedLines: slot?.droppedLines ?? 0 }));\n\tdiagnostics.push(toolDiagnostic(code, message));\n\treturn {\n\t\tcontent: slot?.output === undefined || slot.output === \"\" ? [] : [{ type: \"text\", text: slot.output }],\n\t\tisError: true,\n\t\t...(slot?.details === undefined ? {} : { details: slot.details }),\n\t\tdiagnostics,\n\t};\n}\n\n/** An error result the Harness writes itself: no content and one `error` diagnostic with `code`. */\nexport function harnessError(code: string, message: string): ToolExecutionResult {\n\treturn { content: [], isError: true, diagnostics: [toolDiagnostic(code, message)] };\n}\n\nfunction toolDiagnostic(code: string, message: string): ToolDiagnostic {\n\treturn { severity: \"error\", code, message };\n}\n\n/** The Harness's truncation diagnostic; `retain` is unknown when rebuilt from a slot after recovery. */\nfunction truncated(\n\tdropped: { readonly droppedLines: number; readonly droppedBytes: number },\n\tretain?: \"head\" | \"tail\",\n): ToolDiagnostic {\n\tconst kept = retain === undefined ? \"\" : ` to its ${retain === \"head\" ? \"beginning\" : \"end\"}`;\n\treturn {\n\t\tseverity: \"warn\",\n\t\tcode: \"truncated\",\n\t\tmessage: `Output truncated${kept}: ${dropped.droppedLines} lines, ${dropped.droppedBytes} bytes dropped`,\n\t};\n}\n\n/**\n * Append a `pi.tool-result` entry. The content ends with the rendered diagnostics, so the stored message is exactly\n * what the model sees; `data` keeps the structured list. A result's usage is added to `pi.usage` in the same commit.\n */\nexport async function appendToolResult(\n\ttx: Tx,\n\tconversationId: ConversationId,\n\tcall: ToolCall,\n\tresult: ToolExecutionResult,\n\ttimestamp: number,\n): Promise<TypedEntry<{ diagnostics: ToolDiagnostic[] }>> {\n\tconst diagnostics = [...(result.diagnostics ?? [])];\n\tconst content: Content = [...(result.content ?? [])];\n\tif (diagnostics.length > 0) content.push({ type: \"text\", text: renderDiagnostics(diagnostics) });\n\tconst message = {\n\t\trole: \"toolResult\",\n\t\ttoolCallId: call.id,\n\t\ttoolName: call.name,\n\t\tcontent,\n\t\t...(result.details === undefined ? {} : { details: result.details }),\n\t\t...(result.usage === undefined ? {} : { usage: result.usage }),\n\t\tisError: result.isError ?? false,\n\t\ttimestamp,\n\t} as ToolResultMessage;\n\tif (result.usage !== undefined) await recordUsage(tx, conversationId, \"tools\", call.name, result.usage);\n\treturn tx.appendEntry(ToolResultEntry, conversationId, { model: [message], data: { diagnostics } });\n}\n\nfunction renderDiagnostics(diagnostics: readonly ToolDiagnostic[]): string {\n\treturn `<harness>\\n${diagnostics.map((diagnostic) => `[${diagnostic.severity}] ${diagnostic.message}`).join(\"\\n\")}\\n</harness>`;\n}\n\n/**\n * Bound the text of result content. When the joined text exceeds the limits, the text items are replaced by one bounded\n * item at the position of the first (head) or last (tail) text item; other content is kept.\n */\nfunction boundContent(\n\tcontent: Content,\n\tlimits: OutputLimits,\n): { content: Content; droppedBytes: number; droppedLines: number } {\n\tconst texts = content.filter((item): item is TextContent => item.type === \"text\");\n\tconst bounded = boundOutput(texts.map((item) => item.text).join(\"\"), limits);\n\tif (bounded.droppedBytes === 0) return { content, droppedBytes: 0, droppedLines: 0 };\n\tconst keep = limits.retain === \"head\" ? texts[0] : texts.at(-1);\n\tconst result: Content = [];\n\tfor (const item of content) {\n\t\tif (item.type !== \"text\") result.push(item);\n\t\telse if (item === keep) result.push({ ...item, text: bounded.text });\n\t}\n\treturn { content: result, droppedBytes: bounded.droppedBytes, droppedLines: bounded.droppedLines };\n}\n\nfunction errorText(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n"]}
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/harness/tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Context, copyJson, type JsonValue } from \"@earendil-works/chord\";\nimport { awaitWithContext } from \"@earendil-works/chord/context\";\nimport { overlap } from \"@earendil-works/chord/delta\";\nimport type { ImageContent, TextContent, ToolCall, ToolResultMessage } from \"@earendil-works/pi-ai\";\nimport { validateToolArguments } from \"@earendil-works/pi-ai/utils/validation\";\nimport { AssistantEntry, ToolResultEntry } from \"../entries.ts\";\nimport { defineTask } from \"../tasks.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, utf8ByteLength } from \"../truncate.ts\";\nimport type {\n\tConversationId,\n\tEntryId,\n\tJsonObject,\n\tTask,\n\tTaskId,\n\tTaskOptions,\n\tTaskRuntime,\n\tTx,\n\tTypedEntry,\n} from \"../types.ts\";\nimport { assignJson } from \"./json.ts\";\nimport { clearProgress, finishSlot, LiveDoc, type ToolSlot, toolSlot } from \"./live.ts\";\nimport { boundOutput, OutputBuffer, type OutputLimits, Progress } from \"./output.ts\";\nimport type {\n\tToolControl,\n\tToolDiagnostic,\n\tToolExecutionApi,\n\tToolExecutionResult,\n\tToolHooks,\n\tToolRegistration,\n} from \"./types.ts\";\nimport { recordUsage } from \"./usage.ts\";\n\nexport type ToolTaskInput = { assistant: EntryId; callId: string };\n\nexport type ToolTaskCheckpoint =\n\t| { phase: \"call\" }\n\t/** Durable intent: the final arguments and the replay policy recorded before execution. */\n\t| { phase: \"execute\"; arguments: JsonObject; replay: \"safe\" | \"unsafe\" };\n\nexport type ToolTaskResult = { entryId: EntryId; control?: ToolControl };\n\ntype Runtime = TaskRuntime<ToolTaskInput, ToolTaskCheckpoint, ToolTaskResult, ToolHooks>;\ntype Content = (TextContent | ImageContent)[];\n\n/**\n * Built-in tool task: resolves the called tool among its phase agent's tools, validates, runs `beforeTool`, records intent,\n * executes, runs `afterTool`, and appends the result, all in one `call` handler so nothing separates resolution from\n * settlement. `execute` is reached only by recovery and applies the replay rule.\n */\nexport const ToolTask = defineTask<ToolTaskInput, ToolTaskCheckpoint, ToolTaskResult, ToolHooks>({\n\tname: \"pi.tool\",\n\tversion: 1,\n\tinitial: () => ({ phase: \"call\" }),\n\tphases: {\n\t\tcall: async (task, runtime, context) => {\n\t\t\tconst call = await readCall(runtime, task.input, context);\n\t\t\tconst tool = (await runtime.agent(context)).tools.find((each) => each.name === call.name);\n\t\t\tif (tool === undefined) {\n\t\t\t\tconst error = harnessError(\"tool_unavailable\", `Tool ${call.name} is not available`);\n\t\t\t\treturn settle(runtime, call, COMPLETED, () => error, context);\n\t\t\t}\n\t\t\tconst prepared = prepare(tool, call.arguments as JsonObject);\n\t\t\tconst checked = \"error\" in prepared ? prepared : validate(tool, call, prepared.args);\n\t\t\tif (\"error\" in checked) return settle(runtime, call, COMPLETED, () => invalid(checked.error), context);\n\t\t\tlet args = checked.args;\n\t\t\tlet block: string | undefined;\n\t\t\tawait runtime.hooks.each(\"beforeTool\", async (hook) => {\n\t\t\t\tif (block !== undefined) return;\n\t\t\t\ttry {\n\t\t\t\t\tconst decision = await hook({ ...call, arguments: args }, runtime, context);\n\t\t\t\t\tif (decision?.block !== undefined) block = decision.block;\n\t\t\t\t\telse if (decision?.arguments !== undefined) args = decision.arguments;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (runtime.signal.aborted) throw error;\n\t\t\t\t\tblock = errorText(error);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (block !== undefined) {\n\t\t\t\tconst blocked = harnessError(\"blocked\", `Tool call blocked: ${block}`);\n\t\t\t\treturn settle(runtime, call, COMPLETED, () => blocked, context);\n\t\t\t}\n\t\t\tconst validated = validate(tool, call, args);\n\t\t\tif (\"error\" in validated) return settle(runtime, call, COMPLETED, () => invalid(validated.error), context);\n\t\t\tconst final = validated.args;\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tconst slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\t\tif (slot !== undefined) slot.status = \"running\";\n\t\t\t\tconst intent = { phase: \"execute\", arguments: final, replay: tool.replay ?? \"unsafe\" } as const;\n\t\t\t\treturn { status: \"running\", checkpoint: intent };\n\t\t\t}, context);\n\t\t\tawait run(runtime, call, tool, final, context);\n\t\t},\n\t\t/** Recovery after intent: rerun only when the stored and the current policy both say `safe`. */\n\t\texecute: async (task, runtime, context) => {\n\t\t\tconst { arguments: args, replay } = task.state.checkpoint;\n\t\t\tconst call = await readCall(runtime, task.input, context);\n\t\t\tconst tool = (await runtime.agent(context)).tools.find((each) => each.name === call.name);\n\t\t\tif (replay === \"safe\" && tool?.replay === \"safe\") {\n\t\t\t\t// The rerun reports from scratch; clear what the interrupted attempt published.\n\t\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\t\tconst slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\t\t\tif (slot !== undefined) clearProgress(slot);\n\t\t\t\t\treturn undefined;\n\t\t\t\t}, context);\n\t\t\t\treturn run(runtime, call, tool, args, context);\n\t\t\t}\n\t\t\tconst message = `Tool ${call.name} was interrupted and may have partially run`;\n\t\t\t// `failed` records cancellation intent, so the call's owned conversations, left unsupervised, are aborted.\n\t\t\tconst ending = { status: \"failed\", message } as const;\n\t\t\tawait settle(runtime, call, ending, (slot) => fromSlot(slot, \"interrupted\", message), context);\n\t\t},\n\t},\n\tabort: async (task, runtime, context) => {\n\t\tconst call = await readCall(runtime, task.input, context);\n\t\tconst message = `Tool ${call.name} was aborted`;\n\t\tawait settle(runtime, call, { status: \"aborted\" }, (slot) => fromSlot(slot, \"aborted\", message), context);\n\t},\n});\n\n/** The tool call `callId` of the assistant entry. */\nasync function readCall(runtime: Runtime, input: ToolTaskInput, context: Context): Promise<ToolCall> {\n\tconst entry = await runtime.entry(AssistantEntry, input.assistant, context);\n\tconst message = entry?.model?.[0];\n\tconst call =\n\t\tmessage?.role === \"assistant\"\n\t\t\t? message.content.find(\n\t\t\t\t\t(content): content is ToolCall => content.type === \"toolCall\" && content.id === input.callId,\n\t\t\t\t)\n\t\t\t: undefined;\n\tif (call === undefined) throw new Error(`Entry ${input.assistant} has no tool call ${input.callId}`);\n\treturn call;\n}\n\n/** Arguments, or why they are invalid. */\ntype Checked = { readonly args: JsonObject } | { readonly error: string };\n\n/** The call's arguments as repaired by the tool; a throwing repair makes them invalid. */\nfunction prepare(tool: ToolRegistration, args: JsonObject): Checked {\n\tif (tool.prepareArguments === undefined) return { args };\n\ttry {\n\t\treturn { args: tool.prepareArguments(args) as JsonObject };\n\t} catch (error) {\n\t\treturn { error: errorText(error) };\n\t}\n}\n\n/** Arguments validated and coerced against the implementation's schema. */\nfunction validate(tool: ToolRegistration, call: ToolCall, args: JsonObject): Checked {\n\ttry {\n\t\treturn { args: validateToolArguments(tool, { ...call, arguments: args }) as JsonObject };\n\t} catch (error) {\n\t\treturn { error: errorText(error) };\n\t}\n}\n\nfunction invalid(message: string): ToolExecutionResult {\n\treturn harnessError(\"invalid_arguments\", message);\n}\n\n/** What a running tool reported through its api: output, the last details, and diagnostics. */\ntype Reported = {\n\treadonly output: OutputBuffer;\n\treadonly limits: OutputLimits;\n\treadonly diagnostics: ToolDiagnostic[];\n\tdetails: JsonValue | undefined;\n};\n\n/** Execute with the resolved implementation, then settle its result. */\nasync function run(\n\truntime: Runtime,\n\tcall: ToolCall,\n\ttool: ToolRegistration,\n\targs: JsonObject,\n\tcontext: Context,\n): Promise<void> {\n\tconst limits: OutputLimits = {\n\t\tmaxBytes: tool.outputLimits?.maxBytes ?? DEFAULT_MAX_BYTES,\n\t\tmaxLines: tool.outputLimits?.maxLines ?? DEFAULT_MAX_LINES,\n\t\tretain: tool.outputLimits?.retain ?? \"head\",\n\t};\n\tconst reported: Reported = { output: new OutputBuffer(limits), limits, diagnostics: [], details: undefined };\n\tconst progress = publishProgress(runtime, reported, context);\n\tlet ended = false;\n\tconst assertLive = (): void => {\n\t\tif (ended) throw new Error(`Tool call ${call.id} has settled`);\n\t};\n\tconst api: Omit<ToolExecutionApi, \"env\"> = {\n\t\ttaskId: runtime.taskId,\n\t\tconversationId: runtime.conversationId,\n\t\tcallId: call.id,\n\t\tregistry: runtime.registry,\n\t\tagent: runtime.agent,\n\t\toutput: (chunk) => {\n\t\t\tassertLive();\n\t\t\tif (reported.output.push(chunk)) progress.mark();\n\t\t},\n\t\tdiagnostic: (diagnostic) => {\n\t\t\tassertLive();\n\t\t\treported.diagnostics.push(copyJson(diagnostic, { omitUndefinedProperties: true }) as ToolDiagnostic);\n\t\t\tprogress.mark();\n\t\t},\n\t\tdetails: async (value, detailsContext) => {\n\t\t\tassertLive();\n\t\t\tdetailsContext.abortSignal?.throwIfAborted();\n\t\t\treported.details = copyJson(value, { omitUndefinedProperties: true });\n\t\t\tconst committed = progress.markAndWait();\n\t\t\t// Cancelling the wait leaves the update in place; the commit's own outcome stays observed.\n\t\t\tcommitted.catch(() => {});\n\t\t\treturn awaitWithContext(committed, detailsContext);\n\t\t},\n\t\tcommit: async (change, commitContext) => {\n\t\t\tlet result: Awaited<ReturnType<typeof change>> | undefined;\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tresult = await change(tx);\n\t\t\t\treturn undefined;\n\t\t\t}, commitContext);\n\t\t\treturn result as Awaited<ReturnType<typeof change>>;\n\t\t},\n\t\tmemo: runtime.memo,\n\t\tcreateTask: async <I, S extends { phase: string }, R, H extends object>(\n\t\t\ttask: Task<I, S, R, H>,\n\t\t\tinput: I,\n\t\t\toptions: Omit<TaskOptions, \"conversationId\">,\n\t\t\ttaskContext: Context,\n\t\t): Promise<TaskId<R>> => {\n\t\t\tlet id: TaskId<R> | undefined;\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tid = await tx.createTask(task, input, options);\n\t\t\t\treturn undefined;\n\t\t\t}, taskContext);\n\t\t\treturn id!;\n\t\t},\n\t\tgetTask: runtime.getTask,\n\t\twaitForTask: runtime.waitForTask,\n\t\tconversation: runtime.conversation,\n\t\tsnapshot: runtime.snapshot,\n\t\tsnapshotAsOf: runtime.snapshotAsOf,\n\t\twatchDoc: runtime.watchDoc,\n\t};\n\n\tlet result: ToolExecutionResult;\n\tlet ending = COMPLETED;\n\ttry {\n\t\t// Built for this call, so a rerun after recovery gets the conversation's environment at that time.\n\t\tconst env = await runtime.env(context);\n\t\tresult = await tool.execute(args, { ...api, env }, context);\n\t} catch (error) {\n\t\tif (runtime.signal.aborted) {\n\t\t\tended = true;\n\t\t\tfor (const waiter of await progress.stop()) waiter.reject(error);\n\t\t\tthrow error;\n\t\t}\n\t\tresult = { isError: true, diagnostics: [toolDiagnostic(\"tool_error\", errorText(error))] };\n\t\t// A throw, from `execute()` or from building the environment, ends the task `failed`, which cancels what the call owned; it no longer supervises it. The error text\n\t\t// is already in the result entry.\n\t\tending = { status: \"failed\", message: `Tool ${call.name} threw` };\n\t}\n\tended = true;\n\treported.output.end();\n\t// Details still waiting for a progress commit settle with the terminal commit, the final flush.\n\tconst pending = await progress.stop();\n\ttry {\n\t\tconst settled = await finalResult(runtime, call, result, reported, context);\n\t\tawait settle(runtime, call, ending, () => settled, context);\n\t} catch (error) {\n\t\tfor (const waiter of pending) waiter.reject(error);\n\t\tthrow error;\n\t}\n\tfor (const waiter of pending) waiter.resolve();\n}\n\n/**\n * Throttled commits of what the tool reported into its `pi.live.tools` slot, each writing only what changed since the\n * last one.\n */\nfunction publishProgress(runtime: Runtime, reported: Reported, context: Context): Progress {\n\tlet written = { text: \"\", details: undefined as JsonValue | undefined, diagnostics: 0 };\n\treturn new Progress(\n\t\tasync () => {\n\t\t\t// Capture everything synchronously: the tool keeps reporting while the commit is in flight.\n\t\t\tconst snapshot = reported.output.snapshot();\n\t\t\tconst current = { text: snapshot.text, details: reported.details, diagnostics: reported.diagnostics.length };\n\t\t\tconst added = reported.diagnostics.slice(written.diagnostics, current.diagnostics);\n\t\t\tconst detailsChanged = current.details !== written.details;\n\t\t\t// What the commit writes, as Chord diffs the string: an append, a trim plus an append of what follows the shared\n\t\t\t// part, or the whole window when its bounded overlap search finds nothing.\n\t\t\tlet bytes = 0;\n\t\t\tif (snapshot.text !== written.text) {\n\t\t\t\tconst shared = snapshot.text.startsWith(written.text)\n\t\t\t\t\t? written.text.length\n\t\t\t\t\t: overlap(written.text, snapshot.text, 65_536);\n\t\t\t\tbytes += utf8ByteLength(snapshot.text.slice(shared));\n\t\t\t}\n\t\t\tif (detailsChanged) bytes += utf8ByteLength(JSON.stringify(current.details ?? null));\n\t\t\tif (added.length > 0) bytes += utf8ByteLength(JSON.stringify(added));\n\t\t\tawait runtime.commit(async (tx) => {\n\t\t\t\tconst slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\t\t\tif (slot === undefined) return undefined;\n\t\t\t\t// REMINDER: assign `output` as one string field. Chord then diffs it into an append, or a trim plus an\n\t\t\t\t// append for a sliding tail; replacing the slot object would record the whole window on every commit.\n\t\t\t\tif ((slot.output ?? \"\") !== snapshot.text) slot.output = snapshot.text;\n\t\t\t\tif (snapshot.droppedBytes > 0) slot.droppedBytes = snapshot.droppedBytes;\n\t\t\t\tif (snapshot.droppedLines > 0) slot.droppedLines = snapshot.droppedLines;\n\t\t\t\t// Diff details leaf by leaf and append new diagnostics, so each commit writes only what changed.\n\t\t\t\tif (detailsChanged && current.details !== undefined) {\n\t\t\t\t\tassignJson(slot as unknown as Record<string, JsonValue>, \"details\", current.details);\n\t\t\t\t}\n\t\t\t\tif (added.length > 0) {\n\t\t\t\t\tif (slot.diagnostics === undefined) slot.diagnostics = [];\n\t\t\t\t\tfor (const diagnostic of added) slot.diagnostics.push(diagnostic);\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}, context);\n\t\t\twritten = current;\n\t\t\treturn bytes;\n\t\t},\n\t\t(error) => {\n\t\t\t// Rejections after an abort mark or close are expected; the committed state stays consistent.\n\t\t\tif (!runtime.signal.aborted) runtime.report(error);\n\t\t},\n\t);\n}\n\n/**\n * The settled result: the tool's result with the retained output and last details as fallbacks, its diagnostics after\n * those reported through the api, `afterTool` applied, and explicit text bounded, with the Harness's truncation\n * diagnostic last.\n */\nasync function finalResult(\n\truntime: Runtime,\n\tcall: ToolCall,\n\tresult: ToolExecutionResult,\n\treported: Reported,\n\tcontext: Context,\n): Promise<ToolExecutionResult> {\n\tconst harness: ToolDiagnostic[] = [];\n\tconst retained = result.content === undefined ? reported.output.snapshot() : undefined;\n\tconst content: Content =\n\t\tretained === undefined ? result.content! : retained.text === \"\" ? [] : [{ type: \"text\", text: retained.text }];\n\tlet final: ToolExecutionResult = {\n\t\t...result,\n\t\tcontent,\n\t\tdetails: result.details === undefined ? reported.details : result.details,\n\t\tdiagnostics: [...reported.diagnostics, ...(result.diagnostics ?? [])],\n\t};\n\tawait runtime.hooks.each(\"afterTool\", async (hook) => {\n\t\tfinal = (await hook(call, final, runtime, context)) ?? final;\n\t});\n\t// The retained output's truncation applies only while afterTool kept that content.\n\tif (retained !== undefined && retained.droppedBytes > 0 && final.content === content) {\n\t\tharness.push(truncated(retained, reported.limits.retain));\n\t}\n\tconst bounded = boundContent(final.content ?? [], reported.limits);\n\tif (bounded.droppedBytes > 0) harness.push(truncated(bounded, reported.limits.retain));\n\treturn { ...final, content: bounded.content, diagnostics: [...(final.diagnostics ?? []), ...harness] };\n}\n\n/**\n * Commit the tool's terminal state: append its result entry, mark its slot done, and complete or end aborted with the\n * entry ID. `build` receives the slot so interruption and abort can report the durable partial output.\n */\nasync function settle(\n\truntime: Runtime,\n\tcall: ToolCall,\n\tending: Ending,\n\tbuild: (slot: Readonly<ToolSlot> | undefined) => ToolExecutionResult,\n\tcontext: Context,\n): Promise<void> {\n\tawait runtime.commit(async (tx) => {\n\t\tconst slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);\n\t\tconst result = build(slot);\n\t\tconst entry = await appendToolResult(tx, runtime.conversationId, call, result, runtime.now());\n\t\tif (slot !== undefined) finishSlot(slot, entry.id);\n\t\tconst entryId = entry.id;\n\t\tif (ending.status === \"aborted\")\n\t\t\treturn { status: \"terminal\", outcome: { status: \"aborted\", result: { entryId } } };\n\t\tif (ending.status === \"failed\") {\n\t\t\tconst error = { message: ending.message };\n\t\t\treturn { status: \"terminal\", outcome: { status: \"failed\", error, result: { entryId } } };\n\t\t}\n\t\t// Tools build control objects freely; drop keys set to undefined so the task result is strict JSON.\n\t\tconst control =\n\t\t\tresult.control === undefined\n\t\t\t\t? {}\n\t\t\t\t: { control: copyJson(result.control as JsonValue, { omitUndefinedProperties: true }) as ToolControl };\n\t\treturn { status: \"terminal\", outcome: { status: \"completed\", result: { entryId, ...control } } };\n\t}, context);\n}\n\n/**\n * How a tool task ends; the result entry is appended either way. `failed` (execution threw or was interrupted)\n * records cancellation intent for the conversations the call owns; a result with `isError` still completes.\n */\ntype Ending = { readonly status: \"completed\" | \"aborted\" } | { readonly status: \"failed\"; readonly message: string };\n\nconst COMPLETED: Ending = { status: \"completed\" };\n\n/** An error result from the slot's durable partial output, details, and diagnostics. */\nfunction fromSlot(slot: Readonly<ToolSlot> | undefined, code: string, message: string): ToolExecutionResult {\n\tconst diagnostics = [...(slot?.diagnostics ?? [])];\n\tconst droppedBytes = slot?.droppedBytes ?? 0;\n\tif (droppedBytes > 0) diagnostics.push(truncated({ droppedBytes, droppedLines: slot?.droppedLines ?? 0 }));\n\tdiagnostics.push(toolDiagnostic(code, message));\n\treturn {\n\t\tcontent: slot?.output === undefined || slot.output === \"\" ? [] : [{ type: \"text\", text: slot.output }],\n\t\tisError: true,\n\t\t...(slot?.details === undefined ? {} : { details: slot.details }),\n\t\tdiagnostics,\n\t};\n}\n\n/** An error result the Harness writes itself: no content and one `error` diagnostic with `code`. */\nexport function harnessError(code: string, message: string): ToolExecutionResult {\n\treturn { content: [], isError: true, diagnostics: [toolDiagnostic(code, message)] };\n}\n\nfunction toolDiagnostic(code: string, message: string): ToolDiagnostic {\n\treturn { severity: \"error\", code, message };\n}\n\n/** The Harness's truncation diagnostic; `retain` is unknown when rebuilt from a slot after recovery. */\nfunction truncated(\n\tdropped: { readonly droppedLines: number; readonly droppedBytes: number },\n\tretain?: \"head\" | \"tail\",\n): ToolDiagnostic {\n\tconst kept = retain === undefined ? \"\" : ` to its ${retain === \"head\" ? \"beginning\" : \"end\"}`;\n\treturn {\n\t\tseverity: \"warn\",\n\t\tcode: \"truncated\",\n\t\tmessage: `Output truncated${kept}: ${dropped.droppedLines} lines, ${dropped.droppedBytes} bytes dropped`,\n\t};\n}\n\n/**\n * Append a `pi.tool-result` entry. The content ends with the rendered diagnostics, so the stored message is exactly\n * what the model sees; `data` keeps the structured list. A result's usage is added to `pi.usage` in the same commit.\n */\nexport async function appendToolResult(\n\ttx: Tx,\n\tconversationId: ConversationId,\n\tcall: ToolCall,\n\tresult: ToolExecutionResult,\n\ttimestamp: number,\n): Promise<TypedEntry<{ diagnostics: ToolDiagnostic[] }>> {\n\tconst diagnostics = [...(result.diagnostics ?? [])];\n\tconst content: Content = [...(result.content ?? [])];\n\tif (diagnostics.length > 0) content.push({ type: \"text\", text: renderDiagnostics(diagnostics) });\n\tconst message = {\n\t\trole: \"toolResult\",\n\t\ttoolCallId: call.id,\n\t\ttoolName: call.name,\n\t\tcontent,\n\t\t...(result.details === undefined ? {} : { details: result.details }),\n\t\t...(result.usage === undefined ? {} : { usage: result.usage }),\n\t\tisError: result.isError ?? false,\n\t\ttimestamp,\n\t} as ToolResultMessage;\n\tif (result.usage !== undefined) await recordUsage(tx, conversationId, \"tools\", call.name, result.usage);\n\treturn tx.appendEntry(ToolResultEntry, conversationId, { model: [message], data: { diagnostics } });\n}\n\nfunction renderDiagnostics(diagnostics: readonly ToolDiagnostic[]): string {\n\treturn `<harness>\\n${diagnostics.map((diagnostic) => `[${diagnostic.severity}] ${diagnostic.message}`).join(\"\\n\")}\\n</harness>`;\n}\n\n/**\n * Bound the text of result content. When the joined text exceeds the limits, the text items are replaced by one bounded\n * item at the position of the first (head) or last (tail) text item; other content is kept.\n */\nfunction boundContent(\n\tcontent: Content,\n\tlimits: OutputLimits,\n): { content: Content; droppedBytes: number; droppedLines: number } {\n\tconst texts = content.filter((item): item is TextContent => item.type === \"text\");\n\tconst bounded = boundOutput(texts.map((item) => item.text).join(\"\"), limits);\n\tif (bounded.droppedBytes === 0) return { content, droppedBytes: 0, droppedLines: 0 };\n\tconst keep = limits.retain === \"head\" ? texts[0] : texts.at(-1);\n\tconst result: Content = [];\n\tfor (const item of content) {\n\t\tif (item.type !== \"text\") result.push(item);\n\t\telse if (item === keep) result.push({ ...item, text: bounded.text });\n\t}\n\treturn { content: result, droppedBytes: bounded.droppedBytes, droppedLines: bounded.droppedLines };\n}\n\nfunction errorText(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n"]}