@cryptiklemur/lattice 1.37.0 → 1.37.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cryptiklemur/lattice",
3
- "version": "1.37.0",
3
+ "version": "1.37.2",
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>",
@@ -250,7 +250,7 @@ export async function startDaemon(portOverride?: number | null): Promise<void> {
250
250
  }
251
251
  }
252
252
 
253
- if (!isAuthenticated(req, config.passphraseHash)) {
253
+ if (url.pathname !== "/ws" && !isAuthenticated(req, config.passphraseHash)) {
254
254
  return new Response(buildLoginPage(), {
255
255
  status: 200,
256
256
  headers: { "Content-Type": "text/html; charset=utf-8" },
@@ -5,7 +5,8 @@ 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, getPeer } from "../mesh/peers";
8
- import { getConnectedPeerIds, connectToPeer, reconnectPeer, getPeerConnection, disconnectPeer, getConnectedPeerProjects } from "../mesh/connector";
8
+ import { getConnectedPeerIds, connectToPeer, reconnectPeer, getPeerConnection, disconnectPeer, getConnectedPeerProjects, registerInboundPeer } from "../mesh/connector";
9
+ import { getClientWebSocket } from "../ws/broadcast";
9
10
  import type { PeerInfo } from "@lattice/shared";
10
11
  import { networkInterfaces } from "node:os";
11
12
  import { existsSync, readFileSync } from "node:fs";
@@ -237,6 +238,12 @@ registerHandler("mesh", function (clientId: string, message: ClientMessage) {
237
238
  sendTo(clientId, { type: "mesh:hello_rejected" as any, error: "Public key mismatch — possible impersonation" });
238
239
  return;
239
240
  }
241
+
242
+ var inboundWs = getClientWebSocket(clientId);
243
+ if (inboundWs) {
244
+ registerInboundPeer(hello.nodeId, inboundWs as any);
245
+ }
246
+
240
247
  var identity = loadOrCreateIdentity();
241
248
  sendTo(clientId, {
242
249
  type: "mesh:hello" as any,
@@ -239,6 +239,52 @@ export function getPeerConnection(nodeId: string): WebSocket | undefined {
239
239
  return conn.ws;
240
240
  }
241
241
 
242
+ export function registerInboundPeer(nodeId: string, ws: { send: (data: string) => void; readyState: number }): void {
243
+ var existing = connections.get(nodeId);
244
+ if (existing && !existing.dead && existing.ws.readyState === WebSocket.OPEN) {
245
+ return;
246
+ }
247
+
248
+ if (existing) {
249
+ existing.dead = true;
250
+ if (existing.retryTimer !== null) {
251
+ clearTimeout(existing.retryTimer);
252
+ }
253
+ }
254
+
255
+ circuitBreakers.delete(nodeId);
256
+
257
+ var conn: PeerConnection = {
258
+ nodeId: nodeId,
259
+ ws: ws as WebSocket,
260
+ backoffMs: 1000,
261
+ retryTimer: null,
262
+ dead: false,
263
+ projects: [],
264
+ };
265
+
266
+ connections.set(nodeId, conn);
267
+
268
+ var peers = loadPeers();
269
+ var peer = peers.find(function (p) { return p.id === nodeId; });
270
+ if (peer) {
271
+ var identity = loadOrCreateIdentity();
272
+ var config = loadConfig();
273
+ var projects = config.projects || [];
274
+ conn.projects = [];
275
+
276
+ ws.send(JSON.stringify({
277
+ type: "mesh:hello",
278
+ nodeId: identity.id,
279
+ name: config.name,
280
+ publicKey: identity.publicKey,
281
+ projects: projects.map(function (p: { slug: string; title: string }) {
282
+ return { slug: p.slug, title: p.title };
283
+ }),
284
+ }));
285
+ }
286
+ }
287
+
242
288
  export function disconnectPeer(nodeId: string): void {
243
289
  var existing = connections.get(nodeId);
244
290
  if (existing) {
@@ -40,6 +40,10 @@ export function sendTo(id: string, message: object): void {
40
40
  }
41
41
  }
42
42
 
43
+ export function getClientWebSocket(id: string): ServerWebSocket<{ id: string }> | undefined {
44
+ return clients.get(id);
45
+ }
46
+
43
47
  export function getClientCount(): number {
44
48
  return clients.size;
45
49
  }