@wrongstack/core 0.267.0 → 0.269.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 (78) hide show
  1. package/dist/{agent-bridge-STJ3JwwK.d.ts → agent-bridge-PcHQl_UQ.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-CzPGP3jA.d.ts → agent-subagent-runner-SHJW7t8q.d.ts} +8 -8
  3. package/dist/{brain-Cdg77tVN.d.ts → brain-BYcK__Ym.d.ts} +1 -1
  4. package/dist/{compactor-iMZ84CXq.d.ts → compactor-C2RKEBtC.d.ts} +1 -1
  5. package/dist/{config-Du3pYYln.d.ts → config-C_ae2k86.d.ts} +79 -2
  6. package/dist/{context-dT5Ueund.d.ts → context-Dp87Bcaq.d.ts} +47 -1
  7. package/dist/coordination/index.d.ts +62 -160
  8. package/dist/coordination/index.js +566 -149
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +26 -25
  11. package/dist/defaults/index.js +366 -137
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +72 -16
  14. package/dist/execution/index.js +267 -55
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/execution/prompt-enhancer.d.ts +1 -1
  17. package/dist/extension/index.d.ts +7 -6
  18. package/dist/global-mailbox-Bvrz1P3f.d.ts +664 -0
  19. package/dist/{goal-preamble-SulMTowG.d.ts → goal-preamble-CA_4yiGQ.d.ts} +9 -9
  20. package/dist/{goal-store-CABDwdFE.d.ts → goal-store-DhuJoUNG.d.ts} +1 -1
  21. package/dist/hq/index.d.ts +204 -0
  22. package/dist/hq/index.js +1931 -0
  23. package/dist/hq/index.js.map +1 -0
  24. package/dist/{index-DtCVWel4.d.ts → index-CZQ6Pwbs.d.ts} +8 -8
  25. package/dist/{index-Bms0m4oy.d.ts → index-W4VJCzHa.d.ts} +5 -5
  26. package/dist/{index-IEuxQd-E.d.ts → index-whDfTANu.d.ts} +2 -2
  27. package/dist/index.d.ts +46 -42
  28. package/dist/index.js +3472 -1651
  29. package/dist/index.js.map +1 -1
  30. package/dist/infrastructure/index.d.ts +6 -6
  31. package/dist/infrastructure/index.js +48 -21
  32. package/dist/infrastructure/index.js.map +1 -1
  33. package/dist/kernel/index.d.ts +10 -9
  34. package/dist/{pipeline-BfD2k1rT.d.ts → mailbox-types-Ct2hJq0P.d.ts} +1 -244
  35. package/dist/{mcp-servers-C2cBTxUR.d.ts → mcp-servers-DJdZiRcv.d.ts} +10 -4
  36. package/dist/models/index.d.ts +5 -5
  37. package/dist/models/index.js +4 -3
  38. package/dist/models/index.js.map +1 -1
  39. package/dist/{models-registry-BqGZNJQ-.d.ts → models-registry-C3a-2-Yd.d.ts} +1 -1
  40. package/dist/{multi-agent-coordinator-B8R43uPz.d.ts → multi-agent-coordinator-CJSpTe5O.d.ts} +1 -1
  41. package/dist/{null-fleet-bus-CnXa5oTH.d.ts → null-fleet-bus-QVshIsDx.d.ts} +6 -6
  42. package/dist/observability/index.d.ts +2 -2
  43. package/dist/{parallel-eternal-engine-DdNnw9BQ.d.ts → parallel-eternal-engine-D9y5Pkcc.d.ts} +9 -15
  44. package/dist/{path-resolver-COIMLCQL.d.ts → path-resolver-CnQ8SIfh.d.ts} +4 -3
  45. package/dist/{permission-B75JAi3-.d.ts → permission-CvYQNUqZ.d.ts} +1 -1
  46. package/dist/{permission-policy-DlR9eJAM.d.ts → permission-policy-D5Ss8j4B.d.ts} +2 -3
  47. package/dist/pipeline-l_zzFRh3.d.ts +245 -0
  48. package/dist/{plan-templates-DSIKCXZN.d.ts → plan-templates-NtPgyeJA.d.ts} +6 -5
  49. package/dist/{provider-model-resolve-BNRsNuJx.d.ts → provider-model-resolve-d5poT5y0.d.ts} +3 -3
  50. package/dist/{provider-runner-CX7iIvox.d.ts → provider-runner-gkctlQV_.d.ts} +3 -3
  51. package/dist/{retry-policy-BilV1ujH.d.ts → retry-policy-CtFhfwa8.d.ts} +1 -1
  52. package/dist/sdd/index.d.ts +9 -8
  53. package/dist/sdd/index.js +33 -3
  54. package/dist/sdd/index.js.map +1 -1
  55. package/dist/{secret-vault-gkvEZZfE.d.ts → secret-vault-BLsVmTIK.d.ts} +1 -1
  56. package/dist/security/index.d.ts +5 -5
  57. package/dist/security/index.js +39 -29
  58. package/dist/security/index.js.map +1 -1
  59. package/dist/{selector-Bc7eWtT3.d.ts → selector-CXl2_y9W.d.ts} +1 -1
  60. package/dist/{session-event-bridge-D-araDEz.d.ts → session-event-bridge-Ccud20CC.d.ts} +1 -1
  61. package/dist/{session-reader-D7Dapswh.d.ts → session-reader-ZeXQmsmE.d.ts} +1 -1
  62. package/dist/skills/index.js.map +1 -1
  63. package/dist/storage/index.d.ts +16 -12
  64. package/dist/storage/index.js +273 -100
  65. package/dist/storage/index.js.map +1 -1
  66. package/dist/tools/index.d.ts +2 -2
  67. package/dist/tools/index.js +166 -31
  68. package/dist/tools/index.js.map +1 -1
  69. package/dist/types/index.d.ts +22 -21
  70. package/dist/types/index.js +178 -70
  71. package/dist/types/index.js.map +1 -1
  72. package/dist/utils/index.d.ts +22 -3
  73. package/dist/utils/index.js +197 -25
  74. package/dist/utils/index.js.map +1 -1
  75. package/package.json +5 -1
  76. package/skills/chimera/SKILL.md +1 -1
  77. package/skills/typescript-strict/SKILL.md +3 -3
  78. package/skills/typescript-strict/SKILL.save.md +1 -1
