@wrongstack/core 0.119.1 → 0.148.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/{agent-bridge-PRAbEX-9.d.ts → agent-bridge-r9y6gdn4.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-DXWImnNV.d.ts → agent-subagent-runner-1GeQE_L0.d.ts} +7 -7
  3. package/dist/{brain-NZZqL8sn.d.ts → brain-Cp_3GIS2.d.ts} +14 -3
  4. package/dist/{compactor-C3stu664.d.ts → compactor-BueGt7LG.d.ts} +9 -1
  5. package/dist/{config-DZV9VK9n.d.ts → config-BaVThgnT.d.ts} +1 -1
  6. package/dist/{context-hvXINa6a.d.ts → context-C7G_MtLV.d.ts} +7 -0
  7. package/dist/coordination/index.d.ts +12 -12
  8. package/dist/coordination/index.js +35 -21
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +24 -24
  11. package/dist/defaults/index.js +869 -788
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +14 -14
  14. package/dist/execution/index.js +454 -321
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/extension/index.d.ts +6 -6
  17. package/dist/{goal-preamble-COpt55W8.d.ts → goal-preamble-CYJLg0wk.d.ts} +55 -17
  18. package/dist/{index-Cj3le7TI.d.ts → index-BZdezm3g.d.ts} +8 -8
  19. package/dist/{index-4VVHuTZF.d.ts → index-CPweVoFM.d.ts} +5 -5
  20. package/dist/index.d.ts +48 -48
  21. package/dist/index.js +612 -513
  22. package/dist/index.js.map +1 -1
  23. package/dist/infrastructure/index.d.ts +6 -6
  24. package/dist/infrastructure/index.js +64 -19
  25. package/dist/infrastructure/index.js.map +1 -1
  26. package/dist/kernel/index.d.ts +9 -9
  27. package/dist/kernel/index.js.map +1 -1
  28. package/dist/{llm-selector-Bmx4PsVM.d.ts → llm-selector-CP72f1lC.d.ts} +2 -2
  29. package/dist/{mcp-servers-CofNHOqn.d.ts → mcp-servers-Bl5LTvQg.d.ts} +3 -3
  30. package/dist/models/index.d.ts +5 -5
  31. package/dist/models/index.js +53 -20
  32. package/dist/models/index.js.map +1 -1
  33. package/dist/{models-registry-BzlsjKcy.d.ts → models-registry-D90K9UnM.d.ts} +1 -1
  34. package/dist/{multi-agent-coordinator-CmDmUgq2.d.ts → multi-agent-coordinator-QWEzJDlm.d.ts} +1 -1
  35. package/dist/{null-fleet-bus-CyH2YqP4.d.ts → null-fleet-bus-BUyfqh23.d.ts} +13 -10
  36. package/dist/observability/index.d.ts +2 -2
  37. package/dist/{parallel-eternal-engine-uxVm4y4V.d.ts → parallel-eternal-engine-C75QuhAI.d.ts} +33 -11
  38. package/dist/{path-resolver-gfoGxpdd.d.ts → path-resolver-DRjQBkoO.d.ts} +3 -3
  39. package/dist/{permission-DhLrgA30.d.ts → permission-B7nKnEvQ.d.ts} +1 -1
  40. package/dist/{permission-policy-DGOvne7i.d.ts → permission-policy-8-6zBmfA.d.ts} +2 -13
  41. package/dist/{pipeline-CqF7uju2.d.ts → pipeline-BG7UgbDc.d.ts} +2 -2
  42. package/dist/{plan-templates-DoKhzenv.d.ts → plan-templates-CkKNPU3I.d.ts} +5 -5
  43. package/dist/{provider-runner-BPlI5sPZ.d.ts → provider-runner-BNpuIyOL.d.ts} +3 -3
  44. package/dist/{retry-policy-B4Q-FZgE.d.ts → retry-policy-rutAfVeR.d.ts} +1 -1
  45. package/dist/sdd/index.d.ts +8 -8
  46. package/dist/sdd/index.js +10 -1
  47. package/dist/sdd/index.js.map +1 -1
  48. package/dist/{secret-vault-B7GnL6o9.d.ts → secret-vault-BTcC_T5v.d.ts} +3 -2
  49. package/dist/security/index.d.ts +5 -7
  50. package/dist/security/index.js +5 -36
  51. package/dist/security/index.js.map +1 -1
  52. package/dist/{selector-BakeMnWR.d.ts → selector-4vDFZKt3.d.ts} +1 -1
  53. package/dist/{session-event-bridge-DE5Oekwx.d.ts → session-event-bridge-DWlvglC2.d.ts} +2 -2
  54. package/dist/{session-reader-DFC81-4p.d.ts → session-reader-BAtCxdaw.d.ts} +1 -1
  55. package/dist/storage/index.d.ts +13 -13
  56. package/dist/storage/index.js +100 -103
  57. package/dist/storage/index.js.map +1 -1
  58. package/dist/types/index.d.ts +18 -18
  59. package/dist/types/index.js +276 -103
  60. package/dist/types/index.js.map +1 -1
  61. package/dist/utils/index.d.ts +37 -13
  62. package/dist/utils/index.js +63 -35
  63. package/dist/utils/index.js.map +1 -1
  64. package/package.json +2 -2
  65. package/skills/tech-stack/SKILL.md +253 -97
