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.
Files changed (102) hide show
  1. package/dist/ActivityPage.c48n83h2.js +3 -0
  2. package/dist/ApiDocsPage.yzcxx5ax.js +4 -0
  3. package/dist/App.09yb8t0b.js +1 -0
  4. package/dist/App.152mbs1r.js +4 -0
  5. package/dist/App.3a67nx9w.js +4 -0
  6. package/dist/App.9epx6785.js +4 -0
  7. package/dist/App.d8955awp.js +4 -0
  8. package/dist/App.drwb57jq.js +4 -0
  9. package/dist/App.gssbmajb.js +4 -0
  10. package/dist/App.qw70pc29.js +53 -0
  11. package/dist/{App.7fb3e7mp.js → App.qzbx5wtj.js} +1 -1
  12. package/dist/App.r5serxkt.js +8 -0
  13. package/dist/App.tpmp9020.js +20 -0
  14. package/dist/App.v2wb4d7d.js +61 -0
  15. package/dist/App.vxmaaj0m.js +13 -0
  16. package/dist/App.w4p2tda9.js +4 -0
  17. package/dist/App.wv2ng55q.js +221 -0
  18. package/dist/App.yncnrn0f.js +4 -0
  19. package/dist/ConnectionsPage.k6cspyqq.js +3 -0
  20. package/dist/McpPage.cdxm48xj.js +3 -0
  21. package/dist/SettingsPage.evpv7c2y.js +3 -0
  22. package/dist/SkillsPage.pvzp6c1a.js +3 -0
  23. package/dist/TasksPage.6jnvbpsy.js +3 -0
  24. package/dist/TelemetryPage.t7vk24zc.js +3 -0
  25. package/dist/TestsPage.5x6658aa.js +3 -0
  26. package/dist/ThreadsPage.3fvhtevh.js +3 -0
  27. package/dist/apteva-kit.css +1 -1
  28. package/dist/index.html +1 -1
  29. package/dist/styles.css +1 -1
  30. package/package.json +8 -8
  31. package/src/db.ts +19 -9
  32. package/src/integrations/agentdojo.ts +1 -0
  33. package/src/mcp-platform.ts +418 -63
  34. package/src/openapi.ts +96 -0
  35. package/src/providers.ts +50 -24
  36. package/src/routes/api/agent-utils.ts +0 -1
  37. package/src/routes/api/agents.ts +19 -1
  38. package/src/routes/api/meta-agent.ts +2 -0
  39. package/src/routes/api/system.ts +90 -1
  40. package/src/routes/api/telemetry.ts +19 -1
  41. package/src/routes/share.ts +85 -0
  42. package/src/server.ts +12 -0
  43. package/src/web/App.tsx +89 -11
  44. package/src/web/components/activity/ActivityPage.tsx +14 -14
  45. package/src/web/components/agents/AgentCard.tsx +14 -14
  46. package/src/web/components/agents/AgentPanel.tsx +358 -198
  47. package/src/web/components/agents/AgentsView.tsx +4 -4
  48. package/src/web/components/agents/CreateAgentModal.tsx +21 -79
  49. package/src/web/components/api/ApiDocsPage.tsx +66 -66
  50. package/src/web/components/auth/CreateAccountStep.tsx +16 -16
  51. package/src/web/components/auth/LoginPage.tsx +10 -10
  52. package/src/web/components/common/LoadingSpinner.tsx +2 -2
  53. package/src/web/components/common/Modal.tsx +8 -8
  54. package/src/web/components/common/Select.tsx +9 -9
  55. package/src/web/components/connections/ConnectionsPage.tsx +4 -4
  56. package/src/web/components/connections/IntegrationsTab.tsx +18 -18
  57. package/src/web/components/connections/OverviewTab.tsx +13 -13
  58. package/src/web/components/connections/TriggersTab.tsx +99 -99
  59. package/src/web/components/dashboard/Dashboard.tsx +32 -32
  60. package/src/web/components/layout/Header.tsx +50 -34
  61. package/src/web/components/layout/Sidebar.tsx +34 -15
  62. package/src/web/components/mcp/IntegrationsPanel.tsx +40 -40
  63. package/src/web/components/mcp/McpPage.tsx +208 -208
  64. package/src/web/components/meta-agent/MetaAgent.tsx +12 -10
  65. package/src/web/components/onboarding/OnboardingWizard.tsx +25 -25
  66. package/src/web/components/settings/SettingsPage.tsx +258 -175
  67. package/src/web/components/skills/SkillsPage.tsx +88 -88
  68. package/src/web/components/tasks/TasksPage.tsx +339 -54
  69. package/src/web/components/telemetry/TelemetryPage.tsx +135 -64
  70. package/src/web/components/tests/TestsPage.tsx +50 -50
  71. package/src/web/components/threads/ThreadsPage.tsx +23 -21
  72. package/src/web/context/ProjectContext.tsx +6 -1
  73. package/src/web/context/ThemeContext.tsx +69 -0
  74. package/src/web/context/index.ts +2 -0
  75. package/src/web/styles.css +5 -3
  76. package/src/web/themes.ts +99 -0
  77. package/src/web/types.ts +0 -4
  78. package/dist/ActivityPage.7907h64p.js +0 -3
  79. package/dist/ApiDocsPage.k3jjenpq.js +0 -4
  80. package/dist/App.01nq20st.js +0 -4
  81. package/dist/App.1maqvamf.js +0 -4
  82. package/dist/App.2yjrh32f.js +0 -4
  83. package/dist/App.3qw8nben.js +0 -20
  84. package/dist/App.7sy3wq8c.js +0 -4
  85. package/dist/App.apjrmctz.js +0 -57
  86. package/dist/App.av6t2yhe.js +0 -4
  87. package/dist/App.jqj5a094.js +0 -46
  88. package/dist/App.mc7xf85h.js +0 -4
  89. package/dist/App.myxqcj9x.js +0 -4
  90. package/dist/App.nm91r1mp.js +0 -13
  91. package/dist/App.p02f4ret.js +0 -1
  92. package/dist/App.qcknavjz.js +0 -221
  93. package/dist/App.vc7vfhg4.js +0 -4
  94. package/dist/App.z4s9zkw5.js +0 -4
  95. package/dist/ConnectionsPage.z1pw5xe2.js +0 -3
  96. package/dist/McpPage.8vc97z0b.js +0 -3
  97. package/dist/SettingsPage.p61bz8kd.js +0 -3
  98. package/dist/SkillsPage.r9x43g3g.js +0 -3
  99. package/dist/TasksPage.1e0zkye4.js +0 -3
  100. package/dist/TelemetryPage.p9vbe4gf.js +0 -3
  101. package/dist/TestsPage.d4xy504e.js +0 -3
  102. package/dist/ThreadsPage.m016am3x.js +0 -3
