agent-nuvira 3.5.0 → 3.5.1

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 (42) hide show
  1. package/README.md +13 -13
  2. package/dist/agent-sdk/src/scaffold.d.ts +1 -1
  3. package/dist/agent-sdk/src/scaffold.js +1 -1
  4. package/dist/cli/chat.d.ts +117 -6
  5. package/dist/cli/chat.d.ts.map +1 -1
  6. package/dist/cli/chat.js +344 -20
  7. package/dist/cli/chat.js.map +1 -1
  8. package/dist/cli/duties.d.ts +11 -0
  9. package/dist/cli/duties.d.ts.map +1 -1
  10. package/dist/cli/duties.js +31 -0
  11. package/dist/cli/duties.js.map +1 -1
  12. package/dist/cli/models.d.ts.map +1 -1
  13. package/dist/cli/models.js +55 -0
  14. package/dist/cli/models.js.map +1 -1
  15. package/dist/learning/auto-router.d.ts +28 -0
  16. package/dist/learning/auto-router.d.ts.map +1 -1
  17. package/dist/learning/auto-router.js +84 -5
  18. package/dist/learning/auto-router.js.map +1 -1
  19. package/dist/learning/duty-lease.d.ts +163 -0
  20. package/dist/learning/duty-lease.d.ts.map +1 -0
  21. package/dist/learning/duty-lease.js +301 -0
  22. package/dist/learning/duty-lease.js.map +1 -0
  23. package/dist/learning/model-first-router.d.ts +14 -0
  24. package/dist/learning/model-first-router.d.ts.map +1 -1
  25. package/dist/learning/model-first-router.js +54 -17
  26. package/dist/learning/model-first-router.js.map +1 -1
  27. package/dist/learning/model-warmup.d.ts +92 -0
  28. package/dist/learning/model-warmup.d.ts.map +1 -1
  29. package/dist/learning/model-warmup.js +137 -2
  30. package/dist/learning/model-warmup.js.map +1 -1
  31. package/dist/learning/retry-patience.d.ts +139 -0
  32. package/dist/learning/retry-patience.d.ts.map +1 -0
  33. package/dist/learning/retry-patience.js +169 -0
  34. package/dist/learning/retry-patience.js.map +1 -0
  35. package/dist/tools/tool-loop.d.ts +41 -3
  36. package/dist/tools/tool-loop.d.ts.map +1 -1
  37. package/dist/tools/tool-loop.js +260 -4
  38. package/dist/tools/tool-loop.js.map +1 -1
  39. package/package.json +4 -1
  40. package/src/web-dashboard/public/assets/{index-yky0dw5e.js → index-Bik91KJh.js} +2 -2
  41. package/src/web-dashboard/public/assets/{index-yky0dw5e.js.map → index-Bik91KJh.js.map} +1 -1
  42. package/src/web-dashboard/public/index.html +1 -1
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Blip patience — how long to STAY on the pair that just failed, and whether
3
+ * walking away is even a remedy.
4
+ *
5
+ * THE OBSERVED PROBLEM THIS ENCODES. A cloud provider does not go down for a
6
+ * turn: it returns 200, then a few empty/5xx responses for a handful of seconds,
7
+ * then serves normally again (measured repeatedly on `deepseek`). Two opposite
8
+ * mistakes are available, and the codebase has made both:
9
+ *
10
+ * - FAIL FAST: give up after seconds and fold onto the next candidate — which
11
+ * for that blip means silently dropping from a strong model to a weak one.
12
+ * The result is answered, badly, by a model the user did not choose.
13
+ * - WAIT BLINDLY: sit out a long fixed backoff on a pair that is actually
14
+ * dead, and make every user of a broken provider pay for it.
15
+ *
16
+ * A timeout cannot tell those apart, so a fixed schedule is the wrong shape
17
+ * either way. What CAN tell them apart is the evidence already in hand:
18
+ *
19
+ * 1. THE ALTERNATIVES. Walking away is only a remedy when it does not cost
20
+ * quality. If every alternative sits in a LOWER capability band, then
21
+ * "fail over" means "de-escalate", and for a blip that is the worse trade —
22
+ * so we wait instead. If a same-or-better band is reachable, failing over is
23
+ * free and waiting is pure waste.
24
+ * 2. THE PAIR'S TRACK RECORD. A pair that has served real traffic with a low
25
+ * error rate earns patience; a never-proven id does not.
26
+ * 3. THE SHAPE OF THE FAILURE. One failing step is a blip. The SAME pair
27
+ * failing two steps in a row is not — patience collapses there, whatever
28
+ * the alternatives look like.
29
+ *
30
+ * And the schedule's SHAPE matters as much as its total: a 2-second blink is
31
+ * caught by a retry at t≈1s, not at t=5s, so the early delays are dense and the
32
+ * late ones sparse ({@link TRANSIENT_BLIP_DELAYS_MS} → attempts at ≈1, 3, 7, 15,
33
+ * 30, 60s). That rides out both a blink and a real minute-long spike.
34
+ *
35
+ * PURE AND DETERMINISTIC. This module reads no clock, no registry and no config:
36
+ * the caller gathers the evidence (it has the registry and the ranked pool) and
37
+ * gets back a plan it can log. That is what makes the policy reviewable and
38
+ * testable one row at a time — see the table in the tests.
39
+ */
40
+ import { bandRank, capabilityClassOf } from './model-capability.js';
41
+ /**
42
+ * Transient (server/network/timeout) backoff, dense early and sparse late:
43
+ * attempts at ≈1s, 3s, 7s, 15s, 30s, 60s. Used exactly when WAITING beats
44
+ * walking away — no alternative, or only degrading ones.
45
+ */
46
+ export const TRANSIENT_BLIP_DELAYS_MS = [1_000, 2_000, 4_000, 8_000, 15_000, 30_000];
47
+ /**
48
+ * Transient backoff when a same-or-better-band candidate IS reachable: a short
49
+ * courtesy retry (two blinks' worth, <2s) and then the walk. Spending longer is
50
+ * waste — the replacement costs nothing in quality.
51
+ */
52
+ export const TRANSIENT_FREE_ALTERNATIVE_DELAYS_MS = [500, 1_500];
53
+ /**
54
+ * Transient backoff for a pair we have no reason to trust and no alternative to:
55
+ * a token wait (≈5s), then the honest failure.
56
+ */
57
+ export const TRANSIENT_LAST_RESORT_DELAYS_MS = [1_000, 4_000];
58
+ /** Empty-response patience for a proven pair — the "final verse" case. */
59
+ export const EMPTY_PATIENCE_MS = [2_000, 5_000];
60
+ /**
61
+ * Empty-response patience when EVERY alternative would de-escalate. Longer, and
62
+ * deliberately so: this is the one situation where the choice is literally
63
+ * "wait a few more seconds" vs "answer with a weaker model".
64
+ */
65
+ export const EMPTY_PATIENCE_WAIT_BEATS_FOLDING_MS = [2_000, 5_000, 10_000];
66
+ /**
67
+ * Error rate at or below which a verified pair counts as a proven track record.
68
+ * Above it the pair has failed roughly 1 call in 5, which is not something a
69
+ * blip explains away.
70
+ */
71
+ export const PROVEN_ERROR_RATE_MAX = 0.2;
72
+ /** Is the registry evidence strong enough to grant a pair extra patience? */
73
+ function hasProvenTrackRecord(evidence) {
74
+ if (!evidence?.verified)
75
+ return false;
76
+ if ((evidence.errorRate ?? 0) > PROVEN_ERROR_RATE_MAX)
77
+ return false;
78
+ // A `probe` (catalog listing) is not evidence about answers; `telemetry` and
79
+ // `spot-check` are.
80
+ return evidence.source !== 'probe';
81
+ }
82
+ /**
83
+ * Decide how patient to be with the pair that just failed, and say why.
84
+ *
85
+ * The whole policy, in order (see the tests for each row):
86
+ *
87
+ * 1. The pair already failed an earlier step of this turn → NOT a blip. One
88
+ * token wait, no empty patience.
89
+ * 2. Nothing to gain by patience: a same-or-better band is reachable → short
90
+ * transient retry; empty patched only for a proven pair (a good pair's
91
+ * first blink is still worth two short waits).
92
+ * 3. A PROVEN pair facing only degrading alternatives (or none) → long, dense
93
+ * transient patience, and extended empty patience. This is the row that
94
+ * stops a blinking strong model from being replaced by a weak one.
95
+ * 4. An UNPROVEN pair with nowhere better to go → a token wait; the walk (or
96
+ * the honest failure) is the remedy, not optimism about a stranger.
97
+ */
98
+ export function planBlipPatience(input) {
99
+ const currentBand = capabilityClassOf(input.current.model);
100
+ const currentRank = bandRank(currentBand);
101
+ let bestRank = -1;
102
+ let bestAlternativeBand;
103
+ for (const alternative of input.alternatives) {
104
+ if (!alternative?.model)
105
+ continue;
106
+ const band = capabilityClassOf(alternative.model);
107
+ const rank = bandRank(band);
108
+ if (rank > bestRank) {
109
+ bestRank = rank;
110
+ bestAlternativeBand = band;
111
+ }
112
+ }
113
+ const hasAlternative = bestRank >= 0;
114
+ const sameOrBetterReachable = bestRank >= currentRank;
115
+ const foldingWouldDegrade = hasAlternative && !sameOrBetterReachable;
116
+ const proven = hasProvenTrackRecord(input.evidence) || input.deliveredWorkThisTurn === true;
117
+ // 1. Two failing steps in a row is a pattern, not a blip.
118
+ if (input.failedEarlierStep) {
119
+ return {
120
+ transientDelaysMs: TRANSIENT_LAST_RESORT_DELAYS_MS,
121
+ emptyResponseDelaysMs: [],
122
+ bestAlternativeBand,
123
+ foldingWouldDegrade: false,
124
+ reason: `${input.current.provider}/${input.current.model} failed an earlier step too — not a blip, so no patience`,
125
+ };
126
+ }
127
+ // 2. A same-or-better candidate is reachable: failing over costs no quality.
128
+ if (sameOrBetterReachable) {
129
+ return {
130
+ transientDelaysMs: TRANSIENT_FREE_ALTERNATIVE_DELAYS_MS,
131
+ emptyResponseDelaysMs: proven ? EMPTY_PATIENCE_MS : [],
132
+ bestAlternativeBand,
133
+ foldingWouldDegrade: false,
134
+ reason: `a ${bestAlternativeBand}-band candidate is reachable — failing over costs no quality`,
135
+ };
136
+ }
137
+ // 3. Waiting beats folding down a band.
138
+ if (foldingWouldDegrade && proven) {
139
+ return {
140
+ transientDelaysMs: TRANSIENT_BLIP_DELAYS_MS,
141
+ emptyResponseDelaysMs: EMPTY_PATIENCE_WAIT_BEATS_FOLDING_MS,
142
+ bestAlternativeBand,
143
+ foldingWouldDegrade: true,
144
+ reason: `waiting on ${input.current.provider}/${input.current.model} (${currentBand}) rather than ` +
145
+ `de-escalating to ${bestAlternativeBand} — a blip is not a reason to downgrade`,
146
+ };
147
+ }
148
+ // 3b. Nowhere else to go, but the pair has a track record: waiting is the only remedy.
149
+ if (!hasAlternative && proven) {
150
+ return {
151
+ transientDelaysMs: TRANSIENT_BLIP_DELAYS_MS,
152
+ emptyResponseDelaysMs: EMPTY_PATIENCE_WAIT_BEATS_FOLDING_MS,
153
+ bestAlternativeBand,
154
+ foldingWouldDegrade: false,
155
+ reason: `no alternative is configured — waiting on ${input.current.provider}/${input.current.model} is the only remedy`,
156
+ };
157
+ }
158
+ // 4. Unproven pair: a token wait, then the walk or the honest failure.
159
+ return {
160
+ transientDelaysMs: TRANSIENT_LAST_RESORT_DELAYS_MS,
161
+ emptyResponseDelaysMs: hasAlternative ? [] : EMPTY_PATIENCE_MS,
162
+ bestAlternativeBand,
163
+ foldingWouldDegrade,
164
+ reason: hasAlternative
165
+ ? `${input.current.provider}/${input.current.model} has no track record — the walk is the remedy`
166
+ : `nothing is proven for ${input.current.provider}/${input.current.model} and there is no alternative`,
167
+ };
168
+ }
169
+ //# sourceMappingURL=retry-patience.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-patience.js","sourceRoot":"","sources":["../../src/learning/retry-patience.ts"],"names":[],"mappings":"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"}
@@ -1086,9 +1086,18 @@ export declare const DEFAULT_THREAD_BUDGET_CHARS = 200000;
1086
1086
  /**
1087
1087
  * Deterministically trim a thread to `maxChars`:
1088
1088
  * 1. Never touch the system prompt or the FIRST user message (the ask).
1089
- * 2. Never touch the last `RECENT_KEEP` messages (recent context).
1090
- * 3. Oldest-first: tool results longer than 500 chars collapse to the stub;
1091
- * if still over budget, remaining old tool results collapse entirely.
1089
+ * 2. Never touch the last `RECENT_KEEP` messages (recent context) — except for
1090
+ * the tail clamps in steps 4–5, which run ONLY when the oldest-first passes
1091
+ * could not pay for the overage.
1092
+ * 3. Oldest-first pays FIRST, and only as much as the deficit needs: tool
1093
+ * results longer than 500 chars collapse to the stub; if still over budget,
1094
+ * remaining old tool results collapse entirely; then oversized old user
1095
+ * messages shrink.
1096
+ * 4. Only if the thread is STILL over does the protected tail pay: an oversized
1097
+ * recent tool result is clamped to head + rescued error lines + tail, and
1098
+ * then clamped harder, so the prompt actually fits the window it goes to.
1099
+ * The ORDER is what protects delivery: recent context is the model's working
1100
+ * memory, so it is spent only when nothing older can cover the overage.
1092
1101
  * Returns a NEW array (input untouched) + how many messages were trimmed.
1093
1102
  */
