@aragon-agent/cli 0.6.2 → 0.6.4

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 (167) hide show
  1. package/CHANGELOG.md +321 -0
  2. package/README.md +297 -2
  3. package/dist/agent/controller.d.ts +193 -1
  4. package/dist/agent/controller.js +475 -2
  5. package/dist/agent/headless.d.ts +8 -0
  6. package/dist/agent/headless.js +47 -0
  7. package/dist/agent/reducer.d.ts +189 -0
  8. package/dist/agent/reducer.js +301 -2
  9. package/dist/agent/system-prompt.d.ts +14 -0
  10. package/dist/agent/system-prompt.js +2 -0
  11. package/dist/cli.js +297 -16
  12. package/dist/commands/builtins.js +165 -24
  13. package/dist/commands/registry.d.ts +27 -0
  14. package/dist/compaction/archive.d.ts +175 -0
  15. package/dist/compaction/archive.js +267 -0
  16. package/dist/compaction/child.d.ts +97 -0
  17. package/dist/compaction/child.js +118 -0
  18. package/dist/compaction/command.d.ts +41 -0
  19. package/dist/compaction/command.js +355 -0
  20. package/dist/compaction/compactor.d.ts +302 -0
  21. package/dist/compaction/compactor.js +810 -0
  22. package/dist/compaction/digest.d.ts +62 -0
  23. package/dist/compaction/digest.js +164 -0
  24. package/dist/compaction/limits.d.ts +165 -0
  25. package/dist/compaction/limits.js +172 -0
  26. package/dist/compaction/pressure.d.ts +135 -0
  27. package/dist/compaction/pressure.js +167 -0
  28. package/dist/compaction/summarize-call.d.ts +70 -0
  29. package/dist/compaction/summarize-call.js +86 -0
  30. package/dist/compaction/summary-prompt.d.ts +85 -0
  31. package/dist/compaction/summary-prompt.js +197 -0
  32. package/dist/compaction/tail-budget.d.ts +52 -0
  33. package/dist/compaction/tail-budget.js +67 -0
  34. package/dist/compaction/types.d.ts +215 -0
  35. package/dist/compaction/types.js +22 -0
  36. package/dist/compaction/wiring.d.ts +264 -0
  37. package/dist/compaction/wiring.js +577 -0
  38. package/dist/config/app-paths.d.ts +14 -0
  39. package/dist/config/app-paths.js +16 -0
  40. package/dist/config/cli-commands.d.ts +41 -0
  41. package/dist/config/cli-commands.js +77 -1
  42. package/dist/config/env.d.ts +5 -2
  43. package/dist/config/env.js +140 -3
  44. package/dist/config/load.d.ts +42 -0
  45. package/dist/config/load.js +101 -1
  46. package/dist/config/schema.d.ts +244 -0
  47. package/dist/config/schema.js +170 -0
  48. package/dist/config/store.js +37 -1
  49. package/dist/config/ui-state.d.ts +28 -1
  50. package/dist/config/ui-state.js +9 -0
  51. package/dist/exec/events.d.ts +50 -1
  52. package/dist/exec/runner.js +42 -0
  53. package/dist/input/limits.d.ts +72 -0
  54. package/dist/input/limits.js +63 -0
  55. package/dist/input/mouse-events.d.ts +31 -5
  56. package/dist/input/mouse-events.js +86 -27
  57. package/dist/input/paste-parse.d.ts +71 -0
  58. package/dist/input/paste-parse.js +95 -0
  59. package/dist/input/stdin-filter.d.ts +81 -0
  60. package/dist/input/stdin-filter.js +379 -0
  61. package/dist/logging/install.d.ts +53 -1
  62. package/dist/logging/install.js +81 -1
  63. package/dist/logging/logger.d.ts +1 -1
  64. package/dist/proc/classify.d.ts +52 -0
  65. package/dist/proc/classify.js +143 -0
  66. package/dist/proc/kill-tree.d.ts +42 -0
  67. package/dist/proc/kill-tree.js +119 -0
  68. package/dist/proc/limits.d.ts +84 -0
  69. package/dist/proc/limits.js +84 -0
  70. package/dist/proc/log-ring.d.ts +68 -0
  71. package/dist/proc/log-ring.js +102 -0
  72. package/dist/proc/prompt.d.ts +24 -0
  73. package/dist/proc/prompt.js +49 -0
  74. package/dist/proc/readiness.d.ts +102 -0
  75. package/dist/proc/readiness.js +219 -0
  76. package/dist/proc/supervisor.d.ts +103 -0
  77. package/dist/proc/supervisor.js +465 -0
  78. package/dist/proc/types.d.ts +175 -0
  79. package/dist/proc/types.js +15 -0
  80. package/dist/session/persist.js +55 -1
  81. package/dist/team/report.js +7 -1
  82. package/dist/team/runtime.d.ts +10 -0
  83. package/dist/team/runtime.js +7 -0
  84. package/dist/team/subagent.d.ts +31 -1
  85. package/dist/team/subagent.js +42 -15
  86. package/dist/team/types.d.ts +8 -0
  87. package/dist/tools/bash-tool.d.ts +51 -2
  88. package/dist/tools/bash-tool.js +321 -51
  89. package/dist/tools/fs-tools.d.ts +17 -0
  90. package/dist/tools/index.d.ts +55 -2
  91. package/dist/tools/index.js +39 -1
  92. package/dist/tools/proc-tools.d.ts +25 -0
  93. package/dist/tools/proc-tools.js +102 -0
  94. package/dist/ui/ActivityLine.d.ts +19 -1
  95. package/dist/ui/ActivityLine.js +10 -2
  96. package/dist/ui/App.d.ts +62 -2
  97. package/dist/ui/App.js +546 -16
  98. package/dist/ui/Composer.d.ts +66 -1
  99. package/dist/ui/Composer.js +50 -6
  100. package/dist/ui/PromptInput.d.ts +82 -3
  101. package/dist/ui/PromptInput.js +232 -49
  102. package/dist/ui/StatusBar.d.ts +59 -0
  103. package/dist/ui/StatusBar.js +16 -4
  104. package/dist/ui/TeamPanel.js +7 -1
  105. package/dist/ui/Transcript.d.ts +21 -1
  106. package/dist/ui/Transcript.js +61 -3
  107. package/dist/ui/clipboard.d.ts +52 -0
  108. package/dist/ui/clipboard.js +91 -0
  109. package/dist/ui/composer-limits.d.ts +31 -0
  110. package/dist/ui/composer-limits.js +50 -0
  111. package/dist/ui/composer-rows.d.ts +73 -0
  112. package/dist/ui/composer-rows.js +201 -0
  113. package/dist/ui/editor-reducer.d.ts +37 -0
  114. package/dist/ui/editor-reducer.js +88 -12
  115. package/dist/ui/entries/CompactionCard.d.ts +75 -0
  116. package/dist/ui/entries/CompactionCard.js +158 -0
  117. package/dist/ui/entries/ServiceCard.d.ts +66 -0
  118. package/dist/ui/entries/ServiceCard.js +116 -0
  119. package/dist/ui/entries/UserEntry.d.ts +17 -3
  120. package/dist/ui/entries/UserEntry.js +34 -5
  121. package/dist/ui/frame-differ.d.ts +46 -0
  122. package/dist/ui/frame-differ.js +94 -10
  123. package/dist/ui/gauge.d.ts +16 -1
  124. package/dist/ui/gauge.js +25 -6
  125. package/dist/ui/glyphs.d.ts +11 -0
  126. package/dist/ui/glyphs.js +2 -0
  127. package/dist/ui/layout/ScrollViewport.d.ts +43 -6
  128. package/dist/ui/layout/ScrollViewport.js +128 -21
  129. package/dist/ui/layout/budget.d.ts +44 -9
  130. package/dist/ui/layout/budget.js +42 -10
  131. package/dist/ui/layout/follow-state.d.ts +137 -0
  132. package/dist/ui/layout/follow-state.js +150 -0
  133. package/dist/ui/layout/virtual-window.d.ts +11 -0
  134. package/dist/ui/layout/virtual-window.js +85 -1
  135. package/dist/ui/overlays/HelpOverlay.js +9 -1
  136. package/dist/ui/overlays/PlanReviewOverlay.js +10 -2
  137. package/dist/ui/overlays/QuestionOverlay.js +5 -1
  138. package/dist/ui/overlays/SettingsScreen.d.ts +47 -1
  139. package/dist/ui/overlays/SettingsScreen.js +74 -2
  140. package/dist/ui/palettes.d.ts +16 -0
  141. package/dist/ui/palettes.js +6 -0
  142. package/dist/ui/paste-frames.d.ts +87 -0
  143. package/dist/ui/paste-frames.js +112 -0
  144. package/dist/ui/paste-tokens.d.ts +90 -0
  145. package/dist/ui/paste-tokens.js +147 -0
  146. package/dist/ui/screen.d.ts +38 -0
  147. package/dist/ui/screen.js +113 -8
  148. package/dist/ui/selection/highlight.d.ts +39 -0
  149. package/dist/ui/selection/highlight.js +64 -0
  150. package/dist/ui/selection/screen-mirror.d.ts +24 -0
  151. package/dist/ui/selection/screen-mirror.js +35 -0
  152. package/dist/ui/selection/selection-controller.d.ts +88 -0
  153. package/dist/ui/selection/selection-controller.js +282 -0
  154. package/dist/ui/selection/selection.d.ts +90 -0
  155. package/dist/ui/selection/selection.js +223 -0
  156. package/dist/ui/stdout-frame-writer.d.ts +33 -0
  157. package/dist/ui/stdout-frame-writer.js +15 -0
  158. package/dist/ui/theme.d.ts +11 -0
  159. package/dist/ui/theme.js +2 -0
  160. package/dist/ui/transcript-text.js +72 -0
  161. package/dist/ui/use-startup-notices.d.ts +27 -1
  162. package/dist/ui/use-startup-notices.js +43 -11
  163. package/dist/ui/use-wheel-routing.d.ts +1 -1
  164. package/dist/ui/use-wheel-routing.js +8 -0
  165. package/package.json +4 -2
  166. package/dist/input/stdin-mouse-filter.d.ts +0 -42
  167. package/dist/input/stdin-mouse-filter.js +0 -153
