@aragon-agent/cli 0.6.16 → 0.6.18
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 +107 -51
- package/README.md +91 -48
- package/dist/agent/controller.js +52 -47
- package/dist/agent/headless.js +7 -0
- package/dist/agent/reducer.js +0 -4
- package/dist/cli.js +0 -13
- package/dist/commands/builtins.js +21 -20
- package/dist/commands/index-build.d.ts +39 -0
- package/dist/commands/index-build.js +61 -0
- package/dist/compaction/child.d.ts +10 -8
- package/dist/compaction/child.js +23 -25
- package/dist/compaction/limits.d.ts +0 -2
- package/dist/compaction/limits.js +0 -2
- package/dist/config/cli-commands.d.ts +2 -2
- package/dist/config/cli-commands.js +19 -15
- package/dist/config/load.d.ts +0 -17
- package/dist/config/load.js +0 -6
- package/dist/config/schema.d.ts +41 -9
- package/dist/config/schema.js +18 -11
- package/dist/exec/events.d.ts +16 -9
- package/dist/exec/events.js +2 -2
- package/dist/exec/runner.js +17 -1
- package/dist/fast/limits.d.ts +2 -2
- package/dist/fast/limits.js +2 -2
- package/dist/fast/prompt.d.ts +10 -11
- package/dist/fast/prompt.js +19 -20
- package/dist/fast/reviewer.d.ts +1 -1
- package/dist/fast/reviewer.js +1 -1
- package/dist/fast/types.d.ts +0 -2
- package/dist/fast/wiring.d.ts +18 -34
- package/dist/fast/wiring.js +20 -51
- package/dist/input/csiu-keys.js +13 -2
- package/dist/input/limits.d.ts +15 -0
- package/dist/input/limits.js +15 -0
- package/dist/input/win32-input-mode.js +7 -1
- package/dist/logging/install.d.ts +9 -0
- package/dist/logging/install.js +11 -0
- package/dist/session/validate-session.js +3 -1
- package/dist/team/child-reviewer.d.ts +105 -0
- package/dist/team/child-reviewer.js +117 -0
- package/dist/team/human-queue.d.ts +11 -0
- package/dist/team/human-queue.js +18 -1
- package/dist/team/limits.d.ts +40 -0
- package/dist/team/limits.js +41 -0
- package/dist/team/normalize.d.ts +7 -26
- package/dist/team/normalize.js +9 -22
- package/dist/team/overseer.d.ts +157 -0
- package/dist/team/overseer.js +348 -0
- package/dist/team/prompt.d.ts +0 -11
- package/dist/team/prompt.js +3 -12
- package/dist/team/report.d.ts +4 -19
- package/dist/team/report.js +27 -28
- package/dist/team/runtime.d.ts +76 -16
- package/dist/team/runtime.js +410 -57
- package/dist/team/subagent.d.ts +48 -19
- package/dist/team/subagent.js +88 -31
- package/dist/team/task-tool.d.ts +6 -26
- package/dist/team/task-tool.js +17 -48
- package/dist/team/types.d.ts +65 -41
- package/dist/ui/App.d.ts +1 -1
- package/dist/ui/App.js +64 -4
- package/dist/ui/BottomStatusRow.js +2 -1
- package/dist/ui/Header.js +13 -2
- package/dist/ui/PromptInput.js +11 -1
- package/dist/ui/StatusBar.js +2 -1
- package/dist/ui/TeamPanel.js +1 -1
- package/dist/ui/entries/TeamCard.js +1 -6
- package/dist/ui/layout/status-detail-layout.js +12 -2
- package/dist/ui/layout/status-layout.d.ts +4 -2
- package/dist/ui/layout/status-layout.js +24 -1
- package/dist/ui/overlays/HelpOverlay.js +2 -2
- package/package.json +2 -2
- package/skills/project-indexer/SKILL.md +163 -0
- package/skills/project-indexer/templates/cleancode-overrides.md +46 -0
- package/skills/project-indexer/templates/cleancode-template.md +94 -0
- package/skills/project-indexer/templates/config-template.md +69 -0
- package/skills/project-indexer/templates/index-template.md +129 -0
- package/dist/ui/ModeChip.d.ts +0 -18
- package/dist/ui/ModeChip.js +0 -24
|
@@ -14,7 +14,7 @@ import { getConfigBackupPath, getConfigPath, getHomeRoot, getLogsDir, getPromptH
|
|
|
14
14
|
import { getHomeMigrationBreadcrumbPath } from './migrate-home.js';
|
|
15
15
|
import { loadPersistedConfig, updatePersistedConfig } from './store.js';
|
|
16
16
|
import { normalizeModelProfiles, validateModelProfiles } from './model-profiles.js';
|
|
17
|
-
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
|
+
import { clampFastConfig, clampRetryConfig, clampCompactionConfig, clampTeamConfig, parseThresholdInput, clampUpdateConfig, coercePositiveInt, maskSecret, DEFAULT_FAST_CONFIG, DEFAULT_RETRY_CONFIG, DEFAULT_TEAM_CONFIG, DEFAULT_COMPACTION_CONFIG, DEFAULT_UPDATE_CONFIG, } from './schema.js';
|
|
18
18
|
import { clampLogLevel } from '../logging/levels.js';
|
|
19
19
|
/** Config keys under `log.` that `aragon config set` accepts. */
|
|
20
20
|
export const LOG_CONFIG_SET_KEYS = [
|
|
@@ -43,6 +43,7 @@ export const TEAM_CONFIG_SET_KEYS = [
|
|
|
43
43
|
'team.subagentTimeoutMs',
|
|
44
44
|
'team.dispatchTimeoutMs',
|
|
45
45
|
'team.maxTurnsPerSubagent',
|
|
46
|
+
'team.overseer',
|
|
46
47
|
];
|
|
47
48
|
/**
|
|
48
49
|
* Config keys under `retry.` that `aragon config set` accepts
|
|
@@ -81,7 +82,6 @@ export const FAST_CONFIG_SET_KEYS = [
|
|
|
81
82
|
'fast.model',
|
|
82
83
|
'fast.baseUrl',
|
|
83
84
|
'fast.thinkingLevel',
|
|
84
|
-
'fast.delegate',
|
|
85
85
|
'fast.review',
|
|
86
86
|
'fast.reviewEveryTurns',
|
|
87
87
|
'fast.reviewContextTurns',
|
|
@@ -177,25 +177,31 @@ export function applyLogConfigSet(key, value) {
|
|
|
177
177
|
*/
|
|
178
178
|
export function applyTeamConfigSet(key, value) {
|
|
179
179
|
const patch = (team) => ({ team });
|
|
180
|
+
// EVERY NUMERIC KEY ROUTES THROUGH `clampTeamConfig`, not through
|
|
181
|
+
// `coercePositiveInt`, for the reason `applyRetryConfigSet` records one block
|
|
182
|
+
// below: `coercePositiveInt` returns its fallback for `n <= 0`, so
|
|
183
|
+
// `config set team.subagentTimeoutMs 0` would write 300000 (the old default)
|
|
184
|
+
// instead of the documented NO-LIMIT value, silently. The caller echoes the
|
|
185
|
+
// STORED value, which is what makes an out-of-range input visible.
|
|
186
|
+
const clampOne = (field) => {
|
|
187
|
+
const merged = clampTeamConfig({ ...DEFAULT_TEAM_CONFIG, [field]: value });
|
|
188
|
+
return { [field]: merged[field] };
|
|
189
|
+
};
|
|
180
190
|
switch (key) {
|
|
181
191
|
case 'team.enabled':
|
|
182
192
|
return patch({ enabled: isTrue(value) });
|
|
183
193
|
case 'team.maxSubagents':
|
|
184
|
-
return patch(
|
|
194
|
+
return patch(clampOne('maxSubagents'));
|
|
185
195
|
case 'team.maxConcurrent':
|
|
186
|
-
return patch(
|
|
196
|
+
return patch(clampOne('maxConcurrent'));
|
|
187
197
|
case 'team.subagentTimeoutMs':
|
|
188
|
-
return patch(
|
|
189
|
-
subagentTimeoutMs: coercePositiveInt(value, DEFAULT_TEAM_CONFIG.subagentTimeoutMs),
|
|
190
|
-
});
|
|
198
|
+
return patch(clampOne('subagentTimeoutMs'));
|
|
191
199
|
case 'team.dispatchTimeoutMs':
|
|
192
|
-
return patch(
|
|
193
|
-
dispatchTimeoutMs: coercePositiveInt(value, DEFAULT_TEAM_CONFIG.dispatchTimeoutMs),
|
|
194
|
-
});
|
|
200
|
+
return patch(clampOne('dispatchTimeoutMs'));
|
|
195
201
|
case 'team.maxTurnsPerSubagent':
|
|
196
|
-
return patch(
|
|
197
|
-
|
|
198
|
-
});
|
|
202
|
+
return patch(clampOne('maxTurnsPerSubagent'));
|
|
203
|
+
case 'team.overseer':
|
|
204
|
+
return patch({ overseer: isTrue(value) });
|
|
199
205
|
default:
|
|
200
206
|
return null;
|
|
201
207
|
}
|
|
@@ -273,8 +279,6 @@ export function applyFastConfigSet(key, value) {
|
|
|
273
279
|
return patch(clampOne('baseUrl'));
|
|
274
280
|
case 'fast.thinkingLevel':
|
|
275
281
|
return patch(clampOne('thinkingLevel'));
|
|
276
|
-
case 'fast.delegate':
|
|
277
|
-
return patch({ delegate: isTrue(value) });
|
|
278
282
|
case 'fast.review':
|
|
279
283
|
return patch({ review: isTrue(value) });
|
|
280
284
|
case 'fast.reviewEveryTurns':
|
package/dist/config/load.d.ts
CHANGED
|
@@ -193,23 +193,6 @@ export interface CliFlags {
|
|
|
193
193
|
* to keep in step with `toFlags`.
|
|
194
194
|
*/
|
|
195
195
|
fastReview?: string;
|
|
196
|
-
/**
|
|
197
|
-
* `--fast-delegate` ⇒ true, `--no-fast-delegate` ⇒ false, absent ⇒ undefined
|
|
198
|
-
* (web-use-tier-cooperation-and-control-closure §4.1.5).
|
|
199
|
-
*
|
|
200
|
-
* DECLARED AS A PAIR — MANDATORY, for the reason `--team`, `--todo-panel`,
|
|
201
|
-
* `--render-governor`, `--retry` and `--fast` each record in turn, and here
|
|
202
|
-
* with the SAME polarity as `--update`: `fast.delegate` is PERSISTED and
|
|
203
|
-
* defaults to `true`, so a lone `--no-fast-delegate` would make commander
|
|
204
|
-
* default `opts.fastDelegate` to `true` and silently overwrite a stored
|
|
205
|
-
* `false` on every run that passed no flag at all.
|
|
206
|
-
*
|
|
207
|
-
* It exists because it is the ONLY `fast.*` sub-switch with no channel a
|
|
208
|
-
* wrapper can reach: `--fast-review <n|off>` already covers `review` and
|
|
209
|
-
* `reviewEveryTurns`, and `enabled` / `model` / `provider` have both a flag
|
|
210
|
-
* and an environment variable.
|
|
211
|
-
*/
|
|
212
|
-
fastDelegate?: boolean;
|
|
213
196
|
/**
|
|
214
197
|
* `--update` ⇒ true, `--no-update` ⇒ false, absent ⇒ undefined
|
|
215
198
|
* (cli-auto-update §4.2).
|
package/dist/config/load.js
CHANGED
|
@@ -243,12 +243,6 @@ function resolveFastConfig(flags, env, file) {
|
|
|
243
243
|
...(flags.fastProvider !== undefined && flags.fastProvider !== ''
|
|
244
244
|
? { provider: flags.fastProvider }
|
|
245
245
|
: {}),
|
|
246
|
-
// `!== undefined`, for the reason stated on `flags.fast` above: commander
|
|
247
|
-
// materialises a lone `--no-fast-delegate` as `opts.fastDelegate = true`
|
|
248
|
-
// when the flag is absent, and `delegate` defaults to TRUE — so a truthiness
|
|
249
|
-
// check would force it on for every run that passed no flag at all,
|
|
250
|
-
// overwriting a stored `false` with nothing to show for it.
|
|
251
|
-
...(flags.fastDelegate !== undefined ? { delegate: flags.fastDelegate } : {}),
|
|
252
246
|
...reviewPatch,
|
|
253
247
|
});
|
|
254
248
|
}
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -303,12 +303,43 @@ export interface TeamConfig {
|
|
|
303
303
|
* failed subagent.
|
|
304
304
|
*/
|
|
305
305
|
maxConcurrent: number;
|
|
306
|
-
/**
|
|
306
|
+
/**
|
|
307
|
+
* One child's wall clock before its own abort. `0` (the default) means NO
|
|
308
|
+
* ceiling: a subagent runs until it finishes or is aborted, exactly like
|
|
309
|
+
* the lead, whose only in-run ceiling is the event-silence idle watchdog
|
|
310
|
+
* a child already keeps. A wedged child still dies on its OWN watchdog.
|
|
311
|
+
*
|
|
312
|
+
* WITH `team.overseer` ON (the default) this is the FIRST wall-clock
|
|
313
|
+
* INSPECTION point, not a hard abort: the supervisor looks and decides
|
|
314
|
+
* (wait / nudge / replace / abandon), so a slow-but-healthy child is no
|
|
315
|
+
* longer killed at an arbitrary wall clock.
|
|
316
|
+
*/
|
|
307
317
|
subagentTimeoutMs: number;
|
|
308
|
-
/**
|
|
318
|
+
/**
|
|
319
|
+
* The whole dispatch's wall clock, and the `task` tool-timeout override.
|
|
320
|
+
* `0` (the default) means NO ceiling: the executor override of `0` arms no
|
|
321
|
+
* timer (see Core `ToolExecutor`), so the fan-out lasts as long as its
|
|
322
|
+
* slowest child and only an Esc ends it early.
|
|
323
|
+
*/
|
|
309
324
|
dispatchTimeoutMs: number;
|
|
310
|
-
/**
|
|
325
|
+
/**
|
|
326
|
+
* Runaway-loop cap: turns one child may take before it is stopped.
|
|
327
|
+
* `0` (the default) means NO cap - the same exposure the lead has, and
|
|
328
|
+
* the deliberate trade of "subagents as capable as the main agent".
|
|
329
|
+
*/
|
|
311
330
|
maxTurnsPerSubagent: number;
|
|
331
|
+
/**
|
|
332
|
+
* The dispatch supervisor (team-overseer): time ceilings on children
|
|
333
|
+
* become inspection triggers for a fast-tier supervisor that decides
|
|
334
|
+
* wait / nudge / replace / abandon, instead of aborts. Default TRUE.
|
|
335
|
+
*
|
|
336
|
+
* READ PER DISPATCH. With the supervisor off (or no fast tier), children
|
|
337
|
+
* run exactly the pre-feature regime: `subagentTimeoutMs` is a hard abort
|
|
338
|
+
* and silence is the child's own watchdog. With it ON,
|
|
339
|
+
* `subagentTimeoutMs > 0` is the FIRST wall-clock inspection point, not
|
|
340
|
+
* a death sentence.
|
|
341
|
+
*/
|
|
342
|
+
overseer: boolean;
|
|
312
343
|
}
|
|
313
344
|
/**
|
|
314
345
|
* The requirement's ceiling on the fan-out (R-g).
|
|
@@ -458,8 +489,6 @@ export interface FastConfig {
|
|
|
458
489
|
/** Applied to fast-tier children and to the review call. Defaults to `'off'`:
|
|
459
490
|
* a "fast" model asked to think for 32 768 tokens is not fast (D-13). */
|
|
460
491
|
thinkingLevel: ThinkingLevel;
|
|
461
|
-
/** Allow `model: "fast"` on `task`. */
|
|
462
|
-
delegate: boolean;
|
|
463
492
|
/** Run the periodic asynchronous review. */
|
|
464
493
|
review: boolean;
|
|
465
494
|
/** Completed turns between reviews. */
|
|
@@ -584,10 +613,13 @@ export interface CompactionConfig {
|
|
|
584
613
|
* (context-auto-compaction-hardening §3.4 / W3). Default TRUE.
|
|
585
614
|
*
|
|
586
615
|
* IT REVERSES D-15, WHOSE PREMISE IS MEASURABLY FALSE at the configured bounds:
|
|
587
|
-
* `team.maxTurnsPerSubagent`
|
|
588
|
-
* 24 turns over fifteen minutes is the same profile
|
|
589
|
-
*
|
|
590
|
-
*
|
|
616
|
+
* D-15 measured `team.maxTurnsPerSubagent` 24 and `team.dispatchTimeoutMs`
|
|
617
|
+
* 900 000, where 24 turns over fifteen minutes is already the same profile
|
|
618
|
+
* as the lead run this feature exists for — and the parity defaults of
|
|
619
|
+
* 2ff15a9c3 later removed both ceilings (0 = no turn cap, no wall clock),
|
|
620
|
+
* which makes the premise falser still, not truer. When a child overflows
|
|
621
|
+
* today its history is discarded and the lead receives one partial sentence
|
|
622
|
+
* for the whole dispatch.
|
|
591
623
|
*
|
|
592
624
|
* `false` REPRODUCES ROUND 1 EXACTLY: `subagent.ts` spreads no `contextManager`
|
|
593
625
|
* key at all, so the child's loop gate tests an absent field.
|
package/dist/config/schema.js
CHANGED
|
@@ -447,15 +447,23 @@ export const DEFAULT_TEAM_CONFIG = {
|
|
|
447
447
|
enabled: true,
|
|
448
448
|
maxSubagents: 5,
|
|
449
449
|
maxConcurrent: 3,
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
450
|
+
// 0 = NO LIMIT. Subagents run under the same regime as the lead: no
|
|
451
|
+
// wall clock, no turn cap; only the idle watchdog and the user's Esc.
|
|
452
|
+
subagentTimeoutMs: 0,
|
|
453
|
+
dispatchTimeoutMs: 0,
|
|
454
|
+
maxTurnsPerSubagent: 0,
|
|
455
|
+
// The dispatch supervisor, default ON (team-overseer): ceilings become
|
|
456
|
+
// inspections; the fast-tier supervisor decides what to do.
|
|
457
|
+
overseer: true,
|
|
453
458
|
};
|
|
454
459
|
const SUBAGENTS_RANGE = { min: 1, max: HARD_MAX_SUBAGENTS };
|
|
455
460
|
const CONCURRENT_RANGE = { min: 1, max: HARD_MAX_SUBAGENTS };
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
461
|
+
// `min: 0` is the documented OFF SWITCH for each bound, so these MUST use
|
|
462
|
+
// `clampIntAllowingZero`: plain `clampInt` folds `0` back to the fallback
|
|
463
|
+
// ("my setting won't stick"), the exact trap `scrollResumeMs` records above.
|
|
464
|
+
const SUBAGENT_TIMEOUT_RANGE = { min: 0, max: 1_800_000 };
|
|
465
|
+
const DISPATCH_TIMEOUT_RANGE = { min: 0, max: 3_600_000 };
|
|
466
|
+
const TURNS_RANGE = { min: 0, max: 100 };
|
|
459
467
|
/**
|
|
460
468
|
* THE single gate for every team-config read AND write, mirroring
|
|
461
469
|
* `clampSkillsConfig` / `clampLogConfig` for the reason those two record:
|
|
@@ -474,9 +482,10 @@ export function clampTeamConfig(raw) {
|
|
|
474
482
|
enabled: bool(src.enabled, DEFAULT_TEAM_CONFIG.enabled),
|
|
475
483
|
maxSubagents,
|
|
476
484
|
maxConcurrent: Math.min(maxSubagents, clampInt(src.maxConcurrent, DEFAULT_TEAM_CONFIG.maxConcurrent, CONCURRENT_RANGE)),
|
|
477
|
-
subagentTimeoutMs:
|
|
478
|
-
dispatchTimeoutMs:
|
|
479
|
-
maxTurnsPerSubagent:
|
|
485
|
+
subagentTimeoutMs: clampIntAllowingZero(src.subagentTimeoutMs, DEFAULT_TEAM_CONFIG.subagentTimeoutMs, SUBAGENT_TIMEOUT_RANGE),
|
|
486
|
+
dispatchTimeoutMs: clampIntAllowingZero(src.dispatchTimeoutMs, DEFAULT_TEAM_CONFIG.dispatchTimeoutMs, DISPATCH_TIMEOUT_RANGE),
|
|
487
|
+
maxTurnsPerSubagent: clampIntAllowingZero(src.maxTurnsPerSubagent, DEFAULT_TEAM_CONFIG.maxTurnsPerSubagent, TURNS_RANGE),
|
|
488
|
+
overseer: bool(src.overseer, DEFAULT_TEAM_CONFIG.overseer),
|
|
480
489
|
};
|
|
481
490
|
}
|
|
482
491
|
export const DEFAULT_TODO_CONFIG = {
|
|
@@ -615,7 +624,6 @@ export const DEFAULT_FAST_CONFIG = {
|
|
|
615
624
|
model: '',
|
|
616
625
|
baseUrl: '',
|
|
617
626
|
thinkingLevel: 'off',
|
|
618
|
-
delegate: true,
|
|
619
627
|
review: true,
|
|
620
628
|
reviewEveryTurns: 5,
|
|
621
629
|
reviewContextTurns: 3,
|
|
@@ -655,7 +663,6 @@ export function clampFastConfig(raw) {
|
|
|
655
663
|
model: text(src.model, DEFAULT_FAST_CONFIG.model),
|
|
656
664
|
baseUrl: text(src.baseUrl, DEFAULT_FAST_CONFIG.baseUrl),
|
|
657
665
|
thinkingLevel: clampThinkingLevel(src.thinkingLevel, DEFAULT_FAST_CONFIG.thinkingLevel),
|
|
658
|
-
delegate: bool(src.delegate, DEFAULT_FAST_CONFIG.delegate),
|
|
659
666
|
review: bool(src.review, DEFAULT_FAST_CONFIG.review),
|
|
660
667
|
reviewEveryTurns: clampInt(src.reviewEveryTurns, DEFAULT_FAST_CONFIG.reviewEveryTurns, REVIEW_EVERY_RANGE),
|
|
661
668
|
reviewContextTurns: clampInt(src.reviewContextTurns, DEFAULT_FAST_CONFIG.reviewContextTurns, REVIEW_CONTEXT_RANGE),
|
package/dist/exec/events.d.ts
CHANGED
|
@@ -193,7 +193,10 @@ export interface ExecTodoEvent {
|
|
|
193
193
|
export interface ExecTeamEvent {
|
|
194
194
|
type: 'team';
|
|
195
195
|
sessionId: string;
|
|
196
|
-
subtype: 'dispatch_start' | 'agent_update' | 'dispatch_end';
|
|
196
|
+
subtype: 'dispatch_start' | 'agent_update' | 'dispatch_end' | 'overseer';
|
|
197
|
+
action?: string;
|
|
198
|
+
trigger?: string;
|
|
199
|
+
reason?: string;
|
|
197
200
|
label?: string;
|
|
198
201
|
phase?: string;
|
|
199
202
|
description?: string;
|
|
@@ -219,11 +222,11 @@ export interface ExecFastReviewEvent {
|
|
|
219
222
|
* not know is unaffected.
|
|
220
223
|
*
|
|
221
224
|
* THE PROBLEM IT SOLVES. `fast_review` only fires when a review produced TEXT,
|
|
222
|
-
* so every other outcome — a review that failed, a tier that switched itself
|
|
223
|
-
* after three failures, a budget that ran out
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
225
|
+
* so every other outcome — a review that failed, a tier that switched itself
|
|
226
|
+
* off after three failures, or a budget that ran out — was invisible to a
|
|
227
|
+
* wrapper. The single most likely and least self-diagnosable failure ("it
|
|
228
|
+
* runs but not one review card ever arrives") had no signal at all on this
|
|
229
|
+
* stream.
|
|
227
230
|
*
|
|
228
231
|
* IT IS A STATE EVENT, NOT A LOG LINE. It fires on `tier_changed` and on every
|
|
229
232
|
* `review_end`, which in a session with reviews is a handful per hundred turns.
|
|
@@ -249,7 +252,11 @@ export interface ExecFastTierEvent {
|
|
|
249
252
|
reviews: number;
|
|
250
253
|
reviewBudget: number;
|
|
251
254
|
budgetReached: boolean;
|
|
252
|
-
/**
|
|
255
|
+
/**
|
|
256
|
+
* DEPRECATED, ALWAYS `0`. Fast-tier children no longer exist (every `task`
|
|
257
|
+
* child runs the lead's model); the field is kept so schema-v1 consumers
|
|
258
|
+
* keep parsing. Do not build new readers on it.
|
|
259
|
+
*/
|
|
253
260
|
delegated: number;
|
|
254
261
|
inFlight: boolean;
|
|
255
262
|
/** Present only on the `review_end` branch. */
|
|
@@ -399,8 +406,8 @@ export interface ExecInitParams {
|
|
|
399
406
|
*
|
|
400
407
|
* · `'interrupt'` — `{"type":"interrupt"}` on stdin settles the turn
|
|
401
408
|
* without killing the process.
|
|
402
|
-
* · `'fast-policy'` — this build understands `--fast-
|
|
403
|
-
*
|
|
409
|
+
* · `'fast-policy'` — this build understands `--fast-review`.
|
|
410
|
+
* FOR AFTER-THE-FACT DISPLAY ONLY:
|
|
404
411
|
* argv is fixed before `system/init` arrives, so it
|
|
405
412
|
* cannot gate whether the flags are passed.
|
|
406
413
|
* · `'fast-tier-events'` — this build emits `fast_tier`. Its ABSENCE is what
|
package/dist/exec/events.js
CHANGED
|
@@ -34,8 +34,8 @@ export const EXEC_SCHEMA_VERSION = 1;
|
|
|
34
34
|
*
|
|
35
35
|
* · `'interrupt'` — `{"type":"interrupt"}` on stdin settles the turn
|
|
36
36
|
* without killing the process.
|
|
37
|
-
* · `'fast-policy'` — this build understands `--fast-
|
|
38
|
-
*
|
|
37
|
+
* · `'fast-policy'` — this build understands `--fast-review`.
|
|
38
|
+
* FOR AFTER-THE-FACT DISPLAY ONLY:
|
|
39
39
|
* argv is fixed before `system/init` arrives, so it
|
|
40
40
|
* cannot gate whether the flags are passed.
|
|
41
41
|
* · `'fast-tier-events'` — this build emits `fast_tier`. Its ABSENCE is what
|
package/dist/exec/runner.js
CHANGED
|
@@ -153,7 +153,10 @@ export class ExecRunner {
|
|
|
153
153
|
reviews: snapshot.reviews,
|
|
154
154
|
reviewBudget: snapshot.reviewBudget,
|
|
155
155
|
budgetReached: snapshot.budgetReached,
|
|
156
|
-
|
|
156
|
+
// Deprecated in schema v1: always 0 since fast-tier children were
|
|
157
|
+
// removed (every task child runs the lead's model). Emitted so
|
|
158
|
+
// schema-v1 consumers keep parsing.
|
|
159
|
+
delegated: 0,
|
|
157
160
|
inFlight: snapshot.inFlight,
|
|
158
161
|
...(event.type === 'review_end'
|
|
159
162
|
? {
|
|
@@ -704,6 +707,19 @@ export class ExecRunner {
|
|
|
704
707
|
total: runs.length,
|
|
705
708
|
aborted: event.outcome.aborted,
|
|
706
709
|
});
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (event.type === 'overseer') {
|
|
713
|
+
this.emit({
|
|
714
|
+
type: 'team',
|
|
715
|
+
sessionId: this.sessionId,
|
|
716
|
+
subtype: 'overseer',
|
|
717
|
+
label: event.label,
|
|
718
|
+
action: event.decision.action,
|
|
719
|
+
trigger: event.trigger,
|
|
720
|
+
reason: event.decision.reason,
|
|
721
|
+
});
|
|
722
|
+
return;
|
|
707
723
|
}
|
|
708
724
|
}
|
|
709
725
|
}
|
package/dist/fast/limits.d.ts
CHANGED
|
@@ -76,7 +76,7 @@ export declare const FAST_LIMITS: {
|
|
|
76
76
|
* A critique waiting for its injection window goes stale (RV-12).
|
|
77
77
|
*
|
|
78
78
|
* The window is not guaranteed to be prompt: one `task` dispatch is a single
|
|
79
|
-
* tool call that can run for
|
|
79
|
+
* tool call that can run for as long as its children need, so a critique triggered
|
|
80
80
|
* just before one arrives at the far side describing a state five children
|
|
81
81
|
* have since rewritten. Advice that is merely late is worse than no advice,
|
|
82
82
|
* because the lead cannot tell that it is late.
|
|
@@ -95,4 +95,4 @@ export declare const FAST_LIMITS: {
|
|
|
95
95
|
* changes, so a behaviour report can be tied to a block revision with one grep -
|
|
96
96
|
* exactly what `TEAM_BLOCK_VERSION` and `TODO_BLOCK_VERSION` are for.
|
|
97
97
|
*/
|
|
98
|
-
export declare const FAST_BLOCK_VERSION = "
|
|
98
|
+
export declare const FAST_BLOCK_VERSION = "v2-2026-10";
|
package/dist/fast/limits.js
CHANGED
|
@@ -76,7 +76,7 @@ export const FAST_LIMITS = {
|
|
|
76
76
|
* A critique waiting for its injection window goes stale (RV-12).
|
|
77
77
|
*
|
|
78
78
|
* The window is not guaranteed to be prompt: one `task` dispatch is a single
|
|
79
|
-
* tool call that can run for
|
|
79
|
+
* tool call that can run for as long as its children need, so a critique triggered
|
|
80
80
|
* just before one arrives at the far side describing a state five children
|
|
81
81
|
* have since rewritten. Advice that is merely late is worse than no advice,
|
|
82
82
|
* because the lead cannot tell that it is late.
|
|
@@ -95,4 +95,4 @@ export const FAST_LIMITS = {
|
|
|
95
95
|
* changes, so a behaviour report can be tied to a block revision with one grep -
|
|
96
96
|
* exactly what `TEAM_BLOCK_VERSION` and `TODO_BLOCK_VERSION` are for.
|
|
97
97
|
*/
|
|
98
|
-
export const FAST_BLOCK_VERSION = '
|
|
98
|
+
export const FAST_BLOCK_VERSION = 'v2-2026-10';
|
package/dist/fast/prompt.d.ts
CHANGED
|
@@ -19,23 +19,22 @@ export interface FastBlockParams {
|
|
|
19
19
|
/** The resolved fast model id, interpolated so the prompt never names a model
|
|
20
20
|
* the tier will not actually use (§3.9 / RV-3). */
|
|
21
21
|
model: string;
|
|
22
|
-
/** `fast.delegate` — whether `model: "fast"` is honoured on `task`. */
|
|
23
|
-
delegate: boolean;
|
|
24
22
|
/** `fast.review` — whether `<fast_review>` blocks can appear at all. */
|
|
25
23
|
review: boolean;
|
|
26
24
|
}
|
|
27
25
|
/**
|
|
28
|
-
* The
|
|
29
|
-
*
|
|
30
|
-
*
|
|
26
|
+
* The `<fast_tier>` block, spliced for the lead AND for task children running
|
|
27
|
+
* under a per-child reviewer. Under 1100 characters on purpose: it is paid for
|
|
28
|
+
* on EVERY turn of every fast-enabled session, so anything that does not change
|
|
29
|
+
* a decision does not belong in it (R-11).
|
|
31
30
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
31
|
+
* REVIEW-ONLY SIN MAIN-AGENT PARITY: every `task` child runs the lead's own
|
|
32
|
+
* model, so the block no longer advertises a per-child `model:"fast"`. Telling
|
|
33
|
+
* a model about a field that no longer exists is how you get a model that keeps
|
|
34
|
+
* asking for something it can never have.
|
|
36
35
|
*
|
|
37
|
-
* Returns `''` when
|
|
38
|
-
*
|
|
36
|
+
* Returns `''` when the review is off, which the splice treats as "no block"
|
|
37
|
+
* and which keeps the byte-identity branch intact.
|
|
39
38
|
*/
|
|
40
39
|
export declare function buildFastBlock(params: FastBlockParams): string;
|
|
41
40
|
export interface ReviewSystemPromptParams {
|
package/dist/fast/prompt.js
CHANGED
|
@@ -16,33 +16,32 @@
|
|
|
16
16
|
import { FAST_BLOCK_VERSION } from './limits.js';
|
|
17
17
|
export { FAST_BLOCK_VERSION };
|
|
18
18
|
/**
|
|
19
|
-
* The
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* The `<fast_tier>` block, spliced for the lead AND for task children running
|
|
20
|
+
* under a per-child reviewer. Under 1100 characters on purpose: it is paid for
|
|
21
|
+
* on EVERY turn of every fast-enabled session, so anything that does not change
|
|
22
|
+
* a decision does not belong in it (R-11).
|
|
22
23
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* REVIEW-ONLY SIN MAIN-AGENT PARITY: every `task` child runs the lead's own
|
|
25
|
+
* model, so the block no longer advertises a per-child `model:"fast"`. Telling
|
|
26
|
+
* a model about a field that no longer exists is how you get a model that keeps
|
|
27
|
+
* asking for something it can never have.
|
|
27
28
|
*
|
|
28
|
-
* Returns `''` when
|
|
29
|
-
*
|
|
29
|
+
* Returns `''` when the review is off, which the splice treats as "no block"
|
|
30
|
+
* and which keeps the byte-identity branch intact.
|
|
30
31
|
*/
|
|
31
32
|
export function buildFastBlock(params) {
|
|
32
|
-
if (!params.
|
|
33
|
+
if (!params.review)
|
|
33
34
|
return '';
|
|
34
|
-
|
|
35
|
+
return [
|
|
35
36
|
'<fast_tier>',
|
|
36
37
|
`A second, cheaper model is available in this session (${params.model}).`,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
lines.push('</fast_tier>');
|
|
45
|
-
return lines.join('\n');
|
|
38
|
+
'',
|
|
39
|
+
'Reviews: every few turns a <fast_review> block may appear in the conversation.',
|
|
40
|
+
'It is an automated second opinion from the fast model - NOT a message from the',
|
|
41
|
+
'user. Treat it as advice: act on it when it is right, say so briefly and carry',
|
|
42
|
+
'on when it is not, and never ask the user to confirm it.',
|
|
43
|
+
'</fast_tier>',
|
|
44
|
+
].join('\n');
|
|
46
45
|
}
|
|
47
46
|
/**
|
|
48
47
|
* The reviewer's own system prompt.
|
package/dist/fast/reviewer.d.ts
CHANGED
|
@@ -97,7 +97,7 @@ export interface FastReviewerDeps {
|
|
|
97
97
|
* `FastWiring.snapshot()`, so the self-disable can announce itself.
|
|
98
98
|
*
|
|
99
99
|
* The reviewer cannot build a `FastSnapshot` on its own — `live`,
|
|
100
|
-
* `sameAsMain
|
|
100
|
+
* `sameAsMain` and `pricingUnknown` all belong to the wiring —
|
|
101
101
|
* and the two existing `tier_changed` emitters read it the same way.
|
|
102
102
|
*/
|
|
103
103
|
snapshot(): FastSnapshot;
|
package/dist/fast/reviewer.js
CHANGED
|
@@ -375,7 +375,7 @@ export class FastReviewer {
|
|
|
375
375
|
return;
|
|
376
376
|
this.budgetAnnouncedAt = limit;
|
|
377
377
|
this.deps.notify('info', `Fast reviews: session budget reached (${limit}). ` +
|
|
378
|
-
`
|
|
378
|
+
`Raise it with /fast budget <n>.`);
|
|
379
379
|
this.log.info('fast_review_budget_reached', { limit, reviews: this.reviewIndex });
|
|
380
380
|
}
|
|
381
381
|
// -----------------------------------------------------------------------
|
package/dist/fast/types.d.ts
CHANGED
|
@@ -107,8 +107,6 @@ export interface FastSnapshot {
|
|
|
107
107
|
* report a budget reached for a session that never had one (RV-H10).
|
|
108
108
|
*/
|
|
109
109
|
budgetReached: boolean;
|
|
110
|
-
/** Fast-tier children dispatched this session. */
|
|
111
|
-
delegated: number;
|
|
112
110
|
usage: TokenUsage;
|
|
113
111
|
/**
|
|
114
112
|
* No price table for `model` (C-11 / RV-4).
|
package/dist/fast/wiring.d.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* THIS CLASS EXISTS FOR A BUDGET REASON, NOT AN AESTHETIC ONE (C-12 / RV-5).
|
|
8
8
|
* `CLAUDE.md` caps a source file at 1000 lines and `controller.ts` was at 960
|
|
9
9
|
* before this feature, which handed it nine new responsibilities. `FastWiring`
|
|
10
|
-
* owns the flag pair, the tier cache, the reviewer's lifetime and the
|
|
11
|
-
*
|
|
10
|
+
* owns the flag pair, the tier cache, the reviewer's lifetime and the shared
|
|
11
|
+
* fail-fast review transport; `AgentController` keeps one field and four thin
|
|
12
12
|
* forwarders. It is still CLI-local and still holds no `ui/` import.
|
|
13
13
|
*
|
|
14
14
|
* TWO FLAGS AND ONE LIVE PREDICATE (§3.3), which is the shape every optional
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
* caused it (`agent-loop.ts:140-145`).
|
|
32
32
|
*/
|
|
33
33
|
import type { ModelRole } from '../config/model-profiles.js';
|
|
34
|
-
import { type AgentEvent, type AssistantMessage, type LLMRequest, type ModelRef
|
|
34
|
+
import { type AgentEvent, type AssistantMessage, type LLMRequest, type ModelRef } from '@aragon-agent/core';
|
|
35
35
|
import type { CliConfig } from '../config/schema.js';
|
|
36
36
|
import type { NoticeLevel } from '../agent/reducer.js';
|
|
37
|
-
import type { FastEventListener, FastSnapshot, FastTier
|
|
37
|
+
import type { FastEventListener, FastSnapshot, FastTier } from './types.js';
|
|
38
38
|
export interface FastWiringDeps {
|
|
39
39
|
/** Read LIVE on every call - the controller replaces the object on mutation. */
|
|
40
40
|
getConfig: () => CliConfig;
|
|
@@ -88,7 +88,6 @@ export declare class FastWiring {
|
|
|
88
88
|
private tier;
|
|
89
89
|
/** Warned once per TRANSITION, so a broken tier does not shout every turn. */
|
|
90
90
|
private lastReportedReason;
|
|
91
|
-
private delegated;
|
|
92
91
|
constructor(deps: FastWiringDeps);
|
|
93
92
|
/**
|
|
94
93
|
* The registry the REVIEW calls through — separate from the lead's, and
|
|
@@ -120,22 +119,13 @@ export declare class FastWiring {
|
|
|
120
119
|
* §3.3's live predicate. THE THIRD TERM IS THE POINT - see the header.
|
|
121
120
|
*
|
|
122
121
|
* `FastReviewer.isSelfDisabled()` is DELIBERATELY NOT a fourth term. Folding
|
|
123
|
-
* it in would look tidier and would break something else:
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
122
|
+
* it in would look tidier and would break something else: per-child reviewers
|
|
123
|
+
* gate on `available()` too, so three consecutive REVIEW failures would
|
|
124
|
+
* silently stop every child's reviews as well - turning a diagnostic signal
|
|
125
|
+
* into a behaviour change for every dispatch. The two facts are reported
|
|
126
|
+
* separately on `FastSnapshot` instead (`live` / `selfDisabled`).
|
|
128
127
|
*/
|
|
129
128
|
available(): boolean;
|
|
130
|
-
/**
|
|
131
|
-
* Whether `model: "fast"` on `task` is honoured right now.
|
|
132
|
-
*
|
|
133
|
-
* Evaluated AT DISPATCH TIME, never snapshot (§3.4 / RV-3). `fast.delegate:
|
|
134
|
-
* false` and "the tier stopped resolving twenty minutes ago" are the same
|
|
135
|
-
* observable to the model - a downgrade, counted and reported - which is the
|
|
136
|
-
* honest reading of both.
|
|
137
|
-
*/
|
|
138
|
-
delegationAvailable(): boolean;
|
|
139
129
|
setEnabled(enabled: boolean): void;
|
|
140
130
|
/**
|
|
141
131
|
* Re-resolve the tier after ANY config mutation (§3.2 rule 8 / §3.9 / RV-3).
|
|
@@ -152,24 +142,18 @@ export declare class FastWiring {
|
|
|
152
142
|
* (§3.3). Raised once, at construction, through the controller's `notify`.
|
|
153
143
|
*/
|
|
154
144
|
startupNotice(): string | null;
|
|
145
|
+
/** The resolved fast `ModelRef`, or `null` - for cost lookups (§3.6). */
|
|
146
|
+
fastRef(): ModelRef | null;
|
|
155
147
|
/**
|
|
156
|
-
* The
|
|
148
|
+
* The fail-fast review transport, exposed so PER-CHILD reviewers share ONE
|
|
149
|
+
* registry instead of building one each - the same adapter-state reuse
|
|
150
|
+
* argument `TeamRuntime` makes about the lead's `ProviderRegistry`.
|
|
157
151
|
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* build a child against a `ModelRef` the tier no longer resolves (RV-3).
|
|
152
|
+
* Lazy: a session that never reviews allocates nothing (I-2). The retry
|
|
153
|
+
* policy is `FAST_RETRY_POLICY`, deliberately not the user's `retry` config
|
|
154
|
+
* - see `getFastRegistry()` for the reason.
|
|
162
155
|
*/
|
|
163
|
-
|
|
164
|
-
ref: ModelRef;
|
|
165
|
-
thinkingLevel: ThinkingLevel;
|
|
166
|
-
role?: ModelRole;
|
|
167
|
-
};
|
|
168
|
-
/** The resolved fast `ModelRef`, or `null` - for per-tier cost lookup (§3.6). */
|
|
169
|
-
fastRef(): ModelRef | null;
|
|
170
|
-
/** Count fast-tier children so `/fast status` can answer "is this saving me
|
|
171
|
-
* anything?" — the aggregate on the status bar cannot. */
|
|
172
|
-
noteDelegated(count: number): void;
|
|
156
|
+
completeViaFastRegistry(providerId: string, request: LLMRequest): Promise<AssistantMessage>;
|
|
173
157
|
setGoal(text: string): void;
|
|
174
158
|
abort(): void;
|
|
175
159
|
dispose(): void;
|