1094
1103
  export declare function trimThreadBudget(thread: ToolMessage[], maxChars?: number): {
@@ -1106,6 +1115,35 @@ export declare function buildWorkDigest(input: {
1106
1115
  mutatedPaths: readonly string[];
1107
1116
  executedActions: readonly ExecutedAction[];
1108
1117
  }): string;
1118
+ /** Marker prefix identifying the loop's mid-turn HANDOFF note. */
1119
+ export declare const HANDOFF_NOTE_MARKER = "[handoff \u2014 the model serving this turn changed]";
1120
+ /**
1121
+ * The note a mid-turn model switch leaves in the thread.
1122
+ *
1123
+ * It says three things the TRANSCRIPT cannot say by itself: that the pair
1124
+ * answering this step is not the pair that answered the previous ones, that the
1125
+ * context above is genuinely this model's to use (nothing was restarted), and
1126
+ * which work is already DONE (files changed, commands and their verdicts) — so
1127
+ * the replacement continues instead of re-deriving a plan from the ask. It also
1128
+ * states the rule that costs real steps when broken: do not re-run finished
1129
+ * commands or restate the work in more words.
1130
+ *
1131
+ * Deterministic and LLM-free, like the digest it borrows its facts from — a
1132
+ * handoff must not spend a model call to describe itself.
1133
+ */
1134
+ export declare function buildHandoffNote(input: {
1135
+ route?: string;
1136
+ facts?: string;
1137
+ }): string;
1138
+ /**
1139
+ * Insert or refresh the single handoff note. Idempotent — a turn may hand off
1140
+ * more than once (a second pair can also answer with nothing), and stacking a
1141
+ * note per handoff would fill the thread with the same information. Kept with
1142
+ * the run's framing (right after the leading system prompt) so it is a `system`
1143
+ * message: the thread-budget passes never trim one, and it therefore survives
1144
+ * every compaction between the handoff and the answer.
1145
+ */
1146
+ export declare function upsertHandoffNote(thread: ToolMessage[], note: string): void;
1109
1147
  /**
1110
1148
  * Insert or refresh the single work-digest message. Idempotent: a digest already
1111
1149
  * in the thread is UPDATED in place, never stacked, so repeated compaction in a
@@ -1 +1 @@
1
- {"version":3,"file":"tool-loop.d.ts","sourceRoot":"","sources":["../../src/tools/tool-loop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-loop.d.ts","sourceRoot":"","sources":["../../src/tools/tool-loop.ts"],"names":[],"mappings":"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"}
@@ -1056,7 +1056,7 @@ async function runToolLoopInner(opts, progress) {
1056
1056
  if (digest)
1057
1057
  upsertWorkDigest(thread, digest);
1058
1058
  }
1059
- deps.onEvent?.(` ✂️ ${trimmedResult.trimmed} old tool result(s) trimmed to fit the ${Math.round(budgetChars / 1000)}K-char context budget.`);
1059
+ deps.onEvent?.(` ✂️ ${trimmedResult.trimmed} message(s) trimmed to fit the ${Math.round(budgetChars / 1000)}K-char context budget.`);
1060
1060
  }
1061
1061
  }
1062
1062
  // ── The route feed, re-synced before every call ────────────────────────
@@ -1288,6 +1288,43 @@ async function runToolLoopInner(opts, progress) {
1288
1288
  }
1289
1289
  if (switched) {
1290
1290
  modelHandoffs += 1;
1291
+ // ── CONTEXT HANDOFF NOTE (Proposal 2, reassessed) ─────────────
1292
+ //
1293
+ // The CONTEXT already travels: one `thread` is kept across the
1294
+ // switch, so the replacement receives the ask, every tool call and
1295
+ // every result. What deliberately does NOT travel is the previous
1296
+ // model's `reasoningContent` (replaying a stranger's chain-of-
1297
+ // thought is either rejected outright or anchors the new model to
1298
+ // the failed reading of the task) — that stays dropped.
1299
+ //
1300
+ // What was missing is the plain STATEMENT of the handoff: a model
1301
+ // that starts mid-thread with no note reads the transcript as its
1302
+ // own and re-plans from the ask, re-running finished commands and
1303
+ // re-reading files whose results are already in front of it. The
1304
+ // note names the change, tells it the context is its own, and hands
1305
+ // it the facts (files changed, commands with their verdicts) so it
1306
+ // continues instead of restarting.
1307
+ let servedNow;
1308
+ try {
1309
+ const route = opts.servedRoute?.();
1310
+ if (route?.model && !isUnresolvedModel(route.model)) {
1311
+ servedNow = `${route.providerType}/${route.model}`;
1312
+ }
1313
+ }
1314
+ catch {
1315
+ // An unknown route is fine — the note reads generically then.
1316
+ }
1317
+ upsertHandoffNote(thread, buildHandoffNote({
1318
+ route: servedNow,
1319
+ facts: isWorkDigestEnabled(context.configManager)
1320
+ ? buildWorkDigest({
1321
+ successfulTools: progress.successfulToolCalls,
1322
+ mutatedPaths: progress.mutatedPaths,
1323
+ executedActions: progress.executedActions,
1324
+ })
1325
+ : '',
1326
+ }));
1327
+ deps.onEvent?.(' 🤝 handoff note written into the thread — the replacement model starts from the work already done.');
1291
1328
  // ── C5 — RE-FIT THE THREAD TO THE MODEL THAT NOW ANSWERS ──────
1292
1329
  // `budgetChars` was resolved before this loop started, from the pair
1293
1330
  // the turn BEGAN on — and the handoff worth catching is the one to a
@@ -3771,16 +3808,127 @@ export const DEFAULT_THREAD_BUDGET_CHARS = 200_000;
3771
3808
  const RECENT_KEEP = 6;
3772
3809
  /** Stub left in place of a trimmed tool result. */
3773
3810
  const TRIM_STUB = '[earlier tool result trimmed to fit the context budget]';
3811
+ /**
3812
+ * Floor for the per-message tool-result clamp (the tail clamp). A single tool
3813
+ * result may never exceed half the thread budget, so one oversized output cannot
3814
+ * dominate the prompt; this floor keeps the clamp sane for a tiny budget.
3815
+ */
3816
+ const MIN_TOOL_RESULT_CHARS = 8_000;
3817
+ /**
3818
+ * Bounded scan window for the clamp's error-line rescue. An elided middle can be
3819
+ * megabytes, and scanning all of it would cost more CPU than the prompt costs
3820
+ * tokens, so only the EDGES of the middle are searched. Nothing here is
3821
+ * unrecoverable: a clipped result is re-runnable (`run_terminal` again) or
3822
+ * re-readable (`read_file` with offset/limit), which the notice says out loud.
3823
+ */
3824
+ const CLAMP_SCAN_CHARS = 250_000;
3825
+ /** Cap on rescued error-looking lines, and on the chars they may add back. */
3826
+ const CLAMP_ERROR_LINES = 12;
3827
+ const CLAMP_ERROR_CHARS = 2_000;
3828
+ /**
3829
+ * A line that looks like the REASON something failed. Deliberately broad: one
3830
+ * extra line costs a few tokens, while dropping the only line that says WHY the
3831
+ * build broke costs a wrong fix built on a log the model never saw.
3832
+ */
3833
+ const ERROR_LINE_RE = /\b(?:error|errors|fail|failed|failing|failure|exception|panic|fatal|traceback|assert|assertion|expected|received|refused|denied|unhandled|cannot|unable|timeout|enoent|econnrefused)\b|\btimed out\b|\bexit(?:ed)?(?: with)?(?: code)? [1-9]\d*\b|[✗✘✕]/i;
3834
+ /** `5234567` → `5,234,567` (deterministic grouping — no locale/ICU dependence). */
3835
+ function withThousands(n) {
3836
+ return String(Math.max(0, Math.trunc(n))).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
3837
+ }
3774
3838
  /** Estimated character size of one thread message (chars/4 ≈ tokens). */
3775
3839
  function messageChars(m) {
3776
3840
  return (m.content?.length ?? 0) + (m.toolCalls?.length ? JSON.stringify(m.toolCalls).length : 0);
3777
3841
  }
3842
+ /**
3843
+ * Rescue the error-looking lines from the MIDDLE of a result that is about to be
3844
+ * clamped away. The clamp keeps head + tail, and a tool's verdict usually lands
3845
+ * in the tail — but the REASON for a failure (an assertion, a stack frame, `exit
3846
+ * code 1`) can sit in the middle, and a model that never sees it fixes the wrong
3847
+ * thing. Deterministic: a line filter, no LLM, no summary, no drift.
3848
+ */
3849
+ function errorLinesFrom(middle) {
3850
+ const regions = middle.length <= CLAMP_SCAN_CHARS * 2
3851
+ ? [middle]
3852
+ : [middle.slice(0, CLAMP_SCAN_CHARS), middle.slice(-CLAMP_SCAN_CHARS)];
3853
+ const out = [];
3854
+ let used = 0;
3855
+ for (const region of regions) {
3856
+ for (const raw of region.split('\n')) {
3857
+ const line = raw.trim();
3858
+ if (!line)
3859
+ continue;
3860
+ // NO length filter. A tool's output rarely ends on a newline, so the tail
3861
+ // cut lands MID-LINE and fuses the last real line with the kept tail —
3862
+ // MEASURED: a 38-char `AssertionError: 2 !== 3 (received 3)` arrived here
3863
+ // as 1,036 chars, and a `> 1000` skip dropped it, i.e. the rescue silently
3864
+ // lost exactly the line it exists to save. Long lines are kept by their
3865
+ // first 200 chars instead (an error keyword in a minified blob is still
3866
+ // the start of the reason).
3867
+ if (!ERROR_LINE_RE.test(line))
3868
+ continue;
3869
+ const kept = line.slice(0, 200);
3870
+ if (out.includes(kept))
3871
+ continue;
3872
+ if (used + kept.length > CLAMP_ERROR_CHARS)
3873
+ return out;
3874
+ out.push(kept);
3875
+ used += kept.length;
3876
+ if (out.length >= CLAMP_ERROR_LINES)
3877
+ return out;
3878
+ }
3879
+ }
3880
+ return out;
3881
+ }
3882
+ /**
3883
+ * The notice a clamp leaves behind: it names the tool, counts the elided
3884
+ * characters and says how to get them back. A model handed a SILENTLY partial
3885
+ * result cannot tell whether anything is missing; one handed a QUANTIFIED cut
3886
+ * can re-run the command or re-read the file — far cheaper than a fix built on a
3887
+ * log it never saw.
3888
+ */
3889
+ function clampNotice(tool, elided, errorLines) {
3890
+ const who = tool ? `${tool}: ` : '';
3891
+ const rescued = errorLines.length > 0 ? '; the error-looking lines from the elided middle are kept below' : '';
3892
+ return (`\n[tool result trimmed to fit the context budget — ${who}${withThousands(elided)} chars elided ` +
3893
+ `from the middle${rescued}. The beginning and the end are kept verbatim; re-run the command, or ` +
3894
+ `read the file again with offset/limit, to see the rest.]\n` +
3895
+ (errorLines.length > 0 ? `${errorLines.join('\n')}\n` : ''));
3896
+ }
3897
+ /**
3898
+ * Clamp one oversized tool result to `cap` chars, keeping its HEAD and TAIL so
3899
+ * the model still sees which tool ran and how its output ended, plus any
3900
+ * error-looking lines from the elided middle. Deterministic — no summary, no
3901
+ * model call. The result never exceeds `cap`: the head absorbs what the notice
3902
+ * and the rescued lines do not use.
3903
+ */
3904
+ function clampToolResult(content, cap, tool) {
3905
+ if (content.length <= cap)
3906
+ return content;
3907
+ const tailLen = Math.min(1_000, Math.floor(cap / 4));
3908
+ const tailStart = Math.max(0, content.length - tailLen);
3909
+ const middle = content.slice(0, tailStart);
3910
+ const errors = errorLinesFrom(middle);
3911
+ // Sized with the LARGEST possible elided count, so the exact (smaller) notice
3912
+ // that follows can never push the result past `cap`.
3913
+ const headLen = Math.max(0, cap - tailLen - clampNotice(tool, middle.length, errors).length);
3914
+ const head = content.slice(0, headLen);
3915
+ return head + clampNotice(tool, Math.max(0, middle.length - headLen), errors) + content.slice(tailStart);
3916
+ }
3778
3917
  /**
3779
3918
  * Deterministically trim a thread to `maxChars`:
3780
3919
  * 1. Never touch the system prompt or the FIRST user message (the ask).
3781
- * 2. Never touch the last `RECENT_KEEP` messages (recent context).
3782
- * 3. Oldest-first: tool results longer than 500 chars collapse to the stub;
3783
- * if still over budget, remaining old tool results collapse entirely.
3920
+ * 2. Never touch the last `RECENT_KEEP` messages (recent context) — except for
3921
+ * the tail clamps in steps 4–5, which run ONLY when the oldest-first passes
3922
+ * could not pay for the overage.
3923
+ * 3. Oldest-first pays FIRST, and only as much as the deficit needs: tool
3924
+ * results longer than 500 chars collapse to the stub; if still over budget,
3925
+ * remaining old tool results collapse entirely; then oversized old user
3926
+ * messages shrink.
3927
+ * 4. Only if the thread is STILL over does the protected tail pay: an oversized
3928
+ * recent tool result is clamped to head + rescued error lines + tail, and
3929
+ * then clamped harder, so the prompt actually fits the window it goes to.
3930
+ * The ORDER is what protects delivery: recent context is the model's working
3931
+ * memory, so it is spent only when nothing older can cover the overage.
3784
3932
  * Returns a NEW array (input untouched) + how many messages were trimmed.
3785
3933
  */
3786
3934
  export function trimThreadBudget(thread, maxChars = DEFAULT_THREAD_BUDGET_CHARS) {
@@ -3801,6 +3949,9 @@ export function trimThreadBudget(thread, maxChars = DEFAULT_THREAD_BUDGET_CHARS)
3801
3949
  }
3802
3950
  let over = total - maxChars;
3803
3951
  let trimmed = 0;
3952
+ // A single result may never exceed half the budget, whatever the passes below
3953
+ // do (see MIN_TOOL_RESULT_CHARS).
3954
+ const perMessageCap = Math.max(MIN_TOOL_RESULT_CHARS, Math.floor(maxChars / 2));
3804
3955
  // Pass 1: collapse long OLD tool results to the stub (keep the first 500
3805
3956
  // chars so the model retains the gist of what it did).
3806
3957
  for (const i of eligible) {
@@ -3848,6 +3999,66 @@ export function trimThreadBudget(thread, maxChars = DEFAULT_THREAD_BUDGET_CHARS)
3848
3999
  trimmed++;
3849
4000
  }
3850
4001
  }
