@aragon-agent/cli 0.6.12 → 0.6.14
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 +27 -0
- package/README.md +108 -31
- package/dist/agent/controller.d.ts +38 -2
- package/dist/agent/controller.js +185 -34
- package/dist/agent/model-profile-settings.d.ts +31 -0
- package/dist/agent/model-profile-settings.js +208 -0
- package/dist/agent/queued-messages.d.ts +12 -0
- package/dist/agent/queued-messages.js +18 -0
- package/dist/agent/reducer.d.ts +13 -1
- package/dist/agent/reducer.js +52 -12
- package/dist/boot/guard.d.ts +3 -3
- package/dist/boot/guard.js +3 -3
- package/dist/cli.js +48 -16
- package/dist/commands/builtins.js +66 -39
- package/dist/commands/queue-command.d.ts +3 -0
- package/dist/commands/queue-command.js +5 -0
- package/dist/commands/registry.d.ts +3 -0
- package/dist/compaction/child.d.ts +4 -2
- package/dist/compaction/child.js +8 -1
- package/dist/compaction/compactor.d.ts +7 -2
- package/dist/compaction/compactor.js +21 -16
- package/dist/compaction/context-command.js +10 -3
- package/dist/compaction/meter.js +2 -0
- package/dist/compaction/pressure.d.ts +1 -0
- package/dist/compaction/pressure.js +1 -0
- package/dist/compaction/types.d.ts +2 -0
- package/dist/compaction/wiring.d.ts +4 -3
- package/dist/compaction/wiring.js +10 -2
- package/dist/config/cli-commands.d.ts +2 -0
- package/dist/config/cli-commands.js +16 -4
- package/dist/config/load.d.ts +5 -2
- package/dist/config/load.js +23 -12
- package/dist/config/model-profile-resolution.d.ts +20 -0
- package/dist/config/model-profile-resolution.js +81 -0
- package/dist/config/model-profile-store.d.ts +67 -0
- package/dist/config/model-profile-store.js +153 -0
- package/dist/config/model-profiles.d.ts +44 -0
- package/dist/config/model-profiles.js +121 -0
- package/dist/config/schema.d.ts +11 -2
- package/dist/config/store.d.ts +11 -1
- package/dist/config/store.js +43 -27
- package/dist/fast/resolve.d.ts +2 -1
- package/dist/fast/resolve.js +6 -4
- package/dist/fast/wiring.d.ts +5 -3
- package/dist/fast/wiring.js +8 -4
- package/dist/input/stdin-filter.js +3 -2
- package/dist/logging/install.js +4 -2
- package/dist/logging/secret-registry.d.ts +2 -0
- package/dist/logging/secret-registry.js +18 -0
- package/dist/team/runtime.d.ts +2 -1
- package/dist/team/subagent.d.ts +3 -1
- package/dist/team/subagent.js +3 -1
- package/dist/ui/ActivityLine.d.ts +6 -70
- package/dist/ui/ActivityLine.js +12 -34
- package/dist/ui/App.d.ts +1 -0
- package/dist/ui/App.js +116 -215
- package/dist/ui/BottomStatusRow.d.ts +6 -86
- package/dist/ui/BottomStatusRow.js +11 -26
- package/dist/ui/Composer.d.ts +16 -83
- package/dist/ui/Composer.js +9 -100
- package/dist/ui/Logo.d.ts +3 -5
- package/dist/ui/Logo.js +4 -8
- package/dist/ui/PromptInput.d.ts +4 -1
- package/dist/ui/PromptInput.js +44 -35
- package/dist/ui/QueuePanel.d.ts +8 -0
- package/dist/ui/QueuePanel.js +9 -0
- package/dist/ui/QueueStatusRow.d.ts +2 -0
- package/dist/ui/QueueStatusRow.js +1 -1
- package/dist/ui/StatusBar.d.ts +13 -149
- package/dist/ui/StatusBar.js +27 -142
- package/dist/ui/capabilities.d.ts +2 -0
- package/dist/ui/capabilities.js +6 -0
- package/dist/ui/clipboard-task.d.ts +29 -0
- package/dist/ui/clipboard-task.js +66 -0
- package/dist/ui/clipboard.d.ts +29 -50
- package/dist/ui/clipboard.js +141 -75
- package/dist/ui/color-runtime.d.ts +5 -0
- package/dist/ui/color-runtime.js +29 -0
- package/dist/ui/composer-limits.d.ts +3 -4
- package/dist/ui/composer-limits.js +4 -9
- package/dist/ui/composer-rows.d.ts +1 -1
- package/dist/ui/composer-rows.js +24 -137
- package/dist/ui/editor-navigation.d.ts +45 -0
- package/dist/ui/editor-navigation.js +85 -0
- package/dist/ui/editor-reducer.d.ts +4 -0
- package/dist/ui/editor-reducer.js +29 -15
- package/dist/ui/glyphs.js +10 -8
- package/dist/ui/ink-runtime.d.ts +3 -0
- package/dist/ui/ink-runtime.js +30 -0
- package/dist/ui/interaction-copy.d.ts +77 -0
- package/dist/ui/interaction-copy.js +40 -0
- package/dist/ui/interaction-hints.d.ts +18 -0
- package/dist/ui/interaction-hints.js +92 -0
- package/dist/ui/layout/budget.js +1 -1
- package/dist/ui/layout/queue-layout.d.ts +19 -0
- package/dist/ui/layout/queue-layout.js +26 -0
- package/dist/ui/layout/status-layout.d.ts +55 -0
- package/dist/ui/layout/status-layout.js +110 -0
- package/dist/ui/layout/todo-layout.d.ts +1 -0
- package/dist/ui/layout/todo-layout.js +1 -1
- package/dist/ui/overlays/HelpOverlay.js +8 -8
- package/dist/ui/overlays/ModelProfileEditor.d.ts +12 -0
- package/dist/ui/overlays/ModelProfileEditor.js +103 -0
- package/dist/ui/overlays/ModelProfilePicker.d.ts +35 -0
- package/dist/ui/overlays/ModelProfilePicker.js +167 -0
- package/dist/ui/overlays/QueueOverlay.d.ts +22 -0
- package/dist/ui/overlays/QueueOverlay.js +79 -0
- package/dist/ui/overlays/SettingsScreen.d.ts +9 -2
- package/dist/ui/overlays/SettingsScreen.js +347 -3
- package/dist/ui/overlays/model-profile-state.d.ts +74 -0
- package/dist/ui/overlays/model-profile-state.js +119 -0
- package/dist/ui/render-cache.d.ts +2 -2
- package/dist/ui/render-cache.js +4 -3
- package/dist/ui/run-status-row.d.ts +7 -19
- package/dist/ui/run-status-row.js +2 -18
- package/dist/ui/selection/selection-controller.d.ts +2 -2
- package/dist/ui/selection/selection-controller.js +1 -0
- package/dist/ui/use-wheel-routing.js +2 -1
- package/package.json +2 -2
package/dist/config/schema.d.ts
CHANGED
|
@@ -671,6 +671,7 @@ export declare function clampBashConfig(raw: unknown): BashConfig;
|
|
|
671
671
|
*/
|
|
672
672
|
export declare function parseThresholdInput(raw: string): number | null;
|
|
673
673
|
export interface PersistedConfig {
|
|
674
|
+
modelProfiles?: import('./model-profiles.js').ModelProfilesConfig;
|
|
674
675
|
version: number;
|
|
675
676
|
provider: string;
|
|
676
677
|
model: string;
|
|
@@ -838,6 +839,14 @@ export declare const LEGACY_STATE_KEYS: readonly ["promptHistory", "submitCount"
|
|
|
838
839
|
*/
|
|
839
840
|
export declare function stripLegacyStateKeys<T extends object>(raw: T): T;
|
|
840
841
|
export interface CliConfig {
|
|
842
|
+
/** A committed model snapshot failed to apply; no further requests may start. */
|
|
843
|
+
modelSettingsRestartRequired?: boolean;
|
|
844
|
+
modelProfiles?: import('./model-profiles.js').ModelProfilesConfig;
|
|
845
|
+
modelProfileState?: import('./model-profiles.js').ModelProfilesRuntime;
|
|
846
|
+
apiKeyOverrideTarget?: {
|
|
847
|
+
provider: string;
|
|
848
|
+
baseUrl: string | null;
|
|
849
|
+
};
|
|
841
850
|
provider: string;
|
|
842
851
|
model: string;
|
|
843
852
|
baseUrl?: string;
|
|
@@ -1088,9 +1097,9 @@ export interface CliConfig {
|
|
|
1088
1097
|
cwd: string;
|
|
1089
1098
|
/** Whether ANSI color is enabled. */
|
|
1090
1099
|
color: boolean;
|
|
1091
|
-
/**
|
|
1100
|
+
/** Resolved color depth: TUI policy or non-interactive terminal detection. */
|
|
1092
1101
|
colorLevel?: 0 | 1 | 2 | 3;
|
|
1093
|
-
/**
|
|
1102
|
+
/** TUI always enables Unicode; non-interactive output uses detection. */
|
|
1094
1103
|
unicode?: boolean;
|
|
1095
1104
|
/** One-shot `--api-key` override; applies to the active provider only. */
|
|
1096
1105
|
apiKeyOverride?: string;
|
package/dist/config/store.d.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* the drift the header of that module warns about.
|
|
11
11
|
*/
|
|
12
12
|
import { getConfigPath, getSessionsDir } from './app-paths.js';
|
|
13
|
+
import { type ModelSettingsPatch } from './model-profile-store.js';
|
|
14
|
+
import { type ModelProfilesConfig } from './model-profiles.js';
|
|
13
15
|
import { type PersistedConfig } from './schema.js';
|
|
14
16
|
export { getConfigPath, getSessionsDir };
|
|
15
17
|
export interface ConfigFileRead {
|
|
@@ -40,6 +42,8 @@ export declare function writeConfigFile(config: PersistedConfig): void;
|
|
|
40
42
|
* Unlike `readConfigFile`, this always returns a complete `PersistedConfig`.
|
|
41
43
|
*/
|
|
42
44
|
export declare function loadPersistedConfig(): PersistedConfig;
|
|
45
|
+
/** Fill legacy defaults without projecting bindings or discarding unknown profile data. */
|
|
46
|
+
export declare function normalizePersistedConfig(input: Partial<PersistedConfig>): PersistedConfig;
|
|
43
47
|
/**
|
|
44
48
|
* Read the persisted config, apply a patch, write it back atomically, and
|
|
45
49
|
* return the merged result. This is the single write path used by the settings
|
|
@@ -59,4 +63,10 @@ export declare function loadPersistedConfig(): PersistedConfig;
|
|
|
59
63
|
* a third SECTION, but it is still one level deep (scalars only), so the same
|
|
60
64
|
* hand-written merge covers it — and it must stay that way for that reason.
|
|
61
65
|
*/
|
|
62
|
-
export declare function updatePersistedConfig(patch:
|
|
66
|
+
export declare function updatePersistedConfig(patch: ModelSettingsPatch & {
|
|
67
|
+
modelProfiles?: ModelProfilesConfig;
|
|
68
|
+
}): PersistedConfig;
|
|
69
|
+
/** Merge an already adapted patch, replacing profile arrays as one complete section. */
|
|
70
|
+
export declare function mergePersistedConfig(current: PersistedConfig, patch: ModelSettingsPatch & {
|
|
71
|
+
modelProfiles?: ModelProfilesConfig;
|
|
72
|
+
}): PersistedConfig;
|
package/dist/config/store.js
CHANGED
|
@@ -9,11 +9,14 @@
|
|
|
9
9
|
* a second name for `skills/paths.ts::getUserSkillsDir()`, which is precisely
|
|
10
10
|
* the drift the header of that module warns about.
|
|
11
11
|
*/
|
|
12
|
-
import { existsSync, mkdirSync,
|
|
12
|
+
import { existsSync, mkdirSync, renameSync, writeFileSync, chmodSync, rmSync } from 'node:fs';
|
|
13
|
+
import { randomUUID } from 'node:crypto';
|
|
13
14
|
import { dirname } from 'node:path';
|
|
14
15
|
import process from 'node:process';
|
|
15
16
|
import { getConfigPath, getSessionsDir } from './app-paths.js';
|
|
16
|
-
import { registerSecretsFrom } from '../logging/secret-registry.js';
|
|
17
|
+
import { registerProfileSecrets, registerSecretsFrom } from '../logging/secret-registry.js';
|
|
18
|
+
import { adaptLegacyConnectionPatch, ModelProfileConfigError, readModelSettingsDisk } from './model-profile-store.js';
|
|
19
|
+
import { normalizeModelProfiles } from './model-profiles.js';
|
|
17
20
|
import { clampBashConfig, CONFIG_VERSION, DEFAULT_CONFIG, clampCompactionConfig, clampFastConfig, clampLogConfig, clampMaxTokens, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampContextWindow, clampUpdateConfig, isAutoToken, stripLegacyStateKeys, } from './schema.js';
|
|
18
21
|
/**
|
|
19
22
|
* Normalize `maxTokens` for both directions of the config file.
|
|
@@ -62,25 +65,12 @@ export { getConfigPath, getSessionsDir };
|
|
|
62
65
|
* workflow, so the failure mode had to become visible.
|
|
63
66
|
*/
|
|
64
67
|
export function readConfigFile() {
|
|
65
|
-
const
|
|
66
|
-
if (!
|
|
67
|
-
return { config: null };
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (parsed && typeof parsed === 'object') {
|
|
72
|
-
// Retired layout preference: tolerate old files without restoring a UI mode.
|
|
73
|
-
delete parsed.fullscreen;
|
|
74
|
-
return { config: parsed };
|
|
75
|
-
}
|
|
76
|
-
return { config: null, parseError: `${file} does not contain a JSON object` };
|
|
77
|
-
}
|
|
78
|
-
catch (err) {
|
|
79
|
-
return {
|
|
80
|
-
config: null,
|
|
81
|
-
parseError: `${file}: ${err instanceof Error ? err.message : String(err)}`,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
68
|
+
const read = readModelSettingsDisk();
|
|
69
|
+
if (!read.ok)
|
|
70
|
+
return { config: null, parseError: `${getConfigPath()}: ${read.error}` };
|
|
71
|
+
if (read.parsed)
|
|
72
|
+
delete read.parsed.fullscreen;
|
|
73
|
+
return { config: read.parsed };
|
|
84
74
|
}
|
|
85
75
|
// ---------------------------------------------------------------------------
|
|
86
76
|
// Write (atomic + 0600)
|
|
@@ -97,10 +87,19 @@ function ensureDir(dir) {
|
|
|
97
87
|
export function writeConfigFile(config) {
|
|
98
88
|
const file = getConfigPath();
|
|
99
89
|
ensureDir(dirname(file));
|
|
100
|
-
const tmp = `${file}.${process.pid}.tmp`;
|
|
90
|
+
const tmp = `${file}.${process.pid}.${randomUUID()}.tmp`;
|
|
101
91
|
const json = `${JSON.stringify(config, null, 2)}\n`;
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
try {
|
|
93
|
+
writeFileSync(tmp, json, { encoding: 'utf-8', mode: 0o600, flag: 'wx' });
|
|
94
|
+
renameSync(tmp, file);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
try {
|
|
98
|
+
rmSync(tmp, { force: true });
|
|
99
|
+
}
|
|
100
|
+
catch { /* Only our temporary path is eligible. */ }
|
|
101
|
+
throw new ModelProfileConfigError('write_failed');
|
|
102
|
+
}
|
|
104
103
|
// rename may not preserve mode on every platform; re-chmod on POSIX.
|
|
105
104
|
if (process.platform !== 'win32') {
|
|
106
105
|
try {
|
|
@@ -116,12 +115,17 @@ export function writeConfigFile(config) {
|
|
|
116
115
|
* Unlike `readConfigFile`, this always returns a complete `PersistedConfig`.
|
|
117
116
|
*/
|
|
118
117
|
export function loadPersistedConfig() {
|
|
118
|
+
return normalizePersistedConfig(readConfigFile().config ?? {});
|
|
119
|
+
}
|
|
120
|
+
/** Fill legacy defaults without projecting bindings or discarding unknown profile data. */
|
|
121
|
+
export function normalizePersistedConfig(input) {
|
|
119
122
|
// STRIP BEFORE THE SPREAD, not after. `partial` is the raw file, so any
|
|
120
123
|
// `promptHistory` / `submitCount` / `mouseNoticeSeen` / `recentModels` left
|
|
121
124
|
// on disk would otherwise ride the spread into `merged` and be written back
|
|
122
125
|
// out by `updatePersistedConfig` — the "I deleted it and it grew back" bug
|
|
123
126
|
// that `stripLegacyStateKeys` exists to make impossible (§4.5).
|
|
124
|
-
const partial = stripLegacyStateKeys(
|
|
127
|
+
const partial = stripLegacyStateKeys(input);
|
|
128
|
+
delete partial.fullscreen;
|
|
125
129
|
return {
|
|
126
130
|
...DEFAULT_CONFIG,
|
|
127
131
|
...partial,
|
|
@@ -207,14 +211,27 @@ export function loadPersistedConfig() {
|
|
|
207
211
|
* hand-written merge covers it — and it must stay that way for that reason.
|
|
208
212
|
*/
|
|
209
213
|
export function updatePersistedConfig(patch) {
|
|
214
|
+
const read = readModelSettingsDisk();
|
|
215
|
+
if (!read.ok)
|
|
216
|
+
throw new ModelProfileConfigError('read_failed');
|
|
217
|
+
const adapted = adaptLegacyConnectionPatch({ current: read.config, patch });
|
|
218
|
+
const merged = mergePersistedConfig(read.config, adapted);
|
|
219
|
+
writeConfigFile(merged);
|
|
220
|
+
return merged;
|
|
221
|
+
}
|
|
222
|
+
/** Merge an already adapted patch, replacing profile arrays as one complete section. */
|
|
223
|
+
export function mergePersistedConfig(current, patch) {
|
|
210
224
|
// Registration site 5. Whatever route a key took to get here, this is the one
|
|
211
225
|
// function that writes it to disk, so this is the last place it can be added
|
|
212
226
|
// to the redactor's backstop before it also starts appearing in log records.
|
|
213
227
|
registerSecretsFrom(patch.apiKeys);
|
|
214
|
-
|
|
228
|
+
registerProfileSecrets(patch);
|
|
229
|
+
const submittedProfiles = patch.modelProfiles === undefined
|
|
230
|
+
? {} : { modelProfiles: normalizeModelProfiles(patch.modelProfiles) };
|
|
215
231
|
const merged = {
|
|
216
232
|
...current,
|
|
217
233
|
...patch,
|
|
234
|
+
...submittedProfiles,
|
|
218
235
|
version: CONFIG_VERSION,
|
|
219
236
|
// The write half of the gate: without it `config set maxTokens 900000` puts
|
|
220
237
|
// a number on disk that the read path silently rewrites on every launch.
|
|
@@ -273,6 +290,5 @@ export function updatePersistedConfig(patch) {
|
|
|
273
290
|
// `bash_output` / `bash_kill` from the next launch onward.
|
|
274
291
|
bash: clampBashConfig({ ...current.bash, ...(patch.bash ?? {}) }),
|
|
275
292
|
};
|
|
276
|
-
writeConfigFile(merged);
|
|
277
293
|
return merged;
|
|
278
294
|
}
|
package/dist/fast/resolve.d.ts
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* at construction is a tier that can be describing a provider the session no
|
|
19
19
|
* longer uses.
|
|
20
20
|
*/
|
|
21
|
+
import type { ModelRole } from '../config/model-profiles.js';
|
|
21
22
|
import { type CliConfig } from '../config/schema.js';
|
|
22
23
|
import type { FastTier } from './types.js';
|
|
23
24
|
/**
|
|
@@ -29,7 +30,7 @@ import type { FastTier } from './types.js';
|
|
|
29
30
|
* `--api-key` override. Injected rather than reimplemented, because a second
|
|
30
31
|
* key resolver is a second answer to "why does it say no key?".
|
|
31
32
|
*/
|
|
32
|
-
export declare function resolveFastTier(config: CliConfig, hasKey: (providerId: string) => boolean): FastTier;
|
|
33
|
+
export declare function resolveFastTier(config: CliConfig, hasKey: (providerId: string, role?: ModelRole) => boolean): FastTier;
|
|
33
34
|
/**
|
|
34
35
|
* The one-line notice for a tier the user switched on that cannot resolve, or
|
|
35
36
|
* `null` when there is nothing worth saying.
|
package/dist/fast/resolve.js
CHANGED
|
@@ -47,7 +47,7 @@ export function resolveFastTier(config, hasKey) {
|
|
|
47
47
|
// different settings.
|
|
48
48
|
if (!isAdapterProvider(provider))
|
|
49
49
|
return { ok: false, reason: 'no_adapter' };
|
|
50
|
-
if (!hasKey(provider))
|
|
50
|
+
if (!hasKey(provider, 'fast'))
|
|
51
51
|
return { ok: false, reason: 'no_key' };
|
|
52
52
|
// 6. A fast tier on the SAME provider inherits the session's base URL: a user
|
|
53
53
|
// pointing the CLI at a gateway means both models, not one. A fast tier on
|
|
@@ -56,9 +56,11 @@ export function resolveFastTier(config, hasKey) {
|
|
|
56
56
|
const explicitBaseUrl = fast.baseUrl.trim();
|
|
57
57
|
const baseUrl = explicitBaseUrl.length > 0
|
|
58
58
|
? explicitBaseUrl
|
|
59
|
-
:
|
|
60
|
-
?
|
|
61
|
-
:
|
|
59
|
+
: config.modelProfiles?.fastId && !config.modelProfileState?.fast.invalid
|
|
60
|
+
? undefined
|
|
61
|
+
: provider === config.provider
|
|
62
|
+
? config.baseUrl
|
|
63
|
+
: undefined;
|
|
62
64
|
const ref = {
|
|
63
65
|
providerId: provider,
|
|
64
66
|
modelId,
|
package/dist/fast/wiring.d.ts
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
* inside its own loop with an error naming neither the tier nor the setting that
|
|
31
31
|
* caused it (`agent-loop.ts:140-145`).
|
|
32
32
|
*/
|
|
33
|
+
import type { ModelRole } from '../config/model-profiles.js';
|
|
33
34
|
import { type AgentEvent, type AssistantMessage, type LLMRequest, type ModelRef, type ThinkingLevel } from '@aragon-agent/core';
|
|
34
35
|
import type { CliConfig } from '../config/schema.js';
|
|
35
36
|
import type { NoticeLevel } from '../agent/reducer.js';
|
|
@@ -38,8 +39,8 @@ export interface FastWiringDeps {
|
|
|
38
39
|
/** Read LIVE on every call - the controller replaces the object on mutation. */
|
|
39
40
|
getConfig: () => CliConfig;
|
|
40
41
|
/** `AgentController.hasApiKey`, so there is exactly one key resolver. */
|
|
41
|
-
hasKey: (providerId: string) => boolean;
|
|
42
|
-
getApiKey: (providerId: string) => string | undefined;
|
|
42
|
+
hasKey: (providerId: string, role?: ModelRole) => boolean;
|
|
43
|
+
getApiKey: (providerId: string, role?: ModelRole) => string | undefined;
|
|
43
44
|
/** Whether the static price table knows this model (C-11 / RV-4). */
|
|
44
45
|
isPricedModel: (ref: Pick<ModelRef, 'providerId' | 'modelId'>) => boolean;
|
|
45
46
|
/** The lead agent's event stream and steering surface. */
|
|
@@ -145,7 +146,7 @@ export declare class FastWiring {
|
|
|
145
146
|
* resolved model id and a prompt naming a model the tier will not use is worse
|
|
146
147
|
* than no prompt at all.
|
|
147
148
|
*/
|
|
148
|
-
onConfigChanged(): void;
|
|
149
|
+
onConfigChanged(refreshPrompt?: boolean, enabled?: boolean): void;
|
|
149
150
|
/**
|
|
150
151
|
* The startup notice for a configuration mistake that is otherwise invisible
|
|
151
152
|
* (§3.3). Raised once, at construction, through the controller's `notify`.
|
|
@@ -162,6 +163,7 @@ export declare class FastWiring {
|
|
|
162
163
|
resolveTier(tier: FastTierName): {
|
|
163
164
|
ref: ModelRef;
|
|
164
165
|
thinkingLevel: ThinkingLevel;
|
|
166
|
+
role?: ModelRole;
|
|
165
167
|
};
|
|
166
168
|
/** The resolved fast `ModelRef`, or `null` - for per-tier cost lookup (§3.6). */
|
|
167
169
|
fastRef(): ModelRef | null;
|
package/dist/fast/wiring.js
CHANGED
|
@@ -114,7 +114,7 @@ export class FastWiring {
|
|
|
114
114
|
getTier: () => this.tier,
|
|
115
115
|
getConfig: () => this.deps.getConfig().fast,
|
|
116
116
|
available: () => this.available(),
|
|
117
|
-
getApiKey: deps.getApiKey,
|
|
117
|
+
getApiKey: (id) => deps.getApiKey(id, 'fast'),
|
|
118
118
|
emit: (event) => this.emit(event),
|
|
119
119
|
// The reviewer announces its own self-disable with a `tier_changed`, and
|
|
120
120
|
// only the wiring can build the snapshot that carries it.
|
|
@@ -202,7 +202,9 @@ export class FastWiring {
|
|
|
202
202
|
* resolved model id and a prompt naming a model the tier will not use is worse
|
|
203
203
|
* than no prompt at all.
|
|
204
204
|
*/
|
|
205
|
-
onConfigChanged() {
|
|
205
|
+
onConfigChanged(refreshPrompt = true, enabled) {
|
|
206
|
+
if (enabled !== undefined)
|
|
207
|
+
this.enabled = enabled;
|
|
206
208
|
const next = resolveFastTier(this.deps.getConfig(), this.deps.hasKey);
|
|
207
209
|
const before = this.tier;
|
|
208
210
|
this.tier = next;
|
|
@@ -219,7 +221,8 @@ export class FastWiring {
|
|
|
219
221
|
this.deps.notify('warn', text);
|
|
220
222
|
}
|
|
221
223
|
}
|
|
222
|
-
|
|
224
|
+
if (refreshPrompt)
|
|
225
|
+
this.deps.onPromptChanged();
|
|
223
226
|
this.emit({ type: 'tier_changed', snapshot: this.snapshot() });
|
|
224
227
|
}
|
|
225
228
|
/**
|
|
@@ -243,7 +246,7 @@ export class FastWiring {
|
|
|
243
246
|
resolveTier(tier) {
|
|
244
247
|
const config = this.deps.getConfig();
|
|
245
248
|
if (tier === 'fast' && this.delegationAvailable() && this.tier.ok) {
|
|
246
|
-
return { ref: this.tier.ref, thinkingLevel: this.tier.thinkingLevel };
|
|
249
|
+
return { ref: this.tier.ref, thinkingLevel: this.tier.thinkingLevel, role: 'fast' };
|
|
247
250
|
}
|
|
248
251
|
return {
|
|
249
252
|
ref: {
|
|
@@ -252,6 +255,7 @@ export class FastWiring {
|
|
|
252
255
|
...(config.baseUrl ? { baseUrl: config.baseUrl } : {}),
|
|
253
256
|
},
|
|
254
257
|
thinkingLevel: config.thinkingLevel,
|
|
258
|
+
role: 'main',
|
|
255
259
|
};
|
|
256
260
|
}
|
|
257
261
|
/** The resolved fast `ModelRef`, or `null` - for per-tier cost lookup (§3.6). */
|
|
@@ -228,8 +228,9 @@ export function createStdinFilter(real, features, bridge, onWarn) {
|
|
|
228
228
|
burstTimer = arm(flushBurst, PASTE_BURST_MS);
|
|
229
229
|
return;
|
|
230
230
|
}
|
|
231
|
-
//
|
|
232
|
-
//
|
|
231
|
+
// Ink conflates DEL Backspace with CSI Delete. Normalize only keyboard
|
|
232
|
+
// text, after burst classification, preserving ESC for Alt+Backspace.
|
|
233
|
+
text = text.replace(/\x7f/g, '\x08');
|
|
233
234
|
if (!features.mouse) {
|
|
234
235
|
writeInput(text);
|
|
235
236
|
return;
|
package/dist/logging/install.js
CHANGED
|
@@ -42,7 +42,7 @@ import { readConfigFile } from '../config/store.js';
|
|
|
42
42
|
import { clampLogConfig } from '../config/schema.js';
|
|
43
43
|
import { clampLogLevel } from './levels.js';
|
|
44
44
|
import { Logger, setActiveLogger } from './logger.js';
|
|
45
|
-
import { registerSecretsFrom } from './secret-registry.js';
|
|
45
|
+
import { registerProfileSecrets, registerSecretsFrom } from './secret-registry.js';
|
|
46
46
|
/** POSIX signal numbers for the `128 + signo` exit-code convention. */
|
|
47
47
|
const SIGNAL_NUMBERS = { SIGINT: 2, SIGTERM: 15, SIGHUP: 1 };
|
|
48
48
|
let screenRestore = () => { };
|
|
@@ -213,7 +213,9 @@ export function installLogging(opts = {}) {
|
|
|
213
213
|
// Registration site 1 (§4.4.3): whatever the config file already holds. Sites
|
|
214
214
|
// 2, 3, 4 and 5 add the env, the merged view plus `--api-key`, the settings
|
|
215
215
|
// screen, and every persisted write respectively.
|
|
216
|
-
|
|
216
|
+
const persisted = readConfigFile().config;
|
|
217
|
+
registerSecretsFrom(persisted?.apiKeys ?? undefined);
|
|
218
|
+
registerProfileSecrets(persisted);
|
|
217
219
|
const warning = getHomeResolutionWarning();
|
|
218
220
|
if (warning)
|
|
219
221
|
logger.warn('cli', 'home_resolution_fallback', { reason: warning });
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
export declare function registerSecret(value: string | undefined | null): void;
|
|
19
19
|
/** Convenience for the `apiKeys` maps every registration site happens to hold. */
|
|
20
20
|
export declare function registerSecretsFrom(keys: Record<string, string | null | undefined> | undefined): void;
|
|
21
|
+
/** Register dedicated credentials in untrusted parsed config before schema validation. */
|
|
22
|
+
export declare function registerProfileSecrets(value: unknown): void;
|
|
21
23
|
/**
|
|
22
24
|
* Every known secret, LONGEST FIRST.
|
|
23
25
|
*
|
|
@@ -39,6 +39,24 @@ export function registerSecretsFrom(keys) {
|
|
|
39
39
|
for (const value of Object.values(keys))
|
|
40
40
|
registerSecret(value);
|
|
41
41
|
}
|
|
42
|
+
/** Register dedicated credentials in untrusted parsed config before schema validation. */
|
|
43
|
+
export function registerProfileSecrets(value) {
|
|
44
|
+
if (!value || typeof value !== 'object')
|
|
45
|
+
return;
|
|
46
|
+
const profiles = value.modelProfiles;
|
|
47
|
+
if (!profiles || typeof profiles !== 'object')
|
|
48
|
+
return;
|
|
49
|
+
const entries = profiles.entries;
|
|
50
|
+
if (!Array.isArray(entries))
|
|
51
|
+
return;
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
if (!entry || typeof entry !== 'object')
|
|
54
|
+
continue;
|
|
55
|
+
const key = entry.apiKey;
|
|
56
|
+
if (typeof key === 'string')
|
|
57
|
+
registerSecret(key);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
42
60
|
/**
|
|
43
61
|
* Every known secret, LONGEST FIRST.
|
|
44
62
|
*
|
package/dist/team/runtime.d.ts
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* queue class, no event-loop trickery — every path is observable from the event
|
|
18
18
|
* stream.
|
|
19
19
|
*/
|
|
20
|
+
import type { ModelRole } from '../config/model-profiles.js';
|
|
20
21
|
import type { ProviderRegistry, SkillRegistry, ToolPolicyDecision, ToolPolicyVerdict } from '@aragon-agent/core';
|
|
21
22
|
import type { AgentMode } from '../agent/agent-mode.js';
|
|
22
23
|
import type { CliConfig } from '../config/schema.js';
|
|
@@ -30,7 +31,7 @@ export interface TeamRuntimeDeps {
|
|
|
30
31
|
providerRegistry: ProviderRegistry;
|
|
31
32
|
getCwd: () => string;
|
|
32
33
|
getMode: () => AgentMode;
|
|
33
|
-
getApiKey: (providerId: string) => string | undefined;
|
|
34
|
+
getApiKey: (providerId: string, role?: ModelRole) => string | undefined;
|
|
34
35
|
skillRegistry?: SkillRegistry;
|
|
35
36
|
alwaysBlock?: () => string;
|
|
36
37
|
toolPolicy?: () => ToolPolicyDecision;
|
package/dist/team/subagent.d.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* them (§3.11 / R-6). What a child does NOT get is spelled out below, and each
|
|
11
11
|
* omission has a reason that is a correctness boundary rather than caution.
|
|
12
12
|
*/
|
|
13
|
+
import type { ModelRole } from '../config/model-profiles.js';
|
|
13
14
|
import { type AgentConfig, type AgentEvent, type AgentTool, type Message, type ModelRef, type ProviderRegistry, type SkillRegistry, type ThinkingLevel, type TokenUsage, type ToolPolicyDecision, type ToolPolicyVerdict } from '@aragon-agent/core';
|
|
14
15
|
import type { AgentMode } from '../agent/agent-mode.js';
|
|
15
16
|
import type { ChildContextManagerProvider } from '../compaction/child.js';
|
|
@@ -60,7 +61,7 @@ export interface SubagentDeps {
|
|
|
60
61
|
getCwd: () => string;
|
|
61
62
|
/** The lead's live session mode. Read at CALL time, never cached. */
|
|
62
63
|
getMode: () => AgentMode;
|
|
63
|
-
getApiKey: (providerId: string) => string | undefined;
|
|
64
|
+
getApiKey: (providerId: string, role?: ModelRole) => string | undefined;
|
|
64
65
|
/**
|
|
65
66
|
* The lead's `SkillRegistry`, used for `skill_find` ONLY.
|
|
66
67
|
*
|
|
@@ -109,6 +110,7 @@ export interface SubagentDeps {
|
|
|
109
110
|
resolveTier?: (tier: FastTierName) => {
|
|
110
111
|
ref: ModelRef;
|
|
111
112
|
thinkingLevel: ThinkingLevel;
|
|
113
|
+
role?: ModelRole;
|
|
112
114
|
};
|
|
113
115
|
/**
|
|
114
116
|
* Build this child its own context manager
|
package/dist/team/subagent.js
CHANGED
|
@@ -181,6 +181,7 @@ export function createSubagent(spec, deps, hooks) {
|
|
|
181
181
|
...(deps.config.baseUrl ? { baseUrl: deps.config.baseUrl } : {}),
|
|
182
182
|
},
|
|
183
183
|
thinkingLevel: deps.config.thinkingLevel,
|
|
184
|
+
role: 'main',
|
|
184
185
|
};
|
|
185
186
|
const model = resolved.ref;
|
|
186
187
|
// HOISTED TO A LOCAL, AND THAT IS WHAT MAKES W3 POSSIBLE AT ALL. This was built
|
|
@@ -209,6 +210,7 @@ export function createSubagent(spec, deps, hooks) {
|
|
|
209
210
|
const contextManager = deps.contextManagerFor?.({
|
|
210
211
|
label: spec.label,
|
|
211
212
|
model,
|
|
213
|
+
role: resolved.role ?? 'main',
|
|
212
214
|
getMessages: () => agentRef?.state.messages ?? [],
|
|
213
215
|
getSystemPrompt: () => systemPrompt,
|
|
214
216
|
onCompacted: () => {
|
|
@@ -224,7 +226,7 @@ export function createSubagent(spec, deps, hooks) {
|
|
|
224
226
|
// constructing five of them per dispatch is pure waste.
|
|
225
227
|
providerRegistry: deps.providerRegistry,
|
|
226
228
|
// The lead's closure, so a settings-screen key edit reaches children too.
|
|
227
|
-
getApiKey: deps.getApiKey,
|
|
229
|
+
getApiKey: (id) => deps.getApiKey(id, resolved.role ?? 'main'),
|
|
228
230
|
...(deps.config.maxTokens !== undefined ? { maxTokens: deps.config.maxTokens } : {}),
|
|
229
231
|
timeouts: {
|
|
230
232
|
toolTimeout: deps.config.toolTimeoutMs,
|
|
@@ -1,85 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Exactly one row, immediately above the composer, while a run is in flight:
|
|
5
|
-
*
|
|
6
|
-
* * Percolating...
|
|
7
|
-
*
|
|
8
|
-
* THE ROW CARRIES THE PHRASE AND NOTHING ELSE, AND THAT IS THE WHOLE OF ITS
|
|
9
|
-
* DESIGN (D-5 / P1-1). No elapsed clock, no token count, no `esc abort`, at any
|
|
10
|
-
* width. Every one of those is already on screen while running: the status bar
|
|
11
|
-
* renders `formatDuration(elapsedMs)` under exactly the `running` condition that
|
|
12
|
-
* mounts this row and the token cluster at `cols >= 72`, and both composers carry
|
|
13
|
-
* the abort hint. Duplicated rows are precisely what the v0.4.0 removal of the
|
|
14
|
-
* status bar's hint cluster was for, and that rule does not distinguish between a
|
|
15
|
-
* duplicated string and a duplicated number.
|
|
16
|
-
*
|
|
17
|
-
* Because there are no clusters there is NO WIDTH LADDER: one row, one
|
|
18
|
-
* truncating `<Text>`, identical at 200 columns and at 40. `cols` is therefore
|
|
19
|
-
* not a prop — nothing on the row depends on width, and a prop that changed on
|
|
20
|
-
* every resize but was never read would be a false dependency on a memo boundary.
|
|
21
|
-
*
|
|
22
|
-
* What is left is the one thing the status bar cannot say: THAT THE SILENCE IS
|
|
23
|
-
* WORK. The bar shows state; this row shows life.
|
|
24
|
-
*
|
|
25
|
-
* THIS ROW OWNS THE ONLY ANIMATED SPINNER WHILE IT IS MOUNTED
|
|
26
|
-
* (single-spinner-while-running D-1). Seven other sites can animate — the
|
|
27
|
-
* streaming assistant marker, the tool badge, the team/fast/retry cards, and the
|
|
28
|
-
* two panels' rows — and each was independently right to. Emergently they put up
|
|
29
|
-
* to five braille animations on adjacent rows, each on its own 80 ms timer: one
|
|
30
|
-
* piece of information rendered five times and out of phase, which is the same
|
|
31
|
-
* duplication the paragraph above legislates against for text. So `App` widens
|
|
32
|
-
* the `reducedMotion` it hands those seven to `cfg.reducedMotion || (running &&
|
|
33
|
-
* !overlay)`, and they all fall back to the static glyphs they already had.
|
|
34
|
-
*
|
|
35
|
-
* THIS COMPONENT KEEPS THE RAW CONFIG FLAG, and that asymmetry is deliberate
|
|
36
|
-
* (D-5). It reads the flag TWICE: once for the spinner below, and once for
|
|
37
|
-
* `pickActivityPhrase`'s rotation. Handing it the widened value would freeze the
|
|
38
|
-
* phrase at the first word of every run — a second, unrelated regression, and
|
|
39
|
-
* one nobody would connect to a change about icons.
|
|
1
|
+
/** Legacy activity presentation. Explicit facts share the global status label mapping.
|
|
2
|
+
* StatusBar owns the application's sole live spinner via the factory below.
|
|
40
3
|
*/
|
|
41
4
|
import React from 'react';
|
|
42
5
|
import type { Theme } from './theme.js';
|
|
43
6
|
import type { TermCapabilities } from './capabilities.js';
|
|
44
7
|
import { pickGlyphs } from './glyphs.js';
|
|
45
8
|
import type { RunActivity } from './run-status-row.js';
|
|
46
|
-
/**
|
|
47
|
-
* The animated spinner this row draws while it is live, or `null` when it would
|
|
48
|
-
* be STATIC — an ASCII terminal, or a user who asked for stillness.
|
|
49
|
-
*
|
|
50
|
-
* A FACTORY, NOT A COMPONENT, and the distinction is load-bearing. A
|
|
51
|
-
* `<LiveSpinner/>` element whose own render returned `null` would still be
|
|
52
|
-
* truthy at the call site — the exact trap `BottomStatusRow`'s `update` prop
|
|
53
|
-
* documents at length. Callers test the RETURN VALUE and get a real answer.
|
|
54
|
-
*
|
|
55
|
-
* It is exported so `BottomStatusRow` can put the bare glyph beside a toast
|
|
56
|
-
* without importing `ink-spinner` itself: `spinner-census.test.ts` enumerates
|
|
57
|
-
* every file under `src/ui/**` that imports it, and that list is the checklist
|
|
58
|
-
* for "who is allowed to animate". One more importer is one more site a future
|
|
59
|
-
* reader has to reason about; one more caller of this function is not.
|
|
60
|
-
*/
|
|
9
|
+
/** Shared animation factory; returns null for ASCII or reduced-motion terminals. */
|
|
61
10
|
export declare function liveSpinner(reducedMotion: boolean, caps: TermCapabilities): React.ReactElement | null;
|
|
62
|
-
/**
|
|
63
|
-
* The label ladder, MOST SPECIFIC FIRST: `Compacting context` outranks a tool name
|
|
64
|
-
* because compaction can be the only thing happening, and the tool name outranks
|
|
65
|
-
* the rotating phrase for the reason `runningTool` exists at all. One
|
|
66
|
-
* implementation, because the fixed bottom row and the run status row above the
|
|
67
|
-
* input must never disagree about what the agent is doing.
|
|
68
|
-
*
|
|
69
|
-
* `Running ${name}` rather than a per-tool verb table: a table would be a SECOND
|
|
70
|
-
* registry of tool names, and `toolGlyph` is already the one place that knows
|
|
71
|
-
* them. ASCII only, and the ellipsis comes from `pickGlyphs` like every other one.
|
|
72
|
-
*/
|
|
11
|
+
/** Explicit execution facts outrank compatibility tool names and rotating phrases. */
|
|
73
12
|
export declare function resolveActivityLabel(activity: RunActivity, glyphs: ReturnType<typeof pickGlyphs>): string;
|
|
74
13
|
export interface ActivityLabelProps extends RunActivity {
|
|
75
14
|
/**
|
|
76
|
-
* False
|
|
77
|
-
* uses it when it has scrolled out of the viewport (the fixed bottom row owns
|
|
78
|
-
* the animation then) or an overlay covers the chat. The phrase still rotates
|
|
79
|
-
* from the RAW `reducedMotion`, so a still icon never freezes the wording.
|
|
15
|
+
* False forces a static glyph. Compatibility phrases still follow reducedMotion.
|
|
80
16
|
*/
|
|
81
17
|
spinnerLive?: boolean;
|
|
82
|
-
/** Prefix one space
|
|
18
|
+
/** Prefix one space for compatibility line consumers. */
|
|
83
19
|
leadingSpace?: boolean;
|
|
84
20
|
theme: Theme;
|
|
85
21
|
caps: TermCapabilities;
|
package/dist/ui/ActivityLine.js
CHANGED
|
@@ -3,36 +3,19 @@ import { Box, Text } from 'ink';
|
|
|
3
3
|
import Spinner from 'ink-spinner';
|
|
4
4
|
import { pickGlyphs } from './glyphs.js';
|
|
5
5
|
import { pickActivityPhrase } from './activity-phrases.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* be STATIC — an ASCII terminal, or a user who asked for stillness.
|
|
9
|
-
*
|
|
10
|
-
* A FACTORY, NOT A COMPONENT, and the distinction is load-bearing. A
|
|
11
|
-
* `<LiveSpinner/>` element whose own render returned `null` would still be
|
|
12
|
-
* truthy at the call site — the exact trap `BottomStatusRow`'s `update` prop
|
|
13
|
-
* documents at length. Callers test the RETURN VALUE and get a real answer.
|
|
14
|
-
*
|
|
15
|
-
* It is exported so `BottomStatusRow` can put the bare glyph beside a toast
|
|
16
|
-
* without importing `ink-spinner` itself: `spinner-census.test.ts` enumerates
|
|
17
|
-
* every file under `src/ui/**` that imports it, and that list is the checklist
|
|
18
|
-
* for "who is allowed to animate". One more importer is one more site a future
|
|
19
|
-
* reader has to reason about; one more caller of this function is not.
|
|
20
|
-
*/
|
|
6
|
+
import { phaseLabels } from './layout/status-layout.js';
|
|
7
|
+
/** Shared animation factory; returns null for ASCII or reduced-motion terminals. */
|
|
21
8
|
export function liveSpinner(reducedMotion, caps) {
|
|
22
9
|
return caps.unicode && !reducedMotion ? _jsx(Spinner, { type: "dots" }) : null;
|
|
23
10
|
}
|
|
24
|
-
/**
|
|
25
|
-
* The label ladder, MOST SPECIFIC FIRST: `Compacting context` outranks a tool name
|
|
26
|
-
* because compaction can be the only thing happening, and the tool name outranks
|
|
27
|
-
* the rotating phrase for the reason `runningTool` exists at all. One
|
|
28
|
-
* implementation, because the fixed bottom row and the run status row above the
|
|
29
|
-
* input must never disagree about what the agent is doing.
|
|
30
|
-
*
|
|
31
|
-
* `Running ${name}` rather than a per-tool verb table: a table would be a SECOND
|
|
32
|
-
* registry of tool names, and `toolGlyph` is already the one place that knows
|
|
33
|
-
* them. ASCII only, and the ellipsis comes from `pickGlyphs` like every other one.
|
|
34
|
-
*/
|
|
11
|
+
/** Explicit execution facts outrank compatibility tool names and rotating phrases. */
|
|
35
12
|
export function resolveActivityLabel(activity, glyphs) {
|
|
13
|
+
if (activity.phase !== undefined || activity.activeTool !== undefined || activity.outcome !== undefined) {
|
|
14
|
+
return phaseLabels({
|
|
15
|
+
phase: activity.phase ?? (activity.activeTool ? 'tool' : 'idle'),
|
|
16
|
+
activeTool: activity.activeTool, runOutcome: activity.outcome, compacting: activity.compacting,
|
|
17
|
+
})[1];
|
|
18
|
+
}
|
|
36
19
|
if (activity.compacting)
|
|
37
20
|
return `Compacting context${glyphs.ellipsis}`;
|
|
38
21
|
if (activity.runningTool)
|
|
@@ -47,14 +30,9 @@ export function resolveActivityLabel(activity, glyphs) {
|
|
|
47
30
|
export function ActivityLabel({ spinnerLive = true, leadingSpace = false, theme, caps, ...activity }) {
|
|
48
31
|
const glyphs = pickGlyphs(caps);
|
|
49
32
|
const label = resolveActivityLabel(activity, glyphs);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
//
|
|
54
|
-
// Through `liveSpinner` rather than inline, so this row and the glyph
|
|
55
|
-
// `BottomStatusRow` composes beside a toast can never disagree about WHEN the
|
|
56
|
-
// spinner is live - the same reason `App` names its mount condition once.
|
|
57
|
-
const spinner = (spinnerLive ? liveSpinner(activity.reducedMotion, caps) : null) ??
|
|
33
|
+
const settled = activity.phase === 'idle' || (activity.phase === undefined
|
|
34
|
+
&& activity.outcome !== undefined && activity.outcome !== 'none' && !activity.activeTool);
|
|
35
|
+
const spinner = (spinnerLive && (!settled || activity.compacting) ? liveSpinner(activity.reducedMotion, caps) : null) ??
|
|
58
36
|
glyphs.spinnerStill;
|
|
59
37
|
return (_jsxs(Text, { wrap: "truncate", color: theme.thinking, children: [leadingSpace ? ' ' : '', spinner, " ", label] }));
|
|
60
38
|
}
|
package/dist/ui/App.d.ts
CHANGED
|
@@ -88,6 +88,7 @@ export interface TerminalBridge {
|
|
|
88
88
|
scrollbar?: ScrollbarBridge;
|
|
89
89
|
/** Whether drag-select is on for this session (`mouseSelect` + a filter). */
|
|
90
90
|
mouseSelect: boolean;
|
|
91
|
+
deleteDisambiguated?: boolean;
|
|
91
92
|
/** Release the mouse to the terminal, or take it back (`/mouse`, G3). */
|
|
92
93
|
setMouseCapture?: (on: boolean) => void;
|
|
93
94
|
/** Whether the mouse is captured right now — read at command time. */
|