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

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/tool-skill/README.md
5
- README.md: 4cfd8f22b3cfaf22b6f9f6cdc48f0db994858906
6
- README.zh.md: 4b4fc6382a7f3e00592b6ebbf0b4887748cddf70
5
+ README.md: c814f2cd78ed53576d1f52b1d47f16826e14e77e
6
+ README.zh.md: c083f4d8419df9de3148343be857a4ea1b1522db
package/README.md CHANGED
@@ -1,42 +1,117 @@
1
+ ---
2
+ description: "The model-facing skill catalog and loader tool for users and maintainers understanding what agents see, or configuring the session skill catalog."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-tool-skill
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- The model-facing skill catalog and `skill` tool.
10
+ ## Summary
11
+
12
+ Agents can discover and load skills during a session: before the first request they receive a durable catalog of every available skill's name and capped description, and they can load any listed skill's full instructions by name through the `skill` loader tool. A user can also invoke a skill directly with a `/name` token, which injects that skill's instructions into the step. The catalog stays current: membership, description, or visibility changes append a complete replacement catalog, and a deleted skill is explicitly retired. Mount it alongside the skill registry (and at least one provider) when agents should load skills; its only configuration caps catalog description length.
13
+
14
+ ## Table of Contents
15
+
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)
6
22
 
7
- Requires `ctx.agents`, `ctx.tools`, and `ctx.skills` (`inject: ['agents', 'tools', 'skills']`).
23
+ -----
8
24
 
9
- ## Catalog lifecycle
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
10
27
 
11
- At every eligible `agent/pre-step`, the plugin calls `ctx.skills.snapshot()` for the calling session's cwd, forwards the pre-step abort signal to discovery, applies exact `skill` tool visibility, and renders the ordered `name` and `description` entries. When no prior catalog exists and that view is non-empty, it adds an initial durable user-role `<system-reminder>` to a downstream `enter` decision. Catalog messages contain only those summaries; skill bodies, paths, sources, providers, and `whenToUse` hints remain outside the catalog.
28
+ Mount the plugin alongside the skill registry to give agents a session skill catalog and the `skill` loader tool. It requires `ctx.agents`, `ctx.tools`, and `ctx.skills`.
12
29
 
13
- Every catalog message carries the `skill-catalog` source: a `catalog`-form context whose `entries` record exactly the `name` and `description` pairs it published, plus `update` on a replacement. The digest covers those durable entries, not the rendered prose, so the surrounding `<system-reminder>` framing cannot decide whether a republish is needed and consumers never re-parse the `<available_skills>` block. The plugin scans durable session events backwards without copying them and derives the comparison baseline from the newest visible `skill-catalog` message it can read; unreadable and foreign records are skipped. When the digest changes, the downstream `enter` decision receives a durable user-role message containing the complete replacement catalog; an empty replacement explicitly retires earlier names. If no catalog remains visible but a recognizable historical catalog exists, compaction hid it and the next complete observation re-establishes the current catalog. An incomplete provider snapshot emits nothing and preserves the last-good model view for retry at the next pre-step. If no prior catalog exists and the current view is empty, no tombstone is necessary.
30
+ ### When to choose it
14
31
 
15
- The catalog is omitted when no model-invocable skills are initially available, and also when that agent's tool view restricts away the shipped `skill` tool or resolves a same-name scoped shadow instead. Identity is compared against the definition this plugin registered rather than a lookup of its own name, so the plugin works mounted globally or inside one agent's composition, where `register()` files into that agent's layer alone. Visibility changes participate in the digest, keeping prompt guidance, model-visible schema, and executable dispatch aligned.
32
+ Use it when agents should discover and load skills during a session. Skip it when skill loading is handled by another consumer or not needed at all without it, providers and the registry still work, but nothing renders a catalog or a tool for the model.
16
33
 
17
- `catalogDescriptionMaxLength` controls normalized catalog descriptions; rendering XML-escapes them. Its default is `500` and values must be integers of at least `3`, which reserves room for a truncation ellipsis. The [skill catalog hot-refresh Agent Note](../../../.agents/notes/implemented/feature/2026-07-27-skill-catalog-hot-refresh.md) owns the durable initial catalog and replacement lifecycle.
34
+ ### Mount and configure
18
35
 
19
- ## Tool: `skill`
36
+ Load the plugin together with the skill registry and at least one provider. The only configuration caps the normalized description length rendered in the catalog.
20
37
 
