@sideboard-ai/core 0.1.207 → 0.1.209

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 (51) hide show
  1. package/dist/{abletime-I4IYZBKU.js → abletime-G3MWSZVM.js} +4 -4
  2. package/dist/{abletime-UWSSLXH3.js → abletime-SQREWITG.js} +4 -4
  3. package/dist/{abletime-oauth-UZHPB3W2.js → abletime-oauth-7AOE4KJL.js} +3 -3
  4. package/dist/{abletime-oauth-C3BQXKW3.js → abletime-oauth-SQD6K47H.js} +3 -3
  5. package/dist/{abletime-rest-5YPPEOKK.js → abletime-rest-BXL7QHCX.js} +3 -3
  6. package/dist/{abletime-rest-HYNYDYK3.js → abletime-rest-QRTJH42S.js} +3 -3
  7. package/dist/agents/cursor-runner.js +3 -3
  8. package/dist/{agents-7MULGRPU.js → agents-KA6HDNNP.js} +6 -5
  9. package/dist/{agents-KCBCFMFW.js → agents-U2NVCYGC.js} +6 -5
  10. package/dist/{app-settings-R2KNCT37.js → app-settings-6SZLZNA7.js} +7 -1
  11. package/dist/{app-settings-GJ6KDYEF.js → app-settings-VBQHGX5Z.js} +7 -1
  12. package/dist/{chunk-6KH4OBEW.js → chunk-22A45QOI.js} +2 -2
  13. package/dist/{chunk-N4A4NWFO.js → chunk-42VGWRSE.js} +2 -2
  14. package/dist/{chunk-X45BV4VX.js → chunk-5LFD3KCJ.js} +5 -5
  15. package/dist/{chunk-F4LZUEIO.js → chunk-B2RPIHNJ.js} +2 -2
  16. package/dist/{chunk-6YZLSZLK.js → chunk-CQZCXRVG.js} +3 -3
  17. package/dist/{chunk-4EGK47WV.js → chunk-FUC3XFE2.js} +215 -0
  18. package/dist/{chunk-5UQTT4S7.js → chunk-HBL7ILQA.js} +154 -31
  19. package/dist/{chunk-TEDEVD4O.js → chunk-IIENQFJ6.js} +2 -2
  20. package/dist/{chunk-6J4OQ6TF.js → chunk-IOOL3T7Q.js} +3 -3
  21. package/dist/{chunk-A2BRWIEM.js → chunk-KJAHVQL6.js} +51 -94
  22. package/dist/{chunk-ZU7R35NY.js → chunk-MS2P5GXL.js} +49 -87
  23. package/dist/{chunk-2GPZ4BAU.js → chunk-MZP2C4KE.js} +158 -31
  24. package/dist/{chunk-ARR4OGLY.js → chunk-OY7THBLG.js} +12 -2
  25. package/dist/{chunk-QOJB5PC7.js → chunk-PTOIWKDU.js} +3 -3
  26. package/dist/{chunk-W6X4GZJG.js → chunk-QVVJO4GN.js} +3 -3
  27. package/dist/{chunk-DWGEBZ3C.js → chunk-RPZFNKND.js} +12 -2
  28. package/dist/{chunk-PAQPT3JO.js → chunk-TZCWNRMC.js} +3 -3
  29. package/dist/{chunk-Y4CF7LHH.js → chunk-VJQDUD24.js} +230 -0
  30. package/dist/chunk-X5B3OS5I.js +34 -0
  31. package/dist/{chunk-WXWJ5MJ4.js → chunk-XRIF6M5H.js} +5 -5
  32. package/dist/{coordinator-prompt-6NV2IHEX.js → coordinator-prompt-2YCOE5R4.js} +5 -4
  33. package/dist/{coordinator-prompt-6A3D7BV3.js → coordinator-prompt-EO2X2EYW.js} +5 -4
  34. package/dist/{cursor-recover-TXVTLAMA.js → cursor-recover-4PQAADAU.js} +3 -28
  35. package/dist/{global-workspace-I2X6UQMX.js → global-workspace-H2ANUSGR.js} +5 -4
  36. package/dist/{global-workspace-VS6HZF2I.js → global-workspace-JEKMVE42.js} +5 -4
  37. package/dist/index.cjs +752 -391
  38. package/dist/index.d.cts +127 -5
  39. package/dist/index.d.ts +127 -5
  40. package/dist/index.js +63 -19
  41. package/dist/mcp/run-stdio.cjs +706 -391
  42. package/dist/mcp/run-stdio.js +12 -11
  43. package/dist/{orchestrator-CXQY5YRG.js → orchestrator-N7LLTK5O.js} +7 -6
  44. package/dist/{orchestrator-7WF32ZXJ.js → orchestrator-RUQXDYM7.js} +7 -6
  45. package/dist/{thread-store-XGYWXR2P.js → thread-store-55X2JYDT.js} +2 -1
  46. package/dist/{thread-store-LS2T6RVH.js → thread-store-CMZWM5NY.js} +2 -1
  47. package/dist/{workspaces-CEU25ANO.js → workspaces-2YNYLSPV.js} +5 -4
  48. package/dist/{workspaces-7PM7UGLG.js → workspaces-SVDORZEI.js} +5 -4
  49. package/dist/{worktree-YD7Y6NRY.js → worktree-5CPGB4D2.js} +4 -3
  50. package/dist/{worktree-T6PCOIHZ.js → worktree-YQ6XUSR2.js} +4 -3
  51. package/package.json +1 -1
@@ -801,6 +801,37 @@ var init_thinking_effort = __esm({
801
801
  }
802
802
  });
803
803
 