@@ -13,6 +13,7 @@ interface TelemetryStats {
13
13
  total_errors: number;
14
14
  total_input_tokens: number;
15
15
  total_output_tokens: number;
16
+ total_cost: number;
16
17
  }
17
18
 
18
19
  interface UsageByAgent {
@@ -22,6 +23,7 @@ interface UsageByAgent {
22
23
  llm_calls: number;
23
24
  tool_calls: number;
24
25
  errors: number;
26
+ cost: number;
25
27
  }
26
28
 
27
29
  interface DailyUsage {
@@ -58,7 +60,7 @@ function extractEventStats(event: TelemetryEvent): {
58
60
 
59
61
  export function TelemetryPage() {
60
62
  const { events: realtimeEvents, statusChangeCounter } = useTelemetryContext();
61
- const { currentProjectId, currentProject } = useProjects();
63
+ const { currentProjectId, currentProject, costTrackingEnabled } = useProjects();
62
64
  const { authFetch } = useAuth();
63
65
  const [fetchedStats, setFetchedStats] = useState<TelemetryStats | null>(null);
64
66
  const [historicalEvents, setHistoricalEvents] = useState<TelemetryEvent[]>([]);
@@ -74,6 +76,20 @@ export function TelemetryPage() {
74
76
  const [agents, setAgents] = useState<Array<{ id: string; name: string; projectId: string | null }>>([]);
75
77
  const [expandedEvent, setExpandedEvent] = useState<string | null>(null);
76
78
 
79
+ // Sort state for usage table
80
+ type SortKey = "agent" | "llm_calls" | "tool_calls" | "input_tokens" | "output_tokens" | "errors" | "cost";
81
+ const [sortKey, setSortKey] = useState<SortKey>("cost");
82
+ const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");
83
+
84
+ const handleSort = (key: SortKey) => {
85
+ if (sortKey === key) {
86
+ setSortDir(d => d === "asc" ? "desc" : "asc");
87
+ } else {
88
+ setSortKey(key);
89
+ setSortDir("desc");
90
+ }
91
+ };
92
+
77
93
  // Track IDs that were in the fetched stats to avoid double-counting
78
94
  const countedEventIdsRef = useRef<Set<string>>(new Set());
79
95
 
@@ -194,6 +210,7 @@ export function TelemetryPage() {
194
210
  total_errors: fetchedStats.total_errors + deltaErrors,
195
211
  total_input_tokens: fetchedStats.total_input_tokens + deltaInputTokens,
196
212
  total_output_tokens: fetchedStats.total_output_tokens + deltaOutputTokens,
213
+ total_cost: fetchedStats.total_cost || 0,
197
214
  };
198
215
  }, [fetchedStats, realtimeEvents]);
199
216
 
@@ -224,6 +241,7 @@ export function TelemetryPage() {
224
241
  errors: eventStats.errors,
225
242
  input_tokens: eventStats.input_tokens,
226
243
  output_tokens: eventStats.output_tokens,
244
+ cost: 0,
227
245
  });
228
246
  }
229
247
  }