package/dist/index.js CHANGED
@@ -1761,16 +1761,17 @@ function expectDefined(value, label) {
1761
1761
 
1762
1762
  // src/utils/token-estimate.ts
1763
1763
  var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
1764
- var _cal = {
1765
- ratio: 1,
1766
- // current calibration multiplier (actual / estimated)
1767
- count: 0,
1768
- // number of samples recorded
1769
- prevEst: 0,
1770
- // estimated tokens from the most recent estimateRequestTokens call
1771
- /** EWM α — higher = faster adaptation, more volatile */
1772
- alpha: 0.3
1773
- };
1764
+ var CAL_ALPHA = 0.3;
1765
+ var CALIBRATION_GLOBAL_KEY = "__global__";
1766
+ var _cals = /* @__PURE__ */ new Map();
1767
+ function calState(key) {
1768
+ let state = _cals.get(key);
1769
+ if (!state) {
1770
+ state = { ratio: 1, count: 0, prevEst: 0 };
1771
+ _cals.set(key, state);
1772
+ }
1773
+ return state;
1774
+ }
1774
1775
  var MIN_SAMPLES_FOR_CALIBRATION = 3;
1775
1776
  var ESTIMATE_CACHE = /* @__PURE__ */ new Map();
1776
1777
  var ESTIMATE_CACHE_MAX_SIZE = 1e4;
@@ -1803,10 +1804,25 @@ function estimateToolResultTokens(content) {
1803
1804
  function estimateTextTokens(text) {
1804
1805
  return RoughTokenEstimate(text);
1805
1806
  }
1807
+ function estimateMessageTokens(messages) {
1808
+ let total = 0;
1809
+ for (const m of messages) {
1810
+ if (typeof m.content === "string") {
1811
+ total += estimateTextTokens(m.content);
1812
+ } else {
1813
+ for (const b of m.content) {
1814
+ if (b.type === "text") total += estimateTextTokens(b.text);
1815
+ else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
1816
+ else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
1817
+ }
1818
+ }
1819
+ }
1820
+ return total;
1821
+ }
1806
1822
  function estimateToolDefTokens(tool) {
1807
1823
  return RoughTokenEstimate(tool.name) + RoughTokenEstimate(tool.description ?? "") + RoughTokenEstimate(JSON.stringify(tool.inputSchema));
1808
1824
  }
1809
- function estimateRequestTokens(messages, systemPrompt, tools) {
1825
+ function estimateRequestTokens(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
1810
1826
  let messagesTokens = 0;
1811
1827
  if (typeof messages === "string") {
1812
1828
  messagesTokens = RoughTokenEstimate(messages);
@@ -1845,7 +1861,7 @@ function estimateRequestTokens(messages, systemPrompt, tools) {
1845
1861
  toolsTokens += estimateToolDefTokens(t2);
1846
1862
  }
1847
1863
  const total = messagesTokens + systemTokens + toolsTokens;
1848
- _cal.prevEst = total;
1864
+ calState(calibrationKey).prevEst = total;
1849
1865
  return {
1850
1866
  messages: messagesTokens,
1851
1867
  systemPrompt: systemTokens,
@@ -1853,30 +1869,33 @@ function estimateRequestTokens(messages, systemPrompt, tools) {
1853
1869
  total
1854
1870
  };
1855
1871
  }
1856
- function recordActualUsage(actualInputTokens, estimatedInputTokens) {
1872
+ function recordActualUsage(actualInputTokens, estimatedInputTokens, calibrationKey = CALIBRATION_GLOBAL_KEY) {
1857
1873
  if (actualInputTokens <= 0) return;
1858
- const est = estimatedInputTokens ?? _cal.prevEst;
1874
+ const cal = calState(calibrationKey);
1875
+ const est = estimatedInputTokens ?? cal.prevEst;
1859
1876
  if (est <= 0) return;
1860
1877
  const sampleRatio = actualInputTokens / est;
1861
- if (_cal.count === 0) {
1862
- _cal.ratio = sampleRatio;
1878
+ if (cal.count === 0) {
1879
+ cal.ratio = sampleRatio;
1863
1880
  } else {
1864
- _cal.ratio = _cal.alpha * sampleRatio + (1 - _cal.alpha) * _cal.ratio;
1881
+ cal.ratio = CAL_ALPHA * sampleRatio + (1 - CAL_ALPHA) * cal.ratio;
1865
1882
  }
1866
- _cal.ratio = Math.min(1.5, Math.max(0.5, _cal.ratio));
1867
- _cal.count++;
1883
+ cal.ratio = Math.min(1.5, Math.max(0.5, cal.ratio));
1884
+ cal.count++;
1868
1885
  }
1869
- function getCalibrationState() {
1886
+ function getCalibrationState(calibrationKey = CALIBRATION_GLOBAL_KEY) {
1887
+ const cal = calState(calibrationKey);
1870
1888
  return {
1871
- ratio: _cal.ratio,
1872
- count: _cal.count,
1873
- calibrated: _cal.count >= MIN_SAMPLES_FOR_CALIBRATION
1889
+ ratio: cal.ratio,
1890
+ count: cal.count,
1891
+ calibrated: cal.count >= MIN_SAMPLES_FOR_CALIBRATION
1874
1892
  };
1875
1893
  }
1876
- function estimateRequestTokensCalibrated(messages, systemPrompt, tools) {
1877
- const result = estimateRequestTokens(messages, systemPrompt, tools);
1878
- if (_cal.count >= MIN_SAMPLES_FOR_CALIBRATION) {
1879
- const safeRatio = Math.min(1.5, Math.max(0.5, _cal.ratio));
1894
+ function estimateRequestTokensCalibrated(messages, systemPrompt, tools, calibrationKey = CALIBRATION_GLOBAL_KEY) {
1895
+ const result = estimateRequestTokens(messages, systemPrompt, tools, calibrationKey);
1896
+ const cal = calState(calibrationKey);
1897
+ if (cal.count >= MIN_SAMPLES_FOR_CALIBRATION) {
1898
+ const safeRatio = Math.min(1.5, Math.max(0.5, cal.ratio));
1880
1899
  return {
1881
1900
  messages: Math.round(result.messages * safeRatio),
1882
1901
  systemPrompt: Math.round(result.systemPrompt * safeRatio),
@@ -1886,10 +1905,12 @@ function estimateRequestTokensCalibrated(messages, systemPrompt, tools) {
1886
1905
  }
1887
1906
  return result;
1888
1907
  }
1889
- function resetCalibration() {
1890
- _cal.ratio = 1;
1891
- _cal.count = 0;
1892
- _cal.prevEst = 0;
1908
+ function resetCalibration(calibrationKey) {
1909
+ if (calibrationKey === void 0) {
1910
+ _cals.clear();
1911
+ return;
1912
+ }
1913
+ _cals.delete(calibrationKey);
1893
1914
  }
1894
1915
 
1895
1916
  // src/utils/message-invariants.ts
@@ -1984,34 +2005,267 @@ function isEmptyMessage(msg) {
1984
2005
  return msg.content.length === 0;
1985
2006
  }
1986
2007
 
2008
+ // src/execution/compaction-core.ts
2009
+ var estimateMessages = estimateMessageTokens;
2010
+ function hasTextContent(m) {
2011
+ if (typeof m.content === "string") return m.content.trim().length > 0;
2012
+ return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
2013
+ }
2014
+ function findPreserveStart(messages, preserveK) {
2015
+ let pairCount = 0;
2016
+ let preserveStart = messages.length;
2017
+ for (let i = messages.length - 1; i >= 0 && pairCount < preserveK; i--) {
2018
+ const m = messages[i];
2019
+ if (!m) continue;
2020
+ if (m.role === "user" || m.role === "assistant") {
2021
+ pairCount++;
2022
+ preserveStart = i;
2023
+ }
2024
+ }
2025
+ for (let i = preserveStart; i < messages.length; i++) {
2026
+ const m = messages[i];
2027
+ if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
2028
+ const hasToolUse3 = m.content.some((b) => b.type === "tool_use");
2029
+ if (hasToolUse3 && i + 1 < messages.length) {
2030
+ const next = messages[i + 1];
2031
+ if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
2032
+ preserveStart = i + 1;
2033
+ }
2034
+ }
2035
+ }
2036
+ return preserveStart;
2037
+ }
2038
+ function eliseOldToolResults(messages, opts) {
2039
+ const preserveStart = findPreserveStart(messages, opts.preserveK);
2040
+ let saved = 0;
2041
+ let changed = false;
2042
+ const next = new Array(messages.length);
2043
+ for (let i = 0; i < messages.length; i++) {
2044
+ const msg = messages[i];
2045
+ if (i >= preserveStart || !msg || !Array.isArray(msg.content)) {
2046
+ next[i] = msg;
2047
+ continue;
2048
+ }
2049
+ const original = msg.content;
2050
+ const newContent = original.map((b) => {
2051
+ if (b.type !== "tool_result") return b;
2052
+ const tokens = estimateToolResultTokens(b.content);
2053
+ if (tokens < opts.eliseThreshold) return b;
2054
+ saved += tokens;
2055
+ const elided = {
2056
+ type: "tool_result",
2057
+ tool_use_id: b.tool_use_id,
2058
+ content: `[elided: ~${tokens} tokens]`,
2059
+ is_error: b.is_error
2060
+ };
2061
+ return elided;
2062
+ });
2063
+ if (newContent.every((b, idx) => b === original[idx])) {
2064
+ next[i] = msg;
2065
+ } else {
2066
+ next[i] = { ...msg, content: newContent };
2067
+ changed = true;
2068
+ }
2069
+ }
2070
+ return { messages: changed ? next : messages, saved, changed };
2071
+ }
2072
+ function buildLosslessDigest(messages) {
2073
+ const lines = [];
2074
+ for (const m of messages) {
2075
+ let text;
2076
+ let omitted = 0;
2077
+ if (typeof m.content === "string") {
2078
+ text = m.content;
2079
+ } else {
2080
+ const parts = [];
2081
+ for (const b of m.content) {
2082
+ if (isTextBlock(b)) parts.push(b.text);
2083
+ else if (b.type === "tool_use" || b.type === "tool_result") omitted++;
2084
+ }
2085
+ text = parts.join(" ");
2086
+ }
2087
+ if (text.trim().length === 0 && omitted === 0) continue;
2088
+ const marker = omitted > 0 ? ` [${omitted} tool call(s) omitted \u2014 see session log]` : "";
2089
+ lines.push(`[${m.role}]: ${text}${marker}`);
2090
+ }
2091
+ return lines.join("\n");
2092
+ }
2093
+ function extractText(m) {
2094
+ if (typeof m.content === "string") return m.content;
2095
+ return m.content.filter(isTextBlock).map((b) => b.text).join(" ");
2096
+ }
2097
+ function hasToolUse2(m) {
2098
+ if (typeof m.content === "string") return false;
2099
+ return m.content.some((b) => b.type === "tool_use");
2100
+ }
2101
+ function hasLargeToolResult(m, threshold = 3e3) {
2102
+ if (typeof m.content === "string") return false;
2103
+ return m.content.some(
2104
+ (b) => b.type === "tool_result" && b.content && (typeof b.content === "string" ? b.content.length : JSON.stringify(b.content).length) > threshold
2105
+ );
2106
+ }
2107
+ function scoreMessage(m, context) {
2108
+ const text = extractText(m).toLowerCase();
2109
+ if (text.trim().length === 0 && (hasToolUse2(m) || typeof m.content !== "string")) {
2110
+ const hasResult = typeof m.content !== "string" && m.content.some((b) => b.type === "tool_result");
2111
+ if (hasToolUse2(m) || hasResult) return 0;
2112
+ }
2113
+ if (context?.failureCounts && m.role === "user" && hasToolUse2(m) === false) {
2114
+ const isFailure = /error|fail|exception|timeout|enonet|eacces|eperm|enoent|abort/i.test(text);
2115
+ if (isFailure) {
2116
+ const errKey = /(error|fail|exception|timeout|enonet|eacces|eperm|enoent|abort)/i.exec(text)?.[0]?.toLowerCase() ?? "error";
2117
+ const count = (context.failureCounts.get(errKey) ?? 0) + 1;
2118
+ context.failureCounts.set(errKey, count);
2119
+ if (count >= 5) return 0;
2120
+ if (count >= 3) return 1;
2121
+ }
2122
+ }
2123
+ if (m.role === "user") {
2124
+ if (/\b(wrong|no\b|stop\b|don'?t\b|actually|fix that|undo|revert|forget|ignore|skip)\b/i.test(
2125
+ text
2126
+ )) {
2127
+ return 5;
2128
+ }
2129
+ }
2130
+ if (/\b(error|exception|fatal|critical|crash|panic|abort|segfault|core dump|undefined is not|null pointer|typeerror|referenceerror|syntaxerror)\b/i.test(
2131
+ text
2132
+ )) {
2133
+ return 5;
2134
+ }
2135
+ if (/\b(security|vulnerability|injection|xss|csrf|secret|apikey|api.key|hardcoded|leak|exploit|cve)\b/i.test(
2136
+ text
2137
+ )) {
2138
+ return 5;
2139
+ }
2140
+ if (m.role === "assistant" && /\b(architecture|design|approach|strategy|pattern|refactor|migrate|restructure|decision|trade.?off)\b/i.test(
2141
+ text
2142
+ )) {
2143
+ return 5;
2144
+ }
2145
+ if (hasLargeToolResult(m)) return 1;
2146
+ if (m.role === "user" && !hasToolUse2(m) && /\b(files_with_matches|count|found \d+ match|directory tree|\.\.\. and \d+ more)\b/i.test(text)) {
2147
+ return 1;
2148
+ }
2149
+ return 3;
2150
+ }
2151
+ function buildSmartDigest(messages) {
2152
+ const lines = [];
2153
+ const failureCounts = /* @__PURE__ */ new Map();
2154
+ let noiseCount = 0;
2155
+ for (const m of messages) {
2156
+ const score = scoreMessage(m, { failureCounts });
2157
+ const text = extractText(m);
2158
+ const toolCount = countToolBlocks(m);
2159
+ if (score === 0) {
2160
+ noiseCount++;
2161
+ continue;
2162
+ }
2163
+ const marker = toolCount > 0 ? ` [${toolCount} tool call(s)]` : "";
2164
+ let display;
2165
+ switch (score) {
2166
+ case 5:
2167
+ display = text.trim();
2168
+ break;
2169
+ case 3:
2170
+ display = firstSentence(text);
2171
+ break;
2172
+ case 1:
2173
+ display = oneLineSummary(m, text);
2174
+ break;
2175
+ default:
2176
+ display = firstSentence(text);
2177
+ }
2178
+ if (display.length === 0 && toolCount === 0) continue;
2179
+ lines.push(`[${m.role}]: ${display}${marker}`);
2180
+ }
2181
+ if (noiseCount > 0) {
2182
+ lines.push(`[system]: ${noiseCount} low-importance turn(s) collapsed (repeated failures / pure tool I/O)`);
2183
+ }
2184
+ return lines.join("\n");
2185
+ }
2186
+ function countToolBlocks(m) {
2187
+ if (typeof m.content === "string") return 0;
2188
+ return m.content.filter(
2189
+ (b) => b.type === "tool_use" || b.type === "tool_result"
2190
+ ).length;
2191
+ }
2192
+ function firstSentence(text) {
2193
+ const trimmed = text.trim();
2194
+ if (trimmed.length === 0) return "";
2195
+ const dot = trimmed.indexOf(". ");
2196
+ if (dot === -1) return trimmed.length > 150 ? `${trimmed.slice(0, 147)}\u2026` : trimmed;
2197
+ const sentence = trimmed.slice(0, dot + 1);
2198
+ return sentence.length > 150 ? `${sentence.slice(0, 147)}\u2026` : sentence;
2199
+ }
2200
+ function oneLineSummary(m, text) {
2201
+ const trimmed = text.trim();
2202
+ if (trimmed.length === 0) {
2203
+ if (typeof m.content !== "string") {
2204
+ const results = m.content.filter((b) => b.type === "tool_result");
2205
+ if (results.length > 0) {
2206
+ return `[${results.length} tool result(s) \u2014 see session log]`;
2207
+ }
2208
+ }
2209
+ return "[no text content]";
2210
+ }
2211
+ const firstLine = trimmed.split("\n")[0] ?? "";
2212
+ return firstLine.length > 100 ? `${firstLine.slice(0, 97)}\u2026` : firstLine;
2213
+ }
2214
+ function findSafeBoundary(messages, from, to) {
2215
+ for (let i = to; i >= from; i--) {
2216
+ const m = messages[i];
2217
+ if (!m) continue;
2218
+ if (m.role === "user" && hasTextContent(m)) {
2219
+ return findExchangeStart(messages, i);
2220
+ }
2221
+ }
2222
+ return -1;
2223
+ }
2224
+ function findExchangeStart(messages, userIndex) {
2225
+ for (let i = userIndex - 1; i >= 0; i--) {
2226
+ const m = messages[i];
2227
+ if (!m) continue;
2228
+ if (m.role === "assistant") {
2229
+ const hasToolUse3 = Array.isArray(m.content) ? m.content.some((b) => b.type === "tool_use") : false;
2230
+ if (!hasToolUse3) return i + 1;
2231
+ } else if (m.role === "user") {
2232
+ return i;
2233
+ }
2234
+ }
2235
+ return 0;
2236
+ }
2237
+
1987
2238
  // src/execution/compactor.ts
1988
2239
  var HybridCompactor = class {
1989
2240
  preserveK;
1990
2241
  eliseThreshold;
1991
- estimator;
2242
+ smart;
1992
2243
  constructor(opts = {}) {
1993
2244
  this.preserveK = opts.preserveK ?? 5;
1994
2245
  this.eliseThreshold = opts.eliseThreshold ?? 2e3;
1995
- this.estimator = opts.estimator ?? estimateTextTokens;
2246
+ this.smart = opts.smart ?? false;
1996
2247
  }
1997
2248
  async compact(ctx, opts = {}) {
1998
- const beforeTokens = this.estimateMessages(ctx.messages);
2249
+ const beforeTokens = estimateMessages(ctx.messages);
1999
2250
  const beforeFull = this.estimateFullRequest(ctx);
2000
2251
  const reductions = [];
2001
2252
  const policy = readContextWindowPolicy(ctx);
2002
2253
  const preserveK = policy?.preserveK ?? this.preserveK;
2003
2254
  const eliseThreshold = policy?.eliseThreshold ?? this.eliseThreshold;
2004
- const phase1Saved = this.eliseOldToolResults(ctx, preserveK, eliseThreshold);
2005
- if (phase1Saved > 0) reductions.push({ phase: "elision", saved: phase1Saved });
2255
+ const elide = eliseOldToolResults(ctx.messages, { preserveK, eliseThreshold });
2256
+ if (elide.changed) ctx.state.replaceMessages(elide.messages);
2257
+ if (elide.saved > 0) reductions.push({ phase: "elision", saved: elide.saved });
2258
+ let collapsedDigest;
2006
2259
  if (opts.aggressive) {
2007
- const phase2Saved = this.collapseAncientTurns(ctx, preserveK);
2008
- if (phase2Saved > 0) reductions.push({ phase: "summary", saved: phase2Saved });
2260
+ const phase2 = this.collapseAncientTurns(ctx, preserveK);
2261
+ if (phase2.saved > 0) reductions.push({ phase: "summary", saved: phase2.saved });
2262
+ collapsedDigest = phase2.digest;
2009
2263
  }
2010
2264
  const repaired = repairToolUseAdjacency(ctx.messages);
2011
2265
  if (repaired.report.changed) {
2012
2266
  ctx.state.replaceMessages(repaired.messages);
2013
2267
  }
2014
- const afterTokens = this.estimateMessages(ctx.messages);
2268
+ const afterTokens = estimateMessages(ctx.messages);
2015
2269
  const afterFull = this.estimateFullRequest(ctx);
2016
2270
  return {
2017
2271
  before: beforeTokens,
@@ -2019,6 +2273,7 @@ var HybridCompactor = class {
2019
2273
  fullRequestTokensBefore: beforeFull,
2020
2274
  fullRequestTokensAfter: afterFull,
2021
2275
  reductions,
2276
+ collapsedDigest,
2022
2277
  repaired: repaired.report.changed ? {
2023
2278
  removedToolUses: repaired.report.removedToolUses,
2024
2279
  removedToolResults: repaired.report.removedToolResults,
@@ -2031,72 +2286,23 @@ var HybridCompactor = class {
2031
2286
  * This is the accurate figure for context-window pressure monitoring.
2032
2287
  */
2033
2288
  estimateFullRequest(ctx) {
2034
- const breakdown = estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []);
2035
- return breakdown.total;
2036
- }
2037
- eliseOldToolResults(ctx, preserveK = this.preserveK, eliseThreshold = this.eliseThreshold) {
2038
- const messages = ctx.messages;
2039
- let pairCount = 0;
2040
- let preserveStart = messages.length;
2041
- for (let i = messages.length - 1; i >= 0 && pairCount < preserveK; i--) {
2042
- const m = messages[i];
2043
- if (!m) continue;
2044
- if (m.role === "user" || m.role === "assistant") {
2045
- pairCount++;
2046
- preserveStart = i;
2047
- }
2048
- }
2049
- for (let i = preserveStart; i < messages.length; i++) {
2050
- const m = messages[i];
2051
- if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
2052
- const hasToolUse2 = m.content.some((b) => b.type === "tool_use");
2053
- if (hasToolUse2 && i + 1 < messages.length) {
2054
- const next = messages[i + 1];
2055
- if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
2056
- preserveStart = i + 1;
2057
- }
2058
- }
2059
- }
2060
- let saved = 0;
2061
- let changed = false;
2062
- const nextMessages = new Array(messages.length);
2063
- for (let i = 0; i < messages.length; i++) {
2064
- const msg = messages[i];
2065
- if (i >= preserveStart) {
2066
- nextMessages[i] = msg;
2067
- continue;
2068
- }
2069
- if (!msg || !Array.isArray(msg.content)) {
2070
- nextMessages[i] = msg;
2071
- continue;
2072
- }
2073
- const newContent = msg.content.map((b) => {
2074
- if (b.type !== "tool_result") return b;
2075
- const tokens = estimateToolResultTokens(b.content);
2076
- if (tokens < eliseThreshold) return b;
2077
- saved += tokens;
2078
- const elided = {
2079
- type: "tool_result",
2080
- tool_use_id: b.tool_use_id,
2081
- content: `[elided: ~${tokens} tokens]`,
2082
- is_error: b.is_error
2083
- };
2084
- return elided;
2085
- });
2086
- if (newContent.length === msg.content.length && newContent.every((b, idx) => b === msg.content[idx])) {
2087
- nextMessages[i] = msg;
2088
- } else {
2089
- nextMessages[i] = { ...msg, content: newContent };
2090
- changed = true;
2091
- }
2092
- }
2093
- if (changed) ctx.state.replaceMessages(nextMessages);
2094
- return saved;
2289
+ return estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total;
2095
2290
  }
2291
+ /**
2292
+ * Lossless rule-based collapse of ancient turns into a single digest message.
2293
+ *
2294
+ * Preserves ALL textual content of the collapsed range — user instructions,
2295
+ * assistant decisions/conclusions, and any prior digests (chained forward so
2296
+ * the digest stays lossless across repeated compactions). Only `tool_use` /
2297
+ * `tool_result` protocol blocks are dropped and replaced with a count marker;
2298
+ * their full payload already lives in the session log. No sub-LLM call.
2299
+ *
2300
+ * Returns the token savings and the digest text (for audit logging).
2301
+ */
2096
2302
  collapseAncientTurns(ctx, preserveK = this.preserveK) {
2097
2303
  const messages = ctx.messages;
2098
2304
  const cutTarget = Math.max(0, messages.length - preserveK * 2);
2099
- if (cutTarget <= 0) return 0;
2305
+ if (cutTarget <= 0) return { saved: 0 };
2100
2306
  let boundary = -1;
2101
2307
  for (let i = cutTarget; i < messages.length; i++) {
2102
2308
  const m = messages[i];
@@ -2106,34 +2312,20 @@ var HybridCompactor = class {
2106
2312
  break;
2107
2313
  }
2108
2314
  }
2109
- if (boundary <= 0) return 0;
2315
+ if (boundary <= 0) return { saved: 0 };
2110
2316
  const removed = messages.slice(0, boundary);
2111
- const removedTokens = this.estimateMessages(removed);
2112
- const summary = [
2113
- {
2114
- role: "user",
2115
- content: `[previous_session_summary: ${removed.length} earlier turns compacted. Todo state preserved in context.]`
2116
- },
2117
- { role: "assistant", content: "Continuing from compacted context." }
2118
- ];
2317
+ const removedTokens = estimateMessages(removed);
2318
+ const digest = this.smart ? buildSmartDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)` : buildLosslessDigest(removed) || `${removed.length} earlier turns (no textual content; tool I/O omitted \u2014 see session log)`;
2319
+ const summaryMsg = {
2320
+ role: "system",
2321
+ content: `[prior_turns_digest: ${digest}]`
2322
+ };
2119
2323
  const tail = ctx.messages.slice(boundary);
2120
- ctx.state.replaceMessages([...summary, ...tail]);
2121
- return Math.max(0, removedTokens - this.estimateMessages(summary));
2122
- }
2123
- estimateMessages(messages) {
2124
- let total = 0;
2125
- for (const m of messages) {
2126
- if (typeof m.content === "string") {
2127
- total += this.estimator(m.content);
2128
- } else {
2129
- for (const b of m.content) {
2130
- if (b.type === "text") total += this.estimator(b.text);
2131
- else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
2132
- else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
2133
- }
2134
- }
2135
- }
2136
- return total;
2324
+ ctx.state.replaceMessages([summaryMsg, ...tail]);
2325
+ return {
2326
+ saved: Math.max(0, removedTokens - estimateMessages([summaryMsg])),
2327
+ digest
2328
+ };
2137
2329
  }
2138
2330
  };
2139
2331
  function readContextWindowPolicy(ctx) {
@@ -2145,10 +2337,6 @@ function readContextWindowPolicy(ctx) {
2145
2337
  }
2146
2338
  return candidate;
2147
2339
  }
2148
- function hasTextContent(m) {
2149
- if (typeof m.content === "string") return m.content.trim().length > 0;
2150
- return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
2151
- }
2152
2340
  var PROJECT_MARKERS = [
2153
2341
  ".git",
2154
2342
  "package.json",
@@ -3396,6 +3584,8 @@ function topologicalSort(graph) {
3396
3584
  var ToolCapabilities = {
3397
3585
  /** Can execute arbitrary commands in the user's shell (the `bash` tool). */
3398
3586
  SHELL_ARBITRARY: "shell.arbitrary",
3587
+ /** Can execute a restricted set of commands (the `exec` tool). */
3588
+ SHELL_RESTRICTED: "shell.restricted",
3399
3589
  /** Can write / modify / delete files inside the project. */
3400
3590
  FS_WRITE: "fs.write",
3401
3591
  /** Can write files outside the current project root (very high risk). */
@@ -3411,6 +3601,7 @@ var ToolCapabilities = {
3411
3601
  };
3412
3602
  var DANGEROUS_FOR_SUBAGENTS = [
3413
3603
  ToolCapabilities.SHELL_ARBITRARY,
3604
+ ToolCapabilities.SHELL_RESTRICTED,
3414
3605
  ToolCapabilities.FS_WRITE,
3415
3606
  ToolCapabilities.FS_WRITE_OUTSIDE_PROJECT,
3416
3607
  ToolCapabilities.MCP_PROXY,
@@ -3960,7 +4151,7 @@ ${excerpt}`;
3960
4151
  subjectFor(toolName, input, subjectKey) {
3961
4152
  if (!input || typeof input !== "object") return void 0;
3962
4153
  const obj = input;
3963
- const globChars = /[*?\[\]]/g;
4154
+ const globChars = /[*?[\]]/g;
3964
4155
  const escapeGlob = (s) => s.replace(globChars, (c) => `\\${c}`);
3965
4156
  const normalizePath = (s) => escapeGlob(s.replace(/\\/g, "/"));
3966
4157
  if (subjectKey) {
@@ -4922,8 +5113,8 @@ function looksSecret(name) {
4922
5113
  }
4923
5114
  function buildChildEnv(optsOrSessionId) {
4924
5115
  const opts = typeof optsOrSessionId === "string" ? { sessionId: optsOrSessionId } : optsOrSessionId ?? {};
4925
- const hasOwn = Object.prototype.hasOwnProperty.call(process.env, "WRONGSTACK_CHILD_ENV_PASSTHROUGH");
4926
- const legacyHasOwn = Object.prototype.hasOwnProperty.call(process.env, "WRONGSTACK_BASH_ENV_PASSTHROUGH");
5116
+ const hasOwn = Object.hasOwn(process.env, "WRONGSTACK_CHILD_ENV_PASSTHROUGH");
5117
+ const legacyHasOwn = Object.hasOwn(process.env, "WRONGSTACK_BASH_ENV_PASSTHROUGH");
4927
5118
  const passthrough = hasOwn && process.env["WRONGSTACK_CHILD_ENV_PASSTHROUGH"] === "1" || legacyHasOwn && process.env["WRONGSTACK_BASH_ENV_PASSTHROUGH"] === "1";
4928
5119
  if (passthrough && !process.env["CI"]) {
4929
5120
  console.warn(
@@ -4958,6 +5149,13 @@ function buildChildEnv(optsOrSessionId) {
4958
5149
  function sleep(ms) {
4959
5150
  return new Promise((resolve12) => setTimeout(resolve12, ms));
4960
5151
  }
5152
+
5153
+ // src/utils/assert-never.ts
5154
+ function assertNever(x, message) {
5155
+ throw new Error(
5156
+ message ?? `Unhandled case: ${JSON.stringify(x)}`
5157
+ );
5158
+ }
4961
5159
  var GLOB_CHARS = /* @__PURE__ */ new Set(["*", "?", "["]);
4962
5160
  var IS_WINDOWS = process.platform === "win32";
4963
5161
  var SEP = IS_WINDOWS ? "\\" : "/";
@@ -5020,14 +5218,14 @@ async function expandGlob(pattern) {
5020
5218
  const abs = isAbsolute(pattern);
5021
5219
  const base = abs ? baseDir(pattern) : baseDir(pattern);
5022
5220
  const relPat = base === "." ? pattern : pattern.slice(base.length + 1);
5023
- async function walk4(dir, pat) {
5221
+ async function walk3(dir, pat) {
5024
5222
  let entries;
5025
5223
  try {
5026
5224
  entries = await fsp3.readdir(dir);
5027
5225
  } catch {
5028
5226
  return;
5029
5227
  }
5030
- const firstGlob = pat.search(/[*?[\[]/);
5228
+ const firstGlob = pat.search(/[*?[[]/);
5031
5229
  if (firstGlob < 0) {
5032
5230
  const re = globToRegex(pat);
5033
5231
  for (const e of entries) {
@@ -5041,12 +5239,12 @@ async function expandGlob(pattern) {
5041
5239
  const before = pat.slice(0, firstGlob);
5042
5240
  const rest = pat.slice(firstGlob);
5043
5241
  if (before.endsWith("**")) {
5044
- await walk4(dir, rest);
5242
+ await walk3(dir, rest);
5045
5243
  for (const e of entries) {
5046
5244
  const full = `${dir}${SEP}${e}`;
5047
5245
  try {
5048
5246
  const stat11 = await fsp3.stat(full);
5049
- if (stat11.isDirectory()) await walk4(full, rest);
5247
+ if (stat11.isDirectory()) await walk3(full, rest);
5050
5248
  } catch {
5051
5249
  }
5052
5250
  }
@@ -5064,13 +5262,13 @@ async function expandGlob(pattern) {
5064
5262
  const full = `${dir}${SEP}${seg}`;
5065
5263
  try {
5066
5264
  const stat11 = await fsp3.stat(full);
5067
- if (stat11.isDirectory()) await walk4(full, rest);
5265
+ if (stat11.isDirectory()) await walk3(full, rest);
5068
5266
  } catch {
5069
5267
  }
5070
5268
  }
5071
5269
  }
5072
5270
  }
5073
- await walk4(base === "." ? "." : base, relPat);
5271
+ await walk3(base === "." ? "." : base, relPat);
5074
5272
  return [...results];
5075
5273
  }
5076
5274
 
@@ -5241,8 +5439,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
5241
5439
  onClose: (s) => this.appendToIndex(s)
5242
5440
  });
5243
5441
  } catch (err) {
5244
- await handle.close().catch(() => {
5245
- });
5442
+ await handle.close().catch((e) => console.warn(`[session-store] handle.close() failed: ${e}`));
5246
5443
  throw err;
5247
5444
  }
5248
5445
  }
@@ -5273,8 +5470,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
5273
5470
  );
5274
5471
  return { writer, data };
5275
5472
  } catch (err) {
5276
- await handle.close().catch(() => {
5277
- });
5473
+ await handle.close().catch((e) => console.warn(`[session-store] handle.close() failed: ${e}`));
5278
5474
  throw err;
5279
5475
  }
5280
5476
  }
@@ -5463,15 +5659,15 @@ var DefaultSessionStore = class _DefaultSessionStore {
5463
5659
  * sidecars, and the session directory (fleet.json, shared/, subagents/).
5464
5660
  */
5465
5661
  async deleteSession(id) {
5466
- await fsp3.unlink(this.sessionPath(id, ".jsonl")).catch(() => void 0);
5467
- await fsp3.unlink(this.sessionPath(id, ".summary.json")).catch(() => void 0);
5662
+ await fsp3.unlink(this.sessionPath(id, ".jsonl")).catch((err) => console.warn(`[session-store] delete .jsonl failed: ${err}`));
5663
+ await fsp3.unlink(this.sessionPath(id, ".summary.json")).catch((err) => console.warn(`[session-store] delete .summary.json failed: ${err}`));
5468
5664
  const shardDir = path6.dirname(path6.join(this.dir, id));
5469
5665
  const base = path6.basename(id);
5470
5666
  for (const ext of [".plan.json", ".todos.json"]) {
5471
- await fsp3.unlink(path6.join(shardDir, `${base}${ext}`)).catch(() => void 0);
5667
+ await fsp3.unlink(path6.join(shardDir, `${base}${ext}`)).catch((err) => console.warn(`[session-store] delete ${ext} failed: ${err}`));
5472
5668
  }
5473
5669
  const sessDir = path6.join(shardDir, base);
5474
- await fsp3.rm(sessDir, { recursive: true, force: true }).catch(() => void 0);
5670
+ await fsp3.rm(sessDir, { recursive: true, force: true }).catch((err) => console.warn(`[session-store] delete session dir failed: ${err}`));
5475
5671
  await this.writeTombstone(id);
5476
5672
  }
5477
5673
  async delete(id) {
@@ -5548,7 +5744,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
5548
5744
  let toolErrorCount = 0;
5549
5745
  let fileChangeCount = 0;
5550
5746
  const toolBreakdown = {};
5551
- let outcome = void 0;
5747
+ let outcome;
5552
5748
  const lastEvent = data.events[data.events.length - 1];
5553
5749
  for (const e of data.events) {
5554
5750
  if (e.type === "in_flight_start") iterationCount++;
@@ -6761,48 +6957,6 @@ function deepFreeze(obj) {
6761
6957
  }
6762
6958
  return Object.freeze(obj);
6763
6959
  }
6764
-
6765
- // src/security/config-secrets.ts
6766
- function decryptConfigSecrets2(cfg, vault) {
6767
- return walk3(cfg, vault, (v, key) => {
6768
- try {
6769
- return vault.decrypt(v);
6770
- } catch (err) {
6771
- console.warn(
6772
- `[secret-vault] Failed to decrypt "${key}":`,
6773
- err instanceof Error ? err.message : err
6774
- );
6775
- return "";
6776
- }
6777
- });
6778
- }
6779
- function walk3(node, vault, transform) {
6780
- if (node === null || node === void 0) return node;
6781
- if (typeof node !== "object") return node;
6782
- if (Array.isArray(node)) {
6783
- return node.map((item) => walk3(item, vault, transform));
6784
- }
6785
- const out = /* @__PURE__ */ Object.create(null);
6786
- for (const [k, v] of Object.entries(node)) {
6787
- if (typeof v === "string" && isSecretField2(k)) {
6788
- out[k] = transform(v, k);
6789
- } else if (typeof v === "object" && v !== null) {
6790
- out[k] = walk3(v, vault, transform);
6791
- } else {
6792
- out[k] = v;
6793
- }
6794
- }
6795
- return out;
6796
- }
6797
- var SECRET_KEY_PATTERN2 = /(?:apikey|api_key|authtoken|auth_token|bearer|secret|password|passwd|pwd|refreshtoken|refresh_token|sessionkey|session_key|access[_-]?token|private[_-]?key)/i;
6798
- var NON_SECRET_OVERRIDES2 = /* @__PURE__ */ new Set(["publickey", "public_key"]);
6799
- function isSecretField2(name) {
6800
- const lc = name.toLowerCase();
6801
- if (NON_SECRET_OVERRIDES2.has(lc)) return false;
6802
- return SECRET_KEY_PATTERN2.test(lc);
6803
- }
6804
-
6805
- // src/storage/config-loader.ts
6806
6960
  init_atomic_write();
6807
6961
  var BEHAVIOR_DEFAULTS = {
6808
6962
  version: 1,
@@ -6972,7 +7126,7 @@ var DefaultConfigLoader = class {
6972
7126
  cfg = deepMerge2(cfg, opts.cliFlags);
6973
7127
  }
6974
7128
  if (this.vault) {
6975
- cfg = decryptConfigSecrets2(cfg, this.vault);
7129
+ cfg = decryptConfigSecrets(cfg, this.vault);
6976
7130
  }
6977
7131
  if (cfg.providers) {
6978
7132
  for (const pcfg of Object.values(cfg.providers)) {
@@ -7022,7 +7176,7 @@ var DefaultConfigLoader = class {
7022
7176
  const parsed = safeParse(raw);
7023
7177
  if (!parsed.ok || !parsed.value) return null;
7024
7178
  if (this.vault) {
7025
- const decrypted = decryptConfigSecrets2({ sync: parsed.value }, this.vault);
7179
+ const decrypted = decryptConfigSecrets({ sync: parsed.value }, this.vault);
7026
7180
  return decrypted.sync ?? null;
7027
7181
  }
7028
7182
  return parsed.value;
@@ -8274,7 +8428,7 @@ var DefaultPermissionPolicy = class {
8274
8428
  subjectFor(toolName, input, subjectKey) {
8275
8429
  if (!input || typeof input !== "object") return void 0;
8276
8430
  const obj = input;
8277
- const globChars = /[*?\[\]]/g;
8431
+ const globChars = /[*?[\]]/g;
8278
8432
  const escapeGlob = (s) => s.replace(globChars, (c) => `\\${c}`);
8279
8433
  const normalizePath = (s) => escapeGlob(s.replace(/\\/g, "/"));
8280
8434
  if (subjectKey) {
@@ -8305,38 +8459,15 @@ var DefaultPermissionPolicy = class {
8305
8459
  }
8306
8460
  };
8307
8461
  var AutoApprovePermissionPolicy = class _AutoApprovePermissionPolicy {
8308
- /**
8309
- * Legacy name-based denylist.
8310
- * @deprecated Prefer declaring `capabilities` on the Tool and using capability-based checks.
8311
- */
8312
- static LEGACY_NAME_DENY = /* @__PURE__ */ new Set([
8313
- "bash",
8314
- "write",
8315
- "edit",
8316
- "replace",
8317
- "scaffold",
8318
- "patch",
8319
- "install",
8320
- "exec"
8321
- ]);
8322
- // Note: hasDangerousCapabilityForSubagents is now the shared helper from capabilities.ts
8323
- // The old private method was removed in favor of the centralized utility.
8324
- /**
8325
- * Tools from MCP servers (`mcp__<server>__<tool>`) are external code of
8326
- * unknown capability — they may wrap a shell or filesystem. They are
8327
- * fail-closed here: not auto-approved for subagents by default, so the
8328
- * leader must allow them explicitly per-spawn.
8329
- */
8330
8462
  static isMcpTool(name) {
8331
8463
  return name.startsWith("mcp__");
8332
8464
  }
8333
8465
  async evaluate(tool) {
8334
8466
  const hasDangerousCap = hasDangerousCapabilityForSubagents(tool);
8335
- const legacyNameBlock = _AutoApprovePermissionPolicy.LEGACY_NAME_DENY.has(tool.name);
8336
8467
  const isMcp = _AutoApprovePermissionPolicy.isMcpTool(tool.name);
8337
- const blocked = tool.permission === "deny" || hasDangerousCap || legacyNameBlock || isMcp;
8468
+ const blocked = tool.permission === "deny" || hasDangerousCap || isMcp;
8338
8469
  if (blocked) {
8339
- const reason = hasDangerousCap ? `tool declares dangerous capability (${tool.capabilities?.join(", ")}) \u2014 not auto-approved for subagents` : legacyNameBlock || isMcp ? `tool ${tool.name} is not auto-approved for subagents \u2014 ask the leader to allow it explicitly` : "tool default deny";
8470
+ const reason = hasDangerousCap ? `tool declares dangerous capability (${tool.capabilities?.join(", ")}) \u2014 not auto-approved for subagents` : isMcp ? `MCP tool ${tool.name} is not auto-approved for subagents \u2014 ask the leader to allow it explicitly` : "tool default deny";
8340
8471
  return {
8341
8472
  permission: "deny",
8342
8473
  source: "subagent_guard",
@@ -8638,53 +8769,63 @@ async function streamProviderToResponse(provider, req, signal, ctx, events) {
8638
8769
  const next = await iter.next();
8639
8770
  if (next.done) break;
8640
8771
  const ev = next.value;
8641
- switch (ev.type) {
8642
- case "message_start":
8643
- handleMessageStart(state, ev.model);
8644
- break;
8645
- case "content_block_start":
8646
- handleContentBlockStart(state, ev);
8647
- break;
8648
- case "content_block_stop":
8649
- handleContentBlockStop(state, ev);
8650
- break;
8651
- case "text_delta":
8652
- handleTextDelta(state, ev.text);
8653
- events.emit("provider.text_delta", { ctx, text: ev.text });
8654
- break;
8655
- case "tool_use_start": {
8656
- const idVal = ev.id;
8657
- const nameVal = ev.name;
8658
- handleToolUseStart(state, { id: idVal, name: nameVal });
8659
- const emittedPayload = { ctx, id: idVal ?? "unknown", name: nameVal ?? "unknown" };
8660
- events.emit("provider.tool_use_start", emittedPayload);
8661
- break;
8662
- }
8663
- case "tool_use_input_delta":
8664
- handleToolUseInputDelta(state, ev);
8665
- break;
8666
- case "tool_use_stop": {
8667
- const stoppedName = state.tools.get(ev.id)?.name ?? "unknown";
8668
- handleToolUseStop(state, ev);
8669
- events.emit("provider.tool_use_stop", { ctx, id: ev.id, name: stoppedName });
8670
- break;
8772
+ try {
8773
+ switch (ev.type) {
8774
+ case "message_start":
8775
+ handleMessageStart(state, ev.model);
8776
+ break;
8777
+ case "content_block_start":
8778
+ handleContentBlockStart(state, ev);
8779
+ break;
8780
+ case "content_block_stop":
8781
+ handleContentBlockStop(state, ev);
8782
+ break;
8783
+ case "text_delta":
8784
+ handleTextDelta(state, ev.text);
8785
+ events.emit("provider.text_delta", { ctx, text: ev.text });
8786
+ break;
8787
+ case "tool_use_start": {
8788
+ const idVal = ev.id;
8789
+ const nameVal = ev.name;
8790
+ handleToolUseStart(state, { id: idVal, name: nameVal });
8791
+ const emittedPayload = { ctx, id: idVal ?? "unknown", name: nameVal ?? "unknown" };
8792
+ events.emit("provider.tool_use_start", emittedPayload);
8793
+ break;
8794
+ }
8795
+ case "tool_use_input_delta":
8796
+ handleToolUseInputDelta(state, ev);
8797
+ break;
8798
+ case "tool_use_stop": {
8799
+ const stoppedName = state.tools.get(ev.id)?.name ?? "unknown";
8800
+ handleToolUseStop(state, ev);
8801
+ events.emit("provider.tool_use_stop", { ctx, id: ev.id, name: stoppedName });
8802
+ break;
8803
+ }
8804
+ case "thinking_start":
8805
+ handleThinkingStart(state, ev);
8806
+ break;
8807
+ case "thinking_delta":
8808
+ handleThinkingDelta(state, ev.text);
8809
+ events.emit("provider.thinking_delta", { ctx, text: ev.text });
8810
+ break;
8811
+ case "thinking_signature":
8812
+ handleThinkingSignature(state, ev.signature);
8813
+ break;
8814
+ case "thinking_stop":
8815
+ handleThinkingStop(state);
8816
+ break;
8817
+ case "message_stop":
8818
+ handleMessageStop(state, ev);
8819
+ break;
8820
+ default:
8821
+ break;
8671
8822
  }
8672
- case "thinking_start":
8673
- handleThinkingStart(state, ev);
8674
- break;
8675
- case "thinking_delta":
8676
- handleThinkingDelta(state, ev.text);
8677
- events.emit("provider.thinking_delta", { ctx, text: ev.text });
8678
- break;
8679
- case "thinking_signature":
8680
- handleThinkingSignature(state, ev.signature);
8681
- break;
8682
- case "thinking_stop":
8683
- handleThinkingStop(state);
8684
- break;
8685
- case "message_stop":
8686
- handleMessageStop(state, ev);
8687
- break;
8823
+ } catch (handlerErr) {
8824
+ events.emit("provider.stream_error", {
8825
+ ctx,
8826
+ eventType: ev.type,
8827
+ msg: handlerErr instanceof Error ? handlerErr.message : String(handlerErr)
8828
+ });
8688
8829
  }
8689
8830
  }
8690
8831
  } catch (err) {
@@ -8697,8 +8838,10 @@ async function streamProviderToResponse(provider, req, signal, ctx, events) {
8697
8838
  try {
8698
8839
  let drainTimer = null;
8699
8840
  try {
8841
+ const drainPromise = Promise.resolve(iter.return?.()).catch(() => {
8842
+ });
8700
8843
  await Promise.race([
8701
- Promise.resolve(iter.return?.()),
8844
+ drainPromise,
8702
8845
  new Promise((resolve12) => {
8703
8846
  drainTimer = setTimeout(resolve12, STREAM_DRAIN_TIMEOUT_MS);
8704
8847
  })
@@ -8817,23 +8960,25 @@ var IntelligentCompactor = class {
8817
8960
  this.summarizerModel = opts.summarizerModel;
8818
8961
  }
8819
8962
  async compact(ctx, opts = {}) {
8820
- const beforeTokens = this.estimateTokens(ctx.messages);
8963
+ const beforeTokens = estimateMessages(ctx.messages);
8821
8964
  const beforeFull = this.estimateFullRequest(ctx);
8822
8965
  const reductions = [];
8823
8966
  const load = beforeFull / this.maxContext;
8824
8967
  const aggressive = load >= this.hardThreshold ? true : opts.aggressive ?? load >= this.softThreshold;
8825
- const saved1 = this.eliseOldToolResults(ctx);
8968
+ const saved1 = this.elide(ctx);
8826
8969
  if (saved1 > 0) reductions.push({ phase: "elision", saved: saved1 });
8970
+ let collapsedDigest;
8827
8971
  if (aggressive) {
8828
- const saved2 = await this.summarizeAncientTurns(ctx);
8829
- if (saved2 > 0) reductions.push({ phase: "summary", saved: saved2 });
8972
+ const phase2 = await this.summarizeAncientTurns(ctx);
8973
+ if (phase2.saved > 0) reductions.push({ phase: "summary", saved: phase2.saved });
8974
+ collapsedDigest = phase2.digest;
8830
8975
  } else if (load >= this.warnThreshold) {
8831
- const saved2 = this.lightweightCompact(ctx);
8976
+ const saved2 = this.elide(ctx);
8832
8977
  if (saved2 > 0) reductions.push({ phase: "elision", saved: saved2 });
8833
8978
  }
8834
8979
  const repaired = repairToolUseAdjacency(ctx.messages);
8835
8980
  if (repaired.report.changed) ctx.state.replaceMessages(repaired.messages);
8836
- const afterTokens = this.estimateTokens(ctx.messages);
8981
+ const afterTokens = estimateMessages(ctx.messages);
8837
8982
  const afterFull = this.estimateFullRequest(ctx);
8838
8983
  return {
8839
8984
  before: beforeTokens,
@@ -8841,6 +8986,7 @@ var IntelligentCompactor = class {
8841
8986
  fullRequestTokensBefore: beforeFull,
8842
8987
  fullRequestTokensAfter: afterFull,
8843
8988
  reductions,
8989
+ collapsedDigest,
8844
8990
  repaired: repaired.report.changed ? {
8845
8991
  removedToolUses: repaired.report.removedToolUses,
8846
8992
  removedToolResults: repaired.report.removedToolResults,
@@ -8853,75 +8999,39 @@ var IntelligentCompactor = class {
8853
8999
  * This is the accurate figure for context-window pressure monitoring.
8854
9000
  */
8855
9001
  estimateFullRequest(ctx) {
8856
- const breakdown = estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []);
8857
- return breakdown.total;
9002
+ return estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total;
9003
+ }
9004
+ /** Run shared tool-result elision and commit through ConversationState. */
9005
+ elide(ctx) {
9006
+ const result = eliseOldToolResults(ctx.messages, {
9007
+ preserveK: this.preserveK,
9008
+ eliseThreshold: this.eliseThreshold
9009
+ });
9010
+ if (result.changed) ctx.state.replaceMessages(result.messages);
9011
+ return result.saved;
8858
9012
  }
8859
9013
  async summarizeAncientTurns(ctx) {
8860
9014
  const messages = ctx.messages;
8861
9015
  const cutoff = Math.max(0, messages.length - this.preserveK * 2);
8862
- if (cutoff <= 2) return 0;
8863
- const boundary = this.findSafeBoundary(messages, 0, cutoff);
8864
- if (boundary <= 1) return 0;
9016
+ if (cutoff <= 2) return { saved: 0 };
9017
+ const boundary = findSafeBoundary(messages, 0, cutoff);
9018
+ if (boundary <= 1) return { saved: 0 };
8865
9019
  const toSummarize = messages.slice(0, boundary);
8866
- const removedTokens = this.estimateTokens(toSummarize);
9020
+ const removedTokens = estimateMessages(toSummarize);
8867
9021
  let summaryText;
8868
9022
  try {
8869
9023
  summaryText = await this.callSummarizer(toSummarize, ctx);
8870
9024
  } catch {
8871
- const preservedMessages = [];
8872
- for (const m of toSummarize) {
8873
- if (m.role === "system") continue;
8874
- if (typeof m.content === "string") {
8875
- preservedMessages.push(m);
8876
- } else if (Array.isArray(m.content)) {
8877
- const textParts = m.content.filter(isTextBlock);
8878
- const toolParts = m.content.filter((b) => b.type === "tool_use" || b.type === "tool_result");
8879
- const next = {
8880
- role: m.role,
8881
- content: [
8882
- ...textParts,
8883
- ...toolParts.length > 0 ? [{ type: "text", text: `[${toolParts.length} tool call(s) omitted]` }] : []
8884
- ]
8885
- };
8886
- preservedMessages.push(next);
8887
- }
8888
- }
8889
- summaryText = preservedMessages.map((m) => `[${m.role}]: ${typeof m.content === "string" ? m.content : m.content.filter(isTextBlock).map((b) => b.text).join(" ")}`).join("\n");
8890
- if (!summaryText) summaryText = `${toSummarize.length} earlier turns (semantic content preserved)`;
9025
+ summaryText = buildLosslessDigest(toSummarize) || `${toSummarize.length} earlier turns (semantic content preserved)`;
8891
9026
  }
8892
9027
  const summaryMsg = {
8893
9028
  role: "system",
8894
9029
  content: `[prior_turns_summary: ${summaryText}]`
8895
9030
  };
8896
- const summaryTokens = this.estimateTokens([summaryMsg]);
9031
+ const summaryTokens = estimateMessages([summaryMsg]);
8897
9032
  const tail = ctx.messages.slice(boundary);
8898
9033
  ctx.state.replaceMessages([summaryMsg, ...tail]);
8899
- return Math.max(0, removedTokens - summaryTokens);
8900
- }
8901
- findSafeBoundary(messages, from, to) {
8902
- for (let i = to; i >= from; i--) {
8903
- const m = messages[i];
8904
- if (!m) continue;
8905
- if (m.role === "user" && this.hasTextContent(m)) {
8906
- return this.findExchangeStart(messages, i);
8907
- }
8908
- }
8909
- return -1;
8910
- }
8911
- findExchangeStart(messages, userIndex) {
8912
- for (let i = userIndex - 1; i >= 0; i--) {
8913
- const m = messages[i];
8914
- if (!m) continue;
8915
- if (m.role === "assistant") {
8916
- const hasToolUse2 = Array.isArray(m.content) ? m.content.some((b) => b.type === "tool_use") : false;
8917
- if (!hasToolUse2) {
8918
- return i + 1;
8919
- }
8920
- } else if (m.role !== "user") ; else {
8921
- return i;
8922
- }
8923
- }
8924
- return 0;
9034
+ return { saved: Math.max(0, removedTokens - summaryTokens), digest: summaryText };
8925
9035
  }
8926
9036
  async callSummarizer(messages, ctx) {
8927
9037
  const prompt = [
@@ -8956,86 +9066,6 @@ var IntelligentCompactor = class {
8956
9066
  }
8957
9067
  return [{ type: "text", text: lines.join("\n") }];
8958
9068
  }
8959
- lightweightCompact(ctx) {
8960
- return this.eliseOldToolResults(ctx);
8961
- }
8962
- eliseOldToolResults(ctx) {
8963
- const messages = ctx.messages;
8964
- let pairCount = 0;
8965
- let preserveStart = messages.length;
8966
- for (let i = messages.length - 1; i >= 0 && pairCount < this.preserveK; i--) {
8967
- const m = messages[i];
8968
- if (!m) continue;
8969
- if (m.role === "user" || m.role === "assistant") {
8970
- pairCount++;
8971
- preserveStart = i;
8972
- }
8973
- }
8974
- for (let i = preserveStart; i < messages.length; i++) {
8975
- const m = messages[i];
8976
- if (!m || typeof m.content === "string" || !Array.isArray(m.content)) continue;
8977
- const hasToolUse2 = m.content.some((b) => b.type === "tool_use");
8978
- if (hasToolUse2 && i + 1 < messages.length) {
8979
- const next = messages[i + 1];
8980
- if (next && next.role === "user" && typeof next.content !== "string" && Array.isArray(next.content) && next.content.some((b) => b.type === "tool_result")) {
8981
- preserveStart = i + 1;
8982
- }
8983
- }
8984
- }
8985
- let saved = 0;
8986
- let changed = false;
8987
- const nextMessages = new Array(messages.length);
8988
- for (let i = 0; i < messages.length; i++) {
8989
- const msg = messages[i];
8990
- if (i >= preserveStart) {
8991
- nextMessages[i] = msg;
8992
- continue;
8993
- }
8994
- if (!msg || !Array.isArray(msg.content)) {
8995
- nextMessages[i] = msg;
8996
- continue;
8997
- }
8998
- const newContent = msg.content.map((b) => {
8999
- if (b.type !== "tool_result") return b;
9000
- const tokens = estimateToolResultTokens(b.content);
9001
- if (tokens < this.eliseThreshold) return b;
9002
- saved += tokens;
9003
- return {
9004
- type: "tool_result",
9005
- tool_use_id: b.tool_use_id,
9006
- content: `[elided: ~${tokens} tokens]`,
9007
- is_error: b.is_error
9008
- };
9009
- });
9010
- if (newContent.length === msg.content.length && newContent.every((b, idx) => b === msg.content[idx])) {
9011
- nextMessages[i] = msg;
9012
- } else {
9013
- nextMessages[i] = { ...msg, content: newContent };
9014
- changed = true;
9015
- }
9016
- }
9017
- if (changed) ctx.state.replaceMessages(nextMessages);
9018
- return saved;
9019
- }
9020
- hasTextContent(m) {
9021
- if (typeof m.content === "string") return m.content.trim().length > 0;
9022
- return m.content.some((b) => b.type === "text" && b.text.trim().length > 0);
9023
- }
9024
- estimateTokens(messages) {
9025
- let total = 0;
9026
- for (const m of messages) {
9027
- if (typeof m.content === "string") {
9028
- total += estimateTextTokens(m.content);
9029
- } else {
9030
- for (const b of m.content) {
9031
- if (b.type === "text") total += estimateTextTokens(b.text);
9032
- else if (b.type === "tool_use") total += estimateToolInputTokens(b.input);
9033
- else if (b.type === "tool_result") total += estimateToolResultTokens(b.content);
9034
- }
9035
- }
9036
- }
9037
- return total;
9038
- }
9039
9069
  };
9040
9070
 
9041
9071
  // src/models/llm-selector.ts
@@ -9061,20 +9091,6 @@ Rules:
9061
9091
  - If unsure, keep rather than collapse (errors are more costly than waste)
9062
9092
 
9063
9093
  Return ONLY the JSON object, no markdown, no explanation outside the JSON.`;
9064
- function estimateTokens(messages) {
9065
- let total = 0;
9066
- for (const m of messages) {
9067
- if (typeof m.content === "string") {
9068
- total += Math.ceil(m.content.length / 4);
9069
- } else if (Array.isArray(m.content)) {
9070
- for (const b of m.content) {
9071
- if (b.type === "text") total += Math.ceil(b.text.length / 4);
9072
- else total += Math.ceil(JSON.stringify(b).length / 4);
9073
- }
9074
- }
9075
- }
9076
- return total;
9077
- }
9078
9094
  function formatMessages(messages, maxChars = 8e3) {
9079
9095
  const lines = [];
9080
9096
  let used = 0;
@@ -9113,7 +9129,7 @@ var LLMSelector = class {
9113
9129
  async select(messages, maxToKeep) {
9114
9130
  const effectiveBudget = Math.min(maxToKeep, this.maxContextTokens);
9115
9131
  const historyText = formatMessages(messages);
9116
- const totalTokens = estimateTokens(messages);
9132
+ const totalTokens = estimateMessageTokens(messages);
9117
9133
  const systemText = `${this.systemPrompt}
9118
9134
 
9119
9135
  Conversation (${messages.length} messages, ~${totalTokens} tokens, budget: ${effectiveBudget}):
@@ -9145,10 +9161,7 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
9145
9161
  let startIdx = 0;
9146
9162
  for (let i = messages.length - 1; i >= 0; i--) {
9147
9163
  const m = expectDefined(messages[i]);
9148
- const cost = typeof m.content === "string" ? Math.ceil(m.content.length / 4) : m.content.reduce(
9149
- (acc, b) => acc + (b.type === "text" ? Math.ceil(b.text.length / 4) : Math.ceil(JSON.stringify(b).length / 4)),
9150
- 0
9151
- );
9164
+ const cost = estimateMessageTokens([m]);
9152
9165
  if (tokenCount + cost <= budget) {
9153
9166
  tokenCount += cost;
9154
9167
  } else {
@@ -9381,52 +9394,12 @@ Summarize the following message range:`;
9381
9394
  return Math.floor(this.maxContext * 0.75);
9382
9395
  }
9383
9396
  eliseOldToolResults(ctx) {
9384
- const messages = ctx.messages;
9385
- let pairCount = 0;
9386
- let preserveStart = messages.length;
9387
- for (let i = messages.length - 1; i >= 0 && pairCount < this.preserveK; i--) {
9388
- const m = messages[i];
9389
- if (!m) continue;
9390
- if (m.role === "user" || m.role === "assistant") {
9391
- pairCount++;
9392
- preserveStart = i;
9393
- }
9394
- }
9395
- let saved = 0;
9396
- let changed = false;
9397
- const nextMessages = new Array(messages.length);
9398
- for (let i = 0; i < messages.length; i++) {
9399
- const msg = messages[i];
9400
- if (i >= preserveStart) {
9401
- nextMessages[i] = msg;
9402
- continue;
9403
- }
9404
- if (!msg || !Array.isArray(msg.content)) {
9405
- nextMessages[i] = msg;
9406
- continue;
9407
- }
9408
- const newContent = msg.content.map((b) => {
9409
- if (b.type !== "tool_result") return b;
9410
- const text = typeof b.content === "string" ? b.content : JSON.stringify(b.content);
9411
- const tokens = this.roughTokenEstimate(text);
9412
- if (tokens < this.eliseThreshold) return b;
9413
- saved += tokens;
9414
- return {
9415
- type: "tool_result",
9416
- tool_use_id: b.tool_use_id,
9417
- content: `[elided: ~${tokens} tokens]`,
9418
- is_error: b.is_error
9419
- };
9420
- });
9421
- if (newContent.every((b, idx) => b === msg.content[idx])) {
9422
- nextMessages[i] = msg;
9423
- } else {
9424
- nextMessages[i] = { ...msg, content: newContent };
9425
- changed = true;
9426
- }
9427
- }
9428
- if (changed) ctx.state.replaceMessages(nextMessages);
9429
- return saved;
9397
+ const result = eliseOldToolResults(ctx.messages, {
9398
+ preserveK: this.preserveK,
9399
+ eliseThreshold: this.eliseThreshold
9400
+ });
9401
+ if (result.changed) ctx.state.replaceMessages(result.messages);
9402
+ return result.saved;
9430
9403
  }
9431
9404
  hasTextContent(m) {
9432
9405
  if (typeof m.content === "string") return m.content.trim().length > 0;
@@ -9456,8 +9429,81 @@ Summarize the following message range:`;
9456
9429
  }
9457
9430
  };
9458
9431
 
9432
+ // src/execution/strategy-compactor.ts
9433
+ function createStrategyCompactor(opts = {}) {
9434
+ const requested = opts.strategy ?? (opts.llmSelector ? "selective" : "hybrid");
9435
+ const strategy = requested;
9436
+ if (strategy === "intelligent" || strategy === "selective") {
9437
+ return new ProviderBackedCompactor(strategy, opts);
9438
+ }
9439
+ return new HybridCompactor({
9440
+ preserveK: opts.preserveK,
9441
+ eliseThreshold: opts.eliseThreshold,
9442
+ smart: opts.smart
9443
+ });
9444
+ }
9445
+ var ProviderBackedCompactor = class {
9446
+ constructor(strategy, opts) {
9447
+ this.strategy = strategy;
9448
+ this.opts = opts;
9449
+ }
9450
+ strategy;
9451
+ opts;
9452
+ async compact(ctx, compactOpts = {}) {
9453
+ return this.resolveInner(ctx).compact(ctx, compactOpts);
9454
+ }
9455
+ /**
9456
+ * Construct the concrete compactor for this run. Rebuilt per call (cheap, no
9457
+ * I/O) so a model switch — which changes `ctx.provider.capabilities.maxContext`
9458
+ * — is always reflected. Reads the active ContextWindowPolicy from `ctx.meta`
9459
+ * so the LLM compactors honor the same thresholds/preserveK as the policy.
9460
+ */
9461
+ resolveInner(ctx) {
9462
+ const provider = ctx.provider;
9463
+ if (!provider) {
9464
+ return new HybridCompactor({
9465
+ preserveK: this.opts.preserveK,
9466
+ eliseThreshold: this.opts.eliseThreshold
9467
+ });
9468
+ }
9469
+ const policy = readPolicy(ctx);
9470
+ const maxContext = provider.capabilities?.maxContext || void 0;
9471
+ const thresholds = policy?.thresholds;
9472
+ const common = {
9473
+ provider,
9474
+ maxContext,
9475
+ preserveK: this.opts.preserveK ?? policy?.preserveK,
9476
+ eliseThreshold: this.opts.eliseThreshold ?? policy?.eliseThreshold,
9477
+ ...thresholds ? { warnThreshold: thresholds.warn, softThreshold: thresholds.soft, hardThreshold: thresholds.hard } : {}
9478
+ };
9479
+ if (this.strategy === "selective") {
9480
+ return new SelectiveCompactor({
9481
+ ...common,
9482
+ selectorModel: this.opts.summarizerModel,
9483
+ summarizerModel: this.opts.summarizerModel
9484
+ });
9485
+ }
9486
+ return new IntelligentCompactor({
9487
+ ...common,
9488
+ summarizerModel: this.opts.summarizerModel
9489
+ });
9490
+ }
9491
+ };
9492
+ function readPolicy(ctx) {
9493
+ const policy = ctx.meta?.["contextWindowPolicy"];
9494
+ if (!policy || typeof policy !== "object") return null;
9495
+ const candidate = policy;
9496
+ if (typeof candidate.preserveK !== "number" || !candidate.thresholds) return null;
9497
+ return candidate;
9498
+ }
9499
+
9459
9500
  // src/execution/auto-compaction-middleware.ts
9460
9501
  var LEVEL_RANK2 = { warn: 0, soft: 1, hard: 2 };
9502
+ var MAX_DIGEST_LOG_CHARS = 4e3;
9503
+ function truncateDigest(digest) {
9504
+ if (digest.length <= MAX_DIGEST_LOG_CHARS) return digest;
9505
+ return `${digest.slice(0, MAX_DIGEST_LOG_CHARS)}\u2026 [+${digest.length - MAX_DIGEST_LOG_CHARS} chars; full turns in session log]`;
9506
+ }
9461
9507
  var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
9462
9508
  name = "AutoCompaction";
9463
9509
  compactor;
@@ -9518,7 +9564,12 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
9518
9564
  }
9519
9565
  handler() {
9520
9566
  return async (ctx, next) => {
9521
- const tokens = this._estimator ? this._estimator(ctx) : estimateRequestTokensCalibrated(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total;
9567
+ const tokens = this._estimator ? this._estimator(ctx) : estimateRequestTokensCalibrated(
9568
+ ctx.messages,
9569
+ ctx.systemPrompt,
9570
+ ctx.tools ?? [],
9571
+ `${ctx.provider?.id ?? "unknown"}/${ctx.model}`
9572
+ ).total;
9522
9573
  const load = tokens / this._maxContext;
9523
9574
  const policy = this.policyProvider?.(ctx);
9524
9575
  const thresholds = policy?.thresholds ?? {
@@ -9580,7 +9631,11 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
9580
9631
  after: report.after,
9581
9632
  level: pressure.level,
9582
9633
  aggressive,
9583
- reductions: report.reductions?.map((r) => ({ phase: r.phase, saved: r.saved }))
9634
+ reductions: report.reductions?.map((r) => ({ phase: r.phase, saved: r.saved })),
9635
+ // Record what was collapsed so the audit trail shows the preserved
9636
+ // content, not just token counts. Bounded to keep the log line small;
9637
+ // the full original turns are already in the session JSONL.
9638
+ ...report.collapsedDigest ? { digest: truncateDigest(report.collapsedDigest) } : {}
9584
9639
  });
9585
9640
  ctx.clearFileTracking();
9586
9641
  } catch (err) {
@@ -9665,6 +9720,12 @@ var DoneConditionChecker = class {
9665
9720
  return { done: true, reason: `max tool calls (${this.condition.maxToolCalls}) reached`, ...state };
9666
9721
  }
9667
9722
  break;
9723
+ case "all_tasks_done":
9724
+ break;
9725
+ case "custom":
9726
+ break;
9727
+ default:
9728
+ return assertNever(this.condition.type);
9668
9729
  }
9669
9730
  return { done: false, iterations: state.iterations, toolCalls: state.toolCalls };
9670
9731
  }
@@ -9924,12 +9985,12 @@ function formatGoal(goal, journalLimit = 10) {
9924
9985
  return lines.join("\n");
9925
9986
  }
9926
9987
  function parseProgressFromText(text) {
9927
- const re = /\[progress:\s*(\d{1,3})%\]\s*(?:[—\-]\s*(.+))?/i;
9988
+ const re = /\[progress:\s*(\d{1,3})%\]\s*(?:[—-]\s*(.+))?/i;
9928
9989
  const m = text.match(re);
9929
9990
  if (!m) return null;
9930
- const progress = Math.min(100, Math.max(0, Number.parseInt(m[1], 10)));
9991
+ const progress = Math.min(100, Math.max(0, Number.parseInt(m[1] ?? "0", 10)));
9931
9992
  const note = m[2]?.trim() || void 0;
9932
- return { progress, note };
9993
+ return note === void 0 ? { progress } : { progress, note };
9933
9994
  }
9934
9995
  function recordProgress(goal, progress, note) {
9935
9996
  const clamped = Math.min(100, Math.max(0, progress));
@@ -10523,6 +10584,7 @@ ${recentJournal}` : "No prior iterations.",
10523
10584
  note: note.slice(0, 240)
10524
10585
  });
10525
10586
  await saveGoal(this.goalPath, withEntry);
10587
+ this.opts.onEternalStop?.();
10526
10588
  }
10527
10589
  /**
10528
10590
  * Manually clear the goal — equivalent to `/goal clear` typed by the user.
@@ -15461,7 +15523,7 @@ var CollabSession = class extends EventEmitter {
15461
15523
  bugs = /* @__PURE__ */ new Map();
15462
15524
  plans = /* @__PURE__ */ new Map();
15463
15525
  evaluations = /* @__PURE__ */ new Map();
15464
- disposers = new Array();
15526
+ disposers = [];
15465
15527
  settled = false;
15466
15528
  timeoutMs;
15467
15529
  cancelled = false;
@@ -16669,7 +16731,7 @@ var FleetUsageAggregator = class {
16669
16731
  metaLookup;
16670
16732
  perSubagent = /* @__PURE__ */ new Map();
16671
16733
  total = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
16672
- unsub = new Array();
16734
+ unsub = [];
16673
16735
  /**
16674
16736
  * Remove a terminated subagent's data from the aggregator and subtract its
16675
16737
  * contribution from the running totals. Call this when a subagent is removed
@@ -17052,7 +17114,10 @@ var Director = class _Director {
17052
17114
  workCompleteFlag = false;
17053
17115
  /** Pending /btw notes stashed by the leader agent (see setLeaderBtwNote). */
17054
17116
  _leaderBtwNotes = [];
17055
- /** Active collab sessions tracked by sessionId (see spawnCollab). */
17117
+ /** Active collab sessions tracked by sessionId (see spawnCollab).
17118
+ * The tuple holds the session and its Director-registered listener unsubs.
17119
+ * Calling the unsubs on cancel/premature-cleanup prevents listener accumulation
17120
+ * on CollabSession (EventEmitter) across many spawnCollab() calls. */
17056
17121
  _activeCollabSessions = /* @__PURE__ */ new Map();
17057
17122
  /** Prevents large `ask_subagent` answers from bloating the leader's context window. */
17058
17123
  largeAnswerStore;
@@ -17382,11 +17447,13 @@ var Director = class _Director {
17382
17447
  * The CollabDebugReport will reflect 'cancelled' disposition when awaited.
17383
17448
  */
17384
17449
  cancelCollabSession(sessionId, reason = "Director cancelled") {
17385
- const session = this._activeCollabSessions.get(sessionId);
17386
- if (!session || session.isCancelled()) return;
17387
- session.cancel(reason);
17388
- for (const [_role, subagentId] of session.getSubagentIds()) {
17389
- this.coordinator.stop(subagentId).catch(() => {
17450
+ const entry = this._activeCollabSessions.get(sessionId);
17451
+ if (!entry || entry.session.isCancelled()) return;
17452
+ for (const unsub of entry.unsubs) unsub();
17453
+ entry.session.cancel(reason);
17454
+ for (const [_role, subagentId] of entry.session.getSubagentIds()) {
17455
+ this.coordinator.stop(subagentId).catch((err) => {
17456
+ console.debug(`[director] stop subagent ${subagentId} failed (may have already completed): ${err}`);
17390
17457
  });
17391
17458
  }
17392
17459
  }
@@ -18034,9 +18101,15 @@ var Director = class _Director {
18034
18101
  return options.onBudgetWarning?.(alert) ?? "ignore";
18035
18102
  }
18036
18103
  });
18037
- this._activeCollabSessions.set(session.sessionId, session);
18038
- session.on("session.done", () => this._activeCollabSessions.delete(session.sessionId));
18039
- session.on("session.error", () => this._activeCollabSessions.delete(session.sessionId));
18104
+ const doneHandler = () => this._activeCollabSessions.delete(session.sessionId);
18105
+ const errorHandler = () => this._activeCollabSessions.delete(session.sessionId);
18106
+ session.on("session.done", doneHandler);
18107
+ session.on("session.error", errorHandler);
18108
+ const unsubs = [
18109
+ () => session.off("session.done", doneHandler),
18110
+ () => session.off("session.error", errorHandler)
18111
+ ];
18112
+ this._activeCollabSessions.set(session.sessionId, { session, unsubs });
18040
18113
  return session.start();
18041
18114
  }
18042
18115
  /**
@@ -20804,6 +20877,8 @@ var SpecVersioning = class {
20804
20877
  switch (type) {
20805
20878
  case "functional":
20806
20879
  return "feature";
20880
+ case "non-functional":
20881
+ return "feature";
20807
20882
  case "security":
20808
20883
  return "feature";
20809
20884
  case "performance":
@@ -20811,7 +20886,7 @@ var SpecVersioning = class {
20811
20886
  case "ux":
20812
20887
  return "feature";
20813
20888
  default:
20814
- return "feature";
20889
+ return assertNever(type);
20815
20890
  }
20816
20891
  }
20817
20892
  };
@@ -21962,27 +22037,13 @@ function startOtlpTraceExporter(opts) {
21962
22037
  // src/infrastructure/context-manager.ts
21963
22038
  var CONTEXT_MANAGER_TOOL_NAME = "context_manager";
21964
22039
  function roughEstimate(messages) {
21965
- let total = 0;
21966
- for (const m of messages) {
21967
- if (typeof m.content === "string") {
21968
- total += Math.ceil(m.content.length / 4);
21969
- } else if (Array.isArray(m.content)) {
21970
- for (const b of m.content) {
21971
- if (b.type === "text") total += Math.ceil(b.text.length / 4);
21972
- else if (b.type === "tool_use" || b.type === "tool_result") {
21973
- total += Math.ceil(JSON.stringify(b).length / 4);
21974
- }
21975
- }
21976
- }
21977
- }
21978
- return total;
22040
+ return estimateMessageTokens(messages);
21979
22041
  }
21980
22042
  function createContextManagerTool(opts = {}) {
21981
22043
  const minCompactThreshold = opts.minCompactThreshold ?? 0;
21982
22044
  const noopRetryDeltaTokens = opts.noopRetryDeltaTokens ?? 2e3;
21983
- const maxContext = opts.maxContext ?? 128e3;
22045
+ const configuredMaxContext = opts.maxContext;
21984
22046
  const compactThresholdFraction = opts.compactThresholdFraction ?? 0.5;
21985
- const effectiveThreshold = minCompactThreshold > 0 ? minCompactThreshold : Math.floor(maxContext * compactThresholdFraction);
21986
22047
  let lastNoopTokens = 0;
21987
22048
  return {
21988
22049
  name: CONTEXT_MANAGER_TOOL_NAME,
@@ -22076,6 +22137,8 @@ function createContextManagerTool(opts = {}) {
22076
22137
  }
22077
22138
  const fullEstimate = input.systemPrompt != null && Array.isArray(input.tools) ? estimateRequestTokens(messages, input.systemPrompt, input.tools) : { total: beforeTokens};
22078
22139
  const currentTokens = fullEstimate.total;
22140
+ const runtimeMaxContext = configuredMaxContext ?? ctx.provider?.capabilities?.maxContext ?? 128e3;
22141
+ const runtimeThreshold = minCompactThreshold > 0 ? minCompactThreshold : Math.floor(runtimeMaxContext * compactThresholdFraction);
22079
22142
  if (lastNoopTokens > 0) {
22080
22143
  const delta = currentTokens - lastNoopTokens;
22081
22144
  if (delta < noopRetryDeltaTokens) {
@@ -22088,13 +22151,13 @@ function createContextManagerTool(opts = {}) {
22088
22151
  };
22089
22152
  }
22090
22153
  }
22091
- if (currentTokens < effectiveThreshold) {
22154
+ if (runtimeThreshold > 0 && currentTokens < runtimeThreshold) {
22092
22155
  return {
22093
22156
  action: "compact",
22094
22157
  beforeTokens,
22095
22158
  afterTokens: beforeTokens,
22096
22159
  messageCount: messages.length,
22097
- notes: `Context tokens (${currentTokens}) below compact threshold (${effectiveThreshold}). Skipping.`
22160
+ notes: `Context tokens (${currentTokens}) below compact threshold (${runtimeThreshold}, based on provider maxContext ${runtimeMaxContext}). Skipping.`
22098
22161
  };
22099
22162
  }
22100
22163
  const report = await opts.compactor.compact(ctx);
@@ -27463,9 +27526,17 @@ function createAgentLoopHandler(a, handlers) {
27463
27526
  async function compactContextIfNeeded() {
27464
27527
  await a.pipelines.contextWindow.run(a.ctx);
27465
27528
  }
27529
+ const calibrationKey = (model = a.ctx.model) => `${a.ctx.provider?.id ?? "unknown"}/${model}`;
27466
27530
  function emitContextPct() {
27467
- const maxContext = a.ctx.provider.capabilities.maxContext ?? 2e5;
27468
- const { total } = estimateRequestTokens(a.ctx.messages, a.ctx.systemPrompt, a.ctx.tools ?? []);
27531
+ const metaLimit = a.ctx.meta?.["effectiveMaxContext"];
27532
+ const providerMax = a.ctx.provider.capabilities.maxContext;
27533
+ const maxContext = typeof metaLimit === "number" && metaLimit > 0 ? metaLimit : typeof providerMax === "number" && providerMax > 0 ? providerMax : 2e5;
27534
+ const { total } = estimateRequestTokensCalibrated(
27535
+ a.ctx.messages,
27536
+ a.ctx.systemPrompt,
27537
+ a.ctx.tools ?? [],
27538
+ calibrationKey()
27539
+ );
27469
27540
  a.events.emit("ctx.pct", { load: total / maxContext, tokens: total, maxContext });
27470
27541
  }
27471
27542
  function injectPendingBtwNotes() {
@@ -27581,8 +27652,9 @@ function createAgentLoopHandler(a, handlers) {
27581
27652
  let res;
27582
27653
  try {
27583
27654
  res = await customRunner(a.ctx, req);
27584
- const calibratedEstimate = estimateRequestTokensCalibrated(req.messages, req.system, req.tools ?? []).total;
27585
- recordActualUsage(res.usage.input, calibratedEstimate);
27655
+ const key = calibrationKey(req.model);
27656
+ const calibratedEstimate = estimateRequestTokensCalibrated(req.messages, req.system, req.tools ?? [], key).total;
27657
+ recordActualUsage(res.usage.input, calibratedEstimate, key);
27586
27658
  recoveryRetries = 0;
27587
27659
  } catch (err) {
27588
27660
  if (controller.signal.aborted) {
@@ -28615,7 +28687,30 @@ Never silently skip a failure \u2014 always report it, even when you choose not
28615
28687
  - **Move on from mistakes.** When something fails, report what happened and what you'll do next. No apologies, no hand-wringing.
28616
28688
  - **Respect denied tools.** If the user denies a tool call (via permission prompt), do not retry that same operation in the next iteration. The user's "no" means "find another way or ask". Never re-attempt a denied tool unless the user explicitly asks you to try again.
28617
28689
  - **When denied, ask.** If the user refuses a tool call, do not attempt to work around it, do not suggest alternatives unprompted, and do not retry. Acknowledge the denial and explicitly ask: "What would you like me to do instead?"
28618
- - **Stay in your lane.** Don't lecture about software engineering principles unless explicitly asked \u2014 the user is the expert on their codebase.`;
28690
+ - **Stay in your lane.** Don't lecture about software engineering principles unless explicitly asked \u2014 the user is the expert on their codebase.
28691
+
28692
+ ## After-task suggestions
28693
+
28694
+ After completing a significant task, end your response with 2\u20134 suggested next
28695
+ actions under a \`\u{1F4A1} Next steps\` heading. Use this format so the user can
28696
+ select them with \`/next 1\`, \`/next 2\`, or \`/next 1 2 3\`:
28697
+
28698
+ \`\`\`
28699
+ \u{1F4A1} Next steps
28700
+ 1. First suggestion \u2014 imperative, specific, actionable
28701
+ 2. Second suggestion
28702
+ 3. Third suggestion
28703
+ \`\`\`
28704
+
28705
+ Rules:
28706
+ - Each line is a single imperative sentence the user can act on immediately.
28707
+ - Be specific: mention file names, tool names, or commands.
28708
+ - Order by priority. Keep each suggestion to one line.
28709
+ - Skip during multi-step operations \u2014 only show after completion.
28710
+ - If nothing is pending, say "No pending actions."
28711
+
28712
+ The user can execute via \`/next 1\`, view via \`/next list\`, or generate
28713
+ fresh suggestions via \`/suggest\`.`;
28619
28714
 
28620
28715
  // src/core/system-prompt-builder.ts
28621
28716
  var LAYER_1_IDENTITY = PROMPT;
@@ -30155,8 +30250,7 @@ var PhaseOrchestrator = class {
30155
30250
  /** Wait for all pending phase merges, dependency-ordered and globally serialized. */
30156
30251
  async drainMerges() {
30157
30252
  await Promise.allSettled([...this.phaseMergePromise.values()]);
30158
- await this.mergeQueue.catch(() => {
30159
- });
30253
+ await this.mergeQueue.catch((err) => console.warn(`[phase-orchestrator] mergeQueue failed: ${err}`));
30160
30254
  }
30161
30255
  /** Pause: active phases continue, but no new phase starts. */
30162
30256
  pause() {
@@ -31892,6 +31986,11 @@ var DefaultBrainArbiter = class {
31892
31986
  options: request.options,
31893
31987
  rationale: "Decision requires human authority or lacks a safe automatic option."
31894
31988
  };
31989
+ default:
31990
+ return {
31991
+ type: "deny",
31992
+ reason: `Brain could not safely decide (unknown fallback: ${String(request.fallback)}): ${request.question}`
31993
+ };
31895
31994
  }
31896
31995
  }
31897
31996
  };
@@ -33198,6 +33297,6 @@ ${formatPlan(updated)}`
33198
33297
  };
33199
33298
  }
33200
33299
 
33201
- export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BudgetExceededError, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GraphMemoryBackend, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MEMORY_TYPE_LABELS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, StreamHangError, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertSafePath, atomicWrite, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildRecoveryStrategies, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMcpControlTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createSyncPlugin, createToolOutputSerializer, decryptConfigSecrets, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, dispatchAgent, downloadGitHubTarball, emptyGoal, emptyPlan, emptyTaskFile, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expectDefined, extractRunEnv, filesystemServer, findCriticalPath, flagsToConfigPatch, formatContextWindowModeList, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getPlanTemplate, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hashRequest, hookMatcherMatches, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, normalizeToLf, normalizedEqual, onResize, parseContinueDirective, parseEntries, parseProgressFromText, parseSkillRef, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, recordProgress, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveContextWindowPolicy, resolveModelMatrix, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, securitySlashCommand, sentinelServer, setBtwNote, setOutputLineGuard, setPlanItemStatus, setProgress, setRawMode, shouldEnhance, slackServer, sleep, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, withFileLock, wrapAsState, writeErr, writeOut, zaiVisionServer };
33300
+ export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BudgetExceededError, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GraphMemoryBackend, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MEMORY_TYPE_LABELS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, StreamHangError, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertNever, assertSafePath, atomicWrite, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildRecoveryStrategies, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMcpControlTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createStrategyCompactor, createSyncPlugin, createToolOutputSerializer, decryptConfigSecrets, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, dispatchAgent, downloadGitHubTarball, emptyGoal, emptyPlan, emptyTaskFile, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateMessageTokens, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expectDefined, extractRunEnv, filesystemServer, findCriticalPath, flagsToConfigPatch, formatContextWindowModeList, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getPlanTemplate, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hashRequest, hookMatcherMatches, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isSecretField, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, normalizeToLf, normalizedEqual, onResize, parseContinueDirective, parseEntries, parseProgressFromText, parseSkillRef, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, recordProgress, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveContextWindowPolicy, resolveModelMatrix, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, securitySlashCommand, sentinelServer, setBtwNote, setOutputLineGuard, setPlanItemStatus, setProgress, setRawMode, shouldEnhance, slackServer, sleep, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, withFileLock, wrapAsState, writeErr, writeOut, zaiVisionServer };
33202
33301
  //# sourceMappingURL=index.js.map
33203
33302
  //# sourceMappingURL=index.js.map