@aragon-agent/cli 0.5.6 → 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.
Files changed (156) hide show
  1. package/CHANGELOG.md +356 -0
  2. package/README.md +1429 -1105
  3. package/dist/agent/coalesce.d.ts +13 -0
  4. package/dist/agent/coalesce.js +50 -11
  5. package/dist/agent/controller.d.ts +141 -2
  6. package/dist/agent/controller.js +396 -4
  7. package/dist/agent/entry-limits.d.ts +65 -0
  8. package/dist/agent/entry-limits.js +133 -0
  9. package/dist/agent/headless.d.ts +8 -0
  10. package/dist/agent/headless.js +40 -0
  11. package/dist/agent/reducer.d.ts +253 -3
  12. package/dist/agent/reducer.js +553 -28
  13. package/dist/agent/retry-view.d.ts +68 -0
  14. package/dist/agent/retry-view.js +95 -0
  15. package/dist/agent/system-prompt.d.ts +11 -0
  16. package/dist/agent/system-prompt.js +2 -0
  17. package/dist/cli.js +122 -4
  18. package/dist/commands/builtins.d.ts +1 -1
  19. package/dist/commands/builtins.js +313 -2
  20. package/dist/commands/perf.d.ts +45 -0
  21. package/dist/commands/perf.js +78 -0
  22. package/dist/config/cli-commands.d.ts +53 -2
  23. package/dist/config/cli-commands.js +136 -3
  24. package/dist/config/env.d.ts +6 -1
  25. package/dist/config/env.js +131 -1
  26. package/dist/config/load.d.ts +63 -0
  27. package/dist/config/load.js +125 -2
  28. package/dist/config/schema.d.ts +273 -10
  29. package/dist/config/schema.js +250 -7
  30. package/dist/config/store.js +20 -1
  31. package/dist/fast/critique.d.ts +43 -0
  32. package/dist/fast/critique.js +62 -0
  33. package/dist/fast/digest.d.ts +42 -0
  34. package/dist/fast/digest.js +85 -0
  35. package/dist/fast/frames.d.ts +99 -0
  36. package/dist/fast/frames.js +180 -0
  37. package/dist/fast/limits.d.ts +98 -0
  38. package/dist/fast/limits.js +98 -0
  39. package/dist/fast/prompt.d.ts +72 -0
  40. package/dist/fast/prompt.js +94 -0
  41. package/dist/fast/resolve.d.ts +43 -0
  42. package/dist/fast/resolve.js +105 -0
  43. package/dist/fast/review-call.d.ts +99 -0
  44. package/dist/fast/review-call.js +130 -0
  45. package/dist/fast/reviewer.d.ts +248 -0
  46. package/dist/fast/reviewer.js +664 -0
  47. package/dist/fast/types.d.ts +128 -0
  48. package/dist/fast/types.js +14 -0
  49. package/dist/fast/wiring.d.ts +170 -0
  50. package/dist/fast/wiring.js +316 -0
  51. package/dist/logging/install.d.ts +15 -1
  52. package/dist/logging/install.js +37 -4
  53. package/dist/logging/logger.d.ts +1 -1
  54. package/dist/session/persist.js +57 -1
  55. package/dist/team/normalize.d.ts +26 -1
  56. package/dist/team/normalize.js +23 -3
  57. package/dist/team/prompt.d.ts +11 -0
  58. package/dist/team/prompt.js +10 -0
  59. package/dist/team/report.d.ts +18 -0
  60. package/dist/team/report.js +27 -1
  61. package/dist/team/runtime.d.ts +13 -2
  62. package/dist/team/runtime.js +33 -6
  63. package/dist/team/subagent.d.ts +19 -1
  64. package/dist/team/subagent.js +72 -10
  65. package/dist/team/task-tool.d.ts +26 -0
  66. package/dist/team/task-tool.js +48 -4
  67. package/dist/team/types.d.ts +80 -1
  68. package/dist/tools/bash-tool.js +19 -3
  69. package/dist/tools/diff.d.ts +25 -5
  70. package/dist/tools/diff.js +72 -41
  71. package/dist/tools/file-change-store.d.ts +34 -0
  72. package/dist/tools/file-change-store.js +57 -0
  73. package/dist/tools/fs-tools.d.ts +26 -0
  74. package/dist/tools/fs-tools.js +62 -5
  75. package/dist/tools/index.d.ts +31 -0
  76. package/dist/tools/index.js +7 -1
  77. package/dist/tools/patch.d.ts +115 -0
  78. package/dist/tools/patch.js +453 -0
  79. package/dist/tools/terminal-output.d.ts +107 -0
  80. package/dist/tools/terminal-output.js +198 -0
  81. package/dist/tools/tool-output-store.d.ts +68 -0
  82. package/dist/tools/tool-output-store.js +102 -0
  83. package/dist/ui/ActivityLine.d.ts +48 -0
  84. package/dist/ui/ActivityLine.js +22 -0
  85. package/dist/ui/App.d.ts +1 -4
  86. package/dist/ui/App.js +357 -44
  87. package/dist/ui/BottomStatusRow.d.ts +43 -0
  88. package/dist/ui/BottomStatusRow.js +14 -0
  89. package/dist/ui/Composer.d.ts +1 -6
  90. package/dist/ui/Composer.js +2 -2
  91. package/dist/ui/Markdown.d.ts +7 -1
  92. package/dist/ui/Markdown.js +15 -48
  93. package/dist/ui/PromptInput.d.ts +1 -15
  94. package/dist/ui/PromptInput.js +1 -38
  95. package/dist/ui/StatusBar.d.ts +50 -0
  96. package/dist/ui/StatusBar.js +7 -3
  97. package/dist/ui/TeamPanel.d.ts +5 -4
  98. package/dist/ui/TeamPanel.js +1 -1
  99. package/dist/ui/TodoPanel.d.ts +5 -4
  100. package/dist/ui/Transcript.d.ts +80 -5
  101. package/dist/ui/Transcript.js +179 -11
  102. package/dist/ui/activity-phrases.d.ts +33 -0
  103. package/dist/ui/activity-phrases.js +50 -0
  104. package/dist/ui/entries/AssistantEntry.d.ts +38 -1
  105. package/dist/ui/entries/AssistantEntry.js +34 -3
  106. package/dist/ui/entries/DiffView.d.ts +67 -0
  107. package/dist/ui/entries/DiffView.js +103 -0
  108. package/dist/ui/entries/FastCard.d.ts +53 -0
  109. package/dist/ui/entries/FastCard.js +87 -0
  110. package/dist/ui/entries/RetryCard.d.ts +56 -0
  111. package/dist/ui/entries/RetryCard.js +60 -0
  112. package/dist/ui/entries/TeamCard.d.ts +9 -1
  113. package/dist/ui/entries/TeamCard.js +28 -2
  114. package/dist/ui/entries/TodoCard.d.ts +9 -1
  115. package/dist/ui/entries/TodoCard.js +23 -1
  116. package/dist/ui/entries/ToolCard.d.ts +50 -1
  117. package/dist/ui/entries/ToolCard.js +104 -7
  118. package/dist/ui/entries/ToolPreview.d.ts +2 -2
  119. package/dist/ui/entries/UserEntry.d.ts +9 -1
  120. package/dist/ui/entries/UserEntry.js +17 -1
  121. package/dist/ui/exit-snapshot.d.ts +7 -0
  122. package/dist/ui/glyphs.d.ts +9 -0
  123. package/dist/ui/glyphs.js +2 -0
  124. package/dist/ui/layout/AppShell.d.ts +13 -22
  125. package/dist/ui/layout/AppShell.js +3 -38
  126. package/dist/ui/layout/MeasuredEntry.d.ts +21 -0
  127. package/dist/ui/layout/MeasuredEntry.js +30 -0
  128. package/dist/ui/layout/ScrollViewport.js +8 -2
  129. package/dist/ui/layout/viewport-geometry.d.ts +28 -0
  130. package/dist/ui/layout/viewport-geometry.js +27 -0
  131. package/dist/ui/layout/virtual-window.d.ts +100 -0
  132. package/dist/ui/layout/virtual-window.js +308 -0
  133. package/dist/ui/live-clamp.d.ts +42 -0
  134. package/dist/ui/live-clamp.js +74 -0
  135. package/dist/ui/markdown-blocks.d.ts +25 -1
  136. package/dist/ui/markdown-blocks.js +43 -0
  137. package/dist/ui/overlays/HelpOverlay.js +16 -2
  138. package/dist/ui/overlays/SettingsScreen.d.ts +82 -1
  139. package/dist/ui/overlays/SettingsScreen.js +147 -1
  140. package/dist/ui/render-cache.d.ts +81 -0
  141. package/dist/ui/render-cache.js +195 -0
  142. package/dist/ui/render-governor.d.ts +54 -0
  143. package/dist/ui/render-governor.js +78 -0
  144. package/dist/ui/transcript-text.d.ts +11 -0
  145. package/dist/ui/transcript-text.js +32 -0
  146. package/dist/ui/use-height-store.d.ts +31 -0
  147. package/dist/ui/use-height-store.js +76 -0
  148. package/dist/ui/use-render-governor.d.ts +39 -0
  149. package/dist/ui/use-render-governor.js +57 -0
  150. package/dist/ui/use-startup-notices.d.ts +9 -1
  151. package/dist/ui/use-startup-notices.js +35 -1
  152. package/dist/ui/use-wheel-routing.d.ts +16 -32
  153. package/dist/ui/use-wheel-routing.js +21 -38
  154. package/package.json +2 -2
  155. package/dist/ui/layout/regions.d.ts +0 -55
  156. package/dist/ui/layout/regions.js +0 -52
