@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.
- package/LICENSE +201 -0
- package/README.md +22 -0
- package/README.zh-CN.md +17 -0
- package/dist/chat-egress.d.ts +12 -0
- package/dist/chat-egress.d.ts.map +1 -0
- package/dist/chat-egress.js +144 -0
- package/dist/chat-egress.js.map +1 -0
- package/dist/chat-ingress.d.ts +39 -0
- package/dist/chat-ingress.d.ts.map +1 -0
- package/dist/chat-ingress.js +323 -0
- package/dist/chat-ingress.js.map +1 -0
- package/dist/chat-stream-egress.d.ts +8 -0
- package/dist/chat-stream-egress.d.ts.map +1 -0
- package/dist/chat-stream-egress.js +129 -0
- package/dist/chat-stream-egress.js.map +1 -0
- package/dist/contracts.d.ts +61 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +2 -0
- package/dist/contracts.js.map +1 -0
- package/dist/egress-codec-registry.d.ts +36 -0
- package/dist/egress-codec-registry.d.ts.map +1 -0
- package/dist/egress-codec-registry.js +125 -0
- package/dist/egress-codec-registry.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/ingress-codec-registry.d.ts +26 -0
- package/dist/ingress-codec-registry.d.ts.map +1 -0
- package/dist/ingress-codec-registry.js +106 -0
- package/dist/ingress-codec-registry.js.map +1 -0
- package/dist/media-images.d.ts +154 -0
- package/dist/media-images.d.ts.map +1 -0
- package/dist/media-images.js +721 -0
- package/dist/media-images.js.map +1 -0
- package/dist/media-video.d.ts +68 -0
- package/dist/media-video.d.ts.map +1 -0
- package/dist/media-video.js +196 -0
- package/dist/media-video.js.map +1 -0
- package/dist/native-images.d.ts +68 -0
- package/dist/native-images.d.ts.map +1 -0
- package/dist/native-images.js +424 -0
- package/dist/native-images.js.map +1 -0
- package/dist/openai-embeddings-egress.d.ts +4 -0
- package/dist/openai-embeddings-egress.d.ts.map +1 -0
- package/dist/openai-embeddings-egress.js +21 -0
- package/dist/openai-embeddings-egress.js.map +1 -0
- package/dist/openai-embeddings.d.ts +66 -0
- package/dist/openai-embeddings.d.ts.map +1 -0
- package/dist/openai-embeddings.js +442 -0
- package/dist/openai-embeddings.js.map +1 -0
- package/dist/openai-responses-egress.d.ts +17 -0
- package/dist/openai-responses-egress.d.ts.map +1 -0
- package/dist/openai-responses-egress.js +99 -0
- package/dist/openai-responses-egress.js.map +1 -0
- package/dist/openai-responses-stream-egress.d.ts +4 -0
- package/dist/openai-responses-stream-egress.d.ts.map +1 -0
- package/dist/openai-responses-stream-egress.js +252 -0
- package/dist/openai-responses-stream-egress.js.map +1 -0
- package/dist/openai-responses.d.ts +15 -0
- package/dist/openai-responses.d.ts.map +1 -0
- package/dist/openai-responses.js +363 -0
- package/dist/openai-responses.js.map +1 -0
- package/dist/provider-source.d.ts +20 -0
- package/dist/provider-source.d.ts.map +1 -0
- package/dist/provider-source.js +41 -0
- package/dist/provider-source.js.map +1 -0
- package/dist/provider-transport.d.ts +5 -0
- package/dist/provider-transport.d.ts.map +1 -0
- package/dist/provider-transport.js +114 -0
- package/dist/provider-transport.js.map +1 -0
- package/dist/runtime-v2-validation.d.ts +16 -0
- package/dist/runtime-v2-validation.d.ts.map +1 -0
- package/dist/runtime-v2-validation.js +915 -0
- package/dist/runtime-v2-validation.js.map +1 -0
- package/dist/runtime-v2.d.ts +462 -0
- package/dist/runtime-v2.d.ts.map +1 -0
- package/dist/runtime-v2.js +56 -0
- package/dist/runtime-v2.js.map +1 -0
- package/dist/tokenforge-task-projection.d.ts +8 -0
- package/dist/tokenforge-task-projection.d.ts.map +1 -0
- package/dist/tokenforge-task-projection.js +247 -0
- package/dist/tokenforge-task-projection.js.map +1 -0
- package/dist/tokenforge-tasks.d.ts +241 -0
- package/dist/tokenforge-tasks.d.ts.map +1 -0
- package/dist/tokenforge-tasks.js +1132 -0
- package/dist/tokenforge-tasks.js.map +1 -0
- package/dist/usage-reservation.d.ts +11 -0
- package/dist/usage-reservation.d.ts.map +1 -0
- package/dist/usage-reservation.js +40 -0
- package/dist/usage-reservation.js.map +1 -0
- package/dist/validation.d.ts +22 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +415 -0
- package/dist/validation.js.map +1 -0
- package/dist/video-ingress.d.ts +31 -0
- package/dist/video-ingress.d.ts.map +1 -0
- package/dist/video-ingress.js +246 -0
- package/dist/video-ingress.js.map +1 -0
- package/dist/volc-video-task-codec.d.ts +59 -0
- package/dist/volc-video-task-codec.d.ts.map +1 -0
- package/dist/volc-video-task-codec.js +123 -0
- package/dist/volc-video-task-codec.js.map +1 -0
- 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
|