@cryptiklemur/lattice 5.12.8 → 5.13.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.
@@ -15,7 +15,7 @@ import { startDiscovery } from "./mesh/discovery.js";
15
15
  import { startMeshConnections, onPeerConnected, onPeerDisconnected, onPeerMessage, getAllRemoteProjects } from "./mesh/connector.js";
16
16
  import { handleProxyRequest, handleProxyResponse } from "./mesh/proxy.js";
17
17
  import { verifyPassphrase, generateSessionToken, addSession, isValidSession } from "./auth/passphrase.js";
18
- import { log } from "./logger.js";
18
+ import { log, initFileLogger } from "./logger.js";
19
19
  import { detectIdeProjectName } from "./handlers/settings.js";
20
20
  import "./handlers/session.js";
21
21
  import "./handlers/chat.js";
@@ -326,6 +326,7 @@ export async function startDaemon(portOverride, tlsOverride) {
326
326
  if (tlsOverride !== null && tlsOverride !== undefined) {
327
327
  config.tls = tlsOverride;
328
328
  }
329
+ initFileLogger(getLatticeHome());
329
330
  const identity = loadOrCreateIdentity();
330
331
  log.server("Node: %s (%s)", config.name, identity.id);
331
332
  log.server("Home: %s", getLatticeHome());
@@ -1,21 +1,50 @@
1
1
  import createDebug from "debug";
2
+ import { createWriteStream, existsSync, mkdirSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { format } from "node:util";
5
+ let fileStream = null;
6
+ export function initFileLogger(latticeHome) {
7
+ const logsDir = join(latticeHome, "logs");
8
+ if (!existsSync(logsDir)) {
9
+ mkdirSync(logsDir, { recursive: true });
10
+ }
11
+ const logPath = join(logsDir, "debug.log");
12
+ fileStream = createWriteStream(logPath, { flags: "a" });
13
+ fileStream.on("error", function () {
14
+ fileStream = null;
15
+ });
16
+ }
17
+ function writeToFile(namespace, fmt, ...args) {
18
+ if (!fileStream)
19
+ return;
20
+ const timestamp = new Date().toISOString();
21
+ const message = format(fmt, ...args);
22
+ fileStream.write(timestamp + " " + namespace + " " + message + "\n");
23
+ }
24
+ function createLogger(namespace) {
25
+ const debugInstance = createDebug(namespace);
26
+ return function (fmt, ...args) {
27
+ writeToFile(namespace, fmt, ...args);
28
+ debugInstance(fmt, ...args);
29
+ };
30
+ }
2
31
  export const log = {
3
- server: createDebug("lattice:server"),
4
- ws: createDebug("lattice:ws"),
5
- chat: createDebug("lattice:chat"),
6
- session: createDebug("lattice:session"),
7
- mesh: createDebug("lattice:mesh"),
8
- meshConnect: createDebug("lattice:mesh:connect"),
9
- meshHello: createDebug("lattice:mesh:hello"),
10
- meshProxy: createDebug("lattice:mesh:proxy"),
11
- router: createDebug("lattice:router"),
12
- broadcast: createDebug("lattice:broadcast"),
13
- auth: createDebug("lattice:auth"),
14
- fs: createDebug("lattice:fs"),
15
- analytics: createDebug("lattice:analytics"),
16
- plugins: createDebug("lattice:plugins"),
17
- update: createDebug("lattice:update"),
18
- terminal: createDebug("lattice:terminal"),
19
- settings: createDebug("lattice:settings"),
20
- superpowers: createDebug("lattice:superpowers"),
32
+ server: createLogger("lattice:server"),
33
+ ws: createLogger("lattice:ws"),
34
+ chat: createLogger("lattice:chat"),
35
+ session: createLogger("lattice:session"),
36
+ mesh: createLogger("lattice:mesh"),
37
+ meshConnect: createLogger("lattice:mesh:connect"),
38
+ meshHello: createLogger("lattice:mesh:hello"),
39
+ meshProxy: createLogger("lattice:mesh:proxy"),
40
+ router: createLogger("lattice:router"),
41
+ broadcast: createLogger("lattice:broadcast"),
42
+ auth: createLogger("lattice:auth"),
43
+ fs: createLogger("lattice:fs"),
44
+ analytics: createLogger("lattice:analytics"),
45
+ plugins: createLogger("lattice:plugins"),
46
+ update: createLogger("lattice:update"),
47
+ terminal: createLogger("lattice:terminal"),
48
+ settings: createLogger("lattice:settings"),
49
+ superpowers: createLogger("lattice:superpowers"),
21
50
  };
@@ -376,6 +376,7 @@ function buildSDKUserMessage(prompt, attachments, sessionId) {
376
376
  }
377
377
  function pushToExistingStream(session, options) {
378
378
  const { text, attachments, clientId, sessionId, model } = options;
379
+ log.chat("Session %s pushing to existing stream (ended=%s)", sessionId, String(session.ended));
379
380
  session.clientId = clientId;
380
381
  session.turnStartTime = Date.now();
381
382
  session.turnDoneSent = false;
@@ -398,6 +399,7 @@ function pushToExistingStream(session, options) {
398
399
  }
399
400
  export function startChatStream(options) {
400
401
  const { projectSlug, sessionId, text, attachments, clientId, cwd, env, model, effort, isNewSession } = options;
402
+ log.chat("startChatStream called: session=%s project=%s client=%s", sessionId, projectSlug, clientId);
401
403
  const existing = sessionStreams.get(sessionId);
402
404
  if (existing && !existing.ended) {
403
405
  pushToExistingStream(existing, options);
@@ -470,9 +472,7 @@ export function startChatStream(options) {
470
472
  additionalDirectories: savedAdditionalDirs.length > 0 ? savedAdditionalDirs : undefined,
471
473
  mcpServers: Object.keys(mcpServers).length > 0 ? mcpServers : undefined,
472
474
  stderr: function (data) {
473
- if (data.includes("error") || data.includes("Error") || data.includes("credit") || data.includes("Credit") || data.includes("billing") || data.includes("auth")) {
474
- log.chat("SDK stderr: %s", data.trim());
475
- }
475
+ log.chat("Session %s SDK stderr: %s", sessionId, data.trim());
476
476
  },
477
477
  };
478
478
  queryOptions.toolConfig = {
@@ -685,20 +685,31 @@ export function startChatStream(options) {
685
685
  persistStreamState();
686
686
  broadcast({ type: "session:busy", sessionId, busy: true }, clientId);
687
687
  void (async function () {
688
+ log.chat("Session %s stream starting (resume=%s, model=%s)", sessionId, String(shouldResume), model || "default");
688
689
  try {
689
690
  await stream.initializationResult();
691
+ log.chat("Session %s SDK initialized", sessionId);
690
692
  }
691
693
  catch (initErr) {
692
- log.chat("Session %s SDK initialization warning: %O", sessionId, initErr);
694
+ log.chat("Session %s SDK initialization FAILED: %O", sessionId, initErr);
693
695
  }
696
+ log.chat("Session %s pushing first message to queue", sessionId);
694
697
  mq.push(firstMsg);
695
698
  try {
699
+ log.chat("Session %s entering stream loop", sessionId);
700
+ let msgCount = 0;
696
701
  for await (const msg of stream) {
702
+ msgCount++;
703
+ if (msgCount <= 3 || msg.type === "result") {
704
+ log.chat("Session %s msg #%d type=%s", sessionId, msgCount, msg.type);
705
+ }
697
706
  processMessage(sessionStream, msg);
698
707
  }
708
+ log.chat("Session %s stream ended normally after %d messages", sessionId, msgCount);
699
709
  }
700
710
  catch (err) {
701
711
  const errMsg = err instanceof Error ? err.message : String(err);
712
+ log.chat("Session %s stream error: %s", sessionId, errMsg);
702
713
  if (errMsg.includes("aborted") || errMsg.includes("AbortError")) {
703
714
  log.chat("Session %s stream aborted", sessionId);
704
715
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cryptiklemur/lattice",
3
- "version": "5.12.8",
3
+ "version": "5.13.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>",