@cryptiklemur/lattice 1.43.0 → 1.43.1

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.
@@ -295,7 +295,7 @@ export function SessionList(props: SessionListProps) {
295
295
  if (props.projectSlug && ws.status === "connected") {
296
296
  sendRef.current({ type: "session:list_request", projectSlug: props.projectSlug, offset: 0, limit: PAGE_SIZE });
297
297
  }
298
- }, 10000);
298
+ }, 30000);
299
299
  return function () { clearInterval(interval); };
300
300
  }
301
301
  }, [props.projectSlug, ws.status]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cryptiklemur/lattice",
3
- "version": "1.43.0",
3
+ "version": "1.43.1",
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>",
@@ -3,6 +3,7 @@ import type {
3
3
  SessionActivateMessage,
4
4
  SessionCreateMessage,
5
5
  SessionDeleteMessage,
6
+ SessionSummary,
6
7
  SessionListRequestMessage,
7
8
  SessionPreviewRequestMessage,
8
9
  SessionRenameMessage,
@@ -18,6 +19,7 @@ import {
18
19
  getSessionTitle,
19
20
  getSessionUsage,
20
21
  listSessions,
22
+ invalidateSessionCache,
21
23
  loadSessionHistory,
22
24
  renameSession,
23
25
  } from "../project/session";
@@ -30,16 +32,14 @@ import { log } from "../logger";
30
32
  registerHandler("session", function (clientId: string, message: ClientMessage) {
31
33
  if (message.type === "session:list_request") {
32
34
  var listReqMsg = message as SessionListRequestMessage;
33
- void listSessions(listReqMsg.projectSlug).then(function (sessions) {
34
- var offset = listReqMsg.offset || 0;
35
- var limit = listReqMsg.limit || 0;
36
- var totalCount = sessions.length;
37
- var sliced = limit > 0 ? sessions.slice(offset, offset + limit) : sessions;
35
+ var offset = listReqMsg.offset || 0;
36
+ var limit = listReqMsg.limit || 0;
37
+ void listSessions(listReqMsg.projectSlug, { offset, limit }).then(function (result) {
38
38
  sendTo(clientId, {
39
39
  type: "session:list",
40
40
  projectSlug: listReqMsg.projectSlug,
41
- sessions: sliced,
42
- totalCount,
41
+ sessions: result.sessions,
42
+ totalCount: result.totalCount,
43
43
  offset,
44
44
  });
45
45
  });
@@ -59,16 +59,16 @@ registerHandler("session", function (clientId: string, message: ClientMessage) {
59
59
  if (message.type === "session:list_all_request") {
60
60
  var config = loadConfig();
61
61
  var allPromises = config.projects.map(function (p: typeof config.projects[number]) {
62
- return listSessions(p.slug);
62
+ return listSessions(p.slug, { limit: 20 });
63
63
  });
64
64
  void Promise.all(allPromises).then(function (results) {
65
- var merged: typeof results[0] = [];
65
+ var merged: SessionSummary[] = [];
66
66
  for (var i = 0; i < results.length; i++) {
67
- for (var j = 0; j < results[i].length; j++) {
68
- merged.push(results[i][j]);
67
+ for (var j = 0; j < results[i].sessions.length; j++) {
68
+ merged.push(results[i].sessions[j]);
69
69
  }
70
70
  }
71
- merged.sort(function (a: typeof merged[number], b: typeof merged[number]) { return b.updatedAt - a.updatedAt; });
71
+ merged.sort(function (a, b) { return b.updatedAt - a.updatedAt; });
72
72
  sendTo(clientId, {
73
73
  type: "session:list_all",
74
74
  sessions: merged.slice(0, 20),
@@ -171,11 +171,13 @@ registerHandler("session", function (clientId: string, message: ClientMessage) {
171
171
  return;
172
172
  }
173
173
  void renameSession(projectSlug, renameMsg.sessionId, renameMsg.title).then(function () {
174
- void listSessions(projectSlug).then(function (sessions) {
174
+ invalidateSessionCache(projectSlug);
175
+ void listSessions(projectSlug, { limit: 40 }).then(function (result) {
175
176
  sendTo(clientId, {
176
177
  type: "session:list",
177
178
  projectSlug,
178
- sessions,
179
+ sessions: result.sessions,
180
+ totalCount: result.totalCount,
179
181
  });
180
182
  });
181
183
  });
@@ -191,11 +193,13 @@ registerHandler("session", function (clientId: string, message: ClientMessage) {
191
193
  return;
192
194
  }
193
195
  void deleteSession(deleteProjectSlug, deleteMsg.sessionId).then(function () {
194
- void listSessions(deleteProjectSlug).then(function (sessions) {
196
+ invalidateSessionCache(deleteProjectSlug);
197
+ void listSessions(deleteProjectSlug, { limit: 40 }).then(function (result) {
195
198
  sendTo(clientId, {
196
199
  type: "session:list",
197
200
  projectSlug: deleteProjectSlug,
198
- sessions,
201
+ sessions: result.sessions,
202
+ totalCount: result.totalCount,
199
203
  });
200
204
  });
201
205
  });
@@ -11,7 +11,7 @@ import { sendTo, broadcast } from "../ws/broadcast";
11
11
  import { syncSessionToPeers } from "../mesh/session-sync";
12
12
  import { resolveSkillContent } from "../handlers/skills";
13
13
  import { getPluginMcpServers } from "../handlers/plugins";
14
- import { guessContextWindow, getSessionTitle, renameSession, listSessions } from "./session";
14
+ import { guessContextWindow, getSessionTitle, renameSession, listSessions, invalidateSessionCache } from "./session";
15
15
  import { getLatticeHome, loadConfig } from "../config";
16
16
  import { log } from "../logger";
17
17
  import { getDailySpend, invalidateDailySpendCache } from "../analytics/engine";
@@ -1032,8 +1032,9 @@ export function startChatStream(options: ChatStreamOptions): void {
1032
1032
  void renameSession(projectSlug, sessionId, newTitle).then(function (ok) {
1033
1033
  if (!ok) return;
1034
1034
  log.session("Auto-titled session %s: %s", sessionId, newTitle);
1035
- void listSessions(projectSlug).then(function (sessions) {
1036
- broadcast({ type: "session:list", projectSlug, sessions });
1035
+ invalidateSessionCache(projectSlug);
1036
+ void listSessions(projectSlug, { limit: 40 }).then(function (result) {
1037
+ broadcast({ type: "session:list", projectSlug, sessions: result.sessions, totalCount: result.totalCount });
1037
1038
  });
1038
1039
  });
1039
1040
  });
@@ -404,10 +404,21 @@ export async function getSessionPreview(projectSlug: string, sessionId: string):
404
404
  }
405
405
  }
406
406
 
407
- export async function listSessions(projectSlug: string): Promise<SessionSummary[]> {
407
+ var sessionListCache = new Map<string, { sessions: SessionSummary[]; time: number }>();
408
+ var SESSION_CACHE_TTL = 5000;
409
+
410
+ export async function listSessions(projectSlug: string, options?: { offset?: number; limit?: number; noCache?: boolean }): Promise<{ sessions: SessionSummary[]; totalCount: number }> {
408
411
  var projectPath = getProjectPath(projectSlug);
409
412
  if (!projectPath) {
410
- return [];
413
+ return { sessions: [], totalCount: 0 };
414
+ }
415
+
416
+ var cached = sessionListCache.get(projectSlug);
417
+ if (cached && !options?.noCache && Date.now() - cached.time < SESSION_CACHE_TTL) {
418
+ var offset = options?.offset ?? 0;
419
+ var limit = options?.limit ?? 0;
420
+ var sliced = limit > 0 ? cached.sessions.slice(offset, offset + limit) : cached.sessions;
421
+ return { sessions: sliced, totalCount: cached.sessions.length };
411
422
  }
412
423
 
413
424
  try {
@@ -416,13 +427,22 @@ export async function listSessions(projectSlug: string): Promise<SessionSummary[
416
427
  return mapSDKSession(s, projectSlug);
417
428
  });
418
429
  summaries.sort(function (a, b) { return b.updatedAt - a.updatedAt; });
419
- return summaries;
430
+ sessionListCache.set(projectSlug, { sessions: summaries, time: Date.now() });
431
+
432
+ var offset2 = options?.offset ?? 0;
433
+ var limit2 = options?.limit ?? 0;
434
+ var sliced2 = limit2 > 0 ? summaries.slice(offset2, offset2 + limit2) : summaries;
435
+ return { sessions: sliced2, totalCount: summaries.length };
420
436
  } catch (err) {
421
437
  log.session("Failed to list SDK sessions: %O", err);
422
- return [];
438
+ return { sessions: [], totalCount: 0 };
423
439
  }
424
440
  }
425
441
 
442
+ export function invalidateSessionCache(projectSlug: string): void {
443
+ sessionListCache.delete(projectSlug);
444
+ }
445
+
426
446
  export async function getSessionTitle(projectSlug: string, sessionId: string): Promise<string> {
427
447
  var projectPath = getProjectPath(projectSlug);
428
448
  var options = projectPath ? { dir: projectPath } : undefined;