kimi-proxy 0.0.1

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 (91) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +177 -0
  3. package/dist/adapters/anthropicAdapter.d.ts +138 -0
  4. package/dist/adapters/anthropicAdapter.js +184 -0
  5. package/dist/adapters/anthropicAdapter.js.map +1 -0
  6. package/dist/config.d.ts +27 -0
  7. package/dist/config.js +228 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/core/converters/anthropicToOpenAI.d.ts +11 -0
  10. package/dist/core/converters/anthropicToOpenAI.js +18 -0
  11. package/dist/core/converters/anthropicToOpenAI.js.map +1 -0
  12. package/dist/core/converters/openaiPassthrough.d.ts +18 -0
  13. package/dist/core/converters/openaiPassthrough.js +794 -0
  14. package/dist/core/converters/openaiPassthrough.js.map +1 -0
  15. package/dist/core/converters/types.d.ts +14 -0
  16. package/dist/core/converters/types.js +16 -0
  17. package/dist/core/converters/types.js.map +1 -0
  18. package/dist/core/ensureToolCall.d.ts +24 -0
  19. package/dist/core/ensureToolCall.js +93 -0
  20. package/dist/core/ensureToolCall.js.map +1 -0
  21. package/dist/core/modelRegistry.d.ts +46 -0
  22. package/dist/core/modelRegistry.js +92 -0
  23. package/dist/core/modelRegistry.js.map +1 -0
  24. package/dist/core/pipeline.d.ts +17 -0
  25. package/dist/core/pipeline.js +109 -0
  26. package/dist/core/pipeline.js.map +1 -0
  27. package/dist/core/pipelineControl.d.ts +12 -0
  28. package/dist/core/pipelineControl.js +51 -0
  29. package/dist/core/pipelineControl.js.map +1 -0
  30. package/dist/core/providers/openRouterProvider.d.ts +52 -0
  31. package/dist/core/providers/openRouterProvider.js +158 -0
  32. package/dist/core/providers/openRouterProvider.js.map +1 -0
  33. package/dist/core/providers/openaiProvider.d.ts +22 -0
  34. package/dist/core/providers/openaiProvider.js +79 -0
  35. package/dist/core/providers/openaiProvider.js.map +1 -0
  36. package/dist/core/providers/types.d.ts +24 -0
  37. package/dist/core/providers/types.js +14 -0
  38. package/dist/core/providers/types.js.map +1 -0
  39. package/dist/core/providers/vertexProvider.d.ts +37 -0
  40. package/dist/core/providers/vertexProvider.js +167 -0
  41. package/dist/core/providers/vertexProvider.js.map +1 -0
  42. package/dist/core/syntheticResponse.d.ts +6 -0
  43. package/dist/core/syntheticResponse.js +36 -0
  44. package/dist/core/syntheticResponse.js.map +1 -0
  45. package/dist/core/transforms/request/ClampMaxTokensTransform.d.ts +7 -0
  46. package/dist/core/transforms/request/ClampMaxTokensTransform.js +29 -0
  47. package/dist/core/transforms/request/ClampMaxTokensTransform.js.map +1 -0
  48. package/dist/core/transforms/request/DisableStreamingTransform.d.ts +7 -0
  49. package/dist/core/transforms/request/DisableStreamingTransform.js +15 -0
  50. package/dist/core/transforms/request/DisableStreamingTransform.js.map +1 -0
  51. package/dist/core/transforms/request/EnsureToolCallRequestTransform.d.ts +12 -0
  52. package/dist/core/transforms/request/EnsureToolCallRequestTransform.js +120 -0
  53. package/dist/core/transforms/request/EnsureToolCallRequestTransform.js.map +1 -0
  54. package/dist/core/transforms/response/EnsureToolCallResponseTransform.d.ts +9 -0
  55. package/dist/core/transforms/response/EnsureToolCallResponseTransform.js +223 -0
  56. package/dist/core/transforms/response/EnsureToolCallResponseTransform.js.map +1 -0
  57. package/dist/core/transforms/response/KimiResponseTransform.d.ts +7 -0
  58. package/dist/core/transforms/response/KimiResponseTransform.js +32 -0
  59. package/dist/core/transforms/response/KimiResponseTransform.js.map +1 -0
  60. package/dist/core/types.d.ts +80 -0
  61. package/dist/core/types.js +18 -0
  62. package/dist/core/types.js.map +1 -0
  63. package/dist/index.d.ts +1 -0
  64. package/dist/index.js +17 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/persistence/logStore.d.ts +43 -0
  67. package/dist/persistence/logStore.js +115 -0
  68. package/dist/persistence/logStore.js.map +1 -0
  69. package/dist/server.d.ts +3 -0
  70. package/dist/server.js +385 -0
  71. package/dist/server.js.map +1 -0
  72. package/dist/services/kimiFixer.d.ts +13 -0
  73. package/dist/services/kimiFixer.js +160 -0
  74. package/dist/services/kimiFixer.js.map +1 -0
  75. package/dist/services/streaming.d.ts +9 -0
  76. package/dist/services/streaming.js +513 -0
  77. package/dist/services/streaming.js.map +1 -0
  78. package/dist/utils/envResolver.d.ts +26 -0
  79. package/dist/utils/envResolver.js +64 -0
  80. package/dist/utils/envResolver.js.map +1 -0
  81. package/dist/utils/ids.d.ts +1 -0
  82. package/dist/utils/ids.js +7 -0
  83. package/dist/utils/ids.js.map +1 -0
  84. package/dist/utils/logger.d.ts +3 -0
  85. package/dist/utils/logger.js +12 -0
  86. package/dist/utils/logger.js.map +1 -0
  87. package/frontend/dist/assets/JSONViewer-97138fd7.js +3 -0
  88. package/frontend/dist/assets/index-0e7c091b.css +1 -0
  89. package/frontend/dist/assets/index-4b354ce2.js +40 -0
  90. package/frontend/dist/index.html +22 -0
  91. package/package.json +60 -0
