groove-dev 0.27.67 → 0.27.69

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 (42) hide show
  1. package/node_modules/@groove-dev/cli/package.json +1 -1
  2. package/node_modules/@groove-dev/daemon/package.json +1 -1
  3. package/node_modules/@groove-dev/daemon/src/api.js +137 -3
  4. package/node_modules/@groove-dev/daemon/src/process.js +11 -5
  5. package/node_modules/@groove-dev/daemon/src/tunnel-manager.js +19 -1
  6. package/node_modules/@groove-dev/gui/dist/assets/index-DhnTm_1P.js +8614 -0
  7. package/node_modules/@groove-dev/gui/dist/assets/index-oQ0ejlfH.css +1 -0
  8. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  9. package/node_modules/@groove-dev/gui/package.json +1 -1
  10. package/node_modules/@groove-dev/gui/src/app.jsx +23 -0
  11. package/node_modules/@groove-dev/gui/src/components/agents/folder-browser.jsx +23 -5
  12. package/node_modules/@groove-dev/gui/src/components/network/activity-chart.jsx +208 -124
  13. package/node_modules/@groove-dev/gui/src/components/network/compute-header.jsx +12 -1
  14. package/node_modules/@groove-dev/gui/src/components/network/identity-bar.jsx +4 -40
  15. package/node_modules/@groove-dev/gui/src/components/network/performance-dashboard.jsx +600 -0
  16. package/node_modules/@groove-dev/gui/src/components/network/token-waterfall.jsx +111 -0
  17. package/node_modules/@groove-dev/gui/src/stores/groove.js +60 -0
  18. package/node_modules/@groove-dev/gui/src/views/network.jsx +6 -0
  19. package/package.json +1 -1
  20. package/packages/cli/package.json +1 -1
  21. package/packages/daemon/package.json +1 -1
  22. package/packages/daemon/src/api.js +137 -3
  23. package/packages/daemon/src/process.js +11 -5
  24. package/packages/daemon/src/tunnel-manager.js +19 -1
  25. package/packages/gui/dist/assets/index-DhnTm_1P.js +8614 -0
  26. package/packages/gui/dist/assets/index-oQ0ejlfH.css +1 -0
  27. package/packages/gui/dist/index.html +2 -2
  28. package/packages/gui/package.json +1 -1
  29. package/packages/gui/src/app.jsx +23 -0
  30. package/packages/gui/src/components/agents/folder-browser.jsx +23 -5
  31. package/packages/gui/src/components/network/activity-chart.jsx +208 -124
  32. package/packages/gui/src/components/network/compute-header.jsx +12 -1
  33. package/packages/gui/src/components/network/identity-bar.jsx +4 -40
  34. package/packages/gui/src/components/network/performance-dashboard.jsx +600 -0
  35. package/packages/gui/src/components/network/token-waterfall.jsx +111 -0
  36. package/packages/gui/src/stores/groove.js +60 -0
  37. package/packages/gui/src/views/network.jsx +6 -0
  38. package/spash-page.png +0 -0
  39. package/node_modules/@groove-dev/gui/dist/assets/index-MPNqazCA.js +0 -8614
  40. package/node_modules/@groove-dev/gui/dist/assets/index-YeunozTU.css +0 -1
  41. package/packages/gui/dist/assets/index-MPNqazCA.js +0 -8614
  42. package/packages/gui/dist/assets/index-YeunozTU.css +0 -1