21
- | Arg | Type | Notes |
38
+ ```yaml
39
+ - name: '@deepseek-ai/dsh-skill'
40
+ - name: '@deepseek-ai/dsh-skill-filesystem'
41
+ - name: '@deepseek-ai/dsh-tool-skill'
42
+ ```
43
+
44
+ | Field | Default | Meaning |
22
45
  |---|---|---|
23
- | `name` | string (required) | Exact kebab-case skill name from the available skills listing. |
46
+ | `catalogDescriptionMaxLength` | `500` | Maximum normalized description length rendered in the session catalog; minimum 3 |
47
+
48
+ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-tool-skill) is the exhaustive source for every accepted field.
49
+
50
+ ### What the model gets
51
+
52
+ - **A session catalog.** When model-invocable skills exist and the `skill` tool is visible, the agent receives a durable user-role message before its first request, listing each skill's name and a capped description; the message tells the model to load a skill with the tool before acting on it, and never to infer instructions from the summary alone.
53
+ - **A loader tool.** The model calls `skill` with the exact skill name and receives the full instruction body plus resource guidance in a canonical `<skill_content>` block; the result is retained as ordinary tool history.
54
+ - **Explicit user invocation.** A `/name` token in direct user input that names a user-invocable skill injects that skill's instructions into the step, without the model having to load it.
55
+ - **Live catalog updates.** Later membership, description, or visibility changes append a complete replacement catalog; removing every skill appends an empty catalog that retires older names.
56
+
57
+ ### Observable success and failures
58
+
59
+ Loading a listed skill returns its full instructions; the model sees one canonical shape whether the load came from the tool or from a user's explicit invocation. An invalid name reports `Error: invalid skill name "<name>"`, an unknown name reports the skill is unknown or no longer available, and a skill disabled for model invocation reports it is not available for model invocation. The catalog is omitted entirely only when no model-invocable skills exist and none was ever published; a later visibility loss — the `skill` tool hidden or shadowed by a same-name scoped tool — instead appends an empty retirement catalog, as when every skill is removed.
60
+
61
+ -----
62
+
63
+ <a id="understand-the-implementation"></a>
64
+ ## Understand the implementation
65
+
66
+ <details>
67
+ <summary>Implementation internals — click to expand</summary>
68
+
69
+ This section explains how the catalog and the invocation boundary are built; the observable behavior is fully covered in [Use this package](#use-this-package) and the Model Experience section below.
70
+
71
+ ### Design concept
24
72
 
25
- Execution uses the calling agent's `session.header.cwd` so workspace-sensitive providers resolve the winning skill. A successful call returns canonical `{ name, provider, resourceBase?, content }`, excluding catalog ranking and provider-internal machinery; its Native renderer produces one text result containing `<skill_content name="...">`, `<skill_resources>`, and `<skill_instructions>`.
73
+ The package is built on two ideas. First, the catalog is a durable projection, diffed by a digest over the published entries rather than the rendered prose, so the `<system-reminder>` framing can never force a republish and consumers never re-parse the `<available_skills>` block. Second, one canonical rendering serves both load paths — the tool result and the user-explicit injection through `renderSkillContent` shared from `dsh-skill`, so the model sees the same `<skill_content>` shape regardless of who initiated the load.
26
74
 
27
- Resource guidance resolves only paths or URLs explicitly referenced by the instructions against `resourceBase`; scripts, references, and assets load on demand, and the result does not enumerate a skill directory. Local providers may supply a directory, while remote or embedded providers may supply a URL or opaque loading guidance.
75
+ ### Source map
28
76
 
29
- An unresolved name reports that the skill is unknown or no longer available. Invalid names and skills whose `invocation.modelInvocable` is `false` produce distinct error results. `invocation.userInvocable` does not restrict this model-facing tool.
77
+ | File | Role |
78
+ |---|---|
79
+ | [`src/index.ts`](src/index.ts) | Plugin entry: tool registration, catalog and gesture pre-step listeners, rendering and digest |
80
+ | [`src/invariant.ts`](src/invariant.ts) | Invariant companion |
30
81
 
31
- Tool execution does not add a synthetic context message. Its freshly loaded result is already recorded as the tool result and becomes available to the next model step without duplicating the body. Only the catalog projection adds replacement summaries.
82
+ ### Catalog lifecycle
32
83
 
84
+ At each eligible `agent/pre-step`, the plugin snapshots the calling session's skill catalog, applies exact `skill` tool visibility, filters to model-invocable skills, and compares a digest of the entries against the newest visible `skill-catalog` message in the session log. When the digest changed, it hands the `enter` decision a durable user-role message containing the complete replacement catalog; an empty replacement explicitly retires earlier names. An incomplete provider snapshot emits nothing and preserves the last-good view for the next pre-step. The visibility check compares against the exact tool definition this plugin registered, so a scoped same-name shadow removes both the schema and its guidance; the plugin works mounted globally or inside one agent's composition.
85
+
86
+ ### Invocation boundary
87
+
88
+ The `/name` gesture listener scans only claimed user messages: a whitespace-bounded token naming a user-invocable skill in the workspace catalog injects the same `<skill_content>` rendering as a `user`-role instructions context appended after every other injection. Unknown names and user-disabled skills stay ordinary prose. This is the only entry point for `disable-model-invocation` skills, which the catalog and the `skill` tool never expose.
89
+
90
+ </details>
91
+
92
+ -----
93
+
94
+ <a id="further-exploration"></a>
95
+ ## Further Exploration
96
+
97
+ Read these pages when the package-level contract is not enough. They move from the registry vocabulary behind the catalog to the exact tool schema and the design rationale.
98
+
99
+ - [Skill subsystem reference](../../../docs/subsystems/skills.md) — the registry and provider vocabulary behind the catalog.
100
+ - [skill package](../skill/README.md) — the registry and the shared `renderSkillContent` rendering.
101
+ - [Generated tool catalog](../../../docs/tool-catalog.md#deepseek-aidsh-tool-skill) — the exact `skill` schema the model receives.
102
+ - [Skill catalog hot-refresh Agent Note](../../../.agents/notes/implemented/feature/2026-07-27-skill-catalog-hot-refresh.md) — the durable initial catalog and replacement lifecycle.
103
+ - [User-explicit skill invocation Agent Note](../../../.agents/notes/implemented/feature/2026-08-08-user-explicit-skill-invocation.md) — the `/name` gesture design.
104
+
105
+ -----
106
+
107
+ <a id="model-experience"></a>
33
108
  ## Model Experience
34
109
 
35
110
  ### Session catalog
36
111
 
37
112
  #### What the model sees
38
113
 
39
- If model-invocable skills exist and this exact `skill` tool is visible, the agent receives the catalog template below as a durable user-role message before the first request, with one data-dependent entry per sorted skill. Later membership, description, or visibility changes append a complete replacement using the same `<available_skills>` envelope; deleting every skill appends an empty envelope with an explicit instruction not to use older names. The template's closing sentence is the rule against double-loading: the user-explicit gesture boundary (the pre-step listener below) injects the same `renderSkillContent` output (shared from `@deepseek-ai/dsh-skill`) inline, and the catalog tells the model to follow that block instead of re-loading the skill through the tool; the replacement-catalog template carries the same sentence in both arms, including the emptied catalog.
114
+ If model-invocable skills exist and this exact `skill` tool is visible, the agent receives the catalog template below as a durable user-role message before the first request, with one data-dependent entry per sorted skill. Later membership, description, or visibility changes append a complete replacement using the same `<available_skills>` envelope; deleting every skill appends an empty envelope with an explicit instruction not to use older names. The template's closing sentence is the rule against double-loading: the user-explicit gesture boundary (the pre-step listener below) injects the same `renderSkillContent` output (shared from `@deepseek-ai/dsh-skill`) inline, and the catalog tells the model to follow that block instead of re-loading the skill through the tool; the replacement-catalog template carries the same anti-double-loading rule in both arms, including the emptied catalog.
40
115
 
41
116
  ##### Skill catalog template
42
117
 
@@ -161,9 +236,24 @@ Append-only; the injection lands after the reusable request prefix inside the st
161
236
 
162
237
  ## Known Limitations and Deferred Work
163
238
 
239
+ <a id="known-limitations-and-deferred-work"></a>
240
+
241
+
242
+ These limits define when the catalog or the loader is a poor fit. They are current package constraints, not a task backlog.
243
+
164
244
  - **The catalog omits `whenToUse`, source, and provider metadata** — routing is based only on name and a capped description; `whenToUse` remains provider metadata and is not rendered by the loaded wrapper either.
165
245
  - **Loaded instruction bodies have no size cap** — a provider can return a skill large enough to consume substantial next-step context; only catalog descriptions are truncated.
166
246
  - **Resources are guidance, not attachments** — the tool reports a base directory/URL/opaque hint but neither enumerates nor fetches referenced files for the model.
167
247
  - **Loading is one-shot text** — there is no partial, streaming, or cached-content handle when a remote provider is slow or a skill body is large.
168
- - **Catalog replacement is whole-list** — one changed name or description appends every currently visible summary; this keeps stale-name retirement explicit but costs tokens proportional to the catalog.
248
+ - **Catalog replacement is whole-list** — one changed name or description appends every visible summary; this keeps stale-name retirement explicit but costs tokens proportional to the catalog.
169
249
  - **Bodies are not versioned** — body-only edits do not change the catalog digest or notify the model; a later tool call reads the current provider content while earlier tool results remain historical facts.
250
+
251
+ <a id="dev-note"></a>
252
+ ### Dev Note
253
+
254
+ <details>
255
+ <summary>Working context for maintainers — click to expand</summary>
256
+
257
+ None.
258
+
259
+ </details>
package/README.zh.md CHANGED
@@ -1,42 +1,117 @@
1
+ ---
2
+ description: "面向模型的 skill 目录与加载工具,供了解 agent 看到什么、或配置会话 skill 目录的用户与维护者阅读。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-tool-skill
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 面向模型的 skill(技能)目录和 `skill` 工具。
10
+ ## 概述
11
+
12
+ agent(智能体)可以在会话期间发现并加载 skill(技能):在首次请求前,它们会收到一份持久目录,列出每个可用 skill 的名称与有长度上限的描述,并可通过 `skill` 加载工具按名称加载任一列出 skill 的完整指令。用户也可以用 `/name` token 直接调用某个 skill,把该 skill 的指令注入当轮次。目录保持最新:成员关系、描述或可见性变化会追加完整的替换目录,被删除的 skill 会被显式停用。当 agent 需要加载 skill 时,请把它与 skill 注册表(以及至少一个提供方)一起挂载;它唯一的配置项限制目录描述长度。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
6
22
 
7
- 需要 `ctx.agents`、`ctx.tools` 和 `ctx.skills`(`inject: ['agents', 'tools', 'skills']`)。
23
+ -----
8
24
 
9
- ## 目录生命周期
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
10
27
 
11
- 每次符合条件的 `agent/pre-step`,该插件都会使用调用会话的 cwd 调用 `ctx.skills.snapshot()`,将 pre-step 中止信号转发到发现流程,应用 `skill` 工具的精确可见性,并按顺序渲染 `name` `description` 条目。如果先前不存在目录且该视图非空,插件会向下游 `enter` 决策添加初始的持久用户角色 `<system-reminder>`。目录消息只包含这些摘要;skill 正文、路径、来源、提供方和 `whenToUse` 提示仍位于目录之外。
28
+ skill 注册表一起挂载该插件,即可让 agent 拥有会话 skill 目录和 `skill` 加载工具。它需要 `ctx.agents`、`ctx.tools` `ctx.skills`。
12
29
 
13
- 每条目录消息都携带 `skill-catalog` 来源,也就是 `catalog` 形态的上下文。它的 `entries` 精确记录本次发布的 `name` 与 `description` 对,替换目录另带 `update`。digest 覆盖这些持久条目,而不是渲染后的正文,因此 `<system-reminder>` 包装不会影响是否需要重新发布,消费方也不需要重新解析 `<available_skills>` 块。插件从后向前扫描持久会话事件且不复制,并以最新一条仍可见且可读的 `skill-catalog` 消息作为比较基线;不可读和外来的记录都会跳过。digest 变化时,下游 `enter` 决策会收到一条包含完整替换目录的持久用户角色消息;空替换会显式停用较早的名称。如果已无目录可见,但历史中存在可识别目录,则说明压缩(compaction)已将其遮蔽,下一次完整观察会重新建立当前目录。提供方快照不完整时,插件不会发送任何内容,并会保留最后一次完整的模型视图,在下一次 pre-step 重试。若不存在先前目录且当前视图为空,则不需要 tombstone。
30
+ ### 何时选择
14
31
 
15
- 如果最初没有模型可调用 skill,则省略目录;如果该 agent(智能体)的工具视图排除了随附的 `skill` 工具,或解析出同名的作用域内遮蔽项,也会省略目录。身份比对针对本插件所注册的那个定义,而非按自身名字回查,因此本插件既可全局挂载,也可挂在单个 agent 的组装内——在后者中 `register()` 只注册到该 agent 的层中。可见性变更参与 digest 计算,使提示词指引、模型可见 schema 和可执行分派保持对齐。
32
+ agent 应在会话期间发现并加载 skill 时使用它。当 skill 加载由其他消费方处理或完全不需要时,请跳过——没有它,提供方与注册表仍可工作,但不会有任何东西为模型渲染目录或工具。
16
33
 
17
- `catalogDescriptionMaxLength` 控制规范化后的目录描述,渲染时会对其执行 XML 转义。其默认值是 `500`,且必须是不小于 `3` 的整数,以便为截断省略号保留空间。[skill 目录热刷新 Agent Note](../../../.agents/notes/implemented/feature/2026-07-27-skill-catalog-hot-refresh.zh.md) 负责定义持久初始目录和替换目录的生命周期。
34
+ ### 挂载与配置
18
35
 
19
- ## 工具:`skill`
36
+ skill 注册表和至少一个提供方一起加载该插件。唯一配置项限制目录中渲染的规范化描述长度。
20
37
 
21
- | 参数 | 类型 | 说明 |
38
+ ```yaml
39
+ - name: '@deepseek-ai/dsh-skill'
40
+ - name: '@deepseek-ai/dsh-skill-filesystem'
41
+ - name: '@deepseek-ai/dsh-tool-skill'
42
+ ```
43
+
44
+ | 字段 | 默认值 | 含义 |
22
45
  |---|---|---|
23
- | `name` | string(必填) | 可用 skill 列表中精确的 kebab-case skill 名称。 |
46
+ | `catalogDescriptionMaxLength` | `500` | 会话目录中渲染的规范化描述最大长度;最小为 3 |
47
+
48
+ 生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-tool-skill)是每个受支持字段的穷尽式真源。
49
+
50
+ ### 模型得到什么
51
+
52
+ - **会话目录。** 当存在模型可调用 skill 且 `skill` 工具可见时,agent 会在首次请求前收到一条持久的用户角色消息,列出每个 skill 的名称与有长度上限的描述;该消息告诉模型在着手任务前先用工具加载 skill,且绝不能仅凭摘要推断指令。
53
+ - **加载工具。** 模型以精确的 skill 名称调用 `skill`,并收到完整指令正文以及规范的 `<skill_content>` 块中的资源指引;该结果作为普通工具历史保留。
54
+ - **用户显式调用。** 直接用户输入中的 `/name` token 若指名某个用户可调用 skill,会把该 skill 的指令注入当轮次,而无需模型自行加载。
55
+ - **实时目录更新。** 后续成员关系、描述或可见性变化会追加完整的替换目录;删除全部 skill 时会追加空目录,停用较早的名称。
56
+
57
+ ### 可观察的成功与失败
58
+
59
+ 加载列出的 skill 会返回其完整指令;无论加载来自工具还是用户的显式调用,模型看到的都是同一种规范形态。无效名称会报告 `Error: invalid skill name "<name>"`,未知名称会报告该 skill 未知或已不可用,被禁用模型调用的 skill 会报告其不可用于模型调用。只有不存在模型可调用 skill 且从未发布过目录时,目录才会被整体省略;此后的可见性丧失——`skill` 工具被隐藏或被同名作用域工具遮蔽——会改为追加空目录来停用旧名称,与删除全部 skill 时相同。
60
+
61
+ -----
62
+
63
+ <a id="understand-the-implementation"></a>
64
+ ## 理解实现
65
+
66
+ <details>
67
+ <summary>实现细节——点击展开</summary>
68
+
69
+ 本节解释目录与调用边界如何构建;可观察行为已在[使用本包](#use-this-package)和下方模型体验章节中完整说明。
70
+
71
+ ### 设计理念
24
72
 
25
- 执行使用调用 agent `session.header.cwd`,使结果随工作区变化的提供方能够解析出胜出的 skill。成功调用返回规范形式的 `{ name, provider, resourceBase?, content }`,其中不包含目录排名和提供方内部机制;其 Native 渲染器会生成一个文本结果,其中包含 `<skill_content name="...">`、`<skill_resources>` 和 `<skill_instructions>`。
73
+ 本包建立在两个想法之上。第一,目录是一种持久投影,按已发布条目的 digest 而非渲染后的正文做差异比较,因此 `<system-reminder>` 包装永远不会强制重新发布,消费方也不需要重新解析 `<available_skills>` 块。第二,一条规范渲染服务两条加载路径——工具结果与用户显式注入——经由共享自 `dsh-skill` `renderSkillContent`,因此无论加载由谁发起,模型看到的都是同一种 `<skill_content>` 形态。
26
74
 
27
- 资源指引只会根据 `resourceBase` 解析指令显式引用的路径或 URL;脚本、参考资料和资源文件按需加载,结果不会列举 skill 目录。本地提供方可以提供目录,而远程或嵌入式提供方可以提供 URL 或不透明加载指引。
75
+ ### 源码地图
28
76
 
29
- 无法解析的名称会报告 skill 未知或已不可用。无效名称和 `invocation.modelInvocable` 为 `false` 的 skill 会产生不同的错误结果。`invocation.userInvocable` 不限制这个面向模型的接口。
77
+ | 文件 | 职责 |
78
+ |---|---|
79
+ | [`src/index.ts`](src/index.ts) | 插件入口:工具注册、目录与手势 pre-step 监听器、渲染与 digest |
80
+ | [`src/invariant.ts`](src/invariant.ts) | 不变式伴生插件 |
30
81
 
31
- 工具执行不会添加合成上下文消息。新加载的结果已作为工具结果记录,并在下一个模型步骤可用,无需重复正文。只有目录投影会添加替换摘要。
82
+ ### 目录生命周期
32
83
 
84
+ 在每次符合条件的 `agent/pre-step`,插件都会快照调用会话的 skill 目录,应用 `skill` 工具的精确可见性,过滤出模型可调用的 skill,并把条目 digest 与会话日志中最新可见的 `skill-catalog` 消息做比较。digest 变化时,它把包含完整替换目录的持久用户角色消息交给 `enter` 决策;空替换会显式停用较早的名称。提供方快照不完整时不发送任何内容,并为下一次 pre-step 保留最后一份可用视图。可见性检查针对本插件所注册的精确工具定义,因此作用域内同名的遮蔽项会同时移除 schema 及其指引;该插件既可全局挂载,也可挂在单个 agent 的组合内。
85
+
86
+ ### 调用边界
87
+
88
+ `/name` 手势监听器只扫描已认领的用户消息:若某个以空白为界、指名工作区目录中用户可调用 skill 的 token 出现,则把同一份 `<skill_content>` 渲染作为 `user` 角色的指令上下文注入,追加在该步骤所有其他注入之后。未知名称与用户不可调用的名称保持为普通行文。这是 `disable-model-invocation` skill 唯一的入口,目录与 `skill` 工具永不暴露这类 skill。
89
+
90
+ </details>
91
+
92
+ -----
93
+
94
+ <a id="further-exploration"></a>
95
+ ## 进一步探索
96
+
97
+ 当包级约定不够用时阅读以下页面。它们从目录背后的注册表词汇逐步进入精确工具 schema 与设计依据。
98
+
99
+ - [skill 子系统参考](../../../docs/subsystems/skills.zh.md)——目录背后的注册表与提供方词汇。
100
+ - [skill 包](../skill/README.zh.md)——注册表与共享的 `renderSkillContent` 渲染。
101
+ - [生成工具目录](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-skill)——模型接收的精确 `skill` schema。
102
+ - [skill 目录热刷新 Agent Note](../../../.agents/notes/implemented/feature/2026-07-27-skill-catalog-hot-refresh.zh.md)——持久初始目录与替换生命周期。
103
+ - [用户显式 skill 调用 Agent Note](../../../.agents/notes/implemented/feature/2026-08-08-user-explicit-skill-invocation.zh.md)——`/name` 手势设计。
104
+
105
+ -----
106
+
107
+ <a id="model-experience"></a>
33
108
  ## 模型体验
34
109
 
35
110
  ### 会话目录
36
111
 
37
- #### 模型看到的内容
112
+ #### 模型看到什么
38
113
 
39
- 如果存在模型可调用 skill,且可见的正是这个 `skill` 工具,agent 会在第一个请求之前收到下方目录模板,其中包含每个已排序 skill 的一条随数据而定的条目。该目录是一条持久的用户角色消息。后续成员关系、描述或可见性的变化会使用同一个 `<available_skills>` 信封追加完整替换;删除所有 skill 时,会追加一个空信封,并明确指示不得使用旧名称。模板的结尾一句是防止双重加载的规则:用户显式的手势边界(下文的 pre-step 监听器)会把同一份 `renderSkillContent` 输出(共享自 `@deepseek-ai/dsh-skill`)内联注入,目录则告诉模型遵循该块,而不是再经工具重新加载该 skill;替换目录模板的两个分支——包括清空后的目录——都携带同一句话。
114
+ 如果存在模型可调用 skill,且可见的正是这个 `skill` 工具,agent 会在第一个请求之前收到下方目录模板,其中包含每个已排序 skill 的一条随数据而定的条目。该目录是一条持久的用户角色消息。后续成员关系、描述或可见性的变化会使用同一个 `<available_skills>` 信封追加完整替换;删除所有 skill 时,会追加一个空信封,并明确指示不得使用旧名称。模板的结尾一句是防止双重加载的规则:用户显式的手势边界(下文的 pre-step 监听器)会把同一份 `renderSkillContent` 输出(共享自 `@deepseek-ai/dsh-skill`)内联注入,目录则告诉模型遵循该块,而不是再经工具重新加载该 skill;替换目录模板的两个分支——包括清空后的目录——都携带同一条防双重加载规则。
40
115
 
41
116
  ##### Skill 目录模板
42
117
 
@@ -63,7 +138,7 @@ A user may also invoke a skill directly; its <skill_content> block then appears
63
138
 
64
139
  ### 工具 schema
65
140
 
66
- #### 模型看到的内容
141
+ #### 模型看到什么
67
142
 
68
143
  模型会看到生成的 [`skill` schema](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-skill)。
69
144
 
@@ -77,7 +152,7 @@ A user may also invoke a skill directly; its <skill_content> block then appears
77
152
 
78
153
  ### 工具结果
79
154
 
80
- #### 模型看到的内容
155
+ #### 模型看到什么
81
156
 
82
157
  成功调用使用下方结果模板,以及提供方管理的资源指引、目录资源指引、URL 资源指引或不透明资源指引。
83
158
 
@@ -133,7 +208,7 @@ Load referenced resources only as needed.
133
208
 
134
209
  ### 工具错误
135
210
 
136
- #### 模型看到的内容
211
+ #### 模型看到什么
137
212
 
138
213
  无效或陈旧选择会精确返回 `Error: invalid skill name "<name>"`、`Error: skill "<name>" is unknown or no longer available` 或 `Error: skill "<name>" is not available for model invocation`。提供方抛出的查找文本取决于数据,并套用同一个 `Error: <message>` 包装层。
139
214
 
@@ -147,7 +222,7 @@ Load referenced resources only as needed.
147
222
 
148
223
  ### 用户显式调用注入
149
224
 
150
- #### 模型看到的内容
225
+ #### 模型看到什么
151
226
 
152
227
  已认领用户消息中任意位置、以空白为界、指名工作区目录中某个用户可调用 skill 的 `/name` token,会把该 skill 的完整 `<skill_content>` 渲染(与上文结果模板完全相同的形态)作为 `user` 角色的指令上下文注入,追加在该步骤所有其他注入之后——背景在前,模型要着手处理的材料在最后。只扫描直接的用户输入,检查在已加载定义上进行,未知名称和用户不可调用的名称保持为普通行文。这是 `disable-model-invocation` skill 唯一的入口,目录和 `skill` 工具永不暴露这类 skill;目录的结尾一句会告诉模型遵循注入块,而不是重新加载它。
153
228
 
@@ -159,11 +234,26 @@ Load referenced resources only as needed.
159
234
 
160
235
  仅追加;注入落在该步骤的消息批次中、可重用请求前缀之后,不会使现有 KV Cache 条目失效。
161
236
 
162
- ## 已知限制与暂缓事项
237
+ ## 已知限制与延期工作
238
+
239
+ <a id="known-limitations-and-deferred-work"></a>
240
+
241
+
242
+ 这些限制说明目录或加载器何时不合适。它们是当前包约束,不是任务积压。
243
+
244
+ - **目录省略 `whenToUse`、来源和提供方元数据**——路由只基于名称和有长度上限的描述;`whenToUse` 仍是提供方元数据,加载后的包装层也不渲染它。
245
+ - **已加载指令正文没有大小上限**——提供方可返回足以占用大量下一步上下文的 skill;只有目录描述会被截断。
246
+ - **资源是指引,而非附件**——工具报告基础目录/URL/不透明提示,但既不列举也不为模型获取引用文件。
247
+ - **加载是一次性文本**——远程提供方缓慢或 skill 正文很大时,不提供部分内容、流式输出或缓存内容句柄。
248
+ - **目录替换采用全量列表**——一个名称或描述发生变化,就会追加所有可见摘要;这样能显式停用陈旧名称,但 token 成本与目录大小成正比。
249
+ - **正文不做版本化**——仅修改正文不会改变目录 digest,也不会通知模型;后续工具调用会读取提供方的当前内容,而先前工具结果仍是历史事实。
250
+
251
+ <a id="dev-note"></a>
252
+ ### 开发备注
253
+
254
+ <details>
255
+ <summary>维护者的工作上下文——点击展开</summary>
256
+
257
+ 无。
163
258
 
164
- - **目录省略 `whenToUse`、来源和提供方元数据**:路由只基于名称和有长度上限的描述;`whenToUse` 仍是提供方元数据,加载后的包装层也不渲染它。
165
- - **已加载指令正文没有大小上限**:提供方可返回足以占用大量下一步上下文的 skill;只有目录描述会被截断。
166
- - **资源是指引,而非附件**:工具报告基础目录/URL/不透明提示,但既不列举也不为模型获取引用文件。
167
- - **加载是一次性文本**:远程提供方缓慢或 skill 正文很大时,不提供部分内容、流式输出或缓存内容句柄。
168
- - **目录替换采用全量列表**:一个名称或描述发生变化,就会追加当前所有可见摘要;这样能显式停用陈旧名称,但 token 成本与目录大小成正比。
169
- - **正文不做版本化**:仅修改正文不会改变目录 digest,也不会通知模型;后续工具调用会读取提供方的当前内容,而先前工具结果仍是历史事实。
259
+ </details>
package/lib/index.js CHANGED
@@ -174,7 +174,7 @@ function apply(ctx, config = {}) {
174
174
  }
175
175
  if (injections.length === 0) return decision;
176
176
  return {
177
- kind: "enter",
177
+ ...decision,
178
178
  messages: [...decision.messages, ...injections]
179
179
  };
180
180
  });
