@rivet-dev/agentos-core 0.4.0 → 0.4.2
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 +3 -3
- package/dist/agent-os.js +12 -1
- package/dist/default-software/coreutils.aospkg +2 -2
- package/dist/default-software/diffutils.aospkg +0 -0
- package/dist/default-software/findutils.aospkg +0 -0
- package/dist/default-software/gawk.aospkg +0 -0
- package/dist/default-software/grep.aospkg +0 -0
- package/dist/default-software/gzip.aospkg +0 -0
- package/dist/default-software/sed.aospkg +0 -0
- package/dist/default-software/tar.aospkg +0 -0
- package/dist/language-execution.d.ts +7 -0
- package/dist/sidecar/rpc-client.d.ts +1 -1
- package/dist/sidecar/rpc-client.js +46 -9
- package/package.json +4 -4
package/dist/agent-os.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NativeMountPluginDescriptor } from "@rivet-dev/agentos-runtime-core/descriptors";
|
|
2
2
|
import type { CreateVmConfig, VmUserConfig } from "@rivet-dev/agentos-runtime-core/vm-config";
|
|
3
3
|
import { type HostFunctionCollections, type HostFunctionSchemas } from "@rivet-dev/agentos-runtime-core/host-functions";
|
|
4
|
-
import type { CodeEvaluationResult, CodeExecutionResult, ContextDescriptor, ExecutionSignal, InlineExecutionOptions, JavaScriptEvaluationOptions, JavaScriptExecutionOptions, JsonValue, LanguageExecutionOptions, LanguageSpawnOptions, NpmPackageInstallOptions, NpmProjectInstallOptions, OutputReplay, ProcessDescriptor, ProcessExit,
|
|
4
|
+
import type { CodeEvaluationResult, CodeExecutionResult, ContextDescriptor, ExecutionSignal, InlineExecutionOptions, JavaScriptEvaluationOptions, JavaScriptExecutionOptions, JsonValue, LanguageExecutionOptions, LanguageSpawnOptions, NpmPackageInstallOptions, NpmProjectInstallOptions, OutputReplay, ProcessDescriptor, ProcessExit, ProcessSpawnOptions, PythonInstallOptions, TypeScriptCheckOptions, TypeScriptCheckResult, TypeScriptEvaluationOptions, TypeScriptExecutionOptions, TypeScriptFileExecutionOptions } from "./language-execution.js";
|
|
5
5
|
import type { ConnectTerminalOptions, Kernel, KernelExecOptions, KernelExecResult, OpenShellOptions, Permissions, VirtualFileSystem, VirtualStat } from "./runtime-compat.js";
|
|
6
6
|
import { type AgentOsSandboxInput } from "./sandbox.js";
|
|
7
7
|
import { type ReplayReadOptions } from "./output-replay.js";
|
|
@@ -461,7 +461,7 @@ export declare class AgentOs {
|
|
|
461
461
|
readonly process: {
|
|
462
462
|
exec: (command: string, options?: LanguageExecutionOptions) => Promise<CodeExecutionResult>;
|
|
463
463
|
execFile: (command: string, args?: readonly string[], options?: Omit<LanguageExecutionOptions, "args">) => Promise<CodeExecutionResult>;
|
|
464
|
-
spawn: (command: string, args?: string[], options?:
|
|
464
|
+
spawn: (command: string, args?: string[], options?: ProcessSpawnOptions) => Promise<ProcessDescriptor>;
|
|
465
465
|
get: (pid: number) => Promise<ProcessDescriptor>;
|
|
466
466
|
list: () => Promise<ProcessDescriptor[]>;
|
|
467
467
|
tree: () => Promise<ProcessTreeNode[]>;
|
|
@@ -630,7 +630,7 @@ export declare class AgentOs {
|
|
|
630
630
|
private _reserveProcessRegistrySlot;
|
|
631
631
|
private _pruneExitedProcesses;
|
|
632
632
|
private _spawnProcess;
|
|
633
|
-
spawn(command: string, args?: string[], options?:
|
|
633
|
+
spawn(command: string, args?: string[], options?: ProcessSpawnOptions): Promise<ProcessDescriptor>;
|
|
634
634
|
/** Write data to a process's stdin. */
|
|
635
635
|
private _writeProcessStdin;
|
|
636
636
|
/** Close a process's stdin stream. */
|
package/dist/agent-os.js
CHANGED
|
@@ -2648,7 +2648,7 @@ export class AgentOs {
|
|
|
2648
2648
|
env: options.env,
|
|
2649
2649
|
stdin: options.stdin,
|
|
2650
2650
|
timeout: options.timeoutMs,
|
|
2651
|
-
streamStdin: true,
|
|
2651
|
+
streamStdin: options.streamStdin ?? true,
|
|
2652
2652
|
retainOutput: options.output?.retainEvents ?? false,
|
|
2653
2653
|
onStdout: (data, metadata) => {
|
|
2654
2654
|
options?.onStdout?.(data);
|
|
@@ -3926,6 +3926,17 @@ function ensureSharedSidecarNativeProcess(sidecar) {
|
|
|
3926
3926
|
applySharedSidecarHold(state);
|
|
3927
3927
|
try {
|
|
3928
3928
|
const session = await client.authenticateAndOpenSession();
|
|
3929
|
+
// A transport that fails for good (process exit, silence watchdog,
|
|
3930
|
+
// event buffer overflow, undecodable frame) leaves the VMs out of
|
|
3931
|
+
// reach. Stop the process, as the Rust client does, and report the
|
|
3932
|
+
// handle disposed so a shared pool spawns a fresh sidecar.
|
|
3933
|
+
const child = state.sharedChild;
|
|
3934
|
+
client.onClose(() => {
|
|
3935
|
+
child?.kill?.("SIGKILL");
|
|
3936
|
+
if (state.description.state === "ready") {
|
|
3937
|
+
state.description.state = "disposed";
|
|
3938
|
+
}
|
|
3939
|
+
});
|
|
3929
3940
|
return { client, session };
|
|
3930
3941
|
}
|
|
3931
3942
|
catch (error) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/dist/default-software/coreutils.aospkg
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 67548825 bytes
|
|
4
|
+
sha256: be05ed39037fb797efb65701f766f9a9bac8b11f80596226fcfaad4d52488656
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -110,6 +110,13 @@ export interface SpawnOptions {
|
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
export type LanguageSpawnOptions = SpawnOptions;
|
|
113
|
+
export interface ProcessSpawnOptions extends SpawnOptions {
|
|
114
|
+
/**
|
|
115
|
+
* Keep stdin open for `writeStdin`. Defaults to `true`. With `false` the
|
|
116
|
+
* process reads EOF as soon as it starts, as with `</dev/null`.
|
|
117
|
+
*/
|
|
118
|
+
streamStdin?: boolean;
|
|
119
|
+
}
|
|
113
120
|
export interface ExecutionErrorData {
|
|
114
121
|
code: string;
|
|
115
122
|
name: string;
|
|
@@ -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 { ProcessForestRecord } from "../process-forest.js";
|
|
5
|
-
import type
|
|
5
|
+
import { type ConnectTerminalOptions, type KernelExecOptions, type KernelExecResult, type KernelSpawnOptions, type ManagedProcess, type OpenShellOptions, type ProcessInfo, type ShellHandle, type VirtualFileSystem, type VirtualStat } from "../runtime-compat.js";
|
|
6
6
|
import type { AuthenticatedSession, CreatedVm, SidecarPermissionsPolicy, SidecarProcess, SidecarSignalHandlerRegistration } from "./native-process-client.js";
|
|
7
7
|
export declare function toSidecarSignalName(signal: number): string;
|
|
8
8
|
export interface LocalCompatMount {
|
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { constants as osConstants } from "node:os";
|
|
3
3
|
import { posix as posixPath } from "node:path";
|
|
4
4
|
import { SidecarRejectedError } from "@rivet-dev/agentos-runtime-core/sidecar-errors";
|
|
5
|
+
import { KernelError, } from "../runtime-compat.js";
|
|
5
6
|
const SYNTHETIC_PID_BASE = 1_000_000;
|
|
6
7
|
const MISSING_EXIT_EVENT_GRACE_MS = 500;
|
|
7
8
|
const PROTECTED_READ_ONLY_GUEST_ROOTS = ["/etc/agentos"];
|
|
@@ -458,11 +459,13 @@ export class NativeSidecarKernelProxy {
|
|
|
458
459
|
const parsedCommand = parseSimpleExecCommand(command);
|
|
459
460
|
const runAndCapture = async (proc, stdinOverride, readExitCode) => {
|
|
460
461
|
const shellExitCode = await runManagedProcessToCompletion(proc, async () => {
|
|
462
|
+
// A command may exit without reading its input, as `true` does in
|
|
463
|
+
// `echo x | true`; its exit status is the result.
|
|
461
464
|
if (stdinOverride !== undefined) {
|
|
462
|
-
await proc.writeStdin(stdinOverride);
|
|
465
|
+
await proc.writeStdin(stdinOverride).catch(ignoreBrokenPipe);
|
|
463
466
|
}
|
|
464
467
|
else if (options?.stdin !== undefined) {
|
|
465
|
-
await proc.writeStdin(options.stdin);
|
|
468
|
+
await proc.writeStdin(options.stdin).catch(ignoreBrokenPipe);
|
|
466
469
|
}
|
|
467
470
|
// Non-interactive runs must observe EOF after any provided input.
|
|
468
471
|
await proc.closeStdin();
|
|
@@ -527,7 +530,7 @@ export class NativeSidecarKernelProxy {
|
|
|
527
530
|
const runAndCapture = async (proc) => {
|
|
528
531
|
const exitCode = await runManagedProcessToCompletion(proc, async () => {
|
|
529
532
|
if (options?.stdin !== undefined) {
|
|
530
|
-
await proc.writeStdin(options.stdin);
|
|
533
|
+
await proc.writeStdin(options.stdin).catch(ignoreBrokenPipe);
|
|
531
534
|
}
|
|
532
535
|
await proc.closeStdin();
|
|
533
536
|
}, deadlineMs);
|
|
@@ -620,7 +623,7 @@ export class NativeSidecarKernelProxy {
|
|
|
620
623
|
processId,
|
|
621
624
|
writeStdin: (data) => {
|
|
622
625
|
if (entry.exitCode !== null) {
|
|
623
|
-
return Promise.
|
|
626
|
+
return Promise.reject(stdinHasNoReader(entry.pid));
|
|
624
627
|
}
|
|
625
628
|
if (entry.waitError)
|
|
626
629
|
return Promise.reject(entry.waitError);
|
|
@@ -1712,7 +1715,10 @@ export class NativeSidecarKernelProxy {
|
|
|
1712
1715
|
if (entry.waitError)
|
|
1713
1716
|
throw entry.waitError;
|
|
1714
1717
|
if (entry.exitCode !== null) {
|
|
1715
|
-
|
|
1718
|
+
if (entry.pendingStdin.length === 0)
|
|
1719
|
+
return;
|
|
1720
|
+
entry.pendingStdin.length = 0;
|
|
1721
|
+
throw stdinHasNoReader(entry.pid);
|
|
1716
1722
|
}
|
|
1717
1723
|
while (entry.pendingStdin.length > 0) {
|
|
1718
1724
|
const chunk = entry.pendingStdin.shift();
|
|
@@ -1725,9 +1731,9 @@ export class NativeSidecarKernelProxy {
|
|
|
1725
1731
|
.catch((error) => {
|
|
1726
1732
|
if (entry.exitCode !== null &&
|
|
1727
1733
|
(isNoSuchProcessError(error) || isUnknownVmError(error))) {
|
|
1728
|
-
|
|
1734
|
+
throw stdinHasNoReader(entry.pid);
|
|
1729
1735
|
}
|
|
1730
|
-
throw error;
|
|
1736
|
+
throw guestStdinError(error) ?? error;
|
|
1731
1737
|
})
|
|
1732
1738
|
.finally(() => {
|
|
1733
1739
|
entry.stdinFlushPromise = null;
|
|
@@ -1745,7 +1751,8 @@ export class NativeSidecarKernelProxy {
|
|
|
1745
1751
|
await entry.startPromise;
|
|
1746
1752
|
if (entry.waitError)
|
|
1747
1753
|
throw entry.waitError;
|
|
1748
|
-
|
|
1754
|
+
// Closing stdin succeeds after exit even though queued writes had no reader.
|
|
1755
|
+
await this.flushPendingStdin(entry).catch(ignoreBrokenPipe);
|
|
1749
1756
|
if (entry.exitCode !== null || !entry.pendingCloseStdin) {
|
|
1750
1757
|
return;
|
|
1751
1758
|
}
|
|
@@ -1758,10 +1765,14 @@ export class NativeSidecarKernelProxy {
|
|
|
1758
1765
|
(isNoSuchProcessError(error) || isUnknownVmError(error))) {
|
|
1759
1766
|
return;
|
|
1760
1767
|
}
|
|
1761
|
-
throw error;
|
|
1768
|
+
throw guestStdinError(error) ?? error;
|
|
1762
1769
|
}
|
|
1763
1770
|
}
|
|
1764
1771
|
handleBackgroundProcessError(entry, error) {
|
|
1772
|
+
// The writer already received the errno; a stdin write the guest
|
|
1773
|
+
// refused is not a process failure.
|
|
1774
|
+
if (isRefusedStdinWrite(error))
|
|
1775
|
+
return;
|
|
1765
1776
|
if (entry.exitCode !== null) {
|
|
1766
1777
|
// An I/O failure after exit must never rewrite the guest's real status.
|
|
1767
1778
|
if (!isNoSuchProcessError(error) && !isUnknownVmError(error)) {
|
|
@@ -2194,6 +2205,32 @@ function buildCommandMap(commandGuestPaths) {
|
|
|
2194
2205
|
}
|
|
2195
2206
|
return commands;
|
|
2196
2207
|
}
|
|
2208
|
+
/** Stdin written after its process exited, as a pipe write with no reader on Linux. */
|
|
2209
|
+
function stdinHasNoReader(pid) {
|
|
2210
|
+
return new KernelError("EPIPE", `process ${pid} has exited, so its stdin has no reader`);
|
|
2211
|
+
}
|
|
2212
|
+
/**
|
|
2213
|
+
* A stdin rejection that carries a guest errno, such as EBADF for a write
|
|
2214
|
+
* after closeStdin, as the KernelError the Rust client also returns.
|
|
2215
|
+
*/
|
|
2216
|
+
function guestStdinError(error) {
|
|
2217
|
+
if (!(error instanceof SidecarRejectedError) || !error.detail.errno)
|
|
2218
|
+
return null;
|
|
2219
|
+
return new KernelError(error.detail.errno, error.detail.message);
|
|
2220
|
+
}
|
|
2221
|
+
/** EPIPE (no reader) or EBADF (stdin closed): the guest refused the write. */
|
|
2222
|
+
function isRefusedStdinWrite(error) {
|
|
2223
|
+
return (error instanceof KernelError &&
|
|
2224
|
+
(error.code === "EPIPE" || error.code === "EBADF"));
|
|
2225
|
+
}
|
|
2226
|
+
function isBrokenPipe(error) {
|
|
2227
|
+
return error instanceof KernelError && error.code === "EPIPE";
|
|
2228
|
+
}
|
|
2229
|
+
function ignoreBrokenPipe(error) {
|
|
2230
|
+
if (isBrokenPipe(error))
|
|
2231
|
+
return;
|
|
2232
|
+
throw error;
|
|
2233
|
+
}
|
|
2197
2234
|
function isNoSuchProcessError(error) {
|
|
2198
2235
|
if (!(error instanceof Error)) {
|
|
2199
2236
|
return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivet-dev/agentos-core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@aws-sdk/client-s3": "^3.1019.0",
|
|
63
|
-
"@rivet-dev/agentos-runtime-sidecar": "0.4.
|
|
64
|
-
"@rivet-dev/agentos-runtime-core": "0.4.
|
|
63
|
+
"@rivet-dev/agentos-runtime-sidecar": "0.4.2",
|
|
64
|
+
"@rivet-dev/agentos-runtime-core": "0.4.2",
|
|
65
65
|
"@xterm/headless": "^6.0.0",
|
|
66
66
|
"better-sqlite3": "^12.8.0",
|
|
67
67
|
"croner": "^10.0.1",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"@bare-ts/lib": "^0.4.0",
|
|
76
|
-
"@rivet-dev/agentos-test-harness": "0.4.
|
|
76
|
+
"@rivet-dev/agentos-test-harness": "0.4.2",
|
|
77
77
|
"@browserbasehq/browse-cli": "0.5.0",
|
|
78
78
|
"@browserbasehq/cli": "0.5.4",
|
|
79
79
|
"@browserbasehq/sdk": "2.10.0",
|