kilo-superpowers-compose 0.1.0 → 0.1.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.md +158 -97
- package/agents/compose-dev.md +1 -4
- package/agents/compose-review.md +1 -4
- package/bin/lib.js +2 -0
- package/package.json +12 -1
- package/plugin/index.js +246 -0
package/README.md
CHANGED
|
@@ -1,150 +1,211 @@
|
|
|
1
1
|
# kilo-superpowers-compose
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
> 头脑风暴 → 规划 → 子代理实现 → 两阶段评审 → 合并的完整流程。
|
|
3
|
+
[](https://www.npmjs.com/package/kilo-superpowers-compose)
|
|
4
|
+
[](./LICENSE)
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
> A Kilo Code / Kilo CLI plugin that packages the
|
|
7
|
+
> [obra/superpowers](https://github.com/obra/superpowers) development workflow
|
|
8
|
+
> into a single installable package, exposing a **`compose`** orchestrator agent
|
|
9
|
+
> that drives brainstorming → planning → subagent implementation → two-stage
|
|
10
|
+
> review → merge.
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
并通过自动化测试与隔离环境往返验证。详见 [更新日志](#更新日志)。
|
|
12
|
+
## Status
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
**v0.1.2.** Installed via the npm CLI and verified on both **Kilo CLI** and the
|
|
15
|
+
**VS Code Kilo Code** extension (they share the same config, so one install
|
|
16
|
+
covers both).
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
代理,对任意编码任务运行完整的、有纪律的 Superpowers 工作流。
|
|
18
|
+
> **About the `plugin` field:** Kilo's `plugin: ["…"]` field in `kilo.jsonc`
|
|
19
|
+
> does **not** load npm-named plugins in current Kilo — adding it only slows
|
|
20
|
+
> startup. This package ships a plugin module (`plugin/index.js`) for the
|
|
21
|
+
> future, but **do not add it to the `plugin` field**. Use the npm CLI install
|
|
22
|
+
> below. See [docs/DESIGN.md §10 Q5](docs/DESIGN.md#10-open-questions--decisions-pending).
|
|
20
23
|
|
|
21
|
-
##
|
|
24
|
+
## What it is
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
`kilo-superpowers-compose` bundles 14 battle-tested Superpowers skills + 3
|
|
27
|
+
purpose-built agents + a `/superpowers` slash command into one npm package.
|
|
28
|
+
Run one install command and the skills link into `~/.kilo/skills/`, the agent
|
|
29
|
+
files copy into `~/.config/kilo/agent/`, the command into
|
|
30
|
+
`~/.config/kilo/commands/`, and `kilo.jsonc` gets the skill path registered.
|
|
31
|
+
Restart Kilo and a `compose` agent appears in the agent picker, ready to run
|
|
32
|
+
the full, disciplined Superpowers workflow on any coding task.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
> ⚠ **Two steps required.** Running only step ① (`npm install -g`) does
|
|
37
|
+
> nothing visible — it only installs the CLI binary, not the agent/command
|
|
38
|
+
> files, the skills link, or `kilo.jsonc`. Skipping step ② is the most
|
|
39
|
+
> common mistake.
|
|
40
|
+
|
|
41
|
+
**Step ① — Install the CLI**:
|
|
24
42
|
|
|
25
43
|
```bash
|
|
26
44
|
npm install -g kilo-superpowers-compose
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Only installs the CLI binary (the `kilo-superpowers-compose` command
|
|
48
|
+
itself); does not touch your config directory.
|
|
49
|
+
|
|
50
|
+
**Step ② — Install into Kilo**:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
27
53
|
kilo-superpowers-compose install
|
|
28
54
|
```
|
|
29
55
|
|
|
30
|
-
|
|
31
|
-
|
|
56
|
+
Copies the 3 agent files to `~/.config/kilo/agent/`, the command to
|
|
57
|
+
`~/.config/kilo/commands/`, creates the skills link at
|
|
58
|
+
`~/.kilo/skills/superpowers`, and adds an entry to `kilo.jsonc`'s
|
|
59
|
+
`skills.paths`. **Idempotent**: safe to re-run.
|
|
32
60
|
|
|
33
|
-
|
|
61
|
+
**Step ③ — Restart Kilo** (fully quit and reopen the CLI; **Reload Window**
|
|
62
|
+
in VS Code).
|
|
34
63
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
[docs/DESIGN.md §10 Q5](docs/DESIGN.md)。
|
|
64
|
+
After this, `compose` appears in `/agents` and `/superpowers` works. One
|
|
65
|
+
install covers both Kilo CLI and the VS Code Kilo Code extension (they
|
|
66
|
+
share `~/.config/kilo/`).
|
|
39
67
|
|
|
40
|
-
|
|
41
|
-
> 技能复制到 `~/.config/kilo/skills/`)。后续版本会提交到 [kilo-marketplace](https://github.com/Kilo-Org/kilo-marketplace)。
|
|
68
|
+
### Kilo Marketplace (official channel — coming soon)
|
|
42
69
|
|
|
43
|
-
|
|
70
|
+
The Marketplace lets you install from the Kilo sidebar with no terminal. We're
|
|
71
|
+
preparing a contribution to
|
|
72
|
+
[`Kilo-Org/kilo-marketplace`](https://github.com/Kilo-Org/kilo-marketplace).
|
|
73
|
+
Until then, use the npm install above.
|
|
44
74
|
|
|
45
|
-
|
|
46
|
-
`using-superpowers`、`brainstorming`、`test-driven-development`、`systematic-debugging`、
|
|
47
|
-
`verification-before-completion`、`writing-plans`、`executing-plans`、
|
|
48
|
-
`subagent-driven-development`、`requesting-code-review`、`receiving-code-review`、
|
|
49
|
-
`using-git-worktrees`、`finishing-a-development-branch`、`dispatching-parallel-agents`、
|
|
50
|
-
`writing-skills`。
|
|
51
|
-
- **3 个代理**:`compose`(主代理 / 编排器)、`compose-dev`(子代理 / 实现者)、
|
|
52
|
-
`compose-review`(子代理 / 评审者)。三者均**不锁定 `model`**,沿用你的全局默认模型。
|
|
53
|
-
- **1 个斜杠命令**:`/superpowers`(路由到 `compose`)。
|
|
75
|
+
## What gets installed
|
|
54
76
|
|
|
55
|
-
|
|
77
|
+
- **14 skills** under the `superpowers` namespace, vendored verbatim from
|
|
78
|
+
obra/superpowers `v6.1.1` (MIT): `using-superpowers`, `brainstorming`,
|
|
79
|
+
`test-driven-development`, `systematic-debugging`,
|
|
80
|
+
`verification-before-completion`, `writing-plans`, `executing-plans`,
|
|
81
|
+
`subagent-driven-development`, `requesting-code-review`,
|
|
82
|
+
`receiving-code-review`, `using-git-worktrees`,
|
|
83
|
+
`finishing-a-development-branch`, `dispatching-parallel-agents`,
|
|
84
|
+
`writing-skills`.
|
|
85
|
+
- **3 agents**: `compose` (primary orchestrator), `compose-dev` (TDD
|
|
86
|
+
implementer subagent), `compose-review` (two-stage reviewer subagent). None
|
|
87
|
+
pin a `model` — they use your global default model.
|
|
88
|
+
- **1 slash command**: `/superpowers` (routes to `compose`).
|
|
56
89
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
90
|
+
## Update & uninstall
|
|
91
|
+
|
|
92
|
+
> **Update is also two steps.** `npm update -g` upgrades the package
|
|
93
|
+
> itself; the `update` subcommand re-syncs the artifacts to Kilo's config.
|
|
94
|
+
> Running only step ① won't update your agents/commands/skills link.
|
|
60
95
|
|
|
61
|
-
|
|
62
|
-
|
|
96
|
+
**Update** (two steps, after a new version is published):
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm update -g kilo-superpowers-compose # ① upgrade the package
|
|
100
|
+
kilo-superpowers-compose update # ② re-sync artifacts to Kilo (idempotent)
|
|
63
101
|
```
|
|
64
102
|
|
|
65
|
-
|
|
103
|
+
You can also just re-run `kilo-superpowers-compose update` (without
|
|
104
|
+
`npm update`) — it refreshes artifacts using the current global package
|
|
105
|
+
version, but won't pull a newer version.
|
|
106
|
+
|
|
107
|
+
**Uninstall** (removes everything this package installed, manifest-based;
|
|
108
|
+
never touches your own files):
|
|
66
109
|
|
|
67
110
|
```bash
|
|
68
|
-
|
|
69
|
-
kilo-superpowers-compose
|
|
111
|
+
kilo-superpowers-compose uninstall # remove artifacts
|
|
112
|
+
npm uninstall -g kilo-superpowers-compose # remove the CLI itself
|
|
70
113
|
```
|
|
71
114
|
|
|
72
|
-
|
|
73
|
-
`
|
|
115
|
+
Uninstall removes: the skills link, the 3 agent files, the
|
|
116
|
+
`superpowers.md` command, this package's `skills.paths` entry in
|
|
117
|
+
`kilo.jsonc`, and the install manifest. Your own skills, agents, and config
|
|
118
|
+
are left untouched.
|
|
119
|
+
|
|
120
|
+
## Common mistakes
|
|
121
|
+
|
|
122
|
+
**"I ran `npm install -g` but `/agents` doesn't show `compose`."**
|
|
123
|
+
— You only ran step ①. The CLI is installed, but no agent files, skills
|
|
124
|
+
link, or command were created. Run `kilo-superpowers-compose install`.
|
|
74
125
|
|
|
75
|
-
|
|
126
|
+
**"I changed package code after install; restarting Kilo doesn't pick it up."**
|
|
127
|
+
— `~/.kilo/skills/superpowers` is a junction pointing to the package
|
|
128
|
+
directory, so package upgrades are picked up automatically. But
|
|
129
|
+
agent/command files were copied at install time and don't auto-update. Run
|
|
130
|
+
`kilo-superpowers-compose update`.
|
|
131
|
+
|
|
132
|
+
**"I added `plugin: ['kilo-superpowers-compose']` to `kilo.jsonc`."**
|
|
133
|
+
— Remove it. Current Kilo doesn't load this field; it only slows startup.
|
|
134
|
+
This package installs via the npm CLI — no `plugin` field needed.
|
|
135
|
+
|
|
136
|
+
## CLI usage
|
|
76
137
|
|
|
77
138
|
```text
|
|
78
139
|
kilo-superpowers-compose <command>
|
|
79
140
|
|
|
80
|
-
|
|
81
|
-
install
|
|
82
|
-
uninstall
|
|
83
|
-
update
|
|
141
|
+
Commands:
|
|
142
|
+
install Install skills, agents, and the slash command (default)
|
|
143
|
+
uninstall Remove everything this package installed (manifest-based)
|
|
144
|
+
update Re-run install (idempotent)
|
|
84
145
|
|
|
85
|
-
|
|
86
|
-
-v, --version
|
|
87
|
-
-h, --help
|
|
146
|
+
Options:
|
|
147
|
+
-v, --version Show version
|
|
148
|
+
-h, --help Show help
|
|
88
149
|
```
|
|
89
150
|
|
|
90
|
-
###
|
|
151
|
+
### Environment variables
|
|
91
152
|
|
|
92
|
-
|
|
|
153
|
+
| Variable | Purpose |
|
|
93
154
|
|---|---|
|
|
94
|
-
| `KILO_HOME=<path>` |
|
|
95
|
-
| `KILO_SUPERPOWERS_PREFIX=1` |
|
|
96
|
-
| `KILO_SUPERPOWERS_DRY_RUN=1` |
|
|
97
|
-
| `KILO_SUPERPOWERS_VERBOSE=1` |
|
|
155
|
+
| `KILO_HOME=<path>` | Override user home (for testing / isolated configs) |
|
|
156
|
+
| `KILO_SUPERPOWERS_PREFIX=1` | (reserved) prefix skill names; v0.1 isolates via the `superpowers` namespace instead |
|
|
157
|
+
| `KILO_SUPERPOWERS_DRY_RUN=1` | Print intended actions without modifying anything |
|
|
158
|
+
| `KILO_SUPERPOWERS_VERBOSE=1` | Verbose logging (to stderr) |
|
|
98
159
|
|
|
99
|
-
###
|
|
160
|
+
### Exit codes
|
|
100
161
|
|
|
101
|
-
`0`
|
|
162
|
+
`0` success · `1` generic error · `2` `kilo.jsonc` parse error (restored from
|
|
163
|
+
backup) · `3` target dir not writable · `4` skills link creation failed.
|
|
102
164
|
|
|
103
|
-
>
|
|
104
|
-
>
|
|
105
|
-
>
|
|
165
|
+
> **`kilo.jsonc` comments**: the installer strips only `//` line comments;
|
|
166
|
+
> **block comments `/* */` are not handled**. If your `kilo.jsonc` has block
|
|
167
|
+
> comments and fails to parse, the installer restores from the auto-backup and
|
|
168
|
+
> exits with code `2`. Writing back loses comments (accepted trade-off).
|
|
106
169
|
|
|
107
|
-
##
|
|
170
|
+
## Notes
|
|
108
171
|
|
|
109
|
-
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
-
|
|
172
|
+
- **Same-name agent**: if you already have an agent named `compose`, installing
|
|
173
|
+
overwrites it (accepted for v0.1).
|
|
174
|
+
- **Skill namespace**: the 14 skills live under `superpowers/`, so they won't
|
|
175
|
+
collide with your own `~/.kilo/skills/<name>` skills — only an existing
|
|
176
|
+
`superpowers` directory would conflict.
|
|
177
|
+
- **Windows links**: skills are linked via a directory junction (no admin
|
|
178
|
+
rights needed); on rare failure it falls back to a recursive copy.
|
|
179
|
+
- **No auto-`postinstall`**: install is explicit, so your `kilo.jsonc` is never
|
|
180
|
+
modified without you running the command.
|
|
115
181
|
|
|
116
|
-
##
|
|
182
|
+
## Development & testing
|
|
117
183
|
|
|
118
184
|
```bash
|
|
119
|
-
node --test #
|
|
120
|
-
npm pack #
|
|
185
|
+
node --test # zero-dependency tests (installer logic + plugin module + install/uninstall round-trip)
|
|
186
|
+
npm pack # inspect the published tarball
|
|
121
187
|
```
|
|
122
188
|
|
|
123
|
-
##
|
|
124
|
-
|
|
125
|
-
- [docs/DESIGN.md](docs/DESIGN.md) —— 架构、命名、包布局、设计决策、风险
|
|
126
|
-
- [docs/INSTALLER.md](docs/INSTALLER.md) —— `bin/` 安装器规格与源码
|
|
127
|
-
- [docs/AGENTS.md](docs/AGENTS.md) —— 三个代理的规格(frontmatter + 系统提示词)
|
|
128
|
-
- [docs/REFERENCES.md](docs/REFERENCES.md) —— 所有参考链接(上游项目、Kilo 文档等)
|
|
129
|
-
- [NOTICE](NOTICE) —— 上游 obra/superpowers 归属(tag `v6.1.1`,MIT)
|
|
130
|
-
|
|
131
|
-
## 灵感来源
|
|
132
|
-
|
|
133
|
-
本项目移植 / 改编自
|
|
134
|
-
[moyu-by/opencode-mimo-compose](https://github.com/moyu-by/opencode-mimo-compose),
|
|
135
|
-
后者为 OpenCode 做了同样的事。我们:
|
|
189
|
+
## Documentation
|
|
136
190
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
191
|
+
- [docs/DESIGN.md](docs/DESIGN.md) — architecture, naming, layout, decisions, risks
|
|
192
|
+
- [docs/INSTALLER.md](docs/INSTALLER.md) — `bin/` installer spec and source
|
|
193
|
+
- [docs/AGENTS.md](docs/AGENTS.md) — the three agents (frontmatter + prompts)
|
|
194
|
+
- [docs/REFERENCES.md](docs/REFERENCES.md) — all reference links
|
|
195
|
+
- [NOTICE](NOTICE) — upstream obra/superpowers attribution (tag `v6.1.1`, MIT)
|
|
140
196
|
|
|
141
|
-
##
|
|
197
|
+
## Inspiration
|
|
142
198
|
|
|
143
|
-
|
|
144
|
-
|
|
199
|
+
This project ports/adapts
|
|
200
|
+
[moyu-by/opencode-mimo-compose](https://github.com/moyu-by/opencode-mimo-compose)
|
|
201
|
+
(which did the same for OpenCode). We: re-target it at Kilo (a Kilo is an
|
|
202
|
+
OpenCode fork — high overlap); swap the skill source to
|
|
203
|
+
[obra/superpowers](https://github.com/obra/superpowers) (MIT); and tighten the
|
|
204
|
+
orchestrator into a pure-routing role (it never writes code itself) with a
|
|
205
|
+
strict two-stage review subagent.
|
|
145
206
|
|
|
146
|
-
##
|
|
207
|
+
## License
|
|
147
208
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
209
|
+
MIT — see [LICENSE](LICENSE). The 14 vendored skills are from
|
|
210
|
+
obra/superpowers (MIT, © Jesse Vincent), kept verbatim; attribution in
|
|
211
|
+
[NOTICE](NOTICE).
|
package/agents/compose-dev.md
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
3
|
-
Implementation subagent for the compose workflow. Loads TDD,
|
|
4
|
-
systematic debugging, and verification-before-completion skills.
|
|
5
|
-
Receives a single discrete task; executes it; reports back.
|
|
2
|
+
description: "Implementation subagent for the compose workflow. Executes a single discrete task via TDD, systematic debugging, and verification."
|
|
6
3
|
mode: subagent
|
|
7
4
|
---
|
|
8
5
|
|
package/agents/compose-review.md
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
3
|
-
Two-stage code review subagent for the compose workflow.
|
|
4
|
-
Stage 1: spec compliance. Stage 2: code quality.
|
|
5
|
-
Reports findings by severity (critical / important / nit).
|
|
2
|
+
description: "Two-stage code review subagent (spec compliance + code quality) for the compose workflow. Reports findings only; never edits code."
|
|
6
3
|
mode: subagent
|
|
7
4
|
---
|
|
8
5
|
|
package/bin/lib.js
CHANGED
|
@@ -368,6 +368,8 @@ export function runInstall(opts = {}) {
|
|
|
368
368
|
console.log(` kilo.jsonc: skills.paths ${added ? '已新增条目' : '已存在(幂等跳过)'}`);
|
|
369
369
|
console.log('');
|
|
370
370
|
console.log(' 请重启 Kilo CLI / VS Code 扩展以加载。');
|
|
371
|
+
console.log('');
|
|
372
|
+
console.log(' 💡 To upgrade later: npm update -g kilo-superpowers-compose && kilo-superpowers-compose update');
|
|
371
373
|
return EXIT.OK;
|
|
372
374
|
}
|
|
373
375
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kilo-superpowers-compose",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "将 obra/superpowers 工作流打包为 Kilo 插件:一个 compose 编排器代理、/superpowers 斜杠命令与 14 个技能,一条命令安装。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kilo",
|
|
@@ -29,14 +29,25 @@
|
|
|
29
29
|
"engines": {
|
|
30
30
|
"node": ">=18"
|
|
31
31
|
},
|
|
32
|
+
"main": "plugin/index.js",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": "./plugin/index.js"
|
|
35
|
+
},
|
|
32
36
|
"bin": {
|
|
33
37
|
"kilo-superpowers-compose": "bin/cli.js"
|
|
34
38
|
},
|
|
39
|
+
"kilo": {
|
|
40
|
+
"type": "plugin"
|
|
41
|
+
},
|
|
42
|
+
"opencode": {
|
|
43
|
+
"type": "plugin"
|
|
44
|
+
},
|
|
35
45
|
"files": [
|
|
36
46
|
"bin",
|
|
37
47
|
"skills",
|
|
38
48
|
"agents",
|
|
39
49
|
"commands",
|
|
50
|
+
"plugin",
|
|
40
51
|
"NOTICE"
|
|
41
52
|
],
|
|
42
53
|
"scripts": {
|
package/plugin/index.js
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// plugin/index.js
|
|
2
|
+
// kilo-superpowers-compose — Kilo 插件模块(Path B)。
|
|
3
|
+
//
|
|
4
|
+
// 这是 Path A(npm CLI 安装器,见 bin/)之外的另一条安装路径:
|
|
5
|
+
// 在 kilo.jsonc 里写 `"plugin": ["kilo-superpowers-compose"]`,Kilo 启动时
|
|
6
|
+
// 会加载本模块的默认导出(工厂函数),调用其 `config(config)` 钩子,向**运行时**
|
|
7
|
+
// 配置对象直接注入 3 个 agent 与 skills.paths —— agent 从不落盘,仅存活于运行时。
|
|
8
|
+
//
|
|
9
|
+
// 设计参考:moyu-by/opencode-mimo-compose 的 src/index.js(OpenCode 插件机制)。
|
|
10
|
+
// Kilo 是 OpenCode 的 fork,复用同样的 `config` 钩子契约。
|
|
11
|
+
//
|
|
12
|
+
// 硬性约束(与 bin/lib.js 一致):
|
|
13
|
+
// - 零第三方依赖;仅用 node:fs / node:path / node:os / node:url。
|
|
14
|
+
// - 绝不抛异常:**插件崩溃会让 Kilo 启动失败**。所有 fs / 解析操作均包 try/catch。
|
|
15
|
+
// - 跨平台路径一律用 path.join,绝不手拼反斜杠;尊重 KILO_HOME。
|
|
16
|
+
// - skills.paths 幂等判定用规范化路径比较(path.resolve + toLowerCase)。
|
|
17
|
+
//
|
|
18
|
+
// 自动更新原理:
|
|
19
|
+
// - agents:每次 Kilo 启动由 config 钩子重注(永远取包内最新内容)。
|
|
20
|
+
// - skills:config.skills.paths 指向**包内** skills 目录,`npm update -g` 后即时刷新。
|
|
21
|
+
// - /superpowers 命令:无法经 config 钩子注册(Kilo 无对应钩子),故采用
|
|
22
|
+
// "复制到 ~/.config/kilo/commands/ + 版本标记" 的方式;包升级时标记比对触发重同步。
|
|
23
|
+
|
|
24
|
+
import fs from 'node:fs';
|
|
25
|
+
import path from 'node:path';
|
|
26
|
+
import os from 'node:os';
|
|
27
|
+
import { fileURLToPath } from 'node:url';
|
|
28
|
+
|
|
29
|
+
// ─── 路径常量 ──────────────────────────────────────────────────────────
|
|
30
|
+
// 本文件即 plugin/index.js;其上一级为包根。
|
|
31
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
32
|
+
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
33
|
+
|
|
34
|
+
const AGENTS_SRC = path.join(PKG_ROOT, 'agents');
|
|
35
|
+
const SKILLS_SRC = path.join(PKG_ROOT, 'skills');
|
|
36
|
+
const COMMANDS_SRC = path.join(PKG_ROOT, 'commands');
|
|
37
|
+
|
|
38
|
+
// Kilo 配置目录(尊重 KILO_HOME,便于测试与隔离配置)。
|
|
39
|
+
// 惰性求值 —— 读取在调用时进行(而非模块加载时),使测试可用临时 KILO_HOME 隔离,
|
|
40
|
+
// 不触碰用户真实配置目录。
|
|
41
|
+
function defaultConfigDir() {
|
|
42
|
+
const home = (process.env.KILO_HOME || os.homedir()) + '';
|
|
43
|
+
return path.join(home, '.config', 'kilo');
|
|
44
|
+
}
|
|
45
|
+
function defaultMarkerFile() {
|
|
46
|
+
return path.join(defaultConfigDir(), '.kilo-superpowers-compose-plugin');
|
|
47
|
+
}
|
|
48
|
+
function defaultCommandsDstDir() {
|
|
49
|
+
return path.join(defaultConfigDir(), 'commands');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 包版本(仅用于版本标记比对;读失败回退为占位串)。
|
|
53
|
+
const PKG_VERSION = readPkgVersion(PKG_ROOT);
|
|
54
|
+
|
|
55
|
+
function readPkgVersion(root) {
|
|
56
|
+
try {
|
|
57
|
+
return JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')).version || '0.0.0';
|
|
58
|
+
} catch (_) {
|
|
59
|
+
return '0.0.0';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ─── 纯函数 / 路径规范化 ───────────────────────────────────────────────
|
|
64
|
+
// 与 bin/lib.js 的 normalizePath 行为一致,便于 skills.paths 去重判定。
|
|
65
|
+
export function normalizePath(p) {
|
|
66
|
+
try {
|
|
67
|
+
return path.resolve(p).toLowerCase();
|
|
68
|
+
} catch (_) {
|
|
69
|
+
return String(p || '').toLowerCase();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// skills.paths 是否已包含目标(规范化比较,跨分隔符 / 大小写)。
|
|
74
|
+
export function skillsPathsContains(paths, target) {
|
|
75
|
+
const t = normalizePath(target);
|
|
76
|
+
return Array.isArray(paths) && paths.some((p) => normalizePath(p) === t);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 去除字符串两端的成对引号。
|
|
80
|
+
function stripQuotes(v) {
|
|
81
|
+
if (v.length >= 2) {
|
|
82
|
+
const a = v[0];
|
|
83
|
+
const b = v[v.length - 1];
|
|
84
|
+
if ((a === '"' && b === '"') || (a === "'" && b === "'")) {
|
|
85
|
+
return v.slice(1, -1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return v;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─── Frontmatter 解析 ──────────────────────────────────────────────────
|
|
92
|
+
// 既支持单行 `key: value`(我们的 3 个 agent description 现均为单行),
|
|
93
|
+
// 也防御性地支持 YAML 块标量(`|` 字面量 / `>` 折叠)以防有人改回多行。
|
|
94
|
+
// 不引入第三方 YAML 解析器 —— 只覆盖我们用到的子集。
|
|
95
|
+
export function parseFrontmatter(content) {
|
|
96
|
+
const m = typeof content === 'string'
|
|
97
|
+
? content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/)
|
|
98
|
+
: null;
|
|
99
|
+
if (!m) return { data: {}, body: typeof content === 'string' ? content : '' };
|
|
100
|
+
const lines = m[1].split(/\r?\n/);
|
|
101
|
+
const data = {};
|
|
102
|
+
let i = 0;
|
|
103
|
+
while (i < lines.length) {
|
|
104
|
+
const line = lines[i];
|
|
105
|
+
const kv = line.match(/^([\w-]+)[ \t]*:[ \t]*(.*)$/);
|
|
106
|
+
if (!kv) {
|
|
107
|
+
i++;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const key = kv[1];
|
|
111
|
+
let val = kv[2];
|
|
112
|
+
// 块标量:|(字面量,保留换行)或 >(折叠为空格)。
|
|
113
|
+
if (/^[|>][+-]?$/.test(val)) {
|
|
114
|
+
const folded = val.startsWith('>');
|
|
115
|
+
const collected = [];
|
|
116
|
+
i++;
|
|
117
|
+
while (i < lines.length && (lines[i] === '' || /^[ \t]/.test(lines[i]))) {
|
|
118
|
+
collected.push(lines[i].replace(/^[ \t]+/, ''));
|
|
119
|
+
i++;
|
|
120
|
+
}
|
|
121
|
+
val = (folded ? collected.join(' ') : collected.join('\n')).trim();
|
|
122
|
+
data[key] = val;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const tv = val.trim();
|
|
126
|
+
if (tv === 'true') data[key] = true;
|
|
127
|
+
else if (tv === 'false') data[key] = false;
|
|
128
|
+
else data[key] = stripQuotes(tv);
|
|
129
|
+
i++;
|
|
130
|
+
}
|
|
131
|
+
return { data, body: m[2] };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ─── Agent 加载 ────────────────────────────────────────────────────────
|
|
135
|
+
// 读取包内 agents/*.md,剥离 frontmatter 取 description / mode 与正文 prompt。
|
|
136
|
+
export function loadAgents(agentsSrc) {
|
|
137
|
+
const dir = agentsSrc || AGENTS_SRC;
|
|
138
|
+
const agents = {};
|
|
139
|
+
try {
|
|
140
|
+
const files = fs.readdirSync(dir).filter((f) => f.endsWith('.md'));
|
|
141
|
+
for (const file of files) {
|
|
142
|
+
try {
|
|
143
|
+
const content = fs.readFileSync(path.join(dir, file), 'utf8');
|
|
144
|
+
const { data, body } = parseFrontmatter(content);
|
|
145
|
+
const name = file.replace(/\.md$/, '');
|
|
146
|
+
agents[name] = {
|
|
147
|
+
description: data.description || name,
|
|
148
|
+
// primary 保持 primary;其余一律按 subagent 处理(防御性默认)。
|
|
149
|
+
mode: data.mode === 'primary' ? 'primary' : 'subagent',
|
|
150
|
+
prompt: body,
|
|
151
|
+
};
|
|
152
|
+
} catch (_) {
|
|
153
|
+
// 单个 agent 解析失败不阻断其余 agent。
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
} catch (_) {
|
|
157
|
+
// agents 目录不存在 / 不可读 → 返回空集(不抛)。
|
|
158
|
+
}
|
|
159
|
+
return agents;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ─── 版本标记:同步复制的命令 ──────────────────────────────────────────
|
|
163
|
+
// agents / skills 每次启动自动重注 / 自动刷新;只有复制的 /superpowers 命令
|
|
164
|
+
// 需要版本标记触发重同步。
|
|
165
|
+
export function needsSetup(markerFile) {
|
|
166
|
+
const f = markerFile || defaultMarkerFile();
|
|
167
|
+
try {
|
|
168
|
+
if (!fs.existsSync(f)) return true;
|
|
169
|
+
return fs.readFileSync(f, 'utf8').trim() !== PKG_VERSION;
|
|
170
|
+
} catch (_) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 执行命令同步:把 commands/superpowers.md 复制到 ~/.config/kilo/commands/,并写标记。
|
|
176
|
+
export function runSetup(opts = {}) {
|
|
177
|
+
const commandsDst = opts.commandsDstDir || defaultCommandsDstDir();
|
|
178
|
+
const mf = opts.markerFile || defaultMarkerFile();
|
|
179
|
+
try {
|
|
180
|
+
const srcCmd = path.join(opts.commandsSrc || COMMANDS_SRC, 'superpowers.md');
|
|
181
|
+
if (fs.existsSync(srcCmd)) {
|
|
182
|
+
try {
|
|
183
|
+
fs.mkdirSync(commandsDst, { recursive: true });
|
|
184
|
+
fs.copyFileSync(srcCmd, path.join(commandsDst, 'superpowers.md'));
|
|
185
|
+
} catch (_) {
|
|
186
|
+
// 命令复制失败不应阻断 agent / skills 注入 —— 仅记录为无命令。
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
fs.mkdirSync(path.dirname(mf), { recursive: true });
|
|
191
|
+
fs.writeFileSync(mf, PKG_VERSION, 'utf8');
|
|
192
|
+
} catch (_) {
|
|
193
|
+
// 标记写失败:下次启动会重试,无致命影响。
|
|
194
|
+
}
|
|
195
|
+
} catch (_) {
|
|
196
|
+
// 整体防御:runSetup 任何异常都不外泄。
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ─── 插件工厂(Kilo 加载入口,当前休眠)──────────────────────────────
|
|
201
|
+
// 设计目标:Kilo 按 PluginModule 契约({ server: Plugin },见 @kilocode/plugin)
|
|
202
|
+
// import 本模块、调用 server() 工厂、再调用返回的 config() 钩子,向运行时配置
|
|
203
|
+
// 注入 agents/skills/command。
|
|
204
|
+
//
|
|
205
|
+
// 实测结论(2026-07,见 docs/DESIGN.md §10 Q5):当前 Kilo **不会**经
|
|
206
|
+
// `kilo.jsonc` 的 `plugin:["包名"]` 字段加载 npm 命名插件(该字段无效,还会拖慢
|
|
207
|
+
// 启动)。本模块的 config() 钩子契约本身正确(经 glob 加载器实测可注入 agent),
|
|
208
|
+
// 但作为用户安装方式暂不启用 —— 安装走 npm CLI(见 bin/)。本模块保留待 Kilo
|
|
209
|
+
// 正式支持插件加载后即可启用。命名兼容:同时以 server 命名导出(与 mimo 一致)。
|
|
210
|
+
export async function plugin(_input, _options) {
|
|
211
|
+
// 首次安装或包升级时同步命令(失败被 runSetup 内部吞掉)。
|
|
212
|
+
try {
|
|
213
|
+
if (needsSetup()) runSetup();
|
|
214
|
+
} catch (_) {}
|
|
215
|
+
|
|
216
|
+
const agents = loadAgents();
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
// config 钩子:**副作用式**改写传入的 Kilo 配置对象(不返回新对象)。
|
|
220
|
+
config: async (kiloConfig) => {
|
|
221
|
+
try {
|
|
222
|
+
if (!kiloConfig || typeof kiloConfig !== 'object') return;
|
|
223
|
+
// 1. 注册 agents:config.agent[name] = { prompt, description, mode }。
|
|
224
|
+
if (!kiloConfig.agent) kiloConfig.agent = {};
|
|
225
|
+
for (const [name, agent] of Object.entries(agents)) {
|
|
226
|
+
kiloConfig.agent[name] = {
|
|
227
|
+
prompt: agent.prompt,
|
|
228
|
+
description: agent.description,
|
|
229
|
+
mode: agent.mode,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
// 2. 注册 skills:config.skills.paths 追加包内 skills 目录(规范化去重)。
|
|
233
|
+
if (!kiloConfig.skills) kiloConfig.skills = {};
|
|
234
|
+
if (!Array.isArray(kiloConfig.skills.paths)) kiloConfig.skills.paths = [];
|
|
235
|
+
if (fs.existsSync(SKILLS_SRC) && !skillsPathsContains(kiloConfig.skills.paths, SKILLS_SRC)) {
|
|
236
|
+
kiloConfig.skills.paths.push(SKILLS_SRC);
|
|
237
|
+
}
|
|
238
|
+
} catch (_) {
|
|
239
|
+
// config 钩子内任何异常都不外泄,避免拖垮 Kilo 启动。
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export { plugin as server };
|
|
246
|
+
export default plugin;
|