新增: 小程序端跨端AI对话
This commit is contained in:
@@ -55,6 +55,8 @@ use serde::{Deserialize, Serialize};
|
||||
// RiskLevel 不在此 import:PendingApproval.risk_level 删后 mod.rs 不再用(audit 流程在 audit.rs 自 import)
|
||||
use df_ai::context::ContextManager;
|
||||
use df_ai::context::ContextConfig;
|
||||
// F-#95 扩展:AiMessageHistory 事件载荷 Vec<ChatMessage>(历史消息同步)。
|
||||
use df_ai::provider::ChatMessage;
|
||||
|
||||
// ============================================================
|
||||
// 重导出 — 保路径不变(state.rs / lib.rs / knowledge.rs 在用)
|
||||
@@ -145,6 +147,24 @@ pub enum AiChatEvent {
|
||||
error_type: Option<ErrorType>,
|
||||
conversation_id: Option<String>,
|
||||
},
|
||||
/// F-260622-02 跨端用户消息同步(miniapp→device→桌面 user 气泡渲染):
|
||||
///
|
||||
/// 触发:remote_bridge `route_send_message` 放行后(调 ai_chat_send 前)`publish_event`,
|
||||
/// 把 miniapp 发来的用户消息广播到 ai_event_bus。语义:远程入口(miniapp)发来的用户消息,
|
||||
/// 专供桌面 useAiEvents 收到并补 user 气泡(桌面本地 sendMessage 是乐观渲染不发此事件)。
|
||||
///
|
||||
/// 根因(为何需要此事件):ai_chat_send 内部只 push session.messages,全程不 emit 用户消息,
|
||||
/// 桌面用户气泡是纯本地乐观渲染(useAiSend.sendMessage 本地 push,不依赖事件)。
|
||||
/// miniapp 发消息时桌面用户没在自己输入框敲字 → 桌面 store 没有这条 user 气泡 →
|
||||
/// 桌面只看到 assistant 响应气泡(经 AiAgentRound/AiTextDelta 流式建),前面缺对应 user prompt
|
||||
/// → **孤立响应气泡**。此事件填补该缺口。
|
||||
///
|
||||
/// 去重(防双气泡):前端 handleEvent 收到此事件时,若末条已是同 content 的 user(本地乐观
|
||||
/// push 的),跳过。miniapp 自身乐观 push 也会收到此事件回灌,同样去重处理。
|
||||
AiUserMessage {
|
||||
message: String,
|
||||
conversation_id: Option<String>,
|
||||
},
|
||||
/// Agent 循环新一轮(前端需新建 assistant 消息)
|
||||
AiAgentRound { round: u32, conversation_id: Option<String> },
|
||||
/// 流式心跳(静默期报活,前端 watchdog reset,区分「LLM 在跑」与「真断」)
|
||||
@@ -200,6 +220,36 @@ pub enum AiChatEvent {
|
||||
options: Vec<String>,
|
||||
conversation_id: Option<String>,
|
||||
},
|
||||
/// F-#95 跨端会话列表同步(Phase3,2026-06-22):device 响应 miniapp `list_conversations`
|
||||
/// 命令,把本地 AiConversationRepo 列表摘要(不含消息体,省带宽)推回 miniapp。
|
||||
///
|
||||
/// 触发:remote_bridge `list_conversations` 路由 → `list_all()` → 映射 ConvSummary →
|
||||
/// `publish_event`(跨端透传,经 EventBus→tunnel subscriber→relay→miniapp)。
|
||||
///
|
||||
/// 双职责:
|
||||
/// 1. miniapp 会话列表渲染(conversations/index.vue 替换本地空表)
|
||||
/// 2. device 在线探测(miniapp 收到此响应 = device 在线,chat/index.vue 状态文案切「已连接桌面端」)
|
||||
///
|
||||
/// 兼容:relay 纯透传不广播 device presence,故「device 是否在线」靠此响应隐式判定
|
||||
/// (device 离线则 miniapp 发 list_conversations 无响应,文案保持「已连接中继」诚实表述)。
|
||||
AiConversationList {
|
||||
/// 会话摘要列表(已按 updated_at 倒序,不含 messages 全文)
|
||||
conversations: Vec<ConvSummary>,
|
||||
},
|
||||
/// F-#95 扩展:miniapp 历史消息同步(device→miniapp 推消息列表)。
|
||||
///
|
||||
/// 触发:remote_bridge `load_messages` 路由 → `ai_messages.list_by_conversation` →
|
||||
/// 映射 `ChatMessage`(record_to_message,对齐 ai_conversation_switch 读路径) →
|
||||
/// `publish_event`(跨端透传,经 EventBus→tunnel subscriber→relay→miniapp)。
|
||||
///
|
||||
/// 职责:miniapp 点进对话时加载历史消息(替代 switch_conversation 后端忽略致空白)。
|
||||
/// miniapp 据 conversation_id 匹配 activeConversationId 才替换,防串会话。
|
||||
AiMessageHistory {
|
||||
/// 对话 ID
|
||||
conversation_id: String,
|
||||
/// 历史消息数组(ORDER BY seq ASC,含 role/content/tool_calls 等完整字段)
|
||||
messages: Vec<ChatMessage>,
|
||||
},
|
||||
/// L2 统一状态机(批2 1b,2026-06-22):对话生命周期状态变更通知。
|
||||
///
|
||||
/// 后端 `ConvState`(Idle/Generating/Stopping/Error/Compressed)经写收敛
|
||||
@@ -214,6 +264,61 @@ pub enum AiChatEvent {
|
||||
conv_state: ConvState,
|
||||
conversation_id: Option<String>,
|
||||
},
|
||||
/// F-#95 跨端技能列表同步(Phase3,2026-06-23):device 响应 miniapp `list_skills` 命令,
|
||||
/// 把本机 Claude 技能(skills/commands/plugins 三类,`ai_list_skills` 进程内缓存)推回 miniapp。
|
||||
///
|
||||
/// 触发:remote_bridge `list_skills` 路由 → `ai_list_skills().await` →
|
||||
/// `publish_event`(跨端透传,经 EventBus→tunnel subscriber→relay→miniapp)。
|
||||
///
|
||||
/// 职责:miniapp 技能联想(输入框 `/` 触发浮层),对齐桌面端 `/` 联想体验。
|
||||
/// 内嵌 `SkillInfo` 自身序列化字段(name/description/argument_hint?/source/path/duplicates?),
|
||||
/// 变体整体无额外 rename_all 需求(照 AiConversationList 变体模式)。
|
||||
AiSkillList {
|
||||
/// 本机技能列表(ai_list_skills 返回的进程内缓存,已按 skills>commands>plugins 优先级去重)
|
||||
skills: Vec<crate::commands::ai::skills::SkillInfo>,
|
||||
},
|
||||
/// F-#95 跨端实体列表同步(Phase3,2026-06-23):device 响应 miniapp `list_entities` 命令,
|
||||
/// 把本地项目/任务/灵感全量列表(list_projects/list_tasks/list_ideas 全量等价路径)推回 miniapp。
|
||||
///
|
||||
/// 触发:remote_bridge `list_entities` 路由 → 并行调三 Tauri command(query/project_id/status
|
||||
/// 均传 None 走 list_active/list_all 全量) → 合并打包 → `publish_event` 跨端透传。
|
||||
///
|
||||
/// 职责:miniapp `@` 实体联想(输入框 `@` 触发浮层选项目/任务/灵感),对齐桌面端 @ 体验。
|
||||
/// 全量字段(对齐桌面端 src/api/types.ts,带宽敏感裁剪留后续批;Record 类型是
|
||||
/// #[tauri::command] 返回值,必然 impl Serialize)。
|
||||
AiEntityList {
|
||||
/// 项目全量列表(list_active,deleted_at IS NULL)
|
||||
projects: Vec<df_storage::models::ProjectRecord>,
|
||||
/// 任务全量列表(list_active 等价,未删任务)
|
||||
tasks: Vec<df_storage::models::TaskRecord>,
|
||||
/// 灵感全量列表(list_by_query 空 query,等价 list_all)
|
||||
ideas: Vec<df_storage::models::IdeaRecord>,
|
||||
},
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// F-#95 跨端会话列表同步:会话摘要结构
|
||||
// ============================================================
|
||||
|
||||
/// 会话摘要(miniapp 会话列表渲染用,对齐 apps/df-miniapp/src/types/events.ts:78 Conversation)。
|
||||
///
|
||||
/// 与 `AiConversationRecord` 区别:仅含列表展示必需字段,**不含 messages 全文**(省带宽,
|
||||
/// miniapp MVP 不在列表展示历史消息,进入会话时按需同步)。`updated_at` 用 i64(ms 数值)
|
||||
/// 便于前端直接比较排序;record 里是 ms 字符串,routing 层 parse 转。
|
||||
///
|
||||
/// `#[serde(rename_all = "camelCase")]` 对齐 miniapp Conversation 字段名
|
||||
/// (id/title/lastMessage/updatedAt/createdAt),TS 侧无需 snake→camel 转换。
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ConvSummary {
|
||||
pub id: String,
|
||||
pub title: String,
|
||||
/// 最近一条消息摘要(MVP 暂不取,留 None;后续批可解析 messages 末条)
|
||||
pub last_message: Option<String>,
|
||||
/// 最近更新时间(ms 数值)
|
||||
pub updated_at: Option<i64>,
|
||||
/// 创建时间(ms 数值,可选展示)
|
||||
pub created_at: Option<i64>,
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
|
||||
Reference in New Issue
Block a user