claude-code-session-manager 0.17.2 → 0.18.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 (28) hide show
  1. package/dist/assets/{TiptapBody-B16U7NOC.js → TiptapBody-BYuX12nR.js} +1 -1
  2. package/dist/assets/{cssMode-BlRHn_L6.js → cssMode-Bl7tLpHc.js} +1 -1
  3. package/dist/assets/{freemarker2-Bk2fXLx4.js → freemarker2-BNg8eaix.js} +1 -1
  4. package/dist/assets/{handlebars-eLqjBxBa.js → handlebars-DOtypyYM.js} +1 -1
  5. package/dist/assets/{html-BzvHaJnM.js → html-C5Y_A8fx.js} +1 -1
  6. package/dist/assets/{htmlMode-C9rcOKw8.js → htmlMode-GCffrndJ.js} +1 -1
  7. package/dist/assets/{index-BqYM-JWd.css → index-CILtNJFv.css} +1 -1
  8. package/dist/assets/index-DpwXs8WR.js +4411 -0
  9. package/dist/assets/{javascript-BAOAmGHx.js → javascript-Ci7pAiN4.js} +1 -1
  10. package/dist/assets/{jsonMode-CM0KALCa.js → jsonMode-DQ3Dmk2R.js} +1 -1
  11. package/dist/assets/{liquid-Bi-cszJ-.js → liquid-Cngw0Bvl.js} +1 -1
  12. package/dist/assets/{lspLanguageFeatures-BxkipFwP.js → lspLanguageFeatures-u9E6DcOs.js} +1 -1
  13. package/dist/assets/{mdx-DwbRtWl-.js → mdx-C1X2XFk1.js} +1 -1
  14. package/dist/assets/{python-D-IprHOk.js → python-bzrLgYRP.js} +1 -1
  15. package/dist/assets/{razor-CC6ogdu3.js → razor-UzmH3H-S.js} +1 -1
  16. package/dist/assets/{tsMode-BJR_Ezbp.js → tsMode-B7OLLJk-.js} +1 -1
  17. package/dist/assets/{typescript-FkJpv2Nj.js → typescript-BDlZri5r.js} +1 -1
  18. package/dist/assets/{xml-BVuV92it.js → xml-M5NECxDB.js} +1 -1
  19. package/dist/assets/{yaml-CKj9MriX.js → yaml-BcrGaG2T.js} +1 -1
  20. package/dist/index.html +2 -2
  21. package/package.json +2 -1
  22. package/src/main/crashDiagnostics.cjs +12 -1
  23. package/src/main/index.cjs +27 -3
  24. package/src/main/kg.cjs +0 -0
  25. package/src/main/memoryTool.cjs +12 -6
  26. package/src/preload/api.d.ts +47 -0
  27. package/src/preload/index.cjs +11 -0
  28. package/dist/assets/index-DqO1hmJF.js +0 -4365
@@ -34,6 +34,7 @@ const agentMemory = require('./agentMemory.cjs');
34
34
  const { registerDocEditorHandlers } = require('./docEditor.cjs');
35
35
  const git = require('./git.cjs');
36
36
  const superagent = require('./superagent.cjs');
37
+ const kg = require('./kg.cjs');
37
38
  const { registerProjectSkillsHandlers } = require('./projectSkills.cjs');
38
39
  const filesIpc = require('./files.cjs');
39
40
  const searchIpc = require('./search.cjs');
@@ -276,6 +277,7 @@ async function rebootApp() {
276
277
  logReboot('falling back to app.relaunch()');
277
278
  app.relaunch();
278
279
  }
280
+ runShutdownCleanup(); // app.exit bypasses will-quit
279
281
  app.exit(0);
280
282
  }
281
283
 
@@ -338,6 +340,7 @@ function createWindow() {
338
340
  // instead of blindly trying http://localhost:5173, which would (a) load
339
341
  // remote content and (b) almost always fail in a packaged install.
340
342
  console.error('[main] dist/index.html missing and SM_DEV is not set — refusing to load remote content. Reinstall or set SM_DEV=1 for dev.');
343
+ runShutdownCleanup(); // app.exit bypasses will-quit
341
344
  app.exit(1);
342
345
  return;
343
346
  }
