@sideboard-ai/core 0.1.198 → 0.1.200

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{abletime-JINF5KJV.js → abletime-345SE3B4.js} +2 -2
  2. package/dist/{abletime-HR6P4GJH.js → abletime-KGPD3UUJ.js} +2 -2
  3. package/dist/{agents-5TZY6LLX.js → agents-N7WXOGN6.js} +28 -4
  4. package/dist/{agents-AQQKPD46.js → agents-ZRIFDXCB.js} +28 -4
  5. package/dist/{app-settings-5KHVKJKO.js → app-settings-AXCURTZJ.js} +11 -1
  6. package/dist/{app-settings-J775CYOO.js → app-settings-V6IHESEQ.js} +11 -1
  7. package/dist/{chunk-SYXSSU7G.js → chunk-5XSDGJMP.js} +369 -4
  8. package/dist/{chunk-DROELG52.js → chunk-62IMZIIZ.js} +58 -41
  9. package/dist/{chunk-E37JHCO3.js → chunk-7AHAABKN.js} +1 -1
  10. package/dist/{chunk-S5GLSRLP.js → chunk-CXFW5LIH.js} +48 -1
  11. package/dist/{chunk-6YTI2HBG.js → chunk-EWDE54OI.js} +2 -2
  12. package/dist/{chunk-AH6WIBLY.js → chunk-ISV5IFH3.js} +48 -1
  13. package/dist/{chunk-DP4TKAMZ.js → chunk-NXM45OS3.js} +1 -1
  14. package/dist/{chunk-6YS5IKD2.js → chunk-O2DRYD2B.js} +59 -42
  15. package/dist/{chunk-S4QCBBXS.js → chunk-OSPE25A7.js} +1 -1
  16. package/dist/{chunk-HZTHWU6A.js → chunk-PDMNYCPL.js} +2 -2
  17. package/dist/{chunk-KTHRWHA3.js → chunk-PGQGP4FD.js} +1 -1
  18. package/dist/{chunk-EA67VQM2.js → chunk-PKUPOVKP.js} +369 -4
  19. package/dist/{coordinator-prompt-IX66YUJ2.js → coordinator-prompt-2RWBH6W7.js} +3 -3
  20. package/dist/{coordinator-prompt-LYKS3YNG.js → coordinator-prompt-AL62H73U.js} +3 -3
  21. package/dist/{global-workspace-SNJ2Z6SL.js → global-workspace-VAO3BQP5.js} +3 -3
  22. package/dist/{global-workspace-4QX6UEOY.js → global-workspace-Y5KKGXN7.js} +3 -3
  23. package/dist/index.cjs +766 -280
  24. package/dist/index.d.cts +116 -11
  25. package/dist/index.d.ts +116 -11
  26. package/dist/index.js +42 -8
  27. package/dist/mcp/run-stdio.cjs +374 -276
  28. package/dist/mcp/run-stdio.js +8 -8
  29. package/dist/{orchestrator-L2H42HPW.js → orchestrator-D2EJ4Z7Z.js} +5 -5
  30. package/dist/{orchestrator-6ZNKCPNL.js → orchestrator-DPHIMK44.js} +5 -5
  31. package/dist/{workspaces-URMUVGAQ.js → workspaces-DZZQM745.js} +3 -3
  32. package/dist/{workspaces-UTOYGBYB.js → workspaces-HEKFQP4B.js} +3 -3
  33. package/dist/{worktree-R43JOR4V.js → worktree-ENRMJUI3.js} +2 -2
  34. package/dist/{worktree-RM6UWNGZ.js → worktree-IEUSQ63V.js} +2 -2
  35. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -988,6 +988,30 @@ var init_branch_prefix = __esm({
988
988
  }
989
989
  });
990
990
 
991
+ // src/store/usage-on-limit.ts
992
+ function isUsageOnLimit(value) {
993
+ return value === "keep_going" || value === "confirm" || value === "switch_agent" || value === "wait_reset";
994
+ }
995
+ function resolveUsageOnLimit(advanced = {}) {
996
+ if (isUsageOnLimit(advanced.usageOnLimit)) return advanced.usageOnLimit;
997
+ if (advanced.confirmClaudeUsageOverLimit) return "confirm";
998
+ if (advanced.orchestrationQuotaOnLimit === "wait_reset") return "wait_reset";
999
+ if (advanced.orchestrationQuotaOnLimit === "switch_agent") return "switch_agent";
1000
+ return "keep_going";
1001
+ }
1002
+ var USAGE_ON_LIMIT_VALUES;
1003
+ var init_usage_on_limit = __esm({
1004
+ "src/store/usage-on-limit.ts"() {
1005
+ "use strict";
1006
+ USAGE_ON_LIMIT_VALUES = [
1007
+ "keep_going",
1008
+ "confirm",
1009
+ "switch_agent",
1010
+ "wait_reset"
1011
+ ];
1012
+ }
1013
+ });
1014
+
991
1015
  // src/store/issue-source-labels.ts
