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.
Files changed (77) hide show
  1. package/README.md +7 -6
  2. package/UPGRADE.md +5 -6
  3. package/dist/server/coding-plan.js +94 -0
  4. package/dist/server/config-managed-fields.js +1 -0
  5. package/dist/server/conversions/compact.js +613 -0
  6. package/dist/server/conversions/detector.js +70 -0
  7. package/dist/server/conversions/index.js +285 -0
  8. package/dist/server/conversions/pairs/claude-completions/request.js +167 -0
  9. package/dist/server/conversions/pairs/claude-completions/response.js +56 -0
  10. package/dist/server/conversions/pairs/claude-completions/streaming.js +259 -0
  11. package/dist/server/conversions/pairs/claude-gemini/request.js +130 -0
  12. package/dist/server/conversions/pairs/claude-gemini/response.js +65 -0
  13. package/dist/server/conversions/pairs/claude-gemini/streaming.js +199 -0
  14. package/dist/server/conversions/pairs/claude-responses/request.js +190 -0
  15. package/dist/server/conversions/pairs/claude-responses/response.js +89 -0
  16. package/dist/server/conversions/pairs/claude-responses/streaming.js +266 -0
  17. package/dist/server/conversions/pairs/completions-claude/request.js +111 -0
  18. package/dist/server/conversions/pairs/completions-claude/response.js +67 -0
  19. package/dist/server/conversions/pairs/completions-claude/streaming.js +165 -0
  20. package/dist/server/conversions/pairs/completions-gemini/request.js +169 -0
  21. package/dist/server/conversions/pairs/completions-gemini/response.js +70 -0
  22. package/dist/server/conversions/pairs/completions-gemini/streaming.js +132 -0
  23. package/dist/server/conversions/pairs/completions-responses/request.js +149 -0
  24. package/dist/server/conversions/pairs/completions-responses/response.js +74 -0
  25. package/dist/server/conversions/pairs/completions-responses/streaming.js +189 -0
  26. package/dist/server/conversions/pairs/gemini-claude/request.js +118 -0
  27. package/dist/server/conversions/pairs/gemini-claude/response.js +45 -0
  28. package/dist/server/conversions/pairs/gemini-claude/streaming.js +146 -0
  29. package/dist/server/conversions/pairs/gemini-completions/request.js +151 -0
  30. package/dist/server/conversions/pairs/gemini-completions/response.js +54 -0
  31. package/dist/server/conversions/pairs/gemini-completions/streaming.js +108 -0
  32. package/dist/server/conversions/pairs/gemini-responses/request.js +18 -0
  33. package/dist/server/conversions/pairs/gemini-responses/response.js +18 -0
  34. package/dist/server/conversions/pairs/gemini-responses/streaming.js +43 -0
  35. package/dist/server/conversions/pairs/responses-claude/request.js +155 -0
  36. package/dist/server/conversions/pairs/responses-claude/response.js +70 -0
  37. package/dist/server/conversions/pairs/responses-claude/streaming.js +345 -0
  38. package/dist/server/conversions/pairs/responses-completions/request.js +207 -0
  39. package/dist/server/conversions/pairs/responses-completions/response.js +96 -0
  40. package/dist/server/conversions/pairs/responses-completions/streaming.js +344 -0
  41. package/dist/server/conversions/pairs/responses-gemini/request.js +18 -0
  42. package/dist/server/conversions/pairs/responses-gemini/response.js +18 -0
  43. package/dist/server/conversions/pairs/responses-gemini/streaming.js +43 -0
  44. package/dist/server/conversions/pairs/responses-responses/request.js +115 -0
  45. package/dist/server/conversions/pipeline.js +296 -0
  46. package/dist/server/conversions/stream-converter-adapter.js +49 -0
  47. package/dist/server/conversions/thinking/effort.js +61 -0
  48. package/dist/server/conversions/thinking/mapper.js +59 -0
  49. package/dist/server/conversions/thinking/providers.js +76 -0
  50. package/dist/server/conversions/types.js +5 -0
  51. package/dist/server/conversions/url-normalizer.js +58 -0
  52. package/dist/server/conversions/utils/format-mappers.js +57 -0
  53. package/dist/server/conversions/utils/id.js +33 -0
  54. package/dist/server/conversions/utils/stop-reasons.js +95 -0
  55. package/dist/server/conversions/utils/streaming-helpers.js +59 -0
  56. package/dist/server/conversions/utils/tool-schema.js +169 -0
  57. package/dist/server/conversions/utils/usage.js +82 -0
  58. package/dist/server/fs-database.js +465 -135
  59. package/dist/server/main.js +93 -33
  60. package/dist/server/original-config-reader.js +1 -1
  61. package/dist/server/proxy-server.js +1102 -804
  62. package/dist/server/transformers/chunk-collector.js +5 -1
  63. package/dist/server/transformers/streaming.js +6 -3235
  64. package/dist/server/type-migration.js +2 -3
  65. package/dist/server/utils.js +5 -0
  66. package/dist/ui/assets/{index-C7G0whng.css → index-BHR12ImE.css} +1 -1
  67. package/dist/ui/assets/index-DjdBW1yu.js +517 -0
  68. package/dist/ui/index.html +2 -2
  69. package/package.json +1 -1
  70. package/dist/server/transformers/transformers.js +0 -1767
  71. package/dist/ui/assets/index-Nl6yJxrc.js +0 -514
  72. package/schema/claude.schema.md +0 -946
  73. package/schema/deepseek-chat.schema.md +0 -799
  74. package/schema/gemini.schema.md +0 -1408
  75. package/schema/openai-chat-completions.schema.md +0 -1088
  76. package/schema/openai-responses.schema.md +0 -226196
  77. package/schema/stream.md +0 -2592
