@cryptiklemur/lattice 5.10.0 → 5.11.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.
Files changed (142) hide show
  1. package/dist/client/assets/{angular-html-BDIcxkJq.js → angular-html-BoFzmWT8.js} +1 -1
  2. package/dist/client/assets/{angular-ts-Bt22ouNH.js → angular-ts-DZnI8rKE.js} +1 -1
  3. package/dist/client/assets/{apl-p8qkxzEK.js → apl-DstVmncE.js} +1 -1
  4. package/dist/client/assets/{astro-CIaMc49M.js → astro-DTPCjzEx.js} +1 -1
  5. package/dist/client/assets/{blade-BR56EAMD.js → blade-6q42Ss3F.js} +1 -1
  6. package/dist/client/assets/{c-Dli0HzAh.js → c-BQDGJ-nQ.js} +1 -1
  7. package/dist/client/assets/{cobol-Cad15ECy.js → cobol-Dlh0WvsZ.js} +1 -1
  8. package/dist/client/assets/{coffee-DpyATEbF.js → coffee-DdQv129j.js} +1 -1
  9. package/dist/client/assets/{cpp-KN8_NFsf.js → cpp-DhbQJIv4.js} +1 -1
  10. package/dist/client/assets/{crystal-CuyGv0kh.js → crystal-C22kERUB.js} +1 -1
  11. package/dist/client/assets/{css-Cm3q4bxn.js → css-n31O5kHj.js} +1 -1
  12. package/dist/client/assets/{dist-BjxsMc4u.js → dist-D8okl7lw.js} +2 -2
  13. package/dist/client/assets/{edge-B6S7CSbx.js → edge-Cgwx-o_7.js} +1 -1
  14. package/dist/client/assets/{elixir-CNUy9H8T.js → elixir-DAGM2WKD.js} +1 -1
  15. package/dist/client/assets/{elm-CNfcWmb9.js → elm-BLw_7oO9.js} +1 -1
  16. package/dist/client/assets/{erb-DWebzDaI.js → erb-DCaNhYa7.js} +1 -1
  17. package/dist/client/assets/{git-rebase-B_Pt2ZBK.js → git-rebase-CNNhb8-g.js} +1 -1
  18. package/dist/client/assets/{glimmer-js-CVwoOd72.js → glimmer-js-BnZd88Wi.js} +1 -1
  19. package/dist/client/assets/{glimmer-ts-CjtFSxjz.js → glimmer-ts-DvFNbZu-.js} +1 -1
  20. package/dist/client/assets/{glsl-CP4rggAA.js → glsl-Dnrk_Jnx.js} +1 -1
  21. package/dist/client/assets/{graphql-Dbm6sAtp.js → graphql-DlWTPvCG.js} +1 -1
  22. package/dist/client/assets/{hack-Bj9y3SGf.js → hack-DQg1Ek33.js} +1 -1
  23. package/dist/client/assets/{haml-DRGrdf3f.js → haml-DSk45qIE.js} +1 -1
  24. package/dist/client/assets/{handlebars-CFKjcBMg.js → handlebars-DuLvATB2.js} +1 -1
  25. package/dist/client/assets/{html-Vcd4eHHg.js → html-D4DiUnLg.js} +1 -1
  26. package/dist/client/assets/{html-derivative-BF0YbD4L.js → html-derivative-CS5MZ6d9.js} +1 -1
  27. package/dist/client/assets/{http-CGVTa2NT.js → http-CkDncfer.js} +1 -1
  28. package/dist/client/assets/{hurl-B0GrsGqd.js → hurl-DU39oO3U.js} +1 -1
  29. package/dist/client/assets/{index-CX1tudsF.js → index-CHPfE1Zl.js} +129 -129
  30. package/dist/client/assets/index-DHUKmLLC.css +2 -0
  31. package/dist/client/assets/{java-BJHQqHsm.js → java-lntACKEu.js} +1 -1
  32. package/dist/client/assets/{javascript-CmuMsKrc.js → javascript-CxkFc6nV.js} +1 -1
  33. package/dist/client/assets/{jinja-JxCLeq1j.js → jinja-DolO2zO7.js} +1 -1
  34. package/dist/client/assets/{jison-BdgAUhei.js → jison-Cok5FPev.js} +1 -1
  35. package/dist/client/assets/{json-DtPissHL.js → json-BebuQPrq.js} +1 -1
  36. package/dist/client/assets/{jsx-DUAxxDkP.js → jsx-iLBaUyXr.js} +1 -1
  37. package/dist/client/assets/{julia-DxDlbL6e.js → julia-C5Dsc7cH.js} +1 -1
  38. package/dist/client/assets/{just-CVmAAx2R.js → just-DJYqq_9R.js} +1 -1
  39. package/dist/client/assets/{latex-uwxggTWA.js → latex-BTTYiKj1.js} +1 -1
  40. package/dist/client/assets/{liquid-xsETAJJy.js → liquid-DpAKCrOB.js} +1 -1
  41. package/dist/client/assets/{lua-B2Hh8PgD.js → lua-BZ6b1hko.js} +1 -1
  42. package/dist/client/assets/{marko-yDeGxD87.js → marko-D8VK6iGt.js} +1 -1
  43. package/dist/client/assets/{mdc-QMp4ieYR.js → mdc-Paa3XzwY.js} +1 -1
  44. package/dist/client/assets/{nginx-7gmRmcqz.js → nginx-C5k9mWtJ.js} +1 -1
  45. package/dist/client/assets/{nim-CA8SNY_7.js → nim-Dst6YSnE.js} +1 -1
  46. package/dist/client/assets/{perl-lx5nW4VC.js → perl-XhiCjgBp.js} +1 -1
  47. package/dist/client/assets/{php-DgHiW953.js → php-BcsPLnLU.js} +1 -1
  48. package/dist/client/assets/{pug-CbbB1vwb.js → pug-GLH9-eAJ.js} +1 -1
  49. package/dist/client/assets/{qml-COrzwCIh.js → qml-Cj_lJioE.js} +1 -1
  50. package/dist/client/assets/{r-Dv7pZJDH.js → r-B70aGYK5.js} +1 -1
  51. package/dist/client/assets/{razor-D2m8EDP5.js → razor-R3gub_zy.js} +1 -1
  52. package/dist/client/assets/{regexp-BXLT-jPc.js → regexp-itC0dIUJ.js} +1 -1
  53. package/dist/client/assets/{rst-_S6rrUYh.js → rst-DdyoV8E2.js} +1 -1
  54. package/dist/client/assets/{ruby-C3XO7tYY.js → ruby-BYBZsv66.js} +1 -1
  55. package/dist/client/assets/{sas-DP2k4iuN.js → sas-fqfqXqj1.js} +1 -1
  56. package/dist/client/assets/{scss-lhLFMXGn.js → scss-B-ELv6mu.js} +1 -1
  57. package/dist/client/assets/{shellscript-BYlBPHen.js → shellscript-BgB8TNw6.js} +1 -1
  58. package/dist/client/assets/{shellsession-CbVyQKWZ.js → shellsession-BLK2Dgkm.js} +1 -1
  59. package/dist/client/assets/{soy-Be8a0lHq.js → soy-C7_RmNrp.js} +1 -1
  60. package/dist/client/assets/{sql-2KxvU9YS.js → sql-AUgbUJq4.js} +1 -1
  61. package/dist/client/assets/{stata-BxlWftTS.js → stata-CIVqSIOr.js} +1 -1
  62. package/dist/client/assets/{surrealql-CJ-q86nR.js → surrealql-BzRQzc5S.js} +1 -1
  63. package/dist/client/assets/{svelte-Q1ml0OiY.js → svelte-BCIwEwtb.js} +1 -1
  64. package/dist/client/assets/{templ-BbfPZhtu.js → templ-C1hbwe4u.js} +1 -1
  65. package/dist/client/assets/{tex-Dcth4Gi6.js → tex-CI4tIsaP.js} +1 -1
  66. package/dist/client/assets/{ts-tags-BKhSOXI3.js → ts-tags-SUeikhEp.js} +1 -1
  67. package/dist/client/assets/{tsx-CS6iQ0XH.js → tsx-xkp7aIZs.js} +1 -1
  68. package/dist/client/assets/{twig-BHp31ZxS.js → twig-CGgBSAyc.js} +1 -1
  69. package/dist/client/assets/{typescript-16YJBTaO.js → typescript-O2YMTl_s.js} +1 -1
  70. package/dist/client/assets/{vue-CMKwTi4r.js → vue-DsNRxos1.js} +1 -1
  71. package/dist/client/assets/{vue-html-Dr8VUA2G.js → vue-html-CuY3t7bs.js} +1 -1
  72. package/dist/client/assets/{vue-vine-DZUqDerl.js → vue-vine-C6kSCKwY.js} +1 -1
  73. package/dist/client/assets/{xml-CBbBKKDC.js → xml-DafwzOLY.js} +1 -1
  74. package/dist/client/assets/{xsl-DWEX6PKX.js → xsl-1SGGZibr.js} +1 -1
  75. package/dist/client/assets/{yaml-DvKvvh3X.js → yaml-DSVhzmhr.js} +1 -1
  76. package/dist/client/index.html +2 -2
  77. package/dist/client/sw.js +1 -1
  78. package/dist/server/analytics/engine.js +241 -241
  79. package/dist/server/assets.js +4 -4
  80. package/dist/server/auth/passphrase.js +13 -13
  81. package/dist/server/config.js +7 -7
  82. package/dist/server/daemon.js +93 -93
  83. package/dist/server/features/brainstorm.js +42 -42
  84. package/dist/server/features/ralph-loop.js +33 -33
  85. package/dist/server/features/scheduler.js +53 -53
  86. package/dist/server/features/specs.js +54 -54
  87. package/dist/server/features/sticky-notes.js +17 -17
  88. package/dist/server/features/superpowers.js +24 -24
  89. package/dist/server/handlers/analytics.js +1 -1
  90. package/dist/server/handlers/attachment.js +32 -32
  91. package/dist/server/handlers/bookmarks.js +4 -4
  92. package/dist/server/handlers/brainstorm.js +4 -4
  93. package/dist/server/handlers/chat.js +54 -54
  94. package/dist/server/handlers/editor.js +13 -13
  95. package/dist/server/handlers/fs.js +51 -51
  96. package/dist/server/handlers/hooks.js +20 -20
  97. package/dist/server/handlers/loop.js +6 -6
  98. package/dist/server/handlers/memory.js +44 -44
  99. package/dist/server/handlers/mesh.js +60 -60
  100. package/dist/server/handlers/notes.js +7 -7
  101. package/dist/server/handlers/plugins.js +174 -174
  102. package/dist/server/handlers/project-settings.js +26 -26
  103. package/dist/server/handlers/scheduler.js +6 -6
  104. package/dist/server/handlers/session.js +24 -24
  105. package/dist/server/handlers/settings.js +21 -21
  106. package/dist/server/handlers/skills.js +91 -91
  107. package/dist/server/handlers/specs.js +51 -28
  108. package/dist/server/handlers/terminal.js +13 -13
  109. package/dist/server/handlers/themes.js +21 -21
  110. package/dist/server/handlers/update.js +17 -17
  111. package/dist/server/hooks/event_forward.sh +34 -0
  112. package/dist/server/hooks/post_tool_use.sh +26 -0
  113. package/dist/server/hooks/statusline.sh +26 -0
  114. package/dist/server/identity.js +6 -6
  115. package/dist/server/index.js +111 -111
  116. package/dist/server/logger.js +1 -1
  117. package/dist/server/mesh/connector.js +78 -78
  118. package/dist/server/mesh/crypto.js +20 -20
  119. package/dist/server/mesh/discovery.js +14 -14
  120. package/dist/server/mesh/pairing.js +30 -30
  121. package/dist/server/mesh/peers.js +10 -10
  122. package/dist/server/mesh/proxy.js +14 -14
  123. package/dist/server/mesh/session-sync.js +23 -23
  124. package/dist/server/project/bookmarks.js +11 -11
  125. package/dist/server/project/context-breakdown.js +70 -70
  126. package/dist/server/project/file-browser.js +17 -17
  127. package/dist/server/project/project-files.js +68 -68
  128. package/dist/server/project/registry.js +10 -10
  129. package/dist/server/project/sdk-bridge.js +157 -157
  130. package/dist/server/project/session.js +201 -199
  131. package/dist/server/project/terminal.js +15 -15
  132. package/dist/server/project/warmup.js +37 -37
  133. package/dist/server/push.js +11 -11
  134. package/dist/server/runtime.js +1 -1
  135. package/dist/server/tls.js +15 -15
  136. package/dist/server/tui.js +15 -15
  137. package/dist/server/update-checker.js +21 -21
  138. package/dist/server/ws/broadcast.js +18 -18
  139. package/dist/server/ws/router.js +17 -17
  140. package/dist/shared/constants.js +8 -8
  141. package/package.json +2 -2
  142. package/dist/client/assets/index-DlfI20Gn.css +0 -2
