refactor(llm): 移除 ToolDefinition 别名与遗留 deprecation 抑制点

完成 ToolDef IR 切换的最后清理:移除 ToolDefinition 别名与
OpenaiToolDefinition 的公共 re-export;各调用点(cycle/registry/mcp/agent)
直接使用 ToolDef 并清理对应的 #[allow(deprecated)] 抑制点;新增
roundtrip 测试验证 ToolDef 序列化兼容性。
This commit is contained in:
徐涛
2026-07-05 10:32:35 +08:00
parent 9da9b83167
commit 4cf5918b9c
6 changed files with 57 additions and 27 deletions
+2 -4
View File
@@ -7,14 +7,12 @@
//! - **不绑定业务循环**`submit_turn` 在 `AgentSession` 上,不在 trait 上
use crate::agent::runtime::RuntimeBundle;
#[allow(deprecated)]
use crate::llm::types::ToolDefinition;
use crate::llm::types::tool::ToolDef;
/// Agent 角色抽象。
///
/// 实现此 trait 即可接入 Agent Runtime。典型实现是 struct 持有静态配置(name、system prompt 模板),
/// 也可以是基于配置动态生成的轻量实现。
#[allow(deprecated)]
pub trait Agent: Send + Sync {
/// 角色名(用于日志、调试、UI 展示)。
fn name(&self) -> &str;
@@ -26,7 +24,7 @@ pub trait Agent: Send + Sync {
///
/// **默认实现**:从 `bundle.tool_registry` 取全部工具(最常用模式)。
/// **子 trait / 具体实现可覆盖**:做白名单、过滤、按状态动态调整等。
fn tool_definitions(&self, bundle: &RuntimeBundle) -> Vec<ToolDefinition> {
fn tool_definitions(&self, bundle: &RuntimeBundle) -> Vec<ToolDef> {
bundle.tool_registry.definitions()
}
}
+7 -7
View File
@@ -21,8 +21,8 @@ use crate::llm::stream::StreamEvent;
use crate::llm::types::message::{ContentBlock, Message};
use crate::llm::types::request_v2::MessageRequest;
use crate::llm::types::response_v2::{MessageResponse, StopReason};
#[allow(deprecated)]
use crate::llm::types::{ToolChoice, ToolDefinition};
use crate::llm::types::tool::ToolDef;
use crate::llm::types::ToolChoice;
/// LLM 调用周期配置。
pub struct CycleConfig {
@@ -179,7 +179,7 @@ impl LlmCycle {
pub async fn submit_messages(
&mut self,
messages: Vec<Message>,
tools: Vec<ToolDefinition>,
tools: Vec<ToolDef>,
) -> Result<MessageResponse, LlmError> {
let request = MessageRequest {
model: self.config.model.clone(),
@@ -237,7 +237,7 @@ impl LlmCycle {
pub async fn submit(
&mut self,
prompt: String,
tools: Vec<ToolDefinition>,
tools: Vec<ToolDef>,
) -> Result<MessageResponse, LlmError> {
self.messages.push(Message::user_text(prompt));
@@ -347,7 +347,7 @@ impl LlmCycle {
pub async fn submit_stream(
&mut self,
prompt: String,
tools: Vec<ToolDefinition>,
tools: Vec<ToolDef>,
) -> Result<Pin<Box<dyn Stream<Item = StreamEvent> + Send>>, LlmError> {
self.messages.push(Message::user_text(prompt));
@@ -429,7 +429,7 @@ impl LlmCycle {
}))
}
fn build_request(&self, tools: &[ToolDefinition]) -> MessageRequest {
fn build_request(&self, tools: &[ToolDef]) -> MessageRequest {
// ponytail: Phase 2 简化 —— 直接 clone self.messages,无任何转换 / system prompt 注入。
// 系统消息如需存在,由调用方通过 `with_messages()` 自行管理。
MessageRequest {
@@ -448,7 +448,7 @@ impl LlmCycle {
/// 用于 `submit_with_tools()` 的多轮 tool 循环。
async fn submit_request(
&mut self,
tools: &[ToolDefinition],
tools: &[ToolDef],
) -> Result<MessageResponse, LlmError> {
let mut attempts = 0;
+1 -4
View File
@@ -26,7 +26,7 @@ pub use shared::{
AudioFormat, FinishReason, ImageDetail, Modality, ResponseFormat, Role, ServiceTier,
StopSequence,
};
pub use tool::{FunctionCall, OpenaiToolCall, OpenaiToolDefinition, ToolDef};
pub use tool::{FunctionCall, OpenaiToolCall, ToolDef};
pub use usage::{CompletionTokensDetails, CostTracker, PromptTokensDetails, Usage};
// Re-export IR 内容块 / 消息类型供 `types::ContentBlock` 等历史路径消费。
@@ -96,6 +96,3 @@ impl From<ChatResponse> for OpenaiChatChunk {
}
}
}
/// 工具定义别名 —— 指向 v0.2 新增的 Provider 无关 IR 类型。
pub type ToolDefinition = ToolDef;
+40
View File
@@ -198,4 +198,44 @@ mod tests {
assert_eq!(decoded.stream, req.stream);
assert_eq!(decoded.extra.get("trace_id"), Some(&json!("t-1")));
}
#[test]
fn message_request_with_tools_roundtrip() {
// 验证 ToolDef 的 serde 属性与 OpenaiToolDefinition 一致:
// 同名字段(name/description/parameters)序列化结果应一致。
let params = json!({
"type": "object",
"properties": {"x": {"type": "number"}},
"required": ["x"],
});
let tool = super::ToolDef {
name: "add".to_string(),
description: Some("add two numbers".to_string()),
parameters: params.clone(),
};
let req = MessageRequest {
model: "gpt-4o".into(),
messages: vec![Message::user_text("hi")],
tools: vec![tool],
tool_choice: ToolChoice::Auto,
max_tokens: None,
temperature: None,
top_p: None,
stop_sequences: vec![],
stream: false,
thinking: None,
extra: HashMap::new(),
};
let json = serde_json::to_string(&req).expect("serialize");
// 验证反序列化能还原所有字段(包括嵌套 parameters
let decoded: MessageRequest = serde_json::from_str(&json).expect("deserialize");
assert_eq!(decoded.tools.len(), 1);
assert_eq!(decoded.tools[0].name, "add");
assert_eq!(decoded.tools[0].description.as_deref(), Some("add two numbers"));
assert_eq!(decoded.tools[0].parameters, params);
// 验证序列化 JSON 不含 ToolDef 没有的字段(如 strict),保持 wire-format 兼容
assert!(!json.contains("strict"), "ToolDef 序列化不应包含 strict 字段");
}
}
+3 -6
View File
@@ -20,8 +20,7 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::process::{Child, ChildStdin, ChildStdout, Command};
use tokio::sync::{Mutex, oneshot};
#[allow(deprecated)]
use crate::llm::types::ToolDefinition;
use crate::llm::types::tool::ToolDef;
use crate::tools::base::{BaseTool, ToolContext, ToolRef};
use crate::tools::error::ToolError;
@@ -136,7 +135,6 @@ impl std::fmt::Debug for McpClient {
}
}
#[allow(deprecated)]
impl McpClient {
/// 创建一个 MCP 客户端。
pub fn new(server_name: impl Into<String>, transport: McpTransport) -> Self {
@@ -237,7 +235,7 @@ impl McpClient {
}
/// 列出服务器支持的工具(调用 `tools/list`)。
pub async fn list_tools(&mut self) -> Result<Vec<ToolDefinition>, ToolError> {
pub async fn list_tools(&mut self) -> Result<Vec<ToolDef>, ToolError> {
if !self.is_initialized() {
return Err(ToolError::McpNotInitialized(self.server_name.clone()));
}
@@ -272,7 +270,7 @@ impl McpClient {
description: description.clone(),
input_schema: input_schema.clone(),
});
defs.push(ToolDefinition {
defs.push(ToolDef {
name,
description,
parameters: input_schema,
@@ -530,7 +528,6 @@ enum McpClientHandle {
}
#[async_trait]
#[allow(deprecated)]
impl BaseTool for McpToolAdapter {
fn name(&self) -> &str {
&self.name
+4 -6
View File
@@ -7,8 +7,7 @@ use std::time::Duration;
use futures::future::join_all;
use serde_json::Value;
#[allow(deprecated)]
use crate::llm::types::ToolDefinition;
use crate::llm::types::tool::ToolDef;
use crate::tools::base::{ToolContext, ToolRef};
use crate::tools::error::ToolError;
use crate::tools::permission::PermissionChecker;
@@ -71,7 +70,6 @@ impl std::fmt::Debug for ToolRegistry {
}
}
#[allow(deprecated)]
impl ToolRegistry {
/// 创建一个新的工具注册表。
pub fn new() -> Self {
@@ -127,12 +125,12 @@ impl ToolRegistry {
self.inner.tools.keys().cloned().collect()
}
/// 获取所有工具的 `ToolDefinition` 列表(用于传递给 LLM)。
pub fn definitions(&self) -> Vec<ToolDefinition> {
/// 获取所有工具的 `ToolDef` 列表(用于传递给 LLM)。
pub fn definitions(&self) -> Vec<ToolDef> {
self.inner
.tools
.values()
.map(|tool| ToolDefinition {
.map(|tool| ToolDef {
name: tool.name().to_string(),
description: Some(tool.description().to_string()),
parameters: tool.parameters(),