docs: rescan rebased documentation hierarchy
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/util/README.md
|
||||
README.md: 46904aba70c7cf0f98bb75cce79d97bb12b950a9
|
||||
README.zh.md: 78a4c3038ef31bb1ec5fb10751b7c148ea20b716
|
||||
README.md: b84f2cbb88981aa2edbde65d8a711b28cc5b48e9
|
||||
README.zh.md: 44834041aad8d891b5dcaf63e02be5641e878cdc
|
||||
|
||||
@@ -2,21 +2,13 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
其他分组共享的零依赖原语。当某个包拥有某个微小的基础类型或辅助工具,而该类型或辅助工具为多个功能家族所需,却不属于其中任何一个家族时,该包就归入此处。这样可避免一个功能包仅为使用共享原语而依赖不相关的功能包。这些都是**支持** 包:规模小、稳定,且不依赖 harness。
|
||||
这些零依赖包提供由多个能力家族共享的小型原语。业务语义仍归各个消费这些原语的能力所有。
|
||||
|
||||
| 包 | 职责 |
|
||||
|---|---|
|
||||
| `brand/` | 仅包含类型的 `Branded<B>` 名义类型原语(无运行时代码,无 harness 依赖) |
|
||||
| `paths/` | 规范的单根 `DSH_HOME` 解析,以及 harness 用户数据的共享文件系统路径常量和辅助工具(无 harness 依赖) |
|
||||
| `timeout/` | 超时的时序/分类部分:`clampTimeout`/`deadline`/`timeoutOf`/`TimeoutReason`(纯函数,无 harness 依赖);终止机制保留在各个功能中 |
|
||||
| `retention/` | 有界的面向模型输出:`ItemRetainer`/`TextRetainer` 加上中性通知辅助工具(纯工具,无 harness 依赖);业务语义保留在各个工具中 |
|
||||
| `atomic-write/` | 原子文件替换:`writeFileAtomic`(独占创建临时文件 + 携带调用方所声明 mode 的 rename);由设置与凭据存储共用 |
|
||||
| `native-command/` | 宿主原生 OS 集成的免 shell `execFile` 运行器——utf8 捕获、abort 传播、Windows 窗口隐藏(无 harness 依赖);命令选择保留在各调用方 |
|
||||
|
||||
`dsh-brand` 是规范示例:它只负责 `Branded<B>` 辅助工具,因此功能包可以为自己拥有的 id 添加品牌(`dsh-tasks` 的 `TaskId`、`dsh-session` 的 `SessionId` 等),而只需依赖 `dsh-brand`,无需仅为使用 `Branded` 而引入不相关的包。
|
||||
|
||||
`dsh-paths` 为每个包提供同一个可配置的 Harness 主目录,而不将这项横切事实归属给 bash、skill(技能)、telemetry 或组合包。它优先解析显式值,其次是 `$DSH_HOME`,最后回退到 `~/.dsh`;返回绝对路径,但不缓存、创建或修改任何内容。harness 将所有用户数据保存在同一根目录下。
|
||||
|
||||
`dsh-timeout` 对超时家族采用相同结构:`dsh-bash` 和 `dsh-web-fetch-local` 都只依赖 `dsh-timeout`,便可将调用方的取消与 deadline 融合,然后区分「已超时」和「已取消」。它刻意只负责时序/分类部分,*终止*机制(对进程组发送 SIGKILL、关闭 fetch socket)保留在各个功能中,因为没有任何共享层可以负责每个功能的终止操作(见[超时库 Agent Note](../../.agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.md))。
|
||||
|
||||
`dsh-retention` 对有界工具输出采用同样的拆分方式:工具(`glob`/`grep`/`bash`/`web_fetch`/`web_search`)将项或文本送入 retainer,取回保留的内容以及精确的省略量;分组、退出码、提供方错误和恢复文案则仍由工具负责。它刻意只负责保留机制;`truncated` 只表示因预算而发生了省略,绝不表示「检查不完整」状态(见[保留库 Agent Note](../../.agents/notes/implemented/architecture/2026-07-06-tool-result-retention-library.md))。
|
||||
| [`brand/`](brand/README.md) | 提供带名义品牌的类型 |
|
||||
| [`paths/`](paths/README.md) | 解析 Harness 数据根目录和共享路径 |
|
||||
| [`timeout/`](timeout/README.md) | 提供截止时间和超时分类原语 |
|
||||
| [`retention/`](retention/README.md) | 限制保留文本和项目集合的大小 |
|
||||
| [`atomic-write/`](atomic-write/README.md) | 以原子方式替换文件 |
|
||||
| [`native-command/`](native-command/README.md) | 不经 shell 运行宿主原生命令 |
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/util/atomic-write/README.md
|
||||
README.md: 2ff4abb6ac10d8b592ccd2056b4f1f92cc8518b0
|
||||
README.zh.md: bd5d3f1f2583ff1b97a80ce2c1c6ca7989e13d15
|
||||
README.zh.md: 4284d06422564268bb9e31d1a1ed06ab5271e562
|
||||
|
||||
@@ -30,15 +30,15 @@ await withFileLock('/home/u/.dsh/settings.yaml', async () => {
|
||||
|
||||
`withFileLock` 跨进程串行化同一文件的写入方,服务于单靠原子提交无法保证安全的读-渲染-提交循环。锁是以 `wx` 创建的同目录 `<filename>.lock`,因此读取方从不参与竞争;等待方按指数退避,超时即失败而非无限阻塞。竞争者绝不移除现有锁:锁龄无法区分已经崩溃的所有者与被暂停但仍存活的写入方。
|
||||
|
||||
## Model Experience
|
||||
## 模型体验
|
||||
|
||||
无:本包是纯文件系统原语,此处没有任何内容会到达模型请求。
|
||||
|
||||
#### KV Cache effect
|
||||
#### KV Cache 影响
|
||||
|
||||
无;此处没有任何内容会进入请求前缀。
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
## 已知限制与暂缓事项
|
||||
|
||||
- **原子但不保证持久**——不对文件或其所在目录做 `fsync`,因此崩溃后可能观察到 rename 被回退。此处的文件型存储在启动时重新读取并重新发布,把持久性留作调用方的策略。
|
||||
- **仅支持字符串内容**——在有消费方需要之前,不提供 `Buffer` 或流式形态。
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/util/native-command/README.md
|
||||
README.md: 7fc8b1f4640ef87ada62b6656854feb37080e4e6
|
||||
README.zh.md: 94db732afbb77eb90faf3c5710a8a9c4a8630f95
|
||||
README.zh.md: b91af6fe4787c35c56fbd4523d5a7e10673e32cb
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
它是**库,不是服务或插件**:没有 `ctx`、不注册任何东西、不持有状态、不发事件。
|
||||
|
||||
## Surface
|
||||
## 接口面
|
||||
|
||||
```ts
|
||||
import { runNativeCommand, type NativeCommandRunner } from '@deepseek-ai/dsh-native-command'
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/util/retention/README.md
|
||||
README.md: d257075a67b35e92bce53a88fc6d002f4f4d5d9b
|
||||
README.zh.md: 1a0761b4744b7f090cfbf94f847bb99fc2d41a96
|
||||
README.md: 45c88e9fc2d8df98f935fd1c3b43c4622802bd2a
|
||||
README.zh.md: 0fcb76a8ae381d3e3da54e90640a38cba9de12e8
|
||||
|
||||
@@ -47,7 +47,7 @@ Text caps and `omittedBytes` count **bytes**, for process/body safety (a child's
|
||||
|
||||
## Tool mappings
|
||||
|
||||
Every current retention consumer maps to the library below. A broad migration is out of scope for the library's first landing — these are the intended shapes.
|
||||
Current retention consumers use these mappings:
|
||||
|
||||
| Tool | Retainer & strategy | Notes |
|
||||
|---|---|---|
|
||||
@@ -57,7 +57,7 @@ Every current retention consumer maps to the library below. A broad migration is
|
||||
| `web_fetch` | `TextRetainer`, `head` or `headTail` | Provider/resource caps stay provider facts; the retainer supplies only retained text and omission metadata. |
|
||||
| `web_search` | `ItemRetainer<WebSearchSource>`, `head` | Standardizes the "sources capped" notice when providers return more sources than the model-facing result should include. |
|
||||
|
||||
`read` is **intentionally out of scope for v1.** Its `read-render` helper owns a file-specific pagination contract — `offset`/`limit`, line numbers, `totalLines`, offset-out-of-range errors, per-line preview truncation, a byte cap over the selected window — which is a line-window renderer, not generic retention. A single `Omitted` count cannot represent both sides of a line window.
|
||||
`read` remains outside this generic library. Its `read-render` helper owns a file-specific pagination contract — `offset`/`limit`, line numbers, `totalLines`, offset-out-of-range errors, per-line preview truncation, and a byte cap over the selected window — which is a line-window renderer. A single `Omitted` count cannot represent both sides of that window.
|
||||
|
||||
## Usage shape
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ import type {
|
||||
|
||||
## 工具映射
|
||||
|
||||
当前每个保留消费方都按下表映射到该库。广泛迁移不属于该库首次落地的范围;下表是预期形态。
|
||||
当前的保留机制消费方采用以下映射:
|
||||
|
||||
| 工具 | Retainer 与策略 | 说明 |
|
||||
|---|---|---|
|
||||
@@ -57,7 +57,7 @@ import type {
|
||||
| `web_fetch` | `TextRetainer`,`head` 或 `headTail` | 提供方/资源上限保留为提供方事实;retainer 只提供保留文本和省略元数据。 |
|
||||
| `web_search` | `ItemRetainer<WebSearchSource>`,`head` | 当提供方返回的来源超过面向模型的结果应包含的数量时,标准化「来源已达上限」通知。 |
|
||||
|
||||
`read` **刻意不在 v1 范围内**。其 `read-render` 辅助工具负责文件专用的分页契约:`offset`/`limit`、行号、`totalLines`、偏移越界错误、每行预览截断、针对已选窗口的字节上限。这是行窗口渲染器,而非通用保留机制。单个 `Omitted` 数量无法表示行窗口两侧。
|
||||
`read` 仍不属于这个通用库。其 `read-render` 辅助工具负责文件专用的分页契约:`offset`/`limit`、行号、`totalLines`、偏移越界错误、每行预览截断,以及所选窗口的字节上限。这是行窗口渲染器。单个 `Omitted` 数量无法表示该窗口两侧。
|
||||
|
||||
## 使用形态
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/util/timeout/README.md
|
||||
README.md: 11c55a45a1255e14fb551e42ba3965453dbd94ae
|
||||
README.zh.md: 078c36a20b4ba7d08f67cc394b2f178f6c0a9ab8
|
||||
README.md: 0ff5550ef7ea6b8315a6a529a4b8b503162a8f12
|
||||
README.zh.md: 79d7ee674209b0324ae9428c1a04fda8a2547db5
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function runWithDeadline(upstream: AbortSignal | undefined, timeout
|
||||
|
||||
The signal only *notifies* — the caller MUST attach its own termination (`d.signal.addEventListener('abort', kill)`, or hand `d.signal` to `fetch`). Racing a promise against a timer would resolve the tool-call while the child process or socket leaks on; handing out a signal forces a real termination path to exist.
|
||||
|
||||
Pass your own `code` to `timeoutOf` so classification composes under nesting: when the `upstream` you were handed is *itself* a deadline signal (a future `tools/execute` middleware arming a per-call deadline), `AbortSignal.any` preserves the outer `TimeoutReason` if the outer timer fires first. Scoping to your `code` makes a foreign timeout read as an ordinary upstream cancel — the correct classification from your capability's view — instead of your own timeout firing when your local timer never expired.
|
||||
Pass your own `code` to `timeoutOf` so classification composes under nesting. When `upstream` is itself a deadline signal, `AbortSignal.any` preserves its `TimeoutReason` if that timer fires first. Scoping to your code makes a foreign timeout read as an ordinary upstream cancel instead of claiming that the local timer expired.
|
||||
|
||||
For a streamed transport, create one `idleWatchdog`, pass its stable `signal` into the transport, and call `watchdog.next(iterator)` for each provider read. The interval must be positive, finite, and no greater than `MAX_TIMER_DELAY_MS`; Node otherwise clamps it to one millisecond. It measures only outstanding demand, so no timer runs while downstream code renders or otherwise waits before asking for the next chunk. The primitive still only notifies, so the transport must observe the stable signal; the DeepSeek and pi-ai adapters prove that timeout closes their real response body or SDK request.
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function runWithDeadline(upstream: AbortSignal | undefined, timeout
|
||||
|
||||
该信号只会*通知*;调用方必须接入自己的终止机制(`d.signal.addEventListener('abort', kill)`,或将 `d.signal` 传给 `fetch`)。让 promise 与 timer 竞速,会在子进程或套接字仍在泄漏时就让工具调用完成;发出信号则会强制要求存在真正的终止路径。
|
||||
|
||||
将你自己的 `code` 传给 `timeoutOf`,以便分类可在嵌套中组合:当你收到的 `upstream` *本身*就是 deadline 信号时(未来启动每次调用 deadline 的 `tools/execute` 中间件),如果外层 timer 首先触发,`AbortSignal.any` 会保留外层 `TimeoutReason`。将范围限定为你的 `code`,可将外部超时视为普通 upstream 取消,这才是你所属功能视角下的正确分类,而不会在本地 timer 尚未到期时就声称自己超时。
|
||||
将你自己的 `code` 传给 `timeoutOf`,使分类可在嵌套场景中正确组合。当 `upstream` 本身是 deadline 信号时,如果该 timer 先触发,`AbortSignal.any` 会保留它的 `TimeoutReason`。将匹配范围限定为你的 code,会把外部超时视为普通的 upstream 取消,而不会声称本地 timer 已到期。
|
||||
|
||||
对于流式传输,创建一个 `idleWatchdog`,将其稳定的 `signal` 传给传输层,并为提供方的每次读取调用 `watchdog.next(iterator)`。间隔必须为正有限数,且不得超过 `MAX_TIMER_DELAY_MS`;否则 Node 会将其限制为 1 毫秒。它只对尚未完成的读取请求计时,因此当下游代码进行渲染或在请求下一个分片前以其他方式等待时,timer 不会运行。该原语仍然只会通知,因此传输层必须观察稳定信号;DeepSeek 和 pi-ai 适配器证明,超时会关闭它们的真实响应正文或 SDK 请求。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user