新增: miniapp补齐4远程命令(approve/authorize_dir/continue_loop/stop_loop 对齐Phase3 §2.2)
This commit is contained in:
@@ -24,6 +24,10 @@
|
||||
* - stop(): 停止生成(stop Command → device invoke ai_chat_stop)
|
||||
* - regenerate(): 重发最后一条 user 消息(重新 send_message)
|
||||
* - switchConversation(id): 切换会话(switch Command → device 切 active)
|
||||
* - approve(toolCallId, approved): 审批工具调用(approve Command → device invoke ai_approve)
|
||||
* - authorizeDir(toolCallId, decision): 路径授权(authorize_dir Command → device invoke ai_authorize_dir)
|
||||
* - continueLoop(convId): 继续循环(continue_loop Command → device invoke ai_continue_loop)
|
||||
* - stopLoop(convId): 停止循环(stop_loop Command → device invoke ai_stop_loop)
|
||||
*/
|
||||
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
@@ -428,6 +432,84 @@ function regenerate(): void {
|
||||
send(lastUserText)
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批工具调用(approve Command → relay → device invoke ai_approve)
|
||||
*
|
||||
* Phase3 §2.2 路由表:{cmd:"approve", args:{tool_call_id, approved}}
|
||||
* 对应事件:AiApprovalRequired(挂起审批列表 pendingApprovals)。
|
||||
*/
|
||||
function approve(toolCallId: string, approved: boolean): void {
|
||||
if (!toolCallId) return
|
||||
const cmd: MiniCommand = {
|
||||
cmd: 'approve',
|
||||
args: {
|
||||
tool_call_id: toolCallId,
|
||||
approved,
|
||||
},
|
||||
}
|
||||
wsClient.send(cmd)
|
||||
// 乐观从挂起列表移除(对齐 AiApprovalResult 事件处理,避免 UI 卡 pending)
|
||||
const idx = pendingApprovals.findIndex((p) => p.id === toolCallId)
|
||||
if (idx >= 0) pendingApprovals.splice(idx, 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 路径授权(authorize_dir Command → relay → device invoke ai_authorize_dir)
|
||||
*
|
||||
* Phase3 §2.2 路由表:{cmd:"authorize_dir", args:{tool_call_id, decision}}
|
||||
* 对应事件:AiDirAuthRequired(决策:'once'=本次 / 'always'=永久 / 'deny'=拒绝)。
|
||||
*/
|
||||
function authorizeDir(toolCallId: string, decision: 'once' | 'always' | 'deny'): void {
|
||||
if (!toolCallId) return
|
||||
const cmd: MiniCommand = {
|
||||
cmd: 'authorize_dir',
|
||||
args: {
|
||||
tool_call_id: toolCallId,
|
||||
decision,
|
||||
},
|
||||
}
|
||||
wsClient.send(cmd)
|
||||
}
|
||||
|
||||
/**
|
||||
* 继续循环(continue_loop Command → relay → device invoke ai_continue_loop)
|
||||
*
|
||||
* Phase3 §2.2 路由表:{cmd:"continue_loop", args:{conversation_id}}
|
||||
* 对应场景:AiMaxRoundsReached 达最大轮次暂停后,用户选「继续」再跑一轮。
|
||||
*/
|
||||
function continueLoop(conversationId?: string | null): void {
|
||||
const convId = conversationId ?? activeConversationId.value
|
||||
if (!convId) {
|
||||
console.warn('[useAiChat] continue_loop 缺 conversation_id')
|
||||
return
|
||||
}
|
||||
const cmd: MiniCommand = {
|
||||
cmd: 'continue_loop',
|
||||
args: { conversation_id: convId },
|
||||
}
|
||||
wsClient.send(cmd)
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止循环(stop_loop Command → relay → device invoke ai_stop_loop)
|
||||
*
|
||||
* Phase3 §2.2 路由表:{cmd:"stop_loop", args:{conversation_id}}
|
||||
* 对应场景:AiMaxRoundsReached 达最大轮次暂停后,用户选「停止」彻底终止。
|
||||
* 与 stop 区别:stop 是中断流式生成,stop_loop 是停止多轮 agent 循环。
|
||||
*/
|
||||
function stopLoop(conversationId?: string | null): void {
|
||||
const convId = conversationId ?? activeConversationId.value
|
||||
if (!convId) {
|
||||
console.warn('[useAiChat] stop_loop 缺 conversation_id')
|
||||
return
|
||||
}
|
||||
const cmd: MiniCommand = {
|
||||
cmd: 'stop_loop',
|
||||
args: { conversation_id: convId },
|
||||
}
|
||||
wsClient.send(cmd)
|
||||
}
|
||||
|
||||
/** 切换会话(switch Command → device 切 active_conversation_id) */
|
||||
function switchConversation(convId: string): void {
|
||||
activeConversationId.value = convId
|
||||
@@ -484,6 +566,10 @@ export function useAiChat() {
|
||||
regenerate,
|
||||
switchConversation,
|
||||
newConversation,
|
||||
approve,
|
||||
authorizeDir,
|
||||
continueLoop,
|
||||
stopLoop,
|
||||
handleEvent,
|
||||
friendlyError,
|
||||
}
|
||||
|
||||
@@ -83,7 +83,9 @@ export type ControlMessage =
|
||||
* - cmd:命令名(对齐 src-tauri command 函数名)
|
||||
* - args:命令参数(对齐各 command 的参数)
|
||||
*
|
||||
* MVP 三条(send_message / stop / switch_conversation),其余审批/重试等留后续批。
|
||||
* Phase3 §2.2 路由表全覆盖(8 条):
|
||||
* - send_message / stop / switch_conversation / regenerate(MVP 已发)
|
||||
* - approve / authorize_dir / continue_loop / stop_loop(阶段3 补齐,见 useAiChat.ts)
|
||||
*/
|
||||
export interface MiniCommand {
|
||||
/** Tauri command 名 */
|
||||
@@ -108,3 +110,38 @@ export interface SwitchConversationArgs {
|
||||
export interface StopArgs {
|
||||
conversation_id?: string | null
|
||||
}
|
||||
|
||||
/** approve 命令参数(对齐 src-tauri ai_approve,Phase3 §2.2 路由表) */
|
||||
export interface ApproveArgs {
|
||||
/** 待审批的工具调用 id(对应 AiApprovalRequired 事件的 id) */
|
||||
tool_call_id: string
|
||||
/** 是否批准(true=批准执行,false=拒绝) */
|
||||
approved: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* authorize_dir 命令参数(对齐 src-tauri ai_authorize_dir,Phase3 §2.2 路由表)
|
||||
*
|
||||
* decision 取值:对齐 src-tauri ai_authorize_dir 的 decision 参数
|
||||
* - 'once':本次授权(下次同路径仍需问)
|
||||
* - 'always':永久授权(写入会话级信任目录)
|
||||
* - 'deny':拒绝(本次不授权)
|
||||
*/
|
||||
export interface AuthorizeDirArgs {
|
||||
/** 待授权的工具调用 id(对应 AiDirAuthRequired 事件的 id) */
|
||||
tool_call_id: string
|
||||
/** 授权决策('once' / 'always' / 'deny') */
|
||||
decision: 'once' | 'always' | 'deny'
|
||||
}
|
||||
|
||||
/** continue_loop 命令参数(对齐 src-tauri ai_continue_loop,Phase3 §2.2 路由表) */
|
||||
export interface ContinueLoopArgs {
|
||||
/** 需继续运行的会话 id */
|
||||
conversation_id: string
|
||||
}
|
||||
|
||||
/** stop_loop 命令参数(对齐 src-tauri ai_stop_loop,Phase3 §2.2 路由表) */
|
||||
export interface StopLoopArgs {
|
||||
/** 霷停止循环的会话 id */
|
||||
conversation_id: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user