universal-llm-client 3.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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +414 -0
  3. package/dist/ai-model.d.ts +53 -0
  4. package/dist/ai-model.d.ts.map +1 -0
  5. package/dist/ai-model.js +159 -0
  6. package/dist/ai-model.js.map +1 -0
  7. package/dist/auditor.d.ts +78 -0
  8. package/dist/auditor.d.ts.map +1 -0
  9. package/dist/auditor.js +104 -0
  10. package/dist/auditor.js.map +1 -0
  11. package/dist/client.d.ts +75 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/client.js +240 -0
  14. package/dist/client.js.map +1 -0
  15. package/dist/http.d.ts +47 -0
  16. package/dist/http.d.ts.map +1 -0
  17. package/dist/http.js +186 -0
  18. package/dist/http.js.map +1 -0
  19. package/dist/index.d.ts +16 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +41 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/interfaces.d.ts +324 -0
  24. package/dist/interfaces.d.ts.map +1 -0
  25. package/dist/interfaces.js +63 -0
  26. package/dist/interfaces.js.map +1 -0
  27. package/dist/mcp.d.ts +85 -0
  28. package/dist/mcp.d.ts.map +1 -0
  29. package/dist/mcp.js +255 -0
  30. package/dist/mcp.js.map +1 -0
  31. package/dist/providers/google.d.ts +33 -0
  32. package/dist/providers/google.d.ts.map +1 -0
  33. package/dist/providers/google.js +426 -0
  34. package/dist/providers/google.js.map +1 -0
  35. package/dist/providers/index.d.ts +7 -0
  36. package/dist/providers/index.d.ts.map +1 -0
  37. package/dist/providers/index.js +7 -0
  38. package/dist/providers/index.js.map +1 -0
  39. package/dist/providers/ollama.d.ts +26 -0
  40. package/dist/providers/ollama.d.ts.map +1 -0
  41. package/dist/providers/ollama.js +304 -0
  42. package/dist/providers/ollama.js.map +1 -0
  43. package/dist/providers/openai.d.ts +20 -0
  44. package/dist/providers/openai.d.ts.map +1 -0
  45. package/dist/providers/openai.js +251 -0
  46. package/dist/providers/openai.js.map +1 -0
  47. package/dist/router.d.ts +87 -0
  48. package/dist/router.d.ts.map +1 -0
  49. package/dist/router.js +260 -0
  50. package/dist/router.js.map +1 -0
  51. package/dist/stream-decoder.d.ts +112 -0
  52. package/dist/stream-decoder.d.ts.map +1 -0
  53. package/dist/stream-decoder.js +238 -0
  54. package/dist/stream-decoder.js.map +1 -0
  55. package/dist/tools.d.ts +78 -0
  56. package/dist/tools.d.ts.map +1 -0
  57. package/dist/tools.js +207 -0
  58. package/dist/tools.js.map +1 -0
  59. package/package.json +91 -0
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Universal LLM Client v3 — Ollama Provider
3
+ *
4
+ * Implements BaseLLMClient for Ollama's native API.
5
+ * Supports chat, streaming (NDJSON), embeddings, model discovery,
6
+ * and context length detection via /api/show.
7
+ */
8
+ import { BaseLLMClient } from '../client.js';
9
+ import { httpRequest, httpStream, parseNDJSON, buildHeaders } from '../http.js';
10
+ import { StandardChatDecoder } from '../stream-decoder.js';
11
+ export class OllamaClient extends BaseLLMClient {
12
+ constructor(options, auditor) {
13
+ super({
14
+ ...options,
15
+ url: (options.url || 'http://localhost:11434').replace(/\/+$/, ''),
16
+ }, auditor);
17
+ }
18
+ // ========================================================================
19
+ // Chat
20
+ // ========================================================================
21
+ async chat(messages, options) {
22
+ const url = `${this.options.url}/api/chat`;
23
+ const tools = options?.tools ?? (Object.keys(this.toolRegistry).length > 0 ? this.getToolDefinitions() : undefined);
24
+ const body = {
25
+ model: this.options.model,
26
+ messages: this.convertMessages(messages),
27
+ stream: false,
28
+ options: this.buildOllamaOptions(options),
29
+ };
30
+ if (tools?.length) {
31
+ body['tools'] = this.convertToolsToOllama(tools);
32
+ }
33
+ if (this.options.thinking) {
34
+ body['think'] = true;
35
+ }
36
+ const start = Date.now();
37
+ this.auditor.record({
38
+ timestamp: start,
39
+ type: 'request',
40
+ provider: 'ollama',
41
+ model: this.options.model,
42
+ });
43
+ const response = await httpRequest(url, {
44
+ method: 'POST',
45
+ headers: buildHeaders(this.options),
46
+ body,
47
+ timeout: this.options.timeout ?? 30000,
48
+ });
49
+ const data = response.data;
50
+ const usage = (data.prompt_eval_count || data.eval_count)
51
+ ? {
52
+ inputTokens: data.prompt_eval_count ?? 0,
53
+ outputTokens: data.eval_count ?? 0,
54
+ totalTokens: (data.prompt_eval_count ?? 0) + (data.eval_count ?? 0),
55
+ }
56
+ : undefined;
57
+ // Normalize tool call IDs (Ollama sometimes omits them)
58
+ const toolCalls = data.message.tool_calls?.map(tc => ({
59
+ ...tc,
60
+ id: tc.id || this.generateToolCallId(),
61
+ function: {
62
+ ...tc.function,
63
+ arguments: typeof tc.function.arguments === 'string'
64
+ ? tc.function.arguments
65
+ : JSON.stringify(tc.function.arguments),
66
+ },
67
+ }));
68
+ const result = {
69
+ message: {
70
+ role: 'assistant',
71
+ content: data.message.content || data.message.thinking || '',
72
+ tool_calls: toolCalls,
73
+ },
74
+ reasoning: data.message.content ? data.message.thinking : undefined,
75
+ usage,
76
+ provider: 'ollama',
77
+ };
78
+ this.auditor.record({
79
+ timestamp: Date.now(),
80
+ type: 'response',
81
+ provider: 'ollama',
82
+ model: this.options.model,
83
+ duration: Date.now() - start,
84
+ usage,
85
+ });
86
+ return result;
87
+ }
88
+ // ========================================================================
89
+ // Streaming
90
+ // ========================================================================
91
+ async *chatStream(messages, options) {
92
+ const url = `${this.options.url}/api/chat`;
93
+ const tools = options?.tools ?? (Object.keys(this.toolRegistry).length > 0 ? this.getToolDefinitions() : undefined);
94
+ const body = {
95
+ model: this.options.model,
96
+ messages: this.convertMessages(messages),
97
+ stream: true,
98
+ options: this.buildOllamaOptions(options),
99
+ };
100
+ if (tools?.length) {
101
+ body['tools'] = this.convertToolsToOllama(tools);
102
+ }
103
+ if (this.options.thinking) {
104
+ body['think'] = true;
105
+ }
106
+ const start = Date.now();
107
+ this.auditor.record({
108
+ timestamp: start,
109
+ type: 'stream_start',
110
+ provider: 'ollama',
111
+ model: this.options.model,
112
+ });
113
+ const decoder = new StandardChatDecoder(() => { });
114
+ let lastResponse;
115
+ const stream = httpStream(url, {
116
+ method: 'POST',
117
+ headers: buildHeaders(this.options),
118
+ body,
119
+ timeout: this.options.timeout ?? 120000,
120
+ });
121
+ for await (const chunk of parseNDJSON(stream)) {
122
+ lastResponse = chunk;
123
+ if (chunk.message?.thinking) {
124
+ decoder.pushReasoning(chunk.message.thinking);
125
+ yield { type: 'thinking', content: chunk.message.thinking };
126
+ }
127
+ if (chunk.message?.content) {
128
+ decoder.push(chunk.message.content);
129
+ yield { type: 'text', content: chunk.message.content };
130
+ }
131
+ if (chunk.message?.tool_calls?.length) {
132
+ const normalized = chunk.message.tool_calls.map(tc => ({
133
+ ...tc,
134
+ id: tc.id || this.generateToolCallId(),
135
+ function: {
136
+ ...tc.function,
137
+ arguments: typeof tc.function.arguments === 'string'
138
+ ? tc.function.arguments
139
+ : JSON.stringify(tc.function.arguments),
140
+ },
141
+ }));
142
+ yield { type: 'tool_call', calls: normalized };
143
+ }
144
+ }
145
+ decoder.flush();
146
+ const usage = lastResponse?.prompt_eval_count
147
+ ? {
148
+ inputTokens: lastResponse.prompt_eval_count ?? 0,
149
+ outputTokens: lastResponse.eval_count ?? 0,
150
+ totalTokens: (lastResponse.prompt_eval_count ?? 0) + (lastResponse.eval_count ?? 0),
151
+ }
152
+ : undefined;
153
+ this.auditor.record({
154
+ timestamp: Date.now(),
155
+ type: 'stream_end',
156
+ provider: 'ollama',
157
+ model: this.options.model,
158
+ duration: Date.now() - start,
159
+ usage,
160
+ });
161
+ return {
162
+ message: {
163
+ role: 'assistant',
164
+ content: decoder.getCleanContent(),
165
+ },
166
+ reasoning: decoder.getReasoning(),
167
+ usage,
168
+ provider: 'ollama',
169
+ };
170
+ }
171
+ // ========================================================================
172
+ // Embeddings
173
+ // ========================================================================
174
+ async embed(text) {
175
+ const url = `${this.options.url}/api/embed`;
176
+ const response = await httpRequest(url, {
177
+ method: 'POST',
178
+ headers: buildHeaders(this.options),
179
+ body: { model: this.options.model, input: text },
180
+ timeout: this.options.timeout ?? 30000,
181
+ });
182
+ return response.data.embeddings[0] ?? [];
183
+ }
184
+ async embedArray(texts) {
185
+ const url = `${this.options.url}/api/embed`;
186
+ const response = await httpRequest(url, {
187
+ method: 'POST',
188
+ headers: buildHeaders(this.options),
189
+ body: { model: this.options.model, input: texts },
190
+ timeout: this.options.timeout ?? 30000,
191
+ });
192
+ return response.data.embeddings;
193
+ }
194
+ // ========================================================================
195
+ // Model Discovery
196
+ // ========================================================================
197
+ async getModels() {
198
+ const url = `${this.options.url}/api/tags`;
199
+ const response = await httpRequest(url, {
200
+ timeout: 5000,
201
+ });
202
+ return response.data.models.map(m => m.name);
203
+ }
204
+ async getModelInfo(modelName) {
205
+ const url = `${this.options.url}/api/show`;
206
+ try {
207
+ const response = await httpRequest(url, {
208
+ method: 'POST',
209
+ body: { name: modelName ?? this.options.model },
210
+ timeout: 5000,
211
+ });
212
+ const modelInfo = response.data['model_info'];
213
+ if (!modelInfo)
214
+ return { contextLength: 8192 };
215
+ // Extract architecture-specific context length
216
+ const arch = modelInfo['general.architecture'];
217
+ let contextLength = 8192;
218
+ if (arch) {
219
+ const ctxKey = `${arch}.context_length`;
220
+ const ctxValue = modelInfo[ctxKey];
221
+ if (ctxValue)
222
+ contextLength = ctxValue;
223
+ }
224
+ const paramCountRaw = modelInfo['general.parameter_count'];
225
+ return {
226
+ model: modelName ?? this.options.model,
227
+ contextLength,
228
+ architecture: arch,
229
+ parameterCount: paramCountRaw,
230
+ };
231
+ }
232
+ catch {
233
+ return { contextLength: 8192 };
234
+ }
235
+ }
236
+ // ========================================================================
237
+ // Readiness
238
+ // ========================================================================
239
+ /** Ensure model is available, pull if missing */
240
+ async ensureReady() {
241
+ try {
242
+ await this.getModelInfo();
243
+ }
244
+ catch {
245
+ // Try pulling the model
246
+ this.debugLog(`Model not found, attempting pull: ${this.options.model}`);
247
+ await httpRequest(`${this.options.url}/api/pull`, {
248
+ method: 'POST',
249
+ body: { name: this.options.model },
250
+ timeout: 300000, // 5 min for pull
251
+ });
252
+ }
253
+ }
254
+ // ========================================================================
255
+ // Internals
256
+ // ========================================================================
257
+ convertMessages(messages) {
258
+ return messages.map(msg => {
259
+ // Ollama needs tool call arguments as objects, not strings
260
+ if (msg.tool_calls?.length) {
261
+ return {
262
+ ...msg,
263
+ tool_calls: msg.tool_calls.map(tc => ({
264
+ ...tc,
265
+ function: {
266
+ ...tc.function,
267
+ arguments: typeof tc.function.arguments === 'string'
268
+ ? (() => { try {
269
+ return JSON.parse(tc.function.arguments);
270
+ }
271
+ catch {
272
+ return tc.function.arguments;
273
+ } })()
274
+ : tc.function.arguments,
275
+ },
276
+ })),
277
+ };
278
+ }
279
+ return msg;
280
+ });
281
+ }
282
+ convertToolsToOllama(tools) {
283
+ return tools.map(t => ({
284
+ type: 'function',
285
+ function: {
286
+ name: t.function.name,
287
+ description: t.function.description,
288
+ parameters: t.function.parameters,
289
+ },
290
+ }));
291
+ }
292
+ buildOllamaOptions(options) {
293
+ const params = {
294
+ ...this.options.defaultParameters,
295
+ ...options?.parameters,
296
+ };
297
+ if (options?.temperature !== undefined)
298
+ params['temperature'] = options.temperature;
299
+ if (options?.maxTokens !== undefined)
300
+ params['num_predict'] = options.maxTokens;
301
+ return params;
302
+ }
303
+ }
304
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/providers/ollama.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAe3D,MAAM,OAAO,YAAa,SAAQ,aAAa;IAC3C,YAAY,OAAyB,EAAE,OAAiB;QACpD,KAAK,CAAC;YACF,GAAG,OAAO;YACV,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,IAAI,wBAAwB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;SACrE,EAAE,OAAO,CAAC,CAAC;IAChB,CAAC;IAED,2EAA2E;IAC3E,OAAO;IACP,2EAA2E;IAE3E,KAAK,CAAC,IAAI,CACN,QAA0B,EAC1B,OAAqB;QAErB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC;QAC3C,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAEpH,MAAM,IAAI,GAA4B;YAClC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;YACzB,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;YACxC,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;SAC5C,CAAC;QAEF,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;QACzB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAChB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;SAC5B,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAiB,GAAG,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;YACnC,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK;SACzC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QAC3B,MAAM,KAAK,GAA+B,CAAC,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,UAAU,CAAC;YACjF,CAAC,CAAC;gBACE,WAAW,EAAE,IAAI,CAAC,iBAAiB,IAAI,CAAC;gBACxC,YAAY,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;gBAClC,WAAW,EAAE,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;aACtE;YACD,CAAC,CAAC,SAAS,CAAC;QAEhB,wDAAwD;QACxD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAClD,GAAG,EAAE;YACL,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,IAAI,CAAC,kBAAkB,EAAE;YACtC,QAAQ,EAAE;gBACN,GAAG,EAAE,CAAC,QAAQ;gBACd,SAAS,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,KAAK,QAAQ;oBAChD,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS;oBACvB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;aAC9C;SACJ,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAoB;YAC5B,OAAO,EAAE;gBACL,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE;gBAC5D,UAAU,EAAE,SAAS;aACxB;YACD,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;YACnE,KAAK;YACL,QAAQ,EAAE,QAAQ;SACrB,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;YACzB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC5B,KAAK;SACR,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,2EAA2E;IAC3E,YAAY;IACZ,2EAA2E;IAE3E,KAAK,CAAC,CAAC,UAAU,CACb,QAA0B,EAC1B,OAAqB;QAErB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC;QAC3C,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAEpH,MAAM,IAAI,GAA4B;YAClC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;YACzB,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;YACxC,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;SAC5C,CAAC;QAEF,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;QACzB,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAChB,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;SAC5B,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAClD,IAAI,YAAwC,CAAC;QAE7C,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;YACnC,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,MAAM;SAC1C,CAAC,CAAC;QAEH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,WAAW,CAAiB,MAAM,CAAC,EAAE,CAAC;YAC5D,YAAY,GAAG,KAAK,CAAC;YAErB,IAAI,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;gBAC1B,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAC9C,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAChE,CAAC;YAED,IAAI,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACpC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3D,CAAC;YAED,IAAI,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;gBACpC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;oBACnD,GAAG,EAAE;oBACL,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,IAAI,CAAC,kBAAkB,EAAE;oBACtC,QAAQ,EAAE;wBACN,GAAG,EAAE,CAAC,QAAQ;wBACd,SAAS,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,KAAK,QAAQ;4BAChD,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS;4BACvB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;qBAC9C;iBACJ,CAAC,CAAC,CAAC;gBACJ,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;YACnD,CAAC;QACL,CAAC;QAED,OAAO,CAAC,KAAK,EAAE,CAAC;QAEhB,MAAM,KAAK,GAA+B,YAAY,EAAE,iBAAiB;YACrE,CAAC,CAAC;gBACE,WAAW,EAAE,YAAY,CAAC,iBAAiB,IAAI,CAAC;gBAChD,YAAY,EAAE,YAAY,CAAC,UAAU,IAAI,CAAC;gBAC1C,WAAW,EAAE,CAAC,YAAY,CAAC,iBAAiB,IAAI,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,UAAU,IAAI,CAAC,CAAC;aACtF;YACD,CAAC,CAAC,SAAS,CAAC;QAEhB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;YACzB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;YAC5B,KAAK;SACR,CAAC,CAAC;QAEH,OAAO;YACH,OAAO,EAAE;gBACL,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,OAAO,CAAC,eAAe,EAAE;aACrC;YACD,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE;YACjC,KAAK;YACL,QAAQ,EAAE,QAAQ;SACrB,CAAC;IACN,CAAC;IAED,2EAA2E;IAC3E,aAAa;IACb,2EAA2E;IAE3E,KAAK,CAAC,KAAK,CAAC,IAAY;QACpB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC;QAC5C,MAAM,QAAQ,GAAG,MAAM,WAAW,CAA6B,GAAG,EAAE;YAChE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;YACnC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;YAChD,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK;SACzC,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7C,CAAC;IAEQ,KAAK,CAAC,UAAU,CAAC,KAAe;QACrC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC;QAC5C,MAAM,QAAQ,GAAG,MAAM,WAAW,CAA6B,GAAG,EAAE;YAChE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;YACnC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;YACjD,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK;SACzC,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;IACpC,CAAC;IAED,2EAA2E;IAC3E,kBAAkB;IAClB,2EAA2E;IAE3E,KAAK,CAAC,SAAS;QACX,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC;QAC3C,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAgC,GAAG,EAAE;YACnE,OAAO,EAAE,IAAI;SAChB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAEQ,KAAK,CAAC,YAAY,CAAC,SAAkB;QAC1C,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC;QAC3C,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAA0B,GAAG,EAAE;gBAC7D,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAC/C,OAAO,EAAE,IAAI;aAChB,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAwC,CAAC;YACrF,IAAI,CAAC,SAAS;gBAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;YAE/C,+CAA+C;YAC/C,MAAM,IAAI,GAAG,SAAS,CAAC,sBAAsB,CAAuB,CAAC;YACrE,IAAI,aAAa,GAAG,IAAI,CAAC;YAEzB,IAAI,IAAI,EAAE,CAAC;gBACP,MAAM,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC;gBACxC,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAuB,CAAC;gBACzD,IAAI,QAAQ;oBAAE,aAAa,GAAG,QAAQ,CAAC;YAC3C,CAAC;YAED,MAAM,aAAa,GAAG,SAAS,CAAC,yBAAyB,CAAuB,CAAC;YAEjF,OAAO;gBACH,KAAK,EAAE,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK;gBACtC,aAAa;gBACb,YAAY,EAAE,IAAI;gBAClB,cAAc,EAAE,aAAa;aAChC,CAAC;QACN,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;QACnC,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,YAAY;IACZ,2EAA2E;IAE3E,iDAAiD;IACjD,KAAK,CAAC,WAAW;QACb,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACL,wBAAwB;YACxB,IAAI,CAAC,QAAQ,CAAC,qCAAqC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YACzE,MAAM,WAAW,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,WAAW,EAAE;gBAC9C,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClC,OAAO,EAAE,MAAM,EAAE,iBAAiB;aACrC,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,YAAY;IACZ,2EAA2E;IAEnE,eAAe,CAAC,QAA0B;QAC9C,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YACtB,2DAA2D;YAC3D,IAAI,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBACzB,OAAO;oBACH,GAAG,GAAG;oBACN,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;wBAClC,GAAG,EAAE;wBACL,QAAQ,EAAE;4BACN,GAAG,EAAE,CAAC,QAAQ;4BACd,SAAS,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,KAAK,QAAQ;gCAChD,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;oCAAC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gCAAC,CAAC;gCAAC,MAAM,CAAC;oCAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;gCAAC,CAAC,CAAC,CAAC,CAAC,EAAE;gCACzG,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS;yBAC9B;qBACJ,CAAC,CAAC;iBACN,CAAC;YACN,CAAC;YACD,OAAO,GAAG,CAAC;QACf,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,oBAAoB,CAAC,KAA0B;QACnD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnB,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE;gBACN,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;gBACrB,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW;gBACnC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;aACpC;SACJ,CAAC,CAAC,CAAC;IACR,CAAC;IAEO,kBAAkB,CAAC,OAAqB;QAC5C,MAAM,MAAM,GAA4B;YACpC,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB;YACjC,GAAG,OAAO,EAAE,UAAU;SACzB,CAAC;QACF,IAAI,OAAO,EAAE,WAAW,KAAK,SAAS;YAAE,MAAM,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;QACpF,IAAI,OAAO,EAAE,SAAS,KAAK,SAAS;YAAE,MAAM,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;QAChF,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Universal LLM Client v3 — OpenAI-Compatible Provider
3
+ *
4
+ * Implements BaseLLMClient for OpenAI-compatible APIs.
5
+ * Works with: OpenAI, OpenRouter, LM Studio, LlamaCpp, vLLM, Groq, Together.
6
+ */
7
+ import { BaseLLMClient } from '../client.js';
8
+ import type { LLMClientOptions, LLMChatMessage, LLMChatResponse, ChatOptions } from '../interfaces.js';
9
+ import type { DecodedEvent } from '../stream-decoder.js';
10
+ import type { Auditor } from '../auditor.js';
11
+ export declare class OpenAICompatibleClient extends BaseLLMClient {
12
+ constructor(options: LLMClientOptions, auditor?: Auditor);
13
+ chat(messages: LLMChatMessage[], options?: ChatOptions): Promise<LLMChatResponse>;
14
+ chatStream(messages: LLMChatMessage[], options?: ChatOptions): AsyncGenerator<DecodedEvent, LLMChatResponse | void, unknown>;
15
+ embed(text: string): Promise<number[]>;
16
+ getModels(): Promise<string[]>;
17
+ private convertMessages;
18
+ private buildRequestParams;
19
+ }
20
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,OAAO,KAAK,EACR,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,WAAW,EAId,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,qBAAa,sBAAuB,SAAQ,aAAa;gBACzC,OAAO,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,OAAO;IAalD,IAAI,CACN,QAAQ,EAAE,cAAc,EAAE,EAC1B,OAAO,CAAC,EAAE,WAAW,GACtB,OAAO,CAAC,eAAe,CAAC;IA+EpB,UAAU,CACb,QAAQ,EAAE,cAAc,EAAE,EAC1B,OAAO,CAAC,EAAE,WAAW,GACtB,cAAc,CAAC,YAAY,EAAE,eAAe,GAAG,IAAI,EAAE,OAAO,CAAC;IAqJ1D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoBtC,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAmBpC,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,kBAAkB;CAS7B"}
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Universal LLM Client v3 — OpenAI-Compatible Provider
3
+ *
4
+ * Implements BaseLLMClient for OpenAI-compatible APIs.
5
+ * Works with: OpenAI, OpenRouter, LM Studio, LlamaCpp, vLLM, Groq, Together.
6
+ */
7
+ import { BaseLLMClient } from '../client.js';
8
+ import { httpRequest, httpStream, parseSSE, buildHeaders } from '../http.js';
9
+ import { StandardChatDecoder } from '../stream-decoder.js';
10
+ export class OpenAICompatibleClient extends BaseLLMClient {
11
+ constructor(options, auditor) {
12
+ // Ensure URL ends with /v1 for standard endpoints
13
+ let url = (options.url || 'https://api.openai.com').replace(/\/+$/, '');
14
+ if (!url.endsWith('/v1')) {
15
+ url += '/v1';
16
+ }
17
+ super({ ...options, url }, auditor);
18
+ }
19
+ // ========================================================================
20
+ // Chat
21
+ // ========================================================================
22
+ async chat(messages, options) {
23
+ const url = `${this.options.url}/chat/completions`;
24
+ const tools = options?.tools ?? (Object.keys(this.toolRegistry).length > 0 ? this.getToolDefinitions() : undefined);
25
+ const body = {
26
+ model: this.options.model,
27
+ messages: this.convertMessages(messages),
28
+ ...this.buildRequestParams(options),
29
+ };
30
+ if (tools?.length) {
31
+ body['tools'] = tools;
32
+ if (options?.toolChoice) {
33
+ body['tool_choice'] = options.toolChoice;
34
+ }
35
+ }
36
+ const start = Date.now();
37
+ this.auditor.record({
38
+ timestamp: start,
39
+ type: 'request',
40
+ provider: 'openai',
41
+ model: this.options.model,
42
+ });
43
+ const response = await httpRequest(url, {
44
+ method: 'POST',
45
+ headers: buildHeaders(this.options),
46
+ body,
47
+ timeout: this.options.timeout ?? 30000,
48
+ });
49
+ const data = response.data;
50
+ const choice = data.choices[0];
51
+ if (!choice) {
52
+ throw new Error('No choices returned from OpenAI API');
53
+ }
54
+ const usage = data.usage
55
+ ? {
56
+ inputTokens: data.usage.prompt_tokens,
57
+ outputTokens: data.usage.completion_tokens,
58
+ totalTokens: data.usage.total_tokens,
59
+ }
60
+ : undefined;
61
+ // Normalize tool calls (ensure IDs exist)
62
+ const toolCalls = choice.message.tool_calls?.map(tc => ({
63
+ ...tc,
64
+ id: tc.id || this.generateToolCallId(),
65
+ }));
66
+ const result = {
67
+ message: {
68
+ role: 'assistant',
69
+ content: choice.message.content || '',
70
+ tool_calls: toolCalls,
71
+ },
72
+ usage,
73
+ provider: 'openai',
74
+ };
75
+ this.auditor.record({
76
+ timestamp: Date.now(),
77
+ type: 'response',
78
+ provider: 'openai',
79
+ model: this.options.model,
80
+ duration: Date.now() - start,
81
+ usage,
82
+ });
83
+ return result;
84
+ }
85
+ // ========================================================================
86
+ // Streaming
87
+ // ========================================================================
88
+ async *chatStream(messages, options) {
89
+ const url = `${this.options.url}/chat/completions`;
90
+ const tools = options?.tools ?? (Object.keys(this.toolRegistry).length > 0 ? this.getToolDefinitions() : undefined);
91
+ const body = {
92
+ model: this.options.model,
93
+ messages: this.convertMessages(messages),
94
+ stream: true,
95
+ ...this.buildRequestParams(options),
96
+ };
97
+ if (tools?.length) {
98
+ body['tools'] = tools;
99
+ if (options?.toolChoice) {
100
+ body['tool_choice'] = options.toolChoice;
101
+ }
102
+ }
103
+ const start = Date.now();
104
+ this.auditor.record({
105
+ timestamp: start,
106
+ type: 'stream_start',
107
+ provider: 'openai',
108
+ model: this.options.model,
109
+ });
110
+ const decoder = new StandardChatDecoder(() => { });
111
+ // Track accumulated tool calls across chunks
112
+ const toolCallAccum = new Map();
113
+ const stream = httpStream(url, {
114
+ method: 'POST',
115
+ headers: buildHeaders(this.options),
116
+ body,
117
+ timeout: this.options.timeout ?? 120000,
118
+ });
119
+ let usage;
120
+ for await (const { data } of parseSSE(stream)) {
121
+ try {
122
+ const parsed = JSON.parse(data);
123
+ if (parsed.usage) {
124
+ usage = {
125
+ inputTokens: parsed.usage.prompt_tokens,
126
+ outputTokens: parsed.usage.completion_tokens,
127
+ totalTokens: parsed.usage.total_tokens,
128
+ };
129
+ }
130
+ const delta = parsed.choices?.[0]?.delta;
131
+ if (!delta)
132
+ continue;
133
+ if (delta.content) {
134
+ decoder.push(delta.content);
135
+ yield { type: 'text', content: delta.content };
136
+ }
137
+ // Accumulate streamed tool calls
138
+ if (delta.tool_calls) {
139
+ for (const tc of delta.tool_calls) {
140
+ const existing = toolCallAccum.get(tc.index);
141
+ if (!existing) {
142
+ toolCallAccum.set(tc.index, {
143
+ id: tc.id || this.generateToolCallId(),
144
+ type: 'function',
145
+ function: {
146
+ name: tc.function?.name || '',
147
+ arguments: tc.function?.arguments || '',
148
+ },
149
+ });
150
+ }
151
+ else {
152
+ if (tc.function?.arguments) {
153
+ existing.function.arguments += tc.function.arguments;
154
+ }
155
+ if (tc.function?.name) {
156
+ existing.function.name += tc.function.name;
157
+ }
158
+ }
159
+ }
160
+ }
161
+ // Emit tool calls when stream finishes
162
+ if (parsed.choices?.[0]?.finish_reason === 'tool_calls' || parsed.choices?.[0]?.finish_reason === 'stop') {
163
+ if (toolCallAccum.size > 0) {
164
+ const calls = Array.from(toolCallAccum.values());
165
+ yield { type: 'tool_call', calls };
166
+ }
167
+ }
168
+ }
169
+ catch {
170
+ // Skip unparseable SSE data
171
+ }
172
+ }
173
+ decoder.flush();
174
+ this.auditor.record({
175
+ timestamp: Date.now(),
176
+ type: 'stream_end',
177
+ provider: 'openai',
178
+ model: this.options.model,
179
+ duration: Date.now() - start,
180
+ usage,
181
+ });
182
+ const finalToolCalls = toolCallAccum.size > 0
183
+ ? Array.from(toolCallAccum.values())
184
+ : undefined;
185
+ return {
186
+ message: {
187
+ role: 'assistant',
188
+ content: decoder.getCleanContent(),
189
+ tool_calls: finalToolCalls,
190
+ },
191
+ reasoning: decoder.getReasoning(),
192
+ usage,
193
+ provider: 'openai',
194
+ };
195
+ }
196
+ // ========================================================================
197
+ // Embeddings
198
+ // ========================================================================
199
+ async embed(text) {
200
+ const url = `${this.options.url}/embeddings`;
201
+ const response = await httpRequest(url, {
202
+ method: 'POST',
203
+ headers: buildHeaders(this.options),
204
+ body: {
205
+ model: this.options.model,
206
+ input: text,
207
+ },
208
+ timeout: this.options.timeout ?? 30000,
209
+ });
210
+ return response.data.data[0]?.embedding ?? [];
211
+ }
212
+ // ========================================================================
213
+ // Model Discovery
214
+ // ========================================================================
215
+ async getModels() {
216
+ const url = `${this.options.url}/models`;
217
+ try {
218
+ const response = await httpRequest(url, {
219
+ headers: buildHeaders(this.options),
220
+ timeout: 5000,
221
+ });
222
+ return response.data.data.map(m => m.id);
223
+ }
224
+ catch {
225
+ return [];
226
+ }
227
+ }
228
+ // ========================================================================
229
+ // Internals
230
+ // ========================================================================
231
+ convertMessages(messages) {
232
+ // OpenAI format is our canonical format, minimal conversion needed
233
+ return messages.map(msg => ({
234
+ ...msg,
235
+ // Ensure content is never null/undefined
236
+ content: msg.content ?? '',
237
+ }));
238
+ }
239
+ buildRequestParams(options) {
240
+ const params = {
241
+ ...this.options.defaultParameters,
242
+ ...options?.parameters,
243
+ };
244
+ if (options?.temperature !== undefined)
245
+ params['temperature'] = options.temperature;
246
+ if (options?.maxTokens !== undefined)
247
+ params['max_tokens'] = options.maxTokens;
248
+ return params;
249
+ }
250
+ }
251
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}