4002
+ // ── Pass 4 — only NOW does the PROTECTED TAIL pay ─────────────────────────
4003
+ // Nothing older could cover the deficit, so an oversized RECENT tool result
4004
+ // must be clamped — otherwise the prompt goes out verbatim and either the
4005
+ // provider rejects it or the model silently loses its middle.
4006
+ //
4007
+ // MEASURED (trace-1791879575576-x731yp): step 4 ran a 24s test command; its
4008
+ // result landed in the tail, the oldest-first passes could not reach it, and
4009
+ // step 5 — handed to `local/qwen2.5:0.5b` (32K window) — recorded 5,292,237
4010
+ // context chars (~1.18M tokens), carried into the dashboard and cost ledger
4011
+ // as REAL input. Running this pass here (rather than before the oldest-first
4012
+ // passes) is deliberate: recent context is the model's working memory, so it
4013
+ // is spent only when older output cannot pay for the overage.
4014
+ // A tool message carries only the call ID, so the notice's tool name comes
4015
+ // from the assistant message that made the call. Built lazily: a turn whose
4016
+ // thread fits never walks the thread for names it will not print.
4017
+ const toolNameById = new Map();
4018
+ const toolNameOf = (m) => {
4019
+ if (!m.toolCallId)
4020
+ return undefined;
4021
+ if (toolNameById.size === 0) {
4022
+ for (const t of thread) {
4023
+ for (const call of t.toolCalls ?? []) {
4024
+ if (call?.id)
4025
+ toolNameById.set(call.id, call.name);
4026
+ }
4027
+ }
4028
+ }
4029
+ return toolNameById.get(m.toolCallId);
4030
+ };
4031
+ if (over > 0) {
4032
+ for (let i = Math.max(0, out.length - RECENT_KEEP); i < out.length && over > 0; i++) {
4033
+ const m = out[i];
4034
+ if (m.role !== 'tool' || m.content.length <= perMessageCap)
4035
+ continue;
4036
+ const clamped = clampToolResult(m.content, perMessageCap, toolNameOf(m));
4037
+ if (clamped.length >= m.content.length)
4038
+ continue;
4039
+ out[i] = { ...m, content: clamped };
4040
+ over -= m.content.length - clamped.length;
4041
+ trimmed++;
4042
+ }
4043
+ }
4044
+ // Pass 5: STILL over — the protected tail holds the bulk even after the clamp
4045
+ // above; clamp its tool results harder rather than ship a prompt the model's
4046
+ // window cannot hold. Only TOOL results in the tail are touched — the user's
4047
+ // ask and the latest assistant turn stay.
4048
+ if (over > 0) {
4049
+ const tailFloor = Math.max(500, Math.floor(perMessageCap / 4));
4050
+ for (let i = Math.max(0, out.length - RECENT_KEEP); i < out.length && over > 0; i++) {
4051
+ const m = out[i];
4052
+ if (m.role !== 'tool')
4053
+ continue;
4054
+ const clamped = clampToolResult(m.content, tailFloor, toolNameOf(m));
4055
+ if (clamped.length >= m.content.length)
4056
+ continue;
4057
+ out[i] = { ...m, content: clamped };
4058
+ over -= m.content.length - clamped.length;
4059
+ trimmed++;
4060
+ }
4061
+ }
3851
4062
  return { thread: out, trimmed };
