claude-threads 1.9.2 → 1.9.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/dist/index.js CHANGED
@@ -11747,76 +11747,6 @@ var require_ws = __commonJS((exports, module) => {
11747
11747
  module.exports = WebSocket;
11748
11748
  });
11749
11749
 
11750
- // src/utils/emoji.ts
11751
- var exports_emoji = {};
11752
- __export(exports_emoji, {
11753
- isResumeEmoji: () => isResumeEmoji,
11754
- isMinimizeToggleEmoji: () => isMinimizeToggleEmoji,
11755
- isEscapeEmoji: () => isEscapeEmoji,
11756
- isDenialEmoji: () => isDenialEmoji,
11757
- isCancelEmoji: () => isCancelEmoji,
11758
- isBugReportEmoji: () => isBugReportEmoji,
11759
- isApprovalEmoji: () => isApprovalEmoji,
11760
- isAllowAllEmoji: () => isAllowAllEmoji,
11761
- getNumberEmojiIndex: () => getNumberEmojiIndex,
11762
- RESUME_EMOJIS: () => RESUME_EMOJIS,
11763
- NUMBER_EMOJIS: () => NUMBER_EMOJIS,
11764
- MINIMIZE_TOGGLE_EMOJIS: () => MINIMIZE_TOGGLE_EMOJIS,
11765
- ESCAPE_EMOJIS: () => ESCAPE_EMOJIS,
11766
- DENIAL_EMOJIS: () => DENIAL_EMOJIS,
11767
- CANCEL_EMOJIS: () => CANCEL_EMOJIS,
11768
- BUG_REPORT_EMOJI: () => BUG_REPORT_EMOJI,
11769
- APPROVAL_EMOJIS: () => APPROVAL_EMOJIS,
11770
- ALLOW_ALL_EMOJIS: () => ALLOW_ALL_EMOJIS
11771
- });
11772
- function isApprovalEmoji(emoji) {
11773
- return APPROVAL_EMOJIS.includes(emoji);
11774
- }
11775
- function isDenialEmoji(emoji) {
11776
- return DENIAL_EMOJIS.includes(emoji);
11777
- }
11778
- function isAllowAllEmoji(emoji) {
11779
- return ALLOW_ALL_EMOJIS.includes(emoji);
11780
- }
11781
- function isCancelEmoji(emoji) {
11782
- return CANCEL_EMOJIS.includes(emoji);
11783
- }
11784
- function isEscapeEmoji(emoji) {
11785
- return ESCAPE_EMOJIS.includes(emoji);
11786
- }
11787
- function isResumeEmoji(emoji) {
11788
- return RESUME_EMOJIS.includes(emoji);
11789
- }
11790
- function isMinimizeToggleEmoji(emoji) {
11791
- return MINIMIZE_TOGGLE_EMOJIS.includes(emoji);
11792
- }
11793
- function isBugReportEmoji(emoji) {
11794
- return emoji === BUG_REPORT_EMOJI || emoji === "\uD83D\uDC1B";
11795
- }
11796
- function getNumberEmojiIndex(emoji) {
11797
- const textIndex = NUMBER_EMOJIS.indexOf(emoji);
11798
- if (textIndex >= 0)
11799
- return textIndex;
11800
- return UNICODE_NUMBER_EMOJIS[emoji] ?? -1;
11801
- }
11802
- var APPROVAL_EMOJIS, DENIAL_EMOJIS, ALLOW_ALL_EMOJIS, NUMBER_EMOJIS, CANCEL_EMOJIS, ESCAPE_EMOJIS, RESUME_EMOJIS, MINIMIZE_TOGGLE_EMOJIS, BUG_REPORT_EMOJI = "bug", UNICODE_NUMBER_EMOJIS;
11803
- var init_emoji = __esm(() => {
11804
- APPROVAL_EMOJIS = ["+1", "thumbsup"];
11805
- DENIAL_EMOJIS = ["-1", "thumbsdown"];
11806
- ALLOW_ALL_EMOJIS = ["white_check_mark", "heavy_check_mark"];
11807
- NUMBER_EMOJIS = ["one", "two", "three", "four"];
11808
- CANCEL_EMOJIS = ["x", "octagonal_sign", "stop_sign", "stop"];
11809
- ESCAPE_EMOJIS = ["double_vertical_bar", "pause_button", "pause"];
11810
- RESUME_EMOJIS = ["arrows_counterclockwise", "arrow_forward", "repeat"];
11811
- MINIMIZE_TOGGLE_EMOJIS = ["arrow_down_small", "small_red_triangle_down"];
11812
- UNICODE_NUMBER_EMOJIS = {
11813
- "1️⃣": 0,
11814
- "2️⃣": 1,
11815
- "3️⃣": 2,
11816
- "4️⃣": 3
11817
- };
11818
- });
11819
-
11820
11750
  // src/utils/spawn.ts
11821
11751
  import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "child_process";
