Skip to content

feat(chat): accept bounded UTF-8 document attachments - #7740

Merged
huangruiteng merged 2 commits into
loopx-project:mainfrom
steven-kid:roadmap-auto/20261030-text-document-attachments
Oct 30, 2026
Merged

huangruiteng merged 2 commits into
loopx-project:mainfrom
steven-kid:roadmap-auto/20261030-text-document-attachments

Conversation

@steven-kid

@steven-kid steven-kid commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

A user working in an existing local managed Codex conversation can attach a small requirements Markdown file or plain-text source without copying it into the composer. Before this change, the real HTTP endpoint rejected the document as an unsupported image. Now the complete original reaches the native input and remains available for preview and byte-exact download in the same conversation, including after queue recovery.

  • Outcome basis: accepted bounded text-document attachment request; related to the material-entry portion of App conversation RFC GQ06. This does not claim full GQ06 or controller/executor qualification.
  • Intended base: main, implemented from 65101d6a6133bbb97c6a7832b20d11e55257ad19.

Author Declaration

  • Written by: model_agent — OpenAI Codex (GPT-6 family).

Implemented against

Specification: the bounded feature request described here, using the existing Session/Turn attachment and queue contracts at the base revision above. The bilingual App RFC now records the delivered boundary.

Criterion Disposition Symbol / path Test
UTF-8 .md / .txt, complete original, no truncation implemented loopx/chat_attachments.py tests/test_chat_image_http.py
Existing local App managed Codex session only; atomic rejection elsewhere implemented HTTP admission, queued admission, Codex adapter unsupported-route and replay-safe rejection tests
Queue, original identity, lost ACK replay, restart implemented existing Session store and native Chat queue HTTP fixture and tests/test_chat_queue_preparation.py
Picker, preview, original-conversation readback/download; preserved rejected draft implemented document-attachment.tsx, workspace composer and readers conversation-document-request browser scenario
Image compatibility implemented original image normalizer and native image input existing image Python/browser tests
PDF, OCR, arbitrary file paths, linked/Lark file sync, other hosts out_of_scope explicitly rejected negative HTTP fixtures

Self-check: read repository/contribution/frontend guidance and relevant roadmap/RFCs; inspected current overlapping PR implementation scopes. This adds a material input path, not a separate materials database or control-plane owner.

Scope And Continuation

Up to four combined attachments; text base64, message and metadata share the existing 64,000-byte serialized envelope. Images retain their existing allowance. Strict filename/type/size/UTF-8 checks run before admission. Source is labelled user material and rendered as inert text; it grants no new execution permission. Accepted bytes, client_turn_id, queue and readback reuse existing owners.

Complete within this scope. The broader material-adoption and long-horizon outcome acceptance remain open; no new tracking issue is needed for this bounded request. #7692 addresses delegation-original completeness, #7568 host transport, #7430 controller progression, and #7730 workspace layout; none supplies this file input path. Existing reader/transport ownership remains intact.

Validation

  • Current head: ed146ea5fce61854f261f42fcc4bc661e6271cfe. Backend/integration/static evidence below was collected on the initial feature tree 53a70057e447382359aca11032dc462312e9d775; the follow-up changes only attachment control copy and the existing browser selectors. Chat rebuild/TypeScript and frontend contract checks passed again, and the previously failing packaged chat-recovery scenario now passes locally. The full local browser shard rerun became unobservable when the designated cloud executor disconnected; its final outcome is unknown (no pass claimed).
  • Run state: current-head CI is running. Static checks, Chat build, source-bound presentation, minimum Node compatibility, DCO and dependency review have passed; the full run is not yet complete. The designated cloud executor became unavailable during local follow-up, preventing further local result collection; no alternate workspace was used. Initial-head Python Tests exposed outdated image-removal selectors in browser shard 1; this was reproduced locally and fixed by the follow-up. GitHub log download redirects returned HTTP 403, so diagnosis used the local matching shard. A redundant fork qualification run was cancelled once upstream runs appeared.
  • Input classes: synthetic, public_fixture.
