@deepseek-ai/dsh-fs 0.0.1-rc.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/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, DeepSeek
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,6 @@
1
+ # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
2
+ # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
+ # after editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write packages/fs/fs/README.md
5
+ README.md: 62d3febde82e013ace054a9e6242147c1756b0d1
6
+ README.zh.md: 137c1e8da1014bf7dda7c4bf2e667aca6d2f51b5
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # @deepseek-ai/dsh-fs
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ The **`FileSystem`** (`ctx.fs`) defines the storage primitives in one execution world — resolve paths, expose canonical process paths and file URIs, test containment, read whole or streaming text, inspect/list metadata, write atomically, and apply a literal edit — without saying HOW. Both mutations take their version guard **optionally**, so `ctx.fs` on its own is a complete, unconstrained text-storage seam. This package also owns the `fs/*` policy event vocabulary the tool dispatches and the policy plugin listens for.
6
+
7
+ This package owns the Service Definition and provider contract layer of the four-layer filesystem stack, split so each concern can evolve (and be swapped) independently (see [the capability-seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md), [the filesystem capability-seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.md), [the split-the-filesystem-seam Agent Note](../../../.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md), and [the file-context event-gate Agent Note](../../../.agents/notes/implemented/architecture/2026-06-26-file-context-as-event-gate.md)):
8
+
9
+ | Layer | Package | Role |
10
+ |---|---|---|
11
+ | tool / executor | `@deepseek-ai/dsh-tool-fs` | model-facing `read`/`write`/`edit` schemas + read windowing + text rendering; reads/writes/edits via `ctx.fs`, dispatches the `fs/*` events |
12
+ | policy | `@deepseek-ai/dsh-fs-policy` | observed-state + read-before-edit + version-guarded write/edit, contributed through the `fs/*` event gate (no service) |
13
+ | provider contract | `@deepseek-ai/dsh-fs` (this) | `ctx.fs`: execution-world paths, text IO, and atomic mutation primitives (optional version guard); owns the `fs/*` event vocabulary |
14
+ | provider | `@deepseek-ai/dsh-fs-local` | the host-filesystem implementation |
15
+
16
+ `fs-sandbox` and `fs-e2b` implement this interface without touching the policy/tool layers.
17
+
18
+ ## Service API (`ctx.fs`)
19
+
20
+ A backend subclasses `FileSystem` and implements eleven primitives.
21
+
22
+ | Member | Semantics |
23
+ |---|---|
24
+ | `resolve(path, opts?)` | Resolve a path into a stable `FsTarget` (opaque `targetKey`, `displayPath`). `opts.cwd` is the base a relative `path` resolves against (a caller supplies its session workspace; absolute paths ignore it; omitted ⇒ the backend default), while `opts.signal` aborts a backend round-trip. Async — a remote backend may need I/O. The same file via different paths must yield the same `targetKey`. |
25
+ | `processPath(target)` | Return the canonical absolute path that a subprocess in this provider's execution world can open. This is intentionally distinct from opaque `targetKey`. |
26
+ | `fileUrl(target)` | Return the canonical `file:` URI in the execution world's platform syntax. The backend, not the host process, owns encoding. |
27
+ | `contains(parent, child)` | Test canonical identity/descendant containment without exposing or parsing target keys. Both targets come from this provider. |
28
+ | `stat(target, signal?)` | Return `FsInfo` metadata (`version`, `type`, optional `size`), or `undefined` when the target is absent. Never content. |
29
+ | `lstat(path, opts?, signal?)` | Return `FsPathInfo` metadata without following the final path component when it is a symlink. This is path-shaped so consumers can reject repository-owned symlinks before `resolve` follows them into a target. |
30
+ | `readText(target, signal?)` | Read the whole regular text file as one decoded string. Owns regular-file checks, UTF-8 decoding, binary/NUL rejection (`FS_NOT_TEXT`). |
31
+ | `streamText(target, signal?)` | Stream the same text as decoded chunks for large files (cross-chunk UTF-8 decoding stays here); consumers that need a byte ceiling enforce it while consuming the stream. |
32
+ | `listDir(target, signal?)` | List direct directory children in stable name order. Returns entry names, entry types, resolved child targets, and cheap metadata (`version`/file `size` when available); never reads file contents. Missing targets throw `FS_NOT_FOUND`, non-directories throw `FS_NOT_DIRECTORY`, permission failures throw `FS_PERMISSION_DENIED`, and other backend I/O failures throw `FS_IO_ERROR`. Broken/disappeared children may be returned as `other` without metadata; child permission/IO failures fail the whole listing with the same structured codes. |
33
+ | `writeText(target, content, expected?, signal?)` | Atomic create/replace. `expected` is OPTIONAL: omit ⇒ unconditional create-or-overwrite; supply an `FsWriteIntent` (`createIfAbsent`/`replaceIfVersion`) to guard. `createIfAbsent` must perform a no-replace publication so a creator racing the initial probe is preserved. |
34
+ | `editText(target, edit, expected?, signal?)` | Literal edit. `expected` is OPTIONAL: omit ⇒ unconditional edit of the current content; supply `{ version }` to guard (verified BEFORE matching). A missing target reports `FS_STALE_VERSION` either way. Applies and writes atomically — one mutation critical section. |
35
+
36
+ The mutation runs inside the backend's per-target lock either way, so an unconditional write/edit is still atomic — "unconditional" drops the *version* precondition, not the atomicity.
37
+
38
+ ## The `fs/*` policy events
39
+
40
+ This package declares three events (see the generated region of [filesystem.md](../../../docs/subsystems/filesystem.md#cordis-surface)) so the emitter (`@deepseek-ai/dsh-tool-fs`) and the policy listener (`@deepseek-ai/dsh-fs-policy`) share a vocabulary without the emitter depending on the policy plugin. `fs/write-intent` and `fs/edit-intent` are single-slot decision waterfalls (the listener fully decides, never calling `next()`); `fs/observed` is a fire-and-forget recording event carrying an `FsObservation` discriminated union: present with a version or confirmed absent. They carry only `dsh-fs` vocabulary plus an opaque `object` actor — no model-facing concepts and no agent/session owner structure.
41
+
42
+ ## A provider contract, not the policy layer
43
+
44
+ `ctx.fs` is deliberately close to fsspec-style storage primitives — half a level above byte-level `cat`/`open`, because it decodes text and rejects binaries so the policy layer never touches raw bytes. It owns UTF-8 decoding, binary rejection, atomic writes, and the literal-edit critical section. It does **not** own line windows, numbered lines, rendered footers, or observed-state. Observed-state, read-before-edit, and version-guarded write/edit are policy a plugin (`@deepseek-ai/dsh-fs-policy`) ADDS by supplying the optional guard — not provider behavior — so a sandboxed/remote backend inherits no model-facing observation policy.
45
+
46
+ `editText` stays on this seam (not composed in the policy layer from a read plus a write) because version guard + literal match + atomic rewrite must stay inside one critical section for correct error attribution and one-wins/one-stale concurrency, and a remote backend may implement it as a native compare-and-edit.
47
+
48
+ ## Vocabulary
49
+
50
+ `FsTargetKey` / `FsVersion` are branded opaque ids ([the branded-ids Agent Note](../../../.agents/notes/implemented/architecture/2026-06-20-branded-ids.md)) — consumers must not parse `targetKey` or interpret `version`; only `displayPath` is for model/UI output. `FsObservation` distinguishes `{ kind: 'present', version }` from `{ kind: 'absent' }`, so a policy can separate an unseen target from confirmed absence without performing I/O. `FsWriteIntent` is the explicit GUARDED write intent (`createIfAbsent` creates a missing target and rejects an existing one with `FS_NOT_OBSERVED`; `replaceIfVersion` replaces only at the observed version, else `FS_STALE_VERSION`); omitting it from `writeText` is the third, unconditional state. `FsPathInfo` is the no-follow metadata shape that can report `symlink`, unlike target-level `FsInfo`. Failures throw `FsError` (extends `HarnessError`, [the structured error taxonomy Agent Note](../../../.agents/notes/implemented/architecture/2026-06-11-structured-error-taxonomy.md)) carrying a stable `FsErrorCode` (`FS_NOT_FOUND`, `FS_NOT_DIRECTORY`, `FS_NOT_TEXT`, `FS_NOT_REGULAR_FILE`, `FS_PERMISSION_DENIED`, `FS_IO_ERROR`, `FS_STALE_VERSION`, `FS_NOT_OBSERVED`, `FS_AMBIGUOUS_EDIT`, `FS_EDIT_NOT_FOUND`, `FS_ABORTED`); the tool registry surfaces `{ name, code }` on `isError` results. See `src/types.ts` for the full contracts.
51
+
52
+ ## Model Experience
53
+
54
+ Indirectly, through `dsh-tool-fs`, which renders provider text and errors as bounded, retained filesystem tool results.
55
+
56
+ #### KV Cache effect
57
+
58
+ No direct invalidation; the named consumer owns any request-prefix changes.
59
+
60
+ ## Known Limitations and Deferred Work
61
+
62
+ - **Text-only by contract** — backends reject binary/non-UTF-8 content with `FS_NOT_TEXT`; binary-safe operations are a deliberate deferral of [the tool-schemas Agent Note](../../../.agents/notes/implemented/feature/2026-06-17-filesystem-tool-schemas.md).
63
+ - **Eleven primitives only** — no delete, rename/move, copy, or watch; `listDir` is single-level, with recursion, globbing, pagination, and search out of scope per [the directory-listing Agent Note](../../../.agents/notes/archived/architecture/2026-07-03-filesystem-directory-listing-seam.md).
64
+ - **No IO deadline** — the seam arms no timeout; cancellation is a best-effort optional `AbortSignal` per primitive (the deliberate [fs-family stance](../README.md)).
65
+ - **Resolve-then-operate costs a remote backend two round-trips per tool call** — folding or caching resolution is left to such a backend.
package/README.zh.md ADDED
@@ -0,0 +1,65 @@
1
+ # @deepseek-ai/dsh-fs
2
+
3
+ [English](README.md) | 中文
4
+
5
+ **`FileSystem`**(`ctx.fs`)定义同一个执行世界中的存储原语,包括解析路径、公开规范化进程路径与文件 URI、检查包含关系、完整或流式读取文本、检查/列出元数据、原子写入和应用字面量编辑,但不规定实现方式。两个变更操作都**可选** 接收版本防护,因此 `ctx.fs` 本身就是完整且不受约束的文本存储 seam。本包还拥有由工具分派、政策插件监听的 `fs/*` 政策事件词汇。
6
+
7
+ 本包是四层文件系统栈中的提供方约定层;该拆分使每个关注点可以独立演进和替换(见[能力 seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)、[文件系统能力 seam Agent Note](../../../.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.md)、[拆分文件系统 seam Agent Note](../../../.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md)和[文件上下文事件门禁 Agent Note](../../../.agents/notes/implemented/architecture/2026-06-26-file-context-as-event-gate.md)):
8
+
9
+ | 层 | 包 | 角色 |
10
+ |---|---|---|
11
+ | 工具/执行器 | `@deepseek-ai/dsh-tool-fs` | 面向模型的 `read`/`write`/`edit` schema、读取窗口和文本渲染;通过 `ctx.fs` 读取/写入/编辑,并分派 `fs/*` 事件 |
12
+ | 政策 | `@deepseek-ai/dsh-fs-policy` | 已观察状态、编辑前读取和版本防护的写入/编辑,通过 `fs/*` 事件门禁贡献(无服务) |
13
+ | 提供方约定 | `@deepseek-ai/dsh-fs`(本包) | `ctx.fs`:执行世界路径、文本 I/O 与原子变更原语(可选版本防护);拥有 `fs/*` 事件词汇 |
14
+ | 提供方 | `@deepseek-ai/dsh-fs-local` | 宿主文件系统实现 |
15
+
16
+ `fs-sandbox` 与 `fs-e2b` 实现该接口,无需更改政策层和工具层。
17
+
18
+ ## 服务 API(`ctx.fs`)
19
+
20
+ 后端继承 `FileSystem` 并实现十一个原语。
21
+
22
+ | 成员 | 语义 |
23
+ |---|---|
24
+ | `resolve(path, opts?)` | 把路径解析为稳定的 `FsTarget`(不透明 `targetKey`、`displayPath`)。`opts.cwd` 是相对 `path` 解析所依据的基准(调用方提供其会话工作区;绝对路径忽略该值;省略时使用后端默认值),`opts.signal` 则中止后端往返。该方法是异步的,因为远程后端可能需要 I/O。经不同路径到达的同一文件必须产生相同 `targetKey`。 |
25
+ | `processPath(target)` | 返回该提供方执行世界中的子进程可以打开的规范化绝对路径。该路径有意与不透明的 `targetKey` 分离。 |
26
+ | `fileUrl(target)` | 返回采用执行世界平台语法的规范化 `file:` URI。编码由后端而非宿主进程负责。 |
27
+ | `contains(parent, child)` | 在不公开或解析目标 key 的情况下,检查规范化身份相等或后代包含关系。两个目标都来自该提供方。 |
28
+ | `stat(target, signal?)` | 返回 `FsInfo` 元数据(`version`、`type`、可选 `size`);目标不存在时返回 `undefined`。绝不返回内容。 |
29
+ | `lstat(path, opts?, signal?)` | 当最后一个路径组件是符号链接时,不跟随该组件,返回 `FsPathInfo` 元数据。该方法采用路径形态,使消费方能在 `resolve` 跟随仓库所有的符号链接进入目标前拒绝它。 |
30
+ | `readText(target, signal?)` | 把整个普通文本文件读取为一个解码后的字符串。负责普通文件检查、UTF-8 解码和二进制/NUL 拒绝(`FS_NOT_TEXT`)。 |
31
+ | `streamText(target, signal?)` | 为大文件按解码后的分片流式读取相同文本(跨分片 UTF-8 解码仍由此处负责);需要字节上限的消费方在消费流时执行该上限。 |
32
+ | `listDir(target, signal?)` | 按稳定名称顺序列出直接子项。返回条目名称、条目类型、解析后的子目标和低成本元数据(若可用则包括 `version`/文件 `size`);绝不读取文件内容。缺失目标抛出 `FS_NOT_FOUND`,非目录抛出 `FS_NOT_DIRECTORY`,权限失败抛出 `FS_PERMISSION_DENIED`,其他后端 I/O 失败抛出 `FS_IO_ERROR`。损坏/消失的子项可以作为无元数据的 `other` 返回;子项权限/I/O 失败会使用相同结构化代码使整个列表失败。 |
33
+ | `writeText(target, content, expected?, signal?)` | 原子创建/替换。`expected` 是可选的:省略 ⇒ 无条件创建或覆盖;提供 `FsWriteIntent`(`createIfAbsent`/`replaceIfVersion`)⇒ 添加防护。`createIfAbsent` 必须以不替换的方式发布,使初始探测后抢先创建的文件得到保留。 |
34
+ | `editText(target, edit, expected?, signal?)` | 字面量编辑。`expected` 是可选的:省略 ⇒ 无条件编辑当前内容;提供 `{ version }` ⇒ 添加防护,并在匹配之前校验。无论哪种情况,目标缺失都报告 `FS_STALE_VERSION`。应用和写入以原子方式完成,使用同一个变更临界区。 |
35
+
36
+ 无论是否有版本防护,变更都在后端的每目标锁内运行,因此无条件写入/编辑仍是原子的;「无条件」只移除*版本*前置条件,不移除原子性。
37
+
38
+ ## `fs/*` 政策事件
39
+
40
+ 本包声明三个事件(见 [filesystem.md](../../../docs/subsystems/filesystem.md#cordis-surface) 的生成区块),使发出方(`@deepseek-ai/dsh-tool-fs`)和政策监听器(`@deepseek-ai/dsh-fs-policy`)共享词汇,而无需让发出方依赖政策插件。`fs/write-intent` 和 `fs/edit-intent` 是单槽决策 waterfall(监听器完整决策,绝不调用 `next()`);`fs/observed` 是发后即忘的记录事件,携带 `FsObservation` 可辨识联合:存在并带有版本,或确认缺失。它们只携带 `dsh-fs` 词汇和一个不透明 `object` 参与者,不含面向模型的概念或 agent(智能体)/会话所有者结构。
41
+
42
+ ## 提供方约定,不是政策层
43
+
44
+ `ctx.fs` 有意接近 fsspec 风格的存储原语,比字节级 `cat`/`open` 高半层,因为它会解码文本并拒绝二进制,使政策层绝不接触原始字节。它负责 UTF-8 解码、二进制拒绝、原子写入和字面量编辑临界区。它**不** 负责行窗口、编号行、渲染 footer 或已观察状态。已观察状态、编辑前读取和版本防护的写入/编辑属于插件(`@deepseek-ai/dsh-fs-policy`)通过提供可选防护而添加的政策,并非提供方行为,因此沙箱化/远程后端不会继承任何面向模型的观察政策。
45
+
46
+ `editText` 留在该 seam 上,不由政策层通过读取加写入组合,因为版本防护、字面量匹配和原子重写必须处于同一临界区内,才能正确归因错误并实现一方胜出/一方陈旧的并发;远程后端也可以将其实现为原生比较并编辑操作。
47
+
48
+ ## 词汇
49
+
50
+ `FsTargetKey` / `FsVersion` 是带品牌的不透明 id(见[品牌 id Agent Note](../../../.agents/notes/implemented/architecture/2026-06-20-branded-ids.md));消费方不得解析 `targetKey` 或解释 `version`,只有 `displayPath` 用于模型/UI 输出。`FsObservation` 区分 `{ kind: 'present', version }` 与 `{ kind: 'absent' }`,使策略无需执行 I/O 即可分辨未见目标和确认缺失。`FsWriteIntent` 是显式的防护写入意图(`createIfAbsent` 创建缺失目标,并以 `FS_NOT_OBSERVED` 拒绝现有目标;`replaceIfVersion` 只在观察版本上替换,否则为 `FS_STALE_VERSION`);从 `writeText` 中省略该值就是第三种无条件状态。`FsPathInfo` 是可报告 `symlink` 的不跟随链接元数据形态,区别于目标级 `FsInfo`。失败会抛出 `FsError`(继承 `HarnessError`;见[结构化错误分类 Agent Note](../../../.agents/notes/implemented/architecture/2026-06-11-structured-error-taxonomy.md)),并携带稳定的 `FsErrorCode`(`FS_NOT_FOUND`、`FS_NOT_DIRECTORY`、`FS_NOT_TEXT`、`FS_NOT_REGULAR_FILE`、`FS_PERMISSION_DENIED`、`FS_IO_ERROR`、`FS_STALE_VERSION`、`FS_NOT_OBSERVED`、`FS_AMBIGUOUS_EDIT`、`FS_EDIT_NOT_FOUND`、`FS_ABORTED`);工具注册表公开 `{ name, code }`,并将其附在 `isError` 结果上。完整约定见 `src/types.ts`。
51
+
52
+ ## 模型体验
53
+
54
+ 通过 `dsh-tool-fs` 间接产生影响;该消费方把提供方文本和错误渲染为有界且保留的文件系统工具结果。
55
+
56
+ #### KV Cache 影响
57
+
58
+ 不会直接使缓存失效;具名消费方负责请求前缀的任何变化。
59
+
60
+ ## 已知限制与延期工作
61
+
62
+ - **约定只支持文本**:后端以 `FS_NOT_TEXT` 拒绝二进制/非 UTF-8 内容;二进制安全操作是[工具 schema Agent Note](../../../.agents/notes/implemented/feature/2026-06-17-filesystem-tool-schemas.md)有意延期的工作。
63
+ - **只有十一个原语**:没有删除、重命名/移动、复制或监视;`listDir` 只支持一层,递归、glob、分页和搜索不在范围内,见[目录列出 Agent Note](../../../.agents/notes/archived/architecture/2026-07-03-filesystem-directory-listing-seam.md)。
64
+ - **没有 I/O deadline**:该 seam 不启动超时;取消只是每个原语上尽力而为的可选 `AbortSignal`(见有意采用的 [fs 能力族立场](../README.md))。
65
+ - **先解析后操作使远程后端每次工具调用需要两次往返**:折叠或缓存解析由这种后端自行决定。
package/lib/index.js ADDED
@@ -0,0 +1,77 @@
1
+ import { Service } from "@deepseek-ai/cordis";
2
+ import { HarnessError } from "@deepseek-ai/dsh-llm";
3
+ //#region lib/types/types.js
4
+ /**
5
+ * Vocabulary for the filesystem Service Definition (`ctx.fs`): the opaque target/version
6
+ * identities, the metadata `stat` returns, the write-intent and outcome shapes, the
7
+ * literal-edit request/outcome, and the typed error taxonomy.
8
+ * @module @deepseek-ai/dsh-fs/types
9
+ */
10
+ /**
11
+ * Brand a string as an {@link FsTargetKey}. For backend use only — a consumer
12
+ * never manufactures a key, it receives one from `resolve()`.
13
+ * @param key - the backend's raw key string (the local backend passes a realpath).
14
+ * @returns the same string, branded; no validation is performed.
15
+ */
16
+ function FsTargetKey(key) {
17
+ return key;
18
+ }
19
+ /**
20
+ * Brand a string as an {@link FsVersion}. For backend use only — a consumer
21
+ * never manufactures a version, it receives one from `stat`/write/edit outcomes.
22
+ * @param v - the backend's raw version string.
23
+ * @returns the same string, branded; no validation is performed.
24
+ */
25
+ function FsVersion(v) {
26
+ return v;
27
+ }
28
+ /**
29
+ * Typed filesystem error. Extends {@link HarnessError} so it carries a stable
30
+ * {@link FsErrorCode} and chains `cause`. `dsh-fs` owns this vocabulary so
31
+ * backends and the policy layer raise the same codes instead of each inventing
32
+ * message strings.
33
+ */
34
+ var FsError = class extends HarnessError {
35
+ code;
36
+ constructor(message, code, options) {
37
+ super(message, code, options);
38
+ this.code = code;
39
+ }
40
+ };
41
+ //#endregion
42
+ //#region lib/types/index.js
43
+ /**
44
+ * Filesystem Service Definition for one execution world. Backends own stable target
45
+ * identity, process paths and file URIs, containment, text reads, decoding,
46
+ * binary rejection, and atomic mutations. Read windows and
47
+ * observed-state policy stay in consumer and policy plugins; `editText`
48
+ * remains here so version check, literal match, and rewrite share one critical
49
+ * section.
50
+ * @module @deepseek-ai/dsh-fs
51
+ */
52
+ /**
53
+ * Abstract filesystem provider. Targets must preserve identity across aliases;
54
+ * reads expose regular UTF-8 text or typed errors, listings are stable and
55
+ * content-free, and mutations are atomic. Optional guards add stale protection
56
+ * without changing the unguarded provider contract.
57
+ */
58
+ var FileSystem = class extends Service {
59
+ constructor(ctx) {
60
+ super(ctx, "fs");
61
+ }
62
+ /**
63
+ * The sandbox mode this backend enforces on mutations BY DEFAULT, or
64
+ * `undefined` when it does not confine at all — the capability fact the tool
65
+ * layer reads to advertise the escalation fields honestly (mirrors
66
+ * `BashExecutor.sandboxMode`). The base class and the bare local backend
67
+ * report `undefined`; a sandboxing backend (`@deepseek-ai/dsh-fs-sandbox`)
68
+ * overrides it with the deployment default. A session override may make the
69
+ * effective mode narrower or wider, so strict escalation widening is checked
70
+ * per call rather than encoded in this default-relative fact.
71
+ * @returns the configured default mode of a sandboxing backend; `undefined`
72
+ * for a backend that never confines.
73
+ */
74
+ get sandboxMode() {}
75
+ };
76
+ //#endregion
77
+ export { FileSystem, FileSystem as default, FsError, FsTargetKey, FsVersion };
@@ -0,0 +1,37 @@
1
+ //#region lib/types/invariant.js
2
+ /** Package-owned filesystem event-data invariants. @module @deepseek-ai/dsh-fs/invariant */
3
+ const PACKAGE_NAME = "@deepseek-ai/dsh-fs";
4
+ /** Cordis companion plugin name. */
5
+ const name = "fs-invariant";
6
+ /** Service required before the companion can reserve package ownership. */
7
+ const inject = ["invariants"];
8
+ /** Assert that an event carries a usable opaque target identity. */
9
+ function validateTarget(target, fail) {
10
+ if (target.targetKey.length === 0) fail("filesystem event targetKey must be non-empty");
11
+ if (target.displayPath.length === 0) fail("filesystem event displayPath must be non-empty");
12
+ }
13
+ /** Install checks over the filesystem decision and observation event stream. */
14
+ const install = (ctx, fail) => {
15
+ ctx.on("internal/dispatch", (_mode, eventName, args) => {
16
+ if (eventName !== "fs/write-intent" && eventName !== "fs/edit-intent" && eventName !== "fs/observed") return;
17
+ validateTarget(args[0], fail);
18
+ if (eventName === "fs/observed") {
19
+ const observation = args[1];
20
+ switch (observation.kind) {
21
+ case "present":
22
+ if (observation.version.length === 0) fail("fs/observed present version must be non-empty");
23
+ break;
24
+ case "absent": break;
25
+ default: fail("fs/observed kind must be present or absent");
26
+ }
27
+ }
28
+ }, { global: true });
29
+ };
30
+ /**
31
+ * Register the filesystem invariant companion.
32
+ * @param ctx - Cordis context carrying the invariant service.
33
+ * @returns the installed registration's disposer after setup succeeds.
34
+ */
35
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
36
+ //#endregion
37
+ export { apply, inject, name };
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Filesystem Service Definition for one execution world. Backends own stable target
3
+ * identity, process paths and file URIs, containment, text reads, decoding,
4
+ * binary rejection, and atomic mutations. Read windows and
5
+ * observed-state policy stay in consumer and policy plugins; `editText`
6
+ * remains here so version check, literal match, and rewrite share one critical
7
+ * section.
8
+ * @module @deepseek-ai/dsh-fs
9
+ */
10
+ import { Context, Service } from '@deepseek-ai/cordis';
11
+ import type { SandboxExecutionPolicy, SandboxMode } from '@deepseek-ai/dsh-sandbox';
12
+ import type { FsDirEntry, FsEditOutcome, FsEditRequest, FsInfo, FsPathInfo, FsObservation, FsTarget, FsVersion, FsWriteIntent, FsWriteOutcome } from './types.ts';
13
+ export { FsError, FsTargetKey, FsVersion, } from './types.ts';
14
+ export type { FsEditOutcome, FsEditRequest, FsDirEntry, FsErrorCode, FsInfo, FsObservation, FsPathInfo, FsTarget, FsWriteIntent, FsWriteOutcome, } from './types.ts';
15
+ declare module '@deepseek-ai/cordis' {
16
+ interface Context {
17
+ fs: FileSystem;
18
+ }
19
+ interface Events {
20
+ /**
21
+ * Single-slot decision for the next {@link FileSystem.writeText}. Calling
22
+ * `next()` yields the bare provider's unconditional write; the first listener
23
+ * that returns an intent owns the decision rather than composing with peers.
24
+ * @param target - the resolved target about to be written.
25
+ * @param actor - the opaque tool-execution context the decider keys off.
26
+ * @mode waterfall
27
+ */
28
+ 'fs/write-intent'(target: FsTarget, actor: object | undefined, next: () => FsWriteIntent | undefined | Promise<FsWriteIntent | undefined>): Promise<FsWriteIntent | undefined>;
29
+ /**
30
+ * Single-slot decision for the next {@link FileSystem.editText}. Calling
31
+ * `next()` yields an unconditional edit; the first returned guard wins.
32
+ * @param target - the resolved target about to be edited.
33
+ * @param actor - the opaque tool-execution context the decider keys off.
34
+ * @mode waterfall
35
+ */
36
+ 'fs/edit-intent'(target: FsTarget, actor: object | undefined, next: () => {
37
+ version: FsVersion;
38
+ } | undefined | Promise<{
39
+ version: FsVersion;
40
+ } | undefined>): Promise<{
41
+ version: FsVersion;
42
+ } | undefined>;
43
+ /**
44
+ * Record an authoritative positive or negative observation. Listeners must
45
+ * be synchronous recorders: throws fail the tool call and returned promises
46
+ * are not awaited.
47
+ * @param target - the target whose presence or absence was observed.
48
+ * @param observation - present with its version, or confirmed absent.
49
+ * @param actor - the observing tool-execution context; undefined records nothing useful.
50
+ * @mode emit
51
+ */
52
+ 'fs/observed'(target: FsTarget, observation: FsObservation, actor: object | undefined): void;
53
+ }
54
+ }
55
+ /**
56
+ * Abstract filesystem provider. Targets must preserve identity across aliases;
57
+ * reads expose regular UTF-8 text or typed errors, listings are stable and
58
+ * content-free, and mutations are atomic. Optional guards add stale protection
59
+ * without changing the unguarded provider contract.
60
+ */
61
+ export declare abstract class FileSystem extends Service {
62
+ constructor(ctx: Context);
63
+ /**
64
+ * The sandbox mode this backend enforces on mutations BY DEFAULT, or
65
+ * `undefined` when it does not confine at all — the capability fact the tool
66
+ * layer reads to advertise the escalation fields honestly (mirrors
67
+ * `BashExecutor.sandboxMode`). The base class and the bare local backend
68
+ * report `undefined`; a sandboxing backend (`@deepseek-ai/dsh-fs-sandbox`)
69
+ * overrides it with the deployment default. A session override may make the
70
+ * effective mode narrower or wider, so strict escalation widening is checked
71
+ * per call rather than encoded in this default-relative fact.
72
+ * @returns the configured default mode of a sandboxing backend; `undefined`
73
+ * for a backend that never confines.
74
+ */
75
+ get sandboxMode(): SandboxMode | undefined;
76
+ /**
77
+ * Resolve a model/plugin-supplied path into a stable {@link FsTarget}. May perform I/O (a
78
+ * remote/sandboxed backend may need a round-trip to map a path to a stable identity), hence
79
+ * async even though the local backend only normalizes + realpaths.
80
+ *
81
+ * @param path - the path to resolve; relative paths resolve against `opts.cwd`.
82
+ * @param opts - optional cwd override and cancellation signal.
83
+ * @returns the stable target; the same file yields the same `targetKey`.
84
+ */
85
+ abstract resolve(path: string, opts?: {
86
+ cwd?: string;
87
+ signal?: AbortSignal;
88
+ }): Promise<FsTarget>;
89
+ /**
90
+ * Return the canonical absolute path a subprocess in this filesystem's
91
+ * execution world can open. The path is deliberately separate from
92
+ * {@link FsTarget.targetKey}: consumers may pass this value to another OS
93
+ * capability, but must continue treating the target key as opaque.
94
+ * @param target - the resolved target whose process path is required.
95
+ * @returns an absolute path in the backend's execution world.
96
+ */
97
+ abstract processPath(target: FsTarget): string;
98
+ /**
99
+ * Return the canonical `file:` URI for a target in this filesystem's
100
+ * execution world. Backends own URI encoding because the host platform may
101
+ * differ from the execution platform.
102
+ * @param target - the resolved target to encode.
103
+ * @returns the target's canonical file URI.
104
+ */
105
+ abstract fileUrl(target: FsTarget): string;
106
+ /**
107
+ * Test canonical containment without exposing or parsing backend target
108
+ * keys. Both targets must come from this provider.
109
+ * @param parent - canonical directory target.
110
+ * @param child - canonical candidate target.
111
+ * @returns true when `child` is `parent` or a descendant of it.
112
+ */
113
+ abstract contains(parent: FsTarget, child: FsTarget): boolean;
114
+ /**
115
+ * Return target metadata, or `undefined` when the target does not exist.
116
+ * @param target - the resolved target to stat.
117
+ * @param signal - aborts the metadata round-trip.
118
+ * @returns metadata only, never content; undefined for an absent target.
119
+ */
120
+ abstract stat(target: FsTarget, signal?: AbortSignal): Promise<FsInfo | undefined>;
121
+ /**
122
+ * Return path metadata without following the final path component when it is a
123
+ * symbolic link. This is intentionally path-shaped, not target-shaped:
124
+ * {@link resolve} follows symlinks to produce the stable identity used by
125
+ * normal reads/writes, while `lstat` lets a consumer reject the path itself
126
+ * before that follow happens.
127
+ *
128
+ * `opts.cwd` follows {@link resolve}'s cwd rules. `undefined` means the path is
129
+ * absent.
130
+ * @param path - the path to inspect; relative paths resolve against `opts.cwd`.
131
+ * @param opts - `cwd` overrides the backend's default base for relative paths.
132
+ * @param signal - aborts the metadata round-trip.
133
+ * @returns metadata only, never content; undefined for an absent path.
134
+ */
135
+ abstract lstat(path: string, opts?: {
136
+ cwd?: string;
137
+ }, signal?: AbortSignal): Promise<FsPathInfo | undefined>;
138
+ /**
139
+ * Read the whole regular text file as a single decoded string.
140
+ * @param target - the resolved target to read.
141
+ * @param signal - aborts the read.
142
+ * @returns the full decoded UTF-8 content.
143
+ */
144
+ abstract readText(target: FsTarget, signal?: AbortSignal): Promise<string>;
145
+ /**
146
+ * Stream the whole regular text file as decoded text chunks (same text
147
+ * semantics as {@link readText}, for large files). The backend owns
148
+ * cross-chunk UTF-8 decoding and binary rejection so the policy layer never
149
+ * touches raw bytes.
150
+ * @param target - the resolved target to read.
151
+ * @param signal - aborts the stream, including between chunks.
152
+ * @returns the chunk iterable, decoded and validated like {@link readText}.
153
+ */
154
+ abstract streamText(target: FsTarget, signal?: AbortSignal): Promise<AsyncIterable<string>>;
155
+ /**
156
+ * List direct children of a directory in stable name order. Returns resolved
157
+ * child targets plus cheap metadata only; never reads file contents.
158
+ * @param target - the resolved directory target.
159
+ * @param signal - aborts the listing.
160
+ * @returns one entry per direct child, in stable name order.
161
+ */
162
+ abstract listDir(target: FsTarget, signal?: AbortSignal): Promise<FsDirEntry[]>;
163
+ /**
164
+ * Atomically create or replace UTF-8 text. `expected` guards intent and
165
+ * staleness; omission allows unconditional overwrite.
166
+ * @param target - the resolved target to write.
167
+ * @param content - the full new file content.
168
+ * @param expected - the write intent guarding the write; omit for unconditional.
169
+ * @param signal - aborts before atomic publication takes effect.
170
+ * @param sandboxPolicy - the per-call mode and workspace root this write
171
+ * runs under; a sandboxing backend fences the write by it, the bare backend
172
+ * ignores it. Omit to leave the backend its own default.
173
+ * @returns the outcome, including the version the write produced.
174
+ */
175
+ abstract writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal, sandboxPolicy?: SandboxExecutionPolicy): Promise<FsWriteOutcome>;
176
+ /**
177
+ * Atomically edit literal text. When supplied, the version guard is checked
178
+ * before matching so stale content reports `FS_STALE_VERSION`; omission edits
179
+ * the current content without a freshness precondition.
180
+ * @param target - the resolved target to edit.
181
+ * @param edit - the literal search/replace request.
182
+ * @param expected - the version guard; omit for an unconditional edit.
183
+ * @param signal - aborts before atomic publication takes effect.
184
+ * @param sandboxPolicy - the per-call mode and workspace root this edit runs
185
+ * under; a sandboxing backend fences the edit by it, the bare backend
186
+ * ignores it. Omit to leave the backend its own default.
187
+ * @returns the outcome, including the version the edit produced.
188
+ */
189
+ abstract editText(target: FsTarget, edit: FsEditRequest, expected?: {
190
+ version: FsVersion;
191
+ }, signal?: AbortSignal, sandboxPolicy?: SandboxExecutionPolicy): Promise<FsEditOutcome>;
192
+ }
193
+ export default FileSystem;
194
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,13 @@
1
+ /** Package-owned filesystem event-data invariants. @module @deepseek-ai/dsh-fs/invariant */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ /** Cordis companion plugin name. */
4
+ export declare const name = "fs-invariant";
5
+ /** Service required before the companion can reserve package ownership. */
6
+ export declare const inject: string[];
7
+ /**
8
+ * Register the filesystem invariant companion.
9
+ * @param ctx - Cordis context carrying the invariant service.
10
+ * @returns the installed registration's disposer after setup succeeds.
11
+ */
12
+ export declare const apply: (ctx: Context) => Promise<() => void>;
13
+ //# sourceMappingURL=invariant.d.ts.map
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Vocabulary for the filesystem Service Definition (`ctx.fs`): the opaque target/version
3
+ * identities, the metadata `stat` returns, the write-intent and outcome shapes, the
4
+ * literal-edit request/outcome, and the typed error taxonomy.
5
+ * @module @deepseek-ai/dsh-fs/types
6
+ */
7
+ import { HarnessError } from '@deepseek-ai/dsh-llm';
8
+ import type { Branded } from '@deepseek-ai/dsh-brand';
9
+ /**
10
+ * Opaque key for stale guards and target lookup. The local backend uses a
11
+ * realpath-like string; a remote backend might use a workspace URI or file id.
12
+ * Consumers MUST NOT parse it or assume it is a local absolute path.
13
+ */
14
+ export type FsTargetKey = Branded<'FsTargetKey'>;
15
+ /**
16
+ * Brand a string as an {@link FsTargetKey}. For backend use only — a consumer
17
+ * never manufactures a key, it receives one from `resolve()`.
18
+ * @param key - the backend's raw key string (the local backend passes a realpath).
19
+ * @returns the same string, branded; no validation is performed.
20
+ */
21
+ export declare function FsTargetKey(key: string): FsTargetKey;
22
+ /**
23
+ * Opaque file-version token — the freshness token a write/edit guards against.
24
+ * The local backend derives it from high-resolution stat identity and freshness
25
+ * fields; a remote backend might use a revision id. The policy layer records it
26
+ * for stale checks; consumers may display related metadata but MUST NOT
27
+ * interpret this token.
28
+ */
29
+ export type FsVersion = Branded<'FsVersion'>;
30
+ /**
31
+ * Brand a string as an {@link FsVersion}. For backend use only — a consumer
32
+ * never manufactures a version, it receives one from `stat`/write/edit outcomes.
33
+ * @param v - the backend's raw version string.
34
+ * @returns the same string, branded; no validation is performed.
35
+ */
36
+ export declare function FsVersion(v: string): FsVersion;
37
+ /**
38
+ * One authoritative observation of a target. A present observation carries the
39
+ * version used by guarded replacement; an absent observation authorizes only a
40
+ * guarded create, never an edit.
41
+ */
42
+ export type FsObservation = {
43
+ readonly kind: 'present';
44
+ readonly version: FsVersion;
45
+ } | {
46
+ readonly kind: 'absent';
47
+ };
48
+ /**
49
+ * A path resolved by a backend into a stable identity. `resolve()` produces
50
+ * this; every other operation takes it.
51
+ */
52
+ export interface FsTarget {
53
+ /** Opaque key for stale guards and target lookup. */
54
+ targetKey: FsTargetKey;
55
+ /**
56
+ * Path for model/UI-facing output. May be a local absolute path,
57
+ * workspace-relative path, or remote URI depending on the backend.
58
+ */
59
+ displayPath: string;
60
+ }
61
+ /**
62
+ * Metadata about a target — what {@link FileSystem.stat} returns. Lets the
63
+ * policy layer reject directories/special files before reading and choose
64
+ * `readText` vs `streamText` from `size` without probing by failure. `version`
65
+ * is the freshness token. `undefined` from `stat` means the target is absent.
66
+ */
67
+ export interface FsInfo {
68
+ /** Opaque freshness token of the target right now. */
69
+ version: FsVersion;
70
+ /** Whether the target is a regular file, a directory, or something else. */
71
+ type: 'file' | 'directory' | 'other';
72
+ /** Byte size of a regular file, when the backend can report it. */
73
+ size?: number;
74
+ }
75
+ /**
76
+ * Metadata about a path without following the final path component when it is a
77
+ * symbolic link. Unlike {@link FsInfo}, this path-level probe can report
78
+ * `symlink` so consumers with trust-boundary rules can reject repository-owned
79
+ * links before resolving a target.
80
+ */
81
+ export interface FsPathInfo {
82
+ /** Opaque freshness token of the path entry right now. */
83
+ version: FsVersion;
84
+ /** Whether the path entry is a regular file, directory, symlink, or other. */
85
+ type: 'file' | 'directory' | 'symlink' | 'other';
86
+ /** Byte size of the path entry, when the backend can report it. */
87
+ size?: number;
88
+ }
89
+ /**
90
+ * One direct child returned by {@link FileSystem.listDir}. Listing returns
91
+ * metadata and resolved targets only; it must not read file contents.
92
+ */
93
+ export interface FsDirEntry {
94
+ /** Basename of the child inside the listed directory. */
95
+ name: string;
96
+ /** Whether the child is a regular file, a directory, or something else. */
97
+ type: 'file' | 'directory' | 'other';
98
+ /** Resolved child target for follow-up operations. */
99
+ target: FsTarget;
100
+ /** Opaque freshness token when the backend can report metadata cheaply. */
101
+ version?: FsVersion;
102
+ /** Byte size of a regular file, when the backend can report it. */
103
+ size?: number;
104
+ }
105
+ /**
106
+ * Guarded write intent. `createIfAbsent` rejects an existing target with
107
+ * `FS_NOT_OBSERVED`; `replaceIfVersion` rejects absence or mismatch with
108
+ * `FS_STALE_VERSION`. Omitting the intent from `writeText` means unconditional
109
+ * create-or-overwrite, not a third union arm.
110
+ */
111
+ export type FsWriteIntent = {
112
+ kind: 'createIfAbsent';
113
+ } | {
114
+ kind: 'replaceIfVersion';
115
+ version: FsVersion;
116
+ };
117
+ /** Outcome of a full-file write. */
118
+ export interface FsWriteOutcome {
119
+ /** Whether the write created a new file or replaced an existing one. */
120
+ operation: 'create' | 'update';
121
+ /** Opaque version of the file after the write. */
122
+ version: FsVersion;
123
+ /**
124
+ * The file's content BEFORE the write, or `null` when the file did not exist
125
+ * (a create) or the backend declined a contextual basis (for example, a
126
+ * binary/non-UTF-8 prior file or either overwrite side reaching its exclusive limit).
127
+ * LF-normalized storage text (the diff basis), never a diff — a consumer
128
+ * computes the result-time contextual diff from `before`/`after` when
129
+ * `before` is present, else falls back to a whole-file diff.
130
+ */
131
+ before: string | null;
132
+ /** The file's content AFTER the write, LF-normalized to share `before`'s diff basis. */
133
+ after: string;
134
+ }
135
+ /** A literal-replacement edit request. */
136
+ export interface FsEditRequest {
137
+ /** Literal non-empty text to replace. Must match exactly (after line-ending normalization). */
138
+ oldString: string;
139
+ /** Literal replacement text. An empty string deletes the matched text. */
140
+ newString: string;
141
+ /** Replace every match instead of requiring exactly one. */
142
+ replaceAll: boolean;
143
+ }
144
+ /** Outcome of a literal edit. */
145
+ export interface FsEditOutcome {
146
+ /** Opaque version of the file after the edit. */
147
+ version: FsVersion;
148
+ /**
149
+ * The file's content BEFORE the edit. Raw storage text (LF-normalized by the
150
+ * backend), never a diff — a consumer computes the result-time contextual diff
151
+ * (the applied hunk with context) from `before`/`after`.
152
+ */
153
+ before: string;
154
+ /** The file's content AFTER the edit. */
155
+ after: string;
156
+ }
157
+ /**
158
+ * Stable, machine-routable codes for filesystem failures. Carried on
159
+ * {@link FsError}; the tool registry surfaces `{ name, code }` on `isError`
160
+ * results so retry/permission/UI layers can branch without parsing messages.
161
+ */
162
+ export type FsErrorCode = 'FS_NOT_FOUND' | 'FS_NOT_DIRECTORY' | 'FS_NOT_TEXT' | 'FS_NOT_REGULAR_FILE' | 'FS_PERMISSION_DENIED' | 'FS_SANDBOX_DENIED' | 'FS_IO_ERROR' | 'FS_STALE_VERSION' | 'FS_NOT_OBSERVED' | 'FS_AMBIGUOUS_EDIT' | 'FS_EDIT_NOT_FOUND' | 'FS_ABORTED';
163
+ /**
164
+ * Typed filesystem error. Extends {@link HarnessError} so it carries a stable
165
+ * {@link FsErrorCode} and chains `cause`. `dsh-fs` owns this vocabulary so
166
+ * backends and the policy layer raise the same codes instead of each inventing
167
+ * message strings.
168
+ */
169
+ export declare class FsError extends HarnessError {
170
+ readonly code: FsErrorCode;
171
+ constructor(message: string, code: FsErrorCode, options?: ErrorOptions);
172
+ }
173
+ //# sourceMappingURL=types.d.ts.map
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@deepseek-ai/dsh-fs",
3
+ "description": "Abstract filesystem capability seam (ctx.fs) for the DeepSeek Harness — vocabulary types, the FileSystem service (text IO + optional version-guarded atomic mutations), and the fs/* policy event vocabulary",
4
+ "version": "0.0.1-rc.1",
5
+ "publishConfig": {
6
+ "access": "restricted"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
11
+ "directory": "packages/fs/fs"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./invariant": {
22
+ "types": "./lib/types/invariant.d.ts",
23
+ "default": "./lib/invariant.js"
24
+ },
25
+ "./src/*": "./src/*",
26
+ "./package.json": "./package.json"
27
+ },
28
+ "files": [
29
+ "lib/index.js",
30
+ "lib/invariant.js",
31
+ "lib/types/**/*.d.ts"
32
+ ],
33
+ "license": "BSD-3-Clause",
34
+ "peerDependencies": {
35
+ "@deepseek-ai/dsh-brand": "^0.0.1-rc.1",
36
+ "@deepseek-ai/dsh-invariants": "^0.0.1-rc.1",
37
+ "@deepseek-ai/dsh-llm": "^0.0.1-rc.1",
38
+ "@deepseek-ai/dsh-sandbox": "^0.0.1-rc.1",
39
+ "@deepseek-ai/cordis": "^4.0.1-rc.1"
40
+ },
41
+ "devDependencies": {
42
+ "@deepseek-ai/dsh-brand": "^0.0.1-rc.1",
43
+ "@deepseek-ai/dsh-invariants": "^0.0.1-rc.1",
44
+ "@deepseek-ai/dsh-llm": "^0.0.1-rc.1",
45
+ "@deepseek-ai/dsh-sandbox": "^0.0.1-rc.1",
46
+ "@deepseek-ai/cordis": "^4.0.1-rc.1"
47
+ }
48
+ }