@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,252 @@
1
+ import { openAiResponsesSafeErrorFactsV1 } from './openai-responses-egress.js';
2
+ export function encodeOpenAiResponsesStreamEventV1(event) {
3
+ const type = (event.type === 'output.content_part.added' ||
4
+ event.type === 'output.content_part.completed') &&
5
+ event.part.type === 'reasoning_summary'
6
+ ? event.type === 'output.content_part.added'
7
+ ? 'response.reasoning_summary_part.added'
8
+ : 'response.reasoning_summary_part.done'
9
+ : responsesEventType(event.type);
10
+ const base = { type, sequence_number: event.sequenceNumber };
11
+ let data;
12
+ switch (event.type) {
13
+ case 'response.started':
14
+ data = { ...base, response: { id: event.responseId, status: 'in_progress' } };
15
+ break;
16
+ case 'response.in_progress':
17
+ data = { ...base, response: { id: event.responseId, status: event.status } };
18
+ break;
19
+ case 'output.item.added':
20
+ data = {
21
+ ...base,
22
+ output_index: event.outputIndex,
23
+ item: nativeOutputItem(event.item, event.itemId, 'in_progress', event.itemKind),
24
+ };
25
+ break;
26
+ case 'output.item.completed':
27
+ data = {
28
+ ...base,
29
+ output_index: event.outputIndex,
30
+ item: nativeOutputItem(event.item, event.itemId, event.status, event.itemKind),
31
+ };
32
+ break;
33
+ case 'output.content_part.added':
34
+ case 'output.content_part.completed':
35
+ data = {
36
+ ...base,
37
+ item_id: event.itemId,
38
+ output_index: event.outputIndex,
39
+ ...(event.part.type === 'reasoning_summary'
40
+ ? { summary_index: event.contentIndex }
41
+ : { content_index: event.contentIndex }),
42
+ part: nativeContentPart(event.part),
43
+ };
44
+ break;
45
+ case 'output.text.delta':
46
+ case 'output.refusal.delta':
47
+ data = {
48
+ ...base,
49
+ item_id: event.itemId,
50
+ output_index: event.outputIndex,
51
+ content_index: event.contentIndex,
52
+ delta: event.delta,
53
+ };
54
+ break;
55
+ case 'output.text.completed':
56
+ data = {
57
+ ...base,
58
+ item_id: event.itemId,
59
+ output_index: event.outputIndex,
60
+ content_index: event.contentIndex,
61
+ text: event.text,
62
+ };
63
+ break;
64
+ case 'output.refusal.completed':
65
+ data = {
66
+ ...base,
67
+ item_id: event.itemId,
68
+ output_index: event.outputIndex,
69
+ content_index: event.contentIndex,
70
+ refusal: event.refusal,
71
+ };
72
+ break;
73
+ case 'output.tool_call.delta':
74
+ data = {
75
+ ...base,
76
+ item_id: event.itemId,
77
+ output_index: event.outputIndex,
78
+ call_id: event.callId,
79
+ delta: event.argumentsDelta,
80
+ };
81
+ break;
82
+ case 'output.tool_call.completed':
83
+ data = {
84
+ ...base,
85
+ item_id: event.itemId,
86
+ output_index: event.outputIndex,
87
+ call_id: event.callId,
88
+ name: event.name,
89
+ arguments: event.arguments,
90
+ };
91
+ break;
92
+ case 'output.reasoning_summary.delta':
93
+ data = {
94
+ ...base,
95
+ item_id: event.itemId,
96
+ output_index: event.outputIndex,
97
+ summary_index: event.contentIndex,
98
+ delta: event.delta,
99
+ };
100
+ break;
101
+ case 'output.reasoning_summary.completed':
102
+ data = {
103
+ ...base,
104
+ item_id: event.itemId,
105
+ output_index: event.outputIndex,
106
+ summary_index: event.contentIndex,
107
+ text: event.text,
108
+ };
109
+ break;
110
+ case 'response.completed':
111
+ data = {
112
+ ...base,
113
+ response: {
114
+ id: event.responseId,
115
+ status: 'completed',
116
+ ...(event.usage ? { usage: nativeUsage(event.usage) } : {}),
117
+ },
118
+ };
119
+ break;
120
+ case 'response.incomplete':
121
+ data = {
122
+ ...base,
123
+ response: {
124
+ id: event.responseId,
125
+ status: 'incomplete',
126
+ incomplete_details: { reason: event.reason },
127
+ ...(event.usage ? { usage: nativeUsage(event.usage) } : {}),
128
+ },
129
+ };
130
+ break;
131
+ case 'response.failed':
132
+ data = {
133
+ ...base,
134
+ response: {
135
+ id: event.responseId,
136
+ status: 'failed',
137
+ error: openAiResponsesSafeErrorFactsV1(event.error.code),
138
+ ...(event.usage ? { usage: nativeUsage(event.usage) } : {}),
139
+ },
140
+ };
141
+ break;
142
+ case 'response.cancelled':
143
+ data = {
144
+ ...base,
145
+ response: {
146
+ id: event.responseId,
147
+ status: event.status,
148
+ ...(event.usage ? { usage: nativeUsage(event.usage) } : {}),
149
+ },
150
+ };
151
+ break;
152
+ case 'usage.updated':
153
+ data = { ...base, response_id: event.responseId, usage: nativeUsage(event.usage) };
154
+ break;
155
+ }
156
+ return `event: ${type}\ndata: ${JSON.stringify(data)}\n\n`;
157
+ }
158
+ export function encodeOpenAiResponsesStreamFailureV1(responseId, sequenceNumber, code) {
159
+ const error = openAiResponsesSafeErrorFactsV1(code);
160
+ if (responseId) {
161
+ const data = {
162
+ type: 'response.failed',
163
+ sequence_number: Math.max(0, sequenceNumber),
164
+ response: { id: responseId, status: 'failed', error },
165
+ };
166
+ return `event: response.failed\ndata: ${JSON.stringify(data)}\n\n`;
167
+ }
168
+ const data = {
169
+ type: 'error',
170
+ sequence_number: Math.max(0, sequenceNumber),
171
+ error: { status: 'failed', ...error },
172
+ };
173
+ return `event: error\ndata: ${JSON.stringify(data)}\n\n`;
174
+ }
175
+ function responsesEventType(type) {
176
+ const names = {
177
+ 'response.started': 'response.created',
178
+ 'response.in_progress': 'response.in_progress',
179
+ 'output.item.added': 'response.output_item.added',
180
+ 'output.item.completed': 'response.output_item.done',
181
+ 'output.content_part.added': 'response.content_part.added',
182
+ 'output.content_part.completed': 'response.content_part.done',
183
+ 'output.text.delta': 'response.output_text.delta',
184
+ 'output.text.completed': 'response.output_text.done',
185
+ 'output.refusal.delta': 'response.refusal.delta',
186
+ 'output.refusal.completed': 'response.refusal.done',
187
+ 'output.tool_call.delta': 'response.function_call_arguments.delta',
188
+ 'output.tool_call.completed': 'response.function_call_arguments.done',
189
+ 'output.reasoning_summary.delta': 'response.reasoning_summary_text.delta',
190
+ 'output.reasoning_summary.completed': 'response.reasoning_summary_text.done',
191
+ 'usage.updated': 'response.usage.updated',
192
+ 'response.completed': 'response.completed',
193
+ 'response.incomplete': 'response.incomplete',
194
+ 'response.failed': 'response.failed',
195
+ 'response.cancelled': 'response.cancelled',
196
+ };
197
+ return names[type];
198
+ }
199
+ function nativeOutputItem(item, id, status, itemKind) {
200
+ if (itemKind === 'function_call') {
201
+ if (item.type !== 'function_call')
202
+ throw new Error('NORMALIZED_OUTPUT_ITEM_KIND_MISMATCH');
203
+ return {
204
+ id,
205
+ type: 'function_call',
206
+ status,
207
+ call_id: item.callId,
208
+ name: item.name,
209
+ arguments: item.arguments,
210
+ };
211
+ }
212
+ if (item.type !== 'message')
213
+ throw new Error('NORMALIZED_OUTPUT_ITEM_KIND_MISMATCH');
214
+ if (itemKind === 'reasoning') {
215
+ return {
216
+ id,
217
+ type: 'reasoning',
218
+ status,
219
+ summary: item.content.map(nativeContentPart),
220
+ };
221
+ }
222
+ return { id, type: 'message', status, content: item.content.map(nativeContentPart) };
223
+ }
224
+ function nativeContentPart(part) {
225
+ if (part.type === 'refusal')
226
+ return { type: 'refusal', refusal: part.text };
227
+ if (part.type === 'reasoning_summary')
228
+ return { type: 'summary_text', text: part.text };
229
+ return { type: 'output_text', text: part.text };
230
+ }
231
+ function nativeUsage(usage) {
232
+ return {
233
+ ...(usage.inputTokens !== undefined ? { input_tokens: usage.inputTokens } : {}),
234
+ ...(usage.outputTokens !== undefined ? { output_tokens: usage.outputTokens } : {}),
235
+ ...(usage.totalTokens !== undefined ? { total_tokens: usage.totalTokens } : {}),
236
+ ...(usage.inputTokenDetails
237
+ ? { input_tokens_details: { cached_tokens: usage.inputTokenDetails.cachedTokens ?? 0 } }
238
+ : usage.cachedInputTokens === undefined
239
+ ? {}
240
+ : { input_tokens_details: { cached_tokens: usage.cachedInputTokens } }),
241
+ ...(usage.outputTokenDetails
242
+ ? {
243
+ output_tokens_details: {
244
+ reasoning_tokens: usage.outputTokenDetails.reasoningTokens ?? 0,
245
+ },
246
+ }
247
+ : usage.reasoningOutputTokens === undefined
248
+ ? {}
249
+ : { output_tokens_details: { reasoning_tokens: usage.reasoningOutputTokens } }),
250
+ };
251
+ }
252
+ //# sourceMappingURL=openai-responses-stream-egress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses-stream-egress.js","sourceRoot":"","sources":["../src/openai-responses-stream-egress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ProviderCapability } from './contracts.js';
2
+ import type { DecodedTaskV1 } from './runtime-v2.js';
3
+ export declare const OPENAI_RESPONSES_PROTOCOL: "openai-responses/v1";
4
+ export declare const OPENAI_RESPONSES_MAX_IMAGE_BYTES: number;
5
+ export type OpenAiResponsesRequestErrorCode = 'body_required' | 'unknown_field' | 'model_required' | 'store_not_supported' | 'input_required' | 'invalid_input' | 'unsupported_content' | 'invalid_image_url' | 'image_too_large' | 'unsupported_tool' | 'invalid_tool' | 'invalid_tool_choice' | 'invalid_reasoning' | 'invalid_generation_option' | 'protocol_family_mismatch' | 'unsupported_capability';
6
+ export type OpenAiResponsesRequestErrorStatus = 400 | 422;
7
+ export declare class OpenAiResponsesRequestError extends Error {
8
+ readonly code: OpenAiResponsesRequestErrorCode;
9
+ readonly status: OpenAiResponsesRequestErrorStatus;
10
+ readonly name = "OpenAiResponsesRequestError";
11
+ constructor(code: OpenAiResponsesRequestErrorCode, status: OpenAiResponsesRequestErrorStatus);
12
+ }
13
+ export declare function decodeOpenAiResponsesRequest(body: unknown, requestId: string): DecodedTaskV1;
14
+ export declare function validateOpenAiResponsesCapability(decoded: DecodedTaskV1, capability: ProviderCapability): void;
15
+ //# sourceMappingURL=openai-responses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../src/openai-responses.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,eAAO,MAAM,yBAAyB,EAAG,qBAA8B,CAAC;AACxE,eAAO,MAAM,gCAAgC,QAAmB,CAAC;AAEjE,MAAM,MAAM,+BAA+B,GACvC,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,qBAAqB,GACrB,gBAAgB,GAChB,eAAe,GACf,qBAAqB,GACrB,mBAAmB,GACnB,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,GACd,qBAAqB,GACrB,mBAAmB,GACnB,2BAA2B,GAC3B,0BAA0B,GAC1B,wBAAwB,CAAC;AAE7B,MAAM,MAAM,iCAAiC,GAAG,GAAG,GAAG,GAAG,CAAC;AAE1D,qBAAa,2BAA4B,SAAQ,KAAK;IAIlD,QAAQ,CAAC,IAAI,EAAE,+BAA+B;IAC9C,QAAQ,CAAC,MAAM,EAAE,iCAAiC;IAJpD,SAAkB,IAAI,iCAAiC;gBAG5C,IAAI,EAAE,+BAA+B,EACrC,MAAM,EAAE,iCAAiC;CAIrD;AAmDD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,CA+D5F;AAED,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,aAAa,EACtB,UAAU,EAAE,kBAAkB,GAC7B,IAAI,CA4BN"}
@@ -0,0 +1,363 @@
1
+ export const OPENAI_RESPONSES_PROTOCOL = 'openai-responses/v1';
2
+ export const OPENAI_RESPONSES_MAX_IMAGE_BYTES = 20 * 1024 * 1024;
3
+ export class OpenAiResponsesRequestError extends Error {
4
+ code;
5
+ status;
6
+ name = 'OpenAiResponsesRequestError';
7
+ constructor(code, status) {
8
+ super(`OpenAI Responses request rejected: ${code}`);
9
+ this.code = code;
10
+ this.status = status;
11
+ }
12
+ }
13
+ const ALLOWED_TOP_LEVEL_FIELDS = new Set([
14
+ 'model',
15
+ 'input',
16
+ 'instructions',
17
+ 'tools',
18
+ 'tool_choice',
19
+ 'reasoning',
20
+ 'max_output_tokens',
21
+ 'max_tool_calls',
22
+ 'parallel_tool_calls',
23
+ 'temperature',
24
+ 'top_p',
25
+ 'stream',
26
+ 'store',
27
+ 'logicalRequestId',
28
+ 'attemptId',
29
+ ]);
30
+ const ALLOWED_IMAGE_MIME_TYPES = new Set(['image/gif', 'image/jpeg', 'image/png', 'image/webp']);
31
+ const REASONING_EFFORTS = new Set(['none', 'minimal', 'low', 'medium', 'high', 'xhigh']);
32
+ export function decodeOpenAiResponsesRequest(body, requestId) {
33
+ if (!requestId.trim()) {
34
+ reject('invalid_input', 400);
35
+ }
36
+ const request = requireRecord(body, 'body_required');
37
+ assertKnownFields(request, ALLOWED_TOP_LEVEL_FIELDS);
38
+ if ('store' in request && request.store !== false) {
39
+ reject('store_not_supported', 400);
40
+ }
41
+ const model = requiredString(request.model, 'model_required');
42
+ const input = decodeInput(request.input);
43
+ const tools = decodeTools(request.tools);
44
+ const toolChoice = decodeToolChoice(request.tool_choice);
45
+ validateToolChoice(tools, toolChoice);
46
+ const reasoning = decodeReasoning(request.reasoning);
47
+ const generation = decodeGenerationOptions(request);
48
+ const stream = request.stream === undefined ? false : requiredBoolean(request.stream, 'invalid_input');
49
+ const normalizedInput = {
50
+ model,
51
+ input: input.items,
52
+ store: false,
53
+ stream,
54
+ ...generation,
55
+ };
56
+ const instructions = request.instructions === undefined
57
+ ? undefined
58
+ : requiredString(request.instructions, 'invalid_input');
59
+ if (instructions !== undefined) {
60
+ normalizedInput.instructions = instructions;
61
+ }
62
+ if (tools !== undefined) {
63
+ normalizedInput.tools = tools;
64
+ }
65
+ if (toolChoice !== undefined) {
66
+ normalizedInput.tool_choice = toolChoice;
67
+ }
68
+ if (reasoning !== undefined) {
69
+ normalizedInput.reasoning = reasoning;
70
+ }
71
+ return {
72
+ ingressProtocolFamily: OPENAI_RESPONSES_PROTOCOL,
73
+ model,
74
+ taskKind: 'chat',
75
+ executionMode: stream ? 'stream' : 'sync',
76
+ inputModalities: instructions === undefined ? input.modalities : appendTextModality(input.modalities),
77
+ outputModalities: ['text'],
78
+ requiresFunctionTools: tools !== undefined && tools.length > 0,
79
+ requiresReasoning: reasoning !== undefined,
80
+ normalizedInput,
81
+ providerOptions: {
82
+ ...(tools === undefined ? {} : { tools }),
83
+ ...(toolChoice === undefined ? {} : { tool_choice: toolChoice }),
84
+ ...(reasoning === undefined ? {} : { reasoning }),
85
+ ...generation,
86
+ },
87
+ };
88
+ }
89
+ export function validateOpenAiResponsesCapability(decoded, capability) {
90
+ if (decoded.ingressProtocolFamily !== capability.protocolFamily) {
91
+ reject('protocol_family_mismatch', 422);
92
+ }
93
+ if (decoded.taskKind !== 'chat' || capability.taskKind !== 'chat') {
94
+ reject('unsupported_capability', 422);
95
+ }
96
+ if (!capability.executionModes.includes(decoded.executionMode)) {
97
+ reject('unsupported_capability', 422);
98
+ }
99
+ if (!hasOnlySupportedModalities(decoded.inputModalities, ['text', 'image']) ||
100
+ !decoded.inputModalities.every((modality) => capability.inputModalities.includes(modality))) {
101
+ reject('unsupported_capability', 422);
102
+ }
103
+ if (!hasOnlySupportedModalities(decoded.outputModalities, ['text']) ||
104
+ !decoded.outputModalities.every((modality) => capability.outputModalities.includes(modality))) {
105
+ reject('unsupported_capability', 422);
106
+ }
107
+ if (decoded.requiresFunctionTools && !capability.features.includes('function_tools')) {
108
+ reject('unsupported_capability', 422);
109
+ }
110
+ if (decoded.requiresReasoning && !capability.features.includes('reasoning')) {
111
+ reject('unsupported_capability', 422);
112
+ }
113
+ }
114
+ function decodeInput(value) {
115
+ if (typeof value === 'string') {
116
+ const text = requiredString(value, 'input_required');
117
+ return {
118
+ items: [{ role: 'user', content: [{ type: 'input_text', text }] }],
119
+ modalities: ['text'],
120
+ };
121
+ }
122
+ if (!Array.isArray(value) || value.length === 0) {
123
+ reject('input_required', 400);
124
+ }
125
+ const modalities = new Set();
126
+ const items = value.map((item) => decodeInputItem(item, modalities));
127
+ if (modalities.size === 0) {
128
+ reject('input_required', 400);
129
+ }
130
+ return { items, modalities: [...modalities] };
131
+ }
132
+ function decodeInputItem(value, modalities) {
133
+ const item = requireRecord(value, 'invalid_input');
134
+ assertKnownFields(item, new Set(['role', 'content']));
135
+ const role = requiredString(item.role, 'invalid_input');
136
+ if (!['user', 'developer', 'system'].includes(role)) {
137
+ reject('unsupported_content', 400);
138
+ }
139
+ const content = typeof item.content === 'string' ? [{ type: 'input_text', text: item.content }] : item.content;
140
+ if (!Array.isArray(content) || content.length === 0) {
141
+ reject('input_required', 400);
142
+ }
143
+ return {
144
+ role,
145
+ content: content.map((part) => decodeContentPart(part, modalities)),
146
+ };
147
+ }
148
+ function decodeContentPart(value, modalities) {
149
+ const part = requireRecord(value, 'invalid_input');
150
+ const type = requiredString(part.type, 'invalid_input');
151
+ if (type === 'input_text') {
152
+ assertKnownFields(part, new Set(['type', 'text']));
153
+ modalities.add('text');
154
+ return { type, text: requiredString(part.text, 'input_required') };
155
+ }
156
+ if (type === 'input_image') {
157
+ assertKnownFields(part, new Set(['type', 'image_url', 'detail']));
158
+ const imageUrl = requiredString(part.image_url, 'invalid_image_url');
159
+ validateImageUrl(imageUrl);
160
+ if (part.detail !== undefined &&
161
+ !['auto', 'low', 'high'].includes(requiredString(part.detail, 'invalid_input'))) {
162
+ reject('invalid_input', 400);
163
+ }
164
+ modalities.add('image');
165
+ return {
166
+ type,
167
+ image_url: imageUrl,
168
+ ...(part.detail === undefined ? {} : { detail: part.detail }),
169
+ };
170
+ }
171
+ reject('unsupported_content', 400);
172
+ }
173
+ function decodeTools(value) {
174
+ if (value === undefined) {
175
+ return undefined;
176
+ }
177
+ if (!Array.isArray(value)) {
178
+ reject('invalid_tool', 400);
179
+ }
180
+ return value.map((tool) => {
181
+ const record = requireRecord(tool, 'invalid_tool');
182
+ if (record.type !== 'function') {
183
+ reject('unsupported_tool', 400);
184
+ }
185
+ assertKnownFields(record, new Set(['type', 'name', 'description', 'parameters', 'strict']));
186
+ const name = requiredString(record.name, 'invalid_tool');
187
+ if (record.description !== undefined && typeof record.description !== 'string') {
188
+ reject('invalid_tool', 400);
189
+ }
190
+ if (record.parameters !== undefined) {
191
+ requireRecord(record.parameters, 'invalid_tool');
192
+ }
193
+ if (record.strict !== undefined) {
194
+ requiredBoolean(record.strict, 'invalid_tool');
195
+ }
196
+ return {
197
+ type: 'function',
198
+ name,
199
+ ...(record.description === undefined ? {} : { description: record.description }),
200
+ ...(record.parameters === undefined ? {} : { parameters: record.parameters }),
201
+ ...(record.strict === undefined ? {} : { strict: record.strict }),
202
+ };
203
+ });
204
+ }
205
+ function decodeToolChoice(value) {
206
+ if (value === undefined) {
207
+ return undefined;
208
+ }
209
+ if (value === 'auto' || value === 'required' || value === 'none') {
210
+ return value;
211
+ }
212
+ const choice = requireRecord(value, 'invalid_tool_choice');
213
+ assertKnownFields(choice, new Set(['type', 'name']));
214
+ if (choice.type !== 'function') {
215
+ reject('invalid_tool_choice', 400);
216
+ }
217
+ return { type: 'function', name: requiredString(choice.name, 'invalid_tool_choice') };
218
+ }
219
+ function validateToolChoice(tools, toolChoice) {
220
+ if (toolChoice === undefined || toolChoice === 'auto' || toolChoice === 'none') {
221
+ return;
222
+ }
223
+ if (!tools || tools.length === 0) {
224
+ reject('invalid_tool_choice', 400);
225
+ }
226
+ if (toolChoice === 'required') {
227
+ return;
228
+ }
229
+ if (!tools.some((tool) => tool.name === toolChoice.name)) {
230
+ reject('invalid_tool_choice', 400);
231
+ }
232
+ }
233
+ function decodeReasoning(value) {
234
+ if (value === undefined) {
235
+ return undefined;
236
+ }
237
+ const reasoning = requireRecord(value, 'invalid_reasoning');
238
+ assertKnownFields(reasoning, new Set(['effort']));
239
+ const effort = requiredString(reasoning.effort, 'invalid_reasoning');
240
+ if (!REASONING_EFFORTS.has(effort)) {
241
+ reject('invalid_reasoning', 400);
242
+ }
243
+ return { effort };
244
+ }
245
+ function decodeGenerationOptions(request) {
246
+ const options = {};
247
+ if (request.max_output_tokens !== undefined) {
248
+ options.max_output_tokens = positiveInteger(request.max_output_tokens);
249
+ }
250
+ if (request.max_tool_calls !== undefined) {
251
+ options.max_tool_calls = positiveInteger(request.max_tool_calls);
252
+ }
253
+ if (request.parallel_tool_calls !== undefined) {
254
+ options.parallel_tool_calls = requiredBoolean(request.parallel_tool_calls, 'invalid_generation_option');
255
+ }
256
+ if (request.temperature !== undefined) {
257
+ const temperature = finiteNumber(request.temperature);
258
+ if (temperature < 0 || temperature > 2) {
259
+ reject('invalid_generation_option', 400);
260
+ }
261
+ options.temperature = temperature;
262
+ }
263
+ if (request.top_p !== undefined) {
264
+ const topP = finiteNumber(request.top_p);
265
+ if (topP <= 0 || topP > 1) {
266
+ reject('invalid_generation_option', 400);
267
+ }
268
+ options.top_p = topP;
269
+ }
270
+ return options;
271
+ }
272
+ function validateImageUrl(imageUrl) {
273
+ if (imageUrl.startsWith('data:')) {
274
+ const match = /^data:([^;,]+);base64,([A-Za-z0-9+/]*={0,2})$/.exec(imageUrl);
275
+ if (!match) {
276
+ reject('invalid_image_url', 400);
277
+ }
278
+ const mimeType = match[1];
279
+ const encoded = match[2];
280
+ if (!ALLOWED_IMAGE_MIME_TYPES.has(mimeType) || !isValidBase64(encoded)) {
281
+ reject('invalid_image_url', 400);
282
+ }
283
+ const byteLength = decodedBase64ByteLength(encoded);
284
+ if (byteLength === 0) {
285
+ reject('invalid_image_url', 400);
286
+ }
287
+ if (byteLength > OPENAI_RESPONSES_MAX_IMAGE_BYTES) {
288
+ reject('image_too_large', 400);
289
+ }
290
+ return;
291
+ }
292
+ let parsed;
293
+ try {
294
+ parsed = new URL(imageUrl);
295
+ }
296
+ catch {
297
+ reject('invalid_image_url', 400);
298
+ }
299
+ if (parsed.protocol !== 'https:' || !parsed.hostname || parsed.username || parsed.password) {
300
+ reject('invalid_image_url', 400);
301
+ }
302
+ }
303
+ function assertKnownFields(value, allowed) {
304
+ for (const key of Object.keys(value)) {
305
+ if (!allowed.has(key)) {
306
+ reject('unknown_field', 400);
307
+ }
308
+ }
309
+ }
310
+ function requireRecord(value, code) {
311
+ if (!isPlainRecord(value)) {
312
+ reject(code, 400);
313
+ }
314
+ return value;
315
+ }
316
+ function requiredString(value, code) {
317
+ if (typeof value !== 'string' || !value.trim()) {
318
+ reject(code, 400);
319
+ }
320
+ return value;
321
+ }
322
+ function requiredBoolean(value, code) {
323
+ if (typeof value !== 'boolean') {
324
+ reject(code, 400);
325
+ }
326
+ return value;
327
+ }
328
+ function positiveInteger(value) {
329
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0) {
330
+ reject('invalid_generation_option', 400);
331
+ }
332
+ return value;
333
+ }
334
+ function finiteNumber(value) {
335
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
336
+ reject('invalid_generation_option', 400);
337
+ }
338
+ return value;
339
+ }
340
+ function isPlainRecord(value) {
341
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
342
+ return false;
343
+ }
344
+ const prototype = Object.getPrototypeOf(value);
345
+ return prototype === Object.prototype || prototype === null;
346
+ }
347
+ function isValidBase64(value) {
348
+ return value.length > 0 && value.length % 4 === 0 && !/=.*=.+/.test(value);
349
+ }
350
+ function decodedBase64ByteLength(value) {
351
+ const padding = value.endsWith('==') ? 2 : value.endsWith('=') ? 1 : 0;
352
+ return (value.length / 4) * 3 - padding;
353
+ }
354
+ function appendTextModality(modalities) {
355
+ return modalities.includes('text') ? modalities : [...modalities, 'text'];
356
+ }
357
+ function hasOnlySupportedModalities(modalities, supported) {
358
+ return modalities.length > 0 && modalities.every((modality) => supported.includes(modality));
359
+ }
360
+ function reject(code, status) {
361
+ throw new OpenAiResponsesRequestError(code, status);
362
+ }
363
+ //# sourceMappingURL=openai-responses.js.map