@@ -5,26 +5,26 @@ function getPeersPath() {
5
5
  return join(getLatticeHome(), "peers.json");
6
6
  }
7
7
  export function loadPeers() {
8
- var path = getPeersPath();
8
+ const path = getPeersPath();
9
9
  if (!existsSync(path)) {
10
10
  return [];
11
11
  }
12
- var raw = readFileSync(path, "utf-8");
12
+ const raw = readFileSync(path, "utf-8");
13
13
  return JSON.parse(raw);
14
14
  }
15
15
  export function savePeers(peers) {
16
- var path = getPeersPath();
16
+ const path = getPeersPath();
17
17
  writeFileSync(path, JSON.stringify(peers, null, 2), "utf-8");
18
18
  }
19
19
  export function addPeer(peer) {
20
- var peers = loadPeers();
21
- var idx = peers.findIndex(function (p) { return p.id === peer.id; });
20
+ const peers = loadPeers();
21
+ const idx = peers.findIndex(function (p) { return p.id === peer.id; });
22
22
  if (idx >= 0) {
23
23
  peers[idx] = peer;
24
24
  }
25
25
  else {
26
- var addrSet = new Set(peer.addresses);
27
- var dupeIdx = peers.findIndex(function (p) {
26
+ const addrSet = new Set(peer.addresses);
27
+ const dupeIdx = peers.findIndex(function (p) {
28
28
  return p.addresses.some(function (a) { return addrSet.has(a); });
29
29
  });
30
30
  if (dupeIdx >= 0) {
@@ -37,8 +37,8 @@ export function addPeer(peer) {
37
37
  savePeers(peers);
38
38
  }
39
39
  export function removePeer(nodeId) {
40
- var peers = loadPeers();
41
- var next = peers.filter(function (p) { return p.id !== nodeId; });
40
+ const peers = loadPeers();
41
+ const next = peers.filter(function (p) { return p.id !== nodeId; });
42
42
  if (next.length === peers.length) {
43
43
  return false;
44
44
  }
@@ -46,7 +46,7 @@ export function removePeer(nodeId) {
46
46
  return true;
47
47
  }
48
48
  export function getPeer(nodeId) {
49
- var peers = loadPeers();
49
+ const peers = loadPeers();
50
50
  return peers.find(function (p) { return p.id === nodeId; });
51
51
  }
52
52
  export function isPaired(nodeId) {
@@ -3,19 +3,19 @@ import { getPeerConnection } from "./connector.js";
3
3
  import { sendTo, registerVirtualClient, removeVirtualClient } from "../ws/broadcast.js";
4
4
  import { routeMessage } from "../ws/router.js";
5
5
  import { log } from "../logger.js";
6
- var pendingRequests = new Map();
6
+ const pendingRequests = new Map();
7
7
  export function proxyToRemoteNode(nodeId, projectSlug, clientId, message) {
8
8
  log.meshProxy("→ proxy %s to node %s for project %s", message.type, nodeId.slice(0, 8), projectSlug);
9
- var ws = getPeerConnection(nodeId);
9
+ const ws = getPeerConnection(nodeId);
10
10
  if (!ws) {
11
11
  log.meshProxy(" ✗ no connection to node %s", nodeId.slice(0, 8));
12
12
  sendTo(clientId, { type: "chat:error", message: "Remote node is not connected" });
13
13
  return;
14
14
  }
15
- var requestId = randomUUID();
15
+ const requestId = randomUUID();
16
16
  pendingRequests.set(requestId, clientId);
17
17
  log.meshProxy(" envelope requestId=%s", requestId.slice(0, 8));
18
- var envelope = {
18
+ const envelope = {
19
19
  type: "mesh:proxy_request",
20
20
  projectSlug: projectSlug,
21
21
  requestId: requestId,
@@ -24,17 +24,17 @@ export function proxyToRemoteNode(nodeId, projectSlug, clientId, message) {
24
24
  ws.send(JSON.stringify(envelope));
25
25
  }
26
26
  export function handleProxyRequest(sourceNodeId, msg) {
27
- var proxyClientId = "mesh-proxy:" + sourceNodeId + ":" + msg.requestId;
27
+ const proxyClientId = "mesh-proxy:" + sourceNodeId + ":" + msg.requestId;
28
28
  log.meshProxy("← proxy_request from %s: %s for %s (reqId=%s)", sourceNodeId.slice(0, 8), msg.payload.type, msg.projectSlug, msg.requestId.slice(0, 8));
29
29
  registerVirtualClient(proxyClientId, function (response) {
30
30
  log.meshProxy(" → proxy_response %s back to %s", response.type, sourceNodeId.slice(0, 8));
31
- var ws = getPeerConnection(sourceNodeId);
31
+ const ws = getPeerConnection(sourceNodeId);
32
32
  if (!ws) {
33
33
  console.warn("[mesh/proxy] Cannot send response, no connection to: " + sourceNodeId);
34
34
  removeVirtualClient(proxyClientId);
35
35
  return;
36
36
  }
37
- var envelope = {
37
+ const envelope = {
38
38
  type: "mesh:proxy_response",
39
39
  projectSlug: msg.projectSlug,
40
40
  requestId: msg.requestId,
@@ -47,7 +47,7 @@ export function handleProxyRequest(sourceNodeId, msg) {
47
47
  }
48
48
  export function handleProxyResponse(msg) {
49
49
  log.meshProxy("← proxy_response %s (reqId=%s)", msg.payload.type, msg.requestId.slice(0, 8));
50
- var clientId = pendingRequests.get(msg.requestId);
50
+ const clientId = pendingRequests.get(msg.requestId);
51
51
  if (!clientId) {
52
52
  log.meshProxy(" ✗ no pending request for %s", msg.requestId.slice(0, 8));
53
53
  return;
@@ -55,13 +55,13 @@ export function handleProxyResponse(msg) {
55
55
  pendingRequests.delete(msg.requestId);
56
56
  sendTo(clientId, msg.payload);
57
57
  }
58
- var proxyHandlers = new Map();
58
+ const proxyHandlers = new Map();
59
59
  export function registerProxyAwareHandler(prefix, handler) {
60
60
  proxyHandlers.set(prefix, handler);
61
61
  }
62
62
  function proxyRouteMessage(clientId, message, sendToFn) {
63
- var prefix = message.type.split(":")[0];
64
- var proxyHandler = proxyHandlers.get(prefix);
63
+ const prefix = message.type.split(":")[0];
64
+ const proxyHandler = proxyHandlers.get(prefix);
65
65
  if (proxyHandler) {
66
66
  proxyHandler(clientId, message, sendToFn);
67
67
  return;
@@ -69,15 +69,15 @@ function proxyRouteMessage(clientId, message, sendToFn) {
69
69
  routeMessage(clientId, message);
70
70
  }
71
71
  export function getProxySendTo(requestId, sourceNodeId) {
72
- var clientId = pendingRequests.get(requestId);
72
+ const clientId = pendingRequests.get(requestId);
73
73
  if (clientId !== undefined) {
74
- var resolvedClientId = clientId;
74
+ const resolvedClientId = clientId;
75
75
  return function (msg) {
76
76
  sendTo(resolvedClientId, msg);
77
77
  };
78
78
  }
79
79
  return function (msg) {
80
- var ws = getPeerConnection(sourceNodeId);
80
+ const ws = getPeerConnection(sourceNodeId);
81
81
  if (!ws) {
82
82
  return;
83
83
  }
@@ -3,45 +3,45 @@ import { join } from "node:path";
3
3
  import { homedir } from "node:os";
4
4
  import { getConnectedPeerIds, getPeerConnection } from "./connector.js";
5
5
  import { getLatticeHome } from "../config.js";
6
- var syncOffsets = new Map();
6
+ const syncOffsets = new Map();
7
7
  function getSyncKey(nodeId, sessionId) {
8
8
  return nodeId + ":" + sessionId;
9
9
  }
10
10
  function getRemoteSessionsDir(nodeId, projectSlug) {
11
- var dir = join(getLatticeHome(), "remote-sessions", nodeId, projectSlug);
11
+ const dir = join(getLatticeHome(), "remote-sessions", nodeId, projectSlug);
12
12
  if (!existsSync(dir)) {
13
13
  mkdirSync(dir, { recursive: true });
14
14
  }
15
15
  return dir;
16
16
  }
17
17
  function getSessionFilePath(projectPath, sessionId) {
18
- var hash = projectPath.replace(/\//g, "-");
18
+ const hash = projectPath.replace(/\//g, "-");
19
19
  return join(homedir(), ".claude", "projects", hash, sessionId + ".jsonl");
20
20
  }
21
21
  export function syncSessionToPeers(projectPath, projectSlug, sessionId) {
22
- var filePath = getSessionFilePath(projectPath, sessionId);
22
+ const filePath = getSessionFilePath(projectPath, sessionId);
23
23
  if (!existsSync(filePath)) {
24
24
  return;
25
25
  }
26
- var content = readFileSync(filePath, "utf-8");
27
- var peerIds = getConnectedPeerIds();
28
- for (var i = 0; i < peerIds.length; i++) {
29
- var nodeId = peerIds[i];
30
- var key = getSyncKey(nodeId, sessionId);
31
- var lastOffset = syncOffsets.get(key) || 0;
26
+ const content = readFileSync(filePath, "utf-8");
27
+ const peerIds = getConnectedPeerIds();
28
+ for (let i = 0; i < peerIds.length; i++) {
29
+ const nodeId = peerIds[i];
30
+ const key = getSyncKey(nodeId, sessionId);
31
+ const lastOffset = syncOffsets.get(key) || 0;
32
32
  if (content.length <= lastOffset) {
33
33
  continue;
34
34
  }
35
- var newContent = content.slice(lastOffset);
36
- var newLines = newContent.split("\n").filter(function (l) { return l.trim().length > 0; });
35
+ const newContent = content.slice(lastOffset);
36
+ const newLines = newContent.split("\n").filter(function (l) { return l.trim().length > 0; });
37
37
  if (newLines.length === 0) {
38
38
  continue;
39
39
  }
40
- var ws = getPeerConnection(nodeId);
40
+ const ws = getPeerConnection(nodeId);
41
41
  if (!ws) {
42
42
  continue;
43
43
  }
44
- var msg = {
44
+ const msg = {
45
45
  type: "mesh:session_sync",
46
46
  projectSlug,
47
47
  sessionId,
@@ -53,28 +53,28 @@ export function syncSessionToPeers(projectPath, projectSlug, sessionId) {
53
53
  }
54
54
  }
55
55
  export function handleSessionSync(nodeId, msg) {
56
- var dir = getRemoteSessionsDir(nodeId, msg.projectSlug);
57
- var filePath = join(dir, msg.sessionId + ".jsonl");
58
- for (var i = 0; i < msg.lines.length; i++) {
56
+ const dir = getRemoteSessionsDir(nodeId, msg.projectSlug);
57
+ const filePath = join(dir, msg.sessionId + ".jsonl");
58
+ for (let i = 0; i < msg.lines.length; i++) {
59
59
  appendFileSync(filePath, msg.lines[i] + "\n", "utf-8");
60
60
  }
61
61
  }
62
62
  export function handleSessionRequest(nodeId, msg, projectPath) {
63
- var filePath = getSessionFilePath(projectPath, msg.sessionId);
63
+ const filePath = getSessionFilePath(projectPath, msg.sessionId);
64
64
  if (!existsSync(filePath)) {
65
65
  return;
66
66
  }
67
- var content = readFileSync(filePath, "utf-8");
68
- var newContent = content.slice(msg.fromOffset);
69
- var lines = newContent.split("\n").filter(function (l) { return l.trim().length > 0; });
67
+ const content = readFileSync(filePath, "utf-8");
68
+ const newContent = content.slice(msg.fromOffset);
69
+ const lines = newContent.split("\n").filter(function (l) { return l.trim().length > 0; });
70
70
  if (lines.length === 0) {
71
71
  return;
72
72
  }
73
- var ws = getPeerConnection(nodeId);
73
+ const ws = getPeerConnection(nodeId);
74
74
  if (!ws) {
75
75
  return;
76
76
  }
77
- var syncMsg = {
77
+ const syncMsg = {
78
78
  type: "mesh:session_sync",
79
79
  projectSlug: msg.projectSlug,
80
80
  sessionId: msg.sessionId,
@@ -2,8 +2,8 @@ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "
2
2
  import { join } from "node:path";
3
3
  import { randomBytes } from "node:crypto";
4
4
  import { getLatticeHome } from "../config.js";
5
- var bookmarksFile = "";
6
- var bookmarks = [];
5
+ let bookmarksFile = "";
6
+ let bookmarks = [];
7
7
  function getBookmarksPath() {
8
8
  if (!bookmarksFile) {
9
9
  bookmarksFile = join(getLatticeHome(), "bookmarks.json");
@@ -11,13 +11,13 @@ function getBookmarksPath() {
11
11
  return bookmarksFile;
12
12
  }
13
13
  export function loadBookmarks() {
14
- var path = getBookmarksPath();
14
+ const path = getBookmarksPath();
15
15
  if (!existsSync(path)) {
16
16
  bookmarks = [];
17
17
  return;
18
18
  }
19
19
  try {
20
- var raw = readFileSync(path, "utf-8");
20
+ const raw = readFileSync(path, "utf-8");
21
21
  bookmarks = JSON.parse(raw);
22
22
  }
23
23
  catch (err) {
@@ -26,12 +26,12 @@ export function loadBookmarks() {
26
26
  }
27
27
  }
28
28
  function saveBookmarks() {
29
- var path = getBookmarksPath();
30
- var dir = join(path, "..");
29
+ const path = getBookmarksPath();
30
+ const dir = join(path, "..");
31
31
  if (!existsSync(dir)) {
32
32
  mkdirSync(dir, { recursive: true });
33
33
  }
34
- var tmp = path + ".tmp";
34
+ const tmp = path + ".tmp";
35
35
  try {
36
36
  writeFileSync(tmp, JSON.stringify(bookmarks, null, 2));
37
37
  renameSync(tmp, path);
@@ -41,7 +41,7 @@ function saveBookmarks() {
41
41
  }
42
42
  }
43
43
  export function listBookmarks(projectSlug, sessionId) {
44
- var result = bookmarks;
44
+ let result = bookmarks;
45
45
  if (projectSlug) {
46
46
  result = result.filter(function (b) { return b.projectSlug === projectSlug; });
47
47
  }
@@ -51,8 +51,8 @@ export function listBookmarks(projectSlug, sessionId) {
51
51
  return result.slice();
52
52
  }
53
53
  export function addBookmark(bookmark) {
54
- var now = Date.now();
55
- var entry = {
54
+ const now = Date.now();
55
+ const entry = {
56
56
  id: "bm_" + now + "_" + randomBytes(3).toString("hex"),
57
57
  sessionId: bookmark.sessionId,
58
58
  projectSlug: bookmark.projectSlug,
@@ -66,7 +66,7 @@ export function addBookmark(bookmark) {
66
66
  return entry;
67
67
  }
68
68
  export function removeBookmark(id) {
69
- for (var i = 0; i < bookmarks.length; i++) {
69
+ for (let i = 0; i < bookmarks.length; i++) {
70
70
  if (bookmarks[i].id === id) {
71
71
  bookmarks.splice(i, 1);
72
72
  saveBookmarks();
@@ -5,7 +5,7 @@ import { homedir } from "node:os";
5
5
  import { guessContextWindow } from "./session.js";
6
6
  import { loadConfig } from "../config.js";
7
7
  import { getInstalledPluginCount, getPluginSkillRuleTokenEstimate } from "../handlers/plugins.js";
8
- var encoder = encodingForModel("gpt-4o");
8
+ const encoder = encodingForModel("gpt-4o");
9
9
  function countTokens(text) {
10
10
  if (!text)
11
11
  return 0;
@@ -23,9 +23,9 @@ function readDirFiles(dirPath) {
23
23
  try {
24
24
  if (!existsSync(dirPath))
25
25
  return "";
26
- var files = readdirSync(dirPath, { withFileTypes: true });
27
- var content = "";
28
- for (var i = 0; i < files.length; i++) {
26
+ const files = readdirSync(dirPath, { withFileTypes: true });
27
+ let content = "";
28
+ for (let i = 0; i < files.length; i++) {
29
29
  if (files[i].isFile()) {
30
30
  content += readFileSafe(join(dirPath, files[i].name)) + "\n";
31
31
  }
@@ -39,13 +39,13 @@ function projectPathToHash(projectPath) {
39
39
  return projectPath.replace(/\//g, "-");
40
40
  }
41
41
  function getProjectPath(projectSlug) {
42
- var config = loadConfig();
43
- var project = config.projects.find(function (p) { return p.slug === projectSlug; });
42
+ const config = loadConfig();
43
+ const project = config.projects.find(function (p) { return p.slug === projectSlug; });
44
44
  return project ? project.path : null;
45
45
  }
46
46
  // Known built-in Claude Code tools with approximate per-tool token counts
47
47
  // These are the tool definitions sent in every API request
48
- var BUILTIN_TOOLS = {
48
+ const BUILTIN_TOOLS = {
49
49
  "Read": 350,
50
50
  "Write": 300,
51
51
  "Edit": 400,
@@ -71,20 +71,20 @@ var BUILTIN_TOOLS = {
71
71
  "ToolSearch": 250,
72
72
  };
73
73
  // Average tokens per MCP tool definition (name + description + JSON schema)
74
- var MCP_TOOL_AVG_TOKENS = 250;
74
+ const MCP_TOOL_AVG_TOKENS = 250;
75
75
  function extractToolsFromSession(lines) {
76
- var builtinSet = new Set();
77
- var mcpMap = new Map();
76
+ const builtinSet = new Set();
77
+ const mcpMap = new Map();
78
78
  // First: check compact boundary metadata for preCompactDiscoveredTools
79
- for (var i = 0; i < lines.length; i++) {
80
- var line = lines[i].trim();
79
+ for (let i = 0; i < lines.length; i++) {
80
+ const line = lines[i].trim();
81
81
  if (!line || !line.includes("compactMetadata"))
82
82
  continue;
83
83
  try {
84
- var parsed = JSON.parse(line);
85
- var tools = parsed.compactMetadata?.preCompactDiscoveredTools;
84
+ const parsed = JSON.parse(line);
85
+ const tools = parsed.compactMetadata?.preCompactDiscoveredTools;
86
86
  if (Array.isArray(tools)) {
87
- for (var t = 0; t < tools.length; t++) {
87
+ for (let t = 0; t < tools.length; t++) {
88
88
  categorizeToolName(tools[t], builtinSet, mcpMap);
89
89
  }
90
90
  }
@@ -92,15 +92,15 @@ function extractToolsFromSession(lines) {
92
92
  catch { }
93
93
  }
94
94
  // Second: scan tool_use blocks from assistant messages for any we missed
95
- for (var j = 0; j < lines.length; j++) {
96
- var aLine = lines[j].trim();
95
+ for (let j = 0; j < lines.length; j++) {
96
+ const aLine = lines[j].trim();
97
97
  if (!aLine || !aLine.includes("tool_use"))
98
98
  continue;
99
99
  try {
100
- var aParsed = JSON.parse(aLine);
100
+ const aParsed = JSON.parse(aLine);
101
101
  if (aParsed.type === "assistant" && aParsed.message && Array.isArray(aParsed.message.content)) {
102
- for (var k = 0; k < aParsed.message.content.length; k++) {
103
- var block = aParsed.message.content[k];
102
+ for (let k = 0; k < aParsed.message.content.length; k++) {
103
+ const block = aParsed.message.content[k];
104
104
  if (block.type === "tool_use" && block.name) {
105
105
  categorizeToolName(block.name, builtinSet, mcpMap);
106
106
  }
@@ -125,8 +125,8 @@ function extractToolsFromSession(lines) {
125
125
  }
126
126
  function categorizeToolName(name, builtinSet, mcpMap) {
127
127
  if (name.startsWith("mcp__")) {
128
- var parts = name.split("__");
129
- var serverName = parts[1] || "unknown";
128
+ const parts = name.split("__");
129
+ const serverName = parts[1] || "unknown";
130
130
  if (!mcpMap.has(serverName)) {
131
131
  mcpMap.set(serverName, new Set());
132
132
  }
@@ -137,13 +137,13 @@ function categorizeToolName(name, builtinSet, mcpMap) {
137
137
  }
138
138
  }
139
139
  function estimateBuiltinToolTokens(toolNames) {
140
- var total = 0;
141
- for (var i = 0; i < toolNames.length; i++) {
140
+ let total = 0;
141
+ for (let i = 0; i < toolNames.length; i++) {
142
142
  total += BUILTIN_TOOLS[toolNames[i]] || 300;
143
143
  }
144
144
  // Also include tools that are always sent but might not appear in usage
145
- var knownKeys = Object.keys(BUILTIN_TOOLS);
146
- for (var j = 0; j < knownKeys.length; j++) {
145
+ const knownKeys = Object.keys(BUILTIN_TOOLS);
146
+ for (let j = 0; j < knownKeys.length; j++) {
147
147
  if (toolNames.indexOf(knownKeys[j]) === -1) {
148
148
  total += BUILTIN_TOOLS[knownKeys[j]];
149
149
  }
@@ -151,55 +151,55 @@ function estimateBuiltinToolTokens(toolNames) {
151
151
  return total;
152
152
  }
153
153
  export async function getContextBreakdown(projectSlug, sessionId) {
154
- var projectPath = getProjectPath(projectSlug);
154
+ const projectPath = getProjectPath(projectSlug);
155
155
  if (!projectPath)
156
156
  return null;
157
- var home = homedir();
158
- var hash = projectPathToHash(projectPath);
159
- var sessionFile = join(home, ".claude", "projects", hash, sessionId + ".jsonl");
157
+ const home = homedir();
158
+ const hash = projectPathToHash(projectPath);
159
+ const sessionFile = join(home, ".claude", "projects", hash, sessionId + ".jsonl");
160
160
  if (!existsSync(sessionFile))
161
161
  return null;
162
162
  // Read instruction files
163
- var globalClaudeMd = readFileSafe(join(home, ".claude", "CLAUDE.md"));
164
- var globalRulesContent = readDirFiles(join(home, ".claude", "rules"));
165
- var projectClaudeMd = readFileSafe(join(projectPath, "CLAUDE.md"));
166
- var projectLocalClaudeMd = readFileSafe(join(home, ".claude", "projects", hash, "CLAUDE.md"));
167
- var memoryContent = readDirFiles(join(home, ".claude", "projects", hash, "memory"));
168
- var memoryIndex = readFileSafe(join(home, ".claude", "projects", hash, "MEMORY.md"));
169
- var instructionsTokens = countTokens(globalClaudeMd + globalRulesContent + projectClaudeMd + projectLocalClaudeMd);
170
- var memoryTokens = countTokens(memoryContent + memoryIndex);
163
+ const globalClaudeMd = readFileSafe(join(home, ".claude", "CLAUDE.md"));
164
+ const globalRulesContent = readDirFiles(join(home, ".claude", "rules"));
165
+ const projectClaudeMd = readFileSafe(join(projectPath, "CLAUDE.md"));
166
+ const projectLocalClaudeMd = readFileSafe(join(home, ".claude", "projects", hash, "CLAUDE.md"));
167
+ const memoryContent = readDirFiles(join(home, ".claude", "projects", hash, "memory"));
168
+ const memoryIndex = readFileSafe(join(home, ".claude", "projects", hash, "MEMORY.md"));
169
+ const instructionsTokens = countTokens(globalClaudeMd + globalRulesContent + projectClaudeMd + projectLocalClaudeMd);
170
+ const memoryTokens = countTokens(memoryContent + memoryIndex);
171
171
  // Parse session — read last 2MB for recent context (avoids reading 35MB+ files)
172
- var fd = openSync(sessionFile, "r");
173
- var fileStat = fstatSync(fd);
174
- var readSize = Math.min(fileStat.size, 2 * 1024 * 1024);
175
- var readBuf = Buffer.alloc(readSize);
172
+ const fd = openSync(sessionFile, "r");
173
+ const fileStat = fstatSync(fd);
174
+ const readSize = Math.min(fileStat.size, 2 * 1024 * 1024);
175
+ const readBuf = Buffer.alloc(readSize);
176
176
  readSync(fd, readBuf, 0, readSize, fileStat.size - readSize);
177
177
  closeSync(fd);
178
- var content = readBuf.toString("utf-8");
179
- var lines = content.split("\n").filter(function (l) { return l.length > 0; });
178
+ const content = readBuf.toString("utf-8");
179
+ const lines = content.split("\n").filter(function (l) { return l.length > 0; });
180
180
  // Extract tool info
181
- var toolCounts = extractToolsFromSession(lines);
182
- var builtinToolTokens = estimateBuiltinToolTokens(toolCounts.builtinTools);
181
+ const toolCounts = extractToolsFromSession(lines);
182
+ const builtinToolTokens = estimateBuiltinToolTokens(toolCounts.builtinTools);
183
183
  // Parse conversation messages
184
- var userText = "";
185
- var assistantText = "";
186
- var toolResultText = "";
187
- var contextWindow = 0;
188
- var lastModel = "";
189
- for (var i = 0; i < lines.length; i++) {
190
- var line = lines[i].trim();
184
+ let userText = "";
185
+ let assistantText = "";
186
+ let toolResultText = "";
187
+ let contextWindow = 0;
188
+ let lastModel = "";
189
+ for (let i = 0; i < lines.length; i++) {
190
+ const line = lines[i].trim();
191
191
  if (!line)
192
192
  continue;
193
193
  try {
194
- var parsed = JSON.parse(line);
194
+ const parsed = JSON.parse(line);
195
195
  if (parsed.type === "user" && parsed.message) {
196
- var userContent = parsed.message.content;
196
+ const userContent = parsed.message.content;
197
197
  if (typeof userContent === "string") {
198
198
  userText += userContent + "\n";
199
199
  }
200
200
  else if (Array.isArray(userContent)) {
201
- for (var j = 0; j < userContent.length; j++) {
202
- var block = userContent[j];
201
+ for (let j = 0; j < userContent.length; j++) {
202
+ const block = userContent[j];
203
203
  if (block.type === "text" && block.text) {
204
204
  userText += block.text + "\n";
205
205
  }
@@ -208,7 +208,7 @@ export async function getContextBreakdown(projectSlug, sessionId) {
208
208
  toolResultText += block.content + "\n";
209
209
  }
210
210
  else if (Array.isArray(block.content)) {
211
- for (var ri = 0; ri < block.content.length; ri++) {
211
+ for (let ri = 0; ri < block.content.length; ri++) {
212
212
  if (block.content[ri].type === "text" && block.content[ri].text) {
213
213
  toolResultText += block.content[ri].text + "\n";
214
214
  }
@@ -219,13 +219,13 @@ export async function getContextBreakdown(projectSlug, sessionId) {
219
219
  }
220
220
  }
221
221
  else if (parsed.type === "assistant" && parsed.message) {
222
- var aContent = parsed.message.content;
222
+ const aContent = parsed.message.content;
223
223
  if (typeof aContent === "string") {
224
224
  assistantText += aContent + "\n";
225
225
  }
226
226
  else if (Array.isArray(aContent)) {
227
- for (var k = 0; k < aContent.length; k++) {
228
- var ab = aContent[k];
227
+ for (let k = 0; k < aContent.length; k++) {
228
+ const ab = aContent[k];
229
229
  if (ab.type === "text" && ab.text) {
230
230
  assistantText += ab.text + "\n";
231
231
  }
@@ -244,19 +244,19 @@ export async function getContextBreakdown(projectSlug, sessionId) {
244
244
  }
245
245
  catch { }
246
246
  }
247
- var userTokens = countTokens(userText);
248
- var assistantTokens = countTokens(assistantText);
249
- var toolResultTokens = countTokens(toolResultText);
247
+ const userTokens = countTokens(userText);
248
+ const assistantTokens = countTokens(assistantText);
249
+ const toolResultTokens = countTokens(toolResultText);
250
250
  contextWindow = guessContextWindow(lastModel);
251
- var autocompactAt = Math.round(contextWindow * 0.9);
252
- var systemPromptEstimate = 4500;
253
- var segments = [
251
+ const autocompactAt = Math.round(contextWindow * 0.9);
252
+ const systemPromptEstimate = 4500;
253
+ const segments = [
254
254
  { label: "System prompt", tokens: systemPromptEstimate, id: "system", estimated: true },
255
255
  { label: "Built-in tools (" + Object.keys(BUILTIN_TOOLS).length + ")", tokens: builtinToolTokens, id: "builtin_tools", estimated: true },
256
256
  ];
257
257
  // Add per-MCP-server segments
258
258
  toolCounts.mcpTools.forEach(function (tools, serverName) {
259
- var mcpTokens = tools.length * MCP_TOOL_AVG_TOKENS;
259
+ const mcpTokens = tools.length * MCP_TOOL_AVG_TOKENS;
260
260
  segments.push({
261
261
  label: serverName + " (" + tools.length + " tools)",
262
262
  tokens: mcpTokens,
@@ -264,9 +264,9 @@ export async function getContextBreakdown(projectSlug, sessionId) {
264
264
  estimated: true,
265
265
  });
266
266
  });
267
- var pluginCount = getInstalledPluginCount();
267
+ const pluginCount = getInstalledPluginCount();
268
268
  if (pluginCount > 0) {
269
- var pluginTokens = getPluginSkillRuleTokenEstimate();
269
+ const pluginTokens = getPluginSkillRuleTokenEstimate();
270
270
  segments.push({
271
271
  label: "Plugins (" + pluginCount + ")",
272
272
  tokens: pluginTokens,