@zfdx123/dsh-superpowers 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +27 -0
- package/LICENSE.superpowers +21 -0
- package/README.md +109 -0
- package/README.zh.md +109 -0
- package/cordis.patch.yml +16 -0
- package/index.js +395 -0
- package/package.json +68 -0
- package/skills/brainstorming/SKILL.md +250 -0
- package/skills/brainstorming/scripts/frame-template.html +213 -0
- package/skills/brainstorming/scripts/helper.js +179 -0
- package/skills/brainstorming/scripts/server.cjs +781 -0
- package/skills/brainstorming/scripts/start-server.sh +209 -0
- package/skills/brainstorming/scripts/stop-server.sh +120 -0
- package/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/skills/brainstorming/visual-companion.md +299 -0
- package/skills/dispatching-parallel-agents/SKILL.md +167 -0
- package/skills/executing-plans/SKILL.md +64 -0
- package/skills/finishing-a-development-branch/SKILL.md +225 -0
- package/skills/receiving-code-review/SKILL.md +205 -0
- package/skills/requesting-code-review/SKILL.md +95 -0
- package/skills/requesting-code-review/code-reviewer.md +181 -0
- package/skills/subagent-driven-development/SKILL.md +568 -0
- package/skills/subagent-driven-development/implementer-prompt.md +154 -0
- package/skills/subagent-driven-development/re-review-prompt.md +115 -0
- package/skills/subagent-driven-development/scripts/review-package +46 -0
- package/skills/subagent-driven-development/scripts/sdd-workspace +40 -0
- package/skills/subagent-driven-development/scripts/task-brief +41 -0
- package/skills/subagent-driven-development/task-reviewer-prompt.md +207 -0
- package/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/skills/systematic-debugging/SKILL.md +283 -0
- package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/skills/systematic-debugging/find-polluter.sh +72 -0
- package/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/skills/systematic-debugging/test-academic.md +14 -0
- package/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/skills/test-driven-development/SKILL.md +320 -0
- package/skills/test-driven-development/writing-good-tests.md +198 -0
- package/skills/using-git-worktrees/SKILL.md +167 -0
- package/skills/using-superpowers/SKILL.md +63 -0
- package/skills/using-superpowers/references/antigravity-tools.md +23 -0
- package/skills/using-superpowers/references/codex-tools.md +108 -0
- package/skills/using-superpowers/references/gemini-tools.md +63 -0
- package/skills/using-superpowers/references/hermes-tools.md +56 -0
- package/skills/using-superpowers/references/pi-tools.md +16 -0
- package/skills/verification-before-completion/SKILL.md +120 -0
- package/skills/writing-plans/SKILL.md +171 -0
- package/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/skills/writing-skills/SKILL.md +679 -0
- package/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/skills/writing-skills/persuasion-principles.md +187 -0
- package/skills/writing-skills/render-graphs.js +172 -0
- package/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/test/index.test.js +332 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-superpowers contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
The contents of skills/ are vendored unmodified from https://github.com/obra/superpowers
|
|
26
|
+
(v6.3.0, commit b36e0829c6d0140e93cfef2ca599b1b07d4a7797) and remain under their own
|
|
27
|
+
MIT license, reproduced in LICENSE.superpowers.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jesse Vincent
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# dsh-superpowers
|
|
2
|
+
|
|
3
|
+
English | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
dsh-superpowers adds [obra/superpowers](https://github.com/obra/superpowers) support to [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness). It registers 14 skills for brainstorming, planning, TDD, debugging, and code review, and keeps the `using-superpowers` bootstrap active throughout the session.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [What it does](#what-it-does)
|
|
11
|
+
- [Verification](#verification)
|
|
12
|
+
- [Configuration](#configuration)
|
|
13
|
+
- [Limitations](#limitations)
|
|
14
|
+
- [Overhead](#overhead)
|
|
15
|
+
- [Testing](#testing)
|
|
16
|
+
- [Requirements](#requirements)
|
|
17
|
+
- [Upstream and license](#upstream-and-license)
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
Add the package to the profile as a local workspace dependency, then restart the surface:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
cd E:/work/ai/dsh-superpowers && npm install # the config schema is a runtime dependency
|
|
25
|
+
dsh plugin --profile web add link:E:/work/ai/dsh-superpowers
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Stop and restart `dsh web` afterwards. Replace `web` with `headless` or a custom profile name when installing for a different surface, then restart that surface instead.
|
|
29
|
+
|
|
30
|
+
## What it does
|
|
31
|
+
|
|
32
|
+
- Registers all 14 Superpowers skills on `ctx.skills`. They appear in the skill catalog and load through the native `skill` tool. Nothing is copied into `~/.dsh/skills`.
|
|
33
|
+
- Adds the `using-superpowers` bootstrap as the `superpowers:bootstrap` prompt section at order 50. It is present on the first request and survives context compaction because it is part of the system prompt, not a one-off session message. A preset that owns the whole system prompt replaces it — see [Limitations](#limitations).
|
|
34
|
+
- Warns on the first agent of a workspace when a project or preset skill shadows one of the bundled names, naming the copy the model will load instead.
|
|
35
|
+
- Maps Claude Code-style tool names such as `Task`, `TodoWrite`, and `Bash`/`Read`/`Write`/`Edit` to their DeepSeek Harness equivalents. The mapping also notes that hooks and slash commands are not available.
|
|
36
|
+
|
|
37
|
+
## Verification
|
|
38
|
+
|
|
39
|
+
Check that the plugin is present in the profile:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
dsh --profile web --dump-config
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The output should contain `id: superpowers` followed by `name: @zfdx123/dsh-superpowers`.
|
|
46
|
+
|
|
47
|
+
Then start a new session and ask for a feature. The agent should explore first and respond with questions or a design instead of writing code immediately. Its tool calls should include `skill`.
|
|
48
|
+
|
|
49
|
+
If the bootstrap never arrives, check the session's preset: a preset whose persona owns the complete system prompt is the one case where it is absent by design — see [Limitations](#limitations).
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
Every field is optional. Override fields in the profile's own `cordis.patch.yml`:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
- id: superpowers
|
|
57
|
+
config:
|
|
58
|
+
bootstrap: false
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
| Field | Default | Description |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| `skills` | `true` | Register the bundled skills on `ctx.skills`. |
|
|
64
|
+
| `bootstrap` | `true` | Register the `using-superpowers` prompt section. |
|
|
65
|
+
| `toolMapping` | `true` | Append the DeepSeek Harness tool mapping to the bootstrap section. |
|
|
66
|
+
| `order` | `50` | Place the bootstrap after the persona prefix (0), before the plan policy (500) and tool guidance (1000+). |
|
|
67
|
+
|
|
68
|
+
Every field is validated against the plugin's schema before it applies: a misspelled type fails the profile with the offending field named, instead of half-registering the plugin.
|
|
69
|
+
|
|
70
|
+
Setting `bootstrap: false` keeps the skills discoverable but stops them from self-triggering; the model will use them only when it decides to consult the catalog.
|
|
71
|
+
|
|
72
|
+
## Limitations
|
|
73
|
+
|
|
74
|
+
A preset can own the entire system prompt. When the preset's persona declares itself the complete prompt — the bundled `minimal` preset does, with `complete: true` — the prompt registry restores that one section after assembly and drops every other section, including `superpowers:bootstrap`. The drop is silent, and dsh publishes no signal for it: a section's `complete` flag never leaves the registry, and a `system-prompt/assemble` listener cannot append prompt text to a scope that has one. The plugin therefore registers the section and documents the case rather than guessing; `verify/src-02-complete-persona-shadow.mjs` pins the mechanism against the installed dsh.
|
|
75
|
+
|
|
76
|
+
Under such a preset:
|
|
77
|
+
|
|
78
|
+
- The bootstrap is not delivered, so the skills never self-trigger. The 14 skills are still registered on `ctx.skills`, but whether the model can reach them is the preset's decision, because the preset also decides which tools exist — `minimal` exposes only the persistent shell, so no `skill` tool is available there either.
|
|
79
|
+
- `bootstrap: true` cannot make the section appear, and `bootstrap: false` reports nothing: the section was never going to be delivered.
|
|
80
|
+
|
|
81
|
+
Use a preset whose persona is not complete to get the bootstrap.
|
|
82
|
+
|
|
83
|
+
## Overhead
|
|
84
|
+
|
|
85
|
+
The bootstrap adds roughly 1.1k tokens (4,465 characters) to the system prompt of each request. The section is static and stays within the cached prefix. It is not appended as a new chat message on every turn. Set `bootstrap: false` to keep the skills without the fixed prompt overhead.
|
|
86
|
+
|
|
87
|
+
## Testing
|
|
88
|
+
|
|
89
|
+
`npm test` runs the suite through `node --test`. `test/` ships in the published tarball, so the command works from an installed copy as well as from a checkout.
|
|
90
|
+
|
|
91
|
+
`verify/` holds maintainer-only probes that mount the real dsh service classes. They are not published, and they need a local dsh installation (pass its `package.json` path as the first argument to point at another one):
|
|
92
|
+
|
|
93
|
+
- `verify/dsh-compat.mjs` — every runtime and packaging contract this plugin depends on.
|
|
94
|
+
- `verify/src-01-doc-order-drift.mjs` — the documented prompt-order band against the installed section orders.
|
|
95
|
+
- `verify/src-02-complete-persona-shadow.mjs` — the complete-persona drop recorded under [Limitations](#limitations).
|
|
96
|
+
|
|
97
|
+
## Requirements
|
|
98
|
+
|
|
99
|
+
- DeepSeek Harness `0.1.0-rc.6` or newer
|
|
100
|
+
- Node.js 22.19+ or 24+
|
|
101
|
+
- One runtime dependency, `@deepseek-ai/schemastery`, which provides the config schema. A registry install pulls it in; a `link:` install needs `npm install` in the checkout first, or the plugin fails to load. Every other registry is reached through `ctx`.
|
|
102
|
+
|
|
103
|
+
## Upstream and license
|
|
104
|
+
|
|
105
|
+
The skills under `skills/` are vendored unmodified from [obra/superpowers](https://github.com/obra/superpowers) v6.3.0 at commit [`b36e082`](https://github.com/obra/superpowers/commit/b36e0829c6d0140e93cfef2ca599b1b07d4a7797). The exact upstream version and commit are recorded in `package.json`.
|
|
106
|
+
|
|
107
|
+
The optional visual companion in `brainstorming` loads an upstream-hosted logo containing the Superpowers version. It sends no project or prompt content. Set `SUPERPOWERS_DISABLE_TELEMETRY` to a true value to disable it.
|
|
108
|
+
|
|
109
|
+
Two MIT license notices apply: the adapter is © its contributors under [LICENSE](LICENSE), while the bundled skills are © Jesse Vincent and the Superpowers contributors under [LICENSE.superpowers](LICENSE.superpowers).
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# dsh-superpowers
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
dsh-superpowers 为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供 [obra/superpowers](https://github.com/obra/superpowers) 适配。它注册 14 个覆盖需求澄清、任务规划、TDD、调试与代码审查的技能,并让 `using-superpowers` bootstrap 在整个会话中保持生效。
|
|
6
|
+
|
|
7
|
+
## 目录
|
|
8
|
+
|
|
9
|
+
- [安装](#安装)
|
|
10
|
+
- [它做了什么](#它做了什么)
|
|
11
|
+
- [验证](#验证)
|
|
12
|
+
- [配置](#配置)
|
|
13
|
+
- [已知限制](#已知限制)
|
|
14
|
+
- [开销](#开销)
|
|
15
|
+
- [测试](#测试)
|
|
16
|
+
- [环境要求](#环境要求)
|
|
17
|
+
- [上游与许可](#上游与许可)
|
|
18
|
+
|
|
19
|
+
## 安装
|
|
20
|
+
|
|
21
|
+
把本包作为本地工作区依赖加进 profile,然后重启对应形态:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
cd E:/work/ai/dsh-superpowers && npm install # 配置 schema 是运行时依赖
|
|
25
|
+
dsh plugin --profile web add link:E:/work/ai/dsh-superpowers
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
执行后先停止再重启 `dsh web`。如果要安装到其他形态,可把 `web` 换成 `headless` 或自定义 profile 名,并重启对应形态。
|
|
29
|
+
|
|
30
|
+
## 它做了什么
|
|
31
|
+
|
|
32
|
+
- 在 `ctx.skills` 注册全部 14 个 Superpowers 技能。它们会出现在技能目录中,并通过原生 `skill` 工具加载;不会往 `~/.dsh/skills` 复制任何文件。
|
|
33
|
+
- 把 `using-superpowers` bootstrap 注册为 `superpowers:bootstrap` 提示词段落,order 为 50。它在第一条请求中生效,并能在上下文压缩后继续存在,因为它属于系统提示词,不是一次性会话消息。若预设独占整个系统提示词,它会被替换,见[已知限制](#已知限制)。
|
|
34
|
+
- 每个工作区首个 agent 创建时,若内置技能名被项目或预设技能遮蔽,会报出警告,并指明模型实际加载的那份副本。
|
|
35
|
+
- 将 `Task`、`TodoWrite`、`Bash`/`Read`/`Write`/`Edit` 等 Claude Code 风格工具名映射到 DeepSeek Harness 对应工具。映射中也会说明当前环境不提供 hooks 与斜杠命令。
|
|
36
|
+
|
|
37
|
+
## 验证
|
|
38
|
+
|
|
39
|
+
先确认插件已挂载到 profile:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
dsh --profile web --dump-config
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
输出中应包含 `id: superpowers`,其后是 `name: @zfdx123/dsh-superpowers`。
|
|
46
|
+
|
|
47
|
+
然后新建会话并提出一个功能需求。Agent 应先探查,再给出问题或设计,不会立即开始写代码。工具调用中应出现 `skill`。
|
|
48
|
+
|
|
49
|
+
如果 bootstrap 始终没有出现,请检查会话所用的预设:当预设的 persona 独占完整系统提示词时,它按设计就不会下发,见[已知限制](#已知限制)。
|
|
50
|
+
|
|
51
|
+
## 配置
|
|
52
|
+
|
|
53
|
+
所有字段均为可选项,可在 profile 自己的 `cordis.patch.yml` 中覆盖:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
- id: superpowers
|
|
57
|
+
config:
|
|
58
|
+
bootstrap: false
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
| 字段 | 默认值 | 说明 |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| `skills` | `true` | 把内置技能注册到 `ctx.skills`。 |
|
|
64
|
+
| `bootstrap` | `true` | 注册 `using-superpowers` 提示词段落。 |
|
|
65
|
+
| `toolMapping` | `true` | 在 bootstrap 段落中追加 DeepSeek Harness 工具映射。 |
|
|
66
|
+
| `order` | `50` | 把 bootstrap 放在 persona 前缀(0)之后、计划策略(500)与工具指导(1000+)之前。 |
|
|
67
|
+
|
|
68
|
+
所有字段在生效前都会先过插件自己的 schema:类型写错时 profile 会直接失败并指出出错字段,而不是把插件注册到一半。
|
|
69
|
+
|
|
70
|
+
设置 `bootstrap: false` 后,技能仍可被发现,但不会再自动触发;模型只会在自己决定查询技能目录时使用它们。
|
|
71
|
+
|
|
72
|
+
## 已知限制
|
|
73
|
+
|
|
74
|
+
预设可以独占整个系统提示词。当预设的 persona 声明自己就是完整提示词时——内置的 `minimal` 预设正是如此(`complete: true`)——提示词注册表会在装配结束后只保留那一个段落,丢掉包括 `superpowers:bootstrap` 在内的其他所有段落。这一丢弃是静默的,而且 dsh 不发布任何相关信号:段落的 `complete` 标记不会离开注册表,`system-prompt/assemble` 监听器也无法向存在 complete 段落的 scope 追加提示词文本。因此本插件照常注册该段落、把这种情况写进文档,而不是去猜;`verify/src-02-complete-persona-shadow.mjs` 会针对已安装的 dsh 钉住这一机制。
|
|
75
|
+
|
|
76
|
+
在该类预设下:
|
|
77
|
+
|
|
78
|
+
- bootstrap 不会下发,技能因此不会自动触发。14 个技能仍注册在 `ctx.skills` 上,但模型能否取到它们由预设决定——预设同时决定有哪些工具:`minimal` 只挂常驻 shell,所以那里也没有 `skill` 工具。
|
|
79
|
+
- `bootstrap: true` 不会让它出现,`bootstrap: false` 也不会有任何提示:这个段落本来就不会下发。
|
|
80
|
+
|
|
81
|
+
要拿到 bootstrap,请使用 persona 不是 complete 的预设。
|
|
82
|
+
|
|
83
|
+
## 开销
|
|
84
|
+
|
|
85
|
+
bootstrap 会给每次请求的系统提示词增加约 1.1k token(4,465 字符)。这段内容是静态的,位于缓存前缀内,不会在每一轮作为新的聊天消息追加。设置 `bootstrap: false` 可以保留技能,同时去掉这份固定提示词开销。
|
|
86
|
+
|
|
87
|
+
## 测试
|
|
88
|
+
|
|
89
|
+
`npm test` 通过 `node --test` 运行测试。`test/` 会随发布产物一起发布,因此在安装后的副本里和源码检出里都能直接运行。
|
|
90
|
+
|
|
91
|
+
`verify/` 下是维护者专用的探针,会挂载真实的 dsh 服务类。它们不随包发布,且需要本机装有 dsh(第一个参数可传入另一份 dsh 的 `package.json` 路径):
|
|
92
|
+
|
|
93
|
+
- `verify/dsh-compat.mjs` —— 本插件依赖的全部运行时与打包契约。
|
|
94
|
+
- `verify/src-01-doc-order-drift.mjs` —— 文档中的 order 区间与已安装段落顺序表的对照。
|
|
95
|
+
- `verify/src-02-complete-persona-shadow.mjs` —— [已知限制](#已知限制) 中记录的 complete persona 覆盖机制。
|
|
96
|
+
|
|
97
|
+
## 环境要求
|
|
98
|
+
|
|
99
|
+
- DeepSeek Harness `0.1.0-rc.6` 及以上
|
|
100
|
+
- Node.js 22.19+ 或 24+
|
|
101
|
+
- 一个运行时依赖 `@deepseek-ai/schemastery`,用于提供配置 schema。从 registry 安装会自动带上它;用 `link:` 安装时需要先在检出目录执行 `npm install`,否则插件无法加载。其余注册表都只通过 `ctx` 访问。
|
|
102
|
+
|
|
103
|
+
## 上游与许可
|
|
104
|
+
|
|
105
|
+
`skills/` 下的技能原样取自 [obra/superpowers](https://github.com/obra/superpowers) v6.3.0,对应 commit [`b36e082`](https://github.com/obra/superpowers/commit/b36e0829c6d0140e93cfef2ca599b1b07d4a7797),未做修改;`package.json` 记录了确切的上游版本与 commit。
|
|
106
|
+
|
|
107
|
+
`brainstorming` 的可选视觉组件会从上游网站加载带 Superpowers 版本号的 logo,不包含项目或提示词内容。把 `SUPERPOWERS_DISABLE_TELEMETRY` 设为任一 true 值即可关闭。
|
|
108
|
+
|
|
109
|
+
这里同时适用两份 MIT 许可声明:适配器版权归其贡献者所有,依据 [LICENSE](LICENSE) 许可;内置技能版权归 Jesse Vincent 与 Superpowers 贡献者所有,依据 [LICENSE.superpowers](LICENSE.superpowers) 许可。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# The dsh-superpowers bundle patch: one host-plane row.
|
|
2
|
+
#
|
|
3
|
+
# The row registers a `ctx.skills` provider for the bundled Superpowers skills
|
|
4
|
+
# and a `superpowers:bootstrap` prompt section. Both land in the global layer,
|
|
5
|
+
# which every agent's scope chain merges, so the plugin works on the Web surface
|
|
6
|
+
# (where the agent plane sits behind presets) without touching any preset.
|
|
7
|
+
#
|
|
8
|
+
# Turn a half off in the profile's own cordis.patch.yml, for example:
|
|
9
|
+
#
|
|
10
|
+
# - id: superpowers
|
|
11
|
+
# config:
|
|
12
|
+
# bootstrap: false
|
|
13
|
+
#
|
|
14
|
+
- insert:
|
|
15
|
+
- id: superpowers
|
|
16
|
+
name: "@zfdx123/dsh-superpowers"
|
package/index.js
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Superpowers for DeepSeek Harness.
|
|
3
|
+
*
|
|
4
|
+
* Brings the Superpowers software-development methodology (obra/superpowers) to
|
|
5
|
+
* dsh: the bundled skills are registered as runtime skills on `ctx.skills`, and
|
|
6
|
+
* the `using-superpowers` bootstrap is registered as a prompt section so it is
|
|
7
|
+
* present from the first request and survives context compaction.
|
|
8
|
+
*
|
|
9
|
+
* Both registries are reached through `ctx` alone — a third-party plugin cannot
|
|
10
|
+
* rely on a `@deepseek-ai/*` service package resolving from its own directory,
|
|
11
|
+
* because they are nested inside the dsh installation. The one exception is the
|
|
12
|
+
* config-schema package, which is a declared dependency of this package and
|
|
13
|
+
* therefore resolves from this package's own tree.
|
|
14
|
+
*
|
|
15
|
+
* @module dsh-superpowers
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { readdirSync, readFileSync } from 'node:fs'
|
|
19
|
+
import { dirname, join, resolve } from 'node:path'
|
|
20
|
+
import { fileURLToPath } from 'node:url'
|
|
21
|
+
|
|
22
|
+
import Schema from '@deepseek-ai/schemastery'
|
|
23
|
+
|
|
24
|
+
/** Cordis plugin name used by loader diagnostics. */
|
|
25
|
+
export const name = 'superpowers'
|
|
26
|
+
|
|
27
|
+
/** The prompt and skill registries this plugin registers into. */
|
|
28
|
+
export const inject = ['systemPrompt', 'skills']
|
|
29
|
+
|
|
30
|
+
const packageRoot = dirname(fileURLToPath(import.meta.url))
|
|
31
|
+
const skillsDir = resolve(packageRoot, 'skills')
|
|
32
|
+
const BOOTSTRAP_SKILL = 'using-superpowers'
|
|
33
|
+
const BOOTSTRAP_SECTION = 'superpowers:bootstrap'
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Prompt order of the bootstrap section: after the deployment persona prefix
|
|
37
|
+
* (0), and before the plan policy (500) and the tool guidance at 1000+.
|
|
38
|
+
* `verify/src-01-doc-order-drift.mjs` re-checks that placement against the
|
|
39
|
+
* installed dsh.
|
|
40
|
+
*/
|
|
41
|
+
const DEFAULT_ORDER = 50
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Plugin configuration. Every deployment-varying choice is a validated field:
|
|
45
|
+
* cordis resolves these defaults and rejects a malformed override before
|
|
46
|
+
* {@link apply} runs, instead of failing the fiber halfway through setup.
|
|
47
|
+
*/
|
|
48
|
+
export const Config = Schema.object({
|
|
49
|
+
/** Register the bundled skills on `ctx.skills`. */
|
|
50
|
+
skills: Schema.boolean().default(true),
|
|
51
|
+
/** Register the `using-superpowers` bootstrap prompt section. */
|
|
52
|
+
bootstrap: Schema.boolean().default(true),
|
|
53
|
+
/** Append the DeepSeek Harness tool mapping to the bootstrap section. */
|
|
54
|
+
toolMapping: Schema.boolean().default(true),
|
|
55
|
+
/** Prompt order of the bootstrap section; the registry rejects a non-finite value. */
|
|
56
|
+
order: Schema.number().default(DEFAULT_ORDER),
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Split a `SKILL.md` into its frontmatter block and body.
|
|
61
|
+
* @param content - the raw file text.
|
|
62
|
+
* @returns the frontmatter text (empty when absent) and the trimmed body.
|
|
63
|
+
*/
|
|
64
|
+
function splitFrontmatter(content) {
|
|
65
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/)
|
|
66
|
+
if (match === null) return { frontmatter: '', body: content.trim() }
|
|
67
|
+
return { frontmatter: match[1], body: match[2].trim() }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Count the leading ASCII spaces on one YAML line. */
|
|
71
|
+
function leadingSpaces(line) {
|
|
72
|
+
return line.length - line.trimStart().length
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Parse a YAML block-scalar header from a value such as `>-`, `|+`, or `>2-`.
|
|
77
|
+
* @returns the scalar controls, or undefined for an ordinary scalar.
|
|
78
|
+
*/
|
|
79
|
+
function parseBlockHeader(value) {
|
|
80
|
+
const match = value.match(/^([|>])(?:(?:([1-9])([+-]?))|(?:([+-])([1-9]?)))?(?:\s+#.*)?$/)
|
|
81
|
+
if (match === null) return undefined
|
|
82
|
+
return {
|
|
83
|
+
style: match[1],
|
|
84
|
+
indentation: Number(match[2] || match[5] || 0),
|
|
85
|
+
chomping: match[3] || match[4] || '',
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Fold non-empty YAML lines while preserving paragraph and indented breaks. */
|
|
90
|
+
function foldBlockLines(lines, moreIndented) {
|
|
91
|
+
let value = ''
|
|
92
|
+
for (let index = 0; index < lines.length;) {
|
|
93
|
+
if (lines[index] === '') {
|
|
94
|
+
let end = index
|
|
95
|
+
while (end < lines.length && lines[end] === '') end += 1
|
|
96
|
+
value += '\n'.repeat(end - index)
|
|
97
|
+
index = end
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
value += lines[index]
|
|
102
|
+
const next = index + 1
|
|
103
|
+
if (next < lines.length && lines[next] !== '') {
|
|
104
|
+
value += moreIndented[index] || moreIndented[next] ? '\n' : ' '
|
|
105
|
+
}
|
|
106
|
+
index = next
|
|
107
|
+
}
|
|
108
|
+
return value
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Read one top-level YAML block scalar and return the next unconsumed line.
|
|
113
|
+
* This deliberately implements only scalar semantics needed by skill metadata,
|
|
114
|
+
* while covering literal/folded styles, indentation indicators, and chomping.
|
|
115
|
+
*/
|
|
116
|
+
function readBlockScalar(lines, start, header) {
|
|
117
|
+
let end = start
|
|
118
|
+
while (end < lines.length && (lines[end].trim() === '' || lines[end].startsWith(' '))) {
|
|
119
|
+
end += 1
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const rawLines = lines.slice(start, end)
|
|
123
|
+
const firstContent = rawLines.find((line) => line.trim() !== '')
|
|
124
|
+
const indentation = header.indentation || (firstContent === undefined ? 1 : leadingSpaces(firstContent))
|
|
125
|
+
|
|
126
|
+
for (const line of rawLines) {
|
|
127
|
+
if (line.trim() !== '' && leadingSpaces(line) < indentation) {
|
|
128
|
+
throw new Error('invalid block-scalar indentation')
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const contentLines = rawLines.map((line) => (line.trim() === '' ? '' : line.slice(indentation)))
|
|
133
|
+
const moreIndented = rawLines.map((line) => line.trim() !== '' && leadingSpaces(line) > indentation)
|
|
134
|
+
const hasContent = contentLines.some((line) => line !== '')
|
|
135
|
+
let value = header.style === '|' ? contentLines.join('\n') : foldBlockLines(contentLines, moreIndented)
|
|
136
|
+
|
|
137
|
+
if (rawLines.length > 0) value += '\n'
|
|
138
|
+
if (header.chomping === '-') {
|
|
139
|
+
value = value.replace(/\n+$/, '')
|
|
140
|
+
} else if (header.chomping !== '+') {
|
|
141
|
+
value = hasContent ? `${value.replace(/\n+$/, '')}\n` : ''
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return { value, nextLine: end }
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Parse one quoted or plain YAML scalar. */
|
|
148
|
+
function parseInlineScalar(value) {
|
|
149
|
+
if (value.startsWith('"')) {
|
|
150
|
+
if (!value.endsWith('"')) throw new Error('unterminated double-quoted scalar')
|
|
151
|
+
return JSON.parse(value)
|
|
152
|
+
}
|
|
153
|
+
if (value.startsWith("'")) {
|
|
154
|
+
if (!value.endsWith("'")) throw new Error('unterminated single-quoted scalar')
|
|
155
|
+
return value.slice(1, -1).replace(/''/g, "'")
|
|
156
|
+
}
|
|
157
|
+
return value.replace(/\s+#.*$/, '').trim()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Read the scalar frontmatter keys a Superpowers skill declares. Besides the
|
|
162
|
+
* current one-line metadata, support YAML literal and folded block scalars so
|
|
163
|
+
* a future vendored release cannot silently turn `description: >-` into `>-`.
|
|
164
|
+
* @param frontmatter - the frontmatter text.
|
|
165
|
+
* @returns the parsed string values by key.
|
|
166
|
+
*/
|
|
167
|
+
function parseFrontmatter(frontmatter) {
|
|
168
|
+
const fields = {}
|
|
169
|
+
const lines = frontmatter.split(/\r?\n/)
|
|
170
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
171
|
+
const match = lines[index].match(/^([A-Za-z][A-Za-z0-9_-]*):\s*(.*)$/)
|
|
172
|
+
if (match === null) continue
|
|
173
|
+
|
|
174
|
+
const rawValue = match[2].trim()
|
|
175
|
+
const block = parseBlockHeader(rawValue)
|
|
176
|
+
if (block !== undefined) {
|
|
177
|
+
const parsed = readBlockScalar(lines, index + 1, block)
|
|
178
|
+
fields[match[1]] = parsed.value
|
|
179
|
+
index = parsed.nextLine - 1
|
|
180
|
+
continue
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (rawValue !== '') fields[match[1]] = parseInlineScalar(rawValue)
|
|
184
|
+
}
|
|
185
|
+
return fields
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Load every bundled skill.
|
|
190
|
+
* @returns one entry per readable skill directory.
|
|
191
|
+
*/
|
|
192
|
+
function loadBundledSkills() {
|
|
193
|
+
const skills = []
|
|
194
|
+
const issues = []
|
|
195
|
+
let entries
|
|
196
|
+
try {
|
|
197
|
+
entries = readdirSync(skillsDir, { withFileTypes: true })
|
|
198
|
+
} catch (error) {
|
|
199
|
+
issues.push(`cannot read skills directory ${skillsDir}: ${error instanceof Error ? error.message : String(error)}`)
|
|
200
|
+
return { skills, issues }
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const seen = new Map()
|
|
204
|
+
entries.sort((left, right) => left.name.localeCompare(right.name))
|
|
205
|
+
for (const entry of entries) {
|
|
206
|
+
if (!entry.isDirectory()) continue
|
|
207
|
+
const skillDir = join(skillsDir, entry.name)
|
|
208
|
+
const skillPath = join(skillDir, 'SKILL.md')
|
|
209
|
+
let raw
|
|
210
|
+
try {
|
|
211
|
+
raw = readFileSync(skillPath, 'utf8')
|
|
212
|
+
} catch (error) {
|
|
213
|
+
issues.push(`cannot read ${skillPath}: ${error instanceof Error ? error.message : String(error)}`)
|
|
214
|
+
continue
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const { frontmatter, body } = splitFrontmatter(raw)
|
|
218
|
+
if (frontmatter === '') {
|
|
219
|
+
issues.push(`${skillPath} has no valid frontmatter`)
|
|
220
|
+
continue
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let fields
|
|
224
|
+
try {
|
|
225
|
+
fields = parseFrontmatter(frontmatter)
|
|
226
|
+
} catch (error) {
|
|
227
|
+
issues.push(`cannot parse ${skillPath}: ${error instanceof Error ? error.message : String(error)}`)
|
|
228
|
+
continue
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const skillName = fields.name
|
|
232
|
+
const description = fields.description
|
|
233
|
+
if (skillName === undefined || description === undefined || description === '') {
|
|
234
|
+
issues.push(`${skillPath} requires non-empty name and description fields`)
|
|
235
|
+
continue
|
|
236
|
+
}
|
|
237
|
+
if (body === '') {
|
|
238
|
+
issues.push(`${skillPath} has an empty instruction body`)
|
|
239
|
+
continue
|
|
240
|
+
}
|
|
241
|
+
if (seen.has(skillName)) {
|
|
242
|
+
issues.push(`${skillPath} duplicates skill name "${skillName}" from ${seen.get(skillName)}`)
|
|
243
|
+
continue
|
|
244
|
+
}
|
|
245
|
+
seen.set(skillName, skillPath)
|
|
246
|
+
|
|
247
|
+
skills.push({
|
|
248
|
+
name: skillName,
|
|
249
|
+
description,
|
|
250
|
+
...(fields.whenToUse === undefined ? {} : { whenToUse: fields.whenToUse }),
|
|
251
|
+
content: body,
|
|
252
|
+
source: 'bundled',
|
|
253
|
+
path: skillPath,
|
|
254
|
+
resourceBase: { kind: 'directory', path: skillDir },
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
return { skills, issues }
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* The dsh tool vocabulary Superpowers instructions map onto. Superpowers is
|
|
262
|
+
* written against several harnesses and names Claude Code's PascalCase tools;
|
|
263
|
+
* without this mapping a skill tells the model to call tools that do not exist
|
|
264
|
+
* here.
|
|
265
|
+
* @returns the mapping section text.
|
|
266
|
+
*/
|
|
267
|
+
function dshToolMapping() {
|
|
268
|
+
return `## DeepSeek Harness tool mapping
|
|
269
|
+
|
|
270
|
+
Superpowers skills are written for several coding agents. In DeepSeek Harness, use these tools:
|
|
271
|
+
|
|
272
|
+
- Invoke a skill → the native \`skill\` tool; every Superpowers skill is already in your skill catalog, so never read a \`SKILL.md\` by hand
|
|
273
|
+
- Read a file → \`read\` (\`read_image\` for images)
|
|
274
|
+
- Create or overwrite a file → \`write\`
|
|
275
|
+
- Modify an existing file → \`edit\`, or \`str_replace_editor\` where it is offered
|
|
276
|
+
- Run a shell command → \`bash\`; for long work pass \`run_in_background\`, then collect it with \`job_output\`, \`job_list\`, and \`job_kill\`
|
|
277
|
+
- Find files by path pattern → \`glob\`
|
|
278
|
+
- Search file contents → \`grep\`
|
|
279
|
+
- Track tasks → \`todo_write\`
|
|
280
|
+
- Ask the human a question → \`ask_user_question\`
|
|
281
|
+
- Search the web → \`web_search\`
|
|
282
|
+
- Dispatch a subagent → \`subagent\` for a fresh child, \`subagent_fork\` to continue from this session; steer children with \`send_message\`, \`interrupt_agent\`, and \`list_agents\`
|
|
283
|
+
- Present a plan for approval → \`exit_plan_mode\`, while the session is in plan mode
|
|
284
|
+
|
|
285
|
+
Read Claude Code's \`Task\` as \`subagent\`, \`TodoWrite\` as \`todo_write\`, and \`Bash\`/\`Read\`/\`Write\`/\`Edit\`/\`Glob\`/\`Grep\` as their lowercase equivalents above. DeepSeek Harness exposes no hook or slash-command API to skills, so skip instructions that install hooks or register commands and do the work with these tools instead.`
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Build the bootstrap text.
|
|
290
|
+
* @param bootstrapBody - the `using-superpowers` body, without frontmatter.
|
|
291
|
+
* @param includeToolMapping - whether to append the dsh tool mapping.
|
|
292
|
+
* @returns the prompt section text.
|
|
293
|
+
*/
|
|
294
|
+
function buildBootstrap(bootstrapBody, includeToolMapping) {
|
|
295
|
+
const mapping = includeToolMapping ? `\n\n${dshToolMapping()}` : ''
|
|
296
|
+
return `<EXTREMELY_IMPORTANT>
|
|
297
|
+
You have superpowers.
|
|
298
|
+
|
|
299
|
+
The using-superpowers skill content is included below and is already loaded for this session. Follow it now. Do not load using-superpowers again through the skill tool.
|
|
300
|
+
|
|
301
|
+
${bootstrapBody}${mapping}
|
|
302
|
+
</EXTREMELY_IMPORTANT>`
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Report bundled skills whose name a higher-priority skill owns.
|
|
307
|
+
*
|
|
308
|
+
* The registry resolves precedence when it collects a catalog, and only there:
|
|
309
|
+
* a project skill outranks this plugin's runtime registration, and a preset's
|
|
310
|
+
* own skill outranks it outright. Neither is an error — a deployment may shadow
|
|
311
|
+
* on purpose — but a shadowed skill must not be invisible, which is what this
|
|
312
|
+
* report exists for. It runs once per workspace, because every subagent of a
|
|
313
|
+
* session shares its parent's composition and would repeat the same warning.
|
|
314
|
+
*
|
|
315
|
+
* @param ctx - plugin context; used for the catalog read and the warning.
|
|
316
|
+
* @param agent - the agent whose catalog view to check.
|
|
317
|
+
* @param bundled - the skills this plugin registered.
|
|
318
|
+
* @param reported - signatures already warned about, kept per plugin instance.
|
|
319
|
+
*/
|
|
320
|
+
async function reportShadowedSkills(ctx, agent, bundled, reported) {
|
|
321
|
+
const cwd = agent?.session?.header?.cwd
|
|
322
|
+
const owned = new Map(bundled.map((skill) => [skill.name, skill.path]))
|
|
323
|
+
const visible = await ctx.skills.list({ cwd, scope: agent })
|
|
324
|
+
const shadowed = visible.filter((skill) => owned.has(skill.name) && skill.path !== owned.get(skill.name))
|
|
325
|
+
if (shadowed.length === 0) return
|
|
326
|
+
|
|
327
|
+
const signature = `${cwd ?? ''}\u0000${shadowed
|
|
328
|
+
.map((skill) => `${skill.name}:${skill.provider}:${skill.source}:${skill.path ?? ''}`)
|
|
329
|
+
.sort()
|
|
330
|
+
.join('|')}`
|
|
331
|
+
if (reported.has(signature)) return
|
|
332
|
+
reported.add(signature)
|
|
333
|
+
|
|
334
|
+
const winners = shadowed
|
|
335
|
+
.map((skill) => {
|
|
336
|
+
const at = skill.path === undefined ? '' : ` at ${skill.path}`
|
|
337
|
+
return `"${skill.name}" from ${skill.source} (provider "${skill.provider}")${at}`
|
|
338
|
+
})
|
|
339
|
+
.join(', ')
|
|
340
|
+
const where = cwd === undefined ? '' : ` in ${cwd}`
|
|
341
|
+
const count = shadowed.length
|
|
342
|
+
ctx.logger.warn(
|
|
343
|
+
`superpowers: ${count} bundled skill${count === 1 ? '' : 's'} shadowed${where}; the model loads ${winners} instead`,
|
|
344
|
+
)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Register the bundled skills, the per-agent shadow report, and the bootstrap
|
|
349
|
+
* prompt section.
|
|
350
|
+
* @param ctx - plugin context; every registration is disposed with it.
|
|
351
|
+
* @param config - plugin configuration; unset fields take their schema defaults.
|
|
352
|
+
*/
|
|
353
|
+
export function apply(ctx, config) {
|
|
354
|
+
const options = Config(config)
|
|
355
|
+
if (!options.skills && !options.bootstrap) return
|
|
356
|
+
|
|
357
|
+
const { skills: bundled, issues } = loadBundledSkills()
|
|
358
|
+
for (const issue of issues) ctx.logger.warn(`superpowers: ${issue}`)
|
|
359
|
+
|
|
360
|
+
if (bundled.length === 0) {
|
|
361
|
+
ctx.logger.warn(`superpowers: no valid skills found under ${skillsDir}`)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (options.skills) {
|
|
365
|
+
for (const skill of bundled) ctx.skills.register(skill)
|
|
366
|
+
|
|
367
|
+
const reported = new Set()
|
|
368
|
+
ctx.on('agent/created', async ({ agent }) => {
|
|
369
|
+
try {
|
|
370
|
+
await reportShadowedSkills(ctx, agent, bundled, reported)
|
|
371
|
+
} catch (error) {
|
|
372
|
+
const reason = error instanceof Error ? error.message : String(error)
|
|
373
|
+
ctx.logger.warn(`superpowers: cannot check the skill catalog of agent "${agent?.id}": ${reason}`)
|
|
374
|
+
}
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (!options.bootstrap) return
|
|
379
|
+
|
|
380
|
+
const bootstrap = bundled.find((skill) => skill.name === BOOTSTRAP_SKILL)
|
|
381
|
+
if (bootstrap === undefined) {
|
|
382
|
+
ctx.logger.warn(`superpowers: ${BOOTSTRAP_SKILL} is missing; the bootstrap section is not registered`)
|
|
383
|
+
return
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// A preset whose persona declares itself the complete section owns the whole
|
|
387
|
+
// system prompt, and the registry drops this section in that scope without an
|
|
388
|
+
// error; no published API reports that decision, so the registration stands
|
|
389
|
+
// and the limitation is documented in the README instead.
|
|
390
|
+
ctx.systemPrompt.section({
|
|
391
|
+
name: BOOTSTRAP_SECTION,
|
|
392
|
+
order: options.order,
|
|
393
|
+
text: buildBootstrap(bootstrap.content, options.toolMapping),
|
|
394
|
+
})
|
|
395
|
+
}
|