@aragon-agent/cli 0.6.2 → 0.6.4
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 +321 -0
- package/README.md +297 -2
- package/dist/agent/controller.d.ts +193 -1
- package/dist/agent/controller.js +475 -2
- package/dist/agent/headless.d.ts +8 -0
- package/dist/agent/headless.js +47 -0
- package/dist/agent/reducer.d.ts +189 -0
- package/dist/agent/reducer.js +301 -2
- package/dist/agent/system-prompt.d.ts +14 -0
- package/dist/agent/system-prompt.js +2 -0
- package/dist/cli.js +297 -16
- package/dist/commands/builtins.js +165 -24
- package/dist/commands/registry.d.ts +27 -0
- package/dist/compaction/archive.d.ts +175 -0
- package/dist/compaction/archive.js +267 -0
- package/dist/compaction/child.d.ts +97 -0
- package/dist/compaction/child.js +118 -0
- package/dist/compaction/command.d.ts +41 -0
- package/dist/compaction/command.js +355 -0
- package/dist/compaction/compactor.d.ts +302 -0
- package/dist/compaction/compactor.js +810 -0
- package/dist/compaction/digest.d.ts +62 -0
- package/dist/compaction/digest.js +164 -0
- package/dist/compaction/limits.d.ts +165 -0
- package/dist/compaction/limits.js +172 -0
- package/dist/compaction/pressure.d.ts +135 -0
- package/dist/compaction/pressure.js +167 -0
- package/dist/compaction/summarize-call.d.ts +70 -0
- package/dist/compaction/summarize-call.js +86 -0
- package/dist/compaction/summary-prompt.d.ts +85 -0
- package/dist/compaction/summary-prompt.js +197 -0
- package/dist/compaction/tail-budget.d.ts +52 -0
- package/dist/compaction/tail-budget.js +67 -0
- package/dist/compaction/types.d.ts +215 -0
- package/dist/compaction/types.js +22 -0
- package/dist/compaction/wiring.d.ts +264 -0
- package/dist/compaction/wiring.js +577 -0
- package/dist/config/app-paths.d.ts +14 -0
- package/dist/config/app-paths.js +16 -0
- package/dist/config/cli-commands.d.ts +41 -0
- package/dist/config/cli-commands.js +77 -1
- package/dist/config/env.d.ts +5 -2
- package/dist/config/env.js +140 -3
- package/dist/config/load.d.ts +42 -0
- package/dist/config/load.js +101 -1
- package/dist/config/schema.d.ts +244 -0
- package/dist/config/schema.js +170 -0
- package/dist/config/store.js +37 -1
- package/dist/config/ui-state.d.ts +28 -1
- package/dist/config/ui-state.js +9 -0
- package/dist/exec/events.d.ts +50 -1
- package/dist/exec/runner.js +42 -0
- package/dist/input/limits.d.ts +72 -0
- package/dist/input/limits.js +63 -0
- package/dist/input/mouse-events.d.ts +31 -5
- package/dist/input/mouse-events.js +86 -27
- package/dist/input/paste-parse.d.ts +71 -0
- package/dist/input/paste-parse.js +95 -0
- package/dist/input/stdin-filter.d.ts +81 -0
- package/dist/input/stdin-filter.js +379 -0
- package/dist/logging/install.d.ts +53 -1
- package/dist/logging/install.js +81 -1
- package/dist/logging/logger.d.ts +1 -1
- package/dist/proc/classify.d.ts +52 -0
- package/dist/proc/classify.js +143 -0
- package/dist/proc/kill-tree.d.ts +42 -0
- package/dist/proc/kill-tree.js +119 -0
- package/dist/proc/limits.d.ts +84 -0
- package/dist/proc/limits.js +84 -0
- package/dist/proc/log-ring.d.ts +68 -0
- package/dist/proc/log-ring.js +102 -0
- package/dist/proc/prompt.d.ts +24 -0
- package/dist/proc/prompt.js +49 -0
- package/dist/proc/readiness.d.ts +102 -0
- package/dist/proc/readiness.js +219 -0
- package/dist/proc/supervisor.d.ts +103 -0
- package/dist/proc/supervisor.js +465 -0
- package/dist/proc/types.d.ts +175 -0
- package/dist/proc/types.js +15 -0
- package/dist/session/persist.js +55 -1
- package/dist/team/report.js +7 -1
- package/dist/team/runtime.d.ts +10 -0
- package/dist/team/runtime.js +7 -0
- package/dist/team/subagent.d.ts +31 -1
- package/dist/team/subagent.js +42 -15
- package/dist/team/types.d.ts +8 -0
- package/dist/tools/bash-tool.d.ts +51 -2
- package/dist/tools/bash-tool.js +321 -51
- package/dist/tools/fs-tools.d.ts +17 -0
- package/dist/tools/index.d.ts +55 -2
- package/dist/tools/index.js +39 -1
- package/dist/tools/proc-tools.d.ts +25 -0
- package/dist/tools/proc-tools.js +102 -0
- package/dist/ui/ActivityLine.d.ts +19 -1
- package/dist/ui/ActivityLine.js +10 -2
- package/dist/ui/App.d.ts +62 -2
- package/dist/ui/App.js +546 -16
- package/dist/ui/Composer.d.ts +66 -1
- package/dist/ui/Composer.js +50 -6
- package/dist/ui/PromptInput.d.ts +82 -3
- package/dist/ui/PromptInput.js +232 -49
- package/dist/ui/StatusBar.d.ts +59 -0
- package/dist/ui/StatusBar.js +16 -4
- package/dist/ui/TeamPanel.js +7 -1
- package/dist/ui/Transcript.d.ts +21 -1
- package/dist/ui/Transcript.js +61 -3
- package/dist/ui/clipboard.d.ts +52 -0
- package/dist/ui/clipboard.js +91 -0
- package/dist/ui/composer-limits.d.ts +31 -0
- package/dist/ui/composer-limits.js +50 -0
- package/dist/ui/composer-rows.d.ts +73 -0
- package/dist/ui/composer-rows.js +201 -0
- package/dist/ui/editor-reducer.d.ts +37 -0
- package/dist/ui/editor-reducer.js +88 -12
- package/dist/ui/entries/CompactionCard.d.ts +75 -0
- package/dist/ui/entries/CompactionCard.js +158 -0
- package/dist/ui/entries/ServiceCard.d.ts +66 -0
- package/dist/ui/entries/ServiceCard.js +116 -0
- package/dist/ui/entries/UserEntry.d.ts +17 -3
- package/dist/ui/entries/UserEntry.js +34 -5
- package/dist/ui/frame-differ.d.ts +46 -0
- package/dist/ui/frame-differ.js +94 -10
- package/dist/ui/gauge.d.ts +16 -1
- package/dist/ui/gauge.js +25 -6
- package/dist/ui/glyphs.d.ts +11 -0
- package/dist/ui/glyphs.js +2 -0
- package/dist/ui/layout/ScrollViewport.d.ts +43 -6
- package/dist/ui/layout/ScrollViewport.js +128 -21
- package/dist/ui/layout/budget.d.ts +44 -9
- package/dist/ui/layout/budget.js +42 -10
- package/dist/ui/layout/follow-state.d.ts +137 -0
- package/dist/ui/layout/follow-state.js +150 -0
- package/dist/ui/layout/virtual-window.d.ts +11 -0
- package/dist/ui/layout/virtual-window.js +85 -1
- package/dist/ui/overlays/HelpOverlay.js +9 -1
- package/dist/ui/overlays/PlanReviewOverlay.js +10 -2
- package/dist/ui/overlays/QuestionOverlay.js +5 -1
- package/dist/ui/overlays/SettingsScreen.d.ts +47 -1
- package/dist/ui/overlays/SettingsScreen.js +74 -2
- package/dist/ui/palettes.d.ts +16 -0
- package/dist/ui/palettes.js +6 -0
- package/dist/ui/paste-frames.d.ts +87 -0
- package/dist/ui/paste-frames.js +112 -0
- package/dist/ui/paste-tokens.d.ts +90 -0
- package/dist/ui/paste-tokens.js +147 -0
- package/dist/ui/screen.d.ts +38 -0
- package/dist/ui/screen.js +113 -8
- package/dist/ui/selection/highlight.d.ts +39 -0
- package/dist/ui/selection/highlight.js +64 -0
- package/dist/ui/selection/screen-mirror.d.ts +24 -0
- package/dist/ui/selection/screen-mirror.js +35 -0
- package/dist/ui/selection/selection-controller.d.ts +88 -0
- package/dist/ui/selection/selection-controller.js +282 -0
- package/dist/ui/selection/selection.d.ts +90 -0
- package/dist/ui/selection/selection.js +223 -0
- package/dist/ui/stdout-frame-writer.d.ts +33 -0
- package/dist/ui/stdout-frame-writer.js +15 -0
- package/dist/ui/theme.d.ts +11 -0
- package/dist/ui/theme.js +2 -0
- package/dist/ui/transcript-text.js +72 -0
- package/dist/ui/use-startup-notices.d.ts +27 -1
- package/dist/ui/use-startup-notices.js +43 -11
- package/dist/ui/use-wheel-routing.d.ts +1 -1
- package/dist/ui/use-wheel-routing.js +8 -0
- package/package.json +4 -2
- package/dist/input/stdin-mouse-filter.d.ts +0 -42
- package/dist/input/stdin-mouse-filter.js +0 -153
package/dist/session/persist.js
CHANGED
|
@@ -59,6 +59,24 @@ function stripLiveToolOutput(entries) {
|
|
|
59
59
|
? { ...e, live: undefined, liveSeq: undefined, lastOutputAt: undefined }
|
|
60
60
|
: e);
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Drop the service tail on the way to disk, beside `stripLiveToolOutput` and for
|
|
64
|
+
* the same three reasons (background-service-supervision §6).
|
|
65
|
+
*
|
|
66
|
+
* A resumed card's tail describes a PROCESS THAT NO LONGER EXISTS - it died with
|
|
67
|
+
* the session, because nothing in this package outlives the CLI by design. The
|
|
68
|
+
* tail is also the only unbounded field a service entry carries, and dropping it
|
|
69
|
+
* keeps a saved session's size a function of how many services ran rather than
|
|
70
|
+
* of how chatty they were.
|
|
71
|
+
*
|
|
72
|
+
* `rowsSeen` IS KEPT. It is the revision cursor, not display data, and a
|
|
73
|
+
* restored card that reported 0 rows seen while `normalizeLoadedEntries` was
|
|
74
|
+
* flipping its status would produce a revision collision with a live card that
|
|
75
|
+
* genuinely has none.
|
|
76
|
+
*/
|
|
77
|
+
function stripServiceTail(entries) {
|
|
78
|
+
return entries.map((e) => (e.kind === 'service' && e.rows.length > 0 ? { ...e, rows: [] } : e));
|
|
79
|
+
}
|
|
62
80
|
/**
|
|
63
81
|
* `data` GAINS `todos`, AND WIDENING `SavedSession` ALONE IS NOT ENOUGH (P0-2):
|
|
64
82
|
* the writer below builds its payload from THIS parameter, not from the type, so
|
|
@@ -81,7 +99,7 @@ export function saveSession(filePath, data) {
|
|
|
81
99
|
savedAt: Date.now(),
|
|
82
100
|
model: data.model,
|
|
83
101
|
messages: data.messages,
|
|
84
|
-
entries: stripLiveToolOutput(data.entries),
|
|
102
|
+
entries: stripServiceTail(stripLiveToolOutput(data.entries)),
|
|
85
103
|
todos: data.todos,
|
|
86
104
|
...(data.meta ? { meta: data.meta } : {}),
|
|
87
105
|
};
|
|
@@ -139,6 +157,42 @@ export function normalizeLoadedEntries(entries) {
|
|
|
139
157
|
detail: 'interrupted (session resumed)',
|
|
140
158
|
};
|
|
141
159
|
}
|
|
160
|
+
// THE FIFTH CLAUSE (context-auto-compaction §5.5 / C-8 / AC-19). A compaction
|
|
161
|
+
// card saved while its summarization was open resumes claiming to be running
|
|
162
|
+
// while nothing is, and — the part that actually costs — it never settles, so
|
|
163
|
+
// `Transcript`'s MONOTONIC boundary never advances past it and every frame for
|
|
164
|
+
// the rest of the session re-renders the whole tail.
|
|
165
|
+
//
|
|
166
|
+
// `applied: false` is also simply TRUE: whatever the call was going to
|
|
167
|
+
// return died with the process, and the history on disk is the PRE-compaction
|
|
168
|
+
// one. A card that claimed otherwise would tell the user their session had
|
|
169
|
+
// been compacted when it had not.
|
|
170
|
+
if (entry.kind === 'compaction' && entry.live) {
|
|
171
|
+
return {
|
|
172
|
+
...entry,
|
|
173
|
+
live: false,
|
|
174
|
+
applied: false,
|
|
175
|
+
mode: 'none',
|
|
176
|
+
reason: 'interrupted (session resumed)',
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// THE SIXTH CLAUSE (background-service-supervision §6 / R-7). A card saved
|
|
180
|
+
// while its service was up resumes claiming to be running while nothing is -
|
|
181
|
+
// the process died with the session, because nothing here outlives the CLI.
|
|
182
|
+
//
|
|
183
|
+
// AND `starting` IS THE ONE THAT ACTUALLY COSTS: it is the single service
|
|
184
|
+
// status that blocks `Transcript`'s MONOTONIC settled boundary (D-11), so a
|
|
185
|
+
// restored `starting` card would never settle and every frame for the rest of
|
|
186
|
+
// the session would re-render the whole tail. `ready` / `running` would
|
|
187
|
+
// "only" be a lie; this one is a lie that gets slower.
|
|
188
|
+
//
|
|
189
|
+
// `stopped` rather than `exited`: we did not observe an exit code, and
|
|
190
|
+
// claiming one would be inventing a number. The terminal record the session
|
|
191
|
+
// may also carry is already terminal and is left alone.
|
|
192
|
+
if (entry.kind === 'service' &&
|
|
193
|
+
(entry.status === 'starting' || entry.status === 'ready' || entry.status === 'running')) {
|
|
194
|
+
return { ...entry, status: 'stopped', rows: [] };
|
|
195
|
+
}
|
|
142
196
|
return entry;
|
|
143
197
|
});
|
|
144
198
|
}
|
package/dist/team/report.js
CHANGED
|
@@ -143,9 +143,15 @@ function buildSection(run) {
|
|
|
143
143
|
// bytes, and it is the only place the lead learns which of its children were
|
|
144
144
|
// cheap — the fact the whole second cost line is about.
|
|
145
145
|
const tier = run.tier === 'fast' ? ' [fast]' : '';
|
|
146
|
+
// `compacted N` in the same position `retried Nx` uses, and for the same
|
|
147
|
+
// reason (context-auto-compaction-hardening §3.4.4 / W3): this is the ONLY
|
|
148
|
+
// place the lead learns that a child's own history was summarized mid-task, so
|
|
149
|
+
// a summary that reads thinner than the turn count suggests has a stated cause
|
|
150
|
+
// rather than an unexplained one. Absent when it never happened.
|
|
151
|
+
const compacted = run.compactions ? `, compacted ${run.compactions}` : '';
|
|
146
152
|
const head = [
|
|
147
153
|
`### ${run.label}${tier} "${run.description}" ${statusBadge(run)} ${elapsed(run)}, ` +
|
|
148
|
-
`${run.turns} turns, ${run.toolCalls} tools${retried}`,
|
|
154
|
+
`${run.turns} turns, ${run.toolCalls} tools${retried}${compacted}`,
|
|
149
155
|
];
|
|
150
156
|
if (run.filesTouched.length > 0)
|
|
151
157
|
head.push(`files: ${run.filesTouched.join(', ')}`);
|
package/dist/team/runtime.d.ts
CHANGED
|
@@ -60,6 +60,16 @@ export interface TeamRuntimeDeps {
|
|
|
60
60
|
* is the pre-feature behaviour.
|
|
61
61
|
*/
|
|
62
62
|
resolveTier?: SubagentDeps['resolveTier'];
|
|
63
|
+
/**
|
|
64
|
+
* Per-child context compaction (context-auto-compaction-hardening §3.4 / W3).
|
|
65
|
+
*
|
|
66
|
+
* Passed straight through to `SubagentDeps`; absent means children get none,
|
|
67
|
+
* which is the pre-hardening behaviour exactly. `AgentController` supplies it
|
|
68
|
+
* from `CompactionWiring.childFactory()`, and the closure returns `undefined`
|
|
69
|
+
* when compaction is unregistered or `compaction.subagents` is false - which is
|
|
70
|
+
* what lets `subagent.ts` spread nothing at all.
|
|
71
|
+
*/
|
|
72
|
+
contextManagerFor?: SubagentDeps['contextManagerFor'];
|
|
63
73
|
}
|
|
64
74
|
export declare class TeamRuntime {
|
|
65
75
|
private readonly deps;
|
package/dist/team/runtime.js
CHANGED
|
@@ -132,6 +132,13 @@ export class TeamRuntime {
|
|
|
132
132
|
...(this.deps.humanQueue ? { humanQueue: this.deps.humanQueue } : {}),
|
|
133
133
|
agentFactory: this.deps.agentFactory ?? defaultSubagentFactory,
|
|
134
134
|
...(this.deps.resolveTier ? { resolveTier: this.deps.resolveTier } : {}),
|
|
135
|
+
// Site two of two, and the omission is silent in the same way the policy
|
|
136
|
+
// one above is: declaring it on `TeamRuntimeDeps` and forgetting this line
|
|
137
|
+
// type-checks and forwards nothing, so every child would quietly run with
|
|
138
|
+
// no compaction while the config key says it has one.
|
|
139
|
+
...(this.deps.contextManagerFor
|
|
140
|
+
? { contextManagerFor: this.deps.contextManagerFor }
|
|
141
|
+
: {}),
|
|
135
142
|
};
|
|
136
143
|
// Hoisted into a factory so a retry can build a fresh child with IDENTICAL
|
|
137
144
|
// wiring (F-4). Replacing the child rather than re-prompting it is the only
|
package/dist/team/subagent.d.ts
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* them (§3.11 / R-6). What a child does NOT get is spelled out below, and each
|
|
11
11
|
* omission has a reason that is a correctness boundary rather than caution.
|
|
12
12
|
*/
|
|
13
|
-
import { type AgentConfig, type AgentEvent, type AgentTool, type ModelRef, type ProviderRegistry, type SkillRegistry, type ThinkingLevel, type TokenUsage, type ToolPolicyDecision, type ToolPolicyVerdict } from '@aragon-agent/core';
|
|
13
|
+
import { type AgentConfig, type AgentEvent, type AgentTool, type Message, type ModelRef, type ProviderRegistry, type SkillRegistry, type ThinkingLevel, type TokenUsage, type ToolPolicyDecision, type ToolPolicyVerdict } from '@aragon-agent/core';
|
|
14
14
|
import type { AgentMode } from '../agent/agent-mode.js';
|
|
15
|
+
import type { ChildContextManagerProvider } from '../compaction/child.js';
|
|
15
16
|
import type { CliConfig } from '../config/schema.js';
|
|
16
17
|
import type { ToolPermission } from '../exec/permission.js';
|
|
17
18
|
import type { FastTierName } from '../fast/types.js';
|
|
@@ -29,6 +30,24 @@ export interface SubagentAgentLike extends WatchdogPausable {
|
|
|
29
30
|
prompt(text: string): Promise<void>;
|
|
30
31
|
abort(): void;
|
|
31
32
|
subscribe(listener: (event: AgentEvent) => void): () => void;
|
|
33
|
+
/**
|
|
34
|
+
* The child's live history, for its own context manager
|
|
35
|
+
* (context-auto-compaction-hardening §3.4.3 / W3).
|
|
36
|
+
*
|
|
37
|
+
* NARROWED ON PURPOSE. `Agent` satisfies this with its full `AgentState`
|
|
38
|
+
* getter and a stub satisfies it with `{ messages: [] }`. Widening it to
|
|
39
|
+
* `AgentState` would make every test stub fabricate a systemPrompt, a model and
|
|
40
|
+
* a phase to compile, for fields none of them use.
|
|
41
|
+
*
|
|
42
|
+
* A PROPERTY READ, NOT A METHOD CALL, AND THAT IS NOT A STYLE CHOICE: core's
|
|
43
|
+
* `Agent` has NO `getMessages()`. It exposes `get state(): AgentState`;
|
|
44
|
+
* `AgentController.getMessages()` is the CONTROLLER's own one-line forwarder
|
|
45
|
+
* over `this.agent.state.messages`. Adding a method to the engine to serve a
|
|
46
|
+
* host-side convenience would move the core export surface for nothing.
|
|
47
|
+
*/
|
|
48
|
+
readonly state: {
|
|
49
|
+
readonly messages: readonly Message[];
|
|
50
|
+
};
|
|
32
51
|
}
|
|
33
52
|
export type SubagentAgentFactory = (config: AgentConfig) => SubagentAgentLike;
|
|
34
53
|
/** The default factory: a real `Agent` from `@aragon-agent/core`. */
|
|
@@ -91,6 +110,17 @@ export interface SubagentDeps {
|
|
|
91
110
|
ref: ModelRef;
|
|
92
111
|
thinkingLevel: ThinkingLevel;
|
|
93
112
|
};
|
|
113
|
+
/**
|
|
114
|
+
* Build this child its own context manager
|
|
115
|
+
* (context-auto-compaction-hardening §3.4.3 / W3).
|
|
116
|
+
*
|
|
117
|
+
* ABSENT means children get none, and `subagent.ts` then spreads NO
|
|
118
|
+
* `contextManager` key at all - so the child's loop gate tests a genuinely
|
|
119
|
+
* undefined field and a `compaction.subagents: false` session is byte-identical
|
|
120
|
+
* to round 1 (AC-H10). `AgentController` supplies it from
|
|
121
|
+
* `CompactionWiring.childFactory()`, which returns `null` when the key is off.
|
|
122
|
+
*/
|
|
123
|
+
contextManagerFor?: ChildContextManagerProvider;
|
|
94
124
|
}
|
|
95
125
|
export interface SubagentHooks {
|
|
96
126
|
/** Coalesced at the source (§5.2); phase transitions always pass. */
|
package/dist/team/subagent.js
CHANGED
|
@@ -183,22 +183,40 @@ export function createSubagent(spec, deps, hooks) {
|
|
|
183
183
|
thinkingLevel: deps.config.thinkingLevel,
|
|
184
184
|
};
|
|
185
185
|
const model = resolved.ref;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
186
|
+
// HOISTED TO A LOCAL, AND THAT IS WHAT MAKES W3 POSSIBLE AT ALL. This was built
|
|
187
|
+
// INLINE inside the `agentFactory({...})` argument, so there was nothing for the
|
|
188
|
+
// child manager's `getSystemPrompt` accessor to close over - and the accessor
|
|
189
|
+
// cannot read it back off the agent, because `SubagentAgentLike` is narrowed to
|
|
190
|
+
// `state.messages` on purpose.
|
|
191
|
+
const systemPrompt = buildSystemPrompt({
|
|
192
|
+
cwd: deps.getCwd(),
|
|
193
|
+
tools,
|
|
194
|
+
skillsBlock: deps.alwaysBlock ?? '',
|
|
195
|
+
agentMode: spec.readOnly ? 'plan' : deps.getMode(),
|
|
196
|
+
// A child has no overlay, so the plan block must describe the headless
|
|
197
|
+
// shape: write the plan as the final message rather than calling tools it
|
|
198
|
+
// does not have.
|
|
199
|
+
planInteractive: false,
|
|
200
|
+
subagentBlock: buildSubagentBlock({
|
|
201
|
+
label: spec.label,
|
|
202
|
+
description: spec.description,
|
|
203
|
+
peers: deps.bus.peersOf(spec.label),
|
|
201
204
|
}),
|
|
205
|
+
});
|
|
206
|
+
// LAZY ACCESSORS OVER `agentRef`, WHICH IS ASSIGNED AFTER THIS RETURNS. A
|
|
207
|
+
// non-lazy read here is `undefined` at construction and the child's estimate
|
|
208
|
+
// branch would silently measure an empty history - CR-1 one module over.
|
|
209
|
+
const contextManager = deps.contextManagerFor?.({
|
|
210
|
+
label: spec.label,
|
|
211
|
+
model,
|
|
212
|
+
getMessages: () => agentRef?.state.messages ?? [],
|
|
213
|
+
getSystemPrompt: () => systemPrompt,
|
|
214
|
+
onCompacted: () => {
|
|
215
|
+
run.compactions = (run.compactions ?? 0) + 1;
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
const agent = deps.agentFactory({
|
|
219
|
+
systemPrompt,
|
|
202
220
|
model,
|
|
203
221
|
tools,
|
|
204
222
|
thinkingLevel: resolved.thinkingLevel,
|
|
@@ -217,6 +235,11 @@ export function createSubagent(spec, deps, hooks) {
|
|
|
217
235
|
// explicitly.
|
|
218
236
|
idleTimeout: deps.config.idleTimeoutMs,
|
|
219
237
|
},
|
|
238
|
+
// SPREAD CONDITIONALLY, never `contextManager: deps.contextManagerFor?.(...)`.
|
|
239
|
+
// With the feature off the options bag has no such key, so the loop's gate
|
|
240
|
+
// tests a field that is genuinely `undefined` rather than a property holding
|
|
241
|
+
// one - the identical argument `AgentController` makes for the lead (AC-H10).
|
|
242
|
+
...(contextManager ? { contextManager } : {}),
|
|
220
243
|
});
|
|
221
244
|
agentRef = agent;
|
|
222
245
|
let lastEmit = 0;
|
|
@@ -289,6 +312,10 @@ export function createSubagent(spec, deps, hooks) {
|
|
|
289
312
|
outputTokens: run.usage.outputTokens + event.usage.outputTokens,
|
|
290
313
|
};
|
|
291
314
|
hooks.onUsage(spec.label, event.usage);
|
|
315
|
+
// W1's delta needs the history LENGTH the measurement covered, and the
|
|
316
|
+
// port carries no turn hook. `turn_end` is emitted BEFORE the assistant
|
|
317
|
+
// push, so this is exactly the history the reported `usage` describes.
|
|
318
|
+
contextManager?.onTurnEnd(event.usage, agentRef?.state.messages ?? [], systemPrompt);
|
|
292
319
|
const text = assistantText(event.message);
|
|
293
320
|
// The LAST non-empty assistant text wins, which is exactly the child's
|
|
294
321
|
// final message once the loop stops calling tools. Capturing it here
|
package/dist/team/types.d.ts
CHANGED
|
@@ -78,6 +78,14 @@ export interface SubagentRun {
|
|
|
78
78
|
error?: string;
|
|
79
79
|
/** Hit `team.maxTurnsPerSubagent` and was stopped mid-work. */
|
|
80
80
|
truncated?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Compactions this child performed on its OWN history
|
|
83
|
+
* (context-auto-compaction-hardening §3.4.4 / W3).
|
|
84
|
+
*
|
|
85
|
+
* OPTIONAL, so every existing construction site and fixture compiles
|
|
86
|
+
* unchanged. Absent and `0` mean the same thing to every reader.
|
|
87
|
+
*/
|
|
88
|
+
compactions?: number;
|
|
81
89
|
/**
|
|
82
90
|
* Prose the child is writing right now, sanitized and clamped to
|
|
83
91
|
* `TEAM_LIMITS.activityChars`. Set only between tool calls; cleared on
|
|
@@ -1,12 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* bash tool — run a shell command at full permission (spec §3.6)
|
|
2
|
+
* bash tool — run a shell command at full permission (spec §3.6), and, since
|
|
3
|
+
* background-service-supervision, supervise the ones that do not exit.
|
|
3
4
|
*
|
|
4
5
|
* Shell selection: Windows uses `process.env.ComSpec` (cmd.exe by default);
|
|
5
6
|
* POSIX uses `/bin/sh -c`. The command's stdout+stderr and exit code are
|
|
6
7
|
* captured. The `timeout?` param can only SHRINK within the executor ceiling
|
|
7
8
|
* (the core ToolExecutor owns the real timeout + 100 KB truncation — R4), so
|
|
8
9
|
* this tool does not re-implement an output cap.
|
|
10
|
+
*
|
|
11
|
+
* I-1 — THIS TOOL NEVER LEAVES ITS PROMISE PENDING. Every exit path goes through
|
|
12
|
+
* `settle`, and `settle` is reachable from FIVE places: `'error'`, `'close'`,
|
|
13
|
+
* `'exit'` plus a drain timer, an abort plus a kill grace, and the `timeout`
|
|
14
|
+
* param plus the same grace. That is the whole of W1, and each of the five
|
|
15
|
+
* closes a way the old implementation could hang:
|
|
16
|
+
*
|
|
17
|
+
* 1. It settled on `'close'`, which fires only when the process has exited AND
|
|
18
|
+
* every stdio stream is closed. A child that spawns a detached grandchild
|
|
19
|
+
* inheriting the pipe — `Start-Process`, `&`, `nohup`, and every
|
|
20
|
+
* `npm run dev` that re-execs — keeps that pipe open after the shell is
|
|
21
|
+
* long gone. The shell exited; the promise did not.
|
|
22
|
+
* 2. `stdio` defaulted to `'pipe'` for stdin, so a command that PROMPTS —
|
|
23
|
+
* `npm init`, a package manager asking to install something, `sudo`, a git
|
|
24
|
+
* credential prompt — blocked on a read that could never be satisfied.
|
|
25
|
+
* 3. An abort killed the tree and then went on waiting for a `'close'` that a
|
|
26
|
+
* detached grandchild was still holding.
|
|
27
|
+
*
|
|
28
|
+
* The happy path is BYTE-IDENTICAL to the pre-change build: `$ cmd\n<output>\n
|
|
29
|
+
* [exit code N]`, same truncation, same footer. That is what keeps the existing
|
|
30
|
+
* `bash` assertions meaningful rather than rewritten.
|
|
9
31
|
*/
|
|
10
32
|
import { type AgentTool } from '@aragon-agent/core';
|
|
33
|
+
import type { ProcSupervisorPort } from '../proc/types.js';
|
|
11
34
|
import type { ToolDeps } from './fs-tools.js';
|
|
12
|
-
export
|
|
35
|
+
export interface BashToolOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Present only when background launches are on for this session.
|
|
38
|
+
*
|
|
39
|
+
* ITS ABSENCE IS WHAT MAKES I-2 CHECKABLE: no `background` property in the
|
|
40
|
+
* schema, no supervisor call, no readiness timer, and a description string
|
|
41
|
+
* identical to the pre-feature one.
|
|
42
|
+
*/
|
|
43
|
+
supervisor?: ProcSupervisorPort;
|
|
44
|
+
/** `cfg.bash.autoBackground`, read LIVE. */
|
|
45
|
+
autoBackground?: () => boolean;
|
|
46
|
+
/** `cfg.bash.startupSettleMs`, read LIVE. */
|
|
47
|
+
startupSettleMs?: () => number;
|
|
48
|
+
/**
|
|
49
|
+
* Whether a card can be rendered and a user can keep a service alive (D-15 /
|
|
50
|
+
* P1-8).
|
|
51
|
+
*
|
|
52
|
+
* FALSE IN `aragon exec` AND `-p`. It suppresses only the CLASSIFIER: an
|
|
53
|
+
* explicit `background: true` is still honoured — the model asked for it —
|
|
54
|
+
* and the result then carries one extra line saying the service dies with the
|
|
55
|
+
* run. Without this rule `aragon -p "npm run dev"` would background a server,
|
|
56
|
+
* return in `startupSettleMs`, and reap it at process exit with no card, no
|
|
57
|
+
* `/bg`, no event and nothing in the result saying so.
|
|
58
|
+
*/
|
|
59
|
+
interactive?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export declare function makeBash(deps: ToolDeps, options?: BashToolOptions): AgentTool;
|