@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.
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/dist/adapters/anthropic/AnthropicLogAdapter.d.ts +6 -0
- package/dist/adapters/anthropic/AnthropicLogAdapter.d.ts.map +1 -0
- package/dist/adapters/anthropic/AnthropicLogAdapter.js +41 -0
- package/dist/adapters/anthropic/AnthropicOutputAdapter.d.ts +6 -0
- package/dist/adapters/anthropic/AnthropicOutputAdapter.d.ts.map +1 -0
- package/dist/adapters/anthropic/AnthropicOutputAdapter.js +41 -0
- package/dist/adapters/anthropic/AnthropicPromptAdapter.d.ts +12 -0
- package/dist/adapters/anthropic/AnthropicPromptAdapter.d.ts.map +1 -0
- package/dist/adapters/anthropic/AnthropicPromptAdapter.js +249 -0
- package/dist/adapters/anthropic/AnthropicToolAdapter.d.ts +6 -0
- package/dist/adapters/anthropic/AnthropicToolAdapter.d.ts.map +1 -0
- package/dist/adapters/anthropic/AnthropicToolAdapter.js +20 -0
- package/dist/adapters/gemini/GeminiAudioAdapter.d.ts +40 -0
- package/dist/adapters/gemini/GeminiAudioAdapter.d.ts.map +1 -0
- package/dist/adapters/gemini/GeminiAudioAdapter.js +273 -0
- package/dist/adapters/gemini/GeminiLogAdapter.d.ts +6 -0
- package/dist/adapters/gemini/GeminiLogAdapter.d.ts.map +1 -0
- package/dist/adapters/gemini/GeminiLogAdapter.js +43 -0
- package/dist/adapters/gemini/GeminiOutputAdapter.d.ts +6 -0
- package/dist/adapters/gemini/GeminiOutputAdapter.d.ts.map +1 -0
- package/dist/adapters/gemini/GeminiOutputAdapter.js +38 -0
- package/dist/adapters/gemini/GeminiPromptAdapter.d.ts +26 -0
- package/dist/adapters/gemini/GeminiPromptAdapter.d.ts.map +1 -0
- package/dist/adapters/gemini/GeminiPromptAdapter.js +334 -0
- package/dist/adapters/gemini/GeminiToolAdapter.d.ts +8 -0
- package/dist/adapters/gemini/GeminiToolAdapter.d.ts.map +1 -0
- package/dist/adapters/gemini/GeminiToolAdapter.js +42 -0
- package/dist/adapters/gemini/types.d.ts +14 -0
- package/dist/adapters/gemini/types.d.ts.map +1 -0
- package/dist/adapters/gemini/types.js +2 -0
- package/dist/adapters/openai/OpenAIOutputAdapter.d.ts +6 -0
- package/dist/adapters/openai/OpenAIOutputAdapter.d.ts.map +1 -0
- package/dist/adapters/openai/OpenAIOutputAdapter.js +18 -0
- package/dist/adapters/openai/OpenAIPromptAdapter.d.ts +13 -0
- package/dist/adapters/openai/OpenAIPromptAdapter.d.ts.map +1 -0
- package/dist/adapters/openai/OpenAIPromptAdapter.js +215 -0
- package/dist/adapters/openai/OpenAiLogAdapter.d.ts +6 -0
- package/dist/adapters/openai/OpenAiLogAdapter.d.ts.map +1 -0
- package/dist/adapters/openai/OpenAiLogAdapter.js +37 -0
- package/dist/adapters/openai/OpenAiToolAdapter.d.ts +6 -0
- package/dist/adapters/openai/OpenAiToolAdapter.d.ts.map +1 -0
- package/dist/adapters/openai/OpenAiToolAdapter.js +20 -0
- package/dist/adapters/qwen/QwenLogAdapter.d.ts +7 -0
- package/dist/adapters/qwen/QwenLogAdapter.d.ts.map +1 -0
- package/dist/adapters/qwen/QwenLogAdapter.js +49 -0
- package/dist/adapters/qwen/QwenOutputAdapter.d.ts +6 -0
- package/dist/adapters/qwen/QwenOutputAdapter.d.ts.map +1 -0
- package/dist/adapters/qwen/QwenOutputAdapter.js +9 -0
- package/dist/adapters/qwen/QwenPromptAdapter.d.ts +13 -0
- package/dist/adapters/qwen/QwenPromptAdapter.d.ts.map +1 -0
- package/dist/adapters/qwen/QwenPromptAdapter.js +313 -0
- package/dist/adapters/qwen/QwenToolAdapter.d.ts +6 -0
- package/dist/adapters/qwen/QwenToolAdapter.d.ts.map +1 -0
- package/dist/adapters/qwen/QwenToolAdapter.js +20 -0
- package/dist/common/types.d.ts +106 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/types.js +2 -0
- package/dist/core/LLMAdapter.d.ts +74 -0
- package/dist/core/LLMAdapter.d.ts.map +1 -0
- package/dist/core/LLMAdapter.js +70 -0
- package/dist/core/Models.d.ts +16 -0
- package/dist/core/Models.d.ts.map +1 -0
- package/dist/core/Models.js +118 -0
- package/dist/core/UnifiedLLMClient.d.ts +68 -0
- package/dist/core/UnifiedLLMClient.d.ts.map +1 -0
- package/dist/core/UnifiedLLMClient.js +185 -0
- package/dist/examples/anthropic-example.d.ts +2 -0
- package/dist/examples/anthropic-example.d.ts.map +1 -0
- package/dist/examples/anthropic-example.js +243 -0
- package/dist/examples/audio-example.d.ts +14 -0
- package/dist/examples/audio-example.d.ts.map +1 -0
- package/dist/examples/audio-example.js +204 -0
- package/dist/examples/example-logging.d.ts +2 -0
- package/dist/examples/example-logging.d.ts.map +1 -0
- package/dist/examples/example-logging.js +53 -0
- package/dist/examples/example.d.ts +2 -0
- package/dist/examples/example.d.ts.map +1 -0
- package/dist/examples/example.js +373 -0
- package/dist/examples/qwen-vl-example.d.ts +26 -0
- package/dist/examples/qwen-vl-example.d.ts.map +1 -0
- package/dist/examples/qwen-vl-example.js +314 -0
- package/dist/examples/test-multiturn-tools.d.ts +2 -0
- package/dist/examples/test-multiturn-tools.d.ts.map +1 -0
- package/dist/examples/test-multiturn-tools.js +139 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/utils/audioUtils.d.ts +41 -0
- package/dist/utils/audioUtils.d.ts.map +1 -0
- package/dist/utils/audioUtils.js +185 -0
- package/package.json +64 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AudioAdapter } from '../../core/LLMAdapter';
|
|
2
|
+
import { AudioGenerationOptions, AudioGenerationResponse, VoiceConfig, SpeakerConfig } from '../../common/types';
|
|
3
|
+
export interface GeminiAudioAdapterOptions {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
model?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class GeminiAudioAdapter implements AudioAdapter {
|
|
8
|
+
private client;
|
|
9
|
+
private model;
|
|
10
|
+
constructor(options: GeminiAudioAdapterOptions);
|
|
11
|
+
/**
|
|
12
|
+
* Génère de l'audio à partir de texte
|
|
13
|
+
*/
|
|
14
|
+
generateAudio(options: AudioGenerationOptions): Promise<AudioGenerationResponse>;
|
|
15
|
+
/**
|
|
16
|
+
* Génère de l'audio en streaming
|
|
17
|
+
*/
|
|
18
|
+
generateAudioStream(options: AudioGenerationOptions): AsyncIterable<Buffer>;
|
|
19
|
+
/**
|
|
20
|
+
* Retourne la liste des voix supportées
|
|
21
|
+
*/
|
|
22
|
+
getSupportedVoices(): Promise<string[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Construit la configuration audio pour l'API Gemini
|
|
25
|
+
*/
|
|
26
|
+
private buildAudioConfig;
|
|
27
|
+
/**
|
|
28
|
+
* Génère de l'audio multi-voix avec parsing automatique du texte
|
|
29
|
+
*/
|
|
30
|
+
generateMultiSpeakerAudio(text: string, speakers: SpeakerConfig[], outputPath?: string): Promise<AudioGenerationResponse>;
|
|
31
|
+
/**
|
|
32
|
+
* Génère de l'audio simple avec une seule voix
|
|
33
|
+
*/
|
|
34
|
+
generateSingleVoiceAudio(text: string, voiceConfig: VoiceConfig, outputPath?: string): Promise<AudioGenerationResponse>;
|
|
35
|
+
/**
|
|
36
|
+
* Sauvegarde automatique avec nom de fichier généré
|
|
37
|
+
*/
|
|
38
|
+
generateAudioWithAutoSave(options: Omit<AudioGenerationOptions, 'outputPath'>, outputDirectory?: string): Promise<AudioGenerationResponse>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=GeminiAudioAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeminiAudioAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/gemini/GeminiAudioAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AASjH,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,EAAE,yBAAyB;IAO9C;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA2EtF;;OAEG;IACI,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,GAAG,aAAa,CAAC,MAAM,CAAC;IAyClF;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAc7C;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkCxB;;OAEG;IACG,yBAAyB,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,aAAa,EAAE,EACzB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,uBAAuB,CAAC;IAWnC;;OAEG;IACG,wBAAwB,CAC5B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,WAAW,EACxB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,uBAAuB,CAAC;IAWnC;;OAEG;IACG,yBAAyB,CAC7B,OAAO,EAAE,IAAI,CAAC,sBAAsB,EAAE,YAAY,CAAC,EACnD,eAAe,GAAE,MAAyB,GACzC,OAAO,CAAC,uBAAuB,CAAC;CASpC"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
18
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
19
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
20
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
21
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
22
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
23
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
24
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
25
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
26
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
27
|
+
function fulfill(value) { resume("next", value); }
|
|
28
|
+
function reject(value) { resume("throw", value); }
|
|
29
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.GeminiAudioAdapter = void 0;
|
|
33
|
+
const genai_1 = require("@google/genai");
|
|
34
|
+
const audioUtils_1 = require("../../utils/audioUtils");
|
|
35
|
+
class GeminiAudioAdapter {
|
|
36
|
+
constructor(options) {
|
|
37
|
+
this.client = new genai_1.GoogleGenAI({
|
|
38
|
+
apiKey: options.apiKey
|
|
39
|
+
});
|
|
40
|
+
this.model = options.model || 'gemini-2.5-pro-preview-tts';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Génère de l'audio à partir de texte
|
|
44
|
+
*/
|
|
45
|
+
generateAudio(options) {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
var _a, e_1, _b, _c;
|
|
48
|
+
var _d, _e, _f;
|
|
49
|
+
try {
|
|
50
|
+
// Configuration de base
|
|
51
|
+
const config = this.buildAudioConfig(options);
|
|
52
|
+
// Contenu de la requête
|
|
53
|
+
const contents = [{
|
|
54
|
+
role: 'user',
|
|
55
|
+
parts: [{
|
|
56
|
+
text: options.multiSpeaker ? options.text : `Read aloud in a warm, welcoming tone: ${options.text}`
|
|
57
|
+
}]
|
|
58
|
+
}];
|
|
59
|
+
// Génération de l'audio
|
|
60
|
+
const response = yield this.client.models.generateContentStream({
|
|
61
|
+
model: this.model,
|
|
62
|
+
config,
|
|
63
|
+
contents
|
|
64
|
+
});
|
|
65
|
+
// Collecter les chunks audio
|
|
66
|
+
const audioChunks = [];
|
|
67
|
+
let finalMimeType = 'audio/wav';
|
|
68
|
+
let rawResponse = null;
|
|
69
|
+
try {
|
|
70
|
+
for (var _g = true, response_1 = __asyncValues(response), response_1_1; response_1_1 = yield response_1.next(), _a = response_1_1.done, !_a; _g = true) {
|
|
71
|
+
_c = response_1_1.value;
|
|
72
|
+
_g = false;
|
|
73
|
+
const chunk = _c;
|
|
74
|
+
if (!((_f = (_e = (_d = chunk.candidates) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content) === null || _f === void 0 ? void 0 : _f.parts))
|
|
75
|
+
continue;
|
|
76
|
+
const inlineData = chunk.candidates[0].content.parts[0].inlineData;
|
|
77
|
+
if (inlineData === null || inlineData === void 0 ? void 0 : inlineData.data) {
|
|
78
|
+
rawResponse = chunk;
|
|
79
|
+
finalMimeType = inlineData.mimeType || 'audio/wav';
|
|
80
|
+
let audioBuffer;
|
|
81
|
+
// Convertir au format WAV si nécessaire
|
|
82
|
+
const extension = (0, audioUtils_1.getAttachedFileExtension)(finalMimeType);
|
|
83
|
+
if (extension === 'wav' && finalMimeType !== 'audio/wav') {
|
|
84
|
+
audioBuffer = (0, audioUtils_1.convertToWav)(inlineData.data, finalMimeType);
|
|
85
|
+
finalMimeType = 'audio/wav';
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
audioBuffer = Buffer.from(inlineData.data, 'base64');
|
|
89
|
+
}
|
|
90
|
+
audioChunks.push(audioBuffer);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
95
|
+
finally {
|
|
96
|
+
try {
|
|
97
|
+
if (!_g && !_a && (_b = response_1.return)) yield _b.call(response_1);
|
|
98
|
+
}
|
|
99
|
+
finally { if (e_1) throw e_1.error; }
|
|
100
|
+
}
|
|
101
|
+
if (audioChunks.length === 0) {
|
|
102
|
+
throw new Error('Aucun contenu audio généré par l\'API');
|
|
103
|
+
}
|
|
104
|
+
// Combiner tous les chunks
|
|
105
|
+
const finalAudioData = Buffer.concat(audioChunks);
|
|
106
|
+
// Sauvegarder le fichier si un chemin est fourni
|
|
107
|
+
let filePath;
|
|
108
|
+
if (options.outputPath) {
|
|
109
|
+
const validatedPath = (0, audioUtils_1.validateOutputPath)(options.outputPath);
|
|
110
|
+
yield (0, audioUtils_1.saveAttachedFile)(validatedPath, finalAudioData);
|
|
111
|
+
filePath = validatedPath;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
audioData: finalAudioData,
|
|
115
|
+
mimeType: finalMimeType,
|
|
116
|
+
filePath,
|
|
117
|
+
raw: rawResponse
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
throw new Error(`Erreur lors de la génération audio Gemini: ${error instanceof Error ? error.message : String(error)}`);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Génère de l'audio en streaming
|
|
127
|
+
*/
|
|
128
|
+
generateAudioStream(options) {
|
|
129
|
+
return __asyncGenerator(this, arguments, function* generateAudioStream_1() {
|
|
130
|
+
var _a, e_2, _b, _c;
|
|
131
|
+
var _d, _e, _f;
|
|
132
|
+
try {
|
|
133
|
+
const config = this.buildAudioConfig(options);
|
|
134
|
+
const contents = [{
|
|
135
|
+
role: 'user',
|
|
136
|
+
parts: [{
|
|
137
|
+
text: options.multiSpeaker ? options.text : `Read aloud in a warm, welcoming tone: ${options.text}`
|
|
138
|
+
}]
|
|
139
|
+
}];
|
|
140
|
+
const response = yield __await(this.client.models.generateContentStream({
|
|
141
|
+
model: this.model,
|
|
142
|
+
config,
|
|
143
|
+
contents
|
|
144
|
+
}));
|
|
145
|
+
try {
|
|
146
|
+
for (var _g = true, response_2 = __asyncValues(response), response_2_1; response_2_1 = yield __await(response_2.next()), _a = response_2_1.done, !_a; _g = true) {
|
|
147
|
+
_c = response_2_1.value;
|
|
148
|
+
_g = false;
|
|
149
|
+
const chunk = _c;
|
|
150
|
+
if (!((_f = (_e = (_d = chunk.candidates) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content) === null || _f === void 0 ? void 0 : _f.parts))
|
|
151
|
+
continue;
|
|
152
|
+
const inlineData = chunk.candidates[0].content.parts[0].inlineData;
|
|
153
|
+
if (inlineData === null || inlineData === void 0 ? void 0 : inlineData.data) {
|
|
154
|
+
const mimeType = inlineData.mimeType || 'audio/wav';
|
|
155
|
+
let audioBuffer;
|
|
156
|
+
const extension = (0, audioUtils_1.getAttachedFileExtension)(mimeType);
|
|
157
|
+
if (extension === 'wav' && mimeType !== 'audio/wav') {
|
|
158
|
+
audioBuffer = (0, audioUtils_1.convertToWav)(inlineData.data, mimeType);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
audioBuffer = Buffer.from(inlineData.data, 'base64');
|
|
162
|
+
}
|
|
163
|
+
yield yield __await(audioBuffer);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
168
|
+
finally {
|
|
169
|
+
try {
|
|
170
|
+
if (!_g && !_a && (_b = response_2.return)) yield __await(_b.call(response_2));
|
|
171
|
+
}
|
|
172
|
+
finally { if (e_2) throw e_2.error; }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
throw new Error(`Erreur lors du streaming audio Gemini: ${error instanceof Error ? error.message : String(error)}`);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Retourne la liste des voix supportées
|
|
182
|
+
*/
|
|
183
|
+
getSupportedVoices() {
|
|
184
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
185
|
+
// En réalité, cette liste pourrait être récupérée via une API dédiée si disponible
|
|
186
|
+
return [
|
|
187
|
+
'enceladus', // Voix masculine
|
|
188
|
+
'gacrux', // Voix féminine
|
|
189
|
+
'proxima', // Voix neutre
|
|
190
|
+
'charon', // Voix grave
|
|
191
|
+
'europa', // Voix claire
|
|
192
|
+
'titan', // Voix profonde
|
|
193
|
+
'astra', // Voix énergique
|
|
194
|
+
'nova' // Voix douce
|
|
195
|
+
];
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Construit la configuration audio pour l'API Gemini
|
|
200
|
+
*/
|
|
201
|
+
buildAudioConfig(options) {
|
|
202
|
+
var _a, _b;
|
|
203
|
+
const config = {
|
|
204
|
+
temperature: ((_a = options.voiceConfig) === null || _a === void 0 ? void 0 : _a.temperature) || 1.3,
|
|
205
|
+
responseModalities: ['audio']
|
|
206
|
+
};
|
|
207
|
+
if (options.multiSpeaker && options.speakers && options.speakers.length > 0) {
|
|
208
|
+
// Configuration multi-voix
|
|
209
|
+
config.speechConfig = {
|
|
210
|
+
multiSpeakerVoiceConfig: {
|
|
211
|
+
speakerVoiceConfigs: options.speakers.map(speaker => ({
|
|
212
|
+
speaker: speaker.speaker,
|
|
213
|
+
voiceConfig: {
|
|
214
|
+
prebuiltVoiceConfig: {
|
|
215
|
+
voiceName: speaker.voiceConfig.voiceName
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}))
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
else if ((_b = options.voiceConfig) === null || _b === void 0 ? void 0 : _b.voiceName) {
|
|
223
|
+
// Configuration voix simple
|
|
224
|
+
config.speechConfig = {
|
|
225
|
+
voiceConfig: {
|
|
226
|
+
prebuiltVoiceConfig: {
|
|
227
|
+
voiceName: options.voiceConfig.voiceName
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return config;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Génère de l'audio multi-voix avec parsing automatique du texte
|
|
236
|
+
*/
|
|
237
|
+
generateMultiSpeakerAudio(text, speakers, outputPath) {
|
|
238
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
+
const options = {
|
|
240
|
+
text,
|
|
241
|
+
outputPath,
|
|
242
|
+
multiSpeaker: true,
|
|
243
|
+
speakers
|
|
244
|
+
};
|
|
245
|
+
return this.generateAudio(options);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Génère de l'audio simple avec une seule voix
|
|
250
|
+
*/
|
|
251
|
+
generateSingleVoiceAudio(text, voiceConfig, outputPath) {
|
|
252
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
253
|
+
const options = {
|
|
254
|
+
text,
|
|
255
|
+
outputPath,
|
|
256
|
+
voiceConfig,
|
|
257
|
+
multiSpeaker: false
|
|
258
|
+
};
|
|
259
|
+
return this.generateAudio(options);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Sauvegarde automatique avec nom de fichier généré
|
|
264
|
+
*/
|
|
265
|
+
generateAudioWithAutoSave(options_1) {
|
|
266
|
+
return __awaiter(this, arguments, void 0, function* (options, outputDirectory = './audio-output') {
|
|
267
|
+
const filename = (0, audioUtils_1.generateUniqueAttachedFilename)('gemini-tts', 'wav');
|
|
268
|
+
const fullPath = `${outputDirectory}/${filename}`;
|
|
269
|
+
return this.generateAudio(Object.assign(Object.assign({}, options), { outputPath: fullPath }));
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
exports.GeminiAudioAdapter = GeminiAudioAdapter;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UnifiedLog } from "../../common/types";
|
|
2
|
+
import { LogAdapter, LogData } from "../../core/LLMAdapter";
|
|
3
|
+
export declare class GeminiLogAdapter implements LogAdapter {
|
|
4
|
+
toUnifiedLog(data: LogData): UnifiedLog;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=GeminiLogAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeminiLogAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/gemini/GeminiLogAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAY,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAI5D,qBAAa,gBAAiB,YAAW,UAAU;IACjD,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU;CAsCxC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GeminiLogAdapter = void 0;
|
|
4
|
+
class GeminiLogAdapter {
|
|
5
|
+
toUnifiedLog(data) {
|
|
6
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
7
|
+
const { model, provider, messages, response, latencyMs, metadata } = data;
|
|
8
|
+
const usage = response.usage;
|
|
9
|
+
// Récupération de la structure brute de Gemini
|
|
10
|
+
const usageMetadata = (((_a = response.raw) === null || _a === void 0 ? void 0 : _a.usageMetadata) || ((_c = (_b = response.raw) === null || _b === void 0 ? void 0 : _b.response) === null || _c === void 0 ? void 0 : _c.usageMetadata));
|
|
11
|
+
return {
|
|
12
|
+
requestId: ((_d = response.raw) === null || _d === void 0 ? void 0 : _d.requestId) || `gemini-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
13
|
+
timestamp: new Date(),
|
|
14
|
+
provider: provider,
|
|
15
|
+
model: model,
|
|
16
|
+
prompt: messages,
|
|
17
|
+
output: {
|
|
18
|
+
content: response.content,
|
|
19
|
+
toolCalls: response.toolCalls,
|
|
20
|
+
finishReason: response.finishReason,
|
|
21
|
+
},
|
|
22
|
+
usage: {
|
|
23
|
+
promptTokens: (usage === null || usage === void 0 ? void 0 : usage.promptTokens) || 0,
|
|
24
|
+
completionTokens: (usage === null || usage === void 0 ? void 0 : usage.completionTokens) || 0,
|
|
25
|
+
totalTokens: (usage === null || usage === void 0 ? void 0 : usage.totalTokens) || 0,
|
|
26
|
+
promptDetails: {
|
|
27
|
+
textTokens: ((_f = (_e = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.promptTokensDetails) === null || _e === void 0 ? void 0 : _e.find(d => d.modality === 'TEXT')) === null || _f === void 0 ? void 0 : _f.tokenCount) || (usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.promptTokenCount),
|
|
28
|
+
audioTokens: (_h = (_g = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.promptTokensDetails) === null || _g === void 0 ? void 0 : _g.find(d => d.modality === 'AUDIO')) === null || _h === void 0 ? void 0 : _h.tokenCount,
|
|
29
|
+
imageTokens: (_k = (_j = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.promptTokensDetails) === null || _j === void 0 ? void 0 : _j.find(d => d.modality === 'IMAGE')) === null || _k === void 0 ? void 0 : _k.tokenCount,
|
|
30
|
+
cachedTokens: (usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.cachedContentTokenCount) || 0,
|
|
31
|
+
},
|
|
32
|
+
completionDetails: {
|
|
33
|
+
textTokens: ((_m = (_l = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.candidatesTokensDetails) === null || _l === void 0 ? void 0 : _l.find(d => d.modality === 'TEXT')) === null || _m === void 0 ? void 0 : _m.tokenCount) || (usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.candidatesTokenCount),
|
|
34
|
+
audioTokens: (_p = (_o = usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.candidatesTokensDetails) === null || _o === void 0 ? void 0 : _o.find(d => d.modality === 'AUDIO')) === null || _p === void 0 ? void 0 : _p.tokenCount,
|
|
35
|
+
thinkingTokens: (usageMetadata === null || usageMetadata === void 0 ? void 0 : usageMetadata.thoughtsTokenCount) || 0,
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
latencyMs: latencyMs,
|
|
39
|
+
metadata: metadata,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.GeminiLogAdapter = GeminiLogAdapter;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ChatResponse } from "../../common/types";
|
|
2
|
+
import { OutputAdapter } from "../../core/LLMAdapter";
|
|
3
|
+
export declare class GeminiOutputAdapter implements OutputAdapter {
|
|
4
|
+
parse(providerResponse: any): ChatResponse;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=GeminiOutputAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeminiOutputAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/gemini/GeminiOutputAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAY,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,qBAAa,mBAAoB,YAAW,aAAa;IAChD,KAAK,CAAC,gBAAgB,EAAE,GAAG,GAAG,YAAY;CAoClD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GeminiOutputAdapter = void 0;
|
|
4
|
+
class GeminiOutputAdapter {
|
|
5
|
+
parse(providerResponse) {
|
|
6
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
7
|
+
const functionCalls = [];
|
|
8
|
+
const parts = (_c = (_b = (_a = providerResponse.raw.candidates) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.parts;
|
|
9
|
+
if (!parts) {
|
|
10
|
+
const finishReason = (_e = (_d = providerResponse.raw.candidates) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.finishReason;
|
|
11
|
+
throw new Error(`Gemini returned no content parts${finishReason ? ` (finishReason: ${finishReason})` : ''}`);
|
|
12
|
+
}
|
|
13
|
+
parts.forEach((part) => {
|
|
14
|
+
if (part.functionCall) {
|
|
15
|
+
functionCalls.push({
|
|
16
|
+
id: part.functionCall.id,
|
|
17
|
+
name: part.functionCall.name,
|
|
18
|
+
arguments: part.functionCall.args,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
if (functionCalls.length > 0) {
|
|
23
|
+
providerResponse.toolCalls = functionCalls;
|
|
24
|
+
}
|
|
25
|
+
const usageMetadata = providerResponse.raw.usageMetadata || ((_f = providerResponse.raw.response) === null || _f === void 0 ? void 0 : _f.usageMetadata);
|
|
26
|
+
if (usageMetadata) {
|
|
27
|
+
providerResponse.usage = {
|
|
28
|
+
promptTokens: usageMetadata.promptTokenCount || 0,
|
|
29
|
+
completionTokens: usageMetadata.candidatesTokenCount || 0,
|
|
30
|
+
totalTokens: usageMetadata.totalTokenCount || 0,
|
|
31
|
+
promptTokensDetails: usageMetadata.promptTokensDetails || [],
|
|
32
|
+
thoughtsToken: usageMetadata.thoughtsTokenCount || 0,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return Object.assign(Object.assign({}, providerResponse), { lastToolArguments: ((_g = functionCalls[0]) === null || _g === void 0 ? void 0 : _g.arguments) || {} });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.GeminiOutputAdapter = GeminiOutputAdapter;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Content } from "@google/genai";
|
|
2
|
+
import { PromptAdapterOptions, ChatMessage, ChatResponse, ToolDefinition } from "../..";
|
|
3
|
+
import { ChatOptionalConfig, ChatStreamOptions, PromptAdapter } from "../../core/LLMAdapter";
|
|
4
|
+
export declare class GeminiPromptAdapter implements PromptAdapter {
|
|
5
|
+
private genAI;
|
|
6
|
+
private opts;
|
|
7
|
+
constructor(opts: PromptAdapterOptions);
|
|
8
|
+
formatMessage(message: ChatMessage): Promise<Content>;
|
|
9
|
+
sendToProvider(messages: any, tools?: ToolDefinition[], toolChoice?: "auto" | "none" | string, attachedFile?: string | string[], model?: string, config?: ChatOptionalConfig): Promise<ChatResponse>;
|
|
10
|
+
/**
|
|
11
|
+
* Initiates a streaming chat session with the Gemini model.
|
|
12
|
+
*
|
|
13
|
+
* This method sends the conversation history and any specified tools to the Gemini API
|
|
14
|
+
* and returns an asynchronous iterable that yields chunks of the response as they become available.
|
|
15
|
+
* It also provides a way to retrieve the final aggregated response metadata once the stream completes.
|
|
16
|
+
*
|
|
17
|
+
* @param messages An array of `ChatMessage` objects representing the conversation history.
|
|
18
|
+
* @param tools Optional. An array of `ToolDefinition` objects that the LLM can use.
|
|
19
|
+
* @param toolChoice Optional. Controls how the LLM uses tools: "auto", "none", or a specific tool name.
|
|
20
|
+
* @returns A `StreamingChatResult` object containing the stream of `StreamedChatChunk` and a function `getFinalResponse`
|
|
21
|
+
* to retrieve the final response metadata (excluding content, which is streamed).
|
|
22
|
+
* @throws Error if the Gemini API key is not configured or if the underlying SDK call fails.
|
|
23
|
+
*/
|
|
24
|
+
streamFromProvider?({ messages, tools, toolChoice, model, onChunk, onFinalResponse, config, }: ChatStreamOptions): Promise<ChatResponse>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=GeminiPromptAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeminiPromptAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/gemini/GeminiPromptAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,OAAO,EAUR,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,YAAY,EAAY,cAAc,EAAE,MAAM,OAAO,CAAC;AAClG,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,aAAa,EAA0C,MAAM,uBAAuB,CAAC;AAGrI,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,IAAI,CAAuB;gBACvB,IAAI,EAAE,oBAAoB;IAQzB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAmE5D,cAAc,CAClB,QAAQ,EAAE,GAAG,EACb,KAAK,GAAE,cAAc,EAAO,EAC5B,UAAU,GAAE,MAAM,GAAG,MAAM,GAAG,MAAe,EAC7C,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAChC,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC;IA6DxB;;;;;;;;;;;;;OAaG;IACG,kBAAkB,CAAC,CAAC,EACxB,QAAQ,EACR,KAAK,EACL,UAAU,EACV,KAAK,EACL,OAAO,EACP,eAAe,EACf,MAAM,GACP,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;CAiI7C"}
|