@cortexkit/aft-bridge 0.50.3 → 0.51.1
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/bash-host-fallback.d.ts +21 -0
- package/dist/bash-host-fallback.d.ts.map +1 -0
- package/dist/bash-host-fallback.js +109 -0
- package/dist/bash-host-fallback.js.map +1 -0
- package/dist/bridge.d.ts +8 -21
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +42 -44
- package/dist/bridge.js.map +1 -1
- package/dist/error-contract.d.ts +5 -0
- package/dist/error-contract.d.ts.map +1 -1
- package/dist/error-contract.js +25 -4
- package/dist/error-contract.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/revivable-transport.d.ts +0 -1
- package/dist/revivable-transport.d.ts.map +1 -1
- package/dist/revivable-transport.js +0 -3
- package/dist/revivable-transport.js.map +1 -1
- package/dist/subc-transport.d.ts +5 -5
- package/dist/subc-transport.d.ts.map +1 -1
- package/dist/subc-transport.js +12 -19
- package/dist/subc-transport.js.map +1 -1
- package/dist/transport.d.ts +0 -3
- package/dist/transport.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/status-bar.d.ts +0 -46
- package/dist/status-bar.d.ts.map +0 -1
- package/dist/status-bar.js +0 -90
- package/dist/status-bar.js.map +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const BASH_HOST_FALLBACK_BANNER = "[AFT host fallback - module transport down; no rewrites/compression/background]";
|
|
2
|
+
export declare const BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES: number;
|
|
3
|
+
export declare const BASH_HOST_FALLBACK_MAX_TIMEOUT_MS: number;
|
|
4
|
+
export declare const BASH_HOST_FALLBACK_REFUSAL = "AFT transport is down; only foreground execution is available in host fallback";
|
|
5
|
+
export interface BashHostFallbackOptions {
|
|
6
|
+
command: string;
|
|
7
|
+
projectRoot: string;
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
env?: NodeJS.ProcessEnv;
|
|
11
|
+
}
|
|
12
|
+
export interface BashHostFallbackResult extends Record<string, unknown> {
|
|
13
|
+
success: true;
|
|
14
|
+
output: string;
|
|
15
|
+
exit_code: number;
|
|
16
|
+
truncated: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function bashHostFallbackAskPattern(command: string, cwd: string): string;
|
|
19
|
+
/** Execute one explicitly-approved shell command without any AFT processing. */
|
|
20
|
+
export declare function runBashHostFallback(options: BashHostFallbackOptions): Promise<BashHostFallbackResult>;
|
|
21
|
+
//# sourceMappingURL=bash-host-fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash-host-fallback.d.ts","sourceRoot":"","sources":["../src/bash-host-fallback.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,oFAC6C,CAAC;AACpF,eAAO,MAAM,mCAAmC,QAAa,CAAC;AAC9D,eAAO,MAAM,iCAAiC,QAAiB,CAAC;AAChE,eAAO,MAAM,0BAA0B,mFAC2C,CAAC;AAEnF,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,sBAAuB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACrE,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/E;AAmBD,gFAAgF;AAChF,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CAyFjC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export const BASH_HOST_FALLBACK_BANNER = "[AFT host fallback - module transport down; no rewrites/compression/background]";
|
|
3
|
+
export const BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES = 100 * 1024;
|
|
4
|
+
export const BASH_HOST_FALLBACK_MAX_TIMEOUT_MS = 10 * 60 * 1000;
|
|
5
|
+
export const BASH_HOST_FALLBACK_REFUSAL = "AFT transport is down; only foreground execution is available in host fallback";
|
|
6
|
+
export function bashHostFallbackAskPattern(command, cwd) {
|
|
7
|
+
return `AFT UNAVAILABLE - host fallback execution:\n\nExact command:\n${command}\n\nWorking directory:\n${cwd}`;
|
|
8
|
+
}
|
|
9
|
+
function appendTail(chunks, chunk) {
|
|
10
|
+
const combined = Buffer.concat([...chunks, chunk]);
|
|
11
|
+
if (combined.byteLength <= BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES) {
|
|
12
|
+
return { chunks: [combined], truncated: false };
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
chunks: [combined.subarray(combined.byteLength - BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES)],
|
|
16
|
+
truncated: true,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function renderOutput(output, exitCode) {
|
|
20
|
+
const body = output.toString("utf8");
|
|
21
|
+
const separator = body.length === 0 || body.endsWith("\n") ? "" : "\n";
|
|
22
|
+
return `${BASH_HOST_FALLBACK_BANNER}\n${body}${separator}[exit code: ${exitCode}]`;
|
|
23
|
+
}
|
|
24
|
+
/** Execute one explicitly-approved shell command without any AFT processing. */
|
|
25
|
+
export async function runBashHostFallback(options) {
|
|
26
|
+
const timeoutMs = Math.min(Math.max(1, options.timeoutMs ?? BASH_HOST_FALLBACK_MAX_TIMEOUT_MS), BASH_HOST_FALLBACK_MAX_TIMEOUT_MS);
|
|
27
|
+
if (options.signal?.aborted) {
|
|
28
|
+
throw new DOMException("The host fallback command was aborted", "AbortError");
|
|
29
|
+
}
|
|
30
|
+
return await new Promise((resolve, reject) => {
|
|
31
|
+
const child = spawn(options.command, {
|
|
32
|
+
cwd: options.projectRoot,
|
|
33
|
+
shell: true,
|
|
34
|
+
env: { ...process.env, ...options.env },
|
|
35
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
36
|
+
detached: process.platform !== "win32",
|
|
37
|
+
windowsHide: true,
|
|
38
|
+
});
|
|
39
|
+
let chunks = [];
|
|
40
|
+
let truncated = false;
|
|
41
|
+
let timedOut = false;
|
|
42
|
+
let aborted = false;
|
|
43
|
+
let settled = false;
|
|
44
|
+
let abortForceTimer;
|
|
45
|
+
const capture = (chunk) => {
|
|
46
|
+
const next = appendTail(chunks, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
47
|
+
chunks = next.chunks;
|
|
48
|
+
truncated ||= next.truncated;
|
|
49
|
+
};
|
|
50
|
+
child.stdout?.on("data", capture);
|
|
51
|
+
child.stderr?.on("data", capture);
|
|
52
|
+
const kill = (signal) => {
|
|
53
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
54
|
+
return;
|
|
55
|
+
if (process.platform !== "win32" && child.pid !== undefined) {
|
|
56
|
+
try {
|
|
57
|
+
process.kill(-child.pid, signal);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// The process may have exited between the liveness check and group kill.
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
child.kill(signal);
|
|
65
|
+
};
|
|
66
|
+
const onAbort = () => {
|
|
67
|
+
aborted = true;
|
|
68
|
+
kill("SIGTERM");
|
|
69
|
+
abortForceTimer = setTimeout(() => kill("SIGKILL"), 250);
|
|
70
|
+
abortForceTimer.unref?.();
|
|
71
|
+
};
|
|
72
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
73
|
+
const timer = setTimeout(() => {
|
|
74
|
+
timedOut = true;
|
|
75
|
+
kill("SIGKILL");
|
|
76
|
+
}, timeoutMs);
|
|
77
|
+
const cleanup = () => {
|
|
78
|
+
clearTimeout(timer);
|
|
79
|
+
if (abortForceTimer !== undefined)
|
|
80
|
+
clearTimeout(abortForceTimer);
|
|
81
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
82
|
+
};
|
|
83
|
+
child.once("error", (error) => {
|
|
84
|
+
if (settled)
|
|
85
|
+
return;
|
|
86
|
+
settled = true;
|
|
87
|
+
cleanup();
|
|
88
|
+
reject(error);
|
|
89
|
+
});
|
|
90
|
+
child.once("close", (code) => {
|
|
91
|
+
if (settled)
|
|
92
|
+
return;
|
|
93
|
+
settled = true;
|
|
94
|
+
cleanup();
|
|
95
|
+
if (aborted) {
|
|
96
|
+
reject(new DOMException("The host fallback command was aborted", "AbortError"));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const exitCode = timedOut ? 124 : (code ?? 1);
|
|
100
|
+
resolve({
|
|
101
|
+
success: true,
|
|
102
|
+
output: renderOutput(Buffer.concat(chunks), exitCode),
|
|
103
|
+
exit_code: exitCode,
|
|
104
|
+
truncated,
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=bash-host-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash-host-fallback.js","sourceRoot":"","sources":["../src/bash-host-fallback.ts"],"names":[],"mappings":"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"}
|
package/dist/bridge.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Logger } from "./logger.js";
|
|
2
2
|
import type { BgCompletion, StatusCompression } from "./protocol.js";
|
|
3
|
-
import { type StatusBarCounts } from "./status-bar.js";
|
|
4
3
|
import type { AftProjectTransport, ToolCallArguments, ToolCallOptions, ToolCallResult } from "./transport.js";
|
|
5
4
|
type BinaryFingerprintReader = (binaryPath: string) => string | null | undefined;
|
|
6
5
|
/** Test seam: replace the on-disk binary fingerprint reader without fs module mocks. */
|
|
@@ -69,6 +68,13 @@ export declare class BridgeTransportTimeoutError extends Error {
|
|
|
69
68
|
readonly code: "transport_timeout";
|
|
70
69
|
constructor(command: string, timeoutMs: number, message: string);
|
|
71
70
|
}
|
|
71
|
+
/** A standalone bridge cannot carry a request because its process transport died. */
|
|
72
|
+
export declare class BridgeTransportUnavailableError extends Error {
|
|
73
|
+
readonly code: "bridge_transport_unavailable";
|
|
74
|
+
constructor(message: string, options?: {
|
|
75
|
+
cause?: unknown;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
72
78
|
/** Type guard for a transport-timeout rejection (bridge busy, retryable). */
|
|
73
79
|
export declare function isBridgeTransportTimeout(err: unknown): err is BridgeTransportTimeoutError;
|
|
74
80
|
export interface BridgeOptions {
|
|
@@ -235,13 +241,6 @@ export declare class BinaryBridge implements AftProjectTransport {
|
|
|
235
241
|
private restartResetTimer;
|
|
236
242
|
/** Updated after every successfully parsed stdout frame from the child. */
|
|
237
243
|
private lastChildActivityAt;
|
|
238
|
-
/**
|
|
239
|
-
* Latest agent status-bar counts seen on any `data.status_bar` envelope. The
|
|
240
|
-
* Rust bridge attaches current counts to (almost) every response; we cache
|
|
241
|
-
* the freshest so the per-tool after-hook can render the bar without extra
|
|
242
|
-
* plumbing per call. `undefined` until the first attach (no scan yet).
|
|
243
|
-
*/
|
|
244
|
-
private lastStatusBar;
|
|
245
244
|
/** Consecutive non-bash-style request timeouts without an id-matched response. */
|
|
246
245
|
private consecutiveRequestTimeouts;
|
|
247
246
|
private errorPrefix;
|
|
@@ -259,6 +258,7 @@ export declare class BinaryBridge implements AftProjectTransport {
|
|
|
259
258
|
get restartCount(): number;
|
|
260
259
|
/** Whether the child process is currently alive. */
|
|
261
260
|
isAlive(): boolean;
|
|
261
|
+
private invalidateTransportProcess;
|
|
262
262
|
hasPendingRequests(): boolean;
|
|
263
263
|
hasOutstandingBackgroundTasks(): boolean;
|
|
264
264
|
/**
|
|
@@ -328,19 +328,6 @@ export declare class BinaryBridge implements AftProjectTransport {
|
|
|
328
328
|
private flushStdoutBuffer;
|
|
329
329
|
private processStdoutLine;
|
|
330
330
|
private accountForBashTaskResponse;
|
|
331
|
-
/**
|
|
332
|
-
* Cache the agent status-bar counts from a response. The Rust `Response.data`
|
|
333
|
-
* is `#[serde(flatten)]`, so the attached `status_bar` object lands at the
|
|
334
|
-
* TOP LEVEL of the wire envelope (`response.status_bar`), not nested under a
|
|
335
|
-
* `data` key — same as `bg_completions`.
|
|
336
|
-
*/
|
|
337
|
-
private captureStatusBar;
|
|
338
|
-
/**
|
|
339
|
-
* Latest agent status-bar counts seen on any response, or `undefined` before
|
|
340
|
-
* the first attach (no inspect scan has populated Tier-2 yet). The per-tool
|
|
341
|
-
* after-hook reads this and applies emit-on-change gating.
|
|
342
|
-
*/
|
|
343
|
-
getStatusBar(): StatusBarCounts | undefined;
|
|
344
331
|
private handleTimeout;
|
|
345
332
|
private handleCrash;
|
|
346
333
|
private rejectAllPending;
|
package/dist/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/bridge.js
CHANGED
|
@@ -6,7 +6,6 @@ import { join } from "node:path";
|
|
|
6
6
|
import { StringDecoder } from "node:string_decoder";
|
|
7
7
|
import { error, getActiveLogger, getLogFilePath, log, warn } from "./active-logger.js";
|
|
8
8
|
import { isPassiveCommand, PASSIVE_COMMAND_TIMEOUT_MS } from "./command-timeouts.js";
|
|
9
|
-
import { parseStatusBarCounts } from "./status-bar.js";
|
|
10
9
|
const DEFAULT_BRIDGE_TIMEOUT_MS = 30_000;
|
|
11
10
|
const BRIDGE_HANG_TIMEOUT_THRESHOLD = 2;
|
|
12
11
|
const MAX_STDOUT_BUFFER = 64 * 1024 * 1024; // 64MB
|
|
@@ -187,6 +186,14 @@ export class BridgeTransportTimeoutError extends Error {
|
|
|
187
186
|
this.name = "BridgeTransportTimeoutError";
|
|
188
187
|
}
|
|
189
188
|
}
|
|
189
|
+
/** A standalone bridge cannot carry a request because its process transport died. */
|
|
190
|
+
export class BridgeTransportUnavailableError extends Error {
|
|
191
|
+
code = "bridge_transport_unavailable";
|
|
192
|
+
constructor(message, options) {
|
|
193
|
+
super(message, options);
|
|
194
|
+
this.name = "BridgeTransportUnavailableError";
|
|
195
|
+
}
|
|
196
|
+
}
|
|
190
197
|
/** Type guard for a transport-timeout rejection (bridge busy, retryable). */
|
|
191
198
|
export function isBridgeTransportTimeout(err) {
|
|
192
199
|
return err instanceof Error && err.code === "transport_timeout";
|
|
@@ -241,13 +248,6 @@ export class BinaryBridge {
|
|
|
241
248
|
restartResetTimer = null;
|
|
242
249
|
/** Updated after every successfully parsed stdout frame from the child. */
|
|
243
250
|
lastChildActivityAt = 0;
|
|
244
|
-
/**
|
|
245
|
-
* Latest agent status-bar counts seen on any `data.status_bar` envelope. The
|
|
246
|
-
* Rust bridge attaches current counts to (almost) every response; we cache
|
|
247
|
-
* the freshest so the per-tool after-hook can render the bar without extra
|
|
248
|
-
* plumbing per call. `undefined` until the first attach (no scan yet).
|
|
249
|
-
*/
|
|
250
|
-
lastStatusBar;
|
|
251
251
|
/** Consecutive non-bash-style request timeouts without an id-matched response. */
|
|
252
252
|
consecutiveRequestTimeouts = 0;
|
|
253
253
|
errorPrefix;
|
|
@@ -365,6 +365,20 @@ export class BinaryBridge {
|
|
|
365
365
|
isAlive() {
|
|
366
366
|
return this.process !== null && this.process.exitCode === null && !this.process.killed;
|
|
367
367
|
}
|
|
368
|
+
invalidateTransportProcess(error) {
|
|
369
|
+
const proc = this.process;
|
|
370
|
+
if (!proc)
|
|
371
|
+
return;
|
|
372
|
+
this.process = null;
|
|
373
|
+
this.spawnedBinaryFingerprint = null;
|
|
374
|
+
if (proc.exitCode === null && !proc.killed) {
|
|
375
|
+
proc.kill("SIGKILL");
|
|
376
|
+
}
|
|
377
|
+
this.clearRestartResetTimer();
|
|
378
|
+
this.configured = false;
|
|
379
|
+
this.outstandingBackgroundTaskIds.clear();
|
|
380
|
+
this.rejectAllPending(error);
|
|
381
|
+
}
|
|
368
382
|
hasPendingRequests() {
|
|
369
383
|
return this.pending.size > 0;
|
|
370
384
|
}
|
|
@@ -491,7 +505,7 @@ export class BinaryBridge {
|
|
|
491
505
|
throw new Error(`${this.errorPrefix} Bridge is retiring after the on-disk binary changed; retry to respawn on the updated binary`);
|
|
492
506
|
}
|
|
493
507
|
if (this._shuttingDown) {
|
|
494
|
-
throw new
|
|
508
|
+
throw new BridgeTransportUnavailableError(`${this.errorPrefix} Bridge is shutting down, cannot send "${command}"`);
|
|
495
509
|
}
|
|
496
510
|
if (Object.hasOwn(params, "id")) {
|
|
497
511
|
throw new Error("params cannot contain reserved key 'id'");
|
|
@@ -562,7 +576,7 @@ export class BinaryBridge {
|
|
|
562
576
|
// Re-check liveness after version check — checkVersion() swallows
|
|
563
577
|
// errors as best-effort, so the bridge may have died without throwing.
|
|
564
578
|
if (!this.isAlive()) {
|
|
565
|
-
throw new
|
|
579
|
+
throw new BridgeTransportUnavailableError(`${this.errorPrefix} Bridge died during version check. Check logs: ${this.getLogFilePathVia()}`);
|
|
566
580
|
}
|
|
567
581
|
this.configured = true;
|
|
568
582
|
}
|
|
@@ -607,6 +621,7 @@ export class BinaryBridge {
|
|
|
607
621
|
// forget it.
|
|
608
622
|
const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
|
|
609
623
|
let requestSentAt = Date.now();
|
|
624
|
+
const child = this.process;
|
|
610
625
|
const response = await new Promise((resolve, reject) => {
|
|
611
626
|
const timer = setTimeout(() => {
|
|
612
627
|
const entry = this.pending.get(id);
|
|
@@ -645,21 +660,27 @@ export class BinaryBridge {
|
|
|
645
660
|
this.handleTimeout(requestSessionId);
|
|
646
661
|
}, effectiveTimeoutMs);
|
|
647
662
|
this.pending.set(id, { resolve, reject, timer, onProgress: options?.onProgress, command });
|
|
648
|
-
if (!
|
|
663
|
+
if (!child?.stdin?.writable) {
|
|
649
664
|
this.pending.delete(id);
|
|
650
665
|
clearTimeout(timer);
|
|
651
|
-
|
|
666
|
+
const error = new BridgeTransportUnavailableError(`${this.errorPrefix} stdin not writable for command "${command}"`);
|
|
667
|
+
reject(error);
|
|
668
|
+
if (this.process === child)
|
|
669
|
+
this.invalidateTransportProcess(error);
|
|
652
670
|
return;
|
|
653
671
|
}
|
|
654
672
|
requestSentAt = Date.now();
|
|
655
|
-
|
|
673
|
+
child.stdin.write(line, (err) => {
|
|
656
674
|
if (err) {
|
|
675
|
+
const error = new BridgeTransportUnavailableError(`${this.errorPrefix} Failed to write to stdin: ${err.message}`, { cause: err });
|
|
657
676
|
const entry = this.pending.get(id);
|
|
658
677
|
if (entry) {
|
|
659
678
|
this.pending.delete(id);
|
|
660
679
|
clearTimeout(entry.timer);
|
|
661
|
-
entry.reject(
|
|
680
|
+
entry.reject(error);
|
|
662
681
|
}
|
|
682
|
+
if (this.process === child)
|
|
683
|
+
this.invalidateTransportProcess(error);
|
|
663
684
|
}
|
|
664
685
|
});
|
|
665
686
|
});
|
|
@@ -848,18 +869,15 @@ export class BinaryBridge {
|
|
|
848
869
|
});
|
|
849
870
|
}
|
|
850
871
|
ensureSpawned(triggeringSessionId) {
|
|
851
|
-
if (this.isAlive())
|
|
872
|
+
if (this.isAlive() && this.process?.stdin?.writable)
|
|
852
873
|
return;
|
|
874
|
+
if (this.process !== null) {
|
|
875
|
+
this.invalidateTransportProcess(new BridgeTransportUnavailableError(`${this.errorPrefix} Child stdin is not writable`));
|
|
876
|
+
}
|
|
853
877
|
this.spawnProcess(triggeringSessionId);
|
|
854
878
|
}
|
|
855
879
|
spawnProcess(triggeringSessionId) {
|
|
856
880
|
this._retiringDueToBinaryChange = false;
|
|
857
|
-
// A freshly-spawned process has published no diagnostics yet, so its warm
|
|
858
|
-
// E/W set is empty. Drop the cached status bar from any prior process here
|
|
859
|
-
// (covers initial spawn, crash auto-restart, and version-swap respawn) so a
|
|
860
|
-
// dead process's stale counts are never re-emitted on the next tool result
|
|
861
|
-
// before the new process repopulates them (#6).
|
|
862
|
-
this.lastStatusBar = undefined;
|
|
863
881
|
if (triggeringSessionId) {
|
|
864
882
|
this.sessionLogVia(triggeringSessionId, `Spawning binary: ${this.binaryPath} (cwd: ${this.cwd})`);
|
|
865
883
|
}
|
|
@@ -966,7 +984,7 @@ export class BinaryBridge {
|
|
|
966
984
|
if (this.process !== currentChild)
|
|
967
985
|
return;
|
|
968
986
|
this.errorVia(`Process error: ${err.message}${this.formatStderrTail()}`);
|
|
969
|
-
this.handleCrash();
|
|
987
|
+
this.handleCrash(err);
|
|
970
988
|
});
|
|
971
989
|
child.on("exit", (code, signal) => {
|
|
972
990
|
if (this.process !== currentChild)
|
|
@@ -989,7 +1007,7 @@ export class BinaryBridge {
|
|
|
989
1007
|
this.process = null;
|
|
990
1008
|
this.configured = false;
|
|
991
1009
|
this.clearRestartResetTimer();
|
|
992
|
-
this.rejectAllPending(new
|
|
1010
|
+
this.rejectAllPending(new BridgeTransportUnavailableError(`${this.errorPrefix} Binary killed by ${signal}`));
|
|
993
1011
|
return;
|
|
994
1012
|
}
|
|
995
1013
|
this.handleCrash();
|
|
@@ -1148,7 +1166,6 @@ export class BinaryBridge {
|
|
|
1148
1166
|
this.consecutiveRequestTimeouts = 0;
|
|
1149
1167
|
this.scheduleRestartCountReset();
|
|
1150
1168
|
this.accountForBashTaskResponse(entry.command, response);
|
|
1151
|
-
this.captureStatusBar(response);
|
|
1152
1169
|
entry.resolve(response);
|
|
1153
1170
|
}
|
|
1154
1171
|
else if (typeof response.type === "string") {
|
|
@@ -1175,25 +1192,6 @@ export class BinaryBridge {
|
|
|
1175
1192
|
this.outstandingBackgroundTaskIds.add(taskId);
|
|
1176
1193
|
}
|
|
1177
1194
|
}
|
|
1178
|
-
/**
|
|
1179
|
-
* Cache the agent status-bar counts from a response. The Rust `Response.data`
|
|
1180
|
-
* is `#[serde(flatten)]`, so the attached `status_bar` object lands at the
|
|
1181
|
-
* TOP LEVEL of the wire envelope (`response.status_bar`), not nested under a
|
|
1182
|
-
* `data` key — same as `bg_completions`.
|
|
1183
|
-
*/
|
|
1184
|
-
captureStatusBar(response) {
|
|
1185
|
-
const parsed = parseStatusBarCounts(response.status_bar);
|
|
1186
|
-
if (parsed)
|
|
1187
|
-
this.lastStatusBar = parsed;
|
|
1188
|
-
}
|
|
1189
|
-
/**
|
|
1190
|
-
* Latest agent status-bar counts seen on any response, or `undefined` before
|
|
1191
|
-
* the first attach (no inspect scan has populated Tier-2 yet). The per-tool
|
|
1192
|
-
* after-hook reads this and applies emit-on-change gating.
|
|
1193
|
-
*/
|
|
1194
|
-
getStatusBar() {
|
|
1195
|
-
return this.lastStatusBar;
|
|
1196
|
-
}
|
|
1197
1195
|
handleTimeout(triggeringSessionId) {
|
|
1198
1196
|
this.consecutiveRequestTimeouts = 0;
|
|
1199
1197
|
this.spawnedBinaryFingerprint = null;
|
|
@@ -1260,7 +1258,7 @@ export class BinaryBridge {
|
|
|
1260
1258
|
if (tail) {
|
|
1261
1259
|
this.errorVia(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
|
|
1262
1260
|
}
|
|
1263
|
-
this.rejectAllPending(new
|
|
1261
|
+
this.rejectAllPending(new BridgeTransportUnavailableError(`${this.errorPrefix} Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${this.getLogFilePathVia()})`, { cause }));
|
|
1264
1262
|
if (this._retiringDueToBinaryChange) {
|
|
1265
1263
|
this.logVia("Binary exited while retiring after an on-disk update; skipping auto-restart");
|
|
1266
1264
|
return;
|