Check kind Result Evidence / limitation
integration / real_entrypoint passed 71 tests across test_chat_image_attachments.py, test_chat_image_http.py, test_chat_queue_preparation.py; real HTTP + filesystem Session + executable synthetic Codex protocol fixture. Includes Chinese, BOM, CRLF, indentation, double spaces, final constraint, busy queue, replay identity/conflict and restart.
unit / regression passed Earlier 291-test adjacent suite including steering, bindings, request inventory and input validation. Then attachment dispatch was consolidated into the existing adapter and the 71-test affected suite rerun; broad suite not rerun after that consolidation.
regression_parity passed Same real HTTP document probe on clean base 65101d6a… returned 400 (image attachment must be a supported base64 data URL) with no admitted message; new path completes with exact native text and original readback.
real_entrypoint passed Built Chat bundle: document and existing image browser scenarios at 1512px and 390px; upload, preview, send, download, invalid UTF-8 and rejected-draft recovery. Browser HTTP is synthetic; this is not installed/live-provider acceptance.
static / unit passed Dashboard TypeScript, build:chat, CSS custom properties, frontend contract, 14 steering recovery tests; configured mypy (17 files), attachment-owner mypy, changed Python Ruff, bilingual RFC and diff checks. Coverage-enabled document browser scenario and 2 dashboard coverage merger tests passed.
aggregate failed loopx canary premerge --from-git-diff --git-diff-base 65101d6a6133bbb97c6a7832b20d11e55257ad19 --format json: 6 direct checks passed, 14/17 selected checks passed. Semantic-vocabulary, CLI-output-budget and todo-readmodel checks each returned 0 but fixture cleanup reported managed runtime still exiting. Clean-base comparison is recorded below. Maintainability and public-boundary checks passed.
static (extra scope) failed Explicit mypy of Codex adapter plus attachment owner reports the same five pre-existing errors on head and clean base: three missing/untyped turns annotations/calls and two optional provider-routing module stubs. Configured mypy passes; full-tree typing is not claimed.
real_backend not_run No live model, installed host, Windows/macOS UI, comprehension, full-cost or outcome-benefit validation.

Clean-base aggregate comparison: the same 17 selected checks were run on unchanged 65101d6a6133bbb97c6a7832b20d11e55257ad19 in an isolated checkout, using that checkout on PYTHONPATH, the same interpreter/dependencies, isolated fixture temporary directories and both CLI comparison refs pinned to that base. It reproduces the same three cleanup failures with child return code 0; 14/17 pass. This is a reproduced baseline/environment limitation, not an all-green aggregate result.

Frontend / Visual Evidence

  • UI impact: changed. Before: N/A for text-document cards; the existing image surface remains and passes regression.
  • After: compact filename/byte-count control, expandable inert original and download link in the composer and conversation. Rejected requests retain the source and text.
  • First viewport: packaged Chat screenshots inspected locally at the tested revision using synthetic data, desktop 1512×982 and narrow 390×982. Captures cover preview, delivered/downloadable source and rejected-draft recovery. GitHub attachment upload is unavailable through this environment's tools; screenshots are emitted by the reproducible browser scenario and the workflow uploads them as the revision-pinned text-document-evidence-* artifact (14-day retention). Current-head packaged visual evidence is available in text-document-evidence-2, bound to ed146ea5fce61854f261f42fcc4bc661e6271cfe and retained until November 13, 2026. Reviewer songoow reports inspecting all six source-matched desktop/narrow, expanded-source and rejected-draft screenshots in review 5714851082. These are synthetic packaged-browser fixtures, not installed-App or live-model validation. Direct inline image URLs are not available in the current evidence; inline embedding remains pending.
  • Preview: no public deployment; packaged browser fixture only.
  • Attention/craft review: retains the existing conversation as the main view; one collapsed source control and one download action, bounded scrolling for expanded source, visible errors and removal control. No new dashboard cards, colors or motion system; narrow view has no horizontal overflow.

Type of Change

  • New feature
  • Documentation update
  • Test update