@@ -198,17 +198,17 @@ function apply(ctx, config = {}) {
198
198
  const history = catalogHistory(agent);
199
199
  const existing = catalogMessage(decision.messages);
200
200
  if (history.visibleDigest === digest) return existing === void 0 ? decision : {
201
- kind: "enter",
201
+ ...decision,
202
202
  messages: decision.messages.filter((message) => message.id !== existing.message.id)
203
203
  };
204
204
  if (existing !== void 0 && digestCatalogEntries(existing.entries) === digest) return decision;
205
205
  if (!history.published && skills.length === 0) return existing === void 0 ? decision : {
206
- kind: "enter",
206
+ ...decision,
207
207
  messages: decision.messages.filter((message) => message.id !== existing.message.id)
208
208
  };
209
209
  const catalog = history.published ? renderCatalogUpdate(entries) : renderCatalogMessage(entries);
210
210
  return {
211
- kind: "enter",
211
+ ...decision,
212
212
  messages: existing === void 0 ? [...decision.messages, catalog] : decision.messages.map((message) => message.id === existing.message.id ? catalog : message)
213
213
  };
214
214
  });
@@ -334,7 +334,6 @@ function catalogMessage(messages) {
334
334
  };
335
335
  }
336
336
  }
337
- /** Normalized, length-bounded description exactly as the catalog publishes it (unescaped). */
338
337
  function catalogDescription(value, maxLength) {
339
338
  const normalized = value.replaceAll(/\s+/g, " ").trim();
340
339
  return normalized.length <= maxLength ? normalized : `${normalized.slice(0, maxLength - 3)}...`;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-tool-skill",
3
3
  "description": "Model-facing skill loading tool for the DeepSeek Harness",
4
- "version": "0.1.1-rc.2",
4
+ "version": "0.1.2-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -32,25 +32,25 @@
32
32
  ],
