claude-code-session-manager 0.13.0 → 0.14.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 (43) hide show
  1. package/dist/assets/{TiptapBody-ZBlGHTXg.js → TiptapBody-CzNkD0kT.js} +1 -1
  2. package/dist/assets/{cssMode-Co9Kuq5g.js → cssMode-DUMBBgBO.js} +1 -1
  3. package/dist/assets/{freemarker2-B9Y0PjVt.js → freemarker2-BjnoO8uS.js} +1 -1
  4. package/dist/assets/{handlebars-BGL0s1rN.js → handlebars-CggfdTjZ.js} +1 -1
  5. package/dist/assets/{html-C8BuG-2M.js → html-Bcnp_pNA.js} +1 -1
  6. package/dist/assets/{htmlMode-BfCigMol.js → htmlMode-CFws8rf5.js} +1 -1
  7. package/dist/assets/{index-CkI_4Vt7.js → index-0geebEag.js} +1684 -1383
  8. package/dist/assets/{index-DewIHWBs.css → index-DOo1Vtox.css} +1 -1
  9. package/dist/assets/{javascript-sES7Ewin.js → javascript-DI4e0TwT.js} +1 -1
  10. package/dist/assets/{jsonMode-C7txz4wN.js → jsonMode-Ca0fgEAF.js} +1 -1
  11. package/dist/assets/{liquid-B4qxgigx.js → liquid-E7hk4hx9.js} +1 -1
  12. package/dist/assets/{lspLanguageFeatures-B5xgGS7m.js → lspLanguageFeatures-Wh7EFavn.js} +1 -1
  13. package/dist/assets/{mdx-De-8TTNY.js → mdx-iXIhpMBJ.js} +1 -1
  14. package/dist/assets/{python-SfayDkVl.js → python-laxy9eG1.js} +1 -1
  15. package/dist/assets/{razor-BRCdaeYo.js → razor-CatPL_eG.js} +1 -1
  16. package/dist/assets/{tsMode-DBTPpTr8.js → tsMode-D2WL55Cf.js} +1 -1
  17. package/dist/assets/{typescript-Bxbq3Vd7.js → typescript-B5DFbVoi.js} +1 -1
  18. package/dist/assets/{xml-DQBPiVNP.js → xml-BsStStQW.js} +1 -1
  19. package/dist/assets/{yaml-lyIgZXXz.js → yaml-rg2IIDpu.js} +1 -1
  20. package/dist/index.html +2 -2
  21. package/package.json +2 -1
  22. package/src/main/__tests__/runVerify.test.cjs +388 -0
  23. package/src/main/config.cjs +1 -7
  24. package/src/main/files.cjs +4 -37
  25. package/src/main/historyAggregator.cjs +37 -14
  26. package/src/main/index.cjs +53 -134
  27. package/src/main/ipcSchemas.cjs +4 -0
  28. package/src/main/lib/childWithLog.cjs +218 -0
  29. package/src/main/lib/expandHome.cjs +21 -0
  30. package/src/main/lib/insideHome.cjs +74 -21
  31. package/src/main/lib/openExternalApp.cjs +141 -0
  32. package/src/main/pluginInstall.cjs +39 -1
  33. package/src/main/pty.cjs +11 -4
  34. package/src/main/queueOps.cjs +2 -2
  35. package/src/main/runVerify.cjs +527 -0
  36. package/src/main/scheduler.cjs +335 -286
  37. package/src/main/search.cjs +1 -6
  38. package/src/main/superagent.cjs +10 -0
  39. package/src/main/supervisor.cjs +16 -8
  40. package/src/main/transcripts.cjs +6 -0
  41. package/src/main/watchers.cjs +2 -2
  42. package/src/preload/api.d.ts +16 -7
  43. package/src/preload/index.cjs +1 -0
@@ -53,12 +53,7 @@ function probeRipgrep() {
53
53
  }
54
54
 
55
55
  // ── helpers ───────────────────────────────────────────────────────────────
56
- function expandHome(p) {
57
- if (!p) return p;
58
- if (p === '~') return os.homedir();
59
- if (p.startsWith('~/')) return path.join(os.homedir(), p.slice(2));
60
- return p;
61
- }
56
+ const { expandHome } = require('./lib/expandHome.cjs');
62
57
 
