@aragon-agent/cli 0.6.2 → 0.6.3
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 +216 -0
- package/README.md +202 -0
- package/dist/agent/controller.d.ts +74 -1
- package/dist/agent/controller.js +200 -1
- package/dist/agent/headless.d.ts +8 -0
- package/dist/agent/headless.js +47 -0
- package/dist/agent/reducer.d.ts +120 -0
- package/dist/agent/reducer.js +201 -2
- package/dist/cli.js +224 -5
- package/dist/commands/builtins.js +73 -23
- package/dist/commands/registry.d.ts +27 -0
- package/dist/compaction/archive.d.ts +175 -0
- package/dist/compaction/archive.js +267 -0
- package/dist/compaction/child.d.ts +97 -0
- package/dist/compaction/child.js +113 -0
- package/dist/compaction/command.d.ts +41 -0
- package/dist/compaction/command.js +342 -0
- package/dist/compaction/compactor.d.ts +268 -0
- package/dist/compaction/compactor.js +689 -0
- package/dist/compaction/digest.d.ts +62 -0
- package/dist/compaction/digest.js +164 -0
- package/dist/compaction/limits.d.ts +165 -0
- package/dist/compaction/limits.js +172 -0
- package/dist/compaction/pressure.d.ts +135 -0
- package/dist/compaction/pressure.js +167 -0
- package/dist/compaction/summarize-call.d.ts +70 -0
- package/dist/compaction/summarize-call.js +86 -0
- package/dist/compaction/summary-prompt.d.ts +85 -0
- package/dist/compaction/summary-prompt.js +197 -0
- package/dist/compaction/tail-budget.d.ts +52 -0
- package/dist/compaction/tail-budget.js +67 -0
- package/dist/compaction/types.d.ts +179 -0
- package/dist/compaction/types.js +22 -0
- package/dist/compaction/wiring.d.ts +255 -0
- package/dist/compaction/wiring.js +556 -0
- package/dist/config/app-paths.d.ts +14 -0
- package/dist/config/app-paths.js +16 -0
- package/dist/config/cli-commands.d.ts +41 -0
- package/dist/config/cli-commands.js +77 -1
- package/dist/config/env.d.ts +4 -1
- package/dist/config/env.js +92 -2
- package/dist/config/load.d.ts +31 -0
- package/dist/config/load.js +63 -1
- package/dist/config/schema.d.ts +159 -0
- package/dist/config/schema.js +137 -0
- package/dist/config/store.js +17 -1
- package/dist/config/ui-state.d.ts +28 -1
- package/dist/config/ui-state.js +9 -0
- package/dist/exec/events.d.ts +50 -1
- package/dist/exec/runner.js +42 -0
- package/dist/input/mouse-events.d.ts +31 -5
- package/dist/input/mouse-events.js +86 -27
- package/dist/input/stdin-mouse-filter.d.ts +8 -3
- package/dist/logging/install.d.ts +51 -1
- package/dist/logging/install.js +28 -0
- package/dist/logging/logger.d.ts +1 -1
- package/dist/session/persist.js +19 -0
- package/dist/team/report.js +7 -1
- package/dist/team/runtime.d.ts +10 -0
- package/dist/team/runtime.js +7 -0
- package/dist/team/subagent.d.ts +31 -1
- package/dist/team/subagent.js +42 -15
- package/dist/team/types.d.ts +8 -0
- package/dist/ui/ActivityLine.d.ts +19 -1
- package/dist/ui/ActivityLine.js +10 -2
- package/dist/ui/App.d.ts +48 -1
- package/dist/ui/App.js +294 -13
- package/dist/ui/Composer.d.ts +13 -1
- package/dist/ui/Composer.js +2 -2
- package/dist/ui/PromptInput.d.ts +34 -1
- package/dist/ui/PromptInput.js +54 -3
- package/dist/ui/StatusBar.d.ts +40 -0
- package/dist/ui/StatusBar.js +13 -4
- package/dist/ui/TeamPanel.js +7 -1
- package/dist/ui/Transcript.d.ts +21 -1
- package/dist/ui/Transcript.js +32 -2
- package/dist/ui/clipboard.d.ts +52 -0
- package/dist/ui/clipboard.js +91 -0
- package/dist/ui/entries/CompactionCard.d.ts +75 -0
- package/dist/ui/entries/CompactionCard.js +158 -0
- package/dist/ui/frame-differ.d.ts +46 -0
- package/dist/ui/frame-differ.js +94 -10
- package/dist/ui/gauge.d.ts +16 -1
- package/dist/ui/gauge.js +25 -6
- package/dist/ui/glyphs.d.ts +11 -0
- package/dist/ui/glyphs.js +2 -0
- package/dist/ui/layout/ScrollViewport.d.ts +43 -6
- package/dist/ui/layout/ScrollViewport.js +128 -21
- package/dist/ui/layout/budget.d.ts +10 -3
- package/dist/ui/layout/budget.js +10 -3
- package/dist/ui/layout/follow-state.d.ts +137 -0
- package/dist/ui/layout/follow-state.js +150 -0
- package/dist/ui/layout/virtual-window.d.ts +11 -0
- package/dist/ui/layout/virtual-window.js +34 -0
- package/dist/ui/overlays/HelpOverlay.js +6 -1
- package/dist/ui/overlays/SettingsScreen.d.ts +47 -1
- package/dist/ui/overlays/SettingsScreen.js +60 -1
- package/dist/ui/palettes.d.ts +16 -0
- package/dist/ui/palettes.js +6 -0
- package/dist/ui/screen.d.ts +22 -0
- package/dist/ui/screen.js +70 -8
- package/dist/ui/selection/highlight.d.ts +39 -0
- package/dist/ui/selection/highlight.js +64 -0
- package/dist/ui/selection/screen-mirror.d.ts +24 -0
- package/dist/ui/selection/screen-mirror.js +35 -0
- package/dist/ui/selection/selection-controller.d.ts +88 -0
- package/dist/ui/selection/selection-controller.js +282 -0
- package/dist/ui/selection/selection.d.ts +90 -0
- package/dist/ui/selection/selection.js +223 -0
- package/dist/ui/stdout-frame-writer.d.ts +33 -0
- package/dist/ui/stdout-frame-writer.js +15 -0
- package/dist/ui/theme.d.ts +11 -0
- package/dist/ui/theme.js +2 -0
- package/dist/ui/transcript-text.js +23 -0
- package/dist/ui/use-startup-notices.d.ts +27 -1
- package/dist/ui/use-startup-notices.js +43 -11
- package/dist/ui/use-wheel-routing.js +8 -0
- package/package.json +4 -2
|
@@ -13,7 +13,7 @@ import process from 'node:process';
|
|
|
13
13
|
import { getConfigBackupPath, getConfigPath, getHomeRoot, getLogsDir, getPromptHistoryPath, getUiStatePath, isHomeOverridden, } from './app-paths.js';
|
|
14
14
|
import { getHomeMigrationBreadcrumbPath } from './migrate-home.js';
|
|
15
15
|
import { loadPersistedConfig, updatePersistedConfig } from './store.js';
|
|
16
|
-
import { clampFastConfig, clampRetryConfig, clampUpdateConfig, coercePositiveInt, maskSecret, DEFAULT_FAST_CONFIG, DEFAULT_RETRY_CONFIG, DEFAULT_TEAM_CONFIG, DEFAULT_UPDATE_CONFIG, } from './schema.js';
|
|
16
|
+
import { clampFastConfig, clampRetryConfig, clampCompactionConfig, parseThresholdInput, clampUpdateConfig, coercePositiveInt, maskSecret, DEFAULT_FAST_CONFIG, DEFAULT_RETRY_CONFIG, DEFAULT_TEAM_CONFIG, DEFAULT_COMPACTION_CONFIG, DEFAULT_UPDATE_CONFIG, } from './schema.js';
|
|
17
17
|
import { clampLogLevel } from '../logging/levels.js';
|
|
18
18
|
/** Config keys under `log.` that `aragon config set` accepts. */
|
|
19
19
|
export const LOG_CONFIG_SET_KEYS = [
|
|
@@ -103,6 +103,33 @@ export const UPDATE_CONFIG_SET_KEYS = [
|
|
|
103
103
|
'update.registry',
|
|
104
104
|
'update.distTag',
|
|
105
105
|
];
|
|
106
|
+
/**
|
|
107
|
+
* Config keys under `compaction.` that `aragon config set` accepts
|
|
108
|
+
* (context-auto-compaction §4.2).
|
|
109
|
+
*
|
|
110
|
+
* A DEDICATED SETTER RATHER THAN A GENERIC DOTTED WRITER, for the reason the
|
|
111
|
+
* five sets above each record: a generic setter would write `compaction` as a
|
|
112
|
+
* FLAT string key (`"compaction.enabled": "false"` at the top level of the
|
|
113
|
+
* file), the section would silently never take effect, and `config set` would
|
|
114
|
+
* still print `Set compaction.enabled = false`.
|
|
115
|
+
*
|
|
116
|
+
* THIS SET IS WHAT MAKES THE KILL SWITCH REACHABLE FROM A SCRIPT. `config list`
|
|
117
|
+
* enumerates the section dynamically and so shows these keys whether they are
|
|
118
|
+
* here or not; `config set` does not, so without this block
|
|
119
|
+
* `aragon config set compaction.enabled false` fails with "Unknown config key"
|
|
120
|
+
* while the key is visibly listed one command over. Manual-test row 9 — the
|
|
121
|
+
* persisted-off-survives-a-flagless-run check — runs exactly that command.
|
|
122
|
+
*/
|
|
123
|
+
export const COMPACTION_CONFIG_SET_KEYS = [
|
|
124
|
+
'compaction.enabled',
|
|
125
|
+
'compaction.threshold',
|
|
126
|
+
'compaction.warnThreshold',
|
|
127
|
+
'compaction.keepRecentTurns',
|
|
128
|
+
'compaction.useFastTier',
|
|
129
|
+
'compaction.onFailure',
|
|
130
|
+
'compaction.subagents',
|
|
131
|
+
'compaction.archive',
|
|
132
|
+
];
|
|
106
133
|
function isTrue(value) {
|
|
107
134
|
return value === 'true' || value === '1';
|
|
108
135
|
}
|
|
@@ -294,6 +321,55 @@ export function applyUpdateConfigSet(key, value) {
|
|
|
294
321
|
return null;
|
|
295
322
|
}
|
|
296
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Translate a `compaction.*` dotted key into a patch, or `null` for anything
|
|
326
|
+
* else (context-auto-compaction §4.2).
|
|
327
|
+
*
|
|
328
|
+
* EVERY KEY ROUTES THROUGH `clampCompactionConfig`, not through a local parse,
|
|
329
|
+
* for the reason `applyRetryConfigSet`, `applyFastConfigSet` and
|
|
330
|
+
* `applyUpdateConfigSet` all record: one gate for both directions means no key
|
|
331
|
+
* here can pick up a different coercion later, and `config set
|
|
332
|
+
* compaction.threshold 0.2` writes the clamped `0.5` while the caller echoes the
|
|
333
|
+
* STORED value.
|
|
334
|
+
*
|
|
335
|
+
* `threshold` and `warnThreshold` additionally accept a PERCENTAGE, because that
|
|
336
|
+
* is the unit the status bar shows and `/compact threshold` accepts.
|
|
337
|
+
*
|
|
338
|
+
* A VALUE THE PARSER REJECTS RESOLVES TO THE DEFAULT, NOT TO THE CURRENT SETTING
|
|
339
|
+
* — the same thing `config set retry.maxRetries banana` does, because `clampOne`
|
|
340
|
+
* merges the field onto `DEFAULT_COMPACTION_CONFIG` before clamping it. That is
|
|
341
|
+
* the house behaviour and it is not silent: `cli.tsx` echoes the STORED value, so
|
|
342
|
+
* a typo prints the number that was actually written rather than the one that was
|
|
343
|
+
* typed. Unlike the settings screen and `/compact threshold`, both of which
|
|
344
|
+
* genuinely ignore an unparseable value, this surface has no third state.
|
|
345
|
+
*/
|
|
346
|
+
export function applyCompactionConfigSet(key, value) {
|
|
347
|
+
const patch = (compaction) => ({ compaction });
|
|
348
|
+
const clampOne = (field, raw = value) => {
|
|
349
|
+
const merged = clampCompactionConfig({ ...DEFAULT_COMPACTION_CONFIG, [field]: raw });
|
|
350
|
+
return { [field]: merged[field] };
|
|
351
|
+
};
|
|
352
|
+
switch (key) {
|
|
353
|
+
case 'compaction.enabled':
|
|
354
|
+
return patch(clampOne('enabled', isTrue(value)));
|
|
355
|
+
case 'compaction.threshold':
|
|
356
|
+
return patch(clampOne('threshold', parseThresholdInput(value) ?? undefined));
|
|
357
|
+
case 'compaction.warnThreshold':
|
|
358
|
+
return patch(clampOne('warnThreshold', parseThresholdInput(value) ?? undefined));
|
|
359
|
+
case 'compaction.keepRecentTurns':
|
|
360
|
+
return patch(clampOne('keepRecentTurns'));
|
|
361
|
+
case 'compaction.useFastTier':
|
|
362
|
+
return patch(clampOne('useFastTier', isTrue(value)));
|
|
363
|
+
case 'compaction.onFailure':
|
|
364
|
+
return patch(clampOne('onFailure'));
|
|
365
|
+
case 'compaction.subagents':
|
|
366
|
+
return patch(clampOne('subagents', isTrue(value)));
|
|
367
|
+
case 'compaction.archive':
|
|
368
|
+
return patch(clampOne('archive', isTrue(value)));
|
|
369
|
+
default:
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
297
373
|
/**
|
|
298
374
|
* `log.redactSecrets false` is the one setting that lets credentials reach the
|
|
299
375
|
* disk. It is command-line-only (there is no settings-screen entry) and it says
|
package/dist/config/env.d.ts
CHANGED
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
* ARAGON_LOG_FILE, ARAGON_LOG_DIR, ARAGON_TRANSCRIPT_RETAIN,
|
|
15
15
|
* ARAGON_RENDER_GOVERNOR, ARAGON_MAX_RENDER_INTERVAL_MS,
|
|
16
16
|
* ARAGON_DIFF_RENDER, ARAGON_SYNC_OUTPUT,
|
|
17
|
-
* ARAGON_UPDATE
|
|
17
|
+
* ARAGON_UPDATE,
|
|
18
|
+
* ARAGON_COMPACTION, ARAGON_COMPACTION_THRESHOLD,
|
|
19
|
+
* ARAGON_COMPACTION_KEEP_TURNS, ARAGON_COMPACTION_SUBAGENTS,
|
|
20
|
+
* ARAGON_COMPACTION_ARCHIVE.
|
|
18
21
|
*
|
|
19
22
|
* READ ELSEWHERE, ON PURPOSE: `ARAGON_UPDATE_REGISTRY` and `npm_config_registry`
|
|
20
23
|
* are resolved by `update/registry.ts::resolveRegistryUrl`, NOT here, because
|
package/dist/config/env.js
CHANGED
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
* ARAGON_LOG_FILE, ARAGON_LOG_DIR, ARAGON_TRANSCRIPT_RETAIN,
|
|
15
15
|
* ARAGON_RENDER_GOVERNOR, ARAGON_MAX_RENDER_INTERVAL_MS,
|
|
16
16
|
* ARAGON_DIFF_RENDER, ARAGON_SYNC_OUTPUT,
|
|
17
|
-
* ARAGON_UPDATE
|
|
17
|
+
* ARAGON_UPDATE,
|
|
18
|
+
* ARAGON_COMPACTION, ARAGON_COMPACTION_THRESHOLD,
|
|
19
|
+
* ARAGON_COMPACTION_KEEP_TURNS, ARAGON_COMPACTION_SUBAGENTS,
|
|
20
|
+
* ARAGON_COMPACTION_ARCHIVE.
|
|
18
21
|
*
|
|
19
22
|
* READ ELSEWHERE, ON PURPOSE: `ARAGON_UPDATE_REGISTRY` and `npm_config_registry`
|
|
20
23
|
* are resolved by `update/registry.ts::resolveRegistryUrl`, NOT here, because
|
|
@@ -34,7 +37,7 @@ import process from 'node:process';
|
|
|
34
37
|
import dotenv from 'dotenv';
|
|
35
38
|
import { registerSecretsFrom } from '../logging/secret-registry.js';
|
|
36
39
|
import { clampLogLevel } from '../logging/levels.js';
|
|
37
|
-
import { clampMaxTokens, clampTheme, clampThinkingLevel, isAutoToken, } from './schema.js';
|
|
40
|
+
import { clampMaxTokens, clampTheme, clampThinkingLevel, isAutoToken, parseThresholdInput, } from './schema.js';
|
|
38
41
|
/**
|
|
39
42
|
* Load a project `.env` from the given directory into `process.env` (existing
|
|
40
43
|
* process env wins — dotenv never overrides already-set variables).
|
|
@@ -127,6 +130,29 @@ export function readEnvConfig() {
|
|
|
127
130
|
if (mouse !== undefined && mouse.length > 0) {
|
|
128
131
|
partial.mouse = mouse === '1' || mouse === 'true' || mouse === 'on' || mouse === 'yes';
|
|
129
132
|
}
|
|
133
|
+
// ARAGON_MOUSE_SELECT=0 turns drag-select off while leaving the wheel alone —
|
|
134
|
+
// the third rung of the mouse ladder (`--no-mouse` is the first two). Parsed by
|
|
135
|
+
// the POSITIVE list, exactly as its neighbour above is.
|
|
136
|
+
const mouseSelect = process.env.ARAGON_MOUSE_SELECT?.trim().toLowerCase();
|
|
137
|
+
if (mouseSelect !== undefined && mouseSelect.length > 0) {
|
|
138
|
+
partial.mouseSelect =
|
|
139
|
+
mouseSelect === '1' ||
|
|
140
|
+
mouseSelect === 'true' ||
|
|
141
|
+
mouseSelect === 'on' ||
|
|
142
|
+
mouseSelect === 'yes';
|
|
143
|
+
}
|
|
144
|
+
// ARAGON_SCROLL_RESUME_MS=<n> — idle delay before a paused viewport returns to
|
|
145
|
+
// the newest line; `0` disables auto-resume. THE ONLY CHANNEL BESIDES THE
|
|
146
|
+
// CONFIG FILE, because §6.1 gives this key no CLI flag on purpose. `load.ts`
|
|
147
|
+
// clamps it to [0, 120000]; a non-numeric value is LEFT ABSENT rather than
|
|
148
|
+
// written, so a typo falls through to the config file underneath instead of
|
|
149
|
+
// silently replacing it (the rule `ARAGON_MAX_TOKENS` above already follows).
|
|
150
|
+
const scrollResume = process.env.ARAGON_SCROLL_RESUME_MS?.trim();
|
|
151
|
+
if (scrollResume !== undefined && scrollResume.length > 0) {
|
|
152
|
+
const n = Number.parseInt(scrollResume, 10);
|
|
153
|
+
if (Number.isFinite(n) && n >= 0)
|
|
154
|
+
partial.scrollResumeMs = n;
|
|
155
|
+
}
|
|
130
156
|
// ARAGON_PLAN=1 starts the session in PLAN mode — the same channel story as
|
|
131
157
|
// ARAGON_FULLSCREEN, for terminals reached through a wrapper that owns argv.
|
|
132
158
|
const plan = process.env.ARAGON_PLAN?.trim().toLowerCase();
|
|
@@ -289,6 +315,70 @@ export function readEnvConfig() {
|
|
|
289
315
|
if (Object.keys(section).length > 0)
|
|
290
316
|
partial.fast = section;
|
|
291
317
|
}
|
|
318
|
+
// ARAGON_COMPACTION=0 turns context compaction off; the other two tune it
|
|
319
|
+
// (context-auto-compaction §4.3). Parsed by the POSITIVE list, exactly as
|
|
320
|
+
// ARAGON_FULLSCREEN / ARAGON_MOUSE / ARAGON_PLAN / ARAGON_TEAM / ARAGON_TODO /
|
|
321
|
+
// ARAGON_RETRY / ARAGON_FAST are — NOT by `envBool` below, whose NEGATIVE list
|
|
322
|
+
// disagrees with it on values like `ARAGON_COMPACTION=disable`.
|
|
323
|
+
//
|
|
324
|
+
// THREE VARS, AND DELIBERATELY NO `ARAGON_COMPACTION_ON_FAILURE` /
|
|
325
|
+
// `_USE_FAST_TIER` / `_WARN_THRESHOLD`. The rule this file states is that an
|
|
326
|
+
// environment variable exists only where a flag AND a config file are BOTH
|
|
327
|
+
// unreachable — a container, an ssh session, being spawned by another tool.
|
|
328
|
+
// "Is it on, when does it fire, and how much does it keep" passes that test;
|
|
329
|
+
// "what should it do if the summarizer 500s" does not, and every key that fails
|
|
330
|
+
// it is documentation debt plus a fifth place for the value to disagree with
|
|
331
|
+
// itself.
|
|
332
|
+
//
|
|
333
|
+
// ONE ACCUMULATED SECTION, ASSIGNED ONCE — the shape the four branches above
|
|
334
|
+
// all use, and NOT three `if` blocks each assigning `partial.compaction`. THE
|
|
335
|
+
// CAST IS WHAT WOULD MAKE THAT MISTAKE SILENT: a second assignment compiles
|
|
336
|
+
// clean and drops `enabled`.
|
|
337
|
+
const compaction = process.env.ARAGON_COMPACTION?.trim().toLowerCase();
|
|
338
|
+
const compactionThreshold = process.env.ARAGON_COMPACTION_THRESHOLD?.trim();
|
|
339
|
+
const compactionKeepTurns = process.env.ARAGON_COMPACTION_KEEP_TURNS?.trim();
|
|
340
|
+
// The two hardening kill switches (context-auto-compaction-hardening §4.3).
|
|
341
|
+
// They pass the same test the three above do: both name a behaviour that a
|
|
342
|
+
// container or an automated harness may need to switch off with no flag and no
|
|
343
|
+
// config file in reach - sub-agent compaction because it changes what a
|
|
344
|
+
// dispatch costs, and the archive because it writes conversation content to
|
|
345
|
+
// disk in an environment that may not permit it.
|
|
346
|
+
const compactionSubagents = process.env.ARAGON_COMPACTION_SUBAGENTS?.trim().toLowerCase();
|
|
347
|
+
const compactionArchive = process.env.ARAGON_COMPACTION_ARCHIVE?.trim().toLowerCase();
|
|
348
|
+
const positive = (v) => v === '1' || v === 'true' || v === 'on' || v === 'yes';
|
|
349
|
+
if ((compaction !== undefined && compaction.length > 0) ||
|
|
350
|
+
(compactionThreshold !== undefined && compactionThreshold.length > 0) ||
|
|
351
|
+
(compactionKeepTurns !== undefined && compactionKeepTurns.length > 0) ||
|
|
352
|
+
(compactionSubagents !== undefined && compactionSubagents.length > 0) ||
|
|
353
|
+
(compactionArchive !== undefined && compactionArchive.length > 0)) {
|
|
354
|
+
const section = {};
|
|
355
|
+
if (compaction !== undefined && compaction.length > 0) {
|
|
356
|
+
section.enabled = positive(compaction);
|
|
357
|
+
}
|
|
358
|
+
if (compactionSubagents !== undefined && compactionSubagents.length > 0) {
|
|
359
|
+
section.subagents = positive(compactionSubagents);
|
|
360
|
+
}
|
|
361
|
+
if (compactionArchive !== undefined && compactionArchive.length > 0) {
|
|
362
|
+
section.archive = positive(compactionArchive);
|
|
363
|
+
}
|
|
364
|
+
if (compactionThreshold !== undefined && compactionThreshold.length > 0) {
|
|
365
|
+
// Left ABSENT on a bad value rather than clamped to a default, so a typo
|
|
366
|
+
// falls through to the config layer instead of masking it for the session.
|
|
367
|
+
const parsed = parseThresholdInput(compactionThreshold);
|
|
368
|
+
if (parsed !== null)
|
|
369
|
+
section.threshold = parsed;
|
|
370
|
+
}
|
|
371
|
+
if (compactionKeepTurns !== undefined && compactionKeepTurns.length > 0) {
|
|
372
|
+
const n = Number.parseInt(compactionKeepTurns, 10);
|
|
373
|
+
if (Number.isFinite(n) && n > 0)
|
|
374
|
+
section.keepRecentTurns = n;
|
|
375
|
+
}
|
|
376
|
+
// A PARTIAL section, safe only because every consumer deep-merges it — the
|
|
377
|
+
// same contract the five sections above rely on.
|
|
378
|
+
if (Object.keys(section).length > 0) {
|
|
379
|
+
partial.compaction = section;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
292
382
|
// ARAGON_UPDATE=0|off|false turns auto-update off; `notify` reports without
|
|
293
383
|
// installing; 1|on|true|yes turns it on (cli-auto-update §4.2).
|
|
294
384
|
//
|
package/dist/config/load.d.ts
CHANGED
|
@@ -36,6 +36,19 @@ export interface CliFlags {
|
|
|
36
36
|
liveToolOutput?: boolean;
|
|
37
37
|
/** `--mouse` ⇒ true, `--no-mouse` ⇒ false, absent ⇒ undefined. */
|
|
38
38
|
mouse?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* `--mouse-select` ⇒ true, `--no-mouse-select` ⇒ false, absent ⇒ undefined
|
|
41
|
+
* (tui-selection-and-scroll-follow §6.1).
|
|
42
|
+
*
|
|
43
|
+
* DECLARED AS A PAIR, and carried through `toFlags`, for the reason the
|
|
44
|
+
* `mouse` note above it records: a flag that reaches neither `CliFlags` nor
|
|
45
|
+
* `toFlags` is inert with no compile error and no runtime error. `mouseSelect`
|
|
46
|
+
* is additionally PERSISTED and defaults to `true`, so a lone
|
|
47
|
+
* `--no-mouse-select` would make commander default `opts.mouseSelect` to
|
|
48
|
+
* `true` — indistinguishable from silence, and silently overriding a stored
|
|
49
|
+
* `false` on every run (the `--todo-panel` trap).
|
|
50
|
+
*/
|
|
51
|
+
mouseSelect?: boolean;
|
|
39
52
|
/** `--no-skills` ⇒ false. Turns the whole skill subsystem off (§7.5). */
|
|
40
53
|
skills?: boolean;
|
|
41
54
|
/** `--skill <name>` ×N — force Level 2 injection for this run. */
|
|
@@ -178,6 +191,24 @@ export interface CliFlags {
|
|
|
178
191
|
* config file and `ARAGON_UPDATE=notify`.
|
|
179
192
|
*/
|
|
180
193
|
update?: boolean;
|
|
194
|
+
/**
|
|
195
|
+
* `--compaction` ⇒ true, `--no-compaction` ⇒ false, absent ⇒ undefined
|
|
196
|
+
* (context-auto-compaction §4.3).
|
|
197
|
+
*
|
|
198
|
+
* DECLARED AS A PAIR — MANDATORY (C-13 / P1-5), for the reason `--team`,
|
|
199
|
+
* `--todo-panel`, `--render-governor`, `--retry`, `--fast` and `--update` each
|
|
200
|
+
* record in turn, and this one shares the WORST polarity with `--update`:
|
|
201
|
+
* `compaction.enabled` is PERSISTED and defaults to `true`, so a lone
|
|
202
|
+
* `--no-compaction` would make commander default `opts.compaction` to `true`,
|
|
203
|
+
* at which point the flag is indistinguishable from its own default and
|
|
204
|
+
* silently overwrites a stored `false` on EVERY run that passed no flag at all.
|
|
205
|
+
*
|
|
206
|
+
* That would make R-12's whole mitigation ("one config key restores the old
|
|
207
|
+
* behaviour exactly") FALSE — for a feature that spends the user's money.
|
|
208
|
+
*/
|
|
209
|
+
compaction?: boolean;
|
|
210
|
+
/** `--compaction-threshold <0..1|N%>` — session override for `threshold`. */
|
|
211
|
+
compactionThreshold?: string;
|
|
181
212
|
}
|
|
182
213
|
/**
|
|
183
214
|
* Resolve the effective config by merging all layers, then derive the runtime
|
package/dist/config/load.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* legitimately long single tool run can never be watchdog-killed.
|
|
7
7
|
*/
|
|
8
8
|
import process from 'node:process';
|
|
9
|
-
import { DEFAULT_CONFIG, IDLE_TIMEOUT_MARGIN_MS, clampAskRounds, clampDensity, clampHumanTimeout, clampLogConfig, clampFastConfig, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampUpdateConfig, clampTheme, clampThinkingLevel, clampMaxTokens, clampMaxRenderInterval, clampTranscriptRetain, clampTranscriptWindow, coercePositiveInt, isAutoToken, isSkillsToolPolicyMode, } from './schema.js';
|
|
9
|
+
import { DEFAULT_CONFIG, IDLE_TIMEOUT_MARGIN_MS, clampAskRounds, clampDensity, clampHumanTimeout, clampCompactionConfig, clampLogConfig, clampFastConfig, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampUpdateConfig, clampTheme, clampThinkingLevel, clampMaxTokens, clampMaxRenderInterval, clampScrollResumeMs, clampTranscriptRetain, clampTranscriptWindow, coercePositiveInt, isAutoToken, isSkillsToolPolicyMode, parseThresholdInput, } from './schema.js';
|
|
10
10
|
import { loadDotenv, readEnvConfig, readEnvDisabledSkills } from './env.js';
|
|
11
11
|
import { readConfigFile } from './store.js';
|
|
12
12
|
import { getConfigPath } from './app-paths.js';
|
|
@@ -59,6 +59,38 @@ function resolveMouse(flags, env, file) {
|
|
|
59
59
|
return file.mouse;
|
|
60
60
|
return DEFAULT_CONFIG.mouse;
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Drag-select: flag › env › file › default `true`
|
|
64
|
+
* (tui-selection-and-scroll-follow §6.1).
|
|
65
|
+
*
|
|
66
|
+
* SHAPED EXACTLY LIKE `resolveMouse` above, deliberately and not by copy-paste
|
|
67
|
+
* habit: it has the same four layers, the same "a persisted `true` is a value
|
|
68
|
+
* and not an opinion" property, and the same env var story. Reaching for the
|
|
69
|
+
* `hints` shape instead — `flags.x !== undefined ? … : file.x ?? DEFAULT`, which
|
|
70
|
+
* reads NO ENV AT ALL — would ship `ARAGON_MOUSE_SELECT` as documented-but-dead,
|
|
71
|
+
* which is precisely the failure the note above `resolveMouse` records for
|
|
72
|
+
* `ARAGON_MOUSE`.
|
|
73
|
+
*/
|
|
74
|
+
function resolveMouseSelect(flags, env, file) {
|
|
75
|
+
if (flags.mouseSelect !== undefined)
|
|
76
|
+
return flags.mouseSelect;
|
|
77
|
+
if (env.mouseSelect !== undefined)
|
|
78
|
+
return env.mouseSelect;
|
|
79
|
+
if (file.mouseSelect !== undefined)
|
|
80
|
+
return file.mouseSelect;
|
|
81
|
+
return DEFAULT_CONFIG.mouseSelect;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Idle scroll-resume delay: env › file › default 5000, clamped to [0, 120000].
|
|
85
|
+
*
|
|
86
|
+
* NO FLAG LAYER, and the absence is the design rather than an omission (§6.1):
|
|
87
|
+
* this key has no `--scroll-resume-ms`, so `CliFlags` carries no field for one
|
|
88
|
+
* and a resolver that read it would be reading a value nothing can ever set.
|
|
89
|
+
*/
|
|
90
|
+
function resolveScrollResumeMs(env, file) {
|
|
91
|
+
const raw = env.scrollResumeMs ?? file.scrollResumeMs;
|
|
92
|
+
return clampScrollResumeMs(raw, DEFAULT_CONFIG.scrollResumeMs);
|
|
93
|
+
}
|
|
62
94
|
/**
|
|
63
95
|
* Resolve whether logs reach a file: flag › env › an explicit `false` in the
|
|
64
96
|
* file › default `true`.
|
|
@@ -208,6 +240,33 @@ function resolveUpdateConfig(flags, env, file) {
|
|
|
208
240
|
...(flags.update !== undefined ? { mode: flags.update ? 'auto' : 'off' } : {}),
|
|
209
241
|
});
|
|
210
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Merge the `compaction` section across all four layers (defaults › file › env ›
|
|
245
|
+
* flags), context-auto-compaction §4.3.
|
|
246
|
+
*
|
|
247
|
+
* `!== undefined` ON `flags.compaction`, WHICH IS THE WHOLE POINT (C-13 / P1-5).
|
|
248
|
+
* The rule `resolveTeamConfig`, `resolveTodoConfig`, `resolveRetryConfig`,
|
|
249
|
+
* `resolveFastConfig` and `resolveUpdateConfig` each state once: commander
|
|
250
|
+
* materialises a lone `--no-compaction` as `opts.compaction = true` when the flag
|
|
251
|
+
* is absent, so a truthiness check cannot tell `--no-compaction` from "not
|
|
252
|
+
* passed" — and here the damage runs in the worst direction, silently re-enabling
|
|
253
|
+
* a subsystem the user turned off, on every flagless run, for a feature that
|
|
254
|
+
* spends money.
|
|
255
|
+
*
|
|
256
|
+
* `--compaction-threshold` is PARSED rather than spread, because `90%` and `0.9`
|
|
257
|
+
* are both legitimate spellings and a typo must change NOTHING rather than
|
|
258
|
+
* resolve to a default (`parseThresholdInput` returns `null`).
|
|
259
|
+
*/
|
|
260
|
+
function resolveCompactionConfig(flags, env, file) {
|
|
261
|
+
const thresholdFlag = flags.compactionThreshold !== undefined ? parseThresholdInput(flags.compactionThreshold) : null;
|
|
262
|
+
return clampCompactionConfig({
|
|
263
|
+
...DEFAULT_CONFIG.compaction,
|
|
264
|
+
...(file.compaction ?? {}),
|
|
265
|
+
...(env.compaction ?? {}),
|
|
266
|
+
...(flags.compaction !== undefined ? { enabled: flags.compaction } : {}),
|
|
267
|
+
...(thresholdFlag !== null ? { threshold: thresholdFlag } : {}),
|
|
268
|
+
});
|
|
269
|
+
}
|
|
211
270
|
/**
|
|
212
271
|
* Resolve the adaptive render governor: flag › env › file › default `true`
|
|
213
272
|
* (tui-render-performance L4).
|
|
@@ -460,6 +519,8 @@ export function loadConfig(flags = {}) {
|
|
|
460
519
|
density,
|
|
461
520
|
hints,
|
|
462
521
|
mouse: resolveMouse(flags, env.partial, file),
|
|
522
|
+
mouseSelect: resolveMouseSelect(flags, env.partial, file),
|
|
523
|
+
scrollResumeMs: resolveScrollResumeMs(env.partial, file),
|
|
463
524
|
// From `<home>/state.json`, not the config file — see `ui-state.ts`.
|
|
464
525
|
submitCount: readSubmitCount(),
|
|
465
526
|
startInPlanMode,
|
|
@@ -483,6 +544,7 @@ export function loadConfig(flags = {}) {
|
|
|
483
544
|
retry: resolveRetryConfig(flags, env.partial, file),
|
|
484
545
|
fast: resolveFastConfig(flags, env.partial, file),
|
|
485
546
|
update: resolveUpdateConfig(flags, env.partial, file),
|
|
547
|
+
compaction: resolveCompactionConfig(flags, env.partial, file),
|
|
486
548
|
cwd,
|
|
487
549
|
color,
|
|
488
550
|
colorLevel,
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -115,6 +115,36 @@ export declare const DEFAULT_DIFF_RENDER = true;
|
|
|
115
115
|
* because the frame differ already removes the flicker on its own.
|
|
116
116
|
*/
|
|
117
117
|
export declare const DEFAULT_SYNC_OUTPUT = true;
|
|
118
|
+
/**
|
|
119
|
+
* Drag-select + copy, and — because §4.4.1 gates `\x1b[?1002h` on exactly this
|
|
120
|
+
* value — whether motion reporting is requested from the terminal at all.
|
|
121
|
+
*
|
|
122
|
+
* That gating is what makes `false` BYTE-IDENTICAL to a pre-feature session
|
|
123
|
+
* rather than merely equivalent (AC-8 / D-15). Ignored when `mouse` is false,
|
|
124
|
+
* since there is no capture to select with.
|
|
125
|
+
*/
|
|
126
|
+
export declare const DEFAULT_MOUSE_SELECT = true;
|
|
127
|
+
/**
|
|
128
|
+
* Idle delay before a paused viewport returns to the newest line, in ms.
|
|
129
|
+
*
|
|
130
|
+
* Five seconds is chosen to be LONGER than a glance and SHORTER than a read.
|
|
131
|
+
* `0` disables auto-resume entirely, and it is a real value rather than a
|
|
132
|
+
* sentinel-shaped default: `shouldArmResume` refuses on it before any timer is
|
|
133
|
+
* created (AC-9), so the revert for Rule B is one config key.
|
|
134
|
+
*
|
|
135
|
+
* NO CLI FLAG (§6.1). It is a comfort preference, set once
|
|
136
|
+
* (`aragon config set scrollResumeMs 8000`) and then forgotten — the same
|
|
137
|
+
* argument this file already makes for `historyEnabled`. Adding a flag for every
|
|
138
|
+
* scalar is how a CLI ends up with sixty of them.
|
|
139
|
+
*/
|
|
140
|
+
export declare const DEFAULT_SCROLL_RESUME_MS = 5000;
|
|
141
|
+
/**
|
|
142
|
+
* `clampIntAllowingZero`, and the choice is load-bearing: `clampInt` delegates to
|
|
143
|
+
* `coercePositiveInt`, which returns the FALLBACK for `n <= 0` — so `0` would
|
|
144
|
+
* silently become 5000 and the documented off switch would not be an off switch.
|
|
145
|
+
* Exactly the trap `retry.maxRetries` needed this helper for.
|
|
146
|
+
*/
|
|
147
|
+
export declare function clampScrollResumeMs(v: unknown, fallback: number): number;
|
|
118
148
|
/** `ask_user` calls allowed per user turn. */
|
|
119
149
|
export declare const DEFAULT_PLAN_MAX_ASK_ROUNDS = 4;
|
|
120
150
|
/**
|
|
@@ -489,6 +519,94 @@ export declare const DEFAULT_UPDATE_CONFIG: UpdateConfig;
|
|
|
489
519
|
* cannot see it reading.
|
|
490
520
|
*/
|
|
491
521
|
export declare function clampUpdateConfig(raw: unknown): UpdateConfig;
|
|
522
|
+
export type CompactionFailureMode = 'truncate' | 'stop';
|
|
523
|
+
export interface CompactionConfig {
|
|
524
|
+
/**
|
|
525
|
+
* Whether a `ContextManager` is constructed at all. Default TRUE.
|
|
526
|
+
*
|
|
527
|
+
* THE ONLY KEY IN THIS SECTION THAT DEFAULTS ON, AND THE ONLY ONE READ ONCE AT
|
|
528
|
+
* CONSTRUCTION — the `team.enabled` / `todo.enabled` / `fast.enabled` rule.
|
|
529
|
+
*
|
|
530
|
+
* IT DEFAULTS TO `true` UNLIKE EVERY OTHER OPTIONAL SUBSYSTEM HERE, and that is
|
|
531
|
+
* deliberate (D-16): `fast.enabled` and `team.enabled` default off because they
|
|
532
|
+
* ADD behaviour the user did not ask for. This one REMOVES a failure the user
|
|
533
|
+
* did not ask for — without it, the answer to a full context window is a dead
|
|
534
|
+
* run. Byte-identity is still honoured: `--no-compaction` constructs no
|
|
535
|
+
* manager, subscribes nothing, allocates no registry, and leaves the engine
|
|
536
|
+
* loop with `ctx.contextManager === undefined`.
|
|
537
|
+
*/
|
|
538
|
+
enabled: boolean;
|
|
539
|
+
/** Occupancy ratio that triggers compaction. Read LIVE. */
|
|
540
|
+
threshold: number;
|
|
541
|
+
/**
|
|
542
|
+
* Where the status-bar gauge turns amber.
|
|
543
|
+
*
|
|
544
|
+
* CLAMPED JOINTLY WITH `threshold`, AND THE ORDER IS FIXED — see
|
|
545
|
+
* `clampCompactionConfig`. "Jointly" is not an instruction.
|
|
546
|
+
*/
|
|
547
|
+
warnThreshold: number;
|
|
548
|
+
/** Complete turns kept verbatim in the tail. Read LIVE. */
|
|
549
|
+
keepRecentTurns: number;
|
|
550
|
+
/**
|
|
551
|
+
* Summarize with the fast tier when it resolves. Default TRUE.
|
|
552
|
+
*
|
|
553
|
+
* A PREFERENCE, NOT THE COMMON PATH (P2-8). `resolveFastTier` returns
|
|
554
|
+
* `{ok:false, reason:'disabled'}` on `fast.enabled !== true` alone, and
|
|
555
|
+
* `fast.enabled` defaults to `false` — so out of the box the summarizer is the
|
|
556
|
+
* SESSION'S OWN MODEL, and the first compaction is a ~30 k-token call on it.
|
|
557
|
+
*/
|
|
558
|
+
useFastTier: boolean;
|
|
559
|
+
/** What happens when summarization fails outright. See §3.7 rungs 3 / 4. */
|
|
560
|
+
onFailure: CompactionFailureMode;
|
|
561
|
+
/**
|
|
562
|
+
* Give `task` children their own compaction
|
|
563
|
+
* (context-auto-compaction-hardening §3.4 / W3). Default TRUE.
|
|
564
|
+
*
|
|
565
|
+
* IT REVERSES D-15, WHOSE PREMISE IS MEASURABLY FALSE at the configured bounds:
|
|
566
|
+
* `team.maxTurnsPerSubagent` is 24 and `team.dispatchTimeoutMs` is 900 000, and
|
|
567
|
+
* 24 turns over fifteen minutes is the same profile as the lead run this
|
|
568
|
+
* feature exists for. When a child overflows today its history is discarded and
|
|
569
|
+
* the lead receives one partial sentence for the whole dispatch.
|
|
570
|
+
*
|
|
571
|
+
* `false` REPRODUCES ROUND 1 EXACTLY: `subagent.ts` spreads no `contextManager`
|
|
572
|
+
* key at all, so the child's loop gate tests an absent field.
|
|
573
|
+
*/
|
|
574
|
+
subagents: boolean;
|
|
575
|
+
/**
|
|
576
|
+
* Write the dropped messages to `<home>/compaction/` before adopting a splice
|
|
577
|
+
* (context-auto-compaction-hardening §3.5 / W4). Default TRUE.
|
|
578
|
+
*
|
|
579
|
+
* NOT UNDO (§12): restoring an over-full history restores the condition that
|
|
580
|
+
* triggered the compaction. This is fidelity on disk, so "the summary is wrong
|
|
581
|
+
* and the agent proceeded on a false record" becomes something a human can
|
|
582
|
+
* check rather than something they must accept.
|
|
583
|
+
*/
|
|
584
|
+
archive: boolean;
|
|
585
|
+
}
|
|
586
|
+
export declare const DEFAULT_COMPACTION_CONFIG: CompactionConfig;
|
|
587
|
+
/**
|
|
588
|
+
* THE single gate for every compaction-config read AND write, mirroring the six
|
|
589
|
+
* clamps above for the reason all of them record: hardening only the read path
|
|
590
|
+
* leaves a bad value on disk that reverts to the default on every launch, which
|
|
591
|
+
* presents to the user as "my setting won't stick".
|
|
592
|
+
*
|
|
593
|
+
* THE ORDER IS FIXED AND IT MATTERS (§4.2 / P2-5). `threshold` is clamped to
|
|
594
|
+
* `[0.5, 0.95]` FIRST, then `warnThreshold` to
|
|
595
|
+
* `[0.4, clampedThreshold - 0.05]`. The other order lets a file holding
|
|
596
|
+
* `{threshold: 0.6, warnThreshold: 0.9}` produce a warn mark ABOVE the trigger —
|
|
597
|
+
* a gauge that turns amber after it has already gone red. Both bounds of the
|
|
598
|
+
* second range stay reachable at the extremes: `threshold` floored at `0.5`
|
|
599
|
+
* gives `warnThreshold` a range of `[0.4, 0.45]`.
|
|
600
|
+
*/
|
|
601
|
+
export declare function clampCompactionConfig(raw: unknown): CompactionConfig;
|
|
602
|
+
/**
|
|
603
|
+
* Parse `0.9`, `90%` or `90` into a ratio, or `null` when it is neither.
|
|
604
|
+
*
|
|
605
|
+
* `null` RATHER THAN A CLAMPED DEFAULT, because this is a COMMAND argument and
|
|
606
|
+
* not a config value: `/compact threshold banana` must say so rather than
|
|
607
|
+
* silently setting 0.9 and reporting success.
|
|
608
|
+
*/
|
|
609
|
+
export declare function parseThresholdInput(raw: string): number | null;
|
|
492
610
|
export interface PersistedConfig {
|
|
493
611
|
version: number;
|
|
494
612
|
provider: string;
|
|
@@ -578,6 +696,14 @@ export interface PersistedConfig {
|
|
|
578
696
|
* heuristics for an explicit `true` to override (D-10).
|
|
579
697
|
*/
|
|
580
698
|
mouse: boolean;
|
|
699
|
+
/**
|
|
700
|
+
* Drag-select + copy in full-screen mode (tui-selection-and-scroll-follow
|
|
701
|
+
* §6.1). Ignored when `mouse` is false; also decides whether `?1002h` is
|
|
702
|
+
* written at all, so `false` is byte-identical to a pre-feature session.
|
|
703
|
+
*/
|
|
704
|
+
mouseSelect: boolean;
|
|
705
|
+
/** Idle ms before a paused viewport returns to the newest line; `0` disables. */
|
|
706
|
+
scrollResumeMs: number;
|
|
581
707
|
/** Start every session in PLAN mode (plan-mode §4.4). */
|
|
582
708
|
planModeDefault: boolean;
|
|
583
709
|
/** `ask_user` rounds allowed per user turn; clamped to [1, 10]. */
|
|
@@ -598,6 +724,8 @@ export interface PersistedConfig {
|
|
|
598
724
|
fast: FastConfig;
|
|
599
725
|
/** Auto-update. The EIGHTH nested object; scalars only (see UpdateConfig). */
|
|
600
726
|
update: UpdateConfig;
|
|
727
|
+
/** Context compaction. The NINTH nested object; scalars only (see CompactionConfig). */
|
|
728
|
+
compaction: CompactionConfig;
|
|
601
729
|
}
|
|
602
730
|
export declare const DEFAULT_CONFIG: PersistedConfig;
|
|
603
731
|
/**
|
|
@@ -727,6 +855,19 @@ export interface CliConfig {
|
|
|
727
855
|
* only). Resolved by `resolveMouse` in `load.ts`.
|
|
728
856
|
*/
|
|
729
857
|
mouse: boolean;
|
|
858
|
+
/**
|
|
859
|
+
* Whether this session may drag-select and copy.
|
|
860
|
+
*
|
|
861
|
+
* IT MUST EXIST HERE AND NOT ONLY IN `PersistedConfig`, for the reason
|
|
862
|
+
* `diffRender` above records at length: `runInteractive` reads
|
|
863
|
+
* `config.mouseSelect` — where `config` is a `CliConfig` — to decide the
|
|
864
|
+
* `?1002h` write, the controller and the `decorate` hook. A key added to the
|
|
865
|
+
* persisted shape alone would round-trip through `config set`, appear in
|
|
866
|
+
* `config list`, and never reach a single one of them.
|
|
867
|
+
*/
|
|
868
|
+
mouseSelect: boolean;
|
|
869
|
+
/** Idle ms before a paused viewport returns to the newest line; `0` disables. */
|
|
870
|
+
scrollResumeMs: number;
|
|
730
871
|
/**
|
|
731
872
|
* Whether this session opens in PLAN mode.
|
|
732
873
|
*
|
|
@@ -800,6 +941,24 @@ export interface CliConfig {
|
|
|
800
941
|
* and be discarded, with no compile error and no runtime error.
|
|
801
942
|
*/
|
|
802
943
|
update: UpdateConfig;
|
|
944
|
+
/**
|
|
945
|
+
* Resolved context-compaction settings (context-auto-compaction §4.2).
|
|
946
|
+
*
|
|
947
|
+
* `enabled` here decides whether `AgentController` CONSTRUCTS a
|
|
948
|
+
* `CompactionWiring` at all, which is what makes `false` byte-identical to a
|
|
949
|
+
* pre-feature build: no manager is passed to `new Agent({...})`, nothing is
|
|
950
|
+
* subscribed, no registry is allocated, and the loop's checkpoint is one `if`
|
|
951
|
+
* against an absent field. The other five keys are read LIVE on every use, so
|
|
952
|
+
* `/compact threshold 0.8` takes effect in the running session.
|
|
953
|
+
*
|
|
954
|
+
* IT MUST EXIST HERE AND NOT ONLY IN `PersistedConfig`, for the reason
|
|
955
|
+
* `showThinking`, `liveToolOutput`, `diffRender`, `mouseSelect` and `update`
|
|
956
|
+
* each record above: the controller and the compactor read `config.compaction`,
|
|
957
|
+
* where `config` is a `CliConfig`, so a key added to the persisted shape alone
|
|
958
|
+
* would round-trip through `config set`, appear in `config list` — and never
|
|
959
|
+
* reach either of them.
|
|
960
|
+
*/
|
|
961
|
+
compaction: CompactionConfig;
|
|
803
962
|
/**
|
|
804
963
|
* Lifetime submit count driving the composer hint fade (`HINT_FADE_AFTER`).
|
|
805
964
|
*
|