# 新消息原子取消待答卡片
# 目标
当 ask_user 卡片仍待回答时,用户直接在底部输入框发送新消息,应以该新消息为准,不允许旧卡片和新任务同时占用同一会话。
# 实现
WebMain.chat在该会话既有锁中,先检查AgentState.pendingInteraction。- 若存在待答卡片,按严格顺序完成:
- 追加原
askuser的ToolResultMessage,标记cancelled/newuser_message; - 清除
agent-state.json中的 pending; - 记录 trace,并通过 SSE 发送
interaction_cancelled; - 才追加新的
UserMessage并运行新的 AgentLoop。 - 前端点击发送时立即移除活动卡片;SSE 到达后在执行流中显示“已因发送新消息取消上一个待答问题”。
# 语义
这是原子完成,不是仅隐藏页面组件。即使页面刷新、重连或随后读取历史,旧 ask_user 也已有匹配的取消 ToolResult,不会形成悬空 tool call。
# 边界
- 同时提交卡片和发送新消息时,以先取得会话锁的一方为准;另一方会得到“追问不存在或已过期”或继续新会话状态。
- 该策略只处理
ask_user待答状态,不改变命令审批的 allow/deny 流程。
# 验证
mvn -pl pi-agent-v1 clean test通过。web/下执行npm run build通过。- 使用隔离 Mock 服务验证:首条消息产生
userinputrequired;第二条消息先返回interactioncancelled,随后开始新的 Agent 运行;历史顺序为原 user、askusertoolCall、取消 ToolResult、新 user、新 assistant 回复。
# 启动脚本修正
start-mac.sh原本已能识别并向本项目的 Java/Vite 监听进程发送终止信号,但没有等待端口释放,可能马上触发Address already in use。- 现在会等待最多 3 秒;超时仅强制结束已按命令行确认属于本项目的 PID,随后再次确认端口空闲才启动。