@deepseek-ai/dsh-tool-fs 0.1.2-alpha.2 → 0.1.2-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +7 -4
- package/README.zh.md +7 -4
- package/lib/index.js +53 -6
- package/lib/types/read-image.d.ts +10 -1
- package/package.json +28 -28
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/fs/tool-fs/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: f00c96d18619e0fb59609eb66729ebfce445dbc6
|
|
6
|
+
README.zh.md: 5915e5a07de10775469d0ebe301564948b357569
|
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ The policy plugin is optional: without it the tools run against the bare provide
|
|
|
44
44
|
| Tool | Arguments | Behavior |
|
|
45
45
|
|---|---|---|
|
|
46
46
|
| `read` | `file_path`, `offset?`, `limit?` | Line-numbered UTF-8 content with a pagination footer; `offset` is 1-based and `limit` defaults to and caps at the configured `readLimit` |
|
|
47
|
-
| `read_image` | `file_path` | Reads and persists a PNG/JPEG/WebP/GIF source; normalization can downscale it before the next model request, so the model need not create a thumbnail first |
|
|
47
|
+
| `read_image` | `file_path` | Reads and persists a PNG/JPEG/WebP/GIF source; an extension-less path (normalized attachment object paths included) is identified from its file signature; normalization can downscale it before the next model request, so the model need not create a thumbnail first |
|
|
48
48
|
| `write` | `file_path`, `content` | Creates or fully replaces a file; with the policy plugin, overwriting requires a prior `read` at the unchanged version, creating does not |
|
|
49
49
|
| `edit` | `file_path`, `old_string`, `new_string`, `replace_all?` | Literal replacement requiring a unique match unless `replace_all` is true; with the policy plugin, requires a prior `read` and an unchanged file |
|
|
50
50
|
|
|
@@ -65,6 +65,8 @@ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-a
|
|
|
65
65
|
|
|
66
66
|
### Policy and sandbox behavior
|
|
67
67
|
|
|
68
|
+
Path authorization for `read` and `read_image` belongs entirely to `ctx.fs`; media-type declarations and file signatures only decide whether `read_image` accepts the bytes returned by that backend.
|
|
69
|
+
|
|
68
70
|
With the policy plugin mounted, `write` and `edit` obtain their guard from the `fs/*` intent slots, so an unread target or a stale observation fails with `FS_NOT_OBSERVED` or `FS_STALE_VERSION` and a recovery instruction. Under a confining backend (`fs-sandbox`), `write`/`edit` additionally advertise `sandbox_permissions` and `justification`; a denied mutation returns the `[sandbox: file access denied under <mode> mode]` marker with the same-turn escalation hint, and an approved retry may stamp a strictly wider mode for that one call.
|
|
69
71
|
|
|
70
72
|
### Failures and recovery
|
|
@@ -219,7 +221,7 @@ Append-only; newly visible content follows the reusable request prefix and does
|
|
|
219
221
|
|
|
220
222
|
#### What the model sees
|
|
221
223
|
|
|
222
|
-
Failures are normalized as `Error: <message>`. This package's stable validation and read messages are `file_path must be a non-empty string`, `limit must be less than or equal to <max>`, `old_string must be a non-empty string`, `old_string and new_string must differ`, `cannot read "<path>": not found`, `cannot read "<path>": not a regular file`, `offset <offset> is out of range for "<path>" (<total> lines)`, `cannot read "<path>": read_image
|
|
224
|
+
Failures are normalized as `Error: <message>`. This package's stable validation and read messages are `file_path must be a non-empty string`, `limit must be less than or equal to <max>`, `old_string must be a non-empty string`, `old_string and new_string must differ`, `cannot read "<path>": not found`, `cannot read "<path>": not a regular file`, `offset <offset> is out of range for "<path>" (<total> lines)`, `cannot read "<path>": the <ext> extension does not declare a supported image format; read_image accepts PNG/JPEG/WebP/GIF files, including extension-less files in those formats`, `cannot read "<path>": the file content is not a supported image format; read_image accepts PNG/JPEG/WebP/GIF`, `cannot read "<path>": the bytes do not decode as a supported PNG/JPEG/WebP/GIF image; the file may be truncated or corrupt`, `cannot read "<path>" as an image: model "<model>" does not declare image input; switch to an image-capable model to read images`, and the mismatch repair `cannot read "<path>": the <ext> extension declares <type>, but the bytes use a different image format; rename the file to match its actual format if it is PNG/JPEG/WebP/GIF, or convert it to one of those formats` (an extension-less mismatch reports `cannot read "<path>": the file signature claims <type>, but the bytes decode as a different image format; the file may be corrupt`). A failed 16-bit conversion reports `cannot read "<path>": the 16-bit PNG could not be converted to the normalized 8-bit sRGB form; convert it to an 8-bit PNG/JPEG/WebP and retry`. Provider and policy templates are quoted in their package READMEs. Guarded-mutation failures additionally carry their recovery instruction in the message, appended by this package's model-facing error wrapper: `FS_STALE_VERSION` gets `— re-read the file, then retry`, and `FS_NOT_OBSERVED` gets `— read the file, then retry`; the structured code is preserved. After that reread confirms absence, `edit` reports `FS_NOT_FOUND` instead of repeating a stale remedy, while `write` uses guarded creation.
|
|
223
225
|
|
|
224
226
|
#### Token effect
|
|
225
227
|
|
|
@@ -237,8 +239,9 @@ Append-only; newly visible content follows the reusable request prefix and does
|
|
|
237
239
|
These limits define when the tool suite is a poor fit or needs special operational care. They are current package constraints, not a general filesystem comparison or a task backlog.
|
|
238
240
|
|
|
239
241
|
- **No model-facing directory listing ships** — `ctx.fs.listDir` serves provider code such as skill discovery, while the sibling `dsh-tool-fs-search` package supplies ripgrep-backed `glob` and `grep` rather than extending the filesystem seam.
|
|
240
|
-
- **`read` handles UTF-8 text files only** — images use the separate
|
|
241
|
-
- **Extension-declared media type** —
|
|
242
|
+
- **`read` handles UTF-8 text files only** — images use the separate `read_image` tool; PDF, audio, and video remain deferred. A directory target is `FS_NOT_REGULAR_FILE`.
|
|
243
|
+
- **Extension-declared media type** — an extension selects the declared type and the attachment store's magic-byte validation stays authoritative; a correctly formatted image under a wrong extension is refused with the rename remedy rather than sniffed. Only a path with no extension is identified from its file signature.
|
|
244
|
+
- **Object paths re-enter source admission** — `read_image` on a normalized attachment object re-admits its bytes as a new source, so a deployment whose `maxImageBytes`/`maxMessageImageBytes` sit below the normalized-image byte budget can refuse an object path that `ctx.attachments.readImage` still serves; shipped defaults keep the normalized budget (4 MiB) far under the source caps (20 MiB).
|
|
242
245
|
- **No inline image preview on the tool-result card** — UI surfaces render the image result generically (the durable reference, not pixels); inline rendering is deferred to the UI packages.
|
|
243
246
|
- **No attachment-region tool** — an agent may crop an image through another available tool when it has a filesystem path; a pasted or dragged image without a path cannot be re-read at higher resolution.
|
|
244
247
|
- **No timeout surface** — `read`/`write`/`edit` take no timeout argument and declare no timeout budget; cancellation rides `exec.signal` only ([provider rationale](../README.md)).
|
package/README.zh.md
CHANGED
|
@@ -44,7 +44,7 @@ kind: "package-reference"
|
|
|
44
44
|
| 工具 | 参数 | 行为 |
|
|
45
45
|
|---|---|---|
|
|
46
46
|
| `read` | `file_path`、`offset?`、`limit?` | 带行号的 UTF-8 内容与分页 footer;`offset` 从 1 开始,`limit` 默认为配置的 `readLimit`,上限也为该值 |
|
|
47
|
-
| `read_image` | `file_path` | 读取并持久保存 PNG/JPEG/WebP/GIF
|
|
47
|
+
| `read_image` | `file_path` | 读取并持久保存 PNG/JPEG/WebP/GIF 源图;无扩展名路径(包括规范化附件对象路径)按文件签名识别格式;规范化可在下一次模型请求前缩小图片,因此模型无需先创建缩略图 |
|
|
48
48
|
| `write` | `file_path`、`content` | 创建或完整替换文件;有策略插件时,覆盖要求先在未变版本上执行 `read`,创建不需要 |
|
|
49
49
|
| `edit` | `file_path`、`old_string`、`new_string`、`replace_all?` | 字面量替换,除非 `replace_all` 为 true 否则要求唯一匹配;有策略插件时,要求先执行 `read` 且文件未变 |
|
|
50
50
|
|
|
@@ -65,6 +65,8 @@ kind: "package-reference"
|
|
|
65
65
|
|
|
66
66
|
### 策略与沙箱行为
|
|
67
67
|
|
|
68
|
+
`read` 与 `read_image` 的路径授权完全由 `ctx.fs` 负责;媒体类型声明和文件签名只决定 `read_image` 是否接受该后端返回的字节。
|
|
69
|
+
|
|
68
70
|
挂载策略插件后,`write` 与 `edit` 从 `fs/*` 意图槽位取得防护,因此未读目标或陈旧观察会以 `FS_NOT_OBSERVED` 或 `FS_STALE_VERSION` 及恢复指令失败。使用施加沙箱限制的后端(`fs-sandbox`)时,`write`/`edit` 还会公开 `sandbox_permissions` 与 `justification`;被拒绝的变更返回 `[sandbox: file access denied under <mode> mode]` 标记与同轮次升级提示,获批的重试可以在该次调用中加盖严格更宽的模式。
|
|
69
71
|
|
|
70
72
|
### 失败与恢复
|
|
@@ -219,7 +221,7 @@ Use the edit tool for targeted changes to existing UTF-8 text files. It replaces
|
|
|
219
221
|
|
|
220
222
|
#### 模型看到的内容
|
|
221
223
|
|
|
222
|
-
失败会规范化为 `Error: <message>`。本包稳定的校验和读取消息是 `file_path must be a non-empty string`、`limit must be less than or equal to <max>`、`old_string must be a non-empty string`、`old_string and new_string must differ`、`cannot read "<path>": not found`、`cannot read "<path>": not a regular file`、`offset <offset> is out of range for "<path>" (<total> lines)`、`cannot read "<path>": read_image
|
|
224
|
+
失败会规范化为 `Error: <message>`。本包稳定的校验和读取消息是 `file_path must be a non-empty string`、`limit must be less than or equal to <max>`、`old_string must be a non-empty string`、`old_string and new_string must differ`、`cannot read "<path>": not found`、`cannot read "<path>": not a regular file`、`offset <offset> is out of range for "<path>" (<total> lines)`、`cannot read "<path>": the <ext> extension does not declare a supported image format; read_image accepts PNG/JPEG/WebP/GIF files, including extension-less files in those formats`、`cannot read "<path>": the file content is not a supported image format; read_image accepts PNG/JPEG/WebP/GIF`、`cannot read "<path>": the bytes do not decode as a supported PNG/JPEG/WebP/GIF image; the file may be truncated or corrupt`、`cannot read "<path>" as an image: model "<model>" does not declare image input; switch to an image-capable model to read images`,以及类型不匹配的修复消息 `cannot read "<path>": the <ext> extension declares <type>, but the bytes use a different image format; rename the file to match its actual format if it is PNG/JPEG/WebP/GIF, or convert it to one of those formats`(无扩展名路径的不匹配报告 `cannot read "<path>": the file signature claims <type>, but the bytes decode as a different image format; the file may be corrupt`)。16-bit 转换失败会报告 `cannot read "<path>": the 16-bit PNG could not be converted to the normalized 8-bit sRGB form; convert it to an 8-bit PNG/JPEG/WebP and retry`。提供方和策略模板在各自包的 README 中逐字列出。防护变更失败还会在消息中携带恢复指令,由本包面向模型的错误包装追加:`FS_STALE_VERSION` 追加 `— re-read the file, then retry`,`FS_NOT_OBSERVED` 追加 `— read the file, then retry`;结构化错误码保持不变。该次重新读取确认缺失后,`edit` 会报告 `FS_NOT_FOUND`,而不会重复陈旧恢复指令;`write` 则使用带防护的创建。
|
|
223
225
|
|
|
224
226
|
#### Token 影响
|
|
225
227
|
|
|
@@ -237,8 +239,9 @@ Use the edit tool for targeted changes to existing UTF-8 text files. It replaces
|
|
|
237
239
|
这些限制说明工具套件何时不合适,或何时需要特别的运维注意。它们是当前包约束,不是通用文件系统对比或任务积压。
|
|
238
240
|
|
|
239
241
|
- **未交付面向模型的目录列表工具**:`ctx.fs.listDir` 服务于 skill(技能)发现等提供方代码,同级 `dsh-tool-fs-search` 包则提供基于 ripgrep 的 `glob` 与 `grep`,而不是扩展文件系统 seam。
|
|
240
|
-
- **`read` 只处理 UTF-8
|
|
241
|
-
-
|
|
242
|
+
- **`read` 只处理 UTF-8 文本文件**:图像使用独立的 `read_image` 工具;PDF、音频和视频仍延期处理。目录目标为 `FS_NOT_REGULAR_FILE`。
|
|
243
|
+
- **媒体类型按扩展名声明**:扩展名选择声明类型,附件存储的魔数校验保持权威;扩展名错误但格式正确的图像会得到改名修复提示,而不是被嗅探接受。只有没有扩展名的路径按文件签名识别格式。
|
|
244
|
+
- **对象路径重新走源准入**:对规范化附件对象调用 `read_image` 会把其字节作为新来源重新准入,因此把 `maxImageBytes`/`maxMessageImageBytes` 配置得低于规范化图片字节预算的部署可能拒绝 `ctx.attachments.readImage` 仍可读取的对象路径;默认配置下规范化预算(4 MiB)远低于源上限(20 MiB)。
|
|
242
245
|
- **工具结果卡片没有内嵌图像预览**:UI 表面以通用形式渲染图像结果(持久引用而非像素);内嵌渲染延后到 UI 包处理。
|
|
243
246
|
- **没有附件区域工具**:agent 在拥有文件系统路径时可以通过其他可用工具裁剪图片;没有路径的粘贴或拖入图片无法按更高分辨率重新读取。
|
|
244
247
|
- **没有超时接口**:`read`/`write`/`edit` 不接受超时参数,也不声明超时预算;取消只通过 `exec.signal` 传递(见[提供方理由](../README.zh.md))。
|
package/lib/index.js
CHANGED
|
@@ -850,7 +850,10 @@ function applyEditTool(ctx, sandbox) {
|
|
|
850
850
|
//#endregion
|
|
851
851
|
//#region lib/types/read-image.js
|
|
852
852
|
/**
|
|
853
|
-
* The model-facing `read_image` tool commits a PNG/JPEG/WebP/GIF file.
|
|
853
|
+
* The model-facing `read_image` tool commits a PNG/JPEG/WebP/GIF file. A path
|
|
854
|
+
* without a file extension is identified from its file signature, while the
|
|
855
|
+
* attachment service's full decode stays authoritative. The mounted `ctx.fs`
|
|
856
|
+
* backend owns path resolution and read access; names only declare media type.
|
|
854
857
|
*
|
|
855
858
|
* The route gate is deliberately stricter than the host upload preflight. An
|
|
856
859
|
* image-reading tool is useful only when the exact calling route can inspect
|
|
@@ -866,6 +869,41 @@ const IMAGE_EXTENSIONS = {
|
|
|
866
869
|
".webp": "image/webp",
|
|
867
870
|
".gif": "image/gif"
|
|
868
871
|
};
|
|
872
|
+
const PNG_SIGNATURE = [
|
|
873
|
+
137,
|
|
874
|
+
80,
|
|
875
|
+
78,
|
|
876
|
+
71,
|
|
877
|
+
13,
|
|
878
|
+
10,
|
|
879
|
+
26,
|
|
880
|
+
10
|
|
881
|
+
];
|
|
882
|
+
const JPEG_SIGNATURE = [
|
|
883
|
+
255,
|
|
884
|
+
216,
|
|
885
|
+
255
|
|
886
|
+
];
|
|
887
|
+
function matchesBytes(data, offset, expected) {
|
|
888
|
+
if (data.byteLength < offset + expected.length) return false;
|
|
889
|
+
return expected.every((byte, index) => data[offset + index] === byte);
|
|
890
|
+
}
|
|
891
|
+
function matchesAscii(data, offset, value) {
|
|
892
|
+
if (data.byteLength < offset + value.length) return false;
|
|
893
|
+
for (let index = 0; index < value.length; index += 1) if (data[offset + index] !== value.charCodeAt(index)) return false;
|
|
894
|
+
return true;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Identify the media type declared by a supported image file signature.
|
|
898
|
+
* @param data - file bytes read through the current filesystem backend.
|
|
899
|
+
* @returns the detected supported media type, or undefined for other bytes.
|
|
900
|
+
*/
|
|
901
|
+
function sniffImageMediaType(data) {
|
|
902
|
+
if (matchesBytes(data, 0, PNG_SIGNATURE)) return "image/png";
|
|
903
|
+
if (matchesBytes(data, 0, JPEG_SIGNATURE)) return "image/jpeg";
|
|
904
|
+
if (matchesAscii(data, 0, "GIF87a") || matchesAscii(data, 0, "GIF89a")) return "image/gif";
|
|
905
|
+
if (matchesAscii(data, 0, "RIFF") && matchesAscii(data, 8, "WEBP")) return "image/webp";
|
|
906
|
+
}
|
|
869
907
|
const IMAGE_VALUE_SCHEMA = {
|
|
870
908
|
type: "object",
|
|
871
909
|
additionalProperties: false,
|
|
@@ -939,6 +977,10 @@ async function assertImageCapableRoute(ctx, exec, requestedPath) {
|
|
|
939
977
|
const active = await llm.resolveModelInfo(provider, model, exec.signal);
|
|
940
978
|
if (active.inputModalities === void 0 || !active.inputModalities.includes("image")) throw new Error(`cannot read "${requestedPath}" as an image: model "${model}" does not declare image input; switch to an image-capable model to read images`);
|
|
941
979
|
}
|
|
980
|
+
/** Refuse a media type outside the deployment's accepted set, naming the offending path. */
|
|
981
|
+
function assertDeploymentAccepts(attachments, mediaType, displayPath) {
|
|
982
|
+
if (!attachments.imageLimits.mediaTypes.includes(mediaType)) throw new Error(`cannot read "${displayPath}": ${mediaType} images are not accepted by this deployment`);
|
|
983
|
+
}
|
|
942
984
|
/**
|
|
943
985
|
* Re-brand a structured image outcome into the durable attachment reference an
|
|
944
986
|
* `ImageBlock` carries.
|
|
@@ -1004,7 +1046,7 @@ function imageReadContent(value) {
|
|
|
1004
1046
|
function applyReadImageTool(ctx) {
|
|
1005
1047
|
ctx.tools.register(defineTool({
|
|
1006
1048
|
name: "read_image",
|
|
1007
|
-
description: "Read a PNG/JPEG/WebP/GIF file and return the image itself. Harness validates and downscales large supported images before the next model request, so use this tool directly instead of installing image libraries or creating thumbnails merely to inspect an image. Independent files may be read concurrently in small batches. Requires the current model to accept image input.",
|
|
1049
|
+
description: "Read a PNG/JPEG/WebP/GIF file and return the image itself. A path without a file extension is accepted; the format is detected from the file content, so normalized attachment paths can be passed directly without copying or renaming. Harness validates and downscales large supported images before the next model request, so use this tool directly instead of installing image libraries or creating thumbnails merely to inspect an image. Independent files may be read concurrently in small batches. Requires the current model to accept image input.",
|
|
1008
1050
|
parameters: { file_path: {
|
|
1009
1051
|
type: "string",
|
|
1010
1052
|
required: true,
|
|
@@ -1027,15 +1069,19 @@ function applyReadImageTool(ctx) {
|
|
|
1027
1069
|
isConcurrencySafe: () => true,
|
|
1028
1070
|
async execute(args, exec) {
|
|
1029
1071
|
if (args.file_path.trim().length === 0) throw new Error("file_path must be a non-empty string");
|
|
1030
|
-
const
|
|
1031
|
-
|
|
1072
|
+
const extension = extname(args.file_path).toLowerCase();
|
|
1073
|
+
const declared = imageMediaTypeForPath(args.file_path);
|
|
1074
|
+
if (declared === void 0 && extension !== "") throw new Error(`cannot read "${args.file_path}": the ${extension} extension does not declare a supported image format; read_image accepts PNG/JPEG/WebP/GIF files, including extension-less files in those formats`);
|
|
1032
1075
|
const attachments = ctx.get("attachments");
|
|
1033
1076
|
if (attachments === void 0) throw new Error(`cannot read "${args.file_path}" as an image: no attachment service is mounted`);
|
|
1034
|
-
if (
|
|
1077
|
+
if (declared !== void 0) assertDeploymentAccepts(attachments, declared, args.file_path);
|
|
1035
1078
|
await assertImageCapableRoute(ctx, exec, args.file_path);
|
|
1036
1079
|
const { target, info } = await resolveRegularReadTarget(ctx, exec, args.file_path);
|
|
1037
1080
|
const byteCap = Math.min(attachments.imageLimits.maxImageBytes, attachments.imageLimits.maxMessageImageBytes);
|
|
1038
1081
|
const data = await ctx.fs.readBytes(target, exec.signal, byteCap);
|
|
1082
|
+
const mediaType = declared ?? sniffImageMediaType(data);
|
|
1083
|
+
if (mediaType === void 0) throw new Error(`cannot read "${target.displayPath}": the file content is not a supported image format; read_image accepts PNG/JPEG/WebP/GIF`);
|
|
1084
|
+
if (declared === void 0) assertDeploymentAccepts(attachments, mediaType, target.displayPath);
|
|
1039
1085
|
let ref;
|
|
1040
1086
|
try {
|
|
1041
1087
|
ref = await attachments.saveImage({
|
|
@@ -1049,8 +1095,9 @@ function applyReadImageTool(ctx) {
|
|
|
1049
1095
|
if (error.code === "IMAGE_TOO_MANY_PIXELS") throw new Error(`cannot read "${target.displayPath}": the image exceeds the ${attachments.imageLimits.maxImagePixels}-pixel decoded-size limit; downscale the image and read the smaller copy`, { cause: error });
|
|
1050
1096
|
if (error.code === "IMAGE_TOO_LARGE") throw new Error(`cannot read "${target.displayPath}": the image cannot be stored within the deployment's byte limits; downscale the image and read the smaller copy`, { cause: error });
|
|
1051
1097
|
if (error.code === "ATTACHMENT_WRITE_FAILED" && /16-bit PNG/iu.test(error.message)) throw new Error(`cannot read "${target.displayPath}": the 16-bit PNG could not be converted to the normalized 8-bit sRGB form; convert it to an 8-bit PNG/JPEG/WebP and retry`, { cause: error });
|
|
1098
|
+
if (error.code === "INVALID_IMAGE" && declared === void 0) throw new Error(`cannot read "${target.displayPath}": the bytes do not decode as a supported PNG/JPEG/WebP/GIF image; the file may be truncated or corrupt`, { cause: error });
|
|
1052
1099
|
if (error.code !== "IMAGE_TYPE_MISMATCH") throw error;
|
|
1053
|
-
|
|
1100
|
+
if (declared === void 0) throw new Error(`cannot read "${target.displayPath}": the file signature claims ${mediaType}, but the bytes decode as a different image format; the file may be corrupt`, { cause: error });
|
|
1054
1101
|
throw new Error(`cannot read "${target.displayPath}": the ${extension} extension declares ${mediaType}, but the bytes use a different image format; rename the file to match its actual format if it is PNG/JPEG/WebP/GIF, or convert it to one of those formats`, { cause: error });
|
|
1055
1102
|
}
|
|
1056
1103
|
ctx.emit("fs/observed", target, {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The model-facing `read_image` tool commits a PNG/JPEG/WebP/GIF file.
|
|
2
|
+
* The model-facing `read_image` tool commits a PNG/JPEG/WebP/GIF file. A path
|
|
3
|
+
* without a file extension is identified from its file signature, while the
|
|
4
|
+
* attachment service's full decode stays authoritative. The mounted `ctx.fs`
|
|
5
|
+
* backend owns path resolution and read access; names only declare media type.
|
|
3
6
|
*
|
|
4
7
|
* The route gate is deliberately stricter than the host upload preflight. An
|
|
5
8
|
* image-reading tool is useful only when the exact calling route can inspect
|
|
@@ -10,6 +13,12 @@
|
|
|
10
13
|
import type { Context } from '@deepseek-ai/cordis';
|
|
11
14
|
import type { ImageAttachmentRef, ImageMediaType } from '@deepseek-ai/dsh-attachment';
|
|
12
15
|
import type { ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
16
|
+
/**
|
|
17
|
+
* Identify the media type declared by a supported image file signature.
|
|
18
|
+
* @param data - file bytes read through the current filesystem backend.
|
|
19
|
+
* @returns the detected supported media type, or undefined for other bytes.
|
|
20
|
+
*/
|
|
21
|
+
export declare function sniffImageMediaType(data: Uint8Array): ImageMediaType | undefined;
|
|
13
22
|
/** The structured outcome declared by the `read_image` output schema. */
|
|
14
23
|
export interface ImageReadValue {
|
|
15
24
|
path: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-tool-fs",
|
|
3
3
|
"description": "Model-facing filesystem tools (read, write, edit) over the DeepSeek Harness filesystem seam (ctx.fs)",
|
|
4
|
-
"version": "0.1.2-alpha.
|
|
4
|
+
"version": "0.1.2-alpha.3",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -36,36 +36,36 @@
|
|
|
36
36
|
"@deepseek-ai/schemastery": "^3.18.2"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@deepseek-ai/dsh-attachment": "^0.1.2-alpha.
|
|
40
|
-
"@deepseek-ai/dsh-fs": "^0.1.2-alpha.
|
|
41
|
-
"@deepseek-ai/dsh-
|
|
42
|
-
"@deepseek-ai/dsh-
|
|
43
|
-
"@deepseek-ai/dsh-sandbox": "^0.1.2-alpha.
|
|
44
|
-
"@deepseek-ai/dsh-
|
|
45
|
-
"@deepseek-ai/dsh-
|
|
46
|
-
"@deepseek-ai/dsh-
|
|
39
|
+
"@deepseek-ai/dsh-attachment": "^0.1.2-alpha.3",
|
|
40
|
+
"@deepseek-ai/dsh-fs": "^0.1.2-alpha.3",
|
|
41
|
+
"@deepseek-ai/dsh-llm": "^0.1.2-alpha.3",
|
|
42
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.3",
|
|
43
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.2-alpha.3",
|
|
44
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.3",
|
|
45
|
+
"@deepseek-ai/dsh-session": "^0.1.2-alpha.3",
|
|
46
|
+
"@deepseek-ai/dsh-tools": "^0.1.2-alpha.3",
|
|
47
|
+
"@deepseek-ai/dsh-user-approval": "^0.1.2-alpha.3",
|
|
47
48
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
48
|
-
"@deepseek-ai/dsh-
|
|
49
|
-
"@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.2"
|
|
49
|
+
"@deepseek-ai/dsh-sandbox-policy": "^0.1.2-alpha.3"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@deepseek-ai/dsh-agent": "^0.1.2-alpha.
|
|
53
|
-
"@deepseek-ai/dsh-agent-loop": "^0.1.2-alpha.
|
|
54
|
-
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.2-alpha.
|
|
55
|
-
"@deepseek-ai/dsh-attachment": "^0.1.2-alpha.
|
|
56
|
-
"@deepseek-ai/dsh-fs
|
|
57
|
-
"@deepseek-ai/dsh-fs-
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-llm
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-sandbox
|
|
63
|
-
"@deepseek-ai/dsh-
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
65
|
-
"@deepseek-ai/dsh-tools": "^0.1.2-alpha.
|
|
66
|
-
"@deepseek-ai/dsh-user-approval": "^0.1.2-alpha.
|
|
52
|
+
"@deepseek-ai/dsh-agent": "^0.1.2-alpha.3",
|
|
53
|
+
"@deepseek-ai/dsh-agent-loop": "^0.1.2-alpha.3",
|
|
54
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.2-alpha.3",
|
|
55
|
+
"@deepseek-ai/dsh-attachment": "^0.1.2-alpha.3",
|
|
56
|
+
"@deepseek-ai/dsh-fs": "^0.1.2-alpha.3",
|
|
57
|
+
"@deepseek-ai/dsh-fs-local": "^0.1.2-alpha.3",
|
|
58
|
+
"@deepseek-ai/dsh-fs-observation-policy": "^0.1.2-alpha.3",
|
|
59
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.3",
|
|
60
|
+
"@deepseek-ai/dsh-llm": "^0.1.2-alpha.3",
|
|
61
|
+
"@deepseek-ai/dsh-llm-deepseek": "^0.1.2-alpha.3",
|
|
62
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.2-alpha.3",
|
|
63
|
+
"@deepseek-ai/dsh-sandbox-policy": "^0.1.2-alpha.3",
|
|
64
|
+
"@deepseek-ai/dsh-session": "^0.1.2-alpha.3",
|
|
65
|
+
"@deepseek-ai/dsh-tools": "^0.1.2-alpha.3",
|
|
66
|
+
"@deepseek-ai/dsh-user-approval": "^0.1.2-alpha.3",
|
|
67
67
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
68
|
-
"@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.
|
|
69
|
-
"@deepseek-ai/dsh-
|
|
68
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.3",
|
|
69
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.3"
|
|
70
70
|
}
|
|
71
71
|
}
|