@@ -232,6 +250,22 @@ export function TelemetryPage() {
232
250
  return Array.from(usageMap.values());
233
251
  }, [fetchedUsage, realtimeEvents]);
234
252
 
253
+ // Sorted usage for the table
254
+ const sortedUsage = useMemo(() => {
255
+ const sorted = [...usage];
256
+ sorted.sort((a, b) => {
257
+ if (sortKey === "agent") {
258
+ const aName = (agents.find(ag => ag.id === a.agent_id)?.name || a.agent_id).toLowerCase();
259
+ const bName = (agents.find(ag => ag.id === b.agent_id)?.name || b.agent_id).toLowerCase();
260
+ return sortDir === "asc" ? (aName < bName ? -1 : 1) : (aName > bName ? -1 : 1);
261
+ }
262
+ const aVal = a[sortKey] as number;
263
+ const bVal = b[sortKey] as number;
264
+ return sortDir === "asc" ? aVal - bVal : bVal - aVal;
265
+ });
266
+ return sorted;
267
+ }, [usage, sortKey, sortDir, agents]);
268
+
235
269
  // Merge real-time events with historical, filtering and deduping
236
270
  const allEvents = React.useMemo(() => {
237
271
  // Apply filters to real-time events
@@ -315,7 +349,7 @@ export function TelemetryPage() {
315
349
  };
316
350
 
317
351
  const levelColors: Record<string, string> = {
318
- debug: "text-[#555]",
352
+ debug: "text-[var(--color-text-faint)]",
319
353
  info: "text-blue-400",
320
354
  warn: "text-yellow-400",
321
355
  error: "text-red-400",
@@ -380,20 +414,23 @@ export function TelemetryPage() {
380
414
  : `Telemetry - ${currentProject?.name || ""}`}
381
415
  </h1>
382
416
  </div>
383
- <p className="text-[#666]">
417
+ <p className="text-[var(--color-text-muted)]">
384
418
  Monitor agent activity, token usage, and errors.
385
419
  </p>
386
420
  </div>
387
421
 
388
422
  {/* Stats Cards */}
389
423
  {stats && (
390
- <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4 mb-6">
424
+ <div className={`grid grid-cols-2 md:grid-cols-3 ${costTrackingEnabled ? "lg:grid-cols-7" : "lg:grid-cols-6"} gap-4 mb-6`}>
391
425
  <StatCard label="Events" value={formatNumber(stats.total_events)} />
392
426
  <StatCard label="LLM Calls" value={formatNumber(stats.total_llm_calls)} />
393
427
  <StatCard label="Tool Calls" value={formatNumber(stats.total_tool_calls)} />
394
428
  <StatCard label="Errors" value={formatNumber(stats.total_errors)} color="red" />
395
429
  <StatCard label="Input Tokens" value={formatNumber(stats.total_input_tokens)} />
396
430
  <StatCard label="Output Tokens" value={formatNumber(stats.total_output_tokens)} />
431
+ {costTrackingEnabled && (
432
+ <StatCard label="Total Cost" value={`$${stats.total_cost.toFixed(4)}`} color="orange" />
433
+ )}
397
434
  </div>
398
435
  )}
399
436
 
@@ -427,15 +464,15 @@ export function TelemetryPage() {
427
464
  return (
428
465
  <div className="grid grid-cols-1 lg:grid-cols-2 gap-4 mb-6">
429
466
  {/* Activity Chart */}
430
- <div className="bg-[#111] border border-[#1a1a1a] rounded-lg p-4">
431
- <h3 className="text-sm font-medium text-[#888] mb-4">{chartLabel} Activity</h3>
467
+ <div className="bg-[var(--color-surface)] border border-[var(--color-border)] rounded-lg p-4">
468
+ <h3 className="text-sm font-medium text-[var(--color-text-secondary)] mb-4">{chartLabel} Activity</h3>
432
469
  <ResponsiveContainer width="100%" height={200}>
433
470
  <AreaChart data={chartData}>
434
- <CartesianGrid strokeDasharray="3 3" stroke="#1a1a1a" />
471
+ <CartesianGrid strokeDasharray="3 3" stroke="var(--color-border)" />
435
472
  <XAxis
436
473
  dataKey="date"
437
- stroke="#444"
438
- tick={{ fill: "#666", fontSize: 11 }}
474
+ stroke="var(--color-border-light)"
475
+ tick={{ fill: "var(--color-text-muted)", fontSize: 11 }}
439
476
  tickFormatter={(v) => {
440
477
  if (!useDaily && v.includes(" ")) {
441
478
  return v.split(" ")[1];
@@ -444,15 +481,15 @@ export function TelemetryPage() {
444
481
  return `${d.getMonth() + 1}/${d.getDate()}`;
445
482
  }}
446
483
  />
447
- <YAxis stroke="#444" tick={{ fill: "#666", fontSize: 11 }} allowDecimals={false} />
484
+ <YAxis stroke="var(--color-border-light)" tick={{ fill: "var(--color-text-muted)", fontSize: 11 }} allowDecimals={false} />
448
485
  <Tooltip
449
486
  contentStyle={{
450
- backgroundColor: "#111",
451
- border: "1px solid #333",
487
+ backgroundColor: "var(--color-surface)",
488
+ border: "1px solid var(--color-border-light)",
452
489
  borderRadius: "8px",
453
490
  fontSize: 12,
454
491
  }}
455
- labelStyle={{ color: "#888" }}
492
+ labelStyle={{ color: "var(--color-text-secondary)" }}
456
493
  cursor={{ stroke: "rgba(255,255,255,0.1)" }}
457
494
  labelFormatter={(v) => useDaily ? new Date(v + "T00:00:00").toLocaleDateString() : v}
458
495
  />
@@ -465,8 +502,8 @@ export function TelemetryPage() {
465
502
  type="monotone"
466
503
  dataKey="llm_calls"
467
504
  name="LLM Calls"
468
- stroke="#f97316"
469
- fill="#f97316"
505
+ stroke="var(--color-accent)"
506
+ fill="var(--color-accent)"
470
507
  fillOpacity={0.15}
471
508
  strokeWidth={1.5}
472
509
  />
@@ -474,8 +511,8 @@ export function TelemetryPage() {
474
511
  type="monotone"
475
512
  dataKey="tool_calls"
476
513
  name="Tool Calls"
477
- stroke="#fb923c"
478
- fill="#fb923c"
514
+ stroke="var(--color-accent-hover)"
515
+ fill="var(--color-accent-hover)"
479
516
  fillOpacity={0.08}
480
517
  strokeWidth={1.5}
481
518
  />
@@ -493,15 +530,15 @@ export function TelemetryPage() {
493
530
  </div>
494
531
 
495
532
  {/* Token Usage Chart */}
496
- <div className="bg-[#111] border border-[#1a1a1a] rounded-lg p-4">
497
- <h3 className="text-sm font-medium text-[#888] mb-4">{chartLabel} Token Usage</h3>
533
+ <div className="bg-[var(--color-surface)] border border-[var(--color-border)] rounded-lg p-4">
534
+ <h3 className="text-sm font-medium text-[var(--color-text-secondary)] mb-4">{chartLabel} Token Usage</h3>
498
535
  <ResponsiveContainer width="100%" height={200}>
499
536
  <BarChart data={chartData}>
500
- <CartesianGrid strokeDasharray="3 3" stroke="#1a1a1a" />
537
+ <CartesianGrid strokeDasharray="3 3" stroke="var(--color-border)" />
501
538
  <XAxis
502
539
  dataKey="date"
503
- stroke="#444"
504
- tick={{ fill: "#666", fontSize: 11 }}
540
+ stroke="var(--color-border-light)"
541
+ tick={{ fill: "var(--color-text-muted)", fontSize: 11 }}
505
542
  tickFormatter={(v) => {
506
543
  if (!useDaily && v.includes(" ")) {
507
544
  return v.split(" ")[1];
@@ -511,8 +548,8 @@ export function TelemetryPage() {
511
548
  }}
512
549
  />
513
550
  <YAxis
514
- stroke="#444"
515
- tick={{ fill: "#666", fontSize: 11 }}
551
+ stroke="var(--color-border-light)"
552
+ tick={{ fill: "var(--color-text-muted)", fontSize: 11 }}
516
553
  tickFormatter={(v) => {
517
554
  if (v >= 1000000) return `${(v / 1000000).toFixed(1)}M`;
518
555
  if (v >= 1000) return `${(v / 1000).toFixed(0)}K`;
@@ -521,12 +558,12 @@ export function TelemetryPage() {
521
558
  />
522
559
  <Tooltip
523
560
  contentStyle={{
524
- backgroundColor: "#111",
525
- border: "1px solid #333",
561
+ backgroundColor: "var(--color-surface)",
562
+ border: "1px solid var(--color-border-light)",
526
563
  borderRadius: "8px",
527
564
  fontSize: 12,
528
565
  }}
529
- labelStyle={{ color: "#888" }}
566
+ labelStyle={{ color: "var(--color-text-secondary)" }}
530
567
  cursor={{ fill: "rgba(255,255,255,0.03)" }}
531
568
  labelFormatter={(v) => useDaily ? new Date(v + "T00:00:00").toLocaleDateString() : v}
532
569
  formatter={(value: number) => [value.toLocaleString(), undefined]}
@@ -539,13 +576,13 @@ export function TelemetryPage() {
539
576
  <Bar
540
577
  dataKey="input_tokens"
541
578
  name="Input Tokens"
542
- fill="#f97316"
579
+ fill="var(--color-accent)"
543
580
  radius={[2, 2, 0, 0]}
544
581
  />
545
582
  <Bar
546
583
  dataKey="output_tokens"
547
584
  name="Output Tokens"
548
- fill="#ea580c"
585
+ fill="var(--color-accent-hover)"
549
586
  radius={[2, 2, 0, 0]}
550
587
  />
551
588
  </BarChart>
@@ -556,43 +593,77 @@ export function TelemetryPage() {
556
593
  })()}
557
594
 
558
595
  {/* Usage by Agent */}
559
- {usage.length > 0 && (
596
+ {usage.length > 0 && (() => {
597
+ const maxCost = Math.max(...sortedUsage.map(u => u.cost), 0.0001);
598
+ const SortHeader = ({ label, field, align = "right" }: { label: string; field: SortKey; align?: string }) => (
599
+ <th
600
+ className={`${align === "left" ? "text-left" : "text-right"} p-3 cursor-pointer hover:text-[var(--color-text-secondary)] select-none transition-colors`}
601
+ onClick={() => handleSort(field)}
602
+ >
603
+ <span className="inline-flex items-center gap-1">
604
+ {align === "right" && sortKey === field && (
605
+ <span className="text-orange-400">{sortDir === "asc" ? "\u25b2" : "\u25bc"}</span>
606
+ )}
607
+ {label}
608
+ {align === "left" && sortKey === field && (
609
+ <span className="text-orange-400">{sortDir === "asc" ? "\u25b2" : "\u25bc"}</span>
610
+ )}
611
+ </span>
612
+ </th>
613
+ );
614
+
615
+ return (
560
616
  <div className="mb-6">
561
617
  <h2 className="text-lg font-medium mb-3">Usage by Agent</h2>
562
- <div className="bg-[#111] border border-[#1a1a1a] rounded-lg overflow-hidden">
618
+ <div className="bg-[var(--color-surface)] border border-[var(--color-border)] rounded-lg overflow-hidden">
563
619
  <table className="w-full text-sm">
564
620
  <thead>
565
- <tr className="border-b border-[#1a1a1a] text-[#666]">
566
- <th className="text-left p-3">Agent</th>
567
- <th className="text-right p-3">LLM Calls</th>
568
- <th className="text-right p-3">Tool Calls</th>
569
- <th className="text-right p-3">Input Tokens</th>
570
- <th className="text-right p-3">Output Tokens</th>
571
- <th className="text-right p-3">Errors</th>
621
+ <tr className="border-b border-[var(--color-border)] text-[var(--color-text-muted)]">
622
+ <SortHeader label="Agent" field="agent" align="left" />
623
+ <SortHeader label="LLM Calls" field="llm_calls" />
624
+ <SortHeader label="Tool Calls" field="tool_calls" />
625
+ <SortHeader label="Input Tokens" field="input_tokens" />
626
+ <SortHeader label="Output Tokens" field="output_tokens" />
627
+ <SortHeader label="Errors" field="errors" />
628
+ {costTrackingEnabled && <SortHeader label="Est. Cost" field="cost" />}
572
629
  </tr>
573
630
  </thead>
574
631
  <tbody>
575
- {usage.map((u) => (
576
- <tr key={u.agent_id} className="border-b border-[#1a1a1a] last:border-0">
632
+ {sortedUsage.map((u) => (
633
+ <tr key={u.agent_id} className="border-b border-[var(--color-border)] last:border-0 hover:bg-[var(--color-bg)]">
577
634
  <td className="p-3 font-medium">{getAgentName(u.agent_id)}</td>
578
- <td className="p-3 text-right text-[#888]">{formatNumber(u.llm_calls)}</td>
579
- <td className="p-3 text-right text-[#888]">{formatNumber(u.tool_calls)}</td>
580
- <td className="p-3 text-right text-[#888]">{formatNumber(u.input_tokens)}</td>
581
- <td className="p-3 text-right text-[#888]">{formatNumber(u.output_tokens)}</td>
635
+ <td className="p-3 text-right text-[var(--color-text-secondary)]">{formatNumber(u.llm_calls)}</td>
636
+ <td className="p-3 text-right text-[var(--color-text-secondary)]">{formatNumber(u.tool_calls)}</td>
637
+ <td className="p-3 text-right text-[var(--color-text-secondary)]">{formatNumber(u.input_tokens)}</td>
638
+ <td className="p-3 text-right text-[var(--color-text-secondary)]">{formatNumber(u.output_tokens)}</td>
582
639
  <td className="p-3 text-right">
583
640
  {u.errors > 0 ? (
584
641
  <span className="text-red-400">{u.errors}</span>
585
642
  ) : (
586
- <span className="text-[#444]">0</span>
643
+ <span className="text-[var(--color-text-faint)]">0</span>
587
644
  )}
588
645
  </td>
646
+ {costTrackingEnabled && (
647
+ <td className="p-3 text-right">
648
+ <div className="flex items-center justify-end gap-2">
649
+ <div className="w-16 h-1.5 bg-[var(--color-surface-raised)] rounded-full overflow-hidden">
650
+ <div
651
+ className="h-full bg-orange-500 rounded-full"
652
+ style={{ width: `${(u.cost / maxCost) * 100}%` }}
653
+ />
654
+ </div>
655
+ <span className="text-[var(--color-text-secondary)] min-w-[60px] text-right">${u.cost.toFixed(4)}</span>
656
+ </div>
657
+ </td>
658
+ )}
589
659
  </tr>
590
660
  ))}
591
661
  </tbody>
592
662
  </table>
593
663
  </div>
594
664
  </div>
595
- )}
665
+ );
666
+ })()}
596
667
 
597
668
  {/* Filters */}
598
669
  <div className="flex flex-wrap items-center gap-3 mb-4">
@@ -608,14 +679,14 @@ export function TelemetryPage() {
608
679
  <div className="flex flex-wrap items-center gap-1.5 flex-1">
609
680
  {allCategories.map((cat) => {
610
681
  const isHidden = hiddenCategories.has(cat);
611
- const colorClass = categoryColors[cat] || "bg-[#222] text-[#888] border-[#333]";
682
+ const colorClass = categoryColors[cat] || "bg-[var(--color-surface-raised)] text-[var(--color-text-secondary)] border-[var(--color-border-light)]";
612
683
  return (
613
684
  <button
614
685
  key={cat}
615
686
  onClick={() => toggleCategory(cat)}
616
687
  className={`px-2 py-0.5 rounded text-xs border transition-all ${
617
688
  isHidden
618
- ? "bg-[#1a1a1a] text-[#555] border-[#333] opacity-50"
689
+ ? "bg-[var(--color-surface-raised)] text-[var(--color-text-faint)] border-[var(--color-border-light)] opacity-50"
619
690
  : colorClass
620
691
  }`}
621
692
  >
@@ -635,7 +706,7 @@ export function TelemetryPage() {
635
706
  </div>
636
707
  <button
637
708
  onClick={fetchData}
638
- className="px-3 py-2 bg-[#1a1a1a] hover:bg-[#222] border border-[#333] rounded text-sm transition"
709
+ className="px-3 py-2 bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] rounded text-sm transition"
639
710
  >
640
711
  Refresh
641
712
  </button>
@@ -643,31 +714,31 @@ export function TelemetryPage() {
643
714
  </div>
644
715
 
645
716
  {/* Events List */}
646
- <div className="bg-[#111] border border-[#1a1a1a] rounded-lg">
647
- <div className="p-3 border-b border-[#1a1a1a] flex items-center justify-between">
717
+ <div className="bg-[var(--color-surface)] border border-[var(--color-border)] rounded-lg">
718
+ <div className="p-3 border-b border-[var(--color-border)] flex items-center justify-between">
648
719
  <h2 className="font-medium">Recent Events</h2>
649
720
  {realtimeEvents.length > 0 && (
650
- <span className="text-xs text-[#666]">
721
+ <span className="text-xs text-[var(--color-text-muted)]">
651
722
  {realtimeEvents.length} new
652
723
  </span>
653
724
  )}
654
725
  </div>
655
726
 
656
727
  {loading && allEvents.length === 0 ? (
657
- <div className="p-8 text-center text-[#666]">Loading...</div>
728
+ <div className="p-8 text-center text-[var(--color-text-muted)]">Loading...</div>
658
729
  ) : allEvents.length === 0 ? (
659
- <div className="p-8 text-center text-[#666]">
730
+ <div className="p-8 text-center text-[var(--color-text-muted)]">
660
731
  No telemetry events yet. Events will appear here in real-time once agents start sending data.
661
732
  </div>
662
733
  ) : (
663
- <div className="divide-y divide-[#1a1a1a]">
734
+ <div className="divide-y divide-[var(--color-border)]">
664
735
  {allEvents.map((event) => {
665
736
  const isNew = newEventIds.has(event.id);
666
737
 
667
738
  return (
668
739
  <div
669
740
  key={event.id}
670
- className={`p-3 hover:bg-[#0a0a0a] cursor-pointer transition-all duration-500 ${
741
+ className={`p-3 hover:bg-[var(--color-bg)] cursor-pointer transition-all duration-500 ${
671
742
  isNew ? "bg-green-500/5" : ""
672
743
  }`}
673
744
  style={{
@@ -676,17 +747,17 @@ export function TelemetryPage() {
676
747
  onClick={() => setExpandedEvent(expandedEvent === event.id ? null : event.id)}
677
748
  >
678
749
  <div className="flex items-start gap-3">
679
- <span className={`px-2 py-0.5 rounded text-xs border transition-colors duration-300 ${categoryColors[event.category] || "bg-[#222] text-[#888] border-[#333]"}`}>
750
+ <span className={`px-2 py-0.5 rounded text-xs border transition-colors duration-300 ${categoryColors[event.category] || "bg-[var(--color-surface-raised)] text-[var(--color-text-secondary)] border-[var(--color-border-light)]"}`}>
680
751
  {event.category}
681
752
  </span>
682
753
  <div className="flex-1 min-w-0">
683
754
  <div className="flex items-center gap-2">
684
755
  <span className="font-medium text-sm">{event.type}</span>
685
- <span className={`text-xs ${levelColors[event.level] || "text-[#666]"}`}>
756
+ <span className={`text-xs ${levelColors[event.level] || "text-[var(--color-text-muted)]"}`}>
686
757
  {event.level}
687
758
  </span>
688
759
  {event.duration_ms && (
689
- <span className="text-xs text-[#555]">{event.duration_ms}ms</span>
760
+ <span className="text-xs text-[var(--color-text-faint)]">{event.duration_ms}ms</span>
690
761
  )}
691
762
  <span
692
763
  className={`w-1.5 h-1.5 rounded-full bg-green-400 transition-opacity duration-1000 ${
@@ -694,14 +765,14 @@ export function TelemetryPage() {
694
765
  }`}
695
766
  />
696
767
  </div>
697
- <div className="text-xs text-[#555] mt-1">
768
+ <div className="text-xs text-[var(--color-text-faint)] mt-1">
698
769
  {getAgentName(event.agent_id)} · {new Date(event.timestamp).toLocaleString()}
699
770
  </div>
700
771
  {event.error && (
701
772
  <div className="text-xs text-red-400 mt-1 font-mono">{event.error}</div>
702
773
  )}
703
774
  {expandedEvent === event.id && event.data && Object.keys(event.data).length > 0 && (
704
- <pre className="text-xs text-[#666] mt-2 p-2 bg-[#0a0a0a] rounded overflow-x-auto">
775
+ <pre className="text-xs text-[var(--color-text-muted)] mt-2 p-2 bg-[var(--color-bg)] rounded overflow-x-auto">
705
776
  {JSON.stringify(event.data, null, 2)}
706
777
  </pre>
707
778
  )}
@@ -720,9 +791,9 @@ export function TelemetryPage() {
720
791
 
721
792
  function StatCard({ label, value, color }: { label: string; value: string; color?: string }) {
722
793
  return (
723
- <div className="bg-[#111] border border-[#1a1a1a] rounded-lg p-4">
724
- <div className="text-[#666] text-xs mb-1">{label}</div>
725
- <div className={`text-2xl font-semibold ${color === "red" ? "text-red-400" : ""}`}>
794
+ <div className="bg-[var(--color-surface)] border border-[var(--color-border)] rounded-lg p-4">
795
+ <div className="text-[var(--color-text-muted)] text-xs mb-1">{label}</div>
796
+ <div className={`text-2xl font-semibold ${color === "red" ? "text-red-400" : color === "orange" ? "text-orange-400" : ""}`}>
726
797
  {value}
727
798
  </div>
728
799
  </div>