(config: AgentLoopConfig = {})
| 77 | // ================== |
| 78 | |
| 79 | export function useAgentLoop(config: AgentLoopConfig = {}) { |
| 80 | const approvalStore = useApprovalStore(); |
| 81 | const thinkingStore = useThinkingStore(); |
| 82 | const toolsStore = useToolsStore(); |
| 83 | const { connect, getInstance, isConnected } = useWebSocket(); |
| 84 | |
| 85 | // 状态 |
| 86 | const isRunning = ref(false); |
| 87 | const isPaused = ref(false); |
| 88 | const currentOutput = ref(""); |
| 89 | const history = ref<any[]>([]); |
| 90 | const pendingApproval = ref<ApprovalRequest | null>(null); |
| 91 | |
| 92 | // 配置 |
| 93 | const sensitiveTools = config.sensitiveTools || ["Edit", "Write", "bash", "fs_write"]; |
| 94 | const maxRetries = config.maxRetries || 3; |
| 95 | const maxLoops = config.maxLoops || 10; |
| 96 | |
| 97 | // WebSocket URL |
| 98 | const apiUrl = config.apiUrl || import.meta.env.VITE_API_URL || "http://localhost:8080"; |
| 99 | const wsUrl = config.wsUrl || apiUrl.replace(/^http/, "ws") + "/v1/ws"; |
| 100 | |
| 101 | /** |
| 102 | * 初始化 WebSocket 连接 |
| 103 | */ |
| 104 | const initConnection = async () => { |
| 105 | if (!isConnected.value) { |
| 106 | await connect(wsUrl); |
| 107 | } |
| 108 | return getInstance(); |
| 109 | }; |
| 110 | |
| 111 | /** |
| 112 | * 发送思考事件 |
| 113 | */ |
| 114 | const emitThink = (event: Partial<ThinkAloudEvent>) => { |
| 115 | const fullEvent: ThinkAloudEvent = { |
| 116 | id: generateId("think"), |
| 117 | stage: event.stage || "Thinking", |
| 118 | reasoning: event.reasoning || "", |
| 119 | decision: event.decision || "", |
| 120 | timestamp: new Date().toISOString(), |
| 121 | ...event, |
| 122 | }; |
| 123 | |
| 124 | config.onThink?.(fullEvent); |
| 125 | return fullEvent; |
| 126 | }; |
| 127 | |
| 128 | /** |
| 129 | * 执行 Agent Loop |
| 130 | * |
| 131 | * @param input 用户输入 |
| 132 | * @param contextData 上下文数据 |
| 133 | * @param resumeState 恢复状态 (用于 HITL 恢复) |
| 134 | */ |
| 135 | const execute = async (input: string, contextData: string = "", resumeState?: { history: any[]; approvedTool?: ApprovalRequest }): Promise<AgentExecutionResult> => { |
| 136 | isRunning.value = true; |
nothing calls this directly
no test coverage detected