# Agent Note: read_image 接受无扩展名图片路径

Status: implemented
Archived: 2026-09-04

[English](2026-08-28-read-image-extensionless-paths.md) | 中文

## 问题

`read_image` 只按扩展名把 `file_path` 映射到媒体类型，并拒绝没有扩展名的路径。因此，模型必须先创建一份改名副本，才能查看合法的无扩展名图片。向模型公开的规范化本地附件对象以内容摘要命名，不带扩展名，所以其已发布的只读路径也会触发同一项拒绝。

## 决定

`read_image` 把文件扩展名视为媒体类型声明。PNG、JPEG、WebP 与 GIF 扩展名选择各自声明的类型；其他非空扩展名在文件系统 I/O 前被拒绝，附件存储的完整解码会拒绝与字节不匹配的声明。对于无扩展名路径，工具通过 `ctx.fs` 在既有 `maxImageBytes` 和更严格的 `maxMessageImageBytes` 上限内读取文件，再由工具内部的 `sniffImageMediaType` 辅助函数识别四种受支持的文件签名。识别结果经过同一套部署媒体类型策略和 `saveImage` 准入，后者的完整解码保持权威。这把[最小 read_image 工具 Agent Note](../feature/2026-08-10-minimal-read-image-tool.zh.md)中对嗅探的拒绝收窄到带扩展名的路径。

挂载的 `ctx.fs` 后端是 `read_image` 路径授权的完整依据。扩展名和文件签名只决定工具是否接受后端返回的字节。该后端可读的每个合法无扩展名图片都能进入当前会话，包括规范化附件对象；工具不证明 Session 引用，附件服务也不提供反向路径查找。

准入失败会指出出错路径。无扩展名路径的类型不匹配会指出提供声明的文件签名，而不受支持的字节不会出现在错误消息中。

## 考虑过的替代方案

**从附件 Service Definition 包导出文件签名识别。** 只有 `read_image` 需要这项准入前声明。公开该辅助函数会把单个消费方的文件名策略加入提供方无关的附件 API，而存储已经负责权威解码。

**特殊处理规范化附件对象路径。** 把路径反查为 Session 引用，会使 `ctx.fs` 以相同方式提供的两个文件根据来源产生不同读取结果，而且普通无扩展名图片仍然不受支持。文件系统访问保持读取授权决定。

**为存储的附件对象增加扩展名。** 这会为了满足一个工具的媒体类型声明规则而修改存储布局和每个对象路径消费方。

## 影响

模型可以在 native 和 PTC 模式下直接读取普通无扩展名图片与规范化附件路径。错误扩展名保留 I/O 前拒绝和类型不匹配修复提示。无扩展名非图片路径会在拒绝前读取到图片字节上限，规范化对象也会重新经过来源准入，而不会绕过当前部署限额。行为改动只位于 `dsh-tool-fs`；附件 Service Definition 与本地提供方保持现有 API 和存储行为。
