@deepseek-ai/dsh-skill-filesystem 0.1.1-rc.2 → 0.1.2-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml 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/skill/skill-filesystem/README.md
5
- README.md: 33fb550a9ca804c4f0f380232c2bfd94cc58a67e
6
- README.zh.md: c1d24f590c7fc525fbf15356f7a8bee9c4d1308b
5
+ README.md: 2044ad11bf1ea9b6ec02571cf0107f62cf6ad0a9
6
+ README.zh.md: 5708ed896861677dc829ef08419255d8bce6a204
package/README.md CHANGED
@@ -1,34 +1,47 @@
1
+ ---
2
+ description: "The local filesystem skill provider for users and maintainers authoring local skills or configuring how project, custom, and user skill roots are discovered and watched."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-skill-filesystem
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- Local filesystem provider for the `ctx.skills` registry.
10
+ ## Summary
6
11
 
7
- This package implements one skill source. It scans local project, custom, and user skill roots, parses `SKILL.md` or flat Markdown skill files, and registers the provider on `ctx.skills`. The registry remains in `@deepseek-ai/dsh-skill`; the durable session catalogs and model-facing loader tool remain in `@deepseek-ai/dsh-tool-skill`.
12
+ Agents can use local skills from the repository, a custom directory, or the user's agent configuration: author a skill as a directory bundle with a `SKILL.md` or a flat `<name>.md` file under any scanned root, and it appears in the session catalog. The provider discovers the project, custom, and user roots, parses each skill's YAML frontmatter, and watches the directories, so new, renamed, or deleted skills reach agents without a restart. Choose it when skills live on disk the registry (`dsh-skill`) accepts any provider, and another provider can supply skills from elsewhere.
8
13
 
9
- ## Plugin
14
+ ## Table of Contents
10
15
 
11
- Requires `ctx.skills` (`inject: ['skills']`).
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
12
22
 
13
- ### Config
23
+ -----
14
24
 
15
- | Field | Default | Meaning |
16
- |---|---|---|
17
- | `providerName` | `filesystem` | Unique name used to register this provider on `ctx.skills`. |
18
- | `includeDefaultRoots` | `true` | Include project and user roots around `customSkillDirs`; set false for an isolated custom-root provider. |
19
- | `dshHome` | `$DSH_HOME` or `~/.dsh` | DeepSeek Harness config root resolved by [`@deepseek-ai/dsh-home-paths`](../../util/home-paths/README.md); scans `skills` under this directory. |
20
- | `agentsHome` | `$DSH_AGENTS_HOME` or `~/.agents` | Shared agent config root scanned for compatible skills. |
21
- | `customSkillDirs` | `[]` | Additional local skill roots scanned after project roots and before user roots. |
22
- | `watch` | `true` | Watch host-local roots and invalidate the local provider when catalog membership or frontmatter may have changed. |
23
- | `watchUsePolling` | `false` | Use Chokidar polling instead of native events for existing skill roots. |
24
- | `watchStabilityThresholdMs` | `200` | Stable-write window for Chokidar `add` and `change` events. |
25
- | `watchPollIntervalMs` | `100` | Chokidar polling/stability interval and missing-path probe interval. |
26
- | `watchMaxProjects` | `128` | Maximum distinct project roots retained in the watcher LRU. |
27
- | `watchFollowSymlinks` | `true` | Follow symbolic links while watching existing roots. |
28
-
29
- ## Discovery
30
-
31
- Default roots are resolved in this provider's rank order:
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Mount the plugin to make local skills available to agents. It scans the project, custom, and user skill roots below, parses each skill's frontmatter into a catalog entry, and loads the body on demand; it also watches the roots so new, renamed, or deleted skills reach the next catalog without a restart.
29
+
30
+ ### When to choose it
31
+
32
+ Use this provider when skills live on disk in the repository, a custom directory, or the user's agent configuration. Avoid it when skills come from a remote registry or embedded plugin data: the registry accepts any provider, and this package is one implementation.
33
+
34
+ ### Skill format
35
+
36
+ A skill is either a directory bundle `<name>/SKILL.md` or a flat file `<name>.md` at the top level of a scanned root; nested `**/SKILL.md` files are deliberately not discovered. The file starts with YAML frontmatter: required `name` and `description`, plus optional `whenToUse`, `metadata`, `disable-model-invocation`, and `user-invocable`.
37
+
38
+ `disable-model-invocation: true` keeps the skill out of model-facing catalogs and loaders; `user-invocable: false` keeps it out of human-facing commands, and omitted fields default to permitting their surface. The two keys accept YAML booleans plus the case-insensitive `true`/`false`, `yes`/`no`, `on`/`off`, and `1`/`0` forms; a rejected spelling or a non-boolean value drops the whole skill with a warning rather than silently permitting a surface.
39
+
40
+ The catalog and the body have separate lifecycles: discovery parses frontmatter into the catalog entry, and every load re-reads the current file, so editing a skill body needs no versioning or cache invalidation.
41
+
42
+ ### Roots and priority
43
+
44
+ Default roots are scanned in this provider's rank order:
32
45
 
33
46
  | Rank | Source | Path |
34
47
  |---|---|---|
