@cryptiklemur/lattice 1.30.1 → 1.31.1

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.
@@ -39,11 +39,18 @@ function NodeRow(props: NodeRowProps) {
39
39
  </span>
40
40
  )}
41
41
  </div>
42
- <div className="text-[11px] text-base-content/40 truncate">
43
- {props.node.address}:{props.node.port}
44
- {!props.node.online && (
45
- <span className="ml-2 text-base-content/30 italic">offline</span>
46
- )}
42
+ <div className="text-[11px] text-base-content/40">
43
+ {(props.node.addresses && props.node.addresses.length > 0
44
+ ? props.node.addresses
45
+ : [props.node.address + (props.node.port ? ":" + props.node.port : "")]
46
+ ).map(function (addr, i) {
47
+ return (
48
+ <span key={addr} className="mr-2">
49
+ {i > 0 && <span className="text-base-content/20 mr-2">/</span>}
50
+ {addr}
51
+ </span>
52
+ );
53
+ })}
47
54
  </div>
48
55
  </div>
49
56
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cryptiklemur/lattice",
3
- "version": "1.30.1",
3
+ "version": "1.31.1",
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>",
@@ -5,6 +5,7 @@ import { loadConfig } from "../config";
5
5
  import { loadOrCreateIdentity } from "../identity";
6
6
  import { generateInviteCode, parseInviteCode, validatePairingToken, consumePairingToken } from "../mesh/pairing";
7
7
  import { addPeer, removePeer, loadPeers } from "../mesh/peers";
8
+ import { getConnectedPeerIds, connectToPeer } from "../mesh/connector";
8
9
  import type { PeerInfo } from "@lattice/shared";
9
10
  import { networkInterfaces } from "node:os";
10
11
 
@@ -33,11 +34,14 @@ export function buildNodesMessage(): NodeInfo[] {
33
34
  var peers = loadPeers();
34
35
  var config = loadConfig();
35
36
  var identity = loadOrCreateIdentity();
37
+ var connectedIds = new Set(getConnectedPeerIds());
38
+ var localAddrs = getAllAddresses().map(function (a) { return a.address + ":" + config.port; });
36
39
 
37
40
  var local: NodeInfo = {
38
41
  id: identity.id,
39
42
  name: config.name,
40
- address: "localhost",
43
+ address: localAddrs[0] ?? "localhost:" + config.port,
44
+ addresses: localAddrs.length > 0 ? localAddrs : ["localhost:" + config.port],
41
45
  port: config.port,
42
46
  online: true,
43
47
  isLocal: true,
@@ -51,8 +55,9 @@ export function buildNodesMessage(): NodeInfo[] {
51
55
  id: peer.id,
52
56
  name: peer.name,
53
57
  address: peer.addresses[0] ?? "",
58
+ addresses: peer.addresses,
54
59
  port: 0,
55
- online: false,
60
+ online: connectedIds.has(peer.id),
56
61
  isLocal: false,
57
62
  projects: [],
58
63
  };
@@ -101,11 +106,14 @@ registerHandler("mesh", function (clientId: string, message: ClientMessage) {
101
106
 
102
107
  pairWs.addEventListener("open", function () {
103
108
  var identity = loadOrCreateIdentity();
109
+ var pairConfig = loadConfig();
104
110
  pairWs.send(JSON.stringify({
105
111
  type: "mesh:hello",
106
112
  nodeId: identity.id,
107
- name: loadConfig().name,
113
+ name: pairConfig.name,
108
114
  token: parsed!.token,
115
+ port: pairConfig.port,
116
+ addresses: getAllAddresses().map(function (a) { return a.address + ":" + pairConfig.port; }),
109
117
  projects: [],
110
118
  }));
111
119
  });
@@ -123,20 +131,24 @@ registerHandler("mesh", function (clientId: string, message: ClientMessage) {
123
131
 
124
132
  if (data.type === "mesh:hello" && data.nodeId && data.name) {
125
133
  clearTimeout(pairTimeout);
134
+ var peerAddr = parsed!.address + ":" + parsed!.port;
126
135
  var peer: PeerInfo = {
127
136
  id: data.nodeId,
128
137
  name: data.name,
129
- addresses: [parsed!.address],
138
+ addresses: [peerAddr],
130
139
  publicKey: "",
131
140
  pairedAt: Date.now(),
132
141
  };
133
142
  addPeer(peer);
134
143
  pairWs.close();
135
144
 
145
+ connectToPeer(peer.id, peerAddr);
146
+
136
147
  var nodeInfo: NodeInfo = {
137
148
  id: peer.id,
138
149
  name: peer.name,
139
- address: parsed!.address,
150
+ address: peerAddr,
151
+ addresses: [peerAddr],
140
152
  port: parsed!.port,
141
153
  online: true,
142
154
  isLocal: false,
@@ -158,7 +170,7 @@ registerHandler("mesh", function (clientId: string, message: ClientMessage) {
158
170
  }
159
171
 
160
172
  if ((message as any).type === "mesh:hello") {
161
- var hello = message as any as { type: "mesh:hello"; nodeId: string; name: string; token?: string; projects: Array<{ slug: string; title: string }> };
173
+ var hello = message as any as { type: "mesh:hello"; nodeId: string; name: string; token?: string; port?: number; addresses?: string[]; projects: Array<{ slug: string; title: string }> };
162
174
 
163
175
  if (!hello.token || !validatePairingToken(hello.token)) {
164
176
  sendTo(clientId, { type: "mesh:hello_rejected" as any, error: "Invalid or expired invite code" });
@@ -166,15 +178,21 @@ registerHandler("mesh", function (clientId: string, message: ClientMessage) {
166
178
  }
167
179
  consumePairingToken(hello.token);
168
180
 
181
+ var peerAddresses = hello.addresses ?? [];
182
+
169
183
  var peer: PeerInfo = {
170
184
  id: hello.nodeId,
171
185
  name: hello.name,
172
- addresses: [],
186
+ addresses: peerAddresses,
173
187
  publicKey: "",
174
188
  pairedAt: Date.now(),
175
189
  };
176
190
  addPeer(peer);
177
191
 
192
+ if (peerAddresses.length > 0) {
193
+ connectToPeer(peer.id, peerAddresses[0]);
194
+ }
195
+
178
196
  var identity = loadOrCreateIdentity();
179
197
  sendTo(clientId, {
180
198
  type: "mesh:hello" as any,
@@ -66,9 +66,10 @@ export function connectToPeer(nodeId: string, address: string): void {
66
66
  }
67
67
 
68
68
  var config = loadConfig();
69
- var port = config.port;
70
69
  var protocol = config.tls ? "wss" : "ws";
71
- var url = protocol + "://" + address + ":" + port + "/ws";
70
+ var url = address.includes(":")
71
+ ? protocol + "://" + address + "/ws"
72
+ : protocol + "://" + address + ":" + config.port + "/ws";
72
73
 
73
74
  var conn: PeerConnection = {
74
75
  nodeId: nodeId,
@@ -4,6 +4,7 @@ export interface NodeInfo {
4
4
  id: string;
5
5
  name: string;
6
6
  address: string;
7
+ addresses: string[];
7
8
  port: number;
8
9
  online: boolean;
9
10
  isLocal: boolean;