@chongyan/autospec 1.0.1

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.
Files changed (243) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +472 -0
  3. package/README.md +476 -0
  4. package/bin/autospec.js +3 -0
  5. package/knowledge/README.md +144 -0
  6. package/knowledge/checklists/code.md +182 -0
  7. package/knowledge/checklists/design.md +196 -0
  8. package/knowledge/checklists/release.md +70 -0
  9. package/knowledge/checklists/requirement.md +169 -0
  10. package/knowledge/checklists/test.md +46 -0
  11. package/knowledge/config/README.en.md +44 -0
  12. package/knowledge/config/README.md +44 -0
  13. package/knowledge/config/role-composition.yaml +98 -0
  14. package/knowledge/config/role-extensions.yaml +140 -0
  15. package/knowledge/config/skill-compositions.yaml +142 -0
  16. package/knowledge/config/team-stage.yaml +95 -0
  17. package/knowledge/config/team-tasks.yaml +139 -0
  18. package/knowledge/config/team-triggers.yaml +198 -0
  19. package/knowledge/config/validation-patterns.yaml +137 -0
  20. package/knowledge/domain/README.md +115 -0
  21. package/knowledge/domain/flows/README.md +194 -0
  22. package/knowledge/domain/glossary.md +143 -0
  23. package/knowledge/domain/rules.md +138 -0
  24. package/knowledge/environment/README.en.md +36 -0
  25. package/knowledge/environment/README.md +87 -0
  26. package/knowledge/environment/component-knowledge.md +316 -0
  27. package/knowledge/environment/detection-patterns.yaml +502 -0
  28. package/knowledge/environment/middleware-knowledge.md +237 -0
  29. package/knowledge/environment/template-registry.md +321 -0
  30. package/knowledge/guides/domain-driven-design.md +345 -0
  31. package/knowledge/guides/knowledge-management.md +369 -0
  32. package/knowledge/guides/requirement-engineering.md +329 -0
  33. package/knowledge/guides/stages/ai-effect-evaluator.md +93 -0
  34. package/knowledge/guides/stages/code-implementer.md +205 -0
  35. package/knowledge/guides/stages/code-reviewer.md +111 -0
  36. package/knowledge/guides/stages/consistency-checker.md +177 -0
  37. package/knowledge/guides/stages/design-planner.md +401 -0
  38. package/knowledge/guides/stages/design-reviewer.md +83 -0
  39. package/knowledge/guides/stages/integration-test-runner.md +105 -0
  40. package/knowledge/guides/stages/release-checker.md +205 -0
  41. package/knowledge/guides/stages/requirement-analyzer.md +195 -0
  42. package/knowledge/guides/stages/requirement-reviewer.md +83 -0
  43. package/knowledge/guides/stages/security-reviewer.md +89 -0
  44. package/knowledge/guides/stages/test-context-analyzer.md +250 -0
  45. package/knowledge/guides/stages/test-generator.md +241 -0
  46. package/knowledge/guides/stages/test-planner.md +183 -0
  47. package/knowledge/guides/stages/test-reviewer.md +76 -0
  48. package/knowledge/guides/stages/unit-test-runner.md +83 -0
  49. package/knowledge/guides/support/ai-agent-analyzer.md +362 -0
  50. package/knowledge/guides/support/ai-anomaly-analyzer.md +213 -0
  51. package/knowledge/guides/support/ai-artifact-evaluator.md +192 -0
  52. package/knowledge/guides/support/ai-capability-analyzer.md +193 -0
  53. package/knowledge/guides/support/ai-component-analyzer.md +169 -0
  54. package/knowledge/guides/support/ai-data-validator.md +276 -0
  55. package/knowledge/guides/support/ai-evaluation-planner.md +374 -0
  56. package/knowledge/guides/support/ai-path-evaluator.md +274 -0
  57. package/knowledge/guides/support/ai-pipeline-evaluator.md +219 -0
  58. package/knowledge/guides/support/ai-rag-analyzer.md +339 -0
  59. package/knowledge/guides/support/ai-task-assessor.md +418 -0
  60. package/knowledge/guides/support/ai-test-diagnostics.md +133 -0
  61. package/knowledge/guides/support/complexity-assessor.md +268 -0
  62. package/knowledge/guides/support/component-discovery.md +183 -0
  63. package/knowledge/guides/support/environment-scanner.md +207 -0
  64. package/knowledge/guides/support/environment-validator.md +207 -0
  65. package/knowledge/guides/support/knowledge-generator.md +234 -0
  66. package/knowledge/guides/support/methodology-extractor.md +55 -0
  67. package/knowledge/guides/support/pipeline-protocol.md +438 -0
  68. package/knowledge/guides/support/practice-logger.md +359 -0
  69. package/knowledge/guides/support/scope-inference.md +174 -0
  70. package/knowledge/guides/support/skill-distiller.md +91 -0
  71. package/knowledge/guides/support/skill-updater.md +45 -0
  72. package/knowledge/guides/support/skill-validator.md +72 -0
  73. package/knowledge/guides/support/team-orchestrator.md +323 -0
  74. package/knowledge/guides/support/tech-stack-analyzer.md +139 -0
  75. package/knowledge/guides/support/test-runner.md +254 -0
  76. package/knowledge/guides/system-design.md +352 -0
  77. package/knowledge/organization/ai-native-team.md +318 -0
  78. package/knowledge/organization/team-metrics.md +228 -0
  79. package/knowledge/principles/constitution.md +134 -0
  80. package/knowledge/principles/core-principles.md +368 -0
  81. package/knowledge/principles/design-philosophy.md +877 -0
  82. package/knowledge/principles/evolution.md +553 -0
  83. package/knowledge/process/01-requirement.md +113 -0
  84. package/knowledge/process/02-design.md +123 -0
  85. package/knowledge/process/03-implementation.md +90 -0
  86. package/knowledge/process/04-review.md +80 -0
  87. package/knowledge/process/05-testing.md +90 -0
  88. package/knowledge/process/06-delivery.md +88 -0
  89. package/knowledge/process/README.en.md +38 -0
  90. package/knowledge/process/README.md +48 -0
  91. package/knowledge/process/ai-sdlc.md +475 -0
  92. package/knowledge/process/overview.md +319 -0
  93. package/knowledge/standards/code-review.md +876 -0
  94. package/knowledge/standards/coding-style.md +940 -0
  95. package/knowledge/standards/data-consistency.md +1085 -0
  96. package/knowledge/standards/document-versioning.md +210 -0
  97. package/knowledge/standards/risk-detection.md +186 -0
  98. package/knowledge/templates/ai-evaluation.md +150 -0
  99. package/knowledge/templates/api-design.md +117 -0
  100. package/knowledge/templates/database-design.md +132 -0
  101. package/knowledge/templates/domain-driven-design.md +321 -0
  102. package/knowledge/templates/product-proposal.md +201 -0
  103. package/knowledge/templates/system-design.md +227 -0
  104. package/knowledge/templates/task-breakdown.md +107 -0
  105. package/knowledge/templates/test-case.md +170 -0
  106. package/package.json +53 -0
  107. package/plugins/.claude-plugin/plugin.json +134 -0
  108. package/plugins/agents/roles/ai-engineer.md +129 -0
  109. package/plugins/agents/roles/backend-engineer.md +165 -0
  110. package/plugins/agents/roles/ceo.md +94 -0
  111. package/plugins/agents/roles/data-engineer.md +135 -0
  112. package/plugins/agents/roles/devops-engineer.md +181 -0
  113. package/plugins/agents/roles/frontend-engineer.md +129 -0
  114. package/plugins/agents/roles/product-owner.md +98 -0
  115. package/plugins/agents/roles/quality-engineer.md +129 -0
  116. package/plugins/agents/roles/security-engineer.md +180 -0
  117. package/plugins/agents/roles/tech-lead.md +97 -0
  118. package/plugins/agents/support/blind-comparator.md +88 -0
  119. package/plugins/agents/support/consistency-checker.md +103 -0
  120. package/plugins/agents/support/failure-diagnostician.md +141 -0
  121. package/plugins/agents/support/independent-reviewer.md +80 -0
  122. package/plugins/agents/support/safety-auditor.md +121 -0
  123. package/plugins/agents/support/skill-benchmarker.md +86 -0
  124. package/plugins/agents/support/skill-forger.md +105 -0
  125. package/plugins/agents/support/stage-gate-evaluator.md +121 -0
  126. package/plugins/agents/support/test-coverage-reviewer.md +73 -0
  127. package/plugins/benchmarks/templates/README.md +44 -0
  128. package/plugins/benchmarks/templates/commands/explore-template.yaml +48 -0
  129. package/plugins/benchmarks/templates/pipeline/agile-template.yaml +84 -0
  130. package/plugins/benchmarks/templates/pipeline/waterfall-template.yaml +106 -0
  131. package/plugins/benchmarks/templates/skills/requirement-analyzer-template.yaml +48 -0
  132. package/plugins/commands/README.en.md +96 -0
  133. package/plugins/commands/README.md +96 -0
  134. package/plugins/commands/apply.md +191 -0
  135. package/plugins/commands/archive.md +76 -0
  136. package/plugins/commands/env-export.md +79 -0
  137. package/plugins/commands/env-sync.md +640 -0
  138. package/plugins/commands/env-template.md +223 -0
  139. package/plugins/commands/env-update.md +264 -0
  140. package/plugins/commands/env-validate.md +176 -0
  141. package/plugins/commands/env.md +79 -0
  142. package/plugins/commands/explore.md +76 -0
  143. package/plugins/commands/field-evolve.md +536 -0
  144. package/plugins/commands/memory.md +249 -0
  145. package/plugins/commands/project-evolve.md +821 -0
  146. package/plugins/commands/propose.md +93 -0
  147. package/plugins/commands/review.md +140 -0
  148. package/plugins/commands/run.md +224 -0
  149. package/plugins/commands/status.md +62 -0
  150. package/plugins/commands/validate.md +108 -0
  151. package/plugins/hooks/README.en.md +56 -0
  152. package/plugins/hooks/README.md +56 -0
  153. package/plugins/hooks/ai-project-guard.js +329 -0
  154. package/plugins/hooks/artifact-evaluation-hook.js +237 -0
  155. package/plugins/hooks/constitution-guard.js +211 -0
  156. package/plugins/hooks/environment-autocommit.js +264 -0
  157. package/plugins/hooks/environment-manager.js +778 -0
  158. package/plugins/hooks/execution-tracker.js +354 -0
  159. package/plugins/hooks/frozen-zone-guard.js +140 -0
  160. package/plugins/hooks/layer1-validator.js +423 -0
  161. package/plugins/hooks/lib/artifact-evaluator.js +414 -0
  162. package/plugins/hooks/lib/benchmarks/change-detector.js +390 -0
  163. package/plugins/hooks/lib/benchmarks/evaluator.js +605 -0
  164. package/plugins/hooks/lib/benchmarks/integration-example.js +169 -0
  165. package/plugins/hooks/lib/data-and-ai-detector.js +275 -0
  166. package/plugins/hooks/lib/detection-pattern-loader.js +865 -0
  167. package/plugins/hooks/lib/directory-discovery.js +395 -0
  168. package/plugins/hooks/lib/environment-config-loader.js +341 -0
  169. package/plugins/hooks/lib/environment-detector.js +553 -0
  170. package/plugins/hooks/lib/environment-evolver.js +564 -0
  171. package/plugins/hooks/lib/environment-registry.js +813 -0
  172. package/plugins/hooks/lib/execution-path.js +427 -0
  173. package/plugins/hooks/lib/hook-error-recorder.js +245 -0
  174. package/plugins/hooks/lib/hook-logger.js +538 -0
  175. package/plugins/hooks/lib/hook-runner.js +97 -0
  176. package/plugins/hooks/lib/hook-runner.sh +44 -0
  177. package/plugins/hooks/lib/hook-state-manager.js +480 -0
  178. package/plugins/hooks/lib/memory-extractor.js +377 -0
  179. package/plugins/hooks/lib/memory-manager.js +673 -0
  180. package/plugins/hooks/lib/metrics-analyzer.js +489 -0
  181. package/plugins/hooks/lib/project-evolution/auto-fixer.js +511 -0
  182. package/plugins/hooks/lib/project-evolution/memory-manager.js +346 -0
  183. package/plugins/hooks/lib/project-evolution/pattern-detector.js +476 -0
  184. package/plugins/hooks/lib/project-evolution/semantic-indexer.js +480 -0
  185. package/plugins/hooks/lib/project-structure-detector.js +326 -0
  186. package/plugins/hooks/lib/rollback-tracker.js +346 -0
  187. package/plugins/hooks/lib/source-code-scanner.js +596 -0
  188. package/plugins/hooks/lib/technology-stack-detector.js +374 -0
  189. package/plugins/hooks/lib/test-failure-analyzer.js +375 -0
  190. package/plugins/hooks/lib/test-failure-fixer.js +268 -0
  191. package/plugins/hooks/lib/trace-context.js +277 -0
  192. package/plugins/hooks/lib/validation-patterns.js +415 -0
  193. package/plugins/hooks/memory-sync.js +171 -0
  194. package/plugins/hooks/pipeline-observer.js +413 -0
  195. package/plugins/hooks/scope-sentinel.js +204 -0
  196. package/plugins/hooks/trace-initialization.js +169 -0
  197. package/plugins/memory/templates/code-quality.yaml +149 -0
  198. package/plugins/memory/templates/multi-system.yaml +155 -0
  199. package/plugins/memory/templates/team-habits.yaml +119 -0
  200. package/plugins/memory/templates/testing.yaml +121 -0
  201. package/plugins/skills/README.en.md +47 -0
  202. package/plugins/skills/README.md +104 -0
  203. package/plugins/skills/benchmark-executor/README.md +93 -0
  204. package/plugins/skills/benchmark-executor/SKILL.md +647 -0
  205. package/plugins/skills/benchmark-generator/SKILL.md +349 -0
  206. package/plugins/skills/delivery-stage/SKILL.md +203 -0
  207. package/plugins/skills/design-stage/SKILL.md +216 -0
  208. package/plugins/skills/evolution-process/SKILL.md +291 -0
  209. package/plugins/skills/exploration-phase/SKILL.md +133 -0
  210. package/plugins/skills/implementation-stage/SKILL.md +179 -0
  211. package/plugins/skills/layer1-validation/SKILL.md +79 -0
  212. package/plugins/skills/pending-dashboard/SKILL.md +109 -0
  213. package/plugins/skills/project-evolution/SKILL.md +847 -0
  214. package/plugins/skills/requirement-stage/SKILL.md +183 -0
  215. package/plugins/skills/skill-forge/SKILL.md +223 -0
  216. package/plugins/skills/skill-forge/references/description-guide.md +92 -0
  217. package/plugins/skills/skill-forge/references/quality-rubric.md +104 -0
  218. package/plugins/skills/skill-forge/references/skill-template.md +106 -0
  219. package/plugins/skills/startup-guard/SKILL.md +38 -0
  220. package/plugins/skills/testing-stage/SKILL.md +195 -0
  221. package/scripts/cli/global-init.js +288 -0
  222. package/scripts/cli/global.js +324 -0
  223. package/scripts/cli/index.js +55 -0
  224. package/scripts/cli/init.js +382 -0
  225. package/scripts/cli/list.js +69 -0
  226. package/scripts/cli/org.js +340 -0
  227. package/scripts/cli/update.js +44 -0
  228. package/scripts/config/commands.config.js +145 -0
  229. package/scripts/config/hooks.config.js +197 -0
  230. package/scripts/evolution/evolution-router.js +273 -0
  231. package/scripts/evolution/evolution-signal-collector.js +307 -0
  232. package/scripts/evolution/knowledge-loader.js +346 -0
  233. package/scripts/evolution/marketplace.js +317 -0
  234. package/scripts/evolution/version-manager.js +371 -0
  235. package/scripts/install/agents.js +106 -0
  236. package/scripts/install/commands.js +133 -0
  237. package/scripts/install/constants.js +424 -0
  238. package/scripts/install/hook-logger.js +536 -0
  239. package/scripts/install/hooks.js +110 -0
  240. package/scripts/install/index.js +39 -0
  241. package/scripts/install/skills.js +95 -0
  242. package/scripts/postinstall.js +25 -0
  243. package/scripts/state.js +376 -0
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Marketplace - 插件市场集成
3
+ *
4
+ * 实现插件市场发布接口、搜索/安装、生成兼容 Claude Code 的 plugin.json
5
+ */
6
+
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import os from 'os';
10
+ import {
11
+ GLOBAL_AUTOSPEC_DIR,
12
+ KNOWLEDGE_SCOPE
13
+ } from '../install/constants.js';
14
+ import { getLatestSkillVersion, listSkillVersions, getVersionHistory } from './version-manager.js';
15
+
16
+ /**
17
+ * 获取市场目录
18
+ * @returns {string} 市场目录
19
+ */
20
+ function getMarketplaceDir() {
21
+ return path.join(os.homedir(), '.claude/autospec/marketplace');
22
+ }
23
+
24
+ /**
25
+ * 获取市场索引文件路径
26
+ * @returns {string} 索引文件路径
27
+ */
28
+ function getMarketplaceIndexPath() {
29
+ return path.join(getMarketplaceDir(), 'index.json');
30
+ }
31
+
32
+ /**
33
+ * 安全地读取 JSON 文件
34
+ * @param {string} filePath - 文件路径
35
+ * @param {any} defaultValue - 默认值
36
+ * @returns {any} 解析后的数据
37
+ */
38
+ function safeReadJson(filePath, defaultValue = null) {
39
+ try {
40
+ if (!fs.existsSync(filePath)) {
41
+ return defaultValue;
42
+ }
43
+ const content = fs.readFileSync(filePath, 'utf-8');
44
+ return JSON.parse(content);
45
+ } catch (e) {
46
+ return defaultValue;
47
+ }
48
+ }
49
+
50
+ /**
51
+ * 安全地写入 JSON 文件
52
+ * @param {string} filePath - 文件路径
53
+ * @param {any} data - 数据
54
+ * @returns {boolean} 是否成功
55
+ */
56
+ function safeWriteJson(filePath, data) {
57
+ try {
58
+ const dir = path.dirname(filePath);
59
+ if (!fs.existsSync(dir)) {
60
+ fs.mkdirSync(dir, { recursive: true });
61
+ }
62
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
63
+ return true;
64
+ } catch (e) {
65
+ return false;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * 生成 plugin.json(Claude Code 格式)
71
+ *
72
+ * @param {string} skillName - 技能名称
73
+ * @param {Object} options - 选项
74
+ * @returns {Object} plugin.json 内容
75
+ */
76
+ export function generatePluginJson(skillName, options = {}) {
77
+ const { version = '1.0.0', description = '', author = '', namespace = 'autospec' } = options;
78
+
79
+ // 获取技能内容
80
+ const content = getLatestSkillVersion(skillName);
81
+ const versions = listSkillVersions(skillName);
82
+
83
+ // 从技能内容中提取描述
84
+ let skillDescription = description;
85
+ if (!skillDescription && content) {
86
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
87
+ if (match) {
88
+ const frontmatter = match[1];
89
+ const descMatch = frontmatter.match(/description:\s*(.+)/);
90
+ if (descMatch) {
91
+ skillDescription = descMatch[1].trim();
92
+ }
93
+ }
94
+ }
95
+
96
+ return {
97
+ name: `${namespace}-${skillName}`,
98
+ version,
99
+ namespace,
100
+ description: skillDescription || `${skillName} skill`,
101
+ skills: [
102
+ {
103
+ name: skillName,
104
+ path: `skills/${skillName}/SKILL.md`,
105
+ versions: versions.map(v => v.version)
106
+ }
107
+ ],
108
+ author: author || 'AutoSpec User',
109
+ releasedAt: new Date().toISOString()
110
+ };
111
+ }
112
+
113
+ /**
114
+ * 发布到市场
115
+ *
116
+ * @param {string} skillName - 技能名称
117
+ * @param {Object} options - 选项
118
+ * @returns {Object} 发布结果 { success, marketplaceUrl }
119
+ */
120
+ export function publishToMarketplace(skillName, options = {}) {
121
+ const { version = '1.0.0', description = '', author = '', isPublic = false } = options;
122
+
123
+ const marketplaceDir = getMarketplaceDir();
124
+ const skillMarketplaceDir = path.join(marketplaceDir, skillName);
125
+
126
+ try {
127
+ // 创建技能市场目录
128
+ if (!fs.existsSync(skillMarketplaceDir)) {
129
+ fs.mkdirSync(skillMarketplaceDir, { recursive: true });
130
+ }
131
+
132
+ // 获取最新版本内容
133
+ const content = getLatestSkillVersion(skillName);
134
+ if (!content) {
135
+ return { success: false, error: '技能不存在或无法获取内容' };
136
+ }
137
+
138
+ // 写入技能文件
139
+ const skillPath = path.join(skillMarketplaceDir, 'SKILL.md');
140
+ fs.writeFileSync(skillPath, content);
141
+
142
+ // 生成并写入 plugin.json
143
+ const pluginJson = generatePluginJson(skillName, { version, description, author });
144
+ const pluginPath = path.join(skillMarketplaceDir, 'plugin.json');
145
+ safeWriteJson(pluginPath, pluginJson);
146
+
147
+ // 更新市场索引
148
+ const indexPath = getMarketplaceIndexPath();
149
+ const index = safeReadJson(indexPath, { skills: [], lastUpdated: null });
150
+
151
+ const existingIndex = index.skills.findIndex(s => s.name === skillName);
152
+ const skillEntry = {
153
+ name: skillName,
154
+ version,
155
+ description: pluginJson.description,
156
+ author,
157
+ isPublic,
158
+ publishedAt: new Date().toISOString()
159
+ };
160
+
161
+ if (existingIndex >= 0) {
162
+ index.skills[existingIndex] = skillEntry;
163
+ } else {
164
+ index.skills.push(skillEntry);
165
+ }
166
+
167
+ index.lastUpdated = new Date().toISOString();
168
+ safeWriteJson(indexPath, index);
169
+
170
+ // 生成市场 URL(本地路径)
171
+ const marketplaceUrl = `file://${skillMarketplaceDir}`;
172
+
173
+ return {
174
+ success: true,
175
+ marketplaceUrl,
176
+ skillName,
177
+ version
178
+ };
179
+ } catch (e) {
180
+ return {
181
+ success: false,
182
+ error: e.message
183
+ };
184
+ }
185
+ }
186
+
187
+ /**
188
+ * 从市场安装技能
189
+ *
190
+ * @param {string} skillName - 技能名称
191
+ * @param {Object} options - 选项
192
+ * @returns {Object} 安装结果 { success, path }
193
+ */
194
+ export function installFromMarketplace(skillName, options = {}) {
195
+ const { targetScope = KNOWLEDGE_SCOPE.GLOBAL, orgName = null } = options;
196
+
197
+ const marketplaceDir = getMarketplaceDir();
198
+ const skillMarketplaceDir = path.join(marketplaceDir, skillName);
199
+ const skillPath = path.join(skillMarketplaceDir, 'SKILL.md');
200
+
201
+ if (!fs.existsSync(skillPath)) {
202
+ return { success: false, error: '市场技能不存在' };
203
+ }
204
+
205
+ try {
206
+ // 读取市场技能内容
207
+ const content = fs.readFileSync(skillPath, 'utf-8');
208
+
209
+ // 目标目录
210
+ const targetDir = targetScope === KNOWLEDGE_SCOPE.ORG
211
+ ? path.join(os.homedir(), '.claude/autospec/orgs', orgName, 'skills')
212
+ : path.join(os.homedir(), GLOBAL_AUTOSPEC_DIR, 'skills');
213
+
214
+ const targetPath = path.join(targetDir, skillName);
215
+
216
+ // 创建目标目录
217
+ if (!fs.existsSync(targetPath)) {
218
+ fs.mkdirSync(targetPath, { recursive: true });
219
+ }
220
+
221
+ // 写入技能文件
222
+ const targetSkillPath = path.join(targetPath, 'SKILL.md');
223
+ fs.writeFileSync(targetSkillPath, content);
224
+
225
+ return {
226
+ success: true,
227
+ path: targetSkillPath
228
+ };
229
+ } catch (e) {
230
+ return {
231
+ success: false,
232
+ error: e.message
233
+ };
234
+ }
235
+ }
236
+
237
+ /**
238
+ * 搜索市场技能
239
+ *
240
+ * @param {string} query - 搜索关键词
241
+ * @returns {Array} 搜索结果
242
+ */
243
+ export function searchMarketplace(query) {
244
+ const indexPath = getMarketplaceIndexPath();
245
+ const index = safeReadJson(indexPath, { skills: [] });
246
+
247
+ if (!query) {
248
+ return index.skills;
249
+ }
250
+
251
+ const queryLower = query.toLowerCase();
252
+
253
+ return index.skills.filter(skill =>
254
+ skill.name.toLowerCase().includes(queryLower) ||
255
+ (skill.description && skill.description.toLowerCase().includes(queryLower))
256
+ );
257
+ }
258
+
259
+ /**
260
+ * 获取市场技能列表
261
+ *
262
+ * @returns {Array} 技能列表
263
+ */
264
+ export function listMarketplaceSkills() {
265
+ const indexPath = getMarketplaceIndexPath();
266
+ const index = safeReadJson(indexPath, { skills: [], lastUpdated: null });
267
+
268
+ return {
269
+ skills: index.skills,
270
+ lastUpdated: index.lastUpdated,
271
+ count: index.skills.length
272
+ };
273
+ }
274
+
275
+ /**
276
+ * 从市场移除技能
277
+ *
278
+ * @param {string} skillName - 技能名称
279
+ * @returns {Object} 移除结果
280
+ */
281
+ export function removeFromMarketplace(skillName) {
282
+ const marketplaceDir = getMarketplaceDir();
283
+ const skillMarketplaceDir = path.join(marketplaceDir, skillName);
284
+
285
+ if (!fs.existsSync(skillMarketplaceDir)) {
286
+ return { success: false, error: '市场技能不存在' };
287
+ }
288
+
289
+ try {
290
+ // 删除技能目录
291
+ fs.rmSync(skillMarketplaceDir, { recursive: true });
292
+
293
+ // 更新市场索引
294
+ const indexPath = getMarketplaceIndexPath();
295
+ const index = safeReadJson(indexPath, { skills: [], lastUpdated: null });
296
+
297
+ index.skills = index.skills.filter(s => s.name !== skillName);
298
+ index.lastUpdated = new Date().toISOString();
299
+ safeWriteJson(indexPath, index);
300
+
301
+ return { success: true };
302
+ } catch (e) {
303
+ return {
304
+ success: false,
305
+ error: e.message
306
+ };
307
+ }
308
+ }
309
+
310
+ export default {
311
+ generatePluginJson,
312
+ publishToMarketplace,
313
+ installFromMarketplace,
314
+ searchMarketplace,
315
+ listMarketplaceSkills,
316
+ removeFromMarketplace
317
+ };
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Version Manager - 版本管理器
3
+ *
4
+ * 实现版本标签管理、回滚逻辑、历史查询
5
+ */
6
+
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import os from 'os';
10
+ import {
11
+ GLOBAL_AUTOSPEC_DIR,
12
+ KNOWLEDGE_SCOPE
13
+ } from '../install/constants.js';
14
+
15
+ /**
16
+ * 获取全局技能目录
17
+ * @returns {string} 全局技能目录
18
+ */
19
+ function getGlobalSkillsDir() {
20
+ return path.join(os.homedir(), GLOBAL_AUTOSPEC_DIR, 'skills');
21
+ }
22
+
23
+ /**
24
+ * 获取组织技能目录
25
+ * @param {string} orgName - 组织名称
26
+ * @returns {string} 组织技能目录
27
+ */
28
+ function getOrgSkillsDir(orgName) {
29
+ return path.join(os.homedir(), '.claude/autospec/orgs', orgName, 'skills');
30
+ }
31
+
32
+ /**
33
+ * 安全地读取 JSON 文件
34
+ * @param {string} filePath - 文件路径
35
+ * @param {any} defaultValue - 默认值
36
+ * @returns {any} 解析后的数据
37
+ */
38
+ function safeReadJson(filePath, defaultValue = null) {
39
+ try {
40
+ if (!fs.existsSync(filePath)) {
41
+ return defaultValue;
42
+ }
43
+ const content = fs.readFileSync(filePath, 'utf-8');
44
+ return JSON.parse(content);
45
+ } catch (e) {
46
+ return defaultValue;
47
+ }
48
+ }
49
+
50
+ /**
51
+ * 安全地写入 JSON 文件
52
+ * @param {string} filePath - 文件路径
53
+ * @param {any} data - 数据
54
+ * @returns {boolean} 是否成功
55
+ */
56
+ function safeWriteJson(filePath, data) {
57
+ try {
58
+ const dir = path.dirname(filePath);
59
+ if (!fs.existsSync(dir)) {
60
+ fs.mkdirSync(dir, { recursive: true });
61
+ }
62
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
63
+ return true;
64
+ } catch (e) {
65
+ return false;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * 解析版本号
71
+ * @param {string} version - 版本号字符串
72
+ * @returns {Object} 解析结果 { major, minor, patch, raw }
73
+ */
74
+ function parseVersion(version) {
75
+ const match = version.match(/^v?(\d+)\.(\d+)\.(\d+)$/);
76
+ if (match) {
77
+ return {
78
+ major: parseInt(match[1], 10),
79
+ minor: parseInt(match[2], 10),
80
+ patch: parseInt(match[3], 10),
81
+ raw: version
82
+ };
83
+ }
84
+ return { major: 0, minor: 0, patch: 0, raw: version };
85
+ }
86
+
87
+ /**
88
+ * 比较版本号
89
+ * @param {string} v1 - 版本1
90
+ * @param {string} v2 - 版本2
91
+ * @returns {number} -1: v1 < v2, 0: v1 = v2, 1: v1 > v2
92
+ */
93
+ function compareVersions(v1, v2) {
94
+ const p1 = parseVersion(v1);
95
+ const p2 = parseVersion(v2);
96
+
97
+ if (p1.major !== p2.major) return p1.major - p2.major;
98
+ if (p1.minor !== p2.minor) return p1.minor - p2.minor;
99
+ return p1.patch - p2.patch;
100
+ }
101
+
102
+ /**
103
+ * 获取技能版本目录
104
+ * @param {string} skillName - 技能名称
105
+ * @param {string} scope - 作用域
106
+ * @param {string} orgName - 组织名称
107
+ * @returns {string} 技能版本目录
108
+ */
109
+ function getSkillVersionDir(skillName, scope, orgName = null) {
110
+ const baseDir = scope === KNOWLEDGE_SCOPE.ORG
111
+ ? getOrgSkillsDir(orgName)
112
+ : getGlobalSkillsDir();
113
+
114
+ return path.join(baseDir, skillName);
115
+ }
116
+
117
+ /**
118
+ * 发布技能新版本
119
+ *
120
+ * @param {string} skillName - 技能名称
121
+ * @param {string} content - 技能内容
122
+ * @param {Object} options - 选项
123
+ * @returns {Object} 发布结果 { success, version, path }
124
+ */
125
+ export function publishSkillVersion(skillName, content, options = {}) {
126
+ const { scope = KNOWLEDGE_SCOPE.GLOBAL, orgName = null, version = null, message = '' } = options;
127
+
128
+ const versionDir = getSkillVersionDir(skillName, scope, orgName);
129
+
130
+ // 确定版本号
131
+ const newVersion = version || getNextVersion(skillName, scope, orgName);
132
+ const versionPath = path.join(versionDir, `v${newVersion}`);
133
+
134
+ try {
135
+ // 创建版本目录
136
+ if (!fs.existsSync(versionPath)) {
137
+ fs.mkdirSync(versionPath, { recursive: true });
138
+ }
139
+
140
+ // 写入技能文件
141
+ const skillFilePath = path.join(versionPath, 'SKILL.md');
142
+ fs.writeFileSync(skillFilePath, content);
143
+
144
+ // 更新版本历史
145
+ const historyFilePath = path.join(versionDir, 'versions.json');
146
+ const history = safeReadJson(historyFilePath, { versions: [], latest: null });
147
+
148
+ history.versions = history.versions || [];
149
+ history.versions.push({
150
+ version: newVersion,
151
+ releasedAt: new Date().toISOString(),
152
+ message: message || `Release v${newVersion}`
153
+ });
154
+ history.latest = newVersion;
155
+
156
+ safeWriteJson(historyFilePath, history);
157
+
158
+ // 更新 latest 符号链接
159
+ const latestLink = path.join(versionDir, 'latest');
160
+ if (fs.existsSync(latestLink)) {
161
+ fs.unlinkSync(latestLink);
162
+ }
163
+ // 注意:符号链接创建可能需要管理员权限,这里用副本代替
164
+ fs.copyFileSync(skillFilePath, path.join(versionDir, 'SKILL.md'));
165
+
166
+ return {
167
+ success: true,
168
+ version: newVersion,
169
+ path: skillFilePath
170
+ };
171
+ } catch (e) {
172
+ return {
173
+ success: false,
174
+ error: e.message
175
+ };
176
+ }
177
+ }
178
+
179
+ /**
180
+ * 获取下一个版本号
181
+ * @param {string} skillName - 技能名称
182
+ * @param {string} scope - 作用域
183
+ * @param {string} orgName - 组织名称
184
+ * @returns {string} 下一个版本号
185
+ */
186
+ function getNextVersion(skillName, scope, orgName = null) {
187
+ const versionDir = getSkillVersionDir(skillName, scope, orgName);
188
+ const historyFilePath = path.join(versionDir, 'versions.json');
189
+ const history = safeReadJson(historyFilePath, { versions: [] });
190
+
191
+ if (!history.versions || history.versions.length === 0) {
192
+ return '1.0.0';
193
+ }
194
+
195
+ // 获取最新版本
196
+ const latestVersion = history.versions[history.versions.length - 1].version;
197
+ const parsed = parseVersion(latestVersion);
198
+
199
+ // 递增 patch 版本
200
+ parsed.patch += 1;
201
+
202
+ return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
203
+ }
204
+
205
+ /**
206
+ * 回滚到指定版本
207
+ *
208
+ * @param {string} skillName - 技能名称
209
+ * @param {string} targetVersion - 目标版本
210
+ * @param {Object} options - 选项
211
+ * @returns {Object} 回滚结果 { success, version }
212
+ */
213
+ export function rollbackSkillVersion(skillName, targetVersion, options = {}) {
214
+ const { scope = KNOWLEDGE_SCOPE.GLOBAL, orgName = null } = options;
215
+
216
+ const versionDir = getSkillVersionDir(skillName, scope, orgName);
217
+ const versionPath = path.join(versionDir, `v${targetVersion}`);
218
+ const skillFilePath = path.join(versionPath, 'SKILL.md');
219
+
220
+ if (!fs.existsSync(skillFilePath)) {
221
+ return { success: false, error: `版本 v${targetVersion} 不存在` };
222
+ }
223
+
224
+ try {
225
+ // 读取目标版本内容
226
+ const content = fs.readFileSync(skillFilePath, 'utf-8');
227
+
228
+ // 写入当前版本(覆盖 latest)
229
+ const latestPath = path.join(versionDir, 'SKILL.md');
230
+ fs.writeFileSync(latestPath, content);
231
+
232
+ // 记录回滚历史
233
+ const historyFilePath = path.join(versionDir, 'versions.json');
234
+ const history = safeReadJson(historyFilePath, { versions: [], latest: null });
235
+
236
+ history.versions.push({
237
+ version: targetVersion,
238
+ action: 'rollback',
239
+ rolledBackAt: new Date().toISOString()
240
+ });
241
+ history.latest = targetVersion;
242
+
243
+ safeWriteJson(historyFilePath, history);
244
+
245
+ return {
246
+ success: true,
247
+ version: targetVersion
248
+ };
249
+ } catch (e) {
250
+ return {
251
+ success: false,
252
+ error: e.message
253
+ };
254
+ }
255
+ }
256
+
257
+ /**
258
+ * 获取版本历史
259
+ *
260
+ * @param {string} skillName - 技能名称
261
+ * @param {Object} options - 选项
262
+ * @returns {Object} 版本历史
263
+ */
264
+ export function getVersionHistory(skillName, options = {}) {
265
+ const { scope = KNOWLEDGE_SCOPE.GLOBAL, orgName = null } = options;
266
+
267
+ const versionDir = getSkillVersionDir(skillName, scope, orgName);
268
+ const historyFilePath = path.join(versionDir, 'versions.json');
269
+
270
+ return safeReadJson(historyFilePath, { versions: [], latest: null });
271
+ }
272
+
273
+ /**
274
+ * 获取所有版本列表
275
+ *
276
+ * @param {string} skillName - 技能名称
277
+ * @param {Object} options - 选项
278
+ * @returns {Array} 版本列表
279
+ */
280
+ export function listSkillVersions(skillName, options = {}) {
281
+ const { scope = KNOWLEDGE_SCOPE.GLOBAL, orgName = null } = options;
282
+
283
+ const versionDir = getSkillVersionDir(skillName, scope, orgName);
284
+
285
+ if (!fs.existsSync(versionDir)) {
286
+ return [];
287
+ }
288
+
289
+ const entries = fs.readdirSync(versionDir, { withFileTypes: true });
290
+ const versions = [];
291
+
292
+ for (const entry of entries) {
293
+ if (entry.isDirectory() && entry.name.startsWith('v')) {
294
+ const versionPath = path.join(versionDir, entry.name, 'SKILL.md');
295
+ if (fs.existsSync(versionPath)) {
296
+ const stats = fs.statSync(versionPath);
297
+ versions.push({
298
+ version: entry.name.substring(1), // 去掉 'v' 前缀
299
+ path: versionPath,
300
+ releasedAt: stats.mtime.toISOString()
301
+ });
302
+ }
303
+ }
304
+ }
305
+
306
+ // 按版本号排序
307
+ return versions.sort((a, b) => compareVersions(b.version, a.version));
308
+ }
309
+
310
+ /**
311
+ * 获取指定版本内容
312
+ *
313
+ * @param {string} skillName - 技能名称
314
+ * @param {string} version - 版本号
315
+ * @param {Object} options - 选项
316
+ * @returns {string|null} 技能内容
317
+ */
318
+ export function getSkillVersion(skillName, version, options = {}) {
319
+ const { scope = KNOWLEDGE_SCOPE.GLOBAL, orgName = null } = options;
320
+
321
+ const versionDir = getSkillVersionDir(skillName, scope, orgName);
322
+ const skillFilePath = path.join(versionDir, `v${version}`, 'SKILL.md');
323
+
324
+ try {
325
+ if (fs.existsSync(skillFilePath)) {
326
+ return fs.readFileSync(skillFilePath, 'utf-8');
327
+ }
328
+ return null;
329
+ } catch (e) {
330
+ return null;
331
+ }
332
+ }
333
+
334
+ /**
335
+ * 获取最新版本内容
336
+ *
337
+ * @param {string} skillName - 技能名称
338
+ * @param {Object} options - 选项
339
+ * @returns {string|null} 技能内容
340
+ */
341
+ export function getLatestSkillVersion(skillName, options = {}) {
342
+ const { scope = KNOWLEDGE_SCOPE.GLOBAL, orgName = null } = options;
343
+
344
+ const versionDir = getSkillVersionDir(skillName, scope, orgName);
345
+ const latestPath = path.join(versionDir, 'SKILL.md');
346
+
347
+ try {
348
+ if (fs.existsSync(latestPath)) {
349
+ return fs.readFileSync(latestPath, 'utf-8');
350
+ }
351
+
352
+ // 尝试从 versions.json 获取最新版本
353
+ const history = getVersionHistory(skillName, { scope, orgName });
354
+ if (history.latest) {
355
+ return getSkillVersion(skillName, history.latest, { scope, orgName });
356
+ }
357
+
358
+ return null;
359
+ } catch (e) {
360
+ return null;
361
+ }
362
+ }
363
+
364
+ export default {
365
+ publishSkillVersion,
366
+ rollbackSkillVersion,
367
+ getVersionHistory,
368
+ listSkillVersions,
369
+ getSkillVersion,
370
+ getLatestSkillVersion
371
+ };