@aragon-agent/cli 0.6.3 → 0.6.7
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 +142 -0
- package/README.md +203 -13
- package/dist/agent/controller.d.ts +158 -2
- package/dist/agent/controller.js +400 -1
- package/dist/agent/reducer.d.ts +102 -19
- package/dist/agent/reducer.js +162 -71
- package/dist/agent/system-prompt.d.ts +14 -0
- package/dist/agent/system-prompt.js +2 -0
- package/dist/agent/usage.d.ts +34 -0
- package/dist/agent/usage.js +43 -0
- package/dist/cli.js +132 -23
- package/dist/commands/builtins.js +101 -1
- package/dist/compaction/child.js +5 -0
- package/dist/compaction/command.js +14 -1
- package/dist/compaction/compactor.d.ts +94 -24
- package/dist/compaction/compactor.js +247 -98
- package/dist/compaction/context-command.d.ts +33 -0
- package/dist/compaction/context-command.js +166 -0
- package/dist/compaction/meter.d.ts +251 -0
- package/dist/compaction/meter.js +428 -0
- package/dist/compaction/pressure.d.ts +6 -0
- package/dist/compaction/pressure.js +4 -0
- package/dist/compaction/types.d.ts +77 -0
- package/dist/compaction/wiring.d.ts +56 -0
- package/dist/compaction/wiring.js +107 -25
- package/dist/config/cli-commands.js +5 -0
- package/dist/config/env.d.ts +1 -1
- package/dist/config/env.js +63 -2
- package/dist/config/load.d.ts +28 -0
- package/dist/config/load.js +83 -1
- package/dist/config/schema.d.ts +129 -0
- package/dist/config/schema.js +69 -0
- package/dist/config/store.js +47 -1
- package/dist/exec/events.d.ts +138 -1
- package/dist/exec/events.js +42 -0
- package/dist/exec/index.js +43 -6
- package/dist/exec/progress-reporter.d.ts +23 -0
- package/dist/exec/progress-reporter.js +88 -0
- package/dist/exec/runner.d.ts +34 -0
- package/dist/exec/runner.js +137 -25
- package/dist/fast/reviewer.d.ts +19 -1
- package/dist/fast/reviewer.js +22 -0
- package/dist/fast/types.d.ts +15 -0
- package/dist/fast/wiring.d.ts +10 -1
- package/dist/fast/wiring.js +18 -1
- package/dist/input/limits.d.ts +72 -0
- package/dist/input/limits.js +63 -0
- 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 +2 -0
- package/dist/logging/install.js +53 -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 +36 -1
- package/dist/todo/limits.d.ts +4 -17
- package/dist/todo/limits.js +4 -17
- package/dist/todo/panel-rows.d.ts +8 -6
- package/dist/todo/panel-rows.js +19 -6
- 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/App.d.ts +15 -2
- package/dist/ui/App.js +330 -69
- package/dist/ui/AutocompletePopup.d.ts +3 -1
- package/dist/ui/AutocompletePopup.js +9 -11
- package/dist/ui/BottomStatusRow.d.ts +1 -1
- package/dist/ui/Composer.d.ts +56 -1
- package/dist/ui/Composer.js +50 -6
- package/dist/ui/PromptInput.d.ts +52 -3
- package/dist/ui/PromptInput.js +201 -55
- package/dist/ui/StatusBar.d.ts +40 -15
- package/dist/ui/StatusBar.js +51 -9
- package/dist/ui/TeamPanel.d.ts +3 -1
- package/dist/ui/TeamPanel.js +13 -9
- package/dist/ui/TodoPanel.d.ts +5 -5
- package/dist/ui/TodoPanel.js +56 -24
- package/dist/ui/Transcript.js +29 -1
- package/dist/ui/UpdateLine.d.ts +1 -1
- package/dist/ui/capabilities.js +5 -5
- 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/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/exit-snapshot.d.ts +9 -0
- package/dist/ui/layout/ScrollViewport.d.ts +1 -1
- package/dist/ui/layout/autocomplete.d.ts +18 -0
- package/dist/ui/layout/autocomplete.js +26 -0
- package/dist/ui/layout/budget.d.ts +34 -6
- package/dist/ui/layout/budget.js +32 -7
- package/dist/ui/layout/rail.d.ts +4 -53
- package/dist/ui/layout/rail.js +10 -62
- package/dist/ui/layout/team-panel.d.ts +18 -0
- package/dist/ui/layout/team-panel.js +22 -0
- package/dist/ui/layout/todo-layout.d.ts +24 -0
- package/dist/ui/layout/todo-layout.js +27 -0
- package/dist/ui/layout/virtual-window.js +51 -1
- package/dist/ui/overlays/HelpOverlay.js +3 -0
- package/dist/ui/overlays/PlanReviewOverlay.js +10 -2
- package/dist/ui/overlays/QuestionOverlay.js +5 -1
- package/dist/ui/overlays/SettingsScreen.js +14 -1
- 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 +16 -0
- package/dist/ui/screen.js +45 -2
- package/dist/ui/selection/selection-controller.d.ts +1 -1
- package/dist/ui/transcript-text.js +55 -2
- package/dist/ui/use-wheel-routing.d.ts +1 -1
- package/package.json +2 -2
- package/dist/input/stdin-mouse-filter.d.ts +0 -47
- package/dist/input/stdin-mouse-filter.js +0 -153
package/dist/config/schema.d.ts
CHANGED
|
@@ -78,6 +78,27 @@ export declare const DEFAULT_TRANSCRIPT_WINDOW = 1000;
|
|
|
78
78
|
export declare const MIN_TRANSCRIPT_WINDOW = 50;
|
|
79
79
|
export declare const MAX_TRANSCRIPT_WINDOW = 20000;
|
|
80
80
|
export declare function clampTranscriptWindow(v: unknown, fallback: number): number;
|
|
81
|
+
/**
|
|
82
|
+
* Bounds for a hand-supplied context window.
|
|
83
|
+
*
|
|
84
|
+
* The floor is roughly the smallest window any current model ships with; the
|
|
85
|
+
* ceiling is well above the largest, and both exist to keep a typo (a missing
|
|
86
|
+
* or an extra zero) from producing a gauge that is permanently red or
|
|
87
|
+
* permanently flat.
|
|
88
|
+
*/
|
|
89
|
+
export declare const MIN_CONTEXT_WINDOW = 8000;
|
|
90
|
+
export declare const MAX_CONTEXT_WINDOW = 5000000;
|
|
91
|
+
/**
|
|
92
|
+
* THE single gate for every `contextWindow` read AND write.
|
|
93
|
+
*
|
|
94
|
+
* TRI-STATE, AND `null` MUST PASS STRAIGHT THROUGH (RV-12). `null` means AUTO -
|
|
95
|
+
* take the model table's number, or the 128k placeholder. Clamping it into
|
|
96
|
+
* `[8000, ...]` yields 8000, which removes "auto" from the config permanently
|
|
97
|
+
* and presents to the user as an 8k denominator with a permanently red bar and
|
|
98
|
+
* no visible source. `maxTokens` above is the existing tri-state precedent and
|
|
99
|
+
* this deliberately copies its shape rather than inventing a second convention.
|
|
100
|
+
*/
|
|
101
|
+
export declare function clampContextWindow(v: unknown, fallback: number | null): number | null;
|
|
81
102
|
/**
|
|
82
103
|
* Entries kept in `ViewState` at all (tui-render-performance L1 / R5).
|
|
83
104
|
*
|
|
@@ -599,6 +620,48 @@ export declare const DEFAULT_COMPACTION_CONFIG: CompactionConfig;
|
|
|
599
620
|
* gives `warnThreshold` a range of `[0.4, 0.45]`.
|
|
600
621
|
*/
|
|
601
622
|
export declare function clampCompactionConfig(raw: unknown): CompactionConfig;
|
|
623
|
+
export interface BashConfig {
|
|
624
|
+
/**
|
|
625
|
+
* Register `bash_output` / `bash_kill`, honour `background`, splice the prompt
|
|
626
|
+
* block, render the chip. Default TRUE.
|
|
627
|
+
*
|
|
628
|
+
* READ ONCE AT CONSTRUCTION, the `team.enabled` / `todo.enabled` /
|
|
629
|
+
* `fast.enabled` rule.
|
|
630
|
+
*
|
|
631
|
+
* IT GOVERNS *SERVICES*, NEVER *INTERRUPTIBILITY* (I-2 / D-9). `Esc`/`Esc`,
|
|
632
|
+
* the foreground child registry and `forceStop()` are unconditional, because
|
|
633
|
+
* "bash always settles" and "Esc twice always works" are promised
|
|
634
|
+
* unconditionally — a user who turned background services off has not asked
|
|
635
|
+
* for a less interruptible agent.
|
|
636
|
+
*/
|
|
637
|
+
background: boolean;
|
|
638
|
+
/**
|
|
639
|
+
* Let the classifier decide when the model did not say. Default TRUE.
|
|
640
|
+
*
|
|
641
|
+
* RESOLVES TO `false` WITHOUT AN INTERACTIVE VIEW (D-15 / P1-8), and that is
|
|
642
|
+
* decided at the tool layer rather than here: the value on disk is the user's
|
|
643
|
+
* preference, and headless has no card, no `/bg` and no user to keep a service
|
|
644
|
+
* alive, so the rescue would be a surprise instead. An explicit
|
|
645
|
+
* `background: true` is still honoured there — that one the model asked for.
|
|
646
|
+
*/
|
|
647
|
+
autoBackground: boolean;
|
|
648
|
+
/** How long a background launch may block the turn before returning. */
|
|
649
|
+
startupSettleMs: number;
|
|
650
|
+
/** How long a service may stay `starting` before it is called `running`. */
|
|
651
|
+
readyTimeoutMs: number;
|
|
652
|
+
}
|
|
653
|
+
export declare const DEFAULT_BASH_CONFIG: BashConfig;
|
|
654
|
+
/**
|
|
655
|
+
* THE single gate for every bash-config read AND write, mirroring
|
|
656
|
+
* `clampSkillsConfig` / `clampLogConfig` / `clampTeamConfig` / `clampTodoConfig`
|
|
657
|
+
* for the reason those record: hardening only the read path leaves a bad value
|
|
658
|
+
* on disk that reverts to the default on every launch, which presents to the
|
|
659
|
+
* user as "my setting won't stick".
|
|
660
|
+
*
|
|
661
|
+
* CLAMPED, NEVER REJECTED — the discipline every other key in this file follows.
|
|
662
|
+
* A garbage `startupSettleMs` resolves to 4000 and throws nothing.
|
|
663
|
+
*/
|
|
664
|
+
export declare function clampBashConfig(raw: unknown): BashConfig;
|
|
602
665
|
/**
|
|
603
666
|
* Parse `0.9`, `90%` or `90` into a ratio, or `null` when it is neither.
|
|
604
667
|
*
|
|
@@ -650,6 +713,18 @@ export interface PersistedConfig {
|
|
|
650
713
|
* `null`), which left the user no way to express "let the model decide".
|
|
651
714
|
*/
|
|
652
715
|
maxTokens: number | null;
|
|
716
|
+
/**
|
|
717
|
+
* The context window to measure occupancy against, or `null` for AUTO
|
|
718
|
+
* (context-usage-gauge-accuracy §3.6).
|
|
719
|
+
*
|
|
720
|
+
* `null` MEANS AUTO - the model table's window, or `buildRuntimeModel`'s 128k
|
|
721
|
+
* placeholder for a model the table has never seen. It exists because that
|
|
722
|
+
* placeholder is a FABRICATED denominator: on a custom `baseUrl` or an
|
|
723
|
+
* unlisted model id the gauge is a percentage of a number nobody supplied, and
|
|
724
|
+
* before this key there was no way to correct it. Setting it also removes the
|
|
725
|
+
* `?` marker from the absolute pair (I-6).
|
|
726
|
+
*/
|
|
727
|
+
contextWindow: number | null;
|
|
653
728
|
theme: ThemeName;
|
|
654
729
|
/** Replace spinners with a static glyph for calmer, low-motion output. */
|
|
655
730
|
reducedMotion: boolean;
|
|
@@ -702,6 +777,16 @@ export interface PersistedConfig {
|
|
|
702
777
|
* written at all, so `false` is byte-identical to a pre-feature session.
|
|
703
778
|
*/
|
|
704
779
|
mouseSelect: boolean;
|
|
780
|
+
/**
|
|
781
|
+
* Recognise pasted text and collapse a large paste into a placeholder
|
|
782
|
+
* (tui-paste-handling D-10 / section 7.3).
|
|
783
|
+
*
|
|
784
|
+
* A PLAIN BOOLEAN and the ONLY user-facing key this feature adds: the collapse
|
|
785
|
+
* threshold and every size bound are structural and live in `input/limits.ts`
|
|
786
|
+
* / `ui/composer-limits.ts`. A tunable threshold is a preference nobody has
|
|
787
|
+
* asked for; a kill switch is what a bug report needs.
|
|
788
|
+
*/
|
|
789
|
+
paste: boolean;
|
|
705
790
|
/** Idle ms before a paused viewport returns to the newest line; `0` disables. */
|
|
706
791
|
scrollResumeMs: number;
|
|
707
792
|
/** Start every session in PLAN mode (plan-mode §4.4). */
|
|
@@ -726,6 +811,8 @@ export interface PersistedConfig {
|
|
|
726
811
|
update: UpdateConfig;
|
|
727
812
|
/** Context compaction. The NINTH nested object; scalars only (see CompactionConfig). */
|
|
728
813
|
compaction: CompactionConfig;
|
|
814
|
+
/** Background services. The TENTH nested object; scalars only (see BashConfig). */
|
|
815
|
+
bash: BashConfig;
|
|
729
816
|
}
|
|
730
817
|
export declare const DEFAULT_CONFIG: PersistedConfig;
|
|
731
818
|
/**
|
|
@@ -781,6 +868,17 @@ export interface CliConfig {
|
|
|
781
868
|
liveToolOutput: boolean;
|
|
782
869
|
/** The resolved cap, or `undefined` for AUTO (per-model ceiling, ≤ 64000). */
|
|
783
870
|
maxTokens?: number;
|
|
871
|
+
/**
|
|
872
|
+
* The user's context-window override, or `null` for AUTO.
|
|
873
|
+
*
|
|
874
|
+
* IT MUST EXIST HERE AND NOT ONLY IN `PersistedConfig`, for the reason
|
|
875
|
+
* `showThinking` / `liveToolOutput` / `diffRender` each record above: the
|
|
876
|
+
* runtime reads `config.*`, where `config` is a `CliConfig`, so a key added to
|
|
877
|
+
* the persisted shape alone would round-trip through `config set`, appear in
|
|
878
|
+
* `config list` - and never reach `ContextMeter`. `ARAGON_CONTEXT_WINDOW`
|
|
879
|
+
* would parse and be discarded, with nothing failing.
|
|
880
|
+
*/
|
|
881
|
+
contextWindow: number | null;
|
|
784
882
|
theme: ThemeName;
|
|
785
883
|
reducedMotion: boolean;
|
|
786
884
|
/**
|
|
@@ -866,6 +964,17 @@ export interface CliConfig {
|
|
|
866
964
|
* `config list`, and never reach a single one of them.
|
|
867
965
|
*/
|
|
868
966
|
mouseSelect: boolean;
|
|
967
|
+
/**
|
|
968
|
+
* Whether this session recognises pastes at all.
|
|
969
|
+
*
|
|
970
|
+
* IT MUST EXIST HERE AND NOT ONLY IN `PersistedConfig`, for the reason
|
|
971
|
+
* `mouseSelect` above records: `runInteractive` reads `config.paste` -- where
|
|
972
|
+
* `config` is a `CliConfig` -- to decide the filter's `paste` feature, the
|
|
973
|
+
* `?2004h` write and the `PasteBridge`. A key added to the persisted shape
|
|
974
|
+
* alone would round-trip through `config set`, appear in `config list`, and
|
|
975
|
+
* reach none of them.
|
|
976
|
+
*/
|
|
977
|
+
paste: boolean;
|
|
869
978
|
/** Idle ms before a paused viewport returns to the newest line; `0` disables. */
|
|
870
979
|
scrollResumeMs: number;
|
|
871
980
|
/**
|
|
@@ -959,6 +1068,26 @@ export interface CliConfig {
|
|
|
959
1068
|
* reach either of them.
|
|
960
1069
|
*/
|
|
961
1070
|
compaction: CompactionConfig;
|
|
1071
|
+
/**
|
|
1072
|
+
* Resolved background-service settings (background-service-supervision §5.4).
|
|
1073
|
+
*
|
|
1074
|
+
* `background` here decides whether `bash`'s schema carries a `background`
|
|
1075
|
+
* property, whether `bash_output` / `bash_kill` are REGISTERED and whether
|
|
1076
|
+
* `<background_services>` is spliced — all three at construction, and none of
|
|
1077
|
+
* them undoable, the `team.enabled` / `todo.enabled` / `fast.enabled` rule.
|
|
1078
|
+
* The other three keys are read LIVE.
|
|
1079
|
+
*
|
|
1080
|
+
* IT DOES NOT GATE THE INTERRUPT LADDER (I-2 / D-9). `ProcSupervisor` is
|
|
1081
|
+
* constructed unconditionally, because `Esc`/`Esc` and the foreground registry
|
|
1082
|
+
* are what make G2 and G3 true and those are promised whatever this says.
|
|
1083
|
+
*
|
|
1084
|
+
* IT MUST EXIST HERE AND NOT ONLY IN `PersistedConfig`, for the reason every
|
|
1085
|
+
* section above records: the controller and `bash` read `config.bash`, where
|
|
1086
|
+
* `config` is a `CliConfig`, so a key added to the persisted shape alone would
|
|
1087
|
+
* round-trip through `config set`, appear in `config list` — and never reach
|
|
1088
|
+
* either of them.
|
|
1089
|
+
*/
|
|
1090
|
+
bash: BashConfig;
|
|
962
1091
|
/**
|
|
963
1092
|
* Lifetime submit count driving the composer hint fade (`HINT_FADE_AFTER`).
|
|
964
1093
|
*
|
package/dist/config/schema.js
CHANGED
|
@@ -115,6 +115,39 @@ export function clampTranscriptWindow(v, fallback) {
|
|
|
115
115
|
const n = coercePositiveInt(v, fallback);
|
|
116
116
|
return Math.min(MAX_TRANSCRIPT_WINDOW, Math.max(MIN_TRANSCRIPT_WINDOW, n));
|
|
117
117
|
}
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Context window override (context-usage-gauge-accuracy §3.6 / W5)
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
/**
|
|
122
|
+
* Bounds for a hand-supplied context window.
|
|
123
|
+
*
|
|
124
|
+
* The floor is roughly the smallest window any current model ships with; the
|
|
125
|
+
* ceiling is well above the largest, and both exist to keep a typo (a missing
|
|
126
|
+
* or an extra zero) from producing a gauge that is permanently red or
|
|
127
|
+
* permanently flat.
|
|
128
|
+
*/
|
|
129
|
+
export const MIN_CONTEXT_WINDOW = 8_000;
|
|
130
|
+
export const MAX_CONTEXT_WINDOW = 5_000_000;
|
|
131
|
+
/**
|
|
132
|
+
* THE single gate for every `contextWindow` read AND write.
|
|
133
|
+
*
|
|
134
|
+
* TRI-STATE, AND `null` MUST PASS STRAIGHT THROUGH (RV-12). `null` means AUTO -
|
|
135
|
+
* take the model table's number, or the 128k placeholder. Clamping it into
|
|
136
|
+
* `[8000, ...]` yields 8000, which removes "auto" from the config permanently
|
|
137
|
+
* and presents to the user as an 8k denominator with a permanently red bar and
|
|
138
|
+
* no visible source. `maxTokens` above is the existing tri-state precedent and
|
|
139
|
+
* this deliberately copies its shape rather than inventing a second convention.
|
|
140
|
+
*/
|
|
141
|
+
export function clampContextWindow(v, fallback) {
|
|
142
|
+
if (v === null)
|
|
143
|
+
return null;
|
|
144
|
+
if (v === undefined || v === '')
|
|
145
|
+
return fallback;
|
|
146
|
+
const n = typeof v === 'number' ? v : Number.parseInt(String(v), 10);
|
|
147
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
148
|
+
return fallback;
|
|
149
|
+
return Math.min(MAX_CONTEXT_WINDOW, Math.max(MIN_CONTEXT_WINDOW, Math.floor(n)));
|
|
150
|
+
}
|
|
118
151
|
/**
|
|
119
152
|
* Entries kept in `ViewState` at all (tui-render-performance L1 / R5).
|
|
120
153
|
*
|
|
@@ -777,6 +810,33 @@ export function clampCompactionConfig(raw) {
|
|
|
777
810
|
archive: bool(src.archive, DEFAULT_COMPACTION_CONFIG.archive),
|
|
778
811
|
};
|
|
779
812
|
}
|
|
813
|
+
export const DEFAULT_BASH_CONFIG = {
|
|
814
|
+
background: true,
|
|
815
|
+
autoBackground: true,
|
|
816
|
+
startupSettleMs: 4000,
|
|
817
|
+
readyTimeoutMs: 60_000,
|
|
818
|
+
};
|
|
819
|
+
const STARTUP_SETTLE_RANGE = { min: 500, max: 30_000 };
|
|
820
|
+
const READY_TIMEOUT_RANGE = { min: 5_000, max: 600_000 };
|
|
821
|
+
/**
|
|
822
|
+
* THE single gate for every bash-config read AND write, mirroring
|
|
823
|
+
* `clampSkillsConfig` / `clampLogConfig` / `clampTeamConfig` / `clampTodoConfig`
|
|
824
|
+
* for the reason those record: hardening only the read path leaves a bad value
|
|
825
|
+
* on disk that reverts to the default on every launch, which presents to the
|
|
826
|
+
* user as "my setting won't stick".
|
|
827
|
+
*
|
|
828
|
+
* CLAMPED, NEVER REJECTED — the discipline every other key in this file follows.
|
|
829
|
+
* A garbage `startupSettleMs` resolves to 4000 and throws nothing.
|
|
830
|
+
*/
|
|
831
|
+
export function clampBashConfig(raw) {
|
|
832
|
+
const src = (raw && typeof raw === 'object' ? raw : {});
|
|
833
|
+
return {
|
|
834
|
+
background: bool(src.background, DEFAULT_BASH_CONFIG.background),
|
|
835
|
+
autoBackground: bool(src.autoBackground, DEFAULT_BASH_CONFIG.autoBackground),
|
|
836
|
+
startupSettleMs: clampInt(src.startupSettleMs, DEFAULT_BASH_CONFIG.startupSettleMs, STARTUP_SETTLE_RANGE),
|
|
837
|
+
readyTimeoutMs: clampInt(src.readyTimeoutMs, DEFAULT_BASH_CONFIG.readyTimeoutMs, READY_TIMEOUT_RANGE),
|
|
838
|
+
};
|
|
839
|
+
}
|
|
780
840
|
/**
|
|
781
841
|
* Parse `0.9`, `90%` or `90` into a ratio, or `null` when it is neither.
|
|
782
842
|
*
|
|
@@ -814,6 +874,9 @@ export const DEFAULT_CONFIG = {
|
|
|
814
874
|
// The engine owns this number; spelling it here again is how the CLI and the
|
|
815
875
|
// provider adapters end up disagreeing about what "the default" is.
|
|
816
876
|
maxTokens: DEFAULT_MAX_OUTPUT_TOKENS,
|
|
877
|
+
// AUTO. The model table is right for every listed model, and a default number
|
|
878
|
+
// here would be the same fabricated denominator this key exists to correct.
|
|
879
|
+
contextWindow: null,
|
|
817
880
|
theme: 'auto',
|
|
818
881
|
reducedMotion: false,
|
|
819
882
|
fullscreen: true,
|
|
@@ -833,6 +896,7 @@ export const DEFAULT_CONFIG = {
|
|
|
833
896
|
hints: true,
|
|
834
897
|
mouse: true,
|
|
835
898
|
mouseSelect: DEFAULT_MOUSE_SELECT,
|
|
899
|
+
paste: true,
|
|
836
900
|
scrollResumeMs: DEFAULT_SCROLL_RESUME_MS,
|
|
837
901
|
planModeDefault: false,
|
|
838
902
|
planModeMaxAskRounds: DEFAULT_PLAN_MAX_ASK_ROUNDS,
|
|
@@ -865,6 +929,11 @@ export const DEFAULT_CONFIG = {
|
|
|
865
929
|
// arrive OFF for every existing user, which is the one direction this
|
|
866
930
|
// particular default must never fail in.
|
|
867
931
|
compaction: DEFAULT_COMPACTION_CONFIG,
|
|
932
|
+
// And one section later again, for the fifth time. `bash.background` is `true`
|
|
933
|
+
// by default, so a `config.json` predating this feature resolving it to
|
|
934
|
+
// `undefined` would arrive with background services OFF for every existing
|
|
935
|
+
// user — the same direction the compaction line above must never fail in.
|
|
936
|
+
bash: DEFAULT_BASH_CONFIG,
|
|
868
937
|
};
|
|
869
938
|
/**
|
|
870
939
|
* Runtime state that used to be stored in `config.json` by mistake
|
package/dist/config/store.js
CHANGED
|
@@ -14,7 +14,7 @@ import { dirname } from 'node:path';
|
|
|
14
14
|
import process from 'node:process';
|
|
15
15
|
import { getConfigPath, getSessionsDir } from './app-paths.js';
|
|
16
16
|
import { registerSecretsFrom } from '../logging/secret-registry.js';
|
|
17
|
-
import { CONFIG_VERSION, DEFAULT_CONFIG, clampCompactionConfig, clampFastConfig, clampLogConfig, clampMaxTokens, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampUpdateConfig, isAutoToken, stripLegacyStateKeys, } from './schema.js';
|
|
17
|
+
import { clampBashConfig, CONFIG_VERSION, DEFAULT_CONFIG, clampCompactionConfig, clampFastConfig, clampLogConfig, clampMaxTokens, clampRetryConfig, clampSkillsConfig, clampTeamConfig, clampTodoConfig, clampContextWindow, clampUpdateConfig, isAutoToken, stripLegacyStateKeys, } from './schema.js';
|
|
18
18
|
/**
|
|
19
19
|
* Normalize `maxTokens` for both directions of the config file.
|
|
20
20
|
*
|
|
@@ -31,6 +31,22 @@ function normalizeMaxTokens(v) {
|
|
|
31
31
|
return null;
|
|
32
32
|
return clampMaxTokens(v) ?? null;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Normalize `contextWindow` for both directions of the config file.
|
|
36
|
+
*
|
|
37
|
+
* THE SAME TRI-STATE DISCIPLINE AS `maxTokens` ABOVE, and for the same reason:
|
|
38
|
+
* hardening only the read path leaves a bad value on disk that reverts on every
|
|
39
|
+
* launch and presents as "my setting won't stick". `null` is AUTO and survives
|
|
40
|
+
* untouched; `auto` / `0` / an empty string mean AUTO too; a number is clamped;
|
|
41
|
+
* anything else on a hand-edited file becomes AUTO rather than a silent default.
|
|
42
|
+
*/
|
|
43
|
+
function normalizeContextWindow(v) {
|
|
44
|
+
if (v === undefined)
|
|
45
|
+
return DEFAULT_CONFIG.contextWindow;
|
|
46
|
+
if (v === null || isAutoToken(v))
|
|
47
|
+
return null;
|
|
48
|
+
return clampContextWindow(v, null);
|
|
49
|
+
}
|
|
34
50
|
// Re-exported so the many existing importers of `store.js` keep working; the
|
|
35
51
|
// definitions live in `app-paths.ts` because they are pure path arithmetic.
|
|
36
52
|
export { getConfigPath, getSessionsDir };
|
|
@@ -114,6 +130,11 @@ export function loadPersistedConfig() {
|
|
|
114
130
|
maxTokens: Object.prototype.hasOwnProperty.call(partial, 'maxTokens')
|
|
115
131
|
? normalizeMaxTokens(partial.maxTokens)
|
|
116
132
|
: DEFAULT_CONFIG.maxTokens,
|
|
133
|
+
// Own-property aware for the reason its neighbour records: `null` is AUTO
|
|
134
|
+
// and a spread cannot tell it from an absent key.
|
|
135
|
+
contextWindow: Object.prototype.hasOwnProperty.call(partial, 'contextWindow')
|
|
136
|
+
? normalizeContextWindow(partial.contextWindow)
|
|
137
|
+
: DEFAULT_CONFIG.contextWindow,
|
|
117
138
|
apiKeys: { ...DEFAULT_CONFIG.apiKeys, ...(partial.apiKeys ?? {}) },
|
|
118
139
|
// `skills` is the second nested object in this file and needs the same
|
|
119
140
|
// treatment `apiKeys` gets — see the note on updatePersistedConfig below.
|
|
@@ -148,6 +169,20 @@ export function loadPersistedConfig() {
|
|
|
148
169
|
...DEFAULT_CONFIG.compaction,
|
|
149
170
|
...(partial.compaction ?? {}),
|
|
150
171
|
}),
|
|
172
|
+
// `bash` is the tenth. Same one-level rule, same merge — and the READ half
|
|
173
|
+
// supplies a whole section to every user whose `config.json` predates
|
|
174
|
+
// background services, which is all of them. Without it
|
|
175
|
+
// `config.bash.background` reads `undefined`, which is FALSY, so a feature
|
|
176
|
+
// that is `true` by default would arrive off for every existing user.
|
|
177
|
+
//
|
|
178
|
+
// A SIBLING OF `compaction`, NOT A KEY INSIDE ITS ARGUMENT. Nesting it one
|
|
179
|
+
// level too deep type-checks — `...DEFAULT_CONFIG` above already supplies a
|
|
180
|
+
// `bash`, so nothing is missing from the return type — and hands
|
|
181
|
+
// `clampCompactionConfig` a key it drops on the floor. The section then
|
|
182
|
+
// reaches callers straight off the shallow `...partial` spread: unclamped,
|
|
183
|
+
// and NOT merged over the defaults, which is verbatim the failure the
|
|
184
|
+
// paragraph above says this line prevents.
|
|
185
|
+
bash: clampBashConfig({ ...DEFAULT_CONFIG.bash, ...(partial.bash ?? {}) }),
|
|
151
186
|
};
|
|
152
187
|
}
|
|
153
188
|
/**
|
|
@@ -184,6 +219,11 @@ export function updatePersistedConfig(patch) {
|
|
|
184
219
|
maxTokens: Object.prototype.hasOwnProperty.call(patch, 'maxTokens')
|
|
185
220
|
? normalizeMaxTokens(patch.maxTokens)
|
|
186
221
|
: current.maxTokens,
|
|
222
|
+
// The write half of the same gate: without it `config set contextWindow
|
|
223
|
+
// 99999999` puts a number on disk that the read path silently rewrites.
|
|
224
|
+
contextWindow: Object.prototype.hasOwnProperty.call(patch, 'contextWindow')
|
|
225
|
+
? normalizeContextWindow(patch.contextWindow)
|
|
226
|
+
: current.contextWindow,
|
|
187
227
|
apiKeys: { ...current.apiKeys, ...(patch.apiKeys ?? {}) },
|
|
188
228
|
skills: clampSkillsConfig({ ...current.skills, ...(patch.skills ?? {}) }),
|
|
189
229
|
// Without this line, changing the log level from the settings screen would
|
|
@@ -224,6 +264,12 @@ export function updatePersistedConfig(patch) {
|
|
|
224
264
|
// OFF finds it back on tomorrow — a feature that spends money on their behalf
|
|
225
265
|
// re-enabling itself because they nudged a threshold.
|
|
226
266
|
compaction: clampCompactionConfig({ ...current.compaction, ...(patch.compaction ?? {}) }),
|
|
267
|
+
// The tenth section, and the fifth time this file records the same trap.
|
|
268
|
+
// A patch carrying only `{ bash: { autoBackground: false } }` — turning the
|
|
269
|
+
// CLASSIFIER off — would, without this line, be spread shallowly over the
|
|
270
|
+
// top level and write `background` absent, silently unregistering
|
|
271
|
+
// `bash_output` / `bash_kill` from the next launch onward.
|
|
272
|
+
bash: clampBashConfig({ ...current.bash, ...(patch.bash ?? {}) }),
|
|
227
273
|
};
|
|
228
274
|
writeConfigFile(merged);
|
|
229
275
|
return merged;
|
package/dist/exec/events.d.ts
CHANGED
|
@@ -71,6 +71,43 @@ export interface ExecSystemInitEvent {
|
|
|
71
71
|
permissionMode: ExecPermissionMode;
|
|
72
72
|
tools: string[];
|
|
73
73
|
resumed: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Capabilities of THIS build that a caller has to know about before using
|
|
76
|
+
* them. Optional so older consumers are unaffected, and additive so
|
|
77
|
+
* `EXEC_SCHEMA_VERSION` does not move (see the file header).
|
|
78
|
+
*
|
|
79
|
+
* `'interrupt'` means the stdin `{"type":"interrupt"}` frame really does run
|
|
80
|
+
* the full settle -> persist -> `result` sequence ON EVERY PLATFORM. Builds
|
|
81
|
+
* before that fix routed it through a self-directed SIGINT, which on Windows
|
|
82
|
+
* terminates the process outright with exit code 1 - no persistence, no
|
|
83
|
+
* `result`. A wrapper cannot tell the two apart by observation, and guessing
|
|
84
|
+
* wrong costs the user their conversation, so this build states it.
|
|
85
|
+
*/
|
|
86
|
+
capabilities?: string[];
|
|
87
|
+
/**
|
|
88
|
+
* Absolute path of the session file THIS run reads and writes; `null` under
|
|
89
|
+
* `--no-save-session` (web-use-durable-control-and-tier-accountability W2).
|
|
90
|
+
*
|
|
91
|
+
* Optional and additive, so `EXEC_SCHEMA_VERSION` does not move (file header).
|
|
92
|
+
* Stamped by `buildInitEvent`, never set by a caller - the same discipline
|
|
93
|
+
* `capabilities` follows.
|
|
94
|
+
*
|
|
95
|
+
* ## Why a wrapper cannot work this out for itself
|
|
96
|
+
*
|
|
97
|
+
* Deriving it host-side means re-implementing `getSessionsDir()`
|
|
98
|
+
* (`envPaths('aragon-agent')` plus its environment override) in a second
|
|
99
|
+
* codebase that has no way to notice when this one changes. The failure mode
|
|
100
|
+
* of a drifted copy is a path that does not exist, which a wrapper reads as
|
|
101
|
+
* "that conversation is gone" - identical, on screen, to the session really
|
|
102
|
+
* being gone. The run that is writing the file is the only party that can say
|
|
103
|
+
* where it is without guessing.
|
|
104
|
+
*
|
|
105
|
+
* It is the id THIS RUN writes back under, not the string the caller typed:
|
|
106
|
+
* `--resume` accepts `<id|path>`, and `resumedSessionId()` decides what the
|
|
107
|
+
* file is actually called. A wrapper asking "can I reattach later" needs the
|
|
108
|
+
* latter.
|
|
109
|
+
*/
|
|
110
|
+
sessionFile?: string | null;
|
|
74
111
|
}
|
|
75
112
|
export interface ExecUserEvent {
|
|
76
113
|
type: 'user';
|
|
@@ -84,6 +121,22 @@ export interface ExecUserEvent {
|
|
|
84
121
|
*/
|
|
85
122
|
source: 'caller' | 'todo_continue';
|
|
86
123
|
}
|
|
124
|
+
/** One caller input and its complete automatic follow-through chain. */
|
|
125
|
+
export interface ExecTurnStateEvent {
|
|
126
|
+
type: 'turn_state';
|
|
127
|
+
sessionId: string;
|
|
128
|
+
requestSeq: number;
|
|
129
|
+
phase: 'started' | 'completed' | 'failed' | 'cancelled';
|
|
130
|
+
}
|
|
131
|
+
/** Semantic source progress; never includes model or tool content. */
|
|
132
|
+
export interface ExecProgressEvent {
|
|
133
|
+
type: 'execution_progress';
|
|
134
|
+
sessionId: string;
|
|
135
|
+
requestSeq: number;
|
|
136
|
+
progressSeq: number;
|
|
137
|
+
phase: 'model' | 'thinking' | 'tool_arguments' | 'tool' | 'compaction' | 'retry';
|
|
138
|
+
retryDelayMs?: number;
|
|
139
|
+
}
|
|
87
140
|
export interface ExecTextDeltaEvent {
|
|
88
141
|
type: 'text_delta';
|
|
89
142
|
sessionId: string;
|
|
@@ -157,6 +210,57 @@ export interface ExecFastReviewEvent {
|
|
|
157
210
|
model: string;
|
|
158
211
|
text: string;
|
|
159
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* What the fast tier is ACTUALLY doing, as opposed to what it was configured to
|
|
215
|
+
* do (web-use-tier-cooperation-and-control-closure W2).
|
|
216
|
+
*
|
|
217
|
+
* ONE ADDITIVE EVENT TYPE, AND `EXEC_SCHEMA_VERSION` DOES NOT MOVE — the same
|
|
218
|
+
* rule `ExecCompactionEvent` states. A consumer that ignores event types it does
|
|
219
|
+
* not know is unaffected.
|
|
220
|
+
*
|
|
221
|
+
* THE PROBLEM IT SOLVES. `fast_review` only fires when a review produced TEXT,
|
|
222
|
+
* so every other outcome — a review that failed, a tier that switched itself off
|
|
223
|
+
* after three failures, a budget that ran out, a delegation that did or did not
|
|
224
|
+
* happen — was invisible to a wrapper. The single most likely and least
|
|
225
|
+
* self-diagnosable failure ("it runs but not one review card ever arrives") had
|
|
226
|
+
* no signal at all on this stream.
|
|
227
|
+
*
|
|
228
|
+
* IT IS A STATE EVENT, NOT A LOG LINE. It fires on `tier_changed` and on every
|
|
229
|
+
* `review_end`, which in a session with reviews is a handful per hundred turns.
|
|
230
|
+
*/
|
|
231
|
+
export interface ExecFastTierEvent {
|
|
232
|
+
type: 'fast_tier';
|
|
233
|
+
sessionId: string;
|
|
234
|
+
/** Taken from the runner's own turn counter — `tier_changed` carries none. */
|
|
235
|
+
turn: number;
|
|
236
|
+
/** The tier resolved AND the live switch is on. */
|
|
237
|
+
live: boolean;
|
|
238
|
+
/**
|
|
239
|
+
* The CLI switched the fast REVIEWS off by itself after three consecutive
|
|
240
|
+
* non-transient failures.
|
|
241
|
+
*
|
|
242
|
+
* ORTHOGONAL TO `live` AND NOT DERIVABLE FROM IT: the self-disable leaves
|
|
243
|
+
* `live` at `true`. A consumer reporting "the reviews stopped" MUST read this
|
|
244
|
+
* field; `live === false && reviews > 0` is a predicate that can never be true.
|
|
245
|
+
*/
|
|
246
|
+
selfDisabled: boolean;
|
|
247
|
+
model: string;
|
|
248
|
+
sameAsMain: boolean;
|
|
249
|
+
reviews: number;
|
|
250
|
+
reviewBudget: number;
|
|
251
|
+
budgetReached: boolean;
|
|
252
|
+
/** Fast-tier children dispatched — the only evidence delegation is working. */
|
|
253
|
+
delegated: number;
|
|
254
|
+
inFlight: boolean;
|
|
255
|
+
/** Present only on the `review_end` branch. */
|
|
256
|
+
review?: {
|
|
257
|
+
index: number;
|
|
258
|
+
kind: 'ok' | 'advice' | 'empty' | 'failed' | 'dropped';
|
|
259
|
+
detail?: string;
|
|
260
|
+
durationMs: number;
|
|
261
|
+
injected: boolean;
|
|
262
|
+
};
|
|
263
|
+
}
|
|
160
264
|
/**
|
|
161
265
|
* Context compaction (context-auto-compaction §4.6).
|
|
162
266
|
*
|
|
@@ -251,7 +355,7 @@ export interface ExecResultEvent {
|
|
|
251
355
|
todos: ExecTodoCounts | null;
|
|
252
356
|
error: ExecErrorInfo | null;
|
|
253
357
|
}
|
|
254
|
-
export type ExecEvent = ExecSystemInitEvent | ExecUserEvent | ExecTextDeltaEvent | ExecThinkingEvent | ExecAssistantEvent | ExecToolCallEvent | ExecToolResultEvent | ExecTodoEvent | ExecTeamEvent | ExecFastReviewEvent | ExecCompactionEvent | ExecRetryEvent | ExecErrorEvent | ExecResultEvent;
|
|
358
|
+
export type ExecEvent = ExecSystemInitEvent | ExecUserEvent | ExecTurnStateEvent | ExecProgressEvent | ExecTextDeltaEvent | ExecThinkingEvent | ExecAssistantEvent | ExecToolCallEvent | ExecToolResultEvent | ExecTodoEvent | ExecTeamEvent | ExecFastReviewEvent | ExecFastTierEvent | ExecCompactionEvent | ExecRetryEvent | ExecErrorEvent | ExecResultEvent;
|
|
255
359
|
/** Everything `system/init` needs that the runner cannot derive for itself. */
|
|
256
360
|
export interface ExecInitParams {
|
|
257
361
|
sessionId: string;
|
|
@@ -266,7 +370,40 @@ export interface ExecInitParams {
|
|
|
266
370
|
permissionMode: ExecPermissionMode;
|
|
267
371
|
tools: string[];
|
|
268
372
|
resumed: boolean;
|
|
373
|
+
/**
|
|
374
|
+
* Absolute path of the session file this run reads and writes; `null` under
|
|
375
|
+
* `--no-save-session`. See `ExecSystemInitEvent.sessionFile`.
|
|
376
|
+
*/
|
|
377
|
+
sessionFile?: string | null;
|
|
269
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* What this build announces in `system/init`.
|
|
381
|
+
*
|
|
382
|
+
* Stamped by `buildInitEvent`, never by a caller - the same discipline as
|
|
383
|
+
* `schemaVersion`. A caller that could set it could claim a capability the
|
|
384
|
+
* binary does not have, which is precisely the mistake the field exists to
|
|
385
|
+
* prevent.
|
|
386
|
+
*/
|
|
387
|
+
/**
|
|
388
|
+
* APPEND ONLY, NEVER REORDER. Consumers use `includes()`, but the next one may
|
|
389
|
+
* not; inserting ahead of `'interrupt'` costs nothing and makes a diff look
|
|
390
|
+
* bigger than it is.
|
|
391
|
+
*
|
|
392
|
+
* · `'interrupt'` — `{"type":"interrupt"}` on stdin settles the turn
|
|
393
|
+
* without killing the process.
|
|
394
|
+
* · `'fast-policy'` — this build understands `--fast-delegate` and
|
|
395
|
+
* `--fast-review`. FOR AFTER-THE-FACT DISPLAY ONLY:
|
|
396
|
+
* argv is fixed before `system/init` arrives, so it
|
|
397
|
+
* cannot gate whether the flags are passed.
|
|
398
|
+
* · `'fast-tier-events'` — this build emits `fast_tier`. Its ABSENCE is what
|
|
399
|
+
* lets a wrapper say "this CLI does not report" and
|
|
400
|
+
* not "the fast tier did nothing" — two very
|
|
401
|
+
* different sentences to a user.
|
|
402
|
+
* · `'session-file'` — `system/init` carries `sessionFile`, so a wrapper
|
|
403
|
+
* can check on disk whether a stopped conversation
|
|
404
|
+
* is still resumable instead of guessing the path.
|
|
405
|
+
*/
|
|
406
|
+
export declare const EXEC_CAPABILITIES: readonly string[];
|
|
270
407
|
export declare function buildInitEvent(params: ExecInitParams): ExecSystemInitEvent;
|
|
271
408
|
/** Everything `result` needs. `schemaVersion` is stamped here, never by a caller. */
|
|
272
409
|
export type ExecResultParams = Omit<ExecResultEvent, 'type' | 'schemaVersion'>;
|
package/dist/exec/events.js
CHANGED
|
@@ -19,6 +19,41 @@
|
|
|
19
19
|
* additive change and every wrapper would pin an exact number forever.
|
|
20
20
|
*/
|
|
21
21
|
export const EXEC_SCHEMA_VERSION = 1;
|
|
22
|
+
/**
|
|
23
|
+
* What this build announces in `system/init`.
|
|
24
|
+
*
|
|
25
|
+
* Stamped by `buildInitEvent`, never by a caller - the same discipline as
|
|
26
|
+
* `schemaVersion`. A caller that could set it could claim a capability the
|
|
27
|
+
* binary does not have, which is precisely the mistake the field exists to
|
|
28
|
+
* prevent.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* APPEND ONLY, NEVER REORDER. Consumers use `includes()`, but the next one may
|
|
32
|
+
* not; inserting ahead of `'interrupt'` costs nothing and makes a diff look
|
|
33
|
+
* bigger than it is.
|
|
34
|
+
*
|
|
35
|
+
* · `'interrupt'` — `{"type":"interrupt"}` on stdin settles the turn
|
|
36
|
+
* without killing the process.
|
|
37
|
+
* · `'fast-policy'` — this build understands `--fast-delegate` and
|
|
38
|
+
* `--fast-review`. FOR AFTER-THE-FACT DISPLAY ONLY:
|
|
39
|
+
* argv is fixed before `system/init` arrives, so it
|
|
40
|
+
* cannot gate whether the flags are passed.
|
|
41
|
+
* · `'fast-tier-events'` — this build emits `fast_tier`. Its ABSENCE is what
|
|
42
|
+
* lets a wrapper say "this CLI does not report" and
|
|
43
|
+
* not "the fast tier did nothing" — two very
|
|
44
|
+
* different sentences to a user.
|
|
45
|
+
* · `'session-file'` — `system/init` carries `sessionFile`, so a wrapper
|
|
46
|
+
* can check on disk whether a stopped conversation
|
|
47
|
+
* is still resumable instead of guessing the path.
|
|
48
|
+
*/
|
|
49
|
+
export const EXEC_CAPABILITIES = [
|
|
50
|
+
'interrupt',
|
|
51
|
+
'fast-policy',
|
|
52
|
+
'fast-tier-events',
|
|
53
|
+
'session-file',
|
|
54
|
+
'turn-lifecycle',
|
|
55
|
+
'execution-progress',
|
|
56
|
+
];
|
|
22
57
|
export function buildInitEvent(params) {
|
|
23
58
|
return {
|
|
24
59
|
type: 'system',
|
|
@@ -32,6 +67,13 @@ export function buildInitEvent(params) {
|
|
|
32
67
|
permissionMode: params.permissionMode,
|
|
33
68
|
tools: params.tools,
|
|
34
69
|
resumed: params.resumed,
|
|
70
|
+
capabilities: [...EXEC_CAPABILITIES],
|
|
71
|
+
// `?? null` rather than a conditional spread: the field's contract is
|
|
72
|
+
// three-valued for a CONSUMER (`undefined` = an old build that cannot say,
|
|
73
|
+
// `null` = this run saves nothing, a string = here it is), and omitting it
|
|
74
|
+
// when a caller passed nothing would make this build indistinguishable from
|
|
75
|
+
// one that predates the field.
|
|
76
|
+
sessionFile: params.sessionFile ?? null,
|
|
35
77
|
};
|
|
36
78
|
}
|
|
37
79
|
export function buildResultEvent(params) {
|