11822
11752
  function addWindowsShell(options2) {
@@ -12161,6 +12091,76 @@ var init_worktree = __esm(() => {
12161
12091
  METADATA_STORE_PATH = path.join(homedir4(), ".claude-threads", "worktree-metadata.json");
12162
12092
  });
12163
12093
 
12094
+ // src/utils/emoji.ts
12095
+ var exports_emoji = {};
12096
+ __export(exports_emoji, {
12097
+ isResumeEmoji: () => isResumeEmoji,
12098
+ isMinimizeToggleEmoji: () => isMinimizeToggleEmoji,
12099
+ isEscapeEmoji: () => isEscapeEmoji,
12100
+ isDenialEmoji: () => isDenialEmoji,
12101
+ isCancelEmoji: () => isCancelEmoji,
12102
+ isBugReportEmoji: () => isBugReportEmoji,
12103
+ isApprovalEmoji: () => isApprovalEmoji,
12104
+ isAllowAllEmoji: () => isAllowAllEmoji,
12105
+ getNumberEmojiIndex: () => getNumberEmojiIndex,
12106
+ RESUME_EMOJIS: () => RESUME_EMOJIS,
12107
+ NUMBER_EMOJIS: () => NUMBER_EMOJIS,
12108
+ MINIMIZE_TOGGLE_EMOJIS: () => MINIMIZE_TOGGLE_EMOJIS,
12109
+ ESCAPE_EMOJIS: () => ESCAPE_EMOJIS,
12110
+ DENIAL_EMOJIS: () => DENIAL_EMOJIS,
12111
+ CANCEL_EMOJIS: () => CANCEL_EMOJIS,
12112
+ BUG_REPORT_EMOJI: () => BUG_REPORT_EMOJI,
12113
+ APPROVAL_EMOJIS: () => APPROVAL_EMOJIS,
12114
+ ALLOW_ALL_EMOJIS: () => ALLOW_ALL_EMOJIS
12115
+ });
12116
+ function isApprovalEmoji(emoji) {
12117
+ return APPROVAL_EMOJIS.includes(emoji);
12118
+ }
12119
+ function isDenialEmoji(emoji) {
12120
+ return DENIAL_EMOJIS.includes(emoji);
12121
+ }
12122
+ function isAllowAllEmoji(emoji) {
12123
+ return ALLOW_ALL_EMOJIS.includes(emoji);
12124
+ }
12125
+ function isCancelEmoji(emoji) {
12126
+ return CANCEL_EMOJIS.includes(emoji);
12127
+ }
12128
+ function isEscapeEmoji(emoji) {
12129
+ return ESCAPE_EMOJIS.includes(emoji);
12130
+ }
12131
+ function isResumeEmoji(emoji) {
12132
+ return RESUME_EMOJIS.includes(emoji);
12133
+ }
12134
+ function isMinimizeToggleEmoji(emoji) {
12135
+ return MINIMIZE_TOGGLE_EMOJIS.includes(emoji);
12136
+ }
12137
+ function isBugReportEmoji(emoji) {
12138
+ return emoji === BUG_REPORT_EMOJI || emoji === "\uD83D\uDC1B";
12139
+ }
12140
+ function getNumberEmojiIndex(emoji) {
12141
+ const textIndex = NUMBER_EMOJIS.indexOf(emoji);
12142
+ if (textIndex >= 0)
12143
+ return textIndex;
12144
+ return UNICODE_NUMBER_EMOJIS[emoji] ?? -1;
12145
+ }
12146
+ var APPROVAL_EMOJIS, DENIAL_EMOJIS, ALLOW_ALL_EMOJIS, NUMBER_EMOJIS, CANCEL_EMOJIS, ESCAPE_EMOJIS, RESUME_EMOJIS, MINIMIZE_TOGGLE_EMOJIS, BUG_REPORT_EMOJI = "bug", UNICODE_NUMBER_EMOJIS;
12147
+ var init_emoji = __esm(() => {
12148
+ APPROVAL_EMOJIS = ["+1", "thumbsup"];
12149
+ DENIAL_EMOJIS = ["-1", "thumbsdown"];
12150
+ ALLOW_ALL_EMOJIS = ["white_check_mark", "heavy_check_mark"];
12151
+ NUMBER_EMOJIS = ["one", "two", "three", "four"];
12152
+ CANCEL_EMOJIS = ["x", "octagonal_sign", "stop_sign", "stop"];
12153
+ ESCAPE_EMOJIS = ["double_vertical_bar", "pause_button", "pause"];
12154
+ RESUME_EMOJIS = ["arrows_counterclockwise", "arrow_forward", "repeat"];
12155
+ MINIMIZE_TOGGLE_EMOJIS = ["arrow_down_small", "small_red_triangle_down"];
12156
+ UNICODE_NUMBER_EMOJIS = {
12157
+ "1️⃣": 0,
12158
+ "2️⃣": 1,
12159
+ "3️⃣": 2,
12160
+ "4️⃣": 3
12161
+ };
12162
+ });
12163
+
12164
12164
  // node_modules/pend/index.js
12165
12165
  var require_pend = __commonJS((exports, module) => {
12166
12166
  module.exports = Pend;
@@ -19496,7 +19496,7 @@ var require_react_reconciler_development = __commonJS((exports, module) => {
19496
19496
  return hook.checkDCE ? true : false;
19497
19497
  }
19498
19498
  function setIsStrictModeForDevtools(newIsStrictMode) {
19499
- typeof log30 === "function" && unstable_setDisableYieldValue2(newIsStrictMode);
19499
+ typeof log32 === "function" && unstable_setDisableYieldValue2(newIsStrictMode);
19500
19500
  if (injectedHook && typeof injectedHook.setStrictMode === "function")
19501
19501
  try {
19502
19502
  injectedHook.setStrictMode(rendererID, newIsStrictMode);
@@ -22381,7 +22381,7 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
22381
22381
  if (queue === null)
22382
22382
  throw Error("Should have a queue. You are likely calling Hooks conditionally, which is not allowed. (https://react.dev/link/invalid-hook-call)");
22383
22383
  queue.lastRenderedReducer = reducer;
22384
- var { dispatch, pending: lastRenderPhaseUpdate } = queue, newState = hook.memoizedState;
22384
+ var { dispatch: dispatch2, pending: lastRenderPhaseUpdate } = queue, newState = hook.memoizedState;
22385
22385
  if (lastRenderPhaseUpdate !== null) {
22386
22386
  queue.pending = null;
22387
22387
  var update = lastRenderPhaseUpdate = lastRenderPhaseUpdate.next;
@@ -22393,7 +22393,7 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
22393
22393
  hook.baseQueue === null && (hook.baseState = newState);
22394
22394
  queue.lastRenderedState = newState;
22395
22395
  }
22396
- return [newState, dispatch];
22396
+ return [newState, dispatch2];
22397
22397
  }
22398
22398
  function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) {
22399
22399
  var fiber = currentlyRenderingFiber, hook = mountWorkInProgressHook();
@@ -22497,9 +22497,9 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
22497
22497
  }
22498
22498
  function mountState(initialState) {
22499
22499
  initialState = mountStateImpl(initialState);
22500
- var queue = initialState.queue, dispatch = dispatchSetState.bind(null, currentlyRenderingFiber, queue);
22501
- queue.dispatch = dispatch;
22502
- return [initialState.memoizedState, dispatch];
22500
+ var queue = initialState.queue, dispatch2 = dispatchSetState.bind(null, currentlyRenderingFiber, queue);
22501
+ queue.dispatch = dispatch2;
22502
+ return [initialState.memoizedState, dispatch2];
22503
22503
  }
22504
22504
  function mountOptimistic(passthrough) {
22505
22505
  var hook = mountWorkInProgressHook();
@@ -22678,9 +22678,9 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
22678
22678
  else
22679
22679
  state = currentStateHook;
22680
22680
  currentStateHook = updateWorkInProgressHook();
22681
- var actionQueue = currentStateHook.queue, dispatch = actionQueue.dispatch;
22681
+ var actionQueue = currentStateHook.queue, dispatch2 = actionQueue.dispatch;
22682
22682
  action !== currentStateHook.memoizedState && (currentlyRenderingFiber.flags |= 2048, pushSimpleEffect(HasEffect | Passive, { destroy: undefined }, actionStateActionEffect.bind(null, actionQueue, action), null));
22683
- return [state, dispatch, stateHook];
22683
+ return [state, dispatch2, stateHook];
22684
22684
  }
22685
22685
  function actionStateActionEffect(actionQueue, action) {
22686
22686
  actionQueue.action = action;
@@ -22692,9 +22692,9 @@ Incoming: %s`, currentHookNameInDev, "[" + prevDeps.join(", ") + "]", "[" + next
22692
22692
  updateWorkInProgressHook();
22693
22693
  stateHook = stateHook.memoizedState;
22694
22694
  currentStateHook = updateWorkInProgressHook();
22695
- var dispatch = currentStateHook.queue.dispatch;
22695
+ var dispatch2 = currentStateHook.queue.dispatch;
22696
22696
  currentStateHook.memoizedState = action;
22697
- return [stateHook, dispatch, false];
22697
+ return [stateHook, dispatch2, false];
22698
22698
  }
22699
22699
  function pushSimpleEffect(tag, inst, create, deps) {
22700
22700
  tag = { tag, create, deps, inst, next: null };
@@ -27580,7 +27580,7 @@ Check the render method of %s.`, getComponentNameFromFiber(current) || "Unknown"
27580
27580
  var fiberStack = [];
27581
27581
  var index$jscomp$0 = -1, emptyContextObject = {};
27582
27582
  Object.freeze(emptyContextObject);
27583
- var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log$1 = Math.log, LN2 = Math.LN2, nextTransitionUpdateLane = 256, nextTransitionDeferredLane = 262144, nextRetryLane = 4194304, scheduleCallback$3 = Scheduler.unstable_scheduleCallback, cancelCallback$1 = Scheduler.unstable_cancelCallback, shouldYield = Scheduler.unstable_shouldYield, requestPaint = Scheduler.unstable_requestPaint, now$1 = Scheduler.unstable_now, ImmediatePriority = Scheduler.unstable_ImmediatePriority, UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, NormalPriority$1 = Scheduler.unstable_NormalPriority, IdlePriority = Scheduler.unstable_IdlePriority, log30 = Scheduler.log, unstable_setDisableYieldValue2 = Scheduler.unstable_setDisableYieldValue, rendererID = null, injectedHook = null, hasLoggedError = false, isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined", lastResetTime = 0;
27583
+ var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback, log$1 = Math.log, LN2 = Math.LN2, nextTransitionUpdateLane = 256, nextTransitionDeferredLane = 262144, nextRetryLane = 4194304, scheduleCallback$3 = Scheduler.unstable_scheduleCallback, cancelCallback$1 = Scheduler.unstable_cancelCallback, shouldYield = Scheduler.unstable_shouldYield, requestPaint = Scheduler.unstable_requestPaint, now$1 = Scheduler.unstable_now, ImmediatePriority = Scheduler.unstable_ImmediatePriority, UserBlockingPriority = Scheduler.unstable_UserBlockingPriority, NormalPriority$1 = Scheduler.unstable_NormalPriority, IdlePriority = Scheduler.unstable_IdlePriority, log32 = Scheduler.log, unstable_setDisableYieldValue2 = Scheduler.unstable_setDisableYieldValue, rendererID = null, injectedHook = null, hasLoggedError = false, isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined", lastResetTime = 0;
27584
27584
  if (typeof performance === "object" && typeof performance.now === "function") {
27585
27585
  var localPerformance = performance;
27586
27586
  var getCurrentTime = function() {
@@ -53750,9 +53750,6 @@ class AccountPool {
53750
53750
  }
53751
53751
  }
53752
53752
 
53753
- // src/session/manager.ts
53754
- init_emoji();
53755
-
53756
53753
  // src/cleanup/scheduler.ts
53757
53754
  init_logger();
53758
53755
  import { existsSync as existsSync7 } from "fs";
@@ -54213,6 +54210,50 @@ class CleanupScheduler {
54213
54210
  // src/operations/monitor/handler.ts
54214
54211
  init_logger();
54215
54212
 
54213
+ // src/session/lifecycle-fsm.ts
54214
+ init_logger();
54215
+ var log9 = createLogger("fsm");
54216
+ var ALLOWED_TRANSITIONS = {
54217
+ starting: new Set(["active", "paused", "interrupted", "cancelling", "restarting"]),
54218
+ active: new Set([
54219
+ "active",
54220
+ "processing",
54221
+ "paused",
54222
+ "interrupted",
54223
+ "restarting",
54224
+ "cancelling",
54225
+ "ending"
54226
+ ]),
54227
+ processing: new Set([
54228
+ "active",
54229
+ "paused",
54230
+ "interrupted",
54231
+ "restarting",
54232
+ "cancelling"
54233
+ ]),
54234
+ paused: new Set(["active", "cancelling", "restarting"]),
54235
+ interrupted: new Set(["active", "cancelling", "restarting", "paused"]),
54236
+ restarting: new Set(["active", "paused", "cancelling"]),
54237
+ cancelling: new Set(["ending"]),
54238
+ ending: new Set
54239
+ };
54240
+ function checkTransition(from, to, sessionId) {
54241
+ const allowed = ALLOWED_TRANSITIONS[from];
54242
+ if (allowed.has(to))
54243
+ return;
54244
+ const msg = `illegal lifecycle transition ${from} -> ${to}`;
54245
+ const payload = {
54246
+ event: "fsm.illegal_transition",
54247
+ from,
54248
+ to,
54249
+ sessionId
54250
+ };
54251
+ if (process.env.CLAUDE_THREADS_FSM_STRICT === "1") {
54252
+ throw new Error(`${msg} (sessionId=${sessionId})`);
54253
+ }
54254
+ log9.warn(msg, payload);
54255
+ }
54256
+
54216
54257
  // src/session/timer-manager.ts
54217
54258
  function createSessionTimers() {
54218
54259
  return {
@@ -54258,6 +54299,7 @@ function isSessionCancelled(session) {
54258
54299
  return session.lifecycle.state === "cancelling";
54259
54300
  }
54260
54301
  function transitionTo(session, newState) {
54302
+ checkTransition(session.lifecycle.state, newState, session.sessionId);
54261
54303
  session.lifecycle.state = newState;
54262
54304
  }
54263
54305
  function markClaudeResponded(session) {
@@ -54345,7 +54387,7 @@ function extractResetAt(text, now) {
54345
54387
  }
54346
54388
 
54347
54389
  // src/claude/cli.ts
54348
- var log9 = createLogger("claude");
54390
+ var log10 = createLogger("claude");
54349
54391
  function cleanupBrowserBridgeSockets() {
54350
54392
  try {
54351
54393
  const tempDir = tmpdir();
@@ -54357,13 +54399,13 @@ function cleanupBrowserBridgeSockets() {
54357
54399
  const stats = statSync2(filePath);
54358
54400
  if (stats.isSocket()) {
54359
54401
  unlinkSync2(filePath);
54360
- log9.debug(`Removed stale browser bridge socket: ${file}`);
54402
+ log10.debug(`Removed stale browser bridge socket: ${file}`);
54361
54403
  }
54362
54404
  } catch {}
54363
54405
  }
54364
54406
  }
54365
54407
  } catch (err) {
54366
- log9.debug(`Browser bridge cleanup failed: ${err}`);
54408
+ log10.debug(`Browser bridge cleanup failed: ${err}`);
54367
54409
  }
54368
54410
  }
54369
54411
  function buildClaudeChildEnv(parentEnv, account) {
@@ -54394,7 +54436,7 @@ function isErrorResultEvent(event) {
54394
54436
  return false;
54395
54437
  }
54396
54438
  function materializeMcpConfig(config, sessionId, opts = {}) {
54397
- if (opts.inline ?? process.env.CLAUDE_THREADS_MCP_CONFIG_INLINE === "1") {
54439
+ if (opts.inline) {
54398
54440
  return { mode: "inline", value: JSON.stringify(config) };
54399
54441
  }
54400
54442
  const dir = opts.tmpDirOverride ?? tmpdir();
@@ -55599,7 +55641,7 @@ import { existsSync as existsSync11 } from "fs";
55599
55641
  // src/utils/keep-alive.ts
55600
55642
  init_logger();
55601
55643
  import { spawn as spawn2 } from "child_process";
55602
- var log10 = createLogger("keepalive");
55644
+ var log11 = createLogger("keepalive");
55603
55645
 
55604
55646
  class KeepAliveManager {
55605
55647
  activeSessionCount = 0;
@@ -55614,7 +55656,7 @@ class KeepAliveManager {
55614
55656
  if (!enabled && this.keepAliveProcess) {
55615
55657
  this.stopKeepAlive();
55616
55658
  }
55617
- log10.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
55659
+ log11.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
55618
55660
  }
55619
55661
  isEnabled() {
55620
55662
  return this.enabled;
@@ -55624,7 +55666,7 @@ class KeepAliveManager {
55624
55666
  }
55625
55667
  sessionStarted() {
55626
55668
  this.activeSessionCount++;
55627
- log10.debug(`Session started (${this.activeSessionCount} active)`);
55669
+ log11.debug(`Session started (${this.activeSessionCount} active)`);
55628
55670
  if (this.activeSessionCount === 1) {
55629
55671
  this.startKeepAlive();
55630
55672
  }
@@ -55633,7 +55675,7 @@ class KeepAliveManager {
55633
55675
  if (this.activeSessionCount > 0) {
55634
55676
  this.activeSessionCount--;
55635
55677
  }
55636
- log10.debug(`Session ended (${this.activeSessionCount} active)`);
55678
+ log11.debug(`Session ended (${this.activeSessionCount} active)`);
55637
55679
  if (this.activeSessionCount === 0) {
55638
55680
  this.stopKeepAlive();
55639
55681
  }
@@ -55647,11 +55689,11 @@ class KeepAliveManager {
55647
55689
  }
55648
55690
  startKeepAlive() {
55649
55691
  if (!this.enabled) {
55650
- log10.debug("Keep-alive disabled, skipping");
55692
+ log11.debug("Keep-alive disabled, skipping");
55651
55693
  return;
55652
55694
  }
55653
55695
  if (this.keepAliveProcess) {
55654
- log10.debug("Keep-alive already running");
55696
+ log11.debug("Keep-alive already running");
55655
55697
  return;
55656
55698
  }
55657
55699
  switch (this.platform) {
@@ -55665,12 +55707,12 @@ class KeepAliveManager {
55665
55707
  this.startWindowsKeepAlive();
55666
55708
  break;
55667
55709
  default:
55668
- log10.warn(`Keep-alive not supported on ${this.platform}`);
55710
+ log11.warn(`Keep-alive not supported on ${this.platform}`);
55669
55711
  }
55670
55712
  }
55671
55713
  stopKeepAlive() {
55672
55714
  if (this.keepAliveProcess) {
55673
- log10.debug("Stopping keep-alive");
55715
+ log11.debug("Stopping keep-alive");
55674
55716
  this.keepAliveProcess.kill();
55675
55717
  this.keepAliveProcess = null;
55676
55718
  }
@@ -55682,18 +55724,18 @@ class KeepAliveManager {
55682
55724
  detached: false
55683
55725
  });
55684
55726
  this.keepAliveProcess.on("error", (err) => {
55685
- log10.error(`Failed to start caffeinate: ${err.message}`);
55727
+ log11.error(`Failed to start caffeinate: ${err.message}`);
55686
55728
  this.keepAliveProcess = null;
55687
55729
  });
55688
55730
  this.keepAliveProcess.on("exit", (code) => {
55689
55731
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55690
- log10.debug(`caffeinate exited with code ${code}`);
55732
+ log11.debug(`caffeinate exited with code ${code}`);
55691
55733
  }
55692
55734
  this.keepAliveProcess = null;
55693
55735
  });
55694
- log10.info("Sleep prevention active (caffeinate)");
55736
+ log11.info("Sleep prevention active (caffeinate)");
55695
55737
  } catch (err) {
55696
- log10.error(`Failed to start caffeinate: ${err}`);
55738
+ log11.error(`Failed to start caffeinate: ${err}`);
55697
55739
  }
55698
55740
  }
55699
55741
  startLinuxKeepAlive() {
@@ -55709,19 +55751,19 @@ class KeepAliveManager {
55709
55751
  detached: false
55710
55752
  });
55711
55753
  this.keepAliveProcess.on("error", (err) => {
55712
- log10.debug(`systemd-inhibit not available: ${err.message}`);
55754
+ log11.debug(`systemd-inhibit not available: ${err.message}`);
55713
55755
  this.keepAliveProcess = null;
55714
55756
  this.startLinuxKeepAliveFallback();
55715
55757
  });
55716
55758
  this.keepAliveProcess.on("exit", (code) => {
55717
55759
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55718
- log10.debug(`systemd-inhibit exited with code ${code}`);
55760
+ log11.debug(`systemd-inhibit exited with code ${code}`);
55719
55761
  }
55720
55762
  this.keepAliveProcess = null;
55721
55763
  });
55722
- log10.info("Sleep prevention active (systemd-inhibit)");
55764
+ log11.info("Sleep prevention active (systemd-inhibit)");
55723
55765
  } catch (err) {
55724
- log10.debug(`Failed to start systemd-inhibit: ${err}`);
55766
+ log11.debug(`Failed to start systemd-inhibit: ${err}`);
55725
55767
  this.startLinuxKeepAliveFallback();
55726
55768
  }
55727
55769
  }
@@ -55735,15 +55777,15 @@ class KeepAliveManager {
55735
55777
  detached: false
55736
55778
  });
55737
55779
  this.keepAliveProcess.on("error", (err) => {
55738
- log10.warn(`Linux keep-alive fallback not available: ${err.message}`);
55780
+ log11.warn(`Linux keep-alive fallback not available: ${err.message}`);
55739
55781
  this.keepAliveProcess = null;
55740
55782
  });
55741
55783
  this.keepAliveProcess.on("exit", () => {
55742
55784
  this.keepAliveProcess = null;
55743
55785
  });
55744
- log10.info("Sleep prevention active (xdg-screensaver)");
55786
+ log11.info("Sleep prevention active (xdg-screensaver)");
55745
55787
  } catch (err) {
55746
- log10.warn(`Linux keep-alive not available: ${err}`);
55788
+ log11.warn(`Linux keep-alive not available: ${err}`);
55747
55789
  }
55748
55790
  }
55749
55791
  startWindowsKeepAlive() {
@@ -55768,18 +55810,18 @@ class KeepAliveManager {
55768
55810
  windowsHide: true
55769
55811
  });
55770
55812
  this.keepAliveProcess.on("error", (err) => {
55771
- log10.warn(`Windows keep-alive not available: ${err.message}`);
55813
+ log11.warn(`Windows keep-alive not available: ${err.message}`);
55772
55814
  this.keepAliveProcess = null;
55773
55815
  });
55774
55816
  this.keepAliveProcess.on("exit", (code) => {
55775
55817
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55776
- log10.debug(`PowerShell keep-alive exited with code ${code}`);
55818
+ log11.debug(`PowerShell keep-alive exited with code ${code}`);
55777
55819
  }
55778
55820
  this.keepAliveProcess = null;
55779
55821
  });
55780
- log10.info("Sleep prevention active (SetThreadExecutionState)");
55822
+ log11.info("Sleep prevention active (SetThreadExecutionState)");
55781
55823
  } catch (err) {
55782
- log10.warn(`Windows keep-alive not available: ${err}`);
55824
+ log11.warn(`Windows keep-alive not available: ${err}`);
55783
55825
  }
55784
55826
  }
55785
55827
  }
@@ -55787,7 +55829,7 @@ var keepAlive = new KeepAliveManager;
55787
55829
 
55788
55830
  // src/utils/error-handler/index.ts
55789
55831
  init_logger();
55790
- var log11 = createLogger("error");
55832
+ var log12 = createLogger("error");
55791
55833
 
55792
55834
  class SessionError extends Error {
55793
55835
  sessionId;
@@ -55813,19 +55855,19 @@ async function handleError(error, context, severity = "recoverable") {
55813
55855
  const sessionPart = sessionId ? ` (${formatShortId(sessionId)})` : "";
55814
55856
  const logMessage = `${context.action}${sessionPart}: ${message}`;
55815
55857
  if (severity === "recoverable") {
55816
- log11.warn(logMessage);
55858
+ log12.warn(logMessage);
55817
55859
  } else {
55818
- log11.error(logMessage, error instanceof Error ? error : undefined);
55860
+ log12.error(logMessage, error instanceof Error ? error : undefined);
55819
55861
  }
55820
55862
  if (context.details) {
55821
- log11.debugJson("Error details", context.details);
55863
+ log12.debugJson("Error details", context.details);
55822
55864
  }
55823
55865
  if (context.notifyUser && context.session) {
55824
55866
  try {
55825
55867
  const fmt = context.session.platform.getFormatter();
55826
55868
  await context.session.platform.createPost(`⚠️ ${fmt.formatBold("Error")}: ${context.action} failed - ${message}`, context.session.threadId);
55827
55869
  } catch (notifyError) {
55828
- log11.warn(`Could not notify user: ${notifyError}`);
55870
+ log12.warn(`Could not notify user: ${notifyError}`);
55829
55871
  }
55830
55872
  }
55831
55873
  if (severity === "session-fatal" || severity === "system-fatal") {
@@ -55852,7 +55894,7 @@ async function logAndNotify(error, context) {
55852
55894
  }
55853
55895
  function logSilentError(context, error) {
55854
55896
  const message = error instanceof Error ? error.message : String(error);
55855
- log11.debug(`[${context}] Silently caught: ${message}`);
55897
+ log12.debug(`[${context}] Silently caught: ${message}`);
55856
55898
  }
55857
55899
 
55858
55900
  // src/session/lifecycle.ts
@@ -55872,8 +55914,8 @@ function createSessionLog(baseLog) {
55872
55914
  init_logger();
55873
55915
  init_emoji();
55874
55916
  init_worktree();
55875
- var log12 = createLogger("helpers");
55876
- var sessionLog = createSessionLog(log12);
55917
+ var log13 = createLogger("helpers");
55918
+ var sessionLog = createSessionLog(log13);
55877
55919
  var POST_TYPES = {
55878
55920
  info: "",
55879
55921
  success: "✅",
@@ -55957,7 +55999,7 @@ function updateLastMessage(session, post2) {
55957
55999
  // src/claude/quick-query.ts
55958
56000
  init_spawn();
55959
56001
  init_logger();
55960
- var log13 = createLogger("query");
56002
+ var log14 = createLogger("query");
55961
56003
  async function quickQuery(options2) {
55962
56004
  const {
55963
56005
  prompt,
@@ -55973,7 +56015,7 @@ async function quickQuery(options2) {
55973
56015
  args.push("--system-prompt", systemPrompt);
55974
56016
  }
55975
56017
  args.push(prompt);
55976
- log13.debug(`Quick query: model=${model}, timeout=${timeout}ms, prompt="${prompt.substring(0, 50)}..."`);
56018
+ log14.debug(`Quick query: model=${model}, timeout=${timeout}ms, prompt="${prompt.substring(0, 50)}..."`);
55977
56019
  return new Promise((resolve5) => {
55978
56020
  let stdout = "";
55979
56021
  let stderr = "";
@@ -55987,7 +56029,7 @@ async function quickQuery(options2) {
55987
56029
  if (!resolved) {
55988
56030
  resolved = true;
55989
56031
  proc.kill("SIGTERM");
55990
- log13.debug(`Quick query timed out after ${timeout}ms`);
56032
+ log14.debug(`Quick query timed out after ${timeout}ms`);
55991
56033
  resolve5({
55992
56034
  success: false,
55993
56035
  error: "timeout",
@@ -56005,7 +56047,7 @@ async function quickQuery(options2) {
56005
56047
  if (!resolved) {
56006
56048
  resolved = true;
56007
56049
  clearTimeout(timeoutId);
56008
- log13.debug(`Quick query error: ${err.message}`);
56050
+ log14.debug(`Quick query error: ${err.message}`);
56009
56051
  resolve5({
56010
56052
  success: false,
56011
56053
  error: err.message,
@@ -56019,14 +56061,14 @@ async function quickQuery(options2) {
56019
56061
  clearTimeout(timeoutId);
56020
56062
  const durationMs = Date.now() - startTime;
56021
56063
  if (code === 0 && stdout.trim()) {
56022
- log13.debug(`Quick query success: ${durationMs}ms, ${stdout.length} chars`);
56064
+ log14.debug(`Quick query success: ${durationMs}ms, ${stdout.length} chars`);
56023
56065
  resolve5({
56024
56066
  success: true,
56025
56067
  response: stdout.trim(),
56026
56068
  durationMs
56027
56069
  });
56028
56070
  } else {
56029
- log13.debug(`Quick query failed: code=${code}, stderr=${stderr.substring(0, 100)}`);
56071
+ log14.debug(`Quick query failed: code=${code}, stderr=${stderr.substring(0, 100)}`);
56030
56072
  resolve5({
56031
56073
  success: false,
56032
56074
  error: stderr || `exit code ${code}`,
@@ -56041,7 +56083,7 @@ async function quickQuery(options2) {
56041
56083
 
56042
56084
  // src/operations/suggestions/title.ts
56043
56085
  init_logger();
56044
- var log14 = createLogger("title");
56086
+ var log15 = createLogger("title");
56045
56087
  var SUGGESTION_TIMEOUT = 15000;
56046
56088
  var MIN_TITLE_LENGTH = 3;
56047
56089
  var MAX_TITLE_LENGTH = 50;
@@ -56105,32 +56147,32 @@ function parseMetadata(response) {
56105
56147
  const titleMatch = response.match(/TITLE:\s*(.+)/i);
56106
56148
  const descMatch = response.match(/DESC:\s*(.+)/i);
56107
56149
  if (!titleMatch || !descMatch) {
56108
- log14.debug("Failed to parse title/description from response");
56150
+ log15.debug("Failed to parse title/description from response");
56109
56151
  return null;
56110
56152
  }
56111
56153
  let title = titleMatch[1].trim();
56112
56154
  let description = descMatch[1].trim();
56113
56155
  if (title.length < MIN_TITLE_LENGTH) {
56114
- log14.debug(`Title too short: ${title.length} chars`);
56156
+ log15.debug(`Title too short: ${title.length} chars`);
56115
56157
  return null;
56116
56158
  }
56117
56159
  if (title.length > MAX_TITLE_LENGTH) {
56118
- log14.debug(`Title too long (${title.length} chars), truncating`);
56160
+ log15.debug(`Title too long (${title.length} chars), truncating`);
56119
56161
  title = truncateAtWord(title, MAX_TITLE_LENGTH);
56120
56162
  }
56121
56163
  if (description.length < MIN_DESC_LENGTH) {
56122
- log14.debug(`Description too short: ${description.length} chars`);
56164
+ log15.debug(`Description too short: ${description.length} chars`);
56123
56165
  return null;
56124
56166
  }
56125
56167
  if (description.length > MAX_DESC_LENGTH) {
56126
- log14.debug(`Description too long (${description.length} chars), truncating`);
56168
+ log15.debug(`Description too long (${description.length} chars), truncating`);
56127
56169
  description = truncateAtWord(description, MAX_DESC_LENGTH);
56128
56170
  }
56129
56171
  return { title, description };
56130
56172
  }
56131
56173
  async function suggestSessionMetadata(context) {
56132
56174
  const logContext = typeof context === "string" ? context.substring(0, 50) : context.originalTask.substring(0, 50);
56133
- log14.debug(`Suggesting title for: "${logContext}..."`);
56175
+ log15.debug(`Suggesting title for: "${logContext}..."`);
56134
56176
  try {
56135
56177
  const result = await quickQuery({
56136
56178
  prompt: buildTitlePrompt(context),
@@ -56138,23 +56180,23 @@ async function suggestSessionMetadata(context) {
56138
56180
  timeout: SUGGESTION_TIMEOUT
56139
56181
  });
56140
56182
  if (!result.success || !result.response) {
56141
- log14.debug(`Title suggestion failed: ${result.error || "no response"}`);
56183
+ log15.debug(`Title suggestion failed: ${result.error || "no response"}`);
56142
56184
  return null;
56143
56185
  }
56144
56186
  const metadata = parseMetadata(result.response);
56145
56187
  if (metadata) {
56146
- log14.debug(`Got title: "${metadata.title}" (${result.durationMs}ms)`);
56188
+ log15.debug(`Got title: "${metadata.title}" (${result.durationMs}ms)`);
56147
56189
  }
56148
56190
  return metadata;
56149
56191
  } catch (err) {
56150
- log14.debug(`Title suggestion error: ${err}`);
56192
+ log15.debug(`Title suggestion error: ${err}`);
56151
56193
  return null;
56152
56194
  }
56153
56195
  }
56154
56196
 
56155
56197
  // src/operations/suggestions/tag.ts
56156
56198
  init_logger();
56157
- var log15 = createLogger("tags");
56199
+ var log16 = createLogger("tags");
56158
56200
  var SUGGESTION_TIMEOUT2 = 15000;
56159
56201
  var MAX_TAGS = 3;
56160
56202
  var VALID_TAGS = [
@@ -56186,7 +56228,7 @@ function parseTags(response) {
56186
56228
  return [...new Set(tags)].slice(0, MAX_TAGS);
56187
56229
  }
56188
56230
  async function suggestSessionTags(userMessage) {
56189
- log15.debug(`Suggesting tags for: "${userMessage.substring(0, 50)}..."`);
56231
+ log16.debug(`Suggesting tags for: "${userMessage.substring(0, 50)}..."`);
56190
56232
  try {
56191
56233
  const result = await quickQuery({
56192
56234
  prompt: buildTagPrompt(userMessage),
@@ -56194,14 +56236,14 @@ async function suggestSessionTags(userMessage) {
56194
56236
  timeout: SUGGESTION_TIMEOUT2
56195
56237
  });
56196
56238
  if (!result.success || !result.response) {
56197
- log15.debug(`Tag suggestion failed: ${result.error || "no response"}`);
56239
+ log16.debug(`Tag suggestion failed: ${result.error || "no response"}`);
56198
56240
  return [];
56199
56241
  }
56200
56242
  const tags = parseTags(result.response);
56201
- log15.debug(`Got tags: ${tags.join(", ")} (${result.durationMs}ms)`);
56243
+ log16.debug(`Got tags: ${tags.join(", ")} (${result.durationMs}ms)`);
56202
56244
  return tags;
56203
56245
  } catch (err) {
56204
- log15.debug(`Tag suggestion error: ${err}`);
56246
+ log16.debug(`Tag suggestion error: ${err}`);
56205
56247
  return [];
56206
56248
  }
56207
56249
  }
@@ -59721,7 +59763,7 @@ class BugReportExecutor extends BaseExecutor {
59721
59763
  // src/operations/executors/worktree-prompt.ts
59722
59764
  init_emoji();
59723
59765
  init_logger();
59724
- var log16 = createLogger("wt-prompt");
59766
+ var log17 = createLogger("wt-prompt");
59725
59767
  // src/operations/message-manager.ts
59726
59768
  init_logger();
59727
59769
 
@@ -59758,7 +59800,7 @@ var import_yauzl = __toESM(require_yauzl(), 1);
59758
59800
  import { createGunzip } from "zlib";
59759
59801
  import { pipeline } from "stream/promises";
59760
59802
  import { Readable, Writable } from "stream";
59761
- var log17 = createLogger("streaming");
59803
+ var log18 = createLogger("streaming");
59762
59804
  var MAX_PDF_SIZE = 32 * 1024 * 1024;
59763
59805
  var MAX_TEXT_FILE_SIZE = 1 * 1024 * 1024;
59764
59806
  var MAX_DECOMPRESSED_SIZE = 10 * 1024 * 1024;
@@ -59884,7 +59926,7 @@ async function processImageFile(file, platform, debug = false) {
59884
59926
  const buffer = await platform.downloadFile(file.id);
59885
59927
  const base64 = buffer.toString("base64");
59886
59928
  if (debug) {
59887
- log17.debug(`Attached image: ${file.name} (${file.mimeType}, ${Math.round(buffer.length / 1024)}KB)`);
59929
+ log18.debug(`Attached image: ${file.name} (${file.mimeType}, ${Math.round(buffer.length / 1024)}KB)`);
59888
59930
  }
59889
59931
  return {
59890
59932
  block: {
@@ -59897,7 +59939,7 @@ async function processImageFile(file, platform, debug = false) {
59897
59939
  }
59898
59940
  };
59899
59941
  } catch (err) {
59900
- log17.error(`Failed to download image ${file.name}: ${err}`);
59942
+ log18.error(`Failed to download image ${file.name}: ${err}`);
59901
59943
  return {
59902
59944
  skipped: {
59903
59945
  name: file.name,
@@ -59928,7 +59970,7 @@ async function processPdfFile(file, platform, debug = false) {
59928
59970
  }
59929
59971
  const base64 = buffer.toString("base64");
59930
59972
  if (debug) {
59931
- log17.debug(`Attached PDF: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
59973
+ log18.debug(`Attached PDF: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
59932
59974
  }
59933
59975
  return {
59934
59976
  block: {
@@ -59942,7 +59984,7 @@ async function processPdfFile(file, platform, debug = false) {
59942
59984
  }
59943
59985
  };
59944
59986
  } catch (err) {
59945
- log17.error(`Failed to process PDF ${file.name}: ${err}`);
59987
+ log18.error(`Failed to process PDF ${file.name}: ${err}`);
59946
59988
  return {
59947
59989
  skipped: {
59948
59990
  name: file.name,
@@ -59973,7 +60015,7 @@ async function processTextFile(file, platform, debug = false) {
59973
60015
  }
59974
60016
  const content = buffer.toString("utf-8");
59975
60017
  if (debug) {
59976
- log17.debug(`Attached text file: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
60018
+ log18.debug(`Attached text file: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
59977
60019
  }
59978
60020
  const wrappedContent = formatTextFileContent(file.name, content);
59979
60021
  return {
@@ -59983,7 +60025,7 @@ async function processTextFile(file, platform, debug = false) {
59983
60025
  }
59984
60026
  };
59985
60027
  } catch (err) {
59986
- log17.error(`Failed to process text file ${file.name}: ${err}`);
60028
+ log18.error(`Failed to process text file ${file.name}: ${err}`);
59987
60029
  return {
59988
60030
  skipped: {
59989
60031
  name: file.name,
@@ -60041,7 +60083,7 @@ async function processGzipFile(file, platform, debug = false) {
60041
60083
  compressedBuffer = await platform.downloadFile(file.id);
60042
60084
  } catch (err) {
60043
60085
  const errorMessage = err instanceof Error ? err.message : String(err);
60044
- log17.error(`Failed to download gzip file ${file.name}: ${errorMessage}`);
60086
+ log18.error(`Failed to download gzip file ${file.name}: ${errorMessage}`);
60045
60087
  return {
60046
60088
  skipped: {
60047
60089
  name: file.name,
@@ -60051,7 +60093,7 @@ async function processGzipFile(file, platform, debug = false) {
60051
60093
  };
60052
60094
  }
60053
60095
  if (file.size && compressedBuffer.length !== file.size) {
60054
- log17.warn(`Downloaded size mismatch for ${file.name}: expected ${file.size}, got ${compressedBuffer.length}`);
60096
+ log18.warn(`Downloaded size mismatch for ${file.name}: expected ${file.size}, got ${compressedBuffer.length}`);
60055
60097
  }
60056
60098
  let decompressedBuffer;
60057
60099
  try {
@@ -60087,7 +60129,7 @@ async function processGzipFile(file, platform, debug = false) {
60087
60129
  const innerFilename = file.name.toLowerCase().endsWith(".gz") ? file.name.slice(0, -3) : file.name;
60088
60130
  const contentType = detectDecompressedContentType(decompressedBuffer, innerFilename);
60089
60131
  if (debug) {
60090
- log17.debug(`Decompressed ${file.name}: ${Math.round(decompressedBuffer.length / 1024)}KB, detected type: ${contentType}`);
60132
+ log18.debug(`Decompressed ${file.name}: ${Math.round(decompressedBuffer.length / 1024)}KB, detected type: ${contentType}`);
60091
60133
  }
60092
60134
  if (contentType === "pdf") {
60093
60135
  const base64 = decompressedBuffer.toString("base64");
@@ -60122,7 +60164,7 @@ async function processGzipFile(file, platform, debug = false) {
60122
60164
  }
60123
60165
  } catch (err) {
60124
60166
  const errorMessage = err instanceof Error ? err.message : String(err);
60125
- log17.error(`Failed to process gzip file ${file.name}: ${errorMessage}`);
60167
+ log18.error(`Failed to process gzip file ${file.name}: ${errorMessage}`);
60126
60168
  return {
60127
60169
  skipped: {
60128
60170
  name: file.name,
@@ -60174,7 +60216,7 @@ async function processZipFile(file, platform, debug = false) {
60174
60216
  }
60175
60217
  const zipBuffer = await platform.downloadFile(file.id);
60176
60218
  if (debug) {
60177
- log17.debug(`Processing zip file ${file.name}: ${Math.round(zipBuffer.length / 1024)}KB`);
60219
+ log18.debug(`Processing zip file ${file.name}: ${Math.round(zipBuffer.length / 1024)}KB`);
60178
60220
  }
60179
60221
  const zipfile = await new Promise((resolve5, reject) => {
60180
60222
  import_yauzl.default.fromBuffer(zipBuffer, { lazyEntries: true }, (err, zf) => {
@@ -60248,7 +60290,7 @@ async function processZipFile(file, platform, debug = false) {
60248
60290
  const buffer = await extractZipEntry(zipfile2, entry);
60249
60291
  const contentType = detectDecompressedContentType(buffer, entry.fileName);
60250
60292
  if (debug) {
60251
- log17.debug(`Extracted ${entry.fileName}: ${Math.round(buffer.length / 1024)}KB, type: ${contentType}`);
60293
+ log18.debug(`Extracted ${entry.fileName}: ${Math.round(buffer.length / 1024)}KB, type: ${contentType}`);
60252
60294
  }
60253
60295
  if (contentType === "pdf") {
60254
60296
  const base64 = buffer.toString("base64");
@@ -60291,11 +60333,11 @@ async function processZipFile(file, platform, debug = false) {
60291
60333
  });
60292
60334
  zipfile2.close();
60293
60335
  if (debug) {
60294
- log17.debug(`Zip ${file.name}: processed ${processedCount} files, skipped ${skipped.length}`);
60336
+ log18.debug(`Zip ${file.name}: processed ${processedCount} files, skipped ${skipped.length}`);
60295
60337
  }
60296
60338
  return { blocks, skipped };
60297
60339
  } catch (err) {
60298
- log17.error(`Failed to process zip file ${file.name}: ${err}`);
60340
+ log18.error(`Failed to process zip file ${file.name}: ${err}`);
60299
60341
  return {
60300
60342
  blocks: [],
60301
60343
  skipped: [{
@@ -60392,7 +60434,7 @@ async function processFiles(platform, files, debug = false) {
60392
60434
  blocks.push(...zipResult.blocks);
60393
60435
  for (const s of zipResult.skipped) {
60394
60436
  skipped.push(s);
60395
- log17.warn(`Skipped file ${s.name}: ${s.reason}`);
60437
+ log18.warn(`Skipped file ${s.name}: ${s.reason}`);
60396
60438
  }
60397
60439
  continue;
60398
60440
  }
@@ -60426,7 +60468,7 @@ async function processFiles(platform, files, debug = false) {
60426
60468
  }
60427
60469
  if (result.skipped) {
60428
60470
  skipped.push(result.skipped);
60429
- log17.warn(`Skipped file ${result.skipped.name}: ${result.skipped.reason}`);
60471
+ log18.warn(`Skipped file ${result.skipped.name}: ${result.skipped.reason}`);
60430
60472
  }
60431
60473
  }
60432
60474
  return { blocks, skipped };
@@ -60459,7 +60501,7 @@ function stopTyping(session) {
60459
60501
  }
60460
60502
 
60461
60503
  // src/operations/message-manager.ts
60462
- var log18 = createLogger("msg-mgr");
60504
+ var log19 = createLogger("msg-mgr");
60463
60505
 
60464
60506
  class MessageManager {
60465
60507
  platform;
@@ -60549,7 +60591,7 @@ class MessageManager {
60549
60591
  });
60550
60592
  }
60551
60593
  async handleEvent(event) {
60552
- const logger = log18.forSession(this.sessionId);
60594
+ const logger = log19.forSession(this.sessionId);
60553
60595
  const transformCtx = {
60554
60596
  sessionId: this.sessionId,
60555
60597
  formatter: this.platform.getFormatter(),
@@ -60599,7 +60641,7 @@ class MessageManager {
60599
60641
  }
60600
60642
  }
60601
60643
  async executeOperation(op) {
60602
- const logger = log18.forSession(this.sessionId);
60644
+ const logger = log19.forSession(this.sessionId);
60603
60645
  const ctx = this.getExecutorContext();
60604
60646
  try {
60605
60647
  if (isContentOp(op)) {
@@ -60667,7 +60709,7 @@ class MessageManager {
60667
60709
  threadId: this.threadId,
60668
60710
  platform: this.platform,
60669
60711
  formatter: this.platform.getFormatter(),
60670
- logger: log18.forSession(this.sessionId),
60712
+ logger: log19.forSession(this.sessionId),
60671
60713
  postTracker: this.postTracker,
60672
60714
  contentBreaker: this.contentBreaker,
60673
60715
  threadLogger: this.session.threadLogger,
@@ -60878,13 +60920,13 @@ class MessageManager {
60878
60920
  return this.systemExecutor.postSuccess(message, this.getExecutorContext());
60879
60921
  }
60880
60922
  async prepareForUserMessage() {
60881
- const logger = log18.forSession(this.sessionId);
60923
+ const logger = log19.forSession(this.sessionId);
60882
60924
  logger.debug("Preparing for new user message");
60883
60925
  await this.closeCurrentPost();
60884
60926
  await this.bumpTaskList();
60885
60927
  }
60886
60928
  async handleUserMessage(message, files, username, displayName) {
60887
- const logger = log18.forSession(this.sessionId);
60929
+ const logger = log19.forSession(this.sessionId);
60888
60930
  if (!this.session.claude.isRunning()) {
60889
60931
  logger.debug("Claude not running, ignoring user message");
60890
60932
  return false;
@@ -60921,7 +60963,7 @@ class MessageManager {
60921
60963
  ];
60922
60964
  }
60923
60965
  async handleReaction(postId, emoji, user, action) {
60924
- const logger = log18.forSession(this.sessionId);
60966
+ const logger = log19.forSession(this.sessionId);
60925
60967
  const ctx = this.getExecutorContext();
60926
60968
  logger.debug(`Routing reaction: postId=${postId}, emoji=${emoji}, user=${user}, action=${action}`);
60927
60969
  for (const { name, executor } of this.reactionDispatchList()) {
@@ -60949,6 +60991,7 @@ class MessageManager {
60949
60991
  }
60950
60992
  dispose() {
60951
60993
  this.cancelScheduledFlush();
60994
+ this.postTracker.clearSession(this.sessionId);
60952
60995
  this.reset();
60953
60996
  }
60954
60997
  }
@@ -61101,7 +61144,7 @@ function formatPullRequestLink(url, formatter) {
61101
61144
  }
61102
61145
 
61103
61146
  // src/operations/sticky-message/handler.ts
61104
- var log19 = createLogger("sticky");
61147
+ var log20 = createLogger("sticky");
61105
61148
  var botStartedAt = new Date;
61106
61149
  function getPendingPrompts(session) {
61107
61150
  const prompts2 = [];
@@ -61176,21 +61219,21 @@ function initialize(store) {
61176
61219
  stickyPostIds.set(platformId, postId);
61177
61220
  }
61178
61221
  if (persistedIds.size > 0) {
61179
- log19.info(`\uD83D\uDCCC Restored ${persistedIds.size} sticky post ID(s) from persistence`);
61222
+ log20.info(`\uD83D\uDCCC Restored ${persistedIds.size} sticky post ID(s) from persistence`);
61180
61223
  }
61181
61224
  }
61182
61225
  function setPlatformPaused(platformId, paused) {
61183
61226
  if (paused) {
61184
61227
  pausedPlatforms.set(platformId, true);
61185
- log19.debug(`Platform ${platformId} marked as paused`);
61228
+ log20.debug(`Platform ${platformId} marked as paused`);
61186
61229
  } else {
61187
61230
  pausedPlatforms.delete(platformId);
61188
- log19.debug(`Platform ${platformId} marked as active`);
61231
+ log20.debug(`Platform ${platformId} marked as active`);
61189
61232
  }
61190
61233
  }
61191
61234
  function setShuttingDown(shuttingDown) {
61192
61235
  isShuttingDown = shuttingDown;
61193
- log19.debug(`Bot shutdown state: ${shuttingDown}`);
61236
+ log20.debug(`Bot shutdown state: ${shuttingDown}`);
61194
61237
  }
61195
61238
  function getTaskContent(session) {
61196
61239
  const taskState = session.messageManager?.getTaskListState();
@@ -61501,12 +61544,12 @@ async function validateLastMessageIds(platform, sessions) {
61501
61544
  try {
61502
61545
  const post2 = await platform.getPost(lastMessageId);
61503
61546
  if (!post2) {
61504
- log19.debug(`lastMessageId ${lastMessageId.substring(0, 8)} for session ${session.sessionId} was deleted, clearing`);
61547
+ log20.debug(`lastMessageId ${lastMessageId.substring(0, 8)} for session ${session.sessionId} was deleted, clearing`);
61505
61548
  session.lastMessageId = undefined;
61506
61549
  session.lastMessageTs = undefined;
61507
61550
  }
61508
61551
  } catch (err) {
61509
- log19.debug(`Failed to validate lastMessageId for session ${session.sessionId}, clearing: ${err}`);
61552
+ log20.debug(`Failed to validate lastMessageId for session ${session.sessionId}, clearing: ${err}`);
61510
61553
  session.lastMessageId = undefined;
61511
61554
  session.lastMessageTs = undefined;
61512
61555
  }
@@ -61515,63 +61558,63 @@ async function validateLastMessageIds(platform, sessions) {
61515
61558
  }
61516
61559
  async function updateStickyMessageImpl(platform, sessions, config) {
61517
61560
  const platformSessions = [...sessions.values()].filter((s) => s.platformId === platform.platformId);
61518
- log19.debug(`updateStickyMessage for ${platform.platformId}, ${platformSessions.length} sessions`);
61561
+ log20.debug(`updateStickyMessage for ${platform.platformId}, ${platformSessions.length} sessions`);
61519
61562
  for (const s of platformSessions) {
61520
- log19.debug(` - ${s.sessionId}: title="${s.sessionTitle}" firstPrompt="${s.firstPrompt?.substring(0, 30)}..."`);
61563
+ log20.debug(` - ${s.sessionId}: title="${s.sessionTitle}" firstPrompt="${s.firstPrompt?.substring(0, 30)}..."`);
61521
61564
  }
61522
61565
  await validateLastMessageIds(platform, platformSessions);
61523
61566
  const formatter = platform.getFormatter();
61524
61567
  const content = await buildStickyMessage(sessions, platform.platformId, config, formatter, (threadId) => platform.getThreadLink(threadId));
61525
61568
  const existingPostId = stickyPostIds.get(platform.platformId);
61526
61569
  const shouldBump = needsBump.get(platform.platformId) ?? false;
61527
- log19.debug(`existingPostId: ${existingPostId || "(none)"}, needsBump: ${shouldBump}`);
61570
+ log20.debug(`existingPostId: ${existingPostId || "(none)"}, needsBump: ${shouldBump}`);
61528
61571
  try {
61529
61572
  if (existingPostId && !shouldBump) {
61530
- log19.debug(`Updating existing post in place...`);
61573
+ log20.debug(`Updating existing post in place...`);
61531
61574
  try {
61532
61575
  await platform.updatePost(existingPostId, content);
61533
61576
  try {
61534
61577
  await platform.pinPost(existingPostId);
61535
- log19.debug(`Re-pinned post`);
61578
+ log20.debug(`Re-pinned post`);
61536
61579
  } catch (pinErr) {
61537
- log19.debug(`Re-pin failed (might already be pinned): ${pinErr}`);
61580
+ log20.debug(`Re-pin failed (might already be pinned): ${pinErr}`);
61538
61581
  }
61539
- log19.debug(`Updated successfully`);
61582
+ log20.debug(`Updated successfully`);
61540
61583
  return;
61541
61584
  } catch (err) {
61542
- log19.debug(`Update failed, will create new: ${err}`);
61585
+ log20.debug(`Update failed, will create new: ${err}`);
61543
61586
  }
61544
61587
  }
61545
61588
  needsBump.set(platform.platformId, false);
61546
61589
  if (existingPostId) {
61547
- log19.debug(`Unpinning and deleting existing post ${existingPostId.substring(0, 8)}...`);
61590
+ log20.debug(`Unpinning and deleting existing post ${existingPostId.substring(0, 8)}...`);
61548
61591
  try {
61549
61592
  await platform.unpinPost(existingPostId);
61550
- log19.debug(`Unpinned successfully`);
61593
+ log20.debug(`Unpinned successfully`);
61551
61594
  } catch (err) {
61552
- log19.debug(`Unpin failed (probably already unpinned): ${err}`);
61595
+ log20.debug(`Unpin failed (probably already unpinned): ${err}`);
61553
61596
  }
61554
61597
  try {
61555
61598
  await platform.deletePost(existingPostId);
61556
- log19.debug(`Deleted successfully`);
61599
+ log20.debug(`Deleted successfully`);
61557
61600
  } catch (err) {
61558
- log19.debug(`Delete failed (probably already deleted): ${err}`);
61601
+ log20.debug(`Delete failed (probably already deleted): ${err}`);
61559
61602
  }
61560
61603
  stickyPostIds.delete(platform.platformId);
61561
61604
  }
61562
- log19.debug(`Creating new post...`);
61605
+ log20.debug(`Creating new post...`);
61563
61606
  const post2 = await platform.createPost(content);
61564
61607
  stickyPostIds.set(platform.platformId, post2.id);
61565
61608
  try {
61566
61609
  await platform.pinPost(post2.id);
61567
- log19.debug(`Pinned post successfully`);
61610
+ log20.debug(`Pinned post successfully`);
61568
61611
  } catch (err) {
61569
- log19.debug(`Failed to pin post: ${err}`);
61612
+ log20.debug(`Failed to pin post: ${err}`);
61570
61613
  }
61571
61614
  if (sessionStore) {
61572
61615
  sessionStore.saveStickyPostId(platform.platformId, post2.id);
61573
61616
  }
61574
- log19.info(`\uD83D\uDCCC Created sticky message for ${platform.platformId}: ${formatShortId(post2.id)}`);
61617
+ log20.info(`\uD83D\uDCCC Created sticky message for ${platform.platformId}: ${formatShortId(post2.id)}`);
61575
61618
  const excludePostIds = new Set;
61576
61619
  if (sessionStore) {
61577
61620
  for (const session of sessionStore.load().values()) {
@@ -61587,10 +61630,10 @@ async function updateStickyMessageImpl(platform, sessions, config) {
61587
61630
  }
61588
61631
  const botUser = await platform.getBotUser();
61589
61632
  cleanupOldStickyMessages(platform, botUser.id, false, excludePostIds).catch((err) => {
61590
- log19.debug(`Background cleanup failed: ${err}`);
61633
+ log20.debug(`Background cleanup failed: ${err}`);
61591
61634
  });
61592
61635
  } catch (err) {
61593
- log19.error(`Failed to update sticky message for ${platform.platformId}`, err instanceof Error ? err : undefined);
61636
+ log20.error(`Failed to update sticky message for ${platform.platformId}`, err instanceof Error ? err : undefined);
61594
61637
  }
61595
61638
  }
61596
61639
  async function updateAllStickyMessages(platforms, sessions, config) {
@@ -61615,7 +61658,7 @@ async function cleanupOldStickyMessages(platform, botUserId, forceRun = false, e
61615
61658
  if (!forceRun) {
61616
61659
  const lastRun = lastCleanupTime.get(platformId) || 0;
61617
61660
  if (now - lastRun < CLEANUP_THROTTLE_MS) {
61618
- log19.debug(`Cleanup throttled for ${platformId} (last run ${Math.round((now - lastRun) / 1000)}s ago)`);
61661
+ log20.debug(`Cleanup throttled for ${platformId} (last run ${Math.round((now - lastRun) / 1000)}s ago)`);
61619
61662
  return;
61620
61663
  }
61621
61664
  }
@@ -61625,31 +61668,31 @@ async function cleanupOldStickyMessages(platform, botUserId, forceRun = false, e
61625
61668
  const pinnedPostIds = await platform.getPinnedPosts();
61626
61669
  const recentPinnedIds = pinnedPostIds.filter((id) => id !== currentStickyId && !excludePostIds?.has(id) && isRecentPost(id));
61627
61670
  if (recentPinnedIds.length === 0) {
61628
- log19.debug(`No recent pinned posts to check (${pinnedPostIds.length} total, current: ${currentStickyId?.substring(0, 8) || "(none)"})`);
61671
+ log20.debug(`No recent pinned posts to check (${pinnedPostIds.length} total, current: ${currentStickyId?.substring(0, 8) || "(none)"})`);
61629
61672
  return;
61630
61673
  }
61631
- log19.debug(`Checking ${recentPinnedIds.length} recent pinned posts (of ${pinnedPostIds.length} total)`);
61674
+ log20.debug(`Checking ${recentPinnedIds.length} recent pinned posts (of ${pinnedPostIds.length} total)`);
61632
61675
  for (const postId of recentPinnedIds) {
61633
61676
  try {
61634
61677
  const post2 = await platform.getPost(postId);
61635
61678
  if (!post2)
61636
61679
  continue;
61637
61680
  if (post2.userId === botUserId) {
61638
- log19.debug(`Cleaning up old sticky: ${postId.substring(0, 8)}...`);
61681
+ log20.debug(`Cleaning up old sticky: ${postId.substring(0, 8)}...`);
61639
61682
  try {
61640
61683
  await platform.unpinPost(postId);
61641
61684
  await platform.deletePost(postId);
61642
- log19.info(`\uD83E\uDDF9 Cleaned up old sticky message: ${postId.substring(0, 8)}...`);
61685
+ log20.info(`\uD83E\uDDF9 Cleaned up old sticky message: ${postId.substring(0, 8)}...`);
61643
61686
  } catch (err) {
61644
- log19.debug(`Failed to cleanup ${postId}: ${err}`);
61687
+ log20.debug(`Failed to cleanup ${postId}: ${err}`);
61645
61688
  }
61646
61689
  }
61647
61690
  } catch (err) {
61648
- log19.debug(`Could not check post ${postId}: ${err}`);
61691
+ log20.debug(`Could not check post ${postId}: ${err}`);
61649
61692
  }
61650
61693
  }
61651
61694
  } catch (err) {
61652
- log19.error(`Failed to cleanup old sticky messages`, err instanceof Error ? err : undefined);
61695
+ log20.error(`Failed to cleanup old sticky messages`, err instanceof Error ? err : undefined);
61653
61696
  }
61654
61697
  }
61655
61698
  // src/operations/bug-report/handler.ts
@@ -65712,8 +65755,8 @@ function getUpdateInfo() {
65712
65755
  init_emoji();
65713
65756
  init_logger();
65714
65757
  init_worktree();
65715
- var log20 = createLogger("commands");
65716
- var sessionLog2 = createSessionLog(log20);
65758
+ var log21 = createLogger("commands");
65759
+ var sessionLog2 = createSessionLog(log21);
65717
65760
  function sessionAccountOption(session, ctx) {
65718
65761
  if (!session.claudeAccountId)
65719
65762
  return;
@@ -66247,7 +66290,7 @@ init_logger();
66247
66290
  import { exec as exec3 } from "child_process";
66248
66291
  import { promisify as promisify3 } from "util";
66249
66292
  var execAsync2 = promisify3(exec3);
66250
- var log21 = createLogger("branch");
66293
+ var log22 = createLogger("branch");
66251
66294
  var SUGGESTION_TIMEOUT3 = 15000;
66252
66295
  var MAX_SUGGESTIONS = 3;
66253
66296
  async function getCurrentBranch3(workingDir) {
@@ -66296,7 +66339,7 @@ function parseBranchSuggestions(response) {
66296
66339
  return lines.slice(0, MAX_SUGGESTIONS);
66297
66340
  }
66298
66341
  async function suggestBranchNames(workingDir, userMessage) {
66299
- log21.debug(`Suggesting branch names for: "${userMessage.substring(0, 50)}..."`);
66342
+ log22.debug(`Suggesting branch names for: "${userMessage.substring(0, 50)}..."`);
66300
66343
  try {
66301
66344
  const [currentBranch, recentCommits] = await Promise.all([
66302
66345
  getCurrentBranch3(workingDir),
@@ -66310,14 +66353,14 @@ async function suggestBranchNames(workingDir, userMessage) {
66310
66353
  workingDir
66311
66354
  });
66312
66355
  if (!result.success || !result.response) {
66313
- log21.debug(`Branch suggestion failed: ${result.error || "no response"}`);
66356
+ log22.debug(`Branch suggestion failed: ${result.error || "no response"}`);
66314
66357
  return [];
66315
66358
  }
66316
66359
  const suggestions = parseBranchSuggestions(result.response);
66317
- log21.debug(`Got ${suggestions.length} branch suggestions: ${suggestions.join(", ")}`);
66360
+ log22.debug(`Got ${suggestions.length} branch suggestions: ${suggestions.join(", ")}`);
66318
66361
  return suggestions;
66319
66362
  } catch (err) {
66320
- log21.debug(`Branch suggestion error: ${err}`);
66363
+ log22.debug(`Branch suggestion error: ${err}`);
66321
66364
  return [];
66322
66365
  }
66323
66366
  }
@@ -66326,8 +66369,8 @@ async function suggestBranchNames(workingDir, userMessage) {
66326
66369
  init_worktree();
66327
66370
  import { randomUUID as randomUUID3 } from "crypto";
66328
66371
  init_logger();
66329
- var log22 = createLogger("worktree");
66330
- var sessionLog3 = createSessionLog(log22);
66372
+ var log23 = createLogger("worktree");
66373
+ var sessionLog3 = createSessionLog(log23);
66331
66374
  function parseWorktreeError(error) {
66332
66375
  const message = error instanceof Error ? error.message : String(error);
66333
66376
  const lowerMessage = message.toLowerCase();
@@ -66895,8 +66938,8 @@ async function cleanupWorktreeCommand(session, username, hasOtherSessionsUsingWo
66895
66938
  }
66896
66939
  // src/operations/events/handler.ts
66897
66940
  init_logger();
66898
- var log23 = createLogger("events");
66899
- var sessionLog4 = createSessionLog(log23);
66941
+ var log24 = createLogger("events");
66942
+ var sessionLog4 = createSessionLog(log24);
66900
66943
  function detectAndExecuteClaudeCommands(text, session, ctx) {
66901
66944
  const parsed = parseClaudeCommand(text);
66902
66945
  if (parsed && isClaudeAllowedCommand(parsed.command)) {
@@ -67144,8 +67187,8 @@ function createSessionContext(config, state, ops) {
67144
67187
  // src/operations/context-prompt/handler.ts
67145
67188
  init_emoji();
67146
67189
  init_logger();
67147
- var log24 = createLogger("context");
67148
- var sessionLog5 = createSessionLog(log24);
67190
+ var log25 = createLogger("context");
67191
+ var sessionLog5 = createSessionLog(log25);
67149
67192
  var CONTEXT_PROMPT_TIMEOUT_MS = 30000;
67150
67193
  var CONTEXT_OPTIONS = [3, 5, 10];
67151
67194
  var contextPromptTimeouts = new Map;
@@ -67395,8 +67438,8 @@ function formatRelativeTime(date) {
67395
67438
  }
67396
67439
  // src/session/lifecycle.ts
67397
67440
  init_worktree();
67398
- var log25 = createLogger("lifecycle");
67399
- var sessionLog6 = createSessionLog(log25);
67441
+ var log26 = createLogger("lifecycle");
67442
+ var sessionLog6 = createSessionLog(log26);
67400
67443
  function mutableSessions(ctx) {
67401
67444
  return ctx.state.sessions;
67402
67445
  }
@@ -67443,6 +67486,7 @@ async function cleanupSession(session, ctx, options2 = {}) {
67443
67486
  if (doCloseLogger) {
67444
67487
  await closeThreadLogger(session, action, details);
67445
67488
  }
67489
+ session.messageManager?.dispose();
67446
67490
  ctx.ops.emitSessionRemove(session.sessionId);
67447
67491
  mutableSessions(ctx).delete(session.sessionId);
67448
67492
  if (doCleanupPostIndex) {
@@ -67458,6 +67502,7 @@ function releaseAccountIfHeld(session, ctx) {
67458
67502
  }
67459
67503
  }
67460
67504
  function removeFromRegistry(session, ctx) {
67505
+ session.messageManager?.dispose();
67461
67506
  ctx.ops.emitSessionRemove(session.sessionId);
67462
67507
  mutableSessions(ctx).delete(session.sessionId);
67463
67508
  cleanupPostIndex(ctx, session.threadId);
@@ -67781,17 +67826,17 @@ async function startSession(options2, username, displayName, replyToPostId, plat
67781
67826
  return;
67782
67827
  }
67783
67828
  workingDir = resolvedDir;
67784
- log25.info(`Starting session in directory: ${workingDir} (from !cd command)`);
67829
+ log26.info(`Starting session in directory: ${workingDir} (from !cd command)`);
67785
67830
  }
67786
67831
  if (initialOptions?.permissionMode) {
67787
67832
  permissionMode = initialOptions.permissionMode;
67788
67833
  forceInteractivePermissions = permissionMode === "default";
67789
67834
  sessionPermissionModeOverride = permissionMode;
67790
- log25.info(`Starting session with permission mode "${permissionMode}" (from !permissions command)`);
67835
+ log26.info(`Starting session with permission mode "${permissionMode}" (from !permissions command)`);
67791
67836
  } else if (initialOptions?.forceInteractivePermissions) {
67792
67837
  forceInteractivePermissions = true;
67793
67838
  permissionMode = "default";
67794
- log25.info(`Starting session with interactive permissions (from !permissions command)`);
67839
+ log26.info(`Starting session with interactive permissions (from !permissions command)`);
67795
67840
  }
67796
67841
  const sessionContext = buildSessionContext(platform, workingDir);
67797
67842
  const systemPrompt = `${sessionContext}
@@ -67800,7 +67845,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67800
67845
  const platformMcpConfig = platform.getMcpConfig();
67801
67846
  const claudeAccount = ctx.ops.acquireClaudeAccount();
67802
67847
  if (claudeAccount) {
67803
- log25.info(`Session ${sessionId.substring(0, 20)} reserved Claude account "${claudeAccount.id}"`);
67848
+ log26.info(`Session ${sessionId.substring(0, 20)} reserved Claude account "${claudeAccount.id}"`);
67804
67849
  }
67805
67850
  const cliOptions = {
67806
67851
  workingDir,
@@ -67869,6 +67914,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67869
67914
  } catch (err) {
67870
67915
  await logAndNotify(err, { action: "Start Claude", session });
67871
67916
  ctx.ops.stopTyping(session);
67917
+ session.messageManager?.dispose();
67872
67918
  ctx.ops.emitSessionRemove(session.sessionId);
67873
67919
  mutableSessions(ctx).delete(session.sessionId);
67874
67920
  releaseAccountIfHeld(session, ctx);
@@ -67905,28 +67951,28 @@ async function resumeSession(state, ctx) {
67905
67951
  !state.claudeSessionId && "claudeSessionId",
67906
67952
  !state.workingDir && "workingDir"
67907
67953
  ].filter(Boolean).join(", ");
67908
- log25.warn(`Skipping session with missing required fields: ${missing}`);
67954
+ log26.warn(`Skipping session with missing required fields: ${missing}`);
67909
67955
  return;
67910
67956
  }
67911
67957
  const shortId = state.threadId.substring(0, 8);
67912
67958
  const platforms = ctx.state.platforms;
67913
67959
  const platform = platforms.get(state.platformId);
67914
67960
  if (!platform) {
67915
- log25.warn(`Platform ${state.platformId} not registered, skipping resume for ${shortId}...`);
67961
+ log26.warn(`Platform ${state.platformId} not registered, skipping resume for ${shortId}...`);
67916
67962
  return;
67917
67963
  }
67918
67964
  const threadPost = await platform.getPost(state.threadId);
67919
67965
  if (!threadPost) {
67920
- log25.warn(`Thread ${shortId}... deleted, skipping resume`);
67966
+ log26.warn(`Thread ${shortId}... deleted, skipping resume`);
67921
67967
  ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
67922
67968
  return;
67923
67969
  }
67924
67970
  if (ctx.state.sessions.size >= ctx.config.maxSessions) {
67925
- log25.warn(`Max sessions reached, skipping resume for ${shortId}...`);
67971
+ log26.warn(`Max sessions reached, skipping resume for ${shortId}...`);
67926
67972
  return;
67927
67973
  }
67928
67974
  if (!existsSync11(state.workingDir)) {
67929
- log25.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
67975
+ log26.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
67930
67976
  ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
67931
67977
  const resumeFormatter = platform.getFormatter();
67932
67978
  const tempSession = {
@@ -67950,7 +67996,7 @@ Please start a new session.`), { action: "Post resume failure notification" });
67950
67996
  ${CHAT_PLATFORM_PROMPT}`;
67951
67997
  const claudeAccount = ctx.ops.acquireClaudeAccount(state.claudeAccountId);
67952
67998
  if (state.claudeAccountId && !claudeAccount) {
67953
- log25.warn(`Persisted session referenced Claude account "${state.claudeAccountId}" ` + `which is no longer configured — resuming under default env`);
67999
+ log26.warn(`Persisted session referenced Claude account "${state.claudeAccountId}" ` + `which is no longer configured — resuming under default env`);
67954
68000
  }
67955
68001
  const cliOptions = {
67956
68002
  workingDir: state.workingDir,
@@ -68015,7 +68061,7 @@ ${CHAT_PLATFORM_PROMPT}`;
68015
68061
  worktreePath: detected.worktreePath,
68016
68062
  branch: detected.branch
68017
68063
  };
68018
- log25.info(`Auto-detected worktree info for resumed session: branch=${detected.branch}`);
68064
+ log26.info(`Auto-detected worktree info for resumed session: branch=${detected.branch}`);
68019
68065
  }
68020
68066
  }
68021
68067
  session.messageManager = createMessageManager(session, ctx);
@@ -68071,7 +68117,8 @@ ${sessionFormatter.formatItalic("Reconnected to Claude session. You can continue
68071
68117
  await ctx.ops.updateStickyMessage();
68072
68118
  ctx.ops.persistSession(session);
68073
68119
  } catch (err) {
68074
- log25.error(`Failed to resume session ${shortId}`, err instanceof Error ? err : undefined);
68120
+ log26.error(`Failed to resume session ${shortId}`, err instanceof Error ? err : undefined);
68121
+ session.messageManager?.dispose();
68075
68122
  ctx.ops.emitSessionRemove(sessionId);
68076
68123
  mutableSessions(ctx).delete(sessionId);
68077
68124
  ctx.state.sessionStore.remove(sessionId);
@@ -68111,18 +68158,18 @@ async function resumePausedSession(threadId, message, files, ctx) {
68111
68158
  const persisted = ctx.state.sessionStore.load();
68112
68159
  const state = findPersistedByThreadId(persisted, threadId);
68113
68160
  if (!state) {
68114
- log25.debug(`No persisted session found for ${threadId.substring(0, 8)}...`);
68161
+ log26.debug(`No persisted session found for ${threadId.substring(0, 8)}...`);
68115
68162
  return;
68116
68163
  }
68117
68164
  const shortId = threadId.substring(0, 8);
68118
- log25.info(`\uD83D\uDD04 Resuming paused session ${shortId}... for new message`);
68165
+ log26.info(`\uD83D\uDD04 Resuming paused session ${shortId}... for new message`);
68119
68166
  await resumeSession(state, ctx);
68120
68167
  const session = ctx.ops.findSessionByThreadId(threadId);
68121
68168
  if (session && session.claude.isRunning() && session.messageManager) {
68122
68169
  session.messageCount++;
68123
68170
  await session.messageManager.handleUserMessage(message, files, state.startedBy);
68124
68171
  } else {
68125
- log25.warn(`Failed to resume session ${shortId}..., could not send message`);
68172
+ log26.warn(`Failed to resume session ${shortId}..., could not send message`);
68126
68173
  }
68127
68174
  }
68128
68175
  async function handleExit(sessionId, code, ctx) {
@@ -68130,7 +68177,7 @@ async function handleExit(sessionId, code, ctx) {
68130
68177
  const shortId = sessionId.substring(0, 8);
68131
68178
  sessionLog6(session).debug(`handleExit called code=${code} isShuttingDown=${ctx.state.isShuttingDown}`);
68132
68179
  if (!session) {
68133
- log25.debug(`Session ${shortId}... not found (already cleaned up)`);
68180
+ log26.debug(`Session ${shortId}... not found (already cleaned up)`);
68134
68181
  return;
68135
68182
  }
68136
68183
  if (isSessionRestarting(session)) {
@@ -68323,7 +68370,7 @@ async function cleanupIdleSessions(timeoutMs, warningMs, ctx) {
68323
68370
  }
68324
68371
 
68325
68372
  // src/operations/monitor/handler.ts
68326
- var log26 = createLogger("monitor");
68373
+ var log27 = createLogger("monitor");
68327
68374
  var DEFAULT_INTERVAL_MS = 60 * 1000;
68328
68375
 
68329
68376
  class SessionMonitor {
@@ -68345,14 +68392,14 @@ class SessionMonitor {
68345
68392
  }
68346
68393
  start() {
68347
68394
  if (this.isRunning) {
68348
- log26.debug("Session monitor already running");
68395
+ log27.debug("Session monitor already running");
68349
68396
  return;
68350
68397
  }
68351
68398
  this.isRunning = true;
68352
- log26.debug(`Session monitor started (interval: ${this.intervalMs / 1000}s)`);
68399
+ log27.debug(`Session monitor started (interval: ${this.intervalMs / 1000}s)`);
68353
68400
  this.timer = setInterval(() => {
68354
68401
  this.runCheck().catch((err) => {
68355
- log26.error(`Error during session monitoring: ${err}`);
68402
+ log27.error(`Error during session monitoring: ${err}`);
68356
68403
  });
68357
68404
  }, this.intervalMs);
68358
68405
  }
@@ -68362,7 +68409,7 @@ class SessionMonitor {
68362
68409
  this.timer = null;
68363
68410
  }
68364
68411
  this.isRunning = false;
68365
- log26.debug("Session monitor stopped");
68412
+ log27.debug("Session monitor stopped");
68366
68413
  }
68367
68414
  async runCheck() {
68368
68415
  await cleanupIdleSessions(this.sessionTimeoutMs, this.sessionWarningMs, this.getContext());
@@ -68374,8 +68421,8 @@ class SessionMonitor {
68374
68421
  // src/operations/plugin/handler.ts
68375
68422
  init_spawn();
68376
68423
  init_logger();
68377
- var log27 = createLogger("plugin");
68378
- var sessionLog7 = createSessionLog(log27);
68424
+ var log28 = createLogger("plugin");
68425
+ var sessionLog7 = createSessionLog(log28);
68379
68426
  async function runPluginCommand(args, cwd, timeout2 = 60000) {
68380
68427
  return new Promise((resolve6) => {
68381
68428
  const claudePath = process.env.CLAUDE_PATH || "claude";
@@ -68396,7 +68443,7 @@ async function runPluginCommand(args, cwd, timeout2 = 60000) {
68396
68443
  });
68397
68444
  proc.on("error", (err) => {
68398
68445
  resolve6({ stdout, stderr, exitCode: 1 });
68399
- log27.error(`Plugin command error: ${err.message}`);
68446
+ log28.error(`Plugin command error: ${err.message}`);
68400
68447
  });
68401
68448
  });
68402
68449
  }
@@ -68595,9 +68642,105 @@ class SessionRegistry {
68595
68642
  }
68596
68643
  }
68597
68644
 
68645
+ // src/session/reaction-router.ts
68646
+ init_emoji();
68647
+ init_logger();
68648
+ var log29 = createLogger("manager");
68649
+ async function handleReaction(deps, platformId, postId, emojiName, username, action) {
68650
+ const normalizedEmoji = normalizeEmojiName(emojiName);
68651
+ if (action === "added" && isResumeEmoji(normalizedEmoji)) {
68652
+ const resumed = await tryResumeFromReaction(deps, platformId, postId, username);
68653
+ if (resumed)
68654
+ return;
68655
+ }
68656
+ const session = deps.registry.findByPost(postId);
68657
+ if (!session)
68658
+ return;
68659
+ if (session.platformId !== platformId)
68660
+ return;
68661
+ if (!session.sessionAllowedUsers.has(username) && !session.platform.isUserAllowed(username)) {
68662
+ log29.info(`\uD83D\uDEAB rejected reaction from unauthorized user`, {
68663
+ event: "reaction.rejected",
68664
+ platformId,
68665
+ sessionId: session.sessionId,
68666
+ postId,
68667
+ emoji: normalizedEmoji,
68668
+ action,
68669
+ user: username
68670
+ });
68671
+ return;
68672
+ }
68673
+ await dispatch(deps, session, postId, normalizedEmoji, username, action);
68674
+ }
68675
+ async function tryResumeFromReaction(deps, platformId, postId, username) {
68676
+ const persistedSession = deps.sessionStore.findByPostId(platformId, postId);
68677
+ if (!persistedSession)
68678
+ return false;
68679
+ const sessionId = `${platformId}:${persistedSession.threadId}`;
68680
+ if (deps.registry.hasById(sessionId))
68681
+ return false;
68682
+ const allowedUsers = new Set(persistedSession.sessionAllowedUsers);
68683
+ const platform = deps.platforms.get(platformId);
68684
+ if (!allowedUsers.has(username) && !platform?.isUserAllowed(username)) {
68685
+ if (platform) {
68686
+ await platform.createPost(`⚠️ @${username} is not authorized to resume this session`, persistedSession.threadId);
68687
+ }
68688
+ return false;
68689
+ }
68690
+ if (deps.registry.size >= deps.limits.maxSessions) {
68691
+ if (platform) {
68692
+ const fmt = platform.getFormatter();
68693
+ await platform.createPost(`⚠️ ${fmt.formatBold("Too busy")} - ${deps.registry.size} sessions active. Please try again later.`, persistedSession.threadId);
68694
+ }
68695
+ return false;
68696
+ }
68697
+ const shortId = persistedSession.threadId.substring(0, 8);
68698
+ log29.info(`\uD83D\uDD04 Resuming session ${shortId}... via emoji reaction by @${username}`);
68699
+ await resumeSession(persistedSession, deps.getContext());
68700
+ return true;
68701
+ }
68702
+ async function dispatch(deps, session, postId, emojiName, username, action) {
68703
+ if (action === "added") {
68704
+ if (session.sessionStartPostId === postId) {
68705
+ if (isCancelEmoji(emojiName)) {
68706
+ await cancelSession(session, username, deps.getContext());
68707
+ return;
68708
+ }
68709
+ if (isEscapeEmoji(emojiName)) {
68710
+ await interruptSession(session, username);
68711
+ return;
68712
+ }
68713
+ }
68714
+ if (session.worktreePromptPostId === postId && emojiName === "x") {
68715
+ await handleWorktreeSkip(session, username, (s) => deps.persistSession(s), (s, q) => offerContextPrompt(s, q, undefined, deps.getContextPromptHandler()));
68716
+ return;
68717
+ }
68718
+ if (session.pendingWorktreeSuggestions?.postId === postId) {
68719
+ const emojiIndex = getNumberEmojiIndex(emojiName);
68720
+ if (emojiIndex >= 0) {
68721
+ const handled = await handleBranchSuggestionReaction(session, postId, emojiIndex, username, (tid, branch, user) => deps.createAndSwitchToWorktree(tid, branch, user));
68722
+ if (handled)
68723
+ return;
68724
+ }
68725
+ }
68726
+ if (session.lastError?.postId === postId && isBugReportEmoji(emojiName)) {
68727
+ if (session.startedBy === username || session.platform.isUserAllowed(username) || session.sessionAllowedUsers.has(username)) {
68728
+ log29.info(`\uD83D\uDC1B @${username} triggered bug report from error reaction`);
68729
+ await reportBug(session, undefined, username, deps.getContext(), session.lastError);
68730
+ return;
68731
+ }
68732
+ }
68733
+ }
68734
+ if (session.messageManager) {
68735
+ const handled = await session.messageManager.handleReaction(postId, emojiName, username, action);
68736
+ if (handled)
68737
+ return;
68738
+ }
68739
+ }
68740
+
68598
68741
  // src/session/manager.ts
68599
68742
  init_logger();
68600
- var log28 = createLogger("manager");
68743
+ var log30 = createLogger("manager");
68601
68744
 
68602
68745
  class SessionManager extends EventEmitter4 {
68603
68746
  platforms = new Map;
@@ -68666,7 +68809,7 @@ class SessionManager extends EventEmitter4 {
68666
68809
  markNeedsBump(platformId);
68667
68810
  this.updateStickyMessage();
68668
68811
  });
68669
- log28.info(`\uD83D\uDCE1 Platform "${platformId}" registered`);
68812
+ log30.info(`\uD83D\uDCE1 Platform "${platformId}" registered`);
68670
68813
  }
68671
68814
  removePlatform(platformId) {
68672
68815
  this.platforms.delete(platformId);
@@ -68682,7 +68825,7 @@ class SessionManager extends EventEmitter4 {
68682
68825
  if (users) {
68683
68826
  users.add(sessionId);
68684
68827
  }
68685
- log28.debug(`Registered session ${sessionId.substring(0, 20)} as worktree user for ${worktreePath}`);
68828
+ log30.debug(`Registered session ${sessionId.substring(0, 20)} as worktree user for ${worktreePath}`);
68686
68829
  }
68687
68830
  unregisterWorktreeUser(worktreePath, sessionId) {
68688
68831
  const users = this.worktreeUsers.get(worktreePath);
@@ -68796,95 +68939,19 @@ class SessionManager extends EventEmitter4 {
68796
68939
  }
68797
68940
  async handleMessage(_platformId, _post, _user) {}
68798
68941
  async handleReaction(platformId, postId, emojiName, username, action) {
68799
- const normalizedEmoji = normalizeEmojiName(emojiName);
68800
- if (action === "added" && isResumeEmoji(normalizedEmoji)) {
68801
- const resumed = await this.tryResumeFromReaction(platformId, postId, username);
68802
- if (resumed)
68803
- return;
68804
- }
68805
- const session = this.getSessionByPost(postId);
68806
- if (!session)
68807
- return;
68808
- if (session.platformId !== platformId)
68809
- return;
68810
- if (!session.sessionAllowedUsers.has(username) && !session.platform.isUserAllowed(username)) {
68811
- log28.info(`\uD83D\uDEAB rejected reaction from unauthorized user`, {
68812
- event: "reaction.rejected",
68813
- platformId,
68814
- sessionId: session.sessionId,
68815
- postId,
68816
- emoji: normalizedEmoji,
68817
- action,
68818
- user: username
68819
- });
68820
- return;
68821
- }
68822
- await this.handleSessionReaction(session, postId, normalizedEmoji, username, action);
68823
- }
68824
- async tryResumeFromReaction(platformId, postId, username) {
68825
- const persistedSession = this.sessionStore.findByPostId(platformId, postId);
68826
- if (!persistedSession)
68827
- return false;
68828
- const sessionId = `${platformId}:${persistedSession.threadId}`;
68829
- if (this.registry.hasById(sessionId))
68830
- return false;
68831
- const allowedUsers = new Set(persistedSession.sessionAllowedUsers);
68832
- const platform = this.platforms.get(platformId);
68833
- if (!allowedUsers.has(username) && !platform?.isUserAllowed(username)) {
68834
- if (platform) {
68835
- await platform.createPost(`⚠️ @${username} is not authorized to resume this session`, persistedSession.threadId);
68836
- }
68837
- return false;
68838
- }
68839
- if (this.registry.size >= this.limits.maxSessions) {
68840
- if (platform) {
68841
- const fmt = platform.getFormatter();
68842
- await platform.createPost(`⚠️ ${fmt.formatBold("Too busy")} - ${this.registry.size} sessions active. Please try again later.`, persistedSession.threadId);
68843
- }
68844
- return false;
68845
- }
68846
- const shortId = persistedSession.threadId.substring(0, 8);
68847
- log28.info(`\uD83D\uDD04 Resuming session ${shortId}... via emoji reaction by @${username}`);
68848
- await resumeSession(persistedSession, this.getContext());
68849
- return true;
68942
+ await handleReaction(this.getReactionRouterDeps(), platformId, postId, emojiName, username, action);
68850
68943
  }
68851
- async handleSessionReaction(session, postId, emojiName, username, action) {
68852
- if (action === "added") {
68853
- if (session.sessionStartPostId === postId) {
68854
- if (isCancelEmoji(emojiName)) {
68855
- await cancelSession(session, username, this.getContext());
68856
- return;
68857
- }
68858
- if (isEscapeEmoji(emojiName)) {
68859
- await interruptSession(session, username);
68860
- return;
68861
- }
68862
- }
68863
- if (session.worktreePromptPostId === postId && emojiName === "x") {
68864
- await handleWorktreeSkip(session, username, (s) => this.persistSession(s), (s, q) => offerContextPrompt(s, q, undefined, this.getContextPromptHandler()));
68865
- return;
68866
- }
68867
- if (session.pendingWorktreeSuggestions?.postId === postId) {
68868
- const emojiIndex = getNumberEmojiIndex(emojiName);
68869
- if (emojiIndex >= 0) {
68870
- const handled = await handleBranchSuggestionReaction(session, postId, emojiIndex, username, (tid, branch, user) => this.createAndSwitchToWorktree(tid, branch, user));
68871
- if (handled)
68872
- return;
68873
- }
68874
- }
68875
- if (session.lastError?.postId === postId && isBugReportEmoji(emojiName)) {
68876
- if (session.startedBy === username || session.platform.isUserAllowed(username) || session.sessionAllowedUsers.has(username)) {
68877
- log28.info(`\uD83D\uDC1B @${username} triggered bug report from error reaction`);
68878
- await reportBug(session, undefined, username, this.getContext(), session.lastError);
68879
- return;
68880
- }
68881
- }
68882
- }
68883
- if (session.messageManager) {
68884
- const handled = await session.messageManager.handleReaction(postId, emojiName, username, action);
68885
- if (handled)
68886
- return;
68887
- }
68944
+ getReactionRouterDeps() {
68945
+ return {
68946
+ registry: this.registry,
68947
+ sessionStore: this.sessionStore,
68948
+ platforms: this.platforms,
68949
+ limits: this.limits,
68950
+ getContext: () => this.getContext(),
68951
+ getContextPromptHandler: () => this.getContextPromptHandler(),
68952
+ persistSession: (s) => this.persistSession(s),
68953
+ createAndSwitchToWorktree: (tid, branch, user) => this.createAndSwitchToWorktree(tid, branch, user)
68954
+ };
68888
68955
  }
68889
68956
  getContextPromptHandler() {
68890
68957
  return {
@@ -68943,28 +69010,14 @@ class SessionManager extends EventEmitter4 {
68943
69010
  this.stopTyping(session);
68944
69011
  }
68945
69012
  persistSession(session) {
68946
- const useSerializeV2 = process.env.CLAUDE_THREADS_SERIALIZE_V2 !== "0";
68947
69013
  let taskListSnapshot;
68948
69014
  let contextPromptSnapshot;
68949
- if (useSerializeV2 && session.messageManager) {
69015
+ if (session.messageManager) {
68950
69016
  const serialized = session.messageManager.serialize();
68951
69017
  taskListSnapshot = serialized.taskList;
68952
69018
  if (serialized.contextPrompt) {
68953
69019
  contextPromptSnapshot = serialized.contextPrompt;
68954
69020
  }
68955
- } else {
68956
- const legacyPrompt = session.messageManager?.getPendingContextPrompt();
68957
- if (legacyPrompt) {
68958
- contextPromptSnapshot = {
68959
- postId: legacyPrompt.postId,
68960
- queuedPrompt: legacyPrompt.queuedPrompt,
68961
- queuedFiles: legacyPrompt.queuedFiles,
68962
- threadMessageCount: legacyPrompt.threadMessageCount,
68963
- createdAt: legacyPrompt.createdAt,
68964
- availableOptions: legacyPrompt.availableOptions
68965
- };
68966
- }
68967
- taskListSnapshot = session.messageManager?.getTaskListState();
68968
69021
  }
68969
69022
  const state = {
68970
69023
  platformId: session.platformId,
@@ -69058,11 +69111,11 @@ class SessionManager extends EventEmitter4 {
69058
69111
  }
69059
69112
  }
69060
69113
  if (sessionsToKill.length === 0) {
69061
- log28.info(`No active sessions to pause for platform ${platformId}`);
69114
+ log30.info(`No active sessions to pause for platform ${platformId}`);
69062
69115
  await this.updateStickyMessage();
69063
69116
  return;
69064
69117
  }
69065
- log28.info(`⏸️ Pausing ${sessionsToKill.length} session(s) for platform ${platformId}`);
69118
+ log30.info(`⏸️ Pausing ${sessionsToKill.length} session(s) for platform ${platformId}`);
69066
69119
  for (const session of sessionsToKill) {
69067
69120
  try {
69068
69121
  const fmt = session.platform.getFormatter();
@@ -69078,9 +69131,9 @@ class SessionManager extends EventEmitter4 {
69078
69131
  session.claude.kill();
69079
69132
  this.registry.unregister(session.sessionId);
69080
69133
  this.emitSessionRemove(session.sessionId);
69081
- log28.info(`⏸️ Paused session ${session.threadId.substring(0, 8)}`);
69134
+ log30.info(`⏸️ Paused session ${session.threadId.substring(0, 8)}`);
69082
69135
  } catch (err) {
69083
- log28.warn(`Failed to pause session ${session.threadId}: ${err}`);
69136
+ log30.warn(`Failed to pause session ${session.threadId}: ${err}`);
69084
69137
  }
69085
69138
  }
69086
69139
  for (const session of sessionsToKill) {
@@ -69101,17 +69154,17 @@ class SessionManager extends EventEmitter4 {
69101
69154
  sessionsToResume.push(state);
69102
69155
  }
69103
69156
  if (sessionsToResume.length === 0) {
69104
- log28.info(`No paused sessions to resume for platform ${platformId}`);
69157
+ log30.info(`No paused sessions to resume for platform ${platformId}`);
69105
69158
  await this.updateStickyMessage();
69106
69159
  return;
69107
69160
  }
69108
- log28.info(`▶️ Resuming ${sessionsToResume.length} paused session(s) for platform ${platformId}`);
69161
+ log30.info(`▶️ Resuming ${sessionsToResume.length} paused session(s) for platform ${platformId}`);
69109
69162
  for (const state of sessionsToResume) {
69110
69163
  try {
69111
69164
  await resumeSession(state, this.getContext());
69112
- log28.info(`▶️ Resumed session ${state.threadId.substring(0, 8)}`);
69165
+ log30.info(`▶️ Resumed session ${state.threadId.substring(0, 8)}`);
69113
69166
  } catch (err) {
69114
- log28.warn(`Failed to resume session ${state.threadId}: ${err}`);
69167
+ log30.warn(`Failed to resume session ${state.threadId}: ${err}`);
69115
69168
  }
69116
69169
  }
69117
69170
  await this.updateStickyMessage();
@@ -69123,14 +69176,14 @@ class SessionManager extends EventEmitter4 {
69123
69176
  const sessionTimeoutMs = this.limits.sessionTimeoutMinutes * 60 * 1000;
69124
69177
  const staleIds = this.sessionStore.cleanStale(sessionTimeoutMs * 2);
69125
69178
  if (staleIds.length > 0) {
69126
- log28.info(`\uD83E\uDDF9 Soft-deleted ${staleIds.length} stale session(s) (kept for history)`);
69179
+ log30.info(`\uD83E\uDDF9 Soft-deleted ${staleIds.length} stale session(s) (kept for history)`);
69127
69180
  }
69128
69181
  const removedCount = this.sessionStore.cleanHistory();
69129
69182
  if (removedCount > 0) {
69130
- log28.info(`\uD83D\uDDD1️ Permanently removed ${removedCount} old session(s) from history`);
69183
+ log30.info(`\uD83D\uDDD1️ Permanently removed ${removedCount} old session(s) from history`);
69131
69184
  }
69132
69185
  const persisted = this.sessionStore.load();
69133
- log28.info(`\uD83D\uDCC2 Loaded ${persisted.size} session(s) from persistence`);
69186
+ log30.info(`\uD83D\uDCC2 Loaded ${persisted.size} session(s) from persistence`);
69134
69187
  const excludePostIdsByPlatform = new Map;
69135
69188
  for (const session of persisted.values()) {
69136
69189
  const platformId = session.platformId;
@@ -69150,10 +69203,10 @@ class SessionManager extends EventEmitter4 {
69150
69203
  const excludePostIds = excludePostIdsByPlatform.get(platform.platformId);
69151
69204
  platform.getBotUser().then((botUser) => {
69152
69205
  cleanupOldStickyMessages(platform, botUser.id, true, excludePostIds).catch((err) => {
69153
- log28.warn(`Failed to cleanup old sticky messages for ${platform.platformId}: ${err}`);
69206
+ log30.warn(`Failed to cleanup old sticky messages for ${platform.platformId}: ${err}`);
69154
69207
  });
69155
69208
  }).catch((err) => {
69156
- log28.warn(`Failed to get bot user for cleanup on ${platform.platformId}: ${err}`);
69209
+ log30.warn(`Failed to get bot user for cleanup on ${platform.platformId}: ${err}`);
69157
69210
  });
69158
69211
  }
69159
69212
  if (persisted.size > 0) {
@@ -69167,10 +69220,10 @@ class SessionManager extends EventEmitter4 {
69167
69220
  }
69168
69221
  }
69169
69222
  if (pausedToSkip.length > 0) {
69170
- log28.info(`⏸️ ${pausedToSkip.length} session(s) remain paused (waiting for user message)`);
69223
+ log30.info(`⏸️ ${pausedToSkip.length} session(s) remain paused (waiting for user message)`);
69171
69224
  }
69172
69225
  if (activeToResume.length > 0) {
69173
- log28.info(`\uD83D\uDD04 Attempting to resume ${activeToResume.length} active session(s)...`);
69226
+ log30.info(`\uD83D\uDD04 Attempting to resume ${activeToResume.length} active session(s)...`);
69174
69227
  for (const state of activeToResume) {
69175
69228
  await resumeSession(state, this.getContext());
69176
69229
  }
@@ -69595,7 +69648,7 @@ Mention me to start a session in this worktree.`, threadId);
69595
69648
  const message = messageBuilder(formatter);
69596
69649
  await post(session, "info", message);
69597
69650
  } catch (err) {
69598
- log28.warn(`Failed to broadcast to session ${session.threadId}: ${err}`);
69651
+ log30.warn(`Failed to broadcast to session ${session.threadId}: ${err}`);
69599
69652
  }
69600
69653
  }
69601
69654
  }
@@ -69614,7 +69667,7 @@ Mention me to start a session in this worktree.`, threadId);
69614
69667
  session.messageManager?.setPendingUpdatePrompt({ postId: post2.id });
69615
69668
  this.registerPost(post2.id, session.threadId);
69616
69669
  } catch (err) {
69617
- log28.warn(`Failed to post ask message to ${threadId}: ${err}`);
69670
+ log30.warn(`Failed to post ask message to ${threadId}: ${err}`);
69618
69671
  }
69619
69672
  }
69620
69673
  }
@@ -77210,29 +77263,29 @@ function SessionLog({ logs, maxLines = 20 }) {
77210
77263
  return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
77211
77264
  flexDirection: "column",
77212
77265
  flexShrink: 0,
77213
- children: displayLogs.map((log29) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
77266
+ children: displayLogs.map((log31) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
77214
77267
  flexShrink: 0,
77215
77268
  children: [
77216
77269
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
77217
- color: getColorForLevel(log29.level),
77270
+ color: getColorForLevel(log31.level),
77218
77271
  dimColor: true,
77219
77272
  wrap: "truncate",
77220
77273
  children: [
77221
77274
  "[",
77222
- padComponent(log29.component),
77275
+ padComponent(log31.component),
77223
77276
  "]"
77224
77277
  ]
77225
77278
  }, undefined, true, undefined, this),
77226
77279
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
77227
- color: getColorForLevel(log29.level),
77280
+ color: getColorForLevel(log31.level),
77228
77281
  wrap: "truncate",
77229
77282
  children: [
77230
77283
  " ",
77231
- log29.message
77284
+ log31.message
77232
77285
  ]
77233
77286
  }, undefined, true, undefined, this)
77234
77287
  ]
77235
- }, log29.id, true, undefined, this))
77288
+ }, log31.id, true, undefined, this))
77236
77289
  }, undefined, false, undefined, this);
77237
77290
  }
77238
77291
  // src/ui/components/Footer.tsx
@@ -77756,7 +77809,7 @@ function LogPanel({ logs, maxLines = 10, focused = false }) {
77756
77809
  const scrollRef = import_react59.default.useRef(null);
77757
77810
  const { stdout } = use_stdout_default();
77758
77811
  const isDebug = process.env.DEBUG === "1";
77759
- const displayLogs = logs.filter((log29) => isDebug || log29.level !== "debug");
77812
+ const displayLogs = logs.filter((log31) => isDebug || log31.level !== "debug");
77760
77813
  const visibleLogs = displayLogs.slice(-Math.max(maxLines * 3, 100));
77761
77814
  import_react59.default.useEffect(() => {
77762
77815
  const handleResize = () => scrollRef.current?.remeasure();
@@ -77796,25 +77849,25 @@ function LogPanel({ logs, maxLines = 10, focused = false }) {
77796
77849
  overflow: "hidden",
77797
77850
  children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(ScrollView, {
77798
77851
  ref: scrollRef,
77799
- children: visibleLogs.map((log29) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
77852
+ children: visibleLogs.map((log31) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
77800
77853
  children: [
77801
77854
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
77802
77855
  dimColor: true,
77803
77856
  children: [
77804
77857
  "[",
77805
- padComponent2(log29.component),
77858
+ padComponent2(log31.component),
77806
77859
  "]"
77807
77860
  ]
77808
77861
  }, undefined, true, undefined, this),
77809
77862
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
77810
- color: getLevelColor(log29.level),
77863
+ color: getLevelColor(log31.level),
77811
77864
  children: [
77812
77865
  " ",
77813
- log29.message
77866
+ log31.message
77814
77867
  ]
77815
77868
  }, undefined, true, undefined, this)
77816
77869
  ]
77817
- }, log29.id, true, undefined, this))
77870
+ }, log31.id, true, undefined, this))
77818
77871
  }, undefined, false, undefined, this)
77819
77872
  }, undefined, false, undefined, this);
77820
77873
  }
@@ -78331,10 +78384,10 @@ function useAppState(initialConfig) {
78331
78384
  });
78332
78385
  }, []);
78333
78386
  const getLogsForSession = import_react60.useCallback((sessionId) => {
78334
- return state.logs.filter((log29) => log29.sessionId === sessionId);
78387
+ return state.logs.filter((log31) => log31.sessionId === sessionId);
78335
78388
  }, [state.logs]);
78336
78389
  const getGlobalLogs = import_react60.useCallback(() => {
78337
- return state.logs.filter((log29) => !log29.sessionId);
78390
+ return state.logs.filter((log31) => !log31.sessionId);
78338
78391
  }, [state.logs]);
78339
78392
  const togglePlatformEnabled = import_react60.useCallback((platformId) => {
78340
78393
  let newEnabled = false;
@@ -79341,7 +79394,7 @@ import { EventEmitter as EventEmitter9 } from "events";
79341
79394
  // src/auto-update/checker.ts
79342
79395
  init_logger();
79343
79396
  import { EventEmitter as EventEmitter7 } from "events";
79344
- var log29 = createLogger("checker");
79397
+ var log31 = createLogger("checker");
79345
79398
  var PACKAGE_NAME = "claude-threads";
79346
79399
  function compareVersions(a, b) {
79347
79400
  const partsA = a.replace(/^v/, "").split(".").map(Number);
@@ -79364,13 +79417,13 @@ async function fetchLatestVersion() {
79364
79417
  }
79365
79418
  });
79366
79419
  if (!response.ok) {
79367
- log29.warn(`Failed to fetch latest version: HTTP ${response.status}`);
79420
+ log31.warn(`Failed to fetch latest version: HTTP ${response.status}`);
79368
79421
  return null;
79369
79422
  }
79370
79423
  const data = await response.json();
79371
79424
  return data.version ?? null;
79372
79425
  } catch (err) {
79373
- log29.warn(`Failed to fetch latest version: ${err}`);
79426
+ log31.warn(`Failed to fetch latest version: ${err}`);
79374
79427
  return null;
79375
79428
  }
79376
79429
  }
@@ -79387,38 +79440,38 @@ class UpdateChecker extends EventEmitter7 {
79387
79440
  }
79388
79441
  start() {
79389
79442
  if (!this.config.enabled) {
79390
- log29.debug("Auto-update disabled, not starting checker");
79443
+ log31.debug("Auto-update disabled, not starting checker");
79391
79444
  return;
79392
79445
  }
79393
79446
  setTimeout(() => {
79394
79447
  this.check().catch((err) => {
79395
- log29.warn(`Initial update check failed: ${err}`);
79448
+ log31.warn(`Initial update check failed: ${err}`);
79396
79449
  });
79397
79450
  }, 5000);
79398
79451
  const intervalMs = this.config.checkIntervalMinutes * 60 * 1000;
79399
79452
  this.checkInterval = setInterval(() => {
79400
79453
  this.check().catch((err) => {
79401
- log29.warn(`Periodic update check failed: ${err}`);
79454
+ log31.warn(`Periodic update check failed: ${err}`);
79402
79455
  });
79403
79456
  }, intervalMs);
79404
- log29.info(`\uD83D\uDD04 Update checker started (every ${this.config.checkIntervalMinutes} minutes)`);
79457
+ log31.info(`\uD83D\uDD04 Update checker started (every ${this.config.checkIntervalMinutes} minutes)`);
79405
79458
  }
79406
79459
  stop() {
79407
79460
  if (this.checkInterval) {
79408
79461
  clearInterval(this.checkInterval);
79409
79462
  this.checkInterval = null;
79410
79463
  }
79411
- log29.debug("Update checker stopped");
79464
+ log31.debug("Update checker stopped");
79412
79465
  }
79413
79466
  async check() {
79414
79467
  if (this.isChecking) {
79415
- log29.debug("Check already in progress, skipping");
79468
+ log31.debug("Check already in progress, skipping");
79416
79469
  return this.lastUpdateInfo;
79417
79470
  }
79418
79471
  this.isChecking = true;
79419
79472
  this.emit("check:start");
79420
79473
  try {
79421
- log29.debug("Checking for updates...");
79474
+ log31.debug("Checking for updates...");
79422
79475
  const latestVersion2 = await fetchLatestVersion();
79423
79476
  if (!latestVersion2) {
79424
79477
  this.emit("check:complete", false);
@@ -79435,18 +79488,18 @@ class UpdateChecker extends EventEmitter7 {
79435
79488
  detectedAt: new Date
79436
79489
  };
79437
79490
  if (!this.lastUpdateInfo || this.lastUpdateInfo.latestVersion !== latestVersion2) {
79438
- log29.info(`\uD83C\uDD95 Update available: v${currentVersion} → v${latestVersion2}`);
79491
+ log31.info(`\uD83C\uDD95 Update available: v${currentVersion} → v${latestVersion2}`);
79439
79492
  this.lastUpdateInfo = updateInfo;
79440
79493
  this.emit("update", updateInfo);
79441
79494
  }
79442
79495
  this.emit("check:complete", true);
79443
79496
  return updateInfo;
79444
79497
  }
79445
- log29.debug(`Up to date (v${currentVersion})`);
79498
+ log31.debug(`Up to date (v${currentVersion})`);
79446
79499
  this.emit("check:complete", false);
79447
79500
  return null;
79448
79501
  } catch (err) {
79449
- log29.warn(`Update check failed: ${err}`);
79502
+ log31.warn(`Update check failed: ${err}`);
79450
79503
  this.emit("check:error", err);
79451
79504
  return null;
79452
79505
  } finally {
@@ -79517,7 +79570,7 @@ function isInScheduledWindow(window2) {
79517
79570
  }
79518
79571
 
79519
79572
  // src/auto-update/scheduler.ts
79520
- var log30 = createLogger("scheduler");
79573
+ var log32 = createLogger("scheduler");
79521
79574
 
79522
79575
  class UpdateScheduler extends EventEmitter8 {
79523
79576
  config;
@@ -79541,7 +79594,7 @@ class UpdateScheduler extends EventEmitter8 {
79541
79594
  scheduleUpdate(updateInfo) {
79542
79595
  this.pendingUpdate = updateInfo;
79543
79596
  if (this.config.autoRestartMode === "immediate") {
79544
- log30.info("Immediate mode: triggering update now");
79597
+ log32.info("Immediate mode: triggering update now");
79545
79598
  this.emit("ready", updateInfo);
79546
79599
  return;
79547
79600
  }
@@ -79554,19 +79607,19 @@ class UpdateScheduler extends EventEmitter8 {
79554
79607
  this.scheduledRestartAt = null;
79555
79608
  this.askApprovals.clear();
79556
79609
  this.askStartTime = null;
79557
- log30.debug("Update schedule cancelled");
79610
+ log32.debug("Update schedule cancelled");
79558
79611
  }
79559
79612
  deferUpdate(minutes) {
79560
79613
  const deferUntil = new Date(Date.now() + minutes * 60 * 1000);
79561
79614
  this.scheduledRestartAt = null;
79562
79615
  this.idleStartTime = null;
79563
79616
  this.emit("deferred", deferUntil);
79564
- log30.info(`Update deferred until ${deferUntil.toLocaleTimeString()}`);
79617
+ log32.info(`Update deferred until ${deferUntil.toLocaleTimeString()}`);
79565
79618
  return deferUntil;
79566
79619
  }
79567
79620
  recordAskResponse(threadId, approved) {
79568
79621
  this.askApprovals.set(threadId, approved);
79569
- log30.debug(`Thread ${threadId.substring(0, 8)} ${approved ? "approved" : "denied"} update`);
79622
+ log32.debug(`Thread ${threadId.substring(0, 8)} ${approved ? "approved" : "denied"} update`);
79570
79623
  this.checkAskCondition();
79571
79624
  }
79572
79625
  getScheduledRestartAt() {
@@ -79587,7 +79640,7 @@ class UpdateScheduler extends EventEmitter8 {
79587
79640
  return;
79588
79641
  this.checkCondition();
79589
79642
  this.checkTimer = setInterval(() => this.checkCondition(), 1e4);
79590
- log30.debug(`Started checking for ${this.config.autoRestartMode} condition`);
79643
+ log32.debug(`Started checking for ${this.config.autoRestartMode} condition`);
79591
79644
  }
79592
79645
  stopChecking() {
79593
79646
  if (this.checkTimer) {
@@ -79618,17 +79671,17 @@ class UpdateScheduler extends EventEmitter8 {
79618
79671
  if (activity.activeSessionCount === 0) {
79619
79672
  if (!this.idleStartTime) {
79620
79673
  this.idleStartTime = new Date;
79621
- log30.debug("No active sessions, starting idle timer");
79674
+ log32.debug("No active sessions, starting idle timer");
79622
79675
  }
79623
79676
  const idleMs = Date.now() - this.idleStartTime.getTime();
79624
79677
  const requiredMs = this.config.idleTimeoutMinutes * 60 * 1000;
79625
79678
  if (idleMs >= requiredMs) {
79626
- log30.info(`Idle for ${this.config.idleTimeoutMinutes} minutes, triggering update`);
79679
+ log32.info(`Idle for ${this.config.idleTimeoutMinutes} minutes, triggering update`);
79627
79680
  this.triggerCountdown();
79628
79681
  }
79629
79682
  } else {
79630
79683
  if (this.idleStartTime) {
79631
- log30.debug("Sessions became active, resetting idle timer");
79684
+ log32.debug("Sessions became active, resetting idle timer");
79632
79685
  this.idleStartTime = null;
79633
79686
  }
79634
79687
  }
@@ -79639,7 +79692,7 @@ class UpdateScheduler extends EventEmitter8 {
79639
79692
  const quietMs = Date.now() - activity.lastActivityAt.getTime();
79640
79693
  const requiredMs = this.config.quietTimeoutMinutes * 60 * 1000;
79641
79694
  if (quietMs >= requiredMs && !activity.anySessionBusy) {
79642
- log30.info(`Sessions quiet for ${this.config.quietTimeoutMinutes} minutes, triggering update`);
79695
+ log32.info(`Sessions quiet for ${this.config.quietTimeoutMinutes} minutes, triggering update`);
79643
79696
  this.triggerCountdown();
79644
79697
  }
79645
79698
  } else if (activity.activeSessionCount === 0) {
@@ -79649,7 +79702,7 @@ class UpdateScheduler extends EventEmitter8 {
79649
79702
  const idleMs = Date.now() - this.idleStartTime.getTime();
79650
79703
  const requiredMs = this.config.quietTimeoutMinutes * 60 * 1000;
79651
79704
  if (idleMs >= requiredMs) {
79652
- log30.info("No sessions and quiet timeout reached, triggering update");
79705
+ log32.info("No sessions and quiet timeout reached, triggering update");
79653
79706
  this.triggerCountdown();
79654
79707
  }
79655
79708
  }
@@ -79660,13 +79713,13 @@ class UpdateScheduler extends EventEmitter8 {
79660
79713
  }
79661
79714
  const activity = this.getSessionActivity();
79662
79715
  if (activity.activeSessionCount === 0) {
79663
- log30.info("Within scheduled window and no active sessions, triggering update");
79716
+ log32.info("Within scheduled window and no active sessions, triggering update");
79664
79717
  this.triggerCountdown();
79665
79718
  } else if (activity.lastActivityAt) {
79666
79719
  const quietMs = Date.now() - activity.lastActivityAt.getTime();
79667
79720
  const requiredMs = this.config.idleTimeoutMinutes * 60 * 1000;
79668
79721
  if (quietMs >= requiredMs && !activity.anySessionBusy) {
79669
- log30.info("Within scheduled window and sessions quiet, triggering update");
79722
+ log32.info("Within scheduled window and sessions quiet, triggering update");
79670
79723
  this.triggerCountdown();
79671
79724
  }
79672
79725
  }
@@ -79674,14 +79727,14 @@ class UpdateScheduler extends EventEmitter8 {
79674
79727
  checkAskCondition() {
79675
79728
  const threadIds = this.getActiveThreadIds();
79676
79729
  if (threadIds.length === 0) {
79677
- log30.info("No active threads, proceeding with update");
79730
+ log32.info("No active threads, proceeding with update");
79678
79731
  this.triggerCountdown();
79679
79732
  return;
79680
79733
  }
79681
79734
  if (!this.askStartTime && this.pendingUpdate) {
79682
79735
  this.askStartTime = new Date;
79683
79736
  this.postAskMessage(threadIds, this.pendingUpdate.latestVersion).catch((err) => {
79684
- log30.warn(`Failed to post ask message: ${err}`);
79737
+ log32.warn(`Failed to post ask message: ${err}`);
79685
79738
  });
79686
79739
  return;
79687
79740
  }
@@ -79694,12 +79747,12 @@ class UpdateScheduler extends EventEmitter8 {
79694
79747
  denials++;
79695
79748
  }
79696
79749
  if (approvals > threadIds.length / 2) {
79697
- log30.info(`Majority approved (${approvals}/${threadIds.length}), triggering update`);
79750
+ log32.info(`Majority approved (${approvals}/${threadIds.length}), triggering update`);
79698
79751
  this.triggerCountdown();
79699
79752
  return;
79700
79753
  }
79701
79754
  if (denials > threadIds.length / 2) {
79702
- log30.info(`Majority denied (${denials}/${threadIds.length}), deferring update`);
79755
+ log32.info(`Majority denied (${denials}/${threadIds.length}), deferring update`);
79703
79756
  this.deferUpdate(60);
79704
79757
  return;
79705
79758
  }
@@ -79707,7 +79760,7 @@ class UpdateScheduler extends EventEmitter8 {
79707
79760
  const elapsedMs = Date.now() - this.askStartTime.getTime();
79708
79761
  const timeoutMs = this.config.askTimeoutMinutes * 60 * 1000;
79709
79762
  if (elapsedMs >= timeoutMs) {
79710
- log30.info(`Ask timeout reached (${this.config.askTimeoutMinutes} min), triggering update`);
79763
+ log32.info(`Ask timeout reached (${this.config.askTimeoutMinutes} min), triggering update`);
79711
79764
  this.triggerCountdown();
79712
79765
  }
79713
79766
  }
@@ -79727,7 +79780,7 @@ class UpdateScheduler extends EventEmitter8 {
79727
79780
  this.emit("ready", this.pendingUpdate);
79728
79781
  }
79729
79782
  }, 1000);
79730
- log30.info("Update countdown started (60 seconds)");
79783
+ log32.info("Update countdown started (60 seconds)");
79731
79784
  }
79732
79785
  stopCountdown() {
79733
79786
  if (this.countdownTimer) {
@@ -79743,24 +79796,24 @@ import { spawn as spawn4, spawnSync } from "child_process";
79743
79796
  import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync4 } from "fs";
79744
79797
  import { dirname as dirname8, resolve as resolve6 } from "path";
79745
79798
  import { homedir as homedir5 } from "os";
79746
- var log31 = createLogger("installer");
79799
+ var log33 = createLogger("installer");
79747
79800
  function detectPackageManager() {
79748
79801
  const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
79749
79802
  const originalInstaller = detectOriginalInstaller();
79750
79803
  if (originalInstaller) {
79751
- log31.debug(`Detected original installer: ${originalInstaller}`);
79804
+ log33.debug(`Detected original installer: ${originalInstaller}`);
79752
79805
  if (originalInstaller === "bun") {
79753
79806
  const bunCheck2 = spawnSync("bun", ["--version"], { stdio: "ignore" });
79754
79807
  if (bunCheck2.status === 0) {
79755
79808
  return { cmd: "bun", isBun: true };
79756
79809
  }
79757
- log31.warn("Originally installed with bun, but bun not found. Falling back to npm.");
79810
+ log33.warn("Originally installed with bun, but bun not found. Falling back to npm.");
79758
79811
  } else {
79759
79812
  const npmCheck2 = spawnSync(npmCmd, ["--version"], { stdio: "ignore" });
79760
79813
  if (npmCheck2.status === 0) {
79761
79814
  return { cmd: npmCmd, isBun: false };
79762
79815
  }
79763
- log31.warn("Originally installed with npm, but npm not found. Falling back to bun.");
79816
+ log33.warn("Originally installed with npm, but npm not found. Falling back to bun.");
79764
79817
  }
79765
79818
  }
79766
79819
  const bunCheck = spawnSync("bun", ["--version"], { stdio: "ignore" });
@@ -79811,7 +79864,7 @@ function loadUpdateState() {
79811
79864
  return JSON.parse(content);
79812
79865
  }
79813
79866
  } catch (err) {
79814
- log31.warn(`Failed to load update state: ${err}`);
79867
+ log33.warn(`Failed to load update state: ${err}`);
79815
79868
  }
79816
79869
  return {};
79817
79870
  }
@@ -79822,9 +79875,9 @@ function saveUpdateState(state) {
79822
79875
  mkdirSync4(dir, { recursive: true });
79823
79876
  }
79824
79877
  writeFileSync6(STATE_PATH, JSON.stringify(state, null, 2), "utf-8");
79825
- log31.debug("Update state saved");
79878
+ log33.debug("Update state saved");
79826
79879
  } catch (err) {
79827
- log31.warn(`Failed to save update state: ${err}`);
79880
+ log33.warn(`Failed to save update state: ${err}`);
79828
79881
  }
79829
79882
  }
79830
79883
  function clearUpdateState() {
@@ -79833,7 +79886,7 @@ function clearUpdateState() {
79833
79886
  writeFileSync6(STATE_PATH, "{}", "utf-8");
79834
79887
  }
79835
79888
  } catch (err) {
79836
- log31.warn(`Failed to clear update state: ${err}`);
79889
+ log33.warn(`Failed to clear update state: ${err}`);
79837
79890
  }
79838
79891
  }
79839
79892
  function checkJustUpdated() {
@@ -79865,11 +79918,11 @@ function clearRuntimeSettings() {
79865
79918
  }
79866
79919
  }
79867
79920
  async function installVersion(version) {
79868
- log31.info(`\uD83D\uDCE6 Installing ${PACKAGE_NAME2}@${version}...`);
79921
+ log33.info(`\uD83D\uDCE6 Installing ${PACKAGE_NAME2}@${version}...`);
79869
79922
  const pm = detectPackageManager();
79870
79923
  if (!pm) {
79871
79924
  const error = "Neither bun nor npm found in PATH. Cannot install update.";
79872
- log31.error(`❌ ${error}`);
79925
+ log33.error(`❌ ${error}`);
79873
79926
  return { success: false, error };
79874
79927
  }
79875
79928
  saveUpdateState({
@@ -79881,7 +79934,7 @@ async function installVersion(version) {
79881
79934
  return new Promise((resolve7) => {
79882
79935
  const { cmd, isBun: isBun3 } = pm;
79883
79936
  const args = ["install", "-g", `${PACKAGE_NAME2}@${version}`];
79884
- log31.debug(`Using ${isBun3 ? "bun" : "npm"} for installation`);
79937
+ log33.debug(`Using ${isBun3 ? "bun" : "npm"} for installation`);
79885
79938
  const child = spawn4(cmd, args, {
79886
79939
  stdio: ["ignore", "pipe", "pipe"],
79887
79940
  env: {
@@ -79899,7 +79952,7 @@ async function installVersion(version) {
79899
79952
  });
79900
79953
  child.on("close", (code) => {
79901
79954
  if (code === 0) {
79902
- log31.info(`✅ Successfully installed ${PACKAGE_NAME2}@${version}`);
79955
+ log33.info(`✅ Successfully installed ${PACKAGE_NAME2}@${version}`);
79903
79956
  saveUpdateState({
79904
79957
  previousVersion: VERSION,
79905
79958
  targetVersion: version,
@@ -79909,20 +79962,20 @@ async function installVersion(version) {
79909
79962
  resolve7({ success: true });
79910
79963
  } else {
79911
79964
  const errorMsg = stderr || stdout || `Exit code: ${code}`;
79912
- log31.error(`❌ Installation failed: ${errorMsg}`);
79965
+ log33.error(`❌ Installation failed: ${errorMsg}`);
79913
79966
  clearUpdateState();
79914
79967
  resolve7({ success: false, error: errorMsg });
79915
79968
  }
79916
79969
  });
79917
79970
  child.on("error", (err) => {
79918
- log31.error(`❌ Failed to spawn npm: ${err}`);
79971
+ log33.error(`❌ Failed to spawn npm: ${err}`);
79919
79972
  clearUpdateState();
79920
79973
  resolve7({ success: false, error: err.message });
79921
79974
  });
79922
79975
  setTimeout(() => {
79923
79976
  if (child.exitCode === null) {
79924
79977
  child.kill();
79925
- log31.error("❌ Installation timed out");
79978
+ log33.error("❌ Installation timed out");
79926
79979
  clearUpdateState();
79927
79980
  resolve7({ success: false, error: "Installation timed out" });
79928
79981
  }
@@ -79964,7 +80017,7 @@ class UpdateInstaller {
79964
80017
  }
79965
80018
 
79966
80019
  // src/auto-update/manager.ts
79967
- var log32 = createLogger("updater");
80020
+ var log34 = createLogger("updater");
79968
80021
 
79969
80022
  class AutoUpdateManager extends EventEmitter9 {
79970
80023
  config;
@@ -79987,23 +80040,23 @@ class AutoUpdateManager extends EventEmitter9 {
79987
80040
  }
79988
80041
  start() {
79989
80042
  if (!this.config.enabled) {
79990
- log32.info("Auto-update is disabled");
80043
+ log34.info("Auto-update is disabled");
79991
80044
  return;
79992
80045
  }
79993
80046
  const updateResult = this.installer.checkJustUpdated();
79994
80047
  if (updateResult) {
79995
- log32.info(`\uD83C\uDF89 Updated from v${updateResult.previousVersion} to v${updateResult.currentVersion}`);
80048
+ log34.info(`\uD83C\uDF89 Updated from v${updateResult.previousVersion} to v${updateResult.currentVersion}`);
79996
80049
  this.callbacks.broadcastUpdate((fmt) => `\uD83C\uDF89 ${fmt.formatBold("Bot updated")} from v${updateResult.previousVersion} to v${updateResult.currentVersion}`).catch((err) => {
79997
- log32.warn(`Failed to broadcast update notification: ${err}`);
80050
+ log34.warn(`Failed to broadcast update notification: ${err}`);
79998
80051
  });
79999
80052
  }
80000
80053
  this.checker.start();
80001
- log32.info(`\uD83D\uDD04 Auto-update manager started (mode: ${this.config.autoRestartMode})`);
80054
+ log34.info(`\uD83D\uDD04 Auto-update manager started (mode: ${this.config.autoRestartMode})`);
80002
80055
  }
80003
80056
  stop() {
80004
80057
  this.checker.stop();
80005
80058
  this.scheduler.stop();
80006
- log32.debug("Auto-update manager stopped");
80059
+ log34.debug("Auto-update manager stopped");
80007
80060
  }
80008
80061
  getState() {
80009
80062
  return { ...this.state };
@@ -80017,10 +80070,10 @@ class AutoUpdateManager extends EventEmitter9 {
80017
80070
  async forceUpdate() {
80018
80071
  const updateInfo = this.state.updateInfo || await this.checker.check();
80019
80072
  if (!updateInfo) {
80020
- log32.info("No update available");
80073
+ log34.info("No update available");
80021
80074
  return;
80022
80075
  }
80023
- log32.info("Forcing immediate update");
80076
+ log34.info("Forcing immediate update");
80024
80077
  await this.performUpdate(updateInfo);
80025
80078
  }
80026
80079
  deferUpdate(minutes = 60) {
@@ -80075,7 +80128,7 @@ class AutoUpdateManager extends EventEmitter9 {
80075
80128
  await this.callbacks.broadcastUpdate((fmt) => `✅ ${fmt.formatBold("Update installed")} - restarting now. ${fmt.formatItalic("Sessions will resume automatically.")}`).catch(() => {});
80076
80129
  await new Promise((resolve7) => setTimeout(resolve7, 1000));
80077
80130
  await this.callbacks.prepareForRestart();
80078
- log32.info(`\uD83D\uDD04 Restarting for update to v${updateInfo.latestVersion}`);
80131
+ log34.info(`\uD83D\uDD04 Restarting for update to v${updateInfo.latestVersion}`);
80079
80132
  process.stdout.write("\x1B[2J\x1B[H");
80080
80133
  process.stdout.write("\x1B[?25h");
80081
80134
  process.exit(RESTART_EXIT_CODE);