@aragon-agent/cli 0.6.34 → 0.6.36
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 +21 -0
- package/README.md +173 -7
- package/dist/agent/agent-mode.d.ts +20 -4
- package/dist/agent/agent-mode.js +20 -4
- package/dist/agent/controller.d.ts +67 -3
- package/dist/agent/controller.js +106 -5
- package/dist/agent/headless.js +31 -0
- package/dist/agent/kit-apply.d.ts +56 -0
- package/dist/agent/kit-apply.js +209 -0
- package/dist/agent/model-profile-settings.d.ts +28 -0
- package/dist/agent/model-profile-settings.js +142 -29
- package/dist/agent/reducer.d.ts +13 -2
- package/dist/agent/reducer.js +1 -0
- package/dist/cli.js +12 -0
- package/dist/commands/agents-command.d.ts +15 -0
- package/dist/commands/agents-command.js +27 -0
- package/dist/commands/builtins.js +135 -4
- package/dist/commands/kit-command.d.ts +20 -0
- package/dist/commands/kit-command.js +131 -0
- package/dist/commands/perf.d.ts +11 -0
- package/dist/commands/perf.js +2 -1
- package/dist/commands/registry.d.ts +14 -0
- package/dist/config/app-paths.d.ts +15 -0
- package/dist/config/app-paths.js +33 -2
- package/dist/config/env.d.ts +4 -1
- package/dist/config/env.js +28 -2
- package/dist/config/kit-resolution.d.ts +93 -0
- package/dist/config/kit-resolution.js +226 -0
- package/dist/config/load.d.ts +10 -0
- package/dist/config/load.js +8 -1
- package/dist/config/model-kits.d.ts +224 -0
- package/dist/config/model-kits.js +302 -0
- package/dist/config/model-profile-store.d.ts +25 -0
- package/dist/config/model-profiles.d.ts +41 -3
- package/dist/config/model-profiles.js +46 -5
- package/dist/config/schema.d.ts +84 -0
- package/dist/config/schema.js +39 -0
- package/dist/config/store.js +12 -1
- package/dist/config/ui-state.d.ts +18 -0
- package/dist/config/ui-state.js +9 -0
- package/dist/exec/events.d.ts +25 -0
- package/dist/exec/events.js +4 -0
- package/dist/exec/index.js +16 -1
- package/dist/exec/runner.js +10 -0
- package/dist/input/keymap.js +18 -4
- package/dist/proc/limits.d.ts +16 -0
- package/dist/proc/limits.js +16 -0
- package/dist/proc/supervisor.d.ts +20 -1
- package/dist/proc/supervisor.js +42 -14
- package/dist/prompts/command.d.ts +34 -0
- package/dist/prompts/command.js +237 -0
- package/dist/prompts/copy.d.ts +89 -0
- package/dist/prompts/copy.js +131 -0
- package/dist/prompts/fill.d.ts +51 -0
- package/dist/prompts/fill.js +46 -0
- package/dist/prompts/limits.d.ts +53 -0
- package/dist/prompts/limits.js +53 -0
- package/dist/prompts/normalize.d.ts +53 -0
- package/dist/prompts/normalize.js +190 -0
- package/dist/prompts/resolve.d.ts +31 -0
- package/dist/prompts/resolve.js +60 -0
- package/dist/prompts/search.d.ts +58 -0
- package/dist/prompts/search.js +146 -0
- package/dist/prompts/store.d.ts +86 -0
- package/dist/prompts/store.js +453 -0
- package/dist/prompts/types.d.ts +204 -0
- package/dist/prompts/types.js +13 -0
- package/dist/session/checkpoint.d.ts +8 -1
- package/dist/session/checkpoint.js +6 -0
- package/dist/session/persist.d.ts +19 -1
- package/dist/session/persist.js +13 -1
- package/dist/session/startup-session.d.ts +7 -2
- package/dist/session/startup-session.js +5 -2
- package/dist/session/store.js +3 -0
- package/dist/session/validate-session.js +64 -1
- package/dist/team/limits.d.ts +25 -0
- package/dist/team/limits.js +26 -0
- package/dist/team/runtime.js +27 -2
- package/dist/team/settled.d.ts +57 -0
- package/dist/team/settled.js +87 -0
- package/dist/team/subagent.js +48 -2
- package/dist/team/timeline.d.ts +74 -0
- package/dist/team/timeline.js +101 -0
- package/dist/team/types.d.ts +24 -1
- package/dist/todo/acceptance.d.ts +120 -0
- package/dist/todo/acceptance.js +399 -0
- package/dist/todo/follow-through.d.ts +48 -23
- package/dist/todo/follow-through.js +110 -44
- package/dist/todo/limits.d.ts +62 -1
- package/dist/todo/limits.js +62 -1
- package/dist/todo/panel-rows.d.ts +29 -39
- package/dist/todo/panel-rows.js +37 -83
- package/dist/todo/plan-sections.d.ts +60 -0
- package/dist/todo/plan-sections.js +108 -0
- package/dist/todo/prompt.d.ts +17 -12
- package/dist/todo/prompt.js +59 -40
- package/dist/todo/row-window.d.ts +51 -0
- package/dist/todo/row-window.js +107 -0
- package/dist/todo/store.d.ts +139 -31
- package/dist/todo/store.js +271 -73
- package/dist/todo/todo-tool.d.ts +33 -8
- package/dist/todo/todo-tool.js +186 -30
- package/dist/todo/types.d.ts +58 -0
- package/dist/ui/App.js +414 -54
- package/dist/ui/Composer.d.ts +6 -2
- package/dist/ui/Composer.js +2 -2
- package/dist/ui/Header.d.ts +17 -1
- package/dist/ui/Header.js +8 -2
- package/dist/ui/PromptInput.d.ts +21 -1
- package/dist/ui/PromptInput.js +22 -2
- package/dist/ui/ScrollbackShell.d.ts +22 -7
- package/dist/ui/ScrollbackShell.js +8 -1
- package/dist/ui/StatusBar.d.ts +18 -0
- package/dist/ui/StatusBar.js +11 -3
- package/dist/ui/TeamPanel.d.ts +35 -41
- package/dist/ui/TeamPanel.js +53 -163
- package/dist/ui/TodoPanel.d.ts +17 -14
- package/dist/ui/TodoPanel.js +146 -38
- package/dist/ui/Transcript.js +23 -3
- package/dist/ui/composer-input.d.ts +10 -0
- package/dist/ui/composer-input.js +57 -24
- package/dist/ui/entries/TeamCard.d.ts +18 -2
- package/dist/ui/entries/TeamCard.js +47 -13
- package/dist/ui/entries/TodoCard.d.ts +26 -11
- package/dist/ui/entries/TodoCard.js +56 -15
- package/dist/ui/glyphs.d.ts +19 -0
- package/dist/ui/glyphs.js +4 -0
- package/dist/ui/layout/agents-board.d.ts +102 -0
- package/dist/ui/layout/agents-board.js +389 -0
- package/dist/ui/layout/cells.d.ts +61 -0
- package/dist/ui/layout/cells.js +156 -0
- package/dist/ui/layout/header-hints.d.ts +23 -3
- package/dist/ui/layout/header-hints.js +73 -7
- package/dist/ui/layout/kit-chip.d.ts +50 -0
- package/dist/ui/layout/kit-chip.js +81 -0
- package/dist/ui/layout/status-detail-layout.js +9 -0
- package/dist/ui/layout/status-layout.d.ts +13 -0
- package/dist/ui/layout/team-row.d.ts +139 -0
- package/dist/ui/layout/team-row.js +246 -0
- package/dist/ui/layout/todo-layout.d.ts +38 -0
- package/dist/ui/layout/todo-layout.js +75 -0
- package/dist/ui/layout/virtual-window.js +32 -3
- package/dist/ui/overlays/AgentsBoardOverlay.d.ts +57 -0
- package/dist/ui/overlays/AgentsBoardOverlay.js +183 -0
- package/dist/ui/overlays/HelpOverlay.js +24 -2
- package/dist/ui/overlays/KitEditor.d.ts +23 -0
- package/dist/ui/overlays/KitEditor.js +101 -0
- package/dist/ui/overlays/KitManager.d.ts +23 -0
- package/dist/ui/overlays/KitManager.js +104 -0
- package/dist/ui/overlays/KitPicker.d.ts +49 -0
- package/dist/ui/overlays/KitPicker.js +58 -0
- package/dist/ui/overlays/ModelProfilePicker.js +16 -6
- package/dist/ui/overlays/PromptEditorPage.d.ts +48 -0
- package/dist/ui/overlays/PromptEditorPage.js +227 -0
- package/dist/ui/overlays/PromptLibraryOverlay.d.ts +37 -0
- package/dist/ui/overlays/PromptLibraryOverlay.js +191 -0
- package/dist/ui/overlays/PromptPicker.d.ts +36 -0
- package/dist/ui/overlays/PromptPicker.js +129 -0
- package/dist/ui/overlays/PromptTextArea.d.ts +86 -0
- package/dist/ui/overlays/PromptTextArea.js +141 -0
- package/dist/ui/overlays/SettingsScreen.js +139 -16
- package/dist/ui/overlays/kit-picker-state.d.ts +87 -0
- package/dist/ui/overlays/kit-picker-state.js +136 -0
- package/dist/ui/overlays/kit-settings-state.d.ts +129 -0
- package/dist/ui/overlays/kit-settings-state.js +267 -0
- package/dist/ui/overlays/model-profile-state.d.ts +26 -3
- package/dist/ui/overlays/model-profile-state.js +59 -6
- package/dist/ui/overlays/prompt-library-state.d.ts +162 -0
- package/dist/ui/overlays/prompt-library-state.js +335 -0
- package/dist/ui/overlays/prompt-picker-state.d.ts +71 -0
- package/dist/ui/overlays/prompt-picker-state.js +98 -0
- package/dist/ui/scrollback/LiveTail.d.ts +2 -2
- package/dist/ui/scrollback/LiveTail.js +7 -2
- package/dist/ui/scrollback/band.js +14 -1
- package/dist/ui/scrollback/live-preview.js +10 -3
- package/dist/ui/scrollback/tail-window.d.ts +12 -0
- package/dist/ui/scrollback/tail-window.js +17 -2
- package/dist/ui/scrollback/use-scrollback-view.js +7 -0
- package/dist/ui/team-status.d.ts +166 -0
- package/dist/ui/team-status.js +252 -0
- package/dist/ui/transcript-text.js +13 -4
- package/dist/ui/use-startup-notices.d.ts +35 -1
- package/dist/ui/use-startup-notices.js +29 -2
- package/dist/ui/use-wheel-routing.js +10 -2
- package/package.json +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AgentKit } from './model-kits.js';
|
|
1
2
|
export type ModelRole = 'main' | 'fast';
|
|
2
3
|
export interface ModelProfile {
|
|
3
4
|
id: string;
|
|
@@ -14,6 +15,16 @@ export interface ModelProfilesConfig {
|
|
|
14
15
|
entries: ModelProfile[];
|
|
15
16
|
mainId: string | null;
|
|
16
17
|
fastId: string | null;
|
|
18
|
+
/**
|
|
19
|
+
* Agent model kits (agent-model-kits D-2). OPTIONAL because a file written by
|
|
20
|
+
* a pre-KIT build simply has no such key; `emptyModelProfiles` still fills it
|
|
21
|
+
* in, so every library this build CREATES is explicit.
|
|
22
|
+
*/
|
|
23
|
+
kits?: AgentKit[];
|
|
24
|
+
/** The `Set default` pointer (D-13); a dangling value normalizes to null. */
|
|
25
|
+
defaultKitId?: string | null;
|
|
26
|
+
/** Forward migration marker (D-3). Always 1; never a functional decision. */
|
|
27
|
+
kitsVersion?: 1;
|
|
17
28
|
}
|
|
18
29
|
export interface ProfileBindingState {
|
|
19
30
|
selectedId: string | null;
|
|
@@ -42,7 +53,16 @@ export declare function emptyModelProfileState(invalid?: boolean): ModelProfiles
|
|
|
42
53
|
* copy of these four clauses is one edit away from disagreeing with the config layer.
|
|
43
54
|
*/
|
|
44
55
|
export declare function isValidEndpointUrl(value: string | null | undefined): boolean;
|
|
45
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Validate untrusted input; diagnostics never include supplied values.
|
|
58
|
+
*
|
|
59
|
+
* THE KIT SECTION IS STRUCTURAL ONLY (agent-model-kits RV-P1-1). `mainId` /
|
|
60
|
+
* `fastId` above are `missing_reference` because a dangling ROLE BINDING leaves
|
|
61
|
+
* the whole library unreadable (there is no "nothing bound" recovery path once
|
|
62
|
+
* a bound id is gone), while a dangling KIT SLOT degrades at resolution time
|
|
63
|
+
* into `Profile missing` and a refused apply - the same discipline
|
|
64
|
+
* `team.modelProfileId` already follows (`schema.ts` clampTeamConfig).
|
|
65
|
+
*/
|
|
46
66
|
export declare function validateModelProfiles(value: unknown): ProfileValidationIssue[];
|
|
47
67
|
/**
|
|
48
68
|
* Disk-tolerance gate for a profile-level context window (profile-context-window 5.3).
|
|
@@ -55,11 +75,29 @@ export declare function validateModelProfiles(value: unknown): ProfileValidation
|
|
|
55
75
|
* (invariant 4 - one bad number must not drop the user's credentials).
|
|
56
76
|
*/
|
|
57
77
|
export declare function normalizeProfileContextWindow(value: unknown): number | null;
|
|
58
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Normalize a valid library into a safe field whitelist; throws a fixed error if invalid.
|
|
80
|
+
*
|
|
81
|
+
* THE THREE KIT KEYS ARE LISTED EXPLICITLY, NEVER `...spread` (R-2): this
|
|
82
|
+
* literal IS the whitelist (F-3), so a key missing from it disappears at the
|
|
83
|
+
* next write - a save that only touched `thinking` would silently delete every
|
|
84
|
+
* kit the user owns. `normalizeKits` is TOTAL, so a hand-edited kit degrades
|
|
85
|
+
* instead of taking the library (and the credentials in it) with it.
|
|
86
|
+
*/
|
|
59
87
|
export declare function normalizeModelProfiles(value: unknown): ModelProfilesConfig;
|
|
60
88
|
/** Create an entry with a stable UUID and a frozen default name. */
|
|
61
89
|
export declare function createModelProfile(input: Omit<ModelProfile, 'id'>): ModelProfile;
|
|
62
90
|
/** Duplicate the current draft entry, including its explicitly edited credential. */
|
|
63
91
|
export declare function duplicateModelProfile(entry: ModelProfile): ModelProfile;
|
|
64
|
-
/**
|
|
92
|
+
/** Ids of the kits whose three slots name `id`, for the reference message. */
|
|
93
|
+
export declare function kitNamesForProfile(library: ModelProfilesConfig, id: string): string[];
|
|
94
|
+
/**
|
|
95
|
+
* Remove an unused entry; binding references must be changed explicitly first.
|
|
96
|
+
*
|
|
97
|
+
* The message NAMES the kits that would be orphaned (D-9): a throw that only
|
|
98
|
+
* says "still in use" sends the user hunting through three separate screens for
|
|
99
|
+
* the reference it means, and the kits are the reference nobody thinks of.
|
|
100
|
+
* (The UI never reaches this throw - it unbinds, and deletes the kits, inside
|
|
101
|
+
* the draft first - so this is the library-level backstop, F-25.)
|
|
102
|
+
*/
|
|
65
103
|
export declare function removeModelProfile(library: ModelProfilesConfig, id: string): ModelProfilesConfig;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { ADAPTER_PROVIDERS, clampContextWindow, isAutoToken } from './schema.js';
|
|
3
|
+
import { normalizeKits, validateKits } from './model-kits.js';
|
|
3
4
|
const CONTROL = /[\u0000-\u001f\u007f-\u009f]/;
|
|
4
5
|
/** Return a fresh empty library without initiating a disk migration. */
|
|
5
6
|
export function emptyModelProfiles() {
|
|
6
|
-
return { version: 1, entries: [], mainId: null, fastId: null
|
|
7
|
+
return { version: 1, entries: [], mainId: null, fastId: null, kits: [],
|
|
8
|
+
defaultKitId: null, kitsVersion: 1 };
|
|
7
9
|
}
|
|
8
10
|
/** Return independently mutable role state. */
|
|
9
11
|
export function emptyModelProfileState(invalid = false) {
|
|
@@ -69,7 +71,16 @@ function validateEntry(value, index) {
|
|
|
69
71
|
}
|
|
70
72
|
return issues;
|
|
71
73
|
}
|
|
72
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Validate untrusted input; diagnostics never include supplied values.
|
|
76
|
+
*
|
|
77
|
+
* THE KIT SECTION IS STRUCTURAL ONLY (agent-model-kits RV-P1-1). `mainId` /
|
|
78
|
+
* `fastId` above are `missing_reference` because a dangling ROLE BINDING leaves
|
|
79
|
+
* the whole library unreadable (there is no "nothing bound" recovery path once
|
|
80
|
+
* a bound id is gone), while a dangling KIT SLOT degrades at resolution time
|
|
81
|
+
* into `Profile missing` and a refused apply - the same discipline
|
|
82
|
+
* `team.modelProfileId` already follows (`schema.ts` clampTeamConfig).
|
|
83
|
+
*/
|
|
73
84
|
export function validateModelProfiles(value) {
|
|
74
85
|
if (value === undefined)
|
|
75
86
|
return [];
|
|
@@ -99,6 +110,7 @@ export function validateModelProfiles(value) {
|
|
|
99
110
|
message: 'Select an existing profile or Current custom.' });
|
|
100
111
|
}
|
|
101
112
|
}
|
|
113
|
+
issues.push(...validateKits(value.kits));
|
|
102
114
|
return issues;
|
|
103
115
|
}
|
|
104
116
|
/**
|
|
@@ -116,19 +128,29 @@ export function normalizeProfileContextWindow(value) {
|
|
|
116
128
|
return null;
|
|
117
129
|
return clampContextWindow(value, null);
|
|
118
130
|
}
|
|
119
|
-
/**
|
|
131
|
+
/**
|
|
132
|
+
* Normalize a valid library into a safe field whitelist; throws a fixed error if invalid.
|
|
133
|
+
*
|
|
134
|
+
* THE THREE KIT KEYS ARE LISTED EXPLICITLY, NEVER `...spread` (R-2): this
|
|
135
|
+
* literal IS the whitelist (F-3), so a key missing from it disappears at the
|
|
136
|
+
* next write - a save that only touched `thinking` would silently delete every
|
|
137
|
+
* kit the user owns. `normalizeKits` is TOTAL, so a hand-edited kit degrades
|
|
138
|
+
* instead of taking the library (and the credentials in it) with it.
|
|
139
|
+
*/
|
|
120
140
|
export function normalizeModelProfiles(value) {
|
|
121
141
|
if (validateModelProfiles(value).length)
|
|
122
142
|
throw new Error('Invalid model profiles.');
|
|
123
143
|
if (value === undefined)
|
|
124
144
|
return emptyModelProfiles();
|
|
125
145
|
const library = value;
|
|
146
|
+
const { kits, defaultKitId, kitsVersion } = normalizeKits(library.kits, library.defaultKitId);
|
|
126
147
|
return { version: 1, mainId: library.mainId, fastId: library.fastId,
|
|
127
148
|
entries: library.entries.map((entry) => ({ id: entry.id, name: entry.name.trim()
|
|
128
149
|
|| [...entry.model.trim()].slice(0, 80).join(''), provider: entry.provider,
|
|
129
150
|
model: entry.model.trim(), baseUrl: entry.baseUrl?.trim() || null,
|
|
130
151
|
apiKey: entry.apiKey?.trim() || null,
|
|
131
|
-
contextWindow: normalizeProfileContextWindow(entry.contextWindow) }))
|
|
152
|
+
contextWindow: normalizeProfileContextWindow(entry.contextWindow) })),
|
|
153
|
+
kits, defaultKitId, kitsVersion };
|
|
132
154
|
}
|
|
133
155
|
/** Create an entry with a stable UUID and a frozen default name. */
|
|
134
156
|
export function createModelProfile(input) {
|
|
@@ -139,9 +161,28 @@ export function createModelProfile(input) {
|
|
|
139
161
|
export function duplicateModelProfile(entry) {
|
|
140
162
|
return { ...entry, id: randomUUID(), name: `${[...entry.name].slice(0, 73).join('')} (copy)` };
|
|
141
163
|
}
|
|
142
|
-
/**
|
|
164
|
+
/** Ids of the kits whose three slots name `id`, for the reference message. */
|
|
165
|
+
export function kitNamesForProfile(library, id) {
|
|
166
|
+
return (library.kits ?? []).filter((kit) => kit.mainProfileId === id
|
|
167
|
+
|| kit.fastProfileId === id
|
|
168
|
+
|| (kit.subagent.model === 'profile' && kit.subagent.modelProfileId === id))
|
|
169
|
+
.map((kit) => kit.name);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Remove an unused entry; binding references must be changed explicitly first.
|
|
173
|
+
*
|
|
174
|
+
* The message NAMES the kits that would be orphaned (D-9): a throw that only
|
|
175
|
+
* says "still in use" sends the user hunting through three separate screens for
|
|
176
|
+
* the reference it means, and the kits are the reference nobody thinks of.
|
|
177
|
+
* (The UI never reaches this throw - it unbinds, and deletes the kits, inside
|
|
178
|
+
* the draft first - so this is the library-level backstop, F-25.)
|
|
179
|
+
*/
|
|
143
180
|
export function removeModelProfile(library, id) {
|
|
144
181
|
if (library.mainId === id || library.fastId === id)
|
|
145
182
|
throw new Error('Profile is still in use.');
|
|
183
|
+
const kits = kitNamesForProfile(library, id);
|
|
184
|
+
if (kits.length) {
|
|
185
|
+
throw new Error(`Profile is used by kit ${kits.map((name) => `"${name}"`).join(', ')}.`);
|
|
186
|
+
}
|
|
146
187
|
return { ...library, entries: library.entries.filter((entry) => entry.id !== id) };
|
|
147
188
|
}
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -489,6 +489,17 @@ export interface TodoConfig {
|
|
|
489
489
|
* be, and would mean replacing both merges first.
|
|
490
490
|
*/
|
|
491
491
|
followThrough: FollowThroughMode;
|
|
492
|
+
/**
|
|
493
|
+
* Must a plan also declare acceptance criteria, and does the UI show them
|
|
494
|
+
* (todo-acceptance-criteria §6.8.1). Default TRUE.
|
|
495
|
+
*
|
|
496
|
+
* THE FOURTH SCALAR, and it is a scalar for exactly the reason above: both
|
|
497
|
+
* hand-written merges in `config/store.ts` spread the whole `todo` object, so a
|
|
498
|
+
* new scalar key flows through them automatically. `clampTodoConfig` below is the
|
|
499
|
+
* only other place that has to know about it - a value that is missing THERE
|
|
500
|
+
* would silently keep the default and make `--no-todo-acceptance` look broken.
|
|
501
|
+
*/
|
|
502
|
+
acceptance: boolean;
|
|
492
503
|
}
|
|
493
504
|
export declare const DEFAULT_TODO_CONFIG: TodoConfig;
|
|
494
505
|
/**
|
|
@@ -851,6 +862,43 @@ export declare const DEFAULT_JOBS_CONFIG: JobsConfig;
|
|
|
851
862
|
* resolve to `undefined` and the setting would silently never apply.
|
|
852
863
|
*/
|
|
853
864
|
export declare function clampJobsConfig(raw: unknown): JobsConfig;
|
|
865
|
+
/**
|
|
866
|
+
* The quick-prompt library's three POLICY scalars (quick-prompt-library D-19).
|
|
867
|
+
*
|
|
868
|
+
* THE LIBRARY ITSELF IS NOT HERE (D-3). Two hundred prompts with bodies is user
|
|
869
|
+
* content that grows with usage, and `ui-state.ts:5-13` already wrote the rule:
|
|
870
|
+
* anything carrying user content opens its own file. `config.json` holds the three
|
|
871
|
+
* decisions that are about BEHAVIOUR - whether the key exists, what a fill does to
|
|
872
|
+
* a non-empty draft, and whether the header teaches the key.
|
|
873
|
+
*
|
|
874
|
+
* ONE LEVEL DEEP, like every section beside it: `runConfigGet` splits on a single
|
|
875
|
+
* dot, so `prompts.hint` resolves and `prompts.some.nested` would not.
|
|
876
|
+
*/
|
|
877
|
+
export interface PromptsConfig {
|
|
878
|
+
/**
|
|
879
|
+
* `false` stops `Ctrl+P` and the header hint; `/prompts` STAYS REGISTERED and
|
|
880
|
+
* reports that the feature is off (D-19 / AC-30). Removing the command as well
|
|
881
|
+
* would leave the one surface that can explain the switch unable to run.
|
|
882
|
+
*/
|
|
883
|
+
enabled: boolean;
|
|
884
|
+
/**
|
|
885
|
+
* What a fill does to a draft that already has text in it (D-6).
|
|
886
|
+
* `insert` keeps the user's words; `replace` overwrites them.
|
|
887
|
+
*/
|
|
888
|
+
insertMode: 'insert' | 'replace';
|
|
889
|
+
/** Whether the header's right-hand column may teach `^P prompts`. */
|
|
890
|
+
hint: boolean;
|
|
891
|
+
}
|
|
892
|
+
export declare const DEFAULT_PROMPTS_CONFIG: PromptsConfig;
|
|
893
|
+
/**
|
|
894
|
+
* THE single gate for every `prompts` read AND write, like the eleven sections
|
|
895
|
+
* above it.
|
|
896
|
+
*
|
|
897
|
+
* An unrecognized `insertMode` falls back to `insert` rather than to `replace`,
|
|
898
|
+
* and that direction is deliberate: a typo must never silently start DISCARDING
|
|
899
|
+
* what the user has already typed into the composer.
|
|
900
|
+
*/
|
|
901
|
+
export declare function clampPromptsConfig(raw: unknown): PromptsConfig;
|
|
854
902
|
/**
|
|
855
903
|
* Parse `0.9`, `90%` or `90` into a ratio, or `null` when it is neither.
|
|
856
904
|
*
|
|
@@ -1013,6 +1061,8 @@ export interface PersistedConfig {
|
|
|
1013
1061
|
bash: BashConfig;
|
|
1014
1062
|
/** Background jobs and bounded waiting. The ELEVENTH; scalars only (see JobsConfig). */
|
|
1015
1063
|
jobs: JobsConfig;
|
|
1064
|
+
/** Quick prompts. The TWELFTH; three scalars (see PromptsConfig). */
|
|
1065
|
+
prompts: PromptsConfig;
|
|
1016
1066
|
}
|
|
1017
1067
|
export declare const DEFAULT_CONFIG: PersistedConfig;
|
|
1018
1068
|
/**
|
|
@@ -1044,6 +1094,22 @@ export interface CliConfig {
|
|
|
1044
1094
|
modelSettingsRestartRequired?: boolean;
|
|
1045
1095
|
modelProfiles?: import('./model-profiles.js').ModelProfilesConfig;
|
|
1046
1096
|
modelProfileState?: import('./model-profiles.js').ModelProfilesRuntime;
|
|
1097
|
+
/**
|
|
1098
|
+
* The SESSION kit (agent-model-kits D-5 / §7.2). RUNTIME-ONLY.
|
|
1099
|
+
*
|
|
1100
|
+
* IT IS NOT IN `PersistedConfig` AND IT NEVER WILL BE (I-5 / I-14): `ctrl+K`
|
|
1101
|
+
* and `/kit use` promise "this session only", and that promise is worth more
|
|
1102
|
+
* than a saved convenience - it is what makes "one keystroke changed my
|
|
1103
|
+
* defaults" structurally impossible rather than merely unlikely.
|
|
1104
|
+
*
|
|
1105
|
+
* `held` is the only fact worth storing: WHICH slots still belong to the kit.
|
|
1106
|
+
* The bindings are derivable, and a stored copy of them would be a second
|
|
1107
|
+
* truth (I-7: every held slot must have been written into the live config).
|
|
1108
|
+
*/
|
|
1109
|
+
sessionKit?: {
|
|
1110
|
+
id: string;
|
|
1111
|
+
held: import('./model-kits.js').KitSlot[];
|
|
1112
|
+
};
|
|
1047
1113
|
apiKeyOverrideTarget?: {
|
|
1048
1114
|
provider: string;
|
|
1049
1115
|
baseUrl: string | null;
|
|
@@ -1335,6 +1401,24 @@ export interface CliConfig {
|
|
|
1335
1401
|
* `undefined` and report an empty value for a setting that IS on disk.
|
|
1336
1402
|
*/
|
|
1337
1403
|
jobs: JobsConfig;
|
|
1404
|
+
/**
|
|
1405
|
+
* Quick prompts (quick-prompt-library D-19). The TWELFTH nested object; three
|
|
1406
|
+
* scalars, one level deep.
|
|
1407
|
+
*
|
|
1408
|
+
* ON `CliConfig` AS WELL AS `PersistedConfig`, for the reason every section above
|
|
1409
|
+
* records: `App` reads `cfg.prompts?.enabled` / `.hint` / `.insertMode` from a
|
|
1410
|
+
* `CliConfig`, so a key added to the persisted shape alone would round-trip
|
|
1411
|
+
* through the `config` commands, appear in `config list`, and change nothing.
|
|
1412
|
+
*
|
|
1413
|
+
* OPTIONAL ON THIS SHAPE ONLY, and `loadConfig` always fills it. The reason is the
|
|
1414
|
+
* one the `jobs` note above does not have to state: `CliConfig` is built by hand in
|
|
1415
|
+
* ~20 test fixtures, and a REQUIRED section turns every one of them into a compile
|
|
1416
|
+
* error for a feature none of them is about. The three readers then fall back to the
|
|
1417
|
+
* DOCUMENTED defaults (`enabled: true`, `insertMode: 'insert'`, `hint: true`), so a
|
|
1418
|
+
* missing section can only ever behave like a default session - never like a
|
|
1419
|
+
* disabled or destructive one.
|
|
1420
|
+
*/
|
|
1421
|
+
prompts?: PromptsConfig;
|
|
1338
1422
|
/**
|
|
1339
1423
|
* Lifetime submit count driving the composer hint fade (`HINT_FADE_AFTER`).
|
|
1340
1424
|
*
|
package/dist/config/schema.js
CHANGED
|
@@ -578,6 +578,7 @@ export const DEFAULT_TODO_CONFIG = {
|
|
|
578
578
|
enabled: true,
|
|
579
579
|
panel: true,
|
|
580
580
|
followThrough: 'notify',
|
|
581
|
+
acceptance: true,
|
|
581
582
|
};
|
|
582
583
|
/**
|
|
583
584
|
* There is no enum helper in this file, so this follows the `isThinkingLevel`
|
|
@@ -606,6 +607,10 @@ export function clampTodoConfig(raw) {
|
|
|
606
607
|
// `ARAGON_TODO_FOLLOW=garbage` therefore resolves to `'notify'` and throws
|
|
607
608
|
// nothing (AC-5).
|
|
608
609
|
followThrough: followMode(src.followThrough, DEFAULT_TODO_CONFIG.followThrough),
|
|
610
|
+
// The fourth key needs nothing beyond this line: no migration, because
|
|
611
|
+
// `CONFIG_VERSION` is only stamped and never branched, and an old file reaches
|
|
612
|
+
// the new default through `{ ...DEFAULT, ...partial } + clamp`.
|
|
613
|
+
acceptance: bool(src.acceptance, DEFAULT_TODO_CONFIG.acceptance),
|
|
609
614
|
};
|
|
610
615
|
}
|
|
611
616
|
export const DEFAULT_RETRY_CONFIG = {
|
|
@@ -958,6 +963,31 @@ export function clampJobsConfig(raw) {
|
|
|
958
963
|
noticeSteer: bool(src.noticeSteer, DEFAULT_JOBS_CONFIG.noticeSteer),
|
|
959
964
|
};
|
|
960
965
|
}
|
|
966
|
+
export const DEFAULT_PROMPTS_CONFIG = {
|
|
967
|
+
enabled: true,
|
|
968
|
+
insertMode: 'insert',
|
|
969
|
+
hint: true,
|
|
970
|
+
};
|
|
971
|
+
const PROMPT_INSERT_MODES = ['insert', 'replace'];
|
|
972
|
+
/**
|
|
973
|
+
* THE single gate for every `prompts` read AND write, like the eleven sections
|
|
974
|
+
* above it.
|
|
975
|
+
*
|
|
976
|
+
* An unrecognized `insertMode` falls back to `insert` rather than to `replace`,
|
|
977
|
+
* and that direction is deliberate: a typo must never silently start DISCARDING
|
|
978
|
+
* what the user has already typed into the composer.
|
|
979
|
+
*/
|
|
980
|
+
export function clampPromptsConfig(raw) {
|
|
981
|
+
const src = (raw && typeof raw === 'object' ? raw : {});
|
|
982
|
+
const mode = typeof src.insertMode === 'string' ? src.insertMode.trim().toLowerCase() : '';
|
|
983
|
+
return {
|
|
984
|
+
enabled: bool(src.enabled, DEFAULT_PROMPTS_CONFIG.enabled),
|
|
985
|
+
insertMode: PROMPT_INSERT_MODES.includes(mode)
|
|
986
|
+
? mode
|
|
987
|
+
: DEFAULT_PROMPTS_CONFIG.insertMode,
|
|
988
|
+
hint: bool(src.hint, DEFAULT_PROMPTS_CONFIG.hint),
|
|
989
|
+
};
|
|
990
|
+
}
|
|
961
991
|
/**
|
|
962
992
|
* Parse `0.9`, `90%` or `90` into a ratio, or `null` when it is neither.
|
|
963
993
|
*
|
|
@@ -1062,6 +1092,15 @@ export const DEFAULT_CONFIG = {
|
|
|
1062
1092
|
// to `undefined` would throw on `config.jobs.waitSeconds` at construction
|
|
1063
1093
|
// rather than quietly disabling something.
|
|
1064
1094
|
jobs: DEFAULT_JOBS_CONFIG,
|
|
1095
|
+
// And one section later again, for the seventh time, and this one has BOTH
|
|
1096
|
+
// failure directions at once: `prompts.enabled` and `prompts.hint` are `true` by
|
|
1097
|
+
// default, so a `config.json` predating this feature would resolve them to
|
|
1098
|
+
// `undefined` (falsy) and arrive with the key and its hint silently off - while
|
|
1099
|
+
// `prompts.insertMode` would be `undefined`, which is neither `'insert'` nor
|
|
1100
|
+
// `'replace'` and would make `planPromptFill` fall through to its `replace`
|
|
1101
|
+
// branch. That branch discards the user's own words, so the miss would be a data
|
|
1102
|
+
// loss rather than a missing hint.
|
|
1103
|
+
prompts: DEFAULT_PROMPTS_CONFIG,
|
|
1065
1104
|
};
|
|
1066
1105
|
/**
|
|
1067
1106
|
* Runtime state that used to be stored in `config.json` by mistake
|
package/dist/config/store.js
CHANGED
|
@@ -17,7 +17,7 @@ import { getConfigPath, getSessionsDir } from './app-paths.js';
|
|
|
17
17
|
import { registerProfileSecrets, registerSecretsFrom } from '../logging/secret-registry.js';
|
|
18
18
|
import { adaptLegacyConnectionPatch, ModelProfileConfigError, readModelSettingsDisk } from './model-profile-store.js';
|
|
19
19
|
import { normalizeModelProfiles } from './model-profiles.js';
|
|
20
|
-
import { clampBashConfig, clampJobsConfig, CONFIG_VERSION, DEFAULT_CONFIG, clampCompactionConfig, clampFastConfig, clampLogConfig, clampMaxTokens, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampContextWindow, clampUpdateConfig, isAutoToken, stripLegacyStateKeys, } from './schema.js';
|
|
20
|
+
import { clampBashConfig, clampJobsConfig, clampPromptsConfig, CONFIG_VERSION, DEFAULT_CONFIG, clampCompactionConfig, clampFastConfig, clampLogConfig, clampMaxTokens, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampContextWindow, clampUpdateConfig, isAutoToken, stripLegacyStateKeys, } from './schema.js';
|
|
21
21
|
/**
|
|
22
22
|
* Normalize `maxTokens` for both directions of the config file.
|
|
23
23
|
*
|
|
@@ -195,6 +195,11 @@ export function normalizePersistedConfig(input) {
|
|
|
195
195
|
// outright, which is a crash on the first `job_wait` rather than a silently
|
|
196
196
|
// wrong setting.
|
|
197
197
|
jobs: clampJobsConfig({ ...DEFAULT_CONFIG.jobs, ...(partial.jobs ?? {}) }),
|
|
198
|
+
// And the twelfth, on the same line and for the same reason - with one extra
|
|
199
|
+
// edge: without it `prompts.insertMode` reads `undefined`, which is neither
|
|
200
|
+
// `'insert'` nor `'replace'`, so a fill into a non-empty draft would take the
|
|
201
|
+
// branch that REPLACES what the user typed.
|
|
202
|
+
prompts: clampPromptsConfig({ ...DEFAULT_CONFIG.prompts, ...(partial.prompts ?? {}) }),
|
|
198
203
|
};
|
|
199
204
|
}
|
|
200
205
|
/**
|
|
@@ -302,6 +307,12 @@ export function mergePersistedConfig(current, patch) {
|
|
|
302
307
|
// absent — with `noticeSteer`'s default masking it on the next load, so the
|
|
303
308
|
// user would never learn that their privacy switch had been turned back on.
|
|
304
309
|
jobs: clampJobsConfig({ ...current.jobs, ...(patch.jobs ?? {}) }),
|
|
310
|
+
// The twelfth section, and the seventh time this file records the same trap.
|
|
311
|
+
// `aragon config set prompts.hint false` sends `{ prompts: { hint: false } }`;
|
|
312
|
+
// without this line the shallow top-level spread REPLACES the section and
|
|
313
|
+
// `insertMode` is written absent - which reads back as neither `'insert'` nor
|
|
314
|
+
// `'replace'`, i.e. the next fill overwrites the user's own draft.
|
|
315
|
+
prompts: clampPromptsConfig({ ...current.prompts, ...(patch.prompts ?? {}) }),
|
|
305
316
|
};
|
|
306
317
|
return merged;
|
|
307
318
|
}
|
|
@@ -90,6 +90,21 @@ export interface UiState {
|
|
|
90
90
|
* others for the same reasons the two above record, and NOT a schema bump.
|
|
91
91
|
*/
|
|
92
92
|
scrollModeNoticeVersion: number;
|
|
93
|
+
/**
|
|
94
|
+
* Which revision of the "Ctrl+P moved to the prompt library" notice this user has
|
|
95
|
+
* been shown (`0` = none; quick-prompt-library D-20).
|
|
96
|
+
*
|
|
97
|
+
* A VERSION BESIDE THE OTHERS AND NOT A SCHEMA BUMP, for the third time in this
|
|
98
|
+
* file: bumping `UI_STATE_SCHEMA` makes `readFromDisk` discard the whole object, so
|
|
99
|
+
* every user's `submitCount` resets and the composer hint un-fades - to re-show one
|
|
100
|
+
* line. A NEW field simply reads as its default on an older file, which is exactly
|
|
101
|
+
* the behaviour wanted here.
|
|
102
|
+
*
|
|
103
|
+
* IT EXISTS BECAUSE THE KEY MOVED. `Ctrl+P` now opens the prompt library and the
|
|
104
|
+
* mode fallback is `Ctrl+N`; the audience for that sentence is every existing user,
|
|
105
|
+
* and a boolean could only ever say "shown", never "shown WHAT".
|
|
106
|
+
*/
|
|
107
|
+
promptKeyNoticeVersion: number;
|
|
93
108
|
}
|
|
94
109
|
/** Read the state, caching it for the life of the process. Never throws. */
|
|
95
110
|
export declare function loadUiState(): UiState;
|
|
@@ -107,6 +122,9 @@ export declare function setVtInputNoticeVersion(version: number): void;
|
|
|
107
122
|
/** `0` on a file written before the field existed. */
|
|
108
123
|
export declare function getScrollModeNoticeVersion(): number;
|
|
109
124
|
export declare function setScrollModeNoticeVersion(version: number): void;
|
|
125
|
+
/** `0` on a file written before the field existed; see the field's comment. */
|
|
126
|
+
export declare function getPromptKeyNoticeVersion(): number;
|
|
127
|
+
export declare function setPromptKeyNoticeVersion(version: number): void;
|
|
110
128
|
/**
|
|
111
129
|
* Migration-only: fill in fields that are still at their default, and never
|
|
112
130
|
* overwrite a value already here. A second import — after a half-finished
|
package/dist/config/ui-state.js
CHANGED
|
@@ -38,6 +38,7 @@ const DEFAULT_UI_STATE = {
|
|
|
38
38
|
mouseNoticeVersion: 0,
|
|
39
39
|
vtInputNoticeVersion: 0,
|
|
40
40
|
scrollModeNoticeVersion: 0,
|
|
41
|
+
promptKeyNoticeVersion: 0,
|
|
41
42
|
};
|
|
42
43
|
let memory = null;
|
|
43
44
|
/** Non-negative integer or `fallback`; shared by both numeric fields. */
|
|
@@ -71,6 +72,7 @@ function readFromDisk() {
|
|
|
71
72
|
mouseNoticeVersion: coerceCount(parsed.mouseNoticeVersion, DEFAULT_UI_STATE.mouseNoticeVersion),
|
|
72
73
|
vtInputNoticeVersion: coerceCount(parsed.vtInputNoticeVersion, DEFAULT_UI_STATE.vtInputNoticeVersion),
|
|
73
74
|
scrollModeNoticeVersion: coerceCount(parsed.scrollModeNoticeVersion, DEFAULT_UI_STATE.scrollModeNoticeVersion),
|
|
75
|
+
promptKeyNoticeVersion: coerceCount(parsed.promptKeyNoticeVersion, DEFAULT_UI_STATE.promptKeyNoticeVersion),
|
|
74
76
|
};
|
|
75
77
|
}
|
|
76
78
|
catch {
|
|
@@ -151,6 +153,13 @@ export function getScrollModeNoticeVersion() {
|
|
|
151
153
|
export function setScrollModeNoticeVersion(version) {
|
|
152
154
|
update({ scrollModeNoticeVersion: version });
|
|
153
155
|
}
|
|
156
|
+
/** `0` on a file written before the field existed; see the field's comment. */
|
|
157
|
+
export function getPromptKeyNoticeVersion() {
|
|
158
|
+
return loadUiState().promptKeyNoticeVersion;
|
|
159
|
+
}
|
|
160
|
+
export function setPromptKeyNoticeVersion(version) {
|
|
161
|
+
update({ promptKeyNoticeVersion: version });
|
|
162
|
+
}
|
|
154
163
|
/**
|
|
155
164
|
* Migration-only: fill in fields that are still at their default, and never
|
|
156
165
|
* overwrite a value already here. A second import — after a half-finished
|
package/dist/exec/events.d.ts
CHANGED
|
@@ -192,6 +192,22 @@ export interface ExecTodoEvent {
|
|
|
192
192
|
content: string;
|
|
193
193
|
status: 'pending' | 'in_progress' | 'completed';
|
|
194
194
|
}[];
|
|
195
|
+
/**
|
|
196
|
+
* Acceptance counts (todo-acceptance-criteria §6.13.2). `null` when the capability
|
|
197
|
+
* is off or the plan has no criteria.
|
|
198
|
+
*
|
|
199
|
+
* REQUIRED BUT NULLABLE, not optional: `runner` is the only producer and can
|
|
200
|
+
* always answer, while for a consumer `null` and "field absent" mean the same
|
|
201
|
+
* thing under the forward-compatibility contract above. Per-criterion `evidence`
|
|
202
|
+
* never reaches this stream (I-8) - a machine consumer that needs it reads the
|
|
203
|
+
* session file.
|
|
204
|
+
*/
|
|
205
|
+
acceptance: {
|
|
206
|
+
total: number;
|
|
207
|
+
checked: number;
|
|
208
|
+
passed: number;
|
|
209
|
+
failed: number;
|
|
210
|
+
} | null;
|
|
195
211
|
}
|
|
196
212
|
export interface ExecTeamEvent {
|
|
197
213
|
type: 'team';
|
|
@@ -371,6 +387,15 @@ export interface ExecResultEvent {
|
|
|
371
387
|
id: string;
|
|
372
388
|
};
|
|
373
389
|
todos: ExecTodoCounts | null;
|
|
390
|
+
/**
|
|
391
|
+
* The acceptance tally for the run (todo-acceptance-criteria §6.13.2), on the same
|
|
392
|
+
* terms as `ExecTodoEvent.acceptance`: required but nullable, no evidence.
|
|
393
|
+
*/
|
|
394
|
+
acceptance: {
|
|
395
|
+
total: number;
|
|
396
|
+
passed: number;
|
|
397
|
+
failed: number;
|
|
398
|
+
} | null;
|
|
374
399
|
error: ExecErrorInfo | null;
|
|
375
400
|
}
|
|
376
401
|
/**
|
package/dist/exec/events.js
CHANGED
|
@@ -44,6 +44,10 @@ export const EXEC_CAPABILITIES = [
|
|
|
44
44
|
// Background job lifecycle events (long-task-jobs §4.10). A consumer that does
|
|
45
45
|
// not know the `job` type ignores it; this string is how it asks first.
|
|
46
46
|
'background-jobs',
|
|
47
|
+
// Acceptance counts on the todo event and the result event
|
|
48
|
+
// (todo-acceptance-criteria §6.13.2). APPEND-ONLY: a wrapper detects support by
|
|
49
|
+
// asking for this string, and an older wrapper never asks.
|
|
50
|
+
'todo-acceptance',
|
|
47
51
|
];
|
|
48
52
|
export function buildInitEvent(params) {
|
|
49
53
|
return {
|
package/dist/exec/index.js
CHANGED
|
@@ -112,7 +112,7 @@ async function execute(input) {
|
|
|
112
112
|
});
|
|
113
113
|
if (plan.saved) {
|
|
114
114
|
controller.replaceMessages(plan.saved.messages, plan.saved.compactionIdentity);
|
|
115
|
-
controller.restoreTodos(plan.saved.todos);
|
|
115
|
+
controller.restoreTodos(plan.saved.todos, plan.saved.acceptance);
|
|
116
116
|
}
|
|
117
117
|
const config = controller.getConfig();
|
|
118
118
|
emitter.init({
|
|
@@ -190,6 +190,14 @@ async function execute(input) {
|
|
|
190
190
|
cost: buildCost(controller, stats.usage, stats.compactionBilling),
|
|
191
191
|
model: { provider: config.provider, id: config.model },
|
|
192
192
|
todos: todo ? { total: todo.total, done: todo.doneCount } : null,
|
|
193
|
+
// The verdict tally for the run, with no per-criterion evidence (I-8).
|
|
194
|
+
acceptance: todo?.acceptance
|
|
195
|
+
? {
|
|
196
|
+
total: todo.acceptance.total,
|
|
197
|
+
passed: todo.acceptance.passedCount,
|
|
198
|
+
failed: todo.acceptance.failedCount,
|
|
199
|
+
}
|
|
200
|
+
: null,
|
|
193
201
|
error: stats.errorCode && stats.errorMessage
|
|
194
202
|
? { code: stats.errorCode, message: stats.errorMessage }
|
|
195
203
|
: null,
|
|
@@ -288,6 +296,7 @@ function failedResult(sessionId, config, message, code, durationMs) {
|
|
|
288
296
|
cost: { amount: 0, currency: 'USD', known: false },
|
|
289
297
|
model: { provider: config.provider, id: config.model },
|
|
290
298
|
todos: null,
|
|
299
|
+
acceptance: null,
|
|
291
300
|
error: { code, message },
|
|
292
301
|
};
|
|
293
302
|
}
|
|
@@ -479,6 +488,12 @@ function persist(plan, controller, turns, usage, cli, at) {
|
|
|
479
488
|
...(controller.getSessionSnapshot?.() ?? { messages: controller.getMessages() }),
|
|
480
489
|
entries: [],
|
|
481
490
|
todos: controller.getTodoSnapshot?.()?.items ?? [],
|
|
491
|
+
// From the STORE, not the render projection: a run whose capability is off
|
|
492
|
+
// must still persist the verdicts it already has. OPTIONAL CALL, like the line
|
|
493
|
+
// above: `ExecControllerFactory` is a port, and a caller whose controller
|
|
494
|
+
// predates this feature must keep saving sessions rather than fail on a method
|
|
495
|
+
// it never heard of - the failure mode would be a session silently not written.
|
|
496
|
+
acceptance: controller.getAcceptanceItems?.() ?? [],
|
|
482
497
|
},
|
|
483
498
|
meta,
|
|
484
499
|
});
|
package/dist/exec/runner.js
CHANGED
|
@@ -108,6 +108,16 @@ export class ExecRunner {
|
|
|
108
108
|
done: doneCount,
|
|
109
109
|
activeIndex,
|
|
110
110
|
items: items.map((item) => ({ content: item.content, status: item.status })),
|
|
111
|
+
// Counts only, never per-criterion evidence (I-8): this stream is a machine
|
|
112
|
+
// surface, and a criterion's evidence is written for a human to read.
|
|
113
|
+
acceptance: event.snapshot.acceptance
|
|
114
|
+
? {
|
|
115
|
+
total: event.snapshot.acceptance.total,
|
|
116
|
+
checked: event.snapshot.acceptance.checkedCount,
|
|
117
|
+
passed: event.snapshot.acceptance.passedCount,
|
|
118
|
+
failed: event.snapshot.acceptance.failedCount,
|
|
119
|
+
}
|
|
120
|
+
: null,
|
|
111
121
|
});
|
|
112
122
|
});
|
|
113
123
|
if (todos)
|
package/dist/input/keymap.js
CHANGED
|
@@ -7,7 +7,15 @@
|
|
|
7
7
|
* does not own so the caller can drop unknown control bytes instead of
|
|
8
8
|
* inserting them into the buffer.
|
|
9
9
|
*/
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Map a Ctrl-modified key to an intent, if any.
|
|
12
|
+
*
|
|
13
|
+
* `Ctrl+K` IS DELIBERATELY NOT HERE (agent-model-kits D-15). That byte belongs
|
|
14
|
+
* to the Agent-kit picker on the main screen, and this recognizer runs BEFORE
|
|
15
|
+
* `PromptInput`'s `if (key.ctrl) return` - so keeping the binding would delete
|
|
16
|
+
* the user's draft in one listener while the other opened the overlay. The
|
|
17
|
+
* capability moved to `Alt+K` (`fromMeta`) instead of being dropped.
|
|
18
|
+
*/
|
|
11
19
|
function fromCtrl(input, key) {
|
|
12
20
|
if (key.leftArrow)
|
|
13
21
|
return 'wordLeft';
|
|
@@ -22,8 +30,6 @@ function fromCtrl(input, key) {
|
|
|
22
30
|
return 'deleteWordBack';
|
|
23
31
|
case 'u':
|
|
24
32
|
return 'killToStart';
|
|
25
|
-
case 'k':
|
|
26
|
-
return 'killToEnd';
|
|
27
33
|
default:
|
|
28
34
|
return null;
|
|
29
35
|
}
|
|
@@ -34,6 +40,11 @@ function fromMeta(input) {
|
|
|
34
40
|
return 'wordLeft';
|
|
35
41
|
if (input === 'f')
|
|
36
42
|
return 'wordRight';
|
|
43
|
+
// `killToEnd` LIVES HERE NOW (agent-model-kits D-15). `Alt+K` keeps the
|
|
44
|
+
// capability, and it keeps the kill family together: `M-k` is kill-sentence in
|
|
45
|
+
// the Emacs tradition this keymap already borrows `Ctrl+W` and `Alt+B/F` from.
|
|
46
|
+
if (input === 'k')
|
|
47
|
+
return 'killToEnd';
|
|
37
48
|
if (input === '\x7f' || input === '\b')
|
|
38
49
|
return 'deleteWordBack';
|
|
39
50
|
return null;
|
|
@@ -63,7 +74,10 @@ function fromRaw(input) {
|
|
|
63
74
|
return 'deleteWordBack';
|
|
64
75
|
case '\x15': // Ctrl+U (raw)
|
|
65
76
|
return 'killToStart';
|
|
66
|
-
case '\
|
|
77
|
+
case '\x1bk':
|
|
78
|
+
// Alt+K (raw ESC + k). `\x0b` (Ctrl+K) is deliberately ABSENT: it belongs
|
|
79
|
+
// to the Agent-kit picker, and a case for it here would be a dead binding
|
|
80
|
+
// that still looks alive to every future reader.
|
|
67
81
|
return 'killToEnd';
|
|
68
82
|
default:
|
|
69
83
|
return null;
|
package/dist/proc/limits.d.ts
CHANGED
|
@@ -79,6 +79,22 @@ export declare const PROC_LIMITS: {
|
|
|
79
79
|
readonly outputCoalesceMs: 100;
|
|
80
80
|
/** `SIGTERM` -> `SIGKILL` escalation window for a graceful stop. */
|
|
81
81
|
readonly stopGraceMs: 3000;
|
|
82
|
+
/**
|
|
83
|
+
* How long to KEEP ASKING whether the `SIGKILL` actually landed before
|
|
84
|
+
* declaring the job `stopped`.
|
|
85
|
+
*
|
|
86
|
+
* THIS NUMBER IS NOT A GUESS ABOUT THE PLATFORM. `killTree` spawns `taskkill`,
|
|
87
|
+
* which is a process of its own: a Windows tree kill of a shell plus its node
|
|
88
|
+
* child measures ~0.8 s on the reference machine (while starting `cmd` costs
|
|
89
|
+
* 50 ms), so the fixed 250 ms this used to allow expired first and `stop()`
|
|
90
|
+
* reported `stopped` with the child still running - AC-18 caught exactly that.
|
|
91
|
+
* The wait stays BOUNDED against the opposite failure (a promise that never
|
|
92
|
+
* resolves); at this deadline the record keeps the honest `killIncomplete`
|
|
93
|
+
* flag instead.
|
|
94
|
+
*/
|
|
95
|
+
readonly killVerifyMs: 2000;
|
|
96
|
+
/** Liveness poll interval while waiting for a `SIGKILL` to land. */
|
|
97
|
+
readonly killVerifyPollMs: 50;
|
|
82
98
|
/** Below this many terminal columns the status chip degrades to `[N]`. */
|
|
83
99
|
readonly statusCompactCols: 92;
|
|
84
100
|
/**
|
package/dist/proc/limits.js
CHANGED
|
@@ -79,6 +79,22 @@ export const PROC_LIMITS = {
|
|
|
79
79
|
outputCoalesceMs: 100,
|
|
80
80
|
/** `SIGTERM` -> `SIGKILL` escalation window for a graceful stop. */
|
|
81
81
|
stopGraceMs: 3000,
|
|
82
|
+
/**
|
|
83
|
+
* How long to KEEP ASKING whether the `SIGKILL` actually landed before
|
|
84
|
+
* declaring the job `stopped`.
|
|
85
|
+
*
|
|
86
|
+
* THIS NUMBER IS NOT A GUESS ABOUT THE PLATFORM. `killTree` spawns `taskkill`,
|
|
87
|
+
* which is a process of its own: a Windows tree kill of a shell plus its node
|
|
88
|
+
* child measures ~0.8 s on the reference machine (while starting `cmd` costs
|
|
89
|
+
* 50 ms), so the fixed 250 ms this used to allow expired first and `stop()`
|
|
90
|
+
* reported `stopped` with the child still running - AC-18 caught exactly that.
|
|
91
|
+
* The wait stays BOUNDED against the opposite failure (a promise that never
|
|
92
|
+
* resolves); at this deadline the record keeps the honest `killIncomplete`
|
|
93
|
+
* flag instead.
|
|
94
|
+
*/
|
|
95
|
+
killVerifyMs: 2000,
|
|
96
|
+
/** Liveness poll interval while waiting for a `SIGKILL` to land. */
|
|
97
|
+
killVerifyPollMs: 50,
|
|
82
98
|
/** Below this many terminal columns the status chip degrades to `[N]`. */
|
|
83
99
|
statusCompactCols: 92,
|
|
84
100
|
// --- long-task-jobs: bounded waiting, progress, notices, log mirror --------
|