@@ -0,0 +1,155 @@
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
+ if (body.input) {
26
+ for (const item of body.input) {
27
+ if (item.type === 'message') {
28
+ if (item.role === 'user') {
29
+ const content = extractMessageContent(item, 'input_text');
30
+ if (content.length > 0) {
31
+ messages.push({ role: 'user', content });
32
+ }
33
+ }
34
+ else if (item.role === 'assistant' || item.role === 'developer') {
35
+ const content = extractMessageContent(item, 'output_text');
36
+ if (content.length > 0) {
37
+ messages.push({ role: item.role === 'developer' ? 'user' : 'assistant', content });
38
+ }
39
+ }
40
+ }
41
+ else if (item.type === 'function_call') {
42
+ let parsedInput;
43
+ try {
44
+ parsedInput = typeof item.arguments === 'string' ? JSON.parse(item.arguments) : item.arguments;
45
+ }
46
+ catch (_c) {
47
+ parsedInput = item.arguments;
48
+ }
49
+ messages.push({
50
+ role: 'assistant',
51
+ content: [{
52
+ type: 'tool_use',
53
+ id: item.call_id,
54
+ name: item.name,
55
+ input: parsedInput,
56
+ }],
57
+ });
58
+ }
59
+ else if (item.type === 'function_call_output') {
60
+ messages.push({
61
+ role: 'user',
62
+ content: [{
63
+ type: 'tool_result',
64
+ tool_use_id: item.call_id,
65
+ content: item.output,
66
+ }],
67
+ });
68
+ }
69
+ else if (item.type === 'reasoning') {
70
+ // Skip reasoning items in messages (effort is extracted for thinking config below)
71
+ continue;
72
+ }
73
+ }
74
+ }
75
+ // --- Build result ---
76
+ const result = {
77
+ model: body.model,
78
+ messages,
79
+ max_tokens: body.max_output_tokens || 8192,
80
+ stream: (_a = body.stream) !== null && _a !== void 0 ? _a : false,
81
+ };
82
+ if (systemPrompt)
83
+ result.system = systemPrompt;
84
+ if (body.temperature !== undefined)
85
+ result.temperature = body.temperature;
86
+ if (body.top_p !== undefined)
87
+ result.top_p = body.top_p;
88
+ // --- Reasoning -> thinking ---
89
+ if ((_b = body.reasoning) === null || _b === void 0 ? void 0 : _b.effort) {
90
+ result.thinking = (0, effort_js_1.reasoningEffortToClaudeThinking)(body.reasoning.effort);
91
+ }
92
+ // --- Tools ---
93
+ if (body.tools && body.tools.length > 0) {
94
+ result.tools = (0, tool_schema_js_1.responsesToClaudeTools)(body.tools);
95
+ }
96
+ // --- Tool choice reverse mapping ---
97
+ if (body.tool_choice !== undefined) {
98
+ result.tool_choice = mapResponsesToolChoice(body.tool_choice);
99
+ }
100
+ return result;
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // Helpers
104
+ // ---------------------------------------------------------------------------
105
+ /**
106
+ * Extract content blocks from a Responses API message item into Claude content blocks.
107
+ */
108
+ function extractMessageContent(item, textType) {
109
+ const content = [];
110
+ if (item.content) {
111
+ if (typeof item.content === 'string') {
112
+ content.push({ type: 'text', text: item.content });
113
+ }
114
+ else if (Array.isArray(item.content)) {
115
+ for (const part of item.content) {
116
+ if (part.type === textType || part.type === 'text') {
117
+ content.push({ type: 'text', text: part.text || '' });
118
+ }
119
+ else if (part.type === 'input_image' && part.image_url) {
120
+ // Parse data URL back into image block
121
+ const dataUrlMatch = part.image_url.match(/^data:([^;]+);base64,(.+)$/);
122
+ if (dataUrlMatch) {
123
+ content.push({
124
+ type: 'image',
125
+ source: {
126
+ type: 'base64',
127
+ media_type: dataUrlMatch[1],
128
+ data: dataUrlMatch[2],
129
+ },
130
+ });
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ if (item.text) {
137
+ content.push({ type: 'text', text: item.text });
138
+ }
139
+ return content;
140
+ }
141
+ /**
142
+ * Map Responses API tool_choice to Claude tool_choice.
143
+ */
144
+ function mapResponsesToolChoice(toolChoice) {
145
+ if (toolChoice === 'required')
146
+ return { type: 'any' };
147
+ if (toolChoice === 'auto')
148
+ return { type: 'auto' };
149
+ if (toolChoice === 'none')
150
+ return { type: 'none' };
151
+ if (typeof toolChoice === 'object' && toolChoice.type === 'function') {
152
+ return { type: 'tool', name: toolChoice.name };
153
+ }
154
+ return { type: 'auto' };
155
+ }
@@ -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;