- session.* 传输暴露:新增 gateway_api 蓝图(list/create/history),RuntimeService 补 create_session - host Bearer 通道:gateway_auth 双通道认证(host 模式+回环限定,token 存 DATA_DIR/host_api_token),tasks/approval 路由接入 - api_v1 会话路由转调公共入口消双轨,会话索引/列表补齐 run_mode/model_key/custom_prompt_name/personalization_name - flask 包依赖拆解:_flask_bridge 延迟桥接 + context 子包 PEP 562 懒加载,import server.tasks/runtime 不再拉起 flask - 审批链路:mark_expired 终态回写(超时/软停止/取消三路径)+ 终态 TTL 惰性清理(3600s) - 测试 patch 点随迁;全量 75 测试失败恰为 4 项存量,独立启动验收 4/4 全绿 Co-authored-by: Astrion powered by Kimi-K3 <astrion-agent@users.noreply.github.com>
37 KiB
Astrion Gateway 架构现状文档(修订版 v2)
生成日期:2026-09-07(同日经外部模型审阅修订;13 条批注 G1-G13 已消化进正文,消化对照见附录 §8.2)
本轮目标锚定(G1):以四层架构 + CLI/GUI/IDE 插件独立接入为目标。前期「先用定时任务验证公共入口」的路线适用于当时唯一明确的新调用方;现在优先级调整为:Gateway 独立启动 → 公共协议与多客户端交互闭环 → 正式客户端接入;定时任务随后接入该边界(见 §7)。
定位:回答一个问题——对照四层架构愿景,当前代码实际做到哪一步、差距在哪、通往「完整 Gateway」还剩哪些工作。 本文只做现状盘点与路线规划,不做实现。
信息来源(三方交叉验证):
- 愿景文档:
.astrion/user_upload/Astrion_Architecture_Product_Roadmap_Review_1.md(§10-15、§16-18、§35-38、§41-43)- 契约与研究:
docs/runtime_contract.md、cache_research/gateway/(work_plan / phase12_implementation_plan / eval_summary + 四份子报告)- 2026-09-07 当日三份只读代码核查(全文见附录 §8.1):
audit_entry_points_v2/entry_points_audit.md(任务入口收敛核查)audit_state_ownership_v2/state_ownership_audit.md(状态责任表 S1-S10 落地核查)audit_research_summary_v2/research_summary.md(既有研究汇总 + G1-G18 遗留全集)- 当日实测:改造相关测试复跑 25/25 全绿(unittest 方式);
git log确认改动已提交;G4 依赖链论断经主智能体亲自复验(§3.3)。
1. 愿景参照系
1.1 四层目标架构(§10.1 / §43 合并)
┌──────────────────────────────────────────────┐
│ Client Layer │
│ Web / Desktop / CLI/TUI / IDE / Android / SDK
└──────────────────────┬───────────────────────┘
│ Stable Runtime Protocol
┌──────────────────────▼───────────────────────┐
│ Gateway │
│ identity/auth · session ownership · run/task
│ lifecycle · routing · approval routing ·
│ event stream · reconnect/persistence · policy
└──────────────────────┬───────────────────────┘
│ Runtime Internal API
┌──────────────────────▼───────────────────────┐
│ Agent Runtime │
│ agent loop · context/compaction · workflow ·
│ sub-agent/AgentSession · memory · tool planning
└──────────────────────┬───────────────────────┘
│ Execution Contract
┌──────────────────────▼───────────────────────┐
│ Execution Plane │
│ Host Sandbox / Docker / Remote Worker / │
│ Browser / Tool Broker │
└──────────────────────────────────────────────┘
1.2 四层职责划分(G2 澄清)
| 层 | 职责 |
|---|---|
| 前端 | 输入、展示、状态投影 |
| Gateway | 身份与资源授权、会话管理、Run 受理与可查询生命周期、审批裁决、订阅与恢复 |
| Agent Runtime | 模型循环、上下文、工作流、子智能体编排、工具调用决策;向 Gateway 报告执行进展 |
| 执行环境 | 具体工具执行,落实路径/网络/沙箱限制,返回结构化结果与取消结果 |
层间接口:Gateway↔Runtime 使用明确的执行上下文、事件输出与交互接口;Runtime↔执行环境使用 Execution Contract。Gateway 可以内部委托多个 manager 管理状态——无需把所有数据放进一个大类,也无需将四层拆成四个进程。
1.3 关键设计原则(Roadmap 原文立场)
| 原则 | 出处 | 要点 |
|---|---|---|
| 逻辑边界先行,不拆微服务 | §11 | 先做进程内 RuntimeService 类边界,Flask 只是 Adapter;先稳定 contract,再决定 deployment topology |
| Transport 与 Protocol 分离 | §13 | 协议语义同一,传输按通道裁剪(HTTP/WS、stdio/socket 均可承载);客户端只理解稳定 protocol,不理解 Agent 内部实现 |
| State 只有一个 Owner | §14 | Gateway owns session/run/approval/event history/task state;Clients 只是 state projection |
| 去 Flask 化语义(≠不用 Flask) | §37 | 依赖方向单向:Flask → Gateway Service → Runtime Service → Core/Modules;禁止反向 import 读 request/cookie |
| 正式 Runtime Contract 文档 | §38 | 先定义 Entities/Commands/Events,再选传输 |
| 验收标准:Phase B | §41 | 见本文 §4.2 逐项对照 |
1.4 协议原语:现有基础与真实缺口(G3 口径)
Roadmap §12 的四个原语与当前实现的映射:
| 原语 | 当前基础 | 真实缺口 |
|---|---|---|
| Session(长期会话) | conversation 已有(id/user/workspace/metadata/持久化 JSON) | 公共契约中的字段子集与生命周期语义未定义 |
| Turn(一轮执行) | Run/task 已有(TaskRecord,pending/running/终态) | 未采用 Turn 命名本身不是架构缺口;真正要做的是主 Run、子智能体任务、后台执行的映射关系明确,不能只按名称合并 |
| Item(UI 可见事件统一单元) | 事件类型已事实存在(assistant/tool_call/approval...) | Item 的稳定标识、内容更新与生命周期(started/delta/completed)未定义;应逐步适配现有事件,避免同时重写所有前端渲染 |
| Event(Server→Client 通知) | task 级 idx/offset 协议 + socket 推送已有 | 序号作用域、事件覆盖范围、授权订阅、缺口检测、快照水位与续传衔接未定义(详见 §7 第 3 步) |
公共协议还需明确(当前均未定义):Commands、Queries、Events、授权范围、错误码、请求重试与兼容版本策略——不能只列实体字段。
2. 当前进度总览
2.1 三阶段路线状态(gateway_work_plan.md,2026-09-07 修订版)
| 阶段 | 目标 | 状态 | 证据 |
|---|---|---|---|
| 阶段一 · 固定契约 | 状态责任表 + RuntimeService 契约 + 回归用例 | ✅ 完成 | docs/runtime_contract.md(143 行) |
| 阶段二 · 公共任务入口 | RuntimeContext + RuntimeService + 6 处调用方迁移 + 拆 Flask 桥 | ✅ 完成(但见 §3.3 的边界收窄) | server/runtime/ 包;commit 652c1606 |
| 阶段三 · 定时任务 | Schedule/Occurrence 实体 + 幂等/重叠/停机语义 + 持久化 | ⬜ 未做,本轮路线重排后后置(§7.6) | 无任何调度器代码 |
提交状态:阶段一/二改动已提交(652c1606,前置 7d290d17/6e043389,后续还有 9a17b381/c80bc4fb/b4deee0f 三个修复)。
测试现状:改造相关测试 25/25 全绿(当日 unittest 复跑;项目 .venv 无 pytest)。构成:test_server_refactor_smoke(6) + test_runtime_service(10) + test_conversation_model_persistence(4) + test_runtime_identity_resources(4) + 新增 1 例。存量失败 4 项与本次改造无关。
测试覆盖口径警示(G13):test_runtime_service.py:117-118 将 task_manager._run_chat_task 替换为空 lambda(线程即刻结束)——入口测试绕过了真实执行装配,不能以这类测试通过认定边界完成;后续验收必须覆盖真实执行装配与生命周期。
2.2 范围评估的关键数字(eval_summary,经 R1-R6 审阅修订)
- 全部 Flask 端点 196 个:必须迁移的 16 个(8.2%) = T1 任务受理 3 + T2 任务控制 13;其余 180 个(观察/CRUD/状态/认证)不需要迁移。
- 16 个端点复杂度:12 小 / 3 中 / 1 大(唯一大项 = workflow activate)。
- 四支撑链路评估:事件/取消/保存可直接复用(需适配层),审批链路需改造。
- 口径警示(G6):16 个端点是「任务受理/控制」的范围估算,不是多端独立接入所需的公共能力范围上限(见 §4.3)。
3. 已实现清单(阶段一/二交付物)
3.1 契约层(阶段一)
docs/runtime_contract.md:概念对齐(Session=conversation / Run=一轮主任务 / Event=task events 条目);状态责任表 S1-S10;已有正确性保障 6 项;RuntimeService 契约;调用方迁移表;回归用例 T01-T12。
3.2 入口层(阶段二,当日核查验证)
server/runtime/包(新):context.py(197 行):RuntimeContext 三层模型——TrustedPrincipal(只能由适配层认证后构造)/TaskParams/InternalDirectives(普通客户端不可提交);不 import flask。service.py(114 行):RuntimeService无状态薄层——create_task / cancel_task / guidance 与 pending 队列×4 / get_task / get_task_events;进程级单例;不持有任务状态。
- 入口收敛(当日验证,声明属实):
- 全部 6 处任务创建调用点已迁移到
runtime_service.create_task(ctx):server/tasks/api.py:220、server/api_v1.py:335、server/workflow_runtime_api.py:192/:269、server/chat_flow_task_main.py:618/:1417。 - 无漏网调用点:
create_chat_task实体调用全仓仅 2 处 = 定义models.py:128+ 委托service.py:38。 create_chat_task强制显式 RuntimeContext,缺失抛 ValueError;2026-09-08 已拆除 session_data 兼容桥:TaskRecord 三层结构化直存(principal/task_params/directives+ 可变goal_progress),to_session_data()已删除,全库生产代码无 session_data dict 残留。
- 全部 6 处任务创建调用点已迁移到
- 执行链运行期解耦(当日验证属实):
_run_chat_task不再建立test_request_context,任务线程全程RuntimeIdentity驱动(server/context/identity.py);server/core/modules/utils 下test_request_context实体调用 = 0;models.py无session[读取。 - 依赖方向(结论收窄,见 §3.3):
server/context.py(989 行)已拆分为server/context/子包;get_user_resources已参数化(RuntimeIdentity 显式身份快照)。「符合单向依赖」的结论仅适用于「任务所需运行期上下文已显式化」这一层。 - 审批超时透传管道:terminal
_approval_timeout_seconds→ 工具循环_approval_timeout_for()→ 4 个_wait_*调用点(默认 3600s 语义不变)。
3.3 独立启动缺口(G4,当日主智能体复验属实)
论断:移除 test_request_context ≠ 独立服务初始化与依赖解耦完成。运行期上下文已显式化,但模块加载期依赖仍锚定 Web 栈:
runtime_service.create_task()
→ from server.tasks import task_manager # service.py:35 等 8 处延迟导入
→ server/tasks/__init__.py:3 # from flask import Blueprint;创建 tasks_bp;级联 import 路由模块
→ server/tasks/models.py:15 # from server.chat_flow import run_chat_task_sync
→ server/chat_flow.py:19/55/73 # 导入 Flask(request/session)、认证辅助、socketio
后果:任何无 Web 的进程想使用 RuntimeService,import 时仍会拉起整条 Flask/SocketIO 依赖链——「不启动 Web 应用、独立初始化 Gateway/Runtime」目前做不到。
下一步方向:抽出不依赖 Web 应用初始化的服务装配入口,显式注入资源解析、事件输出及交互接口;Web 适配层继续使用 Flask。不能用「整仓 Flask 关键词零命中」代替边界验收;验收标准 = 真实服务在无 Flask 环境中完成初始化与任务生命周期(§7.2)。
4. 达成度矩阵(核心差距)
4.1 四层逐层对照(G5 口径修正)
| 层 | Roadmap 要求 | 现状 | 达成度 |
|---|---|---|---|
| Client Layer | Web/Desktop/CLI/IDE/Android/SDK | Web、Android WebView、React/Ink CLI 存在;CLI 仍是「Web API 消费者」(cli/src/api.ts:fetch 127.0.0.1:8091 + cookie/CSRF/hostLogin,并自启 python -m server.app) |
⚠️ 客户端存在,但全部消费 Web 专属业务流程 |
| Stable Runtime Protocol | Session/Turn/Item/Event 原语 + Commands/Events 契约 | 稳定公共契约不存在。已有基础:_append_event 已注入 task_id/conversation_id/workspace_id 并分配任务内 idx(models.py:757-782)。真正缺的:稳定公共契约、跨任务及非运行中状态变化的覆盖、可查询快照与同步规则 |
❌ 未开始(有可用基础) |
| Gateway | 状态唯一 Owner;可独立初始化 | 进程内公共入口已建立(RuntimeService + 状态责任表);但 import 依赖链仍耦合 Flask(§3.3),无法独立启动;状态持有仍分散在既有 manager(§5) | ⚠️ 入口收敛 ✅ / 独立初始化 ❌ |
| Agent Runtime | agent loop / context / workflow / sub-agent | 已存在且运行期请求上下文依赖已消除;但 §3.3 的模块依赖与输出耦合仍在,「达成」限定为进程内、Web 进程伴生形态 | ⚠️ 进程内达成 |
| Execution Plane | Host/Docker/Remote + 统一 Execution Contract | Host 沙箱(Seatbelt/bwrap/WSL2)+ Docker(非特权 uid + Landlock)已成熟;无统一 Execution Contract 抽象;Remote Worker 未做(P2) | ⚠️ 部分 |
口径说明(G5):薄入口、命名差异及端点数量不能直接折算成四层边界完成比例;本表「达成度」按各层职责(§1.2)能否独立履职衡量。
4.2 Phase B 验收清单逐项对照(§41)
| §41 Phase B 条目 | 状态 | 说明 |
|---|---|---|
| 定义 Session / Turn / Item / Event | ⚠️ 部分 | 概念对齐已做;Item 生命周期未定义;主 Run/子智能体/后台任务的映射未契约化 |
| 抽出 RuntimeService | ✅ | 已收敛全部 6 处入口(§3.2);独立启动未达成(§3.3) |
| Flask route 只做 adapter | ⚠️ 部分 | 任务受理/控制链路(16 端点)已是 adapter;其余 180 端点保持 Flask 直写(评估结论:不需要迁移);审批回答端点仍直调 manager(见 §4.3) |
| CLI 改为 Runtime Client 语义 | ❌ | 后置(§7.6) |
| 定义 event sequence / reconnect 模型 | ⚠️ 部分 | task 级 idx/offset + 前端对账去重已有;序号作用域/快照水位/续传衔接未定义 |
| 写 docs/runtime_protocol.md | ❌ | 现有 runtime_contract.md 是内部契约;协议文档(Entities/Commands/Events/错误码/版本)未写 |
| 为 protocol 生成 TS types | ❌ | 未做(启动条件:多客户端类型维护成实际成本) |
小结:7 项中 1 项完成、3 项部分、3 项未做。 「Web 与 CLI 使用同一套 Runtime contract,不需要知道彼此存在」尚未达到。
4.3 公共能力范围(G6)
「16 个端点」只是任务受理/控制的迁移估算。多端独立接入需要的公共能力应按客户端操作列清单,再确定所属服务:
工作区选择 · 会话创建/加载/历史 · 运行/取消/引导 · 审批与提问 · 模型及权限设置 · 必要附件能力 …
现状核查发现:审批回答(server/chat/approval.py)仍直接调用 manager,未经公共入口(契约 §4.2 明确审批回答不进 RuntimeService 首版)。旧 URL 可以保留,但这些业务能力不能要求新客户端复制 Web 路由内的装配与编排;与 Agent 使用无关的管理页面无需机械迁移。
5. 状态责任表 S1-S10 落地核查
全文见
audit_state_ownership_v2/state_ownership_audit.md。
| # | 状态 | 一致性 | 关键点 |
|---|---|---|---|
| S1 | 对话历史与元数据 | ✅ | merge-on-save + _io_lock + 原子替换 + 缩减拒绝(crud_mixin.py:252-358、base.py:47、index_mixin.py:104) |
| S2 | 任务记录 TaskRecord | ✅ | 唯一 TaskManager;chat 互斥 + notice 豁免(models.py:158-173);纯内存 |
| S3 | 任务事件流 | ✅ | deque maxlen=20000、idx 单调、offset 续读(models.py:74/757-782/200-206);纯内存 |
| S4 | 主任务门闸 | ⚠️ 基本一致 | 唯一入口/finally 释放/token 移交/失败回滚全部命中;疑点 N1:异常回退路径(chat_flow_task_main.py:644-690 直跑 handle_task_with_sender)自身不释放门闸且无任务线程,回退场景门闸可能长期占用(静态推断,待复现) |
| S5 | 停止标志 | ✅ | server/state.py:38 模块级 dict;REST 硬取消 vs socket 软标志;任务级键隔离;无锁全局可变(进程内依赖事件循环+线程隔离) |
| S6 | 审批/提问条目 | ✅(含缺口证实) | 三个内存 manager + 锁内单次裁决;契约 §6 四个缺口全部证实:超时不回写终态 / 无 TTL / task_id 恒 None(静态证实:WebTerminal 全仓无赋值点) / socket 软 stop 不打断等待(大概率) |
| S7 | 对话级 terminal | ✅ | 三段 key(resources.py:52-54);回收器 24h + 实例身份校验(reaper.py:40/92-130) |
| S8 | 权限模式/执行环境 | ✅ | 运行中入队由工具循环消费(permission.py + main_terminal.py:325-376 + chat_flow_tool_loop.py:1544) |
| S9 | 多智能体实例状态 | ✅ | GLOBAL_MULTI_AGENT_STATES 进程级单例 + RLock + 快照 + 终态校准(multi_agent/state.py:668/671、sub_agent/state.py:104-133) |
| S10 | 用户偏好 | ⚠️ 基本一致 | 新发现偏差:save_personalization_config 直接覆写 open(path,"w"),非原子写(personalization_manager.py:851-856) |
契约 §3 六项正确性保障:代码中全部找到对应实现(第 6 项附 N1 疑点)。
5.1 关键判断:归属、共享、恢复是三件事(G7 口径改写)
v1 原文把「内存态」直接判为「状态唯一 Owner 的障碍」,混淆了三个不同问题,现拆开:
- 状态归属(谁是权威):进程内达成度较高——每类状态基本都有唯一 owner 与互斥(9/10 一致或基本一致)。✅
- 多客户端共享(§14 场景:CLI 发起、GUI 审批):只需两个客户端连接同一个 Gateway 实例,内存中的任务与审批即可共享。Gateway 是统一管理边界,内部可继续由 TaskManager、审批 manager、会话存储各自持有状态;关键是授权、写入和裁决路径统一。内存态不构成此场景的障碍。
- 跨重启恢复:这才是内存态(S2/S3/S6)真正限制的能力——重启后任务记录/事件流/审批条目即失。是否补齐由跨重启查询/审计需求决定(持久化被列为后续独立决策),不能单凭未落盘判定「无唯一 Owner」。
锁、原子写和丢更新风险应按真实写入并发分别处理(S5 无锁、S10 非原子写属此类,见 §6);持久化本身也不会自动解决这些问题。
6. 已知缺口与遗留待办
6.1 必须先闭环的疑点
| # | 事项 | 口径(G8 修正后) | 来源 |
|---|---|---|---|
| N1 | S4 异常回退路径门闸释放 | 保持待复现:不能仅因回退函数自身没有 release 就判定泄漏;验证应覆盖预占→受理失败→回退执行→最终释放全链路 | 当日 S4 核查 |
| N2 | 审批条目 task_id 恒 None | 静态证实。修复方向:在审批创建处显式传入当前 Run 上下文;不宜把「给会话级 terminal 加 task_id」直接确定为方案——若沿用可变属性,必须处理通知任务重叠、作用域恢复和清理。审批/计划确认/用户提问需保持各自语义,并补齐超时/取消终态与迟到回答规则 | 当日 S6 核查 + G2 |
| N3 | 真实运行环境验证未做 | Web 聊天/停止/审批/workflow 激活/多智能体派发需重启服务后人工完成;get_user_resources 分支选错会静默串工作区(最高风险点) |
G1 |
| N4 | 并发重复任务记录 | models.py:157「检查运行中→创建记录」与门闸分属两处,并发下是否产生重复任务记录未验证 |
G7①/G10 |
| N5 | issue_socket_token 发放竞争 |
未复现;若存在作为独立小缺陷处理 | G7② |
实施状态(2026-09-07 第 0-4 步完成后):N1 ✅已修复(回退路径 finally 释放,
chat_flow_task_main.py);N2 ✅已修复(审批创建处显式task_id=client_sid,chat_flow_tool_loop.py4 处 +_handle_submit_plan);N3 ⬜仍待用户重启服务后人工验证(清单见 §7.1);N4/N5 保持原口径未动;S10 ✅已修复(save_personalization_config改用公共atomic_write_json)。另修复两处盘点后新发现:执行链 4 处裸socketio.emit(未绑定抛 AttributeError;task_stopped曾因异常顺序跳过事件流记录,已改为先写事件流再推送);chat 任务无 cid 时服务层补建对话(RuntimeService._ensure_conversation_for_chat,自tasks/api.py下沉)。
6.2 结构性缺口
- 跨重启恢复能力:S2/S3/S6 纯内存态,重启即失;S6 条目永不清理(无 TTL)。TTL 应在终态与迟到回答规则明确后设计,不能直接删除仍合法等待的请求(G11)。
- 审批链路四个缺口:超时不回写终态 / 无 TTL / task_id 恒 None(=N2)/ socket 软 stop 不打断等待(REST 硬取消可打断);超时语义(拒绝当前工具继续 vs 结束任务)是产品决策未定,R5 明确其不是定时任务的技术前提。
- S10 personalization 非原子写:原子替换可防写中断损坏;但读改写并发的丢更新风险需另行判断(G8)。
- 独立启动缺口:§3.3 的 import 依赖链(G4)。
- 事件前台干扰:定时任务事件会推给在线用户 socket 房间,需 source 字段或产品确认(G13-old)。
- 异常回退路径绕过 TaskRecord 登记:无事件 deque、不可按 task_id 轮询/取消(G14-old)。
- 阶段三定时任务未做:详细设计要求见 work_plan §4(research_summary.md §1 全量保留);本轮路线重排后后置(§7.6)。
- 后续独立决策(有明确需求再启动):SSE/WS 传输替换、对话级订阅、durable 事件与快照恢复、审批持久化、TS/SDK 生成、身份体系整理(不能直接合并 Web/API 用户数据空间)、设备配对/Remote Worker。
- 存量测试失败 4 项(与改造无关,未修)。
7. 后续路线(按 G9 重排为五步 + 前置第 0 步)
总原则:协议草案与接口适配可迭代推进;每一步保留现有门闸、保存和恢复保障;四层不要求四进程(G13);Remote Worker 不是本轮完成条件。
实施状态速览(2026-09-07,三档口径:接口存在 / 适配完成 / 行为验收):
能力 接口存在 适配完成(既有入口转调) 行为验收 run.start / cancel / guide / queue ✅ ✅(tasks/api.py、api_v1.py 全部转调) ✅ chain 双客户端 + lifecycle run.get / run.events(含 window_start) ✅ ✅(HTTP 轮询透传水位) ✅ offset/水位断言 + 客户端缺口处理(2026-09-08:Web 检测后发 event_window_gap→ 会话快照对账;CLI 提示并对齐窗口续读)run.list(发现,审核 F1) ✅ ✅(/api/tasks 列表、running-status、api_v1 删除保护转调) ✅ B 发现 A 的活动 Run 并取消 approval.list / resolve ✅ ✅(chat/approval.py 三类六个路由转调) ✅ 等待→批准→继续(approval_wait) session.list / history(principal 用户+工作区双校验,F3) ✅ ✅(2026-09-08:新增 server/gateway_api.py GET/POST /api/runtime/sessions+GET .../history传输暴露;api_v1 两会话路由转调公共入口消双轨,载荷字段经索引补字段保持兼容)✅ 含越权/跨工作区拒绝断言 通道认证(host Bearer token) ✅(2026-09-08:server/gateway_auth.py;host 模式+回环限定,token 存 <DATA_DIR>/host_api_token0600)✅(gateway_api 3 路由 + tasks/api.py 9 路由 + chat/approval.py 6 路由均支持双通道) ⬜ 待真实环境验证 Gateway 独立初始化 — — ✅ 子进程隔离(ASTRION_IGNORE_DOTENV 逃生门 + 假模型自包含 + 装配证据断言,F4) ExecutionBackend 替身(E1-E4) ✅ —(默认 None,生产路径不变) ✅ fake_exec ③↔④ 全量贯通(Host/Docker 迁入、E5-E10) ⬜ ⬜ ⬜ 后置(§7.5-补) 审核收口记录(gateway_implementation_review_2026-09-07.md):F1 已补 run.list 公共发现入口;F2 已完成 15+ 处路由转调(tasks/api.py 7、api_v1.py 3、chat/approval.py 6 + 载荷序列化收敛至 models.py 单一实现,死导入清零);F3 已补 principal 工作区一致性校验;F4 已修(config .env 逃生门 + 测试自包含 + 假通过修复 + 审批等待链)。审核 §4 契约注释误导已修正(execution_plane/base.py:命令校验/路径授权仍在旧链路,真实后端接入时必须保留)。
第一档+第二档收尾(2026-09-08 实施):
- flask 包依赖拆解(G4 收口):新增
server/context/_flask_bridge.py(延迟桥接 has_request_context/session_get/session_set,flask 缺失按无上下文处理);identity/resources/conversation/personalization 四子模块顶层 flask+auth_helpers 依赖全拆;server/context/__init__.py改 PEP 562 懒加载;chat_flow.py 清理死导入。实测:import server.tasks/import server.runtime不再拉起 flask/flask_socketio/auth_helpers/chat_flow(venv 验证)。剩余形态:任务执行阶段(_run_chat_task 线程内延迟导入 chat_flow → security/extensions)仍拉起 flask+flask_socketio(SocketIO 空壳实例不 init_app),执行层彻底脱 flask 属更大工程,本轮未动。- 审批链路三缺口收口:三个 manager 新增
mark_expired(幂等)+ 终态 TTL 惰性清理(RESOLVED_TTL_SECONDS=3600,pending 永不自动清理);三个 wait* 等待函数超时/软停止(stop_check 注入)/协程取消(CancelledError)三路径均回写 expired 终态;软停止打断对齐 REST 硬取消。i18n 新增 approval_stopped/approval_expired/question_stopped/question_expired 四键。- 测试 patch 点随迁:test_conversation_model_persistence(session→session_get/session_set)、test_runtime_identity_resources(get_current_user_→get_current_user wrapper)。全量 75 测试失败恰为 4 项存量(与改造无关)。
- 存量索引兼容注记:会话列表 items 新增 run_mode/model_key/custom_prompt_name/personalization_name 字段(索引两个写入点同步补齐);存量索引条目在对话下次更新前这两个新字段为 None。
本轮收口决策(2026-09-07 用户拍板):①②③ 链路(Client ↔ Gateway ↔ Runtime)贯通即为本轮终点;③↔④ 全量贯通(Host/Docker 迁入 ExecutionBackend 契约、E5-E10 纳入)后置为独立工作,期间默认路径
execution_backend=None(现有真实链路不变)。②↔③ 内部形态结构化(2026-09-08):
to_session_data()兼容桥已拆除——create_chat_task签名改为收RuntimeContext必填,TaskRecord三层结构化直存(principal/task_params/directives+ 可变goal_progress字段);_run_chat_task身份还原/门闸认领/事件注入/terminal 属性设置全部改为按层属性访问;to_session_data()方法删除,生产代码 session_data dict 零残留。验证:75 测试全量回归失败恰为 4 项存量。
7.1 第 0 步:闭环疑点与小修复(不依赖架构决策)
- 复现验证 N1(回退路径门闸,覆盖预占/受理失败/回退执行/最终释放全链路)。
- 修复 N2:审批创建处显式传入当前 Run 上下文(方案比选后实施,见 §6.1)。
- 修复 S10:
save_personalization_config改用原子替换写。 - 完成 N3 真实环境验证清单。
7.2 第 1 步:独立服务启动(Gateway 可脱离 Web 初始化)
- 拆解 §3.3 的 import 依赖链:
server/tasks/__init__.py的 Blueprint 创建与级联路由 import、models.py → chat_flow的静态引用。 - 抽出不依赖 Web 应用初始化的服务装配入口,显式注入资源解析、事件输出与交互接口;Web 适配层继续用 Flask。
- 验收:不启动 Web 应用也能创建会话、运行受控任务、查询并取消——以真实执行装配验证,不接受替换执行线程的替身测试(G13)。
7.3 第 2 步:完整公共协议 + 极简客户端验收
- 写
docs/runtime_protocol.md(§38):Entities/Commands/Queries/Events + 授权范围、错误码、请求重试、兼容版本策略(G3)。 - 能力清单按客户端操作划分(§4.3),审批回答等直调 manager 的路径纳入公共入口。
- 用非 Web 的极简测试客户端提前参与验收(G12):验证 工作区→会话→运行→审批/提问→停止→历史 全链路。
- 传输选择(G12):HTTP 可以承载公共 Gateway 协议,本地 socket 也可以——摆脱的是旧 Web 专属的登录、会话装配及路由业务流程,不是 HTTP 这个传输。新客户端不依赖 Web Cookie/CSRF/hostLogin,但必须经过适合通道的认证与资源授权,不能自报可信身份或内部门闸 token。采用 stdio 时须区分连接适配器与服务实例——不能让每个客户端各启动一份独立状态的 Runtime 却宣称共享 Gateway。跨凭证访问同一资源需明确身份映射,不直接合并现有 Web/API 数据空间。
7.4 第 3 步:多客户端共享与恢复
- 场景验收:A 发起、B 查询并操作;A 断开不结束任务;重连后状态一致。
- 事件模型定义(G10):先定义序号作用域(会话或其他明确作用域即可,不要求跨所有用户/会话的全局总序)、事件覆盖、授权订阅、缺口检测、快照水位与续传衔接;保留现有任务 idx 时,须区分它与连接序号及其他游标的含义,并定义窗口过期后的重新同步规则。
- 重启语义三场景分开(G11):客户端断开 ≠ Gateway 重启 ≠ 原执行继续。多端接入首先要求任务独立于连接;Gateway 重启后旧 Run 的查询与失效规则须明确;若保留旧 Run 记录,恢复为中断/待核验等明确状态,不无依据宣告成功、不自动重做可能已有副作用的动作。持久化 pending 审批不会重建原执行线程;只有另行实现待执行动作恢复、权限重校验及结果对账后,才能承诺重启续跑。
- 持久化范围由跨重启查询/审计需求决定;当前内容快照与已提交生命周期记录可分别设计,live delta 无需默认全部持久化;实现仍须遵守原 work plan 的一致提交、快照水位、裁剪与恢复规则。
7.5 第 4 步:Runtime 与执行环境分层
- 定义 Execution Contract:相同 Runtime 可接测试执行器(替身)及现有 Host/Docker 实现;执行链无需了解 Web 会话与客户端连接。
- 验收:Runtime + 替身执行器可独立测试;Host/Docker 后端经同一契约接入。
7.5-补 ③↔④ 全量贯通工作分解(2026-09-07 定,后置独立工作)
首版已完成:契约文档 + ExecutionBackend 协议(E1-E4)+ 替身执行器 + 接入点 (
MainTerminal.execution_backend,默认 None)。以下为「Host/Docker 迁入契约」的四件事:
- 接口面补全 E5-E10:文件读三模式 / 文件 CRUD 族 / 持久终端 6 操作 / path_validate / 执行环境快照 / 命令校验。照搬现状语义(返回结构、截断、错误形态),不发明新能力。主改
modules/execution_plane/base.py。 - 真实适配器 HostDockerBackend:新实现类内部委托现有 terminal_ops / file_manager / terminal_manager / background_command_manager。决策点:薄适配(纯转发,快、风险小,4 处后端选择复制的结构债留着)vs 厚适配(顺手收敛 terminal_ops/run.py、background_command_manager.py、persistent_terminal/start.py、container_file_proxy.py 的后端选择逻辑,根治但动四个核心执行文件)。既定方向:先薄适配。
- 编排层全面切换:tools_execution.py 给 E5-E10 分支插 backend 注入(约 6-10 处);默认装配由 None 改为 HostDockerBackend 实例。风险点是行为等价:权限裁决/先读后写/浅备份/编辑摘要/字符截断留在编排层,执行细节归后端,边界必须切干净。
- 验收:替身测试保持绿 + 全量回归 + N3 真实环境人工验证一并做。
完成后收益:Runtime 对执行环境零直接依赖;换后端(Remote Worker、子智能体独立沙箱)只需换实现,不碰智能体循环。
7.6 第 5 步:正式客户端接入 + 定时任务后置接入
- Web 与正式 CLI/GUI/IDE 接入同一业务服务与协议。
- 定时任务(原阶段三)后置接入该边界,不作为公共协议建设的前置条件(G9)——按 work_plan §4 设计实施(幂等/重叠/停机/审批超时/持久化选型)。
7.7 本轮 Gateway 化的完成判据(G13,行为验收)
- 新客户端通过公开承诺的协议能力完成 Agent 使用全流程,无需复刻 Web 启动逻辑。
- Web 与其他端对同一会话/Run/审批状态一致。
- 断连不终止已受理任务;重连与 Gateway 重启分别有明确处理规则。
- 所有任务来源遵守统一受理、取消、授权、保存及事件规则。
- Gateway 可独立初始化;Runtime 与执行环境可通过替身独立测试。
- 测试必须覆盖真实执行装配与生命周期——不能以替换整个执行线程后的入口测试通过认定完成。
7.8 不在路线内(Roadmap §42 明确反对)
- 拆微服务 / 引入 K8s;重写前后端;每个 sub-agent 独立进程;把四档权限 UI 改成 policy DSL 暴露给普通用户。
8. 附录
8.1 本次核查产物索引
| 产物 | 路径 |
|---|---|
| 任务入口收敛核查(6 处迁移点 + 漏网扫描 + Flask 拆桥) | cache_research/gateway/audit_entry_points_v2/entry_points_audit.md |
| 状态责任表 S1-S10 落地核查(含 N1/N2/S10 新发现) | cache_research/gateway/audit_state_ownership_v2/state_ownership_audit.md |
| 既有研究汇总(三阶段要点 / R1-R6 / 早期盘点修正对照 / G1-G18 遗留全集 / 外部借鉴) | cache_research/gateway/audit_research_summary_v2/research_summary.md |
| 内部契约 | docs/runtime_contract.md |
| 三阶段工作计划 | cache_research/gateway/gateway_work_plan.md |
| 阶段一/二实施与验收记录 | cache_research/gateway/phase12_implementation_plan.md |
8.2 审阅批注消化对照表(G1-G13 → 本版落点)
| 批注 | 核心意见 | 本版落点 |
|---|---|---|
| G1 本轮目标 | 目标重锚为四层+多端独立接入,优先级调整 | 文首锚定 + §7 全线重排 |
| G2 四层职责 | 四层职责明确划分;Gateway 内部可委托多 manager | §1.2 |
| G3 协议演进 | Turn 命名不是缺口;Item 逐步适配;协议需 Commands/Queries/Events/授权/错误码/重试/版本 | §1.4、§7.3 |
| G4 独立启动缺口 | import 依赖链仍耦合 Flask;运行期显式化 ≠ 加载期解耦 | §3.3(含复验证据)、§7.2 |
| G5 达成度口径 | _append_event 已注入关联字段;薄入口/命名/端点数不折算完成比例 | §4.1 |
| G6 公共能力范围 | 16 端点非能力上限;按客户端操作列能力清单;审批回答仍直调 manager | §4.3 |
| G7 Owner 与恢复分开 | 归属/共享/恢复三件事分开;内存态不构成多端共享障碍 | §5.1 |
| G8 缺陷验证口径 | N1 保持待复现;N2 修复走显式 Run 上下文;S10 丢更新另行判断 | §6.1、§6.2 |
| G9 路线重排 | 五步路线;定时任务后置 | §7 |
| G10 事件持久化边界 | 序号作用域先行;非全局总序;live delta 无需默认持久化 | §7.4 |
| G11 重启语义 | 断开/重启/执行继续三场景分开;持久化 pending ≠ 续跑;TTL 后设 | §7.4、§6.2 |
| G12 传输与客户端验证 | 摆脱 Web 专属流程而非 HTTP;stdio 防独立 Runtime 陷阱;极简客户端提前验收 | §7.3 |
| G13 完成判据 | 行为验收六条;测试须覆盖真实执行装配 | §7.7、§2.1 |
注:本文所有「文件:行号」证据为 2026-09-07 当日代码快照,后续变动以符号/函数名为准。