aicodeswitch 4.0.3 → 5.0.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/README.md +7 -6
- package/UPGRADE.md +5 -6
- package/dist/server/coding-plan.js +94 -0
- package/dist/server/config-managed-fields.js +1 -0
- package/dist/server/conversions/compact.js +613 -0
- package/dist/server/conversions/detector.js +70 -0
- package/dist/server/conversions/index.js +285 -0
- package/dist/server/conversions/pairs/claude-completions/request.js +167 -0
- package/dist/server/conversions/pairs/claude-completions/response.js +56 -0
- package/dist/server/conversions/pairs/claude-completions/streaming.js +259 -0
- package/dist/server/conversions/pairs/claude-gemini/request.js +130 -0
- package/dist/server/conversions/pairs/claude-gemini/response.js +65 -0
- package/dist/server/conversions/pairs/claude-gemini/streaming.js +199 -0
- package/dist/server/conversions/pairs/claude-responses/request.js +190 -0
- package/dist/server/conversions/pairs/claude-responses/response.js +89 -0
- package/dist/server/conversions/pairs/claude-responses/streaming.js +266 -0
- package/dist/server/conversions/pairs/completions-claude/request.js +111 -0
- package/dist/server/conversions/pairs/completions-claude/response.js +67 -0
- package/dist/server/conversions/pairs/completions-claude/streaming.js +165 -0
- package/dist/server/conversions/pairs/completions-gemini/request.js +169 -0
- package/dist/server/conversions/pairs/completions-gemini/response.js +70 -0
- package/dist/server/conversions/pairs/completions-gemini/streaming.js +132 -0
- package/dist/server/conversions/pairs/completions-responses/request.js +149 -0
- package/dist/server/conversions/pairs/completions-responses/response.js +74 -0
- package/dist/server/conversions/pairs/completions-responses/streaming.js +189 -0
- package/dist/server/conversions/pairs/gemini-claude/request.js +118 -0
- package/dist/server/conversions/pairs/gemini-claude/response.js +45 -0
- package/dist/server/conversions/pairs/gemini-claude/streaming.js +146 -0
- package/dist/server/conversions/pairs/gemini-completions/request.js +151 -0
- package/dist/server/conversions/pairs/gemini-completions/response.js +54 -0
- package/dist/server/conversions/pairs/gemini-completions/streaming.js +108 -0
- package/dist/server/conversions/pairs/gemini-responses/request.js +18 -0
- package/dist/server/conversions/pairs/gemini-responses/response.js +18 -0
- package/dist/server/conversions/pairs/gemini-responses/streaming.js +43 -0
- package/dist/server/conversions/pairs/responses-claude/request.js +155 -0
- package/dist/server/conversions/pairs/responses-claude/response.js +70 -0
- package/dist/server/conversions/pairs/responses-claude/streaming.js +345 -0
- package/dist/server/conversions/pairs/responses-completions/request.js +207 -0
- package/dist/server/conversions/pairs/responses-completions/response.js +96 -0
- package/dist/server/conversions/pairs/responses-completions/streaming.js +344 -0
- package/dist/server/conversions/pairs/responses-gemini/request.js +18 -0
- package/dist/server/conversions/pairs/responses-gemini/response.js +18 -0
- package/dist/server/conversions/pairs/responses-gemini/streaming.js +43 -0
- package/dist/server/conversions/pairs/responses-responses/request.js +115 -0
- package/dist/server/conversions/pipeline.js +296 -0
- package/dist/server/conversions/stream-converter-adapter.js +49 -0
- package/dist/server/conversions/thinking/effort.js +61 -0
- package/dist/server/conversions/thinking/mapper.js +59 -0
- package/dist/server/conversions/thinking/providers.js +76 -0
- package/dist/server/conversions/types.js +5 -0
- package/dist/server/conversions/url-normalizer.js +58 -0
- package/dist/server/conversions/utils/format-mappers.js +57 -0
- package/dist/server/conversions/utils/id.js +33 -0
- package/dist/server/conversions/utils/stop-reasons.js +95 -0
- package/dist/server/conversions/utils/streaming-helpers.js +59 -0
- package/dist/server/conversions/utils/tool-schema.js +169 -0
- package/dist/server/conversions/utils/usage.js +82 -0
- package/dist/server/fs-database.js +465 -135
- package/dist/server/main.js +93 -33
- package/dist/server/original-config-reader.js +1 -1
- package/dist/server/proxy-server.js +1102 -804
- package/dist/server/transformers/chunk-collector.js +5 -1
- package/dist/server/transformers/streaming.js +6 -3235
- package/dist/server/type-migration.js +2 -3
- package/dist/server/utils.js +5 -0
- package/dist/ui/assets/{index-C7G0whng.css → index-BHR12ImE.css} +1 -1
- package/dist/ui/assets/index-DjdBW1yu.js +517 -0
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/server/transformers/transformers.js +0 -1767
- package/dist/ui/assets/index-Nl6yJxrc.js +0 -514
- package/schema/claude.schema.md +0 -946
- package/schema/deepseek-chat.schema.md +0 -799
- package/schema/gemini.schema.md +0 -1408
- package/schema/openai-chat-completions.schema.md +0 -1088
- package/schema/openai-responses.schema.md +0 -226196
- package/schema/stream.md +0 -2592
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude SSE → Gemini SSE streaming converter.
|
|
4
|
+
*
|
|
5
|
+
* ClaudeToGeminiConverter: Stateful converter for Claude SSE → Gemini SSE.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.ClaudeToGeminiConverter = void 0;
|
|
9
|
+
const stop_reasons_js_1 = require("../../utils/stop-reasons.js");
|
|
10
|
+
const streaming_helpers_js_1 = require("../../utils/streaming-helpers.js");
|
|
11
|
+
/**
|
|
12
|
+
* Stateful converter that transforms Claude SSE events into Gemini streaming
|
|
13
|
+
* chunks. Gemini streaming uses cumulative snapshots, so the converter
|
|
14
|
+
* accumulates Claude content and outputs Gemini cumulative candidate objects.
|
|
15
|
+
*/
|
|
16
|
+
class ClaudeToGeminiConverter {
|
|
17
|
+
constructor() {
|
|
18
|
+
Object.defineProperty(this, "textContent", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: ''
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "toolCalls", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: []
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "currentToolJson", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: ''
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
convertEvent(event) {
|
|
38
|
+
var _a, _b, _c;
|
|
39
|
+
if (!event.data)
|
|
40
|
+
return [];
|
|
41
|
+
// Pass through [DONE]
|
|
42
|
+
if (event.data === '[DONE]' || (typeof event.data === 'object' && ((_a = event.data) === null || _a === void 0 ? void 0 : _a.type) === 'done')) {
|
|
43
|
+
return [{ data: '[DONE]', event: event.event }];
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const parsed = (0, streaming_helpers_js_1.parseEventData)(event.data);
|
|
47
|
+
const type = parsed.type;
|
|
48
|
+
const results = [];
|
|
49
|
+
switch (type) {
|
|
50
|
+
case 'message_start':
|
|
51
|
+
// Nothing to emit for Gemini on start
|
|
52
|
+
break;
|
|
53
|
+
case 'content_block_start': {
|
|
54
|
+
const block = parsed.content_block;
|
|
55
|
+
if ((block === null || block === void 0 ? void 0 : block.type) === 'text') {
|
|
56
|
+
this.textContent = '';
|
|
57
|
+
}
|
|
58
|
+
else if ((block === null || block === void 0 ? void 0 : block.type) === 'tool_use') {
|
|
59
|
+
this.currentToolJson = '';
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case 'content_block_delta': {
|
|
64
|
+
const delta = parsed.delta;
|
|
65
|
+
if ((delta === null || delta === void 0 ? void 0 : delta.type) === 'text_delta' && delta.text) {
|
|
66
|
+
this.textContent += delta.text;
|
|
67
|
+
// Emit cumulative snapshot
|
|
68
|
+
results.push({
|
|
69
|
+
data: this.buildCumulativeChunk(),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else if ((delta === null || delta === void 0 ? void 0 : delta.type) === 'input_json_delta' && delta.partial_json) {
|
|
73
|
+
this.currentToolJson += delta.partial_json;
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case 'content_block_stop': {
|
|
78
|
+
// If we were accumulating a tool call, finalize it
|
|
79
|
+
if (this.currentToolJson) {
|
|
80
|
+
try {
|
|
81
|
+
const args = JSON.parse(this.currentToolJson);
|
|
82
|
+
this.toolCalls.push(args);
|
|
83
|
+
}
|
|
84
|
+
catch (_d) {
|
|
85
|
+
this.toolCalls.push({ name: '', args: {}, raw: this.currentToolJson });
|
|
86
|
+
}
|
|
87
|
+
this.currentToolJson = '';
|
|
88
|
+
// Emit snapshot with the new tool call included
|
|
89
|
+
results.push({
|
|
90
|
+
data: this.buildCumulativeChunk(),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case 'message_delta': {
|
|
96
|
+
const stopReason = (0, stop_reasons_js_1.claudeToGeminiStopReason)((_b = parsed.delta) === null || _b === void 0 ? void 0 : _b.stop_reason);
|
|
97
|
+
const usage = parsed.usage;
|
|
98
|
+
const chunk = this.buildCumulativeChunk();
|
|
99
|
+
// Set finishReason on the first candidate
|
|
100
|
+
if ((_c = chunk.candidates) === null || _c === void 0 ? void 0 : _c[0]) {
|
|
101
|
+
chunk.candidates[0].finishReason = stopReason;
|
|
102
|
+
}
|
|
103
|
+
if (usage === null || usage === void 0 ? void 0 : usage.output_tokens) {
|
|
104
|
+
chunk.usageMetadata = chunk.usageMetadata || {};
|
|
105
|
+
chunk.usageMetadata.candidatesTokenCount = usage.output_tokens;
|
|
106
|
+
}
|
|
107
|
+
results.push({ data: chunk });
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case 'message_stop':
|
|
111
|
+
// Nothing extra to emit
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
return results;
|
|
115
|
+
}
|
|
116
|
+
catch (_e) {
|
|
117
|
+
return [event];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// --- Helpers --------------------------------------------------------------
|
|
121
|
+
buildCumulativeChunk() {
|
|
122
|
+
const parts = [];
|
|
123
|
+
if (this.textContent) {
|
|
124
|
+
parts.push({ text: this.textContent });
|
|
125
|
+
}
|
|
126
|
+
for (const tc of this.toolCalls) {
|
|
127
|
+
parts.push({
|
|
128
|
+
functionCall: {
|
|
129
|
+
name: tc.name || '',
|
|
130
|
+
args: tc.args || tc,
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
candidates: [
|
|
136
|
+
{
|
|
137
|
+
content: {
|
|
138
|
+
parts: parts.length > 0 ? parts : [],
|
|
139
|
+
role: 'model',
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
exports.ClaudeToGeminiConverter = ClaudeToGeminiConverter;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gemini generateContent → OpenAI Chat Completions request conversion.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.geminiToCompletions = geminiToCompletions;
|
|
7
|
+
/**
|
|
8
|
+
* Convert a Gemini generateContent request body to a Chat Completions request body.
|
|
9
|
+
*/
|
|
10
|
+
function geminiToCompletions(body) {
|
|
11
|
+
var _a, _b, _c, _d;
|
|
12
|
+
const messages = [];
|
|
13
|
+
// --- System instruction → system message ---
|
|
14
|
+
if (body.systemInstruction) {
|
|
15
|
+
const text = (body.systemInstruction.parts || [])
|
|
16
|
+
.map((p) => p.text || '')
|
|
17
|
+
.join('\n\n');
|
|
18
|
+
if (text) {
|
|
19
|
+
messages.push({ role: 'system', content: text });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// --- Contents → messages ---
|
|
23
|
+
if (body.contents) {
|
|
24
|
+
for (const entry of body.contents) {
|
|
25
|
+
const role = entry.role === 'model' ? 'assistant' : 'user';
|
|
26
|
+
const converted = convertGeminiPartsToCompletionsMessage(entry.parts, role);
|
|
27
|
+
if (converted)
|
|
28
|
+
messages.push(converted);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// --- Build result ---
|
|
32
|
+
const result = {
|
|
33
|
+
messages,
|
|
34
|
+
stream: false,
|
|
35
|
+
};
|
|
36
|
+
// --- Generation config reverse mapping ---
|
|
37
|
+
const gc = body.generationConfig || {};
|
|
38
|
+
if (gc.maxOutputTokens)
|
|
39
|
+
result.max_tokens = gc.maxOutputTokens;
|
|
40
|
+
if (gc.temperature !== undefined)
|
|
41
|
+
result.temperature = gc.temperature;
|
|
42
|
+
if (gc.topP !== undefined)
|
|
43
|
+
result.top_p = gc.topP;
|
|
44
|
+
if (gc.stopSequences)
|
|
45
|
+
result.stop = gc.stopSequences;
|
|
46
|
+
// --- Tools reverse mapping ---
|
|
47
|
+
const funcDecls = ((_a = body.tools) === null || _a === void 0 ? void 0 : _a.flatMap((t) => t.functionDeclarations || t)) || [];
|
|
48
|
+
if (funcDecls.length > 0) {
|
|
49
|
+
result.tools = funcDecls.map((fd) => ({
|
|
50
|
+
type: 'function',
|
|
51
|
+
function: {
|
|
52
|
+
name: fd.name,
|
|
53
|
+
description: fd.description || '',
|
|
54
|
+
parameters: fd.parameters || {},
|
|
55
|
+
},
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
// --- ToolConfig reverse mapping ---
|
|
59
|
+
if ((_b = body.toolConfig) === null || _b === void 0 ? void 0 : _b.functionCallingConfig) {
|
|
60
|
+
const fcc = body.toolConfig.functionCallingConfig;
|
|
61
|
+
if (fcc.mode === 'ANY') {
|
|
62
|
+
if (((_c = fcc.allowedFunctionNames) === null || _c === void 0 ? void 0 : _c.length) === 1) {
|
|
63
|
+
result.tool_choice = { type: 'function', function: { name: fcc.allowedFunctionNames[0] } };
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
result.tool_choice = 'required';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (fcc.mode === 'AUTO') {
|
|
70
|
+
result.tool_choice = 'auto';
|
|
71
|
+
}
|
|
72
|
+
else if (fcc.mode === 'NONE') {
|
|
73
|
+
result.tool_choice = 'none';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// --- Thinking config → reasoning_effort ---
|
|
77
|
+
if ((_d = gc.thinkingConfig) === null || _d === void 0 ? void 0 : _d.thinkingBudget) {
|
|
78
|
+
result.reasoning_effort = mapThinkingBudgetToEffort(gc.thinkingConfig.thinkingBudget);
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Convert Gemini parts array to a Completions message object.
|
|
84
|
+
*/
|
|
85
|
+
function convertGeminiPartsToCompletionsMessage(parts, role) {
|
|
86
|
+
var _a;
|
|
87
|
+
if (!parts || parts.length === 0)
|
|
88
|
+
return { role, content: '' };
|
|
89
|
+
const texts = [];
|
|
90
|
+
const toolCalls = [];
|
|
91
|
+
let hasFunctionResponse = false;
|
|
92
|
+
let functionResponseContent;
|
|
93
|
+
let functionResponseName;
|
|
94
|
+
for (const part of parts) {
|
|
95
|
+
if (part.text !== undefined && part.text !== null) {
|
|
96
|
+
texts.push(part.text);
|
|
97
|
+
}
|
|
98
|
+
else if (part.functionCall) {
|
|
99
|
+
toolCalls.push({
|
|
100
|
+
id: `call_${Math.random().toString(36).slice(2, 14)}`,
|
|
101
|
+
type: 'function',
|
|
102
|
+
function: {
|
|
103
|
+
name: part.functionCall.name || '',
|
|
104
|
+
arguments: typeof part.functionCall.args === 'string'
|
|
105
|
+
? part.functionCall.args
|
|
106
|
+
: JSON.stringify(part.functionCall.args || {}),
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else if (part.functionResponse) {
|
|
111
|
+
hasFunctionResponse = true;
|
|
112
|
+
functionResponseName = part.functionResponse.name;
|
|
113
|
+
functionResponseContent = ((_a = part.functionResponse.response) === null || _a === void 0 ? void 0 : _a.content)
|
|
114
|
+
|| JSON.stringify(part.functionResponse.response);
|
|
115
|
+
}
|
|
116
|
+
else if (part.inlineData) {
|
|
117
|
+
texts.push(`data:${part.inlineData.mimeType};base64,${part.inlineData.data}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Tool result message
|
|
121
|
+
if (hasFunctionResponse) {
|
|
122
|
+
return {
|
|
123
|
+
role: 'tool',
|
|
124
|
+
tool_call_id: functionResponseName || '',
|
|
125
|
+
content: functionResponseContent || '',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Assistant message with tool calls
|
|
129
|
+
if (role === 'assistant' && toolCalls.length > 0) {
|
|
130
|
+
return {
|
|
131
|
+
role: 'assistant',
|
|
132
|
+
content: texts.join('') || null,
|
|
133
|
+
tool_calls: toolCalls,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// Plain message
|
|
137
|
+
return {
|
|
138
|
+
role,
|
|
139
|
+
content: texts.join('') || '',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// Helpers
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
function mapThinkingBudgetToEffort(budget) {
|
|
146
|
+
if (budget <= 4096)
|
|
147
|
+
return 'low';
|
|
148
|
+
if (budget <= 16384)
|
|
149
|
+
return 'medium';
|
|
150
|
+
return 'high';
|
|
151
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Completions → Gemini response conversion for gemini-completions pair.
|
|
4
|
+
*
|
|
5
|
+
* Client=gemini, upstream=completions.
|
|
6
|
+
* Converts upstream Chat Completions response → client Gemini generateContent response.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.completionsToGeminiResponse = completionsToGeminiResponse;
|
|
10
|
+
const format_mappers_js_1 = require("../../utils/format-mappers.js");
|
|
11
|
+
/**
|
|
12
|
+
* Convert a Chat Completions response to a Gemini generateContent response.
|
|
13
|
+
*/
|
|
14
|
+
function completionsToGeminiResponse(response) {
|
|
15
|
+
var _a, _b, _c, _d, _e, _f;
|
|
16
|
+
const choice = (_a = response.choices) === null || _a === void 0 ? void 0 : _a[0];
|
|
17
|
+
if (!choice)
|
|
18
|
+
return response;
|
|
19
|
+
const parts = [];
|
|
20
|
+
// Text content
|
|
21
|
+
if ((_b = choice.message) === null || _b === void 0 ? void 0 : _b.content) {
|
|
22
|
+
parts.push({ text: choice.message.content });
|
|
23
|
+
}
|
|
24
|
+
// Tool calls → functionCall parts
|
|
25
|
+
if ((_c = choice.message) === null || _c === void 0 ? void 0 : _c.tool_calls) {
|
|
26
|
+
for (const tc of choice.message.tool_calls) {
|
|
27
|
+
const args = typeof ((_d = tc.function) === null || _d === void 0 ? void 0 : _d.arguments) === 'string'
|
|
28
|
+
? JSON.parse(tc.function.arguments)
|
|
29
|
+
: ((_e = tc.function) === null || _e === void 0 ? void 0 : _e.arguments) || {};
|
|
30
|
+
parts.push({
|
|
31
|
+
functionCall: {
|
|
32
|
+
name: ((_f = tc.function) === null || _f === void 0 ? void 0 : _f.name) || '',
|
|
33
|
+
args,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (parts.length === 0) {
|
|
39
|
+
parts.push({ text: '' });
|
|
40
|
+
}
|
|
41
|
+
const finishReason = (0, format_mappers_js_1.mapCompletionsFinishReason)(choice.finish_reason);
|
|
42
|
+
const usage = (0, format_mappers_js_1.mapCompletionsUsage)(response.usage);
|
|
43
|
+
return {
|
|
44
|
+
candidates: [{
|
|
45
|
+
content: {
|
|
46
|
+
role: 'model',
|
|
47
|
+
parts,
|
|
48
|
+
},
|
|
49
|
+
finishReason,
|
|
50
|
+
}],
|
|
51
|
+
usageMetadata: usage,
|
|
52
|
+
modelVersion: response.model || '',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI Chat Completions → Gemini generateContent streaming conversion.
|
|
4
|
+
*
|
|
5
|
+
* Stateful converter that processes Chat Completions SSE events and produces
|
|
6
|
+
* Gemini SSE events.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CompletionsToGeminiConverter = void 0;
|
|
10
|
+
const format_mappers_js_1 = require("../../utils/format-mappers.js");
|
|
11
|
+
const streaming_helpers_js_1 = require("../../utils/streaming-helpers.js");
|
|
12
|
+
/**
|
|
13
|
+
* Convert Chat Completions SSE events into Gemini generateContent SSE events.
|
|
14
|
+
*
|
|
15
|
+
* Accumulates text content and tool calls, emitting cumulative Gemini snapshots.
|
|
16
|
+
*/
|
|
17
|
+
class CompletionsToGeminiConverter {
|
|
18
|
+
constructor() {
|
|
19
|
+
Object.defineProperty(this, "started", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: false
|
|
24
|
+
});
|
|
25
|
+
Object.defineProperty(this, "textContent", {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
configurable: true,
|
|
28
|
+
writable: true,
|
|
29
|
+
value: ''
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(this, "toolCalls", {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
configurable: true,
|
|
34
|
+
writable: true,
|
|
35
|
+
value: new Map()
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
convertEvent(event) {
|
|
39
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
40
|
+
if (!event.data)
|
|
41
|
+
return [];
|
|
42
|
+
if (event.data === '[DONE]' || (typeof event.data === 'object' && ((_a = event.data) === null || _a === void 0 ? void 0 : _a.type) === 'done'))
|
|
43
|
+
return this.flush();
|
|
44
|
+
try {
|
|
45
|
+
const chunk = (0, streaming_helpers_js_1.parseEventData)(event.data);
|
|
46
|
+
const delta = (_c = (_b = chunk.choices) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.delta;
|
|
47
|
+
const finishReason = (_e = (_d = chunk.choices) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.finish_reason;
|
|
48
|
+
const parts = [];
|
|
49
|
+
// Text delta → accumulate and emit cumulative text
|
|
50
|
+
if (delta === null || delta === void 0 ? void 0 : delta.content) {
|
|
51
|
+
this.textContent += delta.content;
|
|
52
|
+
parts.push({ text: this.textContent });
|
|
53
|
+
}
|
|
54
|
+
// Reasoning content → no Gemini equivalent, skip
|
|
55
|
+
// Tool calls → accumulate arguments and emit functionCall
|
|
56
|
+
if (Array.isArray(delta === null || delta === void 0 ? void 0 : delta.tool_calls)) {
|
|
57
|
+
for (const tc of delta.tool_calls) {
|
|
58
|
+
const idx = (_f = tc.index) !== null && _f !== void 0 ? _f : 0;
|
|
59
|
+
const existing = this.toolCalls.get(idx);
|
|
60
|
+
if (!existing && ((_g = tc.function) === null || _g === void 0 ? void 0 : _g.name)) {
|
|
61
|
+
this.toolCalls.set(idx, {
|
|
62
|
+
name: tc.function.name,
|
|
63
|
+
argumentsText: ((_h = tc.function) === null || _h === void 0 ? void 0 : _h.arguments) || '',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else if (existing && ((_j = tc.function) === null || _j === void 0 ? void 0 : _j.arguments)) {
|
|
67
|
+
existing.argumentsText += tc.function.arguments;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Emit accumulated tool calls as functionCall parts
|
|
71
|
+
for (const [, tc] of this.toolCalls) {
|
|
72
|
+
parts.push({
|
|
73
|
+
functionCall: {
|
|
74
|
+
name: tc.name,
|
|
75
|
+
args: JSON.parse(tc.argumentsText || '{}'),
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (parts.length > 0 || !this.started) {
|
|
81
|
+
const candidate = {
|
|
82
|
+
content: { role: 'model', parts: parts.length > 0 ? parts : [{ text: '' }] },
|
|
83
|
+
};
|
|
84
|
+
if (finishReason) {
|
|
85
|
+
candidate.finishReason = (0, format_mappers_js_1.mapCompletionsFinishReason)(finishReason);
|
|
86
|
+
}
|
|
87
|
+
const result = { candidates: [candidate] };
|
|
88
|
+
if (chunk.usage) {
|
|
89
|
+
result.usageMetadata = {
|
|
90
|
+
promptTokenCount: (_k = chunk.usage.prompt_tokens) !== null && _k !== void 0 ? _k : 0,
|
|
91
|
+
candidatesTokenCount: (_l = chunk.usage.completion_tokens) !== null && _l !== void 0 ? _l : 0,
|
|
92
|
+
totalTokenCount: (_m = chunk.usage.total_tokens) !== null && _m !== void 0 ? _m : 0,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
this.started = true;
|
|
96
|
+
return [{ data: result, event: '' }];
|
|
97
|
+
}
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
catch (_o) {
|
|
101
|
+
return [event];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
flush() {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.CompletionsToGeminiConverter = CompletionsToGeminiConverter;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gemini → Responses API composite request conversion.
|
|
4
|
+
*
|
|
5
|
+
* Composes: gemini → completions → responses
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.geminiToResponsesRequest = geminiToResponsesRequest;
|
|
9
|
+
const request_js_1 = require("../gemini-completions/request.js");
|
|
10
|
+
const request_js_2 = require("../completions-responses/request.js");
|
|
11
|
+
/**
|
|
12
|
+
* Convert a Gemini request to a Responses API request.
|
|
13
|
+
* Path: gemini → completions → responses
|
|
14
|
+
*/
|
|
15
|
+
function geminiToResponsesRequest(body) {
|
|
16
|
+
const completionsBody = (0, request_js_1.geminiToCompletions)(body);
|
|
17
|
+
return (0, request_js_2.completionsToResponses)(completionsBody);
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Responses API → Gemini composite response conversion.
|
|
4
|
+
*
|
|
5
|
+
* Composes: responses → completions → gemini
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.responsesToGeminiResponse = responsesToGeminiResponse;
|
|
9
|
+
const response_js_1 = require("../completions-responses/response.js");
|
|
10
|
+
const response_js_2 = require("../gemini-completions/response.js");
|
|
11
|
+
/**
|
|
12
|
+
* Convert a Responses API response to a Gemini response.
|
|
13
|
+
* Path: responses → completions → gemini
|
|
14
|
+
*/
|
|
15
|
+
function responsesToGeminiResponse(response) {
|
|
16
|
+
const completionsResponse = (0, response_js_1.responsesToCompletionsResponse)(response);
|
|
17
|
+
return (0, response_js_2.completionsToGeminiResponse)(completionsResponse);
|
|
18
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Composite streaming converter: Responses API SSE → Gemini SSE.
|
|
4
|
+
*
|
|
5
|
+
* Chains: ResponsesToCompletionsConverter → CompletionsToGeminiConverter
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.ResponsesToGeminiConverter = void 0;
|
|
9
|
+
const streaming_js_1 = require("../completions-responses/streaming.js");
|
|
10
|
+
const streaming_js_2 = require("../gemini-completions/streaming.js");
|
|
11
|
+
const streaming_helpers_js_1 = require("../../utils/streaming-helpers.js");
|
|
12
|
+
/**
|
|
13
|
+
* Composite converter: Responses API SSE → Completions SSE → Gemini SSE
|
|
14
|
+
*/
|
|
15
|
+
class ResponsesToGeminiConverter {
|
|
16
|
+
constructor() {
|
|
17
|
+
Object.defineProperty(this, "first", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: void 0
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(this, "second", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true,
|
|
27
|
+
value: void 0
|
|
28
|
+
});
|
|
29
|
+
this.first = new streaming_js_1.ResponsesToCompletionsConverter();
|
|
30
|
+
this.second = new streaming_js_2.CompletionsToGeminiConverter();
|
|
31
|
+
}
|
|
32
|
+
convertEvent(event) {
|
|
33
|
+
const intermediate = this.first.convertEvent(event);
|
|
34
|
+
return intermediate.flatMap((e) => this.second.convertEvent(e));
|
|
35
|
+
}
|
|
36
|
+
flush() {
|
|
37
|
+
const intermediate = (0, streaming_helpers_js_1.flushConverter)(this.first);
|
|
38
|
+
const secondFromIntermediate = intermediate.flatMap((e) => this.second.convertEvent(e));
|
|
39
|
+
const secondFlush = (0, streaming_helpers_js_1.flushConverter)(this.second);
|
|
40
|
+
return [...secondFromIntermediate, ...secondFlush];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.ResponsesToGeminiConverter = ResponsesToGeminiConverter;
|