aicodeswitch 4.0.4 → 5.1.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 +6 -5
- 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 +290 -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 +180 -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 +80 -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 +887 -633
- 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-Rwiqttz-.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-Dl-B9pXM.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,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI Responses API → Claude Messages request conversion.
|
|
4
|
+
*
|
|
5
|
+
* Converts a Responses API request body into a Claude Messages request body.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.responsesToClaude = responsesToClaude;
|
|
9
|
+
const effort_js_1 = require("../../thinking/effort.js");
|
|
10
|
+
const tool_schema_js_1 = require("../../utils/tool-schema.js");
|
|
11
|
+
/**
|
|
12
|
+
* Convert an OpenAI Responses API request body to a Claude Messages request body.
|
|
13
|
+
*/
|
|
14
|
+
function responsesToClaude(body) {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
const messages = [];
|
|
17
|
+
let systemPrompt;
|
|
18
|
+
// --- Instructions -> system ---
|
|
19
|
+
if (body.instructions) {
|
|
20
|
+
systemPrompt = typeof body.instructions === 'string'
|
|
21
|
+
? body.instructions
|
|
22
|
+
: undefined;
|
|
23
|
+
}
|
|
24
|
+
// --- Input -> messages ---
|
|
25
|
+
// Track pending thinking blocks from reasoning items to merge into next assistant message
|
|
26
|
+
let pendingThinking = [];
|
|
27
|
+
if (body.input) {
|
|
28
|
+
for (const item of body.input) {
|
|
29
|
+
if (item.type === 'message') {
|
|
30
|
+
if (item.role === 'user') {
|
|
31
|
+
const content = extractMessageContent(item, 'input_text');
|
|
32
|
+
if (content.length > 0) {
|
|
33
|
+
messages.push({ role: 'user', content });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else if (item.role === 'assistant' || item.role === 'developer') {
|
|
37
|
+
const content = extractMessageContent(item, 'output_text');
|
|
38
|
+
// Prepend pending thinking blocks from preceding reasoning items
|
|
39
|
+
if (pendingThinking.length > 0) {
|
|
40
|
+
content.unshift(...pendingThinking);
|
|
41
|
+
pendingThinking = [];
|
|
42
|
+
}
|
|
43
|
+
if (content.length > 0) {
|
|
44
|
+
messages.push({ role: item.role === 'developer' ? 'user' : 'assistant', content });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (item.type === 'function_call') {
|
|
49
|
+
let parsedInput;
|
|
50
|
+
try {
|
|
51
|
+
parsedInput = typeof item.arguments === 'string' ? JSON.parse(item.arguments) : item.arguments;
|
|
52
|
+
}
|
|
53
|
+
catch (_c) {
|
|
54
|
+
parsedInput = item.arguments;
|
|
55
|
+
}
|
|
56
|
+
const content = [];
|
|
57
|
+
// Prepend pending thinking blocks from preceding reasoning items
|
|
58
|
+
if (pendingThinking.length > 0) {
|
|
59
|
+
content.push(...pendingThinking);
|
|
60
|
+
pendingThinking = [];
|
|
61
|
+
}
|
|
62
|
+
content.push({
|
|
63
|
+
type: 'tool_use',
|
|
64
|
+
id: item.call_id,
|
|
65
|
+
name: item.name,
|
|
66
|
+
input: parsedInput,
|
|
67
|
+
});
|
|
68
|
+
messages.push({ role: 'assistant', content });
|
|
69
|
+
}
|
|
70
|
+
else if (item.type === 'function_call_output') {
|
|
71
|
+
messages.push({
|
|
72
|
+
role: 'user',
|
|
73
|
+
content: [{
|
|
74
|
+
type: 'tool_result',
|
|
75
|
+
tool_use_id: item.call_id,
|
|
76
|
+
content: item.output,
|
|
77
|
+
}],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else if (item.type === 'reasoning') {
|
|
81
|
+
// Convert reasoning summary to Claude thinking block and attach to next assistant message
|
|
82
|
+
if (item.summary && Array.isArray(item.summary)) {
|
|
83
|
+
const thinkingText = item.summary
|
|
84
|
+
.filter((s) => s.type === 'summary_text')
|
|
85
|
+
.map((s) => s.text || '')
|
|
86
|
+
.join('');
|
|
87
|
+
if (thinkingText) {
|
|
88
|
+
pendingThinking.push({ type: 'thinking', thinking: thinkingText });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// If there are orphaned thinking blocks (reasoning at end with no following assistant message),
|
|
96
|
+
// create a standalone assistant message to hold them
|
|
97
|
+
if (pendingThinking.length > 0) {
|
|
98
|
+
messages.push({ role: 'assistant', content: pendingThinking });
|
|
99
|
+
}
|
|
100
|
+
// --- Build result ---
|
|
101
|
+
const result = {
|
|
102
|
+
model: body.model,
|
|
103
|
+
messages,
|
|
104
|
+
max_tokens: body.max_output_tokens || 8192,
|
|
105
|
+
stream: (_a = body.stream) !== null && _a !== void 0 ? _a : false,
|
|
106
|
+
};
|
|
107
|
+
if (systemPrompt)
|
|
108
|
+
result.system = systemPrompt;
|
|
109
|
+
if (body.temperature !== undefined)
|
|
110
|
+
result.temperature = body.temperature;
|
|
111
|
+
if (body.top_p !== undefined)
|
|
112
|
+
result.top_p = body.top_p;
|
|
113
|
+
// --- Reasoning -> thinking ---
|
|
114
|
+
if ((_b = body.reasoning) === null || _b === void 0 ? void 0 : _b.effort) {
|
|
115
|
+
result.thinking = (0, effort_js_1.reasoningEffortToClaudeThinking)(body.reasoning.effort);
|
|
116
|
+
}
|
|
117
|
+
// --- Tools ---
|
|
118
|
+
if (body.tools && body.tools.length > 0) {
|
|
119
|
+
result.tools = (0, tool_schema_js_1.responsesToClaudeTools)(body.tools);
|
|
120
|
+
}
|
|
121
|
+
// --- Tool choice reverse mapping ---
|
|
122
|
+
if (body.tool_choice !== undefined) {
|
|
123
|
+
result.tool_choice = mapResponsesToolChoice(body.tool_choice);
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// Helpers
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
/**
|
|
131
|
+
* Extract content blocks from a Responses API message item into Claude content blocks.
|
|
132
|
+
*/
|
|
133
|
+
function extractMessageContent(item, textType) {
|
|
134
|
+
const content = [];
|
|
135
|
+
if (item.content) {
|
|
136
|
+
if (typeof item.content === 'string') {
|
|
137
|
+
content.push({ type: 'text', text: item.content });
|
|
138
|
+
}
|
|
139
|
+
else if (Array.isArray(item.content)) {
|
|
140
|
+
for (const part of item.content) {
|
|
141
|
+
if (part.type === textType || part.type === 'text') {
|
|
142
|
+
content.push({ type: 'text', text: part.text || '' });
|
|
143
|
+
}
|
|
144
|
+
else if (part.type === 'input_image' && part.image_url) {
|
|
145
|
+
// Parse data URL back into image block
|
|
146
|
+
const dataUrlMatch = part.image_url.match(/^data:([^;]+);base64,(.+)$/);
|
|
147
|
+
if (dataUrlMatch) {
|
|
148
|
+
content.push({
|
|
149
|
+
type: 'image',
|
|
150
|
+
source: {
|
|
151
|
+
type: 'base64',
|
|
152
|
+
media_type: dataUrlMatch[1],
|
|
153
|
+
data: dataUrlMatch[2],
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (item.text) {
|
|
162
|
+
content.push({ type: 'text', text: item.text });
|
|
163
|
+
}
|
|
164
|
+
return content;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Map Responses API tool_choice to Claude tool_choice.
|
|
168
|
+
*/
|
|
169
|
+
function mapResponsesToolChoice(toolChoice) {
|
|
170
|
+
if (toolChoice === 'required')
|
|
171
|
+
return { type: 'any' };
|
|
172
|
+
if (toolChoice === 'auto')
|
|
173
|
+
return { type: 'auto' };
|
|
174
|
+
if (toolChoice === 'none')
|
|
175
|
+
return { type: 'none' };
|
|
176
|
+
if (typeof toolChoice === 'object' && toolChoice.type === 'function') {
|
|
177
|
+
return { type: 'tool', name: toolChoice.name };
|
|
178
|
+
}
|
|
179
|
+
return { type: 'auto' };
|
|
180
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude Messages → OpenAI Responses API response conversion.
|
|
4
|
+
*
|
|
5
|
+
* Converts a Claude Messages response body into an OpenAI Responses API response body.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.claudeToResponsesResponse = claudeToResponsesResponse;
|
|
9
|
+
const id_js_1 = require("../../utils/id.js");
|
|
10
|
+
const stop_reasons_js_1 = require("../../utils/stop-reasons.js");
|
|
11
|
+
const mapper_js_1 = require("../../thinking/mapper.js");
|
|
12
|
+
/**
|
|
13
|
+
* Convert a Claude Messages response to an OpenAI Responses API response.
|
|
14
|
+
*/
|
|
15
|
+
function claudeToResponsesResponse(response) {
|
|
16
|
+
const output = [];
|
|
17
|
+
for (const block of (response.content || [])) {
|
|
18
|
+
if (block.type === 'thinking') {
|
|
19
|
+
output.push({
|
|
20
|
+
type: 'reasoning',
|
|
21
|
+
id: `rs_${(0, id_js_1.generateCallId)().slice(5)}`,
|
|
22
|
+
summary: (0, mapper_js_1.thinkingToReasoningSummary)(block.thinking || ''),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else if (block.type === 'text') {
|
|
26
|
+
output.push({
|
|
27
|
+
type: 'message',
|
|
28
|
+
status: 'completed',
|
|
29
|
+
role: 'assistant',
|
|
30
|
+
content: [{
|
|
31
|
+
type: 'output_text',
|
|
32
|
+
text: block.text,
|
|
33
|
+
annotations: [],
|
|
34
|
+
}],
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
else if (block.type === 'tool_use') {
|
|
38
|
+
output.push({
|
|
39
|
+
type: 'function_call',
|
|
40
|
+
status: 'completed',
|
|
41
|
+
call_id: block.id,
|
|
42
|
+
name: block.name,
|
|
43
|
+
arguments: typeof block.input === 'string' ? block.input : JSON.stringify(block.input),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const { status, incomplete_details } = (0, stop_reasons_js_1.claudeToResponsesStatus)(response.stop_reason);
|
|
48
|
+
const usage = claudeToResponsesUsage(response.usage);
|
|
49
|
+
const responseId = response.id || (0, id_js_1.generateResponseId)();
|
|
50
|
+
return Object.assign(Object.assign({ id: responseId, object: 'response', status,
|
|
51
|
+
output, model: response.model || '', created_at: Math.floor(Date.now() / 1000), usage }, (incomplete_details ? { incomplete_details } : {})), { metadata: {} });
|
|
52
|
+
}
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Helpers
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
/**
|
|
57
|
+
* Map Claude usage to Responses API usage.
|
|
58
|
+
*/
|
|
59
|
+
function claudeToResponsesUsage(usage) {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
if (!usage)
|
|
62
|
+
return { input_tokens: 0, output_tokens: 0, total_tokens: 0 };
|
|
63
|
+
const input = (_a = usage.input_tokens) !== null && _a !== void 0 ? _a : 0;
|
|
64
|
+
const output = (_b = usage.output_tokens) !== null && _b !== void 0 ? _b : 0;
|
|
65
|
+
return {
|
|
66
|
+
input_tokens: input,
|
|
67
|
+
output_tokens: output,
|
|
68
|
+
total_tokens: input + output,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude Messages SSE → OpenAI Responses API SSE streaming conversion.
|
|
4
|
+
*
|
|
5
|
+
* Stateful converter that translates Claude Messages SSE events into
|
|
6
|
+
* OpenAI Responses API SSE events.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.ClaudeToResponsesConverter = void 0;
|
|
10
|
+
const id_js_1 = require("../../utils/id.js");
|
|
11
|
+
const stop_reasons_js_1 = require("../../utils/stop-reasons.js");
|
|
12
|
+
const streaming_helpers_js_1 = require("../../utils/streaming-helpers.js");
|
|
13
|
+
/**
|
|
14
|
+
* ClaudeToResponsesConverter: Claude Messages SSE → Responses API SSE
|
|
15
|
+
*/
|
|
16
|
+
class ClaudeToResponsesConverter {
|
|
17
|
+
constructor() {
|
|
18
|
+
Object.defineProperty(this, "finalized", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: false
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "textStarted", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: false
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "thinkingStarted", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: false
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(this, "responseId", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: (0, id_js_1.generateResponseId)()
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, "model", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: ''
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(this, "usage", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
writable: true,
|
|
52
|
+
value: { input_tokens: 0, output_tokens: 0 }
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(this, "output", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
configurable: true,
|
|
57
|
+
writable: true,
|
|
58
|
+
value: []
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(this, "currentToolCallId", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
configurable: true,
|
|
63
|
+
writable: true,
|
|
64
|
+
value: null
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(this, "currentToolName", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
configurable: true,
|
|
69
|
+
writable: true,
|
|
70
|
+
value: null
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(this, "currentToolArguments", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
configurable: true,
|
|
75
|
+
writable: true,
|
|
76
|
+
value: ''
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(this, "reasoningText", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
configurable: true,
|
|
81
|
+
writable: true,
|
|
82
|
+
value: ''
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(this, "pendingStopReason", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
configurable: true,
|
|
87
|
+
writable: true,
|
|
88
|
+
value: null
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
convertEvent(event) {
|
|
92
|
+
var _a, _b, _c, _d, _e;
|
|
93
|
+
if (!event.data)
|
|
94
|
+
return [];
|
|
95
|
+
const events = [];
|
|
96
|
+
try {
|
|
97
|
+
const data = (0, streaming_helpers_js_1.parseEventData)(event.data);
|
|
98
|
+
switch (data.type) {
|
|
99
|
+
case 'message_start': {
|
|
100
|
+
this.model = ((_a = data.message) === null || _a === void 0 ? void 0 : _a.model) || '';
|
|
101
|
+
this.responseId = ((_b = data.message) === null || _b === void 0 ? void 0 : _b.id) || this.responseId;
|
|
102
|
+
events.push(this.makeSSE('response.created', {
|
|
103
|
+
id: this.responseId,
|
|
104
|
+
object: 'response',
|
|
105
|
+
status: 'in_progress',
|
|
106
|
+
model: this.model,
|
|
107
|
+
output: [],
|
|
108
|
+
}));
|
|
109
|
+
events.push(this.makeSSE('response.in_progress', {
|
|
110
|
+
id: this.responseId,
|
|
111
|
+
object: 'response',
|
|
112
|
+
status: 'in_progress',
|
|
113
|
+
model: this.model,
|
|
114
|
+
output: [],
|
|
115
|
+
}));
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case 'content_block_start': {
|
|
119
|
+
const block = data.content_block;
|
|
120
|
+
if ((block === null || block === void 0 ? void 0 : block.type) === 'thinking') {
|
|
121
|
+
// Close text if open
|
|
122
|
+
this.closeText(events);
|
|
123
|
+
const rsIdx = this.output.length;
|
|
124
|
+
events.push(this.makeSSE('response.output_item.added', {
|
|
125
|
+
output_index: rsIdx,
|
|
126
|
+
item: { type: 'reasoning', id: `rs_${(0, id_js_1.generateCallId)().slice(5)}` },
|
|
127
|
+
}));
|
|
128
|
+
events.push(this.makeSSE('response.reasoning_summary_part.added', {
|
|
129
|
+
output_index: rsIdx,
|
|
130
|
+
summary_index: 0,
|
|
131
|
+
part: { type: 'summary_text' },
|
|
132
|
+
}));
|
|
133
|
+
this.thinkingStarted = true;
|
|
134
|
+
this.reasoningText = '';
|
|
135
|
+
}
|
|
136
|
+
else if ((block === null || block === void 0 ? void 0 : block.type) === 'text') {
|
|
137
|
+
// Close thinking if open
|
|
138
|
+
this.closeThinking(events);
|
|
139
|
+
const msgIdx = this.output.length;
|
|
140
|
+
events.push(this.makeSSE('response.output_item.added', {
|
|
141
|
+
output_index: msgIdx,
|
|
142
|
+
item: { type: 'message', status: 'in_progress', role: 'assistant', content: [] },
|
|
143
|
+
}));
|
|
144
|
+
events.push(this.makeSSE('response.content_part.added', {
|
|
145
|
+
output_index: msgIdx,
|
|
146
|
+
content_index: 0,
|
|
147
|
+
part: { type: 'output_text', text: '', annotations: [] },
|
|
148
|
+
}));
|
|
149
|
+
this.textStarted = true;
|
|
150
|
+
}
|
|
151
|
+
else if ((block === null || block === void 0 ? void 0 : block.type) === 'tool_use') {
|
|
152
|
+
// Close any open blocks
|
|
153
|
+
this.closeText(events);
|
|
154
|
+
this.closeThinking(events);
|
|
155
|
+
this.currentToolCallId = block.id;
|
|
156
|
+
this.currentToolName = block.name;
|
|
157
|
+
this.currentToolArguments = '';
|
|
158
|
+
const toolIdx = this.output.length;
|
|
159
|
+
events.push(this.makeSSE('response.output_item.added', {
|
|
160
|
+
output_index: toolIdx,
|
|
161
|
+
item: {
|
|
162
|
+
type: 'function_call',
|
|
163
|
+
status: 'in_progress',
|
|
164
|
+
call_id: block.id,
|
|
165
|
+
name: block.name,
|
|
166
|
+
arguments: '',
|
|
167
|
+
},
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
case 'content_block_delta': {
|
|
173
|
+
const delta = data.delta;
|
|
174
|
+
if ((delta === null || delta === void 0 ? void 0 : delta.type) === 'thinking_delta') {
|
|
175
|
+
const text = delta.thinking || '';
|
|
176
|
+
if (text) {
|
|
177
|
+
this.reasoningText += text;
|
|
178
|
+
events.push(this.makeSSE('response.reasoning_summary_text.delta', {
|
|
179
|
+
output_index: this.output.length,
|
|
180
|
+
delta: text,
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else if ((delta === null || delta === void 0 ? void 0 : delta.type) === 'text_delta') {
|
|
185
|
+
const text = delta.text || '';
|
|
186
|
+
if (text) {
|
|
187
|
+
events.push(this.makeSSE('response.output_text.delta', {
|
|
188
|
+
output_index: this.textMessageOutputIndex(),
|
|
189
|
+
content_index: 0,
|
|
190
|
+
delta: text,
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else if ((delta === null || delta === void 0 ? void 0 : delta.type) === 'input_json_delta') {
|
|
195
|
+
const partialJson = delta.partial_json || '';
|
|
196
|
+
if (partialJson) {
|
|
197
|
+
this.currentToolArguments += partialJson;
|
|
198
|
+
events.push(this.makeSSE('response.function_call_arguments.delta', {
|
|
199
|
+
output_index: this.output.length,
|
|
200
|
+
call_id: this.currentToolCallId,
|
|
201
|
+
delta: partialJson,
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
case 'content_block_stop': {
|
|
208
|
+
// If this was a tool_use block, emit function_call_arguments.done and output_item.done
|
|
209
|
+
if (this.currentToolCallId !== null) {
|
|
210
|
+
const tcIdx = this.output.length;
|
|
211
|
+
events.push(this.makeSSE('response.function_call_arguments.done', {
|
|
212
|
+
output_index: tcIdx,
|
|
213
|
+
call_id: this.currentToolCallId,
|
|
214
|
+
}));
|
|
215
|
+
events.push(this.makeSSE('response.output_item.done', {
|
|
216
|
+
output_index: tcIdx,
|
|
217
|
+
item: {
|
|
218
|
+
type: 'function_call',
|
|
219
|
+
status: 'completed',
|
|
220
|
+
call_id: this.currentToolCallId,
|
|
221
|
+
name: this.currentToolName || '',
|
|
222
|
+
arguments: this.currentToolArguments,
|
|
223
|
+
},
|
|
224
|
+
}));
|
|
225
|
+
this.output.push({
|
|
226
|
+
type: 'function_call',
|
|
227
|
+
status: 'completed',
|
|
228
|
+
call_id: this.currentToolCallId,
|
|
229
|
+
name: this.currentToolName,
|
|
230
|
+
arguments: this.currentToolArguments,
|
|
231
|
+
});
|
|
232
|
+
this.currentToolCallId = null;
|
|
233
|
+
this.currentToolName = null;
|
|
234
|
+
this.currentToolArguments = '';
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
case 'message_delta': {
|
|
239
|
+
this.pendingStopReason = ((_c = data.delta) === null || _c === void 0 ? void 0 : _c.stop_reason) || null;
|
|
240
|
+
if (data.usage) {
|
|
241
|
+
this.usage = {
|
|
242
|
+
input_tokens: this.usage.input_tokens,
|
|
243
|
+
output_tokens: (_e = (_d = data.usage.output_tokens) !== null && _d !== void 0 ? _d : data.usage.tokens) !== null && _e !== void 0 ? _e : 0,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
case 'message_stop': {
|
|
249
|
+
this.finalize(events);
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
default:
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (_f) {
|
|
257
|
+
// Ignore parse errors
|
|
258
|
+
}
|
|
259
|
+
return events;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Get the output index of the text message.
|
|
263
|
+
* The text message is at the last output index that hasn't been pushed yet.
|
|
264
|
+
*/
|
|
265
|
+
textMessageOutputIndex() {
|
|
266
|
+
// During streaming, text output hasn't been pushed yet.
|
|
267
|
+
// Its index is determined by what's already been pushed + whether it's after reasoning.
|
|
268
|
+
return this.thinkingStarted ? this.output.length : this.output.length;
|
|
269
|
+
}
|
|
270
|
+
closeText(events) {
|
|
271
|
+
if (this.textStarted) {
|
|
272
|
+
const msgIdx = this.output.length;
|
|
273
|
+
events.push(this.makeSSE('response.output_text.done', {
|
|
274
|
+
output_index: msgIdx,
|
|
275
|
+
content_index: 0,
|
|
276
|
+
text: '',
|
|
277
|
+
}));
|
|
278
|
+
events.push(this.makeSSE('response.content_part.done', {
|
|
279
|
+
output_index: msgIdx,
|
|
280
|
+
content_index: 0,
|
|
281
|
+
part: { type: 'output_text', text: '', annotations: [] },
|
|
282
|
+
}));
|
|
283
|
+
this.output.push({ type: 'message', status: 'completed', role: 'assistant' });
|
|
284
|
+
events.push(this.makeSSE('response.output_item.done', {
|
|
285
|
+
output_index: this.output.length - 1,
|
|
286
|
+
item: { type: 'message', status: 'completed', role: 'assistant' },
|
|
287
|
+
}));
|
|
288
|
+
this.textStarted = false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
closeThinking(events) {
|
|
292
|
+
if (this.thinkingStarted) {
|
|
293
|
+
const rsIdx = this.output.length;
|
|
294
|
+
events.push(this.makeSSE('response.reasoning.done', {
|
|
295
|
+
output_index: rsIdx,
|
|
296
|
+
summary: [{ type: 'summary_text', text: this.reasoningText }],
|
|
297
|
+
}));
|
|
298
|
+
events.push(this.makeSSE('response.reasoning_summary_part.done', {
|
|
299
|
+
output_index: rsIdx,
|
|
300
|
+
}));
|
|
301
|
+
events.push(this.makeSSE('response.output_item.done', {
|
|
302
|
+
output_index: rsIdx,
|
|
303
|
+
item: { type: 'reasoning' },
|
|
304
|
+
}));
|
|
305
|
+
this.output.push({ type: 'reasoning' });
|
|
306
|
+
this.thinkingStarted = false;
|
|
307
|
+
this.reasoningText = '';
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
finalize(events) {
|
|
311
|
+
if (this.finalized)
|
|
312
|
+
return;
|
|
313
|
+
this.finalized = true;
|
|
314
|
+
// Close any open blocks
|
|
315
|
+
this.closeText(events);
|
|
316
|
+
this.closeThinking(events);
|
|
317
|
+
const { status, incomplete_details } = (0, stop_reasons_js_1.claudeToResponsesStatus)(this.pendingStopReason);
|
|
318
|
+
const responseObj = {
|
|
319
|
+
id: this.responseId,
|
|
320
|
+
object: 'response',
|
|
321
|
+
status,
|
|
322
|
+
output: this.output,
|
|
323
|
+
model: this.model,
|
|
324
|
+
created_at: Math.floor(Date.now() / 1000),
|
|
325
|
+
usage: {
|
|
326
|
+
input_tokens: this.usage.input_tokens,
|
|
327
|
+
output_tokens: this.usage.output_tokens,
|
|
328
|
+
total_tokens: this.usage.input_tokens + this.usage.output_tokens,
|
|
329
|
+
},
|
|
330
|
+
metadata: {},
|
|
331
|
+
};
|
|
332
|
+
if (incomplete_details) {
|
|
333
|
+
responseObj.incomplete_details = incomplete_details;
|
|
334
|
+
}
|
|
335
|
+
events.push(this.makeSSE('response.completed', { response: responseObj }));
|
|
336
|
+
events.push({ data: '[DONE]', event: '' });
|
|
337
|
+
}
|
|
338
|
+
makeSSE(eventName, data) {
|
|
339
|
+
return {
|
|
340
|
+
event: eventName,
|
|
341
|
+
data,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
exports.ClaudeToResponsesConverter = ClaudeToResponsesConverter;
|