@deepseek-ai/dsh-fs-local 0.1.3-alpha.2 → 0.1.5-alpha.1
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 +2 -2
- package/README.zh.md +2 -2
- package/lib/index.js +39 -0
- package/lib/types/fsio.d.ts +14 -0
- package/lib/types/index.d.ts +4 -0
- package/package.json +4 -4
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/fs-local/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 427cf02631f9d56246851f7fc67c92dd662c2a62
|
|
6
|
+
README.zh.md: 7009d9dd853b5443780978036792f10ebc9706b5
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
`dsh-fs-local`
|
|
12
|
+
Use `dsh-fs-local` to read, list, atomically write, and edit files on the host filesystem. Relative paths resolve from a configurable base directory, while absolute paths and parent traversal remain unrestricted. Paths and symlinks that reach the same file share one identity. Writes preserve file permissions, and optional version guards reject stale overwrites. Choose this package for direct host access; use `fs-sandbox` for confined mutations or `fs-e2b` for files in a remote execution world.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -50,7 +50,7 @@ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-a
|
|
|
50
50
|
|
|
51
51
|
### What you can do
|
|
52
52
|
|
|
53
|
-
Read any regular UTF-8 text file whole or as a stream, read raw bytes up to a cap you choose, and list one directory level in stable name order. Create or replace a file atomically, and apply a literal text edit atomically; both mutations serialize per file, so concurrent writers never interleave. The version guard is optional: omit it for unconditional create-or-overwrite, or supply it to fail when the file changed since you last observed it.
|
|
53
|
+
Read any regular UTF-8 text file whole or as a stream, read raw bytes up to a cap you choose or as one byte window, and list one directory level in stable name order. Create or replace a file atomically, and apply a literal text edit atomically; both mutations serialize per file, so concurrent writers never interleave. The version guard is optional: omit it for unconditional create-or-overwrite, or supply it to fail when the file changed since you last observed it.
|
|
54
54
|
|
|
55
55
|
Failures are typed `FsError`s with stable codes — `FS_NOT_FOUND`, `FS_NOT_TEXT` (binary content), `FS_STALE_VERSION` (changed since observation), `FS_EDIT_NOT_FOUND` or `FS_AMBIGUOUS_EDIT` (no unique literal match), and others — so callers branch on the code, never on message text. A missing target on a guarded edit reports `FS_STALE_VERSION` either way.
|
|
56
56
|
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@ kind: "package-reference"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
`dsh-fs-local`
|
|
12
|
+
使用 `dsh-fs-local` 可在宿主文件系统上读取、列出、原子写入和编辑文件。相对路径从可配置的基准目录解析,而绝对路径和父目录遍历不受限制。到达同一文件的路径和符号链接共享一个身份。写入保留文件权限,可选版本防护会拒绝陈旧覆盖。直接访问宿主文件时选择本包;需要约束变更时使用 `fs-sandbox`,文件位于远程执行世界时使用 `fs-e2b`。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -50,7 +50,7 @@ kind: "package-reference"
|
|
|
50
50
|
|
|
51
51
|
### 你能做什么
|
|
52
52
|
|
|
53
|
-
完整或流式读取任意普通 UTF-8
|
|
53
|
+
完整或流式读取任意普通 UTF-8 文本文件,按你选择的上限或按字节窗口读取原始字节,并按稳定名称顺序列出一层目录。原子地创建或替换文件,并原子地应用字面量文本编辑;两个变更操作都按文件串行化,并发写入方绝不会交错。版本防护是可选的:省略它即无条件创建或覆盖,提供它则在文件自上次观察以来发生变化时失败。
|
|
54
54
|
|
|
55
55
|
失败是携带稳定错误码的类型化 `FsError`——`FS_NOT_FOUND`、`FS_NOT_TEXT`(二进制内容)、`FS_STALE_VERSION`(自观察以来已变化)、`FS_EDIT_NOT_FOUND` 或 `FS_AMBIGUOUS_EDIT`(无唯一字面量匹配)等——因此调用方依据错误码分支,绝不解析消息文本。带防护的编辑遇到缺失目标时,无论哪种情况都报告 `FS_STALE_VERSION`。
|
|
56
56
|
|
package/lib/index.js
CHANGED
|
@@ -390,6 +390,39 @@ async function readWholeBytes(target, signal, maxBytes, internals = {}) {
|
|
|
390
390
|
return Buffer.concat(chunks, bytes);
|
|
391
391
|
}
|
|
392
392
|
/**
|
|
393
|
+
* Read the bytes at `[offset, offset + length)` of a regular file with no
|
|
394
|
+
* decoding or binary rejection. The window is the bound: the stream opens at
|
|
395
|
+
* `offset` and closes after `length` bytes, so no more than the window is ever
|
|
396
|
+
* buffered whatever the file's size; a window at or past the end is empty.
|
|
397
|
+
* @param target - the resolved file to read.
|
|
398
|
+
* @param range - `offset`, the 0-based first byte, and `length`, the largest byte count.
|
|
399
|
+
* @param signal - aborts the read (`FS_ABORTED`).
|
|
400
|
+
* @returns the window's bytes, at most `length` long.
|
|
401
|
+
*/
|
|
402
|
+
async function readByteWindow(target, range, signal) {
|
|
403
|
+
await statRegularFile(target, "read", signal);
|
|
404
|
+
if (range.length === 0) return new Uint8Array(0);
|
|
405
|
+
const stream = createReadStream(target.targetKey, {
|
|
406
|
+
start: range.offset,
|
|
407
|
+
end: range.offset + range.length - 1,
|
|
408
|
+
...signal ? { signal } : {}
|
|
409
|
+
});
|
|
410
|
+
const chunks = [];
|
|
411
|
+
let bytes = 0;
|
|
412
|
+
try {
|
|
413
|
+
for await (const chunk of stream) {
|
|
414
|
+
chunks.push(chunk);
|
|
415
|
+
bytes += chunk.length;
|
|
416
|
+
}
|
|
417
|
+
} catch (error) {
|
|
418
|
+
/* v8 ignore next 2 -- a mid-stream abort needs cancellation racing an active read; pre-abort is deterministic. */
|
|
419
|
+
if (isAbortError(error)) throw new FsError("read aborted", "FS_ABORTED");
|
|
420
|
+
/* v8 ignore next -- any other stream failure needs an I/O fault after a successful stat. */
|
|
421
|
+
throw error;
|
|
422
|
+
}
|
|
423
|
+
return Buffer.concat(chunks, bytes);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
393
426
|
* Stream a whole regular UTF-8 text file as decoded text chunks. Same text
|
|
394
427
|
* semantics as {@link readWholeText} (regular-file check, binary/NUL rejection,
|
|
395
428
|
* cross-chunk UTF-8 decoding), but never holds the whole file in memory.
|
|
@@ -764,6 +797,12 @@ var LocalFileSystem = class extends FileSystem {
|
|
|
764
797
|
targetKey: target.targetKey
|
|
765
798
|
}, signal, maxBytes, this.internals);
|
|
766
799
|
}
|
|
800
|
+
async readByteRange(target, range, signal) {
|
|
801
|
+
return readByteWindow({
|
|
802
|
+
displayPath: target.displayPath,
|
|
803
|
+
targetKey: target.targetKey
|
|
804
|
+
}, range, signal);
|
|
805
|
+
}
|
|
767
806
|
async listDir(target, signal) {
|
|
768
807
|
return (await listDirectory({
|
|
769
808
|
displayPath: target.displayPath,
|
package/lib/types/fsio.d.ts
CHANGED
|
@@ -114,6 +114,20 @@ export declare function readWholeText(target: LocalTarget, signal?: AbortSignal)
|
|
|
114
114
|
* @returns the full raw content, at most `maxBytes` long.
|
|
115
115
|
*/
|
|
116
116
|
export declare function readWholeBytes(target: LocalTarget, signal: AbortSignal | undefined, maxBytes: number, internals?: FsIoInternals): Promise<Uint8Array>;
|
|
117
|
+
/**
|
|
118
|
+
* Read the bytes at `[offset, offset + length)` of a regular file with no
|
|
119
|
+
* decoding or binary rejection. The window is the bound: the stream opens at
|
|
120
|
+
* `offset` and closes after `length` bytes, so no more than the window is ever
|
|
121
|
+
* buffered whatever the file's size; a window at or past the end is empty.
|
|
122
|
+
* @param target - the resolved file to read.
|
|
123
|
+
* @param range - `offset`, the 0-based first byte, and `length`, the largest byte count.
|
|
124
|
+
* @param signal - aborts the read (`FS_ABORTED`).
|
|
125
|
+
* @returns the window's bytes, at most `length` long.
|
|
126
|
+
*/
|
|
127
|
+
export declare function readByteWindow(target: LocalTarget, range: {
|
|
128
|
+
offset: number;
|
|
129
|
+
length: number;
|
|
130
|
+
}, signal?: AbortSignal): Promise<Uint8Array>;
|
|
117
131
|
/**
|
|
118
132
|
* Stream a whole regular UTF-8 text file as decoded text chunks. Same text
|
|
119
133
|
* semantics as {@link readWholeText} (regular-file check, binary/NUL rejection,
|
package/lib/types/index.d.ts
CHANGED
|
@@ -53,6 +53,10 @@ export declare class LocalFileSystem extends FileSystem {
|
|
|
53
53
|
readText(target: FsTarget, signal?: AbortSignal): Promise<string>;
|
|
54
54
|
streamText(target: FsTarget, signal?: AbortSignal): Promise<AsyncIterable<string>>;
|
|
55
55
|
readBytes(target: FsTarget, signal: AbortSignal | undefined, maxBytes: number): Promise<Uint8Array>;
|
|
56
|
+
readByteRange(target: FsTarget, range: {
|
|
57
|
+
offset: number;
|
|
58
|
+
length: number;
|
|
59
|
+
}, signal?: AbortSignal): Promise<Uint8Array>;
|
|
56
60
|
listDir(target: FsTarget, signal?: AbortSignal): Promise<FsDirEntry[]>;
|
|
57
61
|
writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal): Promise<FsWriteOutcome>;
|
|
58
62
|
editText(target: FsTarget, edit: FsEditRequest, expected?: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-fs-local",
|
|
3
3
|
"description": "Local-filesystem implementation of the DeepSeek Harness filesystem seam (ctx.fs)",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5-alpha.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
],
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@deepseek-ai/dsh-fs": "^0.1.
|
|
30
|
+
"@deepseek-ai/dsh-fs": "^0.1.5-alpha.1",
|
|
31
31
|
"@deepseek-ai/cordis": "^4.0.2"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@deepseek-ai/schemastery": "^3.18.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@deepseek-ai/dsh-fs": "^0.1.
|
|
39
|
-
"@deepseek-ai/dsh-llm": "^0.1.
|
|
38
|
+
"@deepseek-ai/dsh-fs": "^0.1.5-alpha.1",
|
|
39
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-alpha.1",
|
|
40
40
|
"@deepseek-ai/cordis": "^4.0.2"
|
|
41
41
|
}
|
|
42
42
|
}
|