@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":"port.js","names":[],"sources":["../../src/observation/port.ts"],"sourcesContent":["import { deepFreeze } from '../primitives/freeze.ts'\nimport { createSpanId, createTraceId, freezeCorrelation, isSpanId, isTraceId, traceparent, type CorrelationContext } from './context.ts'\nimport type { ObservationEvent, OperationStatus, SafeErrorRecord } from './event.ts'\n\nexport type DeliveryMode = 'operational' | 'reliable' | 'audit'\nexport type ObservationBoundary = 'none' | 'local-durable' | 'remote-acknowledged'\n\nexport interface CaptureReceipt {\n readonly eventId: string\n readonly status: 'accepted' | 'rejected' | 'disabled'\n readonly durable: boolean\n readonly boundary: ObservationBoundary\n readonly reason?: 'capacity' | 'closed' | 'processor-failed' | 'exporter-unavailable'\n}\n\nconst RECEIPT_STATUSES = new Set<CaptureReceipt['status']>(['accepted', 'rejected', 'disabled'])\nconst RECEIPT_BOUNDARIES = new Set<ObservationBoundary>(['none', 'local-durable', 'remote-acknowledged'])\nconst RECEIPT_REASONS = new Set<NonNullable<CaptureReceipt['reason']>>([\n 'capacity',\n 'closed',\n 'processor-failed',\n 'exporter-unavailable',\n])\n\n/** Validate an untrusted observer receipt before using it for delivery claims. */\nexport function validateCaptureReceipt(value: unknown, eventId: string): CaptureReceipt {\n if (typeof value !== 'object' || value === null) throw new TypeError('observation receipt must be an object')\n let receipt: Readonly<Record<string, unknown>>\n try {\n receipt = {\n eventId: Reflect.get(value, 'eventId'),\n status: Reflect.get(value, 'status'),\n durable: Reflect.get(value, 'durable'),\n boundary: Reflect.get(value, 'boundary'),\n reason: Reflect.get(value, 'reason'),\n }\n } catch {\n throw new TypeError('observation receipt properties could not be read')\n }\n if (receipt.eventId !== eventId) throw new TypeError('observation receipt eventId mismatch')\n if (!RECEIPT_STATUSES.has(receipt.status as CaptureReceipt['status'])) throw new TypeError('observation receipt status is invalid')\n if (typeof receipt.durable !== 'boolean') throw new TypeError('observation receipt durable flag is invalid')\n if (!RECEIPT_BOUNDARIES.has(receipt.boundary as ObservationBoundary)) throw new TypeError('observation receipt boundary is invalid')\n if (receipt.reason !== undefined && !RECEIPT_REASONS.has(receipt.reason as NonNullable<CaptureReceipt['reason']>)) {\n throw new TypeError('observation receipt reason is invalid')\n }\n const status = receipt.status as CaptureReceipt['status']\n const boundary = receipt.boundary as ObservationBoundary\n const durable = receipt.durable\n if ((boundary === 'none') === durable) throw new TypeError('observation receipt durable flag contradicts its boundary')\n if (status !== 'accepted' && (durable || boundary !== 'none')) {\n throw new TypeError('a rejected or disabled observation receipt cannot claim durability')\n }\n return Object.freeze({\n eventId,\n status,\n durable,\n boundary,\n ...receipt.reason === undefined ? {} : { reason: receipt.reason as NonNullable<CaptureReceipt['reason']> },\n })\n}\n\nexport type ObservationSpanName =\n | 'sdk.agent.run'\n | 'sdk.agent.turn'\n | 'sdk.model.call'\n | 'sdk.provider.attempt'\n | 'sdk.tool.call'\n | 'sdk.compaction'\n | 'sdk.hook.call'\n | 'sdk.user.input.wait'\n | 'sdk.skill.operation'\n | 'sdk.memory.operation'\n | 'sdk.credential.operation'\n | 'sdk.integration.request'\n\nexport interface OpenObservationSpanInput {\n readonly name: ObservationSpanName\n readonly runId: string\n readonly parent?: CorrelationContext\n readonly correlation?: Omit<Partial<CorrelationContext>, 'traceId' | 'spanId' | 'parentSpanId' | 'runId'>\n readonly startedAt: string\n readonly monotonicMs: number\n}\n\nexport interface ObservationSpan {\n readonly correlation: CorrelationContext\n readonly traceparent: string\n end(status: OperationStatus, endedAt: string, monotonicMs: number): void\n}\n\nexport interface ObservationPort {\n readonly mode: DeliveryMode\n openSpan(input: OpenObservationSpanInput): ObservationSpan\n capture(event: ObservationEvent): CaptureReceipt\n checkpoint?(event: ObservationEvent, signal?: AbortSignal): Promise<CaptureReceipt>\n}\n\nexport interface ObservationDeliverySummary {\n readonly mode: DeliveryMode\n readonly requiredBoundary: ObservationBoundary\n readonly reachedBoundary: ObservationBoundary\n readonly complete: boolean\n readonly acceptedCritical: number\n readonly rejectedCritical: number\n readonly pendingCritical: number\n readonly lastFailure?: SafeErrorRecord\n}\n\nexport function createCoreSpan(input: OpenObservationSpanInput): ObservationSpan {\n const correlation = freezeCorrelation({\n traceId: input.parent?.traceId ?? createTraceId(),\n spanId: createSpanId(),\n parentSpanId: input.parent?.spanId ?? null,\n runId: input.runId,\n ...input.correlation,\n })\n let ended = false\n return Object.freeze({\n correlation,\n traceparent: traceparent(correlation),\n end(_status: OperationStatus, _endedAt: string, _monotonicMs: number): void {\n if (ended) return\n ended = true\n },\n })\n}\n\ninterface ObservationSpanSnapshot extends ObservationSpan {\n readonly end: ObservationSpan['end']\n}\n\nfunction traceparentMatchesCorrelation(value: unknown, correlation: CorrelationContext): value is string {\n if (typeof value !== 'string') return false\n const match = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/.exec(value)\n return match?.[1] === correlation.traceId && match[2] === correlation.spanId\n}\n\nconst OPTIONAL_CORRELATION_KEYS = [\n 'conversationId',\n 'turnId',\n 'modelCallId',\n 'attemptId',\n 'toolCallId',\n 'providerRequestId',\n 'sessionId',\n] as const\n\n/** Copy an untrusted backend span so its getters or later mutations cannot affect events. */\nexport function snapshotObservationSpan(value: unknown): ObservationSpanSnapshot | undefined {\n try {\n if (typeof value !== 'object' || value === null) return undefined\n const correlationValue = Reflect.get(value, 'correlation')\n if (typeof correlationValue !== 'object' || correlationValue === null) return undefined\n const traceId = Reflect.get(correlationValue, 'traceId')\n const spanId = Reflect.get(correlationValue, 'spanId')\n const parentSpanId = Reflect.get(correlationValue, 'parentSpanId')\n const runId = Reflect.get(correlationValue, 'runId')\n if (!isTraceId(traceId) || !isSpanId(spanId)\n || (parentSpanId !== null && !isSpanId(parentSpanId))\n || typeof runId !== 'string' || runId.length === 0) return undefined\n const optional: Partial<Record<typeof OPTIONAL_CORRELATION_KEYS[number], string>> = {}\n for (const key of OPTIONAL_CORRELATION_KEYS) {\n const field = Reflect.get(correlationValue, key)\n if (field === undefined) continue\n if (typeof field !== 'string' || field.length === 0) return undefined\n optional[key] = field\n }\n const correlation = freezeCorrelation({ traceId, spanId, parentSpanId, runId, ...optional })\n const backendTraceparent = Reflect.get(value, 'traceparent')\n const end = Reflect.get(value, 'end')\n if (!traceparentMatchesCorrelation(backendTraceparent, correlation) || typeof end !== 'function') return undefined\n return Object.freeze({\n correlation,\n traceparent: backendTraceparent,\n end: (status: OperationStatus, endedAt: string, monotonicMs: number) => {\n Reflect.apply(end, value, [status, endedAt, monotonicMs])\n },\n })\n } catch {\n return undefined\n }\n}\n\nexport function validObservationSpan(value: unknown): value is ObservationSpan {\n return snapshotObservationSpan(value) !== undefined\n}\n\nexport function disabledDeliverySummary(): ObservationDeliverySummary {\n return deepFreeze({\n mode: 'operational',\n requiredBoundary: 'none',\n reachedBoundary: 'none',\n complete: true,\n acceptedCritical: 0,\n rejectedCritical: 0,\n pendingCritical: 0,\n })\n}\n\nexport const NOOP_OBSERVATION_PORT: ObservationPort = Object.freeze({\n mode: 'operational' as const,\n openSpan: createCoreSpan,\n capture(event: ObservationEvent): CaptureReceipt {\n return Object.freeze({ eventId: event.eventId, status: 'disabled', durable: false, boundary: 'none' })\n },\n checkpoint(event: ObservationEvent): Promise<CaptureReceipt> {\n return Promise.resolve(Object.freeze({ eventId: event.eventId, status: 'disabled', durable: false, boundary: 'none' }))\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"port.js","names":[],"sources":["../../src/observation/port.ts"],"sourcesContent":["import { deepFreeze } from '../primitives/freeze.ts'\nimport { createSpanId, createTraceId, freezeCorrelation, isSpanId, isTraceId, traceparent, type CorrelationContext } from './context.ts'\nimport type { ObservationEvent, OperationStatus, SafeErrorRecord } from './event.ts'\n\nexport type DeliveryMode = 'operational' | 'reliable' | 'audit'\nexport type ObservationBoundary = 'none' | 'local-durable' | 'remote-acknowledged'\n\nexport interface CaptureReceipt {\n readonly eventId: string\n readonly status: 'accepted' | 'rejected' | 'disabled'\n readonly durable: boolean\n readonly boundary: ObservationBoundary\n readonly reason?: 'capacity' | 'closed' | 'processor-failed' | 'exporter-unavailable'\n}\n\nconst RECEIPT_STATUSES = new Set<CaptureReceipt['status']>(['accepted', 'rejected', 'disabled'])\nconst RECEIPT_BOUNDARIES = new Set<ObservationBoundary>(['none', 'local-durable', 'remote-acknowledged'])\nconst RECEIPT_REASONS = new Set<NonNullable<CaptureReceipt['reason']>>([\n 'capacity',\n 'closed',\n 'processor-failed',\n 'exporter-unavailable',\n])\n\n/** Validate an untrusted observer receipt before using it for delivery claims. */\nexport function validateCaptureReceipt(value: unknown, eventId: string): CaptureReceipt {\n if (typeof value !== 'object' || value === null) throw new TypeError('observation receipt must be an object')\n let receipt: Readonly<Record<string, unknown>>\n try {\n receipt = {\n eventId: Reflect.get(value, 'eventId'),\n status: Reflect.get(value, 'status'),\n durable: Reflect.get(value, 'durable'),\n boundary: Reflect.get(value, 'boundary'),\n reason: Reflect.get(value, 'reason'),\n }\n } catch {\n throw new TypeError('observation receipt properties could not be read')\n }\n if (receipt.eventId !== eventId) throw new TypeError('observation receipt eventId mismatch')\n if (!RECEIPT_STATUSES.has(receipt.status as CaptureReceipt['status'])) throw new TypeError('observation receipt status is invalid')\n if (typeof receipt.durable !== 'boolean') throw new TypeError('observation receipt durable flag is invalid')\n if (!RECEIPT_BOUNDARIES.has(receipt.boundary as ObservationBoundary)) throw new TypeError('observation receipt boundary is invalid')\n if (receipt.reason !== undefined && !RECEIPT_REASONS.has(receipt.reason as NonNullable<CaptureReceipt['reason']>)) {\n throw new TypeError('observation receipt reason is invalid')\n }\n const status = receipt.status as CaptureReceipt['status']\n const boundary = receipt.boundary as ObservationBoundary\n const durable = receipt.durable\n if ((boundary === 'none') === durable) throw new TypeError('observation receipt durable flag contradicts its boundary')\n if (status !== 'accepted' && (durable || boundary !== 'none')) {\n throw new TypeError('a rejected or disabled observation receipt cannot claim durability')\n }\n return Object.freeze({\n eventId,\n status,\n durable,\n boundary,\n ...receipt.reason === undefined ? {} : { reason: receipt.reason as NonNullable<CaptureReceipt['reason']> },\n })\n}\n\nexport type ObservationSpanName =\n | 'sdk.agent.run'\n | 'sdk.agent.turn'\n | 'sdk.model.call'\n | 'sdk.embedding.call'\n | 'sdk.embedding.batch'\n | 'sdk.provider.attempt'\n | 'sdk.tool.call'\n | 'sdk.compaction'\n | 'sdk.hook.call'\n | 'sdk.user.input.wait'\n | 'sdk.skill.operation'\n | 'sdk.memory.operation'\n | 'sdk.credential.operation'\n | 'sdk.integration.request'\n\nexport interface OpenObservationSpanInput {\n readonly name: ObservationSpanName\n readonly runId: string\n readonly parent?: CorrelationContext\n readonly correlation?: Omit<Partial<CorrelationContext>, 'traceId' | 'spanId' | 'parentSpanId' | 'runId'>\n readonly startedAt: string\n readonly monotonicMs: number\n}\n\nexport interface ObservationSpan {\n readonly correlation: CorrelationContext\n readonly traceparent: string\n end(status: OperationStatus, endedAt: string, monotonicMs: number): void\n}\n\nexport interface ObservationPort {\n readonly mode: DeliveryMode\n openSpan(input: OpenObservationSpanInput): ObservationSpan\n capture(event: ObservationEvent): CaptureReceipt\n checkpoint?(event: ObservationEvent, signal?: AbortSignal): Promise<CaptureReceipt>\n}\n\nexport interface ObservationDeliverySummary {\n readonly mode: DeliveryMode\n readonly requiredBoundary: ObservationBoundary\n readonly reachedBoundary: ObservationBoundary\n readonly complete: boolean\n readonly acceptedCritical: number\n readonly rejectedCritical: number\n readonly pendingCritical: number\n readonly lastFailure?: SafeErrorRecord\n}\n\nexport function createCoreSpan(input: OpenObservationSpanInput): ObservationSpan {\n const correlation = freezeCorrelation({\n traceId: input.parent?.traceId ?? createTraceId(),\n spanId: createSpanId(),\n parentSpanId: input.parent?.spanId ?? null,\n runId: input.runId,\n ...input.correlation,\n })\n let ended = false\n return Object.freeze({\n correlation,\n traceparent: traceparent(correlation),\n end(_status: OperationStatus, _endedAt: string, _monotonicMs: number): void {\n if (ended) return\n ended = true\n },\n })\n}\n\ninterface ObservationSpanSnapshot extends ObservationSpan {\n readonly end: ObservationSpan['end']\n}\n\nfunction traceparentMatchesCorrelation(value: unknown, correlation: CorrelationContext): value is string {\n if (typeof value !== 'string') return false\n const match = /^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/.exec(value)\n return match?.[1] === correlation.traceId && match[2] === correlation.spanId\n}\n\nconst OPTIONAL_CORRELATION_KEYS = [\n 'conversationId',\n 'turnId',\n 'modelCallId',\n 'attemptId',\n 'toolCallId',\n 'providerRequestId',\n 'sessionId',\n] as const\n\n/** Copy an untrusted backend span so its getters or later mutations cannot affect events. */\nexport function snapshotObservationSpan(value: unknown): ObservationSpanSnapshot | undefined {\n try {\n if (typeof value !== 'object' || value === null) return undefined\n const correlationValue = Reflect.get(value, 'correlation')\n if (typeof correlationValue !== 'object' || correlationValue === null) return undefined\n const traceId = Reflect.get(correlationValue, 'traceId')\n const spanId = Reflect.get(correlationValue, 'spanId')\n const parentSpanId = Reflect.get(correlationValue, 'parentSpanId')\n const runId = Reflect.get(correlationValue, 'runId')\n if (!isTraceId(traceId) || !isSpanId(spanId)\n || (parentSpanId !== null && !isSpanId(parentSpanId))\n || typeof runId !== 'string' || runId.length === 0) return undefined\n const optional: Partial<Record<typeof OPTIONAL_CORRELATION_KEYS[number], string>> = {}\n for (const key of OPTIONAL_CORRELATION_KEYS) {\n const field = Reflect.get(correlationValue, key)\n if (field === undefined) continue\n if (typeof field !== 'string' || field.length === 0) return undefined\n optional[key] = field\n }\n const correlation = freezeCorrelation({ traceId, spanId, parentSpanId, runId, ...optional })\n const backendTraceparent = Reflect.get(value, 'traceparent')\n const end = Reflect.get(value, 'end')\n if (!traceparentMatchesCorrelation(backendTraceparent, correlation) || typeof end !== 'function') return undefined\n return Object.freeze({\n correlation,\n traceparent: backendTraceparent,\n end: (status: OperationStatus, endedAt: string, monotonicMs: number) => {\n Reflect.apply(end, value, [status, endedAt, monotonicMs])\n },\n })\n } catch {\n return undefined\n }\n}\n\nexport function validObservationSpan(value: unknown): value is ObservationSpan {\n return snapshotObservationSpan(value) !== undefined\n}\n\nexport function disabledDeliverySummary(): ObservationDeliverySummary {\n return deepFreeze({\n mode: 'operational',\n requiredBoundary: 'none',\n reachedBoundary: 'none',\n complete: true,\n acceptedCritical: 0,\n rejectedCritical: 0,\n pendingCritical: 0,\n })\n}\n\nexport const NOOP_OBSERVATION_PORT: ObservationPort = Object.freeze({\n mode: 'operational' as const,\n openSpan: createCoreSpan,\n capture(event: ObservationEvent): CaptureReceipt {\n return Object.freeze({ eventId: event.eventId, status: 'disabled', durable: false, boundary: 'none' })\n },\n checkpoint(event: ObservationEvent): Promise<CaptureReceipt> {\n return Promise.resolve(Object.freeze({ eventId: event.eventId, status: 'disabled', durable: false, boundary: 'none' }))\n },\n})\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{deepFreeze as e}from"../primitives/freeze.js";import{isSpanId as t,isTraceId as n}from"./context.js";import{safeErrorRecord as r}from"./event.js";const i=2048,a=65536,o=`[REDACTED]`,s=new Set([`sdk.agent.run`,`sdk.agent.turn`,`sdk.model.call`,`sdk.provider.attempt`,`sdk.provider.retry.scheduled`,`sdk.tool.call`,`sdk.compaction`,`sdk.hook.call`,`sdk.user.input.wait`,`sdk.skill.operation`,`sdk.memory.operation`,`sdk.credential.operation`,`sdk.integration.request`,`sdk.observer.failure`,`sdk.exporter.state`,`sdk.log`]),c=new Set([`start`,`end`,`point`]),l=new Set([`critical`,`normal`,`verbose`]),u=new Set([`answer`,`arguments`,`body`,`completion`,`content`,`filecontent`,`image`,`input`,`messages`,`output`,`prompt`,`reasoning`,`requestbody`,`responsebody`,`result`,`text`,`toolarguments`,`toolresult`]),d=new Set([`accept`,`content-type`,`request-id`,`traceparent`,`user-agent`]),f=[`conversationId`,`turnId`,`modelCallId`,`attemptId`,`toolCallId`,`providerRequestId`,`sessionId`];function p(e,t){try{return Reflect.get(e,t)}catch{return}}function m(e){return e.toLowerCase().replace(/[^a-z0-9]/g,``)}function h(e){let t=m(e);return t===`authorization`||t===`proxyauthorization`||t===`cookie`||t===`setcookie`||t.includes(`apikey`)||t.includes(`accesstoken`)||t.includes(`refreshtoken`)||t.includes(`idtoken`)||t.includes(`clientsecret`)||t.includes(`password`)||t.includes(`sessionsecret`)}function g(e){return typeof e==`string`?{kind:`string`,length:e.length}:Array.isArray(e)?{kind:`array`,length:e.length}:typeof e==`object`&&e?{kind:`object`}:{kind:typeof e}}function _(e,t,n){let r=e;for(let e of n)try{r=e.redact(r,t)}catch{return`[REDACTION_FAILED]`}return r}function v(e){return e.replace(/\b(Bearer)\s+[A-Za-z0-9._~+/=-]+/gi,`$1 [REDACTED]`).replace(/\b(authorization|proxy[-_]?authorization|api[-_]?key|access[-_]?token|refresh[-_]?token|id[-_]?token|client[-_]?secret|password|session[-_]?secret)\s*[:=]\s*[^\s,;]+/gi,`$1=[REDACTED]`)}function y(t,n){let r={options:n,seen:new WeakSet,truncated:!1},i=b(t,[`data`],0,r);if(i===null||Array.isArray(i)||typeof i!=`object`)throw TypeError(`observation data must be an object`);let a={...i};return r.truncated&&(a[`observability.truncated`]=!0),e(a)}function b(e,t,n,a){if(e===null)return null;if(typeof e==`string`){let t=v(e);return t.length>i&&(a.truncated=!0),t.slice(0,i)}if(typeof e==`number`)return Number.isFinite(e)?e:String(e);if(typeof e==`boolean`)return e;if(typeof e==`bigint`||typeof e==`symbol`||typeof e==`function`||e===void 0)return a.truncated=!0,`[${typeof e}]`;if(e instanceof Error)return b(r(e,a.options.includeErrorStacks),t,n,a);if(n>=8)return a.truncated=!0,`[MaxDepth]`;if(a.seen.has(e))return a.truncated=!0,`[Circular]`;a.seen.add(e);try{if(Array.isArray(e)){e.length>100&&(a.truncated=!0);let r=[];for(let i=0;i<Math.min(e.length,100);i++)r.push(b(p(e,i),[...t,String(i)],n+1,a));return r}let r=Object.create(null),i;try{i=Object.keys(e)}catch{return a.truncated=!0,`[Uninspectable]`}let s=m(t.at(-1)??``)===`headers`;for(let c of i){if(Object.keys(r).length>=64){a.truncated=!0;break}let i=c.slice(0,128);if(i!==c&&(a.truncated=!0),s&&!d.has(c.toLowerCase())){r[i]=o;continue}let l=p(e,c);if(h(c)){r[i]=o;continue}let f=u.has(m(c));if(!(f&&a.options.content===`none`)){if(f&&a.options.content===`metadata`){r[i]=g(l);continue}if(f&&a.options.content===`redacted`&&typeof l==`string`){r[i]=b(_(l,[...t,c],a.options.redactors),[...t,c],n+1,a);continue}r[i]=b(l,[...t,c],n+1,a)}}return r}finally{a.seen.delete(e)}}function x(e,t){if(typeof e!=`string`||e.length===0)throw TypeError(`observation ${t} is invalid`);return e.slice(0,i)}function S(e){return new TextEncoder().encode(JSON.stringify(e)).byteLength}function C(r,a){if(typeof r!=`object`||!r)throw TypeError(`observation event must be an object`);if(p(r,`schemaVersion`)!==1)throw TypeError(`observation schemaVersion is invalid`);let o=p(r,`name`),u=p(r,`phase`),d=p(r,`priority`);if(!s.has(o))throw TypeError(`observation name is invalid`);if(!c.has(u))throw TypeError(`observation phase is invalid`);if(!l.has(d))throw TypeError(`observation priority is invalid`);let m=p(r,`sequence`),h=p(r,`monotonicMs`);if(!Number.isSafeInteger(m)||m<1)throw TypeError(`observation sequence is invalid`);if(typeof h!=`number`||!Number.isFinite(h)||h<0)throw TypeError(`observation monotonicMs is invalid`);let g=p(r,`resource`),_=p(r,`correlation`);if(typeof g!=`object`||!g||p(g,`sdkName`)!==`ai-agent-sdk`)throw TypeError(`observation resource is invalid`);if(typeof _!=`object`||!_||!n(p(_,`traceId`))||!t(p(_,`spanId`)))throw TypeError(`observation correlation is invalid`);let v=p(_,`parentSpanId`);if(v!==null&&!t(v))throw TypeError(`observation parentSpanId is invalid`);if(typeof p(_,`runId`)!=`string`||String(p(_,`runId`)).length===0)throw TypeError(`observation runId is invalid`);for(let e of f){let t=p(_,e);if(t!==void 0&&(typeof t!=`string`||t.length===0))throw TypeError(`observation ${e} is invalid`)}let y=x(p(r,`occurredAt`),`occurredAt`);if(Number.isNaN(Date.parse(y))||new Date(y).toISOString()!==y)throw TypeError(`observation occurredAt must be UTC ISO 8601`);let C=x(p(r,`eventId`),`eventId`);if(!/^[0-9a-f]{32}$/.test(C)||/^0+$/.test(C))throw TypeError(`observation eventId is invalid`);let w=x(p(g,`sdkVersion`),`resource.sdkVersion`),T=p(g,`runtime`);if(![`browser`,`edge`,`node`,`unknown`].includes(String(T)))throw TypeError(`observation resource runtime is invalid`);let E={options:a,seen:new WeakSet,truncated:!1},D=b(p(r,`data`),[`data`],0,E);if(D===null||Array.isArray(D)||typeof D!=`object`)throw TypeError(`observation data must be an object`);let O={...D};E.truncated&&(O[`observability.truncated`]=!0);let k={schemaVersion:1,eventId:C,sequence:m,name:o,phase:u,occurredAt:y,monotonicMs:h,priority:d,resource:{sdkName:`ai-agent-sdk`,sdkVersion:w,...typeof p(g,`serviceName`)==`string`?{serviceName:String(p(g,`serviceName`)).slice(0,i)}:{},...typeof p(g,`serviceVersion`)==`string`?{serviceVersion:String(p(g,`serviceVersion`)).slice(0,i)}:{},runtime:T},correlation:b(_,[`correlation`],0,E),data:O};if(S(k)>65536){let e=Object.keys(O);for(;e.length>0&&S(k)>65536;){let t=e.pop();t!==void 0&&t!==`observability.truncated`&&delete O[t]}O[`observability.truncated`]=!0}if(S(k)>65536)throw RangeError(`observation event exceeds the 64 KiB hard limit`);return e(k)}function w(e){return S(e)}export{a as MAX_EVENT_BYTES,h as isSecretKey,v as redactInlineSecrets,y as sanitizeObservationData,C as sanitizeObservationEvent,w as serializedEventBytes};
1
+ import{deepFreeze as e}from"../primitives/freeze.js";import{isSpanId as t,isTraceId as n}from"./context.js";import{safeErrorRecord as r}from"./event.js";const i=2048,a=65536,o=`[REDACTED]`,s=new Set([`sdk.agent.run`,`sdk.agent.turn`,`sdk.model.call`,`sdk.provider.attempt`,`sdk.embedding.call`,`sdk.embedding.batch`,`sdk.provider.retry.scheduled`,`sdk.tool.call`,`sdk.compaction`,`sdk.hook.call`,`sdk.user.input.wait`,`sdk.skill.operation`,`sdk.memory.operation`,`sdk.credential.operation`,`sdk.integration.request`,`sdk.observer.failure`,`sdk.exporter.state`,`sdk.log`]),c=new Set([`start`,`end`,`point`]),l=new Set([`critical`,`normal`,`verbose`]),u=new Set([`answer`,`arguments`,`body`,`completion`,`content`,`document`,`filecontent`,`filedata`,`image`,`input`,`messages`,`output`,`prompt`,`reasoning`,`requestbody`,`responsebody`,`result`,`text`,`toolarguments`,`toolresult`]),d=new Set([`accept`,`content-type`,`request-id`,`traceparent`,`user-agent`]),f=[`conversationId`,`turnId`,`modelCallId`,`attemptId`,`toolCallId`,`providerRequestId`,`sessionId`];function p(e,t){try{return Reflect.get(e,t)}catch{return}}function m(e){return e.toLowerCase().replace(/[^a-z0-9]/g,``)}function h(e){let t=m(e);return t===`authorization`||t===`proxyauthorization`||t===`cookie`||t===`setcookie`||t.includes(`apikey`)||t.includes(`accesstoken`)||t.includes(`refreshtoken`)||t.includes(`idtoken`)||t.includes(`clientsecret`)||t.includes(`password`)||t.includes(`sessionsecret`)}function g(e){return typeof e==`string`?{kind:`string`,length:e.length}:Array.isArray(e)?{kind:`array`,length:e.length}:typeof e==`object`&&e?{kind:`object`}:{kind:typeof e}}function _(e,t,n){let r=e;for(let e of n)try{r=e.redact(r,t)}catch{return`[REDACTION_FAILED]`}return r}function v(e){return e.replace(/\b(Bearer)\s+[A-Za-z0-9._~+/=-]+/gi,`$1 [REDACTED]`).replace(/\b(authorization|proxy[-_]?authorization|api[-_]?key|access[-_]?token|refresh[-_]?token|id[-_]?token|client[-_]?secret|password|session[-_]?secret)\s*[:=]\s*[^\s,;]+/gi,`$1=[REDACTED]`)}function y(t,n){let r={options:n,seen:new WeakSet,truncated:!1},i=b(t,[`data`],0,r);if(i===null||Array.isArray(i)||typeof i!=`object`)throw TypeError(`observation data must be an object`);let a={...i};return r.truncated&&(a[`observability.truncated`]=!0),e(a)}function b(e,t,n,a){if(e===null)return null;if(typeof e==`string`){let t=v(e);return t.length>i&&(a.truncated=!0),t.slice(0,i)}if(typeof e==`number`)return Number.isFinite(e)?e:String(e);if(typeof e==`boolean`)return e;if(typeof e==`bigint`||typeof e==`symbol`||typeof e==`function`||e===void 0)return a.truncated=!0,`[${typeof e}]`;if(e instanceof Error)return b(r(e,a.options.includeErrorStacks),t,n,a);if(n>=8)return a.truncated=!0,`[MaxDepth]`;if(a.seen.has(e))return a.truncated=!0,`[Circular]`;a.seen.add(e);try{if(Array.isArray(e)){e.length>100&&(a.truncated=!0);let r=[];for(let i=0;i<Math.min(e.length,100);i++)r.push(b(p(e,i),[...t,String(i)],n+1,a));return r}let r=Object.create(null),i;try{i=Object.keys(e)}catch{return a.truncated=!0,`[Uninspectable]`}let s=m(t.at(-1)??``)===`headers`;for(let c of i){if(Object.keys(r).length>=64){a.truncated=!0;break}let i=c.slice(0,128);if(i!==c&&(a.truncated=!0),s&&!d.has(c.toLowerCase())){r[i]=o;continue}let l=p(e,c);if(h(c)){r[i]=o;continue}let f=u.has(m(c));if(!(f&&a.options.content===`none`)){if(f&&a.options.content===`metadata`){r[i]=g(l);continue}if(f&&a.options.content===`redacted`&&typeof l==`string`){r[i]=b(_(l,[...t,c],a.options.redactors),[...t,c],n+1,a);continue}r[i]=b(l,[...t,c],n+1,a)}}return r}finally{a.seen.delete(e)}}function x(e,t){if(typeof e!=`string`||e.length===0)throw TypeError(`observation ${t} is invalid`);return e.slice(0,i)}function S(e){return new TextEncoder().encode(JSON.stringify(e)).byteLength}function C(r,a){if(typeof r!=`object`||!r)throw TypeError(`observation event must be an object`);if(p(r,`schemaVersion`)!==1)throw TypeError(`observation schemaVersion is invalid`);let o=p(r,`name`),u=p(r,`phase`),d=p(r,`priority`);if(!s.has(o))throw TypeError(`observation name is invalid`);if(!c.has(u))throw TypeError(`observation phase is invalid`);if(!l.has(d))throw TypeError(`observation priority is invalid`);let m=p(r,`sequence`),h=p(r,`monotonicMs`);if(!Number.isSafeInteger(m)||m<1)throw TypeError(`observation sequence is invalid`);if(typeof h!=`number`||!Number.isFinite(h)||h<0)throw TypeError(`observation monotonicMs is invalid`);let g=p(r,`resource`),_=p(r,`correlation`);if(typeof g!=`object`||!g||p(g,`sdkName`)!==`ai-agent-sdk`)throw TypeError(`observation resource is invalid`);if(typeof _!=`object`||!_||!n(p(_,`traceId`))||!t(p(_,`spanId`)))throw TypeError(`observation correlation is invalid`);let v=p(_,`parentSpanId`);if(v!==null&&!t(v))throw TypeError(`observation parentSpanId is invalid`);if(typeof p(_,`runId`)!=`string`||String(p(_,`runId`)).length===0)throw TypeError(`observation runId is invalid`);for(let e of f){let t=p(_,e);if(t!==void 0&&(typeof t!=`string`||t.length===0))throw TypeError(`observation ${e} is invalid`)}let y=x(p(r,`occurredAt`),`occurredAt`);if(Number.isNaN(Date.parse(y))||new Date(y).toISOString()!==y)throw TypeError(`observation occurredAt must be UTC ISO 8601`);let C=x(p(r,`eventId`),`eventId`);if(!/^[0-9a-f]{32}$/.test(C)||/^0+$/.test(C))throw TypeError(`observation eventId is invalid`);let w=x(p(g,`sdkVersion`),`resource.sdkVersion`),T=p(g,`runtime`);if(![`browser`,`edge`,`node`,`unknown`].includes(String(T)))throw TypeError(`observation resource runtime is invalid`);let E={options:a,seen:new WeakSet,truncated:!1},D=b(p(r,`data`),[`data`],0,E);if(D===null||Array.isArray(D)||typeof D!=`object`)throw TypeError(`observation data must be an object`);let O={...D};E.truncated&&(O[`observability.truncated`]=!0);let k={schemaVersion:1,eventId:C,sequence:m,name:o,phase:u,occurredAt:y,monotonicMs:h,priority:d,resource:{sdkName:`ai-agent-sdk`,sdkVersion:w,...typeof p(g,`serviceName`)==`string`?{serviceName:String(p(g,`serviceName`)).slice(0,i)}:{},...typeof p(g,`serviceVersion`)==`string`?{serviceVersion:String(p(g,`serviceVersion`)).slice(0,i)}:{},runtime:T},correlation:b(_,[`correlation`],0,E),data:O};if(S(k)>65536){let e=Object.keys(O);for(;e.length>0&&S(k)>65536;){let t=e.pop();t!==void 0&&t!==`observability.truncated`&&delete O[t]}O[`observability.truncated`]=!0}if(S(k)>65536)throw RangeError(`observation event exceeds the 64 KiB hard limit`);return e(k)}function w(e){return S(e)}export{a as MAX_EVENT_BYTES,h as isSecretKey,v as redactInlineSecrets,y as sanitizeObservationData,C as sanitizeObservationEvent,w as serializedEventBytes};
2
2
  //# sourceMappingURL=privacy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"privacy.js","names":[],"sources":["../../src/observation/privacy.ts"],"sourcesContent":["import {\n deepFreeze,\n type JsonObject,\n type JsonValue,\n} from '../primitives/index.ts'\nimport {\n isSpanId,\n isTraceId,\n safeErrorRecord,\n type ObservationEvent,\n type ObservationEventName,\n type ObservationPhase,\n type ObservationPriority,\n} from '../observation/index.ts'\nimport type { ContentRedactor, ObservationContentPolicy } from './telemetry-types.ts'\n\nconst MAX_TOP_LEVEL_FIELDS = 64\nconst MAX_KEY_LENGTH = 128\nconst MAX_STRING_LENGTH = 2_048\nconst MAX_ARRAY_LENGTH = 100\nconst MAX_DEPTH = 8\nexport const MAX_EVENT_BYTES = 64 * 1024\nconst REDACTED = '[REDACTED]'\n\nconst EVENT_NAMES = new Set<ObservationEventName>([\n 'sdk.agent.run', 'sdk.agent.turn', 'sdk.model.call', 'sdk.provider.attempt',\n 'sdk.provider.retry.scheduled', 'sdk.tool.call', 'sdk.compaction', 'sdk.hook.call',\n 'sdk.user.input.wait', 'sdk.skill.operation', 'sdk.memory.operation',\n 'sdk.credential.operation', 'sdk.integration.request', 'sdk.observer.failure',\n 'sdk.exporter.state', 'sdk.log',\n])\nconst PHASES = new Set<ObservationPhase>(['start', 'end', 'point'])\nconst PRIORITIES = new Set<ObservationPriority>(['critical', 'normal', 'verbose'])\nconst CONTENT_KEYS = new Set([\n 'answer', 'arguments', 'body', 'completion', 'content', 'filecontent', 'image',\n 'input', 'messages', 'output', 'prompt', 'reasoning', 'requestbody', 'responsebody',\n 'result', 'text', 'toolarguments', 'toolresult',\n])\nconst SAFE_HEADER_NAMES = new Set(['accept', 'content-type', 'request-id', 'traceparent', 'user-agent'])\nconst OPTIONAL_CORRELATION_KEYS = [\n 'conversationId', 'turnId', 'modelCallId', 'attemptId', 'toolCallId',\n 'providerRequestId', 'sessionId',\n] as const\n\ninterface PrivacyOptions {\n readonly content: ObservationContentPolicy\n readonly redactors: readonly ContentRedactor[]\n readonly includeErrorStacks: boolean\n}\n\nfunction safeRead(source: unknown, key: PropertyKey): unknown {\n try { return Reflect.get(source as object, key) } catch { return undefined }\n}\n\nfunction normalizedKey(key: string): string {\n return key.toLowerCase().replace(/[^a-z0-9]/g, '')\n}\n\nexport function isSecretKey(key: string): boolean {\n const normalized = normalizedKey(key)\n return normalized === 'authorization' || normalized === 'proxyauthorization'\n || normalized === 'cookie' || normalized === 'setcookie'\n || normalized.includes('apikey') || normalized.includes('accesstoken')\n || normalized.includes('refreshtoken') || normalized.includes('idtoken')\n || normalized.includes('clientsecret') || normalized.includes('password')\n || normalized.includes('sessionsecret')\n}\n\nfunction contentMetadata(value: unknown): JsonObject {\n if (typeof value === 'string') return { kind: 'string', length: value.length }\n if (Array.isArray(value)) return { kind: 'array', length: value.length }\n if (value !== null && typeof value === 'object') return { kind: 'object' }\n return { kind: typeof value }\n}\n\nfunction redactContent(value: string, path: readonly string[], redactors: readonly ContentRedactor[]): string {\n let current = value\n for (const redactor of redactors) {\n try { current = redactor.redact(current, path) } catch { return '[REDACTION_FAILED]' }\n }\n return current\n}\n\nexport function redactInlineSecrets(value: string): string {\n return value\n .replace(/\\b(Bearer)\\s+[A-Za-z0-9._~+/=-]+/gi, '$1 [REDACTED]')\n .replace(\n /\\b(authorization|proxy[-_]?authorization|api[-_]?key|access[-_]?token|refresh[-_]?token|id[-_]?token|client[-_]?secret|password|session[-_]?secret)\\s*[:=]\\s*[^\\s,;]+/gi,\n '$1=[REDACTED]',\n )\n}\n\ninterface CloneState {\n readonly options: PrivacyOptions\n readonly seen: WeakSet<object>\n truncated: boolean\n}\n\n/** Internal composition helper: apply the same recursive content/secret policy before retaining logger child fields. */\nexport function sanitizeObservationData(value: unknown, options: PrivacyOptions): JsonObject {\n const state: CloneState = { options, seen: new WeakSet(), truncated: false }\n const cloned = cloneValue(value, ['data'], 0, state)\n if (cloned === null || Array.isArray(cloned) || typeof cloned !== 'object') throw new TypeError('observation data must be an object')\n const data: Record<string, JsonValue> = { ...(cloned as Record<string, JsonValue>) }\n if (state.truncated) data['observability.truncated'] = true\n return deepFreeze(data)\n}\n\nfunction cloneValue(value: unknown, path: readonly string[], depth: number, state: CloneState): JsonValue {\n if (value === null) return null\n if (typeof value === 'string') {\n const redacted = redactInlineSecrets(value)\n if (redacted.length > MAX_STRING_LENGTH) state.truncated = true\n return redacted.slice(0, MAX_STRING_LENGTH)\n }\n if (typeof value === 'number') return Number.isFinite(value) ? value : String(value)\n if (typeof value === 'boolean') return value\n if (typeof value === 'bigint' || typeof value === 'symbol' || typeof value === 'function' || value === undefined) {\n state.truncated = true\n return `[${typeof value}]`\n }\n if (value instanceof Error) return cloneValue(\n safeErrorRecord(value, state.options.includeErrorStacks), path, depth, state,\n )\n if (depth >= MAX_DEPTH) { state.truncated = true; return '[MaxDepth]' }\n if (state.seen.has(value)) { state.truncated = true; return '[Circular]' }\n state.seen.add(value)\n try {\n if (Array.isArray(value)) {\n if (value.length > MAX_ARRAY_LENGTH) state.truncated = true\n const output: JsonValue[] = []\n for (let index = 0; index < Math.min(value.length, MAX_ARRAY_LENGTH); index++) {\n output.push(cloneValue(safeRead(value, index), [...path, String(index)], depth + 1, state))\n }\n return output\n }\n const output: Record<string, JsonValue> = Object.create(null) as Record<string, JsonValue>\n let keys: string[]\n try { keys = Object.keys(value) } catch { state.truncated = true; return '[Uninspectable]' }\n const headers = normalizedKey(path.at(-1) ?? '') === 'headers'\n for (const originalKey of keys) {\n if (Object.keys(output).length >= MAX_TOP_LEVEL_FIELDS) { state.truncated = true; break }\n const key = originalKey.slice(0, MAX_KEY_LENGTH)\n if (key !== originalKey) state.truncated = true\n if (headers && !SAFE_HEADER_NAMES.has(originalKey.toLowerCase())) {\n output[key] = REDACTED\n continue\n }\n const child = safeRead(value, originalKey)\n if (isSecretKey(originalKey)) {\n output[key] = REDACTED\n continue\n }\n const contentKey = CONTENT_KEYS.has(normalizedKey(originalKey))\n if (contentKey && state.options.content === 'none') continue\n if (contentKey && state.options.content === 'metadata') {\n output[key] = contentMetadata(child)\n continue\n }\n if (contentKey && state.options.content === 'redacted' && typeof child === 'string') {\n output[key] = cloneValue(\n redactContent(child, [...path, originalKey], state.options.redactors),\n [...path, originalKey], depth + 1, state,\n )\n continue\n }\n output[key] = cloneValue(child, [...path, originalKey], depth + 1, state)\n }\n return output\n } finally {\n state.seen.delete(value)\n }\n}\n\nfunction requiredString(value: unknown, field: string): string {\n if (typeof value !== 'string' || value.length === 0) throw new TypeError(`observation ${field} is invalid`)\n return value.slice(0, MAX_STRING_LENGTH)\n}\n\nfunction eventBytes(event: ObservationEvent): number {\n return new TextEncoder().encode(JSON.stringify(event)).byteLength\n}\n\n/** Validate, privacy-process, bound, and deeply freeze one untrusted event. */\nexport function sanitizeObservationEvent(event: unknown, options: PrivacyOptions): ObservationEvent {\n if (typeof event !== 'object' || event === null) throw new TypeError('observation event must be an object')\n if (safeRead(event, 'schemaVersion') !== 1) throw new TypeError('observation schemaVersion is invalid')\n const name = safeRead(event, 'name')\n const phase = safeRead(event, 'phase')\n const priority = safeRead(event, 'priority')\n if (!EVENT_NAMES.has(name as ObservationEventName)) throw new TypeError('observation name is invalid')\n if (!PHASES.has(phase as ObservationPhase)) throw new TypeError('observation phase is invalid')\n if (!PRIORITIES.has(priority as ObservationPriority)) throw new TypeError('observation priority is invalid')\n const sequence = safeRead(event, 'sequence')\n const monotonicMs = safeRead(event, 'monotonicMs')\n if (!Number.isSafeInteger(sequence) || (sequence as number) < 1) throw new TypeError('observation sequence is invalid')\n if (typeof monotonicMs !== 'number' || !Number.isFinite(monotonicMs) || monotonicMs < 0) {\n throw new TypeError('observation monotonicMs is invalid')\n }\n const resource = safeRead(event, 'resource')\n const correlation = safeRead(event, 'correlation')\n if (typeof resource !== 'object' || resource === null || safeRead(resource, 'sdkName') !== 'ai-agent-sdk') {\n throw new TypeError('observation resource is invalid')\n }\n if (typeof correlation !== 'object' || correlation === null\n || !isTraceId(safeRead(correlation, 'traceId')) || !isSpanId(safeRead(correlation, 'spanId'))) {\n throw new TypeError('observation correlation is invalid')\n }\n const parentSpanId = safeRead(correlation, 'parentSpanId')\n if (parentSpanId !== null && !isSpanId(parentSpanId)) throw new TypeError('observation parentSpanId is invalid')\n if (typeof safeRead(correlation, 'runId') !== 'string' || String(safeRead(correlation, 'runId')).length === 0) {\n throw new TypeError('observation runId is invalid')\n }\n for (const key of OPTIONAL_CORRELATION_KEYS) {\n const value = safeRead(correlation, key)\n if (value !== undefined && (typeof value !== 'string' || value.length === 0)) {\n throw new TypeError(`observation ${key} is invalid`)\n }\n }\n const occurredAt = requiredString(safeRead(event, 'occurredAt'), 'occurredAt')\n if (Number.isNaN(Date.parse(occurredAt)) || new Date(occurredAt).toISOString() !== occurredAt) {\n throw new TypeError('observation occurredAt must be UTC ISO 8601')\n }\n const eventId = requiredString(safeRead(event, 'eventId'), 'eventId')\n if (!/^[0-9a-f]{32}$/.test(eventId) || /^0+$/.test(eventId)) throw new TypeError('observation eventId is invalid')\n const sdkVersion = requiredString(safeRead(resource, 'sdkVersion'), 'resource.sdkVersion')\n const runtime = safeRead(resource, 'runtime')\n if (!['browser', 'edge', 'node', 'unknown'].includes(String(runtime))) {\n throw new TypeError('observation resource runtime is invalid')\n }\n\n const state: CloneState = { options, seen: new WeakSet(), truncated: false }\n const clonedData = cloneValue(safeRead(event, 'data'), ['data'], 0, state)\n if (clonedData === null || Array.isArray(clonedData) || typeof clonedData !== 'object') {\n throw new TypeError('observation data must be an object')\n }\n const data: Record<string, JsonValue> = { ...(clonedData as Record<string, JsonValue>) }\n if (state.truncated) data['observability.truncated'] = true\n const safe: ObservationEvent = {\n schemaVersion: 1,\n eventId,\n sequence: sequence as number,\n name: name as ObservationEventName,\n phase: phase as ObservationPhase,\n occurredAt,\n monotonicMs,\n priority: priority as ObservationPriority,\n resource: {\n sdkName: 'ai-agent-sdk',\n sdkVersion,\n ...typeof safeRead(resource, 'serviceName') === 'string'\n ? { serviceName: String(safeRead(resource, 'serviceName')).slice(0, MAX_STRING_LENGTH) }\n : {},\n ...typeof safeRead(resource, 'serviceVersion') === 'string'\n ? { serviceVersion: String(safeRead(resource, 'serviceVersion')).slice(0, MAX_STRING_LENGTH) }\n : {},\n runtime: runtime as 'browser' | 'edge' | 'node' | 'unknown',\n },\n correlation: cloneValue(correlation, ['correlation'], 0, state) as unknown as ObservationEvent['correlation'],\n data,\n }\n if (eventBytes(safe) > MAX_EVENT_BYTES) {\n const keys = Object.keys(data)\n while (keys.length > 0 && eventBytes(safe) > MAX_EVENT_BYTES) {\n const key = keys.pop()\n if (key !== undefined && key !== 'observability.truncated') delete data[key]\n }\n data['observability.truncated'] = true\n }\n if (eventBytes(safe) > MAX_EVENT_BYTES) throw new RangeError('observation event exceeds the 64 KiB hard limit')\n return deepFreeze(safe)\n}\n\nexport function serializedEventBytes(event: ObservationEvent): number {\n return eventBytes(event)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"privacy.js","names":[],"sources":["../../src/observation/privacy.ts"],"sourcesContent":["import {\n deepFreeze,\n type JsonObject,\n type JsonValue,\n} from '../primitives/index.ts'\nimport {\n isSpanId,\n isTraceId,\n safeErrorRecord,\n type ObservationEvent,\n type ObservationEventName,\n type ObservationPhase,\n type ObservationPriority,\n} from '../observation/index.ts'\nimport type { ContentRedactor, ObservationContentPolicy } from './telemetry-types.ts'\n\nconst MAX_TOP_LEVEL_FIELDS = 64\nconst MAX_KEY_LENGTH = 128\nconst MAX_STRING_LENGTH = 2_048\nconst MAX_ARRAY_LENGTH = 100\nconst MAX_DEPTH = 8\nexport const MAX_EVENT_BYTES = 64 * 1024\nconst REDACTED = '[REDACTED]'\n\nconst EVENT_NAMES = new Set<ObservationEventName>([\n 'sdk.agent.run', 'sdk.agent.turn', 'sdk.model.call', 'sdk.provider.attempt',\n 'sdk.embedding.call', 'sdk.embedding.batch',\n 'sdk.provider.retry.scheduled', 'sdk.tool.call', 'sdk.compaction', 'sdk.hook.call',\n 'sdk.user.input.wait', 'sdk.skill.operation', 'sdk.memory.operation',\n 'sdk.credential.operation', 'sdk.integration.request', 'sdk.observer.failure',\n 'sdk.exporter.state', 'sdk.log',\n])\nconst PHASES = new Set<ObservationPhase>(['start', 'end', 'point'])\nconst PRIORITIES = new Set<ObservationPriority>(['critical', 'normal', 'verbose'])\nconst CONTENT_KEYS = new Set([\n 'answer', 'arguments', 'body', 'completion', 'content', 'document', 'filecontent', 'filedata', 'image',\n 'input', 'messages', 'output', 'prompt', 'reasoning', 'requestbody', 'responsebody',\n 'result', 'text', 'toolarguments', 'toolresult',\n])\nconst SAFE_HEADER_NAMES = new Set(['accept', 'content-type', 'request-id', 'traceparent', 'user-agent'])\nconst OPTIONAL_CORRELATION_KEYS = [\n 'conversationId', 'turnId', 'modelCallId', 'attemptId', 'toolCallId',\n 'providerRequestId', 'sessionId',\n] as const\n\ninterface PrivacyOptions {\n readonly content: ObservationContentPolicy\n readonly redactors: readonly ContentRedactor[]\n readonly includeErrorStacks: boolean\n}\n\nfunction safeRead(source: unknown, key: PropertyKey): unknown {\n try { return Reflect.get(source as object, key) } catch { return undefined }\n}\n\nfunction normalizedKey(key: string): string {\n return key.toLowerCase().replace(/[^a-z0-9]/g, '')\n}\n\nexport function isSecretKey(key: string): boolean {\n const normalized = normalizedKey(key)\n return normalized === 'authorization' || normalized === 'proxyauthorization'\n || normalized === 'cookie' || normalized === 'setcookie'\n || normalized.includes('apikey') || normalized.includes('accesstoken')\n || normalized.includes('refreshtoken') || normalized.includes('idtoken')\n || normalized.includes('clientsecret') || normalized.includes('password')\n || normalized.includes('sessionsecret')\n}\n\nfunction contentMetadata(value: unknown): JsonObject {\n if (typeof value === 'string') return { kind: 'string', length: value.length }\n if (Array.isArray(value)) return { kind: 'array', length: value.length }\n if (value !== null && typeof value === 'object') return { kind: 'object' }\n return { kind: typeof value }\n}\n\nfunction redactContent(value: string, path: readonly string[], redactors: readonly ContentRedactor[]): string {\n let current = value\n for (const redactor of redactors) {\n try { current = redactor.redact(current, path) } catch { return '[REDACTION_FAILED]' }\n }\n return current\n}\n\nexport function redactInlineSecrets(value: string): string {\n return value\n .replace(/\\b(Bearer)\\s+[A-Za-z0-9._~+/=-]+/gi, '$1 [REDACTED]')\n .replace(\n /\\b(authorization|proxy[-_]?authorization|api[-_]?key|access[-_]?token|refresh[-_]?token|id[-_]?token|client[-_]?secret|password|session[-_]?secret)\\s*[:=]\\s*[^\\s,;]+/gi,\n '$1=[REDACTED]',\n )\n}\n\ninterface CloneState {\n readonly options: PrivacyOptions\n readonly seen: WeakSet<object>\n truncated: boolean\n}\n\n/** Internal composition helper: apply the same recursive content/secret policy before retaining logger child fields. */\nexport function sanitizeObservationData(value: unknown, options: PrivacyOptions): JsonObject {\n const state: CloneState = { options, seen: new WeakSet(), truncated: false }\n const cloned = cloneValue(value, ['data'], 0, state)\n if (cloned === null || Array.isArray(cloned) || typeof cloned !== 'object') throw new TypeError('observation data must be an object')\n const data: Record<string, JsonValue> = { ...(cloned as Record<string, JsonValue>) }\n if (state.truncated) data['observability.truncated'] = true\n return deepFreeze(data)\n}\n\nfunction cloneValue(value: unknown, path: readonly string[], depth: number, state: CloneState): JsonValue {\n if (value === null) return null\n if (typeof value === 'string') {\n const redacted = redactInlineSecrets(value)\n if (redacted.length > MAX_STRING_LENGTH) state.truncated = true\n return redacted.slice(0, MAX_STRING_LENGTH)\n }\n if (typeof value === 'number') return Number.isFinite(value) ? value : String(value)\n if (typeof value === 'boolean') return value\n if (typeof value === 'bigint' || typeof value === 'symbol' || typeof value === 'function' || value === undefined) {\n state.truncated = true\n return `[${typeof value}]`\n }\n if (value instanceof Error) return cloneValue(\n safeErrorRecord(value, state.options.includeErrorStacks), path, depth, state,\n )\n if (depth >= MAX_DEPTH) { state.truncated = true; return '[MaxDepth]' }\n if (state.seen.has(value)) { state.truncated = true; return '[Circular]' }\n state.seen.add(value)\n try {\n if (Array.isArray(value)) {\n if (value.length > MAX_ARRAY_LENGTH) state.truncated = true\n const output: JsonValue[] = []\n for (let index = 0; index < Math.min(value.length, MAX_ARRAY_LENGTH); index++) {\n output.push(cloneValue(safeRead(value, index), [...path, String(index)], depth + 1, state))\n }\n return output\n }\n const output: Record<string, JsonValue> = Object.create(null) as Record<string, JsonValue>\n let keys: string[]\n try { keys = Object.keys(value) } catch { state.truncated = true; return '[Uninspectable]' }\n const headers = normalizedKey(path.at(-1) ?? '') === 'headers'\n for (const originalKey of keys) {\n if (Object.keys(output).length >= MAX_TOP_LEVEL_FIELDS) { state.truncated = true; break }\n const key = originalKey.slice(0, MAX_KEY_LENGTH)\n if (key !== originalKey) state.truncated = true\n if (headers && !SAFE_HEADER_NAMES.has(originalKey.toLowerCase())) {\n output[key] = REDACTED\n continue\n }\n const child = safeRead(value, originalKey)\n if (isSecretKey(originalKey)) {\n output[key] = REDACTED\n continue\n }\n const contentKey = CONTENT_KEYS.has(normalizedKey(originalKey))\n if (contentKey && state.options.content === 'none') continue\n if (contentKey && state.options.content === 'metadata') {\n output[key] = contentMetadata(child)\n continue\n }\n if (contentKey && state.options.content === 'redacted' && typeof child === 'string') {\n output[key] = cloneValue(\n redactContent(child, [...path, originalKey], state.options.redactors),\n [...path, originalKey], depth + 1, state,\n )\n continue\n }\n output[key] = cloneValue(child, [...path, originalKey], depth + 1, state)\n }\n return output\n } finally {\n state.seen.delete(value)\n }\n}\n\nfunction requiredString(value: unknown, field: string): string {\n if (typeof value !== 'string' || value.length === 0) throw new TypeError(`observation ${field} is invalid`)\n return value.slice(0, MAX_STRING_LENGTH)\n}\n\nfunction eventBytes(event: ObservationEvent): number {\n return new TextEncoder().encode(JSON.stringify(event)).byteLength\n}\n\n/** Validate, privacy-process, bound, and deeply freeze one untrusted event. */\nexport function sanitizeObservationEvent(event: unknown, options: PrivacyOptions): ObservationEvent {\n if (typeof event !== 'object' || event === null) throw new TypeError('observation event must be an object')\n if (safeRead(event, 'schemaVersion') !== 1) throw new TypeError('observation schemaVersion is invalid')\n const name = safeRead(event, 'name')\n const phase = safeRead(event, 'phase')\n const priority = safeRead(event, 'priority')\n if (!EVENT_NAMES.has(name as ObservationEventName)) throw new TypeError('observation name is invalid')\n if (!PHASES.has(phase as ObservationPhase)) throw new TypeError('observation phase is invalid')\n if (!PRIORITIES.has(priority as ObservationPriority)) throw new TypeError('observation priority is invalid')\n const sequence = safeRead(event, 'sequence')\n const monotonicMs = safeRead(event, 'monotonicMs')\n if (!Number.isSafeInteger(sequence) || (sequence as number) < 1) throw new TypeError('observation sequence is invalid')\n if (typeof monotonicMs !== 'number' || !Number.isFinite(monotonicMs) || monotonicMs < 0) {\n throw new TypeError('observation monotonicMs is invalid')\n }\n const resource = safeRead(event, 'resource')\n const correlation = safeRead(event, 'correlation')\n if (typeof resource !== 'object' || resource === null || safeRead(resource, 'sdkName') !== 'ai-agent-sdk') {\n throw new TypeError('observation resource is invalid')\n }\n if (typeof correlation !== 'object' || correlation === null\n || !isTraceId(safeRead(correlation, 'traceId')) || !isSpanId(safeRead(correlation, 'spanId'))) {\n throw new TypeError('observation correlation is invalid')\n }\n const parentSpanId = safeRead(correlation, 'parentSpanId')\n if (parentSpanId !== null && !isSpanId(parentSpanId)) throw new TypeError('observation parentSpanId is invalid')\n if (typeof safeRead(correlation, 'runId') !== 'string' || String(safeRead(correlation, 'runId')).length === 0) {\n throw new TypeError('observation runId is invalid')\n }\n for (const key of OPTIONAL_CORRELATION_KEYS) {\n const value = safeRead(correlation, key)\n if (value !== undefined && (typeof value !== 'string' || value.length === 0)) {\n throw new TypeError(`observation ${key} is invalid`)\n }\n }\n const occurredAt = requiredString(safeRead(event, 'occurredAt'), 'occurredAt')\n if (Number.isNaN(Date.parse(occurredAt)) || new Date(occurredAt).toISOString() !== occurredAt) {\n throw new TypeError('observation occurredAt must be UTC ISO 8601')\n }\n const eventId = requiredString(safeRead(event, 'eventId'), 'eventId')\n if (!/^[0-9a-f]{32}$/.test(eventId) || /^0+$/.test(eventId)) throw new TypeError('observation eventId is invalid')\n const sdkVersion = requiredString(safeRead(resource, 'sdkVersion'), 'resource.sdkVersion')\n const runtime = safeRead(resource, 'runtime')\n if (!['browser', 'edge', 'node', 'unknown'].includes(String(runtime))) {\n throw new TypeError('observation resource runtime is invalid')\n }\n\n const state: CloneState = { options, seen: new WeakSet(), truncated: false }\n const clonedData = cloneValue(safeRead(event, 'data'), ['data'], 0, state)\n if (clonedData === null || Array.isArray(clonedData) || typeof clonedData !== 'object') {\n throw new TypeError('observation data must be an object')\n }\n const data: Record<string, JsonValue> = { ...(clonedData as Record<string, JsonValue>) }\n if (state.truncated) data['observability.truncated'] = true\n const safe: ObservationEvent = {\n schemaVersion: 1,\n eventId,\n sequence: sequence as number,\n name: name as ObservationEventName,\n phase: phase as ObservationPhase,\n occurredAt,\n monotonicMs,\n priority: priority as ObservationPriority,\n resource: {\n sdkName: 'ai-agent-sdk',\n sdkVersion,\n ...typeof safeRead(resource, 'serviceName') === 'string'\n ? { serviceName: String(safeRead(resource, 'serviceName')).slice(0, MAX_STRING_LENGTH) }\n : {},\n ...typeof safeRead(resource, 'serviceVersion') === 'string'\n ? { serviceVersion: String(safeRead(resource, 'serviceVersion')).slice(0, MAX_STRING_LENGTH) }\n : {},\n runtime: runtime as 'browser' | 'edge' | 'node' | 'unknown',\n },\n correlation: cloneValue(correlation, ['correlation'], 0, state) as unknown as ObservationEvent['correlation'],\n data,\n }\n if (eventBytes(safe) > MAX_EVENT_BYTES) {\n const keys = Object.keys(data)\n while (keys.length > 0 && eventBytes(safe) > MAX_EVENT_BYTES) {\n const key = keys.pop()\n if (key !== undefined && key !== 'observability.truncated') delete data[key]\n }\n data['observability.truncated'] = true\n }\n if (eventBytes(safe) > MAX_EVENT_BYTES) throw new RangeError('observation event exceeds the 64 KiB hard limit')\n return deepFreeze(safe)\n}\n\nexport function serializedEventBytes(event: ObservationEvent): number {\n return eventBytes(event)\n}\n"],"mappings":"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"}
@@ -51,6 +51,8 @@ interface EndProviderAttemptInput {
51
51
  readonly status: OperationStatus;
52
52
  readonly dispatchState: DispatchState;
53
53
  readonly reported?: UsageCounters;
54
+ /** False for a provisional snapshot, even when every counter is present. */
55
+ readonly usageFinal?: boolean;
54
56
  readonly httpStatus?: number;
55
57
  readonly providerRequestId?: string;
56
58
  /** Must already be safe for support reports; raw response bodies are forbidden. */
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","names":[],"sources":["../../src/observation/report.ts"],"mappings":";;;;;;;;UAQiB;WACN;WACA,SAAS;WACT;WACA,QAAQ;WACR;;WAEA;;WAEA;WACA;WACA,QAAQ;WACR;WACA;WACA;WACA;;WAEA,gBAAgB;WAChB,UAAU;WACV,UAAU;WACV,YAAY;WACZ,mBAAmB;WACnB;WACA;WACA,UAAU;WACV,QAAQ;;UAGF,wBAAwB,cAAc;WAC5C;WACA;WACA,QAAQ,QAAQ;;;UAIV;WACN;WACA;WACA;;WAEA;;;UAIM;WACN,QAAQ;WACR,eAAe;WACf,WAAW;WACX;WACA;;WAEA,QAAQ;;;UAIF;WACN;WACA;WACA;;;UAIM;WACN;WACA;WACA;EACT,IAAI,OAAO,0BAA0B;;UAGtB;WACN,cAAc;;WAEd,WAAW;WACX,cAAc,QAAQ;WACtB;;WAEA,QAAQ;;WAER,SAAS;;WAET;;;;;WAKA,wBACP,OAAO,2BACP,SAAS,gBACN,QAAQ;WACJ,uBAAuB,OAAO;;cAG5B,yBAAuB;WACf;WACD;WACA;WACH;WACA;WACE;WACL;WACG;WACa;WACA;WACL;WACR;WACC;WACD;WACS;;cAGb,kCAAkC;WACpC;WACA;WACA,SAAS;WACT,QAAQ;EAEjB,YAAY,iBAAiB,QAAQ,iBAAiB,UAAU"}
1
+ {"version":3,"file":"report.d.ts","names":[],"sources":["../../src/observation/report.ts"],"mappings":";;;;;;;;UAQiB;WACN;WACA,SAAS;WACT;WACA,QAAQ;WACR;;WAEA;;WAEA;WACA;WACA,QAAQ;WACR;WACA;WACA;WACA;;WAEA,gBAAgB;WAChB,UAAU;WACV,UAAU;WACV,YAAY;WACZ,mBAAmB;WACnB;WACA;WACA,UAAU;WACV,QAAQ;;UAGF,wBAAwB,cAAc;WAC5C;WACA;WACA,QAAQ,QAAQ;;;UAIV;WACN;WACA;WACA;;WAEA;;;UAIM;WACN,QAAQ;WACR,eAAe;WACf,WAAW;;WAEX;WACA;WACA;;WAEA,QAAQ;;;UAIF;WACN;WACA;WACA;;;UAIM;WACN;WACA;WACA;EACT,IAAI,OAAO,0BAA0B;;UAGtB;WACN,cAAc;;WAEd,WAAW;WACX,cAAc,QAAQ;WACtB;;WAEA,QAAQ;;WAER,SAAS;;WAET;;;;;WAKA,wBACP,OAAO,2BACP,SAAS,gBACN,QAAQ;WACJ,uBAAuB,OAAO;;cAG5B,yBAAuB;WACf;WACD;WACA;WACH;WACA;WACE;WACL;WACG;WACa;WACA;WACL;WACR;WACC;WACD;WACS;;cAGb,kCAAkC;WACpC;WACA;WACA,SAAS;WACT,QAAQ;EAEjB,YAAY,iBAAiB,QAAQ,iBAAiB,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","names":[],"sources":["../../src/observation/report.ts"],"sourcesContent":["import type { StreamChunk } from '../stream/chunk.ts'\nimport { AgentSdkError } from '../errors/agent-sdk-error.ts'\nimport type { CorrelationContext, ObservationRunScope, SpanId, TraceId } from './context.ts'\nimport type { ObservationResource, OperationStatus, SafeErrorRecord } from './event.ts'\nimport type { ObservationDeliverySummary, ObservationPort } from './port.ts'\nimport type { AttemptUsageReport, DispatchState, UsageCounters, UsageCoverage } from './usage.ts'\nimport type { SdkLogger } from '../logging/types.ts'\n\nexport interface ModelCallReport {\n readonly runId: string\n readonly traceId: TraceId\n readonly modelCallId: string\n readonly spanId: SpanId\n readonly provider: string\n /** Provider family independently of the selected route, when installed as a plugin. */\n readonly providerFamily?: string\n /** Exact plugin installation that owned the selected route. */\n readonly providerPluginId?: string\n readonly model: string\n readonly status: OperationStatus\n readonly startedAt: string\n readonly endedAt: string\n readonly durationMs: number\n readonly finishReason?: string\n /** Logical dispatch state, retained even when an adapter did not expose physical attempts. */\n readonly dispatchState?: DispatchState\n readonly coverage: UsageCoverage\n readonly reported: UsageCounters\n readonly estimated?: UsageCounters\n readonly attempts: readonly AttemptUsageReport[]\n readonly possiblyBilledAttemptsWithoutUsage: number\n readonly authoritative: boolean\n readonly delivery: ObservationDeliverySummary\n readonly error?: SafeErrorRecord\n}\n\nexport interface ModelCallHandle extends AsyncIterable<StreamChunk> {\n readonly runId: string\n readonly modelCallId: string\n readonly report: Promise<ModelCallReport>\n}\n\n/** Safe facts known immediately before one physical provider dispatch. */\nexport interface StartProviderAttemptInput {\n readonly provider: string\n readonly model: string\n readonly method: string\n /** Scheme, host, and explicit non-default port only; never a path or query. */\n readonly origin: string\n}\n\n/** Terminal facts supplied by a transport after exactly one dispatch boundary. */\nexport interface EndProviderAttemptInput {\n readonly status: OperationStatus\n readonly dispatchState: DispatchState\n readonly reported?: UsageCounters\n readonly httpStatus?: number\n readonly providerRequestId?: string\n /** Must already be safe for support reports; raw response bodies are forbidden. */\n readonly error?: SafeErrorRecord\n}\n\n/** Safe scheduling facts between two physical provider attempts. */\nexport interface ProviderRetryScheduledInput {\n readonly nextAttemptNumber: number\n readonly delayMs: number\n readonly failureCode: string\n}\n\n/** One physical provider-attempt lifecycle owned by the model-call handle. */\nexport interface ProviderAttemptHandle {\n readonly attemptId: string\n readonly attemptNumber: number\n readonly traceparent: string\n end(input: EndProviderAttemptInput): AttemptUsageReport\n}\n\nexport interface ModelInvocationContext {\n readonly observation?: ObservationPort\n /** Safe SDK/service/runtime identity copied onto nested provider operations. */\n readonly resource?: ObservationResource\n readonly correlation?: Partial<CorrelationContext>\n readonly terminalCheckpointOwner?: 'model-call' | 'agent-run'\n /** Shared sequence/monotonic scope when this call belongs to a larger agent run. */\n readonly scope?: ObservationRunScope\n /** Always present on AgentRuntime calls; optional for preserved low-level callers. */\n readonly logger?: SdkLogger\n /** Declares that the adapter will report the real network boundary itself. */\n readonly declareProviderAttemptAccounting?: () => void\n /**\n * Internal transport accounting boundary. HTTP providers call this immediately\n * before dispatch; audit mode may reject before any network request is invoked.\n */\n readonly startProviderAttempt?: (\n input: StartProviderAttemptInput,\n signal?: AbortSignal,\n ) => Promise<ProviderAttemptHandle>\n readonly recordProviderRetry?: (input: ProviderRetryScheduledInput) => void\n}\n\nexport const OBSERVATION_ERROR_CODES = Object.freeze({\n AUDIT_UNAVAILABLE: 'OBSERVABILITY_AUDIT_UNAVAILABLE',\n CAPTURE_REJECTED: 'OBSERVABILITY_CAPTURE_REJECTED',\n PROCESSOR_FAILED: 'OBSERVABILITY_PROCESSOR_FAILED',\n EXPORT_FAILED: 'OBSERVABILITY_EXPORT_FAILED',\n FLUSH_TIMEOUT: 'OBSERVABILITY_FLUSH_TIMEOUT',\n JOURNAL_CORRUPT: 'OBSERVABILITY_JOURNAL_CORRUPT',\n JOURNAL_IO: 'OBSERVABILITY_JOURNAL_IO',\n BROWSER_QUOTA: 'OBSERVABILITY_BROWSER_QUOTA',\n OTEL_PROVIDER_UNCONFIGURED: 'OTEL_PROVIDER_UNCONFIGURED',\n OPERATION_TERMINAL_MISSING: 'OPERATION_TERMINAL_MISSING',\n LEDGER_LIMIT_EXCEEDED: 'LEDGER_LIMIT_EXCEEDED',\n USAGE_MISSING: 'USAGE_MISSING',\n USAGE_REQUIRED: 'USAGE_REQUIRED',\n USAGE_INVALID: 'USAGE_INVALID',\n USAGE_COUNTER_OVERFLOW: 'USAGE_COUNTER_OVERFLOW',\n} as const)\n\nexport class ModelCallObservationError extends AgentSdkError {\n readonly runId: string\n readonly modelCallId: string\n readonly traceId: TraceId\n readonly report: ModelCallReport\n\n constructor(message: string, report: ModelCallReport, options?: ErrorOptions) {\n super(message, OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE, options)\n this.name = 'ModelCallObservationError'\n this.runId = report.runId\n this.modelCallId = report.modelCallId\n this.traceId = report.traceId\n this.report = report\n }\n}\n"],"mappings":"6DAoGA,MAAa,EAA0B,OAAO,OAAO,CACnD,kBAAmB,kCACnB,iBAAkB,iCAClB,iBAAkB,iCAClB,cAAe,8BACf,cAAe,8BACf,gBAAiB,gCACjB,WAAY,2BACZ,cAAe,8BACf,2BAA4B,6BAC5B,2BAA4B,6BAC5B,sBAAuB,wBACvB,cAAe,gBACf,eAAgB,iBAChB,cAAe,gBACf,uBAAwB,wBAC1B,CAAU,EAEV,IAAa,EAAb,cAA+C,CAAc,CAC3D,MACA,YACA,QACA,OAEA,YAAY,EAAiB,EAAyB,EAAwB,CAC5E,MAAM,EAAS,EAAwB,kBAAmB,CAAO,EACjE,KAAK,KAAO,4BACZ,KAAK,MAAQ,EAAO,MACpB,KAAK,YAAc,EAAO,YAC1B,KAAK,QAAU,EAAO,QACtB,KAAK,OAAS,CAChB,CACF"}
1
+ {"version":3,"file":"report.js","names":[],"sources":["../../src/observation/report.ts"],"sourcesContent":["import type { StreamChunk } from '../stream/chunk.ts'\nimport { AgentSdkError } from '../errors/agent-sdk-error.ts'\nimport type { CorrelationContext, ObservationRunScope, SpanId, TraceId } from './context.ts'\nimport type { ObservationResource, OperationStatus, SafeErrorRecord } from './event.ts'\nimport type { ObservationDeliverySummary, ObservationPort } from './port.ts'\nimport type { AttemptUsageReport, DispatchState, UsageCounters, UsageCoverage } from './usage.ts'\nimport type { SdkLogger } from '../logging/types.ts'\n\nexport interface ModelCallReport {\n readonly runId: string\n readonly traceId: TraceId\n readonly modelCallId: string\n readonly spanId: SpanId\n readonly provider: string\n /** Provider family independently of the selected route, when installed as a plugin. */\n readonly providerFamily?: string\n /** Exact plugin installation that owned the selected route. */\n readonly providerPluginId?: string\n readonly model: string\n readonly status: OperationStatus\n readonly startedAt: string\n readonly endedAt: string\n readonly durationMs: number\n readonly finishReason?: string\n /** Logical dispatch state, retained even when an adapter did not expose physical attempts. */\n readonly dispatchState?: DispatchState\n readonly coverage: UsageCoverage\n readonly reported: UsageCounters\n readonly estimated?: UsageCounters\n readonly attempts: readonly AttemptUsageReport[]\n readonly possiblyBilledAttemptsWithoutUsage: number\n readonly authoritative: boolean\n readonly delivery: ObservationDeliverySummary\n readonly error?: SafeErrorRecord\n}\n\nexport interface ModelCallHandle extends AsyncIterable<StreamChunk> {\n readonly runId: string\n readonly modelCallId: string\n readonly report: Promise<ModelCallReport>\n}\n\n/** Safe facts known immediately before one physical provider dispatch. */\nexport interface StartProviderAttemptInput {\n readonly provider: string\n readonly model: string\n readonly method: string\n /** Scheme, host, and explicit non-default port only; never a path or query. */\n readonly origin: string\n}\n\n/** Terminal facts supplied by a transport after exactly one dispatch boundary. */\nexport interface EndProviderAttemptInput {\n readonly status: OperationStatus\n readonly dispatchState: DispatchState\n readonly reported?: UsageCounters\n /** False for a provisional snapshot, even when every counter is present. */\n readonly usageFinal?: boolean\n readonly httpStatus?: number\n readonly providerRequestId?: string\n /** Must already be safe for support reports; raw response bodies are forbidden. */\n readonly error?: SafeErrorRecord\n}\n\n/** Safe scheduling facts between two physical provider attempts. */\nexport interface ProviderRetryScheduledInput {\n readonly nextAttemptNumber: number\n readonly delayMs: number\n readonly failureCode: string\n}\n\n/** One physical provider-attempt lifecycle owned by the model-call handle. */\nexport interface ProviderAttemptHandle {\n readonly attemptId: string\n readonly attemptNumber: number\n readonly traceparent: string\n end(input: EndProviderAttemptInput): AttemptUsageReport\n}\n\nexport interface ModelInvocationContext {\n readonly observation?: ObservationPort\n /** Safe SDK/service/runtime identity copied onto nested provider operations. */\n readonly resource?: ObservationResource\n readonly correlation?: Partial<CorrelationContext>\n readonly terminalCheckpointOwner?: 'model-call' | 'agent-run'\n /** Shared sequence/monotonic scope when this call belongs to a larger agent run. */\n readonly scope?: ObservationRunScope\n /** Always present on AgentRuntime calls; optional for preserved low-level callers. */\n readonly logger?: SdkLogger\n /** Declares that the adapter will report the real network boundary itself. */\n readonly declareProviderAttemptAccounting?: () => void\n /**\n * Internal transport accounting boundary. HTTP providers call this immediately\n * before dispatch; audit mode may reject before any network request is invoked.\n */\n readonly startProviderAttempt?: (\n input: StartProviderAttemptInput,\n signal?: AbortSignal,\n ) => Promise<ProviderAttemptHandle>\n readonly recordProviderRetry?: (input: ProviderRetryScheduledInput) => void\n}\n\nexport const OBSERVATION_ERROR_CODES = Object.freeze({\n AUDIT_UNAVAILABLE: 'OBSERVABILITY_AUDIT_UNAVAILABLE',\n CAPTURE_REJECTED: 'OBSERVABILITY_CAPTURE_REJECTED',\n PROCESSOR_FAILED: 'OBSERVABILITY_PROCESSOR_FAILED',\n EXPORT_FAILED: 'OBSERVABILITY_EXPORT_FAILED',\n FLUSH_TIMEOUT: 'OBSERVABILITY_FLUSH_TIMEOUT',\n JOURNAL_CORRUPT: 'OBSERVABILITY_JOURNAL_CORRUPT',\n JOURNAL_IO: 'OBSERVABILITY_JOURNAL_IO',\n BROWSER_QUOTA: 'OBSERVABILITY_BROWSER_QUOTA',\n OTEL_PROVIDER_UNCONFIGURED: 'OTEL_PROVIDER_UNCONFIGURED',\n OPERATION_TERMINAL_MISSING: 'OPERATION_TERMINAL_MISSING',\n LEDGER_LIMIT_EXCEEDED: 'LEDGER_LIMIT_EXCEEDED',\n USAGE_MISSING: 'USAGE_MISSING',\n USAGE_REQUIRED: 'USAGE_REQUIRED',\n USAGE_INVALID: 'USAGE_INVALID',\n USAGE_COUNTER_OVERFLOW: 'USAGE_COUNTER_OVERFLOW',\n} as const)\n\nexport class ModelCallObservationError extends AgentSdkError {\n readonly runId: string\n readonly modelCallId: string\n readonly traceId: TraceId\n readonly report: ModelCallReport\n\n constructor(message: string, report: ModelCallReport, options?: ErrorOptions) {\n super(message, OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE, options)\n this.name = 'ModelCallObservationError'\n this.runId = report.runId\n this.modelCallId = report.modelCallId\n this.traceId = report.traceId\n this.report = report\n }\n}\n"],"mappings":"6DAsGA,MAAa,EAA0B,OAAO,OAAO,CACnD,kBAAmB,kCACnB,iBAAkB,iCAClB,iBAAkB,iCAClB,cAAe,8BACf,cAAe,8BACf,gBAAiB,gCACjB,WAAY,2BACZ,cAAe,8BACf,2BAA4B,6BAC5B,2BAA4B,6BAC5B,sBAAuB,wBACvB,cAAe,gBACf,eAAgB,iBAChB,cAAe,gBACf,uBAAwB,wBAC1B,CAAU,EAEV,IAAa,EAAb,cAA+C,CAAc,CAC3D,MACA,YACA,QACA,OAEA,YAAY,EAAiB,EAAyB,EAAwB,CAC5E,MAAM,EAAS,EAAwB,kBAAmB,CAAO,EACjE,KAAK,KAAO,4BACZ,KAAK,MAAQ,EAAO,MACpB,KAAK,YAAc,EAAO,YAC1B,KAAK,QAAU,EAAO,QACtB,KAAK,OAAS,CAChB,CACF"}
@@ -1,6 +1,6 @@
1
1
  //#region src/primitives/version.d.ts
2
2
  /** Package version injected as a Web-standard literal; release tooling updates this file. */
3
- declare const SDK_VERSION = "0.1.0";
3
+ declare const SDK_VERSION = "0.1.2";
4
4
  //#endregion
5
5
  export { SDK_VERSION };
6
6
  //# sourceMappingURL=version.d.ts.map
@@ -1,2 +1,2 @@
1
- const e=`0.1.0`;export{e as SDK_VERSION};
1
+ const e=`0.1.2`;export{e as SDK_VERSION};
2
2
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","names":[],"sources":["../../src/primitives/version.ts"],"sourcesContent":["/** Package version injected as a Web-standard literal; release tooling updates this file. */\nexport const SDK_VERSION = '0.1.0'\n"],"mappings":"AACA,MAAa,EAAc"}
1
+ {"version":3,"file":"version.js","names":[],"sources":["../../src/primitives/version.ts"],"sourcesContent":["/** Package version injected as a Web-standard literal; release tooling updates this file. */\nexport const SDK_VERSION = '0.1.2'\n"],"mappings":"AACA,MAAa,EAAc"}
@@ -12,8 +12,10 @@ import { ModelAdapter, PreparedAdapterCall } from "./contract/adapter.js";
12
12
  import { AdapterRegistrationHandle, ModelProviderPlugin, ModelProviderRegistrar, StreamMiddleware } from "./plugin/provider-plugin.js";
13
13
  import { ModelRegistry } from "./runtime/registry.js";
14
14
  import { ComposableModelProviderPlugin, ComposableModelProviderRegistrar, ModelProviderPluginDefinition, ModelTarget, PROVIDER_PLUGIN_API_VERSION } from "./composition/provider/types.js";
15
+ import { ComposableEmbeddingProviderPlugin, ComposableEmbeddingProviderRegistrar, ComposableRuntimeProviderPlugin, EMBEDDING_PROVIDER_PLUGIN_API_VERSION, EmbeddingProviderPluginDefinition, EmbeddingProviderRegistrar } from "./composition/embedding/plugin-types.js";
15
16
  import { CREDENTIAL_CAPABILITY_API_VERSION } from "./composition/credential/config.js";
16
17
  import { CredentialCommitInput, CredentialCommitResult, CredentialInput, CredentialOperationOptions, CredentialRecord, CredentialSource, CredentialStore, CredentialStoreDefinition } from "./composition/credential/types.js";
17
18
  import { defineCredentialSource, defineCredentialStore } from "./composition/credential/definition.js";
19
+ import { defineEmbeddingProviderPlugin } from "./composition/embedding/definition.js";
18
20
  import { defineModelProviderPlugin } from "./composition/provider/definition.js";
19
- export { type AdapterRegistrationHandle, AgentSdkError, CREDENTIAL_CAPABILITY_API_VERSION, type ComposableModelProviderPlugin, type ComposableModelProviderRegistrar, type CredentialCommitInput, type CredentialCommitResult, type CredentialInput, type CredentialOperationOptions, type CredentialRecord, type CredentialSource, type CredentialStore, type CredentialStoreDefinition, type EndProviderAttemptInput, type GenerateOptions, ModelAdapter, type ModelInfo, type ModelInvocationContext, type ModelModality, type ModelProviderPlugin, type ModelProviderPluginDefinition, type ModelProviderRegistrar, type ModelReasoningInfo, ModelRegistry, type ModelTarget, type ModelToolSchema, type NativeImageGenerationTool, type NativeToolName, type NativeToolSchema, type NativeToolSchemaMap, type NativeWebSearchTool, PROVIDER_PLUGIN_API_VERSION, type PreparedAdapterCall, type ProviderAttemptHandle, type ProviderInfo, type ProviderRequestId, type ResolvedModelInfo, type ResolvedRetryPolicy, type RetryPolicyConfig, type SdkLogger, type StartProviderAttemptInput, type StreamChunk, type StreamMiddleware, type ToolChoice, type UsageCounters, type WebSearchLocation, defineCredentialSource, defineCredentialStore, defineModelProviderPlugin };
21
+ export { type AdapterRegistrationHandle, AgentSdkError, CREDENTIAL_CAPABILITY_API_VERSION, type ComposableEmbeddingProviderPlugin, type ComposableEmbeddingProviderRegistrar, type ComposableModelProviderPlugin, type ComposableModelProviderRegistrar, type ComposableRuntimeProviderPlugin, type CredentialCommitInput, type CredentialCommitResult, type CredentialInput, type CredentialOperationOptions, type CredentialRecord, type CredentialSource, type CredentialStore, type CredentialStoreDefinition, EMBEDDING_PROVIDER_PLUGIN_API_VERSION, type EmbeddingProviderPluginDefinition, type EmbeddingProviderRegistrar, type EndProviderAttemptInput, type GenerateOptions, ModelAdapter, type ModelInfo, type ModelInvocationContext, type ModelModality, type ModelProviderPlugin, type ModelProviderPluginDefinition, type ModelProviderRegistrar, type ModelReasoningInfo, ModelRegistry, type ModelTarget, type ModelToolSchema, type NativeImageGenerationTool, type NativeToolName, type NativeToolSchema, type NativeToolSchemaMap, type NativeWebSearchTool, PROVIDER_PLUGIN_API_VERSION, type PreparedAdapterCall, type ProviderAttemptHandle, type ProviderInfo, type ProviderRequestId, type ResolvedModelInfo, type ResolvedRetryPolicy, type RetryPolicyConfig, type SdkLogger, type StartProviderAttemptInput, type StreamChunk, type StreamMiddleware, type ToolChoice, type UsageCounters, type WebSearchLocation, defineCredentialSource, defineCredentialStore, defineEmbeddingProviderPlugin, defineModelProviderPlugin };
package/dist/provider.js CHANGED
@@ -1 +1 @@
1
- import{AgentSdkError as e}from"./errors/agent-sdk-error.js";import{ModelAdapter as t}from"./contract/adapter.js";import{ModelRegistry as n}from"./runtime/registry.js";import{PROVIDER_PLUGIN_API_VERSION as r}from"./composition/provider/types.js";import{CREDENTIAL_CAPABILITY_API_VERSION as i}from"./composition/credential/config.js";import{defineCredentialSource as a,defineCredentialStore as o}from"./composition/credential/definition.js";import{defineModelProviderPlugin as s}from"./composition/provider/definition.js";export{e as AgentSdkError,i as CREDENTIAL_CAPABILITY_API_VERSION,t as ModelAdapter,n as ModelRegistry,r as PROVIDER_PLUGIN_API_VERSION,a as defineCredentialSource,o as defineCredentialStore,s as defineModelProviderPlugin};
1
+ import{AgentSdkError as e}from"./errors/agent-sdk-error.js";import{ModelAdapter as t}from"./contract/adapter.js";import{ModelRegistry as n}from"./runtime/registry.js";import{PROVIDER_PLUGIN_API_VERSION as r}from"./composition/provider/types.js";import{EMBEDDING_PROVIDER_PLUGIN_API_VERSION as i}from"./composition/embedding/plugin-types.js";import{CREDENTIAL_CAPABILITY_API_VERSION as a}from"./composition/credential/config.js";import{defineCredentialSource as o,defineCredentialStore as s}from"./composition/credential/definition.js";import{defineEmbeddingProviderPlugin as c}from"./composition/embedding/definition.js";import{defineModelProviderPlugin as l}from"./composition/provider/definition.js";export{e as AgentSdkError,a as CREDENTIAL_CAPABILITY_API_VERSION,i as EMBEDDING_PROVIDER_PLUGIN_API_VERSION,t as ModelAdapter,n as ModelRegistry,r as PROVIDER_PLUGIN_API_VERSION,o as defineCredentialSource,s as defineCredentialStore,c as defineEmbeddingProviderPlugin,l as defineModelProviderPlugin};
@@ -1,2 +1,2 @@
1
- import{deepFreeze as e}from"../primitives/freeze.js";import{createObservationRunScope as t,createOperationId as n,isSpanId as r,isTraceId as i}from"../observation/context.js";import{safeErrorRecord as a}from"../observation/event.js";import{NOOP_OBSERVATION_PORT as o,createCoreSpan as s,disabledDeliverySummary as c,snapshotObservationSpan as l,validateCaptureReceipt as u}from"../observation/port.js";import{AgentSdkError as d}from"../errors/agent-sdk-error.js";import{ModelCallObservationError as f,OBSERVATION_ERROR_CODES as p}from"../observation/report.js";import{addUsageCounters as m,classifyUsageCoverage as h,possiblyBilledAttemptsWithoutUsage as g,validateUsageCounters as _}from"../observation/usage.js";const v=new WeakMap;function y(){return globalThis.performance?.now()??Date.now()}function b(e,n,r){if(r!==void 0)return r;let i=v.get(e);i||(i=new Map,v.set(e,i));let a=i.get(n);return a||(a=t(),i.set(n,a)),a}function x(e,t){if(e.reason.kind!==`error`&&e.reason.kind!==`aborted`)return;let n=e.reason.failure;return Object.freeze({type:`ModelError`,message:e.reason.kind===`aborted`?`model call was aborted; inspect the stable code for classification`:`model call failed; inspect the stable code and provider request ID`,code:n.code,...t===void 0?{}:{retryable:t(n.code)},...n.status===void 0?{}:{status:n.status}})}function S(e){return e===`remote-acknowledged`?2:+(e===`local-durable`)}function C(e,t,n){n&&(t.status===`accepted`?e.accepted+=1:e.rejected+=1,t.status===`accepted`&&S(t.boundary)>S(e.reached)&&(e.reached=t.boundary))}function w(t,n,r){if(t===o)return c();let i=n===`operational`?`none`:S(r.reached)>0?r.reached:`local-durable`;return e({mode:n,requiredBoundary:i,reachedBoundary:r.reached,complete:r.rejected===0&&r.pending===0&&S(r.reached)>=S(i),acceptedCritical:r.accepted,rejectedCritical:r.rejected,pendingCritical:r.pending,...r.lastFailure===void 0?{}:{lastFailure:r.lastFailure}})}function T(e){if(!(!e||!i(e.traceId)||!r(e.spanId)||typeof e.runId!=`string`||e.runId.length===0))return{traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId===null||r(e.parentSpanId)?e.parentSpanId:null,runId:e.runId,...e.conversationId===void 0?{}:{conversationId:e.conversationId},...e.turnId===void 0?{}:{turnId:e.turnId},...e.modelCallId===void 0?{}:{modelCallId:e.modelCallId},...e.attemptId===void 0?{}:{attemptId:e.attemptId},...e.toolCallId===void 0?{}:{toolCallId:e.toolCallId},...e.providerRequestId===void 0?{}:{providerRequestId:e.providerRequestId},...e.sessionId===void 0?{}:{sessionId:e.sessionId}}}function E(e,t,n){try{let r=l(e.openSpan(t));if(r&&r.correlation.runId===t.runId&&r.correlation.modelCallId===t.correlation?.modelCallId){let e=!1;return Object.freeze({correlation:r.correlation,traceparent:r.traceparent,end(t,i,o){if(!e){e=!0;try{r.end(t,i,o)}catch(e){n.lastFailure=a(e)}}}})}n.lastFailure=Object.freeze({type:`ObservationSpanError`,message:`observation backend returned an invalid or mismatched span identity`,code:p.OTEL_PROVIDER_UNCONFIGURED})}catch(e){n.lastFailure=a(e)}return s(t)}function D(t){let r=t.context??{},i=t.context?.correlation,s=typeof i?.runId==`string`&&i.runId.length>0?i.runId:n(),c=typeof i?.modelCallId==`string`&&i.modelCallId.length>0?i.modelCallId:n(),l=b(r,s,t.context?.scope),v=new Date().toISOString(),S=y(),D=t.context?.observation??t.defaultObservation??o,O={accepted:0,rejected:0,pending:0,reached:`none`},k=`operational`;try{let e=D.mode;if(e!==`operational`&&e!==`reliable`&&e!==`audit`)throw TypeError(`observation delivery mode is invalid`);k=e}catch(e){O.lastFailure=a(e)}let A=T(i),j=E(D,{name:`sdk.model.call`,runId:s,...A===void 0?{}:{parent:A},correlation:{modelCallId:c,...i?.conversationId===void 0?{}:{conversationId:i.conversationId},...i?.turnId===void 0?{}:{turnId:i.turnId},...i?.sessionId===void 0?{}:{sessionId:i.sessionId}},startedAt:v,monotonicMs:l.monotonicMs()},O),M=(r,i)=>e({schemaVersion:1,eventId:n(),sequence:l.nextSequence(),name:`sdk.model.call`,phase:r,occurredAt:new Date().toISOString(),monotonicMs:l.monotonicMs(),priority:`critical`,resource:t.resource,correlation:j.correlation,data:i}),N=e=>{try{let t=u(D.capture(e),e.eventId);C(O,t,e.priority===`critical`)}catch(t){O.rejected+=+(e.priority===`critical`),O.lastFailure=a(t)}},P=[],F=new Set,I=1,L=!1;function R(r){N(e({schemaVersion:1,eventId:n(),sequence:l.nextSequence(),name:`sdk.provider.retry.scheduled`,phase:`point`,occurredAt:new Date().toISOString(),monotonicMs:l.monotonicMs(),priority:`critical`,resource:t.resource,correlation:j.correlation,data:{nextAttemptNumber:r.nextAttemptNumber,delayMs:r.delayMs,failureCode:r.failureCode}}))}async function z(r,i){let o=I++,f=n(),m=new Date().toISOString(),h=y(),g=E(D,{name:`sdk.provider.attempt`,runId:s,parent:j.correlation,correlation:{modelCallId:c,attemptId:f},startedAt:m,monotonicMs:l.monotonicMs()},O),v=e({schemaVersion:1,eventId:n(),sequence:l.nextSequence(),name:`sdk.provider.attempt`,phase:`start`,occurredAt:m,monotonicMs:l.monotonicMs(),priority:`critical`,resource:t.resource,correlation:g.correlation,data:{provider:r.provider,model:r.model,attemptNumber:o,method:r.method,origin:r.origin,dispatchState:`not-sent`}});if(k===`audit`){O.pending+=1;try{let e=D.checkpoint?await D.checkpoint(v,i):Object.freeze({eventId:v.eventId,status:`rejected`,durable:!1,boundary:`none`,reason:`exporter-unavailable`}),t=u(e,v.eventId);if(--O.pending,C(O,t,!0),t.status!==`accepted`||!t.durable)throw t.status===`accepted`&&(O.rejected+=1),O.lastFailure=Object.freeze({type:`ObservationCheckpointError`,message:`provider-attempt audit checkpoint was ${t.status}`,code:p.CAPTURE_REJECTED}),g.end(`rejected`,new Date().toISOString(),l.monotonicMs()),new d(`audit observation is unavailable before provider dispatch`,p.AUDIT_UNAVAILABLE)}catch(e){throw O.pending>0&&--O.pending,e instanceof d&&e.code===p.AUDIT_UNAVAILABLE||(O.rejected+=1,O.lastFailure=a(e),g.end(`rejected`,new Date().toISOString(),l.monotonicMs())),e instanceof d&&e.code===p.AUDIT_UNAVAILABLE?e:new d(`audit observation is unavailable before provider dispatch`,p.AUDIT_UNAVAILABLE,{cause:e})}}else N(v);let b,x=i=>{if(b!==void 0)return b;let a=new Date().toISOString(),s=y(),c=_(i.reported,!0),u=i.dispatchState===`not-sent`?`not-applicable`:c.complete?`complete`:Object.keys(c.reported).length>0?`partial`:`missing`,d=c.invalidFields.length>0||c.overflow?Object.freeze({type:`UsageValidationError`,message:c.overflow?`provider attempt usage counters overflowed safe integer validation`:`provider attempt usage contained invalid fields: ${c.invalidFields.join(`, `)}`,code:c.overflow?p.USAGE_COUNTER_OVERFLOW:p.USAGE_INVALID}):void 0,v=i.error??d,S=Math.max(0,s-h);g.end(i.status,a,l.monotonicMs());let C=i.providerRequestId===void 0?g.correlation:e({...g.correlation,providerRequestId:i.providerRequestId});return N(e({schemaVersion:1,eventId:n(),sequence:l.nextSequence(),name:`sdk.provider.attempt`,phase:`end`,occurredAt:a,monotonicMs:l.monotonicMs(),priority:`critical`,resource:t.resource,correlation:C,data:{status:i.status,durationMs:S,origin:r.origin,dispatchState:i.dispatchState,coverage:u,reported:{...c.reported},...i.httpStatus===void 0?{}:{httpStatus:i.httpStatus},...i.providerRequestId===void 0?{}:{providerRequestId:i.providerRequestId},...v===void 0?{}:{error:{...v}}}})),b=e({attemptId:f,spanId:g.correlation.spanId,attemptNumber:o,status:i.status,startedAt:m,endedAt:a,durationMs:S,dispatchState:i.dispatchState,coverage:u,reported:c.reported,origin:r.origin,...i.httpStatus===void 0?{}:{httpStatus:i.httpStatus},...i.providerRequestId===void 0?{}:{providerRequestId:i.providerRequestId},...v===void 0?{}:{error:v}}),P.push(b),F.delete(x),b};return F.add(x),Object.freeze({attemptId:f,attemptNumber:o,traceparent:g.traceparent,end:x})}let B=Object.freeze({observation:D,resource:t.resource,correlation:j.correlation,terminalCheckpointOwner:t.context?.terminalCheckpointOwner??`model-call`,scope:l,...t.context?.logger===void 0?{}:{logger:t.context.logger},declareProviderAttemptAccounting:()=>{L=!0},startProviderAttempt:z,recordProviderRetry:R});N(M(`start`,{provider:t.options.provider,model:t.options.model,operation:`stream`}));let V=()=>{},H=new Promise(e=>{V=e}),U=!1,W=!1,G=`unknown`,K,q,J,Y=async()=>{if(U)return{report:await H,auditFailure:!1};U=!0;let n=new Date().toISOString(),r=y();G===`unknown`&&(q??=Object.freeze({type:`OperationTerminalError`,message:`model call closed without a terminal finish reason`,code:p.OPERATION_TERMINAL_MISSING}));for(let e of[...F])e({status:G===`aborted`?`aborted`:`unknown`,dispatchState:t.dispatchState()===`not-sent`?`not-sent`:`unknown`,...q===void 0?{}:{error:q}});try{j.end(G,n,l.monotonicMs())}catch(e){O.lastFailure=a(e)}let i=J===void 0?void 0:_(J,!0),o=!t.routePresent||t.dispatchState()===`not-sent`,d=P.length>0||L?h(P):i===void 0?o?`not-applicable`:`missing`:i.complete?`complete`:`partial`;i&&(i.invalidFields.length>0||i.overflow)?q??=Object.freeze({type:`UsageValidationError`,message:i.overflow?`provider usage counters overflowed safe integer aggregation`:`provider usage contained invalid fields: ${i.invalidFields.join(`, `)}`,code:i.overflow?p.USAGE_COUNTER_OVERFLOW:p.USAGE_INVALID}):d===`missing`&&q===void 0&&(q=Object.freeze({type:`UsageMissingError`,message:`model call may have been dispatched but no provider usage was reported`,code:p.USAGE_MISSING}));let f=Math.max(0,r-S),b=P.length===0?void 0:m(P.map(e=>e.reported)),x=b?.overflow===!0||i?.overflow===!0;x&&(q??=Object.freeze({type:`UsageValidationError`,message:`provider usage counters overflowed safe integer aggregation`,code:p.USAGE_COUNTER_OVERFLOW}));let T=b?.counters??i?.reported??{},E=M(`end`,{status:G,durationMs:f,...K===void 0?{}:{finishReason:K},dispatchState:P.at(-1)?.dispatchState??(t.dispatchState()===`not-sent`?`not-sent`:`unknown`),coverage:d,reported:{...T},attemptCount:P.length}),A=!1;if((B.terminalCheckpointOwner??`model-call`)===`model-call`&&k!==`operational`){O.pending+=1;try{let e=D.checkpoint?await D.checkpoint(E):Object.freeze({eventId:E.eventId,status:`rejected`,durable:!1,boundary:`none`,reason:`exporter-unavailable`}),t=u(e,E.eventId);--O.pending,C(O,t,!0),(t.status!==`accepted`||!t.durable)&&(A=k===`audit`,O.lastFailure=Object.freeze({type:`ObservationCheckpointError`,message:`terminal observation checkpoint was ${t.status}`,code:p.CAPTURE_REJECTED}))}catch(e){--O.pending,O.rejected+=1,O.lastFailure=a(e),A=k===`audit`}}else N(E);let I=e({runId:s,traceId:j.correlation.traceId,modelCallId:c,spanId:j.correlation.spanId,provider:t.options.provider,...t.providerFamily===void 0?{}:{providerFamily:t.providerFamily},...t.providerPluginId===void 0?{}:{providerPluginId:t.providerPluginId},model:t.options.model,status:G,startedAt:v,endedAt:n,durationMs:f,...K===void 0?{}:{finishReason:K},dispatchState:P.at(-1)?.dispatchState??(t.dispatchState()===`not-sent`?`not-sent`:`unknown`),coverage:d,reported:T,attempts:[...P].sort((e,t)=>e.attemptNumber-t.attemptNumber),possiblyBilledAttemptsWithoutUsage:P.length>0?g(P):+(d===`missing`||d===`partial`),authoritative:(d===`complete`||d===`not-applicable`)&&!x,delivery:w(D,k,O),...q===void 0?{}:{error:q}});return V(I),{report:I,auditFailure:A}},X=async function*(){let e,n=!1,r;try{for(e=t.stream(B)[Symbol.asyncIterator]();;){let r=await e.next();if(r.done){n=!0;break}let i=r.value;i.type===`usage`&&(J=i.usage),i.type===`finish`&&(K=i.reason.kind,G=i.reason.kind===`aborted`?`aborted`:i.reason.kind===`error`?`error`:`success`,q=x(i,t.isRetryable)),yield i}}catch(e){throw r=e,G=t.options.signal?.aborted===!0?`aborted`:`error`,q=a(e),e}finally{if(!n){r===void 0&&(G=`aborted`);let t=e?.return?.bind(e);if(t)try{await t()}catch(e){q??=a(e)}}let t=await Y();if(t.auditFailure)throw new f(`audit observation checkpoint failed after model-call finalization`,t.report)}};return Object.freeze({runId:s,modelCallId:c,report:H,[Symbol.asyncIterator](){return W?(async function*(){throw Error(`a model call handle can only be iterated once`)})():(W=!0,X())}})}export{D as createModelCallHandle};
1
+ import{deepFreeze as e}from"../primitives/freeze.js";import{createObservationRunScope as t,createOperationId as n,isSpanId as r,isTraceId as i}from"../observation/context.js";import{safeErrorRecord as a}from"../observation/event.js";import{NOOP_OBSERVATION_PORT as o,createCoreSpan as s,disabledDeliverySummary as c,snapshotObservationSpan as l,validateCaptureReceipt as u}from"../observation/port.js";import{AgentSdkError as d}from"../errors/agent-sdk-error.js";import{ModelCallObservationError as f,OBSERVATION_ERROR_CODES as p}from"../observation/report.js";import{addUsageCounters as m,classifyUsageCoverage as h,possiblyBilledAttemptsWithoutUsage as g,validateUsageCounters as _}from"../observation/usage.js";const v=new WeakMap;function y(){return globalThis.performance?.now()??Date.now()}function b(e,n,r){if(r!==void 0)return r;let i=v.get(e);i||(i=new Map,v.set(e,i));let a=i.get(n);return a||(a=t(),i.set(n,a)),a}function x(e,t){if(e.reason.kind!==`error`&&e.reason.kind!==`aborted`)return;let n=e.reason.failure;return Object.freeze({type:`ModelError`,message:e.reason.kind===`aborted`?`model call was aborted; inspect the stable code for classification`:`model call failed; inspect the stable code and provider request ID`,code:n.code,...t===void 0?{}:{retryable:t(n.code)},...n.status===void 0?{}:{status:n.status}})}function S(e){return e===`remote-acknowledged`?2:+(e===`local-durable`)}function C(e,t,n){n&&(t.status===`accepted`?e.accepted+=1:e.rejected+=1,t.status===`accepted`&&S(t.boundary)>S(e.reached)&&(e.reached=t.boundary))}function w(t,n,r){if(t===o)return c();let i=n===`operational`?`none`:S(r.reached)>0?r.reached:`local-durable`;return e({mode:n,requiredBoundary:i,reachedBoundary:r.reached,complete:r.rejected===0&&r.pending===0&&S(r.reached)>=S(i),acceptedCritical:r.accepted,rejectedCritical:r.rejected,pendingCritical:r.pending,...r.lastFailure===void 0?{}:{lastFailure:r.lastFailure}})}function T(e){if(!(!e||!i(e.traceId)||!r(e.spanId)||typeof e.runId!=`string`||e.runId.length===0))return{traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId===null||r(e.parentSpanId)?e.parentSpanId:null,runId:e.runId,...e.conversationId===void 0?{}:{conversationId:e.conversationId},...e.turnId===void 0?{}:{turnId:e.turnId},...e.modelCallId===void 0?{}:{modelCallId:e.modelCallId},...e.attemptId===void 0?{}:{attemptId:e.attemptId},...e.toolCallId===void 0?{}:{toolCallId:e.toolCallId},...e.providerRequestId===void 0?{}:{providerRequestId:e.providerRequestId},...e.sessionId===void 0?{}:{sessionId:e.sessionId}}}function E(e,t,n){try{let r=l(e.openSpan(t));if(r&&r.correlation.runId===t.runId&&r.correlation.modelCallId===t.correlation?.modelCallId){let e=!1;return Object.freeze({correlation:r.correlation,traceparent:r.traceparent,end(t,i,o){if(!e){e=!0;try{r.end(t,i,o)}catch(e){n.lastFailure=a(e)}}}})}n.lastFailure=Object.freeze({type:`ObservationSpanError`,message:`observation backend returned an invalid or mismatched span identity`,code:p.OTEL_PROVIDER_UNCONFIGURED})}catch(e){n.lastFailure=a(e)}return s(t)}function D(t){let r=t.context??{},i=t.context?.correlation,s=typeof i?.runId==`string`&&i.runId.length>0?i.runId:n(),c=typeof i?.modelCallId==`string`&&i.modelCallId.length>0?i.modelCallId:n(),l=b(r,s,t.context?.scope),v=new Date().toISOString(),S=y(),D=t.context?.observation??t.defaultObservation??o,O={accepted:0,rejected:0,pending:0,reached:`none`},k=`operational`;try{let e=D.mode;if(e!==`operational`&&e!==`reliable`&&e!==`audit`)throw TypeError(`observation delivery mode is invalid`);k=e}catch(e){O.lastFailure=a(e)}let A=T(i),j=E(D,{name:`sdk.model.call`,runId:s,...A===void 0?{}:{parent:A},correlation:{modelCallId:c,...i?.conversationId===void 0?{}:{conversationId:i.conversationId},...i?.turnId===void 0?{}:{turnId:i.turnId},...i?.sessionId===void 0?{}:{sessionId:i.sessionId}},startedAt:v,monotonicMs:l.monotonicMs()},O),M=(r,i)=>e({schemaVersion:1,eventId:n(),sequence:l.nextSequence(),name:`sdk.model.call`,phase:r,occurredAt:new Date().toISOString(),monotonicMs:l.monotonicMs(),priority:`critical`,resource:t.resource,correlation:j.correlation,data:i}),N=e=>{try{let t=u(D.capture(e),e.eventId);C(O,t,e.priority===`critical`)}catch(t){O.rejected+=+(e.priority===`critical`),O.lastFailure=a(t)}},P=[],F=new Set,I=1,L=!1;function R(r){N(e({schemaVersion:1,eventId:n(),sequence:l.nextSequence(),name:`sdk.provider.retry.scheduled`,phase:`point`,occurredAt:new Date().toISOString(),monotonicMs:l.monotonicMs(),priority:`critical`,resource:t.resource,correlation:j.correlation,data:{nextAttemptNumber:r.nextAttemptNumber,delayMs:r.delayMs,failureCode:r.failureCode}}))}async function z(r,i){let o=I++,f=n(),m=new Date().toISOString(),h=y(),g=E(D,{name:`sdk.provider.attempt`,runId:s,parent:j.correlation,correlation:{modelCallId:c,attemptId:f},startedAt:m,monotonicMs:l.monotonicMs()},O),v=e({schemaVersion:1,eventId:n(),sequence:l.nextSequence(),name:`sdk.provider.attempt`,phase:`start`,occurredAt:m,monotonicMs:l.monotonicMs(),priority:`critical`,resource:t.resource,correlation:g.correlation,data:{provider:r.provider,model:r.model,attemptNumber:o,method:r.method,origin:r.origin,dispatchState:`not-sent`}});if(k===`audit`){O.pending+=1;try{let e=D.checkpoint?await D.checkpoint(v,i):Object.freeze({eventId:v.eventId,status:`rejected`,durable:!1,boundary:`none`,reason:`exporter-unavailable`}),t=u(e,v.eventId);if(--O.pending,C(O,t,!0),t.status!==`accepted`||!t.durable)throw t.status===`accepted`&&(O.rejected+=1),O.lastFailure=Object.freeze({type:`ObservationCheckpointError`,message:`provider-attempt audit checkpoint was ${t.status}`,code:p.CAPTURE_REJECTED}),g.end(`rejected`,new Date().toISOString(),l.monotonicMs()),new d(`audit observation is unavailable before provider dispatch`,p.AUDIT_UNAVAILABLE)}catch(e){throw O.pending>0&&--O.pending,e instanceof d&&e.code===p.AUDIT_UNAVAILABLE||(O.rejected+=1,O.lastFailure=a(e),g.end(`rejected`,new Date().toISOString(),l.monotonicMs())),e instanceof d&&e.code===p.AUDIT_UNAVAILABLE?e:new d(`audit observation is unavailable before provider dispatch`,p.AUDIT_UNAVAILABLE,{cause:e})}}else N(v);let b,x=i=>{if(b!==void 0)return b;let a=new Date().toISOString(),s=y(),c=_(i.reported,!0),u=i.dispatchState===`not-sent`?`not-applicable`:c.complete&&i.usageFinal!==!1?`complete`:Object.keys(c.reported).length>0?`partial`:`missing`,d=c.invalidFields.length>0||c.overflow?Object.freeze({type:`UsageValidationError`,message:c.overflow?`provider attempt usage counters overflowed safe integer validation`:`provider attempt usage contained invalid fields: ${c.invalidFields.join(`, `)}`,code:c.overflow?p.USAGE_COUNTER_OVERFLOW:p.USAGE_INVALID}):void 0,v=i.error??d,S=Math.max(0,s-h);g.end(i.status,a,l.monotonicMs());let C=i.providerRequestId===void 0?g.correlation:e({...g.correlation,providerRequestId:i.providerRequestId});return N(e({schemaVersion:1,eventId:n(),sequence:l.nextSequence(),name:`sdk.provider.attempt`,phase:`end`,occurredAt:a,monotonicMs:l.monotonicMs(),priority:`critical`,resource:t.resource,correlation:C,data:{status:i.status,durationMs:S,origin:r.origin,dispatchState:i.dispatchState,coverage:u,reported:{...c.reported},...i.httpStatus===void 0?{}:{httpStatus:i.httpStatus},...i.providerRequestId===void 0?{}:{providerRequestId:i.providerRequestId},...v===void 0?{}:{error:{...v}}}})),b=e({attemptId:f,spanId:g.correlation.spanId,attemptNumber:o,status:i.status,startedAt:m,endedAt:a,durationMs:S,dispatchState:i.dispatchState,coverage:u,reported:c.reported,origin:r.origin,...i.httpStatus===void 0?{}:{httpStatus:i.httpStatus},...i.providerRequestId===void 0?{}:{providerRequestId:i.providerRequestId},...v===void 0?{}:{error:v}}),P.push(b),F.delete(x),b};return F.add(x),Object.freeze({attemptId:f,attemptNumber:o,traceparent:g.traceparent,end:x})}let B=Object.freeze({observation:D,resource:t.resource,correlation:j.correlation,terminalCheckpointOwner:t.context?.terminalCheckpointOwner??`model-call`,scope:l,...t.context?.logger===void 0?{}:{logger:t.context.logger},declareProviderAttemptAccounting:()=>{L=!0},startProviderAttempt:z,recordProviderRetry:R});N(M(`start`,{provider:t.options.provider,model:t.options.model,operation:`stream`}));let V=()=>{},H=new Promise(e=>{V=e}),U=!1,W=!1,G=`unknown`,K,q,J,Y=async()=>{if(U)return{report:await H,auditFailure:!1};U=!0;let n=new Date().toISOString(),r=y();G===`unknown`&&(q??=Object.freeze({type:`OperationTerminalError`,message:`model call closed without a terminal finish reason`,code:p.OPERATION_TERMINAL_MISSING}));for(let e of[...F])e({status:G===`aborted`?`aborted`:`unknown`,dispatchState:t.dispatchState()===`not-sent`?`not-sent`:`unknown`,...q===void 0?{}:{error:q}});try{j.end(G,n,l.monotonicMs())}catch(e){O.lastFailure=a(e)}let i=J===void 0?void 0:_(J,!0),o=!t.routePresent||t.dispatchState()===`not-sent`,d=P.length>0||L?h(P):i===void 0?o?`not-applicable`:`missing`:i.complete?`complete`:`partial`;i&&(i.invalidFields.length>0||i.overflow)?q??=Object.freeze({type:`UsageValidationError`,message:i.overflow?`provider usage counters overflowed safe integer aggregation`:`provider usage contained invalid fields: ${i.invalidFields.join(`, `)}`,code:i.overflow?p.USAGE_COUNTER_OVERFLOW:p.USAGE_INVALID}):d===`missing`&&q===void 0&&(q=Object.freeze({type:`UsageMissingError`,message:`model call may have been dispatched but no provider usage was reported`,code:p.USAGE_MISSING}));let f=Math.max(0,r-S),b=P.length===0?void 0:m(P.map(e=>e.reported)),x=b?.overflow===!0||i?.overflow===!0;x&&(q??=Object.freeze({type:`UsageValidationError`,message:`provider usage counters overflowed safe integer aggregation`,code:p.USAGE_COUNTER_OVERFLOW}));let T=b?.counters??i?.reported??{},E=M(`end`,{status:G,durationMs:f,...K===void 0?{}:{finishReason:K},dispatchState:P.at(-1)?.dispatchState??(t.dispatchState()===`not-sent`?`not-sent`:`unknown`),coverage:d,reported:{...T},attemptCount:P.length}),A=!1;if((B.terminalCheckpointOwner??`model-call`)===`model-call`&&k!==`operational`){O.pending+=1;try{let e=D.checkpoint?await D.checkpoint(E):Object.freeze({eventId:E.eventId,status:`rejected`,durable:!1,boundary:`none`,reason:`exporter-unavailable`}),t=u(e,E.eventId);--O.pending,C(O,t,!0),(t.status!==`accepted`||!t.durable)&&(A=k===`audit`,O.lastFailure=Object.freeze({type:`ObservationCheckpointError`,message:`terminal observation checkpoint was ${t.status}`,code:p.CAPTURE_REJECTED}))}catch(e){--O.pending,O.rejected+=1,O.lastFailure=a(e),A=k===`audit`}}else N(E);let I=e({runId:s,traceId:j.correlation.traceId,modelCallId:c,spanId:j.correlation.spanId,provider:t.options.provider,...t.providerFamily===void 0?{}:{providerFamily:t.providerFamily},...t.providerPluginId===void 0?{}:{providerPluginId:t.providerPluginId},model:t.options.model,status:G,startedAt:v,endedAt:n,durationMs:f,...K===void 0?{}:{finishReason:K},dispatchState:P.at(-1)?.dispatchState??(t.dispatchState()===`not-sent`?`not-sent`:`unknown`),coverage:d,reported:T,attempts:[...P].sort((e,t)=>e.attemptNumber-t.attemptNumber),possiblyBilledAttemptsWithoutUsage:P.length>0?g(P):+(d===`missing`||d===`partial`),authoritative:(d===`complete`||d===`not-applicable`)&&!x,delivery:w(D,k,O),...q===void 0?{}:{error:q}});return V(I),{report:I,auditFailure:A}},X=async function*(){let e,n=!1,r;try{for(e=t.stream(B)[Symbol.asyncIterator]();;){let r=await e.next();if(r.done){n=!0;break}let i=r.value;i.type===`usage`&&(J=i.usage),i.type===`finish`&&(K=i.reason.kind,G=i.reason.kind===`aborted`?`aborted`:i.reason.kind===`error`?`error`:`success`,q=x(i,t.isRetryable)),yield i}}catch(e){throw r=e,G=t.options.signal?.aborted===!0?`aborted`:`error`,q=a(e),e}finally{if(!n){r===void 0&&(G=`aborted`);let t=e?.return?.bind(e);if(t)try{await t()}catch(e){q??=a(e)}}let t=await Y();if(t.auditFailure)throw new f(`audit observation checkpoint failed after model-call finalization`,t.report)}};return Object.freeze({runId:s,modelCallId:c,report:H,[Symbol.asyncIterator](){return W?(async function*(){throw Error(`a model call handle can only be iterated once`)})():(W=!0,X())}})}export{D as createModelCallHandle};
2
2
  //# sourceMappingURL=model-call-handle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-call-handle.js","names":[],"sources":["../../src/runtime/model-call-handle.ts"],"sourcesContent":["import type { GenerateOptions } from '../contract/generate-options.ts'\nimport { deepFreeze } from '../primitives/freeze.ts'\nimport type { JsonObject } from '../primitives/json.ts'\nimport type { StreamChunk, TokenUsage } from '../stream/chunk.ts'\nimport { createObservationRunScope, createOperationId, isSpanId, isTraceId, type CorrelationContext, type ObservationRunScope } from '../observation/context.ts'\nimport { safeErrorRecord, type ObservationEvent, type ObservationResource, type OperationStatus, type SafeErrorRecord } from '../observation/event.ts'\nimport { createCoreSpan, disabledDeliverySummary, NOOP_OBSERVATION_PORT, snapshotObservationSpan, validateCaptureReceipt, type CaptureReceipt, type DeliveryMode, type ObservationBoundary, type ObservationDeliverySummary, type ObservationPort, type ObservationSpan } from '../observation/port.ts'\nimport { AgentSdkError } from '../errors/agent-sdk-error.ts'\nimport { ModelCallObservationError, OBSERVATION_ERROR_CODES, type EndProviderAttemptInput, type ModelCallHandle, type ModelCallReport, type ModelInvocationContext, type ProviderAttemptHandle, type ProviderRetryScheduledInput, type StartProviderAttemptInput } from '../observation/report.ts'\nimport { addUsageCounters, classifyUsageCoverage, possiblyBilledAttemptsWithoutUsage, validateUsageCounters, type AttemptUsageReport, type UsageCoverage } from '../observation/usage.ts'\n\nconst scopes = new WeakMap<object, Map<string, ObservationRunScope>>()\n\nfunction nowMonotonic(): number {\n return globalThis.performance?.now() ?? Date.now()\n}\n\nfunction scopeFor(key: object, runId: string, supplied?: ObservationRunScope): ObservationRunScope {\n if (supplied !== undefined) return supplied\n let runs = scopes.get(key)\n if (!runs) {\n runs = new Map()\n scopes.set(key, runs)\n }\n let scope = runs.get(runId)\n if (!scope) {\n scope = createObservationRunScope()\n runs.set(runId, scope)\n }\n return scope\n}\n\nfunction safeFailureFromFinish(\n chunk: Extract<StreamChunk, { type: 'finish' }>,\n isRetryable?: (code: string) => boolean,\n): SafeErrorRecord | undefined {\n if (chunk.reason.kind !== 'error' && chunk.reason.kind !== 'aborted') return undefined\n const failure = chunk.reason.failure\n return Object.freeze({\n type: 'ModelError',\n message: chunk.reason.kind === 'aborted'\n ? 'model call was aborted; inspect the stable code for classification'\n : 'model call failed; inspect the stable code and provider request ID',\n code: failure.code,\n ...isRetryable === undefined ? {} : { retryable: isRetryable(failure.code) },\n ...failure.status === undefined ? {} : { status: failure.status },\n })\n}\n\nfunction boundaryRank(boundary: ObservationBoundary): number {\n if (boundary === 'remote-acknowledged') return 2\n if (boundary === 'local-durable') return 1\n return 0\n}\n\ninterface DeliveryTracker {\n accepted: number\n rejected: number\n pending: number\n reached: ObservationBoundary\n lastFailure?: SafeErrorRecord\n}\n\nfunction applyReceipt(tracker: DeliveryTracker, receipt: CaptureReceipt, critical: boolean): void {\n if (!critical) return\n if (receipt.status === 'accepted') tracker.accepted += 1\n else tracker.rejected += 1\n if (receipt.status === 'accepted' && boundaryRank(receipt.boundary) > boundaryRank(tracker.reached)) tracker.reached = receipt.boundary\n}\n\nfunction deliverySummary(port: ObservationPort, mode: DeliveryMode, tracker: DeliveryTracker): ObservationDeliverySummary {\n if (port === NOOP_OBSERVATION_PORT) return disabledDeliverySummary()\n const requiredBoundary: ObservationBoundary = mode === 'operational'\n ? 'none'\n : boundaryRank(tracker.reached) > 0 ? tracker.reached : 'local-durable'\n return deepFreeze({\n mode,\n requiredBoundary,\n reachedBoundary: tracker.reached,\n complete: tracker.rejected === 0 && tracker.pending === 0\n && boundaryRank(tracker.reached) >= boundaryRank(requiredBoundary),\n acceptedCritical: tracker.accepted,\n rejectedCritical: tracker.rejected,\n pendingCritical: tracker.pending,\n ...tracker.lastFailure === undefined ? {} : { lastFailure: tracker.lastFailure },\n })\n}\n\nfunction validParent(value: Partial<CorrelationContext> | undefined): CorrelationContext | undefined {\n if (!value || !isTraceId(value.traceId) || !isSpanId(value.spanId)\n || typeof value.runId !== 'string' || value.runId.length === 0) return undefined\n return {\n traceId: value.traceId,\n spanId: value.spanId,\n parentSpanId: value.parentSpanId === null || isSpanId(value.parentSpanId) ? value.parentSpanId : null,\n runId: value.runId,\n ...value.conversationId === undefined ? {} : { conversationId: value.conversationId },\n ...value.turnId === undefined ? {} : { turnId: value.turnId },\n ...value.modelCallId === undefined ? {} : { modelCallId: value.modelCallId },\n ...value.attemptId === undefined ? {} : { attemptId: value.attemptId },\n ...value.toolCallId === undefined ? {} : { toolCallId: value.toolCallId },\n ...value.providerRequestId === undefined ? {} : { providerRequestId: value.providerRequestId },\n ...value.sessionId === undefined ? {} : { sessionId: value.sessionId },\n }\n}\n\nfunction openContainedSpan(port: ObservationPort, input: Parameters<ObservationPort['openSpan']>[0], tracker: DeliveryTracker): ObservationSpan {\n try {\n const span = snapshotObservationSpan(port.openSpan(input))\n if (span && span.correlation.runId === input.runId\n && span.correlation.modelCallId === input.correlation?.modelCallId) {\n let ended = false\n return Object.freeze({\n correlation: span.correlation,\n traceparent: span.traceparent,\n end(status: OperationStatus, endedAt: string, monotonicMs: number): void {\n if (ended) return\n ended = true\n try { span.end(status, endedAt, monotonicMs) } catch (error) { tracker.lastFailure = safeErrorRecord(error) }\n },\n })\n }\n tracker.lastFailure = Object.freeze({\n type: 'ObservationSpanError',\n message: 'observation backend returned an invalid or mismatched span identity',\n code: OBSERVATION_ERROR_CODES.OTEL_PROVIDER_UNCONFIGURED,\n })\n } catch (error) {\n tracker.lastFailure = safeErrorRecord(error)\n }\n return createCoreSpan(input)\n}\n\nexport interface CreateModelCallHandleOptions {\n readonly options: GenerateOptions\n readonly providerFamily?: string\n readonly providerPluginId?: string\n readonly isRetryable?: (code: string) => boolean\n readonly context?: ModelInvocationContext\n readonly defaultObservation?: ObservationPort\n readonly resource: ObservationResource\n readonly routePresent: boolean\n readonly dispatchState: () => 'not-sent' | 'unknown'\n readonly stream: (context: ModelInvocationContext) => AsyncIterable<StreamChunk>\n}\n\nexport function createModelCallHandle(input: CreateModelCallHandleOptions): ModelCallHandle {\n const contextKey = input.context ?? {}\n const supplied = input.context?.correlation\n const runId = typeof supplied?.runId === 'string' && supplied.runId.length > 0 ? supplied.runId : createOperationId()\n const modelCallId = typeof supplied?.modelCallId === 'string' && supplied.modelCallId.length > 0 ? supplied.modelCallId : createOperationId()\n const scope = scopeFor(contextKey, runId, input.context?.scope)\n const startedAt = new Date().toISOString()\n const startedMonotonic = nowMonotonic()\n const port = input.context?.observation ?? input.defaultObservation ?? NOOP_OBSERVATION_PORT\n const tracker: DeliveryTracker = { accepted: 0, rejected: 0, pending: 0, reached: 'none' }\n let mode: DeliveryMode = 'operational'\n try {\n const configuredMode = port.mode\n if (configuredMode !== 'operational' && configuredMode !== 'reliable' && configuredMode !== 'audit') {\n throw new TypeError('observation delivery mode is invalid')\n }\n mode = configuredMode\n } catch (modeError) {\n tracker.lastFailure = safeErrorRecord(modeError)\n }\n const parent = validParent(supplied)\n const span = openContainedSpan(port, {\n name: 'sdk.model.call',\n runId,\n ...(parent === undefined ? {} : { parent }),\n correlation: {\n modelCallId,\n ...supplied?.conversationId === undefined ? {} : { conversationId: supplied.conversationId },\n ...supplied?.turnId === undefined ? {} : { turnId: supplied.turnId },\n ...supplied?.sessionId === undefined ? {} : { sessionId: supplied.sessionId },\n },\n startedAt,\n monotonicMs: scope.monotonicMs(),\n }, tracker)\n const makeEvent = (phase: 'start' | 'end', data: JsonObject): ObservationEvent<'sdk.model.call'> => deepFreeze({\n schemaVersion: 1,\n eventId: createOperationId(),\n sequence: scope.nextSequence(),\n name: 'sdk.model.call',\n phase,\n occurredAt: new Date().toISOString(),\n monotonicMs: scope.monotonicMs(),\n priority: 'critical',\n resource: input.resource,\n correlation: span.correlation,\n data,\n })\n\n const capture = (event: ObservationEvent): void => {\n try {\n const receipt = validateCaptureReceipt(port.capture(event), event.eventId)\n applyReceipt(tracker, receipt, event.priority === 'critical')\n } catch (error) {\n tracker.rejected += event.priority === 'critical' ? 1 : 0\n tracker.lastFailure = safeErrorRecord(error)\n }\n }\n\n const attempts: AttemptUsageReport[] = []\n const openAttempts = new Set<(input: EndProviderAttemptInput) => AttemptUsageReport>()\n let nextAttemptNumber = 1\n let providerAttemptAccountingDeclared = false\n\n function recordProviderRetry(retry: ProviderRetryScheduledInput): void {\n capture(deepFreeze({\n schemaVersion: 1,\n eventId: createOperationId(),\n sequence: scope.nextSequence(),\n name: 'sdk.provider.retry.scheduled',\n phase: 'point',\n occurredAt: new Date().toISOString(),\n monotonicMs: scope.monotonicMs(),\n priority: 'critical',\n resource: input.resource,\n correlation: span.correlation,\n data: {\n nextAttemptNumber: retry.nextAttemptNumber,\n delayMs: retry.delayMs,\n failureCode: retry.failureCode,\n },\n }))\n }\n\n async function startProviderAttempt(\n attemptInput: StartProviderAttemptInput,\n signal?: AbortSignal,\n ): Promise<ProviderAttemptHandle> {\n const attemptNumber = nextAttemptNumber++\n const attemptId = createOperationId()\n const attemptStartedAt = new Date().toISOString()\n const attemptStartedMonotonic = nowMonotonic()\n const attemptSpan = openContainedSpan(port, {\n name: 'sdk.provider.attempt',\n runId,\n parent: span.correlation,\n correlation: { modelCallId, attemptId },\n startedAt: attemptStartedAt,\n monotonicMs: scope.monotonicMs(),\n }, tracker)\n const startEvent: ObservationEvent<'sdk.provider.attempt'> = deepFreeze({\n schemaVersion: 1,\n eventId: createOperationId(),\n sequence: scope.nextSequence(),\n name: 'sdk.provider.attempt',\n phase: 'start',\n occurredAt: attemptStartedAt,\n monotonicMs: scope.monotonicMs(),\n priority: 'critical',\n resource: input.resource,\n correlation: attemptSpan.correlation,\n data: {\n provider: attemptInput.provider,\n model: attemptInput.model,\n attemptNumber,\n method: attemptInput.method,\n origin: attemptInput.origin,\n dispatchState: 'not-sent',\n },\n })\n\n if (mode === 'audit') {\n tracker.pending += 1\n try {\n const rawReceipt = port.checkpoint\n ? await port.checkpoint(startEvent, signal)\n : Object.freeze({\n eventId: startEvent.eventId,\n status: 'rejected' as const,\n durable: false,\n boundary: 'none' as const,\n reason: 'exporter-unavailable' as const,\n })\n const receipt = validateCaptureReceipt(rawReceipt, startEvent.eventId)\n tracker.pending -= 1\n applyReceipt(tracker, receipt, true)\n if (receipt.status !== 'accepted' || !receipt.durable) {\n if (receipt.status === 'accepted') tracker.rejected += 1\n tracker.lastFailure = Object.freeze({\n type: 'ObservationCheckpointError',\n message: `provider-attempt audit checkpoint was ${receipt.status}`,\n code: OBSERVATION_ERROR_CODES.CAPTURE_REJECTED,\n })\n attemptSpan.end('rejected', new Date().toISOString(), scope.monotonicMs())\n throw new AgentSdkError(\n 'audit observation is unavailable before provider dispatch',\n OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE,\n )\n }\n } catch (checkpointError) {\n if (tracker.pending > 0) tracker.pending -= 1\n if (!(checkpointError instanceof AgentSdkError\n && checkpointError.code === OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE)) {\n tracker.rejected += 1\n tracker.lastFailure = safeErrorRecord(checkpointError)\n attemptSpan.end('rejected', new Date().toISOString(), scope.monotonicMs())\n }\n throw checkpointError instanceof AgentSdkError\n && checkpointError.code === OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE\n ? checkpointError\n : new AgentSdkError(\n 'audit observation is unavailable before provider dispatch',\n OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE,\n { cause: checkpointError },\n )\n }\n } else capture(startEvent)\n\n let finalReport: AttemptUsageReport | undefined\n const end = (endInput: EndProviderAttemptInput): AttemptUsageReport => {\n if (finalReport !== undefined) return finalReport\n const endedAt = new Date().toISOString()\n const endedMonotonic = nowMonotonic()\n const validated = validateUsageCounters(endInput.reported, true)\n const coverage: UsageCoverage = endInput.dispatchState === 'not-sent'\n ? 'not-applicable'\n : validated.complete ? 'complete'\n : Object.keys(validated.reported).length > 0 ? 'partial' : 'missing'\n const invalidError = validated.invalidFields.length > 0 || validated.overflow\n ? Object.freeze({\n type: 'UsageValidationError',\n message: validated.overflow\n ? 'provider attempt usage counters overflowed safe integer validation'\n : `provider attempt usage contained invalid fields: ${validated.invalidFields.join(', ')}`,\n code: validated.overflow\n ? OBSERVATION_ERROR_CODES.USAGE_COUNTER_OVERFLOW\n : OBSERVATION_ERROR_CODES.USAGE_INVALID,\n })\n : undefined\n const terminalError = endInput.error ?? invalidError\n const durationMs = Math.max(0, endedMonotonic - attemptStartedMonotonic)\n attemptSpan.end(endInput.status, endedAt, scope.monotonicMs())\n const terminalCorrelation = endInput.providerRequestId === undefined\n ? attemptSpan.correlation\n : deepFreeze({ ...attemptSpan.correlation, providerRequestId: endInput.providerRequestId })\n capture(deepFreeze({\n schemaVersion: 1,\n eventId: createOperationId(),\n sequence: scope.nextSequence(),\n name: 'sdk.provider.attempt',\n phase: 'end',\n occurredAt: endedAt,\n monotonicMs: scope.monotonicMs(),\n priority: 'critical',\n resource: input.resource,\n correlation: terminalCorrelation,\n data: {\n status: endInput.status,\n durationMs,\n origin: attemptInput.origin,\n dispatchState: endInput.dispatchState,\n coverage,\n reported: { ...validated.reported },\n ...endInput.httpStatus === undefined ? {} : { httpStatus: endInput.httpStatus },\n ...endInput.providerRequestId === undefined ? {} : { providerRequestId: endInput.providerRequestId },\n ...terminalError === undefined ? {} : { error: { ...terminalError } },\n },\n }))\n finalReport = deepFreeze({\n attemptId,\n spanId: attemptSpan.correlation.spanId,\n attemptNumber,\n status: endInput.status,\n startedAt: attemptStartedAt,\n endedAt,\n durationMs,\n dispatchState: endInput.dispatchState,\n coverage,\n reported: validated.reported,\n origin: attemptInput.origin,\n ...endInput.httpStatus === undefined ? {} : { httpStatus: endInput.httpStatus },\n ...endInput.providerRequestId === undefined ? {} : { providerRequestId: endInput.providerRequestId },\n ...terminalError === undefined ? {} : { error: terminalError },\n })\n attempts.push(finalReport)\n openAttempts.delete(end)\n return finalReport\n }\n openAttempts.add(end)\n return Object.freeze({ attemptId, attemptNumber, traceparent: attemptSpan.traceparent, end })\n }\n const effectiveContext: ModelInvocationContext = Object.freeze({\n observation: port,\n resource: input.resource,\n correlation: span.correlation,\n terminalCheckpointOwner: input.context?.terminalCheckpointOwner ?? 'model-call',\n scope,\n ...(input.context?.logger === undefined ? {} : { logger: input.context.logger }),\n declareProviderAttemptAccounting: () => { providerAttemptAccountingDeclared = true },\n startProviderAttempt,\n recordProviderRetry,\n })\n capture(makeEvent('start', {\n provider: input.options.provider,\n model: input.options.model,\n operation: 'stream',\n }))\n\n let resolveReport: (report: ModelCallReport) => void = () => {}\n const report = new Promise<ModelCallReport>((resolvePromise) => { resolveReport = resolvePromise })\n let finalized = false\n let iterated = false\n let status: OperationStatus = 'unknown'\n let finishReason: string | undefined\n let error: SafeErrorRecord | undefined\n let usage: TokenUsage | undefined\n\n const finalize = async (): Promise<{ report: ModelCallReport; auditFailure: boolean }> => {\n if (finalized) return { report: await report, auditFailure: false }\n finalized = true\n const endedAt = new Date().toISOString()\n const endedMonotonic = nowMonotonic()\n if (status === 'unknown') {\n error ??= Object.freeze({\n type: 'OperationTerminalError',\n message: 'model call closed without a terminal finish reason',\n code: OBSERVATION_ERROR_CODES.OPERATION_TERMINAL_MISSING,\n })\n }\n for (const closeAttempt of [...openAttempts]) {\n closeAttempt({\n status: status === 'aborted' ? 'aborted' : 'unknown',\n dispatchState: input.dispatchState() === 'not-sent' ? 'not-sent' : 'unknown',\n ...(error === undefined ? {} : { error }),\n })\n }\n try { span.end(status, endedAt, scope.monotonicMs()) } catch (spanError) { tracker.lastFailure = safeErrorRecord(spanError) }\n\n const validated = usage === undefined ? undefined : validateUsageCounters(usage, true)\n const preDispatch = !input.routePresent || input.dispatchState() === 'not-sent'\n const coverage: UsageCoverage = attempts.length > 0 || providerAttemptAccountingDeclared\n ? classifyUsageCoverage(attempts)\n : validated === undefined\n ? preDispatch ? 'not-applicable' : 'missing'\n : validated.complete ? 'complete' : 'partial'\n if (validated && (validated.invalidFields.length > 0 || validated.overflow)) {\n error ??= Object.freeze({\n type: 'UsageValidationError',\n message: validated.overflow\n ? 'provider usage counters overflowed safe integer aggregation'\n : `provider usage contained invalid fields: ${validated.invalidFields.join(', ')}`,\n code: validated.overflow ? OBSERVATION_ERROR_CODES.USAGE_COUNTER_OVERFLOW : OBSERVATION_ERROR_CODES.USAGE_INVALID,\n })\n } else if (coverage === 'missing' && error === undefined) {\n error = Object.freeze({\n type: 'UsageMissingError',\n message: 'model call may have been dispatched but no provider usage was reported',\n code: OBSERVATION_ERROR_CODES.USAGE_MISSING,\n })\n }\n const durationMs = Math.max(0, endedMonotonic - startedMonotonic)\n const attemptUsage = attempts.length === 0\n ? undefined\n : addUsageCounters(attempts.map(attempt => attempt.reported))\n const accountingOverflow = attemptUsage?.overflow === true || validated?.overflow === true\n if (accountingOverflow) error ??= Object.freeze({\n type: 'UsageValidationError', message: 'provider usage counters overflowed safe integer aggregation',\n code: OBSERVATION_ERROR_CODES.USAGE_COUNTER_OVERFLOW,\n })\n const reported = attemptUsage?.counters ?? validated?.reported ?? {}\n const endEvent = makeEvent('end', {\n status,\n durationMs,\n ...finishReason === undefined ? {} : { finishReason },\n dispatchState: attempts.at(-1)?.dispatchState\n ?? (input.dispatchState() === 'not-sent' ? 'not-sent' : 'unknown'),\n coverage,\n reported: { ...reported },\n attemptCount: attempts.length,\n })\n let auditFailure = false\n const checkpointOwner = effectiveContext.terminalCheckpointOwner ?? 'model-call'\n if (checkpointOwner === 'model-call' && mode !== 'operational') {\n tracker.pending += 1\n try {\n const rawReceipt = port.checkpoint\n ? await port.checkpoint(endEvent)\n : Object.freeze({ eventId: endEvent.eventId, status: 'rejected' as const, durable: false, boundary: 'none' as const, reason: 'exporter-unavailable' as const })\n const receipt = validateCaptureReceipt(rawReceipt, endEvent.eventId)\n tracker.pending -= 1\n applyReceipt(tracker, receipt, true)\n if (receipt.status !== 'accepted' || !receipt.durable) {\n auditFailure = mode === 'audit'\n tracker.lastFailure = Object.freeze({\n type: 'ObservationCheckpointError',\n message: `terminal observation checkpoint was ${receipt.status}`,\n code: OBSERVATION_ERROR_CODES.CAPTURE_REJECTED,\n })\n }\n } catch (checkpointError) {\n tracker.pending -= 1\n tracker.rejected += 1\n tracker.lastFailure = safeErrorRecord(checkpointError)\n auditFailure = mode === 'audit'\n }\n } else capture(endEvent)\n\n const finalReport = deepFreeze<ModelCallReport>({\n runId,\n traceId: span.correlation.traceId,\n modelCallId,\n spanId: span.correlation.spanId,\n provider: input.options.provider,\n ...input.providerFamily === undefined ? {} : { providerFamily: input.providerFamily },\n ...input.providerPluginId === undefined ? {} : { providerPluginId: input.providerPluginId },\n model: input.options.model,\n status,\n startedAt,\n endedAt,\n durationMs,\n ...finishReason === undefined ? {} : { finishReason },\n dispatchState: attempts.at(-1)?.dispatchState\n ?? (input.dispatchState() === 'not-sent' ? 'not-sent' : 'unknown'),\n coverage,\n reported,\n attempts: [...attempts].sort((left, right) => left.attemptNumber - right.attemptNumber),\n possiblyBilledAttemptsWithoutUsage: attempts.length > 0\n ? possiblyBilledAttemptsWithoutUsage(attempts)\n : coverage === 'missing' || coverage === 'partial' ? 1 : 0,\n authoritative: (coverage === 'complete' || coverage === 'not-applicable') && !accountingOverflow,\n delivery: deliverySummary(port, mode, tracker),\n ...error === undefined ? {} : { error },\n })\n resolveReport(finalReport)\n return { report: finalReport, auditFailure }\n }\n\n const iterate = async function* (): AsyncGenerator<StreamChunk> {\n let iterator: AsyncIterator<StreamChunk> | undefined\n let sourceDone = false\n let thrown: unknown\n try {\n iterator = input.stream(effectiveContext)[Symbol.asyncIterator]()\n while (true) {\n const item = await iterator.next()\n if (item.done) {\n sourceDone = true\n break\n }\n const chunk = item.value\n if (chunk.type === 'usage') usage = chunk.usage\n if (chunk.type === 'finish') {\n finishReason = chunk.reason.kind\n status = chunk.reason.kind === 'aborted' ? 'aborted'\n : chunk.reason.kind === 'error' ? 'error' : 'success'\n error = safeFailureFromFinish(chunk, input.isRetryable)\n }\n yield chunk\n }\n } catch (streamError) {\n thrown = streamError\n status = input.options.signal?.aborted === true ? 'aborted' : 'error'\n error = safeErrorRecord(streamError)\n throw streamError\n } finally {\n if (!sourceDone) {\n if (thrown === undefined) status = 'aborted'\n const close = iterator?.return?.bind(iterator)\n if (close) try { await close() } catch (closeError) { error ??= safeErrorRecord(closeError) }\n }\n const terminal = await finalize()\n if (terminal.auditFailure) {\n throw new ModelCallObservationError('audit observation checkpoint failed after model-call finalization', terminal.report)\n }\n }\n }\n\n return Object.freeze({\n runId,\n modelCallId,\n report,\n [Symbol.asyncIterator](): AsyncIterator<StreamChunk> {\n if (iterated) {\n return (async function* () { throw new Error('a model call handle can only be iterated once') })()\n }\n iterated = true\n return iterate()\n },\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"model-call-handle.js","names":[],"sources":["../../src/runtime/model-call-handle.ts"],"sourcesContent":["import type { GenerateOptions } from '../contract/generate-options.ts'\nimport { deepFreeze } from '../primitives/freeze.ts'\nimport type { JsonObject } from '../primitives/json.ts'\nimport type { StreamChunk, TokenUsage } from '../stream/chunk.ts'\nimport { createObservationRunScope, createOperationId, isSpanId, isTraceId, type CorrelationContext, type ObservationRunScope } from '../observation/context.ts'\nimport { safeErrorRecord, type ObservationEvent, type ObservationResource, type OperationStatus, type SafeErrorRecord } from '../observation/event.ts'\nimport { createCoreSpan, disabledDeliverySummary, NOOP_OBSERVATION_PORT, snapshotObservationSpan, validateCaptureReceipt, type CaptureReceipt, type DeliveryMode, type ObservationBoundary, type ObservationDeliverySummary, type ObservationPort, type ObservationSpan } from '../observation/port.ts'\nimport { AgentSdkError } from '../errors/agent-sdk-error.ts'\nimport { ModelCallObservationError, OBSERVATION_ERROR_CODES, type EndProviderAttemptInput, type ModelCallHandle, type ModelCallReport, type ModelInvocationContext, type ProviderAttemptHandle, type ProviderRetryScheduledInput, type StartProviderAttemptInput } from '../observation/report.ts'\nimport { addUsageCounters, classifyUsageCoverage, possiblyBilledAttemptsWithoutUsage, validateUsageCounters, type AttemptUsageReport, type UsageCoverage } from '../observation/usage.ts'\n\nconst scopes = new WeakMap<object, Map<string, ObservationRunScope>>()\n\nfunction nowMonotonic(): number {\n return globalThis.performance?.now() ?? Date.now()\n}\n\nfunction scopeFor(key: object, runId: string, supplied?: ObservationRunScope): ObservationRunScope {\n if (supplied !== undefined) return supplied\n let runs = scopes.get(key)\n if (!runs) {\n runs = new Map()\n scopes.set(key, runs)\n }\n let scope = runs.get(runId)\n if (!scope) {\n scope = createObservationRunScope()\n runs.set(runId, scope)\n }\n return scope\n}\n\nfunction safeFailureFromFinish(\n chunk: Extract<StreamChunk, { type: 'finish' }>,\n isRetryable?: (code: string) => boolean,\n): SafeErrorRecord | undefined {\n if (chunk.reason.kind !== 'error' && chunk.reason.kind !== 'aborted') return undefined\n const failure = chunk.reason.failure\n return Object.freeze({\n type: 'ModelError',\n message: chunk.reason.kind === 'aborted'\n ? 'model call was aborted; inspect the stable code for classification'\n : 'model call failed; inspect the stable code and provider request ID',\n code: failure.code,\n ...isRetryable === undefined ? {} : { retryable: isRetryable(failure.code) },\n ...failure.status === undefined ? {} : { status: failure.status },\n })\n}\n\nfunction boundaryRank(boundary: ObservationBoundary): number {\n if (boundary === 'remote-acknowledged') return 2\n if (boundary === 'local-durable') return 1\n return 0\n}\n\ninterface DeliveryTracker {\n accepted: number\n rejected: number\n pending: number\n reached: ObservationBoundary\n lastFailure?: SafeErrorRecord\n}\n\nfunction applyReceipt(tracker: DeliveryTracker, receipt: CaptureReceipt, critical: boolean): void {\n if (!critical) return\n if (receipt.status === 'accepted') tracker.accepted += 1\n else tracker.rejected += 1\n if (receipt.status === 'accepted' && boundaryRank(receipt.boundary) > boundaryRank(tracker.reached)) tracker.reached = receipt.boundary\n}\n\nfunction deliverySummary(port: ObservationPort, mode: DeliveryMode, tracker: DeliveryTracker): ObservationDeliverySummary {\n if (port === NOOP_OBSERVATION_PORT) return disabledDeliverySummary()\n const requiredBoundary: ObservationBoundary = mode === 'operational'\n ? 'none'\n : boundaryRank(tracker.reached) > 0 ? tracker.reached : 'local-durable'\n return deepFreeze({\n mode,\n requiredBoundary,\n reachedBoundary: tracker.reached,\n complete: tracker.rejected === 0 && tracker.pending === 0\n && boundaryRank(tracker.reached) >= boundaryRank(requiredBoundary),\n acceptedCritical: tracker.accepted,\n rejectedCritical: tracker.rejected,\n pendingCritical: tracker.pending,\n ...tracker.lastFailure === undefined ? {} : { lastFailure: tracker.lastFailure },\n })\n}\n\nfunction validParent(value: Partial<CorrelationContext> | undefined): CorrelationContext | undefined {\n if (!value || !isTraceId(value.traceId) || !isSpanId(value.spanId)\n || typeof value.runId !== 'string' || value.runId.length === 0) return undefined\n return {\n traceId: value.traceId,\n spanId: value.spanId,\n parentSpanId: value.parentSpanId === null || isSpanId(value.parentSpanId) ? value.parentSpanId : null,\n runId: value.runId,\n ...value.conversationId === undefined ? {} : { conversationId: value.conversationId },\n ...value.turnId === undefined ? {} : { turnId: value.turnId },\n ...value.modelCallId === undefined ? {} : { modelCallId: value.modelCallId },\n ...value.attemptId === undefined ? {} : { attemptId: value.attemptId },\n ...value.toolCallId === undefined ? {} : { toolCallId: value.toolCallId },\n ...value.providerRequestId === undefined ? {} : { providerRequestId: value.providerRequestId },\n ...value.sessionId === undefined ? {} : { sessionId: value.sessionId },\n }\n}\n\nfunction openContainedSpan(port: ObservationPort, input: Parameters<ObservationPort['openSpan']>[0], tracker: DeliveryTracker): ObservationSpan {\n try {\n const span = snapshotObservationSpan(port.openSpan(input))\n if (span && span.correlation.runId === input.runId\n && span.correlation.modelCallId === input.correlation?.modelCallId) {\n let ended = false\n return Object.freeze({\n correlation: span.correlation,\n traceparent: span.traceparent,\n end(status: OperationStatus, endedAt: string, monotonicMs: number): void {\n if (ended) return\n ended = true\n try { span.end(status, endedAt, monotonicMs) } catch (error) { tracker.lastFailure = safeErrorRecord(error) }\n },\n })\n }\n tracker.lastFailure = Object.freeze({\n type: 'ObservationSpanError',\n message: 'observation backend returned an invalid or mismatched span identity',\n code: OBSERVATION_ERROR_CODES.OTEL_PROVIDER_UNCONFIGURED,\n })\n } catch (error) {\n tracker.lastFailure = safeErrorRecord(error)\n }\n return createCoreSpan(input)\n}\n\nexport interface CreateModelCallHandleOptions {\n readonly options: GenerateOptions\n readonly providerFamily?: string\n readonly providerPluginId?: string\n readonly isRetryable?: (code: string) => boolean\n readonly context?: ModelInvocationContext\n readonly defaultObservation?: ObservationPort\n readonly resource: ObservationResource\n readonly routePresent: boolean\n readonly dispatchState: () => 'not-sent' | 'unknown'\n readonly stream: (context: ModelInvocationContext) => AsyncIterable<StreamChunk>\n}\n\nexport function createModelCallHandle(input: CreateModelCallHandleOptions): ModelCallHandle {\n const contextKey = input.context ?? {}\n const supplied = input.context?.correlation\n const runId = typeof supplied?.runId === 'string' && supplied.runId.length > 0 ? supplied.runId : createOperationId()\n const modelCallId = typeof supplied?.modelCallId === 'string' && supplied.modelCallId.length > 0 ? supplied.modelCallId : createOperationId()\n const scope = scopeFor(contextKey, runId, input.context?.scope)\n const startedAt = new Date().toISOString()\n const startedMonotonic = nowMonotonic()\n const port = input.context?.observation ?? input.defaultObservation ?? NOOP_OBSERVATION_PORT\n const tracker: DeliveryTracker = { accepted: 0, rejected: 0, pending: 0, reached: 'none' }\n let mode: DeliveryMode = 'operational'\n try {\n const configuredMode = port.mode\n if (configuredMode !== 'operational' && configuredMode !== 'reliable' && configuredMode !== 'audit') {\n throw new TypeError('observation delivery mode is invalid')\n }\n mode = configuredMode\n } catch (modeError) {\n tracker.lastFailure = safeErrorRecord(modeError)\n }\n const parent = validParent(supplied)\n const span = openContainedSpan(port, {\n name: 'sdk.model.call',\n runId,\n ...(parent === undefined ? {} : { parent }),\n correlation: {\n modelCallId,\n ...supplied?.conversationId === undefined ? {} : { conversationId: supplied.conversationId },\n ...supplied?.turnId === undefined ? {} : { turnId: supplied.turnId },\n ...supplied?.sessionId === undefined ? {} : { sessionId: supplied.sessionId },\n },\n startedAt,\n monotonicMs: scope.monotonicMs(),\n }, tracker)\n const makeEvent = (phase: 'start' | 'end', data: JsonObject): ObservationEvent<'sdk.model.call'> => deepFreeze({\n schemaVersion: 1,\n eventId: createOperationId(),\n sequence: scope.nextSequence(),\n name: 'sdk.model.call',\n phase,\n occurredAt: new Date().toISOString(),\n monotonicMs: scope.monotonicMs(),\n priority: 'critical',\n resource: input.resource,\n correlation: span.correlation,\n data,\n })\n\n const capture = (event: ObservationEvent): void => {\n try {\n const receipt = validateCaptureReceipt(port.capture(event), event.eventId)\n applyReceipt(tracker, receipt, event.priority === 'critical')\n } catch (error) {\n tracker.rejected += event.priority === 'critical' ? 1 : 0\n tracker.lastFailure = safeErrorRecord(error)\n }\n }\n\n const attempts: AttemptUsageReport[] = []\n const openAttempts = new Set<(input: EndProviderAttemptInput) => AttemptUsageReport>()\n let nextAttemptNumber = 1\n let providerAttemptAccountingDeclared = false\n\n function recordProviderRetry(retry: ProviderRetryScheduledInput): void {\n capture(deepFreeze({\n schemaVersion: 1,\n eventId: createOperationId(),\n sequence: scope.nextSequence(),\n name: 'sdk.provider.retry.scheduled',\n phase: 'point',\n occurredAt: new Date().toISOString(),\n monotonicMs: scope.monotonicMs(),\n priority: 'critical',\n resource: input.resource,\n correlation: span.correlation,\n data: {\n nextAttemptNumber: retry.nextAttemptNumber,\n delayMs: retry.delayMs,\n failureCode: retry.failureCode,\n },\n }))\n }\n\n async function startProviderAttempt(\n attemptInput: StartProviderAttemptInput,\n signal?: AbortSignal,\n ): Promise<ProviderAttemptHandle> {\n const attemptNumber = nextAttemptNumber++\n const attemptId = createOperationId()\n const attemptStartedAt = new Date().toISOString()\n const attemptStartedMonotonic = nowMonotonic()\n const attemptSpan = openContainedSpan(port, {\n name: 'sdk.provider.attempt',\n runId,\n parent: span.correlation,\n correlation: { modelCallId, attemptId },\n startedAt: attemptStartedAt,\n monotonicMs: scope.monotonicMs(),\n }, tracker)\n const startEvent: ObservationEvent<'sdk.provider.attempt'> = deepFreeze({\n schemaVersion: 1,\n eventId: createOperationId(),\n sequence: scope.nextSequence(),\n name: 'sdk.provider.attempt',\n phase: 'start',\n occurredAt: attemptStartedAt,\n monotonicMs: scope.monotonicMs(),\n priority: 'critical',\n resource: input.resource,\n correlation: attemptSpan.correlation,\n data: {\n provider: attemptInput.provider,\n model: attemptInput.model,\n attemptNumber,\n method: attemptInput.method,\n origin: attemptInput.origin,\n dispatchState: 'not-sent',\n },\n })\n\n if (mode === 'audit') {\n tracker.pending += 1\n try {\n const rawReceipt = port.checkpoint\n ? await port.checkpoint(startEvent, signal)\n : Object.freeze({\n eventId: startEvent.eventId,\n status: 'rejected' as const,\n durable: false,\n boundary: 'none' as const,\n reason: 'exporter-unavailable' as const,\n })\n const receipt = validateCaptureReceipt(rawReceipt, startEvent.eventId)\n tracker.pending -= 1\n applyReceipt(tracker, receipt, true)\n if (receipt.status !== 'accepted' || !receipt.durable) {\n if (receipt.status === 'accepted') tracker.rejected += 1\n tracker.lastFailure = Object.freeze({\n type: 'ObservationCheckpointError',\n message: `provider-attempt audit checkpoint was ${receipt.status}`,\n code: OBSERVATION_ERROR_CODES.CAPTURE_REJECTED,\n })\n attemptSpan.end('rejected', new Date().toISOString(), scope.monotonicMs())\n throw new AgentSdkError(\n 'audit observation is unavailable before provider dispatch',\n OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE,\n )\n }\n } catch (checkpointError) {\n if (tracker.pending > 0) tracker.pending -= 1\n if (!(checkpointError instanceof AgentSdkError\n && checkpointError.code === OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE)) {\n tracker.rejected += 1\n tracker.lastFailure = safeErrorRecord(checkpointError)\n attemptSpan.end('rejected', new Date().toISOString(), scope.monotonicMs())\n }\n throw checkpointError instanceof AgentSdkError\n && checkpointError.code === OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE\n ? checkpointError\n : new AgentSdkError(\n 'audit observation is unavailable before provider dispatch',\n OBSERVATION_ERROR_CODES.AUDIT_UNAVAILABLE,\n { cause: checkpointError },\n )\n }\n } else capture(startEvent)\n\n let finalReport: AttemptUsageReport | undefined\n const end = (endInput: EndProviderAttemptInput): AttemptUsageReport => {\n if (finalReport !== undefined) return finalReport\n const endedAt = new Date().toISOString()\n const endedMonotonic = nowMonotonic()\n const validated = validateUsageCounters(endInput.reported, true)\n const coverage: UsageCoverage = endInput.dispatchState === 'not-sent'\n ? 'not-applicable'\n : validated.complete && endInput.usageFinal !== false ? 'complete'\n : Object.keys(validated.reported).length > 0 ? 'partial' : 'missing'\n const invalidError = validated.invalidFields.length > 0 || validated.overflow\n ? Object.freeze({\n type: 'UsageValidationError',\n message: validated.overflow\n ? 'provider attempt usage counters overflowed safe integer validation'\n : `provider attempt usage contained invalid fields: ${validated.invalidFields.join(', ')}`,\n code: validated.overflow\n ? OBSERVATION_ERROR_CODES.USAGE_COUNTER_OVERFLOW\n : OBSERVATION_ERROR_CODES.USAGE_INVALID,\n })\n : undefined\n const terminalError = endInput.error ?? invalidError\n const durationMs = Math.max(0, endedMonotonic - attemptStartedMonotonic)\n attemptSpan.end(endInput.status, endedAt, scope.monotonicMs())\n const terminalCorrelation = endInput.providerRequestId === undefined\n ? attemptSpan.correlation\n : deepFreeze({ ...attemptSpan.correlation, providerRequestId: endInput.providerRequestId })\n capture(deepFreeze({\n schemaVersion: 1,\n eventId: createOperationId(),\n sequence: scope.nextSequence(),\n name: 'sdk.provider.attempt',\n phase: 'end',\n occurredAt: endedAt,\n monotonicMs: scope.monotonicMs(),\n priority: 'critical',\n resource: input.resource,\n correlation: terminalCorrelation,\n data: {\n status: endInput.status,\n durationMs,\n origin: attemptInput.origin,\n dispatchState: endInput.dispatchState,\n coverage,\n reported: { ...validated.reported },\n ...endInput.httpStatus === undefined ? {} : { httpStatus: endInput.httpStatus },\n ...endInput.providerRequestId === undefined ? {} : { providerRequestId: endInput.providerRequestId },\n ...terminalError === undefined ? {} : { error: { ...terminalError } },\n },\n }))\n finalReport = deepFreeze({\n attemptId,\n spanId: attemptSpan.correlation.spanId,\n attemptNumber,\n status: endInput.status,\n startedAt: attemptStartedAt,\n endedAt,\n durationMs,\n dispatchState: endInput.dispatchState,\n coverage,\n reported: validated.reported,\n origin: attemptInput.origin,\n ...endInput.httpStatus === undefined ? {} : { httpStatus: endInput.httpStatus },\n ...endInput.providerRequestId === undefined ? {} : { providerRequestId: endInput.providerRequestId },\n ...terminalError === undefined ? {} : { error: terminalError },\n })\n attempts.push(finalReport)\n openAttempts.delete(end)\n return finalReport\n }\n openAttempts.add(end)\n return Object.freeze({ attemptId, attemptNumber, traceparent: attemptSpan.traceparent, end })\n }\n const effectiveContext: ModelInvocationContext = Object.freeze({\n observation: port,\n resource: input.resource,\n correlation: span.correlation,\n terminalCheckpointOwner: input.context?.terminalCheckpointOwner ?? 'model-call',\n scope,\n ...(input.context?.logger === undefined ? {} : { logger: input.context.logger }),\n declareProviderAttemptAccounting: () => { providerAttemptAccountingDeclared = true },\n startProviderAttempt,\n recordProviderRetry,\n })\n capture(makeEvent('start', {\n provider: input.options.provider,\n model: input.options.model,\n operation: 'stream',\n }))\n\n let resolveReport: (report: ModelCallReport) => void = () => {}\n const report = new Promise<ModelCallReport>((resolvePromise) => { resolveReport = resolvePromise })\n let finalized = false\n let iterated = false\n let status: OperationStatus = 'unknown'\n let finishReason: string | undefined\n let error: SafeErrorRecord | undefined\n let usage: TokenUsage | undefined\n\n const finalize = async (): Promise<{ report: ModelCallReport; auditFailure: boolean }> => {\n if (finalized) return { report: await report, auditFailure: false }\n finalized = true\n const endedAt = new Date().toISOString()\n const endedMonotonic = nowMonotonic()\n if (status === 'unknown') {\n error ??= Object.freeze({\n type: 'OperationTerminalError',\n message: 'model call closed without a terminal finish reason',\n code: OBSERVATION_ERROR_CODES.OPERATION_TERMINAL_MISSING,\n })\n }\n for (const closeAttempt of [...openAttempts]) {\n closeAttempt({\n status: status === 'aborted' ? 'aborted' : 'unknown',\n dispatchState: input.dispatchState() === 'not-sent' ? 'not-sent' : 'unknown',\n ...(error === undefined ? {} : { error }),\n })\n }\n try { span.end(status, endedAt, scope.monotonicMs()) } catch (spanError) { tracker.lastFailure = safeErrorRecord(spanError) }\n\n const validated = usage === undefined ? undefined : validateUsageCounters(usage, true)\n const preDispatch = !input.routePresent || input.dispatchState() === 'not-sent'\n const coverage: UsageCoverage = attempts.length > 0 || providerAttemptAccountingDeclared\n ? classifyUsageCoverage(attempts)\n : validated === undefined\n ? preDispatch ? 'not-applicable' : 'missing'\n : validated.complete ? 'complete' : 'partial'\n if (validated && (validated.invalidFields.length > 0 || validated.overflow)) {\n error ??= Object.freeze({\n type: 'UsageValidationError',\n message: validated.overflow\n ? 'provider usage counters overflowed safe integer aggregation'\n : `provider usage contained invalid fields: ${validated.invalidFields.join(', ')}`,\n code: validated.overflow ? OBSERVATION_ERROR_CODES.USAGE_COUNTER_OVERFLOW : OBSERVATION_ERROR_CODES.USAGE_INVALID,\n })\n } else if (coverage === 'missing' && error === undefined) {\n error = Object.freeze({\n type: 'UsageMissingError',\n message: 'model call may have been dispatched but no provider usage was reported',\n code: OBSERVATION_ERROR_CODES.USAGE_MISSING,\n })\n }\n const durationMs = Math.max(0, endedMonotonic - startedMonotonic)\n const attemptUsage = attempts.length === 0\n ? undefined\n : addUsageCounters(attempts.map(attempt => attempt.reported))\n const accountingOverflow = attemptUsage?.overflow === true || validated?.overflow === true\n if (accountingOverflow) error ??= Object.freeze({\n type: 'UsageValidationError', message: 'provider usage counters overflowed safe integer aggregation',\n code: OBSERVATION_ERROR_CODES.USAGE_COUNTER_OVERFLOW,\n })\n const reported = attemptUsage?.counters ?? validated?.reported ?? {}\n const endEvent = makeEvent('end', {\n status,\n durationMs,\n ...finishReason === undefined ? {} : { finishReason },\n dispatchState: attempts.at(-1)?.dispatchState\n ?? (input.dispatchState() === 'not-sent' ? 'not-sent' : 'unknown'),\n coverage,\n reported: { ...reported },\n attemptCount: attempts.length,\n })\n let auditFailure = false\n const checkpointOwner = effectiveContext.terminalCheckpointOwner ?? 'model-call'\n if (checkpointOwner === 'model-call' && mode !== 'operational') {\n tracker.pending += 1\n try {\n const rawReceipt = port.checkpoint\n ? await port.checkpoint(endEvent)\n : Object.freeze({ eventId: endEvent.eventId, status: 'rejected' as const, durable: false, boundary: 'none' as const, reason: 'exporter-unavailable' as const })\n const receipt = validateCaptureReceipt(rawReceipt, endEvent.eventId)\n tracker.pending -= 1\n applyReceipt(tracker, receipt, true)\n if (receipt.status !== 'accepted' || !receipt.durable) {\n auditFailure = mode === 'audit'\n tracker.lastFailure = Object.freeze({\n type: 'ObservationCheckpointError',\n message: `terminal observation checkpoint was ${receipt.status}`,\n code: OBSERVATION_ERROR_CODES.CAPTURE_REJECTED,\n })\n }\n } catch (checkpointError) {\n tracker.pending -= 1\n tracker.rejected += 1\n tracker.lastFailure = safeErrorRecord(checkpointError)\n auditFailure = mode === 'audit'\n }\n } else capture(endEvent)\n\n const finalReport = deepFreeze<ModelCallReport>({\n runId,\n traceId: span.correlation.traceId,\n modelCallId,\n spanId: span.correlation.spanId,\n provider: input.options.provider,\n ...input.providerFamily === undefined ? {} : { providerFamily: input.providerFamily },\n ...input.providerPluginId === undefined ? {} : { providerPluginId: input.providerPluginId },\n model: input.options.model,\n status,\n startedAt,\n endedAt,\n durationMs,\n ...finishReason === undefined ? {} : { finishReason },\n dispatchState: attempts.at(-1)?.dispatchState\n ?? (input.dispatchState() === 'not-sent' ? 'not-sent' : 'unknown'),\n coverage,\n reported,\n attempts: [...attempts].sort((left, right) => left.attemptNumber - right.attemptNumber),\n possiblyBilledAttemptsWithoutUsage: attempts.length > 0\n ? possiblyBilledAttemptsWithoutUsage(attempts)\n : coverage === 'missing' || coverage === 'partial' ? 1 : 0,\n authoritative: (coverage === 'complete' || coverage === 'not-applicable') && !accountingOverflow,\n delivery: deliverySummary(port, mode, tracker),\n ...error === undefined ? {} : { error },\n })\n resolveReport(finalReport)\n return { report: finalReport, auditFailure }\n }\n\n const iterate = async function* (): AsyncGenerator<StreamChunk> {\n let iterator: AsyncIterator<StreamChunk> | undefined\n let sourceDone = false\n let thrown: unknown\n try {\n iterator = input.stream(effectiveContext)[Symbol.asyncIterator]()\n while (true) {\n const item = await iterator.next()\n if (item.done) {\n sourceDone = true\n break\n }\n const chunk = item.value\n if (chunk.type === 'usage') usage = chunk.usage\n if (chunk.type === 'finish') {\n finishReason = chunk.reason.kind\n status = chunk.reason.kind === 'aborted' ? 'aborted'\n : chunk.reason.kind === 'error' ? 'error' : 'success'\n error = safeFailureFromFinish(chunk, input.isRetryable)\n }\n yield chunk\n }\n } catch (streamError) {\n thrown = streamError\n status = input.options.signal?.aborted === true ? 'aborted' : 'error'\n error = safeErrorRecord(streamError)\n throw streamError\n } finally {\n if (!sourceDone) {\n if (thrown === undefined) status = 'aborted'\n const close = iterator?.return?.bind(iterator)\n if (close) try { await close() } catch (closeError) { error ??= safeErrorRecord(closeError) }\n }\n const terminal = await finalize()\n if (terminal.auditFailure) {\n throw new ModelCallObservationError('audit observation checkpoint failed after model-call finalization', terminal.report)\n }\n }\n }\n\n return Object.freeze({\n runId,\n modelCallId,\n report,\n [Symbol.asyncIterator](): AsyncIterator<StreamChunk> {\n if (iterated) {\n return (async function* () { throw new Error('a model call handle can only be iterated once') })()\n }\n iterated = true\n return iterate()\n },\n })\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{deepFreeze as e}from"../primitives/freeze.js";import{ModelError as t,REGISTRY_ERROR_CODES as n}from"../errors/model-error.js";import{freezeMessage as r}from"../message/message.js";function i(e,r,i,a){if(!Array.isArray(r))throw new t(`route "${e}" returned a catalog that is not an array`,n.INVALID_CATALOG);if(r.length>i||f(r,n.INVALID_CATALOG)>a)throw new t(`route "${e}" catalog exceeds the configured registry limit`,n.INVALID_CATALOG);let o=new Set;return r.map(r=>{if(r.provider!==e||typeof r.id!=`string`||r.id.length===0||typeof r.name!=`string`||r.name.length===0)throw new t(`route "${e}" advertised a model entry with invalid identity`,n.INVALID_CATALOG);if(o.has(r.id))throw new t(`route "${e}" advertised model "${r.id}" more than once`,n.INVALID_CATALOG);return o.add(r.id),structuredClone(r)})}function a(r,a,o,s){if(typeof a!=`object`||!a||a.provider?.id!==r||typeof a.provider.name!=`string`||a.provider.name.length===0||![`static`,`fresh`,`empty`,`stale`,`unavailable`].includes(a.state)||typeof a.revision!=`string`||a.revision.length===0||typeof a.observedAt!=`string`||!Number.isFinite(Date.parse(a.observedAt)))throw new t(`route "${r}" returned an invalid catalog snapshot`,n.INVALID_CATALOG);let c=i(r,a.models,o,s);return e({...structuredClone(a),provider:{...a.provider},models:c})}function o(r,i,a,o){if(a.provider!==r||a.id!==i||typeof a.name!=`string`||a.name.length===0)throw l(r,i,`mismatched identity`);if(a.context!==void 0&&(!Number.isSafeInteger(a.context.contextWindow)||a.context.contextWindow<=0))throw l(r,i,`a non-positive context window`);if(a.defaultMaxTokens!==void 0&&(!Number.isSafeInteger(a.defaultMaxTokens)||a.defaultMaxTokens<=0))throw l(r,i,`a non-positive defaultMaxTokens`);if(a.maxOutputTokens!==void 0&&(!Number.isSafeInteger(a.maxOutputTokens)||a.maxOutputTokens<=0))throw l(r,i,`a non-positive maxOutputTokens`);if(a.defaultMaxTokens!==void 0&&a.maxOutputTokens!==void 0&&a.defaultMaxTokens>a.maxOutputTokens)throw l(r,i,`defaultMaxTokens above maxOutputTokens`);if(a.context!==void 0&&a.defaultMaxTokens!==void 0&&a.defaultMaxTokens>=a.context.contextWindow||a.context!==void 0&&a.maxOutputTokens!==void 0&&a.maxOutputTokens>=a.context.contextWindow)throw l(r,i,`no input headroom`);s(r,i,a),c(r,i,a);let u=e(structuredClone({...a,...a.inputModalities===void 0?{}:{inputModalities:[...a.inputModalities]},...a.outputModalities===void 0?{}:{outputModalities:[...a.outputModalities]},...a.nativeTools===void 0?{}:{nativeTools:[...a.nativeTools]}}));if(f(u,n.INVALID_MODEL_INFO)>o)throw new t(`route "${r}" model metadata exceeds the configured registry limit`,n.INVALID_MODEL_INFO);return u}function s(e,t,n){if(n.reasoning===void 0)return;let r=n.reasoning.efforts.map(e=>e.id);if(r.length===0||new Set(r).size!==r.length||n.reasoning.efforts.some(e=>typeof e.id!=`string`||e.id.length===0||typeof e.name!=`string`||e.name.length===0))throw l(e,t,`empty or duplicated reasoning efforts`);if(n.reasoning.defaultEffort!==void 0&&!r.includes(n.reasoning.defaultEffort))throw l(e,t,`a default reasoning effort it does not offer`)}function c(e,t,n){for(let[r,i]of[[`input modalities`,n.inputModalities],[`output modalities`,n.outputModalities],[`native tools`,n.nativeTools]])if(i!==void 0&&(new Set(i).size!==i.length||i.some(e=>typeof e!=`string`||e.length===0)))throw l(e,t,`invalid ${r}`)}function l(e,r,i){return new t(`route "${e}" resolved model "${r}" with ${i}`,n.INVALID_MODEL_INFO)}function u(e,r){let i=e.reasoningEffort??r.reasoning?.defaultEffort;if(e.reasoningEffort!==void 0&&r.reasoning?.efforts.some(t=>t.id===e.reasoningEffort)!==!0)throw new t(`model "${r.id}" on route "${r.provider}" does not offer reasoning effort "${e.reasoningEffort}"`,n.UNSUPPORTED_REASONING_EFFORT);let a=e.maxTokens??r.defaultMaxTokens;if(a!==void 0&&r.maxOutputTokens!==void 0&&a>r.maxOutputTokens)throw new t(`model "${r.id}" on route "${r.provider}" supports at most ${r.maxOutputTokens} output tokens, received ${a}`,n.OUTPUT_TOKEN_LIMIT_EXCEEDED);if(a!==void 0&&r.context!==void 0&&a>=r.context.contextWindow)throw new t(`model "${r.id}" on route "${r.provider}" cannot reserve ${a} output tokens inside its ${r.context.contextWindow}-token combined context window`,n.OUTPUT_TOKEN_LIMIT_EXCEEDED);return{config:{provider:e.provider,model:e.model,...i===void 0?{}:{reasoningEffort:i},...e.temperature===void 0?{}:{temperature:e.temperature},...e.topP===void 0?{}:{topP:e.topP},...a===void 0?{}:{maxTokens:a},...e.stop===void 0?{}:{stop:[...e.stop]}},context:r.context}}function d(e,t,n){let i=e.messages.map(e=>{let i=e.source;return e.role!==`assistant`||i.kind!==`model`||i.replayState===void 0||n(i.provider)===t?e:r({...e,source:{kind:`model`,provider:i.provider,model:i.model}})});return i.every((t,n)=>t===e.messages[n])?e:{...e,messages:i}}function f(e,n){let r;try{r=JSON.stringify(e)}catch(e){throw new t(`adapter model metadata must be JSON-serializable`,n,{cause:e})}if(r===void 0)throw new t(`adapter model metadata must be JSON-serializable`,n);return new TextEncoder().encode(r).byteLength}export{o as normalizeResolvedModelInfo,d as projectReplayForAdapter,u as resolveCallWithModelInfo,i as validateCatalogModels,a as validateModelCatalogSnapshot};
1
+ import{deepFreeze as e}from"../primitives/freeze.js";import{ModelError as t,REGISTRY_ERROR_CODES as n}from"../errors/model-error.js";import{freezeMessage as r}from"../message/message.js";function i(e,r,i,a){if(!Array.isArray(r))throw new t(`route "${e}" returned a catalog that is not an array`,n.INVALID_CATALOG);if(r.length>i||f(r,n.INVALID_CATALOG)>a)throw new t(`route "${e}" catalog exceeds the configured registry limit`,n.INVALID_CATALOG);let o=new Set;return r.map(r=>{if(r.provider!==e||typeof r.id!=`string`||r.id.length===0||typeof r.name!=`string`||r.name.length===0)throw new t(`route "${e}" advertised a model entry with invalid identity`,n.INVALID_CATALOG);if(o.has(r.id))throw new t(`route "${e}" advertised model "${r.id}" more than once`,n.INVALID_CATALOG);return o.add(r.id),structuredClone(r)})}function a(r,a,o,s){if(typeof a!=`object`||!a||a.provider?.id!==r||typeof a.provider.name!=`string`||a.provider.name.length===0||![`static`,`fresh`,`empty`,`stale`,`unavailable`].includes(a.state)||typeof a.revision!=`string`||a.revision.length===0||typeof a.observedAt!=`string`||!Number.isFinite(Date.parse(a.observedAt)))throw new t(`route "${r}" returned an invalid catalog snapshot`,n.INVALID_CATALOG);let c=i(r,a.models,o,s);return e({...structuredClone(a),provider:{...a.provider},models:c})}function o(r,i,a,o){if(a.provider!==r||a.id!==i||typeof a.name!=`string`||a.name.length===0)throw l(r,i,`mismatched identity`);if(a.context!==void 0&&(!Number.isSafeInteger(a.context.contextWindow)||a.context.contextWindow<=0))throw l(r,i,`a non-positive context window`);if(a.defaultMaxTokens!==void 0&&(!Number.isSafeInteger(a.defaultMaxTokens)||a.defaultMaxTokens<=0))throw l(r,i,`a non-positive defaultMaxTokens`);for(let e of[a.context?.maxContextWindow,a.context?.defaultContextWindow,a.context?.standardPriceInputTokens])if(e!==void 0&&(!Number.isSafeInteger(e)||e<=0))throw l(r,i,`invalid context policy`);if(a.context?.maxContextWindow!==void 0&&(a.context.contextWindow>a.context.maxContextWindow||(a.context.defaultContextWindow??0)>a.context.maxContextWindow))throw l(r,i,`contextWindow above maxContextWindow`);if(a.maxOutputTokens!==void 0&&(!Number.isSafeInteger(a.maxOutputTokens)||a.maxOutputTokens<=0))throw l(r,i,`a non-positive maxOutputTokens`);if(a.defaultMaxTokens!==void 0&&a.maxOutputTokens!==void 0&&a.defaultMaxTokens>a.maxOutputTokens)throw l(r,i,`defaultMaxTokens above maxOutputTokens`);if(a.context!==void 0&&a.defaultMaxTokens!==void 0&&a.defaultMaxTokens>=a.context.contextWindow||a.context!==void 0&&a.maxOutputTokens!==void 0&&a.maxOutputTokens>=(a.context.maxContextWindow??a.context.contextWindow))throw l(r,i,`no input headroom`);s(r,i,a),c(r,i,a);let u=e(structuredClone({...a,...a.inputModalities===void 0?{}:{inputModalities:[...a.inputModalities]},...a.outputModalities===void 0?{}:{outputModalities:[...a.outputModalities]},...a.nativeTools===void 0?{}:{nativeTools:[...a.nativeTools]}}));if(f(u,n.INVALID_MODEL_INFO)>o)throw new t(`route "${r}" model metadata exceeds the configured registry limit`,n.INVALID_MODEL_INFO);return u}function s(e,t,n){if(n.reasoning===void 0)return;let r=n.reasoning.efforts.map(e=>e.id);if(r.length===0||new Set(r).size!==r.length||n.reasoning.efforts.some(e=>typeof e.id!=`string`||e.id.length===0||typeof e.name!=`string`||e.name.length===0))throw l(e,t,`empty or duplicated reasoning efforts`);if(n.reasoning.defaultEffort!==void 0&&!r.includes(n.reasoning.defaultEffort))throw l(e,t,`a default reasoning effort it does not offer`)}function c(e,t,n){for(let[r,i]of[[`input modalities`,n.inputModalities],[`output modalities`,n.outputModalities],[`native tools`,n.nativeTools]])if(i!==void 0&&(new Set(i).size!==i.length||i.some(e=>typeof e!=`string`||e.length===0)))throw l(e,t,`invalid ${r}`)}function l(e,r,i){return new t(`route "${e}" resolved model "${r}" with ${i}`,n.INVALID_MODEL_INFO)}function u(e,r){let i=e.reasoningEffort??r.reasoning?.defaultEffort;if(e.reasoningEffort!==void 0&&r.reasoning?.efforts.some(t=>t.id===e.reasoningEffort)!==!0)throw new t(`model "${r.id}" on route "${r.provider}" does not offer reasoning effort "${e.reasoningEffort}"`,n.UNSUPPORTED_REASONING_EFFORT);let a=e.maxTokens??r.defaultMaxTokens;if(a!==void 0&&r.maxOutputTokens!==void 0&&a>r.maxOutputTokens)throw new t(`model "${r.id}" on route "${r.provider}" supports at most ${r.maxOutputTokens} output tokens, received ${a}`,n.OUTPUT_TOKEN_LIMIT_EXCEEDED);if(a!==void 0&&r.context!==void 0&&a>=r.context.contextWindow)throw new t(`model "${r.id}" on route "${r.provider}" cannot reserve ${a} output tokens inside its ${r.context.contextWindow}-token combined context window`,n.OUTPUT_TOKEN_LIMIT_EXCEEDED);return{config:{provider:e.provider,model:e.model,...i===void 0?{}:{reasoningEffort:i},...e.temperature===void 0?{}:{temperature:e.temperature},...e.topP===void 0?{}:{topP:e.topP},...a===void 0?{}:{maxTokens:a},...e.stop===void 0?{}:{stop:[...e.stop]}},context:r.context}}function d(e,t,n){let i=e.messages.map(e=>{let i=e.source;return e.role!==`assistant`||i.kind!==`model`||i.replayState===void 0||n(i.provider)===t?e:r({...e,source:{kind:`model`,provider:i.provider,model:i.model}})});return i.every((t,n)=>t===e.messages[n])?e:{...e,messages:i}}function f(e,n){let r;try{r=JSON.stringify(e)}catch(e){throw new t(`adapter model metadata must be JSON-serializable`,n,{cause:e})}if(r===void 0)throw new t(`adapter model metadata must be JSON-serializable`,n);return new TextEncoder().encode(r).byteLength}export{o as normalizeResolvedModelInfo,d as projectReplayForAdapter,u as resolveCallWithModelInfo,i as validateCatalogModels,a as validateModelCatalogSnapshot};
2
2
  //# sourceMappingURL=model-metadata.js.map