diff --git a/.astrion/memory/runtime_state_loading_concurrency_redesign.md b/.astrion/memory/runtime_state_loading_concurrency_redesign.md new file mode 100644 index 00000000..c55a2a6e --- /dev/null +++ b/.astrion/memory/runtime_state_loading_concurrency_redesign.md @@ -0,0 +1,40 @@ +--- +name: runtime_state_loading_concurrency_redesign +description: 当继续讨论/实现 conversation 级 WebTerminal 隔离(单对话单 terminal、同工作区多对话并行)、24h TTL 回收、子智能体按需加载、git worktree 时,应该索引本记忆 +--- + +# 运行状态对账 + Conversation 级 WebTerminal 隔离(全部已完成) + +> 2026-07-20 更新。完整实现记录见 `docs/conversation_level_terminal_design.md` §7(含文件级改动清单与验证结果)。 + +## 状态 +- 议题 1(运行状态 REST 对账):✅ 完成并验证。事件为主 + 2.5s 对账纠偏(`GET /api/conversations//running-status`,前端 `probe.ts` 单循环)。 +- 议题 4(conversation 级 WebTerminal 隔离):✅ 2026-07-20 完成并端到端验证。议题 2(子智能体按需加载)、议题 3(worktree)暂缓。 + +## 议题 4 核心架构(勿重新讨论,用户已拍板) +- terminal key = `username::workspace_id::conversation_id`(`server/context.py _make_terminal_key`);**container key 保持工作区级**(docker 一工作区一容器)。 +- `get_user_resources(..., conversation_id=None)` 可选参数;无对话上下文的 API(对话列表/api_v1/skills/conversation.py/socket connect)保持工作区级服务实例(shell 惰性)。 +- WebTerminal `_bound_conversation_id`,`_ensure_conversation` 加载绑定对话不 fallback;`last_activity_at` + 24h TTL 回收器(`reap_idle_conversation_terminals`,env `CONVERSATION_TERMINAL_TTL_SECONDS`)。 +- chat 互斥:同工作区 → 同对话(`tasks/models.py create_chat_task`,`_norm_cid` 比较)。 +- TerminalManager per 对话(每对话 max 3 终端、对话间分离);广播回调包装注入 conversation_id(`_wrap_callback_with_conversation_id`),前端 TerminalPanel `acceptTerminalBroadcast` 过滤 7 事件。 +- 前端 `currentWorkspaceHasRunningTask` 已改当前对话判定(名字未改,遗留更名)。 +- **行为变化**:SubAgentManager 按 `owner_conversation_id` 过滤恢复,重启后多智能体任务延迟到对话激活时恢复(工作区级 manager 不再恢复)。 + +## 验证资产 +- `_experiments/verify_conversation_level_terminal.py`(9 断言)、`_experiments/verify_running_status_api.py`。 +- 实测铁证:双对话并行 running、同对话 409、A 运行中 B 页面零锁定、终端 A/B 列表隔离、/api/terminals max_allowed=3。 + +## 边界修复轮次(commit 序列) +- `a4eb6888` 议题1+4 主体 → `1289c31d` 模型持久化四防线 → `6b5b1732` 二轮边界(压缩路由走对话级/回收器竞态防护/空cid补建对话)→ `e8bbaccf` idle 多智能体不算运行(对齐 socket 语义,防 REST 幽灵运行+回收器永久阻塞;idle 实例靠 restore_running_tasks 磁盘恢复兜底)。 +- 详见 `docs/conversation_level_terminal_design.md` §8/§9。 + +## 环境教训(2026-07-20 实测踩坑) +- **8092 端口是用户另一检出的服务**(cwd=`/Users/jojo/Desktop/外置/agents`),不是本仓库;打接口前必须 `lsof -nP -p | grep cwd` 确认进程归属。 +- 沙箱会拦 `kill`/`ps`(Operation not permitted),新服务在 socketio.run 绑端口时被杀;测服务相关改动优先进程内直调(如 `_experiments/test_reaper_unit.py` 19 断言)。 +- host 模式多实例共写同一 debug_stream.log 且启动即截断;import server.app 的测试脚本必须先设 `ASTRION_DATA_ROOT` 到 /tmp 隔离。 +- 短 TTL 回收实测(CONVERSATION_TERMINAL_TTL_SECONDS=120)尚未在真实服务验证,待用户下次自然重启服务后补测(单元测试已覆盖逻辑)。 + +## 遗留 +- 测试对话 conv_20260720_001402_595/857(语音工作区,A 内有 test-shell-a);张雪峰对话 conv_20260718_005231_752 有测试消息;conv_20260720_032131_953/032132_014(TTL 测试误建,在共享数据里,可删)。 +- 既有 bug 未修:assistant reasoning_content 前端渲染两遍(历史加载路径)。 +- 服务验证用 host-login 后必须重新 GET /api/csrf-token(login 会 force_new token);启动服务不要用 `| head` 管道(Broken pipe 杀任务)。