3852
4063
  }
3853
4064
  // ─── Within-turn work digest (the memory a trimmed thread keeps) ────────────
@@ -3895,6 +4106,51 @@ export function buildWorkDigest(input) {
3895
4106
  return '';
3896
4107
  return `${WORK_DIGEST_MARKER}\n${lines.join('\n')}`;
3897
4108
  }
4109
+ /** Marker prefix identifying the loop's mid-turn HANDOFF note. */
4110
+ export const HANDOFF_NOTE_MARKER = '[handoff — the model serving this turn changed]';
4111
+ /**
4112
+ * The note a mid-turn model switch leaves in the thread.
4113
+ *
4114
+ * It says three things the TRANSCRIPT cannot say by itself: that the pair
4115
+ * answering this step is not the pair that answered the previous ones, that the
4116
+ * context above is genuinely this model's to use (nothing was restarted), and
4117
+ * which work is already DONE (files changed, commands and their verdicts) — so
4118
+ * the replacement continues instead of re-deriving a plan from the ask. It also
4119
+ * states the rule that costs real steps when broken: do not re-run finished
4120
+ * commands or restate the work in more words.
4121
+ *
4122
+ * Deterministic and LLM-free, like the digest it borrows its facts from — a
4123
+ * handoff must not spend a model call to describe itself.
4124
+ */
4125
+ export function buildHandoffNote(input) {
4126
+ const served = input.route
4127
+ ? ` This step is served by ${input.route}.`
4128
+ : ' This step is served by a different model.';
4129
+ const facts = (input.facts ?? '').trim();
4130
+ return (`${HANDOFF_NOTE_MARKER}${served}\n` +
4131
+ 'The pair that had been answering returned nothing usable, so the turn was handed to you mid-flight —\n' +
4132
+ 'everything above is YOUR context: the ask, every tool call and every result. Nothing was restarted.\n' +
4133
+ (facts ? `${facts}\n` : '') +
4134
+ 'Continue from the work that is already done. Do not re-run finished commands, re-read files whose results\n' +
4135
+ 'are above, or restate the work in more words.');
4136
+ }
4137
+ /**
4138
+ * Insert or refresh the single handoff note. Idempotent — a turn may hand off
4139
+ * more than once (a second pair can also answer with nothing), and stacking a
4140
+ * note per handoff would fill the thread with the same information. Kept with
4141
+ * the run's framing (right after the leading system prompt) so it is a `system`
4142
+ * message: the thread-budget passes never trim one, and it therefore survives
4143
+ * every compaction between the handoff and the answer.
4144
+ */
4145
+ export function upsertHandoffNote(thread, note) {
4146
+ const existing = thread.findIndex((m) => m.content.startsWith(HANDOFF_NOTE_MARKER));
4147
+ if (existing !== -1) {
4148
+ thread[existing] = { ...thread[existing], content: note };
4149
+ return;
4150
+ }
4151
+ const insertAt = thread.length > 0 && thread[0].role === 'system' ? 1 : 0;
4152
+ thread.splice(insertAt, 0, { role: 'system', content: note });
4153
+ }
3898
4154
  /**
3899
4155
  * Insert or refresh the single work-digest message. Idempotent: a digest already
3900
4156
  * in the thread is UPDATED in place, never stacked, so repeated compaction in a