@alvin0/ai-agent-sdk-core 0.1.0 → 0.1.2

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 (178) hide show
  1. package/dist/agent/define/session/model-config.js +1 -1
  2. package/dist/agent/define/session/model-config.js.map +1 -1
  3. package/dist/agent/define/session/types.d.ts +21 -0
  4. package/dist/agent/define/session/types.d.ts.map +1 -1
  5. package/dist/agent/define/session.d.ts +2 -0
  6. package/dist/agent/define/session.d.ts.map +1 -1
  7. package/dist/agent/define/session.js +1 -1
  8. package/dist/agent/define/session.js.map +1 -1
  9. package/dist/agent/history/validation.js +1 -1
  10. package/dist/agent/history/validation.js.map +1 -1
  11. package/dist/agent/loop/events.d.ts +5 -0
  12. package/dist/agent/loop/events.d.ts.map +1 -1
  13. package/dist/agent/loop/schedule.js +1 -1
  14. package/dist/agent/loop/schedule.js.map +1 -1
  15. package/dist/agent/loop/turn/model-round.js +1 -1
  16. package/dist/agent/loop/turn/model-round.js.map +1 -1
  17. package/dist/agent/loop/turn/types.d.ts +2 -0
  18. package/dist/agent/loop/turn/types.d.ts.map +1 -1
  19. package/dist/agent/loop/turn/validation.js +1 -1
  20. package/dist/agent/loop/turn/validation.js.map +1 -1
  21. package/dist/agent/memory/compaction.d.ts +10 -1
  22. package/dist/agent/memory/compaction.d.ts.map +1 -1
  23. package/dist/agent/memory/compaction.js +2 -2
  24. package/dist/agent/memory/compaction.js.map +1 -1
  25. package/dist/agent/memory/token-estimator.js +1 -1
  26. package/dist/agent/memory/token-estimator.js.map +1 -1
  27. package/dist/agent/mode/run-agent.js +1 -1
  28. package/dist/agent/mode/run-agent.js.map +1 -1
  29. package/dist/composition/agent/options.js +1 -1
  30. package/dist/composition/agent/options.js.map +1 -1
  31. package/dist/composition/agent/session.js +1 -1
  32. package/dist/composition/agent/session.js.map +1 -1
  33. package/dist/composition/agent/types.d.ts +43 -1
  34. package/dist/composition/agent/types.d.ts.map +1 -1
  35. package/dist/composition/common/errors.d.ts.map +1 -1
  36. package/dist/composition/common/errors.js +1 -1
  37. package/dist/composition/common/errors.js.map +1 -1
  38. package/dist/composition/embedding/activation.js +2 -0
  39. package/dist/composition/embedding/activation.js.map +1 -0
  40. package/dist/composition/embedding/cache.js +2 -0
  41. package/dist/composition/embedding/cache.js.map +1 -0
  42. package/dist/composition/embedding/definition.d.ts +7 -0
  43. package/dist/composition/embedding/definition.d.ts.map +1 -0
  44. package/dist/composition/embedding/definition.js +2 -0
  45. package/dist/composition/embedding/definition.js.map +1 -0
  46. package/dist/composition/embedding/handle.js +2 -0
  47. package/dist/composition/embedding/handle.js.map +1 -0
  48. package/dist/composition/embedding/limiter.js +2 -0
  49. package/dist/composition/embedding/limiter.js.map +1 -0
  50. package/dist/composition/embedding/manager.js +2 -0
  51. package/dist/composition/embedding/manager.js.map +1 -0
  52. package/dist/composition/embedding/observation.js +2 -0
  53. package/dist/composition/embedding/observation.js.map +1 -0
  54. package/dist/composition/embedding/planner.js +2 -0
  55. package/dist/composition/embedding/planner.js.map +1 -0
  56. package/dist/composition/embedding/plugin-types.d.ts +48 -0
  57. package/dist/composition/embedding/plugin-types.d.ts.map +1 -0
  58. package/dist/composition/embedding/plugin-types.js +2 -0
  59. package/dist/composition/embedding/plugin-types.js.map +1 -0
  60. package/dist/composition/embedding/preflight.js +2 -0
  61. package/dist/composition/embedding/preflight.js.map +1 -0
  62. package/dist/composition/embedding/registry.js +2 -0
  63. package/dist/composition/embedding/registry.js.map +1 -0
  64. package/dist/composition/embedding/retry.js +2 -0
  65. package/dist/composition/embedding/retry.js.map +1 -0
  66. package/dist/composition/embedding/usage.js +2 -0
  67. package/dist/composition/embedding/usage.js.map +1 -0
  68. package/dist/composition/lifecycle/types.d.ts +5 -1
  69. package/dist/composition/lifecycle/types.d.ts.map +1 -1
  70. package/dist/composition/lifecycle/types.js +1 -1
  71. package/dist/composition/lifecycle/types.js.map +1 -1
  72. package/dist/composition/preflight.js +1 -1
  73. package/dist/composition/preflight.js.map +1 -1
  74. package/dist/composition/provider/activation.js +1 -1
  75. package/dist/composition/provider/activation.js.map +1 -1
  76. package/dist/composition/provider/model-selection.js +1 -1
  77. package/dist/composition/provider/model-selection.js.map +1 -1
  78. package/dist/composition/provider/preflight.js +1 -1
  79. package/dist/composition/provider/preflight.js.map +1 -1
  80. package/dist/composition/runtime/owner.js +1 -1
  81. package/dist/composition/runtime/owner.js.map +1 -1
  82. package/dist/composition/runtime/public.js +1 -1
  83. package/dist/composition/runtime/public.js.map +1 -1
  84. package/dist/composition/runtime/types.d.ts +25 -2
  85. package/dist/composition/runtime/types.d.ts.map +1 -1
  86. package/dist/composition/startup.js +1 -1
  87. package/dist/composition/startup.js.map +1 -1
  88. package/dist/composition/team/options.js +1 -1
  89. package/dist/composition/team/options.js.map +1 -1
  90. package/dist/composition/team/runtime.js +1 -1
  91. package/dist/composition/team/runtime.js.map +1 -1
  92. package/dist/composition/team/types.d.ts +3 -0
  93. package/dist/composition/team/types.d.ts.map +1 -1
  94. package/dist/contract/generate-options.d.ts +2 -0
  95. package/dist/contract/generate-options.d.ts.map +1 -1
  96. package/dist/contract/model-info.d.ts +12 -2
  97. package/dist/contract/model-info.d.ts.map +1 -1
  98. package/dist/embedding/adapter.d.ts +104 -0
  99. package/dist/embedding/adapter.d.ts.map +1 -0
  100. package/dist/embedding/adapter.js +2 -0
  101. package/dist/embedding/adapter.js.map +1 -0
  102. package/dist/embedding/catalog.d.ts +82 -0
  103. package/dist/embedding/catalog.d.ts.map +1 -0
  104. package/dist/embedding/catalog.js +2 -0
  105. package/dist/embedding/catalog.js.map +1 -0
  106. package/dist/embedding/errors.d.ts +98 -0
  107. package/dist/embedding/errors.d.ts.map +1 -0
  108. package/dist/embedding/errors.js +2 -0
  109. package/dist/embedding/errors.js.map +1 -0
  110. package/dist/embedding/handle.d.ts +76 -0
  111. package/dist/embedding/handle.d.ts.map +1 -0
  112. package/dist/embedding/limits.d.ts +47 -0
  113. package/dist/embedding/limits.d.ts.map +1 -0
  114. package/dist/embedding/limits.js +2 -0
  115. package/dist/embedding/limits.js.map +1 -0
  116. package/dist/embedding/profile.d.ts +89 -0
  117. package/dist/embedding/profile.d.ts.map +1 -0
  118. package/dist/embedding/profile.js +2 -0
  119. package/dist/embedding/profile.js.map +1 -0
  120. package/dist/embedding/purpose.d.ts +37 -0
  121. package/dist/embedding/purpose.d.ts.map +1 -0
  122. package/dist/embedding/request.d.ts +54 -0
  123. package/dist/embedding/request.d.ts.map +1 -0
  124. package/dist/embedding/request.js +2 -0
  125. package/dist/embedding/request.js.map +1 -0
  126. package/dist/embedding/result.d.ts +50 -0
  127. package/dist/embedding/result.d.ts.map +1 -0
  128. package/dist/embedding/usage.d.ts +64 -0
  129. package/dist/embedding/usage.d.ts.map +1 -0
  130. package/dist/embedding/usage.js +2 -0
  131. package/dist/embedding/usage.js.map +1 -0
  132. package/dist/embedding/validation.d.ts +68 -0
  133. package/dist/embedding/validation.d.ts.map +1 -0
  134. package/dist/embedding/validation.js +2 -0
  135. package/dist/embedding/validation.js.map +1 -0
  136. package/dist/embedding.d.ts +12 -0
  137. package/dist/embedding.js +1 -0
  138. package/dist/index.d.ts +6 -3
  139. package/dist/index.js +1 -1
  140. package/dist/message/content.d.ts +71 -1
  141. package/dist/message/content.d.ts.map +1 -1
  142. package/dist/message/projection.d.ts +28 -2
  143. package/dist/message/projection.d.ts.map +1 -1
  144. package/dist/message/projection.js +1 -1
  145. package/dist/message/projection.js.map +1 -1
  146. package/dist/observability/bus.js +1 -1
  147. package/dist/observation/event.d.ts +1 -1
  148. package/dist/observation/event.d.ts.map +1 -1
  149. package/dist/observation/event.js.map +1 -1
  150. package/dist/observation/port.d.ts +1 -1
  151. package/dist/observation/port.d.ts.map +1 -1
  152. package/dist/observation/port.js.map +1 -1
  153. package/dist/observation/privacy.js +1 -1
  154. package/dist/observation/privacy.js.map +1 -1
  155. package/dist/observation/report.d.ts +2 -0
  156. package/dist/observation/report.d.ts.map +1 -1
  157. package/dist/observation/report.js.map +1 -1
  158. package/dist/primitives/version.d.ts +1 -1
  159. package/dist/primitives/version.js +1 -1
  160. package/dist/primitives/version.js.map +1 -1
  161. package/dist/provider.d.ts +3 -1
  162. package/dist/provider.js +1 -1
  163. package/dist/runtime/model-call-handle.js +1 -1
  164. package/dist/runtime/model-call-handle.js.map +1 -1
  165. package/dist/runtime/model-metadata.js +1 -1
  166. package/dist/runtime/model-metadata.js.map +1 -1
  167. package/dist/runtime/model-stream.js +1 -1
  168. package/dist/runtime/model-stream.js.map +1 -1
  169. package/dist/runtime/registry.js +1 -1
  170. package/dist/runtime/with-retry.d.ts.map +1 -1
  171. package/dist/runtime/with-retry.js +1 -1
  172. package/dist/runtime/with-retry.js.map +1 -1
  173. package/dist/stream/assembler.d.ts.map +1 -1
  174. package/dist/stream/assembler.js +1 -1
  175. package/dist/stream/assembler.js.map +1 -1
  176. package/dist/stream/chunk.d.ts +6 -0
  177. package/dist/stream/chunk.d.ts.map +1 -1
  178. package/package.json +6 -1
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","names":[],"sources":["../../../src/agent/history/validation.ts"],"sourcesContent":["import type { Message } from '../../message/index.ts'\nimport {\n type SurfaceOp, type HistoryEvent, type HistoryEntry, type HistorySnapshot,\n type ResolvedHistoryLimits,\n} from './types.ts'\nimport { MAX_CONTENT_DEPTH, serializedBytes } from './config.ts'\n\nexport function snapshotEntries(value: unknown): readonly HistoryEntry[] {\n if (typeof value !== 'object' || value === null) throw new TypeError('history snapshot must be an object')\n const snapshot = value as Partial<HistorySnapshot>\n if (snapshot.version !== 1) throw new TypeError('unsupported history snapshot version')\n if (!Array.isArray(snapshot.entries)) throw new TypeError('history snapshot entries must be an array')\n return snapshot.entries as readonly HistoryEntry[]\n}\n\nexport function assertEntriesWithinLimits(entries: readonly HistoryEntry[], limits: ResolvedHistoryLimits): number {\n let totalBytes = 0\n for (const entry of entries) {\n const bytes = serializedBytes(entry)\n if (bytes > limits.maxEntryBytes) {\n throw new RangeError(`history snapshot entry exceeds the ${limits.maxEntryBytes}-byte limit`)\n }\n totalBytes += bytes\n if (totalBytes > limits.maxBytes) {\n throw new RangeError(`history snapshot exceeds the ${limits.maxBytes}-byte limit`)\n }\n }\n return totalBytes\n}\n\nexport function emptyValidationState(): SnapshotValidationState {\n return {\n messageIds: new Set(),\n toolCallIds: new Set(),\n nativeToolIds: new Set(),\n toolCallEventIds: new Set(),\n compactions: new Map(),\n visibleMessageSeqs: new Set(),\n }\n}\n\nexport function cloneValidationState(state: SnapshotValidationState): SnapshotValidationState {\n return {\n messageIds: new Set(state.messageIds),\n toolCallIds: new Set(state.toolCallIds),\n nativeToolIds: new Set(state.nativeToolIds),\n toolCallEventIds: new Set(state.toolCallEventIds),\n compactions: new Map([...state.compactions].map(([id, lifecycle]) => [id, { ...lifecycle }])),\n visibleMessageSeqs: new Set(state.visibleMessageSeqs),\n }\n}\n\nexport function validateEntries(entries: readonly HistoryEntry[]): SnapshotValidationState {\n const state = emptyValidationState()\n for (let index = 0; index < entries.length; index++) {\n const entry = entries[index] as Partial<HistoryEntry> | undefined\n if (entry === undefined || entry.seq !== index + 1 || typeof entry.event !== 'object'\n || entry.event === null || !('kind' in entry.event)) {\n throw new TypeError(`invalid history entry at index ${index}`)\n }\n if (![\n 'user', 'assistant', 'tool-call', 'tool-result',\n 'compaction-start', 'compaction-prune', 'compaction-summary', 'compaction-end',\n ].includes(String(entry.event.kind))) {\n throw new TypeError(`unknown history event kind at index ${index}`)\n }\n validateHistoryEvent(entry.event, entry.seq, state)\n validateSurfaceOp(\n entry.surfaceOp as SurfaceOp,\n entry.seq,\n state.visibleMessageSeqs,\n messageOfHistoryEvent(entry.event),\n )\n updateVisibleMessages(entry as HistoryEntry, state.visibleMessageSeqs)\n }\n return state\n}\n\nexport interface SnapshotValidationState {\n readonly messageIds: Set<string>\n readonly toolCallIds: Set<string>\n readonly nativeToolIds: Set<string>\n readonly toolCallEventIds: Set<string>\n readonly compactions: Map<string, { summary: boolean; end: boolean }>\n readonly visibleMessageSeqs: Set<number>\n}\n\nexport function validateHistoryEvent(\n event: HistoryEvent,\n seq: number,\n state: SnapshotValidationState,\n): void {\n const path = `history entry ${seq} ${event.kind}`\n switch (event.kind) {\n case 'user':\n validateMessage(event.message, `${path}.message`, state)\n return\n case 'assistant':\n validateMessage(event.message, `${path}.message`, state)\n if (event.interrupted !== undefined && event.interrupted !== true) {\n throw new TypeError(`${path}.interrupted must be true when present`)\n }\n if (event.usage !== undefined) validateUsage(event.usage, `${path}.usage`)\n return\n case 'tool-call': {\n const callId = nonEmptyString(event.callId, `${path}.callId`)\n if (state.toolCallEventIds.has(callId)) throw new TypeError(`duplicate tool-call event id '${callId}'`)\n state.toolCallEventIds.add(callId)\n nonEmptyString(event.name, `${path}.name`)\n if (typeof event.rawArguments !== 'string') throw new TypeError(`${path}.rawArguments must be a string`)\n return\n }\n case 'tool-result': {\n const callId = nonEmptyString(event.callId, `${path}.callId`)\n validateMessage(event.message, `${path}.message`, state)\n validateToolResultMessage(event.message, callId, `${path}.message`)\n validateToolExecutionResult(event.result, `${path}.result`)\n return\n }\n case 'compaction-start': {\n const id = nonEmptyString(event.compactionId, `${path}.compactionId`)\n if (state.compactions.has(id)) throw new TypeError(`duplicate compaction id '${id}'`)\n if (!['pressure', 'context-overflow', 'manual'].includes(event.trigger)) {\n throw new TypeError(`${path}.trigger is invalid`)\n }\n validateIsoTimestamp(event.at, `${path}.at`)\n state.compactions.set(id, { summary: false, end: false })\n return\n }\n case 'compaction-prune':\n nonEmptyString(event.callId, `${path}.callId`)\n positiveInteger(event.originalSeq, `${path}.originalSeq`)\n if (event.originalSeq >= seq) throw new TypeError(`${path}.originalSeq must reference an earlier entry`)\n nonNegativeInteger(event.charsBefore, `${path}.charsBefore`)\n nonNegativeInteger(event.charsAfter, `${path}.charsAfter`)\n if (event.charsAfter > event.charsBefore) throw new TypeError(`${path}.charsAfter cannot exceed charsBefore`)\n return\n case 'compaction-summary': {\n const id = nonEmptyString(event.compactionId, `${path}.compactionId`)\n const lifecycle = state.compactions.get(id)\n if (lifecycle === undefined) throw new TypeError(`${path} has no matching compaction-start`)\n if (lifecycle.summary) throw new TypeError(`duplicate compaction summary for '${id}'`)\n if (lifecycle.end) throw new TypeError(`${path} appears after compaction-end`)\n nonEmptyString(event.summary, `${path}.summary`)\n validateSeqTargets(event.shadowedSeqs, seq, `${path}.shadowedSeqs`)\n for (const target of event.shadowedSeqs) {\n if (!state.visibleMessageSeqs.has(target)) {\n throw new TypeError(`${path}.shadowedSeqs references non-visible message ${target}`)\n }\n }\n nonNegativeInteger(event.estimatedTokensBefore, `${path}.estimatedTokensBefore`)\n nonNegativeInteger(event.estimatedTokensAfter, `${path}.estimatedTokensAfter`)\n if (event.estimatedTokensAfter > event.estimatedTokensBefore) {\n throw new TypeError(`${path}.estimatedTokensAfter cannot exceed estimatedTokensBefore`)\n }\n nonEmptyString(event.provider, `${path}.provider`)\n nonEmptyString(event.model, `${path}.model`)\n if (event.usage !== undefined) validateUsage(event.usage, `${path}.usage`)\n lifecycle.summary = true\n return\n }\n case 'compaction-end': {\n const id = nonEmptyString(event.compactionId, `${path}.compactionId`)\n const lifecycle = state.compactions.get(id)\n if (lifecycle === undefined) throw new TypeError(`${path} has no matching compaction-start`)\n if (lifecycle.end) throw new TypeError(`duplicate compaction end for '${id}'`)\n if (!['completed', 'failed'].includes(event.status)) throw new TypeError(`${path}.status is invalid`)\n validateIsoTimestamp(event.at, `${path}.at`)\n if (event.thresholdTokens !== undefined) positiveInteger(event.thresholdTokens, `${path}.thresholdTokens`)\n if (event.estimatedNonCompactableTokens !== undefined) {\n nonNegativeInteger(event.estimatedNonCompactableTokens, `${path}.estimatedNonCompactableTokens`)\n }\n if (event.backoffReason !== undefined\n && !['low-savings', 'unreachable-threshold'].includes(event.backoffReason)) {\n throw new TypeError(`${path}.backoffReason is invalid`)\n }\n if (event.cooldownSteps !== undefined) positiveInteger(event.cooldownSteps, `${path}.cooldownSteps`)\n if ((event.backoffReason === undefined) !== (event.cooldownSteps === undefined)) {\n throw new TypeError(`${path}.backoffReason and cooldownSteps must be set together`)\n }\n if (event.backoffReason !== undefined && event.thresholdTokens === undefined) {\n throw new TypeError(`${path}.backoffReason requires thresholdTokens`)\n }\n if (event.status === 'completed') {\n if (!lifecycle.summary) throw new TypeError(`${path} completed without a compaction-summary`)\n if (event.error !== undefined) throw new TypeError(`${path}.error is only valid for failed compaction`)\n } else {\n nonEmptyString(event.error, `${path}.error`)\n if (event.backoffReason !== undefined || event.thresholdTokens !== undefined\n || event.estimatedNonCompactableTokens !== undefined) {\n throw new TypeError(`${path} failed compaction cannot carry completed metrics`)\n }\n }\n lifecycle.end = true\n return\n }\n }\n}\n\nexport function validateMessage(value: unknown, path: string, state: SnapshotValidationState): asserts value is Message {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const id = nonEmptyString(value.id, `${path}.id`)\n if (state.messageIds.has(id)) throw new TypeError(`duplicate message id '${id}'`)\n state.messageIds.add(id)\n if (!['system', 'user', 'assistant'].includes(String(value.role))) {\n throw new TypeError(`${path}.role is invalid`)\n }\n if (!Array.isArray(value.content)) throw new TypeError(`${path}.content must be an array`)\n for (let index = 0; index < value.content.length; index++) {\n validateContentBlock(value.content[index], `${path}.content[${index}]`, state, new Set(), 0)\n }\n validateMessageSource(value.source, `${path}.source`)\n}\n\nexport function validateMessageSource(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const kind = nonEmptyString(value.kind, `${path}.kind`)\n switch (kind) {\n case 'user': return\n case 'app': nonEmptyString(value.producer, `${path}.producer`); return\n case 'model':\n nonEmptyString(value.provider, `${path}.provider`)\n nonEmptyString(value.model, `${path}.model`)\n return\n case 'tool': nonEmptyString(value.callId, `${path}.callId`); return\n default:\n // Message sources and content blocks are declaration-merge extensible.\n // Preserve third-party kinds while still requiring their discriminator.\n return\n }\n}\n\nexport function validateContentBlock(\n value: unknown,\n path: string,\n state: SnapshotValidationState,\n ancestors: Set<object>,\n depth: number,\n): void {\n if (depth > MAX_CONTENT_DEPTH) throw new TypeError(`${path} exceeds the maximum content depth`)\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n if (ancestors.has(value)) throw new TypeError(`${path} must not contain a cycle`)\n const nextAncestors = new Set(ancestors).add(value)\n const type = nonEmptyString(value.type, `${path}.type`)\n switch (type) {\n case 'text':\n if (typeof value.text !== 'string') throw new TypeError(`${path}.text must be a string`)\n if (value.phase !== undefined && !['commentary', 'final-answer'].includes(String(value.phase))) {\n throw new TypeError(`${path}.phase is invalid`)\n }\n if (value.annotations !== undefined) {\n if (!Array.isArray(value.annotations)) throw new TypeError(`${path}.annotations must be an array`)\n for (let index = 0; index < value.annotations.length; index++) {\n validateTextAnnotation(value.annotations[index], `${path}.annotations[${index}]`)\n }\n }\n return\n case 'reasoning':\n if (typeof value.text !== 'string') throw new TypeError(`${path}.text must be a string`)\n return\n case 'image': validateImageSource(value.source, `${path}.source`); return\n case 'native-tool-call':\n {\n const id = nonEmptyString(value.id, `${path}.id`)\n if (state.nativeToolIds.has(id)) throw new TypeError(`duplicate native tool id '${id}'`)\n state.nativeToolIds.add(id)\n }\n nonEmptyString(value.name, `${path}.name`)\n if (value.status !== undefined && typeof value.status !== 'string') {\n throw new TypeError(`${path}.status must be a string`)\n }\n validateContentArray(value.content, `${path}.content`, state, nextAncestors, depth + 1)\n return\n case 'tool-call': {\n const id = nonEmptyString(value.id, `${path}.id`)\n if (state.toolCallIds.has(id)) throw new TypeError(`duplicate tool call id '${id}'`)\n state.toolCallIds.add(id)\n nonEmptyString(value.name, `${path}.name`)\n if (typeof value.arguments !== 'string') throw new TypeError(`${path}.arguments must be a string`)\n return\n }\n case 'tool-result':\n nonEmptyString(value.toolCallId, `${path}.toolCallId`)\n if (value.isError !== undefined && typeof value.isError !== 'boolean') {\n throw new TypeError(`${path}.isError must be a boolean`)\n }\n validateContentArray(value.content, `${path}.content`, state, nextAncestors, depth + 1)\n return\n default:\n return\n }\n}\n\nexport function validateContentArray(\n value: unknown,\n path: string,\n state: SnapshotValidationState,\n ancestors: Set<object>,\n depth: number,\n): void {\n if (!Array.isArray(value)) throw new TypeError(`${path} must be an array`)\n for (let index = 0; index < value.length; index++) {\n validateContentBlock(value[index], `${path}[${index}]`, state, ancestors, depth)\n }\n}\n\nexport function validateTextAnnotation(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const type = nonEmptyString(value.type, `${path}.type`)\n if (type !== 'url-citation') return\n nonEmptyString(value.url, `${path}.url`)\n if (value.title !== undefined && typeof value.title !== 'string') throw new TypeError(`${path}.title must be a string`)\n for (const field of ['startIndex', 'endIndex'] as const) {\n if (value[field] !== undefined) nonNegativeInteger(value[field], `${path}.${field}`)\n }\n}\n\nexport function validateImageSource(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const kind = nonEmptyString(value.kind, `${path}.kind`)\n if (kind === 'base64') {\n if (!['image/jpeg', 'image/png', 'image/gif', 'image/webp'].includes(String(value.mediaType))) {\n throw new TypeError(`${path}.mediaType is invalid`)\n }\n if (typeof value.data !== 'string') throw new TypeError(`${path}.data must be a string`)\n } else if (kind === 'url') {\n nonEmptyString(value.url, `${path}.url`)\n } else if (kind === 'file') {\n nonEmptyString(value.fileId, `${path}.fileId`)\n } else {\n throw new TypeError(`${path}.kind is invalid`)\n }\n}\n\nexport function validateToolResultMessage(message: Message, callId: string, path: string): void {\n if (message.source.kind !== 'tool' || message.source.callId !== callId) {\n throw new TypeError(`${path}.source.callId must match its tool-result event`)\n }\n if (message.role !== 'user' || message.content.length !== 1\n || message.content[0]?.type !== 'tool-result'\n || message.content[0].toolCallId !== callId) {\n throw new TypeError(`${path} must carry exactly one matching tool-result block`)\n }\n}\n\nexport function validateToolExecutionResult(value: unknown, path: string): void {\n if (!isRecord(value) || typeof value.isError !== 'boolean') {\n throw new TypeError(`${path}.isError must be a boolean`)\n }\n validateDetachedContent(value.content, `${path}.content`)\n if (value.additionalContext !== undefined) {\n validateDetachedContent(value.additionalContext, `${path}.additionalContext`)\n }\n if (value.meta !== undefined && (!isRecord(value.meta))) throw new TypeError(`${path}.meta must be an object`)\n if (value.isError) {\n if (!isRecord(value.error)) throw new TypeError(`${path}.error must be an object`)\n nonEmptyString(value.error.message, `${path}.error.message`)\n nonEmptyString(value.error.code, `${path}.error.code`)\n if (value.concludesTurn !== undefined) throw new TypeError(`${path}.concludesTurn is invalid for a failure`)\n } else if (value.concludesTurn !== undefined && value.concludesTurn !== true) {\n throw new TypeError(`${path}.concludesTurn must be true when present`)\n }\n}\n\nexport function validateDetachedContent(value: unknown, path: string): void {\n const state: SnapshotValidationState = {\n messageIds: new Set(), toolCallIds: new Set(), nativeToolIds: new Set(), toolCallEventIds: new Set(),\n compactions: new Map(), visibleMessageSeqs: new Set(),\n }\n validateContentArray(value, path, state, new Set(), 0)\n}\n\nexport function validateUsage(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n for (const field of [\n 'inputTokens', 'outputTokens', 'totalTokens', 'cacheReadTokens', 'cacheWriteTokens', 'reasoningTokens',\n ] as const) {\n const tokenCount = value[field]\n if ((field === 'inputTokens' || field === 'outputTokens') || tokenCount !== undefined) {\n nonNegativeInteger(tokenCount, `${path}.${field}`)\n }\n }\n}\n\nexport function validateSeqTargets(value: unknown, nextSeq: number, path: string): asserts value is readonly number[] {\n if (!Array.isArray(value) || value.length === 0 || new Set(value).size !== value.length) {\n throw new TypeError(`${path} must contain unique earlier sequence numbers`)\n }\n if (value.some(seq => !Number.isInteger(seq) || seq < 1 || seq >= nextSeq)) {\n throw new TypeError(`${path} must contain unique earlier sequence numbers`)\n }\n}\n\nexport function updateVisibleMessages(entry: HistoryEntry, visible: Set<number>): void {\n if (entry.surfaceOp !== 'append') {\n const operation = entry.surfaceOp\n const targets = operation.targets === undefined\n ? [...visible].filter(seq => seq >= operation.from && seq <= operation.to)\n : [...operation.targets]\n for (const target of targets) visible.delete(target)\n }\n if (messageOfHistoryEvent(entry.event)) visible.add(entry.seq)\n}\n\nexport function messageOfHistoryEvent(event: HistoryEvent): boolean {\n return event.kind === 'user' || event.kind === 'assistant' || event.kind === 'tool-result'\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport function nonEmptyString(value: unknown, path: string): string {\n if (typeof value !== 'string' || value.trim().length === 0) throw new TypeError(`${path} must be a non-empty string`)\n return value\n}\n\nexport function positiveInteger(value: unknown, path: string): asserts value is number {\n if (!Number.isSafeInteger(value) || Number(value) < 1) throw new TypeError(`${path} must be a positive integer`)\n}\n\nexport function nonNegativeInteger(value: unknown, path: string): asserts value is number {\n if (!Number.isSafeInteger(value) || Number(value) < 0) throw new TypeError(`${path} must be a non-negative integer`)\n}\n\nexport function validateIsoTimestamp(value: unknown, path: string): void {\n const timestamp = nonEmptyString(value, path)\n const date = new Date(timestamp)\n if (Number.isNaN(date.valueOf()) || date.toISOString() !== timestamp) {\n throw new TypeError(`${path} must be an ISO timestamp`)\n }\n}\n\nexport function validateSurfaceOp(\n op: SurfaceOp,\n nextSeq: number,\n visible?: ReadonlySet<number>,\n replacementCarriesMessage = true,\n): void {\n if (op === 'append') return\n if (typeof op !== 'object' || op.op !== 'replace'\n || !Number.isInteger(op.from) || !Number.isInteger(op.to)\n || op.from < 1 || op.to < op.from || op.to >= nextSeq) {\n throw new TypeError('history replace span must reference an earlier inclusive sequence range')\n }\n if (op.targets !== undefined) {\n if (op.targets.length === 0 || new Set(op.targets).size !== op.targets.length\n || op.targets.some(seq => !Number.isInteger(seq) || seq < 1 || seq >= nextSeq)) {\n throw new TypeError('history replace targets must be unique earlier sequence numbers')\n }\n if (op.targets.some(seq => seq < op.from || seq > op.to)) {\n throw new TypeError('history replace targets must stay within its inclusive sequence range')\n }\n }\n if (visible !== undefined) {\n if (!replacementCarriesMessage) throw new TypeError('history replacement entry must carry a message')\n const targets = op.targets ?? [...visible].filter(seq => seq >= op.from && seq <= op.to)\n if (targets.length === 0 || targets.some(seq => !visible.has(seq))) {\n throw new TypeError('history replace targets must reference current visible messages')\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"validation.js","names":[],"sources":["../../../src/agent/history/validation.ts"],"sourcesContent":["import type { Message } from '../../message/index.ts'\nimport {\n type SurfaceOp, type HistoryEvent, type HistoryEntry, type HistorySnapshot,\n type ResolvedHistoryLimits,\n} from './types.ts'\nimport { MAX_CONTENT_DEPTH, serializedBytes } from './config.ts'\n\nexport function snapshotEntries(value: unknown): readonly HistoryEntry[] {\n if (typeof value !== 'object' || value === null) throw new TypeError('history snapshot must be an object')\n const snapshot = value as Partial<HistorySnapshot>\n if (snapshot.version !== 1) throw new TypeError('unsupported history snapshot version')\n if (!Array.isArray(snapshot.entries)) throw new TypeError('history snapshot entries must be an array')\n return snapshot.entries as readonly HistoryEntry[]\n}\n\nexport function assertEntriesWithinLimits(entries: readonly HistoryEntry[], limits: ResolvedHistoryLimits): number {\n let totalBytes = 0\n for (const entry of entries) {\n const bytes = serializedBytes(entry)\n if (bytes > limits.maxEntryBytes) {\n throw new RangeError(`history snapshot entry exceeds the ${limits.maxEntryBytes}-byte limit`)\n }\n totalBytes += bytes\n if (totalBytes > limits.maxBytes) {\n throw new RangeError(`history snapshot exceeds the ${limits.maxBytes}-byte limit`)\n }\n }\n return totalBytes\n}\n\nexport function emptyValidationState(): SnapshotValidationState {\n return {\n messageIds: new Set(),\n toolCallIds: new Set(),\n nativeToolIds: new Set(),\n toolCallEventIds: new Set(),\n compactions: new Map(),\n visibleMessageSeqs: new Set(),\n }\n}\n\nexport function cloneValidationState(state: SnapshotValidationState): SnapshotValidationState {\n return {\n messageIds: new Set(state.messageIds),\n toolCallIds: new Set(state.toolCallIds),\n nativeToolIds: new Set(state.nativeToolIds),\n toolCallEventIds: new Set(state.toolCallEventIds),\n compactions: new Map([...state.compactions].map(([id, lifecycle]) => [id, { ...lifecycle }])),\n visibleMessageSeqs: new Set(state.visibleMessageSeqs),\n }\n}\n\nexport function validateEntries(entries: readonly HistoryEntry[]): SnapshotValidationState {\n const state = emptyValidationState()\n for (let index = 0; index < entries.length; index++) {\n const entry = entries[index] as Partial<HistoryEntry> | undefined\n if (entry === undefined || entry.seq !== index + 1 || typeof entry.event !== 'object'\n || entry.event === null || !('kind' in entry.event)) {\n throw new TypeError(`invalid history entry at index ${index}`)\n }\n if (![\n 'user', 'assistant', 'tool-call', 'tool-result',\n 'compaction-start', 'compaction-prune', 'compaction-summary', 'compaction-end',\n ].includes(String(entry.event.kind))) {\n throw new TypeError(`unknown history event kind at index ${index}`)\n }\n validateHistoryEvent(entry.event, entry.seq, state)\n validateSurfaceOp(\n entry.surfaceOp as SurfaceOp,\n entry.seq,\n state.visibleMessageSeqs,\n messageOfHistoryEvent(entry.event),\n )\n updateVisibleMessages(entry as HistoryEntry, state.visibleMessageSeqs)\n }\n return state\n}\n\nexport interface SnapshotValidationState {\n readonly messageIds: Set<string>\n readonly toolCallIds: Set<string>\n readonly nativeToolIds: Set<string>\n readonly toolCallEventIds: Set<string>\n readonly compactions: Map<string, { summary: boolean; end: boolean }>\n readonly visibleMessageSeqs: Set<number>\n}\n\nexport function validateHistoryEvent(\n event: HistoryEvent,\n seq: number,\n state: SnapshotValidationState,\n): void {\n const path = `history entry ${seq} ${event.kind}`\n switch (event.kind) {\n case 'user':\n validateMessage(event.message, `${path}.message`, state)\n return\n case 'assistant':\n validateMessage(event.message, `${path}.message`, state)\n if (event.interrupted !== undefined && event.interrupted !== true) {\n throw new TypeError(`${path}.interrupted must be true when present`)\n }\n if (event.usage !== undefined) validateUsage(event.usage, `${path}.usage`)\n return\n case 'tool-call': {\n const callId = nonEmptyString(event.callId, `${path}.callId`)\n if (state.toolCallEventIds.has(callId)) throw new TypeError(`duplicate tool-call event id '${callId}'`)\n state.toolCallEventIds.add(callId)\n nonEmptyString(event.name, `${path}.name`)\n if (typeof event.rawArguments !== 'string') throw new TypeError(`${path}.rawArguments must be a string`)\n return\n }\n case 'tool-result': {\n const callId = nonEmptyString(event.callId, `${path}.callId`)\n validateMessage(event.message, `${path}.message`, state)\n validateToolResultMessage(event.message, callId, `${path}.message`)\n validateToolExecutionResult(event.result, `${path}.result`)\n return\n }\n case 'compaction-start': {\n const id = nonEmptyString(event.compactionId, `${path}.compactionId`)\n if (state.compactions.has(id)) throw new TypeError(`duplicate compaction id '${id}'`)\n if (!['pressure', 'context-overflow', 'manual'].includes(event.trigger)) {\n throw new TypeError(`${path}.trigger is invalid`)\n }\n validateIsoTimestamp(event.at, `${path}.at`)\n state.compactions.set(id, { summary: false, end: false })\n return\n }\n case 'compaction-prune':\n nonEmptyString(event.callId, `${path}.callId`)\n positiveInteger(event.originalSeq, `${path}.originalSeq`)\n if (event.originalSeq >= seq) throw new TypeError(`${path}.originalSeq must reference an earlier entry`)\n nonNegativeInteger(event.charsBefore, `${path}.charsBefore`)\n nonNegativeInteger(event.charsAfter, `${path}.charsAfter`)\n if (event.charsAfter > event.charsBefore) throw new TypeError(`${path}.charsAfter cannot exceed charsBefore`)\n return\n case 'compaction-summary': {\n const id = nonEmptyString(event.compactionId, `${path}.compactionId`)\n const lifecycle = state.compactions.get(id)\n if (lifecycle === undefined) throw new TypeError(`${path} has no matching compaction-start`)\n if (lifecycle.summary) throw new TypeError(`duplicate compaction summary for '${id}'`)\n if (lifecycle.end) throw new TypeError(`${path} appears after compaction-end`)\n nonEmptyString(event.summary, `${path}.summary`)\n validateSeqTargets(event.shadowedSeqs, seq, `${path}.shadowedSeqs`)\n for (const target of event.shadowedSeqs) {\n if (!state.visibleMessageSeqs.has(target)) {\n throw new TypeError(`${path}.shadowedSeqs references non-visible message ${target}`)\n }\n }\n nonNegativeInteger(event.estimatedTokensBefore, `${path}.estimatedTokensBefore`)\n nonNegativeInteger(event.estimatedTokensAfter, `${path}.estimatedTokensAfter`)\n if (event.estimatedTokensAfter > event.estimatedTokensBefore) {\n throw new TypeError(`${path}.estimatedTokensAfter cannot exceed estimatedTokensBefore`)\n }\n nonEmptyString(event.provider, `${path}.provider`)\n nonEmptyString(event.model, `${path}.model`)\n if (event.usage !== undefined) validateUsage(event.usage, `${path}.usage`)\n lifecycle.summary = true\n return\n }\n case 'compaction-end': {\n const id = nonEmptyString(event.compactionId, `${path}.compactionId`)\n const lifecycle = state.compactions.get(id)\n if (lifecycle === undefined) throw new TypeError(`${path} has no matching compaction-start`)\n if (lifecycle.end) throw new TypeError(`duplicate compaction end for '${id}'`)\n if (!['completed', 'failed'].includes(event.status)) throw new TypeError(`${path}.status is invalid`)\n validateIsoTimestamp(event.at, `${path}.at`)\n if (event.thresholdTokens !== undefined) positiveInteger(event.thresholdTokens, `${path}.thresholdTokens`)\n if (event.estimatedNonCompactableTokens !== undefined) {\n nonNegativeInteger(event.estimatedNonCompactableTokens, `${path}.estimatedNonCompactableTokens`)\n }\n if (event.backoffReason !== undefined\n && !['low-savings', 'unreachable-threshold'].includes(event.backoffReason)) {\n throw new TypeError(`${path}.backoffReason is invalid`)\n }\n if (event.cooldownSteps !== undefined) positiveInteger(event.cooldownSteps, `${path}.cooldownSteps`)\n if ((event.backoffReason === undefined) !== (event.cooldownSteps === undefined)) {\n throw new TypeError(`${path}.backoffReason and cooldownSteps must be set together`)\n }\n if (event.backoffReason !== undefined && event.thresholdTokens === undefined) {\n throw new TypeError(`${path}.backoffReason requires thresholdTokens`)\n }\n if (event.status === 'completed') {\n if (!lifecycle.summary) throw new TypeError(`${path} completed without a compaction-summary`)\n if (event.error !== undefined) throw new TypeError(`${path}.error is only valid for failed compaction`)\n } else {\n nonEmptyString(event.error, `${path}.error`)\n if (event.backoffReason !== undefined || event.thresholdTokens !== undefined\n || event.estimatedNonCompactableTokens !== undefined) {\n throw new TypeError(`${path} failed compaction cannot carry completed metrics`)\n }\n }\n lifecycle.end = true\n return\n }\n }\n}\n\nexport function validateMessage(value: unknown, path: string, state: SnapshotValidationState): asserts value is Message {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const id = nonEmptyString(value.id, `${path}.id`)\n if (state.messageIds.has(id)) throw new TypeError(`duplicate message id '${id}'`)\n state.messageIds.add(id)\n if (!['system', 'user', 'assistant'].includes(String(value.role))) {\n throw new TypeError(`${path}.role is invalid`)\n }\n if (!Array.isArray(value.content)) throw new TypeError(`${path}.content must be an array`)\n for (let index = 0; index < value.content.length; index++) {\n validateContentBlock(value.content[index], `${path}.content[${index}]`, state, new Set(), 0)\n }\n validateMessageSource(value.source, `${path}.source`)\n}\n\nexport function validateMessageSource(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const kind = nonEmptyString(value.kind, `${path}.kind`)\n switch (kind) {\n case 'user': return\n case 'app': nonEmptyString(value.producer, `${path}.producer`); return\n case 'model':\n nonEmptyString(value.provider, `${path}.provider`)\n nonEmptyString(value.model, `${path}.model`)\n return\n case 'tool': nonEmptyString(value.callId, `${path}.callId`); return\n default:\n // Message sources and content blocks are declaration-merge extensible.\n // Preserve third-party kinds while still requiring their discriminator.\n return\n }\n}\n\nexport function validateContentBlock(\n value: unknown,\n path: string,\n state: SnapshotValidationState,\n ancestors: Set<object>,\n depth: number,\n): void {\n if (depth > MAX_CONTENT_DEPTH) throw new TypeError(`${path} exceeds the maximum content depth`)\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n if (ancestors.has(value)) throw new TypeError(`${path} must not contain a cycle`)\n const nextAncestors = new Set(ancestors).add(value)\n const type = nonEmptyString(value.type, `${path}.type`)\n switch (type) {\n case 'text':\n if (typeof value.text !== 'string') throw new TypeError(`${path}.text must be a string`)\n if (value.phase !== undefined && !['commentary', 'final-answer'].includes(String(value.phase))) {\n throw new TypeError(`${path}.phase is invalid`)\n }\n if (value.annotations !== undefined) {\n if (!Array.isArray(value.annotations)) throw new TypeError(`${path}.annotations must be an array`)\n for (let index = 0; index < value.annotations.length; index++) {\n validateTextAnnotation(value.annotations[index], `${path}.annotations[${index}]`)\n }\n }\n return\n case 'reasoning':\n if (typeof value.text !== 'string') throw new TypeError(`${path}.text must be a string`)\n return\n case 'image': validateImageSource(value.source, `${path}.source`); return\n case 'document':\n validateDocumentSource(value.source, `${path}.source`)\n for (const field of ['filename', 'title', 'context'] as const) {\n if (value[field] !== undefined && typeof value[field] !== 'string') {\n throw new TypeError(`${path}.${field} must be a string`)\n }\n }\n if (value.citations !== undefined && typeof value.citations !== 'boolean') {\n throw new TypeError(`${path}.citations must be a boolean`)\n }\n if (value.pages !== undefined) {\n if (!Number.isSafeInteger(value.pages) || (value.pages as number) <= 0) {\n throw new TypeError(`${path}.pages must be a positive integer`)\n }\n }\n return\n case 'native-tool-call':\n {\n const id = nonEmptyString(value.id, `${path}.id`)\n if (state.nativeToolIds.has(id)) throw new TypeError(`duplicate native tool id '${id}'`)\n state.nativeToolIds.add(id)\n }\n nonEmptyString(value.name, `${path}.name`)\n if (value.status !== undefined && typeof value.status !== 'string') {\n throw new TypeError(`${path}.status must be a string`)\n }\n validateContentArray(value.content, `${path}.content`, state, nextAncestors, depth + 1)\n return\n case 'tool-call': {\n const id = nonEmptyString(value.id, `${path}.id`)\n if (state.toolCallIds.has(id)) throw new TypeError(`duplicate tool call id '${id}'`)\n state.toolCallIds.add(id)\n nonEmptyString(value.name, `${path}.name`)\n if (typeof value.arguments !== 'string') throw new TypeError(`${path}.arguments must be a string`)\n return\n }\n case 'tool-result':\n nonEmptyString(value.toolCallId, `${path}.toolCallId`)\n if (value.isError !== undefined && typeof value.isError !== 'boolean') {\n throw new TypeError(`${path}.isError must be a boolean`)\n }\n validateContentArray(value.content, `${path}.content`, state, nextAncestors, depth + 1)\n return\n default:\n return\n }\n}\n\nexport function validateContentArray(\n value: unknown,\n path: string,\n state: SnapshotValidationState,\n ancestors: Set<object>,\n depth: number,\n): void {\n if (!Array.isArray(value)) throw new TypeError(`${path} must be an array`)\n for (let index = 0; index < value.length; index++) {\n validateContentBlock(value[index], `${path}[${index}]`, state, ancestors, depth)\n }\n}\n\nexport function validateTextAnnotation(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const type = nonEmptyString(value.type, `${path}.type`)\n if (type !== 'url-citation') return\n nonEmptyString(value.url, `${path}.url`)\n if (value.title !== undefined && typeof value.title !== 'string') throw new TypeError(`${path}.title must be a string`)\n for (const field of ['startIndex', 'endIndex'] as const) {\n if (value[field] !== undefined) nonNegativeInteger(value[field], `${path}.${field}`)\n }\n}\n\nexport function validateImageSource(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const kind = nonEmptyString(value.kind, `${path}.kind`)\n if (kind === 'base64') {\n if (!['image/jpeg', 'image/png', 'image/gif', 'image/webp'].includes(String(value.mediaType))) {\n throw new TypeError(`${path}.mediaType is invalid`)\n }\n if (typeof value.data !== 'string') throw new TypeError(`${path}.data must be a string`)\n } else if (kind === 'url') {\n nonEmptyString(value.url, `${path}.url`)\n } else if (kind === 'file') {\n nonEmptyString(value.fileId, `${path}.fileId`)\n } else {\n throw new TypeError(`${path}.kind is invalid`)\n }\n}\n\nexport function validateDocumentSource(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n const kind = nonEmptyString(value.kind, `${path}.kind`)\n if (kind === 'base64') {\n if (String(value.mediaType) !== 'application/pdf') throw new TypeError(`${path}.mediaType is invalid`)\n if (typeof value.data !== 'string') throw new TypeError(`${path}.data must be a string`)\n } else if (kind === 'url') {\n nonEmptyString(value.url, `${path}.url`)\n } else if (kind === 'file') {\n nonEmptyString(value.fileId, `${path}.fileId`)\n } else {\n throw new TypeError(`${path}.kind is invalid`)\n }\n}\n\nexport function validateToolResultMessage(message: Message, callId: string, path: string): void {\n if (message.source.kind !== 'tool' || message.source.callId !== callId) {\n throw new TypeError(`${path}.source.callId must match its tool-result event`)\n }\n if (message.role !== 'user' || message.content.length !== 1\n || message.content[0]?.type !== 'tool-result'\n || message.content[0].toolCallId !== callId) {\n throw new TypeError(`${path} must carry exactly one matching tool-result block`)\n }\n}\n\nexport function validateToolExecutionResult(value: unknown, path: string): void {\n if (!isRecord(value) || typeof value.isError !== 'boolean') {\n throw new TypeError(`${path}.isError must be a boolean`)\n }\n validateDetachedContent(value.content, `${path}.content`)\n if (value.additionalContext !== undefined) {\n validateDetachedContent(value.additionalContext, `${path}.additionalContext`)\n }\n if (value.meta !== undefined && (!isRecord(value.meta))) throw new TypeError(`${path}.meta must be an object`)\n if (value.isError) {\n if (!isRecord(value.error)) throw new TypeError(`${path}.error must be an object`)\n nonEmptyString(value.error.message, `${path}.error.message`)\n nonEmptyString(value.error.code, `${path}.error.code`)\n if (value.concludesTurn !== undefined) throw new TypeError(`${path}.concludesTurn is invalid for a failure`)\n } else if (value.concludesTurn !== undefined && value.concludesTurn !== true) {\n throw new TypeError(`${path}.concludesTurn must be true when present`)\n }\n}\n\nexport function validateDetachedContent(value: unknown, path: string): void {\n const state: SnapshotValidationState = {\n messageIds: new Set(), toolCallIds: new Set(), nativeToolIds: new Set(), toolCallEventIds: new Set(),\n compactions: new Map(), visibleMessageSeqs: new Set(),\n }\n validateContentArray(value, path, state, new Set(), 0)\n}\n\nexport function validateUsage(value: unknown, path: string): void {\n if (!isRecord(value)) throw new TypeError(`${path} must be an object`)\n for (const field of [\n 'inputTokens', 'outputTokens', 'totalTokens', 'cacheReadTokens', 'cacheWriteTokens', 'reasoningTokens',\n ] as const) {\n const tokenCount = value[field]\n if ((field === 'inputTokens' || field === 'outputTokens') || tokenCount !== undefined) {\n nonNegativeInteger(tokenCount, `${path}.${field}`)\n }\n }\n}\n\nexport function validateSeqTargets(value: unknown, nextSeq: number, path: string): asserts value is readonly number[] {\n if (!Array.isArray(value) || value.length === 0 || new Set(value).size !== value.length) {\n throw new TypeError(`${path} must contain unique earlier sequence numbers`)\n }\n if (value.some(seq => !Number.isInteger(seq) || seq < 1 || seq >= nextSeq)) {\n throw new TypeError(`${path} must contain unique earlier sequence numbers`)\n }\n}\n\nexport function updateVisibleMessages(entry: HistoryEntry, visible: Set<number>): void {\n if (entry.surfaceOp !== 'append') {\n const operation = entry.surfaceOp\n const targets = operation.targets === undefined\n ? [...visible].filter(seq => seq >= operation.from && seq <= operation.to)\n : [...operation.targets]\n for (const target of targets) visible.delete(target)\n }\n if (messageOfHistoryEvent(entry.event)) visible.add(entry.seq)\n}\n\nexport function messageOfHistoryEvent(event: HistoryEvent): boolean {\n return event.kind === 'user' || event.kind === 'assistant' || event.kind === 'tool-result'\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport function nonEmptyString(value: unknown, path: string): string {\n if (typeof value !== 'string' || value.trim().length === 0) throw new TypeError(`${path} must be a non-empty string`)\n return value\n}\n\nexport function positiveInteger(value: unknown, path: string): asserts value is number {\n if (!Number.isSafeInteger(value) || Number(value) < 1) throw new TypeError(`${path} must be a positive integer`)\n}\n\nexport function nonNegativeInteger(value: unknown, path: string): asserts value is number {\n if (!Number.isSafeInteger(value) || Number(value) < 0) throw new TypeError(`${path} must be a non-negative integer`)\n}\n\nexport function validateIsoTimestamp(value: unknown, path: string): void {\n const timestamp = nonEmptyString(value, path)\n const date = new Date(timestamp)\n if (Number.isNaN(date.valueOf()) || date.toISOString() !== timestamp) {\n throw new TypeError(`${path} must be an ISO timestamp`)\n }\n}\n\nexport function validateSurfaceOp(\n op: SurfaceOp,\n nextSeq: number,\n visible?: ReadonlySet<number>,\n replacementCarriesMessage = true,\n): void {\n if (op === 'append') return\n if (typeof op !== 'object' || op.op !== 'replace'\n || !Number.isInteger(op.from) || !Number.isInteger(op.to)\n || op.from < 1 || op.to < op.from || op.to >= nextSeq) {\n throw new TypeError('history replace span must reference an earlier inclusive sequence range')\n }\n if (op.targets !== undefined) {\n if (op.targets.length === 0 || new Set(op.targets).size !== op.targets.length\n || op.targets.some(seq => !Number.isInteger(seq) || seq < 1 || seq >= nextSeq)) {\n throw new TypeError('history replace targets must be unique earlier sequence numbers')\n }\n if (op.targets.some(seq => seq < op.from || seq > op.to)) {\n throw new TypeError('history replace targets must stay within its inclusive sequence range')\n }\n }\n if (visible !== undefined) {\n if (!replacementCarriesMessage) throw new TypeError('history replacement entry must carry a message')\n const targets = op.targets ?? [...visible].filter(seq => seq >= op.from && seq <= op.to)\n if (targets.length === 0 || targets.some(seq => !visible.has(seq))) {\n throw new TypeError('history replace targets must reference current visible messages')\n }\n }\n}\n"],"mappings":"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"}
@@ -2,6 +2,7 @@ import { MessageId, ToolCallId } from "../../primitives/brand.js";
2
2
  import { ModelFailure } from "../../errors/failure.js";
3
3
  import { AssistantTextPhase, ImageMediaType, NativeToolCallBlock } from "../../message/content.js";
4
4
  import { TokenUsage } from "../../stream/chunk.js";
5
+ import { UsageCounters } from "../../observation/usage.js";
5
6
  import { SdkLogger } from "../../logging/types.js";
6
7
  import { Message } from "../../message/message.js";
7
8
  import { GenerateOptions } from "../../contract/generate-options.js";
@@ -150,6 +151,10 @@ type AgentEvent = TraceEvent | (AgentMaintenanceEvent & Traced) | ({
150
151
  } & Traced) | ({
151
152
  readonly type: 'usage';
152
153
  readonly usage: TokenUsage;
154
+ } & Traced) | ({
155
+ readonly type: 'usage-progress';
156
+ readonly usage: UsageCounters;
157
+ readonly attemptId?: string;
153
158
  } & Traced) | ({
154
159
  readonly type: 'step-end';
155
160
  readonly turn: number;
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","names":[],"sources":["../../../src/agent/loop/events.ts"],"mappings":";;;;;;;;;;;;;;KAgBY;;;;;;;;KAcA,oBAAoB;KAEpB;WACG;;WACA;WAAoC;;WACpC;WAAmC,QAAQ;WAA0B;;WAErE;;WACA;;WACA;WAAoC;;WACpC;;WACA;WAAwB,SAAS;;UAE/B;WACN,QAAQ;WACR;WACA;;WAEA,QAAQ;;WAER,aAAa;WACb;WACA;;UAGD;WAAkB,OAAO;;KACvB;KACA,6BAA6B;KAC7B;KACA;WAEC;WACA;WACA,SAAS;WACT;;WAGA;WACA;WACA,SAAS;WACT;WACA;WACA;WACA;WACA;WACA;WACA,gBAAgB;WAChB;WACA;WACA;WACA,QAAQ;;KAET,aAAa,cACpB,wBAAwB;WACb;WAA6B;IAAiB;WAC9C;WAA6B;WAAuB;WAAuB;IAAuB;WAClG;WAA6B;WAAwB;WAAuB,OAAO;IAA+B;;;;;WAIlH;WAA2B;WAAwB;WAAuB,OAAO;WAA6B;IAAsB;WACpI;WAAkC;WAAwB;IAAiB;WAE9E;WACA;WACA;WACA,WAAW;WACX;IACP;WACU;WAAoC,SAAS;IAAY;WAE5D;WACA,WAAW;WACX;WACA,OAAO;WACP,QAAQ;WACR,sBAAsB;WACtB,2BAA2B;IAClC;WAEO;WACA,WAAW;WACX,MAAM;IACb;;WAGO;WACA,WAAW;WACX;WACA,QAAQ;WACR,sBAAsB;WACtB,2BAA2B;IAClC;WACU;WAA4B,MAAM;IAAoB;WACtD;WAA8B,MAAM;WAA0B,QAAQ;IAAwB;WAC9F;WAAmC,SAAS;IAAoB;WAChE;WAAwB,OAAO;IAAe;WAC9C;WAA2B;WAAuB;IAAiB;WACnE;WAA2B,SAAS;IAAgB;UAEnD;WACN;WACA;WACA,mBAAmB;WACnB,UAAU;WACV,QAAQ;WACR,SAAS;EAClB,KAAK,OAAO,wBAAwB;;KAE1B;WACG;WAA0B,mBAAmB;;WAC7C;WAAyB;;UACvB;WACN;WACA;WACA,SAAS;WACT,UAAU;WACV,QAAQ;WACR,SAAS;EAClB,KAAK,OAAO,wBAAwB;;KAE1B;WACG;WAAuC,SAAS;WAA0B,UAAU;WACpF,SAAS;WAAsB,SAAS;;WACxC;WAAuC,MAAM;WAA0B,UAAU;WACjF,SAAS;WAAsB,SAAS;;UACtC;WACN,SAAS;WACT,UAAU;;WAEV;;UAEM;WACN,cAAc,KAAK,sBAAsB,QAAQ,gBAAgB;WACjE,kBAAkB,KAAK,wBAAwB;WAC/C,cAAc,KAAK,sBAAsB;WACzC,aAAa,KAAK,mBAAmB"}
1
+ {"version":3,"file":"events.d.ts","names":[],"sources":["../../../src/agent/loop/events.ts"],"mappings":";;;;;;;;;;;;;;;KAgBY;;;;;;;;KAcA,oBAAoB;KAEpB;WACG;;WACA;WAAoC;;WACpC;WAAmC,QAAQ;WAA0B;;WAErE;;WACA;;WACA;WAAoC;;WACpC;;WACA;WAAwB,SAAS;;UAE/B;WACN,QAAQ;WACR;WACA;;WAEA,QAAQ;;WAER,aAAa;WACb;WACA;;UAGD;WAAkB,OAAO;;KACvB;KACA,6BAA6B;KAC7B;KACA;WAEC;WACA;WACA,SAAS;WACT;;WAGA;WACA;WACA,SAAS;WACT;WACA;WACA;WACA;WACA;WACA;WACA,gBAAgB;WAChB;WACA;WACA;WACA,QAAQ;;KAET,aAAa,cACpB,wBAAwB;WACb;WAA6B;IAAiB;WAC9C;WAA6B;WAAuB;WAAuB;IAAuB;WAClG;WAA6B;WAAwB;WAAuB,OAAO;IAA+B;;;;;WAIlH;WAA2B;WAAwB;WAAuB,OAAO;WAA6B;IAAsB;WACpI;WAAkC;WAAwB;IAAiB;WAE9E;WACA;WACA;WACA,WAAW;WACX;IACP;WACU;WAAoC,SAAS;IAAY;WAE5D;WACA,WAAW;WACX;WACA,OAAO;WACP,QAAQ;WACR,sBAAsB;WACtB,2BAA2B;IAClC;WAEO;WACA,WAAW;WACX,MAAM;IACb;;WAGO;WACA,WAAW;WACX;WACA,QAAQ;WACR,sBAAsB;WACtB,2BAA2B;IAClC;WACU;WAA4B,MAAM;IAAoB;WACtD;WAA8B,MAAM;WAA0B,QAAQ;IAAwB;WAC9F;WAAmC,SAAS;IAAoB;WAChE;WAAwB,OAAO;IAAe;WAC9C;WAAiC,OADa;WACuD;IAAuB;WAC5H;WAA2B;WAAuB;IAAiB;WACnE;WAA2B,SAAS;IAAgB;UAEnD;WACN;WACA;WACA,mBAAmB;WACnB,UAAU;WACV,QAAQ;WACR,SAAS;EAClB,KAAK,OAAO,wBAAwB;;KAE1B;WACG;WAA0B,mBAAmB;;WAC7C;WAAyB;;UACvB;WACN;WACA;WACA,SAAS;WACT,UAAU;WACV,QAAQ;WACR,SAAS;EAClB,KAAK,OAAO,wBAAwB;;KAE1B;WACG;WAAuC,SAAS;WAA0B,UAAU;WACpF,SAAS;WAAsB,SAAS;;WACxC;WAAuC,MAAM;WAA0B,UAAU;WACjF,SAAS;WAAsB,SAAS;;UACtC;WACN,SAAS;WACT,UAAU;;WAEV;;UAEM;WACN,cAAc,KAAK,sBAAsB,QAAQ,gBAAgB;WACjE,kBAAkB,KAAK,wBAAwB;WAC/C,cAAc,KAAK,sBAAsB;WACzC,aAAa,KAAK,mBAAmB"}
@@ -1,3 +1,3 @@
1
- import{detachedFrozen as e}from"../../primitives/snapshot.js";import{waitForSettlement as t}from"../../async/settlement.js";import{createSpanId as n}from"../../observation/context.js";import{createToolResultMessage as r,createUserMessage as i}from"../../message/message.js";import{estimateTextBlockTokens as a,previewForSpill as o,truncateMiddleToTokens as s}from"../tool/output-budget.js";import{TOOL_ERROR_CODES as c,ToolError as l,toolErrorDisposition as u}from"../tool/errors.js";import{authorizeToolCall as d,dispatchAuthorizedToolCall as f,finalizeToolCall as p,prepareToolCall as m,toolFailure as h}from"../tool/pipeline.js";async function g(e){let t=M(e.maxParallel??8,`maxParallel`),n=M(e.maxResultBytes??4194304,`maxResultBytes`),r=M(e.maxDurationMs??6e5,`maxDurationMs`),i=M(e.teardownTimeoutMs??3e4,`teardownTimeoutMs`),a=Object.freeze(e.calls.map(T)),o=Math.max(0,e.dispatchLimit??a.length),s=[],c=0,l=0,u=0,d,f=0,p;for(;f<a.length;){let m=a[f];if(m===void 0)break;let h=p??_(e,m);if(p=void 0,h.mode===`exclusive`){let t=await v(e,h,l<o,r,i);c+=+!!t.dispatched,l+=+(t.budgeted===!0),u+=+(t.declined===!0);let a=await S(e,t,n);s.push(a),d===void 0&&!a.isError&&a.concludesTurn&&(d=m.toolName),f++;continue}let g=[],y=new AbortController,b={...e,signal:AbortSignal.any([e.signal,y.signal])},C=h;try{for(;f<a.length&&g.length<t&&a[f]!==void 0;){let e=C;if(e.mode!==`parallel`)break;let n=await v(b,e,l<o,r,i);c+=+!!n.dispatched,l+=+(n.budgeted===!0),u+=+(n.declined===!0),g.push(n),f++;let s=a[f];s!==void 0&&g.length<t&&(C=_(b,s),C.mode!==`parallel`&&(p=C))}}catch(t){throw y.abort(t),await x(e,g,n),t}if(g.length===0)continue;let w,T=!1;for(let t of g)try{let r=await S(e,t,n);s.push(r),d===void 0&&!r.isError&&r.concludesTurn&&(d=t.call.toolName)}catch(e){T||(w=e),T=!0,y.abort(e)}if(T)throw w}return{results:Object.freeze(s),concluded:d!==void 0,...d===void 0?{}:{concludedBy:d},dispatched:c,budgeted:l,declined:u}}function _(e,t){return m({catalog:e.catalog,call:t,position:e.position,signal:e.signal,...e.logger===void 0?{}:{logger:e.logger},...e.interceptors===void 0?{}:{interceptors:e.interceptors},...e.approvals===void 0?{}:{approvals:e.approvals}})}async function v(e,r,i,a,o){let s=AbortSignal.timeout(a),l=AbortSignal.any([e.signal,s]),u={...r,options:{...r.options,signal:l,teardownTimeoutMs:o},context:{...r.context,signal:l}},p=u.options.call,m={traceId:e.parentTrace.traceId,spanId:n(),parentSpanId:e.parentTrace.spanId};e.history.append({kind:`tool-call`,callId:p.callId,name:p.toolName,rawArguments:p.rawArguments}),await j(e,{type:`span-start`,trace:m,at:F(),name:`execute_tool ${p.toolName}`,kind:`execute_tool`,attributes:{"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.name":p.toolName,"gen_ai.tool.call.id":p.callId}}),await j(e,{type:`tool-call`,call:p,trace:m});let g=e.catalog.get(p.toolName)?.budgetExempt===!0;if(!i&&!g)return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,declined:!0,pending:Promise.resolve(y(e.declineReason??`tool-calls`))};if(e.signal.aborted)return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(h(`the call was cancelled before it started`,c.ABORTED_BEFORE_DISPATCH))};let _,v={...u,options:{...u.options,onApprovalRequest:async t=>{_=e.accounting?.startOperation(`user-input`,{toolCallId:t.callId,data:{action:`approval`,toolName:t.toolName}}),await j(e,{type:`approval-request`,request:t,trace:m})},...e.accounting===void 0?{}:{onApprovalSettled:(t,n)=>{_!==void 0&&(e.accounting?.endOperation(_,t,n===void 0?{}:{error:n}),_=void 0)}}}},b=d(v),x;try{x=await A(b,l)}catch(e){if(!l.aborted)throw e;if(!await t(b,o))throw k(p.toolName,`authorization`,o,e);return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(O(s,a))}}if(x.kind===`final`)return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(x.result)};try{await e.checkpoint?.({kind:`before-tool-dispatch`,call:p,snapshot:e.history.snapshot(),signal:l,...e.logger===void 0?{}:{logger:e.logger}})}catch(e){return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(h(`history checkpoint failed: ${P(e)}`,c.CHECKPOINT_FAILED))}}let S=f(x.call);return S.catch(()=>void 0),{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,authorized:x.call,dispatched:!0,budgeted:!g,pending:S}}function y(e){return{isError:!1,value:void 0,content:[{type:`text`,text:b(e)}],meta:{declined:!0,reason:e}}}function b(e){let t=` Answer now from what you already have, and say plainly what is unverified or unfinished.`;switch(e){case`tool-calls`:return`This call was not run: the turn has spent its tool-call budget. Further work calls will not run either, so do not retry it.`+t;case`repeated-tool-call`:return`This call was not run: it repeats a call already made with the same arguments, and repeating it cannot produce a new result. Change approach or finish.`+t;case`tool-call-cycle`:return`This call was not run: the same sequence of calls has repeated several times without progress. Break the cycle rather than re-entering it.`+t;case`tokens`:return`This call was not run: the turn has spent its token budget.`+t;case`consecutive-tool-errors`:return`This call was not run: too many calls in a row have failed. Something in the approach is wrong, not the individual call.`+t;case`steps`:return`This call was not run: the turn has no model steps left.`+t;case`usage-required`:return`This call was not run: the run policy requires provider usage reporting that the last model call did not supply.`+t}}async function x(e,t,n){for(let r of t)try{await S(e,r,n)}catch{}}async function S(e,n,a){let o,s,c=!1;try{let r;try{r=await A(n.pending,n.signal)}catch(e){if(!n.signal.aborted)throw e;if(!await t(n.pending,n.teardownTimeoutMs))throw k(n.call.toolName,`execution`,n.teardownTimeoutMs,e);r=O(n.deadline)}let i=r;if(n.authorized!==void 0){let e=p(n.authorized,r);try{i=await A(e,n.signal)}catch(r){if(!n.signal.aborted)throw r;if(!await t(e,n.teardownTimeoutMs))throw k(n.call.toolName,`finalization`,n.teardownTimeoutMs,r);i=O(n.deadline)}}o=E(await C(e,n,i),a)}catch(e){c=u(e)===`fatal`,s=e,o=E(h(P(e),N(e)),a)}let l=r({callId:n.call.callId,content:[...o.content],isError:o.isError});if(e.history.append({kind:`tool-result`,callId:n.call.callId,message:l,result:o}),await j(e,{type:`tool-result`,call:n.call,result:o,trace:n.trace}),await j(e,{type:`span-end`,trace:n.trace,at:F(),status:o.isError?`error`:`success`,output:o.isError?{error:o.error}:o.value,...o.isError?{error:{type:`ToolError`,message:o.error.message,code:o.error.code}}:{}}),o.additionalContext!==void 0&&e.history.append({kind:`user`,message:i({content:[...o.additionalContext],source:{kind:`app`,producer:`tool:${n.call.toolName}`}})}),c)throw s;return o}async function C(e,t,n){let r=e.maxResultTokens,i=e.catalog.get(t.call.toolName)?.maxOutputTokens,c=r===void 0?i:i===void 0?r:Math.min(r,i);if(c===void 0)return n;let l=a(n.content);if(l<=c)return n;let u=n.content.filter(e=>e.type===`text`);if(u.length===0)return n;let d=u.map(e=>e.text).join(`
1
+ import{detachedFrozen as e}from"../../primitives/snapshot.js";import{waitForSettlement as t}from"../../async/settlement.js";import{createSpanId as n}from"../../observation/context.js";import{createToolResultMessage as r,createUserMessage as i}from"../../message/message.js";import{estimateTextBlockTokens as a,previewForSpill as o,truncateMiddleToTokens as s}from"../tool/output-budget.js";import{TOOL_ERROR_CODES as c,ToolError as l,toolErrorDisposition as u}from"../tool/errors.js";import{authorizeToolCall as d,dispatchAuthorizedToolCall as f,finalizeToolCall as p,prepareToolCall as m,toolFailure as h}from"../tool/pipeline.js";async function g(e){let t=M(e.maxParallel??8,`maxParallel`),n=M(e.maxResultBytes??4194304,`maxResultBytes`),r=M(e.maxDurationMs??6e5,`maxDurationMs`),i=M(e.teardownTimeoutMs??3e4,`teardownTimeoutMs`),a=Object.freeze(e.calls.map(T)),o=Math.max(0,e.dispatchLimit??a.length),s=[],c=0,l=0,u=0,d,f=0,p;for(;f<a.length;){let m=a[f];if(m===void 0)break;let h=p??_(e,m);if(p=void 0,h.mode===`exclusive`){let t=await v(e,h,l<o,r,i);c+=+!!t.dispatched,l+=+(t.budgeted===!0),u+=+(t.declined===!0);let a=await S(e,t,n);s.push(a),d===void 0&&!a.isError&&a.concludesTurn&&(d=m.toolName),f++;continue}let g=[],y=new AbortController,b={...e,signal:AbortSignal.any([e.signal,y.signal])},C=h;try{for(;f<a.length&&g.length<t&&a[f]!==void 0;){let e=C;if(e.mode!==`parallel`)break;let n=await v(b,e,l<o,r,i);c+=+!!n.dispatched,l+=+(n.budgeted===!0),u+=+(n.declined===!0),g.push(n),f++;let s=a[f];s!==void 0&&g.length<t&&(C=_(b,s),C.mode!==`parallel`&&(p=C))}}catch(t){throw y.abort(t),await x(e,g,n),t}if(g.length===0)continue;let w,T=!1;for(let t of g)try{let r=await S(e,t,n);s.push(r),d===void 0&&!r.isError&&r.concludesTurn&&(d=t.call.toolName)}catch(e){T||(w=e),T=!0,y.abort(e)}if(T)throw w}return{results:Object.freeze(s),concluded:d!==void 0,...d===void 0?{}:{concludedBy:d},dispatched:c,budgeted:l,declined:u}}function _(e,t){return m({catalog:e.catalog,call:t,position:e.position,signal:e.signal,...e.logger===void 0?{}:{logger:e.logger},...e.interceptors===void 0?{}:{interceptors:e.interceptors},...e.approvals===void 0?{}:{approvals:e.approvals}})}async function v(e,r,i,a,o){let s=AbortSignal.timeout(a),l=AbortSignal.any([e.signal,s]),u={...r,options:{...r.options,signal:l,teardownTimeoutMs:o},context:{...r.context,signal:l}},p=u.options.call,m={traceId:e.parentTrace.traceId,spanId:n(),parentSpanId:e.parentTrace.spanId};e.history.append({kind:`tool-call`,callId:p.callId,name:p.toolName,rawArguments:p.rawArguments}),await j(e,{type:`span-start`,trace:m,at:F(),name:`execute_tool ${p.toolName}`,kind:`execute_tool`,attributes:{"gen_ai.operation.name":`execute_tool`,"gen_ai.tool.name":p.toolName,"gen_ai.tool.call.id":p.callId},input:p.rawArguments}),await j(e,{type:`tool-call`,call:p,trace:m});let g=e.catalog.get(p.toolName)?.budgetExempt===!0;if(!i&&!g)return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,declined:!0,pending:Promise.resolve(y(e.declineReason??`tool-calls`))};if(e.signal.aborted)return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(h(`the call was cancelled before it started`,c.ABORTED_BEFORE_DISPATCH))};let _,v={...u,options:{...u.options,onApprovalRequest:async t=>{_=e.accounting?.startOperation(`user-input`,{toolCallId:t.callId,data:{action:`approval`,toolName:t.toolName}}),await j(e,{type:`approval-request`,request:t,trace:m})},...e.accounting===void 0?{}:{onApprovalSettled:(t,n)=>{_!==void 0&&(e.accounting?.endOperation(_,t,n===void 0?{}:{error:n}),_=void 0)}}}},b=d(v),x;try{x=await A(b,l)}catch(e){if(!l.aborted)throw e;if(!await t(b,o))throw k(p.toolName,`authorization`,o,e);return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(O(s,a))}}if(x.kind===`final`)return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(x.result)};try{await e.checkpoint?.({kind:`before-tool-dispatch`,call:p,snapshot:e.history.snapshot(),signal:l,...e.logger===void 0?{}:{logger:e.logger}})}catch(e){return{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,dispatched:!1,pending:Promise.resolve(h(`history checkpoint failed: ${P(e)}`,c.CHECKPOINT_FAILED))}}let S=f(x.call);return S.catch(()=>void 0),{call:p,trace:m,signal:l,deadline:s,teardownTimeoutMs:o,authorized:x.call,dispatched:!0,budgeted:!g,pending:S}}function y(e){return{isError:!1,value:void 0,content:[{type:`text`,text:b(e)}],meta:{declined:!0,reason:e}}}function b(e){let t=` Answer now from what you already have, and say plainly what is unverified or unfinished.`;switch(e){case`tool-calls`:return`This call was not run: the turn has spent its tool-call budget. Further work calls will not run either, so do not retry it.`+t;case`repeated-tool-call`:return`This call was not run: it repeats a call already made with the same arguments, and repeating it cannot produce a new result. Change approach or finish.`+t;case`tool-call-cycle`:return`This call was not run: the same sequence of calls has repeated several times without progress. Break the cycle rather than re-entering it.`+t;case`tokens`:return`This call was not run: the turn has spent its token budget.`+t;case`consecutive-tool-errors`:return`This call was not run: too many calls in a row have failed. Something in the approach is wrong, not the individual call.`+t;case`steps`:return`This call was not run: the turn has no model steps left.`+t;case`usage-required`:return`This call was not run: the run policy requires provider usage reporting that the last model call did not supply.`+t}}async function x(e,t,n){for(let r of t)try{await S(e,r,n)}catch{}}async function S(e,n,a){let o,s,c=!1;try{let r;try{r=await A(n.pending,n.signal)}catch(e){if(!n.signal.aborted)throw e;if(!await t(n.pending,n.teardownTimeoutMs))throw k(n.call.toolName,`execution`,n.teardownTimeoutMs,e);r=O(n.deadline)}let i=r;if(n.authorized!==void 0){let e=p(n.authorized,r);try{i=await A(e,n.signal)}catch(r){if(!n.signal.aborted)throw r;if(!await t(e,n.teardownTimeoutMs))throw k(n.call.toolName,`finalization`,n.teardownTimeoutMs,r);i=O(n.deadline)}}o=E(await C(e,n,i),a)}catch(e){c=u(e)===`fatal`,s=e,o=E(h(P(e),N(e)),a)}let l=r({callId:n.call.callId,content:[...o.content],isError:o.isError});if(e.history.append({kind:`tool-result`,callId:n.call.callId,message:l,result:o}),await j(e,{type:`tool-result`,call:n.call,result:o,trace:n.trace}),await j(e,{type:`span-end`,trace:n.trace,at:F(),status:o.isError?`error`:`success`,output:o.isError?{error:o.error}:o.value,...o.isError?{error:{type:`ToolError`,message:o.error.message,code:o.error.code}}:{}}),o.additionalContext!==void 0&&e.history.append({kind:`user`,message:i({content:[...o.additionalContext],source:{kind:`app`,producer:`tool:${n.call.toolName}`}})}),c)throw s;return o}async function C(e,t,n){let r=e.maxResultTokens,i=e.catalog.get(t.call.toolName)?.maxOutputTokens,c=r===void 0?i:i===void 0?r:Math.min(r,i);if(c===void 0)return n;let l=a(n.content);if(l<=c)return n;let u=n.content.filter(e=>e.type===`text`);if(u.length===0)return n;let d=u.map(e=>e.text).join(`
2
2
  `),f=e.resultOverflow??`auto`,p=e.spillStore;if(f!==`truncate`&&p!==void 0)try{let e=await p.save(d,{toolName:t.call.toolName,callId:String(t.call.callId)});return w(n,`${o(d,Math.max(1,Math.floor(c*.75)))}\n\n[Output exceeded this call's budget of ${String(c)} estimated tokens. The full ${String(e.bytes)} bytes are saved. ${e.retrieval}]`,{outputSpilled:{locator:e.locator,bytes:e.bytes,estimatedTokens:l}})}catch{}let m=s(d,c);return w(n,m.text+`\n\n[Output was ${String(m.originalTokens)} estimated tokens, over this call's budget of ${String(c)}. Re-run more narrowly if you need the omitted part.]`,{outputTruncated:{estimatedTokens:m.originalTokens,budget:c}})}function w(e,t,n){let r=!1,i=[];for(let n of e.content){if(n.type!==`text`){i.push(n);continue}r||(r=!0,i.push({type:`text`,text:t}))}return{...e,content:i,meta:{...e.meta,...n}}}function T(t){if(typeof t.callId!=`string`||t.callId.length===0||typeof t.toolName!=`string`||t.toolName.length===0||typeof t.rawArguments!=`string`)throw TypeError(`tool call identity, name, and raw arguments must be strings`);return e(t)}function E(t,n){try{if(D(t)>n)return e(h(`tool result exceeds the ${n}-byte retention limit`,c.INVALID_RESULT));let r=e(t);return D(r)>n?e(h(`tool result exceeds the ${n}-byte retention limit`,c.INVALID_RESULT)):r}catch(e){throw l.fatal(`tool result could not be detached as lossless structured data`,c.INVALID_RESULT,{cause:e})}}function D(e){let t=JSON.stringify(e);if(t===void 0)throw TypeError(`tool result is not lossless JSON`);return new TextEncoder().encode(t).byteLength}function O(e,t){let n=t===void 0?`configured time limit`:`${t}ms time limit`;return e.aborted?h(`the tool exceeded its ${n}`,c.TIMEOUT):h(`the call was cancelled`,c.ABORTED)}function k(e,t,n,r){return l.fatal(`tool "${e}" ${t} ignored cancellation for more than ${n}ms; the in-process operation may still be running`,c.TEARDOWN_TIMEOUT,{cause:r})}async function A(e,t){if(t.aborted)throw t.reason??Error(`tool call aborted`);return await new Promise((n,r)=>{let i=()=>{t.removeEventListener(`abort`,i),r(t.reason??Error(`tool call aborted`))};t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}async function j(t,n){await t.emit?.(e(n))}function M(e,t){if(!Number.isInteger(e)||e<1)throw RangeError(`${t} must be a positive integer`);return e}function N(e){return typeof e==`object`&&e&&`code`in e&&typeof e.code==`string`?e.code:c.FAILED}function P(e){return e instanceof Error?e.message:String(e)}function F(){return new Date().toISOString()}export{g as runToolCalls};
3
3
  //# sourceMappingURL=schedule.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schedule.js","names":[],"sources":["../../../src/agent/loop/schedule.ts"],"sourcesContent":["import { createToolResultMessage, createUserMessage } from '../../message/index.ts'\nimport type { ContentBlock } from '../../message/index.ts'\nimport { detachedFrozen } from '../../primitives/index.ts'\nimport type { JsonObject } from '../../primitives/index.ts'\nimport { waitForSettlement } from '../../async/index.ts'\nimport type { History } from '../history/history.ts'\nimport type { ApprovalBroker } from '../tool/approval.ts'\nimport type { ToolCallPosition, ToolExecutionResult } from '../tool/definition.ts'\nimport {\n estimateTextBlockTokens, previewForSpill, truncateMiddleToTokens,\n type SpillStore, type ToolOutputOverflowPolicy,\n} from '../tool/output-budget.ts'\nimport { TOOL_ERROR_CODES, ToolError, toolErrorDisposition } from '../tool/errors.ts'\nimport {\n authorizeToolCall, dispatchAuthorizedToolCall, finalizeToolCall, prepareToolCall, toolFailure,\n type AuthorizedToolCall, type ToolCallRequest, type ToolInterceptor,\n} from '../tool/pipeline.ts'\nimport type { ToolCatalog } from '../tool/registry.ts'\nimport { createSpanId, type TraceRef } from '../trace/trace.ts'\nimport type { AgentEvent, ToolDeclineReason, TurnHooks } from './events.ts'\nimport type { RunAccountingPort } from '../accounting/contracts.ts'\nimport type { SdkLogger } from '../../logging/types.ts'\n\nexport interface RunToolCallsOptions {\n readonly calls: readonly ToolCallRequest[]\n readonly catalog: ToolCatalog\n readonly history: History\n readonly position: ToolCallPosition\n readonly signal: AbortSignal\n readonly logger?: SdkLogger\n readonly parentTrace: TraceRef\n readonly maxParallel?: number\n /**\n * How many BUDGETED calls may still be dispatched this step.\n *\n * Calls to a `budgetExempt` tool are not counted against it, so a spent\n * budget never blocks the model from submitting, asking, or delegating.\n */\n readonly dispatchLimit?: number\n /** Why calls past `dispatchLimit` are not run; shown to the model verbatim. */\n readonly declineReason?: ToolDeclineReason\n /** Estimated tokens of text one result may put in front of the model. */\n readonly maxResultTokens?: number\n /** What happens to output over that budget. Defaults to `auto`. */\n readonly resultOverflow?: ToolOutputOverflowPolicy\n /** Where spilled output goes; `auto` spills only when this is mounted. */\n readonly spillStore?: SpillStore\n /** Maximum serialized bytes retained for one finalized result. Defaults to 4 MiB. */\n readonly maxResultBytes?: number\n /** End-to-end wall-clock allowance for one call. Defaults to 10 minutes. */\n readonly maxDurationMs?: number\n /** Maximum cancellation settlement wait. Defaults to 30 seconds. */\n readonly teardownTimeoutMs?: number\n readonly interceptors?: readonly ToolInterceptor[]\n readonly approvals?: ApprovalBroker\n readonly emit?: (event: AgentEvent) => Promise<void>\n readonly checkpoint?: TurnHooks['checkpoint']\n readonly accounting?: RunAccountingPort\n}\nexport interface ToolCallsOutcome {\n readonly results: readonly ToolExecutionResult[]\n readonly concluded: boolean\n readonly concludedBy?: string\n readonly dispatched: number\n /** Dispatched calls that spent budget; exempt tools are excluded. */\n readonly budgeted: number\n /** Calls the loop refused to run, for the reason in `declineReason`. */\n readonly declined: number\n}\n\ninterface Slot {\n readonly call: ToolCallRequest\n readonly trace: TraceRef\n readonly authorized?: AuthorizedToolCall\n readonly pending: Promise<ToolExecutionResult>\n readonly dispatched: boolean\n /** Whether this dispatch spent turn budget; exempt tools never do. */\n readonly budgeted?: boolean\n /** Set when the loop refused to run the call. */\n readonly declined?: boolean\n readonly signal: AbortSignal\n readonly deadline: AbortSignal\n readonly teardownTimeoutMs: number\n}\n\n/** Execute safe siblings concurrently while committing every result in model order. */\nexport async function runToolCalls(options: RunToolCallsOptions): Promise<ToolCallsOutcome> {\n const maxParallel = positiveInteger(options.maxParallel ?? 8, 'maxParallel')\n const maxResultBytes = positiveInteger(options.maxResultBytes ?? 4 * 1024 * 1024, 'maxResultBytes')\n const maxDurationMs = positiveInteger(options.maxDurationMs ?? 10 * 60_000, 'maxDurationMs')\n const teardownTimeoutMs = positiveInteger(options.teardownTimeoutMs ?? 30_000, 'teardownTimeoutMs')\n const calls = Object.freeze(options.calls.map(immutableCall))\n const dispatchLimit = Math.max(0, options.dispatchLimit ?? calls.length)\n const results: ToolExecutionResult[] = []\n let dispatched = 0\n let budgeted = 0\n let declined = 0\n let concludedBy: string | undefined\n let index = 0\n let carried: ReturnType<typeof prepareToolCall> | undefined\n\n while (index < calls.length) {\n const first = calls[index]\n if (first === undefined) break\n const prepared = carried ?? prepare(options, first)\n carried = undefined\n if (prepared.mode === 'exclusive') {\n const slot = await start(options, prepared, budgeted < dispatchLimit, maxDurationMs, teardownTimeoutMs)\n dispatched += slot.dispatched ? 1 : 0\n budgeted += slot.budgeted === true ? 1 : 0\n declined += slot.declined === true ? 1 : 0\n const result = await commit(options, slot, maxResultBytes)\n results.push(result)\n if (concludedBy === undefined && !result.isError && result.concludesTurn) concludedBy = first.toolName\n index++\n continue\n }\n\n // A rolling parallel segment. Re-prepare each call immediately before start;\n // an updated registry can therefore turn the next call into a barrier.\n const segment: Slot[] = []\n const segmentAbort = new AbortController()\n const segmentOptions: RunToolCallsOptions = {\n ...options,\n signal: AbortSignal.any([options.signal, segmentAbort.signal]),\n }\n let nextPrepared = prepared\n try {\n while (index < calls.length && segment.length < maxParallel) {\n const call = calls[index]\n if (call === undefined) break\n const candidate = nextPrepared\n if (candidate.mode !== 'parallel') break\n const slot = await start(segmentOptions, candidate, budgeted < dispatchLimit, maxDurationMs, teardownTimeoutMs)\n dispatched += slot.dispatched ? 1 : 0\n budgeted += slot.budgeted === true ? 1 : 0\n declined += slot.declined === true ? 1 : 0\n segment.push(slot)\n index++\n const nextCall = calls[index]\n if (nextCall !== undefined && segment.length < maxParallel) {\n nextPrepared = prepare(segmentOptions, nextCall)\n if (nextPrepared.mode !== 'parallel') carried = nextPrepared\n }\n }\n } catch (error: unknown) {\n // Admission of a later sibling failed after earlier bodies started.\n // Cancel and drain everything already owned before propagating that error.\n segmentAbort.abort(error)\n await drainSegment(options, segment, maxResultBytes)\n throw error\n }\n if (segment.length === 0) continue\n // Bodies have already started. Finalization and history publication remain ordered.\n let fatal: unknown\n let hasFatal = false\n for (const slot of segment) {\n try {\n const result = await commit(options, slot, maxResultBytes)\n results.push(result)\n if (concludedBy === undefined && !result.isError && result.concludesTurn) concludedBy = slot.call.toolName\n } catch (error: unknown) {\n if (!hasFatal) fatal = error\n hasFatal = true\n segmentAbort.abort(error)\n }\n }\n // Every parallel body was already dispatched. Commit/drain all siblings so\n // none is orphaned, then propagate the first fatal contract violation.\n if (hasFatal) throw fatal\n }\n return {\n results: Object.freeze(results),\n concluded: concludedBy !== undefined,\n ...concludedBy === undefined ? {} : { concludedBy },\n dispatched,\n budgeted,\n declined,\n }\n}\n\nfunction prepare(options: RunToolCallsOptions, call: ToolCallRequest) {\n return prepareToolCall({\n catalog: options.catalog, call, position: options.position, signal: options.signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n ...options.interceptors === undefined ? {} : { interceptors: options.interceptors },\n ...options.approvals === undefined ? {} : { approvals: options.approvals },\n })\n}\n\nasync function start(\n options: RunToolCallsOptions,\n prepared: ReturnType<typeof prepareToolCall>,\n hasBudget: boolean,\n maxDurationMs: number,\n teardownTimeoutMs: number,\n): Promise<Slot> {\n const deadline = AbortSignal.timeout(maxDurationMs)\n const signal = AbortSignal.any([options.signal, deadline])\n const boundedPrepared = {\n ...prepared,\n options: { ...prepared.options, signal, teardownTimeoutMs },\n context: { ...prepared.context, signal },\n }\n const call = boundedPrepared.options.call\n const trace: TraceRef = {\n traceId: options.parentTrace.traceId,\n spanId: createSpanId(),\n parentSpanId: options.parentTrace.spanId,\n }\n options.history.append({ kind: 'tool-call', callId: call.callId, name: call.toolName, rawArguments: call.rawArguments })\n await emitEvent(options, { type: 'span-start', trace, at: now(), name: `execute_tool ${call.toolName}`, kind: 'execute_tool', attributes: {\n 'gen_ai.operation.name': 'execute_tool', 'gen_ai.tool.name': call.toolName, 'gen_ai.tool.call.id': call.callId,\n } })\n await emitEvent(options, { type: 'tool-call', call, trace })\n // A tool the model may always reach: submitting, asking, delegating. Letting\n // a budget block these is what turns a spent budget into a dead run.\n const exempt = options.catalog.get(call.toolName)?.budgetExempt === true\n if (!hasBudget && !exempt) return {\n call, trace, signal, deadline, teardownTimeoutMs, dispatched: false, declined: true,\n pending: Promise.resolve(declinedResult(options.declineReason ?? 'tool-calls')),\n }\n if (options.signal.aborted) return {\n call, trace, signal, deadline, teardownTimeoutMs, dispatched: false,\n pending: Promise.resolve(toolFailure('the call was cancelled before it started', TOOL_ERROR_CODES.ABORTED_BEFORE_DISPATCH)),\n }\n let approvalOperation: string | undefined\n const withApprovalEvent = {\n ...boundedPrepared,\n options: {\n ...boundedPrepared.options,\n onApprovalRequest: async (request: Parameters<NonNullable<typeof prepared.options.onApprovalRequest>>[0]) => {\n approvalOperation = options.accounting?.startOperation('user-input', {\n toolCallId: request.callId,\n data: { action: 'approval', toolName: request.toolName },\n })\n await emitEvent(options, { type: 'approval-request', request, trace })\n },\n ...options.accounting === undefined ? {} : {\n onApprovalSettled: (status: 'success' | 'error' | 'aborted', error?: unknown) => {\n if (approvalOperation !== undefined) {\n options.accounting?.endOperation(approvalOperation, status, error === undefined ? {} : { error })\n approvalOperation = undefined\n }\n },\n },\n },\n }\n const authorizationPending = authorizeToolCall(withApprovalEvent)\n let authorization: Awaited<ReturnType<typeof authorizeToolCall>>\n try {\n authorization = await raceWithSignal(authorizationPending, signal)\n } catch (error: unknown) {\n if (!signal.aborted) throw error\n const settled = await waitForSettlement(authorizationPending, teardownTimeoutMs)\n if (!settled) throw teardownFailure(call.toolName, 'authorization', teardownTimeoutMs, error)\n return {\n call, trace, signal, deadline, teardownTimeoutMs, dispatched: false,\n pending: Promise.resolve(cancelledResult(deadline, maxDurationMs)),\n }\n }\n if (authorization.kind === 'final') return {\n call, trace, signal, deadline, teardownTimeoutMs,\n dispatched: false, pending: Promise.resolve(authorization.result),\n }\n try {\n await options.checkpoint?.({\n kind: 'before-tool-dispatch', call, snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n })\n } catch (error: unknown) {\n return {\n call, trace, signal, deadline, teardownTimeoutMs, dispatched: false,\n pending: Promise.resolve(toolFailure(`history checkpoint failed: ${messageOf(error)}`, TOOL_ERROR_CODES.CHECKPOINT_FAILED)),\n }\n }\n const pending = dispatchAuthorizedToolCall(authorization.call)\n // Observe rejection in the same turn in which dispatch creates the promise.\n // commit() still receives and propagates the original rejection in order.\n void pending.catch(() => undefined)\n return {\n call, trace, signal, deadline, teardownTimeoutMs,\n authorized: authorization.call, dispatched: true, budgeted: !exempt,\n pending,\n }\n}\n\n/**\n * What the model reads when the loop refuses to run a call.\n *\n * Not a failure. A failure is something that went wrong, and a model answers\n * one by retrying — with a smaller argument, a different path — which spends\n * exactly what is no longer there. This says what happened and what to do\n * instead, in the plainest terms available, and nothing about it reads as\n * broken tooling.\n * @param reason - Which limit refused the call.\n * @returns A successful result carrying the instruction.\n */\nfunction declinedResult(reason: ToolDeclineReason): ToolExecutionResult {\n return {\n isError: false,\n value: undefined,\n content: [{ type: 'text', text: declineText(reason) }],\n // Never shown to the model; lets a UI render this as declined rather than\n // as work that succeeded.\n meta: { declined: true, reason },\n }\n}\n\n/**\n * The instruction for one decline reason.\n *\n * Each limit gets its own wording: a model told \"no remaining tool-call\n * budget\" when it actually tripped the repeat guard learns the wrong lesson\n * and repeats the call in the next turn.\n * @param reason - Which limit refused the call.\n * @returns The sentence the model reads.\n */\nfunction declineText(reason: ToolDeclineReason): string {\n const finish = ' Answer now from what you already have, and say plainly what is'\n + ' unverified or unfinished.'\n switch (reason) {\n case 'tool-calls':\n return 'This call was not run: the turn has spent its tool-call budget.'\n + ' Further work calls will not run either, so do not retry it.' + finish\n case 'repeated-tool-call':\n return 'This call was not run: it repeats a call already made with the same'\n + ' arguments, and repeating it cannot produce a new result. Change'\n + ' approach or finish.' + finish\n case 'tool-call-cycle':\n return 'This call was not run: the same sequence of calls has repeated'\n + ' several times without progress. Break the cycle rather than'\n + ' re-entering it.' + finish\n case 'tokens':\n return 'This call was not run: the turn has spent its token budget.' + finish\n case 'consecutive-tool-errors':\n return 'This call was not run: too many calls in a row have failed.'\n + ' Something in the approach is wrong, not the individual call.' + finish\n case 'steps':\n return 'This call was not run: the turn has no model steps left.' + finish\n case 'usage-required':\n return 'This call was not run: the run policy requires provider usage'\n + ' reporting that the last model call did not supply.' + finish\n }\n}\n\nasync function drainSegment(\n options: RunToolCallsOptions,\n segment: readonly Slot[],\n maxResultBytes: number,\n): Promise<void> {\n for (const slot of segment) {\n try { await commit(options, slot, maxResultBytes) }\n catch { /* The admission failure remains primary after every owned slot settles. */ }\n }\n}\n\nasync function commit(\n options: RunToolCallsOptions,\n slot: Slot,\n maxResultBytes: number,\n): Promise<ToolExecutionResult> {\n let result: ToolExecutionResult\n let fatal: unknown\n let hasFatal = false\n try {\n let pending: ToolExecutionResult\n try {\n pending = await raceWithSignal(slot.pending, slot.signal)\n } catch (error: unknown) {\n if (!slot.signal.aborted) throw error\n const settled = await waitForSettlement(slot.pending, slot.teardownTimeoutMs)\n if (!settled) throw teardownFailure(slot.call.toolName, 'execution', slot.teardownTimeoutMs, error)\n pending = cancelledResult(slot.deadline)\n }\n let finalized = pending\n if (slot.authorized !== undefined) {\n const finalizing = finalizeToolCall(slot.authorized, pending)\n try {\n finalized = await raceWithSignal(finalizing, slot.signal)\n } catch (error: unknown) {\n if (!slot.signal.aborted) throw error\n const settled = await waitForSettlement(finalizing, slot.teardownTimeoutMs)\n if (!settled) throw teardownFailure(slot.call.toolName, 'finalization', slot.teardownTimeoutMs, error)\n finalized = cancelledResult(slot.deadline)\n }\n }\n result = immutableResult(await boundOutput(options, slot, finalized), maxResultBytes)\n } catch (error: unknown) {\n hasFatal = toolErrorDisposition(error) === 'fatal'\n fatal = error\n result = immutableResult(toolFailure(messageOf(error), errorCode(error)), maxResultBytes)\n }\n const message = createToolResultMessage({ callId: slot.call.callId, content: [...result.content], isError: result.isError })\n options.history.append({ kind: 'tool-result', callId: slot.call.callId, message, result })\n await emitEvent(options, { type: 'tool-result', call: slot.call, result, trace: slot.trace })\n await emitEvent(options, {\n type: 'span-end', trace: slot.trace, at: now(), status: result.isError ? 'error' : 'success',\n output: result.isError ? { error: result.error } : result.value,\n ...result.isError ? { error: { type: 'ToolError', message: result.error.message, code: result.error.code } } : {},\n })\n if (result.additionalContext !== undefined) {\n // Additional context is deliberately a separate application message.\n options.history.append({ kind: 'user', message: createUserMessage({\n content: [...result.additionalContext], source: { kind: 'app', producer: `tool:${slot.call.toolName}` },\n }) })\n }\n if (hasFatal) throw fatal\n return result\n}\n\n/**\n * Keep one tool result inside its share of the context window.\n *\n * This runs at the RESULT boundary rather than when the request is assembled,\n * which is the whole point: by the time an oversized result reaches the model\n * the window is already gone, and the turn's only remaining move is to lose\n * everything it has paid for. Both reference harnesses cut here.\n *\n * The budget is the stricter of the turn's and the tool's own declaration, so\n * a tool that knows it returns a lot can ask for room without any tool being\n * able to exceed what the host allows.\n * @param options - The scheduling options carrying budget and store.\n * @param slot - The call this result belongs to.\n * @param result - The finalized result.\n * @returns The result the model will read.\n */\nasync function boundOutput(\n options: RunToolCallsOptions,\n slot: Slot,\n result: ToolExecutionResult,\n): Promise<ToolExecutionResult> {\n const turnBudget = options.maxResultTokens\n const toolBudget = options.catalog.get(slot.call.toolName)?.maxOutputTokens\n const budget = turnBudget === undefined\n ? toolBudget\n : toolBudget === undefined ? turnBudget : Math.min(turnBudget, toolBudget)\n if (budget === undefined) return result\n const tokens = estimateTextBlockTokens(result.content)\n if (tokens <= budget) return result\n\n // Only text is shortened. Cutting an image block produces a corrupt image\n // rather than a smaller one, so those pass through and are counted by the\n // byte cap instead.\n const texts = result.content.filter(block => block.type === 'text')\n if (texts.length === 0) return result\n const full = texts.map(block => block.text).join('\\n')\n const policy = options.resultOverflow ?? 'auto'\n const store = options.spillStore\n\n if (policy !== 'truncate' && store !== undefined) {\n try {\n // Reserve room for the notice inside the budget, so the replacement is\n // never bigger than what it replaced.\n const record = await store.save(full, {\n toolName: slot.call.toolName, callId: String(slot.call.callId),\n })\n const preview = previewForSpill(full, Math.max(1, Math.floor(budget * 0.75)))\n return replaceText(result, `${preview}\\n\\n[Output exceeded this call's budget of `\n + `${String(budget)} estimated tokens. The full ${String(record.bytes)} bytes are saved. `\n + `${record.retrieval}]`, {\n outputSpilled: { locator: record.locator, bytes: record.bytes, estimatedTokens: tokens },\n })\n } catch {\n // Best-effort, deliberately: a store that is full or unreachable must not\n // cost the model a result it can still read most of.\n }\n }\n\n const truncated = truncateMiddleToTokens(full, budget)\n return replaceText(result, truncated.text\n + `\\n\\n[Output was ${String(truncated.originalTokens)} estimated tokens, over this call's `\n + `budget of ${String(budget)}. Re-run more narrowly if you need the omitted part.]`, {\n outputTruncated: { estimatedTokens: truncated.originalTokens, budget },\n })\n}\n\n/**\n * Swap a result's text for one shortened block, keeping everything else.\n * @param result - The original result.\n * @param text - The replacement text.\n * @param meta - What a UI should know about the replacement.\n * @returns The rewritten result.\n */\nfunction replaceText(\n result: ToolExecutionResult,\n text: string,\n meta: JsonObject,\n): ToolExecutionResult {\n // The replacement takes the FIRST text block's position and the other text\n // blocks drop out. Appending it after the non-text blocks instead would\n // reorder a result whose image came after its caption.\n let placed = false\n const content: ContentBlock[] = []\n for (const block of result.content) {\n if (block.type !== 'text') { content.push(block); continue }\n if (placed) continue\n placed = true\n content.push({ type: 'text', text })\n }\n // `value` is deliberately untouched: it is what a host logs and replays, and\n // shortening it would make the record disagree with what the tool returned.\n return { ...result, content, meta: { ...result.meta, ...meta } }\n}\n\nfunction immutableCall(call: ToolCallRequest): ToolCallRequest {\n if (typeof call.callId !== 'string' || call.callId.length === 0\n || typeof call.toolName !== 'string' || call.toolName.length === 0\n || typeof call.rawArguments !== 'string') {\n throw new TypeError('tool call identity, name, and raw arguments must be strings')\n }\n return detachedFrozen(call)\n}\n\nfunction immutableResult(result: ToolExecutionResult, maxResultBytes: number): ToolExecutionResult {\n try {\n if (serializedBytes(result) > maxResultBytes) {\n return detachedFrozen(toolFailure(\n `tool result exceeds the ${maxResultBytes}-byte retention limit`,\n TOOL_ERROR_CODES.INVALID_RESULT,\n ))\n }\n const detached = detachedFrozen(result)\n const bytes = serializedBytes(detached)\n if (bytes > maxResultBytes) {\n return detachedFrozen(toolFailure(\n `tool result exceeds the ${maxResultBytes}-byte retention limit`,\n TOOL_ERROR_CODES.INVALID_RESULT,\n ))\n }\n return detached\n } catch (error: unknown) {\n throw ToolError.fatal(\n 'tool result could not be detached as lossless structured data',\n TOOL_ERROR_CODES.INVALID_RESULT,\n { cause: error },\n )\n }\n}\n\nfunction serializedBytes(value: unknown): number {\n const serialized = JSON.stringify(value)\n if (serialized === undefined) throw new TypeError('tool result is not lossless JSON')\n return new TextEncoder().encode(serialized).byteLength\n}\n\nfunction cancelledResult(deadline: AbortSignal, maxDurationMs?: number): ToolExecutionResult {\n const limit = maxDurationMs === undefined ? 'configured time limit' : `${maxDurationMs}ms time limit`\n return deadline.aborted\n ? toolFailure(\n `the tool exceeded its ${limit}`,\n TOOL_ERROR_CODES.TIMEOUT,\n )\n : toolFailure('the call was cancelled', TOOL_ERROR_CODES.ABORTED)\n}\n\nfunction teardownFailure(\n toolName: string,\n stage: string,\n timeoutMs: number,\n cause: unknown,\n): ToolError {\n return ToolError.fatal(\n `tool \"${toolName}\" ${stage} ignored cancellation for more than ${timeoutMs}ms; the in-process operation may still be running`,\n TOOL_ERROR_CODES.TEARDOWN_TIMEOUT,\n { cause },\n )\n}\n\nasync function raceWithSignal<T>(pending: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) throw signal.reason ?? new Error('tool call aborted')\n return await new Promise<T>((resolve, reject) => {\n const abort = () => {\n signal.removeEventListener('abort', abort)\n reject(signal.reason ?? new Error('tool call aborted'))\n }\n signal.addEventListener('abort', abort, { once: true })\n void pending.then(\n value => { signal.removeEventListener('abort', abort); resolve(value) },\n error => { signal.removeEventListener('abort', abort); reject(error) },\n )\n })\n}\n\nasync function emitEvent(options: RunToolCallsOptions, event: AgentEvent): Promise<void> {\n await options.emit?.(detachedFrozen(event))\n}\n\nfunction positiveInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1) throw new RangeError(`${name} must be a positive integer`)\n return value\n}\nfunction errorCode(error: unknown): string {\n return typeof error === 'object' && error !== null && 'code' in error && typeof error.code === 'string'\n ? error.code : TOOL_ERROR_CODES.FAILED\n}\nfunction messageOf(error: unknown): string { return error instanceof Error ? error.message : String(error) }\nfunction now(): string { return new Date().toISOString() }\n"],"mappings":"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"}
