DirectProject对话状态问题 #335

Open
opened 2026-09-12 14:48:56 +08:00 by k88936 · 3 comments
Member

在ai思考中退出这个项目或者到其他页面:
agent对话会在后台跑完, 但是正在跑的状态没有显示, , 再发消息时会阻止: "陶泥儿智能创作 被项目权限或安全策略阻止,请检查审批配置"

在ai思考中退出这个项目或者到其他页面: agent对话会在后台跑完, 但是正在跑的状态没有显示, , 再发消息时会阻止: "陶泥儿智能创作 被项目权限或安全策略阻止,请检查审批配置" <video src="attachments/89cc6c69-a3c0-433a-9389-18fafb5b65a4" title="2026-09-12 13-59-45.mp4" controls></video>
k88936 added the
Priority
Low
4
Kind/Bug
labels 2026-09-12 14:48:56 +08:00
k88936 added this to the 陶泥儿gameAgent project 2026-09-12 14:48:56 +08:00
k88936 self-assigned this 2026-09-14 20:23:43 +08:00
Author
Member

对比 Codex Desktop,缺口主要是:

能力 当前 AGC 实现 Codex Desktop 式实现
执行归属 页面组件内存 独立 session/thread manager
离开页面 UI 状态丢失,任务继续跑 UI 只是脱离观察,任务状态仍可查询
重新进入 只恢复历史文本 恢复 thread/turn 当前状态和事件订阅
活跃任务续接 没有统一活动 turn 查询 通过 thread/turn 状态或事件流重新绑定
并发提示 项目级 guard 直接拒绝 明确识别 active turn,并提供等待/续接/steer
错误展示 policy/permission 错误被统一泛化 保留具体错误类别和可执行恢复动作
对比 Codex Desktop,缺口主要是: | 能力 | 当前 AGC 实现 | Codex Desktop 式实现 | |---|---|---| | 执行归属 | 页面组件内存 | 独立 session/thread manager | | 离开页面 | UI 状态丢失,任务继续跑 | UI 只是脱离观察,任务状态仍可查询 | | 重新进入 | 只恢复历史文本 | 恢复 thread/turn 当前状态和事件订阅 | | 活跃任务续接 | 没有统一活动 turn 查询 | 通过 thread/turn 状态或事件流重新绑定 | | 并发提示 | 项目级 guard 直接拒绝 | 明确识别 active turn,并提供等待/续接/steer | | 错误展示 | policy/permission 错误被统一泛化 | 保留具体错误类别和可执行恢复动作 |
k88936 added a new dependency 2026-09-15 15:51:56 +08:00
Author
Member

会有很多冲突, rebase在那个之上

会有很多冲突, rebase在那个之上
kdletters moved this to 已完成 in 陶泥儿gameAgent on 2026-09-16 12:10:34 +08:00
Author
Member

项目开发工作台的聊天链路实际是:

ProjectDevelopmentView → ProjectSupervisorView → App.tsx 的 game-creator-direct-turn-update → project.jsonl / turn-stream.jsonl / tool-calls.jsonl。

按目标方案第 68 行后的合同复核,发现以下问题。

  1. 高优先级:Thread Manager bootstrap 事件被完全丢弃

apps/ai-game-creator-shell/src/App.tsx:2424 只读取 subscriptionId,没有处理 result.events 或 lastCompletedItemId:

subscriptionId = result.subscriptionId;
refreshActive();

但 Rust 端 subscribe() 会把当前未完成 item 和生命周期锚点放进 bootstrap,并把 subscriber cursor 直接设到当前尾部(apps/ai-game-creator-shell/src-tauri/src/agent/direct_thread_manager.rs:166)。

后续 consume() 只根据 turn.started/turn.completed 刷新活动快照,也没有 reducer item.started/item.delta/tool/approval 事件(apps/ai-game-creator-shell/src/App.tsx:2443)。

因此页面重进时,如果 bootstrap 中包含当前工具或未完成 item,而对应的 turn-stream / tool-calls 尚未落盘,聊天无法恢复这些过程事件。它与目标方案第 95、115、129 行要求的“bootstrap + consume 用同一 reducer 重放”不一致。

需要注意:较新的实施计划又把 Thread Manager 降级为“只触发快照和历史同步”。如果该新口径是有意替代目标方案,这属于文档漂移;否则就是实现缺失。

  1. 高优先级:异常终态的 Thread Manager 完成事件顺序错误,部分异常甚至没有终态事件

在 app-server 收到 turn/completed 时,代码先追加 Thread Manager 的 turn.completed:

apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs:3242

随后才返回 failed/interrupted,再在外层持久化异常回合的 partial assistant item:

apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs:3293

这违反目标方案第 117 行“完成事件必须在完成 item 成功持久化后进入队列”。消费者可能先收到回合完成,再读取不到刚刚生成的 partial assistant 历史。

另外,TransportClosed 和 stdout EOF 分支直接返回错误,没有追加任何 Thread Manager 终态事件:

apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs:3276

这与目标方案第 36 行列出的异常终态恢复要求不闭合。当前聊天 UI 仍可能依靠 Direct emitter 的 failed 事件和活动快照轮询兜底,但 Thread Manager 公共契约本身是不完整的。

  1. 中优先级:历史分页可能永久卡在同一页

后端分页按原始 project.jsonl item 数量切片,而不是按可显示消息数量切片:

apps/ai-game-creator-shell/src-tauri/src/agent/direct_project_history.rs:546

前端再把工具、reasoning 等非消息 item 全部过滤掉:

apps/ai-game-creator-shell/src/App.tsx:12496

如果某一页 20 个原始 item 全是工具或其它不可显示 item,older 会是空数组;此时前端不会推进 directHistoryOldestItemIdRef:

apps/ai-game-creator-shell/src/App.tsx:12511

结果是“显示更早的对话”按钮反复请求同一个 beforeItemId,用户无法继续加载更早的消息。这直接影响目标方案第 95 行要求的历史懒加载。

建议分页接口返回原始 item cursor,前端即使本页没有可显示消息也要推进 cursor,或后端循环读取直到收集到足够的可显示消息。

> 项目开发工作台的聊天链路实际是: > > ProjectDevelopmentView → ProjectSupervisorView → App.tsx 的 game-creator-direct-turn-update → project.jsonl / turn-stream.jsonl / tool-calls.jsonl。 > > 按目标方案第 68 行后的合同复核,发现以下问题。 > > 1. 高优先级:Thread Manager bootstrap 事件被完全丢弃 > > apps/ai-game-creator-shell/src/App.tsx:2424 只读取 subscriptionId,没有处理 result.events 或 lastCompletedItemId: > > subscriptionId = result.subscriptionId; > refreshActive(); > > 但 Rust 端 subscribe() 会把当前未完成 item 和生命周期锚点放进 bootstrap,并把 subscriber cursor 直接设到当前尾部(apps/ai-game-creator-shell/src-tauri/src/agent/direct_thread_manager.rs:166)。 > > 后续 consume() 只根据 turn.started/turn.completed 刷新活动快照,也没有 reducer item.started/item.delta/tool/approval 事件(apps/ai-game-creator-shell/src/App.tsx:2443)。 > > 因此页面重进时,如果 bootstrap 中包含当前工具或未完成 item,而对应的 turn-stream / tool-calls 尚未落盘,聊天无法恢复这些过程事件。它与目标方案第 95、115、129 行要求的“bootstrap + consume 用同一 reducer 重放”不一致。 > > 需要注意:较新的实施计划又把 Thread Manager 降级为“只触发快照和历史同步”。如果该新口径是有意替代目标方案,这属于文档漂移;否则就是实现缺失。 > > 2. 高优先级:异常终态的 Thread Manager 完成事件顺序错误,部分异常甚至没有终态事件 > > 在 app-server 收到 turn/completed 时,代码先追加 Thread Manager 的 turn.completed: > > apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs:3242 > > 随后才返回 failed/interrupted,再在外层持久化异常回合的 partial assistant item: > > apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs:3293 > > 这违反目标方案第 117 行“完成事件必须在完成 item 成功持久化后进入队列”。消费者可能先收到回合完成,再读取不到刚刚生成的 partial assistant 历史。 > > 另外,TransportClosed 和 stdout EOF 分支直接返回错误,没有追加任何 Thread Manager 终态事件: > > apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rs:3276 > > 这与目标方案第 36 行列出的异常终态恢复要求不闭合。当前聊天 UI 仍可能依靠 Direct emitter 的 failed 事件和活动快照轮询兜底,但 Thread Manager 公共契约本身是不完整的。 > > 3. 中优先级:历史分页可能永久卡在同一页 > > 后端分页按原始 project.jsonl item 数量切片,而不是按可显示消息数量切片: > > apps/ai-game-creator-shell/src-tauri/src/agent/direct_project_history.rs:546 > > 前端再把工具、reasoning 等非消息 item 全部过滤掉: > > apps/ai-game-creator-shell/src/App.tsx:12496 > > 如果某一页 20 个原始 item 全是工具或其它不可显示 item,older 会是空数组;此时前端不会推进 directHistoryOldestItemIdRef: > > apps/ai-game-creator-shell/src/App.tsx:12511 > > 结果是“显示更早的对话”按钮反复请求同一个 beforeItemId,用户无法继续加载更早的消息。这直接影响目标方案第 95 行要求的历史懒加载。 > > 建议分页接口返回原始 item cursor,前端即使本页没有可显示消息也要推进 cursor,或后端循环读取直到收集到足够的可显示消息。
k88936 moved this to 进行中 in 陶泥儿gameAgent on 2026-09-16 16:27:46 +08:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Depends on
#365 WIP: fix/引用持久化
GenarrativeAI/Genarrative
Reference: GenarrativeAI/Genarrative#335