dsh-skill-hub 0.3.7 → 0.3.8

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 (109) hide show
  1. package/README.md +40 -50
  2. package/README.zh.md +38 -48
  3. package/lib/client.js +2209 -1820
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +653 -419
  6. package/lib/types/client/SkillHubSettingsCard.d.ts +1 -0
  7. package/lib/types/client/api.d.ts +12 -6
  8. package/lib/types/client/helpers.d.ts +0 -1
  9. package/lib/types/client/locales/common.d.ts +52 -0
  10. package/lib/types/client/locales/detail.d.ts +16 -0
  11. package/lib/types/client/locales/market.d.ts +73 -0
  12. package/lib/types/client/locales/settings.d.ts +41 -0
  13. package/lib/types/client/locales/skills.d.ts +65 -0
  14. package/lib/types/client/locales/sources.d.ts +35 -0
  15. package/lib/types/client/locales.d.ts +124 -118
  16. package/lib/types/client/panel/MarketSourceRow.d.ts +12 -0
  17. package/lib/types/client/panel/MarketView.d.ts +1 -0
  18. package/lib/types/client/panel/RepoScanCard.d.ts +10 -0
  19. package/lib/types/client/panel/hooks/shared.d.ts +72 -0
  20. package/lib/types/client/panel/hooks/useCatalogFlow.d.ts +62 -0
  21. package/lib/types/client/panel/hooks/useGroupFlow.d.ts +41 -0
  22. package/lib/types/client/panel/hooks/useMarketFlow.d.ts +73 -0
  23. package/lib/types/client/panel/hooks/useMetaFlow.d.ts +18 -0
  24. package/lib/types/client/panel/hooks/useSourceFlow.d.ts +44 -0
  25. package/lib/types/client/panel/market-format.d.ts +6 -0
  26. package/lib/types/client/panel/useSkillHub.d.ts +45 -73
  27. package/lib/types/client/settings-card.d.ts +20 -0
  28. package/lib/types/client/settings-form.d.ts +6 -0
  29. package/lib/types/protocol/api.d.ts +38 -0
  30. package/lib/types/protocol/catalog.d.ts +155 -0
  31. package/lib/types/protocol/config.d.ts +113 -0
  32. package/lib/types/protocol/groups.d.ts +95 -0
  33. package/lib/types/protocol/market.d.ts +94 -0
  34. package/lib/types/protocol/repo.d.ts +107 -0
  35. package/lib/types/protocol/sources.d.ts +139 -0
  36. package/lib/types/protocol/stats.d.ts +46 -0
  37. package/lib/types/protocol.d.ts +13 -743
  38. package/lib/types/repo/github-client.d.ts +42 -0
  39. package/lib/types/repo.d.ts +6 -17
  40. package/lib/types/routes/catalog.d.ts +7 -0
  41. package/lib/types/routes/config.d.ts +7 -0
  42. package/lib/types/routes/groups.d.ts +7 -0
  43. package/lib/types/routes/helpers.d.ts +145 -0
  44. package/lib/types/routes/market.d.ts +8 -0
  45. package/lib/types/routes/repo-import.d.ts +7 -0
  46. package/lib/types/routes/route-state.d.ts +55 -0
  47. package/lib/types/routes/sources.d.ts +8 -0
  48. package/lib/types/routes.d.ts +5 -34
  49. package/lib/types/stats.d.ts +3 -2
  50. package/lib/types/store/errors.d.ts +10 -0
  51. package/lib/types/store/migrate.d.ts +44 -0
  52. package/lib/types/store/paths.d.ts +32 -0
  53. package/lib/types/store/store.d.ts +133 -0
  54. package/lib/types/store.d.ts +7 -146
  55. package/package.json +28 -27
  56. package/src/client/SkillHubSettingsCard.tsx +17 -3
  57. package/src/client/api.ts +101 -195
  58. package/src/client/helpers.ts +10 -1
  59. package/src/client/locales/common.ts +102 -0
  60. package/src/client/locales/detail.ts +30 -0
  61. package/src/client/locales/market.ts +144 -0
  62. package/src/client/locales/settings.ts +80 -0
  63. package/src/client/locales/skills.ts +128 -0
  64. package/src/client/locales/sources.ts +68 -0
  65. package/src/client/locales.ts +26 -512
  66. package/src/client/panel/MarketSourceRow.tsx +108 -0
  67. package/src/client/panel/MarketView.tsx +12 -253
  68. package/src/client/panel/RepoScanCard.tsx +171 -0
  69. package/src/client/panel/hooks/shared.ts +81 -0
  70. package/src/client/panel/hooks/useCatalogFlow.ts +211 -0
  71. package/src/client/panel/hooks/useGroupFlow.ts +240 -0
  72. package/src/client/panel/hooks/useMarketFlow.ts +421 -0
  73. package/src/client/panel/hooks/useMetaFlow.ts +58 -0
  74. package/src/client/panel/hooks/useSourceFlow.ts +193 -0
  75. package/src/client/panel/market-format.ts +22 -0
  76. package/src/client/panel/useSkillHub.ts +141 -1032
  77. package/src/client/settings-card.tsx +51 -0
  78. package/src/client/settings-form.ts +18 -0
  79. package/src/index.ts +14 -4
  80. package/src/protocol/api.ts +38 -0
  81. package/src/protocol/catalog.ts +168 -0
  82. package/src/protocol/config.ts +145 -0
  83. package/src/protocol/groups.ts +106 -0
  84. package/src/protocol/market.ts +100 -0
  85. package/src/protocol/repo.ts +104 -0
  86. package/src/protocol/sources.ts +146 -0
  87. package/src/protocol/stats.ts +42 -0
  88. package/src/protocol.ts +83 -809
  89. package/src/repo/github-client.ts +131 -0
  90. package/src/repo.test.ts +24 -1
  91. package/src/repo.ts +50 -170
  92. package/src/routes/catalog.ts +309 -0
  93. package/src/routes/config.ts +119 -0
  94. package/src/routes/groups.ts +133 -0
  95. package/src/routes/helpers.ts +489 -0
  96. package/src/routes/market.ts +255 -0
  97. package/src/routes/repo-import.ts +267 -0
  98. package/src/routes/route-state.ts +89 -0
  99. package/src/routes/sources.ts +318 -0
  100. package/src/routes.test.ts +20 -0
  101. package/src/routes.ts +21 -1699
  102. package/src/stats.test.ts +58 -3
  103. package/src/stats.ts +45 -16
  104. package/src/store/errors.ts +14 -0
  105. package/src/store/migrate.ts +272 -0
  106. package/src/store/paths.ts +43 -0
  107. package/src/store/store.ts +532 -0
  108. package/src/store.test.ts +18 -0
  109. package/src/store.ts +7 -737
