skill-flow 1.0.3 → 1.0.5
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 +40 -3
- package/README.zh.md +40 -3
- package/dist/adapters/channel-adapters.js +11 -3
- package/dist/adapters/channel-adapters.js.map +1 -1
- package/dist/cli.js +69 -37
- package/dist/cli.js.map +1 -1
- package/dist/domain/types.d.ts +54 -1
- package/dist/services/config-coordinator.d.ts +38 -0
- package/dist/services/config-coordinator.js +81 -0
- package/dist/services/config-coordinator.js.map +1 -0
- package/dist/services/doctor-service.d.ts +2 -0
- package/dist/services/doctor-service.js +62 -0
- package/dist/services/doctor-service.js.map +1 -1
- package/dist/services/inventory-service.d.ts +3 -1
- package/dist/services/inventory-service.js +12 -5
- package/dist/services/inventory-service.js.map +1 -1
- package/dist/services/skill-flow.d.ts +50 -26
- package/dist/services/skill-flow.js +502 -89
- package/dist/services/skill-flow.js.map +1 -1
- package/dist/services/source-service.d.ts +20 -10
- package/dist/services/source-service.js +359 -75
- package/dist/services/source-service.js.map +1 -1
- package/dist/services/workflow-service.d.ts +2 -2
- package/dist/services/workflow-service.js +17 -4
- package/dist/services/workflow-service.js.map +1 -1
- package/dist/services/workspace-bootstrap-service.d.ts +25 -0
- package/dist/services/workspace-bootstrap-service.js +140 -0
- package/dist/services/workspace-bootstrap-service.js.map +1 -0
- package/dist/state/store.d.ts +16 -0
- package/dist/state/store.js +93 -18
- package/dist/state/store.js.map +1 -1
- package/dist/tests/clawhub.test.d.ts +1 -0
- package/dist/tests/clawhub.test.js +63 -0
- package/dist/tests/clawhub.test.js.map +1 -0
- package/dist/tests/cli-utils.test.d.ts +1 -0
- package/dist/tests/cli-utils.test.js +15 -0
- package/dist/tests/cli-utils.test.js.map +1 -0
- package/dist/tests/config-coordinator.test.d.ts +1 -0
- package/dist/tests/config-coordinator.test.js +172 -0
- package/dist/tests/config-coordinator.test.js.map +1 -0
- package/dist/tests/config-integration.test.d.ts +1 -0
- package/dist/tests/config-integration.test.js +238 -0
- package/dist/tests/config-integration.test.js.map +1 -0
- package/dist/tests/config-ui-utils.test.d.ts +1 -0
- package/dist/tests/config-ui-utils.test.js +389 -0
- package/dist/tests/config-ui-utils.test.js.map +1 -0
- package/dist/tests/find-and-naming-utils.test.d.ts +1 -0
- package/dist/tests/find-and-naming-utils.test.js +127 -0
- package/dist/tests/find-and-naming-utils.test.js.map +1 -0
- package/dist/tests/skill-flow.test.js +334 -881
- package/dist/tests/skill-flow.test.js.map +1 -1
- package/dist/tests/source-lifecycle.test.d.ts +1 -0
- package/dist/tests/source-lifecycle.test.js +605 -0
- package/dist/tests/source-lifecycle.test.js.map +1 -0
- package/dist/tests/target-definitions.test.d.ts +1 -0
- package/dist/tests/target-definitions.test.js +51 -0
- package/dist/tests/target-definitions.test.js.map +1 -0
- package/dist/tests/test-helpers.d.ts +18 -0
- package/dist/tests/test-helpers.js +123 -0
- package/dist/tests/test-helpers.js.map +1 -0
- package/dist/tui/config-app.d.ts +147 -24
- package/dist/tui/config-app.js +1081 -335
- package/dist/tui/config-app.js.map +1 -1
- package/dist/tui/find-app.d.ts +1 -1
- package/dist/tui/find-app.js +36 -4
- package/dist/tui/find-app.js.map +1 -1
- package/dist/utils/clawhub.d.ts +3 -0
- package/dist/utils/clawhub.js +32 -3
- package/dist/utils/clawhub.js.map +1 -1
- package/dist/utils/cli.d.ts +1 -0
- package/dist/utils/cli.js +15 -0
- package/dist/utils/cli.js.map +1 -0
- package/dist/utils/constants.d.ts +4 -0
- package/dist/utils/constants.js +31 -0
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/fs.d.ts +5 -0
- package/dist/utils/fs.js +52 -1
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/naming.d.ts +1 -0
- package/dist/utils/naming.js +7 -1
- package/dist/utils/naming.js.map +1 -1
- package/dist/utils/source-id.js +4 -0
- package/dist/utils/source-id.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ As your AI agent skills grow, management gets messy: one Git repo has a bunch of
|
|
|
16
16
|
|
|
17
17
|
## Key Features
|
|
18
18
|
|
|
19
|
-

