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
@@ -0,0 +1,100 @@
1
+ /** One market source: a tracked upstream repo plus its pinned version. */
2
+ export interface MarketSourceRecord {
3
+ /** Repo slug (owner/repo). */
4
+ repo: string
5
+ /** Pinned version: release tag, branch name, or custom ref. Absent = not yet pinned. */
6
+ ref?: string
7
+ /** Commit the pinned ref last resolved to (update-check baseline). */
8
+ commitSha?: string
9
+ }
10
+
11
+ /** GET /api/skill-hub/market — the user's added market sources. */
12
+ export interface MarketSourcesResponse {
13
+ ok: true
14
+ /** Added market sources, in addition order. */
15
+ repos: MarketSourceRecord[]
16
+ }
17
+
18
+ /** POST /api/skill-hub/market/source — add one repo as a market source. */
19
+ export interface MarketSourceRequest {
20
+ /** owner/repo, owner/repo@ref, or a github.com URL. */
21
+ repo: string
22
+ }
23
+
24
+ /** POST /api/skill-hub/market/source|delete */
25
+ export interface MarketSourceResponse {
26
+ ok: true
27
+ repos: MarketSourceRecord[]
28
+ }
29
+
30
+ /** POST /api/skill-hub/market/source/ref — pin a market source to an explicit ref. */
31
+ export interface MarketSourceRefRequest {
32
+ repo: string
33
+ /** Release tag or branch name chosen for the repo. */
34
+ ref: string
35
+ }
36
+
37
+ /** GET /api/skill-hub/market/source/versions?repo= — releases + branches for the version picker. */
38
+ export interface MarketSourceVersionsResponse {
39
+ ok: true
40
+ repo: string
41
+ /** Currently pinned ref, when one is recorded. */
42
+ current?: string
43
+ /** Release tags, newest first (drafts excluded). */
44
+ releases: string[]
45
+ /** Branch names, default branch first. */
46
+ branches: string[]
47
+ }
48
+
49
+ /** Persisted market-stats snapshot (sidecar `marketStats` field): last fetched stars/downloads per repo. */
50
+ export interface MarketStatsSnapshot {
51
+ /** Epoch ms of the fetch this snapshot was built from (drives the hourly TTL). */
52
+ fetchedAt: number
53
+ /** Per-repo numbers, keyed by repo slug. */
54
+ stats: Record<string, { stars: number; downloads: number }>
55
+ }
56
+
57
+ /** GET /api/skill-hub/market/stats — stars + release-asset downloads per market source. */
58
+ export interface MarketStatsResponse {
59
+ ok: true
60
+ results: Array<{
61
+ repo: string
62
+ stars: number
63
+ downloads: number
64
+ /** Throttled: served from the hourly cache without a network round. */
65
+ throttled?: boolean
66
+ /** Stale: older than the hourly TTL, a background refresh is on its way. */
67
+ stale?: boolean
68
+ error?: string
69
+ }>
70
+ }
71
+
72
+ /** GET /api/skill-hub/market/check — update check over market sources. */
73
+ export interface MarketCheckResponse {
74
+ ok: true
75
+ results: Array<{
76
+ repo: string
77
+ /** Pinned ref, when one is recorded. */
78
+ ref?: string
79
+ /** Latest release tag on the repo, when it has one. */
80
+ latestTag?: string
81
+ /** Whether the pinned ref (or the repo) has moved ahead. */
82
+ updateAvailable: boolean
83
+ /** Latest commit of the checked ref. */
84
+ commitSha: string
85
+ /** Throttled: the check was skipped within the interval. */
86
+ throttled?: boolean
87
+ error?: string
88
+ }>
89
+ }
90
+
91
+ /** POST /api/skill-hub/market/source/sync — align a market source to its pinned ref. */
92
+ export interface MarketSyncResponse {
93
+ ok: true
94
+ repo: string
95
+ /** The ref the source is now pinned to. */
96
+ ref: string
97
+ commitSha: string
98
+ /** Local skills tracked from this repo (candidates for a batch update). */
99
+ skills: string[]
100
+ }
@@ -0,0 +1,104 @@
1
+ /** A skill discovered in a GitHub repo under any top-level root (e.g. skills/, templates/). */
2
+ export interface RepoSkillEntry {
3
+ /** Kebab-case skill name (directory basename). */
4
+ name: string
5
+ /** Root-relative skill directory, e.g. skills/code-review. */
6
+ dir: string
7
+ /** Root-relative SKILL.md path, e.g. skills/code-review/SKILL.md. */
8
+ path: string
9
+ /** Repo root the skill lives in. */
10
+ root: RepoRoot
11
+ /** Collection name recorded as origin after import. */
12
+ origin: string
13
+ /** Number of files in the skill directory. */
14
+ fileCount: number
15
+ /** Total bytes across all files in the skill directory. */
16
+ totalBytes: number
17
+ /** Whether a same-named skill already exists locally. */
18
+ existing: boolean
19
+ }
20
+
21
+ /** 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. */
22
+ export type RepoRoot = string
23
+
24
+ /** GET /api/skill-hub/repo — discover importable skills in a GitHub repo. */
25
+ export interface RepoDiscoverResponse {
26
+ ok: true
27
+ repo: string
28
+ /**
29
+ * Ref the discovery ran against (release tag / branch / default branch).
30
+ * Null means the repo has no release and no pinned ref — the client must
31
+ * ask the user to pick a branch (see `branches`) and pin it first.
32
+ */
33
+ ref: string | null
34
+ /** Branch names to choose from when ref is null (default branch first). */
35
+ branches?: string[]
36
+ entries: RepoSkillEntry[]
37
+ /** GitHub truncated the tree; discovery is partial (mirrors codex walk_truncated). */
38
+ truncated?: boolean
39
+ }
40
+
41
+ /** POST /api/skill-hub/repo/import — install selected repo skills. */
42
+ export interface RepoImportRequest {
43
+ repo: string
44
+ /** Selected SKILL.md paths from the discover response. */
45
+ paths: string[]
46
+ /** The ref the discovery ran against; the import must use the same one. */
47
+ ref?: string
48
+ }
49
+
50
+ /** POST /api/skill-hub/repo/import — now creates an async job (B方案) */
51
+ export interface RepoImportResponse {
52
+ ok: true
53
+ jobId: string
54
+ total: number
55
+ totalBytes: number
56
+ }
57
+
58
+ /** GET /api/skill-hub/repo/import/progress?jobId=xxx */
59
+ export interface RepoImportProgressResponse {
60
+ ok: true
61
+ jobId: string
62
+ status: 'running' | 'done' | 'cancelled' | 'error'
63
+ total: number
64
+ done: number
65
+ /** 当前正在下载的 skill 名,done < total 时有效 */
66
+ current?: string
67
+ /** 当前正在下载的文件路径(相对 skill dir) */
68
+ currentFile?: string
69
+ /** 字节级进度 */
70
+ totalBytes: number
71
+ downloadedBytes: number
72
+ /** 下载速度 bytes/sec,running 时有效 */
73
+ bytesPerSecond?: number
74
+ imported: Array<{ name: string; origin: string; path: string }>
75
+ skipped: Array<{ name: string; reason: 'exists' }>
76
+ failed: Array<{ name: string; error: string }>
77
+ /** error 状态时的原因 */
78
+ error?: string
79
+ }
80
+
81
+ /** POST /api/skill-hub/repo/import/cancel */
82
+ export interface RepoImportCancelRequest {
83
+ jobId: string
84
+ }
85
+ export interface RepoImportCancelResponse {
86
+ ok: true
87
+ jobId: string
88
+ status: 'cancelled' | 'done'
89
+ }
90
+
91
+ /** GET /api/skill-hub/update — check the plugin's own latest GitHub release. */
92
+ export interface UpdateCheckResponse {
93
+ ok: true
94
+ /** Installed plugin version (from the bundled host build). */
95
+ currentVersion: string
96
+ /** Latest release tag, normalized without the leading v; null when unknown. */
97
+ latestVersion: string | null
98
+ /** True when latestVersion is strictly newer than currentVersion. */
99
+ updateAvailable: boolean
100
+ /** Release page URL; null when unavailable. */
101
+ url: string | null
102
+ /** Best-effort message when the check failed or no release exists. */
103
+ error?: string
104
+ }
@@ -0,0 +1,146 @@
1
+ import type { CollectionGroup } from './groups.ts'
2
+ import type { RepoRoot } from './repo.ts'
3
+
4
+ /** 来源跟踪记录:一组来自同一上游仓库根目录的技能。 */
5
+ export interface SourceRecord {
6
+ /** GitHub owner/repo。 */
7
+ repo: string
8
+ /** 显式分支/tag;缺省表示默认分支。 */
9
+ ref?: string
10
+ /** 技能在仓库中的根目录。 */
11
+ root: RepoRoot
12
+ /** 上次导入/同步时的上游 commit SHA;空 = 尚未核对过。 */
13
+ commitSha: string
14
+ /** 该来源下的技能名(来源组 = 这些技能)。 */
15
+ skills: string[]
16
+ /** 仓库内路径 → 文件大小 的基线清单(差异检测用;缺失 = 无基线)。 */
17
+ manifest?: Record<string, number>
18
+ }
19
+
20
+ /** 回收站条目:上游删除后跟进删除(移入 .trash)的技能。 */
21
+ export interface TrashEntry {
22
+ name: string
23
+ /** .trash 下的绝对路径。 */
24
+ path: string
25
+ /** 移入回收站的时间(epoch ms)。 */
26
+ movedAt: number
27
+ /** 移入回收站前的原始路径(目录或文件);旧版本条目没有该字段。 */
28
+ sourcePath?: string
29
+ /**
30
+ * 移入回收站前的来源跟踪快照(恢复时用它把技能重新挂回来源记录,
31
+ * 否则恢复后的技能会丢失来源归属、变成「个人技能」)。
32
+ */
33
+ origin?: {
34
+ repo: string
35
+ root: RepoRoot
36
+ ref?: string
37
+ commitSha: string
38
+ }
39
+ /** 移入回收站前所属的场景(tag)ID;恢复时重新加回这些场景。 */
40
+ tagIds?: string[]
41
+ }
42
+
43
+ /** GET /api/skill-hub/sources */
44
+ export interface SourcesResponse {
45
+ ok: true
46
+ /** 全部来源记录(按 repo 排序)。 */
47
+ sources: SourceRecord[]
48
+ /** skillName → 集合名(由 sources 派生)。 */
49
+ origins: Record<string, string>
50
+ /** 来源集合组(按 origin 聚合)。 */
51
+ collections: CollectionGroup[]
52
+ /** 回收站内容。 */
53
+ trash: TrashEntry[]
54
+ }
55
+
56
+ /** POST /api/skill-hub/sources/check — 检查指定(或全部)来源的上游更新。 */
57
+ export interface SourceCheckRequest {
58
+ /** 仅检查该 repo;缺省检查全部。 */
59
+ repo?: string
60
+ }
61
+
62
+ /** 单个来源的检查结果。 */
63
+ export interface SourceCheckResult {
64
+ repo: string
65
+ ref?: string
66
+ /** 检查失败时的原因(如仓库不可达/限流)。 */
67
+ error?: string
68
+ /** 上游 commit 是否变化。 */
69
+ changed: boolean
70
+ /** 上游最新 commit SHA(检查成功时)。 */
71
+ commitSha?: string
72
+ /** 上游有更新的技能名(changed 时经 tree 差异得出)。 */
73
+ updated: string[]
74
+ /** 上游已删除的技能名(changed 时经 tree 差异得出)。 */
75
+ deleted: string[]
76
+ /** 节流跳过(距上次检查不足 5 分钟,未访问网络)。 */
77
+ throttled?: boolean
78
+ /** 该来源此前没有快照(迁移/旧记录),本次已回填 commit,尚未有差异基线。 */
79
+ unverified?: boolean
80
+ }
81
+
82
+ /** POST /api/skill-hub/sources/check */
83
+ export interface SourceCheckResponse {
84
+ ok: true
85
+ results: SourceCheckResult[]
86
+ }
87
+
88
+ /** POST /api/skill-hub/sources/sync — 按上游重新下载所选技能并更新快照。 */
89
+ export interface SourceSyncRequest {
90
+ repo: string
91
+ /** 要同步的技能名;缺省同步该来源全部技能。 */
92
+ skills?: string[]
93
+ }
94
+
95
+ /** POST /api/skill-hub/sources/sync */
96
+ export interface SourceSyncResponse {
97
+ ok: true
98
+ repo: string
99
+ /** 同步后的上游 commit SHA。 */
100
+ commitSha: string
101
+ /** 成功同步的技能。 */
102
+ synced: string[]
103
+ /** 失败的技能。 */
104
+ failed: Array<{ name: string; error: string }>
105
+ }
106
+
107
+ /** POST /api/skill-hub/sources/delete — 跟进上游删除,本地移入回收站。 */
108
+ export interface SourceDeleteRequest {
109
+ repo: string
110
+ /** 要删除的技能名(移入 .trash)。 */
111
+ skills: string[]
112
+ }
113
+
114
+ /** POST /api/skill-hub/sources/delete */
115
+ export interface SourceDeleteResponse {
116
+ ok: true
117
+ /** 已移入回收站的技能。 */
118
+ trashed: string[]
119
+ failed: Array<{ name: string; error: string }>
120
+ }
121
+
122
+ /** POST /api/skill-hub/sources/restore — 从回收站恢复一个技能。 */
123
+ export interface SourceRestoreRequest {
124
+ name: string
125
+ }
126
+
127
+ /** POST /api/skill-hub/sources/restore */
128
+ export interface SourceRestoreResponse {
129
+ ok: true
130
+ name: string
131
+ path: string
132
+ }
133
+
134
+ /** POST /api/skill-hub/sources/trash/clear — 永久删除回收站里的全部技能。 */
135
+ export interface SourceTrashClearResponse {
136
+ ok: true
137
+ /** 已永久删除的技能名。 */
138
+ deleted: string[]
139
+ /** 未能删除的技能(保留在回收站中)。 */
140
+ failed: Array<{ name: string; error: string }>
141
+ }
142
+
143
+ /** 项目级技能来源(它们有 workspace 归属,不属于「个人」组)。 */
144
+ export function isProjectSource(source: string): boolean {
145
+ return source === 'project-dsh' || source === 'project-agents'
146
+ }
@@ -0,0 +1,42 @@
1
+ /** One skill's invocation stats across the local session logs. */
2
+ export interface SkillStat {
3
+ /** Kebab-case skill name. */
4
+ name: string
5
+ /** How many sessions recorded a user-explicit invocation of this skill. */
6
+ count: number
7
+ /** Unix epoch ms of the most recent invocation (absent when never called). */
8
+ lastUsed?: number
9
+ }
10
+
11
+ /** GET /api/skill-hub/stats */
12
+ export interface StatsResponse {
13
+ ok: true
14
+ /** Whether a session-log source was available (false means counts are empty). */
15
+ available: boolean
16
+ /** Sorted per-skill invocation counts. */
17
+ stats: SkillStat[]
18
+ }
19
+
20
+ /**
21
+ * Persisted incremental-scan checkpoint for the usage statistics (sidecar
22
+ * `skillStats` field). Sessions created before `frozenBefore` are treated as
23
+ * finalized: their per-session counts live in `frozenSessions` (only sessions
24
+ * with at least one invocation are kept) and they are not re-read on
25
+ * incremental scans. A daily full reconciliation rebuilds the cache and
26
+ * advances the watermark, so a resumed old session is eventually re-counted.
27
+ */
28
+ export interface SkillStatsCheckpoint {
29
+ /** The rolling-window configuration this checkpoint was built for (0 = all history). */
30
+ windowDays: number
31
+ /** Watermark: every session with header.createdAt < this value is frozen. */
32
+ frozenBefore: number
33
+ /** Per-session counts of finalized sessions, keyed by session id. */
34
+ frozenSessions: Record<string, { createdAt: number; counts: Record<string, { count: number; lastUsed: number }> }>
35
+ /** Epoch ms of the last full reconciliation (drives the daily cadence). */
36
+ lastFullReconcile: number
37
+ /**
38
+ * Totals from the last completed scan (any kind). Served instantly on cold
39
+ * start so a restart still shows numbers while the background rescan runs.
40
+ */
41
+ lastTotals?: SkillStat[]
42
+ }