Merge remote-tracking branch 'origin/master' into xtr/react-loop-simplification
# Conflicts: # .agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.i18n.yaml # .agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.zh.md # .agents/notes/implemented/architecture/2026-06-11-event-sourced-sessions.i18n.yaml # .agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.i18n.yaml # .agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.zh.md # .agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.i18n.yaml # .agents/notes/implemented/architecture/2026-06-18-session-surface.i18n.yaml # .agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.i18n.yaml # .agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.zh.md # .agents/notes/implemented/architecture/2026-06-30-event-domain-semantics.i18n.yaml # .agents/notes/implemented/architecture/2026-06-30-event-domain-semantics.zh.md # .agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.i18n.yaml # .agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.zh.md # .agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.i18n.yaml # .agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.zh.md # .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.i18n.yaml # .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md # .agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.i18n.yaml # .agents/notes/implemented/architecture/2026-07-15-replay-token-meter-service.i18n.yaml # .agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.i18n.yaml # .agents/notes/implemented/architecture/2026-07-22-unified-send-and-coalesced-user-messages.i18n.yaml # .agents/notes/implemented/architecture/2026-07-22-unified-send-and-coalesced-user-messages.zh.md # .agents/notes/implemented/architecture/2026-07-24-separate-context-injection-from-turn-execution.i18n.yaml # .agents/notes/implemented/architecture/2026-07-24-separate-context-injection-from-turn-execution.zh.md # .agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.i18n.yaml # .agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.zh.md # .agents/notes/implemented/architecture/2026-07-28-identified-immutable-message-values.i18n.yaml # .agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.i18n.yaml # .agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.zh.md # .agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.i18n.yaml # .agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md # .agents/notes/implemented/feature/2026-06-24-workspace-context.i18n.yaml # .agents/notes/implemented/feature/2026-06-24-workspace-context.zh.md # .agents/notes/implemented/feature/2026-06-30-hook-bridges.i18n.yaml # .agents/notes/implemented/feature/2026-06-30-hook-protocol-lib.i18n.yaml # .agents/notes/implemented/feature/2026-06-30-hook-protocol-lib.zh.md # .agents/notes/implemented/feature/2026-06-30-interception-seams.i18n.yaml # .agents/notes/implemented/feature/2026-06-30-interception-seams.zh.md # .agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml # .agents/notes/implemented/feature/2026-07-06-sandbox.zh.md # .agents/notes/implemented/feature/2026-07-16-durable-per-step-time-context.i18n.yaml # .agents/notes/implemented/feature/2026-07-16-durable-per-step-time-context.zh.md # .agents/notes/implemented/feature/2026-07-16-harness-level-loop.i18n.yaml # .agents/notes/implemented/feature/2026-07-16-harness-level-loop.zh.md # .agents/notes/implemented/feature/2026-07-19-human-goal-command.i18n.yaml # .agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.i18n.yaml # .agents/notes/implemented/feature/2026-07-19-persisted-same-session-goal-domain.i18n.yaml # .agents/notes/implemented/feature/2026-07-19-persisted-same-session-goal-domain.zh.md # .agents/notes/implemented/feature/2026-07-19-plugin-command-registration.i18n.yaml # .agents/notes/implemented/feature/2026-07-19-same-session-goal-round-driver.i18n.yaml # .agents/notes/implemented/feature/2026-07-19-same-session-goal-round-driver.zh.md # .agents/notes/implemented/feature/2026-07-21-cross-session-references.i18n.yaml # .agents/notes/implemented/feature/2026-07-21-cross-session-references.zh.md # .agents/notes/implemented/feature/2026-07-27-tmux-location-context.i18n.yaml # .agents/notes/implemented/simplification/2026-06-20-public-agent-stop-surface.i18n.yaml # .agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.i18n.yaml # .agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.zh.md # .agents/notes/implemented/simplification/2026-07-20-unwrap-injected-content-envelopes.i18n.yaml # .agents/notes/implemented/simplification/2026-07-22-plan-specific-collaboration-state.i18n.yaml # .agents/notes/implemented/simplification/2026-07-22-plan-specific-collaboration-state.zh.md # .agents/notes/implemented/simplification/2026-07-24-agent-loop-observable-state-machine.i18n.yaml # .agents/notes/implemented/simplification/2026-07-27-request-error-retry-action.i18n.yaml # docs/core-data-structures/compaction.i18n.yaml # docs/core-data-structures/goal.i18n.yaml # docs/core-data-structures/goal.zh.md # docs/core-data-structures/llm-streaming.i18n.yaml # docs/core-data-structures/session.i18n.yaml # docs/core-data-structures/session.zh.md # docs/core-data-structures/skills.i18n.yaml # docs/core-data-structures/skills.zh.md # docs/core-data-structures/system-prompt.i18n.yaml # docs/defensive-patterns.i18n.yaml # docs/defensive-patterns.zh.md # docs/user/develop/framework/events.i18n.yaml # docs/user/develop/framework/events.zh.md # packages/acp/acp/README.i18n.yaml # packages/client/ui-goal/README.i18n.yaml # packages/compact/compact-basic/README.i18n.yaml # packages/compact/compact/README.i18n.yaml # packages/context/time-context/README.i18n.yaml # packages/context/tmux-context/README.i18n.yaml # packages/core/agent-loop/README.i18n.yaml # packages/core/agent-loop/README.zh.md # packages/core/agent/README.i18n.yaml # packages/core/agent/README.zh.md # packages/core/session/README.i18n.yaml # packages/core/session/README.zh.md # packages/core/system-prompt/README.i18n.yaml # packages/core/system-prompt/README.zh.md # packages/examples/cli-demo/README.i18n.yaml # packages/goal/command-goal/README.i18n.yaml # packages/goal/goal-session/README.i18n.yaml # packages/goal/goal/README.i18n.yaml # packages/goal/tool-goal/README.i18n.yaml # packages/goal/tool-goal/README.zh.md # packages/guard/README.i18n.yaml # packages/guard/README.zh.md # packages/guard/repeat-tool-guard/README.i18n.yaml # packages/hooks/hooks-claude/README.i18n.yaml # packages/hooks/hooks-codex/README.i18n.yaml # packages/host/apiproxy/README.i18n.yaml # packages/host/apiproxy/README.zh.md # packages/llm/llm/README.i18n.yaml # packages/plan/plan-mode/README.i18n.yaml # packages/plan/plan-mode/README.zh.md # packages/sdk/sdk-client/README.i18n.yaml # packages/sdk/sdk-client/README.zh.md # packages/sdk/sdk-protocol/README.i18n.yaml # packages/session-persistence/session-persistence/README.i18n.yaml # packages/session-persistence/session-persistence/README.zh.md # packages/skill/tool-skill/README.i18n.yaml # packages/subagent/subagent-dsh-sdk/README.i18n.yaml # packages/subagent/subagent-inprocess/README.i18n.yaml # packages/subagent/subagent-inprocess/README.zh.md # packages/ui/jsonrpc/README.i18n.yaml
This commit is contained in:
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/fs/README.md
|
||||
README.md: b5e0ac9d1c0c550eb372b8a66fc6358711fddc07
|
||||
README.zh.md: ee64a617aa0d9549bcaf00b20821a6d59c6673c8
|
||||
README.zh.md: 7a7cafb814a1f6c4a79671cf23c7d4577ac2b716
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
文件系统栈包括:提供方 seam(文本 I/O 与带可选版本防护的原子变更)、本地实现、策略门禁插件(已观察状态、编辑前读取、版本防护的写入/编辑)、面向模型的文件工具与执行器,以及基于 bash 的发现工具。全部都是**产品**包(package)。
|
||||
文件系统栈包括:提供方 seam(文本 I/O 与带可选版本防护的原子变更)、本地实现、策略门禁插件(已观察状态、编辑前读取、版本防护的写入/编辑)、面向模型的文件工具与执行器,以及基于 bash 的发现工具。全部都是**产品**包。
|
||||
|
||||
| 包 | 角色 | ctx 键 |
|
||||
|---|---|---|
|
||||
@@ -14,7 +14,7 @@
|
||||
| `tool-fs-search/` | 面向模型的 `glob`/`grep` 发现工具;当 `rg` 位于 bash 执行器 `PATH` 上时注册,通过 `ctx.bash` 运行固定 ripgrep 命令,而不是使用 `ctx.fs` 提供方方法 | (注册到 `ctx.tools`) |
|
||||
| `tool-str-replace-editor/` | 基于 `ctx.fs` 提供查看/创建/唯一字面量替换/按行插入的模型可见 `str_replace_editor` | (注册到 `ctx.tools`) |
|
||||
|
||||
接口位于 `fs/fs/`。沙箱化、远程或限定项目作用域的文件系统后端可以替换 `fs-local`,而无需更改 seam、策略门禁或面向模型的工具 schema;`fs-sandbox` 是第一个这样的替代实现(基于共享沙箱模式的进程内路径围栏;见[跨能力族 fs 沙箱 Agent Note(agent 决策记录)](../../.agents/notes/implemented/feature/2026-07-14-cross-family-fs-sandbox.md))。策略(`fs-policy/`)是一个只通过 `fs/*` 事件门禁参与的插件,不是工具注入的服务;因此移除它只会使策略失效,留下不受约束的裸提供方,而不会破坏工具。加载 `tool-fs/` 的部署也应加载该插件。模式围栏与编辑前读取门禁彼此正交,可以组合。发现(`tool-fs-search/`)有意不扩展提供方 seam:搜索是在 bash 执行器上运行 `rg`、基于进程的工作流,因此文件系统后端无需承担通用搜索契约;只有当执行器能找到 `rg` 时,其工具才会注册。如果 bash 工作目录与 `read` 根目录是同一工作区,其结果便可供后续读取,这也是其 README 所述的共置部署。
|
||||
接口位于 `fs/fs/`。沙箱化、远程或限定项目作用域的文件系统后端可以替换 `fs-local`,而无需更改 seam、策略门禁或面向模型的工具 schema;`fs-sandbox` 是第一个这样的替代实现(基于共享沙箱模式的进程内路径围栏;见[跨能力族 fs 沙箱 Agent Note](../../.agents/notes/implemented/feature/2026-07-14-cross-family-fs-sandbox.md))。策略(`fs-policy/`)是一个只通过 `fs/*` 事件门禁参与的插件,不是工具注入的服务;因此移除它只会使策略失效,留下不受约束的裸提供方,而不会破坏工具。加载 `tool-fs/` 的部署也应加载该插件。模式围栏与编辑前读取门禁彼此正交,可以组合。发现(`tool-fs-search/`)有意不扩展提供方 seam:搜索是在 bash 执行器上运行 `rg`、基于进程的工作流,因此文件系统后端无需承担通用搜索契约;只有当执行器能找到 `rg` 时,其工具才会注册。如果 bash 工作目录与 `read` 根目录是同一工作区,其结果便可供后续读取,这也是其 README 所述的共置部署。
|
||||
|
||||
## 文件 I/O 不设超时
|
||||
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/fs/fs-local/README.md
|
||||
README.md: 6d344fa3fef7f6bda6c0daa50184661156a925a7
|
||||
README.zh.md: 3d488004aa638931bcbf3a7b660ad687220101da
|
||||
README.zh.md: 4c94de64561d805684f91f02d5b0dfc375f0d04f
|
||||
|
||||
@@ -14,14 +14,14 @@ await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
|
||||
|
||||
## 行为
|
||||
|
||||
- **`resolve(path, opts?)`**:相对 `path` 在调用方提供 `opts.cwd` 时以该值为基准解析(面向模型的工具会传入调用 agent(智能体)的会话 cwd;见[每会话 cwd Agent Note(agent 决策记录)](../../../.agents/notes/implemented/architecture/2026-07-02-fs-per-session-cwd.md)),否则以 `config.cwd` 为基准(默认 `process.cwd()`);绝对 `path` 会忽略两者。`opts.signal` 会在本地解析前后检查,远程同级后端则可以用它中止往返。`targetKey` 是文件的 `realpath`,因此经符号链接到达同一文件的两个输入路径会共享一个身份,写入/编辑落在链接目标上,同时保留链接。尚不存在的路径在父目录存在时使用 realpath 后的父目录加 basename;只有父目录无法解析时才回退到绝对路径。`displayPath` 是绝对但未经解析的路径。
|
||||
- **`resolve(path, opts?)`**:相对 `path` 在调用方提供 `opts.cwd` 时以该值为基准解析(面向模型的工具会传入调用 agent(智能体)的会话 cwd;见[每会话 cwd Agent Note](../../../.agents/notes/implemented/architecture/2026-07-02-fs-per-session-cwd.md)),否则以 `config.cwd` 为基准(默认 `process.cwd()`);绝对 `path` 会忽略两者。`opts.signal` 会在本地解析前后检查,远程同级后端则可以用它中止往返。`targetKey` 是文件的 `realpath`,因此经符号链接到达同一文件的两个输入路径会共享一个身份,写入/编辑落在链接目标上,同时保留链接。尚不存在的路径在父目录存在时使用 realpath 后的父目录加 basename;只有父目录无法解析时才回退到绝对路径。`displayPath` 是绝对但未经解析的路径。
|
||||
- **`stat` / `lstat`**:返回目标元数据;目标不存在时返回 `undefined`。`stat` 为已解析目标报告 `FsInfo`(`version` 是由 bigint `dev:ino:size:mtimeNs:ctimeNs` 派生的不透明 token,`type` 为 `file`/`directory`/`other`,`size` 以字节计);路径形态的 `lstat` 不跟随最后一个符号链接,报告 `FsPathInfo`,因此可以返回 `symlink`。两者都会在异步元数据探测前后检查取消,因此异步探测进行期间发生的中止会报告 `FS_ABORTED`,而非已失效的「不存在」结果。
|
||||
- **`readText` / `streamText`**:只支持 UTF-8。`readText` 读取整个文件;`streamText` 按分片流式读取(跨分片解码),因此超大文件无需整体保存在内存中。两者都会拒绝无效 UTF-8、包含 NUL 字节的二进制样本(`FS_NOT_TEXT`)以及非普通文件目标。`read` 工具(`@deepseek-ai/dsh-tool-fs`)按大小决定调用哪个方法,并负责行窗口逻辑。
|
||||
- **`listDir`**:按稳定的 `name.localeCompare()` 顺序列出一层目录。每个条目携带子项 basename、类型、解析后的子目标(`displayPath` 位于所列目录下,`targetKey` 是 realpath 身份)和低成本 stat 元数据(`version`,普通文件另有 `size`)。它绝不会打开或解码文件内容。缺失目标报告 `FS_NOT_FOUND`,文件/特殊文件目标报告 `FS_NOT_DIRECTORY`,已中止调用报告 `FS_ABORTED`,权限失败报告 `FS_PERMISSION_DENIED`,其他列出或子项元数据 I/O 失败报告 `FS_IO_ERROR`。损坏/消失的子项以无元数据的 `other` 返回,但解析子项时出现权限/I/O 失败会让整个列表以结构化 `FsError` 失败。
|
||||
- **`writeText`**:原子写入。它会向排他打开的临时文件(`wx`、`0o600`)写入;该文件位于目标旁随机命名的私有暂存目录(`0o700`)内。完成写入和 fsync 后,以 rename 覆盖目标。现有文件的 mode 会保留,新文件默认为 `0o600`;Windows 上的新文件继承目标目录的 DACL,而替换会在写入前把目标 DACL 复制到空临时文件,并通过 `ReplaceFileW` 发布,使原访问策略得以保留(见 [Windows DACL 保留 Agent Note](../../../.agents/notes/implemented/bug-fix/2026-07-19-windows-atomic-write-dacl-preservation.md))。`expected` 防护是可选(OPTIONAL)的:省略时无条件创建或覆盖;`createIfAbsent` 创建缺失目标并拒绝现有目标(`FS_NOT_OBSERVED`);`replaceIfVersion` 只在观察到的版本上替换(目标缺失或版本不匹配均为 `FS_STALE_VERSION`)。
|
||||
- **`editText`**:在同一原语之上执行原子式的字面量读取-修改-写入,并通过变更锁按目标串行化。`expected` 防护是可选(OPTIONAL)的:提供时,会在字面量匹配之前校验版本(陈旧编辑报告 `FS_STALE_VERSION`,绝不会针对较新内容报告 `FS_EDIT_NOT_FOUND`/`FS_AMBIGUOUS_EDIT`);省略时,无条件编辑当前内容。无论哪种情况,目标缺失都报告 `FS_STALE_VERSION`。匹配时规范化为 LF,随后恢复文件主要的 CRLF/LF 风格;空 `oldString` / 零匹配报告 `FS_EDIT_NOT_FOUND`,未设置 `replace_all` 的多个匹配则报告 `FS_AMBIGUOUS_EDIT`。
|
||||
|
||||
包(package)根目录的 SDK 接口包含默认/具名 `LocalFileSystem` 类和 `Config`。原始 I/O 位于 `src/fsio.ts`(不依赖 Cordis,单独进行单元测试);`src/index.ts` 是轻量服务接线。
|
||||
包根目录的 SDK 接口包含默认/具名 `LocalFileSystem` 类和 `Config`。原始 I/O 位于 `src/fsio.ts`(不依赖 Cordis,单独进行单元测试);`src/index.ts` 是轻量服务接线。
|
||||
|
||||
## 模型体验
|
||||
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/fs/fs-policy/README.md
|
||||
README.md: dc4e9377793570c80b8d71ec84196bebe7fe583a
|
||||
README.zh.md: aa0cb25899f5906ac9f531583ba48d01ad6095b4
|
||||
README.zh.md: 499192d2623765f214af7556d23beabbe2129ea1
|
||||
|
||||
@@ -20,7 +20,7 @@ await ctx.plugin(FsPolicy)
|
||||
|
||||
## 四层拆分
|
||||
|
||||
| 层 | 包(package) | 角色 |
|
||||
| 层 | 包 | 角色 |
|
||||
|---|---|---|
|
||||
| 工具/执行器 | `@deepseek-ai/dsh-tool-fs` | 面向模型的 schema、读取窗口和文本渲染;通过 `ctx.fs` 读取/写入/编辑,并分派 `fs/*` 事件 |
|
||||
| 策略 | `@deepseek-ai/dsh-fs-policy`(本包) | 通过 `fs/*` 事件门禁提供已观察状态、编辑前读取和版本防护的写入/编辑(无服务) |
|
||||
@@ -63,11 +63,11 @@ await ctx.plugin(FsPolicy)
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
|
||||
仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **已观察状态无法在会话恢复后保留**:`WeakMap` 记录的持久化工作延期处理,因此恢复的会话必须重新读取文件,才能执行防护写入/编辑。
|
||||
- **没有 agent(智能体)会话的参与者绝无法满足策略**:它们的编辑会抛出 `FS_NOT_OBSERVED`,写入总会解析为 `createIfAbsent`,因此非 agent 调用方无法通过门禁覆盖现有文件。
|
||||
- **直接 `ctx.fs` 读取不会发出 `fs/observed`**:在 `read` 工具之外读取的文件仍未观察;后续防护编辑会以 `FS_NOT_OBSERVED` 拒绝,直到工具读取该文件。
|
||||
- **授权依据是版本新鲜度,而非视图完整性**:任何窗口读取都会授权对未变文件执行全文件覆盖,这有意弱于完整视图规则(见 [seam 拆分 Agent Note(agent 决策记录)](../../../.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md))。
|
||||
- **授权依据是版本新鲜度,而非视图完整性**:任何窗口读取都会授权对未变文件执行全文件覆盖,这有意弱于完整视图规则(见 [seam 拆分 Agent Note](../../../.agents/notes/implemented/simplification/2026-06-26-fsspec-style-fs-seam.md))。
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/fs/fs-sandbox/README.md
|
||||
README.md: d6070f4971e7531e929e659b6b5ed476a672dc5d
|
||||
README.zh.md: c051b240163f229f7fbc583939c9f4da5095e9aa
|
||||
README.zh.md: 9304095c2d077adb657af61f4b2b54e087a252c7
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
围栏是在可信代码中检查模型控制的路径。操作本身属于 seam(open、rename),只有目标路径不可信,因此「规范化后检查包含关系」就是该接口的完整答案。这与 `code-runtime` 的立场相同:提供约束,但不是安全边界。不可信代码的内核级隔离仍由 `ctx.bash` 负责([`dsh-bash-sandbox`](../../bash/bash-sandbox/README.md))。剩余 TOCTOU(在包含关系复查与系统调用之间替换祖先符号链接)会通过写入前立即重新规范化来缩小,并为该威胁模型所接受;内核严密边界需要 `openat2` 一类原语,其可移植性成本在此不值得。
|
||||
|
||||
拒绝是结构化 `FsError`(`FS_SANDBOX_DENIED`,携带有效模式),不通过 stderr 文本推断(不同于 bash 的内核拒绝),因为进程内围栏准确知道自己拒绝了什么。面向模型的 `[sandbox: file access denied under <mode> mode]` 标记以及唯一一次获批的更宽权限重试位于工具层(`dsh-tool-fs`),与 bash 完全相同。见[跨能力族 fs 沙箱 Agent Note(agent 决策记录)](../../../.agents/notes/implemented/feature/2026-07-14-cross-family-fs-sandbox.md)。
|
||||
拒绝是结构化 `FsError`(`FS_SANDBOX_DENIED`,携带有效模式),不通过 stderr 文本推断(不同于 bash 的内核拒绝),因为进程内围栏准确知道自己拒绝了什么。面向模型的 `[sandbox: file access denied under <mode> mode]` 标记以及唯一一次获批的更宽权限重试位于工具层(`dsh-tool-fs`),与 bash 完全相同。见[跨能力族 fs 沙箱 Agent Note](../../../.agents/notes/implemented/feature/2026-07-14-cross-family-fs-sandbox.md)。
|
||||
|
||||
## 模型体验
|
||||
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/fs/fs/README.md
|
||||
README.md: 9e6c954abad124fb2b30ebc01368a55746752013
|
||||
README.zh.md: ff97513490d4a2855564042ba0ebf9403f28289c
|
||||
README.zh.md: c72b1f9a83485ca9c188344ba7a345c889951c7b
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
**文件系统提供方 seam**:抽象 `FileSystem` 服务(`ctx.fs`),定义后端提供的存储原语,包括路径解析、stat 元数据、不跟随链接的路径元数据、读取/流式读取文本、列出目录、原子写入和应用字面量编辑,但不规定实现方式。两个变更操作都**可选**接收版本防护,因此 `ctx.fs` 本身就是完整且不受约束的文本存储 seam。本包(package)还拥有由工具分派、策略插件监听的 `fs/*` 策略事件词汇。
|
||||
**文件系统提供方 seam**:抽象 `FileSystem` 服务(`ctx.fs`),定义后端提供的存储原语,包括路径解析、stat 元数据、不跟随链接的路径元数据、读取/流式读取文本、列出目录、原子写入和应用字面量编辑,但不规定实现方式。两个变更操作都**可选**接收版本防护,因此 `ctx.fs` 本身就是完整且不受约束的文本存储 seam。本包还拥有由工具分派、策略插件监听的 `fs/*` 策略事件词汇。
|
||||
|
||||
本包是四层文件系统栈中的提供方 seam 层;该拆分使每个关注点可以独立演进和替换(见[能力 seam Agent Note(agent 决策记录)](../../../.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)):
|
||||
本包是四层文件系统栈中的提供方 seam 层;该拆分使每个关注点可以独立演进和替换(见[能力 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)):
|
||||
|
||||
| 层 | 包 | 角色 |
|
||||
|---|---|---|
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/fs/tool-fs-search/README.md
|
||||
README.md: 78ffa069e56da5fc987913acf761eb5c6ae15b1a
|
||||
README.zh.md: 42b123d5c47d8f48bc21b6f9bed4905372ca8625
|
||||
README.zh.md: b7bb08f94682b0c85baf33ad9045320e3306bbb2
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
**面向模型的文件系统发现工具**(`glob`、`grep`)由 **打包的 ripgrep 二进制**(`@vscode/ripgrep`)支持,而不是由 `ctx.fs` 提供方方法或系统 `rg` 安装支持。注册是无条件的:二进制随 npm 依赖一起交付,因此没有加载期可用性探针。每次调用都通过 `ctx.subprocess` seam 以固定 argv 向量 spawn 该二进制(前缀 `--no-config`,使宿主的 `RIPGREP_CONFIG_PATH` 无法向不受约束的 spawn 注入 `--pre` 预处理器;模型控制的值是普通 argv 元素——不存在 shell 层,因此无需引号),解析原始 `rg` 输出,并返回相对于工作目录的规范值。本包注入 `tools`、`systemPrompt` 和 `subprocess`,有意**不**注入 `fs`;格式化结果 spill 为可选功能,因此机会性读取 `ctx.spillStore`,调用方式为 `ctx.get()`。
|
||||
**面向模型的文件系统发现工具**(`glob`、`grep`)由 **打包的 ripgrep 二进制**(`@vscode/ripgrep`)支持,而不是由 `ctx.fs` 提供方方法或系统 `rg` 安装支持。注册是无条件的:二进制随 NPM 依赖一起交付,因此没有加载期可用性探针。每次调用都通过 `ctx.subprocess` seam 以固定 argv 向量 spawn 该二进制(前缀 `--no-config`,使宿主的 `RIPGREP_CONFIG_PATH` 无法向不受约束的 spawn 注入 `--pre` 预处理器;模型控制的值是普通 argv 元素——不存在 shell 层,因此不涉及 shell 引号处理),解析原始 `rg` 输出,并返回相对于工作目录的规范值。本包注入 `tools`、`systemPrompt` 和 `subprocess`,有意**不**注入 `fs`;格式化结果 spill 为可选功能,因此机会性读取 `ctx.spillStore`,调用方式为 `ctx.get()`。
|
||||
|
||||
```ts ignore-check
|
||||
// A deployment chooses how over-cap glob pages are selected.
|
||||
@@ -20,9 +20,9 @@ await ctx.plugin(LocalSpillStore) // @deepseek-ai/dsh-
|
||||
|
||||
## 配置
|
||||
|
||||
`sampleOverCapGlobResults` 是必填项且没有回退值;部署必须显式选择超过上限时的排序契约。其余键是可选的搜索上限,默认值如下。
|
||||
`sampleOverCapGlobResults` 是必填项且没有回退值;部署必须显式选择超过上限时的排序契约。其余配置键是可选的搜索上限,默认值如下。
|
||||
|
||||
| 键 | 默认值 | 含义 |
|
||||
| 配置键 | 默认值 | 含义 |
|
||||
|---|---|---|
|
||||
| `sampleOverCapGlobResults` | 无(必填) | `true` 会在顶层条目之间对超过上限的 `glob` 页面采样;`false` 保留按修改时间排序的前部。格式化 spill 成功时,两种模式都会在该产物中保留完整排序列表。 |
|
||||
| `globMaxResults` | `100` | 一次 `glob` 调用内联展示的最大路径数(与 Claude Code 的 `GlobTool` 上限相同)。未超过上限的结果保持完整,并按修改时间排序。 |
|
||||
@@ -44,11 +44,11 @@ await ctx.plugin(LocalSpillStore) // @deepseek-ai/dsh-
|
||||
|
||||
## 两类预算、两类产物
|
||||
|
||||
原始 `rg` stdout 与 stderr 是内部传输细节。每次搜索从 subprocess seam 请求 collect 模式预算——`rawOutputMaxBytes` 内的完整 stdout 与 `stderrMaxBytes` 的诊断尾部——两条流都不产生 spill 文件(工具从不读取原始 spill 路径)。如果 seam 仍报告 lossy stdout 读取,搜索会以 `SEARCH_RAW_OUTPUT_OVERFLOW` 失败,并要求模型缩小查询;lossy stderr 读取只把诊断摘录标记为 `[stderr truncated]`。成功的 `glob` 在 `{ root, paths }` 中保留所显示的搜索根及所有已取得路径;启用采样时,借助 `root`,原生渲染器能以显式的相对或绝对搜索路径为根,按该根下的条目分组,而不是按其工作目录前缀分组。`grep` 保留所有已取得的 `{ path, lineNumber, line }`,并将其存入 `{ matches }`。内联条目和每行预览上限只应用于原生渲染器。直接接口调用的逻辑结果超过内联上限时,后置策略会尽力通过 `ctx.spillStore.saveText()` 保存完整格式化预览,并只把呈现替换为配置指定的页面与 locator。嵌套 Code 分派会跳过 spill,因为其完整规范值不会进入模型上下文。spill 缺失/失败时保留内联页面,并报告完整结果无法保存,绝不会成为 `isError`。
|
||||
原始 `rg` stdout 与 stderr 是内部传输细节。每次搜索从 subprocess seam 请求 collect 模式预算——`rawOutputMaxBytes` 内的完整 stdout 与 `stderrMaxBytes` 的诊断尾部——两条流都不产生 spill 文件(工具从不读取原始 spill 路径)。如果 seam 仍报告 lossy stdout 读取,搜索会以 `SEARCH_RAW_OUTPUT_OVERFLOW` 失败,并要求模型缩小查询;lossy stderr 读取只把诊断摘录标记为 `[stderr truncated]`。成功的 `glob` 在 `{ root, paths }` 中保留所显示的搜索根及所有已取得路径;启用采样时,借助 `root`,Native 渲染器能以显式的相对或绝对搜索路径为根,按该根下的条目分组,而不是按其工作目录前缀分组。`grep` 保留所有已取得的 `{ path, lineNumber, line }`,并将其存入 `{ matches }`。内联条目和每行预览上限只应用于 Native 渲染器。直接接口调用的逻辑结果超过内联上限时,后置策略会尽力通过 `ctx.spillStore.saveText()` 保存完整格式化预览,并只把呈现替换为配置指定的页面与 locator。嵌套 Code 分派会跳过 spill,因为其完整规范值不会进入模型上下文。spill 缺失/失败时保留内联页面,并报告完整结果无法保存,绝不会成为 `isError`。
|
||||
|
||||
## 错误
|
||||
|
||||
搜索失败携带本包拥有的 `SearchError`(`HarnessError` 子类),以 `{ name, code }` 公开在 `isError` 结果上:`SEARCH_INVALID_PATTERN`(ripgrep 拒绝正则/glob)、`SEARCH_FAILED`(`rg` 启动失败、目标不可访问、信号终止、`--json` 输出格式错误)、`SEARCH_RAW_OUTPUT_OVERFLOW`(原始输出超过 `rawOutputMaxBytes`,或在请求 stdout 捕获预算后仍 lossy)和 `SEARCH_ABORTED`(协作式工具超时或调用方取消)。ripgrep 退出语义由工具拥有:退出 0 表示成功且有结果,退出 1 表示成功的空搜索(`No files found` / `No matches found`),只有其他退出值表示失败。模型参数错误(空白 pattern、列表值 `include`)仍是普通工具参数错误。
|
||||
搜索失败会携带由本包定义的 `SearchError`(`HarnessError` 子类),并以 `{ name, code }` 的形式呈现在 `isError` 结果上:`SEARCH_INVALID_PATTERN`(ripgrep 拒绝正则/glob)、`SEARCH_FAILED`(`rg` 启动失败、目标不可访问、信号终止、`--json` 输出格式错误)、`SEARCH_RAW_OUTPUT_OVERFLOW`(原始输出超过 `rawOutputMaxBytes`,或在请求 stdout 捕获预算后仍 lossy)和 `SEARCH_ABORTED`(协作式工具超时或调用方取消)。ripgrep 的退出语义由工具负责处理:退出 0 表示成功且有结果,退出 1 表示成功的空搜索(`No files found` / `No matches found`),只有其他退出值表示失败。模型参数错误(空白 pattern、列表值 `include`)仍是普通工具参数错误。
|
||||
|
||||
## 模型体验
|
||||
|
||||
@@ -82,7 +82,7 @@ Use the grep tool — not shell grep or rg — to search file contents. Use read
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
插件作用域、采样选择与指导文本不变时前缀稳定。激活、销毁或改变选择可能使该提示词段的复用失效。
|
||||
插件作用域、采样选择与指导文本不变时前缀稳定。激活、dispose(资源释放)或改变选择可能使该提示词段的复用失效。
|
||||
|
||||
### 工具 schema
|
||||
|
||||
@@ -102,15 +102,15 @@ glob 描述声明了配置的超过上限排序方式。生成的 [`glob` 和 `g
|
||||
|
||||
#### 模型看到的内容
|
||||
|
||||
`glob` 每行返回一个路径;`grep` 在每个路径下分组展示 `Line <line>: <preview>` 匹配。空搜索返回 `No files found` 或 `No matches found`。达到上限的结果以省略计数结尾,并附 spill locator 与后端检索提示;否则说明完整结果无法保存。启用 `sampleOverCapGlobResults: true` 时,超过上限的 `glob` 页面按实际搜索根正下方的条目轮转取路径,页脚说明采样依据及其覆盖的顶层条目数;无法覆盖全部条目时,页脚提示模型收窄 `path`。`false` 时页面是按修改时间排序的前部,并保留普通的上限结果页脚。未超过上限的结果原样呈现;扁平采样的结果也保留普通页脚,因为其采样等于按修改时间排序的前部。spill 产物始终持有按修改时间排序的完整列表。
|
||||
`glob` 每行返回一个路径;`grep` 在每个路径下分组展示 `Line <line>: <preview>` 匹配。空搜索返回 `No files found` 或 `No matches found`。达到上限的结果以省略计数结尾,并附 spill locator 与后端检索提示,或说明完整结果无法保存。启用 `sampleOverCapGlobResults: true` 时,超过上限的 `glob` 页面按实际搜索根正下方的条目轮转取路径,页脚说明采样依据及其覆盖的顶层条目数;无法覆盖全部条目时,页脚提示模型收窄 `path`。`false` 时页面是按修改时间排序的前部,并保留普通的上限结果页脚。未超过上限的结果原样呈现;扁平采样的结果也保留普通页脚,因为其采样等于按修改时间排序的前部。spill 产物始终持有按修改时间排序的完整列表。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
内联路径与匹配受 `globMaxResults`、`grepMaxMatches` 与 `grepMaxLineBytes` 约束;调用与保留结果在压缩前留在历史中。
|
||||
内联路径与匹配受 `globMaxResults`、`grepMaxMatches` 与 `grepMaxLineBytes` 约束;调用及其保留结果在压缩(compaction)前留在历史中。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
只追加;新可见内容跟在可复用请求前缀之后,不会使既有 KV-cache 条目失效。
|
||||
只追加;新可见内容跟在可复用请求前缀之后,不会使既有 KV Cache 条目失效。
|
||||
|
||||
### 工具错误
|
||||
|
||||
@@ -124,11 +124,11 @@ glob 描述声明了配置的超过上限排序方式。生成的 [`glob` 和 `g
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
只追加;新可见内容跟在可复用请求前缀之后,不会使既有 KV-cache 条目失效。
|
||||
只追加;新可见内容跟在可复用请求前缀之后,不会使既有 KV Cache 条目失效。
|
||||
|
||||
## 已知局限与延期工作
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **搜索与文件访问没有共享工作区证明**——只有当工作目录与文件系统根目录指向同一工作区时,返回路径才保证可继续读取;本包不执行运行时跨服务校验。
|
||||
- **搜索与文件访问没有共享工作区证明**——只有当工作目录与文件系统根目录指向同一工作区时,返回路径才可继续读取;本包不执行运行时跨服务校验。
|
||||
- **打包二进制固定在依赖版本上**——`@vscode/ripgrep` 覆盖其随附的平台(macOS/Linux/Windows,x64/arm64);不支持的平台或损坏的安装会以 `SEARCH_FAILED` 使调用失败。远程或虚拟文件系统需要共置的工作区或另一个搜索消费方。
|
||||
- **schema 只暴露一个有界页面**——偏移分页、大小写开关、替代输出模式与提供方支撑的发现仍不在本包范围内;达到上限的完整输出需要 spill 后端。
|
||||
- **启用采样时仅按搜索根正下方的第一段路径分组**——超过上限的 `glob` 页面在这些顶层条目之间平衡,因此集中在更深处的结果(一棵均匀树里某个繁忙目录)在该层级之下仍会呈现不均;递归平衡被延期。
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/fs/tool-fs/README.md
|
||||
README.md: a695d0ba8fb1d600689d2b68763e8423d1591da5
|
||||
README.zh.md: 5c600ab70b46da640637aec64efc1c0f0d0d54c0
|
||||
README.zh.md: 7b7dc26f514cc757cac97283eab52276505bfaae
|
||||
|
||||
@@ -24,7 +24,7 @@ await ctx.plugin(ToolFs) // this package — re
|
||||
| `readMaxBytes` | `51200` | 一次 `read` 调用所选行的字节上限;溢出时以「已达上限」footer 结束窗口。 |
|
||||
| `readStreamMinSize` | `10485760` | 大于等于该大小或大小未知的文件采用流式读取,而不是整体加载到内存。 |
|
||||
|
||||
## 工具(schema 见[文件系统工具 schema Agent Note(agent 决策记录)](../../../.agents/notes/implemented/feature/2026-06-17-filesystem-tool-schemas.md))
|
||||
## 工具(schema 见[文件系统工具 schema Agent Note](../../../.agents/notes/implemented/feature/2026-06-17-filesystem-tool-schemas.md))
|
||||
|
||||
| 工具 | 参数 | 行为 |
|
||||
|---|---|---|
|
||||
@@ -54,7 +54,7 @@ await ctx.plugin(ToolFs) // this package — re
|
||||
|
||||
`read` 允许并发调度,因为其唯一变更是同步版本记录器。稍后的 `write` 或 `edit` 会在目标锁内重新检查版本,因此记录器竞态会以拒绝方式关闭;两个变更工具仍保持互斥。见[并行工具调用 Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-parallel-tool-call-execution.md)。
|
||||
|
||||
包(package)根目录只导出 Cordis 插件契约(`name`、`inject`、`Config` 和 `apply`)。读取渲染(行窗口与输出格式化)位于 `src/read-render.ts`(不依赖 Cordis,单独进行单元测试);`src/read.ts`/`write.ts`/`edit.ts` 是工具执行器,`src/index.ts` 负责组合。
|
||||
包根目录只导出 Cordis 插件契约(`name`、`inject`、`Config` 和 `apply`)。读取渲染(行窗口与输出格式化)位于 `src/read-render.ts`(不依赖 Cordis,单独进行单元测试);`src/read.ts`/`write.ts`/`edit.ts` 是工具执行器,`src/index.ts` 负责组合。
|
||||
|
||||
## 模型体验
|
||||
|
||||
@@ -116,7 +116,7 @@ Use the edit tool for targeted changes to existing UTF-8 text files. It replaces
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
|
||||
仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。
|
||||
|
||||
### 写入与编辑结果
|
||||
|
||||
@@ -130,7 +130,7 @@ Use the edit tool for targeted changes to existing UTF-8 text files. It replaces
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
|
||||
仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。
|
||||
|
||||
### 工具错误
|
||||
|
||||
@@ -144,7 +144,7 @@ Use the edit tool for targeted changes to existing UTF-8 text files. It replaces
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV-cache 条目失效。
|
||||
仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。
|
||||
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
|
||||
Reference in New Issue
Block a user