63
58
  /**
64
59
  * Spawn rg with argv (no shell), capture stdout/stderr, enforce TIMEOUT_MS.
@@ -176,6 +176,15 @@ function getStatus(tabId) {
176
176
  return runs.get(tabId) ?? null;
177
177
  }
178
178
 
179
+ function dropTab(tabId) {
180
+ if (runs.has(tabId)) {
181
+ runs.delete(tabId);
182
+ if (process.env.SM_DEBUG_LEAKS === '1') {
183
+ console.log('[superagent] dropTab', tabId, 'runs.size=', runs.size);
184
+ }
185
+ }
186
+ }
187
+
179
188
  function registerSuperAgentHandlers() {
180
189
  ipcMain.handle('superagent:start', (_e, payload) => {
181
190
  const parsed = schemas.superagentStart.parse(payload);
@@ -196,6 +205,7 @@ function registerSuperAgentHandlers() {
196
205
  module.exports = {
197
206
  attachWindow,
198
207
  registerSuperAgentHandlers,
208
+ dropTab,
199
209
  // Exposed for tests.
200
210
  buildBossPrompt,
201
211
  _runs: runs,
@@ -154,15 +154,23 @@ function appendSupervisorLog(entry) {
154
154
  }
155
155
 
156
156
  function readSupervisorLog(n) {
157
- try {
158
- const text = fs.readFileSync(SUPERVISOR_LOG_PATH, 'utf8');
159
- const lines = text.split('\n').filter((l) => l.trim());
160
- return lines.slice(-n).map((l) => {
161
- try { return JSON.parse(l); } catch { return null; }
162
- }).filter(Boolean).reverse();
163
- } catch {
164
- return [];
157
+ const lines = [];
158
+ for (const p of [SUPERVISOR_LOG_PATH + '.1', SUPERVISOR_LOG_PATH]) {
159
+ let stat;
160
+ try { stat = fs.statSync(p); } catch { continue; }
161
+ // Sanity-cap: skip any file larger than the rotation ceiling.
162
+ // The rotated file is bounded to SUPERVISOR_LOG_MAX_BYTES by policy;
163
+ // anything larger indicates corruption or a hand-edit — skip it.
164
+ if (stat.size > 2 * SUPERVISOR_LOG_MAX_BYTES) continue;
165
+ try {
166
+ const t = fs.readFileSync(p, 'utf8');
167
+ for (const l of t.split('\n')) if (l.trim()) lines.push(l);
168
+ } catch { /* file vanished between stat and read — skip */ }
165
169
  }
170
+ return lines.slice(-n)
171
+ .map((l) => { try { return JSON.parse(l); } catch { return null; } })
172
+ .filter(Boolean)
173
+ .reverse();
166
174
  }
167
175
 
168
176
  // ─── Probe ──────────────────────────────────────────────────────────────────
