@imenam/unified-llm-client 1.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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -0
  3. package/dist/adapters/anthropic/AnthropicLogAdapter.d.ts +6 -0
  4. package/dist/adapters/anthropic/AnthropicLogAdapter.d.ts.map +1 -0
  5. package/dist/adapters/anthropic/AnthropicLogAdapter.js +41 -0
  6. package/dist/adapters/anthropic/AnthropicOutputAdapter.d.ts +6 -0
  7. package/dist/adapters/anthropic/AnthropicOutputAdapter.d.ts.map +1 -0
  8. package/dist/adapters/anthropic/AnthropicOutputAdapter.js +41 -0
  9. package/dist/adapters/anthropic/AnthropicPromptAdapter.d.ts +12 -0
  10. package/dist/adapters/anthropic/AnthropicPromptAdapter.d.ts.map +1 -0
  11. package/dist/adapters/anthropic/AnthropicPromptAdapter.js +249 -0
  12. package/dist/adapters/anthropic/AnthropicToolAdapter.d.ts +6 -0
  13. package/dist/adapters/anthropic/AnthropicToolAdapter.d.ts.map +1 -0
  14. package/dist/adapters/anthropic/AnthropicToolAdapter.js +20 -0
  15. package/dist/adapters/gemini/GeminiAudioAdapter.d.ts +40 -0
  16. package/dist/adapters/gemini/GeminiAudioAdapter.d.ts.map +1 -0
  17. package/dist/adapters/gemini/GeminiAudioAdapter.js +273 -0
  18. package/dist/adapters/gemini/GeminiLogAdapter.d.ts +6 -0
  19. package/dist/adapters/gemini/GeminiLogAdapter.d.ts.map +1 -0
  20. package/dist/adapters/gemini/GeminiLogAdapter.js +43 -0
  21. package/dist/adapters/gemini/GeminiOutputAdapter.d.ts +6 -0
  22. package/dist/adapters/gemini/GeminiOutputAdapter.d.ts.map +1 -0
  23. package/dist/adapters/gemini/GeminiOutputAdapter.js +38 -0
  24. package/dist/adapters/gemini/GeminiPromptAdapter.d.ts +26 -0
  25. package/dist/adapters/gemini/GeminiPromptAdapter.d.ts.map +1 -0
  26. package/dist/adapters/gemini/GeminiPromptAdapter.js +334 -0
  27. package/dist/adapters/gemini/GeminiToolAdapter.d.ts +8 -0
  28. package/dist/adapters/gemini/GeminiToolAdapter.d.ts.map +1 -0
  29. package/dist/adapters/gemini/GeminiToolAdapter.js +42 -0
  30. package/dist/adapters/gemini/types.d.ts +14 -0
  31. package/dist/adapters/gemini/types.d.ts.map +1 -0
  32. package/dist/adapters/gemini/types.js +2 -0
  33. package/dist/adapters/openai/OpenAIOutputAdapter.d.ts +6 -0
  34. package/dist/adapters/openai/OpenAIOutputAdapter.d.ts.map +1 -0
  35. package/dist/adapters/openai/OpenAIOutputAdapter.js +18 -0
  36. package/dist/adapters/openai/OpenAIPromptAdapter.d.ts +13 -0
  37. package/dist/adapters/openai/OpenAIPromptAdapter.d.ts.map +1 -0
  38. package/dist/adapters/openai/OpenAIPromptAdapter.js +215 -0
  39. package/dist/adapters/openai/OpenAiLogAdapter.d.ts +6 -0
  40. package/dist/adapters/openai/OpenAiLogAdapter.d.ts.map +1 -0
  41. package/dist/adapters/openai/OpenAiLogAdapter.js +37 -0
  42. package/dist/adapters/openai/OpenAiToolAdapter.d.ts +6 -0
  43. package/dist/adapters/openai/OpenAiToolAdapter.d.ts.map +1 -0
  44. package/dist/adapters/openai/OpenAiToolAdapter.js +20 -0
  45. package/dist/adapters/qwen/QwenLogAdapter.d.ts +7 -0
  46. package/dist/adapters/qwen/QwenLogAdapter.d.ts.map +1 -0
  47. package/dist/adapters/qwen/QwenLogAdapter.js +49 -0
  48. package/dist/adapters/qwen/QwenOutputAdapter.d.ts +6 -0
  49. package/dist/adapters/qwen/QwenOutputAdapter.d.ts.map +1 -0
  50. package/dist/adapters/qwen/QwenOutputAdapter.js +9 -0
  51. package/dist/adapters/qwen/QwenPromptAdapter.d.ts +13 -0
  52. package/dist/adapters/qwen/QwenPromptAdapter.d.ts.map +1 -0
  53. package/dist/adapters/qwen/QwenPromptAdapter.js +313 -0
  54. package/dist/adapters/qwen/QwenToolAdapter.d.ts +6 -0
  55. package/dist/adapters/qwen/QwenToolAdapter.d.ts.map +1 -0
  56. package/dist/adapters/qwen/QwenToolAdapter.js +20 -0
  57. package/dist/common/types.d.ts +106 -0
  58. package/dist/common/types.d.ts.map +1 -0
  59. package/dist/common/types.js +2 -0
  60. package/dist/core/LLMAdapter.d.ts +74 -0
  61. package/dist/core/LLMAdapter.d.ts.map +1 -0
  62. package/dist/core/LLMAdapter.js +70 -0
  63. package/dist/core/Models.d.ts +16 -0
  64. package/dist/core/Models.d.ts.map +1 -0
  65. package/dist/core/Models.js +118 -0
  66. package/dist/core/UnifiedLLMClient.d.ts +68 -0
  67. package/dist/core/UnifiedLLMClient.d.ts.map +1 -0
  68. package/dist/core/UnifiedLLMClient.js +185 -0
  69. package/dist/examples/anthropic-example.d.ts +2 -0
  70. package/dist/examples/anthropic-example.d.ts.map +1 -0
  71. package/dist/examples/anthropic-example.js +243 -0
  72. package/dist/examples/audio-example.d.ts +14 -0
  73. package/dist/examples/audio-example.d.ts.map +1 -0
  74. package/dist/examples/audio-example.js +204 -0
  75. package/dist/examples/example-logging.d.ts +2 -0
  76. package/dist/examples/example-logging.d.ts.map +1 -0
  77. package/dist/examples/example-logging.js +53 -0
  78. package/dist/examples/example.d.ts +2 -0
  79. package/dist/examples/example.d.ts.map +1 -0
  80. package/dist/examples/example.js +373 -0
  81. package/dist/examples/qwen-vl-example.d.ts +26 -0
  82. package/dist/examples/qwen-vl-example.d.ts.map +1 -0
  83. package/dist/examples/qwen-vl-example.js +314 -0
  84. package/dist/examples/test-multiturn-tools.d.ts +2 -0
  85. package/dist/examples/test-multiturn-tools.d.ts.map +1 -0
  86. package/dist/examples/test-multiturn-tools.js +139 -0
  87. package/dist/index.d.ts +7 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +7 -0
  90. package/dist/utils/audioUtils.d.ts +41 -0
  91. package/dist/utils/audioUtils.d.ts.map +1 -0
  92. package/dist/utils/audioUtils.js +185 -0
  93. package/package.json +64 -0
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.QwenPromptAdapter = void 0;
49
+ const node_fetch_1 = __importDefault(require("node-fetch"));
50
+ const fs = __importStar(require("fs"));
51
+ const path = __importStar(require("path"));
52
+ class QwenPromptAdapter {
53
+ constructor(opts) {
54
+ var _a, _b;
55
+ this.opts = opts;
56
+ this.messages = [];
57
+ this.endpoint =
58
+ (_b = (_a = opts.baseUrl) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, "")) !== null && _b !== void 0 ? _b : "https://dashscope-intl.aliyuncs.com/compatible-mode/v1";
59
+ this.endpoint += "/chat/completions";
60
+ }
61
+ formatMessage(message) {
62
+ var _a;
63
+ // Assistant message with tool calls → OpenAI-compatible format
64
+ if (message.role === "assistant" && message.tool_calls && message.tool_calls.length > 0) {
65
+ return {
66
+ role: "assistant",
67
+ content: (_a = message.content) !== null && _a !== void 0 ? _a : null,
68
+ tool_calls: message.tool_calls.map(tc => {
69
+ var _a;
70
+ return ({
71
+ id: (_a = tc.id) !== null && _a !== void 0 ? _a : tc.name,
72
+ type: "function",
73
+ function: {
74
+ name: tc.name,
75
+ arguments: JSON.stringify(tc.arguments),
76
+ },
77
+ });
78
+ }),
79
+ };
80
+ }
81
+ // Si le message contient des attachedFile, les convertir au format Qwen VL
82
+ if (message.attachedFile) {
83
+ const content = [];
84
+ // Ajouter le texte si présent
85
+ if (message.content && typeof message.content === 'string') {
86
+ content.push({
87
+ type: "text",
88
+ text: message.content
89
+ });
90
+ }
91
+ // Ajouter les fichiers attachés
92
+ const files = Array.isArray(message.attachedFile) ? message.attachedFile : [message.attachedFile];
93
+ for (const file of files) {
94
+ if (typeof file === 'string') {
95
+ try {
96
+ // Lire le fichier et le convertir en base64
97
+ const filePath = path.resolve(file);
98
+ const fileBuffer = fs.readFileSync(filePath);
99
+ const base64Data = fileBuffer.toString('base64');
100
+ // Déterminer le type MIME
101
+ const ext = path.extname(filePath).toLowerCase();
102
+ let mimeType = 'application/octet-stream';
103
+ if (ext === '.jpg' || ext === '.jpeg') {
104
+ mimeType = 'image/jpeg';
105
+ }
106
+ else if (ext === '.png') {
107
+ mimeType = 'image/png';
108
+ }
109
+ else if (ext === '.gif') {
110
+ mimeType = 'image/gif';
111
+ }
112
+ else if (ext === '.webp') {
113
+ mimeType = 'image/webp';
114
+ }
115
+ else if (ext === '.pdf') {
116
+ mimeType = 'application/pdf';
117
+ }
118
+ content.push({
119
+ type: "image_url",
120
+ image_url: {
121
+ url: `data:${mimeType};base64,${base64Data}`
122
+ }
123
+ });
124
+ }
125
+ catch (error) {
126
+ console.warn(`Failed to read attached file ${file}:`, error);
127
+ }
128
+ }
129
+ }
130
+ return {
131
+ role: message.role,
132
+ content: content
133
+ };
134
+ }
135
+ // Pour les messages sans attachedFile, retourner tel quel
136
+ return message;
137
+ }
138
+ sendToProvider(messages_1) {
139
+ return __awaiter(this, arguments, void 0, function* (messages, tools = [], toolChoice = "auto", attachedFile, model) {
140
+ var _a;
141
+ const body = {
142
+ model: model || this.opts.model,
143
+ messages,
144
+ stream: false,
145
+ };
146
+ if (tools.length) {
147
+ body.tools = tools.map((fn) => ({ type: "function", function: fn }));
148
+ body.tool_choice =
149
+ toolChoice === "auto"
150
+ ? "auto"
151
+ : toolChoice === "none"
152
+ ? "none"
153
+ : { type: "function", function: { name: toolChoice } };
154
+ }
155
+ const response = yield this.request(body);
156
+ const responseMessage = response.choices[0].message;
157
+ const calls = (responseMessage.tool_calls || []).map((c) => {
158
+ var _a;
159
+ return ({
160
+ id: c.id,
161
+ name: c.function.name,
162
+ arguments: JSON.parse((_a = c.function.arguments) !== null && _a !== void 0 ? _a : "{}"),
163
+ });
164
+ });
165
+ return {
166
+ content: (_a = responseMessage.content) !== null && _a !== void 0 ? _a : null,
167
+ toolCalls: calls,
168
+ raw: response,
169
+ };
170
+ });
171
+ }
172
+ streamFromProvider(_a) {
173
+ return __awaiter(this, arguments, void 0, function* ({ messages, tools, toolChoice, model, onChunk, onFinalResponse, }) {
174
+ const body = {
175
+ model: model || this.opts.model,
176
+ messages,
177
+ stream: true,
178
+ };
179
+ if (tools === null || tools === void 0 ? void 0 : tools.length) {
180
+ body.tools = tools.map((fn) => ({ type: "function", function: fn }));
181
+ body.tool_choice =
182
+ toolChoice === "auto"
183
+ ? "auto"
184
+ : toolChoice === "none"
185
+ ? "none"
186
+ : { type: "function", function: { name: toolChoice } };
187
+ }
188
+ const response = yield (0, node_fetch_1.default)(this.endpoint, {
189
+ method: "POST",
190
+ headers: {
191
+ "Content-Type": "application/json",
192
+ Authorization: `Bearer ${this.opts.apiKey}`,
193
+ },
194
+ body: JSON.stringify(body),
195
+ });
196
+ if (!response.ok) {
197
+ throw new Error(`Qwen API ${response.status}: ${yield response.text()}`);
198
+ }
199
+ // Traitement du streaming avec les streams Node.js classiques
200
+ if (!response.body) {
201
+ throw new Error("Response body is not available for streaming");
202
+ }
203
+ return new Promise((resolve, reject) => {
204
+ let aggregatedContent = "";
205
+ const aggregatedToolCalls = [];
206
+ let buffer = "";
207
+ response.body.on('data', (chunk) => {
208
+ var _a, _b;
209
+ // Convertir le buffer en string
210
+ buffer += chunk.toString('utf8');
211
+ // Traiter les lignes complètes
212
+ const lines = buffer.split('\n');
213
+ buffer = lines.pop() || ""; // Garder le dernier fragment incomplet
214
+ for (const line of lines) {
215
+ if (line.startsWith('data: ')) {
216
+ const data = line.slice(6);
217
+ if (data === '[DONE]') {
218
+ continue;
219
+ }
220
+ try {
221
+ const parsed = JSON.parse(data);
222
+ const delta = (_b = (_a = parsed.choices) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.delta;
223
+ if (delta === null || delta === void 0 ? void 0 : delta.content) {
224
+ aggregatedContent += delta.content;
225
+ onChunk === null || onChunk === void 0 ? void 0 : onChunk({ contentChunk: delta.content, rawChunk: parsed });
226
+ }
227
+ if (delta === null || delta === void 0 ? void 0 : delta.tool_calls) {
228
+ for (const toolCall of delta.tool_calls) {
229
+ if (toolCall.function) {
230
+ aggregatedToolCalls.push({
231
+ id: toolCall.id,
232
+ name: toolCall.function.name,
233
+ arguments: JSON.parse(toolCall.function.arguments || "{}"),
234
+ });
235
+ }
236
+ }
237
+ }
238
+ }
239
+ catch (e) {
240
+ // Ignorer les chunks malformés
241
+ console.warn("Malformed chunk:", e);
242
+ }
243
+ }
244
+ }
245
+ });
246
+ response.body.on('end', () => {
247
+ var _a, _b;
248
+ // Traiter tout ce qui reste dans le buffer
249
+ if (buffer.trim()) {
250
+ const lines = buffer.split('\n');
251
+ for (const line of lines) {
252
+ if (line.startsWith('data: ')) {
253
+ const data = line.slice(6);
254
+ if (data !== '[DONE]') {
255
+ try {
256
+ const parsed = JSON.parse(data);
257
+ const delta = (_b = (_a = parsed.choices) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.delta;
258
+ if (delta === null || delta === void 0 ? void 0 : delta.content) {
259
+ aggregatedContent += delta.content;
260
+ onChunk === null || onChunk === void 0 ? void 0 : onChunk({ contentChunk: delta.content, rawChunk: parsed });
261
+ }
262
+ if (delta === null || delta === void 0 ? void 0 : delta.tool_calls) {
263
+ for (const toolCall of delta.tool_calls) {
264
+ if (toolCall.function) {
265
+ aggregatedToolCalls.push({
266
+ id: toolCall.id,
267
+ name: toolCall.function.name,
268
+ arguments: JSON.parse(toolCall.function.arguments || "{}"),
269
+ });
270
+ }
271
+ }
272
+ }
273
+ }
274
+ catch (e) {
275
+ // Ignorer les chunks malformés
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
281
+ const finalResponse = {
282
+ content: aggregatedContent,
283
+ toolCalls: aggregatedToolCalls.length > 0 ? aggregatedToolCalls : undefined,
284
+ raw: null,
285
+ };
286
+ onFinalResponse === null || onFinalResponse === void 0 ? void 0 : onFinalResponse(finalResponse);
287
+ resolve(finalResponse);
288
+ });
289
+ response.body.on('error', (error) => {
290
+ reject(new Error(`Stream error: ${error.message}`));
291
+ });
292
+ });
293
+ });
294
+ }
295
+ //--------------------------------------------------
296
+ request(body) {
297
+ return __awaiter(this, void 0, void 0, function* () {
298
+ const res = yield (0, node_fetch_1.default)(this.endpoint, {
299
+ method: "POST",
300
+ headers: {
301
+ "Content-Type": "application/json",
302
+ Authorization: `Bearer ${this.opts.apiKey}`,
303
+ },
304
+ body: JSON.stringify(body),
305
+ });
306
+ if (!res.ok) {
307
+ throw new Error(`Qwen API ${res.status}: ${yield res.text()}`);
308
+ }
309
+ return res.json();
310
+ });
311
+ }
312
+ }
313
+ exports.QwenPromptAdapter = QwenPromptAdapter;
@@ -0,0 +1,6 @@
1
+ import { ToolCall } from "../../common/types";
2
+ import { ToolAdapter } from "../../core/LLMAdapter";
3
+ export declare class QwenToolAdapter implements ToolAdapter {
4
+ formatToolCallResult(toolCall: ToolCall): any;
5
+ }
6
+ //# sourceMappingURL=QwenToolAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QwenToolAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/qwen/QwenToolAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,qBAAa,eAAgB,YAAW,WAAW;IACjD,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,GAAG;CAc9C"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QwenToolAdapter = void 0;
4
+ class QwenToolAdapter {
5
+ formatToolCallResult(toolCall) {
6
+ if (!toolCall.id || toolCall.id === "") {
7
+ throw new Error("Tool call ID is required to format response - toolCall: " + JSON.stringify(toolCall));
8
+ }
9
+ if (typeof toolCall.result !== 'string') {
10
+ toolCall.result = JSON.stringify(toolCall.result);
11
+ }
12
+ return {
13
+ tool_call_id: toolCall.id,
14
+ role: "tool",
15
+ name: toolCall.name,
16
+ content: toolCall.result,
17
+ };
18
+ }
19
+ }
20
+ exports.QwenToolAdapter = QwenToolAdapter;
@@ -0,0 +1,106 @@
1
+ export type Provider = "openai" | "gemini" | "qwen" | "anthropic";
2
+ export type ChatMessageRole = "user" | "assistant" | "system" | "tool" | "function";
3
+ export interface ChatMessage {
4
+ tool_call_id?: string;
5
+ role: ChatMessageRole;
6
+ content: string | any;
7
+ attachedFile?: string | string[];
8
+ /** Tool calls declared by the assistant (for multi-turn conversations).
9
+ * For Gemini tool results (role: "tool"), set tool_call_id to the function name. */
10
+ tool_calls?: ToolCall[];
11
+ }
12
+ export interface ToolDefinition {
13
+ name: string;
14
+ description?: string;
15
+ /** JSON‑Schema style parameters */
16
+ parameters?: Record<string, unknown>;
17
+ executor?: (args: Record<string, unknown>) => Promise<string>;
18
+ }
19
+ export interface ToolCall {
20
+ id?: string;
21
+ name: string;
22
+ arguments: Record<string, unknown>;
23
+ result?: string | Record<string, unknown>;
24
+ }
25
+ export interface ChatResponse {
26
+ content: string | null;
27
+ toolCalls?: ToolCall[];
28
+ raw: unknown;
29
+ usage?: {
30
+ promptTokens: number;
31
+ completionTokens: number;
32
+ totalTokens: number;
33
+ promptTokensDetails: any;
34
+ thoughtsToken: number;
35
+ };
36
+ finishReason?: string;
37
+ requestId?: string;
38
+ llmLogId?: number;
39
+ lastToolArguments?: ToolCall["arguments"];
40
+ }
41
+ export type Model = {
42
+ provider: Provider;
43
+ modelName: string;
44
+ costsPer1MTokens: {
45
+ prompt: number;
46
+ prompt_cache?: number | null;
47
+ prompt_image?: number | null;
48
+ prompt_audio?: number | null;
49
+ prompt_audio_cache?: number | null;
50
+ output: number;
51
+ };
52
+ currency: string;
53
+ };
54
+ export interface UnifiedUsage {
55
+ promptTokens: number;
56
+ completionTokens: number;
57
+ totalTokens: number;
58
+ promptDetails?: {
59
+ textTokens?: number;
60
+ audioTokens?: number;
61
+ imageTokens?: number;
62
+ cachedTokens?: number;
63
+ };
64
+ completionDetails?: {
65
+ textTokens?: number;
66
+ audioTokens?: number;
67
+ thinkingTokens?: number;
68
+ };
69
+ }
70
+ export interface UnifiedLog {
71
+ requestId: string;
72
+ timestamp: Date;
73
+ provider: Provider;
74
+ model: string;
75
+ prompt: ChatMessage[];
76
+ output: {
77
+ content: string | null;
78
+ toolCalls?: ToolCall[];
79
+ finishReason?: string;
80
+ };
81
+ usage: UnifiedUsage;
82
+ latencyMs: number;
83
+ metadata?: Record<string, any>;
84
+ }
85
+ export interface VoiceConfig {
86
+ voiceName: string;
87
+ temperature?: number;
88
+ }
89
+ export interface SpeakerConfig {
90
+ speaker: string;
91
+ voiceConfig: VoiceConfig;
92
+ }
93
+ export interface AudioGenerationOptions {
94
+ text: string;
95
+ outputPath?: string;
96
+ voiceConfig?: VoiceConfig;
97
+ multiSpeaker?: boolean;
98
+ speakers?: SpeakerConfig[];
99
+ }
100
+ export interface AudioGenerationResponse {
101
+ audioData: Buffer;
102
+ mimeType: string;
103
+ filePath?: string;
104
+ raw: any;
105
+ }
106
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/common/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,74 @@
1
+ import { ChatMessage, ToolDefinition, ChatResponse, ToolCall, AudioGenerationOptions, AudioGenerationResponse, UnifiedLog, Provider } from "../common/types";
2
+ export declare const PROVIDERS_CONFIG: Record<Provider, ProviderOptions>;
3
+ export type StreamedChatChunk = {
4
+ contentChunk?: string;
5
+ toolCallChunk?: ToolCall[];
6
+ isFinal?: boolean;
7
+ rawChunk?: any;
8
+ error?: any;
9
+ };
10
+ export type StreamingChatResult = {
11
+ response: ChatResponse;
12
+ };
13
+ export interface PromptAdapterOptions {
14
+ model: string;
15
+ apiKey: string;
16
+ baseUrl?: string;
17
+ }
18
+ export interface ChatStreamOptions {
19
+ messages: ChatMessage[];
20
+ tools?: ToolDefinition[];
21
+ toolChoice?: "auto" | "none" | string;
22
+ model?: string;
23
+ config?: ChatOptionalConfig;
24
+ onChunk?: (chunk: StreamedChatChunk) => void;
25
+ onFinalResponse?: (finalResponse: ChatResponse) => void;
26
+ }
27
+ export type ChatOptionalConfig = {
28
+ thinkingBudget?: number;
29
+ metadata?: Record<string, any>;
30
+ };
31
+ export interface LogData {
32
+ model: string;
33
+ provider: Provider;
34
+ messages: ChatMessage[];
35
+ response: ChatResponse;
36
+ latencyMs: number;
37
+ metadata?: Record<string, any>;
38
+ }
39
+ /**
40
+ * Interface for logging adapters
41
+ */
42
+ export interface LogAdapter {
43
+ toUnifiedLog(data: LogData): UnifiedLog;
44
+ }
45
+ /**
46
+ * The contract every concrete adapter must implement.
47
+ */
48
+ export interface PromptAdapter {
49
+ formatMessage(message: ChatMessage): any;
50
+ sendToProvider(messages: ChatMessage[], tools?: ToolDefinition[], toolChoice?: "auto" | "none" | string, attachedFile?: string | string[], model?: string, config?: ChatOptionalConfig): Promise<ChatResponse>;
51
+ streamFromProvider?(options: ChatStreamOptions): Promise<ChatResponse>;
52
+ }
53
+ export interface ToolAdapter {
54
+ formatToolCallResult(toolCall: ToolCall): any;
55
+ }
56
+ export interface OutputAdapter {
57
+ parse(providerResponse: any): ChatResponse;
58
+ }
59
+ /**
60
+ * Interface for audio generation adapters
61
+ */
62
+ export interface AudioAdapter {
63
+ generateAudio(options: AudioGenerationOptions): Promise<AudioGenerationResponse>;
64
+ generateAudioStream(options: AudioGenerationOptions): AsyncIterable<Buffer>;
65
+ getSupportedVoices(): Promise<string[]>;
66
+ }
67
+ export type ProviderOptions = {
68
+ promptAdapter: PromptAdapter;
69
+ outputAdapter: OutputAdapter;
70
+ toolAdapter: ToolAdapter;
71
+ audioAdapter?: AudioAdapter;
72
+ logAdapter?: LogAdapter;
73
+ };
74
+ //# sourceMappingURL=LLMAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LLMAdapter.d.ts","sourceRoot":"","sources":["../../src/core/LLMAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PROVIDERS_CONFIG = void 0;
7
+ const GeminiOutputAdapter_1 = require("../adapters/gemini/GeminiOutputAdapter");
8
+ const GeminiPromptAdapter_1 = require("../adapters/gemini/GeminiPromptAdapter");
9
+ const GeminiToolAdapter_1 = require("../adapters/gemini/GeminiToolAdapter");
10
+ const GeminiAudioAdapter_1 = require("../adapters/gemini/GeminiAudioAdapter");
11
+ const OpenAIOutputAdapter_1 = require("../adapters/openai/OpenAIOutputAdapter");
12
+ const OpenAIPromptAdapter_1 = require("../adapters/openai/OpenAIPromptAdapter");
13
+ const OpenAiToolAdapter_1 = require("../adapters/openai/OpenAiToolAdapter");
14
+ const QwenOutputAdapter_1 = require("../adapters/qwen/QwenOutputAdapter");
15
+ const QwenPromptAdapter_1 = require("../adapters/qwen/QwenPromptAdapter");
16
+ const QwenToolAdapter_1 = require("../adapters/qwen/QwenToolAdapter");
17
+ const GeminiLogAdapter_1 = require("../adapters/gemini/GeminiLogAdapter");
18
+ const OpenAiLogAdapter_1 = require("../adapters/openai/OpenAiLogAdapter");
19
+ const QwenLogAdapter_1 = require("../adapters/qwen/QwenLogAdapter");
20
+ const AnthropicPromptAdapter_1 = require("../adapters/anthropic/AnthropicPromptAdapter");
21
+ const AnthropicOutputAdapter_1 = require("../adapters/anthropic/AnthropicOutputAdapter");
22
+ const AnthropicToolAdapter_1 = require("../adapters/anthropic/AnthropicToolAdapter");
23
+ const AnthropicLogAdapter_1 = require("../adapters/anthropic/AnthropicLogAdapter");
24
+ const dotenv_1 = __importDefault(require("dotenv"));
25
+ dotenv_1.default.config();
26
+ exports.PROVIDERS_CONFIG = {
27
+ gemini: {
28
+ promptAdapter: new GeminiPromptAdapter_1.GeminiPromptAdapter({
29
+ apiKey: process.env.GOOGLE_API_KEY,
30
+ model: "gemini-2.5-flash",
31
+ }),
32
+ outputAdapter: new GeminiOutputAdapter_1.GeminiOutputAdapter(),
33
+ toolAdapter: new GeminiToolAdapter_1.GeminiToolAdapter(),
34
+ audioAdapter: new GeminiAudioAdapter_1.GeminiAudioAdapter({
35
+ apiKey: process.env.GOOGLE_API_KEY,
36
+ model: "gemini-2.5-pro-preview-tts",
37
+ }),
38
+ logAdapter: new GeminiLogAdapter_1.GeminiLogAdapter(),
39
+ },
40
+ openai: {
41
+ promptAdapter: new OpenAIPromptAdapter_1.OpenAIPromptAdapter({
42
+ apiKey: process.env.OPENAI_API_KEY,
43
+ model: "gpt-4o-mini",
44
+ }),
45
+ toolAdapter: new OpenAiToolAdapter_1.OpenAiToolAdapter(),
46
+ outputAdapter: new OpenAIOutputAdapter_1.OpenAIOutputAdapter(),
47
+ logAdapter: new OpenAiLogAdapter_1.OpenAiLogAdapter(),
48
+ // Note: OpenAI n'a pas encore d'audioAdapter - peut être ajouté plus tard
49
+ },
50
+ qwen: {
51
+ promptAdapter: new QwenPromptAdapter_1.QwenPromptAdapter({
52
+ apiKey: process.env.ALIBABA_CLOUD_API_KEY,
53
+ model: "qwen3-vl-235b-a22b-instruct",
54
+ baseUrl: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
55
+ }),
56
+ toolAdapter: new QwenToolAdapter_1.QwenToolAdapter(),
57
+ outputAdapter: new QwenOutputAdapter_1.QwenOutputAdapter(),
58
+ logAdapter: new QwenLogAdapter_1.QwenLogAdapter(),
59
+ // Note: Qwen n'a pas d'audioAdapter pour le moment
60
+ },
61
+ anthropic: {
62
+ promptAdapter: new AnthropicPromptAdapter_1.AnthropicPromptAdapter({
63
+ apiKey: process.env.ANTHROPIC_API_KEY,
64
+ model: "claude-sonnet-4-5-20250929",
65
+ }),
66
+ outputAdapter: new AnthropicOutputAdapter_1.AnthropicOutputAdapter(),
67
+ toolAdapter: new AnthropicToolAdapter_1.AnthropicToolAdapter(),
68
+ logAdapter: new AnthropicLogAdapter_1.AnthropicLogAdapter(),
69
+ },
70
+ };
@@ -0,0 +1,16 @@
1
+ import { Model } from "../common/types";
2
+ export declare const MODELS: {
3
+ GEMINI_FLASH_2_5: Model;
4
+ GEMINI_2_5_PRO: Model;
5
+ GPT_4O_MINI: Model;
6
+ GPT_5: Model;
7
+ QWEN_VL_3: Model;
8
+ QWEN_VL_FLASH: Model;
9
+ QWEN_VL_3_FLASH: Model;
10
+ GEMINI_3_PRO: Model;
11
+ GEMINI_3_1_PRO: Model;
12
+ GEMINI_3_FLASH: Model;
13
+ CLAUDE_SONNET_4_6: Model;
14
+ CLAUDE_OPUS_4_6: Model;
15
+ };
16
+ //# sourceMappingURL=Models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../src/core/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,eAAO,MAAM,MAAM;sBAWZ,KAAK;oBAYL,KAAK;iBAYL,KAAK;WAWL,KAAK;eAWL,KAAK;mBAWL,KAAK;qBAWL,KAAK;kBAWL,KAAK;oBAWL,KAAK;oBAaL,KAAK;uBAKL,KAAK;qBAKL,KAAK;CACX,CAAC"}