执行摘要
本 PR 对 Rust 工具参数转换模块进行了重构,引入 ParamInput 抽象和递归模式处理,为未来支持结构化解析器输入做好准备。核心文件 parameters.rs 重写了 JSON Schema 解析和值转换逻辑,使嵌套对象、数组和类型化附加属性得以递归处理。虽保持现有字符串解析器兼容,但空字符串处理存在微小行为差异,值得关注。
功能与动机
目前工具参数转换仅接受原始字符串,无法解析未来解析器可能产生的结构化参数(如嵌套对象)。PR 旨在扩展转换工具,使其能递归处理任意深度的参数模式,同时通过 Into<ParamInput> 桥接保持对现有字符串解析器的向前兼容。
实现拆解
- 引入
ParamInput 和 ParamElement:在 parameters.rs 中添加枚举 ParamInput(Text | Elements)和结构体 ParamElement,作为解析器中立的参数输入表示。现有字符串调用者通过 From<String> 无缝迁移。
- 扩展
JsonParamType 为递归结构:Object 变体现携带 properties: BTreeMap<String, JsonParamType> 和 additional_properties: Option<Box<JsonParamType>>;Array 变体现携带 items: Option<Box<JsonParamType>>。这允许模式任意嵌套。
- 重写
from_schema 方法:递归解析嵌套模式。新增辅助函数 from_type_value、from_type_name、object_from_schema、array_from_schema,处理 type、properties、additionalProperties、items、anyOf 等 JSON Schema 关键字。
- 重写转换逻辑:新增
convert_with_optional_schema 和 try_convert_value 函数,根据输入是文本还是结构化元素分别处理。文本输入尝试按类型解析 JSON 字面量;结构化输入递归遍历元素,根据模式转换每个子值。未知参数名回退到对象式 JSON。
- 适配现有调用者:
convert_params_with_schema 和 convert_param_with_schema 改为泛型 P: Into<ParamInput>。DeepSeek DSML 解析器对应调整一处调用,移除取引用操作。
rust/src/tool-parser/src/parameters.rs
核心实现文件,包含所有新增类型和递归转换逻辑。
// 新的 JsonParamType 支持递归嵌套
#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) enum JsonParamType {
String,
Integer,
Number,
Boolean,
Object {
properties: BTreeMap<String, JsonParamType>,
additional_properties: Option<Box<JsonParamType>>,
},
Array {
items: Option<Box<JsonParamType>>,
},
Null,
OneOf(Vec<JsonParamType>),
}
// 根据可选的模式进行递归转换
fn convert_with_optional_schema(
param_type: Option<&JsonParamType>,
input: &ParamInput,
) -> Value {
// 如果输入是文本且为 "null",直接返回 JSON null
if let ParamInput::Text(value) = input
&& value.eq_ignore_ascii_case("null")
{
return Value::Null;
}
// 如果提供了模式,则用模式转换
if let Some(param_type) = param_type {
return try_convert_value(param_type, input);
}
// 无模式时的回退:根据输入类型尽力转换
match input {
ParamInput::Text(value) => Value::String(value.clone()),
ParamInput::Elements(elements) => {
// 将命名元素递归转换为 JSON 对象
let mut map = Map::new();
for element in elements {
let value = convert_with_optional_schema(None, &element.value);
map.insert(element.name.clone(), value);
}
Value::Object(map)
}
}
}
评论区精华
- P2 潜在回归:chatgpt-codex-connector 指出,当字符串解析器传入空值时,对象/数组参数现在会返回
{} 或 [] 而非原始字符串 "",这可能违背“保留原始字符串行为”的承诺。作者未回复,评审者仍批准合并。
风险与影响
- 空字符串行为变更:当前对空字符串的处理与之前不同,可能影响依赖原始字符串行为的解析器(如 DSML/XML)。这是最大风险点。
- 递归深度:极端嵌套的 schema 可能触发栈溢出,但 Rust 默认栈大小在典型场景下足够。
- 测试覆盖:未覆盖所有结构化输入边界场景,但已有单元测试。
- 影响范围:仅限 Rust 工具解析模块,不影响 Python 前端。
关联脉络
本 PR 属于 Rust 前端模块的持续重构与能力增强,与该模块的先前 PR #43883(request-id-headers 支持)和近期测试 PR #44320 同属一线。在更广的视角下,它与 Python 前端的解析器统一工作(PR #42977、#44267)形成呼应,共同推进工具调用解析的抽象化。
参与讨论