@@ -1,23 +1,24 @@
1
- export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, E as EternalAutonomyEngine, c as EternalAutonomyOptions, d as EternalEngineState, H as HybridCompactor, I as IterationStage, P as ParallelEngineState, e as ParallelEternalEngine, f as ParallelEternalOptions, g as ParallelIterationStage, T as ToolExecutor } from '../parallel-eternal-engine-DdNnw9BQ.js';
2
- export { A as AutoCompactionMiddleware, a as AutonomousRunner, b as AutonomousRunnerOptions, c as AutonomyPromptContributorOptions, C as CompactorStrategy, l as ContextWindowBudgetSnapshot, D as DefaultSkillLoader, d as DoneCheckResult, e as DoneConditionChecker, I as IntelligentCompactor, f as IntelligentCompactorOptions, S as SelectiveCompactor, g as SelectiveCompactorOptions, h as SkillLoaderOptions, i as StrategyCompactorOptions, j as buildGoalPreamble, k as createStrategyCompactor, m as makeAutonomyPromptContributor } from '../goal-preamble-SulMTowG.js';
3
- import { P as Provider } from '../context-dT5Ueund.js';
4
- import { e as BrainDecision, h as BrainDecisionRequest, B as BrainArbiter } from '../brain-Cdg77tVN.js';
5
- import '../retry-policy-BilV1ujH.js';
6
- import '../compactor-iMZ84CXq.js';
7
- import '../config-Du3pYYln.js';
8
- import '../index-Bms0m4oy.js';
1
+ export { C as CompactorOptions, a as DefaultErrorHandler, b as DefaultRetryPolicy, E as EternalAutonomyEngine, c as EternalAutonomyOptions, d as EternalEngineState, H as HybridCompactor, I as IterationStage, P as ParallelEngineState, e as ParallelEternalEngine, f as ParallelEternalOptions, g as ParallelIterationStage, T as ToolExecutor } from '../parallel-eternal-engine-D9y5Pkcc.js';
2
+ export { A as AutoCompactionMiddleware, a as AutonomousRunner, b as AutonomousRunnerOptions, c as AutonomyPromptContributorOptions, C as CompactorStrategy, l as ContextWindowBudgetSnapshot, D as DefaultSkillLoader, d as DoneCheckResult, e as DoneConditionChecker, I as IntelligentCompactor, f as IntelligentCompactorOptions, S as SelectiveCompactor, g as SelectiveCompactorOptions, h as SkillLoaderOptions, i as StrategyCompactorOptions, j as buildGoalPreamble, k as createStrategyCompactor, m as makeAutonomyPromptContributor } from '../goal-preamble-CA_4yiGQ.js';
3
+ import { P as Provider, l as ReasoningConfig, R as Request } from '../context-Dp87Bcaq.js';
4
+ import { e as BrainDecision, h as BrainDecisionRequest, B as BrainArbiter } from '../brain-BYcK__Ym.js';
5
+ import { G as ModelRuntimeConfig } from '../config-C_ae2k86.js';
6
+ import '../retry-policy-CtFhfwa8.js';
7
+ import '../compactor-C2RKEBtC.js';
8
+ import '../index-W4VJCzHa.js';
9
9
  import '../logger-B63L5bTg.js';
10
- import '../pipeline-BfD2k1rT.js';
10
+ import '../pipeline-l_zzFRh3.js';
11
+ import '../mailbox-types-Ct2hJq0P.js';
11
12
  import '../observability-D-HZN_mF.js';
12
- import '../permission-B75JAi3-.js';
13
- import '../agent-subagent-runner-CzPGP3jA.js';
14
- import '../goal-store-CABDwdFE.js';
15
- import '../multi-agent-coordinator-B8R43uPz.js';
13
+ import '../permission-CvYQNUqZ.js';
14
+ import '../agent-subagent-runner-SHJW7t8q.js';
15
+ import '../goal-store-DhuJoUNG.js';
16
+ import '../multi-agent-coordinator-CJSpTe5O.js';
16
17
  import 'node:events';
17
18
  import '../skill-DGIXCtdv.js';
18
19
  import '../wstack-paths-hOpNLmvf.js';
