dsh-skill-hub 0.3.14 → 0.3.15

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 (56) hide show
  1. package/CONTRIBUTING.md +6 -4
  2. package/README.md +9 -5
  3. package/README.zh.md +9 -5
  4. package/lib/client.js +32 -11
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +529 -314
  7. package/lib/types/client/index.d.ts +13 -12
  8. package/lib/types/client/locales/market.d.ts +1 -0
  9. package/lib/types/client/locales.d.ts +1 -0
  10. package/lib/types/client/settings-form.d.ts +9 -3
  11. package/lib/types/client/slash-dots.d.ts +3 -3
  12. package/lib/types/index.d.ts +59 -23
  13. package/lib/types/protocol/api.d.ts +22 -2
  14. package/lib/types/protocol/config.d.ts +30 -4
  15. package/lib/types/protocol/market.d.ts +1 -1
  16. package/lib/types/protocol/repo.d.ts +18 -1
  17. package/lib/types/protocol.d.ts +3 -3
  18. package/lib/types/repo/discovery.d.ts +59 -3
  19. package/lib/types/repo/github-client.d.ts +16 -0
  20. package/lib/types/repo.d.ts +6 -3
  21. package/lib/types/routes/helpers.d.ts +8 -1
  22. package/lib/types/routes/market.d.ts +2 -2
  23. package/lib/types/routes.d.ts +1 -1
  24. package/lib/types/store/store.d.ts +4 -0
  25. package/package.json +31 -30
  26. package/src/client/index.tsx +25 -26
  27. package/src/client/locales/market.ts +2 -0
  28. package/src/client/panel/RepoScanCard.tsx +6 -3
  29. package/src/client/panel/SkillHubPanel.tsx +1 -1
  30. package/src/client/panel/SourcesView.tsx +1 -1
  31. package/src/client/panel/hooks/useGroupFlow.ts +1 -8
  32. package/src/client/settings-form.ts +9 -4
  33. package/src/client/slash-dots.test.ts +3 -3
  34. package/src/client/slash-dots.tsx +3 -3
  35. package/src/index.ts +145 -80
  36. package/src/protocol/api.ts +24 -2
  37. package/src/protocol/config.ts +35 -4
  38. package/src/protocol/market.ts +1 -1
  39. package/src/protocol/repo.ts +22 -1
  40. package/src/protocol.ts +3 -3
  41. package/src/repo/discovery.ts +120 -33
  42. package/src/repo/github-client.ts +18 -1
  43. package/src/repo/install.ts +8 -7
  44. package/src/repo.test.ts +158 -4
  45. package/src/repo.ts +10 -2
  46. package/src/routes/config.ts +19 -2
  47. package/src/routes/helpers.ts +9 -2
  48. package/src/routes/market.ts +49 -37
  49. package/src/routes/repo-import.ts +3 -2
  50. package/src/routes/sources.ts +2 -1
  51. package/src/routes.test.ts +107 -1
  52. package/src/routes.ts +21 -3
  53. package/src/store/migrate.ts +3 -2
  54. package/src/store/store.ts +7 -2
  55. package/src/store.test.ts +50 -0
  56. package/src/update.ts +4 -2
