claude-threads 1.9.1 → 1.9.3

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() {
@@ -51565,6 +51565,23 @@ function truncateAtWord(str2, maxLength) {
51565
51565
  function escapeRegExp(string) {
51566
51566
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
51567
51567
  }
51568
+ function formatWebSocketError(err) {
51569
+ if (err instanceof Error)
51570
+ return err.message;
51571
+ if (err && typeof err === "object") {
51572
+ const e = err;
51573
+ if (typeof e.message === "string" && e.message)
51574
+ return e.message;
51575
+ if (e.error instanceof Error)
51576
+ return e.error.message;
51577
+ if (typeof e.error === "string" && e.error)
51578
+ return e.error;
51579
+ if (typeof e.type === "string" && e.type) {
51580
+ return typeof e.code === "string" || typeof e.code === "number" ? `${e.type} (code: ${e.code})` : e.type;
51581
+ }
51582
+ }
51583
+ return String(err);
51584
+ }
51568
51585
  function getPlatformIcon(platformType) {
51569
51586
  switch (platformType) {
51570
51587
  case "slack":
@@ -52110,9 +52127,10 @@ class MattermostClient extends BasePlatformClient {
52110
52127
  this.onConnectionClosed();
52111
52128
  };
52112
52129
  this.ws.onerror = (event) => {
52113
- wsLogger.warn(`WebSocket error: ${event}`);
52114
- this.emit("error", event);
52115
- reject(event);
52130
+ const msg = formatWebSocketError(event);
52131
+ wsLogger.warn(`WebSocket error: ${msg}`);
52132
+ this.emit("error", new Error(`WebSocket error: ${msg}`));
52133
+ reject(new Error(`WebSocket error: ${msg}`));
52116
52134
  };
52117
52135
  });
52118
52136
  }
@@ -52540,11 +52558,12 @@ class SlackClient extends BasePlatformClient {
52540
52558
  };
52541
52559
  this.ws.onerror = (event) => {
52542
52560
  clearTimeout(connectionTimeout);
52543
- wsLogger.warn(`Socket Mode: WebSocket error: ${event}`);
52561
+ const msg = formatWebSocketError(event);
52562
+ wsLogger.warn(`Socket Mode: WebSocket error: ${msg}`);
52544
52563
  if (!this.isIntentionalDisconnect && !this.isReconnecting) {
52545
- this.emit("error", new Error("Socket Mode WebSocket error"));
52564
+ this.emit("error", new Error(`Socket Mode WebSocket error: ${msg}`));
52546
52565
  }
52547
- doReject(new Error("Socket Mode WebSocket error"));
52566
+ doReject(new Error(`Socket Mode WebSocket error: ${msg}`));
52548
52567
  };
52549
52568
  });
52550
52569
  }
@@ -53160,7 +53179,7 @@ class MattermostPermissionApi {
53160
53179
  }
53161
53180
  };
53162
53181
  ws.onerror = (event) => {
53163
- mcpLogger.error(`WebSocket error: ${event}`);
53182
+ mcpLogger.error(`WebSocket error: ${formatWebSocketError(event)}`);
53164
53183
  if (!resolved) {
53165
53184
  resolved = true;
53166
53185
  clearTimeout(timeout);
@@ -53356,7 +53375,7 @@ class SlackPermissionApi {
53356
53375
  }
53357
53376
  };
53358
53377
  ws.onerror = (event) => {
53359
- mcpLogger.error(`Socket Mode WebSocket error: ${event}`);
53378
+ mcpLogger.error(`Socket Mode WebSocket error: ${formatWebSocketError(event)}`);
53360
53379
  if (!resolved) {
53361
53380
  resolved = true;
53362
53381
  clearTimeout(timeout);
@@ -53731,9 +53750,6 @@ class AccountPool {
53731
53750
  }
53732
53751
  }
53733
53752
 
53734
- // src/session/manager.ts
53735
- init_emoji();
53736
-
53737
53753
  // src/cleanup/scheduler.ts
53738
53754
  init_logger();
53739
53755
  import { existsSync as existsSync7 } from "fs";
@@ -54194,6 +54210,50 @@ class CleanupScheduler {
54194
54210
  // src/operations/monitor/handler.ts
54195
54211
  init_logger();
54196
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
+
54197
54257
  // src/session/timer-manager.ts
54198
54258
  function createSessionTimers() {
54199
54259
  return {
@@ -54239,6 +54299,7 @@ function isSessionCancelled(session) {
54239
54299
  return session.lifecycle.state === "cancelling";
54240
54300
  }
54241
54301
  function transitionTo(session, newState) {
54302
+ checkTransition(session.lifecycle.state, newState, session.sessionId);
54242
54303
  session.lifecycle.state = newState;
54243
54304
  }
54244
54305
  function markClaudeResponded(session) {
@@ -54326,7 +54387,7 @@ function extractResetAt(text, now) {
54326
54387
  }
54327
54388
 
54328
54389
  // src/claude/cli.ts
54329
- var log9 = createLogger("claude");
54390
+ var log10 = createLogger("claude");
54330
54391
  function cleanupBrowserBridgeSockets() {
54331
54392
  try {
54332
54393
  const tempDir = tmpdir();
@@ -54338,13 +54399,13 @@ function cleanupBrowserBridgeSockets() {
54338
54399
  const stats = statSync2(filePath);
54339
54400
  if (stats.isSocket()) {
54340
54401
  unlinkSync2(filePath);
54341
- log9.debug(`Removed stale browser bridge socket: ${file}`);
54402
+ log10.debug(`Removed stale browser bridge socket: ${file}`);
54342
54403
  }
54343
54404
  } catch {}
54344
54405
  }
54345
54406
  }
54346
54407
  } catch (err) {
54347
- log9.debug(`Browser bridge cleanup failed: ${err}`);
54408
+ log10.debug(`Browser bridge cleanup failed: ${err}`);
54348
54409
  }
54349
54410
  }
54350
54411
  function buildClaudeChildEnv(parentEnv, account) {
@@ -54375,7 +54436,7 @@ function isErrorResultEvent(event) {
54375
54436
  return false;
54376
54437
  }
54377
54438
  function materializeMcpConfig(config, sessionId, opts = {}) {
54378
- if (opts.inline ?? process.env.CLAUDE_THREADS_MCP_CONFIG_INLINE === "1") {
54439
+ if (opts.inline) {
54379
54440
  return { mode: "inline", value: JSON.stringify(config) };
54380
54441
  }
54381
54442
  const dir = opts.tmpDirOverride ?? tmpdir();
@@ -55580,7 +55641,7 @@ import { existsSync as existsSync11 } from "fs";
55580
55641
  // src/utils/keep-alive.ts
55581
55642
  init_logger();
55582
55643
  import { spawn as spawn2 } from "child_process";
55583
- var log10 = createLogger("keepalive");
55644
+ var log11 = createLogger("keepalive");
55584
55645
 
55585
55646
  class KeepAliveManager {
55586
55647
  activeSessionCount = 0;
@@ -55595,7 +55656,7 @@ class KeepAliveManager {
55595
55656
  if (!enabled && this.keepAliveProcess) {
55596
55657
  this.stopKeepAlive();
55597
55658
  }
55598
- log10.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
55659
+ log11.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
55599
55660
  }
55600
55661
  isEnabled() {
55601
55662
  return this.enabled;
@@ -55605,7 +55666,7 @@ class KeepAliveManager {
55605
55666
  }
55606
55667
  sessionStarted() {
55607
55668
  this.activeSessionCount++;
55608
- log10.debug(`Session started (${this.activeSessionCount} active)`);
55669
+ log11.debug(`Session started (${this.activeSessionCount} active)`);
55609
55670
  if (this.activeSessionCount === 1) {
55610
55671
  this.startKeepAlive();
55611
55672
  }
@@ -55614,7 +55675,7 @@ class KeepAliveManager {
55614
55675
  if (this.activeSessionCount > 0) {
55615
55676
  this.activeSessionCount--;
55616
55677
  }
55617
- log10.debug(`Session ended (${this.activeSessionCount} active)`);
55678
+ log11.debug(`Session ended (${this.activeSessionCount} active)`);
55618
55679
  if (this.activeSessionCount === 0) {
55619
55680
  this.stopKeepAlive();
55620
55681
  }
@@ -55628,11 +55689,11 @@ class KeepAliveManager {
55628
55689
  }
55629
55690
  startKeepAlive() {
55630
55691
  if (!this.enabled) {
55631
- log10.debug("Keep-alive disabled, skipping");
55692
+ log11.debug("Keep-alive disabled, skipping");
55632
55693
  return;
55633
55694
  }
55634
55695
  if (this.keepAliveProcess) {
55635
- log10.debug("Keep-alive already running");
55696
+ log11.debug("Keep-alive already running");
55636
55697
  return;
55637
55698
  }
55638
55699
  switch (this.platform) {
@@ -55646,12 +55707,12 @@ class KeepAliveManager {
55646
55707
  this.startWindowsKeepAlive();
55647
55708
  break;
55648
55709
  default:
55649
- log10.warn(`Keep-alive not supported on ${this.platform}`);
55710
+ log11.warn(`Keep-alive not supported on ${this.platform}`);
55650
55711
  }
55651
55712
  }
55652
55713
  stopKeepAlive() {
55653
55714
  if (this.keepAliveProcess) {
55654
- log10.debug("Stopping keep-alive");
55715
+ log11.debug("Stopping keep-alive");
55655
55716
  this.keepAliveProcess.kill();
55656
55717
  this.keepAliveProcess = null;
55657
55718
  }
@@ -55663,18 +55724,18 @@ class KeepAliveManager {
55663
55724
  detached: false
55664
55725
  });
55665
55726
  this.keepAliveProcess.on("error", (err) => {
55666
- log10.error(`Failed to start caffeinate: ${err.message}`);
55727
+ log11.error(`Failed to start caffeinate: ${err.message}`);
55667
55728
  this.keepAliveProcess = null;
55668
55729
  });
55669
55730
  this.keepAliveProcess.on("exit", (code) => {
55670
55731
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55671
- log10.debug(`caffeinate exited with code ${code}`);
55732
+ log11.debug(`caffeinate exited with code ${code}`);
55672
55733
  }
55673
55734
  this.keepAliveProcess = null;
55674
55735
  });
55675
- log10.info("Sleep prevention active (caffeinate)");
55736
+ log11.info("Sleep prevention active (caffeinate)");
55676
55737
  } catch (err) {
55677
- log10.error(`Failed to start caffeinate: ${err}`);
55738
+ log11.error(`Failed to start caffeinate: ${err}`);
55678
55739
  }
55679
55740
  }
55680
55741
  startLinuxKeepAlive() {
@@ -55690,19 +55751,19 @@ class KeepAliveManager {
55690
55751
  detached: false
55691
55752
  });
55692
55753
  this.keepAliveProcess.on("error", (err) => {
55693
- log10.debug(`systemd-inhibit not available: ${err.message}`);
55754
+ log11.debug(`systemd-inhibit not available: ${err.message}`);
55694
55755
  this.keepAliveProcess = null;
55695
55756
  this.startLinuxKeepAliveFallback();
55696
55757
  });
55697
55758
  this.keepAliveProcess.on("exit", (code) => {
55698
55759
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55699
- log10.debug(`systemd-inhibit exited with code ${code}`);
55760
+ log11.debug(`systemd-inhibit exited with code ${code}`);
55700
55761
  }
55701
55762
  this.keepAliveProcess = null;
55702
55763
  });
55703
- log10.info("Sleep prevention active (systemd-inhibit)");
55764
+ log11.info("Sleep prevention active (systemd-inhibit)");
55704
55765
  } catch (err) {
55705
- log10.debug(`Failed to start systemd-inhibit: ${err}`);
55766
+ log11.debug(`Failed to start systemd-inhibit: ${err}`);
55706
55767
  this.startLinuxKeepAliveFallback();
55707
55768
  }
55708
55769
  }
@@ -55716,15 +55777,15 @@ class KeepAliveManager {
55716
55777
  detached: false
55717
55778
  });
55718
55779
  this.keepAliveProcess.on("error", (err) => {
55719
- log10.warn(`Linux keep-alive fallback not available: ${err.message}`);
55780
+ log11.warn(`Linux keep-alive fallback not available: ${err.message}`);
55720
55781
  this.keepAliveProcess = null;
55721
55782
  });
55722
55783
  this.keepAliveProcess.on("exit", () => {
55723
55784
  this.keepAliveProcess = null;
55724
55785
  });
55725
- log10.info("Sleep prevention active (xdg-screensaver)");
55786
+ log11.info("Sleep prevention active (xdg-screensaver)");
55726
55787
  } catch (err) {
55727
- log10.warn(`Linux keep-alive not available: ${err}`);
55788
+ log11.warn(`Linux keep-alive not available: ${err}`);
55728
55789
  }
55729
55790
  }
55730
55791
  startWindowsKeepAlive() {
@@ -55749,18 +55810,18 @@ class KeepAliveManager {
55749
55810
  windowsHide: true
55750
55811
  });
55751
55812
  this.keepAliveProcess.on("error", (err) => {
55752
- log10.warn(`Windows keep-alive not available: ${err.message}`);
55813
+ log11.warn(`Windows keep-alive not available: ${err.message}`);
55753
55814
  this.keepAliveProcess = null;
55754
55815
  });
55755
55816
  this.keepAliveProcess.on("exit", (code) => {
55756
55817
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55757
- log10.debug(`PowerShell keep-alive exited with code ${code}`);
55818
+ log11.debug(`PowerShell keep-alive exited with code ${code}`);
55758
55819
  }
55759
55820
  this.keepAliveProcess = null;
55760
55821
  });
55761
- log10.info("Sleep prevention active (SetThreadExecutionState)");
55822
+ log11.info("Sleep prevention active (SetThreadExecutionState)");
55762
55823
  } catch (err) {
55763
- log10.warn(`Windows keep-alive not available: ${err}`);
55824
+ log11.warn(`Windows keep-alive not available: ${err}`);
55764
55825
  }
55765
55826
  }
55766
55827
  }
@@ -55768,7 +55829,7 @@ var keepAlive = new KeepAliveManager;
55768
55829
 
55769
55830
  // src/utils/error-handler/index.ts
55770
55831
  init_logger();
55771
- var log11 = createLogger("error");
55832
+ var log12 = createLogger("error");
55772
55833
 