@@ -160,6 +160,12 @@ const MAX_TRANSCRIPT_SUBS = 20;
160
160
  async function subscribe({ tabId, cwd, sessionUuid }) {
161
161
  if (subs.has(tabId)) return { ok: true, path: subs.get(tabId).filePath };
162
162
  if (subs.size >= MAX_TRANSCRIPT_SUBS) {
163
+ logs.writeLine({
164
+ level: 'warn',
165
+ scope: 'transcripts',
166
+ message: 'subscribe rejected: at cap',
167
+ meta: { tabId, cap: MAX_TRANSCRIPT_SUBS, cwd },
168
+ });
163
169
  return { ok: false, path: null, error: 'too many active subscriptions' };
164
170
  }
165
171
  const filePath = transcriptPath(cwd, sessionUuid);
@@ -15,7 +15,7 @@ const path = require('node:path');
15
15
  const os = require('node:os');
16
16
  const fs = require('node:fs');
17
17
  const { cleanChildEnv } = require('./lib/cleanEnv.cjs');
18
- const { assertCwdInsideHome } = require('./lib/insideHome.cjs');
18
+ const { checkInsideHome } = require('./lib/insideHome.cjs');
19
19
  const { sendIfAlive } = require('./lib/sendToRenderer.cjs');
20
20
 
21
21
  // Splits a readable stream into lines capped at maxLineBytes. Prevents OOM
@@ -61,7 +61,7 @@ class WatcherManager {
61
61
  add({ tabId, label, command, cwd }) {
62
62
  const resolvedCwd = cwd || process.cwd();
63
63
 
64
- const r = assertCwdInsideHome(resolvedCwd);
64
+ const r = checkInsideHome(resolvedCwd);
65
65
  if (!r.ok) throw new Error(`watcher ${r.error}`);
66
66
 
67
67
  const watcherId = crypto.randomUUID();
@@ -75,7 +75,8 @@ export interface TranscriptEvent {
75
75
 
76
76
  export interface SubscribeResult {
77
77
  ok: boolean;
78
- path: string;
78
+ path: string | null;
79
+ error?: string;
79
80
  }
80
81
 
81
82
  export interface PersistedTab {
@@ -245,7 +246,7 @@ export interface ScheduleConfig {
245
246
  schemaVersion: 1;
246
247
  }
247
248
 
248
- export type ScheduleJobStatus = 'pending' | 'running' | 'completed' | 'failed';
249
+ export type ScheduleJobStatus = 'pending' | 'running' | 'completed' | 'failed' | 'needs_review';
249
250
 
250
251
  export interface ScheduleJobRuntime {
251
252
  pid: number;
@@ -275,6 +276,14 @@ export interface ScheduleJob {
275
276
  * transcript even after restart. */
276
277
  sessionId?: string;
277
278
  runtime?: ScheduleJobRuntime;
279
+ /**
280
+ * Set when the post-run verifier downgrades the job.
281
+ * Values: 'halt' | 'deps_unmet' | 'transcript_errors' | 'verify_unavailable'
282
+ * Cleared when the job is reset to 'pending'.
283
+ */
284
+ verifierVerdict?: string;
285
+ /** Per-job values carried in queue.json for dependency checking. */
286
+ dependsOn?: string[];
278
287
  }
279
288
 
280
289
  export interface SchedulePaths {
@@ -743,16 +752,16 @@ export interface SessionManagerAPI {
743
752
  homeSelfCheck: () => Promise<{ ok: boolean; error?: string; realCwd?: string }>;
744
753
  onNewSession: (handler: () => void) => () => void;
745
754
  onRebootSession: (handler: () => void) => () => void;
746
- openInEditor: (cwd: string, editor?: string | null) => Promise<{ ok: boolean; editor?: string; error?: string }>;
755
+ openInEditor: (cwd: string, editor?: string | null) => Promise<{ ok: boolean; opener?: string; error?: string }>;
747
756
  /** Open an http/https URL in the OS default browser. file://, javascript:,
748
757
  * and other schemes are rejected with `ok:false` to prevent abuse. */
749
758
  openExternal: (url: string) => Promise<{ ok: boolean; error?: string }>;
750
759
  /** Open a specific file at line:col in the user's editor. Editors with
751
760
  * goto-line support (code/cursor/subl) get the `-g file:line:col` form;
752
- * others open the file alone. */
753
- openFileInEditor: (filePath: string, line?: number, col?: number, editor?: string | null) => Promise<{ ok: boolean; editor?: string; error?: string }>;
754
- openInFinder: (cwd: string) => Promise<{ ok: boolean; error?: string }>;
755
- openInTerminal: (cwd: string) => Promise<{ ok: boolean; terminal?: string; error?: string }>;
761
+ * others open the file alone. Image files are routed to the OS default viewer. */
762
+ openFileInEditor: (filePath: string, line?: number, col?: number, editor?: string | null) => Promise<{ ok: boolean; opener?: string; error?: string }>;
763
+ openInFinder: (cwd: string) => Promise<{ ok: boolean; opener?: string; error?: string }>;
764
+ openInTerminal: (cwd: string) => Promise<{ ok: boolean; opener?: string; error?: string }>;
756
765
  archiveProject: (encoded: string) => Promise<{ ok: boolean; error?: string }>;
757
766
  };
758
767
  pty: {
@@ -211,6 +211,7 @@ contextBridge.exposeInMainWorld('api', {
211
211
  },
212
212
  plugins: {
213
213
  install: (payload) => ipcRenderer.invoke('plugins:install', payload),
214
+ abort: (slug) => ipcRenderer.invoke('plugins:abort', slug),
214
215
  onInstallProgress: (handler) => {
215
216
  const listener = (_e, payload) => handler(payload);
216
217
  ipcRenderer.on('plugins:install-progress', listener);