@cryptiklemur/lattice 1.40.0 → 1.40.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.40.0",
3
+ "version": "1.40.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>",
@@ -1,5 +1,7 @@
1
1
  import type { ClientMessage, MeshPairMessage, MeshUnpairMessage, NodeInfo } from "@lattice/shared";
2
2
  import { log } from "../logger";
3
+ import { handleProxyRequest, handleProxyResponse } from "../mesh/proxy";
4
+ import type { MeshProxyRequestMessage, MeshProxyResponseMessage } from "@lattice/shared";
3
5
  import { registerHandler } from "../ws/router";
4
6
  import { sendTo, broadcast } from "../ws/broadcast";
5
7
  import { loadConfig } from "../config";
@@ -7,7 +9,7 @@ import { loadOrCreateIdentity } from "../identity";
7
9
  import { generateInviteCode, parseInviteCode, validatePairingToken, consumePairingToken } from "../mesh/pairing";
8
10
  import { addPeer, removePeer, loadPeers, getPeer } from "../mesh/peers";
9
11
  import { getConnectedPeerIds, connectToPeer, reconnectPeer, getPeerConnection, disconnectPeer, getConnectedPeerProjects, registerInboundPeer } from "../mesh/connector";
10
- import { getClientWebSocket } from "../ws/broadcast";
12
+ import { getClientWebSocket, registerVirtualClient, removeVirtualClient } from "../ws/broadcast";
11
13
  import type { PeerInfo } from "@lattice/shared";
12
14
  import { networkInterfaces } from "node:os";
13
15
  import { existsSync, readFileSync } from "node:fs";
@@ -245,9 +247,9 @@ registerHandler("mesh", function (clientId: string, message: ClientMessage) {
245
247
  }
246
248
 
247
249
  var inboundWs = getClientWebSocket(clientId);
248
- log.meshHello(" registering inbound connection for %s (ws=%s)", hello.name, !!inboundWs);
250
+ log.meshHello(" registering inbound connection for %s (ws=%s, projects=%d)", hello.name, !!inboundWs, hello.projects?.length ?? 0);
249
251
  if (inboundWs) {
250
- registerInboundPeer(hello.nodeId, inboundWs as any);
252
+ registerInboundPeer(hello.nodeId, inboundWs as any, hello.projects ?? []);
251
253
  }
252
254
 
253
255
  var identity = loadOrCreateIdentity();
@@ -296,6 +298,33 @@ registerHandler("mesh", function (clientId: string, message: ClientMessage) {
296
298
  return;
297
299
  }
298
300
 
301
+ if ((message as any).type === "mesh:proxy_request") {
302
+ var proxyReq = message as unknown as MeshProxyRequestMessage;
303
+ log.meshProxy("received proxy_request via handler from %s: %s for %s", clientId.slice(0, 8), (proxyReq.payload as any).type, proxyReq.projectSlug);
304
+
305
+ registerVirtualClient("mesh-proxy:" + clientId + ":" + proxyReq.requestId, function (response: object) {
306
+ log.meshProxy(" → sending proxy_response %s back to client %s", (response as any).type, clientId.slice(0, 8));
307
+ sendTo(clientId, {
308
+ type: "mesh:proxy_response",
309
+ projectSlug: proxyReq.projectSlug,
310
+ requestId: proxyReq.requestId,
311
+ payload: response,
312
+ } as any);
313
+ removeVirtualClient("mesh-proxy:" + clientId + ":" + proxyReq.requestId);
314
+ });
315
+
316
+ var { routeMessage: routeMsg } = require("../ws/router") as typeof import("../ws/router");
317
+ routeMsg("mesh-proxy:" + clientId + ":" + proxyReq.requestId, proxyReq.payload);
318
+ return;
319
+ }
320
+
321
+ if ((message as any).type === "mesh:proxy_response") {
322
+ var proxyRes = message as unknown as MeshProxyResponseMessage;
323
+ log.meshProxy("received proxy_response via handler: %s", (proxyRes.payload as any).type);
324
+ handleProxyResponse(proxyRes);
325
+ return;
326
+ }
327
+
299
328
  if (message.type === "mesh:reconnect") {
300
329
  var reconnectMsg = message as { type: "mesh:reconnect"; nodeId: string };
301
330
  reconnectPeer(reconnectMsg.nodeId);
@@ -252,7 +252,7 @@ export function getPeerConnection(nodeId: string): WebSocket | undefined {
252
252
  return conn.ws;
253
253
  }
254
254
 
255
- export function registerInboundPeer(nodeId: string, ws: { send: (data: string) => void; readyState: number }): void {
255
+ export function registerInboundPeer(nodeId: string, ws: { send: (data: string) => void; readyState: number }, peerProjects?: Array<{ slug: string; title: string }>): void {
256
256
  var existing = connections.get(nodeId);
257
257
  if (existing && !existing.dead && existing.ws.readyState === WebSocket.OPEN) {
258
258
  log.meshConnect("inbound peer %s already connected, skipping", nodeId.slice(0, 8));
@@ -269,15 +269,20 @@ export function registerInboundPeer(nodeId: string, ws: { send: (data: string) =
269
269
 
270
270
  circuitBreakers.delete(nodeId);
271
271
 
272
+ var incomingProjects = peerProjects ?? [];
272
273
  var conn: PeerConnection = {
273
274
  nodeId: nodeId,
274
275
  ws: ws as WebSocket,
275
276
  backoffMs: 1000,
276
277
  retryTimer: null,
277
278
  dead: false,
278
- projects: [],
279
+ projects: incomingProjects,
279
280
  };
280
281
 
282
+ if (incomingProjects.length > 0) {
283
+ lastKnownProjects.set(nodeId, incomingProjects);
284
+ }
285
+
281
286
  connections.set(nodeId, conn);
282
287
 
283
288
  var peers = loadPeers();