From 409da8512403a16874053b26e0b6997af7260a76 Mon Sep 17 00:00:00 2001 From: Surma Date: Fri, 6 Nov 2026 15:14:49 +0000 Subject: [PATCH] v3: host crate skeleton, userland workspace, AGENTS.md for v3 The workspace is now host/ and vfs/. v2 crates leave the workspace as reference. host/src/exec.rs is the contract between the process table and the harness. --- AGENTS.md | 84 +-- Cargo.lock | 988 +----------------------------------- Cargo.toml | 11 +- host/Cargo.toml | 16 + host/src/exec.rs | 37 ++ host/src/harness/mod.rs | 8 + host/src/lib.rs | 7 + host/src/main.rs | 33 ++ host/src/process/mod.rs | 8 + host/src/world.rs | 18 + userland/.cargo/config.toml | 2 + userland/Cargo.toml | 7 + 12 files changed, 192 insertions(+), 1027 deletions(-) create mode 100644 host/Cargo.toml create mode 100644 host/src/exec.rs create mode 100644 host/src/harness/mod.rs create mode 100644 host/src/lib.rs create mode 100644 host/src/main.rs create mode 100644 host/src/process/mod.rs create mode 100644 host/src/world.rs create mode 100644 userland/.cargo/config.toml create mode 100644 userland/Cargo.toml diff --git a/AGENTS.md b/AGENTS.md index 5ac9c98..31cf10f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,56 +1,66 @@ -# Working on Sausage +# Working on Sausage (v3) -Sausage is meant to be read and changed by agents, including its own agent. -Keep it that way. +Sausage is a world of WASI programs and durable agents. It is meant to be read and changed by agents, +including its own. Keep it that way. + +This branch (`v3`) rebuilds Sausage. The plan and its decisions (D1, D2, …) are in +`~/research/sausage-v3/PLAN.md`. `PROTOCOL.md`, `DECISIONS.md` and `README.md` still describe v2. + +## The boundary + +- **The world is the sandbox.** Everything inside the world sees and changes the whole world. Do not add + inner boundaries, permissions or per-agent views. The VFS is a safety net against mistakes, not a wall + against attackers. +- **Host calls pierce the sandbox.** The only host import beyond standard WASI is the process interface + (spawn, wait, kill). Do not add another one. Everything else uses standard WASI 0.2 interfaces: files + through the VFS, `wasi:http` (the host API on its reserved host name, credential injection, signing), + and `wasi:sockets`. +- **The credentials manager in the host is the one real security boundary.** Secrets never enter the + world. Approvals need a passkey. +- **Native code is the exception.** The only native work for the world is the Rust builder, and it runs in + user, mount and network namespaces. ## Priorities -1. **Correct.** Every behavior in `PROTOCOL.md` has a test in `cli/tests/host/`. -2. **Simple and short.** Prefer the obvious code. No abstraction for one - caller. No configuration that nobody asked for. -3. **Readable.** A new reader must understand a file without the others. - Each module starts with a doc comment that says what it owns. -4. **Efficient** on the paths that run per call. -5. **Raw and minimal.** Sausage has no permissions, sandboxing beyond WASI, - limits, or authentication. Do not add them to the core. Add nothing to - the host that a plugin (or the agent, by changing itself) could do. +1. **Correct.** Every behavior has a test. +2. **Simple and short.** Prefer the obvious code. No abstraction for one caller. No configuration that + nobody asked for. +3. **Readable.** A new reader must understand a file without the others. Each module starts with a doc + comment that says what it owns. +4. **Efficient** on the paths that run per command and per model turn. ## Layout -- `cli/`: the host (`sausage` binary and library): the core, the native - `cargo` plugin, the WASI test runner, and the console. -- `vfs/`: `sausage-vfs`, the virtual filesystem for WASI guests. It knows - nothing about Sausage. -- `interface/`: `sausage-interface`: OpenRPC documents, the compatibility - check, and the generator of client code. -- `sdk/`: `sausage-plugin`, the SDK for Rust plugins, and `sdk/macros/`, its - macros. Never published: `cargo` points `sausage-plugin = "0.1"` at its - local copy. -- `agent/`: the agent plugin. `sausage init` embeds and builds it. -- `examples/`: small plugins. They are not workspace members. -- `PROTOCOL.md`: the contract between the core and the plugins. Change it in - the same commit as the behavior. `DECISIONS.md` says why; when the two - disagree, `PROTOCOL.md` and the code win. +- `host/`: the host crate (package and binary `sausage`): the world, the process table, the harness. + `host/src/exec.rs` is the contract between the harness and the process table. +- `vfs/`: `sausage-vfs`, the virtual filesystem for WASI guests and for host code. It knows nothing + about Sausage. Host code reads and writes the world only through it. +- `userland/`: the default CLIs of a world, a separate workspace built for `wasm32-wasip2`. +- `spikes/`: accepted prototypes. Read them for evidence, copy from them, do not build on them. +- `cli/`, `interface/`, `sdk/`, `agent/`, `examples/`: v2 code, outside the workspace. Copy what v3 + needs. They are deleted at the end of P1. + +## Programs in the world + +- Agents write CLIs and servers. That they are WASI binaries is a detail, not a concept to explain. +- The platform is WASI 0.2 components. Rust programs build for `wasm32-wasip2`. WASI 0.1 programs run + through an adapter. ## Checks ```sh -nix flake check -L # all tests below; CI runs this on every push -nix develop -c cargo test --workspace # fast with a warm cache: run it during development -nix develop -c cargo test -p sausage --test host -- core:: # one topic of the host tests -nix develop -c cargo build --release -p agent --target wasm32-wasip2 -nix develop -c cargo clippy --workspace +nix develop -c cargo test --workspace # host and vfs +nix develop -c cargo clippy --workspace --all-targets -- -D warnings +nix develop -c cargo build --manifest-path userland/Cargo.toml --release ``` -`nix run -- init` and `nix run -- run` must keep working without other -setup. +`nix flake check` still describes v2 and is updated later in P1. Tests must stay fast: - Only a few tests may wait for a timing (grace periods, deadlines). - Poll for a condition with a deadline. Do not sleep. - Do not test unrealistic load, such as many fast cycles. -- `#[ignore]` only disables a test for a short time, with the reason in the - attribute. -- Tests that build plugins use the persistent cache in - `env!("CARGO_TARGET_TMPDIR")`. +- `#[ignore]` only disables a test for a short time, with the reason in the attribute. +- Tests that build or compile guests use a persistent cache (for example under + `env!("CARGO_TARGET_TMPDIR")`), so a warm run does not compile again. diff --git a/Cargo.lock b/Cargo.lock index 6277921..b89d4b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,17 +11,6 @@ dependencies = [ "gimli", ] -[[package]] -name = "agent" -version = "0.1.0" -dependencies = [ - "sausage-plugin", - "serde", - "serde_json", - "serde_yaml_ng", - "wstd", -] - [[package]] name = "allocator-api2" version = "0.2.21" @@ -34,15 +23,6 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" -[[package]] -name = "android_system_properties" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" -dependencies = [ - "libc", -] - [[package]] name = "anstream" version = "1.0.0" @@ -105,12 +85,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bc62ac97cc33321f50863d514c3bc38a453947a8f9e781137e47c7401020aed" -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - [[package]] name = "async-trait" version = "0.1.92" @@ -122,12 +96,6 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - [[package]] name = "autocfg" version = "1.5.1" @@ -290,17 +258,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "chrono" -version = "0.4.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" -dependencies = [ - "iana-time-zone", - "num-traits", - "windows-link", -] - [[package]] name = "clap" version = "4.6.7" @@ -341,15 +298,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" -[[package]] -name = "clipboard-win" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" -dependencies = [ - "error-code", -] - [[package]] name = "cobs" version = "0.3.0" @@ -365,12 +313,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "core_detect" version = "1.0.0" @@ -645,12 +587,6 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - [[package]] name = "either" version = "1.19.0" @@ -683,12 +619,6 @@ dependencies = [ "simdutf8", ] -[[package]] -name = "endian-type" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869b0adbda23651a9c5c0c3d270aac9fcb52e8622a8f2b17e57802d7791962f2" - [[package]] name = "equivalent" version = "1.0.3" @@ -705,12 +635,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "error-code" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5343afd4a8365a643ac588dab4cf234a190c7f6c88c9f6dd6ffe00837661b7" - [[package]] name = "fallible-iterator" version = "0.3.0" @@ -723,15 +647,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.5.0" @@ -782,15 +697,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - [[package]] name = "futures" version = "0.3.34" @@ -799,7 +705,6 @@ checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -822,49 +727,12 @@ version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" -[[package]] -name = "futures-executor" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - [[package]] name = "futures-sink" version = "0.3.34" @@ -886,7 +754,6 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", - "futures-macro", "futures-sink", "futures-task", "memchr", @@ -953,39 +820,12 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "glob" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" - -[[package]] -name = "h2" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d29020232d6aa3fb1daca64c1127cf662cf97f254ae16c18c05b8ab635fc118" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "allocator-api2", - "equivalent", "foldhash", ] @@ -1015,120 +855,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "http" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3e324da4c95177d6291d4c8730197c0d1822f8a9766814a4a44fa5ab797c9c" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-util" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff" -dependencies = [ - "bytes", - "http", - "http-body", - "hyper", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "icu_collections" version = "2.3.0" @@ -1239,25 +965,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "include_dir" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" -dependencies = [ - "include_dir_macros", -] - -[[package]] -name = "include_dir_macros" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" -dependencies = [ - "proc-macro2", - "quote", -] - [[package]] name = "indexmap" version = "2.14.2" @@ -1270,44 +977,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "inotify" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc00ea907cab49550b7da656f80ebb97be1b997d931fbcd28d39734e17ce592" -dependencies = [ - "bitflags", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c033f80b2c113cdf91ab7a33faa9cbc014726dcad99880c8609af2a370edf37d" -dependencies = [ - "libc", -] - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "inventory" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6928282826c822ad91bf1c9a1cb90a30ba1c26770749929b4656cd6be829cd7c" -dependencies = [ - "rustversion", -] - [[package]] name = "io-extras" version = "0.19.0" @@ -1398,26 +1067,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kqueue" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d763e5b24120b4ddf50de6c92308156765aabfbbccebf401da7cff2d70a41ea" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" -dependencies = [ - "bitflags", - "libc", -] - [[package]] name = "leb128" version = "0.2.7" @@ -1523,7 +1172,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", - "log", "wasi", "windows-sys 0.61.2", ] @@ -1534,54 +1182,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d" -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.31.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "notify" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" -dependencies = [ - "bitflags", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "notify-types", - "walkdir", - "windows-sys 0.60.2", -] - -[[package]] -name = "notify-types" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" -dependencies = [ - "bitflags", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1615,12 +1215,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - [[package]] name = "parking_lot" version = "0.12.5" @@ -1693,16 +1287,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.119", -] - [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1785,16 +1369,6 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "radix_trie" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4431027dcd37fc2a73ef740b5f233aa805897935b8bce0195e41bbf9a3289a" -dependencies = [ - "endian-type", - "nibble_vec", -] - [[package]] name = "rand" version = "0.10.3" @@ -1861,26 +1435,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "ref-cast" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - [[package]] name = "regalloc2" version = "0.15.2" @@ -1902,30 +1456,6 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" -[[package]] -name = "regress" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158a764437582235e3501f683b93a0a6f8d825d04a789dbe5ed30b8799b8908a" -dependencies = [ - "hashbrown 0.16.1", - "memchr", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.17", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - [[package]] name = "rsqlite-vfs" version = "0.1.1" @@ -1986,41 +1516,6 @@ dependencies = [ "rustix", ] -[[package]] -name = "rustls" -version = "0.23.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" -dependencies = [ - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pki-types" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" -dependencies = [ - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - [[package]] name = "rustversion" version = "1.0.23" @@ -2039,113 +1534,15 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "rustyline" -version = "19.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e1d6bd81c2d5feafd2419138df9183c45a10a492c4e873b8b0acb8eb2b549e" -dependencies = [ - "bitflags", - "clipboard-win", - "home", - "libc", - "log", - "memchr", - "nix", - "radix_trie", - "unicode-segmentation", - "unicode-width", - "utf8parse", - "windows-sys 0.61.2", -] - -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "sausage" -version = "0.1.0" +version = "0.3.0" dependencies = [ "anyhow", - "bytes", - "chrono", + "async-trait", "clap", - "http", - "http-body-util", - "hyper", - "hyper-util", - "include_dir", - "nix", - "notify", - "rusqlite", - "rustyline", - "sausage-interface", "sausage-vfs", - "serde", - "serde_json", - "serde_yaml_ng", - "sha2", - "tempfile", "tokio", - "toml_edit", - "uuid", - "wasmtime", - "wasmtime-wasi", - "wasmtime-wasi-http", -] - -[[package]] -name = "sausage-interface" -version = "0.1.0" -dependencies = [ - "prettyplease", - "proc-macro2", - "proptest", - "quote", - "schemars 0.8.22", - "schemars 1.2.3", - "serde", - "serde_json", - "syn 2.0.119", - "typify", -] - -[[package]] -name = "sausage-plugin" -version = "0.1.0" -dependencies = [ - "futures", - "inventory", - "sausage-interface", - "sausage-plugin-macros", - "schemars 1.2.3", - "serde", - "serde_json", - "trybuild", - "wstd", -] - -[[package]] -name = "sausage-plugin-macros" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "sausage-interface", - "serde_json", - "syn 2.0.119", ] [[package]] @@ -2165,55 +1562,6 @@ dependencies = [ "wasmtime-wasi", ] -[[package]] -name = "schemars" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" -dependencies = [ - "dyn-clone", - "schemars_derive 0.8.22", - "serde", - "serde_json", -] - -[[package]] -name = "schemars" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab508826f74a77ca9d5aba6ff19b522583ee3eaf28a19384ff3d0e5835fadf6e" -dependencies = [ - "dyn-clone", - "ref-cast", - "schemars_derive 1.2.3", - "serde", - "serde_json", -] - -[[package]] -name = "schemars_derive" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals 0.29.1", - "syn 2.0.119", -] - -[[package]] -name = "schemars_derive" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c3a92094fa7d61aa124645844facb6b554dfc797136d0f5fd1f890e2bffc69" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals 0.30.0", - "syn 3.0.9", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -2260,28 +1608,6 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "serde_derive_internals" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "serde_derive_internals" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f852137cce035d6a4df67ccce505ff6b3e9fd3a10e3e52b24dc71e650bb1a9bd" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", -] - [[package]] name = "serde_json" version = "1.0.154" @@ -2304,31 +1630,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_tokenstream" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c49585c52c01f13c5c2ebb333f14f6885d76daa768d8a037d28017ec538c69" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "syn 2.0.119", -] - -[[package]] -name = "serde_yaml_ng" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f" -dependencies = [ - "indexmap", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - [[package]] name = "sha2" version = "0.10.9" @@ -2411,12 +1712,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "syn" version = "2.0.119" @@ -2456,19 +1751,13 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" -[[package]] -name = "target-tuple" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876fef147edbcbddc8ac5cbbba92c7b86519e314e86638596c09673b2ed01e7f" - [[package]] name = "tempfile" version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "fastrand 2.5.0", + "fastrand", "getrandom 0.4.3", "once_cell", "rustix", @@ -2562,30 +1851,6 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "tokio-rustls" -version = "0.26.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "libc", - "pin-project-lite", - "tokio", -] - [[package]] name = "toml" version = "1.1.8+spec-1.1.0" @@ -2619,7 +1884,6 @@ dependencies = [ "indexmap", "toml_datetime", "toml_parser", - "toml_writer", "winnow", ] @@ -2669,80 +1933,12 @@ dependencies = [ "once_cell", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "trybuild" -version = "1.0.122" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62db9c92d704393fbf2132041720cc80b689f2d3f28521015c2ac866223c11b8" -dependencies = [ - "glob", - "serde", - "serde_derive", - "serde_json", - "target-tuple", - "termcolor", - "toml", -] - [[package]] name = "typenum" version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" -[[package]] -name = "typify" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0b89f47309feaeb23c4509c15c9a04234f7deccef6f96c3bfe95319819a304" -dependencies = [ - "typify-impl", - "typify-macro", -] - -[[package]] -name = "typify-impl" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7b026f540b148b81043c720889dbb942b08659aa8a43f624ac4f04dbfc1861" -dependencies = [ - "heck", - "log", - "proc-macro2", - "quote", - "regress", - "schemars 0.8.22", - "semver", - "serde", - "serde_json", - "syn 2.0.119", - "thiserror 2.0.21", - "unicode-ident", -] - -[[package]] -name = "typify-macro" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ed96c57f06ae0839416b986921a98f18b220da63bbb243a8570a00c8492183" -dependencies = [ - "proc-macro2", - "quote", - "schemars 0.8.22", - "semver", - "serde", - "serde_json", - "serde_tokenstream", - "syn 2.0.119", - "typify-impl", -] - [[package]] name = "unarray" version = "0.1.4" @@ -2755,30 +1951,12 @@ version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" -[[package]] -name = "unicode-segmentation" -version = "1.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" - [[package]] name = "unicode-width" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" version = "2.5.8" @@ -2809,7 +1987,6 @@ version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" dependencies = [ - "getrandom 0.4.3", "js-sys", "wasm-bindgen", ] @@ -2835,31 +2012,6 @@ dependencies = [ "libc", ] -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec4cdd0dd910afe868b7ef477227d8d538b46b3075031afee8a9f2acb0a2ed0b" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -3266,31 +2418,6 @@ dependencies = [ "winx", ] -[[package]] -name = "wasmtime-wasi-http" -version = "49.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9248a9ab044a9a4f414afdd14ffb38d7c58d4e2cc0f119ace9464d698f6f3bde" -dependencies = [ - "async-trait", - "bytes", - "futures", - "http", - "http-body", - "http-body-util", - "hyper", - "pin-project-lite", - "rustls", - "tokio", - "tokio-rustls", - "tokio-util", - "tracing", - "wasmtime", - "wasmtime-wasi", - "wasmtime-wasi-io", - "webpki-roots", -] - [[package]] name = "wasmtime-wasi-io" version = "49.0.3" @@ -3335,15 +2462,6 @@ dependencies = [ "wast 262.0.0", ] -[[package]] -name = "webpki-roots" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "wiggle" version = "49.0.3" @@ -3415,74 +2533,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.59.0" @@ -3723,38 +2779,6 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" -[[package]] -name = "wstd" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29b52936db10a79bb724dadd1c2c3aac958e8229dcb1f1c7f2b7044ca9fc6a3a" -dependencies = [ - "anyhow", - "async-task", - "bytes", - "futures-lite", - "http", - "http-body", - "http-body-util", - "itoa", - "pin-project-lite", - "serde", - "serde_json", - "slab", - "wasip2", - "wstd-macro", -] - -[[package]] -name = "wstd-macro" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "153db9b65508bf6c2efe26617169840c03671ba5719a35868db7682a5261f7d4" -dependencies = [ - "quote", - "syn 2.0.119", -] - [[package]] name = "yoke" version = "0.8.3" @@ -3799,12 +2823,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zeroize" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" - [[package]] name = "zerotrie" version = "0.2.5" diff --git a/Cargo.toml b/Cargo.toml index f8c8f48..0954500 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,12 @@ [workspace] resolver = "3" -members = ["cli", "vfs", "interface", "sdk", "sdk/macros", "agent"] -default-members = ["cli"] -# Examples are standalone plugins, each with its own empty [workspace]. -exclude = ["examples"] +members = ["host", "vfs"] +default-members = ["host"] +# Standalone crates with their own empty [workspace]: v2 code kept as reference +# until the end of P1, the spikes, and the userland (its own wasm32-wasip2 workspace). +exclude = ["cli", "interface", "sdk", "agent", "examples", "spikes", "userland"] # Wasmtime compiles components with Cranelift. Optimize dependencies in dev -# builds, so that tests and debug runs start plugins quickly. +# builds, so that tests and debug runs start guests quickly. [profile.dev.package."*"] opt-level = 2 diff --git a/host/Cargo.toml b/host/Cargo.toml new file mode 100644 index 0000000..830af82 --- /dev/null +++ b/host/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "sausage" +version = "0.3.0" +edition = "2024" +description = "A world of WASI programs and durable agents." + +[[bin]] +name = "sausage" +path = "src/main.rs" + +[dependencies] +anyhow = "1" +async-trait = "0.1" +clap = { version = "4", features = ["derive"] } +tokio = { version = "1", features = ["full"] } +sausage-vfs = { version = "0.1.0", path = "../vfs" } diff --git a/host/src/exec.rs b/host/src/exec.rs new file mode 100644 index 0000000..4dad1f4 --- /dev/null +++ b/host/src/exec.rs @@ -0,0 +1,37 @@ +//! The contract between the harness and the process table: run a command in the world. +//! The process table implements it; the harness's `bash` tool uses it. +use std::time::Duration; + +/// What to run: a shell string (run by the world's `sh -c`) or an argv without a shell. +#[derive(Clone, Debug)] +pub enum Command { + Shell(String), + Argv(Vec), +} + +/// How to run it. `cwd` is a world path. `timeout` ends the command and all its processes. +#[derive(Clone, Debug, Default)] +pub struct Options { + pub cwd: String, + pub env: Vec<(String, String)>, + pub timeout: Option, +} + +/// The stream that one output chunk came from. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Stream { + Stdout, + Stderr, +} + +/// Run commands in the world. Dropping the future kills the command and all processes it started. +#[async_trait::async_trait] +pub trait Exec: Send + Sync { + /// Run to completion and return the exit status. `output` gets each chunk as it arrives, in order. + async fn exec( + &self, + command: Command, + options: Options, + output: &mut (dyn FnMut(Stream, &[u8]) + Send), + ) -> anyhow::Result; +} diff --git a/host/src/harness/mod.rs b/host/src/harness/mod.rs new file mode 100644 index 0000000..0e0d05c --- /dev/null +++ b/host/src/harness/mod.rs @@ -0,0 +1,8 @@ +//! The durable agent harness: V8 with pi-durable, harness storage, and the tools' environment. +//! Owned by task T9. +use std::path::Path; + +/// Start the world at `world` with the harness and a console. +pub async fn run(_world: &Path) -> anyhow::Result<()> { + anyhow::bail!("the harness does not exist yet (T9)") +} diff --git a/host/src/lib.rs b/host/src/lib.rs new file mode 100644 index 0000000..1f1056f --- /dev/null +++ b/host/src/lib.rs @@ -0,0 +1,7 @@ +//! The Sausage v3 host: a world folder behind a virtual filesystem, WASI programs in a process table, +//! and the durable agent harness. See `~/research/sausage-v3/PLAN.md` until the docs move here. + +pub mod exec; +pub mod harness; +pub mod process; +pub mod world; diff --git a/host/src/main.rs b/host/src/main.rs new file mode 100644 index 0000000..5c15a42 --- /dev/null +++ b/host/src/main.rs @@ -0,0 +1,33 @@ +//! The `sausage` binary: subcommands only, each delegates to its module. +use clap::{Parser, Subcommand}; +use std::path::PathBuf; + +#[derive(Parser)] +#[command(version, about)] +struct Cli { + #[command(subcommand)] + command: Command, +} + +#[derive(Subcommand)] +enum Command { + /// Start a world: the harness, its services and a console. + Run { world: PathBuf }, + /// Run a shell in a world. With `-c`, run one command and exit with its status. + Sh { + world: PathBuf, + #[arg(short = 'c')] + command: Option, + }, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + match Cli::parse().command { + Command::Run { world } => sausage::harness::run(&world).await, + Command::Sh { world, command } => { + let status = sausage::process::sh(&world, command).await?; + std::process::exit(status); + } + } +} diff --git a/host/src/process/mod.rs b/host/src/process/mod.rs new file mode 100644 index 0000000..d3854d7 --- /dev/null +++ b/host/src/process/mod.rs @@ -0,0 +1,8 @@ +//! The process table: WASI programs in their own stores, the process interface (spawn, wait, kill), +//! `/proc`, and the `Exec` implementation. Owned by task T8. +use std::path::Path; + +/// Run a shell in the world at `world`, or one command with `command`. Returns the exit status. +pub async fn sh(_world: &Path, _command: Option) -> anyhow::Result { + anyhow::bail!("the process table does not exist yet (T8)") +} diff --git a/host/src/world.rs b/host/src/world.rs new file mode 100644 index 0000000..929cdbf --- /dev/null +++ b/host/src/world.rs @@ -0,0 +1,18 @@ +//! A world folder and the one virtual root that host code and guests share. +use sausage_vfs::{Host, Layer, Mounts, Process}; +use std::{path::Path, sync::Arc}; + +/// An open world. `root` is the filesystem every guest sees as `/`; host code (the harness's file +/// tools) reads and writes through the same layer, so both always see the same files. +pub struct World { + pub root: Arc, +} + +impl World { + /// Open the world folder at `path`. The process table adds more mounts (`/proc`, `/run`). + pub fn open(path: &Path) -> anyhow::Result { + let mut mounts = Mounts::default(); + mounts.mount("/", Arc::new(Host::new(path, Process::default())?), false); + Ok(World { root: Arc::new(mounts) }) + } +} diff --git a/userland/.cargo/config.toml b/userland/.cargo/config.toml new file mode 100644 index 0000000..f68f33c --- /dev/null +++ b/userland/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-wasip2" diff --git a/userland/Cargo.toml b/userland/Cargo.toml new file mode 100644 index 0000000..7a39f6b --- /dev/null +++ b/userland/Cargo.toml @@ -0,0 +1,7 @@ +# The default CLIs of a world, built for wasm32-wasip2. Its own workspace, outside the host's. +[workspace] +resolver = "3" +members = [] + +[profile.release] +opt-level = 3