@agenticmail/enterprise 0.5.69 → 0.5.70
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-5KWBRCXT.js +2128 -0
- package/dist/chunk-77QJHMFG.js +898 -0
- package/dist/chunk-SWD4HRGX.js +13099 -0
- package/dist/cli.js +1 -1
- package/dist/dashboard/pages/agent-detail.js +4 -4
- package/dist/index.js +3 -3
- package/dist/routes-TMHXM4EO.js +6241 -0
- package/dist/runtime-3M2QQDTA.js +47 -0
- package/dist/server-N5QXQO5K.js +12 -0
- package/dist/setup-CTHP4V2A.js +20 -0
- package/package.json +1 -1
- package/src/dashboard/pages/agent-detail.js +4 -4
- package/src/engine/oauth-connect-routes.ts +98 -2
- package/src/engine/routes.ts +1 -1
- package/src/server.ts +5 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentRuntime,
|
|
3
|
+
EmailChannel,
|
|
4
|
+
FollowUpScheduler,
|
|
5
|
+
SessionManager,
|
|
6
|
+
SubAgentManager,
|
|
7
|
+
ToolRegistry,
|
|
8
|
+
callLLM,
|
|
9
|
+
createAgentRuntime,
|
|
10
|
+
createNoopHooks,
|
|
11
|
+
createRuntimeHooks,
|
|
12
|
+
estimateMessageTokens,
|
|
13
|
+
estimateTokens,
|
|
14
|
+
executeTool,
|
|
15
|
+
runAgentLoop,
|
|
16
|
+
toolsToDefinitions
|
|
17
|
+
} from "./chunk-SWD4HRGX.js";
|
|
18
|
+
import "./chunk-TYW5XTOW.js";
|
|
19
|
+
import "./chunk-JLSQOQ5L.js";
|
|
20
|
+
import {
|
|
21
|
+
PROVIDER_REGISTRY,
|
|
22
|
+
listAllProviders,
|
|
23
|
+
resolveApiKeyForProvider,
|
|
24
|
+
resolveProvider
|
|
25
|
+
} from "./chunk-67KZYSLU.js";
|
|
26
|
+
import "./chunk-KFQGP6VL.js";
|
|
27
|
+
export {
|
|
28
|
+
AgentRuntime,
|
|
29
|
+
EmailChannel,
|
|
30
|
+
FollowUpScheduler,
|
|
31
|
+
PROVIDER_REGISTRY,
|
|
32
|
+
SessionManager,
|
|
33
|
+
SubAgentManager,
|
|
34
|
+
ToolRegistry,
|
|
35
|
+
callLLM,
|
|
36
|
+
createAgentRuntime,
|
|
37
|
+
createNoopHooks,
|
|
38
|
+
createRuntimeHooks,
|
|
39
|
+
estimateMessageTokens,
|
|
40
|
+
estimateTokens,
|
|
41
|
+
executeTool,
|
|
42
|
+
listAllProviders,
|
|
43
|
+
resolveApiKeyForProvider,
|
|
44
|
+
resolveProvider,
|
|
45
|
+
runAgentLoop,
|
|
46
|
+
toolsToDefinitions
|
|
47
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createServer
|
|
3
|
+
} from "./chunk-5KWBRCXT.js";
|
|
4
|
+
import "./chunk-3SMTCIR4.js";
|
|
5
|
+
import "./chunk-JLSQOQ5L.js";
|
|
6
|
+
import "./chunk-RO537U6H.js";
|
|
7
|
+
import "./chunk-DRXMYYKN.js";
|
|
8
|
+
import "./chunk-67KZYSLU.js";
|
|
9
|
+
import "./chunk-KFQGP6VL.js";
|
|
10
|
+
export {
|
|
11
|
+
createServer
|
|
12
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
promptCompanyInfo,
|
|
3
|
+
promptDatabase,
|
|
4
|
+
promptDeployment,
|
|
5
|
+
promptDomain,
|
|
6
|
+
promptRegistration,
|
|
7
|
+
provision,
|
|
8
|
+
runSetupWizard
|
|
9
|
+
} from "./chunk-77QJHMFG.js";
|
|
10
|
+
import "./chunk-WP76IB36.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
|
@@ -3912,14 +3912,14 @@ function EmailSection(props) {
|
|
|
3912
3912
|
oauthClientId: form.oauthClientId,
|
|
3913
3913
|
oauthClientSecret: form.oauthClientSecret,
|
|
3914
3914
|
oauthTenantId: form.oauthTenantId,
|
|
3915
|
-
oauthRedirectUri: baseUrl + '/oauth/callback',
|
|
3915
|
+
oauthRedirectUri: baseUrl + '/api/engine/oauth/callback',
|
|
3916
3916
|
});
|
|
3917
3917
|
} else if (form.provider === 'google') {
|
|
3918
3918
|
var gBaseUrl = window.location.origin;
|
|
3919
3919
|
Object.assign(body, {
|
|
3920
3920
|
oauthClientId: form.oauthClientId,
|
|
3921
3921
|
oauthClientSecret: form.oauthClientSecret,
|
|
3922
|
-
oauthRedirectUri: gBaseUrl + '/oauth/callback',
|
|
3922
|
+
oauthRedirectUri: gBaseUrl + '/api/engine/oauth/callback',
|
|
3923
3923
|
});
|
|
3924
3924
|
}
|
|
3925
3925
|
|
|
@@ -4098,7 +4098,7 @@ function EmailSection(props) {
|
|
|
4098
4098
|
h('div', { style: { padding: '12px 16px', background: 'var(--info-soft)', borderRadius: 'var(--radius)', fontSize: 12, color: 'var(--info)', marginBottom: 16 } },
|
|
4099
4099
|
h('strong', null, 'Setup Instructions:'), h('br'),
|
|
4100
4100
|
'1. Go to ', h('a', { href: 'https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade', target: '_blank', style: { color: 'var(--accent)' } }, 'Azure Portal → App Registrations'), h('br'),
|
|
4101
|
-
'2. Click "New Registration" → name it (e.g., "AgenticMail Agent") → set redirect URI to: ', h('code', { style: { background: 'var(--bg-tertiary)', padding: '1px 4px', borderRadius: 3 } }, window.location.origin + '/oauth/callback'), h('br'),
|
|
4101
|
+
'2. Click "New Registration" → name it (e.g., "AgenticMail Agent") → set redirect URI to: ', h('code', { style: { background: 'var(--bg-tertiary)', padding: '1px 4px', borderRadius: 3 } }, window.location.origin + '/api/engine/oauth/callback'), h('br'),
|
|
4102
4102
|
'3. Under "Certificates & Secrets" → create a Client Secret', h('br'),
|
|
4103
4103
|
'4. Under "API Permissions" → add Microsoft Graph: Mail.ReadWrite, Mail.Send, offline_access', h('br'),
|
|
4104
4104
|
'5. Copy the Application (client) ID and Client Secret below'
|
|
@@ -4132,7 +4132,7 @@ function EmailSection(props) {
|
|
|
4132
4132
|
h('div', { style: { padding: '12px 16px', background: 'var(--info-soft)', borderRadius: 'var(--radius)', fontSize: 12, color: 'var(--info)', marginBottom: 16 } },
|
|
4133
4133
|
h('strong', null, 'Setup Instructions:'), h('br'),
|
|
4134
4134
|
'1. Go to ', h('a', { href: 'https://console.cloud.google.com/apis/credentials', target: '_blank', style: { color: 'var(--accent)' } }, 'Google Cloud Console → Credentials'), h('br'),
|
|
4135
|
-
'2. Create an OAuth 2.0 Client ID (Web application) → add redirect URI: ', h('code', { style: { background: 'var(--bg-tertiary)', padding: '1px 4px', borderRadius: 3 } }, window.location.origin + '/oauth/callback'), h('br'),
|
|
4135
|
+
'2. Create an OAuth 2.0 Client ID (Web application) → add redirect URI: ', h('code', { style: { background: 'var(--bg-tertiary)', padding: '1px 4px', borderRadius: 3 } }, window.location.origin + '/api/engine/oauth/callback'), h('br'),
|
|
4136
4136
|
'3. Enable the Gmail API in your project', h('br'),
|
|
4137
4137
|
'4. Copy the Client ID and Client Secret below'
|
|
4138
4138
|
),
|
|
@@ -68,7 +68,7 @@ async function findVaultEntryByName(
|
|
|
68
68
|
|
|
69
69
|
// ─── Route Factory ──────────────────────────────────────
|
|
70
70
|
|
|
71
|
-
export function createOAuthConnectRoutes(vault: SecureVault) {
|
|
71
|
+
export function createOAuthConnectRoutes(vault: SecureVault, lifecycle?: any) {
|
|
72
72
|
const router = new Hono();
|
|
73
73
|
|
|
74
74
|
// ─── GET /authorize/:skillId — Start OAuth flow ─────
|
|
@@ -195,9 +195,16 @@ export function createOAuthConnectRoutes(vault: SecureVault) {
|
|
|
195
195
|
return c.html(oauthResultPage(false, 'Missing code or state parameter'));
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
// Validate state
|
|
198
|
+
// Validate state — check skill OAuth states first, then agent email OAuth
|
|
199
199
|
const pending = pendingOAuthStates.get(state);
|
|
200
200
|
if (!pending) {
|
|
201
|
+
// Check if state is an agent ID (agent email OAuth flow)
|
|
202
|
+
if (lifecycle) {
|
|
203
|
+
const managed = lifecycle.getAgent(state);
|
|
204
|
+
if (managed?.config?.emailConfig?.status === 'awaiting_oauth') {
|
|
205
|
+
return await handleAgentEmailOAuthCallback(c, state, code, managed, lifecycle);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
201
208
|
return c.html(oauthResultPage(false, 'Invalid or expired OAuth state'));
|
|
202
209
|
}
|
|
203
210
|
|
|
@@ -338,6 +345,95 @@ export function createOAuthConnectRoutes(vault: SecureVault) {
|
|
|
338
345
|
return router;
|
|
339
346
|
}
|
|
340
347
|
|
|
348
|
+
// ─── Agent Email OAuth Callback Handler ─────────────────
|
|
349
|
+
|
|
350
|
+
async function handleAgentEmailOAuthCallback(c: any, agentId: string, code: string, managed: any, lifecycle: any) {
|
|
351
|
+
const emailConfig = managed.config.emailConfig;
|
|
352
|
+
try {
|
|
353
|
+
if (emailConfig.oauthProvider === 'microsoft') {
|
|
354
|
+
const tokenRes = await fetch(`https://login.microsoftonline.com/${emailConfig.oauthTenantId || 'common'}/oauth2/v2.0/token`, {
|
|
355
|
+
method: 'POST',
|
|
356
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
357
|
+
body: new URLSearchParams({
|
|
358
|
+
client_id: emailConfig.oauthClientId,
|
|
359
|
+
client_secret: emailConfig.oauthClientSecret,
|
|
360
|
+
code,
|
|
361
|
+
redirect_uri: emailConfig.oauthRedirectUri,
|
|
362
|
+
grant_type: 'authorization_code',
|
|
363
|
+
scope: emailConfig.oauthScopes.join(' '),
|
|
364
|
+
}),
|
|
365
|
+
});
|
|
366
|
+
if (!tokenRes.ok) {
|
|
367
|
+
const errText = await tokenRes.text();
|
|
368
|
+
return c.html(oauthResultPage(false, `Microsoft token exchange failed: ${errText}`));
|
|
369
|
+
}
|
|
370
|
+
const tokens = await tokenRes.json() as any;
|
|
371
|
+
emailConfig.oauthAccessToken = tokens.access_token;
|
|
372
|
+
emailConfig.oauthRefreshToken = tokens.refresh_token;
|
|
373
|
+
emailConfig.oauthTokenExpiry = new Date(Date.now() + (tokens.expires_in * 1000)).toISOString();
|
|
374
|
+
|
|
375
|
+
// Get user email from Graph
|
|
376
|
+
try {
|
|
377
|
+
const profileRes = await fetch('https://graph.microsoft.com/v1.0/me?$select=mail,displayName', {
|
|
378
|
+
headers: { Authorization: `Bearer ${tokens.access_token}` },
|
|
379
|
+
});
|
|
380
|
+
if (profileRes.ok) {
|
|
381
|
+
const profile = await profileRes.json() as any;
|
|
382
|
+
if (profile.mail) emailConfig.email = profile.mail;
|
|
383
|
+
}
|
|
384
|
+
} catch {}
|
|
385
|
+
|
|
386
|
+
} else if (emailConfig.oauthProvider === 'google') {
|
|
387
|
+
const tokenRes = await fetch('https://oauth2.googleapis.com/token', {
|
|
388
|
+
method: 'POST',
|
|
389
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
390
|
+
body: new URLSearchParams({
|
|
391
|
+
client_id: emailConfig.oauthClientId,
|
|
392
|
+
client_secret: emailConfig.oauthClientSecret,
|
|
393
|
+
code,
|
|
394
|
+
redirect_uri: emailConfig.oauthRedirectUri,
|
|
395
|
+
grant_type: 'authorization_code',
|
|
396
|
+
}),
|
|
397
|
+
});
|
|
398
|
+
if (!tokenRes.ok) {
|
|
399
|
+
const errText = await tokenRes.text();
|
|
400
|
+
return c.html(oauthResultPage(false, `Google token exchange failed: ${errText}`));
|
|
401
|
+
}
|
|
402
|
+
const tokens = await tokenRes.json() as any;
|
|
403
|
+
emailConfig.oauthAccessToken = tokens.access_token;
|
|
404
|
+
emailConfig.oauthRefreshToken = tokens.refresh_token;
|
|
405
|
+
emailConfig.oauthTokenExpiry = tokens.expires_in
|
|
406
|
+
? new Date(Date.now() + (tokens.expires_in * 1000)).toISOString()
|
|
407
|
+
: undefined;
|
|
408
|
+
|
|
409
|
+
// Get user email from Google
|
|
410
|
+
try {
|
|
411
|
+
const profileRes = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
|
|
412
|
+
headers: { Authorization: `Bearer ${tokens.access_token}` },
|
|
413
|
+
});
|
|
414
|
+
if (profileRes.ok) {
|
|
415
|
+
const profile = await profileRes.json() as any;
|
|
416
|
+
if (profile.email) emailConfig.email = profile.email;
|
|
417
|
+
}
|
|
418
|
+
} catch {}
|
|
419
|
+
|
|
420
|
+
} else {
|
|
421
|
+
return c.html(oauthResultPage(false, `Unknown OAuth provider: ${emailConfig.oauthProvider}`));
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
emailConfig.status = 'connected';
|
|
425
|
+
emailConfig.configured = true;
|
|
426
|
+
delete emailConfig.oauthAuthUrl;
|
|
427
|
+
managed.config.emailConfig = emailConfig;
|
|
428
|
+
managed.updatedAt = new Date().toISOString();
|
|
429
|
+
await lifecycle.saveAgent(agentId);
|
|
430
|
+
|
|
431
|
+
return c.html(oauthResultPage(true, `Email connected via ${emailConfig.oauthProvider === 'google' ? 'Google' : 'Microsoft'} OAuth`));
|
|
432
|
+
} catch (e: any) {
|
|
433
|
+
return c.html(oauthResultPage(false, e.message || 'OAuth token exchange failed'));
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
341
437
|
// ─── HTML Callback Page ─────────────────────────────────
|
|
342
438
|
|
|
343
439
|
/**
|
package/src/engine/routes.ts
CHANGED
|
@@ -214,7 +214,7 @@ engine.route('/storage', createStorageRoutes(storageManager));
|
|
|
214
214
|
engine.route('/policies', createPolicyImportRoutes(policyImporter));
|
|
215
215
|
engine.route('/knowledge-contribution', createKnowledgeContributionRoutes(knowledgeContribution));
|
|
216
216
|
engine.route('/skill-updates', createSkillUpdaterRoutes(skillUpdater));
|
|
217
|
-
engine.route('/oauth', createOAuthConnectRoutes(vault));
|
|
217
|
+
engine.route('/oauth', createOAuthConnectRoutes(vault, lifecycle));
|
|
218
218
|
|
|
219
219
|
// ─── setEngineDb ────────────────────────────────────────
|
|
220
220
|
|
package/src/server.ts
CHANGED
|
@@ -177,6 +177,11 @@ export function createServer(config: ServerConfig): ServerInstance {
|
|
|
177
177
|
|
|
178
178
|
// Authentication middleware
|
|
179
179
|
api.use('*', async (c, next) => {
|
|
180
|
+
// Skip auth for OAuth callback (browser redirect from Google/Microsoft)
|
|
181
|
+
if (c.req.path.endsWith('/oauth/callback') && c.req.method === 'GET') {
|
|
182
|
+
return next();
|
|
183
|
+
}
|
|
184
|
+
|
|
180
185
|
// Check API key first
|
|
181
186
|
const apiKeyHeader = c.req.header('X-API-Key');
|
|
182
187
|
if (apiKeyHeader) {
|