@cryptiklemur/lattice 5.4.3 → 5.5.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 (85) hide show
  1. package/README.md +114 -0
  2. package/dist/client/assets/{angular-html-BMCIs4B9.js → angular-html-Bmjy4gNc.js} +1 -1
  3. package/dist/client/assets/{angular-ts-Dl9U67Xi.js → angular-ts-10l13C4C.js} +1 -1
  4. package/dist/client/assets/{apl-Dc2Jp1EP.js → apl--Bn7yH0T.js} +1 -1
  5. package/dist/client/assets/{astro-KOvSEh6g.js → astro-C8P9TQkP.js} +1 -1
  6. package/dist/client/assets/{blade-Bp9mbJ5K.js → blade-DQiHYnIS.js} +1 -1
  7. package/dist/client/assets/{c-C0ETB1bm.js → c-BFny-WnE.js} +1 -1
  8. package/dist/client/assets/{cobol-DE5VmQJX.js → cobol-hGEexMYH.js} +1 -1
  9. package/dist/client/assets/{coffee-COzJhfRU.js → coffee-j3W4ZALV.js} +1 -1
  10. package/dist/client/assets/{cpp-jzhs79Ii.js → cpp-DquWJNps.js} +1 -1
  11. package/dist/client/assets/{crystal-Czf3Etrk.js → crystal-CWL31dIV.js} +1 -1
  12. package/dist/client/assets/{css-Cf45eU4M.js → css-Di4GSq8V.js} +1 -1
  13. package/dist/client/assets/{dist-Bk-EVR9B.js → dist-CaJdL3Va.js} +2 -2
  14. package/dist/client/assets/{edge-BmKSsYuX.js → edge-rK4d050l.js} +1 -1
  15. package/dist/client/assets/{elixir-Ds7FEpTU.js → elixir-BMFKKu5z.js} +1 -1
  16. package/dist/client/assets/{elm-C_AmF7eK.js → elm-B0QVlW3-.js} +1 -1
  17. package/dist/client/assets/{erb-DevlC2ei.js → erb-C9w9QbhL.js} +1 -1
  18. package/dist/client/assets/{git-rebase-CpJCeeHA.js → git-rebase-FaylS7Vl.js} +1 -1
  19. package/dist/client/assets/{glimmer-js-CFH-Kzxa.js → glimmer-js-Bi2XnbHi.js} +1 -1
  20. package/dist/client/assets/{glimmer-ts-BkiQ1tjj.js → glimmer-ts-DOdxK6E6.js} +1 -1
  21. package/dist/client/assets/{glsl-DLuvkGQM.js → glsl-BiGDIGbZ.js} +1 -1
  22. package/dist/client/assets/{graphql-CYjDXA-l.js → graphql-CZJB8KIP.js} +1 -1
  23. package/dist/client/assets/{hack-CDfrJ_Sc.js → hack-CNGYBFqH.js} +1 -1
  24. package/dist/client/assets/{haml-C4YjrCNF.js → haml-pf3Zh5MH.js} +1 -1
  25. package/dist/client/assets/{handlebars-WIT13u08.js → handlebars-BsQwsvPC.js} +1 -1
  26. package/dist/client/assets/{html-ntqTOVvn.js → html-Dj4Hvv69.js} +1 -1
  27. package/dist/client/assets/{html-derivative-B3rc20Rp.js → html-derivative-CE7dQ_mI.js} +1 -1
  28. package/dist/client/assets/{http-jTU2ko3B.js → http-DjOuMI1u.js} +1 -1
  29. package/dist/client/assets/{hurl-D2HM7b2B.js → hurl-BH_MQrQo.js} +1 -1
  30. package/dist/client/assets/{index-CZNra7P3.js → index-DA8ZBSYW.js} +321 -88
  31. package/dist/client/assets/{index-DCKRhnC1.css → index-DcwXjiH0.css} +1 -1
  32. package/dist/client/assets/{java-BofMW2-d.js → java-CnpykAva.js} +1 -1
  33. package/dist/client/assets/{javascript-DHlF2jGd.js → javascript-BbqQ1sQM.js} +1 -1
  34. package/dist/client/assets/{jinja-BXkUuA_p.js → jinja-DddpvWwk.js} +1 -1
  35. package/dist/client/assets/{jison-CYSiwIU-.js → jison-Bd3G2n4x.js} +1 -1
  36. package/dist/client/assets/{json-5cpQWmWq.js → json-F0eTFQKP.js} +1 -1
  37. package/dist/client/assets/{jsx-D8kfeKVb.js → jsx-B-wB5nUs.js} +1 -1
  38. package/dist/client/assets/{julia-BkW_r2Xd.js → julia-9Lfz4b5s.js} +1 -1
  39. package/dist/client/assets/{just-Dz61xACw.js → just-BVE1sBJx.js} +1 -1
  40. package/dist/client/assets/{latex-gqtZNh_M.js → latex-SF3xMSWG.js} +1 -1
  41. package/dist/client/assets/{liquid-KcpeevnQ.js → liquid-CLkbZ0ZV.js} +1 -1
  42. package/dist/client/assets/{lua-C3Vw3Kyi.js → lua-DNph6TL8.js} +1 -1
  43. package/dist/client/assets/{marko-DVaxNS7b.js → marko-CGqdEtbF.js} +1 -1
  44. package/dist/client/assets/{mdc-DRm1pTBY.js → mdc-BLpzcq82.js} +1 -1
  45. package/dist/client/assets/{nginx-DYudX1m0.js → nginx-s7ciyZD1.js} +1 -1
  46. package/dist/client/assets/{nim-DejMEf9z.js → nim-C4FeZI3R.js} +1 -1
  47. package/dist/client/assets/{perl-D09qXnjW.js → perl-GDfD5AIi.js} +1 -1
  48. package/dist/client/assets/{php-BrfQzrDQ.js → php-CusAuy6y.js} +1 -1
  49. package/dist/client/assets/{pug-DPbk8XD2.js → pug-DCKuXO7x.js} +1 -1
  50. package/dist/client/assets/{qml-BCh8MHc-.js → qml-rp1ZHoeo.js} +1 -1
  51. package/dist/client/assets/{r-DCcyjvCV.js → r-CwNbYaVb.js} +1 -1
  52. package/dist/client/assets/{razor-CHeljxcn.js → razor-CinY5yf4.js} +1 -1
  53. package/dist/client/assets/{regexp-DpLv_uhV.js → regexp-CxVI4rKV.js} +1 -1
  54. package/dist/client/assets/{rst-BmAGX4li.js → rst-BrBmBgUr.js} +1 -1
  55. package/dist/client/assets/{ruby-C28IDakj.js → ruby-BzNCpRio.js} +1 -1
  56. package/dist/client/assets/{sas-Dq78Tt13.js → sas-B4IAap7m.js} +1 -1
  57. package/dist/client/assets/{scss-CCq8md_z.js → scss-eNAsUEA1.js} +1 -1
  58. package/dist/client/assets/{shellscript-Cl_slHLv.js → shellscript-BwH0aChW.js} +1 -1
  59. package/dist/client/assets/{shellsession-D50FTgCo.js → shellsession-B5ibJBbh.js} +1 -1
  60. package/dist/client/assets/{soy-Da12pRro.js → soy-BrqReQP3.js} +1 -1
  61. package/dist/client/assets/{sql-DRKhJcrs.js → sql-KIDgTieS.js} +1 -1
  62. package/dist/client/assets/{stata-E06HAz87.js → stata-D6yim7Rr.js} +1 -1
  63. package/dist/client/assets/{surrealql-CTaVrdiv.js → surrealql-C51iMPEA.js} +1 -1
  64. package/dist/client/assets/{svelte-j0H5d0BS.js → svelte-DYs5QSVt.js} +1 -1
  65. package/dist/client/assets/{templ-BXfOHYWo.js → templ-CLDdaEXl.js} +1 -1
  66. package/dist/client/assets/{tex-CGBWhBxV.js → tex-D16HBCoj.js} +1 -1
  67. package/dist/client/assets/{ts-tags-C-diQc0f.js → ts-tags-DTcB2bBd.js} +1 -1
  68. package/dist/client/assets/{tsx-CUBPow91.js → tsx-BxGfVt8a.js} +1 -1
  69. package/dist/client/assets/{twig-BYoQufij.js → twig-BUC08jwe.js} +1 -1
  70. package/dist/client/assets/{typescript-CAiUPCi4.js → typescript-CuPGT2MR.js} +1 -1
  71. package/dist/client/assets/{vue-CEKqQRtx.js → vue-_ip8-SIk.js} +1 -1
  72. package/dist/client/assets/{vue-html-DSRnbzbs.js → vue-html-D-I9-U-x.js} +1 -1
  73. package/dist/client/assets/{vue-vine-PFaCZbOl.js → vue-vine-7AONB1tt.js} +1 -1
  74. package/dist/client/assets/{xml-CpFeNxWK.js → xml-D2ZUDsPU.js} +1 -1
  75. package/dist/client/assets/{xsl-DOlnqqgg.js → xsl-GlFKKlLy.js} +1 -1
  76. package/dist/client/assets/{yaml-Bv-3IQB_.js → yaml-BnuTxWck.js} +1 -1
  77. package/dist/client/index.html +2 -2
  78. package/dist/client/sw.js +1 -1
  79. package/dist/server/daemon.js +16 -0
  80. package/dist/server/features/brainstorm.js +267 -0
  81. package/dist/server/handlers/brainstorm.js +33 -0
  82. package/dist/server/handlers/fs.js +3 -0
  83. package/dist/server/handlers/session.js +13 -5
  84. package/dist/server/project/session.js +92 -11
  85. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import { registerHandler } from "../ws/router.js";