19
- import '../selector-Bc7eWtT3.js';
20
- import '../session-event-bridge-D-araDEz.js';
20
+ import '../selector-CXl2_y9W.js';
21
+ import '../session-event-bridge-Ccud20CC.js';
21
22
 
22
23
  /**
23
24
  * AutonomyBrain — a self-driving decision layer for autonomous workflows.
@@ -108,4 +109,59 @@ declare function createAutonomyBrain(opts: AutonomyBrainOptions): BrainArbiter;
108
109
  */
109
110
  declare function formatDecisionSummary(decision: BrainDecision, request: BrainDecisionRequest): string;
110
111
 
111
- export { type AutonomyBrainOptions, type BrainAutoRisk, type TieredBrainArbiterOptions, createAutonomyBrain, createTieredBrainArbiter, formatDecisionSummary };
112
+ /**
113
+ * Model-runtime resolver + request-pipeline middleware.
114
+ *
115
+ * Maps the shared `Config.modelRuntime` settings into the per-request
116
+ * `Request.reasoning` and `Request.cache` fields, gated by the active model's
117
+ * `reasoningConfig` capabilities so unsupported values are omitted (and
118
+ * surfaced as warnings) instead of triggering provider 400s.
119
+ *
120
+ * Wired once at boot (REPL/TUI/WebUI all go through the same `request`
121
+ * pipeline) — see `installModelRuntimeMiddleware()`. UIs only need to mutate
122
+ * `Config.modelRuntime` (and persist) for the change to take effect on the next
123
+ * request.
124
+ */
125
+
126
+ interface ResolvedModelRuntime {
127
+ reasoning: Request['reasoning'];
128
+ cache: Request['cache'];
129
+ /** Human-readable warnings for settings that were ignored for this model. */
130
+ warnings: string[];
131
+ }
132
+ /**
133
+ * Resolve user-facing runtime settings into request fields for a specific
134
+ * model capability profile. Pure function — safe to unit-test without a
135
+ * provider or event bus.
136
+ *
137
+ * @param settings `Config.modelRuntime` (may be undefined → no-op)
138
+ * @param reasoning The model's `reasoningConfig`, or undefined when unknown.
139
+ * When undefined the resolver is conservative: explicit
140
+ * on/off is suppressed (provider default wins) and effort is
141
+ * dropped, because we cannot tell whether the model will
142
+ * accept the fields.
143
+ */
144
+ declare function resolveModelRuntime(settings: ModelRuntimeConfig | undefined, reasoning: ReasoningConfig | undefined): ResolvedModelRuntime;
145
+ declare function resolveReasoningForRequest(settings: ModelRuntimeConfig, rc: ReasoningConfig | undefined, warnings: string[]): Request['reasoning'];
146
+ declare function resolveCacheForRequest(settings: ModelRuntimeConfig, _warnings: string[]): Request['cache'];
147
+ interface ModelRuntimeMiddlewareOptions {
148
+ /** Provider id of the active model, for logging/diagnostics only. */
149
+ providerId?: string | undefined;
150
+ /** Model id of the active model, for logging/diagnostics only. */
151
+ modelId?: string | undefined;
152
+ /** Current runtime settings. Called per-request so live changes apply. */
153
+ getSettings(): ModelRuntimeConfig | undefined;
154
+ /** Current model capability profile. Called per-request. */
155
+ getReasoningConfig(): ReasoningConfig | undefined;
156
+ /** Optional sink for suppressed-setting warnings (e.g. emit to event bus). */
157
+ onWarning?: ((message: string) => void) | undefined;
158
+ }
159
+ /**
160
+ * Build a `request`-pipeline middleware that applies runtime settings. The
161
+ * returned function mutates the outgoing request by overlaying resolved
162
+ * `reasoning` / `cache` fields. Existing fields on the request are preserved
163
+ * only when the resolver produces nothing for that field.
164
+ */
165
+ declare function applyModelRuntime(req: Request, opts: ModelRuntimeMiddlewareOptions): Request;
166
+
167
+ export { type AutonomyBrainOptions, type BrainAutoRisk, type ModelRuntimeMiddlewareOptions, type ResolvedModelRuntime, type TieredBrainArbiterOptions, applyModelRuntime, createAutonomyBrain, createTieredBrainArbiter, formatDecisionSummary, resolveCacheForRequest, resolveModelRuntime, resolveReasoningForRequest };
@@ -89,8 +89,19 @@ function calState(key) {
89
89
  return state;
90
90
  }
91
91
  var MIN_SAMPLES_FOR_CALIBRATION = 3;
92
+ var MODEL_FAMILY_RATIO = {
93
+ // Anthropic: ~3.8-4.0 chars/token depending on model
94
+ claude: 3.8,
95
+ // OpenAI: ~4.0 chars/token
96
+ "gpt-4": 4,
97
+ "gpt-3.5": 4,
98
+ // Google: ~3.5 chars/token
99
+ gemini: 3.5,
100
+ // DeepSeek: ~3.5 chars/token
101
+ deepseek: 3.5
102
+ };
92
103
  var ESTIMATE_CACHE = /* @__PURE__ */ new Map();
