itismyskillmarket 1.3.0 → 1.3.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/.github/workflows/publish-npm.yml +59 -0
- package/.github/workflows/publish-skill.yml +72 -0
- package/5e51cb7aa8b8e60d49d86f4689f5d4d1.png +0 -0
- package/CHANGELOG.md +410 -0
- package/DEVELOPMENT.md +376 -0
- package/README.md +75 -6
- package/SKILLMARKET-GUIDE.md +288 -0
- package/dist/index.js +733 -212
- package/docs/WEEKLY-UPDATE-2026-04-23.md +43 -0
- package/docs/plans/2026-04-01-skillmarket-design.md +267 -0
- package/docs/plans/2026-04-01-skillmarket-implementation.md +1031 -0
- package/docs/plans/2026-04-15-cross-platform-adapter-design.md +416 -0
- package/docs/plans/2026-04-15-cross-platform-adapter-plan.md +833 -0
- package/docs/plans/2026-04-16-keyword-search-design.md +143 -0
- package/docs/plans/2026-04-29-weekly-update.md +57 -0
- package/package.json +1 -6
- package/skills/README.md +54 -0
- package/skills/test-skill/SKILL.md +25 -0
- package/skills/test-skill/index.js +66 -0
- package/skills/test-skill/metadata.json +9 -0
- package/skills/test-skill/package.json +19 -0
- package/skills/test-skill-1/SKILL.md +24 -0
- package/skills/test-skill-1/index.js +13 -0
- package/skills/test-skill-1/metadata.json +9 -0
- package/skills/test-skill-1/package.json +16 -0
- package/skills/test-skill-2/SKILL.md +25 -0
- package/skills/test-skill-2/index.js +13 -0
- package/skills/test-skill-2/metadata.json +9 -0
- package/skills/test-skill-2/package.json +16 -0
- package/src/adapters/base.ts +87 -0
- package/src/adapters/claude.ts +31 -0
- package/src/adapters/index.ts +9 -0
- package/src/adapters/opencode.ts +40 -0
- package/src/adapters/registry.ts +77 -0
- package/src/adapters/vscode.ts +62 -0
- package/src/cli.ts +189 -75
- package/src/commands/info.ts +4 -15
- package/src/commands/install.ts +93 -54
- package/src/commands/ls.ts +182 -17
- package/src/commands/npm.ts +118 -16
- package/src/commands/search.ts +12 -7
- package/src/commands/sync.ts +6 -27
- package/src/commands/uninstall.ts +313 -15
- package/src/commands/update.ts +2 -2
- package/src/index.ts +27 -0
- package/src/types.ts +35 -0
- package/tsconfig.json +10 -0
- package/tsup.config.ts +22 -0
- package/wanxuchen-skillmarket-1.0.1.tgz +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# SkillMarket 关键字搜索功能设计方案
|
|
2
|
+
|
|
3
|
+
**版本**: 1.0
|
|
4
|
+
**日期**: 2026-04-16
|
|
5
|
+
**状态**: 待开发
|
|
6
|
+
|
|
7
|
+
## 1. 功能概述
|
|
8
|
+
|
|
9
|
+
为 SkillMarket CLI 添加关键字搜索功能,支持在 npm registry 和本地已安装 skills 中按关键字检索。
|
|
10
|
+
|
|
11
|
+
## 2. 推荐方案
|
|
12
|
+
|
|
13
|
+
### 2.1 新增命令
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# 搜索 npm registry(默认行为,与现有 skm ls 等效但带过滤)
|
|
17
|
+
skm search <keyword>
|
|
18
|
+
|
|
19
|
+
# 搜索本地已安装的 skills
|
|
20
|
+
skm search <keyword> --installed
|
|
21
|
+
|
|
22
|
+
# 组合:分页 + 搜索关键字
|
|
23
|
+
skm search <keyword> --page 1 --limit 20
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2.2 搜索字段
|
|
27
|
+
|
|
28
|
+
支持匹配以下字段:
|
|
29
|
+
- `id`: skill 包名(精确匹配 + 模糊匹配)
|
|
30
|
+
- `displayName`: 显示名称
|
|
31
|
+
- `description`: 描述
|
|
32
|
+
|
|
33
|
+
### 2.3 实现方式
|
|
34
|
+
|
|
35
|
+
复用现有 `skm ls` 命令,添加 `--search` / `-s` 选项:
|
|
36
|
+
|
|
37
|
+
| 命令 | 说明 |
|
|
38
|
+
|------|------|
|
|
39
|
+
| `skm ls --search <keyword>` | 在 npm registry 中搜索 |
|
|
40
|
+
| `skm ls --search <keyword> --installed` | 在本地已安装 skills 中搜索 |
|
|
41
|
+
| `skm ls -s <keyword>` | 简写形式 |
|
|
42
|
+
|
|
43
|
+
**推荐**:将搜索功能作为 `skm ls` 的选项,而不是新增独立命令。原因:
|
|
44
|
+
- 代码复用度高
|
|
45
|
+
- 用户学习成本低
|
|
46
|
+
- 与分页功能自然组合
|
|
47
|
+
|
|
48
|
+
## 3. 技术方案
|
|
49
|
+
|
|
50
|
+
### 3.1 代码修改
|
|
51
|
+
|
|
52
|
+
**文件**: `src/commands/ls.ts`
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
interface LsOptions {
|
|
56
|
+
// ... 现有字段
|
|
57
|
+
search?: string; // 新增:搜索关键字
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3.2 npm search 实现
|
|
62
|
+
|
|
63
|
+
修改 `searchSkillmarketPackages` 函数,添加关键字过滤参数:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
interface SearchOptions {
|
|
67
|
+
from: number;
|
|
68
|
+
size: number;
|
|
69
|
+
keyword?: string; // 新增
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**注意**:npm search API 本身支持通过 `q` 参数进行关键字搜索,可以直接传入。
|
|
74
|
+
|
|
75
|
+
### 3.3 本地搜索实现
|
|
76
|
+
|
|
77
|
+
在已有本地 skills 列表上进行内存过滤:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
function filterInstalledSkills(skills: InstalledSkill[], keyword: string): InstalledSkill[] {
|
|
81
|
+
const lower = keyword.toLowerCase();
|
|
82
|
+
return skills.filter(s =>
|
|
83
|
+
s.id.toLowerCase().includes(lower) ||
|
|
84
|
+
s.displayName?.toLowerCase().includes(lower) ||
|
|
85
|
+
s.description?.toLowerCase().includes(lower)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 3.4 UI 输出
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
# npm 搜索结果
|
|
94
|
+
$ skm ls -s "brainstorm"
|
|
95
|
+
|
|
96
|
+
📦 brainstorming@1.0.0 (Found 1 match for "brainstorm")
|
|
97
|
+
名称: Brainstorming
|
|
98
|
+
描述: 多智能体头脑风暴能力
|
|
99
|
+
平台: opencode
|
|
100
|
+
链接: https://npmjs.com/package/brainstorming
|
|
101
|
+
|
|
102
|
+
# 本地搜索结果
|
|
103
|
+
$ skm ls --installed -s "test"
|
|
104
|
+
|
|
105
|
+
🟢 test-skill-1@1.0.0
|
|
106
|
+
Platforms: opencode
|
|
107
|
+
Installed: 2026-04-16
|
|
108
|
+
|
|
109
|
+
🟢 test-skill-2@1.0.0
|
|
110
|
+
Platforms: opencode
|
|
111
|
+
Installed: 2026-04-15
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 4. 实施步骤
|
|
115
|
+
|
|
116
|
+
1. **修改 `ls.ts` 命令模块**
|
|
117
|
+
- 添加 `search` 选项到 `LsOptions` 接口
|
|
118
|
+
- 实现关键字过滤逻辑
|
|
119
|
+
- 支持 npm search API 和本地过滤
|
|
120
|
+
|
|
121
|
+
2. **修改 `cli.ts`**
|
|
122
|
+
- 在 `ls` 命令中添加 `--search` / `-s` 选项
|
|
123
|
+
|
|
124
|
+
3. **测试**
|
|
125
|
+
- `skm ls -s <keyword>`
|
|
126
|
+
- `skm ls --installed -s <keyword>`
|
|
127
|
+
- 边界情况:无结果、分页
|
|
128
|
+
|
|
129
|
+
## 5. 优先级
|
|
130
|
+
|
|
131
|
+
**P1 - 高**
|
|
132
|
+
- 核心搜索功能
|
|
133
|
+
- npm registry 搜索
|
|
134
|
+
|
|
135
|
+
**P2 - 中**
|
|
136
|
+
- 本地已安装 skills 搜索
|
|
137
|
+
- 搜索结果高亮(可选)
|
|
138
|
+
|
|
139
|
+
## 6. 风险与注意事项
|
|
140
|
+
|
|
141
|
+
- npm search API 有速率限制,生产环境考虑缓存
|
|
142
|
+
- 中文关键字搜索需要确认 npm API 支持
|
|
143
|
+
- 大结果集需要分页处理
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# SkillMarket 本周更新日志 (2026-04-23 ~ 2026-04-29)
|
|
2
|
+
|
|
3
|
+
## 📦 版本发布
|
|
4
|
+
|
|
5
|
+
### v1.3.1 - 2026-04-29
|
|
6
|
+
|
|
7
|
+
**新功能:**
|
|
8
|
+
- ✨ 新增独立 `skm search` 命令,支持关键词匹配搜索技能
|
|
9
|
+
- 🔍 优化搜索精度,增加本地过滤支持
|
|
10
|
+
|
|
11
|
+
**修复:**
|
|
12
|
+
- 🐛 修复 GitHub Actions workflow 中版本重复更新的问题
|
|
13
|
+
- 🔧 改进 `publish-npm.yml` 的版本判断逻辑
|
|
14
|
+
|
|
15
|
+
**发布详情:**
|
|
16
|
+
- npm: https://www.npmjs.com/package/itismyskillmarket/v/1.3.1
|
|
17
|
+
- GitHub Release: https://github.com/wxc2004/market/releases/tag/v1.3.1
|
|
18
|
+
- 对比: https://github.com/wxc2004/market/compare/v1.2.9...v1.3.1
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 📊 本周统计
|
|
23
|
+
|
|
24
|
+
| 指标 | 数据 |
|
|
25
|
+
|------|------|
|
|
26
|
+
| 新增功能 | 1 个 |
|
|
27
|
+
| Bug 修复 | 1 个 |
|
|
28
|
+
| 版本发布 | 1 个 (v1.3.1) |
|
|
29
|
+
| Commits | 2 个 |
|
|
30
|
+
| 代码行变更 | ~150 行 |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🔜 下周计划
|
|
35
|
+
|
|
36
|
+
- [ ] 增加技能评分/评论功能
|
|
37
|
+
- [ ] 支持更多 AI 编码工具平台
|
|
38
|
+
- [ ] 优化安装速度(增量更新)
|
|
39
|
+
- [ ] 增加技能依赖检查
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 📝 详细变更
|
|
44
|
+
|
|
45
|
+
### feat: add independent search command with keyword matching (1e91352)
|
|
46
|
+
- 新增 `skm search <keyword>` 命令
|
|
47
|
+
- 支持按名称、描述关键词搜索已安装和远程技能
|
|
48
|
+
- 本地缓存优先,减少网络请求
|
|
49
|
+
|
|
50
|
+
### fix: skip npm version when version unchanged in workflow (2213d4a)
|
|
51
|
+
- 修复 GitHub Actions 发布时 `npm version` 报错问题
|
|
52
|
+
- 增加版本号判断逻辑,避免重复设置
|
|
53
|
+
- 优化 CI/CD 流程稳定性
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
*生成时间: 2026-04-29*
|
package/package.json
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "itismyskillmarket",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Cross-platform skill manager for AI coding tools",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"files": [
|
|
7
|
-
"dist",
|
|
8
|
-
"src",
|
|
9
|
-
"README.md"
|
|
10
|
-
],
|
|
11
6
|
"bin": {
|
|
12
7
|
"skm": "dist/index.js"
|
|
13
8
|
},
|
package/skills/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# SkillMarket Skills
|
|
2
|
+
|
|
3
|
+
This directory contains the skill packages that can be published to npm.
|
|
4
|
+
|
|
5
|
+
## Adding a New Skill
|
|
6
|
+
|
|
7
|
+
1. Create a new directory under `skills/<skill-name>/`
|
|
8
|
+
2. Add the required files:
|
|
9
|
+
- `package.json` - Package configuration with `skillmarket` metadata
|
|
10
|
+
- `SKILL.md` - Skill documentation
|
|
11
|
+
- `metadata.json` - Skill metadata (optional)
|
|
12
|
+
- `index.js` - Main entry point (OpenCode plugin)
|
|
13
|
+
|
|
14
|
+
3. Publish via GitHub Actions or manually
|
|
15
|
+
|
|
16
|
+
## Publishing a Skill
|
|
17
|
+
|
|
18
|
+
### Option 1: GitHub Actions (Recommended)
|
|
19
|
+
1. Go to repository Actions tab
|
|
20
|
+
2. Select "Publish Skill" workflow
|
|
21
|
+
3. Click "Run workflow"
|
|
22
|
+
4. Enter skill name (e.g., `test-skill`)
|
|
23
|
+
5. Optionally specify version
|
|
24
|
+
|
|
25
|
+
### Option 2: Manual Publish
|
|
26
|
+
```bash
|
|
27
|
+
cd skills/<skill-name>
|
|
28
|
+
npm install
|
|
29
|
+
npm publish --access=public
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Skill Package Requirements
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"name": "@itismyskillmarket/<skill-name>",
|
|
37
|
+
"version": "1.0.0",
|
|
38
|
+
"type": "module",
|
|
39
|
+
"main": "index.js",
|
|
40
|
+
"keywords": ["skillmarket"],
|
|
41
|
+
"skillmarket": {
|
|
42
|
+
"id": "<skill-name>",
|
|
43
|
+
"displayName": "Display Name",
|
|
44
|
+
"description": "Description",
|
|
45
|
+
"platforms": ["opencode", "cursor", "vscode", "claude", "codex", "antigravity"]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Current Skills
|
|
51
|
+
|
|
52
|
+
- `test-skill` - Test skill for validating the installation flow
|
|
53
|
+
- `test-skill-1` - Test skill for validating uninstall and update flows
|
|
54
|
+
- `test-skill-2` - Test skill for validating multi-platform installation
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Test Skill
|
|
2
|
+
|
|
3
|
+
这是一个用于测试 SkillMarket 安装流程的 skill。
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
- `test.greet` - 向用户打招呼
|
|
8
|
+
- `test.randomNumber` - 生成随机数
|
|
9
|
+
- `test.systemInfo` - 获取系统信息
|
|
10
|
+
|
|
11
|
+
## 使用方法
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
skm install test-skill
|
|
15
|
+
skm info test-skill
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 平台支持
|
|
19
|
+
|
|
20
|
+
- OpenCode
|
|
21
|
+
- Cursor
|
|
22
|
+
- VSCode
|
|
23
|
+
- Claude Code
|
|
24
|
+
- Codex
|
|
25
|
+
- Antigravity
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test Skill - SkillMarket 测试技能
|
|
3
|
+
*
|
|
4
|
+
* 这是一个用于验证 SkillMarket 安装流程的示例 skill
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { tool } from "@opencode-ai/plugin";
|
|
8
|
+
|
|
9
|
+
export default async function TestSkill() {
|
|
10
|
+
console.log("✅ Test Skill 加载成功!");
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
tool: {
|
|
14
|
+
// 1. 简单的问候工具
|
|
15
|
+
greet: tool({
|
|
16
|
+
description: "向用户打招呼",
|
|
17
|
+
args: {
|
|
18
|
+
name: tool.schema.string().describe("你的名字")
|
|
19
|
+
},
|
|
20
|
+
async execute({ name }, context) {
|
|
21
|
+
const { agent, sessionID } = context;
|
|
22
|
+
return `你好 ${name}!我是 ${agent} 代理,欢迎使用测试插件!会话ID: ${sessionID}`;
|
|
23
|
+
}
|
|
24
|
+
}),
|
|
25
|
+
|
|
26
|
+
// 2. 随机数生成工具
|
|
27
|
+
randomNumber: tool({
|
|
28
|
+
description: "生成指定范围的随机数",
|
|
29
|
+
args: {
|
|
30
|
+
min: tool.schema.number().describe("最小值").default(1),
|
|
31
|
+
max: tool.schema.number().describe("最大值").default(100)
|
|
32
|
+
},
|
|
33
|
+
async execute({ min, max }, context) {
|
|
34
|
+
const randomNum = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
35
|
+
return `随机数(${min}-${max}): ${randomNum}`;
|
|
36
|
+
}
|
|
37
|
+
}),
|
|
38
|
+
|
|
39
|
+
// 3. 系统信息工具
|
|
40
|
+
systemInfo: tool({
|
|
41
|
+
description: "获取系统信息",
|
|
42
|
+
args: {},
|
|
43
|
+
async execute(args, context) {
|
|
44
|
+
const { sessionID, agent } = context;
|
|
45
|
+
const info = {
|
|
46
|
+
agent: agent,
|
|
47
|
+
sessionID: sessionID,
|
|
48
|
+
timestamp: new Date().toISOString(),
|
|
49
|
+
platform: process.platform,
|
|
50
|
+
nodeVersion: process.version
|
|
51
|
+
};
|
|
52
|
+
return JSON.stringify(info, null, 2);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// 钩子示例
|
|
58
|
+
"tool.execute.before": async (input, output) => {
|
|
59
|
+
console.log(`🛠️ 工具即将执行: ${input.tool}`);
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
"tool.execute.after": async (input, output) => {
|
|
63
|
+
console.log(`✅ 工具执行完成: ${input.tool}`);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@itismyskillmarket/test-skill",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "SkillMarket 测试技能 - 用于验证安装流程",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"keywords": ["skillmarket", "test"],
|
|
8
|
+
"author": "SkillMarket",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@opencode-ai/plugin": "^1.1.31"
|
|
12
|
+
},
|
|
13
|
+
"skillmarket": {
|
|
14
|
+
"id": "test-skill",
|
|
15
|
+
"displayName": "测试技能",
|
|
16
|
+
"description": "这是一个用于测试 SkillMarket 安装流程的 skill",
|
|
17
|
+
"platforms": ["opencode", "cursor", "vscode", "claude", "codex", "antigravity"]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Test Skill 1
|
|
2
|
+
|
|
3
|
+
用于测试 SkillMarket 安装和 info 功能的 skill。
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
- 验证 skm install 功能
|
|
8
|
+
- 验证 skm info 功能
|
|
9
|
+
|
|
10
|
+
## 使用方法
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
skm install test-skill-1
|
|
14
|
+
skm info test-skill-1
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 平台支持
|
|
18
|
+
|
|
19
|
+
- OpenCode
|
|
20
|
+
- Cursor
|
|
21
|
+
- VSCode
|
|
22
|
+
- Claude Code
|
|
23
|
+
- Codex
|
|
24
|
+
- Antigravity
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "test-skill-1",
|
|
3
|
+
"displayName": "测试技能1",
|
|
4
|
+
"description": "用于测试 SkillMarket 安装和 info 功能",
|
|
5
|
+
"version": "1.0.3",
|
|
6
|
+
"author": "SkillMarket",
|
|
7
|
+
"platforms": ["opencode", "cursor", "vscode", "claude", "codex", "antigravity"],
|
|
8
|
+
"tags": ["test", "install", "info"]
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wanxuchen/test-skill-1",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Test Skill 1 - 用于测试 SkillMarket 安装流程",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"keywords": ["skillmarket", "test"],
|
|
8
|
+
"author": "SkillMarket",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"skillmarket": {
|
|
11
|
+
"id": "test-skill-1",
|
|
12
|
+
"displayName": "测试技能1",
|
|
13
|
+
"description": "用于测试 SkillMarket 安装和 info 功能",
|
|
14
|
+
"platforms": ["opencode", "cursor", "vscode", "claude", "codex", "antigravity"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Test Skill 2
|
|
2
|
+
|
|
3
|
+
用于测试 SkillMarket 卸载和更新流程的 skill。
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
- 验证 skm uninstall 功能
|
|
8
|
+
- 验证 skm update 功能
|
|
9
|
+
|
|
10
|
+
## 使用方法
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
skm install test-skill-2
|
|
14
|
+
skm update test-skill-2
|
|
15
|
+
skm uninstall test-skill-2
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 平台支持
|
|
19
|
+
|
|
20
|
+
- OpenCode
|
|
21
|
+
- Cursor
|
|
22
|
+
- VSCode
|
|
23
|
+
- Claude Code
|
|
24
|
+
- Codex
|
|
25
|
+
- Antigravity
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "test-skill-2",
|
|
3
|
+
"displayName": "测试技能2",
|
|
4
|
+
"description": "用于测试 SkillMarket 卸载和更新功能",
|
|
5
|
+
"version": "1.0.3",
|
|
6
|
+
"author": "SkillMarket",
|
|
7
|
+
"platforms": ["opencode", "cursor", "vscode", "claude", "codex", "antigravity"],
|
|
8
|
+
"tags": ["test", "uninstall", "update"]
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wanxuchen/test-skill-2",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Test Skill 2 - 用于测试 SkillMarket 卸载和更新流程",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"keywords": ["skillmarket", "test"],
|
|
8
|
+
"author": "SkillMarket",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"skillmarket": {
|
|
11
|
+
"id": "test-skill-2",
|
|
12
|
+
"displayName": "测试技能2",
|
|
13
|
+
"description": "用于测试 SkillMarket 卸载和更新功能",
|
|
14
|
+
"platforms": ["opencode", "cursor", "vscode", "claude", "codex", "antigravity"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* =============================================================================
|
|
3
|
+
* Base Platform Adapter
|
|
4
|
+
* =============================================================================
|
|
5
|
+
*
|
|
6
|
+
* Abstract base class for platform-specific skill adapters.
|
|
7
|
+
* Provides common functionality for all platforms.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import fs from 'fs-extra';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import type { PlatformAdapter } from '../types.js';
|
|
13
|
+
|
|
14
|
+
export abstract class BaseAdapter implements PlatformAdapter {
|
|
15
|
+
abstract readonly id: string;
|
|
16
|
+
abstract readonly name: string;
|
|
17
|
+
abstract readonly skillDir: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get the path where a specific skill should be installed
|
|
21
|
+
*/
|
|
22
|
+
protected getSkillPath(skillId: string): string {
|
|
23
|
+
return path.join(this.skillDir, skillId);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get the path to the SKILL.md file for a skill
|
|
28
|
+
*/
|
|
29
|
+
protected getSkillFilePath(skillId: string): string {
|
|
30
|
+
return path.join(this.getSkillPath(skillId), 'SKILL.md');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async isAvailable(): Promise<boolean> {
|
|
34
|
+
try {
|
|
35
|
+
await fs.ensureDir(this.skillDir);
|
|
36
|
+
return true;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async isInstalled(skillId: string): Promise<boolean> {
|
|
43
|
+
const skillFile = this.getSkillFilePath(skillId);
|
|
44
|
+
return fs.pathExists(skillFile);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async install(skillId: string, sourceDir: string): Promise<void> {
|
|
48
|
+
const targetDir = this.getSkillPath(skillId);
|
|
49
|
+
const targetFile = this.getSkillFilePath(skillId);
|
|
50
|
+
|
|
51
|
+
await fs.ensureDir(targetDir);
|
|
52
|
+
|
|
53
|
+
const sourceFile = path.join(sourceDir, 'SKILL.md');
|
|
54
|
+
if (!(await fs.pathExists(sourceFile))) {
|
|
55
|
+
throw new Error(`SKILL.md not found in ${sourceDir}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await fs.copy(sourceFile, targetFile, { overwrite: true });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async uninstall(skillId: string): Promise<void> {
|
|
62
|
+
const targetDir = this.getSkillPath(skillId);
|
|
63
|
+
if (await fs.pathExists(targetDir)) {
|
|
64
|
+
await fs.remove(targetDir);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async listInstalled(): Promise<string[]> {
|
|
69
|
+
if (!(await fs.pathExists(this.skillDir))) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const entries = await fs.readdir(this.skillDir, { withFileTypes: true });
|
|
74
|
+
const skills: string[] = [];
|
|
75
|
+
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
if (entry.isDirectory()) {
|
|
78
|
+
const skillFile = path.join(this.skillDir, entry.name, 'SKILL.md');
|
|
79
|
+
if (await fs.pathExists(skillFile)) {
|
|
80
|
+
skills.push(entry.name);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return skills;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* =============================================================================
|
|
3
|
+
* Claude Code Platform Adapter
|
|
4
|
+
* =============================================================================
|
|
5
|
+
*
|
|
6
|
+
* Handles skill installation for Claude Code CLI.
|
|
7
|
+
* Skills are installed to ~/.claude/skills/<skill-id>/
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
import fs from 'fs-extra';
|
|
13
|
+
import { BaseAdapter } from './base.js';
|
|
14
|
+
|
|
15
|
+
export class ClaudeAdapter extends BaseAdapter {
|
|
16
|
+
readonly id = 'claude';
|
|
17
|
+
readonly name = 'Claude Code';
|
|
18
|
+
|
|
19
|
+
get skillDir(): string {
|
|
20
|
+
return path.join(os.homedir(), '.claude', 'skills');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async isAvailable(): Promise<boolean> {
|
|
24
|
+
// Check for environment variable or directory
|
|
25
|
+
if (process.env.CLAUDE_CODE) return true;
|
|
26
|
+
|
|
27
|
+
// Check if .claude directory exists
|
|
28
|
+
const claudeDir = path.join(os.homedir(), '.claude');
|
|
29
|
+
return fs.pathExists(claudeDir);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform adapters index
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { BaseAdapter } from './base.js';
|
|
6
|
+
export { OpenCodeAdapter } from './opencode.js';
|
|
7
|
+
export { ClaudeAdapter } from './claude.js';
|
|
8
|
+
export { VSCodeAdapter } from './vscode.js';
|
|
9
|
+
export { detectPlatforms, getPlatformAdapter, getAllAdapters, getAdapterByPlatform } from './registry.js';
|