@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
@@ -4,13 +4,13 @@ import { broadcast } from "../ws/broadcast.js";
4
4
  import { loadConfig } from "../config.js";
5
5
  import { log } from "../logger.js";
6
6
  import { upsertFromSnapshot, addToolEventToHistory, markSessionEnded } from "../features/session-history.js";
7
- var sessionProjectMap = new Map();
7
+ const sessionProjectMap = new Map();
8
8
  function matchCwdToProject(cwd) {
9
- var config = loadConfig();
10
- var resolved = resolve(cwd);
11
- for (var i = 0; i < config.projects.length; i++) {
12
- var p = config.projects[i];
13
- var projectPath = resolve(p.path);
9
+ const config = loadConfig();
10
+ const resolved = resolve(cwd);
11
+ for (let i = 0; i < config.projects.length; i++) {
12
+ const p = config.projects[i];
13
+ const projectPath = resolve(p.path);
14
14
  if (resolved === projectPath || resolved.startsWith(projectPath + "/")) {
15
15
  return { projectName: p.title, projectSlug: p.slug };
16
16
  }
@@ -57,7 +57,7 @@ export function handleHookStatusline(req, res) {
57
57
  cacheReadTokens,
58
58
  cacheCreationTokens,
59
59
  }, contextWindow);
60
- var statusProject = sessionProjectMap.get(body.session_id) || null;
60
+ const statusProject = sessionProjectMap.get(body.session_id) || null;
61
61
  broadcast({
62
62
  type: "context:statusline",
63
63
  hookSessionId: body.session_id,
@@ -157,7 +157,7 @@ export function handleHookEvent(req, res) {
157
157
  function estimateTokens(value) {
158
158
  if (value == null)
159
159
  return 0;
160
- var text = typeof value === "string" ? value : JSON.stringify(value);
160
+ const text = typeof value === "string" ? value : JSON.stringify(value);
161
161
  return Math.ceil(text.length / 4);
162
162
  }
163
163
  function summarizeInput(toolName, input) {
@@ -166,7 +166,7 @@ function summarizeInput(toolName, input) {
166
166
  if (typeof input === "string")
167
167
  return input.slice(0, 120);
168
168
  if (typeof input === "object") {
169
- var obj = input;
169
+ const obj = input;
170
170
  if (obj.command)
171
171
  return String(obj.command).slice(0, 120);
172
172
  if (obj.file_path)
@@ -177,32 +177,32 @@ function summarizeInput(toolName, input) {
177
177
  return String(obj.query).slice(0, 120);
178
178
  if (obj.prompt)
179
179
  return String(obj.prompt).slice(0, 120);
180
- var keys = Object.keys(obj);
180
+ const keys = Object.keys(obj);
181
181
  if (keys.length > 0)
182
182
  return keys.slice(0, 3).join(", ");
183
183
  }
184
184
  return "";
185
185
  }
186
186
  export function handleHookToolUse(req, res) {
187
- var body = req.body;
187
+ const body = req.body;
188
188
  if (!body.session_id) {
189
189
  res.status(400).json({ status: "error", message: "missing session_id" });
190
190
  return;
191
191
  }
192
- var toolName = body.tool_name || "unknown";
193
- var inputSummary = summarizeInput(toolName, body.tool_input);
194
- var estInput = estimateTokens(body.tool_input);
195
- var estOutput = estimateTokens(body.tool_response);
196
- var now = Date.now();
192
+ const toolName = body.tool_name || "unknown";
193
+ const inputSummary = summarizeInput(toolName, body.tool_input);
194
+ const estInput = estimateTokens(body.tool_input);
195
+ const estOutput = estimateTokens(body.tool_response);
196
+ const now = Date.now();
197
197
  if (body.cwd && !sessionProjectMap.has(body.session_id)) {
198
- var match = matchCwdToProject(body.cwd);
198
+ const match = matchCwdToProject(body.cwd);
199
199
  if (match) {
200
200
  sessionProjectMap.set(body.session_id, match);
201
201
  }
202
202
  }
203
- var sessionProject = sessionProjectMap.get(body.session_id) || null;
204
- var analyzer = getOrCreateAnalyzer(body.session_id);
205
- var toolId = body.session_id + "-" + now;
203
+ const sessionProject = sessionProjectMap.get(body.session_id) || null;
204
+ const analyzer = getOrCreateAnalyzer(body.session_id);
205
+ const toolId = body.session_id + "-" + now;
206
206
  analyzer.onToolStart(toolId, toolName);
207
207
  analyzer.onToolResult(toolId);
208
208
  broadcast({
@@ -3,8 +3,8 @@ import { sendTo } from "../ws/broadcast.js";
3
3
  import { startLoop, stopLoop, getLoopStatus } from "../features/ralph-loop.js";
4
4
  registerHandler("loop", function (clientId, message) {
5
5
  if (message.type === "loop:start") {
6
- var startMsg = message;
7
- var loop = startLoop(startMsg.projectSlug);
6
+ const startMsg = message;
7
+ const loop = startLoop(startMsg.projectSlug);
8
8
  if (!loop) {
9
9
  sendTo(clientId, { type: "chat:error", message: "No PROMPT.md found in .claude/loops/ for this project" });
10
10
  return;
@@ -13,16 +13,16 @@ registerHandler("loop", function (clientId, message) {
13
13
  return;
14
14
  }
15
15
  if (message.type === "loop:stop") {
16
- var stopMsg = message;
17
- var stopped = stopLoop(stopMsg.loopId);
16
+ const stopMsg = message;
17
+ const stopped = stopLoop(stopMsg.loopId);
18
18
  if (!stopped) {
19
19
  sendTo(clientId, { type: "chat:error", message: "Loop not found or not running" });
20
20
  }
21
21
  return;
22
22
  }
23
23
  if (message.type === "loop:status") {
24
- var statusMsg = message;
25
- var status = getLoopStatus(statusMsg.loopId);
24
+ const statusMsg = message;
25
+ const status = getLoopStatus(statusMsg.loopId);
26
26
  if (!status) {
27
27
  sendTo(clientId, { type: "chat:error", message: "Loop not found" });
28
28
  return;
@@ -9,31 +9,31 @@ function getMemoryDir(projectSlug) {
9
9
  if (projectSlug === "__global__") {
10
10
  return join(homedir(), ".claude", "memory");
11
11
  }
12
- var config = loadConfig();
13
- var project = config.projects.find(function (p) { return p.slug === projectSlug; });
12
+ const config = loadConfig();
13
+ const project = config.projects.find(function (p) { return p.slug === projectSlug; });
14
14
  if (!project)
15
15
  return null;
16
- var hash = "-" + project.path.replace(/\//g, "-").replace(/^-/, "");
16
+ const hash = "-" + project.path.replace(/\//g, "-").replace(/^-/, "");
17
17
  return join(homedir(), ".claude", "projects", hash, "memory");
18
18
  }
19
19
  function parseFrontmatter(content) {
20
- var match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
20
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
21
21
  if (!match)
22
22
  return { name: "", description: "", type: "" };
23
- var yaml = match[1];
24
- var name = "";
25
- var description = "";
26
- var type = "";
27
- var lines = yaml.split(/\r?\n/);
28
- for (var i = 0; i < lines.length; i++) {
29
- var line = lines[i];
30
- var nameMatch = line.match(/^name:\s*(.+)/);
23
+ const yaml = match[1];
24
+ let name = "";
25
+ let description = "";
26
+ let type = "";
27
+ const lines = yaml.split(/\r?\n/);
28
+ for (let i = 0; i < lines.length; i++) {
29
+ const line = lines[i];
30
+ const nameMatch = line.match(/^name:\s*(.+)/);
31
31
  if (nameMatch)
32
32
  name = nameMatch[1].trim().replace(/^["']|["']$/g, "");
33
- var descMatch = line.match(/^description:\s*(.+)/);
33
+ const descMatch = line.match(/^description:\s*(.+)/);
34
34
  if (descMatch)
35
35
  description = descMatch[1].trim().replace(/^["']|["']$/g, "");
36
- var typeMatch = line.match(/^type:\s*(.+)/);
36
+ const typeMatch = line.match(/^type:\s*(.+)/);
37
37
  if (typeMatch)
38
38
  type = typeMatch[1].trim().replace(/^["']|["']$/g, "");
39
39
  }
@@ -42,28 +42,28 @@ function parseFrontmatter(content) {
42
42
  async function regenerateIndex(memoryDir) {
43
43
  if (!existsSync(memoryDir))
44
44
  return;
45
- var files = (await readdir(memoryDir)).filter(function (f) {
45
+ const files = (await readdir(memoryDir)).filter(function (f) {
46
46
  return f.endsWith(".md") && f !== "MEMORY.md";
47
47
  });
48
- var grouped = {};
49
- for (var i = 0; i < files.length; i++) {
48
+ const grouped = {};
49
+ for (let i = 0; i < files.length; i++) {
50
50
  try {
51
- var content = await readFile(join(memoryDir, files[i]), "utf-8");
52
- var meta = parseFrontmatter(content);
53
- var type = meta.type || "other";
51
+ const content = await readFile(join(memoryDir, files[i]), "utf-8");
52
+ const meta = parseFrontmatter(content);
53
+ const type = meta.type || "other";
54
54
  if (!grouped[type])
55
55
  grouped[type] = [];
56
56
  grouped[type].push({ filename: files[i], name: meta.name || files[i], description: meta.description || "" });
57
57
  }
58
58
  catch { }
59
59
  }
60
- var lines = ["# Memory Index", ""];
61
- var types = Object.keys(grouped).sort();
62
- for (var t = 0; t < types.length; t++) {
60
+ const lines = ["# Memory Index", ""];
61
+ const types = Object.keys(grouped).sort();
62
+ for (let t = 0; t < types.length; t++) {
63
63
  lines.push("## " + types[t].charAt(0).toUpperCase() + types[t].slice(1));
64
- var entries = grouped[types[t]];
65
- for (var e = 0; e < entries.length; e++) {
66
- var desc = entries[e].description ? " — " + entries[e].description : "";
64
+ const entries = grouped[types[t]];
65
+ for (let e = 0; e < entries.length; e++) {
66
+ const desc = entries[e].description ? " — " + entries[e].description : "";
67
67
  lines.push("- [" + entries[e].filename + "](" + entries[e].filename + ")" + desc);
68
68
  }
69
69
  lines.push("");
@@ -71,14 +71,14 @@ async function regenerateIndex(memoryDir) {
71
71
  await writeFile(join(memoryDir, "MEMORY.md"), lines.join("\n"), "utf-8");
72
72
  }
73
73
  async function listMemoryFiles(memDir) {
74
- var files = (await readdir(memDir)).filter(function (f) {
74
+ const files = (await readdir(memDir)).filter(function (f) {
75
75
  return f.endsWith(".md") && f !== "MEMORY.md";
76
76
  });
77
- var memories = [];
78
- for (var i = 0; i < files.length; i++) {
77
+ const memories = [];
78
+ for (let i = 0; i < files.length; i++) {
79
79
  try {
80
- var content = await readFile(join(memDir, files[i]), "utf-8");
81
- var meta = parseFrontmatter(content);
80
+ const content = await readFile(join(memDir, files[i]), "utf-8");
81
+ const meta = parseFrontmatter(content);
82
82
  memories.push({
83
83
  filename: files[i],
84
84
  name: meta.name || files[i].replace(/\.md$/, ""),
@@ -93,25 +93,25 @@ async function listMemoryFiles(memDir) {
93
93
  }
94
94
  registerHandler("memory", async function (clientId, message) {
95
95
  if (message.type === "memory:list") {
96
- var listMsg = message;
97
- var memDir = getMemoryDir(listMsg.projectSlug);
96
+ const listMsg = message;
97
+ const memDir = getMemoryDir(listMsg.projectSlug);
98
98
  if (!memDir || !existsSync(memDir)) {
99
99
  sendTo(clientId, { type: "memory:list_result", projectSlug: listMsg.projectSlug, memories: [] });
100
100
  return;
101
101
  }
102
- var memories = await listMemoryFiles(memDir);
102
+ const memories = await listMemoryFiles(memDir);
103
103
  sendTo(clientId, { type: "memory:list_result", projectSlug: listMsg.projectSlug, memories: memories });
104
104
  return;
105
105
  }
106
106
  if (message.type === "memory:view") {
107
- var viewMsg = message;
108
- var viewDir = getMemoryDir(viewMsg.projectSlug);
107
+ const viewMsg = message;
108
+ const viewDir = getMemoryDir(viewMsg.projectSlug);
109
109
  if (!viewDir) {
110
110
  sendTo(clientId, { type: "memory:view_result", filename: viewMsg.filename, content: "Project not found." });
111
111
  return;
112
112
  }
113
113
  try {
114
- var viewContent = await readFile(join(viewDir, viewMsg.filename), "utf-8");
114
+ const viewContent = await readFile(join(viewDir, viewMsg.filename), "utf-8");
115
115
  sendTo(clientId, { type: "memory:view_result", filename: viewMsg.filename, content: viewContent });
116
116
  }
117
117
  catch {
@@ -120,8 +120,8 @@ registerHandler("memory", async function (clientId, message) {
120
120
  return;
121
121
  }
122
122
  if (message.type === "memory:save") {
123
- var saveMsg = message;
124
- var saveDir = getMemoryDir(saveMsg.projectSlug);
123
+ const saveMsg = message;
124
+ const saveDir = getMemoryDir(saveMsg.projectSlug);
125
125
  if (!saveDir) {
126
126
  sendTo(clientId, { type: "memory:save_result", success: false, message: "Project not found." });
127
127
  return;
@@ -131,7 +131,7 @@ registerHandler("memory", async function (clientId, message) {
131
131
  await writeFile(join(saveDir, saveMsg.filename), saveMsg.content, "utf-8");
132
132
  await regenerateIndex(saveDir);
133
133
  sendTo(clientId, { type: "memory:save_result", success: true });
134
- var updatedMemories = await listMemoryFiles(saveDir);
134
+ const updatedMemories = await listMemoryFiles(saveDir);
135
135
  sendTo(clientId, { type: "memory:list_result", projectSlug: saveMsg.projectSlug, memories: updatedMemories });
136
136
  }
137
137
  catch (err) {
@@ -140,14 +140,14 @@ registerHandler("memory", async function (clientId, message) {
140
140
  return;
141
141
  }
142
142
  if (message.type === "memory:delete") {
143
- var delMsg = message;
144
- var delDir = getMemoryDir(delMsg.projectSlug);
143
+ const delMsg = message;
144
+ const delDir = getMemoryDir(delMsg.projectSlug);
145
145
  if (!delDir) {
146
146
  sendTo(clientId, { type: "memory:delete_result", success: false, message: "Project not found." });
147
147
  return;
148
148
  }
149
149
  try {
150
- var filePath = join(delDir, delMsg.filename);
150
+ const filePath = join(delDir, delMsg.filename);
151
151
  if (!existsSync(filePath)) {
152
152
  sendTo(clientId, { type: "memory:delete_result", success: false, message: "Memory not found." });
153
153
  return;
@@ -155,7 +155,7 @@ registerHandler("memory", async function (clientId, message) {
155
155
  await unlink(filePath);
156
156
  await regenerateIndex(delDir);
157
157
  sendTo(clientId, { type: "memory:delete_result", success: true });
158
- var remainingMemories = await listMemoryFiles(delDir);
158
+ const remainingMemories = await listMemoryFiles(delDir);
159
159
  sendTo(clientId, { type: "memory:list_result", projectSlug: delMsg.projectSlug, memories: remainingMemories });
160
160
  }
161
161
  catch (err) {
@@ -12,27 +12,27 @@ import { networkInterfaces } from "node:os";
12
12
  import { existsSync, readFileSync } from "node:fs";
13
13
  import { execSync } from "node:child_process";
14
14
  function getLocalAddress() {
15
- var all = getAllAddresses();
15
+ const all = getAllAddresses();
16
16
  return all.length > 0 ? all[0].address : "localhost";
17
17
  }
18
18
  function getAllAddresses() {
19
- var interfaces = networkInterfaces();
20
- var keys = Object.keys(interfaces);
21
- var results = [];
22
- for (var i = 0; i < keys.length; i++) {
23
- var addrs = interfaces[keys[i]];
19
+ const interfaces = networkInterfaces();
20
+ const keys = Object.keys(interfaces);
21
+ const results = [];
22
+ for (let i = 0; i < keys.length; i++) {
23
+ const addrs = interfaces[keys[i]];
24
24
  if (!addrs)
25
25
  continue;
26
- for (var j = 0; j < addrs.length; j++) {
26
+ for (let j = 0; j < addrs.length; j++) {
27
27
  if (!addrs[j].internal && addrs[j].family === "IPv4") {
28
28
  results.push({ name: keys[i], address: addrs[j].address });
29
29
  }
30
30
  }
31
31
  }
32
32
  if (isWSL()) {
33
- var windowsAddrs = getWindowsHostAddresses();
34
- for (var w = 0; w < windowsAddrs.length; w++) {
35
- var exists = results.some(function (r) { return r.address === windowsAddrs[w].address; });
33
+ const windowsAddrs = getWindowsHostAddresses();
34
+ for (let w = 0; w < windowsAddrs.length; w++) {
35
+ const exists = results.some(function (r) { return r.address === windowsAddrs[w].address; });
36
36
  if (!exists) {
37
37
  results.push(windowsAddrs[w]);
38
38
  }
@@ -43,7 +43,7 @@ function getAllAddresses() {
43
43
  function isWSL() {
44
44
  try {
45
45
  if (existsSync("/proc/version")) {
46
- var version = readFileSync("/proc/version", "utf-8");
46
+ const version = readFileSync("/proc/version", "utf-8");
47
47
  return version.toLowerCase().includes("microsoft");
48
48
  }
49
49
  }
@@ -51,14 +51,14 @@ function isWSL() {
51
51
  return false;
52
52
  }
53
53
  function getWindowsHostAddresses() {
54
- var results = [];
54
+ const results = [];
55
55
  try {
56
- var output = execSync("powershell.exe -NoProfile -Command \"Get-NetIPAddress -AddressFamily IPv4 | ForEach-Object { \\$_.IPAddress + '|' + \\$_.InterfaceAlias }\"", { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] });
57
- var lines = output.trim().split(/\r?\n/);
58
- for (var i = 0; i < lines.length; i++) {
59
- var parts = lines[i].trim().split("|");
60
- var ip = parts[0];
61
- var iface = parts[1] || "windows";
56
+ const output = execSync("powershell.exe -NoProfile -Command \"Get-NetIPAddress -AddressFamily IPv4 | ForEach-Object { \\$_.IPAddress + '|' + \\$_.InterfaceAlias }\"", { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] });
57
+ const lines = output.trim().split(/\r?\n/);
58
+ for (let i = 0; i < lines.length; i++) {
59
+ const parts = lines[i].trim().split("|");
60
+ const ip = parts[0];
61
+ const iface = parts[1] || "windows";
62
62
  if (!ip || ip === "127.0.0.1")
63
63
  continue;
64
64
  if (ip.startsWith("169.254."))
@@ -72,18 +72,18 @@ function getWindowsHostAddresses() {
72
72
  return results;
73
73
  }
74
74
  function getLocalProjectsList() {
75
- var config = loadConfig();
75
+ const config = loadConfig();
76
76
  return config.projects.map(function (p) {
77
77
  return { slug: p.slug, title: p.title };
78
78
  });
79
79
  }
80
80
  export function buildNodesMessage() {
81
- var peers = loadPeers();
82
- var config = loadConfig();
83
- var identity = loadOrCreateIdentity();
84
- var connectedIds = new Set(getConnectedPeerIds());
85
- var localAddrs = getAllAddresses().map(function (a) { return a.address + ":" + config.port; });
86
- var local = {
81
+ const peers = loadPeers();
82
+ const config = loadConfig();
83
+ const identity = loadOrCreateIdentity();
84
+ const connectedIds = new Set(getConnectedPeerIds());
85
+ const localAddrs = getAllAddresses().map(function (a) { return a.address + ":" + config.port; });
86
+ const local = {
87
87
  id: identity.id,
88
88
  name: config.name,
89
89
  address: localAddrs[0] ?? "localhost:" + config.port,
@@ -95,9 +95,9 @@ export function buildNodesMessage() {
95
95
  return { slug: p.slug, path: p.path, title: p.title, nodeId: identity.id };
96
96
  }),
97
97
  };
98
- var remotes = peers.map(function (peer) {
99
- var peerProjects = getConnectedPeerProjects(peer.id);
100
- var health = getPeerHealth(peer.id);
98
+ const remotes = peers.map(function (peer) {
99
+ const peerProjects = getConnectedPeerProjects(peer.id);
100
+ const health = getPeerHealth(peer.id);
101
101
  return {
102
102
  id: peer.id,
103
103
  name: peer.name,
@@ -118,9 +118,9 @@ export function buildNodesMessage() {
118
118
  registerHandler("mesh", function (clientId, message) {
119
119
  log.meshHello("mesh message: %s from %s", message.type, clientId.slice(0, 8));
120
120
  if (message.type === "mesh:generate_invite") {
121
- var genMsg = message;
122
- var config = loadConfig();
123
- var address = genMsg.address || getLocalAddress();
121
+ const genMsg = message;
122
+ const config = loadConfig();
123
+ const address = genMsg.address || getLocalAddress();
124
124
  generateInviteCode(address, config.port).then(function (result) {
125
125
  sendTo(clientId, {
126
126
  type: "mesh:invite_code",
@@ -133,26 +133,26 @@ registerHandler("mesh", function (clientId, message) {
133
133
  return;
134
134
  }
135
135
  if (message.type === "mesh:addresses") {
136
- var addresses = getAllAddresses();
136
+ const addresses = getAllAddresses();
137
137
  sendTo(clientId, { type: "mesh:addresses_result", addresses: addresses });
138
138
  return;
139
139
  }
140
140
  if (message.type === "mesh:pair") {
141
- var pairMsg = message;
142
- var parsed = parseInviteCode(pairMsg.code);
141
+ const pairMsg = message;
142
+ const parsed = parseInviteCode(pairMsg.code);
143
143
  if (!parsed) {
144
144
  sendTo(clientId, { type: "mesh:pair_failed", message: "Invalid invite code format" });
145
145
  return;
146
146
  }
147
- var wsUrl = "ws://" + parsed.address + ":" + parsed.port + "/ws";
148
- var pairWs = new WebSocket(wsUrl);
149
- var pairTimeout = setTimeout(function () {
147
+ const wsUrl = "ws://" + parsed.address + ":" + parsed.port + "/ws";
148
+ const pairWs = new WebSocket(wsUrl);
149
+ const pairTimeout = setTimeout(function () {
150
150
  pairWs.close();
151
151
  sendTo(clientId, { type: "mesh:pair_failed", message: "Connection timed out" });
152
152
  }, 15000);
153
153
  pairWs.addEventListener("open", function () {
154
- var identity = loadOrCreateIdentity();
155
- var pairConfig = loadConfig();
154
+ const identity = loadOrCreateIdentity();
155
+ const pairConfig = loadConfig();
156
156
  pairWs.send(JSON.stringify({
157
157
  type: "mesh:hello",
158
158
  nodeId: identity.id,
@@ -166,7 +166,7 @@ registerHandler("mesh", function (clientId, message) {
166
166
  });
167
167
  pairWs.addEventListener("message", function (event) {
168
168
  try {
169
- var data = JSON.parse(event.data);
169
+ const data = JSON.parse(event.data);
170
170
  if (data.type === "mesh:hello_rejected") {
171
171
  clearTimeout(pairTimeout);
172
172
  pairWs.close();
@@ -175,8 +175,8 @@ registerHandler("mesh", function (clientId, message) {
175
175
  }
176
176
  if (data.type === "mesh:hello" && data.nodeId && data.name) {
177
177
  clearTimeout(pairTimeout);
178
- var peerAddr = parsed.address + ":" + parsed.port;
179
- var peer = {
178
+ const peerAddr = parsed.address + ":" + parsed.port;
179
+ const peer = {
180
180
  id: data.nodeId,
181
181
  name: data.name,
182
182
  addresses: [peerAddr],
@@ -186,8 +186,8 @@ registerHandler("mesh", function (clientId, message) {
186
186
  addPeer(peer);
187
187
  pairWs.close();
188
188
  connectToPeer(peer.id, peerAddr);
189
- var remoteProjectsList = data.projects ?? [];
190
- var nodeInfo = {
189
+ const remoteProjectsList = data.projects ?? [];
190
+ const nodeInfo = {
191
191
  id: peer.id,
192
192
  name: peer.name,
193
193
  address: peerAddr,
@@ -214,8 +214,8 @@ registerHandler("mesh", function (clientId, message) {
214
214
  return;
215
215
  }
216
216
  if (message.type === "mesh:hello") {
217
- var hello = message;
218
- var knownPeer = hello.nodeId ? getPeer(hello.nodeId) : undefined;
217
+ const hello = message;
218
+ const knownPeer = hello.nodeId ? getPeer(hello.nodeId) : undefined;
219
219
  log.meshHello("mesh:hello from nodeId=%s name=%s known=%s", hello.nodeId?.slice(0, 8), hello.name, !!knownPeer);
220
220
  if (knownPeer) {
221
221
  if (knownPeer.publicKey && hello.publicKey && knownPeer.publicKey !== hello.publicKey) {
@@ -223,12 +223,12 @@ registerHandler("mesh", function (clientId, message) {
223
223
  sendTo(clientId, { type: "mesh:hello_rejected", error: "Public key mismatch — possible impersonation" });
224
224
  return;
225
225
  }
226
- var inboundWs = getClientWebSocket(clientId);
226
+ const inboundWs = getClientWebSocket(clientId);
227
227
  log.meshHello(" registering inbound connection for %s (ws=%s, projects=%d)", hello.name, !!inboundWs, hello.projects?.length ?? 0);
228
228
  if (inboundWs) {
229
229
  registerInboundPeer(hello.nodeId, inboundWs, hello.projects ?? []);
230
230
  }
231
- var identity = loadOrCreateIdentity();
231
+ const identity = loadOrCreateIdentity();
232
232
  sendTo(clientId, {
233
233
  type: "mesh:hello",
234
234
  nodeId: identity.id,
@@ -244,8 +244,8 @@ registerHandler("mesh", function (clientId, message) {
244
244
  return;
245
245
  }
246
246
  consumePairingToken(hello.token);
247
- var peerAddresses = hello.addresses ?? [];
248
- var peer = {
247
+ const peerAddresses = hello.addresses ?? [];
248
+ const peer = {
249
249
  id: hello.nodeId,
250
250
  name: hello.name,
251
251
  addresses: peerAddresses,
@@ -256,7 +256,7 @@ registerHandler("mesh", function (clientId, message) {
256
256
  if (peerAddresses.length > 0) {
257
257
  connectToPeer(peer.id, peerAddresses[0]);
258
258
  }
259
- var identity2 = loadOrCreateIdentity();
259
+ const identity2 = loadOrCreateIdentity();
260
260
  sendTo(clientId, {
261
261
  type: "mesh:hello",
262
262
  nodeId: identity2.id,
@@ -268,7 +268,7 @@ registerHandler("mesh", function (clientId, message) {
268
268
  return;
269
269
  }
270
270
  if (message.type === "mesh:proxy_request") {
271
- var proxyReq = message;
271
+ const proxyReq = message;
272
272
  log.meshProxy("received proxy_request via handler from %s: %s for %s", clientId.slice(0, 8), proxyReq.payload.type, proxyReq.projectSlug);
273
273
  registerVirtualClient("mesh-proxy:" + clientId + ":" + proxyReq.requestId, function (response) {
274
274
  log.meshProxy(" → sending proxy_response %s back to client %s", response.type, clientId.slice(0, 8));
@@ -286,13 +286,13 @@ registerHandler("mesh", function (clientId, message) {
286
286
  return;
287
287
  }
288
288
  if (message.type === "mesh:proxy_response") {
289
- var proxyRes = message;
289
+ const proxyRes = message;
290
290
  log.meshProxy("received proxy_response via handler: %s", proxyRes.payload.type);
291
291
  handleProxyResponse(proxyRes);
292
292
  return;
293
293
  }
294
294
  if (message.type === "mesh:reconnect") {
295
- var reconnectMsg = message;
295
+ const reconnectMsg = message;
296
296
  reconnectPeer(reconnectMsg.nodeId);
297
297
  setTimeout(function () {
298
298
  broadcast({ type: "mesh:nodes", nodes: buildNodesMessage() });
@@ -300,23 +300,23 @@ registerHandler("mesh", function (clientId, message) {
300
300
  return;
301
301
  }
302
302
  if (message.type === "mesh:unpair") {
303
- var unpairMsg = message;
304
- var identity = loadOrCreateIdentity();
305
- var peerWs = getPeerConnection(unpairMsg.nodeId);
303
+ const unpairMsg = message;
304
+ const identity = loadOrCreateIdentity();
305
+ const peerWs = getPeerConnection(unpairMsg.nodeId);
306
306
  if (peerWs) {
307
307
  peerWs.send(JSON.stringify({ type: "mesh:unpaired", nodeId: identity.id }));
308
308
  }
309
309
  disconnectPeer(unpairMsg.nodeId);
310
- var removed = removePeer(unpairMsg.nodeId);
310
+ const removed = removePeer(unpairMsg.nodeId);
311
311
  if (removed) {
312
312
  broadcast({ type: "mesh:nodes", nodes: buildNodesMessage() });
313
313
  }
314
314
  return;
315
315
  }
316
316
  if (message.type === "mesh:unpaired") {
317
- var unpaired = message;
317
+ const unpaired = message;
318
318
  disconnectPeer(unpaired.nodeId);
319
- var wasRemoved = removePeer(unpaired.nodeId);
319
+ const wasRemoved = removePeer(unpaired.nodeId);
320
320
  if (wasRemoved) {
321
321
  broadcast({ type: "mesh:nodes", nodes: buildNodesMessage() });
322
322
  }
@@ -3,19 +3,19 @@ import { sendTo, broadcast } from "../ws/broadcast.js";
3
3
  import { listNotes, createNote, updateNote, deleteNote } from "../features/sticky-notes.js";
4
4
  registerHandler("notes", function (clientId, message) {
5
5
  if (message.type === "notes:list") {
6
- var listMsg = message;
6
+ const listMsg = message;
7
7
  sendTo(clientId, { type: "notes:list_result", notes: listNotes(listMsg.projectSlug) });
8
8
  return;
9
9
  }
10
10
  if (message.type === "notes:create") {
11
- var createMsg = message;
12
- var note = createNote(createMsg.content, createMsg.projectSlug);
11
+ const createMsg = message;
12
+ const note = createNote(createMsg.content, createMsg.projectSlug);
13
13
  broadcast({ type: "notes:created", note });
14
14
  return;
15
15
  }
16
16
  if (message.type === "notes:update") {
17
- var updateMsg = message;
18
- var updated = updateNote(updateMsg.id, updateMsg.content);
17
+ const updateMsg = message;
18
+ const updated = updateNote(updateMsg.id, updateMsg.content);
19
19
  if (!updated) {
20
20
  sendTo(clientId, { type: "chat:error", message: "Note not found" });
21
21
  return;
@@ -24,8 +24,8 @@ registerHandler("notes", function (clientId, message) {
24
24
  return;
25
25
  }
26
26
  if (message.type === "notes:delete") {
27
- var deleteMsg = message;
28
- var deleted = deleteNote(deleteMsg.id);
27
+ const deleteMsg = message;
28
+ const deleted = deleteNote(deleteMsg.id);
29
29
  if (!deleted) {
30
30
  sendTo(clientId, { type: "chat:error", message: "Note not found" });
31
31
  return;