55773
55834
  class SessionError extends Error {
55774
55835
  sessionId;
@@ -55794,19 +55855,19 @@ async function handleError(error, context, severity = "recoverable") {
55794
55855
  const sessionPart = sessionId ? ` (${formatShortId(sessionId)})` : "";
55795
55856
  const logMessage = `${context.action}${sessionPart}: ${message}`;
55796
55857
  if (severity === "recoverable") {
55797
- log11.warn(logMessage);
55858
+ log12.warn(logMessage);
55798
55859
  } else {
55799
- log11.error(logMessage, error instanceof Error ? error : undefined);
55860
+ log12.error(logMessage, error instanceof Error ? error : undefined);
55800
55861
  }
55801
55862
  if (context.details) {
55802
- log11.debugJson("Error details", context.details);
55863
+ log12.debugJson("Error details", context.details);
55803
55864
  }
55804
55865
  if (context.notifyUser && context.session) {
55805
55866
  try {
55806
55867
  const fmt = context.session.platform.getFormatter();
55807
55868
  await context.session.platform.createPost(`⚠️ ${fmt.formatBold("Error")}: ${context.action} failed - ${message}`, context.session.threadId);
55808
55869
  } catch (notifyError) {
55809
- log11.warn(`Could not notify user: ${notifyError}`);
55870
+ log12.warn(`Could not notify user: ${notifyError}`);
55810
55871
  }
55811
55872
  }
55812
55873
  if (severity === "session-fatal" || severity === "system-fatal") {
@@ -55833,7 +55894,7 @@ async function logAndNotify(error, context) {
55833
55894
  }
55834
55895
  function logSilentError(context, error) {
55835
55896
  const message = error instanceof Error ? error.message : String(error);
55836
- log11.debug(`[${context}] Silently caught: ${message}`);
55897
+ log12.debug(`[${context}] Silently caught: ${message}`);
55837
55898
  }
55838
55899
 
55839
55900
  // src/session/lifecycle.ts
@@ -55853,8 +55914,8 @@ function createSessionLog(baseLog) {
55853
55914
  init_logger();
55854
55915
  init_emoji();
55855
55916
  init_worktree();
55856
- var log12 = createLogger("helpers");
55857
- var sessionLog = createSessionLog(log12);
55917
+ var log13 = createLogger("helpers");
55918
+ var sessionLog = createSessionLog(log13);
55858
55919
  var POST_TYPES = {
55859
55920
  info: "",
55860
55921
  success: "✅",
@@ -55938,7 +55999,7 @@ function updateLastMessage(session, post2) {
55938
55999
  // src/claude/quick-query.ts
55939
56000
  init_spawn();
55940
56001
  init_logger();
55941
- var log13 = createLogger("query");
56002
+ var log14 = createLogger("query");
55942
56003
  async function quickQuery(options2) {
55943
56004
  const {
55944
56005
  prompt,
@@ -55954,7 +56015,7 @@ async function quickQuery(options2) {
55954
56015
  args.push("--system-prompt", systemPrompt);
55955
56016
  }
55956
56017
  args.push(prompt);
55957
- 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)}..."`);
55958
56019
  return new Promise((resolve5) => {
55959
56020
  let stdout = "";
55960
56021
  let stderr = "";
@@ -55968,7 +56029,7 @@ async function quickQuery(options2) {
55968
56029
  if (!resolved) {
55969
56030
  resolved = true;
55970
56031
  proc.kill("SIGTERM");
55971
- log13.debug(`Quick query timed out after ${timeout}ms`);
56032
+ log14.debug(`Quick query timed out after ${timeout}ms`);
55972
56033
  resolve5({
55973
56034
  success: false,
55974
56035
  error: "timeout",
@@ -55986,7 +56047,7 @@ async function quickQuery(options2) {
55986
56047
  if (!resolved) {
55987
56048
  resolved = true;
55988
56049
  clearTimeout(timeoutId);
55989
- log13.debug(`Quick query error: ${err.message}`);
56050
+ log14.debug(`Quick query error: ${err.message}`);
55990
56051
  resolve5({
55991
56052
  success: false,
55992
56053
  error: err.message,
@@ -56000,14 +56061,14 @@ async function quickQuery(options2) {
56000
56061
  clearTimeout(timeoutId);
56001
56062
  const durationMs = Date.now() - startTime;
56002
56063
  if (code === 0 && stdout.trim()) {
56003
- log13.debug(`Quick query success: ${durationMs}ms, ${stdout.length} chars`);
56064
+ log14.debug(`Quick query success: ${durationMs}ms, ${stdout.length} chars`);
56004
56065
  resolve5({
56005
56066
  success: true,
56006
56067
  response: stdout.trim(),
56007
56068
  durationMs
56008
56069
  });
56009
56070
  } else {
56010
- 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)}`);
56011
56072
  resolve5({
56012
56073
  success: false,
56013
56074
  error: stderr || `exit code ${code}`,
@@ -56022,7 +56083,7 @@ async function quickQuery(options2) {
56022
56083
 
56023
56084
  // src/operations/suggestions/title.ts
56024
56085
  init_logger();
56025
- var log14 = createLogger("title");
56086
+ var log15 = createLogger("title");
56026
56087
  var SUGGESTION_TIMEOUT = 15000;
56027
56088
  var MIN_TITLE_LENGTH = 3;
56028
56089
  var MAX_TITLE_LENGTH = 50;
@@ -56086,32 +56147,32 @@ function parseMetadata(response) {
56086
56147
  const titleMatch = response.match(/TITLE:\s*(.+)/i);
56087
56148
  const descMatch = response.match(/DESC:\s*(.+)/i);
56088
56149
  if (!titleMatch || !descMatch) {
56089
- log14.debug("Failed to parse title/description from response");
56150
+ log15.debug("Failed to parse title/description from response");
56090
56151
  return null;
56091
56152
  }
56092
56153
  let title = titleMatch[1].trim();
56093
56154
  let description = descMatch[1].trim();
56094
56155
  if (title.length < MIN_TITLE_LENGTH) {
56095
- log14.debug(`Title too short: ${title.length} chars`);
56156
+ log15.debug(`Title too short: ${title.length} chars`);
56096
56157
  return null;
56097
56158
  }
56098
56159
  if (title.length > MAX_TITLE_LENGTH) {
56099
- log14.debug(`Title too long (${title.length} chars), truncating`);
56160
+ log15.debug(`Title too long (${title.length} chars), truncating`);
56100
56161
  title = truncateAtWord(title, MAX_TITLE_LENGTH);
56101
56162
  }
56102
56163
  if (description.length < MIN_DESC_LENGTH) {
56103
- log14.debug(`Description too short: ${description.length} chars`);
56164
+ log15.debug(`Description too short: ${description.length} chars`);
56104
56165
  return null;
56105
56166
  }
56106
56167
  if (description.length > MAX_DESC_LENGTH) {
56107
- log14.debug(`Description too long (${description.length} chars), truncating`);
56168
+ log15.debug(`Description too long (${description.length} chars), truncating`);
56108
56169
  description = truncateAtWord(description, MAX_DESC_LENGTH);
56109
56170
  }
56110
56171
  return { title, description };
56111
56172
  }
56112
56173
  async function suggestSessionMetadata(context) {
56113
56174
  const logContext = typeof context === "string" ? context.substring(0, 50) : context.originalTask.substring(0, 50);
56114
- log14.debug(`Suggesting title for: "${logContext}..."`);
56175
+ log15.debug(`Suggesting title for: "${logContext}..."`);
56115
56176
  try {
56116
56177
  const result = await quickQuery({
56117
56178
  prompt: buildTitlePrompt(context),
@@ -56119,23 +56180,23 @@ async function suggestSessionMetadata(context) {
56119
56180
  timeout: SUGGESTION_TIMEOUT
56120
56181
  });
56121
56182
  if (!result.success || !result.response) {
56122
- log14.debug(`Title suggestion failed: ${result.error || "no response"}`);
56183
+ log15.debug(`Title suggestion failed: ${result.error || "no response"}`);
56123
56184
  return null;
56124
56185
  }
56125
56186
  const metadata = parseMetadata(result.response);
56126
56187
  if (metadata) {
56127
- log14.debug(`Got title: "${metadata.title}" (${result.durationMs}ms)`);
56188
+ log15.debug(`Got title: "${metadata.title}" (${result.durationMs}ms)`);
56128
56189
  }
56129
56190
  return metadata;
56130
56191
  } catch (err) {
56131
- log14.debug(`Title suggestion error: ${err}`);
56192
+ log15.debug(`Title suggestion error: ${err}`);
56132
56193
  return null;
56133
56194
  }
56134
56195
  }
56135
56196
 
56136
56197
  // src/operations/suggestions/tag.ts
56137
56198
  init_logger();
56138
- var log15 = createLogger("tags");
56199
+ var log16 = createLogger("tags");
56139
56200
  var SUGGESTION_TIMEOUT2 = 15000;
56140
56201
  var MAX_TAGS = 3;
56141
56202
  var VALID_TAGS = [
@@ -56167,7 +56228,7 @@ function parseTags(response) {
56167
56228
  return [...new Set(tags)].slice(0, MAX_TAGS);
56168
56229
  }
56169
56230
  async function suggestSessionTags(userMessage) {
56170
- log15.debug(`Suggesting tags for: "${userMessage.substring(0, 50)}..."`);
56231
+ log16.debug(`Suggesting tags for: "${userMessage.substring(0, 50)}..."`);
56171
56232
  try {
56172
56233
  const result = await quickQuery({
56173
56234
  prompt: buildTagPrompt(userMessage),
@@ -56175,14 +56236,14 @@ async function suggestSessionTags(userMessage) {
56175
56236
  timeout: SUGGESTION_TIMEOUT2
56176
56237
  });
56177
56238
  if (!result.success || !result.response) {
56178
- log15.debug(`Tag suggestion failed: ${result.error || "no response"}`);
56239
+ log16.debug(`Tag suggestion failed: ${result.error || "no response"}`);
56179
56240
  return [];
56180
56241
  }
56181
56242
  const tags = parseTags(result.response);
56182
- log15.debug(`Got tags: ${tags.join(", ")} (${result.durationMs}ms)`);
56243
+ log16.debug(`Got tags: ${tags.join(", ")} (${result.durationMs}ms)`);
56183
56244
  return tags;
56184
56245
  } catch (err) {
56185
- log15.debug(`Tag suggestion error: ${err}`);
56246
+ log16.debug(`Tag suggestion error: ${err}`);
56186
56247
  return [];
56187
56248
  }
56188
56249
  }
@@ -59702,7 +59763,7 @@ class BugReportExecutor extends BaseExecutor {
59702
59763
  // src/operations/executors/worktree-prompt.ts
59703
59764
  init_emoji();
59704
59765
  init_logger();
59705
- var log16 = createLogger("wt-prompt");
59766
+ var log17 = createLogger("wt-prompt");
59706
59767
  // src/operations/message-manager.ts
59707
59768
  init_logger();
59708
59769
 
@@ -59739,7 +59800,7 @@ var import_yauzl = __toESM(require_yauzl(), 1);
59739
59800
  import { createGunzip } from "zlib";
59740
59801
  import { pipeline } from "stream/promises";
59741
59802
  import { Readable, Writable } from "stream";
59742
- var log17 = createLogger("streaming");
59803
+ var log18 = createLogger("streaming");
59743
59804
  var MAX_PDF_SIZE = 32 * 1024 * 1024;
59744
59805
  var MAX_TEXT_FILE_SIZE = 1 * 1024 * 1024;
59745
59806
  var MAX_DECOMPRESSED_SIZE = 10 * 1024 * 1024;
@@ -59865,7 +59926,7 @@ async function processImageFile(file, platform, debug = false) {
59865
59926
  const buffer = await platform.downloadFile(file.id);
59866
59927
  const base64 = buffer.toString("base64");
59867
59928
  if (debug) {
59868
- 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)`);
59869
59930
  }
59870
59931
  return {
59871
59932
  block: {
@@ -59878,7 +59939,7 @@ async function processImageFile(file, platform, debug = false) {
59878
59939
  }
59879
59940
  };
59880
59941
  } catch (err) {
59881
- log17.error(`Failed to download image ${file.name}: ${err}`);
59942
+ log18.error(`Failed to download image ${file.name}: ${err}`);
59882
59943
  return {
59883
59944
  skipped: {
59884
59945
  name: file.name,
@@ -59909,7 +59970,7 @@ async function processPdfFile(file, platform, debug = false) {
59909
59970
  }
59910
59971
  const base64 = buffer.toString("base64");
59911
59972
  if (debug) {
59912
- 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)`);
59913
59974
  }
59914
59975
  return {
59915
59976
  block: {
@@ -59923,7 +59984,7 @@ async function processPdfFile(file, platform, debug = false) {
59923
59984
  }
59924
59985
  };
59925
59986
  } catch (err) {
59926
- log17.error(`Failed to process PDF ${file.name}: ${err}`);
59987
+ log18.error(`Failed to process PDF ${file.name}: ${err}`);
59927
59988
  return {
59928
59989
  skipped: {
59929
59990
  name: file.name,
@@ -59954,7 +60015,7 @@ async function processTextFile(file, platform, debug = false) {
59954
60015
  }
59955
60016
  const content = buffer.toString("utf-8");
59956
60017
  if (debug) {
59957
- 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)`);
59958
60019
  }
59959
60020
  const wrappedContent = formatTextFileContent(file.name, content);
59960
60021
  return {
@@ -59964,7 +60025,7 @@ async function processTextFile(file, platform, debug = false) {
59964
60025
  }
59965
60026
  };
59966
60027
  } catch (err) {
59967
- log17.error(`Failed to process text file ${file.name}: ${err}`);
60028
+ log18.error(`Failed to process text file ${file.name}: ${err}`);
59968
60029
  return {
59969
60030
  skipped: {
59970
60031
  name: file.name,
@@ -60022,7 +60083,7 @@ async function processGzipFile(file, platform, debug = false) {
60022
60083
  compressedBuffer = await platform.downloadFile(file.id);
60023
60084
  } catch (err) {
60024
60085
  const errorMessage = err instanceof Error ? err.message : String(err);
60025
- log17.error(`Failed to download gzip file ${file.name}: ${errorMessage}`);
60086
+ log18.error(`Failed to download gzip file ${file.name}: ${errorMessage}`);
60026
60087
  return {
60027
60088
  skipped: {
60028
60089
  name: file.name,
@@ -60032,7 +60093,7 @@ async function processGzipFile(file, platform, debug = false) {
60032
60093
  };
60033
60094
  }
60034
60095
  if (file.size && compressedBuffer.length !== file.size) {
60035
- 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}`);
60036
60097
  }
60037
60098
  let decompressedBuffer;
60038
60099
  try {
@@ -60068,7 +60129,7 @@ async function processGzipFile(file, platform, debug = false) {
60068
60129
  const innerFilename = file.name.toLowerCase().endsWith(".gz") ? file.name.slice(0, -3) : file.name;
60069
60130
  const contentType = detectDecompressedContentType(decompressedBuffer, innerFilename);
60070
60131
  if (debug) {
60071
- 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}`);
60072
60133
  }
60073
60134
  if (contentType === "pdf") {
60074
60135
  const base64 = decompressedBuffer.toString("base64");
@@ -60103,7 +60164,7 @@ async function processGzipFile(file, platform, debug = false) {
60103
60164
  }
60104
60165
  } catch (err) {
60105
60166
  const errorMessage = err instanceof Error ? err.message : String(err);
60106
- log17.error(`Failed to process gzip file ${file.name}: ${errorMessage}`);
60167
+ log18.error(`Failed to process gzip file ${file.name}: ${errorMessage}`);
60107
60168
  return {
60108
60169
  skipped: {
60109
60170
  name: file.name,
@@ -60155,7 +60216,7 @@ async function processZipFile(file, platform, debug = false) {
60155
60216
  }
60156
60217
  const zipBuffer = await platform.downloadFile(file.id);
60157
60218
  if (debug) {
60158
- 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`);
60159
60220
  }
60160
60221
  const zipfile = await new Promise((resolve5, reject) => {
60161
60222
  import_yauzl.default.fromBuffer(zipBuffer, { lazyEntries: true }, (err, zf) => {
@@ -60229,7 +60290,7 @@ async function processZipFile(file, platform, debug = false) {
60229
60290
  const buffer = await extractZipEntry(zipfile2, entry);
60230
60291
  const contentType = detectDecompressedContentType(buffer, entry.fileName);
60231
60292
  if (debug) {
60232
- 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}`);
60233
60294
  }
60234
60295
  if (contentType === "pdf") {
60235
60296
  const base64 = buffer.toString("base64");
@@ -60272,11 +60333,11 @@ async function processZipFile(file, platform, debug = false) {
60272
60333
  });
60273
60334
  zipfile2.close();
60274
60335
  if (debug) {
60275
- log17.debug(`Zip ${file.name}: processed ${processedCount} files, skipped ${skipped.length}`);
60336
+ log18.debug(`Zip ${file.name}: processed ${processedCount} files, skipped ${skipped.length}`);
60276
60337
  }
60277
60338
  return { blocks, skipped };
60278
60339
  } catch (err) {
60279
- log17.error(`Failed to process zip file ${file.name}: ${err}`);
60340
+ log18.error(`Failed to process zip file ${file.name}: ${err}`);
60280
60341
  return {
60281
60342
  blocks: [],
60282
60343
  skipped: [{
@@ -60373,7 +60434,7 @@ async function processFiles(platform, files, debug = false) {
60373
60434
  blocks.push(...zipResult.blocks);
60374
60435
  for (const s of zipResult.skipped) {
60375
60436
  skipped.push(s);
60376
- log17.warn(`Skipped file ${s.name}: ${s.reason}`);
60437
+ log18.warn(`Skipped file ${s.name}: ${s.reason}`);
60377
60438
  }
60378
60439
  continue;
60379
60440
  }
@@ -60407,7 +60468,7 @@ async function processFiles(platform, files, debug = false) {
60407
60468
  }
60408
60469
  if (result.skipped) {
60409
60470
  skipped.push(result.skipped);
60410
- log17.warn(`Skipped file ${result.skipped.name}: ${result.skipped.reason}`);
60471
+ log18.warn(`Skipped file ${result.skipped.name}: ${result.skipped.reason}`);
60411
60472
  }
60412
60473
  }
60413
60474
  return { blocks, skipped };
@@ -60440,7 +60501,7 @@ function stopTyping(session) {
60440
60501
  }
60441
60502
 
60442
60503
  // src/operations/message-manager.ts
60443
- var log18 = createLogger("msg-mgr");
60504
+ var log19 = createLogger("msg-mgr");
60444
60505
 
60445
60506
  class MessageManager {
60446
60507
  platform;
@@ -60530,7 +60591,7 @@ class MessageManager {
60530
60591
  });
60531
60592
  }
60532
60593
  async handleEvent(event) {
60533
- const logger = log18.forSession(this.sessionId);
60594
+ const logger = log19.forSession(this.sessionId);
60534
60595
  const transformCtx = {
60535
60596
  sessionId: this.sessionId,
60536
60597
  formatter: this.platform.getFormatter(),
@@ -60580,7 +60641,7 @@ class MessageManager {
60580
60641
  }
60581
60642
  }
60582
60643
  async executeOperation(op) {
60583
- const logger = log18.forSession(this.sessionId);
60644
+ const logger = log19.forSession(this.sessionId);
60584
60645
  const ctx = this.getExecutorContext();
60585
60646
  try {
60586
60647
  if (isContentOp(op)) {
@@ -60648,7 +60709,7 @@ class MessageManager {
60648
60709
  threadId: this.threadId,
60649
60710
  platform: this.platform,
60650
60711
  formatter: this.platform.getFormatter(),
60651
- logger: log18.forSession(this.sessionId),
60712
+ logger: log19.forSession(this.sessionId),
60652
60713
  postTracker: this.postTracker,
60653
60714
  contentBreaker: this.contentBreaker,
60654
60715
  threadLogger: this.session.threadLogger,
@@ -60859,13 +60920,13 @@ class MessageManager {
60859
60920
  return this.systemExecutor.postSuccess(message, this.getExecutorContext());
60860
60921
  }
60861
60922
  async prepareForUserMessage() {
60862
- const logger = log18.forSession(this.sessionId);
60923
+ const logger = log19.forSession(this.sessionId);
60863
60924
  logger.debug("Preparing for new user message");
60864
60925
  await this.closeCurrentPost();
60865
60926
  await this.bumpTaskList();
60866
60927
  }
60867
60928
  async handleUserMessage(message, files, username, displayName) {
60868
- const logger = log18.forSession(this.sessionId);
60929
+ const logger = log19.forSession(this.sessionId);
60869
60930
  if (!this.session.claude.isRunning()) {
60870
60931
  logger.debug("Claude not running, ignoring user message");
60871
60932
  return false;
@@ -60902,7 +60963,7 @@ class MessageManager {
60902
60963
  ];
60903
60964
  }
60904
60965
  async handleReaction(postId, emoji, user, action) {
60905
- const logger = log18.forSession(this.sessionId);
60966
+ const logger = log19.forSession(this.sessionId);
60906
60967
  const ctx = this.getExecutorContext();
60907
60968
  logger.debug(`Routing reaction: postId=${postId}, emoji=${emoji}, user=${user}, action=${action}`);
60908
60969
  for (const { name, executor } of this.reactionDispatchList()) {
@@ -61082,7 +61143,7 @@ function formatPullRequestLink(url, formatter) {
61082
61143
  }
61083
61144
 
61084
61145
  // src/operations/sticky-message/handler.ts
61085
- var log19 = createLogger("sticky");
61146
+ var log20 = createLogger("sticky");
61086
61147
  var botStartedAt = new Date;
61087
61148
  function getPendingPrompts(session) {
61088
61149
  const prompts2 = [];
@@ -61157,21 +61218,21 @@ function initialize(store) {
61157
61218
  stickyPostIds.set(platformId, postId);
61158
61219
  }
61159
61220
  if (persistedIds.size > 0) {
61160
- log19.info(`\uD83D\uDCCC Restored ${persistedIds.size} sticky post ID(s) from persistence`);
61221
+ log20.info(`\uD83D\uDCCC Restored ${persistedIds.size} sticky post ID(s) from persistence`);
61161
61222
  }
61162
61223
  }
61163
61224
  function setPlatformPaused(platformId, paused) {
61164
61225
  if (paused) {
61165
61226
  pausedPlatforms.set(platformId, true);
61166
- log19.debug(`Platform ${platformId} marked as paused`);
61227
+ log20.debug(`Platform ${platformId} marked as paused`);
61167
61228
  } else {
61168
61229
  pausedPlatforms.delete(platformId);
61169
- log19.debug(`Platform ${platformId} marked as active`);
61230
+ log20.debug(`Platform ${platformId} marked as active`);
61170
61231
  }
61171
61232
  }
61172
61233
  function setShuttingDown(shuttingDown) {
61173
61234
  isShuttingDown = shuttingDown;
61174
- log19.debug(`Bot shutdown state: ${shuttingDown}`);
61235
+ log20.debug(`Bot shutdown state: ${shuttingDown}`);
61175
61236
  }
61176
61237
  function getTaskContent(session) {
61177
61238
  const taskState = session.messageManager?.getTaskListState();
@@ -61482,12 +61543,12 @@ async function validateLastMessageIds(platform, sessions) {
61482
61543
  try {
61483
61544
  const post2 = await platform.getPost(lastMessageId);
61484
61545
  if (!post2) {
61485
- log19.debug(`lastMessageId ${lastMessageId.substring(0, 8)} for session ${session.sessionId} was deleted, clearing`);
61546
+ log20.debug(`lastMessageId ${lastMessageId.substring(0, 8)} for session ${session.sessionId} was deleted, clearing`);
61486
61547
  session.lastMessageId = undefined;
61487
61548
  session.lastMessageTs = undefined;
61488
61549
  }
61489
61550
  } catch (err) {
61490
- log19.debug(`Failed to validate lastMessageId for session ${session.sessionId}, clearing: ${err}`);
61551
+ log20.debug(`Failed to validate lastMessageId for session ${session.sessionId}, clearing: ${err}`);
61491
61552
  session.lastMessageId = undefined;
61492
61553
  session.lastMessageTs = undefined;
61493
61554
  }
@@ -61496,63 +61557,63 @@ async function validateLastMessageIds(platform, sessions) {
61496
61557
  }
61497
61558
  async function updateStickyMessageImpl(platform, sessions, config) {
61498
61559
  const platformSessions = [...sessions.values()].filter((s) => s.platformId === platform.platformId);
61499
- log19.debug(`updateStickyMessage for ${platform.platformId}, ${platformSessions.length} sessions`);
61560
+ log20.debug(`updateStickyMessage for ${platform.platformId}, ${platformSessions.length} sessions`);
61500
61561
  for (const s of platformSessions) {
61501
- log19.debug(` - ${s.sessionId}: title="${s.sessionTitle}" firstPrompt="${s.firstPrompt?.substring(0, 30)}..."`);
61562
+ log20.debug(` - ${s.sessionId}: title="${s.sessionTitle}" firstPrompt="${s.firstPrompt?.substring(0, 30)}..."`);
61502
61563
  }
61503
61564
  await validateLastMessageIds(platform, platformSessions);
61504
61565
  const formatter = platform.getFormatter();
61505
61566
  const content = await buildStickyMessage(sessions, platform.platformId, config, formatter, (threadId) => platform.getThreadLink(threadId));
61506
61567
  const existingPostId = stickyPostIds.get(platform.platformId);
61507
61568
  const shouldBump = needsBump.get(platform.platformId) ?? false;
61508
- log19.debug(`existingPostId: ${existingPostId || "(none)"}, needsBump: ${shouldBump}`);
61569
+ log20.debug(`existingPostId: ${existingPostId || "(none)"}, needsBump: ${shouldBump}`);
61509
61570
  try {
61510
61571
  if (existingPostId && !shouldBump) {
61511
- log19.debug(`Updating existing post in place...`);
61572
+ log20.debug(`Updating existing post in place...`);
61512
61573
  try {
61513
61574
  await platform.updatePost(existingPostId, content);
61514
61575
  try {
61515
61576
  await platform.pinPost(existingPostId);
61516
- log19.debug(`Re-pinned post`);
61577
+ log20.debug(`Re-pinned post`);
61517
61578
  } catch (pinErr) {
61518
- log19.debug(`Re-pin failed (might already be pinned): ${pinErr}`);
61579
+ log20.debug(`Re-pin failed (might already be pinned): ${pinErr}`);
61519
61580
  }
61520
- log19.debug(`Updated successfully`);
61581
+ log20.debug(`Updated successfully`);
61521
61582
  return;
61522
61583
  } catch (err) {
61523
- log19.debug(`Update failed, will create new: ${err}`);
61584
+ log20.debug(`Update failed, will create new: ${err}`);
61524
61585
  }
61525
61586
  }
61526
61587
  needsBump.set(platform.platformId, false);
61527
61588
  if (existingPostId) {
61528
- log19.debug(`Unpinning and deleting existing post ${existingPostId.substring(0, 8)}...`);
61589
+ log20.debug(`Unpinning and deleting existing post ${existingPostId.substring(0, 8)}...`);
61529
61590
  try {
61530
61591
  await platform.unpinPost(existingPostId);
61531
- log19.debug(`Unpinned successfully`);
61592
+ log20.debug(`Unpinned successfully`);
61532
61593
  } catch (err) {
61533
- log19.debug(`Unpin failed (probably already unpinned): ${err}`);
61594
+ log20.debug(`Unpin failed (probably already unpinned): ${err}`);
61534
61595
  }
61535
61596
  try {
61536
61597
  await platform.deletePost(existingPostId);
61537
- log19.debug(`Deleted successfully`);
61598
+ log20.debug(`Deleted successfully`);
61538
61599
  } catch (err) {
61539
- log19.debug(`Delete failed (probably already deleted): ${err}`);
61600
+ log20.debug(`Delete failed (probably already deleted): ${err}`);
61540
61601
  }
61541
61602
  stickyPostIds.delete(platform.platformId);
61542
61603
  }
61543
- log19.debug(`Creating new post...`);
61604
+ log20.debug(`Creating new post...`);
61544
61605
  const post2 = await platform.createPost(content);
61545
61606
  stickyPostIds.set(platform.platformId, post2.id);
61546
61607
  try {
61547
61608
  await platform.pinPost(post2.id);
61548
- log19.debug(`Pinned post successfully`);
61609
+ log20.debug(`Pinned post successfully`);
61549
61610
  } catch (err) {
61550
- log19.debug(`Failed to pin post: ${err}`);
61611
+ log20.debug(`Failed to pin post: ${err}`);
61551
61612
  }
61552
61613
  if (sessionStore) {
61553
61614
  sessionStore.saveStickyPostId(platform.platformId, post2.id);
61554
61615
  }
61555
- log19.info(`\uD83D\uDCCC Created sticky message for ${platform.platformId}: ${formatShortId(post2.id)}`);
61616
+ log20.info(`\uD83D\uDCCC Created sticky message for ${platform.platformId}: ${formatShortId(post2.id)}`);
61556
61617
  const excludePostIds = new Set;
61557
61618
  if (sessionStore) {
61558
61619
  for (const session of sessionStore.load().values()) {
@@ -61568,10 +61629,10 @@ async function updateStickyMessageImpl(platform, sessions, config) {
61568
61629
  }
61569
61630
  const botUser = await platform.getBotUser();
61570
61631
  cleanupOldStickyMessages(platform, botUser.id, false, excludePostIds).catch((err) => {
61571
- log19.debug(`Background cleanup failed: ${err}`);
61632
+ log20.debug(`Background cleanup failed: ${err}`);
61572
61633
  });
61573
61634
  } catch (err) {
61574
- log19.error(`Failed to update sticky message for ${platform.platformId}`, err instanceof Error ? err : undefined);
61635
+ log20.error(`Failed to update sticky message for ${platform.platformId}`, err instanceof Error ? err : undefined);
61575
61636
  }
61576
61637
  }
61577
61638
  async function updateAllStickyMessages(platforms, sessions, config) {
@@ -61596,7 +61657,7 @@ async function cleanupOldStickyMessages(platform, botUserId, forceRun = false, e
61596
61657
  if (!forceRun) {
61597
61658
  const lastRun = lastCleanupTime.get(platformId) || 0;
61598
61659
  if (now - lastRun < CLEANUP_THROTTLE_MS) {
61599
- log19.debug(`Cleanup throttled for ${platformId} (last run ${Math.round((now - lastRun) / 1000)}s ago)`);
61660
+ log20.debug(`Cleanup throttled for ${platformId} (last run ${Math.round((now - lastRun) / 1000)}s ago)`);
61600
61661
  return;
61601
61662
  }
61602
61663
  }
@@ -61606,31 +61667,31 @@ async function cleanupOldStickyMessages(platform, botUserId, forceRun = false, e
61606
61667
  const pinnedPostIds = await platform.getPinnedPosts();
61607
61668
  const recentPinnedIds = pinnedPostIds.filter((id) => id !== currentStickyId && !excludePostIds?.has(id) && isRecentPost(id));
61608
61669
  if (recentPinnedIds.length === 0) {
61609
- log19.debug(`No recent pinned posts to check (${pinnedPostIds.length} total, current: ${currentStickyId?.substring(0, 8) || "(none)"})`);
61670
+ log20.debug(`No recent pinned posts to check (${pinnedPostIds.length} total, current: ${currentStickyId?.substring(0, 8) || "(none)"})`);
61610
61671
  return;
61611
61672
  }
61612
- log19.debug(`Checking ${recentPinnedIds.length} recent pinned posts (of ${pinnedPostIds.length} total)`);
61673
+ log20.debug(`Checking ${recentPinnedIds.length} recent pinned posts (of ${pinnedPostIds.length} total)`);
61613
61674
  for (const postId of recentPinnedIds) {
61614
61675
  try {
61615
61676
  const post2 = await platform.getPost(postId);
61616
61677
  if (!post2)
61617
61678
  continue;
61618
61679
  if (post2.userId === botUserId) {
61619
- log19.debug(`Cleaning up old sticky: ${postId.substring(0, 8)}...`);
61680
+ log20.debug(`Cleaning up old sticky: ${postId.substring(0, 8)}...`);
61620
61681
  try {
61621
61682
  await platform.unpinPost(postId);
61622
61683
  await platform.deletePost(postId);
61623
- log19.info(`\uD83E\uDDF9 Cleaned up old sticky message: ${postId.substring(0, 8)}...`);
61684
+ log20.info(`\uD83E\uDDF9 Cleaned up old sticky message: ${postId.substring(0, 8)}...`);
61624
61685
  } catch (err) {
61625
- log19.debug(`Failed to cleanup ${postId}: ${err}`);
61686
+ log20.debug(`Failed to cleanup ${postId}: ${err}`);
61626
61687
  }
61627
61688
  }
61628
61689
  } catch (err) {
61629
- log19.debug(`Could not check post ${postId}: ${err}`);
61690
+ log20.debug(`Could not check post ${postId}: ${err}`);
61630
61691
  }
61631
61692
  }
61632
61693
  } catch (err) {
61633
- log19.error(`Failed to cleanup old sticky messages`, err instanceof Error ? err : undefined);
61694
+ log20.error(`Failed to cleanup old sticky messages`, err instanceof Error ? err : undefined);
61634
61695
  }
61635
61696
  }
61636
61697
  // src/operations/bug-report/handler.ts
@@ -65693,8 +65754,8 @@ function getUpdateInfo() {
65693
65754
  init_emoji();
65694
65755
  init_logger();
65695
65756
  init_worktree();
65696
- var log20 = createLogger("commands");
65697
- var sessionLog2 = createSessionLog(log20);
65757
+ var log21 = createLogger("commands");
65758
+ var sessionLog2 = createSessionLog(log21);
65698
65759
  function sessionAccountOption(session, ctx) {
65699
65760
  if (!session.claudeAccountId)
65700
65761
  return;
@@ -66228,7 +66289,7 @@ init_logger();
66228
66289
  import { exec as exec3 } from "child_process";
66229
66290
  import { promisify as promisify3 } from "util";
66230
66291
  var execAsync2 = promisify3(exec3);
66231
- var log21 = createLogger("branch");
66292
+ var log22 = createLogger("branch");
66232
66293
  var SUGGESTION_TIMEOUT3 = 15000;
66233
66294
  var MAX_SUGGESTIONS = 3;
66234
66295
  async function getCurrentBranch3(workingDir) {
@@ -66277,7 +66338,7 @@ function parseBranchSuggestions(response) {
66277
66338
  return lines.slice(0, MAX_SUGGESTIONS);
66278
66339
  }
66279
66340
  async function suggestBranchNames(workingDir, userMessage) {
66280
- log21.debug(`Suggesting branch names for: "${userMessage.substring(0, 50)}..."`);
66341
+ log22.debug(`Suggesting branch names for: "${userMessage.substring(0, 50)}..."`);
66281
66342
  try {
66282
66343
  const [currentBranch, recentCommits] = await Promise.all([
66283
66344
  getCurrentBranch3(workingDir),
@@ -66291,14 +66352,14 @@ async function suggestBranchNames(workingDir, userMessage) {
66291
66352
  workingDir
66292
66353
  });
66293
66354
  if (!result.success || !result.response) {
66294
- log21.debug(`Branch suggestion failed: ${result.error || "no response"}`);
66355
+ log22.debug(`Branch suggestion failed: ${result.error || "no response"}`);
66295
66356
  return [];
66296
66357
  }
66297
66358
  const suggestions = parseBranchSuggestions(result.response);
66298
- log21.debug(`Got ${suggestions.length} branch suggestions: ${suggestions.join(", ")}`);
66359
+ log22.debug(`Got ${suggestions.length} branch suggestions: ${suggestions.join(", ")}`);
66299
66360
  return suggestions;
66300
66361
  } catch (err) {
66301
- log21.debug(`Branch suggestion error: ${err}`);
66362
+ log22.debug(`Branch suggestion error: ${err}`);
66302
66363
  return [];
66303
66364
  }
66304
66365
  }
@@ -66307,8 +66368,8 @@ async function suggestBranchNames(workingDir, userMessage) {
66307
66368
  init_worktree();
66308
66369
  import { randomUUID as randomUUID3 } from "crypto";
66309
66370
  init_logger();
66310
- var log22 = createLogger("worktree");
66311
- var sessionLog3 = createSessionLog(log22);
66371
+ var log23 = createLogger("worktree");
66372
+ var sessionLog3 = createSessionLog(log23);
66312
66373
  function parseWorktreeError(error) {
66313
66374
  const message = error instanceof Error ? error.message : String(error);
66314
66375
  const lowerMessage = message.toLowerCase();
@@ -66318,6 +66379,15 @@ function parseWorktreeError(error) {
66318
66379
  suggestion: "Try a different branch name, or use `!worktree list` to see existing worktrees"
66319
66380
  };
66320
66381
  }
66382
+ const parentBlocksMatch = message.match(/'refs\/heads\/([^']+)' exists; cannot create '(?:refs\/heads\/)?([^']+)'/i);
66383
+ if (parentBlocksMatch) {
66384
+ const parent = parentBlocksMatch[1];
66385
+ const nested = parentBlocksMatch[2];
66386
+ return {
66387
+ summary: `Branch ${parent} already exists and blocks ${nested}`,
66388
+ suggestion: `Pick a name that does not start with ${parent}/, or delete the existing ${parent} branch first.`
66389
+ };
66390
+ }
66321
66391
  if (lowerMessage.includes("already exists")) {
66322
66392
  return {
66323
66393
  summary: "A worktree or branch with this name already exists",
@@ -66867,8 +66937,8 @@ async function cleanupWorktreeCommand(session, username, hasOtherSessionsUsingWo
66867
66937
  }
66868
66938
  // src/operations/events/handler.ts
66869
66939
  init_logger();
66870
- var log23 = createLogger("events");
66871
- var sessionLog4 = createSessionLog(log23);
66940
+ var log24 = createLogger("events");
66941
+ var sessionLog4 = createSessionLog(log24);
66872
66942
  function detectAndExecuteClaudeCommands(text, session, ctx) {
66873
66943
  const parsed = parseClaudeCommand(text);
66874
66944
  if (parsed && isClaudeAllowedCommand(parsed.command)) {
@@ -67116,8 +67186,8 @@ function createSessionContext(config, state, ops) {
67116
67186
  // src/operations/context-prompt/handler.ts
67117
67187
  init_emoji();
67118
67188
  init_logger();
67119
- var log24 = createLogger("context");
67120
- var sessionLog5 = createSessionLog(log24);
67189
+ var log25 = createLogger("context");
67190
+ var sessionLog5 = createSessionLog(log25);
67121
67191
  var CONTEXT_PROMPT_TIMEOUT_MS = 30000;
67122
67192
  var CONTEXT_OPTIONS = [3, 5, 10];
67123
67193
  var contextPromptTimeouts = new Map;
@@ -67367,8 +67437,8 @@ function formatRelativeTime(date) {
67367
67437
  }
67368
67438
  // src/session/lifecycle.ts
67369
67439
  init_worktree();
67370
- var log25 = createLogger("lifecycle");
67371
- var sessionLog6 = createSessionLog(log25);
67440
+ var log26 = createLogger("lifecycle");
67441
+ var sessionLog6 = createSessionLog(log26);
67372
67442
  function mutableSessions(ctx) {
67373
67443
  return ctx.state.sessions;
67374
67444
  }
@@ -67753,17 +67823,17 @@ async function startSession(options2, username, displayName, replyToPostId, plat
67753
67823
  return;
67754
67824
  }
67755
67825
  workingDir = resolvedDir;
67756
- log25.info(`Starting session in directory: ${workingDir} (from !cd command)`);
67826
+ log26.info(`Starting session in directory: ${workingDir} (from !cd command)`);
67757
67827
  }
67758
67828
  if (initialOptions?.permissionMode) {
67759
67829
  permissionMode = initialOptions.permissionMode;
67760
67830
  forceInteractivePermissions = permissionMode === "default";
67761
67831
  sessionPermissionModeOverride = permissionMode;
67762
- log25.info(`Starting session with permission mode "${permissionMode}" (from !permissions command)`);
67832
+ log26.info(`Starting session with permission mode "${permissionMode}" (from !permissions command)`);
67763
67833
  } else if (initialOptions?.forceInteractivePermissions) {
67764
67834
  forceInteractivePermissions = true;
67765
67835
  permissionMode = "default";
67766
- log25.info(`Starting session with interactive permissions (from !permissions command)`);
67836
+ log26.info(`Starting session with interactive permissions (from !permissions command)`);
67767
67837
  }
67768
67838
  const sessionContext = buildSessionContext(platform, workingDir);
67769
67839
  const systemPrompt = `${sessionContext}
@@ -67772,7 +67842,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67772
67842
  const platformMcpConfig = platform.getMcpConfig();
67773
67843
  const claudeAccount = ctx.ops.acquireClaudeAccount();
67774
67844
  if (claudeAccount) {
67775
- log25.info(`Session ${sessionId.substring(0, 20)} reserved Claude account "${claudeAccount.id}"`);
67845
+ log26.info(`Session ${sessionId.substring(0, 20)} reserved Claude account "${claudeAccount.id}"`);
67776
67846
  }
67777
67847
  const cliOptions = {
67778
67848
  workingDir,
@@ -67877,28 +67947,28 @@ async function resumeSession(state, ctx) {
67877
67947
  !state.claudeSessionId && "claudeSessionId",
67878
67948
  !state.workingDir && "workingDir"
67879
67949
  ].filter(Boolean).join(", ");
67880
- log25.warn(`Skipping session with missing required fields: ${missing}`);
67950
+ log26.warn(`Skipping session with missing required fields: ${missing}`);
67881
67951
  return;
67882
67952
  }
67883
67953
  const shortId = state.threadId.substring(0, 8);
67884
67954
  const platforms = ctx.state.platforms;
67885
67955
  const platform = platforms.get(state.platformId);
67886
67956
  if (!platform) {
67887
- log25.warn(`Platform ${state.platformId} not registered, skipping resume for ${shortId}...`);
67957
+ log26.warn(`Platform ${state.platformId} not registered, skipping resume for ${shortId}...`);
67888
67958
  return;
67889
67959
  }
67890
67960
  const threadPost = await platform.getPost(state.threadId);
67891
67961
  if (!threadPost) {
67892
- log25.warn(`Thread ${shortId}... deleted, skipping resume`);
67962
+ log26.warn(`Thread ${shortId}... deleted, skipping resume`);
67893
67963
  ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
67894
67964
  return;
67895
67965
  }
67896
67966
  if (ctx.state.sessions.size >= ctx.config.maxSessions) {
67897
- log25.warn(`Max sessions reached, skipping resume for ${shortId}...`);
67967
+ log26.warn(`Max sessions reached, skipping resume for ${shortId}...`);
67898
67968
  return;
67899
67969
  }
67900
67970
  if (!existsSync11(state.workingDir)) {
67901
- log25.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
67971
+ log26.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
67902
67972
  ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
67903
67973
  const resumeFormatter = platform.getFormatter();
67904
67974
  const tempSession = {
@@ -67922,7 +67992,7 @@ Please start a new session.`), { action: "Post resume failure notification" });
67922
67992
  ${CHAT_PLATFORM_PROMPT}`;
67923
67993
  const claudeAccount = ctx.ops.acquireClaudeAccount(state.claudeAccountId);
67924
67994
  if (state.claudeAccountId && !claudeAccount) {
67925
- log25.warn(`Persisted session referenced Claude account "${state.claudeAccountId}" ` + `which is no longer configured — resuming under default env`);
67995
+ log26.warn(`Persisted session referenced Claude account "${state.claudeAccountId}" ` + `which is no longer configured — resuming under default env`);
67926
67996
  }
67927
67997
  const cliOptions = {
67928
67998
  workingDir: state.workingDir,
@@ -67987,7 +68057,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67987
68057
  worktreePath: detected.worktreePath,
67988
68058
  branch: detected.branch
67989
68059
  };
67990
- log25.info(`Auto-detected worktree info for resumed session: branch=${detected.branch}`);
68060
+ log26.info(`Auto-detected worktree info for resumed session: branch=${detected.branch}`);
67991
68061
  }
67992
68062
  }
67993
68063
  session.messageManager = createMessageManager(session, ctx);
@@ -68043,7 +68113,7 @@ ${sessionFormatter.formatItalic("Reconnected to Claude session. You can continue
68043
68113
  await ctx.ops.updateStickyMessage();
68044
68114
  ctx.ops.persistSession(session);
68045
68115
  } catch (err) {
68046
- log25.error(`Failed to resume session ${shortId}`, err instanceof Error ? err : undefined);
68116
+ log26.error(`Failed to resume session ${shortId}`, err instanceof Error ? err : undefined);
68047
68117
  ctx.ops.emitSessionRemove(sessionId);
68048
68118
  mutableSessions(ctx).delete(sessionId);
68049
68119
  ctx.state.sessionStore.remove(sessionId);
@@ -68083,18 +68153,18 @@ async function resumePausedSession(threadId, message, files, ctx) {
68083
68153
  const persisted = ctx.state.sessionStore.load();
68084
68154
  const state = findPersistedByThreadId(persisted, threadId);
68085
68155
  if (!state) {
68086
- log25.debug(`No persisted session found for ${threadId.substring(0, 8)}...`);
68156
+ log26.debug(`No persisted session found for ${threadId.substring(0, 8)}...`);
68087
68157
  return;
68088
68158
  }
68089
68159
  const shortId = threadId.substring(0, 8);
68090
- log25.info(`\uD83D\uDD04 Resuming paused session ${shortId}... for new message`);
68160
+ log26.info(`\uD83D\uDD04 Resuming paused session ${shortId}... for new message`);
68091
68161
  await resumeSession(state, ctx);
68092
68162
  const session = ctx.ops.findSessionByThreadId(threadId);
68093
68163
  if (session && session.claude.isRunning() && session.messageManager) {
68094
68164
  session.messageCount++;
68095
68165
  await session.messageManager.handleUserMessage(message, files, state.startedBy);
68096
68166
  } else {
68097
- log25.warn(`Failed to resume session ${shortId}..., could not send message`);
68167
+ log26.warn(`Failed to resume session ${shortId}..., could not send message`);
68098
68168
  }
68099
68169
  }
68100
68170
  async function handleExit(sessionId, code, ctx) {
@@ -68102,7 +68172,7 @@ async function handleExit(sessionId, code, ctx) {
68102
68172
  const shortId = sessionId.substring(0, 8);
68103
68173
  sessionLog6(session).debug(`handleExit called code=${code} isShuttingDown=${ctx.state.isShuttingDown}`);
68104
68174
  if (!session) {
68105
- log25.debug(`Session ${shortId}... not found (already cleaned up)`);
68175
+ log26.debug(`Session ${shortId}... not found (already cleaned up)`);
68106
68176
  return;
68107
68177
  }
68108
68178
  if (isSessionRestarting(session)) {
@@ -68295,7 +68365,7 @@ async function cleanupIdleSessions(timeoutMs, warningMs, ctx) {
68295
68365
  }
68296
68366
 
68297
68367
  // src/operations/monitor/handler.ts
68298
- var log26 = createLogger("monitor");
68368
+ var log27 = createLogger("monitor");
68299
68369
  var DEFAULT_INTERVAL_MS = 60 * 1000;
68300
68370
 
68301
68371
  class SessionMonitor {
@@ -68317,14 +68387,14 @@ class SessionMonitor {
68317
68387
  }
68318
68388
  start() {
68319
68389
  if (this.isRunning) {
68320
- log26.debug("Session monitor already running");
68390
+ log27.debug("Session monitor already running");
68321
68391
  return;
68322
68392
  }
68323
68393
  this.isRunning = true;
68324
- log26.debug(`Session monitor started (interval: ${this.intervalMs / 1000}s)`);
68394
+ log27.debug(`Session monitor started (interval: ${this.intervalMs / 1000}s)`);
68325
68395
  this.timer = setInterval(() => {
68326
68396
  this.runCheck().catch((err) => {
68327
- log26.error(`Error during session monitoring: ${err}`);
68397
+ log27.error(`Error during session monitoring: ${err}`);
68328
68398
  });
68329
68399
  }, this.intervalMs);
68330
68400
  }
@@ -68334,7 +68404,7 @@ class SessionMonitor {
68334
68404
  this.timer = null;
68335
68405
  }
68336
68406
  this.isRunning = false;
68337
- log26.debug("Session monitor stopped");
68407
+ log27.debug("Session monitor stopped");
68338
68408
  }
68339
68409
  async runCheck() {
68340
68410
  await cleanupIdleSessions(this.sessionTimeoutMs, this.sessionWarningMs, this.getContext());
@@ -68346,8 +68416,8 @@ class SessionMonitor {
68346
68416
  // src/operations/plugin/handler.ts
68347
68417
  init_spawn();
68348
68418
  init_logger();
68349
- var log27 = createLogger("plugin");
68350
- var sessionLog7 = createSessionLog(log27);
68419
+ var log28 = createLogger("plugin");
68420
+ var sessionLog7 = createSessionLog(log28);
68351
68421
  async function runPluginCommand(args, cwd, timeout2 = 60000) {
68352
68422
  return new Promise((resolve6) => {
68353
68423
  const claudePath = process.env.CLAUDE_PATH || "claude";
@@ -68368,7 +68438,7 @@ async function runPluginCommand(args, cwd, timeout2 = 60000) {
68368
68438
  });
68369
68439
  proc.on("error", (err) => {
68370
68440
  resolve6({ stdout, stderr, exitCode: 1 });
68371
- log27.error(`Plugin command error: ${err.message}`);
68441
+ log28.error(`Plugin command error: ${err.message}`);
68372
68442
  });
68373
68443
  });
68374
68444
  }
@@ -68567,9 +68637,105 @@ class SessionRegistry {
68567
68637
  }
68568
68638
  }
68569
68639
 
68640
+ // src/session/reaction-router.ts
68641
+ init_emoji();
68642
+ init_logger();
68643
+ var log29 = createLogger("manager");
68644
+ async function handleReaction(deps, platformId, postId, emojiName, username, action) {
68645
+ const normalizedEmoji = normalizeEmojiName(emojiName);
68646
+ if (action === "added" && isResumeEmoji(normalizedEmoji)) {
68647
+ const resumed = await tryResumeFromReaction(deps, platformId, postId, username);
68648
+ if (resumed)
68649
+ return;
68650
+ }
68651
+ const session = deps.registry.findByPost(postId);
68652
+ if (!session)
68653
+ return;
68654
+ if (session.platformId !== platformId)
68655
+ return;
68656
+ if (!session.sessionAllowedUsers.has(username) && !session.platform.isUserAllowed(username)) {
68657
+ log29.info(`\uD83D\uDEAB rejected reaction from unauthorized user`, {
68658
+ event: "reaction.rejected",
68659
+ platformId,
68660
+ sessionId: session.sessionId,
68661
+ postId,
68662
+ emoji: normalizedEmoji,
68663
+ action,
68664
+ user: username
68665
+ });
68666
+ return;
68667
+ }
68668
+ await dispatch(deps, session, postId, normalizedEmoji, username, action);
68669
+ }
68670
+ async function tryResumeFromReaction(deps, platformId, postId, username) {
68671
+ const persistedSession = deps.sessionStore.findByPostId(platformId, postId);
68672
+ if (!persistedSession)
68673
+ return false;
68674
+ const sessionId = `${platformId}:${persistedSession.threadId}`;
68675
+ if (deps.registry.hasById(sessionId))
68676
+ return false;
68677
+ const allowedUsers = new Set(persistedSession.sessionAllowedUsers);
68678
+ const platform = deps.platforms.get(platformId);
68679
+ if (!allowedUsers.has(username) && !platform?.isUserAllowed(username)) {
68680
+ if (platform) {
68681
+ await platform.createPost(`⚠️ @${username} is not authorized to resume this session`, persistedSession.threadId);
68682
+ }
68683
+ return false;
68684
+ }
68685
+ if (deps.registry.size >= deps.limits.maxSessions) {
68686
+ if (platform) {
68687
+ const fmt = platform.getFormatter();
68688
+ await platform.createPost(`⚠️ ${fmt.formatBold("Too busy")} - ${deps.registry.size} sessions active. Please try again later.`, persistedSession.threadId);
68689
+ }
68690
+ return false;
68691
+ }
68692
+ const shortId = persistedSession.threadId.substring(0, 8);
68693
+ log29.info(`\uD83D\uDD04 Resuming session ${shortId}... via emoji reaction by @${username}`);
68694
+ await resumeSession(persistedSession, deps.getContext());
68695
+ return true;
68696
+ }
68697
+ async function dispatch(deps, session, postId, emojiName, username, action) {
68698
+ if (action === "added") {
68699
+ if (session.sessionStartPostId === postId) {
68700
+ if (isCancelEmoji(emojiName)) {
68701
+ await cancelSession(session, username, deps.getContext());
68702
+ return;
68703
+ }
68704
+ if (isEscapeEmoji(emojiName)) {
68705
+ await interruptSession(session, username);
68706
+ return;
68707
+ }
68708
+ }
68709
+ if (session.worktreePromptPostId === postId && emojiName === "x") {
68710
+ await handleWorktreeSkip(session, username, (s) => deps.persistSession(s), (s, q) => offerContextPrompt(s, q, undefined, deps.getContextPromptHandler()));
68711
+ return;
68712
+ }
68713
+ if (session.pendingWorktreeSuggestions?.postId === postId) {
68714
+ const emojiIndex = getNumberEmojiIndex(emojiName);
68715
+ if (emojiIndex >= 0) {
68716
+ const handled = await handleBranchSuggestionReaction(session, postId, emojiIndex, username, (tid, branch, user) => deps.createAndSwitchToWorktree(tid, branch, user));
68717
+ if (handled)
68718
+ return;
68719
+ }
68720
+ }
68721
+ if (session.lastError?.postId === postId && isBugReportEmoji(emojiName)) {
68722
+ if (session.startedBy === username || session.platform.isUserAllowed(username) || session.sessionAllowedUsers.has(username)) {
68723
+ log29.info(`\uD83D\uDC1B @${username} triggered bug report from error reaction`);
68724
+ await reportBug(session, undefined, username, deps.getContext(), session.lastError);
68725
+ return;
68726
+ }
68727
+ }
68728
+ }
68729
+ if (session.messageManager) {
68730
+ const handled = await session.messageManager.handleReaction(postId, emojiName, username, action);
68731
+ if (handled)
68732
+ return;
68733
+ }
68734
+ }
68735
+
68570
68736
  // src/session/manager.ts
68571
68737
  init_logger();
68572
- var log28 = createLogger("manager");
68738
+ var log30 = createLogger("manager");
68573
68739
 
68574
68740
  class SessionManager extends EventEmitter4 {
68575
68741
  platforms = new Map;
@@ -68638,7 +68804,7 @@ class SessionManager extends EventEmitter4 {
68638
68804
  markNeedsBump(platformId);
68639
68805
  this.updateStickyMessage();
68640
68806
  });
68641
- log28.info(`\uD83D\uDCE1 Platform "${platformId}" registered`);
68807
+ log30.info(`\uD83D\uDCE1 Platform "${platformId}" registered`);
68642
68808
  }
68643
68809
  removePlatform(platformId) {
68644
68810
  this.platforms.delete(platformId);
@@ -68654,7 +68820,7 @@ class SessionManager extends EventEmitter4 {
68654
68820
  if (users) {
68655
68821
  users.add(sessionId);
68656
68822
  }
68657
- log28.debug(`Registered session ${sessionId.substring(0, 20)} as worktree user for ${worktreePath}`);
68823
+ log30.debug(`Registered session ${sessionId.substring(0, 20)} as worktree user for ${worktreePath}`);
68658
68824
  }
68659
68825
  unregisterWorktreeUser(worktreePath, sessionId) {
68660
68826
  const users = this.worktreeUsers.get(worktreePath);
@@ -68768,95 +68934,19 @@ class SessionManager extends EventEmitter4 {
68768
68934
  }
68769
68935
  async handleMessage(_platformId, _post, _user) {}
68770
68936
  async handleReaction(platformId, postId, emojiName, username, action) {
68771
- const normalizedEmoji = normalizeEmojiName(emojiName);
68772
- if (action === "added" && isResumeEmoji(normalizedEmoji)) {
68773
- const resumed = await this.tryResumeFromReaction(platformId, postId, username);
68774
- if (resumed)
68775
- return;
68776
- }
68777
- const session = this.getSessionByPost(postId);
68778
- if (!session)
68779
- return;
68780
- if (session.platformId !== platformId)
68781
- return;
68782
- if (!session.sessionAllowedUsers.has(username) && !session.platform.isUserAllowed(username)) {
68783
- log28.info(`\uD83D\uDEAB rejected reaction from unauthorized user`, {
68784
- event: "reaction.rejected",
68785
- platformId,
68786
- sessionId: session.sessionId,
68787
- postId,
68788
- emoji: normalizedEmoji,
68789
- action,
68790
- user: username
68791
- });
68792
- return;
68793
- }
68794
- await this.handleSessionReaction(session, postId, normalizedEmoji, username, action);
68937
+ await handleReaction(this.getReactionRouterDeps(), platformId, postId, emojiName, username, action);
68795
68938
  }
68796
- async tryResumeFromReaction(platformId, postId, username) {
68797
- const persistedSession = this.sessionStore.findByPostId(platformId, postId);
68798
- if (!persistedSession)
68799
- return false;
68800
- const sessionId = `${platformId}:${persistedSession.threadId}`;
68801
- if (this.registry.hasById(sessionId))
68802
- return false;
68803
- const allowedUsers = new Set(persistedSession.sessionAllowedUsers);
68804
- const platform = this.platforms.get(platformId);
68805
- if (!allowedUsers.has(username) && !platform?.isUserAllowed(username)) {
68806
- if (platform) {
68807
- await platform.createPost(`⚠️ @${username} is not authorized to resume this session`, persistedSession.threadId);
68808
- }
68809
- return false;
68810
- }
68811
- if (this.registry.size >= this.limits.maxSessions) {
68812
- if (platform) {
68813
- const fmt = platform.getFormatter();
68814
- await platform.createPost(`⚠️ ${fmt.formatBold("Too busy")} - ${this.registry.size} sessions active. Please try again later.`, persistedSession.threadId);
68815
- }
68816
- return false;
68817
- }
68818
- const shortId = persistedSession.threadId.substring(0, 8);
68819
- log28.info(`\uD83D\uDD04 Resuming session ${shortId}... via emoji reaction by @${username}`);
68820
- await resumeSession(persistedSession, this.getContext());
68821
- return true;
68822
- }
68823
- async handleSessionReaction(session, postId, emojiName, username, action) {
68824
- if (action === "added") {
68825
- if (session.sessionStartPostId === postId) {
68826
- if (isCancelEmoji(emojiName)) {
68827
- await cancelSession(session, username, this.getContext());
68828
- return;
68829
- }
68830
- if (isEscapeEmoji(emojiName)) {
68831
- await interruptSession(session, username);
68832
- return;
68833
- }
68834
- }
68835
- if (session.worktreePromptPostId === postId && emojiName === "x") {
68836
- await handleWorktreeSkip(session, username, (s) => this.persistSession(s), (s, q) => offerContextPrompt(s, q, undefined, this.getContextPromptHandler()));
68837
- return;
68838
- }
68839
- if (session.pendingWorktreeSuggestions?.postId === postId) {
68840
- const emojiIndex = getNumberEmojiIndex(emojiName);
68841
- if (emojiIndex >= 0) {
68842
- const handled = await handleBranchSuggestionReaction(session, postId, emojiIndex, username, (tid, branch, user) => this.createAndSwitchToWorktree(tid, branch, user));
68843
- if (handled)
68844
- return;
68845
- }
68846
- }
68847
- if (session.lastError?.postId === postId && isBugReportEmoji(emojiName)) {
68848
- if (session.startedBy === username || session.platform.isUserAllowed(username) || session.sessionAllowedUsers.has(username)) {
68849
- log28.info(`\uD83D\uDC1B @${username} triggered bug report from error reaction`);
68850
- await reportBug(session, undefined, username, this.getContext(), session.lastError);
68851
- return;
68852
- }
68853
- }
68854
- }
68855
- if (session.messageManager) {
68856
- const handled = await session.messageManager.handleReaction(postId, emojiName, username, action);
68857
- if (handled)
68858
- return;
68859
- }
68939
+ getReactionRouterDeps() {
68940
+ return {
68941
+ registry: this.registry,
68942
+ sessionStore: this.sessionStore,
68943
+ platforms: this.platforms,
68944
+ limits: this.limits,
68945
+ getContext: () => this.getContext(),
68946
+ getContextPromptHandler: () => this.getContextPromptHandler(),
68947
+ persistSession: (s) => this.persistSession(s),
68948
+ createAndSwitchToWorktree: (tid, branch, user) => this.createAndSwitchToWorktree(tid, branch, user)
68949
+ };
68860
68950
  }
68861
68951
  getContextPromptHandler() {
68862
68952
  return {
@@ -68915,28 +69005,14 @@ class SessionManager extends EventEmitter4 {
68915
69005
  this.stopTyping(session);
68916
69006
  }
68917
69007
  persistSession(session) {
68918
- const useSerializeV2 = process.env.CLAUDE_THREADS_SERIALIZE_V2 !== "0";
68919
69008
  let taskListSnapshot;
68920
69009
  let contextPromptSnapshot;
68921
- if (useSerializeV2 && session.messageManager) {
69010
+ if (session.messageManager) {
68922
69011
  const serialized = session.messageManager.serialize();
68923
69012
  taskListSnapshot = serialized.taskList;
68924
69013
  if (serialized.contextPrompt) {
68925
69014
  contextPromptSnapshot = serialized.contextPrompt;
68926
69015
  }
68927
- } else {
68928
- const legacyPrompt = session.messageManager?.getPendingContextPrompt();
68929
- if (legacyPrompt) {
68930
- contextPromptSnapshot = {
68931
- postId: legacyPrompt.postId,
68932
- queuedPrompt: legacyPrompt.queuedPrompt,
68933
- queuedFiles: legacyPrompt.queuedFiles,
68934
- threadMessageCount: legacyPrompt.threadMessageCount,
68935
- createdAt: legacyPrompt.createdAt,
68936
- availableOptions: legacyPrompt.availableOptions
68937
- };
68938
- }
68939
- taskListSnapshot = session.messageManager?.getTaskListState();
68940
69016
  }
68941
69017
  const state = {
68942
69018
  platformId: session.platformId,
@@ -69030,11 +69106,11 @@ class SessionManager extends EventEmitter4 {
69030
69106
  }
69031
69107
  }
69032
69108
  if (sessionsToKill.length === 0) {
69033
- log28.info(`No active sessions to pause for platform ${platformId}`);
69109
+ log30.info(`No active sessions to pause for platform ${platformId}`);
69034
69110
  await this.updateStickyMessage();
69035
69111
  return;
69036
69112
  }
69037
- log28.info(`⏸️ Pausing ${sessionsToKill.length} session(s) for platform ${platformId}`);
69113
+ log30.info(`⏸️ Pausing ${sessionsToKill.length} session(s) for platform ${platformId}`);
69038
69114
  for (const session of sessionsToKill) {
69039
69115
  try {
69040
69116
  const fmt = session.platform.getFormatter();
@@ -69050,9 +69126,9 @@ class SessionManager extends EventEmitter4 {
69050
69126
  session.claude.kill();
69051
69127
  this.registry.unregister(session.sessionId);
69052
69128
  this.emitSessionRemove(session.sessionId);
69053
- log28.info(`⏸️ Paused session ${session.threadId.substring(0, 8)}`);
69129
+ log30.info(`⏸️ Paused session ${session.threadId.substring(0, 8)}`);
69054
69130
  } catch (err) {
69055
- log28.warn(`Failed to pause session ${session.threadId}: ${err}`);
69131
+ log30.warn(`Failed to pause session ${session.threadId}: ${err}`);
69056
69132
  }
69057
69133
  }
69058
69134
  for (const session of sessionsToKill) {
@@ -69073,17 +69149,17 @@ class SessionManager extends EventEmitter4 {
69073
69149
  sessionsToResume.push(state);
69074
69150
  }
69075
69151
  if (sessionsToResume.length === 0) {
69076
- log28.info(`No paused sessions to resume for platform ${platformId}`);
69152
+ log30.info(`No paused sessions to resume for platform ${platformId}`);
69077
69153
  await this.updateStickyMessage();
69078
69154
  return;
69079
69155
  }
69080
- log28.info(`▶️ Resuming ${sessionsToResume.length} paused session(s) for platform ${platformId}`);
69156
+ log30.info(`▶️ Resuming ${sessionsToResume.length} paused session(s) for platform ${platformId}`);
69081
69157
  for (const state of sessionsToResume) {
69082
69158
  try {
69083
69159
  await resumeSession(state, this.getContext());
69084
- log28.info(`▶️ Resumed session ${state.threadId.substring(0, 8)}`);
69160
+ log30.info(`▶️ Resumed session ${state.threadId.substring(0, 8)}`);
69085
69161
  } catch (err) {
69086
- log28.warn(`Failed to resume session ${state.threadId}: ${err}`);
69162
+ log30.warn(`Failed to resume session ${state.threadId}: ${err}`);
69087
69163
  }
69088
69164
  }
69089
69165
  await this.updateStickyMessage();
@@ -69095,14 +69171,14 @@ class SessionManager extends EventEmitter4 {
69095
69171
  const sessionTimeoutMs = this.limits.sessionTimeoutMinutes * 60 * 1000;
69096
69172
  const staleIds = this.sessionStore.cleanStale(sessionTimeoutMs * 2);
69097
69173
  if (staleIds.length > 0) {
69098
- log28.info(`\uD83E\uDDF9 Soft-deleted ${staleIds.length} stale session(s) (kept for history)`);
69174
+ log30.info(`\uD83E\uDDF9 Soft-deleted ${staleIds.length} stale session(s) (kept for history)`);
69099
69175
  }
69100
69176
  const removedCount = this.sessionStore.cleanHistory();
69101
69177
  if (removedCount > 0) {
69102
- log28.info(`\uD83D\uDDD1️ Permanently removed ${removedCount} old session(s) from history`);
69178
+ log30.info(`\uD83D\uDDD1️ Permanently removed ${removedCount} old session(s) from history`);
69103
69179
  }
69104
69180
  const persisted = this.sessionStore.load();
69105
- log28.info(`\uD83D\uDCC2 Loaded ${persisted.size} session(s) from persistence`);
69181
+ log30.info(`\uD83D\uDCC2 Loaded ${persisted.size} session(s) from persistence`);
69106
69182
  const excludePostIdsByPlatform = new Map;
69107
69183
  for (const session of persisted.values()) {
69108
69184
  const platformId = session.platformId;
@@ -69122,10 +69198,10 @@ class SessionManager extends EventEmitter4 {
69122
69198
  const excludePostIds = excludePostIdsByPlatform.get(platform.platformId);
69123
69199
  platform.getBotUser().then((botUser) => {
69124
69200
  cleanupOldStickyMessages(platform, botUser.id, true, excludePostIds).catch((err) => {
69125
- log28.warn(`Failed to cleanup old sticky messages for ${platform.platformId}: ${err}`);
69201
+ log30.warn(`Failed to cleanup old sticky messages for ${platform.platformId}: ${err}`);
69126
69202
  });
69127
69203
  }).catch((err) => {
69128
- log28.warn(`Failed to get bot user for cleanup on ${platform.platformId}: ${err}`);
69204
+ log30.warn(`Failed to get bot user for cleanup on ${platform.platformId}: ${err}`);
69129
69205
  });
69130
69206
  }
69131
69207
  if (persisted.size > 0) {
@@ -69139,10 +69215,10 @@ class SessionManager extends EventEmitter4 {
69139
69215
  }
69140
69216
  }
69141
69217
  if (pausedToSkip.length > 0) {
69142
- log28.info(`⏸️ ${pausedToSkip.length} session(s) remain paused (waiting for user message)`);
69218
+ log30.info(`⏸️ ${pausedToSkip.length} session(s) remain paused (waiting for user message)`);
69143
69219
  }
69144
69220
  if (activeToResume.length > 0) {
69145
- log28.info(`\uD83D\uDD04 Attempting to resume ${activeToResume.length} active session(s)...`);
69221
+ log30.info(`\uD83D\uDD04 Attempting to resume ${activeToResume.length} active session(s)...`);
69146
69222
  for (const state of activeToResume) {
69147
69223
  await resumeSession(state, this.getContext());
69148
69224
  }
@@ -69567,7 +69643,7 @@ Mention me to start a session in this worktree.`, threadId);
69567
69643
  const message = messageBuilder(formatter);
69568
69644
  await post(session, "info", message);
69569
69645
  } catch (err) {
69570
- log28.warn(`Failed to broadcast to session ${session.threadId}: ${err}`);
69646
+ log30.warn(`Failed to broadcast to session ${session.threadId}: ${err}`);
69571
69647
  }
69572
69648
  }
69573
69649
  }
@@ -69586,7 +69662,7 @@ Mention me to start a session in this worktree.`, threadId);
69586
69662
  session.messageManager?.setPendingUpdatePrompt({ postId: post2.id });
69587
69663
  this.registerPost(post2.id, session.threadId);
69588
69664
  } catch (err) {
69589
- log28.warn(`Failed to post ask message to ${threadId}: ${err}`);
69665
+ log30.warn(`Failed to post ask message to ${threadId}: ${err}`);
69590
69666
  }
69591
69667
  }
69592
69668
  }
@@ -77182,29 +77258,29 @@ function SessionLog({ logs, maxLines = 20 }) {
77182
77258
  return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
77183
77259
  flexDirection: "column",
77184
77260
  flexShrink: 0,
77185
- children: displayLogs.map((log29) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
77261
+ children: displayLogs.map((log31) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
77186
77262
  flexShrink: 0,
77187
77263
  children: [
77188
77264
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
77189
- color: getColorForLevel(log29.level),
77265
+ color: getColorForLevel(log31.level),
77190
77266
  dimColor: true,
77191
77267
  wrap: "truncate",
77192
77268
  children: [
77193
77269
  "[",
77194
- padComponent(log29.component),
77270
+ padComponent(log31.component),
77195
77271
  "]"
77196
77272
  ]
77197
77273
  }, undefined, true, undefined, this),
77198
77274
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
77199
- color: getColorForLevel(log29.level),
77275
+ color: getColorForLevel(log31.level),
77200
77276
  wrap: "truncate",
77201
77277
  children: [
77202
77278
  " ",
77203
- log29.message
77279
+ log31.message
77204
77280
  ]
77205
77281
  }, undefined, true, undefined, this)
77206
77282
  ]
77207
- }, log29.id, true, undefined, this))
77283
+ }, log31.id, true, undefined, this))
77208
77284
  }, undefined, false, undefined, this);
77209
77285
  }
77210
77286
  // src/ui/components/Footer.tsx
@@ -77728,7 +77804,7 @@ function LogPanel({ logs, maxLines = 10, focused = false }) {
77728
77804
  const scrollRef = import_react59.default.useRef(null);
77729
77805
  const { stdout } = use_stdout_default();
77730
77806
  const isDebug = process.env.DEBUG === "1";
77731
- const displayLogs = logs.filter((log29) => isDebug || log29.level !== "debug");
77807
+ const displayLogs = logs.filter((log31) => isDebug || log31.level !== "debug");
77732
77808
  const visibleLogs = displayLogs.slice(-Math.max(maxLines * 3, 100));
77733
77809
  import_react59.default.useEffect(() => {
77734
77810
  const handleResize = () => scrollRef.current?.remeasure();
@@ -77768,25 +77844,25 @@ function LogPanel({ logs, maxLines = 10, focused = false }) {
77768
77844
  overflow: "hidden",
77769
77845
  children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(ScrollView, {
77770
77846
  ref: scrollRef,
77771
- children: visibleLogs.map((log29) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
77847
+ children: visibleLogs.map((log31) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
77772
77848
  children: [
77773
77849
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
77774
77850
  dimColor: true,
77775
77851
  children: [
77776
77852
  "[",
77777
- padComponent2(log29.component),
77853
+ padComponent2(log31.component),
77778
77854
  "]"
77779
77855
  ]
77780
77856
  }, undefined, true, undefined, this),
77781
77857
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
77782
- color: getLevelColor(log29.level),
77858
+ color: getLevelColor(log31.level),
77783
77859
  children: [
77784
77860
  " ",
77785
- log29.message
77861
+ log31.message
77786
77862
  ]
77787
77863
  }, undefined, true, undefined, this)
77788
77864
  ]
77789
- }, log29.id, true, undefined, this))
77865
+ }, log31.id, true, undefined, this))
77790
77866
  }, undefined, false, undefined, this)
77791
77867
  }, undefined, false, undefined, this);
77792
77868
  }
@@ -78303,10 +78379,10 @@ function useAppState(initialConfig) {
78303
78379
  });
78304
78380
  }, []);
78305
78381
  const getLogsForSession = import_react60.useCallback((sessionId) => {
78306
- return state.logs.filter((log29) => log29.sessionId === sessionId);
78382
+ return state.logs.filter((log31) => log31.sessionId === sessionId);
78307
78383
  }, [state.logs]);
78308
78384
  const getGlobalLogs = import_react60.useCallback(() => {
78309
- return state.logs.filter((log29) => !log29.sessionId);
78385
+ return state.logs.filter((log31) => !log31.sessionId);
78310
78386
  }, [state.logs]);
78311
78387
  const togglePlatformEnabled = import_react60.useCallback((platformId) => {
78312
78388
  let newEnabled = false;
@@ -79313,7 +79389,7 @@ import { EventEmitter as EventEmitter9 } from "events";
79313
79389
  // src/auto-update/checker.ts
79314
79390
  init_logger();
79315
79391
  import { EventEmitter as EventEmitter7 } from "events";
79316
- var log29 = createLogger("checker");
79392
+ var log31 = createLogger("checker");
79317
79393
  var PACKAGE_NAME = "claude-threads";
79318
79394
  function compareVersions(a, b) {
79319
79395
  const partsA = a.replace(/^v/, "").split(".").map(Number);
@@ -79336,13 +79412,13 @@ async function fetchLatestVersion() {
79336
79412
  }
79337
79413
  });
79338
79414
  if (!response.ok) {
79339
- log29.warn(`Failed to fetch latest version: HTTP ${response.status}`);
79415
+ log31.warn(`Failed to fetch latest version: HTTP ${response.status}`);
79340
79416
  return null;
79341
79417
  }
79342
79418
  const data = await response.json();
79343
79419
  return data.version ?? null;
79344
79420
  } catch (err) {
79345
- log29.warn(`Failed to fetch latest version: ${err}`);
79421
+ log31.warn(`Failed to fetch latest version: ${err}`);
79346
79422
  return null;
79347
79423
  }
79348
79424
  }
@@ -79359,38 +79435,38 @@ class UpdateChecker extends EventEmitter7 {
79359
79435
  }
79360
79436
  start() {
79361
79437
  if (!this.config.enabled) {
79362
- log29.debug("Auto-update disabled, not starting checker");
79438
+ log31.debug("Auto-update disabled, not starting checker");
79363
79439
  return;
79364
79440
  }
79365
79441
  setTimeout(() => {
79366
79442
  this.check().catch((err) => {
79367
- log29.warn(`Initial update check failed: ${err}`);
79443
+ log31.warn(`Initial update check failed: ${err}`);
79368
79444
  });
79369
79445
  }, 5000);
79370
79446
  const intervalMs = this.config.checkIntervalMinutes * 60 * 1000;
79371
79447
  this.checkInterval = setInterval(() => {
79372
79448
  this.check().catch((err) => {
79373
- log29.warn(`Periodic update check failed: ${err}`);
79449
+ log31.warn(`Periodic update check failed: ${err}`);
79374
79450
  });
79375
79451
  }, intervalMs);
79376
- log29.info(`\uD83D\uDD04 Update checker started (every ${this.config.checkIntervalMinutes} minutes)`);
79452
+ log31.info(`\uD83D\uDD04 Update checker started (every ${this.config.checkIntervalMinutes} minutes)`);
79377
79453
  }
79378
79454
  stop() {
79379
79455
  if (this.checkInterval) {
79380
79456
  clearInterval(this.checkInterval);
79381
79457
  this.checkInterval = null;
79382
79458
  }
79383
- log29.debug("Update checker stopped");
79459
+ log31.debug("Update checker stopped");
79384
79460
  }
79385
79461
  async check() {
79386
79462
  if (this.isChecking) {
79387
- log29.debug("Check already in progress, skipping");
79463
+ log31.debug("Check already in progress, skipping");
79388
79464
  return this.lastUpdateInfo;
79389
79465
  }
79390
79466
  this.isChecking = true;
79391
79467
  this.emit("check:start");
79392
79468
  try {
79393
- log29.debug("Checking for updates...");
79469
+ log31.debug("Checking for updates...");
79394
79470
  const latestVersion2 = await fetchLatestVersion();
79395
79471
  if (!latestVersion2) {
79396
79472
  this.emit("check:complete", false);
@@ -79407,18 +79483,18 @@ class UpdateChecker extends EventEmitter7 {
79407
79483
  detectedAt: new Date
79408
79484
  };
79409
79485
  if (!this.lastUpdateInfo || this.lastUpdateInfo.latestVersion !== latestVersion2) {
79410
- log29.info(`\uD83C\uDD95 Update available: v${currentVersion} → v${latestVersion2}`);
79486
+ log31.info(`\uD83C\uDD95 Update available: v${currentVersion} → v${latestVersion2}`);
79411
79487
  this.lastUpdateInfo = updateInfo;
79412
79488
  this.emit("update", updateInfo);
79413
79489
  }
79414
79490
  this.emit("check:complete", true);
79415
79491
  return updateInfo;
79416
79492
  }
79417
- log29.debug(`Up to date (v${currentVersion})`);
79493
+ log31.debug(`Up to date (v${currentVersion})`);
79418
79494
  this.emit("check:complete", false);
79419
79495
  return null;
79420
79496
  } catch (err) {
79421
- log29.warn(`Update check failed: ${err}`);
79497
+ log31.warn(`Update check failed: ${err}`);
79422
79498
  this.emit("check:error", err);
79423
79499
  return null;
79424
79500
  } finally {
@@ -79489,7 +79565,7 @@ function isInScheduledWindow(window2) {
79489
79565
  }
79490
79566
 
79491
79567
  // src/auto-update/scheduler.ts
79492
- var log30 = createLogger("scheduler");
79568
+ var log32 = createLogger("scheduler");
79493
79569
 
79494
79570
  class UpdateScheduler extends EventEmitter8 {
79495
79571
  config;
@@ -79513,7 +79589,7 @@ class UpdateScheduler extends EventEmitter8 {
79513
79589
  scheduleUpdate(updateInfo) {
79514
79590
  this.pendingUpdate = updateInfo;
79515
79591
  if (this.config.autoRestartMode === "immediate") {
79516
- log30.info("Immediate mode: triggering update now");
79592
+ log32.info("Immediate mode: triggering update now");
79517
79593
  this.emit("ready", updateInfo);
79518
79594
  return;
79519
79595
  }
@@ -79526,19 +79602,19 @@ class UpdateScheduler extends EventEmitter8 {
79526
79602
  this.scheduledRestartAt = null;
79527
79603
  this.askApprovals.clear();
79528
79604
  this.askStartTime = null;
79529
- log30.debug("Update schedule cancelled");
79605
+ log32.debug("Update schedule cancelled");
79530
79606
  }
79531
79607
  deferUpdate(minutes) {
79532
79608
  const deferUntil = new Date(Date.now() + minutes * 60 * 1000);
79533
79609
  this.scheduledRestartAt = null;
79534
79610
  this.idleStartTime = null;
79535
79611
  this.emit("deferred", deferUntil);
79536
- log30.info(`Update deferred until ${deferUntil.toLocaleTimeString()}`);
79612
+ log32.info(`Update deferred until ${deferUntil.toLocaleTimeString()}`);
79537
79613
  return deferUntil;
79538
79614
  }
79539
79615
  recordAskResponse(threadId, approved) {
79540
79616
  this.askApprovals.set(threadId, approved);
79541
- log30.debug(`Thread ${threadId.substring(0, 8)} ${approved ? "approved" : "denied"} update`);
79617
+ log32.debug(`Thread ${threadId.substring(0, 8)} ${approved ? "approved" : "denied"} update`);
79542
79618
  this.checkAskCondition();
79543
79619
  }
79544
79620
  getScheduledRestartAt() {
@@ -79559,7 +79635,7 @@ class UpdateScheduler extends EventEmitter8 {
79559
79635
  return;
79560
79636
  this.checkCondition();
79561
79637
  this.checkTimer = setInterval(() => this.checkCondition(), 1e4);
79562
- log30.debug(`Started checking for ${this.config.autoRestartMode} condition`);
79638
+ log32.debug(`Started checking for ${this.config.autoRestartMode} condition`);
79563
79639
  }
79564
79640
  stopChecking() {
79565
79641
  if (this.checkTimer) {
@@ -79590,17 +79666,17 @@ class UpdateScheduler extends EventEmitter8 {
79590
79666
  if (activity.activeSessionCount === 0) {
79591
79667
  if (!this.idleStartTime) {
79592
79668
  this.idleStartTime = new Date;
79593
- log30.debug("No active sessions, starting idle timer");
79669
+ log32.debug("No active sessions, starting idle timer");
79594
79670
  }
79595
79671
  const idleMs = Date.now() - this.idleStartTime.getTime();
79596
79672
  const requiredMs = this.config.idleTimeoutMinutes * 60 * 1000;
79597
79673
  if (idleMs >= requiredMs) {
79598
- log30.info(`Idle for ${this.config.idleTimeoutMinutes} minutes, triggering update`);
79674
+ log32.info(`Idle for ${this.config.idleTimeoutMinutes} minutes, triggering update`);
79599
79675
  this.triggerCountdown();
79600
79676
  }
79601
79677
  } else {
79602
79678
  if (this.idleStartTime) {
79603
- log30.debug("Sessions became active, resetting idle timer");
79679
+ log32.debug("Sessions became active, resetting idle timer");
79604
79680
  this.idleStartTime = null;
79605
79681
  }
79606
79682
  }
@@ -79611,7 +79687,7 @@ class UpdateScheduler extends EventEmitter8 {
79611
79687
  const quietMs = Date.now() - activity.lastActivityAt.getTime();
79612
79688
  const requiredMs = this.config.quietTimeoutMinutes * 60 * 1000;
79613
79689
  if (quietMs >= requiredMs && !activity.anySessionBusy) {
79614
- log30.info(`Sessions quiet for ${this.config.quietTimeoutMinutes} minutes, triggering update`);
79690
+ log32.info(`Sessions quiet for ${this.config.quietTimeoutMinutes} minutes, triggering update`);
79615
79691
  this.triggerCountdown();
79616
79692
  }
79617
79693
  } else if (activity.activeSessionCount === 0) {
@@ -79621,7 +79697,7 @@ class UpdateScheduler extends EventEmitter8 {
79621
79697
  const idleMs = Date.now() - this.idleStartTime.getTime();
79622
79698
  const requiredMs = this.config.quietTimeoutMinutes * 60 * 1000;
79623
79699
  if (idleMs >= requiredMs) {
79624
- log30.info("No sessions and quiet timeout reached, triggering update");
79700
+ log32.info("No sessions and quiet timeout reached, triggering update");
79625
79701
  this.triggerCountdown();
79626
79702
  }
79627
79703
  }
@@ -79632,13 +79708,13 @@ class UpdateScheduler extends EventEmitter8 {
79632
79708
  }
79633
79709
  const activity = this.getSessionActivity();
79634
79710
  if (activity.activeSessionCount === 0) {
79635
- log30.info("Within scheduled window and no active sessions, triggering update");
79711
+ log32.info("Within scheduled window and no active sessions, triggering update");
79636
79712
  this.triggerCountdown();
79637
79713
  } else if (activity.lastActivityAt) {
79638
79714
  const quietMs = Date.now() - activity.lastActivityAt.getTime();
79639
79715
  const requiredMs = this.config.idleTimeoutMinutes * 60 * 1000;
79640
79716
  if (quietMs >= requiredMs && !activity.anySessionBusy) {
79641
- log30.info("Within scheduled window and sessions quiet, triggering update");
79717
+ log32.info("Within scheduled window and sessions quiet, triggering update");
79642
79718
  this.triggerCountdown();
79643
79719
  }
79644
79720
  }
@@ -79646,14 +79722,14 @@ class UpdateScheduler extends EventEmitter8 {
79646
79722
  checkAskCondition() {
79647
79723
  const threadIds = this.getActiveThreadIds();
79648
79724
  if (threadIds.length === 0) {
79649
- log30.info("No active threads, proceeding with update");
79725
+ log32.info("No active threads, proceeding with update");
79650
79726
  this.triggerCountdown();
79651
79727
  return;
79652
79728
  }
79653
79729
  if (!this.askStartTime && this.pendingUpdate) {
79654
79730
  this.askStartTime = new Date;
79655
79731
  this.postAskMessage(threadIds, this.pendingUpdate.latestVersion).catch((err) => {
79656
- log30.warn(`Failed to post ask message: ${err}`);
79732
+ log32.warn(`Failed to post ask message: ${err}`);
79657
79733
  });
79658
79734
  return;
79659
79735
  }
@@ -79666,12 +79742,12 @@ class UpdateScheduler extends EventEmitter8 {
79666
79742
  denials++;
79667
79743
  }
79668
79744
  if (approvals > threadIds.length / 2) {
79669
- log30.info(`Majority approved (${approvals}/${threadIds.length}), triggering update`);
79745
+ log32.info(`Majority approved (${approvals}/${threadIds.length}), triggering update`);
79670
79746
  this.triggerCountdown();
79671
79747
  return;
79672
79748
  }
79673
79749
  if (denials > threadIds.length / 2) {
79674
- log30.info(`Majority denied (${denials}/${threadIds.length}), deferring update`);
79750
+ log32.info(`Majority denied (${denials}/${threadIds.length}), deferring update`);
79675
79751
  this.deferUpdate(60);
79676
79752
  return;
79677
79753
  }
@@ -79679,7 +79755,7 @@ class UpdateScheduler extends EventEmitter8 {
79679
79755
  const elapsedMs = Date.now() - this.askStartTime.getTime();
79680
79756
  const timeoutMs = this.config.askTimeoutMinutes * 60 * 1000;
79681
79757
  if (elapsedMs >= timeoutMs) {
79682
- log30.info(`Ask timeout reached (${this.config.askTimeoutMinutes} min), triggering update`);
79758
+ log32.info(`Ask timeout reached (${this.config.askTimeoutMinutes} min), triggering update`);
79683
79759
  this.triggerCountdown();
79684
79760
  }
79685
79761
  }
@@ -79699,7 +79775,7 @@ class UpdateScheduler extends EventEmitter8 {
79699
79775
  this.emit("ready", this.pendingUpdate);
79700
79776
  }
79701
79777
  }, 1000);
79702
- log30.info("Update countdown started (60 seconds)");
79778
+ log32.info("Update countdown started (60 seconds)");
79703
79779
  }
79704
79780
  stopCountdown() {
79705
79781
  if (this.countdownTimer) {
@@ -79715,24 +79791,24 @@ import { spawn as spawn4, spawnSync } from "child_process";
79715
79791
  import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync4 } from "fs";
79716
79792
  import { dirname as dirname8, resolve as resolve6 } from "path";
79717
79793
  import { homedir as homedir5 } from "os";
79718
- var log31 = createLogger("installer");
79794
+ var log33 = createLogger("installer");
79719
79795
  function detectPackageManager() {
79720
79796
  const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
79721
79797
  const originalInstaller = detectOriginalInstaller();
79722
79798
  if (originalInstaller) {
79723
- log31.debug(`Detected original installer: ${originalInstaller}`);
79799
+ log33.debug(`Detected original installer: ${originalInstaller}`);
79724
79800
  if (originalInstaller === "bun") {
79725
79801
  const bunCheck2 = spawnSync("bun", ["--version"], { stdio: "ignore" });
79726
79802
  if (bunCheck2.status === 0) {
79727
79803
  return { cmd: "bun", isBun: true };
79728
79804
  }
79729
- log31.warn("Originally installed with bun, but bun not found. Falling back to npm.");
79805
+ log33.warn("Originally installed with bun, but bun not found. Falling back to npm.");
79730
79806
  } else {
79731
79807
  const npmCheck2 = spawnSync(npmCmd, ["--version"], { stdio: "ignore" });
79732
79808
  if (npmCheck2.status === 0) {
79733
79809
  return { cmd: npmCmd, isBun: false };
79734
79810
  }
79735
- log31.warn("Originally installed with npm, but npm not found. Falling back to bun.");
79811
+ log33.warn("Originally installed with npm, but npm not found. Falling back to bun.");
79736
79812
  }
79737
79813
  }
79738
79814
  const bunCheck = spawnSync("bun", ["--version"], { stdio: "ignore" });
@@ -79783,7 +79859,7 @@ function loadUpdateState() {
79783
79859
  return JSON.parse(content);
79784
79860
  }
79785
79861
  } catch (err) {
79786
- log31.warn(`Failed to load update state: ${err}`);
79862
+ log33.warn(`Failed to load update state: ${err}`);
79787
79863
  }
79788
79864
  return {};
79789
79865
  }
@@ -79794,9 +79870,9 @@ function saveUpdateState(state) {
79794
79870
  mkdirSync4(dir, { recursive: true });
79795
79871
  }
79796
79872
  writeFileSync6(STATE_PATH, JSON.stringify(state, null, 2), "utf-8");
79797
- log31.debug("Update state saved");
79873
+ log33.debug("Update state saved");
79798
79874
  } catch (err) {
79799
- log31.warn(`Failed to save update state: ${err}`);
79875
+ log33.warn(`Failed to save update state: ${err}`);
79800
79876
  }
79801
79877
  }
79802
79878
  function clearUpdateState() {
@@ -79805,7 +79881,7 @@ function clearUpdateState() {
79805
79881
  writeFileSync6(STATE_PATH, "{}", "utf-8");
79806
79882
  }
79807
79883
  } catch (err) {
79808
- log31.warn(`Failed to clear update state: ${err}`);
79884
+ log33.warn(`Failed to clear update state: ${err}`);
79809
79885
  }
79810
79886
  }
79811
79887
  function checkJustUpdated() {
@@ -79837,11 +79913,11 @@ function clearRuntimeSettings() {
79837
79913
  }
79838
79914
  }
79839
79915
  async function installVersion(version) {
79840
- log31.info(`\uD83D\uDCE6 Installing ${PACKAGE_NAME2}@${version}...`);
79916
+ log33.info(`\uD83D\uDCE6 Installing ${PACKAGE_NAME2}@${version}...`);
79841
79917
  const pm = detectPackageManager();
79842
79918
  if (!pm) {
79843
79919
  const error = "Neither bun nor npm found in PATH. Cannot install update.";
79844
- log31.error(`❌ ${error}`);
79920
+ log33.error(`❌ ${error}`);
79845
79921
  return { success: false, error };
79846
79922
  }
79847
79923
  saveUpdateState({
@@ -79853,7 +79929,7 @@ async function installVersion(version) {
79853
79929
  return new Promise((resolve7) => {
79854
79930
  const { cmd, isBun: isBun3 } = pm;
79855
79931
  const args = ["install", "-g", `${PACKAGE_NAME2}@${version}`];
79856
- log31.debug(`Using ${isBun3 ? "bun" : "npm"} for installation`);
79932
+ log33.debug(`Using ${isBun3 ? "bun" : "npm"} for installation`);
79857
79933
  const child = spawn4(cmd, args, {
79858
79934
  stdio: ["ignore", "pipe", "pipe"],
79859
79935
  env: {
@@ -79871,7 +79947,7 @@ async function installVersion(version) {
79871
79947
  });
79872
79948
  child.on("close", (code) => {
79873
79949
  if (code === 0) {
79874
- log31.info(`✅ Successfully installed ${PACKAGE_NAME2}@${version}`);
79950
+ log33.info(`✅ Successfully installed ${PACKAGE_NAME2}@${version}`);
79875
79951
  saveUpdateState({
79876
79952
  previousVersion: VERSION,
79877
79953
  targetVersion: version,
@@ -79881,20 +79957,20 @@ async function installVersion(version) {
79881
79957
  resolve7({ success: true });
79882
79958
  } else {
79883
79959
  const errorMsg = stderr || stdout || `Exit code: ${code}`;
79884
- log31.error(`❌ Installation failed: ${errorMsg}`);
79960
+ log33.error(`❌ Installation failed: ${errorMsg}`);
79885
79961
  clearUpdateState();
79886
79962
  resolve7({ success: false, error: errorMsg });
79887
79963
  }
79888
79964
  });
79889
79965
  child.on("error", (err) => {
79890
- log31.error(`❌ Failed to spawn npm: ${err}`);
79966
+ log33.error(`❌ Failed to spawn npm: ${err}`);
79891
79967
  clearUpdateState();
79892
79968
  resolve7({ success: false, error: err.message });
79893
79969
  });
79894
79970
  setTimeout(() => {
79895
79971
  if (child.exitCode === null) {
79896
79972
  child.kill();
79897
- log31.error("❌ Installation timed out");
79973
+ log33.error("❌ Installation timed out");
79898
79974
  clearUpdateState();
79899
79975
  resolve7({ success: false, error: "Installation timed out" });
79900
79976
  }
@@ -79936,7 +80012,7 @@ class UpdateInstaller {
79936
80012
  }
79937
80013
 
79938
80014
  // src/auto-update/manager.ts
79939
- var log32 = createLogger("updater");
80015
+ var log34 = createLogger("updater");
79940
80016
 
79941
80017
  class AutoUpdateManager extends EventEmitter9 {
79942
80018
  config;
@@ -79959,23 +80035,23 @@ class AutoUpdateManager extends EventEmitter9 {
79959
80035
  }
79960
80036
  start() {
79961
80037
  if (!this.config.enabled) {
79962
- log32.info("Auto-update is disabled");
80038
+ log34.info("Auto-update is disabled");
79963
80039
  return;
79964
80040
  }
79965
80041
  const updateResult = this.installer.checkJustUpdated();
79966
80042
  if (updateResult) {
79967
- log32.info(`\uD83C\uDF89 Updated from v${updateResult.previousVersion} to v${updateResult.currentVersion}`);
80043
+ log34.info(`\uD83C\uDF89 Updated from v${updateResult.previousVersion} to v${updateResult.currentVersion}`);
79968
80044
  this.callbacks.broadcastUpdate((fmt) => `\uD83C\uDF89 ${fmt.formatBold("Bot updated")} from v${updateResult.previousVersion} to v${updateResult.currentVersion}`).catch((err) => {
79969
- log32.warn(`Failed to broadcast update notification: ${err}`);
80045
+ log34.warn(`Failed to broadcast update notification: ${err}`);
79970
80046
  });
79971
80047
  }
79972
80048
  this.checker.start();
79973
- log32.info(`\uD83D\uDD04 Auto-update manager started (mode: ${this.config.autoRestartMode})`);
80049
+ log34.info(`\uD83D\uDD04 Auto-update manager started (mode: ${this.config.autoRestartMode})`);
79974
80050
  }
79975
80051
  stop() {
79976
80052
  this.checker.stop();
79977
80053
  this.scheduler.stop();
79978
- log32.debug("Auto-update manager stopped");
80054
+ log34.debug("Auto-update manager stopped");
79979
80055
  }
79980
80056
  getState() {
79981
80057
  return { ...this.state };
@@ -79989,10 +80065,10 @@ class AutoUpdateManager extends EventEmitter9 {
79989
80065
  async forceUpdate() {
79990
80066
  const updateInfo = this.state.updateInfo || await this.checker.check();
79991
80067
  if (!updateInfo) {
79992
- log32.info("No update available");
80068
+ log34.info("No update available");
79993
80069
  return;
79994
80070
  }
79995
- log32.info("Forcing immediate update");
80071
+ log34.info("Forcing immediate update");
79996
80072
  await this.performUpdate(updateInfo);
79997
80073
  }
79998
80074
  deferUpdate(minutes = 60) {
@@ -80047,7 +80123,7 @@ class AutoUpdateManager extends EventEmitter9 {
80047
80123
  await this.callbacks.broadcastUpdate((fmt) => `✅ ${fmt.formatBold("Update installed")} - restarting now. ${fmt.formatItalic("Sessions will resume automatically.")}`).catch(() => {});
80048
80124
  await new Promise((resolve7) => setTimeout(resolve7, 1000));
80049
80125
  await this.callbacks.prepareForRestart();
80050
- log32.info(`\uD83D\uDD04 Restarting for update to v${updateInfo.latestVersion}`);
80126
+ log34.info(`\uD83D\uDD04 Restarting for update to v${updateInfo.latestVersion}`);
80051
80127
  process.stdout.write("\x1B[2J\x1B[H");
80052
80128
  process.stdout.write("\x1B[?25h");
80053
80129
  process.exit(RESTART_EXIT_CODE);
@@ -80104,7 +80180,8 @@ function wirePlatformEvents(platformId, client, session, ui) {
80104
80180
  ui.setPlatformStatus(platformId, { reconnecting: true, reconnectAttempts: attempt });
80105
80181
  });
80106
80182
  client.on("error", (e) => {
80107
- ui.addLog({ level: "error", component: platformId, message: String(e) });
80183
+ const message = e instanceof Error ? e.message : String(e);
80184
+ ui.addLog({ level: "error", component: platformId, message });
80108
80185
  });
80109
80186
  }
80110
80187
  program.name("claude-threads").version(VERSION).description("Share Claude Code sessions in Mattermost").option("--url <url>", "Mattermost server URL").option("--token <token>", "Mattermost bot token").option("--channel <id>", "Mattermost channel ID").option("--bot-name <name>", "Bot mention name (default: claude-code)").option("--allowed-users <users>", "Comma-separated allowed usernames").option("--permission-mode <mode>", "Permission mode: default | auto | bypass (default: from config)").option("--skip-permissions", "[deprecated] Alias for --permission-mode bypass").option("--no-skip-permissions", "[deprecated] Alias for --permission-mode default").option("--chrome", "Enable Claude in Chrome integration").option("--no-chrome", "Disable Claude in Chrome integration").option("--worktree-mode <mode>", "Git worktree mode: off, prompt, require (default: prompt)").option("--keep-alive", "Enable system sleep prevention (default: enabled)").option("--no-keep-alive", "Disable system sleep prevention").option("--setup", "Run interactive setup wizard (reconfigure existing settings)").option("--debug", "Enable debug logging").option("--skip-version-check", "Skip Claude CLI version compatibility check").option("--auto-restart", "Enable auto-restart on updates (default when autoUpdate enabled)").option("--no-auto-restart", "Disable auto-restart on updates").option("--headless", "Run without interactive UI (logs to stdout)").parse();