@rivet-dev/agentos-runtime-core 0.0.0-ci-speed.3fd7050 → 0.0.0-codex-actor-plugin-contract-coverage.115ca8a

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/commands/bash CHANGED
Binary file
package/commands/sh CHANGED
Binary file
@@ -1,6 +1,9 @@
1
1
  export declare class PendingResponseRegistry<TResponse> {
2
2
  private readonly pending;
3
- waitForResponse(requestId: number): Promise<TResponse>;
3
+ waitForResponse(requestId: number, options: {
4
+ timeoutMs: number;
5
+ timeoutMessage: () => string;
6
+ }): Promise<TResponse>;
4
7
  resolve(requestId: number, frame: TResponse): boolean;
5
8
  reject(requestId: number, error: Error): boolean;
6
9
  rejectAll(error: Error): void;
@@ -1,24 +1,27 @@
1
1
  export class PendingResponseRegistry {
2
2
  pending = new Map();
3
- // Deliberately no per-request timer: local framed stdio never loses frames,
4
- // so a response is bounded by the transport's silence watchdog (a dead or
5
- // wedged sidecar rejects all pending requests through `rejectAll`) rather
6
- // than by guessing how long any one request should take.
7
- waitForResponse(requestId) {
3
+ waitForResponse(requestId, options) {
8
4
  if (this.pending.has(requestId)) {
9
5
  throw new Error(`response waiter already registered for request ${requestId}`);
10
6
  }
11
7
  return new Promise((resolve, reject) => {
12
- this.pending.set(requestId, {
8
+ const entry = {
13
9
  resolve: (frame) => {
10
+ clearTimeout(entry.timer);
14
11
  this.pending.delete(requestId);
15
12
  resolve(frame);
16
13
  },
17
14
  reject: (error) => {
15
+ clearTimeout(entry.timer);
18
16
  this.pending.delete(requestId);
19
17
  reject(error);
20
18
  },
21
- });
19
+ timer: setTimeout(() => {
20
+ this.pending.delete(requestId);
21
+ reject(new Error(options.timeoutMessage()));
22
+ }, options.timeoutMs),
23
+ };
24
+ this.pending.set(requestId, entry);
22
25
  });
23
26
  }
24
27
  resolve(requestId, frame) {
@@ -24,20 +24,15 @@ export declare class FrameRpcTransport<TReadFrame, TWriteFrame, TResponseFrame,
24
24
  private readonly pendingResponses;
25
25
  private readonly eventListeners;
26
26
  private readonly sidecarRequestListeners;
27
- private readonly frameActivityListeners;
28
27
  constructor(options: FrameRpcTransportOptions<TReadFrame, TWriteFrame, TResponseFrame, TEventFrame, TSidecarRequestFrame>);
29
28
  onEvent(handler: (event: TEventFrame) => void): () => void;
30
- /**
31
- * Observe every classified inbound frame (response, event, or sidecar
32
- * request) before it is routed. This is the transport's liveness signal:
33
- * the silence watchdog resets on each invocation, so ANY inbound traffic —
34
- * not just heartbeats — proves the sidecar is alive.
35
- */
36
- onFrameActivity(handler: () => void): () => void;
37
29
  onSidecarRequest(handler: (request: TSidecarRequestFrame) => void): () => void;
38
30
  onError(handler: (error: Error) => void): () => void;
39
31
  onEnd(handler: () => void): () => void;
40
- sendFrame(requestId: number, frame: TWriteFrame): Promise<TResponseFrame>;
32
+ sendFrame(requestId: number, frame: TWriteFrame, options: {
33
+ timeoutMs: number;
34
+ timeoutMessage: () => string;
35
+ }): Promise<TResponseFrame>;
41
36
  writeFrame(frame: TWriteFrame): Promise<void>;
42
37
  rejectAll(error: Error): void;
43
38
  dispose(): void;
package/dist/frame-rpc.js CHANGED
@@ -5,7 +5,6 @@ export class FrameRpcTransport {
5
5
  pendingResponses = new PendingResponseRegistry();
6
6
  eventListeners = new Set();
7
7
  sidecarRequestListeners = new Set();
8
- frameActivityListeners = new Set();
9
8
  constructor(options) {
10
9
  if (options.frameTransport) {
11
10
  this.frameTransport = options.frameTransport;
@@ -31,18 +30,6 @@ export class FrameRpcTransport {
31
30
  this.eventListeners.delete(handler);
32
31
  };
33
32
  }
34
- /**
35
- * Observe every classified inbound frame (response, event, or sidecar
36
- * request) before it is routed. This is the transport's liveness signal:
37
- * the silence watchdog resets on each invocation, so ANY inbound traffic —
38
- * not just heartbeats — proves the sidecar is alive.
39
- */
40
- onFrameActivity(handler) {
41
- this.frameActivityListeners.add(handler);
42
- return () => {
43
- this.frameActivityListeners.delete(handler);
44
- };
45
- }
46
33
  onSidecarRequest(handler) {
47
34
  this.sidecarRequestListeners.add(handler);
48
35
  return () => {
@@ -55,8 +42,8 @@ export class FrameRpcTransport {
55
42
  onEnd(handler) {
56
43
  return this.frameTransport.onEnd(handler);
57
44
  }
58
- async sendFrame(requestId, frame) {
59
- const response = this.pendingResponses.waitForResponse(requestId);
45
+ async sendFrame(requestId, frame, options) {
46
+ const response = this.pendingResponses.waitForResponse(requestId, options);
60
47
  void this.writeFrame(frame).catch((error) => {
61
48
  this.pendingResponses.reject(requestId, error instanceof Error ? error : new Error(String(error)));
62
49
  });
@@ -73,12 +60,8 @@ export class FrameRpcTransport {
73
60
  this.pendingResponses.rejectAll(new Error("frame rpc transport disposed"));
74
61
  this.eventListeners.clear();
75
62
  this.sidecarRequestListeners.clear();
76
- this.frameActivityListeners.clear();
77
63
  }
78
64
  dispatchFrame(classified) {
79
- for (const listener of this.frameActivityListeners) {
80
- listener();
81
- }
82
65
  switch (classified.kind) {
83
66
  case "response":
84
67
  this.pendingResponses.resolve(classified.requestId, classified.frame);
@@ -163,4 +163,4 @@ export declare class NativeSidecarKernelProxy {
163
163
  private updateTrackedProcessSnapshot;
164
164
  }
165
165
  export type { AuthenticatedSession, CreatedVm, GuestFilesystemStat, SidecarSpawnOptions, RootFilesystemEntry, SidecarEventSelector, SidecarPermissionsPolicy, SidecarRegisteredHostCallbackDefinition, SidecarRequestFrame, SidecarRequestHandler, SidecarResponsePayload, SidecarSessionState, SidecarSignalHandlerRegistration, SidecarSocketStateEntry, } from "./sidecar-process.js";
166
- export { SidecarProcess, SidecarEventBufferOverflow, SidecarProcessError, SidecarProcessExited, } from "./sidecar-process.js";
166
+ export { NATIVE_SIDECAR_FRAME_TIMEOUT_MS, SidecarProcess, SidecarEventBufferOverflow, SidecarProcessError, SidecarProcessExited, } from "./sidecar-process.js";
@@ -985,10 +985,6 @@ export class NativeSidecarKernelProxy {
985
985
  }
986
986
  return this.client.rename(this.session, this.vm, oldPath, newPath);
987
987
  }
988
- // Test-runtime only: runtime mounts registered here stay host-side local
989
- // compat mounts and are not delivered to the sidecar. The production proxy
990
- // in @rivet-dev/agentos-core reconfigures sidecar mounts on every
991
- // mountFs/unmountFs.
992
988
  mountFs(path, driver, options) {
993
989
  this.localMounts.unshift({
994
990
  path: posixPath.normalize(path),
@@ -1731,27 +1727,21 @@ function isMissingHostProcessError(error) {
1731
1727
  function errnoError(code, message) {
1732
1728
  return Object.assign(new Error(`${code}: ${message}`), { code });
1733
1729
  }
1734
- // VirtualStat is a numeric, Node-default-shaped view: u64 fields above
1735
- // Number.MAX_SAFE_INTEGER lose precision here, same as Node's non-bigint
1736
- // fs.stat on the host.
1737
1730
  function toVirtualStat(stat) {
1738
1731
  return {
1739
1732
  mode: stat.mode,
1740
- size: Number(stat.size),
1741
- sizeExact: stat.size,
1742
- blocks: Number(stat.blocks),
1743
- dev: Number(stat.dev),
1744
- rdev: Number(stat.rdev),
1733
+ size: stat.size,
1734
+ blocks: stat.blocks,
1735
+ dev: stat.dev,
1736
+ rdev: stat.rdev,
1745
1737
  isDirectory: stat.is_directory,
1746
1738
  isSymbolicLink: stat.is_symbolic_link,
1747
1739
  atimeMs: stat.atime_ms,
1748
1740
  mtimeMs: stat.mtime_ms,
1749
1741
  ctimeMs: stat.ctime_ms,
1750
1742
  birthtimeMs: stat.birthtime_ms,
1751
- ino: Number(stat.ino),
1752
- inoExact: stat.ino,
1753
- nlink: Number(stat.nlink),
1754
- nlinkExact: stat.nlink,
1743
+ ino: stat.ino,
1744
+ nlink: stat.nlink,
1755
1745
  uid: stat.uid,
1756
1746
  gid: stat.gid,
1757
1747
  };
@@ -1784,4 +1774,4 @@ function socketLookupKey(kind, request) {
1784
1774
  path: request.path ?? null,
1785
1775
  });
1786
1776
  }
1787
- export { SidecarProcess, SidecarEventBufferOverflow, SidecarProcessError, SidecarProcessExited, } from "./sidecar-process.js";
1777
+ export { NATIVE_SIDECAR_FRAME_TIMEOUT_MS, SidecarProcess, SidecarEventBufferOverflow, SidecarProcessError, SidecarProcessExited, } from "./sidecar-process.js";
@@ -4,6 +4,7 @@ import type { LiveEventFrame, LiveResponseFrame, LiveSidecarRequestHandler, Prot
4
4
  import type { LiveOwnershipScope } from "./ownership.js";
5
5
  import type { LiveRequestPayload } from "./request-payloads.js";
6
6
  import type { LiveSidecarEventSelector } from "./event-buffer.js";
7
+ export declare const DEFAULT_SIDECAR_FRAME_TIMEOUT_MS = 120000;
7
8
  export declare const DEFAULT_SIDECAR_EVENT_BUFFER_CAPACITY = 4096;
8
9
  export declare const DEFAULT_SIDECAR_GRACEFUL_EXIT_MS = 5000;
9
10
  export declare const DEFAULT_SIDECAR_FORCE_EXIT_MS = 2000;
@@ -11,17 +12,12 @@ export interface StdioSidecarProtocolClientSpawnOptions {
11
12
  cwd?: string;
12
13
  command?: string;
13
14
  args?: string[];
15
+ frameTimeoutMs?: number;
14
16
  eventBufferCapacity?: number;
15
17
  gracefulExitMs?: number;
16
18
  forceExitMs?: number;
17
19
  disposedErrorMessage?: string;
18
20
  payloadCodec?: ProtocolFramePayloadCodec;
19
- /**
20
- * Override the silence watchdog window (default 30s). Tests only — the
21
- * window is a fixed protocol constant paired with the sidecar's 10s
22
- * heartbeat cadence, not an operator tunable.
23
- */
24
- silenceTimeoutMs?: number;
25
21
  }
26
22
  export declare class StdioSidecarProtocolClient implements SidecarProcessTransport {
27
23
  readonly child: StdioSidecarProcess["child"];
@@ -2,6 +2,7 @@ import { resolvePublishedSidecarBinary } from "./binary.js";
2
2
  import { SidecarProcessExited, StdioSidecarProcess, } from "./process.js";
3
3
  import { SidecarProtocolClient } from "./protocol-client.js";
4
4
  import { registerSidecarProcessSpawnFactory } from "./sidecar-process.js";
5
+ export const DEFAULT_SIDECAR_FRAME_TIMEOUT_MS = 120_000;
5
6
  export const DEFAULT_SIDECAR_EVENT_BUFFER_CAPACITY = 4_096;
6
7
  export const DEFAULT_SIDECAR_GRACEFUL_EXIT_MS = 5_000;
7
8
  export const DEFAULT_SIDECAR_FORCE_EXIT_MS = 2_000;
@@ -21,20 +22,9 @@ export class StdioSidecarProtocolClient {
21
22
  this.protocolClient = new SidecarProtocolClient({
22
23
  stdin: this.child.stdin,
23
24
  stdout: this.child.stdout,
25
+ frameTimeoutMs: options.frameTimeoutMs,
24
26
  eventBufferCapacity: options.eventBufferCapacity,
25
27
  payloadCodec: options.payloadCodec,
26
- silenceTimeoutMs: options.silenceTimeoutMs,
27
- // A silent sidecar is dead or wedged; reap the process so it cannot
28
- // linger as a zombie holding VM resources. The watchdog then rejects
29
- // all in-flight requests with `SidecarSilenceTimeout`.
30
- onSilenceExpired: () => {
31
- try {
32
- this.child.kill("SIGKILL");
33
- }
34
- catch {
35
- // The child may have exited between the check and the kill.
36
- }
37
- },
38
28
  stderrText: () => this.sidecarProcess.stderrText(),
39
29
  streamEndedError: () => this.sidecarProcess.currentExitError() ??
40
30
  new SidecarProcessExited({
@@ -57,7 +47,7 @@ export class StdioSidecarProtocolClient {
57
47
  args: options.args ?? [],
58
48
  cwd: options.cwd,
59
49
  }), {
60
- silenceTimeoutMs: options.silenceTimeoutMs,
50
+ frameTimeoutMs: options.frameTimeoutMs ?? DEFAULT_SIDECAR_FRAME_TIMEOUT_MS,
61
51
  eventBufferCapacity: options.eventBufferCapacity ??
62
52
  DEFAULT_SIDECAR_EVENT_BUFFER_CAPACITY,
63
53
  gracefulExitMs: options.gracefulExitMs ?? DEFAULT_SIDECAR_GRACEFUL_EXIT_MS,
@@ -8,25 +8,17 @@ export interface SidecarProtocolClientOptions {
8
8
  frameTransport?: FrameTransport<LiveResponseFrame | LiveEventFrame | LiveSidecarRequestFrame, LiveProtocolFrame>;
9
9
  stdin?: Writable;
10
10
  stdout?: Readable;
11
+ frameTimeoutMs: number;
11
12
  eventBufferCapacity: number;
12
13
  payloadCodec?: ProtocolFramePayloadCodec;
13
14
  stderrText?: () => string;
14
15
  frameError?: (error: Error) => Error;
15
16
  streamEndedError?: () => Error;
16
- /** Override the silence watchdog window. Tests only; production uses the default. */
17
- silenceTimeoutMs?: number;
18
- /**
19
- * Runs when the silence watchdog fires, before pending work is rejected.
20
- * The stdio layer uses it to SIGKILL the sidecar child.
21
- */
22
- onSilenceExpired?: () => void;
23
17
  }
24
18
  export declare class SidecarProtocolClient {
25
19
  private readonly eventBuffer;
26
20
  private readonly eventListeners;
27
- private readonly silenceTimeoutMs;
28
- private silenceTimer;
29
- private lastInboundAtMs;
21
+ private readonly frameTimeoutMs;
30
22
  private readonly payloadCodec;
31
23
  private readonly stderrText;
32
24
  private readonly hostFrameFactory;
@@ -35,15 +27,6 @@ export declare class SidecarProtocolClient {
35
27
  private readonly eventWaiters;
36
28
  private sidecarRequestHandler;
37
29
  constructor(options: SidecarProtocolClientOptions);
38
- /**
39
- * Arm the silence watchdog: ANY inbound frame resets the clock (see the
40
- * `onFrameActivity` tap above), and the sidecar heartbeats every 10s even
41
- * while busy, so sustained silence for the full window means the process
42
- * is dead or wedged — not slow. The check interval is unref'd so an idle
43
- * host process can still exit naturally.
44
- */
45
- private startSilenceWatchdog;
46
- private stopSilenceWatchdog;
47
30
  setSidecarRequestHandler(handler: LiveSidecarRequestHandler | null): void;
48
31
  onEvent(handler: (event: LiveEventFrame) => void): () => void;
49
32
  sendRequest(input: {
@@ -1,21 +1,10 @@
1
1
  import { SidecarEventBuffer, SidecarEventBufferOverflow, normalizeSidecarEventMatcher, sidecarEventWaitAbortError, } from "./event-buffer.js";
2
2
  import { FrameRpcTransport } from "./frame-rpc.js";
3
3
  import { HostProtocolFrameFactory, classifySidecarWrittenProtocolFrame, decodeProtocolFramePayload, encodeProtocolFramePayload, resolveSidecarRequestFramePayload, } from "./protocol-frames.js";
4
- import { SidecarSilenceTimeout } from "./sidecar-errors.js";
5
- /**
6
- * How long the host tolerates TOTAL inbound silence (no responses, events,
7
- * sidecar requests, or heartbeats) before declaring the sidecar dead. The
8
- * sidecar heartbeats every 10s from a dedicated thread, so this allows two
9
- * missed beats plus margin; it bounds "sidecar is dead or wedged", never "this
10
- * request is slow" — individual requests have no deadline of their own.
11
- */
12
- const DEFAULT_SIDECAR_SILENCE_TIMEOUT_MS = 30_000;
13
4
  export class SidecarProtocolClient {
14
5
  eventBuffer;
15
6
  eventListeners = new Set();
16
- silenceTimeoutMs;
17
- silenceTimer = null;
18
- lastInboundAtMs = 0;
7
+ frameTimeoutMs;
19
8
  payloadCodec;
20
9
  stderrText;
21
10
  hostFrameFactory = new HostProtocolFrameFactory();
@@ -24,8 +13,7 @@ export class SidecarProtocolClient {
24
13
  eventWaiters = new Set();
25
14
  sidecarRequestHandler = null;
26
15
  constructor(options) {
27
- this.silenceTimeoutMs =
28
- options.silenceTimeoutMs ?? DEFAULT_SIDECAR_SILENCE_TIMEOUT_MS;
16
+ this.frameTimeoutMs = options.frameTimeoutMs;
29
17
  this.eventBuffer = new SidecarEventBuffer(options.eventBufferCapacity);
30
18
  this.payloadCodec = options.payloadCodec ?? "bare";
31
19
  this.stderrText = options.stderrText ?? (() => "");
@@ -50,45 +38,6 @@ export class SidecarProtocolClient {
50
38
  this.failPermanently(options.streamEndedError?.() ??
51
39
  new Error("sidecar protocol stream ended"));
52
40
  });
53
- this.frameTransport.onFrameActivity(() => {
54
- this.lastInboundAtMs = performance.now();
55
- });
56
- this.startSilenceWatchdog(options.onSilenceExpired);
57
- }
58
- /**
59
- * Arm the silence watchdog: ANY inbound frame resets the clock (see the
60
- * `onFrameActivity` tap above), and the sidecar heartbeats every 10s even
61
- * while busy, so sustained silence for the full window means the process
62
- * is dead or wedged — not slow. The check interval is unref'd so an idle
63
- * host process can still exit naturally.
64
- */
65
- startSilenceWatchdog(onExpired) {
66
- this.lastInboundAtMs = performance.now();
67
- const checkIntervalMs = Math.max(Math.min(this.silenceTimeoutMs / 4, 1_000), 10);
68
- this.silenceTimer = setInterval(() => {
69
- const silenceMs = performance.now() - this.lastInboundAtMs;
70
- if (silenceMs < this.silenceTimeoutMs) {
71
- return;
72
- }
73
- this.stopSilenceWatchdog();
74
- const error = new SidecarSilenceTimeout({
75
- silenceMs,
76
- stderr: this.stderrText(),
77
- });
78
- try {
79
- onExpired?.();
80
- }
81
- finally {
82
- this.failPermanently(error);
83
- }
84
- }, checkIntervalMs);
85
- this.silenceTimer.unref?.();
86
- }
87
- stopSilenceWatchdog() {
88
- if (this.silenceTimer !== null) {
89
- clearInterval(this.silenceTimer);
90
- this.silenceTimer = null;
91
- }
92
41
  }
93
42
  setSidecarRequestHandler(handler) {
94
43
  this.sidecarRequestHandler = handler;
@@ -104,10 +53,10 @@ export class SidecarProtocolClient {
104
53
  throw this.closedError;
105
54
  }
106
55
  const request = this.hostFrameFactory.createRequestFrame(input);
107
- // No per-request deadline: only the caller knows whether an operation is
108
- // legitimately long (a whole agent turn is one request). A dead or
109
- // wedged sidecar rejects this via the silence watchdog instead.
110
- const response = await this.frameTransport.sendFrame(request.request_id, request);
56
+ const response = await this.frameTransport.sendFrame(request.request_id, request, {
57
+ timeoutMs: this.frameTimeoutMs,
58
+ timeoutMessage: () => `timed out waiting for sidecar protocol frame for ${input.payload.type}\nstderr:\n${this.stderrText()}`,
59
+ });
111
60
  if (response.payload.type === "rejected") {
112
61
  throw new Error(`sidecar rejected request ${request.request_id}: ${response.payload.code}: ${response.payload.message}`);
113
62
  }
@@ -177,11 +126,9 @@ export class SidecarProtocolClient {
177
126
  }
178
127
  }
179
128
  this.closedError = error;
180
- this.stopSilenceWatchdog();
181
129
  this.rejectPending(error);
182
130
  }
183
131
  dispose() {
184
- this.stopSilenceWatchdog();
185
132
  this.frameTransport.dispose();
186
133
  }
187
134
  async writeFrame(frame) {
@@ -201,14 +148,6 @@ export class SidecarProtocolClient {
201
148
  }
202
149
  }
203
150
  dispatchEvent(event) {
204
- // Transport-level liveness beats from the sidecar. Their arrival already
205
- // reset the silence watchdog at the frame layer; they carry no meaning
206
- // for consumers and must never reach the bounded event buffer, where a
207
- // long-idle VM would accumulate one every 10s until overflow.
208
- if (event.payload.type === "structured" &&
209
- event.payload.name === "heartbeat") {
210
- return;
211
- }
212
151
  for (const listener of this.eventListeners) {
213
152
  try {
214
153
  listener(event);
@@ -9,7 +9,7 @@ export interface LiveGuestDirEntry {
9
9
  path: string;
10
10
  isDirectory: boolean;
11
11
  isSymbolicLink: boolean;
12
- size: bigint;
12
+ size: number;
13
13
  }
14
14
  export interface LiveSignalHandlerRegistration {
15
15
  action: LiveSignalDispositionAction;
@@ -95,7 +95,7 @@ export function fromGeneratedResponsePayload(payload) {
95
95
  path: entry.path,
96
96
  isDirectory: entry.isDirectory,
97
97
  isSymbolicLink: entry.isSymbolicLink,
98
- size: entry.size,
98
+ size: bigIntToSafeNumber(entry.size, "guest dir entry size"),
99
99
  })),
100
100
  }
101
101
  : {}),
@@ -8,21 +8,6 @@ export declare class SidecarProcessExited extends Error {
8
8
  stderr: string;
9
9
  });
10
10
  }
11
- /**
12
- * The silence watchdog fired: the sidecar produced no protocol frames at all —
13
- * not even its 10s liveness heartbeats — for the full silence window, so the
14
- * process is dead or wedged (not merely busy: a busy sidecar still heartbeats
15
- * from a dedicated thread). The host kills the sidecar and rejects every
16
- * in-flight request with this error.
17
- */
18
- export declare class SidecarSilenceTimeout extends Error {
19
- readonly silenceMs: number;
20
- readonly stderr: string;
21
- constructor(options: {
22
- silenceMs: number;
23
- stderr: string;
24
- });
25
- }
26
11
  export declare class SidecarProcessError extends Error {
27
12
  readonly childError: Error;
28
13
  readonly stderr: string;
@@ -18,23 +18,6 @@ export class SidecarProcessExited extends Error {
18
18
  this.stderr = options.stderr;
19
19
  }
20
20
  }
21
- /**
22
- * The silence watchdog fired: the sidecar produced no protocol frames at all —
23
- * not even its 10s liveness heartbeats — for the full silence window, so the
24
- * process is dead or wedged (not merely busy: a busy sidecar still heartbeats
25
- * from a dedicated thread). The host kills the sidecar and rejects every
26
- * in-flight request with this error.
27
- */
28
- export class SidecarSilenceTimeout extends Error {
29
- silenceMs;
30
- stderr;
31
- constructor(options) {
32
- super(`sidecar unresponsive: no protocol frames or heartbeats for ${Math.round(options.silenceMs)}ms; killing sidecar${formatSidecarStderrSuffix(options.stderr)}`);
33
- this.name = "SidecarSilenceTimeout";
34
- this.silenceMs = options.silenceMs;
35
- this.stderr = options.stderr;
36
- }
37
- }
38
21
  export class SidecarProcessError extends Error {
39
22
  childError;
40
23
  stderr;
@@ -9,9 +9,10 @@ import type { LiveFilesystemOperation, LiveGuestRuntimeKind, LiveWasmPermissionT
9
9
  import { type LiveEventFrame, type LiveSidecarRequestHandler, type LiveSidecarRequestFrame, type LiveSidecarResponseFrame, type ProtocolFramePayloadCodec } from "./protocol-frames.js";
10
10
  import type { LiveGuestDirEntry } from "./response-payloads.js";
11
11
  import { type LiveGuestFilesystemStat } from "./state.js";
12
- export { SidecarProcessError, SidecarProcessExited, SidecarSilenceTimeout, } from "./sidecar-errors.js";
12
+ export { SidecarProcessError, SidecarProcessExited, } from "./sidecar-errors.js";
13
13
  export { SidecarEventBufferOverflow } from "./event-buffer.js";
14
14
  export { SidecarProcess as Sidecar };
15
+ export declare const NATIVE_SIDECAR_FRAME_TIMEOUT_MS = 120000;
15
16
  type GuestRuntimeKind = Extract<LiveGuestRuntimeKind, "java_script" | "python" | "web_assembly">;
16
17
  type WasmPermissionTier = LiveWasmPermissionTier;
17
18
  export interface RootFilesystemEntry extends LiveRootFilesystemEntry {
@@ -104,25 +105,20 @@ export interface SidecarSpawnOptions {
104
105
  cwd?: string;
105
106
  command?: string;
106
107
  args?: string[];
108
+ frameTimeoutMs?: number;
107
109
  eventBufferCapacity?: number;
108
110
  payloadCodec?: NativeTransportPayloadCodec;
109
- /**
110
- * Override the sidecar silence watchdog window (default 30s). Tests only —
111
- * it is a fixed protocol constant paired with the sidecar's 10s heartbeat
112
- * cadence, not an operator tunable.
113
- */
114
- silenceTimeoutMs?: number;
115
111
  }
116
112
  export interface ResolvedSidecarSpawnOptions {
117
113
  cwd?: string;
118
114
  command?: string;
119
115
  args: string[];
116
+ frameTimeoutMs: number;
120
117
  eventBufferCapacity: number;
121
118
  gracefulExitMs: number;
122
119
  forceExitMs: number;
123
120
  disposedErrorMessage: string;
124
121
  payloadCodec: NativeTransportPayloadCodec;
125
- silenceTimeoutMs?: number;
126
122
  }
127
123
  type SidecarProcessSpawnFactory = (options: ResolvedSidecarSpawnOptions) => SidecarProcessTransport;
128
124
  export declare function registerSidecarProcessSpawnFactory(factory: SidecarProcessSpawnFactory): void;
@@ -1,12 +1,13 @@
1
1
  import { decodeGuestFilesystemContent, encodeGuestFilesystemContent, } from "./filesystem.js";
2
2
  import { SIDECAR_PROTOCOL_SCHEMA } from "./protocol-schema.js";
3
- export { SidecarProcessError, SidecarProcessExited, SidecarSilenceTimeout, } from "./sidecar-errors.js";
3
+ export { SidecarProcessError, SidecarProcessExited, } from "./sidecar-errors.js";
4
4
  export { SidecarEventBufferOverflow } from "./event-buffer.js";
5
5
  // `Sidecar` is the public name for the native sidecar process client. The class
6
6
  // is `SidecarProcess` internally; consumers import it as `Sidecar` via the
7
7
  // `@rivet-dev/agentos-runtime-core/sidecar-client` subpath and the package root.
8
8
  export { SidecarProcess as Sidecar };
9
9
  const BRIDGE_CONTRACT_VERSION = 1;
10
+ export const NATIVE_SIDECAR_FRAME_TIMEOUT_MS = 120_000;
10
11
  const DEFAULT_SIDECAR_EVENT_BUFFER_CAPACITY = 4_096;
11
12
  const DEFAULT_SIDECAR_GRACEFUL_EXIT_MS = 5_000;
12
13
  const DEFAULT_SIDECAR_FORCE_EXIT_MS = 2_000;
@@ -30,7 +31,7 @@ export class SidecarProcess {
30
31
  command: options.command,
31
32
  args: options.args ?? [],
32
33
  cwd: options.cwd,
33
- silenceTimeoutMs: options.silenceTimeoutMs,
34
+ frameTimeoutMs: options.frameTimeoutMs ?? NATIVE_SIDECAR_FRAME_TIMEOUT_MS,
34
35
  eventBufferCapacity: options.eventBufferCapacity ?? DEFAULT_SIDECAR_EVENT_BUFFER_CAPACITY,
35
36
  gracefulExitMs: DEFAULT_SIDECAR_GRACEFUL_EXIT_MS,
36
37
  forceExitMs: DEFAULT_SIDECAR_FORCE_EXIT_MS,
package/dist/state.d.ts CHANGED
@@ -1,18 +1,18 @@
1
1
  import * as protocol from "./generated-protocol.js";
2
2
  export interface LiveGuestFilesystemStat {
3
3
  mode: number;
4
- size: bigint;
5
- blocks: bigint;
6
- dev: bigint;
7
- rdev: bigint;
4
+ size: number;
5
+ blocks: number;
6
+ dev: number;
7
+ rdev: number;
8
8
  is_directory: boolean;
9
9
  is_symbolic_link: boolean;
10
10
  atime_ms: number;
11
11
  mtime_ms: number;
12
12
  ctime_ms: number;
13
13
  birthtime_ms: number;
14
- ino: bigint;
15
- nlink: bigint;
14
+ ino: number;
15
+ nlink: number;
16
16
  uid: number;
17
17
  gid: number;
18
18
  }
package/dist/state.js CHANGED
@@ -1,19 +1,20 @@
1
+ import { bigIntToSafeNumber } from "./numbers.js";
1
2
  import { fromGeneratedProcessSnapshotStatus } from "./protocol-maps.js";
2
3
  export function fromGeneratedGuestFilesystemStat(stat) {
3
4
  return {
4
5
  mode: stat.mode,
5
- size: stat.size,
6
- blocks: stat.blocks,
7
- dev: stat.dev,
8
- rdev: stat.rdev,
6
+ size: bigIntToSafeNumber(stat.size, "guest filesystem stat size"),
7
+ blocks: bigIntToSafeNumber(stat.blocks, "guest filesystem stat blocks"),
8
+ dev: bigIntToSafeNumber(stat.dev, "guest filesystem stat dev"),
9
+ rdev: bigIntToSafeNumber(stat.rdev, "guest filesystem stat rdev"),
9
10
  is_directory: stat.isDirectory,
10
11
  is_symbolic_link: stat.isSymbolicLink,
11
- atime_ms: Number(stat.atimeMs),
12
- mtime_ms: Number(stat.mtimeMs),
13
- ctime_ms: Number(stat.ctimeMs),
14
- birthtime_ms: Number(stat.birthtimeMs),
15
- ino: stat.ino,
16
- nlink: stat.nlink,
12
+ atime_ms: bigIntToSafeNumber(stat.atimeMs, "guest filesystem stat atime"),
13
+ mtime_ms: bigIntToSafeNumber(stat.mtimeMs, "guest filesystem stat mtime"),
14
+ ctime_ms: bigIntToSafeNumber(stat.ctimeMs, "guest filesystem stat ctime"),
15
+ birthtime_ms: bigIntToSafeNumber(stat.birthtimeMs, "guest filesystem stat birthtime"),
16
+ ino: bigIntToSafeNumber(stat.ino, "guest filesystem stat ino"),
17
+ nlink: bigIntToSafeNumber(stat.nlink, "guest filesystem stat nlink"),
17
18
  uid: stat.uid,
18
19
  gid: stat.gid,
19
20
  };
@@ -23,7 +23,6 @@ export interface VirtualDirEntry {
23
23
  export interface VirtualStat {
24
24
  mode: number;
25
25
  size: number;
26
- sizeExact?: bigint;
27
26
  blocks: number;
28
27
  dev: number;
29
28
  rdev: number;
@@ -34,9 +33,7 @@ export interface VirtualStat {
34
33
  ctimeMs: number;
35
34
  birthtimeMs: number;
36
35
  ino: number;
37
- inoExact?: bigint;
38
36
  nlink: number;
39
- nlinkExact?: bigint;
40
37
  uid: number;
41
38
  gid: number;
42
39
  }
@@ -5,7 +5,7 @@ import * as path from "node:path";
5
5
  import * as posixPath from "node:path/posix";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import "./native-client.js";
8
- import { NativeSidecarKernelProxy, SidecarProcess, serializeMountConfigForSidecar, } from "./kernel-proxy.js";
8
+ import { NATIVE_SIDECAR_FRAME_TIMEOUT_MS, NativeSidecarKernelProxy, SidecarProcess, serializeMountConfigForSidecar, } from "./kernel-proxy.js";
9
9
  import { resolvePublishedSidecarBinary } from "./binary.js";
10
10
  import { findCargoBinary, resolveCargoBinary } from "./cargo.js";
11
11
  export const AF_INET = 2;
@@ -2062,6 +2062,7 @@ class NativeKernel {
2062
2062
  cwd: REPO_ROOT,
2063
2063
  command: ensureNativeSidecarBinary(),
2064
2064
  args: [],
2065
+ frameTimeoutMs: NATIVE_SIDECAR_FRAME_TIMEOUT_MS,
2065
2066
  }));
2066
2067
  const session = await this.measureBoot("session_open", () => client.authenticateAndOpenSession());
2067
2068
  const vm = await this.measureBoot("vm_create", () => client.createVm(session, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivet-dev/agentos-runtime-core",
3
- "version": "0.0.0-ci-speed.3fd7050",
3
+ "version": "0.0.0-codex-actor-plugin-contract-coverage.115ca8a",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -192,7 +192,7 @@
192
192
  "test": "vitest run"
193
193
  },
194
194
  "dependencies": {
195
- "@rivet-dev/agentos-runtime-sidecar": "0.0.0-ci-speed.3fd7050",
195
+ "@rivet-dev/agentos-runtime-sidecar": "0.0.0-codex-actor-plugin-contract-coverage.115ca8a",
196
196
  "@rivetkit/bare-ts": "^0.6.2",
197
197
  "zod": "^4.1.11"
198
198
  },