@@ -0,0 +1,264 @@
1
+ /**
2
+ * `CompactionWiring` — the controller-side glue for context compaction
3
+ * (context-auto-compaction §3.2.1 / §5.2).
4
+ *
5
+ * ASCII ONLY: `src/compaction/**` is inside the glyph scanner's scope.
6
+ *
7
+ * CONSTRUCT BEFORE THE `Agent`, ATTACH AFTER IT (C-12 / D-19), and the split is
8
+ * the whole reason this class has an `attach` method at all:
9
+ *
10
+ * - The PORT has to be INSIDE the `Agent`'s constructor argument, because
11
+ * `AgentConfig.contextManager` has no setter and the loop reads it from the
12
+ * loop context.
13
+ * - The WIRING has to SUBSCRIBE to the `Agent`, because `compaction_end` is
14
+ * where the engine's `applied` verdict arrives and `agent_start` is what
15
+ * resets the per-run cap.
16
+ *
17
+ * `AgentController` cannot do both in one step: `new Agent({...})` runs before
18
+ * every optional subsystem, precisely because `FastWiring`'s constructor
19
+ * subscribes. So THIS CONSTRUCTOR MUST NOT SUBSCRIBE. A field assigned after the
20
+ * `new Agent` call and spread into it conditionally produces a build where the
21
+ * feature is registered, enabled, and SILENTLY ABSENT - the exact shape of
22
+ * failure `controller.ts`'s `toolOutputs` comment documents.
23
+ *
24
+ * `manager()` returns a STABLE object for the controller's lifetime, whose two
25
+ * methods delegate to a compactor that reads config LIVE - which is what lets
26
+ * `/compact off`, `/compact threshold 0.8` and a settings-screen save take effect
27
+ * mid-session without touching the `Agent`.
28
+ *
29
+ * DECLINED COMPACTIONS PRODUCE NO CLI EVENTS (quiet-noop §3.6). A `pressure`
30
+ * compaction that changed nothing, called nothing and spent nothing never emits
31
+ * `compaction_start`, so `onCompactorEvent` never opens a card and `settlePending`
32
+ * finds neither a held record nor a skeleton to synthesize. CORE still emits its
33
+ * own pair for every attempt, which is why `settlePending` still runs - it just
34
+ * refreshes the snapshot and returns. `onCompactorEvent`'s `if (!this.open)`
35
+ * guard is now unreachable for declines and stays for the abort race it was
36
+ * written for.
37
+ */
38
+ import { type AgentEvent, type ContextManager, type Message, type ModelInfo, type ModelRef, type ProviderRegistry, type ProviderRegistryOptions, type TokenUsage } from '@aragon-agent/core';
39
+ import type { CliConfig } from '../config/schema.js';
40
+ import type { NoticeLevel } from '../agent/reducer.js';
41
+ import { type ChildContextManagerFactory } from './child.js';
42
+ import type { CompactionEventListener, CompactionSnapshot } from './types.js';
43
+ export interface CompactionWiringDeps {
44
+ /** Read LIVE on every call - the controller replaces the object on mutation. */
45
+ getConfig: () => CliConfig;
46
+ hasKey: (providerId: string) => boolean;
47
+ getApiKey: (providerId: string) => string | undefined;
48
+ getModelInfoFor: (ref: Pick<ModelRef, 'providerId' | 'modelId'>) => ModelInfo;
49
+ isPricedModel: (ref: Pick<ModelRef, 'providerId' | 'modelId'>) => boolean;
50
+ /**
51
+ * LAZY, and they must be: this class is constructed BEFORE the `Agent`, so a
52
+ * closure that touches it is only valid from inside an event handler.
53
+ */
54
+ getMessages: () => readonly Message[];
55
+ getSystemPrompt: () => string;
56
+ notify: (level: NoticeLevel, text: string) => void;
57
+ /**
58
+ * How the summarizer's own registry is built. Defaults to `initProviders`.
59
+ *
60
+ * THE ONE PRODUCTION SEAM ADDED FOR TESTABILITY (hardening DH-13 / W6).
61
+ * Everything else the offline harness needs is already public:
62
+ * `ProviderRegistry.register` overwrites by id, `AgentController` exposes the
63
+ * lead's registry, and `Agent` accepts one in its config. `getRegistry()` was
64
+ * the only closed door - it calls `initProviders` with no injection point, so
65
+ * the lead's transport was scriptable in a test and the SUMMARIZER'S was not.
66
+ * A test-only seam per module is how a codebase acquires a shadow API; this is
67
+ * one, and it is named.
68
+ */
69
+ createRegistry?: (options: ProviderRegistryOptions) => ProviderRegistry;
70
+ /**
71
+ * The archive directory, injected by the tests. Production passes nothing and
72
+ * `archive.ts` resolves `<home>/compaction` itself.
73
+ */
74
+ archiveDir?: string;
75
+ }
76
+ /** The status of a session that never had compaction (the wiring is `null`). */
77
+ export declare function offCompactionSnapshot(): CompactionSnapshot;
78
+ export declare class CompactionWiring {
79
+ private readonly deps;
80
+ private readonly log;
81
+ private readonly listeners;
82
+ private readonly compactor;
83
+ /** The compactor's OWN transport (D-10). Lazy - see `getRegistry()`. */
84
+ private registry;
85
+ private unsubscribe;
86
+ /** The stable port handed to `new Agent({...})`. Never reassigned. */
87
+ private readonly port;
88
+ /**
89
+ * The record the compactor produced, waiting for the ENGINE's verdict.
90
+ *
91
+ * `applied` is not knowable on the host side: validation happens after
92
+ * `compact()` returns, inside the loop. So the compactor's record is held here
93
+ * and corrected when the core `compaction_end` arrives (§3.2.1). The IDLE
94
+ * `/compact` path has no core event and settles its own record directly.
95
+ */
96
+ private pending;
97
+ /**
98
+ * What the CLI-local `compaction_start` announced, and `null` once the card has
99
+ * been settled.
100
+ *
101
+ * THE ENGINE'S VERDICT CAN ARRIVE BEFORE THE COMPACTOR'S RECORD, and Esc is the
102
+ * ordinary way it happens: `runCompaction` races `compact()` against the run's
103
+ * signal, so an abort resolves the race and emits `compaction_end` while
104
+ * `compact()` is still unwinding its own call. With nothing held here,
105
+ * `settlePending` would find no record, return, and leave the card `live:
106
+ * true` FOREVER — which is C-8's failure mode exactly: `Transcript`'s settled
107
+ * boundary is monotonic, so the whole tail re-renders on every frame for the
108
+ * rest of the session, and the card goes on claiming a compaction is running.
109
+ * `manager_timeout` and a `compact()` that rejects outright reach the same
110
+ * place.
111
+ *
112
+ * So the verdict settles the card from whatever is available — the compactor's
113
+ * record when it exists, this skeleton when it does not — and clearing this
114
+ * field is what tells a LATE record that its card is already closed.
115
+ */
116
+ private open;
117
+ /** Live flag, flipped by `/compact on|off`. Starts equal to `enabled`. */
118
+ private enabled;
119
+ /**
120
+ * Identifies THIS RUN's archives in a directory several runs share (RV-6).
121
+ *
122
+ * NOT `SessionMeta.id`: that exists only once a session has been saved, and the
123
+ * unattended long run this feature serves is exactly the one nobody saved.
124
+ * Short, filename-safe, and only ever compared for equality - it is a grouping
125
+ * key, not an identity.
126
+ */
127
+ private readonly runId;
128
+ constructor(deps: CompactionWiringDeps);
129
+ /**
130
+ * The port for `new Agent({...})`.
131
+ *
132
+ * Spread CONDITIONALLY at the call site so `contextManager` stays genuinely
133
+ * `undefined` when the feature is off (AC-1): the loop's gate is
134
+ * `if (!ctx.contextManager) return false` against an ABSENT field, not a live
135
+ * object whose predicate says no.
136
+ */
137
+ manager(): ContextManager;
138
+ /**
139
+ * Subscribe to the lead agent's stream. IDEMPOTENT, and separate from the
140
+ * constructor - see the file header.
141
+ */
142
+ attach(subscribe: (listener: (event: AgentEvent) => void) => () => void): void;
143
+ dispose(): void;
144
+ isEnabled(): boolean;
145
+ setEnabled(enabled: boolean): void;
146
+ /** Re-emit the snapshot after any config mutation, so the chip and the gauge move. */
147
+ onConfigChanged(): void;
148
+ abort(): void;
149
+ /**
150
+ * The host replaced or cleared the history (hardening §3.2.3, sites 3 and 4).
151
+ *
152
+ * `/clear`, `/resume`, and any future host-side rewrite. A recorded prefix
153
+ * length indexes an array that no longer exists, so the delta must be
154
+ * abandoned rather than applied to a different history.
155
+ */
156
+ onHistoryReplaced(): void;
157
+ /**
158
+ * The per-child manager factory, or `null` when children get none
159
+ * (hardening §3.4 / W3).
160
+ *
161
+ * `null` RATHER THAN A NO-OP FACTORY, so `subagent.ts` can spread NOTHING and
162
+ * the child's loop gate tests a genuinely absent `contextManager` - the same
163
+ * byte-identity argument `AgentController` makes for the lead (AC-H10).
164
+ */
165
+ childFactory(): ChildContextManagerFactory | null;
166
+ queueManual(instructions?: string): void;
167
+ hasPendingManual(): boolean;
168
+ clearPendingManual(): void;
169
+ /**
170
+ * The IDLE `/compact` path (§4.4 / D-25).
171
+ *
172
+ * IT VALIDATES BEFORE IT SPLICES, AND THAT IS NOT OPTIONAL (P1-7). When the
173
+ * agent is idle there is no loop, so §3.3 step 5 does not run — and the only
174
+ * way to replace the history is `Agent.replaceMessages`, which validates
175
+ * nothing. D-4 declares that gate unbypassable and R-2 calls an invalid splice
176
+ * the worst possible outcome, so this path mirrors the engine's steps 3-5
177
+ * exactly, INCLUDING the failure vocabulary: the card, the log and
178
+ * `/compact status` cannot tell the two paths apart.
179
+ *
180
+ * No watchdog handling is needed — `runLoopWithLifecycle`'s `finally` already
181
+ * called `watchdog.stop()`, so nothing is armed while idle.
182
+ *
183
+ * ITS CALLER MUST ADOPT `messages` — THE ARCHIVE IS ALREADY WRITTEN BY THE
184
+ * TIME THIS RETURNS (hardening RV-7). This path settles `applied: true` here,
185
+ * one statement before the caller splices, so the "never archive a live
186
+ * history" rule holds only because that caller applies unconditionally. That is
187
+ * a fact about one call site rather than an invariant, which is why it is
188
+ * written down where it can be checked.
189
+ */
190
+ compactNow(args: {
191
+ messages: readonly Message[];
192
+ systemPrompt: string;
193
+ model: ModelRef;
194
+ signal: AbortSignal;
195
+ lastUsage?: TokenUsage;
196
+ instructions?: string;
197
+ }): Promise<{
198
+ ok: true;
199
+ messages: Message[];
200
+ } | {
201
+ ok: false;
202
+ reason: string;
203
+ }>;
204
+ snapshot(): CompactionSnapshot;
205
+ /**
206
+ * `snapshot()` with the pressure argument substituted for the re-measurement.
207
+ *
208
+ * SO THE CHECKPOINT DOES NOT MEASURE TWICE. `shouldCompact` has already walked
209
+ * the appended slice; measuring again here would double the one cost DH-15
210
+ * accepted, and - worse - the second measurement could differ from the one the
211
+ * decision was made on if anything appended in between.
212
+ */
213
+ private snapshotWith;
214
+ /** The summarizer that would be used right now, for `/compact status`. */
215
+ summarizerRef(): ModelRef | null;
216
+ subscribe(listener: CompactionEventListener): () => void;
217
+ /**
218
+ * The transport one summarization call goes through - separate from the lead's,
219
+ * and fail-fast (D-10).
220
+ *
221
+ * LAZY, SO OFF STAYS BYTE-IDENTICAL. Nothing is constructed until a compaction
222
+ * actually calls, so a session that never crosses the threshold allocates no
223
+ * registry and registers no adapters.
224
+ */
225
+ private getRegistry;
226
+ private onCompactorEvent;
227
+ private onAgentEvent;
228
+ /**
229
+ * Settle the held record with the authoritative verdict, then emit it.
230
+ *
231
+ * `tokensBefore` / `tokensAfter` come from CORE'S OWN estimator on BOTH sides
232
+ * (§5.1), so the card's headline claim compares two numbers in one unit rather
233
+ * than a measurement against a guess. `tokensReclaimed` is accumulated from the
234
+ * same pair, which is what keeps `/compact status` and the card agreeing.
235
+ */
236
+ private settlePending;
237
+ /**
238
+ * Write the archive, if there is one to write (hardening §3.5.3 / W4).
239
+ *
240
+ * ONLY ON `applied: true`, because the rule the writer enforces is "never
241
+ * archive a history that is still live" - and the two paths reach that verdict
242
+ * at different moments relative to the splice. In loop, the ENGINE decides
243
+ * after `validateHistory`, so this runs AFTER adoption. On the manual path the
244
+ * WIRING decides and `compactNow`'s caller adopts on the next statement, so
245
+ * this runs BEFORE adoption; `compactNow`'s doc comment carries that obligation
246
+ * for its one caller (RV-7).
247
+ *
248
+ * BEST-EFFORT AND SYNCHRONOUS-BUT-GUARDED. `writeArchive` never throws and
249
+ * logs its own failure; a failed archive never affects the compaction, and it
250
+ * never notifies - a toast for a best-effort audit file trains users to ignore
251
+ * toasts.
252
+ */
253
+ private archive;
254
+ /** This run's archive key, for `/compact history` and `/compact show`. */
255
+ archiveRunId(): string;
256
+ /**
257
+ * The minimum a card needs to settle when the compactor's own record has not
258
+ * arrived (see `open`). `null` when no card was ever opened — the
259
+ * `shouldCompact`-threw path, where the engine emits a pair of events the CLI
260
+ * stream knows nothing about.
261
+ */
262
+ private skeletonRecord;
263
+ private emit;
264
+ }