@agenticmail/enterprise 0.5.13 ā 0.5.14
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/chunk-LNWVYHWX.js +1987 -0
- package/dist/chunk-VBKWGYN3.js +889 -0
- package/dist/cli.js +1 -1
- package/dist/dashboard/pages/settings.js +24 -0
- package/dist/index.js +2 -2
- package/dist/server-JRXIBDTH.js +11 -0
- package/dist/setup-UH5AXHZX.js +20 -0
- package/package.json +1 -1
- package/src/admin/routes.ts +25 -0
- package/src/dashboard/pages/settings.js +24 -0
- package/src/server.ts +23 -0
package/dist/cli.js
CHANGED
|
@@ -1310,6 +1310,30 @@ function ProvidersSection(props) {
|
|
|
1310
1310
|
}, isConfigured ? 'Connected' : 'Not Configured')
|
|
1311
1311
|
),
|
|
1312
1312
|
isLocal && p.baseUrl && h('div', { style: { fontSize: 12, color: '#6b7280', marginBottom: 8, wordBreak: 'break-all' } }, p.baseUrl),
|
|
1313
|
+
!isLocal && !p.isCustom && p.requiresApiKey && h('div', { style: { marginTop: 8 } },
|
|
1314
|
+
isConfigured
|
|
1315
|
+
? h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, fontSize: 12 } },
|
|
1316
|
+
h('span', { style: { color: 'var(--success, #16a34a)' } }, 'ā API key configured via environment'),
|
|
1317
|
+
h('button', { className: 'btn btn-sm btn-ghost', style: { padding: '2px 8px', fontSize: 11 }, onClick: function() {
|
|
1318
|
+
var key = prompt('Enter new API key for ' + p.name + ' (leave empty to keep current):');
|
|
1319
|
+
if (key && key.trim()) {
|
|
1320
|
+
apiCall('/providers/' + p.id + '/api-key', { method: 'POST', body: JSON.stringify({ apiKey: key.trim() }) })
|
|
1321
|
+
.then(function() { toast('API key updated for ' + p.name + '. Restart required.', 'success'); window.location.reload(); })
|
|
1322
|
+
.catch(function(e) { toast(e.message || 'Failed to save', 'error'); });
|
|
1323
|
+
}
|
|
1324
|
+
}}, 'Update Key')
|
|
1325
|
+
)
|
|
1326
|
+
: h('div', null,
|
|
1327
|
+
h('button', { className: 'btn btn-sm btn-primary', onClick: function() {
|
|
1328
|
+
var key = prompt('Enter your ' + p.name + ' API key:');
|
|
1329
|
+
if (key && key.trim()) {
|
|
1330
|
+
apiCall('/providers/' + p.id + '/api-key', { method: 'POST', body: JSON.stringify({ apiKey: key.trim() }) })
|
|
1331
|
+
.then(function() { toast('API key saved for ' + p.name + '!', 'success'); window.location.reload(); })
|
|
1332
|
+
.catch(function(e) { toast(e.message || 'Failed to save', 'error'); });
|
|
1333
|
+
}
|
|
1334
|
+
}}, 'š Add API Key')
|
|
1335
|
+
)
|
|
1336
|
+
),
|
|
1313
1337
|
h('div', { style: { display: 'flex', gap: 6, marginTop: 8 } },
|
|
1314
1338
|
isLocal && h('button', {
|
|
1315
1339
|
className: 'btn btn-sm',
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
requireRole,
|
|
27
27
|
securityHeaders,
|
|
28
28
|
validate
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-LNWVYHWX.js";
|
|
30
30
|
import {
|
|
31
31
|
PROVIDER_REGISTRY,
|
|
32
32
|
listAllProviders,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
import {
|
|
37
37
|
provision,
|
|
38
38
|
runSetupWizard
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-VBKWGYN3.js";
|
|
40
40
|
import {
|
|
41
41
|
ENGINE_TABLES,
|
|
42
42
|
ENGINE_TABLES_POSTGRES,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
promptCompanyInfo,
|
|
3
|
+
promptDatabase,
|
|
4
|
+
promptDeployment,
|
|
5
|
+
promptDomain,
|
|
6
|
+
promptRegistration,
|
|
7
|
+
provision,
|
|
8
|
+
runSetupWizard
|
|
9
|
+
} from "./chunk-VBKWGYN3.js";
|
|
10
|
+
import "./chunk-6TDW6ZNI.js";
|
|
11
|
+
import "./chunk-KFQGP6VL.js";
|
|
12
|
+
export {
|
|
13
|
+
promptCompanyInfo,
|
|
14
|
+
promptDatabase,
|
|
15
|
+
promptDeployment,
|
|
16
|
+
promptDomain,
|
|
17
|
+
promptRegistration,
|
|
18
|
+
provision,
|
|
19
|
+
runSetupWizard
|
|
20
|
+
};
|
package/package.json
CHANGED
package/src/admin/routes.ts
CHANGED
|
@@ -629,6 +629,31 @@ export function createAdminRoutes(db: DatabaseAdapter) {
|
|
|
629
629
|
return c.json({ ok: true, provider: body });
|
|
630
630
|
});
|
|
631
631
|
|
|
632
|
+
// āāā Provider API Key Management āāāāāāāāāāāāāāāāāāāāāāāā
|
|
633
|
+
api.post('/providers/:id/api-key', requireRole('admin'), async (c) => {
|
|
634
|
+
var id = c.req.param('id');
|
|
635
|
+
var provider = PROVIDER_REGISTRY[id];
|
|
636
|
+
if (!provider) {
|
|
637
|
+
return c.json({ error: 'Unknown provider' }, 404);
|
|
638
|
+
}
|
|
639
|
+
var body = await c.req.json();
|
|
640
|
+
if (!body.apiKey || typeof body.apiKey !== 'string' || body.apiKey.trim().length < 5) {
|
|
641
|
+
return c.json({ error: 'Valid API key required' }, 400);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// Store API key in company settings (encrypted field)
|
|
645
|
+
var settings = await db.getSettings();
|
|
646
|
+
var config = (settings as any)?.modelPricingConfig || { models: [], currency: 'USD' };
|
|
647
|
+
config.providerApiKeys = config.providerApiKeys || {};
|
|
648
|
+
config.providerApiKeys[id] = body.apiKey.trim();
|
|
649
|
+
await db.updateSettings({ modelPricingConfig: config } as any);
|
|
650
|
+
|
|
651
|
+
// Also set in process.env so it takes effect immediately
|
|
652
|
+
process.env[provider.envKey] = body.apiKey.trim();
|
|
653
|
+
|
|
654
|
+
return c.json({ ok: true, message: 'API key saved for ' + provider.name });
|
|
655
|
+
});
|
|
656
|
+
|
|
632
657
|
api.put('/providers/:id', requireRole('admin'), async (c) => {
|
|
633
658
|
var id = c.req.param('id');
|
|
634
659
|
if (PROVIDER_REGISTRY[id]) {
|
|
@@ -1310,6 +1310,30 @@ function ProvidersSection(props) {
|
|
|
1310
1310
|
}, isConfigured ? 'Connected' : 'Not Configured')
|
|
1311
1311
|
),
|
|
1312
1312
|
isLocal && p.baseUrl && h('div', { style: { fontSize: 12, color: '#6b7280', marginBottom: 8, wordBreak: 'break-all' } }, p.baseUrl),
|
|
1313
|
+
!isLocal && !p.isCustom && p.requiresApiKey && h('div', { style: { marginTop: 8 } },
|
|
1314
|
+
isConfigured
|
|
1315
|
+
? h('div', { style: { display: 'flex', alignItems: 'center', gap: 6, fontSize: 12 } },
|
|
1316
|
+
h('span', { style: { color: 'var(--success, #16a34a)' } }, 'ā API key configured via environment'),
|
|
1317
|
+
h('button', { className: 'btn btn-sm btn-ghost', style: { padding: '2px 8px', fontSize: 11 }, onClick: function() {
|
|
1318
|
+
var key = prompt('Enter new API key for ' + p.name + ' (leave empty to keep current):');
|
|
1319
|
+
if (key && key.trim()) {
|
|
1320
|
+
apiCall('/providers/' + p.id + '/api-key', { method: 'POST', body: JSON.stringify({ apiKey: key.trim() }) })
|
|
1321
|
+
.then(function() { toast('API key updated for ' + p.name + '. Restart required.', 'success'); window.location.reload(); })
|
|
1322
|
+
.catch(function(e) { toast(e.message || 'Failed to save', 'error'); });
|
|
1323
|
+
}
|
|
1324
|
+
}}, 'Update Key')
|
|
1325
|
+
)
|
|
1326
|
+
: h('div', null,
|
|
1327
|
+
h('button', { className: 'btn btn-sm btn-primary', onClick: function() {
|
|
1328
|
+
var key = prompt('Enter your ' + p.name + ' API key:');
|
|
1329
|
+
if (key && key.trim()) {
|
|
1330
|
+
apiCall('/providers/' + p.id + '/api-key', { method: 'POST', body: JSON.stringify({ apiKey: key.trim() }) })
|
|
1331
|
+
.then(function() { toast('API key saved for ' + p.name + '!', 'success'); window.location.reload(); })
|
|
1332
|
+
.catch(function(e) { toast(e.message || 'Failed to save', 'error'); });
|
|
1333
|
+
}
|
|
1334
|
+
}}, 'š Add API Key')
|
|
1335
|
+
)
|
|
1336
|
+
),
|
|
1313
1337
|
h('div', { style: { display: 'flex', gap: 6, marginTop: 8 } },
|
|
1314
1338
|
isLocal && h('button', {
|
|
1315
1339
|
className: 'btn btn-sm',
|
package/src/server.ts
CHANGED
|
@@ -391,6 +391,29 @@ export function createServer(config: ServerConfig): ServerInstance {
|
|
|
391
391
|
// Start health monitoring
|
|
392
392
|
healthMonitor.start();
|
|
393
393
|
|
|
394
|
+
// Load saved provider API keys from DB into process.env
|
|
395
|
+
config.db.getSettings().then((settings: any) => {
|
|
396
|
+
const keys = settings?.modelPricingConfig?.providerApiKeys;
|
|
397
|
+
if (keys && typeof keys === 'object') {
|
|
398
|
+
// Map of provider IDs to their env var names
|
|
399
|
+
const envMap: Record<string, string> = {
|
|
400
|
+
anthropic: 'ANTHROPIC_API_KEY', openai: 'OPENAI_API_KEY',
|
|
401
|
+
google: 'GOOGLE_API_KEY', deepseek: 'DEEPSEEK_API_KEY',
|
|
402
|
+
xai: 'XAI_API_KEY', mistral: 'MISTRAL_API_KEY',
|
|
403
|
+
groq: 'GROQ_API_KEY', together: 'TOGETHER_API_KEY',
|
|
404
|
+
fireworks: 'FIREWORKS_API_KEY', perplexity: 'PERPLEXITY_API_KEY',
|
|
405
|
+
cohere: 'COHERE_API_KEY',
|
|
406
|
+
};
|
|
407
|
+
for (const [providerId, apiKey] of Object.entries(keys)) {
|
|
408
|
+
const envVar = envMap[providerId];
|
|
409
|
+
if (envVar && apiKey && !process.env[envVar]) {
|
|
410
|
+
process.env[envVar] = apiKey as string;
|
|
411
|
+
console.log(` š Loaded API key for ${providerId}`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}).catch(() => {});
|
|
416
|
+
|
|
394
417
|
// Graceful shutdown
|
|
395
418
|
const shutdown = () => {
|
|
396
419
|
console.log('\nā³ Shutting down gracefully...');
|