804
+ // src/agents/cursor-store.ts
805
+ function cursorSdkStoreDir(threadId) {
806
+ const root = (0, import_node_path8.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
807
+ const id = sanitizeCursorStoreSegment(threadId);
808
+ if (!id) return root;
809
+ return (0, import_node_path8.join)(root, "threads", id);
810
+ }
811
+ function cursorSdkRunsNdjsonPath(threadId) {
812
+ return (0, import_node_path8.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
813
+ }
814
+ function cursorSdkRunsNdjsonSearchPaths(threadId) {
815
+ const scoped = cursorSdkRunsNdjsonPath(threadId);
816
+ const shared = cursorSdkRunsNdjsonPath(null);
817
+ if (!threadId || !sanitizeCursorStoreSegment(threadId) || scoped === shared) {
818
+ return [shared];
819
+ }
820
+ return [scoped, shared];
821
+ }
822
+ function sanitizeCursorStoreSegment(threadId) {
823
+ return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
824
+ }
825
+ var import_node_path8, CURSOR_SDK_STORE_DIR;
826
+ var init_cursor_store = __esm({
827
+ "src/agents/cursor-store.ts"() {
828
+ "use strict";
829
+ import_node_path8 = require("path");
830
+ init_paths();
831
+ CURSOR_SDK_STORE_DIR = "cursor-sdk-store";
832
+ }
833
+ });
834
+
804
835
  // src/store/thread-store.ts
805
836
  var thread_store_exports = {};
806
837
  __export(thread_store_exports, {
@@ -841,6 +872,7 @@ function normalizeThread(raw) {
841
872
  lastError: raw.lastError ?? null,
842
873
  agentPid: raw.agentPid ?? null,
843
874
  attachments: Array.isArray(raw.attachments) ? raw.attachments : [],
875
+ pendingTurnAttachments: Array.isArray(raw.pendingTurnAttachments) ? raw.pendingTurnAttachments : [],
844
876
  prTitle: raw.prTitle ?? null,
845
877
  prState: raw.prState ?? null,
846
878
  prIsDraft: Boolean(raw.prIsDraft),
@@ -883,6 +915,7 @@ function createEmptyThread(partial) {
883
915
  userSetTitle: partial.userSetTitle ?? false,
884
916
  messages: partial.messages ?? [],
885
917
  attachments: partial.attachments ?? [],
918
+ pendingTurnAttachments: partial.pendingTurnAttachments ?? [],
886
919
  createdAt: ts,
887
920
  updatedAt: ts,
888
921
  title: partial.title,
@@ -956,10 +989,10 @@ function readThread(id) {
956
989
  rememberThread(thread, mtimeMs);
957
990
  return thread;
958
991
  }
959
- function writeThread(thread) {
992
+ function writeThread(thread, opts) {
960
993
  const path = threadFilePath(idPath(thread.id));
961
994
  const tmp = `${path}.${process.pid}.tmp`;
962
- const next = { ...thread, updatedAt: nowIso() };
995
+ const next = opts?.touch === false ? { ...thread } : { ...thread, updatedAt: nowIso() };
963
996
  (0, import_node_fs8.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
964
997
  (0, import_node_fs8.renameSync)(tmp, path);
965
998
  rememberThread(next, fileMtimeMs(path) ?? Date.now());
@@ -968,7 +1001,7 @@ function idPath(id) {
968
1001
  return id;
969
1002
  }
970
1003
  function isThreadRecordFile(nameOrPath) {
971
- const name = (0, import_node_path8.basename)(nameOrPath);
1004
+ const name = (0, import_node_path9.basename)(nameOrPath);
972
1005
  return name.endsWith(".json") && !name.endsWith(".live.json");
973
1006
  }
974
1007
  function listThreads(opts) {
@@ -1004,6 +1037,10 @@ function deleteThreadRecord(id) {
1004
1037
  } catch {
1005
1038
  }
1006
1039
  }
1040
+ try {
1041
+ (0, import_node_fs8.rmSync)(cursorSdkStoreDir(id), { recursive: true, force: true });
1042
+ } catch {
1043
+ }
1007
1044
  }
1008
1045
  function updateThread(id, patch) {
1009
1046
  const current = readThread(id);
@@ -1026,15 +1063,16 @@ function findThreadByRef(ref) {
1026
1063
  (t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref
1027
1064
  ) ?? null;
1028
1065
  }
1029
- var import_node_crypto2, import_node_fs8, import_node_path8, import_proper_lockfile, listCache;
1066
+ var import_node_crypto2, import_node_fs8, import_node_path9, import_proper_lockfile, listCache;
1030
1067
  var init_thread_store = __esm({
1031
1068
  "src/store/thread-store.ts"() {
1032
1069
  "use strict";
1033
1070
  import_node_crypto2 = require("crypto");
1034
1071
  import_node_fs8 = require("fs");
1035
- import_node_path8 = require("path");
1072
+ import_node_path9 = require("path");
1036
1073
  import_proper_lockfile = __toESM(require("proper-lockfile"), 1);
1037
1074
  init_thinking_effort();
1075
+ init_cursor_store();
1038
1076
  init_paths();
1039
1077
  listCache = null;
1040
1078
  }
@@ -1084,7 +1122,7 @@ var init_api = __esm({
1084
1122
 
1085
1123
  // src/slack/reply-target.ts
1086
1124
  function storePath() {
1087
- return (0, import_node_path9.join)(appDataDir(), "slack-reply-to.json");
1125
+ return (0, import_node_path10.join)(appDataDir(), "slack-reply-to.json");
1088
1126
  }
1089
1127
  function readStore() {
1090
1128
  const path = storePath();
@@ -1099,12 +1137,12 @@ function readStore() {
1099
1137
  function getSlackReplyTarget(threadId) {
1100
1138
  return readStore()[threadId] ?? null;
1101
1139
  }
1102
- var import_node_fs9, import_node_path9;
1140
+ var import_node_fs9, import_node_path10;
1103
1141
  var init_reply_target = __esm({
1104
1142
  "src/slack/reply-target.ts"() {
1105
1143
  "use strict";
1106
1144
  import_node_fs9 = require("fs");
1107
- import_node_path9 = require("path");
1145
+ import_node_path10 = require("path");
1108
1146
  init_paths();
1109
1147
  init_private_file();
1110
1148
  init_secure_file();
@@ -1113,7 +1151,7 @@ var init_reply_target = __esm({
1113
1151
 
1114
1152
  // src/slack/workspaces.ts
1115
1153
  function storePath2() {
1116
- return (0, import_node_path10.join)(appDataDir(), "slack-workspaces.json");
1154
+ return (0, import_node_path11.join)(appDataDir(), "slack-workspaces.json");
1117
1155
  }
1118
1156
  function readStore2() {
1119
1157
  try {
@@ -1174,11 +1212,11 @@ function requireSlackWorkspace(teamId) {
1174
1212
  }
1175
1213
  return ws;
1176
1214
  }
1177
- var import_node_path10;
1215
+ var import_node_path11;
1178
1216
  var init_workspaces = __esm({
1179
1217
  "src/slack/workspaces.ts"() {
1180
1218
  "use strict";
1181
- import_node_path10 = require("path");
1219
+ import_node_path11 = require("path");
1182
1220
  init_paths();
1183
1221
  init_secure_file();
1184
1222
  init_api();
@@ -1187,7 +1225,7 @@ var init_workspaces = __esm({
1187
1225
 
1188
1226
  // src/slack/outbound-watch.ts
1189
1227
  function storePath3() {
1190
- return (0, import_node_path11.join)(appDataDir(), "slack-outbound-watch.json");
1228
+ return (0, import_node_path12.join)(appDataDir(), "slack-outbound-watch.json");
1191
1229
  }
1192
1230
  function watchId(teamId, channelId, ts) {
1193
1231
  return `${teamId}:${channelId}:${ts}`;
@@ -1524,12 +1562,12 @@ async function pollSlackOutboundWatches(opts) {
1524
1562
  }
1525
1563
  if (changed) writeStore(watches);
1526
1564
  }
1527
- var import_node_fs10, import_node_path11, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
1565
+ var import_node_fs10, import_node_path12, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
1528
1566
  var init_outbound_watch = __esm({
1529
1567
  "src/slack/outbound-watch.ts"() {
1530
1568
  "use strict";
1531
1569
  import_node_fs10 = require("fs");
1532
- import_node_path11 = require("path");
1570
+ import_node_path12 = require("path");
1533
1571
  init_paths();
1534
1572
  init_private_file();
1535
1573
  init_secure_file();
@@ -1927,23 +1965,23 @@ var init_error_detail = __esm({
1927
1965
  function prependPathDir(env, dir) {
1928
1966
  if (!dir || !(0, import_node_fs11.existsSync)(dir)) return;
1929
1967
  const current = env.PATH ?? "";
1930
- const parts = current.split(import_node_path12.delimiter).filter(Boolean);
1968
+ const parts = current.split(import_node_path13.delimiter).filter(Boolean);
1931
1969
  if (parts.includes(dir)) {
1932
1970
  env.PATH = current;
1933
1971
  return;
1934
1972
  }
1935
- env.PATH = [dir, ...parts].join(import_node_path12.delimiter);
1973
+ env.PATH = [dir, ...parts].join(import_node_path13.delimiter);
1936
1974
  }
1937
1975
  function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os3.homedir)()) {
1938
- return (0, import_node_path12.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
1976
+ return (0, import_node_path13.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
1939
1977
  }
1940
1978
  function ensureAgentPath(env = process.env) {
1941
1979
  const home = env.HOME || env.USERPROFILE || (0, import_node_os3.homedir)();
1942
1980
  const current = env.PATH ?? "";
1943
- const parts = current.split(import_node_path12.delimiter).filter(Boolean);
1981
+ const parts = current.split(import_node_path13.delimiter).filter(Boolean);
1944
1982
  const seen = new Set(parts);
1945
1983
  const extras = [
1946
- ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path12.join)(home, rel)),
1984
+ ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path13.join)(home, rel)),
1947
1985
  "/opt/homebrew/bin",
1948
1986
  "/usr/local/bin",
1949
1987
  // Keep after Homebrew/npm so a user-installed CLI still wins.
@@ -1954,7 +1992,7 @@ function ensureAgentPath(env = process.env) {
1954
1992
  parts.unshift(dir);
1955
1993
  seen.add(dir);
1956
1994
  }
1957
- const next = parts.join(import_node_path12.delimiter);
1995
+ const next = parts.join(import_node_path13.delimiter);
1958
1996
  env.PATH = next;
1959
1997
  return next;
1960
1998
  }
@@ -1968,21 +2006,21 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
1968
2006
  stdio: ["ignore", "pipe", "ignore"]
1969
2007
  }).trim().split(/\r?\n/).find(Boolean);
1970
2008
  if (prefix) {
1971
- const binDir = process.platform === "win32" ? prefix : (0, import_node_path12.join)(prefix, "bin");
2009
+ const binDir = process.platform === "win32" ? prefix : (0, import_node_path13.join)(prefix, "bin");
1972
2010
  prependPathDir(env, binDir);
1973
2011
  }
1974
2012
  } catch {
1975
2013
  }
1976
2014
  return env.PATH ?? "";
1977
2015
  }
1978
- var import_node_fs11, import_node_child_process3, import_node_os3, import_node_path12, EXTRA_BIN_DIRS;
2016
+ var import_node_fs11, import_node_child_process3, import_node_os3, import_node_path13, EXTRA_BIN_DIRS;
1979
2017
  var init_path = __esm({
1980
2018
  "src/agents/path.ts"() {
1981
2019
  "use strict";
1982
2020
  import_node_fs11 = require("fs");
1983
2021
  import_node_child_process3 = require("child_process");
1984
2022
  import_node_os3 = require("os");
1985
- import_node_path12 = require("path");
2023
+ import_node_path13 = require("path");
1986
2024
  EXTRA_BIN_DIRS = [
1987
2025
  ".local/bin",
1988
2026
  ".cargo/bin",
@@ -2003,18 +2041,18 @@ var init_path = __esm({
2003
2041
  function githubAgentAuthDir() {
2004
2042
  const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
2005
2043
  if (override) return override;
2006
- return (0, import_node_path13.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
2044
+ return (0, import_node_path14.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
2007
2045
  }
2008
2046
  function githubCredentialStorePath() {
2009
- return (0, import_node_path13.join)(githubAgentAuthDir(), "git-credentials");
2047
+ return (0, import_node_path14.join)(githubAgentAuthDir(), "git-credentials");
2010
2048
  }
2011
2049
  function githubGhConfigDir() {
2012
- return (0, import_node_path13.join)(githubAgentAuthDir(), "gh");
2050
+ return (0, import_node_path14.join)(githubAgentAuthDir(), "gh");
2013
2051
  }
2014
2052
  function writePrivateFile2(file, body) {
2015
- (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file), { recursive: true, mode: 448 });
2053
+ (0, import_node_fs12.mkdirSync)((0, import_node_path14.dirname)(file), { recursive: true, mode: 448 });
2016
2054
  try {
2017
- (0, import_node_fs12.chmodSync)((0, import_node_path13.dirname)(file), 448);
2055
+ (0, import_node_fs12.chmodSync)((0, import_node_path14.dirname)(file), 448);
2018
2056
  } catch {
2019
2057
  }
2020
2058
  (0, import_node_fs12.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
@@ -2052,11 +2090,11 @@ function materializeGithubAgentAuth(token, user) {
2052
2090
  writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
2053
2091
  const ghDir = githubGhConfigDir();
2054
2092
  (0, import_node_fs12.mkdirSync)(ghDir, { recursive: true, mode: 448 });
2055
- writePrivateFile2((0, import_node_path13.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
2056
- writePrivateFile2((0, import_node_path13.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
2093
+ writePrivateFile2((0, import_node_path14.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
2094
+ writePrivateFile2((0, import_node_path14.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
2057
2095
  }
2058
2096
  function githubAgentAuthReady() {
2059
- return (0, import_node_fs12.existsSync)(githubCredentialStorePath()) && (0, import_node_fs12.existsSync)((0, import_node_path13.join)(githubGhConfigDir(), "hosts.yml"));
2097
+ return (0, import_node_fs12.existsSync)(githubCredentialStorePath()) && (0, import_node_fs12.existsSync)((0, import_node_path14.join)(githubGhConfigDir(), "hosts.yml"));
2060
2098
  }
2061
2099
  function githubCredentialHelperGitConfig() {
2062
2100
  const file = githubCredentialStorePath();
@@ -2071,13 +2109,13 @@ function githubGhConfigEnv() {
2071
2109
  GH_PROMPT_DISABLED: "1"
2072
2110
  };
2073
2111
  }
2074
- var import_node_fs12, import_node_os4, import_node_path13;
2112
+ var import_node_fs12, import_node_os4, import_node_path14;
2075
2113
  var init_github_agent_auth = __esm({
2076
2114
  "src/git/github-agent-auth.ts"() {
2077
2115
  "use strict";
2078
2116
  import_node_fs12 = require("fs");
2079
2117
  import_node_os4 = require("os");
2080
- import_node_path13 = require("path");
2118
+ import_node_path14 = require("path");
2081
2119
  }
2082
2120
  });
2083
2121
 
@@ -2086,7 +2124,7 @@ function isIndexLockError(text7) {
2086
2124
  return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text7);
2087
2125
  }
2088
2126
  function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
2089
- const lockPath = (0, import_node_path14.join)(gitDir, "index.lock");
2127
+ const lockPath = (0, import_node_path15.join)(gitDir, "index.lock");
2090
2128
  try {
2091
2129
  if (!(0, import_node_fs13.existsSync)(lockPath)) return null;
2092
2130
  if (now - (0, import_node_fs13.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
@@ -2105,12 +2143,12 @@ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
2105
2143
  }
2106
2144
  return removed;
2107
2145
  }
2108
- var import_node_fs13, import_node_path14, STALE_INDEX_LOCK_MS;
2146
+ var import_node_fs13, import_node_path15, STALE_INDEX_LOCK_MS;
2109
2147
  var init_stale_lock = __esm({
2110
2148
  "src/git/stale-lock.ts"() {
2111
2149
  "use strict";
2112
2150
  import_node_fs13 = require("fs");
2113
- import_node_path14 = require("path");
2151
+ import_node_path15 = require("path");
2114
2152
  STALE_INDEX_LOCK_MS = 2e4;
2115
2153
  }
2116
2154
  });
@@ -3220,8 +3258,8 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
3220
3258
  if (gitDir.exitCode !== 0) return;
3221
3259
  const dir = gitDir.stdout.trim();
3222
3260
  if (!dir) return;
3223
- const excludePath = (0, import_node_path15.join)(dir, "info", "exclude");
3224
- (0, import_node_fs14.mkdirSync)((0, import_node_path15.dirname)(excludePath), { recursive: true });
3261
+ const excludePath = (0, import_node_path16.join)(dir, "info", "exclude");
3262
+ (0, import_node_fs14.mkdirSync)((0, import_node_path16.dirname)(excludePath), { recursive: true });
3225
3263
  let body = "";
3226
3264
  try {
3227
3265
  body = (0, import_node_fs14.readFileSync)(excludePath, "utf8");
@@ -3255,12 +3293,12 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
3255
3293
  timeoutMs: 8e3
3256
3294
  });
3257
3295
  }
3258
- var import_node_fs14, import_node_path15, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
3296
+ var import_node_fs14, import_node_path16, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
3259
3297
  var init_worktree_exclude = __esm({
3260
3298
  "src/git/worktree-exclude.ts"() {
3261
3299
  "use strict";
3262
3300
  import_node_fs14 = require("fs");
3263
- import_node_path15 = require("path");
3301
+ import_node_path16 = require("path");
3264
3302
  init_run();
3265
3303
  WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
3266
3304
  WORKTREE_CONTEXT_EXCLUDE = ".context/";
@@ -3411,7 +3449,7 @@ var init_account_profile = __esm({
3411
3449
 
3412
3450
  // src/store/secret-vault.ts
3413
3451
  function secretVaultPath() {
3414
- return (0, import_node_path16.join)(appDataDir(), "secrets.json");
3452
+ return (0, import_node_path17.join)(appDataDir(), "secrets.json");
3415
3453
  }
3416
3454
  function loadSecretVault() {
3417
3455
  const parsed = readSecureJson(secretVaultPath());
@@ -3473,11 +3511,11 @@ function normalizeVault(raw) {
3473
3511
  }
3474
3512
  return out;
3475
3513
  }
3476
- var import_node_path16;
3514
+ var import_node_path17;
3477
3515
  var init_secret_vault = __esm({
3478
3516
  "src/store/secret-vault.ts"() {
3479
3517
  "use strict";
3480
- import_node_path16 = require("path");
3518
+ import_node_path17 = require("path");
3481
3519
  init_paths();
3482
3520
  init_secure_file();
3483
3521
  }
@@ -3509,6 +3547,177 @@ var init_branch_prefix = __esm({
3509
3547
  }
3510
3548
  });
3511
3549
 
3550
+ // src/agents/usage.ts
3551
+ function sumOptional(a, b) {
3552
+ if (a == null && b == null) return void 0;
3553
+ return (a ?? 0) + (b ?? 0);
3554
+ }
3555
+ function fromInclusiveInputUsage(opts) {
3556
+ const totalInput = Number(opts.inputTokens) || 0;
3557
+ const outputTokens = Number(opts.outputTokens) || 0;
3558
+ const cached = Number(opts.cachedInputTokens) || 0;
3559
+ if (!totalInput && !outputTokens) return null;
3560
+ const cacheReadTokens = cached > 0 ? Math.min(cached, totalInput) : 0;
3561
+ return {
3562
+ inputTokens: Math.max(0, totalInput - cacheReadTokens),
3563
+ outputTokens,
3564
+ cacheReadTokens: cacheReadTokens || void 0
3565
+ };
3566
+ }
3567
+ function requestOccupancy(u) {
3568
+ return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
3569
+ }
3570
+ function mergeUsage(a, b) {
3571
+ return {
3572
+ inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
3573
+ outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
3574
+ cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
3575
+ cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
3576
+ costUsd: sumOptional(a?.costUsd, b.costUsd),
3577
+ lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
3578
+ };
3579
+ }
3580
+ function sumUsageList(list) {
3581
+ let acc = null;
3582
+ for (const u of list) {
3583
+ if (!u) continue;
3584
+ acc = mergeUsage(acc, {
3585
+ inputTokens: u.inputTokens,
3586
+ outputTokens: u.outputTokens,
3587
+ cacheReadTokens: u.cacheReadTokens,
3588
+ cacheWriteTokens: u.cacheWriteTokens,
3589
+ costUsd: u.costUsd
3590
+ });
3591
+ }
3592
+ if (!acc) return null;
3593
+ return {
3594
+ inputTokens: acc.inputTokens,
3595
+ outputTokens: acc.outputTokens,
3596
+ ...acc.cacheReadTokens != null ? { cacheReadTokens: acc.cacheReadTokens } : {},
3597
+ ...acc.cacheWriteTokens != null ? { cacheWriteTokens: acc.cacheWriteTokens } : {},
3598
+ ...acc.costUsd != null ? { costUsd: acc.costUsd } : {}
3599
+ };
3600
+ }
3601
+ function hasBilledTokens(u) {
3602
+ return Boolean(
3603
+ u.inputTokens || u.outputTokens || u.cacheReadTokens || u.cacheWriteTokens
3604
+ );
3605
+ }
3606
+ function applyTurnUsage(current, incoming, scope = "request") {
3607
+ if (scope === "turn") {
3608
+ if (!hasBilledTokens(incoming) && current && incoming.costUsd != null) {
3609
+ return { ...current, costUsd: incoming.costUsd };
3610
+ }
3611
+ return {
3612
+ ...incoming,
3613
+ costUsd: incoming.costUsd ?? current?.costUsd,
3614
+ lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
3615
+ };
3616
+ }
3617
+ const merged = mergeUsage(current, incoming);
3618
+ const occ = incoming.lastRequestTokens != null && incoming.lastRequestTokens > 0 ? incoming.lastRequestTokens : requestOccupancy(incoming);
3619
+ return {
3620
+ ...merged,
3621
+ lastRequestTokens: occ > 0 ? occ : current?.lastRequestTokens ?? occ
3622
+ };
3623
+ }
3624
+ function contextTokens(u) {
3625
+ if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
3626
+ return requestOccupancy(u);
3627
+ }
3628
+ var init_usage = __esm({
3629
+ "src/agents/usage.ts"() {
3630
+ "use strict";
3631
+ }
3632
+ });
3633
+
3634
+ // src/store/history-retention.ts
3635
+ function clampHistoryMaxCount(value) {
3636
+ return Math.max(HISTORY_MAX_COUNT_MIN, Math.min(HISTORY_MAX_COUNT_MAX, Math.floor(value)));
3637
+ }
3638
+ function clampHistoryMaxDays(value) {
3639
+ if (!Number.isFinite(value) || value <= 0) return 0;
3640
+ return Math.min(HISTORY_MAX_DAYS_MAX, Math.floor(value));
3641
+ }
3642
+ function archivedUpdatedMs(thread) {
3643
+ const updated = Date.parse(thread.updatedAt);
3644
+ if (Number.isFinite(updated)) return updated;
3645
+ const created = Date.parse(thread.createdAt);
3646
+ return Number.isFinite(created) ? created : 0;
3647
+ }
3648
+ function isHistoryRetentionStub(thread) {
3649
+ if ((thread.attachments?.length ?? 0) > 0) return false;
3650
+ const messages = thread.messages ?? [];
3651
+ if (messages.length === 0) return true;
3652
+ if (messages.length > 1) return false;
3653
+ const only = messages[0];
3654
+ if (only.parts?.length) return false;
3655
+ if ((only.attachments?.length ?? 0) > 0) return false;
3656
+ const text7 = (only.text ?? "").trim();
3657
+ return text7 === "" || text7 === HISTORY_DISCARDED_TEXT;
3658
+ }
3659
+ function historyRetentionStubMessage(thread) {
3660
+ const usage = sumUsageList((thread.messages ?? []).map((m) => m.usage));
3661
+ return {
3662
+ role: "summary",
3663
+ text: HISTORY_DISCARDED_TEXT,
3664
+ ts: thread.updatedAt,
3665
+ ...usage ? { usage } : {}
3666
+ };
3667
+ }
3668
+ function sortArchivedOldestFirst(threads) {
3669
+ return [...threads].sort((a, b) => archivedUpdatedMs(a) - archivedUpdatedMs(b));
3670
+ }
3671
+ function planHistoryRetention(archived, thresholds = {}) {
3672
+ const maxCount = clampHistoryMaxCount(thresholds.maxCount ?? HISTORY_MAX_COUNT_DEFAULT);
3673
+ const maxDays = clampHistoryMaxDays(thresholds.maxDays ?? HISTORY_MAX_DAYS_DEFAULT);
3674
+ const nowMs = thresholds.nowMs ?? Date.now();
3675
+ const oldestFirst = sortArchivedOldestFirst(archived);
3676
+ const expiredIds = /* @__PURE__ */ new Set();
3677
+ if (maxDays > 0) {
3678
+ const cutoff = nowMs - maxDays * 864e5;
3679
+ for (const thread of oldestFirst) {
3680
+ if (archivedUpdatedMs(thread) < cutoff) expiredIds.add(thread.id);
3681
+ }
3682
+ }
3683
+ const remaining = oldestFirst.filter((t) => !expiredIds.has(t.id));
3684
+ const overflow = remaining.length > maxCount ? remaining.slice(0, remaining.length - maxCount) : [];
3685
+ const stripIds = [];
3686
+ const purgeIds = [...expiredIds];
3687
+ const seenPurge = new Set(purgeIds);
3688
+ for (const thread of overflow) {
3689
+ if (isHistoryRetentionStub(thread)) {
3690
+ if (!seenPurge.has(thread.id)) {
3691
+ seenPurge.add(thread.id);
3692
+ purgeIds.push(thread.id);
3693
+ }
3694
+ } else {
3695
+ stripIds.push(thread.id);
3696
+ }
3697
+ }
3698
+ return { stripIds, purgeIds };
3699
+ }
3700
+ function planHistoryAgePurge(archived, olderThanDays, nowMs = Date.now()) {
3701
+ const days = clampHistoryMaxDays(olderThanDays);
3702
+ if (days <= 0) return [];
3703
+ const cutoff = nowMs - days * 864e5;
3704
+ return sortArchivedOldestFirst(archived).filter((t) => archivedUpdatedMs(t) < cutoff).map((t) => t.id);
3705
+ }
3706
+ var HISTORY_MAX_COUNT_DEFAULT, HISTORY_MAX_COUNT_MIN, HISTORY_MAX_COUNT_MAX, HISTORY_MAX_DAYS_DEFAULT, HISTORY_MAX_DAYS_MAX, HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT, HISTORY_DISCARDED_TEXT;
3707
+ var init_history_retention = __esm({
3708
+ "src/store/history-retention.ts"() {
3709
+ "use strict";
3710
+ init_usage();
3711
+ HISTORY_MAX_COUNT_DEFAULT = 200;
3712
+ HISTORY_MAX_COUNT_MIN = 1;
3713
+ HISTORY_MAX_COUNT_MAX = 2e3;
3714
+ HISTORY_MAX_DAYS_DEFAULT = 0;
3715
+ HISTORY_MAX_DAYS_MAX = 3650;
3716
+ HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT = 6;
3717
+ HISTORY_DISCARDED_TEXT = "Transcript discarded by History retention.";
3718
+ }
3719
+ });
3720
+
3512
3721
  // src/store/usage-on-limit.ts
3513
3722
  function isUsageOnLimit(value) {
3514
3723
  return value === "keep_going" || value === "confirm" || value === "switch_agent" || value === "wait_reset";
@@ -3565,6 +3774,7 @@ __export(app_settings_exports, {
3565
3774
  appSettingsPath: () => appSettingsPath,
3566
3775
  applyAppEnvironment: () => applyAppEnvironment,
3567
3776
  autoArchiveOnMergeEnabled: () => autoArchiveOnMergeEnabled,
3777
+ autoCleanupHistoryEnabled: () => autoCleanupHistoryEnabled,
3568
3778
  autoCleanupOrphansEnabled: () => autoCleanupOrphansEnabled,
3569
3779
  autoRenameBranchEnabled: () => autoRenameBranchEnabled,
3570
3780
  autoRunAfterSetupEnabled: () => autoRunAfterSetupEnabled,
@@ -3605,6 +3815,8 @@ __export(app_settings_exports, {
3605
3815
  getLinearApiKey: () => getLinearApiKey,
3606
3816
  gitBranchPrefixSetting: () => gitBranchPrefixSetting,
3607
3817
  harnessEnvKey: () => harnessEnvKey,
3818
+ historyMaxCount: () => historyMaxCount,
3819
+ historyMaxDays: () => historyMaxDays,
3608
3820
  isAbleTimeConnected: () => isAbleTimeConnected,
3609
3821
  isIssueSourceConnected: () => isIssueSourceConnected,
3610
3822
  isLinearConnected: () => isLinearConnected,
@@ -3718,10 +3930,10 @@ function toPublicAppSettings(settings) {
3718
3930
  };
3719
3931
  }
3720
3932
  function appSettingsPath() {
3721
- return (0, import_node_path17.join)(appDataDir(), "settings.json");
3933
+ return (0, import_node_path18.join)(appDataDir(), "settings.json");
3722
3934
  }
3723
3935
  function claudeUserSettingsPath() {
3724
- return (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".claude", "settings.json");
3936
+ return (0, import_node_path18.join)((0, import_node_os5.homedir)(), ".claude", "settings.json");
3725
3937
  }
3726
3938
  function normalizeClaude(raw) {
3727
3939
  if (!raw || typeof raw !== "object") return {};
@@ -3729,7 +3941,7 @@ function normalizeClaude(raw) {
3729
3941
  const out = {};
3730
3942
  if (typeof source.executablePath === "string") {
3731
3943
  const path = source.executablePath.trim();
3732
- if (path && (0, import_node_path17.isAbsolute)(path)) out.executablePath = path;
3944
+ if (path && (0, import_node_path18.isAbsolute)(path)) out.executablePath = path;
3733
3945
  }
3734
3946
  if (typeof source.chromeEnabled === "boolean") {
3735
3947
  out.chromeEnabled = source.chromeEnabled;
@@ -3742,13 +3954,13 @@ function normalizeCliExecutable(raw) {
3742
3954
  const out = {};
3743
3955
  if (typeof source.executablePath === "string") {
3744
3956
  const path = source.executablePath.trim();
3745
- if (path && (0, import_node_path17.isAbsolute)(path)) out.executablePath = path;
3957
+ if (path && (0, import_node_path18.isAbsolute)(path)) out.executablePath = path;
3746
3958
  }
3747
3959
  return out;
3748
3960
  }
3749
3961
  function absoluteExecutablePath(value) {
3750
3962
  const path = value.trim();
3751
- if (!(0, import_node_path17.isAbsolute)(path)) {
3963
+ if (!(0, import_node_path18.isAbsolute)(path)) {
3752
3964
  throw new Error("Executable path must be absolute. Leave it empty to use the system CLI.");
3753
3965
  }
3754
3966
  return path;
@@ -3759,7 +3971,7 @@ function normalizeBrightsy(raw) {
3759
3971
  const out = {};
3760
3972
  if (typeof source.executablePath === "string") {
3761
3973
  const path = source.executablePath.trim();
3762
- if (path && (0, import_node_path17.isAbsolute)(path)) out.executablePath = path;
3974
+ if (path && (0, import_node_path18.isAbsolute)(path)) out.executablePath = path;
3763
3975
  }
3764
3976
  if (typeof source.cloudConnectEnabled === "boolean") {
3765
3977
  out.cloudConnectEnabled = source.cloudConnectEnabled;
@@ -4050,6 +4262,24 @@ function normalizeAdvanced(raw) {
4050
4262
  if (typeof source.autoCleanupOrphans === "boolean") {
4051
4263
  out.autoCleanupOrphans = source.autoCleanupOrphans;
4052
4264
  }
4265
+ if (typeof source.autoCleanupHistory === "boolean") {
4266
+ out.autoCleanupHistory = source.autoCleanupHistory;
4267
+ }
4268
+ if (typeof source.historyMaxCount === "number" && Number.isFinite(source.historyMaxCount)) {
4269
+ out.historyMaxCount = clampHistoryMaxCount(source.historyMaxCount);
4270
+ }
4271
+ if (typeof source.historyMaxDays === "number" && Number.isFinite(source.historyMaxDays)) {
4272
+ out.historyMaxDays = clampHistoryMaxDays(source.historyMaxDays);
4273
+ }
4274
+ if (typeof source.historyCleanupIntervalHours === "number" && Number.isFinite(source.historyCleanupIntervalHours)) {
4275
+ out.historyCleanupIntervalHours = Math.max(
4276
+ 1,
4277
+ Math.min(168, Math.floor(source.historyCleanupIntervalHours))
4278
+ );
4279
+ }
4280
+ if (typeof source.historyLastCleanupAt === "string" && source.historyLastCleanupAt.trim()) {
4281
+ out.historyLastCleanupAt = source.historyLastCleanupAt.trim();
4282
+ }
4053
4283
  if (source.orchestrationQuotaOnLimit === "switch_agent" || source.orchestrationQuotaOnLimit === "wait_reset") {
4054
4284
  out.orchestrationQuotaOnLimit = source.orchestrationQuotaOnLimit;
4055
4285
  }
@@ -4942,6 +5172,24 @@ function updateAdvancedSettings(patch) {
4942
5172
  if (typeof patch.autoCleanupOrphans === "boolean") {
4943
5173
  advanced.autoCleanupOrphans = patch.autoCleanupOrphans;
4944
5174
  }
5175
+ if (typeof patch.autoCleanupHistory === "boolean") {
5176
+ advanced.autoCleanupHistory = patch.autoCleanupHistory;
5177
+ }
5178
+ if (typeof patch.historyMaxCount === "number" && Number.isFinite(patch.historyMaxCount)) {
5179
+ advanced.historyMaxCount = clampHistoryMaxCount(patch.historyMaxCount);
5180
+ }
5181
+ if (typeof patch.historyMaxDays === "number" && Number.isFinite(patch.historyMaxDays)) {
5182
+ advanced.historyMaxDays = clampHistoryMaxDays(patch.historyMaxDays);
5183
+ }
5184
+ if (typeof patch.historyCleanupIntervalHours === "number" && Number.isFinite(patch.historyCleanupIntervalHours)) {
5185
+ advanced.historyCleanupIntervalHours = Math.max(
5186
+ 1,
5187
+ Math.min(168, Math.floor(patch.historyCleanupIntervalHours))
5188
+ );
5189
+ }
5190
+ if (typeof patch.historyLastCleanupAt === "string") {
5191
+ advanced.historyLastCleanupAt = patch.historyLastCleanupAt;
5192
+ }
4945
5193
  if (patch.orchestrationQuotaOnLimit === "switch_agent" || patch.orchestrationQuotaOnLimit === "wait_reset") {
4946
5194
  advanced.orchestrationQuotaOnLimit = patch.orchestrationQuotaOnLimit;
4947
5195
  }
@@ -4992,6 +5240,15 @@ function autoArchiveOnMergeEnabled(settings = loadAppSettings()) {
4992
5240
  function autoCleanupOrphansEnabled(settings = loadAppSettings()) {
4993
5241
  return Boolean(settings.advanced.autoCleanupOrphans);
4994
5242
  }
5243
+ function autoCleanupHistoryEnabled(settings = loadAppSettings()) {
5244
+ return settings.advanced.autoCleanupHistory !== false;
5245
+ }
5246
+ function historyMaxCount(settings = loadAppSettings()) {
5247
+ return clampHistoryMaxCount(settings.advanced.historyMaxCount ?? HISTORY_MAX_COUNT_DEFAULT);
5248
+ }
5249
+ function historyMaxDays(settings = loadAppSettings()) {
5250
+ return clampHistoryMaxDays(settings.advanced.historyMaxDays ?? HISTORY_MAX_DAYS_DEFAULT);
5251
+ }
4995
5252
  function usageOnLimit(settings = loadAppSettings()) {
4996
5253
  return resolveUsageOnLimit(settings.advanced);
4997
5254
  }
@@ -5096,14 +5353,14 @@ function childEnvWithAppSettings(extra) {
5096
5353
  function harnessEnvKey(harness) {
5097
5354
  return HARNESS_ENV_KEYS[harness];
5098
5355
  }
5099
- var import_node_crypto3, import_node_fs15, import_node_os5, import_node_path17, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
5356
+ var import_node_crypto3, import_node_fs15, import_node_os5, import_node_path18, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
5100
5357
  var init_app_settings = __esm({
5101
5358
  "src/store/app-settings.ts"() {
5102
5359
  "use strict";
5103
5360
  import_node_crypto3 = require("crypto");
5104
5361
  import_node_fs15 = require("fs");
5105
5362
  import_node_os5 = require("os");
5106
- import_node_path17 = require("path");
5363
+ import_node_path18 = require("path");
5107
5364
  init_orchestrator_capable();
5108
5365
  init_thinking_effort();
5109
5366
  init_nested_electron_env();
@@ -5112,6 +5369,7 @@ var init_app_settings = __esm({
5112
5369
  init_private_file();
5113
5370
  init_secret_vault();
5114
5371
  init_branch_prefix();
5372
+ init_history_retention();
5115
5373
  init_usage_on_limit();
5116
5374
  init_usage_on_limit();
5117
5375
  init_issue_source_labels();
@@ -5272,7 +5530,7 @@ async function warmGithubAgentAuth(opts) {
5272
5530
  }
5273
5531
  function normalizeWritableRoot(raw) {
5274
5532
  const trimmed = raw.trim().replace(/\/+$/, "");
5275
- return trimmed && (0, import_node_path18.isAbsolute)(trimmed) ? trimmed : null;
5533
+ return trimmed && (0, import_node_path19.isAbsolute)(trimmed) ? trimmed : null;
5276
5534
  }
5277
5535
  async function resolveCodexGitWritableRoots(cwd) {
5278
5536
  const roots = /* @__PURE__ */ new Set();
@@ -5350,11 +5608,11 @@ function formatGitAuthModeDirective(mode) {
5350
5608
  ].join("\n");
5351
5609
  }
5352
5610
  }
5353
- var import_node_path18, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
5611
+ var import_node_path19, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
5354
5612
  var init_git_auth_mode = __esm({
5355
5613
  "src/git/git-auth-mode.ts"() {
5356
5614
  "use strict";
5357
- import_node_path18 = require("path");
5615
+ import_node_path19 = require("path");
5358
5616
  init_app_settings();
5359
5617
  init_github_agent_auth();
5360
5618
  init_run();
@@ -7039,7 +7297,7 @@ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
7039
7297
  }
7040
7298
  async function createThreadWorktree(opts) {
7041
7299
  let branchName = `thread/${opts.slug}`;
7042
- const worktreePath = (0, import_node_path19.join)(worktreesRoot(opts.repoPath), opts.slug);
7300
+ const worktreePath = (0, import_node_path20.join)(worktreesRoot(opts.repoPath), opts.slug);
7043
7301
  if ((0, import_node_fs16.existsSync)(worktreePath)) {
7044
7302
  throw new Error(`Worktree already exists at ${worktreePath}`);
7045
7303
  }
@@ -7081,7 +7339,7 @@ ${add.stdout}`;
7081
7339
  async function createExistingBranchWorktree(opts) {
7082
7340
  const branchName = opts.branchName.trim();
7083
7341
  if (!branchName) throw new Error("branch name required");
7084
- const worktreePath = (0, import_node_path19.join)(worktreesRoot(opts.repoPath), opts.slug);
7342
+ const worktreePath = (0, import_node_path20.join)(worktreesRoot(opts.repoPath), opts.slug);
7085
7343
  if ((0, import_node_fs16.existsSync)(worktreePath)) {
7086
7344
  throw new Error(`Worktree already exists at ${worktreePath}`);
7087
7345
  }
@@ -7363,7 +7621,7 @@ async function createOrUpdatePr(worktreePath, opts) {
7363
7621
  const headRef = ghHeadRef(slug, opts.head);
7364
7622
  const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
7365
7623
  const bodyText = clampGithubPrBody(opts.body ?? opts.title);
7366
- const bodyFile = (0, import_node_path19.join)(
7624
+ const bodyFile = (0, import_node_path20.join)(
7367
7625
  (0, import_node_os6.tmpdir)(),
7368
7626
  `sideboard-pr-body-${process.pid}-${(0, import_node_crypto4.randomBytes)(6).toString("hex")}.md`
7369
7627
  );
@@ -7463,7 +7721,7 @@ function sameRepoPath(a, b) {
7463
7721
  return normalizeWorktreePath(a) === normalizeWorktreePath(b);
7464
7722
  }
7465
7723
  function listLocalThreadBranchSlugs(repoPath) {
7466
- const refsDir = (0, import_node_path19.join)(repoPath, ".git", "refs", "heads", "thread");
7724
+ const refsDir = (0, import_node_path20.join)(repoPath, ".git", "refs", "heads", "thread");
7467
7725
  if (!(0, import_node_fs16.existsSync)(refsDir)) return [];
7468
7726
  try {
7469
7727
  return (0, import_node_fs16.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
@@ -7500,20 +7758,20 @@ function allocateTeamSlug(repoPath) {
7500
7758
  const taken = collectTakenTeamSlugs(repoPath);
7501
7759
  for (let attempt = 0; attempt < 32; attempt++) {
7502
7760
  const team = allocateTeamName(taken);
7503
- const path = (0, import_node_path19.join)(worktreesRoot(repoPath), team.slug);
7761
+ const path = (0, import_node_path20.join)(worktreesRoot(repoPath), team.slug);
7504
7762
  if (!(0, import_node_fs16.existsSync)(path)) return team;
7505
7763
  taken.add(team.slug);
7506
7764
  }
7507
7765
  throw new Error("No available soccer team worktree directories left");
7508
7766
  }
7509
- var import_node_crypto4, import_node_fs16, import_node_os6, import_node_path19, PR_DETAILS_JSON_FIELDS;
7767
+ var import_node_crypto4, import_node_fs16, import_node_os6, import_node_path20, PR_DETAILS_JSON_FIELDS;
7510
7768
  var init_worktree = __esm({
7511
7769
  "src/git/worktree.ts"() {
7512
7770
  "use strict";
7513
7771
  import_node_crypto4 = require("crypto");
7514
7772
  import_node_fs16 = require("fs");
7515
7773
  import_node_os6 = require("os");
7516
- import_node_path19 = require("path");
7774
+ import_node_path20 = require("path");
7517
7775
  init_paths();
7518
7776
  init_thread_store();
7519
7777
  init_teams();
@@ -7585,7 +7843,7 @@ var init_cloud_connect_constants = __esm({
7585
7843
 
7586
7844
  // src/composer/stage-files.ts
7587
7845
  function fileExtension(filePath) {
7588
- const base = (0, import_node_path20.basename)(filePath).toLowerCase();
7846
+ const base = (0, import_node_path21.basename)(filePath).toLowerCase();
7589
7847
  return base.includes(".") ? base.split(".").pop() || "" : "";
7590
7848
  }
7591
7849
  function isImageFilePath(filePath) {
@@ -7595,9 +7853,9 @@ function imageMimeType(filePath) {
7595
7853
  return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
7596
7854
  }
7597
7855
  function ensureAttachmentsDir(worktreePath) {
7598
- const dir = (0, import_node_path20.join)(worktreePath, ATTACHMENTS_DIR);
7856
+ const dir = (0, import_node_path21.join)(worktreePath, ATTACHMENTS_DIR);
7599
7857
  (0, import_node_fs17.mkdirSync)(dir, { recursive: true });
7600
- const gi = (0, import_node_path20.join)(dir, ".gitignore");
7858
+ const gi = (0, import_node_path21.join)(dir, ".gitignore");
7601
7859
  if (!(0, import_node_fs17.existsSync)(gi)) {
7602
7860
  (0, import_node_fs17.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
7603
7861
  }
@@ -7605,12 +7863,12 @@ function ensureAttachmentsDir(worktreePath) {
7605
7863
  }
7606
7864
  function uniqueAttachmentName(dir, originalName) {
7607
7865
  const safe = originalName.replace(/[/\\]/g, "_") || "file";
7608
- if (!(0, import_node_fs17.existsSync)((0, import_node_path20.join)(dir, safe))) return safe;
7609
- const ext = (0, import_node_path20.extname)(safe);
7866
+ if (!(0, import_node_fs17.existsSync)((0, import_node_path21.join)(dir, safe))) return safe;
7867
+ const ext = (0, import_node_path21.extname)(safe);
7610
7868
  const stem = ext ? safe.slice(0, -ext.length) : safe;
7611
7869
  for (let i = 1; i < 1e4; i++) {
7612
7870
  const candidate = `${stem}-${i}${ext}`;
7613
- if (!(0, import_node_fs17.existsSync)((0, import_node_path20.join)(dir, candidate))) return candidate;
7871
+ if (!(0, import_node_fs17.existsSync)((0, import_node_path21.join)(dir, candidate))) return candidate;
7614
7872
  }
7615
7873
  return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
7616
7874
  }
@@ -7666,12 +7924,12 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
7666
7924
  const dir = ensureAttachmentsDir(worktreePath);
7667
7925
  const out = [];
7668
7926
  for (const abs of absolutePaths) {
7669
- const originalName = (0, import_node_path20.basename)(abs);
7927
+ const originalName = (0, import_node_path21.basename)(abs);
7670
7928
  try {
7671
7929
  const st = (0, import_node_fs17.statSync)(abs);
7672
7930
  if (!st.isFile()) continue;
7673
7931
  const name = uniqueAttachmentName(dir, originalName);
7674
- const destAbs = (0, import_node_path20.join)(dir, name);
7932
+ const destAbs = (0, import_node_path21.join)(dir, name);
7675
7933
  (0, import_node_fs17.copyFileSync)(abs, destAbs);
7676
7934
  const rel = `${ATTACHMENTS_DIR}/${name}`;
7677
7935
  const buf = (0, import_node_fs17.readFileSync)(destAbs);
@@ -7696,7 +7954,7 @@ function stageBuffersAsAttachments(worktreePath, buffers2) {
7696
7954
  try {
7697
7955
  const buf = Buffer.from(item.dataBase64, "base64");
7698
7956
  const name = uniqueAttachmentName(dir, originalName);
7699
- const destAbs = (0, import_node_path20.join)(dir, name);
7957
+ const destAbs = (0, import_node_path21.join)(dir, name);
7700
7958
  (0, import_node_fs17.writeFileSync)(destAbs, buf);
7701
7959
  const rel = `${ATTACHMENTS_DIR}/${name}`;
7702
7960
  out.push(attachmentFromBuffer(name, buf, { path: rel }));
@@ -7758,15 +8016,15 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
7758
8016
  if (!rel || rel.includes("..") || rel.startsWith("/")) {
7759
8017
  out.push({
7760
8018
  id: (0, import_node_crypto5.randomUUID)(),
7761
- name: (0, import_node_path20.basename)(rel) || "file",
8019
+ name: (0, import_node_path21.basename)(rel) || "file",
7762
8020
  kind: "file",
7763
8021
  content: `(invalid path: ${rel})`
7764
8022
  });
7765
8023
  continue;
7766
8024
  }
7767
- const name = (0, import_node_path20.basename)(rel);
8025
+ const name = (0, import_node_path21.basename)(rel);
7768
8026
  try {
7769
- const abs = (0, import_node_path20.join)(worktreePath, rel);
8027
+ const abs = (0, import_node_path21.join)(worktreePath, rel);
7770
8028
  const st = (0, import_node_fs17.statSync)(abs);
7771
8029
  if (!st.isFile()) continue;
7772
8030
  const buf = (0, import_node_fs17.readFileSync)(abs);
@@ -7782,12 +8040,12 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
7782
8040
  }
7783
8041
  return out;
7784
8042
  }
7785
- var import_node_fs17, import_node_path20, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
8043
+ var import_node_fs17, import_node_path21, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
7786
8044
  var init_stage_files = __esm({
7787
8045
  "src/composer/stage-files.ts"() {
7788
8046
  "use strict";
7789
8047
  import_node_fs17 = require("fs");
7790
- import_node_path20 = require("path");
8048
+ import_node_path21 = require("path");
7791
8049
  import_node_crypto5 = require("crypto");
7792
8050
  init_workspace_scratch();
7793
8051
  IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -7827,10 +8085,10 @@ __export(workspaces_exports, {
7827
8085
  syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
7828
8086
  });
7829
8087
  function workspacesFile() {
7830
- return (0, import_node_path21.join)(appDataDir(), "workspaces.json");
8088
+ return (0, import_node_path22.join)(appDataDir(), "workspaces.json");
7831
8089
  }
7832
8090
  function removedWorkspacesFile() {
7833
- return (0, import_node_path21.join)(appDataDir(), "removed-workspaces.json");
8091
+ return (0, import_node_path22.join)(appDataDir(), "removed-workspaces.json");
7834
8092
  }
7835
8093
  function readAll() {
7836
8094
  const path = workspacesFile();
@@ -7889,7 +8147,7 @@ async function addWorkspace(repoPath) {
7889
8147
  if (existing) return existing;
7890
8148
  const next = {
7891
8149
  path: root,
7892
- name: (0, import_node_path21.basename)(root),
8150
+ name: (0, import_node_path22.basename)(root),
7893
8151
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
7894
8152
  };
7895
8153
  writeAll([...current, next]);
@@ -7914,7 +8172,7 @@ function syncWorkspacesFromThreads(repoPaths) {
7914
8172
  if (!(0, import_node_fs18.existsSync)(path)) continue;
7915
8173
  const ws = {
7916
8174
  path,
7917
- name: (0, import_node_path21.basename)(path),
8175
+ name: (0, import_node_path22.basename)(path),
7918
8176
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
7919
8177
  };
7920
8178
  byPath.set(path, ws);
@@ -7924,12 +8182,12 @@ function syncWorkspacesFromThreads(repoPaths) {
7924
8182
  if (dirty) writeAll(next);
7925
8183
  return next.sort((a, b) => a.name.localeCompare(b.name));
7926
8184
  }
7927
- var import_node_fs18, import_node_path21;
8185
+ var import_node_fs18, import_node_path22;
7928
8186
  var init_workspaces2 = __esm({
7929
8187
  "src/store/workspaces.ts"() {
7930
8188
  "use strict";
7931
8189
  import_node_fs18 = require("fs");
7932
- import_node_path21 = require("path");
8190
+ import_node_path22 = require("path");
7933
8191
  init_paths();
7934
8192
  init_global_workspace();
7935
8193
  init_worktree();
@@ -8048,7 +8306,7 @@ function ensureGlobalCoordinatorCwd(opts) {
8048
8306
  let orchId = opts?.orchestratorThreadId?.trim() || "";
8049
8307
  if (!orchId) {
8050
8308
  try {
8051
- const existing = (0, import_node_fs19.readFileSync)((0, import_node_path22.join)(dir, "AGENTS.md"), "utf8");
8309
+ const existing = (0, import_node_fs19.readFileSync)((0, import_node_path23.join)(dir, "AGENTS.md"), "utf8");
8052
8310
  const m = existing.match(
8053
8311
  /YOUR orchestration thread id is `([0-9a-f-]{36})`/i
8054
8312
  );
@@ -8093,9 +8351,9 @@ function ensureGlobalCoordinatorCwd(opts) {
8093
8351
  "Always ask worktree agents to commit, push, and open draft PRs (`ask_git` / `send_to_thread`). If the user gave a goal (Greptile 5/5, CI green), pass that goal through so they watch-fix-push until it lands \u2014 do not start that loop on a plain push, and do not tell the human to poll. Tell them to merge only when the user explicitly asked. The worktree agent runs git/gh; never merge from this orchestration cwd."
8094
8352
  ].join("\n");
8095
8353
  try {
8096
- (0, import_node_fs19.writeFileSync)((0, import_node_path22.join)(dir, "CLAUDE.md"), `${body}
8354
+ (0, import_node_fs19.writeFileSync)((0, import_node_path23.join)(dir, "CLAUDE.md"), `${body}
8097
8355
  `, "utf8");
8098
- (0, import_node_fs19.writeFileSync)((0, import_node_path22.join)(dir, "AGENTS.md"), `${body}
8356
+ (0, import_node_fs19.writeFileSync)((0, import_node_path23.join)(dir, "AGENTS.md"), `${body}
8099
8357
  `, "utf8");
8100
8358
  } catch {
8101
8359
  }
@@ -8127,12 +8385,12 @@ function coordinatorSystemPrompt(opts) {
8127
8385
  formatWorkspaceInventory(opts.workspaces)
8128
8386
  ].join("\n");
8129
8387
  }
8130
- var import_node_fs19, import_node_path22, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
8388
+ var import_node_fs19, import_node_path23, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
8131
8389
  var init_coordinator_prompt = __esm({
8132
8390
  "src/orchestrator/coordinator-prompt.ts"() {
8133
8391
  "use strict";
8134
8392
  import_node_fs19 = require("fs");
8135
- import_node_path22 = require("path");
8393
+ import_node_path23 = require("path");
8136
8394
  init_worktree();
8137
8395
  init_app_settings();
8138
8396
  init_paths();
@@ -8448,7 +8706,7 @@ var init_global_workspace = __esm({
8448
8706
  function brightsyConfigPath() {
8449
8707
  const override = process.env.BRIGHTSY_CONFIG?.trim();
8450
8708
  if (override) return override;
8451
- return (0, import_node_path23.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
8709
+ return (0, import_node_path24.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
8452
8710
  }
8453
8711
  function loadBrightsyConfig() {
8454
8712
  const path = brightsyConfigPath();
@@ -8467,13 +8725,13 @@ function saveBrightsyConfig(cfg) {
8467
8725
  mode: 384
8468
8726
  });
8469
8727
  }
8470
- var import_node_fs20, import_node_os7, import_node_path23;
8728
+ var import_node_fs20, import_node_os7, import_node_path24;
8471
8729
  var init_config = __esm({
8472
8730
  "src/brightsy/config.ts"() {
8473
8731
  "use strict";
8474
8732
  import_node_fs20 = require("fs");
8475
8733
  import_node_os7 = require("os");
8476
- import_node_path23 = require("path");
8734
+ import_node_path24 = require("path");
8477
8735
  }
8478
8736
  });
8479
8737
 
@@ -8599,7 +8857,7 @@ var init_oauth = __esm({
8599
8857
 
8600
8858
  // src/brightsy/connected-teams.ts
8601
8859
  function storePath4() {
8602
- return (0, import_node_path24.join)(appDataDir(), "brightsy-teams.json");
8860
+ return (0, import_node_path25.join)(appDataDir(), "brightsy-teams.json");
8603
8861
  }
8604
8862
  function readStore4() {
8605
8863
  const path = storePath4();
@@ -8720,12 +8978,12 @@ function brightsyMcpServerName(slug) {
8720
8978
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
8721
8979
  return `brightsy_${cleaned || "team"}`;
8722
8980
  }
8723
- var import_node_fs21, import_node_path24;
8981
+ var import_node_fs21, import_node_path25;
8724
8982
  var init_connected_teams = __esm({
8725
8983
  "src/brightsy/connected-teams.ts"() {
8726
8984
  "use strict";
8727
8985
  import_node_fs21 = require("fs");
8728
- import_node_path24 = require("path");
8986
+ import_node_path25 = require("path");
8729
8987
  init_paths();
8730
8988
  init_accounts();
8731
8989
  init_config();
@@ -8733,90 +8991,6 @@ var init_connected_teams = __esm({
8733
8991
  }
8734
8992
  });
8735
8993
 
8736
- // src/agents/usage.ts
8737
- function sumOptional(a, b) {
8738
- if (a == null && b == null) return void 0;
8739
- return (a ?? 0) + (b ?? 0);
8740
- }
8741
- function fromInclusiveInputUsage(opts) {
8742
- const totalInput = Number(opts.inputTokens) || 0;
8743
- const outputTokens = Number(opts.outputTokens) || 0;
8744
- const cached = Number(opts.cachedInputTokens) || 0;
8745
- if (!totalInput && !outputTokens) return null;
8746
- const cacheReadTokens = cached > 0 ? Math.min(cached, totalInput) : 0;
8747
- return {
8748
- inputTokens: Math.max(0, totalInput - cacheReadTokens),
8749
- outputTokens,
8750
- cacheReadTokens: cacheReadTokens || void 0
8751
- };
8752
- }
8753
- function requestOccupancy(u) {
8754
- return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
8755
- }
8756
- function mergeUsage(a, b) {
8757
- return {
8758
- inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
8759
- outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
8760
- cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
8761
- cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
8762
- costUsd: sumOptional(a?.costUsd, b.costUsd),
8763
- lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
8764
- };
8765
- }
8766
- function sumUsageList(list) {
8767
- let acc = null;
8768
- for (const u of list) {
8769
- if (!u) continue;
8770
- acc = mergeUsage(acc, {
8771
- inputTokens: u.inputTokens,
8772
- outputTokens: u.outputTokens,
8773
- cacheReadTokens: u.cacheReadTokens,
8774
- cacheWriteTokens: u.cacheWriteTokens,
8775
- costUsd: u.costUsd
8776
- });
8777
- }
8778
- if (!acc) return null;
8779
- return {
8780
- inputTokens: acc.inputTokens,
8781
- outputTokens: acc.outputTokens,
8782
- ...acc.cacheReadTokens != null ? { cacheReadTokens: acc.cacheReadTokens } : {},
8783
- ...acc.cacheWriteTokens != null ? { cacheWriteTokens: acc.cacheWriteTokens } : {},
8784
- ...acc.costUsd != null ? { costUsd: acc.costUsd } : {}
8785
- };
8786
- }
8787
- function hasBilledTokens(u) {
8788
- return Boolean(
8789
- u.inputTokens || u.outputTokens || u.cacheReadTokens || u.cacheWriteTokens
8790
- );
8791
- }
8792
- function applyTurnUsage(current, incoming, scope = "request") {
8793
- if (scope === "turn") {
8794
- if (!hasBilledTokens(incoming) && current && incoming.costUsd != null) {
8795
- return { ...current, costUsd: incoming.costUsd };
8796
- }
8797
- return {
8798
- ...incoming,
8799
- costUsd: incoming.costUsd ?? current?.costUsd,
8800
- lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
8801
- };
8802
- }
8803
- const merged = mergeUsage(current, incoming);
8804
- const occ = incoming.lastRequestTokens != null && incoming.lastRequestTokens > 0 ? incoming.lastRequestTokens : requestOccupancy(incoming);
8805
- return {
8806
- ...merged,
8807
- lastRequestTokens: occ > 0 ? occ : current?.lastRequestTokens ?? occ
8808
- };
8809
- }
8810
- function contextTokens(u) {
8811
- if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
8812
- return requestOccupancy(u);
8813
- }
8814
- var init_usage = __esm({
8815
- "src/agents/usage.ts"() {
8816
- "use strict";
8817
- }
8818
- });
8819
-
8820
8994
  // src/agents/brightsy-targets.ts
8821
8995
  function encodeBrightsyTarget(type, id, accountId) {
8822
8996
  if (accountId) return `team:${accountId}:${type}:${id}`;
@@ -9508,6 +9682,28 @@ function clipThinkingForStore(text7, max = THINKING_PART_MAX_CHARS) {
9508
9682
  const marker = "\u2026(earlier thinking trimmed)\n";
9509
9683
  return marker + text7.slice(text7.length - Math.max(1, max - marker.length));
9510
9684
  }
9685
+ function clipEventTail(text7, max) {
9686
+ if (text7.length <= max) return text7;
9687
+ const marker = "\u2026(truncated)\n";
9688
+ return marker + text7.slice(text7.length - Math.max(1, max - marker.length));
9689
+ }
9690
+ function clipAgentEventForPaint(event) {
9691
+ if (event.type === "tool_result" && event.content) {
9692
+ const content = clipToolResultForStore(event.content);
9693
+ if (content === event.content) return event;
9694
+ return { ...event, content };
9695
+ }
9696
+ if (event.type === "thinking" && event.data.length > THINKING_PART_MAX_CHARS) {
9697
+ return { ...event, data: clipThinkingForStore(event.data) };
9698
+ }
9699
+ if (event.type === "stdout" && event.data.length > STDOUT_EVENT_MAX_CHARS) {
9700
+ return { ...event, data: clipEventTail(event.data, STDOUT_EVENT_MAX_CHARS) };
9701
+ }
9702
+ if (event.type === "stderr" && event.data.length > STDERR_EVENT_MAX_CHARS) {
9703
+ return { ...event, data: clipEventTail(event.data, STDERR_EVENT_MAX_CHARS) };
9704
+ }
9705
+ return event;
9706
+ }
9511
9707
  function withPartTimes(next, prev) {
9512
9708
  const now = Date.now();
9513
9709
  const startedAt = prev && typeof prev.startedAt === "number" ? prev.startedAt : now;
@@ -9723,13 +9919,15 @@ function normalizeParseResult(parsed) {
9723
9919
  if (!parsed) return [];
9724
9920
  return Array.isArray(parsed) ? parsed : [parsed];
9725
9921
  }
9726
- var CHAT_DETAIL_MAX, THINKING_PART_MAX_CHARS;
9922
+ var CHAT_DETAIL_MAX, THINKING_PART_MAX_CHARS, STDOUT_EVENT_MAX_CHARS, STDERR_EVENT_MAX_CHARS;
9727
9923
  var init_message_parts = __esm({
9728
9924
  "src/agents/message-parts.ts"() {
9729
9925
  "use strict";
9730
9926
  init_error_detail();
9731
9927
  CHAT_DETAIL_MAX = 72;
9732
9928
  THINKING_PART_MAX_CHARS = 64e3;
9929
+ STDOUT_EVENT_MAX_CHARS = 16e3;
9930
+ STDERR_EVENT_MAX_CHARS = 4e3;
9733
9931
  }
9734
9932
  });
9735
9933
 
@@ -9754,43 +9952,43 @@ function electronResourcesPath() {
9754
9952
  function packagedCursorRuntimeDir() {
9755
9953
  const resources = electronResourcesPath();
9756
9954
  if (!resources) return null;
9757
- const dir = (0, import_node_path25.join)(resources, "cursor-runtime");
9758
- if (!(0, import_node_fs23.existsSync)((0, import_node_path25.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
9955
+ const dir = (0, import_node_path26.join)(resources, "cursor-runtime");
9956
+ if (!(0, import_node_fs23.existsSync)((0, import_node_path26.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
9759
9957
  return dir;
9760
9958
  }
9761
9959
  function packagedCursorRunnerPath() {
9762
9960
  const dir = packagedCursorRuntimeDir();
9763
- return dir ? (0, import_node_path25.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
9961
+ return dir ? (0, import_node_path26.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
9764
9962
  }
9765
9963
  function packagedMcpDir() {
9766
9964
  const resources = electronResourcesPath();
9767
9965
  if (!resources) return null;
9768
- const dir = (0, import_node_path25.join)(resources, "sideboard-mcp");
9769
- if (!(0, import_node_fs23.existsSync)((0, import_node_path25.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
9966
+ const dir = (0, import_node_path26.join)(resources, "sideboard-mcp");
9967
+ if (!(0, import_node_fs23.existsSync)((0, import_node_path26.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
9770
9968
  return dir;
9771
9969
  }
9772
9970
  function packagedMcpStdioPath() {
9773
9971
  const dir = packagedMcpDir();
9774
- return dir ? (0, import_node_path25.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
9972
+ return dir ? (0, import_node_path26.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
9775
9973
  }
9776
9974
  function packagedBundledNodePath() {
9777
9975
  const resources = electronResourcesPath();
9778
9976
  if (!resources) return null;
9779
- const bin = (0, import_node_path25.join)(resources, "node", "bin", "node");
9977
+ const bin = (0, import_node_path26.join)(resources, "node", "bin", "node");
9780
9978
  if (!(0, import_node_fs23.existsSync)(bin)) return null;
9781
9979
  return bin;
9782
9980
  }
9783
9981
  function packagedCursorRipgrepCandidate(platformPkg, binName) {
9784
9982
  const dir = packagedCursorRuntimeDir();
9785
9983
  if (!dir) return null;
9786
- return (0, import_node_path25.join)(dir, "node_modules", platformPkg, "bin", binName);
9984
+ return (0, import_node_path26.join)(dir, "node_modules", platformPkg, "bin", binName);
9787
9985
  }
9788
- var import_node_fs23, import_node_path25;
9986
+ var import_node_fs23, import_node_path26;
9789
9987
  var init_packaged_runtime = __esm({
9790
9988
  "src/agents/packaged-runtime.ts"() {
9791
9989
  "use strict";
9792
9990
  import_node_fs23 = require("fs");
9793
- import_node_path25 = require("path");
9991
+ import_node_path26 = require("path");
9794
9992
  }
9795
9993
  });
9796
9994
 
@@ -9874,28 +10072,28 @@ function versionDirNodeBins(root, toBin) {
9874
10072
  }
9875
10073
  function defaultNodeBinCandidates(home = (0, import_node_os8.homedir)()) {
9876
10074
  const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
9877
- (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path26.join)(prefix, "opt", `node@${major}`, "bin", "node"))
10075
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path27.join)(prefix, "opt", `node@${major}`, "bin", "node"))
9878
10076
  );
9879
10077
  return [
9880
10078
  ...kegs,
9881
10079
  "/opt/homebrew/bin/node",
9882
10080
  "/usr/local/bin/node",
9883
- (0, import_node_path26.join)(home, ".local/share/fnm/aliases/default/bin/node"),
9884
- (0, import_node_path26.join)(home, ".nvm/current/bin/node"),
9885
- (0, import_node_path26.join)(home, ".volta/bin/node"),
9886
- (0, import_node_path26.join)(home, ".asdf/shims/node"),
9887
- (0, import_node_path26.join)(home, ".local/share/mise/shims/node"),
10081
+ (0, import_node_path27.join)(home, ".local/share/fnm/aliases/default/bin/node"),
10082
+ (0, import_node_path27.join)(home, ".nvm/current/bin/node"),
10083
+ (0, import_node_path27.join)(home, ".volta/bin/node"),
10084
+ (0, import_node_path27.join)(home, ".asdf/shims/node"),
10085
+ (0, import_node_path27.join)(home, ".local/share/mise/shims/node"),
9888
10086
  ...versionDirNodeBins(
9889
- (0, import_node_path26.join)(home, ".nvm", "versions", "node"),
9890
- (name) => (0, import_node_path26.join)(home, ".nvm", "versions", "node", name, "bin", "node")
10087
+ (0, import_node_path27.join)(home, ".nvm", "versions", "node"),
10088
+ (name) => (0, import_node_path27.join)(home, ".nvm", "versions", "node", name, "bin", "node")
9891
10089
  ),
9892
10090
  ...versionDirNodeBins(
9893
- (0, import_node_path26.join)(home, ".local/share/fnm", "node-versions"),
9894
- (name) => (0, import_node_path26.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
10091
+ (0, import_node_path27.join)(home, ".local/share/fnm", "node-versions"),
10092
+ (name) => (0, import_node_path27.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
9895
10093
  ),
9896
10094
  ...versionDirNodeBins(
9897
- (0, import_node_path26.join)(home, ".volta", "tools", "image", "node"),
9898
- (name) => (0, import_node_path26.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
10095
+ (0, import_node_path27.join)(home, ".volta", "tools", "image", "node"),
10096
+ (name) => (0, import_node_path27.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
9899
10097
  )
9900
10098
  ];
9901
10099
  }
@@ -9987,13 +10185,13 @@ async function resolveNodeLaunch(scriptPath) {
9987
10185
  env: { ELECTRON_RUN_AS_NODE: "1" }
9988
10186
  };
9989
10187
  }
9990
- var import_node_fs24, import_node_os8, import_node_path26, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
10188
+ var import_node_fs24, import_node_os8, import_node_path27, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
9991
10189
  var init_node_launch = __esm({
9992
10190
  "src/agents/node-launch.ts"() {
9993
10191
  "use strict";
9994
10192
  import_node_fs24 = require("fs");
9995
10193
  import_node_os8 = require("os");
9996
- import_node_path26 = require("path");
10194
+ import_node_path27 = require("path");
9997
10195
  init_nested_electron_env();
9998
10196
  init_system_ca();
9999
10197
  init_run();
@@ -10095,13 +10293,13 @@ function corePackageDir() {
10095
10293
  try {
10096
10294
  const url = import_meta.url;
10097
10295
  if (typeof url === "string" && url.length > 0) {
10098
- return (0, import_node_path27.dirname)((0, import_node_url.fileURLToPath)(url));
10296
+ return (0, import_node_path28.dirname)((0, import_node_url.fileURLToPath)(url));
10099
10297
  }
10100
10298
  } catch {
10101
10299
  }
10102
10300
  try {
10103
- const req = (0, import_node_module.createRequire)((0, import_node_path27.join)(process.cwd(), "package.json"));
10104
- return (0, import_node_path27.dirname)(req.resolve("@sideboard-ai/core"));
10301
+ const req = (0, import_node_module.createRequire)((0, import_node_path28.join)(process.cwd(), "package.json"));
10302
+ return (0, import_node_path28.dirname)(req.resolve("@sideboard-ai/core"));
10105
10303
  } catch {
10106
10304
  return process.cwd();
10107
10305
  }
@@ -10114,18 +10312,18 @@ function findSideboardMcpJsEntry() {
10114
10312
  let dir = corePackageDir();
10115
10313
  for (let i = 0; i < 10; i++) {
10116
10314
  const candidates = [
10117
- (0, import_node_path27.join)(dir, "mcp/run-stdio.js"),
10118
- (0, import_node_path27.join)(dir, "mcp/run-stdio.cjs"),
10119
- (0, import_node_path27.join)(dir, "dist/mcp/run-stdio.js"),
10120
- (0, import_node_path27.join)(dir, "dist/mcp/run-stdio.cjs"),
10121
- (0, import_node_path27.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
10122
- (0, import_node_path27.join)(dir, "packages/cli/dist/index.js"),
10123
- (0, import_node_path27.join)(dir, "cli/dist/index.js")
10315
+ (0, import_node_path28.join)(dir, "mcp/run-stdio.js"),
10316
+ (0, import_node_path28.join)(dir, "mcp/run-stdio.cjs"),
10317
+ (0, import_node_path28.join)(dir, "dist/mcp/run-stdio.js"),
10318
+ (0, import_node_path28.join)(dir, "dist/mcp/run-stdio.cjs"),
10319
+ (0, import_node_path28.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
10320
+ (0, import_node_path28.join)(dir, "packages/cli/dist/index.js"),
10321
+ (0, import_node_path28.join)(dir, "cli/dist/index.js")
10124
10322
  ];
10125
10323
  for (const p of candidates) {
10126
10324
  if ((0, import_node_fs25.existsSync)(p) && !isAsarPath(p)) return p;
10127
10325
  }
10128
- const parent = (0, import_node_path27.dirname)(dir);
10326
+ const parent = (0, import_node_path28.dirname)(dir);
10129
10327
  if (parent === dir) break;
10130
10328
  dir = parent;
10131
10329
  }
@@ -10272,19 +10470,19 @@ function writeMcpServersConfig(servers) {
10272
10470
  ...env ? { env } : {}
10273
10471
  };
10274
10472
  }
10275
- const dir = (0, import_node_fs25.mkdtempSync)((0, import_node_path27.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
10276
- const cfgPath = (0, import_node_path27.join)(dir, "mcp.json");
10473
+ const dir = (0, import_node_fs25.mkdtempSync)((0, import_node_path28.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
10474
+ const cfgPath = (0, import_node_path28.join)(dir, "mcp.json");
10277
10475
  (0, import_node_fs25.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
10278
10476
  return cfgPath;
10279
10477
  }
10280
- var import_node_fs25, import_node_module, import_node_os9, import_node_path27, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS, SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS, SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
10478
+ var import_node_fs25, import_node_module, import_node_os9, import_node_path28, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS, SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS, SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
10281
10479
  var init_injected_mcp = __esm({
10282
10480
  "src/agents/injected-mcp.ts"() {
10283
10481
  "use strict";
10284
10482
  import_node_fs25 = require("fs");
10285
10483
  import_node_module = require("module");
10286
10484
  import_node_os9 = require("os");
10287
- import_node_path27 = require("path");
10485
+ import_node_path28 = require("path");
10288
10486
  import_node_url = require("url");
10289
10487
  init_run();
10290
10488
  init_config();
@@ -10521,13 +10719,31 @@ function mcpStatusThinkingFromClaudeInit(obj) {
10521
10719
  }
10522
10720
  }
10523
10721
  }
10524
- const notable = servers.filter((s) => !isCleanMcpConnect(s.status));
10722
+ const notable = servers.filter(isNotableMcpInitStatus);
10525
10723
  if (notable.length === 0) return null;
10526
10724
  return `MCP: ${notable.map((s) => `${s.name} ${s.status}`).join(", ")}`;
10527
10725
  }
10528
10726
  function isCleanMcpConnect(status) {
10529
10727
  return /^(connected|ok|ready|success)$/i.test(status.trim());
10530
10728
  }
10729
+ function isMcpAuthStatus(status) {
10730
+ return /needs[_-]?auth|needs authentication|unauthorized|not authenticated|authrequired/i.test(
10731
+ status
10732
+ );
10733
+ }
10734
+ function isSideboardMcpName(name) {
10735
+ return /^sideboard$/i.test(name.trim()) || /^mcp__sideboard$/i.test(name.trim());
10736
+ }
10737
+ function isVendorClaudeAiMcpName(name) {
10738
+ return /^claude\.ai\b/i.test(name.trim()) || /^mcp__claude_ai_/i.test(name.trim());
10739
+ }
10740
+ function isNotableMcpInitStatus(server) {
10741
+ if (isCleanMcpConnect(server.status)) return false;
10742
+ if (isSideboardMcpName(server.name)) return true;
10743
+ if (isVendorClaudeAiMcpName(server.name)) return false;
10744
+ if (isMcpAuthStatus(server.status)) return false;
10745
+ return true;
10746
+ }
10531
10747
  function eventsFromClaudeSystem(obj) {
10532
10748
  const subtype = claudeString(obj, "subtype") ?? "";
10533
10749
  const parentId = claudeParentToolUseId(obj);
@@ -10970,13 +11186,13 @@ var init_claude = __esm({
10970
11186
  });
10971
11187
 
10972
11188
  // src/agents/user-mcp-config.ts
10973
- var import_node_fs27, import_node_os10, import_node_path28;
11189
+ var import_node_fs27, import_node_os10, import_node_path29;
10974
11190
  var init_user_mcp_config = __esm({
10975
11191
  "src/agents/user-mcp-config.ts"() {
10976
11192
  "use strict";
10977
11193
  import_node_fs27 = require("fs");
10978
11194
  import_node_os10 = require("os");
10979
- import_node_path28 = require("path");
11195
+ import_node_path29 = require("path");
10980
11196
  init_paths();
10981
11197
  init_injected_mcp();
10982
11198
  }
@@ -11017,12 +11233,12 @@ function readText(path) {
11017
11233
  }
11018
11234
  }
11019
11235
  function userCodexConfigPaths(home = (0, import_node_os11.homedir)()) {
11020
- return [(0, import_node_path29.join)(home, ".codex", "config.toml"), (0, import_node_path29.join)(home, ".config", "codex", "config.toml")];
11236
+ return [(0, import_node_path30.join)(home, ".codex", "config.toml"), (0, import_node_path30.join)(home, ".config", "codex", "config.toml")];
11021
11237
  }
11022
11238
  function userOpencodeConfigPaths(home = (0, import_node_os11.homedir)()) {
11023
11239
  return [
11024
- (0, import_node_path29.join)(home, ".config", "opencode", "opencode.json"),
11025
- (0, import_node_path29.join)(home, ".config", "opencode", "opencode.jsonc")
11240
+ (0, import_node_path30.join)(home, ".config", "opencode", "opencode.json"),
11241
+ (0, import_node_path30.join)(home, ".config", "opencode", "opencode.jsonc")
11026
11242
  ];
11027
11243
  }
11028
11244
  function userMcpNamesToDisable(opts) {
@@ -11077,13 +11293,13 @@ function toCodexUnattendedAppsArgs() {
11077
11293
  "features.plugins=false"
11078
11294
  ];
11079
11295
  }
11080
- var import_node_fs28, import_node_os11, import_node_path29, import_smol_toml2;
11296
+ var import_node_fs28, import_node_os11, import_node_path30, import_smol_toml2;
11081
11297
  var init_orch_mcp_isolation = __esm({
11082
11298
  "src/agents/orch-mcp-isolation.ts"() {
11083
11299
  "use strict";
11084
11300
  import_node_fs28 = require("fs");
11085
11301
  import_node_os11 = require("os");
11086
- import_node_path29 = require("path");
11302
+ import_node_path30 = require("path");
11087
11303
  import_smol_toml2 = require("smol-toml");
11088
11304
  init_user_mcp_config();
11089
11305
  }
@@ -11134,8 +11350,8 @@ function usageFromCodex(usage) {
11134
11350
  }
11135
11351
  function codexConfigHasNetworkAccess() {
11136
11352
  const candidates = [
11137
- (0, import_node_path30.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
11138
- (0, import_node_path30.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
11353
+ (0, import_node_path31.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
11354
+ (0, import_node_path31.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
11139
11355
  ];
11140
11356
  for (const path of candidates) {
11141
11357
  if (!(0, import_node_fs29.existsSync)(path)) continue;
@@ -11171,7 +11387,7 @@ function asRecord2(value) {
11171
11387
  return void 0;
11172
11388
  }
11173
11389
  function codexLooksAuthenticated() {
11174
- const authPath = (0, import_node_path30.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
11390
+ const authPath = (0, import_node_path31.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
11175
11391
  if (!(0, import_node_fs29.existsSync)(authPath)) return false;
11176
11392
  try {
11177
11393
  return (0, import_node_fs29.statSync)(authPath).size > 2;
@@ -11179,13 +11395,13 @@ function codexLooksAuthenticated() {
11179
11395
  return false;
11180
11396
  }
11181
11397
  }
11182
- var import_node_fs29, import_node_os12, import_node_path30, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
11398
+ var import_node_fs29, import_node_os12, import_node_path31, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
11183
11399
  var init_codex = __esm({
11184
11400
  "src/agents/codex.ts"() {
11185
11401
  "use strict";
11186
11402
  import_node_fs29 = require("fs");
11187
11403
  import_node_os12 = require("os");
11188
- import_node_path30 = require("path");
11404
+ import_node_path31 = require("path");
11189
11405
  init_run();
11190
11406
  init_app_settings();
11191
11407
  init_global_workspace();
@@ -11519,7 +11735,7 @@ function platformRipgrepPackage() {
11519
11735
  }
11520
11736
  function usableRipgrepPath(candidate) {
11521
11737
  const raw = candidate?.trim();
11522
- if (!raw || !(0, import_node_path31.isAbsolute)(raw)) return null;
11738
+ if (!raw || !(0, import_node_path32.isAbsolute)(raw)) return null;
11523
11739
  const readable = nodeReadableScriptPath(raw);
11524
11740
  if (!(0, import_node_fs30.existsSync)(readable) || isAsarPath(readable)) return null;
11525
11741
  return readable;
@@ -11528,12 +11744,12 @@ function walkForBundledRipgrep(startFile) {
11528
11744
  if (!startFile) return null;
11529
11745
  const pkg = platformRipgrepPackage();
11530
11746
  const name = rgBinaryName();
11531
- let dir = (0, import_node_path31.dirname)((0, import_node_path31.resolve)(startFile));
11532
- const root = (0, import_node_path31.parse)(dir).root;
11747
+ let dir = (0, import_node_path32.dirname)((0, import_node_path32.resolve)(startFile));
11748
+ const root = (0, import_node_path32.parse)(dir).root;
11533
11749
  while (dir !== root) {
11534
- const hit = usableRipgrepPath((0, import_node_path31.join)(dir, "node_modules", pkg, "bin", name));
11750
+ const hit = usableRipgrepPath((0, import_node_path32.join)(dir, "node_modules", pkg, "bin", name));
11535
11751
  if (hit) return hit;
11536
- const next = (0, import_node_path31.dirname)(dir);
11752
+ const next = (0, import_node_path32.dirname)(dir);
11537
11753
  if (next === dir) break;
11538
11754
  dir = next;
11539
11755
  }
@@ -11543,7 +11759,7 @@ function requireResolveBundledRipgrep(fromFile) {
11543
11759
  try {
11544
11760
  const req = (0, import_node_module2.createRequire)(fromFile);
11545
11761
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
11546
- return usableRipgrepPath((0, import_node_path31.join)((0, import_node_path31.dirname)(pkgJson), "bin", rgBinaryName()));
11762
+ return usableRipgrepPath((0, import_node_path32.join)((0, import_node_path32.dirname)(pkgJson), "bin", rgBinaryName()));
11547
11763
  } catch {
11548
11764
  return null;
11549
11765
  }
@@ -11565,13 +11781,13 @@ function cursorRipgrepEnv(opts) {
11565
11781
  const path = resolveCursorRipgrepPath(opts);
11566
11782
  return path ? { [RIPGREP_ENV]: path } : {};
11567
11783
  }
11568
- var import_node_fs30, import_node_module2, import_node_path31, RIPGREP_ENV;
11784
+ var import_node_fs30, import_node_module2, import_node_path32, RIPGREP_ENV;
11569
11785
  var init_cursor_ripgrep = __esm({
11570
11786
  "src/agents/cursor-ripgrep.ts"() {
11571
11787
  "use strict";
11572
11788
  import_node_fs30 = require("fs");
11573
11789
  import_node_module2 = require("module");
11574
- import_node_path31 = require("path");
11790
+ import_node_path32 = require("path");
11575
11791
  init_node_launch();
11576
11792
  init_packaged_runtime();
11577
11793
  RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
@@ -11612,11 +11828,11 @@ function entryDir() {
11612
11828
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
11613
11829
  if (cjsDir) return cjsDir;
11614
11830
  try {
11615
- return (0, import_node_path32.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
11831
+ return (0, import_node_path33.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
11616
11832
  } catch {
11617
11833
  try {
11618
11834
  const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
11619
- return (0, import_node_path32.dirname)(req.resolve("@sideboard-ai/core"));
11835
+ return (0, import_node_path33.dirname)(req.resolve("@sideboard-ai/core"));
11620
11836
  } catch {
11621
11837
  return process.cwd();
11622
11838
  }
@@ -11627,27 +11843,27 @@ function cursorRunnerPath() {
11627
11843
  if (packaged) return packaged;
11628
11844
  const root = entryDir();
11629
11845
  const candidates = [
11630
- (0, import_node_path32.join)(root, "agents", "cursor-runner.js"),
11631
- (0, import_node_path32.join)(root, "agents", "cursor-runner.cjs"),
11846
+ (0, import_node_path33.join)(root, "agents", "cursor-runner.js"),
11847
+ (0, import_node_path33.join)(root, "agents", "cursor-runner.cjs"),
11632
11848
  // If somehow resolved from package root instead of dist/
11633
- (0, import_node_path32.join)(root, "dist", "agents", "cursor-runner.js"),
11634
- (0, import_node_path32.join)(root, "dist", "agents", "cursor-runner.cjs"),
11849
+ (0, import_node_path33.join)(root, "dist", "agents", "cursor-runner.js"),
11850
+ (0, import_node_path33.join)(root, "dist", "agents", "cursor-runner.cjs"),
11635
11851
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
11636
- (0, import_node_path32.join)(root, "cursor-runner.ts"),
11637
- (0, import_node_path32.join)(root, "src", "agents", "cursor-runner.ts")
11852
+ (0, import_node_path33.join)(root, "cursor-runner.ts"),
11853
+ (0, import_node_path33.join)(root, "src", "agents", "cursor-runner.ts")
11638
11854
  ];
11639
11855
  for (const candidate of candidates) {
11640
11856
  if ((0, import_node_fs31.existsSync)(candidate)) return candidate;
11641
11857
  }
11642
11858
  return candidates[0];
11643
11859
  }
11644
- var import_node_fs31, import_node_module3, import_node_path32, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
11860
+ var import_node_fs31, import_node_module3, import_node_path33, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
11645
11861
  var init_cursor = __esm({
11646
11862
  "src/agents/cursor.ts"() {
11647
11863
  "use strict";
11648
11864
  import_node_fs31 = require("fs");
11649
11865
  import_node_module3 = require("module");
11650
- import_node_path32 = require("path");
11866
+ import_node_path33 = require("path");
11651
11867
  import_node_url2 = require("url");
11652
11868
  import_sdk = require("@cursor/sdk");
11653
11869
  init_run();
@@ -12348,13 +12564,13 @@ var init_claude_usage = __esm({
12348
12564
  });
12349
12565
 
12350
12566
  // src/agents/claude-usage-client.ts
12351
- var import_node_fs33, import_node_os13, import_node_path33, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS;
12567
+ var import_node_fs33, import_node_os13, import_node_path34, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS;
12352
12568
  var init_claude_usage_client = __esm({
12353
12569
  "src/agents/claude-usage-client.ts"() {
12354
12570
  "use strict";
12355
12571
  import_node_fs33 = require("fs");
12356
12572
  import_node_os13 = require("os");
12357
- import_node_path33 = require("path");
12573
+ import_node_path34 = require("path");
12358
12574
  init_run();
12359
12575
  init_fetch();
12360
12576
  init_app_settings();
@@ -12415,15 +12631,15 @@ var init_agents = __esm({
12415
12631
 
12416
12632
  // src/hook/worktree-pkg-cache.ts
12417
12633
  function worktreePkgCacheRoot(worktreePath) {
12418
- return (0, import_node_path34.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
12634
+ return (0, import_node_path35.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
12419
12635
  }
12420
12636
  function worktreePkgCacheEnv(worktreePath) {
12421
12637
  const root = worktreePkgCacheRoot(worktreePath);
12422
- const store = (0, import_node_path34.join)(root, "pnpm-store");
12423
- const pnpmCache = (0, import_node_path34.join)(root, "pnpm");
12424
- const npmCache = (0, import_node_path34.join)(root, "npm");
12425
- const nodeGyp = (0, import_node_path34.join)(root, "node-gyp");
12426
- const electron = (0, import_node_path34.join)(root, "electron");
12638
+ const store = (0, import_node_path35.join)(root, "pnpm-store");
12639
+ const pnpmCache = (0, import_node_path35.join)(root, "pnpm");
12640
+ const npmCache = (0, import_node_path35.join)(root, "npm");
12641
+ const nodeGyp = (0, import_node_path35.join)(root, "node-gyp");
12642
+ const electron = (0, import_node_path35.join)(root, "electron");
12427
12643
  return {
12428
12644
  npm_config_store_dir: store,
12429
12645
  PNPM_STORE_DIR: store,
@@ -12459,12 +12675,12 @@ function applyWorktreePkgCacheEnv(env, worktreePath) {
12459
12675
  fillGroup(env, ["electron_config_cache"], next);
12460
12676
  ensureWorktreePkgCacheDirs(cwd);
12461
12677
  }
12462
- var import_node_fs34, import_node_path34, WORKTREE_PKG_CACHE_REL;
12678
+ var import_node_fs34, import_node_path35, WORKTREE_PKG_CACHE_REL;
12463
12679
  var init_worktree_pkg_cache = __esm({
12464
12680
  "src/hook/worktree-pkg-cache.ts"() {
12465
12681
  "use strict";
12466
12682
  import_node_fs34 = require("fs");
12467
- import_node_path34 = require("path");
12683
+ import_node_path35 = require("path");
12468
12684
  WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
12469
12685
  }
12470
12686
  });
@@ -13634,12 +13850,12 @@ function readTextIfPresent(abs) {
13634
13850
  }
13635
13851
  }
13636
13852
  function readLocalGuidelines(worktreePath) {
13637
- const localAbs = (0, import_node_path35.join)(worktreePath, REVIEW_REQUEST_PATH);
13853
+ const localAbs = (0, import_node_path36.join)(worktreePath, REVIEW_REQUEST_PATH);
13638
13854
  const localContent = readTextIfPresent(localAbs);
13639
13855
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
13640
13856
  return { path: REVIEW_REQUEST_PATH, content: localContent };
13641
13857
  }
13642
- const legacyAbs = (0, import_node_path35.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
13858
+ const legacyAbs = (0, import_node_path36.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
13643
13859
  const legacyContent = readTextIfPresent(legacyAbs);
13644
13860
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
13645
13861
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -13663,27 +13879,27 @@ function contextGuidelines(content, source) {
13663
13879
  };
13664
13880
  }
13665
13881
  function writeContextGuidelines(worktreePath, content) {
13666
- const abs = (0, import_node_path35.join)(worktreePath, CONTEXT_REVIEW_PATH);
13667
- (0, import_node_fs35.mkdirSync)((0, import_node_path35.dirname)(abs), { recursive: true });
13882
+ const abs = (0, import_node_path36.join)(worktreePath, CONTEXT_REVIEW_PATH);
13883
+ (0, import_node_fs35.mkdirSync)((0, import_node_path36.dirname)(abs), { recursive: true });
13668
13884
  const body = content.endsWith("\n") ? content : `${content}
13669
13885
  `;
13670
13886
  (0, import_node_fs35.writeFileSync)(abs, body, "utf8");
13671
13887
  return body;
13672
13888
  }
13673
13889
  function readSideboardReview(worktreePath, repoPath) {
13674
- const fromWorktree = readTextIfPresent((0, import_node_path35.join)(worktreePath, REPO_REVIEW_PATH));
13890
+ const fromWorktree = readTextIfPresent((0, import_node_path36.join)(worktreePath, REPO_REVIEW_PATH));
13675
13891
  if (fromWorktree) return fromWorktree;
13676
13892
  const repo = repoPath?.replace(/\/+$/, "");
13677
13893
  const wt = worktreePath.replace(/\/+$/, "");
13678
13894
  if (!repo || repo === wt) return null;
13679
- return readTextIfPresent((0, import_node_path35.join)(repo, REPO_REVIEW_PATH));
13895
+ return readTextIfPresent((0, import_node_path36.join)(repo, REPO_REVIEW_PATH));
13680
13896
  }
13681
13897
  function ensureReviewGuidelinesFile(worktreePath, repoPath) {
13682
- const skillContent = readTextIfPresent((0, import_node_path35.join)(worktreePath, REVIEW_SKILL_PATH));
13898
+ const skillContent = readTextIfPresent((0, import_node_path36.join)(worktreePath, REVIEW_SKILL_PATH));
13683
13899
  if (skillContent) {
13684
13900
  return { ...skillGuidelines(skillContent, "skill"), wrote: false };
13685
13901
  }
13686
- const contextContent = readTextIfPresent((0, import_node_path35.join)(worktreePath, CONTEXT_REVIEW_PATH));
13902
+ const contextContent = readTextIfPresent((0, import_node_path36.join)(worktreePath, CONTEXT_REVIEW_PATH));
13687
13903
  if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
13688
13904
  return { ...contextGuidelines(contextContent, "local"), wrote: false };
13689
13905
  }
@@ -13738,13 +13954,13 @@ async function requestReview(threadRef, send) {
13738
13954
  const started = await send(tab.id, REVIEW_REQUEST_PREFILL);
13739
13955
  return { tab: started, from };
13740
13956
  }
13741
- var import_node_crypto7, import_node_fs35, import_node_path35, 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;
13957
+ var import_node_crypto7, import_node_fs35, import_node_path36, 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;
13742
13958
  var init_request_review = __esm({
13743
13959
  "src/review/request-review.ts"() {
13744
13960
  "use strict";
13745
13961
  import_node_crypto7 = require("crypto");
13746
13962
  import_node_fs35 = require("fs");
13747
- import_node_path35 = require("path");
13963
+ import_node_path36 = require("path");
13748
13964
  init_global_workspace();
13749
13965
  init_chat_tabs();
13750
13966
  init_thread_store();
@@ -13770,7 +13986,7 @@ function matchSimpleGlob(pattern, name) {
13770
13986
  return new RegExp(`^${escaped}$`).test(name);
13771
13987
  }
13772
13988
  function readWorktreeInclude(repoPath) {
13773
- const path = (0, import_node_path36.join)(repoPath, ".worktreeinclude");
13989
+ const path = (0, import_node_path37.join)(repoPath, ".worktreeinclude");
13774
13990
  if (!(0, import_node_fs36.existsSync)(path)) return [];
13775
13991
  return (0, import_node_fs36.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
13776
13992
  }
@@ -13785,7 +14001,7 @@ function resolveFilesToCopy(repoPath) {
13785
14001
  for (const entry of (0, import_node_fs36.readdirSync)(repoPath, { withFileTypes: true })) {
13786
14002
  if (!entry.isFile()) continue;
13787
14003
  for (const glob of settings.fileIncludeGlobs) {
13788
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path36.basename)(glob), entry.name)) {
14004
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path37.basename)(glob), entry.name)) {
13789
14005
  matched.push(entry.name);
13790
14006
  break;
13791
14007
  }
@@ -13811,10 +14027,10 @@ function copyConfiguredFiles(repoPath, worktreePath) {
13811
14027
  const patterns = resolveFilesToCopy(repoPath);
13812
14028
  const copied = [];
13813
14029
  for (const rel of patterns) {
13814
- const src = (0, import_node_path36.join)(repoPath, rel);
14030
+ const src = (0, import_node_path37.join)(repoPath, rel);
13815
14031
  if (!(0, import_node_fs36.existsSync)(src)) continue;
13816
- const dest = (0, import_node_path36.join)(worktreePath, rel);
13817
- (0, import_node_fs36.mkdirSync)((0, import_node_path36.dirname)(dest), { recursive: true });
14032
+ const dest = (0, import_node_path37.join)(worktreePath, rel);
14033
+ (0, import_node_fs36.mkdirSync)((0, import_node_path37.dirname)(dest), { recursive: true });
13818
14034
  (0, import_node_fs36.copyFileSync)(src, dest);
13819
14035
  copied.push(rel);
13820
14036
  }
@@ -13850,7 +14066,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
13850
14066
  const env = stripNestedElectronEnv({
13851
14067
  ...baseEnv ?? process.env
13852
14068
  });
13853
- const name = opts.workspaceName ?? (0, import_node_path36.basename)(opts.worktreePath);
14069
+ const name = opts.workspaceName ?? (0, import_node_path37.basename)(opts.worktreePath);
13854
14070
  const ports = opts.ports ?? [];
13855
14071
  const primary = ports[0];
13856
14072
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -14113,13 +14329,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
14113
14329
  done: handle.done
14114
14330
  };
14115
14331
  }
14116
- var import_node_fs36, import_node_net, import_node_path36, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
14332
+ var import_node_fs36, import_node_net, import_node_path37, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
14117
14333
  var init_conductor = __esm({
14118
14334
  "src/hook/conductor.ts"() {
14119
14335
  "use strict";
14120
14336
  import_node_fs36 = require("fs");
14121
14337
  import_node_net = require("net");
14122
- import_node_path36 = require("path");
14338
+ import_node_path37 = require("path");
14123
14339
  import_execa4 = require("execa");
14124
14340
  import_node_readline3 = require("readline");
14125
14341
  init_settings();
@@ -14146,7 +14362,7 @@ ${line}` : line;
14146
14362
  return nl >= 0 && nl < cut.length - 1 ? cut.slice(nl + 1) : cut;
14147
14363
  }
14148
14364
  function setupLogPath(threadId) {
14149
- return (0, import_node_path37.join)(threadsDir(), `${threadId}.setup.log.json`);
14365
+ return (0, import_node_path38.join)(threadsDir(), `${threadId}.setup.log.json`);
14150
14366
  }
14151
14367
  function setupLogKeyForWorktree(worktreePath) {
14152
14368
  const norm = normalizeWorktreePath(worktreePath);
@@ -14241,13 +14457,13 @@ function finishSetupLog(threadId, exitCode, source) {
14241
14457
  persistNow(threadId);
14242
14458
  return clone(snap);
14243
14459
  }
14244
- var import_node_crypto8, import_node_fs37, import_node_path37, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers;
14460
+ var import_node_crypto8, import_node_fs37, import_node_path38, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers;
14245
14461
  var init_setup_log = __esm({
14246
14462
  "src/store/setup-log.ts"() {
14247
14463
  "use strict";
14248
14464
  import_node_crypto8 = require("crypto");
14249
14465
  import_node_fs37 = require("fs");
14250
- import_node_path37 = require("path");
14466
+ import_node_path38 = require("path");
14251
14467
  init_worktree_labels();
14252
14468
  init_paths();
14253
14469
  EMPTY = {
@@ -14309,9 +14525,9 @@ async function findOrphanWorktrees(repoPaths) {
14309
14525
  if ((0, import_node_fs38.existsSync)(root)) {
14310
14526
  for (const entry of (0, import_node_fs38.readdirSync)(root, { withFileTypes: true })) {
14311
14527
  if (!entry.isDirectory()) continue;
14312
- const path = (0, import_node_path38.join)(root, entry.name).replace(/\/$/, "");
14528
+ const path = (0, import_node_path39.join)(root, entry.name).replace(/\/$/, "");
14313
14529
  if (known.has(path) || seen.has(path)) continue;
14314
- if (!(0, import_node_fs38.existsSync)((0, import_node_path38.join)(path, ".git"))) continue;
14530
+ if (!(0, import_node_fs38.existsSync)((0, import_node_path39.join)(path, ".git"))) continue;
14315
14531
  seen.add(path);
14316
14532
  let mtimeMs = 0;
14317
14533
  try {
@@ -14367,12 +14583,12 @@ function shouldRunWorktreeCleanup(settings = loadAppSettings()) {
14367
14583
  const elapsed = Date.now() - Date.parse(last);
14368
14584
  return elapsed >= intervalHours * 36e5;
14369
14585
  }
14370
- var import_node_fs38, import_node_path38;
14586
+ var import_node_fs38, import_node_path39;
14371
14587
  var init_orphan_cleanup = __esm({
14372
14588
  "src/git/orphan-cleanup.ts"() {
14373
14589
  "use strict";
14374
14590
  import_node_fs38 = require("fs");
14375
- import_node_path38 = require("path");
14591
+ import_node_path39 = require("path");
14376
14592
  init_worktree();
14377
14593
  init_thread_store();
14378
14594
  init_paths();
@@ -14380,6 +14596,77 @@ var init_orphan_cleanup = __esm({
14380
14596
  }
14381
14597
  });
14382
14598
 
14599
+ // src/store/history-cleanup.ts
14600
+ function stripArchivedTranscript(thread) {
14601
+ writeThread(
14602
+ {
14603
+ ...thread,
14604
+ attachments: [],
14605
+ pendingTurnAttachments: [],
14606
+ messages: [historyRetentionStubMessage(thread)]
14607
+ },
14608
+ { touch: false }
14609
+ );
14610
+ }
14611
+ function cleanupArchivedHistory(opts = {}) {
14612
+ const settings = loadAppSettings();
14613
+ if (!opts.force && opts.purgeOlderThanDays == null && !autoCleanupHistoryEnabled(settings)) {
14614
+ return { stripped: [], purged: [] };
14615
+ }
14616
+ const archived = listThreads({ includeArchived: true }).filter((t) => t.status === "archived");
14617
+ const nowMs = opts.nowMs ?? Date.now();
14618
+ const plan = opts.purgeOlderThanDays != null ? { stripIds: [], purgeIds: planHistoryAgePurge(archived, opts.purgeOlderThanDays, nowMs) } : planHistoryRetention(archived, {
14619
+ maxCount: opts.maxCount ?? historyMaxCount(settings),
14620
+ maxDays: opts.maxDays ?? historyMaxDays(settings),
14621
+ nowMs
14622
+ });
14623
+ const stripped = [];
14624
+ const purged = [];
14625
+ if (opts.dryRun) {
14626
+ return { stripped: plan.stripIds, purged: plan.purgeIds };
14627
+ }
14628
+ for (const id of plan.stripIds) {
14629
+ const thread = readThread(id);
14630
+ if (!thread || thread.status !== "archived") continue;
14631
+ try {
14632
+ stripArchivedTranscript(thread);
14633
+ stripped.push(id);
14634
+ } catch {
14635
+ }
14636
+ }
14637
+ for (const id of plan.purgeIds) {
14638
+ const thread = readThread(id);
14639
+ if (!thread || thread.status !== "archived") continue;
14640
+ try {
14641
+ deleteThreadRecord(id);
14642
+ purged.push(id);
14643
+ } catch {
14644
+ }
14645
+ }
14646
+ if (stripped.length > 0 || purged.length > 0) {
14647
+ updateAdvancedSettings({
14648
+ historyLastCleanupAt: new Date(nowMs).toISOString()
14649
+ });
14650
+ }
14651
+ return { stripped, purged };
14652
+ }
14653
+ function shouldRunHistoryCleanup(settings = loadAppSettings()) {
14654
+ if (!autoCleanupHistoryEnabled(settings)) return false;
14655
+ const intervalHours = settings.advanced.historyCleanupIntervalHours ?? HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT;
14656
+ const last = settings.advanced.historyLastCleanupAt;
14657
+ if (!last) return true;
14658
+ const elapsed = Date.now() - Date.parse(last);
14659
+ return Number.isFinite(elapsed) && elapsed >= intervalHours * 36e5;
14660
+ }
14661
+ var init_history_cleanup = __esm({
14662
+ "src/store/history-cleanup.ts"() {
14663
+ "use strict";
14664
+ init_app_settings();
14665
+ init_history_retention();
14666
+ init_thread_store();
14667
+ }
14668
+ });
14669
+
14383
14670
  // src/git/apply-into-main.ts
14384
14671
  async function applyThreadIntoMain(thread, opts) {
14385
14672
  const method = opts?.method ?? "merge";
@@ -14475,11 +14762,11 @@ async function cloneRepoIntoSideboard(opts) {
14475
14762
  if (!url) throw new Error("Clone URL is required");
14476
14763
  let name = opts.name?.trim();
14477
14764
  if (!name) {
14478
- const leaf = (0, import_node_path39.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
14765
+ const leaf = (0, import_node_path40.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
14479
14766
  name = leaf || "repo";
14480
14767
  }
14481
14768
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
14482
- const dest = (0, import_node_path39.join)(sideboardReposDir(), name);
14769
+ const dest = (0, import_node_path40.join)(sideboardReposDir(), name);
14483
14770
  if ((0, import_node_fs39.existsSync)(dest)) {
14484
14771
  const repoPath2 = await resolveRepoRoot(dest);
14485
14772
  const workspace2 = await ensureWorkspace(repoPath2);
@@ -14495,12 +14782,12 @@ async function cloneRepoIntoSideboard(opts) {
14495
14782
  const workspace = await ensureWorkspace(repoPath);
14496
14783
  return { repoPath, workspace };
14497
14784
  }
14498
- var import_node_fs39, import_node_path39, import_execa6;
14785
+ var import_node_fs39, import_node_path40, import_execa6;
14499
14786
  var init_clone_repo = __esm({
14500
14787
  "src/git/clone-repo.ts"() {
14501
14788
  "use strict";
14502
14789
  import_node_fs39 = require("fs");
14503
- import_node_path39 = require("path");
14790
+ import_node_path40 = require("path");
14504
14791
  import_execa6 = require("execa");
14505
14792
  init_paths();
14506
14793
  init_workspaces2();
@@ -14510,7 +14797,7 @@ var init_clone_repo = __esm({
14510
14797
 
14511
14798
  // src/store/desktop-host.ts
14512
14799
  function desktopHostPidPath() {
14513
- return (0, import_node_path40.join)(appDataDir(), "desktop-host.pid");
14800
+ return (0, import_node_path41.join)(appDataDir(), "desktop-host.pid");
14514
14801
  }
14515
14802
  function readDesktopHostPid() {
14516
14803
  try {
@@ -14540,12 +14827,12 @@ function thisProcessShouldDrainAgentQueues() {
14540
14827
  if (isThisProcessDesktopHost()) return true;
14541
14828
  return !isDesktopHostAlive();
14542
14829
  }
14543
- var import_node_fs40, import_node_path40;
14830
+ var import_node_fs40, import_node_path41;
14544
14831
  var init_desktop_host = __esm({
14545
14832
  "src/store/desktop-host.ts"() {
14546
14833
  "use strict";
14547
14834
  import_node_fs40 = require("fs");
14548
- import_node_path40 = require("path");
14835
+ import_node_path41 = require("path");
14549
14836
  init_paths();
14550
14837
  }
14551
14838
  });
@@ -14668,7 +14955,7 @@ function readIntFile(file) {
14668
14955
  return Number.isInteger(n) ? n : null;
14669
14956
  }
14670
14957
  function jobDir(root, id, legacy = false) {
14671
- return (0, import_node_path41.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
14958
+ return (0, import_node_path42.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
14672
14959
  }
14673
14960
  function resolveJobDir(root, id) {
14674
14961
  const modern = jobDir(root, id, false);
@@ -14678,7 +14965,7 @@ function resolveJobDir(root, id) {
14678
14965
  return modern;
14679
14966
  }
14680
14967
  function listJobIdsIn(root, rel) {
14681
- const dir = (0, import_node_path41.join)(root, rel);
14968
+ const dir = (0, import_node_path42.join)(root, rel);
14682
14969
  if (!(0, import_node_fs41.existsSync)(dir)) return [];
14683
14970
  return (0, import_node_fs41.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
14684
14971
  }
@@ -14692,7 +14979,7 @@ function listRunningDetachedJobs(worktreePath) {
14692
14979
  const running = [];
14693
14980
  for (const id of ids) {
14694
14981
  const dir = resolveJobDir(root, id);
14695
- const pid = readIntFile((0, import_node_path41.join)(dir, "pid"));
14982
+ const pid = readIntFile((0, import_node_path42.join)(dir, "pid"));
14696
14983
  if (jobTreeAlive(pid)) running.push(id);
14697
14984
  }
14698
14985
  return running.sort();
@@ -14795,15 +15082,15 @@ function takeDelta(logFile, cursorFile) {
14795
15082
  return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
14796
15083
  }
14797
15084
  function snapshotJob(dir) {
14798
- const pid = readIntFile((0, import_node_path41.join)(dir, "pid"));
15085
+ const pid = readIntFile((0, import_node_path42.join)(dir, "pid"));
14799
15086
  const running = jobTreeAlive(pid);
14800
15087
  return {
14801
15088
  pid,
14802
15089
  running,
14803
- exitCode: readIntFile((0, import_node_path41.join)(dir, "exit")),
14804
- log: (0, import_node_path41.join)(dir, "log"),
14805
- cursor: (0, import_node_path41.join)(dir, "present.cursor"),
14806
- progress: tailProgress((0, import_node_path41.join)(dir, "log"))
15090
+ exitCode: readIntFile((0, import_node_path42.join)(dir, "exit")),
15091
+ log: (0, import_node_path42.join)(dir, "log"),
15092
+ cursor: (0, import_node_path42.join)(dir, "present.cursor"),
15093
+ progress: tailProgress((0, import_node_path42.join)(dir, "log"))
14807
15094
  };
14808
15095
  }
14809
15096
  function toResult(id, snap, extra) {
@@ -14812,7 +15099,7 @@ function toResult(id, snap, extra) {
14812
15099
  const stillRunning = snap.running && !ok;
14813
15100
  const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
14814
15101
  try {
14815
- (0, import_node_fs41.mkdirSync)((0, import_node_path41.dirname)(snap.cursor), { recursive: true });
15102
+ (0, import_node_fs41.mkdirSync)((0, import_node_path42.dirname)(snap.cursor), { recursive: true });
14816
15103
  (0, import_node_fs41.writeFileSync)(snap.cursor, `${nextCursor}
14817
15104
  `);
14818
15105
  } catch {
@@ -14888,7 +15175,7 @@ function killProcessTree(pid, signal) {
14888
15175
  }
14889
15176
  function appendJobLog(logFile, line) {
14890
15177
  try {
14891
- (0, import_node_fs41.mkdirSync)((0, import_node_path41.dirname)(logFile), { recursive: true });
15178
+ (0, import_node_fs41.mkdirSync)((0, import_node_path42.dirname)(logFile), { recursive: true });
14892
15179
  const body = line.endsWith("\n") ? line : `${line}
14893
15180
  `;
14894
15181
  (0, import_node_fs41.appendFileSync)(logFile, body);
@@ -14937,7 +15224,7 @@ async function stopDetachedJob(cwd, id, opts) {
14937
15224
  killProcessTree(targetPid, "SIGKILL");
14938
15225
  await sleep(100);
14939
15226
  }
14940
- const exitFile = (0, import_node_path41.join)(dir, "exit");
15227
+ const exitFile = (0, import_node_path42.join)(dir, "exit");
14941
15228
  if (!(0, import_node_fs41.existsSync)(exitFile)) {
14942
15229
  try {
14943
15230
  (0, import_node_fs41.writeFileSync)(exitFile, "1\n");
@@ -14960,12 +15247,12 @@ async function stopDetachedJob(cwd, id, opts) {
14960
15247
  hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
14961
15248
  };
14962
15249
  }
14963
- var import_node_fs41, import_node_path41, 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;
15250
+ var import_node_fs41, 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;
14964
15251
  var init_wait_for_job = __esm({
14965
15252
  "src/mcp/wait-for-job.ts"() {
14966
15253
  "use strict";
14967
15254
  import_node_fs41 = require("fs");
14968
- import_node_path41 = require("path");
15255
+ import_node_path42 = require("path");
14969
15256
  init_workspace_scratch();
14970
15257
  init_wait_for_turn();
14971
15258
  MAX_JOB_CONTINUES = 8;
@@ -17576,7 +17863,7 @@ var init_quota_failover = __esm({
17576
17863
  // src/threads/adopt.ts
17577
17864
  function thisModuleFile() {
17578
17865
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
17579
- return cjsFile || process.argv[1] || (0, import_node_path42.join)(process.cwd(), "package.json");
17866
+ return cjsFile || process.argv[1] || (0, import_node_path43.join)(process.cwd(), "package.json");
17580
17867
  }
17581
17868
  function openReadonlySqlite(file) {
17582
17869
  const req = (0, import_node_module4.createRequire)(thisModuleFile());
@@ -17604,7 +17891,7 @@ function resolveConductorCursorAgentId(workspacePath) {
17604
17891
  return null;
17605
17892
  }
17606
17893
  for (const hash of hashes) {
17607
- const agentsFile = (0, import_node_path42.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
17894
+ const agentsFile = (0, import_node_path43.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
17608
17895
  if (!(0, import_node_fs44.existsSync)(agentsFile)) continue;
17609
17896
  let text7;
17610
17897
  try {
@@ -17661,8 +17948,8 @@ function listConductorWorkspaces() {
17661
17948
  if (!(0, import_node_fs44.existsSync)(CONDUCTOR_DB)) {
17662
17949
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
17663
17950
  }
17664
- const tmp = (0, import_node_fs44.mkdtempSync)((0, import_node_path42.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
17665
- const snapshot = (0, import_node_path42.join)(tmp, "conductor.db");
17951
+ const tmp = (0, import_node_fs44.mkdtempSync)((0, import_node_path43.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
17952
+ const snapshot = (0, import_node_path43.join)(tmp, "conductor.db");
17666
17953
  try {
17667
17954
  (0, import_node_fs44.copyFileSync)(CONDUCTOR_DB, snapshot);
17668
17955
  for (const suffix of ["-wal", "-shm"]) {
@@ -17752,8 +18039,8 @@ function importConductorWorkspace(workspaceId) {
17752
18039
  if (!(0, import_node_fs44.existsSync)(CONDUCTOR_DB)) {
17753
18040
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
17754
18041
  }
17755
- const tmp = (0, import_node_fs44.mkdtempSync)((0, import_node_path42.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
17756
- const snapshot = (0, import_node_path42.join)(tmp, "conductor.db");
18042
+ const tmp = (0, import_node_fs44.mkdtempSync)((0, import_node_path43.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
18043
+ const snapshot = (0, import_node_path43.join)(tmp, "conductor.db");
17757
18044
  try {
17758
18045
  (0, import_node_fs44.copyFileSync)(CONDUCTOR_DB, snapshot);
17759
18046
  for (const suffix of ["-wal", "-shm"]) {
@@ -17847,25 +18134,25 @@ function importConductorWorkspace(workspaceId) {
17847
18134
  async function importConductorWorkspaceAsync(workspaceId) {
17848
18135
  return importConductorWorkspace(workspaceId);
17849
18136
  }
17850
- var import_node_child_process4, import_node_fs44, import_node_os14, import_node_path42, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
18137
+ var import_node_child_process4, import_node_fs44, import_node_os14, import_node_path43, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
17851
18138
  var init_adopt = __esm({
17852
18139
  "src/threads/adopt.ts"() {
17853
18140
  "use strict";
17854
18141
  import_node_child_process4 = require("child_process");
17855
18142
  import_node_fs44 = require("fs");
17856
18143
  import_node_os14 = require("os");
17857
- import_node_path42 = require("path");
18144
+ import_node_path43 = require("path");
17858
18145
  import_node_module4 = require("module");
17859
18146
  init_worktree();
17860
18147
  init_thread_store();
17861
- CONDUCTOR_APP_SUPPORT = (0, import_node_path42.join)(
18148
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path43.join)(
17862
18149
  process.env.HOME ?? "",
17863
18150
  "Library",
17864
18151
  "Application Support",
17865
18152
  "com.conductor.app"
17866
18153
  );
17867
- CONDUCTOR_DB = (0, import_node_path42.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
17868
- CURSOR_SDK_STORE = (0, import_node_path42.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
18154
+ CONDUCTOR_DB = (0, import_node_path43.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
18155
+ CURSOR_SDK_STORE = (0, import_node_path43.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
17869
18156
  }
17870
18157
  });
17871
18158
 
@@ -18310,7 +18597,7 @@ new file mode 100644
18310
18597
  };
18311
18598
  }
18312
18599
  async function untrackedPatch(worktreePath, path, maxHunk) {
18313
- const abs = (0, import_node_path43.join)(worktreePath, path);
18600
+ const abs = (0, import_node_path44.join)(worktreePath, path);
18314
18601
  try {
18315
18602
  const st = (0, import_node_fs46.statSync)(abs);
18316
18603
  if (st.isFile() && st.size > maxHunk) {
@@ -18803,7 +19090,7 @@ function isImageRelativePath(relativePath) {
18803
19090
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
18804
19091
  assertSafeRelativePath(relativePath);
18805
19092
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
18806
- const abs = (0, import_node_path43.join)(worktreePath, relativePath);
19093
+ const abs = (0, import_node_path44.join)(worktreePath, relativePath);
18807
19094
  const st = (0, import_node_fs46.statSync)(abs);
18808
19095
  if (!st.isFile()) {
18809
19096
  throw new Error(`Not a file: ${relativePath}`);
@@ -18823,7 +19110,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
18823
19110
  function readWorktreeFile(worktreePath, relativePath, opts) {
18824
19111
  assertSafeRelativePath(relativePath);
18825
19112
  const maxBytes = opts?.maxBytes ?? 2e5;
18826
- const abs = (0, import_node_path43.join)(worktreePath, relativePath);
19113
+ const abs = (0, import_node_path44.join)(worktreePath, relativePath);
18827
19114
  const st = (0, import_node_fs46.statSync)(abs);
18828
19115
  if (!st.isFile()) {
18829
19116
  throw new Error(`Not a file: ${relativePath}`);
@@ -18871,8 +19158,8 @@ function assertSafeRelativePath(relativePath) {
18871
19158
  }
18872
19159
  function writeWorktreeFile(worktreePath, relativePath, content) {
18873
19160
  assertSafeRelativePath(relativePath);
18874
- const abs = (0, import_node_path43.join)(worktreePath, relativePath);
18875
- (0, import_node_fs46.mkdirSync)((0, import_node_path43.dirname)(abs), { recursive: true });
19161
+ const abs = (0, import_node_path44.join)(worktreePath, relativePath);
19162
+ (0, import_node_fs46.mkdirSync)((0, import_node_path44.dirname)(abs), { recursive: true });
18876
19163
  (0, import_node_fs46.writeFileSync)(abs, content, "utf8");
18877
19164
  return { path: relativePath };
18878
19165
  }
@@ -18890,12 +19177,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
18890
19177
  truncated: full.files.length > maxFiles
18891
19178
  };
18892
19179
  }
18893
- var import_node_fs46, import_node_path43, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
19180
+ var import_node_fs46, import_node_path44, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
18894
19181
  var init_diff = __esm({
18895
19182
  "src/diff/diff.ts"() {
18896
19183
  "use strict";
18897
19184
  import_node_fs46 = require("fs");
18898
- import_node_path43 = require("path");
19185
+ import_node_path44 = require("path");
18899
19186
  init_run();
18900
19187
  init_worktree();
18901
19188
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -19280,7 +19567,7 @@ function scanSkillsDir(dir, source, out) {
19280
19567
  }
19281
19568
  for (const entry of entries) {
19282
19569
  if (entry.startsWith(".")) continue;
19283
- const skillMd = (0, import_node_path44.join)(dir, entry, "SKILL.md");
19570
+ const skillMd = (0, import_node_path45.join)(dir, entry, "SKILL.md");
19284
19571
  if (!(0, import_node_fs47.existsSync)(skillMd)) continue;
19285
19572
  try {
19286
19573
  if (!(0, import_node_fs47.statSync)(skillMd).isFile()) continue;
@@ -19302,12 +19589,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
19302
19589
  return;
19303
19590
  }
19304
19591
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
19305
- const skill = readSkill((0, import_node_path44.join)(dir, "SKILL.md"), "cli");
19592
+ const skill = readSkill((0, import_node_path45.join)(dir, "SKILL.md"), "cli");
19306
19593
  if (skill) out.push(skill);
19307
19594
  }
19308
19595
  for (const entry of entries) {
19309
19596
  if (entry === "node_modules" || entry === ".git") continue;
19310
- const full = (0, import_node_path44.join)(dir, entry);
19597
+ const full = (0, import_node_path45.join)(dir, entry);
19311
19598
  try {
19312
19599
  if (!(0, import_node_fs47.statSync)(full).isDirectory()) continue;
19313
19600
  } catch {
@@ -19327,17 +19614,17 @@ function discoverSkills(worktreePath) {
19327
19614
  const home = (0, import_node_os15.homedir)();
19328
19615
  const collected = [];
19329
19616
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
19330
- scanSkillsDir((0, import_node_path44.join)(worktreePath, rel), "workspace", collected);
19617
+ scanSkillsDir((0, import_node_path45.join)(worktreePath, rel), "workspace", collected);
19331
19618
  }
19332
19619
  for (const abs of [
19333
- (0, import_node_path44.join)(home, ".claude/skills"),
19334
- (0, import_node_path44.join)(home, ".cursor/skills"),
19335
- (0, import_node_path44.join)(home, ".sideboard/skills"),
19336
- (0, import_node_path44.join)(home, ".brightsy/skills")
19620
+ (0, import_node_path45.join)(home, ".claude/skills"),
19621
+ (0, import_node_path45.join)(home, ".cursor/skills"),
19622
+ (0, import_node_path45.join)(home, ".sideboard/skills"),
19623
+ (0, import_node_path45.join)(home, ".brightsy/skills")
19337
19624
  ]) {
19338
19625
  scanSkillsDir(abs, "user", collected);
19339
19626
  }
19340
- scanClaudePluginSkills((0, import_node_path44.join)(home, ".claude/plugins"), collected);
19627
+ scanClaudePluginSkills((0, import_node_path45.join)(home, ".claude/plugins"), collected);
19341
19628
  collected.push(...bundledSkills());
19342
19629
  const rank = {
19343
19630
  workspace: 0,
@@ -19377,13 +19664,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
19377
19664
 
19378
19665
  \u2026(truncated)` : raw;
19379
19666
  }
19380
- var import_node_fs47, import_node_os15, import_node_path44, BUNDLED_SKILL_PREFIX;
19667
+ var import_node_fs47, import_node_os15, import_node_path45, BUNDLED_SKILL_PREFIX;
19381
19668
  var init_discover = __esm({
19382
19669
  "src/skills/discover.ts"() {
19383
19670
  "use strict";
19384
19671
  import_node_fs47 = require("fs");
19385
19672
  import_node_os15 = require("os");
19386
- import_node_path44 = require("path");
19673
+ import_node_path45 = require("path");
19387
19674
  init_long_running();
19388
19675
  BUNDLED_SKILL_PREFIX = "bundled:";
19389
19676
  }
@@ -19474,10 +19761,37 @@ var init_expand = __esm({
19474
19761
  }
19475
19762
  });
19476
19763
 
19764
+ // src/composer/consume-attachments.ts
19765
+ function consumeComposerAttachments(thread) {
19766
+ if (thread.attachments.length === 0) {
19767
+ return {
19768
+ attachments: [],
19769
+ pendingTurnAttachments: thread.pendingTurnAttachments ?? []
19770
+ };
19771
+ }
19772
+ return {
19773
+ attachments: [],
19774
+ pendingTurnAttachments: [
19775
+ ...thread.pendingTurnAttachments ?? [],
19776
+ ...thread.attachments
19777
+ ]
19778
+ };
19779
+ }
19780
+ function takePendingTurnAttachments(thread) {
19781
+ const pending = thread.pendingTurnAttachments ?? [];
19782
+ if (pending.length === 0 && thread.attachments.length === 0) return [];
19783
+ return [...pending, ...thread.attachments];
19784
+ }
19785
+ var init_consume_attachments = __esm({
19786
+ "src/composer/consume-attachments.ts"() {
19787
+ "use strict";
19788
+ }
19789
+ });
19790
+
19477
19791
  // src/skills/detached-job-path.ts
19478
19792
  function detachedJobScriptIn(dir) {
19479
19793
  for (const name of DETACHED_JOB_FILENAMES) {
19480
- const script = (0, import_node_path45.join)(dir, "scripts", name);
19794
+ const script = (0, import_node_path46.join)(dir, "scripts", name);
19481
19795
  if ((0, import_node_fs48.existsSync)(script)) return script;
19482
19796
  }
19483
19797
  return null;
@@ -19490,11 +19804,11 @@ function packagedDetachedJobPath() {
19490
19804
  function resolveDetachedJobScript() {
19491
19805
  const packaged = packagedDetachedJobPath();
19492
19806
  if (packaged) return packaged;
19493
- let dir = (0, import_node_path45.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
19807
+ let dir = (0, import_node_path46.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
19494
19808
  for (let i = 0; i < 8; i++) {
19495
19809
  const candidate = detachedJobScriptIn(dir);
19496
19810
  if (candidate) return candidate;
19497
- const parent = (0, import_node_path45.dirname)(dir);
19811
+ const parent = (0, import_node_path46.dirname)(dir);
19498
19812
  if (parent === dir) break;
19499
19813
  dir = parent;
19500
19814
  }
@@ -19505,12 +19819,12 @@ function formatDetachedJobInvoke(scriptPath) {
19505
19819
  if (resolved) return `node ${JSON.stringify(resolved)}`;
19506
19820
  return "node scripts/detached-job.cjs";
19507
19821
  }
19508
- var import_node_fs48, import_node_path45, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
19822
+ var import_node_fs48, import_node_path46, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
19509
19823
  var init_detached_job_path = __esm({
19510
19824
  "src/skills/detached-job-path.ts"() {
19511
19825
  "use strict";
19512
19826
  import_node_fs48 = require("fs");
19513
- import_node_path45 = require("path");
19827
+ import_node_path46 = require("path");
19514
19828
  import_node_url3 = require("url");
19515
19829
  init_packaged_runtime();
19516
19830
  import_meta3 = {};
@@ -19670,9 +19984,9 @@ function formatPrGateDirective() {
19670
19984
  }
19671
19985
  function formatProcessGuideDirective(opts) {
19672
19986
  const worktree = opts?.worktreePath?.trim();
19673
- const hasGraphSkill = !!worktree && (0, import_node_fs49.existsSync)((0, import_node_path46.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
19674
- const hasReviewSkill = !!worktree && (0, import_node_fs49.existsSync)((0, import_node_path46.join)(worktree, ".claude/skills/review/SKILL.md"));
19675
- const hasInstallSkill = !!worktree && (0, import_node_fs49.existsSync)((0, import_node_path46.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
19987
+ const hasGraphSkill = !!worktree && (0, import_node_fs49.existsSync)((0, import_node_path47.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
19988
+ const hasReviewSkill = !!worktree && (0, import_node_fs49.existsSync)((0, import_node_path47.join)(worktree, ".claude/skills/review/SKILL.md"));
19989
+ const hasInstallSkill = !!worktree && (0, import_node_fs49.existsSync)((0, import_node_path47.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
19676
19990
  return [
19677
19991
  "Process guides (recurring work only):",
19678
19992
  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,
@@ -19710,12 +20024,12 @@ function formatArtifactDirective() {
19710
20024
  function formatUiReminder() {
19711
20025
  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.";
19712
20026
  }
19713
- var import_node_fs49, import_node_path46, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
20027
+ var import_node_fs49, import_node_path47, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
19714
20028
  var init_instructions = __esm({
19715
20029
  "src/agents/instructions.ts"() {
19716
20030
  "use strict";
19717
20031
  import_node_fs49 = require("fs");
19718
- import_node_path46 = require("path");
20032
+ import_node_path47 = require("path");
19719
20033
  init_git_auth_mode();
19720
20034
  init_branch_prefix();
19721
20035
  init_worktree_labels();
@@ -19939,13 +20253,13 @@ __export(plan_file_exports, {
19939
20253
  writePlanFile: () => writePlanFile
19940
20254
  });
19941
20255
  function ensureAttachmentsGitignore(worktreePath) {
19942
- const gitignoreAbs = (0, import_node_path47.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
20256
+ const gitignoreAbs = (0, import_node_path48.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
19943
20257
  if ((0, import_node_fs50.existsSync)(gitignoreAbs)) return;
19944
- (0, import_node_fs50.mkdirSync)((0, import_node_path47.dirname)(gitignoreAbs), { recursive: true });
20258
+ (0, import_node_fs50.mkdirSync)((0, import_node_path48.dirname)(gitignoreAbs), { recursive: true });
19945
20259
  (0, import_node_fs50.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
19946
20260
  }
19947
20261
  function planFileAbs(worktreePath) {
19948
- return (0, import_node_path47.join)(worktreePath, PLAN_FILE_REL);
20262
+ return (0, import_node_path48.join)(worktreePath, PLAN_FILE_REL);
19949
20263
  }
19950
20264
  function readTextIfPresent2(abs) {
19951
20265
  if (!(0, import_node_fs50.existsSync)(abs)) return null;
@@ -19957,22 +20271,22 @@ function readTextIfPresent2(abs) {
19957
20271
  }
19958
20272
  }
19959
20273
  function readPlanFile(worktreePath) {
19960
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path47.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path47.join)(worktreePath, LEGACY_PLAN_FILE_REL));
20274
+ 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));
19961
20275
  }
19962
20276
  function writePlanFile(worktreePath, content) {
19963
20277
  ensureAttachmentsGitignore(worktreePath);
19964
20278
  const abs = planFileAbs(worktreePath);
19965
- (0, import_node_fs50.mkdirSync)((0, import_node_path47.dirname)(abs), { recursive: true });
20279
+ (0, import_node_fs50.mkdirSync)((0, import_node_path48.dirname)(abs), { recursive: true });
19966
20280
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
19967
20281
  (0, import_node_fs50.writeFileSync)(abs, body, "utf8");
19968
20282
  return PLAN_FILE_REL;
19969
20283
  }
19970
- var import_node_fs50, import_node_path47;
20284
+ var import_node_fs50, import_node_path48;
19971
20285
  var init_plan_file = __esm({
19972
20286
  "src/plan/plan-file.ts"() {
19973
20287
  "use strict";
19974
20288
  import_node_fs50 = require("fs");
19975
- import_node_path47 = require("path");
20289
+ import_node_path48 = require("path");
19976
20290
  init_workspace_scratch();
19977
20291
  init_plan_present();
19978
20292
  init_plan_present();
@@ -20032,7 +20346,7 @@ function setCaffeinateHoldHooks(next) {
20032
20346
  hooks = next;
20033
20347
  }
20034
20348
  function caffeinateHoldPath() {
20035
- return (0, import_node_path48.join)(appDataDir(), "caffeinate-hold.json");
20349
+ return (0, import_node_path49.join)(appDataDir(), "caffeinate-hold.json");
20036
20350
  }
20037
20351
  function processAlive(pid) {
20038
20352
  if (hooks.processAlive) return hooks.processAlive(pid);
@@ -20175,13 +20489,13 @@ function releaseCaffeinateHoldForThread(threadId) {
20175
20489
  }
20176
20490
  return setCaffeinateHold(false, { threadId: id });
20177
20491
  }
20178
- var import_node_child_process5, import_node_fs51, import_node_path48, hooks;
20492
+ var import_node_child_process5, import_node_fs51, import_node_path49, hooks;
20179
20493
  var init_caffeinate_hold = __esm({
20180
20494
  "src/store/caffeinate-hold.ts"() {
20181
20495
  "use strict";
20182
20496
  import_node_child_process5 = require("child_process");
20183
20497
  import_node_fs51 = require("fs");
20184
- import_node_path48 = require("path");
20498
+ import_node_path49 = require("path");
20185
20499
  init_paths();
20186
20500
  init_private_file();
20187
20501
  hooks = {};
@@ -20190,7 +20504,7 @@ var init_caffeinate_hold = __esm({
20190
20504
 
20191
20505
  // src/store/schedules.ts
20192
20506
  function schedulesPath() {
20193
- return (0, import_node_path49.join)(appDataDir(), "schedules.json");
20507
+ return (0, import_node_path50.join)(appDataDir(), "schedules.json");
20194
20508
  }
20195
20509
  function parseDurationMs(every) {
20196
20510
  const m = every.trim().match(DURATION_RE);
@@ -20404,13 +20718,13 @@ function recordScheduleRun(id, result) {
20404
20718
  writeAll2(rows);
20405
20719
  return next;
20406
20720
  }
20407
- var import_node_crypto11, import_node_fs52, import_node_path49, import_croner, DURATION_RE, UNIT_MS;
20721
+ var import_node_crypto11, import_node_fs52, import_node_path50, import_croner, DURATION_RE, UNIT_MS;
20408
20722
  var init_schedules = __esm({
20409
20723
  "src/store/schedules.ts"() {
20410
20724
  "use strict";
20411
20725
  import_node_crypto11 = require("crypto");
20412
20726
  import_node_fs52 = require("fs");
20413
- import_node_path49 = require("path");
20727
+ import_node_path50 = require("path");
20414
20728
  import_croner = require("croner");
20415
20729
  init_orchestrator_capable();
20416
20730
  init_paths();
@@ -20550,37 +20864,6 @@ var init_schedule_runner = __esm({
20550
20864
  }
20551
20865
  });
20552
20866
 
20553
- // src/agents/cursor-store.ts
20554
- function cursorSdkStoreDir(threadId) {
20555
- const root = (0, import_node_path50.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
20556
- const id = sanitizeCursorStoreSegment(threadId);
20557
- if (!id) return root;
20558
- return (0, import_node_path50.join)(root, "threads", id);
20559
- }
20560
- function cursorSdkRunsNdjsonPath(threadId) {
20561
- return (0, import_node_path50.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
20562
- }
20563
- function cursorSdkRunsNdjsonSearchPaths(threadId) {
20564
- const scoped = cursorSdkRunsNdjsonPath(threadId);
20565
- const shared = cursorSdkRunsNdjsonPath(null);
20566
- if (!threadId || !sanitizeCursorStoreSegment(threadId) || scoped === shared) {
20567
- return [shared];
20568
- }
20569
- return [scoped, shared];
20570
- }
20571
- function sanitizeCursorStoreSegment(threadId) {
20572
- return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
20573
- }
20574
- var import_node_path50, CURSOR_SDK_STORE_DIR;
20575
- var init_cursor_store = __esm({
20576
- "src/agents/cursor-store.ts"() {
20577
- "use strict";
20578
- import_node_path50 = require("path");
20579
- init_paths();
20580
- CURSOR_SDK_STORE_DIR = "cursor-sdk-store";
20581
- }
20582
- });
20583
-
20584
20867
  // src/agents/cursor-recover.ts
20585
20868
  var cursor_recover_exports = {};
20586
20869
  __export(cursor_recover_exports, {
@@ -20790,6 +21073,7 @@ var init_orchestrator = __esm({
20790
21073
  init_conductor();
20791
21074
  init_setup_log();
20792
21075
  init_orphan_cleanup();
21076
+ init_history_cleanup();
20793
21077
  init_apply_into_main();
20794
21078
  init_clone_repo();
20795
21079
  init_message_parts();
@@ -20819,6 +21103,7 @@ var init_orchestrator = __esm({
20819
21103
  init_diff();
20820
21104
  init_discover();
20821
21105
  init_expand();
21106
+ init_consume_attachments();
20822
21107
  init_stage_files();
20823
21108
  init_context_compact();
20824
21109
  init_instructions();
@@ -20976,6 +21261,12 @@ var init_orchestrator = __esm({
20976
21261
  }
20977
21262
  } catch {
20978
21263
  }
21264
+ try {
21265
+ if (shouldRunHistoryCleanup()) {
21266
+ cleanupArchivedHistory();
21267
+ }
21268
+ } catch {
21269
+ }
20979
21270
  if (drainQueues) {
20980
21271
  this.adoptPersistedQueues();
20981
21272
  }
@@ -21323,6 +21614,11 @@ var init_orchestrator = __esm({
21323
21614
  const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
21324
21615
  shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
21325
21616
  const patch = { queue };
21617
+ if (current.attachments.length > 0) {
21618
+ const consumed = consumeComposerAttachments(current);
21619
+ patch.attachments = consumed.attachments;
21620
+ patch.pendingTurnAttachments = consumed.pendingTurnAttachments;
21621
+ }
21326
21622
  if (!inFlight) patch.status = "queued";
21327
21623
  const pid = current.agentPid;
21328
21624
  if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
@@ -21503,7 +21799,8 @@ var init_orchestrator = __esm({
21503
21799
  thread = this.requireThread(threadId);
21504
21800
  }
21505
21801
  const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
21506
- const sentAttachments = !autoContinue && thread.attachments.length > 0 ? [...thread.attachments] : void 0;
21802
+ const parked = takePendingTurnAttachments(thread);
21803
+ const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
21507
21804
  appendMessage(threadId, {
21508
21805
  role: "user",
21509
21806
  text: prompt,
@@ -21570,8 +21867,8 @@ var init_orchestrator = __esm({
21570
21867
  slackReplyContext,
21571
21868
  expandedPrompt
21572
21869
  ].filter(Boolean).join("\n\n");
21573
- if (!autoContinue && thread.attachments.length > 0) {
21574
- updateThread(threadId, { attachments: [] });
21870
+ if (!autoContinue && sentAttachments) {
21871
+ updateThread(threadId, { attachments: [], pendingTurnAttachments: [] });
21575
21872
  }
21576
21873
  const adapter = getAdapter(thread.agent);
21577
21874
  const resolved = await adapter.resolveSessionId(thread.worktreePath, thread.sessionId);
@@ -21677,8 +21974,9 @@ var init_orchestrator = __esm({
21677
21974
  isolateCodexPlugins: fresh.isolateCodexPlugins === true
21678
21975
  },
21679
21976
  (event) => {
21680
- this.emit({ type: "turn_output", threadId, event });
21681
- noteTurnLiveEvent(threadId, event);
21977
+ const paint = clipAgentEventForPaint(event);
21978
+ this.emit({ type: "turn_output", threadId, event: paint });
21979
+ noteTurnLiveEvent(threadId, paint);
21682
21980
  if (event.type === "session_id") {
21683
21981
  updateThread(threadId, { sessionId: event.data });
21684
21982
  }
@@ -21803,7 +22101,8 @@ var init_orchestrator = __esm({
21803
22101
  isolateCodexPlugins: isolateCodexPluginRetry || retryThread.isolateCodexPlugins === true
21804
22102
  },
21805
22103
  (event) => {
21806
- this.emit({ type: "turn_output", threadId, event });
22104
+ const paint = clipAgentEventForPaint(event);
22105
+ this.emit({ type: "turn_output", threadId, event: paint });
21807
22106
  if (event.type === "session_id") {
21808
22107
  updateThread(threadId, { sessionId: event.data });
21809
22108
  }
@@ -22296,6 +22595,20 @@ var init_orchestrator = __esm({
22296
22595
  repoPaths
22297
22596
  });
22298
22597
  }
22598
+ /** Bound Settings → History. After archive always; reconcile is interval-gated. */
22599
+ enforceHistoryRetention() {
22600
+ try {
22601
+ cleanupArchivedHistory();
22602
+ } catch {
22603
+ }
22604
+ }
22605
+ cleanupHistory(opts) {
22606
+ return cleanupArchivedHistory({
22607
+ dryRun: opts?.dryRun,
22608
+ purgeOlderThanDays: opts?.purgeOlderThanDays,
22609
+ force: opts?.force
22610
+ });
22611
+ }
22299
22612
  /**
22300
22613
  * Best-of-n / fanout: create N threads (one per agent) with the same prompt.
22301
22614
  */
@@ -22856,6 +23169,7 @@ var init_orchestrator = __esm({
22856
23169
  if (isGlobalThread(thread)) {
22857
23170
  const archived2 = setStatus(thread.id, "archived");
22858
23171
  this.emit({ type: "status_changed", threadId: archived2.id, status: "archived" });
23172
+ this.enforceHistoryRetention();
22859
23173
  return archived2;
22860
23174
  }
22861
23175
  const siblings = threadsSharingWorktree(thread.worktreePath).filter((t) => t.id !== thread.id);
@@ -22877,6 +23191,7 @@ var init_orchestrator = __esm({
22877
23191
  }
22878
23192
  const archived = setStatus(thread.id, "archived");
22879
23193
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
23194
+ this.enforceHistoryRetention();
22880
23195
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
22881
23196
  try {
22882
23197
  const { ensureWorkspace: ensureWorkspace2 } = await Promise.resolve().then(() => (init_workspaces2(), workspaces_exports));