- The serve loop ends the process after EOF or exit_after_response, also with background tasks or listeners. - One schema generator per direction for the whole document, so types with the same name get distinct names. - The agent gives the complete error (code, message, data) to the model, writes SKIP only after a successful request, caps tool output at 64 KiB, writes each history line in one write, and skips a damaged line. - Endpoints skip blank and non-RPC lines. client_rs does not panic. - #[must_use] on builders and the lock guard; #[schemars] attributes and duplicate hooks are compile errors; raw identifiers; -32000 for local SDK errors; x-sausage-params only for methods with params.
91 lines
2.3 KiB
Rust
91 lines
2.3 KiB
Rust
//! Regression checks for shared schema names and wire identifiers.
|
|
use sausage_plugin::{Interface, Result, rpc};
|
|
mod a {
|
|
/// Text status.
|
|
#[sausage_plugin::schema]
|
|
pub struct Status {
|
|
/// Text value.
|
|
pub text: String,
|
|
}
|
|
}
|
|
mod b {
|
|
/// Counter status.
|
|
#[sausage_plugin::schema]
|
|
pub struct Status {
|
|
/// Counter value.
|
|
pub count: u32,
|
|
}
|
|
}
|
|
struct Main;
|
|
struct Control;
|
|
#[rpc(endpoints(control = Control))]
|
|
impl Main {
|
|
/// Return text status.
|
|
fn one(&self, p: a::Status) -> Result<a::Status> {
|
|
Ok(p)
|
|
}
|
|
/// Return counter status.
|
|
fn two(&self, p: b::Status) -> Result<b::Status> {
|
|
Ok(p)
|
|
}
|
|
/// Use an unescaped wire name.
|
|
fn r#type(&self) -> Result<()> {
|
|
Ok(())
|
|
}
|
|
}
|
|
#[rpc]
|
|
impl Control {
|
|
/// Return endpoint counter status.
|
|
fn status(&self) -> Result<b::Status> {
|
|
Ok(b::Status { count: 1 })
|
|
}
|
|
}
|
|
#[test]
|
|
fn distinct_status_types_share_document_generators() {
|
|
let doc = Main::describe();
|
|
let methods = doc["methods"].as_array().unwrap();
|
|
let one = methods.iter().find(|m| m["name"] == "one").unwrap();
|
|
let two = methods.iter().find(|m| m["name"] == "two").unwrap();
|
|
assert_eq!(one["params"][0]["name"], "text");
|
|
assert_eq!(two["params"][0]["name"], "count");
|
|
assert_ne!(one["result"]["schema"], two["result"]["schema"]);
|
|
for (method, field) in [
|
|
(one, "text"),
|
|
(two, "count"),
|
|
(
|
|
&doc["x-sausage-endpoints"]["control"]["methods"][0],
|
|
"count",
|
|
),
|
|
] {
|
|
let schema = doc
|
|
.pointer(
|
|
method["result"]["schema"]["$ref"]
|
|
.as_str()
|
|
.unwrap()
|
|
.trim_start_matches('#'),
|
|
)
|
|
.unwrap();
|
|
assert!(schema["properties"].get(field).is_some(), "{doc}");
|
|
}
|
|
}
|
|
#[test]
|
|
fn raw_identifier_has_plain_wire_name() {
|
|
assert!(
|
|
Main::describe()["methods"]
|
|
.as_array()
|
|
.unwrap()
|
|
.iter()
|
|
.any(|m| m["name"] == "type")
|
|
);
|
|
}
|
|
#[test]
|
|
fn local_transport_errors_have_reserved_sdk_code() {
|
|
assert_eq!(
|
|
sausage_plugin::Ctx::default()
|
|
.notify("x", ())
|
|
.unwrap_err()
|
|
.code,
|
|
-32000
|
|
);
|
|
}
|