@cryptiklemur/lattice 1.43.3 → 1.43.4
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cryptiklemur/lattice",
|
|
3
|
-
"version": "1.43.
|
|
3
|
+
"version": "1.43.4",
|
|
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>",
|
|
@@ -34,7 +34,9 @@ registerHandler("session", function (clientId: string, message: ClientMessage) {
|
|
|
34
34
|
var listReqMsg = message as SessionListRequestMessage;
|
|
35
35
|
var offset = listReqMsg.offset || 0;
|
|
36
36
|
var limit = listReqMsg.limit || 0;
|
|
37
|
+
var t0 = Date.now();
|
|
37
38
|
void listSessions(listReqMsg.projectSlug, { offset, limit }).then(function (result) {
|
|
39
|
+
log.session("session:list_request for %s took %dms (%d sessions)", listReqMsg.projectSlug, Date.now() - t0, result.sessions.length);
|
|
38
40
|
sendTo(clientId, {
|
|
39
41
|
type: "session:list",
|
|
40
42
|
projectSlug: listReqMsg.projectSlug,
|
|
@@ -221,7 +221,7 @@ export function getActiveSessionCountForProject(projectPath: string): number {
|
|
|
221
221
|
if (existsSync(join(dir, sessionId + ".jsonl"))) count++;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
if (
|
|
224
|
+
if (cliActiveProjects.has(projectPath)) count++;
|
|
225
225
|
|
|
226
226
|
return count;
|
|
227
227
|
}
|
|
@@ -241,32 +241,15 @@ export function isSessionBusy(sessionId: string): boolean {
|
|
|
241
241
|
* The SDK spawns child processes (e.g. claude-agent-sdk/cli.js) that hold
|
|
242
242
|
* lock files — those are NOT external.
|
|
243
243
|
*/
|
|
244
|
-
var
|
|
245
|
-
var sessionNameCache = new Map<string, string>();
|
|
244
|
+
var cliActiveProjects = new Set<string>();
|
|
246
245
|
|
|
247
246
|
function refreshCliDetection(): void {
|
|
248
|
-
var
|
|
247
|
+
var newActive = new Set<string>();
|
|
249
248
|
var cliPids = getClaudeCliPidsAsync();
|
|
250
|
-
for (var i = 0; i <
|
|
251
|
-
|
|
252
|
-
var found: string | null = null;
|
|
253
|
-
for (var j = 0; j < cliPids.length; j++) {
|
|
254
|
-
if (cliPids[j].cwd !== projectPath) continue;
|
|
255
|
-
var cmdline = cliPids[j].cmdline;
|
|
256
|
-
var resumeIdx = cmdline.indexOf("--resume");
|
|
257
|
-
if (resumeIdx !== -1 && resumeIdx + 1 < cmdline.length) {
|
|
258
|
-
var sessionName = cmdline[resumeIdx + 1];
|
|
259
|
-
found = resolveSessionName(projectPath, sessionName);
|
|
260
|
-
if (!found) {
|
|
261
|
-
resolveSessionNameAsync(projectPath, sessionName);
|
|
262
|
-
}
|
|
263
|
-
} else {
|
|
264
|
-
found = findMostRecentSession(projectPath);
|
|
265
|
-
}
|
|
266
|
-
break;
|
|
267
|
-
}
|
|
268
|
-
cliSessionsByProject.set(projectPath, found);
|
|
249
|
+
for (var i = 0; i < cliPids.length; i++) {
|
|
250
|
+
newActive.add(cliPids[i].cwd);
|
|
269
251
|
}
|
|
252
|
+
cliActiveProjects = newActive;
|
|
270
253
|
}
|
|
271
254
|
|
|
272
255
|
function getClaudeCliPidsAsync(): Array<{ pid: number; cwd: string; cmdline: string[] }> {
|
|
@@ -288,8 +271,7 @@ function getClaudeCliPidsAsync(): Array<{ pid: number; cwd: string; cmdline: str
|
|
|
288
271
|
return results;
|
|
289
272
|
}
|
|
290
273
|
|
|
291
|
-
setInterval(refreshCliDetection,
|
|
292
|
-
setTimeout(refreshCliDetection, 1000);
|
|
274
|
+
setInterval(refreshCliDetection, 10000);
|
|
293
275
|
|
|
294
276
|
function getProjectPathForSession(sessionId: string): string | null {
|
|
295
277
|
var config = loadConfig();
|
|
@@ -302,72 +284,11 @@ function getProjectPathForSession(sessionId: string): string | null {
|
|
|
302
284
|
}
|
|
303
285
|
|
|
304
286
|
|
|
305
|
-
function resolveSessionName(projectPath: string, name: string): string | null {
|
|
306
|
-
var cacheKey = projectPath + ":" + name;
|
|
307
|
-
var cached = sessionNameCache.get(cacheKey);
|
|
308
|
-
if (cached) return cached;
|
|
309
|
-
|
|
310
|
-
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(name)) {
|
|
311
|
-
var hash = projectPath.replace(/\//g, "-");
|
|
312
|
-
if (existsSync(join(homedir(), ".claude", "projects", hash, name + ".jsonl"))) {
|
|
313
|
-
sessionNameCache.set(cacheKey, name);
|
|
314
|
-
return name;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return null;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
function resolveSessionNameAsync(projectPath: string, name: string): void {
|
|
322
|
-
var cacheKey = projectPath + ":" + name;
|
|
323
|
-
if (sessionNameCache.has(cacheKey)) return;
|
|
324
|
-
|
|
325
|
-
var hash = projectPath.replace(/\//g, "-");
|
|
326
|
-
var dir = join(homedir(), ".claude", "projects", hash);
|
|
327
|
-
if (!existsSync(dir)) return;
|
|
328
|
-
|
|
329
|
-
var proc = Bun.spawn(["grep", "-rl", "--include=*.jsonl", "-m", "1", name, dir], {
|
|
330
|
-
stdout: "pipe", stderr: "ignore",
|
|
331
|
-
});
|
|
332
|
-
void proc.exited.then(function () {
|
|
333
|
-
var output = new Response(proc.stdout).text();
|
|
334
|
-
return output;
|
|
335
|
-
}).then(function (text) {
|
|
336
|
-
var files = text.trim().split("\n").filter(Boolean);
|
|
337
|
-
if (files.length > 0) {
|
|
338
|
-
var match = files[0].match(/([0-9a-f-]{36})\.jsonl$/);
|
|
339
|
-
if (match) {
|
|
340
|
-
sessionNameCache.set(cacheKey, match[1]);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}).catch(function () {});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function findMostRecentSession(projectPath: string): string | null {
|
|
347
|
-
var hash = projectPath.replace(/\//g, "-");
|
|
348
|
-
var dir = join(homedir(), ".claude", "projects", hash);
|
|
349
|
-
if (!existsSync(dir)) return null;
|
|
350
|
-
|
|
351
|
-
var entries = readdirSync(dir).filter(function (f) { return f.endsWith(".jsonl"); });
|
|
352
|
-
var latest: { id: string; mtime: number } | null = null;
|
|
353
|
-
for (var e = 0; e < entries.length; e++) {
|
|
354
|
-
try {
|
|
355
|
-
var s = statSync(join(dir, entries[e]));
|
|
356
|
-
if (!latest || s.mtimeMs > latest.mtime) {
|
|
357
|
-
latest = { id: entries[e].replace(".jsonl", ""), mtime: s.mtimeMs };
|
|
358
|
-
}
|
|
359
|
-
} catch {}
|
|
360
|
-
}
|
|
361
|
-
if (latest && Date.now() - latest.mtime < 60000) return latest.id;
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
|
|
366
287
|
function isSessionLockedByExternal(sessionId: string): boolean {
|
|
367
288
|
if (activeStreams.has(sessionId)) return false;
|
|
368
289
|
var projectPath = getProjectPathForSession(sessionId);
|
|
369
290
|
if (!projectPath) return false;
|
|
370
|
-
return
|
|
291
|
+
return cliActiveProjects.has(projectPath);
|
|
371
292
|
}
|
|
372
293
|
|
|
373
294
|
export function stopExternalSession(sessionId: string): boolean {
|