apteva 0.4.20 → 0.4.29
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/ActivityPage.41nbye4r.js +3 -0
- package/dist/{ApiDocsPage.kf6bbwkk.js → ApiDocsPage.4smnt8m3.js} +2 -2
- package/dist/{App.jfx3der4.js → App.0sbax9et.js} +3 -3
- package/dist/App.0ws427h8.js +4 -0
- package/dist/App.4ehxpt48.js +4 -0
- package/dist/App.6q6bar8b.js +4 -0
- package/dist/App.ca1rz1ph.js +4 -0
- package/dist/{App.7v1w3ys9.js → App.ensa6z0r.js} +3 -3
- package/dist/{App.n4jb3c22.js → App.f8g7tych.js} +3 -3
- package/dist/App.kh7d2xj3.js +267 -0
- package/dist/App.mvtqv6qc.js +20 -0
- package/dist/{App.c90t3dxg.js → App.ncgc9cxy.js} +3 -3
- package/dist/{App.039re6cf.js → App.p0fb1pds.js} +3 -3
- package/dist/App.pmaq48sj.js +4 -0
- package/dist/{App.2yy66bnp.js → App.yv87t9m5.js} +3 -3
- package/dist/App.zjmfm8p6.js +4 -0
- package/dist/ConnectionsPage.anb3rv9a.js +3 -0
- package/dist/McpPage.y396h6fy.js +3 -0
- package/dist/SettingsPage.5k6vp396.js +3 -0
- package/dist/SkillsPage.yj3xdsay.js +3 -0
- package/dist/TasksPage.sjv0khtv.js +3 -0
- package/dist/TelemetryPage.2qm4w16r.js +3 -0
- package/dist/TestsPage.zzs4qfj8.js +3 -0
- package/dist/index.html +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
- package/src/channels/telegram.ts +5 -0
- package/src/crypto.ts +13 -4
- package/src/db.ts +25 -2
- package/src/integrations/agentdojo.ts +1 -1
- package/src/providers.ts +46 -0
- package/src/routes/api/agent-utils.ts +64 -9
- package/src/routes/api/agents.ts +41 -13
- package/src/routes/api/integrations.ts +16 -6
- package/src/routes/api/mcp.ts +7 -0
- package/src/routes/api/triggers.ts +45 -5
- package/src/web/App.tsx +1 -0
- package/src/web/components/activity/ActivityPage.tsx +349 -214
- package/src/web/components/agents/AgentCard.tsx +37 -8
- package/src/web/components/agents/AgentPanel.tsx +268 -23
- package/src/web/components/connections/IntegrationsTab.tsx +57 -31
- package/src/web/components/connections/TriggersTab.tsx +336 -159
- package/src/web/components/dashboard/Dashboard.tsx +39 -7
- package/src/web/components/layout/Header.tsx +0 -34
- package/src/web/components/layout/Sidebar.tsx +43 -3
- package/src/web/components/mcp/McpPage.tsx +16 -5
- package/src/web/components/settings/SettingsPage.tsx +279 -30
- package/src/web/components/tasks/TasksPage.tsx +32 -6
- package/src/web/context/ProjectContext.tsx +5 -0
- package/src/web/context/TelemetryContext.tsx +14 -0
- package/src/web/types.ts +20 -2
- package/dist/ActivityPage.h769ek3a.js +0 -3
- package/dist/App.2jmkqm8c.js +0 -4
- package/dist/App.3515wsb4.js +0 -4
- package/dist/App.edwahsvz.js +0 -4
- package/dist/App.q3bpx15d.js +0 -20
- package/dist/App.r0a2nmqs.js +0 -267
- package/dist/App.s2yrcz15.js +0 -4
- package/dist/App.s5j82a5j.js +0 -4
- package/dist/App.tg1b94tx.js +0 -4
- package/dist/ConnectionsPage.a67fjgbf.js +0 -3
- package/dist/McpPage.d4p3xvtk.js +0 -3
- package/dist/SettingsPage.46sqpe39.js +0 -3
- package/dist/SkillsPage.j9hkqm99.js +0 -3
- package/dist/TasksPage.6pvkb7s7.js +0 -3
- package/dist/TelemetryPage.5zq9msb5.js +0 -3
- package/dist/TestsPage.24432yqt.js +0 -3
package/src/routes/api/agents.ts
CHANGED
|
@@ -110,20 +110,47 @@ export async function handleAgentRoutes(
|
|
|
110
110
|
|
|
111
111
|
const updated = AgentDB.update(agentMatch[1], updates);
|
|
112
112
|
|
|
113
|
-
// If agent is running,
|
|
113
|
+
// If agent is running, handle config update
|
|
114
114
|
if (updated && updated.status === "running" && updated.port) {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
115
|
+
const providerChanged = body.provider !== undefined && body.provider !== agent.provider;
|
|
116
|
+
|
|
117
|
+
if (providerChanged) {
|
|
118
|
+
// Provider changed — must restart to get new API key in env
|
|
119
|
+
console.log(`Provider changed for ${updated.name} (${agent.provider} -> ${updated.provider}), restarting...`);
|
|
120
|
+
const agentProc = agentProcesses.get(updated.id);
|
|
121
|
+
if (agentProc) {
|
|
122
|
+
// Graceful shutdown
|
|
123
|
+
try {
|
|
124
|
+
await fetch(`http://localhost:${updated.port}/shutdown`, {
|
|
125
|
+
method: "POST",
|
|
126
|
+
signal: AbortSignal.timeout(2000),
|
|
127
|
+
});
|
|
128
|
+
await new Promise(r => setTimeout(r, 500));
|
|
129
|
+
} catch {}
|
|
130
|
+
try { agentProc.proc.kill(); } catch {}
|
|
131
|
+
agentProcesses.delete(updated.id);
|
|
121
132
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
setAgentStatus(updated.id, "stopped", "provider_changed");
|
|
134
|
+
// Start with new provider
|
|
135
|
+
const startResult = await startAgentProcess(updated, { silent: true });
|
|
136
|
+
if (!startResult.success) {
|
|
137
|
+
console.error(`Failed to restart agent after provider change: ${startResult.error}`);
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
// Same provider — just push updated config
|
|
141
|
+
const providerKey = ProviderKeys.getDecrypted(updated.provider);
|
|
142
|
+
if (providerKey) {
|
|
143
|
+
const config = buildAgentConfig(updated, providerKey);
|
|
144
|
+
const configResult = await pushConfigToAgent(updated.id, updated.port, config);
|
|
145
|
+
if (!configResult.success) {
|
|
146
|
+
console.error(`Failed to push config to running agent: ${configResult.error}`);
|
|
147
|
+
}
|
|
148
|
+
// Push skills via /skills endpoint
|
|
149
|
+
if (config.skills?.definitions?.length > 0) {
|
|
150
|
+
const skillsResult = await pushSkillsToAgent(updated.id, updated.port, config.skills.definitions);
|
|
151
|
+
if (!skillsResult.success) {
|
|
152
|
+
console.error(`Failed to push skills to running agent: ${skillsResult.error}`);
|
|
153
|
+
}
|
|
127
154
|
}
|
|
128
155
|
}
|
|
129
156
|
}
|
|
@@ -215,10 +242,11 @@ export async function handleAgentRoutes(
|
|
|
215
242
|
return json({ error: "No API key found for this agent" }, 404);
|
|
216
243
|
}
|
|
217
244
|
|
|
218
|
-
// Return masked key (
|
|
245
|
+
// Return masked key + full key (full key only shown on demand by frontend)
|
|
219
246
|
const masked = apiKey.substring(0, 8) + "..." + apiKey.substring(apiKey.length - 4);
|
|
220
247
|
return json({
|
|
221
248
|
apiKey: masked,
|
|
249
|
+
fullKey: apiKey,
|
|
222
250
|
hasKey: true,
|
|
223
251
|
});
|
|
224
252
|
}
|
|
@@ -518,20 +518,29 @@ export async function handleIntegrationRoutes(
|
|
|
518
518
|
}
|
|
519
519
|
|
|
520
520
|
try {
|
|
521
|
+
console.log(`[agentdojo:add] configId=${configId} projectId=${projectId}`);
|
|
521
522
|
const server = await getAgentDojoServer(apiKey, configId);
|
|
522
523
|
if (!server) {
|
|
524
|
+
console.log(`[agentdojo:add] server not found from AgentDojo API for configId=${configId}`);
|
|
523
525
|
return json({ error: "Config not found" }, 404);
|
|
524
526
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
527
|
+
console.log(`[agentdojo:add] fetched server: slug=${server.slug} name=${server.name} url=${server.url?.substring(0, 80)}`);
|
|
528
|
+
|
|
529
|
+
// Check if already exists — match by slug in URL, scoped to same project
|
|
530
|
+
const effectiveProjectId = projectId && projectId !== "unassigned" ? projectId : null;
|
|
531
|
+
const allServers = McpServerDB.findAll();
|
|
532
|
+
const agentdojoServers = allServers.filter(s => s.source === "agentdojo");
|
|
533
|
+
console.log(`[agentdojo:add] total servers=${allServers.length} agentdojo servers=${agentdojoServers.length}`);
|
|
534
|
+
const existing = agentdojoServers.find(
|
|
535
|
+
s => s.project_id === effectiveProjectId && s.url?.endsWith(`/${server.slug}`)
|
|
529
536
|
);
|
|
530
537
|
if (existing) {
|
|
538
|
+
console.log(`[agentdojo:add] ALREADY EXISTS: id=${existing.id} project_id=${existing.project_id} slug=${server.slug}`);
|
|
531
539
|
return json({ server: existing, message: "Server already exists" });
|
|
532
540
|
}
|
|
533
541
|
|
|
534
542
|
// Create the MCP server entry
|
|
543
|
+
console.log(`[agentdojo:add] creating new server with effectiveProjectId=${effectiveProjectId}`);
|
|
535
544
|
const mcpServer = McpServerDB.create({
|
|
536
545
|
id: generateId(),
|
|
537
546
|
name: server.name,
|
|
@@ -544,12 +553,13 @@ export async function handleIntegrationRoutes(
|
|
|
544
553
|
url: server.url,
|
|
545
554
|
headers: { "X-API-Key": apiKey },
|
|
546
555
|
source: "agentdojo",
|
|
547
|
-
project_id:
|
|
556
|
+
project_id: effectiveProjectId,
|
|
548
557
|
});
|
|
558
|
+
console.log(`[agentdojo:add] created server: id=${mcpServer.id} project_id=${mcpServer.project_id}`);
|
|
549
559
|
|
|
550
560
|
return json({ server: mcpServer, message: "Server added successfully" });
|
|
551
561
|
} catch (e) {
|
|
552
|
-
console.error("Failed to add AgentDojo config:", e);
|
|
562
|
+
console.error("[agentdojo:add] Failed to add AgentDojo config:", e);
|
|
553
563
|
return json({ error: "Failed to add AgentDojo config" }, 500);
|
|
554
564
|
}
|
|
555
565
|
}
|
package/src/routes/api/mcp.ts
CHANGED
|
@@ -25,16 +25,23 @@ export async function handleMcpRoutes(
|
|
|
25
25
|
const forAgent = url.searchParams.get("forAgent"); // agent's project ID (shows global + project)
|
|
26
26
|
|
|
27
27
|
let servers;
|
|
28
|
+
let queryMode: string;
|
|
28
29
|
if (forAgent !== null) {
|
|
29
30
|
// Get servers available for an agent (global + agent's project)
|
|
30
31
|
servers = McpServerDB.findForAgent(forAgent || null);
|
|
32
|
+
queryMode = `forAgent=${forAgent}`;
|
|
31
33
|
} else if (projectFilter === "global") {
|
|
32
34
|
servers = McpServerDB.findGlobal();
|
|
35
|
+
queryMode = "global";
|
|
33
36
|
} else if (projectFilter && projectFilter !== "all") {
|
|
34
37
|
servers = McpServerDB.findByProject(projectFilter);
|
|
38
|
+
queryMode = `project=${projectFilter}`;
|
|
35
39
|
} else {
|
|
36
40
|
servers = McpServerDB.findAll();
|
|
41
|
+
queryMode = "all";
|
|
37
42
|
}
|
|
43
|
+
const agentdojoCount = servers.filter(s => s.source === "agentdojo").length;
|
|
44
|
+
console.log(`[mcp:GET] mode=${queryMode} total=${servers.length} agentdojo=${agentdojoCount}`);
|
|
38
45
|
return json({ servers });
|
|
39
46
|
}
|
|
40
47
|
|
|
@@ -266,7 +266,19 @@ export async function handleTriggerRoutes(
|
|
|
266
266
|
|
|
267
267
|
try {
|
|
268
268
|
const success = await provider.deleteTrigger(apiKey, triggerId);
|
|
269
|
-
|
|
269
|
+
|
|
270
|
+
// Also clean up any local subscriptions referencing this trigger instance
|
|
271
|
+
const localSubs = SubscriptionDB.findByTriggerInstanceId(triggerId);
|
|
272
|
+
let localDeleted = 0;
|
|
273
|
+
for (const sub of localSubs) {
|
|
274
|
+
SubscriptionDB.delete(sub.id);
|
|
275
|
+
localDeleted++;
|
|
276
|
+
}
|
|
277
|
+
if (localDeleted > 0) {
|
|
278
|
+
console.log(`[triggers] Cleaned up ${localDeleted} local subscription(s) for trigger ${triggerId}`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return json({ success, localSubscriptionsDeleted: localDeleted });
|
|
270
282
|
} catch (e) {
|
|
271
283
|
console.error(`Failed to delete trigger ${triggerId}:`, e);
|
|
272
284
|
return json({ error: "Failed to delete trigger" }, 500);
|
|
@@ -446,14 +458,42 @@ export async function handleTriggerRoutes(
|
|
|
446
458
|
}
|
|
447
459
|
}
|
|
448
460
|
|
|
449
|
-
// DELETE /api/subscriptions/:id
|
|
461
|
+
// DELETE /api/subscriptions/:id?provider=composio&project_id=xxx
|
|
450
462
|
const subDeleteMatch = path.match(/^\/api\/subscriptions\/([^/]+)$/);
|
|
451
463
|
if (subDeleteMatch && method === "DELETE") {
|
|
452
|
-
const
|
|
453
|
-
|
|
464
|
+
const subId = subDeleteMatch[1];
|
|
465
|
+
const sub = SubscriptionDB.findById(subId);
|
|
466
|
+
if (!sub) {
|
|
454
467
|
return json({ error: "Subscription not found" }, 404);
|
|
455
468
|
}
|
|
456
|
-
|
|
469
|
+
|
|
470
|
+
// Also delete the remote trigger if it exists
|
|
471
|
+
let remoteDeleted = false;
|
|
472
|
+
if (sub.trigger_instance_id) {
|
|
473
|
+
const url = new URL(req.url);
|
|
474
|
+
const providerId = url.searchParams.get("provider") || null;
|
|
475
|
+
const projectId = url.searchParams.get("project_id") || sub.project_id || null;
|
|
476
|
+
|
|
477
|
+
// Try to determine provider — check query param, or try all registered providers
|
|
478
|
+
const providerIds = providerId ? [providerId] : getTriggerProviderIds();
|
|
479
|
+
for (const pid of providerIds) {
|
|
480
|
+
const provider = getTriggerProvider(pid);
|
|
481
|
+
const apiKey = provider ? ProviderKeys.getDecryptedForProject(pid, projectId) : null;
|
|
482
|
+
if (provider && apiKey) {
|
|
483
|
+
try {
|
|
484
|
+
await provider.deleteTrigger(apiKey, sub.trigger_instance_id);
|
|
485
|
+
remoteDeleted = true;
|
|
486
|
+
console.log(`[subscriptions] Deleted remote trigger ${sub.trigger_instance_id} via ${pid}`);
|
|
487
|
+
break;
|
|
488
|
+
} catch (e) {
|
|
489
|
+
console.warn(`[subscriptions] Failed to delete remote trigger ${sub.trigger_instance_id} via ${pid}:`, e);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const success = SubscriptionDB.delete(subId);
|
|
496
|
+
return json({ success, remoteDeleted });
|
|
457
497
|
}
|
|
458
498
|
|
|
459
499
|
// POST /api/subscriptions/:id/enable
|