@songsid/agend 2.1.11-beta.1 → 2.1.11-beta.3
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/dist/backend/kiro-engine-ledger.d.ts +36 -0
- package/dist/backend/kiro-engine-ledger.js +113 -0
- package/dist/backend/kiro-engine-ledger.js.map +1 -0
- package/dist/backend/kiro-kas-store.d.ts +11 -0
- package/dist/backend/kiro-kas-store.js +67 -0
- package/dist/backend/kiro-kas-store.js.map +1 -0
- package/dist/backend/kiro-v3-identity.d.ts +28 -0
- package/dist/backend/kiro-v3-identity.js +213 -0
- package/dist/backend/kiro-v3-identity.js.map +1 -0
- package/dist/backend/kiro.d.ts +7 -0
- package/dist/backend/kiro.js +34 -1
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/opencode-permission.d.ts +49 -0
- package/dist/backend/opencode-permission.js +181 -0
- package/dist/backend/opencode-permission.js.map +1 -0
- package/dist/backend/opencode.d.ts +6 -0
- package/dist/backend/opencode.js +46 -2
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/types.d.ts +15 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.js +26 -25
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/ipc-bridge.d.ts +1 -0
- package/dist/channel/ipc-bridge.js +1 -1
- package/dist/channel/ipc-bridge.js.map +1 -1
- package/dist/channel/mcp-tools.js +2 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/cli.js +27 -6
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +99 -0
- package/dist/command-table.js +125 -0
- package/dist/command-table.js.map +1 -0
- package/dist/daemon.d.ts +36 -0
- package/dist/daemon.js +165 -2
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +16 -0
- package/dist/delivery-outbox.js +55 -6
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/e2e-isolation.d.ts +122 -0
- package/dist/e2e-isolation.js +386 -0
- package/dist/e2e-isolation.js.map +1 -0
- package/dist/fleet-manager.d.ts +24 -0
- package/dist/fleet-manager.js +301 -489
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +56 -0
- package/dist/instance-lifecycle.d.ts +2 -0
- package/dist/instance-lifecycle.js +14 -0
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/kiro-engine-status.d.ts +71 -0
- package/dist/kiro-engine-status.js +68 -0
- package/dist/kiro-engine-status.js.map +1 -0
- package/dist/locale.js +16 -4
- package/dist/locale.js.map +1 -1
- package/dist/login-flows.js +10 -0
- package/dist/login-flows.js.map +1 -1
- package/dist/outbound-handlers.js +16 -1
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +3 -0
- package/dist/outbound-schemas.js +3 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/paths.d.ts +19 -0
- package/dist/paths.js +18 -5
- package/dist/paths.js.map +1 -1
- package/dist/tool-permissions.js +4 -2
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.js +3 -2
- package/dist/topic-commands.js.map +1 -1
- package/dist/ui/web-terminal/terminal-input.js +69 -0
- package/dist/ui/web-terminal/terminal.css +6 -0
- package/dist/ui/web-terminal/terminal.html +9 -1
- package/dist/ui/web-terminal/terminal.js +31 -2
- package/dist/update-check.d.ts +40 -2
- package/dist/update-check.js +101 -3
- package/dist/update-check.js.map +1 -1
- package/dist/web-terminal-http.js +1 -0
- package/dist/web-terminal-http.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate a real-platform end-to-end run goes through BEFORE it starts anything.
|
|
3
|
+
*
|
|
4
|
+
* An e2e run drives a scratch fleet with real bot tokens. The one way that goes badly wrong is not a test
|
|
5
|
+
* failing — it is the scratch fleet reaching the LIVE one. It has happened: a "throwaway" fleet started with a
|
|
6
|
+
* changed HOME resolved to tmux's default socket, attached to the live server, and its startup cleanup killed
|
|
7
|
+
* sixteen live windows as orphans (2026-10-03). `AGEND_HOME` isolates the tmux socket, the lock file, the pid
|
|
8
|
+
* file, the IPC sockets and the databases; it does NOT isolate the health port (default 19280, and the CLI
|
|
9
|
+
* treats "something answers there" as "the fleet is running"), `AGEND_PORT`, per-user CLI state, the
|
|
10
|
+
* per-user service unit, or the credentials the child inherits.
|
|
11
|
+
*
|
|
12
|
+
* So this module does two things, both pure (no process is started, no file is written, nothing here ever
|
|
13
|
+
* reads or changes the real process environment):
|
|
14
|
+
*
|
|
15
|
+
* - `planScratchRun` decides, from a requested scratch directory and port, the ONE layout and the ONE child
|
|
16
|
+
* environment a scratch run may use, and refuses — with every violated rule, not just the first — when any
|
|
17
|
+
* guarantee cannot be proven. The child environment is built from an allowlist, never copied: a live token,
|
|
18
|
+
* an AWS key or the real AGEND_HOME in the runner's own environment cannot reach the child.
|
|
19
|
+
* - `planTeardown` produces the only command a run may use to clean up: a tmux `kill-server` against a socket
|
|
20
|
+
* that is proven to live inside the scratch directory.
|
|
21
|
+
*
|
|
22
|
+
* Everything the checks need from the machine (the user's real AgEnD home, realpath, the uid, the temp root)
|
|
23
|
+
* is an injectable seam, so every refusal is exercised with fake values and no real directory.
|
|
24
|
+
*
|
|
25
|
+
* An `ok` is a decision about paths as they were when it was made, not a sandbox: a path can be swapped for a
|
|
26
|
+
* symlink between the plan and the start. The runner must own the scratch directory (create it itself, private to
|
|
27
|
+
* the user, never accept one it did not make) and call `planScratchRun` again immediately before it executes
|
|
28
|
+
* anything, and `planTeardown` immediately before it cleans up. A fact that cannot be established (a path that
|
|
29
|
+
* cannot be resolved, an unknown live home) is a refusal, never an assumption.
|
|
30
|
+
*/
|
|
31
|
+
import { lstatSync, realpathSync } from "node:fs";
|
|
32
|
+
import { tmpdir, userInfo } from "node:os";
|
|
33
|
+
import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
|
|
34
|
+
import { realDefaultAgendHome, tmuxSessionNameFor, tmuxSocketNameFor } from "./paths.js";
|
|
35
|
+
import { UNIX_SOCKET_PATH_MAX } from "./channel/ipc-bridge.js";
|
|
36
|
+
/** The live fleet's default health port. A scratch fleet must never use it. */
|
|
37
|
+
export const LIVE_HEALTH_PORT = 19280;
|
|
38
|
+
/** The longest instance name the layout is checked against: `<home>/instances/<name>/channel.sock` must still fit a unix socket. */
|
|
39
|
+
export const INSTANCE_NAME_BUDGET = 40;
|
|
40
|
+
/** What a scratch token variable must look like: never a name a live fleet could be using. */
|
|
41
|
+
export const SCRATCH_TOKEN_VAR = /^E2E_[A-Z0-9_]+$/;
|
|
42
|
+
/** Knobs the mock backend reads; the only other variables a run may add to the child environment. */
|
|
43
|
+
const MOCK_KNOB = /^MOCK_[A-Z0-9_]+$/;
|
|
44
|
+
/** Variables copied from the runner's environment, and nothing else. */
|
|
45
|
+
const PASSTHROUGH = ["PATH", "LANG", "LC_ALL", "TERM"];
|
|
46
|
+
export class IsolationError extends Error {
|
|
47
|
+
violations;
|
|
48
|
+
constructor(violations) {
|
|
49
|
+
super(`scratch run refused: ${violations.map(v => `${v.rule} (${v.detail})`).join("; ")}`);
|
|
50
|
+
this.violations = violations;
|
|
51
|
+
this.name = "IsolationError";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function defaultSeams(seams) {
|
|
55
|
+
return {
|
|
56
|
+
realAgendHome: seams.realAgendHome !== undefined ? seams.realAgendHome : realDefaultAgendHome(),
|
|
57
|
+
realpath: seams.realpath ?? realpathOfNearestAncestor,
|
|
58
|
+
tmpRoot: seams.tmpRoot ?? tmpdir(),
|
|
59
|
+
livePorts: seams.livePorts ?? [LIVE_HEALTH_PORT],
|
|
60
|
+
uid: seams.uid ?? (typeof process.getuid === "function" ? process.getuid() : userInfo().uid),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* `realpath`, but for a path that need not exist yet: resolve the nearest existing ancestor and re-attach the rest.
|
|
65
|
+
* Only a path that is certainly MISSING is climbed past. A dangling symlink, an unreadable directory (EACCES), a
|
|
66
|
+
* symlink loop (ELOOP) or a file in the middle of the path (ENOTDIR) throws: a fact the check cannot establish
|
|
67
|
+
* is a refusal, never an assumption that the path is harmless.
|
|
68
|
+
*/
|
|
69
|
+
function realpathOfNearestAncestor(path) {
|
|
70
|
+
const rest = [];
|
|
71
|
+
let current = path;
|
|
72
|
+
for (;;) {
|
|
73
|
+
try {
|
|
74
|
+
return rest.length === 0 ? realpathSync.native(current) : join(realpathSync.native(current), ...rest.reverse());
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
if (err.code !== "ENOENT")
|
|
78
|
+
throw err;
|
|
79
|
+
try {
|
|
80
|
+
lstatSync(current);
|
|
81
|
+
throw Object.assign(new Error(`${current} is a dangling symlink`), { code: "ELOOP" });
|
|
82
|
+
}
|
|
83
|
+
catch (lstatErr) {
|
|
84
|
+
if (lstatErr.code !== "ENOENT")
|
|
85
|
+
throw lstatErr;
|
|
86
|
+
}
|
|
87
|
+
const parent = dirname(current);
|
|
88
|
+
if (parent === current)
|
|
89
|
+
return path; // nothing exists: nothing can be a symlink either
|
|
90
|
+
rest.push(basename(current));
|
|
91
|
+
current = parent;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Resolve `path` with the seam; a path that cannot be resolved is a violation, and null. */
|
|
96
|
+
function resolveOrRefuse(s, path, what, out) {
|
|
97
|
+
try {
|
|
98
|
+
return s.realpath(path);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
out.push({ rule: "path-unresolved", detail: `${what} ${path} cannot be resolved (${err.code ?? err.message}); an unproven path is refused` });
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const isInside = (inner, outer) => inner === outer || inner.startsWith(outer.endsWith(sep) ? outer : outer + sep);
|
|
106
|
+
const isStrictlyInside = (inner, outer) => inner !== outer && isInside(inner, outer);
|
|
107
|
+
export function layoutFor(scratchDir) {
|
|
108
|
+
// Short names on purpose: `<home>/instances/<name>/channel.sock` has to fit a unix socket path (~108 bytes).
|
|
109
|
+
return { scratchDir, agendHome: join(scratchDir, "ag"), tmuxTmpdir: join(scratchDir, "tm"), userHome: join(scratchDir, "hm") };
|
|
110
|
+
}
|
|
111
|
+
/** The directory a scratch run's own files live under must be provably the scratch run's. */
|
|
112
|
+
function checkScratchDir(scratchDir, s, out) {
|
|
113
|
+
if (!isAbsolute(scratchDir) || scratchDir !== resolve(scratchDir)) {
|
|
114
|
+
out.push({ rule: "scratch-root", detail: `scratch directory must be an absolute, normalised path (got ${JSON.stringify(scratchDir)})` });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const root = resolveOrRefuse(s, s.tmpRoot, "the temp root", out);
|
|
118
|
+
const real = resolveOrRefuse(s, scratchDir, "the scratch directory", out);
|
|
119
|
+
if (root === null || real === null)
|
|
120
|
+
return;
|
|
121
|
+
if (!isStrictlyInside(real, root)) {
|
|
122
|
+
out.push({ rule: "scratch-root", detail: `${real} is not a directory inside ${root}` });
|
|
123
|
+
}
|
|
124
|
+
if (s.realAgendHome !== null) {
|
|
125
|
+
const live = resolveOrRefuse(s, s.realAgendHome, "the live AgEnD home", out);
|
|
126
|
+
if (live === null)
|
|
127
|
+
return;
|
|
128
|
+
// Inside the live home, equal to it, or a parent of it (a scratch run rooted above the live fleet could be told to clean up inside it).
|
|
129
|
+
if (isInside(real, live) || isInside(live, real)) {
|
|
130
|
+
out.push({ rule: "scratch-not-live", detail: `${real} overlaps the live AgEnD home ${live}` });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Every path the child is handed (its AGEND_HOME, HOME, TMUX_TMPDIR and the tmux socket) must resolve to a place
|
|
136
|
+
* strictly inside the scratch directory and clear of the live home. A symlink at `<scratch>/ag` or `<scratch>/tm` that
|
|
137
|
+
* points elsewhere would otherwise carry the run's data, credentials or tmux server out of the isolation. The
|
|
138
|
+
* scratch directory itself is proven clear of the live home by `checkScratchDir`, so staying strictly inside it is
|
|
139
|
+
* also staying clear of the live home.
|
|
140
|
+
*/
|
|
141
|
+
function checkLayoutContained(layout, tmuxSocketPath, s, out) {
|
|
142
|
+
const scratch = resolveOrRefuse(s, layout.scratchDir, "the scratch directory", out);
|
|
143
|
+
if (scratch === null)
|
|
144
|
+
return;
|
|
145
|
+
const parts = [
|
|
146
|
+
["AGEND_HOME", layout.agendHome], ["HOME", layout.userHome], ["TMUX_TMPDIR", layout.tmuxTmpdir],
|
|
147
|
+
["the tmux socket directory", dirname(tmuxSocketPath)], ["the tmux socket", tmuxSocketPath],
|
|
148
|
+
];
|
|
149
|
+
for (const [what, path] of parts) {
|
|
150
|
+
const real = resolveOrRefuse(s, path, what, out);
|
|
151
|
+
if (real === null)
|
|
152
|
+
continue;
|
|
153
|
+
// Staying strictly inside a scratch directory that `checkScratchDir` has already proven clear of the live home
|
|
154
|
+
// is also staying clear of it.
|
|
155
|
+
if (!isStrictlyInside(real, scratch)) {
|
|
156
|
+
out.push({ rule: "layout-escapes", detail: `${what} ${path} resolves to ${real}, outside the scratch directory ${scratch}` });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function checkPort(port, s, out) {
|
|
161
|
+
if (!Number.isInteger(port) || port < 1024 || port > 65535) {
|
|
162
|
+
out.push({ rule: "health-port", detail: `${String(port)} is not a usable unprivileged port` });
|
|
163
|
+
}
|
|
164
|
+
else if (port === LIVE_HEALTH_PORT || s.livePorts.includes(port)) {
|
|
165
|
+
out.push({ rule: "health-port", detail: `${port} is the live fleet's port` });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Subcommands of the `agend` CLI that act on the machine's service or on the installed package rather than on a
|
|
170
|
+
* fleet directory: they go through the per-user service unit (or `npm`), which a scratch AGEND_HOME does not isolate.
|
|
171
|
+
* `fleet start|stop|restart` are NOT here — they act on the fleet whose health port the scratch config names.
|
|
172
|
+
*/
|
|
173
|
+
const FORBIDDEN_AGEND_SUBCOMMANDS = new Set(["install", "uninstall", "update", "start", "stop", "restart", "setup", "quickstart", "init", "reload"]);
|
|
174
|
+
/** Programs that have no business in a scratch run: they act on the machine, not on the scratch directory. */
|
|
175
|
+
const FORBIDDEN_PROGRAMS = new Set(["systemctl", "launchctl", "service", "sudo", "su", "doas", "kill", "pkill", "killall", "npm", "npx", "pnpm", "yarn"]);
|
|
176
|
+
/** Programs a scratch run may execute. Anything else (`sh -c`, `env`, `tmux`, `xargs`, `bash` …) is an indirection the check cannot see through. */
|
|
177
|
+
const ALLOWED_PROGRAMS = new Set(["agend", "node", "tsx"]);
|
|
178
|
+
const SCRIPT_RUNNERS = new Set(["node", "tsx"]);
|
|
179
|
+
/** The only flags accepted where a subcommand would go: they print and exit. */
|
|
180
|
+
const INFO_FLAGS = new Set(["--version", "-v", "--help", "-h"]);
|
|
181
|
+
/**
|
|
182
|
+
* The command grammar is a whitelist, not a blacklist of words:
|
|
183
|
+
* agend <subcommand> [anything]
|
|
184
|
+
* node|tsx <script> <subcommand> [anything]
|
|
185
|
+
* The subcommand must sit exactly where the grammar puts it. A runtime flag before the script (`node --import x
|
|
186
|
+
* cli.js restart`, `node -- cli.js stop`) or before the subcommand is refused outright, because it can change what
|
|
187
|
+
* runs or hide where the subcommand is. tmux is refused here too: the only tmux command a run may issue is the
|
|
188
|
+
* one `planTeardown` returns, against a socket it has proven.
|
|
189
|
+
*/
|
|
190
|
+
function checkCommand(command, out) {
|
|
191
|
+
if (command.length === 0)
|
|
192
|
+
return;
|
|
193
|
+
const program = basename(command[0]);
|
|
194
|
+
if (FORBIDDEN_PROGRAMS.has(program)) {
|
|
195
|
+
out.push({ rule: "command-forbidden", detail: `${program} acts on the machine, not on the scratch directory` });
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!ALLOWED_PROGRAMS.has(program)) {
|
|
199
|
+
out.push({ rule: "command-forbidden", detail: `${program} is not an allowed program (agend, node, tsx); shells and wrappers hide what they run, and tmux is only used through planTeardown` });
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
let args = command.slice(1);
|
|
203
|
+
if (SCRIPT_RUNNERS.has(program)) {
|
|
204
|
+
const script = args[0];
|
|
205
|
+
if (script === undefined || script.startsWith("-")) {
|
|
206
|
+
out.push({ rule: "command-forbidden", detail: `${program} must be followed directly by a script path, not ${JSON.stringify(script ?? "")}: runtime flags change what runs` });
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
args = args.slice(1);
|
|
210
|
+
}
|
|
211
|
+
const sub = args[0];
|
|
212
|
+
if (sub === undefined)
|
|
213
|
+
return;
|
|
214
|
+
if (sub.startsWith("-")) {
|
|
215
|
+
if (!INFO_FLAGS.has(sub) || args.length > 1) {
|
|
216
|
+
out.push({ rule: "command-forbidden", detail: `${JSON.stringify(sub)} comes where the agend subcommand belongs; only --version/--help (alone) may` });
|
|
217
|
+
}
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (FORBIDDEN_AGEND_SUBCOMMANDS.has(sub)) {
|
|
221
|
+
out.push({ rule: "command-forbidden", detail: `agend ${sub} goes through the per-user service, which a scratch AGEND_HOME does not isolate` });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Decide the layout and child environment of a scratch run, or refuse it with every rule that failed.
|
|
226
|
+
* Pure: it neither starts nor writes anything.
|
|
227
|
+
*/
|
|
228
|
+
export function planScratchRun(request, seams = {}) {
|
|
229
|
+
const s = defaultSeams(seams);
|
|
230
|
+
const violations = [];
|
|
231
|
+
const { scratchDir, parentEnv } = request;
|
|
232
|
+
checkScratchDir(scratchDir, s, violations);
|
|
233
|
+
const layout = layoutFor(scratchDir);
|
|
234
|
+
if (s.realAgendHome === null) {
|
|
235
|
+
violations.push({ rule: "real-home-unknown", detail: "the live AgEnD home cannot be determined, so nothing can be proven different from it" });
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
const live = resolveOrRefuse(s, s.realAgendHome, "the live AgEnD home", violations);
|
|
239
|
+
const home = resolveOrRefuse(s, layout.agendHome, "AGEND_HOME", violations);
|
|
240
|
+
if (live !== null && home !== null && (home === live || layout.agendHome === s.realAgendHome)) {
|
|
241
|
+
violations.push({ rule: "home-not-live", detail: `AGEND_HOME ${layout.agendHome} is the live home` });
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// The decision that once killed live windows, evaluated for the CHILD's home rather than this process's.
|
|
245
|
+
const socketName = tmuxSocketNameFor(layout.agendHome, s.realAgendHome);
|
|
246
|
+
const sessionName = tmuxSessionNameFor(layout.agendHome, s.realAgendHome);
|
|
247
|
+
if (socketName === null) {
|
|
248
|
+
violations.push({ rule: "tmux-socket-default", detail: "the child would use tmux's DEFAULT socket — the live server" });
|
|
249
|
+
}
|
|
250
|
+
if (sessionName === "agend") {
|
|
251
|
+
violations.push({ rule: "tmux-session-live", detail: 'the child would use the live tmux session name "agend"' });
|
|
252
|
+
}
|
|
253
|
+
const longest = join(layout.agendHome, "instances", "x".repeat(INSTANCE_NAME_BUDGET), "channel.sock");
|
|
254
|
+
const tmuxSocketPath = join(layout.tmuxTmpdir, `tmux-${s.uid}`, socketName ?? "default");
|
|
255
|
+
for (const [what, path] of [["IPC socket", longest], ["tmux socket", tmuxSocketPath]]) {
|
|
256
|
+
if (Buffer.byteLength(path) >= UNIX_SOCKET_PATH_MAX) {
|
|
257
|
+
violations.push({ rule: "socket-path-length", detail: `${what} path would be ${Buffer.byteLength(path)} bytes (limit ${UNIX_SOCKET_PATH_MAX - 1}); use a shorter scratch directory` });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
checkLayoutContained(layout, tmuxSocketPath, s, violations);
|
|
261
|
+
checkPort(request.healthPort, s, violations);
|
|
262
|
+
const tokenVars = [...(request.tokenVars ?? [])];
|
|
263
|
+
for (const name of tokenVars) {
|
|
264
|
+
if (!SCRATCH_TOKEN_VAR.test(name)) {
|
|
265
|
+
violations.push({ rule: "token-var", detail: `${JSON.stringify(name)} is not a scratch token variable (E2E_*); a live fleet's variable must never be passed on` });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
for (const key of Object.keys(request.extraEnv ?? {})) {
|
|
269
|
+
if (!MOCK_KNOB.test(key)) {
|
|
270
|
+
violations.push({ rule: "env-forbidden", detail: `${key} may not be added to the child environment (only MOCK_* knobs)` });
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
checkCommand(request.command ?? [], violations);
|
|
274
|
+
if (violations.length > 0)
|
|
275
|
+
return { ok: false, violations };
|
|
276
|
+
const childEnv = {};
|
|
277
|
+
for (const name of PASSTHROUGH) {
|
|
278
|
+
const value = parentEnv[name];
|
|
279
|
+
if (value !== undefined && value !== "")
|
|
280
|
+
childEnv[name] = value;
|
|
281
|
+
}
|
|
282
|
+
childEnv.AGEND_HOME = layout.agendHome;
|
|
283
|
+
childEnv.TMUX_TMPDIR = layout.tmuxTmpdir;
|
|
284
|
+
childEnv.HOME = layout.userHome;
|
|
285
|
+
childEnv.AGEND_E2E = "1";
|
|
286
|
+
for (const name of tokenVars) {
|
|
287
|
+
const value = parentEnv[name];
|
|
288
|
+
if (value !== undefined && value !== "")
|
|
289
|
+
childEnv[name] = value;
|
|
290
|
+
}
|
|
291
|
+
Object.assign(childEnv, request.extraEnv ?? {});
|
|
292
|
+
return { ok: true, plan: { layout, childEnv, healthPort: request.healthPort, socketName: socketName, sessionName, tmuxSocketPath, tokenVars } };
|
|
293
|
+
}
|
|
294
|
+
/** `planScratchRun`, throwing: the form a runner uses so that a refusal cannot be ignored. */
|
|
295
|
+
export function assertScratchRun(request, seams = {}) {
|
|
296
|
+
const result = planScratchRun(request, seams);
|
|
297
|
+
if (!result.ok)
|
|
298
|
+
throw new IsolationError(result.violations);
|
|
299
|
+
return result.plan;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* The only way a run may clean up: `tmux -S <socket> kill-server`, and only for a socket proven to live inside the
|
|
303
|
+
* scratch directory and to carry the scratch run's own name. Never `-L`, never the default socket, never a
|
|
304
|
+
* pattern — a wrong guess here is how live windows die. Returns the command; running it is the caller's job.
|
|
305
|
+
*/
|
|
306
|
+
export function planTeardown(plan, seams = {}) {
|
|
307
|
+
const s = defaultSeams(seams);
|
|
308
|
+
const violations = [];
|
|
309
|
+
const { scratchDir } = plan.layout;
|
|
310
|
+
checkScratchDir(scratchDir, s, violations);
|
|
311
|
+
if (s.realAgendHome === null) {
|
|
312
|
+
violations.push({ rule: "real-home-unknown", detail: "the live AgEnD home cannot be determined, so a kill-server cannot be proven to miss the live fleet" });
|
|
313
|
+
}
|
|
314
|
+
const real = resolveOrRefuse(s, plan.tmuxSocketPath, "the tmux socket", violations);
|
|
315
|
+
const scratchReal = resolveOrRefuse(s, scratchDir, "the scratch directory", violations);
|
|
316
|
+
if (!isAbsolute(plan.tmuxSocketPath) || plan.tmuxSocketPath !== resolve(plan.tmuxSocketPath)) {
|
|
317
|
+
violations.push({ rule: "teardown-target", detail: "the tmux socket path is not an absolute, normalised path" });
|
|
318
|
+
}
|
|
319
|
+
else if (real !== null && scratchReal !== null && !isStrictlyInside(real, scratchReal)) {
|
|
320
|
+
violations.push({ rule: "teardown-target", detail: `${real} is not inside the scratch directory ${scratchReal}` });
|
|
321
|
+
}
|
|
322
|
+
checkLayoutContained(plan.layout, plan.tmuxSocketPath, s, violations);
|
|
323
|
+
if (basename(plan.tmuxSocketPath) !== plan.socketName || plan.socketName.length === 0 || plan.socketName === "default") {
|
|
324
|
+
violations.push({ rule: "teardown-target", detail: `socket ${JSON.stringify(basename(plan.tmuxSocketPath))} is not the scratch run's own (${plan.socketName})` });
|
|
325
|
+
}
|
|
326
|
+
if (s.realAgendHome !== null && tmuxSocketNameFor(plan.layout.agendHome, s.realAgendHome) !== plan.socketName) {
|
|
327
|
+
violations.push({ rule: "teardown-target", detail: "the socket name is not the one the scratch home derives" });
|
|
328
|
+
}
|
|
329
|
+
if (violations.length > 0)
|
|
330
|
+
return { ok: false, violations };
|
|
331
|
+
return { ok: true, argv: ["tmux", "-S", plan.tmuxSocketPath, "kill-server"], removeDir: scratchDir };
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* A scratch run's fleet.yaml, checked before the fleet is given it: the isolation above is worth nothing if the
|
|
335
|
+
* config then names a live token variable, a real backend, a webhook or the live port.
|
|
336
|
+
*/
|
|
337
|
+
export function checkScratchFleetConfig(config, plan) {
|
|
338
|
+
const out = [];
|
|
339
|
+
if (config.health_port !== plan.healthPort) {
|
|
340
|
+
out.push({ rule: "config-health-port", detail: `health_port must be ${plan.healthPort} (got ${JSON.stringify(config.health_port)})` });
|
|
341
|
+
}
|
|
342
|
+
const channels = config.channels ?? (config.channel ? [config.channel] : []);
|
|
343
|
+
channels.forEach((channel, i) => {
|
|
344
|
+
const env = channel.bot_token_env;
|
|
345
|
+
if (typeof env !== "string" || !plan.tokenVars.includes(env)) {
|
|
346
|
+
out.push({ rule: "config-token-var", detail: `channel ${i} bot_token_env ${JSON.stringify(env)} is not one of this run's scratch variables` });
|
|
347
|
+
}
|
|
348
|
+
if (channel.access === undefined || channel.access === null || typeof channel.access !== "object") {
|
|
349
|
+
out.push({ rule: "config-access", detail: `channel ${i} has no explicit access block (who may talk to the scratch bot must be written down)` });
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
if (config.defaults?.backend !== "mock") {
|
|
353
|
+
out.push({ rule: "config-backend", detail: `defaults.backend must be "mock" (got ${JSON.stringify(config.defaults?.backend)}): a real CLI needs real credentials and per-user state` });
|
|
354
|
+
}
|
|
355
|
+
for (const [name, instance] of Object.entries(config.instances ?? {})) {
|
|
356
|
+
if (instance.backend !== undefined && instance.backend !== "mock") {
|
|
357
|
+
out.push({ rule: "config-backend", detail: `instance ${name} backend ${JSON.stringify(instance.backend)} is not "mock"` });
|
|
358
|
+
}
|
|
359
|
+
// An instance inherits `defaults.agent_mode` / `defaults.hang_detector`; the defaults are checked below, so here
|
|
360
|
+
// only what the instance sets itself can differ from them.
|
|
361
|
+
if (instance.agent_mode === "cli") {
|
|
362
|
+
out.push({ rule: "config-agent-mode", detail: `instance ${name} uses agent_mode: cli, whose port (AGEND_PORT, default 19280) is not derived from the scratch health port` });
|
|
363
|
+
}
|
|
364
|
+
const hang = instance.hang_detector?.enabled;
|
|
365
|
+
if (hang !== undefined && hang !== false) {
|
|
366
|
+
out.push({ rule: "config-quiet", detail: `instance ${name} hang_detector.enabled is ${JSON.stringify(hang)}: it overrides the quiet default and posts to the real chat on its own` });
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (config.defaults?.agent_mode === "cli") {
|
|
370
|
+
out.push({ rule: "config-agent-mode", detail: "defaults.agent_mode: cli would put every instance on a port that is not derived from the scratch health port" });
|
|
371
|
+
}
|
|
372
|
+
const quiet = [
|
|
373
|
+
["defaults.tips", config.defaults?.tips],
|
|
374
|
+
["defaults.daily_summary.enabled", config.defaults?.daily_summary?.enabled],
|
|
375
|
+
["defaults.hang_detector.enabled", config.defaults?.hang_detector?.enabled],
|
|
376
|
+
];
|
|
377
|
+
for (const [name, value] of quiet) {
|
|
378
|
+
if (value !== false)
|
|
379
|
+
out.push({ rule: "config-quiet", detail: `${name} must be explicitly false (got ${JSON.stringify(value)}): they post to the real chat on their own schedule` });
|
|
380
|
+
}
|
|
381
|
+
if (config.defaults?.webhooks !== undefined) {
|
|
382
|
+
out.push({ rule: "config-webhooks", detail: "defaults.webhooks would call out to real endpoints" });
|
|
383
|
+
}
|
|
384
|
+
return out;
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=e2e-isolation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e-isolation.js","sourceRoot":"","sources":["../src/e2e-isolation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,oIAAoI;AACpI,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,8FAA8F;AAC9F,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AACpD,qGAAqG;AACrG,MAAM,SAAS,GAAG,mBAAmB,CAAC;AACtC,wEAAwE;AACxE,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAC;AAyDhE,MAAM,OAAO,cAAe,SAAQ,KAAK;IAClB;IAArB,YAAqB,UAAuB;QAC1C,KAAK,CAAC,wBAAwB,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QADxE,eAAU,GAAV,UAAU,CAAa;QAE1C,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,SAAS,YAAY,CAAC,KAAY;IAChC,OAAO;QACL,aAAa,EAAE,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,oBAAoB,EAAE;QAC/F,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,yBAAyB;QACrD,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,MAAM,EAAE;QAClC,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,CAAC,gBAAgB,CAAC;QAChD,GAAG,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC;KAC7F,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,yBAAyB,CAAC,IAAY;IAC7C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,SAAS,CAAC;QACR,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAClH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,GAAG,CAAC;YAChE,IAAI,CAAC;gBACH,SAAS,CAAC,OAAO,CAAC,CAAC;gBACnB,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,OAAO,wBAAwB,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YACxF,CAAC;YAAC,OAAO,QAAQ,EAAE,CAAC;gBAClB,IAAK,QAAkC,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,QAAQ,CAAC;YAC5E,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,MAAM,KAAK,OAAO;gBAAE,OAAO,IAAI,CAAC,CAAY,kDAAkD;YAClG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7B,OAAO,GAAG,MAAM,CAAC;QACnB,CAAC;IACH,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,SAAS,eAAe,CAAC,CAAkB,EAAE,IAAY,EAAE,IAAY,EAAE,GAAgB;IACvF,IAAI,CAAC;QACH,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,IAAI,IAAI,IAAI,wBAAyB,GAA6B,CAAC,IAAI,IAAK,GAAa,CAAC,OAAO,gCAAgC,EAAE,CAAC,CAAC;QACpL,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,KAAa,EAAW,EAAE,CAAC,KAAK,KAAK,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;AAC3I,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAE,KAAa,EAAW,EAAE,CAAC,KAAK,KAAK,KAAK,IAAI,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAE9G,MAAM,UAAU,SAAS,CAAC,UAAkB;IAC1C,6GAA6G;IAC7G,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC;AACjI,CAAC;AAED,6FAA6F;AAC7F,SAAS,eAAe,CAAC,UAAkB,EAAE,CAAkB,EAAE,GAAgB;IAC/E,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAClE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,+DAA+D,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC;QACzI,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,CAAC,CAAC;IACjE,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,EAAE,UAAU,EAAE,uBAAuB,EAAE,GAAG,CAAC,CAAC;IAC1E,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO;IAC3C,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,8BAA8B,IAAI,EAAE,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,CAAC,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa,EAAE,qBAAqB,EAAE,GAAG,CAAC,CAAC;QAC7E,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC1B,wIAAwI;QACxI,IAAI,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,GAAG,IAAI,iCAAiC,IAAI,EAAE,EAAE,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,MAAqB,EAAE,cAAsB,EAAE,CAAkB,EAAE,GAAgB;IAC/G,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,uBAAuB,EAAE,GAAG,CAAC,CAAC;IACpF,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO;IAC7B,MAAM,KAAK,GAA4B;QACrC,CAAC,YAAY,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC;QAC/F,CAAC,2BAA2B,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,iBAAiB,EAAE,cAAc,CAAC;KAC5F,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,IAAI,KAAK,IAAI;YAAE,SAAS;QAC5B,+GAA+G;QAC/G,+BAA+B;QAC/B,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,IAAI,IAAI,IAAI,gBAAgB,IAAI,mCAAmC,OAAO,EAAE,EAAE,CAAC,CAAC;QAChI,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,CAAkB,EAAE,GAAgB;IACnE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QAC3D,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,CAAC,CAAC;IACjG,CAAC;SAAM,IAAI,IAAI,KAAK,gBAAgB,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,2BAA2B,EAAE,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,2BAA2B,GAAwB,IAAI,GAAG,CAC9D,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,CACxG,CAAC;AACF,8GAA8G;AAC9G,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CACrD,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CACtH,CAAC;AACF,oJAAoJ;AACpJ,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAChF,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AACrE,gFAAgF;AAChF,MAAM,UAAU,GAAwB,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;AAErF;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,OAA0B,EAAE,GAAgB;IAChE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC;IACtC,IAAI,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,GAAG,OAAO,oDAAoD,EAAE,CAAC,CAAC;QAChH,OAAO;IACT,CAAC;IACD,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,GAAG,OAAO,mIAAmI,EAAE,CAAC,CAAC;QAC/L,OAAO;IACT,CAAC;IACD,IAAI,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACnD,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,GAAG,OAAO,oDAAoD,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,kCAAkC,EAAE,CAAC,CAAC;YAC9K,OAAO;QACT,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO;IAC9B,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,8EAA8E,EAAE,CAAC,CAAC;QACxJ,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,2BAA2B,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,SAAS,GAAG,iFAAiF,EAAE,CAAC,CAAC;IACjJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAuB,EAAE,QAAe,EAAE;IACvE,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE1C,eAAe,CAAC,UAAU,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IAErC,IAAI,CAAC,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QAC7B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,sFAAsF,EAAE,CAAC,CAAC;IACjJ,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa,EAAE,qBAAqB,EAAE,UAAU,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QAC5E,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9F,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,MAAM,CAAC,SAAS,mBAAmB,EAAE,CAAC,CAAC;QACxG,CAAC;IACH,CAAC;IAED,yGAAyG;IACzG,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC;IACxE,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC;IAC1E,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,6DAA6D,EAAE,CAAC,CAAC;IAC1H,CAAC;IACD,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;QAC5B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,wDAAwD,EAAE,CAAC,CAAC;IACnH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,cAAc,CAAC,CAAC;IACtG,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE,UAAU,IAAI,SAAS,CAAC,CAAC;IACzF,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,CAAU,EAAE,CAAC;QAC/F,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,oBAAoB,EAAE,CAAC;YACpD,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,IAAI,kBAAkB,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,oBAAoB,GAAG,CAAC,oCAAoC,EAAE,CAAC,CAAC;QACzL,CAAC;IACH,CAAC;IAED,oBAAoB,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAC5D,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAE7C,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,2FAA2F,EAAE,CAAC,CAAC;QACrK,CAAC;IACH,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,GAAG,gEAAgE,EAAE,CAAC,CAAC;QAC7H,CAAC;IACH,CAAC;IACD,YAAY,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC;IAEhD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAE5D,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAClE,CAAC;IACD,QAAQ,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC;IACvC,QAAQ,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC;IACzC,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC;IAChC,QAAQ,CAAC,SAAS,GAAG,GAAG,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAClE,CAAC;IACD,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAEhD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,UAAW,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE,CAAC;AACnJ,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,gBAAgB,CAAC,OAAuB,EAAE,QAAe,EAAE;IACzE,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC9C,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAMD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAiB,EAAE,QAAe,EAAE;IAC/D,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;IAEnC,eAAe,CAAC,UAAU,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAC3C,IAAI,CAAC,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QAC7B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,oGAAoG,EAAE,CAAC,CAAC;IAC/J,CAAC;IACD,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAAC;IACpF,MAAM,WAAW,GAAG,eAAe,CAAC,CAAC,EAAE,UAAU,EAAE,uBAAuB,EAAE,UAAU,CAAC,CAAC;IACxF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QAC7F,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,0DAA0D,EAAE,CAAC,CAAC;IACnH,CAAC;SAAM,IAAI,IAAI,KAAK,IAAI,IAAI,WAAW,KAAK,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;QACzF,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,IAAI,wCAAwC,WAAW,EAAE,EAAE,CAAC,CAAC;IACrH,CAAC;IACD,oBAAoB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IACtE,IAAI,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACvH,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,UAAU,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,kCAAkC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;IACpK,CAAC;IACD,IAAI,CAAC,CAAC,aAAa,KAAK,IAAI,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;QAC9G,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,yDAAyD,EAAE,CAAC,CAAC;IAClH,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAC5D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACvG,CAAC;AAWD;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAA0B,EAAE,IAAiB;IACnF,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,IAAI,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,uBAAuB,IAAI,CAAC,UAAU,SAAS,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IACzI,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7E,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE;QAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC;QAClC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7D,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,WAAW,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,6CAA6C,EAAE,CAAC,CAAC;QACjJ,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClG,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,CAAC,sFAAsF,EAAE,CAAC,CAAC;QAClJ,CAAC;IACH,CAAC,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,QAAQ,EAAE,OAAO,KAAK,MAAM,EAAE,CAAC;QACxC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,wCAAwC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,yDAAyD,EAAE,CAAC,CAAC;IAC1L,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,CAAC;QACtE,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;YAClE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,YAAY,IAAI,YAAY,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAC7H,CAAC;QACD,iHAAiH;QACjH,2DAA2D;QAC3D,IAAI,QAAQ,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;YAClC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,YAAY,IAAI,2GAA2G,EAAE,CAAC,CAAC;QAC/K,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;QAC7C,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACzC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,IAAI,6BAA6B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,wEAAwE,EAAE,CAAC,CAAC;QACxL,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,EAAE,UAAU,KAAK,KAAK,EAAE,CAAC;QAC1C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,8GAA8G,EAAE,CAAC,CAAC;IAClK,CAAC;IACD,MAAM,KAAK,GAA6B;QACtC,CAAC,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC;QACxC,CAAC,gCAAgC,EAAE,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAC;QAC3E,CAAC,gCAAgC,EAAE,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAC;KAC5E,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QAClC,IAAI,KAAK,KAAK,KAAK;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,kCAAkC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,qDAAqD,EAAE,CAAC,CAAC;IACvL,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,oDAAoD,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/fleet-manager.d.ts
CHANGED
|
@@ -254,6 +254,7 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
254
254
|
private startupRetryNotices;
|
|
255
255
|
/** Unsupported-CLI refusals waiting to go out, grouped by reason (#1109). */
|
|
256
256
|
private unsupportedCliNotices;
|
|
257
|
+
private kiroIncompatNotices;
|
|
257
258
|
/** Backoff between automatic startup retries; the last step repeats while the backend is down. */
|
|
258
259
|
static readonly STARTUP_RETRY_BACKOFF_MS: number[];
|
|
259
260
|
/** Hard cap on automatic startup retries (3 backoff steps + up to 3 more during a backend outage). */
|
|
@@ -652,6 +653,15 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
652
653
|
* type a slash command could `/update` the host.
|
|
653
654
|
*/
|
|
654
655
|
fleetAdminGate(userId: string, adapterId?: string): "ok" | "disabled" | "denied";
|
|
656
|
+
/**
|
|
657
|
+
* Every Discord slash command, for every adapter, in one place (it used to be two copies that could drift).
|
|
658
|
+
*
|
|
659
|
+
* Two checks before any command's own code runs, and the order matters: the DOOR (src/slash-authz.ts — may
|
|
660
|
+
* this caller speak here at all) and then the COMMAND TABLE (src/command-table.ts — does this command apply
|
|
661
|
+
* in this kind of channel, and which kind of admin does it need). The table can only narrow what the door
|
|
662
|
+
* let through. A command nobody registered is answered, not left to time out.
|
|
663
|
+
*/
|
|
664
|
+
private dispatchSlash;
|
|
655
665
|
/**
|
|
656
666
|
* The door every Discord slash command goes through (src/slash-authz.ts has the rule and the reasoning).
|
|
657
667
|
* Answers the caller itself when it refuses, so a refused command costs one reply and does nothing else.
|
|
@@ -798,6 +808,20 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
798
808
|
* first unattended start and every scheduled retry.
|
|
799
809
|
*/
|
|
800
810
|
private stopOnUnsupportedCli;
|
|
811
|
+
/**
|
|
812
|
+
* LifecycleContext: a kiro instance the installed kiro-cli cannot run as
|
|
813
|
+
* configured (#1109) — at start, or at a respawn after kiro-cli replaced
|
|
814
|
+
* itself. The operator already gets the plain notice; this tells every
|
|
815
|
+
* General, as an agent, so it can explain the kiro engine move when asked.
|
|
816
|
+
* One notice per refusal reason, like the operator's.
|
|
817
|
+
*/
|
|
818
|
+
queueKiroIncompatNotice(name: string, reason: string): void;
|
|
819
|
+
/**
|
|
820
|
+
* Held in the delivery outbox until each General takes it: the same kiro-cli
|
|
821
|
+
* may have stopped the General too, and it should still hear once it is back.
|
|
822
|
+
* Admitted once per day per refusal (reason + names) and General.
|
|
823
|
+
*/
|
|
824
|
+
private sendKiroIncompatToGenerals;
|
|
801
825
|
/**
|
|
802
826
|
* One notice per refusal reason: a kiro-cli that dropped the legacy UI
|
|
803
827
|
* refuses every kiro instance at once, and that is one message, not ten.
|