From 538c79fa2f554721629dd0b05ac66bd01f7a99b8 Mon Sep 17 00:00:00 2001 From: skaunov Date: Sat, 4 Apr 2026 10:18:28 +0300 Subject: [PATCH 1/2] un-hardcode `WASI_VERSION` --- build.rs | 4 ++-- src/build/mod.rs | 24 ++++++++++++++++-------- src/build_start_package/mod.rs | 2 ++ src/main.rs | 22 ++++++++++++++++++---- src/run_tests/mod.rs | 5 ++++- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/build.rs b/build.rs index 1bdf8338..1f9f1d4e 100644 --- a/build.rs +++ b/build.rs @@ -6,7 +6,7 @@ const TEMPLATES_DIR: &str = "src/new/templates"; const TARGET_DIR: &str = "target"; const NEW_INCLUDES: &str = "new_includes.rs"; -/// create target/new_includes.rs to build templates into binary +/// create to build templates into binary fn make_new_includes() -> anyhow::Result<()> { let mut output_buffer = Vec::new(); writeln!( @@ -25,7 +25,7 @@ fn make_new_includes() -> anyhow::Result<()> { let target_dir = Path::new(TARGET_DIR); let new_output_path = target_dir.join(NEW_INCLUDES); - // create *_includes.rs if it does not exist + // create <*_includes.rs> if it does not exist if !target_dir.exists() { fs::create_dir_all(target_dir)?; } diff --git a/src/build/mod.rs b/src/build/mod.rs index 5bab10fd..6d0734ba 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -38,6 +38,7 @@ mod wit_generator; // Default Rust toolchain to use for builds pub const DEFAULT_RUST_TOOLCHAIN: &str = "+1.85.1"; +pub const DEFAULT_WASI_VERSION: semver::Version = semver::Version::new(33, 0, 1); const PY_VENV_NAME: &str = "process_env"; const JAVASCRIPT_SRC_PATH: &str = "src/lib.js"; @@ -47,7 +48,6 @@ const PACKAGE_JSON_NAME: &str = "package.json"; const COMPONENTIZE_MJS_NAME: &str = "componentize.mjs"; const HYPERWARE_WIT_1_0_0_URL: &str = "https://raw.githubusercontent.com/hyperware-ai/hyperware-wit/v1.0.0/hyperware.wit"; -const WASI_VERSION: &str = "33.0.0"; // TODO: un-hardcode const DEFAULT_WORLD_1_0_0: &str = "process-v1"; const KINODE_PROCESS_LIB_CRATE_NAME: &str = "hyperware_process_lib"; @@ -956,6 +956,7 @@ async fn compile_rust_wasm_process( features: &str, verbose: bool, toolchain: &str, + wasi_version: semver::Version, ) -> Result<()> { let Some(package_dir) = process_dir.parent() else { return Err(eyre!( @@ -977,10 +978,7 @@ async fn compile_rust_wasm_process( let wasi_snapshot_file = package_dir .join("target") .join("wasi_snapshot_preview1.wasm"); - let wasi_snapshot_url = format!( - "https://github.com/bytecodealliance/wasmtime/releases/download/v{}/wasi_snapshot_preview1.reactor.wasm", - WASI_VERSION, - ); + let wasi_snapshot_url = format!("https://github.com/bytecodealliance/wasmtime/releases/download/v{wasi_version}/wasi_snapshot_preview1.reactor.wasm"); download_file(&wasi_snapshot_url, &wasi_snapshot_file).await?; // Copy wit directory to bindings @@ -1163,9 +1161,10 @@ async fn compile_package_item( is_js_process: bool, verbose: bool, toolchain: String, + wasi_version: semver::Version, ) -> Result<()> { if is_rust_process { - compile_rust_wasm_process(&path, &features, verbose, &toolchain).await?; + compile_rust_wasm_process(&path, &features, verbose, &toolchain, wasi_version).await?; } else if is_py_process { let python = get_python_version(None, None)? .ok_or_else(|| eyre!("kit requires Python 3.10 or newer"))?; @@ -1225,6 +1224,7 @@ async fn fetch_dependencies( force: bool, verbose: bool, toolchain: &str, + wasi_version: &semver::Version, ) -> Result<()> { if let Err(e) = Box::pin(execute( package_dir, @@ -1246,6 +1246,7 @@ async fn fetch_dependencies( verbose, true, toolchain, + wasi_version, )) .await { @@ -1285,6 +1286,7 @@ async fn fetch_dependencies( verbose, false, toolchain, + wasi_version, )) .await?; fetch_local_built_dependency(apis, wasm_paths, &local_dependency)?; @@ -1563,8 +1565,8 @@ fn is_cluded(path: &Path, include: &HashSet, exclude: &HashSet (include.is_empty() || include.contains(path)) && !exclude.contains(path) } -/// package dir looks like: -/// +/// package dir looks like this +/// ```text /// metadata.json /// api/ <- optional /// my_package:publisher.os-v0.wit @@ -1584,6 +1586,7 @@ fn is_cluded(path: &Path, include: &HashSet, exclude: &HashSet /// target/ <- built /// api/ /// wit/ +/// ``` #[instrument(level = "trace", skip_all)] async fn compile_package( package_dir: &Path, @@ -1603,6 +1606,7 @@ async fn compile_package( hyperapp_processed_projects: Option>, ignore_deps: bool, // for internal use; may cause problems when adding recursive deps toolchain: &str, + wasi_version: &semver::Version, ) -> Result<()> { let metadata = read_and_update_metadata(package_dir)?; let mut wasm_paths = HashSet::new(); @@ -1635,6 +1639,7 @@ async fn compile_package( force, verbose, toolchain, + &wasi_version, ) .await? } @@ -1692,6 +1697,7 @@ async fn compile_package( is_js_process, verbose.clone(), toolchain.to_string(), + wasi_version.clone(), )); } while let Some(res) = tasks.join_next().await { @@ -1776,6 +1782,7 @@ pub async fn execute( verbose: bool, ignore_deps: bool, // for internal use; may cause problems when adding recursive deps toolchain: &str, + wasi_version: &semver::Version, ) -> Result<()> { debug!( "execute: @@ -1915,6 +1922,7 @@ pub async fn execute( hyperapp_processed_projects, ignore_deps, toolchain, + wasi_version, ) .await?; } diff --git a/src/build_start_package/mod.rs b/src/build_start_package/mod.rs index 7a9c2f21..28342b9b 100644 --- a/src/build_start_package/mod.rs +++ b/src/build_start_package/mod.rs @@ -27,6 +27,7 @@ pub async fn execute( force: bool, verbose: bool, toolchain: &str, + wasi_version: &semver::Version, ) -> Result<()> { build::execute( package_dir, @@ -48,6 +49,7 @@ pub async fn execute( verbose, false, toolchain, + &wasi_version, ) .await?; start_package::execute(package_dir, url).await?; diff --git a/src/main.rs b/src/main.rs index 4f96df66..2456d071 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,19 +64,19 @@ fn parse_u128_with_underscores(s: &str) -> Result { #[instrument(level = "trace", skip_all)] fn parse_rust_toolchain(s: &str) -> Result { - // Validate the format: must start with '+' followed by version or channel name + // Validate the format: must start with '+' followed by version or channel name. if !s.starts_with('+') { return Err("Rust toolchain must start with '+' (e.g., '+stable', '+1.85.1', '+nightly')"); } let toolchain = &s[1..]; - // Check if it's a valid channel name or version format + // Check if it's a valid channel name or version format. if toolchain.is_empty() { return Err("Rust toolchain cannot be empty after '+'"); } - // Basic validation: alphanumeric, dots, dashes, and hyphens are allowed + // Basic validation: alphanumeric, dots, dashes, and hyphens are allowed. if !toolchain .chars() .all(|c| c.is_alphanumeric() || c == '.' || c == '-' || c == '_') @@ -309,6 +309,9 @@ async fn execute( *verbose, false, toolchain, + matches + .get_one::("WASI_VERSION") + .expect("`default_value` has been set"), ) .await } @@ -375,6 +378,9 @@ async fn execute( *force, *verbose, toolchain, + matches + .get_one::("WASI_VERSION") + .expect("`default_value` has been set"), ) .await } @@ -574,6 +580,13 @@ async fn execute( #[instrument(level = "trace", skip_all)] async fn make_app(current_dir: &std::ffi::OsString) -> Result { + let wasi_version = Arg::new("WASI_VERSION") + .action(ArgAction::Set) + .long("wasi_version") + .help("specify Wasmtime version to download (default: `v{DEFAULT_WASI_VERSION}`)") + .default_value(build::DEFAULT_WASI_VERSION.to_string()) + .value_parser(clap::builder::ValueParser::new(semver::Version::parse)) + .required(false); Ok(command!() .name("kit") .version(env!("CARGO_PKG_VERSION")) @@ -883,6 +896,7 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result { .value_parser(clap::builder::ValueParser::new(parse_rust_toolchain)) .required(false) ) + .arg(wasi_version.clone()) ) .subcommand(Command::new("build-start-package") .about("Build and start a Hyperware package") @@ -1003,7 +1017,7 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result { .default_value(build::DEFAULT_RUST_TOOLCHAIN) .value_parser(clap::builder::ValueParser::new(parse_rust_toolchain)) .required(false) - ) + ).arg(wasi_version) ) .subcommand(Command::new("chain") .about("Start a local chain for development") diff --git a/src/run_tests/mod.rs b/src/run_tests/mod.rs index 4f95ce7b..ba04abae 100644 --- a/src/run_tests/mod.rs +++ b/src/run_tests/mod.rs @@ -13,7 +13,7 @@ use tracing::{debug, info, instrument}; use hyperware_process_lib::kernel_types::PackageManifestEntry; use crate::boot_fake_node; -use crate::build::{self, DEFAULT_RUST_TOOLCHAIN}; +use crate::build::{self, DEFAULT_RUST_TOOLCHAIN, DEFAULT_WASI_VERSION}; use crate::chain; use crate::inject_message; use crate::start_package; @@ -395,6 +395,7 @@ async fn build_packages( false, false, DEFAULT_RUST_TOOLCHAIN, + &DEFAULT_WASI_VERSION, ) .await?; debug!("Start {path:?}"); @@ -422,6 +423,7 @@ async fn build_packages( false, false, DEFAULT_RUST_TOOLCHAIN, + &DEFAULT_WASI_VERSION, ) .await?; } @@ -446,6 +448,7 @@ async fn build_packages( false, false, DEFAULT_RUST_TOOLCHAIN, + &DEFAULT_WASI_VERSION, ) .await?; } From 250c7bd68944a3e50a256c98cddbd43eaf36f8fe Mon Sep 17 00:00:00 2001 From: skaunov Date: Sat, 4 Apr 2026 12:02:28 +0300 Subject: [PATCH 2/2] less confusing `.help` --- src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 2456d071..641cd26a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -583,8 +583,9 @@ async fn make_app(current_dir: &std::ffi::OsString) -> Result { let wasi_version = Arg::new("WASI_VERSION") .action(ArgAction::Set) .long("wasi_version") - .help("specify Wasmtime version to download (default: `v{DEFAULT_WASI_VERSION}`)") + .help("[specify] Wasmtime version to download (default: \"{DEFAULT_WASI_VERSION}\")") .default_value(build::DEFAULT_WASI_VERSION.to_string()) + // `semver::VersionReq` would be more user-friendly, but current download link pattern requires precision .value_parser(clap::builder::ValueParser::new(semver::Version::parse)) .required(false); Ok(command!()