992
1016
  function issueSourceLabel(source) {
993
1017
  if (source && source in ISSUE_SOURCE_LABELS) {
@@ -1016,6 +1040,7 @@ __export(app_settings_exports, {
1016
1040
  HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
1017
1041
  ISSUE_SOURCE_LABELS: () => ISSUE_SOURCE_LABELS,
1018
1042
  PROFILE_NOTES_MAX: () => PROFILE_NOTES_MAX,
1043
+ USAGE_ON_LIMIT_VALUES: () => USAGE_ON_LIMIT_VALUES,
1019
1044
  appSettingsPath: () => appSettingsPath,
1020
1045
  applyAppEnvironment: () => applyAppEnvironment,
1021
1046
  autoArchiveOnMergeEnabled: () => autoArchiveOnMergeEnabled,
@@ -1032,6 +1057,7 @@ __export(app_settings_exports, {
1032
1057
  childEnvWithAppSettings: () => childEnvWithAppSettings,
1033
1058
  claudeChromeEnabled: () => claudeChromeEnabled,
1034
1059
  claudeUserSettingsPath: () => claudeUserSettingsPath,
1060
+ confirmClaudeUsageOverLimitEnabled: () => confirmClaudeUsageOverLimitEnabled,
1035
1061
  cowboyModeEnabled: () => cowboyModeEnabled,
1036
1062
  deleteBranchOnPurgeEnabled: () => deleteBranchOnPurgeEnabled,
1037
1063
  disconnectAbleTimeConnection: () => disconnectAbleTimeConnection,
@@ -1061,6 +1087,7 @@ __export(app_settings_exports, {
1061
1087
  isAbleTimeConnected: () => isAbleTimeConnected,
1062
1088
  isIssueSourceConnected: () => isIssueSourceConnected,
1063
1089
  isLinearConnected: () => isLinearConnected,
1090
+ isUsageOnLimit: () => isUsageOnLimit,
1064
1091
  issueSourceLabel: () => issueSourceLabel,
1065
1092
  loadAppSettings: () => loadAppSettings,
1066
1093
  maxConcurrentAgents: () => maxConcurrentAgents,
@@ -1076,6 +1103,7 @@ __export(app_settings_exports, {
1076
1103
  resolveNewThreadOptions: () => resolveNewThreadOptions,
1077
1104
  resolveOrchestratorDefaults: () => resolveOrchestratorDefaults,
1078
1105
  resolveThreadDefaults: () => resolveThreadDefaults,
1106
+ resolveUsageOnLimit: () => resolveUsageOnLimit,
1079
1107
  resolveViewerProfile: () => resolveViewerProfile,
1080
1108
  resolveViewerProfileForRepo: () => resolveViewerProfileForRepo,
1081
1109
  saveAbleTimeConnection: () => saveAbleTimeConnection,
@@ -1095,6 +1123,7 @@ __export(app_settings_exports, {
1095
1123
  updateIntegrationsSettings: () => updateIntegrationsSettings,
1096
1124
  updateOpencodeSettings: () => updateOpencodeSettings,
1097
1125
  updateProjectProfileSettings: () => updateProjectProfileSettings,
1126
+ usageOnLimit: () => usageOnLimit,
1098
1127
  writeViewerContext: () => writeViewerContext
1099
1128
  });
1100
1129
  function emptyPublicIntegrations() {
@@ -1459,6 +1488,12 @@ function normalizeAdvanced(raw) {
1459
1488
  if (typeof source.showCost === "boolean") {
1460
1489
  out.showCost = source.showCost;
1461
1490
  }
1491
+ if (isUsageOnLimit(source.usageOnLimit)) {
1492
+ out.usageOnLimit = source.usageOnLimit;
1493
+ }
1494
+ if (typeof source.confirmClaudeUsageOverLimit === "boolean") {
1495
+ out.confirmClaudeUsageOverLimit = source.confirmClaudeUsageOverLimit;
1496
+ }
1462
1497
  if (typeof source.autoArchiveOnMerge === "boolean") {
1463
1498
  out.autoArchiveOnMerge = source.autoArchiveOnMerge;
1464
1499
  }
@@ -2321,6 +2356,17 @@ function updateAdvancedSettings(patch) {
2321
2356
  if (typeof patch.showCost === "boolean") {
2322
2357
  advanced.showCost = patch.showCost;
2323
2358
  }
2359
+ if (isUsageOnLimit(patch.usageOnLimit)) {
2360
+ advanced.usageOnLimit = patch.usageOnLimit;
2361
+ advanced.confirmClaudeUsageOverLimit = patch.usageOnLimit === "confirm";
2362
+ if (patch.usageOnLimit === "switch_agent" || patch.usageOnLimit === "wait_reset") {
2363
+ advanced.orchestrationQuotaOnLimit = patch.usageOnLimit;
2364
+ }
2365
+ } else if (typeof patch.confirmClaudeUsageOverLimit === "boolean") {
2366
+ advanced.confirmClaudeUsageOverLimit = patch.confirmClaudeUsageOverLimit;
2367
+ if (patch.confirmClaudeUsageOverLimit) advanced.usageOnLimit = "confirm";
2368
+ else if (advanced.usageOnLimit === "confirm") advanced.usageOnLimit = "keep_going";
2369
+ }
2324
2370
  if (typeof patch.autoArchiveOnMerge === "boolean") {
2325
2371
  advanced.autoArchiveOnMerge = patch.autoArchiveOnMerge;
2326
2372
  }
@@ -2383,14 +2429,21 @@ function cowboyModeEnabled(settings = loadAppSettings()) {
2383
2429
  function showCostEnabled(settings = loadAppSettings()) {
2384
2430
  return Boolean(settings.advanced.showCost);
2385
2431
  }
2432
+ function confirmClaudeUsageOverLimitEnabled(settings = loadAppSettings()) {
2433
+ return usageOnLimit(settings) === "confirm";
2434
+ }
2386
2435
  function autoArchiveOnMergeEnabled(settings = loadAppSettings()) {
2387
2436
  return Boolean(settings.advanced.autoArchiveOnMerge);
2388
2437
  }
2389
2438
  function autoCleanupOrphansEnabled(settings = loadAppSettings()) {
2390
2439
  return Boolean(settings.advanced.autoCleanupOrphans);
2391
2440
  }
2441
+ function usageOnLimit(settings = loadAppSettings()) {
2442
+ return resolveUsageOnLimit(settings.advanced);
2443
+ }
2392
2444
  function orchestrationQuotaOnLimit(settings = loadAppSettings()) {
2393
- return settings.advanced.orchestrationQuotaOnLimit ?? "switch_agent";
2445
+ const action = usageOnLimit(settings);
2446
+ return action === "wait_reset" ? "wait_reset" : "switch_agent";
2394
2447
  }
2395
2448
  function orchestrationQuotaFallbackAgent(settings = loadAppSettings()) {
2396
2449
  const preferred = settings.advanced.orchestrationQuotaFallbackAgent;
@@ -2505,6 +2558,8 @@ var init_app_settings = __esm({
2505
2558
  init_private_file();
2506
2559
  init_secret_vault();
2507
2560
  init_branch_prefix();
2561
+ init_usage_on_limit();
2562
+ init_usage_on_limit();
2508
2563
  init_issue_source_labels();
2509
2564
  init_account_profile();
2510
2565
  HARNESS_ENV_KEYS = {
@@ -2845,14 +2900,14 @@ function fileMtimeMs(path2) {
2845
2900
  }
2846
2901
  }
2847
2902
  function rememberThread(thread, mtimeMs) {
2848
- const cache = cacheForDir();
2849
- cache.byId.set(thread.id, thread);
2850
- if (mtimeMs != null) cache.mtimeMs.set(thread.id, mtimeMs);
2903
+ const cache2 = cacheForDir();
2904
+ cache2.byId.set(thread.id, thread);
2905
+ if (mtimeMs != null) cache2.mtimeMs.set(thread.id, mtimeMs);
2851
2906
  }
2852
2907
  function forgetThread(id) {
2853
- const cache = cacheForDir();
2854
- cache.byId.delete(id);
2855
- cache.mtimeMs.delete(id);
2908
+ const cache2 = cacheForDir();
2909
+ cache2.byId.delete(id);
2910
+ cache2.mtimeMs.delete(id);
2856
2911
  }
2857
2912
  function invalidateThreadListCache() {
2858
2913
  listCache = null;
@@ -2864,9 +2919,9 @@ function readThread(id) {
2864
2919
  forgetThread(id);
2865
2920
  return null;
2866
2921
  }
2867
- const cache = cacheForDir();
2868
- const cached = cache.byId.get(id);
2869
- if (cached && cache.mtimeMs.get(id) === mtimeMs) return cached;
2922
+ const cache2 = cacheForDir();
2923
+ const cached = cache2.byId.get(id);
2924
+ if (cached && cache2.mtimeMs.get(id) === mtimeMs) return cached;
2870
2925
  const raw = (0, import_node_fs9.readFileSync)(path2, "utf8");
2871
2926
  const thread = normalizeThread(JSON.parse(raw));
2872
2927
  rememberThread(thread, mtimeMs);
@@ -2888,7 +2943,7 @@ function isThreadRecordFile(nameOrPath) {
2888
2943
  return name.endsWith(".json") && !name.endsWith(".live.json");
2889
2944
  }
2890
2945
  function listThreads(opts) {
2891
- const cache = cacheForDir();
2946
+ const cache2 = cacheForDir();
2892
2947
  const files = (0, import_node_fs9.readdirSync)(threadsDir()).filter(isThreadRecordFile);
2893
2948
  const seen = /* @__PURE__ */ new Set();
2894
2949
  for (const f of files) {
@@ -2900,10 +2955,10 @@ function listThreads(opts) {
2900
2955
  } catch {
2901
2956
  }
2902
2957
  }
2903
- for (const id of [...cache.byId.keys()]) {
2958
+ for (const id of [...cache2.byId.keys()]) {
2904
2959
  if (!seen.has(id)) forgetThread(id);
2905
2960
  }
2906
- const threads = [...cache.byId.values()].sort(
2961
+ const threads = [...cache2.byId.values()].sort(
2907
2962
  (a, b) => b.updatedAt.localeCompare(a.updatedAt)
2908
2963
  );
2909
2964
  if (opts?.includeArchived) return threads;
@@ -13674,6 +13729,372 @@ var init_session_quota = __esm({
13674
13729
  }
13675
13730
  });
13676
13731
 
13732
+ // src/agents/claude-usage.ts
13733
+ function parseClaudeResetsAt(value) {
13734
+ if (typeof value === "number" && Number.isFinite(value)) {
13735
+ const ms = value > 1e12 ? value : value * 1e3;
13736
+ const d = new Date(ms);
13737
+ return Number.isNaN(d.getTime()) ? null : d.toISOString();
13738
+ }
13739
+ if (typeof value === "string") {
13740
+ const trimmed = value.trim();
13741
+ if (!trimmed) return null;
13742
+ if (/^\d+(\.\d+)?$/.test(trimmed)) {
13743
+ return parseClaudeResetsAt(Number(trimmed));
13744
+ }
13745
+ const d = new Date(trimmed);
13746
+ return Number.isNaN(d.getTime()) ? null : d.toISOString();
13747
+ }
13748
+ return null;
13749
+ }
13750
+ function parseClaudeUtilization(value) {
13751
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
13752
+ return Math.max(0, Math.min(100, value));
13753
+ }
13754
+ function windowFromRaw(id, raw) {
13755
+ if (!raw || typeof raw !== "object") return null;
13756
+ const row = raw;
13757
+ const used = parseClaudeUtilization(row.utilization ?? row.used_percentage);
13758
+ if (used == null) return null;
13759
+ const meta = WINDOW_META[id];
13760
+ return {
13761
+ id,
13762
+ label: meta.label,
13763
+ shortLabel: meta.shortLabel,
13764
+ detail: meta.detail,
13765
+ usedPercent: used,
13766
+ remainingPercent: Math.max(0, Math.min(100, 100 - used)),
13767
+ resetsAt: parseClaudeResetsAt(row.resets_at)
13768
+ };
13769
+ }
13770
+ function extraUsageFromRaw(raw) {
13771
+ if (!raw || typeof raw !== "object") return void 0;
13772
+ const row = raw;
13773
+ const enabled = row.is_enabled === true || row.enabled === true;
13774
+ if (!enabled && row.is_enabled !== false && row.enabled !== false) return void 0;
13775
+ const usedCredits = numberOrUndef(row.used_credits ?? row.used);
13776
+ const monthlyLimit = numberOrUndef(row.monthly_limit);
13777
+ const usedPercent = parseClaudeUtilization(row.utilization) ?? void 0;
13778
+ return {
13779
+ enabled,
13780
+ ...usedCredits != null ? { usedCredits } : {},
13781
+ ...monthlyLimit != null ? { monthlyLimit } : {},
13782
+ ...usedPercent != null ? { usedPercent } : {}
13783
+ };
13784
+ }
13785
+ function numberOrUndef(value) {
13786
+ if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
13787
+ return value;
13788
+ }
13789
+ function parseClaudeUsagePayload(raw, fetchedAt = (/* @__PURE__ */ new Date()).toISOString()) {
13790
+ if (!raw || typeof raw !== "object") return null;
13791
+ const obj = raw;
13792
+ const source = obj.rate_limits && typeof obj.rate_limits === "object" ? obj.rate_limits : obj;
13793
+ const windows = [];
13794
+ for (const id of WINDOW_ORDER) {
13795
+ const parsed = windowFromRaw(id, source[id]);
13796
+ if (parsed) windows.push(parsed);
13797
+ }
13798
+ if (windows.length === 0) return null;
13799
+ const extra = extraUsageFromRaw(obj.extra_usage ?? source.extra_usage);
13800
+ return {
13801
+ windows,
13802
+ ...extra ? { extraUsage: extra } : {},
13803
+ fetchedAt
13804
+ };
13805
+ }
13806
+ function hottestClaudeWindow(usage) {
13807
+ if (usage.windows.length === 0) return null;
13808
+ return usage.windows.reduce((a, b) => b.usedPercent > a.usedPercent ? b : a);
13809
+ }
13810
+ function formatClaudeUsageReset(resetsAt, now = /* @__PURE__ */ new Date()) {
13811
+ if (!resetsAt) return "";
13812
+ const at = new Date(resetsAt);
13813
+ if (Number.isNaN(at.getTime())) return "";
13814
+ const ms = at.getTime() - now.getTime();
13815
+ if (ms <= 0) return "resets soon";
13816
+ const minutes = Math.round(ms / 6e4);
13817
+ if (minutes < 60) return `resets in ${Math.max(1, minutes)}m`;
13818
+ const hours = Math.round(minutes / 60);
13819
+ if (hours < 36) return `resets in ${hours}h`;
13820
+ try {
13821
+ return `resets ${at.toLocaleString(void 0, {
13822
+ weekday: "short",
13823
+ hour: "numeric",
13824
+ minute: "2-digit"
13825
+ })}`;
13826
+ } catch {
13827
+ return `resets ${at.toISOString()}`;
13828
+ }
13829
+ }
13830
+ function formatClaudeUsageResetClock(resetsAt) {
13831
+ if (!resetsAt) return "";
13832
+ const at = new Date(resetsAt);
13833
+ if (Number.isNaN(at.getTime())) return "";
13834
+ try {
13835
+ return at.toLocaleString(void 0, {
13836
+ weekday: "short",
13837
+ month: "short",
13838
+ day: "numeric",
13839
+ hour: "numeric",
13840
+ minute: "2-digit"
13841
+ });
13842
+ } catch {
13843
+ return at.toISOString();
13844
+ }
13845
+ }
13846
+ function formatClaudeUsageFetchedAt(fetchedAt, now = /* @__PURE__ */ new Date()) {
13847
+ const at = new Date(fetchedAt);
13848
+ if (Number.isNaN(at.getTime())) return "";
13849
+ const minutes = Math.max(0, Math.round((now.getTime() - at.getTime()) / 6e4));
13850
+ if (minutes < 1) return "Updated just now";
13851
+ if (minutes < 60) return `Updated ${minutes}m ago`;
13852
+ const hours = Math.round(minutes / 60);
13853
+ if (hours < 36) return `Updated ${hours}h ago`;
13854
+ return `Updated ${formatClaudeUsageResetClock(fetchedAt)}`;
13855
+ }
13856
+ function formatClaudeExtraUsageDetail(extra) {
13857
+ if (!extra.enabled) return "Extra usage off";
13858
+ const bits = ["Extra usage on"];
13859
+ if (extra.usedCredits != null && extra.monthlyLimit != null) {
13860
+ bits.push(`${extra.usedCredits} / ${extra.monthlyLimit} credits this month`);
13861
+ } else if (extra.usedCredits != null) {
13862
+ bits.push(`${extra.usedCredits} credits used`);
13863
+ }
13864
+ if (extra.usedPercent != null) {
13865
+ bits.push(`${Math.round(extra.usedPercent)}% of extra pool`);
13866
+ }
13867
+ return bits.join(" \xB7 ");
13868
+ }
13869
+ function formatClaudeUsageWindowLine(window, now = /* @__PURE__ */ new Date()) {
13870
+ const reset = formatClaudeUsageReset(window.resetsAt, now);
13871
+ const clock = formatClaudeUsageResetClock(window.resetsAt);
13872
+ const left = `${Math.round(window.remainingPercent)}% left`;
13873
+ const used = `${Math.round(window.usedPercent)}% used`;
13874
+ const resetBit = reset ? clock && !reset.includes(clock) ? `${reset} (${clock})` : reset : "";
13875
+ return resetBit ? `${window.label} \u2014 ${window.detail}. ${left} \xB7 ${used} \xB7 ${resetBit}` : `${window.label} \u2014 ${window.detail}. ${left} \xB7 ${used}`;
13876
+ }
13877
+ function formatClaudeUsageTooltip(usage, now = /* @__PURE__ */ new Date()) {
13878
+ const lines = [
13879
+ "Claude Code plan",
13880
+ ...usage.windows.map((w) => formatClaudeUsageWindowLine(w, now))
13881
+ ];
13882
+ if (usage.extraUsage) {
13883
+ lines.push(formatClaudeExtraUsageDetail(usage.extraUsage));
13884
+ }
13885
+ const fetched = formatClaudeUsageFetchedAt(usage.fetchedAt, now);
13886
+ if (fetched) lines.push(fetched);
13887
+ return lines.join("\n");
13888
+ }
13889
+ function formatClaudeUsageCompact(window) {
13890
+ return `${window.shortLabel} ${Math.round(window.remainingPercent)}%`;
13891
+ }
13892
+ function claudeUsageWindowOverLimit(window) {
13893
+ return window.remainingPercent <= 0 || window.usedPercent >= 100;
13894
+ }
13895
+ function claudeUsageOverLimitWindows(usage) {
13896
+ if (!usage) return [];
13897
+ return usage.windows.filter(claudeUsageWindowOverLimit);
13898
+ }
13899
+ function formatOverLimitWindowList(windows, now) {
13900
+ const parts = windows.map((w) => {
13901
+ const reset = formatClaudeUsageReset(w.resetsAt, now);
13902
+ return reset ? `${w.label} (${reset})` : w.label;
13903
+ });
13904
+ return {
13905
+ list: parts.join(", "),
13906
+ verb: windows.length === 1 ? "is" : "are"
13907
+ };
13908
+ }
13909
+ function formatClaudeUsageOverLimitConfirm(windows, now = /* @__PURE__ */ new Date()) {
13910
+ if (windows.length === 0) return "";
13911
+ const { list, verb } = formatOverLimitWindowList(windows, now);
13912
+ return `Claude Code ${list} ${verb} at or over the plan limit. Send this message anyway?`;
13913
+ }
13914
+ function formatClaudeUsageOverLimitWait(windows, now = /* @__PURE__ */ new Date()) {
13915
+ if (windows.length === 0) return "";
13916
+ const { list, verb } = formatOverLimitWindowList(windows, now);
13917
+ return `Claude Code ${list} ${verb} at or over the plan limit. Sending is paused until the window resets.`;
13918
+ }
13919
+ var WINDOW_META, WINDOW_ORDER;
13920
+ var init_claude_usage = __esm({
13921
+ "src/agents/claude-usage.ts"() {
13922
+ "use strict";
13923
+ WINDOW_META = {
13924
+ five_hour: {
13925
+ label: "5-hour session",
13926
+ shortLabel: "5h",
13927
+ detail: "Rolling 5-hour limit across all models"
13928
+ },
13929
+ seven_day: {
13930
+ label: "Weekly",
13931
+ shortLabel: "wk",
13932
+ detail: "7-day cap across all models"
13933
+ },
13934
+ seven_day_opus: {
13935
+ label: "Opus",
13936
+ shortLabel: "Opus",
13937
+ detail: "Weekly Opus-only cap"
13938
+ },
13939
+ seven_day_sonnet: {
13940
+ label: "Sonnet",
13941
+ shortLabel: "Sonnet",
13942
+ detail: "Weekly Sonnet-only cap"
13943
+ }
13944
+ };
13945
+ WINDOW_ORDER = [
13946
+ "five_hour",
13947
+ "seven_day",
13948
+ "seven_day_opus",
13949
+ "seven_day_sonnet"
13950
+ ];
13951
+ }
13952
+ });
13953
+
13954
+ // src/agents/claude-usage-client.ts
13955
+ function accessTokenFromCredentialsJson(raw) {
13956
+ const trimmed = raw.trim();
13957
+ if (!trimmed) return null;
13958
+ if (trimmed.startsWith("sk-ant-")) {
13959
+ const token = trimmed.split(/\s+/)[0];
13960
+ return token || null;
13961
+ }
13962
+ try {
13963
+ const parsed = JSON.parse(trimmed);
13964
+ const oauth = parsed.claudeAiOauth && typeof parsed.claudeAiOauth === "object" ? parsed.claudeAiOauth : parsed;
13965
+ const token = oauth.accessToken ?? oauth.access_token;
13966
+ return typeof token === "string" && token.trim() ? token.trim() : null;
13967
+ } catch {
13968
+ return null;
13969
+ }
13970
+ }
13971
+ function claudeCredentialsPath() {
13972
+ const root = process.env.CLAUDE_CONFIG_DIR?.trim() || (0, import_node_path37.join)((0, import_node_os13.homedir)(), ".claude");
13973
+ return (0, import_node_path37.join)(root, ".credentials.json");
13974
+ }
13975
+ async function readFileAccessToken() {
13976
+ const path2 = claudeCredentialsPath();
13977
+ if (!(0, import_node_fs37.existsSync)(path2)) return null;
13978
+ try {
13979
+ return accessTokenFromCredentialsJson((0, import_node_fs37.readFileSync)(path2, "utf8"));
13980
+ } catch {
13981
+ return null;
13982
+ }
13983
+ }
13984
+ async function readKeychainAccessToken() {
13985
+ if (process.platform !== "darwin") return null;
13986
+ for (const service of KEYCHAIN_SERVICES) {
13987
+ const result = await run("security", ["find-generic-password", "-s", service, "-w"], {
13988
+ reject: false,
13989
+ timeoutMs: 4e3
13990
+ });
13991
+ if (result.exitCode !== 0 || !result.stdout.trim()) continue;
13992
+ const token = accessTokenFromCredentialsJson(result.stdout);
13993
+ if (token) return token;
13994
+ }
13995
+ return null;
13996
+ }
13997
+ async function readClaudeAccessToken() {
13998
+ const envToken = process.env.CLAUDE_CODE_OAUTH_TOKEN?.trim();
13999
+ if (envToken) return envToken;
14000
+ const fromFile = await readFileAccessToken();
14001
+ if (fromFile) return fromFile;
14002
+ return readKeychainAccessToken();
14003
+ }
14004
+ async function resolveClaudeUserAgent() {
14005
+ if (claudeVersion) return `claude-code/${claudeVersion}`;
14006
+ try {
14007
+ const claude = resolveClaudeExecutable();
14008
+ const result = await run(claude, ["--version"], { reject: false, timeoutMs: 4e3 });
14009
+ const match = `${result.stdout}
14010
+ ${result.stderr}`.match(/(\d+\.\d+\.\d+)/);
14011
+ claudeVersion = match?.[1] ?? "2.1.80";
14012
+ } catch {
14013
+ claudeVersion = "2.1.80";
14014
+ }
14015
+ return `claude-code/${claudeVersion}`;
14016
+ }
14017
+ function staleOk(now) {
14018
+ if (!lastGood) return null;
14019
+ if (now - lastGood.at > CLAUDE_USAGE_STALE_OK_MS) return null;
14020
+ return lastGood.value;
14021
+ }
14022
+ async function getClaudePlanUsage(opts = {}) {
14023
+ const now = opts.now ?? Date.now();
14024
+ if (!opts.force) {
14025
+ if (cache && now - cache.at < CLAUDE_USAGE_TTL_MS) return cache.value;
14026
+ if (now < errorUntil) return staleOk(now);
14027
+ }
14028
+ if (inflight) return inflight;
14029
+ inflight = (async () => {
14030
+ try {
14031
+ const token = await (opts.readAccessToken ?? readClaudeAccessToken)();
14032
+ if (!token) {
14033
+ cache = { at: now, value: null };
14034
+ return null;
14035
+ }
14036
+ const fetchFn = opts.fetch ?? httpFetch;
14037
+ const userAgent = opts.userAgent ?? await resolveClaudeUserAgent();
14038
+ const ac = new AbortController();
14039
+ const timer = setTimeout(() => ac.abort(), 8e3);
14040
+ let res;
14041
+ try {
14042
+ res = await fetchFn(CLAUDE_OAUTH_USAGE_URL, {
14043
+ headers: {
14044
+ Authorization: `Bearer ${token}`,
14045
+ "anthropic-beta": "oauth-2025-04-20",
14046
+ "User-Agent": userAgent
14047
+ },
14048
+ signal: ac.signal
14049
+ });
14050
+ } finally {
14051
+ clearTimeout(timer);
14052
+ }
14053
+ if (res.status === 401 || res.status === 403) {
14054
+ cache = { at: now, value: null };
14055
+ return null;
14056
+ }
14057
+ if (!res.ok) {
14058
+ errorUntil = now + CLAUDE_USAGE_ERROR_TTL_MS;
14059
+ return staleOk(now);
14060
+ }
14061
+ const usage = parseClaudeUsagePayload(await res.json(), new Date(now).toISOString());
14062
+ cache = { at: now, value: usage };
14063
+ if (usage) lastGood = { at: now, value: usage };
14064
+ return usage;
14065
+ } catch {
14066
+ errorUntil = now + CLAUDE_USAGE_ERROR_TTL_MS;
14067
+ return staleOk(now);
14068
+ } finally {
14069
+ inflight = null;
14070
+ }
14071
+ })();
14072
+ return inflight;
14073
+ }
14074
+ var import_node_fs37, import_node_os13, import_node_path37, CLAUDE_OAUTH_USAGE_URL, CLAUDE_USAGE_TTL_MS, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS, KEYCHAIN_SERVICES, cache, errorUntil, inflight, lastGood, claudeVersion;
14075
+ var init_claude_usage_client = __esm({
14076
+ "src/agents/claude-usage-client.ts"() {
14077
+ "use strict";
14078
+ import_node_fs37 = require("fs");
14079
+ import_node_os13 = require("os");
14080
+ import_node_path37 = require("path");
14081
+ init_run();
14082
+ init_fetch();
14083
+ init_app_settings();
14084
+ init_claude_usage();
14085
+ CLAUDE_OAUTH_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
14086
+ CLAUDE_USAGE_TTL_MS = 9e4;
14087
+ CLAUDE_USAGE_ERROR_TTL_MS = 5 * 6e4;
14088
+ CLAUDE_USAGE_STALE_OK_MS = 30 * 6e4;
14089
+ KEYCHAIN_SERVICES = ["Claude Code-credentials", "Claude Code"];
14090
+ cache = null;
14091
+ errorUntil = 0;
14092
+ inflight = null;
14093
+ lastGood = null;
14094
+ claudeVersion = null;
14095
+ }
14096
+ });
14097
+
13677
14098
  // src/agents/install.ts
13678
14099
  function getAgentSetupInfo(agent) {
13679
14100
  return SETUP[agent];
@@ -13922,6 +14343,7 @@ __export(agents_exports, {
13922
14343
  assertOrchestratorCapableAgent: () => assertOrchestratorCapableAgent,
13923
14344
  brightsyAdapter: () => brightsyAdapter,
13924
14345
  claudeAdapter: () => claudeAdapter,
14346
+ claudeUsageOverLimitWindows: () => claudeUsageOverLimitWindows,
13925
14347
  codexAdapter: () => codexAdapter,
13926
14348
  coerceOrchestratorAgent: () => coerceOrchestratorAgent,
13927
14349
  conductorBundledBinDir: () => conductorBundledBinDir,
@@ -13931,8 +14353,18 @@ __export(agents_exports, {
13931
14353
  encodeBrightsyTarget: () => encodeBrightsyTarget,
13932
14354
  enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
13933
14355
  ensureAgentPath: () => ensureAgentPath,
14356
+ formatClaudeExtraUsageDetail: () => formatClaudeExtraUsageDetail,
14357
+ formatClaudeUsageCompact: () => formatClaudeUsageCompact,
14358
+ formatClaudeUsageFetchedAt: () => formatClaudeUsageFetchedAt,
14359
+ formatClaudeUsageOverLimitConfirm: () => formatClaudeUsageOverLimitConfirm,
14360
+ formatClaudeUsageOverLimitWait: () => formatClaudeUsageOverLimitWait,
14361
+ formatClaudeUsageReset: () => formatClaudeUsageReset,
14362
+ formatClaudeUsageResetClock: () => formatClaudeUsageResetClock,
14363
+ formatClaudeUsageTooltip: () => formatClaudeUsageTooltip,
13934
14364
  getAdapter: () => getAdapter,
13935
14365
  getAgentSetupInfo: () => getAgentSetupInfo,
14366
+ getClaudePlanUsage: () => getClaudePlanUsage,
14367
+ hottestClaudeWindow: () => hottestClaudeWindow,
13936
14368
  installAgent: () => installAgent,
13937
14369
  installNpmGlobalPackage: () => installNpmGlobalPackage,
13938
14370
  isConductorBundledCli: () => isConductorBundledCli,
@@ -13950,6 +14382,7 @@ __export(agents_exports, {
13950
14382
  mcpStatusThinkingFromClaudeInit: () => mcpStatusThinkingFromClaudeInit,
13951
14383
  openInSystemTerminal: () => openInSystemTerminal,
13952
14384
  opencodeAdapter: () => opencodeAdapter,
14385
+ parseClaudeUsagePayload: () => parseClaudeUsagePayload,
13953
14386
  parseCursorRunnerLine: () => parseCursorRunnerLine,
13954
14387
  parseSessionQuotaResetAt: () => parseSessionQuotaResetAt,
13955
14388
  permissionMode: () => permissionMode,
@@ -13990,6 +14423,8 @@ var init_agents = __esm({
13990
14423
  init_opencode();
13991
14424
  init_list_models();
13992
14425
  init_session_quota();
14426
+ init_claude_usage();
14427
+ init_claude_usage_client();
13993
14428
  init_orchestrator_capable();
13994
14429
  init_path();
13995
14430
  init_install();
@@ -14005,15 +14440,15 @@ var init_agents = __esm({
14005
14440
 
14006
14441
  // src/hook/worktree-pkg-cache.ts
14007
14442
  function worktreePkgCacheRoot(worktreePath) {
14008
- return (0, import_node_path37.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
14443
+ return (0, import_node_path38.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
14009
14444
  }
14010
14445
  function worktreePkgCacheEnv(worktreePath) {
14011
14446
  const root = worktreePkgCacheRoot(worktreePath);
14012
- const store = (0, import_node_path37.join)(root, "pnpm-store");
14013
- const pnpmCache = (0, import_node_path37.join)(root, "pnpm");
14014
- const npmCache = (0, import_node_path37.join)(root, "npm");
14015
- const nodeGyp = (0, import_node_path37.join)(root, "node-gyp");
14016
- const electron = (0, import_node_path37.join)(root, "electron");
14447
+ const store = (0, import_node_path38.join)(root, "pnpm-store");
14448
+ const pnpmCache = (0, import_node_path38.join)(root, "pnpm");
14449
+ const npmCache = (0, import_node_path38.join)(root, "npm");
14450
+ const nodeGyp = (0, import_node_path38.join)(root, "node-gyp");
14451
+ const electron = (0, import_node_path38.join)(root, "electron");
14017
14452
  return {
14018
14453
  npm_config_store_dir: store,
14019
14454
  PNPM_STORE_DIR: store,
@@ -14035,8 +14470,8 @@ function fillGroup(env, keys, values) {
14035
14470
  }
14036
14471
  }
14037
14472
  function ensureWorktreePkgCacheDirs(worktreePath) {
14038
- if (!(0, import_node_fs37.existsSync)(worktreePath)) return;
14039
- (0, import_node_fs37.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
14473
+ if (!(0, import_node_fs38.existsSync)(worktreePath)) return;
14474
+ (0, import_node_fs38.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
14040
14475
  }
14041
14476
  function applyWorktreePkgCacheEnv(env, worktreePath) {
14042
14477
  const cwd = worktreePath.trim();
@@ -14049,12 +14484,12 @@ function applyWorktreePkgCacheEnv(env, worktreePath) {
14049
14484
  fillGroup(env, ["electron_config_cache"], next);
14050
14485
  ensureWorktreePkgCacheDirs(cwd);
14051
14486
  }
14052
- var import_node_fs37, import_node_path37, WORKTREE_PKG_CACHE_REL;
14487
+ var import_node_fs38, import_node_path38, WORKTREE_PKG_CACHE_REL;
14053
14488
  var init_worktree_pkg_cache = __esm({
14054
14489
  "src/hook/worktree-pkg-cache.ts"() {
14055
14490
  "use strict";
14056
- import_node_fs37 = require("fs");
14057
- import_node_path37 = require("path");
14491
+ import_node_fs38 = require("fs");
14492
+ import_node_path38 = require("path");
14058
14493
  WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
14059
14494
  }
14060
14495
  });
@@ -15213,21 +15648,21 @@ function shouldRefreshReviewRequestTemplate(content) {
15213
15648
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
15214
15649
  }
15215
15650
  function readTextIfPresent(abs) {
15216
- if (!(0, import_node_fs38.existsSync)(abs)) return null;
15651
+ if (!(0, import_node_fs39.existsSync)(abs)) return null;
15217
15652
  try {
15218
- const content = (0, import_node_fs38.readFileSync)(abs, "utf8");
15653
+ const content = (0, import_node_fs39.readFileSync)(abs, "utf8");
15219
15654
  return content.trim() ? content : null;
15220
15655
  } catch {
15221
15656
  return null;
15222
15657
  }
15223
15658
  }
15224
15659
  function readLocalGuidelines(worktreePath) {
15225
- const localAbs = (0, import_node_path38.join)(worktreePath, REVIEW_REQUEST_PATH);
15660
+ const localAbs = (0, import_node_path39.join)(worktreePath, REVIEW_REQUEST_PATH);
15226
15661
  const localContent = readTextIfPresent(localAbs);
15227
15662
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
15228
15663
  return { path: REVIEW_REQUEST_PATH, content: localContent };
15229
15664
  }
15230
- const legacyAbs = (0, import_node_path38.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
15665
+ const legacyAbs = (0, import_node_path39.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
15231
15666
  const legacyContent = readTextIfPresent(legacyAbs);
15232
15667
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
15233
15668
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -15251,27 +15686,27 @@ function contextGuidelines(content, source) {
15251
15686
  };
15252
15687
  }
15253
15688
  function writeContextGuidelines(worktreePath, content) {
15254
- const abs = (0, import_node_path38.join)(worktreePath, CONTEXT_REVIEW_PATH);
15255
- (0, import_node_fs38.mkdirSync)((0, import_node_path38.dirname)(abs), { recursive: true });
15689
+ const abs = (0, import_node_path39.join)(worktreePath, CONTEXT_REVIEW_PATH);
15690
+ (0, import_node_fs39.mkdirSync)((0, import_node_path39.dirname)(abs), { recursive: true });
15256
15691
  const body = content.endsWith("\n") ? content : `${content}
15257
15692
  `;
15258
- (0, import_node_fs38.writeFileSync)(abs, body, "utf8");
15693
+ (0, import_node_fs39.writeFileSync)(abs, body, "utf8");
15259
15694
  return body;
15260
15695
  }
15261
15696
  function readSideboardReview(worktreePath, repoPath) {
15262
- const fromWorktree = readTextIfPresent((0, import_node_path38.join)(worktreePath, REPO_REVIEW_PATH));
15697
+ const fromWorktree = readTextIfPresent((0, import_node_path39.join)(worktreePath, REPO_REVIEW_PATH));
15263
15698
  if (fromWorktree) return fromWorktree;
15264
15699
  const repo = repoPath?.replace(/\/+$/, "");
15265
15700
  const wt = worktreePath.replace(/\/+$/, "");
15266
15701
  if (!repo || repo === wt) return null;
15267
- return readTextIfPresent((0, import_node_path38.join)(repo, REPO_REVIEW_PATH));
15702
+ return readTextIfPresent((0, import_node_path39.join)(repo, REPO_REVIEW_PATH));
15268
15703
  }
15269
15704
  function ensureReviewGuidelinesFile(worktreePath, repoPath) {
15270
- const skillContent = readTextIfPresent((0, import_node_path38.join)(worktreePath, REVIEW_SKILL_PATH));
15705
+ const skillContent = readTextIfPresent((0, import_node_path39.join)(worktreePath, REVIEW_SKILL_PATH));
15271
15706
  if (skillContent) {
15272
15707
  return { ...skillGuidelines(skillContent, "skill"), wrote: false };
15273
15708
  }
15274
- const contextContent = readTextIfPresent((0, import_node_path38.join)(worktreePath, CONTEXT_REVIEW_PATH));
15709
+ const contextContent = readTextIfPresent((0, import_node_path39.join)(worktreePath, CONTEXT_REVIEW_PATH));
15275
15710
  if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
15276
15711
  return { ...contextGuidelines(contextContent, "local"), wrote: false };
15277
15712
  }
@@ -15309,7 +15744,7 @@ function buildReviewRequestAttachment(content, opts) {
15309
15744
  };
15310
15745
  }
15311
15746
  function readExistingReviewRequestFile(worktreePath) {
15312
- return readTextIfPresent((0, import_node_path38.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path38.join)(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path38.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path38.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path38.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
15747
+ return readTextIfPresent((0, import_node_path39.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path39.join)(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path39.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path39.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path39.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
15313
15748
  }
15314
15749
  async function requestReview(threadRef, send2) {
15315
15750
  const from = findThreadByRef(threadRef);
@@ -15336,13 +15771,13 @@ async function requestReview(threadRef, send2) {
15336
15771
  const started = await send2(tab.id, REVIEW_REQUEST_PREFILL);
15337
15772
  return { tab: started, from };
15338
15773
  }
15339
- var import_node_crypto9, import_node_fs38, import_node_path38, REPO_REVIEW_PATH, REPO_REVIEW_NAME, CONTEXT_REVIEW_PATH, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
15774
+ var import_node_crypto9, import_node_fs39, import_node_path39, REPO_REVIEW_PATH, REPO_REVIEW_NAME, CONTEXT_REVIEW_PATH, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
15340
15775
  var init_request_review = __esm({
15341
15776
  "src/review/request-review.ts"() {
15342
15777
  "use strict";
15343
15778
  import_node_crypto9 = require("crypto");
15344
- import_node_fs38 = require("fs");
15345
- import_node_path38 = require("path");
15779
+ import_node_fs39 = require("fs");
15780
+ import_node_path39 = require("path");
15346
15781
  init_global_workspace();
15347
15782
  init_chat_tabs();
15348
15783
  init_thread_store();
@@ -15368,9 +15803,9 @@ function matchSimpleGlob(pattern, name) {
15368
15803
  return new RegExp(`^${escaped}$`).test(name);
15369
15804
  }
15370
15805
  function readWorktreeInclude(repoPath) {
15371
- const path2 = (0, import_node_path39.join)(repoPath, ".worktreeinclude");
15372
- if (!(0, import_node_fs39.existsSync)(path2)) return [];
15373
- return (0, import_node_fs39.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
15806
+ const path2 = (0, import_node_path40.join)(repoPath, ".worktreeinclude");
15807
+ if (!(0, import_node_fs40.existsSync)(path2)) return [];
15808
+ return (0, import_node_fs40.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
15374
15809
  }
15375
15810
  function resolveFilesToCopy(repoPath) {
15376
15811
  const fromInclude = readWorktreeInclude(repoPath);
@@ -15380,10 +15815,10 @@ function resolveFilesToCopy(repoPath) {
15380
15815
  if (settings?.fileIncludeGlobs?.length) {
15381
15816
  const matched = [];
15382
15817
  try {
15383
- for (const entry of (0, import_node_fs39.readdirSync)(repoPath, { withFileTypes: true })) {
15818
+ for (const entry of (0, import_node_fs40.readdirSync)(repoPath, { withFileTypes: true })) {
15384
15819
  if (!entry.isFile()) continue;
15385
15820
  for (const glob of settings.fileIncludeGlobs) {
15386
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path39.basename)(glob), entry.name)) {
15821
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path40.basename)(glob), entry.name)) {
15387
15822
  matched.push(entry.name);
15388
15823
  break;
15389
15824
  }
@@ -15395,7 +15830,7 @@ function resolveFilesToCopy(repoPath) {
15395
15830
  }
15396
15831
  const defaults = [];
15397
15832
  try {
15398
- for (const entry of (0, import_node_fs39.readdirSync)(repoPath, { withFileTypes: true })) {
15833
+ for (const entry of (0, import_node_fs40.readdirSync)(repoPath, { withFileTypes: true })) {
15399
15834
  if (entry.isFile() && entry.name.startsWith(".env")) {
15400
15835
  defaults.push(entry.name);
15401
15836
  }
@@ -15409,11 +15844,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
15409
15844
  const patterns = resolveFilesToCopy(repoPath);
15410
15845
  const copied = [];
15411
15846
  for (const rel of patterns) {
15412
- const src = (0, import_node_path39.join)(repoPath, rel);
15413
- if (!(0, import_node_fs39.existsSync)(src)) continue;
15414
- const dest = (0, import_node_path39.join)(worktreePath, rel);
15415
- (0, import_node_fs39.mkdirSync)((0, import_node_path39.dirname)(dest), { recursive: true });
15416
- (0, import_node_fs39.copyFileSync)(src, dest);
15847
+ const src = (0, import_node_path40.join)(repoPath, rel);
15848
+ if (!(0, import_node_fs40.existsSync)(src)) continue;
15849
+ const dest = (0, import_node_path40.join)(worktreePath, rel);
15850
+ (0, import_node_fs40.mkdirSync)((0, import_node_path40.dirname)(dest), { recursive: true });
15851
+ (0, import_node_fs40.copyFileSync)(src, dest);
15417
15852
  copied.push(rel);
15418
15853
  }
15419
15854
  return copied;
@@ -15448,7 +15883,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
15448
15883
  const env = stripNestedElectronEnv({
15449
15884
  ...baseEnv ?? process.env
15450
15885
  });
15451
- const name = opts.workspaceName ?? (0, import_node_path39.basename)(opts.worktreePath);
15886
+ const name = opts.workspaceName ?? (0, import_node_path40.basename)(opts.worktreePath);
15452
15887
  const ports = opts.ports ?? [];
15453
15888
  const primary = ports[0];
15454
15889
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -15711,13 +16146,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
15711
16146
  done: handle.done
15712
16147
  };
15713
16148
  }
15714
- var import_node_fs39, import_node_net, import_node_path39, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
16149
+ var import_node_fs40, import_node_net, import_node_path40, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
15715
16150
  var init_conductor = __esm({
15716
16151
  "src/hook/conductor.ts"() {
15717
16152
  "use strict";
15718
- import_node_fs39 = require("fs");
16153
+ import_node_fs40 = require("fs");
15719
16154
  import_node_net = require("net");
15720
- import_node_path39 = require("path");
16155
+ import_node_path40 = require("path");
15721
16156
  import_execa4 = require("execa");
15722
16157
  import_node_readline3 = require("readline");
15723
16158
  init_settings();
@@ -15745,9 +16180,9 @@ async function findOrphanWorktrees(repoPaths) {
15745
16180
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
15746
16181
  );
15747
16182
  const homeRoot = sideboardWorkspacesDir();
15748
- if ((0, import_node_fs40.existsSync)(homeRoot)) {
16183
+ if ((0, import_node_fs41.existsSync)(homeRoot)) {
15749
16184
  try {
15750
- for (const entry of (0, import_node_fs40.readdirSync)(homeRoot, { withFileTypes: true })) {
16185
+ for (const entry of (0, import_node_fs41.readdirSync)(homeRoot, { withFileTypes: true })) {
15751
16186
  if (!entry.isDirectory()) continue;
15752
16187
  void entry;
15753
16188
  }
@@ -15757,7 +16192,7 @@ async function findOrphanWorktrees(repoPaths) {
15757
16192
  const orphans = [];
15758
16193
  const seen = /* @__PURE__ */ new Set();
15759
16194
  for (const repoPath of repos) {
15760
- if (!repoPath || !(0, import_node_fs40.existsSync)(repoPath)) continue;
16195
+ if (!repoPath || !(0, import_node_fs41.existsSync)(repoPath)) continue;
15761
16196
  try {
15762
16197
  const wts = await listWorktrees(repoPath);
15763
16198
  for (const wt of wts) {
@@ -15768,7 +16203,7 @@ async function findOrphanWorktrees(repoPaths) {
15768
16203
  seen.add(path2);
15769
16204
  let mtimeMs = 0;
15770
16205
  try {
15771
- mtimeMs = (0, import_node_fs40.statSync)(path2).mtimeMs;
16206
+ mtimeMs = (0, import_node_fs41.statSync)(path2).mtimeMs;
15772
16207
  } catch {
15773
16208
  mtimeMs = 0;
15774
16209
  }
@@ -15778,16 +16213,16 @@ async function findOrphanWorktrees(repoPaths) {
15778
16213
  }
15779
16214
  try {
15780
16215
  const root = worktreesRoot(repoPath);
15781
- if ((0, import_node_fs40.existsSync)(root)) {
15782
- for (const entry of (0, import_node_fs40.readdirSync)(root, { withFileTypes: true })) {
16216
+ if ((0, import_node_fs41.existsSync)(root)) {
16217
+ for (const entry of (0, import_node_fs41.readdirSync)(root, { withFileTypes: true })) {
15783
16218
  if (!entry.isDirectory()) continue;
15784
- const path2 = (0, import_node_path40.join)(root, entry.name).replace(/\/$/, "");
16219
+ const path2 = (0, import_node_path41.join)(root, entry.name).replace(/\/$/, "");
15785
16220
  if (known.has(path2) || seen.has(path2)) continue;
15786
- if (!(0, import_node_fs40.existsSync)((0, import_node_path40.join)(path2, ".git"))) continue;
16221
+ if (!(0, import_node_fs41.existsSync)((0, import_node_path41.join)(path2, ".git"))) continue;
15787
16222
  seen.add(path2);
15788
16223
  let mtimeMs = 0;
15789
16224
  try {
15790
- mtimeMs = (0, import_node_fs40.statSync)(path2).mtimeMs;
16225
+ mtimeMs = (0, import_node_fs41.statSync)(path2).mtimeMs;
15791
16226
  } catch {
15792
16227
  mtimeMs = Date.now();
15793
16228
  }
@@ -15848,12 +16283,12 @@ function worktreeCleanupSettings() {
15848
16283
  autoCleanupOrphans: a.autoCleanupOrphans
15849
16284
  };
15850
16285
  }
15851
- var import_node_fs40, import_node_path40;
16286
+ var import_node_fs41, import_node_path41;
15852
16287
  var init_orphan_cleanup = __esm({
15853
16288
  "src/git/orphan-cleanup.ts"() {
15854
16289
  "use strict";
15855
- import_node_fs40 = require("fs");
15856
- import_node_path40 = require("path");
16290
+ import_node_fs41 = require("fs");
16291
+ import_node_path41 = require("path");
15857
16292
  init_worktree();
15858
16293
  init_thread_store();
15859
16294
  init_paths();
@@ -15956,12 +16391,12 @@ async function cloneRepoIntoSideboard(opts) {
15956
16391
  if (!url) throw new Error("Clone URL is required");
15957
16392
  let name = opts.name?.trim();
15958
16393
  if (!name) {
15959
- const leaf = (0, import_node_path41.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
16394
+ const leaf = (0, import_node_path42.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
15960
16395
  name = leaf || "repo";
15961
16396
  }
15962
16397
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
15963
- const dest = (0, import_node_path41.join)(sideboardReposDir(), name);
15964
- if ((0, import_node_fs41.existsSync)(dest)) {
16398
+ const dest = (0, import_node_path42.join)(sideboardReposDir(), name);
16399
+ if ((0, import_node_fs42.existsSync)(dest)) {
15965
16400
  const repoPath2 = await resolveRepoRoot(dest);
15966
16401
  const workspace2 = await ensureWorkspace(repoPath2);
15967
16402
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -15976,12 +16411,12 @@ async function cloneRepoIntoSideboard(opts) {
15976
16411
  const workspace = await ensureWorkspace(repoPath);
15977
16412
  return { repoPath, workspace };
15978
16413
  }
15979
- var import_node_fs41, import_node_path41, import_execa6;
16414
+ var import_node_fs42, import_node_path42, import_execa6;
15980
16415
  var init_clone_repo = __esm({
15981
16416
  "src/git/clone-repo.ts"() {
15982
16417
  "use strict";
15983
- import_node_fs41 = require("fs");
15984
- import_node_path41 = require("path");
16418
+ import_node_fs42 = require("fs");
16419
+ import_node_path42 = require("path");
15985
16420
  import_execa6 = require("execa");
15986
16421
  init_paths();
15987
16422
  init_workspaces();
@@ -16099,24 +16534,24 @@ function jobTreeAlive(pid) {
16099
16534
  return jobAlive(pid) || processGroupAlive(pid);
16100
16535
  }
16101
16536
  function readIntFile(file) {
16102
- if (!(0, import_node_fs42.existsSync)(file)) return null;
16103
- const n = Number.parseInt((0, import_node_fs42.readFileSync)(file, "utf8").trim(), 10);
16537
+ if (!(0, import_node_fs43.existsSync)(file)) return null;
16538
+ const n = Number.parseInt((0, import_node_fs43.readFileSync)(file, "utf8").trim(), 10);
16104
16539
  return Number.isInteger(n) ? n : null;
16105
16540
  }
16106
16541
  function jobDir(root, id, legacy = false) {
16107
- return (0, import_node_path42.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
16542
+ return (0, import_node_path43.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
16108
16543
  }
16109
16544
  function resolveJobDir(root, id) {
16110
16545
  const modern = jobDir(root, id, false);
16111
- if ((0, import_node_fs42.existsSync)(modern)) return modern;
16546
+ if ((0, import_node_fs43.existsSync)(modern)) return modern;
16112
16547
  const legacy = jobDir(root, id, true);
16113
- if ((0, import_node_fs42.existsSync)(legacy)) return legacy;
16548
+ if ((0, import_node_fs43.existsSync)(legacy)) return legacy;
16114
16549
  return modern;
16115
16550
  }
16116
16551
  function listJobIdsIn(root, rel) {
16117
- const dir = (0, import_node_path42.join)(root, rel);
16118
- if (!(0, import_node_fs42.existsSync)(dir)) return [];
16119
- return (0, import_node_fs42.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
16552
+ const dir = (0, import_node_path43.join)(root, rel);
16553
+ if (!(0, import_node_fs43.existsSync)(dir)) return [];
16554
+ return (0, import_node_fs43.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
16120
16555
  }
16121
16556
  function listRunningDetachedJobs(worktreePath) {
16122
16557
  const root = worktreePath.trim();
@@ -16128,7 +16563,7 @@ function listRunningDetachedJobs(worktreePath) {
16128
16563
  const running = [];
16129
16564
  for (const id of ids) {
16130
16565
  const dir = resolveJobDir(root, id);
16131
- const pid = readIntFile((0, import_node_path42.join)(dir, "pid"));
16566
+ const pid = readIntFile((0, import_node_path43.join)(dir, "pid"));
16132
16567
  if (jobTreeAlive(pid)) running.push(id);
16133
16568
  }
16134
16569
  return running.sort();
@@ -16210,8 +16645,8 @@ function planJobContinue(opts) {
16210
16645
  return { action: "none" };
16211
16646
  }
16212
16647
  function tailProgress(logFile, maxLines = 12) {
16213
- if (!(0, import_node_fs42.existsSync)(logFile)) return "(no log yet)";
16214
- const lines = (0, import_node_fs42.readFileSync)(logFile, "utf8").split("\n");
16648
+ if (!(0, import_node_fs43.existsSync)(logFile)) return "(no log yet)";
16649
+ const lines = (0, import_node_fs43.readFileSync)(logFile, "utf8").split("\n");
16215
16650
  return lines.slice(-maxLines).join("\n");
16216
16651
  }
16217
16652
  function lastProgressLine(progress) {
@@ -16219,8 +16654,8 @@ function lastProgressLine(progress) {
16219
16654
  return last ? last.slice(0, 72) : void 0;
16220
16655
  }
16221
16656
  function readLogLines(file) {
16222
- if (!(0, import_node_fs42.existsSync)(file)) return [];
16223
- const lines = (0, import_node_fs42.readFileSync)(file, "utf8").split("\n");
16657
+ if (!(0, import_node_fs43.existsSync)(file)) return [];
16658
+ const lines = (0, import_node_fs43.readFileSync)(file, "utf8").split("\n");
16224
16659
  if (lines.length && lines[lines.length - 1] === "") lines.pop();
16225
16660
  return lines;
16226
16661
  }
@@ -16231,15 +16666,15 @@ function takeDelta(logFile, cursorFile) {
16231
16666
  return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
16232
16667
  }
16233
16668
  function snapshotJob(dir) {
16234
- const pid = readIntFile((0, import_node_path42.join)(dir, "pid"));
16669
+ const pid = readIntFile((0, import_node_path43.join)(dir, "pid"));
16235
16670
  const running = jobTreeAlive(pid);
16236
16671
  return {
16237
16672
  pid,
16238
16673
  running,
16239
- exitCode: readIntFile((0, import_node_path42.join)(dir, "exit")),
16240
- log: (0, import_node_path42.join)(dir, "log"),
16241
- cursor: (0, import_node_path42.join)(dir, "present.cursor"),
16242
- progress: tailProgress((0, import_node_path42.join)(dir, "log"))
16674
+ exitCode: readIntFile((0, import_node_path43.join)(dir, "exit")),
16675
+ log: (0, import_node_path43.join)(dir, "log"),
16676
+ cursor: (0, import_node_path43.join)(dir, "present.cursor"),
16677
+ progress: tailProgress((0, import_node_path43.join)(dir, "log"))
16243
16678
  };
16244
16679
  }
16245
16680
  function toResult(id, snap, extra) {
@@ -16248,8 +16683,8 @@ function toResult(id, snap, extra) {
16248
16683
  const stillRunning = snap.running && !ok;
16249
16684
  const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
16250
16685
  try {
16251
- (0, import_node_fs42.mkdirSync)((0, import_node_path42.dirname)(snap.cursor), { recursive: true });
16252
- (0, import_node_fs42.writeFileSync)(snap.cursor, `${nextCursor}
16686
+ (0, import_node_fs43.mkdirSync)((0, import_node_path43.dirname)(snap.cursor), { recursive: true });
16687
+ (0, import_node_fs43.writeFileSync)(snap.cursor, `${nextCursor}
16253
16688
  `);
16254
16689
  } catch {
16255
16690
  }
@@ -16278,7 +16713,7 @@ async function waitForDetachedJob(cwd, id, opts) {
16278
16713
  const dir = resolveJobDir(root, jobId);
16279
16714
  const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
16280
16715
  const sleep2 = opts?.sleep ?? sleepMs;
16281
- if (!(0, import_node_fs42.existsSync)(dir)) {
16716
+ if (!(0, import_node_fs43.existsSync)(dir)) {
16282
16717
  return {
16283
16718
  stillRunning: false,
16284
16719
  ok: false,
@@ -16324,10 +16759,10 @@ function killProcessTree(pid, signal) {
16324
16759
  }
16325
16760
  function appendJobLog(logFile, line) {
16326
16761
  try {
16327
- (0, import_node_fs42.mkdirSync)((0, import_node_path42.dirname)(logFile), { recursive: true });
16762
+ (0, import_node_fs43.mkdirSync)((0, import_node_path43.dirname)(logFile), { recursive: true });
16328
16763
  const body = line.endsWith("\n") ? line : `${line}
16329
16764
  `;
16330
- (0, import_node_fs42.appendFileSync)(logFile, body);
16765
+ (0, import_node_fs43.appendFileSync)(logFile, body);
16331
16766
  } catch {
16332
16767
  }
16333
16768
  }
@@ -16337,7 +16772,7 @@ async function stopDetachedJob(cwd, id, opts) {
16337
16772
  const dir = resolveJobDir(root, jobId);
16338
16773
  const sleep2 = opts?.sleep ?? sleepMs;
16339
16774
  const why = opts?.reason?.trim() ?? "";
16340
- if (!(0, import_node_fs42.existsSync)(dir)) {
16775
+ if (!(0, import_node_fs43.existsSync)(dir)) {
16341
16776
  return {
16342
16777
  stillRunning: false,
16343
16778
  ok: false,
@@ -16373,10 +16808,10 @@ async function stopDetachedJob(cwd, id, opts) {
16373
16808
  killProcessTree(targetPid, "SIGKILL");
16374
16809
  await sleep2(100);
16375
16810
  }
16376
- const exitFile = (0, import_node_path42.join)(dir, "exit");
16377
- if (!(0, import_node_fs42.existsSync)(exitFile)) {
16811
+ const exitFile = (0, import_node_path43.join)(dir, "exit");
16812
+ if (!(0, import_node_fs43.existsSync)(exitFile)) {
16378
16813
  try {
16379
- (0, import_node_fs42.writeFileSync)(exitFile, "1\n");
16814
+ (0, import_node_fs43.writeFileSync)(exitFile, "1\n");
16380
16815
  } catch {
16381
16816
  }
16382
16817
  }
@@ -16396,12 +16831,12 @@ async function stopDetachedJob(cwd, id, opts) {
16396
16831
  hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
16397
16832
  };
16398
16833
  }
16399
- var import_node_fs42, import_node_path42, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
16834
+ var import_node_fs43, import_node_path43, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
16400
16835
  var init_wait_for_job = __esm({
16401
16836
  "src/mcp/wait-for-job.ts"() {
16402
16837
  "use strict";
16403
- import_node_fs42 = require("fs");
16404
- import_node_path42 = require("path");
16838
+ import_node_fs43 = require("fs");
16839
+ import_node_path43 = require("path");
16405
16840
  init_workspace_scratch();
16406
16841
  init_wait_for_turn();
16407
16842
  MAX_JOB_CONTINUES = 8;
@@ -17689,7 +18124,7 @@ function reuseLiveThread(input, repoPath, match) {
17689
18124
  }
17690
18125
  async function createThread(input, _onSetupLine) {
17691
18126
  const repoPath = await resolveRepoRoot(input.repoPath);
17692
- if (!(0, import_node_fs43.existsSync)(repoPath)) {
18127
+ if (!(0, import_node_fs44.existsSync)(repoPath)) {
17693
18128
  throw new Error(`Repo not found: ${repoPath}`);
17694
18129
  }
17695
18130
  const reused = reuseLiveThread(input, repoPath, {
@@ -17874,11 +18309,11 @@ async function listLinearIssues(agent, repoPath) {
17874
18309
  }
17875
18310
  return adapter.listLinearIssues(repoPath);
17876
18311
  }
17877
- var import_node_fs43;
18312
+ var import_node_fs44;
17878
18313
  var init_create = __esm({
17879
18314
  "src/threads/create.ts"() {
17880
18315
  "use strict";
17881
- import_node_fs43 = require("fs");
18316
+ import_node_fs44 = require("fs");
17882
18317
  init_detect();
17883
18318
  init_worktree();
17884
18319
  init_home_board();
@@ -17998,20 +18433,20 @@ function writeTurnLive(threadId, progress) {
17998
18433
  const path2 = threadLivePath(threadId);
17999
18434
  const tmp = `${path2}.${process.pid}.tmp`;
18000
18435
  try {
18001
- (0, import_node_fs44.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
18002
- (0, import_node_fs44.renameSync)(tmp, path2);
18436
+ (0, import_node_fs45.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
18437
+ (0, import_node_fs45.renameSync)(tmp, path2);
18003
18438
  } catch {
18004
18439
  try {
18005
- (0, import_node_fs44.unlinkSync)(tmp);
18440
+ (0, import_node_fs45.unlinkSync)(tmp);
18006
18441
  } catch {
18007
18442
  }
18008
18443
  }
18009
18444
  }
18010
18445
  function readTurnLive(threadId) {
18011
18446
  const path2 = threadLivePath(threadId);
18012
- if (!(0, import_node_fs44.existsSync)(path2)) return null;
18447
+ if (!(0, import_node_fs45.existsSync)(path2)) return null;
18013
18448
  try {
18014
- const raw = JSON.parse((0, import_node_fs44.readFileSync)(path2, "utf8"));
18449
+ const raw = JSON.parse((0, import_node_fs45.readFileSync)(path2, "utf8"));
18015
18450
  if (!raw || typeof raw.summary !== "string") return null;
18016
18451
  return raw;
18017
18452
  } catch {
@@ -18023,17 +18458,17 @@ function clearTurnLive(threadId) {
18023
18458
  if (buf?.timer) clearTimeout(buf.timer);
18024
18459
  buffers.delete(threadId);
18025
18460
  const path2 = threadLivePath(threadId);
18026
- if (!(0, import_node_fs44.existsSync)(path2)) return;
18461
+ if (!(0, import_node_fs45.existsSync)(path2)) return;
18027
18462
  try {
18028
- (0, import_node_fs44.unlinkSync)(path2);
18463
+ (0, import_node_fs45.unlinkSync)(path2);
18029
18464
  } catch {
18030
18465
  }
18031
18466
  }
18032
- var import_node_fs44, buffers, FLUSH_MS, MAX_PARTS;
18467
+ var import_node_fs45, buffers, FLUSH_MS, MAX_PARTS;
18033
18468
  var init_turn_live = __esm({
18034
18469
  "src/store/turn-live.ts"() {
18035
18470
  "use strict";
18036
- import_node_fs44 = require("fs");
18471
+ import_node_fs45 = require("fs");
18037
18472
  init_message_parts();
18038
18473
  init_paths();
18039
18474
  buffers = /* @__PURE__ */ new Map();
@@ -18136,12 +18571,18 @@ var init_fork_worktree = __esm({
18136
18571
 
18137
18572
  // src/orchestrator/quota-failover.ts
18138
18573
  function planOrchestrationQuotaFailover(thread, limitText, opts) {
18139
- if (!isOrchestratorThread(thread)) return null;
18140
18574
  if (!isSessionQuotaLimit(limitText)) return null;
18141
- const onLimit = opts?.onLimit ?? orchestrationQuotaOnLimit();
18575
+ const onLimit = opts?.onLimit ?? usageOnLimit();
18142
18576
  const resumeAt = parseSessionQuotaResetAt(limitText, opts?.now);
18577
+ if (onLimit === "keep_going" || onLimit === "confirm") {
18578
+ return {
18579
+ action: "none",
18580
+ reason: onLimit === "confirm" ? "Settings: confirm with user; no automatic continue." : "Settings: keep going; no automatic continue.",
18581
+ limitText
18582
+ };
18583
+ }
18143
18584
  if (thread.quotaContinuedFromId) {
18144
- if (resumeAt) {
18585
+ if (onLimit === "switch_agent" && resumeAt) {
18145
18586
  return {
18146
18587
  action: "wait_reset",
18147
18588
  reason: "Already continued once; waiting for quota reset instead.",
@@ -18151,7 +18592,7 @@ function planOrchestrationQuotaFailover(thread, limitText, opts) {
18151
18592
  }
18152
18593
  return {
18153
18594
  action: "none",
18154
- reason: "Already continued once; no parseable reset time.",
18595
+ reason: "Already continued once; no further automatic continue.",
18155
18596
  limitText
18156
18597
  };
18157
18598
  }
@@ -18188,8 +18629,19 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
18188
18629
  const text7 = m.text.trim().replace(/\s+/g, " ").slice(0, 280);
18189
18630
  return text7 ? `- ${role}: ${text7}` : null;
18190
18631
  }).filter(Boolean);
18632
+ const orch = isOrchestratorThread(from);
18633
+ const instructions = orch ? [
18634
+ "- Continue fleet orchestration from this handoff.",
18635
+ "- Prefer Sideboard MCP (list_board, list_threads, get_thread, send_to_thread, \u2026) for live status.",
18636
+ "- Leave model Auto unless there is a specific reason to pin one.",
18637
+ `- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
18638
+ ] : [
18639
+ "- Continue this worktree chat from the handoff.",
18640
+ "- Leave model Auto unless there is a specific reason to pin one.",
18641
+ `- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
18642
+ ];
18191
18643
  const body = [
18192
- `# Orchestration handoff`,
18644
+ `# ${orch ? "Orchestration" : "Chat"} handoff`,
18193
18645
  "",
18194
18646
  `Previous chat: ${from.title} (\`${from.id}\`) on **${from.agent}** hit a session/usage limit.`,
18195
18647
  `Limit: ${limitText.trim()}`,
@@ -18205,14 +18657,11 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
18205
18657
  recent.length ? recent.join("\n") : "(none)",
18206
18658
  "",
18207
18659
  `## Instructions`,
18208
- `- Continue fleet orchestration from this handoff.`,
18209
- `- Prefer Sideboard MCP (list_board, list_threads, get_thread, send_to_thread, \u2026) for live status.`,
18210
- `- Leave model Auto unless there is a specific reason to pin one.`,
18211
- `- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
18660
+ ...instructions
18212
18661
  ].join("\n");
18213
18662
  return {
18214
18663
  id: (0, import_node_crypto10.randomUUID)(),
18215
- name: "Orchestration quota handoff.md",
18664
+ name: orch ? "Orchestration quota handoff.md" : "Quota handoff.md",
18216
18665
  kind: "transcript",
18217
18666
  content: body
18218
18667
  };
@@ -18225,12 +18674,15 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
18225
18674
  model: null,
18226
18675
  attachments: [handoff]
18227
18676
  });
18228
- return updateThread(tab.id, {
18229
- parentThreadId: from.id,
18677
+ const patch = {
18230
18678
  quotaContinuedFromId: from.id,
18231
- sourceRef: from.sourceRef,
18232
- sourceType: "orchestration"
18233
- });
18679
+ sourceRef: from.sourceRef
18680
+ };
18681
+ if (isOrchestratorThread(from)) {
18682
+ patch.parentThreadId = from.id;
18683
+ patch.sourceType = "orchestration";
18684
+ }
18685
+ return updateThread(tab.id, patch);
18234
18686
  }
18235
18687
  var import_node_crypto10, QUOTA_CONTINUE_PROMPT, QUOTA_RESUME_PROMPT;
18236
18688
  var init_quota_failover = __esm({
@@ -18243,17 +18695,17 @@ var init_quota_failover = __esm({
18243
18695
  init_thread_store();
18244
18696
  init_chat_tabs();
18245
18697
  QUOTA_CONTINUE_PROMPT = (fromAgent, fallback) => [
18246
- `${fromAgent} hit a session/usage limit. Continue this orchestration on ${fallback} using the attached handoff.`,
18247
- "Call list_board or list_threads for live fleet status, then proceed with the goal. Leave model Auto unless needed."
18698
+ `${fromAgent} hit a session/usage limit. Continue this chat on ${fallback} using the attached handoff.`,
18699
+ "Proceed with the goal. Leave model Auto unless needed."
18248
18700
  ].join(" ");
18249
- QUOTA_RESUME_PROMPT = "Session/usage limit window should have reset. Continue the orchestration from where you left off. Use list_board or list_threads for fleet status.";
18701
+ QUOTA_RESUME_PROMPT = "Session/usage limit window should have reset. Continue this chat from where you left off.";
18250
18702
  }
18251
18703
  });
18252
18704
 
18253
18705
  // src/threads/adopt.ts
18254
18706
  function thisModuleFile() {
18255
18707
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
18256
- return cjsFile || process.argv[1] || (0, import_node_path43.join)(process.cwd(), "package.json");
18708
+ return cjsFile || process.argv[1] || (0, import_node_path44.join)(process.cwd(), "package.json");
18257
18709
  }
18258
18710
  function openReadonlySqlite(file) {
18259
18711
  const req = (0, import_node_module4.createRequire)(thisModuleFile());
@@ -18271,21 +18723,21 @@ function mapAgentType(raw) {
18271
18723
  return null;
18272
18724
  }
18273
18725
  function resolveConductorCursorAgentId(workspacePath) {
18274
- if (!workspacePath || !(0, import_node_fs45.existsSync)(CURSOR_SDK_STORE)) return null;
18726
+ if (!workspacePath || !(0, import_node_fs46.existsSync)(CURSOR_SDK_STORE)) return null;
18275
18727
  const normalized = workspacePath.replace(/\/$/, "");
18276
18728
  let best = null;
18277
18729
  let hashes;
18278
18730
  try {
18279
- hashes = (0, import_node_fs45.readdirSync)(CURSOR_SDK_STORE);
18731
+ hashes = (0, import_node_fs46.readdirSync)(CURSOR_SDK_STORE);
18280
18732
  } catch {
18281
18733
  return null;
18282
18734
  }
18283
18735
  for (const hash of hashes) {
18284
- const agentsFile = (0, import_node_path43.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
18285
- if (!(0, import_node_fs45.existsSync)(agentsFile)) continue;
18736
+ const agentsFile = (0, import_node_path44.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
18737
+ if (!(0, import_node_fs46.existsSync)(agentsFile)) continue;
18286
18738
  let text7;
18287
18739
  try {
18288
- text7 = (0, import_node_fs45.readFileSync)(agentsFile, "utf8");
18740
+ text7 = (0, import_node_fs46.readFileSync)(agentsFile, "utf8");
18289
18741
  } catch {
18290
18742
  continue;
18291
18743
  }
@@ -18309,7 +18761,7 @@ function resolveConductorCursorAgentId(workspacePath) {
18309
18761
  return best?.agentId ?? null;
18310
18762
  }
18311
18763
  async function adoptThread(input) {
18312
- if (!(0, import_node_fs45.existsSync)(input.worktreePath)) {
18764
+ if (!(0, import_node_fs46.existsSync)(input.worktreePath)) {
18313
18765
  throw new Error(`Worktree not found: ${input.worktreePath}`);
18314
18766
  }
18315
18767
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -18338,18 +18790,18 @@ function conductorDbPath() {
18338
18790
  return CONDUCTOR_DB;
18339
18791
  }
18340
18792
  function listConductorWorkspaces() {
18341
- if (!(0, import_node_fs45.existsSync)(CONDUCTOR_DB)) {
18793
+ if (!(0, import_node_fs46.existsSync)(CONDUCTOR_DB)) {
18342
18794
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
18343
18795
  }
18344
- const tmp = (0, import_node_fs45.mkdtempSync)((0, import_node_path43.join)((0, import_node_os13.tmpdir)(), "sideboard-conductor-"));
18345
- const snapshot = (0, import_node_path43.join)(tmp, "conductor.db");
18796
+ const tmp = (0, import_node_fs46.mkdtempSync)((0, import_node_path44.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
18797
+ const snapshot = (0, import_node_path44.join)(tmp, "conductor.db");
18346
18798
  try {
18347
- (0, import_node_fs45.copyFileSync)(CONDUCTOR_DB, snapshot);
18799
+ (0, import_node_fs46.copyFileSync)(CONDUCTOR_DB, snapshot);
18348
18800
  for (const suffix of ["-wal", "-shm"]) {
18349
18801
  const src = `${CONDUCTOR_DB}${suffix}`;
18350
- if ((0, import_node_fs45.existsSync)(src)) {
18802
+ if ((0, import_node_fs46.existsSync)(src)) {
18351
18803
  try {
18352
- (0, import_node_fs45.copyFileSync)(src, `${snapshot}${suffix}`);
18804
+ (0, import_node_fs46.copyFileSync)(src, `${snapshot}${suffix}`);
18353
18805
  } catch {
18354
18806
  }
18355
18807
  }
@@ -18425,22 +18877,22 @@ function listConductorWorkspaces() {
18425
18877
  db.close();
18426
18878
  }
18427
18879
  } finally {
18428
- (0, import_node_fs45.rmSync)(tmp, { recursive: true, force: true });
18880
+ (0, import_node_fs46.rmSync)(tmp, { recursive: true, force: true });
18429
18881
  }
18430
18882
  }
18431
18883
  function importConductorWorkspace(workspaceId) {
18432
- if (!(0, import_node_fs45.existsSync)(CONDUCTOR_DB)) {
18884
+ if (!(0, import_node_fs46.existsSync)(CONDUCTOR_DB)) {
18433
18885
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
18434
18886
  }
18435
- const tmp = (0, import_node_fs45.mkdtempSync)((0, import_node_path43.join)((0, import_node_os13.tmpdir)(), "sideboard-conductor-"));
18436
- const snapshot = (0, import_node_path43.join)(tmp, "conductor.db");
18887
+ const tmp = (0, import_node_fs46.mkdtempSync)((0, import_node_path44.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
18888
+ const snapshot = (0, import_node_path44.join)(tmp, "conductor.db");
18437
18889
  try {
18438
- (0, import_node_fs45.copyFileSync)(CONDUCTOR_DB, snapshot);
18890
+ (0, import_node_fs46.copyFileSync)(CONDUCTOR_DB, snapshot);
18439
18891
  for (const suffix of ["-wal", "-shm"]) {
18440
18892
  const src = `${CONDUCTOR_DB}${suffix}`;
18441
- if ((0, import_node_fs45.existsSync)(src)) {
18893
+ if ((0, import_node_fs46.existsSync)(src)) {
18442
18894
  try {
18443
- (0, import_node_fs45.copyFileSync)(src, `${snapshot}${suffix}`);
18895
+ (0, import_node_fs46.copyFileSync)(src, `${snapshot}${suffix}`);
18444
18896
  } catch {
18445
18897
  }
18446
18898
  }
@@ -18458,7 +18910,7 @@ function importConductorWorkspace(workspaceId) {
18458
18910
  ).get(workspaceId);
18459
18911
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
18460
18912
  const worktreePath = String(row.workspacePath);
18461
- if (!(0, import_node_fs45.existsSync)(worktreePath)) {
18913
+ if (!(0, import_node_fs46.existsSync)(worktreePath)) {
18462
18914
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
18463
18915
  }
18464
18916
  let sessionId = null;
@@ -18521,31 +18973,31 @@ function importConductorWorkspace(workspaceId) {
18521
18973
  db.close();
18522
18974
  }
18523
18975
  } finally {
18524
- (0, import_node_fs45.rmSync)(tmp, { recursive: true, force: true });
18976
+ (0, import_node_fs46.rmSync)(tmp, { recursive: true, force: true });
18525
18977
  }
18526
18978
  }
18527
18979
  async function importConductorWorkspaceAsync(workspaceId) {
18528
18980
  return importConductorWorkspace(workspaceId);
18529
18981
  }
18530
- var import_node_child_process5, import_node_fs45, import_node_os13, import_node_path43, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
18982
+ var import_node_child_process5, import_node_fs46, import_node_os14, import_node_path44, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
18531
18983
  var init_adopt = __esm({
18532
18984
  "src/threads/adopt.ts"() {
18533
18985
  "use strict";
18534
18986
  import_node_child_process5 = require("child_process");
18535
- import_node_fs45 = require("fs");
18536
- import_node_os13 = require("os");
18537
- import_node_path43 = require("path");
18987
+ import_node_fs46 = require("fs");
18988
+ import_node_os14 = require("os");
18989
+ import_node_path44 = require("path");
18538
18990
  import_node_module4 = require("module");
18539
18991
  init_worktree();
18540
18992
  init_thread_store();
18541
- CONDUCTOR_APP_SUPPORT = (0, import_node_path43.join)(
18993
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path44.join)(
18542
18994
  process.env.HOME ?? "",
18543
18995
  "Library",
18544
18996
  "Application Support",
18545
18997
  "com.conductor.app"
18546
18998
  );
18547
- CONDUCTOR_DB = (0, import_node_path43.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
18548
- CURSOR_SDK_STORE = (0, import_node_path43.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
18999
+ CONDUCTOR_DB = (0, import_node_path44.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
19000
+ CURSOR_SDK_STORE = (0, import_node_path44.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
18549
19001
  }
18550
19002
  });
18551
19003
 
@@ -18612,7 +19064,7 @@ async function openStackLayer(input, _onSetupLine) {
18612
19064
  let createdWorktree = false;
18613
19065
  const trees = await listWorktrees(repoPath);
18614
19066
  const checkedOut = trees.find((w) => w.branch === branchName);
18615
- if (checkedOut?.path && (0, import_node_fs46.existsSync)(checkedOut.path)) {
19067
+ if (checkedOut?.path && (0, import_node_fs47.existsSync)(checkedOut.path)) {
18616
19068
  if (input.reuseExistingWorktree !== false) {
18617
19069
  worktreePath = checkedOut.path;
18618
19070
  } else {
@@ -18754,7 +19206,7 @@ async function initStackFromThread(input, onSetupLine) {
18754
19206
  async function createPrStack(input, onSetupLine) {
18755
19207
  await requireAgent(input.agent);
18756
19208
  const repoPath = await resolveRepoRoot(input.repoPath);
18757
- if (!(0, import_node_fs46.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
19209
+ if (!(0, import_node_fs47.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
18758
19210
  if (!input.branches.length) throw new Error("At least one branch name required");
18759
19211
  const status = await detectGhStack(repoPath);
18760
19212
  if (!status.available) throw new Error(status.reason);
@@ -18821,7 +19273,7 @@ async function createPrStack(input, onSetupLine) {
18821
19273
  }
18822
19274
  }
18823
19275
  const claimed = new Set(threads.map((t) => t.worktreePath));
18824
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs46.existsSync)(bootstrap.worktreePath)) {
19276
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs47.existsSync)(bootstrap.worktreePath)) {
18825
19277
  try {
18826
19278
  await removeWorktree(repoPath, bootstrap.worktreePath, {
18827
19279
  deleteBranch: bootstrap.branchName
@@ -18841,11 +19293,11 @@ function stackAgentDefaultsFrom(input) {
18841
19293
  planMode: input.planMode
18842
19294
  };
18843
19295
  }
18844
- var import_node_fs46;
19296
+ var import_node_fs47;
18845
19297
  var init_stack_layers = __esm({
18846
19298
  "src/threads/stack-layers.ts"() {
18847
19299
  "use strict";
18848
- import_node_fs46 = require("fs");
19300
+ import_node_fs47 = require("fs");
18849
19301
  init_detect();
18850
19302
  init_run();
18851
19303
  init_stack();
@@ -18858,7 +19310,7 @@ var init_stack_layers = __esm({
18858
19310
 
18859
19311
  // src/diff/diff.ts
18860
19312
  async function inspectGitWorktree(worktreePath) {
18861
- if (!worktreePath || !(0, import_node_fs47.existsSync)(worktreePath)) return "missing_worktree";
19313
+ if (!worktreePath || !(0, import_node_fs48.existsSync)(worktreePath)) return "missing_worktree";
18862
19314
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
18863
19315
  reject: false
18864
19316
  });
@@ -18866,7 +19318,7 @@ async function inspectGitWorktree(worktreePath) {
18866
19318
  return "ok";
18867
19319
  }
18868
19320
  async function initializeGitRepository(worktreePath) {
18869
- if (!worktreePath || !(0, import_node_fs47.existsSync)(worktreePath)) {
19321
+ if (!worktreePath || !(0, import_node_fs48.existsSync)(worktreePath)) {
18870
19322
  throw new Error("Worktree not found");
18871
19323
  }
18872
19324
  const status = await inspectGitWorktree(worktreePath);
@@ -19000,11 +19452,11 @@ new file mode 100644
19000
19452
  };
19001
19453
  }
19002
19454
  async function untrackedPatch(worktreePath, path2, maxHunk) {
19003
- const abs = (0, import_node_path44.join)(worktreePath, path2);
19455
+ const abs = (0, import_node_path45.join)(worktreePath, path2);
19004
19456
  try {
19005
- const st = (0, import_node_fs47.statSync)(abs);
19457
+ const st = (0, import_node_fs48.statSync)(abs);
19006
19458
  if (st.isFile() && st.size > maxHunk) {
19007
- const buf = (0, import_node_fs47.readFileSync)(abs).subarray(0, maxHunk);
19459
+ const buf = (0, import_node_fs48.readFileSync)(abs).subarray(0, maxHunk);
19008
19460
  return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
19009
19461
  }
19010
19462
  } catch {
@@ -19493,8 +19945,8 @@ function isImageRelativePath(relativePath) {
19493
19945
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19494
19946
  assertSafeRelativePath(relativePath);
19495
19947
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
19496
- const abs = (0, import_node_path44.join)(worktreePath, relativePath);
19497
- const st = (0, import_node_fs47.statSync)(abs);
19948
+ const abs = (0, import_node_path45.join)(worktreePath, relativePath);
19949
+ const st = (0, import_node_fs48.statSync)(abs);
19498
19950
  if (!st.isFile()) {
19499
19951
  throw new Error(`Not a file: ${relativePath}`);
19500
19952
  }
@@ -19503,7 +19955,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19503
19955
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
19504
19956
  );
19505
19957
  }
19506
- const buf = (0, import_node_fs47.readFileSync)(abs);
19958
+ const buf = (0, import_node_fs48.readFileSync)(abs);
19507
19959
  return {
19508
19960
  path: relativePath,
19509
19961
  contentBase64: buf.toString("base64"),
@@ -19513,12 +19965,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19513
19965
  function readWorktreeFile(worktreePath, relativePath, opts) {
19514
19966
  assertSafeRelativePath(relativePath);
19515
19967
  const maxBytes = opts?.maxBytes ?? 2e5;
19516
- const abs = (0, import_node_path44.join)(worktreePath, relativePath);
19517
- const st = (0, import_node_fs47.statSync)(abs);
19968
+ const abs = (0, import_node_path45.join)(worktreePath, relativePath);
19969
+ const st = (0, import_node_fs48.statSync)(abs);
19518
19970
  if (!st.isFile()) {
19519
19971
  throw new Error(`Not a file: ${relativePath}`);
19520
19972
  }
19521
- const buf = (0, import_node_fs47.readFileSync)(abs);
19973
+ const buf = (0, import_node_fs48.readFileSync)(abs);
19522
19974
  if (isImageRelativePath(relativePath)) {
19523
19975
  const maxImageBytes = Math.max(maxBytes, 15e6);
19524
19976
  const truncated2 = buf.length > maxImageBytes;
@@ -19561,9 +20013,9 @@ function assertSafeRelativePath(relativePath) {
19561
20013
  }
19562
20014
  function writeWorktreeFile(worktreePath, relativePath, content) {
19563
20015
  assertSafeRelativePath(relativePath);
19564
- const abs = (0, import_node_path44.join)(worktreePath, relativePath);
19565
- (0, import_node_fs47.mkdirSync)((0, import_node_path44.dirname)(abs), { recursive: true });
19566
- (0, import_node_fs47.writeFileSync)(abs, content, "utf8");
20016
+ const abs = (0, import_node_path45.join)(worktreePath, relativePath);
20017
+ (0, import_node_fs48.mkdirSync)((0, import_node_path45.dirname)(abs), { recursive: true });
20018
+ (0, import_node_fs48.writeFileSync)(abs, content, "utf8");
19567
20019
  return { path: relativePath };
19568
20020
  }
19569
20021
  async function getDiffSummary(worktreePath, repoPath, opts) {
@@ -19580,12 +20032,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
19580
20032
  truncated: full.files.length > maxFiles
19581
20033
  };
19582
20034
  }
19583
- var import_node_fs47, import_node_path44, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
20035
+ var import_node_fs48, import_node_path45, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
19584
20036
  var init_diff = __esm({
19585
20037
  "src/diff/diff.ts"() {
19586
20038
  "use strict";
19587
- import_node_fs47 = require("fs");
19588
- import_node_path44 = require("path");
20039
+ import_node_fs48 = require("fs");
20040
+ import_node_path45 = require("path");
19589
20041
  init_run();
19590
20042
  init_worktree();
19591
20043
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -19942,7 +20394,7 @@ function parseFrontmatter(content) {
19942
20394
  }
19943
20395
  function readSkill(skillMd, source) {
19944
20396
  try {
19945
- const content = (0, import_node_fs48.readFileSync)(skillMd, "utf8");
20397
+ const content = (0, import_node_fs49.readFileSync)(skillMd, "utf8");
19946
20398
  const { name: fmName, description } = parseFrontmatter(content);
19947
20399
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
19948
20400
  const name = fmName || dirName;
@@ -19961,19 +20413,19 @@ function readSkill(skillMd, source) {
19961
20413
  }
19962
20414
  }
19963
20415
  function scanSkillsDir(dir, source, out) {
19964
- if (!(0, import_node_fs48.existsSync)(dir)) return;
20416
+ if (!(0, import_node_fs49.existsSync)(dir)) return;
19965
20417
  let entries;
19966
20418
  try {
19967
- entries = (0, import_node_fs48.readdirSync)(dir);
20419
+ entries = (0, import_node_fs49.readdirSync)(dir);
19968
20420
  } catch {
19969
20421
  return;
19970
20422
  }
19971
20423
  for (const entry of entries) {
19972
20424
  if (entry.startsWith(".")) continue;
19973
- const skillMd = (0, import_node_path45.join)(dir, entry, "SKILL.md");
19974
- if (!(0, import_node_fs48.existsSync)(skillMd)) continue;
20425
+ const skillMd = (0, import_node_path46.join)(dir, entry, "SKILL.md");
20426
+ if (!(0, import_node_fs49.existsSync)(skillMd)) continue;
19975
20427
  try {
19976
- if (!(0, import_node_fs48.statSync)(skillMd).isFile()) continue;
20428
+ if (!(0, import_node_fs49.statSync)(skillMd).isFile()) continue;
19977
20429
  } catch {
19978
20430
  continue;
19979
20431
  }
@@ -19982,24 +20434,24 @@ function scanSkillsDir(dir, source, out) {
19982
20434
  }
19983
20435
  }
19984
20436
  function scanClaudePluginSkills(pluginsRoot, out) {
19985
- if (!(0, import_node_fs48.existsSync)(pluginsRoot)) return;
20437
+ if (!(0, import_node_fs49.existsSync)(pluginsRoot)) return;
19986
20438
  const walk = (dir, depth, lookingForSkillsDir) => {
19987
20439
  if (depth > 7) return;
19988
20440
  let entries;
19989
20441
  try {
19990
- entries = (0, import_node_fs48.readdirSync)(dir);
20442
+ entries = (0, import_node_fs49.readdirSync)(dir);
19991
20443
  } catch {
19992
20444
  return;
19993
20445
  }
19994
20446
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
19995
- const skill = readSkill((0, import_node_path45.join)(dir, "SKILL.md"), "cli");
20447
+ const skill = readSkill((0, import_node_path46.join)(dir, "SKILL.md"), "cli");
19996
20448
  if (skill) out.push(skill);
19997
20449
  }
19998
20450
  for (const entry of entries) {
19999
20451
  if (entry === "node_modules" || entry === ".git") continue;
20000
- const full = (0, import_node_path45.join)(dir, entry);
20452
+ const full = (0, import_node_path46.join)(dir, entry);
20001
20453
  try {
20002
- if (!(0, import_node_fs48.statSync)(full).isDirectory()) continue;
20454
+ if (!(0, import_node_fs49.statSync)(full).isDirectory()) continue;
20003
20455
  } catch {
20004
20456
  continue;
20005
20457
  }
@@ -20014,20 +20466,20 @@ function scanClaudePluginSkills(pluginsRoot, out) {
20014
20466
  walk(pluginsRoot, 0, false);
20015
20467
  }
20016
20468
  function discoverSkills(worktreePath) {
20017
- const home = (0, import_node_os14.homedir)();
20469
+ const home = (0, import_node_os15.homedir)();
20018
20470
  const collected = [];
20019
20471
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
20020
- scanSkillsDir((0, import_node_path45.join)(worktreePath, rel), "workspace", collected);
20472
+ scanSkillsDir((0, import_node_path46.join)(worktreePath, rel), "workspace", collected);
20021
20473
  }
20022
20474
  for (const abs of [
20023
- (0, import_node_path45.join)(home, ".claude/skills"),
20024
- (0, import_node_path45.join)(home, ".cursor/skills"),
20025
- (0, import_node_path45.join)(home, ".sideboard/skills"),
20026
- (0, import_node_path45.join)(home, ".brightsy/skills")
20475
+ (0, import_node_path46.join)(home, ".claude/skills"),
20476
+ (0, import_node_path46.join)(home, ".cursor/skills"),
20477
+ (0, import_node_path46.join)(home, ".sideboard/skills"),
20478
+ (0, import_node_path46.join)(home, ".brightsy/skills")
20027
20479
  ]) {
20028
20480
  scanSkillsDir(abs, "user", collected);
20029
20481
  }
20030
- scanClaudePluginSkills((0, import_node_path45.join)(home, ".claude/plugins"), collected);
20482
+ scanClaudePluginSkills((0, import_node_path46.join)(home, ".claude/plugins"), collected);
20031
20483
  collected.push(...bundledSkills());
20032
20484
  const rank = {
20033
20485
  workspace: 0,
@@ -20053,7 +20505,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
20053
20505
  \u2026(truncated)` : body;
20054
20506
  }
20055
20507
  }
20056
- const raw = (0, import_node_fs48.readFileSync)(skillPath, "utf8");
20508
+ const raw = (0, import_node_fs49.readFileSync)(skillPath, "utf8");
20057
20509
  if (raw.startsWith("---")) {
20058
20510
  const end = raw.indexOf("\n---", 3);
20059
20511
  if (end >= 0) {
@@ -20067,13 +20519,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
20067
20519
 
20068
20520
  \u2026(truncated)` : raw;
20069
20521
  }
20070
- var import_node_fs48, import_node_os14, import_node_path45, BUNDLED_SKILL_PREFIX;
20522
+ var import_node_fs49, import_node_os15, import_node_path46, BUNDLED_SKILL_PREFIX;
20071
20523
  var init_discover = __esm({
20072
20524
  "src/skills/discover.ts"() {
20073
20525
  "use strict";
20074
- import_node_fs48 = require("fs");
20075
- import_node_os14 = require("os");
20076
- import_node_path45 = require("path");
20526
+ import_node_fs49 = require("fs");
20527
+ import_node_os15 = require("os");
20528
+ import_node_path46 = require("path");
20077
20529
  init_long_running();
20078
20530
  BUNDLED_SKILL_PREFIX = "bundled:";
20079
20531
  }
@@ -20167,8 +20619,8 @@ var init_expand = __esm({
20167
20619
  // src/skills/detached-job-path.ts
20168
20620
  function detachedJobScriptIn(dir) {
20169
20621
  for (const name of DETACHED_JOB_FILENAMES) {
20170
- const script = (0, import_node_path46.join)(dir, "scripts", name);
20171
- if ((0, import_node_fs49.existsSync)(script)) return script;
20622
+ const script = (0, import_node_path47.join)(dir, "scripts", name);
20623
+ if ((0, import_node_fs50.existsSync)(script)) return script;
20172
20624
  }
20173
20625
  return null;
20174
20626
  }
@@ -20180,11 +20632,11 @@ function packagedDetachedJobPath() {
20180
20632
  function resolveDetachedJobScript() {
20181
20633
  const packaged = packagedDetachedJobPath();
20182
20634
  if (packaged) return packaged;
20183
- let dir = (0, import_node_path46.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
20635
+ let dir = (0, import_node_path47.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
20184
20636
  for (let i = 0; i < 8; i++) {
20185
20637
  const candidate = detachedJobScriptIn(dir);
20186
20638
  if (candidate) return candidate;
20187
- const parent = (0, import_node_path46.dirname)(dir);
20639
+ const parent = (0, import_node_path47.dirname)(dir);
20188
20640
  if (parent === dir) break;
20189
20641
  dir = parent;
20190
20642
  }
@@ -20195,12 +20647,12 @@ function formatDetachedJobInvoke(scriptPath) {
20195
20647
  if (resolved) return `node ${JSON.stringify(resolved)}`;
20196
20648
  return "node scripts/detached-job.cjs";
20197
20649
  }
20198
- var import_node_fs49, import_node_path46, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
20650
+ var import_node_fs50, import_node_path47, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
20199
20651
  var init_detached_job_path = __esm({
20200
20652
  "src/skills/detached-job-path.ts"() {
20201
20653
  "use strict";
20202
- import_node_fs49 = require("fs");
20203
- import_node_path46 = require("path");
20654
+ import_node_fs50 = require("fs");
20655
+ import_node_path47 = require("path");
20204
20656
  import_node_url3 = require("url");
20205
20657
  init_packaged_runtime();
20206
20658
  import_meta3 = {};
@@ -20382,9 +20834,9 @@ function formatPrGateDirective() {
20382
20834
  }
20383
20835
  function formatProcessGuideDirective(opts) {
20384
20836
  const worktree = opts?.worktreePath?.trim();
20385
- const hasGraphSkill = !!worktree && (0, import_node_fs50.existsSync)((0, import_node_path47.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
20386
- const hasReviewSkill = !!worktree && (0, import_node_fs50.existsSync)((0, import_node_path47.join)(worktree, ".claude/skills/review/SKILL.md"));
20387
- const hasInstallSkill = !!worktree && (0, import_node_fs50.existsSync)((0, import_node_path47.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
20837
+ const hasGraphSkill = !!worktree && (0, import_node_fs51.existsSync)((0, import_node_path48.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
20838
+ const hasReviewSkill = !!worktree && (0, import_node_fs51.existsSync)((0, import_node_path48.join)(worktree, ".claude/skills/review/SKILL.md"));
20839
+ const hasInstallSkill = !!worktree && (0, import_node_fs51.existsSync)((0, import_node_path48.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
20388
20840
  return [
20389
20841
  "Process guides (recurring work only):",
20390
20842
  hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
@@ -20422,12 +20874,12 @@ function formatArtifactDirective() {
20422
20874
  function formatUiReminder() {
20423
20875
  return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
20424
20876
  }
20425
- var import_node_fs50, import_node_path47, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
20877
+ var import_node_fs51, import_node_path48, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
20426
20878
  var init_instructions = __esm({
20427
20879
  "src/agents/instructions.ts"() {
20428
20880
  "use strict";
20429
- import_node_fs50 = require("fs");
20430
- import_node_path47 = require("path");
20881
+ import_node_fs51 = require("fs");
20882
+ import_node_path48 = require("path");
20431
20883
  init_git_auth_mode();
20432
20884
  init_branch_prefix();
20433
20885
  init_worktree_labels();
@@ -20813,40 +21265,40 @@ __export(plan_file_exports, {
20813
21265
  writePlanFile: () => writePlanFile
20814
21266
  });
20815
21267
  function ensureAttachmentsGitignore(worktreePath) {
20816
- const gitignoreAbs = (0, import_node_path48.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
20817
- if ((0, import_node_fs51.existsSync)(gitignoreAbs)) return;
20818
- (0, import_node_fs51.mkdirSync)((0, import_node_path48.dirname)(gitignoreAbs), { recursive: true });
20819
- (0, import_node_fs51.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
21268
+ const gitignoreAbs = (0, import_node_path49.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
21269
+ if ((0, import_node_fs52.existsSync)(gitignoreAbs)) return;
21270
+ (0, import_node_fs52.mkdirSync)((0, import_node_path49.dirname)(gitignoreAbs), { recursive: true });
21271
+ (0, import_node_fs52.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
20820
21272
  }
20821
21273
  function planFileAbs(worktreePath) {
20822
- return (0, import_node_path48.join)(worktreePath, PLAN_FILE_REL);
21274
+ return (0, import_node_path49.join)(worktreePath, PLAN_FILE_REL);
20823
21275
  }
20824
21276
  function readTextIfPresent2(abs) {
20825
- if (!(0, import_node_fs51.existsSync)(abs)) return null;
21277
+ if (!(0, import_node_fs52.existsSync)(abs)) return null;
20826
21278
  try {
20827
- const content = (0, import_node_fs51.readFileSync)(abs, "utf8");
21279
+ const content = (0, import_node_fs52.readFileSync)(abs, "utf8");
20828
21280
  return content.trim() ? content : null;
20829
21281
  } catch {
20830
21282
  return null;
20831
21283
  }
20832
21284
  }
20833
21285
  function readPlanFile(worktreePath) {
20834
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path48.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path48.join)(worktreePath, LEGACY_PLAN_FILE_REL));
21286
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path49.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path49.join)(worktreePath, LEGACY_PLAN_FILE_REL));
20835
21287
  }
20836
21288
  function writePlanFile(worktreePath, content) {
20837
21289
  ensureAttachmentsGitignore(worktreePath);
20838
21290
  const abs = planFileAbs(worktreePath);
20839
- (0, import_node_fs51.mkdirSync)((0, import_node_path48.dirname)(abs), { recursive: true });
21291
+ (0, import_node_fs52.mkdirSync)((0, import_node_path49.dirname)(abs), { recursive: true });
20840
21292
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
20841
- (0, import_node_fs51.writeFileSync)(abs, body, "utf8");
21293
+ (0, import_node_fs52.writeFileSync)(abs, body, "utf8");
20842
21294
  return PLAN_FILE_REL;
20843
21295
  }
20844
- var import_node_fs51, import_node_path48;
21296
+ var import_node_fs52, import_node_path49;
20845
21297
  var init_plan_file = __esm({
20846
21298
  "src/plan/plan-file.ts"() {
20847
21299
  "use strict";
20848
- import_node_fs51 = require("fs");
20849
- import_node_path48 = require("path");
21300
+ import_node_fs52 = require("fs");
21301
+ import_node_path49 = require("path");
20850
21302
  init_workspace_scratch();
20851
21303
  init_plan_present();
20852
21304
  init_plan_present();
@@ -20894,13 +21346,13 @@ var init_sync_branch = __esm({
20894
21346
 
20895
21347
  // src/agents/cursor-store.ts
20896
21348
  function cursorSdkStoreDir(threadId) {
20897
- const root = (0, import_node_path49.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
21349
+ const root = (0, import_node_path50.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
20898
21350
  const id = sanitizeCursorStoreSegment(threadId);
20899
21351
  if (!id) return root;
20900
- return (0, import_node_path49.join)(root, "threads", id);
21352
+ return (0, import_node_path50.join)(root, "threads", id);
20901
21353
  }
20902
21354
  function cursorSdkRunsNdjsonPath(threadId) {
20903
- return (0, import_node_path49.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
21355
+ return (0, import_node_path50.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
20904
21356
  }
20905
21357
  function cursorSdkRunsNdjsonSearchPaths(threadId) {
20906
21358
  const scoped = cursorSdkRunsNdjsonPath(threadId);
@@ -20913,11 +21365,11 @@ function cursorSdkRunsNdjsonSearchPaths(threadId) {
20913
21365
  function sanitizeCursorStoreSegment(threadId) {
20914
21366
  return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
20915
21367
  }
20916
- var import_node_path49, CURSOR_SDK_STORE_DIR;
21368
+ var import_node_path50, CURSOR_SDK_STORE_DIR;
20917
21369
  var init_cursor_store = __esm({
20918
21370
  "src/agents/cursor-store.ts"() {
20919
21371
  "use strict";
20920
- import_node_path49 = require("path");
21372
+ import_node_path50 = require("path");
20921
21373
  init_paths();
20922
21374
  CURSOR_SDK_STORE_DIR = "cursor-sdk-store";
20923
21375
  }
@@ -20939,9 +21391,9 @@ function recoverFinishedCursorRun(opts) {
20939
21391
  return best;
20940
21392
  }
20941
21393
  function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
20942
- if (!(0, import_node_fs52.existsSync)(runsPath)) return null;
21394
+ if (!(0, import_node_fs53.existsSync)(runsPath)) return null;
20943
21395
  try {
20944
- const lines = (0, import_node_fs52.readFileSync)(runsPath, "utf8").split("\n");
21396
+ const lines = (0, import_node_fs53.readFileSync)(runsPath, "utf8").split("\n");
20945
21397
  let best = null;
20946
21398
  for (const line of lines) {
20947
21399
  const trimmed = line.trim();
@@ -20967,11 +21419,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
20967
21419
  return null;
20968
21420
  }
20969
21421
  }
20970
- var import_node_fs52;
21422
+ var import_node_fs53;
20971
21423
  var init_cursor_recover = __esm({
20972
21424
  "src/agents/cursor-recover.ts"() {
20973
21425
  "use strict";
20974
- import_node_fs52 = require("fs");
21426
+ import_node_fs53 = require("fs");
20975
21427
  init_cursor_store();
20976
21428
  }
20977
21429
  });
@@ -21118,13 +21570,13 @@ async function startOrchestration(opts) {
21118
21570
  }
21119
21571
  return updated;
21120
21572
  }
21121
- var import_node_events, import_node_fs53, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, Orchestrator, singleton;
21573
+ var import_node_events, import_node_fs54, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, Orchestrator, singleton;
21122
21574
  var init_orchestrator = __esm({
21123
21575
  "src/orchestrator/orchestrator.ts"() {
21124
21576
  "use strict";
21125
21577
  import_node_events = require("events");
21126
21578
  init_outbound_watch();
21127
- import_node_fs53 = require("fs");
21579
+ import_node_fs54 = require("fs");
21128
21580
  init_error_detail();
21129
21581
  init_run();
21130
21582
  init_stale_lock();
@@ -21298,7 +21750,7 @@ var init_orchestrator = __esm({
21298
21750
  }
21299
21751
  continue;
21300
21752
  }
21301
- if (!(0, import_node_fs53.existsSync)(thread.worktreePath)) {
21753
+ if (!(0, import_node_fs54.existsSync)(thread.worktreePath)) {
21302
21754
  setStatus(thread.id, "broken", "Worktree missing on disk");
21303
21755
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
21304
21756
  continue;
@@ -21428,8 +21880,8 @@ var init_orchestrator = __esm({
21428
21880
  await this.send(threadId, QUOTA_RESUME_PROMPT);
21429
21881
  }
21430
21882
  /**
21431
- * Host-side continue when an orchestration chat hits a provider session/usage
21432
- * limit (not context size): switch agent (Auto) or wait until reset.
21883
+ * Host-side continue when any chat hits a provider session/usage limit
21884
+ * (not context size): switch agent (Auto) or wait until reset.
21433
21885
  */
21434
21886
  async maybeHandleOrchestrationQuotaFailover(threadId, limitText) {
21435
21887
  const thread = findThreadByRef(threadId);
@@ -21442,7 +21894,7 @@ var init_orchestrator = __esm({
21442
21894
  setStatus(threadId, "idle", null);
21443
21895
  appendMessage(threadId, {
21444
21896
  role: "agent",
21445
- text: `Sideboard will auto-retry this orchestration around ${plan.resumeAt.toLocaleString()} when the session limit resets.`,
21897
+ text: `Sideboard will auto-retry this chat around ${plan.resumeAt.toLocaleString()} when the session limit resets.`,
21446
21898
  ts: (/* @__PURE__ */ new Date()).toISOString()
21447
21899
  });
21448
21900
  this.emit({
@@ -23245,7 +23697,7 @@ var init_orchestrator = __esm({
23245
23697
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
23246
23698
  return restored2;
23247
23699
  }
23248
- if (!(0, import_node_fs53.existsSync)(thread.worktreePath)) {
23700
+ if (!(0, import_node_fs54.existsSync)(thread.worktreePath)) {
23249
23701
  if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
23250
23702
  throw new Error(
23251
23703
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
@@ -23537,6 +23989,7 @@ __export(index_exports, {
23537
23989
  SlackRelayHub: () => SlackRelayHub,
23538
23990
  THINKING_EFFORTS: () => THINKING_EFFORTS,
23539
23991
  THINKING_PART_MAX_CHARS: () => THINKING_PART_MAX_CHARS,
23992
+ USAGE_ON_LIMIT_VALUES: () => USAGE_ON_LIMIT_VALUES,
23540
23993
  WORKTREE_ABLETIME_MCP_TOOLS: () => WORKTREE_ABLETIME_MCP_TOOLS,
23541
23994
  WORKTREE_GITHUB_MCP_TOOLS: () => WORKTREE_GITHUB_MCP_TOOLS,
23542
23995
  WORKTREE_LINEAR_MCP_TOOLS: () => WORKTREE_LINEAR_MCP_TOOLS,
@@ -23618,6 +24071,7 @@ __export(index_exports, {
23618
24071
  classifyWorktreeColumn: () => classifyWorktreeColumn,
23619
24072
  claudeAdapter: () => claudeAdapter,
23620
24073
  claudeChromeEnabled: () => claudeChromeEnabled,
24074
+ claudeUsageOverLimitWindows: () => claudeUsageOverLimitWindows,
23621
24075
  claudeUserSettingsPath: () => claudeUserSettingsPath,
23622
24076
  cleanupOrphanWorktrees: () => cleanupOrphanWorktrees,
23623
24077
  clearBoardPins: () => clearBoardPins,
@@ -23637,6 +24091,7 @@ __export(index_exports, {
23637
24091
  computeNextRunAt: () => computeNextRunAt,
23638
24092
  conductorBundledBinDir: () => conductorBundledBinDir,
23639
24093
  conductorDbPath: () => conductorDbPath,
24094
+ confirmClaudeUsageOverLimitEnabled: () => confirmClaudeUsageOverLimitEnabled,
23640
24095
  confirmLand: () => confirmLand,
23641
24096
  connectBrightsyTeam: () => connectBrightsyTeam,
23642
24097
  connectOptionalService: () => connectOptionalService,
@@ -23736,6 +24191,14 @@ __export(index_exports, {
23736
24191
  formatAccountProfilePlaybookLine: () => formatAccountProfilePlaybookLine,
23737
24192
  formatArtifactDirective: () => formatArtifactDirective,
23738
24193
  formatBrightsyFetchError: () => formatBrightsyFetchError,
24194
+ formatClaudeExtraUsageDetail: () => formatClaudeExtraUsageDetail,
24195
+ formatClaudeUsageCompact: () => formatClaudeUsageCompact,
24196
+ formatClaudeUsageFetchedAt: () => formatClaudeUsageFetchedAt,
24197
+ formatClaudeUsageOverLimitConfirm: () => formatClaudeUsageOverLimitConfirm,
24198
+ formatClaudeUsageOverLimitWait: () => formatClaudeUsageOverLimitWait,
24199
+ formatClaudeUsageReset: () => formatClaudeUsageReset,
24200
+ formatClaudeUsageResetClock: () => formatClaudeUsageResetClock,
24201
+ formatClaudeUsageTooltip: () => formatClaudeUsageTooltip,
23739
24202
  formatDetachedJobInvoke: () => formatDetachedJobInvoke,
23740
24203
  formatFetchError: () => formatFetchError,
23741
24204
  formatGhLandError: () => formatGhLandError,
@@ -23785,6 +24248,7 @@ __export(index_exports, {
23785
24248
  getAgentSetupInfo: () => getAgentSetupInfo,
23786
24249
  getBrightsySession: () => getBrightsySession,
23787
24250
  getCaffeinateHold: () => getCaffeinateHold,
24251
+ getClaudePlanUsage: () => getClaudePlanUsage,
23788
24252
  getDefaultAgent: () => getDefaultAgent,
23789
24253
  getDefaultEffort: () => getDefaultEffort,
23790
24254
  getDefaultFast: () => getDefaultFast,
@@ -23834,6 +24298,7 @@ __export(index_exports, {
23834
24298
  hasRepoHook: () => hasRepoHook,
23835
24299
  hasWorkspaceHook: () => hasWorkspaceHook,
23836
24300
  healOrchestrationSoccerTitles: () => healOrchestrationSoccerTitles,
24301
+ hottestClaudeWindow: () => hottestClaudeWindow,
23837
24302
  httpFetch: () => httpFetch,
23838
24303
  importConductorWorkspace: () => importConductorWorkspace,
23839
24304
  importConductorWorkspaceAsync: () => importConductorWorkspaceAsync,
@@ -23895,6 +24360,7 @@ __export(index_exports, {
23895
24360
  isThisProcessDesktopHost: () => isThisProcessDesktopHost,
23896
24361
  isThreadCaffeinated: () => isThreadCaffeinated,
23897
24362
  isThreadRecordFile: () => isThreadRecordFile,
24363
+ isUsageOnLimit: () => isUsageOnLimit,
23898
24364
  isWorkspaceScratchPath: () => isWorkspaceScratchPath,
23899
24365
  issueAttachmentForAbleTimeTask: () => issueAttachmentForAbleTimeTask,
23900
24366
  issueMatchesAssignee: () => issueMatchesAssignee,
@@ -23997,6 +24463,7 @@ __export(index_exports, {
23997
24463
  originFetchBranch: () => originFetchBranch,
23998
24464
  originGhRepoEnv: () => originGhRepoEnv,
23999
24465
  packagedDetachedJobPath: () => packagedDetachedJobPath,
24466
+ parseClaudeUsagePayload: () => parseClaudeUsagePayload,
24000
24467
  parseCursorRunnerLine: () => parseCursorRunnerLine,
24001
24468
  parseDurationMs: () => parseDurationMs,
24002
24469
  parseForceStopMessage: () => parseForceStopMessage,
@@ -24093,6 +24560,7 @@ __export(index_exports, {
24093
24560
  resolveSlackListenMode: () => resolveSlackListenMode,
24094
24561
  resolveThreadDefaults: () => resolveThreadDefaults,
24095
24562
  resolveThreadEffort: () => resolveThreadEffort,
24563
+ resolveUsageOnLimit: () => resolveUsageOnLimit,
24096
24564
  resolveVaultKey: () => resolveVaultKey,
24097
24565
  resolveViewerProfile: () => resolveViewerProfile,
24098
24566
  resolveViewerProfileForRepo: () => resolveViewerProfileForRepo,
@@ -24207,6 +24675,7 @@ __export(index_exports, {
24207
24675
  updateProjectProfileSettings: () => updateProjectProfileSettings,
24208
24676
  updateSchedule: () => updateSchedule,
24209
24677
  updateThread: () => updateThread,
24678
+ usageOnLimit: () => usageOnLimit,
24210
24679
  userClaudeMcpConfigPath: () => userClaudeMcpConfigPath,
24211
24680
  userCursorMcpConfigPath: () => userCursorMcpConfigPath,
24212
24681
  userMcpNamesToDisable: () => userMcpNamesToDisable,
@@ -26579,7 +27048,7 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
26579
27048
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
26580
27049
  var import_zod9 = require("zod");
26581
27050
  var import_node_crypto14 = require("crypto");
26582
- var import_node_path52 = require("path");
27051
+ var import_node_path53 = require("path");
26583
27052
  init_orchestrator();
26584
27053
  init_worktree();
26585
27054
  init_global_workspace();
@@ -28299,27 +28768,27 @@ init_gh_errors();
28299
28768
  init_git_auth_mode();
28300
28769
 
28301
28770
  // src/board/load-home-board.ts
28302
- var import_node_fs55 = require("fs");
28303
- var import_node_path51 = require("path");
28771
+ var import_node_fs56 = require("fs");
28772
+ var import_node_path52 = require("path");
28304
28773
  init_worktree();
28305
28774
  init_paths();
28306
28775
 
28307
28776
  // src/board/board-pins.ts
28308
28777
  var import_node_crypto13 = require("crypto");
28309
- var import_node_fs54 = require("fs");
28310
- var import_node_path50 = require("path");
28778
+ var import_node_fs55 = require("fs");
28779
+ var import_node_path51 = require("path");
28311
28780
  init_paths();
28312
28781
  init_home_board();
28313
28782
  var FILE = "home-board-pins.json";
28314
28783
  var VERSION = 1;
28315
28784
  function pinsFile() {
28316
- return (0, import_node_path50.join)(appDataDir(), FILE);
28785
+ return (0, import_node_path51.join)(appDataDir(), FILE);
28317
28786
  }
28318
28787
  function readDisk() {
28319
28788
  const path2 = pinsFile();
28320
- if (!(0, import_node_fs54.existsSync)(path2)) return [];
28789
+ if (!(0, import_node_fs55.existsSync)(path2)) return [];
28321
28790
  try {
28322
- const raw = JSON.parse((0, import_node_fs54.readFileSync)(path2, "utf8"));
28791
+ const raw = JSON.parse((0, import_node_fs55.readFileSync)(path2, "utf8"));
28323
28792
  if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
28324
28793
  return raw.items.filter((item) => item?.id && item.kind && item.ref);
28325
28794
  } catch {
@@ -28327,8 +28796,8 @@ function readDisk() {
28327
28796
  }
28328
28797
  }
28329
28798
  function writeDisk(items) {
28330
- (0, import_node_fs54.mkdirSync)(appDataDir(), { recursive: true });
28331
- (0, import_node_fs54.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
28799
+ (0, import_node_fs55.mkdirSync)(appDataDir(), { recursive: true });
28800
+ (0, import_node_fs55.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
28332
28801
  }
28333
28802
  function listBoardPins() {
28334
28803
  return readDisk();
@@ -28380,7 +28849,7 @@ function replaceBoardPins(items) {
28380
28849
  }
28381
28850
  function clearBoardPins() {
28382
28851
  try {
28383
- (0, import_node_fs54.unlinkSync)(pinsFile());
28852
+ (0, import_node_fs55.unlinkSync)(pinsFile());
28384
28853
  } catch {
28385
28854
  }
28386
28855
  }
@@ -28389,7 +28858,7 @@ function clearBoardPins() {
28389
28858
  init_home_board();
28390
28859
  var CACHE_VERSION = 1;
28391
28860
  var memory2 = null;
28392
- var inflight = null;
28861
+ var inflight2 = null;
28393
28862
  function errText(err) {
28394
28863
  return err instanceof Error ? err.message : String(err);
28395
28864
  }
@@ -28397,7 +28866,7 @@ function homeBoardWorkspaceKey(workspaces) {
28397
28866
  return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
28398
28867
  }
28399
28868
  function cacheFile() {
28400
- return (0, import_node_path51.join)(appDataDir(), "home-board-cache.json");
28869
+ return (0, import_node_path52.join)(appDataDir(), "home-board-cache.json");
28401
28870
  }
28402
28871
  function emptyInputs() {
28403
28872
  return {
@@ -28423,9 +28892,9 @@ function shouldCacheHomeBoardInputs(inputs) {
28423
28892
  }
28424
28893
  function readDiskCache() {
28425
28894
  const path2 = cacheFile();
28426
- if (!(0, import_node_fs55.existsSync)(path2)) return null;
28895
+ if (!(0, import_node_fs56.existsSync)(path2)) return null;
28427
28896
  try {
28428
- const raw = JSON.parse((0, import_node_fs55.readFileSync)(path2, "utf8"));
28897
+ const raw = JSON.parse((0, import_node_fs56.readFileSync)(path2, "utf8"));
28429
28898
  if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
28430
28899
  return null;
28431
28900
  }
@@ -28439,20 +28908,20 @@ function readDiskCache() {
28439
28908
  }
28440
28909
  function writeDiskCache(entry) {
28441
28910
  try {
28442
- (0, import_node_fs55.mkdirSync)(appDataDir(), { recursive: true });
28443
- (0, import_node_fs55.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
28911
+ (0, import_node_fs56.mkdirSync)(appDataDir(), { recursive: true });
28912
+ (0, import_node_fs56.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
28444
28913
  } catch {
28445
28914
  }
28446
28915
  }
28447
28916
  function deleteDiskCache() {
28448
28917
  try {
28449
- (0, import_node_fs55.unlinkSync)(cacheFile());
28918
+ (0, import_node_fs56.unlinkSync)(cacheFile());
28450
28919
  } catch {
28451
28920
  }
28452
28921
  }
28453
28922
  function resetHomeBoardMemory() {
28454
28923
  memory2 = null;
28455
- inflight = null;
28924
+ inflight2 = null;
28456
28925
  }
28457
28926
  function clearHomeBoardCache() {
28458
28927
  resetHomeBoardMemory();
@@ -28551,8 +29020,8 @@ async function getHomeBoardInputs(workspaces, opts) {
28551
29020
  return asLoaded(best, true);
28552
29021
  }
28553
29022
  }
28554
- if (inflight && inflight.key === key) {
28555
- return inflight.promise;
29023
+ if (inflight2 && inflight2.key === key) {
29024
+ return inflight2.promise;
28556
29025
  }
28557
29026
  const promise = (async () => {
28558
29027
  const inputs = await loadHomeBoardInputs(workspaces);
@@ -28572,11 +29041,11 @@ async function getHomeBoardInputs(workspaces, opts) {
28572
29041
  }
28573
29042
  return loaded;
28574
29043
  })();
28575
- inflight = { key, promise };
29044
+ inflight2 = { key, promise };
28576
29045
  try {
28577
29046
  return await promise;
28578
29047
  } finally {
28579
- if (inflight?.promise === promise) inflight = null;
29048
+ if (inflight2?.promise === promise) inflight2 = null;
28580
29049
  }
28581
29050
  }
28582
29051
 
@@ -28796,7 +29265,7 @@ async function startMcpServer() {
28796
29265
  async () => {
28797
29266
  const threads = orch.getThreads(true);
28798
29267
  const lines = threads.map((t) => {
28799
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path52.basename)(t.repoPath) || t.repoPath;
29268
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path53.basename)(t.repoPath) || t.repoPath;
28800
29269
  const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
28801
29270
  const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
28802
29271
  const preview = lastMessagePreview(t.messages, 80);
@@ -31763,9 +32232,9 @@ var import_node_http3 = require("http");
31763
32232
  var import_ws3 = require("ws");
31764
32233
 
31765
32234
  // src/slack/relay-static.ts
31766
- var import_node_fs56 = require("fs");
32235
+ var import_node_fs57 = require("fs");
31767
32236
  var import_promises = require("fs/promises");
31768
- var import_node_path53 = __toESM(require("path"), 1);
32237
+ var import_node_path54 = __toESM(require("path"), 1);
31769
32238
  var TYPES = {
31770
32239
  ".css": "text/css; charset=utf-8",
31771
32240
  ".html": "text/html; charset=utf-8",
@@ -31796,9 +32265,9 @@ function resolveStaticPath(root, requestUrl) {
31796
32265
  return null;
31797
32266
  }
31798
32267
  if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
31799
- const rootResolved = import_node_path53.default.resolve(root);
31800
- const candidate = import_node_path53.default.resolve(rootResolved, `.${pathname}`);
31801
- if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path53.default.sep)) {
32268
+ const rootResolved = import_node_path54.default.resolve(root);
32269
+ const candidate = import_node_path54.default.resolve(rootResolved, `.${pathname}`);
32270
+ if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path54.default.sep)) {
31802
32271
  return null;
31803
32272
  }
31804
32273
  return candidate;
@@ -31812,7 +32281,7 @@ async function fileSize(file) {
31812
32281
  }
31813
32282
  }
31814
32283
  function sendFile(req, res, file, size) {
31815
- const ext = import_node_path53.default.extname(file).toLowerCase();
32284
+ const ext = import_node_path54.default.extname(file).toLowerCase();
31816
32285
  res.writeHead(200, {
31817
32286
  "Content-Type": TYPES[ext] ?? "application/octet-stream",
31818
32287
  "Content-Length": size,
@@ -31822,7 +32291,7 @@ function sendFile(req, res, file, size) {
31822
32291
  res.end();
31823
32292
  return true;
31824
32293
  }
31825
- (0, import_node_fs56.createReadStream)(file).pipe(res);
32294
+ (0, import_node_fs57.createReadStream)(file).pipe(res);
31826
32295
  return true;
31827
32296
  }
31828
32297
  async function tryServeStatic(req, res, root) {
@@ -31831,7 +32300,7 @@ async function tryServeStatic(req, res, root) {
31831
32300
  if (!candidate) return false;
31832
32301
  const direct = await fileSize(candidate);
31833
32302
  if (direct != null) return sendFile(req, res, candidate, direct);
31834
- const asIndex = import_node_path53.default.join(candidate, "index.html");
32303
+ const asIndex = import_node_path54.default.join(candidate, "index.html");
31835
32304
  const indexSize = await fileSize(asIndex);
31836
32305
  if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
31837
32306
  return false;
@@ -32155,6 +32624,7 @@ init_outbound_watch();
32155
32624
  SlackRelayHub,
32156
32625
  THINKING_EFFORTS,
32157
32626
  THINKING_PART_MAX_CHARS,
32627
+ USAGE_ON_LIMIT_VALUES,
32158
32628
  WORKTREE_ABLETIME_MCP_TOOLS,
32159
32629
  WORKTREE_GITHUB_MCP_TOOLS,
32160
32630
  WORKTREE_LINEAR_MCP_TOOLS,
@@ -32236,6 +32706,7 @@ init_outbound_watch();
32236
32706
  classifyWorktreeColumn,
32237
32707
  claudeAdapter,
32238
32708
  claudeChromeEnabled,
32709
+ claudeUsageOverLimitWindows,
32239
32710
  claudeUserSettingsPath,
32240
32711
  cleanupOrphanWorktrees,
32241
32712
  clearBoardPins,
@@ -32255,6 +32726,7 @@ init_outbound_watch();
32255
32726
  computeNextRunAt,
32256
32727
  conductorBundledBinDir,
32257
32728
  conductorDbPath,
32729
+ confirmClaudeUsageOverLimitEnabled,
32258
32730
  confirmLand,
32259
32731
  connectBrightsyTeam,
32260
32732
  connectOptionalService,
@@ -32354,6 +32826,14 @@ init_outbound_watch();
32354
32826
  formatAccountProfilePlaybookLine,
32355
32827
  formatArtifactDirective,
32356
32828
  formatBrightsyFetchError,
32829
+ formatClaudeExtraUsageDetail,
32830
+ formatClaudeUsageCompact,
32831
+ formatClaudeUsageFetchedAt,
32832
+ formatClaudeUsageOverLimitConfirm,
32833
+ formatClaudeUsageOverLimitWait,
32834
+ formatClaudeUsageReset,
32835
+ formatClaudeUsageResetClock,
32836
+ formatClaudeUsageTooltip,
32357
32837
  formatDetachedJobInvoke,
32358
32838
  formatFetchError,
32359
32839
  formatGhLandError,
@@ -32403,6 +32883,7 @@ init_outbound_watch();
32403
32883
  getAgentSetupInfo,
32404
32884
  getBrightsySession,
32405
32885
  getCaffeinateHold,
32886
+ getClaudePlanUsage,
32406
32887
  getDefaultAgent,
32407
32888
  getDefaultEffort,
32408
32889
  getDefaultFast,
@@ -32452,6 +32933,7 @@ init_outbound_watch();
32452
32933
  hasRepoHook,
32453
32934
  hasWorkspaceHook,
32454
32935
  healOrchestrationSoccerTitles,
32936
+ hottestClaudeWindow,
32455
32937
  httpFetch,
32456
32938
  importConductorWorkspace,
32457
32939
  importConductorWorkspaceAsync,
@@ -32513,6 +32995,7 @@ init_outbound_watch();
32513
32995
  isThisProcessDesktopHost,
32514
32996
  isThreadCaffeinated,
32515
32997
  isThreadRecordFile,
32998
+ isUsageOnLimit,
32516
32999
  isWorkspaceScratchPath,
32517
33000
  issueAttachmentForAbleTimeTask,
32518
33001
  issueMatchesAssignee,
@@ -32615,6 +33098,7 @@ init_outbound_watch();
32615
33098
  originFetchBranch,
32616
33099
  originGhRepoEnv,
32617
33100
  packagedDetachedJobPath,
33101
+ parseClaudeUsagePayload,
32618
33102
  parseCursorRunnerLine,
32619
33103
  parseDurationMs,
32620
33104
  parseForceStopMessage,
@@ -32711,6 +33195,7 @@ init_outbound_watch();
32711
33195
  resolveSlackListenMode,
32712
33196
  resolveThreadDefaults,
32713
33197
  resolveThreadEffort,
33198
+ resolveUsageOnLimit,
32714
33199
  resolveVaultKey,
32715
33200
  resolveViewerProfile,
32716
33201
  resolveViewerProfileForRepo,
@@ -32825,6 +33310,7 @@ init_outbound_watch();
32825
33310
  updateProjectProfileSettings,
32826
33311
  updateSchedule,
32827
33312
  updateThread,
33313
+ usageOnLimit,
32828
33314
  userClaudeMcpConfigPath,
32829
33315
  userCursorMcpConfigPath,
32830
33316
  userMcpNamesToDisable,