@@ -732,7 +735,13 @@ app.whenReady().then(async () => {
732
735
  // uncleanly (the silent OOM-kill we've been chasing), then starts the memory
733
736
  // heartbeat + render/child-process-gone hooks for this run. See
734
737
  // crashDiagnostics.cjs for the full rationale.
735
- crashDiagnostics.init({ logs, getPowerBlockerId: () => powerBlockerId });
738
+ crashDiagnostics.init({
739
+ logs,
740
+ getPowerBlockerId: () => powerBlockerId,
741
+ // If a suspend ever fires while we're alive, the OS lock lapsed — re-assert
742
+ // our block-mode systemd-inhibit so the next idle window stays covered.
743
+ onSuspendWhileAlive: () => { stopSystemdInhibit(); startSystemdInhibit(); },
744
+ });
736
745
 
737
746
  // Boot-time detection 1: surface `claude` binary resolution so a missing
738
747
  // install becomes visible to the renderer instead of failing silently on
@@ -908,9 +917,14 @@ app.whenReady().then(async () => {
908
917
  watchers.attachWindow(mainWindow);
909
918
  pluginInstall.attachWindow(mainWindow);
910
919
  superagent.attachWindow(mainWindow);
920
+ kg.attachWindow(mainWindow);
911
921
  scheduler.init().catch((e) => {
912
922
  logs.writeLine({ scope: 'scheduler', level: 'error', message: 'init failed', meta: { error: e?.message } });
913
923
  });
924
+ // Knowledge Graph: watch the prompt log + register kg:* IPC. Best-effort.
925
+ try { kg.init({ logger: logs }); } catch (e) {
926
+ logs.writeLine({ scope: 'kg', level: 'error', message: 'init failed', meta: { error: e?.message } });
927
+ }
914
928
 
915
929
  // Keep the machine awake while the app is open. The scheduler polls billing
916
930
  // usage every 2 min and runs `claude -p` jobs that must survive an idle
@@ -941,7 +955,15 @@ app.whenReady().then(async () => {
941
955
  });
942
956
  });
943
957
 
944
- app.on('will-quit', () => {
958
+ // Centralized teardown. `will-quit` fires on a normal quit, but `app.exit()`
959
+ // (in-app reboot, dist-missing abort) bypasses will-quit entirely — so those
960
+ // sites must call this directly, otherwise markCleanShutdown never runs and the
961
+ // next boot misreports a clean reboot as an UNCLEAN OOM crash, and the
962
+ // powerSaveBlocker/inhibitor leak until process death.
963
+ let teardownDone = false;
964
+ function runShutdownCleanup() {
965
+ if (teardownDone) return; // idempotent — will-quit may still fire after an app.exit path
966
+ teardownDone = true;
945
967
  // Mark a clean exit so the next boot can distinguish a graceful quit from an
946
968
  // OOM-kill / native crash (which leaves the sentinel `open`).
947
969
  crashDiagnostics.markCleanShutdown();
@@ -953,7 +975,9 @@ app.on('will-quit', () => {
953
975
  powerBlockerId = -1;
954
976
  }
955
977
  stopSystemdInhibit();
956
- });
978
+ }
979
+
980
+ app.on('will-quit', runShutdownCleanup);
957
981
 
958
982
  app.on('window-all-closed', () => {
959
983
  if (rebooting) return; // new window is about to be created
Binary file
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * memoryTool.cjs — Memory tab backend (cycle 3, Bundle C).
3
3
  *
4
- * Workspace-scoped markdown store at
5
- * ~/.claude/session-manager/memories/<workspace>/
6
- * where <workspace> is a derived encoding of an active cwd (mirrors the
7
- * Claude-Code transcript-dir convention). The Memory tab is a list+detail
4
+ * Workspace-scoped markdown store at Claude's native auto-memory location:
5
+ * ~/.claude/projects/<workspace>/memory/
6
+ * where <workspace> is a derived encoding of an active cwd (the same
7
+ * transcript-dir slug Claude Code uses). The Memory tab is a list+detail
8
8
  * view over these files. Files are plain markdown with optional frontmatter:
9
9
  *
10
10
  * ---
@@ -37,11 +37,17 @@ const SLUG_RE = /^[a-z0-9-_]+\.md$/;
37
37
  const { encodeCwd: encodeWorkspace } = require('./lib/encodeCwd.cjs');
38
38
 
39
39
  function memoryRoot() {
40
- return path.join(os.homedir(), '.claude', 'session-manager', 'memories');
40
+ return path.join(os.homedir(), '.claude', 'projects');
41
41
  }
42
42
 
43
43
  function workspaceDir(workspace) {
44
- return path.join(memoryRoot(), workspace);
44
+ // Repointed at Claude's native auto-memory store:
45
+ // ~/.claude/projects/<encodedCwd>/memory/
46
+ // where <encodedCwd> is the same transcript-dir slug produced by encodeCwd.
47
+ // Reads AND writes target this dir so the user's real memories (incl. the
48
+ // Claude-managed MEMORY.md index) appear in the Memory tab, and new entries
49
+ // land where Claude actually reads them.
50
+ return path.join(memoryRoot(), workspace, 'memory');
45
51
  }
46
52
 
47
53
  /**
@@ -1025,6 +1025,53 @@ export interface SessionManagerAPI {
1025
1025
  stop: (tabId: string) => Promise<{ ok: boolean }>;
1026
1026
  onStateChanged: (handler: (ev: SuperAgentStateChangedEvent) => void) => () => void;
1027
1027
  };
1028
+ kg: {
1029
+ /** Distilled knowledge graph + ingest status over the prompt log. */
1030
+ get: () => Promise<KgState>;
1031
+ /** Process new prompt-log lines into the graph (incremental). */
1032
+ ingest: () => Promise<{ ok: boolean; added?: number; nodes?: number; edges?: number; error?: string; note?: string }>;
1033
+ /** Ask a question answered from the graph + your real prompts via claude -p. */
1034
+ ask: (question: string) => Promise<{ ok: boolean; answer?: string; cited?: { ts: string; prompt: string }[]; error?: string }>;
1035
+ onIngestProgress: (handler: (ev: KgIngestProgress) => void) => () => void;
1036
+ };
1037
+ }
1038
+
1039
+ export interface KgNode {
1040
+ id: string;
1041
+ key: string;
1042
+ name: string;
1043
+ type: string;
1044
+ description: string;
1045
+ count: number;
1046
+ firstTs: string | null;
1047
+ lastTs: string | null;
1048
+ }
1049
+ export interface KgEdge {
1050
+ src: string;
1051
+ dst: string;
1052
+ relation: string;
1053
+ weight: number;
1054
+ lastTs: string | null;
1055
+ }
1056
+ export interface KgState {
1057
+ nodes: KgNode[];
1058
+ edges: KgEdge[];
1059
+ status: {
1060
+ promptCount: number;
1061
+ totalPrompts: number;
1062
+ pending: number;
1063
+ lastIngest: string | null;
1064
+ ingesting: boolean;
1065
+ logPath: string;
1066
+ };
1067
+ }
1068
+ export interface KgIngestProgress {
1069
+ phase: 'start' | 'extract' | 'done' | 'error';
1070
+ ingesting: boolean;
1071
+ batch?: number;
1072
+ totalBatches?: number;
1073
+ added?: number;
1074
+ error?: string;
1028
1075
  }
1029
1076
 
1030
1077
  declare global {
@@ -279,4 +279,15 @@ contextBridge.exposeInMainWorld('api', {
279
279
  return () => ipcRenderer.removeListener('superagent:state-changed', listener);
280
280
  },
281
281
  },
282
+ kg: {
283
+ /** Knowledge Graph distilled from the prompt log (~/.claude/knowledge-log). */
284
+ get: () => ipcRenderer.invoke('kg:get'),
285
+ ingest: () => ipcRenderer.invoke('kg:ingest'),
286
+ ask: (question) => ipcRenderer.invoke('kg:ask', { question }),
287
+ onIngestProgress: (handler) => {
288
+ const listener = (_e, payload) => handler(payload);
289
+ ipcRenderer.on('kg:ingest-progress', listener);
290
+ return () => ipcRenderer.removeListener('kg:ingest-progress', listener);
291
+ },
292
+ },
282
293
  });