@songsid/agend 2.1.9 → 2.1.10-beta.2
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/README.md +8 -3
- package/README.zh-TW.md +11 -5
- package/dist/backend/antigravity.js +2 -1
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/codex.d.ts +13 -0
- package/dist/backend/codex.js +74 -2
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/kiro.d.ts +81 -5
- package/dist/backend/kiro.js +370 -36
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +10 -0
- package/dist/backend/types.js +13 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/telegram.js +4 -3
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/ipc-bridge.js +10 -3
- package/dist/channel/ipc-bridge.js.map +1 -1
- package/dist/channel/mcp-operation-response.js +5 -4
- package/dist/channel/mcp-operation-response.js.map +1 -1
- package/dist/channel/mcp-server.d.ts +1 -8
- package/dist/channel/mcp-server.js +10 -0
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/types.d.ts +7 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +93 -10
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +13 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +26 -0
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +68 -0
- package/dist/daemon.js +211 -27
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.js +18 -23
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/fleet-manager.d.ts +59 -1
- package/dist/fleet-manager.js +208 -35
- package/dist/fleet-manager.js.map +1 -1
- package/dist/forged-envelope-scan.js +2 -5
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -1
- package/dist/instance-lifecycle.d.ts +25 -5
- package/dist/instance-lifecycle.js +68 -33
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/locale.js +174 -4
- package/dist/locale.js.map +1 -1
- package/dist/logger.js +19 -16
- package/dist/logger.js.map +1 -1
- package/dist/login-controller.d.ts +38 -0
- package/dist/login-controller.js +227 -6
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.d.ts +7 -0
- package/dist/login-flows.js +1 -0
- package/dist/login-flows.js.map +1 -1
- package/dist/muse-usage-relay.js +3 -2
- package/dist/muse-usage-relay.js.map +1 -1
- package/dist/node-warnings.d.ts +1 -0
- package/dist/node-warnings.js +26 -0
- package/dist/node-warnings.js.map +1 -0
- package/dist/outbound-handlers.js +14 -16
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/pause-marker.js +3 -2
- package/dist/pause-marker.js.map +1 -1
- package/dist/private-dir.d.ts +54 -0
- package/dist/private-dir.js +140 -0
- package/dist/private-dir.js.map +1 -0
- package/dist/routing-engine.d.ts +17 -2
- package/dist/routing-engine.js +48 -5
- package/dist/routing-engine.js.map +1 -1
- package/dist/service-installer.d.ts +46 -0
- package/dist/service-installer.js +224 -4
- package/dist/service-installer.js.map +1 -1
- package/dist/setup-wizard.js +3 -1
- package/dist/setup-wizard.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +23 -5
- package/dist/tunnel/cloudflared.js +32 -13
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/manager.d.ts +6 -0
- package/dist/tunnel/manager.js +60 -22
- package/dist/tunnel/manager.js.map +1 -1
- package/dist/tunnel/public-fetch.d.ts +30 -0
- package/dist/tunnel/public-fetch.js +156 -0
- package/dist/tunnel/public-fetch.js.map +1 -0
- package/dist/tunnel/types.d.ts +8 -2
- package/dist/tunnel/types.js +8 -2
- package/dist/tunnel/types.js.map +1 -1
- package/dist/types.d.ts +24 -0
- package/dist/ui/settings.html +2 -2
- package/dist/ui/view.html +14 -0
- package/dist/ui/web-terminal/terminal.html +1 -0
- package/dist/wake-coordinator.d.ts +0 -15
- package/dist/wake-coordinator.js +19 -3
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-host-guard.d.ts +47 -0
- package/dist/web-host-guard.js +75 -0
- package/dist/web-host-guard.js.map +1 -0
- package/dist/web-terminal-http.d.ts +34 -0
- package/dist/web-terminal-http.js +63 -0
- package/dist/web-terminal-http.js.map +1 -1
- package/package.json +1 -1
- package/templates/systemd.service.ejs +17 -1
package/dist/backend/kiro.d.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { type CliBackend, type CliBackendConfig, type ErrorPattern, type StartupDialog, type RuntimeDialog } from "./types.js";
|
|
2
|
-
export declare const KIRO_REQUIRE_MCP_MIN = "1.25.0";
|
|
3
2
|
export declare const KIRO_LEGACY_UI_MIN = "1.27.0";
|
|
4
3
|
export declare const KIRO_EFFORT_FLAG_MIN = "2.6.0";
|
|
4
|
+
/** Oldest kiro-cli AgEnD claims: older ones still launch, with a warning. */
|
|
5
|
+
export declare const KIRO_SUPPORTED_MIN = "2.21.0";
|
|
6
|
+
/**
|
|
7
|
+
* Newest kiro-cli run live under AgEnD. Above it the launch flags come from
|
|
8
|
+
* the binary's own --help instead of the version table, and the operator is
|
|
9
|
+
* told the version is unverified.
|
|
10
|
+
*/
|
|
11
|
+
export declare const KIRO_TESTED_MAX = "2.27.0";
|
|
5
12
|
export interface KiroCliCompatibility {
|
|
6
13
|
version?: string;
|
|
7
|
-
supportsRequireMcpStartup: boolean;
|
|
8
14
|
supportsLegacyUi: boolean;
|
|
15
|
+
supportsTui: boolean;
|
|
16
|
+
/** `--v3` exists, i.e. this binary has an engine AgEnD must not drift into. */
|
|
17
|
+
supportsV3: boolean;
|
|
18
|
+
/** Values `--agent-engine` accepts; null when the flag does not exist. */
|
|
19
|
+
agentEngines: readonly string[] | null;
|
|
9
20
|
supportsEffortFlag: boolean;
|
|
10
21
|
source: "version" | "help" | "unknown";
|
|
11
22
|
}
|
|
@@ -19,8 +30,61 @@ type KiroProbeRunner = (binaryPath: string, args: string[]) => string;
|
|
|
19
30
|
* AgEnD must not pick a replacement on the user's behalf.
|
|
20
31
|
*/
|
|
21
32
|
export declare function kiroUnavailableModelPickerActive(pane: string): boolean;
|
|
22
|
-
|
|
33
|
+
interface KiroLaunchPromptSpec {
|
|
34
|
+
/** Text that identifies the prompt; the LAST occurrence heads it. */
|
|
35
|
+
header: string;
|
|
36
|
+
/** Option labels, in screen order (matched as a row prefix). */
|
|
37
|
+
options: readonly string[];
|
|
38
|
+
}
|
|
39
|
+
export interface KiroLaunchPromptState {
|
|
40
|
+
/** The prompt is the current interactive region of the pane. */
|
|
41
|
+
active: boolean;
|
|
42
|
+
/** Index into `options` of the one row with a recognised cursor; null = unknown. */
|
|
43
|
+
cursor: number | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Whether a kiro launch prompt owns the pane right now, and where its cursor
|
|
47
|
+
* is. Bottom-anchored on purpose: below the header come only its description,
|
|
48
|
+
* then exactly its option rows in order, then at most a short key-hint footer.
|
|
49
|
+
* A quoted copy of the prompt in a transcript has the reply and the composer
|
|
50
|
+
* row (`12% !>`) below it, so it is not active and never receives a key.
|
|
51
|
+
*
|
|
52
|
+
* The cursor is known only when exactly one option row carries a glyph AgEnD
|
|
53
|
+
* recognises; any other glyph, none, or two is "unknown" — still active, so
|
|
54
|
+
* it is held for a human, never answered.
|
|
55
|
+
*/
|
|
56
|
+
export declare function kiroLaunchPromptState(pane: string, spec: KiroLaunchPromptSpec): KiroLaunchPromptState;
|
|
57
|
+
/**
|
|
58
|
+
* The values `chat --help` lists for --agent-engine, or null without the flag.
|
|
59
|
+
* clap prints them as `[possible values: v2, v1, v3]` a few lines below the
|
|
60
|
+
* flag; the quoted names in its description are the fallback.
|
|
61
|
+
*/
|
|
62
|
+
export declare function parseKiroAgentEngines(help: string): string[] | null;
|
|
63
|
+
/**
|
|
64
|
+
* Probe once per binary generation. A version AgEnD has run (<= TESTED_MAX)
|
|
65
|
+
* is answered from the table without a second CLI call; anything newer, or a
|
|
66
|
+
* version string that does not parse, is answered by the binary's own
|
|
67
|
+
* `chat --help` — 3.0 included, which is exactly where the table stops being
|
|
68
|
+
* evidence.
|
|
69
|
+
*/
|
|
23
70
|
export declare function probeKiroCliCompatibility(binaryPath: string, run?: KiroProbeRunner): KiroCliCompatibility;
|
|
71
|
+
export type KiroLaunchPlan = {
|
|
72
|
+
kind: "launch";
|
|
73
|
+
ui: "legacy" | "tui" | "v3";
|
|
74
|
+
flags: string[];
|
|
75
|
+
} | {
|
|
76
|
+
kind: "refuse";
|
|
77
|
+
reason: string;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Pin the UI AND the engine on every launch (#1109). A flag outranks kiro's
|
|
81
|
+
* persisted `chat.agentEngine`, which the V3 ease-in prompt writes for the
|
|
82
|
+
* whole machine and which kiro 3.0 may default to V3. An instance's
|
|
83
|
+
* conversation lives in its engine's store — classic sqlite, V2 JSON, V3 KAS —
|
|
84
|
+
* and moving between them forks it one way, so a launch AgEnD cannot pin to
|
|
85
|
+
* the instance's own engine is refused, never run on whatever kiro defaults to.
|
|
86
|
+
*/
|
|
87
|
+
export declare function planKiroLaunch(ui: "legacy" | "tui" | "v3", compat: KiroCliCompatibility): KiroLaunchPlan;
|
|
24
88
|
/** Process-level memo used by backend construction; exported for regression tests. */
|
|
25
89
|
export declare function getCachedKiroCliCompatibility(binaryPath: string, run?: KiroProbeRunner): KiroCliCompatibility;
|
|
26
90
|
/** Test-only reset for the process-level compatibility and warning memo. */
|
|
@@ -31,8 +95,10 @@ export declare class KiroBackend implements CliBackend {
|
|
|
31
95
|
private instanceDir;
|
|
32
96
|
readonly binaryName = "kiro-cli";
|
|
33
97
|
private binaryPath;
|
|
34
|
-
private
|
|
35
|
-
private
|
|
98
|
+
private compatibility;
|
|
99
|
+
private compatibilityCacheKey?;
|
|
100
|
+
/** Injected by tests: never re-probed. */
|
|
101
|
+
private readonly fixedCompatibility;
|
|
36
102
|
private warnedUnsupportedEffort;
|
|
37
103
|
/**
|
|
38
104
|
* UI flavour and trust mode of the LAST command built. The Enter-drop
|
|
@@ -44,6 +110,8 @@ export declare class KiroBackend implements CliBackend {
|
|
|
44
110
|
*/
|
|
45
111
|
private activeUi;
|
|
46
112
|
private activeTrustAll;
|
|
113
|
+
/** Version-gate notice for the launch just built (consumeLaunchWarning). */
|
|
114
|
+
private launchWarning;
|
|
47
115
|
constructor(instanceDir: string, compatibility?: KiroCliCompatibility);
|
|
48
116
|
requiresDeliveryEnterRetry(): boolean;
|
|
49
117
|
dropsEnterWhileBusy(): boolean;
|
|
@@ -69,6 +137,14 @@ export declare class KiroBackend implements CliBackend {
|
|
|
69
137
|
* launched before this existed.
|
|
70
138
|
*/
|
|
71
139
|
private withCredentialProfile;
|
|
140
|
+
/**
|
|
141
|
+
* P3 of #1109: tell the operator, once per binary generation, when the
|
|
142
|
+
* kiro-cli in use is outside the range AgEnD has run. Never blocks a launch:
|
|
143
|
+
* below KIRO_SUPPORTED_MIN it still works, and above KIRO_TESTED_MAX the
|
|
144
|
+
* flags were already checked against the binary's own --help.
|
|
145
|
+
*/
|
|
146
|
+
private noteVersionGate;
|
|
147
|
+
consumeLaunchWarning(): string | null;
|
|
72
148
|
private shouldWarnUnsupportedEffort;
|
|
73
149
|
writeConfig(config: CliBackendConfig): void;
|
|
74
150
|
getReadyPattern(): RegExp;
|
package/dist/backend/kiro.js
CHANGED
|
@@ -3,27 +3,43 @@ import { getAgendHome } from "../paths.js";
|
|
|
3
3
|
import { credentialHomeSpec, credentialProfileHome, prepareCredentialProfileHome, resolveCredentialProfile, } from "./credential-profile.js";
|
|
4
4
|
import { execFileSync } from "node:child_process";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync, unlinkSync, statSync } from "node:fs";
|
|
6
|
-
import { resolveBinary, shellQuote, validateEffort, validateModel, warnIfModelMismatch } from "./types.js";
|
|
6
|
+
import { UnsupportedCliError, resolveBinary, shellQuote, validateEffort, validateModel, warnIfModelMismatch } from "./types.js";
|
|
7
7
|
import { PIE_CLASS } from "../tui-glyphs.js";
|
|
8
8
|
import { KIRO_EXPIRED_LOGIN_SCREEN } from "../login-flows.js";
|
|
9
|
+
import { t } from "../locale.js";
|
|
9
10
|
// Kiro CLI feature gates. These are deliberately separate: the flags shipped
|
|
10
11
|
// in different releases, so one broad "old Kiro" check would still crash some
|
|
11
|
-
// supported versions with an unknown argument.
|
|
12
|
-
//
|
|
13
|
-
// - 1.27.0:
|
|
14
|
-
//
|
|
12
|
+
// supported versions with an unknown argument. Every row below was read from
|
|
13
|
+
// `chat --help` of the archived release binary (tests/fixtures/kiro-help/).
|
|
14
|
+
// - 1.27.0: --tui / --legacy-ui. Before this, classic was the only UI and
|
|
15
|
+
// neither --legacy-ui nor --classic existed.
|
|
16
|
+
// - 2.3.0: --agent-engine, but its values were `rust` (default) | `kas`:
|
|
17
|
+
// `--agent-engine=v1` exits 2 there.
|
|
18
|
+
// - 2.4.0: --agent-engine v1|v2|kas, and `--legacy-ui` only with v1.
|
|
15
19
|
// - 2.6.0: https://kiro.dev/changelog/cli/2-6/ (initial effort flag)
|
|
16
|
-
|
|
20
|
+
// - 2.8.0: --agent-engine v1|v2|v3, plus --v3.
|
|
17
21
|
export const KIRO_LEGACY_UI_MIN = "1.27.0";
|
|
18
22
|
export const KIRO_EFFORT_FLAG_MIN = "2.6.0";
|
|
23
|
+
/** Oldest kiro-cli AgEnD claims: older ones still launch, with a warning. */
|
|
24
|
+
export const KIRO_SUPPORTED_MIN = "2.21.0";
|
|
25
|
+
/**
|
|
26
|
+
* Newest kiro-cli run live under AgEnD. Above it the launch flags come from
|
|
27
|
+
* the binary's own --help instead of the version table, and the operator is
|
|
28
|
+
* told the version is unverified.
|
|
29
|
+
*/
|
|
30
|
+
export const KIRO_TESTED_MAX = "2.27.0";
|
|
19
31
|
const UNKNOWN_KIRO_COMPATIBILITY = {
|
|
20
|
-
supportsRequireMcpStartup: false,
|
|
21
32
|
supportsLegacyUi: false,
|
|
33
|
+
supportsTui: false,
|
|
34
|
+
supportsV3: false,
|
|
35
|
+
agentEngines: null,
|
|
22
36
|
supportsEffortFlag: false,
|
|
23
37
|
source: "unknown",
|
|
24
38
|
};
|
|
25
39
|
const compatibilityCache = new Map();
|
|
26
40
|
const warnedUnsupportedEffortCacheKeys = new Set();
|
|
41
|
+
/** Binary generations whose version-gate warning already went out. */
|
|
42
|
+
const warnedVersionGateCacheKeys = new Set();
|
|
27
43
|
/**
|
|
28
44
|
* A picker may change its model labels or credit wording between Kiro releases.
|
|
29
45
|
* This broad test is only a safety hold: it must never select an option or
|
|
@@ -127,6 +143,123 @@ export function kiroUnavailableModelPickerActive(pane) {
|
|
|
127
143
|
}
|
|
128
144
|
return cursorCount === 1 && modelCount >= 1;
|
|
129
145
|
}
|
|
146
|
+
const KIRO_PROMPT_CURSOR = /^[❯›>]$/;
|
|
147
|
+
const KIRO_PROMPT_FOOTER = /navigate|select|↑|↓|\benter\b|\besc\b/i;
|
|
148
|
+
/**
|
|
149
|
+
* Whether a kiro launch prompt owns the pane right now, and where its cursor
|
|
150
|
+
* is. Bottom-anchored on purpose: below the header come only its description,
|
|
151
|
+
* then exactly its option rows in order, then at most a short key-hint footer.
|
|
152
|
+
* A quoted copy of the prompt in a transcript has the reply and the composer
|
|
153
|
+
* row (`12% !>`) below it, so it is not active and never receives a key.
|
|
154
|
+
*
|
|
155
|
+
* The cursor is known only when exactly one option row carries a glyph AgEnD
|
|
156
|
+
* recognises; any other glyph, none, or two is "unknown" — still active, so
|
|
157
|
+
* it is held for a human, never answered.
|
|
158
|
+
*/
|
|
159
|
+
export function kiroLaunchPromptState(pane, spec) {
|
|
160
|
+
const none = { active: false, cursor: null };
|
|
161
|
+
const rows = pane.replace(/\r/g, "").split("\n").map(row => row.replace(/\s+$/, ""));
|
|
162
|
+
let header = -1;
|
|
163
|
+
for (let i = rows.length - 1; i >= 0; i--) {
|
|
164
|
+
if (rows[i].includes(spec.header)) {
|
|
165
|
+
header = i;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (header < 0)
|
|
170
|
+
return none;
|
|
171
|
+
const body = rows.slice(header + 1);
|
|
172
|
+
const optionRow = (row, label) => {
|
|
173
|
+
const match = /^\s*(?:(\S)\s+)?(.*)$/.exec(row);
|
|
174
|
+
if (match && match[2].startsWith(label))
|
|
175
|
+
return { glyph: match[1] ?? null };
|
|
176
|
+
// No glyph: the label itself starts the row.
|
|
177
|
+
return row.trim().startsWith(label) ? { glyph: null } : null;
|
|
178
|
+
};
|
|
179
|
+
const first = body.findIndex(row => optionRow(row, spec.options[0]) !== null);
|
|
180
|
+
if (first < 0)
|
|
181
|
+
return none;
|
|
182
|
+
// A composer row anywhere below the header — before the options or after
|
|
183
|
+
// them — means this is quoted history with the input box back on screen.
|
|
184
|
+
// Checked before the footer test, whose keywords (enter/select/esc) a
|
|
185
|
+
// composer line can contain.
|
|
186
|
+
if (body.some(row => KIRO_COMPOSER_ROW.test(row)))
|
|
187
|
+
return none;
|
|
188
|
+
const optionRows = body.slice(first).filter(row => row.trim());
|
|
189
|
+
if (optionRows.length < spec.options.length)
|
|
190
|
+
return none;
|
|
191
|
+
const glyphs = [];
|
|
192
|
+
for (let i = 0; i < spec.options.length; i++) {
|
|
193
|
+
const hit = optionRow(optionRows[i], spec.options[i]);
|
|
194
|
+
if (!hit)
|
|
195
|
+
return none;
|
|
196
|
+
glyphs.push(hit.glyph);
|
|
197
|
+
}
|
|
198
|
+
const trailing = optionRows.slice(spec.options.length);
|
|
199
|
+
if (trailing.length > 2 || !trailing.every(row => KIRO_PROMPT_FOOTER.test(row)))
|
|
200
|
+
return none;
|
|
201
|
+
const marked = glyphs.map((g, i) => (g !== null ? i : -1)).filter(i => i >= 0);
|
|
202
|
+
if (marked.length !== 1 || !KIRO_PROMPT_CURSOR.test(glyphs[marked[0]]))
|
|
203
|
+
return { active: true, cursor: null };
|
|
204
|
+
return { active: true, cursor: marked[0] };
|
|
205
|
+
}
|
|
206
|
+
/** kiro's input row: legacy `12% !>` / `[agent] 3% λ !>`, or a bare `>`/`❯`. */
|
|
207
|
+
const KIRO_COMPOSER_ROW = /^\s*(?:\[[^\]]*\]\s*)?\d+%\s*\S{0,2}\s*!?\s*[❯>]|^\s*[!❯>]\s*$/;
|
|
208
|
+
/**
|
|
209
|
+
* Launch prompts that would move an instance off its engine (#1109). Text
|
|
210
|
+
* from the kiro-cli 2.27.0 binary (crates/chat-cli/src/launch/v3_ease_in.rs,
|
|
211
|
+
* auto_migrate.rs); not yet seen live — the V3 prompt is offered to 25% of
|
|
212
|
+
* internal users only.
|
|
213
|
+
*
|
|
214
|
+
* The first option of each is the one that switches, so it is never confirmed:
|
|
215
|
+
* a cursor verified on it gets ONE Down, and only a later capture that shows
|
|
216
|
+
* the cursor on the option that changes nothing gets Enter. Anything else —
|
|
217
|
+
* an unrecognised cursor, "Don't ask again" (saved for the whole machine), or
|
|
218
|
+
* a Down that did not move the cursor — is held for a human: deliveries stay
|
|
219
|
+
* blocked and the parked-dialog report fires.
|
|
220
|
+
*/
|
|
221
|
+
const KIRO_V3_EASE_IN = {
|
|
222
|
+
header: "CLI 3.0 is becoming the default experience",
|
|
223
|
+
options: ["Switch to 3.0 and upgrade my configs", "Remind me later", "Don't ask again"],
|
|
224
|
+
};
|
|
225
|
+
const KIRO_AGENT_UPGRADE = {
|
|
226
|
+
header: "Your agent configs are still in the 2.0 format",
|
|
227
|
+
options: ["Enable auto-upgrade", "Not now"],
|
|
228
|
+
};
|
|
229
|
+
function kiroLaunchPromptDialogs(spec, name, key, keep) {
|
|
230
|
+
const pattern = new RegExp(spec.header.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
231
|
+
const state = (pane) => kiroLaunchPromptState(pane, spec);
|
|
232
|
+
const guarded = { pattern, blocksDelivery: true, inputBlocked: true, verifyAfterKeys: true };
|
|
233
|
+
return [
|
|
234
|
+
{
|
|
235
|
+
...guarded,
|
|
236
|
+
keys: ["Down"],
|
|
237
|
+
description: `${name} — cursor on '${spec.options[0]}': one step down`,
|
|
238
|
+
isActive: pane => { const s = state(pane); return s.active && s.cursor === 0; },
|
|
239
|
+
autoResolutionKey: `${key}-step`,
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
...guarded,
|
|
243
|
+
keys: ["Enter"],
|
|
244
|
+
description: `${name} — confirm '${spec.options[keep]}'`,
|
|
245
|
+
isActive: pane => { const s = state(pane); return s.active && s.cursor === keep; },
|
|
246
|
+
autoResolutionKey: `${key}-confirm`,
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
pattern,
|
|
250
|
+
keys: [],
|
|
251
|
+
holdOnly: true,
|
|
252
|
+
blocksDelivery: true,
|
|
253
|
+
inputBlocked: true,
|
|
254
|
+
description: `${name} — not on a choice AgEnD can make safely; holding for a human`,
|
|
255
|
+
isActive: pane => state(pane).active,
|
|
256
|
+
},
|
|
257
|
+
];
|
|
258
|
+
}
|
|
259
|
+
const KIRO_ENGINE_PROMPT_DIALOGS = [
|
|
260
|
+
...kiroLaunchPromptDialogs(KIRO_V3_EASE_IN, "Kiro V3 ease-in prompt", "kiro-v3-ease-in", 1),
|
|
261
|
+
...kiroLaunchPromptDialogs(KIRO_AGENT_UPGRADE, "Kiro 3.0 agent-config upgrade prompt", "kiro-agent-upgrade", 1),
|
|
262
|
+
];
|
|
130
263
|
function parseSemver(value) {
|
|
131
264
|
const match = value?.match(/\b(\d+)\.(\d+)\.(\d+)\b/);
|
|
132
265
|
if (!match)
|
|
@@ -142,9 +275,83 @@ function versionAtLeast(version, minimum) {
|
|
|
142
275
|
return true;
|
|
143
276
|
}
|
|
144
277
|
function helpAdvertisesFlag(help, flag) {
|
|
145
|
-
|
|
278
|
+
// clap prints a short alias first when there is one: ` -r, --resume`.
|
|
279
|
+
return new RegExp(`^\\s*(?:-[A-Za-z0-9],\\s*)?${flag}(?:[ =<,]|$)`, "m").test(help);
|
|
146
280
|
}
|
|
147
|
-
/**
|
|
281
|
+
/**
|
|
282
|
+
* The values `chat --help` lists for --agent-engine, or null without the flag.
|
|
283
|
+
* clap prints them as `[possible values: v2, v1, v3]` a few lines below the
|
|
284
|
+
* flag; the quoted names in its description are the fallback.
|
|
285
|
+
*/
|
|
286
|
+
export function parseKiroAgentEngines(help) {
|
|
287
|
+
const lines = help.split("\n");
|
|
288
|
+
const at = lines.findIndex(line => KIRO_HELP_OPTION_ROW.test(line) && /--agent-engine\b/.test(line));
|
|
289
|
+
if (at < 0)
|
|
290
|
+
return null;
|
|
291
|
+
// Only this option's own description/value block: it ends at the next
|
|
292
|
+
// option row, so a neighbour's `[possible values: …]` is never read as ours.
|
|
293
|
+
let end = at + 1;
|
|
294
|
+
while (end < lines.length && !KIRO_HELP_OPTION_ROW.test(lines[end]))
|
|
295
|
+
end++;
|
|
296
|
+
const block = lines.slice(at, end);
|
|
297
|
+
for (const line of block) {
|
|
298
|
+
const listed = line.match(/\[possible values:\s*([^\]]+)\]/);
|
|
299
|
+
if (listed)
|
|
300
|
+
return listed[1].split(",").map(v => v.trim()).filter(Boolean);
|
|
301
|
+
}
|
|
302
|
+
const quoted = [...block.slice(1).join(" ").matchAll(/"([a-z0-9]+)"/gi)].map(m => m[1]);
|
|
303
|
+
// Present but without legible values: [] — nothing to pin to, so refused.
|
|
304
|
+
return [...new Set(quoted)];
|
|
305
|
+
}
|
|
306
|
+
/** A clap option row: ` -r, --resume`, ` --agent-engine <ENGINE>`. */
|
|
307
|
+
const KIRO_HELP_OPTION_ROW = /^\s*(?:-[A-Za-z0-9],\s*)?--[a-z][a-z0-9-]*/;
|
|
308
|
+
/**
|
|
309
|
+
* Whether `help` is kiro's `chat --help` at all. Every release from 1.26 to
|
|
310
|
+
* 2.27 prints the clap usage line and the --trust-all-tools / --resume options
|
|
311
|
+
* AgEnD launches with. An empty or truncated help proves nothing — in
|
|
312
|
+
* particular not that the binary is old enough to have no engine to pin.
|
|
313
|
+
*/
|
|
314
|
+
function isKiroChatHelp(help) {
|
|
315
|
+
return /^Usage:\s+\S*kiro\S*\s+chat\b/m.test(help)
|
|
316
|
+
&& helpAdvertisesFlag(help, "--trust-all-tools")
|
|
317
|
+
&& helpAdvertisesFlag(help, "--resume");
|
|
318
|
+
}
|
|
319
|
+
/** What a released kiro-cli version accepts, per the table above. */
|
|
320
|
+
function compatibilityFromVersion(version, parsed) {
|
|
321
|
+
const has = (min) => versionAtLeast(parsed, min);
|
|
322
|
+
return {
|
|
323
|
+
version,
|
|
324
|
+
supportsLegacyUi: has(KIRO_LEGACY_UI_MIN),
|
|
325
|
+
supportsTui: has(KIRO_LEGACY_UI_MIN),
|
|
326
|
+
supportsV3: has("2.8.0"),
|
|
327
|
+
agentEngines: has("2.8.0") ? ["v2", "v1", "v3"]
|
|
328
|
+
: has("2.4.0") ? ["v2", "v1", "kas"]
|
|
329
|
+
: has("2.3.0") ? ["rust", "kas"]
|
|
330
|
+
: null,
|
|
331
|
+
supportsEffortFlag: has(KIRO_EFFORT_FLAG_MIN),
|
|
332
|
+
source: "version",
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function compatibilityFromHelp(version, help) {
|
|
336
|
+
if (!isKiroChatHelp(help))
|
|
337
|
+
return { ...UNKNOWN_KIRO_COMPATIBILITY, version };
|
|
338
|
+
return {
|
|
339
|
+
version,
|
|
340
|
+
supportsLegacyUi: helpAdvertisesFlag(help, "--legacy-ui"),
|
|
341
|
+
supportsTui: helpAdvertisesFlag(help, "--tui"),
|
|
342
|
+
supportsV3: helpAdvertisesFlag(help, "--v3"),
|
|
343
|
+
agentEngines: parseKiroAgentEngines(help),
|
|
344
|
+
supportsEffortFlag: helpAdvertisesFlag(help, "--effort"),
|
|
345
|
+
source: "help",
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Probe once per binary generation. A version AgEnD has run (<= TESTED_MAX)
|
|
350
|
+
* is answered from the table without a second CLI call; anything newer, or a
|
|
351
|
+
* version string that does not parse, is answered by the binary's own
|
|
352
|
+
* `chat --help` — 3.0 included, which is exactly where the table stops being
|
|
353
|
+
* evidence.
|
|
354
|
+
*/
|
|
148
355
|
export function probeKiroCliCompatibility(binaryPath, run = (binary, args) => execFileSync(binary, args, {
|
|
149
356
|
encoding: "utf-8",
|
|
150
357
|
timeout: 5000,
|
|
@@ -156,29 +363,87 @@ export function probeKiroCliCompatibility(binaryPath, run = (binary, args) => ex
|
|
|
156
363
|
}
|
|
157
364
|
catch { /* fall through to capability help */ }
|
|
158
365
|
const parsed = parseSemver(version);
|
|
159
|
-
if (parsed) {
|
|
160
|
-
return
|
|
161
|
-
version,
|
|
162
|
-
supportsRequireMcpStartup: versionAtLeast(parsed, KIRO_REQUIRE_MCP_MIN),
|
|
163
|
-
supportsLegacyUi: versionAtLeast(parsed, KIRO_LEGACY_UI_MIN),
|
|
164
|
-
supportsEffortFlag: versionAtLeast(parsed, KIRO_EFFORT_FLAG_MIN),
|
|
165
|
-
source: "version",
|
|
166
|
-
};
|
|
366
|
+
if (parsed && !versionAtLeast(parsed, nextPatch(KIRO_TESTED_MAX))) {
|
|
367
|
+
return compatibilityFromVersion(version, parsed);
|
|
167
368
|
}
|
|
168
369
|
try {
|
|
169
|
-
|
|
170
|
-
return {
|
|
171
|
-
version,
|
|
172
|
-
supportsRequireMcpStartup: helpAdvertisesFlag(help, "--require-mcp-startup"),
|
|
173
|
-
supportsLegacyUi: helpAdvertisesFlag(help, "--legacy-ui"),
|
|
174
|
-
supportsEffortFlag: helpAdvertisesFlag(help, "--effort"),
|
|
175
|
-
source: "help",
|
|
176
|
-
};
|
|
370
|
+
return compatibilityFromHelp(version, run(binaryPath, ["chat", "--help"]));
|
|
177
371
|
}
|
|
178
372
|
catch {
|
|
373
|
+
// An untested 2.x whose help cannot be read is still a 2.x; a 3.x or an
|
|
374
|
+
// unidentified binary is not something to guess about.
|
|
375
|
+
if (parsed && !versionAtLeast(parsed, "3.0.0"))
|
|
376
|
+
return compatibilityFromVersion(version, parsed);
|
|
179
377
|
return { ...UNKNOWN_KIRO_COMPATIBILITY, version };
|
|
180
378
|
}
|
|
181
379
|
}
|
|
380
|
+
function nextPatch(version) {
|
|
381
|
+
const [major, minor, patch] = parseSemver(version);
|
|
382
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Pin the UI AND the engine on every launch (#1109). A flag outranks kiro's
|
|
386
|
+
* persisted `chat.agentEngine`, which the V3 ease-in prompt writes for the
|
|
387
|
+
* whole machine and which kiro 3.0 may default to V3. An instance's
|
|
388
|
+
* conversation lives in its engine's store — classic sqlite, V2 JSON, V3 KAS —
|
|
389
|
+
* and moving between them forks it one way, so a launch AgEnD cannot pin to
|
|
390
|
+
* the instance's own engine is refused, never run on whatever kiro defaults to.
|
|
391
|
+
*/
|
|
392
|
+
export function planKiroLaunch(ui, compat) {
|
|
393
|
+
const version = compat.version ?? "of unknown version";
|
|
394
|
+
if (ui === "v3")
|
|
395
|
+
return { kind: "launch", ui, flags: ["--v3"] };
|
|
396
|
+
const engines = compat.agentEngines;
|
|
397
|
+
// A binary with no engine choice at all (before 2.3) has nowhere to drift —
|
|
398
|
+
// but only a version AgEnD knows proves that. Read from --help, a missing
|
|
399
|
+
// selector is just a missing selector: a new release that dropped it must
|
|
400
|
+
// not be launched on its default.
|
|
401
|
+
const knownOld = compat.source === "version";
|
|
402
|
+
const singleEngine = knownOld && engines === null && !compat.supportsV3;
|
|
403
|
+
// 2.3 offered rust|kas with rust (the legacy engine) as its default. Only
|
|
404
|
+
// the version table may say "this is 2.3": a newer help that happens to
|
|
405
|
+
// list `rust` without v1/v2 is a new release, and its default is unknown.
|
|
406
|
+
const rustEra = knownOld && engines?.includes("rust") === true && !compat.supportsV3;
|
|
407
|
+
if (ui === "legacy") {
|
|
408
|
+
if (!compat.supportsLegacyUi) {
|
|
409
|
+
// Before 1.27 classic was the only UI: nothing to select.
|
|
410
|
+
if (!compat.supportsTui && singleEngine)
|
|
411
|
+
return { kind: "launch", ui, flags: [] };
|
|
412
|
+
return {
|
|
413
|
+
kind: "refuse",
|
|
414
|
+
reason: `kiro-cli ${version} no longer offers the legacy UI (--legacy-ui) this instance runs on. `
|
|
415
|
+
+ "AgEnD will not start it on another UI or engine: its conversation would not come along (#1109). "
|
|
416
|
+
+ "Install a kiro-cli 2.x to keep using it; moving instances to the terminal UI is #1110.",
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
if (engines?.includes("v1"))
|
|
420
|
+
return { kind: "launch", ui, flags: ["--legacy-ui", "--agent-engine=v1"] };
|
|
421
|
+
if (singleEngine || rustEra)
|
|
422
|
+
return { kind: "launch", ui, flags: ["--legacy-ui"] };
|
|
423
|
+
return {
|
|
424
|
+
kind: "refuse",
|
|
425
|
+
reason: `kiro-cli ${version} has --legacy-ui but no v1 agent engine to pin it to `
|
|
426
|
+
+ `(--agent-engine accepts: ${engines?.join(", ") || "nothing AgEnD recognises"}). `
|
|
427
|
+
+ "AgEnD will not let it pick an engine on its own (#1109).",
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
// tui
|
|
431
|
+
if (!compat.supportsTui) {
|
|
432
|
+
if (singleEngine)
|
|
433
|
+
return { kind: "launch", ui, flags: [] };
|
|
434
|
+
return { kind: "refuse", reason: `kiro-cli ${version} has no --tui flag; AgEnD cannot tell which UI it would start (#1109).` };
|
|
435
|
+
}
|
|
436
|
+
if (engines?.includes("v2"))
|
|
437
|
+
return { kind: "launch", ui, flags: ["--tui", "--agent-engine=v2"] };
|
|
438
|
+
if (singleEngine || rustEra)
|
|
439
|
+
return { kind: "launch", ui, flags: ["--tui"] };
|
|
440
|
+
return {
|
|
441
|
+
kind: "refuse",
|
|
442
|
+
reason: `kiro-cli ${version} has no v2 agent engine to pin the terminal UI to `
|
|
443
|
+
+ `(--agent-engine accepts: ${engines?.join(", ") || "nothing AgEnD recognises"}). `
|
|
444
|
+
+ "AgEnD will not let it pick an engine on its own (#1109).",
|
|
445
|
+
};
|
|
446
|
+
}
|
|
182
447
|
function kiroBinaryCacheKey(binaryPath) {
|
|
183
448
|
try {
|
|
184
449
|
const stat = statSync(binaryPath);
|
|
@@ -193,12 +458,19 @@ function kiroBinaryCacheKey(binaryPath) {
|
|
|
193
458
|
return `${binaryPath}\0unavailable`;
|
|
194
459
|
}
|
|
195
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* How long an "unknown" probe result is reused. A binary that exists but did
|
|
463
|
+
* not answer (a 5s timeout on a loaded host) refuses its launch, and the
|
|
464
|
+
* fleet's startup retry must get a fresh probe rather than the same miss.
|
|
465
|
+
*/
|
|
466
|
+
const UNKNOWN_COMPATIBILITY_TTL_MS = 60_000;
|
|
196
467
|
function cachedKiroCliCompatibility(binaryPath, run) {
|
|
197
468
|
const cacheKey = kiroBinaryCacheKey(binaryPath);
|
|
198
469
|
const cached = compatibilityCache.get(cacheKey);
|
|
199
|
-
if (cached)
|
|
470
|
+
if (cached && (cached.compatibility.source !== "unknown" || Date.now() - cached.probedAt < UNKNOWN_COMPATIBILITY_TTL_MS)) {
|
|
200
471
|
return cached;
|
|
201
|
-
|
|
472
|
+
}
|
|
473
|
+
const entry = { cacheKey, compatibility: probeKiroCliCompatibility(binaryPath, run), probedAt: Date.now() };
|
|
202
474
|
compatibilityCache.set(cacheKey, entry);
|
|
203
475
|
return entry;
|
|
204
476
|
}
|
|
@@ -210,6 +482,7 @@ export function getCachedKiroCliCompatibility(binaryPath, run) {
|
|
|
210
482
|
export function resetKiroCompatibilityCacheForTests() {
|
|
211
483
|
compatibilityCache.clear();
|
|
212
484
|
warnedUnsupportedEffortCacheKeys.clear();
|
|
485
|
+
warnedVersionGateCacheKeys.clear();
|
|
213
486
|
}
|
|
214
487
|
/** Startup budget for a `--resume` launch (60% first output, 40% ready). */
|
|
215
488
|
export const KIRO_RESUME_STARTUP_BUDGET_MS = 60_000;
|
|
@@ -219,6 +492,8 @@ export class KiroBackend {
|
|
|
219
492
|
binaryPath;
|
|
220
493
|
compatibility;
|
|
221
494
|
compatibilityCacheKey;
|
|
495
|
+
/** Injected by tests: never re-probed. */
|
|
496
|
+
fixedCompatibility;
|
|
222
497
|
warnedUnsupportedEffort = false;
|
|
223
498
|
/**
|
|
224
499
|
* UI flavour and trust mode of the LAST command built. The Enter-drop
|
|
@@ -230,9 +505,12 @@ export class KiroBackend {
|
|
|
230
505
|
*/
|
|
231
506
|
activeUi = "legacy";
|
|
232
507
|
activeTrustAll = true;
|
|
508
|
+
/** Version-gate notice for the launch just built (consumeLaunchWarning). */
|
|
509
|
+
launchWarning = null;
|
|
233
510
|
constructor(instanceDir, compatibility) {
|
|
234
511
|
this.instanceDir = instanceDir;
|
|
235
512
|
this.binaryPath = resolveBinary("kiro-cli");
|
|
513
|
+
this.fixedCompatibility = compatibility !== undefined;
|
|
236
514
|
if (compatibility) {
|
|
237
515
|
this.compatibility = compatibility;
|
|
238
516
|
}
|
|
@@ -308,15 +586,32 @@ export class KiroBackend {
|
|
|
308
586
|
}
|
|
309
587
|
buildCommand(config) {
|
|
310
588
|
const ui = config.kiroUi ?? "legacy";
|
|
589
|
+
// Every launch re-reads the binary generation: a crash-respawn reuses this
|
|
590
|
+
// backend, and kiro-cli may have replaced itself in place since the last
|
|
591
|
+
// launch (an auto-update to a release without this instance's engine).
|
|
592
|
+
// Cheap — a stat and a map lookup unless the binary changed.
|
|
593
|
+
if (!this.fixedCompatibility) {
|
|
594
|
+
const current = cachedKiroCliCompatibility(this.binaryPath);
|
|
595
|
+
this.compatibility = current.compatibility;
|
|
596
|
+
this.compatibilityCacheKey = current.cacheKey;
|
|
597
|
+
}
|
|
598
|
+
if (this.compatibility.source === "unknown") {
|
|
599
|
+
// Neither --version nor chat --help answered: a missing or wedged binary,
|
|
600
|
+
// or a loaded host timing out. Launching blind could start kiro on its
|
|
601
|
+
// default engine; fail this attempt and let the startup retry re-probe.
|
|
602
|
+
throw new Error(`kiro-cli at ${this.binaryPath} did not answer --version or chat --help, so AgEnD cannot pin its UI and engine; not launching (#1109)`);
|
|
603
|
+
}
|
|
604
|
+
const plan = planKiroLaunch(ui, this.compatibility);
|
|
605
|
+
if (plan.kind === "refuse")
|
|
606
|
+
throw new UnsupportedCliError(plan.reason);
|
|
311
607
|
let cmd = `${this.binaryPath} chat`;
|
|
312
|
-
|
|
313
|
-
cmd +=
|
|
314
|
-
|
|
315
|
-
cmd += " --v3";
|
|
608
|
+
for (const flag of plan.flags)
|
|
609
|
+
cmd += ` ${flag}`;
|
|
610
|
+
this.noteVersionGate();
|
|
316
611
|
// Record what is actually being launched for the delivery gate (see
|
|
317
|
-
// dropsEnterWhileBusy):
|
|
318
|
-
//
|
|
319
|
-
this.activeUi =
|
|
612
|
+
// dropsEnterWhileBusy): the legacy prompt row exists only under
|
|
613
|
+
// --legacy-ui; a binary from before 1.27 paints its own classic screen.
|
|
614
|
+
this.activeUi = plan.flags.includes("--legacy-ui") ? "legacy" : ui === "v3" ? "v3" : "tui";
|
|
320
615
|
this.activeTrustAll = config.skipPermissions !== false;
|
|
321
616
|
if (config.skipPermissions !== false)
|
|
322
617
|
cmd += " --trust-all-tools";
|
|
@@ -351,8 +646,14 @@ export class KiroBackend {
|
|
|
351
646
|
console.warn(`[agend] kiro-cli ${detected} does not support the --effort launch flag (requires >= ${KIRO_EFFORT_FLAG_MIN}); configured effort "${effort}" was not applied`);
|
|
352
647
|
}
|
|
353
648
|
}
|
|
354
|
-
|
|
355
|
-
|
|
649
|
+
// Deliberately NOT `--require-mcp-startup` (#1111). Kiro has no per-server
|
|
650
|
+
// "required": the flag exits 3 when ANY enabled MCP server fails, and that
|
|
651
|
+
// includes the user's own servers from ~/.kiro/settings/mcp.json. One
|
|
652
|
+
// third-party server breaking on a kiro-cli update (outline, 2.27) took
|
|
653
|
+
// down every kiro instance at once. Like claude and codex, a broken
|
|
654
|
+
// third-party server now costs only its own tools; whether AgEnD's fleet
|
|
655
|
+
// server connected is the daemon's check (fleet MCP startup watch), which
|
|
656
|
+
// knows which server is which.
|
|
356
657
|
return this.withCredentialProfile(config, cmd);
|
|
357
658
|
}
|
|
358
659
|
/**
|
|
@@ -371,6 +672,36 @@ export class KiroBackend {
|
|
|
371
672
|
prepareCredentialProfileHome(spec, home);
|
|
372
673
|
return `${spec.env}=${shellQuote(home)} ${cmd}`;
|
|
373
674
|
}
|
|
675
|
+
/**
|
|
676
|
+
* P3 of #1109: tell the operator, once per binary generation, when the
|
|
677
|
+
* kiro-cli in use is outside the range AgEnD has run. Never blocks a launch:
|
|
678
|
+
* below KIRO_SUPPORTED_MIN it still works, and above KIRO_TESTED_MAX the
|
|
679
|
+
* flags were already checked against the binary's own --help.
|
|
680
|
+
*/
|
|
681
|
+
noteVersionGate() {
|
|
682
|
+
const parsed = parseSemver(this.compatibility.version);
|
|
683
|
+
if (!parsed)
|
|
684
|
+
return;
|
|
685
|
+
const key = this.compatibilityCacheKey ?? `instance:${this.compatibility.version}`;
|
|
686
|
+
if (warnedVersionGateCacheKeys.has(key))
|
|
687
|
+
return;
|
|
688
|
+
let warning = null;
|
|
689
|
+
if (!versionAtLeast(parsed, KIRO_SUPPORTED_MIN)) {
|
|
690
|
+
warning = t("kiro.version_below_supported", this.compatibility.version, KIRO_SUPPORTED_MIN);
|
|
691
|
+
}
|
|
692
|
+
else if (versionAtLeast(parsed, nextPatch(KIRO_TESTED_MAX))) {
|
|
693
|
+
warning = t("kiro.version_untested", this.compatibility.version, KIRO_TESTED_MAX);
|
|
694
|
+
}
|
|
695
|
+
if (!warning)
|
|
696
|
+
return;
|
|
697
|
+
warnedVersionGateCacheKeys.add(key);
|
|
698
|
+
this.launchWarning = warning;
|
|
699
|
+
}
|
|
700
|
+
consumeLaunchWarning() {
|
|
701
|
+
const warning = this.launchWarning;
|
|
702
|
+
this.launchWarning = null;
|
|
703
|
+
return warning;
|
|
704
|
+
}
|
|
374
705
|
shouldWarnUnsupportedEffort() {
|
|
375
706
|
if (!this.compatibilityCacheKey) {
|
|
376
707
|
if (this.warnedUnsupportedEffort)
|
|
@@ -631,6 +962,7 @@ export class KiroBackend {
|
|
|
631
962
|
}
|
|
632
963
|
getStartupDialogs() {
|
|
633
964
|
return [
|
|
965
|
+
...KIRO_ENGINE_PROMPT_DIALOGS,
|
|
634
966
|
{
|
|
635
967
|
// Kiro CLI --trust-all-tools now shows a confirmation prompt.
|
|
636
968
|
// Default cursor is on "No, exit" — press Down then Enter to select "Yes, I accept".
|
|
@@ -642,6 +974,8 @@ export class KiroBackend {
|
|
|
642
974
|
}
|
|
643
975
|
getRuntimeDialogs() {
|
|
644
976
|
return [
|
|
977
|
+
// The engine prompts can paint after the startup scan has moved on.
|
|
978
|
+
...KIRO_ENGINE_PROMPT_DIALOGS,
|
|
645
979
|
{
|
|
646
980
|
// A service/model outage can drop Kiro into the interactive /model
|
|
647
981
|
// picker. Its choices range across credit multipliers and capability
|