package/src/protocol.ts CHANGED
@@ -3,814 +3,88 @@
3
3
  * both the host half and the browser half import. The browser half must never
4
4
  * depend on host SDK packages, so registry types are re-spelled here as
5
5
  * plain JSON-safe interfaces.
6
+ *
7
+ * 按域拆分后的重导出入口:老 `from './protocol.ts'` 写法保持可用,
8
+ * 新代码可按需直引 `from './protocol/<domain>.ts'`。
6
9
  */
7
10
 
8
- /** Browser-facing base paths of the skill-hub API family. */
9
- export const SKILL_HUB_API = {
10
- catalog: '/api/skill-hub/catalog',
11
- skill: '/api/skill-hub/skill',
12
- skillDelete: '/api/skill-hub/skill/delete',
13
- toggle: '/api/skill-hub/toggle',
14
- toggleBatch: '/api/skill-hub/toggle-batch',
15
- create: '/api/skill-hub/create',
16
- stats: '/api/skill-hub/stats',
17
- config: '/api/skill-hub/config',
18
- market: '/api/skill-hub/market',
19
- marketSource: '/api/skill-hub/market/source',
20
- marketSourceDelete: '/api/skill-hub/market/source/delete',
21
- marketSourceRef: '/api/skill-hub/market/source/ref',
22
- marketCheck: '/api/skill-hub/market/check',
23
- marketSync: '/api/skill-hub/market/source/sync',
24
- repo: '/api/skill-hub/repo',
25
- repoImport: '/api/skill-hub/repo/import',
26
- repoImportProgress: '/api/skill-hub/repo/import/progress',
27
- repoImportCancel: '/api/skill-hub/repo/import/cancel',
28
- update: '/api/skill-hub/update',
29
- groups: '/api/skill-hub/groups',
30
- tag: '/api/skill-hub/tag',
31
- tagDelete: '/api/skill-hub/tag/delete',
32
- tagMembers: '/api/skill-hub/tag/members',
33
- tagReorder: '/api/skill-hub/tag/reorder',
34
- collectionReorder: '/api/skill-hub/collections/reorder',
35
- sourceGroupReorder: '/api/skill-hub/source-groups/reorder',
36
- sources: '/api/skill-hub/sources',
37
- sourceCheck: '/api/skill-hub/sources/check',
38
- sourceSync: '/api/skill-hub/sources/sync',
39
- sourceDelete: '/api/skill-hub/sources/delete',
40
- sourceRestore: '/api/skill-hub/sources/restore',
41
- sourceTrashClear: '/api/skill-hub/sources/trash/clear',
42
- diagnosticFix: '/api/skill-hub/diagnostic/fix',
43
- marketSourceVersions: '/api/skill-hub/market/source/versions',
44
- } as const
45
-
46
- /** User-level roots the hub may write to (matches dsh-skill-filesystem ranks 400/500). */
47
- export type WritableRoot = 'user-dsh' | 'user-agents'
48
-
49
- /** Invocation policy resolved by the registry, re-spelled for the wire. */
50
- export interface HubInvocation {
51
- /** Whether model-facing catalogs may load this skill. */
52
- modelInvocable: boolean
53
- /** Whether human-facing command catalogs may load this skill. */
54
- userInvocable: boolean
55
- }
56
-
57
- /** One enabled skill row in the catalog. */
58
- export interface CatalogSkill {
59
- name: string
60
- description: string
61
- whenToUse?: string
62
- invocation: HubInvocation
63
- provider: string
64
- /** Whether the hub may toggle this skill (user-level filesystem skills only). */
65
- writable: boolean
66
- /** 技能来源标识(user-dsh/user-agents/project-dsh/project-agents/...)。 */
67
- source: string
68
- /** SKILL.md creation time (epoch ms); used for "added" sorting. Absent when unknown. */
69
- addedAt?: number
70
- /** SKILL.md last-modified time (epoch ms); used for "updated" display. Absent when unknown. */
71
- updatedAt?: number
72
- /** 项目技能的所属工作区路径(仅 project-dsh/project-agents 来源携带)。 */
73
- workspace?: string
74
- /** 工作区显示标题(来自 workspace.json;无则回退为路径)。 */
75
- workspaceTitle?: string
76
- /** UI metadata from agents/openai.yaml (mirrors codex SkillInterface). */
77
- displayName?: string
78
- shortDescription?: string
79
- brandColor?: string
80
- iconSmall?: string
81
- iconLarge?: string
82
- defaultPrompt?: string
83
- }
84
-
85
- /** One disabled skill tracked by the hub sidecar (SKILL.md renamed away). */
86
- export interface DisabledSkill {
87
- name: string
88
- description: string
89
- /** Absolute path of the renamed file (SKILL.md.disabled / <name>.md.disabled). */
90
- path: string
91
- root: WritableRoot
92
- disabledAt: number
93
- }
94
-
95
- /** One discovery diagnostic: a file the filesystem provider skips, with the reason. */
96
- export interface DiagnosticEntry {
97
- path: string
98
- root: string
99
- reason: string
100
- /** Whether this diagnostic can be auto-fixed (e.g. unquoted colon). */
101
- fixable?: boolean
102
- }
103
-
104
- /** POST /api/skill-hub/diagnostic/fix — repair a fixable diagnostic in place. */
105
- export interface DiagnosticFixRequest {
106
- path: string
107
- }
108
- export interface DiagnosticFixResponse {
109
- ok: true
110
- path: string
111
- }
112
-
113
- /** GET /api/skill-hub/catalog */
114
- export interface CatalogResponse {
115
- ok: true
116
- /** 已安装插件自身的版本号(package.json version),面板标题旁显示。 */
117
- pluginVersion: string
118
- /** Whether discovery completed within a stable catalog revision. */
119
- complete: boolean
120
- /** Sorted winning summaries of every enabled skill (all roots + providers). */
121
- skills: CatalogSkill[]
122
- /** Skills the hub has toggled off (kept outside provider discovery). */
123
- disabled: DisabledSkill[]
124
- /** Files in the writable roots the provider ignores, with reasons. */
125
- diagnostics: DiagnosticEntry[]
126
- /** Skill names that appeared in multiple roots (first wins, others hidden). Mirrors codex name_counts. */
127
- duplicateNames?: string[]
128
- }
129
-
130
- /** GET /api/skill-hub/skill */
131
- export interface SkillDetail {
132
- name: string
133
- description: string
134
- whenToUse?: string
135
- invocation: HubInvocation
136
- provider: string
137
- /** Absolute file path when the skill came from disk. */
138
- path?: string
139
- /** SKILL.md creation time (epoch ms); absent when the file is unreadable. */
140
- addedAt?: number
141
- /** SKILL.md last-modified time (epoch ms); absent when the file is unreadable. */
142
- updatedAt?: number
143
- /** Markdown instruction body. */
144
- content: string
145
- displayName?: string
146
- shortDescription?: string
147
- brandColor?: string
148
- iconSmall?: string
149
- iconLarge?: string
150
- defaultPrompt?: string
151
- }
152
-
153
- export interface SkillDetailResponse {
154
- ok: true
155
- skill: SkillDetail
156
- }
157
-
158
- /** POST /api/skill-hub/skill/delete — 把单个技能移入回收站(可恢复)。 */
159
- export interface SkillDeleteRequest {
160
- name: string
161
- }
162
-
163
- /** POST /api/skill-hub/skill/delete */
164
- export interface SkillDeleteResponse {
165
- ok: true
166
- name: string
167
- /** 移入回收站后的路径(目录或文件)。 */
168
- path: string
169
- }
170
-
171
- /** POST /api/skill-hub/toggle */
172
- export interface ToggleRequest {
173
- /** Kebab-case skill name. */
174
- name: string
175
- /** true re-enables a hub-disabled skill; false disables an enabled one. */
176
- enabled: boolean
177
- }
178
-
179
- export interface ToggleResponse {
180
- ok: true
181
- /** Fresh catalog after the mutation (the filesystem provider may lag a beat). */
182
- catalog: CatalogResponse
183
- }
184
-
185
- /** POST /api/skill-hub/toggle-batch — one group of skills, one write. */
186
- export interface ToggleBatchRequest {
187
- names: string[]
188
- enabled: boolean
189
- }
190
-
191
- /** POST /api/skill-hub/toggle-batch */
192
- export interface ToggleBatchResponse {
193
- ok: true
194
- catalog: CatalogResponse
195
- /** Per-name failures (unknown/read-only skills); empty means all landed. */
196
- failures: Array<{ name: string; error: string }>
197
- }
198
-
199
- /** POST /api/skill-hub/create */
200
- export interface CreateRequest {
201
- /** Kebab-case skill name (validated with the official isSkillName grammar). */
202
- name: string
203
- /** Optional one-line routing description for the frontmatter. */
204
- description?: string
205
- /** Target user root; defaults to user-dsh (~/.dsh/skills). */
206
- root?: WritableRoot
207
- }
208
-
209
- export interface CreateResponse {
210
- ok: true
211
- path: string
212
- root: WritableRoot
213
- }
214
-
215
- /** One skill's invocation stats across the local session logs. */
216
- export interface SkillStat {
217
- /** Kebab-case skill name. */
218
- name: string
219
- /** How many sessions recorded a user-explicit invocation of this skill. */
220
- count: number
221
- /** Unix epoch ms of the most recent invocation (absent when never called). */
222
- lastUsed?: number
223
- }
224
-
225
- /** GET /api/skill-hub/stats */
226
- export interface StatsResponse {
227
- ok: true
228
- /** Whether a session-log source was available (false means counts are empty). */
229
- available: boolean
230
- /** Sorted per-skill invocation counts. */
231
- stats: SkillStat[]
232
- }
233
-
234
- /**
235
- * Persisted incremental-scan checkpoint for the usage statistics (sidecar
236
- * `skillStats` field). Sessions created before `frozenBefore` are treated as
237
- * finalized: their per-session counts live in `frozenSessions` (only sessions
238
- * with at least one invocation are kept) and they are not re-read on
239
- * incremental scans. A daily full reconciliation rebuilds the cache and
240
- * advances the watermark, so a resumed old session is eventually re-counted.
241
- */
242
- export interface SkillStatsCheckpoint {
243
- /** The rolling-window configuration this checkpoint was built for (0 = all history). */
244
- windowDays: number
245
- /** Watermark: every session with header.createdAt < this value is frozen. */
246
- frozenBefore: number
247
- /** Per-session counts of finalized sessions, keyed by session id. */
248
- frozenSessions: Record<string, { createdAt: number; counts: Record<string, { count: number; lastUsed: number }> }>
249
- /** Epoch ms of the last full reconciliation (drives the daily cadence). */
250
- lastFullReconcile: number
251
- }
252
-
253
- /** JSON error body shared by every route. */
254
- export interface ErrorResponse {
255
- error: string
256
- }
257
-
258
- /** The skill hub's own runtime configuration, edited from the settings card. */
259
- export interface HubConfig {
260
- /** Master switch: routes, provider, and announcement all go live with this. */
261
- enabled: boolean
262
- /** When true, a system-prompt section announces the hub to every agent. */
263
- announceToAgent: boolean
264
- /** Model-invocable dot color (#rrggbb); absent means the panel default. */
265
- dotModelColor?: string
266
- /** User-invocable dot color (#rrggbb); absent means the panel default. */
267
- dotUserColor?: string
268
- /** Show per-skill invocation count chip. Default true. */
269
- showUseCount?: boolean
270
- /** Show per-skill last-used relative time. Default true. */
271
- showUseTime?: boolean
272
- /** Show group-header usage summaries (count + last used). Default true. */
273
- showGroupSummary?: boolean
274
- /** 统计滚动窗口天数:只统计最近 N 天的使用;0 = 全部历史。默认 0。 */
275
- statsWindowDays?: number
276
- /** 自动统计扫描间隔(分钟,最小 1)。默认 5。 */
277
- statsScanMinutes?: number
278
- }
279
-
280
- /**
281
- * The resolved shape of the hub's settings namespace (schema defaults, then
282
- * the composition base, then the user layer). Kept as a type alias so the
283
- * browser-side settings scope snapshot is index-compatible with the card
284
- * form's record shape.
285
- */
286
- export type HubSettingsValue = {
287
- enabled: boolean
288
- announceToAgent: boolean
289
- showUseCount: boolean
290
- showUseTime: boolean
291
- showGroupSummary: boolean
292
- /** Model-invocable dot color (#rrggbb); absent means the panel default. */
293
- dotModelColor?: string
294
- /** User-invocable dot color (#rrggbb); absent means the panel default. */
295
- dotUserColor?: string
296
- /** 统计滚动窗口天数(0 = 全部历史)。 */
297
- statsWindowDays?: number
298
- /** 自动统计扫描间隔(分钟)。 */
299
- statsScanMinutes?: number
300
- }
301
-
302
- /**
303
- * Hub config defaults — the single source every layer reads: the cordis
304
- * schema (index.ts), the host's saved-override merge, and the routes'
305
- * fallback view. Changing a default here changes all three.
306
- */
307
- export const HUB_CONFIG_DEFAULTS = {
308
- enabled: true,
309
- announceToAgent: true,
310
- showUseCount: true,
311
- showUseTime: true,
312
- showGroupSummary: true,
313
- statsWindowDays: 14,
314
- statsScanMinutes: 5,
315
- } as const
316
-
317
- /**
318
- * Resolve the effective hub config: saved sidecar overrides win over the
319
- * cordis composition entry (the web card owns runtime config), missing
320
- * booleans fall back to HUB_CONFIG_DEFAULTS, and dot colors pass through
321
- * (saved first, then base) only when set. Numeric stats knobs are clamped to
322
- * their sane ranges (window ≥ 0, scan interval ≥ 1 minute).
323
- */
324
- export function resolveHubConfig(saved: Partial<HubConfig>, base: Partial<HubConfig> = {}): HubConfig {
325
- const dotModelColor = saved.dotModelColor !== undefined ? saved.dotModelColor : base.dotModelColor
326
- const dotUserColor = saved.dotUserColor !== undefined ? saved.dotUserColor : base.dotUserColor
327
- const windowDays = clampNumber(saved.statsWindowDays ?? base.statsWindowDays, 0) ?? HUB_CONFIG_DEFAULTS.statsWindowDays
328
- const scanMinutes = clampNumber(saved.statsScanMinutes ?? base.statsScanMinutes, 1) ?? HUB_CONFIG_DEFAULTS.statsScanMinutes
329
- return {
330
- enabled: saved.enabled ?? base.enabled ?? HUB_CONFIG_DEFAULTS.enabled,
331
- announceToAgent: saved.announceToAgent ?? base.announceToAgent ?? HUB_CONFIG_DEFAULTS.announceToAgent,
332
- showUseCount: saved.showUseCount ?? base.showUseCount ?? HUB_CONFIG_DEFAULTS.showUseCount,
333
- showUseTime: saved.showUseTime ?? base.showUseTime ?? HUB_CONFIG_DEFAULTS.showUseTime,
334
- showGroupSummary: saved.showGroupSummary ?? base.showGroupSummary ?? HUB_CONFIG_DEFAULTS.showGroupSummary,
335
- statsWindowDays: windowDays,
336
- statsScanMinutes: scanMinutes,
337
- ...(dotModelColor !== undefined ? { dotModelColor } : {}),
338
- ...(dotUserColor !== undefined ? { dotUserColor } : {}),
339
- }
340
- }
341
-
342
- /** Clamp a numeric override into a valid value; undefined/invalid stays undefined. */
343
- function clampNumber(value: unknown, min: number): number | undefined {
344
- if (typeof value !== 'number' || !Number.isFinite(value) || value < min) return undefined
345
- return Math.floor(value)
346
- }
347
-
348
- /** HEX color validation shared by host routes and the settings card. */
349
- export const HEX_COLOR_RE = /^#[0-9a-f]{6}$/i
350
-
351
- /** GET /api/skill-hub/config */
352
- export interface ConfigResponse {
353
- ok: true
354
- /** 已安装插件自身的版本号(package.json version),设置卡标题旁显示。 */
355
- pluginVersion: string
356
- /** Effective configuration (saved overrides merged over the defaults). */
357
- config: HubConfig
358
- /** Raw user overrides persisted in the sidecar (absent fields inherit defaults). */
359
- saved: Partial<HubConfig>
360
- }
361
-
362
- /** POST /api/skill-hub/config — a partial patch; omitted fields keep their values. */
363
- export interface ConfigRequest {
364
- /** Set the field; null clears the saved override so it re-inherits the default. */
365
- enabled?: boolean | null
366
- /** Set the field; null clears the saved override so it re-inherits the default. */
367
- announceToAgent?: boolean | null
368
- /** Set the field; null clears the saved override so it re-inherits the default. */
369
- showUseCount?: boolean | null
370
- /** Set the field; null clears the saved override so it re-inherits the default. */
371
- showUseTime?: boolean | null
372
- /** Set the field; null clears the saved override so it re-inherits the default. */
373
- showGroupSummary?: boolean | null
374
- /** Set the dot color; null clears the saved override so it re-inherits the default. */
375
- dotModelColor?: string | null
376
- /** Set the dot color; null clears the saved override so it re-inherits the default. */
377
- dotUserColor?: string | null
378
- /** 统计滚动窗口天数(0 = 全部历史);null 清除覆盖回默认。 */
379
- statsWindowDays?: number | null
380
- /** 自动统计扫描间隔(分钟);null 清除覆盖回默认。 */
381
- statsScanMinutes?: number | null
382
- }
383
-
384
- /** One market source: a tracked upstream repo plus its pinned version. */
385
- export interface MarketSourceRecord {
386
- /** Repo slug (owner/repo). */
387
- repo: string
388
- /** Pinned version: release tag, branch name, or custom ref. Absent = not yet pinned. */
389
- ref?: string
390
- /** Commit the pinned ref last resolved to (update-check baseline). */
391
- commitSha?: string
392
- }
393
-
394
- /** GET /api/skill-hub/market — the user's added market sources. */
395
- export interface MarketSourcesResponse {
396
- ok: true
397
- /** Added market sources, in addition order. */
398
- repos: MarketSourceRecord[]
399
- }
400
-
401
- /** POST /api/skill-hub/market/source — add one repo as a market source. */
402
- export interface MarketSourceRequest {
403
- /** owner/repo, owner/repo@ref, or a github.com URL. */
404
- repo: string
405
- }
406
-
407
- /** POST /api/skill-hub/market/source|delete */
408
- export interface MarketSourceResponse {
409
- ok: true
410
- repos: MarketSourceRecord[]
411
- }
412
-
413
- /** POST /api/skill-hub/market/source/ref — pin a market source to an explicit ref. */
414
- export interface MarketSourceRefRequest {
415
- repo: string
416
- /** Release tag or branch name chosen for the repo. */
417
- ref: string
418
- }
419
-
420
- /** GET /api/skill-hub/market/source/versions?repo= — releases + branches for the version picker. */
421
- export interface MarketSourceVersionsResponse {
422
- ok: true
423
- repo: string
424
- /** Currently pinned ref, when one is recorded. */
425
- current?: string
426
- /** Release tags, newest first (drafts excluded). */
427
- releases: string[]
428
- /** Branch names, default branch first. */
429
- branches: string[]
430
- }
431
-
432
- /** GET /api/skill-hub/market/check — update check over market sources. */
433
- export interface MarketCheckResponse {
434
- ok: true
435
- results: Array<{
436
- repo: string
437
- /** Pinned ref, when one is recorded. */
438
- ref?: string
439
- /** Latest release tag on the repo, when it has one. */
440
- latestTag?: string
441
- /** Whether the pinned ref (or the repo) has moved ahead. */
442
- updateAvailable: boolean
443
- /** Latest commit of the checked ref. */
444
- commitSha: string
445
- /** Throttled: the check was skipped within the interval. */
446
- throttled?: boolean
447
- error?: string
448
- }>
449
- }
450
-
451
- /** POST /api/skill-hub/market/source/sync — align a market source to its pinned ref. */
452
- export interface MarketSyncResponse {
453
- ok: true
454
- repo: string
455
- /** The ref the source is now pinned to. */
456
- ref: string
457
- commitSha: string
458
- /** Local skills tracked from this repo (candidates for a batch update). */
459
- skills: string[]
460
- }
461
-
462
- /** A skill discovered in a GitHub repo under any top-level root (e.g. skills/, templates/). */
463
- export interface RepoSkillEntry {
464
- /** Kebab-case skill name (directory basename). */
465
- name: string
466
- /** Root-relative skill directory, e.g. skills/code-review. */
467
- dir: string
468
- /** Root-relative SKILL.md path, e.g. skills/code-review/SKILL.md. */
469
- path: string
470
- /** Repo root the skill lives in. */
471
- root: RepoRoot
472
- /** Collection name recorded as origin after import. */
473
- origin: string
474
- /** Number of files in the skill directory. */
475
- fileCount: number
476
- /** Total bytes across all files in the skill directory. */
477
- totalBytes: number
478
- /** Whether a same-named skill already exists locally. */
479
- existing: boolean
480
- }
481
-
482
- /** Skill root in a GitHub repo: the top-level directory that contains skills (e.g. skills, design-templates, templates). Auto-derived from SKILL.md locations, not hard-coded. */
483
- export type RepoRoot = string
484
-
485
- /** GET /api/skill-hub/repo — discover importable skills in a GitHub repo. */
486
- export interface RepoDiscoverResponse {
487
- ok: true
488
- repo: string
489
- /**
490
- * Ref the discovery ran against (release tag / branch / default branch).
491
- * Null means the repo has no release and no pinned ref — the client must
492
- * ask the user to pick a branch (see `branches`) and pin it first.
493
- */
494
- ref: string | null
495
- /** Branch names to choose from when ref is null (default branch first). */
496
- branches?: string[]
497
- entries: RepoSkillEntry[]
498
- /** GitHub truncated the tree; discovery is partial (mirrors codex walk_truncated). */
499
- truncated?: boolean
500
- }
501
-
502
- /** POST /api/skill-hub/repo/import — install selected repo skills. */
503
- export interface RepoImportRequest {
504
- repo: string
505
- /** Selected SKILL.md paths from the discover response. */
506
- paths: string[]
507
- /** The ref the discovery ran against; the import must use the same one. */
508
- ref?: string
509
- }
510
-
511
- /** POST /api/skill-hub/repo/import — now creates an async job (B方案) */
512
- export interface RepoImportResponse {
513
- ok: true
514
- jobId: string
515
- total: number
516
- totalBytes: number
517
- }
518
-
519
- /** GET /api/skill-hub/repo/import/progress?jobId=xxx */
520
- export interface RepoImportProgressResponse {
521
- ok: true
522
- jobId: string
523
- status: 'running' | 'done' | 'cancelled' | 'error'
524
- total: number
525
- done: number
526
- /** 当前正在下载的 skill 名,done < total 时有效 */
527
- current?: string
528
- /** 当前正在下载的文件路径(相对 skill dir) */
529
- currentFile?: string
530
- /** 字节级进度 */
531
- totalBytes: number
532
- downloadedBytes: number
533
- /** 下载速度 bytes/sec,running 时有效 */
534
- bytesPerSecond?: number
535
- imported: Array<{ name: string; origin: string; path: string }>
536
- skipped: Array<{ name: string; reason: 'exists' }>
537
- failed: Array<{ name: string; error: string }>
538
- /** error 状态时的原因 */
539
- error?: string
540
- }
541
-
542
- /** POST /api/skill-hub/repo/import/cancel */
543
- export interface RepoImportCancelRequest {
544
- jobId: string
545
- }
546
- export interface RepoImportCancelResponse {
547
- ok: true
548
- jobId: string
549
- status: 'cancelled' | 'done'
550
- }
551
-
552
- /** GET /api/skill-hub/update — check the plugin's own latest GitHub release. */
553
- export interface UpdateCheckResponse {
554
- ok: true
555
- /** Installed plugin version (from the bundled host build). */
556
- currentVersion: string
557
- /** Latest release tag, normalized without the leading v; null when unknown. */
558
- latestVersion: string | null
559
- /** True when latestVersion is strictly newer than currentVersion. */
560
- updateAvailable: boolean
561
- /** Release page URL; null when unavailable. */
562
- url: string | null
563
- /** Best-effort message when the check failed or no release exists. */
564
- error?: string
565
- }
566
-
567
- /** 用户自定义 tag 分组:纯组织视图,不改技能文件。 */
568
- export interface SkillTag {
569
- /** 稳定 ID(新建时由宿主生成)。 */
570
- id: string
571
- /** 显示名。 */
572
- name: string
573
- /** 成员技能名(集合技能与独立技能都可加入)。 */
574
- skillNames: string[]
575
- /** 默认场景(「通用」):系统预置、不可删除、新技能自动归入。 */
576
- default?: boolean
577
- }
578
-
579
- /** 系统集合组:按 origin(来源集合标识)自动聚合。 */
580
- export interface CollectionGroup {
581
- /** 集合名(origin 值,如 "superpowers" / "anthropics/skills")。 */
582
- name: string
583
- /** 该集合下的技能名,按名称排序。 */
584
- skillNames: string[]
585
- }
586
-
587
- /** GET /api/skill-hub/groups */
588
- export interface GroupsResponse {
589
- ok: true
590
- /** 用户自定义 tag 分组(按拖拽顺序)。 */
591
- tags: SkillTag[]
592
- /** 系统集合组(按拖拽顺序,兜底按名称)。 */
593
- collections: CollectionGroup[]
594
- /** skillName → 集合名 的完整映射。 */
595
- origins: Record<string, string>
596
- /** 来源分组整体顺序(project / col:xxx / uncategorized-source),用于 SourcesView 顶层排序 */
597
- sourceGroupOrder?: string[]
598
- /** 兼容旧 collectionOrder 字段 */
599
- collectionOrder?: string[]
600
- }
601
-
602
- /** POST /api/skill-hub/tag — 新建(缺省 id)或重命名(带 id)。 */
603
- export interface TagSaveRequest {
604
- /** 已有 tag 的 id;缺省表示新建。 */
605
- id?: string
606
- /** 显示名(去空格后非空)。 */
607
- name: string
608
- }
609
-
610
- /** POST /api/skill-hub/tag */
611
- export interface TagSaveResponse {
612
- ok: true
613
- /** 变更后的全部 tag。 */
614
- tags: SkillTag[]
615
- }
616
-
617
- /** POST /api/skill-hub/tag/delete */
618
- export interface TagDeleteRequest {
619
- id: string
620
- }
621
-
622
- /** POST /api/skill-hub/tag/delete */
623
- export interface TagDeleteResponse {
624
- ok: true
625
- tags: SkillTag[]
626
- }
627
-
628
- /** POST /api/skill-hub/tag/members — 直接设置某 tag 的完整成员列表(幂等)。 */
629
- export interface TagMembersRequest {
630
- id: string
631
- /** 目标成员技能名;后端只保留目录中存在的名字。 */
632
- skillNames: string[]
633
- }
634
-
635
- /** POST /api/skill-hub/tag/members */
636
- export interface TagMembersResponse {
637
- ok: true
638
- tags: SkillTag[]
639
- }
640
-
641
- /** POST /api/skill-hub/tag/reorder — 拖拽重排场景分组 */
642
- export interface TagReorderRequest {
643
- /** 按新顺序排列的 tag id 列表(需包含全部 id) */
644
- orderedIds: string[]
645
- }
646
- /** POST /api/skill-hub/tag/reorder */
647
- export interface TagReorderResponse {
648
- ok: true
649
- tags: SkillTag[]
650
- }
651
-
652
- /** POST /api/skill-hub/collections/reorder — 拖拽重排来源集合 */
653
- export interface CollectionReorderRequest {
654
- /** 按新顺序排列的集合名列表(需包含全部 name) */
655
- orderedNames: string[]
656
- }
657
- /** POST /api/skill-hub/collections/reorder */
658
- export interface CollectionReorderResponse {
659
- ok: true
660
- collections: CollectionGroup[]
661
- order: string[]
662
- }
663
-
664
- /** POST /api/skill-hub/source-groups/reorder — 拖拽重排来源顶层分组(project / collections / personal) */
665
- export interface SourceGroupReorderRequest {
666
- /** 按新顺序排列的顶层分组 key 列表(project / col:xxx / uncategorized-source) */
667
- orderedKeys: string[]
668
- }
669
- export interface SourceGroupReorderResponse {
670
- ok: true
671
- order: string[]
672
- }
673
-
674
- /** 来源跟踪记录:一组来自同一上游仓库根目录的技能。 */
675
- export interface SourceRecord {
676
- /** GitHub owner/repo。 */
677
- repo: string
678
- /** 显式分支/tag;缺省表示默认分支。 */
679
- ref?: string
680
- /** 技能在仓库中的根目录。 */
681
- root: RepoRoot
682
- /** 上次导入/同步时的上游 commit SHA;空 = 尚未核对过。 */
683
- commitSha: string
684
- /** 该来源下的技能名(来源组 = 这些技能)。 */
685
- skills: string[]
686
- /** 仓库内路径 → 文件大小 的基线清单(差异检测用;缺失 = 无基线)。 */
687
- manifest?: Record<string, number>
688
- }
689
-
690
- /** 回收站条目:上游删除后跟进删除(移入 .trash)的技能。 */
691
- export interface TrashEntry {
692
- name: string
693
- /** .trash 下的绝对路径。 */
694
- path: string
695
- /** 移入回收站的时间(epoch ms)。 */
696
- movedAt: number
697
- /** 移入回收站前的原始路径(目录或文件);旧版本条目没有该字段。 */
698
- sourcePath?: string
699
- /**
700
- * 移入回收站前的来源跟踪快照(恢复时用它把技能重新挂回来源记录,
701
- * 否则恢复后的技能会丢失来源归属、变成「个人技能」)。
702
- */
703
- origin?: {
704
- repo: string
705
- root: RepoRoot
706
- ref?: string
707
- commitSha: string
708
- }
709
- /** 移入回收站前所属的场景(tag)ID;恢复时重新加回这些场景。 */
710
- tagIds?: string[]
711
- }
712
-
713
- /** GET /api/skill-hub/sources */
714
- export interface SourcesResponse {
715
- ok: true
716
- /** 全部来源记录(按 repo 排序)。 */
717
- sources: SourceRecord[]
718
- /** skillName → 集合名(由 sources 派生)。 */
719
- origins: Record<string, string>
720
- /** 来源集合组(按 origin 聚合)。 */
721
- collections: CollectionGroup[]
722
- /** 回收站内容。 */
723
- trash: TrashEntry[]
724
- }
725
-
726
- /** POST /api/skill-hub/sources/check — 检查指定(或全部)来源的上游更新。 */
727
- export interface SourceCheckRequest {
728
- /** 仅检查该 repo;缺省检查全部。 */
729
- repo?: string
730
- }
731
-
732
- /** 单个来源的检查结果。 */
733
- export interface SourceCheckResult {
734
- repo: string
735
- ref?: string
736
- /** 检查失败时的原因(如仓库不可达/限流)。 */
737
- error?: string
738
- /** 上游 commit 是否变化。 */
739
- changed: boolean
740
- /** 上游最新 commit SHA(检查成功时)。 */
741
- commitSha?: string
742
- /** 上游有更新的技能名(changed 时经 tree 差异得出)。 */
743
- updated: string[]
744
- /** 上游已删除的技能名(changed 时经 tree 差异得出)。 */
745
- deleted: string[]
746
- /** 节流跳过(距上次检查不足 5 分钟,未访问网络)。 */
747
- throttled?: boolean
748
- /** 该来源此前没有快照(迁移/旧记录),本次已回填 commit,尚未有差异基线。 */
749
- unverified?: boolean
750
- }
751
-
752
- /** POST /api/skill-hub/sources/check */
753
- export interface SourceCheckResponse {
754
- ok: true
755
- results: SourceCheckResult[]
756
- }
757
-
758
- /** POST /api/skill-hub/sources/sync — 按上游重新下载所选技能并更新快照。 */
759
- export interface SourceSyncRequest {
760
- repo: string
761
- /** 要同步的技能名;缺省同步该来源全部技能。 */
762
- skills?: string[]
763
- }
764
-
765
- /** POST /api/skill-hub/sources/sync */
766
- export interface SourceSyncResponse {
767
- ok: true
768
- repo: string
769
- /** 同步后的上游 commit SHA。 */
770
- commitSha: string
771
- /** 成功同步的技能。 */
772
- synced: string[]
773
- /** 失败的技能。 */
774
- failed: Array<{ name: string; error: string }>
775
- }
776
-
777
- /** POST /api/skill-hub/sources/delete — 跟进上游删除,本地移入回收站。 */
778
- export interface SourceDeleteRequest {
779
- repo: string
780
- /** 要删除的技能名(移入 .trash)。 */
781
- skills: string[]
782
- }
783
-
784
- /** POST /api/skill-hub/sources/delete */
785
- export interface SourceDeleteResponse {
786
- ok: true
787
- /** 已移入回收站的技能。 */
788
- trashed: string[]
789
- failed: Array<{ name: string; error: string }>
790
- }
791
-
792
- /** POST /api/skill-hub/sources/restore — 从回收站恢复一个技能。 */
793
- export interface SourceRestoreRequest {
794
- name: string
795
- }
796
-
797
- /** POST /api/skill-hub/sources/restore */
798
- export interface SourceRestoreResponse {
799
- ok: true
800
- name: string
801
- path: string
802
- }
803
-
804
- /** POST /api/skill-hub/sources/trash/clear — 永久删除回收站里的全部技能。 */
805
- export interface SourceTrashClearResponse {
806
- ok: true
807
- /** 已永久删除的技能名。 */
808
- deleted: string[]
809
- /** 未能删除的技能(保留在回收站中)。 */
810
- failed: Array<{ name: string; error: string }>
811
- }
812
-
813
- /** 项目级技能来源(它们有 workspace 归属,不属于「个人」组)。 */
814
- export function isProjectSource(source: string): boolean {
815
- return source === 'project-dsh' || source === 'project-agents'
816
- }
11
+ export { SKILL_HUB_API } from './protocol/api.ts'
12
+ export type {
13
+ WritableRoot,
14
+ HubInvocation,
15
+ CatalogSkill,
16
+ DisabledSkill,
17
+ DiagnosticEntry,
18
+ DiagnosticFixRequest,
19
+ DiagnosticFixResponse,
20
+ CatalogResponse,
21
+ SkillDetail,
22
+ SkillDetailResponse,
23
+ SkillDeleteRequest,
24
+ SkillDeleteResponse,
25
+ ToggleRequest,
26
+ ToggleResponse,
27
+ ToggleBatchRequest,
28
+ ToggleBatchResponse,
29
+ CreateRequest,
30
+ CreateResponse,
31
+ } from './protocol/catalog.ts'
32
+ export type { SkillStat, StatsResponse, SkillStatsCheckpoint } from './protocol/stats.ts'
33
+ export type { ErrorResponse, HubConfig, HubSettingsValue, ConfigResponse, ConfigRequest } from './protocol/config.ts'
34
+ export { HUB_CONFIG_DEFAULTS, HEX_COLOR_RE, GITHUB_TOKEN_RE, resolveHubConfig } from './protocol/config.ts'
35
+ export type {
36
+ MarketSourceRecord,
37
+ MarketSourcesResponse,
38
+ MarketSourceRequest,
39
+ MarketSourceResponse,
40
+ MarketSourceRefRequest,
41
+ MarketSourceVersionsResponse,
42
+ MarketStatsSnapshot,
43
+ MarketStatsResponse,
44
+ MarketCheckResponse,
45
+ MarketSyncResponse,
46
+ } from './protocol/market.ts'
47
+ export type {
48
+ RepoSkillEntry,
49
+ RepoRoot,
50
+ RepoDiscoverResponse,
51
+ RepoImportRequest,
52
+ RepoImportResponse,
53
+ RepoImportProgressResponse,
54
+ RepoImportCancelRequest,
55
+ RepoImportCancelResponse,
56
+ UpdateCheckResponse,
57
+ } from './protocol/repo.ts'
58
+ export type {
59
+ SkillTag,
60
+ CollectionGroup,
61
+ GroupsResponse,
62
+ TagSaveRequest,
63
+ TagSaveResponse,
64
+ TagDeleteRequest,
65
+ TagDeleteResponse,
66
+ TagMembersRequest,
67
+ TagMembersResponse,
68
+ TagReorderRequest,
69
+ TagReorderResponse,
70
+ CollectionReorderRequest,
71
+ CollectionReorderResponse,
72
+ SourceGroupReorderRequest,
73
+ SourceGroupReorderResponse,
74
+ } from './protocol/groups.ts'
75
+ export type {
76
+ SourceRecord,
77
+ TrashEntry,
78
+ SourcesResponse,
79
+ SourceCheckRequest,
80
+ SourceCheckResult,
81
+ SourceCheckResponse,
82
+ SourceSyncRequest,
83
+ SourceSyncResponse,
84
+ SourceDeleteRequest,
85
+ SourceDeleteResponse,
86
+ SourceRestoreRequest,
87
+ SourceRestoreResponse,
88
+ SourceTrashClearResponse,
89
+ } from './protocol/sources.ts'
90
+ export { isProjectSource } from './protocol/sources.ts'