claude-threads 1.6.3 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -11880,7 +11880,7 @@ import * as fs from "fs/promises";
11880
11880
  import { homedir as homedir4 } from "os";
11881
11881
  async function execGit(args, cwd) {
11882
11882
  const cmd = `git ${args.join(" ")}`;
11883
- log7.debug(`Executing: ${cmd}`);
11883
+ log8.debug(`Executing: ${cmd}`);
11884
11884
  return new Promise((resolve3, reject) => {
11885
11885
  const proc = crossSpawn("git", args, { cwd });
11886
11886
  let stdout = "";
@@ -11893,15 +11893,15 @@ async function execGit(args, cwd) {
11893
11893
  });
11894
11894
  proc.on("close", (code) => {
11895
11895
  if (code === 0) {
11896
- log7.debug(`${cmd} → success`);
11896
+ log8.debug(`${cmd} → success`);
11897
11897
  resolve3(stdout.trim());
11898
11898
  } else {
11899
- log7.debug(`${cmd} → failed (code=${code}): ${stderr.substring(0, 100) || stdout.substring(0, 100)}`);
11899
+ log8.debug(`${cmd} → failed (code=${code}): ${stderr.substring(0, 100) || stdout.substring(0, 100)}`);
11900
11900
  reject(new Error(`git ${args.join(" ")} failed: ${stderr || stdout}`));
11901
11901
  }
11902
11902
  });
11903
11903
  proc.on("error", (err) => {
11904
- log7.warn(`${cmd} → error: ${err}`);
11904
+ log8.warn(`${cmd} → error: ${err}`);
11905
11905
  reject(err);
11906
11906
  });
11907
11907
  });
@@ -11911,7 +11911,7 @@ async function isGitRepository(dir) {
11911
11911
  await execGit(["rev-parse", "--git-dir"], dir);
11912
11912
  return true;
11913
11913
  } catch (err) {
11914
- log7.debug(`Not a git repository: ${dir} (${err})`);
11914
+ log8.debug(`Not a git repository: ${dir} (${err})`);
11915
11915
  return false;
11916
11916
  }
11917
11917
  }
@@ -12046,7 +12046,7 @@ async function detectWorktreeInfo(workingDir) {
12046
12046
  const branchOutput = await execGit(["rev-parse", "--abbrev-ref", "HEAD"], workingDir);
12047
12047
  const branch = branchOutput?.trim();
12048
12048
  if (!branch) {
12049
- log7.debug(`Could not detect branch for worktree at ${workingDir}`);
12049
+ log8.debug(`Could not detect branch for worktree at ${workingDir}`);
12050
12050
  return null;
12051
12051
  }
12052
12052
  const gitDirOutput = await execGit(["rev-parse", "--git-common-dir"], workingDir);
@@ -12058,45 +12058,45 @@ async function detectWorktreeInfo(workingDir) {
12058
12058
  repoRoot = repoRoot.slice(0, -4);
12059
12059
  }
12060
12060
  }
12061
- log7.debug(`Detected worktree: path=${workingDir}, branch=${branch}, repoRoot=${repoRoot}`);
12061
+ log8.debug(`Detected worktree: path=${workingDir}, branch=${branch}, repoRoot=${repoRoot}`);
12062
12062
  return {
12063
12063
  worktreePath: workingDir,
12064
12064
  branch,
12065
12065
  repoRoot: repoRoot || workingDir
12066
12066
  };
12067
12067
  } catch (err) {
12068
- log7.debug(`Failed to detect worktree info for ${workingDir}: ${err}`);
12068
+ log8.debug(`Failed to detect worktree info for ${workingDir}: ${err}`);
12069
12069
  return null;
12070
12070
  }
12071
12071
  }
12072
12072
  async function createWorktree(repoRoot, branch, targetDir) {
12073
- log7.info(`Creating worktree for branch '${branch}' at ${targetDir}`);
12073
+ log8.info(`Creating worktree for branch '${branch}' at ${targetDir}`);
12074
12074
  const parentDir = path.dirname(targetDir);
12075
- log7.debug(`Creating parent directory: ${parentDir}`);
12075
+ log8.debug(`Creating parent directory: ${parentDir}`);
12076
12076
  await fs.mkdir(parentDir, { recursive: true });
12077
12077
  const exists = await branchExists(repoRoot, branch);
12078
12078
  if (exists) {
12079
- log7.debug(`Branch '${branch}' exists, adding worktree`);
12079
+ log8.debug(`Branch '${branch}' exists, adding worktree`);
12080
12080
  await execGit(["worktree", "add", targetDir, branch], repoRoot);
12081
12081
  } else {
12082
- log7.debug(`Branch '${branch}' does not exist, creating with worktree`);
12082
+ log8.debug(`Branch '${branch}' does not exist, creating with worktree`);
12083
12083
  await execGit(["worktree", "add", "-b", branch, targetDir], repoRoot);
12084
12084
  }
12085
- log7.info(`Worktree created successfully: ${targetDir}`);
12085
+ log8.info(`Worktree created successfully: ${targetDir}`);
12086
12086
  return targetDir;
12087
12087
  }
12088
12088
  async function removeWorktree(repoRoot, worktreePath) {
12089
- log7.info(`Removing worktree: ${worktreePath}`);
12089
+ log8.info(`Removing worktree: ${worktreePath}`);
12090
12090
  try {
12091
12091
  await execGit(["worktree", "remove", worktreePath], repoRoot);
12092
- log7.debug("Worktree removed cleanly");
12092
+ log8.debug("Worktree removed cleanly");
12093
12093
  } catch (err) {
12094
- log7.debug(`Clean remove failed (${err}), trying force remove`);
12094
+ log8.debug(`Clean remove failed (${err}), trying force remove`);
12095
12095
  await execGit(["worktree", "remove", "--force", worktreePath], repoRoot);
12096
12096
  }
12097
- log7.debug("Pruning stale worktree references");
12097
+ log8.debug("Pruning stale worktree references");
12098
12098
  await execGit(["worktree", "prune"], repoRoot);
12099
- log7.info("Worktree removed and pruned successfully");
12099
+ log8.info("Worktree removed and pruned successfully");
12100
12100
  }
12101
12101
  async function findWorktreeByBranch(repoRoot, branch) {
12102
12102
  const worktrees = await listWorktrees(repoRoot);
@@ -12137,14 +12137,14 @@ async function writeMetadataStore(store) {
12137
12137
  await fs.writeFile(METADATA_STORE_PATH, JSON.stringify(store, null, 2), { encoding: "utf-8", mode: 384 });
12138
12138
  await fs.chmod(METADATA_STORE_PATH, 384);
12139
12139
  } catch (err) {
12140
- log7.warn(`Failed to write worktree metadata store: ${err}`);
12140
+ log8.warn(`Failed to write worktree metadata store: ${err}`);
12141
12141
  }
12142
12142
  }
12143
12143
  async function writeWorktreeMetadata(worktreePath, metadata) {
12144
12144
  const store = await readMetadataStore();
12145
12145
  store[worktreePath] = metadata;
12146
12146
  await writeMetadataStore(store);
12147
- log7.debug(`Wrote worktree metadata for: ${worktreePath}`);
12147
+ log8.debug(`Wrote worktree metadata for: ${worktreePath}`);
12148
12148
  }
