@aragon-agent/cli 0.6.14 → 0.6.15

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 (113) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +250 -233
  3. package/dist/agent/controller.d.ts +27 -1
  4. package/dist/agent/controller.js +182 -45
  5. package/dist/agent/plan-prompt.d.ts +1 -1
  6. package/dist/agent/plan-prompt.js +4 -3
  7. package/dist/agent/project-guidance-prompt.d.ts +4 -0
  8. package/dist/agent/project-guidance-prompt.js +104 -0
  9. package/dist/agent/reducer.d.ts +2 -0
  10. package/dist/agent/reducer.js +4 -0
  11. package/dist/agent/system-prompt.js +4 -0
  12. package/dist/commands/builtins.js +2 -2
  13. package/dist/compaction/child.d.ts +9 -1
  14. package/dist/compaction/child.js +39 -13
  15. package/dist/compaction/command.js +20 -10
  16. package/dist/compaction/compactor.d.ts +33 -204
  17. package/dist/compaction/compactor.js +311 -726
  18. package/dist/compaction/digest.d.ts +15 -51
  19. package/dist/compaction/digest.js +113 -148
  20. package/dist/compaction/limits.d.ts +19 -142
  21. package/dist/compaction/limits.js +20 -147
  22. package/dist/compaction/memory-identity.d.ts +16 -0
  23. package/dist/compaction/memory-identity.js +63 -0
  24. package/dist/compaction/memory-input.d.ts +25 -0
  25. package/dist/compaction/memory-input.js +106 -0
  26. package/dist/compaction/memory-render.d.ts +4 -0
  27. package/dist/compaction/memory-render.js +47 -0
  28. package/dist/compaction/memory-validation.d.ts +21 -0
  29. package/dist/compaction/memory-validation.js +268 -0
  30. package/dist/compaction/memory.d.ts +79 -0
  31. package/dist/compaction/memory.js +118 -0
  32. package/dist/compaction/meter.d.ts +14 -10
  33. package/dist/compaction/meter.js +53 -19
  34. package/dist/compaction/operation.d.ts +18 -0
  35. package/dist/compaction/operation.js +68 -0
  36. package/dist/compaction/pressure.d.ts +5 -20
  37. package/dist/compaction/pressure.js +13 -23
  38. package/dist/compaction/summarize-call.d.ts +3 -16
  39. package/dist/compaction/summarize-call.js +20 -20
  40. package/dist/compaction/summary-prompt.d.ts +29 -66
  41. package/dist/compaction/summary-prompt.js +132 -178
  42. package/dist/compaction/types.d.ts +21 -3
  43. package/dist/compaction/wiring.d.ts +10 -25
  44. package/dist/compaction/wiring.js +56 -66
  45. package/dist/config/schema.d.ts +1 -1
  46. package/dist/config/schema.js +1 -1
  47. package/dist/exec/events.d.ts +8 -0
  48. package/dist/exec/index.js +13 -6
  49. package/dist/exec/runner.d.ts +8 -0
  50. package/dist/exec/runner.js +26 -2
  51. package/dist/session/persist.d.ts +3 -0
  52. package/dist/session/persist.js +9 -0
  53. package/dist/session/store.js +2 -0
  54. package/dist/session/validate-session.js +34 -0
  55. package/dist/team/subagent.js +8 -0
  56. package/dist/ui/App.js +218 -116
  57. package/dist/ui/BottomStatusRow.d.ts +5 -10
  58. package/dist/ui/BottomStatusRow.js +7 -11
  59. package/dist/ui/Composer.d.ts +4 -2
  60. package/dist/ui/Composer.js +2 -2
  61. package/dist/ui/Header.d.ts +6 -2
  62. package/dist/ui/Header.js +7 -6
  63. package/dist/ui/PromptInput.d.ts +3 -1
  64. package/dist/ui/PromptInput.js +32 -41
  65. package/dist/ui/StatusBar.d.ts +6 -0
  66. package/dist/ui/StatusBar.js +8 -7
  67. package/dist/ui/Transcript.js +1 -1
  68. package/dist/ui/entries/CompactionCard.d.ts +3 -1
  69. package/dist/ui/entries/CompactionCard.js +7 -5
  70. package/dist/ui/frame-differ.js +27 -0
  71. package/dist/ui/frame-observer.js +18 -5
  72. package/dist/ui/interaction-copy.d.ts +73 -73
  73. package/dist/ui/interaction-copy.js +30 -38
  74. package/dist/ui/interaction-hints.d.ts +8 -1
  75. package/dist/ui/interaction-hints.js +56 -69
  76. package/dist/ui/layout/AppShell.d.ts +6 -2
  77. package/dist/ui/layout/AppShell.js +2 -2
  78. package/dist/ui/layout/OverlayFrame.d.ts +2 -0
  79. package/dist/ui/layout/OverlayFrame.js +23 -14
  80. package/dist/ui/layout/ScrollViewport.d.ts +3 -1
  81. package/dist/ui/layout/ScrollViewport.js +10 -2
  82. package/dist/ui/layout/budget.d.ts +25 -26
  83. package/dist/ui/layout/budget.js +29 -22
  84. package/dist/ui/layout/document-layout.d.ts +2 -2
  85. package/dist/ui/layout/document-layout.js +2 -3
  86. package/dist/ui/layout/queue-layout.js +4 -4
  87. package/dist/ui/layout/status-detail-layout.d.ts +9 -0
  88. package/dist/ui/layout/status-detail-layout.js +56 -0
  89. package/dist/ui/layout/status-layout.d.ts +19 -2
  90. package/dist/ui/layout/status-layout.js +95 -84
  91. package/dist/ui/layout/wrap-rows.d.ts +2 -0
  92. package/dist/ui/layout/wrap-rows.js +21 -7
  93. package/dist/ui/overlays/ConfirmDialog.d.ts +2 -1
  94. package/dist/ui/overlays/ConfirmDialog.js +22 -3
  95. package/dist/ui/overlays/HelpOverlay.js +9 -2
  96. package/dist/ui/overlays/ModelPicker.d.ts +5 -8
  97. package/dist/ui/overlays/ModelPicker.js +44 -10
  98. package/dist/ui/overlays/ModelProfileEditor.js +2 -0
  99. package/dist/ui/overlays/ModelProfilePicker.d.ts +1 -0
  100. package/dist/ui/overlays/ModelProfilePicker.js +4 -2
  101. package/dist/ui/overlays/PlanReviewOverlay.d.ts +2 -1
  102. package/dist/ui/overlays/PlanReviewOverlay.js +7 -4
  103. package/dist/ui/overlays/QuestionOverlay.d.ts +2 -1
  104. package/dist/ui/overlays/QuestionOverlay.js +45 -32
  105. package/dist/ui/overlays/QueueOverlay.js +2 -2
  106. package/dist/ui/overlays/SettingsScreen.d.ts +1 -0
  107. package/dist/ui/overlays/SettingsScreen.js +10 -3
  108. package/dist/ui/run-metrics.d.ts +23 -0
  109. package/dist/ui/run-metrics.js +27 -0
  110. package/dist/ui/status-feedback.d.ts +33 -0
  111. package/dist/ui/status-feedback.js +36 -0
  112. package/dist/ui/stdout-frame-writer.js +28 -0
  113. package/package.json +2 -2
