@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
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {
4
4
  isOrchestratorThread
5
- } from "./chunk-QOJB5PC7.js";
5
+ } from "./chunk-PTOIWKDU.js";
6
6
  import {
7
7
  applyConnectedTeamToCli,
8
8
  brightsyMcpServerName,
@@ -20,7 +20,7 @@ import {
20
20
  mergeAgentGitAuthEnv,
21
21
  resolveAgentGitAuthEnv,
22
22
  resolveCodexGitWritableRoots
23
- } from "./chunk-N4A4NWFO.js";
23
+ } from "./chunk-42VGWRSE.js";
24
24
  import {
25
25
  enrichPathWithNpmGlobalBin,
26
26
  isConductorBundledCli,
@@ -30,6 +30,7 @@ import {
30
30
  } from "./chunk-FNQNJOHY.js";
31
31
  import {
32
32
  claudeChromeEnabled,
33
+ fromInclusiveInputUsage,
33
34
  isAbleTimeConnected,
34
35
  isElectronLikeCommand,
35
36
  isLinearConnected,
@@ -38,7 +39,7 @@ import {
38
39
  resolveClaudeExecutable,
39
40
  unwrapStrippedElectronLaunch,
40
41
  wrapElectronAsNodeLaunch
41
- } from "./chunk-4EGK47WV.js";
42
+ } from "./chunk-FUC3XFE2.js";
42
43
  import {
43
44
  appDataDir
44
45
  } from "./chunk-EQNRWDLN.js";
@@ -46,85 +47,6 @@ import {
46
47
  // src/agents/brightsy.ts
47
48
  import { existsSync } from "fs";
48
49
 
49
- // src/agents/usage.ts
50
- function sumOptional(a, b) {
51
- if (a == null && b == null) return void 0;
52
- return (a ?? 0) + (b ?? 0);
53
- }
54
- function fromInclusiveInputUsage(opts) {
55
- const totalInput = Number(opts.inputTokens) || 0;
56
- const outputTokens = Number(opts.outputTokens) || 0;
57
- const cached = Number(opts.cachedInputTokens) || 0;
58
- if (!totalInput && !outputTokens) return null;
59
- const cacheReadTokens = cached > 0 ? Math.min(cached, totalInput) : 0;
60
- return {
61
- inputTokens: Math.max(0, totalInput - cacheReadTokens),
62
- outputTokens,
63
- cacheReadTokens: cacheReadTokens || void 0
64
- };
65
- }
66
- function requestOccupancy(u) {
67
- return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
68
- }
69
- function mergeUsage(a, b) {
70
- return {
71
- inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
72
- outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
73
- cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
74
- cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
75
- costUsd: sumOptional(a?.costUsd, b.costUsd),
76
- lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
77
- };
78
- }
79
- function sumUsageList(list) {
80
- let acc = null;
81
- for (const u of list) {
82
- if (!u) continue;
83
- acc = mergeUsage(acc, {
84
- inputTokens: u.inputTokens,
85
- outputTokens: u.outputTokens,
86
- cacheReadTokens: u.cacheReadTokens,
87
- cacheWriteTokens: u.cacheWriteTokens,
88
- costUsd: u.costUsd
89
- });
90
- }
91
- if (!acc) return null;
92
- return {
93
- inputTokens: acc.inputTokens,
94
- outputTokens: acc.outputTokens,
95
- ...acc.cacheReadTokens != null ? { cacheReadTokens: acc.cacheReadTokens } : {},
96
- ...acc.cacheWriteTokens != null ? { cacheWriteTokens: acc.cacheWriteTokens } : {},
97
- ...acc.costUsd != null ? { costUsd: acc.costUsd } : {}
98
- };
99
- }
100
- function hasBilledTokens(u) {
101
- return Boolean(
102
- u.inputTokens || u.outputTokens || u.cacheReadTokens || u.cacheWriteTokens
103
- );
104
- }
105
- function applyTurnUsage(current, incoming, scope = "request") {
106
- if (scope === "turn") {
107
- if (!hasBilledTokens(incoming) && current && incoming.costUsd != null) {
108
- return { ...current, costUsd: incoming.costUsd };
109
- }
110
- return {
111
- ...incoming,
112
- costUsd: incoming.costUsd ?? current?.costUsd,
113
- lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
114
- };
115
- }
116
- const merged = mergeUsage(current, incoming);
117
- const occ = incoming.lastRequestTokens != null && incoming.lastRequestTokens > 0 ? incoming.lastRequestTokens : requestOccupancy(incoming);
118
- return {
119
- ...merged,
120
- lastRequestTokens: occ > 0 ? occ : current?.lastRequestTokens ?? occ
121
- };
122
- }
123
- function contextTokens(u) {
124
- if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
125
- return requestOccupancy(u);
126
- }
127
-
128
50
  // src/agents/brightsy-targets.ts
129
51
  function encodeBrightsyTarget(type, id, accountId) {
130
52
  if (accountId) return `team:${accountId}:${type}:${id}`;
@@ -1161,6 +1083,30 @@ function clipThinkingForStore(text, max = THINKING_PART_MAX_CHARS) {
1161
1083
  const marker = "\u2026(earlier thinking trimmed)\n";
1162
1084
  return marker + text.slice(text.length - Math.max(1, max - marker.length));
1163
1085
  }
1086
+ var STDOUT_EVENT_MAX_CHARS = 16e3;
1087
+ var STDERR_EVENT_MAX_CHARS = 4e3;
1088
+ function clipEventTail(text, max) {
1089
+ if (text.length <= max) return text;
1090
+ const marker = "\u2026(truncated)\n";
1091
+ return marker + text.slice(text.length - Math.max(1, max - marker.length));
1092
+ }
1093
+ function clipAgentEventForPaint(event) {
1094
+ if (event.type === "tool_result" && event.content) {
1095
+ const content = clipToolResultForStore(event.content);
1096
+ if (content === event.content) return event;
1097
+ return { ...event, content };
1098
+ }
1099
+ if (event.type === "thinking" && event.data.length > THINKING_PART_MAX_CHARS) {
1100
+ return { ...event, data: clipThinkingForStore(event.data) };
1101
+ }
1102
+ if (event.type === "stdout" && event.data.length > STDOUT_EVENT_MAX_CHARS) {
1103
+ return { ...event, data: clipEventTail(event.data, STDOUT_EVENT_MAX_CHARS) };
1104
+ }
1105
+ if (event.type === "stderr" && event.data.length > STDERR_EVENT_MAX_CHARS) {
1106
+ return { ...event, data: clipEventTail(event.data, STDERR_EVENT_MAX_CHARS) };
1107
+ }
1108
+ return event;
1109
+ }
1164
1110
  function withPartTimes(next, prev) {
1165
1111
  const now = Date.now();
1166
1112
  const startedAt = prev && typeof prev.startedAt === "number" ? prev.startedAt : now;
@@ -2275,13 +2221,31 @@ function mcpStatusThinkingFromClaudeInit(obj) {
2275
2221
  }
2276
2222
  }
2277
2223
  }
2278
- const notable = servers.filter((s) => !isCleanMcpConnect(s.status));
2224
+ const notable = servers.filter(isNotableMcpInitStatus);
2279
2225
  if (notable.length === 0) return null;
2280
2226
  return `MCP: ${notable.map((s) => `${s.name} ${s.status}`).join(", ")}`;
2281
2227
  }
2282
2228
  function isCleanMcpConnect(status) {
2283
2229
  return /^(connected|ok|ready|success)$/i.test(status.trim());
2284
2230
  }
2231
+ function isMcpAuthStatus(status) {
2232
+ return /needs[_-]?auth|needs authentication|unauthorized|not authenticated|authrequired/i.test(
2233
+ status
2234
+ );
2235
+ }
2236
+ function isSideboardMcpName(name) {
2237
+ return /^sideboard$/i.test(name.trim()) || /^mcp__sideboard$/i.test(name.trim());
2238
+ }
2239
+ function isVendorClaudeAiMcpName(name) {
2240
+ return /^claude\.ai\b/i.test(name.trim()) || /^mcp__claude_ai_/i.test(name.trim());
2241
+ }
2242
+ function isNotableMcpInitStatus(server) {
2243
+ if (isCleanMcpConnect(server.status)) return false;
2244
+ if (isSideboardMcpName(server.name)) return true;
2245
+ if (isVendorClaudeAiMcpName(server.name)) return false;
2246
+ if (isMcpAuthStatus(server.status)) return false;
2247
+ return true;
2248
+ }
2285
2249
  function eventsFromClaudeSystem(obj) {
2286
2250
  const subtype = claudeString(obj, "subtype") ?? "";
2287
2251
  const parentId = claudeParentToolUseId(obj);
@@ -2450,7 +2414,7 @@ var claudeAdapter = {
2450
2414
  );
2451
2415
  }
2452
2416
  const mode = permissionMode(thread);
2453
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-I2X6UQMX.js");
2417
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-H2ANUSGR.js");
2454
2418
  const isOrchestrator = isOrchestratorThread2(thread);
2455
2419
  const injectedServers = await buildInjectedMcpServers({
2456
2420
  includeSideboard: true,
@@ -4785,9 +4749,6 @@ export {
4785
4749
  shouldFeedErrorBackToAgent,
4786
4750
  formatAgentErrorContinuePrompt,
4787
4751
  formatTurnExitError,
4788
- sumUsageList,
4789
- applyTurnUsage,
4790
- contextTokens,
4791
4752
  encodeBrightsyTarget,
4792
4753
  decodeBrightsyTarget,
4793
4754
  parseBrightsyCliLine,
@@ -4798,6 +4759,7 @@ export {
4798
4759
  isInternalAgentStatusText,
4799
4760
  isPollWrapperToolName,
4800
4761
  liveActivitySummary,
4762
+ clipAgentEventForPaint,
4801
4763
  applyAgentEvent,
4802
4764
  partsToAssistantText,
4803
4765
  stripBrightsyNdjsonNoise,
@@ -8,8 +8,7 @@ import {
8
8
  adjustBrightsyTurnExit,
9
9
  allAdapters,
10
10
  applyAgentEvent,
11
- applyTurnUsage,
12
- contextTokens,
11
+ clipAgentEventForPaint,
13
12
  finalizeParts,
14
13
  getAdapter,
15
14
  isBrightsyNdjsonLine,
@@ -24,9 +23,8 @@ import {
24
23
  partsToAssistantText,
25
24
  resolveQuotaFallbackAgent,
26
25
  stripBrightsyNdjsonNoise,
27
- sumUsageList,
28
26
  toolDescription
29
- } from "./chunk-A2BRWIEM.js";
27
+ } from "./chunk-KJAHVQL6.js";
30
28
  import {
31
29
  SLACK_REPLY_FORMATTING,
32
30
  addWorkspace,
@@ -49,7 +47,7 @@ import {
49
47
  stageAbsolutePathsAsAttachments,
50
48
  stageBuffersAsAttachments,
51
49
  syncWorkspacesFromThreads
52
- } from "./chunk-PAQPT3JO.js";
50
+ } from "./chunk-TZCWNRMC.js";
53
51
  import {
54
52
  addPrStackLayer,
55
53
  allocateTeamName,
@@ -99,7 +97,7 @@ import {
99
97
  worktreeDisplayLabelForGroup,
100
98
  worktreeNameFromPath,
101
99
  worktreeSlugForTicket
102
- } from "./chunk-6KH4OBEW.js";
100
+ } from "./chunk-22A45QOI.js";
103
101
  import {
104
102
  ATTACHMENTS_DIR,
105
103
  DETACHED_JOBS_DIR,
@@ -133,19 +131,28 @@ import {
133
131
  turnFailChatText
134
132
  } from "./chunk-JZHRZ3DR.js";
135
133
  import {
134
+ HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT,
135
+ applyTurnUsage,
136
136
  assertOrchestratorCapableAgent,
137
+ autoCleanupHistoryEnabled,
137
138
  childEnvWithAppSettings,
138
139
  coerceOrchestratorAgent,
140
+ contextTokens,
139
141
  followUpBehavior,
140
142
  formatViewerContextDirective,
141
143
  formatViewerContextReminder,
142
144
  getIssueSource,
145
+ historyMaxCount,
146
+ historyMaxDays,
147
+ historyRetentionStubMessage,
143
148
  isAbleTimeConnected,
144
149
  isLinearConnected,
145
150
  isOrchestratorCapableAgent,
146
151
  isSecureFileEncrypted,
147
152
  loadAppSettings,
148
153
  orchestrationQuotaFallbackAgent,
154
+ planHistoryAgePurge,
155
+ planHistoryRetention,
149
156
  readSecureJson,
150
157
  resolveEffectiveIssueSource,
151
158
  resolveNewThreadOptions,
@@ -153,10 +160,11 @@ import {
153
160
  resolveVaultKey,
154
161
  resolveViewerProfileForRepo,
155
162
  saveAppSettings,
163
+ sumUsageList,
156
164
  updateAdvancedSettings,
157
165
  usageOnLimit,
158
166
  writeSecureJson
159
- } from "./chunk-Y4CF7LHH.js";
167
+ } from "./chunk-VJQDUD24.js";
160
168
  import {
161
169
  stripNestedElectronEnv
162
170
  } from "./chunk-4TR3HZFT.js";
@@ -181,7 +189,7 @@ import {
181
189
  updateThread,
182
190
  withThreadLock,
183
191
  writeThread
184
- } from "./chunk-ARR4OGLY.js";
192
+ } from "./chunk-OY7THBLG.js";
185
193
  import {
186
194
  appDataDir,
187
195
  findConventionSetup,
@@ -475,7 +483,7 @@ async function continueSourceThread(threadId, prompt) {
475
483
  await continueOnReply(threadId, prompt);
476
484
  return;
477
485
  }
478
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-CXQY5YRG.js");
486
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-N7LLTK5O.js");
479
487
  await getOrchestrator2().send(threadId, prompt);
480
488
  } catch {
481
489
  }
@@ -809,9 +817,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
809
817
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
810
818
  );
811
819
  }
812
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-VS6HZF2I.js");
820
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-JEKMVE42.js");
813
821
  if (isGlobalThread2(thread)) {
814
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-6A3D7BV3.js");
822
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-EO2X2EYW.js");
815
823
  ensureGlobalCoordinatorCwd2(
816
824
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
817
825
  );
@@ -2591,6 +2599,69 @@ function worktreeCleanupSettings() {
2591
2599
  };
2592
2600
  }
2593
2601
 
2602
+ // src/store/history-cleanup.ts
2603
+ function stripArchivedTranscript(thread) {
2604
+ writeThread(
2605
+ {
2606
+ ...thread,
2607
+ attachments: [],
2608
+ pendingTurnAttachments: [],
2609
+ messages: [historyRetentionStubMessage(thread)]
2610
+ },
2611
+ { touch: false }
2612
+ );
2613
+ }
2614
+ function cleanupArchivedHistory(opts = {}) {
2615
+ const settings = loadAppSettings();
2616
+ if (!opts.force && opts.purgeOlderThanDays == null && !autoCleanupHistoryEnabled(settings)) {
2617
+ return { stripped: [], purged: [] };
2618
+ }
2619
+ const archived = listThreads({ includeArchived: true }).filter((t) => t.status === "archived");
2620
+ const nowMs = opts.nowMs ?? Date.now();
2621
+ const plan = opts.purgeOlderThanDays != null ? { stripIds: [], purgeIds: planHistoryAgePurge(archived, opts.purgeOlderThanDays, nowMs) } : planHistoryRetention(archived, {
2622
+ maxCount: opts.maxCount ?? historyMaxCount(settings),
2623
+ maxDays: opts.maxDays ?? historyMaxDays(settings),
2624
+ nowMs
2625
+ });
2626
+ const stripped = [];
2627
+ const purged = [];
2628
+ if (opts.dryRun) {
2629
+ return { stripped: plan.stripIds, purged: plan.purgeIds };
2630
+ }
2631
+ for (const id of plan.stripIds) {
2632
+ const thread = readThread(id);
2633
+ if (!thread || thread.status !== "archived") continue;
2634
+ try {
2635
+ stripArchivedTranscript(thread);
2636
+ stripped.push(id);
2637
+ } catch {
2638
+ }
2639
+ }
2640
+ for (const id of plan.purgeIds) {
2641
+ const thread = readThread(id);
2642
+ if (!thread || thread.status !== "archived") continue;
2643
+ try {
2644
+ deleteThreadRecord(id);
2645
+ purged.push(id);
2646
+ } catch {
2647
+ }
2648
+ }
2649
+ if (stripped.length > 0 || purged.length > 0) {
2650
+ updateAdvancedSettings({
2651
+ historyLastCleanupAt: new Date(nowMs).toISOString()
2652
+ });
2653
+ }
2654
+ return { stripped, purged };
2655
+ }
2656
+ function shouldRunHistoryCleanup(settings = loadAppSettings()) {
2657
+ if (!autoCleanupHistoryEnabled(settings)) return false;
2658
+ const intervalHours = settings.advanced.historyCleanupIntervalHours ?? HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT;
2659
+ const last = settings.advanced.historyLastCleanupAt;
2660
+ if (!last) return true;
2661
+ const elapsed = Date.now() - Date.parse(last);
2662
+ return Number.isFinite(elapsed) && elapsed >= intervalHours * 36e5;
2663
+ }
2664
+
2594
2665
  // src/git/apply-into-main.ts
2595
2666
  import { execa as execa3 } from "execa";
2596
2667
  async function applyThreadIntoMain(thread, opts) {
@@ -3807,7 +3878,7 @@ async function createThread(input, _onSetupLine) {
3807
3878
  });
3808
3879
  await requireAgent(resolved.agent);
3809
3880
  if (input.cowboy) {
3810
- const { cowboyModeEnabled } = await import("./app-settings-GJ6KDYEF.js");
3881
+ const { cowboyModeEnabled } = await import("./app-settings-VBQHGX5Z.js");
3811
3882
  if (!cowboyModeEnabled()) {
3812
3883
  throw new Error(
3813
3884
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -3865,7 +3936,7 @@ async function createThread(input, _onSetupLine) {
3865
3936
  let sourceIsFork = false;
3866
3937
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
3867
3938
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
3868
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-I4IYZBKU.js");
3939
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-G3MWSZVM.js");
3869
3940
  const task = await ensureAbleTimeTask({
3870
3941
  title: title?.trim() || "Untitled work",
3871
3942
  description: input.prompt?.trim() || void 0
@@ -3967,7 +4038,7 @@ async function createThread(input, _onSetupLine) {
3967
4038
  return readThread(thread.id) ?? thread;
3968
4039
  }
3969
4040
  async function listLinearIssues(agent, repoPath) {
3970
- const { getAdapter: getAdapter2 } = await import("./agents-KCBCFMFW.js");
4041
+ const { getAdapter: getAdapter2 } = await import("./agents-U2NVCYGC.js");
3971
4042
  await requireAgent(agent, { requireLinear: true });
3972
4043
  const adapter = getAdapter2(agent);
3973
4044
  if (!adapter.listLinearIssues) {
@@ -4413,7 +4484,7 @@ async function adoptThread(input) {
4413
4484
  messages: input.messages ?? []
4414
4485
  });
4415
4486
  writeThread(thread);
4416
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-7PM7UGLG.js");
4487
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-SVDORZEI.js");
4417
4488
  await ensureWorkspace2(repoPath);
4418
4489
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
4419
4490
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -6171,6 +6242,28 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
6171
6242
  };
6172
6243
  }
6173
6244
 
6245
+ // src/composer/consume-attachments.ts
6246
+ function consumeComposerAttachments(thread) {
6247
+ if (thread.attachments.length === 0) {
6248
+ return {
6249
+ attachments: [],
6250
+ pendingTurnAttachments: thread.pendingTurnAttachments ?? []
6251
+ };
6252
+ }
6253
+ return {
6254
+ attachments: [],
6255
+ pendingTurnAttachments: [
6256
+ ...thread.pendingTurnAttachments ?? [],
6257
+ ...thread.attachments
6258
+ ]
6259
+ };
6260
+ }
6261
+ function takePendingTurnAttachments(thread) {
6262
+ const pending = thread.pendingTurnAttachments ?? [];
6263
+ if (pending.length === 0 && thread.attachments.length === 0) return [];
6264
+ return [...pending, ...thread.attachments];
6265
+ }
6266
+
6174
6267
  // src/agents/instructions.ts
6175
6268
  import { existsSync as existsSync17 } from "fs";
6176
6269
  import { join as join16 } from "path";
@@ -6997,7 +7090,7 @@ function formatScheduledPrompt(name, prompt) {
6997
7090
  ${prompt}`;
6998
7091
  }
6999
7092
  async function defaultDeps() {
7000
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-CXQY5YRG.js");
7093
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-N7LLTK5O.js");
7001
7094
  const orch = getOrchestrator2();
7002
7095
  return {
7003
7096
  findThread: (id) => findThreadByRef(id),
@@ -7267,12 +7360,18 @@ var Orchestrator = class {
7267
7360
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
7268
7361
  });
7269
7362
  }
7270
- const { autoCleanupOrphansEnabled } = await import("./app-settings-GJ6KDYEF.js");
7363
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-VBQHGX5Z.js");
7271
7364
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
7272
7365
  await cleanupOrphanWorktrees({ repoPaths });
7273
7366
  }
7274
7367
  } catch {
7275
7368
  }
7369
+ try {
7370
+ if (shouldRunHistoryCleanup()) {
7371
+ cleanupArchivedHistory();
7372
+ }
7373
+ } catch {
7374
+ }
7276
7375
  if (drainQueues) {
7277
7376
  this.adoptPersistedQueues();
7278
7377
  }
@@ -7559,7 +7658,7 @@ var Orchestrator = class {
7559
7658
  }
7560
7659
  await setup;
7561
7660
  if (skipSetup) return;
7562
- const { autoRunAfterSetupEnabled } = await import("./app-settings-GJ6KDYEF.js");
7661
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-VBQHGX5Z.js");
7563
7662
  if (autoRunAfterSetupEnabled()) {
7564
7663
  try {
7565
7664
  await this.startDev(threadId);
@@ -7620,6 +7719,11 @@ var Orchestrator = class {
7620
7719
  const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
7621
7720
  shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
7622
7721
  const patch = { queue };
7722
+ if (current.attachments.length > 0) {
7723
+ const consumed = consumeComposerAttachments(current);
7724
+ patch.attachments = consumed.attachments;
7725
+ patch.pendingTurnAttachments = consumed.pendingTurnAttachments;
7726
+ }
7623
7727
  if (!inFlight) patch.status = "queued";
7624
7728
  const pid = current.agentPid;
7625
7729
  if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
@@ -7800,7 +7904,8 @@ var Orchestrator = class {
7800
7904
  thread = this.requireThread(threadId);
7801
7905
  }
7802
7906
  const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
7803
- const sentAttachments = !autoContinue && thread.attachments.length > 0 ? [...thread.attachments] : void 0;
7907
+ const parked = takePendingTurnAttachments(thread);
7908
+ const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
7804
7909
  appendMessage(threadId, {
7805
7910
  role: "user",
7806
7911
  text: prompt,
@@ -7867,8 +7972,8 @@ var Orchestrator = class {
7867
7972
  slackReplyContext,
7868
7973
  expandedPrompt
7869
7974
  ].filter(Boolean).join("\n\n");
7870
- if (!autoContinue && thread.attachments.length > 0) {
7871
- updateThread(threadId, { attachments: [] });
7975
+ if (!autoContinue && sentAttachments) {
7976
+ updateThread(threadId, { attachments: [], pendingTurnAttachments: [] });
7872
7977
  }
7873
7978
  const adapter = getAdapter(thread.agent);
7874
7979
  const resolved = await adapter.resolveSessionId(thread.worktreePath, thread.sessionId);
@@ -7883,7 +7988,7 @@ var Orchestrator = class {
7883
7988
  }
7884
7989
  const isBrightsy = fresh.agent === "brightsy";
7885
7990
  const isOrchestration = isOrchestratorThread(fresh);
7886
- const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-GJ6KDYEF.js");
7991
+ const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-VBQHGX5Z.js");
7887
7992
  const gitAuthMode = getGithubGitAuthMode();
7888
7993
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
7889
7994
  githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
@@ -7974,8 +8079,9 @@ var Orchestrator = class {
7974
8079
  isolateCodexPlugins: fresh.isolateCodexPlugins === true
7975
8080
  },
7976
8081
  (event) => {
7977
- this.emit({ type: "turn_output", threadId, event });
7978
- noteTurnLiveEvent(threadId, event);
8082
+ const paint = clipAgentEventForPaint(event);
8083
+ this.emit({ type: "turn_output", threadId, event: paint });
8084
+ noteTurnLiveEvent(threadId, paint);
7979
8085
  if (event.type === "session_id") {
7980
8086
  updateThread(threadId, { sessionId: event.data });
7981
8087
  }
@@ -8100,7 +8206,8 @@ var Orchestrator = class {
8100
8206
  isolateCodexPlugins: isolateCodexPluginRetry || retryThread.isolateCodexPlugins === true
8101
8207
  },
8102
8208
  (event) => {
8103
- this.emit({ type: "turn_output", threadId, event });
8209
+ const paint = clipAgentEventForPaint(event);
8210
+ this.emit({ type: "turn_output", threadId, event: paint });
8104
8211
  if (event.type === "session_id") {
8105
8212
  updateThread(threadId, { sessionId: event.data });
8106
8213
  }
@@ -8593,6 +8700,20 @@ var Orchestrator = class {
8593
8700
  repoPaths
8594
8701
  });
8595
8702
  }
8703
+ /** Bound Settings → History. After archive always; reconcile is interval-gated. */
8704
+ enforceHistoryRetention() {
8705
+ try {
8706
+ cleanupArchivedHistory();
8707
+ } catch {
8708
+ }
8709
+ }
8710
+ cleanupHistory(opts) {
8711
+ return cleanupArchivedHistory({
8712
+ dryRun: opts?.dryRun,
8713
+ purgeOlderThanDays: opts?.purgeOlderThanDays,
8714
+ force: opts?.force
8715
+ });
8716
+ }
8596
8717
  /**
8597
8718
  * Best-of-n / fanout: create N threads (one per agent) with the same prompt.
8598
8719
  */
@@ -8899,7 +9020,7 @@ var Orchestrator = class {
8899
9020
  if (!titled.userSetTitle && meta.title && titled.title !== meta.title) {
8900
9021
  updateThread(thread.id, { title: meta.title });
8901
9022
  }
8902
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-GJ6KDYEF.js");
9023
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-VBQHGX5Z.js");
8903
9024
  const latest = this.requireThread(thread.id);
8904
9025
  if (!shouldAutoArchiveOnPrMerge({
8905
9026
  previousPrState: prevState || null,
@@ -9153,6 +9274,7 @@ var Orchestrator = class {
9153
9274
  if (isGlobalThread(thread)) {
9154
9275
  const archived2 = setStatus(thread.id, "archived");
9155
9276
  this.emit({ type: "status_changed", threadId: archived2.id, status: "archived" });
9277
+ this.enforceHistoryRetention();
9156
9278
  return archived2;
9157
9279
  }
9158
9280
  const siblings = threadsSharingWorktree(thread.worktreePath).filter((t) => t.id !== thread.id);
@@ -9174,9 +9296,10 @@ var Orchestrator = class {
9174
9296
  }
9175
9297
  const archived = setStatus(thread.id, "archived");
9176
9298
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
9299
+ this.enforceHistoryRetention();
9177
9300
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
9178
9301
  try {
9179
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-7PM7UGLG.js");
9302
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-SVDORZEI.js");
9180
9303
  await ensureWorkspace2(thread.repoPath);
9181
9304
  } catch {
9182
9305
  }
@@ -9203,7 +9326,7 @@ var Orchestrator = class {
9203
9326
  await runArchiveScript(thread.repoPath, thread.worktreePath);
9204
9327
  } catch {
9205
9328
  }
9206
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-GJ6KDYEF.js");
9329
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-VBQHGX5Z.js");
9207
9330
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
9208
9331
  await removeWorktree(thread.repoPath, thread.worktreePath, {
9209
9332
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -9230,7 +9353,7 @@ var Orchestrator = class {
9230
9353
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
9231
9354
  );
9232
9355
  }
9233
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-T6PCOIHZ.js");
9356
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-YQ6XUSR2.js");
9234
9357
  const slug = thread.worktreePath.split("/").pop();
9235
9358
  const dest = thread.worktreePath;
9236
9359
  await withRepoGitLock(thread.repoPath, async () => {
@@ -9340,7 +9463,7 @@ async function startOrchestration(opts) {
9340
9463
  sourceRef: "default",
9341
9464
  ...createOpts
9342
9465
  }).catch(async () => {
9343
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-T6PCOIHZ.js");
9466
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-YQ6XUSR2.js");
9344
9467
  const repo = await resolveRepoRoot2(repoPath);
9345
9468
  const def = await resolveDefaultBranch2(repo);
9346
9469
  return orch.createThread({
@@ -9350,7 +9473,7 @@ async function startOrchestration(opts) {
9350
9473
  repoPath: repo
9351
9474
  });
9352
9475
  });
9353
- const { updateThread: upd } = await import("./thread-store-XGYWXR2P.js");
9476
+ const { updateThread: upd } = await import("./thread-store-55X2JYDT.js");
9354
9477
  const updated = upd(thread.id, {
9355
9478
  sourceType: "orchestration",
9356
9479
  sourceRef: goal
@@ -9509,6 +9632,8 @@ export {
9509
9632
  cleanupOrphanWorktrees,
9510
9633
  shouldRunWorktreeCleanup,
9511
9634
  worktreeCleanupSettings,
9635
+ cleanupArchivedHistory,
9636
+ shouldRunHistoryCleanup,
9512
9637
  applyThreadIntoMain,
9513
9638
  cloneRepoIntoSideboard,
9514
9639
  mcpWaitForTurnTimeoutMs,
@@ -9563,6 +9688,8 @@ export {
9563
9688
  discoverSkills,
9564
9689
  readSkillBody,
9565
9690
  expandComposerPrompt,
9691
+ consumeComposerAttachments,
9692
+ takePendingTurnAttachments,
9566
9693
  packagedDetachedJobPath,
9567
9694
  resolveDetachedJobScript,
9568
9695
  formatDetachedJobInvoke,