dsh-skill-hub 0.3.7 → 0.3.9

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 +30 -28
  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,44 @@
1
+ /**
2
+ * useSourceFlow — 来源域:来源列表/更新检查/同步确认/跟进删除/回收站恢复/
3
+ * 清空回收站,以及单个技能/整组的删除确认流。目录与分组的刷新经聚合根
4
+ * 传入的 reload 回调,不直接碰其他域的 state。
5
+ */
6
+ import type { SourceCheckResult, SourcesResponse } from '../../../protocol.ts';
7
+ import type { SkillHubApi } from '../../api.ts';
8
+ import type { FlowNotices } from './shared.ts';
9
+ import type { ConfirmDialogState } from '../dialogs.tsx';
10
+ export declare function useSourceFlow(api: SkillHubApi, shared: FlowNotices,
11
+ /** 目录重载(技能增删后刷新列表,目录域提供)。 */
12
+ reloadCatalog: () => Promise<void>,
13
+ /** 分组重载(来源/成员变化后刷新,分组域提供)。 */
14
+ reloadGroups: () => Promise<void>): {
15
+ sourcesState: SourcesResponse | null;
16
+ sourceCheck: Readonly<Record<string, SourceCheckResult>>;
17
+ checkingSource: string | null;
18
+ syncingSource: string | null;
19
+ confirmDialog: ConfirmDialogState | null;
20
+ deleteSkillDialog: string | null;
21
+ deleteGroupDialog: {
22
+ name: string;
23
+ skillNames: string[];
24
+ } | null;
25
+ confirmClearTrash: boolean;
26
+ setConfirmDialog: import("react").Dispatch<import("react").SetStateAction<ConfirmDialogState | null>>;
27
+ setDeleteSkillDialog: import("react").Dispatch<import("react").SetStateAction<string | null>>;
28
+ setDeleteGroupDialog: import("react").Dispatch<import("react").SetStateAction<{
29
+ name: string;
30
+ skillNames: string[];
31
+ } | null>>;
32
+ setConfirmClearTrash: import("react").Dispatch<import("react").SetStateAction<boolean>>;
33
+ loadSources: () => Promise<void>;
34
+ checkSources: (repo?: string) => Promise<void>;
35
+ requestSync: (repo: string, skills: string[]) => void;
36
+ requestDelete: (repo: string, skills: string[]) => void;
37
+ runConfirmed: () => Promise<void>;
38
+ restoreTrash: (name: string) => Promise<void>;
39
+ clearTrash: () => Promise<void>;
40
+ requestDeleteSkill: (name: string) => void;
41
+ runDeleteSkill: () => Promise<void>;
42
+ requestDeleteGroup: (name: string, skillNames: string[]) => void;
43
+ runDeleteGroup: () => Promise<void>;
44
+ };
@@ -0,0 +1,6 @@
1
+ /** Market tab number formatting (stars/downloads/bytes/speed). Pure, no deps. */
2
+ /** Compact count for stars/downloads (1234 → 1.2k). */
3
+ export declare function formatCount(n: number): string;
4
+ /** Compact byte size for repo preview rows. */
5
+ export declare function formatBytes(bytes: number): string;
6
+ export declare function formatSpeed(bps?: number): string;
@@ -1,68 +1,36 @@
1
1
  /**
2
- * useSkillHub — the panel's state owner. Everything the skill hub panel
3
- * knows (catalog, groups, sources, market, dialogs, drafts) plus every
4
- * async flow lives here; the panel itself only renders. All hooks run
5
- * unconditionally at the top, so the panel may early-return for the detail
6
- * and tag-editor views without violating the rules of hooks.
2
+ * useSkillHub — 面板的状态聚合根:只持有跨域共享的通知状态与纯视图状态,
3
+ * 各域状态与动作分散在 ./hooks/*,这里按依赖顺序组装(meta → 目录 →
4
+ * 分组 → 来源 → 市场),轮询与派生组装在此。返回形状与拆分前完全一致,
5
+ * 所有视图无需改动。All hooks run unconditionally at the top, so the panel
6
+ * may early-return for the detail and tag-editor views without violating
7
+ * the rules of hooks.
7
8
  */
8
- import { type FormEvent } from 'react';
9
- import type { CatalogResponse, CatalogSkill, DisabledSkill, GroupsResponse, HubConfig, MarketSourceRecord, RepoDiscoverResponse, RepoImportProgressResponse, SkillDetail, SkillTag, SourceCheckResult, SourcesResponse, UpdateCheckResponse, WritableRoot } from '../../protocol.ts';
10
9
  import type { SkillHubApi } from '../api.ts';
