@songsid/agend 2.1.4-beta.5 → 2.1.4-beta.50
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 +1 -1
- package/README.zh-TW.md +1 -1
- package/dist/agent-endpoint.js +1 -1
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/backend/antigravity.d.ts +12 -8
- package/dist/backend/antigravity.js +189 -42
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +62 -23
- package/dist/backend/claude-code.js +296 -43
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.d.ts +18 -0
- package/dist/backend/codex.js +148 -8
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/gemini-cli.js +2 -2
- package/dist/backend/gemini-cli.js.map +1 -1
- package/dist/backend/grok.js +2 -2
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +52 -2
- package/dist/backend/kiro.js +267 -12
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/opencode.d.ts +27 -11
- package/dist/backend/opencode.js +65 -41
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/types.d.ts +97 -3
- package/dist/backend/types.js +12 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-outage.d.ts +61 -0
- package/dist/backend-outage.js +71 -0
- package/dist/backend-outage.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +44 -2
- package/dist/channel/adapters/discord.js +526 -78
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +30 -0
- package/dist/channel/adapters/telegram.js +221 -19
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/agy-mcp-launcher.d.ts +2 -0
- package/dist/channel/agy-mcp-launcher.js +28 -0
- package/dist/channel/agy-mcp-launcher.js.map +1 -0
- package/dist/channel/ipc-bridge.d.ts +2 -1
- package/dist/channel/ipc-bridge.js +33 -4
- package/dist/channel/ipc-bridge.js.map +1 -1
- package/dist/channel/mcp-server.js +28 -25
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.js +4 -2
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-queue.js +62 -1
- package/dist/channel/message-queue.js.map +1 -1
- package/dist/channel/types.d.ts +31 -1
- package/dist/classic-channel-manager.d.ts +61 -3
- package/dist/classic-channel-manager.js +256 -31
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +109 -37
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +48 -7
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +12 -1
- package/dist/config.js.map +1 -1
- package/dist/cross-instance-envelope.d.ts +6 -0
- package/dist/cross-instance-envelope.js +30 -0
- package/dist/cross-instance-envelope.js.map +1 -0
- package/dist/daemon.d.ts +429 -9
- package/dist/daemon.js +1843 -289
- package/dist/daemon.js.map +1 -1
- package/dist/doctor.d.ts +41 -0
- package/dist/doctor.js +267 -0
- package/dist/doctor.js.map +1 -0
- package/dist/fleet-context.d.ts +54 -0
- package/dist/fleet-manager.d.ts +398 -11
- package/dist/fleet-manager.js +2756 -499
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-yaml-slim.d.ts +10 -0
- package/dist/fleet-yaml-slim.js +59 -0
- package/dist/fleet-yaml-slim.js.map +1 -0
- package/dist/general-knowledge/skills/backend-providers/SKILL.md +114 -0
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +3 -1
- package/dist/general-knowledge/skills/delegation-playbook/SKILL.md +52 -0
- package/dist/general-knowledge/skills/development-workflow/SKILL.md +28 -0
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -0
- package/dist/general-knowledge/skills/fleet-health/SKILL.md +1 -0
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +1 -0
- package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +1 -0
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +64 -16
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -0
- package/dist/general-knowledge/skills/scheduling/SKILL.md +1 -0
- package/dist/general-knowledge/skills/session-management/SKILL.md +172 -8
- package/dist/general-knowledge/skills/tui-effort/SKILL.md +1 -0
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +30 -0
- package/dist/instance-lifecycle.d.ts +99 -0
- package/dist/instance-lifecycle.js +339 -11
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +12 -0
- package/dist/instructions.js +35 -1
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +1004 -288
- package/dist/locale.js.map +1 -1
- package/dist/login-flows.d.ts +91 -0
- package/dist/login-flows.js +170 -0
- package/dist/login-flows.js.map +1 -0
- package/dist/login-manager.d.ts +63 -0
- package/dist/login-manager.js +134 -0
- package/dist/login-manager.js.map +1 -0
- package/dist/network-family.d.ts +18 -0
- package/dist/network-family.js +20 -0
- package/dist/network-family.js.map +1 -0
- package/dist/outbound-handlers.d.ts +8 -0
- package/dist/outbound-handlers.js +101 -18
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +7 -1
- package/dist/outbound-schemas.js +9 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/pane-input-residue.d.ts +52 -0
- package/dist/pane-input-residue.js +107 -0
- package/dist/pane-input-residue.js.map +1 -0
- package/dist/reply-dedup.d.ts +7 -8
- package/dist/reply-dedup.js +0 -0
- package/dist/reply-dedup.js.map +1 -1
- package/dist/restart-progress.d.ts +2 -0
- package/dist/restart-progress.js +3 -0
- package/dist/restart-progress.js.map +1 -1
- package/dist/scheduler/db.d.ts +12 -0
- package/dist/scheduler/db.js +59 -0
- package/dist/scheduler/db.js.map +1 -1
- package/dist/service-installer.d.ts +11 -0
- package/dist/service-installer.js +84 -18
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.js +1 -1
- package/dist/settings-api.js.map +1 -1
- package/dist/setup-wizard.js +2 -2
- package/dist/setup-wizard.js.map +1 -1
- package/dist/spawn-gate.d.ts +30 -0
- package/dist/spawn-gate.js +79 -0
- package/dist/spawn-gate.js.map +1 -0
- package/dist/storm-window.d.ts +83 -0
- package/dist/storm-window.js +251 -0
- package/dist/storm-window.js.map +1 -0
- package/dist/tips.d.ts +44 -0
- package/dist/tips.js +355 -0
- package/dist/tips.js.map +1 -0
- package/dist/tmux-manager.d.ts +16 -0
- package/dist/tmux-manager.js +110 -25
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tool-progress.d.ts +40 -0
- package/dist/tool-progress.js +289 -0
- package/dist/tool-progress.js.map +1 -0
- package/dist/topic-commands.d.ts +42 -4
- package/dist/topic-commands.js +372 -67
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-monitor.d.ts +15 -2
- package/dist/transcript-monitor.js +63 -17
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +131 -0
- package/dist/transcript-sources.js +580 -0
- package/dist/transcript-sources.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/ui/dashboard.html +55 -32
- package/dist/ui/settings.html +200 -60
- package/dist/ui/view.html +147 -30
- package/dist/usage/format-rich.d.ts +1 -1
- package/dist/usage/format-rich.js +28 -24
- package/dist/usage/format-rich.js.map +1 -1
- package/dist/usage/i18n-keys.d.ts +7 -0
- package/dist/usage/i18n-keys.js +34 -0
- package/dist/usage/i18n-keys.js.map +1 -0
- package/dist/usage/i18n.d.ts +5 -0
- package/dist/usage/i18n.js +27 -0
- package/dist/usage/i18n.js.map +1 -0
- package/dist/usage/providers.d.ts +21 -0
- package/dist/usage/providers.js +153 -75
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/usage-api.d.ts +11 -3
- package/dist/usage/usage-api.js +61 -24
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/workflow-templates/default.md +2 -1
- package/package.json +2 -2
package/dist/daemon.d.ts
CHANGED
|
@@ -6,11 +6,18 @@ import type { CliBackend, InstanceState, InstanceStateSnapshot } from "./backend
|
|
|
6
6
|
import { HangDetector } from "./hang-detector.js";
|
|
7
7
|
import type { TmuxControlClient } from "./tmux-control.js";
|
|
8
8
|
import type { FleetInstructionsParams } from "./instructions.js";
|
|
9
|
+
import type { SpawnGate } from "./spawn-gate.js";
|
|
10
|
+
import type { StormWindow } from "./storm-window.js";
|
|
11
|
+
import type { BackendOutageView } from "./backend-outage.js";
|
|
9
12
|
/** Point a resumed CLI at its one backend-native instruction source. */
|
|
10
13
|
export declare function buildInstructionReloadNotice(binaryName: string, instanceName: string, instanceDir: string): string;
|
|
11
14
|
export declare const DEFAULT_STUCK_TIMEOUT_MS: number;
|
|
12
15
|
export declare const DEFAULT_STATE_IDLE_DEBOUNCE_MS = 2000;
|
|
13
16
|
export declare const DEFAULT_STATE_SAFETY_SWEEP_MS = 60000;
|
|
17
|
+
/** Coalesce one cosmetic-redraw burst before comparing the visible pane. */
|
|
18
|
+
export declare const PERIODIC_REDRAW_PROBE_MS = 25;
|
|
19
|
+
/** A foreground server/port-forward should hand control back or be acknowledged. */
|
|
20
|
+
export declare const DEFAULT_BLOCKING_PROCESS_GRACE_MS: number;
|
|
14
21
|
/**
|
|
15
22
|
* Whether two working directories belong to the same project, so a fleet-scoped
|
|
16
23
|
* decision recorded in one reaches the other. Covers the worktree/checkout
|
|
@@ -62,11 +69,13 @@ export declare function writeLastInboundAt(instanceDir: string, timestamp: numbe
|
|
|
62
69
|
export declare function renderHandoffMetadata(meta: Record<string, string>): string;
|
|
63
70
|
/** Headless inactivity timer used by the daemon and unit tests. */
|
|
64
71
|
export declare class AutoPauseController {
|
|
65
|
-
private
|
|
72
|
+
private thresholdMs;
|
|
66
73
|
private lastActivityAt;
|
|
67
74
|
private pausedAt;
|
|
68
75
|
constructor(thresholdMs: number, lastActivityAt?: number);
|
|
69
76
|
recordActivity(now?: number): void;
|
|
77
|
+
/** Apply a new idle threshold and start a fresh countdown from this update. */
|
|
78
|
+
reconfigure(thresholdMs: number, now?: number): void;
|
|
70
79
|
observe(state: InstanceState, now?: number): boolean;
|
|
71
80
|
markPaused(now?: number): void;
|
|
72
81
|
markAwake(now?: number): void;
|
|
@@ -142,10 +151,13 @@ export declare class PaneStateMachine {
|
|
|
142
151
|
* working" and a finished turn would not be seen as idle until the next 60s
|
|
143
152
|
* safety sweep. Output timestamps are the honest liveness signal here, and
|
|
144
153
|
* the caller has them.
|
|
154
|
+
* @param opts.forceBusy the backend has positively identified a still-running
|
|
155
|
+
* foreground tool even though its TUI keeps an old ready footer visible.
|
|
145
156
|
*/
|
|
146
157
|
observe(pane: string, now?: number, opts?: {
|
|
147
158
|
settled?: boolean;
|
|
148
159
|
changeAt?: number;
|
|
160
|
+
forceBusy?: boolean;
|
|
149
161
|
}): InstanceStateSnapshot;
|
|
150
162
|
/** Record pane motion from tmux control mode without capturing pane content. */
|
|
151
163
|
recordOutput(now?: number): InstanceStateSnapshot;
|
|
@@ -163,6 +175,14 @@ export declare class PendingWorkTracker {
|
|
|
163
175
|
recordIdle(now?: number): void;
|
|
164
176
|
hasPendingWork(): boolean;
|
|
165
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Startup failed because the CLI's backend is unreachable (see backend-outage.ts).
|
|
180
|
+
* The session-id is deliberately KEPT; the fleet schedules a delayed retry.
|
|
181
|
+
*/
|
|
182
|
+
export declare class BackendUnreachableStartupError extends Error {
|
|
183
|
+
readonly backend: string;
|
|
184
|
+
constructor(backend: string);
|
|
185
|
+
}
|
|
166
186
|
/**
|
|
167
187
|
* One-shot timing gate for the first paste after a CLI reaches its ready
|
|
168
188
|
* prompt. A TUI that is still completing its first redraw can swallow Enter.
|
|
@@ -237,6 +257,26 @@ export declare function extractProxyReplyText(pane: string, opts?: {
|
|
|
237
257
|
maxLines?: number;
|
|
238
258
|
maxChars?: number;
|
|
239
259
|
}): string | null;
|
|
260
|
+
export interface MalformedClaudeToolCallDetection {
|
|
261
|
+
/** Stable, non-secret fingerprint used to suppress a stale pane fragment. */
|
|
262
|
+
signature: string;
|
|
263
|
+
/** Sanitized reply argument, or null when only a dangling closing tag survived. */
|
|
264
|
+
text: string | null;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Find the narrow Claude XML failure signature reported in #648.
|
|
268
|
+
*
|
|
269
|
+
* This intentionally runs only at the daemon's busy→idle edge (the caller
|
|
270
|
+
* enforces that) and only scans output after the current inbound marker. A
|
|
271
|
+
* partial tool call while Claude is still streaming is therefore never acted
|
|
272
|
+
* on. The extracted argument goes through the same credential redaction as the
|
|
273
|
+
* dead-MCP pane proxy before it can leave the host.
|
|
274
|
+
*/
|
|
275
|
+
export declare function detectMalformedClaudeToolCall(pane: string, opts?: {
|
|
276
|
+
inboundMarker?: string;
|
|
277
|
+
maxLines?: number;
|
|
278
|
+
maxChars?: number;
|
|
279
|
+
}): MalformedClaudeToolCallDetection | null;
|
|
240
280
|
export type InteractivePromptKind = "sudo_password" | "password" | "confirmation" | "press_enter";
|
|
241
281
|
export interface InteractivePromptDetection {
|
|
242
282
|
kind: InteractivePromptKind;
|
|
@@ -258,6 +298,30 @@ export declare class InteractivePromptDetector {
|
|
|
258
298
|
observe(pane: string, now?: number, outputAt?: number): InteractivePromptDetection | null;
|
|
259
299
|
reset(): void;
|
|
260
300
|
}
|
|
301
|
+
export interface BlockingProcessDetection {
|
|
302
|
+
activity: string;
|
|
303
|
+
evidence: string;
|
|
304
|
+
blockedForMs: number;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Detect a foreground shell tool which has become a long-lived server.
|
|
308
|
+
*
|
|
309
|
+
* Unlike the generic pane-stuck clock, this clock deliberately survives new
|
|
310
|
+
* output: access logs and `Handling connection` lines are exactly why a
|
|
311
|
+
* foreground server can remain blocked forever without ever looking silent.
|
|
312
|
+
* Once a server marker is seen, the still-running tool identity is the stable
|
|
313
|
+
* signal; the marker may scroll out of the 32-row pane.
|
|
314
|
+
*/
|
|
315
|
+
export declare class BlockingProcessDetector {
|
|
316
|
+
private readonly graceMs;
|
|
317
|
+
private activity;
|
|
318
|
+
private evidence;
|
|
319
|
+
private detectedAt;
|
|
320
|
+
private notified;
|
|
321
|
+
constructor(graceMs?: number);
|
|
322
|
+
observe(pane: string, activity: string | null, now?: number): BlockingProcessDetection | null;
|
|
323
|
+
reset(): void;
|
|
324
|
+
}
|
|
261
325
|
export declare class Daemon extends EventEmitter {
|
|
262
326
|
private name;
|
|
263
327
|
private config;
|
|
@@ -266,6 +330,10 @@ export declare class Daemon extends EventEmitter {
|
|
|
266
330
|
private backend?;
|
|
267
331
|
private controlClient?;
|
|
268
332
|
private runtimeIdentity?;
|
|
333
|
+
private spawnGate?;
|
|
334
|
+
private stormWindow?;
|
|
335
|
+
/** Fleet-level "is this CLI's backend down?" memory — see backend-outage.ts. */
|
|
336
|
+
private backendOutage?;
|
|
269
337
|
private logger;
|
|
270
338
|
private tmuxSessionName;
|
|
271
339
|
private tmux;
|
|
@@ -275,6 +343,13 @@ export declare class Daemon extends EventEmitter {
|
|
|
275
343
|
private guardian;
|
|
276
344
|
private adapter;
|
|
277
345
|
private pendingIpcRequests;
|
|
346
|
+
/**
|
|
347
|
+
* Daemon-global request sequence. MCP request ids are only process-local:
|
|
348
|
+
* Claude can have more than one MCP child connected to the same daemon and
|
|
349
|
+
* each starts at 1, so using requestId alone lets one caller steal another's
|
|
350
|
+
* response.
|
|
351
|
+
*/
|
|
352
|
+
private fleetRequestSeq;
|
|
278
353
|
private lastChatId;
|
|
279
354
|
private lastThreadId;
|
|
280
355
|
private lastAdapterId;
|
|
@@ -282,9 +357,6 @@ export declare class Daemon extends EventEmitter {
|
|
|
282
357
|
/** Last activity published to the fleet manager; null when nothing is running. */
|
|
283
358
|
private currentActivity;
|
|
284
359
|
private socketSessionNames;
|
|
285
|
-
private static tmuxServerCrashTimestamps;
|
|
286
|
-
private static tmuxServerPaused;
|
|
287
|
-
private static tmuxServerRecoveryTimer;
|
|
288
360
|
private healthCheckTimer;
|
|
289
361
|
private crashCount;
|
|
290
362
|
private lastCrashAt;
|
|
@@ -305,6 +377,7 @@ export declare class Daemon extends EventEmitter {
|
|
|
305
377
|
private resolveSpawnSettled;
|
|
306
378
|
private spawnDepth;
|
|
307
379
|
private skipResume;
|
|
380
|
+
private startupAborted;
|
|
308
381
|
private backgroundSessionRecoveryAttempted;
|
|
309
382
|
/** Whether the last spawn started a fresh session (not resumed). */
|
|
310
383
|
isNewSession: boolean;
|
|
@@ -317,6 +390,7 @@ export declare class Daemon extends EventEmitter {
|
|
|
317
390
|
/** Fallback safety sweep used only when no shared tmux control client exists. */
|
|
318
391
|
private instanceStateMonitorTimer;
|
|
319
392
|
private instanceStateIdleTimer;
|
|
393
|
+
private instanceStateOutputProbeTimer;
|
|
320
394
|
private instanceStateStuckTimer;
|
|
321
395
|
private instanceStateOutputListener;
|
|
322
396
|
private instanceStateOutputEventName;
|
|
@@ -327,11 +401,16 @@ export declare class Daemon extends EventEmitter {
|
|
|
327
401
|
private instanceStateReadyPattern;
|
|
328
402
|
private instanceStateBusyPattern;
|
|
329
403
|
private instanceStateMonitorActive;
|
|
404
|
+
private sessionCheckpointWarningEmitted;
|
|
330
405
|
private statePollInFlight;
|
|
331
406
|
private turnHadInbound;
|
|
332
407
|
private turnOutboundDelivered;
|
|
408
|
+
/** Successful `reply` specifically; cross-instance tools do not satisfy #648. */
|
|
409
|
+
private turnReplyDelivered;
|
|
333
410
|
private turnCorrelationId;
|
|
334
411
|
private turnInboundMarker;
|
|
412
|
+
/** Prevent a visible stale XML fragment from being recovered on later turns. */
|
|
413
|
+
private lastMalformedToolCallSignature;
|
|
335
414
|
private proxyReplySeq;
|
|
336
415
|
private autoPauseController;
|
|
337
416
|
private pauseRequested;
|
|
@@ -342,6 +421,35 @@ export declare class Daemon extends EventEmitter {
|
|
|
342
421
|
* would silently no-op exactly when we most need to stop feeding the CLI.
|
|
343
422
|
*/
|
|
344
423
|
private pausePending;
|
|
424
|
+
/**
|
|
425
|
+
* An auth failure was detected and nothing has resolved it yet.
|
|
426
|
+
*
|
|
427
|
+
* Separate from `pausePending` because it must outlive it: the deferred pause
|
|
428
|
+
* clears `pausePending` as soon as it fires, but if that pause is refused the
|
|
429
|
+
* instance is still auth-broken and must not resume raising alarms.
|
|
430
|
+
*/
|
|
431
|
+
private authFailureUnresolved;
|
|
432
|
+
/** One login-screen auth report per spawn — the screen persists across polls. */
|
|
433
|
+
private loginScreenReported;
|
|
434
|
+
/** A fatal startup screen (see StartupDialog.fatal) was already reported this run. */
|
|
435
|
+
private fatalStartupReported;
|
|
436
|
+
/**
|
|
437
|
+
* The CLI is parked on a fatal startup screen and every pane write must be
|
|
438
|
+
* refused. This is deliberately separate from the pause that the reported
|
|
439
|
+
* pty_error triggers: the pause is applied by an async handler, and a queued
|
|
440
|
+
* delivery would race it into the modal (where paste+Enter can confirm
|
|
441
|
+
* "Exit and fix manually"). Set synchronously at dialog-match time; cleared
|
|
442
|
+
* when a startup scan reaches a real ready prompt, or on wake().
|
|
443
|
+
*/
|
|
444
|
+
private fatalStartupBlocked;
|
|
445
|
+
/** model_error seen mid-turn: notify only if it survives to the idle screen. */
|
|
446
|
+
private pendingModelErrorKey;
|
|
447
|
+
/**
|
|
448
|
+
* Let the next pause() proceed from a stuck pane. Set only for the auth-deferred
|
|
449
|
+
* pause — see the pausePending consumption site for why waiting for idle there
|
|
450
|
+
* is waiting forever.
|
|
451
|
+
*/
|
|
452
|
+
private pauseAllowStuck;
|
|
345
453
|
private pauseWakeState;
|
|
346
454
|
private pauseWakeTransition;
|
|
347
455
|
private modelOverride;
|
|
@@ -353,6 +461,12 @@ export declare class Daemon extends EventEmitter {
|
|
|
353
461
|
* and ⏳/👀/✅ reactions live here). It does NOT cover the other writers that
|
|
354
462
|
* reach the pane — {@link paneWriteLock} does. */
|
|
355
463
|
private pasteLock;
|
|
464
|
+
/**
|
|
465
|
+
* Fleet cancellation epoch. Queue entries retain the epoch they arrived with;
|
|
466
|
+
* advancing it invalidates only work received before the cancel, never a new
|
|
467
|
+
* user message which arrives immediately afterwards.
|
|
468
|
+
*/
|
|
469
|
+
private deliveryEpoch;
|
|
356
470
|
/** Mutual exclusion for *every* write into the pane, whichever subsystem it
|
|
357
471
|
* comes from. See PaneWriteLock for why interleaving is destructive. */
|
|
358
472
|
private readonly paneWriteLock;
|
|
@@ -362,8 +476,20 @@ export declare class Daemon extends EventEmitter {
|
|
|
362
476
|
private lastBuiltInstructions;
|
|
363
477
|
private pasteQueueDepth;
|
|
364
478
|
private firstDeliveryDelay;
|
|
479
|
+
/** Orders /steer pastes against each other. Deliberately NOT pasteLock:
|
|
480
|
+
* a steer must not queue behind the normal deliveries it exists to
|
|
481
|
+
* overtake. Pane-level exclusion still comes from paneWriteLock inside
|
|
482
|
+
* deliverMessage, so a steer and a normal delivery can never interleave
|
|
483
|
+
* their PTY writes — the steer just doesn't wait for idle. */
|
|
484
|
+
private steerLock;
|
|
485
|
+
/** Tool lines shown in the channel processing bubble for the current turn. */
|
|
486
|
+
private readonly turnProgress;
|
|
487
|
+
private lastProgressBroadcast;
|
|
488
|
+
private progressBroadcastTimer;
|
|
489
|
+
private lastProgressBroadcastAt;
|
|
365
490
|
private errorMonitorTimer;
|
|
366
491
|
private readonly interactivePromptDetector;
|
|
492
|
+
private readonly blockingProcessDetector;
|
|
367
493
|
/** Same 5-min gate the error monitor uses, so a dead MCP server alerts once. */
|
|
368
494
|
private static readonly MCP_DEATH_COOLDOWN_MS;
|
|
369
495
|
private lastMcpDeathNotifiedAt;
|
|
@@ -375,6 +501,16 @@ export declare class Daemon extends EventEmitter {
|
|
|
375
501
|
* past this point interrupting the turn costs less than staying mute.
|
|
376
502
|
*/
|
|
377
503
|
private static readonly MCP_RESTART_MAX_WAIT_MS;
|
|
504
|
+
/**
|
|
505
|
+
* How long the revival restart waits, at the point of firing, for a
|
|
506
|
+
* CLI-respawned MCP server to announce itself.
|
|
507
|
+
*
|
|
508
|
+
* Codex <0.146 tears down and recreates ALL MCP connections on an auth/config
|
|
509
|
+
* change — healthy ones included — so the daemon sees the old pid die while
|
|
510
|
+
* the CLI is fine and a replacement is seconds away. Module load measured
|
|
511
|
+
* ~0.36s, so 2s is roughly 5x headroom without making a genuine loss wait.
|
|
512
|
+
*/
|
|
513
|
+
private static readonly MCP_REPLACEMENT_GRACE_MS;
|
|
378
514
|
/**
|
|
379
515
|
* Sticky "restart to revive the MCP server as soon as the pane idles" — same
|
|
380
516
|
* shape as pausePending, because the death is usually detected mid-turn when
|
|
@@ -383,6 +519,25 @@ export declare class Daemon extends EventEmitter {
|
|
|
383
519
|
*/
|
|
384
520
|
private mcpRestartPending;
|
|
385
521
|
private mcpRestartStaleTimer;
|
|
522
|
+
/** In-flight replacement grace; also the guard against three triggers stacking. */
|
|
523
|
+
private mcpRestartGraceTimer;
|
|
524
|
+
/**
|
|
525
|
+
* Which trigger the in-flight grace will commit under.
|
|
526
|
+
*
|
|
527
|
+
* The single-timer guard would otherwise SWALLOW a stale_timeout that lands
|
|
528
|
+
* during an idle-gated grace — and because the stale timer is one-shot and
|
|
529
|
+
* already cleared itself, the 30-minute backstop would be gone for good on an
|
|
530
|
+
* instance that never idles, which is the exact case it exists for.
|
|
531
|
+
*/
|
|
532
|
+
private mcpRestartGraceTrigger;
|
|
533
|
+
/**
|
|
534
|
+
* A dead-MCP sighting held back once, pending a possible replacement.
|
|
535
|
+
*
|
|
536
|
+
* Deliberately NOT the same field as `mcpDeathNotifiedForPid`: deferring must
|
|
537
|
+
* not consume the once-per-pid budget, or a suspicion that turns out to be a
|
|
538
|
+
* real loss could never be reported at all.
|
|
539
|
+
*/
|
|
540
|
+
private mcpDeathDeferredForPid;
|
|
386
541
|
/** Prevent in-flight monitor callbacks from re-arming after a pause. */
|
|
387
542
|
private runtimeMonitorsFrozen;
|
|
388
543
|
private errorWaitingForRecovery;
|
|
@@ -409,7 +564,9 @@ export declare class Daemon extends EventEmitter {
|
|
|
409
564
|
private lastDetectedErrorType;
|
|
410
565
|
private static errorPatternKey;
|
|
411
566
|
private clearErrorRecoveryGate;
|
|
412
|
-
constructor(name: string, config: InstanceConfig, instanceDir: string, topicMode?: boolean, backend?: CliBackend | undefined, controlClient?: TmuxControlClient | undefined, rootLogger?: Logger, runtimeIdentity?: FleetInstructionsParams["runtimeIdentity"]
|
|
567
|
+
constructor(name: string, config: InstanceConfig, instanceDir: string, topicMode?: boolean, backend?: CliBackend | undefined, controlClient?: TmuxControlClient | undefined, rootLogger?: Logger, runtimeIdentity?: FleetInstructionsParams["runtimeIdentity"], spawnGate?: SpawnGate | undefined, stormWindow?: StormWindow | undefined,
|
|
568
|
+
/** Fleet-level "is this CLI's backend down?" memory — see backend-outage.ts. */
|
|
569
|
+
backendOutage?: BackendOutageView | undefined);
|
|
413
570
|
start(): Promise<void>;
|
|
414
571
|
/**
|
|
415
572
|
* Detect a CRASHED MCP server and report it once.
|
|
@@ -425,7 +582,22 @@ export declare class Daemon extends EventEmitter {
|
|
|
425
582
|
* process would have no client reading it. Only the CLI can restore its own
|
|
426
583
|
* tools — hence notify, and let the operator decide about restarting.
|
|
427
584
|
*/
|
|
585
|
+
/**
|
|
586
|
+
* An MCP server has connected and announced itself.
|
|
587
|
+
*
|
|
588
|
+
* Beyond the existing session bookkeeping this is the earliest evidence that
|
|
589
|
+
* tools are back — roughly 30s ahead of the next health tick, which is
|
|
590
|
+
* exactly the window #663's false restarts fired in.
|
|
591
|
+
*/
|
|
592
|
+
private handleMcpReady;
|
|
428
593
|
private checkMcpServerAlive;
|
|
594
|
+
/**
|
|
595
|
+
* Whether a dead MCP pid on this backend is more likely a CLI-driven
|
|
596
|
+
* replacement than a real loss. Codex only, and deliberately narrow: it is
|
|
597
|
+
* the backend whose released fix (0.146) confirms it tore down healthy MCP
|
|
598
|
+
* connections alongside the one it meant to restart.
|
|
599
|
+
*/
|
|
600
|
+
private suspectsTransientMcpReplacement;
|
|
429
601
|
/**
|
|
430
602
|
* Arm an automatic instance restart to revive a dead MCP server. Fires on the
|
|
431
603
|
* next busy→idle edge — or immediately when the pane is already idle, which is
|
|
@@ -434,7 +606,36 @@ export declare class Daemon extends EventEmitter {
|
|
|
434
606
|
* force-restarted: see that constant for why staying mute costs more.
|
|
435
607
|
*/
|
|
436
608
|
private armMcpRestartWhenIdle;
|
|
609
|
+
/**
|
|
610
|
+
* Single chokepoint for all three revival triggers (already_idle, idle_edge,
|
|
611
|
+
* stale_timeout) — and therefore the one place worth re-checking reality.
|
|
612
|
+
*
|
|
613
|
+
* The pending flag is armed by a health tick that saw the OLD pid die, and
|
|
614
|
+
* was previously fired without ever looking again. When a CLI legitimately
|
|
615
|
+
* respawns its own MCP child, the replacement is already serving by the time
|
|
616
|
+
* the turn ends — but the idle edge fires inside the ~30s before the next
|
|
617
|
+
* health tick can stand the request down, restarting a healthy instance. One
|
|
618
|
+
* external user was restarted 18 times in two days this way (#663).
|
|
619
|
+
*
|
|
620
|
+
* Re-reading here is safe for every backend: worst case it clears a pending
|
|
621
|
+
* restart that should not have existed.
|
|
622
|
+
*/
|
|
437
623
|
private fireMcpRestartRequest;
|
|
624
|
+
/**
|
|
625
|
+
* A recovery is already reshaping the CLI: crash-loop handling
|
|
626
|
+
* (healthCheckPaused), a respawn in flight (spawning), or a pause
|
|
627
|
+
* (isPaused / frozen monitors). Each ends in a fresh CLI — and with it a
|
|
628
|
+
* fresh MCP server — or in supervision ending, where a restart on top would
|
|
629
|
+
* fight the recovery. Either way the revival restart is moot.
|
|
630
|
+
*/
|
|
631
|
+
private mcpRestartCancelledByRecovery;
|
|
632
|
+
/**
|
|
633
|
+
* Emit a dead-MCP report that was held back as a suspected replacement, once
|
|
634
|
+
* it is clear no replacement is coming. Consumes the once-per-pid budget
|
|
635
|
+
* here — deferring was to avoid spending it on a false alarm, not to drop
|
|
636
|
+
* the incident.
|
|
637
|
+
*/
|
|
638
|
+
private reportDeferredMcpDeath;
|
|
438
639
|
private clearMcpRestartRequest;
|
|
439
640
|
private startHealthCheck;
|
|
440
641
|
/**
|
|
@@ -468,6 +669,8 @@ export declare class Daemon extends EventEmitter {
|
|
|
468
669
|
private startErrorMonitor;
|
|
469
670
|
/** Evaluate one pane snapshot. Kept synchronous so state-machine edges are unit-testable. */
|
|
470
671
|
private evaluateErrorPatterns;
|
|
672
|
+
/** Arm the recovery gates and emit one detected error pattern. */
|
|
673
|
+
private emitErrorPattern;
|
|
471
674
|
/**
|
|
472
675
|
* Notification text for a detected pattern. `formatMessage` patterns build it
|
|
473
676
|
* from the match so the user gets the specifics (e.g. which period and what
|
|
@@ -489,12 +692,37 @@ export declare class Daemon extends EventEmitter {
|
|
|
489
692
|
* that message, which is what the user asked for anyway.
|
|
490
693
|
*/
|
|
491
694
|
sendEscape(): Promise<void>;
|
|
695
|
+
/**
|
|
696
|
+
* Drop every not-yet-started pane delivery which predates a user cancel.
|
|
697
|
+
* Promise chains cannot be removed, so entries become generation-checked
|
|
698
|
+
* no-ops. An entry already past its check is allowed to finish its current PTY
|
|
699
|
+
* transaction; the interrupt key still cancels the CLI generation.
|
|
700
|
+
*/
|
|
701
|
+
clearPendingDeliveries(fleetEpoch?: number): void;
|
|
702
|
+
private captureDeliveryEpoch;
|
|
703
|
+
private isDeliveryEpochCurrent;
|
|
704
|
+
private queueRawPaste;
|
|
705
|
+
/**
|
|
706
|
+
* Confirm a backend's terminal-level /clear prompt after the channel-level
|
|
707
|
+
* admin confirmation has already succeeded. Poll instead of pasting `/clear\ny`
|
|
708
|
+
* as one buffer: Kiro versions that clear immediately interpret that queued
|
|
709
|
+
* `y` as a brand-new user message.
|
|
710
|
+
*/
|
|
711
|
+
private confirmBackendClearDialog;
|
|
492
712
|
/** Send the backend-specific graceful quit command/key sequence. */
|
|
493
713
|
private sendQuitSequence;
|
|
494
714
|
stop(): Promise<void>;
|
|
495
715
|
getHangDetector(): HangDetector | null;
|
|
496
716
|
getInstanceState(): InstanceState | "paused";
|
|
497
717
|
getInstanceStateSnapshot(): InstanceStateSnapshot;
|
|
718
|
+
/**
|
|
719
|
+
* Answer a FleetManager state query. Most callers only need the cached state,
|
|
720
|
+
* but lifecycle decisions such as post-reply Cancel retirement need an
|
|
721
|
+
* authoritative pane observation: after startup the last transition can stay
|
|
722
|
+
* "working" even though the CLI has since settled without emitting another
|
|
723
|
+
* control-mode output record.
|
|
724
|
+
*/
|
|
725
|
+
private respondToInstanceStateQuery;
|
|
498
726
|
/** Gracefully stop the CLI while keeping its remain-on-exit tmux window. */
|
|
499
727
|
/**
|
|
500
728
|
* Mark the instance to pause as soon as its pane is idle. Used for auth
|
|
@@ -521,9 +749,21 @@ export declare class Daemon extends EventEmitter {
|
|
|
521
749
|
* here (edge-triggered, then reset) is what makes it at most once per turn.
|
|
522
750
|
*/
|
|
523
751
|
private maybeProxyReplyOnTurnEnd;
|
|
752
|
+
private isClaudeCodeBackend;
|
|
524
753
|
/** Relay the pane's final text to the channel, marked as a daemon proxy reply. */
|
|
525
754
|
private sendProxyReply;
|
|
755
|
+
/** Send a narrowly extracted #648 reply; operator notification is a separate event. */
|
|
756
|
+
private sendRecoveredMalformedReply;
|
|
757
|
+
/** Context-bound reply path shared by dead-MCP and malformed-call recovery. */
|
|
758
|
+
private deliverDaemonReply;
|
|
526
759
|
private clearInstanceStateIdleTimer;
|
|
760
|
+
private clearInstanceStateOutputProbeTimer;
|
|
761
|
+
/**
|
|
762
|
+
* Periodic status-line hooks can generate `%output` without changing a single
|
|
763
|
+
* visible cell. Probe the pane once per burst: a changed capture is real work;
|
|
764
|
+
* an identical ready capture remains idle and emits no state edge.
|
|
765
|
+
*/
|
|
766
|
+
private scheduleInstanceStateOutputProbe;
|
|
527
767
|
private clearInstanceStateStuckTimer;
|
|
528
768
|
private scheduleInstanceStateStuckDeadline;
|
|
529
769
|
private scheduleInstanceStateIdleCapture;
|
|
@@ -542,14 +782,48 @@ export declare class Daemon extends EventEmitter {
|
|
|
542
782
|
* Tell the fleet manager what this instance is doing right now, for the live
|
|
543
783
|
* progress line on the cancel button.
|
|
544
784
|
*
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
*
|
|
785
|
+
* Primarily cosmetic. The foreground-process detector also uses a current
|
|
786
|
+
* shell activity as one of several positive signals, but never makes a state
|
|
787
|
+
* decision from an arbitrary activity label alone.
|
|
548
788
|
*
|
|
549
789
|
* Repeats are dropped: the ticker only edits the channel message when the text
|
|
550
790
|
* changes, and a stream of identical broadcasts would defeat that.
|
|
551
791
|
*/
|
|
552
792
|
private publishActivity;
|
|
793
|
+
/** Effective tool_progress level, hardened against junk config values.
|
|
794
|
+
* Off unless explicitly enabled: an update must never make bubbles start
|
|
795
|
+
* listing tool activity the operator did not ask to broadcast. */
|
|
796
|
+
private toolProgressLevel;
|
|
797
|
+
/**
|
|
798
|
+
* Apply a tool-progress setting without restarting the CLI session.
|
|
799
|
+
*
|
|
800
|
+
* Drop the current accumulator at the boundary: verbose entries may contain
|
|
801
|
+
* command previews which must not survive a downgrade to standard/off, and a
|
|
802
|
+
* newly enabled level should start with a clean, internally consistent list.
|
|
803
|
+
*/
|
|
804
|
+
updateToolProgress(level: InstanceConfig["tool_progress"]): void;
|
|
805
|
+
/** Snapshot the configuration actually owned by this live daemon. */
|
|
806
|
+
getConfigSnapshot(): InstanceConfig;
|
|
807
|
+
/**
|
|
808
|
+
* Apply the whitelisted hot configuration carried by FleetManager IPC.
|
|
809
|
+
* null removes an optional value; invalid/unlisted fields are ignored rather
|
|
810
|
+
* than allowing another client on the per-instance socket to mutate cold
|
|
811
|
+
* process/session settings.
|
|
812
|
+
*/
|
|
813
|
+
applyConfigUpdate(value: unknown): void;
|
|
814
|
+
/**
|
|
815
|
+
* Accumulate one semantic progress line for the channel bubble and schedule
|
|
816
|
+
* a coalesced broadcast. Separate from publishActivity on purpose: that one
|
|
817
|
+
* is the single-line statusline detail (terse, operator-facing), this is the
|
|
818
|
+
* multi-line channel list (semantic, argument-free at `standard`) — see
|
|
819
|
+
* tool-progress.ts for why the two labellers must not merge.
|
|
820
|
+
*/
|
|
821
|
+
private recordToolProgress;
|
|
822
|
+
/** Coalesce progress broadcasts: at most one per 3s, trailing edge kept. */
|
|
823
|
+
private scheduleProgressBroadcast;
|
|
824
|
+
private broadcastToolProgress;
|
|
825
|
+
/** New turn (or turn over): drop the list and tell the fleet to clear it. */
|
|
826
|
+
private resetToolProgress;
|
|
553
827
|
/**
|
|
554
828
|
* Options for every system-initiated paste (startup notice, session snapshot,
|
|
555
829
|
* runtime-dialog keys).
|
|
@@ -561,12 +835,43 @@ export declare class Daemon extends EventEmitter {
|
|
|
561
835
|
*/
|
|
562
836
|
private systemPasteOptions;
|
|
563
837
|
private summarizeTool;
|
|
838
|
+
/**
|
|
839
|
+
* The one place an inbound message grows its metadata wrapper ([user:]/
|
|
840
|
+
* [from:] prefix, pending reactions, handoff metadata, reply instructions).
|
|
841
|
+
* Both the normal queued path (pushChannelMessage) and /steer go through
|
|
842
|
+
* here — a steered message must read EXACTLY like a queued one to the
|
|
843
|
+
* agent, or the two drift apart in what the agent is told about replying.
|
|
844
|
+
*/
|
|
845
|
+
private formatInboundMessage;
|
|
846
|
+
/**
|
|
847
|
+
* /steer: interject into the CURRENT turn instead of queueing for idle.
|
|
848
|
+
*
|
|
849
|
+
* Differences from pushChannelMessage, and nothing else:
|
|
850
|
+
* - serialized on steerLock, not pasteLock — it must overtake, not queue
|
|
851
|
+
* - deliverMessage runs with { steer: true }, which takes the busy branch
|
|
852
|
+
* that pastes immediately (the codex native-queue transaction) instead of
|
|
853
|
+
* waiting for idle. Verification and silent-loss fallback are the ones
|
|
854
|
+
* that path already has: pane-capture visibility check, then one
|
|
855
|
+
* idle-gated redelivery — so on a TUI that swallows busy input the steer
|
|
856
|
+
* degrades to "next message after this turn", never silently vanishes.
|
|
857
|
+
*
|
|
858
|
+
* The steered text goes through formatInboundMessage so the agent sees a
|
|
859
|
+
* normal inbound message, with a steering notice prepended for context.
|
|
860
|
+
*/
|
|
861
|
+
steerMessage(content: string, meta: Record<string, string>, deliveryEpoch?: number): void;
|
|
862
|
+
/**
|
|
863
|
+
* /btw: submit a separately-labelled side question immediately while asking
|
|
864
|
+
* the agent not to change the active task. Claude's native `/btw` opens a
|
|
865
|
+
* branchAndResume panel whose answer never reaches the channel or transcript,
|
|
866
|
+
* so channel delivery intentionally uses a normal wrapped inbound instead.
|
|
867
|
+
*/
|
|
868
|
+
btwMessage(content: string, meta: Record<string, string>, deliveryEpoch?: number): void;
|
|
564
869
|
/**
|
|
565
870
|
* Push an inbound channel message to a specific MCP session.
|
|
566
871
|
* If targetSession is provided, only send to the matching socket.
|
|
567
872
|
* Otherwise send to the instance's own session (this.name).
|
|
568
873
|
*/
|
|
569
|
-
pushChannelMessage(content: string, meta: Record<string, string>, _targetSession?: string): void;
|
|
874
|
+
pushChannelMessage(content: string, meta: Record<string, string>, _targetSession?: string, deliveryEpoch?: number): void;
|
|
570
875
|
/**
|
|
571
876
|
* Deliver a single message and drive its status reactions:
|
|
572
877
|
* ⏳ message_queued — CLI busy; queued locally or by the backend
|
|
@@ -584,6 +889,77 @@ export declare class Daemon extends EventEmitter {
|
|
|
584
889
|
* serial in both cases so separate PTY writes can never overlap.
|
|
585
890
|
*/
|
|
586
891
|
private deliverMessage;
|
|
892
|
+
/**
|
|
893
|
+
* Bottom-anchored readiness for TUIs that drop Enter while busy (see
|
|
894
|
+
* CliBackend.dropsEnterWhileBusy). Output silence is necessary but not
|
|
895
|
+
* sufficient for them: Kiro paints nothing for the whole duration of a shell
|
|
896
|
+
* or MCP tool call (and for each 10s backend retry), yet an Enter arriving
|
|
897
|
+
* then is discarded. Reproduced deterministically: `sleep 9` tool, paste at
|
|
898
|
+
* t+6s → text stranded in the prompt row, next message submitted both.
|
|
899
|
+
* Other backends keep the silence-based gate byte-for-byte.
|
|
900
|
+
*/
|
|
901
|
+
private isPaneReadyForDelivery;
|
|
902
|
+
/**
|
|
903
|
+
* Like waitForPaneIdleForDelivery, plus the bottom-anchored prompt check for
|
|
904
|
+
* Enter-dropping TUIs. Polls at a coarse cadence (each poll is a capture-pane)
|
|
905
|
+
* only after the pane is already quiet, so the common fast-idle delivery still
|
|
906
|
+
* costs a single capture.
|
|
907
|
+
*/
|
|
908
|
+
private waitForPaneReadyForDelivery;
|
|
909
|
+
/**
|
|
910
|
+
* F3: if an AgEnD message is sitting unsubmitted in the input row (a previous
|
|
911
|
+
* delivery's Enter was dropped), submit it with one bare Enter under the pane
|
|
912
|
+
* lock. Only acts on a positive signature — the `[user:`/`[from:` marker every
|
|
913
|
+
* pasted message carries — never on Kiro's own placeholder hints.
|
|
914
|
+
*
|
|
915
|
+
* Outcomes: "idle" = positively verified nothing stranded (the caller may
|
|
916
|
+
* paste); "submitted" = an Enter went out for the stranded text; "busy" = the
|
|
917
|
+
* pane is not at its prompt or could not be read (the caller must wait for
|
|
918
|
+
* the prompt and run this check AGAIN before pasting — never assume someone
|
|
919
|
+
* else submitted it); "failed" = the Enter could not be sent (the delivery
|
|
920
|
+
* must fail rather than paste on top of the stranded text).
|
|
921
|
+
*/
|
|
922
|
+
private submitStrandedInputIfAny;
|
|
923
|
+
/**
|
|
924
|
+
* "stranded": an AgEnD message sits in the input row; "clear": the prompt is
|
|
925
|
+
* at the bottom with no stranded text; "busy": generating, or the prompt is
|
|
926
|
+
* not at the bottom (incl. a blank frame); "unknown": the pane could not be
|
|
927
|
+
* read. Only "clear" is positive evidence.
|
|
928
|
+
*/
|
|
929
|
+
private strandedInputState;
|
|
930
|
+
/**
|
|
931
|
+
* F2: for Enter-dropping TUIs, "some output after Enter" proves nothing — the
|
|
932
|
+
* turn that made the pane look idle keeps producing output. Confirm the
|
|
933
|
+
* SUBMISSION instead: the pasted text is gone from the input row ("absent"),
|
|
934
|
+
* or the TUI's own busy marker is up. "unknown" = the pane could not be read;
|
|
935
|
+
* it never counts as confirmed.
|
|
936
|
+
*/
|
|
937
|
+
private pasteResidue;
|
|
938
|
+
/**
|
|
939
|
+
* Submission = the legacy idle→busy output signal AND the pasted text has
|
|
940
|
+
* verifiably left the input row. The first alone is what produced false ✅s:
|
|
941
|
+
* the turn that made the pane look idle keeps emitting output after our
|
|
942
|
+
* (dropped) Enter — and an unreadable pane is not a verified absence either.
|
|
943
|
+
*/
|
|
944
|
+
private confirmSubmittedAfterEnter;
|
|
945
|
+
/**
|
|
946
|
+
* While the CLI is parked on a fatal startup screen (see fatalStartupBlocked),
|
|
947
|
+
* no pane write may happen: paste+Enter into the corrupt-config modal would
|
|
948
|
+
* confirm "Exit and fix manually" and exit the CLI. The message is failed (❌)
|
|
949
|
+
* rather than held — the accompanying config_error notification tells the user
|
|
950
|
+
* what to fix, and holding would only build a queue that floods the pane the
|
|
951
|
+
* moment the flag clears.
|
|
952
|
+
*/
|
|
953
|
+
private refuseFatalStartupDelivery;
|
|
954
|
+
/**
|
|
955
|
+
* A raw `%output` silence check is authoritative for ordinary TUIs. It is not
|
|
956
|
+
* for a backend such as agy whose status-line hook periodically redraws an
|
|
957
|
+
* identical screen. In that case trust an idle pane-state snapshot only when
|
|
958
|
+
* it was captured after both the latest output and the latest control-client
|
|
959
|
+
* observation reset.
|
|
960
|
+
*/
|
|
961
|
+
private isPaneIdleForDelivery;
|
|
962
|
+
private waitForPaneIdleForDelivery;
|
|
587
963
|
/**
|
|
588
964
|
* The write half of a delivery: paste → Enter → confirm, with retries.
|
|
589
965
|
*
|
|
@@ -660,6 +1036,49 @@ export declare class Daemon extends EventEmitter {
|
|
|
660
1036
|
private waitForSpawnToSettle;
|
|
661
1037
|
/** Spawn a CLI window. Returns true if --resume was used successfully. */
|
|
662
1038
|
private spawnClaudeWindow;
|
|
1039
|
+
/**
|
|
1040
|
+
* Startup budget for this launch: the backend's override (resume-aware), never
|
|
1041
|
+
* below a user-configured startup_timeout_ms; undefined = trySpawn's default.
|
|
1042
|
+
*/
|
|
1043
|
+
private startupBudgetFor;
|
|
1044
|
+
/** Effective wake budget = max(caller timeout, backend resume override, configured startup_timeout_ms). */
|
|
1045
|
+
wakeBudgetMs(timeoutMs: number): number;
|
|
1046
|
+
/** The fleet-level backend key this instance runs on (matches the lifecycle's backendOf). */
|
|
1047
|
+
private backendKey;
|
|
1048
|
+
/**
|
|
1049
|
+
* After a failed launch, read the pane for the backend's fleet-wide outage
|
|
1050
|
+
* text (e.g. kiro's `dispatch failure (timeout) … kiro.dev`) and record it.
|
|
1051
|
+
* The lifecycle only learns about outages from RUNNING instances; during a
|
|
1052
|
+
* post-update herd nothing is running yet, so the startup path must report
|
|
1053
|
+
* what it sees or the first instance in would clear its session for nothing.
|
|
1054
|
+
*/
|
|
1055
|
+
private noteStartupPaneForBackendOutage;
|
|
1056
|
+
/**
|
|
1057
|
+
* Fail the startup WITHOUT touching the session while the backend is known to
|
|
1058
|
+
* be down. The failed window is torn down first: the alternative — a live but
|
|
1059
|
+
* never-ready CLI left behind while the daemon reports `crashed` — would keep
|
|
1060
|
+
* the health monitor from ever seeing a dead pane and retrying.
|
|
1061
|
+
*/
|
|
1062
|
+
private failStartupIfBackendUnreachable;
|
|
1063
|
+
/**
|
|
1064
|
+
* Crash-respawn ran into the backend outage: the ordinary path would leave
|
|
1065
|
+
* `crashed` + a paused monitor + nothing scheduled (and count it as a crash).
|
|
1066
|
+
* Hand the instance to the fleet instead — the lifecycle stops this daemon
|
|
1067
|
+
* and the fleet's delayed startup retry re-creates it later with the session
|
|
1068
|
+
* intact. Returns true when someone took the hand-off.
|
|
1069
|
+
*/
|
|
1070
|
+
private handOffBackendUnreachableRespawn;
|
|
1071
|
+
/**
|
|
1072
|
+
* Dispose a Daemon whose start() rejected. The lifecycle registers a daemon
|
|
1073
|
+
* only after start() resolves, so nothing else owns this object — and by the
|
|
1074
|
+
* time the spawn fails it has already bound its IPC server (channel.sock),
|
|
1075
|
+
* written daemon.pid and possibly created a window. Left alone, each failed
|
|
1076
|
+
* start leaks one live-but-unreachable server handle (the next start unlinks
|
|
1077
|
+
* the socket path and binds a new one), multiplied by the automatic startup
|
|
1078
|
+
* retries. Idempotent, and fast: no graceful CLI quit, the CLI never reached
|
|
1079
|
+
* its prompt.
|
|
1080
|
+
*/
|
|
1081
|
+
abortStartup(): Promise<void>;
|
|
663
1082
|
/** Kill the entire process tree of the current tmux pane (CLI + MCP server). */
|
|
664
1083
|
private killProcessTree;
|
|
665
1084
|
/**
|
|
@@ -669,6 +1088,7 @@ export declare class Daemon extends EventEmitter {
|
|
|
669
1088
|
* Returns true if CLI is ready, false if it failed or got stuck.
|
|
670
1089
|
*/
|
|
671
1090
|
private trySpawn;
|
|
1091
|
+
private trySpawnInsideGate;
|
|
672
1092
|
/**
|
|
673
1093
|
* Repeatedly check pane content, dismiss any confirmation dialogs,
|
|
674
1094
|
* and return true once CLI reaches a ready prompt.
|