@@ -38,26 +51,83 @@ Default roots are resolved in this provider's rank order:
38
51
  | 400 | `user-dsh` | `<dshHome>/skills` |
39
52
  | 500 | `user-agents` | `<agentsHome>/skills` |
40
53
 
41
- The project root is the nearest ancestor containing `.git`; without one, the current cwd is used. The user DSH root skips its `.system` child so system-owned directories are not treated as normal user skills. `includeDefaultRoots: false` omits the project and user rows and the `$DSH_BUNDLED_SKILL_DIR` environment default while retaining explicitly configured custom and bundled roots, allowing several uniquely named isolated providers to see only their own roots. This provider supplies project and user skills; another provider may supply built-in system skills.
54
+ The project root is the nearest ancestor containing `.git`; without one, the current cwd is used. The user DSH root skips its `.system` child. `includeDefaultRoots: false` omits the project and user rows plus the `$DSH_BUNDLED_SKILL_DIR` default so an isolated provider sees only its own configured roots; `bundledSkillDir` adds a bundled root at rank 600.
55
+
56
+ ### Mount and configure
57
+
58
+ Load the plugin alongside the skill registry; it requires `ctx.skills`.
59
+
60
+ ```yaml
61
+ - name: '@deepseek-ai/dsh-skill'
62
+ - name: '@deepseek-ai/dsh-skill-filesystem'
63
+ ```
64
+
65
+ | Field | Default | Meaning |
66
+ |---|---|---|
67
+ | `providerName` | `filesystem` | Unique provider name registered on `ctx.skills` |
68
+ | `includeDefaultRoots` | `true` | Include project and user roots around `customSkillDirs` |
69
+ | `dshHome` | `$DSH_HOME` or `~/.dsh` | Harness config root; its `skills` subdirectory is scanned |
70
+ | `agentsHome` | `$DSH_AGENTS_HOME` or `~/.agents` | Shared agent config root scanned for compatible skills |
71
+ | `customSkillDirs` | `[]` | Additional local skill roots, after project roots and before user roots |
72
+ | `watch` | `true` | Watch local roots and invalidate the provider when the catalog may have changed |
73
+ | `bundledSkillDir` | — | Bundled skill root scanned at rank 600 when configured |
74
+
75
+ The remaining `watch*` fields tune Chokidar behavior — polling, stability window, interval, project cap, and symlink following. The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-skill-filesystem) is the exhaustive source for every field.
76
+
77
+ ### Change detection
42
78
 
43
- When `ctx.fs` is available, discovery lists roots through `ctx.fs.listDir`, reads skill files through `ctx.fs.readText`, and probes `.git` through the filesystem service. Full skill loads forward the lookup abort signal to filesystem metadata and content reads. Without a filesystem service, the provider falls back to abortable Node filesystem I/O so minimal local contexts can still load skills. Confirmed missing paths are valid empty state, malformed or non-text entries warn and skip, and unexpected discovery/read failures make the registry snapshot incomplete rather than replacing a last-good model catalog with a misleading deletion.
79
+ Existing roots are watched, so adding, renaming, or deleting a skill (or editing its frontmatter) triggers a catalog refresh for the next model step; edits below `references`, `scripts`, `assets`, and other bundle resources do not. The first-party `write` and `edit` tools invalidate the provider directly when their target could affect a watched skill, so the model observes its own filesystem mutation without waiting for the host watcher. External IDE, Git, and shell changes are picked up by the host watcher, and a root that does not exist yet is probed until it appears.
44
80
 
45
- ## Catalog Change Detection
81
+ ### Observable success and failures
46
82
 
47
- Existing skill roots are watched with Chokidar. Before opening a native watcher, the provider realpaths the existing root or ancestor and restores the next missing segment; when `watchFollowSymlinks` is false and the root itself is a symbolic link, it preserves that final link so Chokidar can enforce the configured boundary. Discovery and diagnostics retain the configured path, while Windows cannot otherwise mix an 8.3 alias with long-form libuv events. The provider observes direct bundle directory additions/removals, flat Markdown additions/removals, and direct `SKILL.md` additions/removals/changes; `change` exists to rediscover catalog frontmatter such as `name` and `description`. Changes below `references`, `scripts`, `assets`, or other bundle resources do not invalidate the catalog. Events delivered in the same microtask batch collapse to one provider invalidation.
83
+ A valid skill under any scanned root appears in the session catalog sorted by name, and loading it returns the current file body. A file without valid frontmatter, an invalid name, or an invalid invocation value is skipped with a warning, so the model catalog receives no per-skill diagnostic and cannot distinguish an absent skill from an invalid one. Unexpected discovery or read failures leave the catalog observation incomplete rather than replacing the last-good view with a misleading deletion.
48
84
 
49
- A root that does not exist is followed from the nearest existing ancestor one missing path segment at a time. The next segment is probed with `fs.watchFile`; once `.agents`, `skills`, or the configured root appears, observation advances until Chokidar can attach to the real root. Root deletion reverses this process, so deleting and recreating an entire skills directory remains observable. Project-scoped watchers are bounded by `watchMaxProjects`; revisiting an evicted project reattaches observation during discovery.
85
+ -----
50
86
 
