@cryptiklemur/lattice 1.8.0 → 1.9.0
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.
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Component } from "react";
|
|
2
2
|
import { useAnalytics } from "../../hooks/useAnalytics";
|
|
3
|
+
import { useMesh } from "../../hooks/useMesh";
|
|
3
4
|
|
|
4
5
|
class ChartErrorBoundary extends Component<{ children: React.ReactNode; name: string }, { error: Error | null }> {
|
|
5
6
|
constructor(props: { children: React.ReactNode; name: string }) {
|
|
@@ -41,9 +42,12 @@ import { ToolSunburst } from "./charts/ToolSunburst";
|
|
|
41
42
|
import { PermissionBreakdown } from "./charts/PermissionBreakdown";
|
|
42
43
|
import { ProjectRadar } from "./charts/ProjectRadar";
|
|
43
44
|
import { SessionComplexityList } from "./charts/SessionComplexityList";
|
|
45
|
+
import { NodeFleetOverview } from "./charts/NodeFleetOverview";
|
|
44
46
|
|
|
45
47
|
export function AnalyticsView() {
|
|
46
48
|
var analytics = useAnalytics();
|
|
49
|
+
var mesh = useMesh();
|
|
50
|
+
var nodes = mesh.nodes;
|
|
47
51
|
|
|
48
52
|
return (
|
|
49
53
|
<div className="flex flex-col h-full overflow-hidden bg-base-100 bg-lattice-grid">
|
|
@@ -173,6 +177,12 @@ export function AnalyticsView() {
|
|
|
173
177
|
<SessionComplexityList data={analytics.data.sessionComplexity} />
|
|
174
178
|
</ChartErrorBoundary>
|
|
175
179
|
</ChartCard>
|
|
180
|
+
|
|
181
|
+
<ChartCard title="Node Fleet">
|
|
182
|
+
<ChartErrorBoundary name="Fleet">
|
|
183
|
+
<NodeFleetOverview nodes={nodes} />
|
|
184
|
+
</ChartErrorBoundary>
|
|
185
|
+
</ChartCard>
|
|
176
186
|
</div>
|
|
177
187
|
)}
|
|
178
188
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Server, Wifi, WifiOff } from "lucide-react";
|
|
2
|
+
import type { NodeInfo } from "@lattice/shared";
|
|
3
|
+
|
|
4
|
+
interface NodeFleetOverviewProps {
|
|
5
|
+
nodes: NodeInfo[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function NodeFleetOverview(props: NodeFleetOverviewProps) {
|
|
9
|
+
var nodes = props.nodes;
|
|
10
|
+
|
|
11
|
+
if (nodes.length === 0) {
|
|
12
|
+
return (
|
|
13
|
+
<div className="flex items-center justify-center h-[200px] text-base-content/30 font-mono text-[12px]">
|
|
14
|
+
No nodes connected
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
21
|
+
{nodes.map(function (node) {
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
key={node.id}
|
|
25
|
+
className={
|
|
26
|
+
"rounded-lg border p-3.5 transition-colors " +
|
|
27
|
+
(node.online
|
|
28
|
+
? "border-success/20 bg-success/[0.03]"
|
|
29
|
+
: "border-base-content/8 bg-base-content/[0.02] opacity-60")
|
|
30
|
+
}
|
|
31
|
+
>
|
|
32
|
+
<div className="flex items-center gap-2.5 mb-2.5">
|
|
33
|
+
<Server size={14} className={node.online ? "text-success/60" : "text-base-content/25"} />
|
|
34
|
+
<span className="text-[13px] font-mono font-medium text-base-content/80 truncate">{node.name}</span>
|
|
35
|
+
<span className="ml-auto flex-shrink-0">
|
|
36
|
+
{node.online
|
|
37
|
+
? <Wifi size={12} className="text-success/50" />
|
|
38
|
+
: <WifiOff size={12} className="text-base-content/20" />
|
|
39
|
+
}
|
|
40
|
+
</span>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div className="flex flex-col gap-1">
|
|
44
|
+
<div className="flex items-center justify-between text-[10px] font-mono">
|
|
45
|
+
<span className="text-base-content/35 uppercase tracking-wider">Address</span>
|
|
46
|
+
<span className="text-base-content/50">{node.address}:{node.port}</span>
|
|
47
|
+
</div>
|
|
48
|
+
<div className="flex items-center justify-between text-[10px] font-mono">
|
|
49
|
+
<span className="text-base-content/35 uppercase tracking-wider">Projects</span>
|
|
50
|
+
<span className="text-base-content/50">{node.projects.length}</span>
|
|
51
|
+
</div>
|
|
52
|
+
<div className="flex items-center justify-between text-[10px] font-mono">
|
|
53
|
+
<span className="text-base-content/35 uppercase tracking-wider">Status</span>
|
|
54
|
+
<span className={node.online ? "text-success/70" : "text-base-content/30"}>
|
|
55
|
+
{node.online ? "Online" : "Offline"}
|
|
56
|
+
</span>
|
|
57
|
+
</div>
|
|
58
|
+
{node.isLocal && (
|
|
59
|
+
<div className="flex items-center justify-between text-[10px] font-mono">
|
|
60
|
+
<span className="text-base-content/35 uppercase tracking-wider">Type</span>
|
|
61
|
+
<span className="text-primary/50">Local</span>
|
|
62
|
+
</div>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
{node.projects.length > 0 && (
|
|
67
|
+
<div className="mt-2.5 pt-2 border-t border-base-content/5">
|
|
68
|
+
<div className="text-[9px] font-mono text-base-content/25 uppercase tracking-widest mb-1.5">Projects</div>
|
|
69
|
+
<div className="flex flex-wrap gap-1">
|
|
70
|
+
{node.projects.map(function (p) {
|
|
71
|
+
return (
|
|
72
|
+
<span
|
|
73
|
+
key={p.slug}
|
|
74
|
+
className="px-1.5 py-0.5 rounded text-[9px] font-mono bg-base-content/5 text-base-content/40"
|
|
75
|
+
>
|
|
76
|
+
{p.slug}
|
|
77
|
+
</span>
|
|
78
|
+
);
|
|
79
|
+
})}
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
})}
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cryptiklemur/lattice",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "Multi-machine agentic dashboard for Claude Code. Monitor sessions, manage MCP servers and skills, orchestrate across mesh-networked nodes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Aaron Scherer <me@aaronscherer.me>",
|