ai.matey.cli 0.2.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 +21 -0
- package/dist/cjs/convert-request.js +365 -0
- package/dist/cjs/convert-request.js.map +1 -0
- package/dist/cjs/convert-response.js +211 -0
- package/dist/cjs/convert-response.js.map +1 -0
- package/dist/cjs/converters/request-converters.js +183 -0
- package/dist/cjs/converters/request-converters.js.map +1 -0
- package/dist/cjs/converters/response-converters.js +203 -0
- package/dist/cjs/converters/response-converters.js.map +1 -0
- package/dist/cjs/create-backend.js +569 -0
- package/dist/cjs/create-backend.js.map +1 -0
- package/dist/cjs/index.js +31 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/main.js +181 -0
- package/dist/cjs/main.js.map +1 -0
- package/dist/cjs/ollama/commands/list.js +70 -0
- package/dist/cjs/ollama/commands/list.js.map +1 -0
- package/dist/cjs/ollama/commands/ps.js +80 -0
- package/dist/cjs/ollama/commands/ps.js.map +1 -0
- package/dist/cjs/ollama/commands/pull.js +198 -0
- package/dist/cjs/ollama/commands/pull.js.map +1 -0
- package/dist/cjs/ollama/commands/run.js +279 -0
- package/dist/cjs/ollama/commands/run.js.map +1 -0
- package/dist/cjs/ollama/commands/show.js +138 -0
- package/dist/cjs/ollama/commands/show.js.map +1 -0
- package/dist/cjs/ollama/index.js +238 -0
- package/dist/cjs/ollama/index.js.map +1 -0
- package/dist/cjs/ollama/types.js +10 -0
- package/dist/cjs/ollama/types.js.map +1 -0
- package/dist/cjs/proxy.js +406 -0
- package/dist/cjs/proxy.js.map +1 -0
- package/dist/cjs/utils/backend-loader.js +112 -0
- package/dist/cjs/utils/backend-loader.js.map +1 -0
- package/dist/cjs/utils/index.js +29 -0
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/cjs/utils/model-translation.js +138 -0
- package/dist/cjs/utils/model-translation.js.map +1 -0
- package/dist/cjs/utils/output-formatter.js +241 -0
- package/dist/cjs/utils/output-formatter.js.map +1 -0
- package/dist/cjs/utils/pipeline-inspector.js +90 -0
- package/dist/cjs/utils/pipeline-inspector.js.map +1 -0
- package/dist/cjs/utils/state-manager.js +114 -0
- package/dist/cjs/utils/state-manager.js.map +1 -0
- package/dist/esm/convert-request.js +331 -0
- package/dist/esm/convert-request.js.map +1 -0
- package/dist/esm/convert-response.js +177 -0
- package/dist/esm/convert-response.js.map +1 -0
- package/dist/esm/converters/request-converters.js +175 -0
- package/dist/esm/converters/request-converters.js.map +1 -0
- package/dist/esm/converters/response-converters.js +191 -0
- package/dist/esm/converters/response-converters.js.map +1 -0
- package/dist/esm/create-backend.js +533 -0
- package/dist/esm/create-backend.js.map +1 -0
- package/dist/esm/index.js +15 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/main.js +149 -0
- package/dist/esm/main.js.map +1 -0
- package/dist/esm/ollama/commands/list.js +67 -0
- package/dist/esm/ollama/commands/list.js.map +1 -0
- package/dist/esm/ollama/commands/ps.js +77 -0
- package/dist/esm/ollama/commands/ps.js.map +1 -0
- package/dist/esm/ollama/commands/pull.js +195 -0
- package/dist/esm/ollama/commands/pull.js.map +1 -0
- package/dist/esm/ollama/commands/run.js +243 -0
- package/dist/esm/ollama/commands/run.js.map +1 -0
- package/dist/esm/ollama/commands/show.js +135 -0
- package/dist/esm/ollama/commands/show.js.map +1 -0
- package/dist/esm/ollama/index.js +235 -0
- package/dist/esm/ollama/index.js.map +1 -0
- package/dist/esm/ollama/types.js +9 -0
- package/dist/esm/ollama/types.js.map +1 -0
- package/dist/esm/proxy.js +403 -0
- package/dist/esm/proxy.js.map +1 -0
- package/dist/esm/utils/backend-loader.js +74 -0
- package/dist/esm/utils/backend-loader.js.map +1 -0
- package/dist/esm/utils/index.js +13 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/esm/utils/model-translation.js +99 -0
- package/dist/esm/utils/model-translation.js.map +1 -0
- package/dist/esm/utils/output-formatter.js +224 -0
- package/dist/esm/utils/output-formatter.js.map +1 -0
- package/dist/esm/utils/pipeline-inspector.js +84 -0
- package/dist/esm/utils/pipeline-inspector.js.map +1 -0
- package/dist/esm/utils/state-manager.js +111 -0
- package/dist/esm/utils/state-manager.js.map +1 -0
- package/dist/types/convert-request.d.ts +15 -0
- package/dist/types/convert-request.d.ts.map +1 -0
- package/dist/types/convert-response.d.ts +16 -0
- package/dist/types/convert-response.d.ts.map +1 -0
- package/dist/types/converters/request-converters.d.ts +139 -0
- package/dist/types/converters/request-converters.d.ts.map +1 -0
- package/dist/types/converters/response-converters.d.ts +134 -0
- package/dist/types/converters/response-converters.d.ts.map +1 -0
- package/dist/types/create-backend.d.ts +20 -0
- package/dist/types/create-backend.d.ts.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/main.d.ts +19 -0
- package/dist/types/main.d.ts.map +1 -0
- package/dist/types/ollama/commands/list.d.ts +32 -0
- package/dist/types/ollama/commands/list.d.ts.map +1 -0
- package/dist/types/ollama/commands/ps.d.ts +27 -0
- package/dist/types/ollama/commands/ps.d.ts.map +1 -0
- package/dist/types/ollama/commands/pull.d.ts +21 -0
- package/dist/types/ollama/commands/pull.d.ts.map +1 -0
- package/dist/types/ollama/commands/run.d.ts +48 -0
- package/dist/types/ollama/commands/run.d.ts.map +1 -0
- package/dist/types/ollama/commands/show.d.ts +36 -0
- package/dist/types/ollama/commands/show.d.ts.map +1 -0
- package/dist/types/ollama/index.d.ts +12 -0
- package/dist/types/ollama/index.d.ts.map +1 -0
- package/dist/types/ollama/types.d.ts +58 -0
- package/dist/types/ollama/types.d.ts.map +1 -0
- package/dist/types/proxy.d.ts +16 -0
- package/dist/types/proxy.d.ts.map +1 -0
- package/dist/types/utils/backend-loader.d.ts +55 -0
- package/dist/types/utils/backend-loader.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +13 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/dist/types/utils/model-translation.d.ts +64 -0
- package/dist/types/utils/model-translation.d.ts.map +1 -0
- package/dist/types/utils/output-formatter.d.ts +113 -0
- package/dist/types/utils/output-formatter.d.ts.map +1 -0
- package/dist/types/utils/pipeline-inspector.d.ts +50 -0
- package/dist/types/utils/pipeline-inspector.d.ts.map +1 -0
- package/dist/types/utils/state-manager.d.ts +91 -0
- package/dist/types/utils/state-manager.d.ts.map +1 -0
- package/package.json +75 -0
- package/readme.md +32 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AI.Matey Proxy Server
|
|
4
|
+
*
|
|
5
|
+
* HTTP proxy server that accepts provider-format requests (e.g., OpenAI)
|
|
6
|
+
* and routes them through any ai-matey backend adapter.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ai-matey proxy --backend ./backend.mjs --port 3000 --format openai
|
|
10
|
+
*
|
|
11
|
+
* This allows you to use ANY backend as a drop-in replacement for OpenAI/Anthropic/etc!
|
|
12
|
+
*
|
|
13
|
+
* @module cli/proxy
|
|
14
|
+
*/
|
|
15
|
+
import { createServer } from 'node:http';
|
|
16
|
+
import { loadBackend } from './utils/backend-loader.js';
|
|
17
|
+
import { success, error as errorLog, info } from './utils/output-formatter.js';
|
|
18
|
+
import { toOpenAI as responseToOpenAI, toAnthropic as responseToAnthropic, toGemini as responseToGemini, toOllama as responseToOllama, toMistral as responseToMistral, } from './converters/response-converters.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Request Parsing
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Read request body as JSON.
|
|
24
|
+
*/
|
|
25
|
+
async function readBody(req) {
|
|
26
|
+
const chunks = [];
|
|
27
|
+
for await (const chunk of req) {
|
|
28
|
+
chunks.push(chunk);
|
|
29
|
+
}
|
|
30
|
+
const body = Buffer.concat(chunks).toString('utf-8');
|
|
31
|
+
return JSON.parse(body);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Convert provider request to IR.
|
|
35
|
+
*/
|
|
36
|
+
function providerRequestToIR(data, format) {
|
|
37
|
+
switch (format) {
|
|
38
|
+
case 'openai':
|
|
39
|
+
return {
|
|
40
|
+
messages: data.messages || [],
|
|
41
|
+
parameters: {
|
|
42
|
+
model: data.model,
|
|
43
|
+
temperature: data.temperature,
|
|
44
|
+
maxTokens: data.max_tokens,
|
|
45
|
+
topP: data.top_p,
|
|
46
|
+
frequencyPenalty: data.frequency_penalty,
|
|
47
|
+
presencePenalty: data.presence_penalty,
|
|
48
|
+
stopSequences: Array.isArray(data.stop) ? data.stop : data.stop ? [data.stop] : undefined,
|
|
49
|
+
seed: data.seed,
|
|
50
|
+
user: data.user,
|
|
51
|
+
},
|
|
52
|
+
stream: data.stream,
|
|
53
|
+
metadata: {
|
|
54
|
+
requestId: crypto.randomUUID(),
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
provenance: { frontend: 'openai' },
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
case 'anthropic':
|
|
60
|
+
// Add system message if present
|
|
61
|
+
const messages = data.messages || [];
|
|
62
|
+
if (data.system) {
|
|
63
|
+
messages.unshift({ role: 'system', content: data.system });
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
messages,
|
|
67
|
+
parameters: {
|
|
68
|
+
model: data.model,
|
|
69
|
+
temperature: data.temperature,
|
|
70
|
+
maxTokens: data.max_tokens,
|
|
71
|
+
topP: data.top_p,
|
|
72
|
+
topK: data.top_k,
|
|
73
|
+
stopSequences: data.stop_sequences,
|
|
74
|
+
},
|
|
75
|
+
stream: data.stream,
|
|
76
|
+
metadata: {
|
|
77
|
+
requestId: crypto.randomUUID(),
|
|
78
|
+
timestamp: Date.now(),
|
|
79
|
+
provenance: { frontend: 'anthropic' },
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
case 'gemini':
|
|
83
|
+
const geminiMessages = (data.contents || []).map((content) => ({
|
|
84
|
+
role: content.role === 'model' ? 'assistant' : content.role,
|
|
85
|
+
content: content.parts?.map((p) => p.text).join('') || '',
|
|
86
|
+
}));
|
|
87
|
+
return {
|
|
88
|
+
messages: geminiMessages,
|
|
89
|
+
parameters: {
|
|
90
|
+
model: data.model,
|
|
91
|
+
temperature: data.generationConfig?.temperature,
|
|
92
|
+
maxTokens: data.generationConfig?.maxOutputTokens,
|
|
93
|
+
topP: data.generationConfig?.topP,
|
|
94
|
+
topK: data.generationConfig?.topK,
|
|
95
|
+
stopSequences: data.generationConfig?.stopSequences,
|
|
96
|
+
},
|
|
97
|
+
metadata: {
|
|
98
|
+
requestId: crypto.randomUUID(),
|
|
99
|
+
timestamp: Date.now(),
|
|
100
|
+
provenance: { frontend: 'gemini' },
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
case 'ollama':
|
|
104
|
+
return {
|
|
105
|
+
messages: data.messages || [],
|
|
106
|
+
parameters: {
|
|
107
|
+
model: data.model,
|
|
108
|
+
temperature: data.options?.temperature,
|
|
109
|
+
topP: data.options?.top_p,
|
|
110
|
+
topK: data.options?.top_k,
|
|
111
|
+
},
|
|
112
|
+
stream: data.stream,
|
|
113
|
+
metadata: {
|
|
114
|
+
requestId: crypto.randomUUID(),
|
|
115
|
+
timestamp: Date.now(),
|
|
116
|
+
provenance: { frontend: 'ollama' },
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
case 'mistral':
|
|
120
|
+
return {
|
|
121
|
+
messages: data.messages || [],
|
|
122
|
+
parameters: {
|
|
123
|
+
model: data.model,
|
|
124
|
+
temperature: data.temperature,
|
|
125
|
+
maxTokens: data.max_tokens,
|
|
126
|
+
topP: data.top_p,
|
|
127
|
+
},
|
|
128
|
+
stream: data.stream,
|
|
129
|
+
metadata: {
|
|
130
|
+
requestId: crypto.randomUUID(),
|
|
131
|
+
timestamp: Date.now(),
|
|
132
|
+
provenance: { frontend: 'mistral' },
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
default:
|
|
136
|
+
throw new Error(`Unsupported format: ${format}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// Request Handler
|
|
141
|
+
// ============================================================================
|
|
142
|
+
/**
|
|
143
|
+
* Create request handler for the proxy server.
|
|
144
|
+
*/
|
|
145
|
+
function createHandler(backend, format, verbose) {
|
|
146
|
+
return async (req, res) => {
|
|
147
|
+
// CORS headers
|
|
148
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
149
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
150
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
151
|
+
// Handle OPTIONS
|
|
152
|
+
if (req.method === 'OPTIONS') {
|
|
153
|
+
res.writeHead(200);
|
|
154
|
+
res.end();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Only handle POST
|
|
158
|
+
if (req.method !== 'POST') {
|
|
159
|
+
res.writeHead(405, { 'Content-Type': 'application/json' });
|
|
160
|
+
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
// Read and parse request body
|
|
165
|
+
const requestBody = await readBody(req);
|
|
166
|
+
if (verbose) {
|
|
167
|
+
console.log(`[${new Date().toISOString()}] Request:`, JSON.stringify(requestBody, null, 2));
|
|
168
|
+
}
|
|
169
|
+
// Convert to IR
|
|
170
|
+
const irRequest = providerRequestToIR(requestBody, format);
|
|
171
|
+
// Check if streaming
|
|
172
|
+
if (irRequest.stream) {
|
|
173
|
+
// Handle streaming
|
|
174
|
+
res.writeHead(200, {
|
|
175
|
+
'Content-Type': 'text/event-stream',
|
|
176
|
+
'Cache-Control': 'no-cache',
|
|
177
|
+
Connection: 'keep-alive',
|
|
178
|
+
});
|
|
179
|
+
// Execute streaming request
|
|
180
|
+
const stream = backend.executeStream(irRequest);
|
|
181
|
+
for await (const chunk of stream) {
|
|
182
|
+
if (chunk.type === 'content') {
|
|
183
|
+
// Format as SSE
|
|
184
|
+
const data = {
|
|
185
|
+
id: chunk.sequence.toString(),
|
|
186
|
+
object: 'chat.completion.chunk',
|
|
187
|
+
created: Math.floor(Date.now() / 1000),
|
|
188
|
+
model: irRequest.parameters?.model || 'unknown',
|
|
189
|
+
choices: [
|
|
190
|
+
{
|
|
191
|
+
index: 0,
|
|
192
|
+
delta: { content: chunk.delta },
|
|
193
|
+
finish_reason: null,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
198
|
+
}
|
|
199
|
+
else if (chunk.type === 'done') {
|
|
200
|
+
// Send final chunk
|
|
201
|
+
const data = {
|
|
202
|
+
id: chunk.sequence.toString(),
|
|
203
|
+
object: 'chat.completion.chunk',
|
|
204
|
+
created: Math.floor(Date.now() / 1000),
|
|
205
|
+
model: irRequest.parameters?.model || 'unknown',
|
|
206
|
+
choices: [
|
|
207
|
+
{
|
|
208
|
+
index: 0,
|
|
209
|
+
delta: {},
|
|
210
|
+
finish_reason: chunk.finishReason || 'stop',
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
};
|
|
214
|
+
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
|
215
|
+
res.write('data: [DONE]\n\n');
|
|
216
|
+
res.end();
|
|
217
|
+
}
|
|
218
|
+
else if (chunk.type === 'error') {
|
|
219
|
+
res.write(`data: ${JSON.stringify({ error: chunk.error })}\n\n`);
|
|
220
|
+
res.end();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
// Handle non-streaming
|
|
226
|
+
const irResponse = await backend.execute(irRequest);
|
|
227
|
+
// Convert response back to provider format
|
|
228
|
+
let providerResponse;
|
|
229
|
+
switch (format) {
|
|
230
|
+
case 'openai':
|
|
231
|
+
providerResponse = await responseToOpenAI(irResponse);
|
|
232
|
+
break;
|
|
233
|
+
case 'anthropic':
|
|
234
|
+
providerResponse = await responseToAnthropic(irResponse);
|
|
235
|
+
break;
|
|
236
|
+
case 'gemini':
|
|
237
|
+
providerResponse = await responseToGemini(irResponse);
|
|
238
|
+
break;
|
|
239
|
+
case 'ollama':
|
|
240
|
+
providerResponse = await responseToOllama(irResponse);
|
|
241
|
+
break;
|
|
242
|
+
case 'mistral':
|
|
243
|
+
providerResponse = await responseToMistral(irResponse);
|
|
244
|
+
break;
|
|
245
|
+
default:
|
|
246
|
+
throw new Error(`Unsupported format: ${format}`);
|
|
247
|
+
}
|
|
248
|
+
if (verbose) {
|
|
249
|
+
console.log(`[${new Date().toISOString()}] Response:`, JSON.stringify(providerResponse, null, 2));
|
|
250
|
+
}
|
|
251
|
+
// Send response
|
|
252
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
253
|
+
res.end(JSON.stringify(providerResponse));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
console.error('Request error:', err);
|
|
258
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
259
|
+
res.end(JSON.stringify({
|
|
260
|
+
error: {
|
|
261
|
+
message: err instanceof Error ? err.message : String(err),
|
|
262
|
+
type: 'internal_error',
|
|
263
|
+
},
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
// ============================================================================
|
|
269
|
+
// CLI
|
|
270
|
+
// ============================================================================
|
|
271
|
+
function showHelp() {
|
|
272
|
+
console.log(`
|
|
273
|
+
AI.Matey Proxy Server
|
|
274
|
+
|
|
275
|
+
Start an HTTP proxy server that accepts provider-format requests
|
|
276
|
+
and routes them through any ai-matey backend adapter.
|
|
277
|
+
|
|
278
|
+
Usage:
|
|
279
|
+
ai-matey proxy --backend <path> [options]
|
|
280
|
+
|
|
281
|
+
Options:
|
|
282
|
+
--backend <path> Backend module to load (required)
|
|
283
|
+
--port <number> Port to listen on (default: 3000)
|
|
284
|
+
--host <host> Host to bind to (default: localhost)
|
|
285
|
+
--format <format> Provider format to emulate (default: openai)
|
|
286
|
+
Supported: openai, anthropic, gemini, ollama, mistral
|
|
287
|
+
--verbose, -v Verbose logging
|
|
288
|
+
--help, -h Show this help
|
|
289
|
+
|
|
290
|
+
Examples:
|
|
291
|
+
# Start OpenAI-compatible proxy on port 3000
|
|
292
|
+
ai-matey proxy --backend ./groq-backend.mjs --port 3000
|
|
293
|
+
|
|
294
|
+
# Start Anthropic-compatible proxy
|
|
295
|
+
ai-matey proxy --backend ./backend.mjs --format anthropic --port 3001
|
|
296
|
+
|
|
297
|
+
# Use with OpenAI client library
|
|
298
|
+
ai-matey proxy --backend ./backend.mjs --port 3000
|
|
299
|
+
# Then in your code:
|
|
300
|
+
# const openai = new OpenAI({ baseURL: 'http://localhost:3000' })
|
|
301
|
+
|
|
302
|
+
How It Works:
|
|
303
|
+
1. Accepts HTTP requests in the specified provider format (e.g., OpenAI)
|
|
304
|
+
2. Converts the request to Universal IR format
|
|
305
|
+
3. Routes through your backend adapter
|
|
306
|
+
4. Converts the response back to the provider format
|
|
307
|
+
5. Returns to client
|
|
308
|
+
|
|
309
|
+
This allows you to use ANY backend as a drop-in replacement for OpenAI,
|
|
310
|
+
Anthropic, or other providers!
|
|
311
|
+
`);
|
|
312
|
+
}
|
|
313
|
+
function parseArgs(args) {
|
|
314
|
+
const options = {
|
|
315
|
+
backend: '',
|
|
316
|
+
port: 3000,
|
|
317
|
+
host: 'localhost',
|
|
318
|
+
format: 'openai',
|
|
319
|
+
verbose: false,
|
|
320
|
+
};
|
|
321
|
+
for (let i = 0; i < args.length; i++) {
|
|
322
|
+
const arg = args[i];
|
|
323
|
+
switch (arg) {
|
|
324
|
+
case '--backend':
|
|
325
|
+
options.backend = args[++i] || '';
|
|
326
|
+
break;
|
|
327
|
+
case '--port':
|
|
328
|
+
options.port = parseInt(args[++i] || '3000', 10);
|
|
329
|
+
break;
|
|
330
|
+
case '--host':
|
|
331
|
+
options.host = args[++i] || 'localhost';
|
|
332
|
+
break;
|
|
333
|
+
case '--format':
|
|
334
|
+
options.format = args[++i] || 'openai';
|
|
335
|
+
break;
|
|
336
|
+
case '--verbose':
|
|
337
|
+
case '-v':
|
|
338
|
+
options.verbose = true;
|
|
339
|
+
break;
|
|
340
|
+
case '--help':
|
|
341
|
+
case '-h':
|
|
342
|
+
options.help = true;
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return options;
|
|
347
|
+
}
|
|
348
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
349
|
+
const options = parseArgs(argv);
|
|
350
|
+
if (options.help) {
|
|
351
|
+
showHelp();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (!options.backend) {
|
|
355
|
+
errorLog('Missing required option: --backend <path>');
|
|
356
|
+
console.log('\nRun with --help for usage information');
|
|
357
|
+
process.exit(1);
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
// Load backend
|
|
361
|
+
info(`Loading backend from ${options.backend}...`);
|
|
362
|
+
const backend = await loadBackend({ path: options.backend });
|
|
363
|
+
success(`✓ Backend loaded: ${backend.metadata.name} (${backend.metadata.provider})`);
|
|
364
|
+
// Create server
|
|
365
|
+
const handler = createHandler(backend, options.format || 'openai', options.verbose || false);
|
|
366
|
+
const server = createServer(handler);
|
|
367
|
+
// Start listening
|
|
368
|
+
server.listen(options.port, options.host, () => {
|
|
369
|
+
console.log('');
|
|
370
|
+
success(`🚀 Proxy server started!`);
|
|
371
|
+
console.log('');
|
|
372
|
+
console.log(` Format: ${options.format}`);
|
|
373
|
+
console.log(` URL: http://${options.host}:${options.port}`);
|
|
374
|
+
console.log(` Backend: ${backend.metadata.name}`);
|
|
375
|
+
console.log('');
|
|
376
|
+
console.log(' Press Ctrl+C to stop');
|
|
377
|
+
console.log('');
|
|
378
|
+
if (options.format === 'openai') {
|
|
379
|
+
console.log(' Example usage with OpenAI client:');
|
|
380
|
+
console.log(' ┌────────────────────────────────────────────┐');
|
|
381
|
+
console.log(` │ const openai = new OpenAI({ │`);
|
|
382
|
+
console.log(` │ baseURL: 'http://${options.host}:${options.port}', │`);
|
|
383
|
+
console.log(` │ apiKey: 'any-value' │`);
|
|
384
|
+
console.log(` │ }) │`);
|
|
385
|
+
console.log(' └────────────────────────────────────────────┘');
|
|
386
|
+
console.log('');
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
// Handle shutdown
|
|
390
|
+
process.on('SIGINT', () => {
|
|
391
|
+
console.log('\n\nShutting down...');
|
|
392
|
+
server.close(() => {
|
|
393
|
+
console.log('Server closed');
|
|
394
|
+
process.exit(0);
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
catch (err) {
|
|
399
|
+
errorLog(err instanceof Error ? err.message : String(err));
|
|
400
|
+
process.exit(1);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
//# sourceMappingURL=proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend Loader Utility
|
|
3
|
+
*
|
|
4
|
+
* Dynamically loads backend modules from file paths.
|
|
5
|
+
* Node.js only - uses dynamic import.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/utils/backend-loader
|
|
8
|
+
*/
|
|
9
|
+
import { resolve } from 'node:path';
|
|
10
|
+
/**
|
|
11
|
+
* Load a backend from a module file.
|
|
12
|
+
*
|
|
13
|
+
* @param options - Load options
|
|
14
|
+
* @returns Loaded backend adapter
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const backend = await loadBackend({ path: './my-backend.mjs' });
|
|
19
|
+
* const response = await backend.execute(request);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export async function loadBackend(options) {
|
|
23
|
+
const { path, cwd = process.cwd() } = options;
|
|
24
|
+
try {
|
|
25
|
+
// Resolve path
|
|
26
|
+
const resolvedPath = path.startsWith('/') ? path : resolve(cwd, path);
|
|
27
|
+
// Convert to file URL for import
|
|
28
|
+
const fileUrl = `file://${resolvedPath}`;
|
|
29
|
+
// Dynamic import
|
|
30
|
+
const module = (await import(fileUrl));
|
|
31
|
+
if (!module.default) {
|
|
32
|
+
throw new Error(`Backend module ${path} does not have a default export`);
|
|
33
|
+
}
|
|
34
|
+
const backend = module.default;
|
|
35
|
+
// Validate backend
|
|
36
|
+
if (typeof backend.execute !== 'function') {
|
|
37
|
+
throw new Error(`Backend module ${path} does not implement BackendAdapter interface (missing execute method)`);
|
|
38
|
+
}
|
|
39
|
+
return backend;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof Error) {
|
|
43
|
+
// Re-throw with better error message
|
|
44
|
+
throw new Error(`Failed to load backend from ${path}: ${error.message}`, { cause: error });
|
|
45
|
+
}
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if a backend is a model runner (has lifecycle methods).
|
|
51
|
+
*
|
|
52
|
+
* @param backend - Backend to check
|
|
53
|
+
* @returns True if backend is a model runner
|
|
54
|
+
*/
|
|
55
|
+
export function isModelRunner(backend) {
|
|
56
|
+
return (typeof backend.start === 'function' &&
|
|
57
|
+
typeof backend.stop === 'function' &&
|
|
58
|
+
typeof backend.getStats === 'function');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get backend capabilities.
|
|
62
|
+
*
|
|
63
|
+
* @param backend - Backend to inspect
|
|
64
|
+
* @returns Capability flags
|
|
65
|
+
*/
|
|
66
|
+
export function getBackendCapabilities(backend) {
|
|
67
|
+
return {
|
|
68
|
+
hasLifecycle: isModelRunner(backend),
|
|
69
|
+
hasModelList: typeof backend.listModels === 'function',
|
|
70
|
+
hasStats: typeof backend.getStats === 'function',
|
|
71
|
+
metadata: backend.metadata,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=backend-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-loader.js","sourceRoot":"","sources":["../../../src/utils/backend-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA2B;IAC3D,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAE9C,IAAI,CAAC;QACH,eAAe;QACf,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAEtE,iCAAiC;QACjC,MAAM,OAAO,GAAG,UAAU,YAAY,EAAE,CAAC;QAEzC,iBAAiB;QACjB,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAkB,CAAC;QAExD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,iCAAiC,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAE/B,mBAAmB;QACnB,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,kBAAkB,IAAI,uEAAuE,CAC9F,CAAC;QACJ,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,qCAAqC;YACrC,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAuB;IACnD,OAAO,CACL,OAAQ,OAAe,CAAC,KAAK,KAAK,UAAU;QAC5C,OAAQ,OAAe,CAAC,IAAI,KAAK,UAAU;QAC3C,OAAQ,OAAe,CAAC,QAAQ,KAAK,UAAU,CAChD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAuB;IAC5D,OAAO;QACL,YAAY,EAAE,aAAa,CAAC,OAAO,CAAC;QACpC,YAAY,EAAE,OAAQ,OAAe,CAAC,UAAU,KAAK,UAAU;QAC/D,QAAQ,EAAE,OAAQ,OAAe,CAAC,QAAQ,KAAK,UAAU;QACzD,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Utilities
|
|
3
|
+
*
|
|
4
|
+
* Common utilities for CLI implementation.
|
|
5
|
+
* Node.js only - not browser-compatible.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/utils
|
|
8
|
+
*/
|
|
9
|
+
export * from './backend-loader.js';
|
|
10
|
+
export * from './model-translation.js';
|
|
11
|
+
export * from './output-formatter.js';
|
|
12
|
+
export * from './state-manager.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model Translation Utility
|
|
3
|
+
*
|
|
4
|
+
* Translates model names between different providers.
|
|
5
|
+
* Supports backend.modelMapping property or external mapping files.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/utils/model-translation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Translate a model name using mapping or backend default.
|
|
11
|
+
*
|
|
12
|
+
* @param modelName - Original model name
|
|
13
|
+
* @param options - Translation options
|
|
14
|
+
* @returns Translated model name or original if no mapping
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const backend = new OpenAIBackend({ defaultModel: 'gpt-4o' });
|
|
19
|
+
* backend.modelMapping = { 'llama3.1': 'gpt-4o' };
|
|
20
|
+
*
|
|
21
|
+
* const translated = translateModel('llama3.1', { backend });
|
|
22
|
+
* // → 'gpt-4o'
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function translateModel(modelName, options) {
|
|
26
|
+
const { backend, mapping, useBackendDefault = true } = options;
|
|
27
|
+
// Check external mapping first
|
|
28
|
+
if (mapping && mapping[modelName]) {
|
|
29
|
+
return mapping[modelName];
|
|
30
|
+
}
|
|
31
|
+
// Check backend.modelMapping
|
|
32
|
+
const backendMapping = backend.modelMapping;
|
|
33
|
+
if (backendMapping && backendMapping[modelName]) {
|
|
34
|
+
return backendMapping[modelName];
|
|
35
|
+
}
|
|
36
|
+
// Try backend default model
|
|
37
|
+
if (useBackendDefault) {
|
|
38
|
+
const defaultModel = backend.config?.defaultModel;
|
|
39
|
+
if (defaultModel) {
|
|
40
|
+
return defaultModel;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// No translation - return original
|
|
44
|
+
return modelName;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Load model mapping from JSON file.
|
|
48
|
+
*
|
|
49
|
+
* @param path - Path to JSON file
|
|
50
|
+
* @returns Model mapping
|
|
51
|
+
*/
|
|
52
|
+
export async function loadModelMapping(path) {
|
|
53
|
+
const { readFile } = await import('node:fs/promises');
|
|
54
|
+
const { resolve } = await import('node:path');
|
|
55
|
+
try {
|
|
56
|
+
const resolvedPath = resolve(process.cwd(), path);
|
|
57
|
+
const content = await readFile(resolvedPath, 'utf-8');
|
|
58
|
+
const mapping = JSON.parse(content);
|
|
59
|
+
if (typeof mapping !== 'object' || mapping === null) {
|
|
60
|
+
throw new Error('Model mapping must be a JSON object');
|
|
61
|
+
}
|
|
62
|
+
return mapping;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw new Error(`Failed to load model mapping from ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get reverse mapping (backend model → original model name).
|
|
70
|
+
*
|
|
71
|
+
* @param mapping - Forward mapping
|
|
72
|
+
* @returns Reverse mapping
|
|
73
|
+
*/
|
|
74
|
+
export function reverseMapping(mapping) {
|
|
75
|
+
const reversed = {};
|
|
76
|
+
for (const [key, value] of Object.entries(mapping)) {
|
|
77
|
+
reversed[value] = key;
|
|
78
|
+
}
|
|
79
|
+
return reversed;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check if model name needs translation.
|
|
83
|
+
*
|
|
84
|
+
* @param modelName - Model name to check
|
|
85
|
+
* @param options - Translation options
|
|
86
|
+
* @returns True if translation is available
|
|
87
|
+
*/
|
|
88
|
+
export function hasTranslation(modelName, options) {
|
|
89
|
+
const { backend, mapping } = options;
|
|
90
|
+
if (mapping && mapping[modelName]) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
const backendMapping = backend.modelMapping;
|
|
94
|
+
if (backendMapping && backendMapping[modelName]) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=model-translation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-translation.js","sourceRoot":"","sources":["../../../src/utils/model-translation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,OAAgC;IAChF,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAE/D,+BAA+B;IAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC;IAED,6BAA6B;IAC7B,MAAM,cAAc,GAAI,OAAe,CAAC,YAAwC,CAAC;IACjF,IAAI,cAAc,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QAChD,OAAO,cAAc,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED,4BAA4B;IAC5B,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,YAAY,GAAI,OAAe,CAAC,MAAM,EAAE,YAAY,CAAC;QAC3D,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,YAAY,CAAC;QACtB,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY;IACjD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACtD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IAE9C,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEpC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,OAAuB,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,qCAAqC,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACvG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAqB;IAClD,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;IACxB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAiB,EACjB,OAA2D;IAE3D,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAErC,IAAI,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,cAAc,GAAI,OAAe,CAAC,YAAwC,CAAC;IACjF,IAAI,cAAc,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|