51
- The first-party filesystem `write` and `edit` tools also synchronously invalidate the provider through `fs/observed` when their target could affect a watched skill entry. This fast path makes the next model step observe its own filesystem mutation without waiting for the host watcher. External IDE, Git, shell, and process changes rely on Chokidar or the missing-path probe. Existing-root watchers remain persistent until effect teardown so Chokidar owns asynchronous native error events; startup/runtime watcher failures are logged and retried. Discovery still scans readable roots and returns their candidates for direct loading, but marks the observation incomplete so it is not cached or published as an authoritative model catalog. Effect teardown closes every watcher and contains late callbacks.
87
+ <a id="understand-the-implementation"></a>
88
+ ## Understand the implementation
52
89
 
53
- ## Skill Format
90
+ <details>
91
+ <summary>Implementation internals — click to expand</summary>
54
92
 
55
- Skills can be single-level directory bundles (`<name>/SKILL.md`) or flat Markdown files (`<name>.md`). Nested `**/SKILL.md` discovery is deliberately excluded. Frontmatter is parsed as an open YAML object with the `yaml` package; this provider interprets required `name` and `description`, plus optional `whenToUse`, `metadata`, `disable-model-invocation`, and `user-invocable`. Names must be kebab-case.
93
+ This section explains how discovery and watching are organized; the observable behavior is fully covered in [Use this package](#use-this-package).
56
94
 
57
- The two invocation fields accept YAML booleans and the case-insensitive forms `true`/`false`, `yes`/`no`, `on`/`off`, and `1`/`0`. `disable-model-invocation: true` excludes the skill from model-facing catalogs and loaders; `user-invocable: false` excludes it from human-facing commands. Each omitted field defaults to permitting its surface, and the provider always emits both positive internal policy values, including when both keys are absent. A rejected camel-case spelling or a non-boolean invocation value drops the entire skill from discovery with a warning instead of discarding only that field or falling back to a permissive default. Invocation policy fails closed because ignoring invalid data could expose a skill on a disabled surface; wrong-typed optional `whenToUse` and `metadata` values are omitted because neither currently grants invocation.
95
+ ### Design concept
58
96
 
59
- The catalog and body have separate lifecycles. Discovery parses frontmatter to produce the summary. Every `skill(name)` load rereads and reparses the current file, so body edits need no hash, revision, cache invalidation, or proactive model notification. A frontmatter rename between discovery and loading rejects the stale name and invalidates the provider; the next catalog observation publishes the new name.
97
+ The provider is built on two separations. First, catalog versus body: discovery parses frontmatter into summaries, while every load re-reads the file, so body edits need no hash, revision, or cache invalidation. Second, discovery versus watching: `list()` scans roots and resolves the project root through `ctx.fs` when a filesystem service is present (falling back to abortable Node I/O), while a separate watch manager owns Chokidar handles, missing-root probes, and invalidation.
60
98
 
99
+ ### Source map
100
+
101
+ | File | Role |
102
+ |---|---|
103
+ | [`src/index.ts`](src/index.ts) | Plugin entry, provider, root resolution, frontmatter parsing, watch manager |
104
+ | [`src/invariant.ts`](src/invariant.ts) | Invariant companion |
105
+
106
+ ### Discovery flow
107
+
108
+ Discovery resolves the root list for the lookup cwd, asks the watch manager to attach to each root, then scans each root's direct entries: directory bundles resolve `<name>/SKILL.md`, flat files resolve `<name>.md`. Each file is parsed for frontmatter — `name` must be kebab-case, `description` is required, and the invocation keys resolve through the strict boolean grammar — and candidates carry the root's source label and rank so the registry can merge them with other providers. Confirmed missing paths are valid empty state; malformed or non-text entries warn and skip.
109
+
110
+ ### Watching and invalidation
111
+
112
+ Existing roots are watched by Chokidar at depth 1; a root that does not exist is followed from its nearest existing ancestor one missing segment at a time using `fs.watchFile`. Relevant events — direct bundle add/remove, flat `.md` add/remove, and direct `SKILL.md` add/remove/change — coalesce into one provider invalidation per microtask batch, while resource-subtree changes are ignored. The watch manager is bounded by `watchMaxProjects`, logs and retries failed startup, and closes every handle at teardown. First-party `write`/`edit` mutations invalidate synchronously through the `fs/observed` event.
113
+
114
+ </details>
115
+
116
+ -----
117
+
118
+ <a id="further-exploration"></a>
119
+ ## Further Exploration
120
+
121
+ Read these pages when the package-level contract is not enough. They move from the registry contract to the consumer that renders discovered skills and the home-path resolution used by the config defaults.
122
+
123
+ - [Skill subsystem reference](../../../docs/subsystems/skills.md) — the registry contract and the local discovery priority table.
124
+ - [skill package](../skill/README.md) — the registry this provider registers on.
125
+ - [tool-skill package](../tool-skill/README.md) — how discovered skills reach the session catalog and the model.
126
+ - [home-paths package](../../util/home-paths/README.md) — how `dshHome` and `agentsHome` resolve.
127
+
128
+ -----
129
+
130
+ <a id="model-experience"></a>
61
131
  ## Model Experience
62
132
 
63
133
  Indirectly, through `dsh-tool-skill`, which renders this provider's invocable names and capped descriptions into the initial or replacement catalog and a selected current instruction body plus resource-base guidance into retained tool history while paths, provider ranks, and disabled skills remain hidden.
@@ -68,8 +138,23 @@ Watcher invalidation can cause the named consumer to append a replacement catalo
68
138
 
69
139
  ## Known Limitations and Deferred Work
70
140
 
141
+ <a id="known-limitations-and-deferred-work"></a>
142
+
143
+
144
+ These limits define when the provider is a poor fit or needs special operational care. They are current package constraints, not a task backlog.
145
+
71
146
  - **Discovery is one level deep** — only `<root>/<name>/SKILL.md` and `<root>/<name>.md` are recognized; nested skill trees and package manifests are ignored.
72
147
  - **Project scope is the nearest `.git` ancestor** — workspaces without that marker fall back to the supplied cwd, with no alternate project-root marker or monorepo subproject selection.
73
148
  - **Malformed entries disappear with a warning** — the model catalog receives no per-skill diagnostic and cannot distinguish an absent skill from an invalid one; unexpected I/O failures preserve the last-good catalog instead.
74
149
  - **Missing-root observation polls one path segment** — roots absent at startup use `fs.watchFile` at `watchPollIntervalMs` until Chokidar can attach, trading bounded detection latency for reliable creation detection across IDE, Git, and shell workflows.
75
150
  - **No body revision protocol** — a loaded body is ordinary retained tool history; later file edits affect later calls but neither rewrite old results nor announce that the body changed.
151
+
152
+ <a id="dev-note"></a>
153
+ ### Dev Note
154
+
155
+ <details>
156
+ <summary>Working context for maintainers — click to expand</summary>
157
+
158
+ This Dev Note is working context for maintainers and is explicitly non-authoritative — shipped behavior and limits live in the sections above and in the code. A TODO in `src/index.ts` proposes extracting the Chokidar and missing-root observation into a Cordis file-watch service, keeping skill filtering and invalidation here; the missing-root polling tradeoff documented above is part of that open design.
159
+
160
+ </details>
package/README.zh.md CHANGED
@@ -1,34 +1,47 @@
1
+ ---
2
+ description: "本地文件系统 skill 提供方,供编写本地 skill、或配置项目、自定义与用户 skill 根目录如何被发现与监视的用户与维护者阅读。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-skill-filesystem
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- `ctx.skills` 注册表的本地文件系统提供方。
10
+ ## 概述
6
11
 
7
- 该包实现一个 skill(技能)来源。它扫描本地项目、自定义和用户 skill 根目录,解析 `SKILL.md` 或平铺 Markdown skill 文件,并将提供方注册到 `ctx.skills`。注册表仍位于 `@deepseek-ai/dsh-skill`;持久化会话目录和面向模型的 loader 工具仍位于 `@deepseek-ai/dsh-tool-skill`。
12
+ agent(智能体)可以使用来自仓库、自定义目录或用户 agent 配置的本地 skill(技能):把 skill 编写为任一被扫描根目录下的目录 bundle(内含 `SKILL.md`)或平铺 `<name>.md` 文件,它就会出现在会话目录中。该提供方发现项目、自定义与用户根目录,解析每个 skill YAML frontmatter,并监视这些目录,因此新增、改名或删除的 skill 无需重启即可到达 agent。当 skill 存放在磁盘上时选择它——注册表(`dsh-skill`)接受任意提供方,其他提供方可以从别处提供 skill。
8
13
 
9
- ## 插件
14
+ ## 目录
10
15
 
11
- 需要 `ctx.skills`(`inject: ['skills']`)。
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
12
22
 
13
- ### 配置
23
+ -----
14
24
 
15
- | 字段 | 默认值 | 含义 |
16
- |---|---|---|
17
- | `providerName` | `filesystem` | 在 `ctx.skills` 上注册该提供方时使用的唯一名称。 |
18
- | `includeDefaultRoots` | `true` | `customSkillDirs` 周围包含项目根和用户根;设为 false 时仅使用隔离的自定义根。 |
19
- | `dshHome` | `$DSH_HOME` 或 `~/.dsh` | 由 [`@deepseek-ai/dsh-home-paths`](../../util/home-paths/README.zh.md) 解析的 DeepSeek Harness 配置根目录;扫描该目录下的 `skills`。 |
20
- | `agentsHome` | `$DSH_AGENTS_HOME` 或 `~/.agents` | 为兼容 skill 扫描的共享 agent(智能体)配置根目录。 |
21
- | `customSkillDirs` | `[]` | 在项目根目录之后、用户根目录之前扫描的其他本地 skill 根目录。 |
22
- | `watch` | `true` | 监视宿主本地根,并在目录成员或 frontmatter 可能发生变化时使本地提供方失效。 |
23
- | `watchUsePolling` | `false` | 对现有 skill 根使用 Chokidar 轮询,而不是原生事件。 |
24
- | `watchStabilityThresholdMs` | `200` | Chokidar `add` 和 `change` 事件的稳定写入窗口。 |
25
- | `watchPollIntervalMs` | `100` | Chokidar 轮询/稳定性间隔和缺失路径探测间隔。 |
26
- | `watchMaxProjects` | `128` | watcher LRU 中保留的不同项目根数量上限。 |
27
- | `watchFollowSymlinks` | `true` | 监视现有根时跟随符号链接。 |
28
-
29
- ## 发现
30
-
31
- 默认根按该提供方的 rank 顺序解析:
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 挂载插件即可让本地 skill agent 可用。它扫描下方的项目、自定义与用户 skill 根目录,把每个 skill frontmatter 解析为目录条目,并按需加载正文;它还会监视这些根目录,使新增、改名或删除的 skill 无需重启即可进入下一次目录。
29
+
30
+ ### 何时选择
31
+
32
+ skill 存放在磁盘上——仓库、自定义目录或用户的 agent 配置中——时,使用此提供方。当 skill 来自远程注册表或嵌入式插件数据时,请避免使用:注册表接受任意提供方,本包只是其中一种实现。
33
+
34
+ ### skill 格式
35
+
36
+ skill 可以是被扫描根目录顶层的目录 bundle `<name>/SKILL.md`,也可以是平铺文件 `<name>.md`;刻意不支持发现嵌套的 `**/SKILL.md`。文件以 YAML frontmatter 开头:必填 `name` `description`,另有可选 `whenToUse`、`metadata`、`disable-model-invocation` `user-invocable`。
37
+
38
+ `disable-model-invocation: true` 会把 skill 从面向模型的目录和 loader 中排除;`user-invocable: false` 会把它从面向用户的命令中排除,省略的字段默认允许对应接口调用。这两个键接受 YAML 布尔值,以及不区分大小写的 `true`/`false`、`yes`/`no`、`on`/`off` 和 `1`/`0` 形式;被拒绝的拼写或非布尔值会让整个 skill 随警告一起被丢弃,而不会静默允许某个接口。
39
+
40
+ 目录与正文具有独立的生命周期:发现阶段把 frontmatter 解析进目录条目,每次加载都会重新读取当前文件,因此编辑 skill 正文无需版本化或缓存失效。
41
+
42
+ ### 根目录与优先级
43
+
44
+ 默认根按该提供方的 rank 顺序扫描:
32
45
 
33
46
  | Rank | 来源 | 路径 |
34
47
  |---|---|---|
@@ -38,38 +51,110 @@
38
51
  | 400 | `user-dsh` | `<dshHome>/skills` |
39
52
  | 500 | `user-agents` | `<agentsHome>/skills` |
40
53
 
41
- 项目根目录是包含 `.git` 的最近祖先目录;如果不存在,则使用当前 cwd。用户 DSH 根目录会跳过其 `.system` 子目录,因此归系统所有的目录不会被当作普通用户 skill。`includeDefaultRoots: false` 会省略项目根、用户根以及 `$DSH_BUNDLED_SKILL_DIR` 环境默认值,同时保留显式配置的自定义根与 bundled 根,因此可以挂载多个只看到自身根的唯一命名隔离提供方。该提供方提供项目和用户 skill;其他提供方可提供内置系统 skill。
54
+ 项目根目录是包含 `.git` 的最近祖先目录;如果不存在,则使用当前 cwd。用户 DSH 根目录会跳过其 `.system` 子目录。`includeDefaultRoots: false` 会省略项目根、用户根以及 `$DSH_BUNDLED_SKILL_DIR` 默认值,使隔离提供方只看到自身配置的根;`bundledSkillDir` 会按 rank 600 添加一个内置根目录。
55
+
56
+ ### 挂载与配置
57
+
58
+ 与 skill 注册表一起加载该插件;它需要 `ctx.skills`。
59
+
60
+ ```yaml
61
+ - name: '@deepseek-ai/dsh-skill'
62
+ - name: '@deepseek-ai/dsh-skill-filesystem'
63
+ ```
64
+
65
+ | 字段 | 默认值 | 含义 |
66
+ |---|---|---|
67
+ | `providerName` | `filesystem` | 注册到 `ctx.skills` 的唯一提供方名称 |
68
+ | `includeDefaultRoots` | `true` | 在 `customSkillDirs` 周围包含项目根与用户根 |
69
+ | `dshHome` | `$DSH_HOME` 或 `~/.dsh` | Harness 配置根目录;扫描其 `skills` 子目录 |
70
+ | `agentsHome` | `$DSH_AGENTS_HOME` 或 `~/.agents` | 为兼容 skill 扫描的共享 agent 配置根目录 |
71
+ | `customSkillDirs` | `[]` | 其他本地 skill 根目录,位于项目根之后、用户根之前 |
72
+ | `watch` | `true` | 监视本地根,并在目录可能变化时使提供方失效 |
73
+ | `bundledSkillDir` | — | 配置后按 rank 600 扫描的内置 skill 根目录 |
74
+
75
+ 其余 `watch*` 字段用于调节 Chokidar 行为——轮询、稳定窗口、间隔、项目上限与符号链接跟随。生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-skill-filesystem)是每个字段的穷尽式真源。
76
+
77
+ ### 变更检测
42
78
 