@@ -1,20 +1,11 @@
1
- /**
2
- * `Compactor` — the `ContextManager` implementation (context-auto-compaction
3
- * §3.4 / §3.6 / §3.7 / §3.8).
4
- *
5
- * ASCII ONLY: `src/compaction/**` is inside the glyph scanner's scope.
6
- *
7
- * THIS IS THE POLICY HALF OF THE FEATURE. The engine owns exactly one thing -
8
- * structural validity - and every other decision is here: when to fire, what to
9
- * keep, which model summarizes, what the prompt asks for, what happens when the
10
- * call fails, and when to stop spending.
11
- */
1
+ /** Threshold-authorized compaction with host-owned, append-only task memory. */
12
2
  import type { ModelRole } from '../config/model-profiles.js';
13
3
  import { type Message, type ModelInfo, type ModelRef, type TokenUsage, type AssistantMessage, type CompactionContext, type CompactionOutcome, type CompactionProbe, type ContextManager, type LLMRequest } from '@aragon-agent/core';
14
4
  import type { CliConfig } from '../config/schema.js';
15
5
  import type { NoticeLevel } from '../agent/reducer.js';
16
6
  import { resolveFastTier } from '../fast/resolve.js';
17
7
  import { ContextMeter } from './meter.js';
8
+ import { type CompactionIdentity } from './memory-identity.js';
18
9
  import type { CompactionEvent, Pressure } from './types.js';
