@skyold/model-protocol 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +22 -0
  3. package/README.zh-CN.md +17 -0
  4. package/dist/chat-egress.d.ts +12 -0
  5. package/dist/chat-egress.d.ts.map +1 -0
  6. package/dist/chat-egress.js +144 -0
  7. package/dist/chat-egress.js.map +1 -0
  8. package/dist/chat-ingress.d.ts +39 -0
  9. package/dist/chat-ingress.d.ts.map +1 -0
  10. package/dist/chat-ingress.js +323 -0
  11. package/dist/chat-ingress.js.map +1 -0
  12. package/dist/chat-stream-egress.d.ts +8 -0
  13. package/dist/chat-stream-egress.d.ts.map +1 -0
  14. package/dist/chat-stream-egress.js +129 -0
  15. package/dist/chat-stream-egress.js.map +1 -0
  16. package/dist/contracts.d.ts +61 -0
  17. package/dist/contracts.d.ts.map +1 -0
  18. package/dist/contracts.js +2 -0
  19. package/dist/contracts.js.map +1 -0
  20. package/dist/egress-codec-registry.d.ts +36 -0
  21. package/dist/egress-codec-registry.d.ts.map +1 -0
  22. package/dist/egress-codec-registry.js +125 -0
  23. package/dist/egress-codec-registry.js.map +1 -0
  24. package/dist/index.d.ts +39 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +25 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/ingress-codec-registry.d.ts +26 -0
  29. package/dist/ingress-codec-registry.d.ts.map +1 -0
  30. package/dist/ingress-codec-registry.js +106 -0
  31. package/dist/ingress-codec-registry.js.map +1 -0
  32. package/dist/media-images.d.ts +154 -0
  33. package/dist/media-images.d.ts.map +1 -0
  34. package/dist/media-images.js +721 -0
  35. package/dist/media-images.js.map +1 -0
  36. package/dist/media-video.d.ts +68 -0
  37. package/dist/media-video.d.ts.map +1 -0
  38. package/dist/media-video.js +196 -0
  39. package/dist/media-video.js.map +1 -0
  40. package/dist/native-images.d.ts +68 -0
  41. package/dist/native-images.d.ts.map +1 -0
  42. package/dist/native-images.js +424 -0
  43. package/dist/native-images.js.map +1 -0
  44. package/dist/openai-embeddings-egress.d.ts +4 -0
  45. package/dist/openai-embeddings-egress.d.ts.map +1 -0
  46. package/dist/openai-embeddings-egress.js +21 -0
  47. package/dist/openai-embeddings-egress.js.map +1 -0
  48. package/dist/openai-embeddings.d.ts +66 -0
  49. package/dist/openai-embeddings.d.ts.map +1 -0
  50. package/dist/openai-embeddings.js +442 -0
  51. package/dist/openai-embeddings.js.map +1 -0
  52. package/dist/openai-responses-egress.d.ts +17 -0
  53. package/dist/openai-responses-egress.d.ts.map +1 -0
  54. package/dist/openai-responses-egress.js +99 -0
  55. package/dist/openai-responses-egress.js.map +1 -0
  56. package/dist/openai-responses-stream-egress.d.ts +4 -0
  57. package/dist/openai-responses-stream-egress.d.ts.map +1 -0
  58. package/dist/openai-responses-stream-egress.js +252 -0
  59. package/dist/openai-responses-stream-egress.js.map +1 -0
  60. package/dist/openai-responses.d.ts +15 -0
  61. package/dist/openai-responses.d.ts.map +1 -0
  62. package/dist/openai-responses.js +363 -0
  63. package/dist/openai-responses.js.map +1 -0
  64. package/dist/provider-source.d.ts +20 -0
  65. package/dist/provider-source.d.ts.map +1 -0
  66. package/dist/provider-source.js +41 -0
  67. package/dist/provider-source.js.map +1 -0
  68. package/dist/provider-transport.d.ts +5 -0
  69. package/dist/provider-transport.d.ts.map +1 -0
  70. package/dist/provider-transport.js +114 -0
  71. package/dist/provider-transport.js.map +1 -0
  72. package/dist/runtime-v2-validation.d.ts +16 -0
  73. package/dist/runtime-v2-validation.d.ts.map +1 -0
  74. package/dist/runtime-v2-validation.js +915 -0
  75. package/dist/runtime-v2-validation.js.map +1 -0
  76. package/dist/runtime-v2.d.ts +462 -0
  77. package/dist/runtime-v2.d.ts.map +1 -0
  78. package/dist/runtime-v2.js +56 -0
  79. package/dist/runtime-v2.js.map +1 -0
  80. package/dist/tokenforge-task-projection.d.ts +8 -0
  81. package/dist/tokenforge-task-projection.d.ts.map +1 -0
  82. package/dist/tokenforge-task-projection.js +247 -0
  83. package/dist/tokenforge-task-projection.js.map +1 -0
  84. package/dist/tokenforge-tasks.d.ts +241 -0
  85. package/dist/tokenforge-tasks.d.ts.map +1 -0
  86. package/dist/tokenforge-tasks.js +1132 -0
  87. package/dist/tokenforge-tasks.js.map +1 -0
  88. package/dist/usage-reservation.d.ts +11 -0
  89. package/dist/usage-reservation.d.ts.map +1 -0
  90. package/dist/usage-reservation.js +40 -0
  91. package/dist/usage-reservation.js.map +1 -0
  92. package/dist/validation.d.ts +22 -0
  93. package/dist/validation.d.ts.map +1 -0
  94. package/dist/validation.js +415 -0
  95. package/dist/validation.js.map +1 -0
  96. package/dist/video-ingress.d.ts +31 -0
  97. package/dist/video-ingress.d.ts.map +1 -0
  98. package/dist/video-ingress.js +246 -0
  99. package/dist/video-ingress.js.map +1 -0
  100. package/dist/volc-video-task-codec.d.ts +59 -0
  101. package/dist/volc-video-task-codec.d.ts.map +1 -0
  102. package/dist/volc-video-task-codec.js +123 -0
  103. package/dist/volc-video-task-codec.js.map +1 -0
  104. package/package.json +54 -0