43
- `ctx.fs` 可用时,发现通过 `ctx.fs.listDir` 列出根,通过 `ctx.fs.readText` 读取 skill 文件,并通过文件系统服务探测 `.git`。完整 skill 加载会将查找中止信号转发给文件系统元数据和内容读取。如果没有文件系统服务,提供方回退到可中止的 Node 文件系统 I/O,使最小本地上下文仍能加载 skill。已确认缺失的路径属于有效空状态;遇到格式错误或非文本条目时,提供方会发出警告并跳过;意外的发现或读取失败会使注册表快照不完整,系统不会因此用看似发生删除的结果替换上一份可用模型目录。
79
+ 现有根目录会被监视,因此新增、改名或删除 skill(或编辑其 frontmatter)会在下一个模型步骤触发目录刷新;`references`、`scripts`、`assets` bundle 资源下的编辑不会触发。当第一方 `write` `edit` 工具的目标可能影响受监视的 skill 时,它们会直接使提供方失效,因此模型无需等待宿主 watcher 即可观察到自身的文件系统变更。外部 IDE、Git shell 变更由宿主 watcher 捕获;尚不存在的根目录会被探测,直至其出现。
44
80
 
45
- ## 目录变更检测
81
+ ### 可观察的成功与失败
46
82
 
47
- 现有 skill 根由 Chokidar 监视。打开原生 watcher 前,提供方会对现有根或祖先执行 realpath 解析,并拼回下一个缺失路径段;当 `watchFollowSymlinks` 为 false 且根本身是符号链接时,提供方不会展开最后这一级链接,使 Chokidar 能够强制执行配置边界。发现与诊断仍保留配置路径,从而避免 Windows 在 libuv 内部混用 8.3 别名与长格式事件路径。提供方会观察直属 bundle 目录的添加/移除、平铺 Markdown 文件的添加/移除,以及直接 `SKILL.md` 的添加/移除/变更;`change` 事件用于重新发现 `name`、`description` 等目录 frontmatter。`references`、`scripts`、`assets` 或其他 bundle 资源下的变更不会使目录失效。同一微任务批次内送达的事件会合并为一次提供方失效。
83
+ 任一被扫描根目录下的有效 skill 都会按名称排序出现在会话目录中,加载它即可返回当前文件正文。缺少有效 frontmatter、名称无效或调用值无效的文件会随警告被跳过,因此模型目录不会收到逐 skill 诊断,也无法区分缺失的 skill 与无效的 skill。意外的发现或读取失败会让目录观测保持不完整,而不会用看似发生删除的结果替换最后一份可用视图。
48
84
 