|
|
20
20
|
|
|
21
21
|
**Skill-Based Grouping**
|
|
22
22
|
One Git repo = one skills group. Related skills stay together, updates and maintenance happen at the group level.
|
|
@@ -27,6 +27,9 @@ Set it up once, deploy to multiple agents (Claude Code, Cursor, Windsurf, and 13
|
|
|
27
27
|
**Interactive Terminal UI**
|
|
28
28
|
Intuitive TUI: view groups → select skills → choose targets → save configuration.
|
|
29
29
|
|
|
30
|
+
**Bootstrap On Config Open**
|
|
31
|
+
`config` renders immediately, shows boot progress, adopts unmanaged skills already found in agent roots, then audits current projections before entering the main UI.
|
|
32
|
+
|
|
30
33
|
**Explicit State Tracking**
|
|
31
34
|
`manifest.json` = what you want, `lock.json` = what's actually installed. Both are readable and queryable.
|
|
32
35
|
|
|
@@ -86,11 +89,35 @@ skill-flow uninstall my-source-id
|
|
|
86
89
|
|
|
87
90
|
By default, `add` preselects all discovered skills and all detected agent targets. When `--path <repoSubpath>` is provided, the full repo is still imported, but only skills under that path are preselected.
|
|
88
91
|
|
|
92
|
+
Examples:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Local repo
|
|
96
|
+
skill-flow add ~/code/my-skills
|
|
97
|
+
|
|
98
|
+
# GitHub shorthand
|
|
99
|
+
skill-flow add garrytan/gstack
|
|
100
|
+
|
|
101
|
+
# Full Git URL
|
|
102
|
+
skill-flow add https://github.com/garrytan/gstack.git
|
|
103
|
+
skill-flow add git@github.com:garrytan/gstack.git
|
|
104
|
+
|
|
105
|
+
# GitHub tree URL
|
|
106
|
+
skill-flow add https://github.com/garrytan/gstack/tree/main/skills
|
|
107
|
+
|
|
108
|
+
# Import the repo, but only preselect skills under a subpath
|
|
109
|
+
skill-flow add garrytan/gstack --path skills
|
|
110
|
+
|
|
111
|
+
# ClawHub package
|
|
112
|
+
skill-flow add clawhub:example/skill-pack
|
|
113
|
+
skill-flow add clawhub:example/skill-pack@1.2.3
|
|
114
|
+
```
|
|
115
|
+
|
|
89
116
|
## Command Reference
|
|
90
117
|
|
|
91
118
|
| Command | Description |
|
|
92
119
|
|---|---|
|
|
93
|
-
| `add <source>` | Add a skill source (Git repo or ClawHub) |
|
|
120
|
+
| `add <source>` | Add a skill source (local path, Git repo, or ClawHub) |
|
|
94
121
|
| `find <query>` | Search installed skills, built-in Git catalogs, and ClawHub |
|
|
95
122
|
| `search <query>` | Alias of `find` |
|
|
96
123
|
| `list` | Show skills groups |
|
|
@@ -106,6 +133,7 @@ When selected skills collide by name, `skill-flow` keeps identical duplicates as
|
|
|
106
133
|
**State Management**
|
|
107
134
|
- `~/.skillflow/manifest.json` - Your configuration (what you want)
|
|
108
135
|
- `~/.skillflow/lock.json` - Actual state (what's installed)
|
|
136
|
+
- `~/.skillflow/source/local/<source-id>/` - Imported local sources and adopted unmanaged external skills
|
|
109
137
|
- `~/.skillflow/source/git/<source-id>/` - Git repo cache
|
|
110
138
|
- `~/.skillflow/source/clawhub/<source-id>/` - ClawHub cache
|
|
111
139
|
- `~/.skillflow/catalog/git/<source-id>/` - Built-in Git catalog cache
|
|
@@ -113,13 +141,22 @@ When selected skills collide by name, `skill-flow` keeps identical duplicates as
|
|
|
113
141
|
**Deployment Strategy**
|
|
114
142
|
Uses symlinks when possible, file copies when needed. Target directories are just deploy points — real state lives in lock.json.
|
|
115
143
|
|
|
144
|
+
**Config Bootstrap**
|
|
145
|
+
- detect available agent targets
|
|
146
|
+
- scan known agent `skills/` roots for unmanaged skills
|
|
147
|
+
- import unmanaged external skills into `~/.skillflow/source/local/`
|
|
148
|
+
- refresh inventory, normalize bindings, and audit projections
|
|
149
|
+
- enter the interactive config UI
|
|
150
|
+
|
|
151
|
+
Already-managed projections are not imported again. For example, if an agent root contains symlinks that already point into `~/.skillflow/source/*`, bootstrap treats them as managed state and skips them.
|
|
152
|
+
|
|
116
153
|
## Supported Agents
|
|
117
154
|
|
|
118
155
|
Claude Code · Codex · Cursor · GitHub Copilot · Gemini CLI · OpenCode · OpenClaw · Pi · Windsurf · Roo Code · Cline · Amp · Kiro
|
|
119
156
|
|
|
120
157
|
Customize target paths via environment variables (e.g., `SKILL_FLOW_TARGET_CLAUDE_CODE`).
|
|
121
158
|
|
|
122
|
-
Broader ecosystem path references, including project-level rules and instructions paths
|
|
159
|
+
Broader ecosystem path references, including project-level rules and instructions paths (docs TBD).
|
|
123
160
|
|
|
124
161
|
## Built-in Discovery Catalogs
|
|
125
162
|
|
package/README.zh.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
`skill-flow` 用 Skill 视角重新组织管理:以 Github 仓库作为 Skill 分组依据,选择部署目标,统一更新,快速诊断问题。让 Skill 管理清晰、可控、高效。
|
|
16
16
|
|
|
17
17
|
## 核心特性
|
|
18
|
-

|
|
19
19
|
|
|
20
20
|
**Skill 分组管理**
|
|
21
21
|
一个 Github 仓库 = 一个 Skill 分组。相关 Skills 保持在一起,更新和维护以分组为单位进行。
|
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
**交互式终端 UI**
|
|
27
27
|
直观的 TUI 界面:查看分组 → 选择技能 → 选择目标 → 保存配置。
|
|
28
28
|
|
|
29
|
+
**进入 Config 自动自举**
|
|
30
|
+
`config` 会先立即渲染,再显示启动进度;启动阶段会识别 agent 根目录里尚未纳入管理的 skill,回填到 `skill-flow`,并在进入主界面前完成状态审计。
|
|
31
|
+
|
|
29
32
|
**显式状态追踪**
|
|
30
33
|
`manifest.json` 记录你的意图,`lock.json` 记录实际安装状态。状态清晰可查。
|
|
31
34
|
|
|
@@ -85,11 +88,35 @@ skill-flow uninstall my-source-id
|
|
|
85
88
|
|
|
86
89
|
`add` 默认会预选该源的全部 skill,以及当前检测到的全部 agent 目标。传入 `--path <repoSubpath>` 时,仍然会导入整个仓库,但只会预选该路径下的 skill。
|
|
87
90
|
|
|
91
|
+
示例:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# 本地仓库
|
|
95
|
+
skill-flow add ~/code/my-skills
|
|
96
|
+
|
|
97
|
+
# GitHub 简写
|
|
98
|
+
skill-flow add garrytan/gstack
|
|
99
|
+
|
|
100
|
+
# 完整 Git URL
|
|
101
|
+
skill-flow add https://github.com/garrytan/gstack.git
|
|
102
|
+
skill-flow add git@github.com:garrytan/gstack.git
|
|
103
|
+
|
|
104
|
+
# GitHub tree URL
|
|
105
|
+
skill-flow add https://github.com/garrytan/gstack/tree/main/skills
|
|
106
|
+
|
|
107
|
+
# 导入整个仓库,但只预选某个子路径下的 skill
|
|
108
|
+
skill-flow add garrytan/gstack --path skills
|
|
109
|
+
|
|
110
|
+
# ClawHub 包
|
|
111
|
+
skill-flow add clawhub:example/skill-pack
|
|
112
|
+
skill-flow add clawhub:example/skill-pack@1.2.3
|
|
113
|
+
```
|
|
114
|
+
|
|
88
115
|
## 命令参考
|
|
89
116
|
|
|
90
117
|
| 命令 | 说明 |
|
|
91
118
|
|---|---|
|
|
92
|
-
| `add <source>` |
|
|
119
|
+
| `add <source>` | 添加技能源(本地路径、Git 仓库或 ClawHub) |
|
|
93
120
|
| `find <query>` | 搜索本地已安装技能、内置 Git 仓库和 ClawHub |
|
|
94
121
|
| `search <query>` | `find` 的别名 |
|
|
95
122
|
| `list` | 显示 Skill 分组 |
|
|
@@ -105,6 +132,7 @@ skill-flow uninstall my-source-id
|
|
|
105
132
|
**状态管理**
|
|
106
133
|
- `~/.skillflow/manifest.json` - 你的配置(你想要什么)
|
|
107
134
|
- `~/.skillflow/lock.json` - 实际状态(实际装了什么)
|
|
135
|
+
- `~/.skillflow/source/local/<source-id>/` - 本地导入源,以及启动时接管的外部 skill
|
|
108
136
|
- `~/.skillflow/source/git/<source-id>/` - Git 仓库缓存
|
|
109
137
|
- `~/.skillflow/source/clawhub/<source-id>/` - ClawHub 缓存
|
|
110
138
|
- `~/.skillflow/catalog/git/<source-id>/` - 内置 Git 仓库缓存
|
|
@@ -112,13 +140,22 @@ skill-flow uninstall my-source-id
|
|
|
112
140
|
**部署策略**
|
|
113
141
|
优先使用符号链接,必要时使用文件复制。目标目录只是部署点,真正的状态在 lock.json 里。
|
|
114
142
|
|
|
143
|
+
**Config 启动时会做什么**
|
|
144
|
+
- 检测当前可用 agent 目标
|
|
145
|
+
- 扫描已知 agent `skills/` 根目录中的未受管 skill
|
|
146
|
+
- 将这些外部 skill 导入到 `~/.skillflow/source/local/`
|
|
147
|
+
- 刷新 inventory、归一化 bindings、审计当前投影状态
|
|
148
|
+
- 然后进入交互式 config 界面
|
|
149
|
+
|
|
150
|
+
如果某个 agent 根目录里的 symlink 本来就已经指向 `~/.skillflow/source/*` 下的受管内容,bootstrap 会把它视为已管理状态,不会重复回填。
|
|
151
|
+
|
|
115
152
|
## 支持的 Agent
|
|
116
153
|
|
|
117
154
|
Claude Code · Codex · Cursor · GitHub Copilot · Gemini CLI · OpenCode · OpenClaw · Pi · Windsurf · Roo Code · Cline · Amp · Kiro
|
|
118
155
|
|
|
119
156
|
可通过环境变量自定义目标路径(如 `SKILL_FLOW_TARGET_CLAUDE_CODE`)。
|
|
120
157
|
|
|
121
|
-
更广义的生态路径参考,包括 project 级 rules / instructions
|
|
158
|
+
更广义的生态路径参考,包括 project 级 rules / instructions 路径(文档整理中)。
|
|
122
159
|
|
|
123
160
|
## 默认内置发现仓库
|
|
124
161
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { TARGET_DEFINITIONS, } from "../utils/constants.js";
|
|
2
|
+
import { getTargetDetectionCandidates, TARGET_DEFINITIONS, } from "../utils/constants.js";
|
|
3
3
|
import { pathExists } from "../utils/fs.js";
|
|
4
4
|
class DefaultChannelAdapter {
|
|
5
5
|
target;
|
|
@@ -11,8 +11,16 @@ class DefaultChannelAdapter {
|
|
|
11
11
|
async detect() {
|
|
12
12
|
const definition = TARGET_DEFINITIONS[this.target];
|
|
13
13
|
const envVar = definition.envVar;
|
|
14
|
-
const
|
|
15
|
-
|
|
14
|
+
const candidates = getTargetDetectionCandidates(this.target);
|
|
15
|
+
if (candidates.length === 0) {
|
|
16
|
+
return {
|
|
17
|
+
target: this.target,
|
|
18
|
+
strategy: this.strategy,
|
|
19
|
+
available: false,
|
|
20
|
+
rootPath: path.resolve("."),
|
|
21
|
+
reason: `Target is disabled in explicit target mode. Set ${envVar} to enable it.`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
16
24
|
for (const candidate of candidates) {
|
|
17
25
|
const rootPath = path.resolve(candidate);
|
|
18
26
|
if (await pathExists(rootPath)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-adapters.js","sourceRoot":"","sources":["../../src/adapters/channel-adapters.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B,OAAO,EACL,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAS5C,MAAM,qBAAqB;IAGJ;IAFZ,QAAQ,CAAqB;IAEtC,YAAqB,MAA4B;QAA5B,WAAM,GAAN,MAAM,CAAsB;QAC/C,IAAI,CAAC,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;QACjC,MAAM,
|
|
1
|
+
{"version":3,"file":"channel-adapters.js","sourceRoot":"","sources":["../../src/adapters/channel-adapters.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B,OAAO,EACL,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAS5C,MAAM,qBAAqB;IAGJ;IAFZ,QAAQ,CAAqB;IAEtC,YAAqB,MAA4B;QAA5B,WAAM,GAAN,MAAM,CAAsB;QAC/C,IAAI,CAAC,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;QACjC,MAAM,UAAU,GAAG,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE7D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,SAAS,EAAE,KAAK;gBAChB,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;gBAC3B,MAAM,EAAE,mDAAmD,MAAM,gBAAgB;aAClF,CAAC;QACJ,CAAC;QAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACzC,IAAI,MAAM,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/B,OAAO;oBACL,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,SAAS,EAAE,IAAI;oBACf,QAAQ;iBACT,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAC5C,MAAM,EAAE,mCAAmC,MAAM,uCAAuC;SACzF,CAAC;IACJ,CAAC;IAED,iBAAiB,CAAC,QAAgB,EAAE,QAAgB;QAClD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;CACF;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;QACL,IAAI,qBAAqB,CAAC,aAAa,CAAC;QACxC,IAAI,qBAAqB,CAAC,OAAO,CAAC;QAClC,IAAI,qBAAqB,CAAC,QAAQ,CAAC;QACnC,IAAI,qBAAqB,CAAC,gBAAgB,CAAC;QAC3C,IAAI,qBAAqB,CAAC,YAAY,CAAC;QACvC,IAAI,qBAAqB,CAAC,UAAU,CAAC;QACrC,IAAI,qBAAqB,CAAC,UAAU,CAAC;QACrC,IAAI,qBAAqB,CAAC,IAAI,CAAC;QAC/B,IAAI,qBAAqB,CAAC,UAAU,CAAC;QACrC,IAAI,qBAAqB,CAAC,UAAU,CAAC;QACrC,IAAI,qBAAqB,CAAC,OAAO,CAAC;QAClC,IAAI,qBAAqB,CAAC,KAAK,CAAC;QAChC,IAAI,qBAAqB,CAAC,MAAM,CAAC;KAClC,CAAC;AACJ,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -2,31 +2,43 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { render } from "ink";
|
|
5
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
5
6
|
import { SkillFlowApp } from "./services/skill-flow.js";
|
|
6
|
-
import {
|
|
7
|
+
import { ConfigBootstrapApp } from "./tui/config-app.js";
|
|
7
8
|
import { FindApp } from "./tui/find-app.js";
|
|
8
9
|
import { formatGroupRef } from "./utils/naming.js";
|
|
9
|
-
import { formatDoctorIssue, formatWorkflowList, } from "./utils/format.js";
|
|
10
|
+
import { formatActionSummary, formatDoctorIssue, formatWorkflowList, } from "./utils/format.js";
|
|
11
|
+
import { resolveAddSourceLocator } from "./utils/cli.js";
|
|
10
12
|
import { buildFindCommand } from "./utils/find-command.js";
|
|
11
13
|
const program = new Command();
|
|
12
14
|
const app = new SkillFlowApp();
|
|
13
15
|
program
|
|
14
16
|
.name("skill-flow")
|
|
15
17
|
.description("Workflow-first skill projection manager")
|
|
16
|
-
.version(
|
|
18
|
+
.version(packageJson.version);
|
|
17
19
|
program
|
|
18
20
|
.command("add")
|
|
19
21
|
.argument("<source>", "Source locator")
|
|
20
22
|
.option("--path <repoSubpath>", "Filter Git sources to a specific repo subpath")
|
|
23
|
+
.option("--from <catalog>", "Interpret source using a named catalog")
|
|
21
24
|
.action(async (source, options) => {
|
|
22
|
-
|
|
25
|
+
let resolvedSource;
|
|
26
|
+
try {
|
|
27
|
+
resolvedSource = resolveAddSourceLocator(source, options.from);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
printErrors([{ message: error instanceof Error ? error.message : String(error) }]);
|
|
31
|
+
process.exitCode = 1;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const result = await app.addSource(resolvedSource, options.path ? { path: options.path } : undefined);
|
|
23
35
|
if (!result.ok) {
|
|
24
36
|
printErrors(result.errors);
|
|
25
37
|
process.exitCode = 1;
|
|
26
38
|
return;
|
|
27
39
|
}
|
|
28
|
-
const duplicateSkipCount = result.warnings.filter((warning) => warning.
|
|
29
|
-
const visibleWarnings = result.warnings.filter((warning) =>
|
|
40
|
+
const duplicateSkipCount = result.warnings.filter((warning) => warning.code === "DUPLICATE_LEAF").length;
|
|
41
|
+
const visibleWarnings = result.warnings.filter((warning) => warning.code !== "DUPLICATE_LEAF");
|
|
30
42
|
const duplicateSummary = duplicateSkipCount > 0
|
|
31
43
|
? `, skipped ${duplicateSkipCount} duplicate skill${duplicateSkipCount === 1 ? "" : "s"}`
|
|
32
44
|
: "";
|
|
@@ -48,52 +60,57 @@ program
|
|
|
48
60
|
.argument("<query>", "Search query")
|
|
49
61
|
.option("--json", "Print JSON output")
|
|
50
62
|
.action(async (query, options) => {
|
|
51
|
-
const result = await app.findSkills(query);
|
|
52
|
-
if (!result.ok) {
|
|
53
|
-
printErrors(result.errors);
|
|
54
|
-
process.exitCode = 1;
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
63
|
if (options.json) {
|
|
64
|
+
const result = await app.findSkills(query);
|
|
65
|
+
if (!result.ok) {
|
|
66
|
+
printErrors(result.errors);
|
|
67
|
+
process.exitCode = 1;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
58
70
|
console.log(JSON.stringify(result.data.candidates.map((candidate) => ({
|
|
59
71
|
...candidate,
|
|
60
72
|
nextCommand: buildFindCommand(candidate),
|
|
61
73
|
})), null, 2));
|
|
62
|
-
printWarnings(result.warnings.map((warning) => warning.message));
|
|
63
74
|
return;
|
|
64
75
|
}
|
|
65
|
-
const instance = render(_jsx(FindApp, { app: app, query: query
|
|
66
|
-
if (result.warnings.length > 0) {
|
|
67
|
-
for (const warning of result.warnings) {
|
|
68
|
-
console.warn(`warning: ${warning.message}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
76
|
+
const instance = render(_jsx(FindApp, { app: app, query: query }));
|
|
71
77
|
await instance.waitUntilExit();
|
|
72
78
|
});
|
|
73
79
|
program.command("config").action(async () => {
|
|
74
|
-
const
|
|
80
|
+
const instance = render(_jsx(ConfigBootstrapApp, { app: app }));
|
|
81
|
+
await instance.waitUntilExit();
|
|
82
|
+
});
|
|
83
|
+
program
|
|
84
|
+
.command("repair-source")
|
|
85
|
+
.argument("[sourceId]", "Optional skills group id")
|
|
86
|
+
.option("--all", "Repair owned source checkouts for all registered skills groups")
|
|
87
|
+
.action(async (sourceId, options) => {
|
|
88
|
+
const ids = options.all || !sourceId ? undefined : [sourceId];
|
|
89
|
+
const result = await app.repairSource(ids);
|
|
75
90
|
if (!result.ok) {
|
|
76
91
|
printErrors(result.errors);
|
|
77
92
|
process.exitCode = 1;
|
|
78
93
|
return;
|
|
79
94
|
}
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
for (const item of result.data.updated) {
|
|
96
|
+
console.log(`${item.sourceId} changed:${item.changed} +${item.addedLeafIds.length} -${item.removedLeafIds.length} invalidated:${item.invalidatedLeafIds.length}`);
|
|
97
|
+
}
|
|
98
|
+
printWarnings(result.warnings.map((warning) => warning.message));
|
|
99
|
+
});
|
|
100
|
+
program
|
|
101
|
+
.command("repair-state")
|
|
102
|
+
.argument("[sourceId]", "Optional skills group id")
|
|
103
|
+
.option("--all", "Rebuild source-side state for all registered skills groups")
|
|
104
|
+
.action(async (sourceId, options) => {
|
|
105
|
+
const ids = options.all || !sourceId ? undefined : [sourceId];
|
|
106
|
+
const result = await app.repairState(ids);
|
|
107
|
+
if (!result.ok) {
|
|
108
|
+
printErrors(result.errors);
|
|
109
|
+
process.exitCode = 1;
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
console.log(`repaired sources:${result.data.repairedSourceIds.length} removed deployments:${result.data.removedDeploymentCount}`);
|
|
113
|
+
printWarnings(result.warnings.map((warning) => warning.message));
|
|
97
114
|
});
|
|
98
115
|
program
|
|
99
116
|
.command("update")
|
|
@@ -116,6 +133,21 @@ program
|
|
|
116
133
|
}
|
|
117
134
|
printWarnings(result.warnings.map((warning) => warning.message));
|
|
118
135
|
});
|
|
136
|
+
program
|
|
137
|
+
.command("repair-targets")
|
|
138
|
+
.argument("[sourceId]", "Optional skills group id")
|
|
139
|
+
.option("--all", "Repair targets for all registered skills groups")
|
|
140
|
+
.action(async (sourceId, options) => {
|
|
141
|
+
const ids = options.all || !sourceId ? undefined : [sourceId];
|
|
142
|
+
const result = await app.repairTargets(ids);
|
|
143
|
+
if (!result.ok) {
|
|
144
|
+
printErrors(result.errors);
|
|
145
|
+
process.exitCode = 1;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
console.log(formatActionSummary(result.data.actions));
|
|
149
|
+
printWarnings(result.warnings.map((warning) => warning.message));
|
|
150
|
+
});
|
|
119
151
|
program.command("doctor").action(async () => {
|
|
120
152
|
const result = await app.doctor();
|
|
121
153
|
if (!result.ok) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":";;AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":"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"}
|
package/dist/domain/types.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export type Result<T> = {
|
|
|
17
17
|
warnings: Warning[];
|
|
18
18
|
errors: Failure[];
|
|
19
19
|
};
|
|
20
|
-
export type SourceKind = "git" | "clawhub";
|
|
20
|
+
export type SourceKind = "local" | "git" | "clawhub";
|
|
21
21
|
export type DeploymentTargetName = "claude-code" | "codex" | "cursor" | "github-copilot" | "gemini-cli" | "opencode" | "openclaw" | "pi" | "windsurf" | "roo-code" | "cline" | "amp" | "kiro";
|
|
22
22
|
export type DeploymentStrategy = "symlink" | "copy";
|
|
23
23
|
export type HealthStatus = "HEALTHY" | "ACTIVE" | "INACTIVE" | "PARTIAL" | "BLOCKED" | "INVALID" | "UPDATE AVAILABLE" | "UP TO DATE" | "DRIFT DETECTED";
|
|
@@ -28,6 +28,9 @@ export type SourceManifestRecord = {
|
|
|
28
28
|
displayName: string;
|
|
29
29
|
addedAt: string;
|
|
30
30
|
requestedPath?: string;
|
|
31
|
+
selectionMode?: "all" | "partial";
|
|
32
|
+
originLocator?: string;
|
|
33
|
+
originRequestedPath?: string;
|
|
31
34
|
};
|
|
32
35
|
export type TargetBinding = {
|
|
33
36
|
enabled: boolean;
|
|
@@ -36,6 +39,10 @@ export type TargetBinding = {
|
|
|
36
39
|
export type SourceBinding = {
|
|
37
40
|
targets: Partial<Record<DeploymentTargetName, TargetBinding>>;
|
|
38
41
|
};
|
|
42
|
+
export type DraftBinding = {
|
|
43
|
+
enabledTargets: DeploymentTargetName[];
|
|
44
|
+
selectedLeafIds: string[];
|
|
45
|
+
};
|
|
39
46
|
export type Manifest = {
|
|
40
47
|
schemaVersion: 1;
|
|
41
48
|
sources: SourceManifestRecord[];
|
|
@@ -45,6 +52,10 @@ export type InvalidLeafRecord = {
|
|
|
45
52
|
path: string;
|
|
46
53
|
reason: string;
|
|
47
54
|
};
|
|
55
|
+
export type DuplicateLeafRecord = {
|
|
56
|
+
path: string;
|
|
57
|
+
keptPath: string;
|
|
58
|
+
};
|
|
48
59
|
export type SourceLockRecord = {
|
|
49
60
|
id: string;
|
|
50
61
|
locator: string;
|
|
@@ -59,6 +70,9 @@ export type SourceLockRecord = {
|
|
|
59
70
|
resolvedVersion?: string;
|
|
60
71
|
contentHash?: string;
|
|
61
72
|
versionMode?: "pinned" | "floating";
|
|
73
|
+
originBranch?: string;
|
|
74
|
+
importedFromTargets?: DeploymentTargetName[];
|
|
75
|
+
importMode?: "explicit-add" | "bootstrap-detected";
|
|
62
76
|
};
|
|
63
77
|
export type LeafRecord = {
|
|
64
78
|
id: string;
|
|
@@ -90,6 +104,31 @@ export type LockFile = {
|
|
|
90
104
|
leafInventory: LeafRecord[];
|
|
91
105
|
deployments: DeploymentRecord[];
|
|
92
106
|
};
|
|
107
|
+
export type SourceUpdateDiffKind = "added" | "removed" | "moved" | "invalidated" | "changed";
|
|
108
|
+
export type SourceUpdateDiff = {
|
|
109
|
+
kind: SourceUpdateDiffKind;
|
|
110
|
+
sourceId: string;
|
|
111
|
+
leafId: string;
|
|
112
|
+
relativePath: string;
|
|
113
|
+
contentHash: string;
|
|
114
|
+
requestedPath?: string;
|
|
115
|
+
previousLeafId?: string;
|
|
116
|
+
previousRelativePath?: string;
|
|
117
|
+
previousContentHash?: string;
|
|
118
|
+
};
|
|
119
|
+
export type SourceUpdateResultItem = {
|
|
120
|
+
sourceId: string;
|
|
121
|
+
changed: boolean;
|
|
122
|
+
requestedPath?: string;
|
|
123
|
+
selectionMode?: "all" | "partial";
|
|
124
|
+
addedLeafIds: string[];
|
|
125
|
+
removedLeafIds: string[];
|
|
126
|
+
invalidatedLeafIds: string[];
|
|
127
|
+
diffs: SourceUpdateDiff[];
|
|
128
|
+
};
|
|
129
|
+
export type SourceUpdateResult = {
|
|
130
|
+
updated: SourceUpdateResultItem[];
|
|
131
|
+
};
|
|
93
132
|
export type ChannelDetection = {
|
|
94
133
|
target: DeploymentTargetName;
|
|
95
134
|
strategy: DeploymentStrategy;
|
|
@@ -131,6 +170,15 @@ export type DoctorReport = {
|
|
|
131
170
|
status: "HEALTHY" | "PARTIAL" | "BLOCKED";
|
|
132
171
|
issues: DoctorIssue[];
|
|
133
172
|
};
|
|
173
|
+
export type ConfigBootFailure = {
|
|
174
|
+
sourceId: string;
|
|
175
|
+
message: string;
|
|
176
|
+
};
|
|
177
|
+
export type ConfigBootStatus = {
|
|
178
|
+
phase: "success" | "partial_failure";
|
|
179
|
+
updatedSourceIds: string[];
|
|
180
|
+
failedSources: ConfigBootFailure[];
|
|
181
|
+
};
|
|
134
182
|
export type WorkflowSummary = {
|
|
135
183
|
source: SourceManifestRecord;
|
|
136
184
|
lock: SourceLockRecord | undefined;
|
|
@@ -138,6 +186,11 @@ export type WorkflowSummary = {
|
|
|
138
186
|
bindings: SourceBinding;
|
|
139
187
|
activeTargetCount: number;
|
|
140
188
|
health: HealthStatus;
|
|
189
|
+
issueCounts?: {
|
|
190
|
+
warning: number;
|
|
191
|
+
error: number;
|
|
192
|
+
};
|
|
193
|
+
healthReason?: string;
|
|
141
194
|
};
|
|
142
195
|
export type SkillCandidateAction = {
|
|
143
196
|
type: "none";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ConfigBootStatus, DeploymentTargetName, DoctorReport, DraftBinding, LockFile, Manifest, Result, WorkflowSummary } from "../domain/types.js";
|
|
2
|
+
import type { BootstrapEvent } from "./workspace-bootstrap-service.js";
|
|
3
|
+
type ConfigCoordinatorDeps = {
|
|
4
|
+
store: {
|
|
5
|
+
init(): Promise<void>;
|
|
6
|
+
readManifest(): Promise<Manifest>;
|
|
7
|
+
};
|
|
8
|
+
doctorService: {
|
|
9
|
+
run(manifest: Manifest, lockFile: LockFile): Promise<Result<DoctorReport>>;
|
|
10
|
+
};
|
|
11
|
+
workflowService: {
|
|
12
|
+
getSummaries(manifest: Manifest, lockFile: LockFile, audit?: DoctorReport): WorkflowSummary[];
|
|
13
|
+
};
|
|
14
|
+
getAvailableTargets(): Promise<DeploymentTargetName[]>;
|
|
15
|
+
pruneMissingCheckouts(): Promise<Result<{
|
|
16
|
+
removedSourceIds: string[];
|
|
17
|
+
}>>;
|
|
18
|
+
getConfigData(): Promise<Result<{
|
|
19
|
+
manifest: Manifest;
|
|
20
|
+
lockFile: LockFile;
|
|
21
|
+
summaries: WorkflowSummary[];
|
|
22
|
+
}>>;
|
|
23
|
+
};
|
|
24
|
+
export type ConfigBootstrapData = {
|
|
25
|
+
availableTargets: DeploymentTargetName[];
|
|
26
|
+
manifest: Manifest;
|
|
27
|
+
lockFile: LockFile;
|
|
28
|
+
summaries: WorkflowSummary[];
|
|
29
|
+
initialDrafts: Record<string, DraftBinding>;
|
|
30
|
+
audit: DoctorReport;
|
|
31
|
+
bootStatus: ConfigBootStatus;
|
|
32
|
+
};
|
|
33
|
+
export declare class ConfigCoordinator {
|
|
34
|
+
private readonly deps;
|
|
35
|
+
constructor(deps: ConfigCoordinatorDeps);
|
|
36
|
+
bootstrapWorkspaceState(onEvent?: (event: BootstrapEvent) => void): Promise<Result<ConfigBootstrapData>>;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { fail, ok } from "../utils/result.js";
|
|
2
|
+
export class ConfigCoordinator {
|
|
3
|
+
deps;
|
|
4
|
+
constructor(deps) {
|
|
5
|
+
this.deps = deps;
|
|
6
|
+
}
|
|
7
|
+
async bootstrapWorkspaceState(onEvent) {
|
|
8
|
+
onEvent?.({
|
|
9
|
+
phase: "detect-targets",
|
|
10
|
+
level: "info",
|
|
11
|
+
message: "Detecting available agent targets...",
|
|
12
|
+
});
|
|
13
|
+
const availableTargets = await this.deps.getAvailableTargets();
|
|
14
|
+
const pruned = await this.deps.pruneMissingCheckouts();
|
|
15
|
+
if (!pruned.ok) {
|
|
16
|
+
return fail(pruned.errors, pruned.warnings);
|
|
17
|
+
}
|
|
18
|
+
if (pruned.data.removedSourceIds.length > 0) {
|
|
19
|
+
onEvent?.({
|
|
20
|
+
phase: "refresh-sources",
|
|
21
|
+
level: "warning",
|
|
22
|
+
message: `Removed ${pruned.data.removedSourceIds.length} missing group${pruned.data.removedSourceIds.length === 1 ? "" : "s"} from config state.`,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
onEvent?.({
|
|
26
|
+
phase: "normalize-bindings",
|
|
27
|
+
level: "info",
|
|
28
|
+
message: "Loading config state...",
|
|
29
|
+
});
|
|
30
|
+
const configData = await this.deps.getConfigData();
|
|
31
|
+
if (!configData.ok) {
|
|
32
|
+
return fail(configData.errors, configData.warnings);
|
|
33
|
+
}
|
|
34
|
+
onEvent?.({
|
|
35
|
+
phase: "audit-projections",
|
|
36
|
+
level: "info",
|
|
37
|
+
message: "Auditing current projections...",
|
|
38
|
+
});
|
|
39
|
+
const audit = await this.deps.doctorService.run(configData.data.manifest, configData.data.lockFile);
|
|
40
|
+
if (!audit.ok) {
|
|
41
|
+
return fail(audit.errors, audit.warnings);
|
|
42
|
+
}
|
|
43
|
+
onEvent?.({
|
|
44
|
+
phase: "build-summaries",
|
|
45
|
+
level: "info",
|
|
46
|
+
message: "Building config summaries...",
|
|
47
|
+
});
|
|
48
|
+
const summaries = this.deps.workflowService.getSummaries(configData.data.manifest, configData.data.lockFile, audit.data);
|
|
49
|
+
const bootStatus = {
|
|
50
|
+
phase: "success",
|
|
51
|
+
updatedSourceIds: [],
|
|
52
|
+
failedSources: [],
|
|
53
|
+
};
|
|
54
|
+
onEvent?.({
|
|
55
|
+
phase: "done",
|
|
56
|
+
level: "success",
|
|
57
|
+
message: "Config bootstrap complete.",
|
|
58
|
+
});
|
|
59
|
+
return ok({
|
|
60
|
+
availableTargets,
|
|
61
|
+
manifest: configData.data.manifest,
|
|
62
|
+
lockFile: configData.data.lockFile,
|
|
63
|
+
summaries,
|
|
64
|
+
initialDrafts: buildInitialDrafts(summaries),
|
|
65
|
+
audit: audit.data,
|
|
66
|
+
bootStatus,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function buildInitialDrafts(summaries) {
|
|
71
|
+
return Object.fromEntries(summaries.map((summary) => {
|
|
72
|
+
const enabledTargets = Object.entries(summary.bindings.targets)
|
|
73
|
+
.filter(([, value]) => value?.enabled)
|
|
74
|
+
.map(([target]) => target);
|
|
75
|
+
const selectedLeafIds = [
|
|
76
|
+
...new Set(enabledTargets.flatMap((target) => summary.bindings.targets[target]?.leafIds ?? [])),
|
|
77
|
+
];
|
|
78
|
+
return [summary.source.id, { enabledTargets, selectedLeafIds }];
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=config-coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-coordinator.js","sourceRoot":"","sources":["../../src/services/config-coordinator.ts"],"names":[],"mappings":"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"}
|