import { reactive } from 'vue' import { message } from 'ant-design-vue' import { handleChatError } from '@/utils/errorHandler' import { agentApi } from '@/apis' const normalizeOptions = (rawOptions) => { if (!Array.isArray(rawOptions)) return [] return rawOptions .map((item) => { if (item && typeof item === 'object') { const label = String(item.label || item.value || '').trim() const value = String(item.value || item.label || '').trim() return label && value ? { label, value } : null } const text = String(item || '').trim() return text ? { label: text, value: text } : null }) .filter(Boolean) } const extractQuestionPayload = (chunk) => { const interruptInfo = chunk?.interrupt_info || {} const rawOptions = chunk?.options || interruptInfo?.options || [] const options = normalizeOptions(rawOptions) const operation = chunk?.operation || interruptInfo?.operation || '' const source = chunk?.source || interruptInfo?.source || 'interrupt' const multiSelect = Boolean(chunk?.multi_select ?? interruptInfo?.multi_select ?? false) const allowOther = Boolean(chunk?.allow_other ?? interruptInfo?.allow_other ?? true) const questionId = chunk?.question_id || interruptInfo?.question_id || '' const question = chunk?.question || interruptInfo?.question || '请选择一个选项' return { questionId, question, options, multiSelect, allowOther, source, operation } } export function useApproval({ getThreadState, resetOnGoingConv, fetchThreadMessages }) { const approvalState = reactive({ showModal: false, questionId: '', question: '', operation: '', options: [], multiSelect: false, allowOther: true, source: '', threadId: null }) const handleApproval = async (answer, currentAgentId, agentConfigId = null) => { const threadId = approvalState.threadId if (!threadId) { message.error('无效的提问请求') approvalState.showModal = false return } const threadState = getThreadState(threadId) if (!threadState) { message.error('无法找到对应的对话线程') approvalState.showModal = false return } approvalState.showModal = false if (threadState.streamAbortController) { threadState.streamAbortController.abort() threadState.streamAbortController = null } threadState.isStreaming = true resetOnGoingConv(threadId) threadState.streamAbortController = new AbortController() const requestBody = { thread_id: threadId, answer, config: agentConfigId ? { agent_config_id: agentConfigId } : {} } try { const response = await agentApi.resumeAgentChat(currentAgentId, requestBody, { signal: threadState.streamAbortController?.signal }) if (!response.ok) { const errorText = await response.text() throw new Error(`HTTP error! status: ${response.status}, details: ${errorText}`) } return response } catch (error) { if (error.name !== 'AbortError') { handleChatError(error, 'resume') message.error(`恢复对话失败: ${error.message || '未知错误'}`) } threadState.isStreaming = false threadState.streamAbortController = null throw error } } const processApprovalInStream = (chunk, threadId, currentAgentId) => { if ( chunk.status !== 'ask_user_question_required' && chunk.status !== 'human_approval_required' ) { return false } const threadState = getThreadState(threadId) if (!threadState) return false const payload = extractQuestionPayload(chunk) threadState.isStreaming = false approvalState.showModal = true approvalState.questionId = payload.questionId approvalState.question = payload.question approvalState.operation = payload.operation approvalState.options = payload.options approvalState.multiSelect = payload.multiSelect approvalState.allowOther = payload.allowOther approvalState.source = payload.source approvalState.threadId = chunk.thread_id || threadId fetchThreadMessages({ agentId: currentAgentId, threadId }) return true } const resetApprovalState = () => { approvalState.showModal = false approvalState.questionId = '' approvalState.question = '' approvalState.operation = '' approvalState.options = [] approvalState.multiSelect = false approvalState.allowOther = true approvalState.source = '' approvalState.threadId = null } return { approvalState, handleApproval, processApprovalInStream, resetApprovalState } }