49
- 不存在的根会从最近的现有祖先开始,每次沿一个缺失路径段跟踪。系统使用 `fs.watchFile` 探测下一段;当 `.agents`、`skills` 或已配置的根出现后,观察会逐级推进,直至 Chokidar 可以附加到真实根。根删除时,该过程反向执行,因此删除再重建整个 skills 目录仍可被观察到。按项目划分的 watcher 数量受 `watchMaxProjects` 限制;再次访问已被驱逐的项目时,发现阶段会重新附加观察。
85
+ -----
50
86
 
51
- 如果第一方文件系统 `write` 和 `edit` 工具的目标可能影响受监视的 skill 条目,它们还会通过 `fs/observed` 同步使提供方失效。这条快速路径让模型的下一个步骤无需等待宿主 watcher,即可观察到自身的文件系统变更。外部 IDE、Git、shell 和进程产生的变更依赖 Chokidar 或缺失路径探测。现有根的 watcher 会保持持久状态直至 effect 释放,使 Chokidar 能够接管异步原生错误事件;watcher 启动或运行时失败会被记录并触发重试。发现过程仍会扫描可读根目录,并返回其候选项供直接加载,但会将观测标记为不完整,因此不会缓存,也不会作为权威模型目录发布。effect 释放会关闭所有 watcher,并收束延迟回调。
87
+ <a id="understand-the-implementation"></a>
88
+ ## 理解实现
52
89
 
