@contentgrowth/llm-service 1.1.2 → 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/dist/index.cjs +93 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -91
- package/dist/index.d.ts +145 -91
- package/dist/index.js +91 -86
- package/dist/index.js.map +1 -1
- package/package.json +16 -14
package/dist/index.js
CHANGED
|
@@ -71,8 +71,10 @@ var DefaultConfigProvider = class extends BaseConfigProvider {
|
|
|
71
71
|
_buildTenantConfig(tenantConfig, env) {
|
|
72
72
|
return {
|
|
73
73
|
provider: tenantConfig.provider,
|
|
74
|
-
apiKey: tenantConfig.api_key,
|
|
75
74
|
models: MODEL_CONFIGS[tenantConfig.provider],
|
|
75
|
+
apiKey: tenantConfig.api_key,
|
|
76
|
+
project: tenantConfig.project,
|
|
77
|
+
location: tenantConfig.location,
|
|
76
78
|
temperature: parseFloat(env.DEFAULT_TEMPERATURE || "0.7"),
|
|
77
79
|
maxTokens: parseInt(env.DEFAULT_MAX_TOKENS || "65536"),
|
|
78
80
|
capabilities: tenantConfig.capabilities || { chat: true, image: false, video: false },
|
|
@@ -105,6 +107,28 @@ var DefaultConfigProvider = class extends BaseConfigProvider {
|
|
|
105
107
|
image: env.GEMINI_IMAGE_MODEL || providerDefaults.image,
|
|
106
108
|
video: env.GEMINI_VIDEO_MODEL || providerDefaults.video
|
|
107
109
|
};
|
|
110
|
+
} else if (provider === "vertex") {
|
|
111
|
+
apiKey = env.VERTEX_API_KEY;
|
|
112
|
+
const project = env.VERTEX_PROJECT || env.GOOGLE_CLOUD_PROJECT;
|
|
113
|
+
const location = env.VERTEX_LOCATION || env.GOOGLE_CLOUD_LOCATION || "us-central1";
|
|
114
|
+
models = {
|
|
115
|
+
default: env.VERTEX_MODEL || providerDefaults.default,
|
|
116
|
+
edge: env.VERTEX_MODEL_EDGE || providerDefaults.edge,
|
|
117
|
+
fast: env.VERTEX_MODEL_FAST || providerDefaults.fast,
|
|
118
|
+
cost: env.VERTEX_MODEL_COST || providerDefaults.cost,
|
|
119
|
+
free: env.VERTEX_MODEL_FREE || providerDefaults.free,
|
|
120
|
+
image: env.VERTEX_IMAGE_MODEL || providerDefaults.image,
|
|
121
|
+
video: env.VERTEX_VIDEO_MODEL || providerDefaults.video
|
|
122
|
+
};
|
|
123
|
+
return {
|
|
124
|
+
provider,
|
|
125
|
+
apiKey,
|
|
126
|
+
project,
|
|
127
|
+
location,
|
|
128
|
+
models,
|
|
129
|
+
temperature: parseFloat(env.DEFAULT_TEMPERATURE || "0.7"),
|
|
130
|
+
maxTokens: parseInt(env.DEFAULT_MAX_TOKENS || "65536")
|
|
131
|
+
};
|
|
108
132
|
}
|
|
109
133
|
return {
|
|
110
134
|
provider,
|
|
@@ -139,6 +163,15 @@ var MODEL_CONFIGS = {
|
|
|
139
163
|
video: "veo",
|
|
140
164
|
image: "gemini-3-pro-image-preview"
|
|
141
165
|
// Default image generation model
|
|
166
|
+
},
|
|
167
|
+
vertex: {
|
|
168
|
+
default: "gemini-3-flash-preview",
|
|
169
|
+
edge: "gemini-3-pro-preview",
|
|
170
|
+
fast: "gemini-3-flash-preview",
|
|
171
|
+
cost: "gemini-3-flash-preview",
|
|
172
|
+
free: "gemini-3-flash-preview",
|
|
173
|
+
video: "veo",
|
|
174
|
+
image: "gemini-3-pro-image-preview"
|
|
142
175
|
}
|
|
143
176
|
};
|
|
144
177
|
var ConfigManager = class {
|
|
@@ -536,25 +569,43 @@ var OpenAIProvider = class extends BaseLLMProvider {
|
|
|
536
569
|
}
|
|
537
570
|
};
|
|
538
571
|
|
|
539
|
-
// src/llm/providers/
|
|
572
|
+
// src/llm/providers/google-provider.js
|
|
540
573
|
import { GoogleGenAI } from "@google/genai";
|
|
541
|
-
var
|
|
574
|
+
var GoogleProvider = class extends BaseLLMProvider {
|
|
542
575
|
constructor(config) {
|
|
543
576
|
super(config);
|
|
544
|
-
const clientConfig = {};
|
|
545
|
-
if (config.project || config.location) {
|
|
546
|
-
console.log(`[GeminiProvider] Initializing with Vertex AI (Project: ${config.project}, Location: ${config.location || "us-central1"})`);
|
|
547
|
-
clientConfig.vertexAI = {
|
|
548
|
-
project: config.project,
|
|
549
|
-
location: config.location || "us-central1"
|
|
550
|
-
};
|
|
551
|
-
} else {
|
|
552
|
-
clientConfig.apiKey = config.apiKey;
|
|
553
|
-
}
|
|
554
|
-
this.client = new GoogleGenAI(clientConfig);
|
|
555
577
|
this.models = config.models;
|
|
556
578
|
this.defaultModel = config.models.default;
|
|
557
579
|
this._pendingOperations = /* @__PURE__ */ new Map();
|
|
580
|
+
if (config.provider === "vertex") {
|
|
581
|
+
if (config.apiKey) {
|
|
582
|
+
this.client = new GoogleGenAI({
|
|
583
|
+
vertexai: true,
|
|
584
|
+
apiKey: config.apiKey
|
|
585
|
+
});
|
|
586
|
+
} else {
|
|
587
|
+
if (!config.project) {
|
|
588
|
+
console.warn("[GoogleProvider] Vertex AI: no project ID and no API key. Calls will likely fail.");
|
|
589
|
+
}
|
|
590
|
+
this.client = new GoogleGenAI({
|
|
591
|
+
vertexai: true,
|
|
592
|
+
project: config.project,
|
|
593
|
+
location: config.location || "us-central1"
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
} else {
|
|
597
|
+
this.client = new GoogleGenAI({
|
|
598
|
+
apiKey: config.apiKey
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Perform the actual API call. Both AI Studio and Vertex AI use the
|
|
604
|
+
* same @google/genai SDK method — the routing is determined by how
|
|
605
|
+
* the client was constructed.
|
|
606
|
+
*/
|
|
607
|
+
async _generateContent(requestOptions) {
|
|
608
|
+
return this.client.models.generateContent(requestOptions);
|
|
558
609
|
}
|
|
559
610
|
async chat(userMessage, systemPrompt = "", options = {}) {
|
|
560
611
|
const messages = [{ role: "user", content: userMessage }];
|
|
@@ -694,18 +745,12 @@ ${msg.content}`;
|
|
|
694
745
|
if (tools && tools.length > 0) {
|
|
695
746
|
requestOptions.config.tools = [{ functionDeclarations: tools.map((t) => t.function) }];
|
|
696
747
|
if (requestOptions.config.responseMimeType === "application/json") {
|
|
697
|
-
console.warn(
|
|
748
|
+
console.warn(`[${this.constructor.name}] Disabling strict JSON mode because tools are present. Relying on system prompt.`);
|
|
698
749
|
delete requestOptions.config.responseMimeType;
|
|
699
750
|
delete requestOptions.config.responseSchema;
|
|
700
751
|
}
|
|
701
752
|
}
|
|
702
|
-
|
|
703
|
-
try {
|
|
704
|
-
response = await this.client.models.generateContent(requestOptions);
|
|
705
|
-
} catch (error) {
|
|
706
|
-
console.error(`[GeminiProvider] generateContent failed (API Key: ${this._getMaskedApiKey()}):`, error);
|
|
707
|
-
throw error;
|
|
708
|
-
}
|
|
753
|
+
const response = await this._generateContent(requestOptions);
|
|
709
754
|
const candidate = (_c = response.candidates) == null ? void 0 : _c[0];
|
|
710
755
|
if (!candidate) {
|
|
711
756
|
throw new LLMServiceException("No candidates returned from model", 500);
|
|
@@ -735,10 +780,8 @@ ${msg.content}`;
|
|
|
735
780
|
}
|
|
736
781
|
}
|
|
737
782
|
if (!textContent && (!toolCalls || toolCalls.length === 0)) {
|
|
738
|
-
console.error(
|
|
739
|
-
console.error(
|
|
740
|
-
console.error("[GeminiProvider] Safety Ratings:", JSON.stringify(candidate.safetyRatings, null, 2));
|
|
741
|
-
console.error("[GeminiProvider] Full Candidate:", JSON.stringify(candidate, null, 2));
|
|
783
|
+
console.error(`[${this.constructor.name}] Model returned empty response (no text, no tool calls)`);
|
|
784
|
+
console.error(`[${this.constructor.name}] Finish Reason:`, candidate.finishReason);
|
|
742
785
|
throw new LLMServiceException(
|
|
743
786
|
`Model returned empty response. Finish Reason: ${candidate.finishReason}.`,
|
|
744
787
|
500
|
|
@@ -748,18 +791,14 @@ ${msg.content}`;
|
|
|
748
791
|
return {
|
|
749
792
|
content: textContent,
|
|
750
793
|
thought_signature: responseThoughtSignature,
|
|
751
|
-
// Return signature to caller
|
|
752
794
|
tool_calls: toolCalls ? (Array.isArray(toolCalls) ? toolCalls : [toolCalls]).map((fc) => ({
|
|
753
795
|
type: "function",
|
|
754
796
|
function: fc,
|
|
755
797
|
thought_signature: fc.thought_signature
|
|
756
798
|
})) : null,
|
|
757
799
|
finishReason: normalizedFinishReason,
|
|
758
|
-
// Standardized: 'completed', 'truncated', etc.
|
|
759
800
|
_rawFinishReason: candidate.finishReason,
|
|
760
|
-
// Keep original for debugging
|
|
761
801
|
_responseFormat: options.responseFormat,
|
|
762
|
-
// Return usage stats
|
|
763
802
|
usage: {
|
|
764
803
|
prompt_tokens: ((_e = response.usageMetadata) == null ? void 0 : _e.promptTokenCount) || 0,
|
|
765
804
|
completion_tokens: ((_f = response.usageMetadata) == null ? void 0 : _f.candidatesTokenCount) || 0,
|
|
@@ -785,7 +824,7 @@ ${msg.content}`;
|
|
|
785
824
|
if (schema) {
|
|
786
825
|
config.responseSchema = this._convertToGeminiSchema(schema);
|
|
787
826
|
} else {
|
|
788
|
-
console.warn(
|
|
827
|
+
console.warn(`[${this.constructor.name}] Using legacy JSON mode without schema - may produce markdown wrappers`);
|
|
789
828
|
}
|
|
790
829
|
}
|
|
791
830
|
}
|
|
@@ -843,8 +882,7 @@ ${msg.content}`;
|
|
|
843
882
|
if (!content) return null;
|
|
844
883
|
const parsed = extractJsonFromResponse(content);
|
|
845
884
|
if (!parsed) {
|
|
846
|
-
console.error(
|
|
847
|
-
console.error("[GeminiProvider] Content preview:", content.substring(0, 200));
|
|
885
|
+
console.error(`[${this.constructor.name}] Failed to extract valid JSON from response`);
|
|
848
886
|
}
|
|
849
887
|
return parsed;
|
|
850
888
|
}
|
|
@@ -874,9 +912,9 @@ ${msg.content}`;
|
|
|
874
912
|
toolResults.forEach((result) => messages.push({ role: "tool", tool_call_id: result.tool_call_id, content: result.output }));
|
|
875
913
|
}
|
|
876
914
|
async imageGeneration(prompt, systemPrompt, options = {}) {
|
|
877
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i
|
|
915
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
878
916
|
const modelName = options.model || this.models.image || "gemini-3-pro-image-preview";
|
|
879
|
-
console.log(`[
|
|
917
|
+
console.log(`[${this.constructor.name}] Generating image with model: ${modelName}`);
|
|
880
918
|
const hasReferenceImages = options.images && options.images.length > 0;
|
|
881
919
|
const generationConfig = {
|
|
882
920
|
responseModalities: hasReferenceImages ? ["TEXT", "IMAGE"] : ["IMAGE"]
|
|
@@ -908,7 +946,7 @@ ${msg.content}`;
|
|
|
908
946
|
if (systemPrompt) {
|
|
909
947
|
requestOptions.config.systemInstruction = { parts: [{ text: systemPrompt }] };
|
|
910
948
|
}
|
|
911
|
-
const response = await this.
|
|
949
|
+
const response = await this._generateContent(requestOptions);
|
|
912
950
|
const imagePart = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d.find(
|
|
913
951
|
(part) => {
|
|
914
952
|
var _a2;
|
|
@@ -916,30 +954,21 @@ ${msg.content}`;
|
|
|
916
954
|
}
|
|
917
955
|
);
|
|
918
956
|
if (!imagePart || !imagePart.inlineData) {
|
|
919
|
-
const
|
|
920
|
-
|
|
921
|
-
console.error("[GeminiProvider] Image generation failed (no image data)");
|
|
922
|
-
if (candidate) {
|
|
923
|
-
console.error("[GeminiProvider] Finish Reason:", candidate.finishReason);
|
|
924
|
-
console.error("[GeminiProvider] Safety Ratings:", JSON.stringify(candidate.safetyRatings, null, 2));
|
|
925
|
-
console.error("[GeminiProvider] Full Candidate:", JSON.stringify(candidate, null, 2));
|
|
926
|
-
}
|
|
927
|
-
if (textPart) {
|
|
928
|
-
console.warn("[GeminiProvider] Model returned text instead of image:", textPart.text);
|
|
929
|
-
}
|
|
957
|
+
const candidate = (_e = response.candidates) == null ? void 0 : _e[0];
|
|
958
|
+
console.error(`[${this.constructor.name}] Image generation failed (no image data)`);
|
|
930
959
|
throw new Error(`No image data in response. Finish Reason: ${candidate == null ? void 0 : candidate.finishReason}`);
|
|
931
960
|
}
|
|
932
961
|
let thoughtSignature = null;
|
|
933
962
|
if (imagePart.thought_signature || imagePart.thoughtSignature) {
|
|
934
963
|
thoughtSignature = imagePart.thought_signature || imagePart.thoughtSignature;
|
|
935
964
|
} else {
|
|
936
|
-
const signaturePart = (
|
|
965
|
+
const signaturePart = (_i = (_h = (_g = (_f = response.candidates) == null ? void 0 : _f[0]) == null ? void 0 : _g.content) == null ? void 0 : _h.parts) == null ? void 0 : _i.find((p) => p.thought_signature || p.thoughtSignature);
|
|
937
966
|
if (signaturePart) {
|
|
938
967
|
thoughtSignature = signaturePart.thought_signature || signaturePart.thoughtSignature;
|
|
939
968
|
}
|
|
940
969
|
}
|
|
941
970
|
if (thoughtSignature && thoughtSignature.length > 5e4) {
|
|
942
|
-
console.warn(`[
|
|
971
|
+
console.warn(`[${this.constructor.name}] \u26A0\uFE0F Thought signature is abnormally large (${thoughtSignature.length} chars). Replacing with bypass token.`);
|
|
943
972
|
thoughtSignature = "skip_thought_signature_validator";
|
|
944
973
|
}
|
|
945
974
|
return {
|
|
@@ -962,31 +991,20 @@ ${prompt}` : prompt;
|
|
|
962
991
|
durationSeconds: options.durationSeconds || 6,
|
|
963
992
|
aspectRatio: options.aspectRatio || "16:9",
|
|
964
993
|
numberOfVideos: 1,
|
|
965
|
-
// Pass reference images if provided
|
|
966
994
|
...images && images.length > 0 ? { referenceImages: images } : {}
|
|
967
995
|
}
|
|
968
996
|
};
|
|
969
|
-
const logConfig = JSON.parse(JSON.stringify(requestConfig));
|
|
970
|
-
if (logConfig.config && logConfig.config.referenceImages) {
|
|
971
|
-
logConfig.config.referenceImages = logConfig.config.referenceImages.map((img) => ({
|
|
972
|
-
...img,
|
|
973
|
-
data: `... (${img.data ? img.data.length : 0} bytes)`
|
|
974
|
-
// Summarize data
|
|
975
|
-
}));
|
|
976
|
-
}
|
|
977
|
-
console.log("[GeminiProvider] startVideoGeneration request:", JSON.stringify(logConfig, null, 2));
|
|
978
997
|
try {
|
|
979
998
|
const operation = await this.client.models.generateVideos(requestConfig);
|
|
980
999
|
this._pendingOperations.set(operation.name, operation);
|
|
981
1000
|
return { operationName: operation.name };
|
|
982
1001
|
} catch (error) {
|
|
983
|
-
console.error(`[
|
|
1002
|
+
console.error(`[${this.constructor.name}] startVideoGeneration failed (API Key: ${this._getMaskedApiKey()}):`, error);
|
|
984
1003
|
throw error;
|
|
985
1004
|
}
|
|
986
1005
|
}
|
|
987
1006
|
async getVideoGenerationStatus(operationName) {
|
|
988
1007
|
var _a, _b, _c, _d, _e, _f;
|
|
989
|
-
console.log(`[GeminiProvider] Checking status for operation: ${operationName}`);
|
|
990
1008
|
let operation = this._pendingOperations.get(operationName);
|
|
991
1009
|
if (!operation) {
|
|
992
1010
|
operation = await this.client.models.getOperation(operationName);
|
|
@@ -998,11 +1016,9 @@ ${prompt}` : prompt;
|
|
|
998
1016
|
progress: ((_a = operation.metadata) == null ? void 0 : _a.progressPercent) || 0,
|
|
999
1017
|
state: ((_b = operation.metadata) == null ? void 0 : _b.state) || (operation.done ? "COMPLETED" : "PROCESSING")
|
|
1000
1018
|
};
|
|
1001
|
-
console.log(`[GeminiProvider] Operation status: ${result.state}, Progress: ${result.progress}%`);
|
|
1002
1019
|
if (operation.done) {
|
|
1003
1020
|
this._pendingOperations.delete(operationName);
|
|
1004
1021
|
if (operation.error) {
|
|
1005
|
-
console.error("[GeminiProvider] Video generation failed:", JSON.stringify(operation.error, null, 2));
|
|
1006
1022
|
result.error = operation.error;
|
|
1007
1023
|
} else {
|
|
1008
1024
|
const videoResult = operation.response;
|
|
@@ -1014,20 +1030,17 @@ ${prompt}` : prompt;
|
|
|
1014
1030
|
}
|
|
1015
1031
|
async startDeepResearch(prompt, options = {}) {
|
|
1016
1032
|
const agent = options.agent || "deep-research-pro-preview-12-2025";
|
|
1017
|
-
console.log(`[
|
|
1033
|
+
console.log(`[${this.constructor.name}] Starting Deep Research with agent: ${agent}`);
|
|
1018
1034
|
try {
|
|
1019
1035
|
const interaction = await this.client.interactions.create({
|
|
1020
1036
|
agent,
|
|
1021
1037
|
input: prompt,
|
|
1022
1038
|
background: true,
|
|
1023
|
-
// Required for long running
|
|
1024
1039
|
store: true
|
|
1025
|
-
// Required for polling
|
|
1026
1040
|
});
|
|
1027
|
-
console.log(`[GeminiProvider] Deep Research started. Interaction ID: ${interaction.id}`);
|
|
1028
1041
|
return { operationId: interaction.id };
|
|
1029
1042
|
} catch (error) {
|
|
1030
|
-
console.error(`[
|
|
1043
|
+
console.error(`[${this.constructor.name}] startDeepResearch failed:`, error);
|
|
1031
1044
|
throw error;
|
|
1032
1045
|
}
|
|
1033
1046
|
}
|
|
@@ -1046,18 +1059,10 @@ ${prompt}` : prompt;
|
|
|
1046
1059
|
}
|
|
1047
1060
|
return response;
|
|
1048
1061
|
} catch (error) {
|
|
1049
|
-
console.error(`[
|
|
1062
|
+
console.error(`[${this.constructor.name}] getDeepResearchStatus failed for ${operationId}:`, error);
|
|
1050
1063
|
throw error;
|
|
1051
1064
|
}
|
|
1052
1065
|
}
|
|
1053
|
-
/**
|
|
1054
|
-
* Extract structured data from a file (PDF, Image, etc.) using Gemini Multimodal capabilities.
|
|
1055
|
-
* @param {Buffer|string} fileData - Base64 string or Buffer of the file
|
|
1056
|
-
* @param {string} mimeType - Mime type (e.g., 'application/pdf', 'image/png')
|
|
1057
|
-
* @param {string} prompt - Extraction prompt
|
|
1058
|
-
* @param {Object} schema - JSON schema for the output
|
|
1059
|
-
* @param {Object} options - Additional options
|
|
1060
|
-
*/
|
|
1061
1066
|
async extractWithLLM(fileData, mimeType, prompt, schema = null, options = {}) {
|
|
1062
1067
|
var _a, _b, _c, _d;
|
|
1063
1068
|
const tier = options.tier || "default";
|
|
@@ -1069,9 +1074,7 @@ ${prompt}` : prompt;
|
|
|
1069
1074
|
maxTokens,
|
|
1070
1075
|
temperature
|
|
1071
1076
|
);
|
|
1072
|
-
const parts = [
|
|
1073
|
-
{ text: prompt }
|
|
1074
|
-
];
|
|
1077
|
+
const parts = [{ text: prompt }];
|
|
1075
1078
|
let base64Data = fileData;
|
|
1076
1079
|
if (typeof fileData !== "string") {
|
|
1077
1080
|
try {
|
|
@@ -1094,7 +1097,7 @@ ${prompt}` : prompt;
|
|
|
1094
1097
|
config: generationConfig
|
|
1095
1098
|
};
|
|
1096
1099
|
try {
|
|
1097
|
-
const response = await this.
|
|
1100
|
+
const response = await this._generateContent(requestOptions);
|
|
1098
1101
|
const candidate = (_a = response.candidates) == null ? void 0 : _a[0];
|
|
1099
1102
|
if (!candidate) {
|
|
1100
1103
|
throw new LLMServiceException("No candidates returned from model during extraction", 500);
|
|
@@ -1105,7 +1108,7 @@ ${prompt}` : prompt;
|
|
|
1105
1108
|
}
|
|
1106
1109
|
return textContent;
|
|
1107
1110
|
} catch (error) {
|
|
1108
|
-
console.error(`[
|
|
1111
|
+
console.error(`[${this.constructor.name}] extractWithLLM failed (API Key: ${this._getMaskedApiKey()}):`, error);
|
|
1109
1112
|
throw error;
|
|
1110
1113
|
}
|
|
1111
1114
|
}
|
|
@@ -1124,14 +1127,14 @@ var LLMService = class {
|
|
|
1124
1127
|
return this.providerCache.get(cacheKey);
|
|
1125
1128
|
}
|
|
1126
1129
|
const config = await ConfigManager.getConfig(tenantId, this.env);
|
|
1127
|
-
if (!config.apiKey) {
|
|
1130
|
+
if (!config.apiKey && config.provider !== "vertex") {
|
|
1128
1131
|
throw new LLMServiceException(`LLM service is not configured for ${config.provider}. Missing API Key.`, 500);
|
|
1129
1132
|
}
|
|
1130
1133
|
let provider;
|
|
1131
1134
|
if (config.provider === "openai") {
|
|
1132
1135
|
provider = new OpenAIProvider(config);
|
|
1133
|
-
} else if (config.provider === "gemini") {
|
|
1134
|
-
provider = new
|
|
1136
|
+
} else if (config.provider === "gemini" || config.provider === "vertex") {
|
|
1137
|
+
provider = new GoogleProvider(config);
|
|
1135
1138
|
} else {
|
|
1136
1139
|
throw new LLMServiceException(`Unsupported LLM provider: ${config.provider}`, 500);
|
|
1137
1140
|
}
|
|
@@ -1703,13 +1706,15 @@ export {
|
|
|
1703
1706
|
ConfigManager,
|
|
1704
1707
|
DefaultConfigProvider,
|
|
1705
1708
|
FINISH_REASONS,
|
|
1706
|
-
GeminiProvider,
|
|
1709
|
+
GoogleProvider as GeminiProvider,
|
|
1710
|
+
GoogleProvider,
|
|
1707
1711
|
LLMService,
|
|
1708
1712
|
LLMServiceException,
|
|
1709
1713
|
MODEL_CONFIGS,
|
|
1710
1714
|
OpenAIProvider,
|
|
1711
1715
|
TranscriptionService,
|
|
1712
1716
|
TranscriptionServiceException,
|
|
1717
|
+
GoogleProvider as VertexProvider,
|
|
1713
1718
|
createSpeechHandler,
|
|
1714
1719
|
extractJsonFromResponse,
|
|
1715
1720
|
extractTextAndJson,
|