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
|
@@ -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-[
|
|
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-[
|
|
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=
|
|
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-[
|
|
431
|
-
<h3 className="text-sm font-medium text-[
|
|
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="
|
|
471
|
+
<CartesianGrid strokeDasharray="3 3" stroke="var(--color-border)" />
|
|
435
472
|
<XAxis
|
|
436
473
|
dataKey="date"
|
|
437
|
-
stroke="
|
|
438
|
-
tick={{ fill: "
|
|
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="
|
|
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: "
|
|
451
|
-
border: "1px solid
|
|
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: "
|
|
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="
|
|
469
|
-
fill="
|
|
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="
|
|
478
|
-
fill="
|
|
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-[
|
|
497
|
-
<h3 className="text-sm font-medium text-[
|
|
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="
|
|
537
|
+
<CartesianGrid strokeDasharray="3 3" stroke="var(--color-border)" />
|
|
501
538
|
<XAxis
|
|
502
539
|
dataKey="date"
|
|
503
|
-
stroke="
|
|
504
|
-
tick={{ fill: "
|
|
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="
|
|
515
|
-
tick={{ fill: "
|
|
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: "
|
|
525
|
-
border: "1px solid
|
|
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: "
|
|
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="
|
|
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="
|
|
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-[
|
|
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-[
|
|
566
|
-
<
|
|
567
|
-
<
|
|
568
|
-
<
|
|
569
|
-
<
|
|
570
|
-
<
|
|
571
|
-
<
|
|
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
|
-
{
|
|
576
|
-
<tr key={u.agent_id} className="border-b border-[
|
|
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-[
|
|
579
|
-
<td className="p-3 text-right text-[
|
|
580
|
-
<td className="p-3 text-right text-[
|
|
581
|
-
<td className="p-3 text-right text-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
647
|
-
<div className="p-3 border-b border-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
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-[
|
|
724
|
-
<div className="text-[
|
|
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>
|