package/CONTRIBUTING.md CHANGED
@@ -39,7 +39,7 @@ src/client/locales/ dictionaries by view (common/skills/market/sources/detai
39
39
  ```bash
40
40
  npm install
41
41
  npm run typecheck # tsc --noEmit
42
- npm test # vitest (233 tests across 14 suites)
42
+ npm test # vitest (255 tests across 14 suites)
43
43
  npm run build # tsc declarations + tsdown bundles (lib/index.js + lib/client.js)
44
44
  ```
45
45
 
@@ -53,8 +53,8 @@ npm run build # tsc declarations + tsdown bundles (lib/index.js + lib/clie
53
53
  live GUI.
54
54
  3. **Build** — `npm run build` must produce `lib/index.js` and `lib/client.js`.
55
55
  4. **Keep the diff focused** — one logical change per PR, with a clear title and description.
56
- 5. **Documentation** — update `README.md` (including the embedded Chinese collapsible section) when
57
- behavior or the API surface changes.
56
+ 5. **Documentation** — update `README.md` **and** `README.zh.md` (both ship with the package and are
57
+ kept in sync) when behavior or the API surface changes.
58
58
 
59
59
  ## Code style
60
60
 
@@ -68,7 +68,9 @@ npm run build # tsc declarations + tsdown bundles (lib/index.js + lib/clie
68
68
  ```bash
69
69
  # after a change:
70
70
  npm run build
71
- # restart the dsh web process, then verify Settings → 技能 and Settings → 插件 → Skill Hub
71
+ # restart the dsh web process, then verify both surfaces:
72
+ # Settings → 技能 — the skill hub panel
73
+ # sidebar 插件 → dsh-skill-hub — the plugin's settings card
72
74
  ```
73
75
 
74
76
  When the web profile installs this repo as a link (`"dsh-skill-hub": "link:/path/to/repo"`, the
package/README.md CHANGED
@@ -24,7 +24,9 @@ dsh plugin --profile web add dsh-skill-hub
24
24
  # restart dsh web → Settings → 技能 → Market → scan → import
25
25
  ```
26
26
 
27
- Requires `Node ^22.19 || >=24` + dsh web `>=0.1.6-alpha.2 <0.2`.
27
+ Requires `Node ^22.19 || >=24` + dsh web `>=0.1.7-alpha.1 <0.2`.
28
+
29
+ Two surfaces — the hub panel lives at **Settings → 技能**, and this plugin's own configuration card sits on the plugin's page in the **Plugins manager** (sidebar → 插件 → dsh-skill-hub). The card is registered by the plugin itself into the `plugins.bundle.config` slot — dsh has no auto-generated config page — and covers the master switch, announce-to-agent, dot colors, usage display and the stats window/interval.
28
30
 
29
31
  ## Features
30
32
 
@@ -35,10 +37,10 @@ Requires `Node ^22.19 || >=24` + dsh web `>=0.1.6-alpha.2 <0.2`.
35
37
  - **Organize** — scenes (tags) plus auto-aggregated source collections, all drag-reorderable and persisted in `~/.dsh/dsh-skill-hub.json`. Edit mode reveals delete/reorder without cluttering the read view.
36
38
  - **Diagnose & fix** — files the provider skips (missing frontmatter, bad YAML, name mismatch, short description) show up with reasons; auto-fixable ones (e.g. unquoted `:` in descriptions) get a one-click Fix button.
37
39
  - **Scaffold** — new-skill wizard writing to `~/.dsh/skills` or `~/.agents/skills` (`SKILL.md` template below).
38
- - **Market** — built-in curated repos plus custom `owner/repo` sources. Any top-level directory containing `SKILL.md` scans as a root (no allowlist). Async import with byte-level progress and cancel. Each source pins a version — click the ref badge to switch between releases, branches, or a custom ref.
40
+ - **Market** — built-in curated repos plus custom `owner/repo` sources. Any top-level directory containing `SKILL.md` scans as a root (no allowlist), and a `SKILL.md` at the repo root itself scans as a single skill named after the repo (minus repo tooling such as `.github/`). Async import with byte-level progress and cancel. Each source pins a version — click the ref badge to switch between releases, branches, or a custom ref.
39
41
  - **Track updates** — imported skills record a repo + commit snapshot. Check all / update-all, per-source badges (installed / updatable / deleted upstream / new release). Sync overwrites local edits (with confirm); upstream deletions move into a restorable trash that keeps source and scene membership.
40
42
  - **Stats** — per-skill call counts + last-used times from session logs (incremental cache), group summaries; window and scan interval live-configurable from the settings card.
41
- - **Settings card** — master switch, announce-to-agent, invocation dot colors, usage display toggles, stats window/interval; plus a self-update check against GitHub releases.
43
+ - **Settings card** — registered on the plugin's own page in the **Plugins manager** (sidebar → 插件 → dsh-skill-hub; collapsed until you expand the title): master switch, announce-to-agent, invocation dot colors, usage display toggles, stats window/interval.
42
44
 
43
45
  ## Why not just the read-only browser?
44
46
 
@@ -92,7 +94,7 @@ Host uses only `ctx.skills.snapshot/get`, `ctx.webServer.register`, `ctx.systemP
92
94
  | `/api/skill-hub/config` | GET/POST | runtime config (`null` clears) |
93
95
  | `/api/skill-hub/groups` | GET | tags + collections + orders |
94
96
  | `/api/skill-hub/tag` etc. | POST | create/rename, delete, set members, reorder |
95
- | `/api/skill-hub/market` etc. | GET/POST | list/add/delete/pin/check/sync sources |
97
+ | `/api/skill-hub/market` etc. | GET/POST | list/add/delete/pin sources; `…/source/check` + `…/source/sync` update them |
96
98
  | `/api/skill-hub/market/source/versions?repo=` | GET | releases + branches for the version picker |
97
99
  | `/api/skill-hub/repo?repo=` | GET | discover (any root) |
98
100
  | `/api/skill-hub/repo/import` | POST | async job `{jobId, total, totalBytes}` |
@@ -100,12 +102,13 @@ Host uses only `ctx.skills.snapshot/get`, `ctx.webServer.register`, `ctx.systemP
100
102
  | `/api/skill-hub/repo/import/cancel` | POST | cancel job |
101
103
  | `/api/skill-hub/sources` etc. | GET/POST | list/check/sync/delete/restore/clear trash |
102
104
  | `/api/skill-hub/update` | GET | plugin latest release |
105
+ | unknown `/api/skill-hub/*` | GET/POST | `404 {error}` naming the path — a typo must not read as an auth failure (the SPA fallback answers 401 for `/api/*` it does not own) |
103
106
 
104
107
  ## Development
105
108
 
106
109
  ```bash
107
110
  npm run typecheck # tsc --noEmit
108
- npm test # 176 tests, 9 suites
111
+ npm test # 255 tests, 14 suites
109
112
  npm run build # tsc + tsdown → lib/index.js + lib/client.js
110
113
  ```
111
114
 
@@ -117,6 +120,7 @@ npm run build # tsc + tsdown → lib/index.js + lib/client.js
117
120
  - Skill missing — check the diagnostics section (frontmatter / name mismatch / short description).
118
121
  - Empty source group — its skills were deleted, or their disabled records were lost (sidecar restored/hand-edited). Startup reconciles `.disabled` files on disk; source groups with no visible member are no longer rendered.
119
122
  - Dots missing in `/` menu — dsh internals changed; catalog still works.
123
+ - Settings card missing — open the plugin in the Plugins manager (sidebar → 插件 → dsh-skill-hub) and expand the 「技能中枢」 card at the top of the page (collapsed by default). On dsh older than `0.1.7-alpha.1` this plugin does not load at all (the settings API it targets does not exist there).
120
124
 
121
125
  ## Community
122
126
 
package/README.zh.md CHANGED
@@ -24,7 +24,9 @@ dsh plugin --profile web add dsh-skill-hub
24
24
  # 重启 dsh web → 设置 → 技能 → 市场 → 扫描 → 导入
25
25
  ```
26
26
 
27
- 要求 `Node ^22.19 || >=24` + dsh web `>=0.1.6-alpha.2 <0.2`。
27
+ 要求 `Node ^22.19 || >=24` + dsh web `>=0.1.7-alpha.1 <0.2`。
28
+
29
+ 两个界面 —— 管理面板在 **设置 → 技能**;本插件自身的配置卡片在 **插件管理页** 的插件自有页面上(侧边栏「插件」→ dsh-skill-hub)。该卡片由本插件自己注册进 `plugins.bundle.config` 槽位(dsh 没有自动生成的配置页),覆盖总开关、向 Agent 公告、圆点颜色、用量显示与统计窗口/间隔。
28
30
 
29
31
  ## 功能
30
32
 
@@ -35,10 +37,10 @@ dsh plugin --profile web add dsh-skill-hub
35
37
  - **整理** — 场景(tag)+ 自动聚合的来源集合,全部可拖拽排序并持久化到 `~/.dsh/dsh-skill-hub.json`。编辑模式收敛删除/排序控件,阅读视图保持干净。
36
38
  - **诊断与修复** — provider 跳过的文件给出原因(缺 frontmatter、YAML 非法、名称不一致、描述过短);可自动修复的(如描述里未加引号的 `:`)一键 Fix 落盘。
37
39
  - **新建** — 新技能向导,写入 `~/.dsh/skills` 或 `~/.agents/skills`(`SKILL.md` 模板见下)。
38
- - **市场** — 内置精选仓库 + 自定义 `owner/repo`。任何含 `SKILL.md` 的顶层目录都可扫描(无白名单)。异步导入,字节级进度+取消。每个源钉一个版本 —— 点 ref 徽标可在发布版/分支/手输之间切换。
40
+ - **市场** — 内置精选仓库 + 自定义 `owner/repo`。任何含 `SKILL.md` 的顶层目录都可扫描(无白名单);`SKILL.md` 直接放在仓库根时,整个仓库算一个技能,技能名取仓库名(`.github/` 等仓库基建不计入)。异步导入,字节级进度+取消。每个源钉一个版本 —— 点 ref 徽标可在发布版/分支/手输之间切换。
39
41
  - **跟踪更新** — 导入的技能记录 repo+commit 快照。检查全部/一键全更;每源徽章(已装/可更新/上游已删/新版本)。同步覆盖本地修改(先确认);上游删除跟进移入回收站,恢复保留来源与场景归属。
40
42
  - **统计** — 会话日志的调用次数+最近使用,分组头汇总;窗口与扫描间隔在设置卡片实时可调。
41
- - **设置卡片** — 总开关、向 Agent 公告、调用圆点颜色、用量显示开关、统计窗口/间隔;附带插件自更新检查(对 GitHub releases)。
43
+ - **设置卡片** — 注册在 **插件管理页** 的插件自有页面上(侧边栏「插件」→ dsh-skill-hub,默认折叠,点标题展开):总开关、向 Agent 公告、调用圆点颜色、用量显示开关、统计窗口/间隔。
42
44
 
43
45
  ## 为什么还需要一个管理器?
44
46
 
@@ -92,7 +94,7 @@ GitHub 仓库 ──扫描/导入──▶ ~/.dsh/skills
92
94
  | `/api/skill-hub/config` | GET/POST | 运行时配置(`null` 清除) |
93
95
  | `/api/skill-hub/groups` | GET | tags+集合+排序 |
94
96
  | `/api/skill-hub/tag` 等 | POST | 新建/重命名、删除、设成员、排序 |
95
- | `/api/skill-hub/market` 等 | GET/POST | 市场源 列表/添加/删除/钉 ref/检查/同步 |
97
+ | `/api/skill-hub/market` 等 | GET/POST | 市场源 列表/添加/删除/钉 ref;`…/source/check` + `…/source/sync` 检查与同步 |
96
98
  | `/api/skill-hub/market/source/versions?repo=` | GET | 版本选择器的 releases+branches |
97
99
  | `/api/skill-hub/repo?repo=` | GET | 发现(任意根) |
98
100
  | `/api/skill-hub/repo/import` | POST | 异步任务 `{jobId, total, totalBytes}` |
@@ -100,12 +102,13 @@ GitHub 仓库 ──扫描/导入──▶ ~/.dsh/skills
100
102
  | `/api/skill-hub/repo/import/cancel` | POST | 取消任务 |
101
103
  | `/api/skill-hub/sources` 等 | GET/POST | 来源 列表/检查/同步/删除/恢复/清空回收站 |
102
104
  | `/api/skill-hub/update` | GET | 插件最新发布 |
105
+ | 未知的 `/api/skill-hub/*` | GET/POST | `404 {error}` 且写明路径 —— 拼错路径不该被读成鉴权失败(宿主 SPA fallback 对自己不拥有的 `/api/*` 一律回 401) |
103
106
 
104
107
  ## 开发
105
108
 
106
109
  ```bash
107
110
  npm run typecheck # tsc --noEmit
108
- npm test # 176 tests, 9 suites
111
+ npm test # 255 tests, 14 suites
109
112
  npm run build # tsc + tsdown → lib/index.js + lib/client.js
110
113
  ```
111
114
 
@@ -117,6 +120,7 @@ npm run build # tsc + tsdown → lib/index.js + lib/client.js
117
120
  - 技能不出现 — 看诊断区(缺 frontmatter / 名称不一致 / 描述过短)。
118
121
  - 来源组空壳 — 组内技能已被删除、或禁用记录丢失(状态文件被恢复/手改)。启动时自动对账磁盘上的 `.disabled` 文件补记录;无可见成员的来源组不再渲染。
119
122
  - `/` 菜单圆点消失 — dsh 内部触发源变更,目录功能不受影响。
123
+ - 找不到配置卡片 — 在插件管理页打开本插件(侧边栏「插件」→ dsh-skill-hub),展开页面顶部的「技能中枢」卡片(默认折叠)。dsh 低于 `0.1.7-alpha.1` 时本插件无法加载(它所用的 settings API 在旧版不存在)。
120
124
 
121
125
  ## 社区
122
126
 
package/lib/client.js CHANGED
@@ -7,7 +7,13 @@ window.__ModuleLoader__.load({
7
7
  let react = require("react");
8
8
  let react_jsx_runtime = require("react/jsx-runtime");
9
9
  //#region src/protocol/api.ts
10
- /** Browser-facing base paths of the skill-hub API family. */
10
+ /**
11
+ * Browser-facing base paths of the skill-hub API family.
12
+ *
13
+ * Naming rule: a path's segments mirror its scope. Market sources own the
14
+ * `/market/source/*` subtree — add, delete, ref, versions, check, sync — so
15
+ * the update check and the sync that acts on its result sit side by side.
16
+ */
11
17
  const SKILL_HUB_API = {
12
18
  catalog: "/api/skill-hub/catalog",
13
19
  skill: "/api/skill-hub/skill",
@@ -21,7 +27,7 @@ window.__ModuleLoader__.load({
21
27
  marketSource: "/api/skill-hub/market/source",
22
28
  marketSourceDelete: "/api/skill-hub/market/source/delete",
23
29
  marketSourceRef: "/api/skill-hub/market/source/ref",
24
- marketCheck: "/api/skill-hub/market/check",
30
+ marketCheck: "/api/skill-hub/market/source/check",
25
31
  marketSync: "/api/skill-hub/market/source/sync",
26
32
  repo: "/api/skill-hub/repo",
27
33
  repoImport: "/api/skill-hub/repo/import",
@@ -46,6 +52,16 @@ window.__ModuleLoader__.load({
46
52
  marketStats: "/api/skill-hub/market/stats"
47
53
  };
48
54
  //#endregion
55
+ //#region src/protocol/config.ts
56
+ /**
57
+ * This plugin's Loader entry id — the settings namespace dsh serves its config
58
+ * under. It is cordis.patch.yml's insert id, NOT the package name, and it is
59
+ * shared by contract because the browser half addresses the same form through
60
+ * `ctx.configForms.get(HUB_ENTRY_ID)` while the host half writes through
61
+ * `ctx.settings.update(HUB_ENTRY_ID, …)`.
62
+ */
63
+ const HUB_ENTRY_ID = "skill-hub";
64
+ //#endregion
49
65
  //#region src/protocol/sources.ts
50
66
  /** 项目级技能来源(它们有 workspace 归属,不属于「个人」组)。 */
51
67
  function isProjectSource(source) {
@@ -480,6 +496,7 @@ window.__ModuleLoader__.load({
480
496
  "repo.cancel": "取消",
481
497
  "repo.cancelled": "已取消 · 已导入 {imported}/{total} 已保留,临时文件已清理",
482
498
  "repo.importingCurrent": "正在导入: {name} ({done}/{total})",
499
+ "repo.root.self": "仓库根",
483
500
  "repo.root.skills": "skills",
484
501
  "repo.root.designTemplates": "design-templates",
485
502
  "repo.root.generic": "{root}"
@@ -559,6 +576,7 @@ window.__ModuleLoader__.load({
559
576
  "repo.cancel": "Cancel",
560
577
  "repo.cancelled": "Cancelled · {imported}/{total} kept, temp files cleaned",
561
578
  "repo.importingCurrent": "Importing: {name} ({done}/{total})",
579
+ "repo.root.self": "Repo root",
562
580
  "repo.root.skills": "Skills",
563
581
  "repo.root.designTemplates": "Templates",
564
582
  "repo.root.generic": "{root}"
@@ -3836,7 +3854,7 @@ window.__ModuleLoader__.load({
3836
3854
  const visible = visibleCollections(groupsState?.collections ?? [], sourceFiltered, catalog?.disabled ?? [], normalized, sourceFilter, origins);
3837
3855
  const collections = visible.map((entry) => entry.collection);
3838
3856
  const uncategorized = sourceFiltered.filter((skill) => origins[skill.name] === void 0 && !isProjectSource(skill.source));
3839
- const personalDisabled = (catalog?.disabled ?? []).filter((record) => origins[record.name] === void 0).filter((record) => normalized.length === 0 || record.name.toLocaleLowerCase().includes(normalized) || record.description.toLocaleLowerCase().includes(normalized)).filter((record) => sourceFilter === "all" || sourceFilter === "private");
3857
+ const personalDisabled = (catalog?.disabled ?? []).filter((record) => origins[record.name] === void 0).filter((record) => normalized.length === 0 || record.name.toLocaleLowerCase().includes(normalized) || record.description.toLocaleLowerCase().includes(normalized)).filter(() => sourceFilter === "all" || sourceFilter === "private");
3840
3858
  const allPersonalNames = [...uncategorized.map((s) => s.name), ...personalDisabled.map((r) => r.name)];
3841
3859
  const hasPersonal = allPersonalNames.length > 0;
3842
3860
  const defaultTopKeys = [
@@ -4737,8 +4755,11 @@ window.__ModuleLoader__.load({
4737
4755
  /**
4738
4756
  * 已知技能根的显示名键;未知根直接显示目录名。
4739
4757
  * zh 字典里这两项就是目录名本身(与接线前的硬编码文本一致)。
4758
+ * 空串是「技能就在仓库根」的哨兵根(host 侧 REPO_ROOT),目录名无从显示,
4759
+ * 给它一个可读标签,否则筛选按钮会是一片空白。
4740
4760
  */
4741
4761
  function rootLabelKey(root) {
4762
+ if (root === "") return "repo.root.self";
4742
4763
  if (root === "skills") return "repo.root.skills";
4743
4764
  if (root === "design-templates") return "repo.root.designTemplates";
4744
4765
  return "repo.root.generic";
@@ -4899,7 +4920,7 @@ window.__ModuleLoader__.load({
4899
4920
  " ",
4900
4921
  counts.get(root) ?? 0
4901
4922
  ]
4902
- }, root))
4923
+ }, root === "" ? "repo-root" : root))
4903
4924
  ]
4904
4925
  });
4905
4926
  })(),
@@ -4989,7 +5010,7 @@ window.__ModuleLoader__.load({
4989
5010
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4990
5011
  className: panel_module_css_default.rowDesc,
4991
5012
  children: [
4992
- entry.dir,
5013
+ entry.dir === "" ? tt("repo.root.self") : entry.dir,
4993
5014
  " · ",
4994
5015
  tt("repo.files", {
4995
5016
  count: entry.fileCount,
@@ -6917,7 +6938,7 @@ window.__ModuleLoader__.load({
6917
6938
  const [workspaceDraft, setWorkspaceDraft] = (0, react.useState)("");
6918
6939
  /** 「筛选」面板开合(来源 + 调用方式收进这里;搜索/排序/视图切换始终可见)。 */
6919
6940
  const [filtersOpen, setFiltersOpen] = (0, react.useState)(false);
6920
- const { catalog, loading, loadError, successBanner, updateState, detail, detailLoading, showForm, formName, formDesc, formRoot, formBusy, formMessage, hubConfig, tab, skillView, sourceFilter, sortKey, search, workspace, setWorkspace, sourcesState, tagBusy, batchBusy, busyNames, normalized, origins, sourceOptions, filtered, conflictDialog, confirmDialog, deleteSkillDialog, deleteGroupDialog, confirmClearTrash, branchChoice, branchBusy, marketSyncDialog, syncBusy, editingTag, editName, membersDraft, editSearch, uses, groupsState, sourceCheck, checkingSource, syncingSource, showLegend, editMode, setLoadError, setSuccessBanner, setDetail, setShowForm, setFormName, setFormDesc, setFormRoot, setFormMessage, setTab, setSkillView, setSourceFilter, setSortKey, setSearch, setConflictDialog, setConfirmDialog, setDeleteSkillDialog, setDeleteGroupDialog, setConfirmClearTrash, setBranchChoice, setMarketSyncDialog, setEditingTag, setEditName, setMembersDraft, setEditSearch, setShowLegend, setEditMode, checkUpdate, loadMarket, checkSources, requestSync, requestDelete, restoreTrash, clearTrash, runDeleteSkill, runDeleteGroup, runConfirmed, resolveConflict, confirmBranchChoice, confirmMarketSync, create, saveTag, deleteTag, enableDisabled } = hub;
6941
+ const { catalog, loading, loadError, successBanner, updateState, detail, detailLoading, showForm, formName, formDesc, formRoot, formBusy, formMessage, hubConfig, tab, skillView, sourceFilter, sortKey, search, workspace, setWorkspace, sourcesState, tagBusy, batchBusy, sourceOptions, filtered, conflictDialog, confirmDialog, deleteSkillDialog, deleteGroupDialog, confirmClearTrash, branchChoice, branchBusy, marketSyncDialog, syncBusy, editingTag, editName, membersDraft, editSearch, uses, groupsState, sourceCheck, checkingSource, syncingSource, showLegend, editMode, setLoadError, setSuccessBanner, setDetail, setShowForm, setFormName, setFormDesc, setFormRoot, setFormMessage, setTab, setSkillView, setSourceFilter, setSortKey, setSearch, setConflictDialog, setConfirmDialog, setDeleteSkillDialog, setDeleteGroupDialog, setConfirmClearTrash, setBranchChoice, setMarketSyncDialog, setEditingTag, setEditName, setMembersDraft, setEditSearch, setShowLegend, setEditMode, checkUpdate, loadMarket, checkSources, requestSync, requestDelete, restoreTrash, clearTrash, runDeleteSkill, runDeleteGroup, runConfirmed, resolveConflict, confirmBranchChoice, confirmMarketSync, create, saveTag, deleteTag, enableDisabled } = hub;
6921
6942
  const { shortenedCount, fixingPaths, clearListFilters } = hub;
6922
6943
  if (detail !== null) {
6923
6944
  const disabledRecord = catalog?.disabled.find((record) => record.name === detail.name);
@@ -7564,16 +7585,16 @@ window.__ModuleLoader__.load({
7564
7585
  /**
7565
7586
  * Required services (fiber inject waiting — the runtime must be up first).
7566
7587
  * `connection`/`remote` are the settings transport's own prerequisites
7567
- * (`ctx.settingsScope.bind` resolves them on the caller's fiber), and
7568
- * `settingsScope` is the namespace-scope binder itself; mirror the official
7569
- * settings-plugins inject list.
7588
+ * (`ctx.configForms.get` resolves them on the caller's fiber), and
7589
+ * `configForms` is the shared settings-form service itself; mirror the
7590
+ * official settings-plugins inject list.
7570
7591
  */
7571
7592
  const inject = [
7572
7593
  "slots",
7573
7594
  "locale",
7574
7595
  "connection",
7575
7596
  "remote",
7576
- "settingsScope",
7597
+ "configForms",
7577
7598
  "inputTriggers"
7578
7599
  ];
7579
7600
  /**
@@ -7587,7 +7608,7 @@ window.__ModuleLoader__.load({
7587
7608
  }), "dsh-skill-hub: dictionaries");
7588
7609
  const t = ctx.locale.bind(NS);
7589
7610
  const api = new SkillHubApi();
7590
- const scope = ctx.settingsScope.bind({ namespace: NS });
7611
+ const scope = ctx.configForms.get(HUB_ENTRY_ID);
7591
7612
  const settingsCard = new SkillHubSettingsCardController(scope);
7592
7613
  ctx.effect(() => setupSkillSlashDots(ctx, api, scope), "dsh-skill-hub: slash dots");
7593
7614
  ctx.effect(() => ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({