19
10
  export interface CompactorDeps {
20
11
  mainRole?: ModelRole;
@@ -102,242 +93,80 @@ export declare class Compactor implements ContextManager {
102
93
  private compactionsThisRun;
103
94
  private lastCompactionTurn;
104
95
  private compactions;
105
- /**
106
- * How many `compact()` calls returned WITHOUT announcing (quiet-noop D-9).
107
- *
108
- * A SESSION TOTAL, LIKE `compactions`, and reset by neither `onRunStart()` nor
109
- * `clearSelfDisable()`: `/compact on` overrides a guard, it does not rewrite
110
- * history. `/compact status` is its only reader, and it is the whole of what
111
- * keeps a decline reportable once the transcript stops carrying one.
112
- */
113
96
  private declined;
114
97
  private tokensReclaimed;
115
98
  private sessionUsage;
116
99
  private pricingUnknown;
117
- private inFlight;
100
+ private costUsd;
118
101
  private consecutiveNoProgress;
119
102
  private selfDisabled;
120
103
  private selfDisabledReason;
121
104
  private pendingManual;
122
105
  private generation;
123
- /**
124
- * The fallback meter, built on first use when no host injected one (R-1).
125
- *
126
- * `estimateOffset`, `measuredPrefixLength` and `lastPressure` used to be
127
- * FIELDS HERE. They moved to `ContextMeter` wholesale
128
- * (context-usage-gauge-accuracy W1), because keeping them here is what put the
129
- * only measurement in the process behind `compaction.enabled`.
130
- */
131
106
  private ownMeter;
132
- /**
133
- * The messages the last splice dropped, held ONLY until the wiring collects
134
- * them for the archive (W4 / RV-3).
135
- *
136
- * NOT ON `CompactionRecord`: that record is dispatched into the reducer and
137
- * retained in view state for the card's lifetime, so putting a megabyte of
138
- * history on it would park the dropped conversation in React state - precisely
139
- * the memory this compaction just reclaimed.
140
- *
141
- * SET ONLY WHEN ARCHIVING IS ON, so with the key off the slice is never
142
- * retained and W4 costs nothing.
143
- */
144
107
  private lastDropped;
145
- private callAbort;
146
- private callAbortReason;
147
- /** Guard 2's ceiling for this instance (hardening §3.4.2 mechanism B / DH-16). */
108
+ private active;
109
+ private historyEpoch;
110
+ private serial;
111
+ private identity;
112
+ private legacyFailureNotified;
148
113
  private readonly maxPerRun;
149
114
  constructor(deps: CompactorDeps, opts?: CompactorOptions);
150
- /** `agent_start` — the per-run cap resets, the session totals do not. */
151
115
  onRunStart(): void;
152
- /**
153
- * `turn_end` - recompute the calibration offset (D-23).
154
- *
155
- * A THIN FORWARDER since context-usage-gauge-accuracy W1. The meter subscribes
156
- * to `turn_end` itself, so BOTH PATHS MUST BE IDEMPOTENT: this one recomputes
157
- * exactly what the other one did from the same inputs, which it is.
158
- *
159
- * `messages` / `systemPrompt` stay in the signature and are ignored: the meter
160
- * reads them from its own lazy deps, and every existing caller and test keeps
161
- * compiling.
162
- */
116
+ onRunEnd(): void;
163
117
  onTurnEnd(usage: TokenUsage, _messages: readonly Message[], _systemPrompt: string): void;
164
- /**
165
- * The dropped messages, released as they are returned (W4 / RV-3).
166
- *
167
- * `take` RATHER THAN `get`: the reference is dropped on read, so a wiring that
168
- * declines to archive (key off, or `applied: false`) cannot pin it and a second
169
- * read cannot double-write. `settlePending` calls this on EVERY verdict and
170
- * discards on the ones that do not archive, which is what guarantees the array
171
- * cannot outlive one compaction regardless of which branch was taken.
172
- */
118
+ onHistoryReplaced(identity?: CompactionIdentity): void;
119
+ getIdentity(): CompactionIdentity | undefined;
173
120
  takeLastDropped(): Message[] | null;
174
- /** Cancel an in-flight summarization (Esc, `dispose`). */
175
121
  abort(): void;
176
- /**
177
- * Ask for a compaction at the next turn boundary.
178
- *
179
- * THE BOUNDARY IS THE ONLY MOMENT THE ENGINE IS SINGLE-THREADED WITH RESPECT
180
- * TO THE HISTORY, by construction. Replacing `messages` under a live loop is a
181
- * race; a flag `shouldCompact` honours there is not.
182
- */
183
122
  queueManual(instructions?: string): void;
184
123
  hasPendingManual(): boolean;
185
124
  clearPendingManual(): void;
186
- /**
187
- * SYNCHRONOUS AND CHEAP. Two deliberate effects: the pressure cache, and
188
- * `deps.onPressure` (hardening DH-15).
189
- *
190
- * THE MEASUREMENT IS TAKEN ONCE, ABOVE THE GUARDS, AND REPORTED
191
- * UNCONDITIONALLY. Below them it is skipped on five paths — the per-run cap,
192
- * the cooldown, manual, overflow and guard 4 — and TWO OF THOSE NEVER CLEAR
193
- * WITHIN A RUN. A gauge fed from the measurement would therefore go dark
194
- * exactly when compaction is exhausted and the window is still filling, which
195
- * is the one state where the corrected number is the user's only warning. It
196
- * would silently revert to the measured base — the very figure W1 exists
197
- * because it under-reports.
198
- *
199
- * `!config.enabled` STAYS THE FIRST STATEMENT, so a session that turned the
200
- * feature off pays nothing at all and AC-1's byte-identity claim is untouched.
201
- */
202
125
  shouldCompact(probe: CompactionProbe): boolean;
203
126
  compact(ctx: CompactionContext): Promise<CompactionOutcome>;
204
- /**
205
- * Open the card (quiet-noop §3.2).
206
- *
207
- * THE ONLY EMITTER OF `compaction_start`, AND THE ONLY PLACE `this.compactions`
208
- * ADVANCES. A compaction that never reaches an announce point is a DECLINE: it
209
- * changed nothing, called nothing and spent nothing, and it is deliberately
210
- * indistinguishable - on every human surface except `/compact status`'s
211
- * `declined` count (D-9) - from a turn at which `shouldCompact` returned false.
212
- * `finish` is the other half of that rule.
213
- *
214
- * IT RETURNS THE ANNOUNCEMENT RATHER THAN STORING IT (P1-1), and the caller
215
- * keeps it in a LOCAL for the lifetime of one `runCompaction` call - the same
216
- * slot `index` occupied before this change. An instance field would have needed
217
- * a no-re-entrancy argument, and the obvious one is WRONG: guard 1 lives in
218
- * `shouldCompact`, while the idle `/compact` path calls `compact()` straight
219
- * through `wiring.compactNow()` without consulting it. What actually keeps two
220
- * compactions apart is that `command.ts` QUEUES instead of calling `compactNow`
221
- * while the loop runs - a property of a different file, which is exactly why
222
- * this one must not depend on it. A clobbered field would leave `finish` unable
223
- * to settle the card it opened, and a card that never settles pins
224
- * `Transcript`'s monotonic boundary for the rest of the session.
225
- */
226
- private announce;
227
- private runCompaction;
228
- /** Tail relief against this session's window (hardening §3.3.3 / W2). */
229
- private relieveInPlace;
230
- /**
231
- * The failure ladder (§3.7).
232
- *
233
- * Rung 1 is the fast tier (or the main model); rung 2 is ONE retry on the MAIN
234
- * model when rung 1 used the fast tier, because "a fast model that cannot
235
- * summarize" is the most likely single failure. Rungs 3 and 4 are the caller's,
236
- * because they depend on `onFailure`.
237
- */
238
- private runLadder;
127
+ private prepareCandidate;
128
+ private selectInput;
129
+ private checkMinimumCandidate;
130
+ private digestFor;
131
+ private summarize;
239
132
  private callOnce;
240
- /**
241
- * Guard 3 — the progress requirement (§3.8).
242
- *
243
- * ADVISORY ON OVERFLOW, NEVER A VETO (D-24 / P1-13). The arithmetic that makes
244
- * this guard sensible for the proactive trigger INVERTS on the reactive one: a
245
- * pressure compaction that reclaims little has spent money to buy two turns and
246
- * should stop, while an overflow compaction that reclaims little is the
247
- * difference between a continuing run and a dead one, because the provider has
248
- * already refused the request.
249
- *
250
- * The projection is ESTIMATED — no usage exists for a history that has not been
251
- * sent yet — and is therefore CALIBRATED with `estimateOffset` (D-23).
252
- *
253
- * IT TAKES THE *UI* TRIGGER, not `ctx.trigger`. A queued `/compact` reaches the
254
- * loop as an ordinary `pressure` checkpoint (that is what the queue IS), so
255
- * charging its result to guard 4's counter would let a user who types
256
- * `/compact` twice on a short conversation self-disable the proactive trigger
257
- * for the rest of the session — and be told, wrongly, that their recent turns
258
- * exceed the threshold. `uiTrigger` is the only value that knows the difference.
259
- */
260
- private checkProgress;
261
- /**
262
- * Guard 4 — stuck detection (§3.8).
263
- *
264
- * PRESSURE ONLY, AND `pressure` HERE MEANS THE *UI* TRIGGER. A session that
265
- * self-disables still survives an overflow rather than dying at the next
266
- * request, and if the tail really is too large the overflow attempt is the one
267
- * that can do something about it (D-24). A `manual` compaction is excluded for
268
- * a different reason: this guard exists to stop UNREQUESTED spend, and
269
- * `/compact` on a conversation with nothing worth dropping is a user who asked
270
- * — twice — not a runaway loop.
271
- */
133
+ private checkCandidate;
134
+ private isCurrent;
135
+ private announce;
136
+ private keep;
137
+ private finishRecord;
138
+ /** Commit only the engine/host verdict; candidates have no authority before this point. */
139
+ settleOperation(verdict: {
140
+ applied: boolean;
141
+ reason?: string;
142
+ tokensBefore?: number;
143
+ tokensAfter: number;
144
+ }): boolean;
272
145
  private noteNoProgress;
273
- private finish;
274
- /**
275
- * The pressure the trigger and the gauge both read - MEASURED NOW.
276
- *
277
- * A FORWARDER since W1: the decision point supplies its own authoritative
278
- * `lastUsage` (the probe's), and the meter owns everything else. `messages` /
279
- * `systemPrompt` stay in the signature and are ignored, because the meter
280
- * reads the LIVE history through its own deps - which is strictly better than
281
- * a caller that could pass `[]` and get a 0 % reading (the old default here).
282
- */
283
- measure(probe: Pick<CompactionProbe, 'lastUsage'> & {
146
+ measure(_probe: Pick<CompactionProbe, 'lastUsage'> & {
284
147
  messages?: readonly Message[];
285
148
  systemPrompt?: string;
286
149
  }): Pressure;
287
- /**
288
- * The last pressure PUBLISHED. NEVER re-measured - `lastPublished`, not
289
- * `current` (I-10 / RV-3).
290
- *
291
- * `finish()` below reads this for `tokensBefore`, which is the sole upstream of
292
- * `tokensReclaimed`, the card's "reclaimed N tokens" and `/compact status`'s
293
- * session total. All three want the occupancy BEFORE the splice. Point this at
294
- * `meter.current()` and the moment the meter is dirty - which after a splice it
295
- * always is - `tokensBefore` becomes the POST-compaction figure, `reclaimed`
296
- * collapses to 0, and the card renders that with nothing logging a fault.
297
- */
298
150
  lastMeasured(): Pressure | null;
299
- /** Written by the wiring once the engine has reported its verdict. */
300
151
  recordApplied(tokensBefore: number, tokensAfter: number): void;
301
152
  sessionTotals(): {
153
+ selfDisabledReason?: string | undefined;
302
154
  compactions: number;
303
- /** Checkpoints that declined before committing to any work (quiet-noop D-9). */
304
155
  declined: number;
305
156
  tokensReclaimed: number;
306
157
  usage: TokenUsage;
158
+ costUsd: number;
307
159
  pricingUnknown: boolean;
308
160
  inFlight: boolean;
309
161
  selfDisabled: boolean;
310
- selfDisabledReason?: string;
311
162
  generation: number;
312
163
  };
313
- /** `/compact on` after a self-disable — the user overriding the guard. */
314
164
  clearSelfDisable(): void;
315
165
  isSelfDisabled(): boolean;
316
- /**
317
- * Which model summarizes (§3.6.4).
318
- *
319
- * SAY THE DEFAULT OUT LOUD (P2-8): FOR ALMOST EVERYONE THIS IS THE MAIN MODEL.
320
- * `resolveFastTier` returns `{ok: false, reason: 'disabled'}` on
321
- * `fast.enabled !== true` alone, and `fast.enabled` defaults to `false` — so
322
- * `useFastTier: true` describes a PREFERENCE, not the common path, and the
323
- * out-of-the-box first compaction is a ~30 k-token call on the session's own
324
- * model. Three things make that the right trade rather than a hidden cost: it
325
- * happens at most `maxPerRun` times per run, the alternative is losing the
326
- * entire run, and the spend is on the card with the summarizer's own price.
327
- */
328
166
  resolveSummarizer(): SummarizerChoice | null;
329
- /**
330
- * The meter this compactor reads, injected or private (R-1).
331
- *
332
- * MEMOIZED, because a fresh meter on every call would have no `estimateOffset`
333
- * and no cached pressure - `lastMeasured()` would answer `null` forever and
334
- * `tokensReclaimed` would sit at 0. The fallback exists so the ten existing
335
- * `compaction-*.test.ts` construction sites compile unchanged; production
336
- * injects, and `context-gauge-wiring.test.ts` asserts the single instance.
337
- */
167
+ private mainChoice;
338
168
  private meter;
339
169
  private mainRef;
340
- private modelInfo;
341
- private effectiveMaxOutputTokens;
170
+ private settingsKey;
342
171
  private noteUsage;
343
172
  }