@hileeon/mcc 0.1.8 → 0.1.9
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 +226 -127
- package/dist/accounts/store.d.ts +1 -0
- package/dist/accounts/store.d.ts.map +1 -1
- package/dist/accounts/store.js.map +1 -1
- package/dist/commands/launch.d.ts +9 -0
- package/dist/commands/launch.d.ts.map +1 -0
- package/dist/commands/launch.js +158 -0
- package/dist/commands/launch.js.map +1 -0
- package/dist/commands/mcp.d.ts +9 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +112 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/profile.d.ts +8 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +125 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/core/model-router.d.ts.map +1 -1
- package/dist/core/model-router.js +5 -2
- package/dist/core/model-router.js.map +1 -1
- package/dist/{dashboard-server.d.ts → dashboard/server.d.ts} +1 -1
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/{dashboard-server.js → dashboard/server.js} +169 -51
- package/dist/dashboard/server.js.map +1 -0
- package/dist/mcc.d.ts +4 -2
- package/dist/mcc.d.ts.map +1 -1
- package/dist/mcc.js +121 -408
- package/dist/mcc.js.map +1 -1
- package/dist/mcp/mcp-config.d.ts +17 -1
- package/dist/mcp/mcp-config.d.ts.map +1 -1
- package/dist/mcp/mcp-config.js +50 -17
- package/dist/mcp/mcp-config.js.map +1 -1
- package/dist/proxy/proxy-daemon.d.ts.map +1 -1
- package/dist/proxy/proxy-daemon.js +17 -2
- package/dist/proxy/proxy-daemon.js.map +1 -1
- package/dist/proxy/proxy-entry.js +5 -3
- package/dist/proxy/proxy-entry.js.map +1 -1
- package/dist/proxy/proxy-server.d.ts.map +1 -1
- package/dist/proxy/proxy-server.js +32 -6
- package/dist/proxy/proxy-server.js.map +1 -1
- package/dist/shared/config.d.ts +15 -0
- package/dist/shared/config.d.ts.map +1 -0
- package/dist/shared/config.js +79 -0
- package/dist/shared/config.js.map +1 -0
- package/dist/shared/logger.d.ts +23 -18
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/logger.js +17 -178
- package/dist/shared/logger.js.map +1 -1
- package/dist/shared/provider-preset-catalog.d.ts +6 -2
- package/dist/shared/provider-preset-catalog.d.ts.map +1 -1
- package/dist/shared/provider-preset-catalog.js +47 -26
- package/dist/shared/provider-preset-catalog.js.map +1 -1
- package/dist/ui/assets/index-ClqmrjNk.js +40 -0
- package/dist/ui/assets/index-CwMwQ-Z4.css +1 -0
- package/dist/ui/index.html +21 -13
- package/dist/update.d.ts +31 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +196 -0
- package/dist/update.js.map +1 -0
- package/lib/mcp/mcc-image-analysis-server.cjs +454 -454
- package/lib/mcp/mcc-websearch-server.cjs +339 -339
- package/lib/mcp-hooks/image-analysis-runtime.cjs +510 -510
- package/lib/mcp-hooks/image-analyzer-transformer.cjs +526 -526
- package/lib/mcp-hooks/websearch-transformer.cjs +1597 -1421
- package/lib/proxy/config/config-loader-facade.js +24 -24
- package/lib/proxy/glmt/delta-accumulator.js +362 -362
- package/lib/proxy/glmt/glmt-transformer.js +203 -203
- package/lib/proxy/glmt/index.js +40 -40
- package/lib/proxy/glmt/locale-enforcer.js +68 -68
- package/lib/proxy/glmt/pipeline/content-transformer.js +161 -161
- package/lib/proxy/glmt/pipeline/index.js +19 -19
- package/lib/proxy/glmt/pipeline/request-transformer.js +115 -115
- package/lib/proxy/glmt/pipeline/response-builder.js +204 -204
- package/lib/proxy/glmt/pipeline/stream-parser.js +233 -233
- package/lib/proxy/glmt/pipeline/tool-call-handler.js +77 -77
- package/lib/proxy/glmt/pipeline/types.js +5 -5
- package/lib/proxy/glmt/reasoning-enforcer.js +150 -150
- package/lib/proxy/glmt/sse-parser.js +101 -101
- package/lib/proxy/services/logging.js +13 -13
- package/lib/proxy/transformers/request-transformer.js +471 -471
- package/lib/proxy/transformers/sse-stream-transformer.js +198 -198
- package/lib/shared/logger.cjs +156 -138
- package/package.json +58 -41
- package/dist/dashboard-server.d.ts.map +0 -1
- package/dist/dashboard-server.js.map +0 -1
- package/dist/ui/assets/index-B16lhKZ6.js +0 -40
- package/dist/ui/assets/index-jEfiB6-h.css +0 -1
|
@@ -1,199 +1,199 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ProxySseStreamTransformer = exports.createAnthropicProxyResponse = exports.createAnthropicErrorResponse = void 0;
|
|
4
|
-
const delta_accumulator_1 = require("../glmt/delta-accumulator");
|
|
5
|
-
const glmt_transformer_1 = require("../glmt/glmt-transformer");
|
|
6
|
-
const sse_parser_1 = require("../glmt/sse-parser");
|
|
7
|
-
const JSON_TRANSLATION_ERROR_MESSAGE = 'Failed to translate OpenAI-compatible JSON response';
|
|
8
|
-
const STREAM_TRANSLATION_ERROR_MESSAGE = 'Failed to translate OpenAI-compatible SSE response';
|
|
9
|
-
function createAnthropicErrorPayload(type, message) {
|
|
10
|
-
return {
|
|
11
|
-
type: 'error',
|
|
12
|
-
error: {
|
|
13
|
-
type,
|
|
14
|
-
message,
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
function formatErrorForLog(error) {
|
|
19
|
-
if (error instanceof Error) {
|
|
20
|
-
return error.message;
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
return JSON.stringify(error);
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
return String(error);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function logTranslationError(context, error) {
|
|
30
|
-
console.error(`[proxy-sse-transformer] ${context}: ${formatErrorForLog(error)}`);
|
|
31
|
-
}
|
|
32
|
-
function createAnthropicErrorResponse(status, type, message, headers) {
|
|
33
|
-
const responseHeaders = new Headers(headers);
|
|
34
|
-
responseHeaders.set('Content-Type', 'application/json');
|
|
35
|
-
responseHeaders.delete('Content-Length');
|
|
36
|
-
return new Response(JSON.stringify(createAnthropicErrorPayload(type, message)), {
|
|
37
|
-
status,
|
|
38
|
-
headers: responseHeaders,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
exports.createAnthropicErrorResponse = createAnthropicErrorResponse;
|
|
42
|
-
function formatSseEvent(event, data) {
|
|
43
|
-
return `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
|
|
44
|
-
}
|
|
45
|
-
function hasTranslatableChoices(value) {
|
|
46
|
-
if (typeof value !== 'object' || value === null) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
const { choices } = value;
|
|
50
|
-
if (!Array.isArray(choices) || choices.length === 0) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
const firstChoice = choices[0];
|
|
54
|
-
if (typeof firstChoice !== 'object' || firstChoice === null) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
const message = firstChoice.message;
|
|
58
|
-
return typeof message === 'object' && message !== null;
|
|
59
|
-
}
|
|
60
|
-
function isSyntheticTransformationFallback(value) {
|
|
61
|
-
return (typeof value === 'object' &&
|
|
62
|
-
value !== null &&
|
|
63
|
-
typeof value.id === 'string' &&
|
|
64
|
-
value.id.startsWith('msg_error_'));
|
|
65
|
-
}
|
|
66
|
-
async function createAnthropicErrorProxyResponse(response) {
|
|
67
|
-
const headers = new Headers(response.headers);
|
|
68
|
-
headers.delete('Content-Type');
|
|
69
|
-
headers.delete('Content-Length');
|
|
70
|
-
let type = response.status === 401
|
|
71
|
-
? 'authentication_error'
|
|
72
|
-
: response.status === 429
|
|
73
|
-
? 'rate_limit_error'
|
|
74
|
-
: response.status >= 400 && response.status < 500
|
|
75
|
-
? 'invalid_request_error'
|
|
76
|
-
: 'api_error';
|
|
77
|
-
let message = `Upstream request failed with status ${response.status}`;
|
|
78
|
-
try {
|
|
79
|
-
const contentType = (response.headers.get('content-type') || '').toLowerCase();
|
|
80
|
-
if (contentType.includes('application/json')) {
|
|
81
|
-
const payload = (await response.json());
|
|
82
|
-
if (typeof payload?.error?.type === 'string' && payload.error.type.trim().length > 0) {
|
|
83
|
-
type = payload.error.type;
|
|
84
|
-
}
|
|
85
|
-
if (typeof payload?.error?.message === 'string' && payload.error.message.trim().length > 0) {
|
|
86
|
-
message = payload.error.message;
|
|
87
|
-
}
|
|
88
|
-
else if (typeof payload?.message === 'string' && payload.message.trim().length > 0) {
|
|
89
|
-
message = payload.message;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
const text = (await response.text()).trim();
|
|
94
|
-
if (text.length > 0) {
|
|
95
|
-
message = text;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
logTranslationError('Failed to parse upstream error response', error);
|
|
101
|
-
}
|
|
102
|
-
return createAnthropicErrorResponse(response.status, type, message, headers);
|
|
103
|
-
}
|
|
104
|
-
async function createAnthropicJsonResponse(response) {
|
|
105
|
-
try {
|
|
106
|
-
const openAIResponse = await response.json();
|
|
107
|
-
if (!hasTranslatableChoices(openAIResponse)) {
|
|
108
|
-
return createAnthropicErrorResponse(502, 'api_error', JSON_TRANSLATION_ERROR_MESSAGE);
|
|
109
|
-
}
|
|
110
|
-
const anthropicResponse = new glmt_transformer_1.GlmtTransformer().transformResponse(openAIResponse);
|
|
111
|
-
if (isSyntheticTransformationFallback(anthropicResponse)) {
|
|
112
|
-
logTranslationError('OpenAI-compatible JSON translation produced synthetic fallback response', anthropicResponse);
|
|
113
|
-
return createAnthropicErrorResponse(502, 'api_error', JSON_TRANSLATION_ERROR_MESSAGE);
|
|
114
|
-
}
|
|
115
|
-
return new Response(JSON.stringify(anthropicResponse), {
|
|
116
|
-
status: response.status,
|
|
117
|
-
headers: { 'Content-Type': 'application/json' },
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
logTranslationError('OpenAI-compatible JSON translation failed', error);
|
|
122
|
-
return createAnthropicErrorResponse(502, 'api_error', JSON_TRANSLATION_ERROR_MESSAGE);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
function createAnthropicStreamingResponse(response) {
|
|
126
|
-
const body = response.body;
|
|
127
|
-
if (!body) {
|
|
128
|
-
return createAnthropicErrorResponse(502, 'api_error', 'Upstream stream ended before a response body was available');
|
|
129
|
-
}
|
|
130
|
-
const parser = new sse_parser_1.SSEParser({ throwOnMalformedJson: true });
|
|
131
|
-
const transformer = new glmt_transformer_1.GlmtTransformer();
|
|
132
|
-
const accumulator = new delta_accumulator_1.DeltaAccumulator({});
|
|
133
|
-
const encoder = new TextEncoder();
|
|
134
|
-
const readable = new ReadableStream({
|
|
135
|
-
async start(controller) {
|
|
136
|
-
const reader = body.getReader();
|
|
137
|
-
try {
|
|
138
|
-
while (true) {
|
|
139
|
-
const { done, value } = await reader.read();
|
|
140
|
-
if (done) {
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
if (!value) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
const events = parser.parse(Buffer.from(value));
|
|
147
|
-
for (const event of events) {
|
|
148
|
-
const anthropicEvents = transformer.transformDelta(event, accumulator);
|
|
149
|
-
for (const anthropicEvent of anthropicEvents) {
|
|
150
|
-
controller.enqueue(encoder.encode(formatSseEvent(anthropicEvent.event, anthropicEvent.data)));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if (!accumulator.isFinalized() && accumulator.isMessageStarted()) {
|
|
155
|
-
for (const anthropicEvent of transformer.finalizeDelta(accumulator)) {
|
|
156
|
-
controller.enqueue(encoder.encode(formatSseEvent(anthropicEvent.event, anthropicEvent.data)));
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
catch (error) {
|
|
161
|
-
logTranslationError('OpenAI-compatible SSE translation failed', error);
|
|
162
|
-
controller.enqueue(encoder.encode(formatSseEvent('error', createAnthropicErrorPayload('api_error', STREAM_TRANSLATION_ERROR_MESSAGE))));
|
|
163
|
-
}
|
|
164
|
-
finally {
|
|
165
|
-
reader.releaseLock();
|
|
166
|
-
controller.close();
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
});
|
|
170
|
-
return new Response(readable, {
|
|
171
|
-
status: response.status,
|
|
172
|
-
headers: {
|
|
173
|
-
'Content-Type': 'text/event-stream',
|
|
174
|
-
'Cache-Control': 'no-cache',
|
|
175
|
-
Connection: 'keep-alive',
|
|
176
|
-
},
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
async function createAnthropicProxyResponse(response) {
|
|
180
|
-
if (!response.ok) {
|
|
181
|
-
return createAnthropicErrorProxyResponse(response);
|
|
182
|
-
}
|
|
183
|
-
const contentType = (response.headers.get('content-type') || '').toLowerCase();
|
|
184
|
-
const isEventStream = contentType === 'text/event-stream' || contentType.startsWith('text/event-stream;');
|
|
185
|
-
return isEventStream
|
|
186
|
-
? createAnthropicStreamingResponse(response)
|
|
187
|
-
: createAnthropicJsonResponse(response);
|
|
188
|
-
}
|
|
189
|
-
exports.createAnthropicProxyResponse = createAnthropicProxyResponse;
|
|
190
|
-
class ProxySseStreamTransformer {
|
|
191
|
-
async transform(response) {
|
|
192
|
-
return createAnthropicProxyResponse(response);
|
|
193
|
-
}
|
|
194
|
-
error(status, type, message) {
|
|
195
|
-
return createAnthropicErrorResponse(status, type, message);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
exports.ProxySseStreamTransformer = ProxySseStreamTransformer;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProxySseStreamTransformer = exports.createAnthropicProxyResponse = exports.createAnthropicErrorResponse = void 0;
|
|
4
|
+
const delta_accumulator_1 = require("../glmt/delta-accumulator");
|
|
5
|
+
const glmt_transformer_1 = require("../glmt/glmt-transformer");
|
|
6
|
+
const sse_parser_1 = require("../glmt/sse-parser");
|
|
7
|
+
const JSON_TRANSLATION_ERROR_MESSAGE = 'Failed to translate OpenAI-compatible JSON response';
|
|
8
|
+
const STREAM_TRANSLATION_ERROR_MESSAGE = 'Failed to translate OpenAI-compatible SSE response';
|
|
9
|
+
function createAnthropicErrorPayload(type, message) {
|
|
10
|
+
return {
|
|
11
|
+
type: 'error',
|
|
12
|
+
error: {
|
|
13
|
+
type,
|
|
14
|
+
message,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function formatErrorForLog(error) {
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
return error.message;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
return JSON.stringify(error);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return String(error);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function logTranslationError(context, error) {
|
|
30
|
+
console.error(`[proxy-sse-transformer] ${context}: ${formatErrorForLog(error)}`);
|
|
31
|
+
}
|
|
32
|
+
function createAnthropicErrorResponse(status, type, message, headers) {
|
|
33
|
+
const responseHeaders = new Headers(headers);
|
|
34
|
+
responseHeaders.set('Content-Type', 'application/json');
|
|
35
|
+
responseHeaders.delete('Content-Length');
|
|
36
|
+
return new Response(JSON.stringify(createAnthropicErrorPayload(type, message)), {
|
|
37
|
+
status,
|
|
38
|
+
headers: responseHeaders,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
exports.createAnthropicErrorResponse = createAnthropicErrorResponse;
|
|
42
|
+
function formatSseEvent(event, data) {
|
|
43
|
+
return `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
|
|
44
|
+
}
|
|
45
|
+
function hasTranslatableChoices(value) {
|
|
46
|
+
if (typeof value !== 'object' || value === null) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const { choices } = value;
|
|
50
|
+
if (!Array.isArray(choices) || choices.length === 0) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const firstChoice = choices[0];
|
|
54
|
+
if (typeof firstChoice !== 'object' || firstChoice === null) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const message = firstChoice.message;
|
|
58
|
+
return typeof message === 'object' && message !== null;
|
|
59
|
+
}
|
|
60
|
+
function isSyntheticTransformationFallback(value) {
|
|
61
|
+
return (typeof value === 'object' &&
|
|
62
|
+
value !== null &&
|
|
63
|
+
typeof value.id === 'string' &&
|
|
64
|
+
value.id.startsWith('msg_error_'));
|
|
65
|
+
}
|
|
66
|
+
async function createAnthropicErrorProxyResponse(response) {
|
|
67
|
+
const headers = new Headers(response.headers);
|
|
68
|
+
headers.delete('Content-Type');
|
|
69
|
+
headers.delete('Content-Length');
|
|
70
|
+
let type = response.status === 401
|
|
71
|
+
? 'authentication_error'
|
|
72
|
+
: response.status === 429
|
|
73
|
+
? 'rate_limit_error'
|
|
74
|
+
: response.status >= 400 && response.status < 500
|
|
75
|
+
? 'invalid_request_error'
|
|
76
|
+
: 'api_error';
|
|
77
|
+
let message = `Upstream request failed with status ${response.status}`;
|
|
78
|
+
try {
|
|
79
|
+
const contentType = (response.headers.get('content-type') || '').toLowerCase();
|
|
80
|
+
if (contentType.includes('application/json')) {
|
|
81
|
+
const payload = (await response.json());
|
|
82
|
+
if (typeof payload?.error?.type === 'string' && payload.error.type.trim().length > 0) {
|
|
83
|
+
type = payload.error.type;
|
|
84
|
+
}
|
|
85
|
+
if (typeof payload?.error?.message === 'string' && payload.error.message.trim().length > 0) {
|
|
86
|
+
message = payload.error.message;
|
|
87
|
+
}
|
|
88
|
+
else if (typeof payload?.message === 'string' && payload.message.trim().length > 0) {
|
|
89
|
+
message = payload.message;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const text = (await response.text()).trim();
|
|
94
|
+
if (text.length > 0) {
|
|
95
|
+
message = text;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
logTranslationError('Failed to parse upstream error response', error);
|
|
101
|
+
}
|
|
102
|
+
return createAnthropicErrorResponse(response.status, type, message, headers);
|
|
103
|
+
}
|
|
104
|
+
async function createAnthropicJsonResponse(response) {
|
|
105
|
+
try {
|
|
106
|
+
const openAIResponse = await response.json();
|
|
107
|
+
if (!hasTranslatableChoices(openAIResponse)) {
|
|
108
|
+
return createAnthropicErrorResponse(502, 'api_error', JSON_TRANSLATION_ERROR_MESSAGE);
|
|
109
|
+
}
|
|
110
|
+
const anthropicResponse = new glmt_transformer_1.GlmtTransformer().transformResponse(openAIResponse);
|
|
111
|
+
if (isSyntheticTransformationFallback(anthropicResponse)) {
|
|
112
|
+
logTranslationError('OpenAI-compatible JSON translation produced synthetic fallback response', anthropicResponse);
|
|
113
|
+
return createAnthropicErrorResponse(502, 'api_error', JSON_TRANSLATION_ERROR_MESSAGE);
|
|
114
|
+
}
|
|
115
|
+
return new Response(JSON.stringify(anthropicResponse), {
|
|
116
|
+
status: response.status,
|
|
117
|
+
headers: { 'Content-Type': 'application/json' },
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
logTranslationError('OpenAI-compatible JSON translation failed', error);
|
|
122
|
+
return createAnthropicErrorResponse(502, 'api_error', JSON_TRANSLATION_ERROR_MESSAGE);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function createAnthropicStreamingResponse(response) {
|
|
126
|
+
const body = response.body;
|
|
127
|
+
if (!body) {
|
|
128
|
+
return createAnthropicErrorResponse(502, 'api_error', 'Upstream stream ended before a response body was available');
|
|
129
|
+
}
|
|
130
|
+
const parser = new sse_parser_1.SSEParser({ throwOnMalformedJson: true });
|
|
131
|
+
const transformer = new glmt_transformer_1.GlmtTransformer();
|
|
132
|
+
const accumulator = new delta_accumulator_1.DeltaAccumulator({});
|
|
133
|
+
const encoder = new TextEncoder();
|
|
134
|
+
const readable = new ReadableStream({
|
|
135
|
+
async start(controller) {
|
|
136
|
+
const reader = body.getReader();
|
|
137
|
+
try {
|
|
138
|
+
while (true) {
|
|
139
|
+
const { done, value } = await reader.read();
|
|
140
|
+
if (done) {
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
if (!value) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const events = parser.parse(Buffer.from(value));
|
|
147
|
+
for (const event of events) {
|
|
148
|
+
const anthropicEvents = transformer.transformDelta(event, accumulator);
|
|
149
|
+
for (const anthropicEvent of anthropicEvents) {
|
|
150
|
+
controller.enqueue(encoder.encode(formatSseEvent(anthropicEvent.event, anthropicEvent.data)));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!accumulator.isFinalized() && accumulator.isMessageStarted()) {
|
|
155
|
+
for (const anthropicEvent of transformer.finalizeDelta(accumulator)) {
|
|
156
|
+
controller.enqueue(encoder.encode(formatSseEvent(anthropicEvent.event, anthropicEvent.data)));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
logTranslationError('OpenAI-compatible SSE translation failed', error);
|
|
162
|
+
controller.enqueue(encoder.encode(formatSseEvent('error', createAnthropicErrorPayload('api_error', STREAM_TRANSLATION_ERROR_MESSAGE))));
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
reader.releaseLock();
|
|
166
|
+
controller.close();
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
return new Response(readable, {
|
|
171
|
+
status: response.status,
|
|
172
|
+
headers: {
|
|
173
|
+
'Content-Type': 'text/event-stream',
|
|
174
|
+
'Cache-Control': 'no-cache',
|
|
175
|
+
Connection: 'keep-alive',
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
async function createAnthropicProxyResponse(response) {
|
|
180
|
+
if (!response.ok) {
|
|
181
|
+
return createAnthropicErrorProxyResponse(response);
|
|
182
|
+
}
|
|
183
|
+
const contentType = (response.headers.get('content-type') || '').toLowerCase();
|
|
184
|
+
const isEventStream = contentType === 'text/event-stream' || contentType.startsWith('text/event-stream;');
|
|
185
|
+
return isEventStream
|
|
186
|
+
? createAnthropicStreamingResponse(response)
|
|
187
|
+
: createAnthropicJsonResponse(response);
|
|
188
|
+
}
|
|
189
|
+
exports.createAnthropicProxyResponse = createAnthropicProxyResponse;
|
|
190
|
+
class ProxySseStreamTransformer {
|
|
191
|
+
async transform(response) {
|
|
192
|
+
return createAnthropicProxyResponse(response);
|
|
193
|
+
}
|
|
194
|
+
error(status, type, message) {
|
|
195
|
+
return createAnthropicErrorResponse(status, type, message);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
exports.ProxySseStreamTransformer = ProxySseStreamTransformer;
|
|
199
199
|
//# sourceMappingURL=sse-stream-transformer.js.map
|