2
- import { sendTo } from "../ws/broadcast.js";
2
+ import { sendTo, broadcast } from "../ws/broadcast.js";
3
3
  import { loadConfig } from "../config.js";
4
- import { createSession, deleteSession, findProjectSlugForSession, getSessionPreview, getSessionTitle, getSessionUsage, listSessions, invalidateSessionCache, invalidateHistoryCache, getSessionHistoryPage, loadSessionHistory, renameSession, getSessionFileSizeBytes, } from "../project/session.js";
4
+ import { createSession, deleteSession, findProjectSlugForSession, getSessionPreview, getSessionTitle, getSessionUsage, listSessions, invalidateSessionCache, invalidateHistoryCache, getSessionHistoryPage, loadSessionHistory, renameSession, getSessionFileSizeBytes, updateSessionInIndex, removeSessionFromIndex, } from "../project/session.js";
5
5
  import { getContextBreakdown } from "../project/context-breakdown.js";
6
6
  import { setActiveSession, getActiveSession } from "./chat.js";
7
7
  import { setActiveProject } from "./fs.js";
@@ -71,7 +71,15 @@ registerHandler("session", function (clientId, message) {
71
71
  if (message.type === "session:create") {
72
72
  var createMsg = message;
73
73
  var session = createSession(createMsg.projectSlug);
74
+ updateSessionInIndex(createMsg.projectSlug, session);
74
75
  sendTo(clientId, { type: "session:created", session });
76
+ broadcast({
77
+ type: "session:list",
78
+ projectSlug: createMsg.projectSlug,
79
+ sessions: [session],
80
+ totalCount: undefined,
81
+ offset: 0,
82
+ });
75
83
  return;
76
84
  }
77
85
  if (message.type === "session:activate") {
@@ -160,7 +168,7 @@ registerHandler("session", function (clientId, message) {
160
168
  void renameSession(projectSlug, renameMsg.sessionId, renameMsg.title).then(function () {
161
169
  invalidateSessionCache(projectSlug);
162
170
  void listSessions(projectSlug, { limit: 40 }).then(function (result) {
163
- sendTo(clientId, {
171
+ broadcast({
164
172
  type: "session:list",
165
173
  projectSlug,
166
174
  sessions: result.sessions,
@@ -179,9 +187,9 @@ registerHandler("session", function (clientId, message) {
179
187
  return;
180
188
  }
181
189
  void deleteSession(deleteProjectSlug, deleteMsg.sessionId).then(function () {
182
- invalidateSessionCache(deleteProjectSlug);
190
+ removeSessionFromIndex(deleteProjectSlug, deleteMsg.sessionId);
183
191
  void listSessions(deleteProjectSlug, { limit: 40 }).then(function (result) {
184
- sendTo(clientId, {
192
+ broadcast({
185
193
  type: "session:list",
186
194
  projectSlug: deleteProjectSlug,
187
195
  sessions: result.sessions,
@@ -1,10 +1,10 @@
1
1
  import { listSessions as sdkListSessions, getSessionInfo, getSessionMessages, renameSession as sdkRenameSession, } from "@anthropic-ai/claude-agent-sdk";
2
- import { existsSync, unlinkSync, readFileSync, statSync } from "node:fs";
2
+ import { existsSync, unlinkSync, readFileSync, statSync, writeFileSync } from "node:fs";
3
3
  import * as fsPromises from "node:fs/promises";
4
4
  import { join } from "node:path";
5
5
  import { randomUUID } from "node:crypto";
6
6
  import { homedir } from "node:os";
7
- import { loadConfig } from "../config.js";
7
+ import { loadConfig, getLatticeHome } from "../config.js";
8
8
  import { log } from "../logger.js";
9
9
  function getProjectPath(projectSlug) {
10
10
  var config = loadConfig();
@@ -428,7 +428,81 @@ export async function getSessionPreview(projectSlug, sessionId) {
428
428
  }
429
429
  }
430
430
  var sessionListCache = new Map();
431
- var SESSION_CACHE_TTL = 5000;
431
+ var SESSION_CACHE_TTL = 60000;
432
+ var RECONCILE_INTERVAL = 5 * 60 * 1000;
433
+ var lastReconcile = new Map();
434
+ function getIndexPath() {
435
+ return join(getLatticeHome(), "session-index.json");
436
+ }
437
+ function loadSessionIndex() {
438
+ var indexPath = getIndexPath();
439
+ if (!existsSync(indexPath))
440
+ return {};
441
+ try {
442
+ return JSON.parse(readFileSync(indexPath, "utf-8"));
443
+ }
444
+ catch {
445
+ return {};
446
+ }
447
+ }
448
+ function saveSessionIndex(index) {
449
+ try {
450
+ writeFileSync(getIndexPath(), JSON.stringify(index), "utf-8");
451
+ }
452
+ catch (err) {
453
+ log.session("Failed to save session index: %O", err);
454
+ }
455
+ }
456
+ export function updateSessionInIndex(projectSlug, session) {
457
+ var index = loadSessionIndex();
458
+ var sessions = index[projectSlug] || [];
459
+ var existing = -1;
460
+ for (var i = 0; i < sessions.length; i++) {
461
+ if (sessions[i].id === session.id) {
462
+ existing = i;
463
+ break;
464
+ }
465
+ }
466
+ if (existing >= 0) {
467
+ sessions[existing] = session;
468
+ }
469
+ else {
470
+ sessions.push(session);
471
+ }
472
+ sessions.sort(function (a, b) { return b.updatedAt - a.updatedAt; });
473
+ index[projectSlug] = sessions;
474
+ saveSessionIndex(index);
475
+ sessionListCache.set(projectSlug, { sessions, time: Date.now() });
476
+ }
477
+ export function removeSessionFromIndex(projectSlug, sessionId) {
478
+ var index = loadSessionIndex();
479
+ var sessions = index[projectSlug] || [];
480
+ index[projectSlug] = sessions.filter(function (s) { return s.id !== sessionId; });
481
+ saveSessionIndex(index);
482
+ sessionListCache.set(projectSlug, { sessions: index[projectSlug], time: Date.now() });
483
+ }
484
+ async function reconcileWithSDK(projectSlug) {
485
+ var projectPath = getProjectPath(projectSlug);
486
+ if (!projectPath)
487
+ return [];
488
+ var sdkT0 = Date.now();
489
+ var sdkSessions = await sdkListSessions({ dir: projectPath });
490
+ log.session("sdkListSessions for %s: %dms (%d sessions)", projectSlug, Date.now() - sdkT0, sdkSessions.length);
491
+ var summaries = sdkSessions.map(function (s) { return mapSDKSession(s, projectSlug); });
492
+ summaries.sort(function (a, b) { return b.updatedAt - a.updatedAt; });
493
+ var index = loadSessionIndex();
494
+ index[projectSlug] = summaries;
495
+ saveSessionIndex(index);
496
+ sessionListCache.set(projectSlug, { sessions: summaries, time: Date.now() });
497
+ lastReconcile.set(projectSlug, Date.now());
498
+ return summaries;
499
+ }
500
+ function needsReconcile(projectSlug) {
501
+ var last = lastReconcile.get(projectSlug);
502
+ if (!last)
503
+ return true;
504
+ return Date.now() - last > RECONCILE_INTERVAL;
505
+ }
432
506
  export async function listSessions(projectSlug, options) {
433
507
  var projectPath = getProjectPath(projectSlug);
434
508
  if (!projectPath) {
@@ -441,15 +515,22 @@ export async function listSessions(projectSlug, options) {
441
515
  var sliced = limit > 0 ? cached.sessions.slice(offset, offset + limit) : cached.sessions;
442
516
  return { sessions: sliced, totalCount: cached.sessions.length };
443
517
  }
518
+ var index = loadSessionIndex();
519
+ var indexed = index[projectSlug];
520
+ if (indexed && indexed.length > 0) {
521
+ sessionListCache.set(projectSlug, { sessions: indexed, time: Date.now() });
522
+ if (needsReconcile(projectSlug)) {
523
+ reconcileWithSDK(projectSlug).catch(function (err) {
524
+ log.session("Background reconcile failed: %O", err);
525
+ });
526
+ }
527
+ var offset3 = options?.offset ?? 0;
528
+ var limit3 = options?.limit ?? 0;
529
+ var sliced3 = limit3 > 0 ? indexed.slice(offset3, offset3 + limit3) : indexed;
530
+ return { sessions: sliced3, totalCount: indexed.length };
531
+ }
444
532
  try {
445
- var sdkT0 = Date.now();
446
- var sdkSessions = await sdkListSessions({ dir: projectPath });
447
- log.session("sdkListSessions for %s: %dms (%d sessions)", projectSlug, Date.now() - sdkT0, sdkSessions.length);
448
- var summaries = sdkSessions.map(function (s) {
449
- return mapSDKSession(s, projectSlug);
450
- });
451
- summaries.sort(function (a, b) { return b.updatedAt - a.updatedAt; });
452
- sessionListCache.set(projectSlug, { sessions: summaries, time: Date.now() });
533
+ var summaries = await reconcileWithSDK(projectSlug);
453
534
  var offset2 = options?.offset ?? 0;
454
535
  var limit2 = options?.limit ?? 0;
455
536
  var sliced2 = limit2 > 0 ? summaries.slice(offset2, offset2 + limit2) : summaries;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cryptiklemur/lattice",
3
- "version": "5.4.3",
3
+ "version": "5.5.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>",