1
+ {"version":3,"file":"schedule.js","names":[],"sources":["../../../src/agent/loop/schedule.ts"],"sourcesContent":["import { createToolResultMessage, createUserMessage } from '../../message/index.ts'\nimport type { ContentBlock } from '../../message/index.ts'\nimport { detachedFrozen } from '../../primitives/index.ts'\nimport type { JsonObject } from '../../primitives/index.ts'\nimport { waitForSettlement } from '../../async/index.ts'\nimport type { History } from '../history/history.ts'\nimport type { ApprovalBroker } from '../tool/approval.ts'\nimport type { ToolCallPosition, ToolExecutionResult } from '../tool/definition.ts'\nimport {\n estimateTextBlockTokens, previewForSpill, truncateMiddleToTokens,\n type SpillStore, type ToolOutputOverflowPolicy,\n} from '../tool/output-budget.ts'\nimport { TOOL_ERROR_CODES, ToolError, toolErrorDisposition } from '../tool/errors.ts'\nimport {\n authorizeToolCall, dispatchAuthorizedToolCall, finalizeToolCall, prepareToolCall, toolFailure,\n type AuthorizedToolCall, type ToolCallRequest, type ToolInterceptor,\n} from '../tool/pipeline.ts'\nimport type { ToolCatalog } from '../tool/registry.ts'\nimport { createSpanId, type TraceRef } from '../trace/trace.ts'\nimport type { AgentEvent, ToolDeclineReason, TurnHooks } from './events.ts'\nimport type { RunAccountingPort } from '../accounting/contracts.ts'\nimport type { SdkLogger } from '../../logging/types.ts'\n\nexport interface RunToolCallsOptions {\n readonly calls: readonly ToolCallRequest[]\n readonly catalog: ToolCatalog\n readonly history: History\n readonly position: ToolCallPosition\n readonly signal: AbortSignal\n readonly logger?: SdkLogger\n readonly parentTrace: TraceRef\n readonly maxParallel?: number\n /**\n * How many BUDGETED calls may still be dispatched this step.\n *\n * Calls to a `budgetExempt` tool are not counted against it, so a spent\n * budget never blocks the model from submitting, asking, or delegating.\n */\n readonly dispatchLimit?: number\n /** Why calls past `dispatchLimit` are not run; shown to the model verbatim. */\n readonly declineReason?: ToolDeclineReason\n /** Estimated tokens of text one result may put in front of the model. */\n readonly maxResultTokens?: number\n /** What happens to output over that budget. Defaults to `auto`. */\n readonly resultOverflow?: ToolOutputOverflowPolicy\n /** Where spilled output goes; `auto` spills only when this is mounted. */\n readonly spillStore?: SpillStore\n /** Maximum serialized bytes retained for one finalized result. Defaults to 4 MiB. */\n readonly maxResultBytes?: number\n /** End-to-end wall-clock allowance for one call. Defaults to 10 minutes. */\n readonly maxDurationMs?: number\n /** Maximum cancellation settlement wait. Defaults to 30 seconds. */\n readonly teardownTimeoutMs?: number\n readonly interceptors?: readonly ToolInterceptor[]\n readonly approvals?: ApprovalBroker\n readonly emit?: (event: AgentEvent) => Promise<void>\n readonly checkpoint?: TurnHooks['checkpoint']\n readonly accounting?: RunAccountingPort\n}\nexport interface ToolCallsOutcome {\n readonly results: readonly ToolExecutionResult[]\n readonly concluded: boolean\n readonly concludedBy?: string\n readonly dispatched: number\n /** Dispatched calls that spent budget; exempt tools are excluded. */\n readonly budgeted: number\n /** Calls the loop refused to run, for the reason in `declineReason`. */\n readonly declined: number\n}\n\ninterface Slot {\n readonly call: ToolCallRequest\n readonly trace: TraceRef\n readonly authorized?: AuthorizedToolCall\n readonly pending: Promise<ToolExecutionResult>\n readonly dispatched: boolean\n /** Whether this dispatch spent turn budget; exempt tools never do. */\n readonly budgeted?: boolean\n /** Set when the loop refused to run the call. */\n readonly declined?: boolean\n readonly signal: AbortSignal\n readonly deadline: AbortSignal\n readonly teardownTimeoutMs: number\n}\n\n/** Execute safe siblings concurrently while committing every result in model order. */\nexport async function runToolCalls(options: RunToolCallsOptions): Promise<ToolCallsOutcome> {\n const maxParallel = positiveInteger(options.maxParallel ?? 8, 'maxParallel')\n const maxResultBytes = positiveInteger(options.maxResultBytes ?? 4 * 1024 * 1024, 'maxResultBytes')\n const maxDurationMs = positiveInteger(options.maxDurationMs ?? 10 * 60_000, 'maxDurationMs')\n const teardownTimeoutMs = positiveInteger(options.teardownTimeoutMs ?? 30_000, 'teardownTimeoutMs')\n const calls = Object.freeze(options.calls.map(immutableCall))\n const dispatchLimit = Math.max(0, options.dispatchLimit ?? calls.length)\n const results: ToolExecutionResult[] = []\n let dispatched = 0\n let budgeted = 0\n let declined = 0\n let concludedBy: string | undefined\n let index = 0\n let carried: ReturnType<typeof prepareToolCall> | undefined\n\n while (index < calls.length) {\n const first = calls[index]\n if (first === undefined) break\n const prepared = carried ?? prepare(options, first)\n carried = undefined\n if (prepared.mode === 'exclusive') {\n const slot = await start(options, prepared, budgeted < dispatchLimit, maxDurationMs, teardownTimeoutMs)\n dispatched += slot.dispatched ? 1 : 0\n budgeted += slot.budgeted === true ? 1 : 0\n declined += slot.declined === true ? 1 : 0\n const result = await commit(options, slot, maxResultBytes)\n results.push(result)\n if (concludedBy === undefined && !result.isError && result.concludesTurn) concludedBy = first.toolName\n index++\n continue\n }\n\n // A rolling parallel segment. Re-prepare each call immediately before start;\n // an updated registry can therefore turn the next call into a barrier.\n const segment: Slot[] = []\n const segmentAbort = new AbortController()\n const segmentOptions: RunToolCallsOptions = {\n ...options,\n signal: AbortSignal.any([options.signal, segmentAbort.signal]),\n }\n let nextPrepared = prepared\n try {\n while (index < calls.length && segment.length < maxParallel) {\n const call = calls[index]\n if (call === undefined) break\n const candidate = nextPrepared\n if (candidate.mode !== 'parallel') break\n const slot = await start(segmentOptions, candidate, budgeted < dispatchLimit, maxDurationMs, teardownTimeoutMs)\n dispatched += slot.dispatched ? 1 : 0\n budgeted += slot.budgeted === true ? 1 : 0\n declined += slot.declined === true ? 1 : 0\n segment.push(slot)\n index++\n const nextCall = calls[index]\n if (nextCall !== undefined && segment.length < maxParallel) {\n nextPrepared = prepare(segmentOptions, nextCall)\n if (nextPrepared.mode !== 'parallel') carried = nextPrepared\n }\n }\n } catch (error: unknown) {\n // Admission of a later sibling failed after earlier bodies started.\n // Cancel and drain everything already owned before propagating that error.\n segmentAbort.abort(error)\n await drainSegment(options, segment, maxResultBytes)\n throw error\n }\n if (segment.length === 0) continue\n // Bodies have already started. Finalization and history publication remain ordered.\n let fatal: unknown\n let hasFatal = false\n for (const slot of segment) {\n try {\n const result = await commit(options, slot, maxResultBytes)\n results.push(result)\n if (concludedBy === undefined && !result.isError && result.concludesTurn) concludedBy = slot.call.toolName\n } catch (error: unknown) {\n if (!hasFatal) fatal = error\n hasFatal = true\n segmentAbort.abort(error)\n }\n }\n // Every parallel body was already dispatched. Commit/drain all siblings so\n // none is orphaned, then propagate the first fatal contract violation.\n if (hasFatal) throw fatal\n }\n return {\n results: Object.freeze(results),\n concluded: concludedBy !== undefined,\n ...concludedBy === undefined ? {} : { concludedBy },\n dispatched,\n budgeted,\n declined,\n }\n}\n\nfunction prepare(options: RunToolCallsOptions, call: ToolCallRequest) {\n return prepareToolCall({\n catalog: options.catalog, call, position: options.position, signal: options.signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n ...options.interceptors === undefined ? {} : { interceptors: options.interceptors },\n ...options.approvals === undefined ? {} : { approvals: options.approvals },\n })\n}\n\nasync function start(\n options: RunToolCallsOptions,\n prepared: ReturnType<typeof prepareToolCall>,\n hasBudget: boolean,\n maxDurationMs: number,\n teardownTimeoutMs: number,\n): Promise<Slot> {\n const deadline = AbortSignal.timeout(maxDurationMs)\n const signal = AbortSignal.any([options.signal, deadline])\n const boundedPrepared = {\n ...prepared,\n options: { ...prepared.options, signal, teardownTimeoutMs },\n context: { ...prepared.context, signal },\n }\n const call = boundedPrepared.options.call\n const trace: TraceRef = {\n traceId: options.parentTrace.traceId,\n spanId: createSpanId(),\n parentSpanId: options.parentTrace.spanId,\n }\n options.history.append({ kind: 'tool-call', callId: call.callId, name: call.toolName, rawArguments: call.rawArguments })\n await emitEvent(options, { type: 'span-start', trace, at: now(), name: `execute_tool ${call.toolName}`, kind: 'execute_tool', attributes: {\n 'gen_ai.operation.name': 'execute_tool', 'gen_ai.tool.name': call.toolName, 'gen_ai.tool.call.id': call.callId,\n }, input: call.rawArguments })\n await emitEvent(options, { type: 'tool-call', call, trace })\n // A tool the model may always reach: submitting, asking, delegating. Letting\n // a budget block these is what turns a spent budget into a dead run.\n const exempt = options.catalog.get(call.toolName)?.budgetExempt === true\n if (!hasBudget && !exempt) return {\n call, trace, signal, deadline, teardownTimeoutMs, dispatched: false, declined: true,\n pending: Promise.resolve(declinedResult(options.declineReason ?? 'tool-calls')),\n }\n if (options.signal.aborted) return {\n call, trace, signal, deadline, teardownTimeoutMs, dispatched: false,\n pending: Promise.resolve(toolFailure('the call was cancelled before it started', TOOL_ERROR_CODES.ABORTED_BEFORE_DISPATCH)),\n }\n let approvalOperation: string | undefined\n const withApprovalEvent = {\n ...boundedPrepared,\n options: {\n ...boundedPrepared.options,\n onApprovalRequest: async (request: Parameters<NonNullable<typeof prepared.options.onApprovalRequest>>[0]) => {\n approvalOperation = options.accounting?.startOperation('user-input', {\n toolCallId: request.callId,\n data: { action: 'approval', toolName: request.toolName },\n })\n await emitEvent(options, { type: 'approval-request', request, trace })\n },\n ...options.accounting === undefined ? {} : {\n onApprovalSettled: (status: 'success' | 'error' | 'aborted', error?: unknown) => {\n if (approvalOperation !== undefined) {\n options.accounting?.endOperation(approvalOperation, status, error === undefined ? {} : { error })\n approvalOperation = undefined\n }\n },\n },\n },\n }\n const authorizationPending = authorizeToolCall(withApprovalEvent)\n let authorization: Awaited<ReturnType<typeof authorizeToolCall>>\n try {\n authorization = await raceWithSignal(authorizationPending, signal)\n } catch (error: unknown) {\n if (!signal.aborted) throw error\n const settled = await waitForSettlement(authorizationPending, teardownTimeoutMs)\n if (!settled) throw teardownFailure(call.toolName, 'authorization', teardownTimeoutMs, error)\n return {\n call, trace, signal, deadline, teardownTimeoutMs, dispatched: false,\n pending: Promise.resolve(cancelledResult(deadline, maxDurationMs)),\n }\n }\n if (authorization.kind === 'final') return {\n call, trace, signal, deadline, teardownTimeoutMs,\n dispatched: false, pending: Promise.resolve(authorization.result),\n }\n try {\n await options.checkpoint?.({\n kind: 'before-tool-dispatch', call, snapshot: options.history.snapshot(), signal,\n ...(options.logger === undefined ? {} : { logger: options.logger }),\n })\n } catch (error: unknown) {\n return {\n call, trace, signal, deadline, teardownTimeoutMs, dispatched: false,\n pending: Promise.resolve(toolFailure(`history checkpoint failed: ${messageOf(error)}`, TOOL_ERROR_CODES.CHECKPOINT_FAILED)),\n }\n }\n const pending = dispatchAuthorizedToolCall(authorization.call)\n // Observe rejection in the same turn in which dispatch creates the promise.\n // commit() still receives and propagates the original rejection in order.\n void pending.catch(() => undefined)\n return {\n call, trace, signal, deadline, teardownTimeoutMs,\n authorized: authorization.call, dispatched: true, budgeted: !exempt,\n pending,\n }\n}\n\n/**\n * What the model reads when the loop refuses to run a call.\n *\n * Not a failure. A failure is something that went wrong, and a model answers\n * one by retrying — with a smaller argument, a different path — which spends\n * exactly what is no longer there. This says what happened and what to do\n * instead, in the plainest terms available, and nothing about it reads as\n * broken tooling.\n * @param reason - Which limit refused the call.\n * @returns A successful result carrying the instruction.\n */\nfunction declinedResult(reason: ToolDeclineReason): ToolExecutionResult {\n return {\n isError: false,\n value: undefined,\n content: [{ type: 'text', text: declineText(reason) }],\n // Never shown to the model; lets a UI render this as declined rather than\n // as work that succeeded.\n meta: { declined: true, reason },\n }\n}\n\n/**\n * The instruction for one decline reason.\n *\n * Each limit gets its own wording: a model told \"no remaining tool-call\n * budget\" when it actually tripped the repeat guard learns the wrong lesson\n * and repeats the call in the next turn.\n * @param reason - Which limit refused the call.\n * @returns The sentence the model reads.\n */\nfunction declineText(reason: ToolDeclineReason): string {\n const finish = ' Answer now from what you already have, and say plainly what is'\n + ' unverified or unfinished.'\n switch (reason) {\n case 'tool-calls':\n return 'This call was not run: the turn has spent its tool-call budget.'\n + ' Further work calls will not run either, so do not retry it.' + finish\n case 'repeated-tool-call':\n return 'This call was not run: it repeats a call already made with the same'\n + ' arguments, and repeating it cannot produce a new result. Change'\n + ' approach or finish.' + finish\n case 'tool-call-cycle':\n return 'This call was not run: the same sequence of calls has repeated'\n + ' several times without progress. Break the cycle rather than'\n + ' re-entering it.' + finish\n case 'tokens':\n return 'This call was not run: the turn has spent its token budget.' + finish\n case 'consecutive-tool-errors':\n return 'This call was not run: too many calls in a row have failed.'\n + ' Something in the approach is wrong, not the individual call.' + finish\n case 'steps':\n return 'This call was not run: the turn has no model steps left.' + finish\n case 'usage-required':\n return 'This call was not run: the run policy requires provider usage'\n + ' reporting that the last model call did not supply.' + finish\n }\n}\n\nasync function drainSegment(\n options: RunToolCallsOptions,\n segment: readonly Slot[],\n maxResultBytes: number,\n): Promise<void> {\n for (const slot of segment) {\n try { await commit(options, slot, maxResultBytes) }\n catch { /* The admission failure remains primary after every owned slot settles. */ }\n }\n}\n\nasync function commit(\n options: RunToolCallsOptions,\n slot: Slot,\n maxResultBytes: number,\n): Promise<ToolExecutionResult> {\n let result: ToolExecutionResult\n let fatal: unknown\n let hasFatal = false\n try {\n let pending: ToolExecutionResult\n try {\n pending = await raceWithSignal(slot.pending, slot.signal)\n } catch (error: unknown) {\n if (!slot.signal.aborted) throw error\n const settled = await waitForSettlement(slot.pending, slot.teardownTimeoutMs)\n if (!settled) throw teardownFailure(slot.call.toolName, 'execution', slot.teardownTimeoutMs, error)\n pending = cancelledResult(slot.deadline)\n }\n let finalized = pending\n if (slot.authorized !== undefined) {\n const finalizing = finalizeToolCall(slot.authorized, pending)\n try {\n finalized = await raceWithSignal(finalizing, slot.signal)\n } catch (error: unknown) {\n if (!slot.signal.aborted) throw error\n const settled = await waitForSettlement(finalizing, slot.teardownTimeoutMs)\n if (!settled) throw teardownFailure(slot.call.toolName, 'finalization', slot.teardownTimeoutMs, error)\n finalized = cancelledResult(slot.deadline)\n }\n }\n result = immutableResult(await boundOutput(options, slot, finalized), maxResultBytes)\n } catch (error: unknown) {\n hasFatal = toolErrorDisposition(error) === 'fatal'\n fatal = error\n result = immutableResult(toolFailure(messageOf(error), errorCode(error)), maxResultBytes)\n }\n const message = createToolResultMessage({ callId: slot.call.callId, content: [...result.content], isError: result.isError })\n options.history.append({ kind: 'tool-result', callId: slot.call.callId, message, result })\n await emitEvent(options, { type: 'tool-result', call: slot.call, result, trace: slot.trace })\n await emitEvent(options, {\n type: 'span-end', trace: slot.trace, at: now(), status: result.isError ? 'error' : 'success',\n output: result.isError ? { error: result.error } : result.value,\n ...result.isError ? { error: { type: 'ToolError', message: result.error.message, code: result.error.code } } : {},\n })\n if (result.additionalContext !== undefined) {\n // Additional context is deliberately a separate application message.\n options.history.append({ kind: 'user', message: createUserMessage({\n content: [...result.additionalContext], source: { kind: 'app', producer: `tool:${slot.call.toolName}` },\n }) })\n }\n if (hasFatal) throw fatal\n return result\n}\n\n/**\n * Keep one tool result inside its share of the context window.\n *\n * This runs at the RESULT boundary rather than when the request is assembled,\n * which is the whole point: by the time an oversized result reaches the model\n * the window is already gone, and the turn's only remaining move is to lose\n * everything it has paid for. Both reference harnesses cut here.\n *\n * The budget is the stricter of the turn's and the tool's own declaration, so\n * a tool that knows it returns a lot can ask for room without any tool being\n * able to exceed what the host allows.\n * @param options - The scheduling options carrying budget and store.\n * @param slot - The call this result belongs to.\n * @param result - The finalized result.\n * @returns The result the model will read.\n */\nasync function boundOutput(\n options: RunToolCallsOptions,\n slot: Slot,\n result: ToolExecutionResult,\n): Promise<ToolExecutionResult> {\n const turnBudget = options.maxResultTokens\n const toolBudget = options.catalog.get(slot.call.toolName)?.maxOutputTokens\n const budget = turnBudget === undefined\n ? toolBudget\n : toolBudget === undefined ? turnBudget : Math.min(turnBudget, toolBudget)\n if (budget === undefined) return result\n const tokens = estimateTextBlockTokens(result.content)\n if (tokens <= budget) return result\n\n // Only text is shortened. Cutting an image block produces a corrupt image\n // rather than a smaller one, so those pass through and are counted by the\n // byte cap instead.\n const texts = result.content.filter(block => block.type === 'text')\n if (texts.length === 0) return result\n const full = texts.map(block => block.text).join('\\n')\n const policy = options.resultOverflow ?? 'auto'\n const store = options.spillStore\n\n if (policy !== 'truncate' && store !== undefined) {\n try {\n // Reserve room for the notice inside the budget, so the replacement is\n // never bigger than what it replaced.\n const record = await store.save(full, {\n toolName: slot.call.toolName, callId: String(slot.call.callId),\n })\n const preview = previewForSpill(full, Math.max(1, Math.floor(budget * 0.75)))\n return replaceText(result, `${preview}\\n\\n[Output exceeded this call's budget of `\n + `${String(budget)} estimated tokens. The full ${String(record.bytes)} bytes are saved. `\n + `${record.retrieval}]`, {\n outputSpilled: { locator: record.locator, bytes: record.bytes, estimatedTokens: tokens },\n })\n } catch {\n // Best-effort, deliberately: a store that is full or unreachable must not\n // cost the model a result it can still read most of.\n }\n }\n\n const truncated = truncateMiddleToTokens(full, budget)\n return replaceText(result, truncated.text\n + `\\n\\n[Output was ${String(truncated.originalTokens)} estimated tokens, over this call's `\n + `budget of ${String(budget)}. Re-run more narrowly if you need the omitted part.]`, {\n outputTruncated: { estimatedTokens: truncated.originalTokens, budget },\n })\n}\n\n/**\n * Swap a result's text for one shortened block, keeping everything else.\n * @param result - The original result.\n * @param text - The replacement text.\n * @param meta - What a UI should know about the replacement.\n * @returns The rewritten result.\n */\nfunction replaceText(\n result: ToolExecutionResult,\n text: string,\n meta: JsonObject,\n): ToolExecutionResult {\n // The replacement takes the FIRST text block's position and the other text\n // blocks drop out. Appending it after the non-text blocks instead would\n // reorder a result whose image came after its caption.\n let placed = false\n const content: ContentBlock[] = []\n for (const block of result.content) {\n if (block.type !== 'text') { content.push(block); continue }\n if (placed) continue\n placed = true\n content.push({ type: 'text', text })\n }\n // `value` is deliberately untouched: it is what a host logs and replays, and\n // shortening it would make the record disagree with what the tool returned.\n return { ...result, content, meta: { ...result.meta, ...meta } }\n}\n\nfunction immutableCall(call: ToolCallRequest): ToolCallRequest {\n if (typeof call.callId !== 'string' || call.callId.length === 0\n || typeof call.toolName !== 'string' || call.toolName.length === 0\n || typeof call.rawArguments !== 'string') {\n throw new TypeError('tool call identity, name, and raw arguments must be strings')\n }\n return detachedFrozen(call)\n}\n\nfunction immutableResult(result: ToolExecutionResult, maxResultBytes: number): ToolExecutionResult {\n try {\n if (serializedBytes(result) > maxResultBytes) {\n return detachedFrozen(toolFailure(\n `tool result exceeds the ${maxResultBytes}-byte retention limit`,\n TOOL_ERROR_CODES.INVALID_RESULT,\n ))\n }\n const detached = detachedFrozen(result)\n const bytes = serializedBytes(detached)\n if (bytes > maxResultBytes) {\n return detachedFrozen(toolFailure(\n `tool result exceeds the ${maxResultBytes}-byte retention limit`,\n TOOL_ERROR_CODES.INVALID_RESULT,\n ))\n }\n return detached\n } catch (error: unknown) {\n throw ToolError.fatal(\n 'tool result could not be detached as lossless structured data',\n TOOL_ERROR_CODES.INVALID_RESULT,\n { cause: error },\n )\n }\n}\n\nfunction serializedBytes(value: unknown): number {\n const serialized = JSON.stringify(value)\n if (serialized === undefined) throw new TypeError('tool result is not lossless JSON')\n return new TextEncoder().encode(serialized).byteLength\n}\n\nfunction cancelledResult(deadline: AbortSignal, maxDurationMs?: number): ToolExecutionResult {\n const limit = maxDurationMs === undefined ? 'configured time limit' : `${maxDurationMs}ms time limit`\n return deadline.aborted\n ? toolFailure(\n `the tool exceeded its ${limit}`,\n TOOL_ERROR_CODES.TIMEOUT,\n )\n : toolFailure('the call was cancelled', TOOL_ERROR_CODES.ABORTED)\n}\n\nfunction teardownFailure(\n toolName: string,\n stage: string,\n timeoutMs: number,\n cause: unknown,\n): ToolError {\n return ToolError.fatal(\n `tool \"${toolName}\" ${stage} ignored cancellation for more than ${timeoutMs}ms; the in-process operation may still be running`,\n TOOL_ERROR_CODES.TEARDOWN_TIMEOUT,\n { cause },\n )\n}\n\nasync function raceWithSignal<T>(pending: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) throw signal.reason ?? new Error('tool call aborted')\n return await new Promise<T>((resolve, reject) => {\n const abort = () => {\n signal.removeEventListener('abort', abort)\n reject(signal.reason ?? new Error('tool call aborted'))\n }\n signal.addEventListener('abort', abort, { once: true })\n void pending.then(\n value => { signal.removeEventListener('abort', abort); resolve(value) },\n error => { signal.removeEventListener('abort', abort); reject(error) },\n )\n })\n}\n\nasync function emitEvent(options: RunToolCallsOptions, event: AgentEvent): Promise<void> {\n await options.emit?.(detachedFrozen(event))\n}\n\nfunction positiveInteger(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1) throw new RangeError(`${name} must be a positive integer`)\n return value\n}\nfunction errorCode(error: unknown): string {\n return typeof error === 'object' && error !== null && 'code' in error && typeof error.code === 'string'\n ? error.code : TOOL_ERROR_CODES.FAILED\n}\nfunction messageOf(error: unknown): string { return error instanceof Error ? error.message : String(error) }\nfunction now(): string { return new Date().toISOString() }\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{createSpanId as e}from"../../../observation/context.js";import{MODEL_ERROR_CODES as t}from"../../../errors/model-error.js";import{BlockAssembler as n}from"../../../stream/assembler.js";import{normalizeToolPairing as r}from"../../history/normalize.js";import{positiveFinite as i,positiveSafeInteger as a}from"./config.js";import{messageOf as o,modelAbortedFinish as ee,modelFailureFinish as s,now as c,serializedBytes as te}from"./common.js";import{StreamAbortError as ne,closeIterator as re,nextWithAbort as ie}from"./cancellation.js";import{runOptionalHook as l}from"./hooks.js";import{classifyTextPhases as u,contentTiming as d,createAssistant as f,dropDuplicateToolCalls as p,invalidHostToolCall as ae,recentToolResultIds as oe,systemText as se,textOf as m}from"./content.js";import{validateStreamChunk as ce}from"./validation.js";import{accountingUsageStop as le}from"./usage-stop.js";function h(e){let t=e.replace(/\s+/gu,` `).trim();return t.length>600?`${t.slice(0,600)}…`:t}function g(e){let t=[],n=[];for(let r of e.content)r.type===`text`||r.type===`reasoning`?t.push(r.text):r.type===`tool-call`?n.push(`${r.name}(${h(r.arguments)})`):r.type===`tool-result`?t.push(m(r.content)):t.push(`[${r.type}]`);return{role:e.role,producer:e.source.kind,...t.length===0?{}:{text:h(t.join(` `))},...n.length===0?{}:{toolCalls:n}}}function ue(e){let t=e.messages??[],n=Math.max(0,t.length-8);return{messageCount:t.length,...t.at(-1)===void 0?{}:{lastMessageId:t.at(-1)?.id},...e.system===void 0?{}:{system:h(e.system)},...e.tools===void 0||e.tools.length===0?{}:{tools:e.tools.map(e=>e.name)},...e.toolChoice===void 0?{}:{toolChoice:e.toolChoice},...n===0?{}:{earlierMessagesOmitted:n},messages:t.slice(-8).map(g)}}async function _(h,g,_,fe,v,y,b,x){let S=x===`forced-final`,C=x===`final`||S,w={traceId:v.traceId,spanId:e(),parentSpanId:v.spanId},T=r(h.history.messages()),E=oe(h.history),pe=h.history.generation(),me=h.history.entries().length,D=()=>{let e=le(h.accounting);if(!(e===void 0&&!g.aborted))return{trace:w,finish:g.aborted?{kind:`aborted`,failure:{code:`ABORTED`,message:o(g.reason)}}:{kind:`stop`},calls:[],afterToolCallIds:E,timing:d(!1,E.length>0),...e?.kind===`error`?{usageRequired:!0}:{},...e?.kind===`usage-unavailable`?{usageUnavailable:!0}:{}}},he=D();if(he!==void 0)return he;let O=await l(h.hooks?.beforeStep,[{turn:y,step:b,messages:T,snapshot:h.history.snapshot(),signal:g,...h.logger===void 0?{}:{logger:h.logger},emit:fe}],h,g,`beforeStep`),ge=D();if(ge!==void 0)return ge;if(O?.kind===`reject`)return{trace:w,finish:{kind:`error`,failure:{message:O.reason,code:`STEP_REJECTED`}},calls:[],afterToolCallIds:E,timing:d(!1,E.length>0)};(h.history.generation()!==pe||h.history.entries().length!==me)&&(T=r(h.history.messages())),O?.prepend!==void 0&&(T=Object.freeze([...O.prepend,...T]));let k=se(h,S),A=[...h.tools?.schemas()??[],...h.nativeTools??[]],j=!C&&h.outputFormat?.type===`json_schema`?{type:`text`}:h.outputFormat,M={...h.config,messages:T,...k.length===0?{}:{system:k},...A.length===0?{}:{tools:A},...C&&A.length>0?{toolChoice:`none`}:h.toolChoice===void 0?{}:{toolChoice:h.toolChoice},...h.imagePolicy===void 0?{}:{imagePolicy:h.imagePolicy},...j===void 0?{}:{outputFormat:j}},_e={...M,signal:g};try{await l(h.hooks?.checkpoint,[{kind:`before-model-request`,request:_e,snapshot:h.history.snapshot(),signal:g,...h.logger===void 0?{}:{logger:h.logger}}],h,g,`checkpoint`)}catch(e){return{trace:w,finish:{kind:`error`,failure:{message:`history checkpoint failed: ${o(e)}`,code:`CHECKPOINT_FAILED`}},calls:[],afterToolCallIds:E,timing:d(!1,E.length>0)}}let N=D();if(N!==void 0)return N;await _({type:`span-start`,trace:w,at:c(),name:`chat ${h.config.model}`,kind:`chat`,attributes:{"gen_ai.operation.name":`chat`,"gen_ai.request.model":h.config.model,...h.config.reasoningEffort===void 0?{}:{"gen_ai.request.reasoning_effort":h.config.reasoningEffort},turn:y,step:b,forcedFinal:S,phase:x},input:ue(M)}),await _({type:`step-start`,turn:y,step:b,trace:w,...S?{forcedFinal:!0}:{}});let P=new n,F=new Set,I=i(h.modelTimeoutMs??6e5,`modelTimeoutMs`),L=a(h.maxModelRequestBytes??33554432,`maxModelRequestBytes`),R=a(h.maxModelResponseBytes??33554432,`maxModelResponseBytes`),z=a(h.maxModelStreamEvents??1e5,`maxModelStreamEvents`),B=i(h.teardownTimeoutMs??3e4,`teardownTimeoutMs`),V,ve=!1,ye=!1,H;try{H=te(M)}catch(e){H=-1,P.push(s(`model request is not serializable: ${o(e)}`,`INVALID_MODEL_REQUEST`))}if(H>L)P.push(s(`model request exceeds the ${L}-byte limit`,`MODEL_REQUEST_TOO_LARGE`));else if(H>=0){let e=new AbortController,t=AbortSignal.any([g,e.signal]),n=!1,r=setTimeout(()=>{n=!0,e.abort(Error(`model stream exceeded ${I}ms`))},I),i=h.registry.stream({...M,signal:t},h.accounting?.modelInvocation),a=i[Symbol.asyncIterator](),c=!1,l=0,u=0,d=!1;try{for(;;){let n=await ie(a.next(),t);if(n.done===!0){c=!0;break}let r=n.value;try{ce(r,z)}catch(t){P.push(s(`model adapter emitted an invalid stream chunk: ${o(t)}`,`INVALID_MODEL_STREAM`)),e.abort(Error(`invalid model stream chunk`));break}l++;try{u+=te(r)}catch(t){P.push(s(`model adapter emitted a non-serializable stream chunk: ${o(t)}`,`INVALID_MODEL_STREAM`)),e.abort(Error(`non-serializable model stream chunk`));break}if(l>z||u>R){let t=l>z?`${z}-event`:`${R}-byte`;P.push(s(`model response exceeds the ${t} limit`,`MODEL_RESPONSE_TOO_LARGE`)),e.abort(Error(`model response resource limit exceeded`));break}if(d){P.push(s(`model adapter emitted data after its terminal finish chunk`,`INVALID_MODEL_STREAM`)),e.abort(Error(`invalid model stream`));break}P.push(r),!((r.type===`text-delta`||r.type===`reasoning-delta`||r.type===`tool-call-delta`)&&F.has(r.index))&&(r.type===`block-end`&&F.add(r.index),r.type===`finish`&&(d=!0),r.type===`text-delta`?await _({type:`text-delta`,index:r.index,text:r.text,phase:x===`process`?`commentary`:r.phase??`unknown`,trace:w}):r.type===`reasoning-delta`?await _({type:`reasoning-delta`,index:r.index,text:r.text,trace:w}):r.type===`image-delta`?await _({type:`image-delta`,itemId:r.itemId,data:r.data,mediaType:r.mediaType,...r.partialIndex===void 0?{}:{partialIndex:r.partialIndex},trace:w}):r.type===`usage`&&await _({type:`usage`,usage:r.usage,trace:w}))}}catch(e){if(!(e instanceof ne))throw e;P.push(g.aborted?ee(o(g.reason??e)):n?s(`model stream exceeded ${I}ms`,`MODEL_TIMEOUT`):s(o(e.cause??e),`MODEL_STREAM_ABORTED`))}finally{clearTimeout(r),c||(e.abort(Error(`model stream closed before exhaustion`)),await re(a,B)||P.push(s(`model stream ignored cancellation for more than ${B}ms; the adapter operation may still be running`,`MODEL_TEARDOWN_TIMEOUT`)))}let f=await i.report,p=h.accounting===void 0?void 0:await h.accounting.recordModelCall(f,{...M,signal:g});V=p?.report??f,ve=p?.usageRequired??!1,ye=p?.usageUnavailable??!1}let U=P.finish,W=U.kind===`aborted`,G;try{G=U.kind===`aborted`?P.interruptedBlocks():P.blocks()}catch(e){U={kind:`error`,failure:{message:`model adapter emitted an invalid block sequence: ${o(e)}`,code:`INVALID_MODEL_STREAM`}},W=!0,G=P.interruptedBlocks()}let K=P.textBlocks().filter(({block:e})=>!W||e.text.trim()!==``),be=0,xe=u(G.map(e=>{if(e.type!==`text`)return e;let t=K[be++];return e.phase===void 0&&t?.beforeNativeCall?{...e,phase:`commentary`}:e}),x===`process`,P.hasToolCalls),q=p(xe,h.history),J=q.blocks,Se=C&&h.outputFormat?.type===`json_schema`&&U.kind===`stop`&&!de(m(J),h.validateOutput)?{message:`model returned invalid JSON or failed the structured output validator`,code:t.MALFORMED_RESPONSE}:void 0,Y=(C&&J.some(e=>e.type===`tool-call`)?{message:`model emitted a host tool call during the final output phase`,code:`INVALID_TOOL_CALL`}:void 0)??Se??ae(J,h.history),X=Y===void 0?J:J.filter(e=>e.type!==`tool-call`),Z=Y===void 0?U:{kind:`error`,failure:Y},Q=X.length===0&&(Z.kind===`error`||Z.kind===`aborted`)?void 0:f(h,X,W?void 0:P.replayState),$=Q?.content.filter(e=>e.type===`tool-call`).map(e=>({callId:e.id,toolName:e.name,rawArguments:e.arguments}))??[],Ce=d($.length>0,E.length>0);if(X.some(e=>e.type===`text`)){let e=K.map(({index:e})=>e),t=Z.kind===`error`||Z.kind===`aborted`||Z.kind===`max-tokens`,n=0;for(let r of X){if(r.type!==`text`)continue;let i=e[n++];i!==void 0&&await _({type:`text-end`,index:i,text:r.text,phase:r.phase??`final-answer`,trace:w,...t?{incomplete:!0}:{}})}}return await _({type:`span-end`,trace:w,at:c(),status:Z.kind===`error`?`error`:Z.kind===`aborted`?`aborted`:`success`,output:Q===void 0?void 0:{text:m(Q.content),commentary:Q.content.flatMap(e=>e.type===`text`&&e.phase===`commentary`?[e.text]:[]),reasoning:Q.content.flatMap(e=>e.type===`reasoning`?[e.text]:[]),toolCalls:$.length},...P.usage===void 0?{}:{usage:P.usage},...Z.kind===`error`||Z.kind===`aborted`?{error:{type:`ModelError`,message:Z.failure.message,code:Z.failure.code}}:{}}),($.length===0||C)&&await _({type:`step-end`,turn:y,step:b,trace:w}),{trace:w,...Q===void 0?{}:{message:Q},finish:Z,...P.usage===void 0?{}:{usage:P.usage},...V===void 0?{}:{report:V},...ve?{usageRequired:!0}:{},...ye?{usageUnavailable:!0}:{},calls:$,afterToolCallIds:E,timing:Ce,...q.dropped.length===0?{}:{droppedDuplicateCalls:q.dropped}}}function de(e,t){try{let n=JSON.parse(e);return t?.(n),!0}catch{return!1}}export{_ as modelRound};
1
+ import{createSpanId as e}from"../../../observation/context.js";import{MODEL_ERROR_CODES as t}from"../../../errors/model-error.js";import{BlockAssembler as n}from"../../../stream/assembler.js";import{normalizeToolPairing as r}from"../../history/normalize.js";import{positiveFinite as i,positiveSafeInteger as a}from"./config.js";import{messageOf as o,modelAbortedFinish as ee,modelFailureFinish as s,now as c,serializedBytes as te}from"./common.js";import{StreamAbortError as ne,closeIterator as re,nextWithAbort as ie}from"./cancellation.js";import{runOptionalHook as l}from"./hooks.js";import{classifyTextPhases as u,contentTiming as d,createAssistant as f,dropDuplicateToolCalls as p,invalidHostToolCall as ae,recentToolResultIds as oe,systemText as se,textOf as m}from"./content.js";import{validateStreamChunk as ce}from"./validation.js";import{accountingUsageStop as le}from"./usage-stop.js";function h(e){let t=e.replace(/\s+/gu,` `).trim();return t.length>600?`${t.slice(0,600)}…`:t}function g(e){let t=[],n=[];for(let r of e.content)r.type===`text`||r.type===`reasoning`?t.push(r.text):r.type===`tool-call`?n.push(`${r.name}(${h(r.arguments)})`):r.type===`tool-result`?t.push(m(r.content)):t.push(`[${r.type}]`);return{role:e.role,producer:e.source.kind,...t.length===0?{}:{text:h(t.join(` `))},...n.length===0?{}:{toolCalls:n}}}function ue(e){let t=e.messages??[],n=Math.max(0,t.length-8);return{messageCount:t.length,...t.at(-1)===void 0?{}:{lastMessageId:t.at(-1)?.id},...e.system===void 0?{}:{system:h(e.system)},...e.tools===void 0||e.tools.length===0?{}:{tools:e.tools.map(e=>e.name)},...e.toolChoice===void 0?{}:{toolChoice:e.toolChoice},...n===0?{}:{earlierMessagesOmitted:n},messages:t.slice(-8).map(g)}}async function _(h,g,_,fe,v,y,b,x){let S=x===`forced-final`,C=x===`final`||S,w={traceId:v.traceId,spanId:e(),parentSpanId:v.spanId},T=r(h.history.messages()),E=oe(h.history),pe=h.history.generation(),me=h.history.entries().length,D=()=>{let e=le(h.accounting);if(!(e===void 0&&!g.aborted))return{trace:w,finish:g.aborted?{kind:`aborted`,failure:{code:`ABORTED`,message:o(g.reason)}}:{kind:`stop`},calls:[],afterToolCallIds:E,timing:d(!1,E.length>0),...e?.kind===`error`?{usageRequired:!0}:{},...e?.kind===`usage-unavailable`?{usageUnavailable:!0}:{}}},he=D();if(he!==void 0)return he;let O=await l(h.hooks?.beforeStep,[{turn:y,step:b,messages:T,snapshot:h.history.snapshot(),signal:g,...h.logger===void 0?{}:{logger:h.logger},emit:fe}],h,g,`beforeStep`),ge=D();if(ge!==void 0)return ge;if(O?.kind===`reject`)return{trace:w,finish:{kind:`error`,failure:{message:O.reason,code:`STEP_REJECTED`}},calls:[],afterToolCallIds:E,timing:d(!1,E.length>0)};(h.history.generation()!==pe||h.history.entries().length!==me)&&(T=r(h.history.messages())),O?.prepend!==void 0&&(T=Object.freeze([...O.prepend,...T]));let k=se(h,S),A=[...h.tools?.schemas()??[],...h.nativeTools??[]],j=!C&&h.outputFormat?.type===`json_schema`?{type:`text`}:h.outputFormat,M={...h.config,messages:T,...k.length===0?{}:{system:k},...A.length===0?{}:{tools:A},...C&&A.length>0?{toolChoice:`none`}:h.toolChoice===void 0?{}:{toolChoice:h.toolChoice},...h.imagePolicy===void 0?{}:{imagePolicy:h.imagePolicy},...h.documentPolicy===void 0?{}:{documentPolicy:h.documentPolicy},...j===void 0?{}:{outputFormat:j}},_e={...M,signal:g};try{await l(h.hooks?.checkpoint,[{kind:`before-model-request`,request:_e,snapshot:h.history.snapshot(),signal:g,...h.logger===void 0?{}:{logger:h.logger}}],h,g,`checkpoint`)}catch(e){return{trace:w,finish:{kind:`error`,failure:{message:`history checkpoint failed: ${o(e)}`,code:`CHECKPOINT_FAILED`}},calls:[],afterToolCallIds:E,timing:d(!1,E.length>0)}}let N=D();if(N!==void 0)return N;await _({type:`span-start`,trace:w,at:c(),name:`chat ${h.config.model}`,kind:`chat`,attributes:{"gen_ai.operation.name":`chat`,"gen_ai.request.model":h.config.model,...h.config.reasoningEffort===void 0?{}:{"gen_ai.request.reasoning_effort":h.config.reasoningEffort},turn:y,step:b,forcedFinal:S,phase:x},input:ue(M)}),await _({type:`step-start`,turn:y,step:b,trace:w,...S?{forcedFinal:!0}:{}});let P=new n,F=new Set,I=i(h.modelTimeoutMs??6e5,`modelTimeoutMs`),L=a(h.maxModelRequestBytes??33554432,`maxModelRequestBytes`),R=a(h.maxModelResponseBytes??33554432,`maxModelResponseBytes`),z=a(h.maxModelStreamEvents??1e5,`maxModelStreamEvents`),B=i(h.teardownTimeoutMs??3e4,`teardownTimeoutMs`),V,ve=!1,ye=!1,H;try{H=te(M)}catch(e){H=-1,P.push(s(`model request is not serializable: ${o(e)}`,`INVALID_MODEL_REQUEST`))}if(H>L)P.push(s(`model request exceeds the ${L}-byte limit`,`MODEL_REQUEST_TOO_LARGE`));else if(H>=0){let e=new AbortController,t=AbortSignal.any([g,e.signal]),n=!1,r=setTimeout(()=>{n=!0,e.abort(Error(`model stream exceeded ${I}ms`))},I),i=h.registry.stream({...M,signal:t},h.accounting?.modelInvocation),a=i[Symbol.asyncIterator](),c=!1,l=0,u=0,d=!1;try{for(;;){let n=await ie(a.next(),t);if(n.done===!0){c=!0;break}let r=n.value;try{ce(r,z)}catch(t){P.push(s(`model adapter emitted an invalid stream chunk: ${o(t)}`,`INVALID_MODEL_STREAM`)),e.abort(Error(`invalid model stream chunk`));break}l++;try{u+=te(r)}catch(t){P.push(s(`model adapter emitted a non-serializable stream chunk: ${o(t)}`,`INVALID_MODEL_STREAM`)),e.abort(Error(`non-serializable model stream chunk`));break}if(l>z||u>R){let t=l>z?`${z}-event`:`${R}-byte`;P.push(s(`model response exceeds the ${t} limit`,`MODEL_RESPONSE_TOO_LARGE`)),e.abort(Error(`model response resource limit exceeded`));break}if(d){P.push(s(`model adapter emitted data after its terminal finish chunk`,`INVALID_MODEL_STREAM`)),e.abort(Error(`invalid model stream`));break}P.push(r),!((r.type===`text-delta`||r.type===`reasoning-delta`||r.type===`tool-call-delta`)&&F.has(r.index))&&(r.type===`block-end`&&F.add(r.index),r.type===`finish`&&(d=!0),r.type===`text-delta`?await _({type:`text-delta`,index:r.index,text:r.text,phase:x===`process`?`commentary`:r.phase??`unknown`,trace:w}):r.type===`reasoning-delta`?await _({type:`reasoning-delta`,index:r.index,text:r.text,trace:w}):r.type===`image-delta`?await _({type:`image-delta`,itemId:r.itemId,data:r.data,mediaType:r.mediaType,...r.partialIndex===void 0?{}:{partialIndex:r.partialIndex},trace:w}):r.type===`usage`?await _({type:`usage`,usage:r.usage,trace:w}):r.type===`usage-progress`&&await _({...r,trace:w}))}}catch(e){if(!(e instanceof ne))throw e;P.push(g.aborted?ee(o(g.reason??e)):n?s(`model stream exceeded ${I}ms`,`MODEL_TIMEOUT`):s(o(e.cause??e),`MODEL_STREAM_ABORTED`))}finally{clearTimeout(r),c||(e.abort(Error(`model stream closed before exhaustion`)),await re(a,B)||P.push(s(`model stream ignored cancellation for more than ${B}ms; the adapter operation may still be running`,`MODEL_TEARDOWN_TIMEOUT`)))}let f=await i.report,p=h.accounting===void 0?void 0:await h.accounting.recordModelCall(f,{...M,signal:g});V=p?.report??f,ve=p?.usageRequired??!1,ye=p?.usageUnavailable??!1}let U=P.finish,W=U.kind===`aborted`,G;try{G=U.kind===`aborted`?P.interruptedBlocks():P.blocks()}catch(e){U={kind:`error`,failure:{message:`model adapter emitted an invalid block sequence: ${o(e)}`,code:`INVALID_MODEL_STREAM`}},W=!0,G=P.interruptedBlocks()}let K=P.textBlocks().filter(({block:e})=>!W||e.text.trim()!==``),be=0,xe=u(G.map(e=>{if(e.type!==`text`)return e;let t=K[be++];return e.phase===void 0&&t?.beforeNativeCall?{...e,phase:`commentary`}:e}),x===`process`,P.hasToolCalls),q=p(xe,h.history),J=q.blocks,Se=C&&h.outputFormat?.type===`json_schema`&&U.kind===`stop`&&!de(m(J),h.validateOutput)?{message:`model returned invalid JSON or failed the structured output validator`,code:t.MALFORMED_RESPONSE}:void 0,Y=(C&&J.some(e=>e.type===`tool-call`)?{message:`model emitted a host tool call during the final output phase`,code:`INVALID_TOOL_CALL`}:void 0)??Se??ae(J,h.history),X=Y===void 0?J:J.filter(e=>e.type!==`tool-call`),Z=Y===void 0?U:{kind:`error`,failure:Y},Q=X.length===0&&(Z.kind===`error`||Z.kind===`aborted`)?void 0:f(h,X,W?void 0:P.replayState),$=Q?.content.filter(e=>e.type===`tool-call`).map(e=>({callId:e.id,toolName:e.name,rawArguments:e.arguments}))??[],Ce=d($.length>0,E.length>0);if(X.some(e=>e.type===`text`)){let e=K.map(({index:e})=>e),t=Z.kind===`error`||Z.kind===`aborted`||Z.kind===`max-tokens`,n=0;for(let r of X){if(r.type!==`text`)continue;let i=e[n++];i!==void 0&&await _({type:`text-end`,index:i,text:r.text,phase:r.phase??`final-answer`,trace:w,...t?{incomplete:!0}:{}})}}return await _({type:`span-end`,trace:w,at:c(),status:Z.kind===`error`?`error`:Z.kind===`aborted`?`aborted`:`success`,output:Q===void 0?void 0:{text:m(Q.content),commentary:Q.content.flatMap(e=>e.type===`text`&&e.phase===`commentary`?[e.text]:[]),reasoning:Q.content.flatMap(e=>e.type===`reasoning`?[e.text]:[]),toolCalls:$.length},...P.usage===void 0?{}:{usage:P.usage},...Z.kind===`error`||Z.kind===`aborted`?{error:{type:`ModelError`,message:Z.failure.message,code:Z.failure.code}}:{}}),($.length===0||C)&&await _({type:`step-end`,turn:y,step:b,trace:w}),{trace:w,...Q===void 0?{}:{message:Q},finish:Z,...P.usage===void 0?{}:{usage:P.usage},...V===void 0?{}:{report:V},...ve?{usageRequired:!0}:{},...ye?{usageUnavailable:!0}:{},calls:$,afterToolCallIds:E,timing:Ce,...q.dropped.length===0?{}:{droppedDuplicateCalls:q.dropped}}}function de(e,t){try{let n=JSON.parse(e);return t?.(n),!0}catch{return!1}}export{_ as modelRound};
2
2
  //# sourceMappingURL=model-round.js.map