Repository navigation
feat(chat): observe unfinished work in attached Agent conversations - #6599
loopx-agent wants to merge 4 commits into
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; runtime_reported; reasoning_effort=max
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
评审 6599@1db44f2e8ae1450e7b807269793480ad03201392。[P2] “较新记录”返回尾部后保留过期实时草稿。 在 A 显示时回看,宿主更新为 B,再点“较新记录”到尾部,回看提示已消失而 A 仍持续显示。原生订阅与 B 都有效;同一状态下重新回看再点“回到最新”立即显示 B。应让两条恢复跟随路径都发布 latestLive.current,并在没有后续事件时验证。
动机
正在 Goal 中跟进某个既有 Codex App Agent、需要看到尚未保存的可见工作内容的本机负责人。
原来工作页只显示已保存记录,未完成的消息和工具内容不可见;现在页面跟随同一原宿主的只读快照与补丁,但从回看历史经“较新记录”回到尾部时,会静默保留旧实时草稿。
真实 HTTP/Unix 对端与打包页面已证明实时更新、回看冻结、显式回到最新、Agent 隔离及完成转入已保存历史;同样的入口独立复现了“较新记录”恢复后旧草稿持续显示。
本 PR 不启动第二执行者,不授权原生输入或审批,不证明完整 token/event 对齐、Windows 传输、其他 provider、持续负载或已安装 App 采用。
当前需补齐所有恢复到实时尾部的路径;完整 Slice B 的输入、审批、跨平台及安装采用仍沿原有验收继续。
本次从普通用户要判断交付、跟进原工作内容的任务出发。Agent 能从已有上下文准备的技术资料不应再让人重复输入;原本缺失的真实意图或执行权限仍须确认,不能从展示数据推出授权。当前验证限定到真实可用的这个增量,不把测试、回执、截图或 PR 数量当成长程 Goal 的完成证据。
改动思路
Python 留在已有 Codex provider/HTTP 传输边界是合理的:只解析版本化原生数据与 IO,不创建通用控制面决策。LiveView 保存过滤后的当前内容,SSE 重查原绑定;React 将实时行与原保存历史共用 renderer。
原生 Chat provider 适配私有 Unix IPC;既有绑定、活动观察、保存历史及输入 receipt 保持各自 owner,前端只组合一个短暂可见投影。
| 返回方式(同一原生 B) | 当前观察 |
|---|---|
| 回看 → 回到最新 | B 立即显示 |
| 回看 → 较新记录到尾部 | 提示消失,仍显示 A |
| 切换其他 Agent | 旧实时行移除,原订阅释放 |
表中前两行是同一当前 head、同一真实 HTTP/Unix 对端的独立浏览器结果;不是从截图或单元测试推断。
帧读取已合并到 DesktopClient.read_frame,provider-local 状态与既有 renderer 的复用合理。当前应在同一组件统一恢复跟随时的最新投影发布,覆盖两条返回路径;无需新缓存、设置或第二订阅 owner。 保留原 owner 能让后续规则修改与回滚落在一个地方;重新创建配置或第二个原生执行者既扩大风险,也不能解决已经复现的入口问题。以上比较明确区分原状态、预期改进与当前缺口。
具体改动
整份 base-to-head:14 files, +1303/-50; two frontend files, four runtime/HTTP files, two public documents, three browser fixture/scenario files, one 469-line test addition and two synthetic PNGs.
- read_frame:Share frame decoding, keeping the ordinary 8 MiB RPC limit and a separately requested live limit. Length checked before body allocation; malformed object raises a provider-local protocol error.
- LiveView:Add compact exact-thread revisioned visible-work projection instead of retaining raw history. Snapshot/patch version and shape checks; bounded turns/items/fields/view; private and completed items omitted.
- observations:Follow/unfollow only the discovered original owner. Owner/thread/host/version fencing, bounded frame read and finally-unsubscribe; no input method.
- _codex_attached_live:Expose scoped SSE through the existing local HTTP routing. Exact Goal/Agent/binding; two-reader bound; binding checks and heartbeat; protocol stops versus transient retry distinguished.
- AttachedAgentConversations:Append short-lived live rows, freeze while looking back, clear on binding change and completion. Live identity prevents cross-Agent reuse; latestLive buffers updates while following is paused, but older(true) fails to publish that buffer at the tail.
- AttachedConversationRecord:Use current prop text for live rows while retaining stored-detail continuation for durable rows. Live tool title states in-progress; no acceptance or execution permission inferred.
DesktopClient.read_frame 把原有解帧聚合到一个函数,普通调用仍保留 8 MiB 上限。新 Codex-only LiveView 丢弃旧完成 Turn 内容、隐藏推理/用户/配置字段,保留允许的可见项;身份、原宿主版本、baseRevision、索引和大小不连续就拒绝。该原生状态词留在 provider,不成为通用 LoopX actor 或执行状态。
observations 只向发现的原 owner 发送 following/unfollowing,finally 释放;HTTP 路由重查精确 Goal/Agent/binding,限制两个读者,区分暂时断线可重连与协议不兼容停读。额外真实 Unix/HTTP 用例中,第三读者收到 unavailable;9,437,591 字节的原始帧只输出一条当前可见行;撤销绑定使两个原订阅停止。新注册但无绑定的 Agent、同进程另一 Goal、额外 thread 参数与外部 Origin 均拒绝,输入数保持 0,保存历史未因观察被写入。
前端同一个 renderer 接收临时实时文本,原保存记录继续用原 detail/continuation 逻辑。观察区标记内容来自正在运行的原宿主,回看冻结插入、切换 Agent 清除旧行,完成后转到保存历史。新 liveView/latestLive 双缓冲却没有接入 older(true) 的尾部恢复:该分支只重置 following/reading/unread,新增的 setLiveView 只在 latest() 中执行。这是本轮独立重现的当前缺口,单元与普通 wheel 的绿测没有覆盖它。
三个既有 browser/Unix fixture/scenario 文件增加合成快照、补丁、并发客户端及释放;469 行测试覆盖过滤、完成 map、断线、错 owner/version/revision、字段/帧边界和离开页面。两张 PNG 为合成记录,保留未接独立执行服务的提示;RFC 与 integration guide 明说实验范围、64 MiB 帧/32 行/256 KiB 视图和未完成资格。
独立规范依据是 docs/architecture/rfcs/desktop-execution-frontends-v0.md,不可变 revision ebc01b2a46abb493f8a2300ce07bc54036cc7a29。条款映射:Common invariants 的原 owner、精确绑定和无第二执行者获证;companion docs/integrations/session-runtime-control-plane-adapter.md 同 revision 的 Experimental owner-local Codex App conversations 中有界阅读、回看和恢复路径,本次恢复到最新仍 not_met;Attached mode 的完整输入、interrupt/resume 等继续 deferred,不额外要求此观察切片关闭整个 Slice B。新改过的 checkpoint 未被倒用为独立规范。
对主干的风险
主要阻塞是恢复后的内容真实性,不是额外执行或原生输入。后台已有 B,UI 声称结束回看却仍展示 A,且把“回到最新”控件一起隐藏;如果宿主此后没有新的可见变化,SSE 的去重不会再发送一个碰巧修正它的事件。负责人会漏看新结果,或误把旧工具/消息当作当前工作。点击另一次回看再返回虽可恢复,但这是不必要的额外步骤。
最小修复在原组件:所有回到 following 的路径都应用最新缓冲,保留身份 fencing 与历史分页;可用小的共同恢复 helper,避免两处继续漂移。在既有打包场景同时覆盖 Back to latest 与 Newer records 到尾部,并在 B 后停止事件,断言内容立即为 B。无需新状态、自动重连或放宽任何权限。
47 项源码测试通过(55.45s);普通 wheel 的独立 site-packages 环境同样 47 项通过(21.83s)。四个变化的运行时文件与 37 个 Chat 文件均与 head 逐字节相同。Ruff、配置内 mypy 19 文件、Dashboard TypeScript/build、正常 wheel、advisory 后完整语义 smoke 通过;风险 canary 5 direct +17 selected 全通过、无 manual hold。
9 MiB 用例使用真正的 Unix 帧和 HTTP,但原宿主内容是合成数据;它证明独立读限与紧凑投影,不证明私有 Desktop 协议的所有版本或持续成本。没有读取活动会话的私有历史,也没有把作者的原宿主观察当成本轮独立资格。
语义审查覆盖本次局部联合/状态词、实际 producer 和 consumer、default-off/未绑定、同容器未覆盖主体及新主体。advisory 未检出支持的命名载体,并不证明动态构造没有语义变化;此处另逐一追踪。原强制的身份、同意、版本与恢复条件没有被改成“建议”。本 Goal 的 CI policy 是 not_consulted:本轮未查询、轮询、dispatch 或等待远端 CI,局部 canary 也不替代托管/发布或合并资格。
我的整体评价
结论 REQUEST_CHANGES;delivery verdict 为 not_yet_proven。当前观察增量有用,provider 归属与大小边界合理;必须先修复已经重现的返回路径,不能因其余测试通过而批准旧实时内容被静默当作当前。
long_horizon=preserved:执行、调度和接受事实仍由原 owner 决定,局部读回/生命周期与反例保持边界;不据此认证持续部署。user_experience=regression:“较新记录”移除回看提示并恢复 following,却不发布缓存的最新实时投影;不再有变化时页面无限保留旧草稿,要求用户重新进入回看再点回到最新。
帧读取已合并到 DesktopClient.read_frame,provider-local 状态与既有 renderer 的复用合理。当前应在同一组件统一恢复跟随时的最新投影发布,覆盖两条返回路径;无需新缓存、设置或第二订阅 owner。 当前需补齐所有恢复到实时尾部的路径;完整 Slice B 的输入、审批、跨平台及安装采用仍沿原有验收继续。 验收/运行时通过、独立代码评审、原始首屏确认和 exact-head merge readiness 各有其边界;本结论不授予 merge、bypass、dismiss、resolve、输入或安装权限。
English verdict: REQUEST_CHANGES - 1db44f2; Newer records can resume following while retaining a stale live draft. Reconcile the buffered projection on every return-to-tail path; source/wheel/provider checks pass but do not cover this reproduced packaged-UI defect.
| function latest() { | ||
| historyEpoch.current++; after.current = null; history.current = null; revision.current = ""; | ||
| following.current = true; setReadingHistory(false); setUnread(false); setMessages([]); setBefore(null); | ||
| setLiveView(latestLive.current); |
There was a problem hiding this comment.
[P2] 同时覆盖“较新记录”抵达尾部时的恢复。实际打包页中,实时草稿 A → 回看 → 原宿主更新为 B → “较新记录”到尾部后,回看提示已消失但仍显示 A;同状态再点“回到最新”会立即显示 B。older(true) 在第221行恢复 following,却没有发布 latestLive.current;若原宿主不再产生可见变化,旧草稿会一直保留。请让两条恢复路径都应用最新缓冲,并在 B 后无新事件的真实 browser 场景中断言显示 B,保留 Agent 切换/完成/身份 fencing。
…path Look-back froze live insertion correctly, but only "Back to latest" republished the newer buffered draft. Returning to the tail through "Newer records" resumed following while the previous draft stayed visible, so a finished look-back could show stale work as current until some later host event happened to replace it. Restore following through one helper both paths share, so the frozen draft is replaced whenever the tail is resumed. Qualify it in the packaged browser scenario: after a second live draft arrives while reading history, "Newer records" must publish it immediately, without a new subscription. Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
|
This pull request has merge conflicts with Choose the remote for the base repository, not an out-of-date fork. git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEADFor a same-repository clone whose Keep the DCO |
Goal And Delivered Outcome
The attached Agent reader currently waits for saved host records, leaving unfinished messages and tools invisible. This adds read-only observation from the same original Desktop owner inside the existing Agent work page. Opening that page is sufficient; no extra setup or confirmation is added.
Continues the working-session journey from #6482, targeting
docs/architecture/rfcs/desktop-execution-frontends-v0.mdSlice B. Intended base:main. This does not close the full Slice B acceptance.Author Declaration
Written by: model_agent — OpenAI Codex, GPT-6 family, submitted through
loopx-agent.Implemented against the Desktop execution-frontends RFC and
docs/integrations/session-runtime-control-plane-adapter.mdatebc01b2a46abb493f8a2300ce07bc54036cc7a29, plus the accepted original-session observation request.Self-check: source diff, current
main, instructions, provider ownership, public boundary and the checks below. No private transcripts or installed-App screenshots are published.Scope And Continuation
The App frontend changes; existing CLI and Lark entrypoints do not. This is independently reversible observation work. Native-input qualification, approval callbacks, complete parity, Windows transport and installed adoption remain with the existing working-session/release acceptance.
Validation
Tested author revision:
1db44f2e8ae1450e7b807269793480ad03201392. Run state: finished. Input classes: synthetic, public_fixture, authorized_private_read_only.uv run --extra test python -m pytest -q tests/presentation/test_codex_attached_conversation.py: 47 tests; production HTTP + disposable Unix owner, completion maps/patches, identity, privacy, bounds, reconnect and unsubscribe; zero native inputstsc --noEmit, changed-Python Ruff, focused stream/API mypy, browser scenario syntax, bundle build andscripts/chat_bundle.py verify --sourcemainmade it stale again. No green merge-readiness claimRemaining coverage: private protocol compatibility and initial snapshot cost are explicit limits. Full native input/approval, sustained load, other providers and installed-App adoption are unqualified. Exact-head independent review and current-base quality/CI gates remain required before merge.
Frontend / Visual Evidence
UI impact: changed. Source data: synthetic. Existing opening navigation and primary actions are unchanged; the new rows use the existing transcript composition.
These full-viewport images use an isolated conversation fixture, which omits the separate managed executor; its unavailable banner is retained. The same frontend was separately paired with the real original owner, whose private screenshots remain unpublished.
Attention/craft review: the transcript remains the focus. Live source labeling explains an otherwise invisible state; tools reuse collapsed details. Existing pause/return controls handle reading without a new panel or configuration flow. No new cards, animation, color tokens or Goal-workspace layout are introduced. Uncertainty remains visible. Responsive layout is unchanged; narrow/English interaction was nevertheless checked.
Type / Area / Direction
New feature with focused validation and documentation. Native Chat capability/provider, presentation surface and host integration. Direction: operator surface and IM integration / Desktop RFC Slice B. Shared-authority and TypeScript migration fixture impact: N/A; no Goal authority, storage routing or shared decision semantics change.
Boundary Checklist