@@ -0,0 +1,794 @@
1
+ import { ClientFormat, ProviderFormat, ProxyOperation, } from "../types.js";
2
+ function isJsonObject(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+ function asJsonObject(value) {
6
+ return isJsonObject(value) ? value : {};
7
+ }
8
+ function asJsonObjectArray(value) {
9
+ if (!Array.isArray(value)) {
10
+ return [];
11
+ }
12
+ return value.filter((entry) => isJsonObject(entry));
13
+ }
14
+ export class OpenAIChatPassthroughConverter {
15
+ name = "openai-chat";
16
+ sourceFormat = ClientFormat.OpenAIChatCompletions;
17
+ targetFormat = ProviderFormat.OpenAIChatCompletions;
18
+ operations = [ProxyOperation.ChatCompletions];
19
+ convertRequest(body, _context) {
20
+ void _context;
21
+ return { body };
22
+ }
23
+ convertResponse(body, _context) {
24
+ void _context;
25
+ return ensureChatCompletionResponse(body) ?? body;
26
+ }
27
+ }
28
+ export class OpenAIResponsesPassthroughConverter {
29
+ name = "openai-responses";
30
+ sourceFormat = ClientFormat.OpenAIResponses;
31
+ targetFormat = ProviderFormat.OpenAIChatCompletions;
32
+ operations = [ProxyOperation.Responses];
33
+ convertRequest(body, _context) {
34
+ void _context;
35
+ const normalized = isJsonObject(body) ? { ...body } : {};
36
+ const messages = Array.isArray(normalized.messages)
37
+ ? [...normalized.messages]
38
+ : [];
39
+ const normalizedMessages = messages
40
+ .map((message) => normalizeMessage(message))
41
+ .filter((message) => Boolean(message));
42
+ const systemInstruction = normalizeInstruction(normalized.instructions);
43
+ const inputMessages = normalizeInput(normalized.input);
44
+ const finalMessages = [];
45
+ if (systemInstruction) {
46
+ finalMessages.push(systemInstruction);
47
+ }
48
+ if (normalizedMessages.length) {
49
+ finalMessages.push(...normalizedMessages);
50
+ }
51
+ if (inputMessages.length) {
52
+ finalMessages.push(...inputMessages);
53
+ }
54
+ if (finalMessages.length) {
55
+ normalized.messages = finalMessages;
56
+ }
57
+ const normalizedTools = normalizeTools(normalized.tools);
58
+ if (normalizedTools.length) {
59
+ normalized.tools = normalizedTools;
60
+ }
61
+ else {
62
+ delete normalized.tools;
63
+ }
64
+ delete normalized.input;
65
+ delete normalized.instructions;
66
+ return { body: normalized };
67
+ }
68
+ convertResponse(body) {
69
+ const normalizedBody = ensureChatCompletionResponse(body);
70
+ const normalizedResponse = asJsonObject(normalizedBody);
71
+ const responseId = typeof normalizedResponse.id === "string"
72
+ ? normalizedResponse.id
73
+ : undefined;
74
+ const choices = asJsonObjectArray(normalizedResponse.choices);
75
+ const outputs = choices.length
76
+ ? choices.flatMap((choice, index) => convertChoiceToResponseOutputs(choice, index, responseId))
77
+ : [createEmptyOutput(responseId)];
78
+ const outputText = collectOutputText(outputs);
79
+ const response = {
80
+ id: normalizedResponse.id,
81
+ object: "response",
82
+ created: normalizedResponse.created ?? Math.floor(Date.now() / 1000),
83
+ model: normalizedResponse.model,
84
+ usage: normalizeResponseUsage(normalizedResponse.usage),
85
+ status: resolveResponseStatus(),
86
+ output: outputs,
87
+ };
88
+ if (outputText.length) {
89
+ response.output_text = outputText;
90
+ }
91
+ return response;
92
+ }
93
+ }
94
+ function normalizeInstruction(value) {
95
+ if (typeof value !== "string" || !value.trim()) {
96
+ return null;
97
+ }
98
+ return { role: "system", content: value.trim() };
99
+ }
100
+ function normalizeInput(value) {
101
+ if (value === undefined || value === null) {
102
+ return [];
103
+ }
104
+ if (typeof value === "string") {
105
+ return [{ role: "user", content: value }];
106
+ }
107
+ if (Array.isArray(value)) {
108
+ return value
109
+ .map((entry) => normalizeMessage(entry))
110
+ .filter((entry) => Boolean(entry));
111
+ }
112
+ const normalized = normalizeMessage(value);
113
+ return normalized ? [normalized] : [];
114
+ }
115
+ function normalizeMessage(value) {
116
+ if (value === undefined || value === null) {
117
+ return null;
118
+ }
119
+ if (typeof value === "string") {
120
+ return { role: "user", content: value };
121
+ }
122
+ if (typeof value === "object") {
123
+ const record = value;
124
+ if (record.type === "function_call") {
125
+ return {
126
+ role: "assistant",
127
+ content: normalizeMessageContent(record.content ?? record.text ?? ""),
128
+ tool_calls: [
129
+ {
130
+ id: typeof record.call_id === "string" ? record.call_id : undefined,
131
+ type: "function",
132
+ function: {
133
+ name: typeof record.name === "string" ? record.name : "",
134
+ arguments: typeof record.arguments === "string"
135
+ ? record.arguments
136
+ : JSON.stringify(record.arguments ?? {}),
137
+ },
138
+ },
139
+ ],
140
+ };
141
+ }
142
+ if (record.type === "function_call_output") {
143
+ return {
144
+ role: "tool",
145
+ tool_call_id: typeof record.call_id === "string" ? record.call_id : undefined,
146
+ content: normalizeMessageContent(record.output ?? record.content ?? record.text ?? ""),
147
+ };
148
+ }
149
+ const role = typeof record.role === "string" ? record.role : "user";
150
+ const content = normalizeMessageContent(record.content ?? record.text ?? "");
151
+ const normalized = {
152
+ ...record,
153
+ role,
154
+ content,
155
+ };
156
+ const toolCalls = normalizeToolCalls(record.tool_calls);
157
+ if (toolCalls?.length) {
158
+ normalized.tool_calls = toolCalls;
159
+ }
160
+ else {
161
+ delete normalized.tool_calls;
162
+ }
163
+ return normalized;
164
+ }
165
+ return null;
166
+ }
167
+ function normalizeMessageContent(value) {
168
+ if (value === undefined || value === null) {
169
+ return "";
170
+ }
171
+ if (typeof value === "string") {
172
+ return value;
173
+ }
174
+ if (Array.isArray(value)) {
175
+ return value
176
+ .map((entry) => convertInputContentPart(entry))
177
+ .filter((entry) => Boolean(entry));
178
+ }
179
+ if (typeof value === "object") {
180
+ const converted = convertInputContentPart(value);
181
+ return converted ? [converted] : "";
182
+ }
183
+ return String(value);
184
+ }
185
+ function convertInputContentPart(part) {
186
+ if (part === undefined || part === null) {
187
+ return { type: "text", text: "" };
188
+ }
189
+ if (typeof part === "string") {
190
+ return { type: "text", text: part };
191
+ }
192
+ if (typeof part !== "object") {
193
+ return { type: "text", text: String(part) };
194
+ }
195
+ const record = { ...part };
196
+ const type = record.type;
197
+ if (type === "input_text") {
198
+ return { type: "text", text: record.text ?? "" };
199
+ }
200
+ if (type === "input_image") {
201
+ return {
202
+ type: "image_url",
203
+ image_url: record.image_url ?? record.url ?? record.source ?? null,
204
+ };
205
+ }
206
+ if (type === "text" && typeof record.text === "string") {
207
+ return { type: "text", text: record.text };
208
+ }
209
+ if (type === "image_url") {
210
+ return {
211
+ type: "image_url",
212
+ image_url: record.image_url ?? record.url ?? null,
213
+ };
214
+ }
215
+ if (type === "output_text") {
216
+ return { type: "text", text: record.text ?? "" };
217
+ }
218
+ if (type === "output_image") {
219
+ return {
220
+ type: "image_url",
221
+ image_url: record.image_url ?? record.url ?? null,
222
+ };
223
+ }
224
+ if (type === "reasoning_text") {
225
+ return { type: "text", text: record.text ?? "" };
226
+ }
227
+ if (!type && typeof record.text === "string") {
228
+ return { type: "text", text: record.text };
229
+ }
230
+ return record;
231
+ }
232
+ function normalizeTools(value) {
233
+ if (!Array.isArray(value)) {
234
+ return [];
235
+ }
236
+ return value
237
+ .map((tool) => convertToolDefinition(tool))
238
+ .filter((tool) => Boolean(tool));
239
+ }
240
+ function convertToolDefinition(tool) {
241
+ if (!isJsonObject(tool)) {
242
+ return null;
243
+ }
244
+ const fn = asJsonObject(tool.function);
245
+ const name = typeof fn.name === "string" ? fn.name : tool.name;
246
+ if (!name) {
247
+ return null;
248
+ }
249
+ const description = typeof fn.description === "string" ? fn.description : tool.description;
250
+ const parametersValue = fn.parameters ?? tool.parameters;
251
+ const parameters = isJsonObject(parametersValue)
252
+ ? parametersValue
253
+ : undefined;
254
+ const formatValue = fn.format ?? tool.format;
255
+ const format = typeof formatValue === "string" ? formatValue : undefined;
256
+ const strictValue = typeof tool.strict === "boolean" ? tool.strict : fn.strict;
257
+ const strict = typeof strictValue === "boolean" ? strictValue : undefined;
258
+ const functionDefinition = {
259
+ name,
260
+ ...(description ? { description } : {}),
261
+ ...(parameters ? { parameters } : {}),
262
+ };
263
+ if (format) {
264
+ functionDefinition.format = format;
265
+ }
266
+ const normalized = {
267
+ type: "function",
268
+ function: functionDefinition,
269
+ };
270
+ if (strict !== undefined) {
271
+ normalized.strict = strict;
272
+ }
273
+ return normalized;
274
+ }
275
+ function normalizeToolCalls(value) {
276
+ if (!Array.isArray(value)) {
277
+ return undefined;
278
+ }
279
+ const calls = value
280
+ .map((entry) => normalizeToolCallEntry(entry))
281
+ .filter((entry) => Boolean(entry));
282
+ return calls.length ? calls : undefined;
283
+ }
284
+ function normalizeToolCallEntry(entry) {
285
+ if (!isJsonObject(entry)) {
286
+ return null;
287
+ }
288
+ const fn = asJsonObject(entry.function);
289
+ const fnName = typeof fn.name === "string" ? fn.name : undefined;
290
+ const recordName = typeof entry.name === "string" ? entry.name : undefined;
291
+ const name = fnName ?? recordName;
292
+ if (!name) {
293
+ return null;
294
+ }
295
+ const args = normalizeArguments(fn.arguments ?? entry.arguments ?? "");
296
+ return {
297
+ id: typeof entry.id === "string" ? entry.id : undefined,
298
+ type: "function",
299
+ function: {
300
+ name,
301
+ arguments: args,
302
+ },
303
+ };
304
+ }
305
+ function normalizeArguments(value) {
306
+ if (typeof value === "string") {
307
+ return value;
308
+ }
309
+ try {
310
+ return JSON.stringify(value ?? "");
311
+ }
312
+ catch {
313
+ return "";
314
+ }
315
+ }
316
+ function ensureChatCompletionResponse(payload) {
317
+ if (typeof payload === "string") {
318
+ return parseOpenAIChatStream(payload) ?? { object: "stream", payload };
319
+ }
320
+ return payload;
321
+ }
322
+ function parseOpenAIChatStream(payload) {
323
+ const events = extractSSEEvents(payload);
324
+ if (!events.length) {
325
+ return null;
326
+ }
327
+ return consolidateChatCompletionChunks(events);
328
+ }
329
+ function extractSSEEvents(payload) {
330
+ const events = [];
331
+ const lines = payload.split(/\n/);
332
+ let buffer = [];
333
+ const flush = () => {
334
+ if (!buffer.length) {
335
+ return;
336
+ }
337
+ const data = buffer.join("\n").trim();
338
+ buffer = [];
339
+ if (!data || data === "[DONE]") {
340
+ return;
341
+ }
342
+ try {
343
+ const parsed = JSON.parse(data);
344
+ if (isJsonObject(parsed)) {
345
+ events.push(parsed);
346
+ }
347
+ }
348
+ catch {
349
+ // ignore invalid chunks
350
+ }
351
+ };
352
+ for (const raw of lines) {
353
+ if (raw.startsWith("data:")) {
354
+ buffer.push(raw.slice(5).trimStart());
355
+ }
356
+ else if (raw.trim() === "") {
357
+ flush();
358
+ }
359
+ }
360
+ flush();
361
+ return events;
362
+ }
363
+ function consolidateChatCompletionChunks(chunks) {
364
+ const result = {
365
+ id: chunks[0]?.id ?? "streamed-response",
366
+ object: "chat.completion",
367
+ created: chunks[0]?.created ?? Math.floor(Date.now() / 1000),
368
+ model: chunks[0]?.model,
369
+ usage: {},
370
+ choices: [],
371
+ };
372
+ const choiceStates = new Map();
373
+ for (const chunk of chunks) {
374
+ if (!chunk || typeof chunk !== "object") {
375
+ continue;
376
+ }
377
+ if (chunk.id) {
378
+ result.id = chunk.id;
379
+ }
380
+ if (chunk.created) {
381
+ result.created = chunk.created;
382
+ }
383
+ if (chunk.model) {
384
+ result.model = chunk.model;
385
+ }
386
+ if (chunk.usage) {
387
+ result.usage = chunk.usage;
388
+ }
389
+ const choices = asJsonObjectArray(chunk.choices);
390
+ for (const choice of choices) {
391
+ const index = typeof choice.index === "number" ? choice.index : 0;
392
+ let state = choiceStates.get(index);
393
+ if (!state) {
394
+ state = {
395
+ index,
396
+ textBuffer: "",
397
+ contentMode: "string",
398
+ contentParts: [],
399
+ };
400
+ choiceStates.set(index, state);
401
+ }
402
+ const delta = asJsonObject(choice.delta);
403
+ if (typeof delta.role === "string") {
404
+ state.role = delta.role;
405
+ }
406
+ appendDeltaContent(state, delta.content);
407
+ appendDeltaToolCalls(state, delta.tool_calls);
408
+ if (typeof choice.finish_reason === "string") {
409
+ state.finishReason = choice.finish_reason;
410
+ }
411
+ }
412
+ }
413
+ result.choices = Array.from(choiceStates.values())
414
+ .sort((a, b) => a.index - b.index)
415
+ .map((state) => ({
416
+ index: state.index,
417
+ finish_reason: state.finishReason ?? null,
418
+ message: {
419
+ role: state.role ?? "assistant",
420
+ content: finalizeContent(state),
421
+ ...(state.toolCalls?.length ? { tool_calls: state.toolCalls } : {}),
422
+ },
423
+ }));
424
+ return result;
425
+ }
426
+ function appendDeltaContent(state, content) {
427
+ if (content === undefined || content === null) {
428
+ return;
429
+ }
430
+ if (typeof content === "string") {
431
+ if (state.contentMode === "array") {
432
+ state.contentParts.push({ type: "text", text: content });
433
+ }
434
+ else {
435
+ state.textBuffer += content;
436
+ }
437
+ return;
438
+ }
439
+ if (Array.isArray(content)) {
440
+ ensureArrayContent(state);
441
+ for (const part of content) {
442
+ if (part === undefined || part === null) {
443
+ continue;
444
+ }
445
+ if (typeof part === "string") {
446
+ state.contentParts.push({ type: "text", text: part });
447
+ }
448
+ else {
449
+ state.contentParts.push(part);
450
+ }
451
+ }
452
+ return;
453
+ }
454
+ if (typeof content === "object") {
455
+ ensureArrayContent(state);
456
+ state.contentParts.push(content);
457
+ }
458
+ }
459
+ function ensureArrayContent(state) {
460
+ if (state.contentMode === "array") {
461
+ return;
462
+ }
463
+ state.contentMode = "array";
464
+ if (state.textBuffer) {
465
+ state.contentParts.push({ type: "text", text: state.textBuffer });
466
+ state.textBuffer = "";
467
+ }
468
+ }
469
+ function appendDeltaToolCalls(state, toolCalls) {
470
+ if (!Array.isArray(toolCalls)) {
471
+ return;
472
+ }
473
+ state.toolCalls = state.toolCalls ?? [];
474
+ for (const call of toolCalls) {
475
+ if (!isJsonObject(call)) {
476
+ continue;
477
+ }
478
+ const index = typeof call.index === "number" ? call.index : state.toolCalls.length;
479
+ if (!state.toolCalls[index]) {
480
+ state.toolCalls[index] = {
481
+ id: typeof call.id === "string" ? call.id : undefined,
482
+ type: typeof call.type === "string" ? call.type : "function",
483
+ function: {
484
+ name: undefined,
485
+ arguments: "",
486
+ },
487
+ };
488
+ }
489
+ const target = state.toolCalls[index];
490
+ if (typeof call.id === "string") {
491
+ target.id = call.id;
492
+ }
493
+ if (typeof call.type === "string") {
494
+ target.type = call.type;
495
+ }
496
+ const fn = isJsonObject(call.function) ? call.function : undefined;
497
+ if (fn && typeof fn.name === "string") {
498
+ target.function.name = fn.name;
499
+ }
500
+ if (fn && typeof fn.arguments === "string") {
501
+ target.function.arguments =
502
+ (target.function.arguments ?? "") + fn.arguments;
503
+ }
504
+ }
505
+ }
506
+ function finalizeContent(state) {
507
+ if (state.contentMode === "array") {
508
+ if (state.textBuffer) {
509
+ state.contentParts.push({ type: "text", text: state.textBuffer });
510
+ state.textBuffer = "";
511
+ }
512
+ return state.contentParts;
513
+ }
514
+ return state.textBuffer;
515
+ }
516
+ function convertChoiceToResponseOutputs(choice, index, responseId) {
517
+ const message = asJsonObject(choice?.message);
518
+ const content = buildResponseContent(message);
519
+ const outputs = [];
520
+ const finishReason = typeof choice?.finish_reason === "string" ? choice.finish_reason : "stop";
521
+ const resolvedResponseId = responseId ?? "resp";
522
+ const messageId = typeof message.id === "string" && message.id.length
523
+ ? message.id
524
+ : `${resolvedResponseId}_msg_${index}`;
525
+ const role = typeof message.role === "string" ? message.role : "assistant";
526
+ const messageOutput = {
527
+ id: messageId,
528
+ object: "message",
529
+ type: "message",
530
+ role,
531
+ status: resolveItemStatus(finishReason),
532
+ content,
533
+ };
534
+ if (isJsonObject(message.metadata)) {
535
+ messageOutput.metadata = message.metadata;
536
+ }
537
+ if (message.refusal) {
538
+ messageOutput.content.push(createRefusalBlock(message.refusal));
539
+ }
540
+ outputs.push(messageOutput);
541
+ const reasoningBlocks = normalizeReasoningContent(message.reasoning_content ?? []);
542
+ const reasoningRecord = asJsonObject(message.reasoning);
543
+ const reasoningSummarySource = message.reasoning_summary ?? reasoningRecord.summary;
544
+ const reasoningSummary = normalizeReasoningSummary(reasoningSummarySource);
545
+ if (reasoningBlocks.length || reasoningSummary.length) {
546
+ outputs.push({
547
+ id: `${messageId}_reasoning`,
548
+ object: "reasoning",
549
+ type: "reasoning",
550
+ status: "completed",
551
+ summary: reasoningSummary,
552
+ content: reasoningBlocks,
553
+ });
554
+ }
555
+ const toolCalls = asJsonObjectArray(message.tool_calls);
556
+ if (toolCalls.length) {
557
+ for (const [toolIndex, toolCall] of toolCalls.entries()) {
558
+ outputs.push(convertToolCallOutput(toolCall, {
559
+ responseId,
560
+ choiceIndex: index,
561
+ toolIndex,
562
+ }));
563
+ }
564
+ }
565
+ return outputs;
566
+ }
567
+ function buildResponseContent(message) {
568
+ const content = message?.content;
569
+ const blocks = [];
570
+ if (Array.isArray(content)) {
571
+ for (const part of content) {
572
+ blocks.push(convertContentPart(part));
573
+ }
574
+ }
575
+ else if (typeof content === "string") {
576
+ blocks.push({ type: "output_text", text: content });
577
+ }
578
+ else if (content && typeof content === "object") {
579
+ blocks.push(convertContentPart(content));
580
+ }
581
+ return blocks.length ? blocks : [{ type: "output_text", text: "" }];
582
+ }
583
+ function convertContentPart(part) {
584
+ if (part === undefined || part === null) {
585
+ return { type: "output_text", text: "" };
586
+ }
587
+ if (typeof part === "string") {
588
+ return { type: "output_text", text: part };
589
+ }
590
+ if (typeof part === "object") {
591
+ const record = part;
592
+ const type = record.type ?? "text";
593
+ if (type === "text" || type === "output_text") {
594
+ return { type: "output_text", text: String(record.text ?? "") };
595
+ }
596
+ if (type === "image_url") {
597
+ return {
598
+ type: "output_image",
599
+ image_url: record.image_url ?? record.url ?? null,
600
+ };
601
+ }
602
+ if (record.text !== undefined) {
603
+ return { type: "output_text", text: String(record.text) };
604
+ }
605
+ return { ...record };
606
+ }
607
+ return { type: "output_text", text: String(part) };
608
+ }
609
+ function convertToolCallOutput(toolCall, params) {
610
+ const record = isJsonObject(toolCall) ? toolCall : {};
611
+ const fn = isJsonObject(record.function) ? record.function : {};
612
+ const toolId = typeof record.id === "string"
613
+ ? record.id
614
+ : `${params.responseId ?? "resp"}_tool_${params.choiceIndex}_${params.toolIndex}`;
615
+ const callId = typeof fn.call_id === "string"
616
+ ? fn.call_id
617
+ : typeof record.id === "string"
618
+ ? record.id
619
+ : `${params.responseId ?? "resp"}_call_${params.choiceIndex}_${params.toolIndex}`;
620
+ const resolvedArgs = typeof fn.arguments === "string"
621
+ ? fn.arguments
622
+ : fn.arguments !== undefined
623
+ ? JSON.stringify(fn.arguments)
624
+ : "";
625
+ return {
626
+ id: toolId,
627
+ object: "function_call",
628
+ type: "function_call",
629
+ status: "completed",
630
+ name: typeof fn.name === "string" ? fn.name : undefined,
631
+ call_id: callId,
632
+ arguments: resolvedArgs,
633
+ };
634
+ }
635
+ function resolveItemStatus(finishReason) {
636
+ if (!finishReason ||
637
+ finishReason === "stop" ||
638
+ finishReason === "tool_calls") {
639
+ return "completed";
640
+ }
641
+ return "incomplete";
642
+ }
643
+ function createRefusalBlock(refusal) {
644
+ if (typeof refusal === "string") {
645
+ return { type: "output_refusal", text: refusal };
646
+ }
647
+ if (isJsonObject(refusal)) {
648
+ const text = typeof refusal.text === "string" ? refusal.text : "";
649
+ const reason = typeof refusal.reason === "string" ? refusal.reason : undefined;
650
+ return {
651
+ type: "output_refusal",
652
+ text,
653
+ reason,
654
+ content: refusal.content,
655
+ };
656
+ }
657
+ return { type: "output_refusal", text: "" };
658
+ }
659
+ function normalizeReasoningContent(value) {
660
+ const parts = Array.isArray(value) ? value : [value];
661
+ const blocks = [];
662
+ for (const entry of parts) {
663
+ if (typeof entry === "string") {
664
+ blocks.push({ type: "reasoning_text", text: entry });
665
+ continue;
666
+ }
667
+ if (isJsonObject(entry)) {
668
+ const textValue = typeof entry.text === "string"
669
+ ? entry.text
670
+ : typeof entry.thinking === "string"
671
+ ? entry.thinking
672
+ : "";
673
+ const block = {
674
+ type: "reasoning_text",
675
+ text: textValue,
676
+ };
677
+ if (entry.signature) {
678
+ block.signature = entry.signature;
679
+ }
680
+ blocks.push(block);
681
+ continue;
682
+ }
683
+ if (entry !== undefined && entry !== null) {
684
+ blocks.push({ type: "reasoning_text", text: String(entry) });
685
+ }
686
+ }
687
+ return blocks;
688
+ }
689
+ function normalizeReasoningSummary(value) {
690
+ if (value === undefined || value === null) {
691
+ return [];
692
+ }
693
+ const parts = Array.isArray(value) ? value : [value];
694
+ const summaries = [];
695
+ for (const entry of parts) {
696
+ if (typeof entry === "string") {
697
+ const text = entry.trim();
698
+ if (text) {
699
+ summaries.push({ type: "summary_text", text });
700
+ }
701
+ continue;
702
+ }
703
+ if (!isJsonObject(entry)) {
704
+ continue;
705
+ }
706
+ const textValue = typeof entry.text === "string"
707
+ ? entry.text
708
+ : typeof entry.summary === "string"
709
+ ? entry.summary
710
+ : undefined;
711
+ if (textValue && textValue.trim()) {
712
+ summaries.push({ type: "summary_text", text: textValue.trim() });
713
+ }
714
+ }
715
+ return summaries;
716
+ }
717
+ function createEmptyOutput(responseId) {
718
+ return {
719
+ id: `${responseId ?? "resp"}_msg_0`,
720
+ object: "message",
721
+ type: "message",
722
+ role: "assistant",
723
+ status: "completed",
724
+ content: [{ type: "output_text", text: "" }],
725
+ };
726
+ }
727
+ function resolveResponseStatus() {
728
+ return "completed";
729
+ }
730
+ function collectOutputText(outputs) {
731
+ const collected = outputs
732
+ .flatMap((output) => asJsonObjectArray(output.content))
733
+ .filter((content) => content?.type === "output_text")
734
+ .map((content) => {
735
+ const textValue = content?.text;
736
+ return typeof textValue === "string" ? textValue : "";
737
+ })
738
+ .filter((text) => text.length > 0);
739
+ return collected;
740
+ }
741
+ function normalizeResponseUsage(rawUsage) {
742
+ if (!isJsonObject(rawUsage)) {
743
+ return null;
744
+ }
745
+ const toNumber = (value) => {
746
+ if (typeof value === "number" && Number.isFinite(value)) {
747
+ return value;
748
+ }
749
+ if (typeof value === "string" &&
750
+ value.trim().length &&
751
+ Number.isFinite(Number(value))) {
752
+ return Number(value);
753
+ }
754
+ return undefined;
755
+ };
756
+ const inputTokens = toNumber(rawUsage.input_tokens) ?? toNumber(rawUsage.prompt_tokens);
757
+ const outputTokens = toNumber(rawUsage.output_tokens) ?? toNumber(rawUsage.completion_tokens);
758
+ const totalTokens = toNumber(rawUsage.total_tokens) ?? (inputTokens ?? 0) + (outputTokens ?? 0);
759
+ const normalized = {
760
+ input_tokens: inputTokens ?? 0,
761
+ output_tokens: outputTokens ?? 0,
762
+ total_tokens: totalTokens ?? 0,
763
+ };
764
+ const inputDetails = isJsonObject(rawUsage.input_tokens_details)
765
+ ? rawUsage.input_tokens_details
766
+ : isJsonObject(rawUsage.prompt_tokens_details)
767
+ ? rawUsage.prompt_tokens_details
768
+ : null;
769
+ if (inputDetails) {
770
+ const cached = toNumber(inputDetails.cached_tokens) ??
771
+ toNumber(inputDetails.cached) ??
772
+ 0;
773
+ normalized.input_tokens_details = { cached_tokens: cached };
774
+ }
775
+ const outputDetails = isJsonObject(rawUsage.output_tokens_details)
776
+ ? rawUsage.output_tokens_details
777
+ : null;
778
+ if (outputDetails) {
779
+ const reasoning = toNumber(outputDetails.reasoning_tokens) ??
780
+ toNumber(outputDetails.cached_tokens) ??
781
+ 0;
782
+ normalized.output_tokens_details = { reasoning_tokens: reasoning };
783
+ }
784
+ else if (rawUsage.reasoning_tokens !== undefined) {
785
+ normalized.output_tokens_details = {
786
+ reasoning_tokens: toNumber(rawUsage.reasoning_tokens) ?? 0,
787
+ };
788
+ }
789
+ if (rawUsage.extra_properties) {
790
+ normalized.extra_properties = rawUsage.extra_properties;
791
+ }
792
+ return normalized;
793
+ }
794
+ //# sourceMappingURL=openaiPassthrough.js.map