@@ -0,0 +1,111 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+ import { useMemo, memo } from 'react';
3
+ import { useGrooveStore } from '../../stores/groove';
4
+ import { HEX } from '../../lib/theme-hex';
5
+ import { cn } from '../../lib/cn';
6
+ import { Badge } from '../ui/badge';
7
+
8
+ const PHASE_COLORS = {
9
+ serialize_ms: HEX.info,
10
+ send_ms: HEX.accent,
11
+ wait_ms: HEX.text3,
12
+ forward_ms: HEX.success,
13
+ queue_ms: HEX.warning,
14
+ };
15
+
16
+ const PHASE_LABELS = {
17
+ serialize_ms: 'Serialize',
18
+ send_ms: 'Send',
19
+ wait_ms: 'Wait',
20
+ forward_ms: 'Forward',
21
+ queue_ms: 'Queue',
22
+ };
23
+
24
+ function shortAddr(addr) {
25
+ if (!addr || typeof addr !== 'string') return '\u2014';
26
+ if (addr.length < 14) return addr;
27
+ return `${addr.slice(0, 6)}\u2026${addr.slice(-4)}`;
28
+ }
29
+
30
+ export const TokenWaterfall = memo(function TokenWaterfall() {
31
+ const timing = useGrooveStore((s) => s.networkTokenTiming);
32
+
33
+ const stages = useMemo(() => {
34
+ if (!timing?.stages || !Array.isArray(timing.stages)) return [];
35
+ return timing.stages;
36
+ }, [timing]);
37
+
38
+ if (!stages.length) {
39
+ return (
40
+ <div className="flex items-center justify-center py-6">
41
+ <span className="text-xs font-mono text-text-3">Waiting for token timing data\u2026</span>
42
+ </div>
43
+ );
44
+ }
45
+
46
+ const maxRtt = Math.max(...stages.map((s) => s.rtt_ms || 1), 1);
47
+ const phases = Object.keys(PHASE_COLORS);
48
+
49
+ return (
50
+ <div className="flex flex-col gap-0.5">
51
+ <div className="flex items-center gap-3 px-3 py-1.5 flex-wrap">
52
+ {phases.map((p) => (
53
+ <div key={p} className="flex items-center gap-1">
54
+ <span className="w-2 h-2 rounded-sm flex-shrink-0" style={{ background: PHASE_COLORS[p] }} />
55
+ <span className="text-2xs font-mono text-text-3">{PHASE_LABELS[p]}</span>
56
+ </div>
57
+ ))}
58
+ </div>
59
+
60
+ {stages.map((stage, i) => {
61
+ const rtt = stage.rtt_ms || 1;
62
+ const tel = stage.node_telemetry;
63
+ const gpuModel = tel?.gpu_model;
64
+ const device = tel?.device;
65
+
66
+ return (
67
+ <div key={i} className="flex items-center gap-2 px-3 py-1">
68
+ <div className="w-[110px] flex-shrink-0 flex flex-col gap-0.5">
69
+ <div className="flex items-center gap-1.5">
70
+ <span className="text-2xs font-mono text-text-2 truncate">{shortAddr(stage.node)}</span>
71
+ <Badge variant={stage.via === 'p2p' ? 'success' : 'warning'} className="text-2xs px-1 py-0 leading-tight">
72
+ {stage.via || '?'}
73
+ </Badge>
74
+ </div>
75
+ {gpuModel && (
76
+ <div className="flex items-center gap-1">
77
+ {device && (
78
+ <span className={cn(
79
+ 'text-2xs font-mono px-1 py-0 rounded leading-tight',
80
+ device === 'cuda' ? 'bg-info/20 text-info' : 'bg-purple/20 text-purple',
81
+ )}>
82
+ {device}
83
+ </span>
84
+ )}
85
+ <span className="text-2xs font-mono text-text-4 truncate">{gpuModel}</span>
86
+ </div>
87
+ )}
88
+ </div>
89
+ <div className="flex-1 min-w-0 h-4 bg-surface-2 rounded-sm overflow-hidden relative flex">
90
+ {phases.map((p) => {
91
+ const ms = stage[p] || 0;
92
+ const pct = (ms / maxRtt) * 100;
93
+ return (
94
+ <div
95
+ key={p}
96
+ className="h-full flex-shrink-0 transition-all"
97
+ style={{ width: `${pct}%`, background: PHASE_COLORS[p] }}
98
+ title={`${PHASE_LABELS[p]}: ${ms.toFixed(1)}ms`}
99
+ />
100
+ );
101
+ })}
102
+ </div>
103
+ <span className="text-2xs font-mono text-text-3 tabular-nums w-[52px] text-right flex-shrink-0">
104
+ {rtt.toFixed(1)}ms
105
+ </span>
106
+ </div>
107
+ );
108
+ })}
109
+ </div>
110
+ );
111
+ });
@@ -106,6 +106,11 @@ export const useGrooveStore = create((set, get) => ({
106
106
  networkUpdateProgress: { updating: false, step: null, message: null, percent: 0, error: null },
107
107
  networkCompute: { totalRamMb: 0, totalVramMb: 0, totalCpuCores: 0, totalBandwidthMbps: 0, activeNodes: 0, totalNodes: 0, avgLoad: 0 },
108
108
  networkSnapshots: [],
109
+ networkTokenTiming: null,
110
+ networkBenchmarks: [],
111
+ networkTraces: [],
112
+ networkPerfSnapshots: [],
113
+ networkNodeTelemetry: {},
109
114
  networkWallet: { connected: false, address: null, balance: '0.00', token: 'GROOVE', chain: 'base-l2' },
110
115
  networkEarnings: { today: 0, thisWeek: 0, allTime: 0, history: [] },
111
116
 
@@ -901,6 +906,33 @@ export const useGrooveStore = create((set, get) => ({
901
906
  }
902
907
  break;
903
908
  }
909
+
910
+ case 'network:token:timing': {
911
+ const { __proto__: _a, constructor: _b, prototype: _c, ...td } = msg.data || {};
912
+ const updates = {
913
+ networkTokenTiming: td,
914
+ networkPerfSnapshots: [...get().networkPerfSnapshots, { t: Date.now(), tps: td.tps || 0 }].slice(-100),
915
+ };
916
+ if (Array.isArray(td.stages)) {
917
+ const telMap = { ...get().networkNodeTelemetry };
918
+ const unsafe = new Set(['__proto__', 'constructor', 'prototype']);
919
+ for (const stage of td.stages) {
920
+ const nid = stage.node_telemetry?.node_id;
921
+ if (nid && typeof nid === 'string' && !unsafe.has(nid)) {
922
+ telMap[nid] = { ...stage.node_telemetry, forward_ms: stage.forward_ms, updatedAt: Date.now() };
923
+ }
924
+ }
925
+ updates.networkNodeTelemetry = telMap;
926
+ }
927
+ set(updates);
928
+ break;
929
+ }
930
+
931
+ case 'network:timing:summary': {
932
+ const { __proto__: _a, constructor: _b, prototype: _c, ...sd } = msg.data || {};
933
+ set((s) => ({ networkBenchmarks: [...s.networkBenchmarks, sd].slice(-100) }));
934
+ break;
935
+ }
904
936
  }
905
937
  };
906
938
 
@@ -2279,6 +2311,34 @@ export const useGrooveStore = create((set, get) => ({
2279
2311
  return get().networkEarnings;
2280
2312
  },
2281
2313
 
2314
+ async fetchNetworkBenchmarks() {
2315
+ try {
2316
+ const data = await api.get('/network/benchmarks');
2317
+ if (Array.isArray(data)) set({ networkBenchmarks: data.slice(-100) });
2318
+ return data;
2319
+ } catch { return null; }
2320
+ },
2321
+
2322
+ async fetchNetworkTraces() {
2323
+ try {
2324
+ const data = await api.get('/network/traces');
2325
+ if (Array.isArray(data)) set({ networkTraces: data });
2326
+ return data;
2327
+ } catch { return null; }
2328
+ },
2329
+
2330
+ async fetchNetworkTrace(filename) {
2331
+ try {
2332
+ return await api.get(`/network/traces/${encodeURIComponent(filename)}`);
2333
+ } catch { return null; }
2334
+ },
2335
+
2336
+ async fetchLiveTrace(offset = 0) {
2337
+ try {
2338
+ return await api.get(`/network/traces/live?offset=${offset}`);
2339
+ } catch { return null; }
2340
+ },
2341
+
2282
2342
  async renameFile(oldPath, newPath) {
2283
2343
  try {
2284
2344
  await api.post('/files/rename', { oldPath, newPath });
@@ -17,6 +17,7 @@ import { NodeCard } from '../components/network/node-card';
17
17
  import { EarningsCard } from '../components/network/earnings-card';
18
18
  import { FleetTable } from '../components/network/fleet-table';
19
19
  import { WalletView } from '../components/network/wallet-view';
20
+ import { PerformanceDashboard } from '../components/network/performance-dashboard';
20
21
  import { HEX, hexAlpha } from '../lib/theme-hex';
21
22
  import { Globe, Download, Check, AlertCircle, Loader2, Trash2, ArrowUpCircle, Zap } from 'lucide-react';
22
23
 
@@ -483,6 +484,7 @@ export default function NetworkView() {
483
484
  <TabsList className="bg-surface-0 border-b border-border-subtle px-4 flex-shrink-0">
484
485
  <TabsTrigger value="overview" className="text-xs">Overview</TabsTrigger>
485
486
  <TabsTrigger value="fleet" className="text-xs">Fleet</TabsTrigger>
487
+ <TabsTrigger value="performance" className="text-xs flex items-center gap-1"><Zap size={10} />Performance</TabsTrigger>
486
488
  <TabsTrigger value="wallet" className="text-xs">Wallet</TabsTrigger>
487
489
  </TabsList>
488
490
 
@@ -494,6 +496,10 @@ export default function NetworkView() {
494
496
  <FleetTable />
495
497
  </TabsContent>
496
498
 
499
+ <TabsContent value="performance" className="flex-1 min-h-0 overflow-hidden bg-surface-1">
500
+ <PerformanceDashboard active={activeTab === 'performance'} />
501
+ </TabsContent>
502
+
497
503
  <TabsContent value="wallet" className="flex-1 min-h-0 overflow-hidden">
498
504
  <WalletView />
499
505
  </TabsContent>
package/spash-page.png ADDED
Binary file