问题
AskUserTool 原先使用同步回调 AskHandler 模式,CLI 下直接阻塞读 stdin,在 WebUI 场景下完全无法工作。
解决方案
将 AskUserTool 改为始终立即返回 {"status":"pending",...},由 AgentLoop 通过 RunControl::await_ask_user() 阻塞等待用户响应。RuntimeService::Control 通过 SSE 事件 ask_user_requested 通知前端,前端通过新增的 HTTP 端点回传答案。
数据流
AskUserTool → 立即返回 pending
↓
AgentLoop 检测 pending → control.await_ask_user()
↓
RuntimeService::Control → SSE "ask_user_requested" (含 question/options/call_id)
↓
前端展示问题,用户作答
↓
POST /v1/runs/{id}/ask-response {call_id, response}
↓
RuntimeService 找到对应 Control,fulfill promise
↓
AgentLoop 拿到答案,继续执行
改动清单
| 文件 |
改动 |
libs/core/include/merak/execution.hpp |
RunControl 新增 await_ask_user() 虚方法 + NullRunControl 默认实现 |
libs/runtime/include/merak/runtime_service.hpp |
新增 respond_to_ask_user() 声明 |
libs/runtime/src/runtime_service.cpp |
Control 实现 promise/future 等待(5分钟超时),SSE 事件发送,cancel 唤醒 |
libs/http/src/http_server.cpp |
新增 POST /v1/runs/{id}/ask-response 端点 |
libs/loop/src/agent_loop.cpp |
handle_tool_calls 中检测 ask_user pending 并调用 await_ask_user |
libs/tools/include/merak/ask_user_tool.hpp |
删除 AskHandler 类型和 ask_handler_ 成员 |
libs/tools/src/ask_user_tool.cpp |
删除同步回调逻辑,始终返回 pending |
cli/src/main.cpp |
删除 stdin 读取的 ask_handler lambda |
前端待办
WebUI 需要监听 ask_user_requested SSE 事件并调用 POST /v1/runs/{id}/ask-response 完成闭环。
问题
AskUserTool原先使用同步回调AskHandler模式,CLI 下直接阻塞读 stdin,在 WebUI 场景下完全无法工作。解决方案
将
AskUserTool改为始终立即返回{"status":"pending",...},由AgentLoop通过RunControl::await_ask_user()阻塞等待用户响应。RuntimeService::Control通过 SSE 事件ask_user_requested通知前端,前端通过新增的 HTTP 端点回传答案。数据流
改动清单
libs/core/include/merak/execution.hppawait_ask_user()虚方法 + NullRunControl 默认实现libs/runtime/include/merak/runtime_service.hpprespond_to_ask_user()声明libs/runtime/src/runtime_service.cpplibs/http/src/http_server.cppPOST /v1/runs/{id}/ask-response端点libs/loop/src/agent_loop.cpplibs/tools/include/merak/ask_user_tool.hpplibs/tools/src/ask_user_tool.cppcli/src/main.cpp前端待办
WebUI 需要监听
ask_user_requestedSSE 事件并调用POST /v1/runs/{id}/ask-response完成闭环。