diff --git a/.claude/skills/publish-registry/SKILL.md b/.claude/skills/publish-registry/SKILL.md index d7ad81e43e..0f930f130f 100644 --- a/.claude/skills/publish-registry/SKILL.md +++ b/.claude/skills/publish-registry/SKILL.md @@ -29,7 +29,7 @@ just registry-publish-all [tag] ## Rules -- Do not publish registry packages from secure-exec. +- Do not publish registry packages from agentos. - Do not move `latest` unless the user explicitly asks for a release. - Prefer AgentOS workspace builds while iterating; published pins are for consumers and release validation. diff --git a/.claude/skills/release-preview/SKILL.md b/.claude/skills/release-preview/SKILL.md index 64738cb814..1af13060c4 100644 --- a/.claude/skills/release-preview/SKILL.md +++ b/.claude/skills/release-preview/SKILL.md @@ -9,8 +9,8 @@ AgentOS previews are branch snapshots from this repository. The workflow builds debug artifacts and publishes npm packages under a sanitized branch dist-tag. No crates.io release, git tag, or GitHub release is created. -secure-exec is a generated mirror. Do not bump a secure-exec ref or cut a -secure-exec preview by hand. +agentos is a generated mirror. Do not bump a agentos ref or cut a +agentos preview by hand. ## Procedure @@ -32,6 +32,6 @@ npm install @rivet-dev/agentos-core@ ## Rules - Release-preview is for previews only; releases use the `release` skill. -- All code changes belong in AgentOS. The secure-exec mirror is regenerated +- All code changes belong in AgentOS. The agentos mirror is regenerated from AgentOS and follows the published AgentOS version. - On failure: `gh run view --log-failed`, fix, re-dispatch, re-watch. diff --git a/.claude/skills/release/SKILL.md b/.claude/skills/release/SKILL.md index 056ac1ab2a..f1291a38bc 100644 --- a/.claude/skills/release/SKILL.md +++ b/.claude/skills/release/SKILL.md @@ -10,8 +10,8 @@ The publish flow lives in `scripts/publish` and is driven by AgentOS is the source of truth. It publishes npm packages, crates, runtime sidecars, Pyodide/R2 assets, and `@agentos-software/*` registry packages from -this repository. secure-exec releases are generated compatibility shims that -follow the AgentOS version; never release secure-exec first. +this repository. agentos releases are generated compatibility shims that +follow the AgentOS version; never release agentos first. ## Procedure @@ -37,6 +37,6 @@ gh run watch -R rivet-dev/agentos "$run" --exit-status - `scripts/publish/src/local/cut-release.ts` is a pure trigger; version changes happen in the ephemeral CI checkout. - `workspace:*` deps are rewritten to literal versions by the publish bump pass. -- Generated secure-exec shims are dispatched after AgentOS publishes and must +- Generated agentos shims are dispatched after AgentOS publishes and must use the same version. - If anything fails, stop and report — do not retry automatically. diff --git a/.gitattributes b/.gitattributes index 6fae589b06..e575d5386f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,7 +2,7 @@ # # The Rust kernel is the substance of this repo; the rest is the TypeScript # client/protocol/registry plus a large test suite (the kernel itself lives in -# the secure-exec repo). We count Rust in full, plus the core client surface +# the agentos repo). We count Rust in full, plus the core client surface # (the AgentOS client entrypoint + its sidecar wire layer) and the core JS # binary-resolver shim, and exclude everything else (tests, demos, tooling, # generated bundles, the website, and the remaining client/registry code). diff --git a/.github/workflows/ci-nightly.yml b/.github/workflows/ci-nightly.yml index e0931f9eb2..e6f804f213 100644 --- a/.github/workflows/ci-nightly.yml +++ b/.github/workflows/ci-nightly.yml @@ -40,7 +40,6 @@ jobs: sudo apt-get install --yes cmake fi - run: pnpm install --frozen-lockfile - - run: node --test scripts/generate-secure-exec-mirror.test.mjs - run: make -C toolchain commands - run: make -C toolchain cmd/duckdb - run: make -C toolchain codex diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12fcd8be58..d1c026e0f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,6 @@ jobs: - run: node scripts/verify-fixed-versions.mjs - run: node --test scripts/check-layout.test.mjs - run: pnpm check-layout - - run: node --test scripts/generate-secure-exec-mirror.test.mjs - run: node --test scripts/check-rustfmt.test.mjs - run: node scripts/check-rustfmt.mjs - run: pnpm check-types @@ -82,7 +81,6 @@ jobs: --filter '@rivet-dev/agentos-build-tools' \ --filter '@rivet-dev/agentos-toolchain' \ --filter '@rivet-dev/agentos-runtime-sidecar' \ - --filter 'secure-exec' \ test - run: pnpm lint continue-on-error: true diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs new file mode 100644 index 0000000000..f587b62497 --- /dev/null +++ b/.pnpmfile.cjs @@ -0,0 +1,15 @@ +const PINNED_RIVETKIT_VERSION = "0.0.0-sqlite-uds.4e59a38"; + +module.exports = { + hooks: { + readPackage(pkg) { + if (pkg.name === "rivetkit" && pkg.version === PINNED_RIVETKIT_VERSION) { + // This preview bundles its ./agent-os implementation but still declares + // the retired external runtime. Keeping the declaration would restore the + // sunset package graph even though no bundled RivetKit module imports it. + delete pkg.dependencies?.["@rivet-dev/agent-os-core"]; + } + return pkg; + }, + }, +}; diff --git a/.secure-exec-local-path b/.secure-exec-local-path deleted file mode 100644 index 50a51e944b..0000000000 --- a/.secure-exec-local-path +++ /dev/null @@ -1,9 +0,0 @@ -# Local secure-exec checkout that carries the converged browser/wasm build. -# Agent OS depends on secure-exec; the web/wasm work links against this checkout -# via `just secure-exec-local` (which repoints crates to `path = "../secure-exec/..."` -# and npm to `link:`). The converged web architecture (the template for this work) -# currently lives on a branch, NOT yet on secure-exec main. - -SECURE_EXEC_CANONICAL=/home/nathan/secure-exec -SECURE_EXEC_CONVERGED_WEB_WORKSPACE=/home/nathan/secure-exec-convwasi -SECURE_EXEC_CONVERGED_WEB_BRANCH=browser-convergence-item-c diff --git a/CLAUDE.md b/CLAUDE.md index 7273a477f6..32c9245b88 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,8 +1,8 @@ # agentOS AgentOS owns the runtime, kernel, VFS, language execution, registry packages, -ACP/session layer, AgentOS client APIs, docs, and publish machinery. The -`secure-exec` repository is now a generated compatibility mirror only. +ACP/session layer, AgentOS client APIs, docs, and publish machinery. Agent OS +Exec is the JavaScript, TypeScript, and Python execution surface of AgentOS. ## Boundaries @@ -16,9 +16,8 @@ ACP/session layer, AgentOS client APIs, docs, and publish machinery. The or public API that already uses the word. - The protocol has no backward compatibility guarantee. Client, sidecar, and protocol crates ship in same-version lockstep; update both sides together. -- Generic runtime work belongs here, not in `../secure-exec`. Regenerate that - mirror with `node scripts/generate-secure-exec-mirror.mjs` after changing a - shimmed public surface. +- Generic runtime and language-execution work belongs here. Do not add a + compatibility mirror or a second package namespace for AgentOS language execution. - Keep root `package.json` scripts limited to Turbo orchestration; repo-specific commands belong in `justfile` recipes or scoped package scripts. - AgentOS targets native Linux/container execution. Browser support is not @@ -218,9 +217,10 @@ custom host-syscall imports. Treat that target as **native POSIX**; - `scripts/publish` is the source of truth for npm/crates discovery, version rewriting, npm publish, crates publish, release assets, and R2 upload. -- Publishable npm packages and Rust crates are AgentOS-owned. Compatibility - `@secure-exec/*`, `secure-exec`, and `secure-exec-*` artifacts are emitted - from the generated mirror. +- Publishable npm packages and Rust crates are AgentOS-owned. AgentOS language execution is + published through `@rivet-dev/agentos-javascript` and + `@rivet-dev/agentos-python`; `@rivet-dev/agentos` owns the actor API. Do not + publish compatibility artifacts or language subpaths from the actor package. - The release workflow must build and stage the native sidecar binaries, runtime-sidecar binaries, registry WASM commands, and pyodide assets before publish. diff --git a/Cargo.lock b/Cargo.lock index c8740a18e0..d0ea48db4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,6 +197,14 @@ dependencies = [ "md-5 0.10.6", "nix 0.29.0", "openssl", + "oxc-browserslist", + "oxc_allocator", + "oxc_ast", + "oxc_codegen", + "oxc_parser", + "oxc_semantic", + "oxc_span", + "oxc_transformer", "pbkdf2", "rusqlite", "rustix 1.1.4", @@ -1026,13 +1034,13 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex 1.3.0", "syn", ] @@ -1086,9 +1094,12 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.3" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +dependencies = [ + "allocator-api2", +] [[package]] name = "bytes" @@ -1106,6 +1117,15 @@ dependencies = [ "either", ] +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.2.66" @@ -1124,7 +1144,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -1248,6 +1268,20 @@ dependencies = [ "tokio", ] +[[package]] +name = "compact_str" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1310,6 +1344,12 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cow-utils" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1674,6 +1714,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.1.9" @@ -1702,6 +1748,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foldhash" version = "0.2.0" @@ -1972,6 +2024,16 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "foldhash 0.1.5", +] + [[package]] name = "hashbrown" version = "0.16.1" @@ -1980,7 +2042,7 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", ] [[package]] @@ -2487,6 +2549,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -2814,6 +2885,21 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "nonmax" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -2932,6 +3018,345 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" +[[package]] +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + +[[package]] +name = "oxc-browserslist" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5482acf27be53699af8214b9067b71117f34d74974db4b0feef1c09b556c274" +dependencies = [ + "nom 8.0.0", + "rustc-hash 2.1.3", + "serde", + "serde_json", + "thiserror", + "time", +] + +[[package]] +name = "oxc-miette" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4356a61f2ed4c9b3610245215fbf48970eb277126919f87db9d0efa93a74245c" +dependencies = [ + "cfg-if", + "owo-colors", + "oxc-miette-derive", + "textwrap", + "thiserror", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "oxc-miette-derive" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b237422b014f8f8fff75bb9379e697d13f8d57551a22c88bebb39f073c1bf696" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "oxc_allocator" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5dc7d7719a4f90c691fbd6bcf8b623df2832ccc6b303c1d07d85aeb476c5b8e" +dependencies = [ + "allocator-api2", + "bumpalo", + "hashbrown 0.15.5", + "oxc_data_structures", + "rustc-hash 2.1.3", +] + +[[package]] +name = "oxc_ast" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c1308e677a69e31e51537f5b3267aae44a67cd61a2f3a740f815839c89ea97" +dependencies = [ + "bitflags", + "oxc_allocator", + "oxc_ast_macros", + "oxc_data_structures", + "oxc_estree", + "oxc_regular_expression", + "oxc_span", + "oxc_syntax", +] + +[[package]] +name = "oxc_ast_macros" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e85f4a6422af514f59d0d5aab918237b799ca25164bd59e11b59ea61991777ae" +dependencies = [ + "phf", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "oxc_ast_visit" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a8f7472e608b7410cc6ce5b0abb9cac2529a197374e5310f9de567d8853a5d" +dependencies = [ + "oxc_allocator", + "oxc_ast", + "oxc_span", + "oxc_syntax", +] + +[[package]] +name = "oxc_cfg" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd0c7687f260ceee84da03ccd857f3144a8603b421f189d78836068e5dd2785" +dependencies = [ + "bitflags", + "itertools 0.14.0", + "nonmax", + "oxc_index", + "oxc_syntax", + "petgraph", + "rustc-hash 2.1.3", +] + +[[package]] +name = "oxc_codegen" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb7f6be284d2073471ae0123f32e4092ce1063370f0ef2889b5a9c3d16e9e17" +dependencies = [ + "bitflags", + "cow-utils", + "nonmax", + "oxc_allocator", + "oxc_ast", + "oxc_data_structures", + "oxc_index", + "oxc_semantic", + "oxc_sourcemap", + "oxc_span", + "oxc_syntax", + "rustc-hash 2.1.3", + "ryu-js", +] + +[[package]] +name = "oxc_data_structures" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d713c1b57fe1f55af1d557efd461025c9c9bd28835a6b3e0e91f46cdeb995a6" +dependencies = [ + "ropey", + "rustversion", +] + +[[package]] +name = "oxc_diagnostics" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c6188d0a1aa83656795c29b7e7f036060f5c3e5c234ebebc2a5899fb43a579" +dependencies = [ + "cow-utils", + "oxc-miette", + "percent-encoding", +] + +[[package]] +name = "oxc_ecmascript" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "851355a2d035526d3a3525cbd66224bde1e234d7cf339835a4516bf27732dcec" +dependencies = [ + "num-bigint", + "num-traits", + "oxc_ast", + "oxc_span", + "oxc_syntax", +] + +[[package]] +name = "oxc_estree" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67d74c11e1c8a741c9321c86d2f0b30de107e1cc89d5912a6c5b9771b7e56cd" + +[[package]] +name = "oxc_index" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "967ae797e1f284bd1385f2d8e8ab94293ad27f623c76839ecf66827521365f5b" + +[[package]] +name = "oxc_parser" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bbd1f8184ae33834222f9620673c40296b4ba9c4951c54bcc5548bb7a1f2621" +dependencies = [ + "bitflags", + "cow-utils", + "memchr", + "num-bigint", + "num-traits", + "oxc_allocator", + "oxc_ast", + "oxc_data_structures", + "oxc_diagnostics", + "oxc_ecmascript", + "oxc_regular_expression", + "oxc_span", + "oxc_syntax", + "rustc-hash 2.1.3", + "seq-macro", +] + +[[package]] +name = "oxc_regular_expression" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54d16a7346afe27716433d691343ee137d640f94f978bd3244babf7248ed6453" +dependencies = [ + "bitflags", + "oxc_allocator", + "oxc_ast_macros", + "oxc_diagnostics", + "oxc_span", + "phf", + "rustc-hash 2.1.3", + "unicode-id-start", +] + +[[package]] +name = "oxc_semantic" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adb3c19e857e5338522ece075450227cea3de0323ec679789899c9b3cf7be6c" +dependencies = [ + "itertools 0.14.0", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_cfg", + "oxc_data_structures", + "oxc_diagnostics", + "oxc_ecmascript", + "oxc_index", + "oxc_span", + "oxc_syntax", + "phf", + "rustc-hash 2.1.3", + "self_cell", +] + +[[package]] +name = "oxc_sourcemap" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24015d93ed1d8f0c2a0d9f534ca85690888990658a8fc4a87ff0c92640e73300" +dependencies = [ + "base64-simd", + "cfg-if", + "cow-utils", + "rustc-hash 2.1.3", + "serde", + "serde_json", +] + +[[package]] +name = "oxc_span" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93b7cf8b6447a4d0bb9aff91c6c8fcccbae3d28bad9f9ccb1128599761a982b6" +dependencies = [ + "compact_str", + "oxc-miette", + "oxc_allocator", + "oxc_ast_macros", + "oxc_estree", +] + +[[package]] +name = "oxc_syntax" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b6ac136f155820331b326d5cbd178a9c2ee032787f04aa6e14b494c8aeb227" +dependencies = [ + "bitflags", + "cow-utils", + "nonmax", + "oxc_allocator", + "oxc_ast_macros", + "oxc_data_structures", + "oxc_estree", + "oxc_index", + "oxc_span", + "phf", + "rustc-hash 2.1.3", + "ryu-js", + "unicode-id-start", +] + +[[package]] +name = "oxc_transformer" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf60b4314988dd121184340c0d9958a33703f9a01582baf37b9afc2dd2a4e4c" +dependencies = [ + "base64 0.22.1", + "compact_str", + "cow-utils", + "indexmap 2.14.0", + "itoa", + "memchr", + "oxc-browserslist", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_data_structures", + "oxc_diagnostics", + "oxc_ecmascript", + "oxc_parser", + "oxc_regular_expression", + "oxc_semantic", + "oxc_span", + "oxc_syntax", + "oxc_traverse", + "rustc-hash 2.1.3", + "serde", + "serde_json", + "sha1 0.10.6", +] + +[[package]] +name = "oxc_traverse" +version = "0.75.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b915b0d7d967c5769e35f2259b29f1e8861f0bb38920b8209b624455c464005b" +dependencies = [ + "itoa", + "oxc_allocator", + "oxc_ast", + "oxc_ast_visit", + "oxc_data_structures", + "oxc_ecmascript", + "oxc_semantic", + "oxc_span", + "oxc_syntax", + "rustc-hash 2.1.3", +] + [[package]] name = "p256" version = "0.13.2" @@ -3066,6 +3491,61 @@ dependencies = [ "pest", ] +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "serde", +] + +[[package]] +name = "phf" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_generator" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cbb1126afed61dd6368748dae63b1ee7dc480191c6262a3b4ff1e29d86a6c5b" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d713258393a82f091ead52047ca779d37e5766226d009de21696c4e667044368" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -3343,6 +3823,16 @@ dependencies = [ "syn", ] +[[package]] +name = "ropey" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93411e420bcd1a75ddd1dc3caf18c23155eda2c090631a85af21ba19e97093b5" +dependencies = [ + "smallvec", + "str_indices", +] + [[package]] name = "rusqlite" version = "0.32.1" @@ -3363,6 +3853,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -3490,6 +3986,12 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "ryu-js" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04d056b875a9d2e6cb9a61d127afee9ac5999b9f87bcb32079d1318e505be714" + [[package]] name = "salsa20" version = "0.10.2" @@ -3634,12 +4136,24 @@ dependencies = [ "libc", ] +[[package]] +name = "self_cell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab42ca02749e120097e328d91d415325bdf43b1c72c4c8badf37375fe40a813" + [[package]] name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + [[package]] name = "serde" version = "1.0.228" @@ -3865,6 +4379,12 @@ dependencies = [ "time", ] +[[package]] +name = "siphasher" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" + [[package]] name = "slab" version = "0.4.12" @@ -3877,6 +4397,12 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +[[package]] +name = "smawk" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e2fb0f499abb4d162f2bedad68f5ef91a1682b5a03596ddb67efd37768d100" + [[package]] name = "socket2" version = "0.5.10" @@ -3934,6 +4460,18 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "str_indices" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08889ec5408683408db66ad89e0e1f93dff55c73a4ccc71c427d5b277ee47e6" + [[package]] name = "strsim" version = "0.11.1" @@ -4055,6 +4593,17 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" version = "2.0.18" @@ -4350,12 +4899,24 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +[[package]] +name = "unicode-id-start" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-segmentation" version = "1.13.3" @@ -4571,9 +5132,9 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.252.0" +version = "0.248.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8185ae345fa5687c054626ff9a50e7089797a343d9904d1dc9820eb4c4d3196f" +checksum = "ac92cf547bc18d27ecc521015c08c353b4f18b84ab388bb6d1b6b682c620d9b6" dependencies = [ "leb128fmt", "wasmparser", @@ -4581,9 +5142,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.252.0" +version = "0.248.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3eb099dcadcde5be9eef55e3a337128efd4e44b4c93122487e4d2e4e1c6627c" +checksum = "aa4439c5eee9df71ee0c6efb37f63b1fcb1fec38f85f5142c54e7ed05d33091a" dependencies = [ "bitflags", "indexmap 2.14.0", @@ -4592,9 +5153,9 @@ dependencies = [ [[package]] name = "wast" -version = "252.0.0" +version = "248.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942a3449d6a593fccc111a6241c8df52bda168af30e40bf9580d4394d7374c65" +checksum = "acc54622ed5a5cddafcdf152043f9d4aed54d4a653d686b7dfe874809fca99d7" dependencies = [ "bumpalo", "leb128fmt", @@ -4605,9 +5166,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.252.0" +version = "1.248.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c72a4ba7088f7bac94cf516e49882bdf97068904a563768cf249efc839ec42cb" +checksum = "d75cd9e510603909748e6ebab89f27cd04472c1d9d85a3c88a7a6fc51a1a7934" dependencies = [ "wast", ] diff --git a/TODO.md b/TODO.md index 048046cd7a..7ff5f3c317 100644 --- a/TODO.md +++ b/TODO.md @@ -78,7 +78,7 @@ fixtures and benchmarks that exercise host VFS callbacks. Disabled browser sources remain dormant reference code, not a supported production VFS. - [x] Remove the core in-memory VFS and overlay/layer-store implementations. -- [x] Remove their root and secure-exec compatibility exports. +- [x] Remove their root and agentos compatibility exports. - [x] Require a caller-owned filesystem in the low-level compatibility runtime. - [x] Move remaining repository fixtures to the explicit test-only surface. - [x] Remove obsolete duplicate semantic tests. diff --git a/biome.json b/biome.json index dfd8ce5d8c..af860c6ab1 100644 --- a/biome.json +++ b/biome.json @@ -8,7 +8,7 @@ "!packages/runtime-browser", "!packages/playground", "!packages/core/src/sidecar/generated-protocol.ts", - "!_secure-exec-sibling", + "!_agentos-sibling", "!/**/node_modules" ], "ignoreUnknown": true diff --git a/crates/CLAUDE.md b/crates/CLAUDE.md index fb92d0c360..b56394f676 100644 --- a/crates/CLAUDE.md +++ b/crates/CLAUDE.md @@ -5,7 +5,7 @@ The Rust sidecar implements the kernel: virtual filesystem, process table, socke The kernel orchestrates three execution environments: - **WASM processes** -- POSIX utilities (coreutils, sh, grep, etc.) compiled to WebAssembly, running within the sidecar's managed runtime. -- **Node.js (V8 isolates)** -- JS/TS executes inside isolated V8 contexts managed by the sidecar's execution engine. All Node.js builtin modules (`fs`, `net`, `child_process`, `dns`, `http`, `os`, etc.) are kernel-backed polyfills that route through the kernel VFS, socket table, and process table via synchronous RPC. Module loading is intercepted so guest code never touches real host APIs. **⚠️ CURRENTLY BROKEN**: The execution engine currently spawns real host `node` child processes instead of V8 isolates, and most builtins fall through to real host modules. This is being actively fixed. The complete working polyfill code from the original `@secure-exec` packages has been recovered to `~/.agents/recovery/secure-exec/` (source repo: `/home/nathan/secure-exec-1/`). See `crates/execution/CLAUDE.md` for the gap table and recovery file list. +- **Node.js (V8 isolates)** -- JS/TS executes inside isolated V8 contexts managed by the sidecar's execution engine. All Node.js builtin modules (`fs`, `net`, `child_process`, `dns`, `http`, `os`, etc.) are kernel-backed polyfills that route through the kernel VFS, socket table, and process table via synchronous RPC. Module loading is intercepted so guest code never touches real host APIs. **⚠️ CURRENTLY BROKEN**: The execution engine currently spawns real host `node` child processes instead of V8 isolates, and most builtins fall through to real host modules. This is being actively fixed. The complete working polyfill code from the original `@agentos` packages has been recovered to `~/.agents/recovery/agentos/` (source repo: `/home/nathan/agentos-1/`). See `crates/execution/CLAUDE.md` for the gap table and recovery file list. - **Python (Pyodide)** -- CPython compiled to WASM via Pyodide, with kernel-backed file/network I/O. **ALL guest code MUST execute inside the kernel with ZERO host escapes.** No runtime may spawn unsandboxed host processes, touch real host filesystems, open real network sockets, or call real Node.js builtins. Every syscall goes through the kernel. This is the single most important architectural invariant. Any path where guest code reaches the real host is a critical security violation. @@ -19,7 +19,7 @@ These are hard rules with no exceptions: 1. **Every guest syscall goes through the kernel.** File reads go through the kernel VFS, not real `node:fs`. Network connections go through the kernel socket table, not real `node:net`. Process spawning go through the kernel process table, not real `node:child_process`. DNS resolution goes through the kernel's DNS resolver, not real `node:dns`. There are no shortcuts where guest code touches host resources directly. 2. **No real host builtins.** When a guest does `require('fs')` or `import net from 'node:net'`, the module loader must return a kernel-backed polyfill. If no polyfill exists yet, the builtin must be denied (`ERR_ACCESS_DENIED`). The loader must never fall through to Node.js's default resolution and hand the guest the real host module. 3. **The host is an implementation detail.** Guest code should not be able to observe that it is running on a host Node.js process. `process.pid` should be the kernel PID, `os.hostname()` should be the kernel hostname, `fs.readdirSync('/')` should show the kernel VFS root. `process.cwd()` should return the kernel CWD, not a host path. `process.env` must not contain internal `AGENT_OS_*` control variables. Error messages and stack traces must not reveal host filesystem paths. `require.resolve()` must return guest-visible paths, not host paths. Any host state leaking through to the guest is a bug. -4. **Polyfills are ports, not wrappers.** A path-translating shim over real `node:fs` is not a polyfill -- it is a wrapper around a host API. A real polyfill implements the API semantics using only kernel primitives (VFS, socket table, process table, pipe manager). The original JS kernel (`@secure-exec/core` + `@secure-exec/nodejs`, deleted in commit `5a43882`) had full kernel-backed polyfills for `fs`, `net`, `http`, `dns`, `dgram`, `child_process`, and `os`. The Rust sidecar must reach the same level of isolation. +4. **Polyfills are ports, not wrappers.** A path-translating shim over real `node:fs` is not a polyfill -- it is a wrapper around a host API. A real polyfill implements the API semantics using only kernel primitives (VFS, socket table, process table, pipe manager). The original JavaScript kernel packages, deleted in commit `5a43882`, had full kernel-backed polyfills for `fs`, `net`, `http`, `dns`, `dgram`, `child_process`, and `os`. The Rust sidecar must reach the same level of isolation. 5. **Control channels must be out-of-band.** The sidecar must not use in-band magic prefixes on stdout/stderr for control signaling (exit codes, metrics, signal registration). Guest code can write these prefixes to inject fake control messages. Use dedicated file descriptors, separate pipes, or a side-channel protocol for all sidecar-internal communication. 6. **Resource consumption must be bounded.** Every guest-allocatable resource must have a configurable limit enforced by the kernel: filesystem total size, inode count, process count, open FDs, pipes, PTYs, sockets, connections. Unbounded allocation from guest input is a DoS vector. The kernel's `ResourceLimits` must cover all resource types, not just processes and FDs. Sidecar metadata parsing should start from `ResourceLimits::default()` and only override keys that are actually present; rebuilding the struct from sparse metadata drops default filesystem byte/inode caps. @@ -61,8 +61,8 @@ These are hard rules with no exceptions: - **`sandbox_agent` `pread` should prefer HTTP `Range` on `/v1/fs/file`, but older remotes may ignore it and return `200 OK`.** Keep the compatibility path that warns and slices the full response body instead of failing, because the sidecar still has to interoperate with pre-range sandbox-agent servers. - **Native sidecar security/audit telemetry should use structured bridge events, not ad hoc strings.** In `crates/sidecar/src/service.rs`, emit security-relevant records with `bridge.emit_structured_event(...)` and include a `timestamp` field plus stable keys such as `policy`, `path`, `source_pid`, `target_pid`, or `reason` so tests and downstream aggregation can assert on them directly. - **Native mount plugins live under `crates/sidecar/src/plugins/` and register through `plugins/mod.rs`.** Keep `host_dir`, `s3`, `google_drive`, and `sandbox_agent` there with shared registration glue, while `bridge.rs` only layers on sidecar-specific in-memory and JS-bridge plugin registration. -- **The sidecar execution driver's shell-visible builtin commands must mirror the compat runtime surface.** Seed `node` and `wasm` during `create_vm()` and preserve them when refreshing `/__secure_exec/commands/*` in `configure_vm()`, but do not materialize extra `/bin/*` runtime stubs such as `python` unless a lower snapshot or installed software explicitly provides them. Direct `ExecuteRequest { runtime: ... }` dispatch still covers runtimes that are not meant to appear in the guest filesystem. -- **Mounted WASM command directories need both command-map refresh and guest `PATH` refresh.** When `crates/sidecar/src/vm.rs` rediscovers `/__secure_exec/commands/*`, update `vm.command_guest_paths` and prepend those parent directories into `vm.guest_env["PATH"]`; `crates/sidecar/src/execution.rs` child-process resolution should search `PATH` entries before falling back to `/bin`, `/usr/bin`, and `/usr/local/bin`, or guest `child_process.spawn("sh")`/`spawn("grep")` misses mounted registry commands. +- **The sidecar execution driver's shell-visible builtin commands must mirror the compat runtime surface.** Seed `node` and `wasm` during `create_vm()` and preserve them when refreshing `/__agentos/commands/*` in `configure_vm()`, but do not materialize extra `/bin/*` runtime stubs such as `python` unless a lower snapshot or installed software explicitly provides them. Direct `ExecuteRequest { runtime: ... }` dispatch still covers runtimes that are not meant to appear in the guest filesystem. +- **Mounted WASM command directories need both command-map refresh and guest `PATH` refresh.** When `crates/sidecar/src/vm.rs` rediscovers `/__agentos/commands/*`, update `vm.command_guest_paths` and prepend those parent directories into `vm.guest_env["PATH"]`; `crates/sidecar/src/execution.rs` child-process resolution should search `PATH` entries before falling back to `/bin`, `/usr/bin`, and `/usr/local/bin`, or guest `child_process.spawn("sh")`/`spawn("grep")` misses mounted registry commands. - **Native-sidecar command resolution must use the caller's effective `PATH`, not just `vm.guest_env`.** In `crates/sidecar/src/execution.rs`, path-like guest candidates emitted by shells (for example `/home/agentos/.pi/agent/bin/printf`) should only be treated as executables when the candidate or mapped host file actually exists; if the parent directory came from `PATH` but the file is missing, fall back to the basename so registry command remapping can still find `printf`/`bash`/`which`. - **Native-sidecar WASM commands see the shadow root, so standard guest directories must be seeded there during VM creation.** In `crates/sidecar/src/vm.rs`, keep `/tmp`, `/var/tmp`, `/bin`, `/usr`, and the rest of the POSIX bootstrap tree materialized in the shadow root before any WASM command runs, or shell redirection and absolute-path checks will disagree with the kernel VFS (`vm.stat("/tmp")` works while `sh -c 'echo hi > /tmp/x'` fails). - **Host filesystem API writes that should be visible to WASM commands must mirror into the shadow root immediately.** In `crates/sidecar/src/filesystem.rs`, `GuestFilesystemOperation::WriteFile` needs to update both the kernel VFS and the VM shadow tree right away, or `vm.writeFile("/tmp/x")` will succeed while guest `sh`/`cat`/`ls` still miss the file until some later sync path runs. diff --git a/crates/agentos-protocol/protocol/agent_os_acp_v1.bare b/crates/agentos-protocol/protocol/agent_os_acp_v1.bare index 4cc34059c9..f6ca0c6483 100644 --- a/crates/agentos-protocol/protocol/agent_os_acp_v1.bare +++ b/crates/agentos-protocol/protocol/agent_os_acp_v1.bare @@ -1,5 +1,5 @@ # Agent OS ACP extension protocol schema, version 1. -# This schema is intentionally standalone. It imports no secure-exec schema. +# This schema is intentionally standalone. It imports no agentos schema. type JsonUtf8 str @@ -181,12 +181,14 @@ type AcpCloseSessionRequest struct { # Resume a session that exists in durable storage but is not live in the current # VM (e.g. after a Rivet actor slept and woke with a fresh VM). The sidecar runs # the stateless resume state machine (native session/load when the agent supports -# it, else a fresh session/new + transcript continuation preamble). `cwd`/`env` -# describe the fresh adapter launch used by the fallback tier. `transcriptPath`, -# when present, is a guest-readable path the fallback preamble points the agent at. +# it, else a fresh session/new + transcript continuation preamble). `runtime`, +# `cwd`, and `env` describe the fresh adapter launch used by the fallback tier. +# `transcriptPath`, when present, is a guest-readable path the fallback preamble +# points the agent at. type AcpResumeSessionRequest struct { sessionId: str agentType: str + runtime: AcpRuntimeKind transcriptPath: optional cwd: str additionalDirectories: list diff --git a/crates/agentos-sidecar-browser/src/wasm.rs b/crates/agentos-sidecar-browser/src/wasm.rs index 3780937455..cc078fe557 100644 --- a/crates/agentos-sidecar-browser/src/wasm.rs +++ b/crates/agentos-sidecar-browser/src/wasm.rs @@ -1,10 +1,10 @@ //! wasm-bindgen entry point for the Agent OS browser sidecar. //! -//! Mirrors secure-exec's `BrowserSidecarWasm` (pushFrame/pollEvent over the shared +//! Mirrors agentos's `BrowserSidecarWasm` (pushFrame/pollEvent over the shared //! `BrowserWireDispatcher` + `BrowserJsBridge`) but registers the Agent OS ACP //! `BrowserExtension` into the dispatcher's sidecar, so guest ACP/session traffic //! is handled by the Agent OS wrapper while every kernel syscall still routes -//! through the converged secure-exec wasm kernel (the sole enforcement point). +//! through the converged agentos wasm kernel (the sole enforcement point). use agentos_native_sidecar_browser::wire_dispatch::{BrowserWireDispatcher, BROWSER_SIDECAR_ID}; use agentos_native_sidecar_browser::BrowserJsBridge; diff --git a/crates/agentos-sidecar-core/src/engine.rs b/crates/agentos-sidecar-core/src/engine.rs index 3d6f980f1a..bcf0d3e3eb 100644 --- a/crates/agentos-sidecar-core/src/engine.rs +++ b/crates/agentos-sidecar-core/src/engine.rs @@ -15,7 +15,7 @@ use std::collections::BTreeMap; use agentos_protocol::generated::v1::{ AcpCloseSessionRequest, AcpCreateSessionRequest, AcpDeliverAgentOutputRequest, AcpGetSessionStateRequest, AcpPendingResponse, AcpRequest, AcpResponse, - AcpResumeSessionRequest, AcpRuntimeKind, AcpSessionClosedResponse, AcpSessionRequest, + AcpResumeSessionRequest, AcpSessionClosedResponse, AcpSessionRequest, AcpSessionResumedResponse, AcpSessionRpcResponse, }; use serde_json::{json, Map, Value}; @@ -63,13 +63,14 @@ struct AgentPackageManifest { struct AgentPackageAgentBlock { #[serde(rename = "acpEntrypoint", default)] acp_entrypoint: String, + #[serde(default)] env: BTreeMap, #[serde(rename = "launchArgs", default)] launch_args: Vec, } /// Resolve an agent name to its launch parameters by reading the projected -/// manifest at `/opt/agentos//current/agentos-package.json` over the host +/// manifest at `/opt/agentos/pkgs//current/agentos-package.json` over the host /// filesystem seam. A missing file, a missing `agent` block, or an empty /// `agent.acpEntrypoint` all map to a single typed "unknown agent" error. Mirrors /// the native sidecar `resolve_agent`. @@ -1782,7 +1783,7 @@ mod tests { #[test] fn resume_falls_back_to_session_new_when_no_native_capability() { - use agentos_protocol::generated::v1::AcpResumeSessionRequest; + use agentos_protocol::generated::v1::{AcpResumeSessionRequest, AcpRuntimeKind}; use serde_json::Value; use std::collections::{HashMap, VecDeque}; @@ -1852,6 +1853,7 @@ mod tests { let request = AcpResumeSessionRequest { session_id: "old-session".into(), agent_type: "echo".into(), + runtime: AcpRuntimeKind::JavaScript, transcript_path: Some("/transcripts/old.jsonl".into()), cwd: "/workspace".into(), additional_directories: Vec::new(), diff --git a/crates/agentos-sidecar-core/src/lib.rs b/crates/agentos-sidecar-core/src/lib.rs index 85b7547bf8..25034f58b5 100644 --- a/crates/agentos-sidecar-core/src/lib.rs +++ b/crates/agentos-sidecar-core/src/lib.rs @@ -3,7 +3,7 @@ //! Host-free core for the Agent OS ACP sidecar extension. //! //! This crate holds the parts of the ACP extension that do NOT depend on the host -//! runtime (tokio, std::fs, the native secure-exec sidecar): the request/response +//! runtime (tokio, std::fs, the native agentos sidecar): the request/response //! wire codec and the per-session data model. It compiles to wasm32 so the browser //! sidecar (`agentos-sidecar-browser`) can run the same ACP logic the native sidecar //! (`agentos-sidecar`) runs, with each backend supplying the host operations diff --git a/crates/agentos-sidecar/CLAUDE.md b/crates/agentos-sidecar/CLAUDE.md index 894ac4580a..4b19f04fe7 100644 --- a/crates/agentos-sidecar/CLAUDE.md +++ b/crates/agentos-sidecar/CLAUDE.md @@ -2,6 +2,6 @@ - Author ACP behavior as an `Ext` extension over `agentos-protocol`; do not add new top-level sidecar request/response variants for agent-session RPCs. - Keep `agentos-protocol` as the only ACP payload schema source; extension requests, responses, events, and callbacks must use the generated BARE types. -- Keep generic secure-exec sidecar code agent-agnostic; ACP namespace handling belongs in this wrapper extension, not in secure-exec transport or kernel layers. +- Keep generic agentos sidecar code agent-agnostic; ACP namespace handling belongs in this wrapper extension, not in agentos transport or kernel layers. - Extension guest work must still run through the kernel boundary via `ExtensionContext`; never spawn host-native agent adapters or touch host files directly from extension logic. - Emit live session notifications as generated `AcpEvent` payloads in `EventPayload::Ext`; do not add event cursor replay to snapshot state. diff --git a/crates/agentos-sidecar/src/acp/mod.rs b/crates/agentos-sidecar/src/acp/mod.rs index 835a923210..ed30ebe3e5 100644 --- a/crates/agentos-sidecar/src/acp/mod.rs +++ b/crates/agentos-sidecar/src/acp/mod.rs @@ -61,7 +61,7 @@ const ACP_INACTIVITY_WARNING_INTERVAL: Duration = Duration::from_secs(30); const PROMPT_RESPONSE_DRAIN_QUIET: Duration = Duration::from_millis(50); // While an ACP request is in flight the stdio loop is inside the extension // dispatch, so this wait loop becomes the cooperative VM I/O pump. Keep it at -// the same cadence as secure-exec's outer event pump so adapter fetches and +// the same cadence as agentos's outer event pump so adapter fetches and // process output keep moving mid-turn. const ACP_CANCEL_METHOD: &str = "session/cancel"; const ACP_TRACE_PATH_ENV: &str = "AGENT_OS_ACP_TRACE_PATH"; @@ -85,7 +85,7 @@ const AGENTOS_SYSTEM_PROMPT: &str = include_str!("../AGENTOS_SYSTEM_PROMPT.md"); /// evict the now-dead session record instead of leaking it until an explicit /// internal runtime cleanup that may never run. const ADAPTER_EXITED_ERROR_MARKER: &str = "exited with code"; -/// Substring of the secure-exec process-table error returned when an operation +/// Substring of the agentos process-table error returned when an operation /// targets a process that already exited ("VM has no active process "). /// Writing a request to an adapter that crashed while *idle* surfaces this way /// (the exit is observed lazily, on the next stdin write), so it is classified @@ -1424,7 +1424,7 @@ mod tests { assert_eq!(adapter_exit_code_from_error(&exited), Some(7)); // Lazy observation: a request write to an already-reaped adapter fails - // with secure-exec's process-table error (the exact production shape: + // with agentos's process-table error (the exact production shape: // "VM vm-5 has no active process agent-6"). No exit code is observed. let gone = SidecarError::InvalidState(String::from("VM vm-5 has no active process agent-6")); diff --git a/crates/agentos-sidecar/src/acp/runtime.rs b/crates/agentos-sidecar/src/acp/runtime.rs index 34e8d60238..cc2d597b68 100644 --- a/crates/agentos-sidecar/src/acp/runtime.rs +++ b/crates/agentos-sidecar/src/acp/runtime.rs @@ -1229,6 +1229,8 @@ pub(super) async fn send_json_rpc_request( } EventPayload::ProcessOutputEvent(_) | EventPayload::ProcessExitedEvent(_) + | EventPayload::ExecutionOutputEvent(_) + | EventPayload::ExecutionCompletedEvent(_) | EventPayload::VmLifecycleEvent(_) | EventPayload::StructuredEvent(_) | EventPayload::ExtEnvelope(_) => {} @@ -1576,7 +1578,7 @@ pub(super) async fn resolve_agent( } /// Extract the owning connection id from an ownership scope. Every scope carries -/// a connection id, which is the tenant boundary secure-exec enforces; ACP +/// a connection id, which is the tenant boundary AgentOS enforces; ACP /// session ownership is keyed off this same connection id. /// Remove every session in `sessions` owned by `connection_id`, returning the /// adapter process ids of the dropped records. Split out from @@ -1624,7 +1626,7 @@ pub(super) fn is_adapter_exited_error(error: &SidecarError) -> bool { } /// True when `error` means the adapter process is gone: either the in-pump exit -/// observation (`is_adapter_exited_error`) or a secure-exec process-table +/// observation (`is_adapter_exited_error`) or an AgentOS process-table /// lookup failure from operating on an adapter that already exited — the lazy /// observation of an idle-time crash (`ADAPTER_NO_ACTIVE_PROCESS_MARKER`). pub(super) fn is_adapter_gone_error(error: &SidecarError) -> bool { diff --git a/crates/bridge/Cargo.toml b/crates/bridge/Cargo.toml index cddd3c08d1..2a4b4c3e90 100644 --- a/crates/bridge/Cargo.toml +++ b/crates/bridge/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Shared bridge contracts between the secure-exec kernel and execution planes" +description = "Shared bridge contracts between the agentos kernel and execution planes" [dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/crates/bridge/src/lib.rs b/crates/bridge/src/lib.rs index b7d9298b88..06ba41c19b 100644 --- a/crates/bridge/src/lib.rs +++ b/crates/bridge/src/lib.rs @@ -1,6 +1,6 @@ #![forbid(unsafe_code)] -//! Shared bridge contracts between the secure-exec kernel and execution planes. +//! Shared bridge contracts between the agentos kernel and execution planes. pub mod queue_tracker; diff --git a/crates/bridge/src/queue_tracker.rs b/crates/bridge/src/queue_tracker.rs index 06ef0ca1f6..7ef9130f9e 100644 --- a/crates/bridge/src/queue_tracker.rs +++ b/crates/bridge/src/queue_tracker.rs @@ -1,6 +1,6 @@ //! Centralized bounded-queue usage tracker. //! -//! secure-exec streams guest output through a *chain* of bounded queues: the +//! agentos streams guest output through a *chain* of bounded queues: the //! V8 -> host event channel, the sidecar stdout/stdin frame queues, and so on. //! Each queue applies backpressure when full (it parks the producer until the //! consumer drains) rather than crashing, but backpressure is invisible: a slow @@ -403,7 +403,7 @@ pub struct QueueRegistry { } impl QueueRegistry { - /// The shared registry. All `secure-exec` bounded queues register here so + /// The shared registry. All `agentos` bounded queues register here so /// their usage can be inspected from one place. pub fn global() -> &'static QueueRegistry { static REGISTRY: OnceLock = OnceLock::new(); diff --git a/crates/build-support/Cargo.toml b/crates/build-support/Cargo.toml index d9bed0e4d2..abfd01b416 100644 --- a/crates/build-support/Cargo.toml +++ b/crates/build-support/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Build script helpers for secure-exec crates" +description = "Build script helpers for agentos crates" [lib] path = "v8_bridge_build.rs" diff --git a/crates/build-support/v8_bridge_build.rs b/crates/build-support/v8_bridge_build.rs index fc40414f64..c9d64475fb 100644 --- a/crates/build-support/v8_bridge_build.rs +++ b/crates/build-support/v8_bridge_build.rs @@ -301,7 +301,7 @@ mod tests { fn temp_test_dir(name: &str) -> io::Result { let mut path = std::env::temp_dir(); path.push(format!( - "secure-exec-v8-bridge-build-{name}-{}", + "agentos-v8-bridge-build-{name}-{}", std::process::id() )); let _ = fs::remove_dir_all(&path); diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 2f7d5499d6..77cb647d80 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -7,7 +7,7 @@ repository.workspace = true description = "High-level Rust client SDK for the Agent OS native sidecar (1:1 port of the TypeScript AgentOs client)" [dependencies] -# Reuse the secure-exec BARE wire schema + IPC transport. No new wire types are defined here. +# Reuse the agentos BARE wire schema + IPC transport. No new wire types are defined here. agent-client-protocol-schema = { workspace = true } agentos-sidecar-client = { workspace = true } agentos-vm-config = { workspace = true } diff --git a/crates/client/src/agent_os.rs b/crates/client/src/agent_os.rs index 325f52c27d..d3b6df02f0 100644 --- a/crates/client/src/agent_os.rs +++ b/crates/client/src/agent_os.rs @@ -289,7 +289,16 @@ impl AgentOs { | wire::ResponsePayload::ResourceSnapshotResponse(_) | wire::ResponsePayload::PackageLinkedResponse(_) | wire::ResponsePayload::ProvidedCommandsResponse(_) - | wire::ResponsePayload::ListMountsResponse(_) => { + | wire::ResponsePayload::ListMountsResponse(_) + | wire::ResponsePayload::ExecutionAcceptedResponse(_) + | wire::ResponsePayload::ExecutionCompletedResponse(_) + | wire::ResponsePayload::ExecutionEvaluationResponse(_) + | wire::ResponsePayload::TypeScriptCheckResponse(_) + | wire::ResponsePayload::ExecutionDescriptorResponse(_) + | wire::ResponsePayload::ExecutionListResponse(_) + | wire::ResponsePayload::ExecutionDeletedResponse(_) + | wire::ResponsePayload::ExecutionIoResponse(_) + | wire::ResponsePayload::ExecutionOutputPageResponse(_) => { return Err(ClientError::Sidecar( "unexpected open_session response".to_string(), )); @@ -359,7 +368,16 @@ impl AgentOs { | wire::ResponsePayload::ResourceSnapshotResponse(_) | wire::ResponsePayload::PackageLinkedResponse(_) | wire::ResponsePayload::ProvidedCommandsResponse(_) - | wire::ResponsePayload::ListMountsResponse(_) => { + | wire::ResponsePayload::ListMountsResponse(_) + | wire::ResponsePayload::ExecutionAcceptedResponse(_) + | wire::ResponsePayload::ExecutionCompletedResponse(_) + | wire::ResponsePayload::ExecutionEvaluationResponse(_) + | wire::ResponsePayload::TypeScriptCheckResponse(_) + | wire::ResponsePayload::ExecutionDescriptorResponse(_) + | wire::ResponsePayload::ExecutionListResponse(_) + | wire::ResponsePayload::ExecutionDeletedResponse(_) + | wire::ResponsePayload::ExecutionIoResponse(_) + | wire::ResponsePayload::ExecutionOutputPageResponse(_) => { return Err(ClientError::Sidecar( "unexpected create_vm response".to_string(), )); @@ -392,7 +410,7 @@ impl AgentOs { permissions: Some(permissions), // Client-side `moduleAccessCwd` was removed in favor of an // explicit `nodeModulesMount(...)` entry in `mounts`; the - // secure-exec wire field is left unset. + // agentos wire field is left unset. module_access_cwd: None, instructions: config.additional_instructions.clone().into_iter().collect(), projected_modules: Vec::new(), @@ -450,7 +468,16 @@ impl AgentOs { | wire::ResponsePayload::ResourceSnapshotResponse(_) | wire::ResponsePayload::PackageLinkedResponse(_) | wire::ResponsePayload::ProvidedCommandsResponse(_) - | wire::ResponsePayload::ListMountsResponse(_) => { + | wire::ResponsePayload::ListMountsResponse(_) + | wire::ResponsePayload::ExecutionAcceptedResponse(_) + | wire::ResponsePayload::ExecutionCompletedResponse(_) + | wire::ResponsePayload::ExecutionEvaluationResponse(_) + | wire::ResponsePayload::TypeScriptCheckResponse(_) + | wire::ResponsePayload::ExecutionDescriptorResponse(_) + | wire::ResponsePayload::ExecutionListResponse(_) + | wire::ResponsePayload::ExecutionDeletedResponse(_) + | wire::ResponsePayload::ExecutionIoResponse(_) + | wire::ResponsePayload::ExecutionOutputPageResponse(_) => { return Err(ClientError::Sidecar( "unexpected configure_vm response".to_string(), )); @@ -534,7 +561,16 @@ impl AgentOs { | wire::ResponsePayload::ResourceSnapshotResponse(_) | wire::ResponsePayload::PackageLinkedResponse(_) | wire::ResponsePayload::ProvidedCommandsResponse(_) - | wire::ResponsePayload::ListMountsResponse(_) => { + | wire::ResponsePayload::ListMountsResponse(_) + | wire::ResponsePayload::ExecutionAcceptedResponse(_) + | wire::ResponsePayload::ExecutionCompletedResponse(_) + | wire::ResponsePayload::ExecutionEvaluationResponse(_) + | wire::ResponsePayload::TypeScriptCheckResponse(_) + | wire::ResponsePayload::ExecutionDescriptorResponse(_) + | wire::ResponsePayload::ExecutionListResponse(_) + | wire::ResponsePayload::ExecutionDeletedResponse(_) + | wire::ResponsePayload::ExecutionIoResponse(_) + | wire::ResponsePayload::ExecutionOutputPageResponse(_) => { return Err(ClientError::Sidecar( "unexpected register_host_callbacks response".to_string(), )); @@ -887,6 +923,8 @@ fn spawn_acp_event_pump(client: &AgentOs) { wire::EventPayload::VmLifecycleEvent(_) | wire::EventPayload::ProcessOutputEvent(_) | wire::EventPayload::ProcessExitedEvent(_) + | wire::EventPayload::ExecutionOutputEvent(_) + | wire::EventPayload::ExecutionCompletedEvent(_) | wire::EventPayload::StructuredEvent(_), )) => {} Err(broadcast::error::RecvError::Lagged(_)) => {} @@ -1410,6 +1448,8 @@ async fn wait_for_vm_ready( } wire::EventPayload::ProcessOutputEvent(_) | wire::EventPayload::ProcessExitedEvent(_) + | wire::EventPayload::ExecutionOutputEvent(_) + | wire::EventPayload::ExecutionCompletedEvent(_) | wire::EventPayload::StructuredEvent(_) | wire::EventPayload::ExtEnvelope(_) => {} }, diff --git a/crates/client/src/config.rs b/crates/client/src/config.rs index f8de322e9a..2b21a204cb 100644 --- a/crates/client/src/config.rs +++ b/crates/client/src/config.rs @@ -30,11 +30,11 @@ pub struct AgentOsConfig { /// Software packages to install (flattened). Default `[]`. pub software: Vec, /// Package directories to project into the VM's `/opt/agentos` tree (the - /// secure-exec package projection). Each entry is a host dir containing an + /// agentos package projection). Each entry is a host dir containing an /// `agentos-package.json` manifest + the package payload. Default `[]`. pub packages: Vec, /// Guest mount point for the package projection. Default `/opt/agentos` - /// (secure-exec's `OPT_AGENTOS_ROOT`) when `None`. + /// (agentos's `OPT_AGENTOS_ROOT`) when `None`. pub packages_mount_at: Option, /// Loopback ports exempt from the default outbound-to-host block. pub loopback_exempt_ports: Vec, @@ -166,7 +166,7 @@ impl AgentOsConfigBuilder { #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum SoftwareKind { - /// A directory of wasm command binaries. Mounted at `/__secure_exec/commands/{index}/` so the + /// A directory of wasm command binaries. Mounted at `/__agentos/commands/{index}/` so the /// sidecar's command discovery can resolve guest commands (`echo`, `sh`, `grep`, ...). #[default] WasmCommands, @@ -221,7 +221,7 @@ pub struct SidecarJsBridgeCall { /// Host-side handler for sidecar `JsBridgeCallRequest` payloads. /// /// This is Rust-only and intentionally not JSON-serializable. RivetKit uses it to bind a native -/// sidecar root filesystem to actor-owned SQLite (`ctx.db_*`) without teaching secure-exec about +/// sidecar root filesystem to actor-owned SQLite (`ctx.db_*`) without teaching agentos about /// Rivet actors. pub type SidecarJsBridgeCallback = Arc< dyn Fn( diff --git a/crates/client/src/cron.rs b/crates/client/src/cron.rs index 8043eb4a3f..bbe8ef7007 100644 --- a/crates/client/src/cron.rs +++ b/crates/client/src/cron.rs @@ -423,7 +423,7 @@ async fn run_action(vm: &AgentOs, action: &CronAction) -> Result<(), ClientError // and re-parsing it through the `exec` command-line parser would re-split argv elements // on whitespace and shell-evaluate any `$()`/backtick content; `exec_argv` preserves the // structured (command, args) contract element-for-element. - vm.exec_argv(command, args, crate::process::ExecOptions::default()) + vm.exec_argv_process(command, args, crate::process::ExecOptions::default()) .await .map_err(|err| ClientError::Sidecar(err.to_string()))?; Ok(()) diff --git a/crates/client/src/fs.rs b/crates/client/src/fs.rs index 069a498083..5595007a41 100644 --- a/crates/client/src/fs.rs +++ b/crates/client/src/fs.rs @@ -518,7 +518,7 @@ impl AgentOs { let result = self .guest_fs_call(Self::fs_request(GuestFilesystemOperation::ReadDir, path)) .await?; - // secure-exec's READ_DIR now returns rich entries (`entries: + // agentos's READ_DIR now returns rich entries (`entries: // list` with name + is_directory + is_symbolic_link); // this name-only accessor projects the basenames. The richer fields back // the typed [`Self::read_dir_with_types`] path. @@ -703,7 +703,7 @@ impl AgentOs { Ok(entries) } - /// Typed directory listing: each child reported with its resolved type. secure-exec's native + /// Typed directory listing: each child reported with its resolved type. agentos's native /// `READ_DIR` returns basenames only (`entries: list`), so the type of each entry is derived /// with a per-child `lstat` (a symlink is reported as such, lstat-style, not followed). Goes /// through the kernel, so mounts are listed correctly. `.`/`..` are filtered. diff --git a/crates/client/src/language_execution.rs b/crates/client/src/language_execution.rs new file mode 100644 index 0000000000..0178528215 --- /dev/null +++ b/crates/client/src/language_execution.rs @@ -0,0 +1,1014 @@ +//! First-class JavaScript, TypeScript, Python, and shared execution lifecycle. + +use std::collections::HashMap; + +use agentos_sidecar_client::wire; +use tokio::sync::broadcast; + +use crate::agent_os::AgentOs; +use crate::error::{ClientError, ClientResult}; + +pub type ExecutionDescriptor = wire::ExecutionDescriptor; +pub type CodeExecutionResult = wire::ExecutionCompletedResponse; +pub type ExecutionOutputEvent = wire::ExecutionOutputEvent; +pub type ExecutionCompletedEvent = wire::ExecutionCompletedEvent; +pub type ExecutionOutputPage = wire::ExecutionOutputPageResponse; +pub type TypeScriptDiagnostic = wire::TypeScriptDiagnostic; + +#[derive(Debug, Clone, Default)] +pub struct LanguageExecutionOptions { + pub execution_id: Option, + pub create_if_missing: Option, + pub cwd: Option, + pub env: HashMap, + pub args: Vec, + pub stdin: Option>, + pub timeout_ms: Option, + pub detached: bool, + pub pty: Option, +} + +#[derive(Debug, Clone, Copy, Default)] +pub struct ExecutionPtyOptions { + pub cols: Option, + pub rows: Option, +} + +#[derive(Debug, Clone, Default)] +pub struct InlineExecutionOptions { + pub process: LanguageExecutionOptions, + pub inputs: Option>, +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub enum JavaScriptModuleFormat { + #[default] + Module, + CommonJs, +} + +#[derive(Debug, Clone, Default)] +pub struct JavaScriptExecutionOptions { + pub inline: InlineExecutionOptions, + pub format: JavaScriptModuleFormat, + pub file_path: Option, +} + +#[derive(Debug, Clone, Default)] +pub struct TypeScriptExecutionOptions { + pub inline: InlineExecutionOptions, + pub file_path: Option, + pub tsconfig_path: Option, + pub compiler_options: Option>, +} + +#[derive(Debug, Clone, Default)] +pub struct TypeScriptCheckOptions { + pub execution_id: Option, + pub create_if_missing: Option, + pub cwd: Option, + pub file_path: Option, + pub tsconfig_path: Option, + pub compiler_options: Option>, + pub timeout_ms: Option, +} + +#[derive(Debug, Clone, Default)] +pub struct NpmProjectInstallOptions { + pub execution_id: Option, + pub create_if_missing: Option, + pub cwd: Option, + pub env: HashMap, + pub timeout_ms: Option, + pub frozen: Option, +} + +#[derive(Debug, Clone, Default)] +pub struct NpmPackageInstallOptions { + pub execution_id: Option, + pub create_if_missing: Option, + pub cwd: Option, + pub env: HashMap, + pub timeout_ms: Option, + pub dev: Option, + pub global: Option, +} + +#[derive(Debug, Clone, Default)] +pub struct PythonInstallOptions { + pub execution_id: Option, + pub create_if_missing: Option, + pub cwd: Option, + pub env: HashMap, + pub timeout_ms: Option, + pub upgrade: Option, + pub requirements_file: Option, + pub index_url: Option, + pub extra_index_urls: Vec, +} + +#[derive(Debug, Clone)] +pub struct TypeScriptCheckResult { + pub result: CodeExecutionResult, + pub has_errors: Option, + pub diagnostics: Vec, +} + +#[derive(Debug, Clone)] +pub enum ExecutionSubmission { + Completed(CodeExecutionResult), + Detached(ExecutionDescriptor), +} + +#[derive(Debug, Clone)] +pub struct CodeEvaluationResult { + pub result: CodeExecutionResult, + pub value: Option, +} + +fn identity(options: &LanguageExecutionOptions) -> wire::ExecutionIdentityOptions { + wire::ExecutionIdentityOptions { + execution_id: options.execution_id.clone(), + create_if_missing: options.create_if_missing, + } +} + +fn process(options: &LanguageExecutionOptions) -> wire::ProcessExecutionOptions { + wire::ProcessExecutionOptions { + identity: identity(options), + detached: Some(options.detached), + cwd: options.cwd.clone(), + env: (!options.env.is_empty()).then(|| options.env.clone()), + args: options.args.clone(), + stdin: options.stdin.clone(), + timeout_ms: options.timeout_ms, + pty: options.pty.map(|pty| wire::ExecutionPtyOptions { + cols: pty.cols, + rows: pty.rows, + }), + } +} + +fn json_inputs(options: &InlineExecutionOptions) -> ClientResult> { + options + .inputs + .as_ref() + .map(serde_json::to_string) + .transpose() + .map_err(|error| ClientError::Sidecar(format!("failed to serialize inputs: {error}"))) +} + +impl AgentOs { + fn execution_ownership(&self) -> wire::OwnershipScope { + let inner = self.inner(); + wire::OwnershipScope::VmOwnership(wire::VmOwnership { + connection_id: inner.connection_id.clone(), + session_id: inner.session_id.clone(), + vm_id: inner.vm_id.clone(), + }) + } + + async fn submit_execution( + &self, + payload: wire::RequestPayload, + detached: bool, + ) -> ClientResult { + let mut events = self.transport().subscribe_wire_events(); + let accepted = match self + .transport() + .request_wire(self.execution_ownership(), payload) + .await? + { + wire::ResponsePayload::ExecutionAcceptedResponse(response) => response.execution, + wire::ResponsePayload::RejectedResponse(rejected) => { + return Err(ClientError::from_rejection(rejected)) + } + response => { + return Err(ClientError::Sidecar(format!( + "unexpected execution response: {response:?}" + ))) + } + }; + if detached { + return Ok(ExecutionSubmission::Detached(accepted)); + } + wait_for_completion_event(&mut events, &accepted.execution_id).await?; + Ok(ExecutionSubmission::Completed( + self.wait_execution(&accepted.execution_id).await?, + )) + } + + pub async fn exec( + &self, + command: impl Into, + options: LanguageExecutionOptions, + ) -> ClientResult { + let detached = options.detached; + self.submit_execution( + wire::RequestPayload::ShellExecutionRequest(wire::ShellExecutionRequest { + process: process(&options), + command: command.into(), + }), + detached, + ) + .await + } + + pub async fn exec_argv( + &self, + command: impl Into, + args: Vec, + mut options: LanguageExecutionOptions, + ) -> ClientResult { + options.args = args; + let detached = options.detached; + self.submit_execution( + wire::RequestPayload::ArgvExecutionRequest(wire::ArgvExecutionRequest { + process: process(&options), + command: command.into(), + }), + detached, + ) + .await + } + + pub async fn spawn( + &self, + command: impl Into, + args: Vec, + mut options: LanguageExecutionOptions, + ) -> ClientResult { + options.args = args; + options.detached = true; + match self + .exec_argv(command, options.args.clone(), options) + .await? + { + ExecutionSubmission::Detached(descriptor) => Ok(descriptor), + ExecutionSubmission::Completed(_) => Err(ClientError::Sidecar(String::from( + "spawn unexpectedly returned an attached result", + ))), + } + } + + pub async fn execute_javascript( + &self, + source: impl Into, + options: JavaScriptExecutionOptions, + ) -> ClientResult { + let inputs = json_inputs(&options.inline)?; + self.submit_execution( + wire::RequestPayload::JavaScriptExecutionRequest(wire::JavaScriptExecutionRequest { + process: process(&options.inline.process), + source: source.into(), + format: Some(match options.format { + JavaScriptModuleFormat::Module => wire::JavaScriptModuleFormat::Module, + JavaScriptModuleFormat::CommonJs => wire::JavaScriptModuleFormat::CommonJs, + }), + file_path: options.file_path, + inputs, + }), + options.inline.process.detached, + ) + .await + } + + pub async fn evaluate_javascript( + &self, + expression: impl Into, + options: JavaScriptExecutionOptions, + ) -> ClientResult { + let inputs = json_inputs(&options.inline)?; + let submission = self + .submit_execution( + wire::RequestPayload::JavaScriptEvaluationRequest( + wire::JavaScriptEvaluationRequest { + process: process(&options.inline.process), + expression: expression.into(), + format: Some(match options.format { + JavaScriptModuleFormat::Module => wire::JavaScriptModuleFormat::Module, + JavaScriptModuleFormat::CommonJs => { + wire::JavaScriptModuleFormat::CommonJs + } + }), + file_path: options.file_path, + inputs, + }, + ), + false, + ) + .await?; + evaluation_result(submission) + } + + pub async fn execute_javascript_file( + &self, + path: impl Into, + options: LanguageExecutionOptions, + ) -> ClientResult { + let detached = options.detached; + self.submit_execution( + wire::RequestPayload::JavaScriptFileExecutionRequest( + wire::JavaScriptFileExecutionRequest { + process: process(&options), + path: path.into(), + }, + ), + detached, + ) + .await + } + + pub async fn execute_typescript( + &self, + source: impl Into, + options: TypeScriptExecutionOptions, + ) -> ClientResult { + let inputs = json_inputs(&options.inline)?; + self.submit_execution( + wire::RequestPayload::TypeScriptExecutionRequest(wire::TypeScriptExecutionRequest { + process: process(&options.inline.process), + source: source.into(), + file_path: options.file_path, + tsconfig_path: options.tsconfig_path, + compiler_options: options + .compiler_options + .as_ref() + .map(serde_json::to_string) + .transpose() + .map_err(|error| ClientError::Sidecar(error.to_string()))?, + inputs, + }), + options.inline.process.detached, + ) + .await + } + + pub async fn evaluate_typescript( + &self, + expression: impl Into, + options: TypeScriptExecutionOptions, + ) -> ClientResult { + let inputs = json_inputs(&options.inline)?; + let submission = self + .submit_execution( + wire::RequestPayload::TypeScriptEvaluationRequest( + wire::TypeScriptEvaluationRequest { + process: process(&options.inline.process), + expression: expression.into(), + file_path: options.file_path, + tsconfig_path: options.tsconfig_path, + compiler_options: options + .compiler_options + .as_ref() + .map(serde_json::to_string) + .transpose() + .map_err(|error| ClientError::Sidecar(error.to_string()))?, + inputs, + }, + ), + false, + ) + .await?; + evaluation_result(submission) + } + + pub async fn execute_typescript_file( + &self, + path: impl Into, + options: TypeScriptExecutionOptions, + ) -> ClientResult { + let detached = options.inline.process.detached; + self.submit_execution( + wire::RequestPayload::TypeScriptFileExecutionRequest( + wire::TypeScriptFileExecutionRequest { + process: process(&options.inline.process), + path: path.into(), + tsconfig_path: options.tsconfig_path, + compiler_options: options + .compiler_options + .as_ref() + .map(serde_json::to_string) + .transpose() + .map_err(|error| ClientError::Sidecar(error.to_string()))?, + }, + ), + detached, + ) + .await + } + + pub async fn check_typescript( + &self, + source: impl Into, + options: TypeScriptCheckOptions, + ) -> ClientResult { + let compiler_options = options + .compiler_options + .as_ref() + .map(serde_json::to_string) + .transpose() + .map_err(|error| ClientError::Sidecar(error.to_string()))?; + let submission = self + .submit_execution( + wire::RequestPayload::TypeScriptCheckRequest(wire::TypeScriptCheckRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: options.execution_id, + create_if_missing: options.create_if_missing, + }, + source: source.into(), + cwd: options.cwd, + file_path: options.file_path, + tsconfig_path: options.tsconfig_path, + compiler_options, + timeout_ms: options.timeout_ms, + }), + false, + ) + .await?; + let result = completed_submission(submission)?; + typescript_check_result(result) + } + + pub async fn check_typescript_project( + &self, + options: TypeScriptCheckOptions, + ) -> ClientResult { + let submission = self + .submit_execution( + wire::RequestPayload::TypeScriptProjectCheckRequest( + wire::TypeScriptProjectCheckRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: options.execution_id, + create_if_missing: options.create_if_missing, + }, + cwd: options.cwd, + tsconfig_path: options.tsconfig_path, + timeout_ms: options.timeout_ms, + }, + ), + false, + ) + .await?; + let result = completed_submission(submission)?; + typescript_check_result(result) + } + + pub async fn install_npm_project( + &self, + options: NpmProjectInstallOptions, + ) -> ClientResult { + completed_submission( + self.submit_execution( + wire::RequestPayload::NpmProjectInstallRequest(wire::NpmProjectInstallRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: options.execution_id, + create_if_missing: options.create_if_missing, + }, + cwd: options.cwd, + env: (!options.env.is_empty()).then_some(options.env), + timeout_ms: options.timeout_ms, + frozen: options.frozen, + }), + false, + ) + .await?, + ) + } + + pub async fn install_npm_packages( + &self, + packages: Vec, + options: NpmPackageInstallOptions, + ) -> ClientResult { + completed_submission( + self.submit_execution( + wire::RequestPayload::NpmPackageInstallRequest(wire::NpmPackageInstallRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: options.execution_id, + create_if_missing: options.create_if_missing, + }, + cwd: options.cwd, + env: (!options.env.is_empty()).then_some(options.env), + timeout_ms: options.timeout_ms, + packages, + dev: options.dev, + global: options.global, + }), + false, + ) + .await?, + ) + } + + pub async fn execute_npm_script( + &self, + script: impl Into, + options: LanguageExecutionOptions, + ) -> ClientResult { + let detached = options.detached; + self.submit_execution( + wire::RequestPayload::NpmScriptExecutionRequest(wire::NpmScriptExecutionRequest { + process: process(&options), + script: script.into(), + }), + detached, + ) + .await + } + + pub async fn execute_npm_package( + &self, + package_spec: impl Into, + binary: Option, + options: LanguageExecutionOptions, + ) -> ClientResult { + let detached = options.detached; + self.submit_execution( + wire::RequestPayload::NpmPackageExecutionRequest(wire::NpmPackageExecutionRequest { + process: process(&options), + package_spec: package_spec.into(), + binary, + }), + detached, + ) + .await + } + + pub async fn execute_python( + &self, + source: impl Into, + options: InlineExecutionOptions, + ) -> ClientResult { + let inputs = json_inputs(&options)?; + self.submit_execution( + wire::RequestPayload::PythonExecutionRequest(wire::PythonExecutionRequest { + process: process(&options.process), + source: source.into(), + inputs, + }), + options.process.detached, + ) + .await + } + + pub async fn evaluate_python( + &self, + expression: impl Into, + options: InlineExecutionOptions, + ) -> ClientResult { + let inputs = json_inputs(&options)?; + let submission = self + .submit_execution( + wire::RequestPayload::PythonEvaluationRequest(wire::PythonEvaluationRequest { + process: process(&options.process), + expression: expression.into(), + inputs, + }), + false, + ) + .await?; + evaluation_result(submission) + } + + pub async fn execute_python_file( + &self, + path: impl Into, + options: LanguageExecutionOptions, + ) -> ClientResult { + let detached = options.detached; + self.submit_execution( + wire::RequestPayload::PythonFileExecutionRequest(wire::PythonFileExecutionRequest { + process: process(&options), + path: path.into(), + }), + detached, + ) + .await + } + + pub async fn execute_python_module( + &self, + module: impl Into, + options: LanguageExecutionOptions, + ) -> ClientResult { + let detached = options.detached; + self.submit_execution( + wire::RequestPayload::PythonModuleExecutionRequest( + wire::PythonModuleExecutionRequest { + process: process(&options), + module: module.into(), + }, + ), + detached, + ) + .await + } + + pub async fn install_python_packages( + &self, + packages: Vec, + options: PythonInstallOptions, + ) -> ClientResult { + if !packages.is_empty() && options.requirements_file.is_some() { + return Err(ClientError::Sidecar(String::from( + "install_python_packages cannot combine packages with requirements_file", + ))); + } + completed_submission( + self.submit_execution( + wire::RequestPayload::PythonInstallRequest(wire::PythonInstallRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: options.execution_id, + create_if_missing: options.create_if_missing, + }, + cwd: options.cwd, + env: (!options.env.is_empty()).then_some(options.env), + timeout_ms: options.timeout_ms, + packages, + upgrade: options.upgrade, + requirements_file: options.requirements_file, + index_url: options.index_url, + extra_index_urls: options.extra_index_urls, + }), + false, + ) + .await?, + ) + } + + pub async fn get_execution(&self, execution_id: &str) -> ClientResult { + match self + .transport() + .request_wire( + self.execution_ownership(), + wire::RequestPayload::GetExecutionRequest(wire::GetExecutionRequest { + execution_id: execution_id.to_owned(), + }), + ) + .await? + { + wire::ResponsePayload::ExecutionDescriptorResponse(response) => Ok(response.execution), + wire::ResponsePayload::RejectedResponse(rejected) => { + Err(ClientError::from_rejection(rejected)) + } + response => Err(ClientError::Sidecar(format!( + "unexpected get_execution response: {response:?}" + ))), + } + } + + pub async fn list_executions(&self) -> ClientResult> { + match self + .transport() + .request_wire( + self.execution_ownership(), + wire::RequestPayload::ListExecutionsRequest, + ) + .await? + { + wire::ResponsePayload::ExecutionListResponse(response) => Ok(response.executions), + wire::ResponsePayload::RejectedResponse(rejected) => { + Err(ClientError::from_rejection(rejected)) + } + response => Err(ClientError::Sidecar(format!( + "unexpected list_executions response: {response:?}" + ))), + } + } + + pub async fn wait_execution(&self, execution_id: &str) -> ClientResult { + let mut events = self.transport().subscribe_wire_events(); + let first = self + .transport() + .request_wire( + self.execution_ownership(), + wire::RequestPayload::WaitExecutionRequest(wire::WaitExecutionRequest { + execution_id: execution_id.to_owned(), + }), + ) + .await?; + let response = match first { + wire::ResponsePayload::RejectedResponse(rejected) + if rejected.code == "execution_busy" => + { + wait_for_completion_event(&mut events, execution_id).await?; + self.transport() + .request_wire( + self.execution_ownership(), + wire::RequestPayload::WaitExecutionRequest(wire::WaitExecutionRequest { + execution_id: execution_id.to_owned(), + }), + ) + .await? + } + response => response, + }; + match response { + wire::ResponsePayload::ExecutionCompletedResponse(response) => Ok(response), + wire::ResponsePayload::RejectedResponse(rejected) => { + Err(ClientError::from_rejection(rejected)) + } + response => Err(ClientError::Sidecar(format!( + "unexpected wait_execution response: {response:?}" + ))), + } + } + + pub async fn cancel_execution(&self, execution_id: &str) -> ClientResult { + self.execution_descriptor_request(wire::RequestPayload::CancelExecutionRequest( + wire::CancelExecutionRequest { + execution_id: execution_id.to_owned(), + }, + )) + .await + } + + pub async fn signal_execution( + &self, + execution_id: &str, + signal: impl Into, + ) -> ClientResult { + self.execution_descriptor_request(wire::RequestPayload::SignalExecutionRequest( + wire::SignalExecutionRequest { + execution_id: execution_id.to_owned(), + signal: signal.into(), + }, + )) + .await + } + + pub async fn reset_execution(&self, execution_id: &str) -> ClientResult { + self.execution_descriptor_request(wire::RequestPayload::ResetExecutionRequest( + wire::ResetExecutionRequest { + execution_id: execution_id.to_owned(), + }, + )) + .await + } + + async fn execution_descriptor_request( + &self, + payload: wire::RequestPayload, + ) -> ClientResult { + match self + .transport() + .request_wire(self.execution_ownership(), payload) + .await? + { + wire::ResponsePayload::ExecutionDescriptorResponse(response) => Ok(response.execution), + wire::ResponsePayload::RejectedResponse(rejected) => { + Err(ClientError::from_rejection(rejected)) + } + response => Err(ClientError::Sidecar(format!( + "unexpected execution lifecycle response: {response:?}" + ))), + } + } + + pub async fn delete_execution(&self, execution_id: &str) -> ClientResult<()> { + match self + .transport() + .request_wire( + self.execution_ownership(), + wire::RequestPayload::DeleteExecutionRequest(wire::DeleteExecutionRequest { + execution_id: execution_id.to_owned(), + }), + ) + .await? + { + wire::ResponsePayload::ExecutionDeletedResponse(_) => Ok(()), + wire::ResponsePayload::RejectedResponse(rejected) => { + Err(ClientError::from_rejection(rejected)) + } + response => Err(ClientError::Sidecar(format!( + "unexpected delete_execution response: {response:?}" + ))), + } + } + + pub async fn read_execution_output( + &self, + execution_id: &str, + cursor: Option, + limit: Option, + ) -> ClientResult { + match self + .transport() + .request_wire( + self.execution_ownership(), + wire::RequestPayload::ReadExecutionOutputRequest( + wire::ReadExecutionOutputRequest { + execution_id: execution_id.to_owned(), + cursor, + limit, + }, + ), + ) + .await? + { + wire::ResponsePayload::ExecutionOutputPageResponse(response) => Ok(response), + wire::ResponsePayload::RejectedResponse(rejected) => { + Err(ClientError::from_rejection(rejected)) + } + response => Err(ClientError::Sidecar(format!( + "unexpected read_execution_output response: {response:?}" + ))), + } + } + + pub async fn write_execution_stdin( + &self, + execution_id: &str, + chunk: Vec, + ) -> ClientResult<()> { + self.execution_io_request(wire::RequestPayload::WriteExecutionStdinRequest( + wire::WriteExecutionStdinRequest { + execution_id: execution_id.to_owned(), + chunk, + }, + )) + .await + } + + pub async fn close_execution_stdin(&self, execution_id: &str) -> ClientResult<()> { + self.execution_io_request(wire::RequestPayload::CloseExecutionStdinRequest( + wire::CloseExecutionStdinRequest { + execution_id: execution_id.to_owned(), + }, + )) + .await + } + + pub async fn resize_execution_pty( + &self, + execution_id: &str, + cols: u16, + rows: u16, + ) -> ClientResult<()> { + self.execution_io_request(wire::RequestPayload::ResizeExecutionPtyRequest( + wire::ResizeExecutionPtyRequest { + execution_id: execution_id.to_owned(), + cols, + rows, + }, + )) + .await + } + + async fn execution_io_request(&self, payload: wire::RequestPayload) -> ClientResult<()> { + match self + .transport() + .request_wire(self.execution_ownership(), payload) + .await? + { + wire::ResponsePayload::ExecutionIoResponse(_) => Ok(()), + wire::ResponsePayload::RejectedResponse(rejected) => { + Err(ClientError::from_rejection(rejected)) + } + response => Err(ClientError::Sidecar(format!( + "unexpected execution I/O response: {response:?}" + ))), + } + } +} + +async fn wait_for_completion_event( + events: &mut broadcast::Receiver<(wire::OwnershipScope, wire::EventPayload)>, + execution_id: &str, +) -> ClientResult<()> { + loop { + match events.recv().await { + Ok((_, wire::EventPayload::ExecutionCompletedEvent(event))) + if event.execution_id == execution_id => + { + return Ok(()) + } + Ok(_) | Err(broadcast::error::RecvError::Lagged(_)) => {} + Err(broadcast::error::RecvError::Closed) => { + return Err(ClientError::Sidecar(String::from( + "execution event stream closed before completion", + ))) + } + } + } +} + +fn evaluation_result(submission: ExecutionSubmission) -> ClientResult { + let ExecutionSubmission::Completed(result) = submission else { + return Err(ClientError::Sidecar(String::from( + "evaluation unexpectedly returned detached execution", + ))); + }; + let value = serde_json::from_str::(&result.outputs) + .ok() + .and_then(|outputs| outputs.as_array().cloned()) + .and_then(|outputs| { + outputs + .into_iter() + .find_map(|output| output.get("data").cloned()) + }); + Ok(CodeEvaluationResult { result, value }) +} + +fn typescript_check_result(result: CodeExecutionResult) -> ClientResult { + if result.outcome != wire::ExecutionOutcome::Succeeded { + return Ok(TypeScriptCheckResult { + result, + has_errors: None, + diagnostics: Vec::new(), + }); + } + let outputs: serde_json::Value = serde_json::from_str(&result.outputs).map_err(|error| { + ClientError::Sidecar(format!( + "failed to decode TypeScript checker output: {error}" + )) + })?; + let data = outputs + .as_array() + .and_then(|outputs| outputs.iter().find_map(|output| output.get("data"))) + .and_then(serde_json::Value::as_object) + .ok_or_else(|| { + ClientError::Sidecar(String::from( + "TypeScript checker returned no diagnostic result", + )) + })?; + let has_errors = data + .get("hasErrors") + .and_then(serde_json::Value::as_bool) + .ok_or_else(|| { + ClientError::Sidecar(String::from( + "TypeScript checker returned an invalid hasErrors value", + )) + })?; + let diagnostics = data + .get("diagnostics") + .and_then(serde_json::Value::as_array) + .ok_or_else(|| { + ClientError::Sidecar(String::from( + "TypeScript checker returned invalid diagnostics", + )) + })? + .iter() + .map(|diagnostic| { + let code = diagnostic + .get("code") + .and_then(serde_json::Value::as_u64) + .and_then(|code| u32::try_from(code).ok()) + .ok_or_else(|| { + ClientError::Sidecar(String::from( + "TypeScript checker returned an invalid diagnostic code", + )) + })?; + let category = diagnostic + .get("category") + .and_then(serde_json::Value::as_str) + .ok_or_else(|| { + ClientError::Sidecar(String::from( + "TypeScript checker returned an invalid diagnostic category", + )) + })? + .to_owned(); + let message = diagnostic + .get("message") + .and_then(serde_json::Value::as_str) + .ok_or_else(|| { + ClientError::Sidecar(String::from( + "TypeScript checker returned an invalid diagnostic message", + )) + })? + .to_owned(); + Ok(wire::TypeScriptDiagnostic { + code, + category, + message, + file_path: diagnostic + .get("filePath") + .and_then(serde_json::Value::as_str) + .map(str::to_owned), + line: diagnostic + .get("line") + .and_then(serde_json::Value::as_u64) + .and_then(|line| u32::try_from(line).ok()), + column: diagnostic + .get("column") + .and_then(serde_json::Value::as_u64) + .and_then(|column| u32::try_from(column).ok()), + }) + }) + .collect::>>()?; + Ok(TypeScriptCheckResult { + result, + has_errors: Some(has_errors), + diagnostics, + }) +} + +fn completed_submission(submission: ExecutionSubmission) -> ClientResult { + match submission { + ExecutionSubmission::Completed(result) => Ok(result), + ExecutionSubmission::Detached(_) => Err(ClientError::Sidecar(String::from( + "attached operation unexpectedly returned a detached execution", + ))), + } +} diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index c0389caab2..c58be5f377 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -8,7 +8,7 @@ //! //! The client spawns the native `agentos-sidecar` binary and speaks the existing framed BARE //! protocol over its stdio (see [`transport`]). It does NOT embed the kernel in-process and does NOT -//! define a new sidecar wire protocol. The generated Secure Exec schema surface comes from +//! define a new sidecar wire protocol. The generated AgentOS language execution schema surface comes from //! `agentos_sidecar_client::wire`; Agent OS layers ACP/session semantics on top of those generated wire //! frames through the wrapper client. //! @@ -21,6 +21,7 @@ pub mod config; pub mod cron; pub mod error; pub mod fs; +pub mod language_execution; pub mod net; pub mod process; pub mod session; @@ -53,6 +54,12 @@ pub const CRON_JOB_LIMIT: usize = 1024; pub use agent_os::{AgentOs, PackageDescriptor, ProjectedAgent, SoftwareInfo}; pub use error::{ClientError, ClientResult, ResourceLimitDetails}; +pub use language_execution::{ + CodeEvaluationResult, CodeExecutionResult, ExecutionCompletedEvent, ExecutionDescriptor, + ExecutionOutputEvent, ExecutionOutputPage, ExecutionPtyOptions, ExecutionSubmission, + InlineExecutionOptions, JavaScriptExecutionOptions, JavaScriptModuleFormat, + LanguageExecutionOptions, TypeScriptDiagnostic, +}; pub use sidecar::{ AgentOsSidecar, AgentOsSidecarDescription, AgentOsSidecarPlacement, SidecarState, }; diff --git a/crates/client/src/process.rs b/crates/client/src/process.rs index 604c058830..b03ca545a0 100644 --- a/crates/client/src/process.rs +++ b/crates/client/src/process.rs @@ -216,12 +216,12 @@ impl AgentOs { /// process id immediately; stdout/stderr are accumulated and the call resolves once the matching /// `ProcessExited` event arrives. This mirrors the TS pass-through to `kernel.exec` semantically: /// the result is the full captured stdout/stderr plus exit code. - pub async fn exec(&self, command: &str, options: ExecOptions) -> Result { + pub async fn exec_process(&self, command: &str, options: ExecOptions) -> Result { // Parse the command line into a `(command, args)` pair the same way the sidecar's // child_process path does: shell-free argv lists spawn directly (preserving the command's // real exit code), while shell syntax or a builtin head runs under `sh -c `. let (resolved_command, resolved_args) = resolve_exec_command(command)?; - self.exec_argv(&resolved_command, &resolved_args, options) + self.exec_argv_process(&resolved_command, &resolved_args, options) .await } @@ -230,7 +230,7 @@ impl AgentOs { /// no whitespace re-splitting, no shell metacharacter detection, and no routing through /// `sh -c`. Callers that already hold a structured argv (for example the cron `Exec` action) /// must use this so the structured-argv contract is preserved end to end. - pub async fn exec_argv( + pub async fn exec_argv_process( &self, command: &str, args: &[String], @@ -377,6 +377,8 @@ impl AgentOs { } EventPayload::ProcessOutputEvent(_) | EventPayload::ProcessExitedEvent(_) + | EventPayload::ExecutionOutputEvent(_) + | EventPayload::ExecutionCompletedEvent(_) | EventPayload::VmLifecycleEvent(_) | EventPayload::StructuredEvent(_) | EventPayload::ExtEnvelope(_) => {} @@ -397,7 +399,7 @@ impl AgentOs { /// Spawn a process. SYNC; returns `{ pid }` only. Installs stdout/stderr fan-out over broadcast /// channels and wires exit via a background event-pump task. The user-facing `pid` is the /// SDK-allocated map key (the wire `process_id` is held inside the [`ProcessEntry`]). - pub fn spawn( + pub fn spawn_process( &self, command: &str, args: Vec, @@ -1118,6 +1120,8 @@ impl AgentOs { } EventPayload::ProcessOutputEvent(_) | EventPayload::ProcessExitedEvent(_) + | EventPayload::ExecutionOutputEvent(_) + | EventPayload::ExecutionCompletedEvent(_) | EventPayload::VmLifecycleEvent(_) | EventPayload::StructuredEvent(_) | EventPayload::ExtEnvelope(_) => {} diff --git a/crates/client/src/shell.rs b/crates/client/src/shell.rs index a2a9f5a41f..fc0e2ccc9b 100644 --- a/crates/client/src/shell.rs +++ b/crates/client/src/shell.rs @@ -376,6 +376,8 @@ impl AgentOs { } } EventPayload::VmLifecycleEvent(_) + | EventPayload::ExecutionOutputEvent(_) + | EventPayload::ExecutionCompletedEvent(_) | EventPayload::StructuredEvent(_) | EventPayload::ExtEnvelope(_) => {} } @@ -512,6 +514,8 @@ impl AgentOs { } } EventPayload::VmLifecycleEvent(_) + | EventPayload::ExecutionOutputEvent(_) + | EventPayload::ExecutionCompletedEvent(_) | EventPayload::StructuredEvent(_) | EventPayload::ExtEnvelope(_) => {} } @@ -644,6 +648,8 @@ impl AgentOs { } } EventPayload::VmLifecycleEvent(_) + | EventPayload::ExecutionOutputEvent(_) + | EventPayload::ExecutionCompletedEvent(_) | EventPayload::StructuredEvent(_) | EventPayload::ExtEnvelope(_) => {} } diff --git a/crates/client/tests/common/mod.rs b/crates/client/tests/common/mod.rs index fcebfbf55b..e8536ef63a 100644 --- a/crates/client/tests/common/mod.rs +++ b/crates/client/tests/common/mod.rs @@ -147,7 +147,7 @@ fn wasm_command_mounts() -> Vec { }; vec![MountConfig::Native { - path: "/__secure_exec/commands/0".to_string(), + path: "/__agentos/commands/0".to_string(), plugin: MountPlugin { id: "host_dir".to_string(), config: Some(serde_json::json!({ @@ -243,7 +243,7 @@ pub async fn new_vm_with_commands() -> Option { /// registry WASM command packages are absent (the common case in unbuilt trees), so the /// process/shell/fetch suites can gate cleanly without each re-implementing the probe. pub async fn wasm_commands_available(os: &AgentOs) -> bool { - os.exec("sh", agentos_client::ExecOptions::default()) + os.exec_process("sh", agentos_client::ExecOptions::default()) .await .is_ok() } diff --git a/crates/client/tests/exec_command_line_e2e.rs b/crates/client/tests/exec_command_line_e2e.rs index c5af5f1cd4..88c8a750a0 100644 --- a/crates/client/tests/exec_command_line_e2e.rs +++ b/crates/client/tests/exec_command_line_e2e.rs @@ -24,7 +24,7 @@ async fn exec_command_line_paths() { // Direct path: a simple command with arguments runs and returns its output. let echo = os - .exec("echo hello world", ExecOptions::default()) + .exec_process("echo hello world", ExecOptions::default()) .await .expect("exec echo"); assert_eq!(echo.exit_code, 0, "echo exit (stderr: {:?})", echo.stderr); @@ -32,7 +32,7 @@ async fn exec_command_line_paths() { // Direct path preserves a real non-zero exit code (the `sh -c` wrapper can swallow it). let missing = os - .exec("cat /no/such/file", ExecOptions::default()) + .exec_process("cat /no/such/file", ExecOptions::default()) .await .expect("exec cat missing returns a result"); assert_ne!( @@ -42,7 +42,7 @@ async fn exec_command_line_paths() { // Shell path: a `&&` chain runs as a single `sh -c` execution. let chain = os - .exec("echo a && echo b", ExecOptions::default()) + .exec_process("echo a && echo b", ExecOptions::default()) .await .expect("exec && chain"); assert_eq!( @@ -54,7 +54,7 @@ async fn exec_command_line_paths() { // Shell path: a redirect writes a file the VM can read back. let redirect = os - .exec( + .exec_process( "echo redirected > /tmp/exec_redirect.txt", ExecOptions::default(), ) @@ -77,14 +77,16 @@ async fn exec_command_line_paths() { // Shell path: a quoted argument with a space stays one token through `sh -c`. let quoted = os - .exec("echo 'a b'", ExecOptions::default()) + .exec_process("echo 'a b'", ExecOptions::default()) .await .expect("exec quoted"); assert_eq!(quoted.stdout.trim_end(), "a b", "quoted stdout"); // An empty command line is an explicit error, not a silent no-op. assert!( - os.exec(" ", ExecOptions::default()).await.is_err(), + os.exec_process(" ", ExecOptions::default()) + .await + .is_err(), "empty command line must error" ); diff --git a/crates/client/tests/fetch_e2e.rs b/crates/client/tests/fetch_e2e.rs index 29aae9dc56..505f5ef0a2 100644 --- a/crates/client/tests/fetch_e2e.rs +++ b/crates/client/tests/fetch_e2e.rs @@ -184,7 +184,7 @@ async fn fetch_surface_get_post_and_headers() { } let server = os - .spawn( + .spawn_process( "node", vec![ "-e".to_string(), diff --git a/crates/client/tests/link_software_e2e.rs b/crates/client/tests/link_software_e2e.rs index 4c9df70dff..92bae6afb0 100644 --- a/crates/client/tests/link_software_e2e.rs +++ b/crates/client/tests/link_software_e2e.rs @@ -76,7 +76,7 @@ async fn link_software_makes_command_resolve_live() { let captured = Arc::new(Mutex::new(Vec::::new())); let err_cap = Arc::new(Mutex::new(Vec::::new())); let handle = os - .spawn("linked-cmd", Vec::new(), SpawnOptions::default()) + .spawn_process("linked-cmd", Vec::new(), SpawnOptions::default()) .expect("spawn linked-cmd"); let cb = captured.clone(); let ecb = err_cap.clone(); diff --git a/crates/client/tests/native_root_mount_e2e.rs b/crates/client/tests/native_root_mount_e2e.rs index a13f9a2817..71fdd0831d 100644 --- a/crates/client/tests/native_root_mount_e2e.rs +++ b/crates/client/tests/native_root_mount_e2e.rs @@ -556,7 +556,7 @@ async fn native_root_mount_files_visible_to_wasm_commands() { // The regression: guest WASM commands must observe the mount-backed root // content, not an empty/broken view. let cat = os - .exec("cat /workspace/data.txt", ExecOptions::default()) + .exec_process("cat /workspace/data.txt", ExecOptions::default()) .await .expect("exec cat"); assert_eq!( @@ -572,7 +572,7 @@ async fn native_root_mount_files_visible_to_wasm_commands() { ); let wc = os - .exec("wc -c /workspace/data.txt", ExecOptions::default()) + .exec_process("wc -c /workspace/data.txt", ExecOptions::default()) .await .expect("exec wc"); assert_eq!( @@ -589,7 +589,7 @@ async fn native_root_mount_files_visible_to_wasm_commands() { // A command spawned by the guest shell must retain the same mounted root. let sh_absolute = os - .exec("sh -c 'cat /workspace/data.txt'", ExecOptions::default()) + .exec_process("sh -c 'cat /workspace/data.txt'", ExecOptions::default()) .await .expect("exec sh absolute cat"); assert_eq!( @@ -601,7 +601,7 @@ async fn native_root_mount_files_visible_to_wasm_commands() { // Shell traversal into the mounted root must work too. let sh = os - .exec( + .exec_process( "sh -c 'cd /workspace && cat data.txt'", ExecOptions::default(), ) @@ -615,7 +615,7 @@ async fn native_root_mount_files_visible_to_wasm_commands() { assert_eq!(sh.stdout.trim_end(), "hello-bridge-root"); let relative_write = os - .exec( + .exec_process( "sh -c 'cd /workspace && echo relative-write > relative.txt'", ExecOptions::default(), ) @@ -635,7 +635,7 @@ async fn native_root_mount_files_visible_to_wasm_commands() { // Guest writes must round-trip back to the host view as well. let write = os - .exec( + .exec_process( "sh -c 'echo guest-write > /workspace/out.txt'", ExecOptions::default(), ) diff --git a/crates/client/tests/packages_aospkg_e2e.rs b/crates/client/tests/packages_aospkg_e2e.rs index a7aff0e832..319fcfb9b3 100644 --- a/crates/client/tests/packages_aospkg_e2e.rs +++ b/crates/client/tests/packages_aospkg_e2e.rs @@ -31,7 +31,7 @@ async fn spawn_capture(os: &AgentOs, cmd: &str, args: Vec) -> (i32, Stri let captured = Arc::new(Mutex::new(Vec::::new())); let err_cap = Arc::new(Mutex::new(Vec::::new())); let handle = os - .spawn(cmd, args, SpawnOptions::default()) + .spawn_process(cmd, args, SpawnOptions::default()) .unwrap_or_else(|e| panic!("spawn {cmd}: {e:?}")); let cb = captured.clone(); let ecb = err_cap.clone(); diff --git a/crates/client/tests/process_e2e.rs b/crates/client/tests/process_e2e.rs index ff7242f055..93bb92bed6 100644 --- a/crates/client/tests/process_e2e.rs +++ b/crates/client/tests/process_e2e.rs @@ -95,7 +95,7 @@ async fn process_surface_exec_spawn_and_snapshot() { // `exec` forwards only the `command` field (no args), so to get deterministic stdout we use a // command that echoes its stdin: `cat` round-trips its input to stdout and exits 0 on EOF. let echoed = os - .exec( + .exec_process( "cat", ExecOptions { stdin: Some(StdinInput::Text("hello-stdout".to_string())), @@ -115,7 +115,7 @@ async fn process_surface_exec_spawn_and_snapshot() { let streamed = Arc::new(Mutex::new(Vec::::new())); let streamed_cb = Arc::clone(&streamed); let res = os - .exec( + .exec_process( "cat", ExecOptions { stdin: Some(StdinInput::Text("stream-me".to_string())), @@ -142,7 +142,7 @@ async fn process_surface_exec_spawn_and_snapshot() { let captured_cb = Arc::clone(&captured); let bin_input = binary.clone(); let res = os - .exec( + .exec_process( "cat", ExecOptions { stdin: Some(StdinInput::Bytes(bin_input)), @@ -163,7 +163,7 @@ async fn process_surface_exec_spawn_and_snapshot() { // --- spawn: pid + stdin write + stdout stream + exit wait ------------------------------------- let handle = os - .spawn("cat", Vec::new(), SpawnOptions::default()) + .spawn_process("cat", Vec::new(), SpawnOptions::default()) .expect("spawn cat"); assert!( handle.pid >= 1_000_000, diff --git a/crates/client/tests/wasm_command_mount_e2e.rs b/crates/client/tests/wasm_command_mount_e2e.rs index 2e76534922..3dac5b6c1a 100644 --- a/crates/client/tests/wasm_command_mount_e2e.rs +++ b/crates/client/tests/wasm_command_mount_e2e.rs @@ -30,7 +30,7 @@ async fn wasm_command_software_mounts_into_vm() { // Before the mount fix this failed with "command not found"; before the exec command-line fix // the space made the whole string resolve as one command name. let result = os - .exec("echo hello", ExecOptions::default()) + .exec_process("echo hello", ExecOptions::default()) .await .expect("exec echo hello"); assert_eq!( diff --git a/crates/execution/CLAUDE.md b/crates/execution/CLAUDE.md index 8512bf579d..5b741aff1a 100644 --- a/crates/execution/CLAUDE.md +++ b/crates/execution/CLAUDE.md @@ -14,7 +14,7 @@ If tests fail because they were written for the old `Command::new("node")` path, ## Node.js Isolation Model -**Desired state:** Guest JS/TS runs inside isolated V8 contexts managed by the execution engine. All Node.js builtins (`fs`, `net`, `child_process`, `dns`, `http`, `os`, etc.) are kernel-backed polyfills that route through the kernel VFS, socket table, and process table. Module loading is fully intercepted — guest code never touches real host APIs. The execution engine previously had this working via `@secure-exec/core` + `@secure-exec/nodejs` with full kernel-backed polyfills for all builtins. +**Desired state:** Guest JS/TS runs inside isolated V8 contexts managed by the execution engine. All Node.js builtins (`fs`, `net`, `child_process`, `dns`, `http`, `os`, etc.) are kernel-backed polyfills that route through the kernel VFS, socket table, and process table. Module loading is fully intercepted — guest code never touches real host APIs. The previous JavaScript kernel packages had full kernel-backed polyfills for all builtins. **Current state (⚠️ STILL INCOMPLETE -- see `~/.agents/todo/node-isolation-gaps.md`):** @@ -23,7 +23,7 @@ Guest JavaScript entrypoints in `javascript.rs` now run only through the shared - Keep any real-host Node helpers isolated to clearly host-only modules used by benchmarks or import-cache tests. Guest JS/WASM/Python runtime code should depend only on neutral shared helpers (for example signal metadata or path resolution), not on files that also own host launch behavior. - Guest-side WebAssembly inside the V8 isolate must stay enabled on both fresh isolates and snapshot restores. Real npm packages rely on `WebAssembly.Module`, `WebAssembly.Instance`, and `WebAssembly.instantiate*`, and allowing those APIs does not violate the kernel-isolation boundary because compilation stays inside the isolate. Do not reintroduce an embedder callback that blocks WASM; rely on V8's own implementation limits instead. -**Recovery reference:** The complete working polyfill + V8 isolate code from the original `@secure-exec/core` + `@secure-exec/nodejs` + `@secure-exec/v8` packages has been recovered to `~/.agents/recovery/secure-exec/`. Key files to port: +**Recovery reference:** The complete working polyfill + V8 isolate code from the original JavaScript runtime packages has been recovered to `~/.agents/recovery/agentos/`. Key files to port: - `nodejs/src/bridge/fs.ts` (3,974 lines) -- full kernel-backed `fs`/`fs/promises` polyfill - `nodejs/src/bridge/network.ts` (11,149 lines) -- full `net`/`dgram`/`dns` polyfill via kernel socket table - `nodejs/src/bridge/child-process.ts` (1,058 lines) -- `child_process` polyfill via kernel process table @@ -34,11 +34,11 @@ Guest JavaScript entrypoints in `javascript.rs` now run only through the shared - `kernel/` -- the JS kernel (VFS, process table, socket table, PTY, pipes) - `v8/` -- V8 runtime process manager, IPC binary protocol -The original source repo is at `/home/nathan/secure-exec-1/` (tagged `v0.2.1`). +The original source repo is at `/home/nathan/agentos-1/` (tagged `v0.2.1`). **Prior art -- the original JS kernel had full polyfills:** -Before the Rust sidecar (commit `5a43882`), the JS kernel (`@secure-exec/core` + `@secure-exec/nodejs` + `packages/posix/`) had complete kernel-backed polyfills for all builtins. The pattern was: +Before the Rust sidecar (commit `5a43882`), the JavaScript kernel and `packages/posix/` had complete kernel-backed polyfills for all builtins. The pattern was: - **Kernel socket table** -- `kernel.socketTable.create/connect/send/recv` managed all TCP/UDP. Loopback stayed in-kernel; external connections went through a `HostNetworkAdapter`. - **Kernel VFS** -- All `fs` operations routed through the kernel VFS via syscall RPC. - **Kernel process table** -- `child_process.spawn` routed through `kernel.spawn()`. @@ -114,7 +114,7 @@ The host-support ESM loader hook (`loader.mjs`) is generated from a Rust string ## Runner Script Assets - Execution-host runner scripts materialized by `NodeImportCache` should live as checked-in assets under `crates/execution/assets/runners/` and be loaded via `include_str!`. -- The stdlib-backed V8 bridge bundle is generated from `packages/build-tools/bridge-src/` into Cargo `OUT_DIR`; `pnpm --dir packages/secure-exec-core build:v8-bridge` is only for manual debugging. Keep the heavier assert/util/zlib payload in `v8-bridge-zlib.js` so the main `v8-bridge.js` stays below the 500KB cap. +- The stdlib-backed V8 bridge bundle is generated from `packages/build-tools/bridge-src/` into Cargo `OUT_DIR`; `pnpm --dir packages/agentos-core build:v8-bridge` is only for manual debugging. Keep the heavier assert/util/zlib payload in `v8-bridge-zlib.js` so the main `v8-bridge.js` stays below the 500KB cap. - Guest `os` virtualization has two env surfaces: public `process.env` is intentionally scrubbed of `AGENTOS_*`, while the real per-execution values live in the hidden runtime env (`globalThis.__agentOSProcessConfigEnv` in `javascript.rs`, mirrored from the sidecar's `prepare_guest_runtime_env(...)`). If `bridge-src` needs VM-scoped CPU/memory/home metadata, read that hidden env path or `_processConfig.env` rather than the sanitized public env, and keep it aligned with `node_import_cache.rs`. - When `build:v8-bridge` pulls deeper undici API modules (for example `undici/lib/api/*`), keep `packages/build-tools/scripts/build-v8-bridge.mjs` aliasing any extra Node builtins they require to standalone shim files under `crates/execution/assets/undici-shims/`; those imports execute while the bundle is still bootstrapping, so they cannot depend on later `exposeCustomGlobal(...)` wiring like `_asyncHooksModule`. - Keep `http` and `https` default agents scoped to their own module instances inside `packages/build-tools/bridge-src/`; sharing a single global default agent makes `http.request()` inherit HTTPS TLS behavior. Guest-local loopback TLS upgrades must also short-circuit inside the bridge instead of calling `net.socket_upgrade_tls`, because loopback fast-path sockets never have a kernel socket id. diff --git a/crates/execution/Cargo.toml b/crates/execution/Cargo.toml index c772bb9f63..f7b05b573f 100644 --- a/crates/execution/Cargo.toml +++ b/crates/execution/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Native execution plane scaffold for secure-exec" +description = "Native execution plane scaffold for agentos" build = "build.rs" # Large Pyodide runtime assets are staged at build time (copied from the # in-tree assets directory during workspace builds, or downloaded from the diff --git a/crates/execution/assets/pyodide/README.md b/crates/execution/assets/pyodide/README.md index 5a59900469..d5fb73cf19 100644 --- a/crates/execution/assets/pyodide/README.md +++ b/crates/execution/assets/pyodide/README.md @@ -1,4 +1,4 @@ -Pyodide runtime bundle for the secure-exec Python sidecar. +Pyodide runtime bundle for the agentos Python sidecar. Bundled runtime files: - `pyodide.mjs` @@ -26,7 +26,7 @@ Bundle size as vendored in this directory: Dynamic package installs: - `AGENTOS_PYODIDE_PACKAGE_BASE_URL` can override the package base used by Pyodide package resolution when a Python execution needs to install additional wheels from a network-visible host. - The bundled `micropip` wheel is still loaded from the local asset directory first so package-manager bootstrap does not depend on external network access. -- `await micropip.install("https://.../package.whl")` goes through the Python runner's bridge-backed fetch path, which means network permissions are enforced by the secure-exec kernel rather than bypassing it. +- `await micropip.install("https://.../package.whl")` goes through the Python runner's bridge-backed fetch path, which means network permissions are enforced by the agentos kernel rather than bypassing it. Debug timing output: - Set `AGENTOS_PYTHON_WARMUP_DEBUG=1` on a Python execution request to emit `__AGENTOS_PYTHON_WARMUP_METRICS__:` JSON lines on stderr. diff --git a/crates/execution/assets/runners/python-runner.mjs b/crates/execution/assets/runners/python-runner.mjs index ebea35b7f0..1a200f6825 100644 --- a/crates/execution/assets/runners/python-runner.mjs +++ b/crates/execution/assets/runners/python-runner.mjs @@ -19,13 +19,13 @@ const PYTHON_MODULE_ENV = 'AGENTOS_PYTHON_MODULE'; const PYTHON_STDIN_PROGRAM_ENV = 'AGENTOS_PYTHON_STDIN_PROGRAM'; const PYTHON_INTERACTIVE_ENV = 'AGENTOS_PYTHON_INTERACTIVE'; const PYTHON_PREWARM_ONLY_ENV = 'AGENTOS_PYTHON_PREWARM_ONLY'; +const RETAIN_LANGUAGE_CONTEXT_ENV = 'AGENTOS_RETAIN_LANGUAGE_CONTEXT'; const PYTHON_WARMUP_DEBUG_ENV = 'AGENTOS_PYTHON_WARMUP_DEBUG'; const PYTHON_WARMUP_METRICS_PREFIX = '__AGENTOS_PYTHON_WARMUP_METRICS__:'; const PYTHON_PRELOAD_PACKAGES_ENV = 'AGENTOS_PYTHON_PRELOAD_PACKAGES'; const PYTHON_VFS_RPC_REQUEST_FD_ENV = 'AGENTOS_PYTHON_VFS_RPC_REQUEST_FD'; const PYTHON_VFS_RPC_RESPONSE_FD_ENV = 'AGENTOS_PYTHON_VFS_RPC_RESPONSE_FD'; const FORWARD_KERNEL_STDIN_RPC_ENV = 'AGENTOS_FORWARD_KERNEL_STDIN_RPC'; -const PYTHON_RUNTIME_ENV_NAMES = ['HOME', 'USER', 'LOGNAME', 'SHELL', 'PWD', 'TMPDIR', 'PATH']; const INTERNAL_ENV = globalThis.__agentOSPythonInternalEnv ?? Object.create(null); const ALLOW_PROCESS_BINDINGS = readRunnerEnv('AGENTOS_ALLOW_PROCESS_BINDINGS') === '1'; const STDIN_FD = 0; @@ -408,7 +408,7 @@ async function normalizeFetchBody(body) { return Buffer.from(await body.arrayBuffer()).toString('base64'); } - throw new Error('unsupported fetch body type for secure-exec Python package loading'); + throw new Error('unsupported fetch body type for agentos Python package loading'); } function emitPythonStartupMetrics({ @@ -714,7 +714,7 @@ function createPythonFdRpcBridge() { const chunk = Buffer.alloc(4096); const bytesRead = readSync(responseFd, chunk, 0, chunk.length, null); if (bytesRead === 0) { - throw new Error('secure-exec Python VFS RPC response channel closed unexpectedly'); + throw new Error('agentos Python VFS RPC response channel closed unexpectedly'); } responseBuffer += chunk.subarray(0, bytesRead).toString('utf8'); } @@ -724,7 +724,7 @@ function createPythonFdRpcBridge() { try { return JSON.parse(line); } catch (error) { - throw new Error(`invalid secure-exec Python VFS RPC response: ${formatError(error)}`); + throw new Error(`invalid agentos Python VFS RPC response: ${formatError(error)}`); } } @@ -765,7 +765,7 @@ function createPythonFdRpcBridge() { return message.result ?? {}; } - const error = new Error(message?.error?.message || `secure-exec Python VFS RPC request ${id} failed`); + const error = new Error(message?.error?.message || `agentos Python VFS RPC request ${id} failed`); error.code = message?.error?.code || 'ERR_AGENTOS_PYTHON_VFS_RPC'; throw error; } @@ -897,7 +897,7 @@ function createPythonFdRpcBridge() { } function accessDenied(subject) { - const error = new Error(`${subject} is not available in the secure-exec guest Python runtime`); + const error = new Error(`${subject} is not available in the agentos guest Python runtime`); error.code = ACCESS_DENIED_CODE; return error; } @@ -917,9 +917,9 @@ except Exception: _agentos_safe_pyodide_js_api = None def _agentos_raise_access_denied(module_name): - raise RuntimeError(f"{module_name} is not available in the secure-exec guest Python runtime") + raise RuntimeError(f"{module_name} is not available in the agentos guest Python runtime") -class _SecureExecBlockedModule(_agentos_types.ModuleType): +class _AgentOsBlockedModule(_agentos_types.ModuleType): def __init__(self, name): super().__init__(name) self.__dict__['__all__'] = () @@ -931,7 +931,7 @@ class _SecureExecBlockedModule(_agentos_types.ModuleType): return [] _agentos_blocked_modules = { - _agentos_module_name: _SecureExecBlockedModule(_agentos_module_name) + _agentos_module_name: _AgentOsBlockedModule(_agentos_module_name) for _agentos_module_name in ('js', 'pyodide_js') } @@ -967,13 +967,13 @@ import sys as _agentos_sys import types as _agentos_types import urllib.error as _agentos_urllib_error import urllib.request as _agentos_urllib_request -from email.message import Message as _SecureExecMessage +from email.message import Message as _AgentOsMessage from js import __agentOSPythonVfsRpc as _agentos_rpc def _agentos_raise_from_error(error): if not isinstance(error, dict): raise RuntimeError(str(error)) - message = str(error.get("message", "secure-exec Python bridge request failed")) + message = str(error.get("message", "agentos Python bridge request failed")) if "EACCES:" in message: raise PermissionError(message) if "command not found" in message: @@ -998,17 +998,17 @@ def _agentos_dns_lookup(hostname, family=None): _agentos_raise_from_error({"message": str(error)}) addresses = result.get("addresses") or [] if not addresses: - raise OSError(f"secure-exec DNS lookup returned no addresses for {hostname}") + raise OSError(f"agentos DNS lookup returned no addresses for {hostname}") return addresses -class _SecureExecHttpResponse: +class _AgentOsHttpResponse: def __init__(self, payload): self.status = int(payload.get("status", 0)) self.reason = str(payload.get("reason", "")) self.url = str(payload.get("url", "")) self._body = _agentos_base64.b64decode(payload.get("bodyBase64", "") or "") headers = payload.get("headers") or {} - self.headers = _SecureExecMessage() + self.headers = _AgentOsMessage() for name, values in headers.items(): for value in values: self.headers.add_header(str(name), str(value)) @@ -1034,7 +1034,7 @@ class _SecureExecHttpResponse: self.close() return False -class _SecureExecPyfetchResponse: +class _AgentOsPyfetchResponse: def __init__(self, payload): self.status = int(payload.get("status", 0)) self.status_text = str(payload.get("reason", "")) @@ -1079,7 +1079,7 @@ def _agentos_http_request(url_or_request, data=None): ) except Exception as error: _agentos_raise_from_error({"message": str(error)}) - response = _SecureExecHttpResponse(payload) + response = _AgentOsHttpResponse(payload) if response.status >= 400: raise _agentos_urllib_error.HTTPError( url, @@ -1108,7 +1108,7 @@ async def _agentos_pyfetch(url, **kwargs): ) except Exception as error: _agentos_raise_from_error({"message": str(error)}) - return _SecureExecPyfetchResponse(payload) + return _AgentOsPyfetchResponse(payload) def _agentos_urlopen(url, data=None, timeout=None, *args, **kwargs): del timeout, args, kwargs @@ -1143,7 +1143,7 @@ def _agentos_getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): sockaddr = (address, port) results.append((entry_family, socktype, protocol, "", sockaddr)) if not results: - raise OSError(f"secure-exec DNS lookup returned no matching addresses for {host}") + raise OSError(f"agentos DNS lookup returned no matching addresses for {host}") return results def _agentos_gethostbyname(host): @@ -1178,7 +1178,7 @@ def _agentos_socket_rpc(call): except Exception as exc: raise _agentos_socket_oserror(exc) from None -class _SecureExecSocket: +class _AgentOsSocket: def __init__(self, family=None, type=None, proto=0, fileno=None): self.family = family if family is not None else _agentos_socket.AF_INET self.type = type if type is not None else _agentos_socket.SOCK_STREAM @@ -1334,12 +1334,12 @@ def _agentos_socket_factory(family=-1, type=-1, proto=0, fileno=None): and fam in (_agentos_socket.AF_INET, _agentos_socket.AF_INET6) and typ in (_agentos_socket.SOCK_STREAM, _agentos_socket.SOCK_DGRAM) ): - return _SecureExecSocket(fam, typ, proto) + return _AgentOsSocket(fam, typ, proto) return _agentos_original_socket_class(family, type, proto, fileno) _agentos_socket.socket = _agentos_socket_factory -class _SecureExecRequestsResponse: +class _AgentOsRequestsResponse: def __init__(self, payload): self.status_code = int(payload.get("status", 0)) self.reason = str(payload.get("reason", "")) @@ -1360,7 +1360,7 @@ class _SecureExecRequestsResponse: if self.status_code >= 400: raise RuntimeError(f"{self.status_code} {self.reason}") -class _SecureExecRequestsSession: +class _AgentOsRequestsSession: def request(self, method, url, **kwargs): headers = dict(kwargs.get("headers") or {}) data = kwargs.get("data") @@ -1378,16 +1378,16 @@ class _SecureExecRequestsSession: ) except Exception as error: _agentos_raise_from_error({"message": str(error)}) - return _SecureExecRequestsResponse(payload) + return _AgentOsRequestsResponse(payload) def get(self, url, **kwargs): return self.request("GET", url, **kwargs) def _agentos_install_requests_module(): module = _agentos_types.ModuleType("requests") - session = _SecureExecRequestsSession + session = _AgentOsRequestsSession module.Session = session - module.Response = _SecureExecRequestsResponse + module.Response = _AgentOsRequestsResponse module.request = lambda method, url, **kwargs: session().request(method, url, **kwargs) module.get = lambda url, **kwargs: session().get(url, **kwargs) module.exceptions = _agentos_types.SimpleNamespace(RequestException=RuntimeError) @@ -1398,12 +1398,12 @@ try: except ModuleNotFoundError: _agentos_install_requests_module() else: - _agentos_requests.Session = _SecureExecRequestsSession - _agentos_requests.Response = _SecureExecRequestsResponse - _agentos_requests.request = lambda method, url, **kwargs: _SecureExecRequestsSession().request(method, url, **kwargs) - _agentos_requests.get = lambda url, **kwargs: _SecureExecRequestsSession().get(url, **kwargs) + _agentos_requests.Session = _AgentOsRequestsSession + _agentos_requests.Response = _AgentOsRequestsResponse + _agentos_requests.request = lambda method, url, **kwargs: _AgentOsRequestsSession().request(method, url, **kwargs) + _agentos_requests.get = lambda url, **kwargs: _AgentOsRequestsSession().get(url, **kwargs) -class _SecureExecCompletedProcess: +class _AgentOsCompletedProcess: def __init__(self, args, returncode, stdout, stderr): self.args = args self.returncode = returncode @@ -1443,7 +1443,7 @@ def _agentos_subprocess_run(args, *, capture_output=False, check=False, cwd=None merged_env = dict(env or {}) resolved_cwd = cwd if cwd is not None else _agentos_os.environ.get("PWD") if input is not None: - raise NotImplementedError("subprocess.run input is not supported in the secure-exec Python runtime") + raise NotImplementedError("subprocess.run input is not supported in the agentos Python runtime") try: payload = _agentos_json.loads( _agentos_rpc.subprocessRunSync( @@ -1465,7 +1465,7 @@ def _agentos_subprocess_run(args, *, capture_output=False, check=False, cwd=None else: stdout_value = stdout_bytes stderr_value = stderr_bytes - result = _SecureExecCompletedProcess( + result = _AgentOsCompletedProcess( args, int(payload.get("exitCode", 1)), stdout_value if capture_output else None, @@ -1521,9 +1521,13 @@ function installPythonGuestImportBlocklist(pyodide) { function buildPythonRuntimeEnv() { const runtimeEnv = {}; - for (const name of PYTHON_RUNTIME_ENV_NAMES) { - if (typeof process.env[name] === 'string') { - runtimeEnv[name] = process.env[name]; + for (const [name, value] of Object.entries(process.env)) { + if ( + typeof value === 'string' && + !name.startsWith('AGENTOS_') && + !name.startsWith('NODE_SYNC_RPC_') + ) { + runtimeEnv[name] = value; } } return runtimeEnv; @@ -2429,6 +2433,7 @@ function resolvePythonSource(pyodide) { } let pythonVfsRpcBridge = null; +let retainLanguageContext = false; try { const startupStarted = realPerformance.now(); @@ -2442,6 +2447,7 @@ try { const packageCacheDir = resolvePyodidePackageCacheDir(); emitWarmupStage(`package-cache-dir:${packageCacheDir}`); const prewarmOnly = readRunnerEnv(PYTHON_PREWARM_ONLY_ENV) === '1'; + retainLanguageContext = readRunnerEnv(RETAIN_LANGUAGE_CONTEXT_ENV) === '1'; const preloadPackages = parsePreloadPackages(readRunnerEnv(PYTHON_PRELOAD_PACKAGES_ENV)); const lockFileContents = await readLockFileContents(indexPath, indexUrl).catch((error) => { throw wrapPythonStartupError('lock file read', { indexPath, indexUrl }, error); @@ -2502,6 +2508,9 @@ try { error, ); }); + if (retainLanguageContext) { + globalThis.__agentOSRetainedPyodide = pyodide; + } restorePyodideShellCompat(); emitWarmupStage('after-load-pyodide'); const loadPyodideMs = realPerformance.now() - loadPyodideStarted; @@ -2584,7 +2593,11 @@ try { writeStream(process.stderr, formatError(error)); process.exitCode = 1; } finally { - pythonVfsRpcBridge?.dispose(); + if (!retainLanguageContext) { + pythonVfsRpcBridge?.dispose(); + } emitControlMessage({ type: 'python_exit', exitCode: process.exitCode ?? 0 }); } -process.exit(process.exitCode ?? 0); +if (!retainLanguageContext) { + process.exit(process.exitCode ?? 0); +} diff --git a/crates/execution/assets/runners/wasi-module.js b/crates/execution/assets/runners/wasi-module.js index 171efbd1dd..0a9949429f 100644 --- a/crates/execution/assets/runners/wasi-module.js +++ b/crates/execution/assets/runners/wasi-module.js @@ -85,7 +85,7 @@ if (typeof globalThis !== "undefined" && typeof globalThis.__agentOSWasiModule = return; } try { - process.stderr.write(`[secure-exec-wasi] ${message}\n`); + process.stderr.write(`[agentos-wasi] ${message}\n`); } catch { // Ignore debug logging failures. } diff --git a/crates/execution/assets/runners/wasi-module.js.orig b/crates/execution/assets/runners/wasi-module.js.orig index a21b8ea079..ad24d0a4fb 100644 --- a/crates/execution/assets/runners/wasi-module.js.orig +++ b/crates/execution/assets/runners/wasi-module.js.orig @@ -76,7 +76,7 @@ if (typeof globalThis !== "undefined" && typeof globalThis.__agentOSWasiModule = return; } try { - process.stderr.write(`[secure-exec-wasi] ${message}\n`); + process.stderr.write(`[agentos-wasi] ${message}\n`); } catch { // Ignore debug logging failures. } diff --git a/crates/execution/assets/runners/wasm-runner.mjs b/crates/execution/assets/runners/wasm-runner.mjs index 6911085427..2d5d7fe799 100644 --- a/crates/execution/assets/runners/wasm-runner.mjs +++ b/crates/execution/assets/runners/wasm-runner.mjs @@ -798,7 +798,7 @@ function isProjectedCommandGuestPath(subject) { ? path.posix.normalize(raw) : path.posix.resolve(HOST_FS_GUEST_CWD, raw); return ( - /^\/__secure_exec\/commands\/\d+(?:\/|$)/u.test(guestPath) || + /^\/__agentos\/commands\/\d+(?:\/|$)/u.test(guestPath) || /^\/opt\/agentos\/bin\/[^/]+$/u.test(guestPath) ); } @@ -860,7 +860,7 @@ function projectedCommandImageBytes(command) { if (!name || name === '.' || name === '/') return null; for (const mapping of GUEST_PATH_MAPPINGS) { if ( - !/^\/__secure_exec\/commands\/\d+$/u.test(mapping?.guestPath ?? '') && + !/^\/__agentos\/commands\/\d+$/u.test(mapping?.guestPath ?? '') && mapping?.guestPath !== '/opt/agentos/bin' ) continue; const guestCandidate = path.posix.join(mapping.guestPath, name); @@ -4501,7 +4501,7 @@ function readSyncRpcLine() { const chunk = Buffer.alloc(4096); const bytesRead = readSync(NODE_SYNC_RPC_RESPONSE_FD, chunk, 0, chunk.length, null); if (bytesRead === 0) { - throw new Error('secure-exec WASM sync RPC response channel closed unexpectedly'); + throw new Error('agentos WASM sync RPC response channel closed unexpectedly'); } syncRpcResponseBuffer += chunk.subarray(0, bytesRead).toString('utf8'); } @@ -4529,7 +4529,7 @@ function callSyncRpc(method, args = []) { } if (!NODE_SYNC_RPC_ENABLE || NODE_SYNC_RPC_REQUEST_FD == null || NODE_SYNC_RPC_RESPONSE_FD == null) { - const error = new Error(`secure-exec WASM sync RPC is unavailable for ${method}`); + const error = new Error(`agentos WASM sync RPC is unavailable for ${method}`); error.code = 'ERR_AGENTOS_WASM_SYNC_RPC_UNAVAILABLE'; throw error; } @@ -4549,7 +4549,7 @@ function callSyncRpc(method, args = []) { } const error = new Error( - response?.error?.message || `secure-exec WASM sync RPC ${method} failed`, + response?.error?.message || `agentos WASM sync RPC ${method} failed`, ); if (typeof response?.error?.code === 'string') { error.code = response.error.code; @@ -12573,7 +12573,7 @@ function resetCaughtWasmSignalDispositionsForExec(sidecarCommitted) { } } -Object.defineProperty(globalThis, '__secureExecWasmSignalDispatch', { +Object.defineProperty(globalThis, '__agentOsWasmSignalDispatch', { configurable: true, writable: true, value: (_eventType, payload) => { diff --git a/crates/execution/assets/undici-shims/async_hooks.js b/crates/execution/assets/undici-shims/async_hooks.js index 5cf4ad48e4..ca09cf8fe1 100644 --- a/crates/execution/assets/undici-shims/async_hooks.js +++ b/crates/execution/assets/undici-shims/async_hooks.js @@ -48,7 +48,7 @@ class AsyncLocalStorage { } class AsyncResource { - constructor(type = "SecureExecAsyncResource") { + constructor(type = "AgentOsAsyncResource") { this.type = type; } diff --git a/crates/execution/assets/undici-shims/http2.js b/crates/execution/assets/undici-shims/http2.js index d6bc80355e..9d055a1209 100644 --- a/crates/execution/assets/undici-shims/http2.js +++ b/crates/execution/assets/undici-shims/http2.js @@ -19,7 +19,7 @@ const constants = { }; function notImplemented(name) { - const error = new Error(`node:http2 ${name} is not available in the secure-exec bridge bootstrap`); + const error = new Error(`node:http2 ${name} is not available in the agentos bridge bootstrap`); error.code = "ERR_NOT_IMPLEMENTED"; throw error; } diff --git a/crates/execution/assets/undici-shims/stream.js b/crates/execution/assets/undici-shims/stream.js index 875ee53a21..524c6c21d4 100644 --- a/crates/execution/assets/undici-shims/stream.js +++ b/crates/execution/assets/undici-shims/stream.js @@ -1,6 +1,6 @@ "use strict"; -import streamDefault, * as streamNs from "secure-exec-stream-stdlib"; +import streamDefault, * as streamNs from "agentos-stream-stdlib"; import { Buffer } from "node:buffer"; const baseStreamModule = streamNs.default ?? streamDefault ?? {}; @@ -130,7 +130,7 @@ export const isDisturbed = (stream) => { ); }; -export * from "secure-exec-stream-stdlib"; +export * from "agentos-stream-stdlib"; export default { ...baseStreamModule, diff --git a/crates/execution/assets/undici-shims/zlib.js b/crates/execution/assets/undici-shims/zlib.js index 3af356f1b5..ef6275d914 100644 --- a/crates/execution/assets/undici-shims/zlib.js +++ b/crates/execution/assets/undici-shims/zlib.js @@ -1,7 +1,7 @@ "use strict"; function getZlibModule() { - const mod = globalThis.__secureExecBuiltinZlibModule; + const mod = globalThis.__agentOsBuiltinZlibModule; if (!mod) { throw new Error("node:zlib bridge module is not available"); } diff --git a/crates/execution/benchmarks/node-import-baseline.md b/crates/execution/benchmarks/node-import-baseline.md index 760df0c6e9..9b6b24b385 100644 --- a/crates/execution/benchmarks/node-import-baseline.md +++ b/crates/execution/benchmarks/node-import-baseline.md @@ -1,4 +1,4 @@ -# secure-exec Node Import Benchmark +# agentos Node Import Benchmark - Generated at unix ms: `1775118070728` - Node binary: `node` diff --git a/crates/execution/build.rs b/crates/execution/build.rs index 6a26a76cde..c99e47ffb0 100644 --- a/crates/execution/build.rs +++ b/crates/execution/build.rs @@ -1,4 +1,5 @@ use std::env; +use std::fmt::Write as _; use std::fs; use std::path::{Path, PathBuf}; @@ -31,8 +32,73 @@ fn main() { // Declare the cfg used to gate Python availability so `cargo` does not warn // about an unexpected cfg name. println!("cargo:rustc-check-cfg=cfg(agentos_pyodide_unavailable)"); + println!("cargo:rustc-check-cfg=cfg(agentos_typescript_unavailable)"); agentos_build_support::build_v8_bridge(&manifest_dir, &out_dir); stage_pyodide_assets(&manifest_dir, &out_dir); + stage_typescript_assets(&manifest_dir, &out_dir); +} + +fn stage_typescript_assets(manifest_dir: &Path, out_dir: &Path) { + let source_dir = manifest_dir.join("../../node_modules/typescript/lib"); + let staged_dir = out_dir.join("typescript"); + let generated_path = out_dir.join("typescript_assets.rs"); + println!("cargo:rerun-if-changed={}", source_dir.display()); + fs::create_dir_all(&staged_dir).unwrap_or_else(|error| { + panic!( + "failed to create TypeScript staging dir {}: {error}", + staged_dir.display() + ) + }); + + let mut assets = Vec::new(); + if let Ok(entries) = fs::read_dir(&source_dir) { + for entry in entries { + let entry = entry.unwrap_or_else(|error| { + panic!("failed to read TypeScript compiler asset entry: {error}") + }); + let path = entry.path(); + let Some(file_name) = path.file_name().and_then(|name| name.to_str()) else { + continue; + }; + if file_name != "typescript.js" + && !(file_name.starts_with("lib.") && file_name.ends_with(".d.ts")) + { + continue; + } + let destination = staged_dir.join(file_name); + fs::copy(&path, &destination).unwrap_or_else(|error| { + panic!( + "failed to stage TypeScript compiler asset {}: {error}", + path.display() + ) + }); + assets.push(file_name.to_owned()); + } + } + assets.sort(); + + if !assets.iter().any(|asset| asset == "typescript.js") { + println!("cargo:rustc-cfg=agentos_typescript_unavailable"); + println!( + "cargo:warning=agentos-execution: building without the bundled TypeScript compiler; guest TypeScript checking will be unavailable in this build." + ); + } + + let mut generated = String::from("&[\n"); + for asset in assets { + writeln!( + generated, + " ({asset:?}, include_bytes!(concat!(env!(\"OUT_DIR\"), \"/typescript/{asset}\")) as &'static [u8])," + ) + .expect("writing generated TypeScript asset table cannot fail"); + } + generated.push_str("]\n"); + fs::write(&generated_path, generated).unwrap_or_else(|error| { + panic!( + "failed to write TypeScript asset table {}: {error}", + generated_path.display() + ) + }); } fn stage_pyodide_assets(manifest_dir: &Path, out_dir: &Path) { diff --git a/crates/execution/src/benchmark.rs b/crates/execution/src/benchmark.rs index cb406362c3..be426a539b 100644 --- a/crates/execution/src/benchmark.rs +++ b/crates/execution/src/benchmark.rs @@ -195,7 +195,7 @@ impl JavascriptBenchmarkReport { comparison: Option<&BenchmarkComparison>, ) -> String { let mut markdown = String::new(); - let _ = writeln!(&mut markdown, "# secure-exec Node Import Benchmark"); + let _ = writeln!(&mut markdown, "# agentos Node Import Benchmark"); let _ = writeln!(&mut markdown); let _ = writeln!( &mut markdown, @@ -3061,25 +3061,25 @@ fn projected_package_import_entrypoint_source() -> String { fn pdf_lib_startup_entrypoint_source() -> String { timed_entrypoint_source( - "const pdfLib = await import('pdf-lib');\nconst pdfDoc = await pdfLib.PDFDocument.create();\nconst page = pdfDoc.addPage([612, 792]);\nconst font = await pdfDoc.embedFont(pdfLib.StandardFonts.Helvetica);\npage.drawText('secure-exec pdf-lib benchmark', {\n x: 50,\n y: 750,\n font,\n size: 18,\n});\nif (pdfDoc.getPageCount() !== 1 || page.getSize().width !== 612) {\n throw new Error('pdf-lib fixture did not create the expected document');\n}", + "const pdfLib = await import('pdf-lib');\nconst pdfDoc = await pdfLib.PDFDocument.create();\nconst page = pdfDoc.addPage([612, 792]);\nconst font = await pdfDoc.embedFont(pdfLib.StandardFonts.Helvetica);\npage.drawText('agentos pdf-lib benchmark', {\n x: 50,\n y: 750,\n font,\n size: 18,\n});\nif (pdfDoc.getPageCount() !== 1 || page.getSize().width !== 612) {\n throw new Error('pdf-lib fixture did not create the expected document');\n}", ) } fn jszip_startup_entrypoint_source() -> String { timed_entrypoint_source( - "const jszipModule = await import('jszip');\nconst JSZip = jszipModule.default ?? jszipModule;\nconst zip = new JSZip();\nzip.file('README.txt', 'secure-exec benchmark archive');\nconst notes = zip.folder('notes');\nif (!notes) {\n throw new Error('jszip fixture failed to create nested folder');\n}\nnotes.file('todo.txt', 'benchmark staging payload');\nconst fileCount = Object.values(zip.files).filter((entry) => !entry.dir).length;\nif (typeof zip.generateAsync !== 'function' || fileCount !== 2) {\n throw new Error('jszip fixture did not stage the expected archive');\n}", + "const jszipModule = await import('jszip');\nconst JSZip = jszipModule.default ?? jszipModule;\nconst zip = new JSZip();\nzip.file('README.txt', 'agentos benchmark archive');\nconst notes = zip.folder('notes');\nif (!notes) {\n throw new Error('jszip fixture failed to create nested folder');\n}\nnotes.file('todo.txt', 'benchmark staging payload');\nconst fileCount = Object.values(zip.files).filter((entry) => !entry.dir).length;\nif (typeof zip.generateAsync !== 'function' || fileCount !== 2) {\n throw new Error('jszip fixture did not stage the expected archive');\n}", ) } fn jszip_end_to_end_entrypoint_source() -> String { timed_entrypoint_source( - "const jszipModule = await import('jszip');\nconst JSZip = jszipModule.default ?? jszipModule;\nconst zip = new JSZip();\nconst repeatedPayload = 'secure-exec benchmark payload '.repeat(512);\nzip.file('README.txt', repeatedPayload);\nconst notes = zip.folder('notes');\nif (!notes) {\n throw new Error('jszip end-to-end fixture failed to create notes folder');\n}\nnotes.file('todo.txt', 'complete the archive roundtrip');\nconst data = zip.folder('data');\nif (!data) {\n throw new Error('jszip end-to-end fixture failed to create data folder');\n}\ndata.file('payload.json', JSON.stringify({\n repeatedPayloadLength: repeatedPayload.length,\n mode: 'cold-end-to-end',\n}));\nconst archiveBytes = await zip.generateAsync({\n type: 'uint8array',\n compression: 'DEFLATE',\n compressionOptions: { level: 6 },\n});\nconst restored = await JSZip.loadAsync(archiveBytes);\nconst restoredFileCount = Object.values(restored.files).filter((entry) => !entry.dir).length;\nconst restoredReadme = await restored.file('README.txt')?.async('string');\nconst restoredTodo = await restored.file('notes/todo.txt')?.async('string');\nconst restoredPayload = await restored.file('data/payload.json')?.async('string');\nif (\n archiveBytes.byteLength >= repeatedPayload.length ||\n restoredFileCount !== 3 ||\n restoredReadme !== repeatedPayload ||\n restoredTodo !== 'complete the archive roundtrip' ||\n !restoredPayload?.includes('cold-end-to-end')\n) {\n throw new Error('jszip end-to-end fixture did not complete the compressed archive roundtrip');\n}", + "const jszipModule = await import('jszip');\nconst JSZip = jszipModule.default ?? jszipModule;\nconst zip = new JSZip();\nconst repeatedPayload = 'agentos benchmark payload '.repeat(512);\nzip.file('README.txt', repeatedPayload);\nconst notes = zip.folder('notes');\nif (!notes) {\n throw new Error('jszip end-to-end fixture failed to create notes folder');\n}\nnotes.file('todo.txt', 'complete the archive roundtrip');\nconst data = zip.folder('data');\nif (!data) {\n throw new Error('jszip end-to-end fixture failed to create data folder');\n}\ndata.file('payload.json', JSON.stringify({\n repeatedPayloadLength: repeatedPayload.length,\n mode: 'cold-end-to-end',\n}));\nconst archiveBytes = await zip.generateAsync({\n type: 'uint8array',\n compression: 'DEFLATE',\n compressionOptions: { level: 6 },\n});\nconst restored = await JSZip.loadAsync(archiveBytes);\nconst restoredFileCount = Object.values(restored.files).filter((entry) => !entry.dir).length;\nconst restoredReadme = await restored.file('README.txt')?.async('string');\nconst restoredTodo = await restored.file('notes/todo.txt')?.async('string');\nconst restoredPayload = await restored.file('data/payload.json')?.async('string');\nif (\n archiveBytes.byteLength >= repeatedPayload.length ||\n restoredFileCount !== 3 ||\n restoredReadme !== repeatedPayload ||\n restoredTodo !== 'complete the archive roundtrip' ||\n !restoredPayload?.includes('cold-end-to-end')\n) {\n throw new Error('jszip end-to-end fixture did not complete the compressed archive roundtrip');\n}", ) } fn jszip_repeated_session_compressed_entrypoint_source() -> String { timed_entrypoint_source( - "const jszipModule = await import('jszip');\nconst JSZip = jszipModule.default ?? jszipModule;\nconst zip = new JSZip();\nconst repeatedPayload = 'secure-exec benchmark payload '.repeat(512);\nzip.file('README.txt', repeatedPayload);\nconst notes = zip.folder('notes');\nif (!notes) {\n throw new Error('jszip repeated-session fixture failed to create notes folder');\n}\nnotes.file('todo.txt', 'repeat this session workload');\nconst data = zip.folder('data');\nif (!data) {\n throw new Error('jszip repeated-session fixture failed to create data folder');\n}\ndata.file('payload.json', JSON.stringify({\n repeatedPayloadLength: repeatedPayload.length,\n repeatedSessions: true,\n}));\nconst archiveBytes = await zip.generateAsync({\n type: 'uint8array',\n compression: 'DEFLATE',\n compressionOptions: { level: 6 },\n});\nconst restored = await JSZip.loadAsync(archiveBytes);\nconst restoredFileCount = Object.values(restored.files).filter((entry) => !entry.dir).length;\nconst restoredReadme = await restored.file('README.txt')?.async('string');\nconst restoredTodo = await restored.file('notes/todo.txt')?.async('string');\nif (\n archiveBytes.byteLength >= repeatedPayload.length ||\n restoredFileCount !== 3 ||\n restoredReadme !== repeatedPayload ||\n restoredTodo !== 'repeat this session workload'\n) {\n throw new Error('jszip repeated-session fixture did not complete the compressed archive roundtrip');\n}", + "const jszipModule = await import('jszip');\nconst JSZip = jszipModule.default ?? jszipModule;\nconst zip = new JSZip();\nconst repeatedPayload = 'agentos benchmark payload '.repeat(512);\nzip.file('README.txt', repeatedPayload);\nconst notes = zip.folder('notes');\nif (!notes) {\n throw new Error('jszip repeated-session fixture failed to create notes folder');\n}\nnotes.file('todo.txt', 'repeat this session workload');\nconst data = zip.folder('data');\nif (!data) {\n throw new Error('jszip repeated-session fixture failed to create data folder');\n}\ndata.file('payload.json', JSON.stringify({\n repeatedPayloadLength: repeatedPayload.length,\n repeatedSessions: true,\n}));\nconst archiveBytes = await zip.generateAsync({\n type: 'uint8array',\n compression: 'DEFLATE',\n compressionOptions: { level: 6 },\n});\nconst restored = await JSZip.loadAsync(archiveBytes);\nconst restoredFileCount = Object.values(restored.files).filter((entry) => !entry.dir).length;\nconst restoredReadme = await restored.file('README.txt')?.async('string');\nconst restoredTodo = await restored.file('notes/todo.txt')?.async('string');\nif (\n archiveBytes.byteLength >= repeatedPayload.length ||\n restoredFileCount !== 3 ||\n restoredReadme !== repeatedPayload ||\n restoredTodo !== 'repeat this session workload'\n) {\n throw new Error('jszip repeated-session fixture did not complete the compressed archive roundtrip');\n}", ) } diff --git a/crates/execution/src/javascript.rs b/crates/execution/src/javascript.rs index d71e776327..184e4957cd 100644 --- a/crates/execution/src/javascript.rs +++ b/crates/execution/src/javascript.rs @@ -46,6 +46,10 @@ const NODE_IMPORT_CACHE_PATH_ENV: &str = "AGENTOS_NODE_IMPORT_CACHE_PATH"; const NODE_KEEP_STDIN_OPEN_ENV: &str = "AGENTOS_KEEP_STDIN_OPEN"; const NODE_GUEST_ENTRYPOINT_ENV: &str = "AGENTOS_GUEST_ENTRYPOINT"; const NODE_GUEST_ENTRYPOINT_MODULE_MODE_ENV: &str = "AGENTOS_GUEST_ENTRYPOINT_MODULE_MODE"; +const NODE_RETAIN_CONTEXT_ENV: &str = "AGENTOS_RETAIN_LANGUAGE_CONTEXT"; +const NODE_INLINE_FILE_PATH_ENV: &str = "AGENTOS_INLINE_FILE_PATH"; +const NODE_USE_BUNDLED_TYPESCRIPT_ENV: &str = "AGENTOS_USE_BUNDLED_TYPESCRIPT"; +const NODE_TYPESCRIPT_COMPILER_PATH_ENV: &str = "AGENTOS_TYPESCRIPT_COMPILER_PATH"; const NODE_GUEST_PATH_MAPPINGS_ENV: &str = "AGENTOS_GUEST_PATH_MAPPINGS"; const NODE_VIRTUAL_PROCESS_EXEC_PATH_ENV: &str = "AGENTOS_VIRTUAL_PROCESS_EXEC_PATH"; const NODE_VIRTUAL_PROCESS_PID_ENV: &str = "AGENTOS_VIRTUAL_PROCESS_PID"; @@ -161,10 +165,10 @@ const JAVASCRIPT_CAPTURED_OUTPUT_LIMIT_BYTES: usize = 16 * 1024 * 1024; const KERNEL_STDIN_BUFFER_LIMIT_BYTES: usize = 16 * 1024 * 1024; const NODE_WARMUP_MARKER_VERSION: &str = "1"; const NODE_WARMUP_SPECIFIERS: &[&str] = &[ - "secure-exec:builtin/path", - "secure-exec:builtin/url", - "secure-exec:builtin/fs-promises", - "secure-exec:polyfill/path", + "agentos:builtin/path", + "agentos:builtin/url", + "agentos:builtin/fs-promises", + "agentos:polyfill/path", ]; #[derive(Debug, Default, Clone)] @@ -261,6 +265,7 @@ const RESERVED_NODE_ENV_KEYS: &[&str] = &[ NODE_FROZEN_TIME_ENV, NODE_GUEST_ENTRYPOINT_ENV, NODE_GUEST_ENTRYPOINT_MODULE_MODE_ENV, + NODE_INLINE_FILE_PATH_ENV, NODE_GUEST_ARGV_ENV, NODE_GUEST_PATH_MAPPINGS_ENV, NODE_VIRTUAL_PROCESS_EXEC_PATH_ENV, @@ -274,6 +279,9 @@ const RESERVED_NODE_ENV_KEYS: &[&str] = &[ NODE_IMPORT_CACHE_LOADER_PATH_ENV, NODE_IMPORT_CACHE_PATH_ENV, NODE_KEEP_STDIN_OPEN_ENV, + NODE_RETAIN_CONTEXT_ENV, + NODE_USE_BUNDLED_TYPESCRIPT_ENV, + NODE_TYPESCRIPT_COMPILER_PATH_ENV, NODE_ALLOWED_BUILTINS_ENV, NODE_LOOPBACK_EXEMPT_PORTS_ENV, NODE_SYNC_RPC_ENABLE_ENV, @@ -1848,6 +1856,31 @@ impl JavascriptExecution { self.exited.load(Ordering::Acquire) } + /// Run another sidecar-managed operation in this execution's retained V8 + /// context. Public clients submit semantic language requests; only the + /// sidecar calls this executor primitive. + pub fn execute_retained( + &mut self, + user_code: String, + file_path: String, + module: bool, + ) -> Result<(), JavascriptExecutionError> { + self.exited.store(false, Ordering::Release); + self.kernel_stdin.reset(); + self.v8_session + .execute( + 2 | u8::from(module), + file_path, + String::new(), + String::new(), + String::new(), + false, + user_code, + None, + ) + .map_err(JavascriptExecutionError::Spawn) + } + /// Enqueue a replacement image that was fully prepared without running /// guest code. This is the final step of an atomic cross-runtime execve and /// must only be called after the kernel and sidecar process state commit. @@ -2777,12 +2810,18 @@ impl JavascriptExecutionEngine { // synthetic resource name so its dynamic-import callback has the same // resolution base instead of trying to resolve from the literal `-e`. let execution_file_path = if matches!(guest_entrypoint.as_str(), "-e" | "--eval") { - let cwd = translator.guest_cwd().trim_end_matches('/'); - if cwd.is_empty() { - String::from("/[eval]") - } else { - format!("{cwd}/[eval]") - } + request + .env + .get(NODE_INLINE_FILE_PATH_ENV) + .cloned() + .unwrap_or_else(|| { + let cwd = translator.guest_cwd().trim_end_matches('/'); + if cwd.is_empty() { + String::from("/[eval]") + } else { + format!("{cwd}/[eval]") + } + }) } else { guest_entrypoint.clone() }; @@ -2891,8 +2930,12 @@ impl JavascriptExecutionEngine { record_js_start_phase("js_start_install_module_reader", phase_start.elapsed()); let phase_start = Instant::now(); + let retain_context = request + .env + .get(NODE_RETAIN_CONTEXT_ENV) + .is_some_and(|value| value == "1" || value.eq_ignore_ascii_case("true")); let prepared_execute = PreparedJavascriptExecute { - mode: if use_module_mode { 1 } else { 0 }, + mode: u8::from(use_module_mode) | if retain_context { 2 } else { 0 }, file_path: execution_file_path, bridge_code: V8RuntimeHost::bridge_code().to_owned(), post_restore_script: String::new(), @@ -5223,6 +5266,12 @@ fn hex_digit(byte: u8) -> Option { } impl LocalKernelStdinBridge { + fn reset(&self) { + let mut state = self.state.lock().expect("kernel stdin state poisoned"); + state.bytes.clear(); + state.closed = false; + } + fn write(&self, chunk: &[u8]) -> Result<(), JavascriptExecutionError> { let mut state = self.state.lock().expect("kernel stdin state poisoned"); if state.closed { @@ -5470,10 +5519,10 @@ fn polyfill_expression(request: &str) -> Option { format!( "(() => {{ const error = new Error({message}); error.code = {code}; throw error; }})()", message = serde_json::to_string(&format!( - "node:{normalized} is not available in the secure-exec guest runtime" + "node:{normalized} is not available in the agentos guest runtime" )) .unwrap_or_else(|_| format!( - "\"node:{normalized} is not available in the secure-exec guest runtime\"" + "\"node:{normalized} is not available in the agentos guest runtime\"" )), code = serde_json::to_string(error_code) .unwrap_or_else(|_| "\"ERR_ACCESS_DENIED\"".to_owned()) @@ -7264,11 +7313,11 @@ export default { if module_name == "vm" { return String::from( - r#"const VM_CONTEXT_TAG = typeof Symbol === "function" ? Symbol.for("secure-exec.vm.context") : "__secure_exec_vm_context__"; -const VM_CONTEXT_ID = typeof Symbol === "function" ? Symbol.for("secure-exec.vm.context.id") : "__secure_exec_vm_context_id__"; + r#"const VM_CONTEXT_TAG = typeof Symbol === "function" ? Symbol.for("agentos.vm.context") : "__agentos_vm_context__"; +const VM_CONTEXT_ID = typeof Symbol === "function" ? Symbol.for("agentos.vm.context.id") : "__agentos_vm_context_id__"; function createVmNotImplementedError(feature) { - const error = new Error(`node:vm ${feature} is not implemented in the secure-exec guest runtime`); + const error = new Error(`node:vm ${feature} is not implemented in the agentos guest runtime`); error.code = "ERR_NOT_IMPLEMENTED"; return error; } @@ -7406,7 +7455,7 @@ export default { Script, compileFunction, createContext, isContext, measureMemor if module_name == "worker_threads" { return String::from( r#"function createNotImplementedError(feature) { - const error = new Error(`node:worker_threads ${feature} is not available in the secure-exec guest runtime`); + const error = new Error(`node:worker_threads ${feature} is not available in the agentos guest runtime`); error.code = "ERR_NOT_IMPLEMENTED"; return error; } @@ -7460,7 +7509,7 @@ function setEnvironmentData() {} export const BroadcastChannel = globalThis.BroadcastChannel; export { MessageChannel, MessagePort, Worker, getEnvironmentData, markAsUncloneable, markAsUntransferable, moveMessagePortToContext, postMessageToThread, receiveMessageOnPort, setEnvironmentData }; -export const SHARE_ENV = Symbol.for("secure-exec.worker_threads.SHARE_ENV"); +export const SHARE_ENV = Symbol.for("agentos.worker_threads.SHARE_ENV"); export const isMainThread = true; export const parentPort = null; export const resourceLimits = {}; @@ -8761,7 +8810,7 @@ mod tests { .expect("system time") .as_nanos(); let root = std::env::temp_dir().join(format!( - "secure-exec-module-bridge-{}-{unique}", + "agentos-module-bridge-{}-{unique}", std::process::id() )); let bin_dir = root.join("node_modules/next/dist/bin"); diff --git a/crates/execution/src/lib.rs b/crates/execution/src/lib.rs index ba69788fac..737551c1e5 100644 --- a/crates/execution/src/lib.rs +++ b/crates/execution/src/lib.rs @@ -1,6 +1,6 @@ #![forbid(unsafe_code)] -//! Native execution plane scaffold for the secure-exec runtime migration. +//! Native execution plane scaffold for the agentos runtime migration. mod common; mod host_node; @@ -28,6 +28,8 @@ pub use javascript::{ LocalModuleResolutionCache, LocalResolvedModuleFormat, ModuleFsReader, ModuleResolveMode, ModuleResolver, StartJavascriptExecutionRequest, }; +#[doc(hidden)] +pub use node_import_cache::bundled_typescript_assets; pub use python::{ CreatePythonContextRequest, PythonContext, PythonExecution, PythonExecutionEngine, PythonExecutionError, PythonExecutionEvent, PythonExecutionLimits, PythonExecutionResult, diff --git a/crates/execution/src/node_import_cache.rs b/crates/execution/src/node_import_cache.rs index 8cc1a04bd8..0cebdb3ece 100644 --- a/crates/execution/src/node_import_cache.rs +++ b/crates/execution/src/node_import_cache.rs @@ -21,13 +21,13 @@ const NODE_IMPORT_CACHE_SCHEMA_VERSION: &str = "1"; const NODE_IMPORT_CACHE_LOADER_VERSION: &str = "8"; // Upstream reached 104 while the reactor branch independently changed bundled // assets; use a new generation so no stale materialization survives the merge. -const NODE_IMPORT_CACHE_ASSET_VERSION: &str = "105"; +const NODE_IMPORT_CACHE_ASSET_VERSION: &str = "106"; const NODE_IMPORT_CACHE_DIR_PREFIX: &str = "agentos-node-import-cache"; const DEFAULT_NODE_IMPORT_CACHE_MATERIALIZE_TIMEOUT: Duration = Duration::from_secs(30); const NODE_IMPORT_CACHE_BLOCKING_JOB_RESERVATION_BYTES: usize = 64 * 1024; const PYODIDE_DIST_DIR: &str = "pyodide-dist"; -const AGENTOS_BUILTIN_SPECIFIER_PREFIX: &str = "secure-exec:builtin/"; -const AGENTOS_POLYFILL_SPECIFIER_PREFIX: &str = "secure-exec:polyfill/"; +const AGENTOS_BUILTIN_SPECIFIER_PREFIX: &str = "agentos:builtin/"; +const AGENTOS_POLYFILL_SPECIFIER_PREFIX: &str = "agentos:polyfill/"; const BUNDLED_PYODIDE_MJS: &[u8] = include_bytes!("../assets/pyodide/pyodide.mjs"); // Large Pyodide assets are excluded from the published crate and staged into // OUT_DIR by build.rs (copied from `assets/pyodide/` in-tree, or downloaded @@ -57,6 +57,14 @@ const BUNDLED_MICROPIP_WHL: &[u8] = const BUNDLED_CLICK_WHL: &[u8] = include_bytes!("../assets/pyodide/click-8.3.1-py3-none-any.whl"); const NODE_PYTHON_RUNNER_SOURCE: &str = include_str!("../assets/runners/python-runner.mjs"); +const BUNDLED_TYPESCRIPT_ASSETS: &[(&str, &[u8])] = + include!(concat!(env!("OUT_DIR"), "/typescript_assets.rs")); + +#[doc(hidden)] +pub fn bundled_typescript_assets() -> &'static [(&'static str, &'static [u8])] { + BUNDLED_TYPESCRIPT_ASSETS +} + static CLEANED_NODE_IMPORT_CACHE_ROOTS: OnceLock>> = OnceLock::new(); #[cfg(test)] static NODE_IMPORT_CACHE_TEST_MATERIALIZE_DELAY_MS: AtomicU64 = AtomicU64::new(0); @@ -215,7 +223,7 @@ export async function resolve(specifier, context, nextResolve) { metrics.resolveMisses += 1; - const asset = resolveSecureExecAsset(specifier); + const asset = resolveAgentOsAsset(specifier); if (asset) { cacheState.resolutions[key] = { kind: 'explicit-file', @@ -640,7 +648,7 @@ function loadProjectedPackageSource(url, filePath, format) { return source; } -function resolveSecureExecAsset(specifier) { +function resolveAgentOsAsset(specifier) { if (typeof specifier !== 'string' || !ASSET_ROOT) { return null; } @@ -2900,7 +2908,7 @@ fn render_fs_builtin_asset_source(init_counter_key: &str) -> String { globalThis[{init_counter_key}] = initCount;\n\ const mod = globalThis.__agentOSBuiltinFs ?? globalThis.__agentOSGuestFs ?? process.getBuiltinModule?.(\"node:fs\");\n\ if (!mod) {{\n\ - throw new Error('secure-exec guest fs polyfill was not initialized');\n\ + throw new Error('agentos guest fs polyfill was not initialized');\n\ }}\n\n\ export const __agentOSInitCount = initCount;\n\ export default mod;\n\ @@ -2989,7 +2997,7 @@ fn render_fs_promises_builtin_asset_source(init_counter_key: &str) -> String { let init_counter_key = format!("{init_counter_key:?}"); format!( - "import fsModule from \"secure-exec:builtin/fs\";\n\n\ + "import fsModule from \"agentos:builtin/fs\";\n\n\ const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ const mod = fsModule.promises;\n\n\ @@ -3065,7 +3073,7 @@ class AsyncLocalStorage {{\n\ }}\n\ \n\ class AsyncResource {{\n\ - constructor(type = 'SecureExecAsyncResource') {{\n\ + constructor(type = 'AgentOsAsyncResource') {{\n\ this.type = type;\n\ }}\n\ emitBefore() {{}}\n\ @@ -3123,7 +3131,7 @@ fn render_child_process_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinChildProcess) {{\n\ - const error = new Error(\"node:child_process is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:child_process is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3150,7 +3158,7 @@ fn render_net_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinNet) {{\n\ - const error = new Error(\"node:net is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:net is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3183,7 +3191,7 @@ fn render_dgram_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinDgram) {{\n\ - const error = new Error(\"node:dgram is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:dgram is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3324,7 +3332,7 @@ fn render_dns_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinDns) {{\n\ - const error = new Error(\"node:dns is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:dns is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3358,7 +3366,7 @@ fn render_dns_promises_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinDns) {{\n\ - const error = new Error(\"node:dns/promises is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:dns/promises is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3391,7 +3399,7 @@ fn render_http_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinHttp) {{\n\ - const error = new Error(\"node:http is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:http is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3425,7 +3433,7 @@ fn render_http2_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinHttp2) {{\n\ - const error = new Error(\"node:http2 is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:http2 is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3455,7 +3463,7 @@ fn render_https_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinHttps) {{\n\ - const error = new Error(\"node:https is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:https is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3479,7 +3487,7 @@ fn render_tls_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinTls) {{\n\ - const error = new Error(\"node:tls is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:tls is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3514,7 +3522,7 @@ fn render_os_builtin_asset_source(init_counter_key: &str) -> String { const initCount = (globalThis[{init_counter_key}] ?? 0) + 1;\n\ globalThis[{init_counter_key}] = initCount;\n\ if (!globalThis.__agentOSBuiltinOs) {{\n\ - const error = new Error(\"node:os is not available in the secure-exec guest runtime\");\n\ + const error = new Error(\"node:os is not available in the agentos guest runtime\");\n\ error.code = ACCESS_DENIED_CODE;\n\ throw error;\n\ }}\n\n\ @@ -3555,7 +3563,7 @@ fn render_v8_builtin_asset_source(init_counter_key: &str) -> String { globalThis[{init_counter_key}] = initCount;\n\ const mod = process.getBuiltinModule?.(\"node:v8\");\n\ if (!mod) {{\n\ - throw new Error(\"secure-exec guest v8 compatibility module was not initialized\");\n\ + throw new Error(\"agentos guest v8 compatibility module was not initialized\");\n\ }}\n\n\ export const __agentOSInitCount = initCount;\n\ export default mod;\n\ @@ -3591,7 +3599,7 @@ fn render_vm_builtin_asset_source(init_counter_key: &str) -> String { globalThis[{init_counter_key}] = initCount;\n\ const mod = process.getBuiltinModule?.(\"node:vm\");\n\ if (!mod) {{\n\ - throw new Error(\"secure-exec guest vm compatibility module was not initialized\");\n\ + throw new Error(\"agentos guest vm compatibility module was not initialized\");\n\ }}\n\n\ export const __agentOSInitCount = initCount;\n\ export default mod;\n\ @@ -3611,7 +3619,7 @@ fn render_worker_threads_builtin_asset_source(init_counter_key: &str) -> String globalThis[{init_counter_key}] = initCount;\n\ \n\ function createNotImplementedError(feature) {{\n\ - const error = new Error(`node:worker_threads ${{feature}} is not available in the secure-exec guest runtime`);\n\ + const error = new Error(`node:worker_threads ${{feature}} is not available in the agentos guest runtime`);\n\ error.code = \"ERR_NOT_IMPLEMENTED\";\n\ return error;\n\ }}\n\ @@ -3667,7 +3675,7 @@ const mod = {{\n\ BroadcastChannel: globalThis.BroadcastChannel,\n\ MessageChannel,\n\ MessagePort,\n\ - SHARE_ENV: Symbol.for(\"secure-exec.worker_threads.SHARE_ENV\"),\n\ + SHARE_ENV: Symbol.for(\"agentos.worker_threads.SHARE_ENV\"),\n\ Worker,\n\ getEnvironmentData,\n\ isMainThread: true,\n\ @@ -3706,7 +3714,7 @@ export const workerData = mod.workerData;\n" } fn render_denied_asset_source(module_specifier: &str) -> String { - let message = format!("{module_specifier} is not available in the secure-exec guest runtime"); + let message = format!("{module_specifier} is not available in the agentos guest runtime"); format!( "const error = new Error({message:?});\nerror.code = \"ERR_ACCESS_DENIED\";\nthrow error;\n" ) diff --git a/crates/execution/src/python.rs b/crates/execution/src/python.rs index b976b0feb5..2cb9eada5b 100644 --- a/crates/execution/src/python.rs +++ b/crates/execution/src/python.rs @@ -520,6 +520,22 @@ impl PythonExecution { self.inner.uses_shared_v8_runtime() } + /// Run another sidecar-managed operation in the retained Pyodide + /// interpreter owned by this execution. + pub fn execute_retained(&mut self, source: String) -> Result<(), PythonExecutionError> { + let source = serde_json::to_string(&source).map_err(|error| { + PythonExecutionError::Control(std::io::Error::other(format!( + "failed to encode retained Python source: {error}" + ))) + })?; + let runner = format!( + "process.exitCode = 0; (async () => {{ const pyodide = globalThis.__agentOSRetainedPyodide; if (!pyodide) throw new Error('retained Python interpreter is unavailable'); await pyodide.runPythonAsync({source}); }})()" + ); + self.inner + .execute_retained(runner, String::from("/[agentos-python-retained]"), false) + .map_err(map_javascript_error) + } + pub fn start_prepared(&mut self) -> Result<(), PythonExecutionError> { self.inner.start_prepared().map_err(map_javascript_error) } @@ -2776,7 +2792,7 @@ fn warmup_marker_contents( env!("CARGO_PKG_NAME").to_string(), env!("CARGO_PKG_VERSION").to_string(), PYTHON_WARMUP_MARKER_VERSION.to_string(), - String::from("secure-exec-v8"), + String::from("agentos-v8"), python_max_old_space_mb(request).to_string(), compile_cache_dir.display().to_string(), pyodide_dist_path.display().to_string(), diff --git a/crates/execution/src/v8_ipc.rs b/crates/execution/src/v8_ipc.rs index c9999d357b..6fe3b383b6 100644 --- a/crates/execution/src/v8_ipc.rs +++ b/crates/execution/src/v8_ipc.rs @@ -1,4 +1,4 @@ -//! Binary IPC framing for communication with the secure-exec-v8 runtime process. +//! Binary IPC framing for communication with the agentos-v8 runtime process. //! //! Wire format per frame: //! [4B total_len (u32 BE, excludes self)] diff --git a/crates/execution/src/wasm.rs b/crates/execution/src/wasm.rs index af52e69681..e295592c9b 100644 --- a/crates/execution/src/wasm.rs +++ b/crates/execution/src/wasm.rs @@ -3132,7 +3132,7 @@ const __agentOSRequireBuiltin = (specifier) => {{ if (typeof process?.getBuiltinModule === "function") {{ return process.getBuiltinModule(specifier); }} - throw new Error(`secure-exec WASM bootstrap cannot load ${{specifier}}`); + throw new Error(`agentos WASM bootstrap cannot load ${{specifier}}`); }}; {wasi_module_source} {env_merge_source} @@ -3176,42 +3176,42 @@ if (typeof globalThis !== "undefined") {{ return __agentOSRequireBuiltin("node:fs").chmodSync(...args); case "__kernel_stdio_write": if (typeof _kernelStdioWriteRaw === "undefined") {{ - throw new Error("secure-exec WASM kernel stdio bridge is unavailable"); + throw new Error("agentos WASM kernel stdio bridge is unavailable"); }} return _kernelStdioWriteRaw.applySync(void 0, args); case "__kernel_stdin_read": if (typeof _kernelStdinReadRaw === "undefined") {{ - throw new Error("secure-exec WASM kernel stdin bridge is unavailable"); + throw new Error("agentos WASM kernel stdin bridge is unavailable"); }} return _kernelStdinReadRaw.applySync(void 0, args); case "__kernel_poll": if (typeof _kernelPollRaw === "undefined") {{ - throw new Error("secure-exec WASM kernel poll bridge is unavailable"); + throw new Error("agentos WASM kernel poll bridge is unavailable"); }} return _kernelPollRaw.applySync(void 0, args); case "__kernel_isatty": if (typeof _kernelIsattyRaw === "undefined") {{ - throw new Error("secure-exec WASM kernel isatty bridge is unavailable"); + throw new Error("agentos WASM kernel isatty bridge is unavailable"); }} return _kernelIsattyRaw.applySync(void 0, args); case "__kernel_flock_path": if (typeof _kernelFlockRaw === "undefined") {{ - throw new Error("secure-exec WASM kernel file-lock bridge is unavailable"); + throw new Error("agentos WASM kernel file-lock bridge is unavailable"); }} return _kernelFlockRaw.applySync(void 0, args); case "__kernel_tty_size": if (typeof _kernelTtySizeRaw === "undefined") {{ - throw new Error("secure-exec WASM kernel tty size bridge is unavailable"); + throw new Error("agentos WASM kernel tty size bridge is unavailable"); }} return _kernelTtySizeRaw.applySync(void 0, args); case "__pty_set_raw_mode": if (typeof _ptySetRawMode === "undefined") {{ - throw new Error("secure-exec WASM PTY raw-mode bridge is unavailable"); + throw new Error("agentos WASM PTY raw-mode bridge is unavailable"); }} return _ptySetRawMode.applySync(void 0, args); case "child_process.spawn": {{ if (typeof _childProcessSpawnStart === "undefined") {{ - throw new Error("secure-exec WASM child_process bridge is unavailable"); + throw new Error("agentos WASM child_process bridge is unavailable"); }} const [request] = args; return _childProcessSpawnStart.applySync(void 0, [ @@ -3222,32 +3222,32 @@ if (typeof globalThis !== "undefined") {{ }} case "child_process.poll": if (typeof _childProcessPoll === "undefined") {{ - throw new Error("secure-exec WASM child_process poll bridge is unavailable"); + throw new Error("agentos WASM child_process poll bridge is unavailable"); }} return _childProcessPoll.applySync(void 0, args); case "child_process.kill": if (typeof _childProcessKill === "undefined") {{ - throw new Error("secure-exec WASM child_process kill bridge is unavailable"); + throw new Error("agentos WASM child_process kill bridge is unavailable"); }} return _childProcessKill.applySync(void 0, args); case "process.kill": if (typeof _processKill === "undefined") {{ - throw new Error("secure-exec WASM process kill bridge is unavailable"); + throw new Error("agentos WASM process kill bridge is unavailable"); }} return _processKill.applySync(void 0, args); case "process.exec": if (typeof _processExec === "undefined") {{ - throw new Error("secure-exec WASM process exec bridge is unavailable"); + throw new Error("agentos WASM process exec bridge is unavailable"); }} return _processExec.applySync(void 0, args); case "process.exec_fd_image_commit": if (typeof _processExecFdImageCommit === "undefined") {{ - throw new Error("secure-exec WASM process fd image commit bridge is unavailable"); + throw new Error("agentos WASM process fd image commit bridge is unavailable"); }} return _processExecFdImageCommit.applySync(void 0, args); case "child_process.write_stdin": {{ if (typeof _childProcessStdinWrite === "undefined") {{ - throw new Error("secure-exec WASM child_process stdin bridge is unavailable"); + throw new Error("agentos WASM child_process stdin bridge is unavailable"); }} const [childId, chunk] = args; return _childProcessStdinWrite.applySync(void 0, [ @@ -3257,67 +3257,67 @@ if (typeof globalThis !== "undefined") {{ }} case "child_process.close_stdin": if (typeof _childProcessStdinClose === "undefined") {{ - throw new Error("secure-exec WASM child_process stdin-close bridge is unavailable"); + throw new Error("agentos WASM child_process stdin-close bridge is unavailable"); }} return _childProcessStdinClose.applySync(void 0, args); case "net.connect": if (typeof _netSocketConnectRaw === "undefined") {{ - throw new Error("secure-exec WASM net.connect bridge is unavailable"); + throw new Error("agentos WASM net.connect bridge is unavailable"); }} return _netSocketConnectRaw.applySync(void 0, args); case "net.bind_unix": if (typeof _netBindUnixRaw === "undefined") {{ - throw new Error("secure-exec WASM net.bind_unix bridge is unavailable"); + throw new Error("agentos WASM net.bind_unix bridge is unavailable"); }} return _netBindUnixRaw.applySync(void 0, args); case "net.bind_connected_unix": if (typeof _netBindConnectedUnixRaw === "undefined") {{ - throw new Error("secure-exec WASM net.bind_connected_unix bridge is unavailable"); + throw new Error("agentos WASM net.bind_connected_unix bridge is unavailable"); }} return _netBindConnectedUnixRaw.applySync(void 0, args); case "net.reserve_tcp_port": if (typeof _netReserveTcpPortRaw === "undefined") {{ - throw new Error("secure-exec WASM net.reserve_tcp_port bridge is unavailable"); + throw new Error("agentos WASM net.reserve_tcp_port bridge is unavailable"); }} return _netReserveTcpPortRaw.applySync(void 0, args); case "net.release_tcp_port": if (typeof _netReleaseTcpPortRaw === "undefined") {{ - throw new Error("secure-exec WASM net.release_tcp_port bridge is unavailable"); + throw new Error("agentos WASM net.release_tcp_port bridge is unavailable"); }} return _netReleaseTcpPortRaw.applySync(void 0, args); case "net.listen": if (typeof _netServerListenRaw === "undefined") {{ - throw new Error("secure-exec WASM net.listen bridge is unavailable"); + throw new Error("agentos WASM net.listen bridge is unavailable"); }} return _netServerListenRaw.applySync(void 0, args); case "net.server_accept": if (typeof _netServerAcceptRaw === "undefined") {{ - throw new Error("secure-exec WASM net.server_accept bridge is unavailable"); + throw new Error("agentos WASM net.server_accept bridge is unavailable"); }} return _netServerAcceptRaw.applySync(void 0, args); case "net.server_close": if (typeof _netServerCloseSyncRaw === "undefined") {{ - throw new Error("secure-exec WASM net.server_close bridge is unavailable"); + throw new Error("agentos WASM net.server_close bridge is unavailable"); }} return _netServerCloseSyncRaw.applySync(void 0, args); case "net.poll": if (typeof _netSocketPollRaw === "undefined") {{ - throw new Error("secure-exec WASM net.poll bridge is unavailable"); + throw new Error("agentos WASM net.poll bridge is unavailable"); }} return _netSocketPollRaw.applySync(void 0, args); case "net.socket_read": if (typeof _netSocketReadRaw === "undefined") {{ - throw new Error("secure-exec WASM net.socket_read bridge is unavailable"); + throw new Error("agentos WASM net.socket_read bridge is unavailable"); }} return _netSocketReadRaw.applySync(void 0, args); case "net.socket_wait_connect": if (typeof _netSocketWaitConnectSyncRaw === "undefined") {{ - throw new Error("secure-exec WASM net.socket_wait_connect bridge is unavailable"); + throw new Error("agentos WASM net.socket_wait_connect bridge is unavailable"); }} return _netSocketWaitConnectSyncRaw.applySync(void 0, args); case "net.write": if (typeof _netSocketWriteSyncRaw === "undefined") {{ - throw new Error("secure-exec WASM net.write bridge is unavailable"); + throw new Error("agentos WASM net.write bridge is unavailable"); }} return _netSocketWriteSyncRaw.applySync(void 0, [ args[0], @@ -3326,27 +3326,27 @@ if (typeof globalThis !== "undefined") {{ ]); case "net.destroy": if (typeof _netSocketDestroyRaw === "undefined") {{ - throw new Error("secure-exec WASM net.destroy bridge is unavailable"); + throw new Error("agentos WASM net.destroy bridge is unavailable"); }} return _netSocketDestroyRaw.applySync(void 0, args); case "net.socket_upgrade_tls": if (typeof _netSocketUpgradeTlsRaw === "undefined") {{ - throw new Error("secure-exec WASM TLS-upgrade bridge is unavailable"); + throw new Error("agentos WASM TLS-upgrade bridge is unavailable"); }} return _netSocketUpgradeTlsRaw.applySync(void 0, args); case "dgram.createSocket": if (typeof _dgramSocketCreateRaw === "undefined") {{ - throw new Error("secure-exec WASM dgram.createSocket bridge is unavailable"); + throw new Error("agentos WASM dgram.createSocket bridge is unavailable"); }} return _dgramSocketCreateRaw.applySync(void 0, args); case "dgram.bind": if (typeof _dgramSocketBindRaw === "undefined") {{ - throw new Error("secure-exec WASM dgram.bind bridge is unavailable"); + throw new Error("agentos WASM dgram.bind bridge is unavailable"); }} return _dgramSocketBindRaw.applySync(void 0, args); case "dgram.send": {{ if (typeof _dgramSocketSendRaw === "undefined") {{ - throw new Error("secure-exec WASM dgram.send bridge is unavailable"); + throw new Error("agentos WASM dgram.send bridge is unavailable"); }} const [socketId, chunk, options = {{}}] = args; return _dgramSocketSendRaw.applySync(void 0, [ @@ -3357,7 +3357,7 @@ if (typeof globalThis !== "undefined") {{ }} case "dgram.poll": if (typeof _dgramSocketRecvRaw === "undefined") {{ - throw new Error("secure-exec WASM dgram.poll bridge is unavailable"); + throw new Error("agentos WASM dgram.poll bridge is unavailable"); }} const event = _dgramSocketRecvRaw.applySync(void 0, args); if (event && event.type === "message") {{ @@ -3384,32 +3384,32 @@ if (typeof globalThis !== "undefined") {{ return event; case "dgram.close": if (typeof _dgramSocketCloseRaw === "undefined") {{ - throw new Error("secure-exec WASM dgram.close bridge is unavailable"); + throw new Error("agentos WASM dgram.close bridge is unavailable"); }} return _dgramSocketCloseRaw.applySync(void 0, args); case "dgram.address": if (typeof _dgramSocketAddressRaw === "undefined") {{ - throw new Error("secure-exec WASM dgram.address bridge is unavailable"); + throw new Error("agentos WASM dgram.address bridge is unavailable"); }} return _dgramSocketAddressRaw.applySync(void 0, args); case "dgram.setBufferSize": if (typeof _dgramSocketSetBufferSizeRaw === "undefined") {{ - throw new Error("secure-exec WASM dgram.setBufferSize bridge is unavailable"); + throw new Error("agentos WASM dgram.setBufferSize bridge is unavailable"); }} return _dgramSocketSetBufferSizeRaw.applySync(void 0, args); case "dgram.getBufferSize": if (typeof _dgramSocketGetBufferSizeRaw === "undefined") {{ - throw new Error("secure-exec WASM dgram.getBufferSize bridge is unavailable"); + throw new Error("agentos WASM dgram.getBufferSize bridge is unavailable"); }} return _dgramSocketGetBufferSizeRaw.applySync(void 0, args); case "dns.lookup": if (typeof _networkDnsLookupSyncRaw === "undefined") {{ - throw new Error("secure-exec WASM dns.lookup bridge is unavailable"); + throw new Error("agentos WASM dns.lookup bridge is unavailable"); }} return _networkDnsLookupSyncRaw.applySync(void 0, args); case "process.signal_state": {{ if (typeof _processSignalState === "undefined") {{ - throw new Error("secure-exec WASM signal-state bridge is unavailable"); + throw new Error("agentos WASM signal-state bridge is unavailable"); }} const [signal, action = "default", maskJson = "[]", flags = 0] = args; return _processSignalState.applySyncPromise(void 0, [ @@ -3421,7 +3421,7 @@ if (typeof globalThis !== "undefined") {{ }} case "process.take_signal": if (typeof _processTakeSignal === "undefined") {{ - throw new Error("secure-exec WASM signal-drain bridge is unavailable"); + throw new Error("agentos WASM signal-drain bridge is unavailable"); }} return _processTakeSignal.applySync(void 0, args); case "process.getpgid": @@ -3517,11 +3517,11 @@ if (typeof globalThis !== "undefined") {{ case "process.fd_recvmsg_rights": case "process.fd_socket_shutdown": if (typeof _processWasmSyncRpc === "undefined") {{ - throw new Error("secure-exec WASM process-syscall bridge is unavailable"); + throw new Error("agentos WASM process-syscall bridge is unavailable"); }} return _processWasmSyncRpc.applySync(void 0, [method, ...args]); default: - throw new Error(`secure-exec WASM sync RPC method not implemented in V8 runtime: ${{method}}`); + throw new Error(`agentos WASM sync RPC method not implemented in V8 runtime: ${{method}}`); }} }}, async call(method, args = []) {{ @@ -5250,14 +5250,14 @@ mod tests { &BTreeMap::from([( String::from("AGENTOS_GUEST_PATH_MAPPINGS"), format!( - "[{{\"guestPath\":\"/__secure_exec/commands/0\",\"hostPath\":\"{}\"}}]", + "[{{\"guestPath\":\"/__agentos/commands/0\",\"hostPath\":\"{}\"}}]", command_root.display() ), )]), ); assert!(candidates.contains(&module.to_string_lossy().into_owned())); - assert!(candidates.contains(&String::from("/__secure_exec/commands/0/hello"))); + assert!(candidates.contains(&String::from("/__agentos/commands/0/hello"))); } #[test] @@ -5382,7 +5382,7 @@ mod tests { read_only: false, }, super::WasmGuestPathMapping { - guest_path: String::from("/__secure_exec/commands/0"), + guest_path: String::from("/__agentos/commands/0"), host_path: mapped_root.clone(), read_only: false, }, @@ -5609,9 +5609,9 @@ mod tests { fn wasm_sandbox_root_reads_absolute_env_only() { let sandbox_root = wasm_sandbox_root(&BTreeMap::from([( String::from(WASM_SANDBOX_ROOT_ENV), - String::from("/tmp/secure-exec-shadow"), + String::from("/tmp/agentos-shadow"), )])); - assert_eq!(sandbox_root, Some(PathBuf::from("/tmp/secure-exec-shadow"))); + assert_eq!(sandbox_root, Some(PathBuf::from("/tmp/agentos-shadow"))); let relative = wasm_sandbox_root(&BTreeMap::from([( String::from(WASM_SANDBOX_ROOT_ENV), @@ -5639,7 +5639,7 @@ mod tests { module_host_path: PathBuf::from("/tmp/module.wasm"), guest_cwd: String::from("/"), host_cwd: PathBuf::from("/tmp"), - sandbox_root: Some(PathBuf::from("/tmp/secure-exec-shadow")), + sandbox_root: Some(PathBuf::from("/tmp/agentos-shadow")), guest_path_mappings: Vec::new(), route_fs_through_sidecar: true, next_fd: 64, diff --git a/crates/execution/tests/javascript_v8.rs b/crates/execution/tests/javascript_v8.rs index 22e0014121..df4c26e216 100644 --- a/crates/execution/tests/javascript_v8.rs +++ b/crates/execution/tests/javascript_v8.rs @@ -917,7 +917,7 @@ fn javascript_execution_uses_v8_runtime_without_spawning_guest_node_binary() { env: BTreeMap::new(), cwd: temp.path().to_path_buf(), wasm_module_bytes: None, - inline_code: Some(String::from("globalThis.__secureExecRanInV8 = true;")), + inline_code: Some(String::from("globalThis.__agentOsRanInV8 = true;")), }) .expect("start JavaScript execution"); @@ -963,7 +963,7 @@ fn javascript_execution_virtual_os_identity_comes_from_guest_runtime_not_env() { os_tmpdir: Some(String::from("/vm-tmp")), os_type: Some(String::from("VMType")), os_release: Some(String::from("1.2.3-vm")), - os_version: Some(String::from("VM secure-exec build 42")), + os_version: Some(String::from("VM agentos build 42")), os_machine: Some(String::from("vm64")), ..Default::default() }, @@ -992,7 +992,7 @@ if (os.hostname() !== "vm-hostname") throw new Error(`hostname=${os.hostname()}` if (os.tmpdir() !== "/vm-tmp") throw new Error(`tmpdir=${os.tmpdir()}`); if (os.type() !== "VMType") throw new Error(`type=${os.type()}`); if (os.release() !== "1.2.3-vm") throw new Error(`release=${os.release()}`); -if (os.version() !== "VM secure-exec build 42") throw new Error(`version=${os.version()}`); +if (os.version() !== "VM agentos build 42") throw new Error(`version=${os.version()}`); if (os.machine() !== "vm64") throw new Error(`machine=${os.machine()}`); "#, )), @@ -1893,14 +1893,14 @@ fn javascript_execution_high_resolution_time_opt_in_enables_sub_ms_hrtime() { wasm_module_bytes: None, inline_code: Some(String::from( r#" -if (typeof __secureExecHrNowUs !== "function") { +if (typeof __agentOsHrNowUs !== "function") { throw new Error("high-resolution host clock was not installed"); } let sawSubMs = false; for (let attempt = 0; attempt < 80 && !sawSubMs; attempt++) { const start = process.hrtime.bigint(); - const until = __secureExecHrNowUs() + 200; - while (__secureExecHrNowUs() < until) {} + const until = __agentOsHrNowUs() + 200; + while (__agentOsHrNowUs() < until) {} const delta = process.hrtime.bigint() - start; if (delta > 0n && delta < 1000000n) { sawSubMs = true; @@ -1942,7 +1942,7 @@ fn javascript_execution_high_resolution_time_default_off_keeps_coarse_clock() { wasm_module_bytes: None, inline_code: Some(String::from( r#" -if (typeof __secureExecHrNowUs !== "undefined") { +if (typeof __agentOsHrNowUs !== "undefined") { throw new Error("high-resolution host clock exists without opt-in"); } for (let attempt = 0; attempt < 20; attempt++) { diff --git a/crates/execution/tests/process.rs b/crates/execution/tests/process.rs index 4cfc5f05d3..353b00a4d0 100644 --- a/crates/execution/tests/process.rs +++ b/crates/execution/tests/process.rs @@ -57,7 +57,7 @@ fn embedded_runtime_process_keeps_host_pid_internal_for_javascript() { env: BTreeMap::new(), cwd: temp.path().to_path_buf(), wasm_module_bytes: None, - inline_code: Some(String::from("globalThis.__secureExecRanInV8 = true;")), + inline_code: Some(String::from("globalThis.__agentOsRanInV8 = true;")), }) .expect("start JavaScript execution"); diff --git a/crates/kernel/Cargo.toml b/crates/kernel/Cargo.toml index d03fd751a5..007aeda414 100644 --- a/crates/kernel/Cargo.toml +++ b/crates/kernel/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Shared kernel plane for secure-exec native and browser sidecars" +description = "Shared kernel plane for agentos native and browser sidecars" [dependencies] agentos-bridge = { workspace = true } diff --git a/crates/kernel/src/kernel.rs b/crates/kernel/src/kernel.rs index 793bad5cfe..28aa7c7b39 100644 --- a/crates/kernel/src/kernel.rs +++ b/crates/kernel/src/kernel.rs @@ -6970,7 +6970,7 @@ impl KernelVm { interpreter_depth: usize, ) -> KernelResult<()> { let resolved = self.validate_executable_path(path, cwd)?; - // `/bin/` and `/__secure_exec/commands/.../` may be + // `/bin/` and `/__agentos/commands/.../` may be // kernel-owned command stubs whose backing bytes are a self-referential // launcher rather than the projected WASM blob the runner loads. Once // the exact path has resolved to a registered command, its trusted @@ -7014,7 +7014,7 @@ impl KernelVm { } if let Some(name) = normalized - .strip_prefix("/__secure_exec/commands/") + .strip_prefix("/__agentos/commands/") .and_then(|suffix| suffix.rsplit('/').next()) { if !name.is_empty() && !name.contains('/') && self.commands.resolve(name).is_some() { @@ -7727,7 +7727,7 @@ impl KernelVm { let mut body = String::new(); for processor in 0..self.proc_cpu_count() { body.push_str(&format!( - "processor\t: {processor}\nmodel name\t: secure-exec Virtual CPU\ncpu MHz\t\t: 1000.000\nsiblings\t: 1\ncpu cores\t: 1\n\n" + "processor\t: {processor}\nmodel name\t: agentos Virtual CPU\ncpu MHz\t\t: 1000.000\nsiblings\t: 1\ncpu cores\t: 1\n\n" )); } body.into_bytes() diff --git a/crates/kernel/src/lib.rs b/crates/kernel/src/lib.rs index 36f2506684..5090568ff4 100644 --- a/crates/kernel/src/lib.rs +++ b/crates/kernel/src/lib.rs @@ -1,6 +1,6 @@ #![forbid(unsafe_code)] -//! Shared per-VM kernel plane for the secure-exec runtime migration. +//! Shared per-VM kernel plane for the agentos runtime migration. pub use agentos_bridge as bridge; pub mod command_registry; diff --git a/crates/kernel/tests/command_registry.rs b/crates/kernel/tests/command_registry.rs index 6188aded6b..933a82b079 100644 --- a/crates/kernel/tests/command_registry.rs +++ b/crates/kernel/tests/command_registry.rs @@ -166,21 +166,21 @@ fn mounted_agentos_command_paths_resolve_to_registered_drivers() { .expect("register drivers"); kernel - .mkdir("/__secure_exec/commands/0", true) + .mkdir("/__agentos/commands/0", true) .expect("create mounted command root"); kernel .write_file( - "/__secure_exec/commands/0/xu", + "/__agentos/commands/0/xu", b"#!/bin/sh\n# kernel command stub\n".to_vec(), ) .expect("write mounted command stub"); kernel - .chmod("/__secure_exec/commands/0/xu", 0o755) + .chmod("/__agentos/commands/0/xu", 0o755) .expect("chmod mounted command stub"); let process = kernel .spawn_process( - "/__secure_exec/commands/0/xu", + "/__agentos/commands/0/xu", vec![String::from("hello-agentos")], SpawnOptions::default(), ) diff --git a/crates/kernel/tests/default_deny_guards.rs b/crates/kernel/tests/default_deny_guards.rs index 0db396f330..0fd804e703 100644 --- a/crates/kernel/tests/default_deny_guards.rs +++ b/crates/kernel/tests/default_deny_guards.rs @@ -1,6 +1,6 @@ //! Default-deny / fail-closed guards (CI hardening, item #5). //! -//! These tests pin down the secure-exec security posture so a refactor cannot +//! These tests pin down the agentos security posture so a refactor cannot //! silently weaken it: //! //! 1. Default-deny: with no policy configured (`Permissions::default()`), diff --git a/crates/kernel/tests/identity.rs b/crates/kernel/tests/identity.rs index 17f33e619a..905a979c8c 100644 --- a/crates/kernel/tests/identity.rs +++ b/crates/kernel/tests/identity.rs @@ -338,7 +338,7 @@ fn procfs_exposes_linux_like_identity_and_system_files() { let cpuinfo = read_utf8(&mut kernel, "/proc/cpuinfo"); assert!(cpuinfo.contains("processor\t: 0")); - assert!(cpuinfo.contains("model name\t: secure-exec Virtual CPU")); + assert!(cpuinfo.contains("model name\t: agentos Virtual CPU")); let meminfo = read_utf8(&mut kernel, "/proc/meminfo"); assert!(meminfo.contains("MemTotal: 262144 kB")); diff --git a/crates/native-baseline/Cargo.toml b/crates/native-baseline/Cargo.toml index 28d539203d..1dd78c7811 100644 --- a/crates/native-baseline/Cargo.toml +++ b/crates/native-baseline/Cargo.toml @@ -7,7 +7,7 @@ publish = false # Native floor for the differential perf harness. std-only on purpose: this is the # glibc fork/posix_spawn + execve baseline that the agent-os "emulation tax" divides -# against. No secure-exec deps — it must measure the host, not the emulator. +# against. No agentos deps — it must measure the host, not the emulator. [[bin]] name = "agentos-native-baseline" diff --git a/crates/native-baseline/src/main.rs b/crates/native-baseline/src/main.rs index ff180dd639..52a4667fd7 100644 --- a/crates/native-baseline/src/main.rs +++ b/crates/native-baseline/src/main.rs @@ -410,13 +410,13 @@ fn run_once(op: Op, iter: usize, base_dir: &Path, config: &BenchConfig) { assert!(out.status.success(), "pipe chain failed: {out:?}"); } Op::FsStat => { - let path = base_dir.join("secure-exec-native-fs-stat.txt"); + let path = base_dir.join("agentos-native-fs-stat.txt"); std::fs::write(&path, b"hi").expect("write stat fixture"); let meta = std::fs::metadata(&path).expect("stat fixture"); assert!(meta.len() >= 2); } Op::FsStatX32 => { - let path = base_dir.join("secure-exec-native-fs-stat-x32.txt"); + let path = base_dir.join("agentos-native-fs-stat-x32.txt"); if !path.exists() { std::fs::write(&path, b"hi").expect("write stat fixture"); } @@ -433,7 +433,7 @@ fn run_once(op: Op, iter: usize, base_dir: &Path, config: &BenchConfig) { } } Op::FsWrite => { - let path = base_dir.join("secure-exec-native-fs-write.txt"); + let path = base_dir.join("agentos-native-fs-write.txt"); if let Some(size_bytes) = config.size_bytes { std::fs::write(path, vec![(iter & 255) as u8; size_bytes]).expect("write fixture"); } else { @@ -442,7 +442,7 @@ fn run_once(op: Op, iter: usize, base_dir: &Path, config: &BenchConfig) { } Op::FsRead => { let size_bytes = config.size_bytes.unwrap_or(64 * 1024); - let path = base_dir.join("secure-exec-native-fs-read.bin"); + let path = base_dir.join("agentos-native-fs-read.bin"); let rewrite = std::fs::metadata(&path) .map(|meta| meta.len() != size_bytes as u64) .unwrap_or(true); @@ -454,11 +454,9 @@ fn run_once(op: Op, iter: usize, base_dir: &Path, config: &BenchConfig) { } Op::StreamCopy => { let size_bytes = config.size_bytes.unwrap_or(64 * 1024); - let src = base_dir.join(format!( - "secure-exec-native-stream-copy-src-{size_bytes}.bin" - )); + let src = base_dir.join(format!("agentos-native-stream-copy-src-{size_bytes}.bin")); let dst = base_dir.join(format!( - "secure-exec-native-stream-copy-dst-{size_bytes}-{iter}.bin" + "agentos-native-stream-copy-dst-{size_bytes}-{iter}.bin" )); let rewrite = std::fs::metadata(&src) .map(|meta| meta.len() != size_bytes as u64) @@ -487,26 +485,26 @@ fn run_once(op: Op, iter: usize, base_dir: &Path, config: &BenchConfig) { assert_eq!(meta.len(), size_bytes as u64); } Op::FsOpenClose => { - let path = base_dir.join("secure-exec-native-fs-open-close.txt"); + let path = base_dir.join("agentos-native-fs-open-close.txt"); std::fs::write(&path, b"hi").expect("write open fixture"); let file = File::open(path).expect("open fixture"); drop(file); } Op::FsMkdirRmdir => { - let path = base_dir.join(format!("secure-exec-native-dir-{iter}")); + let path = base_dir.join(format!("agentos-native-dir-{iter}")); std::fs::create_dir(&path).expect("create dir"); std::fs::remove_dir(&path).expect("remove dir"); } Op::FsRename => { - let from = base_dir.join(format!("secure-exec-native-rename-{iter}.a")); - let to = base_dir.join(format!("secure-exec-native-rename-{iter}.b")); + let from = base_dir.join(format!("agentos-native-rename-{iter}.a")); + let to = base_dir.join(format!("agentos-native-rename-{iter}.b")); std::fs::write(&from, b"hi").expect("write rename fixture"); std::fs::rename(&from, &to).expect("rename fixture"); std::fs::remove_file(&to).expect("remove rename fixture"); } Op::FsReaddir => { let entry_count = config.entry_count.unwrap_or(32); - let dir = base_dir.join("secure-exec-native-readdir"); + let dir = base_dir.join("agentos-native-readdir"); std::fs::create_dir_all(&dir).expect("create readdir dir"); let marker = dir.join(format!(".fixture-ready-{entry_count}")); if !marker.exists() { @@ -522,7 +520,7 @@ fn run_once(op: Op, iter: usize, base_dir: &Path, config: &BenchConfig) { assert!(count > entry_count); } Op::FsFsync => { - let path = base_dir.join("secure-exec-native-fsync.txt"); + let path = base_dir.join("agentos-native-fsync.txt"); let mut file = File::create(path).expect("create fsync fixture"); file.write_all(b"hello").expect("write fsync fixture"); file.sync_all().expect("fsync fixture"); @@ -593,7 +591,7 @@ fn run_once(op: Op, iter: usize, base_dir: &Path, config: &BenchConfig) { } #[cfg(all(unix, not(target_family = "wasm")))] Op::UnixConnect => { - let sock = base_dir.join(format!("secure-exec-native-unix-connect-{iter}.sock")); + let sock = base_dir.join(format!("agentos-native-unix-connect-{iter}.sock")); let _ = std::fs::remove_file(&sock); let listener = UnixListener::bind(&sock).expect("bind unix listener"); let server = thread::spawn(move || { @@ -607,7 +605,7 @@ fn run_once(op: Op, iter: usize, base_dir: &Path, config: &BenchConfig) { #[cfg(all(unix, not(target_family = "wasm")))] Op::UnixEcho => { let payload = vec![7_u8; config.size_bytes.unwrap_or(16)]; - let sock = base_dir.join(format!("secure-exec-native-unix-echo-{iter}.sock")); + let sock = base_dir.join(format!("agentos-native-unix-echo-{iter}.sock")); let _ = std::fs::remove_file(&sock); let listener = UnixListener::bind(&sock).expect("bind unix listener"); let expected_len = payload.len(); diff --git a/crates/native-sidecar-browser/CLAUDE.md b/crates/native-sidecar-browser/CLAUDE.md index 91a5d062a9..fb974c10b3 100644 --- a/crates/native-sidecar-browser/CLAUDE.md +++ b/crates/native-sidecar-browser/CLAUDE.md @@ -1,5 +1,5 @@ # Browser Support -- Browser support is untested after the secure-exec split; only build-level validation is required during migration. +- Browser support is untested after the agentos split; only build-level validation is required during migration. - Provenance: moved from rivet-dev/agentos@87ed8e21e454. - Keep the browser sidecar separate from the native sidecar because worker transport and main-thread ownership differ from stdio/socket transport. diff --git a/crates/native-sidecar-browser/Cargo.toml b/crates/native-sidecar-browser/Cargo.toml index 2eeaa53c87..d595500874 100644 --- a/crates/native-sidecar-browser/Cargo.toml +++ b/crates/native-sidecar-browser/Cargo.toml @@ -3,7 +3,7 @@ name = "agentos-native-sidecar-browser" version.workspace = true edition.workspace = true license.workspace = true -description = "Browser-side Secure Exec sidecar scaffold" +description = "Browser-side AgentOS language execution sidecar scaffold" # Browser support is retained for a future migration but intentionally disabled # and must not be published while it is outside the unified reactor contract. publish = false diff --git a/crates/native-sidecar-browser/src/lib.rs b/crates/native-sidecar-browser/src/lib.rs index 4c6fa2c22e..574de48eb4 100644 --- a/crates/native-sidecar-browser/src/lib.rs +++ b/crates/native-sidecar-browser/src/lib.rs @@ -2,7 +2,7 @@ // AGENTOS_BROWSER_SUPPORT_DISABLED: retained for reference, but AgentOS is native-only. /* -//! Browser-side sidecar scaffold for the secure-exec runtime migration. +//! Browser-side sidecar scaffold for the agentos runtime migration. mod service; #[cfg(target_arch = "wasm32")] diff --git a/crates/native-sidecar-browser/tests/service.rs b/crates/native-sidecar-browser/tests/service.rs index 95ce97bede..b8539c475c 100644 --- a/crates/native-sidecar-browser/tests/service.rs +++ b/crates/native-sidecar-browser/tests/service.rs @@ -178,12 +178,12 @@ fn test_os_config() -> BrowserWorkerOsConfig { platform: String::from("linux"), arch: String::from("x64"), r#type: String::from("Linux"), - release: String::from("6.8.0-secure-exec"), - version: String::from("#1 SMP PREEMPT_DYNAMIC secure-exec"), + release: String::from("6.8.0-agentos"), + version: String::from("#1 SMP PREEMPT_DYNAMIC agentos"), cpu_count: 1, totalmem: 1024 * 1024 * 1024, freemem: 512 * 1024 * 1024, - hostname: String::from("secure-exec"), + hostname: String::from("agentos"), homedir: String::from("/home/user"), tmpdir: String::from("/tmp"), machine: String::from("x86_64"), @@ -355,16 +355,16 @@ fn browser_worker_spawn_receives_virtual_identity_config() { ); assert_eq!( spawn.get("os_hostname").map(String::as_str), - Some("secure-exec") + Some("agentos") ); assert_eq!(spawn.get("os_type").map(String::as_str), Some("Linux")); assert_eq!( spawn.get("os_release").map(String::as_str), - Some("6.8.0-secure-exec") + Some("6.8.0-agentos") ); assert_eq!( spawn.get("os_version").map(String::as_str), - Some("#1 SMP PREEMPT_DYNAMIC secure-exec") + Some("#1 SMP PREEMPT_DYNAMIC agentos") ); assert_eq!(spawn.get("os_tmpdir").map(String::as_str), Some("/tmp")); assert_eq!(spawn.get("os_machine").map(String::as_str), Some("x86_64")); diff --git a/crates/native-sidecar-browser/tests/wire_dispatch.rs b/crates/native-sidecar-browser/tests/wire_dispatch.rs index 6723d02e91..c4983862b2 100644 --- a/crates/native-sidecar-browser/tests/wire_dispatch.rs +++ b/crates/native-sidecar-browser/tests/wire_dispatch.rs @@ -33,7 +33,7 @@ struct WireExtension; impl BrowserExtension for WireExtension { fn namespace(&self) -> &str { - "dev.rivet.secure-exec.browser-wire-test" + "dev.rivet.agentos.browser-wire-test" } fn handle_request( @@ -775,7 +775,7 @@ fn browser_wire_dispatcher_routes_extension_frames() { connection_id: String::from("client"), }), payload: RequestPayload::ExtEnvelope(ExtEnvelope { - namespace: String::from("dev.rivet.secure-exec.browser-wire-test"), + namespace: String::from("dev.rivet.agentos.browser-wire-test"), payload: b"ping".to_vec(), }), }, @@ -784,10 +784,7 @@ fn browser_wire_dispatcher_routes_extension_frames() { let ResponsePayload::ExtEnvelope(envelope) = response.payload else { panic!("unexpected extension response: {:?}", response.payload); }; - assert_eq!( - envelope.namespace, - "dev.rivet.secure-exec.browser-wire-test" - ); + assert_eq!(envelope.namespace, "dev.rivet.agentos.browser-wire-test"); assert_eq!(envelope.payload, b"wire-ext:ping"); } diff --git a/crates/native-sidecar-core/Cargo.toml b/crates/native-sidecar-core/Cargo.toml index d153e0991b..6d4374b00f 100644 --- a/crates/native-sidecar-core/Cargo.toml +++ b/crates/native-sidecar-core/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Shared Secure Exec sidecar logic for native and browser shells" +description = "Shared AgentOS language execution sidecar logic for native and browser shells" [dependencies] agentos-bridge = { workspace = true } diff --git a/crates/native-sidecar-core/src/frames.rs b/crates/native-sidecar-core/src/frames.rs index f3dd47b172..58afef891a 100644 --- a/crates/native-sidecar-core/src/frames.rs +++ b/crates/native-sidecar-core/src/frames.rs @@ -495,14 +495,13 @@ mod tests { #[test] fn authenticated_response_sets_connection_ownership() { - let response = - authenticated_response(7, "secure-exec-test", String::from("conn-test"), 1024); + let response = authenticated_response(7, "agentos-test", String::from("conn-test"), 1024); assert_eq!(response.request_id, 7); assert_eq!(response.ownership, OwnershipScope::connection("conn-test")); match response.payload { ResponsePayload::Authenticated(authenticated) => { - assert_eq!(authenticated.sidecar_id, "secure-exec-test"); + assert_eq!(authenticated.sidecar_id, "agentos-test"); assert_eq!(authenticated.connection_id, "conn-test"); assert_eq!(authenticated.max_frame_bytes, 1024); } diff --git a/crates/native-sidecar-core/src/identity.rs b/crates/native-sidecar-core/src/identity.rs index 11f2509b16..9a6c768882 100644 --- a/crates/native-sidecar-core/src/identity.rs +++ b/crates/native-sidecar-core/src/identity.rs @@ -42,13 +42,13 @@ pub fn shared_guest_runtime_identity( os_totalmem: virtual_os_totalmem_bytes(resource_limits), os_freemem: virtual_os_freemem_bytes(resource_limits), os_homedir: user.homedir.clone(), - os_hostname: String::from("secure-exec"), + os_hostname: String::from("agentos"), os_shell: user.shell.clone(), os_user: user.username.clone(), os_tmpdir: String::from("/tmp"), os_type: String::from("Linux"), - os_release: String::from("6.8.0-secure-exec"), - os_version: String::from("#1 SMP PREEMPT_DYNAMIC secure-exec"), + os_release: String::from("6.8.0-agentos"), + os_version: String::from("#1 SMP PREEMPT_DYNAMIC agentos"), os_machine: String::from("x86_64"), } } @@ -86,13 +86,13 @@ mod tests { assert_eq!(identity.os_cpu_count, 6); assert_eq!(identity.os_totalmem, 512 * 1024 * 1024); assert_eq!(identity.os_homedir, "/Users/runner"); - assert_eq!(identity.os_hostname, "secure-exec"); + assert_eq!(identity.os_hostname, "agentos"); assert_eq!(identity.os_shell, "/bin/zsh"); assert_eq!(identity.os_user, "runner"); assert_eq!(identity.os_tmpdir, "/tmp"); assert_eq!(identity.os_type, "Linux"); - assert_eq!(identity.os_release, "6.8.0-secure-exec"); - assert_eq!(identity.os_version, "#1 SMP PREEMPT_DYNAMIC secure-exec"); + assert_eq!(identity.os_release, "6.8.0-agentos"); + assert_eq!(identity.os_version, "#1 SMP PREEMPT_DYNAMIC agentos"); assert_eq!(identity.os_machine, "x86_64"); } } diff --git a/crates/native-sidecar-core/src/router.rs b/crates/native-sidecar-core/src/router.rs index c9eee9916c..1cc13ca1d7 100644 --- a/crates/native-sidecar-core/src/router.rs +++ b/crates/native-sidecar-core/src/router.rs @@ -57,6 +57,8 @@ pub enum RequestRoute { GetZombieTimerCount(GetZombieTimerCountRequest), LinkPackage(LinkPackageRequest), ProvidedCommands(ProvidedCommandsRequest), + ExecutionOperation(RequestPayload), + ExecutionLifecycle(RequestPayload), Ext(ExtEnvelope), UnsupportedHostCallbackDirection, } @@ -105,6 +107,36 @@ pub fn route_request_payload(request: &RequestFrame) -> RequestRoute { RequestPayload::GetZombieTimerCount(payload) => RequestRoute::GetZombieTimerCount(payload), RequestPayload::LinkPackage(payload) => RequestRoute::LinkPackage(payload), RequestPayload::ProvidedCommands(payload) => RequestRoute::ProvidedCommands(payload), + payload @ (RequestPayload::ShellExecution(_) + | RequestPayload::ArgvExecution(_) + | RequestPayload::JavaScriptExecution(_) + | RequestPayload::JavaScriptEvaluation(_) + | RequestPayload::JavaScriptFileExecution(_) + | RequestPayload::TypeScriptExecution(_) + | RequestPayload::TypeScriptEvaluation(_) + | RequestPayload::TypeScriptFileExecution(_) + | RequestPayload::TypeScriptCheck(_) + | RequestPayload::TypeScriptProjectCheck(_) + | RequestPayload::NpmProjectInstall(_) + | RequestPayload::NpmPackageInstall(_) + | RequestPayload::NpmScriptExecution(_) + | RequestPayload::NpmPackageExecution(_) + | RequestPayload::PythonExecution(_) + | RequestPayload::PythonEvaluation(_) + | RequestPayload::PythonFileExecution(_) + | RequestPayload::PythonModuleExecution(_) + | RequestPayload::PythonInstall(_)) => RequestRoute::ExecutionOperation(payload), + payload @ (RequestPayload::GetExecution(_) + | RequestPayload::ListExecutions(_) + | RequestPayload::WaitExecution(_) + | RequestPayload::CancelExecution(_) + | RequestPayload::SignalExecution(_) + | RequestPayload::ResetExecution(_) + | RequestPayload::DeleteExecution(_) + | RequestPayload::WriteExecutionStdin(_) + | RequestPayload::CloseExecutionStdin(_) + | RequestPayload::ResizeExecutionPty(_) + | RequestPayload::ReadExecutionOutput(_)) => RequestRoute::ExecutionLifecycle(payload), RequestPayload::HostFilesystemCall(_) | RequestPayload::PersistenceLoad(_) | RequestPayload::PersistenceFlush(_) => RequestRoute::UnsupportedHostCallbackDirection, @@ -169,6 +201,36 @@ pub fn request_dispatch_mode(request: &RequestFrame) -> RequestDispatchMode { | RequestPayload::GetZombieTimerCount(_) | RequestPayload::LinkPackage(_) | RequestPayload::ProvidedCommands(_) + | RequestPayload::ShellExecution(_) + | RequestPayload::ArgvExecution(_) + | RequestPayload::JavaScriptExecution(_) + | RequestPayload::JavaScriptEvaluation(_) + | RequestPayload::JavaScriptFileExecution(_) + | RequestPayload::TypeScriptExecution(_) + | RequestPayload::TypeScriptEvaluation(_) + | RequestPayload::TypeScriptFileExecution(_) + | RequestPayload::TypeScriptCheck(_) + | RequestPayload::TypeScriptProjectCheck(_) + | RequestPayload::NpmProjectInstall(_) + | RequestPayload::NpmPackageInstall(_) + | RequestPayload::NpmScriptExecution(_) + | RequestPayload::NpmPackageExecution(_) + | RequestPayload::PythonExecution(_) + | RequestPayload::PythonEvaluation(_) + | RequestPayload::PythonFileExecution(_) + | RequestPayload::PythonModuleExecution(_) + | RequestPayload::PythonInstall(_) + | RequestPayload::GetExecution(_) + | RequestPayload::ListExecutions(_) + | RequestPayload::WaitExecution(_) + | RequestPayload::CancelExecution(_) + | RequestPayload::SignalExecution(_) + | RequestPayload::ResetExecution(_) + | RequestPayload::DeleteExecution(_) + | RequestPayload::WriteExecutionStdin(_) + | RequestPayload::CloseExecutionStdin(_) + | RequestPayload::ResizeExecutionPty(_) + | RequestPayload::ReadExecutionOutput(_) | RequestPayload::HostFilesystemCall(_) | RequestPayload::PersistenceLoad(_) | RequestPayload::PersistenceFlush(_) => RequestDispatchMode::Immediate, diff --git a/crates/native-sidecar/Cargo.toml b/crates/native-sidecar/Cargo.toml index 9ac6aa003e..47abfd7c56 100644 --- a/crates/native-sidecar/Cargo.toml +++ b/crates/native-sidecar/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Native Secure Exec sidecar runtime" +description = "Native AgentOS language execution sidecar runtime" [lib] name = "agentos_native_sidecar" @@ -45,6 +45,14 @@ nix = { version = "0.29", features = ["fs", "net", "poll", "process", "signal", # system-openssl discovery on any runner (ubuntu/macOS). openssl backs the # guest crypto runtime (RSA/EC/DH/AES), so it cannot be a TLS-only stack. openssl = { version = "0.10", features = ["vendored"] } +oxc_allocator = "0.75.0" +oxc_ast = "0.75.0" +oxc-browserslist = "=2.0.0" +oxc_codegen = "0.75.0" +oxc_parser = "0.75.0" +oxc_semantic = "0.75.0" +oxc_span = "0.75.0" +oxc_transformer = "0.75.0" pbkdf2 = "0.12" rustls = { version = "0.23.37", default-features = false, features = ["aws_lc_rs", "std", "tls12"] } rustls-pemfile = "2.2" diff --git a/crates/native-sidecar/assets/base-filesystem.json b/crates/native-sidecar/assets/base-filesystem.json index e641efddd3..bdb7b06ec7 100644 --- a/crates/native-sidecar/assets/base-filesystem.json +++ b/crates/native-sidecar/assets/base-filesystem.json @@ -5,8 +5,8 @@ "snapshotCreatedAt": "2026-06-22T19:45:20.529Z", "builtAt": "2026-06-23T03:47:12.644Z", "transforms": [ - "Normalize HOSTNAME to secure-exec", - "Preserve the captured user-level environment and filesystem layout as the secure-exec base layer", + "Normalize HOSTNAME to agentos", + "Preserve the captured user-level environment and filesystem layout as the agentos base layer", "Add the non-Alpine /workspace directory (default agent working directory) owned by the base user", "Restore Alpine 3.22's /etc/services database and add the VM's Docker-style /etc/hosts entries for libc lookup parity" ] @@ -15,7 +15,7 @@ "env": { "CHARSET": "UTF-8", "HOME": "/home/agentos", - "HOSTNAME": "secure-exec", + "HOSTNAME": "agentos", "LANG": "C.UTF-8", "LC_COLLATE": "C", "LOGNAME": "agentos", @@ -92,7 +92,7 @@ "mode": "644", "uid": 0, "gid": 0, - "content": "secure-exec\n" + "content": "agentos\n" }, { "path": "/etc/hosts", @@ -100,7 +100,7 @@ "mode": "644", "uid": 0, "gid": 0, - "content": "127.0.0.1 localhost localhost.localdomain\n::1 localhost localhost.localdomain ip6-localhost ip6-loopback\nfe00:: ip6-localnet\nff00:: ip6-mcastprefix\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n127.0.1.1 secure-exec\n" + "content": "127.0.0.1 localhost localhost.localdomain\n::1 localhost localhost.localdomain ip6-localhost ip6-loopback\nfe00:: ip6-localnet\nff00:: ip6-mcastprefix\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n127.0.1.1 agentos\n" }, { "path": "/etc/logrotate.d", diff --git a/crates/native-sidecar/src/bindings.rs b/crates/native-sidecar/src/bindings.rs index 19ade95e46..6ba4acc312 100644 --- a/crates/native-sidecar/src/bindings.rs +++ b/crates/native-sidecar/src/bindings.rs @@ -199,7 +199,7 @@ fn binding_command_name_from_specifier(command: &str) -> Option<&str> { let file_name = Path::new(command).file_name()?.to_str()?; let normalized = normalize_path(command); let registered_internal_path = normalized - .strip_prefix("/__secure_exec/commands/") + .strip_prefix("/__agentos/commands/") .and_then(|suffix| suffix.rsplit('/').next()) .is_some_and(|name| name == file_name); if !matches!( diff --git a/crates/native-sidecar/src/bootstrap.rs b/crates/native-sidecar/src/bootstrap.rs index 4d9ded5d1a..558a9a1112 100644 --- a/crates/native-sidecar/src/bootstrap.rs +++ b/crates/native-sidecar/src/bootstrap.rs @@ -36,7 +36,7 @@ where pub(crate) fn discover_command_guest_paths(kernel: &mut SidecarKernel) -> BTreeMap { let mut command_guest_paths = BTreeMap::new(); - let Ok(command_roots) = kernel.read_dir("/__secure_exec/commands") else { + let Ok(command_roots) = kernel.read_dir("/__agentos/commands") else { return command_guest_paths; }; @@ -47,7 +47,7 @@ pub(crate) fn discover_command_guest_paths(kernel: &mut SidecarKernel) -> BTreeM ordered_roots.sort(); for root in ordered_roots { - let guest_root = format!("/__secure_exec/commands/{root}"); + let guest_root = format!("/__agentos/commands/{root}"); let Ok(entries) = kernel.read_dir(&guest_root) else { continue; }; diff --git a/crates/native-sidecar/src/crypto_cipher.rs b/crates/native-sidecar/src/crypto_cipher.rs index 088c352251..9728d503f0 100644 --- a/crates/native-sidecar/src/crypto_cipher.rs +++ b/crates/native-sidecar/src/crypto_cipher.rs @@ -527,7 +527,7 @@ mod tests { fn aes_256_cbc_roundtrip() { let key = [7_u8; 32]; let iv = [9_u8; 16]; - let plaintext = b"secure-exec-crypto-surface"; + let plaintext = b"agentos-crypto-surface"; let (ciphertext, _) = encrypt_all("aes-256-cbc", &key, &iv, plaintext); let recovered = decrypt_all("aes-256-cbc", &key, &iv, &ciphertext, None); assert_eq!(recovered, plaintext); diff --git a/crates/native-sidecar/src/execution/javascript/rpc.rs b/crates/native-sidecar/src/execution/javascript/rpc.rs index 2074204375..bbe575c27e 100644 --- a/crates/native-sidecar/src/execution/javascript/rpc.rs +++ b/crates/native-sidecar/src/execution/javascript/rpc.rs @@ -5079,7 +5079,7 @@ mod error_code_tests { } #[test] - fn guest_errno_code_accepts_trusted_secure_exec_prefixes() { + fn guest_errno_code_accepts_trusted_agentos_prefixes() { assert_eq!( guest_errno_code("ERR_AGENTOS_NODE_SYNC_RPC: EACCES: permission denied on /foo"), Some("EACCES") diff --git a/crates/native-sidecar/src/execution/launch.rs b/crates/native-sidecar/src/execution/launch.rs index 2b833ab87b..ae7b772c39 100644 --- a/crates/native-sidecar/src/execution/launch.rs +++ b/crates/native-sidecar/src/execution/launch.rs @@ -1837,7 +1837,7 @@ pub(super) fn resolve_host_node_cli_entrypoint( continue; }; let package_root = entrypoint.parent()?.parent()?.to_path_buf(); - let guest_root = format!("/__secure_exec/node-runtime/{command_name}"); + let guest_root = format!("/__agentos/node-runtime/{command_name}"); let relative_entrypoint = entrypoint.strip_prefix(&package_root).ok()?; let guest_entrypoint = normalize_path(&format!( "{guest_root}/{}", @@ -1942,7 +1942,7 @@ pub(super) fn build_host_node_cli_eval(cli: &ResolvedHostNodeCliEntrypoint) -> S let guest_display_module = normalize_path(&format!("{}/lib/utils/display.js", cli.guest_root)); let guest_log_file_module = normalize_path(&format!("{}/lib/utils/log-file.js", cli.guest_root)); - let debug_preamble = "const __agentOSDebugNpmCli = !!process.env.CODEX_DEBUG_NPM_CLI; const __agentOSDebugLog = (...args) => { if (__agentOSDebugNpmCli) { console.error('[secure-exec npm debug]', ...args); } }; const __agentOSIsProcessExitError = (error) => !!(error && typeof error === 'object' && (error._isProcessExit === true || error.name === 'ProcessExitError')); const __agentOSResolveExitCode = (code) => Number.isFinite(code) ? code : (Number.isFinite(process.exitCode) ? process.exitCode : 0); const __agentOSFinish = (code) => { process.exitCode = __agentOSResolveExitCode(code); }; if (__agentOSDebugNpmCli) { const __agentOSWrapAsyncFsMethod = (__agentOSTarget, __agentOSMethod) => { const __agentOSOriginal = __agentOSTarget[__agentOSMethod]; if (typeof __agentOSOriginal !== 'function' || __agentOSOriginal.__agentOSDebugWrapped) { return; } const __agentOSWrapped = async (...args) => { const target = args.length > 0 ? args[0] : ''; __agentOSDebugLog(`fs.${__agentOSMethod}:start`, String(target)); try { const result = await __agentOSOriginal.apply(__agentOSTarget, args); __agentOSDebugLog(`fs.${__agentOSMethod}:done`, String(target)); return result; } catch (error) { __agentOSDebugLog(`fs.${__agentOSMethod}:error`, String(target), error && error.stack ? error.stack : String(error)); throw error; } }; __agentOSWrapped.__agentOSDebugWrapped = true; __agentOSTarget[__agentOSMethod] = __agentOSWrapped; }; const __agentOSWrapSyncFsMethod = (__agentOSTarget, __agentOSMethod) => { const __agentOSOriginal = __agentOSTarget[__agentOSMethod]; if (typeof __agentOSOriginal !== 'function' || __agentOSOriginal.__agentOSDebugWrapped) { return; } const __agentOSWrapped = (...args) => { const target = args.length > 0 ? args[0] : ''; __agentOSDebugLog(`fs.${__agentOSMethod}:start`, String(target)); try { const result = __agentOSOriginal.apply(__agentOSTarget, args); __agentOSDebugLog(`fs.${__agentOSMethod}:done`, String(target)); return result; } catch (error) { __agentOSDebugLog(`fs.${__agentOSMethod}:error`, String(target), error && error.stack ? error.stack : String(error)); throw error; } }; __agentOSWrapped.__agentOSDebugWrapped = true; __agentOSTarget[__agentOSMethod] = __agentOSWrapped; }; const __agentOSFsPromiseModules = [require('fs/promises'), require('node:fs/promises')]; for (const __agentOSFsPromises of __agentOSFsPromiseModules) { for (const __agentOSMethod of ['access', 'lstat', 'mkdir', 'open', 'readFile', 'readdir', 'readlink', 'realpath', 'rename', 'rm', 'rmdir', 'stat', 'symlink', 'unlink', 'writeFile']) { __agentOSWrapAsyncFsMethod(__agentOSFsPromises, __agentOSMethod); } } const __agentOSFsModules = [require('fs'), require('node:fs')]; for (const __agentOSFs of __agentOSFsModules) { for (const __agentOSMethod of ['accessSync', 'existsSync', 'lstatSync', 'mkdirSync', 'openSync', 'readFileSync', 'readdirSync', 'readlinkSync', 'realpathSync', 'renameSync', 'rmSync', 'rmdirSync', 'statSync', 'symlinkSync', 'unlinkSync', 'writeFileSync']) { __agentOSWrapSyncFsMethod(__agentOSFs, __agentOSMethod); } } }"; + let debug_preamble = "const __agentOSDebugNpmCli = !!process.env.CODEX_DEBUG_NPM_CLI; const __agentOSDebugLog = (...args) => { if (__agentOSDebugNpmCli) { console.error('[agentos npm debug]', ...args); } }; const __agentOSIsProcessExitError = (error) => !!(error && typeof error === 'object' && (error._isProcessExit === true || error.name === 'ProcessExitError')); const __agentOSResolveExitCode = (code) => Number.isFinite(code) ? code : (Number.isFinite(process.exitCode) ? process.exitCode : 0); const __agentOSFinish = (code) => { process.exitCode = __agentOSResolveExitCode(code); }; if (__agentOSDebugNpmCli) { const __agentOSWrapAsyncFsMethod = (__agentOSTarget, __agentOSMethod) => { const __agentOSOriginal = __agentOSTarget[__agentOSMethod]; if (typeof __agentOSOriginal !== 'function' || __agentOSOriginal.__agentOSDebugWrapped) { return; } const __agentOSWrapped = async (...args) => { const target = args.length > 0 ? args[0] : ''; __agentOSDebugLog(`fs.${__agentOSMethod}:start`, String(target)); try { const result = await __agentOSOriginal.apply(__agentOSTarget, args); __agentOSDebugLog(`fs.${__agentOSMethod}:done`, String(target)); return result; } catch (error) { __agentOSDebugLog(`fs.${__agentOSMethod}:error`, String(target), error && error.stack ? error.stack : String(error)); throw error; } }; __agentOSWrapped.__agentOSDebugWrapped = true; __agentOSTarget[__agentOSMethod] = __agentOSWrapped; }; const __agentOSWrapSyncFsMethod = (__agentOSTarget, __agentOSMethod) => { const __agentOSOriginal = __agentOSTarget[__agentOSMethod]; if (typeof __agentOSOriginal !== 'function' || __agentOSOriginal.__agentOSDebugWrapped) { return; } const __agentOSWrapped = (...args) => { const target = args.length > 0 ? args[0] : ''; __agentOSDebugLog(`fs.${__agentOSMethod}:start`, String(target)); try { const result = __agentOSOriginal.apply(__agentOSTarget, args); __agentOSDebugLog(`fs.${__agentOSMethod}:done`, String(target)); return result; } catch (error) { __agentOSDebugLog(`fs.${__agentOSMethod}:error`, String(target), error && error.stack ? error.stack : String(error)); throw error; } }; __agentOSWrapped.__agentOSDebugWrapped = true; __agentOSTarget[__agentOSMethod] = __agentOSWrapped; }; const __agentOSFsPromiseModules = [require('fs/promises'), require('node:fs/promises')]; for (const __agentOSFsPromises of __agentOSFsPromiseModules) { for (const __agentOSMethod of ['access', 'lstat', 'mkdir', 'open', 'readFile', 'readdir', 'readlink', 'realpath', 'rename', 'rm', 'rmdir', 'stat', 'symlink', 'unlink', 'writeFile']) { __agentOSWrapAsyncFsMethod(__agentOSFsPromises, __agentOSMethod); } } const __agentOSFsModules = [require('fs'), require('node:fs')]; for (const __agentOSFs of __agentOSFsModules) { for (const __agentOSMethod of ['accessSync', 'existsSync', 'lstatSync', 'mkdirSync', 'openSync', 'readFileSync', 'readdirSync', 'readlinkSync', 'realpathSync', 'renameSync', 'rmSync', 'rmdirSync', 'statSync', 'symlinkSync', 'unlinkSync', 'writeFileSync']) { __agentOSWrapSyncFsMethod(__agentOSFs, __agentOSMethod); } } }"; let display_stub = format!( "const __agentOSDisplayModulePath = require.resolve({display_module}); const __agentOSLogFileModulePath = require.resolve({log_file_module}); const __agentOSColorPassthrough = new Proxy((value) => value, {{ get: () => __agentOSColorPassthrough, apply: (_target, _thisArg, args) => args[0] }}); class __AgentOSNpmDisplayStub {{ constructor() {{ this.chalk = {{ noColor: __agentOSColorPassthrough, stdout: __agentOSColorPassthrough, stderr: __agentOSColorPassthrough }}; this._logPaused = true; this._logBuffer = []; this._outputBuffer = []; const levels = {{ silent: 0, error: 1, warn: 2, notice: 3, http: 4, info: 5, verbose: 6, silly: 7 }}; const loglevelIndex = process.argv.findIndex((arg) => arg === '--loglevel' || arg.startsWith('--loglevel=')); const loglevelArg = loglevelIndex < 0 ? undefined : process.argv[loglevelIndex]; const configuredLevel = loglevelArg && loglevelArg.includes('=') ? loglevelArg.slice(loglevelArg.indexOf('=') + 1) : process.argv[loglevelIndex + 1]; this._logThreshold = levels[String(configuredLevel || process.env.npm_config_loglevel || 'notice').toLowerCase()] ?? levels.notice; this._shouldLog = (level) => levels[level] === undefined || levels[level] <= this._logThreshold; this._write = (stream, values) => {{ if (!Array.isArray(values) || values.length === 0) {{ return; }} const text = values.map((value) => typeof value === 'string' ? value : String(value)).join(' '); if (text.length === 0) {{ return; }} const normalized = text.replace(/\\r\\n/g, '\\n'); if (/^\\n?> npx\\n> /u.test(normalized)) {{ return; }} stream.write(text.endsWith('\\n') ? text : `${{text}}\\n`); }}; this._inputHandler = (level, ...args) => {{ if (level !== 'read') {{ return; }} const [resolve, reject, callback] = args; Promise.resolve().then(() => callback()).then(resolve, reject); }}; this._logHandler = (level, ...args) => {{ if (level === 'resume') {{ this._logPaused = false; for (const [bufferLevel, bufferArgs] of this._logBuffer.splice(0)) {{ if (this._shouldLog(bufferLevel)) {{ this._write(process.stderr, bufferArgs); }} }} return; }} if (level === 'pause') {{ this._logPaused = true; return; }} if (!this._shouldLog(level)) {{ return; }} if (this._logPaused) {{ this._logBuffer.push([level, args]); return; }} this._write(process.stderr, args); }}; this._outputHandler = (level, ...args) => {{ if (level === 'buffer') {{ this._outputBuffer.push(['standard', args]); return; }} if (level === 'flush') {{ for (const [bufferLevel, bufferArgs] of this._outputBuffer.splice(0)) {{ this._write(bufferLevel === 'error' ? process.stderr : process.stdout, bufferArgs); }} return; }} this._write(level === 'error' ? process.stderr : process.stdout, args); }}; process.on('input', this._inputHandler); process.on('log', this._logHandler); process.on('output', this._outputHandler); }} async load() {{ process.emit('log', 'resume'); process.emit('output', 'flush'); }} off() {{ if (this._inputHandler) {{ process.off('input', this._inputHandler); }} if (this._logHandler) {{ process.off('log', this._logHandler); }} if (this._outputHandler) {{ process.off('output', this._outputHandler); }} this._logBuffer.length = 0; this._outputBuffer.length = 0; }} }} class __AgentOSNpmLogFileStub {{ constructor() {{ this.files = []; }} async load() {{ return []; }} off() {{}} }} globalThis._moduleCache[__agentOSDisplayModulePath] = {{ exports: __AgentOSNpmDisplayStub }}; globalThis._moduleCache[__agentOSLogFileModulePath] = {{ exports: __AgentOSNpmLogFileStub }};", display_module = serde_json::to_string(&guest_display_module) @@ -2288,7 +2288,7 @@ pub(super) fn registered_command_name_for_path(vm: &VmState, path: &str) -> Opti .find_map(|prefix| normalized.strip_prefix(prefix)) .or_else(|| { normalized - .strip_prefix("/__secure_exec/commands/") + .strip_prefix("/__agentos/commands/") .and_then(|suffix| suffix.rsplit('/').next()) })?; (!name.is_empty() && !name.contains('/') && vm.kernel.commands().contains_key(name)) @@ -2608,7 +2608,7 @@ fn resolve_guest_command_path_candidate(vm: &VmState, candidate: &str) -> Option || candidate.starts_with("/usr/bin/") || candidate.starts_with("/usr/local/bin/") || candidate.starts_with(&format!("{}/", crate::package_projection::OPT_AGENTOS_BIN)) - || candidate.starts_with("/__secure_exec/commands/") + || candidate.starts_with("/__agentos/commands/") { if let Some(file_name) = Path::new(candidate) .file_name() @@ -2884,9 +2884,20 @@ pub(super) fn guest_virtual_home(vm: &VmState) -> String { /// Build the typed per-execution Python limits from the per-VM `VmLimits`. pub(super) fn python_execution_limits(vm: &VmState) -> PythonExecutionLimits { + python_execution_limits_with_env(vm, &BTreeMap::new()) +} + +/// Build Python limits while honoring a sidecar-owned per-execution timeout. +pub(super) fn python_execution_limits_with_env( + vm: &VmState, + env: &BTreeMap, +) -> PythonExecutionLimits { PythonExecutionLimits { output_buffer_max_bytes: Some(vm.limits.python.output_buffer_max_bytes), - execution_timeout_ms: Some(vm.limits.python.execution_timeout_ms), + execution_timeout_ms: env + .get("AGENTOS_PYTHON_EXECUTION_TIMEOUT_MS") + .and_then(|value| value.parse().ok()) + .or(Some(vm.limits.python.execution_timeout_ms)), max_old_space_mb: Some(vm.limits.python.max_old_space_mb), vfs_rpc_timeout_ms: Some(vm.limits.python.vfs_rpc_timeout_ms), reactor_work_quantum: vm_reactor_work_quantum(&vm.limits), @@ -4938,7 +4949,7 @@ where file_path: python_file_path, env: env.clone(), cwd: resolved.host_cwd.clone(), - limits: python_execution_limits(vm), + limits: python_execution_limits_with_env(vm, &env), guest_runtime: guest_runtime_identity(vm, None, None), }, vm.runtime_context.clone(), diff --git a/crates/native-sidecar/src/execution/mod.rs b/crates/native-sidecar/src/execution/mod.rs index 34349b918a..0b5df9b174 100644 --- a/crates/native-sidecar/src/execution/mod.rs +++ b/crates/native-sidecar/src/execution/mod.rs @@ -100,9 +100,9 @@ use crate::protocol::{ JavascriptPosixSpawnFileAction, JavascriptSpawnHostNetFd, KillProcessRequest, OwnershipScope, ProcessExitedEvent, ProcessOutputEvent, ProcessSnapshotEntry, ProcessSnapshotStatus, PtyResizedResponse, QueueSnapshotEntry, RequestFrame, ResizePtyRequest, - ResourceSnapshotResponse, ResponseFrame, ResponsePayload, SidecarRequestPayload, - SignalDispositionAction, SignalHandlerRegistration, SocketStateEntry, StreamChannel, - VmFetchRequest, VmFetchResponse, WasmPermissionTier, WriteStdinRequest, + ResourceSnapshotResponse, ResponseFrame, ResponsePayload, RetainedExecutionLanguage, + SidecarRequestPayload, SignalDispositionAction, SignalHandlerRegistration, SocketStateEntry, + StreamChannel, VmFetchRequest, VmFetchResponse, WasmPermissionTier, WriteStdinRequest, }; use crate::service::{ audit_fields, dirname, emit_security_audit_event, emit_structured_event_or_stderr, diff --git a/crates/native-sidecar/src/execution/network/dns.rs b/crates/native-sidecar/src/execution/network/dns.rs index 6133600858..3bb18f532f 100644 --- a/crates/native-sidecar/src/execution/network/dns.rs +++ b/crates/native-sidecar/src/execution/network/dns.rs @@ -138,7 +138,7 @@ fn parse_dns_record_type(rrtype: &str) -> Result { "CAA" => Ok(RecordType::CAA), "ANY" => Ok(RecordType::ANY), other => Err(SidecarError::Execution(format!( - "ERR_NOT_IMPLEMENTED: dns rrtype {other} is not supported by the secure-exec dns bridge" + "ERR_NOT_IMPLEMENTED: dns rrtype {other} is not supported by the agentos dns bridge" ))), } } @@ -324,7 +324,7 @@ fn dns_resolution_to_node_value( .collect(), )), other => Err(SidecarError::Execution(format!( - "ERR_NOT_IMPLEMENTED: dns rrtype {other} is not supported by the secure-exec dns bridge" + "ERR_NOT_IMPLEMENTED: dns rrtype {other} is not supported by the agentos dns bridge" ))), } } diff --git a/crates/native-sidecar/src/execution/network/udp.rs b/crates/native-sidecar/src/execution/network/udp.rs index 9a683b7945..3411b29060 100644 --- a/crates/native-sidecar/src/execution/network/udp.rs +++ b/crates/native-sidecar/src/execution/network/udp.rs @@ -1207,7 +1207,7 @@ impl ActiveUdpSocket { ) -> Result { if self.native_commands.is_some() || self.guest_local_addr.is_some() { return Err(SidecarError::Execution(String::from( - "EINVAL: secure-exec dgram socket is already bound", + "EINVAL: agentos dgram socket is already bound", ))); } diff --git a/crates/native-sidecar/src/execution/process.rs b/crates/native-sidecar/src/execution/process.rs index 05a0bcfab2..ec24f235f9 100644 --- a/crates/native-sidecar/src/execution/process.rs +++ b/crates/native-sidecar/src/execution/process.rs @@ -1545,6 +1545,26 @@ impl ActiveExecution { matches!(self, Self::Javascript(execution) if execution.has_exited()) } + pub(crate) fn execute_retained_language( + &mut self, + language: RetainedExecutionLanguage, + source: String, + file_path: String, + module: bool, + ) -> Result<(), SidecarError> { + match (self, language) { + (Self::Javascript(execution), RetainedExecutionLanguage::JavaScript) => execution + .execute_retained(source, file_path, module) + .map_err(|error| SidecarError::Execution(error.to_string())), + (Self::Python(execution), RetainedExecutionLanguage::Python) => execution + .execute_retained(source) + .map_err(|error| SidecarError::Execution(error.to_string())), + _ => Err(SidecarError::InvalidState(String::from( + "retained language does not match the resident executor", + ))), + } + } + pub(crate) fn child_pid(&self) -> u32 { match self { Self::Javascript(execution) => execution.child_pid(), diff --git a/crates/native-sidecar/src/execution/process_events.rs b/crates/native-sidecar/src/execution/process_events.rs index 248a2360ad..ae7037fc22 100644 --- a/crates/native-sidecar/src/execution/process_events.rs +++ b/crates/native-sidecar/src/execution/process_events.rs @@ -1,4 +1,5 @@ use super::*; +use crate::protocol::ExecutionStreamChannel; pub(super) struct BindingProcessEventRequest { pub(super) runtime_context: agentos_runtime::RuntimeContext, @@ -406,6 +407,7 @@ where ownership: &OwnershipScope, ) -> Result { let mut emitted_any = false; + self.expire_public_execution_deadlines()?; let mut queued_envelopes = Vec::new(); { @@ -846,12 +848,29 @@ where } let (connection_id, session_id) = { (vm.connection_id.clone(), vm.session_id.clone()) }; let ownership = OwnershipScope::vm(&connection_id, &session_id, vm_id); + let public_execution = self.is_public_execution_process(vm_id, process_id); if self.capture_extension_process_output_event(vm_id, process_id, &event) { return Ok(None); } match event { + ActiveExecutionEvent::Stdout(chunk) if public_execution => Ok(self + .record_public_execution_output( + vm_id, + process_id, + ExecutionStreamChannel::Stdout, + chunk, + ) + .map(|payload| EventFrame::new(ownership, payload))), + ActiveExecutionEvent::Stderr(chunk) if public_execution => Ok(self + .record_public_execution_output( + vm_id, + process_id, + ExecutionStreamChannel::Stderr, + chunk, + ) + .map(|payload| EventFrame::new(ownership, payload))), ActiveExecutionEvent::Stdout(chunk) => Ok(Some(EventFrame::new( ownership, EventPayload::ProcessOutput(ProcessOutputEvent { @@ -909,25 +928,37 @@ where process_id, ); record_execute_response_to_exit(vm_id, process_id); + let park_resident = public_execution + && self.should_park_public_execution_process(vm_id, process_id); let phase_start = Instant::now(); - let became_idle = self - .finish_active_process_exit(vm_id, process_id, exit_code)? - .unwrap_or(false); + let became_idle = if park_resident { + false + } else { + self.finish_active_process_exit(vm_id, process_id, exit_code)? + .unwrap_or(false) + }; record_execute_phase("process_exit_cleanup", phase_start.elapsed()); let phase_start = Instant::now(); - if became_idle { + if became_idle || (park_resident && !self.has_running_nonresident_processes(vm_id)) + { self.bridge.emit_lifecycle(vm_id, LifecycleState::Ready)?; } record_execute_phase("process_exit_lifecycle_emit", phase_start.elapsed()); - Ok(Some(EventFrame::new( - ownership, - EventPayload::ProcessExited(ProcessExitedEvent { - process_id: process_id.to_owned(), - exit_code, - }), - ))) + if public_execution { + Ok(self + .complete_public_execution(vm_id, process_id, exit_code) + .map(|payload| EventFrame::new(ownership, payload))) + } else { + Ok(Some(EventFrame::new( + ownership, + EventPayload::ProcessExited(ProcessExitedEvent { + process_id: process_id.to_owned(), + exit_code, + }), + ))) + } } } } diff --git a/crates/native-sidecar/src/filesystem.rs b/crates/native-sidecar/src/filesystem.rs index 9cdb048dd6..f7d7c07f46 100644 --- a/crates/native-sidecar/src/filesystem.rs +++ b/crates/native-sidecar/src/filesystem.rs @@ -5869,7 +5869,7 @@ mod tests { ( Some(writable_mapping( "/mapped/file.txt", - "/tmp/secure-exec-mapped-source", + "/tmp/agentos-mapped-source", )), None, ), @@ -5877,7 +5877,7 @@ mod tests { None, Some(writable_mapping( "/mapped-dst/file.txt", - "/tmp/secure-exec-mapped-destination", + "/tmp/agentos-mapped-destination", )), ), ] { diff --git a/crates/native-sidecar/src/language_execution.rs b/crates/native-sidecar/src/language_execution.rs new file mode 100644 index 0000000000..1e6e98ab56 --- /dev/null +++ b/crates/native-sidecar/src/language_execution.rs @@ -0,0 +1,2072 @@ +//! First-class language execution admission and lifecycle. +//! +//! The public protocol names semantic operations. This module is the only +//! place that lowers them to the process transport used by the execution +//! engines; clients never construct runtime or package-manager commands. + +use crate::protocol::*; +use crate::service::{normalize_path, DispatchResult, NativeSidecar, SidecarError}; +use crate::state::{BridgeError, ExecutionValueKind, ManagedLanguageExecution}; +use crate::NativeSidecarBridge; +use oxc_allocator::Allocator; +use oxc_ast::ast::{ImportDeclarationSpecifier, Statement}; +use oxc_codegen::Codegen; +use oxc_parser::Parser; +use oxc_semantic::SemanticBuilder; +use oxc_span::SourceType; +use oxc_transformer::{Module, TransformOptions, Transformer}; +use std::collections::{BTreeMap, VecDeque}; +use std::fmt; +use std::path::Path; +use std::sync::Arc; +use std::time::{SystemTime, UNIX_EPOCH}; + +const EXECUTION_EVENT_BYTES_LIMIT: usize = 2 * 1024 * 1024; +const EXECUTION_RECORD_LIMIT: usize = 1_024; +const MAX_EXECUTION_OUTPUT_PAGE_EVENTS: u32 = 1_000; +const DEFAULT_EXECUTION_OUTPUT_PAGE_EVENTS: u32 = 100; +const EXECUTION_CANCEL_GRACE_MS: u64 = 1_000; +const TTY_ENV: &str = "AGENTOS_EXEC_TTY"; +const TTY_COLS_ENV: &str = "AGENTOS_EXEC_TTY_COLS"; +const TTY_ROWS_ENV: &str = "AGENTOS_EXEC_TTY_ROWS"; +const RETAIN_LANGUAGE_CONTEXT_ENV: &str = "AGENTOS_RETAIN_LANGUAGE_CONTEXT"; +const INLINE_FILE_PATH_ENV: &str = "AGENTOS_INLINE_FILE_PATH"; +const USE_BUNDLED_TYPESCRIPT_ENV: &str = "AGENTOS_USE_BUNDLED_TYPESCRIPT"; + +#[derive(Debug)] +struct LoweredOperation { + identity: ExecutionIdentityOptions, + command: String, + args: Vec, + cwd: Option, + env: BTreeMap, + stdin: Option>, + pty: Option, + timeout_ms: Option, + retained_language: Option, + retained_source: Option, + retained_file_path: Option, + retained_module: bool, + package_mutation: bool, + value_kind: ExecutionValueKind, + value_marker: Option, +} + +fn now_ms() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_millis() + .try_into() + .unwrap_or(u64::MAX) +} + +fn options( + process: ProcessExecutionOptions, +) -> ( + ExecutionIdentityOptions, + Vec, + Option, + BTreeMap, + Option>, + Option, + Option, +) { + ( + process.identity, + process.args, + process.cwd, + process.env.unwrap_or_default().into_iter().collect(), + process.stdin, + process.pty, + process.timeout_ms, + ) +} + +fn inline_inputs_prefix(inputs: Option, python: bool) -> String { + let inputs = inputs.unwrap_or_else(|| String::from("{}")); + if python { + format!( + "import json as __agentos_json\ninputs = __agentos_json.loads({})\n", + serde_json::to_string(&inputs).expect("JSON string serialization cannot fail") + ) + } else { + format!( + "globalThis.inputs = Object.freeze(JSON.parse({}));\n", + serde_json::to_string(&inputs).expect("JSON string serialization cannot fail") + ) + } +} + +fn evaluation_marker(execution_id_hint: Option<&str>) -> String { + let nonce = now_ms(); + format!( + "__AGENTOS_EVALUATION_{}_{}__", + execution_id_hint.unwrap_or("new"), + nonce + ) +} + +fn typescript_check_runner(request: serde_json::Value, marker: &str) -> String { + const RUNNER: &str = r#" +const __request = __AGENTOS_TYPESCRIPT_REQUEST__; +const __compilerPath = process.env.AGENTOS_TYPESCRIPT_COMPILER_PATH; +if (!__compilerPath) throw new Error("bundled TypeScript compiler path is unavailable"); +const ts = require(__compilerPath); +const path = require("node:path"); + +const diagnostic = (item) => { + const result = { + code: item.code, + category: item.category === ts.DiagnosticCategory.Warning + ? "warning" + : item.category === ts.DiagnosticCategory.Suggestion + ? "suggestion" + : item.category === ts.DiagnosticCategory.Message + ? "message" + : "error", + message: ts.flattenDiagnosticMessageText(item.messageText, "\n").trim(), + }; + if (item.file && item.start !== undefined) { + const location = item.file.getLineAndCharacterOfPosition(item.start); + result.filePath = item.file.fileName.replace(/\\/g, "/"); + result.line = location.line + 1; + result.column = location.character + 1; + } + return result; +}; + +const cwd = path.resolve(__request.cwd || process.cwd()); +let diagnostics; +if (__request.kind === "project") { + const configPath = __request.tsconfigPath + ? path.resolve(cwd, __request.tsconfigPath) + : ts.findConfigFile(cwd, ts.sys.fileExists, "tsconfig.json"); + if (!configPath) throw new Error(`Unable to find tsconfig.json from '${cwd}'`); + const config = ts.readConfigFile(configPath, ts.sys.readFile); + if (config.error) { + diagnostics = [config.error]; + } else { + const parsed = ts.parseJsonConfigFileContent( + config.config, + ts.sys, + path.dirname(configPath), + { noEmit: true }, + configPath, + ); + const program = ts.createProgram({ + rootNames: parsed.fileNames, + options: parsed.options, + projectReferences: parsed.projectReferences, + }); + diagnostics = [...parsed.errors, ...ts.getPreEmitDiagnostics(program)]; + } +} else { + const filePath = path.resolve(cwd, __request.filePath || "agentos-inline.ts"); + let projectOptions = {}; + let configDiagnostics = []; + if (__request.tsconfigPath) { + const configPath = path.resolve(cwd, __request.tsconfigPath); + const config = ts.readConfigFile(configPath, ts.sys.readFile); + if (config.error) { + configDiagnostics = [config.error]; + } else { + const parsed = ts.parseJsonConfigFileContent( + config.config, + ts.sys, + path.dirname(configPath), + {}, + configPath, + ); + projectOptions = parsed.options; + configDiagnostics = parsed.errors; + } + } + const converted = ts.convertCompilerOptionsFromJson( + __request.compilerOptions || {}, + cwd, + ); + const compilerOptions = { + target: ts.ScriptTarget.ES2022, + module: ts.ModuleKind.CommonJS, + ...projectOptions, + ...converted.options, + noEmit: true, + }; + const host = ts.createCompilerHost(compilerOptions); + const normalizedFilePath = ts.sys.useCaseSensitiveFileNames + ? filePath + : filePath.toLowerCase(); + const originalFileExists = host.fileExists.bind(host); + const originalReadFile = host.readFile.bind(host); + const originalGetSourceFile = host.getSourceFile.bind(host); + const normalize = (candidate) => ts.sys.useCaseSensitiveFileNames + ? candidate + : candidate.toLowerCase(); + host.fileExists = (candidate) => + normalize(candidate) === normalizedFilePath || originalFileExists(candidate); + host.readFile = (candidate) => + normalize(candidate) === normalizedFilePath + ? __request.source + : originalReadFile(candidate); + host.getSourceFile = (candidate, languageVersion, onError, fresh) => + normalize(candidate) === normalizedFilePath + ? ts.createSourceFile(candidate, __request.source, languageVersion, true) + : originalGetSourceFile(candidate, languageVersion, onError, fresh); + const program = ts.createProgram([filePath], compilerOptions, host); + diagnostics = [ + ...configDiagnostics, + ...converted.errors, + ...ts.getPreEmitDiagnostics(program), + ]; +} + +const result = ts.sortAndDeduplicateDiagnostics(diagnostics).map(diagnostic); +console.log(__AGENTOS_TYPESCRIPT_MARKER__ + JSON.stringify({ + hasErrors: result.some((item) => item.category === "error"), + diagnostics: result, +})); +"#; + format!("(async () => {{\n{}\n}})()", RUNNER) + .replace( + "__AGENTOS_TYPESCRIPT_REQUEST__", + &serde_json::to_string(&request).expect("TypeScript request serialization cannot fail"), + ) + .replace( + "__AGENTOS_TYPESCRIPT_MARKER__", + &serde_json::to_string(marker).expect("TypeScript marker serialization cannot fail"), + ) +} + +fn transform_source( + source: &str, + file_path: &str, + typescript: bool, + common_js: bool, +) -> Result { + let allocator = Allocator::default(); + let source_type = SourceType::from_path(Path::new(file_path)) + .unwrap_or_default() + .with_typescript(typescript) + .with_module(true); + let parsed = Parser::new(&allocator, source, source_type).parse(); + if !parsed.errors.is_empty() { + let message = parsed + .errors + .into_iter() + .map(|error| error.to_string()) + .collect::>() + .join("\n"); + let language = if typescript { + "TypeScript" + } else { + "JavaScript" + }; + return Err(SidecarError::InvalidState(format!( + "{language} syntax error in {file_path}: {message}" + ))); + } + + let mut program = parsed.program; + let semantic = SemanticBuilder::new() + .with_excess_capacity(2.0) + .build(&program); + if !semantic.errors.is_empty() { + let message = semantic + .errors + .into_iter() + .map(|error| error.to_string()) + .collect::>() + .join("\n"); + let language = if typescript { + "TypeScript" + } else { + "JavaScript" + }; + return Err(SidecarError::InvalidState(format!( + "{language} semantic transform error in {file_path}: {message}" + ))); + } + let mut transform_options = TransformOptions::default(); + if common_js { + transform_options.env.module = Module::CommonJS; + } + let result = Transformer::new(&allocator, Path::new(file_path), &transform_options) + .build_with_scoping(semantic.semantic.into_scoping(), &mut program); + if !result.errors.is_empty() { + let message = result + .errors + .into_iter() + .map(|error| error.to_string()) + .collect::>() + .join("\n"); + let language = if typescript { + "TypeScript" + } else { + "JavaScript" + }; + return Err(SidecarError::InvalidState(format!( + "{language} transpilation failed for {file_path}: {message}" + ))); + } + Ok(Codegen::new().build(&program).code) +} + +fn transpile_typescript( + source: &str, + file_path: &str, + common_js: bool, +) -> Result { + transform_source(source, file_path, true, common_js) +} + +fn transform_retained_javascript_module( + source: &str, + file_path: &str, +) -> Result { + let source = rewrite_static_imports(source, file_path, false)?; + transform_source(&source, file_path, false, true) +} + +fn transform_retained_typescript_module( + source: &str, + file_path: &str, +) -> Result { + let source = rewrite_static_imports(source, file_path, true)?; + transform_source(&source, file_path, true, true) +} + +/// Retained cells execute as scripts so their lexical declarations remain in +/// the context's shared script environment. Rewrite only static imports into +/// equivalent `require` declarations before the normal OXC transform; this +/// keeps the caller's local import names as real retained lexical bindings. +fn rewrite_static_imports( + source: &str, + file_path: &str, + typescript: bool, +) -> Result { + let allocator = Allocator::default(); + let source_type = SourceType::from_path(Path::new(file_path)) + .unwrap_or_default() + .with_typescript(typescript) + .with_module(true); + let parsed = Parser::new(&allocator, source, source_type).parse(); + if !parsed.errors.is_empty() { + let language = if typescript { + "TypeScript" + } else { + "JavaScript" + }; + let message = parsed + .errors + .into_iter() + .map(|error| error.to_string()) + .collect::>() + .join("\n"); + return Err(SidecarError::InvalidState(format!( + "{language} syntax error in {file_path}: {message}" + ))); + } + + let mut replacements = Vec::new(); + for statement in &parsed.program.body { + let Statement::ImportDeclaration(declaration) = statement else { + continue; + }; + let replacement = if declaration.import_kind.is_type() { + String::new() + } else { + let source_literal = serde_json::to_string(declaration.source.value.as_str()) + .expect("module specifier serialization cannot fail"); + let mut declarations = Vec::new(); + match declaration.specifiers.as_deref() { + None => declarations.push(format!("require({source_literal});")), + Some(specifiers) if specifiers.is_empty() => { + declarations.push(format!("require({source_literal});")); + } + Some(specifiers) => { + for specifier in specifiers { + match specifier { + ImportDeclarationSpecifier::ImportSpecifier(specifier) => { + if specifier.import_kind.is_type() { + continue; + } + let imported = + serde_json::to_string(specifier.imported.name().as_str()) + .expect("import name serialization cannot fail"); + declarations.push(format!( + "const {} = require({source_literal})[{imported}];", + specifier.local.name + )); + } + ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => { + declarations.push(format!( + "const {} = (() => {{ const value = require({source_literal}); return value && value.__esModule ? value.default : value; }})();", + specifier.local.name + )); + } + ImportDeclarationSpecifier::ImportNamespaceSpecifier(specifier) => { + declarations.push(format!( + "const {} = require({source_literal});", + specifier.local.name + )); + } + } + } + } + } + declarations.join("\n") + }; + replacements.push(( + declaration.span.start as usize, + declaration.span.end as usize, + replacement, + )); + } + + if replacements.is_empty() { + return Ok(source.to_owned()); + } + let mut rewritten = source.to_owned(); + for (start, end, replacement) in replacements.into_iter().rev() { + rewritten.replace_range(start..end, &replacement); + } + Ok(rewritten) +} + +fn lowered_process( + process: ProcessExecutionOptions, + command: impl Into, + mut prefix_args: Vec, +) -> LoweredOperation { + let (identity, args, cwd, env, stdin, pty, timeout_ms) = options(process); + prefix_args.extend(args); + LoweredOperation { + identity, + command: command.into(), + args: prefix_args, + cwd, + env, + stdin, + pty, + timeout_ms, + retained_language: None, + retained_source: None, + retained_file_path: None, + retained_module: false, + package_mutation: false, + value_kind: ExecutionValueKind::None, + value_marker: None, + } +} + +fn lowered_install( + identity: ExecutionIdentityOptions, + cwd: Option, + env: Option>, + timeout_ms: Option, + command: impl Into, + args: Vec, +) -> LoweredOperation { + LoweredOperation { + identity, + command: command.into(), + args, + cwd, + env: env.unwrap_or_default().into_iter().collect(), + stdin: None, + pty: None, + timeout_ms, + retained_language: None, + retained_source: None, + retained_file_path: None, + retained_module: false, + package_mutation: false, + value_kind: ExecutionValueKind::None, + value_marker: None, + } +} + +fn lower_operation(payload: RequestPayload) -> Result { + let lowered = match payload { + RequestPayload::ShellExecution(payload) => lowered_process( + payload.process, + "sh", + vec![String::from("-c"), payload.command], + ), + RequestPayload::ArgvExecution(payload) => { + lowered_process(payload.process, payload.command, Vec::new()) + } + RequestPayload::JavaScriptExecution(payload) => { + let file_path = payload + .file_path + .unwrap_or_else(|| String::from("/[agentos-inline.js]")); + let module = payload.format == Some(JavaScriptModuleFormat::Module); + let mut source = inline_inputs_prefix(payload.inputs, false); + source.push_str(&payload.source); + if module { + source = transform_retained_javascript_module(&source, &file_path)?; + } + let retained_source = source.clone(); + let mut operation = + lowered_process(payload.process, "node", vec![String::from("-e"), source]); + operation.retained_language = Some(RetainedExecutionLanguage::JavaScript); + operation.retained_source = Some(retained_source); + operation.retained_file_path = Some(file_path.clone()); + operation.retained_module = false; + operation + .env + .insert(String::from(INLINE_FILE_PATH_ENV), file_path); + operation + } + RequestPayload::JavaScriptEvaluation(payload) => { + let file_path = payload + .file_path + .unwrap_or_else(|| String::from("/[agentos-evaluation.js]")); + let module = payload.format == Some(JavaScriptModuleFormat::Module); + let marker = evaluation_marker(payload.process.identity.execution_id.as_deref()); + let mut source = inline_inputs_prefix(payload.inputs, false); + source.push_str(&format!( + "Promise.resolve((async () => ({}))()).then((value) => {{ let result; try {{ if (value === undefined || typeof value === 'function' || typeof value === 'symbol') throw new TypeError('undefined, functions, and symbols are not supported'); result = JSON.stringify({{ __agentosEvaluation: true, ok: true, value }}); }} catch (error) {{ result = JSON.stringify({{ __agentosEvaluation: true, ok: false, error: `AgentOS evaluation result must be JSON-serializable: ${{error instanceof Error ? error.message : String(error)}}` }}); }} console.log({} + result); }});", + payload.expression, + serde_json::to_string(&marker).expect("marker serialization cannot fail") + )); + if module { + source = transform_retained_javascript_module(&source, &file_path)?; + } + let mut operation = + lowered_process(payload.process, "node", vec![String::from("-e"), source]); + operation.retained_language = Some(RetainedExecutionLanguage::JavaScript); + operation.retained_source = operation.args.get(1).cloned(); + operation.retained_file_path = Some(file_path.clone()); + operation.retained_module = false; + operation + .env + .insert(String::from(INLINE_FILE_PATH_ENV), file_path); + operation.value_kind = ExecutionValueKind::JavaScript; + operation.value_marker = Some(marker); + operation + } + RequestPayload::JavaScriptFileExecution(payload) => { + lowered_process(payload.process, "node", vec![payload.path]) + } + RequestPayload::TypeScriptExecution(payload) => { + let file_path = payload + .file_path + .unwrap_or_else(|| String::from("agentos-inline.ts")); + let mut source = inline_inputs_prefix(payload.inputs, false); + source.push_str(&payload.source); + let source = transform_retained_typescript_module(&source, &file_path)?; + let mut operation = + lowered_process(payload.process, "node", vec![String::from("-e"), source]); + operation.retained_language = Some(RetainedExecutionLanguage::JavaScript); + operation.retained_source = operation.args.get(1).cloned(); + operation.retained_file_path = Some(file_path.clone()); + operation + .env + .insert(String::from(INLINE_FILE_PATH_ENV), file_path); + operation + } + RequestPayload::TypeScriptEvaluation(payload) => { + let marker = evaluation_marker(payload.process.identity.execution_id.as_deref()); + let file_path = payload + .file_path + .unwrap_or_else(|| String::from("agentos-evaluation.ts")); + let mut source = inline_inputs_prefix(payload.inputs, false); + source.push_str(&format!( + "Promise.resolve((async () => ({}))()).then((value) => {{ let result; try {{ if (value === undefined || typeof value === 'function' || typeof value === 'symbol') throw new TypeError('undefined, functions, and symbols are not supported'); result = JSON.stringify({{ __agentosEvaluation: true, ok: true, value }}); }} catch (error) {{ result = JSON.stringify({{ __agentosEvaluation: true, ok: false, error: `AgentOS evaluation result must be JSON-serializable: ${{error instanceof Error ? error.message : String(error)}}` }}); }} console.log({} + result); }});", + payload.expression, + serde_json::to_string(&marker).expect("marker serialization cannot fail") + )); + let source = transform_retained_typescript_module(&source, &file_path)?; + let mut operation = + lowered_process(payload.process, "node", vec![String::from("-e"), source]); + operation.retained_language = Some(RetainedExecutionLanguage::JavaScript); + operation.retained_source = operation.args.get(1).cloned(); + operation.retained_file_path = Some(file_path.clone()); + operation + .env + .insert(String::from(INLINE_FILE_PATH_ENV), file_path); + operation.value_kind = ExecutionValueKind::JavaScript; + operation.value_marker = Some(marker); + operation + } + RequestPayload::TypeScriptFileExecution(payload) => lowered_process( + payload.process, + "__agentos_typescript_file", + vec![payload.path], + ), + RequestPayload::TypeScriptCheck(payload) => { + let marker = evaluation_marker(payload.identity.execution_id.as_deref()); + let request = serde_json::json!({ + "kind": "source", + "source": payload.source, + "cwd": payload.cwd, + "filePath": payload.file_path, + "tsconfigPath": payload.tsconfig_path, + "compilerOptions": payload + .compiler_options + .as_deref() + .map(serde_json::from_str::) + .transpose() + .map_err(|error| SidecarError::InvalidState(format!("invalid TypeScript compiler options: {error}")))?, + }); + let mut operation = lowered_install( + payload.identity, + request["cwd"].as_str().map(str::to_owned), + None, + payload.timeout_ms, + "node", + vec![ + String::from("-e"), + typescript_check_runner(request, &marker), + ], + ); + operation + .env + .insert(String::from(USE_BUNDLED_TYPESCRIPT_ENV), String::from("1")); + operation.value_kind = ExecutionValueKind::TypeScriptCheck; + operation.value_marker = Some(marker); + operation + } + RequestPayload::TypeScriptProjectCheck(payload) => { + let marker = evaluation_marker(payload.identity.execution_id.as_deref()); + let cwd = payload.cwd.clone(); + let request = serde_json::json!({ + "kind": "project", + "cwd": payload.cwd, + "tsconfigPath": payload.tsconfig_path, + }); + let mut operation = lowered_install( + payload.identity, + cwd, + None, + payload.timeout_ms, + "node", + vec![ + String::from("-e"), + typescript_check_runner(request, &marker), + ], + ); + operation + .env + .insert(String::from(USE_BUNDLED_TYPESCRIPT_ENV), String::from("1")); + operation.value_kind = ExecutionValueKind::TypeScriptCheck; + operation.value_marker = Some(marker); + operation + } + RequestPayload::NpmProjectInstall(payload) => { + let args = if payload.frozen.unwrap_or(false) { + vec![String::from("ci")] + } else { + vec![String::from("install")] + }; + let mut operation = lowered_install( + payload.identity, + payload.cwd, + payload.env, + payload.timeout_ms, + "npm", + args, + ); + operation.package_mutation = true; + operation + } + RequestPayload::NpmPackageInstall(payload) => { + let mut args = vec![String::from("install")]; + if payload.dev.unwrap_or(false) { + args.push(String::from("--save-dev")); + } + if payload.global.unwrap_or(false) { + args.push(String::from("--global")); + } + args.extend(payload.packages); + let mut operation = lowered_install( + payload.identity, + payload.cwd, + payload.env, + payload.timeout_ms, + "npm", + args, + ); + operation.package_mutation = true; + operation + } + RequestPayload::NpmScriptExecution(payload) => { + let script = payload.script; + lowered_process( + payload.process, + "npm", + vec![String::from("run"), script, String::from("--")], + ) + } + RequestPayload::NpmPackageExecution(payload) => { + let mut args = vec![ + String::from("exec"), + String::from("--package"), + payload.package_spec, + ]; + if let Some(binary) = payload.binary { + args.extend([String::from("--"), binary]); + } + lowered_process(payload.process, "npm", args) + } + RequestPayload::PythonExecution(payload) => { + let mut source = inline_inputs_prefix(payload.inputs, true); + source.push_str(&payload.source); + let mut operation = + lowered_process(payload.process, "python", vec![String::from("-c"), source]); + operation.retained_language = Some(RetainedExecutionLanguage::Python); + operation.retained_source = operation.args.get(1).cloned(); + operation + } + RequestPayload::PythonEvaluation(payload) => { + let marker = evaluation_marker(payload.process.identity.execution_id.as_deref()); + let mut source = inline_inputs_prefix(payload.inputs, true); + source.push_str(&format!( + "\n__agentos_value = ({})\ntry:\n __agentos_result = __agentos_json.dumps({{\"__agentosEvaluation\": True, \"ok\": True, \"value\": __agentos_value}}, allow_nan=False)\nexcept Exception as __agentos_error:\n __agentos_result = __agentos_json.dumps({{\"__agentosEvaluation\": True, \"ok\": False, \"error\": \"AgentOS evaluation result must be JSON-serializable: \" + str(__agentos_error)}})\nprint({} + __agentos_result)\n", + payload.expression, + serde_json::to_string(&marker).expect("marker serialization cannot fail") + )); + let mut operation = + lowered_process(payload.process, "python", vec![String::from("-c"), source]); + operation.retained_language = Some(RetainedExecutionLanguage::Python); + operation.retained_source = operation.args.get(1).cloned(); + operation.value_kind = ExecutionValueKind::Python; + operation.value_marker = Some(marker); + operation + } + RequestPayload::PythonFileExecution(payload) => { + lowered_process(payload.process, "python", vec![payload.path]) + } + RequestPayload::PythonModuleExecution(payload) => lowered_process( + payload.process, + "python", + vec![String::from("-m"), payload.module], + ), + RequestPayload::PythonInstall(payload) => { + if !payload.packages.is_empty() && payload.requirements_file.is_some() { + return Err(SidecarError::InvalidState(String::from( + "installPythonPackages cannot combine packages with requirementsFile", + ))); + } + let mut args = vec![ + String::from("-m"), + String::from("pip"), + String::from("install"), + ]; + if payload.upgrade.unwrap_or(false) { + args.push(String::from("--upgrade")); + } + if let Some(path) = payload.requirements_file { + args.extend([String::from("--requirement"), path]); + } + if let Some(url) = payload.index_url { + args.extend([String::from("--index-url"), url]); + } + for url in payload.extra_index_urls { + args.extend([String::from("--extra-index-url"), url]); + } + args.extend(payload.packages); + let mut operation = lowered_install( + payload.identity, + payload.cwd, + payload.env, + payload.timeout_ms, + "python", + args, + ); + operation.package_mutation = true; + operation + } + _ => { + return Err(SidecarError::InvalidState(String::from( + "request is not a language execution operation", + ))) + } + }; + Ok(lowered) +} + +fn typed_rejection(request: &RequestFrame, code: &str, message: impl AsRef) -> DispatchResult { + DispatchResult { + response: agentos_native_sidecar_core::reject(request, code, message.as_ref()), + events: Vec::new(), + } +} + +impl NativeSidecar +where + B: NativeSidecarBridge + Send + 'static, + BridgeError: fmt::Debug + Send + Sync + 'static, +{ + pub(crate) async fn execute_language_operation( + &mut self, + request: &RequestFrame, + payload: RequestPayload, + ) -> Result { + // The caller deadline begins before source transformation, guest-file + // staging, and compiler staging. The remaining budget is handed to the + // runtime after those sidecar-owned phases finish. + let operation_started_at_ms = now_ms(); + let mut operation = match lower_operation(payload) { + Ok(operation) => operation, + Err(error) => { + return Ok(typed_rejection( + request, + "invalid_execution_request", + error.to_string(), + )); + } + }; + let (connection_id, session_id, vm_id) = self.vm_scope_for(&request.ownership)?; + self.require_owned_vm(&connection_id, &session_id, &vm_id)?; + + if operation.command == "__agentos_typescript_file" { + let requested_path = operation.args.first().cloned().ok_or_else(|| { + SidecarError::InvalidState(String::from( + "executeTypeScriptFile requires a file path", + )) + })?; + let vm = self + .vms + .get_mut(&vm_id) + .ok_or_else(|| SidecarError::InvalidState(format!("unknown sidecar VM {vm_id}")))?; + let guest_path = if requested_path.starts_with('/') { + normalize_path(&requested_path) + } else { + let cwd = operation.cwd.as_deref().unwrap_or(&vm.guest_cwd); + normalize_path(&format!("{}/{requested_path}", cwd.trim_end_matches('/'))) + }; + let source = vm.kernel.read_file(&guest_path).map_err(|error| { + SidecarError::InvalidState(format!( + "failed to read TypeScript file {guest_path}: {error}" + )) + })?; + let source = String::from_utf8(source).map_err(|error| { + SidecarError::InvalidState(format!( + "TypeScript file {guest_path} is not UTF-8: {error}" + )) + })?; + operation.command = String::from("node"); + operation.args = vec![ + String::from("-e"), + transpile_typescript(&source, &guest_path, false)?, + ]; + operation.env.insert( + String::from("AGENTOS_GUEST_ENTRYPOINT_MODULE_MODE"), + String::from("1"), + ); + operation + .env + .insert(String::from(INLINE_FILE_PATH_ENV), guest_path); + } + + if operation + .env + .get(USE_BUNDLED_TYPESCRIPT_ENV) + .is_some_and(|value| value == "1" || value.eq_ignore_ascii_case("true")) + { + const COMPILER_ROOT: &str = "/.agentos/runtime/typescript"; + const COMPILER_PATH: &str = "/.agentos/runtime/typescript/typescript.js"; + let vm = self + .vms + .get_mut(&vm_id) + .ok_or_else(|| SidecarError::InvalidState(format!("unknown sidecar VM {vm_id}")))?; + if !vm.typescript_compiler_staged { + let assets = agentos_execution::bundled_typescript_assets(); + if assets.is_empty() { + return Err(SidecarError::InvalidState(String::from( + "bundled TypeScript compiler is unavailable in this build", + ))); + } + vm.kernel.mkdir(COMPILER_ROOT, true).map_err(|error| { + SidecarError::InvalidState(format!( + "failed to create TypeScript compiler runtime directory: {error}" + )) + })?; + for (file_name, bytes) in assets { + vm.kernel + .write_file(&format!("{COMPILER_ROOT}/{file_name}"), bytes.to_vec()) + .map_err(|error| { + SidecarError::InvalidState(format!( + "failed to stage TypeScript compiler asset {file_name}: {error}" + )) + })?; + } + vm.typescript_compiler_staged = true; + } + operation.env.insert( + String::from("AGENTOS_TYPESCRIPT_COMPILER_PATH"), + String::from(COMPILER_PATH), + ); + } + + let now = now_ms(); + if let Some(timeout_ms) = operation.timeout_ms { + let deadline_ms = operation_started_at_ms.saturating_add(timeout_ms); + operation.timeout_ms = Some(deadline_ms.saturating_sub(now).max(1)); + } + let (output_limit_bytes, output_limit_setting) = { + let vm = self + .vms + .get(&vm_id) + .ok_or_else(|| SidecarError::InvalidState(format!("unknown sidecar VM {vm_id}")))?; + match operation.command.as_str() { + "node" | "npm" | "npx" | "__agentos_typescript_file" => ( + vm.limits.js_runtime.captured_output_limit_bytes, + "limits.jsRuntime.capturedOutputLimitBytes", + ), + "python" | "python3" | "pip" | "pip3" => ( + vm.limits.python.output_buffer_max_bytes, + "limits.python.outputBufferMaxBytes", + ), + _ => ( + vm.limits.wasm.captured_output_limit_bytes, + "limits.wasm.capturedOutputLimitBytes", + ), + } + }; + let execution_id = { + let vm = self + .vms + .get_mut(&vm_id) + .ok_or_else(|| SidecarError::InvalidState(format!("unknown sidecar VM {vm_id}")))?; + if operation.package_mutation { + let active_mutation = vm + .package_mutation_execution_id + .as_ref() + .filter(|execution_id| { + vm.executions.get(*execution_id).is_some_and(|execution| { + execution.descriptor.state == ExecutionState::Running + }) + }) + .cloned(); + if let Some(active_mutation) = active_mutation { + return Ok(typed_rejection( + request, + "execution_busy", + format!( + "package mutation execution {active_mutation} is already running in this VM; package installs are serialized at VM scope" + ), + )); + } + vm.package_mutation_execution_id = None; + } + match operation.identity.execution_id.take() { + Some(execution_id) => { + if let Some(existing) = vm.executions.get(&execution_id) { + if existing.descriptor.state == ExecutionState::Running { + return Ok(typed_rejection( + request, + "execution_busy", + format!("execution {execution_id} already has an active operation"), + )); + } + if existing.descriptor.state == ExecutionState::Failed { + return Ok(typed_rejection( + request, + "execution_failed", + format!("execution {execution_id} must be reset or deleted"), + )); + } + if let (Some(existing), Some(requested)) = ( + existing.descriptor.retained_language.as_ref(), + operation.retained_language.as_ref(), + ) { + if existing != requested { + return Ok(typed_rejection( + request, + "execution_language_conflict", + format!( + "execution {execution_id} is retained for {existing:?}" + ), + )); + } + } + } else if operation.identity.create_if_missing != Some(true) { + return Ok(typed_rejection( + request, + "execution_not_found", + format!("execution {execution_id} does not exist"), + )); + } + if !vm.executions.contains_key(&execution_id) + && vm.executions.len() >= EXECUTION_RECORD_LIMIT + { + return Ok(typed_rejection( + request, + "execution_limit_exceeded", + format!( + "VM execution records reached the limit of {EXECUTION_RECORD_LIMIT}; delete idle executions before creating another" + ), + )); + } + execution_id + } + None => { + if operation.identity.create_if_missing.is_some() { + return Ok(typed_rejection( + request, + "invalid_execution_identity", + "createIfMissing requires an explicit executionId", + )); + } + if vm.executions.len() >= EXECUTION_RECORD_LIMIT { + return Ok(typed_rejection( + request, + "execution_limit_exceeded", + format!( + "VM execution records reached the limit of {EXECUTION_RECORD_LIMIT}; delete idle executions before creating another" + ), + )); + } + loop { + vm.next_public_execution_id = vm.next_public_execution_id.saturating_add(1); + let candidate = format!("exec-{now:x}-{:x}", vm.next_public_execution_id); + if !vm.executions.contains_key(&candidate) { + break candidate; + } + } + } + } + }; + + if let Some(vm) = self.vms.get(&vm_id) { + let next_count = vm.executions.len().saturating_add(1); + let warning_threshold = EXECUTION_RECORD_LIMIT.saturating_mul(4) / 5; + if !vm.executions.contains_key(&execution_id) && next_count == warning_threshold { + eprintln!( + "agentos VM {vm_id} retained {next_count} of {EXECUTION_RECORD_LIMIT} execution records; delete idle executions before reaching the limit" + ); + } + } + + let (process_id, generation, descriptor, reused_resident) = { + let vm = self.vms.get_mut(&vm_id).expect("owned VM checked above"); + let resident_process_id = operation + .retained_source + .as_ref() + .and_then(|_| vm.executions.get(&execution_id)) + .and_then(|execution| execution.resident_process_id.clone()) + .filter(|process_id| vm.active_processes.contains_key(process_id)); + let resident_pid = resident_process_id + .as_ref() + .and_then(|process_id| vm.active_processes.get(process_id)) + .map(|process| process.kernel_pid); + let reused_resident = resident_process_id.is_some(); + let execution = vm + .executions + .entry(execution_id.clone()) + .or_insert_with(|| ManagedLanguageExecution { + descriptor: ExecutionDescriptor { + execution_id: execution_id.clone(), + generation: 0, + state: ExecutionState::Creating, + retained_language: None, + process_id: None, + pid: None, + created_at_ms: now, + last_started_at_ms: None, + last_completed_at_ms: None, + last_outcome: None, + last_exit_code: None, + }, + result: None, + events: VecDeque::new(), + retained_event_bytes: 0, + output_truncated: false, + next_sequence: 0, + stdout: Vec::new(), + stderr: Vec::new(), + stdout_truncated: false, + stderr_truncated: false, + output_limit_bytes, + output_limit_setting, + event_limit: self.config.runtime.protocol.max_process_events.max(1), + event_bytes_limit: EXECUTION_EVENT_BYTES_LIMIT, + uses_pty: false, + value_kind: ExecutionValueKind::None, + value_marker: None, + pending_outcome: None, + deadline_ms: None, + deadline_task: None, + resident_process_id: None, + }); + if let Some(task) = execution.deadline_task.take() { + task.abort(); + } + execution.descriptor.generation = execution.descriptor.generation.saturating_add(1); + execution.descriptor.state = ExecutionState::Running; + execution.descriptor.retained_language = execution + .descriptor + .retained_language + .clone() + .or(operation.retained_language.clone()); + execution.descriptor.last_started_at_ms = Some(now); + execution.descriptor.last_completed_at_ms = None; + execution.descriptor.last_outcome = None; + execution.descriptor.last_exit_code = None; + execution.result = None; + execution.events.clear(); + execution.retained_event_bytes = 0; + execution.output_truncated = false; + execution.next_sequence = 0; + execution.stdout.clear(); + execution.stderr.clear(); + execution.stdout_truncated = false; + execution.stderr_truncated = false; + execution.output_limit_bytes = output_limit_bytes; + execution.output_limit_setting = output_limit_setting; + execution.uses_pty = operation.pty.is_some(); + execution.value_kind = operation.value_kind; + execution.value_marker = operation.value_marker.clone(); + execution.pending_outcome = None; + execution.deadline_ms = operation + .timeout_ms + .map(|timeout| now.saturating_add(timeout)); + let generation = execution.descriptor.generation; + let process_id = resident_process_id + .unwrap_or_else(|| format!("execution:{execution_id}:{generation}")); + execution.descriptor.process_id = Some(process_id.clone()); + execution.descriptor.pid = resident_pid; + if operation.retained_source.is_some() { + execution.resident_process_id = Some(process_id.clone()); + } + vm.execution_processes + .insert(process_id.clone(), execution_id.clone()); + if operation.package_mutation { + vm.package_mutation_execution_id = Some(execution_id.clone()); + } + ( + process_id, + generation, + execution.descriptor.clone(), + reused_resident, + ) + }; + + if let Some(timeout_ms) = operation.timeout_ms { + let notify = Arc::clone(&self.process_event_notify); + let runtime = self + .vms + .get(&vm_id) + .expect("owned VM checked above") + .runtime_context + .clone(); + let task = runtime + .spawn(agentos_runtime::TaskClass::Timer, async move { + tokio::time::sleep(std::time::Duration::from_millis(timeout_ms)).await; + notify.notify_one(); + }) + .map_err(|error| SidecarError::Execution(error.to_string()))?; + self.vms + .get_mut(&vm_id) + .and_then(|vm| vm.executions.get_mut(&execution_id)) + .expect("admitted execution exists") + .deadline_task = Some(task); + } + + if let Some(pty) = &operation.pty { + operation + .env + .insert(String::from(TTY_ENV), String::from("1")); + if let Some(cols) = pty.cols { + operation + .env + .insert(String::from(TTY_COLS_ENV), cols.to_string()); + } + if let Some(rows) = pty.rows { + operation + .env + .insert(String::from(TTY_ROWS_ENV), rows.to_string()); + } + } + if let Some(timeout_ms) = operation.timeout_ms { + if matches!(operation.command.as_str(), "node" | "npm" | "npx") { + operation.env.insert( + String::from("AGENTOS_V8_WALL_CLOCK_LIMIT_MS"), + timeout_ms.to_string(), + ); + } else if matches!( + operation.command.as_str(), + "python" | "python3" | "pip" | "pip3" + ) { + operation.env.insert( + String::from("AGENTOS_PYTHON_EXECUTION_TIMEOUT_MS"), + timeout_ms.to_string(), + ); + } + } + if operation.retained_source.is_some() { + operation + .env + .insert(String::from(RETAIN_LANGUAGE_CONTEXT_ENV), String::from("1")); + } + let execute_payload = ExecuteRequest { + process_id: process_id.clone(), + command: Some(operation.command), + runtime: None, + entrypoint: None, + args: operation.args, + env: operation.env.into_iter().collect(), + cwd: operation.cwd, + wasm_permission_tier: None, + }; + let launch_result = if reused_resident { + let language = operation + .retained_language + .clone() + .expect("resident operations have a retained language"); + let source = operation + .retained_source + .clone() + .expect("resident operations have retained source"); + let file_path = operation + .retained_file_path + .clone() + .unwrap_or_else(|| String::from("/[agentos-retained]")); + let vm = self.vms.get_mut(&vm_id).expect("owned VM checked above"); + let process = vm.active_processes.get_mut(&process_id).ok_or_else(|| { + SidecarError::InvalidState(format!( + "resident process {process_id} disappeared before execution" + )) + })?; + process + .execution + .execute_retained_language(language, source, file_path, operation.retained_module) + .map(|()| None) + } else { + self.execute(request, execute_payload).await.map(Some) + }; + let launch = match launch_result { + Ok(result) => result, + Err(error) => { + if reused_resident { + let _ = self.finish_active_process_exit(&vm_id, &process_id, 1); + } + if let Some(vm) = self.vms.get_mut(&vm_id) { + vm.execution_processes.remove(&process_id); + if vm.package_mutation_execution_id.as_deref() == Some(&execution_id) { + vm.package_mutation_execution_id = None; + } + if let Some(execution) = vm.executions.get_mut(&execution_id) { + if let Some(task) = execution.deadline_task.take() { + task.abort(); + } + execution.resident_process_id = None; + execution.descriptor.state = ExecutionState::Failed; + execution.descriptor.process_id = None; + execution.descriptor.pid = None; + execution.descriptor.last_completed_at_ms = Some(now_ms()); + execution.descriptor.last_outcome = Some(ExecutionOutcome::Failed); + execution.result = Some(failed_result( + execution.descriptor.clone(), + "execution_start_failed", + error.to_string(), + )); + } + } + let result = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&execution_id)) + .and_then(|execution| execution.result.clone()) + .expect("admitted start failure stores a result"); + return Ok(DispatchResult { + response: self.respond( + request, + ResponsePayload::ExecutionAccepted(ExecutionAcceptedResponse { + execution: result.execution.clone(), + }), + ), + events: vec![EventFrame::new( + request.ownership.clone(), + EventPayload::ExecutionCompleted(ExecutionCompletedEvent { + execution_id, + generation, + outcome: ExecutionOutcome::Failed, + exit_code: None, + error: result.error, + }), + )], + }); + } + }; + + if let Some(launch) = &launch { + if let ResponsePayload::ProcessStarted(started) = &launch.response.payload { + if let Some(execution) = self + .vms + .get_mut(&vm_id) + .and_then(|vm| vm.executions.get_mut(&execution_id)) + { + execution.descriptor.pid = started.pid; + } + } + } + + if let Some(stdin) = operation.stdin { + self.write_stdin( + request, + WriteStdinRequest { + process_id: process_id.clone(), + chunk: stdin, + }, + ) + .await?; + } + + let descriptor = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&execution_id)) + .map(|execution| execution.descriptor.clone()) + .unwrap_or(descriptor); + debug_assert_eq!(descriptor.generation, generation); + Ok(DispatchResult { + response: self.respond( + request, + ResponsePayload::ExecutionAccepted(ExecutionAcceptedResponse { + execution: descriptor, + }), + ), + events: launch.map_or_else(Vec::new, |launch| launch.events), + }) + } + + pub(crate) async fn handle_execution_lifecycle( + &mut self, + request: &RequestFrame, + payload: RequestPayload, + ) -> Result { + let (connection_id, session_id, vm_id) = self.vm_scope_for(&request.ownership)?; + self.require_owned_vm(&connection_id, &session_id, &vm_id)?; + + let response = match payload { + RequestPayload::GetExecution(payload) => { + let Some(execution) = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&payload.execution_id)) + else { + return Ok(typed_rejection( + request, + "execution_not_found", + format!("execution {} does not exist", payload.execution_id), + )); + }; + ResponsePayload::ExecutionDescriptor(ExecutionDescriptorResponse { + execution: execution.descriptor.clone(), + }) + } + RequestPayload::ListExecutions(_) => { + let executions = self + .vms + .get(&vm_id) + .map(|vm| { + vm.executions + .values() + .map(|item| item.descriptor.clone()) + .collect() + }) + .unwrap_or_default(); + ResponsePayload::ExecutionList(ExecutionListResponse { executions }) + } + RequestPayload::WaitExecution(payload) => { + let Some(execution) = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&payload.execution_id)) + else { + return Ok(typed_rejection( + request, + "execution_not_found", + format!("execution {} does not exist", payload.execution_id), + )); + }; + if execution.descriptor.state == ExecutionState::Running { + return Ok(typed_rejection( + request, + "execution_busy", + format!("execution {} is still running", payload.execution_id), + )); + } + let Some(result) = execution.result.clone() else { + return Ok(typed_rejection( + request, + "execution_result_not_found", + format!( + "execution {} has no completed operation", + payload.execution_id + ), + )); + }; + ResponsePayload::ExecutionCompleted(result) + } + RequestPayload::CancelExecution(payload) => { + let process_id = match active_process_id(self, &vm_id, &payload.execution_id) { + Ok(process_id) => process_id, + Err((code, message)) => return Ok(typed_rejection(request, code, message)), + }; + if let Some(execution) = self + .vms + .get_mut(&vm_id) + .and_then(|vm| vm.executions.get_mut(&payload.execution_id)) + { + execution.pending_outcome = Some(ExecutionOutcome::Cancelled); + execution.deadline_ms = + Some(now_ms().saturating_add(EXECUTION_CANCEL_GRACE_MS)); + if let Some(task) = execution.deadline_task.take() { + task.abort(); + } + } + self.kill_process_internal(&vm_id, &process_id, "SIGTERM")?; + let notify = Arc::clone(&self.process_event_notify); + let runtime = self + .vms + .get(&vm_id) + .expect("execution VM exists") + .runtime_context + .clone(); + let task = runtime + .spawn(agentos_runtime::TaskClass::Timer, async move { + tokio::time::sleep(std::time::Duration::from_millis( + EXECUTION_CANCEL_GRACE_MS, + )) + .await; + notify.notify_one(); + }) + .map_err(|error| SidecarError::Execution(error.to_string()))?; + self.vms + .get_mut(&vm_id) + .and_then(|vm| vm.executions.get_mut(&payload.execution_id)) + .expect("execution checked above") + .deadline_task = Some(task); + let descriptor = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&payload.execution_id)) + .expect("execution checked above") + .descriptor + .clone(); + ResponsePayload::ExecutionDescriptor(ExecutionDescriptorResponse { + execution: descriptor, + }) + } + RequestPayload::SignalExecution(payload) => { + let process_id = match active_process_id(self, &vm_id, &payload.execution_id) { + Ok(process_id) => process_id, + Err((code, message)) => return Ok(typed_rejection(request, code, message)), + }; + self.kill_process_internal(&vm_id, &process_id, &payload.signal)?; + let descriptor = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&payload.execution_id)) + .expect("execution checked above") + .descriptor + .clone(); + ResponsePayload::ExecutionDescriptor(ExecutionDescriptorResponse { + execution: descriptor, + }) + } + RequestPayload::ResetExecution(payload) => { + let Some(existing) = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&payload.execution_id)) + else { + return Ok(typed_rejection( + request, + "execution_not_found", + format!("execution {} does not exist", payload.execution_id), + )); + }; + if existing.descriptor.state == ExecutionState::Running { + return Ok(typed_rejection( + request, + "execution_busy", + format!("execution {} is running", payload.execution_id), + )); + } + let resident_process_id = existing.resident_process_id.clone(); + if let Some(process_id) = resident_process_id { + self.finish_active_process_exit(&vm_id, &process_id, 0)?; + if let Some(vm) = self.vms.get_mut(&vm_id) { + vm.execution_processes.remove(&process_id); + } + } + let execution = self + .vms + .get_mut(&vm_id) + .and_then(|vm| vm.executions.get_mut(&payload.execution_id)) + .expect("execution checked above"); + execution.descriptor.state = ExecutionState::Resetting; + execution.descriptor.generation = execution.descriptor.generation.saturating_add(1); + execution.descriptor.retained_language = None; + execution.descriptor.process_id = None; + execution.descriptor.pid = None; + execution.descriptor.last_started_at_ms = None; + execution.descriptor.last_completed_at_ms = None; + execution.descriptor.last_outcome = None; + execution.descriptor.last_exit_code = None; + execution.result = None; + execution.events.clear(); + execution.retained_event_bytes = 0; + execution.stdout.clear(); + execution.stderr.clear(); + execution.value_marker = None; + execution.value_kind = ExecutionValueKind::None; + execution.deadline_ms = None; + if let Some(task) = execution.deadline_task.take() { + task.abort(); + } + execution.resident_process_id = None; + execution.descriptor.state = ExecutionState::Idle; + ResponsePayload::ExecutionDescriptor(ExecutionDescriptorResponse { + execution: execution.descriptor.clone(), + }) + } + RequestPayload::DeleteExecution(payload) => { + let Some(execution) = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&payload.execution_id)) + else { + return Ok(typed_rejection( + request, + "execution_not_found", + format!("execution {} does not exist", payload.execution_id), + )); + }; + if execution.descriptor.state == ExecutionState::Running { + return Ok(typed_rejection( + request, + "execution_busy", + format!("execution {} is running", payload.execution_id), + )); + } + let resident_process_id = execution.resident_process_id.clone(); + if let Some(process_id) = resident_process_id { + self.finish_active_process_exit(&vm_id, &process_id, 0)?; + if let Some(vm) = self.vms.get_mut(&vm_id) { + vm.execution_processes.remove(&process_id); + } + } + self.vms + .get_mut(&vm_id) + .expect("owned VM checked above") + .executions + .remove(&payload.execution_id); + ResponsePayload::ExecutionDeleted(ExecutionDeletedResponse { + execution_id: payload.execution_id, + }) + } + RequestPayload::WriteExecutionStdin(payload) => { + let process_id = match active_process_id(self, &vm_id, &payload.execution_id) { + Ok(process_id) => process_id, + Err((code, message)) => return Ok(typed_rejection(request, code, message)), + }; + let accepted = payload.chunk.len() as u64; + self.write_stdin( + request, + WriteStdinRequest { + process_id, + chunk: payload.chunk, + }, + ) + .await?; + ResponsePayload::ExecutionIo(ExecutionIoResponse { + execution_id: payload.execution_id, + accepted_bytes: Some(accepted), + }) + } + RequestPayload::CloseExecutionStdin(payload) => { + let process_id = match active_process_id(self, &vm_id, &payload.execution_id) { + Ok(process_id) => process_id, + Err((code, message)) => return Ok(typed_rejection(request, code, message)), + }; + self.close_stdin(request, CloseStdinRequest { process_id }) + .await?; + ResponsePayload::ExecutionIo(ExecutionIoResponse { + execution_id: payload.execution_id, + accepted_bytes: None, + }) + } + RequestPayload::ResizeExecutionPty(payload) => { + let process_id = match active_process_id(self, &vm_id, &payload.execution_id) { + Ok(process_id) => process_id, + Err((code, message)) => return Ok(typed_rejection(request, code, message)), + }; + self.resize_pty( + request, + ResizePtyRequest { + process_id, + cols: payload.cols, + rows: payload.rows, + }, + ) + .await?; + ResponsePayload::ExecutionIo(ExecutionIoResponse { + execution_id: payload.execution_id, + accepted_bytes: None, + }) + } + RequestPayload::ReadExecutionOutput(payload) => { + let Some(execution) = self + .vms + .get(&vm_id) + .and_then(|vm| vm.executions.get(&payload.execution_id)) + else { + return Ok(typed_rejection( + request, + "execution_not_found", + format!("execution {} does not exist", payload.execution_id), + )); + }; + let start = match payload.cursor.as_deref() { + None => 0, + Some(cursor) => { + let Some(start) = parse_cursor(cursor, execution.descriptor.generation) + else { + return Ok(typed_rejection( + request, + "execution_output_cursor_expired", + "the output cursor belongs to an earlier execution generation", + )); + }; + start + } + }; + let limit = payload + .limit + .unwrap_or(DEFAULT_EXECUTION_OUTPUT_PAGE_EVENTS) + .clamp(1, MAX_EXECUTION_OUTPUT_PAGE_EVENTS) + as usize; + let events: Vec<_> = execution + .events + .iter() + .filter(|event| event.sequence >= start) + .take(limit) + .cloned() + .collect(); + let next_sequence = events + .last() + .map_or(start, |event| event.sequence.saturating_add(1)); + let has_more = execution + .events + .iter() + .any(|event| event.sequence >= next_sequence); + ResponsePayload::ExecutionOutputPage(ExecutionOutputPageResponse { + execution_id: payload.execution_id, + generation: execution.descriptor.generation, + events, + next_cursor: format!("{}:{next_sequence}", execution.descriptor.generation), + has_more, + truncated: execution.output_truncated, + }) + } + _ => { + return Err(SidecarError::InvalidState(String::from( + "request is not an execution lifecycle operation", + ))) + } + }; + Ok(DispatchResult { + response: self.respond(request, response), + events: Vec::new(), + }) + } + + pub(crate) fn is_public_execution_process(&self, vm_id: &str, process_id: &str) -> bool { + self.vms + .get(vm_id) + .is_some_and(|vm| vm.execution_processes.contains_key(process_id)) + } + + pub(crate) fn should_park_public_execution_process( + &self, + vm_id: &str, + process_id: &str, + ) -> bool { + self.vms + .get(vm_id) + .and_then(|vm| { + let execution_id = vm.execution_processes.get(process_id)?; + vm.executions.get(execution_id) + }) + .is_some_and(|execution| { + execution.resident_process_id.as_deref() == Some(process_id) + && execution.pending_outcome.is_none() + && !execution + .deadline_ms + .is_some_and(|deadline| now_ms() >= deadline) + }) + } + + pub(crate) fn has_running_nonresident_processes(&self, vm_id: &str) -> bool { + let Some(vm) = self.vms.get(vm_id) else { + return false; + }; + vm.active_processes.keys().any(|process_id| { + !vm.executions + .values() + .any(|execution| execution.resident_process_id.as_deref() == Some(process_id)) + }) + } + + pub(crate) fn expire_public_execution_deadlines(&mut self) -> Result<(), SidecarError> { + let now = now_ms(); + let due = self + .vms + .iter() + .flat_map(|(vm_id, vm)| { + vm.executions.iter().filter_map(move |(_, execution)| { + (execution.descriptor.state == ExecutionState::Running + && execution + .deadline_ms + .is_some_and(|deadline| now >= deadline)) + .then(|| { + execution + .descriptor + .process_id + .as_ref() + .map(|process_id| (vm_id.clone(), process_id.clone())) + }) + .flatten() + }) + }) + .collect::>(); + for (vm_id, process_id) in due { + if let Some(execution_id) = self + .vms + .get(&vm_id) + .and_then(|vm| vm.execution_processes.get(&process_id)) + .cloned() + { + if let Some(execution) = self + .vms + .get_mut(&vm_id) + .and_then(|vm| vm.executions.get_mut(&execution_id)) + { + if execution.pending_outcome != Some(ExecutionOutcome::Cancelled) { + execution.pending_outcome = Some(ExecutionOutcome::TimedOut); + } + execution.deadline_ms = None; + } + // A deadline is already terminal. Force the process tree so a + // CPU-bound guest cannot defer timeout handling indefinitely. + self.kill_process_internal(&vm_id, &process_id, "SIGKILL")?; + } + } + Ok(()) + } + + pub(crate) fn record_public_execution_output( + &mut self, + vm_id: &str, + process_id: &str, + channel: ExecutionStreamChannel, + chunk: Vec, + ) -> Option { + let vm = self.vms.get_mut(vm_id)?; + let execution_id = vm.execution_processes.get(process_id)?.clone(); + let execution = vm.executions.get_mut(&execution_id)?; + if vm.package_mutation_execution_id.as_deref() == Some(&execution_id) { + vm.package_mutation_execution_id = None; + } + let channel = if execution.uses_pty { + ExecutionStreamChannel::Pty + } else { + channel + }; + let target = if matches!(channel, ExecutionStreamChannel::Stderr) { + &mut execution.stderr + } else { + &mut execution.stdout + }; + let previous_len = target.len(); + let available = execution.output_limit_bytes.saturating_sub(target.len()); + let retained_len = chunk.len().min(available); + target.extend_from_slice(&chunk[..retained_len]); + let warning_threshold = execution.output_limit_bytes.saturating_mul(4) / 5; + if previous_len < warning_threshold && target.len() >= warning_threshold { + eprintln!( + "agentos execution {} {:?} output reached {} of {} bytes; raise {} for more retained output", + execution.descriptor.execution_id, + channel, + target.len(), + execution.output_limit_bytes, + execution.output_limit_setting, + ); + } + if retained_len < chunk.len() { + if matches!(channel, ExecutionStreamChannel::Stderr) { + execution.stderr_truncated = true; + } else { + execution.stdout_truncated = true; + } + } + + let event = ExecutionOutputEvent { + execution_id, + generation: execution.descriptor.generation, + process_id: Some(process_id.to_owned()), + sequence: execution.next_sequence, + channel, + chunk, + timestamp_ms: now_ms(), + }; + execution.next_sequence = execution.next_sequence.saturating_add(1); + let event_bytes = event.chunk.len(); + while execution.events.len() >= execution.event_limit + || execution.retained_event_bytes.saturating_add(event_bytes) + > execution.event_bytes_limit + { + let Some(expired) = execution.events.pop_front() else { + break; + }; + execution.retained_event_bytes = execution + .retained_event_bytes + .saturating_sub(expired.chunk.len()); + execution.output_truncated = true; + } + if event_bytes <= execution.event_bytes_limit { + execution.retained_event_bytes = + execution.retained_event_bytes.saturating_add(event_bytes); + execution.events.push_back(event.clone()); + } else { + execution.output_truncated = true; + } + Some(EventPayload::ExecutionOutput(event)) + } + + pub(crate) fn complete_public_execution( + &mut self, + vm_id: &str, + process_id: &str, + exit_code: i32, + ) -> Option { + let vm = self.vms.get_mut(vm_id)?; + let execution_id = vm.execution_processes.get(process_id)?.clone(); + let resident_process_id = vm + .executions + .get(&execution_id) + .and_then(|execution| execution.resident_process_id.clone()) + .filter(|resident_id| vm.active_processes.contains_key(resident_id)); + let completing_resident = resident_process_id.as_deref() == Some(process_id); + if !completing_resident { + vm.execution_processes.remove(process_id); + } + let execution = vm.executions.get_mut(&execution_id)?; + if execution.resident_process_id.is_some() && resident_process_id.is_none() { + execution.resident_process_id = None; + } + let deadline_expired = execution + .deadline_ms + .take() + .is_some_and(|deadline| now_ms() >= deadline); + if let Some(task) = execution.deadline_task.take() { + task.abort(); + } + let mut outcome = execution.pending_outcome.take().unwrap_or_else(|| { + if deadline_expired { + return ExecutionOutcome::TimedOut; + } + if exit_code == 0 { + ExecutionOutcome::Succeeded + } else { + ExecutionOutcome::Failed + } + }); + let (outputs, evaluation_error) = if outcome == ExecutionOutcome::Succeeded { + match extract_evaluation_output(execution) { + Ok(outputs) => (outputs, None), + Err(message) => { + outcome = ExecutionOutcome::Failed; + (String::from("[]"), Some(message)) + } + } + } else { + execution.value_marker = None; + (String::from("[]"), None) + }; + + execution.descriptor.state = ExecutionState::Idle; + execution.descriptor.process_id = None; + execution.descriptor.pid = None; + execution.descriptor.last_completed_at_ms = Some(now_ms()); + execution.descriptor.last_outcome = Some(outcome.clone()); + execution.descriptor.last_exit_code = Some(exit_code); + + let error = if let Some(message) = evaluation_error { + Some(ExecutionErrorData { + code: String::from("evaluation_serialization_failed"), + name: String::from("ExecutionEvaluationError"), + message, + stack: None, + details: None, + }) + } else if outcome == ExecutionOutcome::Succeeded { + None + } else { + Some(ExecutionErrorData { + code: match outcome { + ExecutionOutcome::Cancelled => String::from("execution_cancelled"), + ExecutionOutcome::TimedOut => String::from("execution_timed_out"), + ExecutionOutcome::Failed | ExecutionOutcome::Succeeded => { + String::from("execution_failed") + } + }, + name: String::from("ExecutionError"), + message: match outcome { + ExecutionOutcome::Cancelled => String::from("execution was cancelled"), + ExecutionOutcome::TimedOut => String::from("execution timed out"), + ExecutionOutcome::Failed | ExecutionOutcome::Succeeded => { + format!("execution exited with code {exit_code}") + } + }, + stack: None, + details: None, + }) + }; + execution.result = Some(ExecutionCompletedResponse { + execution: execution.descriptor.clone(), + outcome: outcome.clone(), + exit_code: Some(exit_code), + error: error.clone(), + stdout: execution.stdout.clone(), + stderr: execution.stderr.clone(), + stdout_truncated: execution.stdout_truncated, + stderr_truncated: execution.stderr_truncated, + outputs, + }); + Some(EventPayload::ExecutionCompleted(ExecutionCompletedEvent { + execution_id, + generation: execution.descriptor.generation, + outcome, + exit_code: Some(exit_code), + error, + })) + } +} + +fn extract_evaluation_output(execution: &mut ManagedLanguageExecution) -> Result { + let Some(marker) = execution.value_marker.take() else { + return Ok(String::from("[]")); + }; + let stdout = String::from_utf8_lossy(&execution.stdout); + let Some(start) = stdout.rfind(&marker) else { + return Err(format!( + "evaluation produced no complete JSON result; the value must be JSON-serializable and fit within the {}-byte output limit (raise {})", + execution.output_limit_bytes, execution.output_limit_setting + )); + }; + let value_start = start.saturating_add(marker.len()); + let value_end = stdout[value_start..] + .find('\n') + .map_or(stdout.len(), |offset| value_start.saturating_add(offset)); + let value = stdout[value_start..value_end].to_owned(); + let mut clean = stdout.as_bytes().to_vec(); + let remove_end = if value_end < clean.len() { + value_end.saturating_add(1) + } else { + value_end + }; + clean.drain(start..remove_end); + execution.stdout = clean; + let value = serde_json::from_str::(&value).map_err(|error| { + format!( + "evaluation result must be JSON-serializable: {error}; raise {} if the retained result was truncated", + execution.output_limit_setting + ) + })?; + let value = match execution.value_kind { + ExecutionValueKind::JavaScript | ExecutionValueKind::Python => { + let object = value.as_object().ok_or_else(|| { + String::from("evaluation returned an invalid internal result envelope") + })?; + if object.get("__agentosEvaluation") != Some(&serde_json::Value::Bool(true)) { + return Err(String::from( + "evaluation returned an invalid internal result envelope", + )); + } + if object.get("ok") == Some(&serde_json::Value::Bool(false)) { + return Err(object + .get("error") + .and_then(serde_json::Value::as_str) + .unwrap_or("evaluation result must be JSON-serializable") + .to_owned()); + } + object.get("value").cloned().ok_or_else(|| { + String::from( + "AgentOS evaluation result must be JSON-serializable; undefined, functions, and symbols are not supported", + ) + })? + } + ExecutionValueKind::TypeScriptCheck | ExecutionValueKind::None => value, + }; + serde_json::to_string(&serde_json::json!([{ "type": "json", "data": value }])) + .map_err(|error| format!("failed to serialize evaluation display output: {error}")) +} + +fn active_process_id( + sidecar: &NativeSidecar, + vm_id: &str, + execution_id: &str, +) -> Result { + let Some(execution) = sidecar + .vms + .get(vm_id) + .and_then(|vm| vm.executions.get(execution_id)) + else { + return Err(( + "execution_not_found", + format!("execution {execution_id} does not exist"), + )); + }; + if execution.descriptor.state != ExecutionState::Running { + return Err(( + "execution_not_running", + format!("execution {execution_id} is not running"), + )); + } + execution.descriptor.process_id.clone().ok_or_else(|| { + ( + "execution_not_running", + format!("execution {execution_id} has no active process"), + ) + }) +} + +fn parse_cursor(cursor: &str, generation: u64) -> Option { + let (cursor_generation, sequence) = cursor.split_once(':')?; + (cursor_generation.parse::().ok()? == generation) + .then(|| sequence.parse::().ok()) + .flatten() +} + +fn failed_result( + execution: ExecutionDescriptor, + code: impl Into, + message: impl Into, +) -> ExecutionCompletedResponse { + ExecutionCompletedResponse { + execution, + outcome: ExecutionOutcome::Failed, + exit_code: None, + error: Some(ExecutionErrorData { + code: code.into(), + name: String::from("ExecutionError"), + message: message.into(), + stack: None, + details: None, + }), + stdout: Vec::new(), + stderr: Vec::new(), + stdout_truncated: false, + stderr_truncated: false, + outputs: String::from("[]"), + } +} diff --git a/crates/native-sidecar/src/lib.rs b/crates/native-sidecar/src/lib.rs index 2ed84f54dd..a6607fb770 100644 --- a/crates/native-sidecar/src/lib.rs +++ b/crates/native-sidecar/src/lib.rs @@ -12,6 +12,7 @@ pub mod extension; pub(crate) mod filesystem; #[allow(dead_code)] pub(crate) mod json_rpc; +pub(crate) mod language_execution; pub mod limits; pub(crate) mod metadata; pub mod package_projection; diff --git a/crates/native-sidecar/src/plugins/google_drive.rs b/crates/native-sidecar/src/plugins/google_drive.rs index a72afc8a6b..c12249cb70 100644 --- a/crates/native-sidecar/src/plugins/google_drive.rs +++ b/crates/native-sidecar/src/plugins/google_drive.rs @@ -19,7 +19,7 @@ use url::Url; const DEFAULT_CHUNK_SIZE: usize = 4 * 1024 * 1024; const DEFAULT_INLINE_THRESHOLD: usize = 64 * 1024; -const MANIFEST_FORMAT: &str = "secure_exec_google_drive_filesystem_manifest_v1"; +const MANIFEST_FORMAT: &str = "agentos_google_drive_filesystem_manifest_v1"; const LEGACY_AGENTOS_MANIFEST_FORMAT: &str = "agentos_google_drive_filesystem_manifest_v1"; const DRIVE_SCOPE: &str = "https://www.googleapis.com/auth/drive.file"; const DEFAULT_TOKEN_URL: &str = "https://oauth2.googleapis.com/token"; diff --git a/crates/native-sidecar/src/service.rs b/crates/native-sidecar/src/service.rs index 305f57046b..c76b55eb55 100644 --- a/crates/native-sidecar/src/service.rs +++ b/crates/native-sidecar/src/service.rs @@ -1540,6 +1540,12 @@ where self.snapshot_root_filesystem(&request, payload).await } RequestRoute::ListMounts(payload) => self.list_mounts(&request, payload).await, + RequestRoute::ExecutionOperation(payload) => { + self.execute_language_operation(&request, payload).await + } + RequestRoute::ExecutionLifecycle(payload) => { + self.handle_execution_lifecycle(&request, payload).await + } RequestRoute::Execute(payload) => self.execute(&request, payload).await, RequestRoute::WriteStdin(payload) => self.write_stdin(&request, payload).await, RequestRoute::ResizePty(payload) => self.resize_pty(&request, payload).await, @@ -3162,7 +3168,12 @@ where shared_respond(request, payload) } - fn reject(&self, request: &RequestFrame, code: &str, message: &str) -> ResponseFrame { + pub(crate) fn reject( + &self, + request: &RequestFrame, + code: &str, + message: &str, + ) -> ResponseFrame { shared_reject(request, code, message) } @@ -4007,7 +4018,7 @@ pub(crate) fn vfs_error(error: VfsError) -> SidecarError { /// required. The empirically-supported package managers are captured in /// `crates/sidecar/tests/module_layout_e2e.rs`. #[allow(dead_code)] -const HOISTED_NODE_MODULES_GUIDANCE: &str = "secure-exec can't load mounted node_modules: the directory uses a non-flat layout (pnpm / bun / yarn workspaces store, or yarn Plug'n'Play) whose package store isn't visible inside the VM. A flat (hoisted) node_modules is required.\n - pnpm -> add `node-linker=hoisted` to .npmrc, then reinstall\n - yarn berry -> set `nodeLinker: node-modules` in .yarnrc.yml (not pnp/pnpm)\n - bun -> install dependencies outside a workspace (workspaces use a .bun store)\n - npm / yarn classic -> already flat, no change needed"; +const HOISTED_NODE_MODULES_GUIDANCE: &str = "agentos can't load mounted node_modules: the directory uses a non-flat layout (pnpm / bun / yarn workspaces store, or yarn Plug'n'Play) whose package store isn't visible inside the VM. A flat (hoisted) node_modules is required.\n - pnpm -> add `node-linker=hoisted` to .npmrc, then reinstall\n - yarn berry -> set `nodeLinker: node-modules` in .yarnrc.yml (not pnp/pnpm)\n - bun -> install dependencies outside a workspace (workspaces use a .bun store)\n - npm / yarn classic -> already flat, no change needed"; /// Detect, from an adapter's captured stderr, a non-flat-`node_modules` failure /// signature. Returns the actionable guidance to fold into the surfaced error, @@ -4178,7 +4189,7 @@ mod symlinked_node_modules_hint_tests { // dist/package.json inside the unreachable .pnpm store. let stderr = "Error: ENOENT: no such file or directory, open '/root/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.60.0_x/node_modules/@mariozechner/pi-coding-agent/dist/package.json'"; let hint = symlinked_node_modules_hint(stderr).expect("expected hoisted guidance"); - assert!(hint.contains("secure-exec can't load mounted node_modules")); + assert!(hint.contains("agentos can't load mounted node_modules")); assert!(!hint.contains("agentos")); } diff --git a/crates/native-sidecar/src/state.rs b/crates/native-sidecar/src/state.rs index 41ce39cac2..d09b39e581 100644 --- a/crates/native-sidecar/src/state.rs +++ b/crates/native-sidecar/src/state.rs @@ -4,9 +4,10 @@ //! types, and other shared data structures extracted from service.rs. use crate::protocol::{ - GuestRuntimeKind, MountDescriptor, ProjectedModuleDescriptor, RegisterHostCallbacksRequest, - SidecarRequestFrame, SidecarRequestPayload, SidecarResponseFrame, SidecarResponsePayload, - SignalHandlerRegistration, SoftwareDescriptor, WasmPermissionTier, + ExecutionCompletedResponse, ExecutionDescriptor, ExecutionOutputEvent, GuestRuntimeKind, + MountDescriptor, ProjectedModuleDescriptor, RegisterHostCallbacksRequest, SidecarRequestFrame, + SidecarRequestPayload, SidecarResponseFrame, SidecarResponsePayload, SignalHandlerRegistration, + SoftwareDescriptor, WasmPermissionTier, }; use crate::wire::DEFAULT_MAX_FRAME_BYTES; use agentos_bridge::{ @@ -528,7 +529,7 @@ pub(crate) const VM_LISTEN_PORT_MAX_METADATA_KEY: &str = "network.listen.port_ma pub(crate) const VM_LISTEN_ALLOW_PRIVILEGED_METADATA_KEY: &str = "network.listen.allow_privileged"; pub(crate) const DEFAULT_JAVASCRIPT_NET_BACKLOG: u32 = 511; pub(crate) const LOOPBACK_EXEMPT_PORTS_ENV: &str = "AGENTOS_LOOPBACK_EXEMPT_PORTS"; -pub(crate) const BINDING_DRIVER_NAME: &str = "secure-exec-host-callbacks"; +pub(crate) const BINDING_DRIVER_NAME: &str = "agentos-host-callbacks"; pub(crate) const MAPPED_HOST_FD_START: u32 = 1_000_000_000; // --------------------------------------------------------------------------- @@ -870,6 +871,15 @@ pub(crate) struct VmState { pub(crate) command_permissions: BTreeMap, pub(crate) bindings: BTreeMap, pub(crate) active_processes: BTreeMap, + /// Public language/process executions keyed by their sole lifecycle ID. + /// Process IDs remain internal routing details in `execution_processes`. + pub(crate) executions: BTreeMap, + pub(crate) execution_processes: BTreeMap, + pub(crate) next_public_execution_id: u64, + /// The VM filesystem is shared across executions, so package-manager + /// mutations must never run concurrently. + pub(crate) package_mutation_execution_id: Option, + pub(crate) typescript_compiler_staged: bool, pub(crate) exited_process_snapshots: VecDeque, pub(crate) detached_child_processes: BTreeSet, /// Rotating start positions for bounded child-process event turns. Durable @@ -2554,6 +2564,41 @@ pub(crate) struct ActiveUdpSocket { // Execution types // --------------------------------------------------------------------------- +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum ExecutionValueKind { + None, + JavaScript, + Python, + TypeScriptCheck, +} + +#[derive(Debug)] +pub(crate) struct ManagedLanguageExecution { + pub(crate) descriptor: ExecutionDescriptor, + pub(crate) result: Option, + pub(crate) events: VecDeque, + pub(crate) retained_event_bytes: usize, + pub(crate) output_truncated: bool, + pub(crate) next_sequence: u64, + pub(crate) stdout: Vec, + pub(crate) stderr: Vec, + pub(crate) stdout_truncated: bool, + pub(crate) stderr_truncated: bool, + pub(crate) output_limit_bytes: usize, + pub(crate) output_limit_setting: &'static str, + pub(crate) event_limit: usize, + pub(crate) event_bytes_limit: usize, + pub(crate) uses_pty: bool, + pub(crate) value_kind: ExecutionValueKind, + pub(crate) value_marker: Option, + pub(crate) pending_outcome: Option, + pub(crate) deadline_ms: Option, + pub(crate) deadline_task: Option>, + /// Internal process whose V8/Pyodide context is parked while the public + /// execution is idle. It is never exposed as a second lifecycle identity. + pub(crate) resident_process_id: Option, +} + #[derive(Debug)] #[allow(clippy::large_enum_variant)] // execution state is process-registry owned and preserves backend drop affinity pub(crate) enum ActiveExecution { diff --git a/crates/native-sidecar/src/stdio.rs b/crates/native-sidecar/src/stdio.rs index ae94506c71..913b2eb022 100644 --- a/crates/native-sidecar/src/stdio.rs +++ b/crates/native-sidecar/src/stdio.rs @@ -1878,7 +1878,7 @@ mod tests { use crate::{ExtensionContext, ExtensionFuture, ExtensionInterruptResponse, ExtensionResponse}; use std::io::Cursor; - const TEST_EXTENSION_NAMESPACE: &str = "dev.rivet.secure-exec.test.blocking"; + const TEST_EXTENSION_NAMESPACE: &str = "dev.rivet.agentos.test.blocking"; fn test_protocol_budget( max_frames: usize, diff --git a/crates/native-sidecar/src/vm.rs b/crates/native-sidecar/src/vm.rs index 67cf2dcac7..3015c066a5 100644 --- a/crates/native-sidecar/src/vm.rs +++ b/crates/native-sidecar/src/vm.rs @@ -546,6 +546,11 @@ where command_permissions: BTreeMap::new(), bindings: BTreeMap::new(), active_processes: BTreeMap::new(), + executions: BTreeMap::new(), + execution_processes: BTreeMap::new(), + next_public_execution_id: 0, + package_mutation_execution_id: None, + typescript_compiler_staged: false, exited_process_snapshots: VecDeque::new(), detached_child_processes: BTreeSet::new(), attached_child_event_cursor: 0, @@ -680,7 +685,7 @@ where vm.command_guest_paths = discover_command_guest_paths(&mut vm.kernel); // The `{ packageDir }` projection lands each package's `bin/` at // `/opt/agentos/bin/` (on `$PATH`) but does NOT populate - // `/__secure_exec/commands`, so `discover_command_guest_paths` alone misses + // `/__agentos/commands`, so `discover_command_guest_paths` alone misses // projected commands and every projected wasm/js command resolves to // ENOEXEC (absolute path) / ENOENT (bare name). Register each projected // command by name -> its `/opt/agentos/bin/` entrypoint so both the @@ -3670,9 +3675,8 @@ mod tests { .expect("clock should be monotonic") .as_nanos(); let database_path = - std::env::temp_dir().join(format!("secure-exec-native-root-{unique}.sqlite")); - let block_root = - std::env::temp_dir().join(format!("secure-exec-native-root-blocks-{unique}")); + std::env::temp_dir().join(format!("agentos-native-root-{unique}.sqlite")); + let block_root = std::env::temp_dir().join(format!("agentos-native-root-blocks-{unique}")); let native_root = native_root_plugin_from_config(Some(&agentos_vm_config::NativeRootFilesystemConfig { plugin: agentos_vm_config::MountPluginDescriptor { diff --git a/crates/native-sidecar/tests/architecture_guards.rs b/crates/native-sidecar/tests/architecture_guards.rs index 09039f098d..560e26e393 100644 --- a/crates/native-sidecar/tests/architecture_guards.rs +++ b/crates/native-sidecar/tests/architecture_guards.rs @@ -20,7 +20,7 @@ //! (`sidecar::execution`), the embedded V8 runtime IPC pair, and //! host-backed storage plugins. //! * process -- `std::process::Command` / `tokio::process` / OS `fork`. -//! Sanctioned only where secure-exec spawns its own helper process (the +//! Sanctioned only where agentos spawns its own helper process (the //! client transport that launches the sidecar). Guest "process" spawns are //! dispatched through the kernel `CommandDriver` registry and never touch //! `Command::new`. @@ -394,12 +394,12 @@ const NET_ALLOW: &[&str] = &[ /// process: OS subprocess creation. /// -/// Sanctioned surface: only the client transport, which spawns secure-exec's +/// Sanctioned surface: only the client transport, which spawns agentos's /// own sidecar helper binary. Guest "process" spawns go through the kernel /// `CommandDriver` registry and never reach `Command::new`. const PROCESS_ALLOW: &[&str] = &[ "crates/sidecar-client/src/transport.rs", - // V8 snapshot builder re-execs secure-exec's OWN binary as a helper + // V8 snapshot builder re-execs agentos's OWN binary as a helper // (SNAPSHOT_HELPER_ENV) so snapshot creation runs in a clean process. // Host-side bootstrap only; no guest-controlled input picks the program. "crates/v8-runtime/src/snapshot.rs", @@ -1449,7 +1449,7 @@ fn browser_sources_are_retained_but_disabled_from_native_build_and_publish_gates } let mirror_generator = - std::fs::read_to_string(root.join("scripts/generate-secure-exec-mirror.mjs")) + std::fs::read_to_string(root.join("scripts/generate-agentos-mirror.mjs")) .expect("read compatibility mirror generator"); assert!( mirror_generator.contains("browserShim ? { private: true } : {}") @@ -1460,7 +1460,7 @@ fn browser_sources_are_retained_but_disabled_from_native_build_and_publish_gates let source = std::fs::read_to_string(root.join(relative_path)) .unwrap_or_else(|error| panic!("read {relative_path}: {error}")); assert!( - source.contains("node --test scripts/generate-secure-exec-mirror.test.mjs"), + source.contains("node --test scripts/generate-agentos-mirror.test.mjs"), "{relative_path} must enforce compatibility-mirror reproducibility" ); } diff --git a/crates/native-sidecar/tests/builtin_conformance.rs b/crates/native-sidecar/tests/builtin_conformance.rs index a633af8473..6f9c7a22be 100644 --- a/crates/native-sidecar/tests/builtin_conformance.rs +++ b/crates/native-sidecar/tests/builtin_conformance.rs @@ -579,7 +579,7 @@ fn fixture_dns_answers(query: &Query) -> Vec { ), fixture_dns_record( "bundle.example.test.", - RData::TXT(TXT::new(vec![String::from("secure-exec")])), + RData::TXT(TXT::new(vec![String::from("agentos")])), ), ], ("bundle.example.test.", RecordType::ANY) => vec![ @@ -2916,8 +2916,8 @@ console.log(JSON.stringify({ curvesIncludePrime256v1: curves.includes("prime256v1"), curvesIncludeSecp384r1: curves.includes("secp384r1"), curvesSorted: curves.join(",") === [...curves].sort().join(","), - sha256: crypto.createHash("sha256").update("secure-exec").digest("hex"), - hmacSha256: crypto.createHmac("sha256", "shared-secret").update("secure-exec").digest("hex"), + sha256: crypto.createHash("sha256").update("agentos").digest("hex"), + hmacSha256: crypto.createHmac("sha256", "shared-secret").update("agentos").digest("hex"), randomBytesLength: random.length, randomBytesHexLength: random.toString("hex").length, randomBytesAllZero: Array.from(random).every((value) => value === 0), @@ -2935,7 +2935,7 @@ import crypto from "node:crypto"; const cipherKey = Buffer.alloc(32, 7); const cipherIv = Buffer.alloc(16, 9); -const cipherPlaintext = Buffer.from("secure-exec-crypto-surface", "utf8"); +const cipherPlaintext = Buffer.from("agentos-crypto-surface", "utf8"); const cipher = crypto.createCipheriv("aes-256-cbc", cipherKey, cipherIv); const encrypted = Buffer.concat([cipher.update(cipherPlaintext), cipher.final()]); const decipher = crypto.createDecipheriv("aes-256-cbc", cipherKey, cipherIv); @@ -2968,24 +2968,24 @@ const importedPrivateKey = crypto.createPrivateKey(privatePem); const importedPublicKey = crypto.createPublicKey(publicPem); const signer = crypto.createSign("sha256"); -signer.update("secure-exec-signature"); +signer.update("agentos-signature"); const signature = signer.sign(importedPrivateKey); const verifier = crypto.createVerify("sha256"); -verifier.update("secure-exec-signature"); +verifier.update("agentos-signature"); const signatureVerified = verifier.verify(importedPublicKey, signature); -const oneShotSignature = crypto.sign("sha256", Buffer.from("secure-exec-signature"), importedPrivateKey); +const oneShotSignature = crypto.sign("sha256", Buffer.from("agentos-signature"), importedPrivateKey); const oneShotVerified = crypto.verify( "sha256", - Buffer.from("secure-exec-signature"), + Buffer.from("agentos-signature"), importedPublicKey, oneShotSignature, ); const rsaCiphertext = crypto.publicEncrypt( { key: importedPublicKey, padding: crypto.constants.RSA_PKCS1_PADDING }, - Buffer.from("secure-exec-rsa", "utf8"), + Buffer.from("agentos-rsa", "utf8"), ); const rsaPlaintext = crypto.privateDecrypt( { key: importedPrivateKey, padding: crypto.constants.RSA_PKCS1_PADDING }, @@ -3803,7 +3803,7 @@ const promisified = await util.promisify((value, callback) => callback(null, val const encodedLength = new util.TextEncoder().encode("Grüße").length; const decodedText = new util.TextDecoder().decode(textBytes); -const deflated = zlib.deflateSync(Buffer.from("secure-exec", "utf8")); +const deflated = zlib.deflateSync(Buffer.from("agentos", "utf8")); const inflated = zlib.inflateSync(deflated).toString("utf8"); console.log(JSON.stringify({ @@ -3938,7 +3938,7 @@ const bufferValue = await streamConsumers.buffer( makeAsyncStream([Buffer.from("buf")]), ); -const deflated = zlib.deflateSync(Buffer.from("secure-exec", "utf8")); +const deflated = zlib.deflateSync(Buffer.from("agentos", "utf8")); const inflated = zlib.inflateSync(deflated).toString("utf8"); process.stdout.write(`${JSON.stringify({ @@ -4060,7 +4060,7 @@ process.exit(0); assert_eq!(result["zlib"]["importConstantsHasSyncFlush"], true); assert_eq!(result["zlib"]["createDeflateType"], "function"); assert_eq!(result["zlib"]["createInflateType"], "function"); - assert_eq!(result["zlib"]["inflated"], "secure-exec"); + assert_eq!(result["zlib"]["inflated"], "agentos"); } fn timer_handle_ref_refresh_matches_host_node_impl() { diff --git a/crates/native-sidecar/tests/connection_auth.rs b/crates/native-sidecar/tests/connection_auth.rs index 7c35316838..aa80b2e3ae 100644 --- a/crates/native-sidecar/tests/connection_auth.rs +++ b/crates/native-sidecar/tests/connection_auth.rs @@ -149,7 +149,7 @@ fn ext_requests_fail_closed_when_namespace_is_unregistered() { 2, wire_connection(&connection_id), RequestPayload::ExtEnvelope(ExtEnvelope { - namespace: "dev.rivet.secure-exec.test".to_string(), + namespace: "dev.rivet.agentos.test".to_string(), payload: b"hello-ext".to_vec(), }), )) @@ -158,7 +158,7 @@ fn ext_requests_fail_closed_when_namespace_is_unregistered() { match result.response.payload { ResponsePayload::RejectedResponse(response) => { assert_eq!(response.code, "unknown_extension"); - assert!(response.message.contains("dev.rivet.secure-exec.test")); + assert!(response.message.contains("dev.rivet.agentos.test")); } other => panic!("unexpected ext response: {other:?}"), } diff --git a/crates/native-sidecar/tests/extension.rs b/crates/native-sidecar/tests/extension.rs index 9881739471..a0ba3b33c4 100644 --- a/crates/native-sidecar/tests/extension.rs +++ b/crates/native-sidecar/tests/extension.rs @@ -19,7 +19,7 @@ use support::{ temp_dir, wire_request, wire_vm, RecordingBridge, }; -const TEST_NAMESPACE: &str = "dev.rivet.secure-exec.extension-test"; +const TEST_NAMESPACE: &str = "dev.rivet.agentos.extension-test"; struct EchoExtension; struct VmLifetimeExtension; @@ -191,7 +191,7 @@ impl Extension for EchoExtension { impl Extension for VmLifetimeExtension { fn namespace(&self) -> &str { - "dev.rivet.secure-exec.extension-vm-lifetime-test" + "dev.rivet.agentos.extension-vm-lifetime-test" } fn handle_request<'a>( @@ -318,7 +318,7 @@ fn extension_session_resources_can_dispose_bound_vm() { 4, wire_vm(&connection_id, &session_id, &vm_id), RequestPayload::ExtEnvelope(ExtEnvelope { - namespace: String::from("dev.rivet.secure-exec.extension-vm-lifetime-test"), + namespace: String::from("dev.rivet.agentos.extension-vm-lifetime-test"), payload: Vec::new(), }), )) @@ -328,7 +328,7 @@ fn extension_session_resources_can_dispose_bound_vm() { ResponsePayload::ExtEnvelope(envelope) => { assert_eq!( envelope.namespace, - "dev.rivet.secure-exec.extension-vm-lifetime-test" + "dev.rivet.agentos.extension-vm-lifetime-test" ); assert_eq!(envelope.payload, b"vm-disposed"); } diff --git a/crates/native-sidecar/tests/filesystem.rs b/crates/native-sidecar/tests/filesystem.rs index b6816ab862..861b6a42a3 100644 --- a/crates/native-sidecar/tests/filesystem.rs +++ b/crates/native-sidecar/tests/filesystem.rs @@ -398,7 +398,7 @@ mod shadow_root { let command_root = registry_command_root() .expect("registry WASM commands are required before mounting command root"); let mut mounts = vec![MountDescriptor { - guest_path: String::from("/__secure_exec/commands/0"), + guest_path: String::from("/__agentos/commands/0"), guest_source: String::from("host_dir"), guest_fstype: String::from("host_dir"), read_only: true, diff --git a/crates/native-sidecar/tests/generated_protocol.rs b/crates/native-sidecar/tests/generated_protocol.rs index 4e9cf451a8..6bd8ee6ccc 100644 --- a/crates/native-sidecar/tests/generated_protocol.rs +++ b/crates/native-sidecar/tests/generated_protocol.rs @@ -127,7 +127,7 @@ fn live_bare_codec_matches_generated_request_bytes() { 11, live_protocol::OwnershipScope::connection("conn-1"), live_protocol::RequestPayload::Ext(live_protocol::ExtEnvelope { - namespace: "dev.rivet.secure-exec.test".to_string(), + namespace: "dev.rivet.agentos.test".to_string(), payload: b"extension-bytes".to_vec(), }), )); @@ -305,7 +305,7 @@ fn generated_ext_frame() -> ProtocolFrame { connection_id: "conn-1".to_string(), }), payload: RequestPayload::ExtEnvelope(ExtEnvelope { - namespace: "dev.rivet.secure-exec.test".to_string(), + namespace: "dev.rivet.agentos.test".to_string(), payload: b"extension-bytes".to_vec(), }), }) diff --git a/crates/native-sidecar/tests/guest_identity.rs b/crates/native-sidecar/tests/guest_identity.rs index 9e59ee4589..694dfdb718 100644 --- a/crates/native-sidecar/tests/guest_identity.rs +++ b/crates/native-sidecar/tests/guest_identity.rs @@ -1,7 +1,7 @@ mod support; use agentos_native_sidecar::wire::{ - CreateVmRequest, GuestRuntimeKind, RequestId, RequestPayload, ResponsePayload, + CreateVmRequest, ExecuteRequest, GuestRuntimeKind, RequestId, RequestPayload, ResponsePayload, RootFilesystemDescriptor, RootFilesystemEntry, RootFilesystemEntryEncoding, RootFilesystemEntryKind, RootFilesystemMode, }; @@ -197,6 +197,7 @@ print(json.dumps({ "env_pwd": os.environ.get("PWD"), "env_shell": os.environ.get("SHELL"), "env_path": os.environ.get("PATH"), + "custom_env": os.environ.get("EXEC_REVIEW"), "internal_keys": sorted([ key for key in os.environ if key.startswith("AGENTOS_") or key.startswith("NODE_SYNC_RPC_") @@ -213,17 +214,26 @@ print(json.dumps({ }, ); - execute_wire( - &mut sidecar, - 4, - &connection_id, - &session_id, - &vm_id, - "proc-python-identity", - GuestRuntimeKind::Python, - std::path::Path::new("/workspace/identity.py"), - Vec::new(), - ); + let result = sidecar + .dispatch_wire_blocking(wire_request( + 4, + support::wire_vm(&connection_id, &session_id, &vm_id), + RequestPayload::ExecuteRequest(ExecuteRequest { + process_id: String::from("proc-python-identity"), + command: None, + runtime: Some(GuestRuntimeKind::Python), + entrypoint: Some(String::from("/workspace/identity.py")), + args: Vec::new(), + env: HashMap::from([(String::from("EXEC_REVIEW"), String::from("visible"))]), + cwd: None, + wasm_permission_tier: None, + }), + )) + .expect("start Python identity execution"); + assert!(matches!( + result.response.payload, + ResponsePayload::ProcessStartedResponse(_) + )); let (stdout, stderr, exit_code) = collect_guest_identity_process_output( &mut sidecar, @@ -245,6 +255,7 @@ print(json.dumps({ assert_eq!(parsed["env_pwd"], "/"); assert_eq!(parsed["env_shell"], "/bin/sh"); assert_eq!(parsed["env_path"], DEFAULT_GUEST_PATH_ENV); + assert_eq!(parsed["custom_env"], "visible"); assert_eq!(parsed["internal_keys"], Value::Array(Vec::new())); assert_eq!(parsed["path_home"], "/home/agentos"); } diff --git a/crates/native-sidecar/tests/host_dir.rs b/crates/native-sidecar/tests/host_dir.rs index cb558a2281..899d704932 100644 --- a/crates/native-sidecar/tests/host_dir.rs +++ b/crates/native-sidecar/tests/host_dir.rs @@ -28,8 +28,8 @@ mod host_dir { #[test] fn filesystem_rejects_symlink_escapes_and_round_trips_writes() { - let host_dir = temp_dir("secure-exec-host-dir-plugin"); - let outside_dir = temp_dir("secure-exec-host-dir-plugin-outside"); + let host_dir = temp_dir("agentos-host-dir-plugin"); + let outside_dir = temp_dir("agentos-host-dir-plugin-outside"); fs::write(host_dir.join("hello.txt"), "hello from host").expect("seed host file"); std::os::unix::fs::symlink(&outside_dir, host_dir.join("escape")) .expect("seed escape symlink"); @@ -75,7 +75,7 @@ mod host_dir { #[test] fn filesystem_pwrite_updates_in_place_and_zero_fills_gaps() { - let host_dir = temp_dir("secure-exec-host-dir-plugin-pwrite"); + let host_dir = temp_dir("agentos-host-dir-plugin-pwrite"); fs::write(host_dir.join("data.txt"), b"abcdef").expect("seed host file"); let mut filesystem = HostDirFilesystem::new(&host_dir).expect("create host dir fs"); @@ -96,8 +96,8 @@ mod host_dir { #[test] fn filesystem_pwrite_rejects_symlink_escape_targets() { - let host_dir = temp_dir("secure-exec-host-dir-plugin-pwrite-escape"); - let outside_dir = temp_dir("secure-exec-host-dir-plugin-pwrite-escape-outside"); + let host_dir = temp_dir("agentos-host-dir-plugin-pwrite-escape"); + let outside_dir = temp_dir("agentos-host-dir-plugin-pwrite-escape-outside"); fs::write(outside_dir.join("outside.txt"), b"outside").expect("seed outside file"); std::os::unix::fs::symlink(&outside_dir, host_dir.join("escape")) .expect("seed escape symlink"); @@ -118,7 +118,7 @@ mod host_dir { #[test] fn filesystem_rejects_full_reads_above_host_dir_limit() { - let host_dir = temp_dir("secure-exec-host-dir-plugin-full-read-limit"); + let host_dir = temp_dir("agentos-host-dir-plugin-full-read-limit"); let huge_file = fs::File::create(host_dir.join("huge.bin")).expect("create huge file"); huge_file .set_len(MAX_HOST_DIR_READ_BYTES as u64 + 1) @@ -135,7 +135,7 @@ mod host_dir { #[test] fn filesystem_pread_rejects_lengths_above_host_dir_limit() { - let host_dir = temp_dir("secure-exec-host-dir-plugin-pread-limit"); + let host_dir = temp_dir("agentos-host-dir-plugin-pread-limit"); fs::write(host_dir.join("small.txt"), b"small").expect("seed host file"); let mut filesystem = HostDirFilesystem::new(&host_dir).expect("create host dir fs"); @@ -149,8 +149,8 @@ mod host_dir { #[test] fn filesystem_metadata_ops_reject_symlink_targets() { - let host_dir = temp_dir("secure-exec-host-dir-plugin-metadata"); - let outside_dir = temp_dir("secure-exec-host-dir-plugin-metadata-outside"); + let host_dir = temp_dir("agentos-host-dir-plugin-metadata"); + let outside_dir = temp_dir("agentos-host-dir-plugin-metadata-outside"); let outside_file = outside_dir.join("outside.txt"); fs::write(&outside_file, b"outside").expect("seed outside file"); std::os::unix::fs::symlink(&outside_file, host_dir.join("link")) @@ -293,7 +293,7 @@ mod host_dir { #[test] fn plugin_config_can_enforce_read_only_mounts() { - let host_dir = temp_dir("secure-exec-host-dir-plugin-readonly"); + let host_dir = temp_dir("agentos-host-dir-plugin-readonly"); fs::write(host_dir.join("hello.txt"), "hello from host").expect("seed host file"); let plugin = HostDirMountPlugin; diff --git a/crates/native-sidecar/tests/language_execution.rs b/crates/native-sidecar/tests/language_execution.rs new file mode 100644 index 0000000000..47dc0e53bf --- /dev/null +++ b/crates/native-sidecar/tests/language_execution.rs @@ -0,0 +1,710 @@ +mod support; + +use agentos_native_sidecar::wire; +use std::collections::HashMap; +use std::time::{Duration, Instant}; +use support::{ + authenticate_wire, create_vm_wire, dispose_vm_and_close_session_wire, new_sidecar, + open_session_wire, temp_dir, wire_request, wire_session, wire_vm, +}; + +fn process_options(execution_id: Option) -> wire::ProcessExecutionOptions { + wire::ProcessExecutionOptions { + identity: wire::ExecutionIdentityOptions { + execution_id, + create_if_missing: None, + }, + detached: Some(true), + cwd: None, + env: Some(HashMap::new()), + args: Vec::new(), + stdin: None, + timeout_ms: Some(30_000), + pty: None, + } +} + +fn accepted_execution_id(result: wire::WireDispatchResult) -> String { + match result.response.payload { + wire::ResponsePayload::ExecutionAcceptedResponse(response) => { + response.execution.execution_id + } + other => panic!("unexpected language execution response: {other:?}"), + } +} + +fn wait_for_execution( + sidecar: &mut agentos_native_sidecar::NativeSidecar, + connection_id: &str, + session_id: &str, + vm_id: &str, + execution_id: &str, +) -> wire::ExecutionCompletedResponse { + let deadline = Instant::now() + Duration::from_secs(30); + loop { + let event = sidecar + .poll_event_wire_blocking( + &wire_session(connection_id, session_id), + Duration::from_millis(100), + ) + .expect("poll execution event"); + if let Some(event) = event { + if let wire::EventPayload::ExecutionCompletedEvent(completed) = event.payload { + if completed.execution_id == execution_id { + break; + } + } + } + assert!(Instant::now() < deadline, "language execution timed out"); + } + + let response = sidecar + .dispatch_wire_blocking(wire_request( + 90, + wire_vm(connection_id, session_id, vm_id), + wire::RequestPayload::WaitExecutionRequest(wire::WaitExecutionRequest { + execution_id: execution_id.to_owned(), + }), + )) + .expect("wait for execution result"); + match response.response.payload { + wire::ResponsePayload::ExecutionCompletedResponse(result) => result, + other => panic!("unexpected wait response: {other:?}"), + } +} + +fn reset_execution( + sidecar: &mut agentos_native_sidecar::NativeSidecar, + connection_id: &str, + session_id: &str, + vm_id: &str, + execution_id: &str, +) { + let response = sidecar + .dispatch_wire_blocking(wire_request( + 91, + wire_vm(connection_id, session_id, vm_id), + wire::RequestPayload::ResetExecutionRequest(wire::ResetExecutionRequest { + execution_id: execution_id.to_owned(), + }), + )) + .expect("reset retained execution"); + match response.response.payload { + wire::ResponsePayload::ExecutionDescriptorResponse(response) => { + assert_eq!(response.execution.state, wire::ExecutionState::Idle); + assert_eq!(response.execution.retained_language, None); + } + other => panic!("unexpected reset response: {other:?}"), + } +} + +#[test] +fn javascript_execution_reuses_retained_context() { + let mut sidecar = new_sidecar("language-execution-retained-js"); + let connection_id = authenticate_wire(&mut sidecar, "language-execution-connection"); + let session_id = open_session_wire(&mut sidecar, 2, &connection_id); + let cwd = temp_dir("language-execution-retained-js-cwd"); + let (vm_id, _) = create_vm_wire( + &mut sidecar, + 3, + &connection_id, + &session_id, + wire::GuestRuntimeKind::JavaScript, + &cwd, + ); + let first = sidecar + .dispatch_wire_blocking(wire_request( + 4, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::JavaScriptExecutionRequest(wire::JavaScriptExecutionRequest { + process: process_options(None), + source: String::from( + "import { sep } from 'node:path'; let retainedAnswer = sep === '/' ? 41 : 0;", + ), + format: Some(wire::JavaScriptModuleFormat::Module), + file_path: None, + inputs: None, + }), + )) + .expect("start first JavaScript operation"); + let execution_id = accepted_execution_id(first); + let first_result = wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + assert_eq!(first_result.outcome, wire::ExecutionOutcome::Succeeded); + + let mut fresh_process_options = process_options(Some(execution_id.clone())); + fresh_process_options.args = vec![String::from("-e"), String::from("void 0")]; + let process = sidecar + .dispatch_wire_blocking(wire_request( + 5, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::ArgvExecutionRequest(wire::ArgvExecutionRequest { + process: fresh_process_options, + command: String::from("node"), + }), + )) + .expect("start fresh process between retained operations"); + assert!( + process.events.is_empty(), + "interleaved process failed during admission: {:?}", + process.events + ); + assert_eq!(accepted_execution_id(process), execution_id); + let process_result = wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + assert_eq!(process_result.outcome, wire::ExecutionOutcome::Succeeded); + + let typescript = sidecar + .dispatch_wire_blocking(wire_request( + 6, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::TypeScriptExecutionRequest(wire::TypeScriptExecutionRequest { + process: process_options(Some(execution_id.clone())), + source: String::from( + "const typedAnswer: number = sep === '/' ? retainedAnswer + 1 : 0;", + ), + file_path: Some(String::from("retained-cell.ts")), + tsconfig_path: None, + compiler_options: None, + inputs: None, + }), + )) + .expect("start retained TypeScript operation"); + assert_eq!(accepted_execution_id(typescript), execution_id); + let typescript_result = wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + assert_eq!(typescript_result.outcome, wire::ExecutionOutcome::Succeeded); + + let second = sidecar + .dispatch_wire_blocking(wire_request( + 7, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::JavaScriptEvaluationRequest(wire::JavaScriptEvaluationRequest { + process: process_options(Some(execution_id.clone())), + expression: String::from("typedAnswer"), + format: Some(wire::JavaScriptModuleFormat::Module), + file_path: None, + inputs: None, + }), + )) + .expect("start retained JavaScript evaluation"); + assert_eq!(accepted_execution_id(second), execution_id); + let second_result = wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + assert_eq!(second_result.outcome, wire::ExecutionOutcome::Succeeded); + assert!(second_result.outputs.contains("42")); + + reset_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + dispose_vm_and_close_session_wire(&mut sidecar, &connection_id, &session_id, &vm_id); +} + +#[test] +fn typescript_check_reports_semantic_diagnostics() { + let mut sidecar = new_sidecar("language-execution-typescript-check"); + let connection_id = authenticate_wire(&mut sidecar, "typescript-check-connection"); + let session_id = open_session_wire(&mut sidecar, 2, &connection_id); + let cwd = temp_dir("language-execution-typescript-check-cwd"); + let (vm_id, _) = create_vm_wire( + &mut sidecar, + 3, + &connection_id, + &session_id, + wire::GuestRuntimeKind::JavaScript, + &cwd, + ); + let check = sidecar + .dispatch_wire_blocking(wire_request( + 4, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::TypeScriptCheckRequest(wire::TypeScriptCheckRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: None, + create_if_missing: None, + }, + source: String::from("const answer: string = 42;"), + cwd: None, + file_path: Some(String::from("answer.ts")), + tsconfig_path: None, + compiler_options: None, + timeout_ms: Some(30_000), + }), + )) + .expect("start TypeScript check"); + let execution_id = accepted_execution_id(check); + let result = wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + assert_eq!( + result.outcome, + wire::ExecutionOutcome::Succeeded, + "TypeScript check failed: {}", + String::from_utf8_lossy(&result.stderr) + ); + let outputs: serde_json::Value = + serde_json::from_str(&result.outputs).expect("decode TypeScript check outputs"); + assert_eq!(outputs[0]["data"]["hasErrors"], true); + assert!(outputs[0]["data"]["diagnostics"] + .as_array() + .is_some_and(|diagnostics| diagnostics.iter().any(|item| item["code"] == 2322))); + + dispose_vm_and_close_session_wire(&mut sidecar, &connection_id, &session_id, &vm_id); +} + +#[test] +fn python_execution_reuses_retained_globals() { + let mut sidecar = new_sidecar("language-execution-retained-python"); + let connection_id = authenticate_wire(&mut sidecar, "retained-python-connection"); + let session_id = open_session_wire(&mut sidecar, 2, &connection_id); + let cwd = temp_dir("language-execution-retained-python-cwd"); + let (vm_id, _) = create_vm_wire( + &mut sidecar, + 3, + &connection_id, + &session_id, + wire::GuestRuntimeKind::Python, + &cwd, + ); + let first = sidecar + .dispatch_wire_blocking(wire_request( + 4, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::PythonExecutionRequest(wire::PythonExecutionRequest { + process: process_options(None), + source: String::from( + "import asyncio\nawait asyncio.sleep(0)\nretained_answer = 41", + ), + inputs: None, + }), + )) + .expect("start first Python operation"); + let execution_id = accepted_execution_id(first); + assert_eq!( + wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ) + .outcome, + wire::ExecutionOutcome::Succeeded + ); + + let second = sidecar + .dispatch_wire_blocking(wire_request( + 5, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::PythonEvaluationRequest(wire::PythonEvaluationRequest { + process: process_options(Some(execution_id.clone())), + expression: String::from("retained_answer + 1"), + inputs: None, + }), + )) + .expect("start retained Python evaluation"); + assert_eq!(accepted_execution_id(second), execution_id); + let result = wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + assert_eq!(result.outcome, wire::ExecutionOutcome::Succeeded); + assert!(result.outputs.contains("42")); + + reset_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + dispose_vm_and_close_session_wire(&mut sidecar, &connection_id, &session_id, &vm_id); +} + +#[test] +fn execution_timeout_is_enforced_by_the_sidecar() { + let mut sidecar = new_sidecar("language-execution-timeout"); + let connection_id = authenticate_wire(&mut sidecar, "execution-timeout-connection"); + let session_id = open_session_wire(&mut sidecar, 2, &connection_id); + let cwd = temp_dir("language-execution-timeout-cwd"); + let (vm_id, _) = create_vm_wire( + &mut sidecar, + 3, + &connection_id, + &session_id, + wire::GuestRuntimeKind::JavaScript, + &cwd, + ); + let mut options = process_options(None); + options.timeout_ms = Some(100); + let started_at = Instant::now(); + let started = sidecar + .dispatch_wire_blocking(wire_request( + 4, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::JavaScriptExecutionRequest(wire::JavaScriptExecutionRequest { + process: options, + source: String::from("while (true) {}"), + format: Some(wire::JavaScriptModuleFormat::CommonJs), + file_path: None, + inputs: None, + }), + )) + .expect("start timed JavaScript operation"); + let execution_id = accepted_execution_id(started); + let result = wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + assert_eq!(result.outcome, wire::ExecutionOutcome::TimedOut); + assert_eq!( + result.error.as_ref().map(|error| error.code.as_str()), + Some("execution_timed_out") + ); + assert!( + started_at.elapsed() < Duration::from_secs(5), + "sidecar timeout did not terminate the guest promptly" + ); + + dispose_vm_and_close_session_wire(&mut sidecar, &connection_id, &session_id, &vm_id); +} + +#[test] +fn evaluation_rejects_non_json_values_with_a_structured_result() { + let mut sidecar = new_sidecar("language-execution-json-evaluation"); + let connection_id = authenticate_wire(&mut sidecar, "json-evaluation-connection"); + let session_id = open_session_wire(&mut sidecar, 2, &connection_id); + let cwd = temp_dir("language-execution-json-evaluation-cwd"); + let (vm_id, _) = create_vm_wire( + &mut sidecar, + 3, + &connection_id, + &session_id, + wire::GuestRuntimeKind::JavaScript, + &cwd, + ); + let started = sidecar + .dispatch_wire_blocking(wire_request( + 4, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::JavaScriptEvaluationRequest(wire::JavaScriptEvaluationRequest { + process: process_options(None), + expression: String::from("undefined"), + format: Some(wire::JavaScriptModuleFormat::CommonJs), + file_path: None, + inputs: None, + }), + )) + .expect("start non-JSON JavaScript evaluation"); + let execution_id = accepted_execution_id(started); + let result = wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + assert_eq!(result.outcome, wire::ExecutionOutcome::Failed); + assert_eq!( + result.error.as_ref().map(|error| error.code.as_str()), + Some("evaluation_serialization_failed") + ); + assert!(result + .error + .as_ref() + .is_some_and(|error| error.message.contains("JSON-serializable"))); + assert_eq!(result.outputs, "[]"); + + reset_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + + dispose_vm_and_close_session_wire(&mut sidecar, &connection_id, &session_id, &vm_id); +} + +#[test] +fn package_mutations_are_exclusive_across_executions() { + let mut sidecar = new_sidecar("language-execution-package-mutation"); + let connection_id = authenticate_wire(&mut sidecar, "package-mutation-connection"); + let session_id = open_session_wire(&mut sidecar, 2, &connection_id); + let cwd = temp_dir("language-execution-package-mutation-cwd"); + let (vm_id, _) = create_vm_wire( + &mut sidecar, + 3, + &connection_id, + &session_id, + wire::GuestRuntimeKind::Python, + &cwd, + ); + let first = sidecar + .dispatch_wire_blocking(wire_request( + 4, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::PythonInstallRequest(wire::PythonInstallRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: None, + create_if_missing: None, + }, + cwd: None, + env: None, + timeout_ms: Some(30_000), + packages: vec![String::from("agentos-package-mutation-test")], + upgrade: None, + requirements_file: None, + index_url: Some(String::from("http://127.0.0.1:9/simple")), + extra_index_urls: Vec::new(), + }), + )) + .expect("start first package mutation"); + let first_execution_id = accepted_execution_id(first); + + let second = sidecar + .dispatch_wire_blocking(wire_request( + 5, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::NpmProjectInstallRequest(wire::NpmProjectInstallRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: Some(String::from("second-package-mutation")), + create_if_missing: Some(true), + }, + cwd: None, + env: None, + timeout_ms: Some(30_000), + frozen: None, + }), + )) + .expect("reject concurrent package mutation"); + match second.response.payload { + wire::ResponsePayload::RejectedResponse(rejected) => { + assert_eq!(rejected.code, "execution_busy"); + assert!(rejected.message.contains(&first_execution_id)); + assert!(rejected.message.contains("serialized at VM scope")); + } + other => panic!("expected package mutation rejection, got {other:?}"), + } + + sidecar + .dispatch_wire_blocking(wire_request( + 6, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::CancelExecutionRequest(wire::CancelExecutionRequest { + execution_id: first_execution_id.clone(), + }), + )) + .expect("cancel first package mutation"); + assert_eq!( + wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &first_execution_id, + ) + .outcome, + wire::ExecutionOutcome::Cancelled + ); + + let resumed = sidecar + .dispatch_wire_blocking(wire_request( + 7, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::NpmProjectInstallRequest(wire::NpmProjectInstallRequest { + identity: wire::ExecutionIdentityOptions { + execution_id: Some(String::from("second-package-mutation")), + create_if_missing: Some(true), + }, + cwd: None, + env: None, + timeout_ms: Some(30_000), + frozen: None, + }), + )) + .expect("start package mutation after the prior one completed"); + let resumed_execution_id = accepted_execution_id(resumed); + sidecar + .dispatch_wire_blocking(wire_request( + 8, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::CancelExecutionRequest(wire::CancelExecutionRequest { + execution_id: resumed_execution_id.clone(), + }), + )) + .expect("cancel resumed package mutation"); + assert_eq!( + wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &resumed_execution_id, + ) + .outcome, + wire::ExecutionOutcome::Cancelled + ); + + dispose_vm_and_close_session_wire(&mut sidecar, &connection_id, &session_id, &vm_id); +} + +#[test] +fn detached_lifecycle_replays_cancels_resets_and_deletes() { + let mut sidecar = new_sidecar("language-execution-detached-lifecycle"); + let connection_id = authenticate_wire(&mut sidecar, "detached-lifecycle-connection"); + let session_id = open_session_wire(&mut sidecar, 2, &connection_id); + let cwd = temp_dir("language-execution-detached-lifecycle-cwd"); + let (vm_id, _) = create_vm_wire( + &mut sidecar, + 3, + &connection_id, + &session_id, + wire::GuestRuntimeKind::JavaScript, + &cwd, + ); + + let started = sidecar + .dispatch_wire_blocking(wire_request( + 4, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::JavaScriptExecutionRequest(wire::JavaScriptExecutionRequest { + process: process_options(None), + source: String::from("console.log('replay-me')"), + format: Some(wire::JavaScriptModuleFormat::CommonJs), + file_path: None, + inputs: None, + }), + )) + .expect("start detached JavaScript operation"); + let execution_id = accepted_execution_id(started); + assert_eq!( + wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ) + .outcome, + wire::ExecutionOutcome::Succeeded + ); + + let replay = sidecar + .dispatch_wire_blocking(wire_request( + 5, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::ReadExecutionOutputRequest(wire::ReadExecutionOutputRequest { + execution_id: execution_id.clone(), + cursor: None, + limit: Some(1), + }), + )) + .expect("read retained execution output"); + match replay.response.payload { + wire::ResponsePayload::ExecutionOutputPageResponse(page) => { + assert!(!page.truncated); + assert_eq!(page.events.len(), 1); + assert!(String::from_utf8_lossy(&page.events[0].chunk).contains("replay-me")); + assert!(!page.next_cursor.is_empty()); + } + other => panic!("expected execution output page, got {other:?}"), + } + + reset_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ); + + let mut cancel_options = process_options(Some(execution_id.clone())); + cancel_options.timeout_ms = Some(30_000); + let cancellable = sidecar + .dispatch_wire_blocking(wire_request( + 6, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::JavaScriptExecutionRequest(wire::JavaScriptExecutionRequest { + process: cancel_options, + source: String::from("while (true) {}"), + format: Some(wire::JavaScriptModuleFormat::CommonJs), + file_path: None, + inputs: None, + }), + )) + .expect("start cancellable execution"); + assert_eq!(accepted_execution_id(cancellable), execution_id); + sidecar + .dispatch_wire_blocking(wire_request( + 7, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::CancelExecutionRequest(wire::CancelExecutionRequest { + execution_id: execution_id.clone(), + }), + )) + .expect("cancel execution"); + assert_eq!( + wait_for_execution( + &mut sidecar, + &connection_id, + &session_id, + &vm_id, + &execution_id, + ) + .outcome, + wire::ExecutionOutcome::Cancelled + ); + + let deleted = sidecar + .dispatch_wire_blocking(wire_request( + 8, + wire_vm(&connection_id, &session_id, &vm_id), + wire::RequestPayload::DeleteExecutionRequest(wire::DeleteExecutionRequest { + execution_id: execution_id.clone(), + }), + )) + .expect("delete idle execution"); + match deleted.response.payload { + wire::ResponsePayload::ExecutionDeletedResponse(response) => { + assert_eq!(response.execution_id, execution_id); + } + other => panic!("expected execution deletion, got {other:?}"), + } + + dispose_vm_and_close_session_wire(&mut sidecar, &connection_id, &session_id, &vm_id); +} diff --git a/crates/native-sidecar/tests/posix_path_repro.rs b/crates/native-sidecar/tests/posix_path_repro.rs index 0fb58251a8..03f3796ca0 100644 --- a/crates/native-sidecar/tests/posix_path_repro.rs +++ b/crates/native-sidecar/tests/posix_path_repro.rs @@ -73,7 +73,7 @@ fn configure_mounts( mounts.insert( 0, MountDescriptor { - guest_path: String::from("/__secure_exec/commands/0"), + guest_path: String::from("/__agentos/commands/0"), guest_source: String::from("host_dir"), guest_fstype: String::from("host_dir"), read_only: true, diff --git a/crates/native-sidecar/tests/projection_bench.rs b/crates/native-sidecar/tests/projection_bench.rs index 034b4830f8..c623c19635 100644 --- a/crates/native-sidecar/tests/projection_bench.rs +++ b/crates/native-sidecar/tests/projection_bench.rs @@ -199,7 +199,7 @@ impl Drop for SyntheticTargets { fn write_repeated_file(path: &Path, len: usize) { let mut file = fs::File::create(path) .unwrap_or_else(|e| panic!("create synthetic payload {} failed: {e}", path.display())); - let chunk = b"secure-exec projection bench payload\n"; + let chunk = b"agentos projection bench payload\n"; let mut remaining = len; while remaining > 0 { let n = remaining.min(chunk.len()); @@ -257,7 +257,7 @@ fn create_package_tar(label: &str, dest: &Path, commands: &[&str], payload_bytes fn create_synthetic_targets() -> SyntheticTargets { let unique = format!( - "secure-exec-projection-bench-{}-{}", + "agentos-projection-bench-{}-{}", std::process::id(), std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) @@ -304,7 +304,7 @@ fn create_synthetic_targets() -> SyntheticTargets { fn create_repacked_real_targets(sources: &[(&'static str, &Path)]) -> RealTargets { let unique = format!( - "secure-exec-projection-real-{}-{}", + "agentos-projection-real-{}-{}", std::process::id(), std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) diff --git a/crates/native-sidecar/tests/promisify_module_load.rs b/crates/native-sidecar/tests/promisify_module_load.rs index 540fa323bc..c2c049e9b4 100644 --- a/crates/native-sidecar/tests/promisify_module_load.rs +++ b/crates/native-sidecar/tests/promisify_module_load.rs @@ -1,6 +1,6 @@ //! Regression guard for issue #11: `util.promisify()` throws at module load. //! -//! Original failure mode: a hand-rolled `@secure-exec/core` `util` polyfill exposed many +//! Original failure mode: a hand-rolled legacy `util` polyfill exposed many //! builtin functions as `undefined`. Adapter dependencies (extract-zip, get-stream) called //! `promisify(undefined)` at module-load time, and the polyfill's `promisify` threw a //! `TypeError` synchronously, crashing the whole module load before any application code ran. diff --git a/crates/native-sidecar/tests/protocol.rs b/crates/native-sidecar/tests/protocol.rs index c920439557..b1a17c8cea 100644 --- a/crates/native-sidecar/tests/protocol.rs +++ b/crates/native-sidecar/tests/protocol.rs @@ -130,7 +130,7 @@ fn ext_envelope_event_encoding_microbench() { let ext_frame = ProtocolFrame::Event(EventFrame::new( ownership.clone(), EventPayload::Ext(ExtEnvelope { - namespace: String::from("dev.rivet.secure-exec.acp"), + namespace: String::from("dev.rivet.agentos.acp"), payload: inner, }), )); diff --git a/crates/native-sidecar/tests/sandbox_agent.rs b/crates/native-sidecar/tests/sandbox_agent.rs index 83ce1dcf4d..144ff2e766 100644 --- a/crates/native-sidecar/tests/sandbox_agent.rs +++ b/crates/native-sidecar/tests/sandbox_agent.rs @@ -16,7 +16,7 @@ mod sandbox_agent { #[test] fn filesystem_round_trips_small_files_and_uses_http_range_for_large_pread() { - let server = MockSandboxAgentServer::start("secure-exec-sandbox-plugin", None); + let server = MockSandboxAgentServer::start("agentos-sandbox-plugin", None); fs::write(server.root().join("hello.txt"), "hello from sandbox").expect("seed file"); let large_file = (0..100 * 1024) .map(|index| (index % 251) as u8) @@ -73,10 +73,8 @@ mod sandbox_agent { #[test] fn filesystem_pread_falls_back_to_full_fetch_when_remote_ignores_range() { - let server = MockSandboxAgentServer::start_without_range_support( - "secure-exec-sandbox-plugin", - None, - ); + let server = + MockSandboxAgentServer::start_without_range_support("agentos-sandbox-plugin", None); let large_file = (0..100 * 1024) .map(|index| (index % 251) as u8) .collect::>(); @@ -117,7 +115,7 @@ mod sandbox_agent { #[test] fn filesystem_pread_rejects_full_fetch_fallback_above_limit() { let server = MockSandboxAgentServer::start_without_range_support( - "secure-exec-sandbox-plugin-limit", + "agentos-sandbox-plugin-limit", None, ); fs::write(server.root().join("large.bin"), vec![b'x'; 4096]).expect("seed large file"); @@ -145,7 +143,7 @@ mod sandbox_agent { #[test] fn filesystem_pread_rejects_streamed_full_fetch_fallback_above_limit() { let server = MockSandboxAgentServer::start_without_range_support( - "secure-exec-sandbox-plugin-stream-limit", + "agentos-sandbox-plugin-stream-limit", None, ); fs::write(server.root().join("stream-over-limit"), vec![b'x'; 4096]) @@ -185,7 +183,7 @@ mod sandbox_agent { #[test] fn sandbox_agent_client_does_not_follow_redirects() { - let server = MockSandboxAgentServer::start("secure-exec-sandbox-plugin-redirect", None); + let server = MockSandboxAgentServer::start("agentos-sandbox-plugin-redirect", None); let mut filesystem = SandboxAgentFilesystem::from_config(SandboxAgentMountConfig { base_url: server.base_url().to_owned(), @@ -274,7 +272,7 @@ mod sandbox_agent { #[test] fn filesystem_truncate_uses_process_api_without_full_file_buffering() { - let server = MockSandboxAgentServer::start("secure-exec-sandbox-plugin-truncate", None); + let server = MockSandboxAgentServer::start("agentos-sandbox-plugin-truncate", None); fs::write(server.root().join("large.bin"), vec![b'x'; 512]).expect("seed large file"); let mut filesystem = SandboxAgentFilesystem::from_config(SandboxAgentMountConfig { @@ -340,10 +338,8 @@ mod sandbox_agent { #[test] fn plugin_scopes_base_path_and_preserves_auth_headers() { - let server = MockSandboxAgentServer::start( - "secure-exec-sandbox-plugin-auth", - Some("secret-token"), - ); + let server = + MockSandboxAgentServer::start("agentos-sandbox-plugin-auth", Some("secret-token")); fs::create_dir_all(server.root().join("scoped")).expect("create scoped root"); fs::write(server.root().join("scoped/hello.txt"), "scoped hello") .expect("seed scoped file"); @@ -387,8 +383,7 @@ mod sandbox_agent { #[test] fn plugin_normalizes_relative_base_path_before_scoping_requests() { - let server = - MockSandboxAgentServer::start("secure-exec-sandbox-plugin-base-path", None); + let server = MockSandboxAgentServer::start("agentos-sandbox-plugin-base-path", None); fs::create_dir_all(server.root().join("scoped")).expect("create scoped root"); fs::write( server.root().join("scoped/hello.txt"), @@ -427,7 +422,7 @@ mod sandbox_agent { #[test] fn plugin_unscopes_process_helper_targets_for_relative_base_path() { let server = - MockSandboxAgentServer::start("secure-exec-sandbox-plugin-relative-process", None); + MockSandboxAgentServer::start("agentos-sandbox-plugin-relative-process", None); fs::create_dir_all(server.root().join("scoped")).expect("create scoped root"); fs::write( server.root().join("scoped/original.txt"), @@ -470,7 +465,7 @@ mod sandbox_agent { #[test] fn filesystem_uses_process_api_for_symlink_and_metadata_operations() { - let server = MockSandboxAgentServer::start("secure-exec-sandbox-plugin-process", None); + let server = MockSandboxAgentServer::start("agentos-sandbox-plugin-process", None); fs::write(server.root().join("original.txt"), "hello from sandbox") .expect("seed original file"); @@ -563,7 +558,7 @@ mod sandbox_agent { #[test] fn filesystem_reports_clear_error_when_process_api_is_unavailable() { let server = MockSandboxAgentServer::start_without_process_api( - "secure-exec-sandbox-plugin-no-proc", + "agentos-sandbox-plugin-no-proc", None, ); fs::write(server.root().join("original.txt"), "hello from sandbox") diff --git a/crates/native-sidecar/tests/service.rs b/crates/native-sidecar/tests/service.rs index 4a0769ce9b..cb1f69c64c 100644 --- a/crates/native-sidecar/tests/service.rs +++ b/crates/native-sidecar/tests/service.rs @@ -24,6 +24,9 @@ mod filesystem; #[allow(dead_code, unused_imports)] #[path = "../src/json_rpc.rs"] mod json_rpc; +#[allow(dead_code)] +#[path = "../src/language_execution.rs"] +mod language_execution; #[allow(dead_code, unused_imports)] #[path = "../src/limits.rs"] mod limits; @@ -2209,7 +2212,7 @@ ykAheWCsAteSEWVc0w==\n\ OwnershipScope::vm(connection_id, session_id, vm_id), RequestPayload::ConfigureVm(ConfigureVmRequest { mounts: vec![MountDescriptor { - guest_path: String::from("/__secure_exec/commands/0"), + guest_path: String::from("/__agentos/commands/0"), guest_source: String::from("agentos"), guest_fstype: String::from("agentos"), read_only: true, @@ -3338,7 +3341,7 @@ console.log(JSON.stringify({ status: "ok", summary })); ), fixture_dns_record( "bundle.example.test.", - RData::TXT(TXT::new(vec![String::from("secure-exec")])), + RData::TXT(TXT::new(vec![String::from("agentos")])), ), ], ("bundle.example.test.", RecordType::ANY) => vec![ @@ -9556,7 +9559,7 @@ console.log(JSON.stringify({ status: "ok", summary })); .expect("clock should be monotonic") .as_nanos(); let metadata_path = - std::env::temp_dir().join(format!("secure-exec-service-s3-{unique}.sqlite")); + std::env::temp_dir().join(format!("agentos-service-s3-{unique}.sqlite")); let mut sidecar = create_test_sidecar(); let (connection_id, session_id) = @@ -11304,7 +11307,7 @@ console.log(JSON.stringify({ status: "ok", summary })); OwnershipScope::vm(&connection_id, &session_id, &vm_id), RequestPayload::ConfigureVm(ConfigureVmRequest { mounts: vec![MountDescriptor { - guest_path: String::from("/__secure_exec/commands/0"), + guest_path: String::from("/__agentos/commands/0"), guest_source: String::from("agentos"), guest_fstype: String::from("agentos"), read_only: true, @@ -11406,7 +11409,7 @@ console.log(JSON.stringify({ status: "ok", summary })); OwnershipScope::vm(&connection_id, &session_id, &vm_id), RequestPayload::ConfigureVm(ConfigureVmRequest { mounts: vec![MountDescriptor { - guest_path: String::from("/__secure_exec/commands/0"), + guest_path: String::from("/__agentos/commands/0"), guest_source: String::from("agentos"), guest_fstype: String::from("agentos"), read_only: true, @@ -11804,7 +11807,7 @@ console.log(JSON.stringify({ status: "ok", summary })); OwnershipScope::vm(&connection_id, &session_id, &vm_id), RequestPayload::ConfigureVm(ConfigureVmRequest { mounts: vec![MountDescriptor { - guest_path: String::from("/__secure_exec/commands/0"), + guest_path: String::from("/__agentos/commands/0"), guest_source: String::from("agentos"), guest_fstype: String::from("agentos"), read_only: true, @@ -11841,11 +11844,11 @@ console.log(JSON.stringify({ status: "ok", summary })); assert!( path_entries .first() - .is_some_and(|entry| *entry == "/__secure_exec/commands/0"), + .is_some_and(|entry| *entry == "/__agentos/commands/0"), "PATH should prioritize mounted command root: {path}" ); assert!( - path_entries.contains(&"/__secure_exec/commands/0"), + path_entries.contains(&"/__agentos/commands/0"), "PATH should include mounted command root: {path}" ); @@ -13512,7 +13515,7 @@ process.stdout.write(`${JSON.stringify(snapshot)}\n`); &vm_id, "proc-js-binding-rpc", crate::protocol::JavascriptChildProcessSpawnRequest { - command: String::from("/__secure_exec/commands/0/agentos-math"), + command: String::from("/__agentos/commands/0/agentos-math"), args: vec![ String::from("add"), String::from("--a"), @@ -13566,7 +13569,7 @@ process.stdout.write(`${JSON.stringify(snapshot)}\n`); &vm.guest_cwd, &vm.host_cwd, &crate::protocol::JavascriptChildProcessSpawnRequest { - command: String::from("/__secure_exec/commands/0/agentos-math"), + command: String::from("/__agentos/commands/0/agentos-math"), args: vec![ String::from("add"), String::from("--a"), @@ -17505,7 +17508,7 @@ await new Promise(() => {}); json!("aes-256-gcm"), json!(base64::engine::general_purpose::STANDARD.encode([7_u8; 32])), json!(base64::engine::general_purpose::STANDARD.encode([3_u8; 12])), - json!(base64::engine::general_purpose::STANDARD.encode(b"secure-exec")), + json!(base64::engine::general_purpose::STANDARD.encode(b"agentos")), json!(r#"{"aad":"YWR2YW5jZWQ=","authTagLength":16}"#), ], }, @@ -17535,7 +17538,7 @@ await new Promise(() => {}); .expect("decipheriv response"); assert_eq!( decode_base64(decipher_response.as_str().expect("decipher response")), - b"secure-exec" + b"agentos" ); let mut streaming_process = create_crypto_test_process(); @@ -18986,7 +18989,7 @@ console.log(JSON.stringify({ membershipAddress, sourceAddress, reboundAddress, d r#" import net from "node:net"; -const path = "/tmp/secure-exec-unix-echo.sock"; +const path = "/tmp/agentos-unix-echo.sock"; const summary = await new Promise((resolve, reject) => { const server = net.createServer((socket) => { socket.setEncoding("utf8"); @@ -23755,7 +23758,7 @@ console.log(`BODY:${{body}}`); sidecar.vms.get(&vm_id).expect("javascript vm"), ) .expect("build Unix socket path context"); - let socket_path = "/tmp/secure-exec.sock"; + let socket_path = "/tmp/agentos.sock"; let listen = { let vm = sidecar.vms.get_mut(&vm_id).expect("javascript vm"); @@ -24157,7 +24160,7 @@ console.log(`BODY:${{body}}`); 19_u64, "net.connect", vec![json!({ "path": socket_path })], - "unix:/tmp/secure-exec.sock", + "unix:/tmp/agentos.sock", ), ( 20_u64, @@ -24968,7 +24971,7 @@ try { ), ( String::from("AGENTOS_VIRTUAL_OS_HOSTNAME"), - String::from("secure-exec-test"), + String::from("agentos-test"), ), ( String::from("AGENTOS_PARENT_NODE_ALLOW_CHILD_PROCESS"), @@ -24998,7 +25001,7 @@ try { ); assert_eq!( filtered.get("AGENTOS_VIRTUAL_OS_HOSTNAME"), - Some(&String::from("secure-exec-test")) + Some(&String::from("agentos-test")) ); assert!(!filtered.contains_key("AGENTOS_PARENT_NODE_ALLOW_CHILD_PROCESS")); assert!(!filtered.contains_key("VISIBLE_MARKER")); diff --git a/crates/native-sidecar/tests/support/mod.rs b/crates/native-sidecar/tests/support/mod.rs index 7e9411410f..46598c06aa 100644 --- a/crates/native-sidecar/tests/support/mod.rs +++ b/crates/native-sidecar/tests/support/mod.rs @@ -387,6 +387,8 @@ pub fn try_collect_process_output_wire_with_timeout( agentos_native_sidecar::wire::EventPayload::ProcessExitedEvent(_) | agentos_native_sidecar::wire::EventPayload::VmLifecycleEvent(_) | agentos_native_sidecar::wire::EventPayload::StructuredEvent(_) + | agentos_native_sidecar::wire::EventPayload::ExecutionOutputEvent(_) + | agentos_native_sidecar::wire::EventPayload::ExecutionCompletedEvent(_) | agentos_native_sidecar::wire::EventPayload::ExtEnvelope(_) => {} } } diff --git a/crates/native-sidecar/tests/xfstests_correctness.rs b/crates/native-sidecar/tests/xfstests_correctness.rs index 175fcdf938..b308b04193 100644 --- a/crates/native-sidecar/tests/xfstests_correctness.rs +++ b/crates/native-sidecar/tests/xfstests_correctness.rs @@ -466,15 +466,11 @@ fn configure_verification_mounts( session_id, vm_id, vec![ - host_dir_mount( - "/__secure_exec/commands/0", - &command_root("coreutils"), - true, - ), - host_dir_mount("/__secure_exec/commands/1", &c_probe_root(), true), - host_dir_mount("/__secure_exec/commands/2", &command_root("attr"), true), - host_dir_mount("/__secure_exec/commands/3", &command_root("acl"), true), - host_dir_mount("/__secure_exec/commands/4", &command_root("sed"), true), + host_dir_mount("/__agentos/commands/0", &command_root("coreutils"), true), + host_dir_mount("/__agentos/commands/1", &c_probe_root(), true), + host_dir_mount("/__agentos/commands/2", &command_root("attr"), true), + host_dir_mount("/__agentos/commands/3", &command_root("acl"), true), + host_dir_mount("/__agentos/commands/4", &command_root("sed"), true), xfstests_backend_mount( backend, "/mnt/test", @@ -3726,7 +3722,7 @@ fn xfstests_wasi_fifo_open_routes_to_kernel_pipe() { let vm_id = create_xfstests_vm_wire(&mut sidecar, 3, &connection_id, &session_id, &cwd); let mut mounts = xfstests_mounts(&source, root.path(), XFSTESTS_BACKEND, None); mounts.push(host_dir_mount( - &format!("/__secure_exec/commands/{}", COMMAND_PACKAGES.len()), + &format!("/__agentos/commands/{}", COMMAND_PACKAGES.len()), &c_probe_root(), true, )); @@ -3855,7 +3851,7 @@ fn xfstests_mknod_creates_a_working_null_device() { let vm_id = create_xfstests_vm_wire(&mut sidecar, 3, &connection_id, &session_id, &cwd); let mut mounts = xfstests_mounts(&source, root.path(), XFSTESTS_BACKEND, None); mounts.push(host_dir_mount( - &format!("/__secure_exec/commands/{}", COMMAND_PACKAGES.len()), + &format!("/__agentos/commands/{}", COMMAND_PACKAGES.len()), &c_probe_root(), true, )); @@ -4500,7 +4496,7 @@ fn xfstests_mounts( .enumerate() .map(|(index, package)| { host_dir_mount( - &format!("/__secure_exec/commands/{index}"), + &format!("/__agentos/commands/{index}"), &command_root(package), true, ) @@ -4887,10 +4883,7 @@ printf 'parent-commands-ok\\n'" &connection_id, &session_id, &vm_id, - filesystem_request( - GuestFilesystemOperation::Exists, - "/__secure_exec/commands/2/rm", - ), + filesystem_request(GuestFilesystemOperation::Exists, "/__agentos/commands/2/rm"), ) .exists; let (fresh_stdout, fresh_stderr, fresh_exit_code) = execute_command( @@ -5048,7 +5041,7 @@ fn xfstests_wasi_waitpid_options_and_status() { let vm_id = create_xfstests_vm_wire(&mut sidecar, 3, &connection_id, &session_id, &cwd); let mut mounts = xfstests_mounts(&source, root.path(), XFSTESTS_BACKEND, None); mounts.push(host_dir_mount( - &format!("/__secure_exec/commands/{}", COMMAND_PACKAGES.len()), + &format!("/__agentos/commands/{}", COMMAND_PACKAGES.len()), &c_probe_root(), true, )); @@ -5107,7 +5100,7 @@ fn xfstests_wasi_self_stop_and_parent_continue() { let vm_id = create_xfstests_vm_wire(&mut sidecar, 3, &connection_id, &session_id, &cwd); let mut mounts = xfstests_mounts(&source, root.path(), XFSTESTS_BACKEND, None); mounts.push(host_dir_mount( - &format!("/__secure_exec/commands/{}", COMMAND_PACKAGES.len()), + &format!("/__agentos/commands/{}", COMMAND_PACKAGES.len()), &c_probe_root(), true, )); @@ -5422,7 +5415,7 @@ fn xfstests_truncfile_scaled_throughput_regression() { let vm_id = create_xfstests_vm_wire(&mut sidecar, 3, &connection_id, &session_id, &cwd); let mut mounts = xfstests_mounts(&source, root.path(), &backend, s3_endpoint); mounts.push(host_dir_mount( - &format!("/__secure_exec/commands/{}", COMMAND_PACKAGES.len()), + &format!("/__agentos/commands/{}", COMMAND_PACKAGES.len()), &source.join("src"), true, )); @@ -5507,7 +5500,7 @@ fn xfstests_wasi_helper_ports() { let vm_id = create_xfstests_vm_wire(&mut sidecar, 3, &connection_id, &session_id, &cwd); let mut mounts = xfstests_mounts(&source, root.path(), XFSTESTS_BACKEND, None); mounts.push(host_dir_mount( - &format!("/__secure_exec/commands/{}", COMMAND_PACKAGES.len()), + &format!("/__agentos/commands/{}", COMMAND_PACKAGES.len()), &c_probe_root(), true, )); diff --git a/crates/sidecar-client/CLAUDE.md b/crates/sidecar-client/CLAUDE.md index 037e9b94a2..402e15f2e9 100644 --- a/crates/sidecar-client/CLAUDE.md +++ b/crates/sidecar-client/CLAUDE.md @@ -4,4 +4,4 @@ See `../CLAUDE.md` for crate-wide runtime and testing rules. - Keep this crate Agent OS-agnostic: no `agentos-protocol`, `agentos-client`, `agentos-sidecar`, ACP, agents, sessions, or binding semantics. - The generic transport resolves `AGENTOS_SIDECAR_BIN` / `agentos-native-sidecar`; product wrappers such as Agent OS must resolve their own wrapper binary and pass it explicitly. -- Expose raw secure-exec wire types and transport primitives only; ergonomic product facades belong in product-specific client crates. +- Expose raw agentos wire types and transport primitives only; ergonomic product facades belong in product-specific client crates. diff --git a/crates/sidecar-client/Cargo.toml b/crates/sidecar-client/Cargo.toml index 9f7e17a230..7b79cfffcf 100644 --- a/crates/sidecar-client/Cargo.toml +++ b/crates/sidecar-client/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Rust client transport for the Secure Exec native sidecar" +description = "Rust client transport for the AgentOS language execution native sidecar" [dependencies] agentos-sidecar-protocol = { workspace = true } diff --git a/crates/sidecar-client/src/lib.rs b/crates/sidecar-client/src/lib.rs index 4da4ab71fe..eb1d3347ac 100644 --- a/crates/sidecar-client/src/lib.rs +++ b/crates/sidecar-client/src/lib.rs @@ -1,8 +1,8 @@ #![forbid(unsafe_code)] -//! Low-level Rust client transport for the Secure Exec native sidecar. +//! Low-level Rust client transport for the AgentOS language execution native sidecar. //! -//! This crate owns the framed stdio transport and exposes the generated Secure Exec wire protocol. +//! This crate owns the framed stdio transport and exposes the generated AgentOS language execution wire protocol. //! Higher level products layer their own authentication, extension payloads, and //! typed API surfaces on top of this transport. diff --git a/crates/sidecar-client/src/transport.rs b/crates/sidecar-client/src/transport.rs index b2ee2c715a..9f248181bc 100644 --- a/crates/sidecar-client/src/transport.rs +++ b/crates/sidecar-client/src/transport.rs @@ -660,7 +660,7 @@ mod tests { } #[test] - fn binary_path_uses_secure_exec_env_fallback() { + fn binary_path_uses_agentos_env_fallback() { let _guard = ENV_LOCK.lock().expect("env lock"); let previous = std::env::var(SIDECAR_BIN_ENV).ok(); std::env::set_var(SIDECAR_BIN_ENV, "/tmp/agentos-native-sidecar"); diff --git a/crates/sidecar-client/src/wire.rs b/crates/sidecar-client/src/wire.rs index 73505b95ad..3538444bd3 100644 --- a/crates/sidecar-client/src/wire.rs +++ b/crates/sidecar-client/src/wire.rs @@ -1,3 +1,3 @@ -//! Raw generated Secure Exec sidecar protocol types and BARE frame helpers. +//! Raw generated AgentOS language execution sidecar protocol types and BARE frame helpers. pub use agentos_sidecar_protocol::wire::*; diff --git a/crates/sidecar-protocol/Cargo.toml b/crates/sidecar-protocol/Cargo.toml index 3bb07d4dca..a8fbe8c1b0 100644 --- a/crates/sidecar-protocol/Cargo.toml +++ b/crates/sidecar-protocol/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Shared Secure Exec sidecar wire protocol and frame helpers" +description = "Shared AgentOS language execution sidecar wire protocol and frame helpers" [lib] name = "agentos_sidecar_protocol" diff --git a/crates/sidecar-protocol/protocol/agentos_sidecar_v1.bare b/crates/sidecar-protocol/protocol/agentos_sidecar_v1.bare index 315ecd9ad1..0c145040b1 100644 --- a/crates/sidecar-protocol/protocol/agentos_sidecar_v1.bare +++ b/crates/sidecar-protocol/protocol/agentos_sidecar_v1.bare @@ -1,4 +1,4 @@ -# Secure Exec sidecar protocol schema, version 1. +# AgentOS language execution sidecar protocol schema, version 1. # This schema is generator-ready: numeric ordinals are intentionally omitted # and type blocks are ordered before first use. @@ -384,6 +384,246 @@ type ExecuteRequest struct { wasmPermissionTier: optional } +# First-class execution lifecycle. The legacy process request above remains an +# internal kernel transport while clients migrate in lockstep to these semantic +# operations; language/package command construction belongs to the sidecar. +type ExecutionState enum { + CREATING + IDLE + RUNNING + RESETTING + DELETING + FAILED +} + +type ExecutionOutcome enum { + SUCCEEDED + FAILED + CANCELLED + TIMED_OUT +} + +type RetainedExecutionLanguage enum { + JAVA_SCRIPT + PYTHON +} + +type ExecutionStreamChannel enum { + STDOUT + STDERR + PTY +} + +type JavaScriptModuleFormat enum { + MODULE + COMMON_JS +} + +type ExecutionIdentityOptions struct { + executionId: optional + createIfMissing: optional +} + +type ExecutionPtyOptions struct { + cols: optional + rows: optional +} + +type ProcessExecutionOptions struct { + identity: ExecutionIdentityOptions + detached: optional + cwd: optional + env: optional> + args: list + stdin: optional + timeoutMs: optional + pty: optional +} + +type ShellExecutionRequest struct { + process: ProcessExecutionOptions + command: str +} + +type ArgvExecutionRequest struct { + process: ProcessExecutionOptions + command: str +} + +type JavaScriptExecutionRequest struct { + process: ProcessExecutionOptions + source: str + format: optional + filePath: optional + inputs: optional +} + +type JavaScriptEvaluationRequest struct { + process: ProcessExecutionOptions + expression: str + format: optional + filePath: optional + inputs: optional +} + +type JavaScriptFileExecutionRequest struct { + process: ProcessExecutionOptions + path: str +} + +type TypeScriptExecutionRequest struct { + process: ProcessExecutionOptions + source: str + filePath: optional + tsconfigPath: optional + compilerOptions: optional + inputs: optional +} + +type TypeScriptEvaluationRequest struct { + process: ProcessExecutionOptions + expression: str + filePath: optional + tsconfigPath: optional + compilerOptions: optional + inputs: optional +} + +type TypeScriptFileExecutionRequest struct { + process: ProcessExecutionOptions + path: str + tsconfigPath: optional + compilerOptions: optional +} + +type TypeScriptCheckRequest struct { + identity: ExecutionIdentityOptions + source: str + cwd: optional + filePath: optional + tsconfigPath: optional + compilerOptions: optional + timeoutMs: optional +} + +type TypeScriptProjectCheckRequest struct { + identity: ExecutionIdentityOptions + cwd: optional + tsconfigPath: optional + timeoutMs: optional +} + +type NpmProjectInstallRequest struct { + identity: ExecutionIdentityOptions + cwd: optional + env: optional> + timeoutMs: optional + frozen: optional +} + +type NpmPackageInstallRequest struct { + identity: ExecutionIdentityOptions + cwd: optional + env: optional> + timeoutMs: optional + packages: list + dev: optional + global: optional +} + +type NpmScriptExecutionRequest struct { + process: ProcessExecutionOptions + script: str +} + +type NpmPackageExecutionRequest struct { + process: ProcessExecutionOptions + packageSpec: str + binary: optional +} + +type PythonExecutionRequest struct { + process: ProcessExecutionOptions + source: str + inputs: optional +} + +type PythonEvaluationRequest struct { + process: ProcessExecutionOptions + expression: str + inputs: optional +} + +type PythonFileExecutionRequest struct { + process: ProcessExecutionOptions + path: str +} + +type PythonModuleExecutionRequest struct { + process: ProcessExecutionOptions + module: str +} + +type PythonInstallRequest struct { + identity: ExecutionIdentityOptions + cwd: optional + env: optional> + timeoutMs: optional + packages: list + upgrade: optional + requirementsFile: optional + indexUrl: optional + extraIndexUrls: list +} + +type GetExecutionRequest struct { + executionId: str +} + +type ListExecutionsRequest void + +type WaitExecutionRequest struct { + executionId: str +} + +type CancelExecutionRequest struct { + executionId: str +} + +type SignalExecutionRequest struct { + executionId: str + signal: str +} + +type ResetExecutionRequest struct { + executionId: str +} + +type DeleteExecutionRequest struct { + executionId: str +} + +type WriteExecutionStdinRequest struct { + executionId: str + chunk: data +} + +type CloseExecutionStdinRequest struct { + executionId: str +} + +type ResizeExecutionPtyRequest struct { + executionId: str + cols: u16 + rows: u16 +} + +type ReadExecutionOutputRequest struct { + executionId: str + cursor: optional + limit: optional +} + type WriteStdinRequest struct { processId: str chunk: data @@ -492,7 +732,37 @@ type RequestPayload union { GetResourceSnapshotRequest | LinkPackageRequest | ProvidedCommandsRequest | - ListMountsRequest + ListMountsRequest | + ShellExecutionRequest | + ArgvExecutionRequest | + JavaScriptExecutionRequest | + JavaScriptEvaluationRequest | + JavaScriptFileExecutionRequest | + TypeScriptExecutionRequest | + TypeScriptEvaluationRequest | + TypeScriptFileExecutionRequest | + TypeScriptCheckRequest | + TypeScriptProjectCheckRequest | + NpmProjectInstallRequest | + NpmPackageInstallRequest | + NpmScriptExecutionRequest | + NpmPackageExecutionRequest | + PythonExecutionRequest | + PythonEvaluationRequest | + PythonFileExecutionRequest | + PythonModuleExecutionRequest | + PythonInstallRequest | + GetExecutionRequest | + ListExecutionsRequest | + WaitExecutionRequest | + CancelExecutionRequest | + SignalExecutionRequest | + ResetExecutionRequest | + DeleteExecutionRequest | + WriteExecutionStdinRequest | + CloseExecutionStdinRequest | + ResizeExecutionPtyRequest | + ReadExecutionOutputRequest } type RequestFrame struct { @@ -762,6 +1032,100 @@ type VmFetchResponse struct { responseJson: str } +type ExecutionDescriptor struct { + executionId: str + generation: u64 + state: ExecutionState + retainedLanguage: optional + processId: optional + pid: optional + createdAtMs: u64 + lastStartedAtMs: optional + lastCompletedAtMs: optional + lastOutcome: optional + lastExitCode: optional +} + +type ExecutionErrorData struct { + code: str + name: str + message: str + stack: optional + details: optional +} + +type ExecutionAcceptedResponse struct { + execution: ExecutionDescriptor +} + +type ExecutionCompletedResponse struct { + execution: ExecutionDescriptor + outcome: ExecutionOutcome + exitCode: optional + error: optional + stdout: data + stderr: data + stdoutTruncated: bool + stderrTruncated: bool + outputs: JsonUtf8 +} + +type ExecutionEvaluationResponse struct { + result: ExecutionCompletedResponse + value: optional +} + +type TypeScriptDiagnostic struct { + code: u32 + category: str + message: str + filePath: optional + line: optional + column: optional +} + +type TypeScriptCheckResponse struct { + result: ExecutionCompletedResponse + hasErrors: optional + diagnostics: list +} + +type ExecutionDescriptorResponse struct { + execution: ExecutionDescriptor +} + +type ExecutionListResponse struct { + executions: list +} + +type ExecutionDeletedResponse struct { + executionId: str +} + +type ExecutionIoResponse struct { + executionId: str + acceptedBytes: optional +} + +type ExecutionOutputEvent struct { + executionId: str + generation: u64 + processId: optional + sequence: u64 + channel: ExecutionStreamChannel + chunk: data + timestampMs: u64 +} + +type ExecutionOutputPageResponse struct { + executionId: str + generation: u64 + events: list + nextCursor: str + hasMore: bool + truncated: bool +} + type ResponsePayload union { AuthenticatedResponse | SessionOpenedResponse | @@ -798,7 +1162,16 @@ type ResponsePayload union { ResourceSnapshotResponse | PackageLinkedResponse | ProvidedCommandsResponse | - ListMountsResponse + ListMountsResponse | + ExecutionAcceptedResponse | + ExecutionCompletedResponse | + ExecutionEvaluationResponse | + TypeScriptCheckResponse | + ExecutionDescriptorResponse | + ExecutionListResponse | + ExecutionDeletedResponse | + ExecutionIoResponse | + ExecutionOutputPageResponse } type ResponseFrame struct { @@ -836,6 +1209,14 @@ type ProcessExitedEvent struct { exitCode: i32 } +type ExecutionCompletedEvent struct { + executionId: str + generation: u64 + outcome: ExecutionOutcome + exitCode: optional + error: optional +} + type StructuredEvent struct { name: str detail: map @@ -846,7 +1227,9 @@ type EventPayload union { ProcessOutputEvent | ProcessExitedEvent | StructuredEvent | - ExtEnvelope + ExtEnvelope | + ExecutionOutputEvent | + ExecutionCompletedEvent } type EventFrame struct { diff --git a/crates/sidecar-protocol/src/lib.rs b/crates/sidecar-protocol/src/lib.rs index 7929ac0511..20d162ba5a 100644 --- a/crates/sidecar-protocol/src/lib.rs +++ b/crates/sidecar-protocol/src/lib.rs @@ -3,7 +3,7 @@ // payload variants); boxing them is a wire-adjacent refactor tracked separately. #![allow(clippy::large_enum_variant, clippy::result_large_err)] -//! Shared Secure Exec sidecar wire protocol surface. +//! Shared AgentOS language execution sidecar wire protocol surface. pub mod generated_protocol; pub mod protocol; diff --git a/crates/sidecar-protocol/src/protocol.rs b/crates/sidecar-protocol/src/protocol.rs index 91518f4f3b..beb0cc6987 100644 --- a/crates/sidecar-protocol/src/protocol.rs +++ b/crates/sidecar-protocol/src/protocol.rs @@ -505,6 +505,96 @@ fn to_generated_request_payload( RequestPayload::ProvidedCommands(_) => { generated_protocol::RequestPayload::ProvidedCommandsRequest } + RequestPayload::ShellExecution(inner) => { + generated_protocol::RequestPayload::ShellExecutionRequest(inner.clone()) + } + RequestPayload::ArgvExecution(inner) => { + generated_protocol::RequestPayload::ArgvExecutionRequest(inner.clone()) + } + RequestPayload::JavaScriptExecution(inner) => { + generated_protocol::RequestPayload::JavaScriptExecutionRequest(inner.clone()) + } + RequestPayload::JavaScriptEvaluation(inner) => { + generated_protocol::RequestPayload::JavaScriptEvaluationRequest(inner.clone()) + } + RequestPayload::JavaScriptFileExecution(inner) => { + generated_protocol::RequestPayload::JavaScriptFileExecutionRequest(inner.clone()) + } + RequestPayload::TypeScriptExecution(inner) => { + generated_protocol::RequestPayload::TypeScriptExecutionRequest(inner.clone()) + } + RequestPayload::TypeScriptEvaluation(inner) => { + generated_protocol::RequestPayload::TypeScriptEvaluationRequest(inner.clone()) + } + RequestPayload::TypeScriptFileExecution(inner) => { + generated_protocol::RequestPayload::TypeScriptFileExecutionRequest(inner.clone()) + } + RequestPayload::TypeScriptCheck(inner) => { + generated_protocol::RequestPayload::TypeScriptCheckRequest(inner.clone()) + } + RequestPayload::TypeScriptProjectCheck(inner) => { + generated_protocol::RequestPayload::TypeScriptProjectCheckRequest(inner.clone()) + } + RequestPayload::NpmProjectInstall(inner) => { + generated_protocol::RequestPayload::NpmProjectInstallRequest(inner.clone()) + } + RequestPayload::NpmPackageInstall(inner) => { + generated_protocol::RequestPayload::NpmPackageInstallRequest(inner.clone()) + } + RequestPayload::NpmScriptExecution(inner) => { + generated_protocol::RequestPayload::NpmScriptExecutionRequest(inner.clone()) + } + RequestPayload::NpmPackageExecution(inner) => { + generated_protocol::RequestPayload::NpmPackageExecutionRequest(inner.clone()) + } + RequestPayload::PythonExecution(inner) => { + generated_protocol::RequestPayload::PythonExecutionRequest(inner.clone()) + } + RequestPayload::PythonEvaluation(inner) => { + generated_protocol::RequestPayload::PythonEvaluationRequest(inner.clone()) + } + RequestPayload::PythonFileExecution(inner) => { + generated_protocol::RequestPayload::PythonFileExecutionRequest(inner.clone()) + } + RequestPayload::PythonModuleExecution(inner) => { + generated_protocol::RequestPayload::PythonModuleExecutionRequest(inner.clone()) + } + RequestPayload::PythonInstall(inner) => { + generated_protocol::RequestPayload::PythonInstallRequest(inner.clone()) + } + RequestPayload::GetExecution(inner) => { + generated_protocol::RequestPayload::GetExecutionRequest(inner.clone()) + } + RequestPayload::ListExecutions(_) => { + generated_protocol::RequestPayload::ListExecutionsRequest + } + RequestPayload::WaitExecution(inner) => { + generated_protocol::RequestPayload::WaitExecutionRequest(inner.clone()) + } + RequestPayload::CancelExecution(inner) => { + generated_protocol::RequestPayload::CancelExecutionRequest(inner.clone()) + } + RequestPayload::SignalExecution(inner) => { + generated_protocol::RequestPayload::SignalExecutionRequest(inner.clone()) + } + RequestPayload::ResetExecution(inner) => { + generated_protocol::RequestPayload::ResetExecutionRequest(inner.clone()) + } + RequestPayload::DeleteExecution(inner) => { + generated_protocol::RequestPayload::DeleteExecutionRequest(inner.clone()) + } + RequestPayload::WriteExecutionStdin(inner) => { + generated_protocol::RequestPayload::WriteExecutionStdinRequest(inner.clone()) + } + RequestPayload::CloseExecutionStdin(inner) => { + generated_protocol::RequestPayload::CloseExecutionStdinRequest(inner.clone()) + } + RequestPayload::ResizeExecutionPty(inner) => { + generated_protocol::RequestPayload::ResizeExecutionPtyRequest(inner.clone()) + } + RequestPayload::ReadExecutionOutput(inner) => { + generated_protocol::RequestPayload::ReadExecutionOutputRequest(inner.clone()) + } }) } @@ -616,6 +706,96 @@ fn from_generated_request_payload( generated_protocol::RequestPayload::ProvidedCommandsRequest => { RequestPayload::ProvidedCommands(ProvidedCommandsRequest {}) } + generated_protocol::RequestPayload::ShellExecutionRequest(inner) => { + RequestPayload::ShellExecution(inner) + } + generated_protocol::RequestPayload::ArgvExecutionRequest(inner) => { + RequestPayload::ArgvExecution(inner) + } + generated_protocol::RequestPayload::JavaScriptExecutionRequest(inner) => { + RequestPayload::JavaScriptExecution(inner) + } + generated_protocol::RequestPayload::JavaScriptEvaluationRequest(inner) => { + RequestPayload::JavaScriptEvaluation(inner) + } + generated_protocol::RequestPayload::JavaScriptFileExecutionRequest(inner) => { + RequestPayload::JavaScriptFileExecution(inner) + } + generated_protocol::RequestPayload::TypeScriptExecutionRequest(inner) => { + RequestPayload::TypeScriptExecution(inner) + } + generated_protocol::RequestPayload::TypeScriptEvaluationRequest(inner) => { + RequestPayload::TypeScriptEvaluation(inner) + } + generated_protocol::RequestPayload::TypeScriptFileExecutionRequest(inner) => { + RequestPayload::TypeScriptFileExecution(inner) + } + generated_protocol::RequestPayload::TypeScriptCheckRequest(inner) => { + RequestPayload::TypeScriptCheck(inner) + } + generated_protocol::RequestPayload::TypeScriptProjectCheckRequest(inner) => { + RequestPayload::TypeScriptProjectCheck(inner) + } + generated_protocol::RequestPayload::NpmProjectInstallRequest(inner) => { + RequestPayload::NpmProjectInstall(inner) + } + generated_protocol::RequestPayload::NpmPackageInstallRequest(inner) => { + RequestPayload::NpmPackageInstall(inner) + } + generated_protocol::RequestPayload::NpmScriptExecutionRequest(inner) => { + RequestPayload::NpmScriptExecution(inner) + } + generated_protocol::RequestPayload::NpmPackageExecutionRequest(inner) => { + RequestPayload::NpmPackageExecution(inner) + } + generated_protocol::RequestPayload::PythonExecutionRequest(inner) => { + RequestPayload::PythonExecution(inner) + } + generated_protocol::RequestPayload::PythonEvaluationRequest(inner) => { + RequestPayload::PythonEvaluation(inner) + } + generated_protocol::RequestPayload::PythonFileExecutionRequest(inner) => { + RequestPayload::PythonFileExecution(inner) + } + generated_protocol::RequestPayload::PythonModuleExecutionRequest(inner) => { + RequestPayload::PythonModuleExecution(inner) + } + generated_protocol::RequestPayload::PythonInstallRequest(inner) => { + RequestPayload::PythonInstall(inner) + } + generated_protocol::RequestPayload::GetExecutionRequest(inner) => { + RequestPayload::GetExecution(inner) + } + generated_protocol::RequestPayload::ListExecutionsRequest => { + RequestPayload::ListExecutions(ListExecutionsRequest {}) + } + generated_protocol::RequestPayload::WaitExecutionRequest(inner) => { + RequestPayload::WaitExecution(inner) + } + generated_protocol::RequestPayload::CancelExecutionRequest(inner) => { + RequestPayload::CancelExecution(inner) + } + generated_protocol::RequestPayload::SignalExecutionRequest(inner) => { + RequestPayload::SignalExecution(inner) + } + generated_protocol::RequestPayload::ResetExecutionRequest(inner) => { + RequestPayload::ResetExecution(inner) + } + generated_protocol::RequestPayload::DeleteExecutionRequest(inner) => { + RequestPayload::DeleteExecution(inner) + } + generated_protocol::RequestPayload::WriteExecutionStdinRequest(inner) => { + RequestPayload::WriteExecutionStdin(inner) + } + generated_protocol::RequestPayload::CloseExecutionStdinRequest(inner) => { + RequestPayload::CloseExecutionStdin(inner) + } + generated_protocol::RequestPayload::ResizeExecutionPtyRequest(inner) => { + RequestPayload::ResizeExecutionPty(inner) + } + generated_protocol::RequestPayload::ReadExecutionOutputRequest(inner) => { + RequestPayload::ReadExecutionOutput(inner) + } }) } @@ -773,6 +953,33 @@ fn to_generated_response_payload( ResponsePayload::ProvidedCommands(inner) => { generated_protocol::ResponsePayload::ProvidedCommandsResponse(inner.clone()) } + ResponsePayload::ExecutionAccepted(inner) => { + generated_protocol::ResponsePayload::ExecutionAcceptedResponse(inner.clone()) + } + ResponsePayload::ExecutionCompleted(inner) => { + generated_protocol::ResponsePayload::ExecutionCompletedResponse(inner.clone()) + } + ResponsePayload::ExecutionEvaluation(inner) => { + generated_protocol::ResponsePayload::ExecutionEvaluationResponse(inner.clone()) + } + ResponsePayload::TypeScriptCheck(inner) => { + generated_protocol::ResponsePayload::TypeScriptCheckResponse(inner.clone()) + } + ResponsePayload::ExecutionDescriptor(inner) => { + generated_protocol::ResponsePayload::ExecutionDescriptorResponse(inner.clone()) + } + ResponsePayload::ExecutionList(inner) => { + generated_protocol::ResponsePayload::ExecutionListResponse(inner.clone()) + } + ResponsePayload::ExecutionDeleted(inner) => { + generated_protocol::ResponsePayload::ExecutionDeletedResponse(inner.clone()) + } + ResponsePayload::ExecutionIo(inner) => { + generated_protocol::ResponsePayload::ExecutionIoResponse(inner.clone()) + } + ResponsePayload::ExecutionOutputPage(inner) => { + generated_protocol::ResponsePayload::ExecutionOutputPageResponse(inner.clone()) + } }) } @@ -917,6 +1124,33 @@ fn from_generated_response_payload( generated_protocol::ResponsePayload::ProvidedCommandsResponse(inner) => { ResponsePayload::ProvidedCommands(inner) } + generated_protocol::ResponsePayload::ExecutionAcceptedResponse(inner) => { + ResponsePayload::ExecutionAccepted(inner) + } + generated_protocol::ResponsePayload::ExecutionCompletedResponse(inner) => { + ResponsePayload::ExecutionCompleted(inner) + } + generated_protocol::ResponsePayload::ExecutionEvaluationResponse(inner) => { + ResponsePayload::ExecutionEvaluation(inner) + } + generated_protocol::ResponsePayload::TypeScriptCheckResponse(inner) => { + ResponsePayload::TypeScriptCheck(inner) + } + generated_protocol::ResponsePayload::ExecutionDescriptorResponse(inner) => { + ResponsePayload::ExecutionDescriptor(inner) + } + generated_protocol::ResponsePayload::ExecutionListResponse(inner) => { + ResponsePayload::ExecutionList(inner) + } + generated_protocol::ResponsePayload::ExecutionDeletedResponse(inner) => { + ResponsePayload::ExecutionDeleted(inner) + } + generated_protocol::ResponsePayload::ExecutionIoResponse(inner) => { + ResponsePayload::ExecutionIo(inner) + } + generated_protocol::ResponsePayload::ExecutionOutputPageResponse(inner) => { + ResponsePayload::ExecutionOutputPage(inner) + } }) } @@ -943,6 +1177,12 @@ fn to_generated_event_payload(payload: &EventPayload) -> generated_protocol::Eve EventPayload::Ext(inner) => { generated_protocol::EventPayload::ExtEnvelope(to_generated_ext_envelope(inner)) } + EventPayload::ExecutionOutput(inner) => { + generated_protocol::EventPayload::ExecutionOutputEvent(inner.clone()) + } + EventPayload::ExecutionCompleted(inner) => { + generated_protocol::EventPayload::ExecutionCompletedEvent(inner.clone()) + } } } @@ -967,6 +1207,12 @@ fn from_generated_event_payload(payload: generated_protocol::EventPayload) -> Ev generated_protocol::EventPayload::ExtEnvelope(inner) => { EventPayload::Ext(from_generated_ext_envelope(inner)) } + generated_protocol::EventPayload::ExecutionOutputEvent(inner) => { + EventPayload::ExecutionOutput(inner) + } + generated_protocol::EventPayload::ExecutionCompletedEvent(inner) => { + EventPayload::ExecutionCompleted(inner) + } } } @@ -1290,6 +1536,36 @@ pub enum RequestPayload { GetResourceSnapshot(GetResourceSnapshotRequest), LinkPackage(LinkPackageRequest), ProvidedCommands(ProvidedCommandsRequest), + ShellExecution(ShellExecutionRequest), + ArgvExecution(ArgvExecutionRequest), + JavaScriptExecution(JavaScriptExecutionRequest), + JavaScriptEvaluation(JavaScriptEvaluationRequest), + JavaScriptFileExecution(JavaScriptFileExecutionRequest), + TypeScriptExecution(TypeScriptExecutionRequest), + TypeScriptEvaluation(TypeScriptEvaluationRequest), + TypeScriptFileExecution(TypeScriptFileExecutionRequest), + TypeScriptCheck(TypeScriptCheckRequest), + TypeScriptProjectCheck(TypeScriptProjectCheckRequest), + NpmProjectInstall(NpmProjectInstallRequest), + NpmPackageInstall(NpmPackageInstallRequest), + NpmScriptExecution(NpmScriptExecutionRequest), + NpmPackageExecution(NpmPackageExecutionRequest), + PythonExecution(PythonExecutionRequest), + PythonEvaluation(PythonEvaluationRequest), + PythonFileExecution(PythonFileExecutionRequest), + PythonModuleExecution(PythonModuleExecutionRequest), + PythonInstall(PythonInstallRequest), + GetExecution(GetExecutionRequest), + ListExecutions(ListExecutionsRequest), + WaitExecution(WaitExecutionRequest), + CancelExecution(CancelExecutionRequest), + SignalExecution(SignalExecutionRequest), + ResetExecution(ResetExecutionRequest), + DeleteExecution(DeleteExecutionRequest), + WriteExecutionStdin(WriteExecutionStdinRequest), + CloseExecutionStdin(CloseExecutionStdinRequest), + ResizeExecutionPty(ResizeExecutionPtyRequest), + ReadExecutionOutput(ReadExecutionOutputRequest), } #[derive(Debug, Clone, PartialEq, Eq)] @@ -1330,6 +1606,15 @@ pub enum ResponsePayload { ResourceSnapshot(ResourceSnapshotResponse), PackageLinked(PackageLinkedResponse), ProvidedCommands(ProvidedCommandsResponse), + ExecutionAccepted(ExecutionAcceptedResponse), + ExecutionCompleted(ExecutionCompletedResponse), + ExecutionEvaluation(ExecutionEvaluationResponse), + TypeScriptCheck(TypeScriptCheckResponse), + ExecutionDescriptor(ExecutionDescriptorResponse), + ExecutionList(ExecutionListResponse), + ExecutionDeleted(ExecutionDeletedResponse), + ExecutionIo(ExecutionIoResponse), + ExecutionOutputPage(ExecutionOutputPageResponse), } #[derive(Debug, Clone, PartialEq, Eq)] @@ -1353,6 +1638,8 @@ pub enum EventPayload { ProcessExited(ProcessExitedEvent), Structured(StructuredEvent), Ext(ExtEnvelope), + ExecutionOutput(ExecutionOutputEvent), + ExecutionCompleted(ExecutionCompletedEvent), } pub type SidecarPlacement = crate::wire::SidecarPlacement; @@ -1466,6 +1753,46 @@ pub type WasmPermissionTier = crate::wire::WasmPermissionTier; pub type ExecuteRequest = crate::wire::ExecuteRequest; +pub type ExecutionState = crate::wire::ExecutionState; +pub type ExecutionOutcome = crate::wire::ExecutionOutcome; +pub type RetainedExecutionLanguage = crate::wire::RetainedExecutionLanguage; +pub type ExecutionStreamChannel = crate::wire::ExecutionStreamChannel; +pub type JavaScriptModuleFormat = crate::wire::JavaScriptModuleFormat; +pub type ExecutionIdentityOptions = crate::wire::ExecutionIdentityOptions; +pub type ExecutionPtyOptions = crate::wire::ExecutionPtyOptions; +pub type ProcessExecutionOptions = crate::wire::ProcessExecutionOptions; +pub type ShellExecutionRequest = crate::wire::ShellExecutionRequest; +pub type ArgvExecutionRequest = crate::wire::ArgvExecutionRequest; +pub type JavaScriptExecutionRequest = crate::wire::JavaScriptExecutionRequest; +pub type JavaScriptEvaluationRequest = crate::wire::JavaScriptEvaluationRequest; +pub type JavaScriptFileExecutionRequest = crate::wire::JavaScriptFileExecutionRequest; +pub type TypeScriptExecutionRequest = crate::wire::TypeScriptExecutionRequest; +pub type TypeScriptEvaluationRequest = crate::wire::TypeScriptEvaluationRequest; +pub type TypeScriptFileExecutionRequest = crate::wire::TypeScriptFileExecutionRequest; +pub type TypeScriptCheckRequest = crate::wire::TypeScriptCheckRequest; +pub type TypeScriptProjectCheckRequest = crate::wire::TypeScriptProjectCheckRequest; +pub type NpmProjectInstallRequest = crate::wire::NpmProjectInstallRequest; +pub type NpmPackageInstallRequest = crate::wire::NpmPackageInstallRequest; +pub type NpmScriptExecutionRequest = crate::wire::NpmScriptExecutionRequest; +pub type NpmPackageExecutionRequest = crate::wire::NpmPackageExecutionRequest; +pub type PythonExecutionRequest = crate::wire::PythonExecutionRequest; +pub type PythonEvaluationRequest = crate::wire::PythonEvaluationRequest; +pub type PythonFileExecutionRequest = crate::wire::PythonFileExecutionRequest; +pub type PythonModuleExecutionRequest = crate::wire::PythonModuleExecutionRequest; +pub type PythonInstallRequest = crate::wire::PythonInstallRequest; +pub type GetExecutionRequest = crate::wire::GetExecutionRequest; +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +pub struct ListExecutionsRequest {} +pub type WaitExecutionRequest = crate::wire::WaitExecutionRequest; +pub type CancelExecutionRequest = crate::wire::CancelExecutionRequest; +pub type SignalExecutionRequest = crate::wire::SignalExecutionRequest; +pub type ResetExecutionRequest = crate::wire::ResetExecutionRequest; +pub type DeleteExecutionRequest = crate::wire::DeleteExecutionRequest; +pub type WriteExecutionStdinRequest = crate::wire::WriteExecutionStdinRequest; +pub type CloseExecutionStdinRequest = crate::wire::CloseExecutionStdinRequest; +pub type ResizeExecutionPtyRequest = crate::wire::ResizeExecutionPtyRequest; +pub type ReadExecutionOutputRequest = crate::wire::ReadExecutionOutputRequest; + pub type WriteStdinRequest = crate::wire::WriteStdinRequest; pub type CloseStdinRequest = crate::wire::CloseStdinRequest; @@ -1564,6 +1891,20 @@ pub type ListenerSnapshotResponse = crate::wire::ListenerSnapshotResponse; pub type BoundUdpSnapshotResponse = crate::wire::BoundUdpSnapshotResponse; pub type VmFetchResponse = crate::wire::VmFetchResponse; +pub type ExecutionDescriptor = crate::wire::ExecutionDescriptor; +pub type ExecutionErrorData = crate::wire::ExecutionErrorData; +pub type ExecutionAcceptedResponse = crate::wire::ExecutionAcceptedResponse; +pub type ExecutionCompletedResponse = crate::wire::ExecutionCompletedResponse; +pub type ExecutionEvaluationResponse = crate::wire::ExecutionEvaluationResponse; +pub type TypeScriptDiagnostic = crate::wire::TypeScriptDiagnostic; +pub type TypeScriptCheckResponse = crate::wire::TypeScriptCheckResponse; +pub type ExecutionDescriptorResponse = crate::wire::ExecutionDescriptorResponse; +pub type ExecutionListResponse = crate::wire::ExecutionListResponse; +pub type ExecutionDeletedResponse = crate::wire::ExecutionDeletedResponse; +pub type ExecutionIoResponse = crate::wire::ExecutionIoResponse; +pub type ExecutionOutputEvent = crate::wire::ExecutionOutputEvent; +pub type ExecutionOutputPageResponse = crate::wire::ExecutionOutputPageResponse; +pub type ExecutionCompletedEvent = crate::wire::ExecutionCompletedEvent; pub type SignalDispositionAction = crate::wire::SignalDispositionAction; @@ -1648,6 +1989,36 @@ impl_bare_newtype_union_enum!( LinkPackage(LinkPackageRequest) = 31, ProvidedCommands(ProvidedCommandsRequest) = 32, ListMounts(ListMountsRequest) = 33, + ShellExecution(ShellExecutionRequest) = 34, + ArgvExecution(ArgvExecutionRequest) = 35, + JavaScriptExecution(JavaScriptExecutionRequest) = 36, + JavaScriptEvaluation(JavaScriptEvaluationRequest) = 37, + JavaScriptFileExecution(JavaScriptFileExecutionRequest) = 38, + TypeScriptExecution(TypeScriptExecutionRequest) = 39, + TypeScriptEvaluation(TypeScriptEvaluationRequest) = 40, + TypeScriptFileExecution(TypeScriptFileExecutionRequest) = 41, + TypeScriptCheck(TypeScriptCheckRequest) = 42, + TypeScriptProjectCheck(TypeScriptProjectCheckRequest) = 43, + NpmProjectInstall(NpmProjectInstallRequest) = 44, + NpmPackageInstall(NpmPackageInstallRequest) = 45, + NpmScriptExecution(NpmScriptExecutionRequest) = 46, + NpmPackageExecution(NpmPackageExecutionRequest) = 47, + PythonExecution(PythonExecutionRequest) = 48, + PythonEvaluation(PythonEvaluationRequest) = 49, + PythonFileExecution(PythonFileExecutionRequest) = 50, + PythonModuleExecution(PythonModuleExecutionRequest) = 51, + PythonInstall(PythonInstallRequest) = 52, + GetExecution(GetExecutionRequest) = 53, + ListExecutions(ListExecutionsRequest) = 54, + WaitExecution(WaitExecutionRequest) = 55, + CancelExecution(CancelExecutionRequest) = 56, + SignalExecution(SignalExecutionRequest) = 57, + ResetExecution(ResetExecutionRequest) = 58, + DeleteExecution(DeleteExecutionRequest) = 59, + WriteExecutionStdin(WriteExecutionStdinRequest) = 60, + CloseExecutionStdin(CloseExecutionStdinRequest) = 61, + ResizeExecutionPty(ResizeExecutionPtyRequest) = 62, + ReadExecutionOutput(ReadExecutionOutputRequest) = 63, } ); @@ -1692,6 +2063,15 @@ impl_bare_newtype_union_enum!( PackageLinked(PackageLinkedResponse) = 33, ProvidedCommands(ProvidedCommandsResponse) = 34, MountsListed(ListMountsResponse) = 35, + ExecutionAccepted(ExecutionAcceptedResponse) = 36, + ExecutionCompleted(ExecutionCompletedResponse) = 37, + ExecutionEvaluation(ExecutionEvaluationResponse) = 38, + TypeScriptCheck(TypeScriptCheckResponse) = 39, + ExecutionDescriptor(ExecutionDescriptorResponse) = 40, + ExecutionList(ExecutionListResponse) = 41, + ExecutionDeleted(ExecutionDeletedResponse) = 42, + ExecutionIo(ExecutionIoResponse) = 43, + ExecutionOutputPage(ExecutionOutputPageResponse) = 44, } ); @@ -1728,6 +2108,8 @@ impl_bare_newtype_union_enum!( ProcessExited(ProcessExitedEvent) = 2, Structured(StructuredEvent) = 3, Ext(ExtEnvelope) = 4, + ExecutionOutput(ExecutionOutputEvent) = 5, + ExecutionCompleted(ExecutionCompletedEvent) = 6, } ); @@ -2274,6 +2656,15 @@ enum ExpectedResponseKind { PackageLinked, ProvidedCommands, MountsListed, + ExecutionOperation, + ExecutionCompleted, + ExecutionEvaluation, + TypeScriptCheck, + ExecutionDescriptor, + ExecutionList, + ExecutionDeleted, + ExecutionIo, + ExecutionOutputPage, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -2321,12 +2712,26 @@ impl ExpectedResponseKind { Self::PackageLinked => "package_linked", Self::ProvidedCommands => "provided_commands_response", Self::MountsListed => "mounts_listed", + Self::ExecutionOperation => "execution_operation", + Self::ExecutionCompleted => "execution_completed", + Self::ExecutionEvaluation => "execution_evaluation", + Self::TypeScriptCheck => "type_script_check", + Self::ExecutionDescriptor => "execution_descriptor", + Self::ExecutionList => "execution_list", + Self::ExecutionDeleted => "execution_deleted", + Self::ExecutionIo => "execution_io", + Self::ExecutionOutputPage => "execution_output_page", } } fn matches(self, payload: &ResponsePayload) -> bool { match payload { ResponsePayload::Rejected(_) => true, + ResponsePayload::ExecutionAccepted(_) | ResponsePayload::ExecutionCompleted(_) + if self == Self::ExecutionOperation => + { + true + } _ => payload.kind_name() == self.as_str(), } } @@ -2380,6 +2785,36 @@ impl RequestPayload { | Self::ResizePty(_) | Self::LinkPackage(_) | Self::ProvidedCommands(_) + | Self::ShellExecution(_) + | Self::ArgvExecution(_) + | Self::JavaScriptExecution(_) + | Self::JavaScriptEvaluation(_) + | Self::JavaScriptFileExecution(_) + | Self::TypeScriptExecution(_) + | Self::TypeScriptEvaluation(_) + | Self::TypeScriptFileExecution(_) + | Self::TypeScriptCheck(_) + | Self::TypeScriptProjectCheck(_) + | Self::NpmProjectInstall(_) + | Self::NpmPackageInstall(_) + | Self::NpmScriptExecution(_) + | Self::NpmPackageExecution(_) + | Self::PythonExecution(_) + | Self::PythonEvaluation(_) + | Self::PythonFileExecution(_) + | Self::PythonModuleExecution(_) + | Self::PythonInstall(_) + | Self::GetExecution(_) + | Self::ListExecutions(_) + | Self::WaitExecution(_) + | Self::CancelExecution(_) + | Self::SignalExecution(_) + | Self::ResetExecution(_) + | Self::DeleteExecution(_) + | Self::WriteExecutionStdin(_) + | Self::CloseExecutionStdin(_) + | Self::ResizeExecutionPty(_) + | Self::ReadExecutionOutput(_) | Self::HostFilesystemCall(_) => OwnershipRequirement::Vm, Self::Ext(_) => OwnershipRequirement::Any, } @@ -2421,6 +2856,37 @@ impl RequestPayload { Self::ResizePty(_) => ExpectedResponseKind::PtyResized, Self::LinkPackage(_) => ExpectedResponseKind::PackageLinked, Self::ProvidedCommands(_) => ExpectedResponseKind::ProvidedCommands, + Self::ShellExecution(_) + | Self::ArgvExecution(_) + | Self::JavaScriptExecution(_) + | Self::JavaScriptFileExecution(_) + | Self::TypeScriptExecution(_) + | Self::TypeScriptFileExecution(_) + | Self::NpmProjectInstall(_) + | Self::NpmPackageInstall(_) + | Self::NpmScriptExecution(_) + | Self::NpmPackageExecution(_) + | Self::PythonExecution(_) + | Self::PythonFileExecution(_) + | Self::PythonModuleExecution(_) + | Self::PythonInstall(_) => ExpectedResponseKind::ExecutionOperation, + Self::JavaScriptEvaluation(_) + | Self::TypeScriptEvaluation(_) + | Self::PythonEvaluation(_) => ExpectedResponseKind::ExecutionEvaluation, + Self::TypeScriptCheck(_) | Self::TypeScriptProjectCheck(_) => { + ExpectedResponseKind::TypeScriptCheck + } + Self::GetExecution(_) + | Self::CancelExecution(_) + | Self::SignalExecution(_) + | Self::ResetExecution(_) => ExpectedResponseKind::ExecutionDescriptor, + Self::ListExecutions(_) => ExpectedResponseKind::ExecutionList, + Self::WaitExecution(_) => ExpectedResponseKind::ExecutionCompleted, + Self::DeleteExecution(_) => ExpectedResponseKind::ExecutionDeleted, + Self::WriteExecutionStdin(_) + | Self::CloseExecutionStdin(_) + | Self::ResizeExecutionPty(_) => ExpectedResponseKind::ExecutionIo, + Self::ReadExecutionOutput(_) => ExpectedResponseKind::ExecutionOutputPage, } } } @@ -2475,7 +2941,16 @@ impl ResponsePayload { | Self::GuestKernelResult(_) | Self::PtyResized(_) | Self::PackageLinked(_) - | Self::ProvidedCommands(_) => OwnershipRequirement::Vm, + | Self::ProvidedCommands(_) + | Self::ExecutionAccepted(_) + | Self::ExecutionCompleted(_) + | Self::ExecutionEvaluation(_) + | Self::TypeScriptCheck(_) + | Self::ExecutionDescriptor(_) + | Self::ExecutionList(_) + | Self::ExecutionDeleted(_) + | Self::ExecutionIo(_) + | Self::ExecutionOutputPage(_) => OwnershipRequirement::Vm, Self::ExtResult(_) => OwnershipRequirement::Any, } } @@ -2518,6 +2993,15 @@ impl ResponsePayload { Self::PtyResized(_) => "pty_resized", Self::PackageLinked(_) => "package_linked", Self::ProvidedCommands(_) => "provided_commands_response", + Self::ExecutionAccepted(_) => "execution_accepted", + Self::ExecutionCompleted(_) => "execution_completed", + Self::ExecutionEvaluation(_) => "execution_evaluation", + Self::TypeScriptCheck(_) => "type_script_check", + Self::ExecutionDescriptor(_) => "execution_descriptor", + Self::ExecutionList(_) => "execution_list", + Self::ExecutionDeleted(_) => "execution_deleted", + Self::ExecutionIo(_) => "execution_io", + Self::ExecutionOutputPage(_) => "execution_output_page", } } } @@ -2540,9 +3024,11 @@ impl EventPayload { fn ownership_requirement(&self) -> OwnershipRequirement { match self { Self::Structured(_) => OwnershipRequirement::SessionOrVm, - Self::VmLifecycle(_) | Self::ProcessOutput(_) | Self::ProcessExited(_) => { - OwnershipRequirement::Vm - } + Self::VmLifecycle(_) + | Self::ProcessOutput(_) + | Self::ProcessExited(_) + | Self::ExecutionOutput(_) + | Self::ExecutionCompleted(_) => OwnershipRequirement::Vm, Self::Ext(_) => OwnershipRequirement::Any, } } diff --git a/crates/sidecar-protocol/src/wire.rs b/crates/sidecar-protocol/src/wire.rs index 61e2620560..fb0394e8ad 100644 --- a/crates/sidecar-protocol/src/wire.rs +++ b/crates/sidecar-protocol/src/wire.rs @@ -1,4 +1,4 @@ -//! Generated Secure Exec sidecar wire protocol surface. +//! Generated AgentOS language execution sidecar wire protocol surface. //! //! This module is the public generated protocol entrypoint. The hand-written //! `protocol` module remains an internal compatibility layer while callers move diff --git a/crates/v8-runtime/Cargo.toml b/crates/v8-runtime/Cargo.toml index 08e10dfee2..7d592de2ee 100644 --- a/crates/v8-runtime/Cargo.toml +++ b/crates/v8-runtime/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "V8 isolate runtime for secure-exec guest JavaScript execution" +description = "V8 isolate runtime for agentos guest JavaScript execution" [features] test-support = [] diff --git a/crates/v8-runtime/npm/.gitignore b/crates/v8-runtime/npm/.gitignore index c37406f79d..d460955880 100644 --- a/crates/v8-runtime/npm/.gitignore +++ b/crates/v8-runtime/npm/.gitignore @@ -1,3 +1,3 @@ # Platform binaries are placed here by CI, not committed -*/secure-exec-v8 -*/secure-exec-v8.exe +*/agentos-v8 +*/agentos-v8.exe diff --git a/crates/v8-runtime/npm/linux-x64-gnu/README.md b/crates/v8-runtime/npm/linux-x64-gnu/README.md index 50fa0499ff..ca07d3d011 100644 --- a/crates/v8-runtime/npm/linux-x64-gnu/README.md +++ b/crates/v8-runtime/npm/linux-x64-gnu/README.md @@ -4,6 +4,6 @@ Linux x64 (glibc) binary for @rivet-dev/agentos-v8-runtime. This package is installed automatically by `@rivet-dev/agentos-v8-runtime` as a platform-specific optional dependency. -- Website: https://secureexec.dev -- Docs: https://secureexec.dev/docs -- GitHub: https://github.com/rivet-dev/secure-exec +- Website: https://agentos.dev +- Docs: https://agentos.dev/docs +- GitHub: https://github.com/rivet-dev/agentos diff --git a/crates/v8-runtime/src/bridge.rs b/crates/v8-runtime/src/bridge.rs index 9ec869c662..2f46e12228 100644 --- a/crates/v8-runtime/src/bridge.rs +++ b/crates/v8-runtime/src/bridge.rs @@ -2319,7 +2319,7 @@ mod tests { } #[test] - fn bridge_error_code_accepts_trusted_secure_exec_prefixes() { + fn bridge_error_code_accepts_trusted_agentos_prefixes() { assert_eq!( bridge_error_code("ERR_AGENTOS_NODE_SYNC_RPC: EACCES: permission denied on /foo"), Some("EACCES") diff --git a/crates/v8-runtime/src/embedded_runtime.rs b/crates/v8-runtime/src/embedded_runtime.rs index 96e0178151..aa83a3de23 100644 --- a/crates/v8-runtime/src/embedded_runtime.rs +++ b/crates/v8-runtime/src/embedded_runtime.rs @@ -594,7 +594,7 @@ impl EmbeddedV8SessionHandle { } fn validate_execute_mode(mode: u8) -> io::Result<()> { - if mode > 1 { + if mode > 3 { return Err(io::Error::new( io::ErrorKind::InvalidInput, format!("unknown Execute mode: {mode}"), diff --git a/crates/v8-runtime/src/execution.rs b/crates/v8-runtime/src/execution.rs index 24c1c03f8c..299d72129a 100644 --- a/crates/v8-runtime/src/execution.rs +++ b/crates/v8-runtime/src/execution.rs @@ -116,7 +116,7 @@ pub fn install_high_resolution_time_global(scope: &mut v8::HandleScope, origin: let Some(func) = template.get_function(scope) else { return; }; - let key = v8::String::new(scope, "__secureExecHrNowUs").unwrap(); + let key = v8::String::new(scope, "__agentOsHrNowUs").unwrap(); let attr = v8::PropertyAttribute::READ_ONLY | v8::PropertyAttribute::DONT_DELETE; global.define_own_property(scope, key.into(), func.into(), attr); } @@ -128,7 +128,7 @@ pub fn install_require_esm_sync_global(scope: &mut v8::HandleScope) { let Some(function) = template.get_function(scope) else { return; }; - let key = v8::String::new(scope, "__secureExecRequireEsmSync").unwrap(); + let key = v8::String::new(scope, "__agentOsRequireEsmSync").unwrap(); let attributes = v8::PropertyAttribute::READ_ONLY | v8::PropertyAttribute::DONT_DELETE; global.define_own_property(scope, key.into(), function.into(), attributes); } diff --git a/crates/v8-runtime/src/runtime_protocol.rs b/crates/v8-runtime/src/runtime_protocol.rs index 3d71736716..58b79097d9 100644 --- a/crates/v8-runtime/src/runtime_protocol.rs +++ b/crates/v8-runtime/src/runtime_protocol.rs @@ -208,7 +208,7 @@ impl TryFrom for RuntimeCommand { high_resolution_time, user_code, } => { - if mode > 1 { + if mode > 3 { return Err(io::Error::new( io::ErrorKind::InvalidInput, format!("unknown Execute mode: {mode}"), @@ -352,7 +352,7 @@ mod tests { fn rejects_unknown_execute_mode() { let err = RuntimeCommand::try_from(BinaryFrame::Execute { session_id: "s".into(), - mode: 2, + mode: 4, file_path: "/app/main.mjs".into(), bridge_code: String::new(), post_restore_script: String::new(), diff --git a/crates/v8-runtime/src/session.rs b/crates/v8-runtime/src/session.rs index 91ad64dd65..c5139ba709 100644 --- a/crates/v8-runtime/src/session.rs +++ b/crates/v8-runtime/src/session.rs @@ -3,7 +3,7 @@ #[cfg(not(test))] use std::collections::BTreeMap; use std::collections::{HashMap, HashSet}; -use std::sync::atomic::AtomicU64; +use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::{Arc, Condvar, Mutex, OnceLock}; use std::thread; use std::time::{Duration, Instant}; @@ -517,6 +517,7 @@ struct SessionAssignment { snapshot_cache: Arc, isolate_handle: SharedIsolateHandle, execution_abort: SharedExecutionAbort, + execution_active: Arc, pause_control: Arc, session_id: String, output_generation: Option, @@ -832,7 +833,7 @@ fn spawn_warm_worker( let worker_userland_code = userland_code.clone(); // AGENTOS_THREAD_SITE: bounded-v8-warm-worker let join_handle = match thread::Builder::new() - .name(String::from("secure-exec-v8-warm-worker")) + .name(String::from("agentos-v8-warm-worker")) .spawn(move || { let precreated = precreate_warm_isolate( snapshot_cache, @@ -934,7 +935,7 @@ fn precreate_warm_isolate( /// Normalize an opt-in CPU-time budget: `Some(0)` means "disabled" and folds to /// `None` so the CPU-budget watchdog is NOT armed. The runtime layer does not -/// invent a default here: secure-exec sidecar VM executions pass the typed +/// invent a default here: agentos sidecar VM executions pass the typed /// `limits.jsRuntime.cpuTimeLimitMs` default, while lower-level callers can pass /// `None`/`0` deliberately. fn normalize_cpu_time_limit_ms(cpu_time_limit_ms: Option) -> Option { @@ -1004,6 +1005,9 @@ struct SessionEntry { isolate_handle: SharedIsolateHandle, /// Current execution abort handle used to wake sync bridge waits. execution_abort: SharedExecutionAbort, + /// Set from Execute admission until that operation leaves the session + /// thread, including the startup window before an isolate handle exists. + execution_active: Arc, pause_control: Arc, /// Durable socket readiness and its dedicated capacity-one wake lane. ready_broker: Arc, @@ -1168,6 +1172,14 @@ impl Drop for ActiveExecutionAbort { } } +struct ExecutionActivityGuard(Arc); + +impl Drop for ExecutionActivityGuard { + fn drop(&mut self) { + self.0.store(false, Ordering::Release); + } +} + pub(crate) fn signal_execution_abort(shared: &SharedExecutionAbort, reason: ExecutionAbortReason) { let mut guard = shared.0.lock().unwrap(); if let Some(state) = guard.as_mut() { @@ -1406,6 +1418,7 @@ impl SessionManager { SessionReadiness::new(ready_generation, &session_runtime, ready_batch_handle_limit)?; let isolate_handle = Arc::new(Mutex::new(None)); let execution_abort = new_execution_abort(); + let execution_active = Arc::new(AtomicBool::new(false)); let pause_control = Arc::new(SessionPauseControl::default()); #[cfg(test)] let session_resources = Arc::clone(session_runtime.resources()); @@ -1424,6 +1437,7 @@ impl SessionManager { snapshot_cache: Arc::clone(&self.snapshot_cache), isolate_handle: Arc::clone(&isolate_handle), execution_abort: execution_abort.clone(), + execution_active: Arc::clone(&execution_active), pause_control: Arc::clone(&pause_control), session_id: session_id.clone(), output_generation, @@ -1474,6 +1488,7 @@ impl SessionManager { join_handle: Some(join_handle), isolate_handle, execution_abort, + execution_active, pause_control, ready_broker, #[cfg(test)] @@ -1751,7 +1766,7 @@ impl SessionManager { &self, session_id: &str, msg: &SessionMessage, - ) -> Result<(Sender, usize), String> { + ) -> Result<(Sender, usize, Arc), String> { let entry = self .sessions .get(session_id) @@ -1769,10 +1784,21 @@ impl SessionManager { } } if matches!(msg, SessionMessage::TerminateExecution) { - signal_execution_abort(&entry.execution_abort, ExecutionAbortReason::Terminated); + if entry.execution_active.load(Ordering::Acquire) { + signal_execution_abort_durable( + &entry.execution_abort, + ExecutionAbortReason::Terminated, + ); + } else { + signal_execution_abort(&entry.execution_abort, ExecutionAbortReason::Terminated); + } } - Ok((entry.tx.clone(), entry.command_capacity)) + Ok(( + entry.tx.clone(), + entry.command_capacity, + Arc::clone(&entry.execution_active), + )) } /// Admit an ordinary message without ever blocking the thread that also @@ -1780,6 +1806,7 @@ impl SessionManager { /// `publish_readiness`; ordinary events are never reclassified by name. pub fn try_send_to_session(&self, session_id: &str, msg: SessionMessage) -> Result<(), String> { let terminate_requested = matches!(&msg, SessionMessage::TerminateExecution); + let execute_requested = matches!(&msg, SessionMessage::Execute { .. }); let incoming_kind = match &msg { SessionMessage::InjectGlobals { .. } => String::from("inject_globals"), SessionMessage::Execute { .. } => String::from("execute"), @@ -1787,7 +1814,11 @@ impl SessionManager { SessionMessage::StreamEvent(event) => format!("stream_event:{}", event.event_type), SessionMessage::TerminateExecution => String::from("terminate_execution"), }; - let (sender, command_capacity) = self.session_command_sender(session_id, &msg)?; + let (sender, command_capacity, execution_active) = + self.session_command_sender(session_id, &msg)?; + if execute_requested { + execution_active.store(true, Ordering::Release); + } let command = SessionCommand::Message(msg); match sender.try_send(command) { @@ -1798,12 +1829,18 @@ impl SessionManager { Ok(()) } Err(crossbeam_channel::TrySendError::Full(_)) => { + if execute_requested { + execution_active.store(false, Ordering::Release); + } Err(format!( "ERR_AGENTOS_SESSION_COMMAND_LIMIT: session {session_id} command queue exceeded limit of {command_capacity} while admitting {incoming_kind} (queued={}); raise limits.reactor.maxHandleCommands", sender.len() )) } Err(crossbeam_channel::TrySendError::Disconnected(_)) => { + if execute_requested { + execution_active.store(false, Ordering::Release); + } Err(format!( "session thread disconnected for session {session_id}" )) @@ -2205,6 +2242,7 @@ fn session_thread( snapshot_cache, isolate_handle, execution_abort, + execution_active, pause_control, session_id, output_generation, @@ -2341,6 +2379,7 @@ fn session_thread( user_code, wasm_module_bytes, } => { + let _execution_activity = ExecutionActivityGuard(Arc::clone(&execution_active)); // `userland_code` is consumed only by the non-test snapshot // path below; keep it bound (without a warning) under `test`. #[cfg(test)] @@ -2490,11 +2529,19 @@ fn session_thread( let iso = v8_isolate.as_mut().unwrap(); iso.cancel_terminate_execution(); - // Create execution context: Context::new on a snapshot-restored - // isolate gives a fresh clone of the snapshot's default context - // (bridge IIFE already executed, all infrastructure set up). - // On a non-snapshot isolate, this gives a blank context. - let exec_context = isolate::create_context(iso); + // Language executions set bit 1 to reuse the session's + // process-lifetime context. Normal process executions keep + // receiving a fresh context for every Execute message. + let retain_context = mode & 2 != 0; + let module_mode = mode & 1 != 0; + let exec_context = if retain_context { + _v8_context + .as_ref() + .expect("session context exists after isolate creation") + .clone() + } else { + isolate::create_context(iso) + }; if high_resolution_time { let scope = &mut v8::HandleScope::new(iso); @@ -2538,6 +2585,28 @@ fn session_thread( // terminate requests can unblock sync bridge waits. let (_active_execution_abort, abort_rx) = ActiveExecutionAbort::arm(&execution_abort); + if execution_abort_requested(&abort_rx) { + // Termination may arrive after Execute admission but + // before isolate startup completes. Finish without + // entering guest code; there is no running isolate + // frame for terminate_execution() to interrupt yet. + send_event_with_generation( + &event_tx, + output_generation, + RuntimeEvent::ExecutionResult { + session_id, + exit_code: 1, + exports: None, + error: Some(ExecutionErrorBin { + error_type: String::from("Error"), + message: String::from("Execution terminated"), + stack: String::new(), + code: String::new(), + }), + }, + ); + continue; + } // Async completions have a dedicated bounded lane. // Synchronous calls register their own capacity-one @@ -2776,7 +2845,7 @@ fn session_thread( Some(file_path.as_str()) }; let phase_start = Instant::now(); - let (mut code, mut exports, mut error) = if mode == 0 { + let (mut code, mut exports, mut error) = if !module_mode { let scope = &mut v8::HandleScope::new(iso); let ctx = v8::Local::new(scope, &exec_context); let scope = &mut v8::ContextScope::new(scope, ctx); @@ -2806,7 +2875,7 @@ fn session_thread( // Re-check async ESM completion once immediately so // pure-microtask top-level await settles without // needing a bridge event-loop round-trip. - if mode != 0 && error.is_none() { + if module_mode && error.is_none() { let scope = &mut v8::HandleScope::new(iso); let ctx = v8::Local::new(scope, &exec_context); let scope = &mut v8::ContextScope::new(scope, ctx); @@ -2858,7 +2927,7 @@ fn session_thread( // Finalize any entry-module top-level await that was // waiting on bridge-driven async work (timers/network). - if !terminated && mode != 0 && error.is_none() { + if !terminated && module_mode && error.is_none() { let scope = &mut v8::HandleScope::new(iso); let ctx = v8::Local::new(scope, &exec_context); let scope = &mut v8::ContextScope::new(scope, ctx); @@ -2947,7 +3016,7 @@ fn session_thread( } } - if !terminated && mode == 0 && error.is_none() { + if !terminated && !module_mode && error.is_none() { let scope = &mut v8::HandleScope::new(iso); let ctx = v8::Local::new(scope, &exec_context); let scope = &mut v8::ContextScope::new(scope, ctx); @@ -4232,6 +4301,7 @@ mod tests { join_handle: Some(join_handle), isolate_handle: Arc::new(Mutex::new(None)), execution_abort: new_execution_abort(), + execution_active: Arc::new(AtomicBool::new(false)), pause_control: Arc::new(SessionPauseControl::default()), ready_broker, session_resources, diff --git a/crates/v8-runtime/src/snapshot.rs b/crates/v8-runtime/src/snapshot.rs index 2df4e3b4eb..bafe92aa17 100644 --- a/crates/v8-runtime/src/snapshot.rs +++ b/crates/v8-runtime/src/snapshot.rs @@ -87,9 +87,9 @@ const SNAPSHOT_USERLAND_PREP: &str = r#" // snapshot eval; it also works post-restore (resolution flows through the real // bridge fns swapped in after restore). if (typeof globalThis.require === "undefined" && - typeof globalThis.__secureExecGuestCreateRequire === "function") { + typeof globalThis.__agentOsGuestCreateRequire === "function") { try { - globalThis.require = globalThis.__secureExecGuestCreateRequire("/root/index.js"); + globalThis.require = globalThis.__agentOsGuestCreateRequire("/root/index.js"); } catch (e) {} } // `process.versions` is a bridge-backed lazy getter: it derives `.node` from the diff --git a/crates/v8-runtime/src/stream.rs b/crates/v8-runtime/src/stream.rs index 596e034f7c..aeffefbfda 100644 --- a/crates/v8-runtime/src/stream.rs +++ b/crates/v8-runtime/src/stream.rs @@ -10,7 +10,7 @@ /// - "http2" → _http2Dispatch /// - "stdin", "stdin_end" → _stdinDispatch /// - "net_socket" → _netSocketDispatch -/// - "signal" → __secureExecWasmSignalDispatch or _signalDispatch +/// - "signal" → __agentOsWasmSignalDispatch or _signalDispatch /// - "timer" → _timerDispatch pub fn dispatch_stream_event(scope: &mut v8::HandleScope, event_type: &str, payload: &[u8]) { // Look up the dispatch function on the global object @@ -23,7 +23,7 @@ pub fn dispatch_stream_event(scope: &mut v8::HandleScope, event_type: &str, payl "http2" => &["_http2Dispatch"], "stdin" | "stdin_end" => &["_stdinDispatch"], "net_socket" => &["_netSocketDispatch"], - "signal" => &["__secureExecWasmSignalDispatch", "_signalDispatch"], + "signal" => &["__agentOsWasmSignalDispatch", "_signalDispatch"], "timer" => &["_timerDispatch"], _ => return, // Unknown event type — ignore }; @@ -94,7 +94,7 @@ fn dispatch_stream_value( let context = scope.get_current_context(); let global = context.global(scope); let dispatch_names: &[&str] = match event_type { - "signal" => &["__secureExecWasmSignalDispatch", "_signalDispatch"], + "signal" => &["__agentOsWasmSignalDispatch", "_signalDispatch"], "timer" => &["_timerDispatch"], _ => return, }; diff --git a/crates/v8-runtime/src/timeout.rs b/crates/v8-runtime/src/timeout.rs index ebacaee9d7..7e25814a1a 100644 --- a/crates/v8-runtime/src/timeout.rs +++ b/crates/v8-runtime/src/timeout.rs @@ -15,7 +15,7 @@ // EXCLUDES idle/await. V8 has no native budget primitive, so this poll + // `terminate_execution()` approach is the standard embedder pattern. Armed // when the caller passes a nonzero `limits.jsRuntime.cpuTimeLimitMs`. -// secure-exec sidecar VM executions supply a bounded default; lower-level +// agentos sidecar VM executions supply a bounded default; lower-level // embedders may pass `None`/`0` to leave the guard disabled. // // The two guards are independent: setting one typed limit arms only that guard, diff --git a/crates/vfs-store/CLAUDE.md b/crates/vfs-store/CLAUDE.md index 4d830a1f02..9808ec0129 100644 --- a/crates/vfs-store/CLAUDE.md +++ b/crates/vfs-store/CLAUDE.md @@ -1,5 +1,5 @@ # agentos-vfs -- `agentos-vfs` contains concrete backend adapters for secure-exec deployments: S3, host-disk metadata/block stores, and bridge/callback-backed stores. +- `agentos-vfs` contains concrete backend adapters for agentos deployments: S3, host-disk metadata/block stores, and bridge/callback-backed stores. - Keep policy decisions, trusted configuration validation, mount descriptor parsing, and sidecar lifecycle wiring in the sidecar plugin layer. - Generic filesystem algorithms and in-memory stores belong in `vfs`. diff --git a/crates/vfs-store/Cargo.toml b/crates/vfs-store/Cargo.toml index 3252ceedd4..c277e334e8 100644 --- a/crates/vfs-store/Cargo.toml +++ b/crates/vfs-store/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Secure Exec virtual filesystem backends" +description = "AgentOS language execution virtual filesystem backends" [dependencies] async-trait = "0.1" diff --git a/crates/vfs-store/src/callback_store.rs b/crates/vfs-store/src/callback_store.rs index a3de96a573..674ba501bc 100644 --- a/crates/vfs-store/src/callback_store.rs +++ b/crates/vfs-store/src/callback_store.rs @@ -7,7 +7,7 @@ use vfs::engine::{ MetadataStore, SnapshotId, VfsError, VfsResult, }; -pub const VFS_METADATA_EXT_NAMESPACE: &str = "secure-exec.vfs.metadata.v1"; +pub const VFS_METADATA_EXT_NAMESPACE: &str = "agentos.vfs.metadata.v1"; const CALLBACK_METADATA_TIMEOUT: Duration = Duration::from_secs(30); pub trait CallbackMetadataClient: Clone + Send + Sync + 'static { diff --git a/crates/vfs/CLAUDE.md b/crates/vfs/CLAUDE.md index 4cccd1bb89..2a99a33d70 100644 --- a/crates/vfs/CLAUDE.md +++ b/crates/vfs/CLAUDE.md @@ -1,6 +1,6 @@ # vfs -- `vfs` is generic filesystem infrastructure only. Do not add secure-exec sidecar, bridge, S3, SQLite, host-disk, or registry coupling here. +- `vfs` is generic filesystem infrastructure only. Do not add agentos sidecar, bridge, S3, SQLite, host-disk, or registry coupling here. - The crate intentionally contains separate filesystem type universes under explicit modules while the consolidation is in progress. Do not glob-merge names that would confuse those boundaries. - Concrete environment-bound backends belong in `agentos-vfs`. - The `chunked` engine deliberately decouples the `MetadataStore` from the `BlockStore`: blocks are content-addressed, opaque, and self-describing only as a set, while the directory tree, inode table, chunk map, and refcounts live entirely in the metadata store. The engine makes **no self-containment promise** about either half. Pairing a block store with a metadata store, and ensuring the metadata store is durable and co-located with whatever lifecycle the blocks need, is the **caller's responsibility** (the sidecar plugin / client config that wires the backends), not the engine's. So e.g. an `S3BlockStore` backed by a local `SqliteMetadataStore` is a valid, intended configuration; the engine does not assume blocks carry enough information to reconstruct the tree, and "the metadata lives elsewhere than the blocks" is by design, not a defect. If a deployment needs the tree to survive loss of the local metadata, it must choose a durable metadata store (e.g. the callback backend) — that is a wiring decision, not an engine concern. diff --git a/crates/vfs/assets/base-filesystem.json b/crates/vfs/assets/base-filesystem.json index e641efddd3..bdb7b06ec7 100644 --- a/crates/vfs/assets/base-filesystem.json +++ b/crates/vfs/assets/base-filesystem.json @@ -5,8 +5,8 @@ "snapshotCreatedAt": "2026-06-22T19:45:20.529Z", "builtAt": "2026-06-23T03:47:12.644Z", "transforms": [ - "Normalize HOSTNAME to secure-exec", - "Preserve the captured user-level environment and filesystem layout as the secure-exec base layer", + "Normalize HOSTNAME to agentos", + "Preserve the captured user-level environment and filesystem layout as the agentos base layer", "Add the non-Alpine /workspace directory (default agent working directory) owned by the base user", "Restore Alpine 3.22's /etc/services database and add the VM's Docker-style /etc/hosts entries for libc lookup parity" ] @@ -15,7 +15,7 @@ "env": { "CHARSET": "UTF-8", "HOME": "/home/agentos", - "HOSTNAME": "secure-exec", + "HOSTNAME": "agentos", "LANG": "C.UTF-8", "LC_COLLATE": "C", "LOGNAME": "agentos", @@ -92,7 +92,7 @@ "mode": "644", "uid": 0, "gid": 0, - "content": "secure-exec\n" + "content": "agentos\n" }, { "path": "/etc/hosts", @@ -100,7 +100,7 @@ "mode": "644", "uid": 0, "gid": 0, - "content": "127.0.0.1 localhost localhost.localdomain\n::1 localhost localhost.localdomain ip6-localhost ip6-loopback\nfe00:: ip6-localnet\nff00:: ip6-mcastprefix\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n127.0.1.1 secure-exec\n" + "content": "127.0.0.1 localhost localhost.localdomain\n::1 localhost localhost.localdomain ip6-localhost ip6-loopback\nfe00:: ip6-localnet\nff00:: ip6-mcastprefix\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n127.0.1.1 agentos\n" }, { "path": "/etc/logrotate.d", diff --git a/crates/vfs/src/posix/overlay_fs.rs b/crates/vfs/src/posix/overlay_fs.rs index 362975cfbb..ed3e863c63 100644 --- a/crates/vfs/src/posix/overlay_fs.rs +++ b/crates/vfs/src/posix/overlay_fs.rs @@ -6,9 +6,9 @@ use base64::Engine; use std::collections::BTreeSet; const MAX_SNAPSHOT_DEPTH: usize = 1024; -const OVERLAY_METADATA_ROOT: &str = "/.secure-exec-overlay"; -const OVERLAY_WHITEOUT_DIR: &str = "/.secure-exec-overlay/whiteouts"; -const OVERLAY_OPAQUE_DIR: &str = "/.secure-exec-overlay/opaque"; +const OVERLAY_METADATA_ROOT: &str = "/.agentos-overlay"; +const OVERLAY_WHITEOUT_DIR: &str = "/.agentos-overlay/whiteouts"; +const OVERLAY_OPAQUE_DIR: &str = "/.agentos-overlay/opaque"; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum OverlayMode { @@ -304,7 +304,7 @@ impl OverlayFileSystem { /// /// The lexical [`is_internal_metadata_path`] check alone is bypassable: the /// underlying `MemoryFileSystem` follows symlinks, so a guest-created symlink - /// whose resolved target enters `/.secure-exec-overlay` (directly, or via a + /// whose resolved target enters `/.agentos-overlay` (directly, or via a /// symlink to an ancestor such as `/`) would slip past a purely lexical guard /// and let the guest read or tamper with whiteout/opaque markers (e.g. /// resurrecting a deleted lower-layer file). Resolving before the check @@ -334,7 +334,7 @@ impl OverlayFileSystem { } fn hidden_root_entry_name() -> &'static str { - ".secure-exec-overlay" + ".agentos-overlay" } fn should_hide_directory_entry(path: &str, entry: &str) -> bool { @@ -2165,7 +2165,7 @@ mod tests { // A guest symlink whose target is the metadata root must not become a // window into the reserved namespace. overlay - .symlink("/.secure-exec-overlay/whiteouts", "/escape") + .symlink("/.agentos-overlay/whiteouts", "/escape") .expect("creating the symlink itself is allowed"); // Listing through the symlink must be denied, not disclose markers. @@ -2191,7 +2191,7 @@ mod tests { .expect("symlink to root is allowed"); assert!( overlay - .read_dir("/rootlink/.secure-exec-overlay/whiteouts") + .read_dir("/rootlink/.agentos-overlay/whiteouts") .is_err(), "metadata must be unreachable via an ancestor symlink too" ); @@ -2257,9 +2257,7 @@ mod tests { Vec::::new() ); let root_entries = overlay.read_dir("/").expect("read root"); - assert!(!root_entries - .iter() - .any(|entry| entry == ".secure-exec-overlay")); + assert!(!root_entries.iter().any(|entry| entry == ".agentos-overlay")); } #[test] diff --git a/crates/vfs/src/posix/root_fs.rs b/crates/vfs/src/posix/root_fs.rs index 78c93523f4..a165a9ee54 100644 --- a/crates/vfs/src/posix/root_fs.rs +++ b/crates/vfs/src/posix/root_fs.rs @@ -12,12 +12,12 @@ use serde::Deserialize; use std::collections::BTreeSet; // The base filesystem fixture is staged into OUT_DIR by build.rs: copied from -// the canonical `packages/secure-exec-core/fixtures/base-filesystem.json` +// the canonical `packages/agentos-core/fixtures/base-filesystem.json` // during in-tree builds, or from the vendored `assets/base-filesystem.json` // copy bundled in the published crate. const BUNDLED_BASE_FILESYSTEM_JSON: &str = include_str!(concat!(env!("OUT_DIR"), "/base-filesystem.json")); -pub const ROOT_FILESYSTEM_SNAPSHOT_FORMAT: &str = "secure_exec_filesystem_snapshot_v1"; +pub const ROOT_FILESYSTEM_SNAPSHOT_FORMAT: &str = "agentos_filesystem_snapshot_v1"; const LEGACY_AGENTOS_ROOT_FILESYSTEM_SNAPSHOT_FORMAT: &str = "agentos_filesystem_snapshot_v1"; const ROOT_FILESYSTEM_SNAPSHOT_FIXED_OVERHEAD_BYTES: usize = 4 * 1024; const ROOT_FILESYSTEM_SNAPSHOT_ENTRY_OVERHEAD_BYTES: usize = MAX_PATH_LENGTH + 1024; diff --git a/crates/vfs/tests/package_format.rs b/crates/vfs/tests/package_format.rs index efadeea70e..31c670e774 100644 --- a/crates/vfs/tests/package_format.rs +++ b/crates/vfs/tests/package_format.rs @@ -97,7 +97,7 @@ fn package_format_rejects_unknown_schema_version_and_corrupt_headers() { #[test] fn tar_filesystem_rejects_unsorted_index() { - let path = unique_path("secure-exec-unsorted-aospkg"); + let path = unique_path("agentos-unsorted-aospkg"); let manifest = encode_package_manifest(v1::PackageManifest { name: String::from("unsorted"), version: String::from("1.0.0"), diff --git a/crates/vfs/tests/posix_root_fs.rs b/crates/vfs/tests/posix_root_fs.rs index 26af4db923..6bab39a9e3 100644 --- a/crates/vfs/tests/posix_root_fs.rs +++ b/crates/vfs/tests/posix_root_fs.rs @@ -304,7 +304,7 @@ fn root_filesystem_uses_bundled_base_and_round_trips_snapshots() { .any(|window| window == b"smtp\t\t25/tcp\t\tmail")); assert_eq!( root.read_file("/etc/hosts").expect("read bundled hosts file"), - b"127.0.0.1 localhost localhost.localdomain\n::1 localhost localhost.localdomain ip6-localhost ip6-loopback\nfe00:: ip6-localnet\nff00:: ip6-mcastprefix\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n127.0.1.1 secure-exec\n" + b"127.0.0.1 localhost localhost.localdomain\n::1 localhost localhost.localdomain ip6-localhost ip6-loopback\nfe00:: ip6-localnet\nff00:: ip6-mcastprefix\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n127.0.1.1 agentos\n" ); root.mkdir("/workspace", true).expect("create workspace"); @@ -503,7 +503,7 @@ fn snapshot_round_trip_preserves_file_type_bits_in_modes() { fn decode_snapshot_accepts_zero_mode_strings() { let decoded = decode_snapshot( br#"{ - "format": "secure_exec_filesystem_snapshot_v1", + "format": "agentos_filesystem_snapshot_v1", "filesystem": { "entries": [ { @@ -581,7 +581,7 @@ fn decode_snapshot_rejects_encoded_payloads_that_exceed_import_limits() { let error = decode_snapshot_with_import_limits( br#"{ - "format": "secure_exec_filesystem_snapshot_v1", + "format": "agentos_filesystem_snapshot_v1", "filesystem": { "entries": [] } }"#, &limits, @@ -601,7 +601,7 @@ fn decode_snapshot_rejects_entry_counts_that_exceed_import_limits() { let error = decode_snapshot_with_import_limits( br#"{ - "format": "secure_exec_filesystem_snapshot_v1", + "format": "agentos_filesystem_snapshot_v1", "filesystem": { "entries": [ { @@ -638,7 +638,7 @@ fn decode_snapshot_rejects_content_bytes_that_exceed_import_limits() { let error = decode_snapshot_with_import_limits( br#"{ - "format": "secure_exec_filesystem_snapshot_v1", + "format": "agentos_filesystem_snapshot_v1", "filesystem": { "entries": [ { @@ -665,7 +665,7 @@ fn decode_snapshot_allows_metadata_heavy_entries_within_import_limits() { let path = format!("/{}", "a".repeat(4000)); let snapshot = format!( r#"{{ - "format": "secure_exec_filesystem_snapshot_v1", + "format": "agentos_filesystem_snapshot_v1", "filesystem": {{ "entries": [ {{ diff --git a/crates/vfs/tests/posix_tar_fs.rs b/crates/vfs/tests/posix_tar_fs.rs index dc50551e23..daba597d75 100644 --- a/crates/vfs/tests/posix_tar_fs.rs +++ b/crates/vfs/tests/posix_tar_fs.rs @@ -101,7 +101,7 @@ fn tar_filesystem_cache_uses_file_identity_and_stable_guest_device() { assert_ne!(stat_a.dev, other_stat.dev); let same_bytes = std::fs::read(&tar_path).expect("read fixture tar"); - let copied_tar = unique_tar_path("secure-exec-tar-fs-copy"); + let copied_tar = unique_tar_path("agentos-tar-fs-copy"); std::fs::write(&copied_tar, same_bytes).expect("copy fixture tar bytes"); let fs_copy = TarFileSystem::open(&copied_tar).expect("open copied tar filesystem"); assert_ne!(fs_a.archive_ptr(), fs_copy.archive_ptr()); @@ -114,7 +114,7 @@ fn tar_filesystem_cache_uses_file_identity_and_stable_guest_device() { } fn write_fixture_tar() -> PathBuf { - let path = unique_tar_path("secure-exec-tar-fs-fixture"); + let path = unique_tar_path("agentos-tar-fs-fixture"); write_fixture_tar_at(path) } diff --git a/crates/vm-config/Cargo.toml b/crates/vm-config/Cargo.toml index bee108c954..733a8f3aac 100644 --- a/crates/vm-config/Cargo.toml +++ b/crates/vm-config/Cargo.toml @@ -4,7 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true -description = "Shared Secure Exec VM creation JSON config DTOs" +description = "Shared AgentOS language execution VM creation JSON config DTOs" [dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/docs-internal/kernel-runtime-subsystem-map.md b/docs-internal/kernel-runtime-subsystem-map.md index 40399736a1..5b8011f115 100644 --- a/docs-internal/kernel-runtime-subsystem-map.md +++ b/docs-internal/kernel-runtime-subsystem-map.md @@ -126,7 +126,7 @@ This is the baseline filesystem layer that everything else builds on. Relevant files: - `crates/kernel/src/vfs.rs` - `crates/kernel/src/root_fs.rs` -- `packages/secure-exec-core/fixtures/base-filesystem.json` +- `packages/agentos-core/fixtures/base-filesystem.json` - `crates/kernel/src/device_layer.rs` - `crates/kernel/src/overlay_fs.rs` - `crates/kernel/src/mount_table.rs` diff --git a/docs-internal/registry-flatten-colocation-spec.md b/docs-internal/registry-flatten-colocation-spec.md index b7a21b037f..227582cf5c 100644 --- a/docs-internal/registry-flatten-colocation-spec.md +++ b/docs-internal/registry-flatten-colocation-spec.md @@ -127,7 +127,7 @@ test-program fixtures stay in `toolchain/test-programs/` (not scattered into stub, or a hand-rolled CLI over a library. The only exception is a tool whose canonical upstream *is* the Rust project (`ripgrep`, `fd`). Several current commands violate this (coreutils=uutils, grep, curl driver, and the - `secureexec-*` rewrites) — tracked in `registry-parity-worklist.md` + `agentos-*` rewrites) — tracked in `registry-parity-worklist.md` Cross-cutting #0; new packages must not add more. ## What moves where @@ -325,7 +325,7 @@ Repo recipes orchestrate; they must not reimplement what the CLI does: | per-package `test` script + external authors | `agentos-toolchain test` | **Stays repo-specific** (not CLI, not overfit): `copy-wasm-commands` (vendor into -runtime-core), `verify-fixed-versions` (the 0.0.1 pin), `generate-secure-exec-mirror`, +runtime-core), `verify-fixed-versions` (the 0.0.1 pin), `generate-agentos-mirror`, registry-wide release orchestration, cross-repo dispatch, and the status reporter / coverage gate scoped to *our* registry. diff --git a/docs-internal/registry-parity-worklist.md b/docs-internal/registry-parity-worklist.md index e64c212335..deb88abcdf 100644 --- a/docs-internal/registry-parity-worklist.md +++ b/docs-internal/registry-parity-worklist.md @@ -85,7 +85,7 @@ fuel checkpoints that distinguish user CPU from user-plus-system CPU. **This is the highest-leverage item and reshapes several below.** Audit revealed that **most commands are NOT the real Linux tool** — they are custom Rust rewrites -(`secureexec-*` crates) or `uutils`, plus at least one hand-rolled C CLI (curl). +(`agentos-*` crates) or `uutils`, plus at least one hand-rolled C CLI (curl). Per the load-bearing rule, each must become the **real upstream tool** compiled to WASI and patched as needed. @@ -117,11 +117,11 @@ actual backing: | **wget** | DONE | our 174-line `wget.c` (dropped) | real GNU Wget vs our sysroot — stub `getrlimit`/`getgroups`, then build | | **http-get** | DONE | our 95-line `http_get.c` | dropped; real curl covers HTTP fetches | | **git** | DONE | our hand-rolled git from `sha1`+`flate2` | **real git** (upstream C), patched for WASI — **NOT gitoxide** | -| **fd** | DONE | our `secureexec-fd` on raw `regex` (not sharkdp/fd) | real **fd** (sharkdp) | +| **fd** | DONE | our `agentos-fd` on raw `regex` (not sharkdp/fd) | real **fd** (sharkdp) | | **findutils** (`find`,`xargs`) | DONE | our hand-rolled on `regex`/shims | replaced with `uutils/findutils` | | **tree** | DONE | our hand-rolled, zero deps | real `tree`, or an established one | -| **grep** | DONE | our `secureexec-grep` on raw `regex` (**not** an established grep pkg) | real **GNU grep** | -| **ripgrep** (`rg`) | DONE | our `secureexec-grep` recursive search shim, not real ripgrep | real upstream **ripgrep** | +| **grep** | DONE | our `agentos-grep` on raw `regex` (**not** an established grep pkg) | real **GNU grep** | +| **ripgrep** (`rg`) | DONE | our `agentos-grep` recursive search shim, not real ripgrep | real upstream **ripgrep** | | **zip** | DONE | our 203-line `zip.c` over zlib/minizip (not Info-ZIP) | real Info-ZIP, or an established lib's CLI | | **unzip** | DONE | our 669-line `unzip.c` over zlib/minizip | real Info-ZIP unzip | | **sqlite3 CLI** | DONE | our 558-line `sqlite3_cli.c` (engine is real SQLite; the shell is ours) | real SQLite `shell.c` (its official CLI) | @@ -244,7 +244,7 @@ works (`wasi-spawn` broker), so `xargs` is not a blocker. `2026-07-08T05-43-24-0700-http-get-clear-stale-generated-and-install.log`; cross-runtime network tests pass 11/11 with the WASM curl rows in `2026-07-08T05-47-43-0700-http-get-runtime-cross-network-test-pass.log`. -- **tree — DONE.** Replaced the custom Rust `secureexec-tree`/`cmd-tree` crates +- **tree — DONE.** Replaced the custom Rust `agentos-tree`/`cmd-tree` crates with upstream Steve Baker `tree` 2.3.2 from `OldManProgrammer/unix-tree`. It builds as a C toolchain command from pinned source, stages into `@agentos-software/tree`, and refreshes the tracked runtime-core fallback @@ -266,7 +266,7 @@ works (`wasi-spawn` broker), so `xargs` is not a blocker. longer includes the deleted Rust tree crates in `2026-07-08T05-33-17-0700-tree-cargo-metadata-after-removing-empty-dirs.log`. Rev: `kpmrwxln` — `fix(tree): build upstream tree`. -- **fd — DONE.** Replaced the custom Rust `secureexec-fd` regex walker with +- **fd — DONE.** Replaced the custom Rust `agentos-fd` regex walker with upstream sharkdp `fd-find` 10.4.2. Because `fd-find` is a bin-only crate, `cmd-fd` now acts as the workspace build trigger while the toolchain builds the upstream `fd` binary directly. WASI compatibility stays in dependency @@ -286,7 +286,7 @@ works (`wasi-spawn` broker), so `xargs` is not a blocker. `2026-07-08T06-25-00-0700-fd-vitest-upstream-after-dir-format.log`. Rev: `mrskpomv` — `fix(fd): build upstream fd-find`. - **grep — DONE.** Replaced the `@agentos-software/grep` package's custom - `secureexec-grep` command wrapper with upstream GNU grep 3.12 from the official + `agentos-grep` command wrapper with upstream GNU grep 3.12 from the official GNU release tarball. The real GNU `grep` binary builds through the C toolchain; `egrep` and `fgrep` are separate tiny WASM launchers that preserve GNU's upstream obsolescent scripts by spawning `grep -E` / `grep -F` through the @@ -308,10 +308,10 @@ works (`wasi-spawn` broker), so `xargs` is not a blocker. pass 8/8 in `2026-07-08T06-43-59-0700-grep-vitest-after-wrapper-cache-repair.log`. Rev: `uyukolvr` — `fix(grep): build upstream GNU grep`. - **ripgrep — DONE.** Replaced the `@agentos-software/ripgrep` package's custom - `secureexec-grep` recursive search shim with upstream ripgrep 15.1.0 from the + `agentos-grep` recursive search shim with upstream ripgrep 15.1.0 from the canonical `BurntSushi/ripgrep` crate/release. The local `cmd-rg` crate is now only a build trigger, and `toolchain/Makefile` builds ripgrep's own `rg` bin - directly. The old `secureexec-grep` library is gone. Proof: latest upstream + directly. The old `agentos-grep` library is gone. Proof: latest upstream release captured in `2026-07-08T06-50-40-0700-ripgrep-github-latest-release.json`; crate metadata captured in `2026-07-08T06-52-00-0700-ripgrep-cargo-info.log`; upstream WASM build passes in diff --git a/docs/design/language-execution-api.md b/docs/design/language-execution-api.md new file mode 100644 index 0000000000..bf2305c91a --- /dev/null +++ b/docs/design/language-execution-api.md @@ -0,0 +1,1446 @@ +# Language Execution API + +Status: implemented + +Audience: AgentOS client, actor, sidecar, JavaScript, TypeScript, Python, and +documentation owners + +## 1. Decision + +AgentOS will expose first-class JavaScript, TypeScript, and Python execution on +both the core `AgentOs` client and the `@rivet-dev/agentos` actor. These are +language-native conveniences over the existing VM, filesystem, process, and +package-manager capabilities. They are not a separate product or runtime. + +**Execution** is the only public lifecycle noun. An execution is identified by +`executionId`, can receive multiple sequential operations, and can retain +JavaScript or Python in-memory state between those operations. There is no +second public resource or identifier for retained language state. There is no +standalone `createExecution` method; the first Bash or language operation +creates the execution atomically when requested. + +Arbitrary commands use `process.exec` for configured-shell command strings and +`process.execFile` for exact argv invocation. The existing managed-process +surface is `process.spawn`. We will not add `executeBash` or another +shell-specific abstraction. + +Core and actor actions use the same nested shape. RivetKit serializes nested +actor actions with dotted wire names such as `javascript.execute`, +`javascript.typescript.check`, and `python.execute`. Public TypeScript +identifiers use the canonical `TypeScript` capitalization in type names. + +The API must cover the normal language ecosystem without forcing users to know +how AgentOS invokes `node`, `python`, `python -m`, `npm`, or `pip`. It must not +mirror every package-manager subcommand or CLI flag. Generic command APIs +remain the escape hatch for unusual workflows. + +## 2. Required repository guidance + +The implementation change must add a short scope rule to applicable +`CLAUDE.md` files. At minimum it belongs in `packages/CLAUDE.md`; add a more +specific copy only when a language package has its own `CLAUDE.md`. + +The guidance must preserve this meaning: + +> Language-specific modules own the common end-to-end workflows of their +> ecosystem. A user working purely in JavaScript, TypeScript, or Python should +> be able to execute source and files, evaluate values, install dependencies, +> run project entry points, and use standard module/script workflows without +> manually invoking `node`, `python`, `python -m`, `npm`, or `pip`. Add typed, +> injection-safe conveniences for stable workflows, not one method per CLI +> subcommand or flag. Keep `process.exec`, `process.execFile`, and +> `process.spawn` as the explicit escape hatch for uncommon commands. + +A helper belongs in a language module when it represents a common +language-level intent and can provide safer or clearer behavior than assembling +a command. It does not belong merely because a package-manager flag exists. + +## 3. Goals and non-goals + +### Goals + +- Make inline code, existing files, Python modules, npm scripts, and dependency + installation available without direct runtime binaries. +- Use one execution lifecycle across Bash, argv, JavaScript, TypeScript, + Python, and package-manager operations. +- Retain language state across operations when callers reuse an execution ID. +- Keep JavaScript, TypeScript, and Python results structurally consistent. +- Make TypeScript execution transpile-only by default while providing explicit + type-check APIs. +- Use argv-based internal invocation for user-supplied package names, scripts, + modules, paths, and arguments. +- Keep core, actor, TypeScript, and Rust behavior identical. +- Keep actor inputs, events, results, and errors serializable. +- Preserve `process.exec`, `process.execFile`, and `process.spawn` for + arbitrary Linux workflows. + +### Non-goals + +- A method for every npm, pip, Node.js, Python, or TypeScript CLI operation. +- A generic package-manager framework or immediate pnpm, Yarn, Bun, uv, or + Poetry parity. +- Live JavaScript handles, Python proxy objects, or isolate-owned values + crossing the actor boundary. +- Live notebook display handles or guest-owned display objects. +- A new Bash API. +- Client-side language behavior or command construction. + +## 4. Protocol-first execution model + +An execution is a sidecar-owned unit identified by `executionId`. +Shell, argv, JavaScript, TypeScript, Python, and package-manager operations are +submitted to an execution. An execution admits at most one active operation; +another submission while it is active throws `ExecutionBusyError`. Different +executions may run concurrently. + +An execution may retain JavaScript or Python variables, imports, functions, +loaded modules, and guest objects between operations. It may also own a root OS +process or process tree while an operation is active. `processId` and `pid` are +observational details; `executionId` is the only public lifecycle identity. + +The shared lifecycle is defined in Bare and implemented in the sidecar. The +TypeScript, Rust, standalone language, and actor clients validate and serialize +explicit caller input, route events, and expose generated results. They must not +translate language methods into `node`, `python`, `npm`, `pip`, or shell +commands themselves. + +### 4.1 Shared Bare shape + +The fragments below show the required factoring, not the complete generated +schema. The implementation must define request and response variants for every +semantic operation listed in sections 5 and 7. Exact generated names may +change, but the schema must preserve this shape: + +```bare +type ExecutionState enum { + CREATING + IDLE + RUNNING + RESETTING + DELETING + FAILED +} + +type ExecutionOutcome enum { + SUCCEEDED + FAILED + CANCELLED + TIMED_OUT +} + +type RetainedExecutionLanguage enum { + JAVA_SCRIPT + PYTHON +} + +type ExecutionStreamChannel enum { + STDOUT + STDERR + PTY +} + +type JavaScriptModuleFormat enum { + MODULE + COMMON_JS +} + +type ExecutionIdentityOptions struct { + executionId: optional + createIfMissing: optional +} + +type PtyOptions struct { + cols: optional + rows: optional +} + +type ProcessExecutionOptions struct { + identity: ExecutionIdentityOptions + detached: optional + cwd: optional + env: optional> + args: list + stdin: optional + timeoutMs: optional + pty: optional +} + +type ShellExecutionRequest struct { + process: ProcessExecutionOptions + command: str +} + +type ArgvExecutionRequest struct { + process: ProcessExecutionOptions + command: str +} + +type JavaScriptExecutionRequest struct { + process: ProcessExecutionOptions + source: str + format: optional + filePath: optional + inputs: optional +} + +type TypeScriptExecutionRequest struct { + process: ProcessExecutionOptions + source: str + filePath: optional + tsconfigPath: optional + compilerOptions: optional + inputs: optional +} + +type PythonExecutionRequest struct { + process: ProcessExecutionOptions + source: str + inputs: optional +} +``` + +File, Python-module, npm-script, npm-package, package-install, evaluation, and +type-check requests use the same identity and add only their stable +operation-specific fields. Each distinct semantic operation has a first-class +Bare request. Clients do not implement semantic language conveniences by +calling `process.execFile`. + +Common lifecycle and output are also protocol-owned: + +```bare +type ExecutionDescriptor struct { + executionId: str + generation: u64 + state: ExecutionState + retainedLanguage: optional + processId: optional + pid: optional + createdAtMs: u64 + lastStartedAtMs: optional + lastCompletedAtMs: optional + lastOutcome: optional + lastExitCode: optional +} + +type ExecutionErrorData struct { + code: str + name: str + message: str + stack: optional + details: optional +} + +type ExecutionCompletedResponse struct { + execution: ExecutionDescriptor + outcome: ExecutionOutcome + exitCode: optional + error: optional + stdout: data + stderr: data + stdoutTruncated: bool + stderrTruncated: bool + outputs: JsonUtf8 +} + +type ExecutionOutputEvent struct { + executionId: str + generation: u64 + processId: optional + sequence: u64 + channel: ExecutionStreamChannel + chunk: data + timestampMs: u64 +} + +type ExecutionCompletedEvent struct { + executionId: str + generation: u64 + outcome: ExecutionOutcome + exitCode: optional + error: optional +} + +type GetExecutionRequest struct { + executionId: str +} +type ListExecutionsRequest void +type WaitExecutionRequest struct { + executionId: str +} +type CancelExecutionRequest struct { + executionId: str +} +type SignalExecutionRequest struct { + executionId: str + signal: str +} +type ResetExecutionRequest struct { + executionId: str +} +type DeleteExecutionRequest struct { + executionId: str +} +type WriteExecutionStdinRequest struct { + executionId: str + chunk: data +} +type CloseExecutionStdinRequest struct { + executionId: str +} +type ResizeExecutionPtyRequest struct { + executionId: str + cols: u16 + rows: u16 +} +type ReadExecutionOutputRequest struct { + executionId: str + cursor: optional + limit: optional +} +``` + +A detached operation returns `ExecutionDescriptor` after sidecar admission. +`executions.wait` waits for the execution's sole active operation. When the +execution is already idle or failed, it returns the most recently retained +result or throws `ExecutionResultNotFoundError` if no operation has completed +since creation or reset. + +The sidecar internally orders output for the current or most recently completed +operation by monotonically increasing sequence number. Admitting a new +operation increments the execution's observational `generation`, replaces the +previous retained result and output buffer, and invalidates its cursors; it does +not clear retained language memory. `executions.readOutput` exposes only an opaque +cursor for bounded pagination and replay after actor reconnects. Resetting also +increments `generation`, clears retained output and language state, and +invalidates old cursors. `generation` is a revision marker, not a second +lifecycle identity. + +The current `ExecuteRequest`, PID-only output events, and client-maintained +process records are migration inputs, not the target architecture. The +protocol has no backwards-compatibility requirement, so implementation should +replace them in lockstep rather than add a compatibility path. Optional Bare +fields mean "use the sidecar default"; clients must not duplicate defaults. + +### 4.2 Identity and atomic create-if-missing + +When `executionId` is omitted, the sidecar generates a collision-resistant ID +and creates a fresh execution. When it is supplied, `createIfMissing` defaults +to `false`: + +- if the ID is absent, the sidecar atomically creates it and submits the + operation only when `createIfMissing` is `true`; +- if it exists and is idle, the sidecar submits the operation to that execution; +- if it exists and is active, the sidecar throws `ExecutionBusyError`; +- if it is absent and creation was not requested, the sidecar throws + `ExecutionNotFoundError`; +- concurrent requests for the same absent ID create exactly one execution; +- incompatible retained-language reuse throws `ExecutionLanguageConflictError`. + +JavaScript and TypeScript share one retained JavaScript realm. Python uses a +retained Python interpreter. Process-only operations do not pin a language and +may run before or between language operations. One execution cannot retain +JavaScript and Python state simultaneously. + +Execution IDs are scoped to their owning VM. The same caller-supplied string in +two VMs identifies two independent executions. Supplying +`createIfMissing` without `executionId` is invalid; omission of the ID already +means "create with a generated ID." + +`executionId` is not an idempotency key for every subsequent operation. The +protocol and actor transport retain internal request identities for retry +deduplication, but those identities are not part of the end-user API. Atomic +creation/admission and busy checking are one sidecar operation; client-side +`executions.get` followed by a language operation is prohibited. + +### 4.3 Public shared types + +The names below are illustrative public TypeScript definitions. Final code may +factor them differently, but must preserve their behavior. + +```ts +type JsonPrimitive = string | number | boolean | null; +type JsonValue = + | JsonPrimitive + | JsonValue[] + | { [key: string]: JsonValue }; + +type ExecutionSignal = + | "SIGHUP" + | "SIGINT" + | "SIGQUIT" + | "SIGTERM" + | "SIGKILL" + | "SIGSTOP" + | "SIGCONT" + | "SIGUSR1" + | "SIGUSR2"; + +type ActorData = + | { encoding: "utf8"; data: string } + | { encoding: "base64"; data: string }; + +interface LanguageExecutionOptions { + executionId?: string; + createIfMissing?: boolean; + cwd?: string; + env?: Record; + args?: string[]; + stdin?: string | Uint8Array; + /** Optional wall-clock deadline. Omitted means no caller deadline. */ + timeoutMs?: number; + detached?: boolean; + pty?: { cols?: number; rows?: number }; + + // Core client only. + signal?: AbortSignal; + onStdout?: (chunk: Uint8Array) => void; + onStderr?: (chunk: Uint8Array) => void; +} + +interface InlineExecutionOptions extends LanguageExecutionOptions { + inputs?: Record; +} + +type AttachedInlineExecutionOptions = Omit< + InlineExecutionOptions, + "detached" +>; + +interface ActorLanguageExecutionOptions + extends Omit< + LanguageExecutionOptions, + "stdin" | "signal" | "onStdout" | "onStderr" + > { + stdin?: ActorData; +} + +interface ActorInlineExecutionOptions + extends ActorLanguageExecutionOptions { + inputs?: Record; +} + +type ExecutionState = + | "creating" + | "idle" + | "running" + | "resetting" + | "deleting" + | "failed"; + +type ExecutionOutcome = + | "succeeded" + | "failed" + | "cancelled" + | "timed_out"; + +interface ExecutionDescriptor { + executionId: string; + generation: number; + state: ExecutionState; + retainedLanguage?: "javascript" | "python"; + processId?: string; + pid?: number; + createdAtMs: number; + lastStartedAtMs?: number; + lastCompletedAtMs?: number; + lastOutcome?: ExecutionOutcome; + lastExitCode?: number; +} + +interface DetachedExecution extends ExecutionDescriptor { + detached: true; +} + +interface ExecutionErrorData { + code: string; + name: string; + message: string; + stack?: string; + details?: JsonValue; +} + +interface CodeExecutionResultBase { + executionId: string; + generation: number; + detached: false; + exitCode?: number; + stdout: string; + stderr: string; + stdoutTruncated: boolean; + stderrTruncated: boolean; + outputs: CodeOutput[]; +} + +type CodeExecutionResult = + | (CodeExecutionResultBase & { + outcome: "succeeded"; + error?: never; + }) + | (CodeExecutionResultBase & { + outcome: "failed" | "cancelled" | "timed_out"; + error: ExecutionErrorData; + }); + +type CodeOutput = + | { type: "text" | "markdown" | "html" | "svg"; data: string } + | { type: "json"; data: JsonValue } + | { type: "png" | "jpeg"; data: string; encoding: "base64" }; + +type CodeEvaluationResult = + | (CodeExecutionResult & { + outcome: "succeeded"; + value: T; + }) + | (CodeExecutionResult & { + outcome: "failed" | "cancelled" | "timed_out"; + value?: never; + }); + +interface ExecutionOutputEvent { + executionId: string; + generation: number; + processId?: string; + sequence: number; + channel: "stdout" | "stderr" | "pty"; + chunk: TChunk; + timestampMs: number; +} + +interface ExecutionOutputPage { + executionId: string; + generation: number; + events: ExecutionOutputEvent[]; + nextCursor: string; + hasMore: boolean; + truncated: boolean; +} + +interface ExecutionCompletedEventBase { + executionId: string; + generation: number; + exitCode?: number; +} + +type ExecutionCompletedEvent = + | (ExecutionCompletedEventBase & { + outcome: "succeeded"; + error?: never; + }) + | (ExecutionCompletedEventBase & { + outcome: "failed" | "cancelled" | "timed_out"; + error: ExecutionErrorData; + }); + +executions.get(executionId: string): Promise; +executions.list(): Promise; +executions.wait(executionId: string): Promise; +executions.cancel(executionId: string): Promise; +executions.signal( + executionId: string, + signal: ExecutionSignal, +): Promise; +executions.reset(executionId: string): Promise; +executions.delete(executionId: string): Promise; +executions.writeStdin( + executionId: string, + data: string | Uint8Array, +): Promise; +executions.closeStdin(executionId: string): Promise; +executions.resizePty( + executionId: string, + size: { cols: number; rows: number }, +): Promise; +executions.readOutput( + executionId: string, + options?: { + cursor?: string; + limit?: number; + }, +): Promise; + +// Core client subscriptions. The actor broadcasts equivalent events. +onExecutionOutput( + executionId: string, + handler: (event: ExecutionOutputEvent) => void, +): () => void; +onExecutionCompleted( + executionId: string, + handler: (event: ExecutionCompletedEvent) => void, +): () => void; +``` + +`inputs` is exposed to guest code as a read-only top-level `inputs` object and +is serialized through the protocol rather than interpolated into source. +Evaluation values must be JSON-serializable; the generic type parameter is a +caller-side assertion, not a serializer. + +`executions.cancel` performs bounded graceful cancellation followed by forced +termination. `executions.signal` sends an explicit POSIX signal to the active +execution-owned process group. `executions.delete` accepts only an idle or +failed execution; callers cancel and wait before deleting active work. + +Only inline `javascript.execute`, `javascript.evaluate`, +`javascript.typescript.execute`, `javascript.typescript.evaluate`, +`python.execute`, and `python.evaluate` operations retain language memory. +JavaScript and TypeScript share one retained realm; Python uses a separate +interpreter and cannot share that execution. File, module, type-check, +arbitrary-command, npm, and Python-install operations use a fresh process and +do not mutate retained language memory. Every operation in a VM sees the same +filesystem, so files and installed packages remain visible across executions +until the VM filesystem is removed. + +The `outcome` field is the sole result discriminator. A succeeded evaluation +has `value` and no `error`; failed, cancelled, and timed-out operations have a +serializable `error`. Validation, transport, and other failures before +admission throw typed host errors. Once admitted, an +operation always reaches a retained result and completion event, including +sidecar enforcement failures. Buffered `stdout` and `stderr` are UTF-8 strings; +invalid byte sequences use the Unicode replacement character, and their +truncation flags are always explicit. `outputs` contains bounded serializable +display values and is empty for operations that produce none. Output events +retain exact bytes as `Uint8Array` in core and tagged `ActorData` on the actor +wire. With a PTY, merged terminal bytes use the `pty` event channel and the +`onStdout`/`stdout` attached surface; `stderr` is empty. + +For methods supporting detached operation, omitted or `detached: false` +returns `CodeExecutionResult`, while `detached: true` returns +`DetachedExecution`. No language-specific spawn twins are added. The existing +managed `process.spawn` API remains distinct and returns a PID. + +Actor actions accept only actor-safe options and tagged `ActorData`. They do +not carry `AbortSignal`, callbacks, `Uint8Array`, guest proxies, or class +instances. Core callback subscriptions become actor `executionOutput` and +`executionCompleted` events. Actor output events and +`executions.readOutput` use `ExecutionOutputEvent` and +`ExecutionOutputPage` respectively; core uses their default +`Uint8Array` chunk type. + +`timeoutMs` is an operation property shared by Bash and every language helper. +It starts when the sidecar admits the operation and covers staging, +transpilation or compilation, guest execution, and result collection. Omission +means no caller-configured deadline. Sidecar safety watchdogs and resource +limits remain bounded independently. Timeout cancellation, process-tree +termination, and cleanup are sidecar-owned; cleanup has its own bounded grace +period so a deadline cannot silently abandon resources. + +`timeoutMs` is the only execution-specific limit option introduced by this +API. CPU, memory, process, filesystem, networking, output, and other resource +policies come from the owning VM's existing AgentOS core configuration. The +language helpers inherit and report those limits; they do not duplicate them +under language-specific names or add resource-usage result fields. + +The core `AbortSignal` cancels only the operation submitted by that call. If it +fires before admission, the request is withdrawn; after admission it has the +same operation-level effect as `executions.cancel`. `executions.cancel` targets +the sole active operation and throws a typed state error when the execution is +idle. Cancelling or timing out an inline JavaScript, TypeScript, or Python +operation invalidates that execution's retained language memory before +returning it to idle. Its generation already identifies the admitted operation. +Cancelling a fresh-process operation leaves retained language memory unchanged. + +Public state transitions are: + +| From | Operation | To | +| --- | --- | --- | +| absent | admitted create and operation | `creating` → `running` | +| `idle` | admitted operation | `running` | +| `running` | success, guest failure, cancellation, or timeout | `idle` | +| `running` | sidecar enforcement or cleanup failure | `failed` | +| `idle` or `failed` | reset | `resetting` → `idle` | +| `idle` or `failed` | delete | `deleting` → absent | + +Reset and delete reject an active execution. A failed execution accepts only +inspection, output replay, reset, or deletion. + +## 5. Core API + +All execution semantics are implemented once in the sidecar/runtime. Core and +actor clients only serialize input, route events, and expose typed results. + +### 5.1 Arbitrary commands and managed processes + +The process namespace owns configured-shell commands, exact argv execution, and +managed child processes; no Bash-specific method is added: + +```ts +process.exec( + command: string, + options?: LanguageExecutionOptions & { detached?: false }, +): Promise; +process.exec( + command: string, + options: LanguageExecutionOptions & { detached: true }, +): Promise; + +process.execFile( + command: string, + args?: readonly string[], + options?: Omit & { detached?: false }, +): Promise; +process.execFile( + command: string, + args: readonly string[], + options: Omit & { detached: true }, +): Promise; + +process.spawn( + command: string, + args?: readonly string[], + options?: SpawnOptions, +): { pid: number }; +``` + +`process.exec` retains configured-shell command-string semantics. +`process.execFile` is the injection-safe arbitrary-command API. +`process.spawn` retains the established managed-process contract: it returns a +PID and is controlled with the remaining `process.*` methods. It is not an +alias for a detached execution. No language-specific `spawn*` methods are +added. + +### 5.2 Retained execution state + +Reusing an execution ID retains supported language state: + +```ts +await agentOs.javascript.execute("globalThis.answer = 40", { + executionId: "analysis", + createIfMissing: true, +}); + +const result = await agentOs.javascript.evaluate("answer + 2", { + executionId: "analysis", +}); +``` + +The second operation returns `42`. JavaScript and TypeScript reuse one realm; +Python reuses interpreter globals. A second operation cannot be submitted until +the first is terminal. `inputs` is replaced per operation and is not retained. + +An operation without `executionId` creates a fresh execution with a generated +ID. The returned result includes that ID, so callers may reuse it later. Idle +lifetime, retained memory, output, and execution count are bounded. Expiration +or deletion releases retained resources and invalidates the ID. + +| Methods | Retained language memory | Process behavior | +| --- | --- | --- | +| inline JS/TS execute and evaluate | Shared JavaScript realm | Runs in the execution-owned realm | +| inline Python execute and evaluate | Python interpreter globals | Runs in the execution-owned interpreter | +| JS/TS/Python file and Python module | None | Fresh process | +| Bash, argv, npm, installs, and type checks | None | Fresh process or sidecar compiler operation | + +All rows share the VM filesystem. Per-operation `cwd`, `env`, and `args` do not +persist; guest changes to the process cwd or environment are restored after the +operation, and a shell `cd` or `export` affects only that shell operation. + +Retained JavaScript is a cell/REPL contract, not merely reuse of the same V8 +global object. Top-level `let`, `const`, `var`, function, class, and import +bindings created by a successful JavaScript or TypeScript operation are +available to later inline operations. The implementation must not accomplish +this by replaying earlier source and repeating side effects. A syntax or +transpilation failure does not mutate retained bindings; a guest exception may +leave mutations performed before the exception visible, matching interactive +interpreter behavior. Python follows the same partial-mutation rule. A hard +interruption from cancellation or timeout clears retained memory because its +consistency cannot be guaranteed, but keeps the retained language assignment; +`executions.reset` clears both memory and the language assignment so another +language can claim the execution. + +### 5.3 JavaScript and TypeScript + +```ts +interface JavaScriptExecutionOptions extends InlineExecutionOptions { + format?: "module" | "commonjs"; // default: "module" + filePath?: string; +} + +type JavaScriptEvaluationOptions = Omit< + JavaScriptExecutionOptions, + "detached" +>; + +interface TypeScriptExecutionOptions extends InlineExecutionOptions { + filePath?: string; + tsconfigPath?: string; + compilerOptions?: Record; +} + +type TypeScriptEvaluationOptions = Omit< + TypeScriptExecutionOptions, + "detached" +>; + +interface TypeScriptFileExecutionOptions extends LanguageExecutionOptions { + tsconfigPath?: string; + compilerOptions?: Record; +} + +interface TypeScriptCheckOptions { + executionId?: string; + createIfMissing?: boolean; + cwd?: string; + filePath?: string; + tsconfigPath?: string; + compilerOptions?: Record; + timeoutMs?: number; + signal?: AbortSignal; // Core client only. +} + +interface TypeScriptDiagnostic { + code: number; + category: "error" | "warning" | "suggestion" | "message"; + message: string; + filePath?: string; + line?: number; + column?: number; +} + +type TypeScriptCheckResult = + | (CodeExecutionResult & { + outcome: "succeeded"; + hasErrors: boolean; + diagnostics: TypeScriptDiagnostic[]; + }) + | (CodeExecutionResult & { + outcome: "failed" | "cancelled" | "timed_out"; + hasErrors?: never; + diagnostics: TypeScriptDiagnostic[]; + }); + +javascript.execute( + source: string, + options?: JavaScriptExecutionOptions & { detached?: false }, +): Promise; +javascript.execute( + source: string, + options: JavaScriptExecutionOptions & { detached: true }, +): Promise; + +javascript.evaluate( + expression: string, + options?: JavaScriptEvaluationOptions, +): Promise>; + +javascript.executeFile( + path: string, + options?: LanguageExecutionOptions & { detached?: false }, +): Promise; +javascript.executeFile( + path: string, + options: LanguageExecutionOptions & { detached: true }, +): Promise; + +javascript.typescript.execute( + source: string, + options?: TypeScriptExecutionOptions & { detached?: false }, +): Promise; +javascript.typescript.execute( + source: string, + options: TypeScriptExecutionOptions & { detached: true }, +): Promise; + +javascript.typescript.evaluate( + expression: string, + options?: TypeScriptEvaluationOptions, +): Promise>; + +javascript.typescript.executeFile( + path: string, + options?: TypeScriptFileExecutionOptions & { detached?: false }, +): Promise; +javascript.typescript.executeFile( + path: string, + options: TypeScriptFileExecutionOptions & { detached: true }, +): Promise; + +javascript.typescript.check( + source: string, + options?: TypeScriptCheckOptions, +): Promise; +``` + +TypeScript execute/evaluate methods transpile without semantic type checking. +They may fail for invalid syntax or an emit failure. Users call +`javascript.typescript.check` explicitly when they want diagnostics. There is no +`checkTypes` option and no public `emitTypeScript` or `compileTypeScript` API. +For check results, semantic type errors set `hasErrors: true` while the +operation outcome remains `succeeded`; the outcome is `failed` only when the +checker itself cannot complete. Diagnostic lines and columns are one-based. + +`filePath` on inline source is diagnostic and module-resolution identity; it +does not read that path. File methods are unambiguous for reading and running +existing files. + +### 5.4 npm workflows + +```ts +interface NpmProjectInstallOptions + extends Omit { + frozen?: boolean; +} + +interface NpmPackageInstallOptions + extends Omit { + dev?: boolean; + global?: boolean; +} + +interface NpmScriptOptions extends LanguageExecutionOptions {} + +javascript.npm.install( + options?: NpmProjectInstallOptions, +): Promise; +javascript.npm.install( + packages: string | string[], + options?: NpmPackageInstallOptions, +): Promise; + +javascript.npm.runScript( + script: string, + options?: NpmScriptOptions & { detached?: false }, +): Promise; +javascript.npm.runScript( + script: string, + options: NpmScriptOptions & { detached: true }, +): Promise; +``` + +The options-only install overload installs the project in `cwd`. With +`frozen: true`, it requires the existing npm lockfile and performs a clean, +lockfile-exact install equivalent to `npm ci`; combining `frozen` with named or +global packages is invalid. Named packages are passed as separate argv entries. +`dev` and `global` cover stable install intents; uncommon npm flags remain +available through `process.execFile`. + +`javascript.npm.runScript("build", { args: ["--watch"] })` maps to +`npm run build -- --watch`. npm owns the script's shell semantics; AgentOS does +not construct an outer shell command. + +### 5.5 Python + +```ts +interface PythonInstallOptions + extends Omit { + upgrade?: boolean; + requirementsFile?: string; + indexUrl?: string; + extraIndexUrls?: string[]; +} + +python.execute( + source: string, + options?: InlineExecutionOptions & { detached?: false }, +): Promise; +python.execute( + source: string, + options: InlineExecutionOptions & { detached: true }, +): Promise; + +python.evaluate( + expression: string, + options?: AttachedInlineExecutionOptions, +): Promise>; + +python.executeFile( + path: string, + options?: LanguageExecutionOptions & { detached?: false }, +): Promise; +python.executeFile( + path: string, + options: LanguageExecutionOptions & { detached: true }, +): Promise; + +python.executeModule( + module: string, + options?: LanguageExecutionOptions & { detached?: false }, +): Promise; +python.executeModule( + module: string, + options: LanguageExecutionOptions & { detached: true }, +): Promise; + +python.install( + options?: PythonInstallOptions, +): Promise; +python.install( + packages: string | string[], + options?: PythonInstallOptions, +): Promise; +``` + +`python.executeModule("http.server", { args: ["8000"] })` is the typed +equivalent of `python -m http.server 8000`. + +The options-only install overload installs the project in `cwd` unless +`requirementsFile` is supplied. Providing both named packages and a +requirements file is invalid. + +Inline Python execution and evaluation support top-level `await`, `async for`, +and `async with`. Awaited work is part of the operation and subject to its +timeout. The API does not promise that background or otherwise unawaited +`asyncio` tasks continue between operations; reset, deletion, expiry, or +timeout cancels execution-owned asynchronous work. + +npm and Python installs modify the VM-wide filesystem rather than an +execution-local environment. Installed packages are visible to every execution +in that VM and survive execution reset or deletion. Python requirements files +and pinned package specs provide the reproducible Python workflow; the API does +not invent a cross-ecosystem `frozen` meaning for pip. The sidecar serializes +package mutations at VM scope so installs submitted through different +executions cannot corrupt shared package-manager state. One mutation is +admitted at a time; another install submitted while it is active fails +immediately with `ExecutionBusyError`, so callers can wait for the active +execution before retrying without an implicit unbounded install queue. + +## 6. Actor surface and serialization + +The actor exports the same nested action tree as Core: + +```text +process.exec +process.execFile +process.spawn +process.get +process.list +process.listAll +process.tree +process.wait +process.stop +process.kill +process.writeStdin +process.closeStdin +javascript.execute +javascript.evaluate +javascript.executeFile +javascript.typescript.execute +javascript.typescript.evaluate +javascript.typescript.executeFile +javascript.typescript.check +javascript.typescript.checkProject +javascript.npm.install +javascript.npm.runScript +javascript.npm.runPackage +python.execute +python.evaluate +python.executeFile +python.executeModule +python.install +executions.get +executions.list +executions.wait +executions.cancel +executions.writeStdin +executions.closeStdin +executions.readOutput +executions.reset +executions.delete +executions.signal +executions.resizePty +terminal.open +terminal.write +terminal.resize +terminal.wait +terminal.close +filesystem.readFile +filesystem.writeFile +filesystem.readFiles +filesystem.writeFiles +filesystem.stat +filesystem.mkdir +filesystem.readdir +filesystem.readdirEntries +filesystem.readdirRecursive +filesystem.exists +filesystem.move +filesystem.remove +filesystem.export +filesystem.mount +filesystem.unmount +filesystem.listMounts +network.httpRequest +software.list +software.link +agents.list +sessions.open +sessions.get +sessions.list +sessions.delete +sessions.unload +sessions.prompt +sessions.cancelPrompt +sessions.respondPermission +sessions.readHistory +sessions.getConfig +sessions.setConfigOption +sessions.getCapabilities +sessions.getAgentInfo +cron.schedule +cron.list +cron.cancel +``` + +RivetKit represents these on the wire with the same dotted names. Every action +maps to its corresponding sidecar request and does not reconstruct commands. +The actor-only preview URL actions remain outside this shared tree. + +Actor signatures are derived mechanically from the core signatures: replace +`LanguageExecutionOptions` with `ActorLanguageExecutionOptions`, replace binary +chunks with `ActorData`, and omit core-only `AbortSignal` and callback fields. +This changes only host representation, never admission or runtime behavior. + +The core and actor have matching behavior but intentionally different host +types: + +| Core | Actor wire | +| --- | --- | +| `AbortSignal` | explicit `executions.cancel` action | +| callback functions | `executionOutput` and `executionCompleted` events | +| `Uint8Array` | tagged UTF-8/base64 `ActorData` | +| typed error class | serializable `{ code, message, details }` | +| caller-side generic evaluation type | runtime `JsonValue` | + +Nested serializable option objects such as `pty: { cols, rows }` are allowed. +Actor methods must reject unsupported rich values rather than silently +dropping them. Every JavaScript +numeric input corresponding to Bare `u16`, `u32`, or `u64` is integer- and +range-checked. Every Bare integer exposed as a JavaScript `number` is checked +before conversion and must remain within JavaScript's safe-integer range; +bounded counts and retention make that enforceable. + +The actor automatically acquires an internal keepalive lease before submitting +any attached or detached operation. It holds the lease until the operation is +terminal, all prior output and the completion event have been routed, and +required cleanup has finished; a pre-admission failure releases it immediately. +This behavior has no public option or action. An idle execution does not keep +the actor alive. If hibernation disposes the VM, its in-memory executions +expire; a later lookup returns +`ExecutionNotFoundError` unless the caller explicitly requests creation again. + +## 7. Additional language and lifecycle APIs + +### 7.1 Project TypeScript checking + +```ts +javascript.typescript.checkProject(options?: { + executionId?: string; + createIfMissing?: boolean; + cwd?: string; + tsconfigPath?: string; + timeoutMs?: number; + signal?: AbortSignal; // Core client only. +}): Promise; +``` + +This checks the complete project graph selected by `tsconfig.json` and does not +emit JavaScript. + +### 7.2 One-shot npm package binaries + +```ts +javascript.npm.runPackage( + packageSpec: string, + options?: LanguageExecutionOptions & { detached?: false } & { + binary?: string; + }, +): Promise; +javascript.npm.runPackage( + packageSpec: string, + options: LanguageExecutionOptions & { detached: true } & { + binary?: string; + }, +): Promise; +``` + +This covers the stable `npm exec`/`npx` intent. `binary` handles packages whose +executable differs from the package name. It does not expand into npm init, +pack, publish, audit, outdated, or every npm subcommand. + +### 7.3 Serializable display outputs + +All execution and evaluation results include the bounded +`outputs: CodeOutput[]` field defined in section 4.3. Bash, package, and other +operations without rich displays return an empty array. These are plain tagged +display values, not live guest objects. Each item and the aggregate array have +explicit byte limits. HTML and SVG are untrusted guest output; renderers must +sanitize them or place them in an appropriate isolated display boundary. + +### 7.4 Output replay, reset, deletion, signals, and PTY + +The shared lifecycle includes the methods already defined in section 4.3: + +```text +executions.readOutput +executions.reset +executions.delete +executions.signal +executions.resizePty +``` + +`executions.readOutput` pages the current or most recently completed operation's +retained events with an opaque cursor. Omitting the cursor starts at its oldest +retained event. `nextCursor` is always returned and can be persisted even when +`hasMore` is false so a later call resumes from the same point while that +operation is still active. `limit` is a bounded event count; event chunk size is +also bounded independently. `truncated` reports that earlier output expired +from bounded retention. A new operation, reset, deletion, or recreation +invalidates old cursors with `ExecutionOutputCursorExpiredError` rather than +mixing output from different generations. Replay returns immediately; live +delivery uses the output subscription/event surface. +`executions.reset` accepts only an idle or failed execution, cancels +execution-owned background tasks, clears the retained language assignment and +state, results, and output, increments generation, and leaves filesystem +changes and installed packages untouched. + +`executions.delete` requires an idle or failed execution. It removes retained +state, results, and output immediately. It does not implicitly cancel active +work or revert VM filesystem changes. + +`executions.signal` targets the active execution-owned process group. A present +`pty` option allocates a terminal; `executions.resizePty` changes its dimensions. +PTY output uses the `pty` channel because terminal output merges stdout and +stderr. + +`executions.writeStdin` resolves only after the sidecar has accepted the bytes +into its bounded input path, providing backpressure. It rejects input after +stdin is closed or when the active operation has no writable stdin. + +## 8. Underlying mappings + +Commands below are sidecar implementation details. Public callers provide +typed arguments; the sidecar uses argv invocation and does not construct an +outer shell string except for `process.exec`, whose purpose is configured-shell +execution. + +| Public method | Sidecar operation | Shell involved | +| --- | --- | --- | +| `process.exec` | Submit configured-shell command to the execution | Yes | +| `process.execFile` | Submit exact command and argv | No | +| `process.spawn` | Start a managed child process and return its PID | No | +| `executions.get` / `executions.list` | Read bounded execution metadata | No command | +| `executions.wait` | Wait for the sole active operation, or return the last retained result | No command | +| `executions.cancel` | Gracefully terminate, then force the active process tree | No command | +| `executions.signal` | Signal the active execution-owned process group | No command | +| `executions.reset` | Clear retained state/output and increment generation | No command | +| `executions.delete` | Remove an idle execution and retained data | No command | +| `executions.readOutput` | Page bounded retained output | No command | +| `executions.writeStdin` / `executions.closeStdin` | Route input to the active process or terminal | No command | +| `executions.resizePty` | Resize the active terminal | No command | +| `javascript.execute` | Stage and run JS or evaluate it in the retained JS realm | No | +| `javascript.evaluate` | Evaluate in fresh or retained JS state and serialize the value | No | +| `javascript.executeFile` | `node ...args` | No | +| `javascript.typescript.execute` | Transpile internally, then execute emitted JS | No | +| `javascript.typescript.evaluate` | Transpile internally, evaluate, and serialize | No | +| `javascript.typescript.executeFile` | Project-aware transpile and entry execution | No | +| `javascript.typescript.check` / `javascript.typescript.checkProject` | Internal TypeScript compiler API | No command | +| `javascript.npm.install` | `npm install ...`, or `npm ci` for a frozen project install | No | +| `javascript.npm.runScript` | `npm run + diff --git a/packages/runtime-browser/tests/browser/fixtures/frontend/converged-harness.html b/packages/runtime-browser/tests/browser/fixtures/frontend/converged-harness.html index 8abc901e43..9331a88290 100644 --- a/packages/runtime-browser/tests/browser/fixtures/frontend/converged-harness.html +++ b/packages/runtime-browser/tests/browser/fixtures/frontend/converged-harness.html @@ -2,10 +2,10 @@ - secure-exec converged sidecar harness + agentos converged sidecar harness
loading
- + diff --git a/packages/runtime-browser/tests/browser/fixtures/frontend/converged-runtime-harness.entry.ts b/packages/runtime-browser/tests/browser/fixtures/frontend/converged-runtime-harness.entry.ts index 6209b8b9fb..b605506088 100644 --- a/packages/runtime-browser/tests/browser/fixtures/frontend/converged-runtime-harness.entry.ts +++ b/packages/runtime-browser/tests/browser/fixtures/frontend/converged-runtime-harness.entry.ts @@ -131,7 +131,7 @@ async function execConvergedGuest( } as never; const factory = createBrowserRuntimeDriverFactory({ - workerUrl: new URL("/secure-exec-worker.js", window.location.href), + workerUrl: new URL("/agentos-worker.js", window.location.href), convergedSidecar: { loadSidecar, config }, }); diff --git a/packages/runtime-browser/tests/browser/fixtures/frontend/converged-runtime-harness.html b/packages/runtime-browser/tests/browser/fixtures/frontend/converged-runtime-harness.html index 5ec93ed204..b064585bed 100644 --- a/packages/runtime-browser/tests/browser/fixtures/frontend/converged-runtime-harness.html +++ b/packages/runtime-browser/tests/browser/fixtures/frontend/converged-runtime-harness.html @@ -2,10 +2,10 @@ - secure-exec converged runtime harness + agentos converged runtime harness
loading
- + diff --git a/packages/runtime-browser/tests/browser/harness.smoke.spec.ts b/packages/runtime-browser/tests/browser/harness.smoke.spec.ts index e434b056cd..f17d295ee7 100644 --- a/packages/runtime-browser/tests/browser/harness.smoke.spec.ts +++ b/packages/runtime-browser/tests/browser/harness.smoke.spec.ts @@ -9,7 +9,7 @@ test("playground harness boots a real browser runtime in Chromium", async ({ const result = await smokeHarness(page); expect(result.crossOriginIsolated).toBe(true); - expect(result.workerUrl).toContain("/secure-exec-worker.js"); + expect(result.workerUrl).toContain("/agentos-worker.js"); expect(result.result.code).toBe(0); expect(result.stdio).toEqual([ { diff --git a/packages/runtime-browser/tests/browser/harness.ts b/packages/runtime-browser/tests/browser/harness.ts index e6b58d53fb..5538bcaba5 100644 --- a/packages/runtime-browser/tests/browser/harness.ts +++ b/packages/runtime-browser/tests/browser/harness.ts @@ -76,7 +76,7 @@ export type HarnessSmokeResponse = HarnessExecResponse & { workerUrl: string; }; -type SecureExecBrowserHarness = { +type AgentOsBrowserHarness = { createRuntime( options?: HarnessCreateRuntimeOptions, ): Promise; @@ -109,7 +109,7 @@ type SecureExecBrowserHarness = { declare global { interface Window { - __secureExecBrowserHarness?: SecureExecBrowserHarness; + __agentOsBrowserHarness?: AgentOsBrowserHarness; } } @@ -125,7 +125,7 @@ export async function createRuntime( options?: HarnessCreateRuntimeOptions, ): Promise { return page.evaluate(async (optionsArg) => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { throw new Error("Browser harness is unavailable on window"); } @@ -141,7 +141,7 @@ export async function execRuntime( ): Promise { return page.evaluate( async ({ runtimeId: runtimeIdArg, code: codeArg, options: optionsArg }) => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { throw new Error("Browser harness is unavailable on window"); } @@ -156,7 +156,7 @@ export async function disposeRuntime( runtimeId: string, ): Promise { await page.evaluate(async (runtimeIdArg) => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { return; } @@ -166,7 +166,7 @@ export async function disposeRuntime( export async function disposeAllRuntimes(page: Page): Promise { await page.evaluate(async () => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { return; } @@ -182,7 +182,7 @@ export async function terminatePendingExec( ): Promise { return page.evaluate( async ({ runtimeId: runtimeIdArg, code: codeArg, delayMs: delayMsArg }) => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { throw new Error("Browser harness is unavailable on window"); } @@ -206,7 +206,7 @@ export async function signalPendingExec( signal: signalArg, delayMs: delayMsArg, }) => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { throw new Error("Browser harness is unavailable on window"); } @@ -229,7 +229,7 @@ export async function debugPendingExec( ): Promise { return page.evaluate( async ({ runtimeId: runtimeIdArg, code: codeArg, delayMs: delayMsArg }) => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { throw new Error("Browser harness is unavailable on window"); } @@ -244,7 +244,7 @@ export async function runtimeDebug( runtimeId: string, ): Promise { return page.evaluate(async (runtimeIdArg) => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { throw new Error("Browser harness is unavailable on window"); } @@ -254,7 +254,7 @@ export async function runtimeDebug( export async function smokeHarness(page: Page): Promise { return page.evaluate(async () => { - const harness = window.__secureExecBrowserHarness; + const harness = window.__agentOsBrowserHarness; if (!harness) { throw new Error("Browser harness is unavailable on window"); } diff --git a/packages/runtime-browser/tests/browser/runtime-driver.spec.ts b/packages/runtime-browser/tests/browser/runtime-driver.spec.ts index d578c06a69..32f8acc920 100644 --- a/packages/runtime-browser/tests/browser/runtime-driver.spec.ts +++ b/packages/runtime-browser/tests/browser/runtime-driver.spec.ts @@ -36,7 +36,7 @@ test("preserves sync filesystem and module loading parity in a real Chromium wor await createRuntime(page); expect(crossOriginIsolated).toBe(true); - expect(workerUrl).toContain("/secure-exec-worker.js"); + expect(workerUrl).toContain("/agentos-worker.js"); const filesystemRoundTrip = await execRuntime( page, @@ -185,7 +185,7 @@ test("honors string open flags and positional writeSync without losing data", as test("persists browser filesystem data across OPFS-backed runtimes", async ({ page, }) => { - const path = `/secure-exec-opfs-${Date.now()}-${Math.random() + const path = `/agentos-opfs-${Date.now()}-${Math.random() .toString(16) .slice(2)}.txt`; const first = await createRuntime(page, { filesystem: "opfs" }); @@ -1150,7 +1150,7 @@ test("exposes configured virtual process and OS identity in the browser worker", tmpdir: "/browser-tmp", type: "BrowserLinux", release: "9.9.9-browser", - version: "Browser secure-exec build", + version: "Browser agentos build", machine: "browser64", }, }); @@ -1200,7 +1200,7 @@ test("exposes configured virtual process and OS identity in the browser worker", osTmpdir: "/browser-tmp", osType: "BrowserLinux", osRelease: "9.9.9-browser", - osVersion: "Browser secure-exec build", + osVersion: "Browser agentos build", osMachine: "browser64", userInfo: { username: "runner", @@ -1881,11 +1881,11 @@ test("provides browser node:crypto RSA sign and verify parity", async ({ }); }); }); - const oaepCiphertext = crypto.publicEncrypt(publicKeyObject, encodeText("secure-exec-rsa-oaep")); + const oaepCiphertext = crypto.publicEncrypt(publicKeyObject, encodeText("agentos-rsa-oaep")); const oaepPlaintext = crypto.privateDecrypt(privateKeyObject, oaepCiphertext).toString("utf8"); const pkcs1Ciphertext = crypto.publicEncrypt( { key: publicKeyObject, padding: crypto.constants.RSA_PKCS1_PADDING }, - encodeText("secure-exec-rsa-pkcs1"), + encodeText("agentos-rsa-pkcs1"), ); const pkcs1Plaintext = crypto.privateDecrypt( { key: privateKeyObject, padding: crypto.constants.RSA_PKCS1_PADDING }, @@ -1945,8 +1945,8 @@ test("provides browser node:crypto RSA sign and verify parity", async ({ publicAsymmetricKeyType: "rsa", privateAsymmetricKeyType: "rsa", }, - oaepPlaintext: "secure-exec-rsa-oaep", - pkcs1Plaintext: "secure-exec-rsa-pkcs1", + oaepPlaintext: "agentos-rsa-oaep", + pkcs1Plaintext: "agentos-rsa-pkcs1", keyTypes: ["private", "public"], constants: [1, 4], }); diff --git a/packages/runtime-browser/tests/runtime/resolve-module.test.ts b/packages/runtime-browser/tests/runtime/resolve-module.test.ts index 0308be1fd7..5b81f05858 100644 --- a/packages/runtime-browser/tests/runtime/resolve-module.test.ts +++ b/packages/runtime-browser/tests/runtime/resolve-module.test.ts @@ -85,7 +85,7 @@ describe("browser module resolution", () => { expect(loadPolyfill("node:dns/promises")).toContain("promises"); expect(loadPolyfill("dgram")).toContain("_dgramSocketCreateRaw"); expect(loadPolyfill("node:dgram")).toContain("_dgramSocketCreateRaw"); - expect(loadPolyfill("secure-exec:wasi-command-host")).toContain( + expect(loadPolyfill("agentos:wasi-command-host")).toContain( "createWasiCommandHost", ); }); diff --git a/packages/runtime-browser/tests/runtime/wasi-command-bootstrap.test.ts b/packages/runtime-browser/tests/runtime/wasi-command-bootstrap.test.ts index 540aa47fe4..f2ad39f3a8 100644 --- a/packages/runtime-browser/tests/runtime/wasi-command-bootstrap.test.ts +++ b/packages/runtime-browser/tests/runtime/wasi-command-bootstrap.test.ts @@ -21,7 +21,7 @@ describe("wasi command bootstrap", () => { }); expect(source).toContain('require("node:wasi")'); - expect(source).toContain('require("secure-exec:wasi-command-host")'); + expect(source).toContain('require("agentos:wasi-command-host")'); expect(source).toContain('const commandSource = "/commands/sh";'); expect(source).toContain("/commands/sh"); expect(source).toContain("/commands/echo"); diff --git a/packages/runtime-browser/tests/runtime/wasi-command-host.test.ts b/packages/runtime-browser/tests/runtime/wasi-command-host.test.ts index dec968c1b9..2bc1a4e714 100644 --- a/packages/runtime-browser/tests/runtime/wasi-command-host.test.ts +++ b/packages/runtime-browser/tests/runtime/wasi-command-host.test.ts @@ -100,7 +100,7 @@ function loadCommandHostFactory( exports: {} as { createWasiCommandHost?: CommandHostFactory }, }; const source = getRuntimePolyfillCode( - "secure-exec:wasi-command-host", + "agentos:wasi-command-host", processLimits, ); if (!source) throw new Error("command host polyfill was not found"); diff --git a/packages/runtime-core/README.md b/packages/runtime-core/README.md index 29d2fa75a3..2cfb5b4597 100644 --- a/packages/runtime-core/README.md +++ b/packages/runtime-core/README.md @@ -1,6 +1,6 @@ # @rivet-dev/agentos-runtime-core -Raw Secure Exec protocol types and codecs. +Raw AgentOS language execution protocol types and codecs. - `@rivet-dev/agentos-runtime-core/protocol` exports the generated sidecar protocol. - `@rivet-dev/agentos-runtime-core/binary` resolves the published `agentos-native-sidecar` binary. `AGENTOS_NATIVE_SIDECAR_BIN` overrides only this native runtime; the legacy `AGENTOS_SIDECAR_BIN` override remains the fallback. diff --git a/packages/runtime-core/src/event-buffer.ts b/packages/runtime-core/src/event-buffer.ts index 4e2cb9a6b6..db27ba0e89 100644 --- a/packages/runtime-core/src/event-buffer.ts +++ b/packages/runtime-core/src/event-buffer.ts @@ -1,7 +1,4 @@ -import { - fromGeneratedExtEnvelope, - type LiveExtEnvelope, -} from "./ext.js"; +import { fromGeneratedExtEnvelope, type LiveExtEnvelope } from "./ext.js"; import type * as protocol from "./generated-protocol.js"; import { ownershipMatchesSelector, @@ -38,6 +35,8 @@ export type LiveSidecarEventPayload = name: string; detail: Record; } + | { type: "execution_output"; event: protocol.ExecutionOutputEvent } + | { type: "execution_completed"; event: protocol.ExecutionCompletedEvent } | { type: "ext"; envelope: LiveExtEnvelope; @@ -79,6 +78,16 @@ export type LiveSidecarEventSelector = ownership?: LiveOwnershipScope; name?: string; detail?: Record; + } + | { + type: "execution_output"; + ownership?: LiveOwnershipScope; + executionId?: string; + } + | { + type: "execution_completed"; + ownership?: LiveOwnershipScope; + executionId?: string; }; export type LiveSidecarBufferedEventRecord< @@ -216,6 +225,7 @@ function buildBufferKey( ownership?: LiveOwnershipScope; state?: string; processId?: string; + executionId?: string; channel?: string; name?: string; }, @@ -230,6 +240,9 @@ function buildBufferKey( if (options?.processId) { parts.push(`process:${options.processId}`); } + if (options?.executionId) { + parts.push(`execution:${options.executionId}`); + } if (options?.channel) { parts.push(`channel:${options.channel}`); } @@ -239,10 +252,9 @@ function buildBufferKey( return parts.join("|"); } -export function sidecarSelectorMatchesEvent( - selector: LiveSidecarEventSelector, - event: TEvent, -): boolean { +export function sidecarSelectorMatchesEvent< + TEvent extends LiveSidecarEventFrame, +>(selector: LiveSidecarEventSelector, event: TEvent): boolean { if ("any" in selector) { return true; } @@ -299,6 +311,17 @@ export function sidecarSelectorMatchesEvent; + return ( + selector.executionId === undefined || + payload.event.executionId === selector.executionId + ); + } } } @@ -333,6 +356,12 @@ export function sidecarSelectorBufferKey( ownership: selector.ownership, name: selector.name, }); + case "execution_output": + case "execution_completed": + return buildBufferKey(selector.type, { + ownership: selector.ownership, + executionId: selector.executionId, + }); } } @@ -385,7 +414,11 @@ export function fromGeneratedEventPayload( return { type: "ext", envelope: fromGeneratedExtEnvelope(payload.val), - }; + }; + case "ExecutionOutputEvent": + return { type: "execution_output", event: payload.val }; + case "ExecutionCompletedEvent": + return { type: "execution_completed", event: payload.val }; } } @@ -481,6 +514,20 @@ export function sidecarEventBufferKeys( }), ); break; + case "execution_output": + case "execution_completed": + keys.add( + buildBufferKey(event.payload.type, { + executionId: event.payload.event.executionId, + }), + ); + keys.add( + buildBufferKey(event.payload.type, { + ownership: owner, + executionId: event.payload.event.executionId, + }), + ); + break; case "ext": break; } diff --git a/packages/runtime-core/src/generated-protocol.ts b/packages/runtime-core/src/generated-protocol.ts index 5a69a89ec1..e8b91fc083 100644 --- a/packages/runtime-core/src/generated-protocol.ts +++ b/packages/runtime-core/src/generated-protocol.ts @@ -2023,6 +2023,977 @@ export function writeExecuteRequest(bc: bare.ByteCursor, x: ExecuteRequest): voi write25(bc, x.wasmPermissionTier) } +/** + * First-class execution lifecycle. The legacy process request above remains an + * internal kernel transport while clients migrate in lockstep to these semantic + * operations; language/package command construction belongs to the sidecar. + */ +export enum ExecutionState { + Creating = "Creating", + Idle = "Idle", + Running = "Running", + Resetting = "Resetting", + Deleting = "Deleting", + Failed = "Failed", +} + +export function readExecutionState(bc: bare.ByteCursor): ExecutionState { + const offset = bc.offset + const tag = bare.readU8(bc) + switch (tag) { + case 0: + return ExecutionState.Creating + case 1: + return ExecutionState.Idle + case 2: + return ExecutionState.Running + case 3: + return ExecutionState.Resetting + case 4: + return ExecutionState.Deleting + case 5: + return ExecutionState.Failed + default: { + bc.offset = offset + throw new bare.BareError(offset, "invalid tag") + } + } +} + +export function writeExecutionState(bc: bare.ByteCursor, x: ExecutionState): void { + switch (x) { + case ExecutionState.Creating: { + bare.writeU8(bc, 0) + break + } + case ExecutionState.Idle: { + bare.writeU8(bc, 1) + break + } + case ExecutionState.Running: { + bare.writeU8(bc, 2) + break + } + case ExecutionState.Resetting: { + bare.writeU8(bc, 3) + break + } + case ExecutionState.Deleting: { + bare.writeU8(bc, 4) + break + } + case ExecutionState.Failed: { + bare.writeU8(bc, 5) + break + } + } +} + +export enum ExecutionOutcome { + Succeeded = "Succeeded", + Failed = "Failed", + Cancelled = "Cancelled", + TimedOut = "TimedOut", +} + +export function readExecutionOutcome(bc: bare.ByteCursor): ExecutionOutcome { + const offset = bc.offset + const tag = bare.readU8(bc) + switch (tag) { + case 0: + return ExecutionOutcome.Succeeded + case 1: + return ExecutionOutcome.Failed + case 2: + return ExecutionOutcome.Cancelled + case 3: + return ExecutionOutcome.TimedOut + default: { + bc.offset = offset + throw new bare.BareError(offset, "invalid tag") + } + } +} + +export function writeExecutionOutcome(bc: bare.ByteCursor, x: ExecutionOutcome): void { + switch (x) { + case ExecutionOutcome.Succeeded: { + bare.writeU8(bc, 0) + break + } + case ExecutionOutcome.Failed: { + bare.writeU8(bc, 1) + break + } + case ExecutionOutcome.Cancelled: { + bare.writeU8(bc, 2) + break + } + case ExecutionOutcome.TimedOut: { + bare.writeU8(bc, 3) + break + } + } +} + +export enum RetainedExecutionLanguage { + JavaScript = "JavaScript", + Python = "Python", +} + +export function readRetainedExecutionLanguage(bc: bare.ByteCursor): RetainedExecutionLanguage { + const offset = bc.offset + const tag = bare.readU8(bc) + switch (tag) { + case 0: + return RetainedExecutionLanguage.JavaScript + case 1: + return RetainedExecutionLanguage.Python + default: { + bc.offset = offset + throw new bare.BareError(offset, "invalid tag") + } + } +} + +export function writeRetainedExecutionLanguage(bc: bare.ByteCursor, x: RetainedExecutionLanguage): void { + switch (x) { + case RetainedExecutionLanguage.JavaScript: { + bare.writeU8(bc, 0) + break + } + case RetainedExecutionLanguage.Python: { + bare.writeU8(bc, 1) + break + } + } +} + +export enum ExecutionStreamChannel { + Stdout = "Stdout", + Stderr = "Stderr", + Pty = "Pty", +} + +export function readExecutionStreamChannel(bc: bare.ByteCursor): ExecutionStreamChannel { + const offset = bc.offset + const tag = bare.readU8(bc) + switch (tag) { + case 0: + return ExecutionStreamChannel.Stdout + case 1: + return ExecutionStreamChannel.Stderr + case 2: + return ExecutionStreamChannel.Pty + default: { + bc.offset = offset + throw new bare.BareError(offset, "invalid tag") + } + } +} + +export function writeExecutionStreamChannel(bc: bare.ByteCursor, x: ExecutionStreamChannel): void { + switch (x) { + case ExecutionStreamChannel.Stdout: { + bare.writeU8(bc, 0) + break + } + case ExecutionStreamChannel.Stderr: { + bare.writeU8(bc, 1) + break + } + case ExecutionStreamChannel.Pty: { + bare.writeU8(bc, 2) + break + } + } +} + +export enum JavaScriptModuleFormat { + Module = "Module", + CommonJs = "CommonJs", +} + +export function readJavaScriptModuleFormat(bc: bare.ByteCursor): JavaScriptModuleFormat { + const offset = bc.offset + const tag = bare.readU8(bc) + switch (tag) { + case 0: + return JavaScriptModuleFormat.Module + case 1: + return JavaScriptModuleFormat.CommonJs + default: { + bc.offset = offset + throw new bare.BareError(offset, "invalid tag") + } + } +} + +export function writeJavaScriptModuleFormat(bc: bare.ByteCursor, x: JavaScriptModuleFormat): void { + switch (x) { + case JavaScriptModuleFormat.Module: { + bare.writeU8(bc, 0) + break + } + case JavaScriptModuleFormat.CommonJs: { + bare.writeU8(bc, 1) + break + } + } +} + +function read26(bc: bare.ByteCursor): boolean | null { + return bare.readBool(bc) ? bare.readBool(bc) : null +} + +function write26(bc: bare.ByteCursor, x: boolean | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + bare.writeBool(bc, x) + } +} + +export type ExecutionIdentityOptions = { + readonly executionId: string | null + readonly createIfMissing: boolean | null +} + +export function readExecutionIdentityOptions(bc: bare.ByteCursor): ExecutionIdentityOptions { + return { + executionId: read0(bc), + createIfMissing: read26(bc), + } +} + +export function writeExecutionIdentityOptions(bc: bare.ByteCursor, x: ExecutionIdentityOptions): void { + write0(bc, x.executionId) + write26(bc, x.createIfMissing) +} + +function read27(bc: bare.ByteCursor): u16 | null { + return bare.readBool(bc) ? bare.readU16(bc) : null +} + +function write27(bc: bare.ByteCursor, x: u16 | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + bare.writeU16(bc, x) + } +} + +export type ExecutionPtyOptions = { + readonly cols: u16 | null + readonly rows: u16 | null +} + +export function readExecutionPtyOptions(bc: bare.ByteCursor): ExecutionPtyOptions { + return { + cols: read27(bc), + rows: read27(bc), + } +} + +export function writeExecutionPtyOptions(bc: bare.ByteCursor, x: ExecutionPtyOptions): void { + write27(bc, x.cols) + write27(bc, x.rows) +} + +function read28(bc: bare.ByteCursor): ReadonlyMap | null { + return bare.readBool(bc) ? read1(bc) : null +} + +function write28(bc: bare.ByteCursor, x: ReadonlyMap | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + write1(bc, x) + } +} + +function read29(bc: bare.ByteCursor): ArrayBuffer | null { + return bare.readBool(bc) ? bare.readData(bc) : null +} + +function write29(bc: bare.ByteCursor, x: ArrayBuffer | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + bare.writeData(bc, x) + } +} + +function read30(bc: bare.ByteCursor): ExecutionPtyOptions | null { + return bare.readBool(bc) ? readExecutionPtyOptions(bc) : null +} + +function write30(bc: bare.ByteCursor, x: ExecutionPtyOptions | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + writeExecutionPtyOptions(bc, x) + } +} + +export type ProcessExecutionOptions = { + readonly identity: ExecutionIdentityOptions + readonly detached: boolean | null + readonly cwd: string | null + readonly env: ReadonlyMap | null + readonly args: readonly string[] + readonly stdin: ArrayBuffer | null + readonly timeoutMs: u64 | null + readonly pty: ExecutionPtyOptions | null +} + +export function readProcessExecutionOptions(bc: bare.ByteCursor): ProcessExecutionOptions { + return { + identity: readExecutionIdentityOptions(bc), + detached: read26(bc), + cwd: read0(bc), + env: read28(bc), + args: read6(bc), + stdin: read29(bc), + timeoutMs: read21(bc), + pty: read30(bc), + } +} + +export function writeProcessExecutionOptions(bc: bare.ByteCursor, x: ProcessExecutionOptions): void { + writeExecutionIdentityOptions(bc, x.identity) + write26(bc, x.detached) + write0(bc, x.cwd) + write28(bc, x.env) + write6(bc, x.args) + write29(bc, x.stdin) + write21(bc, x.timeoutMs) + write30(bc, x.pty) +} + +export type ShellExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly command: string +} + +export function readShellExecutionRequest(bc: bare.ByteCursor): ShellExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + command: bare.readString(bc), + } +} + +export function writeShellExecutionRequest(bc: bare.ByteCursor, x: ShellExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.command) +} + +export type ArgvExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly command: string +} + +export function readArgvExecutionRequest(bc: bare.ByteCursor): ArgvExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + command: bare.readString(bc), + } +} + +export function writeArgvExecutionRequest(bc: bare.ByteCursor, x: ArgvExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.command) +} + +function read31(bc: bare.ByteCursor): JavaScriptModuleFormat | null { + return bare.readBool(bc) ? readJavaScriptModuleFormat(bc) : null +} + +function write31(bc: bare.ByteCursor, x: JavaScriptModuleFormat | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + writeJavaScriptModuleFormat(bc, x) + } +} + +function read32(bc: bare.ByteCursor): JsonUtf8 | null { + return bare.readBool(bc) ? readJsonUtf8(bc) : null +} + +function write32(bc: bare.ByteCursor, x: JsonUtf8 | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + writeJsonUtf8(bc, x) + } +} + +export type JavaScriptExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly source: string + readonly format: JavaScriptModuleFormat | null + readonly filePath: string | null + readonly inputs: JsonUtf8 | null +} + +export function readJavaScriptExecutionRequest(bc: bare.ByteCursor): JavaScriptExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + source: bare.readString(bc), + format: read31(bc), + filePath: read0(bc), + inputs: read32(bc), + } +} + +export function writeJavaScriptExecutionRequest(bc: bare.ByteCursor, x: JavaScriptExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.source) + write31(bc, x.format) + write0(bc, x.filePath) + write32(bc, x.inputs) +} + +export type JavaScriptEvaluationRequest = { + readonly process: ProcessExecutionOptions + readonly expression: string + readonly format: JavaScriptModuleFormat | null + readonly filePath: string | null + readonly inputs: JsonUtf8 | null +} + +export function readJavaScriptEvaluationRequest(bc: bare.ByteCursor): JavaScriptEvaluationRequest { + return { + process: readProcessExecutionOptions(bc), + expression: bare.readString(bc), + format: read31(bc), + filePath: read0(bc), + inputs: read32(bc), + } +} + +export function writeJavaScriptEvaluationRequest(bc: bare.ByteCursor, x: JavaScriptEvaluationRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.expression) + write31(bc, x.format) + write0(bc, x.filePath) + write32(bc, x.inputs) +} + +export type JavaScriptFileExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly path: string +} + +export function readJavaScriptFileExecutionRequest(bc: bare.ByteCursor): JavaScriptFileExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + path: bare.readString(bc), + } +} + +export function writeJavaScriptFileExecutionRequest(bc: bare.ByteCursor, x: JavaScriptFileExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.path) +} + +export type TypeScriptExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly source: string + readonly filePath: string | null + readonly tsconfigPath: string | null + readonly compilerOptions: JsonUtf8 | null + readonly inputs: JsonUtf8 | null +} + +export function readTypeScriptExecutionRequest(bc: bare.ByteCursor): TypeScriptExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + source: bare.readString(bc), + filePath: read0(bc), + tsconfigPath: read0(bc), + compilerOptions: read32(bc), + inputs: read32(bc), + } +} + +export function writeTypeScriptExecutionRequest(bc: bare.ByteCursor, x: TypeScriptExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.source) + write0(bc, x.filePath) + write0(bc, x.tsconfigPath) + write32(bc, x.compilerOptions) + write32(bc, x.inputs) +} + +export type TypeScriptEvaluationRequest = { + readonly process: ProcessExecutionOptions + readonly expression: string + readonly filePath: string | null + readonly tsconfigPath: string | null + readonly compilerOptions: JsonUtf8 | null + readonly inputs: JsonUtf8 | null +} + +export function readTypeScriptEvaluationRequest(bc: bare.ByteCursor): TypeScriptEvaluationRequest { + return { + process: readProcessExecutionOptions(bc), + expression: bare.readString(bc), + filePath: read0(bc), + tsconfigPath: read0(bc), + compilerOptions: read32(bc), + inputs: read32(bc), + } +} + +export function writeTypeScriptEvaluationRequest(bc: bare.ByteCursor, x: TypeScriptEvaluationRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.expression) + write0(bc, x.filePath) + write0(bc, x.tsconfigPath) + write32(bc, x.compilerOptions) + write32(bc, x.inputs) +} + +export type TypeScriptFileExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly path: string + readonly tsconfigPath: string | null + readonly compilerOptions: JsonUtf8 | null +} + +export function readTypeScriptFileExecutionRequest(bc: bare.ByteCursor): TypeScriptFileExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + path: bare.readString(bc), + tsconfigPath: read0(bc), + compilerOptions: read32(bc), + } +} + +export function writeTypeScriptFileExecutionRequest(bc: bare.ByteCursor, x: TypeScriptFileExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.path) + write0(bc, x.tsconfigPath) + write32(bc, x.compilerOptions) +} + +export type TypeScriptCheckRequest = { + readonly identity: ExecutionIdentityOptions + readonly source: string + readonly cwd: string | null + readonly filePath: string | null + readonly tsconfigPath: string | null + readonly compilerOptions: JsonUtf8 | null + readonly timeoutMs: u64 | null +} + +export function readTypeScriptCheckRequest(bc: bare.ByteCursor): TypeScriptCheckRequest { + return { + identity: readExecutionIdentityOptions(bc), + source: bare.readString(bc), + cwd: read0(bc), + filePath: read0(bc), + tsconfigPath: read0(bc), + compilerOptions: read32(bc), + timeoutMs: read21(bc), + } +} + +export function writeTypeScriptCheckRequest(bc: bare.ByteCursor, x: TypeScriptCheckRequest): void { + writeExecutionIdentityOptions(bc, x.identity) + bare.writeString(bc, x.source) + write0(bc, x.cwd) + write0(bc, x.filePath) + write0(bc, x.tsconfigPath) + write32(bc, x.compilerOptions) + write21(bc, x.timeoutMs) +} + +export type TypeScriptProjectCheckRequest = { + readonly identity: ExecutionIdentityOptions + readonly cwd: string | null + readonly tsconfigPath: string | null + readonly timeoutMs: u64 | null +} + +export function readTypeScriptProjectCheckRequest(bc: bare.ByteCursor): TypeScriptProjectCheckRequest { + return { + identity: readExecutionIdentityOptions(bc), + cwd: read0(bc), + tsconfigPath: read0(bc), + timeoutMs: read21(bc), + } +} + +export function writeTypeScriptProjectCheckRequest(bc: bare.ByteCursor, x: TypeScriptProjectCheckRequest): void { + writeExecutionIdentityOptions(bc, x.identity) + write0(bc, x.cwd) + write0(bc, x.tsconfigPath) + write21(bc, x.timeoutMs) +} + +export type NpmProjectInstallRequest = { + readonly identity: ExecutionIdentityOptions + readonly cwd: string | null + readonly env: ReadonlyMap | null + readonly timeoutMs: u64 | null + readonly frozen: boolean | null +} + +export function readNpmProjectInstallRequest(bc: bare.ByteCursor): NpmProjectInstallRequest { + return { + identity: readExecutionIdentityOptions(bc), + cwd: read0(bc), + env: read28(bc), + timeoutMs: read21(bc), + frozen: read26(bc), + } +} + +export function writeNpmProjectInstallRequest(bc: bare.ByteCursor, x: NpmProjectInstallRequest): void { + writeExecutionIdentityOptions(bc, x.identity) + write0(bc, x.cwd) + write28(bc, x.env) + write21(bc, x.timeoutMs) + write26(bc, x.frozen) +} + +export type NpmPackageInstallRequest = { + readonly identity: ExecutionIdentityOptions + readonly cwd: string | null + readonly env: ReadonlyMap | null + readonly timeoutMs: u64 | null + readonly packages: readonly string[] + readonly dev: boolean | null + readonly global: boolean | null +} + +export function readNpmPackageInstallRequest(bc: bare.ByteCursor): NpmPackageInstallRequest { + return { + identity: readExecutionIdentityOptions(bc), + cwd: read0(bc), + env: read28(bc), + timeoutMs: read21(bc), + packages: read6(bc), + dev: read26(bc), + global: read26(bc), + } +} + +export function writeNpmPackageInstallRequest(bc: bare.ByteCursor, x: NpmPackageInstallRequest): void { + writeExecutionIdentityOptions(bc, x.identity) + write0(bc, x.cwd) + write28(bc, x.env) + write21(bc, x.timeoutMs) + write6(bc, x.packages) + write26(bc, x.dev) + write26(bc, x.global) +} + +export type NpmScriptExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly script: string +} + +export function readNpmScriptExecutionRequest(bc: bare.ByteCursor): NpmScriptExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + script: bare.readString(bc), + } +} + +export function writeNpmScriptExecutionRequest(bc: bare.ByteCursor, x: NpmScriptExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.script) +} + +export type NpmPackageExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly packageSpec: string + readonly binary: string | null +} + +export function readNpmPackageExecutionRequest(bc: bare.ByteCursor): NpmPackageExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + packageSpec: bare.readString(bc), + binary: read0(bc), + } +} + +export function writeNpmPackageExecutionRequest(bc: bare.ByteCursor, x: NpmPackageExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.packageSpec) + write0(bc, x.binary) +} + +export type PythonExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly source: string + readonly inputs: JsonUtf8 | null +} + +export function readPythonExecutionRequest(bc: bare.ByteCursor): PythonExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + source: bare.readString(bc), + inputs: read32(bc), + } +} + +export function writePythonExecutionRequest(bc: bare.ByteCursor, x: PythonExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.source) + write32(bc, x.inputs) +} + +export type PythonEvaluationRequest = { + readonly process: ProcessExecutionOptions + readonly expression: string + readonly inputs: JsonUtf8 | null +} + +export function readPythonEvaluationRequest(bc: bare.ByteCursor): PythonEvaluationRequest { + return { + process: readProcessExecutionOptions(bc), + expression: bare.readString(bc), + inputs: read32(bc), + } +} + +export function writePythonEvaluationRequest(bc: bare.ByteCursor, x: PythonEvaluationRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.expression) + write32(bc, x.inputs) +} + +export type PythonFileExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly path: string +} + +export function readPythonFileExecutionRequest(bc: bare.ByteCursor): PythonFileExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + path: bare.readString(bc), + } +} + +export function writePythonFileExecutionRequest(bc: bare.ByteCursor, x: PythonFileExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.path) +} + +export type PythonModuleExecutionRequest = { + readonly process: ProcessExecutionOptions + readonly module: string +} + +export function readPythonModuleExecutionRequest(bc: bare.ByteCursor): PythonModuleExecutionRequest { + return { + process: readProcessExecutionOptions(bc), + module: bare.readString(bc), + } +} + +export function writePythonModuleExecutionRequest(bc: bare.ByteCursor, x: PythonModuleExecutionRequest): void { + writeProcessExecutionOptions(bc, x.process) + bare.writeString(bc, x.module) +} + +export type PythonInstallRequest = { + readonly identity: ExecutionIdentityOptions + readonly cwd: string | null + readonly env: ReadonlyMap | null + readonly timeoutMs: u64 | null + readonly packages: readonly string[] + readonly upgrade: boolean | null + readonly requirementsFile: string | null + readonly indexUrl: string | null + readonly extraIndexUrls: readonly string[] +} + +export function readPythonInstallRequest(bc: bare.ByteCursor): PythonInstallRequest { + return { + identity: readExecutionIdentityOptions(bc), + cwd: read0(bc), + env: read28(bc), + timeoutMs: read21(bc), + packages: read6(bc), + upgrade: read26(bc), + requirementsFile: read0(bc), + indexUrl: read0(bc), + extraIndexUrls: read6(bc), + } +} + +export function writePythonInstallRequest(bc: bare.ByteCursor, x: PythonInstallRequest): void { + writeExecutionIdentityOptions(bc, x.identity) + write0(bc, x.cwd) + write28(bc, x.env) + write21(bc, x.timeoutMs) + write6(bc, x.packages) + write26(bc, x.upgrade) + write0(bc, x.requirementsFile) + write0(bc, x.indexUrl) + write6(bc, x.extraIndexUrls) +} + +export type GetExecutionRequest = { + readonly executionId: string +} + +export function readGetExecutionRequest(bc: bare.ByteCursor): GetExecutionRequest { + return { + executionId: bare.readString(bc), + } +} + +export function writeGetExecutionRequest(bc: bare.ByteCursor, x: GetExecutionRequest): void { + bare.writeString(bc, x.executionId) +} + +export type ListExecutionsRequest = null + +export type WaitExecutionRequest = { + readonly executionId: string +} + +export function readWaitExecutionRequest(bc: bare.ByteCursor): WaitExecutionRequest { + return { + executionId: bare.readString(bc), + } +} + +export function writeWaitExecutionRequest(bc: bare.ByteCursor, x: WaitExecutionRequest): void { + bare.writeString(bc, x.executionId) +} + +export type CancelExecutionRequest = { + readonly executionId: string +} + +export function readCancelExecutionRequest(bc: bare.ByteCursor): CancelExecutionRequest { + return { + executionId: bare.readString(bc), + } +} + +export function writeCancelExecutionRequest(bc: bare.ByteCursor, x: CancelExecutionRequest): void { + bare.writeString(bc, x.executionId) +} + +export type SignalExecutionRequest = { + readonly executionId: string + readonly signal: string +} + +export function readSignalExecutionRequest(bc: bare.ByteCursor): SignalExecutionRequest { + return { + executionId: bare.readString(bc), + signal: bare.readString(bc), + } +} + +export function writeSignalExecutionRequest(bc: bare.ByteCursor, x: SignalExecutionRequest): void { + bare.writeString(bc, x.executionId) + bare.writeString(bc, x.signal) +} + +export type ResetExecutionRequest = { + readonly executionId: string +} + +export function readResetExecutionRequest(bc: bare.ByteCursor): ResetExecutionRequest { + return { + executionId: bare.readString(bc), + } +} + +export function writeResetExecutionRequest(bc: bare.ByteCursor, x: ResetExecutionRequest): void { + bare.writeString(bc, x.executionId) +} + +export type DeleteExecutionRequest = { + readonly executionId: string +} + +export function readDeleteExecutionRequest(bc: bare.ByteCursor): DeleteExecutionRequest { + return { + executionId: bare.readString(bc), + } +} + +export function writeDeleteExecutionRequest(bc: bare.ByteCursor, x: DeleteExecutionRequest): void { + bare.writeString(bc, x.executionId) +} + +export type WriteExecutionStdinRequest = { + readonly executionId: string + readonly chunk: ArrayBuffer +} + +export function readWriteExecutionStdinRequest(bc: bare.ByteCursor): WriteExecutionStdinRequest { + return { + executionId: bare.readString(bc), + chunk: bare.readData(bc), + } +} + +export function writeWriteExecutionStdinRequest(bc: bare.ByteCursor, x: WriteExecutionStdinRequest): void { + bare.writeString(bc, x.executionId) + bare.writeData(bc, x.chunk) +} + +export type CloseExecutionStdinRequest = { + readonly executionId: string +} + +export function readCloseExecutionStdinRequest(bc: bare.ByteCursor): CloseExecutionStdinRequest { + return { + executionId: bare.readString(bc), + } +} + +export function writeCloseExecutionStdinRequest(bc: bare.ByteCursor, x: CloseExecutionStdinRequest): void { + bare.writeString(bc, x.executionId) +} + +export type ResizeExecutionPtyRequest = { + readonly executionId: string + readonly cols: u16 + readonly rows: u16 +} + +export function readResizeExecutionPtyRequest(bc: bare.ByteCursor): ResizeExecutionPtyRequest { + return { + executionId: bare.readString(bc), + cols: bare.readU16(bc), + rows: bare.readU16(bc), + } +} + +export function writeResizeExecutionPtyRequest(bc: bare.ByteCursor, x: ResizeExecutionPtyRequest): void { + bare.writeString(bc, x.executionId) + bare.writeU16(bc, x.cols) + bare.writeU16(bc, x.rows) +} + +export type ReadExecutionOutputRequest = { + readonly executionId: string + readonly cursor: string | null + readonly limit: u32 | null +} + +export function readReadExecutionOutputRequest(bc: bare.ByteCursor): ReadExecutionOutputRequest { + return { + executionId: bare.readString(bc), + cursor: read0(bc), + limit: read2(bc), + } +} + +export function writeReadExecutionOutputRequest(bc: bare.ByteCursor, x: ReadExecutionOutputRequest): void { + bare.writeString(bc, x.executionId) + write0(bc, x.cursor) + write2(bc, x.limit) +} + export type WriteStdinRequest = { readonly processId: string readonly chunk: ArrayBuffer @@ -2095,17 +3066,6 @@ export type GetProcessSnapshotRequest = null export type GetResourceSnapshotRequest = null -function read26(bc: bare.ByteCursor): u16 | null { - return bare.readBool(bc) ? bare.readU16(bc) : null -} - -function write26(bc: bare.ByteCursor, x: u16 | null): void { - bare.writeBool(bc, x != null) - if (x != null) { - bare.writeU16(bc, x) - } -} - export type FindListenerRequest = { readonly host: string | null readonly port: u16 | null @@ -2115,14 +3075,14 @@ export type FindListenerRequest = { export function readFindListenerRequest(bc: bare.ByteCursor): FindListenerRequest { return { host: read0(bc), - port: read26(bc), + port: read27(bc), path: read0(bc), } } export function writeFindListenerRequest(bc: bare.ByteCursor, x: FindListenerRequest): void { write0(bc, x.host) - write26(bc, x.port) + write27(bc, x.port) write0(bc, x.path) } @@ -2134,13 +3094,13 @@ export type FindBoundUdpRequest = { export function readFindBoundUdpRequest(bc: bare.ByteCursor): FindBoundUdpRequest { return { host: read0(bc), - port: read26(bc), + port: read27(bc), } } export function writeFindBoundUdpRequest(bc: bare.ByteCursor, x: FindBoundUdpRequest): void { write0(bc, x.host) - write26(bc, x.port) + write27(bc, x.port) } export type GetSignalStateRequest = { @@ -2339,6 +3299,36 @@ export type RequestPayload = | { readonly tag: "LinkPackageRequest"; readonly val: LinkPackageRequest } | { readonly tag: "ProvidedCommandsRequest"; readonly val: ProvidedCommandsRequest } | { readonly tag: "ListMountsRequest"; readonly val: ListMountsRequest } + | { readonly tag: "ShellExecutionRequest"; readonly val: ShellExecutionRequest } + | { readonly tag: "ArgvExecutionRequest"; readonly val: ArgvExecutionRequest } + | { readonly tag: "JavaScriptExecutionRequest"; readonly val: JavaScriptExecutionRequest } + | { readonly tag: "JavaScriptEvaluationRequest"; readonly val: JavaScriptEvaluationRequest } + | { readonly tag: "JavaScriptFileExecutionRequest"; readonly val: JavaScriptFileExecutionRequest } + | { readonly tag: "TypeScriptExecutionRequest"; readonly val: TypeScriptExecutionRequest } + | { readonly tag: "TypeScriptEvaluationRequest"; readonly val: TypeScriptEvaluationRequest } + | { readonly tag: "TypeScriptFileExecutionRequest"; readonly val: TypeScriptFileExecutionRequest } + | { readonly tag: "TypeScriptCheckRequest"; readonly val: TypeScriptCheckRequest } + | { readonly tag: "TypeScriptProjectCheckRequest"; readonly val: TypeScriptProjectCheckRequest } + | { readonly tag: "NpmProjectInstallRequest"; readonly val: NpmProjectInstallRequest } + | { readonly tag: "NpmPackageInstallRequest"; readonly val: NpmPackageInstallRequest } + | { readonly tag: "NpmScriptExecutionRequest"; readonly val: NpmScriptExecutionRequest } + | { readonly tag: "NpmPackageExecutionRequest"; readonly val: NpmPackageExecutionRequest } + | { readonly tag: "PythonExecutionRequest"; readonly val: PythonExecutionRequest } + | { readonly tag: "PythonEvaluationRequest"; readonly val: PythonEvaluationRequest } + | { readonly tag: "PythonFileExecutionRequest"; readonly val: PythonFileExecutionRequest } + | { readonly tag: "PythonModuleExecutionRequest"; readonly val: PythonModuleExecutionRequest } + | { readonly tag: "PythonInstallRequest"; readonly val: PythonInstallRequest } + | { readonly tag: "GetExecutionRequest"; readonly val: GetExecutionRequest } + | { readonly tag: "ListExecutionsRequest"; readonly val: ListExecutionsRequest } + | { readonly tag: "WaitExecutionRequest"; readonly val: WaitExecutionRequest } + | { readonly tag: "CancelExecutionRequest"; readonly val: CancelExecutionRequest } + | { readonly tag: "SignalExecutionRequest"; readonly val: SignalExecutionRequest } + | { readonly tag: "ResetExecutionRequest"; readonly val: ResetExecutionRequest } + | { readonly tag: "DeleteExecutionRequest"; readonly val: DeleteExecutionRequest } + | { readonly tag: "WriteExecutionStdinRequest"; readonly val: WriteExecutionStdinRequest } + | { readonly tag: "CloseExecutionStdinRequest"; readonly val: CloseExecutionStdinRequest } + | { readonly tag: "ResizeExecutionPtyRequest"; readonly val: ResizeExecutionPtyRequest } + | { readonly tag: "ReadExecutionOutputRequest"; readonly val: ReadExecutionOutputRequest } export function readRequestPayload(bc: bare.ByteCursor): RequestPayload { const offset = bc.offset @@ -2412,6 +3402,66 @@ export function readRequestPayload(bc: bare.ByteCursor): RequestPayload { return { tag: "ProvidedCommandsRequest", val: null } case 33: return { tag: "ListMountsRequest", val: null } + case 34: + return { tag: "ShellExecutionRequest", val: readShellExecutionRequest(bc) } + case 35: + return { tag: "ArgvExecutionRequest", val: readArgvExecutionRequest(bc) } + case 36: + return { tag: "JavaScriptExecutionRequest", val: readJavaScriptExecutionRequest(bc) } + case 37: + return { tag: "JavaScriptEvaluationRequest", val: readJavaScriptEvaluationRequest(bc) } + case 38: + return { tag: "JavaScriptFileExecutionRequest", val: readJavaScriptFileExecutionRequest(bc) } + case 39: + return { tag: "TypeScriptExecutionRequest", val: readTypeScriptExecutionRequest(bc) } + case 40: + return { tag: "TypeScriptEvaluationRequest", val: readTypeScriptEvaluationRequest(bc) } + case 41: + return { tag: "TypeScriptFileExecutionRequest", val: readTypeScriptFileExecutionRequest(bc) } + case 42: + return { tag: "TypeScriptCheckRequest", val: readTypeScriptCheckRequest(bc) } + case 43: + return { tag: "TypeScriptProjectCheckRequest", val: readTypeScriptProjectCheckRequest(bc) } + case 44: + return { tag: "NpmProjectInstallRequest", val: readNpmProjectInstallRequest(bc) } + case 45: + return { tag: "NpmPackageInstallRequest", val: readNpmPackageInstallRequest(bc) } + case 46: + return { tag: "NpmScriptExecutionRequest", val: readNpmScriptExecutionRequest(bc) } + case 47: + return { tag: "NpmPackageExecutionRequest", val: readNpmPackageExecutionRequest(bc) } + case 48: + return { tag: "PythonExecutionRequest", val: readPythonExecutionRequest(bc) } + case 49: + return { tag: "PythonEvaluationRequest", val: readPythonEvaluationRequest(bc) } + case 50: + return { tag: "PythonFileExecutionRequest", val: readPythonFileExecutionRequest(bc) } + case 51: + return { tag: "PythonModuleExecutionRequest", val: readPythonModuleExecutionRequest(bc) } + case 52: + return { tag: "PythonInstallRequest", val: readPythonInstallRequest(bc) } + case 53: + return { tag: "GetExecutionRequest", val: readGetExecutionRequest(bc) } + case 54: + return { tag: "ListExecutionsRequest", val: null } + case 55: + return { tag: "WaitExecutionRequest", val: readWaitExecutionRequest(bc) } + case 56: + return { tag: "CancelExecutionRequest", val: readCancelExecutionRequest(bc) } + case 57: + return { tag: "SignalExecutionRequest", val: readSignalExecutionRequest(bc) } + case 58: + return { tag: "ResetExecutionRequest", val: readResetExecutionRequest(bc) } + case 59: + return { tag: "DeleteExecutionRequest", val: readDeleteExecutionRequest(bc) } + case 60: + return { tag: "WriteExecutionStdinRequest", val: readWriteExecutionStdinRequest(bc) } + case 61: + return { tag: "CloseExecutionStdinRequest", val: readCloseExecutionStdinRequest(bc) } + case 62: + return { tag: "ResizeExecutionPtyRequest", val: readResizeExecutionPtyRequest(bc) } + case 63: + return { tag: "ReadExecutionOutputRequest", val: readReadExecutionOutputRequest(bc) } default: { bc.offset = offset throw new bare.BareError(offset, "invalid tag") @@ -2585,6 +3635,155 @@ export function writeRequestPayload(bc: bare.ByteCursor, x: RequestPayload): voi bare.writeU8(bc, 33) break } + case "ShellExecutionRequest": { + bare.writeU8(bc, 34) + writeShellExecutionRequest(bc, x.val) + break + } + case "ArgvExecutionRequest": { + bare.writeU8(bc, 35) + writeArgvExecutionRequest(bc, x.val) + break + } + case "JavaScriptExecutionRequest": { + bare.writeU8(bc, 36) + writeJavaScriptExecutionRequest(bc, x.val) + break + } + case "JavaScriptEvaluationRequest": { + bare.writeU8(bc, 37) + writeJavaScriptEvaluationRequest(bc, x.val) + break + } + case "JavaScriptFileExecutionRequest": { + bare.writeU8(bc, 38) + writeJavaScriptFileExecutionRequest(bc, x.val) + break + } + case "TypeScriptExecutionRequest": { + bare.writeU8(bc, 39) + writeTypeScriptExecutionRequest(bc, x.val) + break + } + case "TypeScriptEvaluationRequest": { + bare.writeU8(bc, 40) + writeTypeScriptEvaluationRequest(bc, x.val) + break + } + case "TypeScriptFileExecutionRequest": { + bare.writeU8(bc, 41) + writeTypeScriptFileExecutionRequest(bc, x.val) + break + } + case "TypeScriptCheckRequest": { + bare.writeU8(bc, 42) + writeTypeScriptCheckRequest(bc, x.val) + break + } + case "TypeScriptProjectCheckRequest": { + bare.writeU8(bc, 43) + writeTypeScriptProjectCheckRequest(bc, x.val) + break + } + case "NpmProjectInstallRequest": { + bare.writeU8(bc, 44) + writeNpmProjectInstallRequest(bc, x.val) + break + } + case "NpmPackageInstallRequest": { + bare.writeU8(bc, 45) + writeNpmPackageInstallRequest(bc, x.val) + break + } + case "NpmScriptExecutionRequest": { + bare.writeU8(bc, 46) + writeNpmScriptExecutionRequest(bc, x.val) + break + } + case "NpmPackageExecutionRequest": { + bare.writeU8(bc, 47) + writeNpmPackageExecutionRequest(bc, x.val) + break + } + case "PythonExecutionRequest": { + bare.writeU8(bc, 48) + writePythonExecutionRequest(bc, x.val) + break + } + case "PythonEvaluationRequest": { + bare.writeU8(bc, 49) + writePythonEvaluationRequest(bc, x.val) + break + } + case "PythonFileExecutionRequest": { + bare.writeU8(bc, 50) + writePythonFileExecutionRequest(bc, x.val) + break + } + case "PythonModuleExecutionRequest": { + bare.writeU8(bc, 51) + writePythonModuleExecutionRequest(bc, x.val) + break + } + case "PythonInstallRequest": { + bare.writeU8(bc, 52) + writePythonInstallRequest(bc, x.val) + break + } + case "GetExecutionRequest": { + bare.writeU8(bc, 53) + writeGetExecutionRequest(bc, x.val) + break + } + case "ListExecutionsRequest": { + bare.writeU8(bc, 54) + break + } + case "WaitExecutionRequest": { + bare.writeU8(bc, 55) + writeWaitExecutionRequest(bc, x.val) + break + } + case "CancelExecutionRequest": { + bare.writeU8(bc, 56) + writeCancelExecutionRequest(bc, x.val) + break + } + case "SignalExecutionRequest": { + bare.writeU8(bc, 57) + writeSignalExecutionRequest(bc, x.val) + break + } + case "ResetExecutionRequest": { + bare.writeU8(bc, 58) + writeResetExecutionRequest(bc, x.val) + break + } + case "DeleteExecutionRequest": { + bare.writeU8(bc, 59) + writeDeleteExecutionRequest(bc, x.val) + break + } + case "WriteExecutionStdinRequest": { + bare.writeU8(bc, 60) + writeWriteExecutionStdinRequest(bc, x.val) + break + } + case "CloseExecutionStdinRequest": { + bare.writeU8(bc, 61) + writeCloseExecutionStdinRequest(bc, x.val) + break + } + case "ResizeExecutionPtyRequest": { + bare.writeU8(bc, 62) + writeResizeExecutionPtyRequest(bc, x.val) + break + } + case "ReadExecutionOutputRequest": { + bare.writeU8(bc, 63) + writeReadExecutionOutputRequest(bc, x.val) + break + } } } @@ -2885,7 +4084,7 @@ export function writeGuestDirEntry(bc: bare.ByteCursor, x: GuestDirEntry): void bare.writeU64(bc, x.size) } -function read27(bc: bare.ByteCursor): readonly GuestDirEntry[] { +function read33(bc: bare.ByteCursor): readonly GuestDirEntry[] { const len = bare.readUintSafe(bc) if (len === 0) { return [] @@ -2897,43 +4096,32 @@ function read27(bc: bare.ByteCursor): readonly GuestDirEntry[] { return result } -function write27(bc: bare.ByteCursor, x: readonly GuestDirEntry[]): void { +function write33(bc: bare.ByteCursor, x: readonly GuestDirEntry[]): void { bare.writeUintSafe(bc, x.length) for (let i = 0; i < x.length; i++) { writeGuestDirEntry(bc, x[i]) } } -function read28(bc: bare.ByteCursor): readonly GuestDirEntry[] | null { - return bare.readBool(bc) ? read27(bc) : null -} - -function write28(bc: bare.ByteCursor, x: readonly GuestDirEntry[] | null): void { - bare.writeBool(bc, x != null) - if (x != null) { - write27(bc, x) - } -} - -function read29(bc: bare.ByteCursor): GuestFilesystemStat | null { - return bare.readBool(bc) ? readGuestFilesystemStat(bc) : null +function read34(bc: bare.ByteCursor): readonly GuestDirEntry[] | null { + return bare.readBool(bc) ? read33(bc) : null } -function write29(bc: bare.ByteCursor, x: GuestFilesystemStat | null): void { +function write34(bc: bare.ByteCursor, x: readonly GuestDirEntry[] | null): void { bare.writeBool(bc, x != null) if (x != null) { - writeGuestFilesystemStat(bc, x) + write33(bc, x) } } -function read30(bc: bare.ByteCursor): boolean | null { - return bare.readBool(bc) ? bare.readBool(bc) : null +function read35(bc: bare.ByteCursor): GuestFilesystemStat | null { + return bare.readBool(bc) ? readGuestFilesystemStat(bc) : null } -function write30(bc: bare.ByteCursor, x: boolean | null): void { +function write35(bc: bare.ByteCursor, x: GuestFilesystemStat | null): void { bare.writeBool(bc, x != null) if (x != null) { - bare.writeBool(bc, x) + writeGuestFilesystemStat(bc, x) } } @@ -2954,9 +4142,9 @@ export function readGuestFilesystemResultResponse(bc: bare.ByteCursor): GuestFil path: bare.readString(bc), content: read0(bc), encoding: read3(bc), - entries: read28(bc), - stat: read29(bc), - exists: read30(bc), + entries: read34(bc), + stat: read35(bc), + exists: read26(bc), target: read0(bc), } } @@ -2966,9 +4154,9 @@ export function writeGuestFilesystemResultResponse(bc: bare.ByteCursor, x: Guest bare.writeString(bc, x.path) write0(bc, x.content) write3(bc, x.encoding) - write28(bc, x.entries) - write29(bc, x.stat) - write30(bc, x.exists) + write34(bc, x.entries) + write35(bc, x.stat) + write26(bc, x.exists) write0(bc, x.target) } @@ -3000,7 +4188,7 @@ export function writeRootFilesystemSnapshotResponse(bc: bare.ByteCursor, x: Root write4(bc, x.entries) } -function read31(bc: bare.ByteCursor): readonly MountInfo[] { +function read36(bc: bare.ByteCursor): readonly MountInfo[] { const len = bare.readUintSafe(bc) if (len === 0) { return [] @@ -3012,7 +4200,7 @@ function read31(bc: bare.ByteCursor): readonly MountInfo[] { return result } -function write31(bc: bare.ByteCursor, x: readonly MountInfo[]): void { +function write36(bc: bare.ByteCursor, x: readonly MountInfo[]): void { bare.writeUintSafe(bc, x.length) for (let i = 0; i < x.length; i++) { writeMountInfo(bc, x[i]) @@ -3025,12 +4213,12 @@ export type ListMountsResponse = { export function readListMountsResponse(bc: bare.ByteCursor): ListMountsResponse { return { - mounts: read31(bc), + mounts: read36(bc), } } export function writeListMountsResponse(bc: bare.ByteCursor, x: ListMountsResponse): void { - write31(bc, x.mounts) + write36(bc, x.mounts) } export type ProcessStartedResponse = { @@ -3155,11 +4343,11 @@ export function writeProcessSnapshotStatus(bc: bare.ByteCursor, x: ProcessSnapsh } } -function read32(bc: bare.ByteCursor): i32 | null { +function read37(bc: bare.ByteCursor): i32 | null { return bare.readBool(bc) ? bare.readI32(bc) : null } -function write32(bc: bare.ByteCursor, x: i32 | null): void { +function write37(bc: bare.ByteCursor, x: i32 | null): void { bare.writeBool(bc, x != null) if (x != null) { bare.writeI32(bc, x) @@ -3192,7 +4380,7 @@ export function readProcessSnapshotEntry(bc: bare.ByteCursor): ProcessSnapshotEn args: read6(bc), cwd: bare.readString(bc), status: readProcessSnapshotStatus(bc), - exitCode: read32(bc), + exitCode: read37(bc), } } @@ -3207,10 +4395,10 @@ export function writeProcessSnapshotEntry(bc: bare.ByteCursor, x: ProcessSnapsho write6(bc, x.args) bare.writeString(bc, x.cwd) writeProcessSnapshotStatus(bc, x.status) - write32(bc, x.exitCode) + write37(bc, x.exitCode) } -function read33(bc: bare.ByteCursor): readonly ProcessSnapshotEntry[] { +function read38(bc: bare.ByteCursor): readonly ProcessSnapshotEntry[] { const len = bare.readUintSafe(bc) if (len === 0) { return [] @@ -3222,7 +4410,7 @@ function read33(bc: bare.ByteCursor): readonly ProcessSnapshotEntry[] { return result } -function write33(bc: bare.ByteCursor, x: readonly ProcessSnapshotEntry[]): void { +function write38(bc: bare.ByteCursor, x: readonly ProcessSnapshotEntry[]): void { bare.writeUintSafe(bc, x.length) for (let i = 0; i < x.length; i++) { writeProcessSnapshotEntry(bc, x[i]) @@ -3235,12 +4423,12 @@ export type ProcessSnapshotResponse = { export function readProcessSnapshotResponse(bc: bare.ByteCursor): ProcessSnapshotResponse { return { - processes: read33(bc), + processes: read38(bc), } } export function writeProcessSnapshotResponse(bc: bare.ByteCursor, x: ProcessSnapshotResponse): void { - write33(bc, x.processes) + write38(bc, x.processes) } export type QueueSnapshotEntry = { @@ -3272,7 +4460,7 @@ export function writeQueueSnapshotEntry(bc: bare.ByteCursor, x: QueueSnapshotEnt bare.writeU64(bc, x.fillPercent) } -function read34(bc: bare.ByteCursor): readonly QueueSnapshotEntry[] { +function read39(bc: bare.ByteCursor): readonly QueueSnapshotEntry[] { const len = bare.readUintSafe(bc) if (len === 0) { return [] @@ -3284,7 +4472,7 @@ function read34(bc: bare.ByteCursor): readonly QueueSnapshotEntry[] { return result } -function write34(bc: bare.ByteCursor, x: readonly QueueSnapshotEntry[]): void { +function write39(bc: bare.ByteCursor, x: readonly QueueSnapshotEntry[]): void { bare.writeUintSafe(bc, x.length) for (let i = 0; i < x.length; i++) { writeQueueSnapshotEntry(bc, x[i]) @@ -3325,7 +4513,7 @@ export function readResourceSnapshotResponse(bc: bare.ByteCursor): ResourceSnaps socketConnections: bare.readU64(bc), socketBufferedBytes: bare.readU64(bc), socketDatagramQueueLen: bare.readU64(bc), - queueSnapshots: read34(bc), + queueSnapshots: read39(bc), } } @@ -3344,7 +4532,7 @@ export function writeResourceSnapshotResponse(bc: bare.ByteCursor, x: ResourceSn bare.writeU64(bc, x.socketConnections) bare.writeU64(bc, x.socketBufferedBytes) bare.writeU64(bc, x.socketDatagramQueueLen) - write34(bc, x.queueSnapshots) + write39(bc, x.queueSnapshots) } export type SocketStateEntry = { @@ -3358,7 +4546,7 @@ export function readSocketStateEntry(bc: bare.ByteCursor): SocketStateEntry { return { processId: bare.readString(bc), host: read0(bc), - port: read26(bc), + port: read27(bc), path: read0(bc), } } @@ -3366,15 +4554,15 @@ export function readSocketStateEntry(bc: bare.ByteCursor): SocketStateEntry { export function writeSocketStateEntry(bc: bare.ByteCursor, x: SocketStateEntry): void { bare.writeString(bc, x.processId) write0(bc, x.host) - write26(bc, x.port) + write27(bc, x.port) write0(bc, x.path) } -function read35(bc: bare.ByteCursor): SocketStateEntry | null { +function read40(bc: bare.ByteCursor): SocketStateEntry | null { return bare.readBool(bc) ? readSocketStateEntry(bc) : null } -function write35(bc: bare.ByteCursor, x: SocketStateEntry | null): void { +function write40(bc: bare.ByteCursor, x: SocketStateEntry | null): void { bare.writeBool(bc, x != null) if (x != null) { writeSocketStateEntry(bc, x) @@ -3387,12 +4575,12 @@ export type ListenerSnapshotResponse = { export function readListenerSnapshotResponse(bc: bare.ByteCursor): ListenerSnapshotResponse { return { - listener: read35(bc), + listener: read40(bc), } } export function writeListenerSnapshotResponse(bc: bare.ByteCursor, x: ListenerSnapshotResponse): void { - write35(bc, x.listener) + write40(bc, x.listener) } export type BoundUdpSnapshotResponse = { @@ -3401,12 +4589,12 @@ export type BoundUdpSnapshotResponse = { export function readBoundUdpSnapshotResponse(bc: bare.ByteCursor): BoundUdpSnapshotResponse { return { - socket: read35(bc), + socket: read40(bc), } } export function writeBoundUdpSnapshotResponse(bc: bare.ByteCursor, x: BoundUdpSnapshotResponse): void { - write35(bc, x.socket) + write40(bc, x.socket) } export enum SignalDispositionAction { @@ -3469,7 +4657,7 @@ export function writeSignalHandlerRegistration(bc: bare.ByteCursor, x: SignalHan bare.writeU32(bc, x.flags) } -function read36(bc: bare.ByteCursor): ReadonlyMap { +function read41(bc: bare.ByteCursor): ReadonlyMap { const len = bare.readUintSafe(bc) const result = new Map() for (let i = 0; i < len; i++) { @@ -3484,7 +4672,7 @@ function read36(bc: bare.ByteCursor): ReadonlyMap): void { +function write41(bc: bare.ByteCursor, x: ReadonlyMap): void { bare.writeUintSafe(bc, x.size) for (const kv of x) { bare.writeU32(bc, kv[0]) @@ -3500,13 +4688,13 @@ export type SignalStateResponse = { export function readSignalStateResponse(bc: bare.ByteCursor): SignalStateResponse { return { processId: bare.readString(bc), - handlers: read36(bc), + handlers: read41(bc), } } export function writeSignalStateResponse(bc: bare.ByteCursor, x: SignalStateResponse): void { bare.writeString(bc, x.processId) - write36(bc, x.handlers) + write41(bc, x.handlers) } export type ZombieTimerCountResponse = { @@ -3630,7 +4818,7 @@ export function readRejectedResponse(bc: bare.ByteCursor): RejectedResponse { capabilityId: read21(bc), operation: read0(bc), configurationPath: read0(bc), - retryable: read30(bc), + retryable: read26(bc), errno: read0(bc), } } @@ -3649,7 +4837,7 @@ export function writeRejectedResponse(bc: bare.ByteCursor, x: RejectedResponse): write21(bc, x.capabilityId) write0(bc, x.operation) write0(bc, x.configurationPath) - write30(bc, x.retryable) + write26(bc, x.retryable) write0(bc, x.errno) } @@ -3667,6 +4855,404 @@ export function writeVmFetchResponse(bc: bare.ByteCursor, x: VmFetchResponse): v bare.writeString(bc, x.responseJson) } +function read42(bc: bare.ByteCursor): RetainedExecutionLanguage | null { + return bare.readBool(bc) ? readRetainedExecutionLanguage(bc) : null +} + +function write42(bc: bare.ByteCursor, x: RetainedExecutionLanguage | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + writeRetainedExecutionLanguage(bc, x) + } +} + +function read43(bc: bare.ByteCursor): ExecutionOutcome | null { + return bare.readBool(bc) ? readExecutionOutcome(bc) : null +} + +function write43(bc: bare.ByteCursor, x: ExecutionOutcome | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + writeExecutionOutcome(bc, x) + } +} + +export type ExecutionDescriptor = { + readonly executionId: string + readonly generation: u64 + readonly state: ExecutionState + readonly retainedLanguage: RetainedExecutionLanguage | null + readonly processId: string | null + readonly pid: u32 | null + readonly createdAtMs: u64 + readonly lastStartedAtMs: u64 | null + readonly lastCompletedAtMs: u64 | null + readonly lastOutcome: ExecutionOutcome | null + readonly lastExitCode: i32 | null +} + +export function readExecutionDescriptor(bc: bare.ByteCursor): ExecutionDescriptor { + return { + executionId: bare.readString(bc), + generation: bare.readU64(bc), + state: readExecutionState(bc), + retainedLanguage: read42(bc), + processId: read0(bc), + pid: read2(bc), + createdAtMs: bare.readU64(bc), + lastStartedAtMs: read21(bc), + lastCompletedAtMs: read21(bc), + lastOutcome: read43(bc), + lastExitCode: read37(bc), + } +} + +export function writeExecutionDescriptor(bc: bare.ByteCursor, x: ExecutionDescriptor): void { + bare.writeString(bc, x.executionId) + bare.writeU64(bc, x.generation) + writeExecutionState(bc, x.state) + write42(bc, x.retainedLanguage) + write0(bc, x.processId) + write2(bc, x.pid) + bare.writeU64(bc, x.createdAtMs) + write21(bc, x.lastStartedAtMs) + write21(bc, x.lastCompletedAtMs) + write43(bc, x.lastOutcome) + write37(bc, x.lastExitCode) +} + +export type ExecutionErrorData = { + readonly code: string + readonly name: string + readonly message: string + readonly stack: string | null + readonly details: JsonUtf8 | null +} + +export function readExecutionErrorData(bc: bare.ByteCursor): ExecutionErrorData { + return { + code: bare.readString(bc), + name: bare.readString(bc), + message: bare.readString(bc), + stack: read0(bc), + details: read32(bc), + } +} + +export function writeExecutionErrorData(bc: bare.ByteCursor, x: ExecutionErrorData): void { + bare.writeString(bc, x.code) + bare.writeString(bc, x.name) + bare.writeString(bc, x.message) + write0(bc, x.stack) + write32(bc, x.details) +} + +export type ExecutionAcceptedResponse = { + readonly execution: ExecutionDescriptor +} + +export function readExecutionAcceptedResponse(bc: bare.ByteCursor): ExecutionAcceptedResponse { + return { + execution: readExecutionDescriptor(bc), + } +} + +export function writeExecutionAcceptedResponse(bc: bare.ByteCursor, x: ExecutionAcceptedResponse): void { + writeExecutionDescriptor(bc, x.execution) +} + +function read44(bc: bare.ByteCursor): ExecutionErrorData | null { + return bare.readBool(bc) ? readExecutionErrorData(bc) : null +} + +function write44(bc: bare.ByteCursor, x: ExecutionErrorData | null): void { + bare.writeBool(bc, x != null) + if (x != null) { + writeExecutionErrorData(bc, x) + } +} + +export type ExecutionCompletedResponse = { + readonly execution: ExecutionDescriptor + readonly outcome: ExecutionOutcome + readonly exitCode: i32 | null + readonly error: ExecutionErrorData | null + readonly stdout: ArrayBuffer + readonly stderr: ArrayBuffer + readonly stdoutTruncated: boolean + readonly stderrTruncated: boolean + readonly outputs: JsonUtf8 +} + +export function readExecutionCompletedResponse(bc: bare.ByteCursor): ExecutionCompletedResponse { + return { + execution: readExecutionDescriptor(bc), + outcome: readExecutionOutcome(bc), + exitCode: read37(bc), + error: read44(bc), + stdout: bare.readData(bc), + stderr: bare.readData(bc), + stdoutTruncated: bare.readBool(bc), + stderrTruncated: bare.readBool(bc), + outputs: readJsonUtf8(bc), + } +} + +export function writeExecutionCompletedResponse(bc: bare.ByteCursor, x: ExecutionCompletedResponse): void { + writeExecutionDescriptor(bc, x.execution) + writeExecutionOutcome(bc, x.outcome) + write37(bc, x.exitCode) + write44(bc, x.error) + bare.writeData(bc, x.stdout) + bare.writeData(bc, x.stderr) + bare.writeBool(bc, x.stdoutTruncated) + bare.writeBool(bc, x.stderrTruncated) + writeJsonUtf8(bc, x.outputs) +} + +export type ExecutionEvaluationResponse = { + readonly result: ExecutionCompletedResponse + readonly value: JsonUtf8 | null +} + +export function readExecutionEvaluationResponse(bc: bare.ByteCursor): ExecutionEvaluationResponse { + return { + result: readExecutionCompletedResponse(bc), + value: read32(bc), + } +} + +export function writeExecutionEvaluationResponse(bc: bare.ByteCursor, x: ExecutionEvaluationResponse): void { + writeExecutionCompletedResponse(bc, x.result) + write32(bc, x.value) +} + +export type TypeScriptDiagnostic = { + readonly code: u32 + readonly category: string + readonly message: string + readonly filePath: string | null + readonly line: u32 | null + readonly column: u32 | null +} + +export function readTypeScriptDiagnostic(bc: bare.ByteCursor): TypeScriptDiagnostic { + return { + code: bare.readU32(bc), + category: bare.readString(bc), + message: bare.readString(bc), + filePath: read0(bc), + line: read2(bc), + column: read2(bc), + } +} + +export function writeTypeScriptDiagnostic(bc: bare.ByteCursor, x: TypeScriptDiagnostic): void { + bare.writeU32(bc, x.code) + bare.writeString(bc, x.category) + bare.writeString(bc, x.message) + write0(bc, x.filePath) + write2(bc, x.line) + write2(bc, x.column) +} + +function read45(bc: bare.ByteCursor): readonly TypeScriptDiagnostic[] { + const len = bare.readUintSafe(bc) + if (len === 0) { + return [] + } + const result = [readTypeScriptDiagnostic(bc)] + for (let i = 1; i < len; i++) { + result[i] = readTypeScriptDiagnostic(bc) + } + return result +} + +function write45(bc: bare.ByteCursor, x: readonly TypeScriptDiagnostic[]): void { + bare.writeUintSafe(bc, x.length) + for (let i = 0; i < x.length; i++) { + writeTypeScriptDiagnostic(bc, x[i]) + } +} + +export type TypeScriptCheckResponse = { + readonly result: ExecutionCompletedResponse + readonly hasErrors: boolean | null + readonly diagnostics: readonly TypeScriptDiagnostic[] +} + +export function readTypeScriptCheckResponse(bc: bare.ByteCursor): TypeScriptCheckResponse { + return { + result: readExecutionCompletedResponse(bc), + hasErrors: read26(bc), + diagnostics: read45(bc), + } +} + +export function writeTypeScriptCheckResponse(bc: bare.ByteCursor, x: TypeScriptCheckResponse): void { + writeExecutionCompletedResponse(bc, x.result) + write26(bc, x.hasErrors) + write45(bc, x.diagnostics) +} + +export type ExecutionDescriptorResponse = { + readonly execution: ExecutionDescriptor +} + +export function readExecutionDescriptorResponse(bc: bare.ByteCursor): ExecutionDescriptorResponse { + return { + execution: readExecutionDescriptor(bc), + } +} + +export function writeExecutionDescriptorResponse(bc: bare.ByteCursor, x: ExecutionDescriptorResponse): void { + writeExecutionDescriptor(bc, x.execution) +} + +function read46(bc: bare.ByteCursor): readonly ExecutionDescriptor[] { + const len = bare.readUintSafe(bc) + if (len === 0) { + return [] + } + const result = [readExecutionDescriptor(bc)] + for (let i = 1; i < len; i++) { + result[i] = readExecutionDescriptor(bc) + } + return result +} + +function write46(bc: bare.ByteCursor, x: readonly ExecutionDescriptor[]): void { + bare.writeUintSafe(bc, x.length) + for (let i = 0; i < x.length; i++) { + writeExecutionDescriptor(bc, x[i]) + } +} + +export type ExecutionListResponse = { + readonly executions: readonly ExecutionDescriptor[] +} + +export function readExecutionListResponse(bc: bare.ByteCursor): ExecutionListResponse { + return { + executions: read46(bc), + } +} + +export function writeExecutionListResponse(bc: bare.ByteCursor, x: ExecutionListResponse): void { + write46(bc, x.executions) +} + +export type ExecutionDeletedResponse = { + readonly executionId: string +} + +export function readExecutionDeletedResponse(bc: bare.ByteCursor): ExecutionDeletedResponse { + return { + executionId: bare.readString(bc), + } +} + +export function writeExecutionDeletedResponse(bc: bare.ByteCursor, x: ExecutionDeletedResponse): void { + bare.writeString(bc, x.executionId) +} + +export type ExecutionIoResponse = { + readonly executionId: string + readonly acceptedBytes: u64 | null +} + +export function readExecutionIoResponse(bc: bare.ByteCursor): ExecutionIoResponse { + return { + executionId: bare.readString(bc), + acceptedBytes: read21(bc), + } +} + +export function writeExecutionIoResponse(bc: bare.ByteCursor, x: ExecutionIoResponse): void { + bare.writeString(bc, x.executionId) + write21(bc, x.acceptedBytes) +} + +export type ExecutionOutputEvent = { + readonly executionId: string + readonly generation: u64 + readonly processId: string | null + readonly sequence: u64 + readonly channel: ExecutionStreamChannel + readonly chunk: ArrayBuffer + readonly timestampMs: u64 +} + +export function readExecutionOutputEvent(bc: bare.ByteCursor): ExecutionOutputEvent { + return { + executionId: bare.readString(bc), + generation: bare.readU64(bc), + processId: read0(bc), + sequence: bare.readU64(bc), + channel: readExecutionStreamChannel(bc), + chunk: bare.readData(bc), + timestampMs: bare.readU64(bc), + } +} + +export function writeExecutionOutputEvent(bc: bare.ByteCursor, x: ExecutionOutputEvent): void { + bare.writeString(bc, x.executionId) + bare.writeU64(bc, x.generation) + write0(bc, x.processId) + bare.writeU64(bc, x.sequence) + writeExecutionStreamChannel(bc, x.channel) + bare.writeData(bc, x.chunk) + bare.writeU64(bc, x.timestampMs) +} + +function read47(bc: bare.ByteCursor): readonly ExecutionOutputEvent[] { + const len = bare.readUintSafe(bc) + if (len === 0) { + return [] + } + const result = [readExecutionOutputEvent(bc)] + for (let i = 1; i < len; i++) { + result[i] = readExecutionOutputEvent(bc) + } + return result +} + +function write47(bc: bare.ByteCursor, x: readonly ExecutionOutputEvent[]): void { + bare.writeUintSafe(bc, x.length) + for (let i = 0; i < x.length; i++) { + writeExecutionOutputEvent(bc, x[i]) + } +} + +export type ExecutionOutputPageResponse = { + readonly executionId: string + readonly generation: u64 + readonly events: readonly ExecutionOutputEvent[] + readonly nextCursor: string + readonly hasMore: boolean + readonly truncated: boolean +} + +export function readExecutionOutputPageResponse(bc: bare.ByteCursor): ExecutionOutputPageResponse { + return { + executionId: bare.readString(bc), + generation: bare.readU64(bc), + events: read47(bc), + nextCursor: bare.readString(bc), + hasMore: bare.readBool(bc), + truncated: bare.readBool(bc), + } +} + +export function writeExecutionOutputPageResponse(bc: bare.ByteCursor, x: ExecutionOutputPageResponse): void { + bare.writeString(bc, x.executionId) + bare.writeU64(bc, x.generation) + write47(bc, x.events) + bare.writeString(bc, x.nextCursor) + bare.writeBool(bc, x.hasMore) + bare.writeBool(bc, x.truncated) +} + export type ResponsePayload = | { readonly tag: "AuthenticatedResponse"; readonly val: AuthenticatedResponse } | { readonly tag: "SessionOpenedResponse"; readonly val: SessionOpenedResponse } @@ -3704,6 +5290,15 @@ export type ResponsePayload = | { readonly tag: "PackageLinkedResponse"; readonly val: PackageLinkedResponse } | { readonly tag: "ProvidedCommandsResponse"; readonly val: ProvidedCommandsResponse } | { readonly tag: "ListMountsResponse"; readonly val: ListMountsResponse } + | { readonly tag: "ExecutionAcceptedResponse"; readonly val: ExecutionAcceptedResponse } + | { readonly tag: "ExecutionCompletedResponse"; readonly val: ExecutionCompletedResponse } + | { readonly tag: "ExecutionEvaluationResponse"; readonly val: ExecutionEvaluationResponse } + | { readonly tag: "TypeScriptCheckResponse"; readonly val: TypeScriptCheckResponse } + | { readonly tag: "ExecutionDescriptorResponse"; readonly val: ExecutionDescriptorResponse } + | { readonly tag: "ExecutionListResponse"; readonly val: ExecutionListResponse } + | { readonly tag: "ExecutionDeletedResponse"; readonly val: ExecutionDeletedResponse } + | { readonly tag: "ExecutionIoResponse"; readonly val: ExecutionIoResponse } + | { readonly tag: "ExecutionOutputPageResponse"; readonly val: ExecutionOutputPageResponse } export function readResponsePayload(bc: bare.ByteCursor): ResponsePayload { const offset = bc.offset @@ -3781,6 +5376,24 @@ export function readResponsePayload(bc: bare.ByteCursor): ResponsePayload { return { tag: "ProvidedCommandsResponse", val: readProvidedCommandsResponse(bc) } case 35: return { tag: "ListMountsResponse", val: readListMountsResponse(bc) } + case 36: + return { tag: "ExecutionAcceptedResponse", val: readExecutionAcceptedResponse(bc) } + case 37: + return { tag: "ExecutionCompletedResponse", val: readExecutionCompletedResponse(bc) } + case 38: + return { tag: "ExecutionEvaluationResponse", val: readExecutionEvaluationResponse(bc) } + case 39: + return { tag: "TypeScriptCheckResponse", val: readTypeScriptCheckResponse(bc) } + case 40: + return { tag: "ExecutionDescriptorResponse", val: readExecutionDescriptorResponse(bc) } + case 41: + return { tag: "ExecutionListResponse", val: readExecutionListResponse(bc) } + case 42: + return { tag: "ExecutionDeletedResponse", val: readExecutionDeletedResponse(bc) } + case 43: + return { tag: "ExecutionIoResponse", val: readExecutionIoResponse(bc) } + case 44: + return { tag: "ExecutionOutputPageResponse", val: readExecutionOutputPageResponse(bc) } default: { bc.offset = offset throw new bare.BareError(offset, "invalid tag") @@ -3970,6 +5583,51 @@ export function writeResponsePayload(bc: bare.ByteCursor, x: ResponsePayload): v writeListMountsResponse(bc, x.val) break } + case "ExecutionAcceptedResponse": { + bare.writeU8(bc, 36) + writeExecutionAcceptedResponse(bc, x.val) + break + } + case "ExecutionCompletedResponse": { + bare.writeU8(bc, 37) + writeExecutionCompletedResponse(bc, x.val) + break + } + case "ExecutionEvaluationResponse": { + bare.writeU8(bc, 38) + writeExecutionEvaluationResponse(bc, x.val) + break + } + case "TypeScriptCheckResponse": { + bare.writeU8(bc, 39) + writeTypeScriptCheckResponse(bc, x.val) + break + } + case "ExecutionDescriptorResponse": { + bare.writeU8(bc, 40) + writeExecutionDescriptorResponse(bc, x.val) + break + } + case "ExecutionListResponse": { + bare.writeU8(bc, 41) + writeExecutionListResponse(bc, x.val) + break + } + case "ExecutionDeletedResponse": { + bare.writeU8(bc, 42) + writeExecutionDeletedResponse(bc, x.val) + break + } + case "ExecutionIoResponse": { + bare.writeU8(bc, 43) + writeExecutionIoResponse(bc, x.val) + break + } + case "ExecutionOutputPageResponse": { + bare.writeU8(bc, 44) + writeExecutionOutputPageResponse(bc, x.val) + break + } } } @@ -4134,6 +5792,32 @@ export function writeProcessExitedEvent(bc: bare.ByteCursor, x: ProcessExitedEve bare.writeI32(bc, x.exitCode) } +export type ExecutionCompletedEvent = { + readonly executionId: string + readonly generation: u64 + readonly outcome: ExecutionOutcome + readonly exitCode: i32 | null + readonly error: ExecutionErrorData | null +} + +export function readExecutionCompletedEvent(bc: bare.ByteCursor): ExecutionCompletedEvent { + return { + executionId: bare.readString(bc), + generation: bare.readU64(bc), + outcome: readExecutionOutcome(bc), + exitCode: read37(bc), + error: read44(bc), + } +} + +export function writeExecutionCompletedEvent(bc: bare.ByteCursor, x: ExecutionCompletedEvent): void { + bare.writeString(bc, x.executionId) + bare.writeU64(bc, x.generation) + writeExecutionOutcome(bc, x.outcome) + write37(bc, x.exitCode) + write44(bc, x.error) +} + export type StructuredEvent = { readonly name: string readonly detail: ReadonlyMap @@ -4157,6 +5841,8 @@ export type EventPayload = | { readonly tag: "ProcessExitedEvent"; readonly val: ProcessExitedEvent } | { readonly tag: "StructuredEvent"; readonly val: StructuredEvent } | { readonly tag: "ExtEnvelope"; readonly val: ExtEnvelope } + | { readonly tag: "ExecutionOutputEvent"; readonly val: ExecutionOutputEvent } + | { readonly tag: "ExecutionCompletedEvent"; readonly val: ExecutionCompletedEvent } export function readEventPayload(bc: bare.ByteCursor): EventPayload { const offset = bc.offset @@ -4172,6 +5858,10 @@ export function readEventPayload(bc: bare.ByteCursor): EventPayload { return { tag: "StructuredEvent", val: readStructuredEvent(bc) } case 4: return { tag: "ExtEnvelope", val: readExtEnvelope(bc) } + case 5: + return { tag: "ExecutionOutputEvent", val: readExecutionOutputEvent(bc) } + case 6: + return { tag: "ExecutionCompletedEvent", val: readExecutionCompletedEvent(bc) } default: { bc.offset = offset throw new bare.BareError(offset, "invalid tag") @@ -4206,6 +5896,16 @@ export function writeEventPayload(bc: bare.ByteCursor, x: EventPayload): void { writeExtEnvelope(bc, x.val) break } + case "ExecutionOutputEvent": { + bare.writeU8(bc, 5) + writeExecutionOutputEvent(bc, x.val) + break + } + case "ExecutionCompletedEvent": { + bare.writeU8(bc, 6) + writeExecutionCompletedEvent(bc, x.val) + break + } } } @@ -4340,17 +6040,6 @@ export function writeSidecarRequestFrame(bc: bare.ByteCursor, x: SidecarRequestF writeSidecarRequestPayload(bc, x.payload) } -function read37(bc: bare.ByteCursor): JsonUtf8 | null { - return bare.readBool(bc) ? readJsonUtf8(bc) : null -} - -function write37(bc: bare.ByteCursor, x: JsonUtf8 | null): void { - bare.writeBool(bc, x != null) - if (x != null) { - writeJsonUtf8(bc, x) - } -} - export type HostCallbackResultResponse = { readonly invocationId: string readonly result: JsonUtf8 | null @@ -4360,14 +6049,14 @@ export type HostCallbackResultResponse = { export function readHostCallbackResultResponse(bc: bare.ByteCursor): HostCallbackResultResponse { return { invocationId: bare.readString(bc), - result: read37(bc), + result: read32(bc), error: read0(bc), } } export function writeHostCallbackResultResponse(bc: bare.ByteCursor, x: HostCallbackResultResponse): void { bare.writeString(bc, x.invocationId) - write37(bc, x.result) + write32(bc, x.result) write0(bc, x.error) } @@ -4380,14 +6069,14 @@ export type JsBridgeResultResponse = { export function readJsBridgeResultResponse(bc: bare.ByteCursor): JsBridgeResultResponse { return { callId: bare.readString(bc), - result: read37(bc), + result: read32(bc), error: read0(bc), } } export function writeJsBridgeResultResponse(bc: bare.ByteCursor, x: JsBridgeResultResponse): void { bare.writeString(bc, x.callId) - write37(bc, x.result) + write32(bc, x.result) write0(bc, x.error) } diff --git a/packages/runtime-core/src/kernel-proxy.ts b/packages/runtime-core/src/kernel-proxy.ts index 92d569b6f0..3422edf366 100644 --- a/packages/runtime-core/src/kernel-proxy.ts +++ b/packages/runtime-core/src/kernel-proxy.ts @@ -74,7 +74,7 @@ export function serializeMountConfigForSidecar( const SYNTHETIC_PID_BASE = 1_000_000; const MISSING_EXIT_EVENT_GRACE_MS = 500; -const PROTECTED_READ_ONLY_GUEST_ROOTS = ["/etc/secure-exec"] as const; +const PROTECTED_READ_ONLY_GUEST_ROOTS = ["/etc/agentos"] as const; const TRAILING_OUTPUT_DRAIN_INTERVAL_MS = 10; const TRAILING_OUTPUT_DRAIN_MAX_MS = 250; const TRAILING_OUTPUT_DRAIN_QUIET_TURNS = 2; diff --git a/packages/runtime-core/src/node-runtime.ts b/packages/runtime-core/src/node-runtime.ts index daead327d4..1114af3eb0 100644 --- a/packages/runtime-core/src/node-runtime.ts +++ b/packages/runtime-core/src/node-runtime.ts @@ -76,7 +76,7 @@ const REPO_COMMANDS_DIR = path.join( /** * Commands vendored into the published `@rivet-dev/agentos-runtime-core` package by * `scripts/copy-wasm-commands.mjs` (listed in `files` as `commands`). This is - * the directory a real `npm install secure-exec` resolves: from the compiled + * the directory a real `npm install agentos` resolves: from the compiled * `dist/node-runtime.js` it sits at `/commands`. This is the analogue * of how the sidecar binary ships inside `@rivet-dev/agentos-runtime-sidecar`. */ @@ -708,7 +708,7 @@ export class NodeRuntime { code: string, options: NodeRuntimeExecOptions = {}, ): Promise { - const programPath = `/tmp/secure-exec-program-${nextProgramId++}.mjs`; + const programPath = `/tmp/agentos-program-${nextProgramId++}.mjs`; await this.kernel.writeFile(programPath, withBindingPreamble(code)); return this.runProgram(programPath, options); } @@ -827,7 +827,7 @@ export class NodeRuntime { code: string, options: NodeRuntimeSpawnOptions = {}, ): Promise { - const programPath = `/tmp/secure-exec-program-${nextProgramId++}.mjs`; + const programPath = `/tmp/agentos-program-${nextProgramId++}.mjs`; await this.kernel.writeFile(programPath, withBindingPreamble(code)); const proc = this.kernel.spawn("node", [programPath], { env: options.env, @@ -955,8 +955,8 @@ export class NodeRuntime { options: NodeRuntimeExecOptions = {}, ): Promise> { const id = nextProgramId++; - const resultPath = `/tmp/secure-exec-result-${id}.json`; - const programPath = `/tmp/secure-exec-program-${id}.mjs`; + const resultPath = `/tmp/agentos-result-${id}.json`; + const programPath = `/tmp/agentos-program-${id}.mjs`; // Inject the __return helper as a module-level preamble, then the user // code at module top level. Import declarations (preamble's and the // user's) are hoisted, so __return is defined before the user's diff --git a/packages/runtime-core/src/request-payloads.ts b/packages/runtime-core/src/request-payloads.ts index 80c32b869f..b53c680cff 100644 --- a/packages/runtime-core/src/request-payloads.ts +++ b/packages/runtime-core/src/request-payloads.ts @@ -238,6 +238,81 @@ export type LiveRequestPayload = key: string; payload_size_bytes: number; } + | { type: "shell_execution"; request: protocol.ShellExecutionRequest } + | { type: "argv_execution"; request: protocol.ArgvExecutionRequest } + | { + type: "javascript_execution"; + request: protocol.JavaScriptExecutionRequest; + } + | { + type: "javascript_evaluation"; + request: protocol.JavaScriptEvaluationRequest; + } + | { + type: "javascript_file_execution"; + request: protocol.JavaScriptFileExecutionRequest; + } + | { + type: "typescript_execution"; + request: protocol.TypeScriptExecutionRequest; + } + | { + type: "typescript_evaluation"; + request: protocol.TypeScriptEvaluationRequest; + } + | { + type: "typescript_file_execution"; + request: protocol.TypeScriptFileExecutionRequest; + } + | { type: "typescript_check"; request: protocol.TypeScriptCheckRequest } + | { + type: "typescript_project_check"; + request: protocol.TypeScriptProjectCheckRequest; + } + | { type: "npm_project_install"; request: protocol.NpmProjectInstallRequest } + | { type: "npm_package_install"; request: protocol.NpmPackageInstallRequest } + | { + type: "npm_script_execution"; + request: protocol.NpmScriptExecutionRequest; + } + | { + type: "npm_package_execution"; + request: protocol.NpmPackageExecutionRequest; + } + | { type: "python_execution"; request: protocol.PythonExecutionRequest } + | { type: "python_evaluation"; request: protocol.PythonEvaluationRequest } + | { + type: "python_file_execution"; + request: protocol.PythonFileExecutionRequest; + } + | { + type: "python_module_execution"; + request: protocol.PythonModuleExecutionRequest; + } + | { type: "python_install"; request: protocol.PythonInstallRequest } + | { type: "get_execution"; request: protocol.GetExecutionRequest } + | { type: "list_executions" } + | { type: "wait_execution"; request: protocol.WaitExecutionRequest } + | { type: "cancel_execution"; request: protocol.CancelExecutionRequest } + | { type: "signal_execution"; request: protocol.SignalExecutionRequest } + | { type: "reset_execution"; request: protocol.ResetExecutionRequest } + | { type: "delete_execution"; request: protocol.DeleteExecutionRequest } + | { + type: "write_execution_stdin"; + request: protocol.WriteExecutionStdinRequest; + } + | { + type: "close_execution_stdin"; + request: protocol.CloseExecutionStdinRequest; + } + | { + type: "resize_execution_pty"; + request: protocol.ResizeExecutionPtyRequest; + } + | { + type: "read_execution_output"; + request: protocol.ReadExecutionOutputRequest; + } | { type: "ext"; envelope: LiveExtEnvelope; @@ -522,6 +597,66 @@ export function toGeneratedRequestPayload( payloadSizeBytes: BigInt(payload.payload_size_bytes), }, }; + case "shell_execution": + return { tag: "ShellExecutionRequest", val: payload.request }; + case "argv_execution": + return { tag: "ArgvExecutionRequest", val: payload.request }; + case "javascript_execution": + return { tag: "JavaScriptExecutionRequest", val: payload.request }; + case "javascript_evaluation": + return { tag: "JavaScriptEvaluationRequest", val: payload.request }; + case "javascript_file_execution": + return { tag: "JavaScriptFileExecutionRequest", val: payload.request }; + case "typescript_execution": + return { tag: "TypeScriptExecutionRequest", val: payload.request }; + case "typescript_evaluation": + return { tag: "TypeScriptEvaluationRequest", val: payload.request }; + case "typescript_file_execution": + return { tag: "TypeScriptFileExecutionRequest", val: payload.request }; + case "typescript_check": + return { tag: "TypeScriptCheckRequest", val: payload.request }; + case "typescript_project_check": + return { tag: "TypeScriptProjectCheckRequest", val: payload.request }; + case "npm_project_install": + return { tag: "NpmProjectInstallRequest", val: payload.request }; + case "npm_package_install": + return { tag: "NpmPackageInstallRequest", val: payload.request }; + case "npm_script_execution": + return { tag: "NpmScriptExecutionRequest", val: payload.request }; + case "npm_package_execution": + return { tag: "NpmPackageExecutionRequest", val: payload.request }; + case "python_execution": + return { tag: "PythonExecutionRequest", val: payload.request }; + case "python_evaluation": + return { tag: "PythonEvaluationRequest", val: payload.request }; + case "python_file_execution": + return { tag: "PythonFileExecutionRequest", val: payload.request }; + case "python_module_execution": + return { tag: "PythonModuleExecutionRequest", val: payload.request }; + case "python_install": + return { tag: "PythonInstallRequest", val: payload.request }; + case "get_execution": + return { tag: "GetExecutionRequest", val: payload.request }; + case "list_executions": + return { tag: "ListExecutionsRequest", val: null }; + case "wait_execution": + return { tag: "WaitExecutionRequest", val: payload.request }; + case "cancel_execution": + return { tag: "CancelExecutionRequest", val: payload.request }; + case "signal_execution": + return { tag: "SignalExecutionRequest", val: payload.request }; + case "reset_execution": + return { tag: "ResetExecutionRequest", val: payload.request }; + case "delete_execution": + return { tag: "DeleteExecutionRequest", val: payload.request }; + case "write_execution_stdin": + return { tag: "WriteExecutionStdinRequest", val: payload.request }; + case "close_execution_stdin": + return { tag: "CloseExecutionStdinRequest", val: payload.request }; + case "resize_execution_pty": + return { tag: "ResizeExecutionPtyRequest", val: payload.request }; + case "read_execution_output": + return { tag: "ReadExecutionOutputRequest", val: payload.request }; case "ext": return { tag: "ExtEnvelope", diff --git a/packages/runtime-core/src/response-payloads.ts b/packages/runtime-core/src/response-payloads.ts index ba7c6fd44e..5de0982e66 100644 --- a/packages/runtime-core/src/response-payloads.ts +++ b/packages/runtime-core/src/response-payloads.ts @@ -264,6 +264,27 @@ export type LiveResponsePayload = retryable: boolean | null; errno: string | null; } + | { type: "execution_accepted"; response: protocol.ExecutionAcceptedResponse } + | { + type: "execution_completed"; + response: protocol.ExecutionCompletedResponse; + } + | { + type: "execution_evaluation"; + response: protocol.ExecutionEvaluationResponse; + } + | { type: "typescript_check"; response: protocol.TypeScriptCheckResponse } + | { + type: "execution_descriptor"; + response: protocol.ExecutionDescriptorResponse; + } + | { type: "execution_list"; response: protocol.ExecutionListResponse } + | { type: "execution_deleted"; response: protocol.ExecutionDeletedResponse } + | { type: "execution_io"; response: protocol.ExecutionIoResponse } + | { + type: "execution_output_page"; + response: protocol.ExecutionOutputPageResponse; + } | { type: "ext_result"; envelope: LiveExtEnvelope; @@ -625,6 +646,24 @@ export function fromGeneratedResponsePayload( type: "ext_result", envelope: fromGeneratedExtEnvelope(payload.val), }; + case "ExecutionAcceptedResponse": + return { type: "execution_accepted", response: payload.val }; + case "ExecutionCompletedResponse": + return { type: "execution_completed", response: payload.val }; + case "ExecutionEvaluationResponse": + return { type: "execution_evaluation", response: payload.val }; + case "TypeScriptCheckResponse": + return { type: "typescript_check", response: payload.val }; + case "ExecutionDescriptorResponse": + return { type: "execution_descriptor", response: payload.val }; + case "ExecutionListResponse": + return { type: "execution_list", response: payload.val }; + case "ExecutionDeletedResponse": + return { type: "execution_deleted", response: payload.val }; + case "ExecutionIoResponse": + return { type: "execution_io", response: payload.val }; + case "ExecutionOutputPageResponse": + return { type: "execution_output_page", response: payload.val }; } } diff --git a/packages/runtime-core/src/sidecar-process.ts b/packages/runtime-core/src/sidecar-process.ts index 913bce87ea..e8ecfc03d3 100644 --- a/packages/runtime-core/src/sidecar-process.ts +++ b/packages/runtime-core/src/sidecar-process.ts @@ -38,7 +38,10 @@ import { type ProtocolFramePayloadCodec, } from "./protocol-frames.js"; import { type LiveRequestPayload } from "./request-payloads.js"; -import type { LiveGuestDirEntry } from "./response-payloads.js"; +import type { + LiveGuestDirEntry, + LiveResponsePayload, +} from "./response-payloads.js"; import { type LiveGuestFilesystemStat, type LiveProcessSnapshotEntry, @@ -370,7 +373,8 @@ export class SidecarProcess { silenceTimeoutMs: options.silenceTimeoutMs, eventBufferCapacity: options.eventBufferCapacity ?? DEFAULT_SIDECAR_EVENT_BUFFER_CAPACITY, - gracefulExitMs: options.gracefulExitMs ?? DEFAULT_SIDECAR_GRACEFUL_EXIT_MS, + gracefulExitMs: + options.gracefulExitMs ?? DEFAULT_SIDECAR_GRACEFUL_EXIT_MS, forceExitMs: options.forceExitMs ?? DEFAULT_SIDECAR_FORCE_EXIT_MS, disposedErrorMessage: "native sidecar disposed", payloadCodec: options.payloadCodec ?? "bare", @@ -396,8 +400,8 @@ export class SidecarProcess { }, payload: { type: "authenticate", - client_name: "secure-exec-core-client", - auth_token: "secure-exec-core-client-token", + client_name: "agentos-core-client", + auth_token: "agentos-core-client-token", protocol_version: SIDECAR_PROTOCOL_SCHEMA.version, bridge_version: BRIDGE_CONTRACT_VERSION, }, @@ -865,7 +869,9 @@ export class SidecarProcess { payload: { type: "list_mounts" }, }); if (response.payload.type !== "mounts_listed") { - throw new Error(`unexpected list_mounts response: ${response.payload.type}`); + throw new Error( + `unexpected list_mounts response: ${response.payload.type}`, + ); } return response.payload.mounts.map((mount) => ({ path: mount.path, @@ -1685,6 +1691,24 @@ export class SidecarProcess { return await this.protocolClient.waitForEvent(matcher, timeoutMs, options); } + /** Internal semantic request entrypoint used by the AgentOS client surface. */ + async sendVmRequest( + session: AuthenticatedSession, + vm: CreatedVm, + payload: LiveRequestPayload, + ): Promise { + const response = await this.sendRequest({ + ownership: { + scope: "vm", + connection_id: session.connectionId, + session_id: session.sessionId, + vm_id: vm.vmId, + }, + payload, + }); + return response.payload; + } + async dispose(): Promise { await this.protocolClient.dispose(); } diff --git a/packages/runtime-core/src/test-runtime.ts b/packages/runtime-core/src/test-runtime.ts index 3b8dd14fb7..8ca174cce0 100644 --- a/packages/runtime-core/src/test-runtime.ts +++ b/packages/runtime-core/src/test-runtime.ts @@ -1938,7 +1938,7 @@ class WasmVmRuntimeDescriptor implements KernelRuntimeDriver { } guestPaths.set( name, - `/__secure_exec/commands/${startIndex + dirOffset}/${name}`, + `/__agentos/commands/${startIndex + dirOffset}/${name}`, ); } return guestPaths; @@ -2360,7 +2360,7 @@ function collectGuestCommandPaths( if (!guestPaths.has(entry.name)) { guestPaths.set( entry.name, - `/__secure_exec/commands/${startIndex + entry.dirOffset}/${entry.name}`, + `/__agentos/commands/${startIndex + entry.dirOffset}/${entry.name}`, ); } } @@ -2890,7 +2890,7 @@ class NativeKernel implements Kernel { const allCommandDirs = [...this.mountedCommandDirs, ...commandDirs]; const sidecarMounts = allCommandDirs.map((commandDir, index) => serializeMountConfigForSidecar({ - path: `/__secure_exec/commands/${index}`, + path: `/__agentos/commands/${index}`, readOnly: true, plugin: { id: "host_dir", diff --git a/packages/runtime-core/tests/integration/bridge-child-process.nightly.test.ts b/packages/runtime-core/tests/integration/bridge-child-process.nightly.test.ts index 97bc565c4b..fdb692714b 100644 --- a/packages/runtime-core/tests/integration/bridge-child-process.nightly.test.ts +++ b/packages/runtime-core/tests/integration/bridge-child-process.nightly.test.ts @@ -713,7 +713,7 @@ describeIf( it("execFileSync on node_modules/.bin shell shims unwraps to the node entrypoint", async () => { const projectRoot = mkdtempSync( - join(tmpdir(), "secure-exec-node-bin-shim-"), + join(tmpdir(), "agentos-node-bin-shim-"), ); cleanupPaths.push(projectRoot); @@ -785,7 +785,7 @@ describeIf( it("execFileSync dereferences node_modules/.bin main-module symlinks", async () => { const projectRoot = mkdtempSync( - join(tmpdir(), "secure-exec-node-bin-symlink-"), + join(tmpdir(), "agentos-node-bin-symlink-"), ); cleanupPaths.push(projectRoot); @@ -853,7 +853,7 @@ describeIf( it("execFileSync unwraps shell shims whose node entrypoint has no shebang or extension", async () => { const projectRoot = mkdtempSync( - join(tmpdir(), "secure-exec-node-bin-shim-no-shebang-"), + join(tmpdir(), "agentos-node-bin-shim-no-shebang-"), ); cleanupPaths.push(projectRoot); diff --git a/packages/runtime-core/tests/integration/projects/developer-clis-pass/src/index.js b/packages/runtime-core/tests/integration/projects/developer-clis-pass/src/index.js index 865e9a86f7..001aa44cbf 100644 --- a/packages/runtime-core/tests/integration/projects/developer-clis-pass/src/index.js +++ b/packages/runtime-core/tests/integration/projects/developer-clis-pass/src/index.js @@ -103,8 +103,8 @@ module.exports = { await mkdir(path.join(monorepo, "packages", "a"), { recursive: true }); await mkdir(path.join(monorepo, "packages", "b"), { recursive: true }); await writeFile(path.join(monorepo, "package.json"), `${JSON.stringify({ name: "agentos-cli-monorepo", version: "1.0.0", private: true, packageManager: "pnpm@11.15.0", workspaces: ["packages/*"] }, null, 2)}\n`); - await writeFile(path.join(monorepo, "packages", "a", "package.json"), "{\"name\":\"@agentos/a\",\"version\":\"1.0.0\"}\n"); - await writeFile(path.join(monorepo, "packages", "b", "package.json"), "{\"name\":\"@agentos/b\",\"version\":\"1.0.0\"}\n"); + await writeFile(path.join(monorepo, "packages", "a", "package.json"), "{\"name\":\"@fixture/a\",\"version\":\"1.0.0\"}\n"); + await writeFile(path.join(monorepo, "packages", "b", "package.json"), "{\"name\":\"@fixture/b\",\"version\":\"1.0.0\"}\n"); await execFileAsync(process.execPath, [require.resolve("@manypkg/cli"), "check"], { cwd: monorepo, env: { ...process.env, CI: "1", NO_COLOR: "1", FORCE_COLOR: "0" }, diff --git a/packages/runtime-core/tests/integration/projects/rivetkit/.pnpmfile.cjs b/packages/runtime-core/tests/integration/projects/rivetkit/.pnpmfile.cjs new file mode 100644 index 0000000000..5fdcdd5e63 --- /dev/null +++ b/packages/runtime-core/tests/integration/projects/rivetkit/.pnpmfile.cjs @@ -0,0 +1,12 @@ +const PINNED_RIVETKIT_VERSION = "0.0.0-sqlite-uds.4e59a38"; + +module.exports = { + hooks: { + readPackage(pkg) { + if (pkg.name === "rivetkit" && pkg.version === PINNED_RIVETKIT_VERSION) { + delete pkg.dependencies?.["@rivet-dev/agent-os-core"]; + } + return pkg; + }, + }, +}; diff --git a/packages/runtime-core/tests/integration/projects/rivetkit/package.json b/packages/runtime-core/tests/integration/projects/rivetkit/package.json index 6ae5ce94ef..16ceebb448 100644 --- a/packages/runtime-core/tests/integration/projects/rivetkit/package.json +++ b/packages/runtime-core/tests/integration/projects/rivetkit/package.json @@ -3,6 +3,6 @@ "private": true, "type": "module", "dependencies": { - "rivetkit": "2.3.4" + "rivetkit": "0.0.0-sqlite-uds.4e59a38" } } diff --git a/packages/runtime-core/tests/integration/projects/rivetkit/pnpm-lock.yaml b/packages/runtime-core/tests/integration/projects/rivetkit/pnpm-lock.yaml index 30b4f9226b..ca511c7382 100644 --- a/packages/runtime-core/tests/integration/projects/rivetkit/pnpm-lock.yaml +++ b/packages/runtime-core/tests/integration/projects/rivetkit/pnpm-lock.yaml @@ -4,13 +4,15 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +pnpmfileChecksum: sha256-US3jzAV8R7azjMsy2waowmY2OhX06rMtgR1bwKXvwtE= + importers: .: dependencies: rivetkit: - specifier: 2.3.4 - version: 2.3.4(better-sqlite3@12.11.1) + specifier: 0.0.0-sqlite-uds.4e59a38 + version: 0.0.0-sqlite-uds.4e59a38 packages: @@ -49,162 +51,6 @@ packages: cpu: [x64] os: [win32] - '@esbuild/aix-ppc64@0.27.7': - resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.27.7': - resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.27.7': - resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.27.7': - resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.27.7': - resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.27.7': - resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.27.7': - resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.27.7': - resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.27.7': - resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.27.7': - resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.27.7': - resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.27.7': - resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.27.7': - resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.27.7': - resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.27.7': - resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.27.7': - resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.27.7': - resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.27.7': - resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.27.7': - resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.27.7': - resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.27.7': - resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.27.7': - resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.27.7': - resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.27.7': - resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.27.7': - resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.27.7': - resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@hono/zod-openapi@1.5.1': resolution: {integrity: sha512-ZaDdEIkn6PEGjIYHXJeyByg6yhvLzI+UXn968pWtahpwcQ6HMjQYXI3zNffTl0Wl9QZ79nUnGqiN1erEIu23fA==} engines: {node: '>=16.0.0'} @@ -226,237 +72,106 @@ packages: '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} - '@rivet-dev/agent-os-core@0.1.1': - resolution: {integrity: sha512-Uw5jr+gUXDY7TDUFqlypjGe1BD2KL9kTHPNo/f1iNS1R+l9IWuvT+FF/MXsLOEkc3fB06OPVu2ZvUuNwp9MpLQ==} - - '@rivet-dev/agent-os-posix@0.1.0': - resolution: {integrity: sha512-NIrI7cCb9x6jdmzRPPx7dAeXoTF/YCqf93ydEzYFA2zshIelLW9Rp5KtgP/2hM6fP0ly4+vVnOeavxJW0wYtcA==} - - '@rivet-dev/agent-os-python@0.1.0': - resolution: {integrity: sha512-1tH1beMf1ceSpicQKwN/a6h+NmJrmfuT4GStiRDZmvN/UWfZhkxuy7HR5VPTQpE/feUZJ01FdtBS3Em/Qoxb2Q==} - peerDependencies: - pyodide: '>=0.28.0' - peerDependenciesMeta: - pyodide: - optional: true - '@rivetkit/bare-ts@0.6.2': resolution: {integrity: sha512-3qndQUQXLdwafMEqfhz24hUtDPcsf1Bu3q52Kb8MqeH8JUh3h6R4HYW3ZJXiQsLcyYyFM68PuIwlLRlg1xDEpg==} engines: {node: ^14.18.0 || >=16.0.0} - '@rivetkit/engine-cli-darwin-arm64@2.3.4': - resolution: {integrity: sha512-ssRb48PGIQ47qvraF+xjeypigFqMtDK7LNHcIjvtojl7rx0/T4JUmJnouurQaPCu/Ay8XgalOAcyjCrDaKUJVA==} + '@rivetkit/engine-cli-darwin-arm64@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-ZT+wqmQzLznezyYVTzRHckWbp7F4yOG3ZCCON+ErdnWd84A4mwJMYXZPIObGD2OVSxmNhWqXO1ocNTKwDsIllw==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [darwin] - '@rivetkit/engine-cli-darwin-x64@2.3.4': - resolution: {integrity: sha512-X6wsfv6FY9OpxRVMZIG9RUX+rG9HGddMAtZOWRvwBuY3+MfuEE1U5gpFVHN7MCcbao3mmBRj2fIWFXx5LKoNMA==} + '@rivetkit/engine-cli-darwin-x64@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-PgiKyvhciN17C7RjyB9J9ApVkCTJmdyaRZnsSmy0xdbNY12uKrhH2mNcaQAPV+7/QB4HB4TjVgD1wT+PCCGiQg==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [darwin] - '@rivetkit/engine-cli-linux-arm64-musl@2.3.4': - resolution: {integrity: sha512-6zVTXPrn/95xS/JRHZ1sfhwOEvMS5iE+1YWQGR/bHtlLYmF9ZhtoCngQoI7mNJsspq9QE88x2mlGV470UFIFyQ==} + '@rivetkit/engine-cli-linux-arm64-musl@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-2FZhrpzYfNIId3Tn0wpz1klcoKZjf2NBzGkmdxGQKY0kh7XynBsZxUnqyHJVFAkfLSSW+1t8E6PLTMSfPHIKXQ==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [linux] - '@rivetkit/engine-cli-linux-x64-musl@2.3.4': - resolution: {integrity: sha512-9qfRJ9t7ZFQQZtv5EIry9kMu+d/Rbapzy+V8XS5pqgPOkGPjVyGP2CwpaLJsh1nMSu+u4OS9HTf6134qj/eGaw==} + '@rivetkit/engine-cli-linux-x64-musl@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-iw3v07nBtc1+qiQxl/g3HPT9UPOJUidvOYixPpxtydaRqh465/6pYy8cTzQOhEKBodBD3drsaB+6GJwDLy8CMA==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [linux] - '@rivetkit/engine-cli-win32-x64@2.3.4': - resolution: {integrity: sha512-qahxiLiW7dnO4LtmKpiLUgq+0Bx+ypvJKxFIeyERZVBZeq53LYAw/eTIHRicyfgUMdlymbgTJKVBfbEd/QlbMg==} - engines: {node: '>= 20.0.0'} - cpu: [x64] - os: [win32] - - '@rivetkit/engine-cli@2.3.4': - resolution: {integrity: sha512-i+bGMloDq4iE24XNanJG4d/vvu1fZ7DQXE70HlW8s/fcLOaMALgfuyrGYCcnX5a1S8ukjq25h2ZafILK/pxnWw==} + '@rivetkit/engine-cli@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-5WYBHyO4Yudb2RuVbbp2srb/XDbEAdTihxUj/aUerahalR3KiNDo5zpUZpfhhoAQrjPQTVTN9Nan/RVloVpFRg==} engines: {node: '>= 20.0.0'} - '@rivetkit/engine-envoy-protocol@2.3.4': - resolution: {integrity: sha512-YHLWsCIKT6bKVuZ3Db/M+Yu7w2aGkdB9bCZvKi6DQNuSoCy9m0PBLbhtRkqb6vsxvmni7qVPyeZrLGKPeB5ETQ==} + '@rivetkit/engine-envoy-protocol@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-asUWA8E+fyD1RLQ5wH6KhCTNZ3laAqqS2bZQkcMQS8mQn/9BVl+sfCm/yM3hLK7lH7WT616sJhcP86EktZCLsA==} '@rivetkit/on-change@6.0.1': resolution: {integrity: sha512-QBN/KRBXLJdCgN4gBTL3XAc/zKm58atSnieXWMOyFSPmo6F1/yIVV/LTRdvAktfCttrGx7W6c32i/lwqCHWnsQ==} engines: {node: '>=20'} - '@rivetkit/rivetkit-napi-darwin-arm64@2.3.4': - resolution: {integrity: sha512-kxsS/fSJ5VERdNaFuNdRQp2gCQCI41I+Hj41jLP4jMnzjWhwRhKmVmBN1YxyVTDcmVHDGZLSwCp3sSJYHvsVKQ==} + '@rivetkit/rivetkit-napi-darwin-arm64@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-sH/wB5IvlDQ7lktL7lk/1h5K8/Rxm/UYyY8GKGOdPzgIhBK7RNE194vhlLLgjWCU2P5eTo/uG8U5n7Shw1VoBA==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [darwin] - '@rivetkit/rivetkit-napi-darwin-x64@2.3.4': - resolution: {integrity: sha512-DthpCVZ6eJTkjQ5QpTyM1Dh8h0JffNUHsYb4huO7EpO3/XC1gZl/SmUSbtmOl1/YcawMofD7bCFbJwdG/W0N0g==} + '@rivetkit/rivetkit-napi-darwin-x64@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-E8Lt44QIOjzNnrFDWALpIFn3p593l57Y7z5mmY4oK0xScJlw8hL6jn0ISvCA1BRd0wPTy5/fwCUxGAivhhVJAg==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [darwin] - '@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.4': - resolution: {integrity: sha512-X63Bv0YqbMCgHUBQ5bqm5qiggYAB4d/+5nueqtFBTqQvnVSM2oJy8rLtdjwlKjNNBS9EFY6gckAhSyP/jih1vg==} + '@rivetkit/rivetkit-napi-linux-arm64-gnu@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-xdFAuc0s8tj6p63zeY/IoS0JKtnmTh6RyOauy+8cptTzGDUXcQnuzQU28YjPJ535je7aGIlJYfSXhL/rd4kmZA==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [linux] - '@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.4': - resolution: {integrity: sha512-iYT0F37FhAbTf/mqVl0Da3o1Wubmo99qXxdppGluy2Cijwj9sQswSm5Dd50oBRH3aOY/bja3twITxvCtzHPlBg==} + '@rivetkit/rivetkit-napi-linux-arm64-musl@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-W6gTRHX1Sx9Oi2KoPpEN1fENEkF/dqvpc5OqNJErCcW8M2WCB/0BU/c7nHsP54ZLzS0kcZtaQov6qw0Nt2eaWA==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [linux] - '@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.4': - resolution: {integrity: sha512-p8SCYiw+9vj8CMa/Sgfn7V/ebQ3o+PBHfS7gK/k85jDA6u8Qs1Xxb3j76tniKwbpLnXE8cdkeiJdkEfE7oHskg==} + '@rivetkit/rivetkit-napi-linux-x64-gnu@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-BY8SZke/5iHh35rFrkJ+GkmMelezHaIrClxjpZ6a3Yfu4owAfOUCOSTHZttYAoba4EdnCpB8aTQ2SimtvNN77g==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [linux] - '@rivetkit/rivetkit-napi-linux-x64-musl@2.3.4': - resolution: {integrity: sha512-jZJfqqkFPkaQotXmz/N8Lk/ZtSSlzX3EuBaFGie+TVL32Z4XMPJMruwE+KwwXgnUYkauiWEjByzYBuU3Kf/oGQ==} + '@rivetkit/rivetkit-napi-linux-x64-musl@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-rxtzRH2hpaz8hx6F1GIIM7f0FpDzyBKNtmusDQswmYajkm/Hfxl9ha2bleHg6EFtNVAr8gQ9cHAZcAv583bAJw==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [linux] - '@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.4': - resolution: {integrity: sha512-J1VvCOMDqvEiUtmhhDgR0eBMCen42IVMPoyIPBJWnUF2Hkm9Ld+NB6DdN19h+U5u+/EwLSCgwrxewxTkNCnf0g==} - engines: {node: '>= 20.0.0'} - cpu: [x64] - os: [win32] - - '@rivetkit/rivetkit-napi@2.3.4': - resolution: {integrity: sha512-EKO533N+0yv4gXK5U75DncV3ubIG/32yIFCeTA6DZZsV+MjFvc+Aj/ojNlja00whJ1OBbKvf0fUGXlHJJxxMjA==} + '@rivetkit/rivetkit-napi@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-0SibmwqUugIfgRdwuG45+SvjMLzk5Bim/cViOtnt2FrucNB1E/YeC7QD4MxMi/Z+z+M/A33dljUst70C2f5uVA==} engines: {node: '>= 20.0.0'} - '@rivetkit/rivetkit-wasm@2.3.4': - resolution: {integrity: sha512-NWza+AJ6cHk7QhZ8nK4E3ejL7OwRKEEfH7h1+xfSgcn548zgOU1TkQMLcLMn+FkypukJdFv8tEON0rxmf53RqQ==} + '@rivetkit/rivetkit-wasm@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-jWMHRJjPU0IPjVmv7kmfpt3wh3ThYOMETsKEg9QU3QupRKANRltkSRZp9Km34kUzzsyKQcqiidmWavYmn61egA==} - '@rivetkit/traces@2.3.4': - resolution: {integrity: sha512-w/3QbwwJEdVC1WtzSjSBCXKXFdCIGeT70AlvW2H9DVjcgyT08Qn7R86gfRQkf+gnDMQxP9CUltzjl4vynOAl5w==} + '@rivetkit/traces@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-4d9Kodk7H0frBHNTmzJBXkOGKGgn5eU+A9XTmOTsoHIpPqK5AUrbJ35P2mQHQmzoU+WoHUumvey0Ze8UOKIy/Q==} engines: {node: '>=18.0.0'} - '@rivetkit/virtual-websocket@2.3.4': - resolution: {integrity: sha512-lXMwTt0SSOYI9SIUSOymh4Qhz2IVM+Gn74dshtEdG3reTPVcbcXWl/QO5aY/UFlzwopiY1YTTD7bapKjwYPsBg==} + '@rivetkit/virtual-websocket@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-U6C9jSf4VaQGEZTROFZHLsfCUci8No4ofBV6muzqmAKTiq6NN7mLE5V0muc0LTUx5dFpcX9hATJW1FSZVpnbYw==} - '@rivetkit/workflow-engine@2.3.4': - resolution: {integrity: sha512-n1J6ZByWXZrkWWmqyCDJ45TvTlcG4L925EeHliHSPSjmIMgV+Qqbxpa34//PtQkafvCsS604QEd+cZLfh7lVOw==} + '@rivetkit/workflow-engine@0.0.0-sqlite-uds.4e59a38': + resolution: {integrity: sha512-TUe2ZEg2D8yCNZTr+F6eeMp2uK2VAybYHhMj1IQUOuWwSyamBD8o5UFkqO12nYcE+52a7NwfHwhHEov8riVb1w==} engines: {node: '>=18.0.0'} - '@secure-exec/core@0.2.1': - resolution: {integrity: sha512-HsnUv6gClpMA1BBRmX86j30TKTZtgJC/fO1tVavr7IpM2zNKbHU8LgSlBd7mv2SNy02ImTmU/GnQ3aYB4NSbEg==} - - '@secure-exec/nodejs@0.2.1': - resolution: {integrity: sha512-UJMJqVFxexlHJV0Q9nWURvrz6GElj8673DDOOFln6FHR6JS+9SaSU3eISrN158DuNC3SFi4rgjb/scKnK4YOYQ==} - - '@secure-exec/v8-darwin-arm64@0.2.1': - resolution: {integrity: sha512-gEWhMHzUpLwzuBNAD0lVkZXE8wFlWMLp4IOZ+56FYwOW/C+m07cYxuW4TjHyPqZ+vPm3IkoaMqqH5yT9VhjX/Q==} - cpu: [arm64] - os: [darwin] - - '@secure-exec/v8-darwin-x64@0.2.1': - resolution: {integrity: sha512-H2Z5K+Cq+fn/kxjGvhJzepnNFWG6qNdyhZybVWGr5bAAZoSz/Qkad4WnXcurWU+880tKDtnf19LHBXrg7zewNQ==} - cpu: [x64] - os: [darwin] - - '@secure-exec/v8-linux-arm64-gnu@0.2.1': - resolution: {integrity: sha512-14subGhVV/gW35mYYm7Gv1Keeex7PxIgQfoKji/JH7wYyDuarP6kgaES0nJw+JXVkxEVud52c+kbcIjIggqCEw==} - cpu: [arm64] - os: [linux] - - '@secure-exec/v8-linux-x64-gnu@0.2.1': - resolution: {integrity: sha512-Az4s+vUf+78vWtsC7rTn/jQc6WKJafAdt2YpEjB4Gnu+sX+FFTIst1hRV4gJonbRyJdy6SW+OQ6DZatmwczorQ==} - cpu: [x64] - os: [linux] - - '@secure-exec/v8@0.2.1': - resolution: {integrity: sha512-ye/seCqzvyMGnvyP+AO7RkVMR/lE3x9m0D2PfmiAXA457R78ZmOFmZ6v+JlJG2vv3LM30KsSXTUhwpG+Teh0hw==} - '@types/retry@0.12.2': resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} - asn1.js@4.10.1: - resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} - - assert@2.1.0: - resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} - atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - better-sqlite3@12.11.1: - resolution: {integrity: sha512-dq9AtApgg5PGFtBzPFSBl3HZQjHok5gaQCM6zh2Yk0aSmDCs1CbnVI8/HgASQkNKsWFpseIO9beg5xxpYhbIfA==} - engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x || 26.x} - - bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - - bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - - bn.js@4.12.5: - resolution: {integrity: sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ==} - - bn.js@5.2.5: - resolution: {integrity: sha512-Vq886eXykuP5E6HcKSSStP3bJgrE6In5WKxVUvJ8XGpWWYs2xZHWqUwzCtGgEtBcxyd57KBFDPFoUfNzdaHCNg==} - - brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - - browser-resolve@2.0.0: - resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==} - - browserify-aes@1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} - - browserify-cipher@1.0.1: - resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} - - browserify-des@1.0.2: - resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} - - browserify-rsa@4.1.1: - resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} - engines: {node: '>= 0.10'} - - browserify-sign@4.2.6: - resolution: {integrity: sha512-sd+Q65fjlWCYWtZKXiKfrUc8d+4jtp/8f0W2NkwzLtoW4bI6UDnWusLWIurHnmurW0XShIRxpwiOX4EoPtXUAg==} - engines: {node: '>= 0.10'} - - browserify-zlib@0.2.0: - resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} - - buffer-xor@1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} - - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - - builtin-status-codes@3.0.0: - resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bind@1.0.9: - resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - cbor-extract@2.2.2: resolution: {integrity: sha512-hlSxxI9XO2yQfe9g6msd3g4xCfDqK5T5P0fRMLuaLHhxn4ViPrm+a+MUfhrvH2W962RGxcBwEGzLQyjbDG1gng==} hasBin: true @@ -464,75 +179,10 @@ packages: cbor-x@1.6.4: resolution: {integrity: sha512-UGKHjp6RHC6QuZ2yy5LCKm7MojM4716DwoSaqwQpaH4DvZvbBTGcoDNTiG9Y2lByXZYFEs9WRkS5tLl96IrF1Q==} - chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - - cipher-base@1.0.7: - resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} - engines: {node: '>= 0.10'} - - cjs-module-lexer@2.2.0: - resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} - - console-browserify@1.2.0: - resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} - - constants-browserify@1.0.0: - resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} - - core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - create-ecdh@4.0.4: - resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} - - create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} - - create-hmac@1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - - croner@10.0.1: - resolution: {integrity: sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g==} - engines: {node: '>=18.0'} - - crypto-browserify@3.12.1: - resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} - engines: {node: '>= 0.10'} - - decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - - des.js@1.1.0: - resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - diffie-hellman@5.0.3: - resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} - - domain-browser@4.22.0: - resolution: {integrity: sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==} - engines: {node: '>=10'} - drizzle-orm@0.44.7: resolution: {integrity: sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ==} peerDependencies: @@ -625,294 +275,42 @@ packages: sqlite3: optional: true - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - elliptic@6.6.1: - resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} - - end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - - es-object-atoms@1.1.2: - resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} - engines: {node: '>= 0.4'} - - esbuild@0.27.7: - resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} - engines: {node: '>=18'} - hasBin: true - - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - - evp_bytestokey@1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} - - expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - fdb-tuple@1.0.0: resolution: {integrity: sha512-8jSvKPCYCgTpi9Pt87qlfTk6griyMx4Gk3Xv31Dp72Qp8b6XgIyFsMm8KzPmFJ9iJ8K4pGvRxvOS8D0XGnrkjw==} - file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} - - fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - generator-function@2.0.1: - resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} - engines: {node: '>= 0.4'} - - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hash-base@3.0.5: - resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} - engines: {node: '>= 0.10'} - - hash-base@3.1.2: - resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} - engines: {node: '>= 0.8'} - - hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - - hasown@2.0.4: - resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} - engines: {node: '>= 0.4'} - - hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - hono@4.12.31: resolution: {integrity: sha512-zJIHFrl6bq3RDd2YusFNCDlM8qUprxKswyi/OPzPyzKDdyBXDqWx8bZlZ7R+saTdSTatUmb3O7K4SspGPaEOQg==} engines: {node: '>=16.9.0'} - https-browserify@1.0.0: - resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - is-arguments@1.2.0: - resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} - engines: {node: '>= 0.4'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.16.2: - resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} - engines: {node: '>= 0.4'} - - is-generator-function@1.1.2: - resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} - engines: {node: '>= 0.4'} - - is-nan@1.3.2: - resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} - engines: {node: '>= 0.4'} - is-network-error@1.3.2: resolution: {integrity: sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==} engines: {node: '>=16'} - is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - - isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isomorphic-timers-promises@1.0.1: - resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==} - engines: {node: '>=10'} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - long-timeout@0.1.1: - resolution: {integrity: sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==} - loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} - - miller-rabin@4.0.1: - resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} - hasBin: true - - mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - - minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - - napi-build-utils@2.0.0: - resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} - - node-abi@3.94.0: - resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==} - engines: {node: '>=10'} - node-gyp-build-optional-packages@5.1.1: resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==} hasBin: true - node-stdlib-browser@1.3.1: - resolution: {integrity: sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==} - engines: {node: '>=10'} - - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} - - object-is@1.1.6: - resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} - engines: {node: '>= 0.4'} - - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - openapi3-ts@4.6.0: resolution: {integrity: sha512-a4sfn6L2sIShhtzJqmjGrARvxAW/3F2BJDdyRVvNF9VhAsZSh5hSyI3a9TNvmzBxXmq66nY5LNT5bQcBxYAZZg==} - os-browserify@0.3.0: - resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - p-retry@6.2.1: resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} engines: {node: '>=16.17'} - pako@1.0.11: - resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - - parse-asn1@5.1.9: - resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==} - engines: {node: '>= 0.10'} - - path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - pbkdf2@3.1.6: - resolution: {integrity: sha512-BT6eelPB1EyGHo8pC0o9Bl6k6SYVhKO1jEbd3lcTrtr7XHdjP8BW1YpfCV3G9Kwkxgattk+S5q2/RvuttCsS1g==} - engines: {node: '>= 0.10'} - pino-abstract-transport@2.0.0: resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} @@ -923,86 +321,22 @@ packages: resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} hasBin: true - pkg-dir@5.0.0: - resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} - engines: {node: '>=10'} - - possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} - - prebuild-install@7.1.3: - resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} - engines: {node: '>=10'} - deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. - hasBin: true - - process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} - process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - - public-encrypt@4.0.3: - resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} - - pump@3.0.4: - resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} - - punycode@1.4.1: - resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} - - qs@6.15.3: - resolution: {integrity: sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==} - engines: {node: '>=0.6'} - - querystring-es3@0.2.1: - resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} - engines: {node: '>=0.4.x'} - quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - - randomfill@1.0.4: - resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} - - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - - readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - real-require@0.2.0: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} - resolve@1.22.12: - resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} - engines: {node: '>= 0.4'} - hasBin: true - retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} - ripemd160@2.0.3: - resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} - engines: {node: '>= 0.8'} - - rivetkit@2.3.4: - resolution: {integrity: sha512-SkQQwt9jXNjKrGFoYXKU72AgEEIV04rysRT5liTjRhH+Dypp+SLBuE3A+Do0BAbfG/F5fZSljk05WTSW556hNg==} + rivetkit@0.0.0-sqlite-uds.4e59a38: + resolution: {integrity: sha512-cZnF3JMeMFirZISiYtZHGrpBPuFXN52A0ctEoM5zON2g7g17x4N3z+sNJOqaUenPL9f73Sv8YPU97UMdeDiZWQ==} engines: {node: '>=22.0.0'} peerDependencies: drizzle-kit: ^0.31.2 @@ -1016,62 +350,10 @@ packages: ws: optional: true - safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - safe-stable-stringify@2.5.0: resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} engines: {node: '>=10'} - secure-exec@0.2.1: - resolution: {integrity: sha512-oaQDzTPDSCOckYC8G0PimIqzEVxY6sYEvcx0fMGsRR/Wl4wkFVHaZgQ3kc2DHWysV6WHWt5g1AXc/6seafO2XQ==} - - semver@7.8.5: - resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} - engines: {node: '>=10'} - hasBin: true - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - - sha.js@2.4.12: - resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} - engines: {node: '>= 0.10'} - hasBin: true - - side-channel-list@1.0.1: - resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.1: - resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} - engines: {node: '>= 0.4'} - - simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - - simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - sonic-boom@4.2.1: resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} @@ -1079,63 +361,8 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - stream-browserify@3.0.0: - resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} - - stream-http@3.2.0: - resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} - - string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - tar-fs@2.1.5: - resolution: {integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==} - - tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - - thread-stream@3.2.0: - resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} - - timers-browserify@2.0.12: - resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} - engines: {node: '>=0.6.0'} - - to-buffer@1.2.2: - resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} - engines: {node: '>= 0.4'} - - tty-browserify@0.0.1: - resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} - - tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - - url@0.11.4: - resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} - engines: {node: '>= 0.4'} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + thread-stream@3.2.0: + resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} uuid@12.0.1: resolution: {integrity: sha512-9obBF8sMIHJWNQaO6IGOG8giGa/jUpKX34bz6o4whVs8M0WAvhID2tNxYp6A2XEBJPuZSX8wsS/6TEKfIDc+nw==} @@ -1145,33 +372,11 @@ packages: resolution: {integrity: sha512-QsxSVw76NqYUWYPVcQmOnQPX8buIVjgn+yqldTHlWISulBTB9TJ9rnzZceDu+GZmycOtzsmuPbPN1YNxvK12fg==} engines: {node: '>=18.0.0'} - vm-browserify@1.1.2: - resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} - - web-streams-polyfill@4.3.0: - resolution: {integrity: sha512-/Gnggvj9oSrEvJbDyyPtAnxBt5fGQM2iWOKQNu7ie1OxDgK40iZpyV3TKaRiEzVj1oA1UxKnEy9XPXh6PW3eVw==} - engines: {node: '>= 8'} - - which-typed-array@1.1.22: - resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} - engines: {node: '>= 0.4'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - yaml@2.9.0: resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} engines: {node: '>= 14.6'} hasBin: true - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} @@ -1200,84 +405,6 @@ snapshots: '@cbor-extract/cbor-extract-win32-x64@2.2.2': optional: true - '@esbuild/aix-ppc64@0.27.7': - optional: true - - '@esbuild/android-arm64@0.27.7': - optional: true - - '@esbuild/android-arm@0.27.7': - optional: true - - '@esbuild/android-x64@0.27.7': - optional: true - - '@esbuild/darwin-arm64@0.27.7': - optional: true - - '@esbuild/darwin-x64@0.27.7': - optional: true - - '@esbuild/freebsd-arm64@0.27.7': - optional: true - - '@esbuild/freebsd-x64@0.27.7': - optional: true - - '@esbuild/linux-arm64@0.27.7': - optional: true - - '@esbuild/linux-arm@0.27.7': - optional: true - - '@esbuild/linux-ia32@0.27.7': - optional: true - - '@esbuild/linux-loong64@0.27.7': - optional: true - - '@esbuild/linux-mips64el@0.27.7': - optional: true - - '@esbuild/linux-ppc64@0.27.7': - optional: true - - '@esbuild/linux-riscv64@0.27.7': - optional: true - - '@esbuild/linux-s390x@0.27.7': - optional: true - - '@esbuild/linux-x64@0.27.7': - optional: true - - '@esbuild/netbsd-arm64@0.27.7': - optional: true - - '@esbuild/netbsd-x64@0.27.7': - optional: true - - '@esbuild/openbsd-arm64@0.27.7': - optional: true - - '@esbuild/openbsd-x64@0.27.7': - optional: true - - '@esbuild/openharmony-arm64@0.27.7': - optional: true - - '@esbuild/sunos-x64@0.27.7': - optional: true - - '@esbuild/win32-arm64@0.27.7': - optional: true - - '@esbuild/win32-ia32@0.27.7': - optional: true - - '@esbuild/win32-x64@0.27.7': - optional: true - '@hono/zod-openapi@1.5.1(hono@4.12.31)(zod@4.4.3)': dependencies: '@asteasolutions/zod-to-openapi': 8.5.0(zod@4.4.3) @@ -1295,104 +422,75 @@ snapshots: '@pinojs/redact@0.4.0': {} - '@rivet-dev/agent-os-core@0.1.1': - dependencies: - '@rivet-dev/agent-os-posix': 0.1.0 - '@rivet-dev/agent-os-python': 0.1.0 - '@secure-exec/core': 0.2.1 - '@secure-exec/nodejs': 0.2.1 - '@secure-exec/v8': 0.2.1 - croner: 10.0.1 - long-timeout: 0.1.1 - secure-exec: 0.2.1 - transitivePeerDependencies: - - pyodide - - '@rivet-dev/agent-os-posix@0.1.0': - dependencies: - '@secure-exec/core': 0.2.1 - - '@rivet-dev/agent-os-python@0.1.0': - dependencies: - '@secure-exec/core': 0.2.1 - '@rivetkit/bare-ts@0.6.2': {} - '@rivetkit/engine-cli-darwin-arm64@2.3.4': - optional: true - - '@rivetkit/engine-cli-darwin-x64@2.3.4': + '@rivetkit/engine-cli-darwin-arm64@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/engine-cli-linux-arm64-musl@2.3.4': + '@rivetkit/engine-cli-darwin-x64@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/engine-cli-linux-x64-musl@2.3.4': + '@rivetkit/engine-cli-linux-arm64-musl@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/engine-cli-win32-x64@2.3.4': + '@rivetkit/engine-cli-linux-x64-musl@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/engine-cli@2.3.4': + '@rivetkit/engine-cli@0.0.0-sqlite-uds.4e59a38': optionalDependencies: - '@rivetkit/engine-cli-darwin-arm64': 2.3.4 - '@rivetkit/engine-cli-darwin-x64': 2.3.4 - '@rivetkit/engine-cli-linux-arm64-musl': 2.3.4 - '@rivetkit/engine-cli-linux-x64-musl': 2.3.4 - '@rivetkit/engine-cli-win32-x64': 2.3.4 + '@rivetkit/engine-cli-darwin-arm64': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/engine-cli-darwin-x64': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/engine-cli-linux-arm64-musl': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/engine-cli-linux-x64-musl': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/engine-envoy-protocol@2.3.4': + '@rivetkit/engine-envoy-protocol@0.0.0-sqlite-uds.4e59a38': dependencies: '@rivetkit/bare-ts': 0.6.2 '@rivetkit/on-change@6.0.1': {} - '@rivetkit/rivetkit-napi-darwin-arm64@2.3.4': + '@rivetkit/rivetkit-napi-darwin-arm64@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/rivetkit-napi-darwin-x64@2.3.4': + '@rivetkit/rivetkit-napi-darwin-x64@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.4': + '@rivetkit/rivetkit-napi-linux-arm64-gnu@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.4': + '@rivetkit/rivetkit-napi-linux-arm64-musl@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.4': + '@rivetkit/rivetkit-napi-linux-x64-gnu@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/rivetkit-napi-linux-x64-musl@2.3.4': + '@rivetkit/rivetkit-napi-linux-x64-musl@0.0.0-sqlite-uds.4e59a38': optional: true - '@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.4': - optional: true - - '@rivetkit/rivetkit-napi@2.3.4': + '@rivetkit/rivetkit-napi@0.0.0-sqlite-uds.4e59a38': dependencies: '@napi-rs/cli': 2.18.4 - '@rivetkit/engine-envoy-protocol': 2.3.4 + '@rivetkit/engine-envoy-protocol': 0.0.0-sqlite-uds.4e59a38 optionalDependencies: - '@rivetkit/rivetkit-napi-darwin-arm64': 2.3.4 - '@rivetkit/rivetkit-napi-darwin-x64': 2.3.4 - '@rivetkit/rivetkit-napi-linux-arm64-gnu': 2.3.4 - '@rivetkit/rivetkit-napi-linux-arm64-musl': 2.3.4 - '@rivetkit/rivetkit-napi-linux-x64-gnu': 2.3.4 - '@rivetkit/rivetkit-napi-linux-x64-musl': 2.3.4 - '@rivetkit/rivetkit-napi-win32-x64-msvc': 2.3.4 + '@rivetkit/rivetkit-napi-darwin-arm64': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/rivetkit-napi-darwin-x64': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/rivetkit-napi-linux-arm64-gnu': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/rivetkit-napi-linux-arm64-musl': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/rivetkit-napi-linux-x64-gnu': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/rivetkit-napi-linux-x64-musl': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/rivetkit-wasm@2.3.4': {} + '@rivetkit/rivetkit-wasm@0.0.0-sqlite-uds.4e59a38': {} - '@rivetkit/traces@2.3.4': + '@rivetkit/traces@0.0.0-sqlite-uds.4e59a38': dependencies: '@rivetkit/bare-ts': 0.6.2 cbor-x: 1.6.4 fdb-tuple: 1.0.0 vbare: 0.0.4 - '@rivetkit/virtual-websocket@2.3.4': {} + '@rivetkit/virtual-websocket@0.0.0-sqlite-uds.4e59a38': {} - '@rivetkit/workflow-engine@2.3.4': + '@rivetkit/workflow-engine@0.0.0-sqlite-uds.4e59a38': dependencies: '@rivetkit/bare-ts': 0.6.2 cbor-x: 1.6.4 @@ -1400,161 +498,10 @@ snapshots: pino: 9.14.0 vbare: 0.0.4 - '@secure-exec/core@0.2.1': - dependencies: - better-sqlite3: 12.11.1 - - '@secure-exec/nodejs@0.2.1': - dependencies: - '@secure-exec/core': 0.2.1 - '@secure-exec/v8': 0.2.1 - cbor-x: 1.6.4 - cjs-module-lexer: 2.2.0 - es-module-lexer: 1.7.0 - esbuild: 0.27.7 - node-stdlib-browser: 1.3.1 - web-streams-polyfill: 4.3.0 - - '@secure-exec/v8-darwin-arm64@0.2.1': - optional: true - - '@secure-exec/v8-darwin-x64@0.2.1': - optional: true - - '@secure-exec/v8-linux-arm64-gnu@0.2.1': - optional: true - - '@secure-exec/v8-linux-x64-gnu@0.2.1': - optional: true - - '@secure-exec/v8@0.2.1': - dependencies: - cbor-x: 1.6.4 - optionalDependencies: - '@secure-exec/v8-darwin-arm64': 0.2.1 - '@secure-exec/v8-darwin-x64': 0.2.1 - '@secure-exec/v8-linux-arm64-gnu': 0.2.1 - '@secure-exec/v8-linux-x64-gnu': 0.2.1 - '@types/retry@0.12.2': {} - asn1.js@4.10.1: - dependencies: - bn.js: 4.12.5 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - - assert@2.1.0: - dependencies: - call-bind: 1.0.9 - is-nan: 1.3.2 - object-is: 1.1.6 - object.assign: 4.1.7 - util: 0.12.5 - atomic-sleep@1.0.0: {} - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 - - base64-js@1.5.1: {} - - better-sqlite3@12.11.1: - dependencies: - bindings: 1.5.0 - prebuild-install: 7.1.3 - - bindings@1.5.0: - dependencies: - file-uri-to-path: 1.0.0 - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - bn.js@4.12.5: {} - - bn.js@5.2.5: {} - - brorand@1.1.0: {} - - browser-resolve@2.0.0: - dependencies: - resolve: 1.22.12 - - browserify-aes@1.2.0: - dependencies: - buffer-xor: 1.0.3 - cipher-base: 1.0.7 - create-hash: 1.2.0 - evp_bytestokey: 1.0.3 - inherits: 2.0.4 - safe-buffer: 5.2.1 - - browserify-cipher@1.0.1: - dependencies: - browserify-aes: 1.2.0 - browserify-des: 1.0.2 - evp_bytestokey: 1.0.3 - - browserify-des@1.0.2: - dependencies: - cipher-base: 1.0.7 - des.js: 1.1.0 - inherits: 2.0.4 - safe-buffer: 5.2.1 - - browserify-rsa@4.1.1: - dependencies: - bn.js: 5.2.5 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - - browserify-sign@4.2.6: - dependencies: - bn.js: 5.2.5 - browserify-rsa: 4.1.1 - create-hash: 1.2.0 - create-hmac: 1.1.7 - elliptic: 6.6.1 - inherits: 2.0.4 - parse-asn1: 5.1.9 - readable-stream: 2.3.8 - safe-buffer: 5.2.1 - - browserify-zlib@0.2.0: - dependencies: - pako: 1.0.11 - - buffer-xor@1.0.3: {} - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - builtin-status-codes@3.0.0: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.9: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - get-intrinsic: 1.3.0 - set-function-length: 1.2.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - cbor-extract@2.2.2: dependencies: node-gyp-build-optional-packages: 5.1.1 @@ -1571,448 +518,44 @@ snapshots: optionalDependencies: cbor-extract: 2.2.2 - chownr@1.1.4: {} - - cipher-base@1.0.7: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - to-buffer: 1.2.2 - - cjs-module-lexer@2.2.0: {} - - console-browserify@1.2.0: {} - - constants-browserify@1.0.0: {} - - core-util-is@1.0.3: {} - - create-ecdh@4.0.4: - dependencies: - bn.js: 4.12.5 - elliptic: 6.6.1 - - create-hash@1.2.0: - dependencies: - cipher-base: 1.0.7 - inherits: 2.0.4 - md5.js: 1.3.5 - ripemd160: 2.0.3 - sha.js: 2.4.12 - - create-hmac@1.1.7: - dependencies: - cipher-base: 1.0.7 - create-hash: 1.2.0 - inherits: 2.0.4 - ripemd160: 2.0.3 - safe-buffer: 5.2.1 - sha.js: 2.4.12 - - create-require@1.1.1: {} - - croner@10.0.1: {} - - crypto-browserify@3.12.1: - dependencies: - browserify-cipher: 1.0.1 - browserify-sign: 4.2.6 - create-ecdh: 4.0.4 - create-hash: 1.2.0 - create-hmac: 1.1.7 - diffie-hellman: 5.0.3 - hash-base: 3.0.5 - inherits: 2.0.4 - pbkdf2: 3.1.6 - public-encrypt: 4.0.3 - randombytes: 2.1.0 - randomfill: 1.0.4 - - decompress-response@6.0.0: - dependencies: - mimic-response: 3.1.0 - - deep-extend@0.6.0: {} - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - des.js@1.1.0: - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - - detect-libc@2.1.2: {} - - diffie-hellman@5.0.3: - dependencies: - bn.js: 4.12.5 - miller-rabin: 4.0.1 - randombytes: 2.1.0 - - domain-browser@4.22.0: {} - - drizzle-orm@0.44.7(better-sqlite3@12.11.1): - optionalDependencies: - better-sqlite3: 12.11.1 - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - elliptic@6.6.1: - dependencies: - bn.js: 4.12.5 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - - end-of-stream@1.4.5: - dependencies: - once: 1.4.0 - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-module-lexer@1.7.0: {} - - es-object-atoms@1.1.2: - dependencies: - es-errors: 1.3.0 - - esbuild@0.27.7: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.7 - '@esbuild/android-arm': 0.27.7 - '@esbuild/android-arm64': 0.27.7 - '@esbuild/android-x64': 0.27.7 - '@esbuild/darwin-arm64': 0.27.7 - '@esbuild/darwin-x64': 0.27.7 - '@esbuild/freebsd-arm64': 0.27.7 - '@esbuild/freebsd-x64': 0.27.7 - '@esbuild/linux-arm': 0.27.7 - '@esbuild/linux-arm64': 0.27.7 - '@esbuild/linux-ia32': 0.27.7 - '@esbuild/linux-loong64': 0.27.7 - '@esbuild/linux-mips64el': 0.27.7 - '@esbuild/linux-ppc64': 0.27.7 - '@esbuild/linux-riscv64': 0.27.7 - '@esbuild/linux-s390x': 0.27.7 - '@esbuild/linux-x64': 0.27.7 - '@esbuild/netbsd-arm64': 0.27.7 - '@esbuild/netbsd-x64': 0.27.7 - '@esbuild/openbsd-arm64': 0.27.7 - '@esbuild/openbsd-x64': 0.27.7 - '@esbuild/openharmony-arm64': 0.27.7 - '@esbuild/sunos-x64': 0.27.7 - '@esbuild/win32-arm64': 0.27.7 - '@esbuild/win32-ia32': 0.27.7 - '@esbuild/win32-x64': 0.27.7 - - events@3.3.0: {} - - evp_bytestokey@1.0.3: - dependencies: - md5.js: 1.3.5 - safe-buffer: 5.2.1 + detect-libc@2.1.2: + optional: true - expand-template@2.0.3: {} + drizzle-orm@0.44.7: {} fdb-tuple@1.0.0: {} - file-uri-to-path@1.0.0: {} - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 - - fs-constants@1.0.0: {} - - function-bind@1.1.2: {} - - generator-function@2.0.1: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.2 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.4 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.2 - - github-from-package@0.0.0: {} - - gopd@1.2.0: {} - - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hash-base@3.0.5: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - - hash-base@3.1.2: - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.8 - safe-buffer: 5.2.1 - to-buffer: 1.2.2 - - hash.js@1.1.7: - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - - hasown@2.0.4: - dependencies: - function-bind: 1.1.2 - - hmac-drbg@1.0.1: - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - hono@4.12.31: {} - https-browserify@1.0.0: {} - - ieee754@1.2.1: {} - - inherits@2.0.4: {} - - ini@1.3.8: {} - invariant@2.2.4: dependencies: loose-envify: 1.4.0 - is-arguments@1.2.0: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-callable@1.2.7: {} - - is-core-module@2.16.2: - dependencies: - hasown: 2.0.4 - - is-generator-function@1.1.2: - dependencies: - call-bound: 1.0.4 - generator-function: 2.0.1 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-nan@1.3.2: - dependencies: - call-bind: 1.0.9 - define-properties: 1.2.1 - is-network-error@1.3.2: {} - is-regex@1.2.1: - dependencies: - call-bound: 1.0.4 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.4 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.22 - - isarray@1.0.0: {} - - isarray@2.0.5: {} - - isomorphic-timers-promises@1.0.1: {} - js-tokens@4.0.0: {} - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - long-timeout@0.1.1: {} - loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 - math-intrinsics@1.1.0: {} - - md5.js@1.3.5: - dependencies: - hash-base: 3.0.5 - inherits: 2.0.4 - safe-buffer: 5.2.1 - - miller-rabin@4.0.1: - dependencies: - bn.js: 4.12.5 - brorand: 1.1.0 - - mimic-response@3.1.0: {} - - minimalistic-assert@1.0.1: {} - - minimalistic-crypto-utils@1.0.1: {} - - minimist@1.2.8: {} - - mkdirp-classic@0.5.3: {} - - napi-build-utils@2.0.0: {} - - node-abi@3.94.0: - dependencies: - semver: 7.8.5 - node-gyp-build-optional-packages@5.1.1: dependencies: detect-libc: 2.1.2 optional: true - node-stdlib-browser@1.3.1: - dependencies: - assert: 2.1.0 - browser-resolve: 2.0.0 - browserify-zlib: 0.2.0 - buffer: 5.7.1 - console-browserify: 1.2.0 - constants-browserify: 1.0.0 - create-require: 1.1.1 - crypto-browserify: 3.12.1 - domain-browser: 4.22.0 - events: 3.3.0 - https-browserify: 1.0.0 - isomorphic-timers-promises: 1.0.1 - os-browserify: 0.3.0 - path-browserify: 1.0.1 - pkg-dir: 5.0.0 - process: 0.11.10 - punycode: 1.4.1 - querystring-es3: 0.2.1 - readable-stream: 3.6.2 - stream-browserify: 3.0.0 - stream-http: 3.2.0 - string_decoder: 1.3.0 - timers-browserify: 2.0.12 - tty-browserify: 0.0.1 - url: 0.11.4 - util: 0.12.5 - vm-browserify: 1.1.2 - - object-inspect@1.13.4: {} - - object-is@1.1.6: - dependencies: - call-bind: 1.0.9 - define-properties: 1.2.1 - - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.9 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.2 - has-symbols: 1.1.0 - object-keys: 1.1.1 - on-exit-leak-free@2.1.2: {} - once@1.4.0: - dependencies: - wrappy: 1.0.2 - openapi3-ts@4.6.0: dependencies: yaml: 2.9.0 - os-browserify@0.3.0: {} - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - p-retry@6.2.1: dependencies: '@types/retry': 0.12.2 is-network-error: 1.3.2 retry: 0.13.1 - pako@1.0.11: {} - - parse-asn1@5.1.9: - dependencies: - asn1.js: 4.10.1 - browserify-aes: 1.2.0 - evp_bytestokey: 1.0.3 - pbkdf2: 3.1.6 - safe-buffer: 5.2.1 - - path-browserify@1.0.1: {} - - path-exists@4.0.0: {} - - path-parse@1.0.7: {} - - pbkdf2@3.1.6: - dependencies: - create-hash: 1.2.0 - create-hmac: 1.1.7 - ripemd160: 2.0.3 - safe-buffer: 5.2.1 - sha.js: 2.4.12 - to-buffer: 1.2.2 - pino-abstract-transport@2.0.0: dependencies: split2: 4.2.0 @@ -2033,121 +576,28 @@ snapshots: sonic-boom: 4.2.1 thread-stream: 3.2.0 - pkg-dir@5.0.0: - dependencies: - find-up: 5.0.0 - - possible-typed-array-names@1.1.0: {} - - prebuild-install@7.1.3: - dependencies: - detect-libc: 2.1.2 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 2.0.0 - node-abi: 3.94.0 - pump: 3.0.4 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.5 - tunnel-agent: 0.6.0 - - process-nextick-args@2.0.1: {} - process-warning@5.0.0: {} - process@0.11.10: {} - - public-encrypt@4.0.3: - dependencies: - bn.js: 4.12.5 - browserify-rsa: 4.1.1 - create-hash: 1.2.0 - parse-asn1: 5.1.9 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - - pump@3.0.4: - dependencies: - end-of-stream: 1.4.5 - once: 1.4.0 - - punycode@1.4.1: {} - - qs@6.15.3: - dependencies: - es-define-property: 1.0.1 - side-channel: 1.1.1 - - querystring-es3@0.2.1: {} - quick-format-unescaped@4.0.4: {} - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - randomfill@1.0.4: - dependencies: - randombytes: 2.1.0 - safe-buffer: 5.2.1 - - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - - readable-stream@2.3.8: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - real-require@0.2.0: {} - resolve@1.22.12: - dependencies: - es-errors: 1.3.0 - is-core-module: 2.16.2 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - retry@0.13.1: {} - ripemd160@2.0.3: - dependencies: - hash-base: 3.1.2 - inherits: 2.0.4 - - rivetkit@2.3.4(better-sqlite3@12.11.1): + rivetkit@0.0.0-sqlite-uds.4e59a38: dependencies: '@hono/zod-openapi': 1.5.1(hono@4.12.31)(zod@4.4.3) - '@rivet-dev/agent-os-core': 0.1.1 '@rivetkit/bare-ts': 0.6.2 - '@rivetkit/engine-cli': 2.3.4 - '@rivetkit/engine-envoy-protocol': 2.3.4 + '@rivetkit/engine-cli': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/engine-envoy-protocol': 0.0.0-sqlite-uds.4e59a38 '@rivetkit/on-change': 6.0.1 - '@rivetkit/rivetkit-napi': 2.3.4 - '@rivetkit/rivetkit-wasm': 2.3.4 - '@rivetkit/traces': 2.3.4 - '@rivetkit/virtual-websocket': 2.3.4 - '@rivetkit/workflow-engine': 2.3.4 + '@rivetkit/rivetkit-napi': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/rivetkit-wasm': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/traces': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/virtual-websocket': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/workflow-engine': 0.0.0-sqlite-uds.4e59a38 cbor-x: 1.6.4 - drizzle-orm: 0.44.7(better-sqlite3@12.11.1) + drizzle-orm: 0.44.7 hono: 4.12.31 invariant: 2.2.4 p-retry: 6.2.1 @@ -2183,192 +633,25 @@ snapshots: - pg - postgres - prisma - - pyodide - sql.js - sqlite3 - safe-buffer@5.1.2: {} - - safe-buffer@5.2.1: {} - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-regex: 1.2.1 - safe-stable-stringify@2.5.0: {} - secure-exec@0.2.1: - dependencies: - '@secure-exec/core': 0.2.1 - '@secure-exec/nodejs': 0.2.1 - - semver@7.8.5: {} - - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - setimmediate@1.0.5: {} - - sha.js@2.4.12: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - to-buffer: 1.2.2 - - side-channel-list@1.0.1: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.1: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.1 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - simple-concat@1.0.1: {} - - simple-get@4.0.1: - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 - sonic-boom@4.2.1: dependencies: atomic-sleep: 1.0.0 split2@4.2.0: {} - stream-browserify@3.0.0: - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.2 - - stream-http@3.2.0: - dependencies: - builtin-status-codes: 3.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - xtend: 4.0.2 - - string_decoder@1.1.1: - dependencies: - safe-buffer: 5.1.2 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - strip-json-comments@2.0.1: {} - - supports-preserve-symlinks-flag@1.0.0: {} - - tar-fs@2.1.5: - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.4 - tar-stream: 2.2.0 - - tar-stream@2.2.0: - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.5 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - thread-stream@3.2.0: dependencies: real-require: 0.2.0 - timers-browserify@2.0.12: - dependencies: - setimmediate: 1.0.5 - - to-buffer@1.2.2: - dependencies: - isarray: 2.0.5 - safe-buffer: 5.2.1 - typed-array-buffer: 1.0.3 - - tty-browserify@0.0.1: {} - - tunnel-agent@0.6.0: - dependencies: - safe-buffer: 5.2.1 - - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - url@0.11.4: - dependencies: - punycode: 1.4.1 - qs: 6.15.3 - - util-deprecate@1.0.2: {} - - util@0.12.5: - dependencies: - inherits: 2.0.4 - is-arguments: 1.2.0 - is-generator-function: 1.1.2 - is-typed-array: 1.1.15 - which-typed-array: 1.1.22 - uuid@12.0.1: {} vbare@0.0.4: {} - vm-browserify@1.1.2: {} - - web-streams-polyfill@4.3.0: {} - - which-typed-array@1.1.22: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.9 - call-bound: 1.0.4 - for-each: 0.3.5 - get-proto: 1.0.1 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - wrappy@1.0.2: {} - - xtend@4.0.2: {} - yaml@2.9.0: {} - yocto-queue@0.1.0: {} - zod@4.4.3: {} diff --git a/packages/runtime-core/tests/native-client.test.ts b/packages/runtime-core/tests/native-client.test.ts index a3ee6c19c7..b0c7308352 100644 --- a/packages/runtime-core/tests/native-client.test.ts +++ b/packages/runtime-core/tests/native-client.test.ts @@ -12,7 +12,7 @@ const ownership = { describe("stdio sidecar protocol client", () => { test("drives a stdio protocol process", async () => { - const fixtureRoot = mkdtempSync(join(tmpdir(), "secure-exec-client-")); + const fixtureRoot = mkdtempSync(join(tmpdir(), "agentos-client-")); const driverPath = join(fixtureRoot, "fake-sidecar.mjs"); writeFileSync( driverPath, @@ -90,7 +90,7 @@ describe("stdio sidecar protocol client", () => { }); test("registers native spawn for the shared SidecarProcess wrapper", async () => { - const fixtureRoot = mkdtempSync(join(tmpdir(), "secure-exec-process-")); + const fixtureRoot = mkdtempSync(join(tmpdir(), "agentos-process-")); const driverPath = join(fixtureRoot, "fake-sidecar.mjs"); writeFileSync( driverPath, diff --git a/packages/runtime-core/tests/node-runtime-decode.test.ts b/packages/runtime-core/tests/node-runtime-decode.test.ts index 7eb9cbb540..74fc66030e 100644 --- a/packages/runtime-core/tests/node-runtime-decode.test.ts +++ b/packages/runtime-core/tests/node-runtime-decode.test.ts @@ -4,7 +4,7 @@ import { describe, expect, test } from "vitest"; // Regression guard for #11 and #59. // -// Both issues were caused by the removed `@secure-exec/v8` runtime.js +// Both issues were caused by the removed legacy V8 runtime.js // (a stdout/socket-path handshake plus a TDZ bug) together with a host-side // `node:v8.deserialize()` decode of `run()` results. That host-side V8 // serialization made result decoding sensitive to the host Node version / diff --git a/packages/runtime-sidecar/npm/darwin-arm64/package.json b/packages/runtime-sidecar/npm/darwin-arm64/package.json index 9a30b703e0..738e2aae57 100644 --- a/packages/runtime-sidecar/npm/darwin-arm64/package.json +++ b/packages/runtime-sidecar/npm/darwin-arm64/package.json @@ -1,11 +1,11 @@ { "name": "@rivet-dev/agentos-runtime-sidecar-darwin-arm64", "version": "0.0.1", - "description": "Secure Exec native sidecar binary for macOS arm64", + "description": "AgentOS language execution native sidecar binary for macOS arm64", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/rivet-dev/secure-exec.git", + "url": "https://github.com/rivet-dev/agentos.git", "directory": "packages/sidecar/npm/darwin-arm64" }, "os": [ diff --git a/packages/runtime-sidecar/npm/darwin-x64/package.json b/packages/runtime-sidecar/npm/darwin-x64/package.json index 0dd77457dd..99b3d32c43 100644 --- a/packages/runtime-sidecar/npm/darwin-x64/package.json +++ b/packages/runtime-sidecar/npm/darwin-x64/package.json @@ -1,11 +1,11 @@ { "name": "@rivet-dev/agentos-runtime-sidecar-darwin-x64", "version": "0.0.1", - "description": "Secure Exec native sidecar binary for macOS x64", + "description": "AgentOS language execution native sidecar binary for macOS x64", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/rivet-dev/secure-exec.git", + "url": "https://github.com/rivet-dev/agentos.git", "directory": "packages/sidecar/npm/darwin-x64" }, "os": [ diff --git a/packages/runtime-sidecar/npm/linux-arm64-gnu/package.json b/packages/runtime-sidecar/npm/linux-arm64-gnu/package.json index 430e10f5d9..d310422730 100644 --- a/packages/runtime-sidecar/npm/linux-arm64-gnu/package.json +++ b/packages/runtime-sidecar/npm/linux-arm64-gnu/package.json @@ -1,11 +1,11 @@ { "name": "@rivet-dev/agentos-runtime-sidecar-linux-arm64-gnu", "version": "0.0.1", - "description": "Secure Exec native sidecar binary for Linux arm64 (glibc)", + "description": "AgentOS language execution native sidecar binary for Linux arm64 (glibc)", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/rivet-dev/secure-exec.git", + "url": "https://github.com/rivet-dev/agentos.git", "directory": "packages/sidecar/npm/linux-arm64-gnu" }, "os": [ diff --git a/packages/runtime-sidecar/npm/linux-x64-gnu/package.json b/packages/runtime-sidecar/npm/linux-x64-gnu/package.json index 38ae2b9c0f..43b30f593c 100644 --- a/packages/runtime-sidecar/npm/linux-x64-gnu/package.json +++ b/packages/runtime-sidecar/npm/linux-x64-gnu/package.json @@ -1,11 +1,11 @@ { "name": "@rivet-dev/agentos-runtime-sidecar-linux-x64-gnu", "version": "0.0.1", - "description": "Secure Exec native sidecar binary for Linux x64 (glibc)", + "description": "AgentOS language execution native sidecar binary for Linux x64 (glibc)", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/rivet-dev/secure-exec.git", + "url": "https://github.com/rivet-dev/agentos.git", "directory": "packages/sidecar/npm/linux-x64-gnu" }, "os": [ diff --git a/packages/runtime-sidecar/package.json b/packages/runtime-sidecar/package.json index 75de6c45eb..ce22d9202a 100644 --- a/packages/runtime-sidecar/package.json +++ b/packages/runtime-sidecar/package.json @@ -1,11 +1,11 @@ { "name": "@rivet-dev/agentos-runtime-sidecar", "version": "0.0.1", - "description": "Platform-specific resolver for the Secure Exec native sidecar binary", + "description": "Platform-specific resolver for the AgentOS language execution native sidecar binary", "license": "Apache-2.0", "repository": { "type": "git", - "url": "https://github.com/rivet-dev/secure-exec.git", + "url": "https://github.com/rivet-dev/agentos.git", "directory": "packages/sidecar" }, "main": "./index.js", diff --git a/packages/secure-exec-example-ai-agent-type-check/package.json b/packages/secure-exec-example-ai-agent-type-check/package.json deleted file mode 100644 index 1335d2cb7d..0000000000 --- a/packages/secure-exec-example-ai-agent-type-check/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-ai-agent-type-check", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit -p tsconfig.json", - "dev": "tsx src/index.ts", - "verify-docs": "node scripts/verify-docs.mjs" - }, - "dependencies": { - "@ai-sdk/anthropic": "^3.0.58", - "@rivet-dev/agentos-typescript": "workspace:*", - "ai": "^6.0.116", - "@rivet-dev/agentos-core": "workspace:*", - "typescript": "^5.7.2", - "zod": "^3.24.0" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.2" - } -} diff --git a/packages/secure-exec-example-ai-agent-type-check/scripts/verify-docs.mjs b/packages/secure-exec-example-ai-agent-type-check/scripts/verify-docs.mjs deleted file mode 100644 index 4d8d667aa3..0000000000 --- a/packages/secure-exec-example-ai-agent-type-check/scripts/verify-docs.mjs +++ /dev/null @@ -1,78 +0,0 @@ -import { readFile } from "node:fs/promises"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const repoRoot = path.resolve(__dirname, "../../.."); -const docsPath = path.join(repoRoot, "docs/features/typescript.mdx"); - -const expectedFiles = new Map([ - [ - "Type-Checked Execution", - path.join( - repoRoot, - "packages/secure-exec-example-ai-agent-type-check/src/index.ts", - ), - ], -]); - -function normalizeTitle(title) { - return title.trim().replace(/^"|"$/g, ""); -} - -function normalizeCode(source) { - const normalized = source.replace(/\r\n/g, "\n").replace(/^\n+|\n+$/g, ""); - const lines = normalized.split("\n"); - const nonEmptyLines = lines.filter((line) => line.trim().length > 0); - const minIndent = nonEmptyLines.reduce((indent, line) => { - const lineIndent = line.match(/^ */)?.[0].length ?? 0; - return Math.min(indent, lineIndent); - }, Number.POSITIVE_INFINITY); - - if (!Number.isFinite(minIndent) || minIndent === 0) { - return normalized; - } - - return lines.map((line) => line.slice(minIndent)).join("\n"); -} - -const docsSource = await readFile(docsPath, "utf8"); -const blockPattern = /^\s*```ts(?:\s+([^\n]+))?\n([\s\S]*?)^\s*```/gm; -const docBlocks = new Map(); - -for (const match of docsSource.matchAll(blockPattern)) { - const rawTitle = match[1]; - if (!rawTitle) { - continue; - } - - const title = normalizeTitle(rawTitle); - if (!expectedFiles.has(title)) { - continue; - } - - docBlocks.set(title, normalizeCode(match[2] ?? "")); -} - -const mismatches = []; - -for (const [title, filePath] of expectedFiles) { - const fileSource = normalizeCode(await readFile(filePath, "utf8")); - const docSource = docBlocks.get(title); - - if (!docSource) { - mismatches.push(`Missing docs snippet for ${title}`); - continue; - } - - if (docSource !== fileSource) { - mismatches.push(`Snippet mismatch for ${title}`); - } -} - -if (mismatches.length > 0) { - console.error(mismatches.join("\n")); - process.exit(1); -} - -console.log("AI agent docs match example sources."); diff --git a/packages/secure-exec-example-ai-agent-type-check/src/index.ts b/packages/secure-exec-example-ai-agent-type-check/src/index.ts deleted file mode 100644 index eba7435898..0000000000 --- a/packages/secure-exec-example-ai-agent-type-check/src/index.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { join } from "node:path"; -import { anthropic } from "@ai-sdk/anthropic"; -import { createTypeScriptTools } from "@rivet-dev/agentos-typescript"; -import { nodeModulesMount } from "@rivet-dev/agentos-core"; -import { generateText, stepCountIs, tool } from "ai"; -import { - allowAll, - createKernel, - createNodeDriver, - createNodeRuntime, - createNodeRuntimeDriverFactory, -} from "@rivet-dev/agentos-core/internal/runtime-compat"; -import { createInMemoryFileSystem } from "@rivet-dev/agentos-core/test/runtime"; -import { z } from "zod"; - -const filesystem = createInMemoryFileSystem(); -const systemDriver = createNodeDriver({ - filesystem, - mounts: [nodeModulesMount(join(process.cwd(), "node_modules"))], - permissions: allowAll, -}); -const runtimeDriverFactory = createNodeRuntimeDriverFactory(); -const ts = createTypeScriptTools({ - systemDriver, - runtimeDriverFactory, - memoryLimit: 256, - cpuTimeLimitMs: 5000, -}); - -const { text } = await generateText({ - model: anthropic("claude-sonnet-4-6"), - prompt: - "Write TypeScript that calculates the first 20 fibonacci numbers. Assign the result to module.exports.", - stopWhen: stepCountIs(5), - tools: { - execute_typescript: tool({ - description: - "Type-check TypeScript in a sandbox, compile it, then run the emitted JavaScript in a sandbox. Return diagnostics when validation fails.", - inputSchema: z.object({ code: z.string() }), - execute: async ({ code }) => { - const typecheck = await ts.typecheckSource({ - sourceText: code, - filePath: "/root/generated.ts", - compilerOptions: { - module: "commonjs", - target: "es2022", - }, - }); - - if (!typecheck.success) { - return { - ok: false, - stage: "typecheck", - diagnostics: typecheck.diagnostics, - }; - } - - const compiled = await ts.compileSource({ - sourceText: code, - filePath: "/root/generated.ts", - compilerOptions: { - module: "commonjs", - target: "es2022", - }, - }); - - if (!compiled.success || !compiled.outputText) { - return { - ok: false, - stage: "compile", - diagnostics: compiled.diagnostics, - }; - } - - try { - await filesystem.mkdir("/root", { recursive: true }); - await filesystem.writeFile("/root/generated.js", compiled.outputText); - const kernel = createKernel({ - filesystem, - permissions: allowAll, - syncFilesystemOnDispose: false, - }); - let stdout = ""; - let stderr = ""; - try { - await kernel.mount(createNodeRuntime()); - const child = kernel.spawn( - "node", - [ - "-e", - "const exportsValue = require('/root/generated.js'); console.log(JSON.stringify(exportsValue));", - ], - { - onStdout: (chunk) => { - stdout += Buffer.from(chunk).toString("utf8"); - }, - onStderr: (chunk) => { - stderr += Buffer.from(chunk).toString("utf8"); - }, - }, - ); - const exitCode = await child.wait(); - if (exitCode !== 0) { - throw new Error( - stderr.trim() || `sandboxed JavaScript exited ${exitCode}`, - ); - } - } finally { - await kernel.dispose(); - } - - return { - ok: true, - stage: "run", - exports: JSON.parse(stdout), - }; - } catch (error) { - return { - ok: false, - stage: "run", - errorMessage: - error instanceof Error ? error.message : String(error), - }; - } - }, - }), - }, -}); - -console.log(text); diff --git a/packages/secure-exec-example-ai-agent-type-check/tsconfig.json b/packages/secure-exec-example-ai-agent-type-check/tsconfig.json deleted file mode 100644 index eb71769d9d..0000000000 --- a/packages/secure-exec-example-ai-agent-type-check/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "noEmit": true, - "baseUrl": ".", - "paths": { - "@rivet-dev/agentos-typescript": ["../typescript/src/index.ts"], - "@rivet-dev/agentos-core": ["../core/src/index.ts"], - "@rivet-dev/agentos-core/internal/runtime-compat": ["../core/src/runtime-compat.ts"] - } - }, - "include": ["src/**/*.ts", "../core/src/cron/long-timeout.d.ts"] -} diff --git a/packages/secure-exec/README.md b/packages/secure-exec/README.md deleted file mode 100644 index c315a349a5..0000000000 --- a/packages/secure-exec/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# secure-exec - -Public Secure-Exec compatibility package backed by Agent OS runtime primitives. - -Use `secure-exec` when you need the documented stable Secure-Exec Node runtime -surface. New product-facing SDK work should use `@rivet-dev/agentos`. diff --git a/packages/secure-exec/src/index.ts b/packages/secure-exec/src/index.ts deleted file mode 100644 index 4714b3609f..0000000000 --- a/packages/secure-exec/src/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Public Secure-Exec compatibility surface backed by Agent OS primitives. - * - * This intentionally exposes only the stable Node-focused API. Deferred - * compatibility packages such as browser and Python remain out of scope. - */ - -export type { - BindingFunction, - BindingTree, - DefaultNetworkAdapterOptions, - DirEntry, - ExecOptions, - ExecResult, - Kernel, - KernelInterface, - NetworkAdapter, - NodeRuntimeDriver, - NodeRuntimeDriverFactory, - NodeRuntimeDriverFactoryOptions, - NodeRuntimeOptions, - OSConfig, - Permissions, - ProcessConfig, - ResourceBudgets, - RunResult, - StatInfo, - StdioChannel, - StdioEvent, - StdioHook, - TimingMitigation, - VirtualFileSystem, -} from "@rivet-dev/agentos-core/internal/runtime-compat"; -export type { NodeModulesMountConfig } from "@rivet-dev/agentos-core"; -export { - allowAll, - allowAllChildProcess, - allowAllEnv, - allowAllFs, - allowAllNetwork, - createDefaultNetworkAdapter, - createKernel, - createNodeDriver, - createNodeHostCommandExecutor, - createNodeRuntime, - createNodeRuntimeDriverFactory, - exists, - isPrivateIp, - mkdir, - NodeExecutionDriver, - NodeFileSystem, - NodeRuntime, - readDirWithTypes, - rename, - stat, -} from "@rivet-dev/agentos-core/internal/runtime-compat"; -export { nodeModulesMount } from "@rivet-dev/agentos-core"; diff --git a/packages/secure-exec/tests/public-api.test.ts b/packages/secure-exec/tests/public-api.test.ts deleted file mode 100644 index e15d195bcb..0000000000 --- a/packages/secure-exec/tests/public-api.test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { - type BindingFunction, - type BindingTree, - NodeExecutionDriver as CoreNodeExecutionDriver, - NodeFileSystem as CoreNodeFileSystem, - NodeRuntime as CoreNodeRuntime, - allowAll as coreAllowAll, - allowAllChildProcess as coreAllowAllChildProcess, - allowAllEnv as coreAllowAllEnv, - allowAllFs as coreAllowAllFs, - allowAllNetwork as coreAllowAllNetwork, - createDefaultNetworkAdapter as coreCreateDefaultNetworkAdapter, - createKernel as coreCreateKernel, - createNodeDriver as coreCreateNodeDriver, - createNodeHostCommandExecutor as coreCreateNodeHostCommandExecutor, - createNodeRuntime as coreCreateNodeRuntime, - createNodeRuntimeDriverFactory as coreCreateNodeRuntimeDriverFactory, - exists as coreExists, - isPrivateIp as coreIsPrivateIp, - mkdir as coreMkdir, - readDirWithTypes as coreReadDirWithTypes, - rename as coreRename, - stat as coreStat, - type DefaultNetworkAdapterOptions, - type DirEntry, - type ExecOptions, - type ExecResult, - type Kernel, - type KernelInterface, - type ModuleAccessOptions, - type NetworkAdapter, - type NodeRuntimeDriver, - type NodeRuntimeDriverFactory, - type NodeRuntimeDriverFactoryOptions, - type NodeRuntimeOptions, - type OSConfig, - type Permissions, - type ProcessConfig, - type ResourceBudgets, - type RunResult, - type StatInfo, - type StdioChannel, - type StdioEvent, - type StdioHook, - type TimingMitigation, - type VirtualFileSystem, -} from "@rivet-dev/agentos-core/internal/runtime-compat"; -import * as secureExec from "secure-exec"; -import { describe, expect, it } from "vitest"; - -describe("secure-exec", () => { - it("re-exports the stable compatibility surface from Agent OS", () => { - expect(secureExec.NodeRuntime).toBe(CoreNodeRuntime); - expect(secureExec.NodeExecutionDriver).toBe(CoreNodeExecutionDriver); - expect(secureExec.NodeFileSystem).toBe(CoreNodeFileSystem); - expect(secureExec.createDefaultNetworkAdapter).toBe( - coreCreateDefaultNetworkAdapter, - ); - expect(secureExec.createNodeDriver).toBe(coreCreateNodeDriver); - expect(secureExec.createNodeHostCommandExecutor).toBe( - coreCreateNodeHostCommandExecutor, - ); - expect(secureExec.createNodeRuntime).toBe(coreCreateNodeRuntime); - expect(secureExec.createNodeRuntimeDriverFactory).toBe( - coreCreateNodeRuntimeDriverFactory, - ); - expect(secureExec.createKernel).toBe(coreCreateKernel); - expect(secureExec.allowAll).toBe(coreAllowAll); - expect(secureExec.allowAllFs).toBe(coreAllowAllFs); - expect(secureExec.allowAllNetwork).toBe(coreAllowAllNetwork); - expect(secureExec.allowAllChildProcess).toBe(coreAllowAllChildProcess); - expect(secureExec.allowAllEnv).toBe(coreAllowAllEnv); - expect(secureExec.exists).toBe(coreExists); - expect(secureExec.stat).toBe(coreStat); - expect(secureExec.rename).toBe(coreRename); - expect(secureExec.readDirWithTypes).toBe(coreReadDirWithTypes); - expect(secureExec.mkdir).toBe(coreMkdir); - expect(secureExec.isPrivateIp).toBe(coreIsPrivateIp); - }); - - it("preserves the published type surface through TypeScript", () => { - void (null as BindingFunction | null); - void (null as BindingTree | null); - void (null as DefaultNetworkAdapterOptions | null); - void (null as DirEntry | null); - void (null as ExecOptions | null); - void (null as ExecResult | null); - void (null as Kernel | null); - void (null as KernelInterface | null); - void (null as ModuleAccessOptions | null); - void (null as NetworkAdapter | null); - void (null as NodeRuntimeDriver | null); - void (null as NodeRuntimeDriverFactory | null); - void (null as NodeRuntimeDriverFactoryOptions | null); - void (null as NodeRuntimeOptions | null); - void (null as OSConfig | null); - void (null as Permissions | null); - void (null as ProcessConfig | null); - void (null as ResourceBudgets | null); - void (null as RunResult | null); - void (null as StatInfo | null); - void (null as StdioChannel | null); - void (null as StdioEvent | null); - void (null as StdioHook | null); - void (null as TimingMitigation | null); - void (null as VirtualFileSystem | null); - - expect(true).toBe(true); - }); - - it("does not expose deferred browser or python subpaths", async () => { - const importDeferred = (specifier: string) => - new Function("target", "return import(target)")( - specifier, - ) as Promise; - - await expect(importDeferred("secure-exec/browser")).rejects.toThrow(); - await expect(importDeferred("secure-exec/python")).rejects.toThrow(); - }); - - it("does not expose an in-memory filesystem factory", () => { - expect(secureExec).not.toHaveProperty("createInMemoryFileSystem"); - }); -}); diff --git a/packages/secure-exec/tests/quickstart-smoke.ts b/packages/secure-exec/tests/quickstart-smoke.ts deleted file mode 100644 index c44f26f65c..0000000000 --- a/packages/secure-exec/tests/quickstart-smoke.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { - allowAll, - createNodeDriver, - createNodeHostCommandExecutor, - createNodeRuntimeDriverFactory, - NodeRuntime, - type NodeRuntimeOptions, -} from "secure-exec"; -import { createInMemoryFileSystem } from "@rivet-dev/agentos-core/test/runtime"; - -export function createQuickstartOptions(): NodeRuntimeOptions { - const filesystem = createInMemoryFileSystem(); - const systemDriver = createNodeDriver({ - filesystem, - permissions: allowAll, - commandExecutor: createNodeHostCommandExecutor(), - }); - - return { - systemDriver, - runtimeDriverFactory: createNodeRuntimeDriverFactory(), - }; -} - -void NodeRuntime; diff --git a/packages/secure-exec/tests/tsconfig.quickstart.json b/packages/secure-exec/tests/tsconfig.quickstart.json deleted file mode 100644 index 462811a6d6..0000000000 --- a/packages/secure-exec/tests/tsconfig.quickstart.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "noEmit": true, - "rootDir": "." - }, - "exclude": [], - "include": ["quickstart-smoke.ts"] -} diff --git a/packages/secure-exec/tsconfig.json b/packages/secure-exec/tsconfig.json deleted file mode 100644 index bb2036bc5e..0000000000 --- a/packages/secure-exec/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "baseUrl": ".", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "esModuleInterop": true, - "declaration": true, - "outDir": "./dist", - "rootDir": "./src", - "paths": { - "@rivet-dev/agentos-core/internal/runtime-compat": [ - "../core/dist/runtime-compat.d.ts" - ] - } - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "tests"] -} diff --git a/packages/typescript/README.md b/packages/typescript/README.md index fe5d3b951a..eb708424c0 100644 --- a/packages/typescript/README.md +++ b/packages/typescript/README.md @@ -1,6 +1,8 @@ -# @rivet-dev/agentos-typescript +# AgentOS internal TypeScript compiler Public AgentOS TypeScript companion package backed by AgentOS runtime primitives. -Use `@rivet-dev/agentos-typescript` when you need sandboxed TypeScript type +This private workspace module implements the compiler used by +`@rivet-dev/agentos-javascript`. It is not a supported install target. Use +`runtime.typescript` when you need isolated TypeScript type checking or compilation on top of the maintained AgentOS runtime surface. diff --git a/packages/typescript/package.json b/packages/typescript/package.json index d19a95a556..a946917937 100644 --- a/packages/typescript/package.json +++ b/packages/typescript/package.json @@ -1,7 +1,8 @@ { - "name": "@rivet-dev/agentos-typescript", + "name": "@rivet-dev/agentos-internal-typescript", + "private": true, "version": "0.0.1", - "description": "AgentOS TypeScript companion tools backed by AgentOS runtime primitives.", + "description": "Internal TypeScript compiler implementation for AgentOS JavaScript execution.", "type": "module", "license": "Apache-2.0", "main": "./dist/index.js", diff --git a/packages/typescript/src/index.ts b/packages/typescript/src/index.ts index d912aa23b4..b4d25cded9 100644 --- a/packages/typescript/src/index.ts +++ b/packages/typescript/src/index.ts @@ -1,6 +1,7 @@ import { realpathSync } from "node:fs"; import { createRequire } from "node:module"; import path from "node:path"; +import type { AgentOs } from "@rivet-dev/agentos-core"; import { createKernel, type createNodeDriver, @@ -56,6 +57,15 @@ export interface TypeScriptToolsOptions { compilerSpecifier?: string; } +export interface AgentOsTypeScriptToolsOptions { + /** Guest path or package specifier for the TypeScript compiler. */ + compilerSpecifier: string; + /** Per-compiler-invocation wall-clock limit. */ + timeoutMs?: number; + /** Per-compiler-invocation CPU limit. */ + cpuTimeLimitMs?: number; +} + export interface TypeScriptTools { typecheckProject(options?: ProjectCompilerOptions): Promise; compileProject( @@ -139,6 +149,104 @@ export function createTypeScriptTools( }; } +let nextAgentOsCompilerRequestId = 0; + +/** + * Bind the TypeScript compiler to an existing AgentOS VM. + * + * Unlike the legacy driver-oriented constructor, this runs every compiler + * invocation in the caller's VM, so source files, tsconfig projects, + * permissions, and resource limits all share one sidecar-owned environment. + */ +export function createAgentOsTypeScriptTools( + vm: AgentOs, + options: AgentOsTypeScriptToolsOptions, +): TypeScriptTools { + const run = async ( + request: Omit, + ): Promise => { + const completeRequest = { + ...request, + compilerSpecifier: options.compilerSpecifier, + } as CompilerRequest; + try { + return (await runCompilerRequestInAgentOs( + vm, + completeRequest, + options, + )) as TResult; + } catch (error) { + return createFailureResult( + completeRequest.kind, + error instanceof Error ? error.message : String(error), + ); + } + }; + + return { + typecheckProject: (requestOptions = {}) => + run({ + kind: "typecheckProject", + options: requestOptions, + }), + compileProject: (requestOptions = {}) => + run({ + kind: "compileProject", + options: requestOptions, + }), + typecheckSource: (requestOptions) => + run({ + kind: "typecheckSource", + options: requestOptions, + }), + compileSource: (requestOptions) => + run({ + kind: "compileSource", + options: requestOptions, + }), + }; +} + +async function runCompilerRequestInAgentOs( + vm: AgentOs, + request: CompilerRequest, + options: AgentOsTypeScriptToolsOptions, +): Promise { + const requestId = nextAgentOsCompilerRequestId++; + const requestPath = `/tmp/agentos-typescript-request-${requestId}.json`; + const runnerPath = `/tmp/agentos-typescript-runner-${requestId}.cjs`; + await vm.writeFile(requestPath, JSON.stringify(request)); + await vm.writeFile(runnerPath, buildCompilerRuntimeScript(requestPath)); + + try { + const result = await vm.execArgv("node", [runnerPath], { + cwd: request.options.cwd ?? "/workspace", + timeout: options.timeoutMs, + cpuTimeLimitMs: options.cpuTimeLimitMs, + }); + if (result.stdout.trim()) { + return parseRuntimeResponse(result.stdout); + } + if (result.exitCode !== 0) { + throw new Error( + result.stderr.trim() || `TypeScript runtime exited ${result.exitCode}`, + ); + } + throw new Error("TypeScript runtime produced no response"); + } finally { + for (const targetPath of [requestPath, runnerPath]) { + try { + if (await vm.exists(targetPath)) await vm.remove(targetPath); + } catch (error) { + console.error( + `[agentos] failed to remove TypeScript compiler temporary file ${targetPath}:`, + error, + ); + } + } + } +} + async function runCompilerRequest( options: TypeScriptToolsOptions, request: CompilerRequest, @@ -388,10 +496,10 @@ function createFailureResult( function normalizeCompilerFailureMessage(errorMessage?: string): string { const message = (errorMessage ?? "TypeScript compiler failed").trim(); if (/memory limit/i.test(message)) { - return "TypeScript compiler exceeded sandbox memory limit"; + return "TypeScript compiler exceeded VM memory limit"; } if (/cpu time limit exceeded|timed out/i.test(message)) { - return "TypeScript compiler exceeded sandbox CPU time limit"; + return "TypeScript compiler exceeded VM CPU time limit"; } return message; } @@ -417,6 +525,7 @@ function buildCompilerRuntimeScript(requestPath: string): string { return ` const fs = require("node:fs"); const path = require("node:path"); +const __require = require; function loadTypeScriptCompiler(compilerSpecifier) { const specifier = @@ -450,6 +559,7 @@ try { function buildCompilerRuntimeEval(request: CompilerRequest): string { return ` const path = require("node:path"); +const __require = require; function loadTypeScriptCompiler(compilerSpecifier) { const specifier = @@ -619,7 +729,7 @@ function compilerRuntimeMain( const cwd = path.resolve(options.cwd ?? "/root"); const filePath = path.resolve( cwd, - options.filePath ?? "__secure_exec_typescript_input__.ts", + options.filePath ?? "__agentos_typescript_input__.ts", ); const projectCompilerOptions = options.configFilePath ? resolveProjectConfig( diff --git a/packages/typescript/tests/quickstart-smoke.ts b/packages/typescript/tests/quickstart-smoke.ts index 8ce0632bdd..9f1be03b49 100644 --- a/packages/typescript/tests/quickstart-smoke.ts +++ b/packages/typescript/tests/quickstart-smoke.ts @@ -3,7 +3,7 @@ import { type ProjectCompileResult, type TypeCheckResult, type TypeScriptTools, -} from "@rivet-dev/agentos-typescript"; +} from "@rivet-dev/agentos-internal-typescript"; import { createNodeDriver, createNodeRuntimeDriverFactory, diff --git a/packages/typescript/tests/typescript-tools.integration.nightly.test.ts b/packages/typescript/tests/typescript-tools.integration.nightly.test.ts index 9b80bbc2b5..6fdce0ec17 100644 --- a/packages/typescript/tests/typescript-tools.integration.nightly.test.ts +++ b/packages/typescript/tests/typescript-tools.integration.nightly.test.ts @@ -1,6 +1,6 @@ import { join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { createTypeScriptTools } from "@rivet-dev/agentos-typescript"; +import { createTypeScriptTools } from "@rivet-dev/agentos-internal-typescript"; import { allowAllFs, createKernel, @@ -32,7 +32,7 @@ function createTools() { }; } -describe("@rivet-dev/agentos-typescript", () => { +describe("AgentOS internal TypeScript compiler", () => { it("typechecks a project with node types from node_modules", async () => { const { filesystem, tools } = createTools(); await filesystem.mkdir("/root"); diff --git a/packages/typescript/tsconfig.json b/packages/typescript/tsconfig.json index 8692ed7bd4..3d9ab046f1 100644 --- a/packages/typescript/tsconfig.json +++ b/packages/typescript/tsconfig.json @@ -9,7 +9,7 @@ "outDir": "./dist", "rootDir": "./src", "paths": { - "@rivet-dev/agentos-typescript": ["./src/index.ts"], + "@rivet-dev/agentos-internal-typescript": ["./src/index.ts"], "@rivet-dev/agentos-core/internal/runtime-compat": [ "../core/dist/runtime-compat.d.ts" ] diff --git a/packages/typescript/vitest.config.ts b/packages/typescript/vitest.config.ts index 3cfd2d1ead..05c2448e4f 100644 --- a/packages/typescript/vitest.config.ts +++ b/packages/typescript/vitest.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ replacement: resolve(__dirname, "../core/dist/runtime-compat.js"), }, { - find: "@rivet-dev/agentos-typescript", + find: "@rivet-dev/agentos-internal-typescript", replacement: resolve(__dirname, "./src/index.ts"), }, ], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2de244aab..9d86adcc2a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,18 +7,20 @@ settings: catalogs: rivetkit: '@rivetkit/react': - specifier: 0.0.0-sqlite-uds.4e59a38 - version: 0.0.0-sqlite-uds.4e59a38 + specifier: 2.3.7 + version: 2.3.7 rivetkit: - specifier: 0.0.0-sqlite-uds.4e59a38 - version: 0.0.0-sqlite-uds.4e59a38 + specifier: 2.3.7 + version: 2.3.7 overrides: '@rivet-dev/agentos-core': workspace:* - '@rivetkit/rivetkit-wasm': 2.3.2 + '@rivetkit/rivetkit-wasm': 2.3.7 '@mariozechner/pi-tui': 0.60.0 '@mariozechner/pi-agent-core': 0.60.0 +pnpmfileChecksum: sha256-SEnUwm6AFeob5DIJB/q7nwJGPinO5RVveyVjDzNYuIM= + importers: .: @@ -49,7 +51,7 @@ importers: version: 1.6.0 '@mariozechner/pi-coding-agent': specifier: ^0.60.0 - version: 0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@3.25.76) + version: 0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6) '@rivet-dev/agentos-core': specifier: workspace:* version: link:packages/core @@ -101,9 +103,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -115,7 +114,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -143,7 +142,7 @@ importers: version: link:../../packages/agentos rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) devDependencies: '@types/node': specifier: ^22.10.2 @@ -169,9 +168,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -183,7 +179,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -218,9 +214,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -232,7 +225,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -267,9 +260,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -281,7 +271,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -324,7 +314,7 @@ importers: version: link:../../packages/agentos '@rivetkit/react': specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(ws@8.21.0(bufferutil@4.1.0)) '@xterm/addon-fit': specifier: ^0.10.0 version: 0.10.0(@xterm/xterm@5.5.0) @@ -339,7 +329,7 @@ importers: version: 19.2.7(react@19.2.7) rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) devDependencies: '@types/react': specifier: ^19.0.0 @@ -379,7 +369,7 @@ importers: version: link:../../packages/agentos rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) devDependencies: '@types/node': specifier: ^22.10.2 @@ -408,9 +398,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -422,7 +409,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -457,9 +444,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -471,7 +455,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -506,9 +490,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -520,7 +501,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -555,9 +536,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -569,7 +547,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -604,9 +582,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -618,7 +593,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -653,9 +628,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -667,7 +639,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -702,9 +674,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -716,7 +685,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -751,9 +720,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -765,7 +731,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -783,6 +749,233 @@ importers: specifier: ^5.7.2 version: 5.9.3 + examples/js-ai-agent-code-exec: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-child-processes: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-code-mode: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + zod: + specifier: ^4.1.11 + version: 4.3.6 + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-dev-servers: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-filesystem: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-module-loading: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-networking: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-networking-wasm: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-output-capture: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-permissions: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-plugin-systems: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-process-isolation: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-quickstart: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-resource-limits: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + examples/js-runtime: dependencies: '@agentos-software/claude-code': @@ -800,9 +993,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -814,7 +1004,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -832,6 +1022,70 @@ importers: specifier: ^5.7.2 version: 5.9.3 + examples/js-runtime-platform: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-sdk-overview: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/js-typescript: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + typescript: + specifier: ^5.7.2 + version: 5.9.3 + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + + examples/js-virtual-filesystem: + dependencies: + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../../packages/javascript + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + examples/llm-credentials: dependencies: '@agentos-software/claude-code': @@ -849,9 +1103,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -863,7 +1114,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -898,9 +1149,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -912,7 +1160,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -947,9 +1195,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -961,7 +1206,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -996,9 +1241,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -1010,7 +1252,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1045,9 +1287,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -1059,7 +1298,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1094,9 +1333,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -1108,7 +1344,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1143,9 +1379,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -1157,7 +1390,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1192,9 +1425,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -1206,7 +1436,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1224,6 +1454,38 @@ importers: specifier: ^5.7.2 version: 5.9.3 + examples/python-quickstart: + dependencies: + '@rivet-dev/agentos-python': + specifier: workspace:* + version: link:../../packages/python + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + + examples/python-sdk-overview: + dependencies: + '@rivet-dev/agentos-python': + specifier: workspace:* + version: link:../../packages/python + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.2 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + examples/quickstart: dependencies: '@agentos-software/claude-code': @@ -1241,9 +1503,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -1255,7 +1514,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1290,9 +1549,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -1310,7 +1566,7 @@ importers: version: 18.3.1(react@18.3.1) rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1348,9 +1604,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1362,7 +1615,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1397,9 +1650,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1411,7 +1661,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1431,9 +1681,9 @@ importers: examples/quickstart/bindings: dependencies: - '@rivet-dev/agentos-core': + '@rivet-dev/agentos': specifier: workspace:* - version: link:../../../packages/core + version: link:../../../packages/agentos zod: specifier: ^4.1.11 version: 4.3.6 @@ -1465,9 +1715,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1479,7 +1726,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1514,9 +1761,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1528,7 +1772,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1563,9 +1807,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1577,7 +1818,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1612,9 +1853,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1626,7 +1864,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1661,9 +1899,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1675,7 +1910,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1710,9 +1945,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1724,7 +1956,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1759,9 +1991,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1773,7 +2002,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1808,9 +2037,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1822,7 +2048,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1840,6 +2066,22 @@ importers: specifier: ^5.7.2 version: 5.9.3 + examples/quickstart/python: + dependencies: + '@rivet-dev/agentos': + specifier: workspace:* + version: link:../../../packages/agentos + devDependencies: + '@types/node': + specifier: ^22.10.2 + version: 22.19.15 + tsx: + specifier: ^4.19.0 + version: 4.21.0 + typescript: + specifier: ^5.7.2 + version: 5.9.3 + examples/quickstart/s3-filesystem: dependencies: '@agentos-software/claude-code': @@ -1857,9 +2099,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1871,7 +2110,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1906,9 +2145,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../../packages/agentos-sandbox @@ -1920,7 +2156,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -1955,9 +2191,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -1969,7 +2202,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -2004,9 +2237,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -2018,7 +2248,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -2053,9 +2283,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -2067,7 +2294,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -2111,9 +2338,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -2125,7 +2349,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -2160,9 +2384,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -2177,7 +2398,7 @@ importers: version: 4.12.9 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -2212,9 +2433,6 @@ importers: '@rivet-dev/agentos': specifier: workspace:* version: link:../../packages/agentos - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../../packages/core '@rivet-dev/agentos-sandbox': specifier: workspace:* version: link:../../packages/agentos-sandbox @@ -2226,7 +2444,7 @@ importers: version: 7.2.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) sandbox-agent: specifier: ^0.4.2 version: 0.4.2(dockerode@4.0.10)(get-port@7.2.0)(zod@4.3.6) @@ -2272,7 +2490,7 @@ importers: version: 9.14.0 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) tsx: specifier: ^4.19.0 version: 4.21.0 @@ -2306,10 +2524,10 @@ importers: version: link:../core '@rivetkit/react': specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(ws@8.21.0(bufferutil@4.1.0)) rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) zod: specifier: ^4.1.11 version: 4.3.6 @@ -2367,7 +2585,7 @@ importers: version: 3.4.19(tsx@4.21.0)(yaml@2.9.0) tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@1.21.7)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) + version: 8.5.1(@microsoft/api-extractor@7.43.0(@types/node@22.19.15))(jiti@1.21.7)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) typescript: specifier: ^5.7.3 version: 5.9.3 @@ -2417,7 +2635,7 @@ importers: version: 22.19.15 tsup: specifier: ^8.3.5 - version: 8.5.1(jiti@2.7.0)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) + version: 8.5.1(@microsoft/api-extractor@7.43.0(@types/node@22.19.15))(jiti@2.7.0)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) typescript: specifier: ^5.7.2 version: 5.9.3 @@ -2649,6 +2867,25 @@ importers: specifier: npm:zod@^3.25.76 version: zod@3.25.76 + packages/javascript: + dependencies: + '@rivet-dev/agentos-core': + specifier: workspace:* + version: link:../core + devDependencies: + '@types/node': + specifier: ^22.19.15 + version: 22.19.15 + tsup: + specifier: ^8.4.0 + version: 8.5.1(@microsoft/api-extractor@7.43.0(@types/node@22.19.15))(jiti@2.7.0)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) + typescript: + specifier: ^5.7.3 + version: 5.9.3 + vitest: + specifier: ^2.1.8 + version: 2.1.9(@types/node@22.19.15) + packages/manifest: devDependencies: '@types/node': @@ -2719,18 +2956,18 @@ importers: packages/python: dependencies: - '@rivet-dev/agentos-runtime-core': + '@rivet-dev/agentos-core': specifier: workspace:* - version: link:../runtime-core - pyodide: - specifier: ^0.28.3 - version: 0.28.3(bufferutil@4.1.0) + version: link:../core devDependencies: '@types/node': - specifier: ^22.10.2 + specifier: ^22.19.15 version: 22.19.15 + tsup: + specifier: ^8.4.0 + version: 8.5.1(@microsoft/api-extractor@7.43.0(@types/node@22.19.15))(jiti@2.7.0)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0) typescript: - specifier: ^5.7.2 + specifier: ^5.7.3 version: 5.9.3 vitest: specifier: ^2.1.8 @@ -2738,6 +2975,12 @@ importers: packages/runtime-benchmarks: dependencies: + '@rivet-dev/agentos': + specifier: workspace:* + version: link:../agentos + '@rivet-dev/agentos-javascript': + specifier: workspace:* + version: link:../javascript '@rivet-dev/agentos-runtime-core': specifier: workspace:* version: link:../runtime-core @@ -2812,50 +3055,6 @@ importers: packages/runtime-sidecar/npm/linux-x64-gnu: {} - packages/secure-exec: - dependencies: - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../core - devDependencies: - '@types/node': - specifier: ^22.10.2 - version: 22.19.15 - typescript: - specifier: ^5.7.2 - version: 5.9.3 - vitest: - specifier: ^2.1.8 - version: 2.1.9(@types/node@22.19.15) - - packages/secure-exec-example-ai-agent-type-check: - dependencies: - '@ai-sdk/anthropic': - specifier: ^3.0.58 - version: 3.0.64(zod@3.25.76) - '@rivet-dev/agentos-core': - specifier: workspace:* - version: link:../core - '@rivet-dev/agentos-typescript': - specifier: workspace:* - version: link:../typescript - ai: - specifier: ^6.0.116 - version: 6.0.141(zod@3.25.76) - typescript: - specifier: ^5.7.2 - version: 5.9.3 - zod: - specifier: ^3.24.0 - version: 3.25.76 - devDependencies: - '@types/node': - specifier: ^22.10.2 - version: 22.19.15 - tsx: - specifier: ^4.19.2 - version: 4.21.0 - packages/shell: dependencies: '@agentos-software/codex-cli': @@ -2938,7 +3137,7 @@ importers: version: 14.0.3 rivetkit: specifier: catalog:rivetkit - version: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + version: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) devDependencies: '@types/node': specifier: ^22.19.3 @@ -3120,14 +3319,14 @@ importers: version: 0.29.2(@cfworker/json-schema@4.1.1) '@anthropic-ai/claude-agent-sdk': specifier: 0.2.112 - version: 0.2.112(@cfworker/json-schema@4.1.1)(zod@3.25.76) + version: 0.2.112(@cfworker/json-schema@4.1.1)(zod@4.3.6) '@anthropic-ai/sdk': specifier: 0.111.0 - version: 0.111.0(zod@3.25.76) + version: 0.111.0(zod@4.3.6) devDependencies: '@agentclientprotocol/sdk': specifier: 1.2.1 - version: 1.2.1(zod@3.25.76) + version: 1.2.1(zod@4.3.6) '@agentos-software/manifest': specifier: workspace:* version: link:../../packages/manifest @@ -3998,12 +4197,6 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/anthropic@3.0.64': - resolution: {integrity: sha512-rwLi/Rsuj2pYniQXIrvClHvXDzgM4UQHHnvHTWEF14efnlKclG/1ghpNC+adsRujAbCTr6gRsSbDE2vEqriV7g==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/azure@2.0.104': resolution: {integrity: sha512-g0ZDc/IgNCnIQuMj+bCBPionZwH4YBkfj5/CYeEPNqWrGBJm3aYfuWCjdT6Yayg+zlimunHZIjpjdDwan3i8Qg==} engines: {node: '>=18'} @@ -4040,12 +4233,6 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/gateway@3.0.83': - resolution: {integrity: sha512-LvlWujbSdEkTBXBLFtF7GS6riXdHhH0O+DpDrCaNQvXeHmSF2jKsOg7JWXiCgygAHM5cWFAO3JYmZp83DjiuBQ==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/google-vertex@3.0.127': resolution: {integrity: sha512-kD2xC1HFbhNe5/yCJqkIP2rV40mlyK3IJiCoI6bwkjC5aPvWdBVoMIYvYcmM/eYlDYkPwC3pkUWd1HqRdLyzZw==} engines: {node: '>=18'} @@ -4106,12 +4293,6 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@4.0.21': - resolution: {integrity: sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider@2.0.1': resolution: {integrity: sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng==} engines: {node: '>=18'} @@ -4120,10 +4301,6 @@ packages: resolution: {integrity: sha512-h88OPkavHTiN9tMn2l5awAznGB0lXzjcLhgR1/rvjB2zlLprsNxbM2tt6OJsHUxduLC3klq0/eqaSf6fX5XVww==} engines: {node: '>=18'} - '@ai-sdk/provider@3.0.8': - resolution: {integrity: sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==} - engines: {node: '>=18'} - '@ai-sdk/togetherai@1.0.38': resolution: {integrity: sha512-3sdh58EZ2rz9fBL8flVIY70Qosmc2QBPO/pzFjXdtumfBL73KAWjweBs9HkQxrfM3jy5CuRaC8q5qBkktWGHeQ==} engines: {node: '>=18'} @@ -5516,6 +5693,19 @@ packages: engines: {node: '>=20.0.0'} deprecated: please use @earendil-works/pi-tui instead going forward + '@microsoft/api-extractor-model@7.28.13': + resolution: {integrity: sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==} + + '@microsoft/api-extractor@7.43.0': + resolution: {integrity: sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==} + hasBin: true + + '@microsoft/tsdoc-config@0.16.2': + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + + '@microsoft/tsdoc@0.14.2': + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + '@mistralai/mistralai@1.14.1': resolution: {integrity: sha512-IiLmmZFCCTReQgPAT33r7KQ1nYo5JPdvGkrkZqA8qQ2qB1GHgs5LoP5K2ICyrjnpw2n8oSxMM/VP+liiKcGNlQ==} @@ -5873,102 +6063,114 @@ packages: resolution: {integrity: sha512-3qndQUQXLdwafMEqfhz24hUtDPcsf1Bu3q52Kb8MqeH8JUh3h6R4HYW3ZJXiQsLcyYyFM68PuIwlLRlg1xDEpg==} engines: {node: ^14.18.0 || >=16.0.0} - '@rivetkit/engine-cli-darwin-arm64@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-ZT+wqmQzLznezyYVTzRHckWbp7F4yOG3ZCCON+ErdnWd84A4mwJMYXZPIObGD2OVSxmNhWqXO1ocNTKwDsIllw==} + '@rivetkit/engine-cli-darwin-arm64@2.3.7': + resolution: {integrity: sha512-F3yGSDIaW94BZzuAm3erQRT/Ki55wHJ/b6tOaE7d9tRmTAZw/XqHmjNdUYjOvFUQKLb+SSsOittM4dINrAANQQ==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [darwin] - '@rivetkit/engine-cli-darwin-x64@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-PgiKyvhciN17C7RjyB9J9ApVkCTJmdyaRZnsSmy0xdbNY12uKrhH2mNcaQAPV+7/QB4HB4TjVgD1wT+PCCGiQg==} + '@rivetkit/engine-cli-darwin-x64@2.3.7': + resolution: {integrity: sha512-P8BbQsamIvv8U/cEoJUFr+uAzwjjl9cG+ZZxjDX9OJxbuD11ESpHvDLgge54ijynO3IjoP8cIzjIXat6mr2Gkw==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [darwin] - '@rivetkit/engine-cli-linux-arm64-musl@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-2FZhrpzYfNIId3Tn0wpz1klcoKZjf2NBzGkmdxGQKY0kh7XynBsZxUnqyHJVFAkfLSSW+1t8E6PLTMSfPHIKXQ==} + '@rivetkit/engine-cli-linux-arm64-musl@2.3.7': + resolution: {integrity: sha512-G3s76BHfIs6R9rm6JYI13sOjPLy08+C8WvVoFwSdMqsibEaqlfo36wVkp/x1g0sEZUek/dBxVrKqMMR7c4/gug==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [linux] - '@rivetkit/engine-cli-linux-x64-musl@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-iw3v07nBtc1+qiQxl/g3HPT9UPOJUidvOYixPpxtydaRqh465/6pYy8cTzQOhEKBodBD3drsaB+6GJwDLy8CMA==} + '@rivetkit/engine-cli-linux-x64-musl@2.3.7': + resolution: {integrity: sha512-LWhrUVzULcsZ4ufCLsx23YfrdMW2INd9g0ANBac9+PzGwL8qYfVIXnDpR3587lapu68EbSEPZcconf1tBlvJxQ==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [linux] - '@rivetkit/engine-cli@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-5WYBHyO4Yudb2RuVbbp2srb/XDbEAdTihxUj/aUerahalR3KiNDo5zpUZpfhhoAQrjPQTVTN9Nan/RVloVpFRg==} + '@rivetkit/engine-cli-win32-x64@2.3.7': + resolution: {integrity: sha512-jyA5PlHivHXyyq2ehnuXwxd5TUSbB4emomnph9EovsJo7qIdmSNaaCO13NYBT483fd0uXiNI0MK/lkJa9ePY5A==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [win32] + + '@rivetkit/engine-cli@2.3.7': + resolution: {integrity: sha512-CezLwJ0B7dWDbA7qM6Aq04mwnrJAdrDActRrrcb4NBa20h7wO9KPAYBwyJz/dRnKm9EUUNcFZ6hrSDpp6T3+Rg==} engines: {node: '>= 20.0.0'} - '@rivetkit/engine-envoy-protocol@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-asUWA8E+fyD1RLQ5wH6KhCTNZ3laAqqS2bZQkcMQS8mQn/9BVl+sfCm/yM3hLK7lH7WT616sJhcP86EktZCLsA==} + '@rivetkit/engine-envoy-protocol@2.3.7': + resolution: {integrity: sha512-lsJM3ERwozQCebaOMKJzqIQlcLbbN3LXurRB0+7LsM6FUUL2l6hMoq5I2De/G35DJ6OWDva9AmzfvzI+5f1GPg==} - '@rivetkit/framework-base@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-s4yFjZZbcPXA++VfS5n1FgEohSG2gJec/svlmV2zko3Q4iqMip7g4/6DIU+5wsD1EkCwKE2dmuYdn0ML9sTtbQ==} + '@rivetkit/framework-base@2.3.7': + resolution: {integrity: sha512-zxmdAzFogA3PeT3ZgFIoYlEAJVi3iCwbPBXczZKf2x2QMCl2cTZ2jswFCAgHUUMQWj+AWiX65usxq73a9Ls/qQ==} '@rivetkit/on-change@6.0.1': resolution: {integrity: sha512-QBN/KRBXLJdCgN4gBTL3XAc/zKm58atSnieXWMOyFSPmo6F1/yIVV/LTRdvAktfCttrGx7W6c32i/lwqCHWnsQ==} engines: {node: '>=20'} - '@rivetkit/react@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-O2DWeQ7RvisfhVV0s5BOy/+BSSRrthS8ntVqFcDAhSiXKex6iUQSflhA4mkfcVW4/XWOzLmf2tNYPxEul/hKhw==} + '@rivetkit/react@2.3.7': + resolution: {integrity: sha512-Y3UoUYhkLKDQrJdloCmYK+fhJMlPw5BPHbRb5VutFh5L8csIRZLoCoMitzV7mjNUxuDE1+k10iGuUHYPZUP4aA==} peerDependencies: react: ^18 || ^19 react-dom: ^18 || ^19 - '@rivetkit/rivetkit-napi-darwin-arm64@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-sH/wB5IvlDQ7lktL7lk/1h5K8/Rxm/UYyY8GKGOdPzgIhBK7RNE194vhlLLgjWCU2P5eTo/uG8U5n7Shw1VoBA==} + '@rivetkit/rivetkit-napi-darwin-arm64@2.3.7': + resolution: {integrity: sha512-gI1wMe6z85VDeR4K/wnzevVakXTg5UCfvjlDOp1+23nyU3NlInhN156dEWO8EsfRMrs+1bYoGdc4rcoN+4PUrw==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [darwin] - '@rivetkit/rivetkit-napi-darwin-x64@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-E8Lt44QIOjzNnrFDWALpIFn3p593l57Y7z5mmY4oK0xScJlw8hL6jn0ISvCA1BRd0wPTy5/fwCUxGAivhhVJAg==} + '@rivetkit/rivetkit-napi-darwin-x64@2.3.7': + resolution: {integrity: sha512-H5tUwvCbKwTIBiyQG01ikK5mdc9ISg+bv8gPUw41mYOKq8rb9nBLkcl2TKcreFHac8KaGxtnBZzYcjbUV3NcwQ==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [darwin] - '@rivetkit/rivetkit-napi-linux-arm64-gnu@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-xdFAuc0s8tj6p63zeY/IoS0JKtnmTh6RyOauy+8cptTzGDUXcQnuzQU28YjPJ535je7aGIlJYfSXhL/rd4kmZA==} + '@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.7': + resolution: {integrity: sha512-MpOeiO5M737e93hM/FjcH+zv8xBEX1tgBd/59K/Uw7qlRbWW7JGz8WGjavdxv211LRqxsn8EUlGRxcADDsXnBA==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [linux] - '@rivetkit/rivetkit-napi-linux-arm64-musl@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-W6gTRHX1Sx9Oi2KoPpEN1fENEkF/dqvpc5OqNJErCcW8M2WCB/0BU/c7nHsP54ZLzS0kcZtaQov6qw0Nt2eaWA==} + '@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.7': + resolution: {integrity: sha512-0GsUgd/HHvIq6v92kp0H175mGm2Exvs4krBLih0MIpVAkqJk8EIcKI6wJhCwY04Fr0MS8sHkUhjuHXa7QcmlYA==} engines: {node: '>= 20.0.0'} cpu: [arm64] os: [linux] - '@rivetkit/rivetkit-napi-linux-x64-gnu@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-BY8SZke/5iHh35rFrkJ+GkmMelezHaIrClxjpZ6a3Yfu4owAfOUCOSTHZttYAoba4EdnCpB8aTQ2SimtvNN77g==} + '@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.7': + resolution: {integrity: sha512-8wCD1FuDpM+yiKRG8ro1K8ILVpJXzCNKViJ1axq1b4Nyqgod/nyEvvKDaT4qhA5+Om+W5i6YRO1uddjC6QjJSQ==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [linux] - '@rivetkit/rivetkit-napi-linux-x64-musl@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-rxtzRH2hpaz8hx6F1GIIM7f0FpDzyBKNtmusDQswmYajkm/Hfxl9ha2bleHg6EFtNVAr8gQ9cHAZcAv583bAJw==} + '@rivetkit/rivetkit-napi-linux-x64-musl@2.3.7': + resolution: {integrity: sha512-8RGzXD33GH1/DWufFzCZRI+npF5IL/9z7Ja3pthsuYgrL+axGG0iqfAjbwj5HHnB/ceUGQVT+uCKzoLnG+odtw==} engines: {node: '>= 20.0.0'} cpu: [x64] os: [linux] - '@rivetkit/rivetkit-napi@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-0SibmwqUugIfgRdwuG45+SvjMLzk5Bim/cViOtnt2FrucNB1E/YeC7QD4MxMi/Z+z+M/A33dljUst70C2f5uVA==} + '@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.7': + resolution: {integrity: sha512-n1by/coKxWOb2FZDGLM2qmULxcLSqx8hxJuk7Hsb1gl4uNHGviUzYr+r7WAiOzonK/Dgy477u3OKf5yBie743A==} + engines: {node: '>= 20.0.0'} + cpu: [x64] + os: [win32] + + '@rivetkit/rivetkit-napi@2.3.7': + resolution: {integrity: sha512-1d3HtNKzJwdkznWDWSpCwg1rBn+nVwUfcKrApINTfiEhfDyVeznwbVFkfHWqOBHsjU17vvWFfjjTtf8QsjLwUQ==} engines: {node: '>= 20.0.0'} - '@rivetkit/rivetkit-wasm@2.3.2': - resolution: {integrity: sha512-HNBzh6uQFi4ZYL0tHAZ6nrYKoGCfa+kObLCwdS+/ZzGePV7WGUl20Do1bHjBtnVgp9UwzQu+lka8kFwKfqm6WA==} + '@rivetkit/rivetkit-wasm@2.3.7': + resolution: {integrity: sha512-o7QBtFOJrajyPVBIDQ32k8sDNFsUc8v2ETfNpr+Ch374ydmZMzCv3XKJU9vubc9bZa7WpCHSzf5ztc8b8i/Xpg==} - '@rivetkit/traces@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-4d9Kodk7H0frBHNTmzJBXkOGKGgn5eU+A9XTmOTsoHIpPqK5AUrbJ35P2mQHQmzoU+WoHUumvey0Ze8UOKIy/Q==} + '@rivetkit/traces@2.3.7': + resolution: {integrity: sha512-B7QYjFP2HPxyfPsVjfcNIV7FPLWgGWGypmlT/dZM1i1Cf1WRdeuBumPLffgs3YceiY7Pm4D/gZZVt5p0m4Cx+A==} engines: {node: '>=18.0.0'} - '@rivetkit/virtual-websocket@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-U6C9jSf4VaQGEZTROFZHLsfCUci8No4ofBV6muzqmAKTiq6NN7mLE5V0muc0LTUx5dFpcX9hATJW1FSZVpnbYw==} + '@rivetkit/virtual-websocket@2.3.7': + resolution: {integrity: sha512-jwxDvYbr3YB6vFuxwRdB/AqUUMwdtC1rIAc4tNN6VQR3weHbE+PrDoHKbe85zrtlBtcnG89/p8tlovrj8qyQWA==} - '@rivetkit/workflow-engine@0.0.0-sqlite-uds.4e59a38': - resolution: {integrity: sha512-TUe2ZEg2D8yCNZTr+F6eeMp2uK2VAybYHhMj1IQUOuWwSyamBD8o5UFkqO12nYcE+52a7NwfHwhHEov8riVb1w==} + '@rivetkit/workflow-engine@2.3.7': + resolution: {integrity: sha512-+C4kGuSNysrw2zs/LQoYxouOxufKHHMxiIXKF8Ab9GU2BCJ32RUST9dYU/gaQE/w9uM+hqAHUz0DTlOBYU6p6g==} engines: {node: '>=18.0.0'} '@rolldown/pluginutils@1.0.0-beta.27': @@ -6099,6 +6301,28 @@ packages: cpu: [x64] os: [win32] + '@rushstack/node-core-library@4.0.2': + resolution: {integrity: sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.5.2': + resolution: {integrity: sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==} + + '@rushstack/terminal@0.10.0': + resolution: {integrity: sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@4.19.1': + resolution: {integrity: sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==} + '@sandbox-agent/cli-darwin-arm64@0.4.2': resolution: {integrity: sha512-+L1O8SI7k/LLhyB4dG0ghmz1cJHa0WtVjuRTrEE2gw/5EbGLWopPBsCVCmQ7snrQ4fPwtaiZDhfExcEj1VI7aw==} cpu: [arm64] @@ -6469,6 +6693,9 @@ packages: cpu: [arm64] os: [win32] + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -6615,12 +6842,6 @@ packages: peerDependencies: zod: ^3.25.76 || ^4.1.8 - ai@6.0.141: - resolution: {integrity: sha512-+GomGQWaId3xN0wcugUW/H7xMMaFkID2PiS7K/Wugj45G3efv0BXhQ3psRZoQVoRbOpdNoUqcK/KTB+FR4h6qg==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -6629,6 +6850,9 @@ packages: ajv: optional: true + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} @@ -6678,6 +6902,9 @@ packages: arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + asn1.js@4.10.1: resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} @@ -6824,6 +7051,9 @@ packages: bowser@2.14.1: resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + brace-expansion@1.1.16: + resolution: {integrity: sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==} + brace-expansion@2.0.3: resolution: {integrity: sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==} @@ -7056,10 +7286,17 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + compress-commons@6.0.2: resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} engines: {node: '>= 14'} + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concurrently@9.2.3: resolution: {integrity: sha512-ihjs0E2SxvDgq/MK418hX6YycQgKhsqxpbZuZbHo0yKfqDWdymWMjWYIpCIzqDDLLKClHlXev8whW/8WXmJ0BA==} engines: {node: '>=18'} @@ -7560,6 +7797,9 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} @@ -7667,6 +7907,10 @@ packages: fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -7896,6 +8140,10 @@ packages: immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} @@ -8036,6 +8284,9 @@ packages: resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + jose@6.2.2: resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} @@ -8061,6 +8312,9 @@ packages: resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} engines: {node: '>=16'} + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -8078,6 +8332,9 @@ packages: jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jszip@3.10.1: resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} @@ -8135,6 +8392,17 @@ packages: lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + lodash@4.18.1: resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} @@ -8161,6 +8429,10 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -8245,6 +8517,9 @@ packages: resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} + minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + minimatch@5.1.9: resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} engines: {node: '>=10'} @@ -8859,14 +9134,14 @@ packages: punycode@1.4.1: resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + puppeteer-core@22.15.0: resolution: {integrity: sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA==} engines: {node: '>=18'} - pyodide@0.28.3: - resolution: {integrity: sha512-rtCsyTU55oNGpLzSVuAd55ZvruJDEX8o6keSdWKN9jPeBVSNlynaKFG7eRqkiIgU7i2M6HEgYtm0atCEQX3u4A==} - engines: {node: '>=18.0.0'} - qs@6.15.0: resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} engines: {node: '>=0.6'} @@ -8992,6 +9267,9 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -9013,8 +9291,8 @@ packages: resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} engines: {node: '>= 0.8'} - rivetkit@0.0.0-sqlite-uds.4e59a38: - resolution: {integrity: sha512-cZnF3JMeMFirZISiYtZHGrpBPuFXN52A0ctEoM5zON2g7g17x4N3z+sNJOqaUenPL9f73Sv8YPU97UMdeDiZWQ==} + rivetkit@2.3.7: + resolution: {integrity: sha512-V2IWlXq9SRLJWrcYVa8WUftELCpbdsBVWZIqz2WQjhhzRK9Aan65RfMoZVx62A9k8HuIO6MH1nAPLhOuk1xePQ==} engines: {node: '>=22.0.0'} peerDependencies: drizzle-kit: ^0.31.2 @@ -9112,6 +9390,11 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + semver@7.7.4: resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} engines: {node: '>=10'} @@ -9234,6 +9517,9 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + ssh2@1.17.0: resolution: {integrity: sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==} engines: {node: '>=10.16.0'} @@ -9260,6 +9546,10 @@ packages: streamx@2.25.0: resolution: {integrity: sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==} + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -9290,6 +9580,10 @@ packages: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + strip-json-comments@5.0.3: resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} engines: {node: '>=14.16'} @@ -9493,6 +9787,11 @@ packages: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} + typescript@5.4.2: + resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} + engines: {node: '>=14.17'} + hasBin: true + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -9525,6 +9824,10 @@ packages: resolution: {integrity: sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg==} engines: {node: '>=22.19.0'} + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -9535,6 +9838,9 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-template@2.0.8: resolution: {integrity: sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==} @@ -9578,6 +9884,10 @@ packages: deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true + validator@13.15.35: + resolution: {integrity: sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==} + engines: {node: '>= 0.10'} + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -9779,6 +10089,9 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.8.3: resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} engines: {node: '>= 14.6'} @@ -9816,6 +10129,11 @@ packages: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} + z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + zip-stream@6.0.1: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} @@ -9838,9 +10156,9 @@ snapshots: '@agentclientprotocol/claude-agent-acp@0.29.2(@cfworker/json-schema@4.1.1)': dependencies: - '@agentclientprotocol/sdk': 0.19.0(zod@3.25.76) - '@anthropic-ai/claude-agent-sdk': 0.2.112(@cfworker/json-schema@4.1.1)(zod@3.25.76) - zod: 3.25.76 + '@agentclientprotocol/sdk': 0.19.0(zod@4.3.6) + '@anthropic-ai/claude-agent-sdk': 0.2.112(@cfworker/json-schema@4.1.1)(zod@4.3.6) + zod: 4.3.6 transitivePeerDependencies: - '@cfworker/json-schema' - supports-color @@ -9853,9 +10171,9 @@ snapshots: dependencies: zod: 4.3.6 - '@agentclientprotocol/sdk@0.19.0(zod@3.25.76)': + '@agentclientprotocol/sdk@0.19.0(zod@4.3.6)': dependencies: - zod: 3.25.76 + zod: 4.3.6 '@agentclientprotocol/sdk@0.21.0(zod@4.3.6)': dependencies: @@ -9894,12 +10212,6 @@ snapshots: zod: 4.3.6 optional: true - '@ai-sdk/anthropic@3.0.64(zod@3.25.76)': - dependencies: - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.21(zod@3.25.76) - zod: 3.25.76 - '@ai-sdk/azure@2.0.104(zod@4.3.6)': dependencies: '@ai-sdk/openai': 2.0.102(zod@4.3.6) @@ -9946,13 +10258,6 @@ snapshots: '@vercel/oidc': 3.1.0 zod: 4.3.6 - '@ai-sdk/gateway@3.0.83(zod@3.25.76)': - dependencies: - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.21(zod@3.25.76) - '@vercel/oidc': 3.1.0 - zod: 3.25.76 - '@ai-sdk/google-vertex@3.0.127(zod@4.3.6)': dependencies: '@ai-sdk/anthropic': 2.0.74(zod@4.3.6) @@ -10030,13 +10335,6 @@ snapshots: zod: 4.3.6 optional: true - '@ai-sdk/provider-utils@4.0.21(zod@3.25.76)': - dependencies: - '@ai-sdk/provider': 3.0.8 - '@standard-schema/spec': 1.1.0 - eventsource-parser: 3.0.6 - zod: 3.25.76 - '@ai-sdk/provider@2.0.1': dependencies: json-schema: 0.4.0 @@ -10046,10 +10344,6 @@ snapshots: json-schema: 0.4.0 optional: true - '@ai-sdk/provider@3.0.8': - dependencies: - json-schema: 0.4.0 - '@ai-sdk/togetherai@1.0.38(zod@4.3.6)': dependencies: '@ai-sdk/openai-compatible': 1.0.35(zod@4.3.6) @@ -10068,11 +10362,11 @@ snapshots: '@alloc/quick-lru@5.2.0': {} - '@anthropic-ai/claude-agent-sdk@0.2.112(@cfworker/json-schema@4.1.1)(zod@3.25.76)': + '@anthropic-ai/claude-agent-sdk@0.2.112(@cfworker/json-schema@4.1.1)(zod@4.3.6)': dependencies: - '@anthropic-ai/sdk': 0.81.0(zod@3.25.76) - '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76) - zod: 3.25.76 + '@anthropic-ai/sdk': 0.81.0(zod@4.3.6) + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6) + zod: 4.3.6 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.5 '@img/sharp-darwin-x64': 0.34.5 @@ -10118,12 +10412,12 @@ snapshots: '@img/sharp-win32-arm64': 0.34.5 '@img/sharp-win32-x64': 0.34.5 - '@anthropic-ai/sdk@0.111.0(zod@3.25.76)': + '@anthropic-ai/sdk@0.111.0(zod@4.3.6)': dependencies: json-schema-to-ts: 3.1.1 standardwebhooks: 1.0.0 optionalDependencies: - zod: 3.25.76 + zod: 4.3.6 '@anthropic-ai/sdk@0.39.0': dependencies: @@ -10143,17 +10437,23 @@ snapshots: optionalDependencies: zod: 3.25.76 + '@anthropic-ai/sdk@0.73.0(zod@4.3.6)': + dependencies: + json-schema-to-ts: 3.1.1 + optionalDependencies: + zod: 4.3.6 + '@anthropic-ai/sdk@0.74.0(zod@4.3.6)': dependencies: json-schema-to-ts: 3.1.1 optionalDependencies: zod: 4.3.6 - '@anthropic-ai/sdk@0.81.0(zod@3.25.76)': + '@anthropic-ai/sdk@0.81.0(zod@4.3.6)': dependencies: json-schema-to-ts: 3.1.1 optionalDependencies: - zod: 3.25.76 + zod: 4.3.6 '@anthropic-ai/sdk@0.91.1(zod@3.25.76)': dependencies: @@ -11870,6 +12170,18 @@ snapshots: - ws - zod + '@mariozechner/pi-agent-core@0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)': + dependencies: + '@mariozechner/pi-ai': 0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + '@mariozechner/pi-ai@0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@3.25.76)': dependencies: '@anthropic-ai/sdk': 0.73.0(zod@3.25.76) @@ -11894,6 +12206,30 @@ snapshots: - ws - zod + '@mariozechner/pi-ai@0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)': + dependencies: + '@anthropic-ai/sdk': 0.73.0(zod@4.3.6) + '@aws-sdk/client-bedrock-runtime': 3.1020.0 + '@google/genai': 1.47.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(bufferutil@4.1.0) + '@mistralai/mistralai': 1.14.1(bufferutil@4.1.0) + '@sinclair/typebox': 0.34.49 + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + chalk: 5.6.2 + openai: 6.26.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6) + partial-json: 0.1.7 + proxy-agent: 6.5.0 + undici: 7.24.6 + zod-to-json-schema: 3.25.2(zod@4.3.6) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + '@mariozechner/pi-coding-agent@0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@3.25.76))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@3.25.76)': dependencies: '@mariozechner/jiti': 2.6.5 @@ -11926,6 +12262,38 @@ snapshots: - ws - zod + '@mariozechner/pi-coding-agent@0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6)': + dependencies: + '@mariozechner/jiti': 2.6.5 + '@mariozechner/pi-agent-core': 0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6) + '@mariozechner/pi-ai': 0.60.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6))(bufferutil@4.1.0)(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6) + '@mariozechner/pi-tui': 0.60.0 + '@silvia-odwyer/photon-node': 0.3.4 + chalk: 5.6.2 + cli-highlight: 2.1.11 + diff: 8.0.4 + extract-zip: 2.0.1 + file-type: 21.3.4 + glob: 13.0.6 + hosted-git-info: 9.0.2 + ignore: 7.0.5 + marked: 15.0.12 + minimatch: 10.2.5 + proper-lockfile: 4.1.2 + strip-ansi: 7.2.0 + undici: 7.24.6 + yaml: 2.8.3 + optionalDependencies: + '@mariozechner/clipboard': 0.3.2 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + '@mariozechner/pi-tui@0.60.0': dependencies: '@types/mime-types': 2.1.4 @@ -11936,11 +12304,50 @@ snapshots: optionalDependencies: koffi: 2.15.2 + '@microsoft/api-extractor-model@7.28.13(@types/node@22.19.15)': + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@22.19.15) + transitivePeerDependencies: + - '@types/node' + optional: true + + '@microsoft/api-extractor@7.43.0(@types/node@22.19.15)': + dependencies: + '@microsoft/api-extractor-model': 7.28.13(@types/node@22.19.15) + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@22.19.15) + '@rushstack/rig-package': 0.5.2 + '@rushstack/terminal': 0.10.0(@types/node@22.19.15) + '@rushstack/ts-command-line': 4.19.1(@types/node@22.19.15) + lodash: 4.17.23 + minimatch: 3.0.8 + resolve: 1.22.11 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.4.2 + transitivePeerDependencies: + - '@types/node' + optional: true + + '@microsoft/tsdoc-config@0.16.2': + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + optional: true + + '@microsoft/tsdoc@0.14.2': + optional: true + '@mistralai/mistralai@1.14.1(bufferutil@4.1.0)': dependencies: ws: 8.21.0(bufferutil@4.1.0) - zod: 3.25.76 - zod-to-json-schema: 3.25.2(zod@3.25.76) + zod: 4.3.6 + zod-to-json-schema: 3.25.2(zod@4.3.6) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -11949,8 +12356,8 @@ snapshots: dependencies: '@opentelemetry/semantic-conventions': 1.43.0 ws: 8.21.0(bufferutil@4.1.0) - zod: 3.25.76 - zod-to-json-schema: 3.25.2(zod@3.25.76) + zod: 4.3.6 + zod-to-json-schema: 3.25.2(zod@4.3.6) optionalDependencies: '@opentelemetry/api': 1.9.0 transitivePeerDependencies: @@ -11961,8 +12368,8 @@ snapshots: dependencies: '@opentelemetry/semantic-conventions': 1.43.0 ws: 8.21.0(bufferutil@4.1.0) - zod: 3.25.76 - zod-to-json-schema: 3.25.2(zod@3.25.76) + zod: 4.3.6 + zod-to-json-schema: 3.25.2(zod@4.3.6) optionalDependencies: '@opentelemetry/api': 1.9.0 transitivePeerDependencies: @@ -12282,10 +12689,10 @@ snapshots: optionalDependencies: '@types/react': 19.2.17 - '@rivet-dev/agent-os-core@0.1.1(pyodide@0.28.3(bufferutil@4.1.0))': + '@rivet-dev/agent-os-core@0.1.1': dependencies: '@rivet-dev/agent-os-posix': 0.1.0 - '@rivet-dev/agent-os-python': 0.1.0(pyodide@0.28.3(bufferutil@4.1.0)) + '@rivet-dev/agent-os-python': 0.1.0 '@secure-exec/core': 0.2.1 '@secure-exec/nodejs': 0.2.1 '@secure-exec/v8': 0.2.1 @@ -12299,42 +12706,44 @@ snapshots: dependencies: '@secure-exec/core': 0.2.1 - '@rivet-dev/agent-os-python@0.1.0(pyodide@0.28.3(bufferutil@4.1.0))': + '@rivet-dev/agent-os-python@0.1.0': dependencies: '@secure-exec/core': 0.2.1 - optionalDependencies: - pyodide: 0.28.3(bufferutil@4.1.0) '@rivetkit/bare-ts@0.6.2': {} - '@rivetkit/engine-cli-darwin-arm64@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/engine-cli-darwin-arm64@2.3.7': + optional: true + + '@rivetkit/engine-cli-darwin-x64@2.3.7': optional: true - '@rivetkit/engine-cli-darwin-x64@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/engine-cli-linux-arm64-musl@2.3.7': optional: true - '@rivetkit/engine-cli-linux-arm64-musl@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/engine-cli-linux-x64-musl@2.3.7': optional: true - '@rivetkit/engine-cli-linux-x64-musl@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/engine-cli-win32-x64@2.3.7': optional: true - '@rivetkit/engine-cli@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/engine-cli@2.3.7': optionalDependencies: - '@rivetkit/engine-cli-darwin-arm64': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/engine-cli-darwin-x64': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/engine-cli-linux-arm64-musl': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/engine-cli-linux-x64-musl': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/engine-cli-darwin-arm64': 2.3.7 + '@rivetkit/engine-cli-darwin-x64': 2.3.7 + '@rivetkit/engine-cli-linux-arm64-musl': 2.3.7 + '@rivetkit/engine-cli-linux-x64-musl': 2.3.7 + '@rivetkit/engine-cli-win32-x64': 2.3.7 - '@rivetkit/engine-envoy-protocol@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/engine-envoy-protocol@2.3.7': dependencies: '@rivetkit/bare-ts': 0.6.2 - '@rivetkit/framework-base@0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0))': + '@rivetkit/framework-base@2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0))': dependencies: '@tanstack/store': 0.7.7 fast-deep-equal: 3.1.3 - rivetkit: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + rivetkit: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) transitivePeerDependencies: - '@aws-sdk/client-rds-data' - '@cloudflare/workers-types' @@ -12372,13 +12781,13 @@ snapshots: '@rivetkit/on-change@6.0.1': {} - '@rivetkit/react@0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(ws@8.21.0(bufferutil@4.1.0))': + '@rivetkit/react@2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(ws@8.21.0(bufferutil@4.1.0))': dependencies: - '@rivetkit/framework-base': 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + '@rivetkit/framework-base': 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) '@tanstack/react-store': 0.7.7(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - rivetkit: 0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)) + rivetkit: 2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)) transitivePeerDependencies: - '@aws-sdk/client-rds-data' - '@cloudflare/workers-types' @@ -12414,48 +12823,52 @@ snapshots: - sqlite3 - ws - '@rivetkit/rivetkit-napi-darwin-arm64@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/rivetkit-napi-darwin-arm64@2.3.7': + optional: true + + '@rivetkit/rivetkit-napi-darwin-x64@2.3.7': optional: true - '@rivetkit/rivetkit-napi-darwin-x64@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/rivetkit-napi-linux-arm64-gnu@2.3.7': optional: true - '@rivetkit/rivetkit-napi-linux-arm64-gnu@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/rivetkit-napi-linux-arm64-musl@2.3.7': optional: true - '@rivetkit/rivetkit-napi-linux-arm64-musl@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/rivetkit-napi-linux-x64-gnu@2.3.7': optional: true - '@rivetkit/rivetkit-napi-linux-x64-gnu@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/rivetkit-napi-linux-x64-musl@2.3.7': optional: true - '@rivetkit/rivetkit-napi-linux-x64-musl@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/rivetkit-napi-win32-x64-msvc@2.3.7': optional: true - '@rivetkit/rivetkit-napi@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/rivetkit-napi@2.3.7': dependencies: '@napi-rs/cli': 2.18.4 - '@rivetkit/engine-envoy-protocol': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/engine-envoy-protocol': 2.3.7 optionalDependencies: - '@rivetkit/rivetkit-napi-darwin-arm64': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/rivetkit-napi-darwin-x64': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/rivetkit-napi-linux-arm64-gnu': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/rivetkit-napi-linux-arm64-musl': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/rivetkit-napi-linux-x64-gnu': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/rivetkit-napi-linux-x64-musl': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/rivetkit-napi-darwin-arm64': 2.3.7 + '@rivetkit/rivetkit-napi-darwin-x64': 2.3.7 + '@rivetkit/rivetkit-napi-linux-arm64-gnu': 2.3.7 + '@rivetkit/rivetkit-napi-linux-arm64-musl': 2.3.7 + '@rivetkit/rivetkit-napi-linux-x64-gnu': 2.3.7 + '@rivetkit/rivetkit-napi-linux-x64-musl': 2.3.7 + '@rivetkit/rivetkit-napi-win32-x64-msvc': 2.3.7 - '@rivetkit/rivetkit-wasm@2.3.2': {} + '@rivetkit/rivetkit-wasm@2.3.7': {} - '@rivetkit/traces@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/traces@2.3.7': dependencies: '@rivetkit/bare-ts': 0.6.2 cbor-x: 1.6.4 fdb-tuple: 1.0.0 vbare: 0.0.4 - '@rivetkit/virtual-websocket@0.0.0-sqlite-uds.4e59a38': {} + '@rivetkit/virtual-websocket@2.3.7': {} - '@rivetkit/workflow-engine@0.0.0-sqlite-uds.4e59a38': + '@rivetkit/workflow-engine@2.3.7': dependencies: '@rivetkit/bare-ts': 0.6.2 cbor-x: 1.6.4 @@ -12540,6 +12953,42 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.60.1': optional: true + '@rushstack/node-core-library@4.0.2(@types/node@22.19.15)': + dependencies: + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.11 + semver: 7.5.4 + z-schema: 5.0.5 + optionalDependencies: + '@types/node': 22.19.15 + optional: true + + '@rushstack/rig-package@0.5.2': + dependencies: + resolve: 1.22.11 + strip-json-comments: 3.1.1 + optional: true + + '@rushstack/terminal@0.10.0(@types/node@22.19.15)': + dependencies: + '@rushstack/node-core-library': 4.0.2(@types/node@22.19.15) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 22.19.15 + optional: true + + '@rushstack/ts-command-line@4.19.1(@types/node@22.19.15)': + dependencies: + '@rushstack/terminal': 0.10.0(@types/node@22.19.15) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + optional: true + '@sandbox-agent/cli-darwin-arm64@0.4.2': optional: true @@ -13028,6 +13477,9 @@ snapshots: '@turbo/windows-arm64@2.9.1': optional: true + '@types/argparse@1.0.38': + optional: true + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.29.7 @@ -13209,18 +13661,18 @@ snapshots: '@opentelemetry/api': 1.9.0 zod: 4.3.6 - ai@6.0.141(zod@3.25.76): - dependencies: - '@ai-sdk/gateway': 3.0.83(zod@3.25.76) - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.21(zod@3.25.76) - '@opentelemetry/api': 1.9.0 - zod: 3.25.76 - ajv-formats@3.0.1(ajv@8.18.0): optionalDependencies: ajv: 8.18.0 + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + optional: true + ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 @@ -13279,6 +13731,11 @@ snapshots: arg@5.0.2: {} + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + optional: true + asn1.js@4.10.1: dependencies: bn.js: 4.12.4 @@ -13414,6 +13871,12 @@ snapshots: bowser@2.14.1: {} + brace-expansion@1.1.16: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + optional: true + brace-expansion@2.0.3: dependencies: balanced-match: 1.0.2 @@ -13723,6 +14186,9 @@ snapshots: commander@4.1.1: {} + commander@9.5.0: + optional: true + compress-commons@6.0.2: dependencies: crc-32: 1.2.2 @@ -13731,6 +14197,9 @@ snapshots: normalize-path: 3.0.0 readable-stream: 4.7.0 + concat-map@0.0.1: + optional: true + concurrently@9.2.3: dependencies: chalk: 4.1.2 @@ -14244,6 +14713,9 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 + fast-json-stable-stringify@2.1.0: + optional: true + fast-safe-stringify@2.1.1: {} fast-sha256@1.3.0: {} @@ -14363,6 +14835,13 @@ snapshots: fs-constants@1.0.0: {} + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + optional: true + fsevents@2.3.2: optional: true @@ -14638,6 +15117,9 @@ snapshots: immediate@3.0.6: {} + import-lazy@4.0.0: + optional: true + indent-string@4.0.0: {} inherits@2.0.4: {} @@ -14753,6 +15235,9 @@ snapshots: jiti@2.7.0: {} + jju@1.4.0: + optional: true + jose@6.2.2: {} joycon@3.1.1: {} @@ -14774,6 +15259,9 @@ snapshots: '@babel/runtime': 7.29.2 ts-algebra: 2.0.0 + json-schema-traverse@0.4.1: + optional: true + json-schema-traverse@1.0.0: {} json-schema-typed@8.0.2: {} @@ -14784,6 +15272,11 @@ snapshots: jsonc-parser@3.3.1: {} + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + optional: true + jszip@3.10.1: dependencies: lie: 3.3.0 @@ -14845,6 +15338,15 @@ snapshots: lodash.camelcase@4.3.0: {} + lodash.get@4.4.2: + optional: true + + lodash.isequal@4.5.0: + optional: true + + lodash@4.17.23: + optional: true + lodash@4.18.1: {} long-timeout@0.1.1: {} @@ -14865,6 +15367,11 @@ snapshots: dependencies: yallist: 3.1.1 + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + optional: true + lru-cache@7.18.3: {} magic-string@0.30.21: @@ -14928,6 +15435,11 @@ snapshots: dependencies: brace-expansion: 5.0.5 + minimatch@3.0.8: + dependencies: + brace-expansion: 1.1.16 + optional: true + minimatch@5.1.9: dependencies: brace-expansion: 2.0.3 @@ -14977,7 +15489,7 @@ snapshots: node-abi@3.89.0: dependencies: - semver: 7.7.4 + semver: 7.8.5 node-domexception@1.0.0: {} @@ -15151,6 +15663,11 @@ snapshots: ws: 8.21.0(bufferutil@4.1.0) zod: 3.25.76 + openai@6.26.0(ws@8.21.0(bufferutil@4.1.0))(zod@4.3.6): + optionalDependencies: + ws: 8.21.0(bufferutil@4.1.0) + zod: 4.3.6 + openapi3-ts@4.6.0: dependencies: yaml: 2.9.0 @@ -15557,6 +16074,9 @@ snapshots: punycode@1.4.1: {} + punycode@2.3.1: + optional: true + puppeteer-core@22.15.0(bufferutil@4.1.0): dependencies: '@puppeteer/browsers': 2.3.0 @@ -15573,13 +16093,6 @@ snapshots: - utf-8-validate optional: true - pyodide@0.28.3(bufferutil@4.1.0): - dependencies: - ws: 8.21.0(bufferutil@4.1.0) - transitivePeerDependencies: - - bufferutil - - utf-8-validate - qs@6.15.0: dependencies: side-channel: 1.1.0 @@ -15707,6 +16220,12 @@ snapshots: resolve-pkg-maps@1.0.0: {} + resolve@1.19.0: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + optional: true + resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -15724,19 +16243,19 @@ snapshots: hash-base: 3.1.2 inherits: 2.0.4 - rivetkit@0.0.0-sqlite-uds.4e59a38(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(pyodide@0.28.3(bufferutil@4.1.0))(ws@8.21.0(bufferutil@4.1.0)): + rivetkit@2.3.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(ws@8.21.0(bufferutil@4.1.0)): dependencies: '@hono/zod-openapi': 1.4.0(hono@4.12.9)(zod@4.3.6) - '@rivet-dev/agent-os-core': 0.1.1(pyodide@0.28.3(bufferutil@4.1.0)) + '@rivet-dev/agent-os-core': 0.1.1 '@rivetkit/bare-ts': 0.6.2 - '@rivetkit/engine-cli': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/engine-envoy-protocol': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/engine-cli': 2.3.7 + '@rivetkit/engine-envoy-protocol': 2.3.7 '@rivetkit/on-change': 6.0.1 - '@rivetkit/rivetkit-napi': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/rivetkit-wasm': 2.3.2 - '@rivetkit/traces': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/virtual-websocket': 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/workflow-engine': 0.0.0-sqlite-uds.4e59a38 + '@rivetkit/rivetkit-napi': 2.3.7 + '@rivetkit/rivetkit-wasm': 2.3.7 + '@rivetkit/traces': 2.3.7 + '@rivetkit/virtual-websocket': 2.3.7 + '@rivetkit/workflow-engine': 2.3.7 cbor-x: 1.6.4 drizzle-orm: 0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0) hono: 4.12.9 @@ -15871,6 +16390,11 @@ snapshots: semver@6.3.1: {} + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + optional: true + semver@7.7.4: {} semver@7.8.0: {} @@ -16005,6 +16529,9 @@ snapshots: split2@4.2.0: {} + sprintf-js@1.0.3: + optional: true + ssh2@1.17.0: dependencies: asn1: 0.2.6 @@ -16045,6 +16572,9 @@ snapshots: - bare-abort-controller - react-native-b4a + string-argv@0.3.2: + optional: true + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -16077,6 +16607,9 @@ snapshots: strip-json-comments@2.0.1: {} + strip-json-comments@3.1.1: + optional: true + strip-json-comments@5.0.3: {} strnum@2.2.2: {} @@ -16271,7 +16804,7 @@ snapshots: tslib@2.8.1: {} - tsup@8.5.1(jiti@1.21.7)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0): + tsup@8.5.1(@microsoft/api-extractor@7.43.0(@types/node@22.19.15))(jiti@1.21.7)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0): dependencies: bundle-require: 5.1.0(esbuild@0.27.4) cac: 6.7.14 @@ -16291,6 +16824,7 @@ snapshots: tinyglobby: 0.2.15 tree-kill: 1.2.2 optionalDependencies: + '@microsoft/api-extractor': 7.43.0(@types/node@22.19.15) postcss: 8.5.8 typescript: 5.9.3 transitivePeerDependencies: @@ -16299,7 +16833,7 @@ snapshots: - tsx - yaml - tsup@8.5.1(jiti@2.7.0)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0): + tsup@8.5.1(@microsoft/api-extractor@7.43.0(@types/node@22.19.15))(jiti@2.7.0)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.9.0): dependencies: bundle-require: 5.1.0(esbuild@0.27.4) cac: 6.7.14 @@ -16319,6 +16853,7 @@ snapshots: tinyglobby: 0.2.15 tree-kill: 1.2.2 optionalDependencies: + '@microsoft/api-extractor': 7.43.0(@types/node@22.19.15) postcss: 8.5.8 typescript: 5.9.3 transitivePeerDependencies: @@ -16369,6 +16904,9 @@ snapshots: es-errors: 1.3.0 is-typed-array: 1.1.15 + typescript@5.4.2: + optional: true + typescript@5.9.3: {} ufo@1.6.4: {} @@ -16391,6 +16929,9 @@ snapshots: undici@8.5.0: {} + universalify@0.1.2: + optional: true + unpipe@1.0.0: {} update-browserslist-db@1.2.3(browserslist@4.28.2): @@ -16399,6 +16940,11 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + optional: true + url-template@2.0.8: {} url@0.11.4: @@ -16433,6 +16979,9 @@ snapshots: uuid@9.0.1: {} + validator@13.15.35: + optional: true + vary@1.1.2: {} vbare@0.0.4: {} @@ -16601,6 +17150,9 @@ snapshots: yallist@3.1.1: {} + yallist@4.0.0: + optional: true + yaml@2.8.3: {} yaml@2.9.0: {} @@ -16638,6 +17190,15 @@ snapshots: yoctocolors@2.1.2: {} + z-schema@5.0.5: + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.15.35 + optionalDependencies: + commander: 9.5.0 + optional: true + zip-stream@6.0.1: dependencies: archiver-utils: 5.0.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 77cb7b4ff3..372d1b07fc 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,6 +2,8 @@ packages: - packages/agentos-sandbox - packages/agentos - packages/agentos-toolchain + - packages/javascript + - packages/python - packages/browser - packages/build-tools - packages/core @@ -9,15 +11,12 @@ packages: - packages/node-pty - packages/playground - packages/posix - - packages/python - packages/runtime-benchmarks - packages/runtime-browser - packages/runtime-core - packages/runtime-sidecar - packages/runtime-sidecar/npm/* - packages/vm-test-harness - - packages/secure-exec - - packages/secure-exec-example-ai-agent-type-check - packages/typescript - packages/shell - packages/sidecar-binary @@ -57,9 +56,9 @@ onlyBuiltDependencies: # pinned once here and referenced everywhere via `catalog:rivetkit`. catalogs: rivetkit: - rivetkit: 0.0.0-sqlite-uds.4e59a38 - '@rivetkit/react': 0.0.0-sqlite-uds.4e59a38 + rivetkit: 2.3.7 + '@rivetkit/react': 2.3.7 overrides: - '@rivetkit/rivetkit-wasm': 2.3.2 + '@rivetkit/rivetkit-wasm': 2.3.7 web-streams-polyfill: 3.3.3 diff --git a/scripts/benchmarks/README.md b/scripts/benchmarks/README.md index f3d22a70bd..328126856d 100644 --- a/scripts/benchmarks/README.md +++ b/scripts/benchmarks/README.md @@ -13,13 +13,13 @@ Agent OS keeps only product-surface benchmarks here: The differential matrix, focused runtime lanes, fuzz/perf harness, leak and footprint probes, native comparisons, and ecosystem command benches now live in -secure-exec: +agentos: -`/home/nathan/.herdr/workspaces/agent-os/secure-exec-perf-rules/packages/benchmarks` +`/home/nathan/.herdr/workspaces/agent-os/agentos-perf-rules/packages/benchmarks` Use that package for runtime-focused investigations; also follow its `CLAUDE.md` Benchmarks section. `overlay-readdir` is deleted here too; its -secure-exec port is pending the API it needs. +agentos port is pending the API it needs. ## Standard Suite diff --git a/scripts/benchmarks/session.bench.ts b/scripts/benchmarks/session.bench.ts index ef683114c9..93364ee4be 100644 --- a/scripts/benchmarks/session.bench.ts +++ b/scripts/benchmarks/session.bench.ts @@ -299,7 +299,7 @@ async function loadPiSoftware(): Promise { // non-snapshot fallback path and hides the optimization entirely. const local = join( import.meta.dirname, - "../../../secure-exec/software/pi/dist/index.js", + "../../../agentos/software/pi/dist/index.js", ); if (existsSync(local)) return (await import(local)).default; // Fallback: the published/installed software package. Variable specifier so @@ -309,7 +309,7 @@ async function loadPiSoftware(): Promise { return (await import(piPkg)).default; } catch { throw new Error( - "Could not resolve the pi software package (../secure-exec/software/pi/dist or @agentos-software/pi). Build it first.", + "Could not resolve the pi software package (../agentos/software/pi/dist or @agentos-software/pi). Build it first.", ); } } @@ -323,7 +323,7 @@ function findPiSdkRoot(): string | null { createRequire( join( import.meta.dirname, - "../../../secure-exec/software/pi/package.json", + "../../../agentos/software/pi/package.json", ), ), ]; @@ -373,7 +373,7 @@ function resolvePiSdkRootOrThrow(): string { * The bare-node session-creation script, run in a FRESH node process per sample * so each pays the full cold SDK load (the VM lane reloads the SDK in a fresh V8 * isolate every session, so this is the apples-to-apples "Node.js equivalent"). - * Mirrors secure-exec software/pi/src/adapter.ts `newSession`, with no VM. It times the + * Mirrors agentos software/pi/src/adapter.ts `newSession`, with no VM. It times the * SDK load + session construction internally and prints `__MS__=`. */ function bareNodeScript(root: string): string { diff --git a/scripts/check-agentos-client-protocol-compat.mjs b/scripts/check-agentos-client-protocol-compat.mjs index b0eba06e47..acb13e2149 100644 --- a/scripts/check-agentos-client-protocol-compat.mjs +++ b/scripts/check-agentos-client-protocol-compat.mjs @@ -11,12 +11,12 @@ const defaultRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const allowedCompatFiles = new Set([]); -const compatPattern = /\bsecure_exec_client::protocol\b/g; +const compatPattern = /\bagentos_client::protocol\b/g; const legacyWireConstantPattern = - /\bsecure_exec_client::protocol::DEFAULT_MAX_FRAME_BYTES\b/g; + /\bagentos_client::protocol::DEFAULT_MAX_FRAME_BYTES\b/g; const staleCompatibilityDocPattern = /\blive transport still uses the compatibility protocol surface\b/g; -const sidecarCompatPattern = /\bsecure_exec_sidecar::protocol\b/g; +const sidecarCompatPattern = /\bagentos_sidecar::protocol\b/g; function isDir(path) { return existsSync(path) && statSync(path).isDirectory(); @@ -56,7 +56,7 @@ function formatPath(root, path) { function reportSidecarProtocolUse(errors, source, rel, index) { const location = lineAndColumn(source, index); errors.push( - `${rel}:${location.line}:${location.column} imports the secure-exec sidecar compatibility protocol surface; use secure_exec_sidecar::wire for generated wire types`, + `${rel}:${location.line}:${location.column} imports the agentos sidecar compatibility protocol surface; use agentos_sidecar::wire for generated wire types`, ); } @@ -80,14 +80,14 @@ export function checkAgentOsClientProtocolCompat(options = {}) { for (const match of source.matchAll(legacyWireConstantPattern)) { const location = lineAndColumn(source, match.index ?? 0); errors.push( - `${rel}:${location.line}:${location.column} reads the default frame limit through the compatibility protocol surface; use secure_exec_client::wire::DEFAULT_MAX_FRAME_BYTES`, + `${rel}:${location.line}:${location.column} reads the default frame limit through the compatibility protocol surface; use agentos_client::wire::DEFAULT_MAX_FRAME_BYTES`, ); } staleCompatibilityDocPattern.lastIndex = 0; for (const match of source.matchAll(staleCompatibilityDocPattern)) { const location = lineAndColumn(source, match.index ?? 0); errors.push( - `${rel}:${location.line}:${location.column} documents stale generated-wire migration state; describe secure_exec_client::wire as the active transport surface`, + `${rel}:${location.line}:${location.column} documents stale generated-wire migration state; describe agentos_client::wire as the active transport surface`, ); } compatPattern.lastIndex = 0; @@ -95,7 +95,7 @@ export function checkAgentOsClientProtocolCompat(options = {}) { if (!allowedCompatFiles.has(rel)) { const location = lineAndColumn(source, match.index ?? 0); errors.push( - `${rel}:${location.line}:${location.column} imports the live protocol compatibility surface; use secure_exec_client::wire for generated wire types or add this file to the migration inventory with justification`, + `${rel}:${location.line}:${location.column} imports the live protocol compatibility surface; use agentos_client::wire for generated wire types or add this file to the migration inventory with justification`, ); } } diff --git a/scripts/check-agentos-client-protocol-compat.test.mjs b/scripts/check-agentos-client-protocol-compat.test.mjs index f49e5b7ed3..897ba8721b 100644 --- a/scripts/check-agentos-client-protocol-compat.test.mjs +++ b/scripts/check-agentos-client-protocol-compat.test.mjs @@ -58,13 +58,13 @@ test("allows agentos-sidecar generated wire imports", () => { root, "crates/agentos-sidecar/src/acp_extension.rs", [ - "use secure_exec_sidecar::wire::{", + "use agentos_sidecar::wire::{", "\tCloseStdinRequest, EventPayload, ExecuteRequest, GuestFilesystemCallRequest,", "\tGuestFilesystemOperation, GuestRuntimeKind, KillProcessRequest, StreamChannel,", "\tWriteStdinRequest,", "};", "", - "fn accepts(events: &[secure_exec_sidecar::wire::EventFrame]) {", + "fn accepts(events: &[agentos_sidecar::wire::EventFrame]) {", "\tlet _ = events;", "}", "", @@ -82,13 +82,13 @@ test("rejects agentos-sidecar primitive protocol imports", () => { root, "crates/agentos-sidecar/src/acp_extension.rs", [ - "use secure_exec_sidecar::protocol::{", + "use agentos_sidecar::protocol::{", "\tCloseStdinRequest, EventPayload, ExecuteRequest, GuestFilesystemCallRequest,", "\tGuestFilesystemOperation, GuestRuntimeKind, KillProcessRequest, StreamChannel,", "\tWriteStdinRequest,", "};", "", - "fn accepts(events: &[secure_exec_sidecar::protocol::EventFrame]) {", + "fn accepts(events: &[agentos_sidecar::protocol::EventFrame]) {", "\tlet _ = events;", "}", "", @@ -96,8 +96,8 @@ test("rejects agentos-sidecar primitive protocol imports", () => { ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/agentos-sidecar/src/acp_extension.rs:1:5 imports the secure-exec sidecar compatibility protocol surface; use secure_exec_sidecar::wire for generated wire types", - "crates/agentos-sidecar/src/acp_extension.rs:7:22 imports the secure-exec sidecar compatibility protocol surface; use secure_exec_sidecar::wire for generated wire types", + "crates/agentos-sidecar/src/acp_extension.rs:1:5 imports the agentos sidecar compatibility protocol surface; use agentos_sidecar::wire for generated wire types", + "crates/agentos-sidecar/src/acp_extension.rs:7:22 imports the agentos sidecar compatibility protocol surface; use agentos_sidecar::wire for generated wire types", ]); }); }); @@ -108,11 +108,11 @@ test("rejects new agentos-client live protocol imports outside the inventory", ( write( root, "crates/client/src/new_feature.rs", - "use secure_exec_client::protocol::RequestPayload;\n", + "use agentos_client::protocol::RequestPayload;\n", ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/client/src/new_feature.rs:1:5 imports the live protocol compatibility surface; use secure_exec_client::wire for generated wire types or add this file to the migration inventory with justification", + "crates/client/src/new_feature.rs:1:5 imports the live protocol compatibility surface; use agentos_client::wire for generated wire types or add this file to the migration inventory with justification", ]); }); }); @@ -123,11 +123,11 @@ test("rejects agentos-client test protocol imports", () => { write( root, "crates/client/tests/session_e2e.rs", - "use secure_exec_client::protocol::RequestPayload;\n", + "use agentos_client::protocol::RequestPayload;\n", ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/client/tests/session_e2e.rs:1:5 imports the live protocol compatibility surface; use secure_exec_client::wire for generated wire types or add this file to the migration inventory with justification", + "crates/client/tests/session_e2e.rs:1:5 imports the live protocol compatibility surface; use agentos_client::wire for generated wire types or add this file to the migration inventory with justification", ]); }); }); @@ -138,11 +138,11 @@ test("rejects production agentos-sidecar dispatch protocol imports", () => { write( root, "crates/agentos-sidecar/src/acp_extension.rs", - "use secure_exec_sidecar::protocol::{EventPayload, RequestFrame, SidecarRequestPayload};\n", + "use agentos_sidecar::protocol::{EventPayload, RequestFrame, SidecarRequestPayload};\n", ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/agentos-sidecar/src/acp_extension.rs:1:5 imports the secure-exec sidecar compatibility protocol surface; use secure_exec_sidecar::wire for generated wire types", + "crates/agentos-sidecar/src/acp_extension.rs:1:5 imports the agentos sidecar compatibility protocol surface; use agentos_sidecar::wire for generated wire types", ]); }); }); @@ -153,11 +153,11 @@ test("rejects agentos-sidecar test protocol imports", () => { write( root, "crates/agentos-sidecar/tests/acp_extension.rs", - "use secure_exec_sidecar::protocol::EventPayload;\n", + "use agentos_sidecar::protocol::EventPayload;\n", ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/agentos-sidecar/tests/acp_extension.rs:1:5 imports the secure-exec sidecar compatibility protocol surface; use secure_exec_sidecar::wire for generated wire types", + "crates/agentos-sidecar/tests/acp_extension.rs:1:5 imports the agentos sidecar compatibility protocol surface; use agentos_sidecar::wire for generated wire types", ]); }); }); @@ -168,11 +168,11 @@ test("rejects production agentos-sidecar qualified dispatch protocol paths", () write( root, "crates/agentos-sidecar/src/acp_extension.rs", - "fn dispatch() { let _ = secure_exec_sidecar::protocol::RequestFrame::new; }\n", + "fn dispatch() { let _ = agentos_sidecar::protocol::RequestFrame::new; }\n", ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/agentos-sidecar/src/acp_extension.rs:1:25 imports the secure-exec sidecar compatibility protocol surface; use secure_exec_sidecar::wire for generated wire types", + "crates/agentos-sidecar/src/acp_extension.rs:1:25 imports the agentos sidecar compatibility protocol surface; use agentos_sidecar::wire for generated wire types", ]); }); }); @@ -183,11 +183,11 @@ test("rejects error taxonomy regressions to the compatibility protocol surface", write( root, "crates/client/src/error.rs", - "use secure_exec_client::protocol::ProtocolCodecError;\n", + "use agentos_client::protocol::ProtocolCodecError;\n", ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/client/src/error.rs:1:5 imports the live protocol compatibility surface; use secure_exec_client::wire for generated wire types or add this file to the migration inventory with justification", + "crates/client/src/error.rs:1:5 imports the live protocol compatibility surface; use agentos_client::wire for generated wire types or add this file to the migration inventory with justification", ]); }); }); @@ -198,11 +198,11 @@ test("rejects docs regressions to naming the compatibility protocol surface", () write( root, "crates/client/src/lib.rs", - "//! The generated schema surface is secure_exec_client::wire, not secure_exec_client::protocol.\n", + "//! The generated schema surface is agentos_client::wire, not agentos_client::protocol.\n", ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/client/src/lib.rs:1:67 imports the live protocol compatibility surface; use secure_exec_client::wire for generated wire types or add this file to the migration inventory with justification", + "crates/client/src/lib.rs:1:63 imports the live protocol compatibility surface; use agentos_client::wire for generated wire types or add this file to the migration inventory with justification", ]); }); }); @@ -213,11 +213,11 @@ test("rejects docs regressions to stale generated-wire migration wording", () => write( root, "crates/client/src/lib.rs", - "//! secure_exec_client::wire; the live transport still uses the compatibility protocol surface while migration continues.\n", + "//! agentos_client::wire; the live transport still uses the compatibility protocol surface while migration continues.\n", ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/client/src/lib.rs:1:35 documents stale generated-wire migration state; describe secure_exec_client::wire as the active transport surface", + "crates/client/src/lib.rs:1:31 documents stale generated-wire migration state; describe agentos_client::wire as the active transport surface", ]); }); }); @@ -228,11 +228,11 @@ test("rejects auth version regressions to the compatibility protocol surface", ( root, "crates/client/src/sidecar.rs", [ - "use secure_exec_client::protocol::{AuthenticateRequest, RequestPayload};", + "use agentos_client::protocol::{AuthenticateRequest, RequestPayload};", "", "fn authenticate() {", "\tlet _ = RequestPayload::Authenticate(AuthenticateRequest {", - "\t\tprotocol_version: secure_exec_client::protocol::PROTOCOL_VERSION,", + "\t\tprotocol_version: agentos_client::protocol::PROTOCOL_VERSION,", "\t});", "}", "", @@ -240,8 +240,8 @@ test("rejects auth version regressions to the compatibility protocol surface", ( ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/client/src/sidecar.rs:1:5 imports the live protocol compatibility surface; use secure_exec_client::wire for generated wire types or add this file to the migration inventory with justification", - "crates/client/src/sidecar.rs:5:21 imports the live protocol compatibility surface; use secure_exec_client::wire for generated wire types or add this file to the migration inventory with justification", + "crates/client/src/sidecar.rs:1:5 imports the live protocol compatibility surface; use agentos_client::wire for generated wire types or add this file to the migration inventory with justification", + "crates/client/src/sidecar.rs:5:21 imports the live protocol compatibility surface; use agentos_client::wire for generated wire types or add this file to the migration inventory with justification", "crates/client/src/sidecar.rs must import agentos_sidecar_client::wire", "crates/client/src/sidecar.rs authenticate request must use wire::PROTOCOL_VERSION", ]); @@ -255,14 +255,14 @@ test("rejects default frame limit regressions to the compatibility protocol surf root, "crates/client/src/net.rs", [ - "const LIMIT: usize = secure_exec_client::protocol::DEFAULT_MAX_FRAME_BYTES;", + "const LIMIT: usize = agentos_client::protocol::DEFAULT_MAX_FRAME_BYTES;", "", ].join("\n"), ); assert.deepEqual(checkAgentOsClientProtocolCompat({ root }), [ - "crates/client/src/net.rs:1:22 reads the default frame limit through the compatibility protocol surface; use secure_exec_client::wire::DEFAULT_MAX_FRAME_BYTES", - "crates/client/src/net.rs:1:22 imports the live protocol compatibility surface; use secure_exec_client::wire for generated wire types or add this file to the migration inventory with justification", + "crates/client/src/net.rs:1:22 reads the default frame limit through the compatibility protocol surface; use agentos_client::wire::DEFAULT_MAX_FRAME_BYTES", + "crates/client/src/net.rs:1:22 imports the live protocol compatibility surface; use agentos_client::wire for generated wire types or add this file to the migration inventory with justification", ]); }); }); diff --git a/scripts/check-rust-package-metadata.test.mjs b/scripts/check-rust-package-metadata.test.mjs index bc8ba216f1..01ec27d4e2 100644 --- a/scripts/check-rust-package-metadata.test.mjs +++ b/scripts/check-rust-package-metadata.test.mjs @@ -37,10 +37,10 @@ test("accepts expected Rust package metadata", () => { assert.deepEqual(checkRustPackageMetadata({ root, metadata: validMetadata }), []); }); -test("rejects stale agentos-client lib target names", () => { +test("rejects noncanonical agentos-client lib target names", () => { const metadata = structuredClone(validMetadata); const client = metadata.packages.find((item) => item.name === "agentos-client"); - client.targets[0].name = "secure_exec_client"; + client.targets[0].name = "agent_os_client"; assert.deepEqual(checkRustPackageMetadata({ root, metadata }), [ "agentos-client must expose a lib target named agentos_client", diff --git a/scripts/ci.sh b/scripts/ci.sh index 006cec47b5..0cd0fc5370 100755 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -34,7 +34,7 @@ run_step node scripts/check-rust-package-metadata.mjs run_step node --test scripts/check-agentos-client-protocol-compat.test.mjs run_step node scripts/check-agentos-client-protocol-compat.mjs run_step pnpm check-layout -run_step node --test scripts/generate-secure-exec-mirror.test.mjs +run_step node --test scripts/generate-agentos-mirror.test.mjs if [[ -f scripts/check-registry-test-runtime-boundary.test.mjs ]]; then run_step node --test scripts/check-registry-test-runtime-boundary.test.mjs run_step node scripts/check-registry-test-runtime-boundary.mjs diff --git a/scripts/generate-secure-exec-mirror.mjs b/scripts/generate-secure-exec-mirror.mjs deleted file mode 100644 index 2877fb73f6..0000000000 --- a/scripts/generate-secure-exec-mirror.mjs +++ /dev/null @@ -1,395 +0,0 @@ -#!/usr/bin/env node -import { - mkdirSync, - readFileSync, - rmSync, - writeFileSync, -} from "node:fs"; -import { dirname, join, relative, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; - -const AGENTOS_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), ".."); -const DEFAULT_MIRROR_ROOT = resolve(AGENTOS_ROOT, "../secure-exec"); -const map = JSON.parse( - readFileSync(join(AGENTOS_ROOT, "scripts/secure-exec-agentos-map.json"), "utf8"), -); - -function parseArgs(argv) { - let mirrorRoot = DEFAULT_MIRROR_ROOT; - for (let i = 0; i < argv.length; i++) { - const arg = argv[i]; - if (arg === "--mirror-root") { - mirrorRoot = resolve(argv[++i]); - continue; - } - if (arg.startsWith("--mirror-root=")) { - mirrorRoot = resolve(arg.slice("--mirror-root=".length)); - continue; - } - throw new Error(`unknown argument: ${arg}`); - } - return { mirrorRoot }; -} - -function write(path, contents) { - mkdirSync(dirname(path), { recursive: true }); - writeFileSync(path, contents); -} - -function packageDirFor(pkg) { - if (pkg === "secure-exec") return "packages/secure-exec"; - const unscoped = pkg.replace(/^@secure-exec\//, ""); - return `packages/${unscoped}`; -} - -function crateDirFor(crateName) { - return `crates/${crateName.replace(/^secure-exec-/, "")}`; -} - -function json(value) { - return `${JSON.stringify(value, null, "\t")}\n`; -} - -function lockedRootVersion(lockfile, packageName) { - const importerStart = lockfile.indexOf("\n .:\n"); - const importerEnd = lockfile.indexOf("\n examples/", importerStart); - if (importerStart === -1 || importerEnd === -1) { - throw new Error("could not locate the AgentOS root importer in pnpm-lock.yaml"); - } - const importer = lockfile.slice(importerStart, importerEnd); - const match = importer.match( - new RegExp( - `\\n ${packageName}:\\n(?: [^\\n]*\\n)*? version: ([^\\n]+)`, - ), - ); - if (!match) { - throw new Error(`could not locate locked root dependency ${packageName}`); - } - return match[1]; -} - -function writePnpmLock(root, npmShims) { - const source = readFileSync(join(AGENTOS_ROOT, "pnpm-lock.yaml"), "utf8"); - const packagesStart = source.indexOf("\npackages:\n"); - if (packagesStart === -1) { - throw new Error("could not locate package snapshots in pnpm-lock.yaml"); - } - const turboVersion = lockedRootVersion(source, "turbo"); - const typescriptVersion = lockedRootVersion(source, "typescript"); - const importers = npmShims - .map((spec) => { - const packageDir = packageDirFor(spec.shimPackage); - const targetPath = join( - AGENTOS_ROOT, - spec.targetPath.replace(/^agentos\//, ""), - ); - const targetLink = `link:${relative(join(root, packageDir), targetPath)}`; - return ` ${packageDir}: - dependencies: - ${JSON.stringify(spec.targetPackage)}: - specifier: ${JSON.stringify(targetLink)} - version: ${JSON.stringify(targetLink)} - devDependencies: - typescript: - specifier: ^5.9.2 - version: ${typescriptVersion}`; - }) - .join("\n\n"); - write( - join(root, "pnpm-lock.yaml"), - `lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - turbo: - specifier: ^2.5.6 - version: ${turboVersion} - typescript: - specifier: ^5.9.2 - version: ${typescriptVersion} - -${importers} -${source.slice(packagesStart)}`, - ); -} - -function npmShimExports(targetPackage) { - return { - ".": { - types: "./dist/index.d.ts", - import: "./dist/index.js", - default: "./dist/index.js", - }, - "./package.json": "./package.json", - }; -} - -function writeNpmShim(root, spec) { - const packageName = spec.shimPackage; - const dir = join(root, packageDirFor(packageName)); - const target = spec.targetPackage; - const browserShim = packageName === "@secure-exec/browser"; - const targetPath = join(AGENTOS_ROOT, spec.targetPath.replace(/^agentos\//, "")); - const targetLink = `link:${relative(dir, targetPath)}`; - write( - join(dir, "package.json"), - json({ - name: packageName, - ...(browserShim ? { private: true } : {}), - version: "0.0.1", - type: "module", - license: "Apache-2.0", - description: `${packageName} compatibility shim for ${target}.`, - main: "./dist/index.js", - types: "./dist/index.d.ts", - files: ["dist", "README.md"], - exports: npmShimExports(target), - scripts: { - build: "tsc", - "check-types": "tsc --noEmit", - }, - dependencies: { - [target]: targetLink, - }, - devDependencies: { - typescript: "^5.9.2", - }, - }), - ); - write( - join(dir, "tsconfig.json"), - json({ - extends: "../../tsconfig.base.json", - compilerOptions: { - outDir: "dist", - rootDir: "src", - }, - include: ["src/**/*.ts"], - }), - ); - write( - join(dir, "src/index.ts"), - `export * from "${target}";\n`, - ); - write( - join(dir, "README.md"), - browserShim - ? `# ${packageName}\n\nCompatibility shim source for \`${target}\`. Browser runtime support is retained but disabled from default CI and publication pending a dedicated security design.\n` - : `# ${packageName}\n\nCompatibility shim for \`${target}\`.\n`, - ); -} - -function rustDependencyName(spec) { - return spec.targetPackage === "agentos-vfs-core" - ? "vfs" - : spec.targetRustIdentifier; -} - -function writeRustShim(root, spec) { - const dir = join(root, crateDirFor(spec.shimPackage)); - const browserShim = spec.shimPackage === "secure-exec-sidecar-browser"; - const targetRel = relative(dir, join(AGENTOS_ROOT, spec.targetPath.replace(/^agentos\//, ""))); - write( - join(dir, "Cargo.toml"), - `[package] -name = "${spec.shimPackage}" -version.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true -description = "${spec.shimPackage} compatibility shim for ${spec.targetPackage}" -${browserShim ? "publish = false" : ""} - -[lib] -name = "${spec.sourceRustIdentifier}" - -[dependencies] -${rustDependencyName(spec)} = { package = "${spec.targetPackage}", path = "${targetRel}", version = "0.0.1" } -`, - ); - write( - join(dir, "src/lib.rs"), - `//! Compatibility shim for \`${spec.targetPackage}\`.\n\npub use ${rustDependencyName(spec)}::*;\n`, - ); -} - -function writeRoot(root, npmShims, rustShims) { - write( - join(root, "package.json"), - json({ - name: "secure-exec-workspace", - private: true, - license: "Apache-2.0", - type: "module", - packageManager: "pnpm@10.13.1", - scripts: { - build: "turbo run build --filter='!@secure-exec/browser'", - "check-types": "turbo run check-types --filter='!@secure-exec/browser'", - test: "pnpm check-types", - }, - devDependencies: { - turbo: "^2.5.6", - typescript: "^5.9.2", - }, - }), - ); - write( - join(root, "pnpm-workspace.yaml"), - "packages:\n - packages/*\n\nonlyBuiltDependencies: []\n", - ); - write( - join(root, "turbo.json"), - json({ - $schema: "https://turbo.build/schema.json", - tasks: { - build: { - dependsOn: ["^build"], - outputs: ["dist/**"], - }, - "check-types": { - dependsOn: ["^check-types"], - outputs: [], - }, - }, - }), - ); - write( - join(root, "tsconfig.base.json"), - json({ - compilerOptions: { - target: "ES2022", - module: "NodeNext", - moduleResolution: "NodeNext", - declaration: true, - strict: true, - skipLibCheck: true, - }, - }), - ); - write( - join(root, "Cargo.toml"), - `[workspace] -resolver = "2" -members = [ -${rustShims.map((spec) => ` "${crateDirFor(spec.shimPackage)}",`).join("\n")} -] - -[workspace.package] -version = "0.0.1" -edition = "2021" -license = "Apache-2.0" -repository = "https://github.com/rivet-dev/secure-exec" -`, - ); - // Compatibility crates and AgentOS ship in lockstep. Seed the mirror from - // the authoritative runtime lock so Cargo cannot independently select a - // newer transitive API for path-linked AgentOS crates. - write(join(root, "Cargo.lock"), readFileSync(join(AGENTOS_ROOT, "Cargo.lock"))); - write( - join(root, "README.md"), - `# secure-exec\n\nCompatibility mirror. Active runtime development moved to the AgentOS runtime packages and crates.\n`, - ); - write( - join(root, "CLAUDE.md"), - "# secure-exec\n\nThis repository is a generated compatibility mirror. Make runtime changes in the AgentOS repository and regenerate the shims.\n", - ); - write( - join(root, "AGENTS.md"), - "# secure-exec\n\nThis repository is a generated compatibility mirror. Make runtime changes in the AgentOS repository and regenerate the shims.\n", - ); - write( - join(root, ".github/workflows/ci.yml"), - `name: CI - -on: - pull_request: - branches: [main] - push: - branches: [main] - -jobs: - static: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: pnpm - - uses: dtolnay/rust-toolchain@stable - - run: pnpm install --frozen-lockfile - - run: pnpm check-types - # Browser compatibility source is retained but disabled until its - # independent reactor/security design is complete. - - run: cargo check --workspace --exclude secure-exec-sidecar-browser -`, - ); - write( - join(root, ".github/workflows/publish.yaml"), - `name: publish - -on: - workflow_dispatch: - inputs: - version: - required: true - type: string - -jobs: - static: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: echo "secure-exec publishes generated compatibility shims only." -`, - ); - write( - join(root, ".github/workflows/sync-from-agentos.yml"), - `name: sync-from-agentos - -on: - workflow_dispatch: - -jobs: - static: - runs-on: ubuntu-latest - steps: - - run: echo "Regenerate this mirror from AgentOS with scripts/generate-secure-exec-mirror.mjs." -`, - ); -} - -function main() { - const { mirrorRoot } = parseArgs(process.argv.slice(2)); - const npmShims = map.npmPackages.filter((item) => item.shimPackage); - const rustShims = map.rustCrates.filter((item) => item.shimPackage); - - for (const rel of [ - "crates", - "docker", - "examples", - "packages", - "registry", - "scripts", - ".claude", - ".github/workflows", - ]) { - rmSync(join(mirrorRoot, rel), { recursive: true, force: true }); - } - writeRoot(mirrorRoot, npmShims, rustShims); - for (const spec of npmShims) writeNpmShim(mirrorRoot, spec); - for (const spec of rustShims) writeRustShim(mirrorRoot, spec); - writePnpmLock(mirrorRoot, npmShims); - console.log( - `generated ${npmShims.length} npm shims and ${rustShims.length} Rust shims in ${mirrorRoot}`, - ); -} - -main(); diff --git a/scripts/generate-secure-exec-mirror.test.mjs b/scripts/generate-secure-exec-mirror.test.mjs deleted file mode 100644 index b468d36c87..0000000000 --- a/scripts/generate-secure-exec-mirror.test.mjs +++ /dev/null @@ -1,83 +0,0 @@ -import assert from "node:assert/strict"; -import { execFileSync } from "node:child_process"; -import { - mkdtempSync, - readdirSync, - readFileSync, - rmSync, - statSync, - writeFileSync, -} from "node:fs"; -import { tmpdir } from "node:os"; -import { join, relative, resolve } from "node:path"; -import test from "node:test"; - -const repoRoot = resolve(import.meta.dirname, ".."); -const generator = join(repoRoot, "scripts/generate-secure-exec-mirror.mjs"); - -function generate(root) { - execFileSync(process.execPath, [generator, "--mirror-root", root], { - cwd: repoRoot, - stdio: "pipe", - }); -} - -function snapshot(root) { - const files = new Map(); - const visit = (directory) => { - for (const entry of readdirSync(directory).sort()) { - const path = join(directory, entry); - if (statSync(path).isDirectory()) visit(path); - else files.set(relative(root, path), readFileSync(path)); - } - }; - visit(root); - return files; -} - -test("secure-exec compatibility mirror generation is idempotent", () => { - const root = mkdtempSync(join(tmpdir(), "agentos-secure-exec-mirror-")); - try { - generate(root); - const first = snapshot(root); - writeFileSync(join(root, "packages/stale-generated-file"), "stale"); - generate(root); - assert.deepEqual(snapshot(root), first); - } finally { - rmSync(root, { recursive: true, force: true }); - } -}); - -test("generated browser compatibility shims stay private and excluded", () => { - const root = mkdtempSync(join(tmpdir(), "agentos-secure-exec-browser-")); - try { - generate(root); - const npmBrowser = JSON.parse( - readFileSync(join(root, "packages/browser/package.json"), "utf8"), - ); - assert.equal(npmBrowser.private, true); - const rustBrowser = readFileSync( - join(root, "crates/sidecar-browser/Cargo.toml"), - "utf8", - ); - assert.match(rustBrowser, /^publish = false$/m); - const workflow = readFileSync( - join(root, ".github/workflows/ci.yml"), - "utf8", - ); - assert.match(workflow, /--exclude secure-exec-sidecar-browser/); - const lockfile = readFileSync(join(root, "pnpm-lock.yaml"), "utf8"); - assert.match(lockfile, /^ packages\/browser:$/m); - assert.match( - lockfile, - new RegExp( - npmBrowser.dependencies["@rivet-dev/agentos-runtime-browser"].replace( - /[.*+?^${}()|[\]\\]/g, - "\\$&", - ), - ), - ); - } finally { - rmSync(root, { recursive: true, force: true }); - } -}); diff --git a/scripts/publish/src/lib/artifacts.test.ts b/scripts/publish/src/lib/artifacts.test.ts index 2548f159e5..6a03688199 100644 --- a/scripts/publish/src/lib/artifacts.test.ts +++ b/scripts/publish/src/lib/artifacts.test.ts @@ -18,23 +18,6 @@ test("defaults release artifact paths to agent-os", () => { ); }); -test("supports secure-exec release artifact namespace", () => { - const env = { - RELEASE_ARTIFACT_NAMESPACE: "secure-exec", - RELEASE_REPOSITORY_URL: "https://github.com/rivet-dev/secure-exec", - }; - - assert.equal(releaseArtifactNamespace(env), "secure-exec"); - assert.equal( - releaseArtifactPrefix({ ref: "0.3.0", name: "sidecar" }, env), - "secure-exec/0.3.0/sidecar/", - ); - assert.equal( - releaseUserAgent(env), - "secure-exec-release-publisher (https://github.com/rivet-dev/secure-exec)", - ); -}); - test("rejects invalid release artifact namespaces", () => { assert.throws( () => releaseArtifactNamespace({ RELEASE_ARTIFACT_NAMESPACE: "../agent-os" }), diff --git a/scripts/publish/src/lib/packages.test.ts b/scripts/publish/src/lib/packages.test.ts index 723b3355a4..08d245892d 100644 --- a/scripts/publish/src/lib/packages.test.ts +++ b/scripts/publish/src/lib/packages.test.ts @@ -74,8 +74,12 @@ test("builds platform map for the agent-os sidecar meta package", () => { test("sanity check passes for the agent-os workspace", () => { const packages = discoverPackages(repoRoot); + const names = new Set(packages.map((pkg) => pkg.name)); assert.doesNotThrow(() => assertDiscoverySanity(packages)); + assert(names.has("@rivet-dev/agentos")); + assert(names.has("@rivet-dev/agentos-javascript")); + assert(names.has("@rivet-dev/agentos-python")); }); test("browser migration packages stay explicitly excluded from publication", () => { diff --git a/scripts/publish/src/lib/packages.ts b/scripts/publish/src/lib/packages.ts index edebc0a19d..080c0e2446 100644 --- a/scripts/publish/src/lib/packages.ts +++ b/scripts/publish/src/lib/packages.ts @@ -40,7 +40,6 @@ export const EXCLUDED = new Set([ // unified sidecar reactor/security contract and must not be published. "@rivet-dev/agentos-browser", "@rivet-dev/agentos-runtime-browser", - "secure-exec", "publish", ]); @@ -220,7 +219,10 @@ export function assertDiscoverySanity(packages: Package[]): void { const required: string[] = []; if (hasAgentOsPackages) { required.push( + "@rivet-dev/agentos", "@rivet-dev/agentos-core", + "@rivet-dev/agentos-javascript", + "@rivet-dev/agentos-python", "@rivet-dev/agentos-sidecar", "@rivet-dev/agentos-runtime-sidecar", ); diff --git a/scripts/publish/src/lib/version.test.ts b/scripts/publish/src/lib/version.test.ts index d6fee5b8bf..6d6a4b8f8b 100644 --- a/scripts/publish/src/lib/version.test.ts +++ b/scripts/publish/src/lib/version.test.ts @@ -88,6 +88,8 @@ test("bumpPackageJsons injects sidecar platform optional dependencies", async () for (const [rel, name] of [ ["packages/agentos", "@rivet-dev/agentos"], ["packages/core", "@rivet-dev/agentos-core"], + ["packages/javascript", "@rivet-dev/agentos-javascript"], + ["packages/python", "@rivet-dev/agentos-python"], ["packages/sidecar-binary", "@rivet-dev/agentos-sidecar"], ["packages/runtime-sidecar", "@rivet-dev/agentos-runtime-sidecar"], ...DEFAULT_SIDECAR_PLATFORMS.map((platform) => [ diff --git a/scripts/secure-exec-agentos-map.json b/scripts/secure-exec-agentos-map.json deleted file mode 100644 index f257f17672..0000000000 --- a/scripts/secure-exec-agentos-map.json +++ /dev/null @@ -1,320 +0,0 @@ -{ - "schemaVersion": 1, - "createdAtPst": "2026-07-05", - "purpose": "Authoritative secure-exec -> AgentOS rename and shim map for the AgentOS/secure-exec flip.", - "decisions": { - "namingModel": "option-a-agentos-owned-core", - "typescriptRuntimeCore": "keep-separate", - "secureExecMirror": "generated-npm-and-crates-shims", - "registryOwnership": "agentos", - "envVarPolicy": "hard-rename-secure-exec-to-agentos-no-aliases", - "wireProtocolPolicy": "freeze-on-wire-version-and-namespace-string-values" - }, - "rustCrates": [ - { - "sourcePackage": "secure-exec-sidecar-browser", - "sourceDependencyKey": "secure-exec-sidecar-browser", - "sourceRustIdentifier": "secure_exec_sidecar_browser", - "sourcePath": "secure-exec/crates/sidecar-browser", - "targetPackage": "agentos-native-sidecar-browser", - "targetDependencyKey": "agentos-native-sidecar-browser", - "targetRustIdentifier": "agentos_native_sidecar_browser", - "targetPath": "agentos/crates/native-sidecar-browser", - "collision": "agentos already owns agentos-sidecar-browser", - "shimPackage": "secure-exec-sidecar-browser" - }, - { - "sourcePackage": "secure-exec-sidecar-core", - "sourceDependencyKey": "secure-exec-sidecar-core", - "sourceRustIdentifier": "secure_exec_sidecar_core", - "sourcePath": "secure-exec/crates/sidecar-core", - "targetPackage": "agentos-native-sidecar-core", - "targetDependencyKey": "agentos-native-sidecar-core", - "targetRustIdentifier": "agentos_native_sidecar_core", - "targetPath": "agentos/crates/native-sidecar-core", - "collision": "agentos already owns agentos-sidecar-core", - "shimPackage": "secure-exec-sidecar-core" - }, - { - "sourcePackage": "secure-exec-sidecar-protocol", - "sourceDependencyKey": "secure-exec-sidecar-protocol", - "sourceRustIdentifier": "secure_exec_sidecar_protocol", - "sourcePath": "secure-exec/crates/sidecar-protocol", - "targetPackage": "agentos-sidecar-protocol", - "targetDependencyKey": "agentos-sidecar-protocol", - "targetRustIdentifier": "agentos_sidecar_protocol", - "targetPath": "agentos/crates/sidecar-protocol", - "shimPackage": "secure-exec-sidecar-protocol" - }, - { - "sourcePackage": "secure-exec-sidecar", - "sourceDependencyKey": "secure-exec-sidecar", - "sourceRustIdentifier": "secure_exec_sidecar", - "sourcePath": "secure-exec/crates/sidecar", - "targetPackage": "agentos-native-sidecar", - "targetDependencyKey": "agentos-native-sidecar", - "targetRustIdentifier": "agentos_native_sidecar", - "targetPath": "agentos/crates/native-sidecar", - "collision": "agentos already owns agentos-sidecar", - "shimPackage": "secure-exec-sidecar" - }, - { - "sourcePackage": "secure-exec-client", - "sourceDependencyKey": "secure-exec-client", - "sourceRustIdentifier": "secure_exec_client", - "sourcePath": "secure-exec/crates/secure-exec-client", - "targetPackage": "agentos-sidecar-client", - "targetDependencyKey": "agentos-sidecar-client", - "targetRustIdentifier": "agentos_sidecar_client", - "targetPath": "agentos/crates/sidecar-client", - "collision": "agentos already owns agentos-client", - "shimPackage": "secure-exec-client" - }, - { - "sourcePackage": "secure-exec-build-support", - "sourceDependencyKey": "secure-exec-build-support", - "sourceRustIdentifier": "secure_exec_build_support", - "sourcePath": "secure-exec/crates/build-support", - "targetPackage": "agentos-build-support", - "targetDependencyKey": "agentos-build-support", - "targetRustIdentifier": "agentos_build_support", - "targetPath": "agentos/crates/build-support", - "shimPackage": "secure-exec-build-support" - }, - { - "sourcePackage": "secure-exec-v8-runtime", - "sourceDependencyKey": "secure-exec-v8-runtime", - "sourceRustIdentifier": "secure_exec_v8_runtime", - "sourcePath": "secure-exec/crates/v8-runtime", - "targetPackage": "agentos-v8-runtime", - "targetDependencyKey": "agentos-v8-runtime", - "targetRustIdentifier": "agentos_v8_runtime", - "targetPath": "agentos/crates/v8-runtime", - "shimPackage": "secure-exec-v8-runtime" - }, - { - "sourcePackage": "secure-exec-vm-config", - "sourceDependencyKey": "secure-exec-vm-config", - "sourceRustIdentifier": "secure_exec_vm_config", - "sourcePath": "secure-exec/crates/vm-config", - "targetPackage": "agentos-vm-config", - "targetDependencyKey": "agentos-vm-config", - "targetRustIdentifier": "agentos_vm_config", - "targetPath": "agentos/crates/vm-config", - "shimPackage": "secure-exec-vm-config" - }, - { - "sourcePackage": "secure-exec-execution", - "sourceDependencyKey": "secure-exec-execution", - "sourceRustIdentifier": "secure_exec_execution", - "sourcePath": "secure-exec/crates/execution", - "targetPackage": "agentos-execution", - "targetDependencyKey": "agentos-execution", - "targetRustIdentifier": "agentos_execution", - "targetPath": "agentos/crates/execution", - "shimPackage": "secure-exec-execution" - }, - { - "sourcePackage": "secure-exec-kernel", - "sourceDependencyKey": "secure-exec-kernel", - "sourceRustIdentifier": "secure_exec_kernel", - "sourcePath": "secure-exec/crates/kernel", - "targetPackage": "agentos-kernel", - "targetDependencyKey": "agentos-kernel", - "targetRustIdentifier": "agentos_kernel", - "targetPath": "agentos/crates/kernel", - "shimPackage": "secure-exec-kernel" - }, - { - "sourcePackage": "secure-exec-bridge", - "sourceDependencyKey": "secure-exec-bridge", - "sourceRustIdentifier": "secure_exec_bridge", - "sourcePath": "secure-exec/crates/bridge", - "targetPackage": "agentos-bridge", - "targetDependencyKey": "agentos-bridge", - "targetRustIdentifier": "agentos_bridge", - "targetPath": "agentos/crates/bridge", - "shimPackage": "secure-exec-bridge" - }, - { - "sourcePackage": "secure-exec-vfs-core", - "sourceDependencyKey": "vfs", - "sourceRustIdentifier": "secure_exec_vfs_core", - "sourcePath": "secure-exec/crates/vfs", - "targetPackage": "agentos-vfs-core", - "targetDependencyKey": "agentos-vfs-core", - "targetRustIdentifier": "agentos_vfs_core", - "targetPath": "agentos/crates/vfs", - "shimPackage": "secure-exec-vfs-core" - }, - { - "sourcePackage": "secure-exec-vfs", - "sourceDependencyKey": "secure-exec-vfs", - "sourceRustIdentifier": "secure_exec_vfs", - "sourcePath": "secure-exec/crates/secure-exec-vfs", - "targetPackage": "agentos-vfs", - "targetDependencyKey": "agentos-vfs", - "targetRustIdentifier": "agentos_vfs", - "targetPath": "agentos/crates/vfs-store", - "shimPackage": "secure-exec-vfs" - }, - { - "sourcePackage": "native-baseline", - "sourceDependencyKey": "native-baseline", - "sourceRustIdentifier": "native_baseline", - "sourcePath": "secure-exec/crates/native-baseline", - "targetPackage": "agentos-native-baseline", - "targetDependencyKey": "agentos-native-baseline", - "targetRustIdentifier": "agentos_native_baseline", - "targetPath": "agentos/crates/native-baseline", - "shimPackage": null - } - ], - "npmPackages": [ - { - "sourcePackage": "@secure-exec/core", - "sourcePath": "secure-exec/packages/core", - "targetPackage": "@rivet-dev/agentos-runtime-core", - "targetPath": "agentos/packages/runtime-core", - "shimPackage": "@secure-exec/core" - }, - { - "sourcePackage": "@secure-exec/browser", - "sourcePath": "secure-exec/packages/browser", - "targetPackage": "@rivet-dev/agentos-runtime-browser", - "targetPath": "agentos/packages/runtime-browser", - "shimPackage": "@secure-exec/browser" - }, - { - "sourcePackage": "@secure-exec/sandbox", - "sourcePath": "secure-exec/registry/tool/sandbox", - "targetPackage": "@rivet-dev/agentos-sandbox", - "targetPath": "agentos/packages/agentos-sandbox", - "migration": "fold into existing AgentOS sandbox wrapper package", - "shimPackage": "@secure-exec/sandbox" - }, - { - "sourcePackage": "@secure-exec/sidecar", - "sourcePath": "secure-exec/packages/sidecar", - "targetPackage": "@rivet-dev/agentos-sidecar", - "targetPath": "agentos/packages/sidecar-binary", - "migration": "fold into existing AgentOS native sidecar resolver package", - "shimPackage": "@secure-exec/sidecar" - }, - { - "sourcePackage": "@secure-exec/typescript", - "sourcePath": "secure-exec/packages/typescript", - "targetPackage": "@rivet-dev/agentos-typescript", - "targetPath": "agentos/packages/typescript", - "shimPackage": "@secure-exec/typescript" - }, - { - "sourcePackage": "@secure-exec/build-tools", - "sourcePath": "secure-exec/packages/build-tools", - "targetPackage": "@rivet-dev/agentos-build-tools", - "targetPath": "agentos/packages/build-tools", - "private": true, - "shimPackage": null - }, - { - "sourcePackage": "@secure-exec/benchmarks", - "sourcePath": "secure-exec/packages/benchmarks", - "targetPackage": "@rivet-dev/agentos-benchmarks", - "targetPath": "agentos/packages/benchmarks", - "private": true, - "shimPackage": null - }, - { - "sourcePackage": "secure-exec", - "sourcePath": "secure-exec/packages/secure-exec", - "targetPackage": "@rivet-dev/agentos-runtime-core", - "targetPath": "agentos/packages/runtime-core", - "migration": "facade shim; no AgentOS package named secure-exec", - "shimPackage": "secure-exec" - } - ], - "unchangedNpmPackagesMovingToAgentos": [ - { - "package": "@rivet-dev/agentos-toolchain", - "sourcePath": "secure-exec/packages/agentos-toolchain", - "targetPath": "agentos/packages/agentos-toolchain" - }, - { - "package": "@agentos-software/manifest", - "sourcePath": "secure-exec/packages/manifest", - "targetPath": "agentos/packages/manifest" - }, - { - "packageGlob": "@agentos-software/*", - "sourcePathGlob": "secure-exec/registry/{agent,software}/*", - "targetPathGlob": "agentos/software/*" - } - ], - "scriptedReplacementOrder": [ - ["secure_exec_sidecar_v1", "agentos_sidecar_v1"], - ["secure-exec-sidecar-v1", "agentos-sidecar-v1"], - ["secure_exec_sidecar_browser", "agentos_native_sidecar_browser"], - ["secure-exec-sidecar-browser", "agentos-native-sidecar-browser"], - ["secure_exec_sidecar_core", "agentos_native_sidecar_core"], - ["secure-exec-sidecar-core", "agentos-native-sidecar-core"], - ["secure_exec_sidecar_protocol", "agentos_sidecar_protocol"], - ["secure-exec-sidecar-protocol", "agentos-sidecar-protocol"], - ["secure_exec_sidecar", "agentos_native_sidecar"], - ["secure-exec-sidecar", "agentos-native-sidecar"], - ["secure_exec_client", "agentos_sidecar_client"], - ["secure-exec-client", "agentos-sidecar-client"], - ["secure_exec_build_support", "agentos_build_support"], - ["secure-exec-build-support", "agentos-build-support"], - ["secure_exec_v8_runtime", "agentos_v8_runtime"], - ["secure-exec-v8-runtime", "agentos-v8-runtime"], - ["secure_exec_vm_config", "agentos_vm_config"], - ["secure-exec-vm-config", "agentos-vm-config"], - ["secure_exec_execution", "agentos_execution"], - ["secure-exec-execution", "agentos-execution"], - ["secure_exec_kernel", "agentos_kernel"], - ["secure-exec-kernel", "agentos-kernel"], - ["secure_exec_bridge", "agentos_bridge"], - ["secure-exec-bridge", "agentos-bridge"], - ["secure_exec_vfs_core", "agentos_vfs_core"], - ["secure-exec-vfs-core", "agentos-vfs-core"], - ["secure_exec_vfs", "agentos_vfs"], - ["secure-exec-vfs", "agentos-vfs"], - ["native_baseline", "agentos_native_baseline"], - ["native-baseline", "agentos-native-baseline"], - ["@secure-exec/typescript", "@rivet-dev/agentos-typescript"], - ["@secure-exec/build-tools", "@rivet-dev/agentos-build-tools"], - ["@secure-exec/benchmarks", "@rivet-dev/agentos-benchmarks"], - ["@secure-exec/browser", "@rivet-dev/agentos-runtime-browser"], - ["@secure-exec/sandbox", "@rivet-dev/agentos-sandbox"], - ["@secure-exec/sidecar", "@rivet-dev/agentos-sidecar"], - ["@secure-exec/core", "@rivet-dev/agentos-runtime-core"], - ["SECURE_EXEC_KEEP_STDIN_OPEN", "AGENTOS_KEEP_STDIN_OPEN"], - ["SECURE_EXEC_SIDECAR_BIN", "AGENTOS_SIDECAR_BIN"], - ["SECURE_EXEC_WORKSPACE_PACKAGES", "AGENTOS_WORKSPACE_PACKAGES"], - ["SECURE_EXEC_WASM_COMMANDS_DIR", "AGENTOS_WASM_COMMANDS_DIR"], - ["SECURE_EXEC_C_WASM_COMMANDS_DIR", "AGENTOS_C_WASM_COMMANDS_DIR"], - ["SECURE_EXEC_C_ROOT", "AGENTOS_C_ROOT"], - ["SECURE_EXEC_ROOT", "AGENTOS_ROOT"], - ["SECURE_EXEC_LOCAL_PATH", "AGENTOS_LOCAL_PATH"], - ["SECURE_EXEC_GIT_URL", "AGENTOS_GIT_URL"], - ["SECURE_EXEC_REPO", "AGENTOS_REPO"], - ["SECURE_EXEC_DISPATCH_TOKEN", "AGENTOS_DISPATCH_TOKEN"], - ["SECURE_EXEC_LOG", "AGENTOS_LOG"], - ["SECURE_EXEC_TEST_HTTP_LOOPBACK_REQUEST_TIMEOUT_MS", "AGENTOS_TEST_HTTP_LOOPBACK_REQUEST_TIMEOUT_MS"], - ["__SECURE_EXEC_WASM_SYNC_READ_LIMIT_BYTES__", "__AGENTOS_WASM_SYNC_READ_LIMIT_BYTES__"], - ["__secure_exec_typescript_input__", "__agentos_typescript_input__"], - ["__secure_exec_net_timeout__", "__agentos_net_timeout__"] - ], - "manualLandmines": [ - "Do not mechanically rename string values used as on-wire PROTOCOL_VERSION values.", - "Do not mechanically rename ACP namespace string value dev.rivet.agent-os.acp.", - "Rename secure_exec_pyodide_unavailable to agentos_pyodide_unavailable in both execution/build.rs and python.rs in the same pass.", - "Update build.rs fixture paths after @secure-exec/core moves to packages/runtime-core.", - "Regenerate generated browser bundles instead of hand-editing baked paths.", - "Fold @secure-exec/sandbox into the existing @rivet-dev/agentos-sandbox package instead of creating a duplicate package.", - "Fold @secure-exec/sidecar into the existing @rivet-dev/agentos-sidecar resolver package instead of creating a duplicate package." - ], - "frozenWireStringValues": [ - "dev.rivet.agent-os.acp" - ] -} diff --git a/software/README.md b/software/README.md index d104021d1e..025d699599 100644 --- a/software/README.md +++ b/software/README.md @@ -1,6 +1,6 @@ # agentOS Software Catalog -Software packages for secure-exec VMs: WASM command binaries +Software packages for agentos VMs: WASM command binaries and JavaScript agent adapters live together under `software/*`. Everything in this catalog publishes under the `@agentos-software/*` npm scope. diff --git a/software/browserbase/package.json b/software/browserbase/package.json index fd6512e4b5..d610716e7f 100644 --- a/software/browserbase/package.json +++ b/software/browserbase/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "Browserbase browse CLI for secure-exec VMs (cloud browser automation)", + "description": "Browserbase browse CLI for agentos VMs (cloud browser automation)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "bin": { diff --git a/software/build-essential/package.json b/software/build-essential/package.json index 1ad710650f..e4a24af26c 100644 --- a/software/build-essential/package.json +++ b/software/build-essential/package.json @@ -3,7 +3,7 @@ "version": "0.3.0-rc.2", "type": "module", "license": "Apache-2.0", - "description": "Build-essential WASM command set for secure-exec VMs (common + git + curl)", + "description": "Build-essential WASM command set for agentos VMs (common + git + curl)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/codex-cli/native/crates/cmd-codex-exec/Cargo.toml b/software/codex-cli/native/crates/cmd-codex-exec/Cargo.toml index eeca177f14..4821e31d5a 100644 --- a/software/codex-cli/native/crates/cmd-codex-exec/Cargo.toml +++ b/software/codex-cli/native/crates/cmd-codex-exec/Cargo.toml @@ -4,14 +4,14 @@ name = "cmd-codex-exec" version.workspace = true edition.workspace = true license.workspace = true -description = "codex-exec command binary for secure-exec VM" +description = "codex-exec command binary for agentos VM" [[bin]] name = "codex-exec" path = "src/main.rs" [dependencies] -wasi-http = { package = "secureexec-wasi-http", path = "../../../../../toolchain/crates/libs/wasi-http" } +wasi-http = { package = "agentos-wasi-http", path = "../../../../../toolchain/crates/libs/wasi-http" } # WASI stub crates for future codex-core dependencies that don't support wasm32-wasip1. codex-network-proxy = "0.0.0" diff --git a/software/codex-cli/native/crates/cmd-codex-exec/src/main.rs b/software/codex-cli/native/crates/cmd-codex-exec/src/main.rs index 47c22f67f3..2f83f8697e 100644 --- a/software/codex-cli/native/crates/cmd-codex-exec/src/main.rs +++ b/software/codex-cli/native/crates/cmd-codex-exec/src/main.rs @@ -1,4 +1,4 @@ -/// Codex headless command for secure-exec VM. +/// Codex headless command for agentos VM. /// /// The prompt mode remains a placeholder command. The ACP session-turn path is /// disabled until it can delegate to the real Codex agent package instead of a diff --git a/software/codex-cli/native/crates/cmd-codex/Cargo.toml b/software/codex-cli/native/crates/cmd-codex/Cargo.toml index cc73f06a16..bcf4b29a2a 100644 --- a/software/codex-cli/native/crates/cmd-codex/Cargo.toml +++ b/software/codex-cli/native/crates/cmd-codex/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-codex" version.workspace = true edition.workspace = true license.workspace = true -description = "codex standalone binary for secure-exec VM" +description = "codex standalone binary for agentos VM" [[bin]] name = "codex" @@ -21,8 +21,8 @@ path = "src/main.rs" # tokio::process::Command in codex-core when compiled for WASI. [dependencies] -wasi-spawn = { package = "secureexec-wasi-spawn", path = "../../../../../toolchain/crates/libs/wasi-spawn" } -wasi-http = { package = "secureexec-wasi-http", path = "../../../../../toolchain/crates/libs/wasi-http" } +wasi-spawn = { package = "agentos-wasi-spawn", path = "../../../../../toolchain/crates/libs/wasi-spawn" } +wasi-http = { package = "agentos-wasi-http", path = "../../../../../toolchain/crates/libs/wasi-http" } # TUI dependencies — ratatui for rendering, crossterm for terminal backend # crossterm is patched for WASI support (see std-patches/crates/crossterm/) diff --git a/software/codex-cli/native/crates/cmd-codex/src/main.rs b/software/codex-cli/native/crates/cmd-codex/src/main.rs index 88f5d80c09..ab7075f943 100644 --- a/software/codex-cli/native/crates/cmd-codex/src/main.rs +++ b/software/codex-cli/native/crates/cmd-codex/src/main.rs @@ -1,4 +1,4 @@ -/// Codex TUI for secure-exec VM. +/// Codex TUI for agentos VM. /// /// Full terminal UI using ratatui + crossterm backend, rendering through /// the WasmVM PTY. This is the interactive entry point — for headless @@ -276,7 +276,7 @@ fn draw_ui(f: &mut Frame, input: &str, messages: &[String], model: Option<&str>) fn print_help() { println!( - "codex {} — interactive Codex TUI for secure-exec VM", + "codex {} — interactive Codex TUI for agentos VM", VERSION ); println!(); diff --git a/software/codex-cli/package.json b/software/codex-cli/package.json index afa587abfa..dc6d5c65f7 100644 --- a/software/codex-cli/package.json +++ b/software/codex-cli/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "OpenAI Codex command package for secure-exec VMs", + "description": "OpenAI Codex command package for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/common/package.json b/software/common/package.json index 8194cac3d7..275b286fa4 100644 --- a/software/common/package.json +++ b/software/common/package.json @@ -3,7 +3,7 @@ "version": "0.3.0-rc.2", "type": "module", "license": "Apache-2.0", - "description": "Common WASM command set for secure-exec VMs (coreutils + sed + grep + gawk + findutils + diffutils + tar + gzip)", + "description": "Common WASM command set for agentos VMs (coreutils + sed + grep + gawk + findutils + diffutils + tar + gzip)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/coreutils/native/crates/cmd-arch/Cargo.toml b/software/coreutils/native/crates/cmd-arch/Cargo.toml index cb72652e83..a09e7e2213 100644 --- a/software/coreutils/native/crates/cmd-arch/Cargo.toml +++ b/software/coreutils/native/crates/cmd-arch/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-arch" version.workspace = true edition.workspace = true license.workspace = true -description = "arch standalone binary for secure-exec VM" +description = "arch standalone binary for agentos VM" [[bin]] name = "arch" diff --git a/software/coreutils/native/crates/cmd-b2sum/Cargo.toml b/software/coreutils/native/crates/cmd-b2sum/Cargo.toml index 3f5da391a6..38757a3a6e 100644 --- a/software/coreutils/native/crates/cmd-b2sum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-b2sum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-b2sum" version.workspace = true edition.workspace = true license.workspace = true -description = "b2sum standalone binary for secure-exec VM" +description = "b2sum standalone binary for agentos VM" [[bin]] name = "b2sum" diff --git a/software/coreutils/native/crates/cmd-base32/Cargo.toml b/software/coreutils/native/crates/cmd-base32/Cargo.toml index 29ea0a98a1..2ff6c26071 100644 --- a/software/coreutils/native/crates/cmd-base32/Cargo.toml +++ b/software/coreutils/native/crates/cmd-base32/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-base32" version.workspace = true edition.workspace = true license.workspace = true -description = "base32 standalone binary for secure-exec VM" +description = "base32 standalone binary for agentos VM" [[bin]] name = "base32" diff --git a/software/coreutils/native/crates/cmd-base64/Cargo.toml b/software/coreutils/native/crates/cmd-base64/Cargo.toml index 105af17592..e74c2cddc3 100644 --- a/software/coreutils/native/crates/cmd-base64/Cargo.toml +++ b/software/coreutils/native/crates/cmd-base64/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-base64" version.workspace = true edition.workspace = true license.workspace = true -description = "base64 standalone binary for secure-exec VM" +description = "base64 standalone binary for agentos VM" [[bin]] name = "base64" diff --git a/software/coreutils/native/crates/cmd-basename/Cargo.toml b/software/coreutils/native/crates/cmd-basename/Cargo.toml index aac009cc30..883b847502 100644 --- a/software/coreutils/native/crates/cmd-basename/Cargo.toml +++ b/software/coreutils/native/crates/cmd-basename/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-basename" version.workspace = true edition.workspace = true license.workspace = true -description = "basename standalone binary for secure-exec VM" +description = "basename standalone binary for agentos VM" [[bin]] name = "basename" diff --git a/software/coreutils/native/crates/cmd-basenc/Cargo.toml b/software/coreutils/native/crates/cmd-basenc/Cargo.toml index 9a297f21c0..798a0e5f2d 100644 --- a/software/coreutils/native/crates/cmd-basenc/Cargo.toml +++ b/software/coreutils/native/crates/cmd-basenc/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-basenc" version.workspace = true edition.workspace = true license.workspace = true -description = "basenc standalone binary for secure-exec VM" +description = "basenc standalone binary for agentos VM" [[bin]] name = "basenc" diff --git a/software/coreutils/native/crates/cmd-cat/Cargo.toml b/software/coreutils/native/crates/cmd-cat/Cargo.toml index 747109c7cd..62516e9c63 100644 --- a/software/coreutils/native/crates/cmd-cat/Cargo.toml +++ b/software/coreutils/native/crates/cmd-cat/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-cat" version.workspace = true edition.workspace = true license.workspace = true -description = "cat standalone binary for secure-exec VM" +description = "cat standalone binary for agentos VM" [[bin]] name = "cat" diff --git a/software/coreutils/native/crates/cmd-chmod/Cargo.toml b/software/coreutils/native/crates/cmd-chmod/Cargo.toml index 9e56965b70..97339833a3 100644 --- a/software/coreutils/native/crates/cmd-chmod/Cargo.toml +++ b/software/coreutils/native/crates/cmd-chmod/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-chmod" version.workspace = true edition.workspace = true license.workspace = true -description = "chmod standalone binary for secure-exec VM" +description = "chmod standalone binary for agentos VM" [[bin]] name = "chmod" diff --git a/software/coreutils/native/crates/cmd-cksum/Cargo.toml b/software/coreutils/native/crates/cmd-cksum/Cargo.toml index 25df33cb56..f2e5603a0b 100644 --- a/software/coreutils/native/crates/cmd-cksum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-cksum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-cksum" version.workspace = true edition.workspace = true license.workspace = true -description = "cksum standalone binary for secure-exec VM" +description = "cksum standalone binary for agentos VM" [[bin]] name = "cksum" diff --git a/software/coreutils/native/crates/cmd-column/Cargo.toml b/software/coreutils/native/crates/cmd-column/Cargo.toml index 8b16759a99..4f65732b71 100644 --- a/software/coreutils/native/crates/cmd-column/Cargo.toml +++ b/software/coreutils/native/crates/cmd-column/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-column" version.workspace = true edition.workspace = true license.workspace = true -description = "column standalone binary for secure-exec VM" +description = "column standalone binary for agentos VM" [[bin]] name = "column" path = "src/main.rs" [dependencies] -secureexec-column = { path = "../column" } +agentos-column = { path = "../column" } diff --git a/software/coreutils/native/crates/cmd-column/src/main.rs b/software/coreutils/native/crates/cmd-column/src/main.rs index d954d4ce4e..5716abc60d 100644 --- a/software/coreutils/native/crates/cmd-column/src/main.rs +++ b/software/coreutils/native/crates/cmd-column/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_column::main(args)); + std::process::exit(agentos_column::main(args)); } diff --git a/software/coreutils/native/crates/cmd-comm/Cargo.toml b/software/coreutils/native/crates/cmd-comm/Cargo.toml index 91e507f0f8..520c47e75d 100644 --- a/software/coreutils/native/crates/cmd-comm/Cargo.toml +++ b/software/coreutils/native/crates/cmd-comm/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-comm" version.workspace = true edition.workspace = true license.workspace = true -description = "comm standalone binary for secure-exec VM" +description = "comm standalone binary for agentos VM" [[bin]] name = "comm" diff --git a/software/coreutils/native/crates/cmd-cp/Cargo.toml b/software/coreutils/native/crates/cmd-cp/Cargo.toml index 56a958c1fe..f4bc3430ca 100644 --- a/software/coreutils/native/crates/cmd-cp/Cargo.toml +++ b/software/coreutils/native/crates/cmd-cp/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-cp" version.workspace = true edition.workspace = true license.workspace = true -description = "cp standalone binary for secure-exec VM" +description = "cp standalone binary for agentos VM" [[bin]] name = "cp" diff --git a/software/coreutils/native/crates/cmd-cut/Cargo.toml b/software/coreutils/native/crates/cmd-cut/Cargo.toml index 72e5a5f814..95ec130aea 100644 --- a/software/coreutils/native/crates/cmd-cut/Cargo.toml +++ b/software/coreutils/native/crates/cmd-cut/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-cut" version.workspace = true edition.workspace = true license.workspace = true -description = "cut standalone binary for secure-exec VM" +description = "cut standalone binary for agentos VM" [[bin]] name = "cut" diff --git a/software/coreutils/native/crates/cmd-date/Cargo.toml b/software/coreutils/native/crates/cmd-date/Cargo.toml index 7b0d440e2f..e22a386416 100644 --- a/software/coreutils/native/crates/cmd-date/Cargo.toml +++ b/software/coreutils/native/crates/cmd-date/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-date" version.workspace = true edition.workspace = true license.workspace = true -description = "date standalone binary for secure-exec VM" +description = "date standalone binary for agentos VM" [[bin]] name = "date" diff --git a/software/coreutils/native/crates/cmd-dd/Cargo.toml b/software/coreutils/native/crates/cmd-dd/Cargo.toml index 744ee8059f..f29c944d4b 100644 --- a/software/coreutils/native/crates/cmd-dd/Cargo.toml +++ b/software/coreutils/native/crates/cmd-dd/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-dd" version.workspace = true edition.workspace = true license.workspace = true -description = "dd standalone binary for secure-exec VM" +description = "dd standalone binary for agentos VM" [[bin]] name = "dd" diff --git a/software/coreutils/native/crates/cmd-dircolors/Cargo.toml b/software/coreutils/native/crates/cmd-dircolors/Cargo.toml index 86c849c392..e45f718047 100644 --- a/software/coreutils/native/crates/cmd-dircolors/Cargo.toml +++ b/software/coreutils/native/crates/cmd-dircolors/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-dircolors" version.workspace = true edition.workspace = true license.workspace = true -description = "dircolors standalone binary for secure-exec VM" +description = "dircolors standalone binary for agentos VM" [[bin]] name = "dircolors" diff --git a/software/coreutils/native/crates/cmd-dirname/Cargo.toml b/software/coreutils/native/crates/cmd-dirname/Cargo.toml index bd1615de6b..5ed37bc89d 100644 --- a/software/coreutils/native/crates/cmd-dirname/Cargo.toml +++ b/software/coreutils/native/crates/cmd-dirname/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-dirname" version.workspace = true edition.workspace = true license.workspace = true -description = "dirname standalone binary for secure-exec VM" +description = "dirname standalone binary for agentos VM" [[bin]] name = "dirname" diff --git a/software/coreutils/native/crates/cmd-du/Cargo.toml b/software/coreutils/native/crates/cmd-du/Cargo.toml index 8a2cc1e9d3..57d2eaa60c 100644 --- a/software/coreutils/native/crates/cmd-du/Cargo.toml +++ b/software/coreutils/native/crates/cmd-du/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-du" version.workspace = true edition.workspace = true license.workspace = true -description = "du standalone binary for secure-exec VM" +description = "du standalone binary for agentos VM" [[bin]] name = "du" path = "src/main.rs" [dependencies] -secureexec-du = { path = "../du" } +agentos-du = { path = "../du" } diff --git a/software/coreutils/native/crates/cmd-du/src/main.rs b/software/coreutils/native/crates/cmd-du/src/main.rs index f76d032ac9..7f28900b38 100644 --- a/software/coreutils/native/crates/cmd-du/src/main.rs +++ b/software/coreutils/native/crates/cmd-du/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_du::main(args)); + std::process::exit(agentos_du::main(args)); } diff --git a/software/coreutils/native/crates/cmd-echo/Cargo.toml b/software/coreutils/native/crates/cmd-echo/Cargo.toml index 2f882f37be..903f379cb3 100644 --- a/software/coreutils/native/crates/cmd-echo/Cargo.toml +++ b/software/coreutils/native/crates/cmd-echo/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-echo" version.workspace = true edition.workspace = true license.workspace = true -description = "echo standalone binary for secure-exec VM" +description = "echo standalone binary for agentos VM" [[bin]] name = "echo" diff --git a/software/coreutils/native/crates/cmd-env/Cargo.toml b/software/coreutils/native/crates/cmd-env/Cargo.toml index 6fe19a8d7d..02e8158936 100644 --- a/software/coreutils/native/crates/cmd-env/Cargo.toml +++ b/software/coreutils/native/crates/cmd-env/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-env" version.workspace = true edition.workspace = true license.workspace = true -description = "env standalone binary for secure-exec VM" +description = "env standalone binary for agentos VM" [[bin]] name = "env" path = "src/main.rs" [dependencies] -shims = { package = "secureexec-shims", path = "../../../../../toolchain/crates/libs/shims" } +shims = { package = "agentos-shims", path = "../../../../../toolchain/crates/libs/shims" } diff --git a/software/coreutils/native/crates/cmd-expand/Cargo.toml b/software/coreutils/native/crates/cmd-expand/Cargo.toml index 08807dc938..ae07f48bdd 100644 --- a/software/coreutils/native/crates/cmd-expand/Cargo.toml +++ b/software/coreutils/native/crates/cmd-expand/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-expand" version.workspace = true edition.workspace = true license.workspace = true -description = "expand standalone binary for secure-exec VM" +description = "expand standalone binary for agentos VM" [[bin]] name = "expand" diff --git a/software/coreutils/native/crates/cmd-expr/Cargo.toml b/software/coreutils/native/crates/cmd-expr/Cargo.toml index 10bd466ba0..7b02e80a76 100644 --- a/software/coreutils/native/crates/cmd-expr/Cargo.toml +++ b/software/coreutils/native/crates/cmd-expr/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-expr" version.workspace = true edition.workspace = true license.workspace = true -description = "expr standalone binary for secure-exec VM" +description = "expr standalone binary for agentos VM" [[bin]] name = "expr" path = "src/main.rs" [dependencies] -secureexec-expr = { path = "../expr" } +agentos-expr = { path = "../expr" } diff --git a/software/coreutils/native/crates/cmd-expr/src/main.rs b/software/coreutils/native/crates/cmd-expr/src/main.rs index 59edddd0f0..725779f2af 100644 --- a/software/coreutils/native/crates/cmd-expr/src/main.rs +++ b/software/coreutils/native/crates/cmd-expr/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_expr::main(args)); + std::process::exit(agentos_expr::main(args)); } diff --git a/software/coreutils/native/crates/cmd-factor/Cargo.toml b/software/coreutils/native/crates/cmd-factor/Cargo.toml index cd4f1f233b..29af5723b2 100644 --- a/software/coreutils/native/crates/cmd-factor/Cargo.toml +++ b/software/coreutils/native/crates/cmd-factor/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-factor" version.workspace = true edition.workspace = true license.workspace = true -description = "factor standalone binary for secure-exec VM" +description = "factor standalone binary for agentos VM" [[bin]] name = "factor" diff --git a/software/coreutils/native/crates/cmd-false/Cargo.toml b/software/coreutils/native/crates/cmd-false/Cargo.toml index a3660c6acf..61738c8871 100644 --- a/software/coreutils/native/crates/cmd-false/Cargo.toml +++ b/software/coreutils/native/crates/cmd-false/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-false" version.workspace = true edition.workspace = true license.workspace = true -description = "false standalone binary for secure-exec VM" +description = "false standalone binary for agentos VM" [[bin]] name = "false" diff --git a/software/coreutils/native/crates/cmd-fmt/Cargo.toml b/software/coreutils/native/crates/cmd-fmt/Cargo.toml index 2ebb0f6f6a..b437da1155 100644 --- a/software/coreutils/native/crates/cmd-fmt/Cargo.toml +++ b/software/coreutils/native/crates/cmd-fmt/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-fmt" version.workspace = true edition.workspace = true license.workspace = true -description = "fmt standalone binary for secure-exec VM" +description = "fmt standalone binary for agentos VM" [[bin]] name = "fmt" diff --git a/software/coreutils/native/crates/cmd-fold/Cargo.toml b/software/coreutils/native/crates/cmd-fold/Cargo.toml index 7d79e95796..cd1ecec2ac 100644 --- a/software/coreutils/native/crates/cmd-fold/Cargo.toml +++ b/software/coreutils/native/crates/cmd-fold/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-fold" version.workspace = true edition.workspace = true license.workspace = true -description = "fold standalone binary for secure-exec VM" +description = "fold standalone binary for agentos VM" [[bin]] name = "fold" diff --git a/software/coreutils/native/crates/cmd-head/Cargo.toml b/software/coreutils/native/crates/cmd-head/Cargo.toml index 287d999055..60cf3e2f5b 100644 --- a/software/coreutils/native/crates/cmd-head/Cargo.toml +++ b/software/coreutils/native/crates/cmd-head/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-head" version.workspace = true edition.workspace = true license.workspace = true -description = "head standalone binary for secure-exec VM" +description = "head standalone binary for agentos VM" [[bin]] name = "head" diff --git a/software/coreutils/native/crates/cmd-join/Cargo.toml b/software/coreutils/native/crates/cmd-join/Cargo.toml index c81c31cb5f..b75d612ba3 100644 --- a/software/coreutils/native/crates/cmd-join/Cargo.toml +++ b/software/coreutils/native/crates/cmd-join/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-join" version.workspace = true edition.workspace = true license.workspace = true -description = "join standalone binary for secure-exec VM" +description = "join standalone binary for agentos VM" [[bin]] name = "join" diff --git a/software/coreutils/native/crates/cmd-link/Cargo.toml b/software/coreutils/native/crates/cmd-link/Cargo.toml index 043488ee6c..6c323e8a10 100644 --- a/software/coreutils/native/crates/cmd-link/Cargo.toml +++ b/software/coreutils/native/crates/cmd-link/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-link" version.workspace = true edition.workspace = true license.workspace = true -description = "link standalone binary for secure-exec VM" +description = "link standalone binary for agentos VM" [[bin]] name = "link" diff --git a/software/coreutils/native/crates/cmd-ln/Cargo.toml b/software/coreutils/native/crates/cmd-ln/Cargo.toml index 92950c1f35..1703688154 100644 --- a/software/coreutils/native/crates/cmd-ln/Cargo.toml +++ b/software/coreutils/native/crates/cmd-ln/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-ln" version.workspace = true edition.workspace = true license.workspace = true -description = "ln standalone binary for secure-exec VM" +description = "ln standalone binary for agentos VM" [[bin]] name = "ln" diff --git a/software/coreutils/native/crates/cmd-logname/Cargo.toml b/software/coreutils/native/crates/cmd-logname/Cargo.toml index 33b6d0d678..51bfc4b5e6 100644 --- a/software/coreutils/native/crates/cmd-logname/Cargo.toml +++ b/software/coreutils/native/crates/cmd-logname/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-logname" version.workspace = true edition.workspace = true license.workspace = true -description = "logname standalone binary for secure-exec VM" +description = "logname standalone binary for agentos VM" [[bin]] name = "logname" diff --git a/software/coreutils/native/crates/cmd-ls/Cargo.toml b/software/coreutils/native/crates/cmd-ls/Cargo.toml index 71ba7a86e8..fedc7cd84f 100644 --- a/software/coreutils/native/crates/cmd-ls/Cargo.toml +++ b/software/coreutils/native/crates/cmd-ls/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-ls" version.workspace = true edition.workspace = true license.workspace = true -description = "ls standalone binary for secure-exec VM" +description = "ls standalone binary for agentos VM" [[bin]] name = "ls" diff --git a/software/coreutils/native/crates/cmd-md5sum/Cargo.toml b/software/coreutils/native/crates/cmd-md5sum/Cargo.toml index ea660b5d0f..5fd7cf4378 100644 --- a/software/coreutils/native/crates/cmd-md5sum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-md5sum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-md5sum" version.workspace = true edition.workspace = true license.workspace = true -description = "md5sum standalone binary for secure-exec VM" +description = "md5sum standalone binary for agentos VM" [[bin]] name = "md5sum" diff --git a/software/coreutils/native/crates/cmd-mkdir/Cargo.toml b/software/coreutils/native/crates/cmd-mkdir/Cargo.toml index 7a3e9f4ccf..d41b274ae0 100644 --- a/software/coreutils/native/crates/cmd-mkdir/Cargo.toml +++ b/software/coreutils/native/crates/cmd-mkdir/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-mkdir" version.workspace = true edition.workspace = true license.workspace = true -description = "mkdir standalone binary for secure-exec VM" +description = "mkdir standalone binary for agentos VM" [[bin]] name = "mkdir" diff --git a/software/coreutils/native/crates/cmd-mktemp/Cargo.toml b/software/coreutils/native/crates/cmd-mktemp/Cargo.toml index 57935df632..d0afffcbac 100644 --- a/software/coreutils/native/crates/cmd-mktemp/Cargo.toml +++ b/software/coreutils/native/crates/cmd-mktemp/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-mktemp" version.workspace = true edition.workspace = true license.workspace = true -description = "mktemp standalone binary for secure-exec VM" +description = "mktemp standalone binary for agentos VM" [[bin]] name = "mktemp" diff --git a/software/coreutils/native/crates/cmd-mv/Cargo.toml b/software/coreutils/native/crates/cmd-mv/Cargo.toml index c4999d907c..5a10e172d6 100644 --- a/software/coreutils/native/crates/cmd-mv/Cargo.toml +++ b/software/coreutils/native/crates/cmd-mv/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-mv" version.workspace = true edition.workspace = true license.workspace = true -description = "mv standalone binary for secure-exec VM" +description = "mv standalone binary for agentos VM" [[bin]] name = "mv" diff --git a/software/coreutils/native/crates/cmd-nice/Cargo.toml b/software/coreutils/native/crates/cmd-nice/Cargo.toml index 2f77be052e..4786fba39b 100644 --- a/software/coreutils/native/crates/cmd-nice/Cargo.toml +++ b/software/coreutils/native/crates/cmd-nice/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-nice" version.workspace = true edition.workspace = true license.workspace = true -description = "nice standalone binary for secure-exec VM" +description = "nice standalone binary for agentos VM" [[bin]] name = "nice" path = "src/main.rs" [dependencies] -shims = { package = "secureexec-shims", path = "../../../../../toolchain/crates/libs/shims" } +shims = { package = "agentos-shims", path = "../../../../../toolchain/crates/libs/shims" } diff --git a/software/coreutils/native/crates/cmd-nl/Cargo.toml b/software/coreutils/native/crates/cmd-nl/Cargo.toml index 067baf0805..a219c47821 100644 --- a/software/coreutils/native/crates/cmd-nl/Cargo.toml +++ b/software/coreutils/native/crates/cmd-nl/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-nl" version.workspace = true edition.workspace = true license.workspace = true -description = "nl standalone binary for secure-exec VM" +description = "nl standalone binary for agentos VM" [[bin]] name = "nl" diff --git a/software/coreutils/native/crates/cmd-nohup/Cargo.toml b/software/coreutils/native/crates/cmd-nohup/Cargo.toml index 94edf64e00..f2e17edb49 100644 --- a/software/coreutils/native/crates/cmd-nohup/Cargo.toml +++ b/software/coreutils/native/crates/cmd-nohup/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-nohup" version.workspace = true edition.workspace = true license.workspace = true -description = "nohup standalone binary for secure-exec VM" +description = "nohup standalone binary for agentos VM" [[bin]] name = "nohup" path = "src/main.rs" [dependencies] -shims = { package = "secureexec-shims", path = "../../../../../toolchain/crates/libs/shims" } +shims = { package = "agentos-shims", path = "../../../../../toolchain/crates/libs/shims" } diff --git a/software/coreutils/native/crates/cmd-nproc/Cargo.toml b/software/coreutils/native/crates/cmd-nproc/Cargo.toml index 9c6fc0fbbb..865f11112c 100644 --- a/software/coreutils/native/crates/cmd-nproc/Cargo.toml +++ b/software/coreutils/native/crates/cmd-nproc/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-nproc" version.workspace = true edition.workspace = true license.workspace = true -description = "nproc standalone binary for secure-exec VM" +description = "nproc standalone binary for agentos VM" [[bin]] name = "nproc" diff --git a/software/coreutils/native/crates/cmd-numfmt/Cargo.toml b/software/coreutils/native/crates/cmd-numfmt/Cargo.toml index 6ae2fedb83..6cf53f3433 100644 --- a/software/coreutils/native/crates/cmd-numfmt/Cargo.toml +++ b/software/coreutils/native/crates/cmd-numfmt/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-numfmt" version.workspace = true edition.workspace = true license.workspace = true -description = "numfmt standalone binary for secure-exec VM" +description = "numfmt standalone binary for agentos VM" [[bin]] name = "numfmt" diff --git a/software/coreutils/native/crates/cmd-od/Cargo.toml b/software/coreutils/native/crates/cmd-od/Cargo.toml index 102a12cdab..a60719144b 100644 --- a/software/coreutils/native/crates/cmd-od/Cargo.toml +++ b/software/coreutils/native/crates/cmd-od/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-od" version.workspace = true edition.workspace = true license.workspace = true -description = "od standalone binary for secure-exec VM" +description = "od standalone binary for agentos VM" [[bin]] name = "od" diff --git a/software/coreutils/native/crates/cmd-paste/Cargo.toml b/software/coreutils/native/crates/cmd-paste/Cargo.toml index 8e45b33c09..3800c5de53 100644 --- a/software/coreutils/native/crates/cmd-paste/Cargo.toml +++ b/software/coreutils/native/crates/cmd-paste/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-paste" version.workspace = true edition.workspace = true license.workspace = true -description = "paste standalone binary for secure-exec VM" +description = "paste standalone binary for agentos VM" [[bin]] name = "paste" diff --git a/software/coreutils/native/crates/cmd-pathchk/Cargo.toml b/software/coreutils/native/crates/cmd-pathchk/Cargo.toml index b675dc27f1..9db0a38b9b 100644 --- a/software/coreutils/native/crates/cmd-pathchk/Cargo.toml +++ b/software/coreutils/native/crates/cmd-pathchk/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-pathchk" version.workspace = true edition.workspace = true license.workspace = true -description = "pathchk standalone binary for secure-exec VM" +description = "pathchk standalone binary for agentos VM" [[bin]] name = "pathchk" diff --git a/software/coreutils/native/crates/cmd-printenv/Cargo.toml b/software/coreutils/native/crates/cmd-printenv/Cargo.toml index 918b962ea6..5790aebe00 100644 --- a/software/coreutils/native/crates/cmd-printenv/Cargo.toml +++ b/software/coreutils/native/crates/cmd-printenv/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-printenv" version.workspace = true edition.workspace = true license.workspace = true -description = "printenv standalone binary for secure-exec VM" +description = "printenv standalone binary for agentos VM" [[bin]] name = "printenv" diff --git a/software/coreutils/native/crates/cmd-printf/Cargo.toml b/software/coreutils/native/crates/cmd-printf/Cargo.toml index c0512cfd17..a6880a7cef 100644 --- a/software/coreutils/native/crates/cmd-printf/Cargo.toml +++ b/software/coreutils/native/crates/cmd-printf/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-printf" version.workspace = true edition.workspace = true license.workspace = true -description = "printf standalone binary for secure-exec VM" +description = "printf standalone binary for agentos VM" [[bin]] name = "printf" diff --git a/software/coreutils/native/crates/cmd-ptx/Cargo.toml b/software/coreutils/native/crates/cmd-ptx/Cargo.toml index 9eefecd190..e25bcaa743 100644 --- a/software/coreutils/native/crates/cmd-ptx/Cargo.toml +++ b/software/coreutils/native/crates/cmd-ptx/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-ptx" version.workspace = true edition.workspace = true license.workspace = true -description = "ptx standalone binary for secure-exec VM" +description = "ptx standalone binary for agentos VM" [[bin]] name = "ptx" diff --git a/software/coreutils/native/crates/cmd-pwd/Cargo.toml b/software/coreutils/native/crates/cmd-pwd/Cargo.toml index b3e7ff6a74..5536c67f3a 100644 --- a/software/coreutils/native/crates/cmd-pwd/Cargo.toml +++ b/software/coreutils/native/crates/cmd-pwd/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-pwd" version.workspace = true edition.workspace = true license.workspace = true -description = "pwd standalone binary for secure-exec VM" +description = "pwd standalone binary for agentos VM" [[bin]] name = "pwd" diff --git a/software/coreutils/native/crates/cmd-readlink/Cargo.toml b/software/coreutils/native/crates/cmd-readlink/Cargo.toml index 7fa48bbe6f..a040bddcc8 100644 --- a/software/coreutils/native/crates/cmd-readlink/Cargo.toml +++ b/software/coreutils/native/crates/cmd-readlink/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-readlink" version.workspace = true edition.workspace = true license.workspace = true -description = "readlink standalone binary for secure-exec VM" +description = "readlink standalone binary for agentos VM" [[bin]] name = "readlink" diff --git a/software/coreutils/native/crates/cmd-realpath/Cargo.toml b/software/coreutils/native/crates/cmd-realpath/Cargo.toml index dbbbc9da3a..8fc76e6fae 100644 --- a/software/coreutils/native/crates/cmd-realpath/Cargo.toml +++ b/software/coreutils/native/crates/cmd-realpath/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-realpath" version.workspace = true edition.workspace = true license.workspace = true -description = "realpath standalone binary for secure-exec VM" +description = "realpath standalone binary for agentos VM" [[bin]] name = "realpath" diff --git a/software/coreutils/native/crates/cmd-rev/Cargo.toml b/software/coreutils/native/crates/cmd-rev/Cargo.toml index 66a1ffd19d..0716a90d57 100644 --- a/software/coreutils/native/crates/cmd-rev/Cargo.toml +++ b/software/coreutils/native/crates/cmd-rev/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-rev" version.workspace = true edition.workspace = true license.workspace = true -description = "rev standalone binary for secure-exec VM" +description = "rev standalone binary for agentos VM" [[bin]] name = "rev" path = "src/main.rs" [dependencies] -secureexec-rev = { path = "../rev" } +agentos-rev = { path = "../rev" } diff --git a/software/coreutils/native/crates/cmd-rev/src/main.rs b/software/coreutils/native/crates/cmd-rev/src/main.rs index 6841e7d15a..1004a8a78b 100644 --- a/software/coreutils/native/crates/cmd-rev/src/main.rs +++ b/software/coreutils/native/crates/cmd-rev/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_rev::main(args)); + std::process::exit(agentos_rev::main(args)); } diff --git a/software/coreutils/native/crates/cmd-rm/Cargo.toml b/software/coreutils/native/crates/cmd-rm/Cargo.toml index 4a9dc744e7..efc64218a8 100644 --- a/software/coreutils/native/crates/cmd-rm/Cargo.toml +++ b/software/coreutils/native/crates/cmd-rm/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-rm" version.workspace = true edition.workspace = true license.workspace = true -description = "rm standalone binary for secure-exec VM" +description = "rm standalone binary for agentos VM" [[bin]] name = "rm" diff --git a/software/coreutils/native/crates/cmd-rmdir/Cargo.toml b/software/coreutils/native/crates/cmd-rmdir/Cargo.toml index f9729df6f7..f44ec436eb 100644 --- a/software/coreutils/native/crates/cmd-rmdir/Cargo.toml +++ b/software/coreutils/native/crates/cmd-rmdir/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-rmdir" version.workspace = true edition.workspace = true license.workspace = true -description = "rmdir standalone binary for secure-exec VM" +description = "rmdir standalone binary for agentos VM" [[bin]] name = "rmdir" diff --git a/software/coreutils/native/crates/cmd-seq/Cargo.toml b/software/coreutils/native/crates/cmd-seq/Cargo.toml index bb035b54fc..11f10db48a 100644 --- a/software/coreutils/native/crates/cmd-seq/Cargo.toml +++ b/software/coreutils/native/crates/cmd-seq/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-seq" version.workspace = true edition.workspace = true license.workspace = true -description = "seq standalone binary for secure-exec VM" +description = "seq standalone binary for agentos VM" [[bin]] name = "seq" diff --git a/software/coreutils/native/crates/cmd-sh/Cargo.toml b/software/coreutils/native/crates/cmd-sh/Cargo.toml index 51976f0cc4..ce950f492e 100644 --- a/software/coreutils/native/crates/cmd-sh/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sh/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sh" version.workspace = true edition.workspace = true license.workspace = true -description = "sh standalone binary for secure-exec VM" +description = "sh standalone binary for agentos VM" [[bin]] name = "sh" diff --git a/software/coreutils/native/crates/cmd-sha1sum/Cargo.toml b/software/coreutils/native/crates/cmd-sha1sum/Cargo.toml index 1e4b91ec01..f924733ff5 100644 --- a/software/coreutils/native/crates/cmd-sha1sum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sha1sum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sha1sum" version.workspace = true edition.workspace = true license.workspace = true -description = "sha1sum standalone binary for secure-exec VM" +description = "sha1sum standalone binary for agentos VM" [[bin]] name = "sha1sum" diff --git a/software/coreutils/native/crates/cmd-sha224sum/Cargo.toml b/software/coreutils/native/crates/cmd-sha224sum/Cargo.toml index bdd6f4cb70..d37b29d52b 100644 --- a/software/coreutils/native/crates/cmd-sha224sum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sha224sum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sha224sum" version.workspace = true edition.workspace = true license.workspace = true -description = "sha224sum standalone binary for secure-exec VM" +description = "sha224sum standalone binary for agentos VM" [[bin]] name = "sha224sum" diff --git a/software/coreutils/native/crates/cmd-sha256sum/Cargo.toml b/software/coreutils/native/crates/cmd-sha256sum/Cargo.toml index a43ebd9ff9..15f5b2bef8 100644 --- a/software/coreutils/native/crates/cmd-sha256sum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sha256sum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sha256sum" version.workspace = true edition.workspace = true license.workspace = true -description = "sha256sum standalone binary for secure-exec VM" +description = "sha256sum standalone binary for agentos VM" [[bin]] name = "sha256sum" diff --git a/software/coreutils/native/crates/cmd-sha384sum/Cargo.toml b/software/coreutils/native/crates/cmd-sha384sum/Cargo.toml index 3cec44da9d..50ce3881d2 100644 --- a/software/coreutils/native/crates/cmd-sha384sum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sha384sum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sha384sum" version.workspace = true edition.workspace = true license.workspace = true -description = "sha384sum standalone binary for secure-exec VM" +description = "sha384sum standalone binary for agentos VM" [[bin]] name = "sha384sum" diff --git a/software/coreutils/native/crates/cmd-sha512sum/Cargo.toml b/software/coreutils/native/crates/cmd-sha512sum/Cargo.toml index 0d15e9ac32..ed5c6c2d4a 100644 --- a/software/coreutils/native/crates/cmd-sha512sum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sha512sum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sha512sum" version.workspace = true edition.workspace = true license.workspace = true -description = "sha512sum standalone binary for secure-exec VM" +description = "sha512sum standalone binary for agentos VM" [[bin]] name = "sha512sum" diff --git a/software/coreutils/native/crates/cmd-shred/Cargo.toml b/software/coreutils/native/crates/cmd-shred/Cargo.toml index 15cb98f87c..0daefa2e81 100644 --- a/software/coreutils/native/crates/cmd-shred/Cargo.toml +++ b/software/coreutils/native/crates/cmd-shred/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-shred" version.workspace = true edition.workspace = true license.workspace = true -description = "shred standalone binary for secure-exec VM" +description = "shred standalone binary for agentos VM" [[bin]] name = "shred" diff --git a/software/coreutils/native/crates/cmd-shuf/Cargo.toml b/software/coreutils/native/crates/cmd-shuf/Cargo.toml index 06dc44cf52..49f8570602 100644 --- a/software/coreutils/native/crates/cmd-shuf/Cargo.toml +++ b/software/coreutils/native/crates/cmd-shuf/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-shuf" version.workspace = true edition.workspace = true license.workspace = true -description = "shuf standalone binary for secure-exec VM" +description = "shuf standalone binary for agentos VM" [[bin]] name = "shuf" diff --git a/software/coreutils/native/crates/cmd-sleep/Cargo.toml b/software/coreutils/native/crates/cmd-sleep/Cargo.toml index 816b051b22..3b09388019 100644 --- a/software/coreutils/native/crates/cmd-sleep/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sleep/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-sleep" version.workspace = true edition.workspace = true license.workspace = true -description = "sleep standalone binary for secure-exec VM" +description = "sleep standalone binary for agentos VM" [[bin]] name = "sleep" path = "src/main.rs" [dependencies] -secureexec-builtins = { path = "../../../../../toolchain/crates/libs/builtins" } +agentos-builtins = { path = "../../../../../toolchain/crates/libs/builtins" } diff --git a/software/coreutils/native/crates/cmd-sleep/src/main.rs b/software/coreutils/native/crates/cmd-sleep/src/main.rs index 87f399d995..e471bc9d0a 100644 --- a/software/coreutils/native/crates/cmd-sleep/src/main.rs +++ b/software/coreutils/native/crates/cmd-sleep/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_builtins::sleep(args)); + std::process::exit(agentos_builtins::sleep(args)); } diff --git a/software/coreutils/native/crates/cmd-sort/Cargo.toml b/software/coreutils/native/crates/cmd-sort/Cargo.toml index 0507575a3b..613c9b3757 100644 --- a/software/coreutils/native/crates/cmd-sort/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sort/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sort" version.workspace = true edition.workspace = true license.workspace = true -description = "sort standalone binary for secure-exec VM" +description = "sort standalone binary for agentos VM" [[bin]] name = "sort" diff --git a/software/coreutils/native/crates/cmd-sort/tests/external_sort.rs b/software/coreutils/native/crates/cmd-sort/tests/external_sort.rs index 50a9fe3261..670a2b9ad9 100644 --- a/software/coreutils/native/crates/cmd-sort/tests/external_sort.rs +++ b/software/coreutils/native/crates/cmd-sort/tests/external_sort.rs @@ -29,7 +29,7 @@ impl Drop for TestDir { } } -// The workspace patches ctrlc to the secure-exec stub, which reports +// The workspace patches ctrlc to the agentos stub, which reports // ErrorKind::Unsupported for signal registration on every target. Forcing an // external-sort spill into a temp directory exercises uu_sort's // ensure_signal_handler_installed soft-skip path. Before the soft skip this diff --git a/software/coreutils/native/crates/cmd-split/Cargo.toml b/software/coreutils/native/crates/cmd-split/Cargo.toml index c0aa7cc026..cfd964daa7 100644 --- a/software/coreutils/native/crates/cmd-split/Cargo.toml +++ b/software/coreutils/native/crates/cmd-split/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-split" version.workspace = true edition.workspace = true license.workspace = true -description = "split standalone binary for secure-exec VM" +description = "split standalone binary for agentos VM" [[bin]] name = "split" diff --git a/software/coreutils/native/crates/cmd-stat/Cargo.toml b/software/coreutils/native/crates/cmd-stat/Cargo.toml index ee741b2614..d270357fa2 100644 --- a/software/coreutils/native/crates/cmd-stat/Cargo.toml +++ b/software/coreutils/native/crates/cmd-stat/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-stat" version.workspace = true edition.workspace = true license.workspace = true -description = "stat standalone binary for secure-exec VM" +description = "stat standalone binary for agentos VM" [[bin]] name = "stat" diff --git a/software/coreutils/native/crates/cmd-stdbuf/Cargo.toml b/software/coreutils/native/crates/cmd-stdbuf/Cargo.toml index 499e2ef4d7..6fa4cda0dd 100644 --- a/software/coreutils/native/crates/cmd-stdbuf/Cargo.toml +++ b/software/coreutils/native/crates/cmd-stdbuf/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-stdbuf" version.workspace = true edition.workspace = true license.workspace = true -description = "stdbuf standalone binary for secure-exec VM" +description = "stdbuf standalone binary for agentos VM" [[bin]] name = "stdbuf" path = "src/main.rs" [dependencies] -shims = { package = "secureexec-shims", path = "../../../../../toolchain/crates/libs/shims" } +shims = { package = "agentos-shims", path = "../../../../../toolchain/crates/libs/shims" } diff --git a/software/coreutils/native/crates/cmd-strings/Cargo.toml b/software/coreutils/native/crates/cmd-strings/Cargo.toml index 4ad7da7c02..2801880dcd 100644 --- a/software/coreutils/native/crates/cmd-strings/Cargo.toml +++ b/software/coreutils/native/crates/cmd-strings/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-strings" version.workspace = true edition.workspace = true license.workspace = true -description = "strings standalone binary for secure-exec VM" +description = "strings standalone binary for agentos VM" [[bin]] name = "strings" path = "src/main.rs" [dependencies] -secureexec-strings-cmd = { path = "../strings-cmd" } +agentos-strings-cmd = { path = "../strings-cmd" } diff --git a/software/coreutils/native/crates/cmd-strings/src/main.rs b/software/coreutils/native/crates/cmd-strings/src/main.rs index 0af588fac5..ec6056d4a4 100644 --- a/software/coreutils/native/crates/cmd-strings/src/main.rs +++ b/software/coreutils/native/crates/cmd-strings/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_strings_cmd::main(args)); + std::process::exit(agentos_strings_cmd::main(args)); } diff --git a/software/coreutils/native/crates/cmd-sum/Cargo.toml b/software/coreutils/native/crates/cmd-sum/Cargo.toml index 5b07f6452b..538bcd6f90 100644 --- a/software/coreutils/native/crates/cmd-sum/Cargo.toml +++ b/software/coreutils/native/crates/cmd-sum/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sum" version.workspace = true edition.workspace = true license.workspace = true -description = "sum standalone binary for secure-exec VM" +description = "sum standalone binary for agentos VM" [[bin]] name = "sum" diff --git a/software/coreutils/native/crates/cmd-tac/Cargo.toml b/software/coreutils/native/crates/cmd-tac/Cargo.toml index f0069010db..2b4ace4610 100644 --- a/software/coreutils/native/crates/cmd-tac/Cargo.toml +++ b/software/coreutils/native/crates/cmd-tac/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-tac" version.workspace = true edition.workspace = true license.workspace = true -description = "tac standalone binary for secure-exec VM" +description = "tac standalone binary for agentos VM" [[bin]] name = "tac" diff --git a/software/coreutils/native/crates/cmd-tail/Cargo.toml b/software/coreutils/native/crates/cmd-tail/Cargo.toml index 7a14ea0dba..1dac932acd 100644 --- a/software/coreutils/native/crates/cmd-tail/Cargo.toml +++ b/software/coreutils/native/crates/cmd-tail/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-tail" version.workspace = true edition.workspace = true license.workspace = true -description = "tail standalone binary for secure-exec VM" +description = "tail standalone binary for agentos VM" [[bin]] name = "tail" diff --git a/software/coreutils/native/crates/cmd-tee/Cargo.toml b/software/coreutils/native/crates/cmd-tee/Cargo.toml index c94c0664e7..8df5425d54 100644 --- a/software/coreutils/native/crates/cmd-tee/Cargo.toml +++ b/software/coreutils/native/crates/cmd-tee/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-tee" version.workspace = true edition.workspace = true license.workspace = true -description = "tee standalone binary for secure-exec VM" +description = "tee standalone binary for agentos VM" [[bin]] name = "tee" diff --git a/software/coreutils/native/crates/cmd-test/Cargo.toml b/software/coreutils/native/crates/cmd-test/Cargo.toml index 1a1581e18b..3f4b21cf28 100644 --- a/software/coreutils/native/crates/cmd-test/Cargo.toml +++ b/software/coreutils/native/crates/cmd-test/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-test" version.workspace = true edition.workspace = true license.workspace = true -description = "test/[ standalone binary for secure-exec VM" +description = "test/[ standalone binary for agentos VM" [[bin]] name = "test" path = "src/main.rs" [dependencies] -secureexec-builtins = { path = "../../../../../toolchain/crates/libs/builtins" } +agentos-builtins = { path = "../../../../../toolchain/crates/libs/builtins" } diff --git a/software/coreutils/native/crates/cmd-test/src/main.rs b/software/coreutils/native/crates/cmd-test/src/main.rs index 4d6acd26f4..5201cac1bb 100644 --- a/software/coreutils/native/crates/cmd-test/src/main.rs +++ b/software/coreutils/native/crates/cmd-test/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_builtins::test_cmd(args)); + std::process::exit(agentos_builtins::test_cmd(args)); } diff --git a/software/coreutils/native/crates/cmd-timeout/Cargo.toml b/software/coreutils/native/crates/cmd-timeout/Cargo.toml index af6e289f59..8f9577734b 100644 --- a/software/coreutils/native/crates/cmd-timeout/Cargo.toml +++ b/software/coreutils/native/crates/cmd-timeout/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-timeout" version.workspace = true edition.workspace = true license.workspace = true -description = "timeout standalone binary for secure-exec VM" +description = "timeout standalone binary for agentos VM" [[bin]] name = "timeout" path = "src/main.rs" [dependencies] -shims = { package = "secureexec-shims", path = "../../../../../toolchain/crates/libs/shims" } +shims = { package = "agentos-shims", path = "../../../../../toolchain/crates/libs/shims" } diff --git a/software/coreutils/native/crates/cmd-touch/Cargo.toml b/software/coreutils/native/crates/cmd-touch/Cargo.toml index 6353e89c77..e5391a2ccd 100644 --- a/software/coreutils/native/crates/cmd-touch/Cargo.toml +++ b/software/coreutils/native/crates/cmd-touch/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-touch" version.workspace = true edition.workspace = true license.workspace = true -description = "touch standalone binary for secure-exec VM" +description = "touch standalone binary for agentos VM" [[bin]] name = "touch" diff --git a/software/coreutils/native/crates/cmd-tr/Cargo.toml b/software/coreutils/native/crates/cmd-tr/Cargo.toml index c11682cac7..3d8d1437cf 100644 --- a/software/coreutils/native/crates/cmd-tr/Cargo.toml +++ b/software/coreutils/native/crates/cmd-tr/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-tr" version.workspace = true edition.workspace = true license.workspace = true -description = "tr standalone binary for secure-exec VM" +description = "tr standalone binary for agentos VM" [[bin]] name = "tr" diff --git a/software/coreutils/native/crates/cmd-true/Cargo.toml b/software/coreutils/native/crates/cmd-true/Cargo.toml index 9730e7f14f..96401018ca 100644 --- a/software/coreutils/native/crates/cmd-true/Cargo.toml +++ b/software/coreutils/native/crates/cmd-true/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-true" version.workspace = true edition.workspace = true license.workspace = true -description = "true standalone binary for secure-exec VM" +description = "true standalone binary for agentos VM" [[bin]] name = "true" diff --git a/software/coreutils/native/crates/cmd-truncate/Cargo.toml b/software/coreutils/native/crates/cmd-truncate/Cargo.toml index 65fa7e80fd..770cc1ca89 100644 --- a/software/coreutils/native/crates/cmd-truncate/Cargo.toml +++ b/software/coreutils/native/crates/cmd-truncate/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-truncate" version.workspace = true edition.workspace = true license.workspace = true -description = "truncate standalone binary for secure-exec VM" +description = "truncate standalone binary for agentos VM" [[bin]] name = "truncate" diff --git a/software/coreutils/native/crates/cmd-tsort/Cargo.toml b/software/coreutils/native/crates/cmd-tsort/Cargo.toml index b0e057b0c8..07932d1b94 100644 --- a/software/coreutils/native/crates/cmd-tsort/Cargo.toml +++ b/software/coreutils/native/crates/cmd-tsort/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-tsort" version.workspace = true edition.workspace = true license.workspace = true -description = "tsort standalone binary for secure-exec VM" +description = "tsort standalone binary for agentos VM" [[bin]] name = "tsort" diff --git a/software/coreutils/native/crates/cmd-uname/Cargo.toml b/software/coreutils/native/crates/cmd-uname/Cargo.toml index b0f0a8c71a..ee112adbce 100644 --- a/software/coreutils/native/crates/cmd-uname/Cargo.toml +++ b/software/coreutils/native/crates/cmd-uname/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-uname" version.workspace = true edition.workspace = true license.workspace = true -description = "uname standalone binary for secure-exec VM" +description = "uname standalone binary for agentos VM" [[bin]] name = "uname" diff --git a/software/coreutils/native/crates/cmd-unexpand/Cargo.toml b/software/coreutils/native/crates/cmd-unexpand/Cargo.toml index d8a9dc9e78..4e10477987 100644 --- a/software/coreutils/native/crates/cmd-unexpand/Cargo.toml +++ b/software/coreutils/native/crates/cmd-unexpand/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-unexpand" version.workspace = true edition.workspace = true license.workspace = true -description = "unexpand standalone binary for secure-exec VM" +description = "unexpand standalone binary for agentos VM" [[bin]] name = "unexpand" diff --git a/software/coreutils/native/crates/cmd-uniq/Cargo.toml b/software/coreutils/native/crates/cmd-uniq/Cargo.toml index c3ead17984..36c7e5057f 100644 --- a/software/coreutils/native/crates/cmd-uniq/Cargo.toml +++ b/software/coreutils/native/crates/cmd-uniq/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-uniq" version.workspace = true edition.workspace = true license.workspace = true -description = "uniq standalone binary for secure-exec VM" +description = "uniq standalone binary for agentos VM" [[bin]] name = "uniq" diff --git a/software/coreutils/native/crates/cmd-unlink/Cargo.toml b/software/coreutils/native/crates/cmd-unlink/Cargo.toml index eb669d0add..3c2b6b90be 100644 --- a/software/coreutils/native/crates/cmd-unlink/Cargo.toml +++ b/software/coreutils/native/crates/cmd-unlink/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-unlink" version.workspace = true edition.workspace = true license.workspace = true -description = "unlink standalone binary for secure-exec VM" +description = "unlink standalone binary for agentos VM" [[bin]] name = "unlink" diff --git a/software/coreutils/native/crates/cmd-wc/Cargo.toml b/software/coreutils/native/crates/cmd-wc/Cargo.toml index 728b9fdad7..bfeaaf2a7e 100644 --- a/software/coreutils/native/crates/cmd-wc/Cargo.toml +++ b/software/coreutils/native/crates/cmd-wc/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-wc" version.workspace = true edition.workspace = true license.workspace = true -description = "wc standalone binary for secure-exec VM" +description = "wc standalone binary for agentos VM" [[bin]] name = "wc" diff --git a/software/coreutils/native/crates/cmd-which/Cargo.toml b/software/coreutils/native/crates/cmd-which/Cargo.toml index 0ea0f38b94..82370fb0db 100644 --- a/software/coreutils/native/crates/cmd-which/Cargo.toml +++ b/software/coreutils/native/crates/cmd-which/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-which" version.workspace = true edition.workspace = true license.workspace = true -description = "which standalone binary for secure-exec VM" +description = "which standalone binary for agentos VM" [[bin]] name = "which" path = "src/main.rs" [dependencies] -shims = { package = "secureexec-shims", path = "../../../../../toolchain/crates/libs/shims" } +shims = { package = "agentos-shims", path = "../../../../../toolchain/crates/libs/shims" } diff --git a/software/coreutils/native/crates/cmd-which/tests/executable_mode.rs b/software/coreutils/native/crates/cmd-which/tests/executable_mode.rs index 8a51e070e4..a2910222ce 100644 --- a/software/coreutils/native/crates/cmd-which/tests/executable_mode.rs +++ b/software/coreutils/native/crates/cmd-which/tests/executable_mode.rs @@ -13,7 +13,7 @@ struct TempDir { impl TempDir { fn new() -> Self { let unique = format!( - "secure-exec-which-test-{}-{}", + "agentos-which-test-{}-{}", std::process::id(), SystemTime::now() .duration_since(UNIX_EPOCH) diff --git a/software/coreutils/native/crates/cmd-whoami/Cargo.toml b/software/coreutils/native/crates/cmd-whoami/Cargo.toml index 988ca47dae..2aafe988fc 100644 --- a/software/coreutils/native/crates/cmd-whoami/Cargo.toml +++ b/software/coreutils/native/crates/cmd-whoami/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-whoami" version.workspace = true edition.workspace = true license.workspace = true -description = "whoami standalone binary for secure-exec VM" +description = "whoami standalone binary for agentos VM" [[bin]] name = "whoami" path = "src/main.rs" [dependencies] -secureexec-builtins = { path = "../../../../../toolchain/crates/libs/builtins" } +agentos-builtins = { path = "../../../../../toolchain/crates/libs/builtins" } diff --git a/software/coreutils/native/crates/cmd-whoami/src/main.rs b/software/coreutils/native/crates/cmd-whoami/src/main.rs index 6d399bd1bc..1180627184 100644 --- a/software/coreutils/native/crates/cmd-whoami/src/main.rs +++ b/software/coreutils/native/crates/cmd-whoami/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_builtins::whoami(args)); + std::process::exit(agentos_builtins::whoami(args)); } diff --git a/software/coreutils/native/crates/cmd-yes/Cargo.toml b/software/coreutils/native/crates/cmd-yes/Cargo.toml index d32f9d582d..91e69e6c6f 100644 --- a/software/coreutils/native/crates/cmd-yes/Cargo.toml +++ b/software/coreutils/native/crates/cmd-yes/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-yes" version.workspace = true edition.workspace = true license.workspace = true -description = "yes standalone binary for secure-exec VM" +description = "yes standalone binary for agentos VM" [[bin]] name = "yes" diff --git a/software/coreutils/native/crates/column/Cargo.toml b/software/coreutils/native/crates/column/Cargo.toml index 3134b792fd..f1d45753fd 100644 --- a/software/coreutils/native/crates/column/Cargo.toml +++ b/software/coreutils/native/crates/column/Cargo.toml @@ -1,9 +1,9 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-column" +name = "agentos-column" version.workspace = true edition.workspace = true license.workspace = true -description = "column implementation for secure-exec standalone binaries" +description = "column implementation for agentos standalone binaries" [dependencies] diff --git a/software/coreutils/native/crates/du/Cargo.toml b/software/coreutils/native/crates/du/Cargo.toml index f167b14657..e2f71e46bf 100644 --- a/software/coreutils/native/crates/du/Cargo.toml +++ b/software/coreutils/native/crates/du/Cargo.toml @@ -1,9 +1,9 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-du" +name = "agentos-du" version.workspace = true edition.workspace = true license.workspace = true -description = "du implementation for secure-exec standalone binaries" +description = "du implementation for agentos standalone binaries" [dependencies] diff --git a/software/coreutils/native/crates/expr/Cargo.toml b/software/coreutils/native/crates/expr/Cargo.toml index e8f413d5c6..c2b49e04dc 100644 --- a/software/coreutils/native/crates/expr/Cargo.toml +++ b/software/coreutils/native/crates/expr/Cargo.toml @@ -1,10 +1,10 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-expr" +name = "agentos-expr" version.workspace = true edition.workspace = true license.workspace = true -description = "expr implementation for secure-exec standalone binaries" +description = "expr implementation for agentos standalone binaries" [dependencies] regex = "1" diff --git a/software/coreutils/native/crates/rev/Cargo.toml b/software/coreutils/native/crates/rev/Cargo.toml index 3c8a175e92..51f335f5da 100644 --- a/software/coreutils/native/crates/rev/Cargo.toml +++ b/software/coreutils/native/crates/rev/Cargo.toml @@ -1,9 +1,9 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-rev" +name = "agentos-rev" version.workspace = true edition.workspace = true license.workspace = true -description = "rev implementation for secure-exec standalone binaries" +description = "rev implementation for agentos standalone binaries" [dependencies] diff --git a/software/coreutils/native/crates/strings-cmd/Cargo.toml b/software/coreutils/native/crates/strings-cmd/Cargo.toml index 7c3c023a54..3960298ab2 100644 --- a/software/coreutils/native/crates/strings-cmd/Cargo.toml +++ b/software/coreutils/native/crates/strings-cmd/Cargo.toml @@ -1,9 +1,9 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-strings-cmd" +name = "agentos-strings-cmd" version.workspace = true edition.workspace = true license.workspace = true -description = "strings command implementation for secure-exec standalone binaries" +description = "strings command implementation for agentos standalone binaries" [dependencies] diff --git a/software/coreutils/package.json b/software/coreutils/package.json index 77e14e7a00..0e2f485859 100644 --- a/software/coreutils/package.json +++ b/software/coreutils/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "GNU coreutils for secure-exec VMs (sh, cat, ls, cp, sort, and 80+ commands)", + "description": "GNU coreutils for agentos VMs (sh, cat, ls, cp, sort, and 80+ commands)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/curl/native/crates/cmd-curl/Cargo.toml b/software/curl/native/crates/cmd-curl/Cargo.toml index 5a65154842..c73e7d9943 100644 --- a/software/curl/native/crates/cmd-curl/Cargo.toml +++ b/software/curl/native/crates/cmd-curl/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-curl" version.workspace = true edition.workspace = true license.workspace = true -description = "Minimal curl-compatible HTTP client for secure-exec" +description = "Minimal curl-compatible HTTP client for agentos" [[bin]] name = "curl" path = "src/main.rs" [dependencies] -wasi-http = { package = "secureexec-wasi-http", path = "../../../../../toolchain/crates/libs/wasi-http" } +wasi-http = { package = "agentos-wasi-http", path = "../../../../../toolchain/crates/libs/wasi-http" } diff --git a/software/curl/package.json b/software/curl/package.json index db20039ec6..766ece1d85 100644 --- a/software/curl/package.json +++ b/software/curl/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "curl HTTP client for secure-exec VMs", + "description": "curl HTTP client for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/diffutils/native/crates/cmd-diff/Cargo.toml b/software/diffutils/native/crates/cmd-diff/Cargo.toml index 8cdc14cb7d..ddcd868da0 100644 --- a/software/diffutils/native/crates/cmd-diff/Cargo.toml +++ b/software/diffutils/native/crates/cmd-diff/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-diff" version.workspace = true edition.workspace = true license.workspace = true -description = "diff standalone binary for secure-exec VM" +description = "diff standalone binary for agentos VM" [[bin]] name = "diff" path = "src/main.rs" [dependencies] -secureexec-diff = { path = "../diff" } +agentos-diff = { path = "../diff" } diff --git a/software/diffutils/native/crates/cmd-diff/src/main.rs b/software/diffutils/native/crates/cmd-diff/src/main.rs index d892591ad3..6c88983f54 100644 --- a/software/diffutils/native/crates/cmd-diff/src/main.rs +++ b/software/diffutils/native/crates/cmd-diff/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_diff::main(args)); + std::process::exit(agentos_diff::main(args)); } diff --git a/software/diffutils/native/crates/diff/Cargo.toml b/software/diffutils/native/crates/diff/Cargo.toml index 587bcf5968..3bde435b91 100644 --- a/software/diffutils/native/crates/diff/Cargo.toml +++ b/software/diffutils/native/crates/diff/Cargo.toml @@ -1,10 +1,10 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-diff" +name = "agentos-diff" version.workspace = true edition.workspace = true license.workspace = true -description = "diff implementation for secure-exec standalone binaries" +description = "diff implementation for agentos standalone binaries" [dependencies] similar = "2" diff --git a/software/diffutils/package.json b/software/diffutils/package.json index 2882b62490..c92a052d30 100644 --- a/software/diffutils/package.json +++ b/software/diffutils/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "GNU diffutils for secure-exec VMs (diff)", + "description": "GNU diffutils for agentos VMs (diff)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/duckdb/package.json b/software/duckdb/package.json index ff3b48a02c..a510aa798f 100644 --- a/software/duckdb/package.json +++ b/software/duckdb/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "DuckDB CLI for secure-exec VMs", + "description": "DuckDB CLI for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/everything/package.json b/software/everything/package.json index 513c40afa7..908a561efc 100644 --- a/software/everything/package.json +++ b/software/everything/package.json @@ -3,7 +3,7 @@ "version": "0.3.0-rc.2", "type": "module", "license": "Apache-2.0", - "description": "All available WASM command packages for secure-exec VMs in a single bundle", + "description": "All available WASM command packages for agentos VMs in a single bundle", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/fd/native/crates/cmd-fd/Cargo.toml b/software/fd/native/crates/cmd-fd/Cargo.toml index ef6223d123..c4550c5955 100644 --- a/software/fd/native/crates/cmd-fd/Cargo.toml +++ b/software/fd/native/crates/cmd-fd/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-fd" version.workspace = true edition.workspace = true license.workspace = true -description = "fd standalone binary for secure-exec VM" +description = "fd standalone binary for agentos VM" publish = false [dependencies] diff --git a/software/fd/package.json b/software/fd/package.json index 9b31f4f20e..8c1df066dc 100644 --- a/software/fd/package.json +++ b/software/fd/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "fd fast file finder for secure-exec VMs", + "description": "fd fast file finder for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/file/native/crates/cmd-file/Cargo.toml b/software/file/native/crates/cmd-file/Cargo.toml index 65e6ee9f90..6384168a9a 100644 --- a/software/file/native/crates/cmd-file/Cargo.toml +++ b/software/file/native/crates/cmd-file/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-file" version.workspace = true edition.workspace = true license.workspace = true -description = "file standalone binary for secure-exec VM" +description = "file standalone binary for agentos VM" [[bin]] name = "file" path = "src/main.rs" [dependencies] -secureexec-file-cmd = { path = "../file-cmd" } +agentos-file-cmd = { path = "../file-cmd" } diff --git a/software/file/native/crates/cmd-file/src/main.rs b/software/file/native/crates/cmd-file/src/main.rs index 75ed52c6c5..a73f816ebf 100644 --- a/software/file/native/crates/cmd-file/src/main.rs +++ b/software/file/native/crates/cmd-file/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_file_cmd::main(args)); + std::process::exit(agentos_file_cmd::main(args)); } diff --git a/software/file/native/crates/file-cmd/Cargo.toml b/software/file/native/crates/file-cmd/Cargo.toml index 203113931a..c058ac7ab1 100644 --- a/software/file/native/crates/file-cmd/Cargo.toml +++ b/software/file/native/crates/file-cmd/Cargo.toml @@ -1,10 +1,10 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-file-cmd" +name = "agentos-file-cmd" version.workspace = true edition.workspace = true license.workspace = true -description = "file command implementation for secure-exec standalone binaries" +description = "file command implementation for agentos standalone binaries" [dependencies] infer = "0.16" diff --git a/software/file/package.json b/software/file/package.json index e3ab79cf8a..30511e0241 100644 --- a/software/file/package.json +++ b/software/file/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "file type detection for secure-exec VMs", + "description": "file type detection for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/findutils/native/crates/cmd-find/Cargo.toml b/software/findutils/native/crates/cmd-find/Cargo.toml index 19cc8f38f4..57bd3955da 100644 --- a/software/findutils/native/crates/cmd-find/Cargo.toml +++ b/software/findutils/native/crates/cmd-find/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-find" version.workspace = true edition.workspace = true license.workspace = true -description = "find standalone binary for secure-exec VM" +description = "find standalone binary for agentos VM" [[bin]] name = "find" diff --git a/software/findutils/native/crates/cmd-xargs/Cargo.toml b/software/findutils/native/crates/cmd-xargs/Cargo.toml index 1037c80a58..9feb70ce20 100644 --- a/software/findutils/native/crates/cmd-xargs/Cargo.toml +++ b/software/findutils/native/crates/cmd-xargs/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-xargs" version.workspace = true edition.workspace = true license.workspace = true -description = "xargs standalone binary for secure-exec VM" +description = "xargs standalone binary for agentos VM" [[bin]] name = "xargs" diff --git a/software/findutils/package.json b/software/findutils/package.json index a877bd859d..78e158a99e 100644 --- a/software/findutils/package.json +++ b/software/findutils/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "GNU findutils for secure-exec VMs (find, xargs)", + "description": "GNU findutils for agentos VMs (find, xargs)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/gawk/native/crates/awk/Cargo.toml b/software/gawk/native/crates/awk/Cargo.toml index c630320b93..3ed5dae9df 100644 --- a/software/gawk/native/crates/awk/Cargo.toml +++ b/software/gawk/native/crates/awk/Cargo.toml @@ -1,10 +1,10 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-awk" +name = "agentos-awk" version.workspace = true edition.workspace = true license.workspace = true -description = "awk implementation for secure-exec standalone binaries" +description = "awk implementation for agentos standalone binaries" [dependencies] awk-rs = "0.1.0" diff --git a/software/gawk/native/crates/cmd-awk/Cargo.toml b/software/gawk/native/crates/cmd-awk/Cargo.toml index af4cd03274..a8e848c71b 100644 --- a/software/gawk/native/crates/cmd-awk/Cargo.toml +++ b/software/gawk/native/crates/cmd-awk/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-awk" version.workspace = true edition.workspace = true license.workspace = true -description = "awk standalone binary for secure-exec VM" +description = "awk standalone binary for agentos VM" [[bin]] name = "awk" path = "src/main.rs" [dependencies] -secureexec-awk = { path = "../awk" } +agentos-awk = { path = "../awk" } diff --git a/software/gawk/native/crates/cmd-awk/src/main.rs b/software/gawk/native/crates/cmd-awk/src/main.rs index a80b7ea9ad..4542ac8005 100644 --- a/software/gawk/native/crates/cmd-awk/src/main.rs +++ b/software/gawk/native/crates/cmd-awk/src/main.rs @@ -2,7 +2,7 @@ fn main() { use std::io::Write; let args: Vec = std::env::args_os().collect(); - let mut code = secureexec_awk::main(args); + let mut code = agentos_awk::main(args); if let Err(error) = std::io::stdout().flush() { eprintln!("Error flushing stdout: {error}"); if code == 0 { diff --git a/software/gawk/package.json b/software/gawk/package.json index ed40a09c97..8ff4fbaa7c 100644 --- a/software/gawk/package.json +++ b/software/gawk/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "GNU awk text processing for secure-exec VMs", + "description": "GNU awk text processing for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/git/test/git.nightly.test.ts b/software/git/test/git.nightly.test.ts index c42be71d67..9f9a31e429 100644 --- a/software/git/test/git.nightly.test.ts +++ b/software/git/test/git.nightly.test.ts @@ -712,7 +712,7 @@ describeIf(hasGit, 'git command', () => { runHostGit(['-C', worktree, 'add', 'README.md']); runHostGit([ '-C', worktree, - '-c', 'user.name=secure-exec', '-c', 'user.email=agent@example.com', + '-c', 'user.name=agentos', '-c', 'user.email=agent@example.com', 'commit', '-m', 'seed', ]); runHostGit(['-C', worktree, 'checkout', '-b', 'feature/deep']); @@ -720,7 +720,7 @@ describeIf(hasGit, 'git command', () => { runHostGit(['-C', worktree, 'add', 'feature.txt']); runHostGit([ '-C', worktree, - '-c', 'user.name=secure-exec', '-c', 'user.email=agent@example.com', + '-c', 'user.name=agentos', '-c', 'user.email=agent@example.com', 'commit', '-m', 'feature branch', ]); runHostGit(['-C', worktree, 'checkout', 'main']); diff --git a/software/grep/native/crates/cmd-egrep/Cargo.toml b/software/grep/native/crates/cmd-egrep/Cargo.toml index b3eb4c9222..dc166edd22 100644 --- a/software/grep/native/crates/cmd-egrep/Cargo.toml +++ b/software/grep/native/crates/cmd-egrep/Cargo.toml @@ -11,4 +11,4 @@ name = "egrep" path = "src/main.rs" [dependencies] -shims = { package = "secureexec-shims", path = "../../../../../toolchain/crates/libs/shims" } +shims = { package = "agentos-shims", path = "../../../../../toolchain/crates/libs/shims" } diff --git a/software/grep/native/crates/cmd-fgrep/Cargo.toml b/software/grep/native/crates/cmd-fgrep/Cargo.toml index 573b6b100e..9b6b4b3f07 100644 --- a/software/grep/native/crates/cmd-fgrep/Cargo.toml +++ b/software/grep/native/crates/cmd-fgrep/Cargo.toml @@ -11,4 +11,4 @@ name = "fgrep" path = "src/main.rs" [dependencies] -shims = { package = "secureexec-shims", path = "../../../../../toolchain/crates/libs/shims" } +shims = { package = "agentos-shims", path = "../../../../../toolchain/crates/libs/shims" } diff --git a/software/grep/package.json b/software/grep/package.json index 9953786470..f75391e73a 100644 --- a/software/grep/package.json +++ b/software/grep/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "GNU grep pattern matching for secure-exec VMs (grep, egrep, fgrep)", + "description": "GNU grep pattern matching for agentos VMs (grep, egrep, fgrep)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/gzip/native/crates/cmd-gzip/Cargo.toml b/software/gzip/native/crates/cmd-gzip/Cargo.toml index dafe689b6d..1ec90fc294 100644 --- a/software/gzip/native/crates/cmd-gzip/Cargo.toml +++ b/software/gzip/native/crates/cmd-gzip/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-gzip" version.workspace = true edition.workspace = true license.workspace = true -description = "gzip standalone binary for secure-exec VM" +description = "gzip standalone binary for agentos VM" [[bin]] name = "gzip" path = "src/main.rs" [dependencies] -secureexec-gzip = { path = "../gzip" } +agentos-gzip = { path = "../gzip" } diff --git a/software/gzip/native/crates/cmd-gzip/src/main.rs b/software/gzip/native/crates/cmd-gzip/src/main.rs index 59581509ad..c32fbf080e 100644 --- a/software/gzip/native/crates/cmd-gzip/src/main.rs +++ b/software/gzip/native/crates/cmd-gzip/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_gzip::main(args)); + std::process::exit(agentos_gzip::main(args)); } diff --git a/software/gzip/native/crates/gzip/Cargo.toml b/software/gzip/native/crates/gzip/Cargo.toml index 897731b6d4..f3d4a6df8b 100644 --- a/software/gzip/native/crates/gzip/Cargo.toml +++ b/software/gzip/native/crates/gzip/Cargo.toml @@ -1,10 +1,10 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-gzip" +name = "agentos-gzip" version.workspace = true edition.workspace = true license.workspace = true -description = "gzip/gunzip/zcat implementations for secure-exec standalone binaries" +description = "gzip/gunzip/zcat implementations for agentos standalone binaries" [dependencies] flate2 = { version = "1.0", default-features = false, features = ["rust_backend"] } diff --git a/software/gzip/package.json b/software/gzip/package.json index 5bf04cc052..317b715754 100644 --- a/software/gzip/package.json +++ b/software/gzip/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "GNU gzip compression for secure-exec VMs (gzip, gunzip, zcat)", + "description": "GNU gzip compression for agentos VMs (gzip, gunzip, zcat)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/jq/native/crates/cmd-jq/Cargo.toml b/software/jq/native/crates/cmd-jq/Cargo.toml index bdc904ce10..7953ef04e1 100644 --- a/software/jq/native/crates/cmd-jq/Cargo.toml +++ b/software/jq/native/crates/cmd-jq/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-jq" version.workspace = true edition.workspace = true license.workspace = true -description = "jq standalone binary for secure-exec VM" +description = "jq standalone binary for agentos VM" [[bin]] name = "jq" path = "src/main.rs" [dependencies] -secureexec-jq = { path = "../jq" } +agentos-jq = { path = "../jq" } diff --git a/software/jq/native/crates/cmd-jq/src/main.rs b/software/jq/native/crates/cmd-jq/src/main.rs index b99f91eb3b..df83960ada 100644 --- a/software/jq/native/crates/cmd-jq/src/main.rs +++ b/software/jq/native/crates/cmd-jq/src/main.rs @@ -2,7 +2,7 @@ fn main() { use std::io::Write; let args: Vec = std::env::args_os().collect(); - let mut code = secureexec_jq::main(args); + let mut code = agentos_jq::main(args); if let Err(error) = std::io::stdout().flush() { eprintln!("Error flushing stdout: {error}"); if code == 0 { diff --git a/software/jq/native/crates/jq/Cargo.toml b/software/jq/native/crates/jq/Cargo.toml index 6a86e30e47..f991a42280 100644 --- a/software/jq/native/crates/jq/Cargo.toml +++ b/software/jq/native/crates/jq/Cargo.toml @@ -1,10 +1,10 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-jq" +name = "agentos-jq" version.workspace = true edition.workspace = true license.workspace = true -description = "jq implementation for secure-exec standalone binaries" +description = "jq implementation for agentos standalone binaries" [dependencies] jaq-core = "2.2" diff --git a/software/jq/package.json b/software/jq/package.json index 26d3c971ec..34c7e15d58 100644 --- a/software/jq/package.json +++ b/software/jq/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "jq JSON processor for secure-exec VMs", + "description": "jq JSON processor for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/ripgrep/native/crates/cmd-rg/Cargo.toml b/software/ripgrep/native/crates/cmd-rg/Cargo.toml index f6184892c7..3824b95025 100644 --- a/software/ripgrep/native/crates/cmd-rg/Cargo.toml +++ b/software/ripgrep/native/crates/cmd-rg/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-rg" version.workspace = true edition.workspace = true license.workspace = true -description = "rg (ripgrep) standalone binary for secure-exec VM" +description = "rg (ripgrep) standalone binary for agentos VM" publish = false [dependencies] diff --git a/software/ripgrep/package.json b/software/ripgrep/package.json index 6179903927..1de009f1ae 100644 --- a/software/ripgrep/package.json +++ b/software/ripgrep/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "ripgrep fast search for secure-exec VMs", + "description": "ripgrep fast search for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/ripgrep/test/ripgrep.nightly.test.ts b/software/ripgrep/test/ripgrep.nightly.test.ts index aac5a9f08f..9bab2d3217 100644 --- a/software/ripgrep/test/ripgrep.nightly.test.ts +++ b/software/ripgrep/test/ripgrep.nightly.test.ts @@ -71,7 +71,7 @@ describeIf(hasWasmBinaries, "ripgrep command", { timeout: 10_000 }, () => { const result = await kernel.exec("rg --version", {}); expect(result.stdout).toContain("ripgrep 15.1.0"); - expect(result.stdout).not.toContain("secure-exec"); + expect(result.stdout).not.toContain("agentos"); }); it("searches recursively and respects .gitignore by default", async () => { diff --git a/software/sed/native/crates/cmd-sed/Cargo.toml b/software/sed/native/crates/cmd-sed/Cargo.toml index 990de688db..5b82328c9b 100644 --- a/software/sed/native/crates/cmd-sed/Cargo.toml +++ b/software/sed/native/crates/cmd-sed/Cargo.toml @@ -4,7 +4,7 @@ name = "cmd-sed" version.workspace = true edition.workspace = true license.workspace = true -description = "sed standalone binary for secure-exec VM" +description = "sed standalone binary for agentos VM" [[bin]] name = "sed" diff --git a/software/sed/package.json b/software/sed/package.json index f1e1e364c4..59a2b5e2cb 100644 --- a/software/sed/package.json +++ b/software/sed/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "GNU sed stream editor for secure-exec VMs", + "description": "GNU sed stream editor for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/sqlite3/package.json b/software/sqlite3/package.json index bbbfd350fc..e7631d659c 100644 --- a/software/sqlite3/package.json +++ b/software/sqlite3/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "SQLite3 CLI for secure-exec VMs", + "description": "SQLite3 CLI for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/tar/native/crates/cmd-tar/Cargo.toml b/software/tar/native/crates/cmd-tar/Cargo.toml index a5ca3d0b4b..880003f2ca 100644 --- a/software/tar/native/crates/cmd-tar/Cargo.toml +++ b/software/tar/native/crates/cmd-tar/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-tar" version.workspace = true edition.workspace = true license.workspace = true -description = "tar standalone binary for secure-exec VM" +description = "tar standalone binary for agentos VM" [[bin]] name = "tar" path = "src/main.rs" [dependencies] -secureexec-tar = { path = "../tar" } +agentos-tar = { path = "../tar" } diff --git a/software/tar/native/crates/cmd-tar/src/main.rs b/software/tar/native/crates/cmd-tar/src/main.rs index 304ba12711..5545be73a1 100644 --- a/software/tar/native/crates/cmd-tar/src/main.rs +++ b/software/tar/native/crates/cmd-tar/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_tar::main(args)); + std::process::exit(agentos_tar::main(args)); } diff --git a/software/tar/native/crates/tar/Cargo.toml b/software/tar/native/crates/tar/Cargo.toml index f10f711e29..effe8c4c6b 100644 --- a/software/tar/native/crates/tar/Cargo.toml +++ b/software/tar/native/crates/tar/Cargo.toml @@ -1,10 +1,10 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-tar" +name = "agentos-tar" version.workspace = true edition.workspace = true license.workspace = true -description = "tar implementation for secure-exec standalone binaries" +description = "tar implementation for agentos standalone binaries" [dependencies] flate2 = { version = "1.0", default-features = false, features = ["rust_backend"] } diff --git a/software/tar/package.json b/software/tar/package.json index 916fe4f32f..eb296ac842 100644 --- a/software/tar/package.json +++ b/software/tar/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "GNU tar archiver for secure-exec VMs", + "description": "GNU tar archiver for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/tree/package.json b/software/tree/package.json index 851e452e08..498ea7c83f 100644 --- a/software/tree/package.json +++ b/software/tree/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "GPL-2.0-or-later", - "description": "tree directory listing for secure-exec VMs", + "description": "tree directory listing for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/unzip/package.json b/software/unzip/package.json index 38b24d6d5c..3277b5708a 100644 --- a/software/unzip/package.json +++ b/software/unzip/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "unzip archive extraction for secure-exec VMs", + "description": "unzip archive extraction for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/vim/native/c/vim-bridge/compat.h b/software/vim/native/c/vim-bridge/compat.h index 05477f040a..cd28a6e3b4 100644 --- a/software/vim/native/c/vim-bridge/compat.h +++ b/software/vim/native/c/vim-bridge/compat.h @@ -1,7 +1,7 @@ /* compat.h — forced-include shim filling full-OS libc gaps for porting - * Linux C programs (vim) to the secure-exec wasm runtime. */ -#ifndef _SECUREEXEC_WASM_COMPAT_H -#define _SECUREEXEC_WASM_COMPAT_H + * Linux C programs (vim) to the agentos wasm runtime. */ +#ifndef _AGENTOS_WASM_COMPAT_H +#define _AGENTOS_WASM_COMPAT_H #include #include #include diff --git a/software/vim/native/c/vim-bridge/termios.h b/software/vim/native/c/vim-bridge/termios.h index e7f777081d..3d8897dcf2 100644 --- a/software/vim/native/c/vim-bridge/termios.h +++ b/software/vim/native/c/vim-bridge/termios.h @@ -1,4 +1,4 @@ -/* termios.h — POSIX termios for the secure-exec full-OS libc (musl layout). +/* termios.h — POSIX termios for the agentos full-OS libc (musl layout). * * wasi-libc ships no termios; this header pairs with termios_bridge.c, which * implements the functions on top of the `host_tty` kernel imports (raw-mode diff --git a/software/vim/native/c/vim-bridge/termios_bridge.c b/software/vim/native/c/vim-bridge/termios_bridge.c index 987fa1a05a..bf1a9dd6e9 100644 --- a/software/vim/native/c/vim-bridge/termios_bridge.c +++ b/software/vim/native/c/vim-bridge/termios_bridge.c @@ -1,4 +1,4 @@ -/* termios_bridge.c — termios for the secure-exec full-OS libc. +/* termios_bridge.c — termios for the agentos full-OS libc. * * The kernel owns the PTY line discipline (canonical/echo/signals) and exposes * a raw-mode toggle + window size to guests via the `host_tty` WASM imports. diff --git a/software/vim/package.json b/software/vim/package.json index 6c7ee85c78..48752ac884 100644 --- a/software/vim/package.json +++ b/software/vim/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "vim for secure-exec VMs (wasm build + bundled runtime via provides)", + "description": "vim for agentos VMs (wasm build + bundled runtime via provides)", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/yq/native/crates/cmd-yq/Cargo.toml b/software/yq/native/crates/cmd-yq/Cargo.toml index dfa19879f9..06ccd3b1cd 100644 --- a/software/yq/native/crates/cmd-yq/Cargo.toml +++ b/software/yq/native/crates/cmd-yq/Cargo.toml @@ -4,11 +4,11 @@ name = "cmd-yq" version.workspace = true edition.workspace = true license.workspace = true -description = "yq standalone binary for secure-exec VM" +description = "yq standalone binary for agentos VM" [[bin]] name = "yq" path = "src/main.rs" [dependencies] -secureexec-yq = { path = "../yq" } +agentos-yq = { path = "../yq" } diff --git a/software/yq/native/crates/cmd-yq/src/main.rs b/software/yq/native/crates/cmd-yq/src/main.rs index b2e37359de..6a7f52bc9d 100644 --- a/software/yq/native/crates/cmd-yq/src/main.rs +++ b/software/yq/native/crates/cmd-yq/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args_os().collect(); - std::process::exit(secureexec_yq::main(args)); + std::process::exit(agentos_yq::main(args)); } diff --git a/software/yq/native/crates/yq/Cargo.toml b/software/yq/native/crates/yq/Cargo.toml index 5712402a21..15ac1ee193 100644 --- a/software/yq/native/crates/yq/Cargo.toml +++ b/software/yq/native/crates/yq/Cargo.toml @@ -1,10 +1,10 @@ [package] workspace = "../../../../../toolchain" -name = "secureexec-yq" +name = "agentos-yq" version.workspace = true edition.workspace = true license.workspace = true -description = "yq (YAML/XML/TOML/JSON processor) implementation for secure-exec standalone binaries" +description = "yq (YAML/XML/TOML/JSON processor) implementation for agentos standalone binaries" [dependencies] jaq-core = "2.2" diff --git a/software/yq/package.json b/software/yq/package.json index 923fe10bcb..b1bb175f33 100644 --- a/software/yq/package.json +++ b/software/yq/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "yq YAML/JSON processor for secure-exec VMs", + "description": "yq YAML/JSON processor for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/software/zip/package.json b/software/zip/package.json index 0367d1268b..786007476c 100644 --- a/software/zip/package.json +++ b/software/zip/package.json @@ -3,7 +3,7 @@ "version": "0.3.3", "type": "module", "license": "Apache-2.0", - "description": "zip archive creation for secure-exec VMs", + "description": "zip archive creation for agentos VMs", "main": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ diff --git a/test-harness/src/agent-os-conformance.ts b/test-harness/src/agent-os-conformance.ts index c3dd250c6e..21c8cae5b2 100644 --- a/test-harness/src/agent-os-conformance.ts +++ b/test-harness/src/agent-os-conformance.ts @@ -7,59 +7,86 @@ export { } from "./agent-os-conformance-fixture.js"; export const AGENT_OS_CONFORMANCE_ACTIONS = [ - "readFile", - "writeFile", - "readFiles", - "writeFiles", - "stat", - "mkdir", - "readdir", - "readdirEntries", - "readdirRecursive", - "exists", - "move", - "remove", - "exec", - "execArgv", - "spawn", - "waitProcess", - "killProcess", - "stopProcess", - "listProcesses", - "allProcesses", - "processTree", - "getProcess", - "writeProcessStdin", - "closeProcessStdin", - "openShell", - "writeShell", - "resizeShell", - "closeShell", - "waitShell", - "httpRequest", - "scheduleCron", - "listCronJobs", - "cancelCronJob", - "listAgents", - "listMounts", - "listSoftware", - "exportRootFilesystem", - "mountFs", - "unmountFs", - "linkSoftware", - "openSession", - "getSession", - "prompt", - "cancelPrompt", - "unloadSession", - "deleteSession", - "respondPermission", - "listSessions", - "readHistory", - "getSessionConfig", - "setSessionConfigOption", - "getSessionCapabilities", - "getSessionAgentInfo", + "process.exec", + "process.execFile", + "process.spawn", + "process.get", + "process.list", + "process.listAll", + "process.tree", + "process.wait", + "process.stop", + "process.kill", + "process.writeStdin", + "process.closeStdin", + "javascript.execute", + "javascript.evaluate", + "javascript.executeFile", + "javascript.typescript.execute", + "javascript.typescript.evaluate", + "javascript.typescript.executeFile", + "javascript.typescript.check", + "javascript.typescript.checkProject", + "javascript.npm.install", + "javascript.npm.runScript", + "javascript.npm.runPackage", + "python.execute", + "python.evaluate", + "python.executeFile", + "python.executeModule", + "python.install", + "executions.get", + "executions.list", + "executions.wait", + "executions.cancel", + "executions.signal", + "executions.reset", + "executions.delete", + "executions.writeStdin", + "executions.closeStdin", + "executions.resizePty", + "executions.readOutput", + "terminal.open", + "terminal.write", + "terminal.resize", + "terminal.wait", + "terminal.close", + "filesystem.readFile", + "filesystem.writeFile", + "filesystem.readFiles", + "filesystem.writeFiles", + "filesystem.stat", + "filesystem.mkdir", + "filesystem.readdir", + "filesystem.readdirEntries", + "filesystem.readdirRecursive", + "filesystem.exists", + "filesystem.move", + "filesystem.remove", + "filesystem.export", + "filesystem.mount", + "filesystem.unmount", + "filesystem.listMounts", + "network.httpRequest", + "software.list", + "software.link", + "agents.list", + "sessions.open", + "sessions.get", + "sessions.list", + "sessions.delete", + "sessions.unload", + "sessions.prompt", + "sessions.cancelPrompt", + "sessions.respondPermission", + "sessions.readHistory", + "sessions.getConfig", + "sessions.setConfigOption", + "sessions.getCapabilities", + "sessions.getAgentInfo", + "cron.schedule", + "cron.list", + "cron.cancel", ] as const; export type AgentOsConformanceAction = @@ -74,6 +101,8 @@ export const AGENT_OS_CONFORMANCE_EVENTS = [ "cronEvent", "sessionEvent", "agentExit", + "executionOutput", + "executionCompleted", ] as const; export type AgentOsConformanceEvent = @@ -155,44 +184,52 @@ export function defineAgentOsConformanceSuite( }, 120_000); test("filesystem actions preserve bytes, metadata, batches, and directory semantics", async () => { - await backend.call("mkdir", "/conformance/fs/nested", { + await backend.call("filesystem.mkdir", "/conformance/fs/nested", { recursive: true, }); - await backend.call("writeFile", "/conformance/fs/a.txt", "alpha"); + await backend.call("filesystem.writeFile", "/conformance/fs/a.txt", "alpha"); await backend.call( - "writeFile", + "filesystem.writeFile", "/conformance/fs/nested/b.bin", new Uint8Array([0, 1, 2, 255]), ); expect( - text(await backend.call("readFile", "/conformance/fs/a.txt")), + text(await backend.call("filesystem.readFile", "/conformance/fs/a.txt")), ).toBe("alpha"); expect([ ...asBytes( - await backend.call("readFile", "/conformance/fs/nested/b.bin"), + await backend.call( + "filesystem.readFile", + "/conformance/fs/nested/b.bin", + ), ), ]).toEqual([0, 1, 2, 255]); - const writes = await backend.call("writeFiles", [ + const writes = await backend.call("filesystem.writeFiles", [ { path: "/conformance/fs/batch/c.txt", content: "charlie" }, { path: "/proc/conformance-denied", content: "no" }, ]); expect(writes.map((entry) => entry.success)).toEqual([true, false]); - const reads = await backend.call("readFiles", [ + const reads = await backend.call("filesystem.readFiles", [ "/conformance/fs/a.txt", "/conformance/fs/missing", ]); expect(text(reads[0].content)).toBe("alpha"); expect(reads[1].content).toBeNull(); - expect(await backend.call("exists", "/conformance/fs/a.txt")).toBe(true); - const stat = await backend.call("stat", "/conformance/fs/nested"); + expect( + await backend.call("filesystem.exists", "/conformance/fs/a.txt"), + ).toBe(true); + const stat = await backend.call( + "filesystem.stat", + "/conformance/fs/nested", + ); expect(stat.isDirectory).toBe(true); expect( - await backend.call("readdir", "/conformance/fs"), + await backend.call("filesystem.readdir", "/conformance/fs"), ).toEqual(expect.arrayContaining(["a.txt", "nested", "batch"])); const entries = await backend.call( - "readdirEntries", + "filesystem.readdirEntries", "/conformance/fs", ); expect(entries).toEqual( @@ -201,7 +238,7 @@ export function defineAgentOsConformanceSuite( ]), ); const recursive = await backend.call( - "readdirRecursive", + "filesystem.readdirRecursive", "/conformance/fs", ); expect(recursive.map((entry) => entry.path)).toContain( @@ -209,21 +246,26 @@ export function defineAgentOsConformanceSuite( ); await backend.call( - "move", + "filesystem.move", "/conformance/fs/a.txt", "/conformance/fs/moved.txt", ); - expect(await backend.call("exists", "/conformance/fs/a.txt")).toBe(false); - await backend.call("remove", "/conformance/fs/moved.txt"); - expect(await backend.call("exists", "/conformance/fs/moved.txt")).toBe( - false, - ); + expect( + await backend.call("filesystem.exists", "/conformance/fs/a.txt"), + ).toBe(false); + await backend.call("filesystem.remove", "/conformance/fs/moved.txt"); + expect( + await backend.call("filesystem.exists", "/conformance/fs/moved.txt"), + ).toBe(false); }, 60_000); test("process actions and events cover execution, inspection, stdin, stop, and kill", async () => { - const execResult = await backend.call("exec", "printf exec-ok"); + const execResult = await backend.call( + "process.exec", + "printf exec-ok", + ); expect(execResult).toMatchObject({ exitCode: 0, stdout: "exec-ok" }); - const argvResult = await backend.call("execArgv", "printf", [ + const argvResult = await backend.call("process.execFile", "printf", [ "argv-ok", ]); expect(argvResult).toMatchObject({ exitCode: 0, stdout: "argv-ok" }); @@ -235,7 +277,7 @@ export function defineAgentOsConformanceSuite( ); const offExit = backend.on("processExit", (event) => exits.push(event)); const spawned = await backend.call( - "spawn", + "process.spawn", "node", [ "-e", @@ -243,27 +285,27 @@ export function defineAgentOsConformanceSuite( ], { streamStdin: true }, ); - expect((await backend.call("getProcess", spawned.pid)).running).toBe( + expect((await backend.call("process.get", spawned.pid)).running).toBe( true, ); expect( - (await backend.call("listProcesses")).some( + (await backend.call("process.list")).some( (process) => process.pid === spawned.pid, ), ).toBe(true); expect( - (await backend.call("allProcesses")).some( + (await backend.call("process.listAll")).some( (process) => process.pid === spawned.pid, ), ).toBe(true); expect( - (await backend.call("processTree")).some( + (await backend.call("process.tree")).some( (process) => process.pid === spawned.pid, ), ).toBe(true); - await backend.call("writeProcessStdin", spawned.pid, "hello"); - await backend.call("closeProcessStdin", spawned.pid); - expect(await backend.call("waitProcess", spawned.pid)).toBe(0); + await backend.call("process.writeStdin", spawned.pid, "hello"); + await backend.call("process.closeStdin", spawned.pid); + expect(await backend.call("process.wait", spawned.pid)).toBe(0); await eventually( () => output, (events) => @@ -278,18 +320,18 @@ export function defineAgentOsConformanceSuite( ), ); - const stopped = await backend.call("spawn", "node", [ + const stopped = await backend.call("process.spawn", "node", [ "-e", "setInterval(() => {}, 1000)", ]); - await backend.call("stopProcess", stopped.pid); - await backend.call("waitProcess", stopped.pid); - const killed = await backend.call("spawn", "node", [ + await backend.call("process.stop", stopped.pid); + await backend.call("process.wait", stopped.pid); + const killed = await backend.call("process.spawn", "node", [ "-e", "setInterval(() => {}, 1000)", ]); - await backend.call("killProcess", killed.pid); - await backend.call("waitProcess", killed.pid); + await backend.call("process.kill", killed.pid); + await backend.call("process.wait", killed.pid); offOutput(); offExit(); }, 60_000); @@ -303,7 +345,7 @@ export function defineAgentOsConformanceSuite( stderr.push(event), ); const offExit = backend.on("shellExit", (event) => exits.push(event)); - const shell = await backend.call("openShell", { + const shell = await backend.call("terminal.open", { command: "node", args: [ "-e", @@ -312,9 +354,9 @@ export function defineAgentOsConformanceSuite( cols: 80, rows: 24, }); - await backend.call("resizeShell", shell.shellId, 100, 30); - await backend.call("writeShell", shell.shellId, "hello-shell\n"); - expect(await backend.call("waitShell", shell.shellId)).toBe(0); + await backend.call("terminal.resize", shell.shellId, 100, 30); + await backend.call("terminal.write", shell.shellId, "hello-shell\n"); + expect(await backend.call("terminal.wait", shell.shellId)).toBe(0); await eventually( () => data, (events) => @@ -338,11 +380,11 @@ export function defineAgentOsConformanceSuite( (events) => events.some((event) => event.shellId === shell.shellId), ); - const closable = await backend.call("openShell", { + const closable = await backend.call("terminal.open", { command: "node", args: ["-e", "setInterval(() => {}, 1000)"], }); - await backend.call("closeShell", closable.shellId); + await backend.call("terminal.close", closable.shellId); offData(); offStderr(); offExit(); @@ -353,7 +395,7 @@ export function defineAgentOsConformanceSuite( const offOutput = backend.on("processOutput", (event) => output.push(event), ); - const server = await backend.call("spawn", "node", [ + const server = await backend.call("process.spawn", "node", [ "-e", ` const http = require('http'); @@ -373,7 +415,7 @@ export function defineAgentOsConformanceSuite( ), ); const response = await backend.call( - "httpRequest", + "network.httpRequest", { port: 31337, path: "/path?q=1", @@ -385,27 +427,27 @@ export function defineAgentOsConformanceSuite( expect(response.status).toBe(200); expect(response.headers["x-conformance"]).toBe("yes"); expect(text(response.body)).toBe("POST:/path?q=1:payload"); - await backend.call("killProcess", server.pid); - await backend.call("waitProcess", server.pid); + await backend.call("process.kill", server.pid); + await backend.call("process.wait", server.pid); offOutput(); - const job = await backend.call("scheduleCron", { + const job = await backend.call("cron.schedule", { id: "conformance-cron", schedule: "0 0 1 1 *", action: { type: "exec", command: "node", args: ["-e", "void 0"] }, overlap: "skip", }); expect(job.id).toBe("conformance-cron"); - expect(await backend.call("listCronJobs")).toEqual([ + expect(await backend.call("cron.list")).toEqual([ expect.objectContaining({ id: "conformance-cron", overlap: "skip" }), ]); - await backend.call("cancelCronJob", job.id); - expect(await backend.call("listCronJobs")).toEqual([]); + await backend.call("cron.cancel", job.id); + expect(await backend.call("cron.list")).toEqual([]); const cronEvents: any[] = []; const offCron = backend.on("cronEvent", (event) => cronEvents.push(event), ); - const oneShot = await backend.call("scheduleCron", { + const oneShot = await backend.call("cron.schedule", { id: "conformance-cron-event", schedule: new Date(Date.now() + 750).toISOString(), action: { type: "exec", command: "node", args: ["-e", "void 0"] }, @@ -419,10 +461,10 @@ export function defineAgentOsConformanceSuite( ), 10_000, ); - await backend.call("cancelCronJob", oneShot.id); + await backend.call("cron.cancel", oneShot.id); offCron(); - const agents = await backend.call("listAgents"); + const agents = await backend.call("agents.list"); expect(agents).toEqual( expect.arrayContaining([ expect.objectContaining({ @@ -431,7 +473,7 @@ export function defineAgentOsConformanceSuite( }), ]), ); - expect(await backend.call("listMounts")).toContainEqual( + expect(await backend.call("filesystem.listMounts")).toContainEqual( expect.objectContaining({ path: "/conformance-mount", kind: "host_dir", @@ -441,19 +483,19 @@ export function defineAgentOsConformanceSuite( expect( text( await backend.call( - "readFile", + "filesystem.readFile", "/conformance-mount/package.json", ), ), ).toContain(CONFORMANCE_AGENT_NAME); await expect( backend.call( - "writeFile", + "filesystem.writeFile", "/conformance-mount/should-fail.txt", "read-only", ), ).rejects.toThrow(); - const software = await backend.call("listSoftware"); + const software = await backend.call("software.list"); expect( software.some((entry) => entry.commands.includes("conformance-agent-acp"), @@ -464,7 +506,7 @@ export function defineAgentOsConformanceSuite( test("sessions cover durable history, live events, permission replies, config, restoration, unload, and deletion", async () => { const sessionId = "conformance-session"; expect( - await backend.call("openSession", { + await backend.call("sessions.open", { sessionId, agent: CONFORMANCE_AGENT_NAME, permissionPolicy: "ask", @@ -474,20 +516,20 @@ export function defineAgentOsConformanceSuite( additionalInstructions: "shared-suite", }), ).toBeUndefined(); - expect((await backend.call("listSessions")).sessions).toContainEqual( + expect((await backend.call("sessions.list")).sessions).toContainEqual( expect.objectContaining({ sessionId, agent: CONFORMANCE_AGENT_NAME, }), ); expect( - (await backend.call("getSessionConfig", { sessionId })).options, + (await backend.call("sessions.getConfig", { sessionId })).options, ).toHaveLength(2); expect( - await backend.call("getSessionCapabilities", { sessionId }), + await backend.call("sessions.getCapabilities", { sessionId }), ).toMatchObject({ loadSession: true }); expect( - await backend.call("getSessionAgentInfo", { sessionId }), + await backend.call("sessions.getAgentInfo", { sessionId }), ).toMatchObject({ name: CONFORMANCE_AGENT_NAME }); const sessionEvents: any[] = []; @@ -503,7 +545,7 @@ export function defineAgentOsConformanceSuite( permissionReady.resolve(event); } }); - const prompt = backend.call("prompt", { + const prompt = backend.call("sessions.prompt", { sessionId, content: [{ type: "text", text: "permission please" }], }); @@ -526,7 +568,7 @@ export function defineAgentOsConformanceSuite( ), ]); expect(permission.toolCall.toolCallId).toBe("binding-call-1"); - await backend.call("respondPermission", { + await backend.call("sessions.respondPermission", { sessionId, requestId: permission.requestId, optionId: "allow_once", @@ -534,17 +576,19 @@ export function defineAgentOsConformanceSuite( expect(JSON.stringify((await prompt).message)).toContain("permission"); expect(permissions).toHaveLength(1); - await backend.call("setSessionConfigOption", { + await backend.call("sessions.setConfigOption", { sessionId, configId: "model", value: "next-model", }); - await backend.call("setSessionConfigOption", { + await backend.call("sessions.setConfigOption", { sessionId, configId: "thought_level", value: "high", }); - const config = (await backend.call("getSessionConfig", { sessionId })) + const config = ( + await backend.call("sessions.getConfig", { sessionId }) + ) .options; expect( config.find((entry: any) => entry.category === "model")?.currentValue, @@ -553,8 +597,10 @@ export function defineAgentOsConformanceSuite( config.find((entry: any) => entry.category === "thought_level") ?.currentValue, ).toBe("high"); - await backend.call("cancelPrompt", { sessionId }); - const history = await backend.call("readHistory", { sessionId }); + await backend.call("sessions.cancelPrompt", { sessionId }); + const history = await backend.call("sessions.readHistory", { + sessionId, + }); expect(history.events.length).toBeGreaterThan(0); const permissionHistory = history.events.filter( (entry: any) => @@ -584,14 +630,16 @@ export function defineAgentOsConformanceSuite( } expect(recoveredBySequence.size).toBe(history.events.length); - await backend.call("unloadSession", { sessionId }); - const restored = await backend.call("prompt", { + await backend.call("sessions.unload", { sessionId }); + const restored = await backend.call("sessions.prompt", { sessionId, content: [{ type: "text", text: "restored" }], }); expect(JSON.stringify(restored.message)).toContain("restored"); - await backend.call("deleteSession", { sessionId }); - expect((await backend.call("listSessions")).sessions).not.toContainEqual( + await backend.call("sessions.delete", { sessionId }); + expect( + (await backend.call("sessions.list")).sessions, + ).not.toContainEqual( expect.objectContaining({ sessionId }), ); offSession(); @@ -607,19 +655,21 @@ export function defineAgentOsConformanceSuite( // permissionPolicy is deliberately omitted: the sidecar-owned default // must be allow_all for both Core and actor clients. expect( - await backend.call("openSession", { + await backend.call("sessions.open", { sessionId, agent: CONFORMANCE_AGENT_NAME, skipOsInstructions: true, }), ).toBeUndefined(); - const result = await backend.call("prompt", { + const result = await backend.call("sessions.prompt", { sessionId, content: [{ type: "text", text: "permission automatically" }], }); expect(JSON.stringify(result.message)).toContain("allow_once"); - const history = await backend.call("readHistory", { sessionId }); + const history = await backend.call("sessions.readHistory", { + sessionId, + }); expect( history.events.filter( (entry: any) => @@ -636,7 +686,7 @@ export function defineAgentOsConformanceSuite( ).toBe(false); } finally { offSession(); - await backend.call("deleteSession", { sessionId }); + await backend.call("sessions.delete", { sessionId }); } }, 90_000); @@ -646,13 +696,13 @@ export function defineAgentOsConformanceSuite( crashes.push(event), ); const sessionId = "crash-session"; - await backend.call("openSession", { + await backend.call("sessions.open", { sessionId, agent: CONFORMANCE_AGENT_NAME, skipOsInstructions: true, }); await backend - .call("prompt", { + .call("sessions.prompt", { sessionId, content: [{ type: "text", text: "crash-adapter" }], }) @@ -662,7 +712,7 @@ export function defineAgentOsConformanceSuite( (events) => events.some((event) => event.sessionId === sessionId), 15_000, ); - await backend.call("deleteSession", { sessionId }); + await backend.call("sessions.delete", { sessionId }); offCrash(); }, 30_000); diff --git a/tests/fixtures/crypto-basic-conformance.json b/tests/fixtures/crypto-basic-conformance.json index d24fe4c19e..7493a8e4ae 100644 --- a/tests/fixtures/crypto-basic-conformance.json +++ b/tests/fixtures/crypto-basic-conformance.json @@ -1,5 +1,5 @@ { - "message": "secure-exec", + "message": "agentos", "hmacKey": "shared-secret", "password": "password", "salt": "salt", @@ -12,20 +12,20 @@ }, "aesCbc": { "algorithm": "aes-256-cbc", - "plaintext": "secure-exec-crypto-surface", + "plaintext": "agentos-crypto-surface", "keyHex": "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff", "ivHex": "0102030405060708090a0b0c0d0e0f10" }, "aesGcm": { "algorithm": "aes-256-gcm", - "plaintext": "secure-exec-gcm-authenticated", - "aad": "secure-exec-aad", + "plaintext": "agentos-gcm-authenticated", + "aad": "agentos-aad", "keyHex": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "ivHex": "101112131415161718191a1b", "authTagLength": 16 }, "rsa": { - "message": "secure-exec advanced crypto", + "message": "agentos advanced crypto", "privatePem": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5r8vgRgQj8qd5\nBzip2/NdY6qTnrF5D5V7F+cSoARQbWTxqoAq92II5swnKTGafmf4m1mdFT9Jqwh8\n+oD2q9cokZsPONBEQTbhgLziUC5h8BU8xZf/5yHi8oQ9CX96D5XNyGZA4fpG4l+0\nxMUXCvPL4loKElgBvSrGKYqA+/3gAqQESELKFzdwiwy6BsJuIYgeHp48aHSm/Mei\nhi7nGncWIWRSccbUbQ2rskqwNJJEi7w1cGzPfyyxlmK7RvxFM979lHtbS266j3K/\nD8azaL14oJkWesjwjAwXaCG+YTBZsznpNIkbzNcboqb7azxPc8ihLYEhZgw7Mypw\nW34i3IWpAgMBAAECggEABiGud0m7y3ew6dezTZsBDPvq2MFCqTWhB4JxQG9Lq5MF\n/gIinyIx7Asgm0hw2WIQ/kFO/73N+OZIO1953VHGViu2Ty94MFDNxm63jgRjMhu5\nIwHmJ4g5cu+NyCAyQ+5HN/2rY4gZLIVyiJsYyptNFDxb7pcCR47SEauy5aVGK4/y\nuv3WmZQPU8EkCol7Cxhgq5MFkfLuXN44+Lt81ADaI8bcKgzosyczswkijAVzmmjt\ncc4T/SDy8dZBQZistej5pBWVaDJHIEJyoxxRrVy5mJCDEfSfDDAm2iNrGGQAMQ6x\nlpVAjT5MtBA+tbwXe4ODMZaGYKiiFC6DxJX8yThrawKBgQDo3Fnf0+3qkmfXbuG2\nO3GjJQ0S5tthS7Av6e90c68zLMn795lh30BCCuMnwfIAw3gP7A3mxXBepFNaG3/h\nUJ5BhT3pegg/9qetNHgLuUpOZE7F22h/TGNBeV2TJr5oYyCQU289yvRgl9tYSE5J\no5/YnGCX9nnTj2LdOvN1BDqHGwKBgQDMI2d8MROUsbLCKR7sHpkpk8lC6wb23x2s\nLe3tb8cjnSLwfIDKruV1O85AVPmQ9vD7lkwDUtn6WsSjK01GBCdS19uOlPbwhsAe\nsVDEa0pchTHerHIFyWX67gX2lWB9wyb5WnoaOW3Z07E2l//5x6/MQihF+KJ7+ooB\nZNj5ZcAeiwKBgQDEfpyAWY9b76sciX6Bjeu4ZV2A47mfgoTsCZV8SNpAbr0Kl8ag\nZgkNMa65L9mMd2Vq2iBo6ZaG5ldHpAjnEmZYl5zE1ar8fqDDcZETI4nmWJJ4N0sY\nkFb5OvaRY5Is9+jUoPMvy4EnuTzoZCtbzGzoFh0UXnIy6b3dPQ+PYMAanQKBgAHo\nzt39g4ZfhyGDyvNAcgROipJiqmUCvz9OCqyu3/j4TkxbjcTXj/PhxFMbuF3fwW9I\n/5sEWl+aG76+9/EQtuFyfW4+/HRRfliLJgtASajF4iqICGT/dkG7mjitOwLSIXox\nm3TFVr6z2TN+hnlqob1SXRgSdEqelE3hCJqEliBzAoGAY8tfltBpUviP6QvUWLuR\nUAVVJAbO5+4nqoAuw99YUk8ROynPJ0DRcl4gWdpmsn3en4l8tDa2B2+4f4aqIHk9\n2pHtDYOvwcOHUmVM3wUd+A8g51aTGc4cDrYNFCU0MNKeZIGUNvmUUIzOe3Ip2baV\nhQMaC2t1SHE0udGv4T0LBLE=\n-----END PRIVATE KEY-----", "publicPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAua/L4EYEI/KneQc4qdvz\nXWOqk56xeQ+VexfnEqAEUG1k8aqAKvdiCObMJykxmn5n+JtZnRU/SasIfPqA9qvX\nKJGbDzjQREE24YC84lAuYfAVPMWX/+ch4vKEPQl/eg+VzchmQOH6RuJftMTFFwrz\ny+JaChJYAb0qximKgPv94AKkBEhCyhc3cIsMugbCbiGIHh6ePGh0pvzHooYu5xp3\nFiFkUnHG1G0Nq7JKsDSSRIu8NXBsz38ssZZiu0b8RTPe/ZR7W0tuuo9yvw/Gs2i9\neKCZFnrI8IwMF2ghvmEwWbM56TSJG8zXG6Km+2s8T3PIoS2BIWYMOzMqcFt+ItyF\nqQIDAQAB\n-----END PUBLIC KEY-----", "sha256SignatureHex": "3b63c4ed2e760a6c49b11889b9b2d3b854f2ef849ddedcdba6da75838122640a79f01959cc314732fe005e7af3a1c5437a735cdbf17796dd5e2ef23ed8e29e7963ab28b22f0cc0992b7519d397ac2fd29259e3557f59c71cf6b2d334715302534ecdf6dae04aea9fca5c3e658b9be66f2b5b51c960f7d41dc2381049ecfc471e7c3119be82f8156f3655451eebb8412eeb989481f28864d6fed41a2bd1b1e8591fbd6afc2b8b46ab2ae19ab1028f380b7ebeb5d1cfe851af08764f40f295ef6ea9b9a64fde565e85dde122cd21ae8cb7100065cecb74e2168ec3404f4ff5f99ed80f0f081000c337a387d29425a33cf15cd8c41f5ebe64a0a99cc9164fde8777" diff --git a/toolchain/Cargo.lock b/toolchain/Cargo.lock index 9ca803d670..e5afb7654c 100644 --- a/toolchain/Cargo.lock +++ b/toolchain/Cargo.lock @@ -677,7 +677,7 @@ dependencies = [ name = "cmd-awk" version = "0.1.0" dependencies = [ - "secureexec-awk", + "agentos-awk", ] [[package]] @@ -770,8 +770,8 @@ dependencies = [ "codex-network-proxy", "codex-otel", "ratatui", - "secureexec-wasi-http", - "secureexec-wasi-spawn", + "agentos-wasi-http", + "agentos-wasi-spawn", ] [[package]] @@ -780,14 +780,14 @@ version = "0.1.0" dependencies = [ "codex-network-proxy", "codex-otel", - "secureexec-wasi-http", + "agentos-wasi-http", ] [[package]] name = "cmd-column" version = "0.1.0" dependencies = [ - "secureexec-column", + "agentos-column", ] [[package]] @@ -808,7 +808,7 @@ dependencies = [ name = "cmd-curl" version = "0.1.0" dependencies = [ - "secureexec-wasi-http", + "agentos-wasi-http", ] [[package]] @@ -840,7 +840,7 @@ version = "0.1.0" name = "cmd-diff" version = "0.1.0" dependencies = [ - "secureexec-diff", + "agentos-diff", ] [[package]] @@ -861,7 +861,7 @@ dependencies = [ name = "cmd-du" version = "0.1.0" dependencies = [ - "secureexec-du", + "agentos-du", ] [[package]] @@ -875,14 +875,14 @@ dependencies = [ name = "cmd-egrep" version = "0.1.0" dependencies = [ - "secureexec-shims", + "agentos-shims", ] [[package]] name = "cmd-env" version = "0.1.0" dependencies = [ - "secureexec-shims", + "agentos-shims", ] [[package]] @@ -896,7 +896,7 @@ dependencies = [ name = "cmd-expr" version = "0.1.0" dependencies = [ - "secureexec-expr", + "agentos-expr", ] [[package]] @@ -924,14 +924,14 @@ dependencies = [ name = "cmd-fgrep" version = "0.1.0" dependencies = [ - "secureexec-shims", + "agentos-shims", ] [[package]] name = "cmd-file" version = "0.1.0" dependencies = [ - "secureexec-file-cmd", + "agentos-file-cmd", ] [[package]] @@ -971,7 +971,7 @@ dependencies = [ name = "cmd-gzip" version = "0.1.0" dependencies = [ - "secureexec-gzip", + "agentos-gzip", ] [[package]] @@ -989,7 +989,7 @@ version = "0.1.0" name = "cmd-http-test" version = "0.1.0" dependencies = [ - "secureexec-wasi-http", + "agentos-wasi-http", ] [[package]] @@ -1010,7 +1010,7 @@ dependencies = [ name = "cmd-jq" version = "0.1.0" dependencies = [ - "secureexec-jq", + "agentos-jq", ] [[package]] @@ -1087,7 +1087,7 @@ dependencies = [ name = "cmd-nice" version = "0.1.0" dependencies = [ - "secureexec-shims", + "agentos-shims", ] [[package]] @@ -1101,7 +1101,7 @@ dependencies = [ name = "cmd-nohup" version = "0.1.0" dependencies = [ - "secureexec-shims", + "agentos-shims", ] [[package]] @@ -1185,7 +1185,7 @@ dependencies = [ name = "cmd-rev" version = "0.1.0" dependencies = [ - "secureexec-rev", + "agentos-rev", ] [[package]] @@ -1290,7 +1290,7 @@ dependencies = [ name = "cmd-sleep" version = "0.1.0" dependencies = [ - "secureexec-builtins", + "agentos-builtins", ] [[package]] @@ -1304,7 +1304,7 @@ dependencies = [ name = "cmd-spawn-test-host" version = "0.1.0" dependencies = [ - "secureexec-wasi-spawn", + "agentos-wasi-spawn", "tokio", ] @@ -1326,21 +1326,21 @@ dependencies = [ name = "cmd-stdbuf" version = "0.1.0" dependencies = [ - "secureexec-shims", + "agentos-shims", ] [[package]] name = "cmd-strings" version = "0.1.0" dependencies = [ - "secureexec-strings-cmd", + "agentos-strings-cmd", ] [[package]] name = "cmd-stubs" version = "0.1.0" dependencies = [ - "secureexec-stubs", + "agentos-stubs", ] [[package]] @@ -1375,7 +1375,7 @@ dependencies = [ name = "cmd-tar" version = "0.1.0" dependencies = [ - "secureexec-tar", + "agentos-tar", ] [[package]] @@ -1389,14 +1389,14 @@ dependencies = [ name = "cmd-test" version = "0.1.0" dependencies = [ - "secureexec-builtins", + "agentos-builtins", ] [[package]] name = "cmd-timeout" version = "0.1.0" dependencies = [ - "secureexec-shims", + "agentos-shims", ] [[package]] @@ -1470,14 +1470,14 @@ dependencies = [ name = "cmd-which" version = "0.1.0" dependencies = [ - "secureexec-shims", + "agentos-shims", ] [[package]] name = "cmd-whoami" version = "0.1.0" dependencies = [ - "secureexec-builtins", + "agentos-builtins", ] [[package]] @@ -1502,7 +1502,7 @@ dependencies = [ name = "cmd-yq" version = "0.1.0" dependencies = [ - "secureexec-yq", + "agentos-yq", ] [[package]] @@ -4110,14 +4110,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "secureexec-awk" +name = "agentos-awk" version = "0.1.0" dependencies = [ "awk-rs", ] [[package]] -name = "secureexec-builtins" +name = "agentos-builtins" version = "0.1.0" dependencies = [ "libc", @@ -4125,43 +4125,43 @@ dependencies = [ ] [[package]] -name = "secureexec-column" +name = "agentos-column" version = "0.1.0" [[package]] -name = "secureexec-diff" +name = "agentos-diff" version = "0.1.0" dependencies = [ "similar", ] [[package]] -name = "secureexec-du" +name = "agentos-du" version = "0.1.0" [[package]] -name = "secureexec-expr" +name = "agentos-expr" version = "0.1.0" dependencies = [ "regex", ] [[package]] -name = "secureexec-file-cmd" +name = "agentos-file-cmd" version = "0.1.0" dependencies = [ "infer", ] [[package]] -name = "secureexec-gzip" +name = "agentos-gzip" version = "0.1.0" dependencies = [ "flate2", ] [[package]] -name = "secureexec-jq" +name = "agentos-jq" version = "0.1.0" dependencies = [ "jaq-core", @@ -4171,26 +4171,26 @@ dependencies = [ ] [[package]] -name = "secureexec-rev" +name = "agentos-rev" version = "0.1.0" [[package]] -name = "secureexec-shims" +name = "agentos-shims" version = "0.1.0" dependencies = [ "wasi-ext", ] [[package]] -name = "secureexec-strings-cmd" +name = "agentos-strings-cmd" version = "0.1.0" [[package]] -name = "secureexec-stubs" +name = "agentos-stubs" version = "0.1.0" [[package]] -name = "secureexec-tar" +name = "agentos-tar" version = "0.1.0" dependencies = [ "flate2", @@ -4198,22 +4198,22 @@ dependencies = [ ] [[package]] -name = "secureexec-wasi-http" +name = "agentos-wasi-http" version = "0.1.0" dependencies = [ "wasi-ext", ] [[package]] -name = "secureexec-wasi-pty" +name = "agentos-wasi-pty" version = "0.1.0" dependencies = [ - "secureexec-wasi-spawn", + "agentos-wasi-spawn", "wasi-ext", ] [[package]] -name = "secureexec-wasi-spawn" +name = "agentos-wasi-spawn" version = "0.1.0" dependencies = [ "wasi", @@ -4221,7 +4221,7 @@ dependencies = [ ] [[package]] -name = "secureexec-yq" +name = "agentos-yq" version = "0.1.0" dependencies = [ "jaq-core", diff --git a/toolchain/c/scripts/build-curl-upstream.sh b/toolchain/c/scripts/build-curl-upstream.sh index 8d11dccca3..27fb34432f 100644 --- a/toolchain/c/scripts/build-curl-upstream.sh +++ b/toolchain/c/scripts/build-curl-upstream.sh @@ -115,7 +115,7 @@ if [[ ! -d "$SRC_DIR" ]]; then exit 1 fi -echo "Applying secure-exec overlay..." +echo "Applying agentos overlay..." while IFS= read -r -d '' file; do rel="${file#$OVERLAY_DIR/}" mkdir -p "$SRC_DIR/$(dirname "$rel")" diff --git a/toolchain/c/scripts/build-wget-upstream.sh b/toolchain/c/scripts/build-wget-upstream.sh index edbd025d9f..1f57119f22 100644 --- a/toolchain/c/scripts/build-wget-upstream.sh +++ b/toolchain/c/scripts/build-wget-upstream.sh @@ -144,8 +144,8 @@ ZLIB_CFLAGS="-I$ZLIB_INCLUDE" \ ZLIB_LIBS="-L$ZLIB_LIBDIR -lz" \ CPPFLAGS="-I$OVERLAY_INCLUDE_DIR -I$MBEDTLS_INCLUDE" \ gl_cv_func_posix_spawn_works=yes \ -gl_cv_func_posix_spawn_secure_exec=yes \ -gl_cv_func_posix_spawnp_secure_exec=yes \ +gl_cv_func_posix_spawn_agentos=yes \ +gl_cv_func_posix_spawnp_agentos=yes \ ac_cv_func_posix_spawn_file_actions_addchdir=yes \ gl_cv_func_posix_spawn_file_actions_addclose_works=yes \ gl_cv_func_posix_spawn_file_actions_adddup2_works=yes \ diff --git a/toolchain/crates/commands/_stubs/Cargo.toml b/toolchain/crates/commands/_stubs/Cargo.toml index 36c2fee922..acf032197b 100644 --- a/toolchain/crates/commands/_stubs/Cargo.toml +++ b/toolchain/crates/commands/_stubs/Cargo.toml @@ -3,11 +3,11 @@ name = "cmd-stubs" version.workspace = true edition.workspace = true license.workspace = true -description = "_stubs mini-multicall binary for unsupported commands in secure-exec VM" +description = "_stubs mini-multicall binary for unsupported commands in agentos VM" [[bin]] name = "_stubs" path = "src/main.rs" [dependencies] -secureexec-stubs = { path = "../../libs/stubs" } +agentos-stubs = { path = "../../libs/stubs" } diff --git a/toolchain/crates/commands/_stubs/src/main.rs b/toolchain/crates/commands/_stubs/src/main.rs index c4367e5076..0424f00086 100644 --- a/toolchain/crates/commands/_stubs/src/main.rs +++ b/toolchain/crates/commands/_stubs/src/main.rs @@ -1,4 +1,4 @@ fn main() { let args: Vec = std::env::args().collect(); - std::process::exit(secureexec_stubs::run(&args)); + std::process::exit(agentos_stubs::run(&args)); } diff --git a/toolchain/crates/commands/http-test/Cargo.toml b/toolchain/crates/commands/http-test/Cargo.toml index f6aae5bde7..0254ad44eb 100644 --- a/toolchain/crates/commands/http-test/Cargo.toml +++ b/toolchain/crates/commands/http-test/Cargo.toml @@ -16,4 +16,4 @@ test = false required-features = ["bin"] [dependencies] -wasi-http = { package = "secureexec-wasi-http", path = "../../libs/wasi-http" } +wasi-http = { package = "agentos-wasi-http", path = "../../libs/wasi-http" } diff --git a/toolchain/crates/commands/spawn-test-host/Cargo.toml b/toolchain/crates/commands/spawn-test-host/Cargo.toml index 580e54c109..dea03a860a 100644 --- a/toolchain/crates/commands/spawn-test-host/Cargo.toml +++ b/toolchain/crates/commands/spawn-test-host/Cargo.toml @@ -10,5 +10,5 @@ name = "spawn-test-host" path = "src/main.rs" [dependencies] -wasi-spawn = { package = "secureexec-wasi-spawn", path = "../../libs/wasi-spawn" } +wasi-spawn = { package = "agentos-wasi-spawn", path = "../../libs/wasi-spawn" } tokio = { version = "1.50.0", features = ["process", "rt"] } diff --git a/toolchain/crates/commands/xu/Cargo.toml b/toolchain/crates/commands/xu/Cargo.toml index 4ed41c9f30..95bc554c3f 100644 --- a/toolchain/crates/commands/xu/Cargo.toml +++ b/toolchain/crates/commands/xu/Cargo.toml @@ -3,7 +3,7 @@ name = "cmd-xu" version.workspace = true edition.workspace = true license.workspace = true -description = "xu standalone binary for secure-exec VM tests" +description = "xu standalone binary for agentos VM tests" [[bin]] name = "xu" diff --git a/toolchain/crates/libs/builtins/Cargo.toml b/toolchain/crates/libs/builtins/Cargo.toml index daac258bf5..6eac724435 100644 --- a/toolchain/crates/libs/builtins/Cargo.toml +++ b/toolchain/crates/libs/builtins/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "secureexec-builtins" +name = "agentos-builtins" version.workspace = true edition.workspace = true license.workspace = true -description = "Built-in command implementations (sleep, test/[, whoami) for secure-exec VM" +description = "Built-in command implementations (sleep, test/[, whoami) for agentos VM" [dependencies] libc = "0.2" diff --git a/toolchain/crates/libs/builtins/src/lib.rs b/toolchain/crates/libs/builtins/src/lib.rs index dee2b00af5..7b1067f782 100644 --- a/toolchain/crates/libs/builtins/src/lib.rs +++ b/toolchain/crates/libs/builtins/src/lib.rs @@ -637,7 +637,7 @@ mod tests { .expect("system time") .as_nanos(); let root = std::env::temp_dir().join(format!( - "secureexec-builtins-test-{}-{}", + "agentos-builtins-test-{}-{}", std::process::id(), unique )); diff --git a/toolchain/crates/libs/shims/Cargo.toml b/toolchain/crates/libs/shims/Cargo.toml index 0d4b05ce1f..a3c7993bad 100644 --- a/toolchain/crates/libs/shims/Cargo.toml +++ b/toolchain/crates/libs/shims/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "secureexec-shims" +name = "agentos-shims" version.workspace = true edition.workspace = true license.workspace = true diff --git a/toolchain/crates/libs/shims/src/which.rs b/toolchain/crates/libs/shims/src/which.rs index c128714637..7fde0037c7 100644 --- a/toolchain/crates/libs/shims/src/which.rs +++ b/toolchain/crates/libs/shims/src/which.rs @@ -1,4 +1,4 @@ -//! Minimal `which` implementation for the secure-exec VM. +//! Minimal `which` implementation for the agentos VM. //! //! Searches the current PATH for one or more command names and prints the first //! matching executable path for each command. This is primarily needed for diff --git a/toolchain/crates/libs/stubs/Cargo.toml b/toolchain/crates/libs/stubs/Cargo.toml index ca054d68ee..a19de8c5d9 100644 --- a/toolchain/crates/libs/stubs/Cargo.toml +++ b/toolchain/crates/libs/stubs/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "secureexec-stubs" +name = "agentos-stubs" version.workspace = true edition.workspace = true license.workspace = true diff --git a/toolchain/crates/libs/wasi-http/Cargo.toml b/toolchain/crates/libs/wasi-http/Cargo.toml index af90f82ce7..775cdef89b 100644 --- a/toolchain/crates/libs/wasi-http/Cargo.toml +++ b/toolchain/crates/libs/wasi-http/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "secureexec-wasi-http" +name = "agentos-wasi-http" version.workspace = true edition.workspace = true license.workspace = true diff --git a/toolchain/crates/libs/wasi-pty/Cargo.toml b/toolchain/crates/libs/wasi-pty/Cargo.toml index 06ccd7e586..7eb5446a6c 100644 --- a/toolchain/crates/libs/wasi-pty/Cargo.toml +++ b/toolchain/crates/libs/wasi-pty/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "secureexec-wasi-pty" +name = "agentos-wasi-pty" version.workspace = true edition.workspace = true license.workspace = true @@ -7,4 +7,4 @@ description = "WASI PTY-based process management via host_process FFI for intera [dependencies] wasi-ext = { path = "../../wasi-ext" } -wasi-spawn = { package = "secureexec-wasi-spawn", path = "../wasi-spawn" } +wasi-spawn = { package = "agentos-wasi-spawn", path = "../wasi-spawn" } diff --git a/toolchain/crates/libs/wasi-spawn/Cargo.toml b/toolchain/crates/libs/wasi-spawn/Cargo.toml index bc2ec7ebf8..a412e3b15c 100644 --- a/toolchain/crates/libs/wasi-spawn/Cargo.toml +++ b/toolchain/crates/libs/wasi-spawn/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "secureexec-wasi-spawn" +name = "agentos-wasi-spawn" version.workspace = true edition.workspace = true license.workspace = true diff --git a/toolchain/std-patches/0009-wasi-split-paths.patch b/toolchain/std-patches/0009-wasi-split-paths.patch index 2ff1aefe10..aae6141601 100644 --- a/toolchain/std-patches/0009-wasi-split-paths.patch +++ b/toolchain/std-patches/0009-wasi-split-paths.patch @@ -13,7 +13,7 @@ -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") +pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { -+ // wasm32-wasip1 uses ':'-separated PATH-like lists, like Unix. (secure-exec ++ // wasm32-wasip1 uses ':'-separated PATH-like lists, like Unix. (agentos + // pipeline-only codex port — codex parses PATH via env::split_paths.) + use crate::os::wasi::ffi::OsStrExt; + let bytes = unparsed.as_bytes(); diff --git a/toolchain/std-patches/codex-source/README.md b/toolchain/std-patches/codex-source/README.md index e7ba9c70ea..d6e568d7ab 100644 --- a/toolchain/std-patches/codex-source/README.md +++ b/toolchain/std-patches/codex-source/README.md @@ -3,7 +3,7 @@ These are minimal, upstreamable additions to codex's own source where it has a hard `compile_error!`/missing-platform arm that NO toolchain patch can bypass (first-party compile-time gates). Each adds REAL wasi support (wasi has the API), -not a hack. Applied to the vendored codex source during the secure-exec build. +not a hack. Applied to the vendored codex source during the agentos build. 1. utils/git/src/platform.rs — add `#[cfg(target_os = "wasi")] create_symlink` using `std::os::wasi::fs::symlink_path`, and widen the fallback @@ -28,7 +28,7 @@ NOT gate the SOURCE usage — an incomplete author wasi port. Breakdown: build_config_state, host_and_port_from_network_addr, normalize_host, validate_policy_against_constraints, NetworkProxyConstraints/Error, NetworkProtocol, NetworkProxyState, NetworkProxyAuditMetadata, NetworkPolicyRequest, …). The real crate - can't compile on wasi (rama proxy stack); EXPAND the secure-exec codex-network-proxy + can't compile on wasi (rama proxy stack); EXPAND the agentos codex-network-proxy stub to this full API (no-op/inert — the VM kernel brokers network policy host-side). - ~6: codex_otel SessionTelemetry methods the stub lacks → expand codex-otel stub. - tokio::signal (no signals on wasi) → gate/stub codex-core's signal usage. @@ -87,7 +87,7 @@ git symlink, rmcp-client resolver. Plus std ExitStatusExt patch (std-patches/ 0008-wasi-exit-status-ext.md). `cargo build -p codex-core -p codex-exec --target wasm32-wasip1 -Z build-std` → Finished, EXIT 0. -REMAINING to e2e: (1) the secure-exec command crate crates/commands/codex-exec +REMAINING to e2e: (1) the agentos command crate crates/commands/codex-exec un-stub --session-turn to delegate to the real codex-core/codex-exec engine and emit the EE newline-JSON protocol (start/text_delta/tool_call_update/permission_request/ done) — the real functional integration; (2) build via `make -C toolchain wasm` @@ -98,7 +98,7 @@ agent-os matrix + un-skip the codex session test. codex-exec/src/lib.rs `wasi_stub_main()` is a placeholder ("WASI runtime support is under development"). codex-core compiles now, so replace it with the real engine (mirror lib_native.rs::run_exec_session, ~200-300 lines, in codex's workspace so it has -codex-core access). The built codex-exec.wasm IS the secure-exec `codex-exec` command. +codex-core access). The built codex-exec.wasm IS the agentos `codex-exec` command. PROTOCOL (newline-JSON, the EE adapter @rivet-ee/agent-os-codex-agent drives it): - stdin: first line {type:"start", cwd, mode, model, thought_level, @@ -146,7 +146,7 @@ agent and emits the EE protocol. `cargo build -p codex-exec --target wasm32-wasi 1. Produce optimized wasm artifacts from the fork (branch wasi-port-codex-core): `cargo build -p codex-exec -p codex --release --target wasm32-wasip1 -Z build-std` (+ wasm-opt) → copy to software/codex/wasm/{codex-exec,codex}. NOTE: the - secure-exec `make wasm` currently builds the STUB crates/commands/{codex,codex-exec}; + agentos `make wasm` currently builds the STUB crates/commands/{codex,codex-exec}; to ship the real engine, either build from the fork directly (above) or vendor the fork into toolchain and point cmd-codex-exec at the real codex-exec. 2. ACP adapter: the codex ACP bridge (spawns `codex-exec --session-turn`, newline-JSON↔ACP) @@ -164,7 +164,7 @@ Built the real codex-exec from the fork (release, wasm-opt'd to 28MB) and placed software/codex/wasm/{codex-exec,codex}. Smoke test (vm.exec("... | codex-exec --session-turn")) shows it SPAWNS and attempts WebAssembly instantiation in the VM — 44 imports, of which 43 (wasi_snapshot_preview1×30, host_net×6, host_process×5, -host_fs×2) are provided by the secure-exec runtime. The ONLY unprovided one was +host_fs×2) are provided by the agentos runtime. The ONLY unprovided one was `env.sqlite3_load_extension` (sqlx's sqlite). Fixed by defining a #[no_mangle] no-op stub in the engine (fork commit). Rebuild + re-place → instantiation should succeed. Then the smoke test ({"type":"start"} before the model call) and the full EE @@ -174,7 +174,7 @@ codex-session.test.ts (with the responses mock) verify the e2e turn. Smoke test (packages/core/tests/codex-smoke.test.ts) PASSES: vm.exec("printf '' | codex-exec --session-turn") → stdout: {"type":"start"} The real codex agent (codex-rs → wasip1, session-turn engine driving codex-core) BOOTS -in the secure-exec VM, instantiates all 44 imports (after adding host +in the agentos VM, instantiates all 44 imports (after adding host path_filestat_set_times), runs the engine, and emits the EE protocol's start event. (exit 1 only because the smoke test provides no model mock/auth, so the turn errors AFTER start — proving the boot + protocol path works.) @@ -187,7 +187,7 @@ complete agent turn. The boot+protocol path is now VERIFIED end-to-end in the VM DBG markers (engine) confirm the real codex agent runs the entire lifecycle in the VM: load config → AuthManager::shared → ThreadManager::new → start_thread → submit Op::UserInput → LIVE next_event loop (received a Warning event, processing). 8 runtime -blockers fixed and committed (host imports, secure-exec host wasi shim +blockers fixed and committed (host imports, agentos host wasi shim path_filestat_set_times, tokio fs-asyncify + spawn_blocking inline on wasi, std split_paths, now_local→UTC). FINAL GAP: the model HTTP POST to the OpenAI Responses mock does not reach it (mock requests=0, then hang). codex honors OPENAI_BASE_URL @@ -209,7 +209,7 @@ single-threaded (no OS threads); the spawn_blocking-as-current-thread-task worka task that can't run. This is an architectural mismatch (codex's threading model vs single-thread wasi), the genuinely hard core of running codex on wasi. Resolving it needs codex-internal tracing to find the exact blocking construct and make it cooperative, or a -different runtime strategy. (Sidecar instrumentation reverted; secure-exec is clean.) +different runtime strategy. (Sidecar instrumentation reverted; agentos is clean.) STATUS: codex compiles + runs the full session lifecycle in the VM (boot → EE protocol → config → auth → ThreadManager → start_thread → submit → live event loop) but hangs in the agent loop before the model call on the single-threaded runtime. @@ -259,7 +259,7 @@ Because `-Z build-std` injects `panic_unwind` via `--extern` while the wasm targ bin's `-Cpanic=abort` resolves a `panic_abort` that is ABI-matched to build-std's core), - builds with `--config 'profile.release.panic="abort"'`. See `/tmp/relink-codex.sh` for the exact invocation. (This sysroot massaging should be folded -into the secure-exec wasm toolchain so it is not a manual step.) +into the agentos wasm toolchain so it is not a manual step.) KNOWN REMAINING (non-blocking; turn works e2e): - Rollout recorder logs `failed to queue rollout items: channel closed` (the writer task exits diff --git a/toolchain/std-patches/codex-source/build-codex-wasip1.sh b/toolchain/std-patches/codex-source/build-codex-wasip1.sh index 3bc9ce0144..a432314194 100755 --- a/toolchain/std-patches/codex-source/build-codex-wasip1.sh +++ b/toolchain/std-patches/codex-source/build-codex-wasip1.sh @@ -4,13 +4,13 @@ # Captures every fix discovered while driving `cargo build -p codex-core # --target wasm32-wasip1` to its current frontier. Run from the codex-rs checkout. # This is the DIAGNOSTIC harness (builds codex IN its own workspace to find the -# frontier). The SHIPPING build vendors codex into secure-exec and swaps the same +# frontier). The SHIPPING build vendors codex into agentos and swaps the same # crates via [patch.crates-io]; the fixes are identical. # -# Usage: CODEX=/path/to/codex-rs SECEXEC=/path/to/secure-exec ./build-codex-wasip1.sh +# Usage: CODEX=/path/to/codex-rs SECEXEC=/path/to/agentos ./build-codex-wasip1.sh set -uo pipefail CODEX="${CODEX:-/home/nathan/agent-e2e/codex-rs/codex-rs}" -SECEXEC="${SECEXEC:-/home/nathan/agent-e2e/secure-exec}" +SECEXEC="${SECEXEC:-/home/nathan/agent-e2e/agentos}" STUBS="$SECEXEC/toolchain/stubs" WSDK="$SECEXEC/toolchain/c/vendor/wasi-sdk" TOOLCHAIN="nightly-2026-03-01" diff --git a/toolchain/std-patches/codex/0005-wasi-build-sysroot-cleanup.patch b/toolchain/std-patches/codex/0005-wasi-build-sysroot-cleanup.patch index 35e2150f3e..fae5387dbe 100644 --- a/toolchain/std-patches/codex/0005-wasi-build-sysroot-cleanup.patch +++ b/toolchain/std-patches/codex/0005-wasi-build-sysroot-cleanup.patch @@ -1,6 +1,6 @@ --- a/scripts/build-wasi-codex-exec.sh +++ b/scripts/build-wasi-codex-exec.sh -@@ -33,6 +33,7 @@ INSTALL="${INSTALL:-${SECURE_EXEC_DIR:+1}}" +@@ -34,5 +34,6 @@ SYSROOT="$(rustc "+$TOOLCHAIN" --print sysroot)" LIBDIR="$SYSROOT/lib/rustlib/wasm32-wasip1/lib" STASH="$LIBDIR/.prebuilt-stash" diff --git a/toolchain/std-patches/crates/rustls-native-certs/0001-wasi-empty-certs.patch b/toolchain/std-patches/crates/rustls-native-certs/0001-wasi-empty-certs.patch index 4bf12668bd..388b164735 100644 --- a/toolchain/std-patches/crates/rustls-native-certs/0001-wasi-empty-certs.patch +++ b/toolchain/std-patches/crates/rustls-native-certs/0001-wasi-empty-certs.patch @@ -2,7 +2,7 @@ # for `load_native_certs()` and has NO wasm/wasi arm -> on wasm32-wasip1 the # `platform` module is undefined and the crate fails to compile (unresolved import # in the top-level `load_native_certs`). wasm32-wasip1 has no native OS cert store; -# TLS is brokered host-side by the secure-exec VM (host CAs), so the in-guest rustls +# TLS is brokered host-side by the agentos VM (host CAs), so the in-guest rustls # never validates certificates. Add a `target_os = "wasi"` platform arm that returns # an empty CertificateResult so the crate compiles (compile/link-only for codex; the # guest never performs cert validation). Pipeline-only codex WASI port. @@ -13,7 +13,7 @@ use macos as platform; +// wasm32-wasip1: no native OS cert store. TLS is brokered host-side by the -+// secure-exec VM (host CAs), so the in-guest rustls never validates certificates. ++// agentos VM (host CAs), so the in-guest rustls never validates certificates. +// Provide an empty native-cert loader so the crate compiles. +#[cfg(target_os = "wasi")] +mod platform { diff --git a/toolchain/std-patches/crates/tokio/VERIFIED-tokio-process-wasi.md b/toolchain/std-patches/crates/tokio/VERIFIED-tokio-process-wasi.md index cdea85d0df..b9f5cc0314 100644 --- a/toolchain/std-patches/crates/tokio/VERIFIED-tokio-process-wasi.md +++ b/toolchain/std-patches/crates/tokio/VERIFIED-tokio-process-wasi.md @@ -4,7 +4,7 @@ Proven in isolation (/tmp/tokio-dev + [patch], --cfg tokio_unstable, -Z build-st `Command::new("echo").arg("hi").output().await` COMPILES for wasm32-wasip1. This de-risks codex's entire exec path under the pipeline-only approach. -## The exact changes (to capture as secure-exec patches): +## The exact changes (to capture as agentos patches): ### A. tokio crate patch (std-patches/crates/tokio/): 1. src/macros/cfg.rs — in `macro_rules! cfg_process`, remove `#[cfg(not(target_os = "wasi"))]`. diff --git a/toolchain/std-patches/crates/tokio/std-wasi-childpipe-fd.rs b/toolchain/std-patches/crates/tokio/std-wasi-childpipe-fd.rs index c778628f54..1f841acd16 100644 --- a/toolchain/std-patches/crates/tokio/std-wasi-childpipe-fd.rs +++ b/toolchain/std-patches/crates/tokio/std-wasi-childpipe-fd.rs @@ -1,6 +1,6 @@ //! std patch artifact (pipeline-only codex port) — wasi public child-pipe fd traits. //! -//! PROBLEM (real secure-exec bug, found 2026-06-23): the patched wasi std provides +//! PROBLEM (real agentos bug, found 2026-06-23): the patched wasi std provides //! the SEOS process impl (`sys/process/wasi.rs`, `ChildPipe(FileDesc)`) but NOT the //! public `process::{ChildStdin,ChildStdout,ChildStderr}` fd traits — `os/unix/process.rs` //! has them (AsRawFd/IntoRawFd/AsFd/From<_> for OwnedFd) but there is no `os/wasi` diff --git a/toolchain/std-patches/std/os/wasi/process.rs b/toolchain/std-patches/std/os/wasi/process.rs index 5b506abe48..9d5c4ff6a7 100644 --- a/toolchain/std-patches/std/os/wasi/process.rs +++ b/toolchain/std-patches/std/os/wasi/process.rs @@ -2,7 +2,7 @@ //! //! Mirrors `os/unix/process.rs`' child-pipe fd traits for wasm32-wasip1 so that //! `tokio::process` (and other fd-extracting code) can reach the parent-side -//! pipe ends of a spawned child. (secure-exec pipeline-only codex port.) +//! pipe ends of a spawned child. (agentos pipeline-only codex port.) //! //! [`std::process`]: crate::process @@ -84,7 +84,7 @@ impl_child_pipe_fd!(process::ChildStdout); impl_child_pipe_fd!(process::ChildStderr); /// WASI-specific extension to construct an [`ExitStatus`] from a raw code, -/// mirroring `std::os::unix::process::ExitStatusExt::from_raw`. (secure-exec +/// mirroring `std::os::unix::process::ExitStatusExt::from_raw`. (agentos /// pipeline-only codex port — codex's synthetic exit statuses need this.) #[stable(feature = "rust1", since = "1.0.0")] pub trait ExitStatusExt { diff --git a/toolchain/std-patches/wasi-libc/0008-sockets.patch b/toolchain/std-patches/wasi-libc/0008-sockets.patch index 8c2e33fb0a..c43aaaefc6 100644 --- a/toolchain/std-patches/wasi-libc/0008-sockets.patch +++ b/toolchain/std-patches/wasi-libc/0008-sockets.patch @@ -28,7 +28,7 @@ Import signatures match wasmvm/crates/wasi-ext/src/lib.rs exactly. - $TARGET_TRIPLE == *"wasip1" || $TARGET_TRIPLE == *"wasip1-threads" ]]; then - MUSL_OMIT_HEADERS+=("netdb.h") -fi -+# NOTE: commented out by the secure-exec 0008-sockets patch — we provide getaddrinfo via host_net ++# NOTE: commented out by the agentos 0008-sockets patch — we provide getaddrinfo via host_net +#if [[ $TARGET_TRIPLE == *"wasi" || $TARGET_TRIPLE == *"wasi-threads" || \ +# $TARGET_TRIPLE == *"wasip1" || $TARGET_TRIPLE == *"wasip1-threads" ]]; then +# MUSL_OMIT_HEADERS+=("netdb.h") diff --git a/toolchain/std-patches/wasi-libc/0013-posix-socket-header-surface.patch b/toolchain/std-patches/wasi-libc/0013-posix-socket-header-surface.patch index 4d5b655f8c..fe3de40a29 100644 --- a/toolchain/std-patches/wasi-libc/0013-posix-socket-header-surface.patch +++ b/toolchain/std-patches/wasi-libc/0013-posix-socket-header-surface.patch @@ -1,5 +1,5 @@ Expose the socket option and poll constants needed by POSIX networking -applications when secure-exec routes sockets through host_net on WASI p1. +applications when agentos routes sockets through host_net on WASI p1. This keeps the WASI-native AF_/SOCK_ values, but publishes the common socket-level constants and non-conflicting extra poll bits that upstream @@ -34,7 +34,7 @@ software such as curl expects to find in and . #endif // __wasilibc_use_wasip2 +/* -+ * secure-exec exposes a POSIX-style socket layer over host_net for WASI p1. ++ * agentos exposes a POSIX-style socket layer over host_net for WASI p1. + * Keep the WASI-native domain/type values below, but expose the common + * socket option and message flag constants that networking applications + * expect to find in . diff --git a/toolchain/std-patches/wasi-libc/0029-openssh-compat-header-surface.patch b/toolchain/std-patches/wasi-libc/0029-openssh-compat-header-surface.patch index 8d576f0037..053de1379d 100644 --- a/toolchain/std-patches/wasi-libc/0029-openssh-compat-header-surface.patch +++ b/toolchain/std-patches/wasi-libc/0029-openssh-compat-header-surface.patch @@ -179,5 +179,5 @@ index 8813360..9a740ad 100755 +# sshbuf-misc.c) include unconditionally. No resolver code is +# built; linking res_* still fails, which is the honest surface. # Exclude `netdb.h` from all of the p1 targets. - # NOTE: commented out by the secure-exec 0008-sockets patch — we provide getaddrinfo via host_net + # NOTE: commented out by the agentos 0008-sockets patch — we provide getaddrinfo via host_net #if [[ $TARGET_TRIPLE == *"wasi" || $TARGET_TRIPLE == *"wasi-threads" || \ diff --git a/toolchain/stubs/portable-pty-wasi/src/wasi.rs b/toolchain/stubs/portable-pty-wasi/src/wasi.rs index f6c5f07987..f44cf80651 100644 --- a/toolchain/stubs/portable-pty-wasi/src/wasi.rs +++ b/toolchain/stubs/portable-pty-wasi/src/wasi.rs @@ -1,6 +1,6 @@ //! wasm32-wasip1 backend stub for portable-pty. //! -//! The secure-exec VM brokers process execution via wasi-spawn/wasi-pty; a full +//! The agentos VM brokers process execution via wasi-spawn/wasi-pty; a full //! PTY bridge is future work. This backend lets portable-pty (and thus //! codex-utils-pty / codex-core) COMPILE for wasip1. PTY operations return an //! Unsupported error at runtime (codex's exec falls back to non-PTY execution). diff --git a/toolchain/stubs/reqwest-shim/Cargo.toml b/toolchain/stubs/reqwest-shim/Cargo.toml index f597af2fe8..f9d7879ab9 100644 --- a/toolchain/stubs/reqwest-shim/Cargo.toml +++ b/toolchain/stubs/reqwest-shim/Cargo.toml @@ -1,4 +1,4 @@ -# reqwest-shim: a wasm32-wasip1 drop-in for `reqwest` 0.12, backed by secure-exec +# reqwest-shim: a wasm32-wasip1 drop-in for `reqwest` 0.12, backed by agentos # `wasi-http` (host_net TCP/TLS). Wired in via `[patch.crates-io] reqwest = { path }` # ONLY once it compiles against codex-exec's whole subtree — patching it in early # would break every command's `make wasm` build. @@ -19,7 +19,7 @@ name = "reqwest" path = "src/lib.rs" [dependencies] -wasi-http = { package = "secureexec-wasi-http", path = "../../crates/libs/wasi-http" } +wasi-http = { package = "agentos-wasi-http", path = "../../crates/libs/wasi-http" } http = "1" bytes = "1" serde = "1" diff --git a/toolchain/stubs/reqwest-shim/src/lib.rs b/toolchain/stubs/reqwest-shim/src/lib.rs index aee774f00a..06fdaf0f45 100644 --- a/toolchain/stubs/reqwest-shim/src/lib.rs +++ b/toolchain/stubs/reqwest-shim/src/lib.rs @@ -1,4 +1,4 @@ -//! `reqwest` 0.12 API shim for wasm32-wasip1, backed by secure-exec `wasi-http` +//! `reqwest` 0.12 API shim for wasm32-wasip1, backed by agentos `wasi-http` //! (host_net TCP/TLS). Drop-in target for `[patch.crates-io] reqwest`. //! //! STATUS: scaffold. The buffered request/response path is implemented against diff --git a/toolchain/test-programs/sqlite3_mem.c b/toolchain/test-programs/sqlite3_mem.c index 9d7eef32f7..ce60717205 100644 --- a/toolchain/test-programs/sqlite3_mem.c +++ b/toolchain/test-programs/sqlite3_mem.c @@ -103,7 +103,7 @@ static sqlite3_vfs memVfs __attribute__((used)) = { sizeof(MemFile), 512, 0, - "secure-exec-mem", + "agentos-mem", 0, memOpen, memDelete, diff --git a/website/docs.config.mjs b/website/docs.config.mjs index a382cbe3dc..7ffef5ed39 100644 --- a/website/docs.config.mjs +++ b/website/docs.config.mjs @@ -20,7 +20,6 @@ import { faMessages, faCheck, faKey, - faCloud, faDownload, faFloppyDisk, faTerminal, @@ -29,7 +28,6 @@ import { faHardDrive, faNodeJs, faGauge, - faLink, faTowerBroadcast, faArrowsLeftRight, faDiagramNext, @@ -45,17 +43,15 @@ export const siteConfig = { repo: "rivet-dev/agentos", editPath: "website/", - // Keep in sync with the marketing nav (src/components/Navigation.tsx): - // same links in the same order across docs + marketing. + // Cookbooks lives in the docs tab strip below, so do not duplicate it here. topNav: [ { label: "Documentation", href: "/docs", match: "/docs" }, - { label: "Cookbooks", href: "/cookbooks", match: "/cookbooks" }, { label: "Use Cases", href: "/use-cases" }, { label: "Registry", href: "/registry" }, { label: "Deploy", href: "/docs/deployment", match: "/docs/deployment" }, ], tabs: [ - { label: "Documentation", href: "/docs", match: "/docs" }, + { label: "General", href: "/docs", match: "/docs" }, { label: "Cookbooks", href: "/cookbooks", match: "/cookbooks" }, ], social: { discord: "https://rivet.dev/discord" }, @@ -76,7 +72,6 @@ export const siteConfig = { title: "Documentation", href: "/docs", sidebar: [ - { title: "Introduction", href: "/docs", icon: faCircleInfo }, { title: "General", pages: [ @@ -102,8 +97,25 @@ export const siteConfig = { }, { title: "Sessions & Transcripts", href: "/docs/sessions", icon: faMessages }, { title: "Approvals", href: "/docs/approvals", icon: faCheck }, - { title: "LLM Credentials", href: "/docs/llm-credentials", icon: faKey }, - { title: "LLM Gateway", href: "/docs/llm-gateway", badge: "Coming Soon", icon: faCloud }, + { title: "Models & Credentials", href: "/docs/models-and-credentials", icon: faKey }, + ], + }, + { + title: "Execution", + pages: [ + { title: "Bash", href: "/docs/execution/bash", icon: faTerminal }, + { title: "JavaScript", href: "/docs/execution/javascript", icon: faNodeJs }, + { title: "Python", href: "/docs/execution/python", icon: faTerminal }, + ], + }, + { + title: "Orchestration", + pages: [ + { title: "Authentication", href: "/docs/authentication", icon: faKey }, + { title: "Multiplayer", href: "/docs/multiplayer", icon: faTowerBroadcast }, + { title: "Workflows & Graphs", href: "/docs/workflows", icon: faDiagramNext }, + { title: "Crons & Loops", href: "/docs/cron", icon: faClock }, + { title: "Agent-to-Agent", href: "/docs/agent-to-agent", icon: faArrowsLeftRight }, ], }, { @@ -111,25 +123,18 @@ export const siteConfig = { pages: [ { title: "Software", href: "/docs/software", icon: faDownload }, { title: "Filesystem", href: "/docs/filesystem", icon: faFloppyDisk }, - { title: "Bindings", href: "/docs/bindings", icon: faWrench }, - { title: "Processes & Shell", href: "/docs/processes", icon: faTerminal }, + { title: "Processes & Shells", href: "/docs/processes", icon: faTerminal }, { title: "Networking & Previews", href: "/docs/networking", icon: faGlobe }, - { title: "Cron Jobs", href: "/docs/cron", icon: faClock }, - { title: "Browser", href: "/docs/browser", badge: "Beta", icon: faWindowMaximize }, - { title: "Sandbox Mounting", href: "/docs/sandbox", badge: "Beta", icon: faHardDrive }, - { title: "JavaScript Runtime", href: "/docs/js-runtime", icon: faNodeJs }, { title: "Permissions", href: "/docs/permissions", icon: faKey }, { title: "Resource Limits", href: "/docs/resource-limits", icon: faGauge }, ], }, { - title: "Orchestration", + title: "Extensions", pages: [ - { title: "Authentication", href: "/docs/authentication", icon: faKey }, - { title: "Webhooks", href: "/docs/webhooks", icon: faLink }, - { title: "Multiplayer & Realtime", href: "/docs/multiplayer", icon: faTowerBroadcast }, - { title: "Agent-to-Agent", href: "/docs/agent-to-agent", icon: faArrowsLeftRight }, - { title: "Workflows", href: "/docs/workflows", icon: faDiagramNext }, + { title: "Custom Bindings", href: "/docs/extensions/custom-bindings", icon: faWrench }, + { title: "Browser Automation", href: "/docs/extensions/browser", badge: "Beta", icon: faWindowMaximize }, + { title: "External Sandboxes", href: "/docs/extensions/sandboxes", badge: "Beta", icon: faHardDrive }, ], }, { @@ -179,10 +184,9 @@ export const siteConfig = { title: "More", collapsible: true, pages: [ - { title: "Core SDK", href: "/docs/core" }, + { title: "Direct VM SDK", href: "/docs/core" }, { title: "Debugging", href: "/docs/debugging" }, - { title: "Benchmarks", href: "/docs/benchmarks" }, - { title: "Cost Evaluation", href: "/docs/cost-evaluation" }, + { title: "Performance", href: "/docs/performance" }, ], }, ], @@ -211,6 +215,15 @@ export const siteConfig = { { title: "Agent to Agent", href: "/cookbooks/agent-to-agent" }, ], }, + { + title: "Code Execution", + pages: [ + { title: "AI Agent Code Exec", href: "/cookbooks/js-ai-agent-code-exec" }, + { title: "Code Mode", href: "/cookbooks/js-code-mode" }, + { title: "Dev Servers", href: "/cookbooks/js-dev-servers" }, + { title: "Plugin Systems", href: "/cookbooks/js-plugin-systems" }, + ], + }, { title: "Filesystem", pages: [{ title: "Filesystem", href: "/cookbooks/filesystem" }], @@ -243,7 +256,6 @@ export const siteConfig = { pages: [ { title: "Cron", href: "/cookbooks/cron" }, { title: "Workflows", href: "/cookbooks/workflows" }, - { title: "Webhooks", href: "/cookbooks/webhooks" }, ], }, { diff --git a/website/public/docs/docs/agent-to-agent.md b/website/public/docs/docs/agent-to-agent.md index 5557b173d0..e3a9a0b1a9 100644 --- a/website/public/docs/docs/agent-to-agent.md +++ b/website/public/docs/docs/agent-to-agent.md @@ -2,7 +2,7 @@ Use bindings to let agents communicate with each other. -Agents communicate through [bindings](/docs/bindings). You define a bindings group that lets one agent send work to another, and the agent calls it like any other CLI command. +Agents communicate through [custom bindings](/docs/extensions/custom-bindings). You define a bindings group that lets one agent send work to another, and the agent calls it like any other CLI command. ## Example: code writer + reviewer diff --git a/website/public/docs/docs/agents/claude.md b/website/public/docs/docs/agents/claude.md index f9b7d27c95..7a9a65863c 100644 --- a/website/public/docs/docs/agents/claude.md +++ b/website/public/docs/docs/agents/claude.md @@ -6,7 +6,7 @@ Run the Claude Code agent inside a VM with skills, MCP servers, and custom confi Read [Sessions](/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. -## LLM Credentials +## Model & credentials Set the relevant variable(s) on the session's `env`, sourced from your server's environment: @@ -17,7 +17,7 @@ Set the relevant variable(s) on the session's `env`, sourced from your server's - `CLAUDE_CODE_USE_BEDROCK=1` — use Amazon Bedrock (auth via the AWS credential chain: `AWS_REGION`, `AWS_PROFILE`, …). - `CLAUDE_CODE_USE_VERTEX=1` — use Google Vertex AI (auth via Google Cloud credentials). -See [LLM Credentials](/docs/llm-credentials), and Claude Code's [environment variables](https://code.claude.com/docs/en/env-vars) for the full list. +See [Models & Credentials](/docs/models-and-credentials), and Claude Code's [environment variables](https://code.claude.com/docs/en/env-vars) for the full list. ## Skills @@ -27,7 +27,7 @@ Claude Code discovers [agent skills](https://docs.claude.com/en/docs/claude-code Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both local child-process servers and remote URLs are supported. -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. +**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. ## Customizing the agent diff --git a/website/public/docs/docs/agents/codex.md b/website/public/docs/docs/agents/codex.md index 441d123039..baeacc7081 100644 --- a/website/public/docs/docs/agents/codex.md +++ b/website/public/docs/docs/agents/codex.md @@ -6,7 +6,7 @@ Run the Codex coding agent inside a VM with skills, MCP servers, and custom conf Read [Sessions](/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. -## LLM Credentials +## Model & credentials Set the relevant variable(s) on the session's `env`, sourced from your server's environment: @@ -14,7 +14,7 @@ Set the relevant variable(s) on the session's `env`, sourced from your server's - `OPENAI_BASE_URL` — route through a gateway or OpenAI-compatible endpoint. - Custom providers — defined in `~/.codex/config.toml`; each provider's `env_key` names the variable Codex reads for its key (e.g. `AZURE_OPENAI_API_KEY`, `MISTRAL_API_KEY`). -See [LLM Credentials](/docs/llm-credentials), and Codex's [config reference](https://developers.openai.com/codex/config-reference) for details. +See [Models & Credentials](/docs/models-and-credentials), and Codex's [config reference](https://developers.openai.com/codex/config-reference) for details. ## Skills @@ -24,7 +24,7 @@ Codex discovers `SKILL.md` files from its skills directory. Write the skill into Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both local child-process servers and remote URLs are supported. -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. +**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. ## Customizing the agent diff --git a/website/public/docs/docs/agents/opencode.md b/website/public/docs/docs/agents/opencode.md index e72aa1fecc..cb8b9576fa 100644 --- a/website/public/docs/docs/agents/opencode.md +++ b/website/public/docs/docs/agents/opencode.md @@ -6,7 +6,7 @@ Run the OpenCode coding agent inside a VM with skills, MCP servers, and custom c Read [Sessions](/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. -## LLM Credentials +## Model & credentials OpenCode auto-detects a provider when its key is present on the session's `env`, sourced from your server's environment. Common variables: @@ -17,7 +17,7 @@ OpenCode auto-detects a provider when its key is present on the session's `env`, - `GROQ_API_KEY` — Groq. - …plus Amazon Bedrock, Azure, Google Vertex, and 70+ providers via [models.dev](https://models.dev). -See [LLM Credentials](/docs/llm-credentials), and OpenCode's [providers docs](https://opencode.ai/docs/providers/) for the full list. +See [Models & Credentials](/docs/models-and-credentials), and OpenCode's [providers docs](https://opencode.ai/docs/providers/) for the full list. ## Model configuration @@ -29,8 +29,8 @@ Two settings will silently produce an **empty response** if wrong: ```ts // Write the config before creating the session -await agent.mkdir("/home/agentos/.config/opencode", { recursive: true }); -await agent.writeFile( +await agent.filesystem.mkdir("/home/agentos/.config/opencode", { recursive: true }); +await agent.filesystem.writeFile( "/home/agentos/.config/opencode/opencode.json", JSON.stringify({ $schema: "https://opencode.ai/config.json", @@ -42,7 +42,7 @@ await agent.writeFile( }), ); -await agent.openSession({ +await agent.sessions.open({ agent: "opencode", env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); @@ -56,7 +56,7 @@ OpenCode discovers `SKILL.md` files from its skills directory. Write the skill i Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both local child-process servers and remote URLs are supported. -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. +**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. ## Customizing the agent diff --git a/website/public/docs/docs/agents/pi.md b/website/public/docs/docs/agents/pi.md index 539b9c8b89..4334b9d1e2 100644 --- a/website/public/docs/docs/agents/pi.md +++ b/website/public/docs/docs/agents/pi.md @@ -6,14 +6,14 @@ Run the Pi coding agent inside a VM with extensions and custom configuration. Read [Sessions](/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. -## LLM Credentials +## Model & credentials Set the relevant variable on the session's `env`, sourced from your server's environment: - `ANTHROPIC_API_KEY` — Anthropic (Claude), the default. - Other providers — use the provider-named key (e.g. `OPENAI_API_KEY`, `GEMINI_API_KEY`, `OPENROUTER_API_KEY`). -See [LLM Credentials](/docs/llm-credentials), and Pi's [providers docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/providers.md) for the full list. +See [Models & Credentials](/docs/models-and-credentials), and Pi's [providers docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/providers.md) for the full list. ## Skills @@ -23,7 +23,7 @@ Pi discovers `SKILL.md` files from its skills directory. Write the skill into th Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both local child-process servers and remote URLs are supported. -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. +**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. ## Extensions diff --git a/website/public/docs/docs/architecture.md b/website/public/docs/docs/architecture.md index 407eaf4ad4..eb3709ca4c 100644 --- a/website/public/docs/docs/architecture.md +++ b/website/public/docs/docs/architecture.md @@ -91,7 +91,7 @@ The kernel is the single chokepoint. Each kind of guest operation is serviced by The executor is the untrusted half of the VM. It runs the guest code and reaches the kernel for everything else. -- **JavaScript Acceleration.** Guest JavaScript runs on a native V8 runtime (the same engine in Chrome and Node.js, with the full JIT compiler) inside an isolate. This is what we call **JavaScript Acceleration**: the guest's JavaScript executes at native speed, not through an interpreter or a translation shim. It is genuinely fast, and it presents normal Node.js semantics. See [JavaScript Runtime](/docs/nodejs-runtime). +- **JavaScript Acceleration.** Guest JavaScript runs on a native V8 runtime (the same engine in Chrome and Node.js, with the full JIT compiler) inside an isolate. This is what we call **JavaScript Acceleration**: the guest's JavaScript executes at native speed, not through an interpreter or a translation shim. It is genuinely fast, and it presents normal Node.js semantics. See [JavaScript](/docs/execution/javascript). - **WASM alongside it.** The shell (`sh`) and the coreutils behind process execution ship as WebAssembly modules, and you can run your own WASM too. See [POSIX Syscalls](/docs/architecture/posix-syscalls) and the [Compiler Toolchain](/docs/architecture/compiler-toolchain). - **Native binaries.** Tools mounted into the VM run inside the same boundary as everything else. - **No host fallthrough.** The executor holds no capability of its own. For every file read, process spawn, or socket open, it issues a syscall and blocks for the kernel's reply. @@ -197,13 +197,13 @@ The `agentOS()` actor (from `@rivet-dev/agentos`) wraps the raw VM in a [Rivet A - **Recurring work.** Schedule a shell command or an agent session on a cron expression. - **Overlap control.** Choose what happens when a run is still going when the next is due (`allow`, `skip`, or `queue`). -- **Observable.** Stream `cronEvent`s to watch executions. See [Cron Jobs](/docs/cron). +- **Observable.** Stream `cronEvent`s to watch executions. See [Crons & Loops](/docs/cron). ### Workflows - **Durable multi-step tasks.** A workflow is the actor's `run` handler wrapped in `workflow()`, where each `ctx.step()` is recorded, retried, and resumed independently. - **Crash-proof.** If the process dies mid-run, replay skips completed steps and continues where it left off. -- **Composable.** The output of one step feeds the next: clone a repo, let an agent fix a bug, run the tests. See [Workflow Automation](/docs/workflows). +- **Composable.** The output of one step feeds the next: clone a repo, let an agent fix a bug, run the tests. See [Workflows & Graphs](/docs/workflows). ### Persistence & sleep/wake diff --git a/website/public/docs/docs/architecture/agent-sessions.md b/website/public/docs/docs/architecture/agent-sessions.md index 85d5c41f5d..566ec61ba9 100644 --- a/website/public/docs/docs/architecture/agent-sessions.md +++ b/website/public/docs/docs/architecture/agent-sessions.md @@ -28,7 +28,7 @@ The sidecar—not the actor or SDK—owns defaults and orchestration. TypeScript One prompt may run per session. Cancellation races are first-writer-wins. AgentOS does not automatically replay interrupted prompts because tool side effects may already have occurred. -The ACP runtime and core SDK transports impose no wall-clock deadline on prompts or human permission waits. After 30 seconds without ACP activity, AgentOS logs an inactivity warning with the total elapsed time and last observed activity, repeating every 30 seconds until activity resumes. Streaming output resets that interval. Bootstrap, teardown, filesystem, terminal, and other machine-to-machine operations retain bounded failure deadlines. Actor-hosted calls currently inherit RivetKit's maximum timer-safe action bound of about 24.8 days because RivetKit does not yet support an unbounded action. +The ACP runtime and AgentOS client transports impose no wall-clock deadline on prompts or human permission waits. After 30 seconds without ACP activity, AgentOS logs an inactivity warning with the total elapsed time and last observed activity, repeating every 30 seconds until activity resumes. Streaming output resets that interval. Bootstrap, teardown, filesystem, terminal, and other machine-to-machine operations retain bounded failure deadlines. Actor-hosted calls currently inherit RivetKit's maximum timer-safe action bound of about 24.8 days because RivetKit does not yet support an unbounded action. ## Reads versus adapter operations diff --git a/website/public/docs/docs/architecture/compiler-toolchain.md b/website/public/docs/docs/architecture/compiler-toolchain.md index cefb2222a9..5124083504 100644 --- a/website/public/docs/docs/architecture/compiler-toolchain.md +++ b/website/public/docs/docs/architecture/compiler-toolchain.md @@ -88,7 +88,7 @@ The same path is open to your own programs. A program you compile for `wasm32-wasip1` runs as a guest command exactly like the bundled ones; link the `wasi-ext` bindings if it needs processes, users, or sockets, and leave them out for a pure-compute tool. Heavy native binaries that are not yet available as -WASM belong in a [mounted sandbox](/docs/sandbox) instead. +WASM belong in an [external sandbox](/docs/extensions/sandboxes) instead. ## Recommendations diff --git a/website/public/docs/docs/architecture/javascript-executor.md b/website/public/docs/docs/architecture/javascript-executor.md index c3da35a00a..d7fc671e27 100644 --- a/website/public/docs/docs/architecture/javascript-executor.md +++ b/website/public/docs/docs/architecture/javascript-executor.md @@ -10,7 +10,7 @@ transport. For socket ownership, loopback, DNS, and network policy, see [Networking](/docs/architecture/networking). For the client-facing JavaScript -environment, see [JavaScript Runtime](/docs/js-runtime). +environment, see [JavaScript](/docs/execution/javascript). Tokio never invokes guest JavaScript from a runtime worker. A Tokio task stores bounded work and publishes durable readiness. The separate V8 executor thread diff --git a/website/public/docs/docs/architecture/packages-and-command-resolution.md b/website/public/docs/docs/architecture/packages-and-command-resolution.md index d60b9e563a..d813ec103b 100644 --- a/website/public/docs/docs/architecture/packages-and-command-resolution.md +++ b/website/public/docs/docs/architecture/packages-and-command-resolution.md @@ -63,7 +63,7 @@ is what the runtime **projects** from that package when it mounts it: | `share/` | FHS data — `share/man/man/*`, etc. | | `current` | Symlink `→ `; switching versions is one atomic rename. | -```jsonc +```json // package.json — commands come from "bin"; an agent's ACP entrypoint is just one of them { "name": "@agentos-software/pi", "version": "0.0.1", "bin": { "pi-acp": "dist/pi-acp.wasm" } } ``` diff --git a/website/public/docs/docs/architecture/processes.md b/website/public/docs/docs/architecture/processes.md index 6d65a445cf..fbf5c20153 100644 --- a/website/public/docs/docs/architecture/processes.md +++ b/website/public/docs/docs/architecture/processes.md @@ -6,7 +6,7 @@ Internals of the kernel process model: the virtual process table, how spawns are This page is an internals deep-dive on the kernel's **process model**: the data structures and syscall paths behind every guest process. For the client-facing -API (`exec`, `spawn`, `openShell`, lifecycle, the process tree), see +API (`process.exec`, `process.spawn`, `terminal.open`, lifecycle, the process tree), see [Processes & Shell](/docs/processes). For the surrounding component and trust model, see [Architecture](/docs/architecture). @@ -80,10 +80,10 @@ An interactive shell needs a terminal, not just piped stdio: line editing, job control signals, and window size all depend on a PTY. The kernel provides virtual PTY devices for this. -- **A shell is a process plus a PTY.** `openShell` allocates a kernel PTY and starts a shell process attached to it, returning a `shellId`. The PTY is a virtualized terminal device, never a host `/dev/pts` entry. -- **Bidirectional terminal I/O.** `writeShell` feeds keystrokes into the PTY master side; everything the shell and its children emit comes back as `shellData` events. This carries terminal control sequences, so full-screen TUIs behave correctly. -- **Resize is a terminal operation.** `resizeShell` updates the PTY's window size (columns and rows), which the kernel propagates to the foreground process the way a real terminal resize would, so programs relying on `TIOCGWINSZ`-style sizing redraw correctly. -- **Teardown.** `closeShell` tears down the PTY and the attached shell process. An open shell keeps the VM active, the same way an open PTY keeps a session alive on a real system. +- **A shell is a process plus a PTY.** `terminal.open` allocates a kernel PTY and starts a shell process attached to it, returning a `shellId`. The PTY is a virtualized terminal device, never a host `/dev/pts` entry. +- **Bidirectional terminal I/O.** `terminal.write` feeds keystrokes into the PTY master side; everything the shell and its children emit comes back as `shellData` events. This carries terminal control sequences, so full-screen TUIs behave correctly. +- **Resize is a terminal operation.** `terminal.resize` updates the PTY's window size (columns and rows), which the kernel propagates to the foreground process the way a real terminal resize would, so programs relying on `TIOCGWINSZ`-style sizing redraw correctly. +- **Teardown.** `terminal.close` tears down the PTY and the attached shell process. An open shell keeps the VM active, the same way an open PTY keeps a session alive on a real system. ## WASM sh and coreutils on the process model diff --git a/website/public/docs/docs/core.md b/website/public/docs/docs/core.md index f3af996317..8d126bf0ac 100644 --- a/website/public/docs/docs/core.md +++ b/website/public/docs/docs/core.md @@ -1,12 +1,13 @@ -# Core Package +# Direct VM API -Use @rivet-dev/agentos-core standalone for direct VM control without the Rivet Actor runtime. +Use the direct AgentOS VM API or layer it into an AgentOS actor. -## agentOS vs agentOS Core +## Direct VM vs actor -The `agentOS()` actor (from `@rivet-dev/agentos`) wraps the core package and adds: +`@rivet-dev/agentos` includes both the direct `AgentOs` VM API and the +`agentOS()` actor API: -| | Core (`@rivet-dev/agentos-core`) | Actor (`@rivet-dev/agentos`) | +| | Direct VM | Actor | |-|---|---| | Persistence | In-memory by default (pluggable via [mounts](#mounts)) | Persistent filesystem and sessions | | Distributed state | Manage yourself | Built-in distributed statefulness | @@ -19,16 +20,16 @@ The `agentOS()` actor (from `@rivet-dev/agentos`) wraps the core package and add | Agent-to-agent communication | Custom | Built into [Rivet Actors](/docs/agent-to-agent) | | Authentication | Set up yourself | [Documentation](/docs/authentication) | -We recommend using [Rivet Actors](https://rivet.dev/docs/actors) because they provide a portable way to run `agentOS()` on any infrastructure with built-in persistence, networking, and orchestration. Use the core package if you need the most bare-bones implementation possible. +We recommend using [Rivet Actors](https://rivet.dev/docs/actors) when you need persistence, networking, and orchestration. Use `AgentOs.create()` from the same package when you need direct VM control in a Node.js process. -`agentOS()` returns an ordinary TypeScript Rivet actor definition. Its config accepts the core VM options together with normal actor state, actions, events, queues, connection types, and lifecycle hooks such as `onBeforeConnect`. AgentOS actions and events are merged in automatically; their names are reserved so they cannot be accidentally shadowed. After a wake, the actor creates the core SDK VM lazily on the first AgentOS action and disposes it on sleep. This lets a connection subscribe before the `vmBooted` event is emitted. +`agentOS()` returns an ordinary TypeScript Rivet actor definition. Its config accepts the VM options together with normal actor state, actions, events, queues, connection types, and lifecycle hooks such as `onBeforeConnect`. AgentOS actions and events are merged in automatically; their names are reserved so they cannot be accidentally shadowed. After a wake, the actor creates its VM lazily on the first AgentOS action and disposes it on sleep. This lets a connection subscribe before the `vmBooted` event is emitted. Creation input is inferred from the actor definition and is passed through normal client creation options: `client.vm.create("key", { input })`. The same input reaches `createState(c, input)` and `onCreate(c, input)`. ## Install ```bash -npm install @rivet-dev/agentos-core +npm install @rivet-dev/agentos ``` ## Boot a VM @@ -37,11 +38,11 @@ Create a VM and drive it directly — no actor runtime, no client/server split. ## Sidecar process -Every VM runs inside a **shared sidecar process** rather than a process of its own. By default all VMs are tenants of a single, process-global sidecar (the `default` pool), so each additional VM only adds its marginal cost — a V8 isolate plus its kernel state — instead of a whole OS process. This is what keeps per-VM memory in the tens of MB and warm VM creation in the single-digit milliseconds (see [Benchmarks](/docs/benchmarks)). +Every VM runs inside a **shared sidecar process** rather than a process of its own. By default all VMs are tenants of a single, process-global sidecar (the `default` pool), so each additional VM only adds its marginal cost — a V8 isolate plus its kernel state — instead of a whole OS process. This is what keeps per-VM memory in the tens of MB and warm VM creation in the single-digit milliseconds (see [Performance](/docs/performance)). This is automatic — `agentOS()` and `AgentOs.create()` use the shared default sidecar with no configuration, and the same applies to Rivet Actors (each actor's VM is a tenant of the shared process). Disposing a VM tears down only that VM; the shared sidecar process is reused across VMs and stays alive for the lifetime of the host process. -For advanced cases the core package exposes explicit sidecar handles so you can isolate a group of VMs in their own process: +For advanced cases the direct VM API exposes explicit sidecar handles so you can isolate a group of VMs in their own process: ## Filesystem @@ -78,8 +79,8 @@ The top-level fields are documented inline above. See [Mounts](#mounts) and [Sof ### Session events -With the core package, `onSessionEvent` receives a generic union containing exact native ACP `SessionUpdate`, `RequestPermissionRequest`, and `RequestPermissionResponse` payloads wrapped with AgentOS durability metadata. Register it before prompting. On reconnect, also read durable history after your last sequence and deduplicate by `(sessionId, sequence)`: +With the direct VM API, `onSessionEvent` receives a generic union containing exact native ACP `SessionUpdate`, `RequestPermissionRequest`, and `RequestPermissionResponse` payloads wrapped with AgentOS durability metadata. Register it before prompting. On reconnect, also read durable history after your last sequence and deduplicate by `(sessionId, sequence)`: ### Timeouts and sleep -Action timeouts and automatic sleep/wake are features of the [`agentOS()` actor](/docs/quickstart), not the core package. A core VM stays alive until you call `dispose()`. See [Persistence & Sleep](/docs/persistence) for the actor's sleep lifecycle. \ No newline at end of file +Action timeouts and automatic sleep/wake are features of the [`agentOS()` actor](/docs/quickstart), not the direct VM API. A direct VM stays alive until you call `dispose()`. See [Persistence & Sleep](/docs/persistence) for the actor's sleep lifecycle. \ No newline at end of file diff --git a/website/public/docs/docs/cost-evaluation.md b/website/public/docs/docs/cost-evaluation.md deleted file mode 100644 index 70eb8a1b47..0000000000 --- a/website/public/docs/docs/cost-evaluation.md +++ /dev/null @@ -1,52 +0,0 @@ -# Cost Evaluation - -How agentOS compares on cost to per-second sandbox providers when you run coding-agent VMs on your own hardware. - -agentOS is a library you run on hardware you already control, not a metered service. That changes the cost model for running coding-agent VMs from "pay a provider per sandbox-second" to "pay for the compute you provision, then pack as much work onto it as it can hold." This page explains where the savings come from and how to reason about them honestly. It does not publish a single magic multiplier, because the real number depends on your workload, your hardware, and how you share VMs. - -For measured latency (cold start, warm execution, and reuse fast paths), see [Benchmarks](/docs/benchmarks). This page is about cost structure, not raw performance. - -## Where the savings come from - -Two structural differences drive the cost gap versus per-second sandbox providers: - -- **You run on your own hardware**: you choose the cloud, instance type, architecture, and region. A small commodity instance (for example an ARM VM from a budget host) costs a flat hourly or monthly rate that is typically far below what per-sandbox-second billing adds up to once you have steady agent traffic. You also avoid egress fees and vendor lock-in. -- **You decide the isolation granularity**: sandbox providers bill a full container or microVM per execution, usually with a minimum memory reservation that you pay for even when your code uses a fraction of it. With agentOS you own the VM lifecycle: you can dedicate a VM per tenant or per task for maximum isolation, or amortize setup by reusing one VM across many runs. - -## The isolation model matters for cost - -Each `AgentOs.create()` boots a fully virtualized VM, and each `exec()` / `run()` inside it is a fresh guest process. That gives you a dial between isolation and density: - -- **One VM per task or tenant (strongest isolation)**: create a VM, run the work, and dispose it, or give each tenant its own VM. Each VM is its own crash and resource domain, with the highest per-VM overhead. Best when load is untrusted or bursty. -- **A shared VM for trusted work**: reuse one VM across many runs to amortize the VM boot cost. Each `exec()` / `run()` still executes in a fresh guest process, so in-memory state does not leak between runs, but the VM and filesystem are shared. Good for trusted, sequential work. - -The denser you can safely pack agent work onto an instance, the lower your effective cost per execution. See [Resource Limits](/docs/resource-limits) for the per-VM caps that govern how densely you can pack, and [Processes & Shell](/docs/processes) for how guest processes run inside a VM. - -## How to estimate your own cost - -Because agentOS runs on hardware you provision, the honest way to compare is to plug in your own numbers: - -1. **Pick your hardware and its rate**: take the hourly or monthly price of the instance you would run on, and divide down to a per-second instance cost. -2. **Estimate how many concurrent VMs fit**: measure per-VM memory overhead on your target hardware under your isolation strategy, then divide your usable RAM by that figure. Leave headroom (the measurement and any orchestration layer will not bin-pack perfectly). -3. **Divide instance cost by concurrent VMs**: that gives a cost-per-VM-second you can compare against a provider's per-sandbox-second rate. - -Measure on the hardware and isolation strategy you will actually deploy. Per-VM overhead depends on whether you create a fresh VM per task or reuse one across runs, and on the work the agent does, so a number measured on one machine will not transfer cleanly to another. - -## Comparing against sandbox providers - -When you do compare against a per-second sandbox provider, hold the methodology honest: - -- **Sandbox cost** is the provider's minimum allocatable memory times their per-GiB-second rate (plus any egress and platform fees). The minimum reservation is the floor you pay even for tiny workloads. -- **agentOS cost** is your instance cost per second divided by the number of VMs you can keep live on it, with realistic headroom for bin-packing inefficiency. - -The advantage is largest for **many small, short executions**, where a per-sandbox minimum reservation dominates and your own hardware lets you pack densely. It narrows for **heavyweight, long-lived workloads** (for example dev servers that need hundreds of megabytes regardless), where the win shifts from density to hardware choice: you still avoid per-second metering, egress fees, and lock-in, but the raw memory-density advantage is smaller. - -| Workload | Primary cost advantage | -| --- | --- | -| Many small, short executions | Density: pack many VMs per instance, no per-sandbox minimum | -| Heavyweight, long-lived workloads | Hardware choice, flat instance pricing, no egress or lock-in | -| High concurrency | Reuse a VM across runs to amortize VM boot cost | - -Be careful generalizing cost ratios from a single benchmark. Provider pricing, instance pricing, and exchange rates change over time, and per-VM overhead varies by workload and isolation strategy. Re-measure on your own hardware before quoting a number. - -When you do need a full Linux sandbox for heavier agent workloads, see [agentOS vs Sandbox](/docs/versus-sandbox) for how the two models combine. \ No newline at end of file diff --git a/website/public/docs/docs/crash-course.md b/website/public/docs/docs/crash-course.md index ae308cd24a..0807021294 100644 --- a/website/public/docs/docs/crash-course.md +++ b/website/public/docs/docs/crash-course.md @@ -30,25 +30,25 @@ Approve or deny agent tool use with human-in-the-loop patterns or auto-approve f *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/approvals)* -### Bindings +### Custom Bindings Expose your JavaScript functions to agents as CLI commands inside the VM. Each binding group becomes a binary at `/usr/local/bin/agentos-{name}`, and each binding becomes a subcommand with flags auto-generated from its Zod input schema. The server below defines a `weather` binding group with a `forecast` binding; the client opens a session and prompts the agent, which calls the binding itself as a shell command. -*See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/bindings) or [Documentation](/docs/bindings)* +*See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/bindings) or [Documentation](/docs/extensions/custom-bindings)* ### Agent-to-Agent -Let one agent call another through a [binding](/docs/bindings). The coder gets a `review` binding it invokes itself, which bridges into the reviewer's isolated VM. +Let one agent call another through a [custom binding](/docs/extensions/custom-bindings). The coder gets a `review` binding it invokes itself, which bridges into the reviewer's isolated VM. *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/agent-to-agent)* -### Multiplayer & Realtime +### Multiplayer Connect multiple clients to the same agent VM. All subscribers see session output, process logs, and shell data in realtime. *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/multiplayer)* -### Workflows +### Workflows & Graphs Orchestrate multi-step agent tasks with durable workflows that survive crashes and restarts. @@ -74,14 +74,14 @@ Proxy HTTP requests into VMs with `httpRequest`. Create actor-namespaced preview *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/networking)* -### Cron Jobs +### Crons & Loops Schedule recurring commands and agent sessions with cron expressions. *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/cron)* -### Sandbox Mounting +### External Sandboxes agentOS uses a hybrid model: agents run in a lightweight VM by default and mount a full sandbox on demand for heavy workloads like browsers, compilation, and desktop automation. Sandboxes are powered by [Sandbox Agent](https://sandboxagent.dev), so you can swap providers without changing agent code. Mount the sandbox as a filesystem and expose its process management as bindings. -[Documentation](/docs/sandbox) \ No newline at end of file +[Documentation](/docs/extensions/sandboxes) \ No newline at end of file diff --git a/website/public/docs/docs/cron.md b/website/public/docs/docs/cron.md index e4a7fa69b9..57c20ed905 100644 --- a/website/public/docs/docs/cron.md +++ b/website/public/docs/docs/cron.md @@ -1,8 +1,12 @@ -# Cron Jobs +# Crons & Loops Schedule recurring commands and agent sessions in agentOS VMs. -Schedule recurring work with cron expressions, running either a shell command (`exec`) or an agent session (`session`), with overlap modes (`allow`, `skip`, `queue`) and native `cronEvent` streaming to monitor execution. Cron jobs keep the actor alive while a job runs; the actor can sleep between executions. +Schedule recurring work and long-running agent loops with cron expressions, +running either a shell command (`exec`) or an agent session (`session`), with +overlap modes (`allow`, `skip`, `queue`) and native `cronEvent` streaming to +monitor execution. Cron jobs keep the actor alive while a job runs; the actor +can sleep between executions. ## Schedule a command diff --git a/website/public/docs/docs/custom-software/definition.md b/website/public/docs/docs/custom-software/definition.md index ed25f6f09e..94b51898e2 100644 --- a/website/public/docs/docs/custom-software/definition.md +++ b/website/public/docs/docs/custom-software/definition.md @@ -107,7 +107,7 @@ packed files, so the JSON never ships into the VM and the metadata never travels command/WASM packages it is **generated** for you (name from `package.json`); for agents you author the `agent` block (or `agentos-toolchain pack --agent ` writes it). -```jsonc +```json { "name": "my-agent", // → /opt/agentos/ "agent": { // optional — also exposes an agent session diff --git a/website/public/docs/docs/deployment.md b/website/public/docs/docs/deployment.md index df6a8d45cb..dd6e9a2620 100644 --- a/website/public/docs/docs/deployment.md +++ b/website/public/docs/docs/deployment.md @@ -6,7 +6,7 @@ agentOS is powered by [Rivet](https://rivet.dev), an open-source actor platform, - **[Rivet Cloud](https://rivet.dev/cloud)**: fully managed (Rivet Compute, or bring your own cloud). Zero-ops. - **Self-hosted**: run the open-source Rivet platform on your own infrastructure (Kubernetes, Hetzner, VMs, and more) for full control. -- **[agentOS Core](/docs/core)**: embed `@rivet-dev/agentos-core` directly in any Node.js backend, no platform required. +- **[Direct VM API](/docs/core)**: embed `@rivet-dev/agentos` directly in any Node.js backend, no platform required. Pick a deploy target below, or see [Rivet's deployment guides](https://rivet.dev/docs/deploy/). diff --git a/website/public/docs/docs/execution/bash.md b/website/public/docs/docs/execution/bash.md new file mode 100644 index 0000000000..5074763bcc --- /dev/null +++ b/website/public/docs/docs/execution/bash.md @@ -0,0 +1,50 @@ +# Bash + +Run shell commands and arbitrary argv operations through the AgentOS execution lifecycle. + +Shell commands are the simplest AgentOS execution surface. Use `process.exec()` +for shell syntax such as pipes and redirects, and `process.execFile()` for +injection-safe command arguments. Both use the same execution lifecycle as +JavaScript, TypeScript, Python, and package workflows. + +## Run commands + +`process.exec()` runs a command through the VM's configured shell and returns +its outcome, exit code, stdout, stderr, and `executionId`. The command runs +inside the VM, never in the host shell. + +Prefer `process.execFile()` when command names or arguments come from data. Each +argument is transferred separately and AgentOS does not interpolate it into a +shell command. Keep `process.exec()` for workflows that intentionally need +shell syntax. + +## Detached and interactive work + +Set `detached: true` on `process.exec()` or `process.execFile()`. Manage the +returned `executionId` with `executions.wait()`, `executions.cancel()`, +`executions.signal()`, stdin, PTY resize, bounded output replay, reset, and +deletion. `process.spawn()` is the separate managed-child-process API: it +returns a PID and is controlled through the remaining `process.*` methods. + +An execution accepts only one active operation. Reusing a running ID fails +immediately. Process-only operations do not pin a retained language, so the +same idle execution can later run JavaScript or Python. + +## Files and software + +Shell commands see the persistent [filesystem](/docs/filesystem) shared by +agents, JavaScript, and Python. Common POSIX commands are available by default, +and additional software is projected through the [software registry](/docs/software). + +## Custom bindings + +[Custom Bindings](/docs/extensions/custom-bindings) appear as commands such as +`agentos-weather forecast`, so shell pipelines can use trusted host +capabilities without putting credentials inside the VM. + +## Permissions, limits, and timeouts + +Every command inherits the VM [permission policy](/docs/permissions) and +[resource limits](/docs/resource-limits). `timeoutMs` sets an operation-level +wall-clock deadline. A denied guest operation receives its normal POSIX error, +and a timed-out execution retains a structured `timed_out` result. \ No newline at end of file diff --git a/website/public/docs/docs/execution/javascript-compatibility.md b/website/public/docs/docs/execution/javascript-compatibility.md new file mode 100644 index 0000000000..eb41f8fcef --- /dev/null +++ b/website/public/docs/docs/execution/javascript-compatibility.md @@ -0,0 +1,74 @@ +# Node.js Compatibility + +Node.js builtins available to JavaScript running inside AgentOS. + +Guest JavaScript never touches the host Node.js runtime. Every `import` or +`require` of a `node:` builtin resolves to a kernel-backed bridge or an +in-isolate implementation, and unknown or denied modules fail explicitly. The +guest reports Node.js `v22.0.0` through `process.version`. + +## How builtins are backed + +- **Kernel-backed:** calls route through the VM filesystem, socket table, + process table, DNS resolver, or entropy source. +- **In-isolate:** pure JavaScript implementations run entirely inside V8 and + require no host access. +- **Denied:** importing the module throws `ERR_ACCESS_DENIED`. + +The canonical inventory lives in +`crates/execution/assets/polyfill-registry.json`. + +A guest never falls through to a real host builtin. Anything not bridged +or implemented in the isolate is denied. + +## Kernel-backed builtins + +| Module | Backed by | +| --- | --- | +| `fs`, `fs/promises` | VM filesystem, including fds, streams, metadata, symlinks, and polling-based watchers. | +| `child_process` | VM process table. `spawn`, `exec`, `execFile`, and sync variants launch guest processes. | +| `net`, `dgram` | VM TCP, Unix-socket, and UDP tables. | +| `dns`, `dns/promises` | VM DNS resolver. | +| `http`, `https`, `http2`, `tls` | VM socket and TLS paths, including clients, servers, and connection pooling. | +| `os` | VM-scoped platform, architecture, hostname, CPU, memory, and user information. | +| `crypto` | Entropy, hashes, HMAC, ciphers, scrypt, UUIDs, and WebCrypto. | +| `process` | VM environment, working directory, signals, timers, stdio, and umask. | +| `module` | `createRequire`, builtin resolution, and basic `Module` compatibility. | +| `console` | Bounded formatting and guest stdout/stderr. | +| `readline`, `sqlite`, `tty` | Kernel-backed compatibility surfaces. | +| `timers`, `timers/promises` | Timeout, interval, immediate, and promise variants. | +| `stream/web`, `stream/consumers`, `stream/promises` | Web Streams and stream helpers. | + +Network builtins obey the VM's [permission policy](/docs/permissions). Network +access is denied until the VM creator grants it. + +## In-isolate builtins + +Pure JavaScript implementations include `path`, `buffer`, `events`, `stream`, +`util`, `assert`, `url`, `querystring`, `string_decoder`, `zlib`, `punycode`, +`constants`, and `sys`. Default and named ESM imports are supported. + +Compatibility shims are also provided for common feature detection, including +`async_hooks`, `diagnostics_channel`, `perf_hooks`, `worker_threads`, `vm`, and +`v8`. The `worker_threads` shim does not create real worker threads. + +## Denied builtins + +`cluster`, `domain`, `inspector`, `repl`, `trace_events`, and `wasi` are denied. + +## Global APIs + +Modern web globals are available, including `fetch`, `Headers`, `Request`, +`Response`, `TextEncoder`, `TextDecoder`, `Buffer`, URL APIs, `Blob`, `File`, +`FormData`, abort APIs, `structuredClone`, `performance`, and WebAssembly. +`fetch()` uses the VM socket table and follows the same policy as `http` and +`net`. + +## Modules and output + +Both ESM and CommonJS use the VM filesystem and normal `node_modules` +resolution. Console and stream output is delivered through the same bounded +process-output path described in [Processes & Shells](/docs/processes). + +Return to the [JavaScript guide](/docs/execution/javascript) for TypeScript, +packages, files, processes, networking, bindings, permissions, and limits. \ No newline at end of file diff --git a/website/public/docs/docs/execution/javascript.md b/website/public/docs/docs/execution/javascript.md new file mode 100644 index 0000000000..5c62be329a --- /dev/null +++ b/website/public/docs/docs/execution/javascript.md @@ -0,0 +1,108 @@ +# JavaScript + +Execute JavaScript and TypeScript, install npm dependencies, and manage execution lifecycles in AgentOS. + +AgentOS runs JavaScript in native V8 behind the VM kernel boundary. Use the +first-class language methods for source, files, values, TypeScript, npm +projects, and package binaries. Use `process.execFile()` only when you need an +unusual command that does not have a language-level method. + +## Get started + +`@rivet-dev/agentos-javascript` is the focused JavaScript/TypeScript entry +point. It creates the same AgentOS VM and delegates every operation to the +sidecar-owned execution protocol. + +Every attached call returns one result discriminated by `outcome`. Successful +evaluations contain a JSON-compatible `value`; failed, cancelled, and timed-out +results contain a structured `error`. Stdout and stderr are always captured +with explicit truncation flags. Evaluation results also expose the value as a +bounded `{ type: "json", data }` display output. Returning `undefined`, a +function, a symbol, a circular object, or another non-JSON value produces an +`evaluation_serialization_failed` result instead of losing the value silently. + +## Use the core client + +The same methods are available directly on `AgentOs` under +`javascript.execute()`, `javascript.evaluate()`, `javascript.executeFile()`, +`javascript.typescript.*`, and `javascript.npm.*`. + +The focused runtime adds default `cwd` and `env` values and exposes the core VM +as `runtime.vm`; it does not implement a second execution engine. + +## Retain JavaScript state + +Give an operation an `executionId` and set `createIfMissing: true` on the first +call. Later inline JavaScript and TypeScript operations with the same ID share +one retained JavaScript realm. `inputs` is replaced on every operation and is +serialized separately from source. + +An execution accepts one active operation at a time. Reusing a busy ID fails +immediately. Bash, files, npm operations, and type checks can use the same +lifecycle ID, but run in fresh processes and do not alter retained language +memory. `executions.reset()` clears memory, results, and output; filesystem and +installed-package changes remain. `executions.delete()` removes an idle +execution. + +## TypeScript + +TypeScript execution is a convenience API in the JavaScript layer. **Executing +TypeScript transpiles it without semantic type checking.** Call +`javascript.typescript.check()` or +`javascript.typescript.checkProject()` when diagnostics are part of the +workflow. + +Inline `filePath` identifies source for diagnostics and module resolution; it +does not read that file. Use `javascript.typescript.executeFile()` on the core +client to execute an existing file. JavaScript and TypeScript inline calls +share retained state when they use the same execution ID. + +## npm projects and packages + +Use the options-only `javascript.npm.install()` overload for the project in +`cwd`. `frozen: true` performs a lockfile-exact clean install. Pass package +names for a named install, and use `javascript.npm.runScript()` or +`javascript.npm.runPackage()` instead of assembling npm commands. The focused +runtime exposes the same workflows as `installNpmPackages()`, +`executeNpmScript()`, and `executeNpmPackage()`. + +Package names, script names, paths, and arguments are transferred as distinct +argv values. Installs modify the VM-wide filesystem, so all executions in that +VM see the same dependencies. AgentOS admits only one npm or Python package +mutation at a time in a VM; a concurrent install fails with `execution_busy` +instead of allowing package managers to corrupt shared state. + +## Detached work and output + +Set `detached: true` on an execution method for a long-running program. The +returned descriptor contains its `executionId`; use `executions.wait()`, +`executions.cancel()`, `executions.signal()`, `executions.writeStdin()`, +`executions.closeStdin()`, `executions.resizePty()`, and +`executions.readOutput()` to manage it. Core callbacks receive exact +`Uint8Array` chunks. + +Actor actions use the same nested method paths as Core; RivetKit transports +them with dotted wire names such as `javascript.execute` and +`executions.readOutput`. Actor stdin and output use tagged +`{ encoding: "utf8" | "base64", data: string }` values, and live output is +broadcast through `executionOutput` and `executionCompleted` events. + +## Filesystem, processes, and networking + +`node:fs` uses the VM [filesystem](/docs/filesystem), `node:child_process` +starts kernel-managed guest processes, and Node networking APIs use the VM +socket table. Files and installed packages are immediately visible to Bash, +Python, agents, and other executions. See [Processes & Shells](/docs/processes), +[Networking & Previews](/docs/networking), and the detailed +[Node.js compatibility matrix](/docs/execution/javascript-compatibility). + +## Custom bindings and policy + +Guest JavaScript invokes [Custom Bindings](/docs/extensions/custom-bindings) +as ordinary typed commands, keeping host credentials outside the VM. + +All operations inherit the VM's [permissions](/docs/permissions) and +[resource limits](/docs/resource-limits). `timeoutMs` adds an operation-level +wall-clock deadline covering sidecar staging, TypeScript transformation, +guest execution, and result collection; it does not replace the independently +bounded VM safety limits. \ No newline at end of file diff --git a/website/public/docs/docs/execution/python.md b/website/public/docs/docs/execution/python.md new file mode 100644 index 0000000000..fd270a4f79 --- /dev/null +++ b/website/public/docs/docs/execution/python.md @@ -0,0 +1,81 @@ +# Python + +Execute Python source, files, modules, and package workflows in AgentOS. + +AgentOS runs CPython 3.13 as a first-class VM execution engine. Python shares +the VM filesystem, process tree, networking policy, permissions, and limits +with agents, Bash, JavaScript, and installed software. + +## Get started + +`@rivet-dev/agentos-python` is the focused Python entry point. It uses the same +sidecar protocol as the core `AgentOs` client. + +Use `python.execute()` for source and `python.evaluate()` for a JSON-compatible +value on the core client. The focused package exposes them as `execute()` and +`evaluate()` and provides default `cwd` and `env` values. Evaluation values are +also returned as bounded JSON display outputs. A value that Python's JSON +encoder cannot represent produces a structured +`evaluation_serialization_failed` result. + +## Retain Python state + +Reuse an `executionId` to keep Python globals, functions, imports, modules, and +guest objects in one interpreter. Set `createIfMissing: true` only on the first +operation. Structured `inputs` is replaced for every call. + +Only inline execute and evaluate calls retain interpreter memory. File, +module, install, Bash, and arbitrary-command operations use fresh processes. +`executions.reset()` clears retained memory and output without reverting the +filesystem; `executions.delete()` removes an idle execution. + +## Files, modules, and async Python + +Use `python.executeFile()` for an existing script and +`python.executeModule()` for the standard `python -m` workflow. Inline Python +supports top-level `await`, `async for`, and `async with`; awaited work is part +of the operation deadline. + +The API does not promise that unawaited `asyncio` tasks survive between +operations. Cancellation, timeout, reset, deletion, or VM disposal stops +execution-owned asynchronous work. + +## Install packages + +Call `python.install()` on `AgentOs`, or `install()` on the focused runtime. +Pass package specs for named installs, `requirementsFile` for a +requirements install, and `upgrade`, `indexUrl`, or `extraIndexUrls` for the +stable package workflows. + +Named packages and a requirements file cannot be combined in one call. +Installs modify the VM-wide filesystem and are visible to every execution in +that VM. AgentOS admits only one npm or Python package mutation at a time in a +VM; a concurrent install fails with `execution_busy` instead of risking shared +package state. Package downloads obey the VM network policy. + +## Detached work and output + +Set `detached: true` on execute, file, or module operations. Manage the returned +`executionId` with `executions.wait()`, `executions.cancel()`, +`executions.signal()`, stdin, PTY resize, reset, deletion, and bounded output +replay. Core output callbacks receive `Uint8Array`; actor events carry tagged +UTF-8/base64 data. Actor actions use the same nested method paths as Core and +RivetKit transports them with dotted wire names. + +## Filesystem, processes, and networking + +`pathlib`, `os`, and file objects use the VM [filesystem](/docs/filesystem). +`subprocess` starts kernel-managed guest commands. Python DNS, HTTP clients, and +outbound sockets use the VM network policy. See +[Processes & Shells](/docs/processes) and +[Networking & Previews](/docs/networking). + +## Custom bindings and policy + +Python can call [Custom Bindings](/docs/extensions/custom-bindings) as normal +commands through `subprocess`. + +All operations inherit [permissions](/docs/permissions) and +[resource limits](/docs/resource-limits). `timeoutMs` is an additional +operation wall-clock deadline covering staging, compilation, guest execution, +and result collection, while VM safety watchdogs remain independently bounded. \ No newline at end of file diff --git a/website/public/docs/docs/browser.md b/website/public/docs/docs/extensions/browser.md similarity index 93% rename from website/public/docs/docs/browser.md rename to website/public/docs/docs/extensions/browser.md index 2b97baa607..4bc062ac84 100644 --- a/website/public/docs/docs/browser.md +++ b/website/public/docs/docs/extensions/browser.md @@ -1,4 +1,4 @@ -# Browser +# Browser Automation Let agents read and search the web from an agentOS VM using Browserbase's cloud browser through the browse CLI — no local browser or sandbox required. @@ -36,4 +36,4 @@ browse cloud sessions list # list cloud browser sessions browse cloud projects list # list Browserbase projects ``` -The [interactive driver mode](https://docs.browserbase.com/integrations/skills/browse-cli) (`browse open`, `browse click`, …) is not supported inside the VM yet ([#1631](https://github.com/rivet-dev/agentos/issues/1631)). For interactive automation, run `browse` inside a sandbox via [Sandbox Mounting](/docs/sandbox). \ No newline at end of file +The [interactive driver mode](https://docs.browserbase.com/integrations/skills/browse-cli) (`browse open`, `browse click`, …) is not supported inside the VM yet ([#1631](https://github.com/rivet-dev/agentos/issues/1631)). For interactive automation, run `browse` inside an external sandbox via [External Sandboxes](/docs/extensions/sandboxes). \ No newline at end of file diff --git a/website/public/docs/docs/bindings.md b/website/public/docs/docs/extensions/custom-bindings.md similarity index 94% rename from website/public/docs/docs/bindings.md rename to website/public/docs/docs/extensions/custom-bindings.md index 9ef4ab7ca3..48770ba4a8 100644 --- a/website/public/docs/docs/bindings.md +++ b/website/public/docs/docs/extensions/custom-bindings.md @@ -1,4 +1,4 @@ -# Bindings +# Custom Bindings Expose custom host functions to agents as CLI commands inside the VM. @@ -62,9 +62,9 @@ On failure (validation or execution error), the binding exits non-zero and write Missing required flag: --city ``` -## Bindings vs MCP servers +## Bindings and MCP servers -agentOS supports two ways to give agents access to external functionality: **bindings** and **MCP servers**. Both work, but they have different tradeoffs. +AgentOS supports two ways to give agents access to external functionality: **bindings** and session-scoped **MCP servers**. Both work, but they have different tradeoffs. | | Bindings | MCP Servers | |---|---|---| diff --git a/website/public/docs/docs/sandbox.md b/website/public/docs/docs/extensions/sandboxes.md similarity index 91% rename from website/public/docs/docs/sandbox.md rename to website/public/docs/docs/extensions/sandboxes.md index f50fb54a13..9cb16b36fa 100644 --- a/website/public/docs/docs/sandbox.md +++ b/website/public/docs/docs/extensions/sandboxes.md @@ -1,8 +1,8 @@ -# Sandbox Mounting +# External Sandboxes Extend agentOS with full sandboxes for heavy workloads like browsers, desktop automation, and compilation. -For heavy workloads like browsers, desktop automation, and compilation, pair agentOS with a full sandbox on demand. Its filesystem mounts into the VM as a native directory, and its process management is exposed as [bindings](/docs/bindings), all provider-agnostic through [Sandbox Agent](https://sandboxagent.dev). +For heavy workloads like browsers, desktop automation, and compilation, pair agentOS with a full sandbox on demand. Its filesystem mounts into the VM as a native directory, and its process management is exposed as [custom bindings](/docs/extensions/custom-bindings), all provider-agnostic through [Sandbox Agent](https://sandboxagent.dev). ## Why use agentOS with a sandbox? @@ -25,7 +25,7 @@ Start with the default agentOS VM for all workloads, and only spin up a sandbox The sandbox integration ships as the `@rivet-dev/agentos-sandbox` package. It works through two mechanisms: - **Filesystem mount**: Projects the sandbox into the VM as a native directory, like mounting a hard drive on your own machine. Read and write files through the mount directly. -- **Bindings**: Exposes sandbox process management as [bindings](/docs/bindings). Execute commands on the sandbox from within the VM. +- **Bindings**: Exposes sandbox process management as [custom bindings](/docs/extensions/custom-bindings). Execute commands on the sandbox from within the VM. Both are powered by [Sandbox Agent](https://sandboxagent.dev), and you can swap providers without changing agent code. Install both packages: diff --git a/website/public/docs/docs/filesystem.md b/website/public/docs/docs/filesystem.md index 7fff8acdbc..f3a583288a 100644 --- a/website/public/docs/docs/filesystem.md +++ b/website/public/docs/docs/filesystem.md @@ -26,7 +26,7 @@ The actor's durable root is handled separately: the sidecar connects directly to ## File operations -These operations are primarily what the agent uses inside the VM, and are also available from the client to seed inputs and read results. For large or read-only inputs (a repo, a dataset), a read-only [host mount](#mounts) is faster than copying files in. Programs that need stdin or live output use exec instead (see [Core](/docs/core)). +These operations are primarily what the agent uses inside the VM, and are also available from the client to seed inputs and read results. For large or read-only inputs (a repo, a dataset), a read-only [host mount](#mounts) is faster than copying files in. Programs that need stdin or live output use exec instead (see the [Direct VM API](/docs/core)). ### Read and write @@ -57,7 +57,7 @@ See [Permissions](/docs/permissions) for the full configuration. ## Sandboxes -For heavier or untrusted workloads, run a full Linux [sandbox](/docs/sandbox) alongside the VM and mount its filesystem into agentOS. The agent then reads and writes the sandbox's files through the same `fs` APIs while the sandbox handles execution. See [Sandbox Mounting](/docs/sandbox) for setup. +For heavier workloads, run a full Linux [external sandbox](/docs/extensions/sandboxes) alongside the VM and mount its filesystem into agentOS. The agent then reads and writes the sandbox's files through the same `fs` APIs while the sandbox handles execution. ## Default layout diff --git a/website/public/docs/docs/js-runtime.md b/website/public/docs/docs/js-runtime.md deleted file mode 100644 index c82300f150..0000000000 --- a/website/public/docs/docs/js-runtime.md +++ /dev/null @@ -1,32 +0,0 @@ -# JavaScript Runtime - -How agentOS runs guest JavaScript: native V8 acceleration, low memory overhead, and Node.js compatibility. - -The JavaScript runtime is powered by the Rivet [Secure Exec](https://secureexec.dev) project, which provides the isolated V8 runtime that agentOS runs guest code in. Every guest VM executes its JavaScript inside this runtime, fully sandboxed from the host. - -## JavaScript Acceleration - -- **JavaScript is unusually slow as WebAssembly**: unlike most software, JavaScript pays a heavy penalty when compiled to WebAssembly, because so much engineering has gone into JIT-compiling JavaScript directly in V8. -- **Native V8, full JIT**: agentOS therefore runs guest JavaScript on the native V8 engine with its full JIT compiler, not through a WASM translation layer. We call this **JavaScript Acceleration**. -- **Native-speed execution**: guest JavaScript runs at native speed while staying inside the isolation boundary, with normal Node.js semantics. - -## Comparison to Node.js efficiency - -- **Isolate model, not processes**: agentOS runs each agent inside a V8 isolate rather than spawning a full Node.js process per agent. -- **Low memory overhead**: an isolate carries far less per-agent memory overhead than a full Node.js process, so many agents fit in the footprint that a process-per-agent model would spend on a handful. -- **Benchmarks**: see the Secure Exec [benchmarks](https://secureexec.dev/docs/benchmarks) for cold start, warm execution, and reuse measurements. - -## Node.js compatibility - -Guest code runs as Node.js (reporting `process.version` as `v22.0.0`), but it never touches the host runtime. Every `node:` builtin resolves to a kernel-backed bridge or an in-isolate polyfill, never the real host module. For the full builtin matrix (`fs`, `net`, `http`, `crypto`, undici-backed `fetch`, and more), see the Secure Exec [Node.js Compatibility](https://secureexec.dev/docs/nodejs-compatibility) reference. - -For the implementation-level event loop—how process-wide Tokio tasks notify a -thread-affine V8 isolate, how readiness is coalesced, and how `Duplex` -backpressure reaches a sidecar-owned socket—see -[JavaScript Executor & Socket Reactor](/docs/architecture/javascript-executor). - -### npm packages - -By default the VM has no npm packages installed. Mount a host `node_modules` directory to give guest code access to real packages: the `nodeModulesMount` helper projects it read-only at `/root/node_modules`, and the in-kernel resolver walks it exactly like Node.js does, with no bundling or patching. - -Resolution matches naive Node.js over the mounted tree: the ancestor `node_modules` walk, `package.json` `exports`/`imports` and conditions, and `realpath`/symlink following (so pnpm and yarn layouts resolve too). Both ESM `import` and CommonJS `require` work. See the Secure Exec [module loading](https://secureexec.dev/docs/features/module-loading) guide for the full model. \ No newline at end of file diff --git a/website/public/docs/docs/limitations.md b/website/public/docs/docs/limitations.md index f45cb0f8bf..7e1864b63b 100644 --- a/website/public/docs/docs/limitations.md +++ b/website/public/docs/docs/limitations.md @@ -6,7 +6,7 @@ agentOS is a Linux environment with a POSIX-compliant virtual kernel. It handles ## Sandbox mounting -When a workload needs a full Linux OS, agents can escalate to a full sandbox on demand without changing code. The [sandbox mounting](/docs/sandbox) extension mounts the sandbox as a filesystem and lets you execute commands on it, like mounting a hard drive on your own machine. Files written in the VM are available in the sandbox and vice versa. +When a workload needs a full Linux OS, agents can escalate to a full sandbox on demand without changing code. The [external sandbox](/docs/extensions/sandboxes) extension mounts the sandbox as a filesystem and lets you execute commands on it, like mounting a hard drive on your own machine. Files written in the VM are available in the sandbox and vice versa. See [agentOS vs Sandbox](/docs/versus-sandbox) for a detailed comparison. @@ -14,7 +14,7 @@ See [agentOS vs Sandbox](/docs/versus-sandbox) for a detailed comparison. ### Software registry -agentOS uses its own [software registry](/registry) of popular tools cross-compiled for the runtime. You cannot download and install arbitrary binaries (for example via `curl` or `apt`), and standard Linux package managers (`apt`, `yum`) are not available since agentOS runs a streamlined Linux environment rather than a full distribution. Native binaries that are not yet available in the registry (such as Go, Rust, or C++ toolchains) require a full [sandbox](/docs/sandbox). +agentOS uses its own [software registry](/registry) of popular tools cross-compiled for the runtime. You cannot download and install arbitrary binaries (for example via `curl` or `apt`), and standard Linux package managers (`apt`, `yum`) are not available since agentOS runs a streamlined Linux environment rather than a full distribution. Native binaries that are not yet available in the registry (such as Go, Rust, or C++ toolchains) require a full [external sandbox](/docs/extensions/sandboxes). See [Software](/docs/software) for how to install and configure available packages. diff --git a/website/public/docs/docs/llm-gateway.md b/website/public/docs/docs/llm-gateway.md deleted file mode 100644 index 6824a3ac08..0000000000 --- a/website/public/docs/docs/llm-gateway.md +++ /dev/null @@ -1,12 +0,0 @@ -# Embedded LLM Gateway - -Route, meter, and manage LLM API calls from agents. - -The Embedded LLM Gateway runs as part of the agentOS library, not as an external service. It intercepts and manages all LLM API calls made by agents inside the VM. - -- **Unified routing** for all agent LLM requests -- **API keys stay on the server** so they are never exposed to agent code inside the VM -- **Usage metering** with per-session and per-agent breakdowns -- **Rate limiting** and cost controls - -Check back soon for full documentation. \ No newline at end of file diff --git a/website/public/docs/docs/llm-credentials.md b/website/public/docs/docs/models-and-credentials.md similarity index 56% rename from website/public/docs/docs/llm-credentials.md rename to website/public/docs/docs/models-and-credentials.md index 3890f09975..d51cb8a16c 100644 --- a/website/public/docs/docs/llm-credentials.md +++ b/website/public/docs/docs/models-and-credentials.md @@ -1,8 +1,10 @@ -# LLM Credentials +# Models & Credentials -Pass LLM API keys to agent sessions securely. +Choose agent models and pass provider credentials to sessions securely. -Pass LLM provider API keys to agent sessions so keys stay on the server and are injected at session creation, with per-tenant isolation for multi-tenant deployments. +Choose the model through your agent adapter, then pass its provider credentials +to the session from trusted server code. Credentials are injected at session +creation and can be isolated per tenant. ## Passing API keys @@ -18,6 +20,9 @@ Then resolve each tenant's key and pass it at session creation: Because keys are resolved per tenant from your own credential store (the `lookupTenantApiKey` stand-in above) and stay on the server, each session uses the tenant's own key and one tenant's key never reaches another tenant or the client. -## Embedded LLM Gateway +## Models -The [Embedded LLM Gateway](/docs/llm-gateway) (coming soon) will remove the need to manage API keys manually. It routes all agent LLM requests through a managed proxy built into agentOS, providing per-tenant usage metering, rate limiting, and cost controls without deploying a separate gateway service. \ No newline at end of file +Model selection belongs to the configured agent adapter. AgentOS forwards the +session environment and preserves the agent's native model behavior instead of +introducing a second model-selection layer. See the page for your +[agent](/docs/agents/pi) for its supported model and provider options. \ No newline at end of file diff --git a/website/public/docs/docs/nodejs-runtime.md b/website/public/docs/docs/nodejs-runtime.md deleted file mode 100644 index 0a113689c6..0000000000 --- a/website/public/docs/docs/nodejs-runtime.md +++ /dev/null @@ -1,50 +0,0 @@ -# Node.js Runtime - -Run Node.js in agentOS: native V8 acceleration, the node CLI, installing packages, and Node.js compatibility. - -agentOS runs **Node.js** (`process.version` `v22.0.0`), fully isolated from the host. `node`, `npm`, and `npx` are on the `PATH`. - -## JavaScript Acceleration - -Normally, JavaScript running inside WebAssembly is exceptionally slow. In agentOS, JavaScript runs inside a native V8 isolate (powered by [Secure Exec](https://secureexec.dev)) for native runtime speeds: - -- **Native V8 speed, no overhead** — guest JS runs on V8's full JIT, not a WASM translation layer. -- **Lower memory than a Node.js process** — each agent is a V8 isolate, not a full process, so many fit where process-per-agent fits a handful. See [benchmarks](https://secureexec.dev/docs/benchmarks). - -## Running Node - -```ts -await agent.exec('node -e "console.log(1 + 1)"'); // inline -await agent.exec("node /workspace/main.js a b"); // script + argv -await agent.exec("npx tsx script.ts"); // npx -await agent.exec('echo "console.log(42)" | node'); // stdin -``` - -`node` works directly (`exec` / `execArgv` / `spawn`), through the guest shell (`sh -c`, pipes), and as a REPL. - -## Installing packages - -### Ahead of time - -Mount a host `node_modules` tree — projected read-only at `/root/node_modules` and resolved exactly like Node.js (ancestor walk, `package.json` `exports`/`imports`, symlinks — so pnpm/yarn layouts work), for both `import` and `require`: - -```ts -import { agentOS, setup, nodeModulesMount } from "@rivet-dev/agentos"; - -const vm = agentOS({ - mounts: [nodeModulesMount("/absolute/path/to/node_modules")], -}); -``` - -### At runtime - -Or install in the VM mid-task: - -```ts -await agent.exec("npm install chalk"); -await agent.exec("node /workspace/app.js"); // app.js: require("chalk") -``` - -## Node.js compatibility - -Guest code runs as Node.js v22, isolated from the host. `node:` builtins — `fs`, `net`, `http`, `crypto`, undici-backed `fetch`, and more — are provided by the runtime, never the host's. See the full [Node.js Compatibility](https://secureexec.dev/docs/nodejs-compatibility) matrix. \ No newline at end of file diff --git a/website/public/docs/docs/benchmarks.md b/website/public/docs/docs/performance.md similarity index 88% rename from website/public/docs/docs/benchmarks.md rename to website/public/docs/docs/performance.md index d23f4fce2e..805273df65 100644 --- a/website/public/docs/docs/benchmarks.md +++ b/website/public/docs/docs/performance.md @@ -1,8 +1,11 @@ -# Benchmarks +# Performance -Performance benchmarks comparing agentOS to traditional sandbox providers. +AgentOS latency, memory, cost, and benchmark methodology. -These are the benchmark figures shown on the agentOS marketing page. All numbers are computed from the same data source used by the marketing page. For independent sandbox comparison data, see the [ComputeSDK benchmarks](https://www.computesdk.com/benchmarks/). +These are the benchmark figures shown on the agentOS marketing page. All +numbers are computed from the same data source used by the marketing page. Use +the methodology below to measure the workload and hardware you will actually +deploy. ## Cold start @@ -68,6 +71,21 @@ Sandbox baseline: **Daytona** at $0.0504/vCPU-h + $0.0162/GiB-h with a 1 vCPU + | Hetzner ARM | $0.000000011/s | $0.000018/s | 1738x cheaper | | Hetzner x86 | $0.000000017/s | $0.000018/s | 1061x cheaper | +## Evaluating your own cost + +AgentOS runs on hardware you provision instead of billing per VM-second. To +estimate your workload, divide the instance's cost per second by the number of +concurrent VMs it can hold with realistic memory and utilization headroom. + +The result depends on workload size and lifecycle. A VM per task or tenant gives +the strongest isolation, while safely reusing a VM for trusted sequential work +amortizes boot and filesystem setup. Small, short executions benefit most from +dense packing; heavyweight, long-lived work depends more on hardware choice and +avoiding per-sandbox minimums. + +Provider prices, instance prices, and workload memory change. Measure +on your target hardware before quoting a cost ratio. + ## Test environment | Component | Details | diff --git a/website/public/docs/docs/python-runtime.md b/website/public/docs/docs/python-runtime.md deleted file mode 100644 index 8c551e8d36..0000000000 --- a/website/public/docs/docs/python-runtime.md +++ /dev/null @@ -1,62 +0,0 @@ -# Python Runtime - -Run Python in agentOS: the python CLI, installing packages ahead of time or at runtime, and what's supported. - -agentOS runs **CPython 3.13** as a first-class runtime. `python` and `python3` are on the `PATH` and plug into the VM's filesystem, processes, and network — agents use them like any other command. - -## Running Python - -```ts -await agent.exec('python -c "print(1 + 1)"'); // inline -await agent.exec("python /workspace/main.py a b"); // script + sys.argv -await agent.exec("python -m http.server 8000"); // module -await agent.exec('echo "print(40 + 2)" | python -'); // stdin -``` - -`python` works directly (`exec` / `execArgv` / `spawn`), through the guest shell (`sh -c`, pipes), and as an interactive REPL. - -## Installing packages - -`pip install` writes to a persistent spot on the VM filesystem, so a package installed once is importable by every later `python` run in that VM. - -### Ahead of time - -Install once during setup so the agent starts ready — no install cost mid-task: - -```ts -// one-off setup pass on the VM, before handing it to the agent -await agent.exec("pip install requests pandas"); -// requests + pandas now import in every python run on this VM -``` - -### At runtime - -Or let the agent install what it needs, mid-task: - -```ts -await agent.exec("pip install rich"); -await agent.exec('python -c "import rich; print(rich.__version__)"'); -``` - -`pip install ` and `python -m pip install ` both work; downloads obey the VM's network policy (default-deny + allowlist). - -## Compatibility - -CPython 3.13 and the standard library, with a few VM-shaped differences. - -### Supported - -- Full VM filesystem (`/tmp`, `/etc`, `/root`, …) — shared with other processes and `readFile()` -- Reading, writing, creating, deleting, and renaming files anywhere on the VM, plus symlinks and file metadata (`os.symlink` / `os.readlink` / `os.chmod` / `os.chown` / `os.utime`) -- A real process in the tree: stdin/stdout/stderr, signals, `kill` -- `subprocess` launching other VM commands (`node`, etc.) -- Pure-Python packages, plus native packages with a prebuilt wheel — `numpy`, `pandas`, `scipy`, `scikit-learn`, `pydantic`, `cryptography`, `Pillow`, and [many more](https://pyodide.org/en/stable/usage/packages-in-pyodide.html) -- `requests`, `urllib`, and `pip` over HTTP/DNS, under the VM network policy -- Outbound raw TCP and UDP sockets (the `socket` module), under the VM network policy - -### Unsupported - -- OS threads and `multiprocessing` — the runtime is single-threaded -- `os.fork` / `os.exec` -- Some packages with native (C/Rust) extensions — see the [full list of supported packages](https://pyodide.org/en/stable/usage/packages-in-pyodide.html) -- Socket servers / listeners (`bind`/`listen`/`accept`) — outbound connections only \ No newline at end of file diff --git a/website/public/docs/docs/quickstart.md b/website/public/docs/docs/quickstart.md index 6079271c04..ad39fc3c94 100644 --- a/website/public/docs/docs/quickstart.md +++ b/website/public/docs/docs/quickstart.md @@ -49,18 +49,19 @@ Set up an agentOS actor, create a session, and run your first coding agent. - **[Software](/docs/software)** — Install software packages inside the VM - **[Filesystem](/docs/filesystem)** — Read, write, and manage files inside the VM - **[Permissions & Resource Limits](/docs/permissions)** — Gate what the agent can do and cap its resource usage - - **[Bindings](/docs/bindings)** — Expose your JavaScript functions to agents as CLI commands + - **[Custom Bindings](/docs/extensions/custom-bindings)** — Expose your JavaScript functions to agents as CLI commands 5. **Deploy** By default, agentOS runs locally with `npx rivetkit dev` — no infrastructure needed. To run in production, deploy to any of these targets: - See [Deployment](/docs/deployment) for managed, self-hosted, and agentOS Core options. + See [Deployment](/docs/deployment) for managed, self-hosted, and direct VM options. agentOS is in preview and the API is subject to change. If you run into issues, please [report them on GitHub](https://github.com/rivet-dev/rivet/issues) or [join our Discord](https://rivet.dev/discord). -## agentOS Core +## Direct VM API -The quickstart above uses `@rivet-dev/agentos`, which includes statefulness, multiplayer, and orchestration out of the box. If you only need direct VM control without those features, you can use the core package (`@rivet-dev/agentos-core`) standalone. +The same `@rivet-dev/agentos` package also exports `AgentOs.create()` for direct +VM control without the actor lifecycle, multiplayer, or orchestration layer. -See [agentOS core documentation](/docs/core) for reference. \ No newline at end of file +See the [direct VM API documentation](/docs/core) for reference. \ No newline at end of file diff --git a/website/public/docs/docs/security-model.md b/website/public/docs/docs/security-model.md index 33d3550123..be7f6b55e0 100644 --- a/website/public/docs/docs/security-model.md +++ b/website/public/docs/docs/security-model.md @@ -110,7 +110,7 @@ Every guest syscall is mediated by the kernel and checked against the runtime's - **Processes.** `node:child_process` spawns kernel-managed guest processes, never real host processes. Children can only run the commands the VM mounts (WASM-backed `sh` and coreutils, V8-backed `node`). See [Processes](/docs/processes). - **Network.** Guest `fetch()`, `node:http`, and raw sockets all flow through the kernel socket table. Guest `fetch()` runs through undici inside the isolate and then through the kernel socket table; it never opens a real host socket. See [Networking](/docs/networking). - **DNS, pipes, and PTYs** are likewise kernel-owned: no guest path reaches the host directly. -- **Bindings.** Registered [bindings](/docs/bindings) are the only sanctioned way to hand the guest a named host capability. The guest invokes a binding by name with JSON input, the call round-trips to the host handler, and only the handler's return value comes back. The guest never receives the underlying host access. +- **Bindings.** Registered [custom bindings](/docs/extensions/custom-bindings) are the only sanctioned way to hand the guest a named host capability. The guest invokes a binding by name with JSON input, the call round-trips to the host handler, and only the handler's return value comes back. The guest never receives the underlying host access. ## What enters the VM @@ -159,7 +159,7 @@ The boundary protects the host from the guest. It does **not** harden your host - Hardening the host process and deployment environment. For internet-facing workloads that take untrusted input, run your host inside an already-hardened environment (for example AWS Lambda, Google Cloud Run, or a similar sandboxed platform). - Validating authentication tokens in `onBeforeConnect`. - Scoping [permissions](/docs/permissions) appropriately for your use case. -- Managing API keys and secrets on the host side (use the [LLM gateway](/docs/llm-gateway) to avoid passing keys into the VM). +- Managing API keys and secrets on the host side (see [Models & Credentials](/docs/models-and-credentials)). - Configuring [resource limits and network controls](/docs/security-model) to match your threat model. - Choosing your blast radius: prefer a fresh VM per untrusted or high-risk task so an escape attempt cannot outlive a single VM. diff --git a/website/public/docs/docs/sessions.md b/website/public/docs/docs/sessions.md index ef990646d0..a938644859 100644 --- a/website/public/docs/docs/sessions.md +++ b/website/public/docs/docs/sessions.md @@ -10,6 +10,18 @@ AgentOS sessions are durable records backed by the VM's SQLite database. The pub The input supports `agent`, `cwd`, `additionalDirectories`, `env`, `mcpServers`, `permissionPolicy`, `skipOsInstructions`, and `additionalInstructions`. Omitted `cwd` defaults to `/home/agentos` in the sidecar. Actor deployments inject their SQLite UDS database automatically. Standalone core clients must configure a VM SQLite file or UDS descriptor. +## MCP servers + +MCP configuration belongs to the session because its tools are part of the +agent's runtime context. Configure local child-process servers or remote servers +before opening the session. The exact config path and supported transports come +from the selected agent adapter; for example, Pi reads `.mcp.json` from its +AgentOS home directory: + +Install local MCP server packages before opening the session so first-run +package-manager output cannot corrupt a stdio handshake. See the selected +[agent guide](/docs/agents/pi) for adapter-specific configuration. + ## Prompt `prompt` accepts native ACP `ContentBlock[]`, not a special AgentOS text format. It never creates a missing session. AgentOS commits the complete user message before dispatching it and never automatically replays a prompt whose delivery may have reached the adapter. @@ -44,7 +56,7 @@ ACP itself does not define a portable history-reading API, and adapters implemen `permissionPolicy` is `reject_all`, `ask`, or `allow_all`, and defaults to `allow_all`. It controls how AgentOS answers native ACP permission requests; it does not configure VM permissions or adapter tool access. Set `permissionPolicy: "ask"` when opening the session before subscribing for interactive decisions; subscribing alone does not change the immutable policy. With `ask`, AgentOS durably records the native ACP `RequestPermissionRequest` as a `permission_request` variant in the generic session-event stream. With the default `allow_all`, AgentOS resolves the adapter request automatically and emits no permission event. Reply to an `ask` request with the exact adapter-supplied `optionId` and an explicit public session ID: ```ts -await agent.respondPermission({ +await agent.sessions.respondPermission({ sessionId: request.sessionId, requestId: request.requestId, optionId: request.options[0].optionId, diff --git a/website/public/docs/docs/software.md b/website/public/docs/docs/software.md index 79abcd8b3b..19edcafb48 100644 --- a/website/public/docs/docs/software.md +++ b/website/public/docs/docs/software.md @@ -22,4 +22,4 @@ Browse all available software packages on the [Registry](/registry). ## Custom Software -Package your own agents, command packages, and WASM commands. See [Software Definition](/docs/custom-software/definition) to define a package, and [Building Binaries](/docs/custom-software/building-wasm) to compile WASM commands from source in the [secure-exec registry](https://github.com/rivet-dev/secure-exec/tree/main/registry). \ No newline at end of file +Package your own agents, command packages, and WASM commands. See [Software Definition](/docs/custom-software/definition) to define a package, and [Building Binaries](/docs/custom-software/building-wasm) to compile WASM commands from source in the [agentos registry](https://github.com/rivet-dev/agentos/tree/main/registry). \ No newline at end of file diff --git a/website/public/docs/docs/versus-sandbox.md b/website/public/docs/docs/versus-sandbox.md index 062161ae53..6921832d72 100644 --- a/website/public/docs/docs/versus-sandbox.md +++ b/website/public/docs/docs/versus-sandbox.md @@ -2,9 +2,9 @@ When to use the lightweight agentOS VM, a full sandbox, or both together. -- **agentOS** is a lightweight VM that runs inside your process. Near-zero cold start, low memory, direct backend integration via [bindings](/docs/bindings). +- **agentOS** is a lightweight VM that runs inside your process. Near-zero cold start, low memory, direct backend integration via [custom bindings](/docs/extensions/custom-bindings). - **Sandboxes** are full Linux environments with root access, system packages, and native binary support. -- **You can use both.** agentOS works with sandboxes through [sandbox mounting](/docs/sandbox). Agents run in the lightweight VM by default and spin up a full sandbox on demand. +- **You can use both.** agentOS works with sandboxes through the [external sandbox extension](/docs/extensions/sandboxes). Agents run in the lightweight VM by default and spin up a full sandbox on demand. ## Comparison @@ -12,8 +12,8 @@ When to use the lightweight agentOS VM, a full sandbox, or both together. |---|---|---| | **Cost** | Very low. Runs in your process. | Pay per second of uptime. | | **Startup** | Near-zero cold start (~6 ms). | Seconds to spin up. | -| **Backend integration** | Direct. [Bindings](/docs/bindings) call your functions with zero latency. | Indirect. Requires network calls back to your backend. | -| **Credentials** | Stay on the host. [Bindings](/docs/bindings) run your functions server-side; agents see only inputs and outputs. | Must be injected into the sandbox environment. | +| **Backend integration** | Direct. [Custom bindings](/docs/extensions/custom-bindings) call your functions with zero latency. | Indirect. Requires network calls back to your backend. | +| **Credentials** | Stay on the host. [Custom bindings](/docs/extensions/custom-bindings) run your functions server-side; agents see only inputs and outputs. | Must be injected into the sandbox environment. | | **Permissions** | Granular, deny-by-default. | Coarse-grained (container-level). | | **Infrastructure** | `npm install` | Vendor account + API keys. | | **Best for** | Coding, file manipulation, scripting, API calls, orchestration. | Browsers, desktop automation, native compilation, dev servers. | @@ -41,7 +41,7 @@ Spin up a sandbox when the workload needs a real Linux kernel: ### Both together -Use agentOS with [sandbox mounting](/docs/sandbox) for workflows that need both: +Use agentOS with [external sandboxes](/docs/extensions/sandboxes) for workflows that need both: - Agent runs in the agentOS VM with full access to bindings and permissions - Sandbox spins up on demand for heavy tasks diff --git a/website/public/docs/docs/webhooks.md b/website/public/docs/docs/webhooks.md deleted file mode 100644 index 350ad55a45..0000000000 --- a/website/public/docs/docs/webhooks.md +++ /dev/null @@ -1,21 +0,0 @@ -# Webhooks - -Trigger agent sessions directly from external webhooks using Hono. - -Use a lightweight HTTP server to receive webhooks and drive an agent. This example uses [Hono](https://hono.dev) to receive Slack webhooks and call an agent directly. - -## Example: Slack webhook to agent - -## How it works - -1. Slack sends an HTTP POST to `/slack/events` -2. The Hono handler validates the event and prompts one durable AgentOS session -3. AgentOS automatically serializes concurrent prompts targeting that session -4. The handler posts the response back to Slack - -No application queue is needed for prompt ordering. Durable session history remains in SQLite, but AgentOS never automatically replays a prompt whose delivery was uncertain. - -## Recommendations - -- The direct example waits for the turn. If the provider requires an immediate `200`, use the hosting platform's durable background-task primitive and call AgentOS from that task. -- Store webhook secrets in environment variables, not in code. \ No newline at end of file diff --git a/website/public/docs/docs/workflows.md b/website/public/docs/docs/workflows.md index 1cab1ed0a6..84eb098e85 100644 --- a/website/public/docs/docs/workflows.md +++ b/website/public/docs/docs/workflows.md @@ -1,4 +1,4 @@ -# Workflow Automation +# Workflows & Graphs Orchestrate multi-step agent tasks with durable workflows. diff --git a/website/public/secure-exec-logo-long.svg b/website/public/secure-exec-logo-long.svg deleted file mode 100644 index cd27d6b8b2..0000000000 --- a/website/public/secure-exec-logo-long.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/website/public/secure-exec-logo.png b/website/public/secure-exec-logo.png deleted file mode 100644 index 564c5d52e1..0000000000 Binary files a/website/public/secure-exec-logo.png and /dev/null differ diff --git a/website/public/secure-exec-logo.svg b/website/public/secure-exec-logo.svg deleted file mode 100644 index d7119e8854..0000000000 --- a/website/public/secure-exec-logo.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/website/src/components/GitHubStars.tsx b/website/src/components/GitHubStars.tsx index afe86190f3..b8b7a24459 100644 --- a/website/src/components/GitHubStars.tsx +++ b/website/src/components/GitHubStars.tsx @@ -13,7 +13,7 @@ function formatNumber(num: number): string { return num.toString(); } -export function GitHubStars({ repo = "rivet-dev/secure-exec", className, ...props }: GitHubStarsProps) { +export function GitHubStars({ repo = "rivet-dev/agentos", className, ...props }: GitHubStarsProps) { const [stars, setStars] = useState(null); useEffect(() => { diff --git a/website/src/components/marketing/diagrams/AgentSessionDemo.tsx b/website/src/components/marketing/diagrams/AgentSessionDemo.tsx index a1cf3708fe..3a89b545fe 100644 --- a/website/src/components/marketing/diagrams/AgentSessionDemo.tsx +++ b/website/src/components/marketing/diagrams/AgentSessionDemo.tsx @@ -202,7 +202,7 @@ const TABS: SessionTab[] = [ key: 'nodejs', title: 'Node.js', description: 'Node v22 compatible, running on WASM. node, npm, and npx on the PATH.', - docsHref: '/docs/nodejs-runtime', + docsHref: '/docs/execution/javascript', docsLabel: 'Node.js runtime docs', iconSrc: '/images/registry/nodejs.svg', script: { fileName: 'report.mjs', lang: 'js', code: REPORT_JS }, @@ -213,7 +213,7 @@ const TABS: SessionTab[] = [ key: 'python', title: 'Python', description: 'CPython 3.13 with pip. Native wheels like numpy and pandas work.', - docsHref: '/docs/python-runtime', + docsHref: '/docs/execution/python', docsLabel: 'Python runtime docs', iconSrc: 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Python-logo.png/120px-Python-logo.png', script: { fileName: 'report.py', lang: 'python', code: REPORT_PY }, diff --git a/website/src/components/marketing/solutions/AgentOSPage.tsx b/website/src/components/marketing/solutions/AgentOSPage.tsx index 5c659ac531..d841b1a31e 100644 --- a/website/src/components/marketing/solutions/AgentOSPage.tsx +++ b/website/src/components/marketing/solutions/AgentOSPage.tsx @@ -1130,13 +1130,6 @@ const ExecutionSection = () => ( - {/* agentOS Exec callout intentionally hidden until the standalone execution product is ready. */} - {/* - - */}
@@ -1940,7 +1933,7 @@ function RuntimeBenchInfo({ {detail.label} {detail.text} ))} - + Methodology & reproduction → @@ -2176,7 +2169,7 @@ const secondaryFeatures = [ icon: Wrench, title: 'Bindings', description: 'Expose typed JavaScript functions as CLI tools while credentials remain on the host.', - docsHref: '/docs/bindings', + docsHref: '/docs/extensions/custom-bindings', }, { icon: ShieldCheck, @@ -2188,13 +2181,13 @@ const secondaryFeatures = [ icon: Package, title: 'Sandbox mounting', description: 'Mount a full Linux sandbox only when native binaries or heavy compilation need one.', - docsHref: '/docs/sandbox', + docsHref: '/docs/extensions/sandboxes', }, { icon: AppWindow, title: 'Browsers', description: 'Connect agents to serverless browser providers like Browserbase without running a browser inside the VM.', - docsHref: '/docs/browser', + docsHref: '/docs/extensions/browser', }, { icon: ChartNoAxesCombined, @@ -2363,7 +2356,7 @@ const BenchmarksSection = () => { What staying in-process saves. Benchmark document diff --git a/website/src/content/docs/docs/agent-to-agent.mdx b/website/src/content/docs/docs/agent-to-agent.mdx index 9f964103a1..a25ede4465 100644 --- a/website/src/content/docs/docs/agent-to-agent.mdx +++ b/website/src/content/docs/docs/agent-to-agent.mdx @@ -4,7 +4,7 @@ description: "Use bindings to let agents communicate with each other." skill: true --- -Agents communicate through [bindings](/docs/bindings). You define a bindings group that lets one agent send work to another, and the agent calls it like any other CLI command. +Agents communicate through [custom bindings](/docs/extensions/custom-bindings). You define a bindings group that lets one agent send work to another, and the agent calls it like any other CLI command. ## Example: code writer + reviewer diff --git a/website/src/content/docs/docs/agents/claude.mdx b/website/src/content/docs/docs/agents/claude.mdx index 1862db52a2..aa0181b2d8 100644 --- a/website/src/content/docs/docs/agents/claude.mdx +++ b/website/src/content/docs/docs/agents/claude.mdx @@ -14,7 +14,7 @@ skill: false Read [Sessions](/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. -## LLM Credentials +## Model & credentials Set the relevant variable(s) on the session's `env`, sourced from your server's environment: @@ -25,7 +25,7 @@ Set the relevant variable(s) on the session's `env`, sourced from your server's - `CLAUDE_CODE_USE_BEDROCK=1` — use Amazon Bedrock (auth via the AWS credential chain: `AWS_REGION`, `AWS_PROFILE`, …). - `CLAUDE_CODE_USE_VERTEX=1` — use Google Vertex AI (auth via Google Cloud credentials). -See [LLM Credentials](/docs/llm-credentials), and Claude Code's [environment variables](https://code.claude.com/docs/en/env-vars) for the full list. +See [Models & Credentials](/docs/models-and-credentials), and Claude Code's [environment variables](https://code.claude.com/docs/en/env-vars) for the full list. ## Skills @@ -40,7 +40,7 @@ Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both l -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. +**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. ## Customizing the agent diff --git a/website/src/content/docs/docs/agents/codex.mdx b/website/src/content/docs/docs/agents/codex.mdx index 4072b98043..852af14ee0 100644 --- a/website/src/content/docs/docs/agents/codex.mdx +++ b/website/src/content/docs/docs/agents/codex.mdx @@ -13,7 +13,7 @@ skill: false Read [Sessions](/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. -## LLM Credentials +## Model & credentials Set the relevant variable(s) on the session's `env`, sourced from your server's environment: @@ -21,7 +21,7 @@ Set the relevant variable(s) on the session's `env`, sourced from your server's - `OPENAI_BASE_URL` — route through a gateway or OpenAI-compatible endpoint. - Custom providers — defined in `~/.codex/config.toml`; each provider's `env_key` names the variable Codex reads for its key (e.g. `AZURE_OPENAI_API_KEY`, `MISTRAL_API_KEY`). -See [LLM Credentials](/docs/llm-credentials), and Codex's [config reference](https://developers.openai.com/codex/config-reference) for details. +See [Models & Credentials](/docs/models-and-credentials), and Codex's [config reference](https://developers.openai.com/codex/config-reference) for details. ## Skills @@ -36,7 +36,7 @@ Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both l -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. +**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. ## Customizing the agent diff --git a/website/src/content/docs/docs/agents/opencode.mdx b/website/src/content/docs/docs/agents/opencode.mdx index 347dc8bcc1..857fc084d2 100644 --- a/website/src/content/docs/docs/agents/opencode.mdx +++ b/website/src/content/docs/docs/agents/opencode.mdx @@ -14,7 +14,7 @@ skill: false Read [Sessions](/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. -## LLM Credentials +## Model & credentials OpenCode auto-detects a provider when its key is present on the session's `env`, sourced from your server's environment. Common variables: @@ -25,7 +25,7 @@ OpenCode auto-detects a provider when its key is present on the session's `env`, - `GROQ_API_KEY` — Groq. - …plus Amazon Bedrock, Azure, Google Vertex, and 70+ providers via [models.dev](https://models.dev). -See [LLM Credentials](/docs/llm-credentials), and OpenCode's [providers docs](https://opencode.ai/docs/providers/) for the full list. +See [Models & Credentials](/docs/models-and-credentials), and OpenCode's [providers docs](https://opencode.ai/docs/providers/) for the full list. ## Model configuration @@ -39,8 +39,8 @@ Two settings will silently produce an **empty response** if wrong: ```ts // Write the config before creating the session -await agent.mkdir("/home/agentos/.config/opencode", { recursive: true }); -await agent.writeFile( +await agent.filesystem.mkdir("/home/agentos/.config/opencode", { recursive: true }); +await agent.filesystem.writeFile( "/home/agentos/.config/opencode/opencode.json", JSON.stringify({ $schema: "https://opencode.ai/config.json", @@ -52,7 +52,7 @@ await agent.writeFile( }), ); -await agent.openSession({ +await agent.sessions.open({ agent: "opencode", env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); @@ -71,7 +71,7 @@ Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both l -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. +**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. ## Customizing the agent diff --git a/website/src/content/docs/docs/agents/pi.mdx b/website/src/content/docs/docs/agents/pi.mdx index 2d15263b0b..dc9d49ebab 100644 --- a/website/src/content/docs/docs/agents/pi.mdx +++ b/website/src/content/docs/docs/agents/pi.mdx @@ -14,14 +14,14 @@ skill: true Read [Sessions](/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. -## LLM Credentials +## Model & credentials Set the relevant variable on the session's `env`, sourced from your server's environment: - `ANTHROPIC_API_KEY` — Anthropic (Claude), the default. - Other providers — use the provider-named key (e.g. `OPENAI_API_KEY`, `GEMINI_API_KEY`, `OPENROUTER_API_KEY`). -See [LLM Credentials](/docs/llm-credentials), and Pi's [providers docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/providers.md) for the full list. +See [Models & Credentials](/docs/models-and-credentials), and Pi's [providers docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/providers.md) for the full list. ## Skills @@ -36,7 +36,7 @@ Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both l -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. +**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. ## Extensions @@ -57,4 +57,3 @@ See the [Pi extension documentation](https://github.com/badlogic/pi-mono/tree/ma ## Customizing the agent Pi is a built-in agent, but it's just a software package under the hood. To ship your own ACP adapter, swap the underlying agent SDK, or register a tweaked Pi build as a new agent, see [Custom Agents](/docs/agents/custom). - diff --git a/website/src/content/docs/docs/architecture.mdx b/website/src/content/docs/docs/architecture.mdx index 5df952c5f4..0f153967c8 100644 --- a/website/src/content/docs/docs/architecture.mdx +++ b/website/src/content/docs/docs/architecture.mdx @@ -174,7 +174,7 @@ The kernel is the single chokepoint. Each kind of guest operation is serviced by The executor is the untrusted half of the VM. It runs the guest code and reaches the kernel for everything else. -- **JavaScript Acceleration.** Guest JavaScript runs on a native V8 runtime (the same engine in Chrome and Node.js, with the full JIT compiler) inside an isolate. This is what we call **JavaScript Acceleration**: the guest's JavaScript executes at native speed, not through an interpreter or a translation shim. It is genuinely fast, and it presents normal Node.js semantics. See [JavaScript Runtime](/docs/nodejs-runtime). +- **JavaScript Acceleration.** Guest JavaScript runs on a native V8 runtime (the same engine in Chrome and Node.js, with the full JIT compiler) inside an isolate. This is what we call **JavaScript Acceleration**: the guest's JavaScript executes at native speed, not through an interpreter or a translation shim. It is genuinely fast, and it presents normal Node.js semantics. See [JavaScript](/docs/execution/javascript). - **WASM alongside it.** The shell (`sh`) and the coreutils behind process execution ship as WebAssembly modules, and you can run your own WASM too. See [POSIX Syscalls](/docs/architecture/posix-syscalls) and the [Compiler Toolchain](/docs/architecture/compiler-toolchain). - **Native binaries.** Tools mounted into the VM run inside the same boundary as everything else. - **No host fallthrough.** The executor holds no capability of its own. For every file read, process spawn, or socket open, it issues a syscall and blocks for the kernel's reply. @@ -336,13 +336,13 @@ The `agentOS()` actor (from `@rivet-dev/agentos`) wraps the raw VM in a [Rivet A - **Recurring work.** Schedule a shell command or an agent session on a cron expression. - **Overlap control.** Choose what happens when a run is still going when the next is due (`allow`, `skip`, or `queue`). -- **Observable.** Stream `cronEvent`s to watch executions. See [Cron Jobs](/docs/cron). +- **Observable.** Stream `cronEvent`s to watch executions. See [Crons & Loops](/docs/cron). ### Workflows - **Durable multi-step tasks.** A workflow is the actor's `run` handler wrapped in `workflow()`, where each `ctx.step()` is recorded, retried, and resumed independently. - **Crash-proof.** If the process dies mid-run, replay skips completed steps and continues where it left off. -- **Composable.** The output of one step feeds the next: clone a repo, let an agent fix a bug, run the tests. See [Workflow Automation](/docs/workflows). +- **Composable.** The output of one step feeds the next: clone a repo, let an agent fix a bug, run the tests. See [Workflows & Graphs](/docs/workflows). ### Persistence & sleep/wake diff --git a/website/src/content/docs/docs/architecture/agent-sessions.mdx b/website/src/content/docs/docs/architecture/agent-sessions.mdx index 4b9705ac99..2b6681e8b6 100644 --- a/website/src/content/docs/docs/architecture/agent-sessions.mdx +++ b/website/src/content/docs/docs/architecture/agent-sessions.mdx @@ -30,7 +30,7 @@ The sidecar—not the actor or SDK—owns defaults and orchestration. TypeScript One prompt may run per session. Cancellation races are first-writer-wins. AgentOS does not automatically replay interrupted prompts because tool side effects may already have occurred. -The ACP runtime and core SDK transports impose no wall-clock deadline on prompts or human permission waits. After 30 seconds without ACP activity, AgentOS logs an inactivity warning with the total elapsed time and last observed activity, repeating every 30 seconds until activity resumes. Streaming output resets that interval. Bootstrap, teardown, filesystem, terminal, and other machine-to-machine operations retain bounded failure deadlines. Actor-hosted calls currently inherit RivetKit's maximum timer-safe action bound of about 24.8 days because RivetKit does not yet support an unbounded action. +The ACP runtime and AgentOS client transports impose no wall-clock deadline on prompts or human permission waits. After 30 seconds without ACP activity, AgentOS logs an inactivity warning with the total elapsed time and last observed activity, repeating every 30 seconds until activity resumes. Streaming output resets that interval. Bootstrap, teardown, filesystem, terminal, and other machine-to-machine operations retain bounded failure deadlines. Actor-hosted calls currently inherit RivetKit's maximum timer-safe action bound of about 24.8 days because RivetKit does not yet support an unbounded action. ## Reads versus adapter operations diff --git a/website/src/content/docs/docs/architecture/compiler-toolchain.mdx b/website/src/content/docs/docs/architecture/compiler-toolchain.mdx index 0187b61362..18010bf2d9 100644 --- a/website/src/content/docs/docs/architecture/compiler-toolchain.mdx +++ b/website/src/content/docs/docs/architecture/compiler-toolchain.mdx @@ -92,7 +92,7 @@ The same path is open to your own programs. A program you compile for `wasm32-wasip1` runs as a guest command exactly like the bundled ones; link the `wasi-ext` bindings if it needs processes, users, or sockets, and leave them out for a pure-compute tool. Heavy native binaries that are not yet available as -WASM belong in a [mounted sandbox](/docs/sandbox) instead. +WASM belong in an [external sandbox](/docs/extensions/sandboxes) instead. ## Recommendations diff --git a/website/src/content/docs/docs/architecture/javascript-executor.mdx b/website/src/content/docs/docs/architecture/javascript-executor.mdx index 89a0de62f0..018a421183 100644 --- a/website/src/content/docs/docs/architecture/javascript-executor.mdx +++ b/website/src/content/docs/docs/architecture/javascript-executor.mdx @@ -12,7 +12,7 @@ transport. For socket ownership, loopback, DNS, and network policy, see [Networking](/docs/architecture/networking). For the client-facing JavaScript -environment, see [JavaScript Runtime](/docs/js-runtime). +environment, see [JavaScript](/docs/execution/javascript). Tokio never invokes guest JavaScript from a runtime worker. A Tokio task stores diff --git a/website/src/content/docs/docs/architecture/packages-and-command-resolution.mdx b/website/src/content/docs/docs/architecture/packages-and-command-resolution.mdx index cc3135cfc4..1d4f3e1f85 100644 --- a/website/src/content/docs/docs/architecture/packages-and-command-resolution.mdx +++ b/website/src/content/docs/docs/architecture/packages-and-command-resolution.mdx @@ -91,7 +91,7 @@ is what the runtime **projects** from that package when it mounts it: | `share/` | FHS data — `share/man/man/*`, etc. | | `current` | Symlink `→ `; switching versions is one atomic rename. | -```jsonc +```json // package.json — commands come from "bin"; an agent's ACP entrypoint is just one of them { "name": "@agentos-software/pi", "version": "0.0.1", "bin": { "pi-acp": "dist/pi-acp.wasm" } } ``` diff --git a/website/src/content/docs/docs/architecture/processes.mdx b/website/src/content/docs/docs/architecture/processes.mdx index 0ae436ddbb..9c98235c1d 100644 --- a/website/src/content/docs/docs/architecture/processes.mdx +++ b/website/src/content/docs/docs/architecture/processes.mdx @@ -8,7 +8,7 @@ skill: true This page is an internals deep-dive on the kernel's **process model**: the data structures and syscall paths behind every guest process. For the client-facing -API (`exec`, `spawn`, `openShell`, lifecycle, the process tree), see +API (`process.exec`, `process.spawn`, `terminal.open`, lifecycle, the process tree), see [Processes & Shell](/docs/processes). For the surrounding component and trust model, see [Architecture](/docs/architecture). @@ -82,10 +82,10 @@ An interactive shell needs a terminal, not just piped stdio: line editing, job control signals, and window size all depend on a PTY. The kernel provides virtual PTY devices for this. -- **A shell is a process plus a PTY.** `openShell` allocates a kernel PTY and starts a shell process attached to it, returning a `shellId`. The PTY is a virtualized terminal device, never a host `/dev/pts` entry. -- **Bidirectional terminal I/O.** `writeShell` feeds keystrokes into the PTY master side; everything the shell and its children emit comes back as `shellData` events. This carries terminal control sequences, so full-screen TUIs behave correctly. -- **Resize is a terminal operation.** `resizeShell` updates the PTY's window size (columns and rows), which the kernel propagates to the foreground process the way a real terminal resize would, so programs relying on `TIOCGWINSZ`-style sizing redraw correctly. -- **Teardown.** `closeShell` tears down the PTY and the attached shell process. An open shell keeps the VM active, the same way an open PTY keeps a session alive on a real system. +- **A shell is a process plus a PTY.** `terminal.open` allocates a kernel PTY and starts a shell process attached to it, returning a `shellId`. The PTY is a virtualized terminal device, never a host `/dev/pts` entry. +- **Bidirectional terminal I/O.** `terminal.write` feeds keystrokes into the PTY master side; everything the shell and its children emit comes back as `shellData` events. This carries terminal control sequences, so full-screen TUIs behave correctly. +- **Resize is a terminal operation.** `terminal.resize` updates the PTY's window size (columns and rows), which the kernel propagates to the foreground process the way a real terminal resize would, so programs relying on `TIOCGWINSZ`-style sizing redraw correctly. +- **Teardown.** `terminal.close` tears down the PTY and the attached shell process. An open shell keeps the VM active, the same way an open PTY keeps a session alive on a real system. ## WASM sh and coreutils on the process model diff --git a/website/src/content/docs/docs/core.mdx b/website/src/content/docs/docs/core.mdx index e66f826e33..a2374a2929 100644 --- a/website/src/content/docs/docs/core.mdx +++ b/website/src/content/docs/docs/core.mdx @@ -1,14 +1,15 @@ --- -title: "Core Package" -description: "Use @rivet-dev/agentos-core standalone for direct VM control without the Rivet Actor runtime." +title: "Direct VM API" +description: "Use the direct AgentOS VM API or layer it into an AgentOS actor." skill: true --- -## agentOS vs agentOS Core +## Direct VM vs actor -The `agentOS()` actor (from `@rivet-dev/agentos`) wraps the core package and adds: +`@rivet-dev/agentos` includes both the direct `AgentOs` VM API and the +`agentOS()` actor API: -| | Core (`@rivet-dev/agentos-core`) | Actor (`@rivet-dev/agentos`) | +| | Direct VM | Actor | |-|---|---| | Persistence | In-memory by default (pluggable via [mounts](#mounts)) | Persistent filesystem and sessions | | Distributed state | Manage yourself | Built-in distributed statefulness | @@ -21,16 +22,16 @@ The `agentOS()` actor (from `@rivet-dev/agentos`) wraps the core package and add | Agent-to-agent communication | Custom | Built into [Rivet Actors](/docs/agent-to-agent) | | Authentication | Set up yourself | [Documentation](/docs/authentication) | -We recommend using [Rivet Actors](https://rivet.dev/docs/actors) because they provide a portable way to run `agentOS()` on any infrastructure with built-in persistence, networking, and orchestration. Use the core package if you need the most bare-bones implementation possible. +We recommend using [Rivet Actors](https://rivet.dev/docs/actors) when you need persistence, networking, and orchestration. Use `AgentOs.create()` from the same package when you need direct VM control in a Node.js process. -`agentOS()` returns an ordinary TypeScript Rivet actor definition. Its config accepts the core VM options together with normal actor state, actions, events, queues, connection types, and lifecycle hooks such as `onBeforeConnect`. AgentOS actions and events are merged in automatically; their names are reserved so they cannot be accidentally shadowed. After a wake, the actor creates the core SDK VM lazily on the first AgentOS action and disposes it on sleep. This lets a connection subscribe before the `vmBooted` event is emitted. +`agentOS()` returns an ordinary TypeScript Rivet actor definition. Its config accepts the VM options together with normal actor state, actions, events, queues, connection types, and lifecycle hooks such as `onBeforeConnect`. AgentOS actions and events are merged in automatically; their names are reserved so they cannot be accidentally shadowed. After a wake, the actor creates its VM lazily on the first AgentOS action and disposes it on sleep. This lets a connection subscribe before the `vmBooted` event is emitted. Creation input is inferred from the actor definition and is passed through normal client creation options: `client.vm.create("key", { input })`. The same input reaches `createState(c, input)` and `onCreate(c, input)`. ## Install ```bash -npm install @rivet-dev/agentos-core +npm install @rivet-dev/agentos ``` ## Boot a VM @@ -41,11 +42,11 @@ Create a VM and drive it directly — no actor runtime, no client/server split. ## Sidecar process -Every VM runs inside a **shared sidecar process** rather than a process of its own. By default all VMs are tenants of a single, process-global sidecar (the `default` pool), so each additional VM only adds its marginal cost — a V8 isolate plus its kernel state — instead of a whole OS process. This is what keeps per-VM memory in the tens of MB and warm VM creation in the single-digit milliseconds (see [Benchmarks](/docs/benchmarks)). +Every VM runs inside a **shared sidecar process** rather than a process of its own. By default all VMs are tenants of a single, process-global sidecar (the `default` pool), so each additional VM only adds its marginal cost — a V8 isolate plus its kernel state — instead of a whole OS process. This is what keeps per-VM memory in the tens of MB and warm VM creation in the single-digit milliseconds (see [Performance](/docs/performance)). This is automatic — `agentOS()` and `AgentOs.create()` use the shared default sidecar with no configuration, and the same applies to Rivet Actors (each actor's VM is a tenant of the shared process). Disposing a VM tears down only that VM; the shared sidecar process is reused across VMs and stays alive for the lifetime of the host process. -For advanced cases the core package exposes explicit sidecar handles so you can isolate a group of VMs in their own process: +For advanced cases the direct VM API exposes explicit sidecar handles so you can isolate a group of VMs in their own process: @@ -98,10 +99,10 @@ The top-level fields are documented inline above. See [Mounts](#mounts) and [Sof ### Session events -With the core package, `onSessionEvent` receives a generic union containing exact native ACP `SessionUpdate`, `RequestPermissionRequest`, and `RequestPermissionResponse` payloads wrapped with AgentOS durability metadata. Register it before prompting. On reconnect, also read durable history after your last sequence and deduplicate by `(sessionId, sequence)`: +With the direct VM API, `onSessionEvent` receives a generic union containing exact native ACP `SessionUpdate`, `RequestPermissionRequest`, and `RequestPermissionResponse` payloads wrapped with AgentOS durability metadata. Register it before prompting. On reconnect, also read durable history after your last sequence and deduplicate by `(sessionId, sequence)`: ### Timeouts and sleep -Action timeouts and automatic sleep/wake are features of the [`agentOS()` actor](/docs/quickstart), not the core package. A core VM stays alive until you call `dispose()`. See [Persistence & Sleep](/docs/persistence) for the actor's sleep lifecycle. +Action timeouts and automatic sleep/wake are features of the [`agentOS()` actor](/docs/quickstart), not the direct VM API. A direct VM stays alive until you call `dispose()`. See [Persistence & Sleep](/docs/persistence) for the actor's sleep lifecycle. diff --git a/website/src/content/docs/docs/cost-evaluation.mdx b/website/src/content/docs/docs/cost-evaluation.mdx deleted file mode 100644 index 386b500520..0000000000 --- a/website/src/content/docs/docs/cost-evaluation.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Cost Evaluation" -description: "How agentOS compares on cost to per-second sandbox providers when you run coding-agent VMs on your own hardware." -skill: true ---- - -agentOS is a library you run on hardware you already control, not a metered service. That changes the cost model for running coding-agent VMs from "pay a provider per sandbox-second" to "pay for the compute you provision, then pack as much work onto it as it can hold." This page explains where the savings come from and how to reason about them honestly. It does not publish a single magic multiplier, because the real number depends on your workload, your hardware, and how you share VMs. - -For measured latency (cold start, warm execution, and reuse fast paths), see [Benchmarks](/docs/benchmarks). This page is about cost structure, not raw performance. - -## Where the savings come from - -Two structural differences drive the cost gap versus per-second sandbox providers: - -- **You run on your own hardware**: you choose the cloud, instance type, architecture, and region. A small commodity instance (for example an ARM VM from a budget host) costs a flat hourly or monthly rate that is typically far below what per-sandbox-second billing adds up to once you have steady agent traffic. You also avoid egress fees and vendor lock-in. -- **You decide the isolation granularity**: sandbox providers bill a full container or microVM per execution, usually with a minimum memory reservation that you pay for even when your code uses a fraction of it. With agentOS you own the VM lifecycle: you can dedicate a VM per tenant or per task for maximum isolation, or amortize setup by reusing one VM across many runs. - -## The isolation model matters for cost - -Each `AgentOs.create()` boots a fully virtualized VM, and each `exec()` / `run()` inside it is a fresh guest process. That gives you a dial between isolation and density: - -- **One VM per task or tenant (strongest isolation)**: create a VM, run the work, and dispose it, or give each tenant its own VM. Each VM is its own crash and resource domain, with the highest per-VM overhead. Best when load is untrusted or bursty. -- **A shared VM for trusted work**: reuse one VM across many runs to amortize the VM boot cost. Each `exec()` / `run()` still executes in a fresh guest process, so in-memory state does not leak between runs, but the VM and filesystem are shared. Good for trusted, sequential work. - -The denser you can safely pack agent work onto an instance, the lower your effective cost per execution. See [Resource Limits](/docs/resource-limits) for the per-VM caps that govern how densely you can pack, and [Processes & Shell](/docs/processes) for how guest processes run inside a VM. - -## How to estimate your own cost - -Because agentOS runs on hardware you provision, the honest way to compare is to plug in your own numbers: - -1. **Pick your hardware and its rate**: take the hourly or monthly price of the instance you would run on, and divide down to a per-second instance cost. -2. **Estimate how many concurrent VMs fit**: measure per-VM memory overhead on your target hardware under your isolation strategy, then divide your usable RAM by that figure. Leave headroom (the measurement and any orchestration layer will not bin-pack perfectly). -3. **Divide instance cost by concurrent VMs**: that gives a cost-per-VM-second you can compare against a provider's per-sandbox-second rate. - -Measure on the hardware and isolation strategy you will actually deploy. Per-VM overhead depends on whether you create a fresh VM per task or reuse one across runs, and on the work the agent does, so a number measured on one machine will not transfer cleanly to another. - -## Comparing against sandbox providers - -When you do compare against a per-second sandbox provider, hold the methodology honest: - -- **Sandbox cost** is the provider's minimum allocatable memory times their per-GiB-second rate (plus any egress and platform fees). The minimum reservation is the floor you pay even for tiny workloads. -- **agentOS cost** is your instance cost per second divided by the number of VMs you can keep live on it, with realistic headroom for bin-packing inefficiency. - -The advantage is largest for **many small, short executions**, where a per-sandbox minimum reservation dominates and your own hardware lets you pack densely. It narrows for **heavyweight, long-lived workloads** (for example dev servers that need hundreds of megabytes regardless), where the win shifts from density to hardware choice: you still avoid per-second metering, egress fees, and lock-in, but the raw memory-density advantage is smaller. - -| Workload | Primary cost advantage | -| --- | --- | -| Many small, short executions | Density: pack many VMs per instance, no per-sandbox minimum | -| Heavyweight, long-lived workloads | Hardware choice, flat instance pricing, no egress or lock-in | -| High concurrency | Reuse a VM across runs to amortize VM boot cost | - -Be careful generalizing cost ratios from a single benchmark. Provider pricing, instance pricing, and exchange rates change over time, and per-VM overhead varies by workload and isolation strategy. Re-measure on your own hardware before quoting a number. - -When you do need a full Linux sandbox for heavier agent workloads, see [agentOS vs Sandbox](/docs/versus-sandbox) for how the two models combine. diff --git a/website/src/content/docs/docs/crash-course.mdx b/website/src/content/docs/docs/crash-course.mdx index f02fc4a326..e3105b5cef 100644 --- a/website/src/content/docs/docs/crash-course.mdx +++ b/website/src/content/docs/docs/crash-course.mdx @@ -54,7 +54,7 @@ Approve or deny agent tool use with human-in-the-loop patterns or auto-approve f *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/approvals)* -### Bindings +### Custom Bindings Expose your JavaScript functions to agents as CLI commands inside the VM. Each binding group becomes a binary at `/usr/local/bin/agentos-{name}`, and each binding becomes a subcommand with flags auto-generated from its Zod input schema. The server below defines a `weather` binding group with a `forecast` binding; the client opens a session and prompts the agent, which calls the binding itself as a shell command. @@ -64,11 +64,11 @@ Expose your JavaScript functions to agents as CLI commands inside the VM. Each b -*See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/bindings) or [Documentation](/docs/bindings)* +*See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/bindings) or [Documentation](/docs/extensions/custom-bindings)* ### Agent-to-Agent -Let one agent call another through a [binding](/docs/bindings). The coder gets a `review` binding it invokes itself, which bridges into the reviewer's isolated VM. +Let one agent call another through a [custom binding](/docs/extensions/custom-bindings). The coder gets a `review` binding it invokes itself, which bridges into the reviewer's isolated VM. @@ -78,7 +78,7 @@ Let one agent call another through a [binding](/docs/bindings). The coder gets a *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/agent-to-agent)* -### Multiplayer & Realtime +### Multiplayer Connect multiple clients to the same agent VM. All subscribers see session output, process logs, and shell data in realtime. @@ -90,7 +90,7 @@ Connect multiple clients to the same agent VM. All subscribers see session outpu *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/multiplayer)* -### Workflows +### Workflows & Graphs Orchestrate multi-step agent tasks with durable workflows that survive crashes and restarts. @@ -136,7 +136,7 @@ Proxy HTTP requests into VMs with `httpRequest`. Create actor-namespaced preview *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/networking)* -### Cron Jobs +### Crons & Loops Schedule recurring commands and agent sessions with cron expressions. @@ -148,12 +148,12 @@ Schedule recurring commands and agent sessions with cron expressions. *See [Full Example](https://github.com/rivet-dev/agentos/tree/main/examples/crash-course) or [Documentation](/docs/cron)* -### Sandbox Mounting +### External Sandboxes agentOS uses a hybrid model: agents run in a lightweight VM by default and mount a full sandbox on demand for heavy workloads like browsers, compilation, and desktop automation. Sandboxes are powered by [Sandbox Agent](https://sandboxagent.dev), so you can swap providers without changing agent code. Mount the sandbox as a filesystem and expose its process management as bindings. -[Documentation](/docs/sandbox) +[Documentation](/docs/extensions/sandboxes) {/* SKILL_OVERVIEW_END */} diff --git a/website/src/content/docs/docs/cron.mdx b/website/src/content/docs/docs/cron.mdx index 9ad5346fc7..f579b8a378 100644 --- a/website/src/content/docs/docs/cron.mdx +++ b/website/src/content/docs/docs/cron.mdx @@ -1,10 +1,14 @@ --- -title: "Cron Jobs" +title: "Crons & Loops" description: "Schedule recurring commands and agent sessions in agentOS VMs." skill: true --- -Schedule recurring work with cron expressions, running either a shell command (`exec`) or an agent session (`session`), with overlap modes (`allow`, `skip`, `queue`) and native `cronEvent` streaming to monitor execution. Cron jobs keep the actor alive while a job runs; the actor can sleep between executions. +Schedule recurring work and long-running agent loops with cron expressions, +running either a shell command (`exec`) or an agent session (`session`), with +overlap modes (`allow`, `skip`, `queue`) and native `cronEvent` streaming to +monitor execution. Cron jobs keep the actor alive while a job runs; the actor +can sleep between executions. ## Schedule a command diff --git a/website/src/content/docs/docs/custom-software/definition.mdx b/website/src/content/docs/docs/custom-software/definition.mdx index 9d9d8ec5d7..be0ba98720 100644 --- a/website/src/content/docs/docs/custom-software/definition.mdx +++ b/website/src/content/docs/docs/custom-software/definition.mdx @@ -134,7 +134,7 @@ packed files, so the JSON never ships into the VM and the metadata never travels command/WASM packages it is **generated** for you (name from `package.json`); for agents you author the `agent` block (or `agentos-toolchain pack --agent ` writes it). -```jsonc +```json { "name": "my-agent", // → /opt/agentos/ "agent": { // optional — also exposes an agent session diff --git a/website/src/content/docs/docs/deployment.mdx b/website/src/content/docs/docs/deployment.mdx index e3bad50eaa..5ee64f65c2 100644 --- a/website/src/content/docs/docs/deployment.mdx +++ b/website/src/content/docs/docs/deployment.mdx @@ -10,7 +10,7 @@ agentOS is powered by [Rivet](https://rivet.dev), an open-source actor platform, - **[Rivet Cloud](https://rivet.dev/cloud)**: fully managed (Rivet Compute, or bring your own cloud). Zero-ops. - **Self-hosted**: run the open-source Rivet platform on your own infrastructure (Kubernetes, Hetzner, VMs, and more) for full control. -- **[agentOS Core](/docs/core)**: embed `@rivet-dev/agentos-core` directly in any Node.js backend, no platform required. +- **[Direct VM API](/docs/core)**: embed `@rivet-dev/agentos` directly in any Node.js backend, no platform required. Pick a deploy target below, or see [Rivet's deployment guides](https://rivet.dev/docs/deploy/). diff --git a/website/src/content/docs/docs/execution/bash.mdx b/website/src/content/docs/docs/execution/bash.mdx new file mode 100644 index 0000000000..93bba5d862 --- /dev/null +++ b/website/src/content/docs/docs/execution/bash.mdx @@ -0,0 +1,54 @@ +--- +title: "Bash" +description: "Run shell commands and arbitrary argv operations through the AgentOS execution lifecycle." +skill: true +--- + +Shell commands are the simplest AgentOS execution surface. Use `process.exec()` +for shell syntax such as pipes and redirects, and `process.execFile()` for +injection-safe command arguments. Both use the same execution lifecycle as +JavaScript, TypeScript, Python, and package workflows. + +## Run commands + +`process.exec()` runs a command through the VM's configured shell and returns +its outcome, exit code, stdout, stderr, and `executionId`. The command runs +inside the VM, never in the host shell. + + + +Prefer `process.execFile()` when command names or arguments come from data. Each +argument is transferred separately and AgentOS does not interpolate it into a +shell command. Keep `process.exec()` for workflows that intentionally need +shell syntax. + +## Detached and interactive work + +Set `detached: true` on `process.exec()` or `process.execFile()`. Manage the +returned `executionId` with `executions.wait()`, `executions.cancel()`, +`executions.signal()`, stdin, PTY resize, bounded output replay, reset, and +deletion. `process.spawn()` is the separate managed-child-process API: it +returns a PID and is controlled through the remaining `process.*` methods. + +An execution accepts only one active operation. Reusing a running ID fails +immediately. Process-only operations do not pin a retained language, so the +same idle execution can later run JavaScript or Python. + +## Files and software + +Shell commands see the persistent [filesystem](/docs/filesystem) shared by +agents, JavaScript, and Python. Common POSIX commands are available by default, +and additional software is projected through the [software registry](/docs/software). + +## Custom bindings + +[Custom Bindings](/docs/extensions/custom-bindings) appear as commands such as +`agentos-weather forecast`, so shell pipelines can use trusted host +capabilities without putting credentials inside the VM. + +## Permissions, limits, and timeouts + +Every command inherits the VM [permission policy](/docs/permissions) and +[resource limits](/docs/resource-limits). `timeoutMs` sets an operation-level +wall-clock deadline. A denied guest operation receives its normal POSIX error, +and a timed-out execution retains a structured `timed_out` result. diff --git a/website/src/content/docs/docs/execution/javascript-compatibility.mdx b/website/src/content/docs/docs/execution/javascript-compatibility.mdx new file mode 100644 index 0000000000..bca2275d35 --- /dev/null +++ b/website/src/content/docs/docs/execution/javascript-compatibility.mdx @@ -0,0 +1,77 @@ +--- +title: "Node.js Compatibility" +description: "Node.js builtins available to JavaScript running inside AgentOS." +--- + +Guest JavaScript never touches the host Node.js runtime. Every `import` or +`require` of a `node:` builtin resolves to a kernel-backed bridge or an +in-isolate implementation, and unknown or denied modules fail explicitly. The +guest reports Node.js `v22.0.0` through `process.version`. + +## How builtins are backed + +- **Kernel-backed:** calls route through the VM filesystem, socket table, + process table, DNS resolver, or entropy source. +- **In-isolate:** pure JavaScript implementations run entirely inside V8 and + require no host access. +- **Denied:** importing the module throws `ERR_ACCESS_DENIED`. + +The canonical inventory lives in +`crates/execution/assets/polyfill-registry.json`. + +A guest never falls through to a real host builtin. Anything not bridged +or implemented in the isolate is denied. + +## Kernel-backed builtins + +| Module | Backed by | +| --- | --- | +| `fs`, `fs/promises` | VM filesystem, including fds, streams, metadata, symlinks, and polling-based watchers. | +| `child_process` | VM process table. `spawn`, `exec`, `execFile`, and sync variants launch guest processes. | +| `net`, `dgram` | VM TCP, Unix-socket, and UDP tables. | +| `dns`, `dns/promises` | VM DNS resolver. | +| `http`, `https`, `http2`, `tls` | VM socket and TLS paths, including clients, servers, and connection pooling. | +| `os` | VM-scoped platform, architecture, hostname, CPU, memory, and user information. | +| `crypto` | Entropy, hashes, HMAC, ciphers, scrypt, UUIDs, and WebCrypto. | +| `process` | VM environment, working directory, signals, timers, stdio, and umask. | +| `module` | `createRequire`, builtin resolution, and basic `Module` compatibility. | +| `console` | Bounded formatting and guest stdout/stderr. | +| `readline`, `sqlite`, `tty` | Kernel-backed compatibility surfaces. | +| `timers`, `timers/promises` | Timeout, interval, immediate, and promise variants. | +| `stream/web`, `stream/consumers`, `stream/promises` | Web Streams and stream helpers. | + +Network builtins obey the VM's [permission policy](/docs/permissions). Network +access is denied until the VM creator grants it. + +## In-isolate builtins + +Pure JavaScript implementations include `path`, `buffer`, `events`, `stream`, +`util`, `assert`, `url`, `querystring`, `string_decoder`, `zlib`, `punycode`, +`constants`, and `sys`. Default and named ESM imports are supported. + +Compatibility shims are also provided for common feature detection, including +`async_hooks`, `diagnostics_channel`, `perf_hooks`, `worker_threads`, `vm`, and +`v8`. The `worker_threads` shim does not create real worker threads. + +## Denied builtins + +`cluster`, `domain`, `inspector`, `repl`, `trace_events`, and `wasi` are denied. + +## Global APIs + +Modern web globals are available, including `fetch`, `Headers`, `Request`, +`Response`, `TextEncoder`, `TextDecoder`, `Buffer`, URL APIs, `Blob`, `File`, +`FormData`, abort APIs, `structuredClone`, `performance`, and WebAssembly. +`fetch()` uses the VM socket table and follows the same policy as `http` and +`net`. + +## Modules and output + +Both ESM and CommonJS use the VM filesystem and normal `node_modules` +resolution. Console and stream output is delivered through the same bounded +process-output path described in [Processes & Shells](/docs/processes). + + + +Return to the [JavaScript guide](/docs/execution/javascript) for TypeScript, +packages, files, processes, networking, bindings, permissions, and limits. diff --git a/website/src/content/docs/docs/execution/javascript.mdx b/website/src/content/docs/docs/execution/javascript.mdx new file mode 100644 index 0000000000..b3af7306e0 --- /dev/null +++ b/website/src/content/docs/docs/execution/javascript.mdx @@ -0,0 +1,122 @@ +--- +title: "JavaScript" +description: "Execute JavaScript and TypeScript, install npm dependencies, and manage execution lifecycles in AgentOS." +skill: true +--- + +AgentOS runs JavaScript in native V8 behind the VM kernel boundary. Use the +first-class language methods for source, files, values, TypeScript, npm +projects, and package binaries. Use `process.execFile()` only when you need an +unusual command that does not have a language-level method. + +## Get started + +`@rivet-dev/agentos-javascript` is the focused JavaScript/TypeScript entry +point. It creates the same AgentOS VM and delegates every operation to the +sidecar-owned execution protocol. + + + +Every attached call returns one result discriminated by `outcome`. Successful +evaluations contain a JSON-compatible `value`; failed, cancelled, and timed-out +results contain a structured `error`. Stdout and stderr are always captured +with explicit truncation flags. Evaluation results also expose the value as a +bounded `{ type: "json", data }` display output. Returning `undefined`, a +function, a symbol, a circular object, or another non-JSON value produces an +`evaluation_serialization_failed` result instead of losing the value silently. + +## Use the core client + +The same methods are available directly on `AgentOs` under +`javascript.execute()`, `javascript.evaluate()`, `javascript.executeFile()`, +`javascript.typescript.*`, and `javascript.npm.*`. + +The focused runtime adds default `cwd` and `env` values and exposes the core VM +as `runtime.vm`; it does not implement a second execution engine. + +## Retain JavaScript state + +Give an operation an `executionId` and set `createIfMissing: true` on the first +call. Later inline JavaScript and TypeScript operations with the same ID share +one retained JavaScript realm. `inputs` is replaced on every operation and is +serialized separately from source. + + + +An execution accepts one active operation at a time. Reusing a busy ID fails +immediately. Bash, files, npm operations, and type checks can use the same +lifecycle ID, but run in fresh processes and do not alter retained language +memory. `executions.reset()` clears memory, results, and output; filesystem and +installed-package changes remain. `executions.delete()` removes an idle +execution. + +## TypeScript + +TypeScript execution is a convenience API in the JavaScript layer. **Executing +TypeScript transpiles it without semantic type checking.** Call +`javascript.typescript.check()` or +`javascript.typescript.checkProject()` when diagnostics are part of the +workflow. + + + +Inline `filePath` identifies source for diagnostics and module resolution; it +does not read that file. Use `javascript.typescript.executeFile()` on the core +client to execute an existing file. JavaScript and TypeScript inline calls +share retained state when they use the same execution ID. + +## npm projects and packages + +Use the options-only `javascript.npm.install()` overload for the project in +`cwd`. `frozen: true` performs a lockfile-exact clean install. Pass package +names for a named install, and use `javascript.npm.runScript()` or +`javascript.npm.runPackage()` instead of assembling npm commands. The focused +runtime exposes the same workflows as `installNpmPackages()`, +`executeNpmScript()`, and `executeNpmPackage()`. + + + +Package names, script names, paths, and arguments are transferred as distinct +argv values. Installs modify the VM-wide filesystem, so all executions in that +VM see the same dependencies. AgentOS admits only one npm or Python package +mutation at a time in a VM; a concurrent install fails with `execution_busy` +instead of allowing package managers to corrupt shared state. + +## Detached work and output + +Set `detached: true` on an execution method for a long-running program. The +returned descriptor contains its `executionId`; use `executions.wait()`, +`executions.cancel()`, `executions.signal()`, `executions.writeStdin()`, +`executions.closeStdin()`, `executions.resizePty()`, and +`executions.readOutput()` to manage it. Core callbacks receive exact +`Uint8Array` chunks. + + + +Actor actions use the same nested method paths as Core; RivetKit transports +them with dotted wire names such as `javascript.execute` and +`executions.readOutput`. Actor stdin and output use tagged +`{ encoding: "utf8" | "base64", data: string }` values, and live output is +broadcast through `executionOutput` and `executionCompleted` events. + +## Filesystem, processes, and networking + +`node:fs` uses the VM [filesystem](/docs/filesystem), `node:child_process` +starts kernel-managed guest processes, and Node networking APIs use the VM +socket table. Files and installed packages are immediately visible to Bash, +Python, agents, and other executions. See [Processes & Shells](/docs/processes), +[Networking & Previews](/docs/networking), and the detailed +[Node.js compatibility matrix](/docs/execution/javascript-compatibility). + +## Custom bindings and policy + +Guest JavaScript invokes [Custom Bindings](/docs/extensions/custom-bindings) +as ordinary typed commands, keeping host credentials outside the VM. + + + +All operations inherit the VM's [permissions](/docs/permissions) and +[resource limits](/docs/resource-limits). `timeoutMs` adds an operation-level +wall-clock deadline covering sidecar staging, TypeScript transformation, +guest execution, and result collection; it does not replace the independently +bounded VM safety limits. diff --git a/website/src/content/docs/docs/execution/python.mdx b/website/src/content/docs/docs/execution/python.mdx new file mode 100644 index 0000000000..75ad1d71b3 --- /dev/null +++ b/website/src/content/docs/docs/execution/python.mdx @@ -0,0 +1,93 @@ +--- +title: "Python" +description: "Execute Python source, files, modules, and package workflows in AgentOS." +skill: true +--- + +AgentOS runs CPython 3.13 as a first-class VM execution engine. Python shares +the VM filesystem, process tree, networking policy, permissions, and limits +with agents, Bash, JavaScript, and installed software. + +## Get started + +`@rivet-dev/agentos-python` is the focused Python entry point. It uses the same +sidecar protocol as the core `AgentOs` client. + + + +Use `python.execute()` for source and `python.evaluate()` for a JSON-compatible +value on the core client. The focused package exposes them as `execute()` and +`evaluate()` and provides default `cwd` and `env` values. Evaluation values are +also returned as bounded JSON display outputs. A value that Python's JSON +encoder cannot represent produces a structured +`evaluation_serialization_failed` result. + +## Retain Python state + +Reuse an `executionId` to keep Python globals, functions, imports, modules, and +guest objects in one interpreter. Set `createIfMissing: true` only on the first +operation. Structured `inputs` is replaced for every call. + + + +Only inline execute and evaluate calls retain interpreter memory. File, +module, install, Bash, and arbitrary-command operations use fresh processes. +`executions.reset()` clears retained memory and output without reverting the +filesystem; `executions.delete()` removes an idle execution. + +## Files, modules, and async Python + +Use `python.executeFile()` for an existing script and +`python.executeModule()` for the standard `python -m` workflow. Inline Python +supports top-level `await`, `async for`, and `async with`; awaited work is part +of the operation deadline. + + + +The API does not promise that unawaited `asyncio` tasks survive between +operations. Cancellation, timeout, reset, deletion, or VM disposal stops +execution-owned asynchronous work. + +## Install packages + +Call `python.install()` on `AgentOs`, or `install()` on the focused runtime. +Pass package specs for named installs, `requirementsFile` for a +requirements install, and `upgrade`, `indexUrl`, or `extraIndexUrls` for the +stable package workflows. + + + +Named packages and a requirements file cannot be combined in one call. +Installs modify the VM-wide filesystem and are visible to every execution in +that VM. AgentOS admits only one npm or Python package mutation at a time in a +VM; a concurrent install fails with `execution_busy` instead of risking shared +package state. Package downloads obey the VM network policy. + +## Detached work and output + +Set `detached: true` on execute, file, or module operations. Manage the returned +`executionId` with `executions.wait()`, `executions.cancel()`, +`executions.signal()`, stdin, PTY resize, reset, deletion, and bounded output +replay. Core output callbacks receive `Uint8Array`; actor events carry tagged +UTF-8/base64 data. Actor actions use the same nested method paths as Core and +RivetKit transports them with dotted wire names. + +## Filesystem, processes, and networking + +`pathlib`, `os`, and file objects use the VM [filesystem](/docs/filesystem). +`subprocess` starts kernel-managed guest commands. Python DNS, HTTP clients, and +outbound sockets use the VM network policy. See +[Processes & Shells](/docs/processes) and +[Networking & Previews](/docs/networking). + +## Custom bindings and policy + +Python can call [Custom Bindings](/docs/extensions/custom-bindings) as normal +commands through `subprocess`. + + + +All operations inherit [permissions](/docs/permissions) and +[resource limits](/docs/resource-limits). `timeoutMs` is an additional +operation wall-clock deadline covering staging, compilation, guest execution, +and result collection, while VM safety watchdogs remain independently bounded. diff --git a/website/src/content/docs/docs/browser.mdx b/website/src/content/docs/docs/extensions/browser.mdx similarity index 95% rename from website/src/content/docs/docs/browser.mdx rename to website/src/content/docs/docs/extensions/browser.mdx index 405fe83990..1a2dcd9c50 100644 --- a/website/src/content/docs/docs/browser.mdx +++ b/website/src/content/docs/docs/extensions/browser.mdx @@ -1,5 +1,5 @@ --- -title: "Browser" +title: "Browser Automation" description: "Let agents read and search the web from an agentOS VM using Browserbase's cloud browser through the browse CLI — no local browser or sandbox required." skill: true --- @@ -65,5 +65,5 @@ browse cloud projects list # list Browserbase projects ``` -The [interactive driver mode](https://docs.browserbase.com/integrations/skills/browse-cli) (`browse open`, `browse click`, …) is not supported inside the VM yet ([#1631](https://github.com/rivet-dev/agentos/issues/1631)). For interactive automation, run `browse` inside a sandbox via [Sandbox Mounting](/docs/sandbox). +The [interactive driver mode](https://docs.browserbase.com/integrations/skills/browse-cli) (`browse open`, `browse click`, …) is not supported inside the VM yet ([#1631](https://github.com/rivet-dev/agentos/issues/1631)). For interactive automation, run `browse` inside an external sandbox via [External Sandboxes](/docs/extensions/sandboxes). diff --git a/website/src/content/docs/docs/bindings.mdx b/website/src/content/docs/docs/extensions/custom-bindings.mdx similarity index 94% rename from website/src/content/docs/docs/bindings.mdx rename to website/src/content/docs/docs/extensions/custom-bindings.mdx index 2dc5e77c39..a69b18bc47 100644 --- a/website/src/content/docs/docs/bindings.mdx +++ b/website/src/content/docs/docs/extensions/custom-bindings.mdx @@ -1,5 +1,5 @@ --- -title: "Bindings" +title: "Custom Bindings" description: "Expose custom host functions to agents as CLI commands inside the VM." skill: true --- @@ -70,9 +70,9 @@ On failure (validation or execution error), the binding exits non-zero and write Missing required flag: --city ``` -## Bindings vs MCP servers +## Bindings and MCP servers -agentOS supports two ways to give agents access to external functionality: **bindings** and **MCP servers**. Both work, but they have different tradeoffs. +AgentOS supports two ways to give agents access to external functionality: **bindings** and session-scoped **MCP servers**. Both work, but they have different tradeoffs. | | Bindings | MCP Servers | |---|---|---| diff --git a/website/src/content/docs/docs/sandbox.mdx b/website/src/content/docs/docs/extensions/sandboxes.mdx similarity index 92% rename from website/src/content/docs/docs/sandbox.mdx rename to website/src/content/docs/docs/extensions/sandboxes.mdx index 29ceb9815e..b58a07b33a 100644 --- a/website/src/content/docs/docs/sandbox.mdx +++ b/website/src/content/docs/docs/extensions/sandboxes.mdx @@ -1,10 +1,10 @@ --- -title: "Sandbox Mounting" +title: "External Sandboxes" description: "Extend agentOS with full sandboxes for heavy workloads like browsers, desktop automation, and compilation." skill: true --- -For heavy workloads like browsers, desktop automation, and compilation, pair agentOS with a full sandbox on demand. Its filesystem mounts into the VM as a native directory, and its process management is exposed as [bindings](/docs/bindings), all provider-agnostic through [Sandbox Agent](https://sandboxagent.dev). +For heavy workloads like browsers, desktop automation, and compilation, pair agentOS with a full sandbox on demand. Its filesystem mounts into the VM as a native directory, and its process management is exposed as [custom bindings](/docs/extensions/custom-bindings), all provider-agnostic through [Sandbox Agent](https://sandboxagent.dev). ## Why use agentOS with a sandbox? @@ -27,7 +27,7 @@ Start with the default agentOS VM for all workloads, and only spin up a sandbox The sandbox integration ships as the `@rivet-dev/agentos-sandbox` package. It works through two mechanisms: - **Filesystem mount**: Projects the sandbox into the VM as a native directory, like mounting a hard drive on your own machine. Read and write files through the mount directly. -- **Bindings**: Exposes sandbox process management as [bindings](/docs/bindings). Execute commands on the sandbox from within the VM. +- **Bindings**: Exposes sandbox process management as [custom bindings](/docs/extensions/custom-bindings). Execute commands on the sandbox from within the VM. Both are powered by [Sandbox Agent](https://sandboxagent.dev), and you can swap providers without changing agent code. Install both packages: diff --git a/website/src/content/docs/docs/filesystem.mdx b/website/src/content/docs/docs/filesystem.mdx index 68c6c2f133..47d9235857 100644 --- a/website/src/content/docs/docs/filesystem.mdx +++ b/website/src/content/docs/docs/filesystem.mdx @@ -62,7 +62,7 @@ The actor's durable root is handled separately: the sidecar connects directly to ## File operations -These operations are primarily what the agent uses inside the VM, and are also available from the client to seed inputs and read results. For large or read-only inputs (a repo, a dataset), a read-only [host mount](#mounts) is faster than copying files in. Programs that need stdin or live output use exec instead (see [Core](/docs/core)). +These operations are primarily what the agent uses inside the VM, and are also available from the client to seed inputs and read results. For large or read-only inputs (a repo, a dataset), a read-only [host mount](#mounts) is faster than copying files in. Programs that need stdin or live output use exec instead (see the [Direct VM API](/docs/core)). ### Read and write @@ -103,7 +103,7 @@ See [Permissions](/docs/permissions) for the full configuration. ## Sandboxes -For heavier or untrusted workloads, run a full Linux [sandbox](/docs/sandbox) alongside the VM and mount its filesystem into agentOS. The agent then reads and writes the sandbox's files through the same `fs` APIs while the sandbox handles execution. See [Sandbox Mounting](/docs/sandbox) for setup. +For heavier workloads, run a full Linux [external sandbox](/docs/extensions/sandboxes) alongside the VM and mount its filesystem into agentOS. The agent then reads and writes the sandbox's files through the same `fs` APIs while the sandbox handles execution. ## Default layout diff --git a/website/src/content/docs/docs/js-runtime.mdx b/website/src/content/docs/docs/js-runtime.mdx deleted file mode 100644 index 1ac3bdb30a..0000000000 --- a/website/src/content/docs/docs/js-runtime.mdx +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "JavaScript Runtime" -description: "How agentOS runs guest JavaScript: native V8 acceleration, low memory overhead, and Node.js compatibility." -skill: true ---- - -The JavaScript runtime is powered by the Rivet [Secure Exec](https://secureexec.dev) project, which provides the isolated V8 runtime that agentOS runs guest code in. Every guest VM executes its JavaScript inside this runtime, fully sandboxed from the host. - -## JavaScript Acceleration - -- **JavaScript is unusually slow as WebAssembly**: unlike most software, JavaScript pays a heavy penalty when compiled to WebAssembly, because so much engineering has gone into JIT-compiling JavaScript directly in V8. -- **Native V8, full JIT**: agentOS therefore runs guest JavaScript on the native V8 engine with its full JIT compiler, not through a WASM translation layer. We call this **JavaScript Acceleration**. -- **Native-speed execution**: guest JavaScript runs at native speed while staying inside the isolation boundary, with normal Node.js semantics. - -## Comparison to Node.js efficiency - -- **Isolate model, not processes**: agentOS runs each agent inside a V8 isolate rather than spawning a full Node.js process per agent. -- **Low memory overhead**: an isolate carries far less per-agent memory overhead than a full Node.js process, so many agents fit in the footprint that a process-per-agent model would spend on a handful. -- **Benchmarks**: see the Secure Exec [benchmarks](https://secureexec.dev/docs/benchmarks) for cold start, warm execution, and reuse measurements. - -## Node.js compatibility - -Guest code runs as Node.js (reporting `process.version` as `v22.0.0`), but it never touches the host runtime. Every `node:` builtin resolves to a kernel-backed bridge or an in-isolate polyfill, never the real host module. For the full builtin matrix (`fs`, `net`, `http`, `crypto`, undici-backed `fetch`, and more), see the Secure Exec [Node.js Compatibility](https://secureexec.dev/docs/nodejs-compatibility) reference. - -For the implementation-level event loop—how process-wide Tokio tasks notify a -thread-affine V8 isolate, how readiness is coalesced, and how `Duplex` -backpressure reaches a sidecar-owned socket—see -[JavaScript Executor & Socket Reactor](/docs/architecture/javascript-executor). - -### npm packages - -By default the VM has no npm packages installed. Mount a host `node_modules` directory to give guest code access to real packages: the `nodeModulesMount` helper projects it read-only at `/root/node_modules`, and the in-kernel resolver walks it exactly like Node.js does, with no bundling or patching. - - - -Resolution matches naive Node.js over the mounted tree: the ancestor `node_modules` walk, `package.json` `exports`/`imports` and conditions, and `realpath`/symlink following (so pnpm and yarn layouts resolve too). Both ESM `import` and CommonJS `require` work. See the Secure Exec [module loading](https://secureexec.dev/docs/features/module-loading) guide for the full model. diff --git a/website/src/content/docs/docs/limitations.mdx b/website/src/content/docs/docs/limitations.mdx index edf74a11a1..6c1e04512a 100644 --- a/website/src/content/docs/docs/limitations.mdx +++ b/website/src/content/docs/docs/limitations.mdx @@ -8,7 +8,7 @@ agentOS is a Linux environment with a POSIX-compliant virtual kernel. It handles ## Sandbox mounting -When a workload needs a full Linux OS, agents can escalate to a full sandbox on demand without changing code. The [sandbox mounting](/docs/sandbox) extension mounts the sandbox as a filesystem and lets you execute commands on it, like mounting a hard drive on your own machine. Files written in the VM are available in the sandbox and vice versa. +When a workload needs a full Linux OS, agents can escalate to a full sandbox on demand without changing code. The [external sandbox](/docs/extensions/sandboxes) extension mounts the sandbox as a filesystem and lets you execute commands on it, like mounting a hard drive on your own machine. Files written in the VM are available in the sandbox and vice versa. See [agentOS vs Sandbox](/docs/versus-sandbox) for a detailed comparison. @@ -16,7 +16,7 @@ See [agentOS vs Sandbox](/docs/versus-sandbox) for a detailed comparison. ### Software registry -agentOS uses its own [software registry](/registry) of popular tools cross-compiled for the runtime. You cannot download and install arbitrary binaries (for example via `curl` or `apt`), and standard Linux package managers (`apt`, `yum`) are not available since agentOS runs a streamlined Linux environment rather than a full distribution. Native binaries that are not yet available in the registry (such as Go, Rust, or C++ toolchains) require a full [sandbox](/docs/sandbox). +agentOS uses its own [software registry](/registry) of popular tools cross-compiled for the runtime. You cannot download and install arbitrary binaries (for example via `curl` or `apt`), and standard Linux package managers (`apt`, `yum`) are not available since agentOS runs a streamlined Linux environment rather than a full distribution. Native binaries that are not yet available in the registry (such as Go, Rust, or C++ toolchains) require a full [external sandbox](/docs/extensions/sandboxes). See [Software](/docs/software) for how to install and configure available packages. @@ -31,4 +31,3 @@ agentOS provides a POSIX-compliant virtual Linux kernel with full filesystem ope ### No hardware access The VM has no access to GPUs, USB devices, or other hardware. - diff --git a/website/src/content/docs/docs/llm-gateway.mdx b/website/src/content/docs/docs/llm-gateway.mdx deleted file mode 100644 index a000dfdb46..0000000000 --- a/website/src/content/docs/docs/llm-gateway.mdx +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Embedded LLM Gateway" -description: "Route, meter, and manage LLM API calls from agents." -skill: true ---- - -{/* TODO: This page is coming soon. */} - -The Embedded LLM Gateway runs as part of the agentOS library, not as an external service. It intercepts and manages all LLM API calls made by agents inside the VM. - -- **Unified routing** for all agent LLM requests -- **API keys stay on the server** so they are never exposed to agent code inside the VM -- **Usage metering** with per-session and per-agent breakdowns -- **Rate limiting** and cost controls - -Check back soon for full documentation. diff --git a/website/src/content/docs/docs/llm-credentials.mdx b/website/src/content/docs/docs/models-and-credentials.mdx similarity index 61% rename from website/src/content/docs/docs/llm-credentials.mdx rename to website/src/content/docs/docs/models-and-credentials.mdx index e5e1e925b8..1b5b914b74 100644 --- a/website/src/content/docs/docs/llm-credentials.mdx +++ b/website/src/content/docs/docs/models-and-credentials.mdx @@ -1,10 +1,12 @@ --- -title: "LLM Credentials" -description: "Pass LLM API keys to agent sessions securely." +title: "Models & Credentials" +description: "Choose agent models and pass provider credentials to sessions securely." skill: true --- -Pass LLM provider API keys to agent sessions so keys stay on the server and are injected at session creation, with per-tenant isolation for multi-tenant deployments. +Choose the model through your agent adapter, then pass its provider credentials +to the session from trusted server code. Credentials are injected at session +creation and can be isolated per tenant. ## Passing API keys @@ -26,6 +28,9 @@ Then resolve each tenant's key and pass it at session creation: Because keys are resolved per tenant from your own credential store (the `lookupTenantApiKey` stand-in above) and stay on the server, each session uses the tenant's own key and one tenant's key never reaches another tenant or the client. -## Embedded LLM Gateway +## Models -The [Embedded LLM Gateway](/docs/llm-gateway) (coming soon) will remove the need to manage API keys manually. It routes all agent LLM requests through a managed proxy built into agentOS, providing per-tenant usage metering, rate limiting, and cost controls without deploying a separate gateway service. +Model selection belongs to the configured agent adapter. AgentOS forwards the +session environment and preserves the agent's native model behavior instead of +introducing a second model-selection layer. See the page for your +[agent](/docs/agents/pi) for its supported model and provider options. diff --git a/website/src/content/docs/docs/nodejs-runtime.mdx b/website/src/content/docs/docs/nodejs-runtime.mdx deleted file mode 100644 index 67df0783cd..0000000000 --- a/website/src/content/docs/docs/nodejs-runtime.mdx +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Node.js Runtime" -description: "Run Node.js in agentOS: native V8 acceleration, the node CLI, installing packages, and Node.js compatibility." -skill: true ---- - -agentOS runs **Node.js** (`process.version` `v22.0.0`), fully isolated from the host. `node`, `npm`, and `npx` are on the `PATH`. - -## JavaScript Acceleration - -Normally, JavaScript running inside WebAssembly is exceptionally slow. In agentOS, JavaScript runs inside a native V8 isolate (powered by [Secure Exec](https://secureexec.dev)) for native runtime speeds: - -- **Native V8 speed, no overhead** — guest JS runs on V8's full JIT, not a WASM translation layer. -- **Lower memory than a Node.js process** — each agent is a V8 isolate, not a full process, so many fit where process-per-agent fits a handful. See [benchmarks](https://secureexec.dev/docs/benchmarks). - -## Running Node - -```ts -await agent.exec('node -e "console.log(1 + 1)"'); // inline -await agent.exec("node /workspace/main.js a b"); // script + argv -await agent.exec("npx tsx script.ts"); // npx -await agent.exec('echo "console.log(42)" | node'); // stdin -``` - -`node` works directly (`exec` / `execArgv` / `spawn`), through the guest shell (`sh -c`, pipes), and as a REPL. - -## Installing packages - -### Ahead of time - -Mount a host `node_modules` tree — projected read-only at `/root/node_modules` and resolved exactly like Node.js (ancestor walk, `package.json` `exports`/`imports`, symlinks — so pnpm/yarn layouts work), for both `import` and `require`: - -```ts -import { agentOS, setup, nodeModulesMount } from "@rivet-dev/agentos"; - -const vm = agentOS({ - mounts: [nodeModulesMount("/absolute/path/to/node_modules")], -}); -``` - -### At runtime - -Or install in the VM mid-task: - -```ts -await agent.exec("npm install chalk"); -await agent.exec("node /workspace/app.js"); // app.js: require("chalk") -``` - -## Node.js compatibility - -Guest code runs as Node.js v22, isolated from the host. `node:` builtins — `fs`, `net`, `http`, `crypto`, undici-backed `fetch`, and more — are provided by the runtime, never the host's. See the full [Node.js Compatibility](https://secureexec.dev/docs/nodejs-compatibility) matrix. diff --git a/website/src/content/docs/docs/benchmarks.mdx b/website/src/content/docs/docs/performance.mdx similarity index 88% rename from website/src/content/docs/docs/benchmarks.mdx rename to website/src/content/docs/docs/performance.mdx index bef9ba7ba3..8cc1e100f1 100644 --- a/website/src/content/docs/docs/benchmarks.mdx +++ b/website/src/content/docs/docs/performance.mdx @@ -1,10 +1,13 @@ --- -title: "Benchmarks" -description: "Performance benchmarks comparing agentOS to traditional sandbox providers." +title: "Performance" +description: "AgentOS latency, memory, cost, and benchmark methodology." skill: true --- -These are the benchmark figures shown on the agentOS marketing page. All numbers are computed from the same data source used by the marketing page. For independent sandbox comparison data, see the [ComputeSDK benchmarks](https://www.computesdk.com/benchmarks/). +These are the benchmark figures shown on the agentOS marketing page. All +numbers are computed from the same data source used by the marketing page. Use +the methodology below to measure the workload and hardware you will actually +deploy. ## Cold start @@ -70,6 +73,21 @@ Sandbox baseline: **Daytona** at $0.0504/vCPU-h + $0.0162/GiB-h with a 1 vCPU + | Hetzner ARM | $0.000000011/s | $0.000018/s | 1738x cheaper | | Hetzner x86 | $0.000000017/s | $0.000018/s | 1061x cheaper | +## Evaluating your own cost + +AgentOS runs on hardware you provision instead of billing per VM-second. To +estimate your workload, divide the instance's cost per second by the number of +concurrent VMs it can hold with realistic memory and utilization headroom. + +The result depends on workload size and lifecycle. A VM per task or tenant gives +the strongest isolation, while safely reusing a VM for trusted sequential work +amortizes boot and filesystem setup. Small, short executions benefit most from +dense packing; heavyweight, long-lived work depends more on hardware choice and +avoiding per-sandbox minimums. + +Provider prices, instance prices, and workload memory change. Measure +on your target hardware before quoting a cost ratio. + ## Test environment | Component | Details | diff --git a/website/src/content/docs/docs/python-runtime.mdx b/website/src/content/docs/docs/python-runtime.mdx deleted file mode 100644 index f0d82ef9bd..0000000000 --- a/website/src/content/docs/docs/python-runtime.mdx +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: "Python Runtime" -description: "Run Python in agentOS: the python CLI, installing packages ahead of time or at runtime, and what's supported." -skill: true ---- - -agentOS runs **CPython 3.13** as a first-class runtime. `python` and `python3` are on the `PATH` and plug into the VM's filesystem, processes, and network — agents use them like any other command. - -## Running Python - -```ts -await agent.exec('python -c "print(1 + 1)"'); // inline -await agent.exec("python /workspace/main.py a b"); // script + sys.argv -await agent.exec("python -m http.server 8000"); // module -await agent.exec('echo "print(40 + 2)" | python -'); // stdin -``` - -`python` works directly (`exec` / `execArgv` / `spawn`), through the guest shell (`sh -c`, pipes), and as an interactive REPL. - -## Installing packages - -`pip install` writes to a persistent spot on the VM filesystem, so a package installed once is importable by every later `python` run in that VM. - -### Ahead of time - -Install once during setup so the agent starts ready — no install cost mid-task: - -```ts -// one-off setup pass on the VM, before handing it to the agent -await agent.exec("pip install requests pandas"); -// requests + pandas now import in every python run on this VM -``` - -### At runtime - -Or let the agent install what it needs, mid-task: - -```ts -await agent.exec("pip install rich"); -await agent.exec('python -c "import rich; print(rich.__version__)"'); -``` - -`pip install ` and `python -m pip install ` both work; downloads obey the VM's network policy (default-deny + allowlist). - -## Compatibility - -CPython 3.13 and the standard library, with a few VM-shaped differences. - -### Supported - -- Full VM filesystem (`/tmp`, `/etc`, `/root`, …) — shared with other processes and `readFile()` -- Reading, writing, creating, deleting, and renaming files anywhere on the VM, plus symlinks and file metadata (`os.symlink` / `os.readlink` / `os.chmod` / `os.chown` / `os.utime`) -- A real process in the tree: stdin/stdout/stderr, signals, `kill` -- `subprocess` launching other VM commands (`node`, etc.) -- Pure-Python packages, plus native packages with a prebuilt wheel — `numpy`, `pandas`, `scipy`, `scikit-learn`, `pydantic`, `cryptography`, `Pillow`, and [many more](https://pyodide.org/en/stable/usage/packages-in-pyodide.html) -- `requests`, `urllib`, and `pip` over HTTP/DNS, under the VM network policy -- Outbound raw TCP and UDP sockets (the `socket` module), under the VM network policy - -### Unsupported - -- OS threads and `multiprocessing` — the runtime is single-threaded -- `os.fork` / `os.exec` -- Some packages with native (C/Rust) extensions — see the [full list of supported packages](https://pyodide.org/en/stable/usage/packages-in-pyodide.html) -- Socket servers / listeners (`bind`/`listen`/`accept`) — outbound connections only diff --git a/website/src/content/docs/docs/quickstart.mdx b/website/src/content/docs/docs/quickstart.mdx index c5dd0e4dee..0c1d5989a4 100644 --- a/website/src/content/docs/docs/quickstart.mdx +++ b/website/src/content/docs/docs/quickstart.mdx @@ -104,7 +104,7 @@ import { AGENT_PROMPT } from '../../../components/marketing/agentPrompt'; - **[Software](/docs/software)** — Install software packages inside the VM - **[Filesystem](/docs/filesystem)** — Read, write, and manage files inside the VM - **[Permissions & Resource Limits](/docs/permissions)** — Gate what the agent can do and cap its resource usage - - **[Bindings](/docs/bindings)** — Expose your JavaScript functions to agents as CLI commands + - **[Custom Bindings](/docs/extensions/custom-bindings)** — Expose your JavaScript functions to agents as CLI commands 5. **Deploy** @@ -112,7 +112,7 @@ import { AGENT_PROMPT } from '../../../components/marketing/agentPrompt'; - See [Deployment](/docs/deployment) for managed, self-hosted, and agentOS Core options. + See [Deployment](/docs/deployment) for managed, self-hosted, and direct VM options. @@ -120,8 +120,9 @@ import { AGENT_PROMPT } from '../../../components/marketing/agentPrompt'; agentOS is in preview and the API is subject to change. If you run into issues, please [report them on GitHub](https://github.com/rivet-dev/rivet/issues) or [join our Discord](https://rivet.dev/discord). -## agentOS Core +## Direct VM API -The quickstart above uses `@rivet-dev/agentos`, which includes statefulness, multiplayer, and orchestration out of the box. If you only need direct VM control without those features, you can use the core package (`@rivet-dev/agentos-core`) standalone. +The same `@rivet-dev/agentos` package also exports `AgentOs.create()` for direct +VM control without the actor lifecycle, multiplayer, or orchestration layer. -See [agentOS core documentation](/docs/core) for reference. +See the [direct VM API documentation](/docs/core) for reference. diff --git a/website/src/content/docs/docs/security-model.mdx b/website/src/content/docs/docs/security-model.mdx index ef8b9424f9..182cf603b6 100644 --- a/website/src/content/docs/docs/security-model.mdx +++ b/website/src/content/docs/docs/security-model.mdx @@ -123,7 +123,7 @@ Every guest syscall is mediated by the kernel and checked against the runtime's - **Processes.** `node:child_process` spawns kernel-managed guest processes, never real host processes. Children can only run the commands the VM mounts (WASM-backed `sh` and coreutils, V8-backed `node`). See [Processes](/docs/processes). - **Network.** Guest `fetch()`, `node:http`, and raw sockets all flow through the kernel socket table. Guest `fetch()` runs through undici inside the isolate and then through the kernel socket table; it never opens a real host socket. See [Networking](/docs/networking). - **DNS, pipes, and PTYs** are likewise kernel-owned: no guest path reaches the host directly. -- **Bindings.** Registered [bindings](/docs/bindings) are the only sanctioned way to hand the guest a named host capability. The guest invokes a binding by name with JSON input, the call round-trips to the host handler, and only the handler's return value comes back. The guest never receives the underlying host access. +- **Bindings.** Registered [custom bindings](/docs/extensions/custom-bindings) are the only sanctioned way to hand the guest a named host capability. The guest invokes a binding by name with JSON input, the call round-trips to the host handler, and only the handler's return value comes back. The guest never receives the underlying host access. ## What enters the VM @@ -172,7 +172,7 @@ The boundary protects the host from the guest. It does **not** harden your host - Hardening the host process and deployment environment. For internet-facing workloads that take untrusted input, run your host inside an already-hardened environment (for example AWS Lambda, Google Cloud Run, or a similar sandboxed platform). - Validating authentication tokens in `onBeforeConnect`. - Scoping [permissions](/docs/permissions) appropriately for your use case. -- Managing API keys and secrets on the host side (use the [LLM gateway](/docs/llm-gateway) to avoid passing keys into the VM). +- Managing API keys and secrets on the host side (see [Models & Credentials](/docs/models-and-credentials)). - Configuring [resource limits and network controls](/docs/security-model) to match your threat model. - Choosing your blast radius: prefer a fresh VM per untrusted or high-risk task so an escape attempt cannot outlive a single VM. diff --git a/website/src/content/docs/docs/sessions.mdx b/website/src/content/docs/docs/sessions.mdx index 78fdea2012..9f95b941ef 100644 --- a/website/src/content/docs/docs/sessions.mdx +++ b/website/src/content/docs/docs/sessions.mdx @@ -17,6 +17,20 @@ AgentOS sessions are durable records backed by the VM's SQLite database. The pub The input supports `agent`, `cwd`, `additionalDirectories`, `env`, `mcpServers`, `permissionPolicy`, `skipOsInstructions`, and `additionalInstructions`. Omitted `cwd` defaults to `/home/agentos` in the sidecar. Actor deployments inject their SQLite UDS database automatically. Standalone core clients must configure a VM SQLite file or UDS descriptor. +## MCP servers + +MCP configuration belongs to the session because its tools are part of the +agent's runtime context. Configure local child-process servers or remote servers +before opening the session. The exact config path and supported transports come +from the selected agent adapter; for example, Pi reads `.mcp.json` from its +AgentOS home directory: + + + +Install local MCP server packages before opening the session so first-run +package-manager output cannot corrupt a stdio handshake. See the selected +[agent guide](/docs/agents/pi) for adapter-specific configuration. + ## Prompt `prompt` accepts native ACP `ContentBlock[]`, not a special AgentOS text format. It never creates a missing session. AgentOS commits the complete user message before dispatching it and never automatically replays a prompt whose delivery may have reached the adapter. @@ -61,7 +75,7 @@ ACP itself does not define a portable history-reading API, and adapters implemen `permissionPolicy` is `reject_all`, `ask`, or `allow_all`, and defaults to `allow_all`. It controls how AgentOS answers native ACP permission requests; it does not configure VM permissions or adapter tool access. Set `permissionPolicy: "ask"` when opening the session before subscribing for interactive decisions; subscribing alone does not change the immutable policy. With `ask`, AgentOS durably records the native ACP `RequestPermissionRequest` as a `permission_request` variant in the generic session-event stream. With the default `allow_all`, AgentOS resolves the adapter request automatically and emits no permission event. Reply to an `ask` request with the exact adapter-supplied `optionId` and an explicit public session ID: ```ts -await agent.respondPermission({ +await agent.sessions.respondPermission({ sessionId: request.sessionId, requestId: request.requestId, optionId: request.options[0].optionId, diff --git a/website/src/content/docs/docs/software.mdx b/website/src/content/docs/docs/software.mdx index 2d8f1c1aec..a991eb80c7 100644 --- a/website/src/content/docs/docs/software.mdx +++ b/website/src/content/docs/docs/software.mdx @@ -30,4 +30,4 @@ Browse all available software packages on the [Registry](/registry). ## Custom Software -Package your own agents, command packages, and WASM commands. See [Software Definition](/docs/custom-software/definition) to define a package, and [Building Binaries](/docs/custom-software/building-wasm) to compile WASM commands from source in the [secure-exec registry](https://github.com/rivet-dev/secure-exec/tree/main/registry). +Package your own agents, command packages, and WASM commands. See [Software Definition](/docs/custom-software/definition) to define a package, and [Building Binaries](/docs/custom-software/building-wasm) to compile WASM commands from source in the [agentos registry](https://github.com/rivet-dev/agentos/tree/main/registry). diff --git a/website/src/content/docs/docs/versus-sandbox.mdx b/website/src/content/docs/docs/versus-sandbox.mdx index ace6b3a6c3..3aa505a06c 100644 --- a/website/src/content/docs/docs/versus-sandbox.mdx +++ b/website/src/content/docs/docs/versus-sandbox.mdx @@ -4,9 +4,9 @@ description: "When to use the lightweight agentOS VM, a full sandbox, or both to skill: true --- -- **agentOS** is a lightweight VM that runs inside your process. Near-zero cold start, low memory, direct backend integration via [bindings](/docs/bindings). +- **agentOS** is a lightweight VM that runs inside your process. Near-zero cold start, low memory, direct backend integration via [custom bindings](/docs/extensions/custom-bindings). - **Sandboxes** are full Linux environments with root access, system packages, and native binary support. -- **You can use both.** agentOS works with sandboxes through [sandbox mounting](/docs/sandbox). Agents run in the lightweight VM by default and spin up a full sandbox on demand. +- **You can use both.** agentOS works with sandboxes through the [external sandbox extension](/docs/extensions/sandboxes). Agents run in the lightweight VM by default and spin up a full sandbox on demand. ## Comparison @@ -14,8 +14,8 @@ skill: true |---|---|---| | **Cost** | Very low. Runs in your process. | Pay per second of uptime. | | **Startup** | Near-zero cold start (~6 ms). | Seconds to spin up. | -| **Backend integration** | Direct. [Bindings](/docs/bindings) call your functions with zero latency. | Indirect. Requires network calls back to your backend. | -| **Credentials** | Stay on the host. [Bindings](/docs/bindings) run your functions server-side; agents see only inputs and outputs. | Must be injected into the sandbox environment. | +| **Backend integration** | Direct. [Custom bindings](/docs/extensions/custom-bindings) call your functions with zero latency. | Indirect. Requires network calls back to your backend. | +| **Credentials** | Stay on the host. [Custom bindings](/docs/extensions/custom-bindings) run your functions server-side; agents see only inputs and outputs. | Must be injected into the sandbox environment. | | **Permissions** | Granular, deny-by-default. | Coarse-grained (container-level). | | **Infrastructure** | `npm install` | Vendor account + API keys. | | **Best for** | Coding, file manipulation, scripting, API calls, orchestration. | Browsers, desktop automation, native compilation, dev servers. | @@ -43,7 +43,7 @@ Spin up a sandbox when the workload needs a real Linux kernel: ### Both together -Use agentOS with [sandbox mounting](/docs/sandbox) for workflows that need both: +Use agentOS with [external sandboxes](/docs/extensions/sandboxes) for workflows that need both: - Agent runs in the agentOS VM with full access to bindings and permissions - Sandbox spins up on demand for heavy tasks diff --git a/website/src/content/docs/docs/webhooks.mdx b/website/src/content/docs/docs/webhooks.mdx deleted file mode 100644 index bfd4217e9e..0000000000 --- a/website/src/content/docs/docs/webhooks.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Webhooks" -description: "Trigger agent sessions directly from external webhooks using Hono." -skill: true ---- - -Use a lightweight HTTP server to receive webhooks and drive an agent. This example uses [Hono](https://hono.dev) to receive Slack webhooks and call an agent directly. - -## Example: Slack webhook to agent - - - - - -## How it works - -1. Slack sends an HTTP POST to `/slack/events` -2. The Hono handler validates the event and prompts one durable AgentOS session -3. AgentOS automatically serializes concurrent prompts targeting that session -4. The handler posts the response back to Slack - -No application queue is needed for prompt ordering. Durable session history remains in SQLite, but AgentOS never automatically replays a prompt whose delivery was uncertain. - -## Recommendations - -- The direct example waits for the turn. If the provider requires an immediate `200`, use the hosting platform's durable background-task primitive and call AgentOS from that task. -- Store webhook secrets in environment variables, not in code. diff --git a/website/src/content/docs/docs/workflows.mdx b/website/src/content/docs/docs/workflows.mdx index d7886f21b0..af17ac3a0d 100644 --- a/website/src/content/docs/docs/workflows.mdx +++ b/website/src/content/docs/docs/workflows.mdx @@ -1,5 +1,5 @@ --- -title: "Workflow Automation" +title: "Workflows & Graphs" description: "Orchestrate multi-step agent tasks with durable workflows." skill: true --- diff --git a/website/src/data/docs-landings.ts b/website/src/data/docs-landings.ts index 8f1b64639d..521db5bb4f 100644 --- a/website/src/data/docs-landings.ts +++ b/website/src/data/docs-landings.ts @@ -15,7 +15,6 @@ import { faHardDrive, faNodeJs, faGauge, - faLink, faTowerBroadcast, faArrowsLeftRight, faDiagramNext, @@ -67,6 +66,15 @@ export const docsLandings: Record = { { title: "Agent to Agent", href: "/cookbooks/agent-to-agent", icon: faArrowsLeftRight, description: "Agents calling agents." }, ], }, + { + title: "Code Execution", + items: [ + { title: "AI Agent Code Exec", href: "/cookbooks/js-ai-agent-code-exec", icon: faRobot, description: "Execute generated code with explicit limits." }, + { title: "Code Mode", href: "/cookbooks/js-code-mode", icon: faTerminal, description: "Let generated code orchestrate narrow bindings." }, + { title: "Dev Servers", href: "/cookbooks/js-dev-servers", icon: faGlobe, description: "Run and drive a long-lived guest server." }, + { title: "Plugin Systems", href: "/cookbooks/js-plugin-systems", icon: faWrench, description: "Evaluate plugins inside a restricted VM." }, + ], + }, { title: "Sessions & Permissions", items: [ @@ -83,7 +91,6 @@ export const docsLandings: Record = { items: [ { title: "Cron", href: "/cookbooks/cron", icon: faClock, description: "Scheduled jobs." }, { title: "Workflows", href: "/cookbooks/workflows", icon: faDiagramNext, description: "Durable workflows." }, - { title: "Webhooks", href: "/cookbooks/webhooks", icon: faLink, description: "Webhook handling." }, ], }, { diff --git a/website/src/data/registry.ts b/website/src/data/registry.ts index 60d7eaec10..10c6b60439 100644 --- a/website/src/data/registry.ts +++ b/website/src/data/registry.ts @@ -242,7 +242,7 @@ export const registry = setup({ use: { vm } });`, "Mount a sandbox filesystem and expose process management bindings. Works with any Sandbox Agent provider.", types: ["binding", "file-system"], icon: "Monitor", - docsHref: "/docs/sandbox", + docsHref: "/docs/extensions/sandboxes", }, // Sandbox Mounting { diff --git a/website/src/generated/registry.json b/website/src/generated/registry.json index 4b656488e9..52f204a117 100644 --- a/website/src/generated/registry.json +++ b/website/src/generated/registry.json @@ -1,67 +1,5 @@ { "entries": [ - { - "slug": "pi", - "title": "PI", - "description": "Run the PI coding agent with lightweight, fast execution.", - "types": [ - "agent" - ], - "category": "agents", - "priority": 100, - "package": "@agentos-software/pi", - "status": "available", - "image": "/images/registry/pi.svg", - "docsHref": "/docs/agents/pi", - "agentId": "pi" - }, - { - "slug": "claude-code", - "title": "Claude Code", - "description": "Run Claude Code as an agentOS agent with full tool access, file editing, and shell execution.", - "types": [ - "agent" - ], - "category": "agents", - "priority": 90, - "package": "@agentos-software/claude-code", - "status": "docs", - "beta": true, - "image": "/images/registry/claude-code.svg", - "docsHref": "/docs/agents/claude", - "agentId": "claude" - }, - { - "slug": "codex", - "title": "Codex", - "description": "Run OpenAI's Codex coding agent inside agentOS with programmatic API access.", - "types": [ - "agent" - ], - "category": "agents", - "priority": 80, - "package": "@agentos-software/codex", - "status": "docs", - "beta": true, - "image": "/images/registry/codex.svg", - "docsHref": "/docs/agents/codex", - "agentId": "codex" - }, - { - "slug": "opencode", - "title": "OpenCode", - "description": "Run OpenCode, an open-source coding agent, inside agentOS.", - "types": [ - "agent" - ], - "category": "agents", - "priority": 70, - "package": "@agentos-software/opencode", - "status": "docs", - "image": "/images/registry/opencode.svg", - "docsHref": "/docs/agents/opencode", - "agentId": "opencode" - }, { "slug": "browserbase", "title": "Browserbase", @@ -100,6 +38,18 @@ "package": "@agentos-software/build-essential", "status": "available" }, + { + "slug": "pi", + "title": "PI", + "description": "Run the PI coding agent with lightweight, fast execution.", + "types": [ + "software" + ], + "priority": 100, + "package": "@agentos-software/pi", + "status": "available", + "image": "/images/registry/pi.svg" + }, { "slug": "common", "title": "Common", @@ -112,6 +62,20 @@ "package": "@agentos-software/common", "status": "available" }, + { + "slug": "claude-code", + "title": "Claude Code", + "description": "Run Claude Code as an agentOS agent with full tool access, file editing, and shell execution.", + "types": [ + "software" + ], + "priority": 90, + "package": "@agentos-software/claude-code", + "status": "docs", + "beta": true, + "image": "/images/registry/claude-code.svg", + "docsHref": "/docs/agents/claude" + }, { "slug": "git", "title": "git", @@ -137,6 +101,20 @@ "package": "@agentos-software/ripgrep", "status": "available" }, + { + "slug": "codex", + "title": "Codex", + "description": "Run OpenAI's Codex coding agent inside agentOS with programmatic API access.", + "types": [ + "software" + ], + "priority": 80, + "package": "@agentos-software/codex", + "status": "docs", + "beta": true, + "image": "/images/registry/codex.svg", + "docsHref": "/docs/agents/codex" + }, { "slug": "jq", "title": "jq", @@ -176,6 +154,19 @@ "status": "available", "image": "/images/registry/duckdb.svg" }, + { + "slug": "opencode", + "title": "OpenCode", + "description": "Run OpenCode, an open-source coding agent, inside agentOS.", + "types": [ + "software" + ], + "priority": 70, + "package": "@agentos-software/opencode", + "status": "docs", + "image": "/images/registry/opencode.svg", + "docsHref": "/docs/agents/opencode" + }, { "slug": "vim", "title": "vim", diff --git a/website/src/generated/routes.json b/website/src/generated/routes.json index 98183e3340..e6b11961f0 100644 --- a/website/src/generated/routes.json +++ b/website/src/generated/routes.json @@ -16,32 +16,16 @@ "title": "Authentication", "description": "Authenticate connections to agentOS actors using Rivet Actor connection params and hooks." }, - "/docs/docs/benchmarks": { - "title": "Benchmarks", - "description": "Performance benchmarks comparing agentOS to traditional sandbox providers." - }, - "/docs/docs/bindings": { - "title": "Bindings", - "description": "Expose custom host functions to agents as CLI commands inside the VM." - }, - "/docs/docs/browser": { - "title": "Browser", - "description": "Let agents read and search the web from an agentOS VM using Browserbase's cloud browser through the browse CLI — no local browser or sandbox required." - }, "/docs/docs/core": { - "title": "Core Package", - "description": "Use @rivet-dev/agentos-core standalone for direct VM control without the Rivet Actor runtime." - }, - "/docs/docs/cost-evaluation": { - "title": "Cost Evaluation", - "description": "How agentOS compares on cost to per-second sandbox providers when you run coding-agent VMs on your own hardware." + "title": "Direct VM API", + "description": "Use the direct AgentOS VM API or layer it into an AgentOS actor." }, "/docs/docs/crash-course": { "title": "Crash Course", "description": "Run coding agents inside isolated VMs with full filesystem, process, and network control." }, "/docs/docs/cron": { - "title": "Cron Jobs", + "title": "Crons & Loops", "description": "Schedule recurring commands and agent sessions in agentOS VMs." }, "/docs/docs/debugging": { @@ -60,21 +44,13 @@ "title": "Introduction", "description": "Run coding agents inside isolated VMs with full filesystem, process, and network control." }, - "/docs/docs/js-runtime": { - "title": "JavaScript Runtime", - "description": "How agentOS runs guest JavaScript: native V8 acceleration, low memory overhead, and Node.js compatibility." - }, "/docs/docs/limitations": { "title": "Limitations", "description": "What the agentOS VM does not support, and how to work around it." }, - "/docs/docs/llm-credentials": { - "title": "LLM Credentials", - "description": "Pass LLM API keys to agent sessions securely." - }, - "/docs/docs/llm-gateway": { - "title": "Embedded LLM Gateway", - "description": "Route, meter, and manage LLM API calls from agents." + "/docs/docs/models-and-credentials": { + "title": "Models & Credentials", + "description": "Choose agent models and pass provider credentials to sessions securely." }, "/docs/docs/multiplayer": { "title": "Multiplayer", @@ -84,9 +60,9 @@ "title": "Networking & Previews", "description": "Proxy HTTP requests into agentOS VMs and create shareable preview URLs." }, - "/docs/docs/nodejs-runtime": { - "title": "Node.js Runtime", - "description": "Run Node.js in agentOS: native V8 acceleration, the node CLI, installing packages, and Node.js compatibility." + "/docs/docs/performance": { + "title": "Performance", + "description": "AgentOS latency, memory, cost, and benchmark methodology." }, "/docs/docs/permissions": { "title": "Permissions", @@ -100,10 +76,6 @@ "title": "Processes & Shell", "description": "Execute commands, spawn long-running processes, and open interactive shells in agentOS VMs." }, - "/docs/docs/python-runtime": { - "title": "Python Runtime", - "description": "Run Python in agentOS: the python CLI, installing packages ahead of time or at runtime, and what's supported." - }, "/docs/docs/quickstart": { "title": "Quickstart", "description": "Set up an agentOS actor, create a session, and run your first coding agent." @@ -112,10 +84,6 @@ "title": "Resource Limits", "description": "Cap per-VM resources, JavaScript CPU/wall-clock time, Python execution, and WASM runtime work so guest code can never exhaust the host." }, - "/docs/docs/sandbox": { - "title": "Sandbox Mounting", - "description": "Extend agentOS with full sandboxes for heavy workloads like browsers, desktop automation, and compilation." - }, "/docs/docs/security-model": { "title": "Security Model", "description": "Trust boundaries, isolation guarantees, and the agentOS threat model." @@ -136,12 +104,8 @@ "title": "agentOS vs Sandbox", "description": "When to use the lightweight agentOS VM, a full sandbox, or both together." }, - "/docs/docs/webhooks": { - "title": "Webhooks", - "description": "Trigger agent sessions directly from external webhooks using Hono." - }, "/docs/docs/workflows": { - "title": "Workflow Automation", + "title": "Workflows & Graphs", "description": "Orchestrate multi-step agent tasks with durable workflows." }, "/docs/docs/agents/claude": { @@ -223,6 +187,34 @@ "/docs/docs/custom-software/publishing": { "title": "Publishing Packages", "description": "Build, publish, and consume agentOS packages — locally, from npm, or from your own repo." + }, + "/docs/docs/execution/bash": { + "title": "Bash", + "description": "Run shell commands and arbitrary argv operations through the AgentOS execution lifecycle." + }, + "/docs/docs/execution/javascript-compatibility": { + "title": "Node.js Compatibility", + "description": "Node.js builtins available to JavaScript running inside AgentOS." + }, + "/docs/docs/execution/javascript": { + "title": "JavaScript", + "description": "Execute JavaScript and TypeScript, install npm dependencies, and manage execution lifecycles in AgentOS." + }, + "/docs/docs/execution/python": { + "title": "Python", + "description": "Execute Python source, files, modules, and package workflows in AgentOS." + }, + "/docs/docs/extensions/browser": { + "title": "Browser Automation", + "description": "Let agents read and search the web from an agentOS VM using Browserbase's cloud browser through the browse CLI — no local browser or sandbox required." + }, + "/docs/docs/extensions/custom-bindings": { + "title": "Custom Bindings", + "description": "Expose custom host functions to agents as CLI commands inside the VM." + }, + "/docs/docs/extensions/sandboxes": { + "title": "External Sandboxes", + "description": "Extend agentOS with full sandboxes for heavy workloads like browsers, desktop automation, and compilation." } } } \ No newline at end of file diff --git a/website/src/pages/[...slug].astro b/website/src/pages/[...slug].astro index 8793ad083e..1985d3eaed 100644 --- a/website/src/pages/[...slug].astro +++ b/website/src/pages/[...slug].astro @@ -15,13 +15,54 @@ import config from "virtual:rivet-docs/config"; export async function getStaticPaths() { const docs = await getCollection("docs"); - return docs.map((entry) => ({ - params: { slug: entry.id }, - props: { entry }, - })); + const legacyRedirects = { + "docs/exec": "/docs/execution/javascript", + "docs/exec/crash-course": "/docs/crash-course", + "docs/exec/architecture": "/docs/architecture", + "docs/exec/security-model": "/docs/security-model", + "docs/exec/benchmarks": "/docs/performance", + "docs/exec/getting-started/javascript": "/docs/execution/javascript", + "docs/exec/getting-started/nodejs": "/docs/execution/javascript", + "docs/exec/getting-started/python": "/docs/execution/python", + "docs/exec/nodejs-compatibility": "/docs/execution/javascript-compatibility", + "docs/exec/python": "/docs/execution/python", + "docs/exec/python/packages": "/docs/execution/python", + "docs/exec/features/typescript": "/docs/execution/javascript", + "docs/exec/features/module-loading": "/docs/execution/javascript", + "docs/exec/features/runtime-platform": "/docs/execution/javascript", + "docs/exec/features/executing-code": "/docs/execution/javascript", + "docs/exec/features/output-capture": "/docs/processes", + "docs/exec/features/long-running-processes": "/docs/processes", + "docs/exec/features/child-processes": "/docs/processes", + "docs/exec/features/bindings": "/docs/extensions/custom-bindings", + "docs/exec/features/permissions": "/docs/permissions", + "docs/exec/features/filesystem": "/docs/filesystem", + "docs/exec/features/networking": "/docs/networking", + "docs/exec/features/resource-limits": "/docs/resource-limits", + "docs/js-runtime": "/docs/execution/javascript", + "docs/nodejs-runtime": "/docs/execution/javascript", + "docs/python-runtime": "/docs/execution/python", + "docs/bindings": "/docs/extensions/custom-bindings", + "docs/browser": "/docs/extensions/browser", + "docs/sandbox": "/docs/extensions/sandboxes", + "docs/llm-credentials": "/docs/models-and-credentials", + "docs/benchmarks": "/docs/performance", + "docs/cost-evaluation": "/docs/performance", + } as const; + return [ + ...docs.map((entry) => ({ + params: { slug: entry.id }, + props: { entry }, + })), + ...Object.entries(legacyRedirects).map(([slug, redirectTo]) => ({ + params: { slug }, + props: { redirectTo }, + })), + ]; } -const { entry } = Astro.props; +const { entry, redirectTo } = Astro.props; +if (redirectTo) return Astro.redirect(redirectTo, 301); const { Content, headings } = await render(entry); const { title, description } = entry.data as { title: string; description?: string }; diff --git a/website/src/pages/registry/[slug].astro b/website/src/pages/registry/[slug].astro index 9908f22062..2c07c22965 100644 --- a/website/src/pages/registry/[slug].astro +++ b/website/src/pages/registry/[slug].astro @@ -68,7 +68,7 @@ const npmHref = packageName // fall back to the relevant documentation page for their type. const docsHref = entry.docsHref ?? - (isSoftware ? "/docs/software" : isSandboxExt ? "/docs/sandbox" : null); + (isSoftware ? "/docs/software" : isSandboxExt ? "/docs/extensions/sandboxes" : null); const configId = entry.status === "config" ? entry.configId : null; const agentId = entry.status === "docs" ? (entry.agentId ?? null) : null; diff --git a/website/tsconfig.typedoc.json b/website/tsconfig.typedoc.json new file mode 100644 index 0000000000..2a466f7863 --- /dev/null +++ b/website/tsconfig.typedoc.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "jsx": "react", + "noEmit": true + }, + "include": [ + "../packages/agentos/src/**/*", + "../packages/javascript/src/**/*", + "../packages/python/src/**/*" + ] +} diff --git a/website/typedoc.json b/website/typedoc.json index 9277eb9f8b..f1b245f8c6 100644 --- a/website/typedoc.json +++ b/website/typedoc.json @@ -1,7 +1,11 @@ { "$schema": "https://typedoc.org/schema.json", - "entryPoints": ["../packages/agentos/src/index.ts"], - "tsconfig": "../packages/agentos/tsconfig.json", + "entryPoints": [ + "../packages/agentos/src/index.ts", + "../packages/javascript/src/index.ts", + "../packages/python/src/index.ts" + ], + "tsconfig": "./tsconfig.typedoc.json", "out": "public/api", "name": "agentOS API Reference", "includeVersion": true,