apteva 0.4.41 → 0.4.44
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.c48n83h2.js +3 -0
- package/dist/ApiDocsPage.yzcxx5ax.js +4 -0
- package/dist/App.09yb8t0b.js +1 -0
- package/dist/App.152mbs1r.js +4 -0
- package/dist/App.3a67nx9w.js +4 -0
- package/dist/App.9epx6785.js +4 -0
- package/dist/App.d8955awp.js +4 -0
- package/dist/App.drwb57jq.js +4 -0
- package/dist/App.gssbmajb.js +4 -0
- package/dist/App.qw70pc29.js +53 -0
- package/dist/{App.7fb3e7mp.js → App.qzbx5wtj.js} +1 -1
- package/dist/App.r5serxkt.js +8 -0
- package/dist/App.tpmp9020.js +20 -0
- package/dist/App.v2wb4d7d.js +61 -0
- package/dist/App.vxmaaj0m.js +13 -0
- package/dist/App.w4p2tda9.js +4 -0
- package/dist/App.wv2ng55q.js +221 -0
- package/dist/App.yncnrn0f.js +4 -0
- package/dist/ConnectionsPage.k6cspyqq.js +3 -0
- package/dist/McpPage.cdxm48xj.js +3 -0
- package/dist/SettingsPage.evpv7c2y.js +3 -0
- package/dist/SkillsPage.pvzp6c1a.js +3 -0
- package/dist/TasksPage.6jnvbpsy.js +3 -0
- package/dist/TelemetryPage.t7vk24zc.js +3 -0
- package/dist/TestsPage.5x6658aa.js +3 -0
- package/dist/ThreadsPage.3fvhtevh.js +3 -0
- package/dist/apteva-kit.css +1 -1
- package/dist/index.html +1 -1
- package/dist/styles.css +1 -1
- package/package.json +8 -8
- package/src/db.ts +19 -9
- package/src/integrations/agentdojo.ts +1 -0
- package/src/mcp-platform.ts +418 -63
- package/src/openapi.ts +96 -0
- package/src/providers.ts +50 -24
- package/src/routes/api/agent-utils.ts +0 -1
- package/src/routes/api/agents.ts +19 -1
- package/src/routes/api/meta-agent.ts +2 -0
- package/src/routes/api/system.ts +90 -1
- package/src/routes/api/telemetry.ts +19 -1
- package/src/routes/share.ts +85 -0
- package/src/server.ts +12 -0
- package/src/web/App.tsx +89 -11
- package/src/web/components/activity/ActivityPage.tsx +14 -14
- package/src/web/components/agents/AgentCard.tsx +14 -14
- package/src/web/components/agents/AgentPanel.tsx +358 -198
- package/src/web/components/agents/AgentsView.tsx +4 -4
- package/src/web/components/agents/CreateAgentModal.tsx +21 -79
- package/src/web/components/api/ApiDocsPage.tsx +66 -66
- package/src/web/components/auth/CreateAccountStep.tsx +16 -16
- package/src/web/components/auth/LoginPage.tsx +10 -10
- package/src/web/components/common/LoadingSpinner.tsx +2 -2
- package/src/web/components/common/Modal.tsx +8 -8
- package/src/web/components/common/Select.tsx +9 -9
- package/src/web/components/connections/ConnectionsPage.tsx +4 -4
- package/src/web/components/connections/IntegrationsTab.tsx +18 -18
- package/src/web/components/connections/OverviewTab.tsx +13 -13
- package/src/web/components/connections/TriggersTab.tsx +99 -99
- package/src/web/components/dashboard/Dashboard.tsx +32 -32
- package/src/web/components/layout/Header.tsx +50 -34
- package/src/web/components/layout/Sidebar.tsx +34 -15
- package/src/web/components/mcp/IntegrationsPanel.tsx +40 -40
- package/src/web/components/mcp/McpPage.tsx +208 -208
- package/src/web/components/meta-agent/MetaAgent.tsx +12 -10
- package/src/web/components/onboarding/OnboardingWizard.tsx +25 -25
- package/src/web/components/settings/SettingsPage.tsx +258 -175
- package/src/web/components/skills/SkillsPage.tsx +88 -88
- package/src/web/components/tasks/TasksPage.tsx +339 -54
- package/src/web/components/telemetry/TelemetryPage.tsx +135 -64
- package/src/web/components/tests/TestsPage.tsx +50 -50
- package/src/web/components/threads/ThreadsPage.tsx +23 -21
- package/src/web/context/ProjectContext.tsx +6 -1
- package/src/web/context/ThemeContext.tsx +69 -0
- package/src/web/context/index.ts +2 -0
- package/src/web/styles.css +5 -3
- package/src/web/themes.ts +99 -0
- package/src/web/types.ts +0 -4
- package/dist/ActivityPage.7907h64p.js +0 -3
- package/dist/ApiDocsPage.k3jjenpq.js +0 -4
- package/dist/App.01nq20st.js +0 -4
- package/dist/App.1maqvamf.js +0 -4
- package/dist/App.2yjrh32f.js +0 -4
- package/dist/App.3qw8nben.js +0 -20
- package/dist/App.7sy3wq8c.js +0 -4
- package/dist/App.apjrmctz.js +0 -57
- package/dist/App.av6t2yhe.js +0 -4
- package/dist/App.jqj5a094.js +0 -46
- package/dist/App.mc7xf85h.js +0 -4
- package/dist/App.myxqcj9x.js +0 -4
- package/dist/App.nm91r1mp.js +0 -13
- package/dist/App.p02f4ret.js +0 -1
- package/dist/App.qcknavjz.js +0 -221
- package/dist/App.vc7vfhg4.js +0 -4
- package/dist/App.z4s9zkw5.js +0 -4
- package/dist/ConnectionsPage.z1pw5xe2.js +0 -3
- package/dist/McpPage.8vc97z0b.js +0 -3
- package/dist/SettingsPage.p61bz8kd.js +0 -3
- package/dist/SkillsPage.r9x43g3g.js +0 -3
- package/dist/TasksPage.1e0zkye4.js +0 -3
- package/dist/TelemetryPage.p9vbe4gf.js +0 -3
- package/dist/TestsPage.d4xy504e.js +0 -3
- package/dist/ThreadsPage.m016am3x.js +0 -3
|
@@ -149,7 +149,7 @@ export function Dashboard({
|
|
|
149
149
|
<StatCard label="Agents" value={filteredAgents.length} subValue={`${filteredRunningCount} running`} />
|
|
150
150
|
<StatCard label="Tasks" value={taskStats.total} subValue={`${taskStats.pending} pending`} />
|
|
151
151
|
<StatCard label="Completed" value={taskStats.completed} color="text-green-400" />
|
|
152
|
-
<StatCard label="Providers" value={configuredProviders.length} color="text-[
|
|
152
|
+
<StatCard label="Providers" value={configuredProviders.length} color="text-[var(--color-accent)]" />
|
|
153
153
|
</div>
|
|
154
154
|
|
|
155
155
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
@@ -160,11 +160,11 @@ export function Dashboard({
|
|
|
160
160
|
onAction={() => onNavigate("agents")}
|
|
161
161
|
>
|
|
162
162
|
{loading ? (
|
|
163
|
-
<div className="p-4 text-center text-[
|
|
163
|
+
<div className="p-4 text-center text-[var(--color-text-muted)]">Loading...</div>
|
|
164
164
|
) : filteredAgents.length === 0 ? (
|
|
165
|
-
<div className="p-4 text-center text-[
|
|
165
|
+
<div className="p-4 text-center text-[var(--color-text-muted)]">No agents yet</div>
|
|
166
166
|
) : (
|
|
167
|
-
<div className="divide-y divide-[
|
|
167
|
+
<div className="divide-y divide-[var(--color-border)]">
|
|
168
168
|
{filteredAgents.slice(0, 5).map((agent) => (
|
|
169
169
|
<AgentListItem
|
|
170
170
|
key={agent.id}
|
|
@@ -185,12 +185,12 @@ export function Dashboard({
|
|
|
185
185
|
onAction={() => onNavigate("telemetry")}
|
|
186
186
|
>
|
|
187
187
|
{activities.length === 0 ? (
|
|
188
|
-
<div className="p-4 text-center text-[
|
|
188
|
+
<div className="p-4 text-center text-[var(--color-text-muted)]">
|
|
189
189
|
<p>No activity yet</p>
|
|
190
|
-
<p className="text-sm text-[
|
|
190
|
+
<p className="text-sm text-[var(--color-text-faint)] mt-1">Agent activity will appear here in real-time</p>
|
|
191
191
|
</div>
|
|
192
192
|
) : (
|
|
193
|
-
<div className="divide-y divide-[
|
|
193
|
+
<div className="divide-y divide-[var(--color-border)]">
|
|
194
194
|
{activities.map((evt) => (
|
|
195
195
|
<ActivityItem
|
|
196
196
|
key={evt.id}
|
|
@@ -210,12 +210,12 @@ export function Dashboard({
|
|
|
210
210
|
onAction={() => onNavigate("tasks")}
|
|
211
211
|
>
|
|
212
212
|
{filteredTasks.length === 0 ? (
|
|
213
|
-
<div className="p-4 text-center text-[
|
|
213
|
+
<div className="p-4 text-center text-[var(--color-text-muted)]">
|
|
214
214
|
<p>No tasks yet</p>
|
|
215
|
-
<p className="text-sm text-[
|
|
215
|
+
<p className="text-sm text-[var(--color-text-faint)] mt-1">Tasks will appear when agents create them</p>
|
|
216
216
|
</div>
|
|
217
217
|
) : (
|
|
218
|
-
<div className="divide-y divide-[
|
|
218
|
+
<div className="divide-y divide-[var(--color-border)]">
|
|
219
219
|
{filteredTasks.slice(0, 5).map((task) => (
|
|
220
220
|
<div
|
|
221
221
|
key={`${task.agentId}-${task.id}`}
|
|
@@ -223,16 +223,16 @@ export function Dashboard({
|
|
|
223
223
|
>
|
|
224
224
|
<div className="flex-1 min-w-0">
|
|
225
225
|
<p className="font-medium truncate">{task.title}</p>
|
|
226
|
-
<p className="text-sm text-[
|
|
226
|
+
<p className="text-sm text-[var(--color-text-muted)]">
|
|
227
227
|
{task.agentName}
|
|
228
228
|
{task.recurrence && (
|
|
229
|
-
<span className="ml-1 text-[
|
|
229
|
+
<span className="ml-1 text-[var(--color-text-faint)]">· {formatCronShort(task.recurrence)}</span>
|
|
230
230
|
)}
|
|
231
231
|
{task.next_run && (
|
|
232
|
-
<span className="ml-1 text-[
|
|
232
|
+
<span className="ml-1 text-[var(--color-accent)]">· {formatRelativeShort(task.next_run)}</span>
|
|
233
233
|
)}
|
|
234
234
|
{!task.next_run && task.execute_at && (
|
|
235
|
-
<span className="ml-1 text-[
|
|
235
|
+
<span className="ml-1 text-[var(--color-accent)]">· {formatRelativeShort(task.execute_at)}</span>
|
|
236
236
|
)}
|
|
237
237
|
</p>
|
|
238
238
|
</div>
|
|
@@ -264,10 +264,10 @@ interface StatCardProps {
|
|
|
264
264
|
|
|
265
265
|
function StatCard({ label, value, subValue, color }: StatCardProps) {
|
|
266
266
|
return (
|
|
267
|
-
<div className="bg-[
|
|
268
|
-
<p className="text-sm text-[
|
|
267
|
+
<div className="bg-[var(--color-surface)] rounded p-4 border border-[var(--color-border)]">
|
|
268
|
+
<p className="text-sm text-[var(--color-text-muted)] mb-1">{label}</p>
|
|
269
269
|
<p className={`text-2xl font-semibold ${color || ''}`}>{value}</p>
|
|
270
|
-
{subValue && <p className="text-xs text-[
|
|
270
|
+
{subValue && <p className="text-xs text-[var(--color-text-faint)] mt-1">{subValue}</p>}
|
|
271
271
|
</div>
|
|
272
272
|
);
|
|
273
273
|
}
|
|
@@ -281,8 +281,8 @@ interface DashboardCardProps {
|
|
|
281
281
|
|
|
282
282
|
function DashboardCard({ title, actionLabel, onAction, children }: DashboardCardProps) {
|
|
283
283
|
return (
|
|
284
|
-
<div className="bg-[
|
|
285
|
-
<div className="px-4 py-3 border-b border-[
|
|
284
|
+
<div className="bg-[var(--color-surface)] rounded border border-[var(--color-border)] overflow-hidden">
|
|
285
|
+
<div className="px-4 py-3 border-b border-[var(--color-border)] flex items-center justify-between">
|
|
286
286
|
<h3 className="font-semibold">{title}</h3>
|
|
287
287
|
<button
|
|
288
288
|
onClick={onAction}
|
|
@@ -304,7 +304,7 @@ function AgentListItem({ agent, onSelect, onMessage, showProject }: { agent: Age
|
|
|
304
304
|
return (
|
|
305
305
|
<div
|
|
306
306
|
onClick={onSelect}
|
|
307
|
-
className="px-4 py-3 hover:bg-[
|
|
307
|
+
className="px-4 py-3 hover:bg-[var(--color-surface-raised)] cursor-pointer flex items-center justify-between group"
|
|
308
308
|
>
|
|
309
309
|
<div className="flex items-center gap-3 flex-1 min-w-0">
|
|
310
310
|
<span
|
|
@@ -313,12 +313,12 @@ function AgentListItem({ agent, onSelect, onMessage, showProject }: { agent: Age
|
|
|
313
313
|
? isActive
|
|
314
314
|
? "bg-green-400 animate-pulse"
|
|
315
315
|
: "bg-[#3b82f6]"
|
|
316
|
-
: "bg-[
|
|
316
|
+
: "bg-[var(--color-scrollbar)]"
|
|
317
317
|
}`}
|
|
318
318
|
/>
|
|
319
319
|
<div className="flex-1 min-w-0">
|
|
320
320
|
<p className="font-medium truncate">{agent.name}</p>
|
|
321
|
-
<div className="flex items-center gap-2 text-sm text-[
|
|
321
|
+
<div className="flex items-center gap-2 text-sm text-[var(--color-text-muted)]">
|
|
322
322
|
{isActive && label ? (
|
|
323
323
|
<span className="text-green-400 truncate">{label}</span>
|
|
324
324
|
) : (
|
|
@@ -326,7 +326,7 @@ function AgentListItem({ agent, onSelect, onMessage, showProject }: { agent: Age
|
|
|
326
326
|
)}
|
|
327
327
|
{showProject && project && (
|
|
328
328
|
<>
|
|
329
|
-
<span className="text-[
|
|
329
|
+
<span className="text-[var(--color-text-faint)]">·</span>
|
|
330
330
|
<span className="flex items-center gap-1">
|
|
331
331
|
<span className="w-2 h-2 rounded-full" style={{ backgroundColor: project.color }} />
|
|
332
332
|
{project.name}
|
|
@@ -339,7 +339,7 @@ function AgentListItem({ agent, onSelect, onMessage, showProject }: { agent: Age
|
|
|
339
339
|
{onMessage && (
|
|
340
340
|
<button
|
|
341
341
|
onClick={(e) => { e.stopPropagation(); onMessage(); }}
|
|
342
|
-
className="opacity-0 group-hover:opacity-100 transition px-2 py-1 text-xs text-[
|
|
342
|
+
className="opacity-0 group-hover:opacity-100 transition px-2 py-1 text-xs text-[var(--color-accent)] hover:bg-[var(--color-accent-10)] rounded"
|
|
343
343
|
title="Send message"
|
|
344
344
|
>
|
|
345
345
|
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -367,9 +367,9 @@ function ActivityItem({ activity, agentName, timestamp }: { activity: string; ag
|
|
|
367
367
|
return (
|
|
368
368
|
<div className="px-4 py-3">
|
|
369
369
|
<p className="text-sm truncate">{activity}</p>
|
|
370
|
-
<div className="flex items-center gap-2 text-xs text-[
|
|
371
|
-
<span className="text-[
|
|
372
|
-
<span className="text-[
|
|
370
|
+
<div className="flex items-center gap-2 text-xs text-[var(--color-text-faint)] mt-1">
|
|
371
|
+
<span className="text-[var(--color-text-muted)]">{agentName}</span>
|
|
372
|
+
<span className="text-[var(--color-text-faint)]">·</span>
|
|
373
373
|
<span>{timeAgo(timestamp)}</span>
|
|
374
374
|
</div>
|
|
375
375
|
</div>
|
|
@@ -428,13 +428,13 @@ function QuickMessageModal({ agent, onClose }: { agent: Agent; onClose: () => vo
|
|
|
428
428
|
return (
|
|
429
429
|
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
|
430
430
|
<div className="absolute inset-0 bg-black/60" onClick={onClose} />
|
|
431
|
-
<div className="relative bg-[
|
|
431
|
+
<div className="relative bg-[var(--color-surface)] border border-[var(--color-border-light)] rounded-xl shadow-2xl w-full max-w-md mx-4 p-5">
|
|
432
432
|
<div className="flex items-center justify-between mb-4">
|
|
433
433
|
<div className="flex items-center gap-3">
|
|
434
434
|
<span className="w-2.5 h-2.5 rounded-full bg-green-400 animate-pulse" />
|
|
435
435
|
<h3 className="font-medium">{agent.name}</h3>
|
|
436
436
|
</div>
|
|
437
|
-
<button onClick={onClose} className="text-[
|
|
437
|
+
<button onClick={onClose} className="text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition">
|
|
438
438
|
<CloseIcon />
|
|
439
439
|
</button>
|
|
440
440
|
</div>
|
|
@@ -442,7 +442,7 @@ function QuickMessageModal({ agent, onClose }: { agent: Agent; onClose: () => vo
|
|
|
442
442
|
{sent ? (
|
|
443
443
|
<div className="py-6 text-center">
|
|
444
444
|
<p className="text-green-400 font-medium">Message sent</p>
|
|
445
|
-
<p className="text-sm text-[
|
|
445
|
+
<p className="text-sm text-[var(--color-text-faint)] mt-1">The agent will process your message</p>
|
|
446
446
|
</div>
|
|
447
447
|
) : (
|
|
448
448
|
<div className="flex gap-2">
|
|
@@ -454,12 +454,12 @@ function QuickMessageModal({ agent, onClose }: { agent: Agent; onClose: () => vo
|
|
|
454
454
|
onKeyDown={e => e.key === "Enter" && handleSend()}
|
|
455
455
|
placeholder={`Message ${agent.name}...`}
|
|
456
456
|
disabled={sending}
|
|
457
|
-
className="flex-1 bg-[
|
|
457
|
+
className="flex-1 bg-[var(--color-bg)] border border-[var(--color-border-light)] rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:border-[var(--color-accent)] placeholder-[#444] disabled:opacity-50"
|
|
458
458
|
/>
|
|
459
459
|
<button
|
|
460
460
|
onClick={handleSend}
|
|
461
461
|
disabled={sending || !message.trim()}
|
|
462
|
-
className="px-4 py-2.5 bg-[
|
|
462
|
+
className="px-4 py-2.5 bg-[var(--color-accent)] text-black rounded-lg text-sm font-medium hover:bg-[var(--color-accent-hover)] transition disabled:opacity-30"
|
|
463
463
|
>
|
|
464
464
|
{sending ? "..." : "Send"}
|
|
465
465
|
</button>
|
|
@@ -134,24 +134,25 @@ export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
|
134
134
|
};
|
|
135
135
|
|
|
136
136
|
const getProjectColor = () => {
|
|
137
|
-
if (currentProjectId === null) return "
|
|
138
|
-
if (currentProjectId === "unassigned") return "
|
|
137
|
+
if (currentProjectId === null) return "var(--color-text-muted)";
|
|
138
|
+
if (currentProjectId === "unassigned") return "var(--color-text-secondary)";
|
|
139
139
|
return currentProject?.color || "#6366f1";
|
|
140
140
|
};
|
|
141
141
|
|
|
142
142
|
return (
|
|
143
|
-
<header className="
|
|
143
|
+
<header className="px-4 md:px-6 py-4 flex-shrink-0" style={{ borderBottom: "1px solid var(--color-border)" }}>
|
|
144
144
|
<div className="flex items-center justify-between">
|
|
145
145
|
<div className="flex items-center gap-3">
|
|
146
146
|
{/* Hamburger menu button - mobile only */}
|
|
147
147
|
<button
|
|
148
148
|
onClick={onMenuClick}
|
|
149
|
-
className="p-2 -ml-2
|
|
149
|
+
className="p-2 -ml-2 transition md:hidden"
|
|
150
|
+
style={{ color: "var(--color-text-muted)" }}
|
|
150
151
|
>
|
|
151
152
|
<MenuIcon />
|
|
152
153
|
</button>
|
|
153
154
|
<div className="flex items-center gap-2">
|
|
154
|
-
<span
|
|
155
|
+
<span style={{ color: "var(--color-accent)" }}>>_</span>
|
|
155
156
|
<span className="text-xl tracking-wider">apteva</span>
|
|
156
157
|
</div>
|
|
157
158
|
|
|
@@ -160,7 +161,8 @@ export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
|
160
161
|
<div className="relative ml-2 md:ml-4">
|
|
161
162
|
<button
|
|
162
163
|
onClick={() => setShowProjectMenu(!showProjectMenu)}
|
|
163
|
-
className="flex items-center gap-2 px-3 py-1.5 rounded
|
|
164
|
+
className="flex items-center gap-2 px-3 py-1.5 rounded transition text-sm"
|
|
165
|
+
style={{ border: "1px solid var(--color-border-light)", backgroundColor: "var(--color-surface)" }}
|
|
164
166
|
>
|
|
165
167
|
<span
|
|
166
168
|
className="w-2.5 h-2.5 rounded-full"
|
|
@@ -172,43 +174,49 @@ export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
|
172
174
|
<ChevronDownIcon />
|
|
173
175
|
</button>
|
|
174
176
|
{showProjectMenu && (
|
|
175
|
-
<div className="absolute left-0 top-full mt-1 w-56
|
|
177
|
+
<div className="absolute left-0 top-full mt-1 w-56 rounded-lg shadow-xl z-50" style={{ backgroundColor: "var(--color-surface)", border: "1px solid var(--color-border-light)" }}>
|
|
176
178
|
<div className="py-1 max-h-64 overflow-y-auto">
|
|
177
179
|
<button
|
|
178
180
|
onClick={() => handleProjectSelect(null)}
|
|
179
|
-
className=
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
className="w-full px-4 py-2 text-left text-sm flex items-center gap-2 transition"
|
|
182
|
+
style={{
|
|
183
|
+
backgroundColor: currentProjectId === null ? "var(--color-surface-raised)" : "transparent",
|
|
184
|
+
color: currentProjectId === null ? "var(--color-accent)" : "var(--color-text)",
|
|
185
|
+
}}
|
|
182
186
|
>
|
|
183
|
-
<span className="w-2.5 h-2.5 rounded-full
|
|
187
|
+
<span className="w-2.5 h-2.5 rounded-full" style={{ backgroundColor: "var(--color-text-muted)" }} />
|
|
184
188
|
All Projects
|
|
185
189
|
</button>
|
|
186
190
|
{projects.map(project => (
|
|
187
191
|
<button
|
|
188
192
|
key={project.id}
|
|
189
193
|
onClick={() => handleProjectSelect(project.id)}
|
|
190
|
-
className=
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
className="w-full px-4 py-2 text-left text-sm flex items-center gap-2 transition"
|
|
195
|
+
style={{
|
|
196
|
+
backgroundColor: currentProjectId === project.id ? "var(--color-surface-raised)" : "transparent",
|
|
197
|
+
color: currentProjectId === project.id ? "var(--color-accent)" : "var(--color-text)",
|
|
198
|
+
}}
|
|
193
199
|
>
|
|
194
200
|
<span
|
|
195
201
|
className="w-2.5 h-2.5 rounded-full flex-shrink-0"
|
|
196
202
|
style={{ backgroundColor: project.color }}
|
|
197
203
|
/>
|
|
198
204
|
<span className="truncate">{project.name}</span>
|
|
199
|
-
<span className="ml-auto text-xs text-
|
|
205
|
+
<span className="ml-auto text-xs" style={{ color: "var(--color-text-muted)" }}>{project.agentCount}</span>
|
|
200
206
|
</button>
|
|
201
207
|
))}
|
|
202
208
|
{unassignedCount > 0 && (
|
|
203
209
|
<button
|
|
204
210
|
onClick={() => handleProjectSelect("unassigned")}
|
|
205
|
-
className=
|
|
206
|
-
|
|
207
|
-
|
|
211
|
+
className="w-full px-4 py-2 text-left text-sm flex items-center gap-2 transition"
|
|
212
|
+
style={{
|
|
213
|
+
backgroundColor: currentProjectId === "unassigned" ? "var(--color-surface-raised)" : "transparent",
|
|
214
|
+
color: currentProjectId === "unassigned" ? "var(--color-accent)" : "var(--color-text)",
|
|
215
|
+
}}
|
|
208
216
|
>
|
|
209
|
-
<span className="w-2.5 h-2.5 rounded-full
|
|
217
|
+
<span className="w-2.5 h-2.5 rounded-full" style={{ backgroundColor: "var(--color-text-secondary)" }} />
|
|
210
218
|
<span className="truncate">Unassigned</span>
|
|
211
|
-
<span className="ml-auto text-xs text-
|
|
219
|
+
<span className="ml-auto text-xs" style={{ color: "var(--color-text-muted)" }}>{unassignedCount}</span>
|
|
212
220
|
</button>
|
|
213
221
|
)}
|
|
214
222
|
</div>
|
|
@@ -222,7 +230,7 @@ export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
|
222
230
|
<span
|
|
223
231
|
className={`w-2 h-2 rounded-full ${connected ? "bg-green-400" : "bg-red-400"}`}
|
|
224
232
|
/>
|
|
225
|
-
<span className="text-xs
|
|
233
|
+
<span className="text-xs hidden sm:inline" style={{ color: "var(--color-text-muted)" }}>
|
|
226
234
|
{connected ? "Live" : "Offline"}
|
|
227
235
|
</span>
|
|
228
236
|
</div>
|
|
@@ -230,7 +238,8 @@ export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
|
230
238
|
<div className="relative">
|
|
231
239
|
<button
|
|
232
240
|
onClick={openNotifications}
|
|
233
|
-
className="relative p-2
|
|
241
|
+
className="relative p-2 transition rounded"
|
|
242
|
+
style={{ color: "var(--color-text-muted)" }}
|
|
234
243
|
>
|
|
235
244
|
<BellIcon className="w-5 h-5" />
|
|
236
245
|
{unseenCount > 0 && (
|
|
@@ -253,40 +262,47 @@ export function Header({ onMenuClick, agents = [] }: HeaderProps) {
|
|
|
253
262
|
{showNotifications && (
|
|
254
263
|
<>
|
|
255
264
|
<div className="fixed inset-0 z-40" onClick={() => setShowNotifications(false)} />
|
|
256
|
-
<div className="absolute right-0 top-full mt-1 w-80
|
|
257
|
-
<div className="px-4 py-3
|
|
265
|
+
<div className="absolute right-0 top-full mt-1 w-80 rounded-lg shadow-xl z-50 max-h-96 overflow-y-auto" style={{ backgroundColor: "var(--color-surface)", border: "1px solid var(--color-border-light)" }}>
|
|
266
|
+
<div className="px-4 py-3 flex items-center justify-between" style={{ borderBottom: "1px solid var(--color-border-light)" }}>
|
|
258
267
|
<span className="text-sm font-medium">Notifications</span>
|
|
259
268
|
{notifications.length > 0 && (
|
|
260
|
-
<span className="text-xs text-
|
|
269
|
+
<span className="text-xs" style={{ color: "var(--color-text-muted)" }}>{notifications.length} recent</span>
|
|
261
270
|
)}
|
|
262
271
|
</div>
|
|
263
272
|
{notifications.length === 0 ? (
|
|
264
|
-
<div className="px-4 py-8 text-center text-sm text-
|
|
273
|
+
<div className="px-4 py-8 text-center text-sm" style={{ color: "var(--color-text-muted)" }}>
|
|
265
274
|
No notifications
|
|
266
275
|
</div>
|
|
267
276
|
) : (
|
|
268
277
|
<div className="py-1">
|
|
269
278
|
{notifications.map(n => (
|
|
270
|
-
<div key={n.id} className=
|
|
279
|
+
<div key={n.id} className="px-4 py-3 transition" style={{
|
|
280
|
+
borderBottom: "1px solid var(--color-border)",
|
|
281
|
+
backgroundColor: !n.seen ? "var(--color-bg-secondary)" : "transparent",
|
|
282
|
+
}}>
|
|
271
283
|
<div className="flex items-center gap-2 mb-1">
|
|
272
284
|
<span className={`w-2 h-2 rounded-full flex-shrink-0 ${
|
|
273
285
|
!n.seen
|
|
274
|
-
? (n.level === "error" || n.category === "ERROR" ? "bg-red-400" : "
|
|
275
|
-
: "
|
|
276
|
-
}`}
|
|
277
|
-
|
|
286
|
+
? (n.level === "error" || n.category === "ERROR" ? "bg-red-400" : "")
|
|
287
|
+
: ""
|
|
288
|
+
}`} style={{
|
|
289
|
+
backgroundColor: !n.seen
|
|
290
|
+
? (n.level === "error" || n.category === "ERROR" ? undefined : "var(--color-accent)")
|
|
291
|
+
: "var(--color-surface-raised)",
|
|
292
|
+
}} />
|
|
293
|
+
<span className="text-xs font-medium truncate" style={{ color: !n.seen ? "var(--color-text)" : "var(--color-text-muted)" }}>
|
|
278
294
|
{n.category === "system" && n.type === "agent_stopped" ? "Agent Stopped" :
|
|
279
295
|
n.category === "ERROR" ? "Error" :
|
|
280
296
|
`${n.category} / ${n.type}`}
|
|
281
297
|
</span>
|
|
282
|
-
<span className="text-[10px]
|
|
298
|
+
<span className="text-[10px] ml-auto flex-shrink-0" style={{ color: "var(--color-text-faint)" }}>
|
|
283
299
|
{formatNotifTime(n.timestamp)}
|
|
284
300
|
</span>
|
|
285
301
|
</div>
|
|
286
|
-
<div className=
|
|
302
|
+
<div className="text-xs truncate" style={{ color: !n.seen ? "var(--color-text-secondary)" : "var(--color-text-muted)" }}>
|
|
287
303
|
{n.error || (n.data as any)?.message || (n.data as any)?.error || `${n.type} event`}
|
|
288
304
|
</div>
|
|
289
|
-
<div className="text-[10px]
|
|
305
|
+
<div className="text-[10px] mt-1" style={{ color: "var(--color-text-faint)" }}>
|
|
290
306
|
{agentNames[n.agent_id] || n.agent_id.slice(0, 8)}
|
|
291
307
|
</div>
|
|
292
308
|
</div>
|
|
@@ -39,20 +39,22 @@ export function Sidebar({ route, agentCount, taskCount, onNavigate, isOpen, onCl
|
|
|
39
39
|
{/* Sidebar - hidden on mobile unless open, always visible on md+ */}
|
|
40
40
|
<aside
|
|
41
41
|
className={`
|
|
42
|
-
fixed inset-y-0 left-0 z-50 w-64
|
|
42
|
+
fixed inset-y-0 left-0 z-50 w-64 p-4 flex flex-col transform transition-transform duration-200 ease-in-out
|
|
43
43
|
md:relative md:w-56 md:translate-x-0 md:z-auto
|
|
44
44
|
${isOpen ? "translate-x-0" : "-translate-x-full"}
|
|
45
45
|
`}
|
|
46
|
+
style={{ backgroundColor: "var(--color-bg)", borderRight: "1px solid var(--color-border)" }}
|
|
46
47
|
>
|
|
47
48
|
{/* Mobile header with close button */}
|
|
48
49
|
<div className="flex items-center justify-between mb-4 md:hidden">
|
|
49
50
|
<div className="flex items-center gap-2">
|
|
50
|
-
<span
|
|
51
|
+
<span style={{ color: "var(--color-accent)" }}>>_</span>
|
|
51
52
|
<span className="text-lg tracking-wider">apteva</span>
|
|
52
53
|
</div>
|
|
53
54
|
<button
|
|
54
55
|
onClick={onClose}
|
|
55
|
-
className="p-2
|
|
56
|
+
className="p-2 transition"
|
|
57
|
+
style={{ color: "var(--color-text-muted)" }}
|
|
56
58
|
>
|
|
57
59
|
<CloseIcon />
|
|
58
60
|
</button>
|
|
@@ -137,26 +139,31 @@ export function Sidebar({ route, agentCount, taskCount, onNavigate, isOpen, onCl
|
|
|
137
139
|
|
|
138
140
|
{/* User profile - pinned to bottom */}
|
|
139
141
|
{user && (
|
|
140
|
-
<div className="relative
|
|
142
|
+
<div className="relative pt-3 mt-3" style={{ borderTop: "1px solid var(--color-border)" }}>
|
|
141
143
|
<button
|
|
142
144
|
onClick={() => setShowUserMenu(!showUserMenu)}
|
|
143
|
-
className="w-full flex items-center gap-3 px-3 py-2 rounded
|
|
145
|
+
className="w-full flex items-center gap-3 px-3 py-2 rounded transition"
|
|
146
|
+
style={{ color: "var(--color-text)" }}
|
|
147
|
+
onMouseEnter={e => e.currentTarget.style.backgroundColor = "var(--color-surface)"}
|
|
148
|
+
onMouseLeave={e => e.currentTarget.style.backgroundColor = "transparent"}
|
|
144
149
|
>
|
|
145
|
-
<div className="w-8 h-8 rounded-full
|
|
150
|
+
<div className="w-8 h-8 rounded-full flex items-center justify-center text-black font-medium text-sm flex-shrink-0" style={{ backgroundColor: "var(--color-accent)" }}>
|
|
146
151
|
{user.username.charAt(0).toUpperCase()}
|
|
147
152
|
</div>
|
|
148
153
|
<div className="flex-1 min-w-0 text-left">
|
|
149
154
|
<p className="text-sm font-medium truncate">{user.username}</p>
|
|
150
|
-
<p className="text-xs text-
|
|
155
|
+
<p className="text-xs" style={{ color: "var(--color-text-faint)" }}>{user.role}</p>
|
|
151
156
|
</div>
|
|
152
157
|
</button>
|
|
153
158
|
{showUserMenu && (
|
|
154
159
|
<>
|
|
155
160
|
<div className="fixed inset-0 z-40" onClick={() => setShowUserMenu(false)} />
|
|
156
|
-
<div className="absolute left-3 bottom-full mb-1 w-48
|
|
161
|
+
<div className="absolute left-3 bottom-full mb-1 w-48 rounded-lg shadow-xl z-50" style={{ backgroundColor: "var(--color-surface)", border: "1px solid var(--color-border-light)" }}>
|
|
157
162
|
<button
|
|
158
163
|
onClick={handleLogout}
|
|
159
|
-
className="w-full px-4 py-2.5 text-left text-sm text-red-400
|
|
164
|
+
className="w-full px-4 py-2.5 text-left text-sm text-red-400 transition rounded-lg"
|
|
165
|
+
onMouseEnter={e => e.currentTarget.style.backgroundColor = "var(--color-surface-raised)"}
|
|
166
|
+
onMouseLeave={e => e.currentTarget.style.backgroundColor = "transparent"}
|
|
160
167
|
>
|
|
161
168
|
Sign out
|
|
162
169
|
</button>
|
|
@@ -182,16 +189,28 @@ function NavButton({ icon, label, active, onClick, badge }: NavButtonProps) {
|
|
|
182
189
|
return (
|
|
183
190
|
<button
|
|
184
191
|
onClick={onClick}
|
|
185
|
-
className=
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
192
|
+
className="w-full flex items-center gap-3 px-3 py-2 rounded font-medium transition"
|
|
193
|
+
style={{
|
|
194
|
+
backgroundColor: active ? "var(--color-surface)" : "transparent",
|
|
195
|
+
color: active ? "var(--color-text)" : "var(--color-text-muted)",
|
|
196
|
+
}}
|
|
197
|
+
onMouseEnter={e => {
|
|
198
|
+
if (!active) {
|
|
199
|
+
e.currentTarget.style.backgroundColor = "var(--color-surface)";
|
|
200
|
+
e.currentTarget.style.color = "var(--color-text-secondary)";
|
|
201
|
+
}
|
|
202
|
+
}}
|
|
203
|
+
onMouseLeave={e => {
|
|
204
|
+
if (!active) {
|
|
205
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
206
|
+
e.currentTarget.style.color = "var(--color-text-muted)";
|
|
207
|
+
}
|
|
208
|
+
}}
|
|
190
209
|
>
|
|
191
210
|
{icon}
|
|
192
211
|
{label}
|
|
193
212
|
{badge && (
|
|
194
|
-
<span className="ml-auto
|
|
213
|
+
<span className="ml-auto text-xs px-2 py-0.5 rounded-full" style={{ backgroundColor: "var(--color-surface-raised)", color: "var(--color-text-secondary)" }}>
|
|
195
214
|
{badge}
|
|
196
215
|
</span>
|
|
197
216
|
)}
|