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
|
@@ -59,7 +59,7 @@ export function Dashboard({
|
|
|
59
59
|
|
|
60
60
|
if (tasksRes.ok) {
|
|
61
61
|
const data = await tasksRes.json();
|
|
62
|
-
setRecentTasks(
|
|
62
|
+
setRecentTasks(data.tasks || []);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
if (activityRes.ok) {
|
|
@@ -75,10 +75,12 @@ export function Dashboard({
|
|
|
75
75
|
fetchDashboardData();
|
|
76
76
|
}, [fetchDashboardData, statusChangeCounter]);
|
|
77
77
|
|
|
78
|
-
// Filter tasks by project agents
|
|
78
|
+
// Filter tasks by project agents and sort by next execution (soonest first)
|
|
79
79
|
const filteredTasks = useMemo(() => {
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
let list = currentProjectId
|
|
81
|
+
? recentTasks.filter(t => projectAgentIds.has(t.agentId))
|
|
82
|
+
: recentTasks;
|
|
83
|
+
return sortTasksByNextExecution(list);
|
|
82
84
|
}, [recentTasks, currentProjectId, projectAgentIds]);
|
|
83
85
|
|
|
84
86
|
// Calculate task stats from filtered tasks
|
|
@@ -179,9 +181,9 @@ export function Dashboard({
|
|
|
179
181
|
)}
|
|
180
182
|
</DashboardCard>
|
|
181
183
|
|
|
182
|
-
{/*
|
|
184
|
+
{/* Tasks */}
|
|
183
185
|
<DashboardCard
|
|
184
|
-
title="
|
|
186
|
+
title="Tasks"
|
|
185
187
|
actionLabel="View All"
|
|
186
188
|
onAction={() => onNavigate("tasks")}
|
|
187
189
|
>
|
|
@@ -192,7 +194,7 @@ export function Dashboard({
|
|
|
192
194
|
</div>
|
|
193
195
|
) : (
|
|
194
196
|
<div className="divide-y divide-[#1a1a1a]">
|
|
195
|
-
{filteredTasks.map((task) => (
|
|
197
|
+
{filteredTasks.slice(0, 5).map((task) => (
|
|
196
198
|
<div
|
|
197
199
|
key={`${task.agentId}-${task.id}`}
|
|
198
200
|
className="px-4 py-3 flex items-center justify-between"
|
|
@@ -343,6 +345,36 @@ function TaskStatusBadge({ status }: { status: Task["status"] }) {
|
|
|
343
345
|
);
|
|
344
346
|
}
|
|
345
347
|
|
|
348
|
+
// --- Task sorting helper ---
|
|
349
|
+
|
|
350
|
+
function statusPriority(task: Task): number {
|
|
351
|
+
if (task.status === "running") return 0;
|
|
352
|
+
if (task.status === "pending") return 1;
|
|
353
|
+
if (task.status === "completed") return 2;
|
|
354
|
+
if (task.status === "failed") return 3;
|
|
355
|
+
return 4; // cancelled etc
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function sortTasksByNextExecution(tasks: Task[]): Task[] {
|
|
359
|
+
return [...tasks].sort((a, b) => {
|
|
360
|
+
const aPri = statusPriority(a);
|
|
361
|
+
const bPri = statusPriority(b);
|
|
362
|
+
if (aPri !== bPri) return aPri - bPri;
|
|
363
|
+
// Within running/pending: soonest next execution first
|
|
364
|
+
if (aPri <= 1) {
|
|
365
|
+
const aTime = a.next_run || a.execute_at || null;
|
|
366
|
+
const bTime = b.next_run || b.execute_at || null;
|
|
367
|
+
const aTs = aTime ? new Date(aTime).getTime() : Infinity;
|
|
368
|
+
const bTs = bTime ? new Date(bTime).getTime() : Infinity;
|
|
369
|
+
return aTs - bTs;
|
|
370
|
+
}
|
|
371
|
+
// Within completed/failed: most recent first
|
|
372
|
+
const aDate = a.completed_at || a.executed_at || a.created_at;
|
|
373
|
+
const bDate = b.completed_at || b.executed_at || b.created_at;
|
|
374
|
+
return new Date(bDate).getTime() - new Date(aDate).getTime();
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
346
378
|
// --- Schedule formatting helpers (compact versions for dashboard) ---
|
|
347
379
|
|
|
348
380
|
const DASH_DAY_NAMES = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
@@ -22,10 +22,8 @@ interface HeaderProps {
|
|
|
22
22
|
|
|
23
23
|
export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
24
24
|
const { connected } = useTelemetryContext();
|
|
25
|
-
const { user, logout } = useAuth();
|
|
26
25
|
const authHeaders = useAuthHeaders();
|
|
27
26
|
const { projects, currentProjectId, currentProject, setCurrentProjectId, unassignedCount, projectsEnabled } = useProjects();
|
|
28
|
-
const [showUserMenu, setShowUserMenu] = useState(false);
|
|
29
27
|
const [showProjectMenu, setShowProjectMenu] = useState(false);
|
|
30
28
|
const [showNotifications, setShowNotifications] = useState(false);
|
|
31
29
|
const [unseenCount, setUnseenCount] = useState(0);
|
|
@@ -124,11 +122,6 @@ export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
|
124
122
|
}
|
|
125
123
|
}, [showNotifications, unseenCount, accessToken, projectAgentIds]);
|
|
126
124
|
|
|
127
|
-
const handleLogout = async () => {
|
|
128
|
-
await logout();
|
|
129
|
-
setShowUserMenu(false);
|
|
130
|
-
};
|
|
131
|
-
|
|
132
125
|
const handleProjectSelect = (projectId: string | null) => {
|
|
133
126
|
setCurrentProjectId(projectId);
|
|
134
127
|
setShowProjectMenu(false);
|
|
@@ -305,33 +298,6 @@ export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
|
305
298
|
)}
|
|
306
299
|
</div>
|
|
307
300
|
<MetaAgentButton />
|
|
308
|
-
{user && (
|
|
309
|
-
<div className="relative">
|
|
310
|
-
<button
|
|
311
|
-
onClick={() => setShowUserMenu(!showUserMenu)}
|
|
312
|
-
className="flex items-center gap-2 px-2 md:px-3 py-2 rounded hover:bg-[#1a1a1a] transition"
|
|
313
|
-
>
|
|
314
|
-
<div className="w-8 h-8 rounded-full bg-[#f97316] flex items-center justify-center text-black font-medium text-sm">
|
|
315
|
-
{user.username.charAt(0).toUpperCase()}
|
|
316
|
-
</div>
|
|
317
|
-
<span className="text-sm text-[#888] hidden sm:block">{user.username}</span>
|
|
318
|
-
</button>
|
|
319
|
-
{showUserMenu && (
|
|
320
|
-
<div className="absolute right-0 top-full mt-1 w-48 bg-[#111] border border-[#222] rounded-lg shadow-xl z-50">
|
|
321
|
-
<div className="px-4 py-3 border-b border-[#222]">
|
|
322
|
-
<p className="text-sm font-medium">{user.username}</p>
|
|
323
|
-
<p className="text-xs text-[#f97316] mt-1">{user.role}</p>
|
|
324
|
-
</div>
|
|
325
|
-
<button
|
|
326
|
-
onClick={handleLogout}
|
|
327
|
-
className="w-full px-4 py-2 text-left text-sm text-red-400 hover:bg-[#1a1a1a] transition"
|
|
328
|
-
>
|
|
329
|
-
Sign out
|
|
330
|
-
</button>
|
|
331
|
-
</div>
|
|
332
|
-
)}
|
|
333
|
-
</div>
|
|
334
|
-
)}
|
|
335
301
|
</div>
|
|
336
302
|
</div>
|
|
337
303
|
</header>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState } from "react";
|
|
2
2
|
import { DashboardIcon, ActivityIcon, AgentsIcon, TasksIcon, ConnectionsIcon, McpIcon, SkillsIcon, TestsIcon, TelemetryIcon, ApiIcon, SettingsIcon, CloseIcon } from "../common/Icons";
|
|
3
|
+
import { useAuth } from "../../context";
|
|
3
4
|
import type { Route } from "../../types";
|
|
4
5
|
|
|
5
6
|
interface SidebarProps {
|
|
@@ -12,11 +13,19 @@ interface SidebarProps {
|
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export function Sidebar({ route, agentCount, taskCount, onNavigate, isOpen, onClose }: SidebarProps) {
|
|
16
|
+
const { user, logout } = useAuth();
|
|
17
|
+
const [showUserMenu, setShowUserMenu] = useState(false);
|
|
18
|
+
|
|
15
19
|
const handleNavigate = (newRoute: Route) => {
|
|
16
20
|
onNavigate(newRoute);
|
|
17
21
|
onClose?.();
|
|
18
22
|
};
|
|
19
23
|
|
|
24
|
+
const handleLogout = async () => {
|
|
25
|
+
await logout();
|
|
26
|
+
setShowUserMenu(false);
|
|
27
|
+
};
|
|
28
|
+
|
|
20
29
|
return (
|
|
21
30
|
<>
|
|
22
31
|
{/* Mobile overlay backdrop */}
|
|
@@ -30,7 +39,7 @@ export function Sidebar({ route, agentCount, taskCount, onNavigate, isOpen, onCl
|
|
|
30
39
|
{/* Sidebar - hidden on mobile unless open, always visible on md+ */}
|
|
31
40
|
<aside
|
|
32
41
|
className={`
|
|
33
|
-
fixed inset-y-0 left-0 z-50 w-64 bg-[#0a0a0a] border-r border-[#1a1a1a] p-4 transform transition-transform duration-200 ease-in-out
|
|
42
|
+
fixed inset-y-0 left-0 z-50 w-64 bg-[#0a0a0a] border-r border-[#1a1a1a] p-4 flex flex-col transform transition-transform duration-200 ease-in-out
|
|
34
43
|
md:relative md:w-56 md:translate-x-0 md:z-auto
|
|
35
44
|
${isOpen ? "translate-x-0" : "-translate-x-full"}
|
|
36
45
|
`}
|
|
@@ -49,7 +58,7 @@ export function Sidebar({ route, agentCount, taskCount, onNavigate, isOpen, onCl
|
|
|
49
58
|
</button>
|
|
50
59
|
</div>
|
|
51
60
|
|
|
52
|
-
<nav className="space-y-1">
|
|
61
|
+
<nav className="space-y-1 flex-1">
|
|
53
62
|
<NavButton
|
|
54
63
|
icon={<DashboardIcon />}
|
|
55
64
|
label="Dashboard"
|
|
@@ -119,6 +128,37 @@ export function Sidebar({ route, agentCount, taskCount, onNavigate, isOpen, onCl
|
|
|
119
128
|
onClick={() => handleNavigate("settings")}
|
|
120
129
|
/>
|
|
121
130
|
</nav>
|
|
131
|
+
|
|
132
|
+
{/* User profile - pinned to bottom */}
|
|
133
|
+
{user && (
|
|
134
|
+
<div className="relative border-t border-[#1a1a1a] pt-3 mt-3">
|
|
135
|
+
<button
|
|
136
|
+
onClick={() => setShowUserMenu(!showUserMenu)}
|
|
137
|
+
className="w-full flex items-center gap-3 px-3 py-2 rounded hover:bg-[#111] transition"
|
|
138
|
+
>
|
|
139
|
+
<div className="w-8 h-8 rounded-full bg-[#f97316] flex items-center justify-center text-black font-medium text-sm flex-shrink-0">
|
|
140
|
+
{user.username.charAt(0).toUpperCase()}
|
|
141
|
+
</div>
|
|
142
|
+
<div className="flex-1 min-w-0 text-left">
|
|
143
|
+
<p className="text-sm font-medium truncate">{user.username}</p>
|
|
144
|
+
<p className="text-xs text-[#555]">{user.role}</p>
|
|
145
|
+
</div>
|
|
146
|
+
</button>
|
|
147
|
+
{showUserMenu && (
|
|
148
|
+
<>
|
|
149
|
+
<div className="fixed inset-0 z-40" onClick={() => setShowUserMenu(false)} />
|
|
150
|
+
<div className="absolute left-3 bottom-full mb-1 w-48 bg-[#111] border border-[#222] rounded-lg shadow-xl z-50">
|
|
151
|
+
<button
|
|
152
|
+
onClick={handleLogout}
|
|
153
|
+
className="w-full px-4 py-2.5 text-left text-sm text-red-400 hover:bg-[#1a1a1a] transition rounded-lg"
|
|
154
|
+
>
|
|
155
|
+
Sign out
|
|
156
|
+
</button>
|
|
157
|
+
</div>
|
|
158
|
+
</>
|
|
159
|
+
)}
|
|
160
|
+
</div>
|
|
161
|
+
)}
|
|
122
162
|
</aside>
|
|
123
163
|
</>
|
|
124
164
|
);
|
|
@@ -1366,6 +1366,7 @@ function AgentDojoContent({
|
|
|
1366
1366
|
const serversUrl = projectId && projectId !== "unassigned"
|
|
1367
1367
|
? `/api/mcp/servers?project=${encodeURIComponent(projectId)}`
|
|
1368
1368
|
: "/api/mcp/servers";
|
|
1369
|
+
console.log(`[AgentDojo:fetchConfigs] projectId=${projectId} serversUrl=${serversUrl}`);
|
|
1369
1370
|
const [configsRes, serversRes] = await Promise.all([
|
|
1370
1371
|
authFetch(`/api/integrations/agentdojo/configs${projectParam}`),
|
|
1371
1372
|
authFetch(serversUrl),
|
|
@@ -1373,18 +1374,24 @@ function AgentDojoContent({
|
|
|
1373
1374
|
const configsData = await configsRes.json();
|
|
1374
1375
|
const serversData = await serversRes.json();
|
|
1375
1376
|
|
|
1377
|
+
console.log(`[AgentDojo:fetchConfigs] configs=${(configsData.configs || []).length} servers=${(serversData.servers || []).length}`);
|
|
1376
1378
|
setConfigs(configsData.configs || []);
|
|
1377
1379
|
|
|
1378
1380
|
// Track which configs are already added as local servers
|
|
1381
|
+
const agentdojoServers = (serversData.servers || []).filter((s: any) => s.source === "agentdojo");
|
|
1382
|
+
console.log(`[AgentDojo:fetchConfigs] agentdojo servers found: ${agentdojoServers.length}`);
|
|
1383
|
+
for (const s of agentdojoServers) {
|
|
1384
|
+
const match = s.url?.match(/\/mcp\/([^/?]+)/);
|
|
1385
|
+
console.log(`[AgentDojo:fetchConfigs] server: id=${s.id} name=${s.name} project_id=${s.project_id} url=${s.url?.substring(0, 80)} extracted=${match ? match[1] : s.name}`);
|
|
1386
|
+
}
|
|
1379
1387
|
const agentdojoServerIds = new Set(
|
|
1380
|
-
(
|
|
1381
|
-
.filter((s: any) => s.source === "agentdojo")
|
|
1382
|
-
.map((s: any) => {
|
|
1388
|
+
agentdojoServers.map((s: any) => {
|
|
1383
1389
|
// Extract config ID from URL or match by name
|
|
1384
1390
|
const match = s.url?.match(/\/mcp\/([^/?]+)/);
|
|
1385
1391
|
return match ? match[1] : s.name;
|
|
1386
1392
|
})
|
|
1387
1393
|
);
|
|
1394
|
+
console.log(`[AgentDojo:fetchConfigs] addedServers set:`, [...agentdojoServerIds]);
|
|
1388
1395
|
setAddedServers(agentdojoServerIds);
|
|
1389
1396
|
} catch (e) {
|
|
1390
1397
|
console.error("Failed to fetch AgentDojo configs:", e);
|
|
@@ -1396,15 +1403,19 @@ function AgentDojoContent({
|
|
|
1396
1403
|
setAddingConfig(configId);
|
|
1397
1404
|
try {
|
|
1398
1405
|
const projectParam = projectId && projectId !== "unassigned" ? `?project_id=${projectId}` : "";
|
|
1406
|
+
console.log(`[AgentDojo:addConfig] configId=${configId} projectParam=${projectParam}`);
|
|
1399
1407
|
const res = await authFetch(`/api/integrations/agentdojo/configs/${configId}/add${projectParam}`, {
|
|
1400
1408
|
method: "POST",
|
|
1401
1409
|
});
|
|
1410
|
+
const data = await res.json();
|
|
1411
|
+
console.log(`[AgentDojo:addConfig] response status=${res.status} ok=${res.ok} message=${data.message} server.id=${data.server?.id} server.project_id=${data.server?.project_id}`);
|
|
1402
1412
|
if (res.ok) {
|
|
1403
1413
|
const config = configs.find(c => c.id === configId);
|
|
1404
|
-
|
|
1414
|
+
const addKey = config?.slug || configId;
|
|
1415
|
+
console.log(`[AgentDojo:addConfig] marking as added: key=${addKey} config.slug=${config?.slug} config.id=${config?.id} config.name=${config?.name}`);
|
|
1416
|
+
setAddedServers(prev => new Set([...prev, addKey]));
|
|
1405
1417
|
onServerAdded?.();
|
|
1406
1418
|
} else {
|
|
1407
|
-
const data = await res.json();
|
|
1408
1419
|
await alert(data.error || "Failed to add config", { title: "Error", variant: "error" });
|
|
1409
1420
|
}
|
|
1410
1421
|
} catch (e) {
|