@aragon-agent/cli 0.6.18 → 0.6.20
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 +14 -0
- package/dist/compaction/meter.d.ts +12 -0
- package/dist/compaction/meter.js +34 -1
- package/dist/compaction/pressure.d.ts +29 -0
- package/dist/compaction/pressure.js +32 -0
- package/dist/input/win32-input-mode.js +12 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,20 @@ were written.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **`Ctrl+I` was dead on Windows.** The win32-input-mode translator only
|
|
13
|
+
recognised the chord when the console reported it as `VK_TAB` (vk 9) with
|
|
14
|
+
ctrl - a record shape no real console was ever probed for. Physical
|
|
15
|
+
Ctrl+I keeps the LETTER vk (0x49, the same Ctrl+letter rule that reports
|
|
16
|
+
Ctrl+A as vk 65 and Ctrl+J as vk 74 in the Shift+Enter probe captures)
|
|
17
|
+
while `char` carries the Tab byte, so the record fell through to the
|
|
18
|
+
generic Ctrl-combo branch, came out as plain Tab, and the keybinding
|
|
19
|
+
silently did completion instead of opening the index confirm. The
|
|
20
|
+
translator now tells Ctrl+I apart from Tab by `char === 0x09 && ctrl`
|
|
21
|
+
whatever vk it rides, with Shift still mapping to Shift+Tab; both record
|
|
22
|
+
shapes are pinned by regression rows in `win32-input-mode.test.ts`.
|
|
23
|
+
|
|
10
24
|
### Team dispatch supervisor (team-overseer)
|
|
11
25
|
|
|
12
26
|
- **A time ceiling on a subagent is now an inspection trigger, not a death
|
|
@@ -103,6 +103,8 @@ export declare class ContextMeter {
|
|
|
103
103
|
private last;
|
|
104
104
|
/** Whether the history has changed since the last measurement. */
|
|
105
105
|
private dirty;
|
|
106
|
+
/** Whether the one-per-run empty-measurement warning has been spent. */
|
|
107
|
+
private hasWarnedUnmeasuredInput;
|
|
106
108
|
private prefixLast;
|
|
107
109
|
private sampledPrompt;
|
|
108
110
|
private sampledVersion;
|
|
@@ -206,6 +208,16 @@ export declare class ContextMeter {
|
|
|
206
208
|
*/
|
|
207
209
|
attach(subscribe: (listener: (event: AgentEvent) => void) => () => void): void;
|
|
208
210
|
dispose(): void;
|
|
211
|
+
/**
|
|
212
|
+
* ONE warn per run (context-usage-zero-input-tokens B). A single day of
|
|
213
|
+
* real usage logged 1,973 zero-input turns; a per-turn warning is a flood
|
|
214
|
+
* that teaches whoever reads the file to ignore it.
|
|
215
|
+
*
|
|
216
|
+
* The logger is resolved LAZILY rather than captured at construction:
|
|
217
|
+
* hosts build this class before `installLogging()`, and a child captured
|
|
218
|
+
* then would stay bound to the silent pre-install logger forever.
|
|
219
|
+
*/
|
|
220
|
+
private warnUnmeasuredInputOnce;
|
|
209
221
|
private onAgentEvent;
|
|
210
222
|
/**
|
|
211
223
|
* The structural belt for a missed invalidation site (I-9).
|
package/dist/compaction/meter.js
CHANGED
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
* `CompactionWiring.settlePending`'s own synchronous code (I-9), and why
|
|
28
28
|
* `current()` carries a structural belt for a missed invalidation site.
|
|
29
29
|
*/
|
|
30
|
-
import {
|
|
30
|
+
import { getLogger } from '../logging/logger.js';
|
|
31
|
+
import { computeEstimateOffset, computePressure, isInputSideUnmeasured } from './pressure.js';
|
|
31
32
|
/**
|
|
32
33
|
* How long a scheduled publish waits.
|
|
33
34
|
*
|
|
@@ -103,6 +104,8 @@ export class ContextMeter {
|
|
|
103
104
|
last = null;
|
|
104
105
|
/** Whether the history has changed since the last measurement. */
|
|
105
106
|
dirty = true;
|
|
107
|
+
/** Whether the one-per-run empty-measurement warning has been spent. */
|
|
108
|
+
hasWarnedUnmeasuredInput = false;
|
|
106
109
|
prefixLast;
|
|
107
110
|
sampledPrompt;
|
|
108
111
|
sampledVersion;
|
|
@@ -174,6 +177,21 @@ export class ContextMeter {
|
|
|
174
177
|
* better number to wait for.
|
|
175
178
|
*/
|
|
176
179
|
onTurnEnd(usage) {
|
|
180
|
+
if (isInputSideUnmeasured(usage)) {
|
|
181
|
+
// A usage that discloses NOTHING on the input side is not a
|
|
182
|
+
// measurement of this history (context-usage-zero-input-tokens B):
|
|
183
|
+
// arming the measured branch with it collapses occupancy to the
|
|
184
|
+
// turn's own outputTokens and strips the `~` off the gauge. KEEP
|
|
185
|
+
// WHATEVER IS STILL TRUSTED - an earlier good measurement of a
|
|
186
|
+
// prefix that still exists (the history only grows between splices,
|
|
187
|
+
// so "old good base + appended estimate" stays self-consistent), and
|
|
188
|
+
// the estimate offset it calibrated - and re-measure NOW so the
|
|
189
|
+
// gauge degrades in this frame instead of after the next turn.
|
|
190
|
+
this.warnUnmeasuredInputOnce(usage);
|
|
191
|
+
this.dirty = true;
|
|
192
|
+
this.current();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
177
195
|
const messages = this.deps.getMessages();
|
|
178
196
|
const systemPrompt = this.readSystemPrompt();
|
|
179
197
|
this.lastUsage = usage;
|
|
@@ -307,6 +325,21 @@ export class ContextMeter {
|
|
|
307
325
|
// =========================================================================
|
|
308
326
|
// Internals
|
|
309
327
|
// =========================================================================
|
|
328
|
+
/**
|
|
329
|
+
* ONE warn per run (context-usage-zero-input-tokens B). A single day of
|
|
330
|
+
* real usage logged 1,973 zero-input turns; a per-turn warning is a flood
|
|
331
|
+
* that teaches whoever reads the file to ignore it.
|
|
332
|
+
*
|
|
333
|
+
* The logger is resolved LAZILY rather than captured at construction:
|
|
334
|
+
* hosts build this class before `installLogging()`, and a child captured
|
|
335
|
+
* then would stay bound to the silent pre-install logger forever.
|
|
336
|
+
*/
|
|
337
|
+
warnUnmeasuredInputOnce(usage) {
|
|
338
|
+
if (this.hasWarnedUnmeasuredInput)
|
|
339
|
+
return;
|
|
340
|
+
this.hasWarnedUnmeasuredInput = true;
|
|
341
|
+
getLogger().warn('compaction', 'context_input_tokens_unreported', { in: usage.inputTokens, out: usage.outputTokens });
|
|
342
|
+
}
|
|
310
343
|
onAgentEvent(event) {
|
|
311
344
|
switch (event.type) {
|
|
312
345
|
case 'turn_end':
|
|
@@ -40,6 +40,35 @@ import type { Pressure } from './types.js';
|
|
|
40
40
|
* the feature is broken, and turns it off.
|
|
41
41
|
*/
|
|
42
42
|
export declare function occupiedTokens(usage: TokenUsage): number;
|
|
43
|
+
/**
|
|
44
|
+
* Whether a usage measured ANYTHING on the input side
|
|
45
|
+
* (context-usage-zero-input-tokens B).
|
|
46
|
+
*
|
|
47
|
+
* THE EMPTY MEASUREMENT THIS EXISTS FOR. A turn that billed output tokens
|
|
48
|
+
* while reporting inputTokens 0 AND no cache terms did not measure the
|
|
49
|
+
* request - no real request is free of input. Anthropic-COMPATIBLE relays
|
|
50
|
+
* emit exactly this shape (bigmodel on every turn, Kimi intermittently),
|
|
51
|
+
* and the meter used to arm its measured branch with it: occupancy collapsed
|
|
52
|
+
* to the turn's own outputTokens, the `~` honesty marker vanished with
|
|
53
|
+
* `source: 'usage'`, and the trigger - which reads the same number - never
|
|
54
|
+
* fired. The defense is to not trust such a usage as a measurement.
|
|
55
|
+
*
|
|
56
|
+
* THE CACHE TERMS ARE PART OF THE INPUT SIDE, DELIBERATELY. Anthropic's real
|
|
57
|
+
* `input_tokens` EXCLUDES cached tokens, so a deeply cached turn reports a
|
|
58
|
+
* tiny `input_tokens` next to a huge `cache_read_input_tokens`. That IS a
|
|
59
|
+
* valid measurement (C-14), and judging on `inputTokens === 0` alone would
|
|
60
|
+
* reject it and strand a correct gauge on the estimator.
|
|
61
|
+
*
|
|
62
|
+
* `outputTokens > 0` separates "the stream ran, billed output, and disclosed
|
|
63
|
+
* no input" from a degenerate all-zero usage, which the reviewed predicate
|
|
64
|
+
* deliberately does not speak for.
|
|
65
|
+
*
|
|
66
|
+
* SINGLE AUTHORITY. The meter consumes this, and any future observability
|
|
67
|
+
* hint (fix C) must too: two inline copies of "did the gateway disclose
|
|
68
|
+
* input" would drift apart exactly the way the gauge and the trigger once
|
|
69
|
+
* could (R-11).
|
|
70
|
+
*/
|
|
71
|
+
export declare function isInputSideUnmeasured(usage: TokenUsage): boolean;
|
|
43
72
|
/**
|
|
44
73
|
* The calibration offset for this turn (D-23 / P1-11).
|
|
45
74
|
*
|
|
@@ -44,6 +44,38 @@ export function occupiedTokens(usage) {
|
|
|
44
44
|
(usage.cacheWriteTokens ?? 0) +
|
|
45
45
|
usage.outputTokens);
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Whether a usage measured ANYTHING on the input side
|
|
49
|
+
* (context-usage-zero-input-tokens B).
|
|
50
|
+
*
|
|
51
|
+
* THE EMPTY MEASUREMENT THIS EXISTS FOR. A turn that billed output tokens
|
|
52
|
+
* while reporting inputTokens 0 AND no cache terms did not measure the
|
|
53
|
+
* request - no real request is free of input. Anthropic-COMPATIBLE relays
|
|
54
|
+
* emit exactly this shape (bigmodel on every turn, Kimi intermittently),
|
|
55
|
+
* and the meter used to arm its measured branch with it: occupancy collapsed
|
|
56
|
+
* to the turn's own outputTokens, the `~` honesty marker vanished with
|
|
57
|
+
* `source: 'usage'`, and the trigger - which reads the same number - never
|
|
58
|
+
* fired. The defense is to not trust such a usage as a measurement.
|
|
59
|
+
*
|
|
60
|
+
* THE CACHE TERMS ARE PART OF THE INPUT SIDE, DELIBERATELY. Anthropic's real
|
|
61
|
+
* `input_tokens` EXCLUDES cached tokens, so a deeply cached turn reports a
|
|
62
|
+
* tiny `input_tokens` next to a huge `cache_read_input_tokens`. That IS a
|
|
63
|
+
* valid measurement (C-14), and judging on `inputTokens === 0` alone would
|
|
64
|
+
* reject it and strand a correct gauge on the estimator.
|
|
65
|
+
*
|
|
66
|
+
* `outputTokens > 0` separates "the stream ran, billed output, and disclosed
|
|
67
|
+
* no input" from a degenerate all-zero usage, which the reviewed predicate
|
|
68
|
+
* deliberately does not speak for.
|
|
69
|
+
*
|
|
70
|
+
* SINGLE AUTHORITY. The meter consumes this, and any future observability
|
|
71
|
+
* hint (fix C) must too: two inline copies of "did the gateway disclose
|
|
72
|
+
* input" would drift apart exactly the way the gauge and the trigger once
|
|
73
|
+
* could (R-11).
|
|
74
|
+
*/
|
|
75
|
+
export function isInputSideUnmeasured(usage) {
|
|
76
|
+
const inputSide = usage.inputTokens + (usage.cacheReadTokens ?? 0) + (usage.cacheWriteTokens ?? 0);
|
|
77
|
+
return inputSide === 0 && usage.outputTokens > 0;
|
|
78
|
+
}
|
|
47
79
|
/**
|
|
48
80
|
* The calibration offset for this turn (D-23 / P1-11).
|
|
49
81
|
*
|
|
@@ -216,6 +216,18 @@ export function translateWin32Key(record) {
|
|
|
216
216
|
return char;
|
|
217
217
|
if (!ctrl && alt)
|
|
218
218
|
return `\x1b${char}`;
|
|
219
|
+
// Ctrl+I, letter-vk shape: a physical Ctrl+I keeps the LETTER vk
|
|
220
|
+
// (0x49, the same Ctrl+letter probe rule that reports Ctrl+A as 65
|
|
221
|
+
// and Ctrl+J as 74) while `char` is already the Tab byte, so the
|
|
222
|
+
// VK_TAB switch above never sees the record. 0x09 is both the Tab
|
|
223
|
+
// byte and VK_TAB, so the tell-apart from plain Tab is ctrl alone,
|
|
224
|
+
// and Shift keeps ESC [ Z exactly like that switch: the mode toggle
|
|
225
|
+
// stays intact and Ctrl+Shift+I stays on the Shift branch.
|
|
226
|
+
if (ctrl && record.char === VK_TAB) {
|
|
227
|
+
if (!shift && !alt)
|
|
228
|
+
return INDEX_KEY_FRAME;
|
|
229
|
+
return shift ? '\x1b[Z' : '\t';
|
|
230
|
+
}
|
|
219
231
|
return ctrl ? `${alt ? '\x1b' : ''}${char}` : char;
|
|
220
232
|
}
|
|
221
233
|
if (isPrintable(record.char)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aragon-agent/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.20",
|
|
4
4
|
"description": "AragonAgent CLI — a Claude-Code / Codex-style interactive terminal UI (TUI) on top of the @aragon-agent/core engine. Installable and runnable via npm / npx.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "AragonAgent contributors",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"prepublishOnly": "npm run build"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@aragon-agent/core": "^0.2.
|
|
59
|
+
"@aragon-agent/core": "^0.2.32",
|
|
60
60
|
"chalk": "^5.6.2",
|
|
61
61
|
"cli-highlight": "^2.0.0",
|
|
62
62
|
"commander": "^12.1.0",
|