新增: AI Chat多项增强(审批去重/编辑重发/导出/实体引用/会话置顶搜索)+任务推进链df-nodes落地

This commit is contained in:
2026-06-16 12:41:13 +08:00
parent 212a927eee
commit 7d5cd4c89a
62 changed files with 4576 additions and 248 deletions

View File

@@ -15,11 +15,47 @@ export const aiApi = {
return invoke('ai_chat_force_send', { message, language: language || 'zh-CN', skill: skill || null })
},
/**
* 重新生成最后一条 AI 回复(UX-02)。
* 后端:占用 generating → 弹出末尾 AI 回复(保留触发它的 user 消息)→ 重跑 agentic loop。
* 前端消费:与 sendMessage 一样需本地 push 空气泡占位 + 置 streaming(见 useAiSend.regenerate)。
*/
regenerate(conversationId: string, language?: string): Promise<string> {
return invoke('ai_regenerate', { conversationId, language: language || 'zh-CN' })
},
/**
* 编辑最后一条 user 消息并重新生成(UX-09)。
* 后端:占用 generating → 替换末条 user content → 其后消息标 truncated(软删)→ 重跑 agentic loop。
* 前端消费:调 editMessage 前需移除被编辑消息之后的所有消息(视图截断)+ push 空气泡占位 + 置 streaming。
* 中间 user 消息编辑被后端拒绝(只允许末条)。
*/
editMessage(conversationId: string, newMessage: string, language?: string): Promise<string> {
return invoke('ai_chat_edit', { conversationId, newMessage, language: language || 'zh-CN' })
},
/** 批准/拒绝工具调用 */
approve(toolCallId: string, approved: boolean): Promise<string> {
return invoke('ai_approve', { toolCallId, approved })
},
/**
* 续跑 agentic 循环(F-260616-03:达 max_iterations 暂停态点继续)。
* 后端 ai_continue_loop:复位 stop_flag → try_continue_agent_loop 重新 spawn
* run_agentic_loop(iteration 从 0 重计,再跑 max_iterations 轮)。
*/
continueLoop(conversationId: string): Promise<string> {
return invoke('ai_continue_loop', { conversationId })
},
/**
* 停止 agentic 循环并走完成流程(F-260616-03:达 max_iterations 暂停态点停止)。
* 后端 ai_stop_loop:复位 generating + emit AiCompleted(暂停前已 save)。
*/
stopLoop(conversationId: string): Promise<string> {
return invoke('ai_stop_loop', { conversationId })
},
/** 查询某对话积压的待审批工具(重启后恢复 toolCard pending_approval 态用) */
pendingToolCalls(convId: string): Promise<{ tool_call_id: string; conversation_id: string | null }[]> {
return invoke('ai_pending_tool_calls', { convId })
@@ -74,6 +110,11 @@ export const aiApi = {
return invoke('ai_set_concurrency_config', { globalLimit, perConvLimit })
},
/** 设置 Agentic 循环最大轮次运行时调整loop 入口锁定边界,热改下次发消息生效) */
setAgentMaxIterations(value: number): Promise<void> {
return invoke('ai_set_agent_max_iterations', { value })
},
/** 列出本机 Claude 技能skills + commands + plugins */
listSkills(): Promise<SkillInfo[]> {
return invoke('ai_list_skills')
@@ -120,4 +161,18 @@ export const aiApi = {
archiveConversation(conversationId: string, archived: boolean): Promise<void> {
return invoke('ai_conversation_archive', { conversationId, archived })
},
/** 置顶/取消置顶对话(UX-17) */
setPinnedConversation(conversationId: string, pinned: boolean): Promise<void> {
return invoke('ai_conversation_set_pinned', { conversationId, pinned })
},
/**
* 导出对话为指定格式(UX-18:对话导出;消费 batch46 ai_conversation_export IPC)。
* 后端返回导出内容 String(markdown/json/txt),前端落 Blob 下载或复制剪贴板。
* @param format 'markdown' | 'json' | 'txt'
*/
exportConversation(conversationId: string, format: 'markdown' | 'json' | 'txt'): Promise<string> {
return invoke('ai_conversation_export', { conversationId, format })
},
}

View File

@@ -125,7 +125,7 @@ export interface WorkflowRecord {
/** 工作流事件载荷(后端 emit 的结构) */
/** 工作流事件类型字面量联合(对应后端 WorkflowEvent serde tag=type rename_all=snake_caseR7收窄防写错 type 字符串) */
export type WorkflowEventType =
| 'node_started' | 'node_progress' | 'node_output' | 'node_completed' | 'node_failed'
| 'node_started' | 'node_progress' | 'node_output' | 'node_completed' | 'node_failed' | 'node_cancelled'
| 'workflow_paused' | 'workflow_completed' | 'workflow_failed'
| 'human_approval_request' | 'human_approval_response'
@@ -180,6 +180,13 @@ export interface AiProviderConfig {
updated_at: string
}
/**
* AI 错误分类字面量集(B-260615-42)。
* 与后端 `commands::ai::ErrorType` 的 serde(rename_all = "snake_case") 严格对齐。
* 前端消费方 switch 于此常量集做差异化提示(auth 引导填 key / network 提示连接 / 等)。
*/
export type AiErrorType = 'auth' | 'network' | 'timeout' | 'provider_config' | 'unknown'
/** AI 聊天事件(后端 emit 的结构conversation_id 用于多对话流式路由) */
export type AiChatEvent = ({
type: 'AiTextDelta'; delta: string
@@ -194,11 +201,14 @@ export type AiChatEvent = ({
} | {
type: 'AiCompleted'; total_tokens: number; prompt_tokens: number; completion_tokens: number
} | {
type: 'AiError'; error: string
type: 'AiError'; error: string; error_type?: AiErrorType
} | {
type: 'AiAgentRound'; round: number
} | {
type: 'AiHeartbeat'
} | {
// F-260616-03: 达 max_iterations 暂停态(后端仍 generating=true),前端展示操作卡询问继续/停止
type: 'AiMaxRoundsReached'
}) & {
conversation_id?: string
}
@@ -233,6 +243,7 @@ export interface AiConversationSummary {
provider_id: string | null
model: string | null
archived: boolean
pinned?: boolean
prompt_tokens?: number | null
completion_tokens?: number | null
created_at: string

View File

@@ -3,12 +3,25 @@ import { listen } from '@tauri-apps/api/event'
import type { WorkflowRecord, WorkflowEventPayload } from './types'
export const workflowApi = {
/** 触发工作流执行,返回 execution_id */
run(name: string, dag: unknown, config?: Record<string, unknown>): Promise<string> {
/**
* 触发工作流执行,返回 execution_id。
*
* F-260616-06 阶段2(②-2): taskId/targetStatus 可选,同时传时工作流完成/失败联动推进任务。
* B-260615-34:Tauri 2 IPC 不转 camelCase,snake_case 对齐后端 workflow.rs。
*/
run(
name: string,
dag: unknown,
config?: Record<string, unknown>,
taskId?: string,
targetStatus?: string,
): Promise<string> {
return invoke('run_workflow', {
name,
dag,
config: config ?? {},
task_id: taskId,
target_status: targetStatus,
})
},