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