@michengai/dsh-skills-manager 1.1.18 → 1.1.21
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/CHANGELOG.md +17 -0
- package/CHANGELOG.zh-CN.md +17 -0
- package/README.md +29 -25
- package/README.zh-CN.md +28 -24
- package/assets/brands/agents.svg +1 -0
- package/assets/brands/cc-switch.png +0 -0
- package/assets/brands/claude.svg +1 -0
- package/assets/brands/codebuddy.svg +1 -0
- package/assets/brands/codex.svg +1 -0
- package/assets/brands/copilot.svg +1 -0
- package/assets/brands/cursor.svg +7 -0
- package/assets/brands/dsh.png +0 -0
- package/assets/brands/gemini.svg +1 -0
- package/assets/brands/openclaw.svg +1 -0
- package/assets/brands/opencode.svg +1 -0
- package/assets/brands/qoder.svg +1 -0
- package/assets/brands/roo.svg +1 -0
- package/assets/brands/trae.svg +1 -0
- package/assets/brands/windsurf.svg +1 -0
- package/assets/brands/workbuddy.png +0 -0
- package/assets/screenshots/project-skills.webp +0 -0
- package/assets/screenshots/skill-repositories.webp +0 -0
- package/assets/screenshots/skills-manager-v2-preview.webp +0 -0
- package/lib/catalog-skill.js +142 -0
- package/lib/clawhub-catalog.js +134 -0
- package/lib/client.js +97 -83
- package/lib/core.js +140 -37
- package/lib/index.js +51 -15
- package/lib/repositories.js +370 -57
- package/lib/repository-updates.js +8 -2
- package/lib/skills-sh-catalog.js +92 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.21 - 2026-10-15
|
|
4
|
+
|
|
5
|
+
- Support DSH `0.2.1-alpha.3` while retaining all existing supported versions.
|
|
6
|
+
- Allow ordinary user-level Shared Agent skills to be managed, trashed and restored without installation records, preserving discovery, loading and path safety while keeping other agent sources read-only.
|
|
7
|
+
- Add real ClawHub / skills.sh search and individual skill installation, with ten-item download-ranking pages and an explicit load-more button.
|
|
8
|
+
- Fix concurrent repository operations overwriting catalog state, lost workspace installation badges, and interference between same-name copies; preserve source identity through trash and restore.
|
|
9
|
+
- Allow installation beyond 500 source records without discarding active copies or recoverable trash identities; retain the state file's byte-size limit.
|
|
10
|
+
- Keep failed recovery from blocking listings and unrelated operations, preserve pending state with actionable warnings, and mark legacy identities with unknown locations rather than guessing directories.
|
|
11
|
+
- Improve oversized-response diagnostics, stream cleanup, and cancellation on navigation or unmount; remove unused skill-array expansion.
|
|
12
|
+
- Support explicit indentation indicators in YAML block scalars.
|
|
13
|
+
- Source tracking above 16 MiB can still be reduced by removing Trash records or legacy identities, without deleting active installation copies. Further growth is rejected.
|
|
14
|
+
- Permanent deletion removes Trash files only after source tracking is saved. A catalog skill with a known installation location no longer also shows an unknown-location badge.
|
|
15
|
+
|
|
16
|
+
## 1.1.19 - 2026-10-14
|
|
17
|
+
|
|
18
|
+
- Adjust settings navigation section order to ensure stable placement and avoid conflicts with other plugins.
|
|
19
|
+
|
|
3
20
|
## 1.1.18 - 2026-10-13
|
|
4
21
|
|
|
5
22
|
- Visual and brand enhancements: integrate official brand logos for ecosystem sources (DSH, WorkBuddy, CC Switch, Codex, Qoder, Cursor, Claude Code, etc.), remove redundant collapse arrows on source cards, and preserve full paths.
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
[English](CHANGELOG.md)
|
|
4
4
|
|
|
5
|
+
## 1.1.21 - 2026-10-15
|
|
6
|
+
|
|
7
|
+
- 支持 DSH `0.2.1-alpha.3`,继续兼容既有已支持版本。
|
|
8
|
+
- 用户级公共 Agent(Shared Agent)统一开放普通技能管理,无安装记录的技能也可回收和恢复;保留原有发现、加载与路径安全保护,其他 Agent 来源仍只读。
|
|
9
|
+
- 发现页接入 ClawHub / skills.sh 的真实搜索与单技能安装,下载榜按每页 10 条加载,并提供可点击的继续加载按钮。
|
|
10
|
+
- 修复并发仓库操作覆盖目录安装状态、项目安装徽章丢失及同名不同位置副本相互影响;移入回收站与恢复保留对应来源身份。
|
|
11
|
+
- 修复累计 500 条来源记录后无法继续安装的问题,保留有效副本与回收身份,继续按文件实际容量限制状态大小。
|
|
12
|
+
- 安装恢复失败不再阻断列表和无关操作,保留文件及待确认状态并提示原因;旧来源记录显示位置未知,不自动猜测安装目录。
|
|
13
|
+
- 完善目录响应超限诊断、流关闭、页面切换和卸载取消;移除无用的技能数组展开。
|
|
14
|
+
- 支持 YAML 块标量的显式缩进指示符。
|
|
15
|
+
- 安装来源状态超过 16 MiB 后仍可清理回收记录和旧身份,清理不会删除仍有效的安装副本;继续新增会被拒绝。
|
|
16
|
+
- 永久删除在来源状态写入成功后才删除回收站文件。已有安装位置的目录技能不再同时显示“位置未知”。
|
|
17
|
+
|
|
18
|
+
## 1.1.19 - 2026-10-14
|
|
19
|
+
|
|
20
|
+
- 调整技能管理在设置中的导航排序序号,避免与其他插件同级竞争导致菜单位置跳动。
|
|
21
|
+
|
|
5
22
|
## 1.1.18 - 2026-10-13
|
|
6
23
|
|
|
7
24
|
- 交互与视觉优化:为各生态来源(DSH、WorkBuddy、CC Switch、Codex、Qoder、Cursor、Claude Code 等)接入官方原版 Brand Logo,来源卡片去除冗余展开小箭头并保留完整路径。
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
[](https://www.npmjs.com/package/@michengai/dsh-skills-manager)
|
|
15
15
|
[](https://www.npmjs.com/package/@michengai/dsh-skills-manager)
|
|
16
16
|
[](https://github.com/MichengAI/dsh-skills-manager)
|
|
17
|
-
[](#installation)
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
20
|
> DSH Skills Manager is a community-maintained DeepSeek Harness (DSH) plugin, not an official DeepSeek AI product.
|
|
@@ -37,15 +37,19 @@ Bring skills from your computer and projects into DSH without switching between
|
|
|
37
37
|
|
|
38
38
|
## Screenshots
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
Global skills:
|
|
41
41
|
|
|
42
|
-

|
|
43
|
+
|
|
44
|
+
Project skills:
|
|
45
|
+
|
|
46
|
+

|
|
43
47
|
|
|
44
48
|
Skill repositories:
|
|
45
49
|
|
|
46
50
|

|
|
47
51
|
|
|
48
|
-
*Screenshots show the
|
|
52
|
+
*Screenshots show the 1.1.18 release featuring global skills, project skills, and skill repositories. Screenshots show only the core feature panels, with background whitespace and unneeded window chrome cropped out, and use lossless WebP.*
|
|
49
53
|
|
|
50
54
|
## Installation
|
|
51
55
|
|
|
@@ -71,7 +75,7 @@ dsh plugin --profile web add @michengai/dsh-skills-manager@latest --registry=htt
|
|
|
71
75
|
|
|
72
76
|
Restart DSH, refresh the page, and open **Settings → Skills**. To update, select **Check for updates** or run the installation command again.
|
|
73
77
|
|
|
74
|
-
- Plugin `1.1.
|
|
78
|
+
- Plugin `1.1.21` is tested with DeepSeek Harness `0.1.2-rc.1`, `0.1.5-rc.1`, `0.1.5-rc.2`, `0.1.5-rc.3`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, `0.2.0-rc.2`, `0.2.1-alpha.2`, `0.2.1-alpha.3`.
|
|
75
79
|
|
|
76
80
|
## Usage
|
|
77
81
|
|
|
@@ -89,7 +93,7 @@ Restart DSH, refresh the page, and open **Settings → Skills**. To update, sele
|
|
|
89
93
|
|
|
90
94
|
- **Registered workspaces**: select a registered workspace from the project tab dropdown. Only that workspace is scanned, displayed and searched. Git repositories use the nearest Git root; other folders use the workspace directory, so no `git init` is required. Empty workspaces remain selectable; unavailable directories are disabled.
|
|
91
95
|
- **Independent copies**: disabling a project copy allows another enabled copy to take over, and the panel identifies the active source. Disable all copies to turn the skill off completely.
|
|
92
|
-
- **File management**: DSH skills can move to Trash from the general manager. Repository-installed copies in DSH, Shared Agent, or a registered workspace can also be uninstalled from **Repositories**. Codex, Claude and other external skills remain read-only. Creation, file import and repository install can write to DSH skills or Shared Agent in your user directory, or to a registered workspace's `.dsh/skills`. Creation, import and installation never preselect a workspace, and Shared Agent is not available for workspaces. The project tab viewing selection is not a write destination.
|
|
96
|
+
- **File management**: User-level DSH and Shared Agent skills can move to Trash and be restored from the general manager without installation records. Project Shared Agent remains read-only. Shared Agent keeps recursive discovery and link reading; linked entries and unsafe paths are not writable. Repository-installed copies in DSH, Shared Agent, or a registered workspace can also be uninstalled from **Repositories**. Codex, Claude and other external skills remain read-only. Creation, file import and repository install can write to DSH skills or Shared Agent in your user directory, or to a registered workspace's `.dsh/skills`. Creation, import and installation never preselect a workspace, and Shared Agent is not available for workspaces. The project tab viewing selection is not a write destination.
|
|
93
97
|
- **Restore**: retired repository provenance belongs to the specific Trash entry and is reactivated only by an explicit restore, including the destination and update/rollback history. A different same-name skill does not inherit repository management. Uninstalling a Shared Agent copy affects every agent using that directory.
|
|
94
98
|
|
|
95
99
|
### Repository boundaries
|
|
@@ -105,25 +109,25 @@ Restart DSH, refresh the page, and open **Settings → Skills**. To update, sele
|
|
|
105
109
|
|
|
106
110
|
| Source | Global directory | Project directory |
|
|
107
111
|
| --- | --- | --- |
|
|
108
|
-
| DSH | `~/.dsh/skills` | `<project>/.dsh/skills` |
|
|
109
|
-
| Shared Agent | `~/.agents/skills` | `<project>/.agents/skills` |
|
|
110
|
-
| CC Switch | `~/.cc-switch/skills` | — |
|
|
111
|
-
| Codex | `~/.codex/skills` | `<project>/.codex/skills` |
|
|
112
|
-
| Claude Code | `~/.claude/skills` | `<project>/.claude/skills` |
|
|
113
|
-
| Gemini | `~/.gemini/skills` | `<project>/.gemini/skills` |
|
|
114
|
-
| OpenCode | `~/.config/opencode/skills` | `<project>/.opencode/skills` |
|
|
115
|
-
| Cursor | `~/.cursor/skills` | `<project>/.cursor/skills` |
|
|
116
|
-
| Copilot | `~/.copilot/skills` | `<project>/.github/skills` |
|
|
117
|
-
| Windsurf | `~/.codeium/windsurf/skills`<br>`~/.windsurf/skills` | `<project>/.windsurf/skills` |
|
|
118
|
-
| Trae | `~/.trae/skills` | `<project>/.trae/skills` |
|
|
119
|
-
| Trae CN | `~/.trae-cn/skills` | `<project>/.trae-cn/skills` |
|
|
120
|
-
| OpenClaw / Clawdbot | `~/.openclaw/skills`<br>`~/.clawdbot/skills` | — |
|
|
121
|
-
| Roo | `~/.roo/skills` | `<project>/.roo/skills` |
|
|
122
|
-
| CodeBuddy | `~/.codebuddy/skills` | `<project>/.codebuddy/skills` |
|
|
123
|
-
| WorkBuddy | `~/.workbuddy/skills` | `<project>/.workbuddy/skills` |
|
|
124
|
-
| Qoder | `~/.qoder/skills` | `<project>/.qoder/skills` |
|
|
125
|
-
| Qoder CN CLI | `~/.qoder-cn/skills` | — |
|
|
126
|
-
| Qoder CN | `~/.lingma/skills` | `<project>/.lingma/skills` |
|
|
112
|
+
| <img src="assets/brands/dsh.png" width="16" height="16" alt="DSH" valign="middle"> DSH | `~/.dsh/skills` | `<project>/.dsh/skills` |
|
|
113
|
+
| <img src="assets/brands/agents.svg" width="16" height="16" alt="Shared Agent" valign="middle"> Shared Agent | `~/.agents/skills` | `<project>/.agents/skills` |
|
|
114
|
+
| <img src="assets/brands/cc-switch.png" width="16" height="16" alt="CC Switch" valign="middle"> CC Switch | `~/.cc-switch/skills` | — |
|
|
115
|
+
| <img src="assets/brands/codex.svg" width="16" height="16" alt="Codex" valign="middle"> Codex | `~/.codex/skills` | `<project>/.codex/skills` |
|
|
116
|
+
| <img src="assets/brands/claude.svg" width="16" height="16" alt="Claude Code" valign="middle"> Claude Code | `~/.claude/skills` | `<project>/.claude/skills` |
|
|
117
|
+
| <img src="assets/brands/gemini.svg" width="16" height="16" alt="Gemini" valign="middle"> Gemini | `~/.gemini/skills` | `<project>/.gemini/skills` |
|
|
118
|
+
| <img src="assets/brands/opencode.svg" width="16" height="16" alt="OpenCode" valign="middle"> OpenCode | `~/.config/opencode/skills` | `<project>/.opencode/skills` |
|
|
119
|
+
| <img src="assets/brands/cursor.svg" width="16" height="16" alt="Cursor" valign="middle"> Cursor | `~/.cursor/skills` | `<project>/.cursor/skills` |
|
|
120
|
+
| <img src="assets/brands/copilot.svg" width="16" height="16" alt="Copilot" valign="middle"> Copilot | `~/.copilot/skills` | `<project>/.github/skills` |
|
|
121
|
+
| <img src="assets/brands/windsurf.svg" width="16" height="16" alt="Windsurf" valign="middle"> Windsurf | `~/.codeium/windsurf/skills`<br>`~/.windsurf/skills` | `<project>/.windsurf/skills` |
|
|
122
|
+
| <img src="assets/brands/trae.svg" width="16" height="16" alt="Trae" valign="middle"> Trae | `~/.trae/skills` | `<project>/.trae/skills` |
|
|
123
|
+
| <img src="assets/brands/trae.svg" width="16" height="16" alt="Trae CN" valign="middle"> Trae CN | `~/.trae-cn/skills` | `<project>/.trae-cn/skills` |
|
|
124
|
+
| <img src="assets/brands/openclaw.svg" width="16" height="16" alt="OpenClaw" valign="middle"> OpenClaw / Clawdbot | `~/.openclaw/skills`<br>`~/.clawdbot/skills` | — |
|
|
125
|
+
| <img src="assets/brands/roo.svg" width="16" height="16" alt="Roo" valign="middle"> Roo | `~/.roo/skills` | `<project>/.roo/skills` |
|
|
126
|
+
| <img src="assets/brands/codebuddy.svg" width="16" height="16" alt="CodeBuddy" valign="middle"> CodeBuddy | `~/.codebuddy/skills` | `<project>/.codebuddy/skills` |
|
|
127
|
+
| <img src="assets/brands/workbuddy.png" width="16" height="16" alt="WorkBuddy" valign="middle"> WorkBuddy | `~/.workbuddy/skills` | `<project>/.workbuddy/skills` |
|
|
128
|
+
| <img src="assets/brands/qoder.svg" width="16" height="16" alt="Qoder" valign="middle"> Qoder | `~/.qoder/skills` | `<project>/.qoder/skills` |
|
|
129
|
+
| <img src="assets/brands/qoder.svg" width="16" height="16" alt="Qoder CN CLI" valign="middle"> Qoder CN CLI | `~/.qoder-cn/skills` | — |
|
|
130
|
+
| <img src="assets/brands/qoder.svg" width="16" height="16" alt="Qoder CN" valign="middle"> Qoder CN | `~/.lingma/skills` | `<project>/.lingma/skills` |
|
|
127
131
|
|
|
128
132
|
Ordinary project-root `<project>/skills` directories are not scanned, so repository release resources are not exposed as Agent skills. OpenClaw / Clawdbot support is limited to the user-level sources above. Qoder CN CLI project skills use `<project>/.qoder/skills` and appear as Qoder. Qoder CN IDE uses the Lingma directories. Missing external source directories are not shown.
|
|
129
133
|
|
package/README.zh-CN.md
CHANGED
|
@@ -37,15 +37,19 @@
|
|
|
37
37
|
|
|
38
38
|
## 界面预览
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
全局技能:
|
|
41
41
|
|
|
42
|
-

|
|
43
|
+
|
|
44
|
+
项目技能:
|
|
45
|
+
|
|
46
|
+

|
|
43
47
|
|
|
44
48
|
技能仓库:
|
|
45
49
|
|
|
46
50
|

|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
*截图展示 1.1.18 版本的全局技能、项目技能与技能仓库。截图仅保留核心功能面板,已裁去背景中的多余留白与无关窗口,采用无损 WebP。*
|
|
49
53
|
|
|
50
54
|
## 安装
|
|
51
55
|
|
|
@@ -71,7 +75,7 @@ dsh plugin --profile web add @michengai/dsh-skills-manager@latest --registry=htt
|
|
|
71
75
|
|
|
72
76
|
安装后重启 DSH 并刷新页面,打开「设置 → 技能」即可使用。更新时可点击「检查更新」,或重新执行安装命令。
|
|
73
77
|
|
|
74
|
-
- `1.1.
|
|
78
|
+
- `1.1.21` 已验证兼容 DeepSeek Harness `0.1.2-rc.1`、`0.1.5-rc.1`、`0.1.5-rc.2`、`0.1.5-rc.3`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.2`、`0.2.1-alpha.3`。
|
|
75
79
|
|
|
76
80
|
## 使用说明
|
|
77
81
|
|
|
@@ -89,7 +93,7 @@ dsh plugin --profile web add @michengai/dsh-skills-manager@latest --registry=htt
|
|
|
89
93
|
|
|
90
94
|
- **按已登记工作区查看**:项目页顶部下拉列出 DSH 里已登记的工作区,选中后只读取并显示这一项的技能,搜索也只针对所选工作区。Git 仓库使用最近的 Git 根目录;普通文件夹使用工作区目录,无需 `git init`。没有技能的工作区也可选择,失效目录不可选。
|
|
91
95
|
- **同名技能独立启停**:停用项目副本后,其他已启用副本仍可接管,页面会提示实际来源。要完全关闭该技能,需停用全部副本。
|
|
92
|
-
-
|
|
96
|
+
- **文件管理范围**:用户级 DSH 和公共 Agent(Shared Agent)来源的普通技能均可从管理页移入回收站并恢复,不要求安装来源记录;项目 Shared Agent 仍只读。公共 Agent 保留递归发现和链接读取,链接条目及不安全路径不允许文件写入;从仓库安装到 DSH、公共 Agent 或已登记工作区的副本也可从「技能仓库」卸载。Codex、Claude 等其他外部技能仍只读。创建、文件导入和仓库安装可以写入用户目录下的 DSH skills 或公共 Agent(Shared Agent),也可以写入某个已登记工作区的 `.dsh/skills`。创建、导入和安装时,工作区不会被预先选中,也不能选 Shared Agent;项目页的只读查看选择不作为写入目标。
|
|
93
97
|
- **恢复**:已卸载副本的仓库来源绑定到具体回收站条目;仅显式恢复后重新启用来源、安装位置和更新/恢复历史。其他同名技能不会继承仓库管理权限。卸载公共 Agent 副本会影响使用该目录的所有 Agent。
|
|
94
98
|
|
|
95
99
|
### 仓库使用边界
|
|
@@ -105,25 +109,25 @@ dsh plugin --profile web add @michengai/dsh-skills-manager@latest --registry=htt
|
|
|
105
109
|
|
|
106
110
|
| 来源 | 全局目录 | 项目目录 |
|
|
107
111
|
| --- | --- | --- |
|
|
108
|
-
| DSH | `~/.dsh/skills` | `<project>/.dsh/skills` |
|
|
109
|
-
| 公共 Agent | `~/.agents/skills` | `<project>/.agents/skills` |
|
|
110
|
-
| CC Switch | `~/.cc-switch/skills` | — |
|
|
111
|
-
| Codex | `~/.codex/skills` | `<project>/.codex/skills` |
|
|
112
|
-
| Claude Code | `~/.claude/skills` | `<project>/.claude/skills` |
|
|
113
|
-
| Gemini | `~/.gemini/skills` | `<project>/.gemini/skills` |
|
|
114
|
-
| OpenCode | `~/.config/opencode/skills` | `<project>/.opencode/skills` |
|
|
115
|
-
| Cursor | `~/.cursor/skills` | `<project>/.cursor/skills` |
|
|
116
|
-
| Copilot | `~/.copilot/skills` | `<project>/.github/skills` |
|
|
117
|
-
| Windsurf | `~/.codeium/windsurf/skills`<br>`~/.windsurf/skills` | `<project>/.windsurf/skills` |
|
|
118
|
-
| Trae | `~/.trae/skills` | `<project>/.trae/skills` |
|
|
119
|
-
| Trae CN | `~/.trae-cn/skills` | `<project>/.trae-cn/skills` |
|
|
120
|
-
| OpenClaw / Clawdbot | `~/.openclaw/skills`<br>`~/.clawdbot/skills` | — |
|
|
121
|
-
| Roo | `~/.roo/skills` | `<project>/.roo/skills` |
|
|
122
|
-
| CodeBuddy | `~/.codebuddy/skills` | `<project>/.codebuddy/skills` |
|
|
123
|
-
| WorkBuddy | `~/.workbuddy/skills` | `<project>/.workbuddy/skills` |
|
|
124
|
-
| Qoder | `~/.qoder/skills` | `<project>/.qoder/skills` |
|
|
125
|
-
| Qoder CN CLI | `~/.qoder-cn/skills` | — |
|
|
126
|
-
| Qoder CN | `~/.lingma/skills` | `<project>/.lingma/skills` |
|
|
112
|
+
| <img src="assets/brands/dsh.png" width="16" height="16" alt="DSH" valign="middle"> DSH | `~/.dsh/skills` | `<project>/.dsh/skills` |
|
|
113
|
+
| <img src="assets/brands/agents.svg" width="16" height="16" alt="Shared Agent" valign="middle"> 公共 Agent | `~/.agents/skills` | `<project>/.agents/skills` |
|
|
114
|
+
| <img src="assets/brands/cc-switch.png" width="16" height="16" alt="CC Switch" valign="middle"> CC Switch | `~/.cc-switch/skills` | — |
|
|
115
|
+
| <img src="assets/brands/codex.svg" width="16" height="16" alt="Codex" valign="middle"> Codex | `~/.codex/skills` | `<project>/.codex/skills` |
|
|
116
|
+
| <img src="assets/brands/claude.svg" width="16" height="16" alt="Claude Code" valign="middle"> Claude Code | `~/.claude/skills` | `<project>/.claude/skills` |
|
|
117
|
+
| <img src="assets/brands/gemini.svg" width="16" height="16" alt="Gemini" valign="middle"> Gemini | `~/.gemini/skills` | `<project>/.gemini/skills` |
|
|
118
|
+
| <img src="assets/brands/opencode.svg" width="16" height="16" alt="OpenCode" valign="middle"> OpenCode | `~/.config/opencode/skills` | `<project>/.opencode/skills` |
|
|
119
|
+
| <img src="assets/brands/cursor.svg" width="16" height="16" alt="Cursor" valign="middle"> Cursor | `~/.cursor/skills` | `<project>/.cursor/skills` |
|
|
120
|
+
| <img src="assets/brands/copilot.svg" width="16" height="16" alt="Copilot" valign="middle"> Copilot | `~/.copilot/skills` | `<project>/.github/skills` |
|
|
121
|
+
| <img src="assets/brands/windsurf.svg" width="16" height="16" alt="Windsurf" valign="middle"> Windsurf | `~/.codeium/windsurf/skills`<br>`~/.windsurf/skills` | `<project>/.windsurf/skills` |
|
|
122
|
+
| <img src="assets/brands/trae.svg" width="16" height="16" alt="Trae" valign="middle"> Trae | `~/.trae/skills` | `<project>/.trae/skills` |
|
|
123
|
+
| <img src="assets/brands/trae.svg" width="16" height="16" alt="Trae CN" valign="middle"> Trae CN | `~/.trae-cn/skills` | `<project>/.trae-cn/skills` |
|
|
124
|
+
| <img src="assets/brands/openclaw.svg" width="16" height="16" alt="OpenClaw" valign="middle"> OpenClaw / Clawdbot | `~/.openclaw/skills`<br>`~/.clawdbot/skills` | — |
|
|
125
|
+
| <img src="assets/brands/roo.svg" width="16" height="16" alt="Roo" valign="middle"> Roo | `~/.roo/skills` | `<project>/.roo/skills` |
|
|
126
|
+
| <img src="assets/brands/codebuddy.svg" width="16" height="16" alt="CodeBuddy" valign="middle"> CodeBuddy | `~/.codebuddy/skills` | `<project>/.codebuddy/skills` |
|
|
127
|
+
| <img src="assets/brands/workbuddy.png" width="16" height="16" alt="WorkBuddy" valign="middle"> WorkBuddy | `~/.workbuddy/skills` | `<project>/.workbuddy/skills` |
|
|
128
|
+
| <img src="assets/brands/qoder.svg" width="16" height="16" alt="Qoder" valign="middle"> Qoder | `~/.qoder/skills` | `<project>/.qoder/skills` |
|
|
129
|
+
| <img src="assets/brands/qoder.svg" width="16" height="16" alt="Qoder CN CLI" valign="middle"> Qoder CN CLI | `~/.qoder-cn/skills` | — |
|
|
130
|
+
| <img src="assets/brands/qoder.svg" width="16" height="16" alt="Qoder CN" valign="middle"> Qoder CN | `~/.lingma/skills` | `<project>/.lingma/skills` |
|
|
127
131
|
|
|
128
132
|
不扫描普通项目根目录的 `<project>/skills`,避免把仓库的发布资源当作 Agent 技能。OpenClaw / Clawdbot 仅保留上表中的用户级来源。Qoder CN CLI 的项目技能在 `<project>/.qoder/skills`,显示为 Qoder。Qoder CN IDE 使用 Lingma 目录。不存在的外部来源目录不会显示。
|
|
129
133
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#10b981" d="M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h2a5 5 0 0 1 5 5v1a3 3 0 0 1 1 2.23V17a3 3 0 0 1-3 3h-1.1A6 6 0 0 1 12 22a6 6 0 0 1-4.9-2H6a3 3 0 0 1-3-3v-1.77A3 3 0 0 1 4 13v-1a5 5 0 0 1 5-5h2V5.73A2 2 0 0 1 10 4a2 2 0 0 1 2-2zm-3 10a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm6 0a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm-6 5a4 4 0 0 0 6 0H9z"/></svg>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#D97757" fill-rule="evenodd" clip-rule="evenodd" d="M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect width="24" height="24" rx="5" fill="#2EA99D"/><path fill="#ffffff" d="M18.777 1.647c.28-.02.536.114.972.51 1.018.926 2.437 2.828 3.318 4.452l.34.631.482.24.11.06v3.638a5.206 5.206 0 00-5.32-1.23c-.491.166-1.021.471-2.08 1.082l-6.09 3.516c-1.057.61-1.586.916-1.975 1.259a5.208 5.208 0 00-1.493 5.572c.165.49.471 1.02 1.082 2.08l.315.543h-3.26c-.685 0-1.34-.135-1.939-.377-.169-.956-.009-1.789.469-2.335.158-.18.164-.189.13-.493a11.846 11.846 0 01-.057-1.711l.02-.444-.667-1.18C2.1 15.622 1.445 14.078 1.192 12.9c-.133-.647-.125-.934.04-1.146.1-.128.427-.261.822-.334.994-.175 3.162-.017 5.575.41l.25.043.551-.487c.915-.81 1.522-1.264 2.641-1.962 1.167-.73 2.484-1.331 3.967-1.807l.476-.152.261-.688c.937-2.471 1.896-4.293 2.58-4.9.235-.21.25-.22.422-.23z"/><path fill="#ffffff" d="M12.139 18.2a1.203 1.203 0 011.642.44l1.296 2.243a1.204 1.204 0 01-2.083 1.203l-1.296-2.243a1.203 1.203 0 01.44-1.644zM18.629 14.452a1.203 1.203 0 011.642.44l1.295 2.244a1.203 1.203 0 11-2.083 1.203l-1.295-2.243a1.203 1.203 0 01.44-1.644z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#10a37f" d="M6.13671 5.82399V4.30398C6.13671 4.17596 6.18431 4.07991 6.29527 4.01598L9.32406 2.256C9.73637 2.01602 10.228 1.90406 10.7353 1.90406C12.6382 1.90406 13.8434 3.3921 13.8434 4.97604C13.8434 5.088 13.8434 5.21602 13.8274 5.34404L10.6877 3.488C10.4975 3.37605 10.3071 3.37605 10.1168 3.488L6.13671 5.82399ZM13.209 11.7441V8.11195C13.209 7.88789 13.1138 7.72791 12.9236 7.61594L8.94344 5.27995L10.2437 4.5279C10.3547 4.46397 10.4499 4.46397 10.5609 4.5279L13.5896 6.28789C14.4619 6.79996 15.0484 7.88789 15.0484 8.94385C15.0484 10.1598 14.335 11.28 13.209 11.7441ZM5.20114 8.54404L3.90086 7.77608C3.78989 7.71215 3.7423 7.6161 3.7423 7.48808V3.96811C3.7423 2.25615 5.04259 0.960061 6.80278 0.960061C7.46883 0.960061 8.08714 1.18413 8.61056 1.58409L5.48672 3.40816C5.29649 3.52012 5.20129 3.68011 5.20129 3.90418L5.20114 8.54404ZM7.99999 10.176L6.13671 9.12005V6.8801L7.99999 5.82414L9.8631 6.8801V9.12005L7.99999 10.176ZM9.19719 15.0401C8.53113 15.0401 7.91282 14.816 7.3894 14.4161L10.5132 12.5919C10.7034 12.48 10.7987 12.3201 10.7987 12.096V7.45596L12.1149 8.22392C12.2258 8.28785 12.2734 8.3839 12.2734 8.51192V12.0319C12.2734 13.7438 10.9572 15.0401 9.19719 15.0401ZM5.43898 11.4721L2.41018 9.71211C1.53796 9.20003 0.95134 8.11211 0.95134 7.05615C0.95134 5.82414 1.68077 4.72016 2.80657 4.25611V7.9041C2.80657 8.12817 2.90177 8.28815 3.092 8.40012L7.05637 10.72L5.75609 11.4721C5.64513 11.5361 5.54993 11.5361 5.43898 11.4721ZM5.26465 14.0961C3.47278 14.0961 2.15658 12.736 2.15658 11.056C2.15658 10.928 2.17249 10.8 2.18826 10.672L5.3121 12.4961C5.50234 12.608 5.69273 12.608 5.88297 12.4961L9.8631 10.1762V11.6962C9.8631 11.8242 9.8155 11.9202 9.70454 11.9841L6.67574 13.7441C6.26344 13.9841 5.77199 14.0961 5.26465 14.0961ZM9.19719 16C11.1159 16 12.7174 14.624 13.0823 12.8C14.8582 12.3359 16 10.6559 16 8.944C16 7.82396 15.5243 6.73603 14.668 5.95201C14.7473 5.61598 14.7949 5.27995 14.7949 4.94407C14.7949 2.65612 12.9554 0.944002 10.8305 0.944002C10.4025 0.944002 9.99013 1.00794 9.57782 1.15201C8.86416 0.447988 7.88099 0 6.80278 0C4.88403 0 3.28254 1.37593 2.91768 3.19999C1.14173 3.66404 0 5.34404 0 7.056C0 8.17604 0.475669 9.26397 1.33197 10.048C1.25269 10.384 1.20509 10.72 1.20509 11.0559C1.20509 13.3438 3.04456 15.0559 5.16946 15.0559C5.59753 15.0559 6.00984 14.9921 6.42215 14.848C7.13565 15.552 8.11882 16 9.19719 16Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#007acc" d="M12 2a8 8 0 0 0-8 8v4a4 4 0 0 0 4 4h1v2a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-2h1a4 4 0 0 0 4-4v-4a8 8 0 0 0-8-8zm-3 8a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm6 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/></svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
2
|
+
<style>
|
|
3
|
+
path { fill: #1e1e20; }
|
|
4
|
+
@media (prefers-color-scheme: dark) { path { fill: #f5f5f5; } }
|
|
5
|
+
</style>
|
|
6
|
+
<path fill-rule="evenodd" d="M22.106 5.68L12.5.135a.998.998 0 00-.998 0L1.893 5.68a.84.84 0 00-.419.726v11.186c0 .3.16.577.42.727l9.607 5.547a.999.999 0 00.998 0l9.608-5.547a.84.84 0 00.42-.727V6.407a.84.84 0 00-.42-.726zm-.603 1.176L12.228 22.92c-.063.108-.228.064-.228-.061V12.34a.59.59 0 00-.295-.51l-9.11-5.26c-.107-.062-.063-.228.062-.228h18.55c.264 0 .428.286.296.514z"/>
|
|
7
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#3b82f6" d="M12 2C12 7.5 7.5 12 2 12c5.5 0 10 4.5 10 10 0-5.5 4.5-10 10-10-5.5 0-10-4.5-10-10z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#FF4D4D" fill-rule="evenodd" d="M16.877 1.912c.58-.27 1.14-.323 1.616-.037a.317.317 0 01-.326.542c-.227-.136-.547-.153-1.022.068-.352.165-.765.45-1.234.866 2.683 1.17 4.4 3.5 5.148 5.921a6.421 6.421 0 00-.704.184c-.578.016-1.174.204-1.502.735-.338.55-.268 1.276.072 2.069l.005.012.007.014c.523 1.045 1.318 1.91 2.2 2.284-.912 3.274-3.44 6.144-5.972 6.988v2.109h-2.11v-2.11c-1.043.417-2.086.01-2.11 0v2.11h-2.11v-2.11c-2.531-.843-5.061-3.713-5.973-6.987.882-.373 1.678-1.238 2.2-2.284l.007-.014.006-.012c.34-.793.41-1.518.071-2.069-.327-.531-.923-.719-1.503-.735a6.409 6.409 0 00-.704-.183c.749-2.421 2.466-4.751 5.149-5.922-.47-.416-.88-.701-1.234-.866-.474-.221-.794-.204-1.021-.068a.318.318 0 01-.435-.109.317.317 0 01.109-.433c.476-.286 1.036-.233 1.615.037.49.229 1.031.628 1.621 1.182A9.924 9.924 0 0112 2.568c1.199 0 2.284.19 3.256.526.59-.554 1.13-.953 1.62-1.182zM8.835 6.577a1.266 1.266 0 100 2.532 1.266 1.266 0 000-2.532zm6.33 0a1.267 1.267 0 100 2.533 1.267 1.267 0 000-2.533z"/><path fill="#FF4D4D" d="M.395 13.118c-.966-1.932-.163-3.863 2.41-3.365v-.001l.05.01c.084.018.17.038.26.06.033.009.067.017.1.027.084.022.168.048.255.076l.09.027c.528 0 .95.158 1.16.501.212.343.212.87-.105 1.61-.085.17-.178.333-.276.489l-.01.017a4.967 4.967 0 01-.62.791l-.019.02c-1.092 1.117-2.496 1.336-3.295-.262z"/><path fill="#FF4D4D" d="M21.193 9.753c2.574-.5 3.378 1.433 2.411 3.365-.58 1.159-1.476 1.361-2.342.96l-.011-.005a2.419 2.419 0 01-.114-.056l-.019-.01a2.751 2.751 0 01-.115-.067l-.023-.014c-.035-.022-.071-.044-.106-.068l-.05-.035c-.55-.388-1.062-1.007-1.44-1.76-.276-.647-.311-1.132-.174-1.472.176-.439.636-.639 1.23-.639.032-.011.066-.02.099-.03.08-.026.16-.05.238-.072l.117-.03a5.502 5.502 0 01.3-.067z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#00d4aa" d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#2ADB5C" d="M23.376 14.458v-4.056c0-2.304-1.003-4.154-2.748-5.075L11.612.574l-.046.086-.045.086c1.68.886 2.644 2.673 2.644 4.902v4.056a7.928 7.928 0 01-.014.454l-.005.061c-.005.081-.01.164-.018.245a4.897 4.897 0 01-.011.1l-.01.076c-.008.068-.015.135-.025.203l-.018.113-.01.058a9.99 9.99 0 01-.098.513l-.007.03a7.209 7.209 0 01-.074.294l-.024.086c-.027.099-.056.197-.087.296l-.027.085a9.592 9.592 0 01-.111.323l-.033.085-.018.046c-.032.082-.064.166-.098.248-.019.048-.04.096-.061.145l-.007.017a6 6 0 01-.084.187c-.024.056-.05.11-.077.165-.03.061-.058.122-.089.182a9.423 9.423 0 01-.176.332c-.03.056-.062.111-.094.167-.031.053-.062.108-.095.16-.033.055-.066.11-.101.164-.033.053-.065.104-.1.155-.034.055-.07.107-.111.169l-.099.144a15.193 15.193 0 01-.34.457c-.04.05-.08.102-.121.151l-.107.128-.007.008a6.987 6.987 0 01-.262.298l-.149.16-.116.12a9.562 9.562 0 01-.204.198l-.03.03-.072.069a9.05 9.05 0 01-.263.235l-.025.022-.029.026-.042.035a11.7 11.7 0 01-.22.18l-.07.055-.018.013a8.904 8.904 0 01-.194.146c-.029.02-.057.042-.086.063a7.7 7.7 0 01-.22.152l-.057.04a8.865 8.865 0 01-.293.185l-.062.037a10.424 10.424 0 01-.307.173l-.037.02-.196.103-.108.052-.012.006a6.196 6.196 0 01-.315.143c-.065.028-.13.054-.196.08l-.035.014-.086.034c-.07.026-.143.05-.215.075l-.039.014-.064.023a8.056 8.056 0 01-.323.097l-.63.173a7.285 7.285 0 01-.33.08l-.07.015c-.053.012-.104.023-.157.032l-.065.011-.085.015a2.332 2.332 0 01-.194.027l-.085.01a4.715 4.715 0 01-.16.018l-.034.003a4.861 4.861 0 01-.246.016h-.033a2.714 2.714 0 01-.155.005h-.106a3.384 3.384 0 01-.225-.007H4.86l-.15-.012-.066-.006a5.586 5.586 0 01-.187-.02l-.04-.005a5.14 5.14 0 01-.219-.035l-.054-.01a6.943 6.943 0 01-.347-.082l-.03-.008-.038-.01a5.034 5.034 0 01-.269-.086l-.063-.023a4.216 4.216 0 01-.188-.073l-.071-.031-.016-.007a4.959 4.959 0 01-.16-.074l-.026-.013a.164.164 0 00-.014-.007l-.671-.351.486.486h.016l8.995 4.742.093.048.03.014.02.01c.056.026.111.052.169.076l.016.008.073.032.195.076.022.008a.718.718 0 01.03.012l.014.004a4.693 4.693 0 00.323.1l.027.007c.073.02.147.038.22.055l.018.004.027.006.066.013.088.016c.075.014.15.026.226.038l.042.004c.064.009.128.016.193.022l.126.012.06.003.05.002.098.005c.046.002.094.002.14.003h.12c.05 0 .1-.002.161-.005h.033l.07-.004a6.17 6.17 0 00.184-.014l.033-.003a.753.753 0 00.058-.005l.108-.012.081-.01.08-.01.129-.021.082-.014.071-.012c.054-.01.107-.021.16-.033l.066-.013.059-.013c.096-.022.192-.046.287-.073l.63-.172a7.354 7.354 0 00.397-.122l.04-.015c.075-.025.149-.051.222-.078.032-.011.062-.024.093-.037l.03-.012c.067-.027.135-.054.2-.082l.128-.056.195-.09.021-.01.102-.05c.068-.034.135-.069.202-.105l.037-.02.073-.038c.08-.044.16-.092.24-.139l.026-.015a8.086 8.086 0 00.322-.2l.065-.045 1.98.902a1.748 1.748 0 002.472-1.59v-7.33l.004.004z"/><path fill="#ffffff" d="M11.617.576a3.904 3.904 0 00-.093-.047c-.016-.009-.033-.016-.05-.024a5.854 5.854 0 00-.166-.077l-.09-.04a4.094 4.094 0 00-.194-.074c-.017-.006-.035-.015-.053-.02l-.013-.005a5.18 5.18 0 00-.277-.088l-.07-.019a4.034 4.034 0 00-.219-.053c-.015-.003-.03-.008-.044-.012L10.253.1l-.057-.011a5.177 5.177 0 00-.225-.036L9.928.047a5.972 5.972 0 00-.191-.022L9.669.02a1.33 1.33 0 00-.058-.005L9.515.009a4.058 4.058 0 00-.111-.005C9.354 0 9.304 0 9.254 0h-.109c-.052 0-.106.004-.16.004L8.884.01A5.32 5.32 0 008.7.022l-.083.006h-.008c-.05.005-.1.013-.15.019l-.12.014c-.056.008-.112.018-.169.028-.037.006-.074.011-.11.018a7.054 7.054 0 00-.572.133l-.63.172c-.111.031-.22.064-.33.1-.037.011-.072.025-.108.037a12.91 12.91 0 00-.345.126c-.067.027-.133.054-.2.083l-.128.055a11.916 11.916 0 00-.318.15 7.376 7.376 0 00-.311.163c-.082.045-.16.092-.24.14a9.424 9.424 0 00-.35.218l-.016.01-.06.04a9.242 9.242 0 00-.51.37 12.54 12.54 0 00-.315.254l-.043.034-.01.007-.045.041c-.09.078-.18.158-.268.24l-.106.101c-.07.067-.139.135-.207.204l-.056.054-.063.067-.153.164-.12.133-.148.17c-.024.03-.049.057-.073.086l-.043.053a5.96 5.96 0 00-.123.155l-.118.151c-.04.053-.08.106-.118.16l-.075.101-.038.056-.107.155-.11.164a9.91 9.91 0 00-.168.265c-.012.02-.023.043-.037.063a12.43 12.43 0 00-.192.335l-.09.168c-.019.034-.04.07-.057.105-.011.022-.02.043-.032.065l-.092.188-.08.167a19.15 19.15 0 00-.083.192c-.017.038-.035.076-.05.115-.008.016-.014.034-.021.051-.035.083-.067.167-.1.253l-.051.134c-.04.11-.077.22-.113.33l-.02.057c0 .002 0 .005-.002.007l-.008.026c-.032.1-.06.2-.09.301l-.023.089c-.027.1-.052.2-.075.301l-.007.03a7.63 7.63 0 00-.057.267l-.008.048c-.015.074-.026.148-.038.223L.082 8.4c-.011.078-.02.156-.029.234-.006.051-.013.103-.017.154a6.57 6.57 0 00-.02.26c-.003.044-.007.086-.009.13-.004.128-.007.257-.007.386v4.056c0 1.478.42 2.741 1.138 3.692A4.75 4.75 0 002.73 18.67l9.015 4.753c-1.656-.874-2.728-2.685-2.73-5.051v-4.056c0-.13.004-.26.01-.39.002-.043.006-.085.01-.128.005-.088.01-.174.019-.261l.017-.155c.01-.077.018-.155.029-.234l.026-.164c.013-.074.025-.15.039-.223.02-.105.04-.21.064-.313l.008-.031c.023-.1.048-.201.075-.301l.023-.088c.028-.1.058-.202.09-.302l.008-.025.021-.063c.036-.11.073-.22.113-.33l.052-.134c.031-.085.065-.169.1-.253.022-.056.047-.111.07-.166a13.856 13.856 0 01.164-.358c.03-.063.06-.126.092-.188l.088-.172a9.22 9.22 0 01.187-.338l.096-.164c.034-.057.069-.112.104-.168l.1-.159a10.49 10.49 0 01.567-.786l.123-.155.116-.139c.05-.057.098-.115.148-.171a14.092 14.092 0 01.272-.297 9.706 9.706 0 01.432-.425c.088-.083.177-.163.268-.241l.054-.048a10.08 10.08 0 01.553-.435l.092-.068c.075-.053.15-.105.226-.156.019-.013.038-.028.06-.04a9.18 9.18 0 01.362-.227c.08-.047.16-.094.241-.139l.11-.058a7.643 7.643 0 01.521-.256l.126-.056a7.509 7.509 0 01.546-.208l.107-.037c.11-.036.22-.069.33-.1l.63-.172c.095-.026.191-.05.287-.072l.097-.02c.062-.014.125-.029.187-.04l.114-.018c.055-.01.11-.02.166-.028.04-.006.08-.01.12-.014.053-.007.105-.014.157-.019l.083-.006c.061-.005.123-.01.184-.013.034-.003.067-.003.101-.004l.16-.006h.11a3.187 3.187 0 01.261.008l.153.01.067.007c.064.006.128.013.192.022l.043.005a5.232 5.232 0 01.281.047l.141.03c.073.016.146.035.218.053l.07.019c.094.026.187.055.278.087l.067.025a4.326 4.326 0 01.449.19l.143.072L11.617.576z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#eab308" fill-rule="evenodd" d="M20.113 5.5l-.442 1.557a.157.157 0 01-.196.106l-7.414-2.157a.16.16 0 00-.143.028l-7.342 5.74a.159.159 0 01-.074.032l-4.37.656a.154.154 0 00-.132.162l.02.245c.005.078.071.14.152.141l5.074.128.058.002 3.75-1.953a.16.16 0 01.164.01l2.657 1.847a.152.152 0 01.066.125l-.023 2.45c0 .032.01.063.028.089l3.737 5.227c.03.04.077.065.129.065h1.182a.153.153 0 00.14-.224l-2.664-4.919a.15.15 0 01.005-.152l1.389-2.169a.156.156 0 01.062-.055l4.965-2.456a.16.16 0 01.158.01l1.418.921a.16.16 0 00.087.026h1.289c.125 0 .2-.136.13-.237l-3.578-5.29c-.074-.109-.246-.082-.282.044z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#32F08C" d="M24 20.541H3.428v-3.426H0V3.4h24V20.54zM3.428 17.115h17.144V6.827H3.428v10.288zm8.573-5.196l-2.425 2.424-2.424-2.424 2.424-2.424 2.425 2.424zm6.857-.001l-2.424 2.423-2.425-2.423 2.425-2.425 2.424 2.425z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#00d084" fill-rule="evenodd" clip-rule="evenodd" d="M23.78 5.004h-.228a2.187 2.187 0 00-2.18 2.196v4.912c0 .98-.804 1.775-1.76 1.775a1.818 1.818 0 01-1.472-.773L13.168 5.95a2.197 2.197 0 00-1.81-.95c-1.134 0-2.154.972-2.154 2.173v4.94c0 .98-.797 1.775-1.76 1.775-.57 0-1.136-.289-1.472-.773L.408 5.098C.282 4.918 0 5.007 0 5.228v4.284c0 .216.066.426.188.604l5.475 7.889c.324.466.8.812 1.351.938 1.377.316 2.645-.754 2.645-2.117V11.89c0-.98.787-1.775 1.76-1.775h.002c.586 0 1.135.288 1.472.773l4.972 7.163a2.15 2.15 0 001.81.95c1.158 0 2.151-.973 2.151-2.173v-4.939c0-.98.787-1.775 1.76-1.775h.194c.122 0 .22-.1.22-.222V5.225a.221.221 0 00-.22-.222z"/></svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { parseSkillDoc } from "./core.js";
|
|
2
|
+
const IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
3
|
+
const SAFE_PATH = /^(?!\/)(?!.*(?:^|\/)\.\.(?:\/|$))[A-Za-z0-9._/-]+$/;
|
|
4
|
+
const MAX_TEXT_BYTES = 1 << 20;
|
|
5
|
+
const MAX_ARCHIVE_BYTES = 8 << 20;
|
|
6
|
+
const MAX_FILES = 100;
|
|
7
|
+
function catalogError(message, statusCode, code) {
|
|
8
|
+
return Object.assign(new Error(message), { statusCode, code });
|
|
9
|
+
}
|
|
10
|
+
function identifier(value) {
|
|
11
|
+
return typeof value === "string" && IDENTIFIER.test(value) ? value : void 0;
|
|
12
|
+
}
|
|
13
|
+
function skillshParts(input) {
|
|
14
|
+
const source = typeof input.source === "string" ? input.source : "";
|
|
15
|
+
const [owner, repo, extra] = source.split("/");
|
|
16
|
+
const skillId = identifier(input.skillId);
|
|
17
|
+
if (!identifier(owner) || !identifier(repo) || extra !== void 0 || !skillId) return void 0;
|
|
18
|
+
return { owner, repo, skillId, source };
|
|
19
|
+
}
|
|
20
|
+
function catalogUrls(input) {
|
|
21
|
+
if (!input || input.catalog === "clawhub") {
|
|
22
|
+
const owner = identifier(input?.owner);
|
|
23
|
+
const slug = identifier(input?.slug);
|
|
24
|
+
if (input?.catalog !== "clawhub" || !owner || !slug) throw catalogError("\u76EE\u5F55\u6280\u80FD\u6807\u8BC6\u65E0\u6548", 400, "error.catalog.identity");
|
|
25
|
+
const detail = new URL(`https://clawhub.ai/api/v1/skills/${encodeURIComponent(slug)}/file`);
|
|
26
|
+
detail.searchParams.set("path", "SKILL.md");
|
|
27
|
+
detail.searchParams.set("owner", owner);
|
|
28
|
+
const download = new URL("https://clawhub.ai/api/v1/download");
|
|
29
|
+
download.searchParams.set("slug", slug);
|
|
30
|
+
download.searchParams.set("owner", owner);
|
|
31
|
+
return { detail: detail.toString(), download: download.toString(), origin: `${owner}/${slug}` };
|
|
32
|
+
}
|
|
33
|
+
if (input.catalog === "skillsh") {
|
|
34
|
+
const parts = skillshParts(input);
|
|
35
|
+
if (!parts) throw catalogError("\u76EE\u5F55\u6280\u80FD\u6807\u8BC6\u65E0\u6548", 400, "error.catalog.identity");
|
|
36
|
+
const download = `https://skills.sh/api/download/${encodeURIComponent(parts.owner)}/${encodeURIComponent(parts.repo)}/${encodeURIComponent(parts.skillId)}`;
|
|
37
|
+
return { detail: download, download, origin: `${parts.source}/${parts.skillId}` };
|
|
38
|
+
}
|
|
39
|
+
throw catalogError("\u76EE\u5F55\u6280\u80FD\u6807\u8BC6\u65E0\u6548", 400, "error.catalog.identity");
|
|
40
|
+
}
|
|
41
|
+
async function readBounded(response, limit) {
|
|
42
|
+
const declared = Number(response.headers.get("content-length"));
|
|
43
|
+
if (Number.isFinite(declared) && declared > limit) {
|
|
44
|
+
await response.body?.cancel().catch(() => void 0);
|
|
45
|
+
throw catalogError("\u76EE\u5F55\u6280\u80FD\u5185\u5BB9\u8FC7\u5927", 502, "error.catalog.response");
|
|
46
|
+
}
|
|
47
|
+
const reader = response.body?.getReader();
|
|
48
|
+
if (!reader) return new Uint8Array();
|
|
49
|
+
const chunks = [];
|
|
50
|
+
let size = 0;
|
|
51
|
+
try {
|
|
52
|
+
while (true) {
|
|
53
|
+
const { done, value } = await reader.read();
|
|
54
|
+
if (done) break;
|
|
55
|
+
size += value.byteLength;
|
|
56
|
+
if (size > limit) {
|
|
57
|
+
throw catalogError("\u76EE\u5F55\u6280\u80FD\u5185\u5BB9\u8FC7\u5927", 502, "error.catalog.response");
|
|
58
|
+
}
|
|
59
|
+
chunks.push(value);
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
await reader.cancel().catch(() => void 0);
|
|
63
|
+
if (error instanceof Error && "code" in error && error.code === "error.catalog.response" && "statusCode" in error && error.statusCode === 502) throw error;
|
|
64
|
+
throw catalogError("\u76EE\u5F55\u6280\u80FD\u54CD\u5E94\u65E0\u6548\u6216\u8BFB\u53D6\u4E2D\u65AD", 502, "error.catalog.response");
|
|
65
|
+
} finally {
|
|
66
|
+
reader.releaseLock();
|
|
67
|
+
}
|
|
68
|
+
return Buffer.concat(chunks, size);
|
|
69
|
+
}
|
|
70
|
+
function parseFilesJson(bytes) {
|
|
71
|
+
let payload;
|
|
72
|
+
try {
|
|
73
|
+
payload = JSON.parse(new TextDecoder().decode(bytes));
|
|
74
|
+
} catch {
|
|
75
|
+
throw catalogError("\u76EE\u5F55\u6280\u80FD\u8FD4\u56DE\u4E86\u65E0\u6548 JSON", 502, "error.catalog.response");
|
|
76
|
+
}
|
|
77
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) throw catalogError("\u76EE\u5F55\u6280\u80FD\u6587\u4EF6\u65E0\u6548", 502, "error.catalog.response");
|
|
78
|
+
const files = payload.files;
|
|
79
|
+
if (!Array.isArray(files) || !files.length || files.length > MAX_FILES) throw catalogError("\u76EE\u5F55\u6280\u80FD\u6587\u4EF6\u65E0\u6548\u6216\u8FC7\u591A", 502, "error.catalog.response");
|
|
80
|
+
for (const file of files) {
|
|
81
|
+
if (!file || typeof file !== "object" || Array.isArray(file) || typeof file.path !== "string" || typeof file.contents !== "string") throw catalogError("\u76EE\u5F55\u6280\u80FD\u6587\u4EF6\u65E0\u6548", 502, "error.catalog.response");
|
|
82
|
+
}
|
|
83
|
+
return { files };
|
|
84
|
+
}
|
|
85
|
+
function skillDocSummary(markdown) {
|
|
86
|
+
const parsed = parseSkillDoc(markdown);
|
|
87
|
+
const name = parsed.map.name?.trim();
|
|
88
|
+
const description = parsed.map.description?.trim();
|
|
89
|
+
return { name, description, body: parsed.body };
|
|
90
|
+
}
|
|
91
|
+
async function fetchFixed(url, fetchImpl, accept) {
|
|
92
|
+
let response;
|
|
93
|
+
try {
|
|
94
|
+
response = await fetchImpl(url, { headers: { accept }, redirect: "error", signal: AbortSignal.timeout(15e3) });
|
|
95
|
+
} catch {
|
|
96
|
+
throw catalogError("\u76EE\u5F55\u6280\u80FD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6", 502, "error.catalog.upstream");
|
|
97
|
+
}
|
|
98
|
+
if (!response.ok) throw catalogError("\u76EE\u5F55\u6280\u80FD\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6", 502, "error.catalog.upstream");
|
|
99
|
+
return response;
|
|
100
|
+
}
|
|
101
|
+
async function readCatalogSkill(input, fetchImpl = fetch) {
|
|
102
|
+
const urls = catalogUrls(input);
|
|
103
|
+
if (input.catalog === "clawhub") {
|
|
104
|
+
const response2 = await fetchFixed(urls.detail, fetchImpl, "text/markdown, text/plain");
|
|
105
|
+
const markdown = new TextDecoder().decode(await readBounded(response2, MAX_TEXT_BYTES));
|
|
106
|
+
const parsed2 = skillDocSummary(markdown);
|
|
107
|
+
if (!parsed2.name || !parsed2.description) throw catalogError("\u76EE\u5F55\u6280\u80FD\u8BF4\u660E\u65E0\u6548", 502, "error.catalog.response");
|
|
108
|
+
return { name: parsed2.name, description: parsed2.description, body: parsed2.body, origin: urls.origin };
|
|
109
|
+
}
|
|
110
|
+
const response = await fetchFixed(urls.download, fetchImpl, "application/json");
|
|
111
|
+
const payload = parseFilesJson(await readBounded(response, MAX_TEXT_BYTES));
|
|
112
|
+
const document = payload.files?.find((file) => file.path === "SKILL.md" && typeof file.contents === "string");
|
|
113
|
+
if (!document || typeof document.contents !== "string") throw catalogError("\u76EE\u5F55\u6280\u80FD\u8BF4\u660E\u65E0\u6548", 502, "error.catalog.response");
|
|
114
|
+
const parsed = skillDocSummary(document.contents);
|
|
115
|
+
if (!parsed.name || !parsed.description) throw catalogError("\u76EE\u5F55\u6280\u80FD\u8BF4\u660E\u65E0\u6548", 502, "error.catalog.response");
|
|
116
|
+
return { name: parsed.name, description: parsed.description, body: parsed.body, origin: urls.origin };
|
|
117
|
+
}
|
|
118
|
+
async function loadCatalogPackage(input, fetchImpl = fetch) {
|
|
119
|
+
const urls = catalogUrls(input);
|
|
120
|
+
if (input.catalog === "clawhub") {
|
|
121
|
+
const response2 = await fetchFixed(urls.download, fetchImpl, "application/zip");
|
|
122
|
+
const bytes = await readBounded(response2, MAX_ARCHIVE_BYTES);
|
|
123
|
+
const detail2 = await readCatalogSkill(input, fetchImpl);
|
|
124
|
+
return { name: detail2.name, zip: Buffer.from(bytes).toString("base64") };
|
|
125
|
+
}
|
|
126
|
+
const response = await fetchFixed(urls.download, fetchImpl, "application/json");
|
|
127
|
+
const payload = parseFilesJson(await readBounded(response, MAX_ARCHIVE_BYTES));
|
|
128
|
+
if (!Array.isArray(payload.files) || !payload.files.length || payload.files.length > MAX_FILES) throw catalogError("\u76EE\u5F55\u6280\u80FD\u6587\u4EF6\u65E0\u6548\u6216\u8FC7\u591A", 502, "error.catalog.response");
|
|
129
|
+
const entries = payload.files.map((file) => {
|
|
130
|
+
if (typeof file.path !== "string" || !SAFE_PATH.test(file.path) || typeof file.contents !== "string") throw catalogError("\u76EE\u5F55\u6280\u80FD\u5305\u542B\u975E\u6CD5\u6587\u4EF6\u8DEF\u5F84", 502, "error.catalog.response");
|
|
131
|
+
return { path: file.path, data: Buffer.from(file.contents, "utf8").toString("base64") };
|
|
132
|
+
});
|
|
133
|
+
if (!entries.some((entry) => entry.path === "SKILL.md")) throw catalogError("\u76EE\u5F55\u6280\u80FD\u7F3A\u5C11 SKILL.md", 502, "error.catalog.response");
|
|
134
|
+
const detail = skillDocSummary(Buffer.from(entries.find((entry) => entry.path === "SKILL.md").data, "base64").toString("utf8"));
|
|
135
|
+
if (!detail.name) throw catalogError("\u76EE\u5F55\u6280\u80FD\u8BF4\u660E\u65E0\u6548", 502, "error.catalog.response");
|
|
136
|
+
return { name: detail.name, entries };
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
catalogUrls,
|
|
140
|
+
loadCatalogPackage,
|
|
141
|
+
readCatalogSkill
|
|
142
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
function record(value) {
|
|
2
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3
|
+
}
|
|
4
|
+
function count(value) {
|
|
5
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
6
|
+
}
|
|
7
|
+
function skillItem(value) {
|
|
8
|
+
const candidate = record(value);
|
|
9
|
+
if (!candidate) return void 0;
|
|
10
|
+
const owner = candidate.ownerHandle ?? record(candidate.owner)?.handle;
|
|
11
|
+
const slug = candidate.slug;
|
|
12
|
+
const identifier = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
13
|
+
if (typeof owner !== "string" || !identifier.test(owner) || typeof slug !== "string" || !identifier.test(slug)) return void 0;
|
|
14
|
+
const item = {
|
|
15
|
+
ownerHandle: owner,
|
|
16
|
+
slug,
|
|
17
|
+
displayName: typeof candidate.displayName === "string" && candidate.displayName && candidate.displayName.length <= 256 ? candidate.displayName : slug,
|
|
18
|
+
summary: typeof candidate.summary === "string" && candidate.summary.length <= 8192 ? candidate.summary : ""
|
|
19
|
+
};
|
|
20
|
+
const stats = record(candidate.stats) ?? record(record(record(candidate.native)?.skill)?.stats);
|
|
21
|
+
if (stats) {
|
|
22
|
+
item.stats = {};
|
|
23
|
+
for (const key of ["downloads", "installs", "stars"]) {
|
|
24
|
+
const number = count(stats[key]);
|
|
25
|
+
if (number !== void 0) item.stats[key] = number;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return item;
|
|
29
|
+
}
|
|
30
|
+
async function searchClawHub(query, options = {}, fetchImpl = fetch) {
|
|
31
|
+
const normalized = typeof query === "string" ? query.trim() : "";
|
|
32
|
+
if (!normalized || normalized.length > 100 || !record(options)) throw catalogError("\u76EE\u5F55\u641C\u7D22\u53C2\u6570\u65E0\u6548", 400, "error.catalog.query");
|
|
33
|
+
const limit = requestLimit(options.limit, 100);
|
|
34
|
+
const url = new URL("https://clawhub.ai/api/v1/search");
|
|
35
|
+
url.searchParams.set("q", normalized);
|
|
36
|
+
url.searchParams.set("limit", String(limit));
|
|
37
|
+
const payload = await fetchJson(url, fetchImpl);
|
|
38
|
+
if (!Array.isArray(payload.results)) throw catalogError("\u76EE\u5F55\u641C\u7D22\u54CD\u5E94\u65E0\u6548", 502, "error.catalog.response");
|
|
39
|
+
const results = [];
|
|
40
|
+
for (const value of payload.results) {
|
|
41
|
+
const candidate = record(value);
|
|
42
|
+
if (!candidate || candidate.source !== void 0 && candidate.source !== "clawhub") continue;
|
|
43
|
+
const item = skillItem(candidate);
|
|
44
|
+
if (!item) continue;
|
|
45
|
+
const result = { ...item, source: "clawhub" };
|
|
46
|
+
if (typeof candidate.id === "string" && candidate.id && candidate.id.length <= 768) result.id = candidate.id;
|
|
47
|
+
const downloads = count(candidate.downloads);
|
|
48
|
+
if (downloads !== void 0) result.downloads = downloads;
|
|
49
|
+
results.push(result);
|
|
50
|
+
if (results.length >= limit) break;
|
|
51
|
+
}
|
|
52
|
+
return { results };
|
|
53
|
+
}
|
|
54
|
+
function catalogError(message, statusCode, code) {
|
|
55
|
+
return Object.assign(new Error(message), { statusCode, code });
|
|
56
|
+
}
|
|
57
|
+
async function fetchJson(url, fetchImpl) {
|
|
58
|
+
let response;
|
|
59
|
+
try {
|
|
60
|
+
response = await fetchImpl(url, { headers: { accept: "application/json" }, redirect: "error", signal: AbortSignal.timeout(1e4) });
|
|
61
|
+
} catch {
|
|
62
|
+
throw catalogError("ClawHub \u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528", 502, "error.catalog.upstream");
|
|
63
|
+
}
|
|
64
|
+
if (!response.ok) throw catalogError("ClawHub \u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528", 502, "error.catalog.upstream");
|
|
65
|
+
const maxBytes = 1 << 20;
|
|
66
|
+
if (Number(response.headers.get("content-length")) > maxBytes) {
|
|
67
|
+
await response.body?.cancel().catch(() => void 0);
|
|
68
|
+
throw catalogError("ClawHub \u54CD\u5E94\u8FC7\u5927", 502, "error.catalog.response");
|
|
69
|
+
}
|
|
70
|
+
const reader = response.body?.getReader();
|
|
71
|
+
const chunks = [];
|
|
72
|
+
let size = 0;
|
|
73
|
+
if (reader) {
|
|
74
|
+
try {
|
|
75
|
+
while (true) {
|
|
76
|
+
const { done, value } = await reader.read();
|
|
77
|
+
if (done) break;
|
|
78
|
+
size += value.byteLength;
|
|
79
|
+
if (size > maxBytes) {
|
|
80
|
+
throw catalogError("ClawHub \u54CD\u5E94\u8FC7\u5927", 502, "error.catalog.response");
|
|
81
|
+
}
|
|
82
|
+
chunks.push(value);
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
await reader.cancel().catch(() => void 0);
|
|
86
|
+
if (error instanceof Error && "code" in error && error.code === "error.catalog.response" && "statusCode" in error && error.statusCode === 502) throw error;
|
|
87
|
+
throw catalogError("ClawHub \u54CD\u5E94\u65E0\u6548\u6216\u8FC7\u5927", 502, "error.catalog.response");
|
|
88
|
+
} finally {
|
|
89
|
+
reader.releaseLock();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
let payload;
|
|
93
|
+
try {
|
|
94
|
+
payload = JSON.parse(Buffer.concat(chunks, size).toString("utf8"));
|
|
95
|
+
} catch {
|
|
96
|
+
throw catalogError("ClawHub \u54CD\u5E94\u4E0D\u662F\u6709\u6548 JSON", 502, "error.catalog.response");
|
|
97
|
+
}
|
|
98
|
+
const object = record(payload);
|
|
99
|
+
if (!object) throw catalogError("ClawHub \u54CD\u5E94\u7ED3\u6784\u65E0\u6548", 502, "error.catalog.response");
|
|
100
|
+
return object;
|
|
101
|
+
}
|
|
102
|
+
function requestLimit(value, max) {
|
|
103
|
+
if (value === void 0) return max;
|
|
104
|
+
const number = typeof value === "string" && /^[0-9]{1,3}$/.test(value) ? Number(value) : value;
|
|
105
|
+
if (typeof number !== "number" || !Number.isInteger(number) || number < 1 || number > max) throw catalogError("\u76EE\u5F55\u67E5\u8BE2 limit \u65E0\u6548", 400, "error.catalog.query");
|
|
106
|
+
return number;
|
|
107
|
+
}
|
|
108
|
+
async function listClawHub(options = {}, fetchImpl = fetch) {
|
|
109
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) throw catalogError("\u76EE\u5F55\u67E5\u8BE2\u53C2\u6570\u65E0\u6548", 400, "error.catalog.query");
|
|
110
|
+
const limit = requestLimit(options.limit, 10);
|
|
111
|
+
const sort = options.sort === void 0 ? "downloads" : options.sort;
|
|
112
|
+
if (sort !== "downloads") throw catalogError("\u76EE\u5F55\u699C\u5355\u6392\u5E8F\u65E0\u6548", 400, "error.catalog.query");
|
|
113
|
+
if (options.cursor !== void 0 && (typeof options.cursor !== "string" || !options.cursor || options.cursor.length > 4096)) throw catalogError("\u76EE\u5F55\u5206\u9875\u6807\u8BC6\u65E0\u6548", 400, "error.catalog.query");
|
|
114
|
+
const url = new URL("https://clawhub.ai/api/v1/skills");
|
|
115
|
+
url.searchParams.set("sort", sort);
|
|
116
|
+
url.searchParams.set("limit", String(limit));
|
|
117
|
+
if (options.cursor !== void 0) url.searchParams.set("cursor", options.cursor);
|
|
118
|
+
const payload = await fetchJson(url, fetchImpl);
|
|
119
|
+
if (!Array.isArray(payload.items)) throw catalogError("\u76EE\u5F55\u699C\u5355\u54CD\u5E94\u65E0\u6548", 502, "error.catalog.response");
|
|
120
|
+
const nextCursor = payload.nextCursor;
|
|
121
|
+
if (nextCursor !== void 0 && nextCursor !== null && (typeof nextCursor !== "string" || nextCursor.length > 4096)) throw catalogError("\u76EE\u5F55\u5206\u9875\u54CD\u5E94\u65E0\u6548", 502, "error.catalog.response");
|
|
122
|
+
const items = [];
|
|
123
|
+
for (const value of payload.items) {
|
|
124
|
+
const item = skillItem(value);
|
|
125
|
+
if (!item) continue;
|
|
126
|
+
items.push(item);
|
|
127
|
+
if (items.length >= limit) break;
|
|
128
|
+
}
|
|
129
|
+
return { items, nextCursor: typeof nextCursor === "string" && nextCursor ? nextCursor : null };
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
listClawHub,
|
|
133
|
+
searchClawHub
|
|
134
|
+
};
|