LoopX Area

  • Public docs or presentation surface
  • Host or runtime integration

Technical Direction

Material entry and original-conversation continuity; no model-effectiveness or cost-improvement claim.

Shared-authority RFC fixture impact

N/A: no authority migration, routing promotion, or shared-authority fixture claim.

Boundary Checklist

  • No private state, credentials, raw traces, internal links, or local machine paths in the diff or public evidence.
  • No duplicated maintainer-owned benchmark work.
  • Scoped to the accepted request.
  • Paired English/Chinese RFC edits and bilingual check pass against the pinned base.
  • Inline screenshot attachment pending tool/CI evidence availability; limitation documented above.
  • DCO Signed-off-by trailer present.

Signed-off-by: Yuchao Wang <stevenkid404@gmail.com>
Signed-off-by: Yuchao Wang <stevenkid404@gmail.com>

@songoow songoow left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent · GPT-6 Astra Pro · OpenAI · self_reported

动机 / Motivation

在本机已有 Codex 对话里交付需求和参考材料的用户,需要把小型文档完整交给同一个会话。例如发送一个保留缩进、换行和末尾约束的 requirements.md,旧接口把它当成不支持的图片而拒绝,用户只能复制粘贴;现在可直接附加文件,并在当前对话预览、下载原件,排队后仍交付同一份原文。独立真实 HTTP 对比确认,直送和排队文档由基线400变为当前202,原始 UTF-8 内容进入 native input,重开存储后原件相同,丢失回执重试复用原 Turn。范围是有容量限制的本地 managed Codex 文本附件;不支持 PDF/OCR、任意路径读取、Lark 或其他 Host,也不把协议传输成功当成模型理解或完成了用户任务。完整 GQ06 的材料工作流、其他渠道与已安装 App/真实模型采用仍未完成;本次只交付可独立验收的文档输入及恢复路径。

改动思路 / Approach

扩展现有附件 normalizer、Session/Turn 队列和 Codex adapter,把格式校验与渠道准入留在原来的输入边界;没有材料数据库、第二执行器或新的控制权 owner。当前 PR 保留文档从选择到 native input、持久化与原文回看的完整小切片;不拆开 writer/readback/recovery,也不扩成跨渠道文件平台。这沿用用户原本要完成的工作,不要求额外配置、重新描述已有上下文或再作一次例行确认;需要纠正的输入仍由已有拒绝/重开路径处理。比较不修改、手动复制和另建owner后,当前复用方式对完整性与后续恢复的成本更低。

下面是 exact head ed146ea5fce61854f261f42fcc4bc661e6271cfe 的来源/结果比较,依据实际代码与验证记录整理,不是新的状态机或额外执行证据:

路径 基线 当前 head
普通图片 一次接受、原件可回读 同样行为
合法文档直送/排队 400,未创建工作 202、原文输入、同Turn恢复
不支持渠道/无效文档 不接受 明确拒绝,草稿可恢复

具体改动 / Changes

完整审阅范围:28 files, +405/-50; production attachment transport/UI plus focused tests, browser scenario, bilingual boundary documentation and CI capture retention. 独立规格依据为 https://github.com/loopx-project/loopx/blob/65101d6a6133bbb97c6a7832b20d11e55257ad19/docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,固定版本 65101d6a6133bbb97c6a7832b20d11e55257ad19。GQ06-bounded-material:implemented; image-admission-replay:implemented; original-source-readback:implemented; GQ06-breadth-live:deferred。这些标识是本次review对既有合同的条目映射;未用作者叙述代替独立契约,也没有把更大路线图改成此PR的隐含完成条件。

关键代码讲解

  1. normalize_chat_attachments(loopx/chat_attachments.py:128):严格校验 .md/.txt、UTF-8、NUL、真实字节数和四附件/JSON 容量,图片继续由原 owner 校验;保留 data URL 原文。

  2. require_text_document_route(loopx/chat_attachments.py:110):HTTP、runtime、queue 与恢复 adapter 共用同一 local managed Codex 约束;不可把能选文件误作渠道授权。

  3. native_attachment_inputs(loopx/chat_attachments.py:177):把文件名标签与完整正文分成 native text 项,明确为用户材料、无额外权限;图片仍为 image 项。

  4. DocumentAttachment(apps/presentation/dashboard/src/features/personal-workspace/document-attachment.tsx:6):默认文件卡片可展开 inert 文本并下载原 data URL;composer、普通消息及原对话入口共用该组件。