53
- ## skill 格式
90
+ <details>
91
+ <summary>实现细节——点击展开</summary>
54
92
 
55
- skill 可以是单层目录 bundle(`<name>/SKILL.md`),也可以是平铺 Markdown 文件(`<name>.md`)。刻意不支持发现嵌套的 `**/SKILL.md`。Frontmatter 使用 `yaml` 包解析为开放的 YAML 对象;该提供方解析必填的 `name` 和 `description`,以及可选的 `whenToUse`、`metadata`、`disable-model-invocation` 和 `user-invocable`。名称必须使用 kebab-case。
93
+ 本节解释发现与监视如何组织;可观察行为已在[使用本包](#use-this-package)中完整说明。
56
94
 
57
- 这两个调用字段接受 YAML 布尔值,以及不区分大小写的 `true`/`false`、`yes`/`no`、`on`/`off` 和 `1`/`0`。`disable-model-invocation: true` 会从面向模型的目录和 loader 中排除该 skill;`user-invocable: false` 会从面向用户的命令中排除该 skill。每个省略的字段都默认为允许对应接口调用;提供方始终输出两个正向内部策略值,即使两个键都不存在也不例外。若使用驼峰拼写或提供非布尔调用值,系统会记录警告并从发现结果中排除整个 skill,而不是只丢弃该字段或回退到宽松的默认值。调用策略校验遵循失败时默认拒绝原则,因为忽略无效数据可能会在已禁用的接口上暴露 skill;类型错误的可选 `whenToUse` 和 `metadata` 值则会被省略,因为这两个字段目前都不授予调用权限。
95
+ ### 设计理念
58
96
 
59
- 目录与正文具有独立的生命周期。发现阶段解析 frontmatter 以生成概述。每次 `skill(name)` 加载都会重新读取并解析当前文件,因此正文编辑不需要 hash、修订号、缓存失效或主动通知模型。若在发现与加载之间更改 frontmatter 中的名称,系统会拒绝陈旧名称并使提供方失效;下一次目录观察会发布新名称。
97
+ 该提供方建立在两个分离之上。第一,目录与正文分离:发现阶段把 frontmatter 解析为摘要,而每次加载都重新读取文件,因此正文编辑无需 hash、修订号或缓存失效。第二,发现与监视分离:`list()` 在存在文件系统服务时通过 `ctx.fs` 扫描根目录并解析项目根(否则回退到可中止的 Node I/O),而独立的监视管理器负责 Chokidar 句柄、缺失根探测与失效。
60
98
 
99
+ ### 源码地图
100
+
101
+ | 文件 | 职责 |
102
+ |---|---|
103
+ | [`src/index.ts`](src/index.ts) | 插件入口、提供方、根解析、frontmatter 解析、监视管理器 |
104
+ | [`src/invariant.ts`](src/invariant.ts) | 不变式伴生插件 |
105
+
106
+ ### 发现流程
107
+
108
+ 发现过程先为查找 cwd 解析根列表,让监视管理器附加到每个根,再扫描每个根的直接条目:目录 bundle 解析为 `<name>/SKILL.md`,平铺文件解析为 `<name>.md`。每个文件都会解析 frontmatter——`name` 必须为 kebab-case,`description` 必填,调用键按严格布尔语法解析——候选项携带根目录的来源标签与 rank,供注册表与其他提供方合并。已确认缺失的路径属于有效空状态;格式错误或非文本条目会随警告跳过。
109
+
110
+ ### 监视与失效
111
+
112
+ 现有根目录由 Chokidar 以深度 1 监视;不存在的根会从最近的现有祖先开始,借助 `fs.watchFile` 每次沿一个缺失路径段跟踪。相关事件——直属 bundle 添加/移除、平铺 `.md` 添加/移除、直接 `SKILL.md` 添加/移除/变更——会在每个微任务批次合并为一次提供方失效,资源子树下的变更则被忽略。监视管理器受 `watchMaxProjects` 限制,会记录并重试失败的启动,并在释放时关闭所有句柄。第一方 `write`/`edit` 变更通过 `fs/observed` 事件同步失效。
113
+
114
+ </details>
115
+
116
+ -----
117
+
118
+ <a id="further-exploration"></a>
119
+ ## 进一步探索
120
+
121
+ 当包级约定不够用时阅读以下页面。它们从注册表约定逐步进入渲染已发现 skill 的消费方,以及配置默认值使用的 home 路径解析。
122
+
123
+ - [skill 子系统参考](../../../docs/subsystems/skills.zh.md)——注册表约定与本地发现优先级表。
124
+ - [skill 包](../skill/README.zh.md)——该提供方注册到的注册表。
125
+ - [tool-skill 包](../tool-skill/README.zh.md)——已发现 skill 如何到达会话目录与模型。
126
+ - [home-paths 包](../../util/home-paths/README.zh.md)——`dshHome` 与 `agentsHome` 如何解析。
127
+
128
+ -----
129
+
130
+ <a id="model-experience"></a>
61
131
  ## 模型体验
62
132
 
63
- 通过 `dsh-tool-skill` 间接影响模型。它将该提供方的可调用名称和有长度上限的描述渲染到初始目录或替换目录中,并将所选的当前指令正文与资源基底指引渲染到保留的工具历史中;路径、提供方 rank 和已禁用 skill 仍被隐藏。
133
+ 通过 `dsh-tool-skill` 间接影响模型;它把该提供方的可调用名称和有长度上限的描述渲染到初始目录或替换目录中,并把所选的当前指令正文与资源基底指引渲染到已保留工具历史中;路径、提供方 rank 与已禁用 skill 仍被隐藏。
64
134
 
65
135
  #### KV Cache 影响
66
136
 
67
137
  watcher 触发的失效可促使上述消费方在现有请求历史中追加替换目录。仅涉及正文的编辑不会改变目录 digest。
68
138
 
69
- ## 已知限制与暂缓事项
139
+ ## 已知限制与延期工作
140
+
141
+ <a id="known-limitations-and-deferred-work"></a>
142
+
143
+
144
+ 这些限制说明该提供方何时不合适,或何时需要特别的运维注意。它们是当前包约束,不是任务积压。
145
+
146
+ - **发现深度为一层**——只识别 `<root>/<name>/SKILL.md` 与 `<root>/<name>.md`;忽略嵌套 skill 树与包 manifest(元数据清单)。
147
+ - **项目范围为最近 `.git` 祖先**——没有该标记的工作区回退到提供的 cwd,不支持其他项目根标记或 monorepo 子项目选择。
148
+ - **格式错误的条目随警告消失**——模型目录不会收到逐 skill 诊断,无法区分缺失的 skill 与无效的 skill;意外的 I/O 失败则会保留最后一份可用目录。
149
+ - **缺失根观察每次轮询一个路径段**——启动时不存在的根会使用 `fs.watchFile` 按 `watchPollIntervalMs` 轮询,直至 Chokidar 可以附加;这以有界检测延迟换取跨 IDE、Git 与 shell 工作流的可靠创建检测。
150
+ - **无正文修订协议**——已加载正文是普通的已保留工具历史;后续文件编辑会影响后续调用,但既不会改写旧结果,也不会通知正文已变化。
151
+
152
+ <a id="dev-note"></a>
153
+ ### 开发备注
154
+
155
+ <details>
156
+ <summary>维护者的工作上下文——点击展开</summary>
157
+
158
+ 本开发备注是维护者的工作上下文,明确不具权威性——已交付的行为与限制以上文和代码为准。`src/index.ts` 中的一条 TODO 提议把 Chokidar 与缺失根观察提取为 Cordis 文件监视服务,把 skill 过滤与失效保留在此处;上文记录的缺失根轮询取舍是该开放设计的一部分。
70
159
 
71
- - **发现深度为一层**:只识别 `<root>/<name>/SKILL.md` 和 `<root>/<name>.md`;忽略嵌套 skill 树和包 manifest(元数据清单)。
72
- - **项目范围为最近 `.git` 祖先**:没有该标记的工作区回退到提供的 cwd,不支持其他项目根标记或 monorepo 子项目选择。
73
- - **格式错误的条目会随警告消失**:模型目录不会收到每个 skill 的诊断,无法区分缺失的 skill 与无效的 skill;意外 I/O 失败则会保留最后一份可用目录。
74
- - **缺失根观察每次轮询一个路径段**:启动时不存在的根会使用 `fs.watchFile` 按 `watchPollIntervalMs` 轮询,直至 Chokidar 可以附加;这以有界检测延迟换取跨 IDE、Git 和 shell 工作流的可靠创建检测。
75
- - **无正文修订协议**:已加载的正文是普通的已保留工具历史;后续文件编辑会影响后续调用,但既不会改写旧结果,也不会通知正文已发生变化。
160
+ </details>
@@ -15,7 +15,7 @@ export declare const name = "skill-filesystem";
15
15
  export declare const inject: string[];
16
16
  /** Local filesystem skill provider configuration. */
17
17
  export interface Config {
18
- /** Unique provider name. Defaults to `local`. */
18
+ /** Unique provider name. Defaults to `filesystem`. */
19
19
  providerName?: string;
20
20
  /** Whether project and user roots are included around custom roots. */
21
21
  includeDefaultRoots?: boolean;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-skill-filesystem",
3
3
  "description": "Local filesystem skill provider for the DeepSeek Harness",
4
- "version": "0.1.1-rc.2",
4
+ "version": "0.1.2-alpha.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -32,22 +32,22 @@
32
32
  ],
33
33
  "license": "MIT",
34
34
  "peerDependencies": {
35
- "@deepseek-ai/dsh-fs": "^0.1.1-rc.2",
36
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
37
- "@deepseek-ai/dsh-home-paths": "^0.1.1-rc.2",
38
- "@deepseek-ai/dsh-skill": "^0.1.1-rc.2",
39
- "@deepseek-ai/cordis": "^4.0.1"
35
+ "@deepseek-ai/dsh-fs": "^0.1.2-alpha.3",
36
+ "@deepseek-ai/dsh-home-paths": "^0.1.2-alpha.3",
37
+ "@deepseek-ai/cordis": "^4.0.2",
38
+ "@deepseek-ai/dsh-skill": "^0.1.2-alpha.3",
39
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.3"
40
40
  },
41
41
  "dependencies": {
42
42
  "chokidar": "^5.0.0",
43
43
  "yaml": "^2.4.2",
44
- "@deepseek-ai/schemastery": "^3.18.1"
44
+ "@deepseek-ai/schemastery": "^3.18.2"
45
45
  },
46
46
  "devDependencies": {
47
- "@deepseek-ai/dsh-fs": "^0.1.1-rc.2",
48
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
49
- "@deepseek-ai/dsh-home-paths": "^0.1.1-rc.2",
50
- "@deepseek-ai/dsh-skill": "^0.1.1-rc.2",
51
- "@deepseek-ai/cordis": "^4.0.1"
47
+ "@deepseek-ai/dsh-fs": "^0.1.2-alpha.3",
48
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.3",
49
+ "@deepseek-ai/dsh-home-paths": "^0.1.2-alpha.3",
50
+ "@deepseek-ai/cordis": "^4.0.2",
51
+ "@deepseek-ai/dsh-skill": "^0.1.2-alpha.3"
52
52
  }
53
53
  }