@aragon-agent/cli 0.5.8 → 0.5.9
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 +279 -0
- package/README.md +1429 -1163
- package/dist/agent/coalesce.d.ts +13 -0
- package/dist/agent/coalesce.js +50 -11
- package/dist/agent/controller.d.ts +141 -2
- package/dist/agent/controller.js +396 -4
- package/dist/agent/headless.d.ts +8 -0
- package/dist/agent/headless.js +40 -0
- package/dist/agent/reducer.d.ts +245 -3
- package/dist/agent/reducer.js +490 -17
- package/dist/agent/retry-view.d.ts +68 -0
- package/dist/agent/retry-view.js +95 -0
- package/dist/agent/system-prompt.d.ts +11 -0
- package/dist/agent/system-prompt.js +2 -0
- package/dist/cli.js +86 -2
- package/dist/commands/builtins.d.ts +1 -1
- package/dist/commands/builtins.js +308 -2
- package/dist/config/cli-commands.d.ts +53 -2
- package/dist/config/cli-commands.js +136 -3
- package/dist/config/env.d.ts +6 -3
- package/dist/config/env.js +103 -3
- package/dist/config/load.d.ts +49 -0
- package/dist/config/load.js +83 -1
- package/dist/config/schema.d.ts +212 -2
- package/dist/config/schema.js +207 -1
- package/dist/config/store.js +20 -1
- package/dist/fast/critique.d.ts +43 -0
- package/dist/fast/critique.js +62 -0
- package/dist/fast/digest.d.ts +42 -0
- package/dist/fast/digest.js +85 -0
- package/dist/fast/frames.d.ts +99 -0
- package/dist/fast/frames.js +180 -0
- package/dist/fast/limits.d.ts +98 -0
- package/dist/fast/limits.js +98 -0
- package/dist/fast/prompt.d.ts +72 -0
- package/dist/fast/prompt.js +94 -0
- package/dist/fast/resolve.d.ts +43 -0
- package/dist/fast/resolve.js +105 -0
- package/dist/fast/review-call.d.ts +99 -0
- package/dist/fast/review-call.js +130 -0
- package/dist/fast/reviewer.d.ts +248 -0
- package/dist/fast/reviewer.js +664 -0
- package/dist/fast/types.d.ts +128 -0
- package/dist/fast/types.js +14 -0
- package/dist/fast/wiring.d.ts +170 -0
- package/dist/fast/wiring.js +316 -0
- package/dist/logging/install.d.ts +15 -1
- package/dist/logging/install.js +37 -4
- package/dist/logging/logger.d.ts +1 -1
- package/dist/session/persist.js +57 -1
- package/dist/team/normalize.d.ts +26 -1
- package/dist/team/normalize.js +23 -3
- package/dist/team/prompt.d.ts +11 -0
- package/dist/team/prompt.js +10 -0
- package/dist/team/report.d.ts +18 -0
- package/dist/team/report.js +27 -1
- package/dist/team/runtime.d.ts +13 -2
- package/dist/team/runtime.js +33 -6
- package/dist/team/subagent.d.ts +19 -1
- package/dist/team/subagent.js +72 -10
- package/dist/team/task-tool.d.ts +26 -0
- package/dist/team/task-tool.js +48 -4
- package/dist/team/types.d.ts +80 -1
- package/dist/tools/bash-tool.js +19 -3
- package/dist/tools/diff.d.ts +25 -5
- package/dist/tools/diff.js +72 -41
- package/dist/tools/file-change-store.d.ts +34 -0
- package/dist/tools/file-change-store.js +57 -0
- package/dist/tools/fs-tools.d.ts +26 -0
- package/dist/tools/fs-tools.js +62 -5
- package/dist/tools/index.d.ts +31 -0
- package/dist/tools/index.js +7 -1
- package/dist/tools/patch.d.ts +115 -0
- package/dist/tools/patch.js +453 -0
- package/dist/tools/terminal-output.d.ts +107 -0
- package/dist/tools/terminal-output.js +198 -0
- package/dist/tools/tool-output-store.d.ts +68 -0
- package/dist/tools/tool-output-store.js +102 -0
- package/dist/ui/ActivityLine.d.ts +48 -0
- package/dist/ui/ActivityLine.js +22 -0
- package/dist/ui/App.d.ts +1 -4
- package/dist/ui/App.js +273 -37
- package/dist/ui/BottomStatusRow.d.ts +43 -0
- package/dist/ui/BottomStatusRow.js +14 -0
- package/dist/ui/Composer.d.ts +1 -6
- package/dist/ui/Composer.js +2 -2
- package/dist/ui/PromptInput.d.ts +1 -15
- package/dist/ui/PromptInput.js +1 -38
- package/dist/ui/StatusBar.d.ts +37 -0
- package/dist/ui/StatusBar.js +5 -3
- package/dist/ui/TeamPanel.d.ts +5 -4
- package/dist/ui/TeamPanel.js +1 -1
- package/dist/ui/TodoPanel.d.ts +5 -4
- package/dist/ui/Transcript.d.ts +26 -3
- package/dist/ui/Transcript.js +76 -10
- package/dist/ui/activity-phrases.d.ts +33 -0
- package/dist/ui/activity-phrases.js +50 -0
- package/dist/ui/entries/AssistantEntry.d.ts +20 -0
- package/dist/ui/entries/AssistantEntry.js +3 -2
- package/dist/ui/entries/DiffView.d.ts +67 -0
- package/dist/ui/entries/DiffView.js +103 -0
- package/dist/ui/entries/FastCard.d.ts +53 -0
- package/dist/ui/entries/FastCard.js +87 -0
- package/dist/ui/entries/RetryCard.d.ts +56 -0
- package/dist/ui/entries/RetryCard.js +60 -0
- package/dist/ui/entries/TeamCard.js +6 -1
- package/dist/ui/entries/ToolCard.d.ts +38 -1
- package/dist/ui/entries/ToolCard.js +68 -5
- package/dist/ui/glyphs.d.ts +9 -0
- package/dist/ui/glyphs.js +2 -0
- package/dist/ui/layout/AppShell.d.ts +13 -22
- package/dist/ui/layout/AppShell.js +3 -38
- package/dist/ui/layout/virtual-window.d.ts +1 -1
- package/dist/ui/layout/virtual-window.js +109 -5
- package/dist/ui/overlays/HelpOverlay.js +16 -2
- package/dist/ui/overlays/SettingsScreen.d.ts +82 -1
- package/dist/ui/overlays/SettingsScreen.js +147 -1
- package/dist/ui/transcript-text.js +27 -0
- package/dist/ui/use-wheel-routing.d.ts +16 -32
- package/dist/ui/use-wheel-routing.js +21 -38
- package/package.json +2 -2
- package/dist/ui/layout/regions.d.ts +0 -55
- package/dist/ui/layout/regions.js +0 -52
package/dist/config/env.js
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
* - Provider secrets: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY /
|
|
6
6
|
* GEMINI_API_KEY.
|
|
7
7
|
* - Overrides: ARAGON_PROVIDER, ARAGON_MODEL, ARAGON_BASE_URL, ARAGON_THINKING,
|
|
8
|
+
* ARAGON_SHOW_THINKING,
|
|
8
9
|
* ARAGON_MAX_TOKENS (a number, or `auto` / `0` for the per-model ceiling),
|
|
9
10
|
* ARAGON_THEME, ARAGON_MOUSE, ARAGON_PLAN, ARAGON_TEAM,
|
|
10
|
-
* ARAGON_TEAM_MAX,
|
|
11
|
-
*
|
|
12
|
-
*
|
|
11
|
+
* ARAGON_TEAM_MAX, ARAGON_RETRY, ARAGON_RETRY_MAX, ARAGON_FAST,
|
|
12
|
+
* ARAGON_FAST_PROVIDER, ARAGON_FAST_MODEL, ARAGON_FAST_BASE_URL,
|
|
13
|
+
* ARAGON_LOG_LEVEL,
|
|
14
|
+
* ARAGON_LOG_FILE, ARAGON_LOG_DIR, ARAGON_TRANSCRIPT_RETAIN,
|
|
15
|
+
* ARAGON_RENDER_GOVERNOR, ARAGON_MAX_RENDER_INTERVAL_MS.
|
|
13
16
|
*
|
|
14
17
|
* NOT here: `ARAGON_HOME`. It is read when `config/app-paths.ts` is first
|
|
15
18
|
* evaluated, which is long before `loadDotenv()` runs, so a `.env` can never
|
|
@@ -61,6 +64,27 @@ export function readEnvConfig() {
|
|
|
61
64
|
if (process.env.ARAGON_THINKING) {
|
|
62
65
|
partial.thinkingLevel = clampThinkingLevel(process.env.ARAGON_THINKING.trim(), 'off');
|
|
63
66
|
}
|
|
67
|
+
// Parsed by the POSITIVE list, like ARAGON_FULLSCREEN: anything else is left
|
|
68
|
+
// ABSENT so the config file underneath still wins.
|
|
69
|
+
const showThinking = process.env.ARAGON_SHOW_THINKING?.trim().toLowerCase();
|
|
70
|
+
if (showThinking !== undefined && showThinking.length > 0) {
|
|
71
|
+
partial.showThinking =
|
|
72
|
+
showThinking === '1' ||
|
|
73
|
+
showThinking === 'true' ||
|
|
74
|
+
showThinking === 'on' ||
|
|
75
|
+
showThinking === 'yes';
|
|
76
|
+
}
|
|
77
|
+
// The same positive-list parse as its neighbour, and the same "a non-empty
|
|
78
|
+
// value is an ANSWER" rule -- which is what lets `ARAGON_LIVE_TOOL_OUTPUT=0`
|
|
79
|
+
// turn a default-ON feature off (agent-activity-presentation-live §4.1).
|
|
80
|
+
const liveToolOutput = process.env.ARAGON_LIVE_TOOL_OUTPUT?.trim().toLowerCase();
|
|
81
|
+
if (liveToolOutput !== undefined && liveToolOutput.length > 0) {
|
|
82
|
+
partial.liveToolOutput =
|
|
83
|
+
liveToolOutput === '1' ||
|
|
84
|
+
liveToolOutput === 'true' ||
|
|
85
|
+
liveToolOutput === 'on' ||
|
|
86
|
+
liveToolOutput === 'yes';
|
|
87
|
+
}
|
|
64
88
|
// `auto` / `0` mean AUTO (`null`); a number is clamped to the accepted range.
|
|
65
89
|
// Anything else is LEFT ABSENT rather than written as `null`: a typo here used
|
|
66
90
|
// to become AUTO and silently discard the number in the config file under it,
|
|
@@ -179,6 +203,82 @@ export function readEnvConfig() {
|
|
|
179
203
|
if (Object.keys(section).length > 0)
|
|
180
204
|
partial.todo = section;
|
|
181
205
|
}
|
|
206
|
+
// ARAGON_RETRY=0 is the kill switch for API retry; ARAGON_RETRY_MAX=<n>
|
|
207
|
+
// overrides the count. Parsed by the POSITIVE list, exactly as
|
|
208
|
+
// ARAGON_FULLSCREEN / ARAGON_MOUSE / ARAGON_PLAN / ARAGON_TEAM / ARAGON_TODO
|
|
209
|
+
// are — NOT by `envBool` below, which uses a negative list.
|
|
210
|
+
//
|
|
211
|
+
// TWO VARS ONLY, and no third for the delays: every env var in this file exists
|
|
212
|
+
// because a flag and a config file are BOTH unreachable in the channel it
|
|
213
|
+
// serves, and nobody tunes a backoff multiplier from a container entrypoint.
|
|
214
|
+
//
|
|
215
|
+
// `>= 0`, NOT `> 0`, and the difference is the whole point (R-16).
|
|
216
|
+
// `ARAGON_TEAM_MAX` above guards `parsed > 0`, which is right for a fan-out
|
|
217
|
+
// width and wrong here: `0` is this key's documented floor AND its kill switch,
|
|
218
|
+
// so a `> 0` guard would drop `ARAGON_RETRY_MAX=0` on the floor and leave the
|
|
219
|
+
// user with the default 10. "Left ABSENT when unparseable" still holds and
|
|
220
|
+
// still matters — an unparseable value must not look permanently supplied, or
|
|
221
|
+
// the config file can never win again.
|
|
222
|
+
const retry = process.env.ARAGON_RETRY?.trim().toLowerCase();
|
|
223
|
+
const retryMax = process.env.ARAGON_RETRY_MAX?.trim();
|
|
224
|
+
if ((retry !== undefined && retry.length > 0) || (retryMax !== undefined && retryMax.length > 0)) {
|
|
225
|
+
const section = {};
|
|
226
|
+
if (retry !== undefined && retry.length > 0) {
|
|
227
|
+
section.enabled = retry === '1' || retry === 'true' || retry === 'on' || retry === 'yes';
|
|
228
|
+
}
|
|
229
|
+
if (retryMax !== undefined && retryMax.length > 0) {
|
|
230
|
+
const parsed = Number.parseInt(retryMax, 10);
|
|
231
|
+
if (Number.isFinite(parsed) && parsed >= 0)
|
|
232
|
+
section.maxRetries = parsed;
|
|
233
|
+
}
|
|
234
|
+
// A PARTIAL section, safe only because every consumer deep-merges it — the
|
|
235
|
+
// same contract `partial.skills` / `partial.log` / `partial.team` rely on.
|
|
236
|
+
if (Object.keys(section).length > 0)
|
|
237
|
+
partial.retry = section;
|
|
238
|
+
}
|
|
239
|
+
// ARAGON_FAST=1 turns the fast model tier on; the other three name it
|
|
240
|
+
// (fast-model-tier §4.3). Parsed by the POSITIVE list, exactly as
|
|
241
|
+
// ARAGON_FULLSCREEN / ARAGON_MOUSE / ARAGON_PLAN / ARAGON_TEAM / ARAGON_TODO /
|
|
242
|
+
// ARAGON_RETRY are — NOT by `envBool` below, whose NEGATIVE list disagrees with
|
|
243
|
+
// it on values like `ARAGON_FAST=disable`.
|
|
244
|
+
//
|
|
245
|
+
// FOUR VARS, AND DELIBERATELY NO `ARAGON_FAST_REVIEW_EVERY` / `_MAX_CHARS` /
|
|
246
|
+
// `_DELEGATE` (D-14). The rule this file states is that an environment variable
|
|
247
|
+
// exists only where a flag AND a config file are BOTH unreachable — a
|
|
248
|
+
// container, an ssh session, being spawned by another tool. "Which model, and
|
|
249
|
+
// is it on" passes that test; tuning a review cadence does not, and every key
|
|
250
|
+
// that fails it is documentation debt plus a fifth place for the value to
|
|
251
|
+
// disagree with itself.
|
|
252
|
+
//
|
|
253
|
+
// ONE ACCUMULATED SECTION, ASSIGNED ONCE — the shape the `team`, `todo` and
|
|
254
|
+
// `retry` branches above all use, and NOT four `if` blocks each assigning
|
|
255
|
+
// `partial.fast`. THE CAST IS WHAT WOULD MAKE THAT MISTAKE SILENT: a second
|
|
256
|
+
// assignment compiles clean and drops `enabled`, so
|
|
257
|
+
// `ARAGON_FAST=1 ARAGON_FAST_MODEL=x` would quietly resolve with the tier off
|
|
258
|
+
// (the P1-4 defect this file records for `todo`).
|
|
259
|
+
const fast = process.env.ARAGON_FAST?.trim().toLowerCase();
|
|
260
|
+
const fastProvider = process.env.ARAGON_FAST_PROVIDER?.trim();
|
|
261
|
+
const fastModel = process.env.ARAGON_FAST_MODEL?.trim();
|
|
262
|
+
const fastBaseUrl = process.env.ARAGON_FAST_BASE_URL?.trim();
|
|
263
|
+
if ((fast !== undefined && fast.length > 0) ||
|
|
264
|
+
(fastProvider !== undefined && fastProvider.length > 0) ||
|
|
265
|
+
(fastModel !== undefined && fastModel.length > 0) ||
|
|
266
|
+
(fastBaseUrl !== undefined && fastBaseUrl.length > 0)) {
|
|
267
|
+
const section = {};
|
|
268
|
+
if (fast !== undefined && fast.length > 0) {
|
|
269
|
+
section.enabled = fast === '1' || fast === 'true' || fast === 'on' || fast === 'yes';
|
|
270
|
+
}
|
|
271
|
+
if (fastProvider !== undefined && fastProvider.length > 0)
|
|
272
|
+
section.provider = fastProvider;
|
|
273
|
+
if (fastModel !== undefined && fastModel.length > 0)
|
|
274
|
+
section.model = fastModel;
|
|
275
|
+
if (fastBaseUrl !== undefined && fastBaseUrl.length > 0)
|
|
276
|
+
section.baseUrl = fastBaseUrl;
|
|
277
|
+
// A PARTIAL section, safe only because every consumer deep-merges it — the
|
|
278
|
+
// same contract the four sections above rely on.
|
|
279
|
+
if (Object.keys(section).length > 0)
|
|
280
|
+
partial.fast = section;
|
|
281
|
+
}
|
|
182
282
|
// Render bounds (tui-render-performance §5.3). Same channel story as
|
|
183
283
|
// ARAGON_FULLSCREEN: a container or a wrapper that owns argv can reach neither
|
|
184
284
|
// a flag nor a config file, and a session that freezes is exactly the case
|
package/dist/config/load.d.ts
CHANGED
|
@@ -27,6 +27,13 @@ export interface CliFlags {
|
|
|
27
27
|
compact?: boolean;
|
|
28
28
|
/** `--hints` ⇒ true, `--no-hints` ⇒ false, absent ⇒ undefined. */
|
|
29
29
|
hints?: boolean;
|
|
30
|
+
/** `--show-thinking` ⇒ true, `--no-show-thinking` ⇒ false, absent ⇒ undefined. */
|
|
31
|
+
showThinking?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* `--live-tool-output` ⇒ true, `--no-live-tool-output` ⇒ false, absent ⇒ undefined
|
|
34
|
+
* (agent-activity-presentation-live §4.1).
|
|
35
|
+
*/
|
|
36
|
+
liveToolOutput?: boolean;
|
|
30
37
|
/** `--mouse` ⇒ true, `--no-mouse` ⇒ false, absent ⇒ undefined. */
|
|
31
38
|
mouse?: boolean;
|
|
32
39
|
/** `--no-skills` ⇒ false. Turns the whole skill subsystem off (§7.5). */
|
|
@@ -99,6 +106,48 @@ export interface CliFlags {
|
|
|
99
106
|
renderGovernor?: boolean;
|
|
100
107
|
/** `--max-render-interval <ms>` — the governor ceiling for this run (L4). */
|
|
101
108
|
maxRenderInterval?: string | number;
|
|
109
|
+
/**
|
|
110
|
+
* `--retry` ⇒ true, `--no-retry` ⇒ false, absent ⇒ undefined
|
|
111
|
+
* (llm-api-retry-backoff §6.2).
|
|
112
|
+
*
|
|
113
|
+
* DECLARED AS A PAIR, for the reason `--todo-panel` and `--render-governor`
|
|
114
|
+
* each record: `retry.enabled` is PERSISTED, so a lone `--no-retry` would make
|
|
115
|
+
* commander default `opts.retry` to `true` and silently overwrite a stored
|
|
116
|
+
* `enabled: false` on every run that passed no flag at all.
|
|
117
|
+
*/
|
|
118
|
+
retry?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* `--retry-max <n>` — override `retry.maxRetries` for this run (still clamped).
|
|
121
|
+
*
|
|
122
|
+
* `0` IS A LEGITIMATE VALUE HERE and is the flag's kill switch, which is why
|
|
123
|
+
* `resolveRetryConfig` tests `!== undefined` rather than truthiness and why the
|
|
124
|
+
* clamp is `clampIntAllowingZero`.
|
|
125
|
+
*/
|
|
126
|
+
retryMax?: string | number;
|
|
127
|
+
/**
|
|
128
|
+
* `--fast` ⇒ true, `--no-fast` ⇒ false, absent ⇒ undefined
|
|
129
|
+
* (fast-model-tier §4.3).
|
|
130
|
+
*
|
|
131
|
+
* DECLARED AS A PAIR — MANDATORY (C-9), for the reason `--team`,
|
|
132
|
+
* `--todo-panel`, `--render-governor` and `--retry` each record in turn.
|
|
133
|
+
* `fast.enabled` is PERSISTED and defaults to `false`, so a lone `--fast`
|
|
134
|
+
* would be indistinguishable from silence and the DEFAULT-OFF guarantee (R-d)
|
|
135
|
+
* would depend on a commander detail.
|
|
136
|
+
*/
|
|
137
|
+
fast?: boolean;
|
|
138
|
+
/** `--fast-model <id>` — implies nothing about `enabled` on its own. */
|
|
139
|
+
fastModel?: string;
|
|
140
|
+
/** `--fast-provider <id>` — `''` (absent) inherits the main provider. */
|
|
141
|
+
fastProvider?: string;
|
|
142
|
+
/**
|
|
143
|
+
* `--fast-review <n|off>` — `off` sets `fast.review: false`, a number sets
|
|
144
|
+
* `reviewEveryTurns`.
|
|
145
|
+
*
|
|
146
|
+
* ONE FLAG FOR TWO KEYS, and deliberately: "how often" and "at all" are one
|
|
147
|
+
* decision to a user, and a separate `--no-fast-review` would be a fifth pair
|
|
148
|
+
* to keep in step with `toFlags`.
|
|
149
|
+
*/
|
|
150
|
+
fastReview?: string;
|
|
102
151
|
}
|
|
103
152
|
/**
|
|
104
153
|
* 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, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampTheme, clampThinkingLevel, clampMaxTokens, clampMaxRenderInterval, clampTranscriptRetain, clampTranscriptWindow, coercePositiveInt, isAutoToken, isSkillsToolPolicyMode, } from './schema.js';
|
|
9
|
+
import { DEFAULT_CONFIG, IDLE_TIMEOUT_MARGIN_MS, clampAskRounds, clampDensity, clampHumanTimeout, clampLogConfig, clampFastConfig, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampTheme, clampThinkingLevel, clampMaxTokens, clampMaxRenderInterval, clampTranscriptRetain, clampTranscriptWindow, coercePositiveInt, isAutoToken, isSkillsToolPolicyMode, } 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';
|
|
@@ -121,6 +121,70 @@ function resolveTodoConfig(flags, env, file) {
|
|
|
121
121
|
...(flags.todoFollow !== undefined ? { followThrough: flags.todoFollow } : {}),
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Merge the `retry` section across all four layers (defaults › file › env ›
|
|
126
|
+
* flags), llm-api-retry-backoff §6.2.
|
|
127
|
+
*
|
|
128
|
+
* `!== undefined` ON BOTH FLAGS, and that is the whole point — the rule
|
|
129
|
+
* `resolveTeamConfig` and `resolveTodoConfig` each state once. Commander
|
|
130
|
+
* materialises a lone `--no-retry` as `opts.retry = true` when the flag is
|
|
131
|
+
* ABSENT, so a truthiness check cannot tell `--no-retry` from "not passed"; and
|
|
132
|
+
* `flags.retryMax` may legitimately be `0`, which a truthiness check would drop
|
|
133
|
+
* on the floor and replace with the default 10 (R-16).
|
|
134
|
+
*/
|
|
135
|
+
function resolveRetryConfig(flags, env, file) {
|
|
136
|
+
return clampRetryConfig({
|
|
137
|
+
...DEFAULT_CONFIG.retry,
|
|
138
|
+
...(file.retry ?? {}),
|
|
139
|
+
...(env.retry ?? {}),
|
|
140
|
+
...(flags.retry !== undefined ? { enabled: flags.retry } : {}),
|
|
141
|
+
...(flags.retryMax !== undefined && flags.retryMax !== ''
|
|
142
|
+
? { maxRetries: flags.retryMax }
|
|
143
|
+
: {}),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Merge the `fast` section across all four layers (defaults › file › env ›
|
|
148
|
+
* flags), fast-model-tier §3.7.
|
|
149
|
+
*
|
|
150
|
+
* `!== undefined` ON `flags.fast`, which is the rule `resolveTeamConfig`,
|
|
151
|
+
* `resolveTodoConfig` and `resolveRetryConfig` each state once (C-9): commander
|
|
152
|
+
* materialises a lone `--no-fast` as `opts.fast = true` when the flag is absent,
|
|
153
|
+
* so a truthiness check cannot tell `--no-fast` from "not passed" — and here the
|
|
154
|
+
* damage would run the other way from usual, silently turning a default-OFF
|
|
155
|
+
* feature ON for every run that passed no flag at all.
|
|
156
|
+
*
|
|
157
|
+
* `--fast-review` maps onto TWO keys, so it is parsed rather than spread: `off`
|
|
158
|
+
* is `review: false`, a number is `reviewEveryTurns`, and anything else is
|
|
159
|
+
* ignored (the clamp discipline every other key in this file follows).
|
|
160
|
+
*/
|
|
161
|
+
function resolveFastConfig(flags, env, file) {
|
|
162
|
+
const reviewFlag = flags.fastReview?.trim().toLowerCase();
|
|
163
|
+
const reviewPatch = {};
|
|
164
|
+
if (reviewFlag !== undefined && reviewFlag.length > 0) {
|
|
165
|
+
if (reviewFlag === 'off') {
|
|
166
|
+
reviewPatch.review = false;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
const n = Number.parseInt(reviewFlag, 10);
|
|
170
|
+
if (Number.isFinite(n) && n > 0)
|
|
171
|
+
reviewPatch.reviewEveryTurns = n;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return clampFastConfig({
|
|
175
|
+
...DEFAULT_CONFIG.fast,
|
|
176
|
+
...(file.fast ?? {}),
|
|
177
|
+
...(env.fast ?? {}),
|
|
178
|
+
...(flags.fast !== undefined ? { enabled: flags.fast } : {}),
|
|
179
|
+
...(flags.fastModel !== undefined && flags.fastModel !== ''
|
|
180
|
+
? { model: flags.fastModel }
|
|
181
|
+
: {}),
|
|
182
|
+
...(flags.fastProvider !== undefined && flags.fastProvider !== ''
|
|
183
|
+
? { provider: flags.fastProvider }
|
|
184
|
+
: {}),
|
|
185
|
+
...reviewPatch,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
124
188
|
/**
|
|
125
189
|
* Resolve the adaptive render governor: flag › env › file › default `true`
|
|
126
190
|
* (tui-render-performance L4).
|
|
@@ -223,6 +287,16 @@ export function loadConfig(flags = {}) {
|
|
|
223
287
|
const model = pick(flags.model, env.partial.model, file.model) ?? DEFAULT_CONFIG.model;
|
|
224
288
|
const baseUrl = pick(flags.baseUrl, env.partial.baseUrl ?? undefined, file.baseUrl ?? undefined);
|
|
225
289
|
const thinkingLevel = clampThinkingLevel(pick(flags.thinking, env.partial.thinkingLevel, file.thinkingLevel), DEFAULT_CONFIG.thinkingLevel);
|
|
290
|
+
// BESIDE ITS SIBLING, and through the same three layers (§4.1 / P1-2). This is
|
|
291
|
+
// the ONLY place flags, environment and file are joined, so a key resolved
|
|
292
|
+
// anywhere else reaches the UI from at most one of them.
|
|
293
|
+
const showThinking = pick(flags.showThinking, env.partial.showThinking, file.showThinking) ??
|
|
294
|
+
DEFAULT_CONFIG.showThinking;
|
|
295
|
+
// THE SAME THREE LAYERS, in the same one place (§4.1). Round 1's P1-2 and the
|
|
296
|
+
// fast tier's round-2 IF both record the identical failure: a key resolved
|
|
297
|
+
// anywhere else reaches the UI from at most one of flags, environment and file.
|
|
298
|
+
const liveToolOutput = pick(flags.liveToolOutput, env.partial.liveToolOutput, file.liveToolOutput) ??
|
|
299
|
+
DEFAULT_CONFIG.liveToolOutput;
|
|
226
300
|
const maxTokens = resolveMaxTokens(flags, env.partial, file);
|
|
227
301
|
// `clampTheme` is also where the v0.3.0 `dark` name is migrated to `cool`,
|
|
228
302
|
// so reading a legacy config file needs no extra step here (§4.5 / R-4).
|
|
@@ -310,6 +384,8 @@ export function loadConfig(flags = {}) {
|
|
|
310
384
|
model,
|
|
311
385
|
baseUrl,
|
|
312
386
|
thinkingLevel,
|
|
387
|
+
showThinking,
|
|
388
|
+
liveToolOutput,
|
|
313
389
|
maxTokens,
|
|
314
390
|
theme,
|
|
315
391
|
reducedMotion,
|
|
@@ -350,6 +426,8 @@ export function loadConfig(flags = {}) {
|
|
|
350
426
|
log: resolveLogConfig(flags, env.partial, file),
|
|
351
427
|
team: resolveTeamConfig(flags, env.partial, file),
|
|
352
428
|
todo: resolveTodoConfig(flags, env.partial, file),
|
|
429
|
+
retry: resolveRetryConfig(flags, env.partial, file),
|
|
430
|
+
fast: resolveFastConfig(flags, env.partial, file),
|
|
353
431
|
cwd,
|
|
354
432
|
color,
|
|
355
433
|
colorLevel,
|
|
@@ -386,6 +464,10 @@ function recordResolvedConfig(config) {
|
|
|
386
464
|
idleTimeoutMs: config.idleTimeoutMs,
|
|
387
465
|
historyEnabled: config.historyEnabled,
|
|
388
466
|
logLevel: config.log.level,
|
|
467
|
+
// Four layers feed this one too, and none of them would otherwise leave a
|
|
468
|
+
// trace — so "why did my failing call sit there for three minutes" (or
|
|
469
|
+
// "why did it not retry at all") has an answer after the fact.
|
|
470
|
+
retry: config.retry.enabled ? config.retry.maxRetries : 'off',
|
|
389
471
|
hasApiKey: Boolean(config.apiKeys[config.provider]),
|
|
390
472
|
configPath: getConfigPath(),
|
|
391
473
|
});
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* See spec §3.5 (resolution pipeline), §6.1 (config file), and §3.8 (timeout
|
|
6
6
|
* invariant).
|
|
7
7
|
*/
|
|
8
|
-
import { type ThinkingLevel } from '@aragon-agent/core';
|
|
8
|
+
import { type RetryPolicy, type ThinkingLevel } from '@aragon-agent/core';
|
|
9
9
|
import { type LogLevelName } from '../logging/levels.js';
|
|
10
10
|
import type { FollowThroughMode } from '../todo/types.js';
|
|
11
11
|
/**
|
|
@@ -299,12 +299,171 @@ export declare const DEFAULT_TODO_CONFIG: TodoConfig;
|
|
|
299
299
|
* setting won't stick".
|
|
300
300
|
*/
|
|
301
301
|
export declare function clampTodoConfig(raw: unknown): TodoConfig;
|
|
302
|
+
export interface RetryConfig {
|
|
303
|
+
/**
|
|
304
|
+
* The user's switch. KEPT SEPARATE FROM `maxRetries: 0` on purpose: `enabled`
|
|
305
|
+
* survives round-tripping through the settings screen, while `maxRetries: 0` is
|
|
306
|
+
* what `toRetryPolicy` produces from it. Folding them would make
|
|
307
|
+
* `/retry off; /retry on` forget the user's chosen count.
|
|
308
|
+
*/
|
|
309
|
+
enabled: boolean;
|
|
310
|
+
/** Retries AFTER the initial attempt. `0` is the kill switch, not a typo. */
|
|
311
|
+
maxRetries: number;
|
|
312
|
+
initialDelayMs: number;
|
|
313
|
+
maxDelayMs: number;
|
|
314
|
+
/** Growth factor. THE ONLY FLOAT KEY in this section. */
|
|
315
|
+
multiplier: number;
|
|
316
|
+
jitter: boolean;
|
|
317
|
+
respectRetryAfter: boolean;
|
|
318
|
+
/** Wall-clock budget from the first failure of one request. */
|
|
319
|
+
maxElapsedMs: number;
|
|
320
|
+
/** Allow a restart after content has already streamed to the transcript. */
|
|
321
|
+
onPartialStream: boolean;
|
|
322
|
+
}
|
|
323
|
+
export declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
|
324
|
+
/**
|
|
325
|
+
* `hardMaxRetries` re-exported rather than re-spelled, for the reason
|
|
326
|
+
* `HARD_MAX_SUBAGENTS` records: the ceiling is enforced in TWO places — here on
|
|
327
|
+
* the config value, and again by `normalizePolicy` inside the engine — and two
|
|
328
|
+
* copies of the same 20 is exactly how a hand-edited `config.json` ends up able
|
|
329
|
+
* to raise a ceiling the mechanism fixed.
|
|
330
|
+
*/
|
|
331
|
+
export declare const HARD_MAX_RETRIES: 20;
|
|
332
|
+
/**
|
|
333
|
+
* THE single gate for every retry-config read AND write, mirroring
|
|
334
|
+
* `clampSkillsConfig` / `clampLogConfig` / `clampTeamConfig` / `clampTodoConfig`
|
|
335
|
+
* for the reason those record: hardening only the read path leaves a bad value on
|
|
336
|
+
* disk that reverts to the default on every launch, which presents to the user as
|
|
337
|
+
* "my setting won't stick".
|
|
338
|
+
*
|
|
339
|
+
* Three invariants live inside the gate:
|
|
340
|
+
*
|
|
341
|
+
* - `maxDelayMs = max(maxDelayMs, initialDelayMs)` — a ceiling under the floor
|
|
342
|
+
* makes the ladder a flat line and the countdown a lie.
|
|
343
|
+
* - `multiplier` goes through `clampNumber`, not `clampInt`: `2.5` is a
|
|
344
|
+
* legitimate factor and `coercePositiveInt` would floor it to 2.
|
|
345
|
+
* - `maxRetries` goes through `clampIntAllowingZero`. THIS IS THE ONE THAT SHIPS
|
|
346
|
+
* BROKEN WITHOUT IT (R-16): `clampInt` returns the fallback for `n <= 0`, so
|
|
347
|
+
* `clampRetryConfig({ maxRetries: 0 })` would yield 10 — the maximum instead
|
|
348
|
+
* of the minimum, silently, for the key that gates the whole feature.
|
|
349
|
+
*
|
|
350
|
+
* `maxElapsedMs` intentionally keeps plain `clampInt`: its floor is 10 000, so it
|
|
351
|
+
* has no `0` to express.
|
|
352
|
+
*/
|
|
353
|
+
export declare function clampRetryConfig(raw: unknown): RetryConfig;
|
|
354
|
+
/**
|
|
355
|
+
* `RetryConfig` (user intent) -> `RetryPolicy` (engine policy), or `null` for
|
|
356
|
+
* "the user said no".
|
|
357
|
+
*
|
|
358
|
+
* `null` rather than a policy with `maxRetries: 0` because `ProviderRegistry`
|
|
359
|
+
* short-circuits on a null policy and returns the adapter's iterator DIRECTLY —
|
|
360
|
+
* an opted-out session is then allocation-identical to a pre-feature build.
|
|
361
|
+
*
|
|
362
|
+
* TOTAL, AND IT ACCEPTS A MISSING SECTION. `loadConfig` always supplies one, but
|
|
363
|
+
* a `CliConfig` built by hand — every controller test in this package does exactly
|
|
364
|
+
* that, and so would an embedder — legitimately omits it, and a `TypeError` from a
|
|
365
|
+
* pure translation function is the wrong way to find out. Routing through
|
|
366
|
+
* `clampRetryConfig` also means an out-of-range hand-built value can never reach
|
|
367
|
+
* the engine, which is the same "one gate, both directions" rule every other
|
|
368
|
+
* section in this file follows.
|
|
369
|
+
*/
|
|
370
|
+
export declare function toRetryPolicy(cfg: RetryConfig | undefined): RetryPolicy | null;
|
|
371
|
+
export interface FastConfig {
|
|
372
|
+
/**
|
|
373
|
+
* Resolve the tier at all. Defaults to FALSE (R-d).
|
|
374
|
+
*
|
|
375
|
+
* OFF IS BYTE-IDENTICAL (I-2): with this false the system prompt, `task`'s
|
|
376
|
+
* schema, the tool array, the transcript, the status bar and the request
|
|
377
|
+
* payloads are exactly what a pre-feature build produces.
|
|
378
|
+
*/
|
|
379
|
+
enabled: boolean;
|
|
380
|
+
/** `''` INHERITS the main provider — what makes `fast.model` alone a complete
|
|
381
|
+
* configuration for the common "same vendor, cheaper model" case. */
|
|
382
|
+
provider: string;
|
|
383
|
+
/** The fast model id. Empty means NOT CONFIGURED, never "same as main": that
|
|
384
|
+
* distinction is what keeps R-e (opt in to fast == main) from being
|
|
385
|
+
* indistinguishable from a typo (D-4). */
|
|
386
|
+
model: string;
|
|
387
|
+
/** `''` inherits only when the provider matches — a base URL belongs to one
|
|
388
|
+
* API, so a fast tier on a different vendor must not borrow it. */
|
|
389
|
+
baseUrl: string;
|
|
390
|
+
/** Applied to fast-tier children and to the review call. Defaults to `'off'`:
|
|
391
|
+
* a "fast" model asked to think for 32 768 tokens is not fast (D-13). */
|
|
392
|
+
thinkingLevel: ThinkingLevel;
|
|
393
|
+
/** Allow `model: "fast"` on `task`. */
|
|
394
|
+
delegate: boolean;
|
|
395
|
+
/** Run the periodic asynchronous review. */
|
|
396
|
+
review: boolean;
|
|
397
|
+
/** Completed turns between reviews. */
|
|
398
|
+
reviewEveryTurns: number;
|
|
399
|
+
/** Turn frames included in one digest. */
|
|
400
|
+
reviewContextTurns: number;
|
|
401
|
+
/** Ceiling on an injected critique, in characters. */
|
|
402
|
+
reviewMaxChars: number;
|
|
403
|
+
/**
|
|
404
|
+
* Reviews STARTED per session, across all runs (fast-model-tier-hardening
|
|
405
|
+
* §4.1 / W1).
|
|
406
|
+
*
|
|
407
|
+
* The one bound on spend the user never asked for. `reviewEveryTurns`
|
|
408
|
+
* controls the PACE; this controls the TOTAL — and the two are different
|
|
409
|
+
* questions, because a session is not one run. `reviewsThisRun` is reset by
|
|
410
|
+
* every user message, so thirty messages buys thirty runs' worth of reviews
|
|
411
|
+
* with nothing counting across them.
|
|
412
|
+
*
|
|
413
|
+
* DENOMINATED IN REVIEWS, NOT CURRENCY (D-H1). The fast tier is by
|
|
414
|
+
* construction the likeliest place in the product to name a model the static
|
|
415
|
+
* cost table has never seen, and `buildRuntimeModel` prices exactly those at
|
|
416
|
+
* zero (C-11) — so a dollar budget would silently never trigger for the
|
|
417
|
+
* configuration that most needs it. A count is exact for every model, and
|
|
418
|
+
* because per-review cost is already bounded on both sides (a 4 000-char
|
|
419
|
+
* digest in, 512 tokens out), `count x bound` is an honest ceiling.
|
|
420
|
+
*/
|
|
421
|
+
reviewMaxPerSession: number;
|
|
422
|
+
}
|
|
423
|
+
export declare const DEFAULT_FAST_CONFIG: FastConfig;
|
|
424
|
+
/**
|
|
425
|
+
* THE single gate for every fast-config read AND write, mirroring
|
|
426
|
+
* `clampSkillsConfig` / `clampLogConfig` / `clampTeamConfig` / `clampTodoConfig`
|
|
427
|
+
* for the reason those four record: hardening only the read path leaves a bad
|
|
428
|
+
* value on disk that reverts to the default on every launch, which presents to
|
|
429
|
+
* the user as "my setting won't stick".
|
|
430
|
+
*
|
|
431
|
+
* `provider` is CLAMPED TO `''` rather than rejected when it names something
|
|
432
|
+
* with no adapter. `''` means "inherit the main provider", which is the safe
|
|
433
|
+
* reading of a typo — and `resolveFastTier` reports `no_adapter` for the case a
|
|
434
|
+
* user really did configure a dead vendor as the MAIN one.
|
|
435
|
+
*/
|
|
436
|
+
export declare function clampFastConfig(raw: unknown): FastConfig;
|
|
302
437
|
export interface PersistedConfig {
|
|
303
438
|
version: number;
|
|
304
439
|
provider: string;
|
|
305
440
|
model: string;
|
|
306
441
|
baseUrl: string | null;
|
|
307
442
|
thinkingLevel: ThinkingLevel;
|
|
443
|
+
/**
|
|
444
|
+
* Whether the terminal DRAWS the reasoning that came back
|
|
445
|
+
* (agent-activity-presentation §4.1).
|
|
446
|
+
*
|
|
447
|
+
* ADJACENT TO `thinkingLevel` AND DELIBERATELY NAMED DIFFERENTLY: that key is
|
|
448
|
+
* the effort the provider is asked to SPEND, this one is whether the transcript
|
|
449
|
+
* shows it. They are one word apart in the config file and must never be
|
|
450
|
+
* confused, which is why the flag is `--show-thinking` rather than the shorter
|
|
451
|
+
* `--thinking` the existing key already resembles.
|
|
452
|
+
*/
|
|
453
|
+
showThinking: boolean;
|
|
454
|
+
/**
|
|
455
|
+
* Whether a RUNNING tool card draws a bounded tail of its live output
|
|
456
|
+
* (agent-activity-presentation-live §4.1).
|
|
457
|
+
*
|
|
458
|
+
* DEFAULT `true`, unlike `showThinking` next door (D-28). That key hides
|
|
459
|
+
* information by default because reasoning is noise most of the time; this one
|
|
460
|
+
* ADDS the information the requirement asks for, and its cost is bounded by
|
|
461
|
+
* construction -- eight rows per call, sixteen calls, whatever the command
|
|
462
|
+
* emits. It exists as a KILL SWITCH, not as an opt-in: "a build's output
|
|
463
|
+
* redraws the transcript" is exactly the kind of change a user on a slow SSH
|
|
464
|
+
* link may want off.
|
|
465
|
+
*/
|
|
466
|
+
liveToolOutput: boolean;
|
|
308
467
|
/**
|
|
309
468
|
* Output token cap.
|
|
310
469
|
*
|
|
@@ -353,7 +512,8 @@ export interface PersistedConfig {
|
|
|
353
512
|
hints: boolean;
|
|
354
513
|
/**
|
|
355
514
|
* Enable SGR mouse reporting in full-screen mode so the wheel scrolls the
|
|
356
|
-
*
|
|
515
|
+
* transcript, whatever row the pointer is on (wheel-scrolls-transcript-only
|
|
516
|
+
* §4.1).
|
|
357
517
|
*
|
|
358
518
|
* A PLAIN BOOLEAN, not a `fullscreen`-style tri-state: there are no
|
|
359
519
|
* heuristics for an explicit `true` to override (D-10).
|
|
@@ -373,6 +533,10 @@ export interface PersistedConfig {
|
|
|
373
533
|
team: TeamConfig;
|
|
374
534
|
/** Todo planning. The FIFTH nested object; scalars only (see TodoConfig). */
|
|
375
535
|
todo: TodoConfig;
|
|
536
|
+
/** API retry. The SIXTH nested object; scalars only (see RetryConfig). */
|
|
537
|
+
retry: RetryConfig;
|
|
538
|
+
/** Fast model tier. The SEVENTH nested object; scalars only (see FastConfig). */
|
|
539
|
+
fast: FastConfig;
|
|
376
540
|
}
|
|
377
541
|
export declare const DEFAULT_CONFIG: PersistedConfig;
|
|
378
542
|
/**
|
|
@@ -404,6 +568,28 @@ export interface CliConfig {
|
|
|
404
568
|
model: string;
|
|
405
569
|
baseUrl?: string;
|
|
406
570
|
thinkingLevel: ThinkingLevel;
|
|
571
|
+
/**
|
|
572
|
+
* Seeds `ViewState.thinkingVisible` on the first frame (§4.1 / P1-2).
|
|
573
|
+
*
|
|
574
|
+
* IT MUST EXIST HERE AND NOT ONLY IN `PersistedConfig`. `App` reads `cfg.*`,
|
|
575
|
+
* where `cfg` is a `CliConfig`; a key added to the persisted shape alone would
|
|
576
|
+
* round-trip through `config set`, appear in `config list` — and never reach
|
|
577
|
+
* `initialViewState`. `--show-thinking` and `ARAGON_SHOW_THINKING` would parse
|
|
578
|
+
* and be discarded. Nothing would fail; the setting would simply do nothing.
|
|
579
|
+
*/
|
|
580
|
+
showThinking: boolean;
|
|
581
|
+
/**
|
|
582
|
+
* Whether `AgentController` allocates the live-output store and binds
|
|
583
|
+
* `recordOutput` (agent-activity-presentation-live §4.1).
|
|
584
|
+
*
|
|
585
|
+
* IT MUST EXIST HERE AND NOT ONLY IN `PersistedConfig`, for the reason its
|
|
586
|
+
* neighbour records one comment up: the controller reads `config.*`, where
|
|
587
|
+
* `config` is a `CliConfig`, so a key added to the persisted shape alone would
|
|
588
|
+
* round-trip through `config set`, appear in `config list` -- and never reach
|
|
589
|
+
* the constructor. `--live-tool-output` and `ARAGON_LIVE_TOOL_OUTPUT` would
|
|
590
|
+
* parse and be discarded, with nothing failing.
|
|
591
|
+
*/
|
|
592
|
+
liveToolOutput: boolean;
|
|
407
593
|
/** The resolved cap, or `undefined` for AUTO (per-model ceiling, ≤ 64000). */
|
|
408
594
|
maxTokens?: number;
|
|
409
595
|
theme: ThemeName;
|
|
@@ -499,6 +685,30 @@ export interface CliConfig {
|
|
|
499
685
|
* must call `setTodoConfig` as well as persisting (P1-2).
|
|
500
686
|
*/
|
|
501
687
|
todo: TodoConfig;
|
|
688
|
+
/**
|
|
689
|
+
* Resolved API-retry settings (llm-api-retry-backoff §6.2).
|
|
690
|
+
*
|
|
691
|
+
* Unlike `team.enabled` / `todo.enabled` this decides NOTHING at construction
|
|
692
|
+
* time: the policy lives on the `ProviderRegistry` and `setRetryConfig()`
|
|
693
|
+
* replaces it live, so `/retry off` takes effect in the running session. That is
|
|
694
|
+
* why the controller has no `retryRegistered` twin of the two flags above.
|
|
695
|
+
*/
|
|
696
|
+
retry: RetryConfig;
|
|
697
|
+
/**
|
|
698
|
+
* Resolved fast-tier settings (fast-model-tier §4.2).
|
|
699
|
+
*
|
|
700
|
+
* `enabled` here decides `fastRegistered` — whether `task`'s schema carries a
|
|
701
|
+
* `model` property at all — which happens once at construction and can never
|
|
702
|
+
* be undone (C-2). The live on/off switch `/fast` flips is a separate flag on
|
|
703
|
+
* `FastWiring`.
|
|
704
|
+
*
|
|
705
|
+
* THE OTHER NINE KEYS ARE READ LIVE, and that is not the same statement.
|
|
706
|
+
* `provider` / `model` / `baseUrl` feed `resolveFastTier`, which is re-run on
|
|
707
|
+
* every config mutation (§3.2 rule 8 / RV-3) because `''` INHERITS from
|
|
708
|
+
* `config.provider` / `config.baseUrl` and those are rewritten by `/model`,
|
|
709
|
+
* `/provider`, `/reload` and the settings screen.
|
|
710
|
+
*/
|
|
711
|
+
fast: FastConfig;
|
|
502
712
|
/**
|
|
503
713
|
* Lifetime submit count driving the composer hint fade (`HINT_FADE_AFTER`).
|
|
504
714
|
*
|