@bonginkan/maria 4.3.8 → 4.3.10
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/README.md +5 -5
- package/dist/READY.manifest.json +1 -1
- package/dist/bin/maria.cjs +5536 -1990
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +7137 -3591
- package/dist/cli.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/server/express-server.cjs +331 -257
- package/dist/server/express-server.js +331 -257
- package/dist/server-express.cjs +331 -257
- package/dist/server-express.cjs.map +1 -1
- package/package.json +2 -2
- package/src/slash-commands/READY.manifest.json +1 -1
package/dist/server-express.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
var secretManager = require('@google-cloud/secret-manager');
|
|
4
5
|
var fs = require('fs');
|
|
5
6
|
var path = require('path');
|
|
6
7
|
var Stream = require('stream');
|
|
@@ -19,7 +20,6 @@ var auth = require('firebase-admin/auth');
|
|
|
19
20
|
var fsp = require('fs/promises');
|
|
20
21
|
var crypto = require('crypto');
|
|
21
22
|
var child_process = require('child_process');
|
|
22
|
-
var secretManager = require('@google-cloud/secret-manager');
|
|
23
23
|
var events = require('events');
|
|
24
24
|
var generativeAi = require('@google/generative-ai');
|
|
25
25
|
var OpenAI = require('openai');
|
|
@@ -99,6 +99,267 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
99
99
|
mod
|
|
100
100
|
));
|
|
101
101
|
|
|
102
|
+
// src/services/intelligent-model-selector/SecretManagerIntegration.ts
|
|
103
|
+
var SecretManagerIntegration_exports = {};
|
|
104
|
+
__export(SecretManagerIntegration_exports, {
|
|
105
|
+
SecretManagerIntegration: () => SecretManagerIntegration
|
|
106
|
+
});
|
|
107
|
+
var SecretManagerIntegration;
|
|
108
|
+
var init_SecretManagerIntegration = __esm({
|
|
109
|
+
"src/services/intelligent-model-selector/SecretManagerIntegration.ts"() {
|
|
110
|
+
SecretManagerIntegration = class {
|
|
111
|
+
constructor(config) {
|
|
112
|
+
this.config = config;
|
|
113
|
+
this.useGsm = this.shouldUseGsm();
|
|
114
|
+
}
|
|
115
|
+
client = null;
|
|
116
|
+
cache = /* @__PURE__ */ new Map();
|
|
117
|
+
cacheExpiry = /* @__PURE__ */ new Map();
|
|
118
|
+
CACHE_TTL = 36e5;
|
|
119
|
+
// 1 hour
|
|
120
|
+
useGsm;
|
|
121
|
+
MAX_RETRIES = 3;
|
|
122
|
+
BASE_DELAY_MS = 200;
|
|
123
|
+
/** Determine whether GSM should be used in this environment */
|
|
124
|
+
shouldUseGsm() {
|
|
125
|
+
if (process.env.MARIA_DISABLE_GSM === "true") return false;
|
|
126
|
+
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) return true;
|
|
127
|
+
if (process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT) return true;
|
|
128
|
+
if (process.env.CLOUD_RUN_SERVICE || process.env.K_SERVICE) return true;
|
|
129
|
+
if (process.env.GCE_METADATA_HOST) return true;
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
/** Lazily create Secret Manager client only when permitted */
|
|
133
|
+
ensureClient() {
|
|
134
|
+
if (!this.useGsm) return null;
|
|
135
|
+
if (this.client) return this.client;
|
|
136
|
+
try {
|
|
137
|
+
this.client = new secretManager.SecretManagerServiceClient();
|
|
138
|
+
} catch {
|
|
139
|
+
this.client = null;
|
|
140
|
+
}
|
|
141
|
+
return this.client;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get API key from Secret Manager with caching
|
|
145
|
+
*/
|
|
146
|
+
async getApiKey(provider) {
|
|
147
|
+
const secretName = this.getSecretName(provider);
|
|
148
|
+
if (!secretName) {
|
|
149
|
+
return void 0;
|
|
150
|
+
}
|
|
151
|
+
const client = this.ensureClient();
|
|
152
|
+
if (!client) {
|
|
153
|
+
return this.getFallbackFromEnv(provider);
|
|
154
|
+
}
|
|
155
|
+
const valid = this.getCachedSecret(secretName);
|
|
156
|
+
if (valid) return valid;
|
|
157
|
+
const res = await this.accessWithBackoff(secretName).catch(() => void 0);
|
|
158
|
+
if (res) {
|
|
159
|
+
this.cacheSecret(secretName, res);
|
|
160
|
+
return res;
|
|
161
|
+
}
|
|
162
|
+
const stale = this.cache.get(secretName);
|
|
163
|
+
if (stale) return stale;
|
|
164
|
+
return this.getFallbackFromEnv(provider);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get all API keys
|
|
168
|
+
*/
|
|
169
|
+
async getAllApiKeys() {
|
|
170
|
+
const [googleApiKey, openaiApiKey, anthropicApiKey, groqApiKey] = await Promise.all([
|
|
171
|
+
this.getApiKey("google"),
|
|
172
|
+
this.getApiKey("openai"),
|
|
173
|
+
this.getApiKey("anthropic"),
|
|
174
|
+
this.getApiKey("groq")
|
|
175
|
+
]);
|
|
176
|
+
return {
|
|
177
|
+
googleApiKey,
|
|
178
|
+
openaiApiKey,
|
|
179
|
+
anthropicApiKey,
|
|
180
|
+
groqApiKey
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/** Fetch optional configuration values (not API keys) */
|
|
184
|
+
async getOptionalConfig() {
|
|
185
|
+
const client = this.ensureClient();
|
|
186
|
+
const read = async (name) => {
|
|
187
|
+
if (!name) return void 0;
|
|
188
|
+
if (!client) return void 0;
|
|
189
|
+
try {
|
|
190
|
+
const resName = `projects/${this.config.projectId}/secrets/${name}/versions/latest`;
|
|
191
|
+
const [version] = await client.accessSecretVersion({ name: resName });
|
|
192
|
+
const payload = version.payload?.data;
|
|
193
|
+
return payload?.toString();
|
|
194
|
+
} catch {
|
|
195
|
+
return void 0;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const [defaultModel, defaultProvider, lmstudioApiBase, ollamaApiUrl, vllmApiUrl] = await Promise.all([
|
|
199
|
+
read(this.config.secrets.defaultModel || "default-model"),
|
|
200
|
+
read(this.config.secrets.defaultProvider || "default-provider"),
|
|
201
|
+
read(this.config.secrets.lmstudioApiBase || "lmstudio-api-base"),
|
|
202
|
+
read(this.config.secrets.ollamaApiUrl || "ollama-api-url"),
|
|
203
|
+
read(this.config.secrets.vllmApiUrl || "vllm-api-url")
|
|
204
|
+
]);
|
|
205
|
+
return { defaultModel, defaultProvider, lmstudioApiBase, ollamaApiUrl, vllmApiUrl };
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Verify that required secrets exist
|
|
209
|
+
*/
|
|
210
|
+
async verifySecrets() {
|
|
211
|
+
const client = this.ensureClient();
|
|
212
|
+
if (!client) {
|
|
213
|
+
return { available: [], missing: [] };
|
|
214
|
+
}
|
|
215
|
+
const available = [];
|
|
216
|
+
const missing = [];
|
|
217
|
+
const providers = ["google", "openai", "anthropic", "groq"];
|
|
218
|
+
for (const provider of providers) {
|
|
219
|
+
const secretName = this.getSecretName(provider);
|
|
220
|
+
if (!secretName) continue;
|
|
221
|
+
try {
|
|
222
|
+
const name = `projects/${this.config.projectId}/secrets/${secretName}`;
|
|
223
|
+
await client.getSecret({ name });
|
|
224
|
+
available.push(provider);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
missing.push(provider);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return { available, missing };
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Create or update a secret
|
|
233
|
+
*/
|
|
234
|
+
async createOrUpdateSecret(provider, apiKey) {
|
|
235
|
+
const secretName = this.getSecretName(provider);
|
|
236
|
+
if (!secretName) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
const client = this.ensureClient();
|
|
240
|
+
if (!client) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
const secretId = `projects/${this.config.projectId}/secrets/${secretName}`;
|
|
244
|
+
try {
|
|
245
|
+
let secretExists = false;
|
|
246
|
+
try {
|
|
247
|
+
await client.getSecret({ name: secretId });
|
|
248
|
+
secretExists = true;
|
|
249
|
+
} catch {
|
|
250
|
+
secretExists = false;
|
|
251
|
+
}
|
|
252
|
+
if (!secretExists) {
|
|
253
|
+
await client.createSecret({
|
|
254
|
+
parent: `projects/${this.config.projectId}`,
|
|
255
|
+
secretId: secretName,
|
|
256
|
+
secret: {
|
|
257
|
+
replication: {
|
|
258
|
+
automatic: {}
|
|
259
|
+
},
|
|
260
|
+
labels: {
|
|
261
|
+
service: "ims",
|
|
262
|
+
provider
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
await client.addSecretVersion({
|
|
268
|
+
parent: secretId,
|
|
269
|
+
payload: {
|
|
270
|
+
data: Buffer.from(apiKey, "utf8")
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
this.cache.delete(secretName);
|
|
274
|
+
this.cacheExpiry.delete(secretName);
|
|
275
|
+
return true;
|
|
276
|
+
} catch (error) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Get secret name for provider
|
|
282
|
+
*/
|
|
283
|
+
getSecretName(provider) {
|
|
284
|
+
switch (provider) {
|
|
285
|
+
case "google":
|
|
286
|
+
return this.config.secrets.googleAI || "google-ai-api-key";
|
|
287
|
+
case "openai":
|
|
288
|
+
return this.config.secrets.openAI || "openai-api-key";
|
|
289
|
+
case "anthropic":
|
|
290
|
+
return this.config.secrets.anthropic || "anthropic-api-key";
|
|
291
|
+
case "groq":
|
|
292
|
+
return this.config.secrets.groq || "groq-api-key";
|
|
293
|
+
default:
|
|
294
|
+
return void 0;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Get cached secret if valid
|
|
299
|
+
*/
|
|
300
|
+
getCachedSecret(secretName) {
|
|
301
|
+
const expiry = this.cacheExpiry.get(secretName);
|
|
302
|
+
if (!expiry || Date.now() > expiry) {
|
|
303
|
+
this.cache.delete(secretName);
|
|
304
|
+
this.cacheExpiry.delete(secretName);
|
|
305
|
+
return void 0;
|
|
306
|
+
}
|
|
307
|
+
return this.cache.get(secretName);
|
|
308
|
+
}
|
|
309
|
+
/** Access a secret with retry + exponential backoff */
|
|
310
|
+
async accessWithBackoff(secretName) {
|
|
311
|
+
const client = this.ensureClient();
|
|
312
|
+
if (!client) return void 0;
|
|
313
|
+
const name = `projects/${this.config.projectId}/secrets/${secretName}/versions/latest`;
|
|
314
|
+
for (let attempt = 0; attempt < this.MAX_RETRIES; attempt++) {
|
|
315
|
+
try {
|
|
316
|
+
const [version] = await client.accessSecretVersion({ name });
|
|
317
|
+
const payload = version.payload?.data;
|
|
318
|
+
if (!payload) return void 0;
|
|
319
|
+
return payload.toString();
|
|
320
|
+
} catch (e2) {
|
|
321
|
+
if (attempt === this.MAX_RETRIES - 1) break;
|
|
322
|
+
const delay = this.BASE_DELAY_MS * Math.pow(2, attempt);
|
|
323
|
+
await new Promise((r2) => setTimeout(r2, delay));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return void 0;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Cache a secret
|
|
330
|
+
*/
|
|
331
|
+
cacheSecret(secretName, value) {
|
|
332
|
+
this.cache.set(secretName, value);
|
|
333
|
+
this.cacheExpiry.set(secretName, Date.now() + this.CACHE_TTL);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Get fallback from environment variable
|
|
337
|
+
*/
|
|
338
|
+
getFallbackFromEnv(provider) {
|
|
339
|
+
switch (provider) {
|
|
340
|
+
case "google":
|
|
341
|
+
return process.env.GOOGLE_AI_API_KEY;
|
|
342
|
+
case "openai":
|
|
343
|
+
return process.env.OPENAI_API_KEY;
|
|
344
|
+
case "anthropic":
|
|
345
|
+
return process.env.ANTHROPIC_API_KEY;
|
|
346
|
+
case "groq":
|
|
347
|
+
return process.env.GROQ_API_KEY;
|
|
348
|
+
default:
|
|
349
|
+
return void 0;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Clear cache
|
|
354
|
+
*/
|
|
355
|
+
clearCache() {
|
|
356
|
+
this.cache.clear();
|
|
357
|
+
this.cacheExpiry.clear();
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
|
|
102
363
|
// node_modules/.pnpm/data-uri-to-buffer@4.0.1/node_modules/data-uri-to-buffer/dist/index.js
|
|
103
364
|
function dataUriToBuffer(uri) {
|
|
104
365
|
if (!/^data:/i.test(uri)) {
|
|
@@ -7035,256 +7296,9 @@ var free_plan_default = {
|
|
|
7035
7296
|
]
|
|
7036
7297
|
}
|
|
7037
7298
|
};
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
this.useGsm = this.shouldUseGsm();
|
|
7042
|
-
}
|
|
7043
|
-
client = null;
|
|
7044
|
-
cache = /* @__PURE__ */ new Map();
|
|
7045
|
-
cacheExpiry = /* @__PURE__ */ new Map();
|
|
7046
|
-
CACHE_TTL = 36e5;
|
|
7047
|
-
// 1 hour
|
|
7048
|
-
useGsm;
|
|
7049
|
-
MAX_RETRIES = 3;
|
|
7050
|
-
BASE_DELAY_MS = 200;
|
|
7051
|
-
/** Determine whether GSM should be used in this environment */
|
|
7052
|
-
shouldUseGsm() {
|
|
7053
|
-
if (process.env.MARIA_DISABLE_GSM === "true") return false;
|
|
7054
|
-
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) return true;
|
|
7055
|
-
if (process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT) return true;
|
|
7056
|
-
if (process.env.CLOUD_RUN_SERVICE || process.env.K_SERVICE) return true;
|
|
7057
|
-
if (process.env.GCE_METADATA_HOST) return true;
|
|
7058
|
-
return false;
|
|
7059
|
-
}
|
|
7060
|
-
/** Lazily create Secret Manager client only when permitted */
|
|
7061
|
-
ensureClient() {
|
|
7062
|
-
if (!this.useGsm) return null;
|
|
7063
|
-
if (this.client) return this.client;
|
|
7064
|
-
try {
|
|
7065
|
-
this.client = new secretManager.SecretManagerServiceClient();
|
|
7066
|
-
} catch {
|
|
7067
|
-
this.client = null;
|
|
7068
|
-
}
|
|
7069
|
-
return this.client;
|
|
7070
|
-
}
|
|
7071
|
-
/**
|
|
7072
|
-
* Get API key from Secret Manager with caching
|
|
7073
|
-
*/
|
|
7074
|
-
async getApiKey(provider) {
|
|
7075
|
-
const secretName = this.getSecretName(provider);
|
|
7076
|
-
if (!secretName) {
|
|
7077
|
-
return void 0;
|
|
7078
|
-
}
|
|
7079
|
-
const client = this.ensureClient();
|
|
7080
|
-
if (!client) {
|
|
7081
|
-
return this.getFallbackFromEnv(provider);
|
|
7082
|
-
}
|
|
7083
|
-
const valid = this.getCachedSecret(secretName);
|
|
7084
|
-
if (valid) return valid;
|
|
7085
|
-
const res = await this.accessWithBackoff(secretName).catch(() => void 0);
|
|
7086
|
-
if (res) {
|
|
7087
|
-
this.cacheSecret(secretName, res);
|
|
7088
|
-
return res;
|
|
7089
|
-
}
|
|
7090
|
-
const stale = this.cache.get(secretName);
|
|
7091
|
-
if (stale) return stale;
|
|
7092
|
-
return this.getFallbackFromEnv(provider);
|
|
7093
|
-
}
|
|
7094
|
-
/**
|
|
7095
|
-
* Get all API keys
|
|
7096
|
-
*/
|
|
7097
|
-
async getAllApiKeys() {
|
|
7098
|
-
const [googleApiKey, openaiApiKey, anthropicApiKey, groqApiKey] = await Promise.all([
|
|
7099
|
-
this.getApiKey("google"),
|
|
7100
|
-
this.getApiKey("openai"),
|
|
7101
|
-
this.getApiKey("anthropic"),
|
|
7102
|
-
this.getApiKey("groq")
|
|
7103
|
-
]);
|
|
7104
|
-
return {
|
|
7105
|
-
googleApiKey,
|
|
7106
|
-
openaiApiKey,
|
|
7107
|
-
anthropicApiKey,
|
|
7108
|
-
groqApiKey
|
|
7109
|
-
};
|
|
7110
|
-
}
|
|
7111
|
-
/** Fetch optional configuration values (not API keys) */
|
|
7112
|
-
async getOptionalConfig() {
|
|
7113
|
-
const client = this.ensureClient();
|
|
7114
|
-
const read = async (name) => {
|
|
7115
|
-
if (!name) return void 0;
|
|
7116
|
-
if (!client) return void 0;
|
|
7117
|
-
try {
|
|
7118
|
-
const resName = `projects/${this.config.projectId}/secrets/${name}/versions/latest`;
|
|
7119
|
-
const [version] = await client.accessSecretVersion({ name: resName });
|
|
7120
|
-
const payload = version.payload?.data;
|
|
7121
|
-
return payload?.toString();
|
|
7122
|
-
} catch {
|
|
7123
|
-
return void 0;
|
|
7124
|
-
}
|
|
7125
|
-
};
|
|
7126
|
-
const [defaultModel, defaultProvider, lmstudioApiBase, ollamaApiUrl, vllmApiUrl] = await Promise.all([
|
|
7127
|
-
read(this.config.secrets.defaultModel || "default-model"),
|
|
7128
|
-
read(this.config.secrets.defaultProvider || "default-provider"),
|
|
7129
|
-
read(this.config.secrets.lmstudioApiBase || "lmstudio-api-base"),
|
|
7130
|
-
read(this.config.secrets.ollamaApiUrl || "ollama-api-url"),
|
|
7131
|
-
read(this.config.secrets.vllmApiUrl || "vllm-api-url")
|
|
7132
|
-
]);
|
|
7133
|
-
return { defaultModel, defaultProvider, lmstudioApiBase, ollamaApiUrl, vllmApiUrl };
|
|
7134
|
-
}
|
|
7135
|
-
/**
|
|
7136
|
-
* Verify that required secrets exist
|
|
7137
|
-
*/
|
|
7138
|
-
async verifySecrets() {
|
|
7139
|
-
const client = this.ensureClient();
|
|
7140
|
-
if (!client) {
|
|
7141
|
-
return { available: [], missing: [] };
|
|
7142
|
-
}
|
|
7143
|
-
const available = [];
|
|
7144
|
-
const missing = [];
|
|
7145
|
-
const providers = ["google", "openai", "anthropic", "groq"];
|
|
7146
|
-
for (const provider of providers) {
|
|
7147
|
-
const secretName = this.getSecretName(provider);
|
|
7148
|
-
if (!secretName) continue;
|
|
7149
|
-
try {
|
|
7150
|
-
const name = `projects/${this.config.projectId}/secrets/${secretName}`;
|
|
7151
|
-
await client.getSecret({ name });
|
|
7152
|
-
available.push(provider);
|
|
7153
|
-
} catch (error) {
|
|
7154
|
-
missing.push(provider);
|
|
7155
|
-
}
|
|
7156
|
-
}
|
|
7157
|
-
return { available, missing };
|
|
7158
|
-
}
|
|
7159
|
-
/**
|
|
7160
|
-
* Create or update a secret
|
|
7161
|
-
*/
|
|
7162
|
-
async createOrUpdateSecret(provider, apiKey) {
|
|
7163
|
-
const secretName = this.getSecretName(provider);
|
|
7164
|
-
if (!secretName) {
|
|
7165
|
-
return false;
|
|
7166
|
-
}
|
|
7167
|
-
const client = this.ensureClient();
|
|
7168
|
-
if (!client) {
|
|
7169
|
-
return false;
|
|
7170
|
-
}
|
|
7171
|
-
const secretId = `projects/${this.config.projectId}/secrets/${secretName}`;
|
|
7172
|
-
try {
|
|
7173
|
-
let secretExists = false;
|
|
7174
|
-
try {
|
|
7175
|
-
await client.getSecret({ name: secretId });
|
|
7176
|
-
secretExists = true;
|
|
7177
|
-
} catch {
|
|
7178
|
-
secretExists = false;
|
|
7179
|
-
}
|
|
7180
|
-
if (!secretExists) {
|
|
7181
|
-
await client.createSecret({
|
|
7182
|
-
parent: `projects/${this.config.projectId}`,
|
|
7183
|
-
secretId: secretName,
|
|
7184
|
-
secret: {
|
|
7185
|
-
replication: {
|
|
7186
|
-
automatic: {}
|
|
7187
|
-
},
|
|
7188
|
-
labels: {
|
|
7189
|
-
service: "ims",
|
|
7190
|
-
provider
|
|
7191
|
-
}
|
|
7192
|
-
}
|
|
7193
|
-
});
|
|
7194
|
-
}
|
|
7195
|
-
await client.addSecretVersion({
|
|
7196
|
-
parent: secretId,
|
|
7197
|
-
payload: {
|
|
7198
|
-
data: Buffer.from(apiKey, "utf8")
|
|
7199
|
-
}
|
|
7200
|
-
});
|
|
7201
|
-
this.cache.delete(secretName);
|
|
7202
|
-
this.cacheExpiry.delete(secretName);
|
|
7203
|
-
return true;
|
|
7204
|
-
} catch (error) {
|
|
7205
|
-
return false;
|
|
7206
|
-
}
|
|
7207
|
-
}
|
|
7208
|
-
/**
|
|
7209
|
-
* Get secret name for provider
|
|
7210
|
-
*/
|
|
7211
|
-
getSecretName(provider) {
|
|
7212
|
-
switch (provider) {
|
|
7213
|
-
case "google":
|
|
7214
|
-
return this.config.secrets.googleAI || "google-ai-api-key";
|
|
7215
|
-
case "openai":
|
|
7216
|
-
return this.config.secrets.openAI || "openai-api-key";
|
|
7217
|
-
case "anthropic":
|
|
7218
|
-
return this.config.secrets.anthropic || "anthropic-api-key";
|
|
7219
|
-
case "groq":
|
|
7220
|
-
return this.config.secrets.groq || "groq-api-key";
|
|
7221
|
-
default:
|
|
7222
|
-
return void 0;
|
|
7223
|
-
}
|
|
7224
|
-
}
|
|
7225
|
-
/**
|
|
7226
|
-
* Get cached secret if valid
|
|
7227
|
-
*/
|
|
7228
|
-
getCachedSecret(secretName) {
|
|
7229
|
-
const expiry = this.cacheExpiry.get(secretName);
|
|
7230
|
-
if (!expiry || Date.now() > expiry) {
|
|
7231
|
-
this.cache.delete(secretName);
|
|
7232
|
-
this.cacheExpiry.delete(secretName);
|
|
7233
|
-
return void 0;
|
|
7234
|
-
}
|
|
7235
|
-
return this.cache.get(secretName);
|
|
7236
|
-
}
|
|
7237
|
-
/** Access a secret with retry + exponential backoff */
|
|
7238
|
-
async accessWithBackoff(secretName) {
|
|
7239
|
-
const client = this.ensureClient();
|
|
7240
|
-
if (!client) return void 0;
|
|
7241
|
-
const name = `projects/${this.config.projectId}/secrets/${secretName}/versions/latest`;
|
|
7242
|
-
for (let attempt = 0; attempt < this.MAX_RETRIES; attempt++) {
|
|
7243
|
-
try {
|
|
7244
|
-
const [version] = await client.accessSecretVersion({ name });
|
|
7245
|
-
const payload = version.payload?.data;
|
|
7246
|
-
if (!payload) return void 0;
|
|
7247
|
-
return payload.toString();
|
|
7248
|
-
} catch (e2) {
|
|
7249
|
-
if (attempt === this.MAX_RETRIES - 1) break;
|
|
7250
|
-
const delay = this.BASE_DELAY_MS * Math.pow(2, attempt);
|
|
7251
|
-
await new Promise((r2) => setTimeout(r2, delay));
|
|
7252
|
-
}
|
|
7253
|
-
}
|
|
7254
|
-
return void 0;
|
|
7255
|
-
}
|
|
7256
|
-
/**
|
|
7257
|
-
* Cache a secret
|
|
7258
|
-
*/
|
|
7259
|
-
cacheSecret(secretName, value) {
|
|
7260
|
-
this.cache.set(secretName, value);
|
|
7261
|
-
this.cacheExpiry.set(secretName, Date.now() + this.CACHE_TTL);
|
|
7262
|
-
}
|
|
7263
|
-
/**
|
|
7264
|
-
* Get fallback from environment variable
|
|
7265
|
-
*/
|
|
7266
|
-
getFallbackFromEnv(provider) {
|
|
7267
|
-
switch (provider) {
|
|
7268
|
-
case "google":
|
|
7269
|
-
return process.env.GOOGLE_AI_API_KEY;
|
|
7270
|
-
case "openai":
|
|
7271
|
-
return process.env.OPENAI_API_KEY;
|
|
7272
|
-
case "anthropic":
|
|
7273
|
-
return process.env.ANTHROPIC_API_KEY;
|
|
7274
|
-
case "groq":
|
|
7275
|
-
return process.env.GROQ_API_KEY;
|
|
7276
|
-
default:
|
|
7277
|
-
return void 0;
|
|
7278
|
-
}
|
|
7279
|
-
}
|
|
7280
|
-
/**
|
|
7281
|
-
* Clear cache
|
|
7282
|
-
*/
|
|
7283
|
-
clearCache() {
|
|
7284
|
-
this.cache.clear();
|
|
7285
|
-
this.cacheExpiry.clear();
|
|
7286
|
-
}
|
|
7287
|
-
};
|
|
7299
|
+
|
|
7300
|
+
// src/services/intelligent-model-selector/IMSFacade.ts
|
|
7301
|
+
init_SecretManagerIntegration();
|
|
7288
7302
|
|
|
7289
7303
|
// src/providers/ai-provider.ts
|
|
7290
7304
|
var BaseAIProvider = class {
|
|
@@ -8532,7 +8546,7 @@ app.get("/health", (req, res) => {
|
|
|
8532
8546
|
app.get("/api/status", (req, res) => {
|
|
8533
8547
|
res.json({
|
|
8534
8548
|
status: "healthy",
|
|
8535
|
-
version: "4.3.
|
|
8549
|
+
version: "4.3.10",
|
|
8536
8550
|
uptime: process.uptime(),
|
|
8537
8551
|
memory: process.memoryUsage(),
|
|
8538
8552
|
platform: process.platform,
|
|
@@ -8543,7 +8557,7 @@ app.get("/api/status", (req, res) => {
|
|
|
8543
8557
|
app.get("/", (req, res) => {
|
|
8544
8558
|
res.json({
|
|
8545
8559
|
name: "MARIA CODE API",
|
|
8546
|
-
version: "4.3.
|
|
8560
|
+
version: "4.3.10",
|
|
8547
8561
|
status: "running",
|
|
8548
8562
|
environment: process.env.NODE_ENV || "development",
|
|
8549
8563
|
endpoints: {
|
|
@@ -8652,8 +8666,40 @@ app.post("/api/auth/revoke", async (req, res) => {
|
|
|
8652
8666
|
return res.status(500).json({ error: "REVOCATION_FAILED" });
|
|
8653
8667
|
}
|
|
8654
8668
|
});
|
|
8669
|
+
var _keysCache = null;
|
|
8670
|
+
async function loadProviderKeys() {
|
|
8671
|
+
if (_keysCache) return _keysCache;
|
|
8672
|
+
try {
|
|
8673
|
+
const { SecretManagerIntegration: SecretManagerIntegration2 } = await Promise.resolve().then(() => (init_SecretManagerIntegration(), SecretManagerIntegration_exports));
|
|
8674
|
+
const sm = new SecretManagerIntegration2({
|
|
8675
|
+
projectId: process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT || "maria-code-470602",
|
|
8676
|
+
secrets: {
|
|
8677
|
+
openAI: "openai-api-key",
|
|
8678
|
+
googleAI: "google-ai-api-key"
|
|
8679
|
+
}
|
|
8680
|
+
});
|
|
8681
|
+
const keys = await sm.getAllApiKeys().catch(() => ({}));
|
|
8682
|
+
_keysCache = {
|
|
8683
|
+
openaiApiKey: keys.openaiApiKey,
|
|
8684
|
+
googleApiKey: keys.googleApiKey
|
|
8685
|
+
};
|
|
8686
|
+
if (_keysCache.googleApiKey && !process.env.GEMINI_API_KEY && !process.env.GOOGLE_API_KEY) {
|
|
8687
|
+
process.env.GEMINI_API_KEY = _keysCache.googleApiKey;
|
|
8688
|
+
}
|
|
8689
|
+
if (_keysCache.openaiApiKey && !process.env.OPENAI_API_KEY) {
|
|
8690
|
+
process.env.OPENAI_API_KEY = _keysCache.openaiApiKey;
|
|
8691
|
+
}
|
|
8692
|
+
} catch {
|
|
8693
|
+
_keysCache = {
|
|
8694
|
+
openaiApiKey: process.env.OPENAI_API_KEY,
|
|
8695
|
+
googleApiKey: process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY
|
|
8696
|
+
};
|
|
8697
|
+
}
|
|
8698
|
+
return _keysCache;
|
|
8699
|
+
}
|
|
8655
8700
|
app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
8656
8701
|
try {
|
|
8702
|
+
await loadProviderKeys();
|
|
8657
8703
|
const auth = req.headers.authorization;
|
|
8658
8704
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8659
8705
|
const { prompt, model, size = "1024x1024", format = "png", count = 1, seed } = req.body || {};
|
|
@@ -8690,6 +8736,7 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8690
8736
|
});
|
|
8691
8737
|
app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
8692
8738
|
try {
|
|
8739
|
+
await loadProviderKeys();
|
|
8693
8740
|
const auth = req.headers.authorization;
|
|
8694
8741
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8695
8742
|
const { prompt, duration = 5, fps = 24, res: resStr = "1280x720", format = "mp4", model, seed } = req.body || {};
|
|
@@ -8794,11 +8841,36 @@ app.post("/v1/ai-proxy", rateLimitMiddleware, async (req, res) => {
|
|
|
8794
8841
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8795
8842
|
const { prompt, taskType } = req.body || {};
|
|
8796
8843
|
if (!prompt) return res.status(400).json({ error: "bad_request", message: "prompt required" });
|
|
8797
|
-
const
|
|
8844
|
+
const sanitizeKey = (v) => {
|
|
8845
|
+
if (!v) return void 0;
|
|
8846
|
+
let k = String(v).trim();
|
|
8847
|
+
if (!k) return void 0;
|
|
8848
|
+
if (k.startsWith('"') && k.endsWith('"') || k.startsWith("'") && k.endsWith("'")) {
|
|
8849
|
+
k = k.slice(1, -1);
|
|
8850
|
+
}
|
|
8851
|
+
if (/^Bearer\s+/i.test(k)) k = k.replace(/^Bearer\s+/i, "");
|
|
8852
|
+
if (/your_.*key|example|placeholder/i.test(k)) return void 0;
|
|
8853
|
+
if (/\s/.test(k)) k = k.replace(/\s+/g, "");
|
|
8854
|
+
return k || void 0;
|
|
8855
|
+
};
|
|
8856
|
+
const keys = await (async () => {
|
|
8857
|
+
try {
|
|
8858
|
+
return await global.___maria_keys ?? await (async () => {
|
|
8859
|
+
const k = await (await Promise.resolve().then(() => (init_SecretManagerIntegration(), SecretManagerIntegration_exports))).SecretManagerIntegration;
|
|
8860
|
+
const sm = new k({ projectId: process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT || "maria-code-470602", secrets: { openAI: "openai-api-key", googleAI: "google-ai-api-key" } });
|
|
8861
|
+
const all = await sm.getAllApiKeys().catch(() => ({}));
|
|
8862
|
+
global.___maria_keys = all;
|
|
8863
|
+
return all;
|
|
8864
|
+
})();
|
|
8865
|
+
} catch {
|
|
8866
|
+
return {};
|
|
8867
|
+
}
|
|
8868
|
+
})();
|
|
8869
|
+
const gemKey = sanitizeKey(keys?.googleApiKey || process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY);
|
|
8798
8870
|
if (gemKey) {
|
|
8799
8871
|
try {
|
|
8800
8872
|
const { GoogleGenerativeAI: GoogleGenerativeAI2 } = await import('@google/generative-ai');
|
|
8801
|
-
const ai = new GoogleGenerativeAI2(
|
|
8873
|
+
const ai = new GoogleGenerativeAI2(gemKey);
|
|
8802
8874
|
const modelName = process.env.MARIA_CODE_MODEL || "gemini-2.5-flash";
|
|
8803
8875
|
const model2 = ai.getGenerativeModel({ model: modelName });
|
|
8804
8876
|
const resp = await model2.generateContent({ contents: [{ role: "user", parts: [{ text: prompt }] }] });
|
|
@@ -8808,8 +8880,10 @@ app.post("/v1/ai-proxy", rateLimitMiddleware, async (req, res) => {
|
|
|
8808
8880
|
console.warn("[AI Proxy] Gemini path failed, falling back to OpenAI:", e2?.message || e2);
|
|
8809
8881
|
}
|
|
8810
8882
|
}
|
|
8811
|
-
const openaiKey = process.env.OPENAI_API_KEY;
|
|
8812
|
-
if (!openaiKey)
|
|
8883
|
+
const openaiKey = sanitizeKey(keys?.openaiApiKey || process.env.OPENAI_API_KEY);
|
|
8884
|
+
if (!openaiKey) {
|
|
8885
|
+
return res.status(503).json({ error: "provider_unavailable", message: "No valid provider key (set GEMINI_API_KEY/GOOGLE_API_KEY or OPENAI_API_KEY)" });
|
|
8886
|
+
}
|
|
8813
8887
|
const OpenAI2 = (await import('openai')).default;
|
|
8814
8888
|
const client = new OpenAI2({ apiKey: openaiKey });
|
|
8815
8889
|
let model = process.env.MARIA_CODE_MODEL || "gpt-5-mini";
|