33
33
  "license": "MIT",
34
34
  "peerDependencies": {
35
- "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
36
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
37
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
38
- "@deepseek-ai/dsh-skill": "^0.1.1-rc.2",
39
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
40
- "@deepseek-ai/cordis": "^4.0.1"
35
+ "@deepseek-ai/dsh-agent": "^0.1.2-alpha.2",
36
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
37
+ "@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
38
+ "@deepseek-ai/dsh-skill": "^0.1.2-alpha.2",
39
+ "@deepseek-ai/cordis": "^4.0.2",
40
+ "@deepseek-ai/dsh-tools": "^0.1.2-alpha.2"
41
41
  },
42
42
  "dependencies": {
43
- "@deepseek-ai/schemastery": "^3.18.1"
43
+ "@deepseek-ai/schemastery": "^3.18.2"
44
44
  },
45
45
  "devDependencies": {
46
- "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
47
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
48
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
49
- "@deepseek-ai/dsh-scope": "^0.1.1-rc.2",
50
- "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
51
- "@deepseek-ai/dsh-skill-filesystem": "^0.1.1-rc.2",
52
- "@deepseek-ai/dsh-skill": "^0.1.1-rc.2",
53
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
54
- "@deepseek-ai/cordis": "^4.0.1"
46
+ "@deepseek-ai/dsh-agent": "^0.1.2-alpha.2",
47
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
48
+ "@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
49
+ "@deepseek-ai/dsh-scope": "^0.1.2-alpha.2",
50
+ "@deepseek-ai/dsh-session": "^0.1.2-alpha.2",
51
+ "@deepseek-ai/dsh-skill": "^0.1.2-alpha.2",
52
+ "@deepseek-ai/dsh-skill-filesystem": "^0.1.2-alpha.2",
53
+ "@deepseek-ai/dsh-tools": "^0.1.2-alpha.2",
54
+ "@deepseek-ai/cordis": "^4.0.2"
55
55
  }
56
56
  }