@aragon-agent/cli 0.5.8 → 0.5.9
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.
- package/CHANGELOG.md +279 -0
- package/README.md +1429 -1163
- package/dist/agent/coalesce.d.ts +13 -0
- package/dist/agent/coalesce.js +50 -11
- package/dist/agent/controller.d.ts +141 -2
- package/dist/agent/controller.js +396 -4
- package/dist/agent/headless.d.ts +8 -0
- package/dist/agent/headless.js +40 -0
- package/dist/agent/reducer.d.ts +245 -3
- package/dist/agent/reducer.js +490 -17
- package/dist/agent/retry-view.d.ts +68 -0
- package/dist/agent/retry-view.js +95 -0
- package/dist/agent/system-prompt.d.ts +11 -0
- package/dist/agent/system-prompt.js +2 -0
- package/dist/cli.js +86 -2
- package/dist/commands/builtins.d.ts +1 -1
- package/dist/commands/builtins.js +308 -2
- package/dist/config/cli-commands.d.ts +53 -2
- package/dist/config/cli-commands.js +136 -3
- package/dist/config/env.d.ts +6 -3
- package/dist/config/env.js +103 -3
- package/dist/config/load.d.ts +49 -0
- package/dist/config/load.js +83 -1
- package/dist/config/schema.d.ts +212 -2
- package/dist/config/schema.js +207 -1
- package/dist/config/store.js +20 -1
- package/dist/fast/critique.d.ts +43 -0
- package/dist/fast/critique.js +62 -0
- package/dist/fast/digest.d.ts +42 -0
- package/dist/fast/digest.js +85 -0
- package/dist/fast/frames.d.ts +99 -0
- package/dist/fast/frames.js +180 -0
- package/dist/fast/limits.d.ts +98 -0
- package/dist/fast/limits.js +98 -0
- package/dist/fast/prompt.d.ts +72 -0
- package/dist/fast/prompt.js +94 -0
- package/dist/fast/resolve.d.ts +43 -0
- package/dist/fast/resolve.js +105 -0
- package/dist/fast/review-call.d.ts +99 -0
- package/dist/fast/review-call.js +130 -0
- package/dist/fast/reviewer.d.ts +248 -0
- package/dist/fast/reviewer.js +664 -0
- package/dist/fast/types.d.ts +128 -0
- package/dist/fast/types.js +14 -0
- package/dist/fast/wiring.d.ts +170 -0
- package/dist/fast/wiring.js +316 -0
- package/dist/logging/install.d.ts +15 -1
- package/dist/logging/install.js +37 -4
- package/dist/logging/logger.d.ts +1 -1
- package/dist/session/persist.js +57 -1
- package/dist/team/normalize.d.ts +26 -1
- package/dist/team/normalize.js +23 -3
- package/dist/team/prompt.d.ts +11 -0
- package/dist/team/prompt.js +10 -0
- package/dist/team/report.d.ts +18 -0
- package/dist/team/report.js +27 -1
- package/dist/team/runtime.d.ts +13 -2
- package/dist/team/runtime.js +33 -6
- package/dist/team/subagent.d.ts +19 -1
- package/dist/team/subagent.js +72 -10
- package/dist/team/task-tool.d.ts +26 -0
- package/dist/team/task-tool.js +48 -4
- package/dist/team/types.d.ts +80 -1
- package/dist/tools/bash-tool.js +19 -3
- package/dist/tools/diff.d.ts +25 -5
- package/dist/tools/diff.js +72 -41
- package/dist/tools/file-change-store.d.ts +34 -0
- package/dist/tools/file-change-store.js +57 -0
- package/dist/tools/fs-tools.d.ts +26 -0
- package/dist/tools/fs-tools.js +62 -5
- package/dist/tools/index.d.ts +31 -0
- package/dist/tools/index.js +7 -1
- package/dist/tools/patch.d.ts +115 -0
- package/dist/tools/patch.js +453 -0
- package/dist/tools/terminal-output.d.ts +107 -0
- package/dist/tools/terminal-output.js +198 -0
- package/dist/tools/tool-output-store.d.ts +68 -0
- package/dist/tools/tool-output-store.js +102 -0
- package/dist/ui/ActivityLine.d.ts +48 -0
- package/dist/ui/ActivityLine.js +22 -0
- package/dist/ui/App.d.ts +1 -4
- package/dist/ui/App.js +273 -37
- package/dist/ui/BottomStatusRow.d.ts +43 -0
- package/dist/ui/BottomStatusRow.js +14 -0
- package/dist/ui/Composer.d.ts +1 -6
- package/dist/ui/Composer.js +2 -2
- package/dist/ui/PromptInput.d.ts +1 -15
- package/dist/ui/PromptInput.js +1 -38
- package/dist/ui/StatusBar.d.ts +37 -0
- package/dist/ui/StatusBar.js +5 -3
- package/dist/ui/TeamPanel.d.ts +5 -4
- package/dist/ui/TeamPanel.js +1 -1
- package/dist/ui/TodoPanel.d.ts +5 -4
- package/dist/ui/Transcript.d.ts +26 -3
- package/dist/ui/Transcript.js +76 -10
- package/dist/ui/activity-phrases.d.ts +33 -0
- package/dist/ui/activity-phrases.js +50 -0
- package/dist/ui/entries/AssistantEntry.d.ts +20 -0
- package/dist/ui/entries/AssistantEntry.js +3 -2
- package/dist/ui/entries/DiffView.d.ts +67 -0
- package/dist/ui/entries/DiffView.js +103 -0
- package/dist/ui/entries/FastCard.d.ts +53 -0
- package/dist/ui/entries/FastCard.js +87 -0
- package/dist/ui/entries/RetryCard.d.ts +56 -0
- package/dist/ui/entries/RetryCard.js +60 -0
- package/dist/ui/entries/TeamCard.js +6 -1
- package/dist/ui/entries/ToolCard.d.ts +38 -1
- package/dist/ui/entries/ToolCard.js +68 -5
- package/dist/ui/glyphs.d.ts +9 -0
- package/dist/ui/glyphs.js +2 -0
- package/dist/ui/layout/AppShell.d.ts +13 -22
- package/dist/ui/layout/AppShell.js +3 -38
- package/dist/ui/layout/virtual-window.d.ts +1 -1
- package/dist/ui/layout/virtual-window.js +109 -5
- package/dist/ui/overlays/HelpOverlay.js +16 -2
- package/dist/ui/overlays/SettingsScreen.d.ts +82 -1
- package/dist/ui/overlays/SettingsScreen.js +147 -1
- package/dist/ui/transcript-text.js +27 -0
- package/dist/ui/use-wheel-routing.d.ts +16 -32
- package/dist/ui/use-wheel-routing.js +21 -38
- package/package.json +2 -2
- package/dist/ui/layout/regions.d.ts +0 -55
- package/dist/ui/layout/regions.js +0 -52
package/CHANGELOG.md
CHANGED
|
@@ -7,8 +7,147 @@ were written.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **A running command shows what it is doing.** `bash` is the only tool here that
|
|
13
|
+
can run for minutes — `npm test`, a `git clone`, a training job — and while it
|
|
14
|
+
ran, its card was one line of text that never changed. Nothing in that frame
|
|
15
|
+
distinguished a test suite at 40% from a child process blocked forever on a
|
|
16
|
+
password prompt this CLI will never show. Its card now carries the last eight
|
|
17
|
+
lines of what the command is printing, plus one footer row that reads
|
|
18
|
+
`(running)` or, once the child has been quiet for ten seconds,
|
|
19
|
+
`no output for 45s` — with the seconds advancing.
|
|
20
|
+
|
|
21
|
+
A `\r`-driven progress bar (npm, pip, curl, docker) is *one* line rewritten a
|
|
22
|
+
thousand times, and it renders as **one row counting up in place** rather than
|
|
23
|
+
a thousand rows of nearly the same string — including the ordinary case where
|
|
24
|
+
the bar emits no newline at all for its entire run.
|
|
25
|
+
|
|
26
|
+
Everything the tail shows is **stripped, not interpreted**: ANSI colour, cursor
|
|
27
|
+
motion, `\r`, `\b`, tabs and every other control byte are removed at the
|
|
28
|
+
boundary before a row is stored, so nothing can move a cursor inside a frame
|
|
29
|
+
the renderer believes it owns. It is bounded twice by construction — eight rows
|
|
30
|
+
per call, sixteen concurrent calls — so a command that writes 400 MB to stdout
|
|
31
|
+
costs a fixed number of retained rows.
|
|
32
|
+
|
|
33
|
+
It is a **display and nothing else**. The text the model receives is
|
|
34
|
+
byte-for-byte what it was; `Ctrl+O` does nothing while a command runs, because
|
|
35
|
+
expansion is a promise about stored content and there is no stored rest of a
|
|
36
|
+
400 MB stream; `/save` during a run writes no tail, since a resumed one would
|
|
37
|
+
describe a process that died with the session; and at settle the card is
|
|
38
|
+
replaced by the authoritative result exactly as before.
|
|
39
|
+
|
|
40
|
+
New config key `liveToolOutput`, defaulting to **`true`** — unlike
|
|
41
|
+
`showThinking` below, this adds information rather than hiding it.
|
|
42
|
+
`aragon config set liveToolOutput false` (or `--no-live-tool-output`, or
|
|
43
|
+
`ARAGON_LIVE_TOOL_OUTPUT=0`, or the **Live output** row in `/settings`) turns it
|
|
44
|
+
off, and with it off no store is allocated and no recorder is attached: `bash`
|
|
45
|
+
is byte-identical to the build before this entry.
|
|
46
|
+
|
|
47
|
+
- **The working line stops guessing while a tool runs.** It reads
|
|
48
|
+
`⠙ Running bash` instead of rotating thinking-words. `running` covers the whole
|
|
49
|
+
turn, including the minutes the model is idle and a child process is doing the
|
|
50
|
+
work, so "Pondering" during a build was not calm — it was wrong. One row, no
|
|
51
|
+
digits, no clock: everything the row already promised still holds.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- **Reasoning blocks are now hidden by default.** `showThinking` is a new
|
|
56
|
+
top-level config key and it defaults to `false`. If you have been reading
|
|
57
|
+
thinking every day, this is the entry that concerns you: `Ctrl+T` still shows
|
|
58
|
+
it for the session exactly as before, `aragon config set showThinking true`
|
|
59
|
+
(or `--show-thinking`, or `ARAGON_SHOW_THINKING=1`) restores the old behaviour
|
|
60
|
+
permanently, and `/settings` has a **Show thinking** row directly under
|
|
61
|
+
**Thinking**.
|
|
62
|
+
|
|
63
|
+
Nothing is hidden silently. A settled turn that thought leaves one muted row
|
|
64
|
+
where the block used to be — `✱ thought for 12s · ctrl+t to show` — so the fact
|
|
65
|
+
that reasoning happened, how long it took, and how to see it are all still on
|
|
66
|
+
screen. In **inline** mode that row omits the key hint and the toast reads
|
|
67
|
+
`Thinking shown for new output.`, because a settled entry there has already
|
|
68
|
+
been printed into your terminal's scrollback and cannot be repainted; the
|
|
69
|
+
toggle applies to the live entry and to everything drawn after it.
|
|
70
|
+
|
|
71
|
+
`thinkingLevel` is untouched and means what it always did — the effort the
|
|
72
|
+
provider is asked to spend. `showThinking` is only whether the terminal draws
|
|
73
|
+
what came back. They are one word apart in the config file, which is why the
|
|
74
|
+
flag is `--show-thinking` rather than the shorter name.
|
|
75
|
+
|
|
76
|
+
### Added
|
|
77
|
+
|
|
78
|
+
- **A live working line while a run is in flight.** One row above the composer,
|
|
79
|
+
carrying a spinner and a word that rotates every four seconds:
|
|
80
|
+
`⠋ Percolating…`. Take reasoning off the screen and the gap between submitting
|
|
81
|
+
and the first token is otherwise completely blank, which reads as dead rather
|
|
82
|
+
than as busy — the two changes are one change.
|
|
83
|
+
|
|
84
|
+
It carries no clock and no token count, deliberately: the status bar one row
|
|
85
|
+
below already renders both, under the same running condition and driven by the
|
|
86
|
+
same 200 ms ticker this row reuses. Under `reducedMotion` the spinner is a
|
|
87
|
+
static glyph and the word is chosen once and holds, because rotating text is
|
|
88
|
+
motion too. An idle frame is unchanged, and so is the viewport's row budget —
|
|
89
|
+
the line shares the row the toast strip already owned rather than adding one.
|
|
90
|
+
|
|
91
|
+
- **`write_file` and `edit_file` render a real diff.** Hunks with old/new line
|
|
92
|
+
numbers, a `+N -M` summary, add/remove/context colouring, and `(truncated)` or
|
|
93
|
+
a `binary` / `too-large` / `unreadable` note when the old side could not be
|
|
94
|
+
read. Diffs collapse at 12 rows behind the existing `Ctrl+O` — no new
|
|
95
|
+
keybinding. A resumed session written by an older build, or a card whose patch
|
|
96
|
+
the bounded store already evicted, falls back to the previous text preview;
|
|
97
|
+
nothing renders blank.
|
|
98
|
+
|
|
99
|
+
`write_file` previously reported creating a 300-line file as
|
|
100
|
+
`Wrote 8214 bytes to path`, and `edit_file`'s diff trimmed the common prefix
|
|
101
|
+
and suffix and rendered *everything* in between as one removed block followed
|
|
102
|
+
by one added block — for a `replace_all` touching line 40 and line 900, that
|
|
103
|
+
was 860 removed rows followed by 860 nearly identical added ones.
|
|
104
|
+
|
|
105
|
+
**The model's input got smaller, not larger.** The structured patch reaches the
|
|
106
|
+
screen on a CLI-local channel rather than through the tool result, and the text
|
|
107
|
+
the model reads gained a 4 000-character ceiling it did not have before (its
|
|
108
|
+
only previous bound was the executor's 100 KB backstop). A single-region edit
|
|
109
|
+
is byte-for-byte what it was plus one `@@` header; a multi-region edit is
|
|
110
|
+
strictly smaller. `write_file`'s result text is unchanged.
|
|
111
|
+
|
|
10
112
|
### Changed
|
|
11
113
|
|
|
114
|
+
- **A stream that stops mid-answer is now a loud failure instead of a silent
|
|
115
|
+
truncated one.** All three provider adapters used to end their SSE loop by
|
|
116
|
+
yielding "done" with whatever had arrived, so a connection closed cleanly
|
|
117
|
+
half-way through an answer — a proxy idle cut, a load-balancer timeout, an
|
|
118
|
+
HTTP/2 GOAWAY — was indistinguishable from a completed reply. You got a
|
|
119
|
+
truncated answer and were told nothing.
|
|
120
|
+
|
|
121
|
+
Each adapter now reports the truncation, which is what lets it be retried and
|
|
122
|
+
recovered. An **abort** is explicitly excluded and still completes normally, and
|
|
123
|
+
a model that legitimately says nothing and stops is still a success.
|
|
124
|
+
|
|
125
|
+
This is deliberately **not** behind `--no-retry`: an adapter that reports a
|
|
126
|
+
truncated stream honestly should do so whether or not retry is enabled. A switch
|
|
127
|
+
that also disabled telling you the truth would be a mute button, not a kill
|
|
128
|
+
switch.
|
|
129
|
+
|
|
130
|
+
- **The mouse wheel now only ever scrolls.** A notch scrolls the transcript
|
|
131
|
+
three rows (a page with `Shift`), or the open overlay when there is one, no
|
|
132
|
+
matter where the pointer is sitting. Prompt history is recalled by `↑` / `↓`
|
|
133
|
+
alone, exactly as in Claude Code and Codex.
|
|
134
|
+
|
|
135
|
+
**This supersedes the 0.5.0 entry below**, which said the wheel "scrolls what
|
|
136
|
+
is under the pointer" and stepped prompt history one entry per notch when the
|
|
137
|
+
pointer was over the input box. That turned out to be wrong in use rather than
|
|
138
|
+
in principle: the pointer is not an instrument you aim in a TUI — it rests
|
|
139
|
+
wherever you last left it, which in a chat-shaped app is next to the thing you
|
|
140
|
+
type into. So the ordinary "scroll back and see what just happened" gesture
|
|
141
|
+
landed on the composer and replaced the draft with an old prompt, with no
|
|
142
|
+
error, no undo and nothing visibly connecting the gesture to the outcome. The
|
|
143
|
+
band that decided this was invisible too: its boundary was a measured row that
|
|
144
|
+
moved as the toast row, the hint row and the completion popup came and went, so
|
|
145
|
+
the same gesture could do two different things a second apart.
|
|
146
|
+
|
|
147
|
+
Nothing else about the wheel changes — same three rows per notch, same
|
|
148
|
+
`Shift`+wheel page, same `--no-mouse` / `ARAGON_MOUSE=0` / `mouse: false`
|
|
149
|
+
escape hatches, same `Shift`+drag for selecting text.
|
|
150
|
+
|
|
12
151
|
- **A long session stays as fast as a short one.** The TUI used to get slower as
|
|
13
152
|
a session grew and, past a threshold, stopped making progress at all. That was
|
|
14
153
|
structural rather than incidental: Ink has no output caching, so every frame
|
|
@@ -68,6 +207,146 @@ were written.
|
|
|
68
207
|
|
|
69
208
|
### Added
|
|
70
209
|
|
|
210
|
+
- **A fast model tier: a second, cheaper model you can delegate to and be
|
|
211
|
+
reviewed by.** Off by default — with `fast.enabled: false` the system prompt,
|
|
212
|
+
the `task` schema, the transcript and the request payloads are byte-identical
|
|
213
|
+
to a build without it — and it does two things once you turn it on.
|
|
214
|
+
|
|
215
|
+
**Delegation.** `task` gains one optional field per subagent, `model: "fast"`.
|
|
216
|
+
A child marked that way runs on the fast model and is otherwise identical:
|
|
217
|
+
same tools, same working directory, same `--confirm` gate, same plan-mode
|
|
218
|
+
gate, same skills ceiling. Delegating to a cheaper model is a *model* choice,
|
|
219
|
+
never a permission boundary. It is where "not complicated, but very expensive
|
|
220
|
+
in context" gets paid for — a child that reads nine files and reports four
|
|
221
|
+
sentences moves the file bodies out of the lead's window and onto a model that
|
|
222
|
+
costs a fraction as much per token.
|
|
223
|
+
|
|
224
|
+
**Periodic review.** Every few turns a small digest of what the lead has been
|
|
225
|
+
doing goes to the fast model with one question — is this still on track? — and
|
|
226
|
+
a critique that is not "on track" is injected into the running loop as a
|
|
227
|
+
`<fast_review>` block, so the lead sees a second opinion while it can still
|
|
228
|
+
act on it:
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
fast review #2 · claude-haiku-4-5 · turn 12 · 1.4s
|
|
232
|
+
You have edited config/schema.ts three times without running the tests.
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The digest is built from a bounded ring of recent turns and **never** from the
|
|
236
|
+
message history: sending a session's accumulated file bodies to the "cheap"
|
|
237
|
+
model would make a review cost more than the turn it reviews, which is the
|
|
238
|
+
inversion the whole feature exists to prevent.
|
|
239
|
+
|
|
240
|
+
Spend is attributed **per tier** — a fast child's tokens are priced at the
|
|
241
|
+
fast model's table, not the lead's, and the dispatch report states the two
|
|
242
|
+
separately. A model the built-in price table has never seen is reported as
|
|
243
|
+
`unknown` rather than as `$0.00`, because a feature that looks free while it
|
|
244
|
+
is spending money is worse than one that admits it does not know.
|
|
245
|
+
|
|
246
|
+
Turn it on with `/fast model <id>` then `/fast on`, with
|
|
247
|
+
`aragon config set fast.enabled true`, with `--fast --fast-model <id>`, or with
|
|
248
|
+
`ARAGON_FAST=1 ARAGON_FAST_MODEL=<id>`. `/fast status` is the guaranteed
|
|
249
|
+
readout: the resolved model, the budget, and this session's reviews, delegated
|
|
250
|
+
children, tokens and cost. Eleven `fast.*` config keys, four flags, four
|
|
251
|
+
environment variables and five settings-screen rows; see the README.
|
|
252
|
+
|
|
253
|
+
**The review has a session budget.** A session is not one run — it is one run
|
|
254
|
+
per message you send — so a cadence bounds the pace and nothing bounds the
|
|
255
|
+
total. `fast.reviewMaxPerSession` (default **40**, raisable live with
|
|
256
|
+
`/fast budget <n>`) is the number of reviews a session may *start*; reaching it
|
|
257
|
+
prints one `info` notice that names the remedy and says delegation is
|
|
258
|
+
unaffected, and `/fast status` reads `12/40` from the first review rather than a
|
|
259
|
+
bare count you can only size after the fact. It is denominated in **reviews,
|
|
260
|
+
not currency**, because the fast tier is exactly where a model the price table
|
|
261
|
+
has never seen lives — a dollar ceiling would silently never fire for the
|
|
262
|
+
configuration that most needs one. Delegation is never budgeted: it is spend the
|
|
263
|
+
lead chose in service of a message you sent, it is already bounded by `team.*`,
|
|
264
|
+
and it exists to *reduce* total cost.
|
|
265
|
+
|
|
266
|
+
**The review also fails fast, so it cannot compete with you.** It calls through
|
|
267
|
+
its own provider registry with **one** retry rather than the ten
|
|
268
|
+
`retry.maxRetries` defaults to for the lead, and it observes neither `retry.*`
|
|
269
|
+
nor `/retry` — that policy says how hard to fight for *your* answer, and
|
|
270
|
+
inheriting it for an unrequested background call is how an advisory ends up
|
|
271
|
+
spending a rate-limited provider's quota on itself. Its own wall-clock bound
|
|
272
|
+
is 20 s.
|
|
273
|
+
|
|
274
|
+
Two failure modes are handled out loud rather than silently. If the tier stops
|
|
275
|
+
resolving mid-session — you switch the main provider and `fast.provider` was
|
|
276
|
+
inheriting it — `model:"fast"` is downgraded to the main model, **counted, and
|
|
277
|
+
stated in the report**, because an agent that silently gets an expensive child
|
|
278
|
+
has no way to learn its cost model is wrong. And three consecutive
|
|
279
|
+
*misconfiguration* failures disable the reviewer for the session with exactly
|
|
280
|
+
one warning, while a merely busy provider (rate-limited or overloaded) is
|
|
281
|
+
treated as transient and never counts — that condition fixes itself, and a
|
|
282
|
+
session-long silent shutdown over it would not. A review you *cancelled* is
|
|
283
|
+
neither: Esc, a run that ends first, or quitting leaves a `cancelled` card and
|
|
284
|
+
no strike against the tier.
|
|
285
|
+
|
|
286
|
+
Reviews log under their own `fast` scope rather than under `agent`, so
|
|
287
|
+
`fast_review_*` records filter cleanly away from the lead's.
|
|
288
|
+
|
|
289
|
+
- **API calls are retried with backoff, and the waiting is legible.** A transient
|
|
290
|
+
provider failure — HTTP 429, 529, 5xx, 408, or a dropped connection — used to end
|
|
291
|
+
the turn. One red notice, an idle prompt, and forty tool calls of work thrown
|
|
292
|
+
away. It is now retried up to **10 times** with an increasing interval
|
|
293
|
+
(1 s → 2 → 4 → 8 → 16 → 30 s, equal-jittered, 30 s per wait at most) under a
|
|
294
|
+
4-minute budget measured from the first failure.
|
|
295
|
+
|
|
296
|
+
What you see while it waits is **one line, rewritten in place** — never ten
|
|
297
|
+
notices — carrying what failed, which attempt this is, and a countdown to the
|
|
298
|
+
next one:
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
↻ Provider overloaded · retry 3/10 in 7s Esc to cancel
|
|
302
|
+
↻ recovered after 3 retries · 12.4s
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
plus a `retry 3/10 7s` chip on the status bar (`[r3]` on a narrow terminal). The
|
|
306
|
+
card settles into the transcript as history — `recovered`, `gave up`, or
|
|
307
|
+
`interrupted` — and shows up in the exit replay, because a turn that spent three
|
|
308
|
+
minutes retrying is exactly the kind of cost an exported transcript should
|
|
309
|
+
account for.
|
|
310
|
+
|
|
311
|
+
**Esc ends the wait within a frame**, not at the end of the countdown, and it
|
|
312
|
+
never produces a fabricated error: an aborted request is silent. That is the one
|
|
313
|
+
detail everything else here depends on, because the provider layer marks an
|
|
314
|
+
`AbortError` as retryable — so the signal is checked *before* the error, and a
|
|
315
|
+
user pressing Esc can never be mistaken for a timeout worth retrying.
|
|
316
|
+
|
|
317
|
+
Never retried: `auth_error` (401/403), `invalid_request`, `context_overflow`.
|
|
318
|
+
Ten retries of a bad API key is three minutes of looking broken.
|
|
319
|
+
|
|
320
|
+
`Retry-After` is honoured as a **floor**, never a replacement — a `Retry-After: 1`
|
|
321
|
+
on the ninth retry does not undo eight retries of backoff — and a stated wait
|
|
322
|
+
longer than a minute is surfaced immediately with the provider's own number
|
|
323
|
+
rather than silently wedging the terminal.
|
|
324
|
+
|
|
325
|
+
A connection that dies **mid-answer** is also covered, and this is the case that
|
|
326
|
+
needed more than a retry loop: the partial text is discarded, the affected tool
|
|
327
|
+
cards are removed, and the answer restarts from the top. Nothing is duplicated,
|
|
328
|
+
because the engine only writes history on a completed turn.
|
|
329
|
+
|
|
330
|
+
- **`/retry [show|on|off|max <n>]`, `--retry` / `--no-retry`, `--retry-max <n>`,
|
|
331
|
+
`ARAGON_RETRY`, `ARAGON_RETRY_MAX`, and a `retry` config section** with nine
|
|
332
|
+
keys (`aragon config set retry.*`). `/retry off` takes effect **in the running
|
|
333
|
+
session** — subagents included, since they share the lead's provider registry —
|
|
334
|
+
not only at the next launch. `retry.maxRetries: 0` is the kill switch and is a
|
|
335
|
+
real value at every one of those entry points. `/settings` gains one read-only
|
|
336
|
+
`API retries` row.
|
|
337
|
+
|
|
338
|
+
- **A subagent's retry is visible on the team card.** A child in backoff reports
|
|
339
|
+
`retry 3/10` on its own row. Children inherit the retry policy for free, but
|
|
340
|
+
their events never reach the lead's view, so without this a subagent spending
|
|
341
|
+
three minutes waiting looked exactly like a hung dispatch.
|
|
342
|
+
|
|
343
|
+
- **Retry lines in `-p` mode go to stderr, never stdout.** `[retry 3/10]
|
|
344
|
+
overloaded — waiting 7s` and `[retry] recovered after 3 retries` are on stderr,
|
|
345
|
+
so `aragon -p … | jq` stays valid; a discarded partial answer is announced there
|
|
346
|
+
too, because a piped consumer otherwise cannot tell a replay from a model that
|
|
347
|
+
repeated itself. They are not suppressed by `--quiet`: a three-minute pause with
|
|
348
|
+
no explanation is not a compact run, it is a hang.
|
|
349
|
+
|
|
71
350
|
- **`/perf`.** Reports what the renderer is actually doing: the frame interval
|
|
72
351
|
and the last commit cost, how many entries exist / are retained / were dropped
|
|
73
352
|
/ are mounted, height-cache and render-cache occupancy, and the viewport
|