@rivet-dev/agentos-core 0.2.0 → 0.2.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/agent-os.d.ts +27 -0
- package/dist/agent-os.js +45 -11
- package/dist/layers.d.ts +1 -0
- package/dist/layers.js +19 -3
- package/dist/options-schema.d.ts +2 -1
- package/dist/options-schema.js +1 -0
- package/dist/packages.js +1 -1
- package/dist/sidecar/rpc-client.d.ts +17 -1
- package/dist/sidecar/rpc-client.js +48 -3
- package/dist/types.d.ts +1 -1
- package/package.json +5 -5
package/dist/agent-os.d.ts
CHANGED
|
@@ -198,6 +198,25 @@ export interface AgentStderrEvent {
|
|
|
198
198
|
chunk: Uint8Array;
|
|
199
199
|
}
|
|
200
200
|
export type AgentStderrHandler = (event: AgentStderrEvent) => void;
|
|
201
|
+
/**
|
|
202
|
+
* A near-capacity warning for one bounded limit (a queue/buffer, a saturating
|
|
203
|
+
* resource cap, or a memory envelope) inside the VM runtime. Delivered the moment
|
|
204
|
+
* usage crosses the runtime's warning threshold (~80%), once per crossing — the
|
|
205
|
+
* runtime applies edge-triggering + hysteresis, so this never spams.
|
|
206
|
+
*/
|
|
207
|
+
export interface LimitWarning {
|
|
208
|
+
/** Stable limit name, e.g. `"javascript_event_channel"` or `"vm_open_fds"`. */
|
|
209
|
+
limit: string;
|
|
210
|
+
/** Limit class: `"queue"`, `"resource"`, or `"memory"`. */
|
|
211
|
+
category: string;
|
|
212
|
+
/** Current observed usage. */
|
|
213
|
+
observed: number;
|
|
214
|
+
/** Configured capacity. */
|
|
215
|
+
capacity: number;
|
|
216
|
+
/** Observed fill as a percentage of capacity (0–100). */
|
|
217
|
+
fillPercent: number;
|
|
218
|
+
}
|
|
219
|
+
export type LimitWarningHandler = (warning: LimitWarning) => void;
|
|
201
220
|
/**
|
|
202
221
|
* Public core VM options.
|
|
203
222
|
*
|
|
@@ -267,6 +286,12 @@ export interface AgentOsOptions {
|
|
|
267
286
|
* `process.stderr`.
|
|
268
287
|
*/
|
|
269
288
|
onAgentStderr?: AgentStderrHandler;
|
|
289
|
+
/**
|
|
290
|
+
* Called when a bounded limit inside the VM runtime approaches capacity
|
|
291
|
+
* (~80%, edge-triggered with hysteresis so it does not spam). Use it to alert
|
|
292
|
+
* on a slow consumer or a runaway guest before the limit is actually hit.
|
|
293
|
+
*/
|
|
294
|
+
onLimitWarning?: LimitWarningHandler;
|
|
270
295
|
}
|
|
271
296
|
/** Configuration for a local MCP server (spawned as a child process). */
|
|
272
297
|
export interface McpServerConfigLocal {
|
|
@@ -385,6 +410,7 @@ export declare class AgentOs {
|
|
|
385
410
|
private readonly _sidecarVm;
|
|
386
411
|
private readonly _disposeSidecarEventListener;
|
|
387
412
|
private readonly _agentStderrHandler?;
|
|
413
|
+
private readonly _limitWarningHandler?;
|
|
388
414
|
private constructor();
|
|
389
415
|
static createSidecar(options?: AgentOsCreateSidecarOptions): Promise<AgentOsSidecar>;
|
|
390
416
|
static getSharedSidecar(options?: AgentOsSharedSidecarOptions): Promise<AgentOsSidecar>;
|
|
@@ -473,6 +499,7 @@ export declare class AgentOs {
|
|
|
473
499
|
private _recordAgentStderr;
|
|
474
500
|
private _applySyntheticConfigOverrides;
|
|
475
501
|
private _handleSidecarEvent;
|
|
502
|
+
private _handleLimitWarning;
|
|
476
503
|
private _handleAcpExtEvent;
|
|
477
504
|
private _unsupportedConfigResponse;
|
|
478
505
|
private _sendAcpRequest;
|
package/dist/agent-os.js
CHANGED
|
@@ -1548,7 +1548,8 @@ export class AgentOs {
|
|
|
1548
1548
|
_sidecarVm;
|
|
1549
1549
|
_disposeSidecarEventListener;
|
|
1550
1550
|
_agentStderrHandler;
|
|
1551
|
-
|
|
1551
|
+
_limitWarningHandler;
|
|
1552
|
+
constructor(kernel, sidecar, softwareRoots, softwareAgentConfigs, hostMounts, env, rootFilesystem, sidecarClient, sidecarSession, sidecarVm, additionalInstructions, agentStderrHandler, limitWarningHandler) {
|
|
1552
1553
|
this.#kernel = kernel;
|
|
1553
1554
|
this.sidecar = sidecar;
|
|
1554
1555
|
this._softwareRoots = softwareRoots;
|
|
@@ -1561,6 +1562,7 @@ export class AgentOs {
|
|
|
1561
1562
|
this._sidecarVm = sidecarVm;
|
|
1562
1563
|
this._additionalInstructions = additionalInstructions;
|
|
1563
1564
|
this._agentStderrHandler = agentStderrHandler;
|
|
1565
|
+
this._limitWarningHandler = limitWarningHandler;
|
|
1564
1566
|
this._disposeSidecarEventListener = this._sidecarClient.onEvent((event) => {
|
|
1565
1567
|
this._handleSidecarEvent(event);
|
|
1566
1568
|
});
|
|
@@ -1787,7 +1789,7 @@ export class AgentOs {
|
|
|
1787
1789
|
createVm: async () => createVmAdmin(),
|
|
1788
1790
|
});
|
|
1789
1791
|
const vmAdmin = sidecarLease.admin;
|
|
1790
|
-
const vm = new AgentOs(vmAdmin.kernel, sidecar, processed.softwareRoots, processed.agentConfigs, vmAdmin.hostMounts, vmAdmin.env, vmAdmin.rootView, vmAdmin.sidecarClient, vmAdmin.sidecarSession, vmAdmin.sidecarVm, options?.additionalInstructions, options?.onAgentStderr ?? defaultAgentStderrHandler);
|
|
1792
|
+
const vm = new AgentOs(vmAdmin.kernel, sidecar, processed.softwareRoots, processed.agentConfigs, vmAdmin.hostMounts, vmAdmin.env, vmAdmin.rootView, vmAdmin.sidecarClient, vmAdmin.sidecarSession, vmAdmin.sidecarVm, options?.additionalInstructions, options?.onAgentStderr ?? defaultAgentStderrHandler, options?.onLimitWarning);
|
|
1791
1793
|
vm._sidecarLease = sidecarLease;
|
|
1792
1794
|
vm._toolKits = vmAdmin.toolKits;
|
|
1793
1795
|
vm._toolReference = vmAdmin.toolReference;
|
|
@@ -1818,6 +1820,11 @@ export class AgentOs {
|
|
|
1818
1820
|
exitHandlers,
|
|
1819
1821
|
};
|
|
1820
1822
|
this._processes.set(proc.pid, entry);
|
|
1823
|
+
// NOTE: do NOT delete from `_processes` on exit — the public API contract
|
|
1824
|
+
// (getProcess/listProcesses/stopProcess, see process-management.test.ts)
|
|
1825
|
+
// requires exited processes to stay queryable (running:false, exitCode set).
|
|
1826
|
+
// `_processes` is a process table for this VM's lifetime; it is freed wholesale
|
|
1827
|
+
// in dispose(). (H5: the leak was that dispose() never cleared it.)
|
|
1821
1828
|
void proc.wait().then((code) => {
|
|
1822
1829
|
for (const h of exitHandlers)
|
|
1823
1830
|
h(code);
|
|
@@ -2000,14 +2007,13 @@ export class AgentOs {
|
|
|
2000
2007
|
/** Recursively create directories (mkdir -p). */
|
|
2001
2008
|
async _mkdirp(path) {
|
|
2002
2009
|
this._assertWritableAbsolutePath(path);
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
}
|
|
2010
|
+
// `kernel.mkdir` is already recursive (it defaults to recursive=true on both
|
|
2011
|
+
// the native sidecar and compat kernels) and creating an existing directory is
|
|
2012
|
+
// a no-op, so a single call is sufficient. Do NOT probe each ancestor with
|
|
2013
|
+
// `exists()` first: on the native sidecar every read-side op
|
|
2014
|
+
// (exists/stat/readFile) triggers a full shadow-tree walk, so a per-component
|
|
2015
|
+
// exists() loop makes `mkdir -p` cost O(components * tree).
|
|
2016
|
+
await this.#kernel.mkdir(path);
|
|
2011
2017
|
}
|
|
2012
2018
|
async mkdir(path, options) {
|
|
2013
2019
|
if (options?.recursive) {
|
|
@@ -2476,6 +2482,10 @@ export class AgentOs {
|
|
|
2476
2482
|
if (event.payload.type !== "structured") {
|
|
2477
2483
|
return;
|
|
2478
2484
|
}
|
|
2485
|
+
if (event.payload.name === "limit_warning") {
|
|
2486
|
+
this._handleLimitWarning(event.payload.detail);
|
|
2487
|
+
return;
|
|
2488
|
+
}
|
|
2479
2489
|
if (event.payload.name !== "acp.session_event") {
|
|
2480
2490
|
return;
|
|
2481
2491
|
}
|
|
@@ -2495,6 +2505,27 @@ export class AgentOs {
|
|
|
2495
2505
|
// Ignore malformed event payloads from the sidecar.
|
|
2496
2506
|
}
|
|
2497
2507
|
}
|
|
2508
|
+
_handleLimitWarning(detail) {
|
|
2509
|
+
if (!this._limitWarningHandler) {
|
|
2510
|
+
return;
|
|
2511
|
+
}
|
|
2512
|
+
const toNumber = (value) => {
|
|
2513
|
+
const parsed = Number(value);
|
|
2514
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
2515
|
+
};
|
|
2516
|
+
try {
|
|
2517
|
+
this._limitWarningHandler({
|
|
2518
|
+
limit: detail.limit ?? "",
|
|
2519
|
+
category: detail.category ?? "",
|
|
2520
|
+
observed: toNumber(detail.observed),
|
|
2521
|
+
capacity: toNumber(detail.capacity),
|
|
2522
|
+
fillPercent: toNumber(detail.fillPercent),
|
|
2523
|
+
});
|
|
2524
|
+
}
|
|
2525
|
+
catch {
|
|
2526
|
+
// A throwing handler must never break the sidecar event loop.
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2498
2529
|
_handleAcpExtEvent(envelope) {
|
|
2499
2530
|
if (envelope.namespace !== ACP_EXTENSION_NAMESPACE) {
|
|
2500
2531
|
return;
|
|
@@ -2936,7 +2967,9 @@ export class AgentOs {
|
|
|
2936
2967
|
case "host_callback":
|
|
2937
2968
|
return handleHostCallback(request, context);
|
|
2938
2969
|
case "js_bridge_call":
|
|
2939
|
-
return handleJsBridgeCall(request.payload, {
|
|
2970
|
+
return handleJsBridgeCall(request.payload, {
|
|
2971
|
+
filesystem: this.#kernel.vfs,
|
|
2972
|
+
});
|
|
2940
2973
|
case "ext":
|
|
2941
2974
|
return this._handleAcpExtSidecarRequest(request.payload.envelope);
|
|
2942
2975
|
}
|
|
@@ -3624,6 +3657,7 @@ export class AgentOs {
|
|
|
3624
3657
|
terminalExitPromises.push(terminal.waitPromise.then(() => undefined, () => undefined));
|
|
3625
3658
|
}
|
|
3626
3659
|
this._acpTerminals.clear();
|
|
3660
|
+
this._processes.clear();
|
|
3627
3661
|
await waitForTrackedExitPromises([...shellExitPromises, ...terminalExitPromises], SHELL_DISPOSE_TIMEOUT_MS);
|
|
3628
3662
|
this._disposeSidecarEventListener();
|
|
3629
3663
|
const sidecarLease = this._sidecarLease;
|
package/dist/layers.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export interface LayerStore {
|
|
|
45
45
|
mode: "read-only";
|
|
46
46
|
lowers: SnapshotLayerHandle[];
|
|
47
47
|
}): VirtualFileSystem;
|
|
48
|
+
dispose(): void;
|
|
48
49
|
}
|
|
49
50
|
export declare function createSnapshotExport(entries: FilesystemEntry[]): RootSnapshotExport;
|
|
50
51
|
export declare function createInMemoryLayerStore(): LayerStore;
|
package/dist/layers.js
CHANGED
|
@@ -73,8 +73,11 @@ export function createInMemoryLayerStore() {
|
|
|
73
73
|
}
|
|
74
74
|
return state;
|
|
75
75
|
}
|
|
76
|
-
|
|
76
|
+
const store = {
|
|
77
77
|
storeId,
|
|
78
|
+
get retainedLayerCount() {
|
|
79
|
+
return layers.size;
|
|
80
|
+
},
|
|
78
81
|
async createWritableLayer() {
|
|
79
82
|
const layerId = randomUUID();
|
|
80
83
|
const leaseId = randomUUID();
|
|
@@ -117,10 +120,11 @@ export function createInMemoryLayerStore() {
|
|
|
117
120
|
if (state.kind !== "writable") {
|
|
118
121
|
throw new Error(`Layer ${layer.layerId} is not writable`);
|
|
119
122
|
}
|
|
120
|
-
|
|
123
|
+
const baseFs = state.activeOverlay ?? state.fs;
|
|
124
|
+
if (!state.valid || state.leaseId !== layer.leaseId || !baseFs) {
|
|
121
125
|
throw new Error(`Writable layer ${layer.layerId} is no longer valid`);
|
|
122
126
|
}
|
|
123
|
-
const entries = await snapshotVirtualFilesystem(
|
|
127
|
+
const entries = await snapshotVirtualFilesystem(baseFs);
|
|
124
128
|
const snapshot = createSnapshotExport(entries).source;
|
|
125
129
|
const layerId = randomUUID();
|
|
126
130
|
layers.set(layerId, {
|
|
@@ -128,8 +132,11 @@ export function createInMemoryLayerStore() {
|
|
|
128
132
|
snapshot,
|
|
129
133
|
fs: await createFilesystemFromEntries(snapshot.filesystem.entries),
|
|
130
134
|
});
|
|
135
|
+
// Release the writable layer's filesystem payload now that it is sealed;
|
|
136
|
+
// the invalid tombstone is retained so stale handles still report cleanly.
|
|
131
137
|
state.valid = false;
|
|
132
138
|
state.activeOverlay = null;
|
|
139
|
+
state.fs = null;
|
|
133
140
|
return cloneSnapshotHandle(storeId, layerId);
|
|
134
141
|
},
|
|
135
142
|
createOverlayFilesystem(options) {
|
|
@@ -162,6 +169,9 @@ export function createInMemoryLayerStore() {
|
|
|
162
169
|
if (upperState.activeOverlay) {
|
|
163
170
|
throw new Error(`Writable layer ${options.upper.layerId} is already attached to an overlay`);
|
|
164
171
|
}
|
|
172
|
+
if (!upperState.fs) {
|
|
173
|
+
throw new Error(`Writable layer ${options.upper.layerId} is no longer valid`);
|
|
174
|
+
}
|
|
165
175
|
const overlay = createOverlayBackend({
|
|
166
176
|
upper: upperState.fs,
|
|
167
177
|
lowers: lowers.map((lower) => {
|
|
@@ -175,7 +185,13 @@ export function createInMemoryLayerStore() {
|
|
|
175
185
|
upperState.activeOverlay = overlay;
|
|
176
186
|
return overlay;
|
|
177
187
|
},
|
|
188
|
+
dispose() {
|
|
189
|
+
// Release every retained layer's filesystem payload so the store does
|
|
190
|
+
// not accumulate snapshots/writable layers for the process lifetime.
|
|
191
|
+
layers.clear();
|
|
192
|
+
},
|
|
178
193
|
};
|
|
194
|
+
return store;
|
|
179
195
|
}
|
|
180
196
|
export function createDefaultRootLowerInput() {
|
|
181
197
|
return {
|
package/dist/options-schema.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
|
-
import type { AgentOsOptions, AgentStderrHandler, NativeMountConfig } from "./agent-os.js";
|
|
2
|
+
import type { AgentOsOptions, AgentStderrHandler, LimitWarningHandler, NativeMountConfig } from "./agent-os.js";
|
|
3
3
|
import type { HostTool, ToolKit } from "./host-tools.js";
|
|
4
4
|
export declare const permissionsSchema: z.ZodObject<{
|
|
5
5
|
fs: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
@@ -432,6 +432,7 @@ export declare const agentOsOptionFieldSchemas: {
|
|
|
432
432
|
}, z.core.$strict>>;
|
|
433
433
|
}, z.core.$strict>>;
|
|
434
434
|
readonly onAgentStderr: z.ZodOptional<z.ZodCustom<AgentStderrHandler, AgentStderrHandler>>;
|
|
435
|
+
readonly onLimitWarning: z.ZodOptional<z.ZodCustom<LimitWarningHandler, LimitWarningHandler>>;
|
|
435
436
|
};
|
|
436
437
|
export declare const agentOsOptionsSchema: z.ZodType<AgentOsOptions>;
|
|
437
438
|
export declare function parseAgentOsOptions(options?: AgentOsOptions): AgentOsOptions;
|
package/dist/options-schema.js
CHANGED
|
@@ -250,6 +250,7 @@ export const agentOsOptionFieldSchemas = {
|
|
|
250
250
|
sidecar: sidecarConfigSchema.optional(),
|
|
251
251
|
limits: agentOsLimitsSchema.optional(),
|
|
252
252
|
onAgentStderr: z.custom((value) => typeof value === "function", { message: "Expected function" }).optional(),
|
|
253
|
+
onLimitWarning: z.custom((value) => typeof value === "function", { message: "Expected function" }).optional(),
|
|
253
254
|
};
|
|
254
255
|
export const agentOsOptionsSchema = z
|
|
255
256
|
.object(agentOsOptionFieldSchemas)
|
package/dist/packages.js
CHANGED
|
@@ -32,7 +32,7 @@ export function resolvePackageDir(startDir, packageName) {
|
|
|
32
32
|
throw new Error(`Package "${packageName}" not found starting from ${startDir}. ` +
|
|
33
33
|
`Ensure it is installed.`);
|
|
34
34
|
}
|
|
35
|
-
const LOCAL_REGISTRY_COMMAND_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "
|
|
35
|
+
const LOCAL_REGISTRY_COMMAND_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "../../../../secure-exec", "registry/native/target/wasm32-wasip1/release/commands");
|
|
36
36
|
function readPackageName(packageDir) {
|
|
37
37
|
const pkg = JSON.parse(readFileSync(join(packageDir, "package.json"), "utf-8"));
|
|
38
38
|
if (typeof pkg.name !== "string" || pkg.name.length === 0) {
|
|
@@ -2,7 +2,7 @@ import type { RootFilesystemConfig as VmConfigRootFilesystemConfig, RootFilesyst
|
|
|
2
2
|
import type { NativeMountConfig, PlainMountConfig, RootFilesystemConfig } from "../agent-os.js";
|
|
3
3
|
import type { RootSnapshotExport } from "../layers.js";
|
|
4
4
|
import type { ConnectTerminalOptions, KernelExecOptions, KernelExecResult, KernelSpawnOptions, ManagedProcess, OpenShellOptions, ProcessInfo, ShellHandle, VirtualFileSystem, VirtualStat } from "../runtime-compat.js";
|
|
5
|
-
import type { AuthenticatedSession, CreatedVm,
|
|
5
|
+
import type { AuthenticatedSession, CreatedVm, SidecarPermissionsPolicy, SidecarProcess, SidecarSignalHandlerRegistration } from "./native-process-client.js";
|
|
6
6
|
export declare function toSidecarSignalName(signal: number): string;
|
|
7
7
|
export interface LocalCompatMount {
|
|
8
8
|
path: string;
|
|
@@ -89,6 +89,21 @@ export declare class NativeSidecarKernelProxy {
|
|
|
89
89
|
get zombieTimerCount(): number;
|
|
90
90
|
registerCommandGuestPaths(commandGuestPaths: ReadonlyMap<string, string>): void;
|
|
91
91
|
dispose(): Promise<void>;
|
|
92
|
+
/** Test-only snapshot of the per-VM tracking collection sizes. */
|
|
93
|
+
__trackingSizesForTest(): {
|
|
94
|
+
trackedProcesses: number;
|
|
95
|
+
trackedProcessesById: number;
|
|
96
|
+
signalStates: number;
|
|
97
|
+
signalRefreshes: number;
|
|
98
|
+
localMounts: number;
|
|
99
|
+
};
|
|
100
|
+
/** Test-only handle to a tracked entry so its listener Sets can be inspected. */
|
|
101
|
+
__trackedEntryForTest(pid: number): {
|
|
102
|
+
onStdout: ReadonlySet<unknown>;
|
|
103
|
+
onStderr: ReadonlySet<unknown>;
|
|
104
|
+
} | undefined;
|
|
105
|
+
/** Test-only join point for in-flight signal-state refreshes. */
|
|
106
|
+
__awaitSignalRefreshesForTest(): Promise<void>;
|
|
92
107
|
exec(command: string, options?: KernelExecOptions): Promise<KernelExecResult>;
|
|
93
108
|
execArgv(command: string, args?: readonly string[], options?: KernelExecOptions): Promise<KernelExecResult>;
|
|
94
109
|
spawn(command: string, args: string[], options?: KernelSpawnOptions): ManagedProcess;
|
|
@@ -130,6 +145,7 @@ export declare class NativeSidecarKernelProxy {
|
|
|
130
145
|
private startTrackedProcess;
|
|
131
146
|
private runEventPump;
|
|
132
147
|
private finishProcess;
|
|
148
|
+
private releaseProcessTrackingAfterDrain;
|
|
133
149
|
private waitForTrackedProcess;
|
|
134
150
|
private signalProcess;
|
|
135
151
|
private flushPendingStdin;
|
|
@@ -273,6 +273,34 @@ export class NativeSidecarKernelProxy {
|
|
|
273
273
|
}
|
|
274
274
|
await this.eventPump.catch(() => { });
|
|
275
275
|
await this.onDispose?.().catch(() => { });
|
|
276
|
+
// Drop all per-VM tracking state so a disposed proxy retains nothing.
|
|
277
|
+
for (const entry of this.trackedProcesses.values()) {
|
|
278
|
+
entry.onStdout.clear();
|
|
279
|
+
entry.onStderr.clear();
|
|
280
|
+
}
|
|
281
|
+
this.trackedProcesses.clear();
|
|
282
|
+
this.trackedProcessesById.clear();
|
|
283
|
+
this.signalStates.clear();
|
|
284
|
+
this.signalRefreshes.clear();
|
|
285
|
+
this.localMounts.length = 0;
|
|
286
|
+
}
|
|
287
|
+
/** Test-only snapshot of the per-VM tracking collection sizes. */
|
|
288
|
+
__trackingSizesForTest() {
|
|
289
|
+
return {
|
|
290
|
+
trackedProcesses: this.trackedProcesses.size,
|
|
291
|
+
trackedProcessesById: this.trackedProcessesById.size,
|
|
292
|
+
signalStates: this.signalStates.size,
|
|
293
|
+
signalRefreshes: this.signalRefreshes.size,
|
|
294
|
+
localMounts: this.localMounts.length,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/** Test-only handle to a tracked entry so its listener Sets can be inspected. */
|
|
298
|
+
__trackedEntryForTest(pid) {
|
|
299
|
+
return this.trackedProcesses.get(pid);
|
|
300
|
+
}
|
|
301
|
+
/** Test-only join point for in-flight signal-state refreshes. */
|
|
302
|
+
async __awaitSignalRefreshesForTest() {
|
|
303
|
+
await Promise.allSettled([...this.signalRefreshes.values()]);
|
|
276
304
|
}
|
|
277
305
|
async exec(command, options) {
|
|
278
306
|
if (!this.commands.has("sh")) {
|
|
@@ -1226,8 +1254,7 @@ export class NativeSidecarKernelProxy {
|
|
|
1226
1254
|
const vmId = this.vm.vmId;
|
|
1227
1255
|
while (!this.disposed) {
|
|
1228
1256
|
try {
|
|
1229
|
-
const event = await this.client.waitForEvent((frame) => frame.ownership.scope === "vm" &&
|
|
1230
|
-
frame.ownership.vm_id === vmId, undefined, { signal: this.eventPumpAbortController.signal });
|
|
1257
|
+
const event = await this.client.waitForEvent((frame) => frame.ownership.scope === "vm" && frame.ownership.vm_id === vmId, undefined, { signal: this.eventPumpAbortController.signal });
|
|
1231
1258
|
if (event.payload.type === "process_output") {
|
|
1232
1259
|
const entry = this.trackedProcessesById.get(event.payload.process_id);
|
|
1233
1260
|
if (!entry) {
|
|
@@ -1254,7 +1281,6 @@ export class NativeSidecarKernelProxy {
|
|
|
1254
1281
|
continue;
|
|
1255
1282
|
}
|
|
1256
1283
|
void this.refreshProcessSnapshot().catch(() => { });
|
|
1257
|
-
this.signalRefreshes.delete(entry.pid);
|
|
1258
1284
|
this.finishProcess(entry, event.payload.exit_code);
|
|
1259
1285
|
}
|
|
1260
1286
|
}
|
|
@@ -1286,6 +1312,25 @@ export class NativeSidecarKernelProxy {
|
|
|
1286
1312
|
entry.exitTime = Date.now();
|
|
1287
1313
|
this.updateTrackedProcessSnapshot(entry);
|
|
1288
1314
|
entry.resolveWait(exitCode);
|
|
1315
|
+
// Release per-process tracking now that the process has terminated so these
|
|
1316
|
+
// maps/Sets don't grow without bound. Defer the release until trailing
|
|
1317
|
+
// output has drained: `wait()`'s drain and late `process_output` events
|
|
1318
|
+
// still need the entry + its listeners during the drain window. The exited
|
|
1319
|
+
// record lives on in `processes` for listing.
|
|
1320
|
+
void this.releaseProcessTrackingAfterDrain(entry);
|
|
1321
|
+
}
|
|
1322
|
+
async releaseProcessTrackingAfterDrain(entry) {
|
|
1323
|
+
try {
|
|
1324
|
+
await this.drainTrailingProcessOutput(entry);
|
|
1325
|
+
}
|
|
1326
|
+
finally {
|
|
1327
|
+
this.trackedProcesses.delete(entry.pid);
|
|
1328
|
+
this.trackedProcessesById.delete(entry.processId);
|
|
1329
|
+
this.signalRefreshes.delete(entry.pid);
|
|
1330
|
+
this.signalStates.delete(entry.pid);
|
|
1331
|
+
entry.onStdout.clear();
|
|
1332
|
+
entry.onStderr.clear();
|
|
1333
|
+
}
|
|
1289
1334
|
}
|
|
1290
1335
|
waitForTrackedProcess(entry) {
|
|
1291
1336
|
if (entry.exitCode !== null) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { AgentCapabilities, AgentInfo, AgentOsCreateSidecarOptions, AgentOsLimits, AgentOsOptions, AgentOsSharedSidecarOptions, AgentOsSidecarConfig, AgentOsSidecarDescription, AgentStderrEvent, AgentStderrHandler, AgentRegistryEntry, BatchReadResult, BatchWriteEntry, BatchWriteResult, CreateSessionOptions, DirEntry, McpServerConfig, McpServerConfigLocal, McpServerConfigRemote, MountConfig, MountConfigJsonObject, MountConfigJsonPrimitive, MountConfigJsonValue, NativeMountConfig, NativeMountPluginDescriptor, OverlayMountConfig, PermissionReply, PermissionRequest, PermissionRequestHandler, PlainMountConfig, ProcessTreeNode, PromptResult, ReaddirRecursiveOptions, ResumeSessionOptions, ResumeSessionResult, RootFilesystemConfig, RootLowerInput, SessionConfigOption, SessionEventHandler, SessionInfo, SessionInitData, SessionMode, SessionModeState, SpawnedProcessInfo, } from "./agent-os.js";
|
|
1
|
+
export type { AgentCapabilities, AgentInfo, AgentOsCreateSidecarOptions, AgentOsLimits, AgentOsOptions, AgentOsSharedSidecarOptions, AgentOsSidecarConfig, AgentOsSidecarDescription, AgentStderrEvent, AgentStderrHandler, AgentRegistryEntry, BatchReadResult, BatchWriteEntry, BatchWriteResult, CreateSessionOptions, DirEntry, LimitWarning, LimitWarningHandler, McpServerConfig, McpServerConfigLocal, McpServerConfigRemote, MountConfig, MountConfigJsonObject, MountConfigJsonPrimitive, MountConfigJsonValue, NativeMountConfig, NativeMountPluginDescriptor, OverlayMountConfig, PermissionReply, PermissionRequest, PermissionRequestHandler, PlainMountConfig, ProcessTreeNode, PromptResult, ReaddirRecursiveOptions, ResumeSessionOptions, ResumeSessionResult, RootFilesystemConfig, RootLowerInput, SessionConfigOption, SessionEventHandler, SessionInfo, SessionInitData, SessionMode, SessionModeState, SpawnedProcessInfo, } from "./agent-os.js";
|
|
2
2
|
export type { AgentConfig, AgentType } from "./agents.js";
|
|
3
3
|
export type { CronAction, CronEvent, CronEventHandler, CronJob, CronJobInfo, CronJobOptions, ScheduleDriver, ScheduleEntry, ScheduleHandle, } from "./cron/index.js";
|
|
4
4
|
export type { HostDirBackendOptions, HostDirMountPluginConfig, NodeModulesMountConfig, } from "./host-dir-mount.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivet-dev/agentos-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@agentos-software/common": "0.3.0-rc.2",
|
|
58
58
|
"@aws-sdk/client-s3": "^3.1019.0",
|
|
59
|
-
"@rivet-dev/agentos-sidecar": "0.2.
|
|
59
|
+
"@rivet-dev/agentos-sidecar": "0.2.1",
|
|
60
60
|
"@rivetkit/bare-ts": "^0.6.2",
|
|
61
|
-
"@secure-exec/core": "0.3.
|
|
61
|
+
"@secure-exec/core": "0.3.2",
|
|
62
62
|
"@xterm/headless": "^6.0.0",
|
|
63
63
|
"better-sqlite3": "^12.8.0",
|
|
64
64
|
"croner": "^10.0.1",
|
|
@@ -79,8 +79,8 @@
|
|
|
79
79
|
"@copilotkit/llmock": "^1.6.0",
|
|
80
80
|
"@rivet-dev/agentos-sandbox": "link:../agentos-sandbox",
|
|
81
81
|
"@agentos-software/git": "0.3.0-rc.2",
|
|
82
|
-
"@secure-exec/google-drive": "0.3.
|
|
83
|
-
"@secure-exec/s3": "0.3.
|
|
82
|
+
"@secure-exec/google-drive": "0.3.2",
|
|
83
|
+
"@secure-exec/s3": "0.3.2",
|
|
84
84
|
"@mariozechner/pi-coding-agent": "^0.60.0",
|
|
85
85
|
"@agentos-software/claude-code": "0.0.0-nathan-binding-workspace.9be0a88",
|
|
86
86
|
"@agentos-software/codex-cli": "0.0.0-codex-claude-runtime-fixes.9cbef3a",
|