@@ -0,0 +1,915 @@
1
+ import { decodeImageGenerationProtocolSnapshotV1, decodeMediaTaskResultV2, parseImageGenerationCapabilityV1, } from './media-images.js';
2
+ export function validateFixedDispatchInput(input) {
3
+ if (!input.target.sourceId.trim()) {
4
+ throw new Error('SOURCE_ID_REQUIRED');
5
+ }
6
+ validateProviderDispatchInputV2(input);
7
+ }
8
+ export function validateProviderDispatchInputV2(input) {
9
+ if (!input.target.connectionRef.trim()) {
10
+ throw new Error('CONNECTION_REF_REQUIRED');
11
+ }
12
+ if (input.task.protocolFamily !== input.target.capability.protocolFamily ||
13
+ input.task.dispatchProtocolFamily !== input.target.capability.protocolFamily) {
14
+ throw new Error('PROTOCOL_FAMILY_MISMATCH');
15
+ }
16
+ if (input.target.capability.protocolFamily !== input.capability.protocolFamily) {
17
+ throw new Error('CAPABILITY_PROTOCOL_MISMATCH');
18
+ }
19
+ if (!capabilityMatchesTarget(input)) {
20
+ throw new Error('TARGET_CAPABILITY_MISMATCH');
21
+ }
22
+ if (input.task.taskKind !== input.capability.taskKind) {
23
+ throw new Error('TASK_KIND_MISMATCH');
24
+ }
25
+ if (!input.capability.executionModes.includes(input.task.executionMode)) {
26
+ throw new Error('EXECUTION_MODE_MISMATCH');
27
+ }
28
+ if (!modalitiesMatch(input.task.inputModalities, input.capability.inputModalities)) {
29
+ throw new Error('INPUT_MODALITY_MISMATCH');
30
+ }
31
+ if (!modalitiesMatch(input.task.outputModalities, input.capability.outputModalities)) {
32
+ throw new Error('OUTPUT_MODALITY_MISMATCH');
33
+ }
34
+ }
35
+ function capabilityMatchesTarget(input) {
36
+ const { capability, target } = input;
37
+ return (target.provider === capability.provider &&
38
+ target.providerModel === capability.model &&
39
+ target.capability.taskKind === capability.taskKind &&
40
+ target.capability.protocolFamily === capability.protocolFamily &&
41
+ sameValues(target.capability.inputModalities, capability.inputModalities) &&
42
+ sameValues(target.capability.outputModalities, capability.outputModalities) &&
43
+ sameValues(target.capability.executionModes, capability.executionModes) &&
44
+ sameValues(target.capability.features, capability.features) &&
45
+ sameOptionalValues(target.capability.operations, capability.operations) &&
46
+ embeddingCapabilitiesMatch(target.capability.embeddingCapability, capability.embeddingCapability) &&
47
+ imageGenerationCapabilitiesMatch(target.capability.imageGenerationCapability, capability.imageGenerationCapability) &&
48
+ imageEditingCapabilitiesMatch(target.capability.imageEditingCapability, capability.imageEditingCapability) &&
49
+ imageUsageReportingCapabilitiesMatch(target.capability.imageUsageReportingCapability, capability.imageUsageReportingCapability) &&
50
+ target.connectionRef === capability.dispatchRef &&
51
+ capability.active);
52
+ }
53
+ function imageUsageReportingCapabilitiesMatch(left, right) {
54
+ if (left === undefined || right === undefined)
55
+ return left === right;
56
+ return (left.schemaVersion === right.schemaVersion &&
57
+ sameValueSet(left.guaranteedUnits, right.guaranteedUnits));
58
+ }
59
+ function imageEditingCapabilitiesMatch(left, right) {
60
+ if (left === undefined || right === undefined)
61
+ return left === right;
62
+ return (left.maxInputImages === right.maxInputImages &&
63
+ left.supportsMask === right.supportsMask &&
64
+ sameValueSet(left.inputMimeTypes, right.inputMimeTypes));
65
+ }
66
+ function imageGenerationCapabilitiesMatch(left, right) {
67
+ if (left === undefined || right === undefined)
68
+ return left === right;
69
+ const parsedLeft = parseImageGenerationCapabilityV1(left);
70
+ const parsedRight = parseImageGenerationCapabilityV1(right);
71
+ if (parsedLeft === null || parsedRight === null)
72
+ return false;
73
+ return (parsedLeft.schemaVersion === parsedRight.schemaVersion &&
74
+ parsedLeft.minCount === parsedRight.minCount &&
75
+ parsedLeft.maxCount === parsedRight.maxCount &&
76
+ parsedLeft.maxPromptUtf8Bytes === parsedRight.maxPromptUtf8Bytes &&
77
+ parsedLeft.certifiedModelRevision === parsedRight.certifiedModelRevision &&
78
+ sameValueSet(parsedLeft.supportedPolicies, parsedRight.supportedPolicies) &&
79
+ sameValueSet(parsedLeft.responseFormats, parsedRight.responseFormats) &&
80
+ sameValueSet(parsedLeft.outputFormats, parsedRight.outputFormats) &&
81
+ sameOptionalValueSet(parsedLeft.allowedBackgrounds, parsedRight.allowedBackgrounds) &&
82
+ formatMappingsMatch(parsedLeft.requestMapping.responseFormat, parsedRight.requestMapping.responseFormat) &&
83
+ formatMappingsMatch(parsedLeft.requestMapping.outputFormat, parsedRight.requestMapping.outputFormat) &&
84
+ sameValueSet(parsedLeft.requestMapping.providerOptions.openaiImages, parsedRight.requestMapping.providerOptions.openaiImages) &&
85
+ sameValueSet(parsedLeft.requestMapping.providerOptions.volcImages, parsedRight.requestMapping.providerOptions.volcImages) &&
86
+ sameValueSet(parsedLeft.qualities, parsedRight.qualities) &&
87
+ sameValueSet(parsedLeft.allowedSizes.map((size) => `${size.width}x${size.height}`), parsedRight.allowedSizes.map((size) => `${size.width}x${size.height}`)));
88
+ }
89
+ function sameOptionalValueSet(left, right) {
90
+ if (left === undefined || right === undefined)
91
+ return left === right;
92
+ return sameValueSet(left, right);
93
+ }
94
+ function formatMappingsMatch(left, right) {
95
+ if (left.mode !== right.mode)
96
+ return false;
97
+ return left.mode === 'parameter'
98
+ ? left.defaultValue === right.defaultValue
99
+ : left.value === right.value;
100
+ }
101
+ function sameOptionalValues(left, right) {
102
+ if (left === undefined || right === undefined)
103
+ return left === right;
104
+ return sameValues(left, right);
105
+ }
106
+ function embeddingCapabilitiesMatch(left, right) {
107
+ if (left === undefined || right === undefined) {
108
+ return left === right;
109
+ }
110
+ return (left.schemaVersion === right.schemaVersion &&
111
+ left.nativeDimensions === right.nativeDimensions &&
112
+ sameValues(left.allowedDimensions, right.allowedDimensions) &&
113
+ sameValues(left.encodingFormats, right.encodingFormats) &&
114
+ left.normalized === right.normalized &&
115
+ left.maxBatchItems === right.maxBatchItems &&
116
+ left.maxInputTokensPerItem === right.maxInputTokensPerItem &&
117
+ left.maxTotalInputTokens === right.maxTotalInputTokens &&
118
+ sameValues(left.inputEncodings, right.inputEncodings) &&
119
+ left.compatibilitySpace.provider === right.compatibilitySpace.provider &&
120
+ left.compatibilitySpace.model === right.compatibilitySpace.model &&
121
+ left.compatibilitySpace.modelVersion === right.compatibilitySpace.modelVersion &&
122
+ left.compatibilitySpace.dimensions === right.compatibilitySpace.dimensions &&
123
+ left.compatibilitySpace.preprocessingVersion ===
124
+ right.compatibilitySpace.preprocessingVersion &&
125
+ left.compatibilitySpace.spaceId === right.compatibilitySpace.spaceId);
126
+ }
127
+ export function validateProviderExecutionStart(input, expectedTaskKind) {
128
+ const value = runtimeRecord(input, 'ADAPTER_EXECUTION_START_INVALID');
129
+ validateProviderAcceptance(value['acceptance'], 'ADAPTER_EXECUTION_START_INVALID');
130
+ validateProviderResponseMetadata(value['responseMetadata'], 'ADAPTER_EXECUTION_START_INVALID');
131
+ if (value['kind'] !== 'sync' && value['kind'] !== 'stream') {
132
+ throw new Error('ADAPTER_EXECUTION_START_INVALID');
133
+ }
134
+ if (input.kind === 'sync') {
135
+ assertOnlyKeys(value, ['kind', 'acceptance', 'responseMetadata', 'terminal'], 'ADAPTER_EXECUTION_START_INVALID');
136
+ validateAdapterTerminalOutcome(input.terminal, expectedTaskKind);
137
+ validateTerminalAcceptance(input.acceptance, input.terminal);
138
+ return input;
139
+ }
140
+ if (!isAsyncIterable(value['events']) ||
141
+ !isPromiseLike(value['terminal']) ||
142
+ typeof value['abort'] !== 'function') {
143
+ throw new Error('ADAPTER_EXECUTION_START_INVALID');
144
+ }
145
+ assertOnlyKeys(value, ['kind', 'acceptance', 'responseMetadata', 'events', 'terminal', 'abort'], 'ADAPTER_EXECUTION_START_INVALID');
146
+ return {
147
+ ...input,
148
+ events: validateStreamEvents(input.events),
149
+ terminal: input.terminal.then((terminal) => {
150
+ validateAdapterTerminalOutcome(terminal, expectedTaskKind);
151
+ validateTerminalAcceptance(input.acceptance, terminal);
152
+ return terminal;
153
+ }),
154
+ };
155
+ }
156
+ /**
157
+ * Runtime boundary for third-party or dynamically registered Adapter streams.
158
+ * Invalid Provider-specific data must fail before it becomes a normalized Host fact.
159
+ */
160
+ export function validateNormalizedStreamEvent(input) {
161
+ const value = runtimeRecord(input, 'ADAPTER_STREAM_EVENT_INVALID');
162
+ if (typeof value['type'] !== 'string' ||
163
+ !requiredString(value['eventId']) ||
164
+ !nonNegativeInteger(value['sequenceNumber']) ||
165
+ !requiredString(value['responseId'])) {
166
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
167
+ }
168
+ switch (value['type']) {
169
+ case 'response.started':
170
+ assertStreamEventKeys(value, []);
171
+ break;
172
+ case 'response.in_progress':
173
+ assertStreamEventKeys(value, ['status']);
174
+ requireLiteral(value['status'], 'in_progress');
175
+ break;
176
+ case 'output.item.added':
177
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'itemKind', 'item']);
178
+ validateIndexedItem(value);
179
+ validateOutputItemKind(value['itemKind']);
180
+ validateNormalizedOutputItem(value['item']);
181
+ validateOutputItemKindMatch(value['itemKind'], value['item']);
182
+ break;
183
+ case 'output.text.delta':
184
+ case 'output.refusal.delta':
185
+ case 'output.reasoning_summary.delta':
186
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'contentIndex', 'delta']);
187
+ validateIndexedContent(value);
188
+ requireString(value['delta']);
189
+ break;
190
+ case 'output.tool_call.delta':
191
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'callId', 'name', 'argumentsDelta']);
192
+ validateIndexedItem(value);
193
+ requireNonEmptyString(value['callId']);
194
+ optionalRequiredString(value['name']);
195
+ requireString(value['argumentsDelta']);
196
+ break;
197
+ case 'output.content_part.added':
198
+ case 'output.content_part.completed':
199
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'contentIndex', 'part']);
200
+ validateIndexedContent(value);
201
+ validateNormalizedContentPart(value['part']);
202
+ break;
203
+ case 'output.item.completed':
204
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'itemKind', 'status', 'item']);
205
+ validateIndexedItem(value);
206
+ validateOutputItemKind(value['itemKind']);
207
+ if (value['status'] !== 'completed' && value['status'] !== 'incomplete') {
208
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
209
+ }
210
+ validateNormalizedOutputItem(value['item']);
211
+ validateOutputItemKindMatch(value['itemKind'], value['item']);
212
+ break;
213
+ case 'output.text.completed':
214
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'contentIndex', 'text']);
215
+ validateIndexedContent(value);
216
+ requireString(value['text']);
217
+ break;
218
+ case 'output.refusal.completed':
219
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'contentIndex', 'refusal']);
220
+ validateIndexedContent(value);
221
+ requireString(value['refusal']);
222
+ break;
223
+ case 'output.tool_call.completed':
224
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'callId', 'name', 'arguments']);
225
+ validateIndexedItem(value);
226
+ requireNonEmptyString(value['callId']);
227
+ requireNonEmptyString(value['name']);
228
+ requireString(value['arguments']);
229
+ break;
230
+ case 'output.reasoning_summary.completed':
231
+ assertStreamEventKeys(value, ['itemId', 'outputIndex', 'contentIndex', 'text']);
232
+ validateIndexedContent(value);
233
+ requireString(value['text']);
234
+ break;
235
+ case 'usage.updated':
236
+ assertStreamEventKeys(value, ['usage']);
237
+ validateNormalizedUsage(value['usage']);
238
+ break;
239
+ case 'response.incomplete':
240
+ assertStreamEventKeys(value, ['reason', 'status', 'incompleteDetails', 'usage']);
241
+ requireNonEmptyString(value['reason']);
242
+ if (value['status'] !== undefined)
243
+ requireLiteral(value['status'], 'incomplete');
244
+ validateOptionalIncompleteDetails(value['incompleteDetails']);
245
+ validateOptionalUsage(value['usage']);
246
+ break;
247
+ case 'response.completed':
248
+ assertStreamEventKeys(value, ['status', 'usage']);
249
+ if (value['status'] !== undefined)
250
+ requireLiteral(value['status'], 'completed');
251
+ validateOptionalUsage(value['usage']);
252
+ break;
253
+ case 'response.cancelled':
254
+ assertStreamEventKeys(value, ['status', 'usage']);
255
+ requireLiteral(value['status'], 'cancelled');
256
+ validateOptionalUsage(value['usage']);
257
+ break;
258
+ case 'response.failed': {
259
+ assertStreamEventKeys(value, ['status', 'error', 'providerError', 'usage']);
260
+ if (value['status'] !== undefined)
261
+ requireLiteral(value['status'], 'failed');
262
+ const error = runtimeRecord(value['error'], 'ADAPTER_STREAM_EVENT_INVALID');
263
+ assertOnlyKeys(error, ['code', 'category', 'retryable'], 'ADAPTER_STREAM_EVENT_INVALID');
264
+ requireNonEmptyString(error['code']);
265
+ requireNonEmptyString(error['category']);
266
+ if (typeof error['retryable'] !== 'boolean') {
267
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
268
+ }
269
+ validateOptionalProviderError(value['providerError']);
270
+ validateOptionalUsage(value['usage']);
271
+ break;
272
+ }
273
+ default:
274
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
275
+ }
276
+ return input;
277
+ }
278
+ /** Runtime-validates terminal facts before Engine exposes them to a Host. */
279
+ export function validateAdapterTerminalOutcome(input, expectedTaskKind) {
280
+ const value = runtimeRecord(input, 'ADAPTER_TERMINAL_INVALID');
281
+ assertOnlyKeys(value, [
282
+ 'status',
283
+ 'acceptanceState',
284
+ 'failureOrigin',
285
+ 'failureCode',
286
+ 'retryable',
287
+ 'result',
288
+ 'usage',
289
+ 'incompleteDetails',
290
+ 'providerError',
291
+ 'normalizedResponse',
292
+ ], 'ADAPTER_TERMINAL_INVALID');
293
+ if (!['succeeded', 'failed', 'cancelled', 'incomplete'].includes(String(value['status'])) ||
294
+ !['accepted', 'not-accepted', 'unknown'].includes(String(value['acceptanceState'])) ||
295
+ typeof value['retryable'] !== 'boolean') {
296
+ throw new Error('ADAPTER_TERMINAL_INVALID');
297
+ }
298
+ if (value['status'] === 'succeeded' && value['acceptanceState'] !== 'accepted') {
299
+ throw new Error('ADAPTER_SUCCEEDED_WITHOUT_ACCEPTANCE');
300
+ }
301
+ optionalNonEmptyStringOrThrow(value['failureOrigin'], 'ADAPTER_TERMINAL_INVALID');
302
+ optionalNonEmptyStringOrThrow(value['failureCode'], 'ADAPTER_TERMINAL_INVALID');
303
+ validateOptionalUsage(value['usage'], 'ADAPTER_TERMINAL_INVALID');
304
+ validateOptionalIncompleteDetails(value['incompleteDetails'], 'ADAPTER_TERMINAL_INVALID');
305
+ validateOptionalProviderError(value['providerError'], 'ADAPTER_TERMINAL_INVALID');
306
+ const result = value['result'] === undefined ? undefined : validateNormalizedResult(value['result']);
307
+ if (result !== undefined &&
308
+ expectedTaskKind !== undefined &&
309
+ result.taskKind !== expectedTaskKind) {
310
+ throw new Error('ADAPTER_TERMINAL_TASK_KIND_MISMATCH');
311
+ }
312
+ if (result?.usage !== undefined &&
313
+ value['usage'] !== undefined &&
314
+ !sameNormalizedUsage(result.usage, value['usage'])) {
315
+ throw new Error('ADAPTER_TERMINAL_USAGE_MISMATCH');
316
+ }
317
+ if (value['normalizedResponse'] !== undefined) {
318
+ const response = validateNormalizedResponsesSyncResponse(value['normalizedResponse']);
319
+ if (!normalizedResponseStatusMatchesTerminal(response.status, String(value['status']))) {
320
+ throw new Error('ADAPTER_TERMINAL_RESPONSE_STATUS_MISMATCH');
321
+ }
322
+ if (response.usage !== undefined &&
323
+ value['usage'] !== undefined &&
324
+ !sameNormalizedUsage(response.usage, value['usage'])) {
325
+ throw new Error('ADAPTER_TERMINAL_USAGE_MISMATCH');
326
+ }
327
+ }
328
+ return input;
329
+ }
330
+ function validateNormalizedResult(value) {
331
+ const result = runtimeRecord(value, 'ADAPTER_TERMINAL_INVALID');
332
+ if (result['taskKind'] === 'chat') {
333
+ assertOnlyKeys(result, ['taskKind', 'output', 'usage'], 'ADAPTER_TERMINAL_INVALID');
334
+ validateChatOutput(result['output']);
335
+ }
336
+ else if (result['taskKind'] === 'embedding') {
337
+ assertOnlyKeys(result, ['taskKind', 'output', 'usage'], 'ADAPTER_TERMINAL_INVALID');
338
+ validateEmbeddingOutput(result['output'], result['usage']);
339
+ }
340
+ else if (result['taskKind'] === 'image_generation') {
341
+ assertOnlyKeys(result, ['taskKind', 'output', 'usage', 'protocolSnapshot'], 'ADAPTER_TERMINAL_INVALID');
342
+ let output;
343
+ try {
344
+ output = decodeMediaTaskResultV2(result['output']);
345
+ if (result['protocolSnapshot'] !== undefined) {
346
+ const snapshot = decodeImageGenerationProtocolSnapshotV1(result['protocolSnapshot']);
347
+ if (snapshot.items.length !== output.items.length) {
348
+ throw new Error('ADAPTER_TERMINAL_INVALID');
349
+ }
350
+ }
351
+ }
352
+ catch {
353
+ throw new Error('ADAPTER_TERMINAL_INVALID');
354
+ }
355
+ const usage = result['usage'];
356
+ if (usage !== undefined &&
357
+ runtimeRecord(usage, 'ADAPTER_TERMINAL_INVALID')['imageCount'] !== undefined &&
358
+ runtimeRecord(usage, 'ADAPTER_TERMINAL_INVALID')['imageCount'] !== output.items.length) {
359
+ throw new Error('ADAPTER_TERMINAL_INVALID');
360
+ }
361
+ }
362
+ else {
363
+ throw new Error('ADAPTER_TERMINAL_INVALID');
364
+ }
365
+ validateOptionalUsage(result['usage'], 'ADAPTER_TERMINAL_INVALID');
366
+ return value;
367
+ }
368
+ function validateChatOutput(value) {
369
+ const output = runtimeRecord(value, 'ADAPTER_TERMINAL_INVALID');
370
+ assertOnlyKeys(output, ['items', 'finishReason', 'incompleteReason'], 'ADAPTER_TERMINAL_INVALID');
371
+ if (!Array.isArray(output['items']) || !requiredString(output['finishReason'])) {
372
+ throw new Error('ADAPTER_TERMINAL_INVALID');
373
+ }
374
+ optionalNonEmptyStringOrThrow(output['incompleteReason'], 'ADAPTER_TERMINAL_INVALID');
375
+ for (const raw of output['items']) {
376
+ const item = runtimeRecord(raw, 'ADAPTER_TERMINAL_INVALID');
377
+ if (item['type'] === 'text' || item['type'] === 'refusal') {
378
+ assertOnlyKeys(item, ['type', 'text'], 'ADAPTER_TERMINAL_INVALID');
379
+ if (typeof item['text'] !== 'string')
380
+ throw new Error('ADAPTER_TERMINAL_INVALID');
381
+ }
382
+ else if (item['type'] === 'function_call') {
383
+ assertOnlyKeys(item, ['type', 'callId', 'name', 'arguments'], 'ADAPTER_TERMINAL_INVALID');
384
+ if (!requiredString(item['callId']) ||
385
+ !requiredString(item['name']) ||
386
+ typeof item['arguments'] !== 'string') {
387
+ throw new Error('ADAPTER_TERMINAL_INVALID');
388
+ }
389
+ }
390
+ else {
391
+ throw new Error('ADAPTER_TERMINAL_INVALID');
392
+ }
393
+ }
394
+ }
395
+ function validateEmbeddingOutput(value, rawUsage) {
396
+ const output = runtimeRecord(value, 'ADAPTER_TERMINAL_INVALID');
397
+ assertOnlyKeys(output, ['vectors', 'dimensions', 'encodingFormat', 'spaceId'], 'ADAPTER_TERMINAL_INVALID');
398
+ if (!Array.isArray(output['vectors']) ||
399
+ output['vectors'].length === 0 ||
400
+ !positiveInteger(output['dimensions']) ||
401
+ (output['encodingFormat'] !== 'float' && output['encodingFormat'] !== 'base64') ||
402
+ !requiredString(output['spaceId'])) {
403
+ throw new Error('ADAPTER_TERMINAL_INVALID');
404
+ }
405
+ const dimensions = output['dimensions'];
406
+ const indices = new Set();
407
+ for (const raw of output['vectors']) {
408
+ const vector = runtimeRecord(raw, 'ADAPTER_TERMINAL_INVALID');
409
+ assertOnlyKeys(vector, ['index', 'vector'], 'ADAPTER_TERMINAL_INVALID');
410
+ if (!nonNegativeInteger(vector['index']) || indices.has(vector['index'])) {
411
+ throw new Error('ADAPTER_TERMINAL_INVALID');
412
+ }
413
+ indices.add(vector['index']);
414
+ if (output['encodingFormat'] === 'float') {
415
+ if (!Array.isArray(vector['vector']) ||
416
+ vector['vector'].length !== dimensions ||
417
+ vector['vector'].some((entry) => typeof entry !== 'number' || !Number.isFinite(entry))) {
418
+ throw new Error('ADAPTER_TERMINAL_INVALID');
419
+ }
420
+ }
421
+ else if (!validFloat32Base64(vector['vector'], dimensions)) {
422
+ throw new Error('ADAPTER_TERMINAL_INVALID');
423
+ }
424
+ }
425
+ if (rawUsage !== undefined) {
426
+ const usage = runtimeRecord(rawUsage, 'ADAPTER_TERMINAL_INVALID');
427
+ if ((usage['vectorCount'] !== undefined && usage['vectorCount'] !== output['vectors'].length) ||
428
+ (usage['dimensions'] !== undefined && usage['dimensions'] !== dimensions) ||
429
+ (usage['encodingFormat'] !== undefined &&
430
+ usage['encodingFormat'] !== output['encodingFormat']) ||
431
+ (usage['spaceId'] !== undefined && usage['spaceId'] !== output['spaceId'])) {
432
+ throw new Error('ADAPTER_TERMINAL_INVALID');
433
+ }
434
+ }
435
+ }
436
+ function validateNormalizedResponsesSyncResponse(value) {
437
+ const response = runtimeRecord(value, 'ADAPTER_TERMINAL_INVALID');
438
+ assertOnlyKeys(response, [
439
+ 'protocolFamily',
440
+ 'id',
441
+ 'object',
442
+ 'status',
443
+ 'model',
444
+ 'store',
445
+ 'output',
446
+ 'usage',
447
+ 'incompleteDetails',
448
+ 'error',
449
+ ], 'ADAPTER_TERMINAL_INVALID');
450
+ if (response['protocolFamily'] !== 'openai-responses/v1' ||
451
+ !requiredString(response['id']) ||
452
+ response['object'] !== 'response' ||
453
+ !['completed', 'incomplete', 'failed', 'cancelled'].includes(String(response['status'])) ||
454
+ response['store'] !== false ||
455
+ !Array.isArray(response['output']) ||
456
+ !optionalNonEmptyString(response['model'])) {
457
+ throw new Error('ADAPTER_TERMINAL_INVALID');
458
+ }
459
+ for (const item of response['output'])
460
+ validateNormalizedResponsesOutputItem(item);
461
+ validateOptionalUsage(response['usage'], 'ADAPTER_TERMINAL_INVALID');
462
+ validateOptionalIncompleteDetails(response['incompleteDetails'], 'ADAPTER_TERMINAL_INVALID');
463
+ validateOptionalProviderError(response['error'], 'ADAPTER_TERMINAL_INVALID');
464
+ if ((response['status'] === 'incomplete' && response['incompleteDetails'] === undefined) ||
465
+ (response['status'] === 'failed' && response['error'] === undefined) ||
466
+ (response['status'] !== 'incomplete' && response['incompleteDetails'] !== undefined) ||
467
+ (response['status'] !== 'failed' && response['error'] !== undefined)) {
468
+ throw new Error('ADAPTER_TERMINAL_INVALID');
469
+ }
470
+ return value;
471
+ }
472
+ function validateNormalizedResponsesOutputItem(value) {
473
+ const item = runtimeRecord(value, 'ADAPTER_TERMINAL_INVALID');
474
+ if (!requiredString(item['id']) || !validResponsesOutputStatus(item['status'])) {
475
+ throw new Error('ADAPTER_TERMINAL_INVALID');
476
+ }
477
+ if (item['type'] === 'message') {
478
+ assertOnlyKeys(item, ['id', 'type', 'status', 'role', 'content'], 'ADAPTER_TERMINAL_INVALID');
479
+ if ((item['role'] !== undefined && item['role'] !== 'assistant') ||
480
+ !Array.isArray(item['content'])) {
481
+ throw new Error('ADAPTER_TERMINAL_INVALID');
482
+ }
483
+ for (const rawPart of item['content']) {
484
+ const part = runtimeRecord(rawPart, 'ADAPTER_TERMINAL_INVALID');
485
+ if (part['type'] === 'output_text') {
486
+ assertOnlyKeys(part, ['type', 'text'], 'ADAPTER_TERMINAL_INVALID');
487
+ if (typeof part['text'] !== 'string')
488
+ throw new Error('ADAPTER_TERMINAL_INVALID');
489
+ }
490
+ else if (part['type'] === 'refusal') {
491
+ assertOnlyKeys(part, ['type', 'refusal'], 'ADAPTER_TERMINAL_INVALID');
492
+ if (typeof part['refusal'] !== 'string')
493
+ throw new Error('ADAPTER_TERMINAL_INVALID');
494
+ }
495
+ else {
496
+ throw new Error('ADAPTER_TERMINAL_INVALID');
497
+ }
498
+ }
499
+ return;
500
+ }
501
+ if (item['type'] === 'reasoning') {
502
+ assertOnlyKeys(item, ['id', 'type', 'status', 'summary'], 'ADAPTER_TERMINAL_INVALID');
503
+ if (!Array.isArray(item['summary']))
504
+ throw new Error('ADAPTER_TERMINAL_INVALID');
505
+ for (const rawPart of item['summary']) {
506
+ const part = runtimeRecord(rawPart, 'ADAPTER_TERMINAL_INVALID');
507
+ assertOnlyKeys(part, ['type', 'text'], 'ADAPTER_TERMINAL_INVALID');
508
+ if (part['type'] !== 'summary_text' || typeof part['text'] !== 'string') {
509
+ throw new Error('ADAPTER_TERMINAL_INVALID');
510
+ }
511
+ }
512
+ return;
513
+ }
514
+ if (item['type'] === 'function_call') {
515
+ assertOnlyKeys(item, ['id', 'type', 'status', 'callId', 'name', 'arguments'], 'ADAPTER_TERMINAL_INVALID');
516
+ if (!requiredString(item['callId']) ||
517
+ !requiredString(item['name']) ||
518
+ typeof item['arguments'] !== 'string') {
519
+ throw new Error('ADAPTER_TERMINAL_INVALID');
520
+ }
521
+ return;
522
+ }
523
+ throw new Error('ADAPTER_TERMINAL_INVALID');
524
+ }
525
+ function validResponsesOutputStatus(value) {
526
+ return value === 'in_progress' || value === 'completed' || value === 'incomplete';
527
+ }
528
+ function normalizedResponseStatusMatchesTerminal(responseStatus, terminalStatus) {
529
+ return ((responseStatus === 'completed' && terminalStatus === 'succeeded') ||
530
+ responseStatus === terminalStatus);
531
+ }
532
+ function validFloat32Base64(value, dimensions) {
533
+ if (typeof value !== 'string' || value.length !== 4 * Math.ceil((dimensions * 4) / 3)) {
534
+ return false;
535
+ }
536
+ return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value);
537
+ }
538
+ function sameNormalizedUsage(left, right) {
539
+ const fields = [
540
+ 'inputTokens',
541
+ 'outputTokens',
542
+ 'totalTokens',
543
+ 'cachedInputTokens',
544
+ 'cacheCreationInputTokens',
545
+ 'cacheCreation5mInputTokens',
546
+ 'cacheCreation1hInputTokens',
547
+ 'reasoningOutputTokens',
548
+ 'vectorCount',
549
+ 'dimensions',
550
+ 'encodingFormat',
551
+ 'spaceId',
552
+ 'requests',
553
+ 'imageCount',
554
+ 'estimated',
555
+ ];
556
+ if (fields.some((field) => left[field] !== right[field]))
557
+ return false;
558
+ return (sameUsageDetails(left.inputTokenDetails, right.inputTokenDetails) &&
559
+ sameUsageDetails(left.outputTokenDetails, right.outputTokenDetails));
560
+ }
561
+ function sameUsageDetails(left, right) {
562
+ if (left === undefined || right === undefined)
563
+ return left === right;
564
+ return ['cachedTokens', 'reasoningTokens', 'imageTokens', 'textTokens'].every((field) => left[field] === right[field]);
565
+ }
566
+ export function validateProviderAsyncJobStart(input) {
567
+ const value = runtimeRecord(input, 'ADAPTER_ASYNC_START_INVALID');
568
+ assertOnlyKeys(value, ['kind', 'acceptance', 'responseMetadata', 'providerJobId', 'failureCode', 'retryable'], 'ADAPTER_ASYNC_START_INVALID');
569
+ const acceptance = runtimeRecord(value['acceptance'], 'ADAPTER_ASYNC_START_INVALID');
570
+ assertOnlyKeys(acceptance, ['state'], 'ADAPTER_ASYNC_START_INVALID');
571
+ validateProviderResponseMetadata(value['responseMetadata'], 'ADAPTER_ASYNC_START_INVALID');
572
+ if (value['kind'] === 'async') {
573
+ assertOnlyKeys(value, ['kind', 'acceptance', 'responseMetadata', 'providerJobId'], 'ADAPTER_ASYNC_START_INVALID');
574
+ if (acceptance['state'] !== 'accepted' ||
575
+ typeof value['providerJobId'] !== 'string' ||
576
+ !value['providerJobId'].trim()) {
577
+ throw new Error('ADAPTER_ASYNC_START_INVALID');
578
+ }
579
+ return input;
580
+ }
581
+ if (value['kind'] !== 'failed' ||
582
+ (acceptance['state'] !== 'not-accepted' && acceptance['state'] !== 'unknown') ||
583
+ typeof value['failureCode'] !== 'string' ||
584
+ !value['failureCode'].trim() ||
585
+ typeof value['retryable'] !== 'boolean') {
586
+ throw new Error('ADAPTER_ASYNC_START_INVALID');
587
+ }
588
+ assertOnlyKeys(value, ['kind', 'acceptance', 'responseMetadata', 'failureCode', 'retryable'], 'ADAPTER_ASYNC_START_INVALID');
589
+ return input;
590
+ }
591
+ export function validateProviderAsyncJobSnapshot(input) {
592
+ const value = runtimeRecord(input, 'ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
593
+ assertOnlyKeys(value, [
594
+ 'providerJobId',
595
+ 'model',
596
+ 'status',
597
+ 'createdAt',
598
+ 'updatedAt',
599
+ 'videoUrl',
600
+ 'lastFrameUrl',
601
+ 'usage',
602
+ 'error',
603
+ ], 'ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
604
+ const validStatuses = new Set(['queued', 'running', 'cancelled', 'succeeded', 'failed']);
605
+ if (typeof value['providerJobId'] !== 'string' ||
606
+ !value['providerJobId'].trim() ||
607
+ typeof value['model'] !== 'string' ||
608
+ !value['model'].trim() ||
609
+ typeof value['status'] !== 'string' ||
610
+ !validStatuses.has(value['status']) ||
611
+ !nonNegativeInteger(value['createdAt']) ||
612
+ !nonNegativeInteger(value['updatedAt']) ||
613
+ value['updatedAt'] < value['createdAt'] ||
614
+ !optionalNonEmptyString(value['videoUrl']) ||
615
+ !optionalNonEmptyString(value['lastFrameUrl'])) {
616
+ throw new Error('ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
617
+ }
618
+ if (value['usage'] !== undefined) {
619
+ const usage = runtimeRecord(value['usage'], 'ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
620
+ assertOnlyKeys(usage, ['completionTokens', 'totalTokens'], 'ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
621
+ if (!nonNegativeInteger(usage['completionTokens']) ||
622
+ !nonNegativeInteger(usage['totalTokens']) ||
623
+ usage['totalTokens'] < usage['completionTokens']) {
624
+ throw new Error('ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
625
+ }
626
+ }
627
+ if (value['error'] !== undefined) {
628
+ const error = runtimeRecord(value['error'], 'ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
629
+ assertOnlyKeys(error, ['code', 'message'], 'ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
630
+ if (typeof error['code'] !== 'string' ||
631
+ !error['code'].trim() ||
632
+ typeof error['message'] !== 'string' ||
633
+ !error['message'].trim()) {
634
+ throw new Error('ADAPTER_ASYNC_JOB_SNAPSHOT_INVALID');
635
+ }
636
+ }
637
+ return input;
638
+ }
639
+ export function validateProviderAsyncJobList(input) {
640
+ const value = runtimeRecord(input, 'ADAPTER_ASYNC_JOB_LIST_INVALID');
641
+ assertOnlyKeys(value, ['items', 'total'], 'ADAPTER_ASYNC_JOB_LIST_INVALID');
642
+ if (!Array.isArray(value['items']) || !nonNegativeInteger(value['total'])) {
643
+ throw new Error('ADAPTER_ASYNC_JOB_LIST_INVALID');
644
+ }
645
+ for (const item of value['items']) {
646
+ try {
647
+ validateProviderAsyncJobSnapshot(item);
648
+ }
649
+ catch {
650
+ throw new Error('ADAPTER_ASYNC_JOB_LIST_INVALID');
651
+ }
652
+ }
653
+ if (value['total'] < value['items'].length) {
654
+ throw new Error('ADAPTER_ASYNC_JOB_LIST_INVALID');
655
+ }
656
+ return input;
657
+ }
658
+ async function* validateStreamEvents(events) {
659
+ let responseId;
660
+ let previousSequence = -1;
661
+ let terminalSeen = false;
662
+ const eventIds = new Set();
663
+ for await (const event of events) {
664
+ const validated = validateNormalizedStreamEvent(event);
665
+ if (terminalSeen ||
666
+ (responseId !== undefined && validated.responseId !== responseId) ||
667
+ validated.sequenceNumber <= previousSequence ||
668
+ eventIds.has(validated.eventId)) {
669
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
670
+ }
671
+ responseId ??= validated.responseId;
672
+ previousSequence = validated.sequenceNumber;
673
+ eventIds.add(validated.eventId);
674
+ terminalSeen = isTerminalStreamEvent(validated.type);
675
+ yield validated;
676
+ }
677
+ }
678
+ function validateProviderAcceptance(value, errorCode) {
679
+ const acceptance = runtimeRecord(value, errorCode);
680
+ assertOnlyKeys(acceptance, ['state'], errorCode);
681
+ if (acceptance['state'] !== 'accepted' &&
682
+ acceptance['state'] !== 'not-accepted' &&
683
+ acceptance['state'] !== 'unknown') {
684
+ throw new Error(errorCode);
685
+ }
686
+ }
687
+ function validateIndexedItem(value) {
688
+ if (!requiredString(value['itemId']) || !nonNegativeInteger(value['outputIndex'])) {
689
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
690
+ }
691
+ }
692
+ function assertStreamEventKeys(value, extra) {
693
+ assertOnlyKeys(value, ['type', 'eventId', 'sequenceNumber', 'responseId', ...extra], 'ADAPTER_STREAM_EVENT_INVALID');
694
+ }
695
+ function validateIndexedContent(value) {
696
+ validateIndexedItem(value);
697
+ if (!nonNegativeInteger(value['contentIndex'])) {
698
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
699
+ }
700
+ }
701
+ function validateOutputItemKind(value) {
702
+ if (value !== 'message' && value !== 'reasoning' && value !== 'function_call') {
703
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
704
+ }
705
+ }
706
+ function validateOutputItemKindMatch(kind, item) {
707
+ const normalized = item;
708
+ if ((kind === 'function_call' && normalized.type !== 'function_call') ||
709
+ ((kind === 'message' || kind === 'reasoning') && normalized.type !== 'message')) {
710
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
711
+ }
712
+ }
713
+ function isTerminalStreamEvent(type) {
714
+ return (type === 'response.completed' ||
715
+ type === 'response.incomplete' ||
716
+ type === 'response.cancelled' ||
717
+ type === 'response.failed');
718
+ }
719
+ function validateNormalizedContentPart(value) {
720
+ const part = runtimeRecord(value, 'ADAPTER_STREAM_EVENT_INVALID');
721
+ assertOnlyKeys(part, ['type', 'text'], 'ADAPTER_STREAM_EVENT_INVALID');
722
+ if (part['type'] !== 'text' &&
723
+ part['type'] !== 'refusal' &&
724
+ part['type'] !== 'reasoning_summary') {
725
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
726
+ }
727
+ requireString(part['text']);
728
+ }
729
+ function validateNormalizedOutputItem(value) {
730
+ const item = runtimeRecord(value, 'ADAPTER_STREAM_EVENT_INVALID');
731
+ if (item['type'] === 'message') {
732
+ assertOnlyKeys(item, ['type', 'content'], 'ADAPTER_STREAM_EVENT_INVALID');
733
+ if (!Array.isArray(item['content']))
734
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
735
+ for (const part of item['content'])
736
+ validateNormalizedContentPart(part);
737
+ return;
738
+ }
739
+ if (item['type'] === 'function_call') {
740
+ assertOnlyKeys(item, ['type', 'callId', 'name', 'arguments'], 'ADAPTER_STREAM_EVENT_INVALID');
741
+ requireNonEmptyString(item['callId']);
742
+ requireNonEmptyString(item['name']);
743
+ requireString(item['arguments']);
744
+ return;
745
+ }
746
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
747
+ }
748
+ function validateNormalizedUsage(value, errorCode = 'ADAPTER_STREAM_EVENT_INVALID') {
749
+ const usage = runtimeRecord(value, errorCode);
750
+ assertOnlyKeys(usage, [
751
+ 'inputTokens',
752
+ 'outputTokens',
753
+ 'totalTokens',
754
+ 'cachedInputTokens',
755
+ 'cacheCreationInputTokens',
756
+ 'cacheCreation5mInputTokens',
757
+ 'cacheCreation1hInputTokens',
758
+ 'reasoningOutputTokens',
759
+ 'inputTokenDetails',
760
+ 'outputTokenDetails',
761
+ 'vectorCount',
762
+ 'dimensions',
763
+ 'encodingFormat',
764
+ 'spaceId',
765
+ 'estimated',
766
+ 'requests',
767
+ 'imageCount',
768
+ ], errorCode);
769
+ if (typeof usage['estimated'] !== 'boolean')
770
+ throw new Error(errorCode);
771
+ const counters = [
772
+ 'inputTokens',
773
+ 'outputTokens',
774
+ 'totalTokens',
775
+ 'cachedInputTokens',
776
+ 'cacheCreationInputTokens',
777
+ 'cacheCreation5mInputTokens',
778
+ 'cacheCreation1hInputTokens',
779
+ 'reasoningOutputTokens',
780
+ 'vectorCount',
781
+ 'dimensions',
782
+ 'requests',
783
+ 'imageCount',
784
+ ];
785
+ for (const key of counters) {
786
+ if (usage[key] !== undefined && !nonNegativeInteger(usage[key])) {
787
+ throw new Error(errorCode);
788
+ }
789
+ }
790
+ validateUsageDetails(usage['inputTokenDetails'], errorCode);
791
+ validateUsageDetails(usage['outputTokenDetails'], errorCode);
792
+ if (usage['encodingFormat'] !== undefined &&
793
+ usage['encodingFormat'] !== 'float' &&
794
+ usage['encodingFormat'] !== 'base64') {
795
+ throw new Error(errorCode);
796
+ }
797
+ optionalNonEmptyStringOrThrow(usage['spaceId'], errorCode);
798
+ }
799
+ function validateUsageDetails(value, errorCode) {
800
+ if (value === undefined)
801
+ return;
802
+ const details = runtimeRecord(value, errorCode);
803
+ assertOnlyKeys(details, ['cachedTokens', 'reasoningTokens', 'imageTokens', 'textTokens'], errorCode);
804
+ for (const key of ['cachedTokens', 'reasoningTokens', 'imageTokens', 'textTokens']) {
805
+ if (details[key] !== undefined && !nonNegativeInteger(details[key])) {
806
+ throw new Error(errorCode);
807
+ }
808
+ }
809
+ }
810
+ function validateOptionalUsage(value, errorCode = 'ADAPTER_STREAM_EVENT_INVALID') {
811
+ if (value !== undefined)
812
+ validateNormalizedUsage(value, errorCode);
813
+ }
814
+ function validateOptionalIncompleteDetails(value, errorCode = 'ADAPTER_STREAM_EVENT_INVALID') {
815
+ if (value === undefined)
816
+ return;
817
+ const details = runtimeRecord(value, errorCode);
818
+ assertOnlyKeys(details, ['reason'], errorCode);
819
+ if (!requiredString(details['reason']))
820
+ throw new Error(errorCode);
821
+ }
822
+ function validateOptionalProviderError(value, errorCode = 'ADAPTER_STREAM_EVENT_INVALID') {
823
+ if (value === undefined)
824
+ return;
825
+ const error = runtimeRecord(value, errorCode);
826
+ assertOnlyKeys(error, ['code', 'message'], errorCode);
827
+ if (!requiredString(error['code']) || !optionalNonEmptyString(error['message'])) {
828
+ throw new Error(errorCode);
829
+ }
830
+ }
831
+ function requireLiteral(value, expected) {
832
+ if (value !== expected)
833
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
834
+ }
835
+ function requireString(value) {
836
+ if (typeof value !== 'string')
837
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
838
+ }
839
+ function requireNonEmptyString(value) {
840
+ if (!requiredString(value))
841
+ throw new Error('ADAPTER_STREAM_EVENT_INVALID');
842
+ }
843
+ function optionalRequiredString(value) {
844
+ if (value !== undefined)
845
+ requireNonEmptyString(value);
846
+ }
847
+ function requiredString(value) {
848
+ return typeof value === 'string' && Boolean(value.trim());
849
+ }
850
+ function optionalNonEmptyStringOrThrow(value, errorCode) {
851
+ if (!optionalNonEmptyString(value))
852
+ throw new Error(errorCode);
853
+ }
854
+ function isAsyncIterable(value) {
855
+ return (value !== null &&
856
+ (typeof value === 'object' || typeof value === 'function') &&
857
+ typeof value[Symbol.asyncIterator] === 'function');
858
+ }
859
+ function isPromiseLike(value) {
860
+ return (value !== null &&
861
+ (typeof value === 'object' || typeof value === 'function') &&
862
+ typeof value.then === 'function');
863
+ }
864
+ function validateProviderResponseMetadata(value, errorCode) {
865
+ const metadata = runtimeRecord(value, errorCode);
866
+ assertOnlyKeys(metadata, ['headersReceived', 'statusCode', 'providerRequestId', 'observedModel'], errorCode);
867
+ if (typeof metadata.headersReceived !== 'boolean' ||
868
+ (metadata.statusCode !== undefined &&
869
+ (!Number.isInteger(metadata.statusCode) ||
870
+ metadata.statusCode < 100 ||
871
+ metadata.statusCode > 599)) ||
872
+ !optionalNonEmptyString(metadata.providerRequestId) ||
873
+ !optionalNonEmptyString(metadata.observedModel)) {
874
+ throw new Error(errorCode);
875
+ }
876
+ }
877
+ function runtimeRecord(value, errorCode) {
878
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
879
+ throw new Error(errorCode);
880
+ }
881
+ return value;
882
+ }
883
+ function assertOnlyKeys(value, allowed, errorCode) {
884
+ const keys = new Set(allowed);
885
+ if (Object.keys(value).some((key) => !keys.has(key)))
886
+ throw new Error(errorCode);
887
+ }
888
+ function nonNegativeInteger(value) {
889
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
890
+ }
891
+ function positiveInteger(value) {
892
+ return nonNegativeInteger(value) && value > 0;
893
+ }
894
+ function optionalNonEmptyString(value) {
895
+ return value === undefined || (typeof value === 'string' && Boolean(value.trim()));
896
+ }
897
+ function validateTerminalAcceptance(acceptance, terminal) {
898
+ const terminalFacts = terminal;
899
+ if (terminalFacts.status === 'succeeded' && terminalFacts.acceptanceState !== 'accepted') {
900
+ throw new Error('ADAPTER_SUCCEEDED_WITHOUT_ACCEPTANCE');
901
+ }
902
+ if (acceptance.state !== terminal.acceptanceState) {
903
+ throw new Error('ADAPTER_ACCEPTANCE_MISMATCH');
904
+ }
905
+ }
906
+ function modalitiesMatch(requestedModalities, supportedModalities) {
907
+ return requestedModalities.every((modality) => supportedModalities.includes(modality));
908
+ }
909
+ function sameValues(left, right) {
910
+ return left.length === right.length && left.every((value, index) => value === right[index]);
911
+ }
912
+ function sameValueSet(left, right) {
913
+ return left.length === right.length && left.every((value) => right.includes(value));
914
+ }
915
+ //# sourceMappingURL=runtime-v2-validation.js.map