apteva 0.2.7 → 0.2.9

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.
Files changed (46) hide show
  1. package/dist/App.m4hg4bxq.js +218 -0
  2. package/dist/index.html +4 -2
  3. package/dist/styles.css +1 -1
  4. package/package.json +1 -1
  5. package/src/auth/index.ts +386 -0
  6. package/src/auth/middleware.ts +183 -0
  7. package/src/binary.ts +19 -1
  8. package/src/db.ts +688 -45
  9. package/src/integrations/composio.ts +437 -0
  10. package/src/integrations/index.ts +80 -0
  11. package/src/openapi.ts +1724 -0
  12. package/src/routes/api.ts +1476 -118
  13. package/src/routes/auth.ts +242 -0
  14. package/src/server.ts +121 -11
  15. package/src/web/App.tsx +64 -19
  16. package/src/web/components/agents/AgentCard.tsx +24 -22
  17. package/src/web/components/agents/AgentPanel.tsx +810 -45
  18. package/src/web/components/agents/AgentsView.tsx +81 -9
  19. package/src/web/components/agents/CreateAgentModal.tsx +28 -1
  20. package/src/web/components/api/ApiDocsPage.tsx +583 -0
  21. package/src/web/components/auth/CreateAccountStep.tsx +176 -0
  22. package/src/web/components/auth/LoginPage.tsx +91 -0
  23. package/src/web/components/auth/index.ts +2 -0
  24. package/src/web/components/common/Icons.tsx +56 -0
  25. package/src/web/components/common/Modal.tsx +184 -1
  26. package/src/web/components/dashboard/Dashboard.tsx +70 -22
  27. package/src/web/components/index.ts +3 -0
  28. package/src/web/components/layout/Header.tsx +135 -18
  29. package/src/web/components/layout/Sidebar.tsx +87 -43
  30. package/src/web/components/mcp/IntegrationsPanel.tsx +743 -0
  31. package/src/web/components/mcp/McpPage.tsx +451 -63
  32. package/src/web/components/onboarding/OnboardingWizard.tsx +64 -8
  33. package/src/web/components/settings/SettingsPage.tsx +340 -26
  34. package/src/web/components/tasks/TasksPage.tsx +22 -20
  35. package/src/web/components/telemetry/TelemetryPage.tsx +163 -61
  36. package/src/web/context/AuthContext.tsx +230 -0
  37. package/src/web/context/ProjectContext.tsx +182 -0
  38. package/src/web/context/index.ts +5 -0
  39. package/src/web/hooks/useAgents.ts +18 -6
  40. package/src/web/hooks/useOnboarding.ts +20 -4
  41. package/src/web/hooks/useProviders.ts +15 -5
  42. package/src/web/icon.png +0 -0
  43. package/src/web/index.html +1 -1
  44. package/src/web/styles.css +12 -0
  45. package/src/web/types.ts +10 -1
  46. package/dist/App.3kb50qa3.js +0 -213
