Files
Unlucky-Launcher/crates/agent/src/registry/schema.rs
T
AskaEth a5d1dec495
CI / fmt (rustfmt --check) (push) Waiting to run
CI / clippy (ubuntu-latest) (push) Waiting to run
CI / clippy (windows-latest) (push) Waiting to run
CI / test (ubuntu-latest) (push) Waiting to run
CI / test (windows-latest) (push) Waiting to run
CI / build release (ubuntu-latest) (push) Waiting to run
CI / build release (windows-latest) (push) Waiting to run
CI / runtime smoke (ubuntu x64, xvfb) (push) Waiting to run
CI / runtime smoke (macos arm64, probe) (push) Skipped
CI / update-e2e (windows x64) (push) Waiting to run
GPU evidence / GPU 判据自测(不需 GPU;跳过 ≠ 已验证) (push) Waiting to run
GPU evidence / GPU 证据 — 探测可用产物与硬件适配器 (push) Waiting to run
Guards / core 零 UI 守门 (push) Waiting to run
Guards / presenter 零 UI 守门 (push) Waiting to run
Guards / design 零第三方依赖守门 (push) Waiting to run
Guards / unsafe 落点守门(集合必须恰好等于期望) (push) Waiting to run
Guards / 文件行数 ≤400 守门 (push) Waiting to run
Guards / 依赖许可与来源(cargo-deny) (push) Waiting to run
Release guard / 发布标记语义守门(push tag → 稳定版) (push) Waiting to run
Signing status(播报,不是门禁) / 判据自测(三行/退出码/变异重放/接线) (push) Waiting to run
Signing status(播报,不是门禁) / 签名就绪度(播报) (push) Waiting to run
Release / 选槽位(默认四个:Windows 两档 + Linux 两档) (push) Waiting to run
release: v0.2.4 里程碑快照(孤儿提交,无父;树 = dev 68362e5)
本批内容见 CHANGELOG.md 的 0.2.4 段。按 D41 用孤儿快照推 main,保留「公开史只有里程碑」的模型。
2026-11-11 21:41:38 +08:00

117 lines
3.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! JSON Schema 构造helper。
//!
//! 工具参数 schema 一律**手写 JSON**(research/02 §6.2:`rig` 的 `DynamicTool::new` 与
//! rmcp 的 `ToolRoute::new_dyn` 吃的都是裸 `serde_json::Value`),所以不需要 schemars 派生。
//! 手写的好处是同一份 schema 直接喂两方,坏处是啰嗦——这个模块把啰嗦收敛到几个函数。
//!
//! 生成的 schema 一律按 **JSON Schema 2020-12** 的写法(rmcp 支持该版本;
//! `additionalProperties: false` 让模型少给野参数,[`super::validate`] 会执行它)。
use serde_json::{json, Map, Value};
/// 对象 schema。`properties` 按给定顺序写入(JSON 对象保序,UI 展示稳定)。
#[must_use]
pub fn object(properties: &[(&str, Value)], required: &[&str]) -> Value {
let mut props = Map::new();
for (name, schema) in properties {
props.insert((*name).to_string(), schema.clone());
}
json!({
"type": "object",
"properties": Value::Object(props),
"required": required,
"additionalProperties": false,
})
}
/// 任意 JSON 值(不校验类型)。
#[must_use]
pub fn any() -> Value {
json!({})
}
/// 字符串。
#[must_use]
pub fn string(description: &str) -> Value {
json!({ "type": "string", "description": description })
}
/// 非空字符串(`minLength: 1`,省掉一堆「路径不能为空」的运行时判断)。
#[must_use]
pub fn non_empty_string(description: &str) -> Value {
json!({ "type": "string", "description": description, "minLength": 1 })
}
/// 枚举字符串。
#[must_use]
pub fn string_enum(values: &[&str], description: &str) -> Value {
json!({ "type": "string", "description": description, "enum": values })
}
/// 布尔。
#[must_use]
pub fn boolean(description: &str) -> Value {
json!({ "type": "boolean", "description": description })
}
/// 带范围约束的整数。
#[must_use]
pub fn integer(description: &str, minimum: i64, maximum: i64) -> Value {
json!({
"type": "integer",
"description": description,
"minimum": minimum,
"maximum": maximum,
})
}
/// 字符串数组(可选条数上限)。
#[must_use]
pub fn string_array(description: &str, max_items: u64) -> Value {
json!({
"type": "array",
"description": description,
"items": { "type": "string" },
"maxItems": max_items,
})
}
/// 枚举字符串数组(如 `kinds: ["stderr","exit"]`)。
#[must_use]
pub fn enum_string_array(values: &[&str], description: &str, max_items: u64) -> Value {
json!({
"type": "array",
"description": description,
"items": { "type": "string", "enum": values },
"maxItems": max_items,
"uniqueItems": true,
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::registry::validate::validate;
#[test]
fn object_records_required_and_forbids_extras() {
let schema = object(
&[("path", non_empty_string("键路径")), ("value", any())],
&["path", "value"],
);
assert_eq!(schema["type"], json!("object"));
assert_eq!(schema["additionalProperties"], json!(false));
assert_eq!(schema["required"], json!(["path", "value"]));
assert!(validate(&schema, &json!({ "path": "a", "value": 1 })).is_ok());
}
#[test]
fn integer_builder_carries_bounds() {
let schema = integer("条数", 1, 500);
assert_eq!(schema["minimum"], json!(1));
assert_eq!(schema["maximum"], json!(500));
assert!(validate(&schema, &json!(0)).is_err());
assert!(validate(&schema, &json!(500)).is_ok());
}
}