---
description: "持久图片附件，供用户与维护者在提示词与命令中附加、复用或排查图片。"
kind: "package-reference"
---

# @deepseek-ai/dsh-attachment

[English](README.md) | 中文

## 概述

你可以把图片附加到提示词和命令中，harness 会持久保存提供方无关的规范化版本：每张源图都会在你的消息被处理前准入并规范化，重新出现在对话历史中，并在同一会话的后续轮次投影到所选模型路由。随附的 `dsh` 组合无需任何配置即可支持这一点。已附加的图片在重启后依然存在，而浏览器路径、提供方 URL、本地存储路径与 base64 绝不会进入持久会话事件。只接受光栅格式（PNG、JPEG、WebP、GIF），未发送的输入区草稿在提交前仍留在浏览器中。已存储的图片永远不会被自动删除，通用文件、音频和视频暂不支持。

## 目录

- [使用本包](#use-this-package)
- [理解实现](#understand-the-implementation)
- [进一步探索](#further-exploration)
- [模型体验](#model-experience)
- [已知限制与延期工作](#known-limitations-and-deferred-work)
- [开发备注](#dev-note)

-----

<a id="use-this-package"></a>
## 使用本包

图片附件端到端可用：把图片附加到提示词或命令，它会自动保存、显示在历史中并发送给模型，无需你再做任何操作。在默认 `dsh` 组合中一切都已接好；自行组合时，一个插件即可启用该能力。

### 在提示词中附加图片

在客户端 UI 中向用户提示词附加一张或多张图片。每个源图都会在你的消息被处理前接受检查、规范化为提供方无关的 8-bit sRGB/sRGBA 光栅并保存；如果任何一张图片被拒绝，整条消息都会失败且不会发布任何内容。支持的源格式为 PNG、JPEG、WebP 与 GIF；部署方分别控制源图限制、规范化存储限制与路由专用请求限制。下面这一个插件即可启用持久图片附件（随附的 base 组合已经挂载它）：

```yaml
- name: '@deepseek-ai/dsh-attachment-local'
```

### 把图片传给命令

接受图片输入的命令以相同方式接收附加图片。如果某个命令不接受图片，harness 会以错误消息拒绝，而不是静默丢弃。

### 在整个会话中复用图片

已保存的规范化图片会保留在对话历史中，并在后续轮次投影为确定性的路由尺寸请求版本；重启后，恢复的会话会显示并复用相同的图片。当前执行文件系统可以映射已存宿主对象时，请求描述符还会携带模型可检查的只读进程路径。回读历史或请求版本时，已存储的字节会与记录的内容比对，因此缺失、损坏或被替换的图片会以错误形式呈现，而不是错误的字节。

### 可能出什么问题

附加图片时可能被拒绝——格式不受支持、超出大小、像素或尺寸限制，或者字节与声明类型不符——此时整条消息失败。之后，如果磁盘上的图片被删除或损坏，历史读取也可能失败。失败带有稳定错误码，客户端与协议适配器可以用自己的措辞解释它们。

-----

<a id="understand-the-implementation"></a>
## 理解实现

<details>
<summary>实现细节——点击展开</summary>

本节解释 seam 背后的设计决策，以及实现用户可见行为的服务操作；可观察行为已在[使用本包](#use-this-package)中完整说明。

### 设计决策

- **事件前完成规范化与持久化。** 每个源图都会在批次按序发布前完成准备与校验，因此会话日志绝不会引用部分完成或规范化失败的对象。
- **不可变且保留策略中立。** 对象一经发布即不可变；恢复和 fork 后的会话可能共享它们，因此引用感知的垃圾回收被推迟，而不是与任何单个会话的删除绑定。
- **读取时校验。** 读取在返回前把字节和元数据与记录的引用比对，请求投影还会完整解码缓存字节，因此缺失、损坏或被替换的对象都会失败关闭。
- **角色无关的图片块。** `dsh-llm` 中的 `ImageBlock` 内容块携带 `ImageAttachmentRef`；提供方适配器以显式像素与字节预算把引用解析为确定性请求版本，执行文件系统则可以把不可变宿主对象映射为模型可读的进程路径。
- **按错误码路由。** `AttachmentError` 重新实现 `HarnessError` 的结构而不是继承它，因为基类位于 `dsh-llm`，而后者依赖本包；消费方按 `code` 路由，绝不依赖原型链。

### 服务操作

服务族运行同一条准入与存储流程：每个入口都强制执行源批次限制与规范 base64，在发布任何成员前准备提供方无关的规范化附件，再按输入顺序持久提交而不产生部分结果。`readImageRequest` 派生确定性的路由尺寸变体，其身份包含附件 id、变换版本、像素与字节预算及编码参数。纯函数导出 `requestImageDimensions` 会按总像素预算计算每个投影保持宽高比的尺寸，使提供方与请求定价共享同一套几何计算。`imageHostPath` 只向需要执行世界映射的受信任同进程消费方暴露实现拥有的宿主位置。调用方组合有序批次，而实现拥有压缩并发、缓存与 singleflight。读取和投影保留调用方的取消语义。失败带有稳定且机器可读的错误码，运行时即可识别可由调用方修正的准入子集，让每个协议适配器映射自己的词汇；各操作的确切约定见 [`src/index.ts`](src/index.ts) 与 [`src/error.ts`](src/error.ts)。

### 源码地图

| 文件 | 职责 |
|---|---|
| [`src/index.ts`](src/index.ts) | 插件入口：抽象 `AttachmentStore` 服务与再导出 |
| [`src/types.ts`](src/types.ts) | 持久词汇：引用、限额、上传与存储载荷 |
| [`src/admission.ts`](src/admission.ts) | `admitEncodedImages`：规范 base64 强制，随后委托 `saveImages` |
| [`src/error.ts`](src/error.ts) | `AttachmentError` 类与 `isImageAdmissionError` 运行时子集 |
| [`src/brand.ts`](src/brand.ts) | `AttachmentId` 带类型标记的不透明标识符 |
| [`src/invariant.ts`](src/invariant.ts) | 不变式伴生插件（无运行时不变式；实现负责强制不可变存储检查） |

</details>

-----

<a id="further-exploration"></a>
## 进一步探索

完整的服务约定与载荷类型请看子系统参考；支撑这一能力的存储请看本地后端。

- [附件子系统参考](../../../docs/subsystems/attachment.zh.md)——服务约定、载荷类型与 `ctx.attachments` 的 cordis 接口面。
- [本地文件系统后端](../attachment-local/README.zh.md)——你的附加图片在本机上的存储位置。
- [能力 seam](../../../docs/capability-seams.zh.md)——本能力家族如何拆分为多个角色。

-----

<a id="model-experience"></a>
## 模型体验

该包通过提供方适配器间接影响模型；适配器会把每个持久引用解析为确切请求版本，并在图片旁发送稳定附件 id 与实际尺寸。执行文件系统可以映射已存对象时，描述符还会包含只读进程路径，以及可写副本使用的匹配扩展名。

#### KV Cache 影响

添加图片会改变提供方请求，因此会使受影响的请求后缀失效。

## 已知限制与延期工作

<a id="known-limitations-and-deferred-work"></a>


这些限制描述了图片附件能做什么、不能做什么；它们是当前包约束，而非任务积压。

- **仅支持光栅图片**——接受 PNG、JPEG、WebP 与 GIF；通用文件、音频和视频暂不支持。
- **图片永远不会被删除**——已存储的图片无限期保留；没有任何机制自动移除它们。
- **未发送的草稿不会保存**——输入区草稿在提交消息前一直留在浏览器中。

<a id="dev-note"></a>
### 开发备注

<details>
<summary>维护者的工作上下文——点击展开</summary>

本开发备注是维护者的工作上下文：尚未决定的探索方向与开放问题。它明确不具权威性——已交付的行为与限制以上文和包代码为准。

#### 未来：引用感知的垃圾回收

恢复和 fork 后的会话可能共享不可变对象，因此任何保留策略都需要一个能考虑会话血缘的引用模型，之后才能回收对象。目前尚未记录任何决定；本地后端当前保留一切。

#### 未来：非图片附件与助手侧输出

通用文件、音频与视频需要单独的生命周期与提供方契约；角色无关的 `ImageBlock` 也把助手侧图片输出留作前瞻兼容——当前生产适配器声明只输出文本，因此只有用户内容携带图片。两个方向都尚未决定。

</details>