93
- var ESTIMATE_CACHE_MAX_SIZE = 1e4;
104
+ var ESTIMATE_CACHE_MAX_SIZE = 5e4;
94
105
  function getCachedEstimate(key, compute) {
95
106
  const existing = ESTIMATE_CACHE.get(key);
96
107
  if (existing !== void 0) return existing;
@@ -218,8 +229,24 @@ function estimateRequestTokensCalibrated(messages, systemPrompt, tools, calibrat
218
229
  total: Math.round(result.total * safeRatio)
219
230
  };
220
231
  }
232
+ const fallbackRatio = getModelFamilyRatio(calibrationKey);
233
+ if (fallbackRatio !== null) {
234
+ return {
235
+ messages: Math.round(result.messages * fallbackRatio),
236
+ systemPrompt: Math.round(result.systemPrompt * fallbackRatio),
237
+ tools: Math.round(result.tools * fallbackRatio),
238
+ total: Math.round(result.total * fallbackRatio)
239
+ };
240
+ }
221
241
  return result;
222
242
  }
243
+ function getModelFamilyRatio(calibrationKey) {
244
+ const lower = calibrationKey.toLowerCase();
245
+ for (const [family, ratio] of Object.entries(MODEL_FAMILY_RATIO)) {
246
+ if (lower.includes(family)) return ratio / 3.5;
247
+ }
248
+ return null;
249
+ }
223
250
 
224
251
  // src/utils/expect-defined.ts
