Repository navigation
Conversation
The shadowed user-message renderer only understood text and image blocks, so a
file attachment disappeared from the transcript entirely. It now renders every
attachment the host renders — images through the images slot, files as cards
built from the platform-seeded client atoms, unknown block types as the host's
JSON inspector — and the same edit box manages the message's attachment set.
Attachment display
- Render file attachments as file cards (type icon, name, extension, size) in
the host's own attachment-row layout, preserving block order.
- Degrade to a name-only card when the host atoms are unavailable, and to the
JSON inspector for a block type this renderer does not know.
Editable attachments
- The edit box lists the message's attachments as removable chips (image
thumbnails, file cards with upload progress and retry); the paperclip, the
file picker and a drop target add new ones.
- `POST /message-tree` accepts an ordered `attachments` array: durable
references pass through, a staged upload receipt resolves through the
file-upload service, and a newly added image is admitted by the attachment
store. An omitted array keeps the original attachments.
- Uploads read the client service's `{ ok, value }` result envelope as well as
its bare value; reading only one left the receipt undefined and JSON dropped
the key, which the host rejected as a malformed request body.
Open a file attachment
- `GET /message-tree/attachment` resolves one stored reference to its host
path through the attachment store, which validates the digest and display
name, so a forged name cannot become a path.
- Transcript file cards open that path in the harness's right sidebar through
the `dsh-resource://file/session/…` address the sidebar's document preview
reads.
Registration no longer risks the whole view: `conversation.input.attachments`
belongs to the composer's entry, and a child slot may have exactly one
declaring entry, so the bubble is registered a second time without the rail
instead of losing the edit button.
Tests cover attachment rendering, the editable set (kept references, staged
receipts, encoded images, refusals), upload-result envelope handling, the
child-slot collision, attachment-path resolution and traversal refusal, and the
sidebar address grammar. Client tests fail on React key warnings.
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



本变更内容
在
v1.1.0基础上,围绕消息附件有三项变更。1. 文件附件此前不可见(修复)
plugin.client.js以优先级-1遮蔽了宿主的用户气泡,因此由它负责内容渲染——而它只理解text和image。一个file块没有命中任何分支:带.log或.json附件的消息只显示其文本,既没有卡片也没有错误。现在它镜像宿主自己的
contentParts拆分:conversation.message.images插槽;file块渲染为宿主的文件卡片(类型图标、名称、EXT SIZE),由平台预置的@deepseek-ai/dsh-client-ui-primitives原子组件构建;JsonBlock,而不是被丢弃;2. 编辑框可以管理附件集(功能)
POST /message-tree接受有序的attachments数组:持久引用直接通过,暂存上传回执通过文件上传服务解析,新添加的图片由attachments.admitPromptContent接纳。省略该数组会保留原始附件,因此旧客户端不受影响。{ ok, value }信封,远程回退返回裸值)。只读取第二种会让回执变成undefined,JSON.stringify丢弃该键,宿主以请求体格式错误为由拒绝整个请求。3. 点击文件卡片即可打开(功能)
GET /message-tree/attachment通过attachments.fileHostPath将一个已存储引用解析为其宿主路径,卡片会把 harness 为其自身文件卡片构建的同一个dsh-resource://file/session/…地址交给右侧栏,以便侧栏的文档预览(文本、代码、PDF、图像)读取它。该引用通过 store 传递,store 会验证摘要和显示名称,因此伪造的名称永远不会变成路径。一个值得写下来的 DSH 约束
conversation.input.attachments由 composer 的入口声明,而插槽注册表(dsh-client-ui-slots、register)只允许恰好一个入口声明子插槽。本分支的第一个修订版也声明了它,注册抛出异常,整个用户视图也随之消失——编辑按钮、版本环和卡片都一样。现在,当第一次尝试被拒绝时,气泡会在不带该栏的情况下进行第二次注册。如果将来想从另一个组件复用 composer 的草稿栏,那么这条单一声明者规则就是需要重新审视的地方。验证
npm test:90 项测试通过(客户端渲染、可编辑附件集、保留的引用/暂存回执/编码图像/拒绝、上传信封处理、子插槽冲突、附件路径解析、路径遍历拒绝、侧栏地址语法)。客户端测试还会在出现 React key 警告时失败。npm run check:package:打包归档仍只包含 13 个运行时文件。0.1.5-rc.2、隔离的 Web 配置环境、本地离线模型适配器(无远程模型调用):附件渲染;在编辑框中移除/上传(包括一次失败的上传及其重试);上传路由返回{ ok, value: { receiptId, file } };一次编辑提交该回执,并且分支发布file(sha256:…) + text;以及附件路由将一个真实存储的文件解析为会话文件系统可读取的路径。1.2.0,并带有.github/release-notes/v1.2.0.md,与v1.1.0的发布方式一致。如果你更愿意自己来做版本提升,说一声,我就把它去掉。