feat(core): 14 个公开枚举标记 #[non_exhaustive]

为 v0.2.0-rc.1 API 稳定性收尾。覆盖:
- P0 核心 IR: Message / ContentBlock / ContentBlockType / StreamEvent / HookEvent
- P0 Error: AgentError / LlmError / ToolError / MemoryError / PromptError
- P1 其他: MemoryStrategy / StepStatus / ToolChoice / ResponseFormat

明确不加的: 内部 wire-format (OpenaiChatMessage 等) /
语义已收敛 (Role/ServiceTier 等) / 使用面窄 (Permission 等)。

示例侧的 3 处 Message exhaustive match (prompt_composer /
conversation_memory_demo) 补全 `_` 通配分支,零行为变化。

验收: cargo build + clippy -D warnings + test --all-targets 全绿 (200 passed)
This commit is contained in:
徐涛
2026-07-05 19:47:03 +08:00
parent b8f4fe0fe3
commit 6e1182e64c
14 changed files with 17 additions and 0 deletions
+1
View File
@@ -29,6 +29,7 @@ fn message_text(msg: &Message) -> &str {
.next() .next()
.unwrap_or(""), .unwrap_or(""),
Message::UserImage { .. } => "[image]", Message::UserImage { .. } => "[image]",
_ => "",
} }
} }
+2
View File
@@ -27,6 +27,7 @@ fn message_text(msg: &Message) -> String {
}) })
.collect(), .collect(),
Message::UserImage { .. } => "[image]".into(), Message::UserImage { .. } => "[image]".into(),
_ => String::new(),
} }
} }
@@ -90,6 +91,7 @@ fn main() {
Message::User { .. } | Message::UserImage { .. } => "user", Message::User { .. } | Message::UserImage { .. } => "user",
Message::Assistant { .. } => "assistant", Message::Assistant { .. } => "assistant",
Message::ToolResult { .. } => "tool", Message::ToolResult { .. } => "tool",
_ => "unknown",
}; };
println!("[{i}] {role}: {}", message_text(m)); println!("[{i}] {role}: {}", message_text(m));
} }
+1
View File
@@ -18,6 +18,7 @@ use crate::tools::error::ToolError;
/// **不实现 `Clone`**:透传内层 `LlmError` / `MemoryError`,两者均未派生 `Clone`(保留 /// **不实现 `Clone`**:透传内层 `LlmError` / `MemoryError`,两者均未派生 `Clone`(保留
/// 完整错误信息,传递所有权)。如需在多 session 间共享错误状态,用 `Arc<AgentError>` 包装。 /// 完整错误信息,传递所有权)。如需在多 session 间共享错误状态,用 `Arc<AgentError>` 包装。
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[non_exhaustive]
pub enum AgentError { pub enum AgentError {
/// LLM 调用错误(透传 Phase 0)。 /// LLM 调用错误(透传 Phase 0)。
#[error("LLM 错误: {0}")] #[error("LLM 错误: {0}")]
+1
View File
@@ -57,6 +57,7 @@ impl Step {
/// 只能 clone 处于 `Pending` / `Running` / `Completed` / `Skipped` 状态的步骤。 /// 只能 clone 处于 `Pending` / `Running` / `Completed` / `Skipped` 状态的步骤。
#[derive(Debug)] #[derive(Debug)]
#[allow(deprecated)] #[allow(deprecated)]
#[non_exhaustive]
pub enum StepStatus { pub enum StepStatus {
/// 初始状态 —— 等待执行。 /// 初始状态 —— 等待执行。
Pending, Pending,
+1
View File
@@ -8,6 +8,7 @@ use std::time::Duration;
/// ///
/// 错误消息面向最终用户(中文),并尽量附带可操作的修复建议(如检查 API key、减少上下文)。 /// 错误消息面向最终用户(中文),并尽量附带可操作的修复建议(如检查 API key、减少上下文)。
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum LlmError { pub enum LlmError {
/// API 认证失败(API key 无效、过期或权限不足)。 /// API 认证失败(API key 无效、过期或权限不足)。
#[error( #[error(
+1
View File
@@ -7,6 +7,7 @@ use crate::llm::types::request_v2::MessageRequest;
/// 生命周期钩子事件点。 /// 生命周期钩子事件点。
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum HookEvent { pub enum HookEvent {
/// LLM 请求发起之前(可阻断)。 /// LLM 请求发起之前(可阻断)。
PreRequest, PreRequest,
+3
View File
@@ -20,6 +20,7 @@ use crate::llm::types::shared::ImageDetail;
/// 消费方 match 可直接区分文本和图片输入。 /// 消费方 match 可直接区分文本和图片输入。
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum Message { pub enum Message {
/// 系统提示(User & Assistant 之外的引导指令)。 /// 系统提示(User & Assistant 之外的引导指令)。
System { content: Vec<ContentBlock> }, System { content: Vec<ContentBlock> },
@@ -97,6 +98,7 @@ impl Message {
/// block 的逃生舱。 /// block 的逃生舱。
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum ContentBlock { pub enum ContentBlock {
/// 纯文本。 /// 纯文本。
Text { text: String }, Text { text: String },
@@ -132,6 +134,7 @@ pub enum ContentBlock {
/// 用途:在流式场景中,Provider 先下发 block 类型,再下发 block 内容增量。 /// 用途:在流式场景中,Provider 先下发 block 类型,再下发 block 内容增量。
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum ContentBlockType { pub enum ContentBlockType {
/// 文本块。 /// 文本块。
Text, Text,
+1
View File
@@ -12,6 +12,7 @@ pub struct StreamOptions {
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub enum ToolChoice { pub enum ToolChoice {
#[default] #[default]
None, None,
+1
View File
@@ -165,6 +165,7 @@ pub enum ContentBlockBuilder {
/// `thinking_signature`,最终通过 `finalize()` 回填到 `full_response` 的 `Thinking` block 中。 /// `thinking_signature`,最终通过 `finalize()` 回填到 `full_response` 的 `Thinking` block 中。
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum StreamEvent { pub enum StreamEvent {
/// 消息开始(元信息)。 /// 消息开始(元信息)。
MessageStart { id: String, model: String }, MessageStart { id: String, model: String },
+1
View File
@@ -68,6 +68,7 @@ pub enum StopSequence {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type")] #[serde(rename_all = "snake_case", tag = "type")]
#[non_exhaustive]
pub enum ResponseFormat { pub enum ResponseFormat {
Text, Text,
JsonObject, JsonObject,
+1
View File
@@ -12,6 +12,7 @@ use crate::memory::types::MemoryItem;
/// 对话消息管理策略。 /// 对话消息管理策略。
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[non_exhaustive]
pub enum MemoryStrategy { pub enum MemoryStrategy {
/// 滑动窗口:达到上限时删除最旧消息。 /// 滑动窗口:达到上限时删除最旧消息。
SlidingWindow, SlidingWindow,
+1
View File
@@ -6,6 +6,7 @@ use thiserror::Error;
/// ///
/// 错误消息面向最终用户(中文),并尽量附带可操作的修复建议(如检查环境变量、重试)。 /// 错误消息面向最终用户(中文),并尽量附带可操作的修复建议(如检查环境变量、重试)。
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[non_exhaustive]
pub enum MemoryError { pub enum MemoryError {
/// 按 ID 未找到指定记忆条目。可重试——通常是 namespace 拼写错误或条目已被淘汰。 /// 按 ID 未找到指定记忆条目。可重试——通常是 namespace 拼写错误或条目已被淘汰。
#[error("未找到记忆条目 '{0}',请检查 ID 或 namespace 是否正确")] #[error("未找到记忆条目 '{0}',请检查 ID 或 namespace 是否正确")]
+1
View File
@@ -1,6 +1,7 @@
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[non_exhaustive]
pub enum PromptError { pub enum PromptError {
#[error("模板解析错误: {0}。请检查模板语法({{var}} / {{#if}} / {{#each}}")] #[error("模板解析错误: {0}。请检查模板语法({{var}} / {{#if}} / {{#each}}")]
Parse(String), Parse(String),
+1
View File
@@ -4,6 +4,7 @@ use std::sync::Arc;
/// 工具调用过程中可能发生的所有错误。 /// 工具调用过程中可能发生的所有错误。
#[derive(thiserror::Error, Debug, Clone)] #[derive(thiserror::Error, Debug, Clone)]
#[non_exhaustive]
pub enum ToolError { pub enum ToolError {
/// 工具未注册。不可恢复——需调用方先 `registry.register(...)`。 /// 工具未注册。不可恢复——需调用方先 `registry.register(...)`。
#[error( #[error(