feat(presenter): M103 AI 助手栏视图模型与事件投影
- 新增 crates/presenter/src/agent.rs(Presenter 门面:agent_rail / agent_submit /
agent_mark_read / agent_confirm + AgentTransport 端口 + 裁决审计镜像)
- 新增 agent/rail.rs:AgentRail(messages / unread / busy / draft / confirm / streaming /
yolo / endpoint_label / error),四类 AgentEvent 的投影与唯一脱敏闸门
- 新增 agent/mock.rs:脚本化后端(正常问答 / 流式中途出错 / 需确认的写操作)
- dto/agent.rs:ConfirmRequest / Sensitivity + AgentEvent::{Failed, ConfirmRequested,
ConfirmResolved};AgentEvent 去掉 Eq(details 含 serde_json::Value)
- state.rs:AiSession 迁成 AgentRail,apply_agent 走 rail.ingest + 未读规则(可见性 =
独立页或栏展开);navigate/toggle_ai 展开时清未读
- 测试:agent/tests.rs 14 条(四条路径 + JWT 红线 + YOLO 语义 + 提交前置条件),
state_tests.rs 补 4 条(Failed / ConfirmRequested / 未读可见性 / 用户消息不计未读)
- 两行声明补进 lib.rs(pub mod agent)与 dto/mod.rs(重导出 ConfirmRequest/Sensitivity)
This commit is contained in:
1 parent
15eec1160d
commit
a8d4cce3e2
9 files changed
+1295
-99
No files matched your search
@@ -1,4 +1,8 @@
|
||||
//! AI 会话 DTO:消息、工具调用可视化与 agent 事件。
|
||||
//! AI 会话 DTO:消息、工具调用可视化、确认请求与 agent 事件。
|
||||
//!
|
||||
//! 与 agent 侧的对应关系(`crates/agent/src/event.rs` / `confirm.rs`):这里是**扁平镜像**,
|
||||
//! 不 import `unlucky_agent::*`(dto 是 IPC 边界,见 `dto/mod.rs` 的纪律)。字段口径刻意逐字
|
||||
//! 对齐,翻译在接线层做:`AgentEvent::ConfirmRequested` ← `confirm::ConfirmRequest`。
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -59,10 +63,70 @@ impl ChatMessage {
|
||||
streaming: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// 系统提示(弱化展示;错误横幅也进会话历史,用户回翻时看得到)。
|
||||
pub fn system(text: impl Into<String>) -> Self {
|
||||
Self {
|
||||
role: ChatRole::System,
|
||||
text: text.into(),
|
||||
tool: None,
|
||||
streaming: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 敏感等级(与 agent 侧 `confirm::Sensitivity` 逐字一致)。
|
||||
///
|
||||
/// | 等级 | 语义 |
|
||||
/// |------|------|
|
||||
/// | `Low` | 静默生效 |
|
||||
/// | `Medium` | 静默生效,审计里能查到 |
|
||||
/// | `High` | 必须用户确认(YOLO 可跳过确认,但**仍受白名单约束**) |
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Sensitivity {
|
||||
/// 静默生效。
|
||||
#[default]
|
||||
Low,
|
||||
/// 静默生效但审计标记。
|
||||
Medium,
|
||||
/// 必须用户确认。
|
||||
High,
|
||||
}
|
||||
|
||||
impl Sensitivity {
|
||||
/// 是否会触发确认弹窗(非 YOLO 时)。
|
||||
#[must_use]
|
||||
pub fn needs_confirm(self) -> bool {
|
||||
self == Self::High
|
||||
}
|
||||
}
|
||||
|
||||
/// 一次待确认的写操作(确认弹窗的原料;与 agent 侧 `confirm::ConfirmRequest` 对齐)。
|
||||
///
|
||||
/// 构造时**不要**放凭据:`details` 会按键名与内容双道脱敏([`crate::agent::rail`]),
|
||||
/// 但白名单之外的键本来就不该出现在这里。
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ConfirmRequest {
|
||||
/// 请求 id(编排层生成,UI 回填决定时原样带回)
|
||||
pub id: String,
|
||||
/// 工具名(与 ToolSpec 注册表同名)
|
||||
pub tool: String,
|
||||
/// 一句话请求(「AI 请求把下载并发 64 改为 16」)
|
||||
pub summary: String,
|
||||
/// 结构化细节(`{"path":…, "old":…, "new":…}`),UI 画 diff 用
|
||||
pub details: serde_json::Value,
|
||||
/// 敏感等级
|
||||
pub sensitivity: Sensitivity,
|
||||
}
|
||||
|
||||
/// agent 侧事件。
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
///
|
||||
/// 四类都投到 [`crate::agent::AgentRail`] 上:流式增量 → 最后一条 assistant 消息;工具调用 →
|
||||
/// 会话里可见的 tool 条目(D4);错误 → 系统条目 + 横幅;确认请求 → `rail.confirm`。
|
||||
///
|
||||
/// 注意这里**没有** `Eq`:`ConfirmRequest::details` 是 `serde_json::Value`(可含浮点)。
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum AgentEvent {
|
||||
/// 追加一条完整消息
|
||||
MessageAppended(ChatMessage),
|
||||
@@ -94,4 +158,22 @@ pub enum AgentEvent {
|
||||
/// 结果摘要
|
||||
summary: String,
|
||||
},
|
||||
/// 循环级错误(provider 断流、AI 被禁用、工具内部异常)。
|
||||
///
|
||||
/// 与 `ToolCallFinished { ok: false }` 的分工:那个是**某一次工具调用**失败,对话继续;
|
||||
/// 这个是**这一轮回复**中止,rail 要收敛掉所有流式标记并立一个错误横幅。
|
||||
Failed {
|
||||
/// 人类可读原因
|
||||
message: String,
|
||||
},
|
||||
/// 需要用户确认(分级确认:写操作先问再改)。
|
||||
ConfirmRequested {
|
||||
/// 待确认请求
|
||||
request: ConfirmRequest,
|
||||
},
|
||||
/// 确认请求已收敛(重放/超时/别处已裁决):把 rail 上同 id 的待确认清掉,避免僵尸弹窗。
|
||||
ConfirmResolved {
|
||||
/// 请求 id
|
||||
id: String,
|
||||
},
|
||||
}
|
||||
@@ -26,7 +26,7 @@ mod settings;
|
||||
mod versions;
|
||||
|
||||
pub use accounts::{AccountKind, AccountView, DeviceLoginPhase, DeviceLoginView};
|
||||
pub use agent::{AgentEvent, ChatMessage, ChatRole, ToolCallView};
|
||||
pub use agent::{AgentEvent, ChatMessage, ChatRole, ConfirmRequest, Sensitivity, ToolCallView};
|
||||
pub use events::{AppCommand, AppEvent, Backend, CoreEvent, LaunchFinished, LiveLogBatch};
|
||||
pub use install::{derive_speed, human_bytes, InstallProgressView, InstallStage};
|
||||
pub use instances::{
|
||||
|
||||
Reference in new issue
Block a user