@@ -4,6 +4,9 @@ export { LoadingSpinner, Modal, Select, CheckIcon, CloseIcon, DashboardIcon, Age
4
4
  // Layout components
5
5
  export { Header, Sidebar, ErrorBanner } from "./layout";
6
6
 
7
+ // Auth components
8
+ export { LoginPage, CreateAccountStep } from "./auth";
9
+
7
10
  // Feature components
8
11
  export { OnboardingWizard } from "./onboarding";
9
12
  export { SettingsPage } from "./settings";
@@ -1,37 +1,154 @@
1
- import React from "react";
2
- import { useTelemetryContext } from "../../context";
1
+ import React, { useState } from "react";
2
+ import { useTelemetryContext, useAuth, useProjects } from "../../context";
3
+ import { MenuIcon, ChevronDownIcon } from "../common/Icons";
3
4
 
4
5
  interface HeaderProps {
5
- onNewAgent: () => void;
6
- canCreateAgent: boolean;
6
+ onMenuClick?: () => void;
7
7
  }
8
8
 
9
- export function Header({ onNewAgent, canCreateAgent }: HeaderProps) {
9
+ export function Header({ onMenuClick }: HeaderProps) {
10
10
  const { connected } = useTelemetryContext();
11
+ const { user, logout } = useAuth();
12
+ const { projects, currentProjectId, currentProject, setCurrentProjectId, unassignedCount } = useProjects();
13
+ const [showUserMenu, setShowUserMenu] = useState(false);
14
+ const [showProjectMenu, setShowProjectMenu] = useState(false);
15
+
16
+ const handleLogout = async () => {
17
+ await logout();
18
+ setShowUserMenu(false);
19
+ };
20
+
21
+ const handleProjectSelect = (projectId: string | null) => {
22
+ setCurrentProjectId(projectId);
23
+ setShowProjectMenu(false);
24
+ };
25
+
26
+ const getProjectLabel = () => {
27
+ if (currentProjectId === null) return "All Projects";
28
+ if (currentProjectId === "unassigned") return "Unassigned";
29
+ return currentProject?.name || "Select Project";
30
+ };
31
+
32
+ const getProjectColor = () => {
33
+ if (currentProjectId === null) return "#666";
34
+ if (currentProjectId === "unassigned") return "#888";
35
+ return currentProject?.color || "#6366f1";
36
+ };
11
37
 
12
38
  return (
13
- <header className="border-b border-[#1a1a1a] px-6 py-4 flex-shrink-0">
39
+ <header className="border-b border-[#1a1a1a] px-4 md:px-6 py-4 flex-shrink-0">
14
40
  <div className="flex items-center justify-between">
15
- <div className="flex items-center gap-2">
16
- <span className="text-[#f97316]">&gt;_</span>
17
- <span className="text-xl tracking-wider">apteva</span>
41
+ <div className="flex items-center gap-3">
42
+ {/* Hamburger menu button - mobile only */}
43
+ <button
44
+ onClick={onMenuClick}
45
+ className="p-2 -ml-2 text-[#666] hover:text-[#e0e0e0] transition md:hidden"
46
+ >
47
+ <MenuIcon />
48
+ </button>
49
+ <div className="flex items-center gap-2">
50
+ <span className="text-[#f97316]">&gt;_</span>
51
+ <span className="text-xl tracking-wider">apteva</span>
52
+ </div>
53
+
54
+ {/* Project Selector */}
55
+ {projects.length > 0 && (
56
+ <div className="relative ml-2 md:ml-4">
57
+ <button
58
+ onClick={() => setShowProjectMenu(!showProjectMenu)}
59
+ className="flex items-center gap-2 px-3 py-1.5 rounded border border-[#222] bg-[#111] hover:bg-[#1a1a1a] transition text-sm"
60
+ >
61
+ <span
62
+ className="w-2.5 h-2.5 rounded-full"
63
+ style={{ backgroundColor: getProjectColor() }}
64
+ />
65
+ <span className="hidden sm:inline max-w-[120px] md:max-w-[180px] truncate">
66
+ {getProjectLabel()}
67
+ </span>
68
+ <ChevronDownIcon />
69
+ </button>
70
+ {showProjectMenu && (
71
+ <div className="absolute left-0 top-full mt-1 w-56 bg-[#111] border border-[#222] rounded-lg shadow-xl z-50">
72
+ <div className="py-1 max-h-64 overflow-y-auto">
73
+ <button
74
+ onClick={() => handleProjectSelect(null)}
75
+ className={`w-full px-4 py-2 text-left text-sm flex items-center gap-2 hover:bg-[#1a1a1a] transition ${
76
+ currentProjectId === null ? "bg-[#1a1a1a] text-[#f97316]" : ""
77
+ }`}
78
+ >
79
+ <span className="w-2.5 h-2.5 rounded-full bg-[#666]" />
80
+ All Projects
81
+ </button>
82
+ {projects.map(project => (
83
+ <button
84
+ key={project.id}
85
+ onClick={() => handleProjectSelect(project.id)}
86
+ className={`w-full px-4 py-2 text-left text-sm flex items-center gap-2 hover:bg-[#1a1a1a] transition ${
87
+ currentProjectId === project.id ? "bg-[#1a1a1a] text-[#f97316]" : ""
88
+ }`}
89
+ >
90
+ <span
91
+ className="w-2.5 h-2.5 rounded-full flex-shrink-0"
92
+ style={{ backgroundColor: project.color }}
93
+ />
94
+ <span className="truncate">{project.name}</span>
95
+ <span className="ml-auto text-xs text-[#666]">{project.agentCount}</span>
96
+ </button>
97
+ ))}
98
+ {unassignedCount > 0 && (
99
+ <button
100
+ onClick={() => handleProjectSelect("unassigned")}
101
+ className={`w-full px-4 py-2 text-left text-sm flex items-center gap-2 hover:bg-[#1a1a1a] transition ${
102
+ currentProjectId === "unassigned" ? "bg-[#1a1a1a] text-[#f97316]" : ""
103
+ }`}
104
+ >
105
+ <span className="w-2.5 h-2.5 rounded-full bg-[#888]" />
106
+ <span className="truncate">Unassigned</span>
107
+ <span className="ml-auto text-xs text-[#666]">{unassignedCount}</span>
108
+ </button>
109
+ )}
110
+ </div>
111
+ </div>
112
+ )}
113
+ </div>
114
+ )}
18
115
  </div>
19
- <div className="flex items-center gap-4">
116
+ <div className="flex items-center gap-3 md:gap-4">
20
117
  <div className="flex items-center gap-2">
21
118
  <span
22
119
  className={`w-2 h-2 rounded-full ${connected ? "bg-green-400" : "bg-red-400"}`}
23
120
  />
24
- <span className="text-xs text-[#666]">
121
+ <span className="text-xs text-[#666] hidden sm:inline">
25
122
  {connected ? "Live" : "Offline"}
26
123
  </span>
27
124
  </div>
28
- <button
29
- onClick={onNewAgent}
30
- disabled={!canCreateAgent}
31
- className="bg-[#f97316] hover:bg-[#fb923c] disabled:opacity-50 disabled:cursor-not-allowed text-black px-4 py-2 rounded font-medium transition"
32
- >
33
- + New Agent
34
- </button>
125
+ {user && (
126
+ <div className="relative">
127
+ <button
128
+ onClick={() => setShowUserMenu(!showUserMenu)}
129
+ className="flex items-center gap-2 px-2 md:px-3 py-2 rounded hover:bg-[#1a1a1a] transition"
130
+ >
131
+ <div className="w-8 h-8 rounded-full bg-[#f97316] flex items-center justify-center text-black font-medium text-sm">
132
+ {user.username.charAt(0).toUpperCase()}
133
+ </div>
134
+ <span className="text-sm text-[#888] hidden sm:block">{user.username}</span>
135
+ </button>
136
+ {showUserMenu && (
137
+ <div className="absolute right-0 top-full mt-1 w-48 bg-[#111] border border-[#222] rounded-lg shadow-xl z-50">
138
+ <div className="px-4 py-3 border-b border-[#222]">
139
+ <p className="text-sm font-medium">{user.username}</p>
140
+ <p className="text-xs text-[#f97316] mt-1">{user.role}</p>
141
+ </div>
142
+ <button
143
+ onClick={handleLogout}
144
+ className="w-full px-4 py-2 text-left text-sm text-red-400 hover:bg-[#1a1a1a] transition"
145
+ >
146
+ Sign out
147
+ </button>
148
+ </div>
149
+ )}
150
+ </div>
151
+ )}
35
152
  </div>
36
153
  </div>
37
154
  </header>
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { DashboardIcon, AgentsIcon, TasksIcon, McpIcon, TelemetryIcon, SettingsIcon } from "../common/Icons";
2
+ import { DashboardIcon, AgentsIcon, TasksIcon, McpIcon, TelemetryIcon, ApiIcon, SettingsIcon, CloseIcon } from "../common/Icons";
3
3
  import type { Route } from "../../types";
4
4
 
5
5
  interface SidebarProps {
@@ -7,52 +7,96 @@ interface SidebarProps {
7
7
  agentCount: number;
8
8
  taskCount?: number;
9
9
  onNavigate: (route: Route) => void;
10
+ isOpen?: boolean;
11
+ onClose?: () => void;
10
12
  }
11
13
 
12
- export function Sidebar({ route, agentCount, taskCount, onNavigate }: SidebarProps) {
14
+ export function Sidebar({ route, agentCount, taskCount, onNavigate, isOpen, onClose }: SidebarProps) {
15
+ const handleNavigate = (newRoute: Route) => {
16
+ onNavigate(newRoute);
17
+ onClose?.();
18
+ };
19
+
13
20
  return (
14
- <aside className="w-56 border-r border-[#1a1a1a] flex-shrink-0 p-4">
15
- <nav className="space-y-1">
16
- <NavButton
17
- icon={<DashboardIcon />}
18
- label="Dashboard"
19
- active={route === "dashboard"}
20
- onClick={() => onNavigate("dashboard")}
21
- />
22
- <NavButton
23
- icon={<AgentsIcon />}
24
- label="Agents"
25
- active={route === "agents"}
26
- onClick={() => onNavigate("agents")}
27
- badge={agentCount > 0 ? String(agentCount) : undefined}
28
- />
29
- <NavButton
30
- icon={<TasksIcon />}
31
- label="Tasks"
32
- active={route === "tasks"}
33
- onClick={() => onNavigate("tasks")}
34
- badge={taskCount && taskCount > 0 ? String(taskCount) : undefined}
35
- />
36
- <NavButton
37
- icon={<McpIcon />}
38
- label="MCP"
39
- active={route === "mcp"}
40
- onClick={() => onNavigate("mcp")}
41
- />
42
- <NavButton
43
- icon={<TelemetryIcon />}
44
- label="Telemetry"
45
- active={route === "telemetry"}
46
- onClick={() => onNavigate("telemetry")}
21
+ <>
22
+ {/* Mobile overlay backdrop */}
23
+ {isOpen && (
24
+ <div
25
+ className="fixed inset-0 bg-black/60 z-40 md:hidden"
26
+ onClick={onClose}
47
27
  />
48
- <NavButton
49
- icon={<SettingsIcon />}
50
- label="Settings"
51
- active={route === "settings"}
52
- onClick={() => onNavigate("settings")}
53
- />
54
- </nav>
55
- </aside>
28
+ )}
29
+
30
+ {/* Sidebar - hidden on mobile unless open, always visible on md+ */}
31
+ <aside
32
+ 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
34
+ md:relative md:w-56 md:translate-x-0 md:z-auto
35
+ ${isOpen ? "translate-x-0" : "-translate-x-full"}
36
+ `}
37
+ >
38
+ {/* Mobile header with close button */}
39
+ <div className="flex items-center justify-between mb-4 md:hidden">
40
+ <div className="flex items-center gap-2">
41
+ <span className="text-[#f97316]">&gt;_</span>
42
+ <span className="text-lg tracking-wider">apteva</span>
43
+ </div>
44
+ <button
45
+ onClick={onClose}
46
+ className="p-2 text-[#666] hover:text-[#e0e0e0] transition"
47
+ >
48
+ <CloseIcon />
49
+ </button>
50
+ </div>
51
+
52
+ <nav className="space-y-1">
53
+ <NavButton
54
+ icon={<DashboardIcon />}
55
+ label="Dashboard"
56
+ active={route === "dashboard"}
57
+ onClick={() => handleNavigate("dashboard")}
58
+ />
59
+ <NavButton
60
+ icon={<AgentsIcon />}
61
+ label="Agents"
62
+ active={route === "agents"}
63
+ onClick={() => handleNavigate("agents")}
64
+ badge={agentCount > 0 ? String(agentCount) : undefined}
65
+ />
66
+ <NavButton
67
+ icon={<TasksIcon />}
68
+ label="Tasks"
69
+ active={route === "tasks"}
70
+ onClick={() => handleNavigate("tasks")}
71
+ badge={taskCount && taskCount > 0 ? String(taskCount) : undefined}
72
+ />
73
+ <NavButton
74
+ icon={<McpIcon />}
75
+ label="MCP"
76
+ active={route === "mcp"}
77
+ onClick={() => handleNavigate("mcp")}
78
+ />
79
+ <NavButton
80
+ icon={<TelemetryIcon />}
81
+ label="Telemetry"
82
+ active={route === "telemetry"}
83
+ onClick={() => handleNavigate("telemetry")}
84
+ />
85
+ <NavButton
86
+ icon={<ApiIcon />}
87
+ label="API"
88
+ active={route === "api"}
89
+ onClick={() => handleNavigate("api")}
90
+ />
91
+ <NavButton
92
+ icon={<SettingsIcon />}
93
+ label="Settings"
94
+ active={route === "settings"}
95
+ onClick={() => handleNavigate("settings")}
96
+ />
97
+ </nav>
98
+ </aside>
99
+ </>
56
100
  );
57
101
  }
58
102