Fix/AGC上下文丢失问题 (#247)
Project CI / Repository checks (push) Successful in 3m1s
Project CI / Frontend tests (push) Successful in 3m27s
Project CI / Backend tests (push) Successful in 7m20s
Project CI / Native shell tests (push) Has been cancelled

权衡之后选择附加历史消息构造一个巨大的prompt
before:
```
1. user:  aabb
2. assistant: bbaa 这里codex崩溃了或者重启上下文丢失
```
after:
重启之后发送新消息abab
 codex看到:
```
user:  aabb
assistant: bbaa
这里崩溃了!
user: abab
```

移除了原来的"会话最后只有用户消息就自动重新发送用户消息"功能, 因为存在冲突: 现在的实现是每次用户手动发送新消息才做以上的步骤

before and after:
![shotmd-1788345830.jpg](/attachments/28549e4d-9913-459a-bae2-a195b8ee9e04)

Close #249

---------

Co-authored-by: 段舒康 <kdletters@qq.com>
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/247
Co-authored-by: 王德宇 <kvtodev@outlook.com>
Co-committed-by: 王德宇 <kvtodev@outlook.com>
This commit was merged in pull request #247.
This commit is contained in:
2026-09-03 19:30:21 +08:00
committed by 段舒康
parent 3e034d681d
commit 520b9344ef
9 changed files with 584 additions and 478 deletions
@@ -7612,6 +7612,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 配置:有无 AGC LLM Key 都只支持 `openai_responses`;非空 Key 映射后 base URL 与逐 Agent model/effort 生效,Key 只经专用环境变量;空 Key 只桥接用户 Codex `auth.json`,移除继承环境 Key。`stream=true` 复用现有 durable final-reply delta`webSearchEnabled=true``openai_chat / anthropic` 必须显式切换 `provider`,不得静默忽略已有 LLM 配置。
- 安全与恢复:app-server 使用隔离临时 `CODEX_HOME` 与 OS HOME,只桥接认证,不加载用户 MCP/config/skills/hooks;启动前关闭 web/multi-agent/shell/browser/plugin/image 等原生能力,固定 read-only、network off、never approvalAGC 是唯一 ToolHost。取消覆盖 turn-start 回包前窗口并只发送单 turn interrupt;已开始 turn 的连接/终态未知直接标记 reconciliation,明确 failed/interrupted 不自动重试。模式与 durable 指纹取同一配置快照。
- 资源与退出:pool 按实际凭据快照/base URL/API kind/CLI 版本和节点 run 身份隔离;空 AppData Key 只允许桥接一次性读取的有界 `auth.json` 快照,并用同一字节快照生成池指纹,宿主 `CODEX_API_KEY` 对 app-server 与一次性 CLI 都必须移除。节点进程与 thread 均有上限并只淘汰 inactive LRUstdout NDJSON 与 stderr 无换行记录均有硬上限,stderr 原文不得写入错误或日志,只记录固定分类、总字节数、SHA-256 与可取得的退出状态。Runner 正常、强制、watchdog 退出显式关池;Linux child 绑定 parent-death signal,避免 Runner 被强杀后遗留带凭据孤儿进程。
- DirectProject 会话恢复补充:Codex thread 继续使用 `ephemeral=true`,不保存或恢复 Codex 原生 thread。项目对话 `.agent/conversations/project.jsonl` 是唯一聊天事实源;仅当 app-server 连接没有可用的项目 thread(通常是进程重启或 thread 被淘汰)时,AGC 才读取全部 `user``assistant``tool` 行,按原顺序渲染为简单的 `user:` / `assistant:` / `tool:` 文本后,再追加本次新 user 请求发送给新 thread;已有 thread 的普通消息仍只发送新 user。app-server 意外中断时,已收到的 partial 文本作为普通 `assistant` 消息追加,并在末尾写入 `unexpected interrupt happened here`;断开处理与下一次发送均可重复追加,但使用普通消息 `messageId` 幂等。项目打开不再根据“只有 user 没有 assistant”自动重发旧请求;Direct 不新增 retry 入口。Runtime Agent 的恢复合同保持独立,不消费项目 Direct 对话历史。
- 兼容迁移:已有 AppData 未写 `agentMode` 时,仅当全局及逐 Agent 都是 `openai_responses` 才迁入 app-server;任何 `openai_chat / anthropic` 路由保持 `provider`,防止项目自动恢复先于用户改配置而批量失败。新安装仍默认 app-server;已确认兼容 Responses 的旧端点可由用户显式切换且继续使用原 model/base URL/API Key。
- 关联:`docs/technical/【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md` V1.52。
@@ -7937,6 +7938,17 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 任务最终状态不再提前绑定平台画布、preview、static smoke 或发布产物检查;这些内容不参与该档位的完成判定,也不会因缺失而重置已完成任务。父 run 在任务图进入终态后直接收束并回复。
- 本档位仍沿用现有项目根和工具权限边界;本次调整只解除流程编排与平台产物验收前置,不新增第二套任务系统。
## 2026-09-02 DirectProject replay 取舍与 thread 原子判定
- DirectProject 的全量 replay、简单 `user:` / `assistant:` / `tool:` 前缀和普通 assistant partial(末尾 `unexpected interrupt happened here`)都是有意的当前产品合同:分别保证 AGC JSONL 事实源无损重建、保持 prompt 形状稳定且不引入 envelope breaking change、让模型明确知道上次输出在中断处结束。后续若调整任一项,必须先更新恢复合同与兼容策略。
- replay 与 thread 创建必须使用同一临界区结果。`turn_gate` 内的 `thread_for()` 原子返回 `(CodexThreadLease, created)`;只有 `created=true` 时才读取项目 JSONL 并构造历史 prompt,复用已有 thread 时只发送当前 user,避免并发首请求重复注入历史。
## 2026-09-03 DirectProject replay 有界滑动窗口
- DirectProject 继续以 `.agent/conversations/project.jsonl` 作为不可变、append-only 唯一事实源;窗口只生成本次恢复请求的派生 prompt,不写回 JSONL,不创建 Runtime compaction summary 或 sidecar。
- 新建/恢复 ephemeral Codex thread 时,replay 使用 `contextWindowTokens``autoCompactTokenLimit`、本次 `maxOutputTokens` 与 4096 安全余量计算预算,从最新记录向前选择连续完整的 `user` / `assistant` / `tool` 行;超预算旧前缀被省略,单条记录不截断,当前 user request 始终保留。
- 发生省略时在 prompt 开头加入普通 `system: Earlier conversation history was omitted due to context budget.` 提示;当前请求本身超过硬上下文预算则直接失败。该策略是 Direct 专用滑动窗口,不复用 Runtime Agent 的摘要、tail 或 session compaction 生命周期。
## 2026-08-31 AGC 错误报告与诊断上传
- AGC 采用 IDEA 风格的当前进程错误池:按 fingerprint 合并 React / window / Promise / Tauri / Agent 错误,重启后不恢复,不使用 run 或 run_id。
@@ -226,6 +226,7 @@ Supervisor 认领该回执后,由父 run 自己为每个原 delivery 逐一创
- 模式升级:`agentMode` 扩为 `codex_app_server / codex_cli / provider`,新默认为 `codex_app_server`V1.51 的一次性 `codex exec` 保留为显式兼容模式,HTTP Provider 保留为非 Responses 配置及故障回退模式。
- 进程与节点:External Runner 按“有效 Agent LLM 凭据/Responses 路由 + `projectId/agentId/sessionId/runId`”隔离长期 `codex app-server --stdio`,即每个权威节点 run 直接持有自己的 Codex CLI 子进程与 ephemeral thread,每次完整权威请求映射 turn。同一节点 turn 串行,节点之间进程级隔离;单节点连接失败不得使其它节点同时失去终态。Codex thread 不写 durable recovery;节点完成、重启、retry、handoff 和 finalization 仍只认 AGC 账本。
- DirectProject replayCodex thread 仍保持 `ephemeral=true``.agent/conversations/project.jsonl` 是聊天唯一、append-only 事实源;每个 GUI turn 在发起 app-server turn 前,先把渲染后的规范化 user prompt 以 `direct-codex:{clientTurnId}:user` 幂等追加,持久化失败则不发起 turn 并公开 failedLLM 失败 / 中断时保留该 user 记录,重试同一 `clientTurnId` 只复用它。仅当 app-server 连接没有可用的项目 thread(通常是进程重启或 thread 被淘汰)时,AGC 才读取历史,按原顺序渲染为简单 `user:` / `assistant:` / `tool:` 行,再追加本次新 user request,发送给新建 thread;已有 thread 的普通消息仍只发送新 user。为避免持久增长的历史超过模型上下文,replay builder 使用全局 `contextWindowTokens``autoCompactTokenLimit`、本次 `maxOutputTokens` 和 4096 安全余量计算输入预算,从最新记录向前选择连续、完整的消息;超预算的旧前缀只在本次 prompt 中省略,不改写 JSONL、不写 summary/sidecar、不拆分单条记录。发生省略时在 prompt 开头加入普通 `system: Earlier conversation history was omitted due to context budget.` 行;当前 user request 始终保留,若其自身超过硬上下文预算则直接失败。这里的简单 role 前缀和普通 assistant partial(末尾 `unexpected interrupt happened here`)仍是产品合同:保持 prompt 形状稳定、避免 envelope breaking change,并让模型明确知道上次输出在断开处结束。app-server 意外中断时,已收到的 partial 文本按普通 `assistant` 消息追加;断开处理和下一次发送都可尝试写入,依赖普通 `messageId` 幂等。项目打开只读取历史,不因 user-only 记录自动重发;Direct 不提供 retry 入口。Runtime Agent 继续使用独立的 runtime/context 恢复链路,不读取 DirectProject 对话作为原生 thread history。
- LLM 配置:`apiKind` 始终只接受 `openai_responses`;非空 Key 转换为 app-server model providerbase URL 生效,Key 仅走专用环境变量;空 Key 只桥接用户 Codex `auth.json`,不继承环境 `CODEX_API_KEY`。设置面板在 app-server 模式继续显示并保存 model、effort、stream、全局/逐 Agent Key 与路由配置;`openai_chat / anthropic` 明确提示切 `provider`,不得悄悄忽略。`stream=true` 接入 app-server 文本 delta`webSearchEnabled=true` 只允许 DirectProject 经客户端审核的 `agc_web_search` 使用,不得启用 Codex 原生 webSearch 或任意网络。
- 安全与取消:临时 cwd、隔离 `CODEX_HOME` 与 OS HOME、read-only、network off、never approval,并在启动前关闭 web/multi-agent/shell/browser/plugin/image 等原生能力;取消从 turn-start pending 阶段就跟踪且只 interrupt 当前 turn。已发送 turn 后连接断开或终态丢失进入 reconciliation,只关闭当前节点进程且不重放同一 request slot;明确 failed/interrupted 不按 transport 重试。
- remote-control 认证边界:没有 ChatGPT `auth.json` 的 API Key / provider-proxy app-server 在启动时设置 Codex 内部环境变量 `CODEX_INTERNAL_APP_SERVER_REMOTE_CONTROL_DISABLED=1`,让 remote-control 以 `desired_state=Disabled` 启动,避免上游进入 1Hz 认证重试;不再依赖需要 ChatGPT 登录态的 `remoteControl/disable` RPC。只有实际桥接 ChatGPT 登录态的 AuthBridge 保持 remote-control 可用。API Key 子进程同时使用 `RUST_LOG=warn` 收敛剩余预期噪音,不伪造 `auth.json` 或静默继续。