225
252
  function expectDefined(value, label) {
@@ -293,7 +320,7 @@ function hasToolResult(msg) {
293
320
  }
294
321
  function toolUseIds(msg) {
295
322
  const ids = /* @__PURE__ */ new Set();
296
- if (!msg || msg.role !== "assistant") return ids;
323
+ if (msg?.role !== "assistant") return ids;
297
324
  for (const block of contentBlocks(msg)) {
298
325
  if (block.type === "tool_use") ids.add(block.id);
299
326
  }
@@ -301,7 +328,7 @@ function toolUseIds(msg) {
301
328
  }
302
329
  function toolResultIds(msg) {
303
330
  const ids = /* @__PURE__ */ new Set();
304
- if (!msg || msg.role !== "user") return ids;
331
+ if (msg?.role !== "user") return ids;
305
332
  for (const block of contentBlocks(msg)) {
306
333
  if (block.type === "tool_result") ids.add(block.tool_use_id);
307
334
  }
@@ -1765,6 +1792,41 @@ function truncate(s, max) {
1765
1792
  return s.length <= max ? s : `${s.slice(0, max - 1)}\u2026`;
1766
1793
  }
1767
1794
 
1795
+ // src/utils/tool-subject.ts
1796
+ var GLOB_METACHARACTERS = /[*?[\]]/g;
1797
+ function escapeGlobSubject(value) {
1798
+ return value.replace(GLOB_METACHARACTERS, (char) => `\\${char}`);
1799
+ }
1800
+ function normalizePathSubject(value) {
1801
+ return escapeGlobSubject(value.replace(/\\/g, "/"));
1802
+ }
1803
+ function isPathSubjectKey(subjectKey) {
1804
+ return subjectKey === "path" || subjectKey === "file" || subjectKey === "files";
1805
+ }
1806
+ function subjectForToolInput(toolName, input, subjectKey) {
1807
+ if (!input || typeof input !== "object") return void 0;
1808
+ const obj = input;
1809
+ if (subjectKey) {
1810
+ const value = obj[subjectKey];
1811
+ if (typeof value === "string") {
1812
+ return isPathSubjectKey(subjectKey) ? normalizePathSubject(value) : escapeGlobSubject(value);
1813
+ }
1814
+ }
1815
+ if (toolName === "bash" && typeof obj.command === "string") {
1816
+ return escapeGlobSubject(obj.command);
1817
+ }
1818
+ if (typeof obj.path === "string") {
1819
+ return normalizePathSubject(obj.path);
1820
+ }
1821
+ if (typeof obj.url === "string") {
1822
+ return escapeGlobSubject(obj.url);
1823
+ }
1824
+ if (typeof obj.name === "string") {
1825
+ return escapeGlobSubject(obj.name);
1826
+ }
1827
+ return void 0;
1828
+ }
1829
+
1768
1830
  // src/utils/tool-output-serializer.ts
1769
1831
  var DEFAULT_LIST_LIMIT = 500;
1770
1832
  var LOG_ENTRY_LIMIT = 200;
@@ -1774,6 +1836,7 @@ var GREP_MATCHES_PER_FILE = 3;
1774
1836
  var DIFF_INLINE_LINE_LIMIT = 260;
1775
1837
  var DIFF_HUNK_LIMIT = 8;
1776
1838
  var DIFF_HUNK_CONTEXT = 14;
1839
+ var GREP_LINE_RE = /^(.+?):(\d+):(.*)$/;
1777
1840
  function createToolOutputSerializer(opts = {}) {
1778
1841
  const capBytes = opts.perIterationOutputCapBytes ?? 1e5;
1779
1842
  function serialize(value, context = {}) {
@@ -2159,7 +2222,7 @@ ${renderStringList(passthrough, "", 50)}`);
2159
2222
  return sections.join("\n");
2160
2223
  }
2161
2224
  function parseGrepContentLine(line) {
2162
- const match = /^(.+?):(\d+):(.*)$/.exec(line);
2225
+ const match = GREP_LINE_RE.exec(line);
2163
2226
  if (!match?.[1] || !match[2]) return void 0;
2164
2227
  return { file: match[1], line: match[2], text: match[3] ?? "" };
2165
2228
  }
@@ -2177,22 +2240,20 @@ function compactDiff(diff) {
2177
2240
  const hunks = lines.filter((line) => line.startsWith("@@")).length;
2178
2241
  const added = lines.filter((line) => line.startsWith("+") && !line.startsWith("+++")).length;
2179
2242
  const removed = lines.filter((line) => line.startsWith("-") && !line.startsWith("---")).length;
2180
- const selected = /* @__PURE__ */ new Set();
2243
+ const intervals = [];
2181
2244
  let hunkCount = 0;
2182
2245
  for (let i = 0; i < lines.length; i++) {
2183
2246
  const line = lines[i] ?? "";
2184
2247
  if (line.startsWith("diff --git") || line.startsWith("--- ") || line.startsWith("+++ ")) {
2185
- selected.add(i);
2248
+ intervals.push([i, i]);
2186
2249
  continue;
2187
2250
  }
2188
2251
  if (!line.startsWith("@@")) continue;
2189
2252
  if (hunkCount >= DIFF_HUNK_LIMIT) continue;
2190
2253
  hunkCount++;
2191
- for (let j = i; j <= Math.min(lines.length - 1, i + DIFF_HUNK_CONTEXT); j++) {
2192
- selected.add(j);
2193
- }
2254
+ intervals.push([i, Math.min(lines.length - 1, i + DIFF_HUNK_CONTEXT)]);
2194
2255
  }
2195
- if (selected.size === 0) {
2256
+ if (intervals.length === 0) {
2196
2257
  return joinSections([
2197
2258
  renderHeader("diff_summary", {
2198
2259
  files: fileCount,
@@ -2205,17 +2266,29 @@ function compactDiff(diff) {
2205
2266
  `[serializer omitted ${Math.max(0, lines.length - DIFF_INLINE_LINE_LIMIT)} diff line(s)]`
2206
2267
  ]);
2207
2268
  }
2269
+ const merged = [intervals[0]];
2270
+ for (let i = 1; i < intervals.length; i++) {
2271
+ const last = merged[merged.length - 1];
2272
+ const current = intervals[i];
2273
+ if (current[0] <= last[1] + 1) {
2274
+ last[1] = Math.max(last[1], current[1]);
2275
+ } else {
2276
+ merged.push(current);
2277
+ }
2278
+ }
2208
2279
  const excerpt = [];
2209
- let previous = -1;
2210
- for (const index of [...selected].sort((a, b) => a - b)) {
2211
- if (index > previous + 1) {
2212
- const omitted = previous === -1 ? index : index - previous - 1;
2280
+ let prevLine = -1;
2281
+ for (const [start, end] of merged) {
2282
+ if (start > prevLine + 1) {
2283
+ const omitted = prevLine === -1 ? start : start - prevLine - 1;
2213
2284
  excerpt.push(`[serializer omitted ${omitted} diff line(s)]`);
2214
2285
  }
2215
- excerpt.push(lines[index] ?? "");
2216
- previous = index;
2286
+ for (let j = start; j <= end; j++) {
2287
+ excerpt.push(lines[j] ?? "");
2288
+ }
2289
+ prevLine = end;
2217
2290
  }
2218
- const trailing = lines.length - previous - 1;
2291
+ const trailing = lines.length - prevLine - 1;
2219
2292
  if (trailing > 0) excerpt.push(`[serializer omitted ${trailing} trailing diff line(s)]`);
2220
2293
  return joinSections([
2221
2294
  renderHeader("diff_summary", {
@@ -2994,7 +3067,7 @@ ${errorDetails}`,
2994
3067
  return { result, tool, durationMs: Date.now() - start };
2995
3068
  }
2996
3069
  } else {
2997
- const suggestedPattern = this.subjectFor(tool.name, use.input, tool.subjectKey) ?? tool.name;
3070
+ const suggestedPattern = subjectForToolInput(tool.name, use.input, tool.subjectKey) ?? tool.name;
2998
3071
  const pending = {
2999
3072
  type: "tool_confirm_pending",
3000
3073
  toolUseId: use.id,
@@ -3040,6 +3113,7 @@ ${post.additionalContext}`;
3040
3113
  } catch (err) {
3041
3114
  const msg = toErrorMessage(err);
3042
3115
  const scrubbed = this.opts.secretScrubber.scrub(msg);
3116
+ const { category, retryable, detail } = classifyToolError(err);
3043
3117
  this.opts.renderer?.writeToolResult(tool.name, scrubbed, true);
3044
3118
  const result = {
3045
3119
  type: "tool_result",
@@ -3050,6 +3124,9 @@ ${post.additionalContext}`;
3050
3124
  budget = this.budgetForString(result.content, budget);
3051
3125
  if (err instanceof Error) span?.recordError(err);
3052
3126
  span?.setAttribute("tool.is_error", true);
3127
+ span?.setAttribute("tool.error_category", category);
3128
+ span?.setAttribute("tool.error_retryable", retryable);
3129
+ if (detail) span?.setAttribute("tool.error_detail", detail);
3053
3130
  return { result, tool, durationMs: Date.now() - start };
3054
3131
  } finally {
3055
3132
  span?.end();
@@ -3061,6 +3138,9 @@ ${post.additionalContext}`;
3061
3138
  } catch (err) {
3062
3139
  const msg = toErrorMessage(err);
3063
3140
  const scrubbed = this.opts.secretScrubber.scrub(msg);
3141
+ const { category, retryable, detail } = classifyToolError(err);
3142
+ const tool = this.registry.get(use.name);
3143
+ this.opts.renderer?.writeToolResult(tool?.name ?? use.name, scrubbed, true);
3064
3144
  const result = {
3065
3145
  type: "tool_result",
3066
3146
  tool_use_id: use.id,
@@ -3068,7 +3148,7 @@ ${post.additionalContext}`;
3068
3148
  is_error: true
3069
3149
  };
3070
3150
  budget = this.budgetForString(result.content, budget);
3071
- return { result, tool: this.registry.get(use.name), durationMs: 0 };
3151
+ return { result, tool, durationMs: 0 };
3072
3152
  }
3073
3153
  };
3074
3154
  if (strategy === "sequential") {
@@ -3273,38 +3353,6 @@ ${excerpt}`;
3273
3353
  budgetForString(content, budget) {
3274
3354
  return Math.max(0, budget - Buffer.byteLength(content, "utf8"));
3275
3355
  }
3276
- /**
3277
- * Compute the suggestedPattern string for a tool+input pair.
3278
- * Matches the logic in DefaultPermissionPolicy so the TUI shows the
3279
- * same subject that the trust file would use.
3280
- */
3281
- subjectFor(toolName, input, subjectKey) {
3282
- if (!input || typeof input !== "object") return void 0;
3283
- const obj = input;
3284
- const globChars = /[*?[\]]/g;
3285
- const escapeGlob = (s) => s.replace(globChars, (c) => `\\${c}`);
3286
- const normalizePath = (s) => escapeGlob(s.replace(/\\/g, "/"));
3287
- if (subjectKey) {
3288
- const v = obj[subjectKey];
3289
- if (typeof v === "string") {
3290
- const isPathKey = subjectKey === "path" || subjectKey === "file" || subjectKey === "files";
3291
- return isPathKey ? normalizePath(v) : escapeGlob(v);
3292
- }
3293
- }
3294
- if (toolName === "bash" && typeof obj.command === "string") {
3295
- return escapeGlob(obj.command);
3296
- }
3297
- if (typeof obj.path === "string") {
3298
- return normalizePath(obj.path);
3299
- }
3300
- if (typeof obj.url === "string") {
3301
- return escapeGlob(obj.url);
3302
- }
3303
- if (typeof obj.name === "string") {
3304
- return escapeGlob(obj.name);
3305
- }
3306
- return void 0;
3307
- }
3308
3356
  };
3309
3357
  function clampTimeoutMs(timeoutMs, maxTimeoutMs) {
3310
3358
  const fallback = 3e5;
@@ -3332,6 +3380,58 @@ function extractMalformedRaw(input) {
3332
3380
  }
3333
3381
  }
3334
3382
  var TOOL_OUTPUT_ARTIFACT_THRESHOLD_BYTES = 64 * 1024;
3383
+ function classifyToolError(err) {
3384
+ if (err instanceof Error && err.name === "AbortError") {
3385
+ return { category: "fatal" /* FATAL */, retryable: false, detail: "aborted" };
3386
+ }
3387
+ if (err instanceof Error && "code" in err) {
3388
+ const code = err.code;
3389
+ switch (code) {
3390
+ case "ETIMEDOUT":
3391
+ case "ECONNRESET":
3392
+ case "ECONNREFUSED":
3393
+ case "ENETUNREACH":
3394
+ case "EHOSTUNREACH":
3395
+ return { category: "transient" /* TRANSIENT */, retryable: true, detail: code };
3396
+ case "ENOENT":
3397
+ case "ENOTDIR":
3398
+ return { category: "not_found" /* NOT_FOUND */, retryable: false, detail: code };
3399
+ case "EACCES":
3400
+ case "EPERM":
3401
+ return { category: "permission" /* PERMISSION */, retryable: false, detail: code };
3402
+ case "EBUSY":
3403
+ case "EMFILE":
3404
+ case "ENFILE":
3405
+ return { category: "transient" /* TRANSIENT */, retryable: true, detail: code };
3406
+ }
3407
+ }
3408
+ if (err instanceof Error && "response" in err) {
3409
+ const response = err.response;
3410
+ const status = response?.status;
3411
+ if (status !== void 0) {
3412
+ if (status === 429 || status === 503 || status === 502 || status === 504) {
3413
+ return { category: "transient" /* TRANSIENT */, retryable: true, detail: `HTTP ${status}` };
3414
+ }
3415
+ if (status === 404 || status === 410) {
3416
+ return { category: "not_found" /* NOT_FOUND */, retryable: false, detail: `HTTP ${status}` };
3417
+ }
3418
+ if (status === 401 || status === 403) {
3419
+ return { category: "permission" /* PERMISSION */, retryable: false, detail: `HTTP ${status}` };
3420
+ }
3421
+ if (status === 400) {
3422
+ return { category: "validation" /* VALIDATION */, retryable: false, detail: `HTTP ${status}` };
3423
+ }
3424
+ }
3425
+ }
3426
+ if (err instanceof Error && err.message.includes("validation")) {
3427
+ return { category: "validation" /* VALIDATION */, retryable: false, detail: "validation" };
3428
+ }
3429
+ return {
3430
+ category: "fatal" /* FATAL */,
3431
+ retryable: false,
3432
+ detail: err instanceof Error ? err.message.slice(0, 100) : String(err).slice(0, 100)
3433
+ };
3434
+ }
3335
3435
  async function maybePersistLargeToolOutput(toolName, content, budget) {
3336
3436
  const bytes = Buffer.byteLength(content, "utf8");
3337
3437
  if (bytes <= Math.min(TOOL_OUTPUT_ARTIFACT_THRESHOLD_BYTES, Math.max(0, budget))) {
@@ -4841,7 +4941,7 @@ var SubagentBudget = class _SubagentBudget {
4841
4941
  */
4842
4942
  _busRequestDecision(entry) {
4843
4943
  const bus = this._events;
4844
- if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
4944
+ if (!bus?.hasListenerFor("budget.threshold_reached")) {
4845
4945
  return Promise.resolve("stop");
4846
4946
  }
4847
4947
  return new Promise((resolve3) => {
@@ -7313,7 +7413,27 @@ Working rules:
7313
7413
  id: "devops",
7314
7414
  name: "DevOps",
7315
7415
  role: "devops",
7316
- tools: [...TOOLS.build],
7416
+ tools: [
7417
+ ...TOOLS.build,
7418
+ "mcp__ssh__ssh_list_servers",
7419
+ "mcp__ssh__ssh_connection_status",
7420
+ "mcp__ssh__ssh_execute",
7421
+ "mcp__ssh__ssh_execute_sudo",
7422
+ "mcp__ssh__ssh_upload",
7423
+ "mcp__ssh__ssh_download",
7424
+ "mcp__ssh__ssh_sync",
7425
+ "mcp__ssh__ssh_deploy",
7426
+ "mcp__ssh__ssh_health_check",
7427
+ "mcp__ssh__ssh_service_status",
7428
+ "mcp__ssh__ssh_process_manager",
7429
+ "mcp__ssh__ssh_tunnel",
7430
+ "mcp__ssh__ssh_backup_create",
7431
+ "mcp__ssh__ssh_backup_list",
7432
+ "mcp__ssh__ssh_backup_restore",
7433
+ "mcp__ssh__ssh_db_list",
7434
+ "mcp__ssh__ssh_db_query",
7435
+ "mcp__ssh__ssh_profile"
7436
+ ],
7317
7437
  prompt: `You are the DevOps agent. Your job is CI/CD, containerization, and
7318
7438
  deployment configuration: make builds reproducible and deploys safe.
7319
7439
 
@@ -7322,6 +7442,7 @@ Scope:
7322
7442
  - Write Dockerfiles/compose and optimize image size and layer caching
7323
7443
  - Configure deployment (env, secrets handling, health checks, rollback)
7324
7444
  - Diagnose flaky/broken pipelines
7445
+ - Use optional SSH MCP tools for remote hosts when the 'ssh' MCP server is enabled: list servers, run health checks, inspect services, transfer/deploy files, and open tunnels
7325
7446
 
7326
7447
  Input format you accept:
7327
7448
  { "task": "ci | container | deploy | fix-pipeline", "platform": "github-actions | gitlab | docker | k8s", "target": "<what>" }
@@ -7336,7 +7457,8 @@ Working rules:
7336
7457
  - Never hardcode secrets in config; reference the secret store
7337
7458
  - Pin versions for reproducible builds; avoid floating :latest
7338
7459
  - Every deploy path needs a rollback and a health check
7339
- - Treat CI/CD changes as high-risk \u2014 explain blast radius before applying`
7460
+ - Treat CI/CD changes as high-risk \u2014 explain blast radius before applying
7461
+ - For remote SSH work, start with ssh_list_servers / ssh_connection_status, prefer read-only checks first, and do not run destructive commands without explicit user approval`
7340
7462
  },
7341
7463
  budget: MEDIUM_BUDGET,
7342
7464
  capability: {
@@ -7353,6 +7475,13 @@ Working rules:
7353
7475
  "kubernetes",
7354
7476
  "k8s",
7355
7477
  "deploy",
7478
+ "ssh",
7479
+ "remote ssh",
7480
+ "remote server",
7481
+ "sftp",
7482
+ "tunnel",
7483
+ "bastion",
7484
+ "jump host",
7356
7485
  "github actions",
7357
7486
  "container"
7358
7487
  ]
@@ -8935,6 +9064,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
8935
9064
  subagentId: result.subagentId,
8936
9065
  taskId: result.taskId,
8937
9066
  status: result.status,
9067
+ result: result.result,
8938
9068
  iterations: result.iterations,
8939
9069
  toolCalls: result.toolCalls,
8940
9070
  durationMs: result.durationMs
@@ -9868,6 +9998,88 @@ function parseDescriptionFromText(desc) {
9868
9998
  return { trigger, scope };
9869
9999
  }
9870
10000
 
9871
- export { AutoCompactionMiddleware, AutonomousRunner, DefaultErrorHandler, DefaultRetryPolicy, DefaultSkillLoader, DoneConditionChecker, EternalAutonomyEngine, HybridCompactor, IntelligentCompactor, ParallelEternalEngine, SelectiveCompactor, ToolExecutor, buildGoalPreamble, createAutonomyBrain, createStrategyCompactor, createTieredBrainArbiter, formatDecisionSummary, makeAutonomyPromptContributor };
10001
+ // src/execution/model-runtime.ts
10002
+ function resolveModelRuntime(settings, reasoning) {
10003
+ const warnings = [];
10004
+ if (!settings) {
10005
+ return { reasoning: void 0, cache: void 0, warnings };
10006
+ }
10007
+ const reasoningField = resolveReasoningForRequest(settings, reasoning, warnings);
10008
+ const cacheField = resolveCacheForRequest(settings);
10009
+ return { reasoning: reasoningField, cache: cacheField, warnings };
10010
+ }
10011
+ function resolveReasoningForRequest(settings, rc, warnings) {
10012
+ const cfg = settings.reasoning;
10013
+ if (!cfg) return void 0;
10014
+ const capKnown = rc !== void 0;
10015
+ const supportsReasoning = rc ? rc.default !== "disabled" || rc.disableSupported || rc.effortSupported : false;
10016
+ const out = {};
10017
+ if (cfg.mode === "off") {
10018
+ if (capKnown && rc?.disableSupported) {
10019
+ out.enabled = false;
10020
+ } else if (capKnown && rc && rc.default === "always_on") {
10021
+ warnings.push(
10022
+ 'reasoning "off" requested, but this model has thinking always on; the disable field was omitted to avoid a provider error.'
10023
+ );
10024
+ } else if (capKnown && rc && !rc.disableSupported) {
10025
+ warnings.push('reasoning "off" requested, but this model does not support disabling thinking; the setting was omitted.');
10026
+ } else {
10027
+ warnings.push('reasoning "off" requested, but model capabilities are unknown; the setting was omitted.');
10028
+ }
10029
+ } else if (cfg.mode === "on") {
10030
+ if (!capKnown) {
10031
+ warnings.push('reasoning "on" requested, but model capabilities are unknown; the setting was omitted.');
10032
+ } else if (!supportsReasoning && rc?.default === "disabled") {
10033
+ warnings.push('reasoning "on" requested, but this model has reasoning disabled by default and does not advertise support; the setting was omitted.');
10034
+ } else {
10035
+ out.enabled = true;
10036
+ }
10037
+ }
10038
+ const effort = cfg.effort;
10039
+ if (effort !== void 0) {
10040
+ if (capKnown && rc?.effortSupported && rc.effortLevels.includes(effort)) {
10041
+ out.effort = effort;
10042
+ } else if (capKnown && rc?.effortSupported) {
10043
+ warnings.push(
10044
+ `reasoning effort "${effort}" not supported by this model (supported: ${rc.effortLevels.join(", ")}); the setting was omitted.`
10045
+ );
10046
+ } else if (capKnown) {
10047
+ warnings.push(`reasoning effort "${effort}" requested, but this model does not support effort; the setting was omitted.`);
10048
+ } else {
10049
+ warnings.push(`reasoning effort "${effort}" requested, but model capabilities are unknown; the setting was omitted.`);
10050
+ }
10051
+ }
10052
+ if (cfg.preserve !== void 0) {
10053
+ if (capKnown && rc && rc.preserveThinking !== "unsupported") {
10054
+ out.preserve = cfg.preserve;
10055
+ } else if (capKnown) {
10056
+ warnings.push("reasoning preserve requested, but this model does not support preserved thinking; the setting was omitted.");
10057
+ }
10058
+ }
10059
+ return Object.keys(out).length > 0 ? out : void 0;
10060
+ }
10061
+ function resolveCacheForRequest(settings, _warnings) {
10062
+ const ttl = settings.cache?.ttl;
10063
+ if (ttl === void 0) return void 0;
10064
+ const out = { ttl };
10065
+ return out;
10066
+ }
10067
+ function applyModelRuntime(req, opts) {
10068
+ const settings = opts.getSettings();
10069
+ if (!settings) return req;
10070
+ const rc = opts.getReasoningConfig();
10071
+ const resolved = resolveModelRuntime(settings, rc);
10072
+ for (const w of resolved.warnings) opts.onWarning?.(w);
10073
+ const next = { ...req };
10074
+ if (resolved.reasoning !== void 0) {
10075
+ next.reasoning = resolved.reasoning;
10076
+ }
10077
+ if (resolved.cache !== void 0) {
10078
+ next.cache = resolved.cache;
10079
+ }
10080
+ return next;
10081
+ }
10082
+
10083
+ export { AutoCompactionMiddleware, AutonomousRunner, DefaultErrorHandler, DefaultRetryPolicy, DefaultSkillLoader, DoneConditionChecker, EternalAutonomyEngine, HybridCompactor, IntelligentCompactor, ParallelEternalEngine, SelectiveCompactor, ToolExecutor, applyModelRuntime, buildGoalPreamble, createAutonomyBrain, createStrategyCompactor, createTieredBrainArbiter, formatDecisionSummary, makeAutonomyPromptContributor, resolveCacheForRequest, resolveModelRuntime, resolveReasoningForRequest };
9872
10084
  //# sourceMappingURL=index.js.map
9873
10085
  //# sourceMappingURL=index.js.map