12149
12149
  async function readWorktreeMetadata(worktreePath) {
12150
12150
  const store = await readMetadataStore();
@@ -12167,14 +12167,14 @@ async function removeWorktreeMetadata(worktreePath) {
12167
12167
  if (store[worktreePath]) {
12168
12168
  delete store[worktreePath];
12169
12169
  await writeMetadataStore(store);
12170
- log7.debug(`Removed worktree metadata for: ${worktreePath}`);
12170
+ log8.debug(`Removed worktree metadata for: ${worktreePath}`);
12171
12171
  }
12172
12172
  }
12173
- var log7, WORKTREES_DIR, METADATA_STORE_PATH;
12173
+ var log8, WORKTREES_DIR, METADATA_STORE_PATH;
12174
12174
  var init_worktree = __esm(() => {
12175
12175
  init_spawn();
12176
12176
  init_logger();
12177
- log7 = createLogger("git-wt");
12177
+ log8 = createLogger("git-wt");
12178
12178
  WORKTREES_DIR = path.join(homedir4(), ".claude-threads", "worktrees");
12179
12179
  METADATA_STORE_PATH = path.join(homedir4(), ".claude-threads", "worktree-metadata.json");
12180
12180
  });
@@ -19514,7 +19514,7 @@ var require_react_reconciler_development = __commonJS((exports, module) => {
19514
19514
  return hook.checkDCE ? true : false;
19515
19515
  }
19516
19516
  function setIsStrictModeForDevtools(newIsStrictMode) {
19517
- typeof log30 === "function" && unstable_setDisableYieldValue2(newIsStrictMode);
19517
+ typeof log31 === "function" && unstable_setDisableYieldValue2(newIsStrictMode);
19518
19518
  if (injectedHook && typeof injectedHook.setStrictMode === "function")
19519
19519
  try {
19520
19520
  injectedHook.setStrictMode(rendererID, newIsStrictMode);
@@ -27598,7 +27598,7 @@ Check the render method of %s.`, getComponentNameFromFiber(current) || "Unknown"
27598
27598
  var fiberStack = [];
27599
27599
  var index$jscomp$0 = -1, emptyContextObject = {};
27600
27600
  Object.freeze(emptyContextObject);
27601
- 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;
27601
+ 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, log31 = Scheduler.log, unstable_setDisableYieldValue2 = Scheduler.unstable_setDisableYieldValue, rendererID = null, injectedHook = null, hasLoggedError = false, isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined", lastResetTime = 0;
27602
27602
  if (typeof performance === "object" && typeof performance.now === "function") {
27603
27603
  var localPerformance = performance;
27604
27604
  var getCurrentTime = function() {
@@ -53546,6 +53546,99 @@ class SessionStore {
53546
53546
  chmodSync2(this.sessionsFile, 384);
53547
53547
  }
53548
53548
  }
53549
+ // src/claude/account-pool.ts
53550
+ init_logger();
53551
+ var log6 = createLogger("account-pool");
53552
+
53553
+ class AccountPool {
53554
+ accounts;
53555
+ byId;
53556
+ activeCounts = new Map;
53557
+ coolingUntil = new Map;
53558
+ roundRobinIndex = 0;
53559
+ constructor(accounts) {
53560
+ this.accounts = (accounts ?? []).filter((acc) => {
53561
+ const hasAuth = !!acc.home || !!acc.apiKey;
53562
+ if (!hasAuth) {
53563
+ log6.warn(`Claude account ${acc.id} has neither home nor apiKey — ignoring`);
53564
+ }
53565
+ return hasAuth;
53566
+ });
53567
+ this.byId = new Map(this.accounts.map((acc) => [acc.id, acc]));
53568
+ for (const acc of this.accounts) {
53569
+ this.activeCounts.set(acc.id, 0);
53570
+ }
53571
+ }
53572
+ get isEmpty() {
53573
+ return this.accounts.length === 0;
53574
+ }
53575
+ get size() {
53576
+ return this.accounts.length;
53577
+ }
53578
+ acquire(preferredId) {
53579
+ if (this.isEmpty)
53580
+ return null;
53581
+ if (preferredId) {
53582
+ const preferred = this.byId.get(preferredId);
53583
+ if (preferred) {
53584
+ this.incrementActive(preferred.id);
53585
+ return preferred;
53586
+ }
53587
+ log6.warn(`Preferred account "${preferredId}" not in pool — falling back to round-robin`);
53588
+ }
53589
+ const now = Date.now();
53590
+ const n = this.accounts.length;
53591
+ for (let i2 = 0;i2 < n; i2++) {
53592
+ const idx = (this.roundRobinIndex + i2) % n;
53593
+ const candidate = this.accounts[idx];
53594
+ const cooling = this.coolingUntil.get(candidate.id) ?? 0;
53595
+ if (cooling <= now) {
53596
+ this.roundRobinIndex = (idx + 1) % n;
53597
+ this.incrementActive(candidate.id);
53598
+ return candidate;
53599
+ }
53600
+ }
53601
+ log6.warn(`All ${n} accounts are in rate-limit cooldown`);
53602
+ return null;
53603
+ }
53604
+ release(accountId) {
53605
+ const current = this.activeCounts.get(accountId);
53606
+ if (current === undefined)
53607
+ return;
53608
+ this.activeCounts.set(accountId, Math.max(0, current - 1));
53609
+ }
53610
+ markCooling(accountId, untilEpochMs) {
53611
+ if (!this.byId.has(accountId)) {
53612
+ log6.warn(`markCooling called for unknown account "${accountId}"`);
53613
+ return;
53614
+ }
53615
+ const existing = this.coolingUntil.get(accountId) ?? 0;
53616
+ if (untilEpochMs > existing) {
53617
+ this.coolingUntil.set(accountId, untilEpochMs);
53618
+ const minutes = Math.ceil((untilEpochMs - Date.now()) / 60000);
53619
+ log6.info(`Account "${accountId}" cooling for ~${minutes}min`);
53620
+ }
53621
+ }
53622
+ get(accountId) {
53623
+ return this.byId.get(accountId);
53624
+ }
53625
+ status() {
53626
+ const now = Date.now();
53627
+ return this.accounts.map((acc) => {
53628
+ const cooling = this.coolingUntil.get(acc.id) ?? 0;
53629
+ return {
53630
+ id: acc.id,
53631
+ displayName: acc.displayName ?? acc.id,
53632
+ activeSessions: this.activeCounts.get(acc.id) ?? 0,
53633
+ coolingUntil: cooling > now ? cooling : null
53634
+ };
53635
+ });
53636
+ }
53637
+ incrementActive(accountId) {
53638
+ this.activeCounts.set(accountId, (this.activeCounts.get(accountId) ?? 0) + 1);
53639
+ }
53640
+ }
53641
+
53549
53642
  // src/session/manager.ts
53550
53643
  init_emoji();
53551
53644
 
@@ -53560,7 +53653,7 @@ init_logger();
53560
53653
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, appendFileSync, readdirSync, statSync, unlinkSync, rmdirSync, readFileSync as readFileSync5, chmodSync as chmodSync3 } from "fs";
53561
53654
  import { homedir as homedir3 } from "os";
53562
53655
  import { join as join4, dirname as dirname4 } from "path";
53563
- var log6 = createLogger("thread-log");
53656
+ var log7 = createLogger("thread-log");
53564
53657
  var LOGS_BASE_DIR = join4(homedir3(), ".claude-threads", "logs");
53565
53658
 
53566
53659
  class ThreadLoggerImpl {
@@ -53590,7 +53683,7 @@ class ThreadLoggerImpl {
53590
53683
  this.flushTimer = setInterval(() => {
53591
53684
  this.flushSync();
53592
53685
  }, this.flushIntervalMs);
53593
- log6.debug(`Thread logger initialized: ${this.logPath}`);
53686
+ log7.debug(`Thread logger initialized: ${this.logPath}`);
53594
53687
  }
53595
53688
  }
53596
53689
  isEnabled() {
@@ -53704,7 +53797,7 @@ class ThreadLoggerImpl {
53704
53797
  this.flushTimer = null;
53705
53798
  }
53706
53799
  this.flushSync();
53707
- log6.debug(`Thread logger closed: ${this.logPath}`);
53800
+ log7.debug(`Thread logger closed: ${this.logPath}`);
53708
53801
  }
53709
53802
  addEntry(entry) {
53710
53803
  this.buffer.push(entry);
@@ -53726,7 +53819,7 @@ class ThreadLoggerImpl {
53726
53819
  }
53727
53820
  this.buffer = [];
53728
53821
  } catch (err) {
53729
- log6.error(`Failed to flush thread log: ${err}`);
53822
+ log7.error(`Failed to flush thread log: ${err}`);
53730
53823
  }
53731
53824
  }
53732
53825
  }
@@ -53777,25 +53870,25 @@ function cleanupOldLogs(retentionDays = 30) {
53777
53870
  if (fileStat.mtimeMs < cutoffMs) {
53778
53871
  unlinkSync(filePath);
53779
53872
  deletedCount++;
53780
- log6.debug(`Deleted old log file: ${filePath}`);
53873
+ log7.debug(`Deleted old log file: ${filePath}`);
53781
53874
  }
53782
53875
  } catch (err) {
53783
- log6.warn(`Failed to check/delete log file ${filePath}: ${err}`);
53876
+ log7.warn(`Failed to check/delete log file ${filePath}: ${err}`);
53784
53877
  }
53785
53878
  }
53786
53879
  try {
53787
53880
  const remaining = readdirSync(platformDir);
53788
53881
  if (remaining.length === 0) {
53789
53882
  rmdirSync(platformDir);
53790
- log6.debug(`Removed empty platform log directory: ${platformDir}`);
53883
+ log7.debug(`Removed empty platform log directory: ${platformDir}`);
53791
53884
  }
53792
53885
  } catch {}
53793
53886
  }
53794
53887
  if (deletedCount > 0) {
53795
- log6.info(`Cleaned up ${deletedCount} old log file(s)`);
53888
+ log7.info(`Cleaned up ${deletedCount} old log file(s)`);
53796
53889
  }
53797
53890
  } catch (err) {
53798
- log6.error(`Failed to clean up old logs: ${err}`);
53891
+ log7.error(`Failed to clean up old logs: ${err}`);
53799
53892
  }
53800
53893
  return deletedCount;
53801
53894
  }
@@ -53804,16 +53897,16 @@ function getLogFilePath(platformId, sessionId) {
53804
53897
  }
53805
53898
  function readRecentLogEntries(platformId, sessionId, maxLines = 50) {
53806
53899
  const logPath = getLogFilePath(platformId, sessionId);
53807
- log6.debug(`Reading log entries from: ${logPath}`);
53900
+ log7.debug(`Reading log entries from: ${logPath}`);
53808
53901
  if (!existsSync6(logPath)) {
53809
- log6.debug(`Log file does not exist: ${logPath}`);
53902
+ log7.debug(`Log file does not exist: ${logPath}`);
53810
53903
  return [];
53811
53904
  }
53812
53905
  try {
53813
53906
  const content = readFileSync5(logPath, "utf8");
53814
53907
  const lines = content.trim().split(`
53815
53908
  `);
53816
- log6.debug(`Log file has ${lines.length} lines`);
53909
+ log7.debug(`Log file has ${lines.length} lines`);
53817
53910
  const recentLines = lines.slice(-maxLines);
53818
53911
  const entries = [];
53819
53912
  for (const line of recentLines) {
@@ -53823,17 +53916,17 @@ function readRecentLogEntries(platformId, sessionId, maxLines = 50) {
53823
53916
  entries.push(JSON.parse(line));
53824
53917
  } catch {}
53825
53918
  }
53826
- log6.debug(`Parsed ${entries.length} log entries`);
53919
+ log7.debug(`Parsed ${entries.length} log entries`);
53827
53920
  return entries;
53828
53921
  } catch (err) {
53829
- log6.error(`Failed to read log file: ${err}`);
53922
+ log7.error(`Failed to read log file: ${err}`);
53830
53923
  return [];
53831
53924
  }
53832
53925
  }
53833
53926
 
53834
53927
  // src/cleanup/scheduler.ts
53835
53928
  init_worktree();
53836
- var log8 = createLogger("cleanup");
53929
+ var log9 = createLogger("cleanup");
53837
53930
  var DEFAULT_CLEANUP_INTERVAL_MS = 60 * 60 * 1000;
53838
53931
  var MAX_WORKTREE_AGE_MS = 24 * 60 * 60 * 1000;
53839
53932
 
@@ -53856,17 +53949,17 @@ class CleanupScheduler {
53856
53949
  }
53857
53950
  start() {
53858
53951
  if (this.isRunning) {
53859
- log8.debug("Cleanup scheduler already running");
53952
+ log9.debug("Cleanup scheduler already running");
53860
53953
  return;
53861
53954
  }
53862
53955
  this.isRunning = true;
53863
- log8.info(`Cleanup scheduler started (interval: ${Math.round(this.intervalMs / 60000)}min)`);
53956
+ log9.info(`Cleanup scheduler started (interval: ${Math.round(this.intervalMs / 60000)}min)`);
53864
53957
  this.runCleanup().catch((err) => {
53865
- log8.warn(`Initial cleanup failed: ${err}`);
53958
+ log9.warn(`Initial cleanup failed: ${err}`);
53866
53959
  });
53867
53960
  this.timer = setInterval(() => {
53868
53961
  this.runCleanup().catch((err) => {
53869
- log8.warn(`Periodic cleanup failed: ${err}`);
53962
+ log9.warn(`Periodic cleanup failed: ${err}`);
53870
53963
  });
53871
53964
  }, this.intervalMs);
53872
53965
  }
@@ -53876,11 +53969,11 @@ class CleanupScheduler {
53876
53969
  this.timer = null;
53877
53970
  }
53878
53971
  this.isRunning = false;
53879
- log8.debug("Cleanup scheduler stopped");
53972
+ log9.debug("Cleanup scheduler stopped");
53880
53973
  }
53881
53974
  async runCleanup() {
53882
53975
  const startTime = Date.now();
53883
- log8.debug("Running background cleanup...");
53976
+ log9.debug("Running background cleanup...");
53884
53977
  const stats = {
53885
53978
  logsDeleted: 0,
53886
53979
  worktreesCleaned: 0,
@@ -53906,9 +53999,9 @@ class CleanupScheduler {
53906
53999
  const elapsed = Date.now() - startTime;
53907
54000
  const totalCleaned = stats.logsDeleted + stats.worktreesCleaned + stats.metadataCleaned;
53908
54001
  if (totalCleaned > 0 || stats.errors.length > 0) {
53909
- log8.info(`Cleanup completed in ${elapsed}ms: ` + `${stats.logsDeleted} logs, ${stats.worktreesCleaned} worktrees, ${stats.metadataCleaned} metadata` + (stats.errors.length > 0 ? ` (${stats.errors.length} errors)` : ""));
54002
+ log9.info(`Cleanup completed in ${elapsed}ms: ` + `${stats.logsDeleted} logs, ${stats.worktreesCleaned} worktrees, ${stats.metadataCleaned} metadata` + (stats.errors.length > 0 ? ` (${stats.errors.length} errors)` : ""));
53910
54003
  } else {
53911
- log8.debug(`Cleanup completed in ${elapsed}ms (nothing to clean)`);
54004
+ log9.debug(`Cleanup completed in ${elapsed}ms (nothing to clean)`);
53912
54005
  }
53913
54006
  return stats;
53914
54007
  }
@@ -53921,7 +54014,7 @@ class CleanupScheduler {
53921
54014
  const deleted = cleanupOldLogs(this.logRetentionDays);
53922
54015
  resolve3(deleted);
53923
54016
  } catch (err) {
53924
- log8.warn(`Log cleanup error: ${err}`);
54017
+ log9.warn(`Log cleanup error: ${err}`);
53925
54018
  resolve3(0);
53926
54019
  }
53927
54020
  });
@@ -53930,7 +54023,7 @@ class CleanupScheduler {
53930
54023
  const worktreesDir = getWorktreesDir();
53931
54024
  const result = { cleaned: 0, metadata: 0 };
53932
54025
  if (!existsSync7(worktreesDir)) {
53933
- log8.debug("No worktrees directory exists, nothing to clean");
54026
+ log9.debug("No worktrees directory exists, nothing to clean");
53934
54027
  return result;
53935
54028
  }
53936
54029
  const persisted = this.sessionStore.load();
@@ -53948,7 +54041,7 @@ class CleanupScheduler {
53948
54041
  continue;
53949
54042
  const worktreePath = join6(worktreesDir, entry.name);
53950
54043
  if (activeWorktrees.has(worktreePath)) {
53951
- log8.debug(`Worktree in use by persisted session, skipping: ${entry.name}`);
54044
+ log9.debug(`Worktree in use by persisted session, skipping: ${entry.name}`);
53952
54045
  continue;
53953
54046
  }
53954
54047
  const meta = await readWorktreeMetadata(worktreePath);
@@ -53958,7 +54051,7 @@ class CleanupScheduler {
53958
54051
  const lastActivity = new Date(meta.lastActivityAt).getTime();
53959
54052
  const age = now - lastActivity;
53960
54053
  if (meta.sessionId && age < this.maxWorktreeAgeMs) {
53961
- log8.debug(`Worktree has active session (${Math.round(age / 60000)}min old), skipping: ${entry.name}`);
54054
+ log9.debug(`Worktree has active session (${Math.round(age / 60000)}min old), skipping: ${entry.name}`);
53962
54055
  continue;
53963
54056
  }
53964
54057
  const merged = age >= this.maxWorktreeAgeMs ? await isBranchMerged(meta.repoRoot, meta.branch).catch(() => false) : false;
@@ -53969,7 +54062,7 @@ class CleanupScheduler {
53969
54062
  shouldCleanup = true;
53970
54063
  cleanupReason = `inactive for ${Math.round(age / 3600000)}h`;
53971
54064
  } else {
53972
- log8.debug(`Worktree recent (${Math.round(age / 60000)}min old), skipping: ${entry.name}`);
54065
+ log9.debug(`Worktree recent (${Math.round(age / 60000)}min old), skipping: ${entry.name}`);
53973
54066
  continue;
53974
54067
  }
53975
54068
  } else {
@@ -53978,7 +54071,7 @@ class CleanupScheduler {
53978
54071
  }
53979
54072
  if (!shouldCleanup)
53980
54073
  continue;
53981
- log8.info(`Cleaning worktree (${cleanupReason}): ${entry.name}`);
54074
+ log9.info(`Cleaning worktree (${cleanupReason}): ${entry.name}`);
53982
54075
  try {
53983
54076
  if (meta?.repoRoot) {
53984
54077
  await removeWorktree(meta.repoRoot, worktreePath);
@@ -53989,19 +54082,19 @@ class CleanupScheduler {
53989
54082
  await removeWorktreeMetadata(worktreePath);
53990
54083
  result.metadata++;
53991
54084
  } catch (err) {
53992
- log8.warn(`Failed to clean orphaned worktree ${entry.name}: ${err}`);
54085
+ log9.warn(`Failed to clean orphaned worktree ${entry.name}: ${err}`);
53993
54086
  try {
53994
54087
  await rm(worktreePath, { recursive: true, force: true });
53995
54088
  result.cleaned++;
53996
54089
  await removeWorktreeMetadata(worktreePath);
53997
54090
  result.metadata++;
53998
54091
  } catch (rmErr) {
53999
- log8.error(`Failed to force remove worktree ${entry.name}: ${rmErr}`);
54092
+ log9.error(`Failed to force remove worktree ${entry.name}: ${rmErr}`);
54000
54093
  }
54001
54094
  }
54002
54095
  }
54003
54096
  } catch (err) {
54004
- log8.warn(`Failed to scan worktrees directory: ${err}`);
54097
+ log9.warn(`Failed to scan worktrees directory: ${err}`);
54005
54098
  }
54006
54099
  return result;
54007
54100
  }
@@ -54078,7 +54171,70 @@ import { fileURLToPath as fileURLToPath3 } from "url";
54078
54171
  import { existsSync as existsSync8, readFileSync as readFileSync6, watchFile, unwatchFile, unlinkSync as unlinkSync2, statSync as statSync2, readdirSync as readdirSync2 } from "fs";
54079
54172
  import { tmpdir } from "os";
54080
54173
  import { join as join7 } from "path";
54081
- var log9 = createLogger("claude");
54174
+
54175
+ // src/claude/rate-limit-detector.ts
54176
+ var RATE_LIMIT_PHRASES = [
54177
+ /usage limit reached/i,
54178
+ /rate[_\s-]?limit[_\s-]?error/i,
54179
+ /you have hit the rate limit/i,
54180
+ /quota (has been )?exceeded/i,
54181
+ /\b429\b.*(rate|limit|quota)/i
54182
+ ];
54183
+ var DEFAULT_COOLDOWN_MS = 60 * 60 * 1000;
54184
+ function detectRateLimit(text, now = Date.now()) {
54185
+ if (!text)
54186
+ return { detected: false };
54187
+ let matched;
54188
+ for (const phrase of RATE_LIMIT_PHRASES) {
54189
+ const m = text.match(phrase);
54190
+ if (m) {
54191
+ matched = m[0];
54192
+ break;
54193
+ }
54194
+ }
54195
+ if (!matched)
54196
+ return { detected: false };
54197
+ const resetAtEpochMs = extractResetAt(text, now);
54198
+ return { detected: true, matched, resetAtEpochMs };
54199
+ }
54200
+ function cooldownDeadline(hit, now = Date.now()) {
54201
+ if (!hit.detected)
54202
+ return now;
54203
+ return hit.resetAtEpochMs ?? now + DEFAULT_COOLDOWN_MS;
54204
+ }
54205
+ function extractResetAt(text, now) {
54206
+ const relative = text.match(/(?:retry[_\s-]?after|resets?\s+in)\s+(\d+)\s*(second|minute|hour|day)s?/i);
54207
+ if (relative) {
54208
+ const value = parseInt(relative[1], 10);
54209
+ const unit = relative[2].toLowerCase();
54210
+ const unitMs = {
54211
+ second: 1000,
54212
+ minute: 60000,
54213
+ hour: 3600000,
54214
+ day: 86400000
54215
+ };
54216
+ return now + value * unitMs[unit];
54217
+ }
54218
+ const unix = text.match(/["']?reset(?:_at)?["']?\s*[:=]\s*(\d{10,13})/);
54219
+ if (unix) {
54220
+ const raw = parseInt(unix[1], 10);
54221
+ return unix[1].length === 13 ? raw : raw * 1000;
54222
+ }
54223
+ const clock = text.match(/resets?\s+at\s+(\d{1,2}):(\d{2})\s*(utc|gmt)?/i);
54224
+ if (clock) {
54225
+ const hh = parseInt(clock[1], 10);
54226
+ const mm = parseInt(clock[2], 10);
54227
+ if (hh < 24 && mm < 60) {
54228
+ const reference = new Date(now);
54229
+ const target = new Date(Date.UTC(reference.getUTCFullYear(), reference.getUTCMonth(), reference.getUTCDate(), hh, mm)).getTime();
54230
+ return target > now ? target : target + 86400000;
54231
+ }
54232
+ }
54233
+ return;
54234
+ }
54235
+
54236
+ // src/claude/cli.ts
54237
+ var log10 = createLogger("claude");
54082
54238
  function cleanupBrowserBridgeSockets() {
54083
54239
  try {
54084
54240
  const tempDir = tmpdir();
@@ -54090,15 +54246,23 @@ function cleanupBrowserBridgeSockets() {
54090
54246
  const stats = statSync2(filePath);
54091
54247
  if (stats.isSocket()) {
54092
54248
  unlinkSync2(filePath);
54093
- log9.debug(`Removed stale browser bridge socket: ${file}`);
54249
+ log10.debug(`Removed stale browser bridge socket: ${file}`);
54094
54250
  }
54095
54251
  } catch {}
54096
54252
  }
54097
54253
  }
54098
54254
  } catch (err) {
54099
- log9.debug(`Browser bridge cleanup failed: ${err}`);
54255
+ log10.debug(`Browser bridge cleanup failed: ${err}`);
54100
54256
  }
54101
54257
  }
54258
+ function isErrorResultEvent(event) {
54259
+ const ev = event;
54260
+ if (typeof ev.subtype === "string" && ev.subtype.startsWith("error"))
54261
+ return true;
54262
+ if (ev.is_error === true)
54263
+ return true;
54264
+ return false;
54265
+ }
54102
54266
 
54103
54267
  class ClaudeCli extends EventEmitter2 {
54104
54268
  process = null;
@@ -54108,6 +54272,7 @@ class ClaudeCli extends EventEmitter2 {
54108
54272
  statusFilePath = null;
54109
54273
  lastStatusData = null;
54110
54274
  stderrBuffer = "";
54275
+ rateLimitEmitted = false;
54111
54276
  log;
54112
54277
  constructor(options2) {
54113
54278
  super();
@@ -54159,6 +54324,7 @@ class ClaudeCli extends EventEmitter2 {
54159
54324
  if (this.process)
54160
54325
  throw new Error("Already running");
54161
54326
  this.stderrBuffer = "";
54327
+ this.rateLimitEmitted = false;
54162
54328
  cleanupBrowserBridgeSockets();
54163
54329
  const claudePath = getClaudePath();
54164
54330
  const args = [
@@ -54228,9 +54394,13 @@ class ClaudeCli extends EventEmitter2 {
54228
54394
  args.push("--settings", JSON.stringify(statusLineSettings));
54229
54395
  }
54230
54396
  this.log.debug(`Starting: ${claudePath} ${args.slice(0, 5).join(" ")}...`);
54397
+ const childEnv = this.buildChildEnv();
54398
+ if (this.options.account) {
54399
+ this.log.debug(`Spawning under Claude account "${this.options.account.id}"`);
54400
+ }
54231
54401
  this.process = crossSpawn(claudePath, args, {
54232
54402
  cwd: this.options.workingDir,
54233
- env: process.env,
54403
+ env: childEnv,
54234
54404
  stdio: ["pipe", "pipe", "pipe"]
54235
54405
  });
54236
54406
  this.log.debug(`Claude process spawned: pid=${this.process.pid}`);
@@ -54244,6 +54414,7 @@ class ClaudeCli extends EventEmitter2 {
54244
54414
  this.stderrBuffer = this.stderrBuffer.slice(-10240);
54245
54415
  }
54246
54416
  this.log.debug(`stderr: ${text.trim()}`);
54417
+ this.maybeEmitRateLimit(text);
54247
54418
  });
54248
54419
  this.process.on("error", (err) => {
54249
54420
  this.log.error(`Claude error: ${err}`);
@@ -54298,9 +54469,22 @@ class ClaudeCli extends EventEmitter2 {
54298
54469
  try {
54299
54470
  const event = JSON.parse(trimmed);
54300
54471
  this.emit("event", event);
54472
+ if (event.type === "result" && isErrorResultEvent(event)) {
54473
+ this.maybeEmitRateLimit(trimmed);
54474
+ }
54301
54475
  } catch {}
54302
54476
  }
54303
54477
  }
54478
+ maybeEmitRateLimit(text) {
54479
+ const hit = detectRateLimit(text);
54480
+ if (!hit.detected)
54481
+ return;
54482
+ if (this.rateLimitEmitted)
54483
+ return;
54484
+ this.rateLimitEmitted = true;
54485
+ this.log.warn(`Rate limit detected: ${hit.matched ?? "(no match text)"}`);
54486
+ this.emit("rate-limit", hit);
54487
+ }
54304
54488
  isRunning() {
54305
54489
  return this.process !== null;
54306
54490
  }
@@ -54369,6 +54553,22 @@ class ClaudeCli extends EventEmitter2 {
54369
54553
  this.process.kill("SIGINT");
54370
54554
  return true;
54371
54555
  }
54556
+ buildChildEnv() {
54557
+ const account = this.options.account;
54558
+ if (!account)
54559
+ return process.env;
54560
+ const env = { ...process.env };
54561
+ if (account.home) {
54562
+ env.HOME = account.home;
54563
+ env.USERPROFILE = account.home;
54564
+ delete env.ANTHROPIC_API_KEY;
54565
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
54566
+ } else if (account.apiKey) {
54567
+ env.ANTHROPIC_API_KEY = account.apiKey;
54568
+ delete env.CLAUDE_CODE_OAUTH_TOKEN;
54569
+ }
54570
+ return env;
54571
+ }
54372
54572
  getMcpServerPath() {
54373
54573
  const __filename2 = fileURLToPath3(import.meta.url);
54374
54574
  const __dirname4 = dirname6(__filename2);
@@ -55205,7 +55405,7 @@ import { existsSync as existsSync11 } from "fs";
55205
55405
  // src/utils/keep-alive.ts
55206
55406
  init_logger();
55207
55407
  import { spawn as spawn2 } from "child_process";
55208
- var log10 = createLogger("keepalive");
55408
+ var log11 = createLogger("keepalive");
55209
55409
 
55210
55410
  class KeepAliveManager {
55211
55411
  activeSessionCount = 0;
@@ -55220,7 +55420,7 @@ class KeepAliveManager {
55220
55420
  if (!enabled && this.keepAliveProcess) {
55221
55421
  this.stopKeepAlive();
55222
55422
  }
55223
- log10.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
55423
+ log11.debug(`Keep-alive ${enabled ? "enabled" : "disabled"}`);
55224
55424
  }
55225
55425
  isEnabled() {
55226
55426
  return this.enabled;
@@ -55230,7 +55430,7 @@ class KeepAliveManager {
55230
55430
  }
55231
55431
  sessionStarted() {
55232
55432
  this.activeSessionCount++;
55233
- log10.debug(`Session started (${this.activeSessionCount} active)`);
55433
+ log11.debug(`Session started (${this.activeSessionCount} active)`);
55234
55434
  if (this.activeSessionCount === 1) {
55235
55435
  this.startKeepAlive();
55236
55436
  }
@@ -55239,7 +55439,7 @@ class KeepAliveManager {
55239
55439
  if (this.activeSessionCount > 0) {
55240
55440
  this.activeSessionCount--;
55241
55441
  }
55242
- log10.debug(`Session ended (${this.activeSessionCount} active)`);
55442
+ log11.debug(`Session ended (${this.activeSessionCount} active)`);
55243
55443
  if (this.activeSessionCount === 0) {
55244
55444
  this.stopKeepAlive();
55245
55445
  }
@@ -55253,11 +55453,11 @@ class KeepAliveManager {
55253
55453
  }
55254
55454
  startKeepAlive() {
55255
55455
  if (!this.enabled) {
55256
- log10.debug("Keep-alive disabled, skipping");
55456
+ log11.debug("Keep-alive disabled, skipping");
55257
55457
  return;
55258
55458
  }
55259
55459
  if (this.keepAliveProcess) {
55260
- log10.debug("Keep-alive already running");
55460
+ log11.debug("Keep-alive already running");
55261
55461
  return;
55262
55462
  }
55263
55463
  switch (this.platform) {
@@ -55271,12 +55471,12 @@ class KeepAliveManager {
55271
55471
  this.startWindowsKeepAlive();
55272
55472
  break;
55273
55473
  default:
55274
- log10.warn(`Keep-alive not supported on ${this.platform}`);
55474
+ log11.warn(`Keep-alive not supported on ${this.platform}`);
55275
55475
  }
55276
55476
  }
55277
55477
  stopKeepAlive() {
55278
55478
  if (this.keepAliveProcess) {
55279
- log10.debug("Stopping keep-alive");
55479
+ log11.debug("Stopping keep-alive");
55280
55480
  this.keepAliveProcess.kill();
55281
55481
  this.keepAliveProcess = null;
55282
55482
  }
@@ -55288,18 +55488,18 @@ class KeepAliveManager {
55288
55488
  detached: false
55289
55489
  });
55290
55490
  this.keepAliveProcess.on("error", (err) => {
55291
- log10.error(`Failed to start caffeinate: ${err.message}`);
55491
+ log11.error(`Failed to start caffeinate: ${err.message}`);
55292
55492
  this.keepAliveProcess = null;
55293
55493
  });
55294
55494
  this.keepAliveProcess.on("exit", (code) => {
55295
55495
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55296
- log10.debug(`caffeinate exited with code ${code}`);
55496
+ log11.debug(`caffeinate exited with code ${code}`);
55297
55497
  }
55298
55498
  this.keepAliveProcess = null;
55299
55499
  });
55300
- log10.info("Sleep prevention active (caffeinate)");
55500
+ log11.info("Sleep prevention active (caffeinate)");
55301
55501
  } catch (err) {
55302
- log10.error(`Failed to start caffeinate: ${err}`);
55502
+ log11.error(`Failed to start caffeinate: ${err}`);
55303
55503
  }
55304
55504
  }
55305
55505
  startLinuxKeepAlive() {
@@ -55315,19 +55515,19 @@ class KeepAliveManager {
55315
55515
  detached: false
55316
55516
  });
55317
55517
  this.keepAliveProcess.on("error", (err) => {
55318
- log10.debug(`systemd-inhibit not available: ${err.message}`);
55518
+ log11.debug(`systemd-inhibit not available: ${err.message}`);
55319
55519
  this.keepAliveProcess = null;
55320
55520
  this.startLinuxKeepAliveFallback();
55321
55521
  });
55322
55522
  this.keepAliveProcess.on("exit", (code) => {
55323
55523
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55324
- log10.debug(`systemd-inhibit exited with code ${code}`);
55524
+ log11.debug(`systemd-inhibit exited with code ${code}`);
55325
55525
  }
55326
55526
  this.keepAliveProcess = null;
55327
55527
  });
55328
- log10.info("Sleep prevention active (systemd-inhibit)");
55528
+ log11.info("Sleep prevention active (systemd-inhibit)");
55329
55529
  } catch (err) {
55330
- log10.debug(`Failed to start systemd-inhibit: ${err}`);
55530
+ log11.debug(`Failed to start systemd-inhibit: ${err}`);
55331
55531
  this.startLinuxKeepAliveFallback();
55332
55532
  }
55333
55533
  }
@@ -55341,15 +55541,15 @@ class KeepAliveManager {
55341
55541
  detached: false
55342
55542
  });
55343
55543
  this.keepAliveProcess.on("error", (err) => {
55344
- log10.warn(`Linux keep-alive fallback not available: ${err.message}`);
55544
+ log11.warn(`Linux keep-alive fallback not available: ${err.message}`);
55345
55545
  this.keepAliveProcess = null;
55346
55546
  });
55347
55547
  this.keepAliveProcess.on("exit", () => {
55348
55548
  this.keepAliveProcess = null;
55349
55549
  });
55350
- log10.info("Sleep prevention active (xdg-screensaver)");
55550
+ log11.info("Sleep prevention active (xdg-screensaver)");
55351
55551
  } catch (err) {
55352
- log10.warn(`Linux keep-alive not available: ${err}`);
55552
+ log11.warn(`Linux keep-alive not available: ${err}`);
55353
55553
  }
55354
55554
  }
55355
55555
  startWindowsKeepAlive() {
@@ -55374,18 +55574,18 @@ class KeepAliveManager {
55374
55574
  windowsHide: true
55375
55575
  });
55376
55576
  this.keepAliveProcess.on("error", (err) => {
55377
- log10.warn(`Windows keep-alive not available: ${err.message}`);
55577
+ log11.warn(`Windows keep-alive not available: ${err.message}`);
55378
55578
  this.keepAliveProcess = null;
55379
55579
  });
55380
55580
  this.keepAliveProcess.on("exit", (code) => {
55381
55581
  if (code !== null && code !== 0 && this.activeSessionCount > 0) {
55382
- log10.debug(`PowerShell keep-alive exited with code ${code}`);
55582
+ log11.debug(`PowerShell keep-alive exited with code ${code}`);
55383
55583
  }
55384
55584
  this.keepAliveProcess = null;
55385
55585
  });
55386
- log10.info("Sleep prevention active (SetThreadExecutionState)");
55586
+ log11.info("Sleep prevention active (SetThreadExecutionState)");
55387
55587
  } catch (err) {
55388
- log10.warn(`Windows keep-alive not available: ${err}`);
55588
+ log11.warn(`Windows keep-alive not available: ${err}`);
55389
55589
  }
55390
55590
  }
55391
55591
  }
@@ -55393,7 +55593,7 @@ var keepAlive = new KeepAliveManager;
55393
55593
 
55394
55594
  // src/utils/error-handler/index.ts
55395
55595
  init_logger();
55396
- var log11 = createLogger("error");
55596
+ var log12 = createLogger("error");
55397
55597
 
55398
55598
  class SessionError extends Error {
55399
55599
  sessionId;
@@ -55419,19 +55619,19 @@ async function handleError(error, context, severity = "recoverable") {
55419
55619
  const sessionPart = sessionId ? ` (${formatShortId(sessionId)})` : "";
55420
55620
  const logMessage = `${context.action}${sessionPart}: ${message}`;
55421
55621
  if (severity === "recoverable") {
55422
- log11.warn(logMessage);
55622
+ log12.warn(logMessage);
55423
55623
  } else {
55424
- log11.error(logMessage, error instanceof Error ? error : undefined);
55624
+ log12.error(logMessage, error instanceof Error ? error : undefined);
55425
55625
  }
55426
55626
  if (context.details) {
55427
- log11.debugJson("Error details", context.details);
55627
+ log12.debugJson("Error details", context.details);
55428
55628
  }
55429
55629
  if (context.notifyUser && context.session) {
55430
55630
  try {
55431
55631
  const fmt = context.session.platform.getFormatter();
55432
55632
  await context.session.platform.createPost(`⚠️ ${fmt.formatBold("Error")}: ${context.action} failed - ${message}`, context.session.threadId);
55433
55633
  } catch (notifyError) {
55434
- log11.warn(`Could not notify user: ${notifyError}`);
55634
+ log12.warn(`Could not notify user: ${notifyError}`);
55435
55635
  }
55436
55636
  }
55437
55637
  if (severity === "session-fatal" || severity === "system-fatal") {
@@ -55458,7 +55658,7 @@ async function logAndNotify(error, context) {
55458
55658
  }
55459
55659
  function logSilentError(context, error) {
55460
55660
  const message = error instanceof Error ? error.message : String(error);
55461
- log11.debug(`[${context}] Silently caught: ${message}`);
55661
+ log12.debug(`[${context}] Silently caught: ${message}`);
55462
55662
  }
55463
55663
 
55464
55664
  // src/session/lifecycle.ts
@@ -55478,8 +55678,8 @@ function createSessionLog(baseLog) {
55478
55678
  init_logger();
55479
55679
  init_emoji();
55480
55680
  init_worktree();
55481
- var log12 = createLogger("helpers");
55482
- var sessionLog = createSessionLog(log12);
55681
+ var log13 = createLogger("helpers");
55682
+ var sessionLog = createSessionLog(log13);
55483
55683
  var POST_TYPES = {
55484
55684
  info: "",
55485
55685
  success: "✅",
@@ -55563,7 +55763,7 @@ function updateLastMessage(session, post2) {
55563
55763
  // src/claude/quick-query.ts
55564
55764
  init_spawn();
55565
55765
  init_logger();
55566
- var log13 = createLogger("query");
55766
+ var log14 = createLogger("query");
55567
55767
  async function quickQuery(options2) {
55568
55768
  const {
55569
55769
  prompt,
@@ -55579,7 +55779,7 @@ async function quickQuery(options2) {
55579
55779
  args.push("--system-prompt", systemPrompt);
55580
55780
  }
55581
55781
  args.push(prompt);
55582
- log13.debug(`Quick query: model=${model}, timeout=${timeout}ms, prompt="${prompt.substring(0, 50)}..."`);
55782
+ log14.debug(`Quick query: model=${model}, timeout=${timeout}ms, prompt="${prompt.substring(0, 50)}..."`);
55583
55783
  return new Promise((resolve5) => {
55584
55784
  let stdout = "";
55585
55785
  let stderr = "";
@@ -55593,7 +55793,7 @@ async function quickQuery(options2) {
55593
55793
  if (!resolved) {
55594
55794
  resolved = true;
55595
55795
  proc.kill("SIGTERM");
55596
- log13.debug(`Quick query timed out after ${timeout}ms`);
55796
+ log14.debug(`Quick query timed out after ${timeout}ms`);
55597
55797
  resolve5({
55598
55798
  success: false,
55599
55799
  error: "timeout",
@@ -55611,7 +55811,7 @@ async function quickQuery(options2) {
55611
55811
  if (!resolved) {
55612
55812
  resolved = true;
55613
55813
  clearTimeout(timeoutId);
55614
- log13.debug(`Quick query error: ${err.message}`);
55814
+ log14.debug(`Quick query error: ${err.message}`);
55615
55815
  resolve5({
55616
55816
  success: false,
55617
55817
  error: err.message,
@@ -55625,14 +55825,14 @@ async function quickQuery(options2) {
55625
55825
  clearTimeout(timeoutId);
55626
55826
  const durationMs = Date.now() - startTime;
55627
55827
  if (code === 0 && stdout.trim()) {
55628
- log13.debug(`Quick query success: ${durationMs}ms, ${stdout.length} chars`);
55828
+ log14.debug(`Quick query success: ${durationMs}ms, ${stdout.length} chars`);
55629
55829
  resolve5({
55630
55830
  success: true,
55631
55831
  response: stdout.trim(),
55632
55832
  durationMs
55633
55833
  });
55634
55834
  } else {
55635
- log13.debug(`Quick query failed: code=${code}, stderr=${stderr.substring(0, 100)}`);
55835
+ log14.debug(`Quick query failed: code=${code}, stderr=${stderr.substring(0, 100)}`);
55636
55836
  resolve5({
55637
55837
  success: false,
55638
55838
  error: stderr || `exit code ${code}`,
@@ -55647,7 +55847,7 @@ async function quickQuery(options2) {
55647
55847
 
55648
55848
  // src/operations/suggestions/title.ts
55649
55849
  init_logger();
55650
- var log14 = createLogger("title");
55850
+ var log15 = createLogger("title");
55651
55851
  var SUGGESTION_TIMEOUT = 15000;
55652
55852
  var MIN_TITLE_LENGTH = 3;
55653
55853
  var MAX_TITLE_LENGTH = 50;
@@ -55711,32 +55911,32 @@ function parseMetadata(response) {
55711
55911
  const titleMatch = response.match(/TITLE:\s*(.+)/i);
55712
55912
  const descMatch = response.match(/DESC:\s*(.+)/i);
55713
55913
  if (!titleMatch || !descMatch) {
55714
- log14.debug("Failed to parse title/description from response");
55914
+ log15.debug("Failed to parse title/description from response");
55715
55915
  return null;
55716
55916
  }
55717
55917
  let title = titleMatch[1].trim();
55718
55918
  let description = descMatch[1].trim();
55719
55919
  if (title.length < MIN_TITLE_LENGTH) {
55720
- log14.debug(`Title too short: ${title.length} chars`);
55920
+ log15.debug(`Title too short: ${title.length} chars`);
55721
55921
  return null;
55722
55922
  }
55723
55923
  if (title.length > MAX_TITLE_LENGTH) {
55724
- log14.debug(`Title too long (${title.length} chars), truncating`);
55924
+ log15.debug(`Title too long (${title.length} chars), truncating`);
55725
55925
  title = truncateAtWord(title, MAX_TITLE_LENGTH);
55726
55926
  }
55727
55927
  if (description.length < MIN_DESC_LENGTH) {
55728
- log14.debug(`Description too short: ${description.length} chars`);
55928
+ log15.debug(`Description too short: ${description.length} chars`);
55729
55929
  return null;
55730
55930
  }
55731
55931
  if (description.length > MAX_DESC_LENGTH) {
55732
- log14.debug(`Description too long (${description.length} chars), truncating`);
55932
+ log15.debug(`Description too long (${description.length} chars), truncating`);
55733
55933
  description = truncateAtWord(description, MAX_DESC_LENGTH);
55734
55934
  }
55735
55935
  return { title, description };
55736
55936
  }
55737
55937
  async function suggestSessionMetadata(context) {
55738
55938
  const logContext = typeof context === "string" ? context.substring(0, 50) : context.originalTask.substring(0, 50);
55739
- log14.debug(`Suggesting title for: "${logContext}..."`);
55939
+ log15.debug(`Suggesting title for: "${logContext}..."`);
55740
55940
  try {
55741
55941
  const result = await quickQuery({
55742
55942
  prompt: buildTitlePrompt(context),
@@ -55744,23 +55944,23 @@ async function suggestSessionMetadata(context) {
55744
55944
  timeout: SUGGESTION_TIMEOUT
55745
55945
  });
55746
55946
  if (!result.success || !result.response) {
55747
- log14.debug(`Title suggestion failed: ${result.error || "no response"}`);
55947
+ log15.debug(`Title suggestion failed: ${result.error || "no response"}`);
55748
55948
  return null;
55749
55949
  }
55750
55950
  const metadata = parseMetadata(result.response);
55751
55951
  if (metadata) {
55752
- log14.debug(`Got title: "${metadata.title}" (${result.durationMs}ms)`);
55952
+ log15.debug(`Got title: "${metadata.title}" (${result.durationMs}ms)`);
55753
55953
  }
55754
55954
  return metadata;
55755
55955
  } catch (err) {
55756
- log14.debug(`Title suggestion error: ${err}`);
55956
+ log15.debug(`Title suggestion error: ${err}`);
55757
55957
  return null;
55758
55958
  }
55759
55959
  }
55760
55960
 
55761
55961
  // src/operations/suggestions/tag.ts
55762
55962
  init_logger();
55763
- var log15 = createLogger("tags");
55963
+ var log16 = createLogger("tags");
55764
55964
  var SUGGESTION_TIMEOUT2 = 15000;
55765
55965
  var MAX_TAGS = 3;
55766
55966
  var VALID_TAGS = [
@@ -55792,7 +55992,7 @@ function parseTags(response) {
55792
55992
  return [...new Set(tags)].slice(0, MAX_TAGS);
55793
55993
  }
55794
55994
  async function suggestSessionTags(userMessage) {
55795
- log15.debug(`Suggesting tags for: "${userMessage.substring(0, 50)}..."`);
55995
+ log16.debug(`Suggesting tags for: "${userMessage.substring(0, 50)}..."`);
55796
55996
  try {
55797
55997
  const result = await quickQuery({
55798
55998
  prompt: buildTagPrompt(userMessage),
@@ -55800,14 +56000,14 @@ async function suggestSessionTags(userMessage) {
55800
56000
  timeout: SUGGESTION_TIMEOUT2
55801
56001
  });
55802
56002
  if (!result.success || !result.response) {
55803
- log15.debug(`Tag suggestion failed: ${result.error || "no response"}`);
56003
+ log16.debug(`Tag suggestion failed: ${result.error || "no response"}`);
55804
56004
  return [];
55805
56005
  }
55806
56006
  const tags = parseTags(result.response);
55807
- log15.debug(`Got tags: ${tags.join(", ")} (${result.durationMs}ms)`);
56007
+ log16.debug(`Got tags: ${tags.join(", ")} (${result.durationMs}ms)`);
55808
56008
  return tags;
55809
56009
  } catch (err) {
55810
- log15.debug(`Tag suggestion error: ${err}`);
56010
+ log16.debug(`Tag suggestion error: ${err}`);
55811
56011
  return [];
55812
56012
  }
55813
56013
  }
@@ -59349,7 +59549,7 @@ class BugReportExecutor extends BaseExecutor {
59349
59549
  // src/operations/executors/worktree-prompt.ts
59350
59550
  init_emoji();
59351
59551
  init_logger();
59352
- var log16 = createLogger("wt-prompt");
59552
+ var log17 = createLogger("wt-prompt");
59353
59553
  // src/operations/message-manager.ts
59354
59554
  init_logger();
59355
59555
 
@@ -59386,7 +59586,7 @@ var import_yauzl = __toESM(require_yauzl(), 1);
59386
59586
  import { createGunzip } from "zlib";
59387
59587
  import { pipeline } from "stream/promises";
59388
59588
  import { Readable, Writable } from "stream";
59389
- var log17 = createLogger("streaming");
59589
+ var log18 = createLogger("streaming");
59390
59590
  var MAX_PDF_SIZE = 32 * 1024 * 1024;
59391
59591
  var MAX_TEXT_FILE_SIZE = 1 * 1024 * 1024;
59392
59592
  var MAX_DECOMPRESSED_SIZE = 10 * 1024 * 1024;
@@ -59512,7 +59712,7 @@ async function processImageFile(file, platform, debug = false) {
59512
59712
  const buffer = await platform.downloadFile(file.id);
59513
59713
  const base64 = buffer.toString("base64");
59514
59714
  if (debug) {
59515
- log17.debug(`Attached image: ${file.name} (${file.mimeType}, ${Math.round(buffer.length / 1024)}KB)`);
59715
+ log18.debug(`Attached image: ${file.name} (${file.mimeType}, ${Math.round(buffer.length / 1024)}KB)`);
59516
59716
  }
59517
59717
  return {
59518
59718
  block: {
@@ -59525,7 +59725,7 @@ async function processImageFile(file, platform, debug = false) {
59525
59725
  }
59526
59726
  };
59527
59727
  } catch (err) {
59528
- log17.error(`Failed to download image ${file.name}: ${err}`);
59728
+ log18.error(`Failed to download image ${file.name}: ${err}`);
59529
59729
  return {
59530
59730
  skipped: {
59531
59731
  name: file.name,
@@ -59556,7 +59756,7 @@ async function processPdfFile(file, platform, debug = false) {
59556
59756
  }
59557
59757
  const base64 = buffer.toString("base64");
59558
59758
  if (debug) {
59559
- log17.debug(`Attached PDF: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
59759
+ log18.debug(`Attached PDF: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
59560
59760
  }
59561
59761
  return {
59562
59762
  block: {
@@ -59570,7 +59770,7 @@ async function processPdfFile(file, platform, debug = false) {
59570
59770
  }
59571
59771
  };
59572
59772
  } catch (err) {
59573
- log17.error(`Failed to process PDF ${file.name}: ${err}`);
59773
+ log18.error(`Failed to process PDF ${file.name}: ${err}`);
59574
59774
  return {
59575
59775
  skipped: {
59576
59776
  name: file.name,
@@ -59601,7 +59801,7 @@ async function processTextFile(file, platform, debug = false) {
59601
59801
  }
59602
59802
  const content = buffer.toString("utf-8");
59603
59803
  if (debug) {
59604
- log17.debug(`Attached text file: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
59804
+ log18.debug(`Attached text file: ${file.name} (${Math.round(buffer.length / 1024)}KB)`);
59605
59805
  }
59606
59806
  const wrappedContent = formatTextFileContent(file.name, content);
59607
59807
  return {
@@ -59611,7 +59811,7 @@ async function processTextFile(file, platform, debug = false) {
59611
59811
  }
59612
59812
  };
59613
59813
  } catch (err) {
59614
- log17.error(`Failed to process text file ${file.name}: ${err}`);
59814
+ log18.error(`Failed to process text file ${file.name}: ${err}`);
59615
59815
  return {
59616
59816
  skipped: {
59617
59817
  name: file.name,
@@ -59669,7 +59869,7 @@ async function processGzipFile(file, platform, debug = false) {
59669
59869
  compressedBuffer = await platform.downloadFile(file.id);
59670
59870
  } catch (err) {
59671
59871
  const errorMessage = err instanceof Error ? err.message : String(err);
59672
- log17.error(`Failed to download gzip file ${file.name}: ${errorMessage}`);
59872
+ log18.error(`Failed to download gzip file ${file.name}: ${errorMessage}`);
59673
59873
  return {
59674
59874
  skipped: {
59675
59875
  name: file.name,
@@ -59679,7 +59879,7 @@ async function processGzipFile(file, platform, debug = false) {
59679
59879
  };
59680
59880
  }
59681
59881
  if (file.size && compressedBuffer.length !== file.size) {
59682
- log17.warn(`Downloaded size mismatch for ${file.name}: expected ${file.size}, got ${compressedBuffer.length}`);
59882
+ log18.warn(`Downloaded size mismatch for ${file.name}: expected ${file.size}, got ${compressedBuffer.length}`);
59683
59883
  }
59684
59884
  let decompressedBuffer;
59685
59885
  try {
@@ -59715,7 +59915,7 @@ async function processGzipFile(file, platform, debug = false) {
59715
59915
  const innerFilename = file.name.toLowerCase().endsWith(".gz") ? file.name.slice(0, -3) : file.name;
59716
59916
  const contentType = detectDecompressedContentType(decompressedBuffer, innerFilename);
59717
59917
  if (debug) {
59718
- log17.debug(`Decompressed ${file.name}: ${Math.round(decompressedBuffer.length / 1024)}KB, detected type: ${contentType}`);
59918
+ log18.debug(`Decompressed ${file.name}: ${Math.round(decompressedBuffer.length / 1024)}KB, detected type: ${contentType}`);
59719
59919
  }
59720
59920
  if (contentType === "pdf") {
59721
59921
  const base64 = decompressedBuffer.toString("base64");
@@ -59750,7 +59950,7 @@ async function processGzipFile(file, platform, debug = false) {
59750
59950
  }
59751
59951
  } catch (err) {
59752
59952
  const errorMessage = err instanceof Error ? err.message : String(err);
59753
- log17.error(`Failed to process gzip file ${file.name}: ${errorMessage}`);
59953
+ log18.error(`Failed to process gzip file ${file.name}: ${errorMessage}`);
59754
59954
  return {
59755
59955
  skipped: {
59756
59956
  name: file.name,
@@ -59802,7 +60002,7 @@ async function processZipFile(file, platform, debug = false) {
59802
60002
  }
59803
60003
  const zipBuffer = await platform.downloadFile(file.id);
59804
60004
  if (debug) {
59805
- log17.debug(`Processing zip file ${file.name}: ${Math.round(zipBuffer.length / 1024)}KB`);
60005
+ log18.debug(`Processing zip file ${file.name}: ${Math.round(zipBuffer.length / 1024)}KB`);
59806
60006
  }
59807
60007
  const zipfile = await new Promise((resolve5, reject) => {
59808
60008
  import_yauzl.default.fromBuffer(zipBuffer, { lazyEntries: true }, (err, zf) => {
@@ -59876,7 +60076,7 @@ async function processZipFile(file, platform, debug = false) {
59876
60076
  const buffer = await extractZipEntry(zipfile2, entry);
59877
60077
  const contentType = detectDecompressedContentType(buffer, entry.fileName);
59878
60078
  if (debug) {
59879
- log17.debug(`Extracted ${entry.fileName}: ${Math.round(buffer.length / 1024)}KB, type: ${contentType}`);
60079
+ log18.debug(`Extracted ${entry.fileName}: ${Math.round(buffer.length / 1024)}KB, type: ${contentType}`);
59880
60080
  }
59881
60081
  if (contentType === "pdf") {
59882
60082
  const base64 = buffer.toString("base64");
@@ -59919,11 +60119,11 @@ async function processZipFile(file, platform, debug = false) {
59919
60119
  });
59920
60120
  zipfile2.close();
59921
60121
  if (debug) {
59922
- log17.debug(`Zip ${file.name}: processed ${processedCount} files, skipped ${skipped.length}`);
60122
+ log18.debug(`Zip ${file.name}: processed ${processedCount} files, skipped ${skipped.length}`);
59923
60123
  }
59924
60124
  return { blocks, skipped };
59925
60125
  } catch (err) {
59926
- log17.error(`Failed to process zip file ${file.name}: ${err}`);
60126
+ log18.error(`Failed to process zip file ${file.name}: ${err}`);
59927
60127
  return {
59928
60128
  blocks: [],
59929
60129
  skipped: [{
@@ -60020,7 +60220,7 @@ async function processFiles(platform, files, debug = false) {
60020
60220
  blocks.push(...zipResult.blocks);
60021
60221
  for (const s of zipResult.skipped) {
60022
60222
  skipped.push(s);
60023
- log17.warn(`Skipped file ${s.name}: ${s.reason}`);
60223
+ log18.warn(`Skipped file ${s.name}: ${s.reason}`);
60024
60224
  }
60025
60225
  continue;
60026
60226
  }
@@ -60054,7 +60254,7 @@ async function processFiles(platform, files, debug = false) {
60054
60254
  }
60055
60255
  if (result.skipped) {
60056
60256
  skipped.push(result.skipped);
60057
- log17.warn(`Skipped file ${result.skipped.name}: ${result.skipped.reason}`);
60257
+ log18.warn(`Skipped file ${result.skipped.name}: ${result.skipped.reason}`);
60058
60258
  }
60059
60259
  }
60060
60260
  return { blocks, skipped };
@@ -60087,7 +60287,7 @@ function stopTyping(session) {
60087
60287
  }
60088
60288
 
60089
60289
  // src/operations/message-manager.ts
60090
- var log18 = createLogger("msg-mgr");
60290
+ var log19 = createLogger("msg-mgr");
60091
60291
 
60092
60292
  class MessageManager {
60093
60293
  platform;
@@ -60175,7 +60375,7 @@ class MessageManager {
60175
60375
  });
60176
60376
  }
60177
60377
  async handleEvent(event) {
60178
- const logger = log18.forSession(this.sessionId);
60378
+ const logger = log19.forSession(this.sessionId);
60179
60379
  const transformCtx = {
60180
60380
  sessionId: this.sessionId,
60181
60381
  formatter: this.platform.getFormatter(),
@@ -60225,7 +60425,7 @@ class MessageManager {
60225
60425
  }
60226
60426
  }
60227
60427
  async executeOperation(op) {
60228
- const logger = log18.forSession(this.sessionId);
60428
+ const logger = log19.forSession(this.sessionId);
60229
60429
  const ctx = this.getExecutorContext();
60230
60430
  try {
60231
60431
  if (isContentOp(op)) {
@@ -60293,7 +60493,7 @@ class MessageManager {
60293
60493
  threadId: this.threadId,
60294
60494
  platform: this.platform,
60295
60495
  formatter: this.platform.getFormatter(),
60296
- logger: log18.forSession(this.sessionId),
60496
+ logger: log19.forSession(this.sessionId),
60297
60497
  postTracker: this.postTracker,
60298
60498
  contentBreaker: this.contentBreaker,
60299
60499
  threadLogger: this.session.threadLogger,
@@ -60504,13 +60704,13 @@ class MessageManager {
60504
60704
  return this.systemExecutor.postSuccess(message, this.getExecutorContext());
60505
60705
  }
60506
60706
  async prepareForUserMessage() {
60507
- const logger = log18.forSession(this.sessionId);
60707
+ const logger = log19.forSession(this.sessionId);
60508
60708
  logger.debug("Preparing for new user message");
60509
60709
  await this.closeCurrentPost();
60510
60710
  await this.bumpTaskList();
60511
60711
  }
60512
60712
  async handleUserMessage(message, files, username, displayName) {
60513
- const logger = log18.forSession(this.sessionId);
60713
+ const logger = log19.forSession(this.sessionId);
60514
60714
  if (!this.session.claude.isRunning()) {
60515
60715
  logger.debug("Claude not running, ignoring user message");
60516
60716
  return false;
@@ -60537,7 +60737,7 @@ class MessageManager {
60537
60737
  return this.session;
60538
60738
  }
60539
60739
  async handleReaction(postId, emoji, user, action) {
60540
- const logger = log18.forSession(this.sessionId);
60740
+ const logger = log19.forSession(this.sessionId);
60541
60741
  const ctx = this.getExecutorContext();
60542
60742
  logger.debug(`Routing reaction: postId=${postId}, emoji=${emoji}, user=${user}, action=${action}`);
60543
60743
  if (await this.questionApprovalExecutor.handleReaction(postId, emoji, user, action, ctx)) {
@@ -60733,7 +60933,7 @@ function formatPullRequestLink(url, formatter) {
60733
60933
  }
60734
60934
 
60735
60935
  // src/operations/sticky-message/handler.ts
60736
- var log19 = createLogger("sticky");
60936
+ var log20 = createLogger("sticky");
60737
60937
  var botStartedAt = new Date;
60738
60938
  function getPendingPrompts(session) {
60739
60939
  const prompts2 = [];
@@ -60808,21 +61008,21 @@ function initialize(store) {
60808
61008
  stickyPostIds.set(platformId, postId);
60809
61009
  }
60810
61010
  if (persistedIds.size > 0) {
60811
- log19.info(`\uD83D\uDCCC Restored ${persistedIds.size} sticky post ID(s) from persistence`);
61011
+ log20.info(`\uD83D\uDCCC Restored ${persistedIds.size} sticky post ID(s) from persistence`);
60812
61012
  }
60813
61013
  }
60814
61014
  function setPlatformPaused(platformId, paused) {
60815
61015
  if (paused) {
60816
61016
  pausedPlatforms.set(platformId, true);
60817
- log19.debug(`Platform ${platformId} marked as paused`);
61017
+ log20.debug(`Platform ${platformId} marked as paused`);
60818
61018
  } else {
60819
61019
  pausedPlatforms.delete(platformId);
60820
- log19.debug(`Platform ${platformId} marked as active`);
61020
+ log20.debug(`Platform ${platformId} marked as active`);
60821
61021
  }
60822
61022
  }
60823
61023
  function setShuttingDown(shuttingDown) {
60824
61024
  isShuttingDown = shuttingDown;
60825
- log19.debug(`Bot shutdown state: ${shuttingDown}`);
61025
+ log20.debug(`Bot shutdown state: ${shuttingDown}`);
60826
61026
  }
60827
61027
  function getTaskContent(session) {
60828
61028
  const taskState = session.messageManager?.getTaskListState();
@@ -60919,6 +61119,13 @@ async function buildStatusBar(sessionCount, config, formatter, platformId) {
60919
61119
  }
60920
61120
  items.push(formatter.formatCode(formatVersionString()));
60921
61121
  items.push(formatter.formatCode(`${sessionCount}/${config.maxSessions} sessions`));
61122
+ if (config.accountPoolStatus && config.accountPoolStatus.length > 0) {
61123
+ const total = config.accountPoolStatus.length;
61124
+ const cooling = config.accountPoolStatus.filter((a) => a.coolingUntil !== null).length;
61125
+ const available = total - cooling;
61126
+ const label = cooling > 0 ? `\uD83D\uDD11 ${available}/${total} accounts (${cooling} cooling)` : `\uD83D\uDD11 ${total} account${total === 1 ? "" : "s"}`;
61127
+ items.push(formatter.formatCode(label));
61128
+ }
60922
61129
  const permMode = config.skipPermissions ? "⚡ Auto" : "\uD83D\uDD10 Interactive";
60923
61130
  items.push(formatter.formatCode(permMode));
60924
61131
  if (config.worktreeMode === "require") {
@@ -61127,12 +61334,12 @@ async function validateLastMessageIds(platform, sessions) {
61127
61334
  try {
61128
61335
  const post2 = await platform.getPost(lastMessageId);
61129
61336
  if (!post2) {
61130
- log19.debug(`lastMessageId ${lastMessageId.substring(0, 8)} for session ${session.sessionId} was deleted, clearing`);
61337
+ log20.debug(`lastMessageId ${lastMessageId.substring(0, 8)} for session ${session.sessionId} was deleted, clearing`);
61131
61338
  session.lastMessageId = undefined;
61132
61339
  session.lastMessageTs = undefined;
61133
61340
  }
61134
61341
  } catch (err) {
61135
- log19.debug(`Failed to validate lastMessageId for session ${session.sessionId}, clearing: ${err}`);
61342
+ log20.debug(`Failed to validate lastMessageId for session ${session.sessionId}, clearing: ${err}`);
61136
61343
  session.lastMessageId = undefined;
61137
61344
  session.lastMessageTs = undefined;
61138
61345
  }
@@ -61141,63 +61348,63 @@ async function validateLastMessageIds(platform, sessions) {
61141
61348
  }
61142
61349
  async function updateStickyMessageImpl(platform, sessions, config) {
61143
61350
  const platformSessions = [...sessions.values()].filter((s) => s.platformId === platform.platformId);
61144
- log19.debug(`updateStickyMessage for ${platform.platformId}, ${platformSessions.length} sessions`);
61351
+ log20.debug(`updateStickyMessage for ${platform.platformId}, ${platformSessions.length} sessions`);
61145
61352
  for (const s of platformSessions) {
61146
- log19.debug(` - ${s.sessionId}: title="${s.sessionTitle}" firstPrompt="${s.firstPrompt?.substring(0, 30)}..."`);
61353
+ log20.debug(` - ${s.sessionId}: title="${s.sessionTitle}" firstPrompt="${s.firstPrompt?.substring(0, 30)}..."`);
61147
61354
  }
61148
61355
  await validateLastMessageIds(platform, platformSessions);
61149
61356
  const formatter = platform.getFormatter();
61150
61357
  const content = await buildStickyMessage(sessions, platform.platformId, config, formatter, (threadId) => platform.getThreadLink(threadId));
61151
61358
  const existingPostId = stickyPostIds.get(platform.platformId);
61152
61359
  const shouldBump = needsBump.get(platform.platformId) ?? false;
61153
- log19.debug(`existingPostId: ${existingPostId || "(none)"}, needsBump: ${shouldBump}`);
61360
+ log20.debug(`existingPostId: ${existingPostId || "(none)"}, needsBump: ${shouldBump}`);
61154
61361
  try {
61155
61362
  if (existingPostId && !shouldBump) {
61156
- log19.debug(`Updating existing post in place...`);
61363
+ log20.debug(`Updating existing post in place...`);
61157
61364
  try {
61158
61365
  await platform.updatePost(existingPostId, content);
61159
61366
  try {
61160
61367
  await platform.pinPost(existingPostId);
61161
- log19.debug(`Re-pinned post`);
61368
+ log20.debug(`Re-pinned post`);
61162
61369
  } catch (pinErr) {
61163
- log19.debug(`Re-pin failed (might already be pinned): ${pinErr}`);
61370
+ log20.debug(`Re-pin failed (might already be pinned): ${pinErr}`);
61164
61371
  }
61165
- log19.debug(`Updated successfully`);
61372
+ log20.debug(`Updated successfully`);
61166
61373
  return;
61167
61374
  } catch (err) {
61168
- log19.debug(`Update failed, will create new: ${err}`);
61375
+ log20.debug(`Update failed, will create new: ${err}`);
61169
61376
  }
61170
61377
  }
61171
61378
  needsBump.set(platform.platformId, false);
61172
61379
  if (existingPostId) {
61173
- log19.debug(`Unpinning and deleting existing post ${existingPostId.substring(0, 8)}...`);
61380
+ log20.debug(`Unpinning and deleting existing post ${existingPostId.substring(0, 8)}...`);
61174
61381
  try {
61175
61382
  await platform.unpinPost(existingPostId);
61176
- log19.debug(`Unpinned successfully`);
61383
+ log20.debug(`Unpinned successfully`);
61177
61384
  } catch (err) {
61178
- log19.debug(`Unpin failed (probably already unpinned): ${err}`);
61385
+ log20.debug(`Unpin failed (probably already unpinned): ${err}`);
61179
61386
  }
61180
61387
  try {
61181
61388
  await platform.deletePost(existingPostId);
61182
- log19.debug(`Deleted successfully`);
61389
+ log20.debug(`Deleted successfully`);
61183
61390
  } catch (err) {
61184
- log19.debug(`Delete failed (probably already deleted): ${err}`);
61391
+ log20.debug(`Delete failed (probably already deleted): ${err}`);
61185
61392
  }
61186
61393
  stickyPostIds.delete(platform.platformId);
61187
61394
  }
61188
- log19.debug(`Creating new post...`);
61395
+ log20.debug(`Creating new post...`);
61189
61396
  const post2 = await platform.createPost(content);
61190
61397
  stickyPostIds.set(platform.platformId, post2.id);
61191
61398
  try {
61192
61399
  await platform.pinPost(post2.id);
61193
- log19.debug(`Pinned post successfully`);
61400
+ log20.debug(`Pinned post successfully`);
61194
61401
  } catch (err) {
61195
- log19.debug(`Failed to pin post: ${err}`);
61402
+ log20.debug(`Failed to pin post: ${err}`);
61196
61403
  }
61197
61404
  if (sessionStore) {
61198
61405
  sessionStore.saveStickyPostId(platform.platformId, post2.id);
61199
61406
  }
61200
- log19.info(`\uD83D\uDCCC Created sticky message for ${platform.platformId}: ${formatShortId(post2.id)}`);
61407
+ log20.info(`\uD83D\uDCCC Created sticky message for ${platform.platformId}: ${formatShortId(post2.id)}`);
61201
61408
  const excludePostIds = new Set;
61202
61409
  if (sessionStore) {
61203
61410
  for (const session of sessionStore.load().values()) {
@@ -61213,10 +61420,10 @@ async function updateStickyMessageImpl(platform, sessions, config) {
61213
61420
  }
61214
61421
  const botUser = await platform.getBotUser();
61215
61422
  cleanupOldStickyMessages(platform, botUser.id, false, excludePostIds).catch((err) => {
61216
- log19.debug(`Background cleanup failed: ${err}`);
61423
+ log20.debug(`Background cleanup failed: ${err}`);
61217
61424
  });
61218
61425
  } catch (err) {
61219
- log19.error(`Failed to update sticky message for ${platform.platformId}`, err instanceof Error ? err : undefined);
61426
+ log20.error(`Failed to update sticky message for ${platform.platformId}`, err instanceof Error ? err : undefined);
61220
61427
  }
61221
61428
  }
61222
61429
  async function updateAllStickyMessages(platforms, sessions, config) {
@@ -61241,7 +61448,7 @@ async function cleanupOldStickyMessages(platform, botUserId, forceRun = false, e
61241
61448
  if (!forceRun) {
61242
61449
  const lastRun = lastCleanupTime.get(platformId) || 0;
61243
61450
  if (now - lastRun < CLEANUP_THROTTLE_MS) {
61244
- log19.debug(`Cleanup throttled for ${platformId} (last run ${Math.round((now - lastRun) / 1000)}s ago)`);
61451
+ log20.debug(`Cleanup throttled for ${platformId} (last run ${Math.round((now - lastRun) / 1000)}s ago)`);
61245
61452
  return;
61246
61453
  }
61247
61454
  }
@@ -61251,31 +61458,31 @@ async function cleanupOldStickyMessages(platform, botUserId, forceRun = false, e
61251
61458
  const pinnedPostIds = await platform.getPinnedPosts();
61252
61459
  const recentPinnedIds = pinnedPostIds.filter((id) => id !== currentStickyId && !excludePostIds?.has(id) && isRecentPost(id));
61253
61460
  if (recentPinnedIds.length === 0) {
61254
- log19.debug(`No recent pinned posts to check (${pinnedPostIds.length} total, current: ${currentStickyId?.substring(0, 8) || "(none)"})`);
61461
+ log20.debug(`No recent pinned posts to check (${pinnedPostIds.length} total, current: ${currentStickyId?.substring(0, 8) || "(none)"})`);
61255
61462
  return;
61256
61463
  }
61257
- log19.debug(`Checking ${recentPinnedIds.length} recent pinned posts (of ${pinnedPostIds.length} total)`);
61464
+ log20.debug(`Checking ${recentPinnedIds.length} recent pinned posts (of ${pinnedPostIds.length} total)`);
61258
61465
  for (const postId of recentPinnedIds) {
61259
61466
  try {
61260
61467
  const post2 = await platform.getPost(postId);
61261
61468
  if (!post2)
61262
61469
  continue;
61263
61470
  if (post2.userId === botUserId) {
61264
- log19.debug(`Cleaning up old sticky: ${postId.substring(0, 8)}...`);
61471
+ log20.debug(`Cleaning up old sticky: ${postId.substring(0, 8)}...`);
61265
61472
  try {
61266
61473
  await platform.unpinPost(postId);
61267
61474
  await platform.deletePost(postId);
61268
- log19.info(`\uD83E\uDDF9 Cleaned up old sticky message: ${postId.substring(0, 8)}...`);
61475
+ log20.info(`\uD83E\uDDF9 Cleaned up old sticky message: ${postId.substring(0, 8)}...`);
61269
61476
  } catch (err) {
61270
- log19.debug(`Failed to cleanup ${postId}: ${err}`);
61477
+ log20.debug(`Failed to cleanup ${postId}: ${err}`);
61271
61478
  }
61272
61479
  }
61273
61480
  } catch (err) {
61274
- log19.debug(`Could not check post ${postId}: ${err}`);
61481
+ log20.debug(`Could not check post ${postId}: ${err}`);
61275
61482
  }
61276
61483
  }
61277
61484
  } catch (err) {
61278
- log19.error(`Failed to cleanup old sticky messages`, err instanceof Error ? err : undefined);
61485
+ log20.error(`Failed to cleanup old sticky messages`, err instanceof Error ? err : undefined);
61279
61486
  }
61280
61487
  }
61281
61488
  // src/operations/bug-report/handler.ts
@@ -65338,8 +65545,16 @@ function getUpdateInfo() {
65338
65545
  init_emoji();
65339
65546
  init_logger();
65340
65547
  init_worktree();
65341
- var log20 = createLogger("commands");
65342
- var sessionLog2 = createSessionLog(log20);
65548
+ var log21 = createLogger("commands");
65549
+ var sessionLog2 = createSessionLog(log21);
65550
+ function sessionAccountOption(session, ctx) {
65551
+ if (!session.claudeAccountId)
65552
+ return;
65553
+ const account = ctx.ops.getClaudeAccount(session.claudeAccountId);
65554
+ if (!account)
65555
+ return;
65556
+ return { id: account.id, home: account.home, apiKey: account.apiKey };
65557
+ }
65343
65558
  async function restartClaudeSession(session, cliOptions, ctx, actionName) {
65344
65559
  ctx.ops.stopTyping(session);
65345
65560
  transitionTo(session, "restarting");
@@ -65348,6 +65563,7 @@ async function restartClaudeSession(session, cliOptions, ctx, actionName) {
65348
65563
  session.claude = new ClaudeCli(cliOptions);
65349
65564
  session.claude.on("event", (e) => ctx.ops.handleEvent(session.sessionId, e));
65350
65565
  session.claude.on("exit", (code) => ctx.ops.handleExit(session.sessionId, code));
65566
+ session.claude.on("rate-limit", (hit) => handleRateLimit(session, hit, ctx));
65351
65567
  try {
65352
65568
  session.claude.start();
65353
65569
  return true;
@@ -65500,7 +65716,8 @@ ${CHAT_PLATFORM_PROMPT}`;
65500
65716
  platformConfig: session.platform.getMcpConfig(),
65501
65717
  appendSystemPrompt,
65502
65718
  logSessionId: session.sessionId,
65503
- permissionTimeoutMs: ctx.config.permissionTimeoutMs
65719
+ permissionTimeoutMs: ctx.config.permissionTimeoutMs,
65720
+ account: sessionAccountOption(session, ctx)
65504
65721
  };
65505
65722
  const success = await restartClaudeSession(session, cliOptions, ctx, "Restart Claude for directory change");
65506
65723
  if (!success)
@@ -65595,7 +65812,8 @@ async function enableInteractivePermissions(session, username, ctx) {
65595
65812
  chrome: ctx.config.chromeEnabled,
65596
65813
  platformConfig: session.platform.getMcpConfig(),
65597
65814
  logSessionId: session.sessionId,
65598
- permissionTimeoutMs: ctx.config.permissionTimeoutMs
65815
+ permissionTimeoutMs: ctx.config.permissionTimeoutMs,
65816
+ account: sessionAccountOption(session, ctx)
65599
65817
  };
65600
65818
  const success = await restartClaudeSession(session, cliOptions, ctx, "Enable interactive permissions");
65601
65819
  if (!success)
@@ -65701,6 +65919,11 @@ async function updateSessionHeader(session, ctx) {
65701
65919
  if (otherParticipants) {
65702
65920
  items.push(["\uD83D\uDC65", "Participants", otherParticipants]);
65703
65921
  }
65922
+ if (session.claudeAccountId) {
65923
+ const account = ctx.ops.getClaudeAccount(session.claudeAccountId);
65924
+ const label = account?.displayName ?? session.claudeAccountId;
65925
+ items.push(["\uD83D\uDD11", "Claude account", formatter.formatCode(label)]);
65926
+ }
65704
65927
  items.push(["\uD83C\uDD94", "Session ID", formatter.formatCode(session.claudeSessionId.substring(0, 8))]);
65705
65928
  const logPath = getLogFilePath(session.platform.platformId, session.claudeSessionId);
65706
65929
  const shortLogPath = logPath.replace(process.env.HOME || "", "~");
@@ -65857,7 +66080,7 @@ init_logger();
65857
66080
  import { exec as exec3 } from "child_process";
65858
66081
  import { promisify as promisify3 } from "util";
65859
66082
  var execAsync2 = promisify3(exec3);
65860
- var log21 = createLogger("branch");
66083
+ var log22 = createLogger("branch");
65861
66084
  var SUGGESTION_TIMEOUT3 = 15000;
65862
66085
  var MAX_SUGGESTIONS = 3;
65863
66086
  async function getCurrentBranch3(workingDir) {
@@ -65906,7 +66129,7 @@ function parseBranchSuggestions(response) {
65906
66129
  return lines.slice(0, MAX_SUGGESTIONS);
65907
66130
  }
65908
66131
  async function suggestBranchNames(workingDir, userMessage) {
65909
- log21.debug(`Suggesting branch names for: "${userMessage.substring(0, 50)}..."`);
66132
+ log22.debug(`Suggesting branch names for: "${userMessage.substring(0, 50)}..."`);
65910
66133
  try {
65911
66134
  const [currentBranch, recentCommits] = await Promise.all([
65912
66135
  getCurrentBranch3(workingDir),
@@ -65920,14 +66143,14 @@ async function suggestBranchNames(workingDir, userMessage) {
65920
66143
  workingDir
65921
66144
  });
65922
66145
  if (!result.success || !result.response) {
65923
- log21.debug(`Branch suggestion failed: ${result.error || "no response"}`);
66146
+ log22.debug(`Branch suggestion failed: ${result.error || "no response"}`);
65924
66147
  return [];
65925
66148
  }
65926
66149
  const suggestions = parseBranchSuggestions(result.response);
65927
- log21.debug(`Got ${suggestions.length} branch suggestions: ${suggestions.join(", ")}`);
66150
+ log22.debug(`Got ${suggestions.length} branch suggestions: ${suggestions.join(", ")}`);
65928
66151
  return suggestions;
65929
66152
  } catch (err) {
65930
- log21.debug(`Branch suggestion error: ${err}`);
66153
+ log22.debug(`Branch suggestion error: ${err}`);
65931
66154
  return [];
65932
66155
  }
65933
66156
  }
@@ -65936,8 +66159,8 @@ async function suggestBranchNames(workingDir, userMessage) {
65936
66159
  init_worktree();
65937
66160
  import { randomUUID as randomUUID3 } from "crypto";
65938
66161
  init_logger();
65939
- var log22 = createLogger("worktree");
65940
- var sessionLog3 = createSessionLog(log22);
66162
+ var log23 = createLogger("worktree");
66163
+ var sessionLog3 = createSessionLog(log23);
65941
66164
  function parseWorktreeError(error) {
65942
66165
  const message = error instanceof Error ? error.message : String(error);
65943
66166
  const lowerMessage = message.toLowerCase();
@@ -66488,8 +66711,8 @@ async function cleanupWorktreeCommand(session, username, hasOtherSessionsUsingWo
66488
66711
  }
66489
66712
  // src/operations/events/handler.ts
66490
66713
  init_logger();
66491
- var log23 = createLogger("events");
66492
- var sessionLog4 = createSessionLog(log23);
66714
+ var log24 = createLogger("events");
66715
+ var sessionLog4 = createSessionLog(log24);
66493
66716
  function detectAndExecuteClaudeCommands(text, session, ctx) {
66494
66717
  const parsed = parseClaudeCommand(text);
66495
66718
  if (parsed && isClaudeAllowedCommand(parsed.command)) {
@@ -66737,8 +66960,8 @@ function createSessionContext(config, state, ops) {
66737
66960
  // src/operations/context-prompt/handler.ts
66738
66961
  init_emoji();
66739
66962
  init_logger();
66740
- var log24 = createLogger("context");
66741
- var sessionLog5 = createSessionLog(log24);
66963
+ var log25 = createLogger("context");
66964
+ var sessionLog5 = createSessionLog(log25);
66742
66965
  var CONTEXT_PROMPT_TIMEOUT_MS = 30000;
66743
66966
  var CONTEXT_OPTIONS = [3, 5, 10];
66744
66967
  var contextPromptTimeouts = new Map;
@@ -66988,8 +67211,8 @@ function formatRelativeTime(date) {
66988
67211
  }
66989
67212
  // src/session/lifecycle.ts
66990
67213
  init_worktree();
66991
- var log25 = createLogger("lifecycle");
66992
- var sessionLog6 = createSessionLog(log25);
67214
+ var log26 = createLogger("lifecycle");
67215
+ var sessionLog6 = createSessionLog(log26);
66993
67216
  function mutableSessions(ctx) {
66994
67217
  return ctx.state.sessions;
66995
67218
  }
@@ -67037,12 +67260,31 @@ async function cleanupSession(session, ctx, options2 = {}) {
67037
67260
  cleanupPostIndex(ctx, session.threadId);
67038
67261
  }
67039
67262
  keepAlive.sessionEnded();
67263
+ releaseAccountIfHeld(session, ctx);
67264
+ }
67265
+ function releaseAccountIfHeld(session, ctx) {
67266
+ if (session.claudeAccountId) {
67267
+ ctx.ops.releaseClaudeAccount(session.claudeAccountId);
67268
+ session.claudeAccountId = undefined;
67269
+ }
67040
67270
  }
67041
67271
  function removeFromRegistry(session, ctx) {
67042
67272
  ctx.ops.emitSessionRemove(session.sessionId);
67043
67273
  mutableSessions(ctx).delete(session.sessionId);
67044
67274
  cleanupPostIndex(ctx, session.threadId);
67045
67275
  keepAlive.sessionEnded();
67276
+ releaseAccountIfHeld(session, ctx);
67277
+ }
67278
+ function handleRateLimit(session, hit, ctx) {
67279
+ if (!session.claudeAccountId) {
67280
+ sessionLog6(session).warn(`Rate limit hit in single-account mode — cannot reroute`);
67281
+ return;
67282
+ }
67283
+ const deadline = cooldownDeadline(hit);
67284
+ ctx.ops.markClaudeAccountCooling(session.claudeAccountId, deadline);
67285
+ const minutes = Math.max(1, Math.ceil((deadline - Date.now()) / 60000));
67286
+ sessionLog6(session).warn(`Rate limit on account "${session.claudeAccountId}" — cooling for ~${minutes}min`);
67287
+ post(session, "warning", `⚠️ Claude account \`${session.claudeAccountId}\` hit a rate limit. ` + `New sessions will use another account until it resets (~${minutes}min).`);
67046
67288
  }
67047
67289
  function findPersistedByThreadId(persisted, threadId) {
67048
67290
  for (const session of persisted.values()) {
@@ -67342,18 +67584,22 @@ async function startSession(options2, username, displayName, replyToPostId, plat
67342
67584
  return;
67343
67585
  }
67344
67586
  workingDir = resolvedDir;
67345
- log25.info(`Starting session in directory: ${workingDir} (from !cd command)`);
67587
+ log26.info(`Starting session in directory: ${workingDir} (from !cd command)`);
67346
67588
  }
67347
67589
  if (initialOptions?.forceInteractivePermissions) {
67348
67590
  forceInteractivePermissions = true;
67349
67591
  skipPermissions = false;
67350
- log25.info(`Starting session with interactive permissions (from !permissions command)`);
67592
+ log26.info(`Starting session with interactive permissions (from !permissions command)`);
67351
67593
  }
67352
67594
  const sessionContext = buildSessionContext(platform, workingDir);
67353
67595
  const systemPrompt = `${sessionContext}
67354
67596
 
67355
67597
  ${CHAT_PLATFORM_PROMPT}`;
67356
67598
  const platformMcpConfig = platform.getMcpConfig();
67599
+ const claudeAccount = ctx.ops.acquireClaudeAccount();
67600
+ if (claudeAccount) {
67601
+ log26.info(`Session ${sessionId.substring(0, 20)} reserved Claude account "${claudeAccount.id}"`);
67602
+ }
67357
67603
  const cliOptions = {
67358
67604
  workingDir,
67359
67605
  threadId: actualThreadId,
@@ -67364,7 +67610,8 @@ ${CHAT_PLATFORM_PROMPT}`;
67364
67610
  platformConfig: platformMcpConfig,
67365
67611
  appendSystemPrompt: systemPrompt,
67366
67612
  logSessionId: sessionId,
67367
- permissionTimeoutMs: ctx.config.permissionTimeoutMs
67613
+ permissionTimeoutMs: ctx.config.permissionTimeoutMs,
67614
+ account: claudeAccount ? { id: claudeAccount.id, home: claudeAccount.home, apiKey: claudeAccount.apiKey } : undefined
67368
67615
  };
67369
67616
  const claude = new ClaudeCli(cliOptions);
67370
67617
  const session = {
@@ -67373,6 +67620,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67373
67620
  sessionId,
67374
67621
  platform,
67375
67622
  claudeSessionId,
67623
+ claudeAccountId: claudeAccount?.id,
67376
67624
  startedBy: username,
67377
67625
  startedByDisplayName: displayName,
67378
67626
  startedAt: new Date,
@@ -67411,6 +67659,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67411
67659
  ctx.ops.startTyping(session);
67412
67660
  claude.on("event", (e) => ctx.ops.handleEvent(sessionId, e));
67413
67661
  claude.on("exit", (code) => ctx.ops.handleExit(sessionId, code));
67662
+ claude.on("rate-limit", (hit) => handleRateLimit(session, hit, ctx));
67414
67663
  try {
67415
67664
  claude.start();
67416
67665
  } catch (err) {
@@ -67418,6 +67667,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67418
67667
  ctx.ops.stopTyping(session);
67419
67668
  ctx.ops.emitSessionRemove(session.sessionId);
67420
67669
  mutableSessions(ctx).delete(session.sessionId);
67670
+ releaseAccountIfHeld(session, ctx);
67421
67671
  await ctx.ops.updateStickyMessage();
67422
67672
  return;
67423
67673
  }
@@ -67453,28 +67703,28 @@ async function resumeSession(state, ctx) {
67453
67703
  !state.claudeSessionId && "claudeSessionId",
67454
67704
  !state.workingDir && "workingDir"
67455
67705
  ].filter(Boolean).join(", ");
67456
- log25.warn(`Skipping session with missing required fields: ${missing}`);
67706
+ log26.warn(`Skipping session with missing required fields: ${missing}`);
67457
67707
  return;
67458
67708
  }
67459
67709
  const shortId = state.threadId.substring(0, 8);
67460
67710
  const platforms = ctx.state.platforms;
67461
67711
  const platform = platforms.get(state.platformId);
67462
67712
  if (!platform) {
67463
- log25.warn(`Platform ${state.platformId} not registered, skipping resume for ${shortId}...`);
67713
+ log26.warn(`Platform ${state.platformId} not registered, skipping resume for ${shortId}...`);
67464
67714
  return;
67465
67715
  }
67466
67716
  const threadPost = await platform.getPost(state.threadId);
67467
67717
  if (!threadPost) {
67468
- log25.warn(`Thread ${shortId}... deleted, skipping resume`);
67718
+ log26.warn(`Thread ${shortId}... deleted, skipping resume`);
67469
67719
  ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
67470
67720
  return;
67471
67721
  }
67472
67722
  if (ctx.state.sessions.size >= ctx.config.maxSessions) {
67473
- log25.warn(`Max sessions reached, skipping resume for ${shortId}...`);
67723
+ log26.warn(`Max sessions reached, skipping resume for ${shortId}...`);
67474
67724
  return;
67475
67725
  }
67476
67726
  if (!existsSync11(state.workingDir)) {
67477
- log25.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
67727
+ log26.warn(`Working directory ${state.workingDir} no longer exists, skipping resume for ${shortId}...`);
67478
67728
  ctx.state.sessionStore.remove(`${state.platformId}:${state.threadId}`);
67479
67729
  const resumeFormatter = platform.getFormatter();
67480
67730
  const tempSession = {
@@ -67496,6 +67746,10 @@ Please start a new session.`), { action: "Post resume failure notification" });
67496
67746
  const appendSystemPrompt = `${sessionContext}
67497
67747
 
67498
67748
  ${CHAT_PLATFORM_PROMPT}`;
67749
+ const claudeAccount = ctx.ops.acquireClaudeAccount(state.claudeAccountId);
67750
+ if (state.claudeAccountId && !claudeAccount) {
67751
+ log26.warn(`Persisted session referenced Claude account "${state.claudeAccountId}" ` + `which is no longer configured — resuming under default env`);
67752
+ }
67499
67753
  const cliOptions = {
67500
67754
  workingDir: state.workingDir,
67501
67755
  threadId: state.threadId,
@@ -67506,7 +67760,8 @@ ${CHAT_PLATFORM_PROMPT}`;
67506
67760
  platformConfig: platformMcpConfig,
67507
67761
  appendSystemPrompt,
67508
67762
  logSessionId: sessionId,
67509
- permissionTimeoutMs: ctx.config.permissionTimeoutMs
67763
+ permissionTimeoutMs: ctx.config.permissionTimeoutMs,
67764
+ account: claudeAccount ? { id: claudeAccount.id, home: claudeAccount.home, apiKey: claudeAccount.apiKey } : undefined
67510
67765
  };
67511
67766
  const claude = new ClaudeCli(cliOptions);
67512
67767
  const session = {
@@ -67515,6 +67770,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67515
67770
  sessionId,
67516
67771
  platform,
67517
67772
  claudeSessionId: state.claudeSessionId,
67773
+ claudeAccountId: claudeAccount?.id,
67518
67774
  startedBy: state.startedBy,
67519
67775
  startedByDisplayName: state.startedByDisplayName,
67520
67776
  startedAt: new Date(state.startedAt),
@@ -67557,7 +67813,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67557
67813
  worktreePath: detected.worktreePath,
67558
67814
  branch: detected.branch
67559
67815
  };
67560
- log25.info(`Auto-detected worktree info for resumed session: branch=${detected.branch}`);
67816
+ log26.info(`Auto-detected worktree info for resumed session: branch=${detected.branch}`);
67561
67817
  }
67562
67818
  }
67563
67819
  session.messageManager = createMessageManager(session, ctx);
@@ -67592,6 +67848,7 @@ ${CHAT_PLATFORM_PROMPT}`;
67592
67848
  keepAlive.sessionStarted();
67593
67849
  claude.on("event", (e) => ctx.ops.handleEvent(sessionId, e));
67594
67850
  claude.on("exit", (code) => ctx.ops.handleExit(sessionId, code));
67851
+ claude.on("rate-limit", (hit) => handleRateLimit(session, hit, ctx));
67595
67852
  try {
67596
67853
  claude.start();
67597
67854
  sessionLog6(session).info(`\uD83D\uDD04 Session resumed (@${state.startedBy})`);
@@ -67612,10 +67869,11 @@ ${sessionFormatter.formatItalic("Reconnected to Claude session. You can continue
67612
67869
  await ctx.ops.updateStickyMessage();
67613
67870
  ctx.ops.persistSession(session);
67614
67871
  } catch (err) {
67615
- log25.error(`Failed to resume session ${shortId}`, err instanceof Error ? err : undefined);
67872
+ log26.error(`Failed to resume session ${shortId}`, err instanceof Error ? err : undefined);
67616
67873
  ctx.ops.emitSessionRemove(sessionId);
67617
67874
  mutableSessions(ctx).delete(sessionId);
67618
67875
  ctx.state.sessionStore.remove(sessionId);
67876
+ releaseAccountIfHeld(session, ctx);
67619
67877
  const failFormatter = session.platform.getFormatter();
67620
67878
  await withErrorHandling(() => post(session, "warning", `${failFormatter.formatBold("Could not resume previous session.")} Starting fresh.
67621
67879
  ${failFormatter.formatItalic("Your previous conversation context is preserved, but Claude needs to re-read it.")}`), { action: "Post resume failure notification", session });
@@ -67651,18 +67909,18 @@ async function resumePausedSession(threadId, message, files, ctx) {
67651
67909
  const persisted = ctx.state.sessionStore.load();
67652
67910
  const state = findPersistedByThreadId(persisted, threadId);
67653
67911
  if (!state) {
67654
- log25.debug(`No persisted session found for ${threadId.substring(0, 8)}...`);
67912
+ log26.debug(`No persisted session found for ${threadId.substring(0, 8)}...`);
67655
67913
  return;
67656
67914
  }
67657
67915
  const shortId = threadId.substring(0, 8);
67658
- log25.info(`\uD83D\uDD04 Resuming paused session ${shortId}... for new message`);
67916
+ log26.info(`\uD83D\uDD04 Resuming paused session ${shortId}... for new message`);
67659
67917
  await resumeSession(state, ctx);
67660
67918
  const session = ctx.ops.findSessionByThreadId(threadId);
67661
67919
  if (session && session.claude.isRunning() && session.messageManager) {
67662
67920
  session.messageCount++;
67663
67921
  await session.messageManager.handleUserMessage(message, files, state.startedBy);
67664
67922
  } else {
67665
- log25.warn(`Failed to resume session ${shortId}..., could not send message`);
67923
+ log26.warn(`Failed to resume session ${shortId}..., could not send message`);
67666
67924
  }
67667
67925
  }
67668
67926
  async function handleExit(sessionId, code, ctx) {
@@ -67670,7 +67928,7 @@ async function handleExit(sessionId, code, ctx) {
67670
67928
  const shortId = sessionId.substring(0, 8);
67671
67929
  sessionLog6(session).debug(`handleExit called code=${code} isShuttingDown=${ctx.state.isShuttingDown}`);
67672
67930
  if (!session) {
67673
- log25.debug(`Session ${shortId}... not found (already cleaned up)`);
67931
+ log26.debug(`Session ${shortId}... not found (already cleaned up)`);
67674
67932
  return;
67675
67933
  }
67676
67934
  if (isSessionRestarting(session)) {
@@ -67863,7 +68121,7 @@ async function cleanupIdleSessions(timeoutMs, warningMs, ctx) {
67863
68121
  }
67864
68122
 
67865
68123
  // src/operations/monitor/handler.ts
67866
- var log26 = createLogger("monitor");
68124
+ var log27 = createLogger("monitor");
67867
68125
  var DEFAULT_INTERVAL_MS = 60 * 1000;
67868
68126
 
67869
68127
  class SessionMonitor {
@@ -67885,14 +68143,14 @@ class SessionMonitor {
67885
68143
  }
67886
68144
  start() {
67887
68145
  if (this.isRunning) {
67888
- log26.debug("Session monitor already running");
68146
+ log27.debug("Session monitor already running");
67889
68147
  return;
67890
68148
  }
67891
68149
  this.isRunning = true;
67892
- log26.debug(`Session monitor started (interval: ${this.intervalMs / 1000}s)`);
68150
+ log27.debug(`Session monitor started (interval: ${this.intervalMs / 1000}s)`);
67893
68151
  this.timer = setInterval(() => {
67894
68152
  this.runCheck().catch((err) => {
67895
- log26.error(`Error during session monitoring: ${err}`);
68153
+ log27.error(`Error during session monitoring: ${err}`);
67896
68154
  });
67897
68155
  }, this.intervalMs);
67898
68156
  }
@@ -67902,7 +68160,7 @@ class SessionMonitor {
67902
68160
  this.timer = null;
67903
68161
  }
67904
68162
  this.isRunning = false;
67905
- log26.debug("Session monitor stopped");
68163
+ log27.debug("Session monitor stopped");
67906
68164
  }
67907
68165
  async runCheck() {
67908
68166
  await cleanupIdleSessions(this.sessionTimeoutMs, this.sessionWarningMs, this.getContext());
@@ -67914,8 +68172,8 @@ class SessionMonitor {
67914
68172
  // src/operations/plugin/handler.ts
67915
68173
  init_spawn();
67916
68174
  init_logger();
67917
- var log27 = createLogger("plugin");
67918
- var sessionLog7 = createSessionLog(log27);
68175
+ var log28 = createLogger("plugin");
68176
+ var sessionLog7 = createSessionLog(log28);
67919
68177
  async function runPluginCommand(args, cwd, timeout2 = 60000) {
67920
68178
  return new Promise((resolve6) => {
67921
68179
  const claudePath = process.env.CLAUDE_PATH || "claude";
@@ -67936,7 +68194,7 @@ async function runPluginCommand(args, cwd, timeout2 = 60000) {
67936
68194
  });
67937
68195
  proc.on("error", (err) => {
67938
68196
  resolve6({ stdout, stderr, exitCode: 1 });
67939
- log27.error(`Plugin command error: ${err.message}`);
68197
+ log28.error(`Plugin command error: ${err.message}`);
67940
68198
  });
67941
68199
  });
67942
68200
  }
@@ -68135,7 +68393,7 @@ class SessionRegistry {
68135
68393
 
68136
68394
  // src/session/manager.ts
68137
68395
  init_logger();
68138
- var log28 = createLogger("manager");
68396
+ var log29 = createLogger("manager");
68139
68397
 
68140
68398
  class SessionManager extends EventEmitter4 {
68141
68399
  platforms = new Map;
@@ -68158,7 +68416,8 @@ class SessionManager extends EventEmitter4 {
68158
68416
  customDescription;
68159
68417
  customFooter;
68160
68418
  autoUpdateManager = null;
68161
- constructor(workingDir, skipPermissions = false, chromeEnabled = false, worktreeMode = "prompt", sessionsPath, threadLogsEnabled = true, threadLogsRetentionDays = 30, limits) {
68419
+ accountPool;
68420
+ constructor(workingDir, skipPermissions = false, chromeEnabled = false, worktreeMode = "prompt", sessionsPath, threadLogsEnabled = true, threadLogsRetentionDays = 30, limits, claudeAccounts) {
68162
68421
  super();
68163
68422
  this.workingDir = workingDir;
68164
68423
  this.skipPermissions = skipPermissions;
@@ -68169,6 +68428,7 @@ class SessionManager extends EventEmitter4 {
68169
68428
  this.limits = resolveLimits(limits);
68170
68429
  this.sessionStore = new SessionStore(sessionsPath);
68171
68430
  this.registry = new SessionRegistry(this.sessionStore);
68431
+ this.accountPool = new AccountPool(claudeAccounts);
68172
68432
  this.sessionMonitor = new SessionMonitor({
68173
68433
  sessionTimeoutMs: this.limits.sessionTimeoutMinutes * 60 * 1000,
68174
68434
  sessionWarningMs: this.limits.sessionWarningMinutes * 60 * 1000,
@@ -68202,7 +68462,7 @@ class SessionManager extends EventEmitter4 {
68202
68462
  markNeedsBump(platformId);
68203
68463
  this.updateStickyMessage();
68204
68464
  });
68205
- log28.info(`\uD83D\uDCE1 Platform "${platformId}" registered`);
68465
+ log29.info(`\uD83D\uDCE1 Platform "${platformId}" registered`);
68206
68466
  }
68207
68467
  removePlatform(platformId) {
68208
68468
  this.platforms.delete(platformId);
@@ -68218,7 +68478,7 @@ class SessionManager extends EventEmitter4 {
68218
68478
  if (users) {
68219
68479
  users.add(sessionId);
68220
68480
  }
68221
- log28.debug(`Registered session ${sessionId.substring(0, 20)} as worktree user for ${worktreePath}`);
68481
+ log29.debug(`Registered session ${sessionId.substring(0, 20)} as worktree user for ${worktreePath}`);
68222
68482
  }
68223
68483
  unregisterWorktreeUser(worktreePath, sessionId) {
68224
68484
  const users = this.worktreeUsers.get(worktreePath);
@@ -68284,7 +68544,12 @@ class SessionManager extends EventEmitter4 {
68284
68544
  offerContextPrompt: (s, q, f, e) => offerContextPrompt(s, q, f, this.getContextPromptHandler(), e),
68285
68545
  emitSessionAdd: (s) => this.emitSessionAdd(s),
68286
68546
  emitSessionUpdate: (sid, u) => this.emitSessionUpdate(sid, u),
68287
- emitSessionRemove: (sid) => this.emitSessionRemove(sid)
68547
+ emitSessionRemove: (sid) => this.emitSessionRemove(sid),
68548
+ acquireClaudeAccount: (preferredId) => this.accountPool.acquire(preferredId),
68549
+ getClaudeAccount: (id) => this.accountPool.get(id),
68550
+ releaseClaudeAccount: (id) => this.accountPool.release(id),
68551
+ markClaudeAccountCooling: (id, untilMs) => this.accountPool.markCooling(id, untilMs),
68552
+ getClaudeAccountPoolStatus: () => this.accountPool.status()
68288
68553
  };
68289
68554
  return createSessionContext(config, state, ops);
68290
68555
  }
@@ -68365,7 +68630,7 @@ class SessionManager extends EventEmitter4 {
68365
68630
  return false;
68366
68631
  }
68367
68632
  const shortId = persistedSession.threadId.substring(0, 8);
68368
- log28.info(`\uD83D\uDD04 Resuming session ${shortId}... via emoji reaction by @${username}`);
68633
+ log29.info(`\uD83D\uDD04 Resuming session ${shortId}... via emoji reaction by @${username}`);
68369
68634
  await resumeSession(persistedSession, this.getContext());
68370
68635
  return true;
68371
68636
  }
@@ -68395,7 +68660,7 @@ class SessionManager extends EventEmitter4 {
68395
68660
  }
68396
68661
  if (session.lastError?.postId === postId && isBugReportEmoji(emojiName)) {
68397
68662
  if (session.startedBy === username || session.platform.isUserAllowed(username) || session.sessionAllowedUsers.has(username)) {
68398
- log28.info(`\uD83D\uDC1B @${username} triggered bug report from error reaction`);
68663
+ log29.info(`\uD83D\uDC1B @${username} triggered bug report from error reaction`);
68399
68664
  await reportBug(session, undefined, username, this.getContext(), session.lastError);
68400
68665
  return;
68401
68666
  }
@@ -68511,7 +68776,8 @@ class SessionManager extends EventEmitter4 {
68511
68776
  sessionTags: session.sessionTags,
68512
68777
  pullRequestUrl: session.pullRequestUrl,
68513
68778
  messageCount: session.messageCount,
68514
- resumeFailCount: session.lifecycle.resumeFailCount
68779
+ resumeFailCount: session.lifecycle.resumeFailCount,
68780
+ claudeAccountId: session.claudeAccountId
68515
68781
  };
68516
68782
  this.sessionStore.save(session.sessionId, state);
68517
68783
  }
@@ -68536,7 +68802,8 @@ class SessionManager extends EventEmitter4 {
68536
68802
  workingDir: this.workingDir,
68537
68803
  debug: this.debug,
68538
68804
  description: this.customDescription,
68539
- footer: this.customFooter
68805
+ footer: this.customFooter,
68806
+ accountPoolStatus: this.accountPool.isEmpty ? undefined : this.accountPool.status()
68540
68807
  });
68541
68808
  }
68542
68809
  async updateAllStickyMessages() {
@@ -68561,11 +68828,11 @@ class SessionManager extends EventEmitter4 {
68561
68828
  }
68562
68829
  }
68563
68830
  if (sessionsToKill.length === 0) {
68564
- log28.info(`No active sessions to pause for platform ${platformId}`);
68831
+ log29.info(`No active sessions to pause for platform ${platformId}`);
68565
68832
  await this.updateStickyMessage();
68566
68833
  return;
68567
68834
  }
68568
- log28.info(`⏸️ Pausing ${sessionsToKill.length} session(s) for platform ${platformId}`);
68835
+ log29.info(`⏸️ Pausing ${sessionsToKill.length} session(s) for platform ${platformId}`);
68569
68836
  for (const session of sessionsToKill) {
68570
68837
  try {
68571
68838
  const fmt = session.platform.getFormatter();
@@ -68581,9 +68848,9 @@ class SessionManager extends EventEmitter4 {
68581
68848
  session.claude.kill();
68582
68849
  this.registry.unregister(session.sessionId);
68583
68850
  this.emitSessionRemove(session.sessionId);
68584
- log28.info(`⏸️ Paused session ${session.threadId.substring(0, 8)}`);
68851
+ log29.info(`⏸️ Paused session ${session.threadId.substring(0, 8)}`);
68585
68852
  } catch (err) {
68586
- log28.warn(`Failed to pause session ${session.threadId}: ${err}`);
68853
+ log29.warn(`Failed to pause session ${session.threadId}: ${err}`);
68587
68854
  }
68588
68855
  }
68589
68856
  for (const session of sessionsToKill) {
@@ -68604,17 +68871,17 @@ class SessionManager extends EventEmitter4 {
68604
68871
  sessionsToResume.push(state);
68605
68872
  }
68606
68873
  if (sessionsToResume.length === 0) {
68607
- log28.info(`No paused sessions to resume for platform ${platformId}`);
68874
+ log29.info(`No paused sessions to resume for platform ${platformId}`);
68608
68875
  await this.updateStickyMessage();
68609
68876
  return;
68610
68877
  }
68611
- log28.info(`▶️ Resuming ${sessionsToResume.length} paused session(s) for platform ${platformId}`);
68878
+ log29.info(`▶️ Resuming ${sessionsToResume.length} paused session(s) for platform ${platformId}`);
68612
68879
  for (const state of sessionsToResume) {
68613
68880
  try {
68614
68881
  await resumeSession(state, this.getContext());
68615
- log28.info(`▶️ Resumed session ${state.threadId.substring(0, 8)}`);
68882
+ log29.info(`▶️ Resumed session ${state.threadId.substring(0, 8)}`);
68616
68883
  } catch (err) {
68617
- log28.warn(`Failed to resume session ${state.threadId}: ${err}`);
68884
+ log29.warn(`Failed to resume session ${state.threadId}: ${err}`);
68618
68885
  }
68619
68886
  }
68620
68887
  await this.updateStickyMessage();
@@ -68626,14 +68893,14 @@ class SessionManager extends EventEmitter4 {
68626
68893
  const sessionTimeoutMs = this.limits.sessionTimeoutMinutes * 60 * 1000;
68627
68894
  const staleIds = this.sessionStore.cleanStale(sessionTimeoutMs * 2);
68628
68895
  if (staleIds.length > 0) {
68629
- log28.info(`\uD83E\uDDF9 Soft-deleted ${staleIds.length} stale session(s) (kept for history)`);
68896
+ log29.info(`\uD83E\uDDF9 Soft-deleted ${staleIds.length} stale session(s) (kept for history)`);
68630
68897
  }
68631
68898
  const removedCount = this.sessionStore.cleanHistory();
68632
68899
  if (removedCount > 0) {
68633
- log28.info(`\uD83D\uDDD1️ Permanently removed ${removedCount} old session(s) from history`);
68900
+ log29.info(`\uD83D\uDDD1️ Permanently removed ${removedCount} old session(s) from history`);
68634
68901
  }
68635
68902
  const persisted = this.sessionStore.load();
68636
- log28.info(`\uD83D\uDCC2 Loaded ${persisted.size} session(s) from persistence`);
68903
+ log29.info(`\uD83D\uDCC2 Loaded ${persisted.size} session(s) from persistence`);
68637
68904
  const excludePostIdsByPlatform = new Map;
68638
68905
  for (const session of persisted.values()) {
68639
68906
  const platformId = session.platformId;
@@ -68653,10 +68920,10 @@ class SessionManager extends EventEmitter4 {
68653
68920
  const excludePostIds = excludePostIdsByPlatform.get(platform.platformId);
68654
68921
  platform.getBotUser().then((botUser) => {
68655
68922
  cleanupOldStickyMessages(platform, botUser.id, true, excludePostIds).catch((err) => {
68656
- log28.warn(`Failed to cleanup old sticky messages for ${platform.platformId}: ${err}`);
68923
+ log29.warn(`Failed to cleanup old sticky messages for ${platform.platformId}: ${err}`);
68657
68924
  });
68658
68925
  }).catch((err) => {
68659
- log28.warn(`Failed to get bot user for cleanup on ${platform.platformId}: ${err}`);
68926
+ log29.warn(`Failed to get bot user for cleanup on ${platform.platformId}: ${err}`);
68660
68927
  });
68661
68928
  }
68662
68929
  if (persisted.size > 0) {
@@ -68670,10 +68937,10 @@ class SessionManager extends EventEmitter4 {
68670
68937
  }
68671
68938
  }
68672
68939
  if (pausedToSkip.length > 0) {
68673
- log28.info(`⏸️ ${pausedToSkip.length} session(s) remain paused (waiting for user message)`);
68940
+ log29.info(`⏸️ ${pausedToSkip.length} session(s) remain paused (waiting for user message)`);
68674
68941
  }
68675
68942
  if (activeToResume.length > 0) {
68676
- log28.info(`\uD83D\uDD04 Attempting to resume ${activeToResume.length} active session(s)...`);
68943
+ log29.info(`\uD83D\uDD04 Attempting to resume ${activeToResume.length} active session(s)...`);
68677
68944
  for (const state of activeToResume) {
68678
68945
  await resumeSession(state, this.getContext());
68679
68946
  }
@@ -69092,7 +69359,7 @@ Mention me to start a session in this worktree.`, threadId);
69092
69359
  const message = messageBuilder(formatter);
69093
69360
  await post(session, "info", message);
69094
69361
  } catch (err) {
69095
- log28.warn(`Failed to broadcast to session ${session.threadId}: ${err}`);
69362
+ log29.warn(`Failed to broadcast to session ${session.threadId}: ${err}`);
69096
69363
  }
69097
69364
  }
69098
69365
  }
@@ -69111,7 +69378,7 @@ Mention me to start a session in this worktree.`, threadId);
69111
69378
  session.messageManager?.setPendingUpdatePrompt({ postId: post2.id });
69112
69379
  this.registerPost(post2.id, session.threadId);
69113
69380
  } catch (err) {
69114
- log28.warn(`Failed to post ask message to ${threadId}: ${err}`);
69381
+ log29.warn(`Failed to post ask message to ${threadId}: ${err}`);
69115
69382
  }
69116
69383
  }
69117
69384
  }
@@ -76706,29 +76973,29 @@ function SessionLog({ logs, maxLines = 20 }) {
76706
76973
  return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
76707
76974
  flexDirection: "column",
76708
76975
  flexShrink: 0,
76709
- children: displayLogs.map((log29) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
76976
+ children: displayLogs.map((log30) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
76710
76977
  flexShrink: 0,
76711
76978
  children: [
76712
76979
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
76713
- color: getColorForLevel(log29.level),
76980
+ color: getColorForLevel(log30.level),
76714
76981
  dimColor: true,
76715
76982
  wrap: "truncate",
76716
76983
  children: [
76717
76984
  "[",
76718
- padComponent(log29.component),
76985
+ padComponent(log30.component),
76719
76986
  "]"
76720
76987
  ]
76721
76988
  }, undefined, true, undefined, this),
76722
76989
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
76723
- color: getColorForLevel(log29.level),
76990
+ color: getColorForLevel(log30.level),
76724
76991
  wrap: "truncate",
76725
76992
  children: [
76726
76993
  " ",
76727
- log29.message
76994
+ log30.message
76728
76995
  ]
76729
76996
  }, undefined, true, undefined, this)
76730
76997
  ]
76731
- }, log29.id, true, undefined, this))
76998
+ }, log30.id, true, undefined, this))
76732
76999
  }, undefined, false, undefined, this);
76733
77000
  }
76734
77001
  // src/ui/components/Footer.tsx
@@ -77226,7 +77493,7 @@ function LogPanel({ logs, maxLines = 10, focused = false }) {
77226
77493
  const scrollRef = import_react59.default.useRef(null);
77227
77494
  const { stdout } = use_stdout_default();
77228
77495
  const isDebug = process.env.DEBUG === "1";
77229
- const displayLogs = logs.filter((log29) => isDebug || log29.level !== "debug");
77496
+ const displayLogs = logs.filter((log30) => isDebug || log30.level !== "debug");
77230
77497
  const visibleLogs = displayLogs.slice(-Math.max(maxLines * 3, 100));
77231
77498
  import_react59.default.useEffect(() => {
77232
77499
  const handleResize = () => scrollRef.current?.remeasure();
@@ -77266,25 +77533,25 @@ function LogPanel({ logs, maxLines = 10, focused = false }) {
77266
77533
  overflow: "hidden",
77267
77534
  children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(ScrollView, {
77268
77535
  ref: scrollRef,
77269
- children: visibleLogs.map((log29) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
77536
+ children: visibleLogs.map((log30) => /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
77270
77537
  children: [
77271
77538
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
77272
77539
  dimColor: true,
77273
77540
  children: [
77274
77541
  "[",
77275
- padComponent2(log29.component),
77542
+ padComponent2(log30.component),
77276
77543
  "]"
77277
77544
  ]
77278
77545
  }, undefined, true, undefined, this),
77279
77546
  /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
77280
- color: getLevelColor(log29.level),
77547
+ color: getLevelColor(log30.level),
77281
77548
  children: [
77282
77549
  " ",
77283
- log29.message
77550
+ log30.message
77284
77551
  ]
77285
77552
  }, undefined, true, undefined, this)
77286
77553
  ]
77287
- }, log29.id, true, undefined, this))
77554
+ }, log30.id, true, undefined, this))
77288
77555
  }, undefined, false, undefined, this)
77289
77556
  }, undefined, false, undefined, this);
77290
77557
  }
@@ -77801,10 +78068,10 @@ function useAppState(initialConfig) {
77801
78068
  });
77802
78069
  }, []);
77803
78070
  const getLogsForSession = import_react60.useCallback((sessionId) => {
77804
- return state.logs.filter((log29) => log29.sessionId === sessionId);
78071
+ return state.logs.filter((log30) => log30.sessionId === sessionId);
77805
78072
  }, [state.logs]);
77806
78073
  const getGlobalLogs = import_react60.useCallback(() => {
77807
- return state.logs.filter((log29) => !log29.sessionId);
78074
+ return state.logs.filter((log30) => !log30.sessionId);
77808
78075
  }, [state.logs]);
77809
78076
  const togglePlatformEnabled = import_react60.useCallback((platformId) => {
77810
78077
  let newEnabled = false;
@@ -78798,7 +79065,7 @@ import { EventEmitter as EventEmitter9 } from "events";
78798
79065
  // src/auto-update/checker.ts
78799
79066
  init_logger();
78800
79067
  import { EventEmitter as EventEmitter7 } from "events";
78801
- var log29 = createLogger("checker");
79068
+ var log30 = createLogger("checker");
78802
79069
  var PACKAGE_NAME = "claude-threads";
78803
79070
  function compareVersions(a, b) {
78804
79071
  const partsA = a.replace(/^v/, "").split(".").map(Number);
@@ -78821,13 +79088,13 @@ async function fetchLatestVersion() {
78821
79088
  }
78822
79089
  });
78823
79090
  if (!response.ok) {
78824
- log29.warn(`Failed to fetch latest version: HTTP ${response.status}`);
79091
+ log30.warn(`Failed to fetch latest version: HTTP ${response.status}`);
78825
79092
  return null;
78826
79093
  }
78827
79094
  const data = await response.json();
78828
79095
  return data.version ?? null;
78829
79096
  } catch (err) {
78830
- log29.warn(`Failed to fetch latest version: ${err}`);
79097
+ log30.warn(`Failed to fetch latest version: ${err}`);
78831
79098
  return null;
78832
79099
  }
78833
79100
  }
@@ -78844,38 +79111,38 @@ class UpdateChecker extends EventEmitter7 {
78844
79111
  }
78845
79112
  start() {
78846
79113
  if (!this.config.enabled) {
78847
- log29.debug("Auto-update disabled, not starting checker");
79114
+ log30.debug("Auto-update disabled, not starting checker");
78848
79115
  return;
78849
79116
  }
78850
79117
  setTimeout(() => {
78851
79118
  this.check().catch((err) => {
78852
- log29.warn(`Initial update check failed: ${err}`);
79119
+ log30.warn(`Initial update check failed: ${err}`);
78853
79120
  });
78854
79121
  }, 5000);
78855
79122
  const intervalMs = this.config.checkIntervalMinutes * 60 * 1000;
78856
79123
  this.checkInterval = setInterval(() => {
78857
79124
  this.check().catch((err) => {
78858
- log29.warn(`Periodic update check failed: ${err}`);
79125
+ log30.warn(`Periodic update check failed: ${err}`);
78859
79126
  });
78860
79127
  }, intervalMs);
78861
- log29.info(`\uD83D\uDD04 Update checker started (every ${this.config.checkIntervalMinutes} minutes)`);
79128
+ log30.info(`\uD83D\uDD04 Update checker started (every ${this.config.checkIntervalMinutes} minutes)`);
78862
79129
  }
78863
79130
  stop() {
78864
79131
  if (this.checkInterval) {
78865
79132
  clearInterval(this.checkInterval);
78866
79133
  this.checkInterval = null;
78867
79134
  }
78868
- log29.debug("Update checker stopped");
79135
+ log30.debug("Update checker stopped");
78869
79136
  }
78870
79137
  async check() {
78871
79138
  if (this.isChecking) {
78872
- log29.debug("Check already in progress, skipping");
79139
+ log30.debug("Check already in progress, skipping");
78873
79140
  return this.lastUpdateInfo;
78874
79141
  }
78875
79142
  this.isChecking = true;
78876
79143
  this.emit("check:start");
78877
79144
  try {
78878
- log29.debug("Checking for updates...");
79145
+ log30.debug("Checking for updates...");
78879
79146
  const latestVersion2 = await fetchLatestVersion();
78880
79147
  if (!latestVersion2) {
78881
79148
  this.emit("check:complete", false);
@@ -78892,18 +79159,18 @@ class UpdateChecker extends EventEmitter7 {
78892
79159
  detectedAt: new Date
78893
79160
  };
78894
79161
  if (!this.lastUpdateInfo || this.lastUpdateInfo.latestVersion !== latestVersion2) {
78895
- log29.info(`\uD83C\uDD95 Update available: v${currentVersion} → v${latestVersion2}`);
79162
+ log30.info(`\uD83C\uDD95 Update available: v${currentVersion} → v${latestVersion2}`);
78896
79163
  this.lastUpdateInfo = updateInfo;
78897
79164
  this.emit("update", updateInfo);
78898
79165
  }
78899
79166
  this.emit("check:complete", true);
78900
79167
  return updateInfo;
78901
79168
  }
78902
- log29.debug(`Up to date (v${currentVersion})`);
79169
+ log30.debug(`Up to date (v${currentVersion})`);
78903
79170
  this.emit("check:complete", false);
78904
79171
  return null;
78905
79172
  } catch (err) {
78906
- log29.warn(`Update check failed: ${err}`);
79173
+ log30.warn(`Update check failed: ${err}`);
78907
79174
  this.emit("check:error", err);
78908
79175
  return null;
78909
79176
  } finally {
@@ -78974,7 +79241,7 @@ function isInScheduledWindow(window2) {
78974
79241
  }
78975
79242
 
78976
79243
  // src/auto-update/scheduler.ts
78977
- var log30 = createLogger("scheduler");
79244
+ var log31 = createLogger("scheduler");
78978
79245
 
78979
79246
  class UpdateScheduler extends EventEmitter8 {
78980
79247
  config;
@@ -78998,7 +79265,7 @@ class UpdateScheduler extends EventEmitter8 {
78998
79265
  scheduleUpdate(updateInfo) {
78999
79266
  this.pendingUpdate = updateInfo;
79000
79267
  if (this.config.autoRestartMode === "immediate") {
79001
- log30.info("Immediate mode: triggering update now");
79268
+ log31.info("Immediate mode: triggering update now");
79002
79269
  this.emit("ready", updateInfo);
79003
79270
  return;
79004
79271
  }
@@ -79011,19 +79278,19 @@ class UpdateScheduler extends EventEmitter8 {
79011
79278
  this.scheduledRestartAt = null;
79012
79279
  this.askApprovals.clear();
79013
79280
  this.askStartTime = null;
79014
- log30.debug("Update schedule cancelled");
79281
+ log31.debug("Update schedule cancelled");
79015
79282
  }
79016
79283
  deferUpdate(minutes) {
79017
79284
  const deferUntil = new Date(Date.now() + minutes * 60 * 1000);
79018
79285
  this.scheduledRestartAt = null;
79019
79286
  this.idleStartTime = null;
79020
79287
  this.emit("deferred", deferUntil);
79021
- log30.info(`Update deferred until ${deferUntil.toLocaleTimeString()}`);
79288
+ log31.info(`Update deferred until ${deferUntil.toLocaleTimeString()}`);
79022
79289
  return deferUntil;
79023
79290
  }
79024
79291
  recordAskResponse(threadId, approved) {
79025
79292
  this.askApprovals.set(threadId, approved);
79026
- log30.debug(`Thread ${threadId.substring(0, 8)} ${approved ? "approved" : "denied"} update`);
79293
+ log31.debug(`Thread ${threadId.substring(0, 8)} ${approved ? "approved" : "denied"} update`);
79027
79294
  this.checkAskCondition();
79028
79295
  }
79029
79296
  getScheduledRestartAt() {
@@ -79044,7 +79311,7 @@ class UpdateScheduler extends EventEmitter8 {
79044
79311
  return;
79045
79312
  this.checkCondition();
79046
79313
  this.checkTimer = setInterval(() => this.checkCondition(), 1e4);
79047
- log30.debug(`Started checking for ${this.config.autoRestartMode} condition`);
79314
+ log31.debug(`Started checking for ${this.config.autoRestartMode} condition`);
79048
79315
  }
79049
79316
  stopChecking() {
79050
79317
  if (this.checkTimer) {
@@ -79075,17 +79342,17 @@ class UpdateScheduler extends EventEmitter8 {
79075
79342
  if (activity.activeSessionCount === 0) {
79076
79343
  if (!this.idleStartTime) {
79077
79344
  this.idleStartTime = new Date;
79078
- log30.debug("No active sessions, starting idle timer");
79345
+ log31.debug("No active sessions, starting idle timer");
79079
79346
  }
79080
79347
  const idleMs = Date.now() - this.idleStartTime.getTime();
79081
79348
  const requiredMs = this.config.idleTimeoutMinutes * 60 * 1000;
79082
79349
  if (idleMs >= requiredMs) {
79083
- log30.info(`Idle for ${this.config.idleTimeoutMinutes} minutes, triggering update`);
79350
+ log31.info(`Idle for ${this.config.idleTimeoutMinutes} minutes, triggering update`);
79084
79351
  this.triggerCountdown();
79085
79352
  }
79086
79353
  } else {
79087
79354
  if (this.idleStartTime) {
79088
- log30.debug("Sessions became active, resetting idle timer");
79355
+ log31.debug("Sessions became active, resetting idle timer");
79089
79356
  this.idleStartTime = null;
79090
79357
  }
79091
79358
  }
@@ -79096,7 +79363,7 @@ class UpdateScheduler extends EventEmitter8 {
79096
79363
  const quietMs = Date.now() - activity.lastActivityAt.getTime();
79097
79364
  const requiredMs = this.config.quietTimeoutMinutes * 60 * 1000;
79098
79365
  if (quietMs >= requiredMs && !activity.anySessionBusy) {
79099
- log30.info(`Sessions quiet for ${this.config.quietTimeoutMinutes} minutes, triggering update`);
79366
+ log31.info(`Sessions quiet for ${this.config.quietTimeoutMinutes} minutes, triggering update`);
79100
79367
  this.triggerCountdown();
79101
79368
  }
79102
79369
  } else if (activity.activeSessionCount === 0) {
@@ -79106,7 +79373,7 @@ class UpdateScheduler extends EventEmitter8 {
79106
79373
  const idleMs = Date.now() - this.idleStartTime.getTime();
79107
79374
  const requiredMs = this.config.quietTimeoutMinutes * 60 * 1000;
79108
79375
  if (idleMs >= requiredMs) {
79109
- log30.info("No sessions and quiet timeout reached, triggering update");
79376
+ log31.info("No sessions and quiet timeout reached, triggering update");
79110
79377
  this.triggerCountdown();
79111
79378
  }
79112
79379
  }
@@ -79117,13 +79384,13 @@ class UpdateScheduler extends EventEmitter8 {
79117
79384
  }
79118
79385
  const activity = this.getSessionActivity();
79119
79386
  if (activity.activeSessionCount === 0) {
79120
- log30.info("Within scheduled window and no active sessions, triggering update");
79387
+ log31.info("Within scheduled window and no active sessions, triggering update");
79121
79388
  this.triggerCountdown();
79122
79389
  } else if (activity.lastActivityAt) {
79123
79390
  const quietMs = Date.now() - activity.lastActivityAt.getTime();
79124
79391
  const requiredMs = this.config.idleTimeoutMinutes * 60 * 1000;
79125
79392
  if (quietMs >= requiredMs && !activity.anySessionBusy) {
79126
- log30.info("Within scheduled window and sessions quiet, triggering update");
79393
+ log31.info("Within scheduled window and sessions quiet, triggering update");
79127
79394
  this.triggerCountdown();
79128
79395
  }
79129
79396
  }
@@ -79131,14 +79398,14 @@ class UpdateScheduler extends EventEmitter8 {
79131
79398
  checkAskCondition() {
79132
79399
  const threadIds = this.getActiveThreadIds();
79133
79400
  if (threadIds.length === 0) {
79134
- log30.info("No active threads, proceeding with update");
79401
+ log31.info("No active threads, proceeding with update");
79135
79402
  this.triggerCountdown();
79136
79403
  return;
79137
79404
  }
79138
79405
  if (!this.askStartTime && this.pendingUpdate) {
79139
79406
  this.askStartTime = new Date;
79140
79407
  this.postAskMessage(threadIds, this.pendingUpdate.latestVersion).catch((err) => {
79141
- log30.warn(`Failed to post ask message: ${err}`);
79408
+ log31.warn(`Failed to post ask message: ${err}`);
79142
79409
  });
79143
79410
  return;
79144
79411
  }
@@ -79151,12 +79418,12 @@ class UpdateScheduler extends EventEmitter8 {
79151
79418
  denials++;
79152
79419
  }
79153
79420
  if (approvals > threadIds.length / 2) {
79154
- log30.info(`Majority approved (${approvals}/${threadIds.length}), triggering update`);
79421
+ log31.info(`Majority approved (${approvals}/${threadIds.length}), triggering update`);
79155
79422
  this.triggerCountdown();
79156
79423
  return;
79157
79424
  }
79158
79425
  if (denials > threadIds.length / 2) {
79159
- log30.info(`Majority denied (${denials}/${threadIds.length}), deferring update`);
79426
+ log31.info(`Majority denied (${denials}/${threadIds.length}), deferring update`);
79160
79427
  this.deferUpdate(60);
79161
79428
  return;
79162
79429
  }
@@ -79164,7 +79431,7 @@ class UpdateScheduler extends EventEmitter8 {
79164
79431
  const elapsedMs = Date.now() - this.askStartTime.getTime();
79165
79432
  const timeoutMs = this.config.askTimeoutMinutes * 60 * 1000;
79166
79433
  if (elapsedMs >= timeoutMs) {
79167
- log30.info(`Ask timeout reached (${this.config.askTimeoutMinutes} min), triggering update`);
79434
+ log31.info(`Ask timeout reached (${this.config.askTimeoutMinutes} min), triggering update`);
79168
79435
  this.triggerCountdown();
79169
79436
  }
79170
79437
  }
@@ -79184,7 +79451,7 @@ class UpdateScheduler extends EventEmitter8 {
79184
79451
  this.emit("ready", this.pendingUpdate);
79185
79452
  }
79186
79453
  }, 1000);
79187
- log30.info("Update countdown started (60 seconds)");
79454
+ log31.info("Update countdown started (60 seconds)");
79188
79455
  }
79189
79456
  stopCountdown() {
79190
79457
  if (this.countdownTimer) {
@@ -79200,24 +79467,24 @@ import { spawn as spawn4, spawnSync } from "child_process";
79200
79467
  import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4 } from "fs";
79201
79468
  import { dirname as dirname8, resolve as resolve6 } from "path";
79202
79469
  import { homedir as homedir5 } from "os";
79203
- var log31 = createLogger("installer");
79470
+ var log32 = createLogger("installer");
79204
79471
  function detectPackageManager() {
79205
79472
  const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
79206
79473
  const originalInstaller = detectOriginalInstaller();
79207
79474
  if (originalInstaller) {
79208
- log31.debug(`Detected original installer: ${originalInstaller}`);
79475
+ log32.debug(`Detected original installer: ${originalInstaller}`);
79209
79476
  if (originalInstaller === "bun") {
79210
79477
  const bunCheck2 = spawnSync("bun", ["--version"], { stdio: "ignore" });
79211
79478
  if (bunCheck2.status === 0) {
79212
79479
  return { cmd: "bun", isBun: true };
79213
79480
  }
79214
- log31.warn("Originally installed with bun, but bun not found. Falling back to npm.");
79481
+ log32.warn("Originally installed with bun, but bun not found. Falling back to npm.");
79215
79482
  } else {
79216
79483
  const npmCheck2 = spawnSync(npmCmd, ["--version"], { stdio: "ignore" });
79217
79484
  if (npmCheck2.status === 0) {
79218
79485
  return { cmd: npmCmd, isBun: false };
79219
79486
  }
79220
- log31.warn("Originally installed with npm, but npm not found. Falling back to bun.");
79487
+ log32.warn("Originally installed with npm, but npm not found. Falling back to bun.");
79221
79488
  }
79222
79489
  }
79223
79490
  const bunCheck = spawnSync("bun", ["--version"], { stdio: "ignore" });
@@ -79268,7 +79535,7 @@ function loadUpdateState() {
79268
79535
  return JSON.parse(content);
79269
79536
  }
79270
79537
  } catch (err) {
79271
- log31.warn(`Failed to load update state: ${err}`);
79538
+ log32.warn(`Failed to load update state: ${err}`);
79272
79539
  }
79273
79540
  return {};
79274
79541
  }
@@ -79279,9 +79546,9 @@ function saveUpdateState(state) {
79279
79546
  mkdirSync4(dir, { recursive: true });
79280
79547
  }
79281
79548
  writeFileSync5(STATE_PATH, JSON.stringify(state, null, 2), "utf-8");
79282
- log31.debug("Update state saved");
79549
+ log32.debug("Update state saved");
79283
79550
  } catch (err) {
79284
- log31.warn(`Failed to save update state: ${err}`);
79551
+ log32.warn(`Failed to save update state: ${err}`);
79285
79552
  }
79286
79553
  }
79287
79554
  function clearUpdateState() {
@@ -79290,7 +79557,7 @@ function clearUpdateState() {
79290
79557
  writeFileSync5(STATE_PATH, "{}", "utf-8");
79291
79558
  }
79292
79559
  } catch (err) {
79293
- log31.warn(`Failed to clear update state: ${err}`);
79560
+ log32.warn(`Failed to clear update state: ${err}`);
79294
79561
  }
79295
79562
  }
79296
79563
  function checkJustUpdated() {
@@ -79322,11 +79589,11 @@ function clearRuntimeSettings() {
79322
79589
  }
79323
79590
  }
79324
79591
  async function installVersion(version) {
79325
- log31.info(`\uD83D\uDCE6 Installing ${PACKAGE_NAME2}@${version}...`);
79592
+ log32.info(`\uD83D\uDCE6 Installing ${PACKAGE_NAME2}@${version}...`);
79326
79593
  const pm = detectPackageManager();
79327
79594
  if (!pm) {
79328
79595
  const error = "Neither bun nor npm found in PATH. Cannot install update.";
79329
- log31.error(`❌ ${error}`);
79596
+ log32.error(`❌ ${error}`);
79330
79597
  return { success: false, error };
79331
79598
  }
79332
79599
  saveUpdateState({
@@ -79338,7 +79605,7 @@ async function installVersion(version) {
79338
79605
  return new Promise((resolve7) => {
79339
79606
  const { cmd, isBun: isBun3 } = pm;
79340
79607
  const args = ["install", "-g", `${PACKAGE_NAME2}@${version}`];
79341
- log31.debug(`Using ${isBun3 ? "bun" : "npm"} for installation`);
79608
+ log32.debug(`Using ${isBun3 ? "bun" : "npm"} for installation`);
79342
79609
  const child = spawn4(cmd, args, {
79343
79610
  stdio: ["ignore", "pipe", "pipe"],
79344
79611
  env: {
@@ -79356,7 +79623,7 @@ async function installVersion(version) {
79356
79623
  });
79357
79624
  child.on("close", (code) => {
79358
79625
  if (code === 0) {
79359
- log31.info(`✅ Successfully installed ${PACKAGE_NAME2}@${version}`);
79626
+ log32.info(`✅ Successfully installed ${PACKAGE_NAME2}@${version}`);
79360
79627
  saveUpdateState({
79361
79628
  previousVersion: VERSION,
79362
79629
  targetVersion: version,
@@ -79366,20 +79633,20 @@ async function installVersion(version) {
79366
79633
  resolve7({ success: true });
79367
79634
  } else {
79368
79635
  const errorMsg = stderr || stdout || `Exit code: ${code}`;
79369
- log31.error(`❌ Installation failed: ${errorMsg}`);
79636
+ log32.error(`❌ Installation failed: ${errorMsg}`);
79370
79637
  clearUpdateState();
79371
79638
  resolve7({ success: false, error: errorMsg });
79372
79639
  }
79373
79640
  });
79374
79641
  child.on("error", (err) => {
79375
- log31.error(`❌ Failed to spawn npm: ${err}`);
79642
+ log32.error(`❌ Failed to spawn npm: ${err}`);
79376
79643
  clearUpdateState();
79377
79644
  resolve7({ success: false, error: err.message });
79378
79645
  });
79379
79646
  setTimeout(() => {
79380
79647
  if (child.exitCode === null) {
79381
79648
  child.kill();
79382
- log31.error("❌ Installation timed out");
79649
+ log32.error("❌ Installation timed out");
79383
79650
  clearUpdateState();
79384
79651
  resolve7({ success: false, error: "Installation timed out" });
79385
79652
  }
@@ -79421,7 +79688,7 @@ class UpdateInstaller {
79421
79688
  }
79422
79689
 
79423
79690
  // src/auto-update/manager.ts
79424
- var log32 = createLogger("updater");
79691
+ var log33 = createLogger("updater");
79425
79692
 
79426
79693
  class AutoUpdateManager extends EventEmitter9 {
79427
79694
  config;
@@ -79444,23 +79711,23 @@ class AutoUpdateManager extends EventEmitter9 {
79444
79711
  }
79445
79712
  start() {
79446
79713
  if (!this.config.enabled) {
79447
- log32.info("Auto-update is disabled");
79714
+ log33.info("Auto-update is disabled");
79448
79715
  return;
79449
79716
  }
79450
79717
  const updateResult = this.installer.checkJustUpdated();
79451
79718
  if (updateResult) {
79452
- log32.info(`\uD83C\uDF89 Updated from v${updateResult.previousVersion} to v${updateResult.currentVersion}`);
79719
+ log33.info(`\uD83C\uDF89 Updated from v${updateResult.previousVersion} to v${updateResult.currentVersion}`);
79453
79720
  this.callbacks.broadcastUpdate((fmt) => `\uD83C\uDF89 ${fmt.formatBold("Bot updated")} from v${updateResult.previousVersion} to v${updateResult.currentVersion}`).catch((err) => {
79454
- log32.warn(`Failed to broadcast update notification: ${err}`);
79721
+ log33.warn(`Failed to broadcast update notification: ${err}`);
79455
79722
  });
79456
79723
  }
79457
79724
  this.checker.start();
79458
- log32.info(`\uD83D\uDD04 Auto-update manager started (mode: ${this.config.autoRestartMode})`);
79725
+ log33.info(`\uD83D\uDD04 Auto-update manager started (mode: ${this.config.autoRestartMode})`);
79459
79726
  }
79460
79727
  stop() {
79461
79728
  this.checker.stop();
79462
79729
  this.scheduler.stop();
79463
- log32.debug("Auto-update manager stopped");
79730
+ log33.debug("Auto-update manager stopped");
79464
79731
  }
79465
79732
  getState() {
79466
79733
  return { ...this.state };
@@ -79474,10 +79741,10 @@ class AutoUpdateManager extends EventEmitter9 {
79474
79741
  async forceUpdate() {
79475
79742
  const updateInfo = this.state.updateInfo || await this.checker.check();
79476
79743
  if (!updateInfo) {
79477
- log32.info("No update available");
79744
+ log33.info("No update available");
79478
79745
  return;
79479
79746
  }
79480
- log32.info("Forcing immediate update");
79747
+ log33.info("Forcing immediate update");
79481
79748
  await this.performUpdate(updateInfo);
79482
79749
  }
79483
79750
  deferUpdate(minutes = 60) {
@@ -79532,7 +79799,7 @@ class AutoUpdateManager extends EventEmitter9 {
79532
79799
  await this.callbacks.broadcastUpdate((fmt) => `✅ ${fmt.formatBold("Update installed")} - restarting now. ${fmt.formatItalic("Sessions will resume automatically.")}`).catch(() => {});
79533
79800
  await new Promise((resolve7) => setTimeout(resolve7, 1000));
79534
79801
  await this.callbacks.prepareForRestart();
79535
- log32.info(`\uD83D\uDD04 Restarting for update to v${updateInfo.latestVersion}`);
79802
+ log33.info(`\uD83D\uDD04 Restarting for update to v${updateInfo.latestVersion}`);
79536
79803
  process.stdout.write("\x1B[2J\x1B[H");
79537
79804
  process.stdout.write("\x1B[?25h");
79538
79805
  process.exit(RESTART_EXIT_CODE);
@@ -79827,7 +80094,7 @@ async function startWithoutDaemon() {
79827
80094
  keepAlive.setEnabled(keepAliveEnabled);
79828
80095
  const threadLogsEnabled = config.threadLogs?.enabled ?? true;
79829
80096
  const threadLogsRetentionDays = config.threadLogs?.retentionDays ?? 30;
79830
- const session = new SessionManager(workingDir, initialSkipPermissions, config.chrome, config.worktreeMode, undefined, threadLogsEnabled, threadLogsRetentionDays, config.limits);
80097
+ const session = new SessionManager(workingDir, initialSkipPermissions, config.chrome, config.worktreeMode, undefined, threadLogsEnabled, threadLogsRetentionDays, config.limits, config.claudeAccounts);
79831
80098
  if (config.stickyMessage) {
79832
80099
  session.setStickyMessageCustomization(config.stickyMessage.description, config.stickyMessage.footer);
79833
80100
  }