plugin: fix rust pdk wit template probes
This commit is contained in:
parent
06287aca40
commit
0a9e585c1d
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -5561,6 +5561,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tempfile",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
"toml",
|
"toml",
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,5 @@ thiserror.workspace = true
|
||||||
wit-bindgen = "0.51.0"
|
wit-bindgen = "0.51.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
tempfile.workspace = true
|
||||||
toml.workspace = true
|
toml.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,13 @@
|
||||||
//! [`export_component_tool!`] macro:
|
//! [`export_component_tool!`] macro:
|
||||||
//!
|
//!
|
||||||
//! ```ignore
|
//! ```ignore
|
||||||
//! yoi_plugin_pdk::wit_bindgen::generate!({
|
//! use yoi_plugin_pdk::wit_bindgen;
|
||||||
|
//!
|
||||||
|
//! wit_bindgen::generate!({
|
||||||
//! world: "tool",
|
//! world: "tool",
|
||||||
//! path: "../../../../resources/plugin/wit",
|
//! path: "../../../../resources/plugin/wit",
|
||||||
|
//! generate_all,
|
||||||
|
//! runtime_path: "yoi_plugin_pdk::wit_bindgen::rt",
|
||||||
//! });
|
//! });
|
||||||
//!
|
//!
|
||||||
//! fn echo(
|
//! fn echo(
|
||||||
|
|
@ -42,7 +46,8 @@ pub const TOOL_WORLD: &str = "yoi:plugin/tool@1.0.0";
|
||||||
pub const TOOL_WIT: &str = include_str!("../../../resources/plugin/wit/yoi-plugin-tool-v1.wit");
|
pub const TOOL_WIT: &str = include_str!("../../../resources/plugin/wit/yoi-plugin-tool-v1.wit");
|
||||||
|
|
||||||
/// Repository WIT for the grant-bound host APIs importable by Tool components.
|
/// Repository WIT for the grant-bound host APIs importable by Tool components.
|
||||||
pub const HOST_WIT: &str = include_str!("../../../resources/plugin/wit/yoi-host-v1.wit");
|
pub const HOST_WIT: &str =
|
||||||
|
include_str!("../../../resources/plugin/wit/deps/yoi-host/yoi-host-v1.wit");
|
||||||
|
|
||||||
/// Maximum serialized ToolOutput JSON accepted by Yoi's current Plugin runtime.
|
/// Maximum serialized ToolOutput JSON accepted by Yoi's current Plugin runtime.
|
||||||
pub const MAX_TOOL_OUTPUT_BYTES: usize = 64 * 1024;
|
pub const MAX_TOOL_OUTPUT_BYTES: usize = 64 * 1024;
|
||||||
|
|
@ -321,9 +326,11 @@ where
|
||||||
/// Implement the generated Component Model `Guest` trait for a typed JSON
|
/// Implement the generated Component Model `Guest` trait for a typed JSON
|
||||||
/// handler and export it with the `wit-bindgen` generated `export!` macro.
|
/// handler and export it with the `wit-bindgen` generated `export!` macro.
|
||||||
///
|
///
|
||||||
/// The caller must invoke `yoi_plugin_pdk::wit_bindgen::generate!` for the
|
/// The caller must import the PDK's `wit_bindgen` re-export and invoke
|
||||||
/// `tool` world first, which defines the `Guest` trait and `export!` macro in
|
/// `wit_bindgen::generate!` for the `tool` world first, with
|
||||||
/// the current module. The generated component still imports only WIT-declared
|
/// `runtime_path: "yoi_plugin_pdk::wit_bindgen::rt"`. That defines the
|
||||||
|
/// `Guest` trait and `export!` macro in the current module. The generated
|
||||||
|
/// component still imports only WIT-declared
|
||||||
/// host APIs; this macro does not grant filesystem, network, or environment
|
/// host APIs; this macro does not grant filesystem, network, or environment
|
||||||
/// authority.
|
/// authority.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
@ -464,5 +471,6 @@ mod tests {
|
||||||
assert_eq!(TOOL_WORLD, "yoi:plugin/tool@1.0.0");
|
assert_eq!(TOOL_WORLD, "yoi:plugin/tool@1.0.0");
|
||||||
assert!(HOST_WIT.contains("interface https"));
|
assert!(HOST_WIT.contains("interface https"));
|
||||||
assert!(HOST_WIT.contains("interface fs"));
|
assert!(HOST_WIT.contains("interface fs"));
|
||||||
|
assert!(HOST_WIT.contains("%list: func"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
|
||||||
const TEMPLATE_CARGO: &str =
|
const TEMPLATE_CARGO: &str =
|
||||||
|
|
@ -15,6 +19,7 @@ const PDK_CARGO: &str = include_str!("../Cargo.toml");
|
||||||
fn rust_component_tool_template_has_expected_files() {
|
fn rust_component_tool_template_has_expected_files() {
|
||||||
let cargo: Value = toml::from_str(TEMPLATE_CARGO).expect("template Cargo.toml parses");
|
let cargo: Value = toml::from_str(TEMPLATE_CARGO).expect("template Cargo.toml parses");
|
||||||
assert_eq!(cargo["package"]["edition"].as_str(), Some("2024"));
|
assert_eq!(cargo["package"]["edition"].as_str(), Some("2024"));
|
||||||
|
assert!(cargo["workspace"].is_table());
|
||||||
assert_eq!(cargo["lib"]["crate-type"][0].as_str(), Some("cdylib"));
|
assert_eq!(cargo["lib"]["crate-type"][0].as_str(), Some("cdylib"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cargo["dependencies"]["yoi-plugin-pdk"]["path"].as_str(),
|
cargo["dependencies"]["yoi-plugin-pdk"]["path"].as_str(),
|
||||||
|
|
@ -31,7 +36,10 @@ fn rust_component_tool_template_has_expected_files() {
|
||||||
);
|
);
|
||||||
assert!(plugin["tools"].as_array().expect("tools array").len() == 1);
|
assert!(plugin["tools"].as_array().expect("tools array").len() == 1);
|
||||||
|
|
||||||
assert!(TEMPLATE_LIB.contains("yoi_plugin_pdk::wit_bindgen::generate!"));
|
assert!(TEMPLATE_LIB.contains("use yoi_plugin_pdk::wit_bindgen"));
|
||||||
|
assert!(TEMPLATE_LIB.contains("wit_bindgen::generate!"));
|
||||||
|
assert!(TEMPLATE_LIB.contains("generate_all"));
|
||||||
|
assert!(TEMPLATE_LIB.contains("runtime_path: \"yoi_plugin_pdk::wit_bindgen::rt\""));
|
||||||
assert!(TEMPLATE_LIB.contains("yoi_plugin_pdk::export_component_tool!"));
|
assert!(TEMPLATE_LIB.contains("yoi_plugin_pdk::export_component_tool!"));
|
||||||
assert!(TEMPLATE_LIB.contains("ToolOutput::json"));
|
assert!(TEMPLATE_LIB.contains("ToolOutput::json"));
|
||||||
assert!(TEMPLATE_README.contains("Component Model Tool Plugin"));
|
assert!(TEMPLATE_README.contains("Component Model Tool Plugin"));
|
||||||
|
|
@ -39,11 +47,47 @@ fn rust_component_tool_template_has_expected_files() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn documented_sample_uses_pdk_component_path() {
|
fn documented_sample_uses_pdk_component_path() {
|
||||||
assert!(SAMPLE_LIB.contains("yoi_plugin_pdk::wit_bindgen::generate!"));
|
assert!(SAMPLE_LIB.contains("use yoi_plugin_pdk::wit_bindgen"));
|
||||||
|
assert!(SAMPLE_LIB.contains("wit_bindgen::generate!"));
|
||||||
|
assert!(SAMPLE_LIB.contains("generate_all"));
|
||||||
|
assert!(SAMPLE_LIB.contains("runtime_path: \"yoi_plugin_pdk::wit_bindgen::rt\""));
|
||||||
assert!(SAMPLE_LIB.contains("yoi_plugin_pdk::export_component_tool!"));
|
assert!(SAMPLE_LIB.contains("yoi_plugin_pdk::export_component_tool!"));
|
||||||
assert!(!SAMPLE_LIB.contains("export_name"));
|
assert!(!SAMPLE_LIB.contains("export_name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn embedded_template_cargo_checks_for_wasm_target() {
|
||||||
|
let crate_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
let template_dir = crate_dir.join("../../resources/plugin/templates/rust-component-tool");
|
||||||
|
let manifest_path = template_dir.join("Cargo.toml");
|
||||||
|
let lock_path = template_dir.join("Cargo.lock");
|
||||||
|
let _ = fs::remove_file(&lock_path);
|
||||||
|
|
||||||
|
let target_dir = tempfile::tempdir().expect("temporary cargo target dir");
|
||||||
|
let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
|
||||||
|
let output = Command::new(cargo)
|
||||||
|
.arg("check")
|
||||||
|
.arg("--manifest-path")
|
||||||
|
.arg(&manifest_path)
|
||||||
|
.arg("--target")
|
||||||
|
.arg("wasm32-unknown-unknown")
|
||||||
|
.arg("--offline")
|
||||||
|
.arg("--target-dir")
|
||||||
|
.arg(target_dir.path())
|
||||||
|
.env("CARGO_TERM_COLOR", "never")
|
||||||
|
.output()
|
||||||
|
.expect("spawn cargo check for embedded template");
|
||||||
|
|
||||||
|
let _ = fs::remove_file(&lock_path);
|
||||||
|
assert!(
|
||||||
|
output.status.success(),
|
||||||
|
"template cargo check failed\nstatus: {}\nstdout:\n{}\nstderr:\n{}",
|
||||||
|
output.status,
|
||||||
|
String::from_utf8_lossy(&output.stdout),
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pdk_runtime_dependencies_are_guest_side_only() {
|
fn pdk_runtime_dependencies_are_guest_side_only() {
|
||||||
let cargo: Value = toml::from_str(PDK_CARGO).expect("PDK Cargo.toml parses");
|
let cargo: Value = toml::from_str(PDK_CARGO).expect("PDK Cargo.toml parses");
|
||||||
|
|
|
||||||
25
crates/plugin-pdk/tests/wit_bindgen_probe.rs
Normal file
25
crates/plugin-pdk/tests/wit_bindgen_probe.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
use yoi_plugin_pdk::wit_bindgen;
|
||||||
|
|
||||||
|
wit_bindgen::generate!({
|
||||||
|
world: "tool",
|
||||||
|
path: "../../resources/plugin/wit",
|
||||||
|
generate_all,
|
||||||
|
runtime_path: "yoi_plugin_pdk::wit_bindgen::rt",
|
||||||
|
});
|
||||||
|
|
||||||
|
struct Probe;
|
||||||
|
|
||||||
|
impl Guest for Probe {
|
||||||
|
fn call(tool_name: String, input_json: String) -> String {
|
||||||
|
yoi_plugin_pdk::run_json_tool(&tool_name, &input_json, |_ctx, input: serde_json::Value| {
|
||||||
|
yoi_plugin_pdk::ToolOutput::json("probe ok", input)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wit_bindgen_generates_current_tool_world() {
|
||||||
|
let output = <Probe as Guest>::call("probe".to_string(), r#"{"ok":true}"#.to_string());
|
||||||
|
let value: serde_json::Value = serde_json::from_str(&output).unwrap();
|
||||||
|
assert_eq!(value["summary"], "probe ok");
|
||||||
|
}
|
||||||
|
|
@ -119,11 +119,14 @@ The important authoring shape is:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use yoi_plugin_pdk::wit_bindgen;
|
||||||
use yoi_plugin_pdk::{ToolContext, ToolError, ToolOutput};
|
use yoi_plugin_pdk::{ToolContext, ToolError, ToolOutput};
|
||||||
|
|
||||||
yoi_plugin_pdk::wit_bindgen::generate!({
|
wit_bindgen::generate!({
|
||||||
world: "tool",
|
world: "tool",
|
||||||
path: "../../../resources/plugin/wit",
|
path: "../../../resources/plugin/wit",
|
||||||
|
generate_all,
|
||||||
|
runtime_path: "yoi_plugin_pdk::wit_bindgen::rt",
|
||||||
});
|
});
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,14 @@
|
||||||
//! and package the adapted component as `plugin.component.wasm`.
|
//! and package the adapted component as `plugin.component.wasm`.
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use yoi_plugin_pdk::wit_bindgen;
|
||||||
use yoi_plugin_pdk::{ToolContext, ToolError, ToolOutput};
|
use yoi_plugin_pdk::{ToolContext, ToolError, ToolOutput};
|
||||||
|
|
||||||
yoi_plugin_pdk::wit_bindgen::generate!({
|
wit_bindgen::generate!({
|
||||||
world: "tool",
|
world: "tool",
|
||||||
path: "../../../resources/plugin/wit",
|
path: "../../../resources/plugin/wit",
|
||||||
|
generate_all,
|
||||||
|
runtime_path: "yoi_plugin_pdk::wit_bindgen::rt",
|
||||||
});
|
});
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ rustPlatform.buildRustPackage rec {
|
||||||
filter = sourceFilter;
|
filter = sourceFilter;
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoHash = "sha256-gMDU496wWn3LYhlXwxczHW/tT3IJxclwJtIY6ZjomtQ=";
|
cargoHash = "sha256-ci9h0U83YQQBeT3xlsGuKULnl1Aphgpg3pR4n0se16I=";
|
||||||
|
|
||||||
depsExtraArgs = {
|
depsExtraArgs = {
|
||||||
# Older fetchCargoVendor utilities used crates.io's API download endpoint,
|
# Older fetchCargoVendor utilities used crates.io's API download endpoint,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,10 @@ edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
# Keep the embedded template checkable in-place without making it a member of
|
||||||
|
# Yoi's root workspace. A copied starter remains a normal standalone package.
|
||||||
|
[workspace]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ The PDK is guest-side only. It does not grant filesystem, network, or environmen
|
||||||
|
|
||||||
## Checkout/development dependency
|
## Checkout/development dependency
|
||||||
|
|
||||||
Inside the Yoi checkout this template uses a local path dependency:
|
Inside the Yoi checkout this template uses a local path dependency and declares an empty `[workspace]` so it can be checked in place without becoming a member of Yoi's root workspace:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
yoi-plugin-pdk = { path = "../../../../crates/plugin-pdk" }
|
yoi-plugin-pdk = { path = "../../../../crates/plugin-pdk" }
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use yoi_plugin_pdk::wit_bindgen;
|
||||||
use yoi_plugin_pdk::{ToolContext, ToolError, ToolOutput};
|
use yoi_plugin_pdk::{ToolContext, ToolError, ToolOutput};
|
||||||
|
|
||||||
yoi_plugin_pdk::wit_bindgen::generate!({
|
wit_bindgen::generate!({
|
||||||
world: "tool",
|
world: "tool",
|
||||||
path: "../../../../resources/plugin/wit",
|
path: "../../../../resources/plugin/wit",
|
||||||
|
generate_all,
|
||||||
|
runtime_path: "yoi_plugin_pdk::wit_bindgen::rt",
|
||||||
});
|
});
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,6 @@ interface https {
|
||||||
/// Grant-bound filesystem host API. No ambient WASI filesystem is exposed.
|
/// Grant-bound filesystem host API. No ambient WASI filesystem is exposed.
|
||||||
interface fs {
|
interface fs {
|
||||||
read: func(request-json: string) -> string;
|
read: func(request-json: string) -> string;
|
||||||
list: func(request-json: string) -> string;
|
%list: func(request-json: string) -> string;
|
||||||
write: func(request-json: string) -> string;
|
write: func(request-json: string) -> string;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user