11
- import { type SortKey, type GroupSwitchState } from '../grouping.ts';
12
- import type { BranchChoiceState, ConfirmDialogState, ConflictDialogState, MarketSyncDialogState, VersionChoiceState } from './dialogs.tsx';
13
- /** One-shot self-update check state. */
14
- type UpdateState = {
15
- status: 'idle';
16
- } | {
17
- status: 'checking';
18
- } | {
19
- status: 'ready';
20
- data: UpdateCheckResponse;
21
- } | {
22
- status: 'error';
23
- message: string;
24
- };
25
- /** Repo scanner/import state (drives the market source preview). */
26
- type RepoDiscoverState = {
27
- status: 'idle';
28
- } | {
29
- status: 'scanning';
30
- } | {
31
- status: 'ready';
32
- data: RepoDiscoverResponse;
33
- } | {
34
- status: 'error';
35
- message: string;
36
- };
37
- /** Market sources list state. */
38
- type MarketState = {
39
- status: 'loading' | 'ready' | 'error';
40
- repos: MarketSourceRecord[];
41
- };
42
10
  /** The hook's result: the panel's complete state + action surface. */
43
11
  export type SkillHubState = ReturnType<typeof useSkillHub>;
44
12
  export declare function useSkillHub(api: SkillHubApi): {
45
- catalog: CatalogResponse | null;
13
+ catalog: import("../../protocol.ts").CatalogResponse | null;
46
14
  loading: boolean;
47
15
  loadError: string | null;
48
16
  successBanner: string | null;
49
- updateState: UpdateState;
50
- repoDiscoverState: RepoDiscoverState;
17
+ updateState: import("./hooks/shared.ts").UpdateState;
18
+ repoDiscoverState: import("./hooks/shared.ts").RepoDiscoverState;
51
19
  scanningRepo: string | null;
52
20
  repoSelected: ReadonlySet<string>;
53
21
  repoImporting: boolean;
54
- repoResult: RepoImportProgressResponse | null;
22
+ repoResult: import("../../protocol.ts").RepoImportProgressResponse | null;
55
23
  importJobId: string | null;
56
24
  search: string;
57
25
  workspace: string;
58
- detail: SkillDetail | null;
26
+ detail: import("../../protocol.ts").SkillDetail | null;
59
27
  detailLoading: boolean;
60
28
  busyNames: ReadonlySet<string>;
61
29
  batchBusy: boolean;
62
30
  showForm: boolean;
63
31
  formName: string;
64
32
  formDesc: string;
65
- formRoot: WritableRoot;
33
+ formRoot: import("../../protocol.ts").WritableRoot;
66
34
  formBusy: boolean;
67
35
  formMessage: {
68
36
  kind: "error" | "success";
@@ -72,13 +40,13 @@ export declare function useSkillHub(api: SkillHubApi): {
72
40
  count: number;
73
41
  lastUsed?: number;
74
42
  }>;
75
- hubConfig: HubConfig | null;
43
+ hubConfig: import("../../protocol.ts").HubConfig | null;
76
44
  tab: "sources" | "scenes" | "market";
77
45
  skillView: "flat" | "groups";
78
46
  sourceFilter: string;
79
47
  invocationFilter: "user" | "model" | "all";
80
- sortKey: SortKey;
81
- marketState: MarketState;
48
+ sortKey: import("../grouping.ts").SortKey;
49
+ marketState: import("./hooks/shared.ts").MarketState;
82
50
  marketCheck: Readonly<Record<string, {
83
51
  repo: string;
84
52
  ref?: string;
@@ -88,19 +56,23 @@ export declare function useSkillHub(api: SkillHubApi): {
88
56
  throttled?: boolean;
89
57
  error?: string;
90
58
  }>>;
91
- branchChoice: BranchChoiceState | null;
59
+ marketStats: Readonly<Record<string, {
60
+ stars: number;
61
+ downloads: number;
62
+ }>>;
63
+ branchChoice: import("./dialogs.tsx").BranchChoiceState | null;
92
64
  branchBusy: boolean;
93
- marketSyncDialog: MarketSyncDialogState | null;
65
+ marketSyncDialog: import("./dialogs.tsx").MarketSyncDialogState | null;
94
66
  syncingMarket: string | null;
95
67
  syncBusy: boolean;
96
68
  newSourceName: string;
97
- groupsState: GroupsResponse | null;
98
- sourcesState: SourcesResponse | null;
99
- sourceCheck: Readonly<Record<string, SourceCheckResult>>;
69
+ groupsState: import("../../protocol.ts").GroupsResponse | null;
70
+ sourcesState: import("../../protocol.ts").SourcesResponse | null;
71
+ sourceCheck: Readonly<Record<string, import("../../protocol.ts").SourceCheckResult>>;
100
72
  checkingSource: string | null;
101
73
  syncingSource: string | null;
102
- conflictDialog: ConflictDialogState | null;
103
- confirmDialog: ConfirmDialogState | null;
74
+ conflictDialog: import("./dialogs.tsx").ConflictDialogState | null;
75
+ confirmDialog: import("./dialogs.tsx").ConfirmDialogState | null;
104
76
  deleteSkillDialog: string | null;
105
77
  deleteGroupDialog: {
106
78
  name: string;
@@ -108,7 +80,7 @@ export declare function useSkillHub(api: SkillHubApi): {
108
80
  } | null;
109
81
  confirmClearTrash: boolean;
110
82
  updateAllDialog: boolean;
111
- editingTag: SkillTag | null;
83
+ editingTag: import("../../protocol.ts").SkillTag | null;
112
84
  editName: string;
113
85
  membersDraft: ReadonlySet<string>;
114
86
  newTagName: string;
@@ -118,25 +90,25 @@ export declare function useSkillHub(api: SkillHubApi): {
118
90
  subdividedProjects: ReadonlySet<string>;
119
91
  showLegend: boolean;
120
92
  editMode: boolean;
121
- versionDialog: VersionChoiceState | null;
93
+ versionDialog: import("./dialogs.tsx").VersionChoiceState | null;
122
94
  versionBusy: boolean;
123
95
  actionNames: Set<string>;
124
96
  viewNames: Set<string>;
125
97
  normalized: string;
126
98
  origins: Record<string, string>;
127
99
  sourceOptions: string[];
128
- filtered: CatalogSkill[];
129
- sorted: CatalogSkill[];
100
+ filtered: import("../../protocol.ts").CatalogSkill[];
101
+ sorted: import("../../protocol.ts").CatalogSkill[];
130
102
  shortenedCount: number;
131
103
  setLoadError: import("react").Dispatch<import("react").SetStateAction<string | null>>;
132
104
  setSuccessBanner: import("react").Dispatch<import("react").SetStateAction<string | null>>;
133
105
  setSearch: import("react").Dispatch<import("react").SetStateAction<string>>;
134
106
  setWorkspace: import("react").Dispatch<import("react").SetStateAction<string>>;
135
- setDetail: import("react").Dispatch<import("react").SetStateAction<SkillDetail | null>>;
107
+ setDetail: import("react").Dispatch<import("react").SetStateAction<import("../../protocol.ts").SkillDetail | null>>;
136
108
  setShowForm: import("react").Dispatch<import("react").SetStateAction<boolean>>;
137
109
  setFormName: import("react").Dispatch<import("react").SetStateAction<string>>;
138
110
  setFormDesc: import("react").Dispatch<import("react").SetStateAction<string>>;
139
- setFormRoot: import("react").Dispatch<import("react").SetStateAction<WritableRoot>>;
111
+ setFormRoot: import("react").Dispatch<import("react").SetStateAction<import("../../protocol.ts").WritableRoot>>;
140
112
  setFormMessage: import("react").Dispatch<import("react").SetStateAction<{
141
113
  kind: "error" | "success";
142
114
  text: string;
@@ -146,12 +118,12 @@ export declare function useSkillHub(api: SkillHubApi): {
146
118
  setSkillView: import("react").Dispatch<import("react").SetStateAction<"flat" | "groups">>;
147
119
  setSourceFilter: import("react").Dispatch<import("react").SetStateAction<string>>;
148
120
  setInvocationFilter: import("react").Dispatch<import("react").SetStateAction<"user" | "model" | "all">>;
149
- setSortKey: import("react").Dispatch<import("react").SetStateAction<SortKey>>;
150
- setBranchChoice: import("react").Dispatch<import("react").SetStateAction<BranchChoiceState | null>>;
151
- setMarketSyncDialog: import("react").Dispatch<import("react").SetStateAction<MarketSyncDialogState | null>>;
121
+ setSortKey: import("react").Dispatch<import("react").SetStateAction<import("../grouping.ts").SortKey>>;
122
+ setBranchChoice: import("react").Dispatch<import("react").SetStateAction<import("./dialogs.tsx").BranchChoiceState | null>>;
123
+ setMarketSyncDialog: import("react").Dispatch<import("react").SetStateAction<import("./dialogs.tsx").MarketSyncDialogState | null>>;
152
124
  setNewSourceName: import("react").Dispatch<import("react").SetStateAction<string>>;
153
- setConflictDialog: import("react").Dispatch<import("react").SetStateAction<ConflictDialogState | null>>;
154
- setConfirmDialog: import("react").Dispatch<import("react").SetStateAction<ConfirmDialogState | null>>;
125
+ setConflictDialog: import("react").Dispatch<import("react").SetStateAction<import("./dialogs.tsx").ConflictDialogState | null>>;
126
+ setConfirmDialog: import("react").Dispatch<import("react").SetStateAction<import("./dialogs.tsx").ConfirmDialogState | null>>;
155
127
  setDeleteSkillDialog: import("react").Dispatch<import("react").SetStateAction<string | null>>;
156
128
  setDeleteGroupDialog: import("react").Dispatch<import("react").SetStateAction<{
157
129
  name: string;
@@ -159,23 +131,23 @@ export declare function useSkillHub(api: SkillHubApi): {
159
131
  } | null>>;
160
132
  setConfirmClearTrash: import("react").Dispatch<import("react").SetStateAction<boolean>>;
161
133
  setUpdateAllDialog: import("react").Dispatch<import("react").SetStateAction<boolean>>;
162
- setEditingTag: import("react").Dispatch<import("react").SetStateAction<SkillTag | null>>;
134
+ setEditingTag: import("react").Dispatch<import("react").SetStateAction<import("../../protocol.ts").SkillTag | null>>;
163
135
  setEditName: import("react").Dispatch<import("react").SetStateAction<string>>;
164
136
  setMembersDraft: import("react").Dispatch<import("react").SetStateAction<ReadonlySet<string>>>;
165
137
  setNewTagName: import("react").Dispatch<import("react").SetStateAction<string>>;
166
138
  setEditSearch: import("react").Dispatch<import("react").SetStateAction<string>>;
167
139
  setShowLegend: import("react").Dispatch<import("react").SetStateAction<boolean>>;
168
140
  setEditMode: import("react").Dispatch<import("react").SetStateAction<boolean>>;
169
- setVersionDialog: import("react").Dispatch<import("react").SetStateAction<VersionChoiceState | null>>;
141
+ setVersionDialog: import("react").Dispatch<import("react").SetStateAction<import("./dialogs.tsx").VersionChoiceState | null>>;
170
142
  toggleGroupCollapse: (key: string) => void;
171
143
  toggleSubdivide: (key: string) => void;
172
144
  checkUpdate: () => Promise<void>;
173
145
  loadMarket: () => Promise<void>;
174
146
  openDetail: (name: string) => Promise<void>;
175
- toggle: (skill: CatalogSkill, enabled: boolean) => Promise<void>;
176
- enableDisabled: (record: DisabledSkill) => Promise<void>;
147
+ toggle: (skill: import("../../protocol.ts").CatalogSkill, enabled: boolean) => Promise<void>;
148
+ enableDisabled: (record: import("../../protocol.ts").DisabledSkill) => Promise<void>;
177
149
  batchToggleNames: (names: string[], enabled: boolean) => Promise<void>;
178
- toggleGroup: (key: string, name: string, view: GroupSwitchState) => void;
150
+ toggleGroup: (key: string, name: string, view: import("../grouping.ts").GroupSwitchState) => void;
179
151
  resolveConflict: (closeAll: boolean) => Promise<void>;
180
152
  runConfirmed: () => Promise<void>;
181
153
  checkSources: (repo?: string) => Promise<void>;
@@ -192,7 +164,7 @@ export declare function useSkillHub(api: SkillHubApi): {
192
164
  runDeleteSkill: () => Promise<void>;
193
165
  requestDeleteGroup: (name: string, skillNames: string[]) => void;
194
166
  runDeleteGroup: () => Promise<void>;
195
- createTag: (event: FormEvent) => Promise<void>;
167
+ createTag: (event: import("react").FormEvent) => Promise<void>;
196
168
  deleteTag: (id: string) => Promise<void>;
197
169
  saveTag: (id: string, name: string, memberNames: string[] | null) => Promise<void>;
198
170
  reorderTags: (orderedIds: string[]) => Promise<void>;
@@ -208,9 +180,9 @@ export declare function useSkillHub(api: SkillHubApi): {
208
180
  cancelImport: () => Promise<void>;
209
181
  clearScan: () => void;
210
182
  checkMarket: () => Promise<void>;
183
+ loadMarketStats: () => Promise<void>;
211
184
  syncMarketSource: (repo: string) => Promise<void>;
212
185
  confirmMarketSync: () => Promise<void>;
213
186
  updateAll: () => Promise<void>;
214
- create: (event: FormEvent) => Promise<void>;
187
+ create: (event: import("react").FormEvent) => Promise<void>;
215
188
  };
216
- export {};
@@ -65,6 +65,26 @@ export interface ColorFieldProps {
65
65
  onReset: () => void;
66
66
  }
67
67
  export declare function ColorField(props: ColorFieldProps): ReactElement;
68
+ /**
69
+ * One staged secret field: a password input that never echoes the stored
70
+ * value. Shows a "set" state via the overridden badge; Reset unsets it.
71
+ */
72
+ export interface SecretFieldProps {
73
+ id: string;
74
+ label: string;
75
+ hint: string;
76
+ /** Placeholder shown while empty (never the stored token). */
77
+ placeholder: string;
78
+ overriddenLabel: string;
79
+ resetLabel: string;
80
+ disabled: boolean;
81
+ text: string;
82
+ overridden: boolean;
83
+ invalid?: boolean;
84
+ onEdit: (text: string) => void;
85
+ onReset: () => void;
86
+ }
87
+ export declare function SecretField(props: SecretFieldProps): ReactElement;
68
88
  /** One staged numeric field: a numeric draft text input with inherit/reset semantics. */
69
89
  export interface NumberFieldProps {
70
90
  id: string;
@@ -23,6 +23,12 @@ export interface FieldSpec {
23
23
  export declare function booleanField(field: string): FieldSpec;
24
24
  /** A #rrggbb color field, edited through hex draft text. */
25
25
  export declare function colorField(field: string): FieldSpec;
26
+ /**
27
+ * A secret field (API token): the stored value is never echoed back into the
28
+ * draft (format always yields ''), so typing is always a fresh set and Reset
29
+ * always unsets. An empty draft stages nothing.
30
+ */
31
+ export declare function secretField(field: string): FieldSpec;
26
32
  /**
27
33
  * A numeric field with range clamping. Integer by default: a fractional draft
28
34
  * is truncated so "5.5 分钟" cannot sneak past an integer-only schema.
@@ -0,0 +1,38 @@
1
+ /** Browser-facing base paths of the skill-hub API family. */
2
+ export declare const SKILL_HUB_API: {
3
+ readonly catalog: "/api/skill-hub/catalog";
4
+ readonly skill: "/api/skill-hub/skill";
5
+ readonly skillDelete: "/api/skill-hub/skill/delete";
6
+ readonly toggle: "/api/skill-hub/toggle";
7
+ readonly toggleBatch: "/api/skill-hub/toggle-batch";
8
+ readonly create: "/api/skill-hub/create";
9
+ readonly stats: "/api/skill-hub/stats";
10
+ readonly config: "/api/skill-hub/config";
11
+ readonly market: "/api/skill-hub/market";
12
+ readonly marketSource: "/api/skill-hub/market/source";
13
+ readonly marketSourceDelete: "/api/skill-hub/market/source/delete";
14
+ readonly marketSourceRef: "/api/skill-hub/market/source/ref";
15
+ readonly marketCheck: "/api/skill-hub/market/check";
16
+ readonly marketSync: "/api/skill-hub/market/source/sync";
17
+ readonly repo: "/api/skill-hub/repo";
18
+ readonly repoImport: "/api/skill-hub/repo/import";
19
+ readonly repoImportProgress: "/api/skill-hub/repo/import/progress";
20
+ readonly repoImportCancel: "/api/skill-hub/repo/import/cancel";
21
+ readonly update: "/api/skill-hub/update";
22
+ readonly groups: "/api/skill-hub/groups";
23
+ readonly tag: "/api/skill-hub/tag";
24
+ readonly tagDelete: "/api/skill-hub/tag/delete";
25
+ readonly tagMembers: "/api/skill-hub/tag/members";
26
+ readonly tagReorder: "/api/skill-hub/tag/reorder";
27
+ readonly collectionReorder: "/api/skill-hub/collections/reorder";
28
+ readonly sourceGroupReorder: "/api/skill-hub/source-groups/reorder";
29
+ readonly sources: "/api/skill-hub/sources";
30
+ readonly sourceCheck: "/api/skill-hub/sources/check";
31
+ readonly sourceSync: "/api/skill-hub/sources/sync";
32
+ readonly sourceDelete: "/api/skill-hub/sources/delete";
33
+ readonly sourceRestore: "/api/skill-hub/sources/restore";
34
+ readonly sourceTrashClear: "/api/skill-hub/sources/trash/clear";
35
+ readonly diagnosticFix: "/api/skill-hub/diagnostic/fix";
36
+ readonly marketSourceVersions: "/api/skill-hub/market/source/versions";
37
+ readonly marketStats: "/api/skill-hub/market/stats";
38
+ };
@@ -0,0 +1,155 @@
1
+ /** User-level roots the hub may write to (matches dsh-skill-filesystem ranks 400/500). */
2
+ export type WritableRoot = 'user-dsh' | 'user-agents';
3
+ /** Invocation policy resolved by the registry, re-spelled for the wire. */
4
+ export interface HubInvocation {
5
+ /** Whether model-facing catalogs may load this skill. */
6
+ modelInvocable: boolean;
7
+ /** Whether human-facing command catalogs may load this skill. */
8
+ userInvocable: boolean;
9
+ }
10
+ /** One enabled skill row in the catalog. */
11
+ export interface CatalogSkill {
12
+ name: string;
13
+ description: string;
14
+ whenToUse?: string;
15
+ invocation: HubInvocation;
16
+ provider: string;
17
+ /** Whether the hub may toggle this skill (user-level filesystem skills only). */
18
+ writable: boolean;
19
+ /** 技能来源标识(user-dsh/user-agents/project-dsh/project-agents/...)。 */
20
+ source: string;
21
+ /** SKILL.md creation time (epoch ms); used for "added" sorting. Absent when unknown. */
22
+ addedAt?: number;
23
+ /** SKILL.md last-modified time (epoch ms); used for "updated" display. Absent when unknown. */
24
+ updatedAt?: number;
25
+ /** 项目技能的所属工作区路径(仅 project-dsh/project-agents 来源携带)。 */
26
+ workspace?: string;
27
+ /** 工作区显示标题(来自 workspace.json;无则回退为路径)。 */
28
+ workspaceTitle?: string;
29
+ /** UI metadata from agents/openai.yaml (mirrors codex SkillInterface). */
30
+ displayName?: string;
31
+ shortDescription?: string;
32
+ brandColor?: string;
33
+ iconSmall?: string;
34
+ iconLarge?: string;
35
+ defaultPrompt?: string;
36
+ }
37
+ /** One disabled skill tracked by the hub sidecar (SKILL.md renamed away). */
38
+ export interface DisabledSkill {
39
+ name: string;
40
+ description: string;
41
+ /** Absolute path of the renamed file (SKILL.md.disabled / <name>.md.disabled). */
42
+ path: string;
43
+ root: WritableRoot;
44
+ disabledAt: number;
45
+ }
46
+ /** One discovery diagnostic: a file the filesystem provider skips, with the reason. */
47
+ export interface DiagnosticEntry {
48
+ path: string;
49
+ root: string;
50
+ reason: string;
51
+ /** Whether this diagnostic can be auto-fixed (e.g. unquoted colon). */
52
+ fixable?: boolean;
53
+ }
54
+ /** POST /api/skill-hub/diagnostic/fix — repair a fixable diagnostic in place. */
55
+ export interface DiagnosticFixRequest {
56
+ path: string;
57
+ }
58
+ export interface DiagnosticFixResponse {
59
+ ok: true;
60
+ path: string;
61
+ }
62
+ /** GET /api/skill-hub/catalog */
63
+ export interface CatalogResponse {
64
+ ok: true;
65
+ /** 已安装插件自身的版本号(package.json version),面板标题旁显示。 */
66
+ pluginVersion: string;
67
+ /** Whether discovery completed within a stable catalog revision. */
68
+ complete: boolean;
69
+ /** Sorted winning summaries of every enabled skill (all roots + providers). */
70
+ skills: CatalogSkill[];
71
+ /** Skills the hub has toggled off (kept outside provider discovery). */
72
+ disabled: DisabledSkill[];
73
+ /** Files in the writable roots the provider ignores, with reasons. */
74
+ diagnostics: DiagnosticEntry[];
75
+ /** Skill names that appeared in multiple roots (first wins, others hidden). Mirrors codex name_counts. */
76
+ duplicateNames?: string[];
77
+ }
78
+ /** GET /api/skill-hub/skill */
79
+ export interface SkillDetail {
80
+ name: string;
81
+ description: string;
82
+ whenToUse?: string;
83
+ invocation: HubInvocation;
84
+ provider: string;
85
+ /** Absolute file path when the skill came from disk. */
86
+ path?: string;
87
+ /** SKILL.md creation time (epoch ms); absent when the file is unreadable. */
88
+ addedAt?: number;
89
+ /** SKILL.md last-modified time (epoch ms); absent when the file is unreadable. */
90
+ updatedAt?: number;
91
+ /** Markdown instruction body. */
92
+ content: string;
93
+ displayName?: string;
94
+ shortDescription?: string;
95
+ brandColor?: string;
96
+ iconSmall?: string;
97
+ iconLarge?: string;
98
+ defaultPrompt?: string;
99
+ }
100
+ export interface SkillDetailResponse {
101
+ ok: true;
102
+ skill: SkillDetail;
103
+ }
104
+ /** POST /api/skill-hub/skill/delete — 把单个技能移入回收站(可恢复)。 */
105
+ export interface SkillDeleteRequest {
106
+ name: string;
107
+ }
108
+ /** POST /api/skill-hub/skill/delete */
109
+ export interface SkillDeleteResponse {
110
+ ok: true;
111
+ name: string;
112
+ /** 移入回收站后的路径(目录或文件)。 */
113
+ path: string;
114
+ }
115
+ /** POST /api/skill-hub/toggle */
116
+ export interface ToggleRequest {
117
+ /** Kebab-case skill name. */
118
+ name: string;
119
+ /** true re-enables a hub-disabled skill; false disables an enabled one. */
120
+ enabled: boolean;
121
+ }
122
+ export interface ToggleResponse {
123
+ ok: true;
124
+ /** Fresh catalog after the mutation (the filesystem provider may lag a beat). */
125
+ catalog: CatalogResponse;
126
+ }
127
+ /** POST /api/skill-hub/toggle-batch — one group of skills, one write. */
128
+ export interface ToggleBatchRequest {
129
+ names: string[];
130
+ enabled: boolean;
131
+ }
132
+ /** POST /api/skill-hub/toggle-batch */
133
+ export interface ToggleBatchResponse {
134
+ ok: true;
135
+ catalog: CatalogResponse;
136
+ /** Per-name failures (unknown/read-only skills); empty means all landed. */
137
+ failures: Array<{
138
+ name: string;
139
+ error: string;
140
+ }>;
141
+ }
142
+ /** POST /api/skill-hub/create */
143
+ export interface CreateRequest {
144
+ /** Kebab-case skill name (validated with the official isSkillName grammar). */
145
+ name: string;
146
+ /** Optional one-line routing description for the frontmatter. */
147
+ description?: string;
148
+ /** Target user root; defaults to user-dsh (~/.dsh/skills). */
149
+ root?: WritableRoot;
150
+ }
151
+ export interface CreateResponse {
152
+ ok: true;
153
+ path: string;
154
+ root: WritableRoot;
155
+ }
@@ -0,0 +1,113 @@
1
+ /** JSON error body shared by every route. */
2
+ export interface ErrorResponse {
3
+ error: string;
4
+ }
5
+ /** The skill hub's own runtime configuration, edited from the settings card. */
6
+ export interface HubConfig {
7
+ /** Master switch: routes, provider, and announcement all go live with this. */
8
+ enabled: boolean;
9
+ /** When true, a system-prompt section announces the hub to every agent. */
10
+ announceToAgent: boolean;
11
+ /** Model-invocable dot color (#rrggbb); absent means the panel default. */
12
+ dotModelColor?: string;
13
+ /** User-invocable dot color (#rrggbb); absent means the panel default. */
14
+ dotUserColor?: string;
15
+ /** Show per-skill invocation count chip. Default true. */
16
+ showUseCount?: boolean;
17
+ /** Show per-skill last-used relative time. Default true. */
18
+ showUseTime?: boolean;
19
+ /** Show group-header usage summaries (count + last used). Default true. */
20
+ showGroupSummary?: boolean;
21
+ /** 统计滚动窗口天数:只统计最近 N 天的使用;0 = 全部历史。默认 0。 */
22
+ statsWindowDays?: number;
23
+ /** 自动统计扫描间隔(分钟,最小 1)。默认 5。 */
24
+ statsScanMinutes?: number;
25
+ /**
26
+ * GitHub personal access token for market/source API calls (anonymous quota
27
+ * is 60 req/h, authed 5000/hr). Stored in the local settings doc; absent
28
+ * means anonymous. Never logged.
29
+ */
30
+ githubToken?: string;
31
+ }
32
+ /**
33
+ * The resolved shape of the hub's settings namespace (schema defaults, then
34
+ * the composition base, then the user layer). Kept as a type alias so the
35
+ * browser-side settings scope snapshot is index-compatible with the card
36
+ * form's record shape.
37
+ */
38
+ export type HubSettingsValue = {
39
+ enabled: boolean;
40
+ announceToAgent: boolean;
41
+ showUseCount: boolean;
42
+ showUseTime: boolean;
43
+ showGroupSummary: boolean;
44
+ /** Model-invocable dot color (#rrggbb); absent means the panel default. */
45
+ dotModelColor?: string;
46
+ /** User-invocable dot color (#rrggbb); absent means the panel default. */
47
+ dotUserColor?: string;
48
+ /** 统计滚动窗口天数(0 = 全部历史)。 */
49
+ statsWindowDays?: number;
50
+ /** 自动统计扫描间隔(分钟)。 */
51
+ statsScanMinutes?: number;
52
+ /** GitHub token(明文存本地设置文档,仅回环可读;缺省为匿名)。 */
53
+ githubToken?: string;
54
+ };
55
+ /**
56
+ * Hub config defaults — the single source every layer reads: the cordis
57
+ * schema (index.ts), the host's saved-override merge, and the routes'
58
+ * fallback view. Changing a default here changes all three.
59
+ */
60
+ export declare const HUB_CONFIG_DEFAULTS: {
61
+ readonly enabled: true;
62
+ readonly announceToAgent: true;
63
+ readonly showUseCount: true;
64
+ readonly showUseTime: true;
65
+ readonly showGroupSummary: true;
66
+ readonly statsWindowDays: 14;
67
+ readonly statsScanMinutes: 5;
68
+ };
69
+ /**
70
+ * Resolve the effective hub config: saved sidecar overrides win over the
71
+ * cordis composition entry (the web card owns runtime config), missing
72
+ * booleans fall back to HUB_CONFIG_DEFAULTS, and dot colors pass through
73
+ * (saved first, then base) only when set. Numeric stats knobs are clamped to
74
+ * their sane ranges (window ≥ 0, scan interval ≥ 1 minute).
75
+ */
76
+ export declare function resolveHubConfig(saved: Partial<HubConfig>, base?: Partial<HubConfig>): HubConfig;
77
+ /** HEX color validation shared by host routes and the settings card. */
78
+ export declare const HEX_COLOR_RE: RegExp;
79
+ /** GET /api/skill-hub/config */
80
+ export interface ConfigResponse {
81
+ ok: true;
82
+ /** 已安装插件自身的版本号(package.json version),设置卡标题旁显示。 */
83
+ pluginVersion: string;
84
+ /** Effective configuration (saved overrides merged over the defaults). */
85
+ config: HubConfig;
86
+ /** Raw user overrides persisted in the sidecar (absent fields inherit defaults). */
87
+ saved: Partial<HubConfig>;
88
+ }
89
+ /** POST /api/skill-hub/config — a partial patch; omitted fields keep their values. */
90
+ export interface ConfigRequest {
91
+ /** Set the field; null clears the saved override so it re-inherits the default. */
92
+ enabled?: boolean | null;
93
+ /** Set the field; null clears the saved override so it re-inherits the default. */
94
+ announceToAgent?: boolean | null;
95
+ /** Set the field; null clears the saved override so it re-inherits the default. */
96
+ showUseCount?: boolean | null;
97
+ /** Set the field; null clears the saved override so it re-inherits the default. */
98
+ showUseTime?: boolean | null;
99
+ /** Set the field; null clears the saved override so it re-inherits the default. */
100
+ showGroupSummary?: boolean | null;
101
+ /** Set the dot color; null clears the saved override so it re-inherits the default. */
102
+ dotModelColor?: string | null;
103
+ /** Set the dot color; null clears the saved override so it re-inherits the default. */
104
+ dotUserColor?: string | null;
105
+ /** 统计滚动窗口天数(0 = 全部历史);null 清除覆盖回默认。 */
106
+ statsWindowDays?: number | null;
107
+ /** 自动统计扫描间隔(分钟);null 清除覆盖回默认。 */
108
+ statsScanMinutes?: number | null;
109
+ /** Set the GitHub token; null/empty clears it back to anonymous. */
110
+ githubToken?: string | null;
111
+ }
112
+ /** GitHub token validation shared by host routes and the settings card. */
113
+ export declare const GITHUB_TOKEN_RE: RegExp;