@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
package/dist/team/report.d.ts
CHANGED
|
@@ -23,26 +23,11 @@
|
|
|
23
23
|
import type { ModelCost } from '@aragon-agent/core';
|
|
24
24
|
import type { DispatchOutcome, SubagentRun } from './types.js';
|
|
25
25
|
export interface ReportOptions {
|
|
26
|
-
/** The lead's model cost table, so the header can state real spend (R-5).
|
|
27
|
-
cost?: ModelCost;
|
|
28
|
-
/**
|
|
29
|
-
* The FAST model's cost table (fast-model-tier §3.4 / R-7).
|
|
30
|
-
*
|
|
31
|
-
* A SECOND TABLE, not a second number derived from the first. Summing
|
|
32
|
-
* fast-tier tokens at the lead's price over-reports a Haiku child under a
|
|
33
|
-
* Sonnet lead by roughly an order of magnitude, and the whole justification
|
|
34
|
-
* for delegating to a cheaper model is the figure on this line.
|
|
35
|
-
*/
|
|
36
|
-
fastCost?: ModelCost;
|
|
37
|
-
/**
|
|
38
|
-
* The static price table has never heard of the fast model (C-11 / RV-4).
|
|
26
|
+
/** The lead's model cost table, so the header can state real spend (R-5).
|
|
39
27
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
* would make the feature look free while it is spending money.
|
|
44
|
-
*/
|
|
45
|
-
fastPricingUnknown?: boolean;
|
|
28
|
+
* THE ONE TABLE, because every child runs the lead's own model
|
|
29
|
+
* (main-agent parity): one tier, one price, one honest total. */
|
|
30
|
+
cost?: ModelCost;
|
|
46
31
|
}
|
|
47
32
|
/**
|
|
48
33
|
* Cut `text` to at most `maxBytes` WITHOUT splitting a UTF-8 sequence.
|
package/dist/team/report.js
CHANGED
|
@@ -106,28 +106,6 @@ function buildHeader(outcome, options) {
|
|
|
106
106
|
`(${counts}) in ${formatDuration(durationMs)}.`);
|
|
107
107
|
lines.push(`Tokens: in ${formatTokens(outcome.usage.inputTokens)}, out ` +
|
|
108
108
|
`${formatTokens(outcome.usage.outputTokens)}. Cost: ${formatCost(computeCost(outcome.usage, options.cost))}.`);
|
|
109
|
-
// A SECOND LINE, NOT A COMBINED TOTAL (fast-model-tier §3.4). Two tiers with
|
|
110
|
-
// two price tables have two answers, and folding them into one figure is the
|
|
111
|
-
// misattribution R-7 is about. Present only when a fast child actually ran, so
|
|
112
|
-
// an ordinary dispatch's header is byte-identical.
|
|
113
|
-
const fastUsage = outcome.fastUsage;
|
|
114
|
-
if (fastUsage) {
|
|
115
|
-
// `unknown` rather than a currency amount when the model has no price table
|
|
116
|
-
// (RV-4): a lower bound rendered as a total is the same class of lie as
|
|
117
|
-
// pricing a Haiku child at Sonnet rates.
|
|
118
|
-
const fastCostLabel = options.fastPricingUnknown
|
|
119
|
-
? 'unknown (no price table)'
|
|
120
|
-
: formatCost(computeCost(fastUsage, options.fastCost));
|
|
121
|
-
lines.push(`Fast tier: in ${formatTokens(fastUsage.inputTokens)}, out ` +
|
|
122
|
-
`${formatTokens(fastUsage.outputTokens)}. Cost: ${fastCostLabel}.`);
|
|
123
|
-
}
|
|
124
|
-
// THE LINE THAT KEEPS A DOWNGRADE FROM BEING SILENT (R-6). Without it the
|
|
125
|
-
// model asked for a cheap child, got an expensive one, and has no way to learn
|
|
126
|
-
// that its cost model is wrong.
|
|
127
|
-
if (outcome.downgraded && outcome.downgraded > 0) {
|
|
128
|
-
const n = outcome.downgraded;
|
|
129
|
-
lines.push(`${n} ${n === 1 ? 'subagent' : 'subagents'} ran on the main model (fast tier off).`);
|
|
130
|
-
}
|
|
131
109
|
for (const conflict of findFileConflicts(outcome.runs)) {
|
|
132
110
|
const who = conflict.labels.map((l) => `"${l}"`).join(' and ');
|
|
133
111
|
lines.push(`WARNING: agents ${who} both wrote ${conflict.path} - review before trusting either.`);
|
|
@@ -139,10 +117,11 @@ function buildSection(run) {
|
|
|
139
117
|
// the only place the lead learns that a child's first attempt died before it
|
|
140
118
|
// did anything (F-4).
|
|
141
119
|
const retried = run.retries ? `, retried ${run.retries}x` : '';
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
const
|
|
120
|
+
// Same head-line position as `retried Nx`, for the same reason: the ONLY
|
|
121
|
+
// place the lead learns that a supervisor looked at this child (N times) or
|
|
122
|
+
// rebuilt it (team-overseer §3.7).
|
|
123
|
+
const overseen = run.interventions ? `, overseer ${run.interventions}` : '';
|
|
124
|
+
const replaced = run.replacements ? `, replaced ${run.replacements}x` : '';
|
|
146
125
|
// `compacted N` in the same position `retried Nx` uses, and for the same
|
|
147
126
|
// reason (context-auto-compaction-hardening §3.4.4 / W3): this is the ONLY
|
|
148
127
|
// place the lead learns that a child's own history was summarized mid-task, so
|
|
@@ -150,8 +129,8 @@ function buildSection(run) {
|
|
|
150
129
|
// rather than an unexplained one. Absent when it never happened.
|
|
151
130
|
const compacted = run.compactions ? `, compacted ${run.compactions}` : '';
|
|
152
131
|
const head = [
|
|
153
|
-
`### ${run.label}
|
|
154
|
-
`${run.turns} turns, ${run.toolCalls} tools${retried}${compacted}`,
|
|
132
|
+
`### ${run.label} "${run.description}" ${statusBadge(run)} ${elapsed(run)}, ` +
|
|
133
|
+
`${run.turns} turns, ${run.toolCalls} tools${retried}${compacted}${overseen}${replaced}`,
|
|
155
134
|
];
|
|
156
135
|
if (run.filesTouched.length > 0)
|
|
157
136
|
head.push(`files: ${run.filesTouched.join(', ')}`);
|
|
@@ -163,6 +142,23 @@ function buildSection(run) {
|
|
|
163
142
|
const summary = (run.summary ?? '').trim();
|
|
164
143
|
return { head, summary: summary.length > 0 ? summary : '(no summary)' };
|
|
165
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* The supervisor's ledger (team-overseer §3.7): one line per APPLIED decision,
|
|
147
|
+
* so the lead can see who was nudged or replaced, when, and why. Budgeted by
|
|
148
|
+
* the same `reportMaxBytes` ladder as everything else - it renders as a block,
|
|
149
|
+
* so trimming it means trimming the blocks, which the ladder already does.
|
|
150
|
+
*/
|
|
151
|
+
function buildOverseer(outcome) {
|
|
152
|
+
const list = outcome.interventions ?? [];
|
|
153
|
+
if (list.length === 0)
|
|
154
|
+
return [];
|
|
155
|
+
const lines = ['### Supervisor'];
|
|
156
|
+
for (const item of list) {
|
|
157
|
+
const at = Math.max(0, Math.round((item.at - outcome.startedAt) / 1000));
|
|
158
|
+
lines.push(`[${item.trigger} ${at}s] ${item.label}: ${item.action} - ${item.reason}`);
|
|
159
|
+
}
|
|
160
|
+
return lines;
|
|
161
|
+
}
|
|
166
162
|
function buildLeadMail(outcome) {
|
|
167
163
|
if (outcome.leadMail.length === 0)
|
|
168
164
|
return [];
|
|
@@ -188,6 +184,7 @@ export function buildDispatchReport(outcome, options = {}) {
|
|
|
188
184
|
const header = buildHeader(outcome, options);
|
|
189
185
|
const sections = outcome.runs.map(buildSection);
|
|
190
186
|
const mail = buildLeadMail(outcome);
|
|
187
|
+
const overseer = buildOverseer(outcome);
|
|
191
188
|
const summaries = sections.map((s) => truncateBytes(s.summary, TEAM_LIMITS.summaryMaxBytes));
|
|
192
189
|
const trimmed = summaries.map((s, i) => s.length < sections[i].summary.length);
|
|
193
190
|
const render = (bodies) => {
|
|
@@ -200,6 +197,8 @@ export function buildDispatchReport(outcome, options = {}) {
|
|
|
200
197
|
}
|
|
201
198
|
blocks.push(lines.join('\n'));
|
|
202
199
|
});
|
|
200
|
+
if (overseer.length > 0)
|
|
201
|
+
blocks.push(overseer.join('\n'));
|
|
203
202
|
if (mail.length > 0)
|
|
204
203
|
blocks.push(mail.join('\n'));
|
|
205
204
|
return blocks.join('\n\n');
|
package/dist/team/runtime.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TeamRuntime — dispatch scheduling, budgets, the `TeamEvent` stream, abort and
|
|
3
|
-
* disposal (team-subagents §3.2 / §3.5 / §3.8).
|
|
3
|
+
* disposal (team-subagents §3.2 / §3.5 / §3.8; team-overseer §3.4).
|
|
4
4
|
*
|
|
5
5
|
* ASCII ONLY: `src/team/**` is inside the glyph scanner's scope.
|
|
6
6
|
*
|
|
@@ -16,6 +16,16 @@
|
|
|
16
16
|
* worker loops, awaited with `Promise.allSettled`. No worker abstraction, no
|
|
17
17
|
* queue class, no event-loop trickery — every path is observable from the event
|
|
18
18
|
* stream.
|
|
19
|
+
*
|
|
20
|
+
* THE DISPATCH SUPERVISOR (team-overseer) — a time ceiling is an inspection
|
|
21
|
+
* trigger, not a death sentence. When a supervisor is live for the dispatch,
|
|
22
|
+
* two SOFT timers per child (wall clock and event silence) fire an inspection;
|
|
23
|
+
* the supervisor decides wait / nudge / replace / abandon; THIS module applies.
|
|
24
|
+
* Lifecycle changes are funnelled exclusively through `runOne`, the only place
|
|
25
|
+
* a child's `prompt()` is awaited (I-OV1): the supervisor may steer, flag and
|
|
26
|
+
* abort, but a replacement is built by the worker loop or it is built for
|
|
27
|
+
* nobody. Without a supervisor, every path below is byte for byte the
|
|
28
|
+
* pre-feature behaviour.
|
|
19
29
|
*/
|
|
20
30
|
import type { ModelRole } from '../config/model-profiles.js';
|
|
21
31
|
import type { ProviderRegistry, SkillRegistry, ToolPolicyDecision, ToolPolicyVerdict } from '@aragon-agent/core';
|
|
@@ -23,6 +33,7 @@ import type { AgentMode } from '../agent/agent-mode.js';
|
|
|
23
33
|
import type { CliConfig } from '../config/schema.js';
|
|
24
34
|
import type { ToolPermission } from '../exec/permission.js';
|
|
25
35
|
import type { TeamHumanQueue } from './human-queue.js';
|
|
36
|
+
import { type OverseerProvider } from './overseer.js';
|
|
26
37
|
import { type SubagentAgentFactory, type SubagentDeps } from './subagent.js';
|
|
27
38
|
import type { DispatchOutcome, SubagentSpec, TeamEventListener, TeamSnapshot } from './types.js';
|
|
28
39
|
export interface TeamRuntimeDeps {
|
|
@@ -56,21 +67,28 @@ export interface TeamRuntimeDeps {
|
|
|
56
67
|
/** Test seam (§8.1): a stub factory keeps the whole scheduler off the network. */
|
|
57
68
|
agentFactory?: SubagentAgentFactory;
|
|
58
69
|
/**
|
|
59
|
-
* Per-
|
|
60
|
-
* `SubagentDeps
|
|
61
|
-
*
|
|
70
|
+
* Per-child fast review (main-agent parity), passed straight through to
|
|
71
|
+
* `SubagentDeps`. ABSENT means the session has no fast wiring and children
|
|
72
|
+
* are built exactly as they were before the reviewers existed.
|
|
62
73
|
*/
|
|
63
|
-
|
|
74
|
+
review?: SubagentDeps['review'];
|
|
64
75
|
/**
|
|
65
76
|
* Per-child context compaction (context-auto-compaction-hardening §3.4 / W3).
|
|
66
77
|
*
|
|
67
78
|
* Passed straight through to `SubagentDeps`; absent means children get none,
|
|
68
79
|
* which is the pre-hardening behaviour exactly. `AgentController` supplies it
|
|
69
80
|
* from `CompactionWiring.childFactory()`, and the closure returns `undefined`
|
|
70
|
-
* when compaction is unregistered or `compaction.subagents` is false - which
|
|
71
|
-
* what lets `subagent.ts` spread nothing at all.
|
|
81
|
+
* when compaction is unregistered or `compaction.subagents` is false - which
|
|
82
|
+
* is what lets `subagent.ts` spread nothing at all.
|
|
72
83
|
*/
|
|
73
84
|
contextManagerFor?: SubagentDeps['contextManagerFor'];
|
|
85
|
+
/**
|
|
86
|
+
* The dispatch supervisor (team-overseer). ABSENT means the session has no
|
|
87
|
+
* supervision, and every path below is the pre-feature behaviour exactly.
|
|
88
|
+
* `active()` is read once per dispatch AND once per inspection (inside
|
|
89
|
+
* `TeamOverseer`), so a mid-dispatch `/fast off` stops the next look.
|
|
90
|
+
*/
|
|
91
|
+
overseer?: OverseerProvider;
|
|
74
92
|
}
|
|
75
93
|
export declare class TeamRuntime {
|
|
76
94
|
private readonly deps;
|
|
@@ -94,6 +112,16 @@ export declare class TeamRuntime {
|
|
|
94
112
|
* quietly not for the others.
|
|
95
113
|
*/
|
|
96
114
|
private readonly pendingBackoffs;
|
|
115
|
+
/**
|
|
116
|
+
* The dispatch supervisor, LIVE for the current dispatch only (team-overseer).
|
|
117
|
+
* Null when the provider is absent/disabled/off, and reset to null at every
|
|
118
|
+
* dispatch end so nothing supervision-shaped leaks across dispatches.
|
|
119
|
+
*/
|
|
120
|
+
private overseer;
|
|
121
|
+
/** The soft timers, same lifetime as `overseer`. */
|
|
122
|
+
private supervision;
|
|
123
|
+
/** Applied interventions for the in-flight dispatch's outcome. */
|
|
124
|
+
private interventions;
|
|
97
125
|
constructor(deps: TeamRuntimeDeps);
|
|
98
126
|
subscribe(listener: TeamEventListener): () => void;
|
|
99
127
|
/**
|
|
@@ -104,28 +132,60 @@ export declare class TeamRuntime {
|
|
|
104
132
|
isBusy(): boolean;
|
|
105
133
|
/** The live roster, for `/team` status. `null` when nothing is dispatching. */
|
|
106
134
|
snapshot(): TeamSnapshot | null;
|
|
107
|
-
dispatch(specs: SubagentSpec[], requested: number, signal?: AbortSignal
|
|
108
|
-
/** Carried through from the normalizer so the report can state it (§3.4 /
|
|
109
|
-
* R-6). Optional, so every existing caller compiles unchanged. */
|
|
110
|
-
extra?: {
|
|
111
|
-
downgraded?: number;
|
|
112
|
-
}): Promise<DispatchOutcome>;
|
|
135
|
+
dispatch(specs: SubagentSpec[], requested: number, signal?: AbortSignal): Promise<DispatchOutcome>;
|
|
113
136
|
/** One slot of the pool: take the next index until the list is exhausted. */
|
|
114
137
|
private worker;
|
|
115
138
|
/**
|
|
116
139
|
* Run one child to a terminal phase, replacing it once if its very first
|
|
117
|
-
* request died on a transport error before it did anything at all (F-4)
|
|
140
|
+
* request died on a transport error before it did anything at all (F-4), and
|
|
141
|
+
* replacing it when the SUPERVISOR decides to (team-overseer §3.4).
|
|
142
|
+
*
|
|
143
|
+
* ONE LOOP, ALL LIFECYCLE: the cold-start replacement, the supervisor's
|
|
144
|
+
* replace and the post-mortem replace all swap `handles[index]` and continue
|
|
145
|
+
* THIS loop, because the await below is the only place a child is driven and
|
|
146
|
+
* a handle swapped anywhere else would never be (I-OV1).
|
|
118
147
|
*/
|
|
119
148
|
private runOne;
|
|
120
149
|
/**
|
|
121
|
-
*
|
|
150
|
+
* One post-mortem inspection, and possibly ONE replacement driven by a
|
|
151
|
+
* recursive `runOne` — the worker that called us has already moved on to the
|
|
152
|
+
* next index, so nobody else will drive the fresh child (I-OV1 holds here
|
|
153
|
+
* too, one frame deeper). Recursion depth is bounded by the replacement
|
|
154
|
+
* budget, which is 1.
|
|
155
|
+
*/
|
|
156
|
+
private maybePostMortem;
|
|
157
|
+
/**
|
|
158
|
+
* Swap one child for a fresh one, carrying only what must survive.
|
|
122
159
|
*
|
|
123
160
|
* `this.live` IS `handles`, so the single assignment below also makes
|
|
124
161
|
* `abortAll()` abort the NEW child and makes the outcome carry the new run.
|
|
125
162
|
* Anyone tempted to "clean up" that aliasing into a defensive copy must update
|
|
126
163
|
* both places.
|
|
164
|
+
*
|
|
165
|
+
* `verdict === null` is the COLD-START retry (F-4): identical spec, `retries`
|
|
166
|
+
* carried. A verdict is the SUPERVISOR's replace: an amended brief
|
|
167
|
+
* (`buildReplacementPrompt`), `replacements` carried, and the supervisor's
|
|
168
|
+
* budget spent HERE, at the moment the rebuild is real.
|
|
169
|
+
*/
|
|
170
|
+
private replaceChild;
|
|
171
|
+
/**
|
|
172
|
+
* Whether a child's silence is a legitimate wait rather than a stall:
|
|
173
|
+
* `team_wait` (the comm tool already pauses the child's own watchdog for
|
|
174
|
+
* exactly this wait) or a confirmation queued on the one human slot.
|
|
175
|
+
*/
|
|
176
|
+
private isBlocked;
|
|
177
|
+
/**
|
|
178
|
+
* One trigger handled: look, then apply. Fired from a supervision timer and
|
|
179
|
+
* therefore async-and-forgotten; nothing here may throw.
|
|
180
|
+
*
|
|
181
|
+
* QUIET (`decision === null` — provider gone, budget spent) CLEARS the
|
|
182
|
+
* child's timers: supervision that has nothing left to say should stop
|
|
183
|
+
* waking up, and the child's own hard ceilings take over.
|
|
127
184
|
*/
|
|
128
|
-
private
|
|
185
|
+
private inspectAndApply;
|
|
186
|
+
private applyDecision;
|
|
187
|
+
/** Record one applied decision on the outcome, the run and the event stream. */
|
|
188
|
+
private recordIntervention;
|
|
129
189
|
/**
|
|
130
190
|
* The final phase of an attempt, in a FIXED ORDER: aborted, then timed out,
|
|
131
191
|
* then error, then no-summary, then done.
|