ASTER CODE / 构建终端智能体
12 · 资源收尾与工程验收
为跨工具资源选择寿命,补充重试和中文边界测试,再按故障场景验收终端智能体。
观察关闭过程
第三章在 Ctrl+C 后退出界面并关闭会话。接入真实工具后,关闭可能还需要取消原运行、结束确认、释放监听器和保存状态。界面应区分“请求停止”“等待收尾”“保存完成”和“收尾失败”。
继续消费事件,等待原 Run 的终态和工作线程结果。需要在退出前等待原执行权释放时,使用第六章的 cancel_and_settle。给等待设置期限。返回 false 时保留失败原因,不能删除原运行后声称安全退出。
终端恢复与运行成功是不同结论。无论请求成功与否,都要恢复 raw mode。清理失败、取消和验证失败需要保留在运行结果中。
工具资源的清理责任
假设后续增加一个预览服务器工具,后续调用还要访问它。监听器若只保存在工具函数局部变量中,会在返回时提前关闭。若随意放进全局变量,则难以确定释放任务。
| 需求 | 注册位置 | 清理时机 |
|---|---|---|
| 只服务本轮模型回复产生的工具调用 | ToolContext::register_capability_effect | 这些工具调用全部结束后 |
| 后续工具轮次还要继续使用 | ToolContext::register_run_capability_effect | 原 Run 收尾时 |
| 跨会话共享的宿主连接 | 宿主自己管理 | 最后一个所有者退出,按宿主规则释放 |
先注册清理责任,再获取资源。Run 级注册需要有效的 Agent Turn。普通宿主直调上下文或已经结束的 Turn 不能补注册。注册不授予访问权限,后续操作也不能保留旧上下文继续使用。
进程崩溃后的外部资源需要另外设计租约、过期或核实流程。关闭本地句柄不会撤销已经发给外部服务的写入。
界面状态测试
把下面测试放在第三章 ui.rs 末尾的测试模块里。第一项检查同轮次重试不会重复拼接,第二项检查显示截断不切断中文字符:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn retry_replaces_provisional_text() {
let mut app = App::default();
app.apply(AgentEvent::TurnStart { turn: 1 });
app.apply(AgentEvent::TextDelta { text: "旧的半段回复".into() });
app.apply(AgentEvent::TurnStart { turn: 1 });
app.apply(AgentEvent::TextDelta { text: "重新生成".into() });
assert_eq!(app.reply, "重新生成");
}
#[test]
fn display_limit_preserves_utf8() {
let mut text = "x".repeat(131_071);
append_bounded(&mut text, "中文");
assert_eq!(text.len(), 131_071);
assert!(!text.ends_with('中'));
}
}
再给输入、确认和事件处理分别准备无网络测试。模型用固定事件替身,工具用临时目录和可核对的计数;不要让每次 cargo test 都调用真实供应商。真实模型、MCP 和平台沙箱另做目标环境验证。
按完整任务链验收
| 场景 | 通过条件 |
|---|---|
| 只读解释项目 | 没有修改,回复与实际项目一致 |
| 拒绝一次写入 | 没有执行开始,也没有磁盘副作用 |
| 批准修改并运行测试 | 回执、摘要、覆盖范围和报告能对应 |
| 测试失败或报告过期 | 保留失败,不能显示 Verified |
| 中文与长代码输出 | 没有损坏字符,可滚动,达到显示上限有明确提示 |
| 运行中取消并立即再次发送 | 原运行未退出前,下一次提交被阻止 |
| 退出后恢复 | 工作区、策略和数据绑定匹配,原操作不会重复执行 |
| 资源清理失败或超时 | 没有成功 End 或 Completed 结论 |
| 两个项目使用不同记忆范围 | 不能跨范围召回或恢复改绑 |
| 长期目标暂停、到期和无进展 | 停止续跑,保留累计历史与准确原因 |
工程边界检查
运行 cargo fmt --all -- --check 和练习包的测试,再检查目标终端的尺寸变化、粘贴、组合键及错误退出。不要在 raw mode 内把日志写到 stdout,也不要把确认参数、密钥和用户会话放进公共截图或构建产物。
将练习宿主改造成产品时,还需补充输入编辑、确认列表选择、凭证管理、目标平台沙箱和可操作的错误页面。验收应逐项核对任务输入、受控执行、验证对应关系、身份保存和资源收尾。