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.
Files changed (80) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +142 -0
  3. package/dist/chat.d.ts +2 -0
  4. package/dist/chat.d.ts.map +1 -0
  5. package/dist/chat.js +212 -0
  6. package/dist/chat.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +216 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/config.d.ts +29 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +125 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/crypto.d.ts +5 -0
  16. package/dist/crypto.d.ts.map +1 -0
  17. package/dist/crypto.js +93 -0
  18. package/dist/crypto.js.map +1 -0
  19. package/dist/logger.d.ts +9 -0
  20. package/dist/logger.d.ts.map +1 -0
  21. package/dist/logger.js +10 -0
  22. package/dist/logger.js.map +1 -0
  23. package/dist/proxy/modelUtils.d.ts +31 -0
  24. package/dist/proxy/modelUtils.d.ts.map +1 -0
  25. package/dist/proxy/modelUtils.js +55 -0
  26. package/dist/proxy/modelUtils.js.map +1 -0
  27. package/dist/proxy/registry.d.ts +40 -0
  28. package/dist/proxy/registry.d.ts.map +1 -0
  29. package/dist/proxy/registry.js +176 -0
  30. package/dist/proxy/registry.js.map +1 -0
  31. package/dist/proxy/shared.d.ts +39 -0
  32. package/dist/proxy/shared.d.ts.map +1 -0
  33. package/dist/proxy/shared.js +74 -0
  34. package/dist/proxy/shared.js.map +1 -0
  35. package/dist/proxy/translators/anthropic.d.ts +119 -0
  36. package/dist/proxy/translators/anthropic.d.ts.map +1 -0
  37. package/dist/proxy/translators/anthropic.js +273 -0
  38. package/dist/proxy/translators/anthropic.js.map +1 -0
  39. package/dist/proxy/translators/google.d.ts +86 -0
  40. package/dist/proxy/translators/google.d.ts.map +1 -0
  41. package/dist/proxy/translators/google.js +111 -0
  42. package/dist/proxy/translators/google.js.map +1 -0
  43. package/dist/proxy/translators/ollama.d.ts +27 -0
  44. package/dist/proxy/translators/ollama.d.ts.map +1 -0
  45. package/dist/proxy/translators/ollama.js +82 -0
  46. package/dist/proxy/translators/ollama.js.map +1 -0
  47. package/dist/proxy/translators/openai.d.ts +132 -0
  48. package/dist/proxy/translators/openai.d.ts.map +1 -0
  49. package/dist/proxy/translators/openai.js +396 -0
  50. package/dist/proxy/translators/openai.js.map +1 -0
  51. package/dist/proxy/translators/utils.d.ts +60 -0
  52. package/dist/proxy/translators/utils.d.ts.map +1 -0
  53. package/dist/proxy/translators/utils.js +504 -0
  54. package/dist/proxy/translators/utils.js.map +1 -0
  55. package/dist/proxy.d.ts +22 -0
  56. package/dist/proxy.d.ts.map +1 -0
  57. package/dist/proxy.js +576 -0
  58. package/dist/proxy.js.map +1 -0
  59. package/dist/schemaValidator.d.ts +50 -0
  60. package/dist/schemaValidator.d.ts.map +1 -0
  61. package/dist/schemaValidator.js +208 -0
  62. package/dist/schemaValidator.js.map +1 -0
  63. package/install.cmd +33 -0
  64. package/package.json +46 -0
  65. package/src/chat.ts +184 -0
  66. package/src/cli.ts +184 -0
  67. package/src/config.ts +99 -0
  68. package/src/crypto.ts +49 -0
  69. package/src/logger.ts +8 -0
  70. package/src/proxy/modelUtils.ts +86 -0
  71. package/src/proxy/registry.ts +196 -0
  72. package/src/proxy/shared.ts +102 -0
  73. package/src/proxy/translators/anthropic.ts +420 -0
  74. package/src/proxy/translators/google.ts +162 -0
  75. package/src/proxy/translators/ollama.ts +88 -0
  76. package/src/proxy/translators/openai.ts +556 -0
  77. package/src/proxy/translators/utils.ts +552 -0
  78. package/src/proxy.ts +573 -0
  79. package/src/schemaValidator.ts +215 -0
  80. 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":"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"}
@@ -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"}