free-antigravity-cli 1.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/LICENSE +201 -0
- package/README.md +142 -0
- package/dist/chat.d.ts +2 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +212 -0
- package/dist/chat.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +216 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +125 -0
- package/dist/config.js.map +1 -0
- package/dist/crypto.d.ts +5 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +93 -0
- package/dist/crypto.js.map +1 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +10 -0
- package/dist/logger.js.map +1 -0
- package/dist/proxy/modelUtils.d.ts +31 -0
- package/dist/proxy/modelUtils.d.ts.map +1 -0
- package/dist/proxy/modelUtils.js +55 -0
- package/dist/proxy/modelUtils.js.map +1 -0
- package/dist/proxy/registry.d.ts +40 -0
- package/dist/proxy/registry.d.ts.map +1 -0
- package/dist/proxy/registry.js +176 -0
- package/dist/proxy/registry.js.map +1 -0
- package/dist/proxy/shared.d.ts +39 -0
- package/dist/proxy/shared.d.ts.map +1 -0
- package/dist/proxy/shared.js +74 -0
- package/dist/proxy/shared.js.map +1 -0
- package/dist/proxy/translators/anthropic.d.ts +119 -0
- package/dist/proxy/translators/anthropic.d.ts.map +1 -0
- package/dist/proxy/translators/anthropic.js +273 -0
- package/dist/proxy/translators/anthropic.js.map +1 -0
- package/dist/proxy/translators/google.d.ts +86 -0
- package/dist/proxy/translators/google.d.ts.map +1 -0
- package/dist/proxy/translators/google.js +111 -0
- package/dist/proxy/translators/google.js.map +1 -0
- package/dist/proxy/translators/ollama.d.ts +27 -0
- package/dist/proxy/translators/ollama.d.ts.map +1 -0
- package/dist/proxy/translators/ollama.js +82 -0
- package/dist/proxy/translators/ollama.js.map +1 -0
- package/dist/proxy/translators/openai.d.ts +132 -0
- package/dist/proxy/translators/openai.d.ts.map +1 -0
- package/dist/proxy/translators/openai.js +396 -0
- package/dist/proxy/translators/openai.js.map +1 -0
- package/dist/proxy/translators/utils.d.ts +60 -0
- package/dist/proxy/translators/utils.d.ts.map +1 -0
- package/dist/proxy/translators/utils.js +504 -0
- package/dist/proxy/translators/utils.js.map +1 -0
- package/dist/proxy.d.ts +22 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +576 -0
- package/dist/proxy.js.map +1 -0
- package/dist/schemaValidator.d.ts +50 -0
- package/dist/schemaValidator.d.ts.map +1 -0
- package/dist/schemaValidator.js +208 -0
- package/dist/schemaValidator.js.map +1 -0
- package/install.cmd +33 -0
- package/package.json +46 -0
- package/src/chat.ts +184 -0
- package/src/cli.ts +184 -0
- package/src/config.ts +99 -0
- package/src/crypto.ts +49 -0
- package/src/logger.ts +8 -0
- package/src/proxy/modelUtils.ts +86 -0
- package/src/proxy/registry.ts +196 -0
- package/src/proxy/shared.ts +102 -0
- package/src/proxy/translators/anthropic.ts +420 -0
- package/src/proxy/translators/google.ts +162 -0
- package/src/proxy/translators/ollama.ts +88 -0
- package/src/proxy/translators/openai.ts +556 -0
- package/src/proxy/translators/utils.ts +552 -0
- package/src/proxy.ts +573 -0
- package/src/schemaValidator.ts +215 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Anthropic provider translator.
|
|
4
|
+
* Handles Gemini ↔ Anthropic request/response mapping and streaming SSE events.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.mapGeminiToAnthropic = mapGeminiToAnthropic;
|
|
8
|
+
exports.mapAnthropicToGemini = mapAnthropicToGemini;
|
|
9
|
+
exports.mapAnthropicChunkToGemini = mapAnthropicChunkToGemini;
|
|
10
|
+
exports.mapGeminiToolsToAnthropic = mapGeminiToolsToAnthropic;
|
|
11
|
+
const logger_1 = require("../../logger");
|
|
12
|
+
const utils_1 = require("./utils");
|
|
13
|
+
const shared_1 = require("../shared");
|
|
14
|
+
const modelUtils_1 = require("../modelUtils");
|
|
15
|
+
// ─── REQUEST: Gemini → Anthropic ──────────────────────────────────────────
|
|
16
|
+
function mapGeminiToolsToAnthropic(geminiTools) {
|
|
17
|
+
if (!geminiTools || !Array.isArray(geminiTools))
|
|
18
|
+
return [];
|
|
19
|
+
const anthropicTools = [];
|
|
20
|
+
for (const toolGroup of geminiTools) {
|
|
21
|
+
if (toolGroup.functionDeclarations && Array.isArray(toolGroup.functionDeclarations)) {
|
|
22
|
+
for (const func of toolGroup.functionDeclarations) {
|
|
23
|
+
const params = func.parameters
|
|
24
|
+
? JSON.parse(JSON.stringify(func.parameters))
|
|
25
|
+
: { type: 'OBJECT', properties: {} };
|
|
26
|
+
if (params.type && typeof params.type === 'string') {
|
|
27
|
+
params.type = params.type.toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
if (params.properties) {
|
|
30
|
+
(0, utils_1.fixParamTypes)(params.properties);
|
|
31
|
+
}
|
|
32
|
+
anthropicTools.push({
|
|
33
|
+
name: func.name,
|
|
34
|
+
description: func.description || '',
|
|
35
|
+
input_schema: params,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return anthropicTools;
|
|
41
|
+
}
|
|
42
|
+
function mapGeminiToAnthropic(geminiBody, modelName) {
|
|
43
|
+
const messages = [];
|
|
44
|
+
let system = undefined;
|
|
45
|
+
if (geminiBody.systemInstruction && geminiBody.systemInstruction.parts) {
|
|
46
|
+
system = geminiBody.systemInstruction.parts.map((p) => p.text || '').join('');
|
|
47
|
+
}
|
|
48
|
+
if (geminiBody.contents) {
|
|
49
|
+
for (const item of geminiBody.contents) {
|
|
50
|
+
if (item.parts) {
|
|
51
|
+
const hasFunctionCall = item.parts.some((p) => p.functionCall);
|
|
52
|
+
const hasFunctionResponse = item.parts.some((p) => p.functionResponse);
|
|
53
|
+
if (hasFunctionCall && item.role === 'model') {
|
|
54
|
+
const contentBlocks = [];
|
|
55
|
+
for (const p of item.parts) {
|
|
56
|
+
if (p.text)
|
|
57
|
+
contentBlocks.push({ type: 'text', text: p.text });
|
|
58
|
+
if (p.functionCall) {
|
|
59
|
+
const callId = p.functionCall.id || 'call_' + Math.random().toString(36).slice(2, 10);
|
|
60
|
+
let originalName = p.functionCall.name;
|
|
61
|
+
let originalArgs = p.functionCall.args;
|
|
62
|
+
const translatedInfo = shared_1.translatedToolCalls.get(callId);
|
|
63
|
+
if (translatedInfo) {
|
|
64
|
+
originalName = translatedInfo.originalName;
|
|
65
|
+
originalArgs = { CommandLine: translatedInfo.cmd, Cwd: translatedInfo.cwd };
|
|
66
|
+
}
|
|
67
|
+
contentBlocks.push({
|
|
68
|
+
type: 'tool_use',
|
|
69
|
+
id: callId,
|
|
70
|
+
name: originalName,
|
|
71
|
+
input: typeof originalArgs === 'string'
|
|
72
|
+
? JSON.parse(originalArgs)
|
|
73
|
+
: originalArgs,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
messages.push({ role: 'assistant', content: contentBlocks });
|
|
78
|
+
}
|
|
79
|
+
else if (hasFunctionResponse) {
|
|
80
|
+
const contentBlocks = [];
|
|
81
|
+
for (const p of item.parts) {
|
|
82
|
+
if (p.functionResponse) {
|
|
83
|
+
const funcName = p.functionResponse.name || '';
|
|
84
|
+
const modelTCIds = shared_1.modelToolCallIds.get(modelName) || {};
|
|
85
|
+
const toolCallId = p.functionResponse.id || modelTCIds[funcName] || 'call_' + funcName;
|
|
86
|
+
const responseData = p.functionResponse.response;
|
|
87
|
+
let contentStr = '';
|
|
88
|
+
const translatedInfo = shared_1.translatedToolCalls.get(toolCallId);
|
|
89
|
+
if (translatedInfo) {
|
|
90
|
+
contentStr = (0, utils_1.formatTranslatedResponse)(translatedInfo, responseData);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
contentStr = typeof responseData === 'string' ? responseData : JSON.stringify(responseData || {});
|
|
94
|
+
}
|
|
95
|
+
contentBlocks.push({
|
|
96
|
+
type: 'tool_result',
|
|
97
|
+
tool_use_id: toolCallId,
|
|
98
|
+
content: contentStr,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
messages.push({ role: 'user', content: contentBlocks });
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
const roleStr = item.role === 'model' ? 'assistant' : item.role || 'user';
|
|
106
|
+
let content = '';
|
|
107
|
+
if (item.parts)
|
|
108
|
+
content = item.parts.map((p) => p.text || '').join('');
|
|
109
|
+
if (roleStr === 'system') {
|
|
110
|
+
system = (system || '') + '\n' + content;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
messages.push({ role: roleStr, content });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const result = {
|
|
120
|
+
model: modelName,
|
|
121
|
+
messages,
|
|
122
|
+
system,
|
|
123
|
+
max_tokens: geminiBody.generationConfig?.maxOutputTokens ?? 16000,
|
|
124
|
+
};
|
|
125
|
+
// Claude thinking models don't support temperature (centralized detection)
|
|
126
|
+
const { isThinkingModel } = (0, modelUtils_1.detectModelCapabilitiesByName)(modelName);
|
|
127
|
+
if (!isThinkingModel) {
|
|
128
|
+
const temp = geminiBody.generationConfig?.temperature;
|
|
129
|
+
if (temp !== undefined && temp !== null)
|
|
130
|
+
result.temperature = temp;
|
|
131
|
+
}
|
|
132
|
+
if (geminiBody.tools && Array.isArray(geminiBody.tools)) {
|
|
133
|
+
const anthTools = mapGeminiToolsToAnthropic(geminiBody.tools);
|
|
134
|
+
if (anthTools.length > 0)
|
|
135
|
+
result.tools = anthTools;
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
// ─── RESPONSE: Anthropic → Gemini ─────────────────────────────────────────
|
|
140
|
+
function mapAnthropicToGemini(anthRes, modelName) {
|
|
141
|
+
const contentBlocks = anthRes.content || [];
|
|
142
|
+
const parts = [];
|
|
143
|
+
const functionCalls = [];
|
|
144
|
+
for (const block of contentBlocks) {
|
|
145
|
+
if (block.type === 'text' && block.text) {
|
|
146
|
+
parts.push({ text: block.text });
|
|
147
|
+
}
|
|
148
|
+
else if (block.type === 'thinking' && block.thinking) {
|
|
149
|
+
parts.push({ text: block.thinking, thought: true });
|
|
150
|
+
}
|
|
151
|
+
else if (block.type === 'tool_use') {
|
|
152
|
+
const modelTCIds = shared_1.modelToolCallIds.get(modelName) || {};
|
|
153
|
+
modelTCIds[block.name || ''] = block.id || '';
|
|
154
|
+
shared_1.modelToolCallIds.set(modelName, modelTCIds);
|
|
155
|
+
(0, shared_1.touchStateTimestamp)(shared_1.stateTimestamps.toolCallIds, modelName);
|
|
156
|
+
const normalizedInput = (0, utils_1.normalizeToolArgs)(block.name || '', block.input || {});
|
|
157
|
+
const translated = (0, utils_1.translateToolCallToNative)(block.name || '', normalizedInput);
|
|
158
|
+
if (translated.name !== block.name) {
|
|
159
|
+
translated.args = (0, utils_1.normalizeToolArgs)(translated.name, translated.args);
|
|
160
|
+
shared_1.translatedToolCalls.set(block.id || '', {
|
|
161
|
+
originalName: block.name || '',
|
|
162
|
+
translatedName: translated.name,
|
|
163
|
+
cmd: normalizedInput.CommandLine || '',
|
|
164
|
+
cwd: normalizedInput.Cwd || '',
|
|
165
|
+
});
|
|
166
|
+
(0, shared_1.touchStateTimestamp)(shared_1.stateTimestamps.translatedCalls, block.id || '');
|
|
167
|
+
}
|
|
168
|
+
functionCalls.push({
|
|
169
|
+
functionCall: { name: translated.name, args: translated.args, id: block.id },
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (functionCalls.length > 0) {
|
|
174
|
+
return {
|
|
175
|
+
candidates: [
|
|
176
|
+
{ content: { parts: [...parts, ...functionCalls], role: 'model' }, finishReason: 'TOOL_CALL', index: 0 },
|
|
177
|
+
],
|
|
178
|
+
usageMetadata: {
|
|
179
|
+
promptTokenCount: anthRes.usage?.input_tokens || 0,
|
|
180
|
+
candidatesTokenCount: anthRes.usage?.output_tokens || 0,
|
|
181
|
+
totalTokenCount: (anthRes.usage?.input_tokens || 0) + (anthRes.usage?.output_tokens || 0),
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const finishReason = anthRes.stop_reason === 'end_turn' ? 'STOP' : anthRes.stop_reason === 'max_tokens' ? 'MAX_TOKENS' : 'OTHER';
|
|
186
|
+
return {
|
|
187
|
+
candidates: [{ content: { parts, role: 'model' }, finishReason, index: 0 }],
|
|
188
|
+
usageMetadata: {
|
|
189
|
+
promptTokenCount: anthRes.usage?.input_tokens || 0,
|
|
190
|
+
candidatesTokenCount: anthRes.usage?.output_tokens || 0,
|
|
191
|
+
totalTokenCount: (anthRes.usage?.input_tokens || 0) + (anthRes.usage?.output_tokens || 0),
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
// ─── STREAM CHUNK: Anthropic SSE → Gemini ─────────────────────────────────
|
|
196
|
+
function mapAnthropicChunkToGemini(chunk, modelName) {
|
|
197
|
+
const type = chunk.type;
|
|
198
|
+
const streamId = chunk.message?.id || 'anthropic_stream';
|
|
199
|
+
if (!shared_1.activeStreamContexts.has(streamId)) {
|
|
200
|
+
shared_1.activeStreamContexts.set(streamId, { accumulatedText: '', accumulatedReasoning: '', toolCalls: {} });
|
|
201
|
+
(0, shared_1.touchStateTimestamp)(shared_1.stateTimestamps.streamCtx, streamId);
|
|
202
|
+
}
|
|
203
|
+
const context = shared_1.activeStreamContexts.get(streamId);
|
|
204
|
+
if (type === 'content_block_start') {
|
|
205
|
+
const block = chunk.content_block;
|
|
206
|
+
const idx = chunk.index ?? 0;
|
|
207
|
+
if (block?.type === 'tool_use') {
|
|
208
|
+
context.toolCalls[idx] = { id: block.id || '', name: block.name || '', arguments: '' };
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (type === 'content_block_delta') {
|
|
212
|
+
const delta = chunk.delta;
|
|
213
|
+
const idx = chunk.index ?? 0;
|
|
214
|
+
if (delta?.type === 'text_delta') {
|
|
215
|
+
const text = delta.text || '';
|
|
216
|
+
context.accumulatedText += text;
|
|
217
|
+
return { content: { parts: [{ text }], role: 'model' }, finishReason: 'OTHER', index: 0 };
|
|
218
|
+
}
|
|
219
|
+
else if (delta?.type === 'thinking_delta') {
|
|
220
|
+
const thinkingText = delta.thinking || '';
|
|
221
|
+
context.accumulatedReasoning += thinkingText;
|
|
222
|
+
return {
|
|
223
|
+
content: { parts: [{ text: thinkingText, thought: true }], role: 'model' },
|
|
224
|
+
finishReason: 'OTHER',
|
|
225
|
+
index: 0,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
else if (delta?.type === 'input_delta') {
|
|
229
|
+
if (context.toolCalls[idx]) {
|
|
230
|
+
context.toolCalls[idx].arguments += delta.partial_json || '';
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (type === 'message_delta') {
|
|
235
|
+
const delta = chunk.delta;
|
|
236
|
+
if (delta?.stop_reason === 'tool_use') {
|
|
237
|
+
const parts = Object.values(context.toolCalls).map((tc) => {
|
|
238
|
+
let args = {};
|
|
239
|
+
try {
|
|
240
|
+
args = JSON.parse(tc.arguments);
|
|
241
|
+
}
|
|
242
|
+
catch (e) {
|
|
243
|
+
logger_1.log.debug('[Anthropic] Stream tool args parse fallback:', e.message);
|
|
244
|
+
args = {};
|
|
245
|
+
}
|
|
246
|
+
args = (0, utils_1.normalizeToolArgs)(tc.name, args);
|
|
247
|
+
const modelTCIds = shared_1.modelToolCallIds.get(modelName) || {};
|
|
248
|
+
modelTCIds[tc.name] = tc.id;
|
|
249
|
+
shared_1.modelToolCallIds.set(modelName, modelTCIds);
|
|
250
|
+
(0, shared_1.touchStateTimestamp)(shared_1.stateTimestamps.toolCallIds, modelName);
|
|
251
|
+
const translated = (0, utils_1.translateToolCallToNative)(tc.name, args);
|
|
252
|
+
if (translated.name !== tc.name) {
|
|
253
|
+
shared_1.translatedToolCalls.set(tc.id, {
|
|
254
|
+
originalName: tc.name,
|
|
255
|
+
translatedName: translated.name,
|
|
256
|
+
cmd: args.CommandLine || '',
|
|
257
|
+
cwd: args.Cwd || '',
|
|
258
|
+
});
|
|
259
|
+
(0, shared_1.touchStateTimestamp)(shared_1.stateTimestamps.translatedCalls, tc.id);
|
|
260
|
+
}
|
|
261
|
+
return { functionCall: { name: translated.name, args: translated.args, id: tc.id } };
|
|
262
|
+
});
|
|
263
|
+
shared_1.activeStreamContexts.delete(streamId);
|
|
264
|
+
return { content: { parts, role: 'model' }, finishReason: 'TOOL_CALL', index: 0 };
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (type === 'message_stop') {
|
|
268
|
+
shared_1.activeStreamContexts.delete(streamId);
|
|
269
|
+
return { content: { parts: [], role: 'model' }, finishReason: 'STOP', index: 0 };
|
|
270
|
+
}
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/proxy/translators/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google AI Studio Translator.
|
|
3
|
+
*
|
|
4
|
+
* Google AI Studio speaks Gemini format natively, so request/response
|
|
5
|
+
* translation is a passthrough. The main addition is SSE streaming chunk
|
|
6
|
+
* parsing and proper endpoint URL handling.
|
|
7
|
+
*/
|
|
8
|
+
interface GeminiPart {
|
|
9
|
+
text?: string;
|
|
10
|
+
functionCall?: {
|
|
11
|
+
name: string;
|
|
12
|
+
args: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
functionResponse?: {
|
|
15
|
+
name: string;
|
|
16
|
+
response: Record<string, unknown>;
|
|
17
|
+
};
|
|
18
|
+
thought?: boolean;
|
|
19
|
+
inlineData?: {
|
|
20
|
+
mimeType: string;
|
|
21
|
+
data: string;
|
|
22
|
+
};
|
|
23
|
+
fileData?: {
|
|
24
|
+
mimeType: string;
|
|
25
|
+
fileUri: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
interface GeminiContent {
|
|
29
|
+
parts?: GeminiPart[];
|
|
30
|
+
role?: string;
|
|
31
|
+
}
|
|
32
|
+
interface GeminiCandidate {
|
|
33
|
+
content?: GeminiContent;
|
|
34
|
+
finishReason?: string;
|
|
35
|
+
index?: number;
|
|
36
|
+
safetyRatings?: unknown[];
|
|
37
|
+
}
|
|
38
|
+
interface GeminiRequestBody {
|
|
39
|
+
model?: string;
|
|
40
|
+
modelId?: string;
|
|
41
|
+
contents?: GeminiContent[];
|
|
42
|
+
systemInstruction?: {
|
|
43
|
+
parts: {
|
|
44
|
+
text?: string;
|
|
45
|
+
}[];
|
|
46
|
+
};
|
|
47
|
+
tools?: unknown[];
|
|
48
|
+
generationConfig?: {
|
|
49
|
+
temperature?: number;
|
|
50
|
+
maxOutputTokens?: number;
|
|
51
|
+
topP?: number;
|
|
52
|
+
topK?: number;
|
|
53
|
+
stopSequences?: string[];
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Google AI Studio uses the same Gemini format — just pass through.
|
|
58
|
+
* The caller handles URL routing (streamGenerateContent vs generateContent).
|
|
59
|
+
*/
|
|
60
|
+
export declare function mapGeminiToGoogle(geminiBody: GeminiRequestBody, modelName: string): GeminiRequestBody;
|
|
61
|
+
/**
|
|
62
|
+
* Google AI Studio returns Gemini-format responses directly.
|
|
63
|
+
* Just pass through — the proxy wraps it in the Cloud Code envelope.
|
|
64
|
+
*/
|
|
65
|
+
export declare function mapGoogleToGemini(googleRes: unknown, _modelName: string): unknown;
|
|
66
|
+
/**
|
|
67
|
+
* Parse a Google AI Studio SSE streaming chunk into a Gemini candidate.
|
|
68
|
+
*
|
|
69
|
+
* Google AI Studio streams JSON chunks like:
|
|
70
|
+
* {"candidates":[{"content":{"parts":[{"text":"Hello"}],"role":"model"},...}]}
|
|
71
|
+
*
|
|
72
|
+
* Each chunk contains complete candidate objects (not deltas).
|
|
73
|
+
*/
|
|
74
|
+
export declare function mapGoogleChunkToGemini(chunk: unknown, _modelName: string): GeminiCandidate | null;
|
|
75
|
+
/**
|
|
76
|
+
* Constructs the correct Google AI Studio endpoint URL based on streaming mode.
|
|
77
|
+
*
|
|
78
|
+
* Google AI Studio uses different endpoints:
|
|
79
|
+
* - Non-streaming: :generateContent
|
|
80
|
+
* - Streaming: :streamGenerateContent
|
|
81
|
+
*
|
|
82
|
+
* If the user's URL already contains one of these endpoints, it's kept as-is.
|
|
83
|
+
*/
|
|
84
|
+
export declare function getGoogleApiUrl(baseUrl: string, modelName: string, isStream: boolean): string;
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=google.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../../src/proxy/translators/google.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IAC/D,gBAAgB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAClD;AAED,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,eAAe;IACvB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;CAC3B;AAQD,UAAU,iBAAiB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE;QAAE,KAAK,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,CAAC;IACnD,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,gBAAgB,CAAC,EAAE;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;CACH;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,GAAG,iBAAiB,CAOrG;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAIjF;AAID;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA8BjG;AAID;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CA2B7F"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Google AI Studio Translator.
|
|
4
|
+
*
|
|
5
|
+
* Google AI Studio speaks Gemini format natively, so request/response
|
|
6
|
+
* translation is a passthrough. The main addition is SSE streaming chunk
|
|
7
|
+
* parsing and proper endpoint URL handling.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.mapGeminiToGoogle = mapGeminiToGoogle;
|
|
11
|
+
exports.mapGoogleToGemini = mapGoogleToGemini;
|
|
12
|
+
exports.mapGoogleChunkToGemini = mapGoogleChunkToGemini;
|
|
13
|
+
exports.getGoogleApiUrl = getGoogleApiUrl;
|
|
14
|
+
const logger_1 = require("../../logger");
|
|
15
|
+
// ─── Request Translation (Passthrough) ────────────────────────────────────
|
|
16
|
+
/**
|
|
17
|
+
* Google AI Studio uses the same Gemini format — just pass through.
|
|
18
|
+
* The caller handles URL routing (streamGenerateContent vs generateContent).
|
|
19
|
+
*/
|
|
20
|
+
function mapGeminiToGoogle(geminiBody, modelName) {
|
|
21
|
+
// Ensure the external model name is set
|
|
22
|
+
const body = { ...geminiBody };
|
|
23
|
+
if (modelName && !body.model) {
|
|
24
|
+
body.model = modelName;
|
|
25
|
+
}
|
|
26
|
+
return body;
|
|
27
|
+
}
|
|
28
|
+
// ─── Response Translation (Passthrough) ───────────────────────────────────
|
|
29
|
+
/**
|
|
30
|
+
* Google AI Studio returns Gemini-format responses directly.
|
|
31
|
+
* Just pass through — the proxy wraps it in the Cloud Code envelope.
|
|
32
|
+
*/
|
|
33
|
+
function mapGoogleToGemini(googleRes, _modelName) {
|
|
34
|
+
// Google AI Studio response is already in Gemini format
|
|
35
|
+
// Wrapped by caller in { response, traceId, metadata }
|
|
36
|
+
return googleRes;
|
|
37
|
+
}
|
|
38
|
+
// ─── Streaming Chunk Translation ──────────────────────────────────────────
|
|
39
|
+
/**
|
|
40
|
+
* Parse a Google AI Studio SSE streaming chunk into a Gemini candidate.
|
|
41
|
+
*
|
|
42
|
+
* Google AI Studio streams JSON chunks like:
|
|
43
|
+
* {"candidates":[{"content":{"parts":[{"text":"Hello"}],"role":"model"},...}]}
|
|
44
|
+
*
|
|
45
|
+
* Each chunk contains complete candidate objects (not deltas).
|
|
46
|
+
*/
|
|
47
|
+
function mapGoogleChunkToGemini(chunk, _modelName) {
|
|
48
|
+
if (!chunk || typeof chunk !== 'object')
|
|
49
|
+
return null;
|
|
50
|
+
const data = chunk;
|
|
51
|
+
// Extract first candidate
|
|
52
|
+
if (!data.candidates || data.candidates.length === 0)
|
|
53
|
+
return null;
|
|
54
|
+
const candidate = data.candidates[0];
|
|
55
|
+
// Check if there's actual content to emit
|
|
56
|
+
const parts = candidate.content?.parts;
|
|
57
|
+
if (!parts || parts.length === 0) {
|
|
58
|
+
// Might be a final chunk with just finishReason
|
|
59
|
+
if (candidate.finishReason) {
|
|
60
|
+
return {
|
|
61
|
+
content: { parts: [], role: 'model' },
|
|
62
|
+
finishReason: candidate.finishReason,
|
|
63
|
+
index: candidate.index ?? 0,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
content: candidate.content,
|
|
70
|
+
finishReason: candidate.finishReason || 'OTHER',
|
|
71
|
+
index: candidate.index ?? 0,
|
|
72
|
+
safetyRatings: candidate.safetyRatings,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// ─── URL Helpers ──────────────────────────────────────────────────────────
|
|
76
|
+
/**
|
|
77
|
+
* Constructs the correct Google AI Studio endpoint URL based on streaming mode.
|
|
78
|
+
*
|
|
79
|
+
* Google AI Studio uses different endpoints:
|
|
80
|
+
* - Non-streaming: :generateContent
|
|
81
|
+
* - Streaming: :streamGenerateContent
|
|
82
|
+
*
|
|
83
|
+
* If the user's URL already contains one of these endpoints, it's kept as-is.
|
|
84
|
+
*/
|
|
85
|
+
function getGoogleApiUrl(baseUrl, modelName, isStream) {
|
|
86
|
+
let url = baseUrl;
|
|
87
|
+
// If the URL doesn't already specify a method, append one
|
|
88
|
+
if (!url.includes(':generateContent') && !url.includes(':streamGenerateContent')) {
|
|
89
|
+
// Strip trailing slash if present
|
|
90
|
+
url = url.replace(/\/$/, '');
|
|
91
|
+
// Check if the URL ends with the model path (e.g. /models/gemini-1.5-pro)
|
|
92
|
+
const modelPathPattern = /\/models\/([^\/]+)$/;
|
|
93
|
+
const modelMatch = modelPathPattern.exec(url);
|
|
94
|
+
if (modelMatch) {
|
|
95
|
+
// URL like .../v1beta/models/gemini-1.5-pro → append :method
|
|
96
|
+
const method = isStream ? ':streamGenerateContent' : ':generateContent';
|
|
97
|
+
url += method;
|
|
98
|
+
}
|
|
99
|
+
else if (modelName) {
|
|
100
|
+
// Append full path with model name
|
|
101
|
+
const method = isStream ? ':streamGenerateContent' : ':generateContent';
|
|
102
|
+
url += `models/${modelName}${method}`;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// Fallback: assume the URL is already complete
|
|
106
|
+
logger_1.log.warn('[GoogleTranslator] Could not determine model name for URL construction');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return url;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.js","sourceRoot":"","sources":["../../../src/proxy/translators/google.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAsDH,8CAOC;AAQD,8CAIC;AAYD,wDA8BC;AAaD,0CA2BC;AAzJD,yCAAmC;AA8CnC,6EAA6E;AAE7E;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,UAA6B,EAAE,SAAiB;IAChF,wCAAwC;IACxC,MAAM,IAAI,GAAsB,EAAE,GAAG,UAAU,EAAE,CAAC;IAClD,IAAI,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;IACzB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6EAA6E;AAE7E;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,SAAkB,EAAE,UAAkB;IACtE,wDAAwD;IACxD,uDAAuD;IACvD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,6EAA6E;AAE7E;;;;;;;GAOG;AACH,SAAgB,sBAAsB,CAAC,KAAc,EAAE,UAAkB;IACvE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAErD,MAAM,IAAI,GAAG,KAA0B,CAAC;IAExC,0BAA0B;IAC1B,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAElE,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAErC,0CAA0C;IAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC;IACvC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,gDAAgD;QAChD,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC;YAC3B,OAAO;gBACL,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;gBACrC,YAAY,EAAE,SAAS,CAAC,YAAY;gBACpC,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,CAAC;aAC5B,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,OAAO,EAAE,SAAS,CAAC,OAAO;QAC1B,YAAY,EAAE,SAAS,CAAC,YAAY,IAAI,OAAO;QAC/C,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,CAAC;QAC3B,aAAa,EAAE,SAAS,CAAC,aAAa;KACvC,CAAC;AACJ,CAAC;AAED,6EAA6E;AAE7E;;;;;;;;GAQG;AACH,SAAgB,eAAe,CAAC,OAAe,EAAE,SAAiB,EAAE,QAAiB;IACnF,IAAI,GAAG,GAAG,OAAO,CAAC;IAElB,0DAA0D;IAC1D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;QACjF,kCAAkC;QAClC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAE7B,0EAA0E;QAC1E,MAAM,gBAAgB,GAAG,qBAAqB,CAAC;QAC/C,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAE9C,IAAI,UAAU,EAAE,CAAC;YACf,6DAA6D;YAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,kBAAkB,CAAC;YACxE,GAAG,IAAI,MAAM,CAAC;QAChB,CAAC;aAAM,IAAI,SAAS,EAAE,CAAC;YACrB,mCAAmC;YACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,kBAAkB,CAAC;YACxE,GAAG,IAAI,UAAU,SAAS,GAAG,MAAM,EAAE,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,+CAA+C;YAC/C,YAAG,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Translator.
|
|
3
|
+
*
|
|
4
|
+
* Ollama is fully OpenAI-compatible (channels/v1/chat/completions).
|
|
5
|
+
* This module re-exports the OpenAI translator functions and adds
|
|
6
|
+
* Ollama-specific helpers:
|
|
7
|
+
* - Default URL normalization (localhost:11434 fallback)
|
|
8
|
+
* - User-friendly error message translation
|
|
9
|
+
*/
|
|
10
|
+
export { mapGeminiToOpenAI, mapOpenAIToGemini, mapOpenAIChunkToGemini } from './openai';
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes an Ollama API URL to the standard chat completions endpoint.
|
|
13
|
+
*
|
|
14
|
+
* Handles these common patterns:
|
|
15
|
+
* http://localhost:11434 → http://localhost:11434/v1/chat/completions
|
|
16
|
+
* http://localhost:11434/v1 → http://localhost:11434/v1/chat/completions
|
|
17
|
+
* http://localhost → http://localhost:11434/v1/chat/completions
|
|
18
|
+
* http://10.0.0.5:11434/api/generate → kept as-is (non-chat endpoint)
|
|
19
|
+
*
|
|
20
|
+
* If localhost has no port, defaults to Ollama's standard port 11434.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getOllamaApiUrl(baseUrl: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Translate raw Ollama errors into user-friendly messages.
|
|
25
|
+
*/
|
|
26
|
+
export declare function translateOllamaError(statusCode: number, body: string): string;
|
|
27
|
+
//# sourceMappingURL=ollama.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/proxy/translators/ollama.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAIxF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA6BvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB7E"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Ollama Translator.
|
|
4
|
+
*
|
|
5
|
+
* Ollama is fully OpenAI-compatible (channels/v1/chat/completions).
|
|
6
|
+
* This module re-exports the OpenAI translator functions and adds
|
|
7
|
+
* Ollama-specific helpers:
|
|
8
|
+
* - Default URL normalization (localhost:11434 fallback)
|
|
9
|
+
* - User-friendly error message translation
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.mapOpenAIChunkToGemini = exports.mapOpenAIToGemini = exports.mapGeminiToOpenAI = void 0;
|
|
13
|
+
exports.getOllamaApiUrl = getOllamaApiUrl;
|
|
14
|
+
exports.translateOllamaError = translateOllamaError;
|
|
15
|
+
const logger_1 = require("../../logger");
|
|
16
|
+
// ─── Re-export all OpenAI translator functions ────────────────────────────
|
|
17
|
+
// The registry auto-discovers these by naming convention:
|
|
18
|
+
// mapGeminiToOpenAI, mapOpenAIToGemini, mapOpenAIChunkToGemini
|
|
19
|
+
// Ollama uses the exact same format, so we re-export verbatim.
|
|
20
|
+
var openai_1 = require("./openai");
|
|
21
|
+
Object.defineProperty(exports, "mapGeminiToOpenAI", { enumerable: true, get: function () { return openai_1.mapGeminiToOpenAI; } });
|
|
22
|
+
Object.defineProperty(exports, "mapOpenAIToGemini", { enumerable: true, get: function () { return openai_1.mapOpenAIToGemini; } });
|
|
23
|
+
Object.defineProperty(exports, "mapOpenAIChunkToGemini", { enumerable: true, get: function () { return openai_1.mapOpenAIChunkToGemini; } });
|
|
24
|
+
// ─── Ollama-Specific Helpers ──────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* Normalizes an Ollama API URL to the standard chat completions endpoint.
|
|
27
|
+
*
|
|
28
|
+
* Handles these common patterns:
|
|
29
|
+
* http://localhost:11434 → http://localhost:11434/v1/chat/completions
|
|
30
|
+
* http://localhost:11434/v1 → http://localhost:11434/v1/chat/completions
|
|
31
|
+
* http://localhost → http://localhost:11434/v1/chat/completions
|
|
32
|
+
* http://10.0.0.5:11434/api/generate → kept as-is (non-chat endpoint)
|
|
33
|
+
*
|
|
34
|
+
* If localhost has no port, defaults to Ollama's standard port 11434.
|
|
35
|
+
*/
|
|
36
|
+
function getOllamaApiUrl(baseUrl) {
|
|
37
|
+
let url = baseUrl;
|
|
38
|
+
// If it already has a specific API path, don't touch it
|
|
39
|
+
if (url.includes('/api/')) {
|
|
40
|
+
return url;
|
|
41
|
+
}
|
|
42
|
+
// Clean trailing slash
|
|
43
|
+
url = url.replace(/\/$/, '');
|
|
44
|
+
// If no port on localhost, use default Ollama port
|
|
45
|
+
if (url.match(/^https?:\/\/localhost$/)) {
|
|
46
|
+
url = 'http://localhost:11434';
|
|
47
|
+
logger_1.log.info('[OllamaTranslator] Added default Ollama port 11434');
|
|
48
|
+
}
|
|
49
|
+
// If URL ends with /v1, append /chat/completions
|
|
50
|
+
if (url.endsWith('/v1')) {
|
|
51
|
+
url += '/chat/completions';
|
|
52
|
+
return url;
|
|
53
|
+
}
|
|
54
|
+
// If URL doesn't have a chat completions path, add full /v1/chat/completions
|
|
55
|
+
if (!url.includes('/chat/completions') && !url.includes('/completions')) {
|
|
56
|
+
url += '/v1/chat/completions';
|
|
57
|
+
}
|
|
58
|
+
return url;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Translate raw Ollama errors into user-friendly messages.
|
|
62
|
+
*/
|
|
63
|
+
function translateOllamaError(statusCode, body) {
|
|
64
|
+
// Connection refused — Ollama service not running
|
|
65
|
+
if (body.includes('ECONNREFUSED') || body.includes('connect ECONNREFUSED')) {
|
|
66
|
+
return 'Ollama is not running. Start it with `ollama serve` or launch the Ollama desktop app.';
|
|
67
|
+
}
|
|
68
|
+
// Model not pulled yet
|
|
69
|
+
if (statusCode === 404 || (body.includes('model') && body.includes('not found'))) {
|
|
70
|
+
const modelMatch = body.match(/model ['"]([^'"]+)['"]/);
|
|
71
|
+
const modelName = modelMatch ? modelMatch[1] : 'unknown';
|
|
72
|
+
return `Ollama model "${modelName}" not found. Pull it: ollama pull ${modelName}`;
|
|
73
|
+
}
|
|
74
|
+
// Server-side errors (OOM, crash, etc.)
|
|
75
|
+
if (statusCode >= 500) {
|
|
76
|
+
return `Ollama server error (${statusCode}). Check if Ollama has enough resources (RAM/VRAM).`;
|
|
77
|
+
}
|
|
78
|
+
// Generic fallback with truncated body
|
|
79
|
+
const snippet = body.substring(0, 200);
|
|
80
|
+
return `Ollama error (${statusCode}): ${snippet}`;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=ollama.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/proxy/translators/ollama.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAwBH,0CA6BC;AAKD,oDAqBC;AA7ED,yCAAmC;AAEnC,6EAA6E;AAC7E,0DAA0D;AAC1D,iEAAiE;AACjE,+DAA+D;AAE/D,mCAAwF;AAA/E,2GAAA,iBAAiB,OAAA;AAAE,2GAAA,iBAAiB,OAAA;AAAE,gHAAA,sBAAsB,OAAA;AAErE,6EAA6E;AAE7E;;;;;;;;;;GAUG;AACH,SAAgB,eAAe,CAAC,OAAe;IAC7C,IAAI,GAAG,GAAG,OAAO,CAAC;IAElB,wDAAwD;IACxD,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,uBAAuB;IACvB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAE7B,mDAAmD;IACnD,IAAI,GAAG,CAAC,KAAK,CAAC,wBAAwB,CAAC,EAAE,CAAC;QACxC,GAAG,GAAG,wBAAwB,CAAC;QAC/B,YAAG,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;IACjE,CAAC;IAED,iDAAiD;IACjD,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,GAAG,IAAI,mBAAmB,CAAC;QAC3B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,6EAA6E;IAC7E,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACxE,GAAG,IAAI,sBAAsB,CAAC;IAChC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAAC,UAAkB,EAAE,IAAY;IACnE,kDAAkD;IAClD,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;QAC3E,OAAO,uFAAuF,CAAC;IACjG,CAAC;IAED,uBAAuB;IACvB,IAAI,UAAU,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QACjF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzD,OAAO,iBAAiB,SAAS,qCAAqC,SAAS,EAAE,CAAC;IACpF,CAAC;IAED,wCAAwC;IACxC,IAAI,UAAU,IAAI,GAAG,EAAE,CAAC;QACtB,OAAO,wBAAwB,UAAU,qDAAqD,CAAC;IACjG,CAAC;IAED,uCAAuC;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvC,OAAO,iBAAiB,UAAU,MAAM,OAAO,EAAE,CAAC;AACpD,CAAC"}
|