@@ -0,0 +1,248 @@
1
+ /**
2
+ * FastReviewer — the periodic asynchronous review (fast-model-tier §3.5).
3
+ *
4
+ * ASCII ONLY: `src/fast/**` is inside the glyph scanner's scope.
5
+ *
6
+ * THE ENTIRE CLASS IS SHAPED AROUND *WHEN* IT IS ALLOWED TO SPEAK.
7
+ * `Agent.steer()` pushes onto a queue that `runAgentLoop` drains at three
8
+ * places, and only one of them is safe:
9
+ *
10
+ * 1 top of the loop, before the LLM call (`agent-loop.ts:126`) - pushed as a
11
+ * `user` message, conversation shape stays valid. SAFE.
12
+ * 2 after the LLM call, before tool execution (`:199`) - `continue`, leaving
13
+ * the assistant's `tool_use` blocks with no `tool_result`. Anthropic then
14
+ * rejects the NEXT request with HTTP 400. HARD FAILURE.
15
+ * 3 between two tool executions (`:214`) - every remaining call in the batch
16
+ * is replaced with "Tool execution skipped due to steering interrupt."
17
+ * SILENTLY DESTRUCTIVE.
18
+ *
19
+ * For a human pressing Enter mid-run, 2 and 3 are the DESIRED semantics. For an
20
+ * unrequested background critique they are a defect generator whose symptoms
21
+ * (an HTTP 400 about tool_result ids; work silently deleted) point nowhere near
22
+ * the reviewer. So this class calls `steer()` from EXACTLY ONE PLACE: inside the
23
+ * synchronous listener for the `tool_execution_end` that brings the batch to
24
+ * zero. `Agent.emit()` runs listeners synchronously inside the loop
25
+ * (`agent.ts:340`), the batch is finished, and the next `hasSteering()` the loop
26
+ * evaluates is therefore checkpoint 1 (AC-20).
27
+ *
28
+ * AND STEERING IS NOT DELIVERY (§3.5.4a / RV-1 / D-19). `steer()` only enqueues;
29
+ * `runLoopWithLifecycle`'s `finally` never clears the queues (`agent.ts:410`);
30
+ * and the loop emits the batch's last `tool_execution_end` (`:249`) BEFORE it
31
+ * re-tests the abort signal (`:271`). So an Esc landing inside the final tool's
32
+ * `await` yields exactly the interleaving where the reviewer steers, the loop
33
+ * breaks, and the block resurfaces in the user's NEXT conversation wearing the
34
+ * user's role. Two guards close it:
35
+ *
36
+ * guard 1 do not steer into a REQUESTED abort (`isAbortRequested`).
37
+ * guard 2 prove delivery. `awaitingDrain` is set on steer and cleared at the
38
+ * next `turn_start` - the loop cannot reach `turn_start` (`:136`)
39
+ * without having passed checkpoint 1 (`:126`), so `turn_start` IS the
40
+ * receipt. Still true at `agent_end` means the block was stranded.
41
+ *
42
+ * Guard 2 exists because the idle watchdog calls `Agent.abort()` DIRECTLY
43
+ * (`watchdog.ts:15-17`), where no controller-level flag can see it (D-20) - and
44
+ * the watchdog fires precisely on the long quiet runs where a review is most
45
+ * likely to be pending.
46
+ *
47
+ * A future refactor that moves `steer()` into the `complete()` callback will
48
+ * look tidier and will reintroduce all of the above.
49
+ *
50
+ * WHAT WAS SPLIT OUT, AND WHAT DELIBERATELY WAS NOT (hardening W3 / §3.3).
51
+ * The turn-frame ring moved to `frames.ts` and the bounded call to
52
+ * `review-call.ts`, both leaves. THE PROTOCOL STAYED HERE, WHOLE: the two drain
53
+ * guards above (AC-H11) and the call-cancellation stamping - `callAbort`,
54
+ * `callAbortReason`, `cancelCall()` and the one `new AbortController()`
55
+ * (AC-H16). A split that puts half of either behind a module boundary is a
56
+ * "simplification" that reopens a P0, and in the cancellation case it is round
57
+ * 1's IF-7 verbatim; `review-call.ts`'s header states why.
58
+ */
59
+ import type { AgentEvent, AssistantMessage, LLMRequest, TokenUsage } from '@aragon-agent/core';
60
+ import type { FastConfig } from '../config/schema.js';
61
+ import type { NoticeLevel } from '../agent/reducer.js';
62
+ import type { FastEvent, FastTier } from './types.js';
63
+ /**
64
+ * Everything the reviewer needs from the rest of the world.
65
+ *
66
+ * ALL INJECTED, so `fast-reviewer.test.ts` can replay a scripted `AgentEvent`
67
+ * sequence against a stub `complete` and assert the injection window without a
68
+ * network, a terminal or an `Agent` (§8.1).
69
+ */
70
+ export interface FastReviewerDeps {
71
+ /** The LEAD agent's event stream, through `AgentController` (C-7). */
72
+ subscribe(listener: (event: AgentEvent) => void): () => void;
73
+ /**
74
+ * `ProviderRegistry.complete` — bound since round 2 to `FastWiring`'s OWN
75
+ * fail-fast registry, not to the lead's (W2 / §3.2). Nothing in this file
76
+ * knows that, which is the whole reason the dep is injected.
77
+ */
78
+ complete(providerId: string, request: LLMRequest): Promise<AssistantMessage>;
79
+ /** `AgentController.steer` - the ONLY writer of the queue besides the user. */
80
+ steer(text: string): void;
81
+ isRunning(): boolean;
82
+ /** Guard 1: `AgentController.abort()` sets this synchronously BEFORE
83
+ * `agent.abort()`, so the reviewer can see an Esc that has not landed yet. */
84
+ isAbortRequested(): boolean;
85
+ /** Guard 2: user messages queued since the last `turn_start`. `0` is what
86
+ * makes `clearAllQueues()` provably safe (D-21). */
87
+ userSteerCount(): number;
88
+ clearAllQueues(): void;
89
+ /** Re-read at EVERY use, never snapshot (RV-3). */
90
+ getTier(): FastTier;
91
+ getConfig(): FastConfig;
92
+ /** `FastWiring.available()` - the live predicate of §3.3. */
93
+ available(): boolean;
94
+ getApiKey(providerId: string): string | undefined;
95
+ emit(event: FastEvent): void;
96
+ notify(level: NoticeLevel, text: string): void;
97
+ /** Injected clock. A test that reads the wall clock fails on a slow machine
98
+ * and nowhere else - the reason `TodoStore` and `TeamPanel` take one. */
99
+ now?: () => number;
100
+ }
101
+ export declare class FastReviewer {
102
+ private readonly deps;
103
+ /** Scope `fast` since round 2 (W4): an unrequested background call is not one
104
+ * of the LEAD's records, and a support reader filtering `agent` wants those. */
105
+ private readonly log;
106
+ private readonly now;
107
+ private unsubscribe;
108
+ private disposed;
109
+ private runId;
110
+ /** The turn-frame ring (`frames.ts`). Owns `turns`, the open frame and the
111
+ * outstanding-call counter; decides nothing. */
112
+ private readonly ring;
113
+ private inFlight;
114
+ private pending;
115
+ private reviewsThisRun;
116
+ /** Set on steer, cleared at the next `turn_start`. Guard 2's receipt. */
117
+ private awaitingDrain;
118
+ private awaitingReviewIndex;
119
+ /** The run's own abort channel for an in-flight `complete()`. */
120
+ private callAbort;
121
+ /**
122
+ * WHY the in-flight call was aborted - RECORDED here because it cannot be
123
+ * recovered from the error: a timeout and a cancellation go through the same
124
+ * `controller.abort()` and arrive as byte-identical bare `Error`s. The full
125
+ * argument, and the prohibition it implies for `review-call.ts`, is in that
126
+ * file's header; this field and `cancelCall()` are the halves it protects.
127
+ */
128
+ private callAbortReason;
129
+ private goal;
130
+ /**
131
+ * Reviews STARTED this session. NEVER RESET (§3.1.1).
132
+ *
133
+ * This is BOTH the status line's numerator and the session budget's left-hand
134
+ * side, on purpose: a parallel `reviewsThisSession` would be a second answer
135
+ * to one question, and the first time the two drifted the product would print
136
+ * `12/40` while suppressing at a number nobody can see.
137
+ */
138
+ private reviewIndex;
139
+ /** The limit at which exhaustion was last announced; `-1` = not announced.
140
+ * Keyed on the LIMIT, not on a boolean, so raising the budget re-arms the
141
+ * notice without a second latch to keep in sync (§3.1.3). */
142
+ private budgetAnnouncedAt;
143
+ private consecutiveFailures;
144
+ private selfDisabled;
145
+ private usage;
146
+ constructor(deps: FastReviewerDeps);
147
+ /** The user's request for this run, captured in `AgentController.prompt()`. */
148
+ setGoal(text: string): void;
149
+ /** Reviews STARTED this session, for `/fast status` and `FastSnapshot`. */
150
+ reviewCount(): number;
151
+ /** The live session budget, read from config so `/fast budget <n>` takes
152
+ * effect on the next sealed frame with no restart. */
153
+ budgetLimit(): number;
154
+ /** Carried on the snapshot rather than re-derived by callers (RV-H10). */
155
+ isBudgetReached(): boolean;
156
+ sessionUsage(): TokenUsage;
157
+ isReviewInFlight(): boolean;
158
+ /**
159
+ * `AgentController.abort()`.
160
+ *
161
+ * Aborts the in-flight call and drops `pending`. It MUST NOT clear
162
+ * `awaitingDrain`: that flag is guard 2's receipt and is resolved only at
163
+ * `turn_start` (delivered) or `agent_end` (stranded).
164
+ */
165
+ abort(): void;
166
+ /**
167
+ * Cancel an in-flight review because nobody wants the answer any more.
168
+ *
169
+ * A CANCELLATION IS NOT A FAILURE (§3.5.5). The three callers - `endRun()`
170
+ * (the run finished first), `abort()` (Esc) and `dispose()` - all mean "never
171
+ * mind", and none of them is evidence of a MISCONFIGURED tier, which is the
172
+ * only thing self-disable exists for (D-18 / D-24). Scoring them as strikes
173
+ * silently killed the reviewer for the rest of a session over three ordinary
174
+ * runs - the common shape, since a turn that answers without tools ends the
175
+ * run - behind a warn quoting an internal stream message (IF-7).
176
+ *
177
+ * THE STAMP MUST HAPPEN HERE, BEFORE THE ABORT, AND THE CONTROLLER MUST STAY
178
+ * REACHABLE FROM THIS METHOD (AC-H16).
179
+ */
180
+ private cancelCall;
181
+ /** Idempotent. Unsubscribes as well as aborting. */
182
+ dispose(): void;
183
+ private onAgentEvent;
184
+ private beginRun;
185
+ private onTurnStart;
186
+ private onToolEnd;
187
+ private endRun;
188
+ /**
189
+ * Remove a block that was steered and never delivered.
190
+ *
191
+ * THE ASYMMETRY IS DELIBERATE (D-21): the reviewer may always destroy its own
192
+ * message and may NEVER destroy the user's. `Agent` exposes no way to remove
193
+ * one entry - only `clearAllQueues()` - so removal is permitted only while the
194
+ * reviewer can PROVE it owns the whole queue, which `userSteerCount() === 0`
195
+ * establishes: `AgentController.steer()` is the only other writer in the
196
+ * package and the counter resets at every `turn_start`.
197
+ *
198
+ * With a user steer queued it clears NOTHING and warns. The residue is
199
+ * bounded, rare, labelled by its own `<fast_review turn model>` wrapper, and -
200
+ * unlike v1 - reported.
201
+ */
202
+ private recoverStranded;
203
+ /** Whether another review could still be STARTED this run. */
204
+ private canReviewAgain;
205
+ private maybeStartReview;
206
+ /**
207
+ * Say it once per limit value, and say what is NOT affected.
208
+ *
209
+ * `info`, NOT `warn` (D-H6): D-24 reserves the alarming register for a
210
+ * MISCONFIGURED tier, because that is the case that never fixes itself. A
211
+ * budget reached is the system working as configured, and warning here would
212
+ * train the user to ignore the register that matters.
213
+ *
214
+ * NEITHER `consecutiveFailures` NOR `selfDisabled` IS TOUCHED. A budget stop
215
+ * is neither a success that clears the strike counter nor a failure that
216
+ * raises it - the exact distinction IF-7 was filed for, applied to a second
217
+ * cause. And the reviewer is not broken: it must revive the moment the budget
218
+ * rises, which `budgetLimit()` reading live config is what delivers.
219
+ *
220
+ * NO TRANSCRIPT CARD, and that is a correctness requirement rather than a
221
+ * styling choice (§3.1.3). R-8 ("it did nothing" is never the observable
222
+ * outcome) governs a review that STARTED; every such path emits a `FastReview`
223
+ * carrying an `index`, and indices come from `this.reviewIndex += 1`. Minting
224
+ * one here would advance the very counter `/fast status` renders as the
225
+ * numerator, so the first suppression would display `41/40`.
226
+ */
227
+ private announceBudgetReached;
228
+ private currentModelId;
229
+ private runReview;
230
+ /**
231
+ * A review nobody is waiting for any more.
232
+ *
233
+ * It still has to produce a TERMINAL card. `review_start` already put a
234
+ * `running` entry in the transcript, and `Transcript`'s settled boundary is
235
+ * monotonic (C-5) - an entry that never settles is re-rendered on every frame
236
+ * for the rest of the session. "It did nothing" is also never allowed to be
237
+ * the observable outcome (R-8).
238
+ *
239
+ * `consecutiveFailures` is left EXACTLY as it was: a cancellation is neither a
240
+ * success that clears the count nor a failure that raises it.
241
+ */
242
+ private onReviewCancelled;
243
+ private onReviewAnswer;
244
+ private onReviewFailure;
245
+ private maybeInject;
246
+ private dropPending;
247
+ private emitReview;
248
+ }