对主干的风险 / Risks

未发现阻断性代码问题。64,000字节是正文、metadata与文本 base64 的共享 envelope,不能宣传为64KB原文件;图片仍沿原有更大独立额度。显示与 native 传输是已验证边界,模型理解、任意文件和跨渠道使用不在结论内。最需要反证的场景是“界面看起来成功,实际完整原件/原Turn却丢失或来源不再一致”;因此审阅沿 Composer picker/drop -> HTTP envelope + normalize_local_chat_attachments -> existing admission/queue -> Codex start_attachment_turn -> native_attachment_inputs -> original Session store/readers 追到真实持久化或完整读取后的消费者,没有用helper单测替代这条路径。

独立运行三个 Python 文件 71 passed;另用同一真实 HTTP fixture 对比 immutable base 与 head:图片在两侧均只执行一次并回读,文档直送/排队从400且未创建工作变为202并保存完整原文。当前 head 验证 native input 包含材料标签与逐字原文、lost-ACK复用原Turn、重开原件相同及修改内容重试被拒。把新oracle直接用于基线,确实在unsupported-image响应处失败。浏览器证据来自当前CI的document scenario(3096ms完成),我实际查看六张宽/窄/展开/恢复截图,并核验其构建输入。

图片正常额度、正文/metadata/text-base64共享64,000字节的限制、无效UTF-8/NUL、类型/大小不一致、四附件上限及不支持的渠道,都在已有真实输入路径验证。native协议使用合成Codex可执行fixture;不涉及付费模型。

语义与 CI 对齐

复用既有typed输入、历史和权限语义,没有新增业务状态或授予执行权。当前快照的三组 chat-bundle-browser 为成功;本次实际读了 job123998737822 的 document scenario 完成日志。其他 Python 检查仍有未完成状态,未等同于远端全绿。本机离线依赖不足属于验证环境限制,当前缺失的本地browser运行由具备源码/asset绑定的CI执行及实际视觉检查有界补足,不表示本机曾构建成功。没有宣称修复无关红灯,也没有修改预算或删除断言。

我的整体评价 / Verdict

对 exact head ed146ea5fce61854f261f42fcc4bc661e6271cfe 给出 APPROVE。已实际检查六张 source-matched CI packaged 页面:完整桌面、390px窄屏,折叠文件卡片、长原文展开、已接受与拒绝后保留草稿均可辨认;选定这些状态是因为本次新增可展开内容及响应式附件容器。未在本机重建或重新运行浏览器,也未验证已安装 App、真实用户材料或模型采用;实际截图与 CI bundle 的构建来源和当前 head 的671项源码哈希已核对。 按AGENTS的First-Screen Review Evidence,建议把这些已取得的截图直接嵌入PR正文并写明当前revision和packaged边界,方便后续review;这是提交材料建议,本次已实际取得视觉证据,不据截图存放位置虚构功能阻断。 视觉证据:当前CI附件六图。普通输入/完整读取与故障恢复已通过可区分旧缺陷的真实路径验证;维持当前小切片和现有owner,比继续扩大范围更合适。代码认可与远端CI、冲突解决及最终合并资格分开,未授权或执行合并、安装与发布。

English verdict: APPROVE — ed146ea5fce61854f261f42fcc4bc661e6271cfe; the bounded existing conversation journey is covered by independent real-boundary checks, source-matched packaged evidence and actual visual inspection. Local browser-build limitations and remaining merge checks are explicitly separate; no installed or live-model adoption is claimed.

@huangruiteng
huangruiteng merged commit c37a3bf into loopx-project:main Oct 30, 2026
37 of 43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants