dsh-agent-plugins-market 0.4.3

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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -0
  3. package/README.zh.md +171 -0
  4. package/client/client.js +954 -0
  5. package/client/client.js.map +1 -0
  6. package/cordis.patch.yml +4 -0
  7. package/lib/commands-mounts.js +169 -0
  8. package/lib/context.js +80 -0
  9. package/lib/discovery/manifests.js +214 -0
  10. package/lib/discovery/surfaces.js +232 -0
  11. package/lib/discovery.js +234 -0
  12. package/lib/git.js +52 -0
  13. package/lib/hooks-mounts.js +95 -0
  14. package/lib/index.js +73 -0
  15. package/lib/manager.js +490 -0
  16. package/lib/mcp-config.js +100 -0
  17. package/lib/mcp-mounts.js +88 -0
  18. package/lib/paths.js +85 -0
  19. package/lib/routes.js +208 -0
  20. package/lib/skills-parse.js +114 -0
  21. package/lib/skills-provider.js +170 -0
  22. package/lib/state.js +64 -0
  23. package/lib/types/commands-mounts.d.ts +29 -0
  24. package/lib/types/context.d.ts +13 -0
  25. package/lib/types/discovery/manifests.d.ts +55 -0
  26. package/lib/types/discovery/surfaces.d.ts +15 -0
  27. package/lib/types/discovery.d.ts +16 -0
  28. package/lib/types/git.d.ts +8 -0
  29. package/lib/types/hooks-mounts.d.ts +19 -0
  30. package/lib/types/index.d.ts +27 -0
  31. package/lib/types/manager.d.ts +87 -0
  32. package/lib/types/mcp-config.d.ts +28 -0
  33. package/lib/types/mcp-mounts.d.ts +31 -0
  34. package/lib/types/paths.d.ts +29 -0
  35. package/lib/types/routes.d.ts +11 -0
  36. package/lib/types/skills-parse.d.ts +22 -0
  37. package/lib/types/skills-provider.d.ts +16 -0
  38. package/lib/types/state.d.ts +6 -0
  39. package/lib/types/types.d.ts +165 -0
  40. package/lib/types/validate.d.ts +34 -0
  41. package/lib/types.js +10 -0
  42. package/lib/validate.js +199 -0
  43. package/package.json +114 -0
  44. package/schemas/1.0.0/mcp.schema.json +120 -0
  45. package/schemas/1.0.0/plugin.schema.json +65 -0
  46. package/schemas/README.md +14 -0
@@ -0,0 +1,954 @@
1
+ window.__ModuleLoader__.load({ id: "dsh-agent-plugins-market", factory: (require) => {
2
+
3
+ var module = { exports: {} };
4
+ var exports = module.exports;
5
+ (function(){if(typeof document!=="undefined"){var s=document.createElement("style");s.setAttribute("data-dsh-client","dsh-agent-plugins-market");s.textContent=".qMtKNa_market {\n min-width: 0;\n height: 100%;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n gap: 14px;\n display: flex;\n}\n\n.qMtKNa_header {\n flex-direction: column;\n flex-shrink: 0;\n gap: 8px;\n display: flex;\n}\n\n.qMtKNa_titleRow {\n align-items: center;\n gap: 12px;\n display: flex;\n}\n\n.qMtKNa_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.qMtKNa_sub {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n align-items: center;\n gap: 8px;\n min-width: 0;\n margin: 0;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n overflow: hidden;\n}\n\n.qMtKNa_spacer {\n flex: 1;\n}\n\n.qMtKNa_tabGap {\n flex-shrink: 0;\n width: 16px;\n}\n\n.qMtKNa_searchGroup {\n align-items: center;\n gap: 2px;\n display: flex;\n}\n\n.qMtKNa_searchWrap, .qMtKNa_searchInput {\n align-items: center;\n display: flex;\n}\n\n.qMtKNa_searchInput input {\n width: 240px;\n font-size: 12px;\n line-height: 20px;\n}\n\n.qMtKNa_tabRow {\n border-bottom: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n justify-content: flex-end;\n align-items: flex-end;\n gap: 2px;\n display: flex;\n}\n\n.qMtKNa_tab, .qMtKNa_tabOn {\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n white-space: nowrap;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n padding: 7px 12px;\n font-size: 13px;\n}\n\n.qMtKNa_tabOn {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n border-bottom-color: var(--dsw-alias-brand-primary, #4f6ef7);\n font-weight: 600;\n}\n\n.qMtKNa_viewSwitch {\n font: inherit;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n cursor: pointer;\n white-space: nowrap;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n padding: 7px 12px;\n font-size: 13px;\n}\n\n.qMtKNa_viewSwitch:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.qMtKNa_body {\n flex: 1;\n align-items: flex-start;\n gap: 20px;\n min-height: 0;\n display: flex;\n}\n\n.qMtKNa_sourceTabsRow {\n padding: 0;\n display: block;\n}\n\n.qMtKNa_sourceTabsScroll {\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n gap: 6px;\n display: grid;\n}\n\n.qMtKNa_srcTabEdit {\n font: inherit;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n cursor: pointer;\n background: none;\n border: none;\n flex-shrink: 0;\n padding: 2px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.qMtKNa_srcTabEdit:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.qMtKNa_srcTabOn .qMtKNa_srcTabEdit {\n color: #ffffffd9;\n}\n\n.qMtKNa_srcTabOn .qMtKNa_srcTabEdit:hover {\n color: #fff;\n}\n\n.qMtKNa_srcTab, .qMtKNa_srcTabOn {\n border: 1px solid var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-layer-1, #fff);\n border-radius: 999px;\n justify-content: center;\n align-items: center;\n width: 100%;\n height: 24px;\n display: inline-flex;\n overflow: hidden;\n}\n\n.qMtKNa_srcTabMain {\n font: inherit;\n color: var(--dsw-alias-label-primary, #1f2328);\n cursor: pointer;\n white-space: nowrap;\n text-overflow: ellipsis;\n background: none;\n border: none;\n flex: 1;\n min-width: 0;\n padding: 2px 2px 2px 10px;\n font-size: 12px;\n line-height: 18px;\n overflow: hidden;\n}\n\n.qMtKNa_srcTabMain:hover {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n\n.qMtKNa_srcTabOn {\n background: var(--dsw-alias-brand-primary, #4f6ef7);\n border-color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n\n.qMtKNa_srcTabOn .qMtKNa_srcTabMain {\n color: #fff;\n font-weight: 600;\n}\n\n.qMtKNa_srcTabDel {\n font: inherit;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n cursor: pointer;\n background: none;\n border: none;\n flex-shrink: 0;\n padding: 2px 8px 2px 2px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.qMtKNa_srcTabDel:hover {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.qMtKNa_srcTabOn .qMtKNa_srcTabDel {\n color: #ffffffd9;\n}\n\n.qMtKNa_srcTabOn .qMtKNa_srcTabDel:hover {\n color: #fff;\n}\n\n.qMtKNa_grid {\n scrollbar-gutter: stable;\n flex: 1;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n align-content: start;\n gap: 12px;\n min-width: 0;\n min-height: 0;\n padding-right: 4px;\n display: grid;\n overflow-y: auto;\n}\n\n.qMtKNa_list {\n scrollbar-gutter: stable;\n flex-direction: column;\n flex: 1;\n gap: 8px;\n min-width: 0;\n min-height: 0;\n padding-right: 4px;\n display: flex;\n overflow-y: auto;\n}\n\n.qMtKNa_list .qMtKNa_card {\n flex-flow: wrap;\n align-items: center;\n gap: 8px 14px;\n}\n\n.qMtKNa_list .qMtKNa_cardTop {\n flex: none;\n}\n\n.qMtKNa_list .qMtKNa_cardDesc {\n -webkit-line-clamp: 1;\n flex: 1;\n min-width: 200px;\n min-height: 0;\n}\n\n.qMtKNa_list .qMtKNa_cardActions {\n flex: none;\n}\n\n.qMtKNa_list .qMtKNa_meta {\n flex-basis: 100%;\n}\n\n.qMtKNa_empty {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-align: center;\n grid-column: 1 / -1;\n padding: 48px 0;\n font-size: 13px;\n}\n\n.qMtKNa_card {\n background: var(--dsw-alias-bg-layer-1, #fff);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 12px;\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n padding: 12px 14px;\n display: flex;\n}\n\n.qMtKNa_cardTop {\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n.qMtKNa_cardTitle {\n flex: 1;\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.qMtKNa_cardName {\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n font-weight: 600;\n line-height: 22px;\n overflow: hidden;\n}\n\n.qMtKNa_version {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-variant-numeric: tabular-nums;\n flex-shrink: 0;\n font-size: 12px;\n line-height: 20px;\n}\n\n.qMtKNa_cardActions {\n flex-shrink: 0;\n align-items: center;\n gap: 4px;\n display: flex;\n}\n\n.qMtKNa_switchOn, .qMtKNa_switchOff {\n cursor: pointer;\n border: none;\n border-radius: 999px;\n flex-shrink: 0;\n width: 38px;\n height: 22px;\n padding: 0;\n transition: background-color .15s;\n position: relative;\n}\n\n.qMtKNa_switchOn {\n background: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n.qMtKNa_switchOff {\n background: var(--dsw-alias-state-neutral, #d1d5db);\n}\n\n.qMtKNa_switchOn:disabled, .qMtKNa_switchOff:disabled {\n opacity: .6;\n cursor: default;\n}\n\n.qMtKNa_switchThumb {\n pointer-events: none;\n background: #fff;\n border-radius: 50%;\n width: 16px;\n height: 16px;\n transition: left .15s;\n position: absolute;\n top: 3px;\n left: 3px;\n box-shadow: 0 1px 2px #0003;\n}\n\n.qMtKNa_switchOn .qMtKNa_switchThumb {\n left: 19px;\n}\n\n.qMtKNa_desc {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n min-height: 36px;\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n display: -webkit-box;\n overflow: hidden;\n}\n\n.qMtKNa_meta {\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.qMtKNa_src {\n color: var(--dsw-alias-label-secondary, #9ca3af);\n font-size: 12px;\n text-decoration: none;\n}\n\n.qMtKNa_tag {\n border: 1px solid var(--dsw-alias-border-l3, #d9dde3);\n color: var(--dsw-alias-label-secondary, #6b7280);\n border-radius: 4px;\n flex-shrink: 0;\n padding: 1px 6px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.qMtKNa_okState {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n white-space: nowrap;\n font-size: 12px;\n font-weight: 600;\n}\n\n.qMtKNa_warnLine {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n cursor: help;\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n}\n\n.qMtKNa_modalFooter {\n justify-content: flex-end;\n gap: 8px;\n width: 100%;\n display: flex;\n}\n\n.qMtKNa_modalFooterLeft {\n gap: 8px;\n margin-right: auto;\n display: flex;\n}\n\n.qMtKNa_editorDialog {\n width: min(500px, 92vw);\n}\n\n.qMtKNa_editorForm {\n flex-direction: column;\n gap: 14px;\n min-width: 0;\n display: flex;\n}\n\n.qMtKNa_modeRow {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-2, #f3f4f6);\n border-radius: 10px;\n align-self: flex-start;\n gap: 6px;\n padding: 3px;\n display: flex;\n}\n\n.qMtKNa_seg, .qMtKNa_segOn {\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 8px;\n padding: 5px 14px;\n font-size: 13px;\n line-height: 20px;\n}\n\n.qMtKNa_segOn {\n background: var(--dsw-alias-bg-layer-1, #fff);\n color: var(--dsw-alias-label-primary, #1f2328);\n font-weight: 600;\n box-shadow: 0 1px 2px #00000014;\n}\n\n.qMtKNa_fieldGroup {\n flex-direction: column;\n gap: 5px;\n display: flex;\n}\n\n.qMtKNa_fieldLabel {\n color: var(--dsw-alias-label-secondary, #6b7280);\n font-size: 12px;\n font-weight: 600;\n}\n\n.qMtKNa_fieldHint {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 12px;\n line-height: 16px;\n}\n\n.qMtKNa_staticId {\n border: 1px dashed var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-layer-2, #f3f4f6);\n border-radius: 8px;\n align-items: center;\n gap: 8px;\n padding: 7px 10px;\n display: flex;\n}\n\n.qMtKNa_staticIdValue {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-size: 13px;\n font-weight: 600;\n}\n\n.qMtKNa_detailDialog {\n width: min(800px, 94vw);\n}\n\n.qMtKNa_detailBody {\n flex-direction: column;\n gap: 14px;\n max-height: 78vh;\n display: flex;\n overflow-y: auto;\n}\n\n.qMtKNa_detailSections {\n flex-direction: column;\n gap: 14px;\n display: flex;\n}\n\n.qMtKNa_detailSection {\n flex-direction: column;\n gap: 6px;\n display: flex;\n}\n\n.qMtKNa_detailHead {\n color: var(--dsw-alias-label-secondary, #6b7280);\n border-bottom: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n margin: 0;\n padding-bottom: 4px;\n font-size: 13px;\n font-weight: 600;\n}\n\n.qMtKNa_detailGrid {\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: 6px 14px;\n display: grid;\n}\n\n.qMtKNa_detailCell {\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n display: flex;\n}\n\n.qMtKNa_detailKey {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 12px;\n}\n\n.qMtKNa_detailValue {\n color: var(--dsw-alias-label-primary, #1f2328);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n overflow: hidden;\n}\n\n.qMtKNa_detailDesc {\n color: var(--dsw-alias-label-secondary, #6b7280);\n margin: 4px 0 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n.qMtKNa_mono {\n word-break: break-all;\n white-space: pre-wrap;\n color: var(--dsw-alias-label-primary, #1f2328);\n margin: 0;\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 12px;\n line-height: 18px;\n}\n\n.qMtKNa_detailItem {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n flex-direction: column;\n display: flex;\n overflow: hidden;\n}\n\n.qMtKNa_detailItemRow, .qMtKNa_detailItemOpen {\n width: 100%;\n font: inherit;\n text-align: left;\n cursor: pointer;\n color: var(--dsw-alias-label-primary, #1f2328);\n background: none;\n border: none;\n align-items: center;\n gap: 8px;\n padding: 7px 10px;\n display: flex;\n}\n\n.qMtKNa_detailItemRow:hover {\n background: var(--dsw-alias-bg-hover, #0000000d);\n}\n\n.qMtKNa_detailItemOpen {\n background: var(--dsw-alias-bg-selected, #4f6ef714);\n}\n\n.qMtKNa_detailItemName {\n flex-shrink: 0;\n font-size: 13px;\n font-weight: 600;\n}\n\n.qMtKNa_detailItemDesc {\n min-width: 0;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n font-size: 12px;\n overflow: hidden;\n}\n\n.qMtKNa_detailChevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n flex-shrink: 0;\n}\n\n.qMtKNa_skillContent {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n max-height: 320px;\n color: var(--dsw-alias-label-primary, #1f2328);\n padding: 10px 12px;\n font-size: 13px;\n line-height: 20px;\n overflow-y: auto;\n}\n";document.head.appendChild(s);}})();
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ //#region \0rolldown/runtime.js
8
+ var __create = Object.create;
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
+ var __getOwnPropNames = Object.getOwnPropertyNames;
12
+ var __getProtoOf = Object.getPrototypeOf;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
16
+ key = keys[i];
17
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
18
+ get: ((k) => from[k]).bind(null, key),
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
25
+ value: mod,
26
+ enumerable: true
27
+ }) : target, mod));
28
+ //#endregion
29
+ let react = require("react");
30
+ let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
31
+ _deepseek_ai_dsh_client_ui_primitives = __toESM(_deepseek_ai_dsh_client_ui_primitives, 1);
32
+ //#region src/client/locales.ts
33
+ const zh = {
34
+ nav: "Agent Plugins 市场",
35
+ subtitle: "发现与安装 Agent Plugins(agent-plugins.org 便携包)",
36
+ searchPh: "搜索 Agent Plugins…",
37
+ tabAll: "全部",
38
+ tabInstalled: "已安装",
39
+ tabUninstalled: "未安装",
40
+ market: "仓库源",
41
+ addSource: "添加源",
42
+ sourceIdPh: "源 id(小写字母数字)",
43
+ sourceUrlPh: "git 仓库地址",
44
+ sourceUrlLocalPh: "本地仓库路径(绝对路径或 ~/…)",
45
+ sourceModeGit: "远程 git",
46
+ sourceModeLocal: "本地目录",
47
+ branchPh: "分支(可选)",
48
+ sourceLocal: "本地",
49
+ editSource: "编辑当前源",
50
+ editSourceTitle: "编辑仓库源",
51
+ addSourceTitle: "新增仓库源",
52
+ save: "保存",
53
+ confirmDelete: "确认删除",
54
+ refreshAll: "刷新全部",
55
+ detailTitle: "Agent Plugins 详情",
56
+ overviewSection: "概览",
57
+ skillsSection: "技能",
58
+ mcpSection: "MCP 服务",
59
+ commandsSection: "命令",
60
+ agentsSection: "子代理",
61
+ hooksLabel: "Hooks",
62
+ sourceLabel: "来源",
63
+ dimensionLabel: "维度",
64
+ layoutLabel: "布局",
65
+ statusLabel: "状态",
66
+ authorLabel: "作者",
67
+ keywordsLabel: "关键词",
68
+ disabledLabel: "已停用",
69
+ notInstalledLabel: "未安装",
70
+ noSkills: "(无技能)",
71
+ noMcp: "(无 MCP 服务)",
72
+ loading: "加载中…",
73
+ lspSection: "LSP 服务",
74
+ editorHint: "仓库源提供 Agent Plugins。本地目录直接读取(实时反映工作树);git 源克隆到 ~/.dsh/agent-plugins/.sources/<id>。",
75
+ idHint: "小写字母/数字/连字符,全局唯一",
76
+ urlGitHint: "git 仓库地址,例如 https://github.com/org/repo.git",
77
+ urlLocalHint: "绝对路径或 ~/…,直接读取本地目录(不克隆、移除源时不会删除)",
78
+ branchHint: "可选;不填则跟踪默认分支",
79
+ idFixed: "id 不可修改(源标识全局唯一)",
80
+ idAutoLabel: "源 ID(自动生成)",
81
+ idAutoHint: "自动从插件清单名或仓库名解析,无需填写",
82
+ detailHint: "点击技能或 MCP 服务行可展开查看详情",
83
+ add: "添加",
84
+ remove: "移除",
85
+ refresh: "刷新",
86
+ install: "安装",
87
+ installing: "安装中…",
88
+ installedBadge: "已安装",
89
+ uninstall: "卸载",
90
+ uninstallConfirmTitle: "卸载 Agent Plugins",
91
+ uninstallConfirmDesc: "将从已安装列表移除该 Agent Plugins,其技能与 MCP 工具随即停止注入。仓库源克隆保留。",
92
+ removeSourceConfirmTitle: "移除仓库源",
93
+ removeSourceConfirmDesc: "将删除该源的本地克隆与全部安装记录。",
94
+ enable: "启用",
95
+ disable: "禁用",
96
+ cancel: "取消",
97
+ confirm: "确认",
98
+ empty: "没有匹配的 Agent Plugins",
99
+ installedEmpty: "还没有安装 Agent Plugins",
100
+ loadFail: "Agent Plugins 目录加载失败,请稍后重试",
101
+ actionFail: "操作失败",
102
+ version: "版本",
103
+ dimensionUser: "用户级",
104
+ dimensionProject: "项目级",
105
+ layoutV1: "便携 v1",
106
+ layoutCC: "Claude Code",
107
+ layoutCodex: "Codex",
108
+ layoutSkills: "技能集合",
109
+ layoutUniversal: "通用",
110
+ layoutCursor: "Cursor",
111
+ layoutKimi: "Kimi",
112
+ layoutRemote: "远程引用",
113
+ remoteRef: "远程",
114
+ surfaceSkills: "技能",
115
+ surfaceMcp: "MCP",
116
+ surfaceHooks: "Hooks",
117
+ surfaceCommands: "命令",
118
+ surfaceAgents: "子代理",
119
+ surfaceLsp: "LSP",
120
+ sourceNotCloned: "未克隆",
121
+ sourceCloned: "已克隆",
122
+ errors: "校验问题",
123
+ grid: "网格",
124
+ list: "列表",
125
+ openSettings: "在设置中打开",
126
+ rootLabel: "Agent Plugins 目录",
127
+ dataLabel: "Agent Plugins 数据目录",
128
+ countAll: "共 {n} 个 Agent Plugins",
129
+ countInstalled: "已装 {n}",
130
+ countEnabled: "启用 {n}"
131
+ };
132
+ const en = {
133
+ nav: "Agent Plugins Market",
134
+ subtitle: "Discover and install Agent Plugins suites (agent-plugins.org portable packages)",
135
+ searchPh: "Search suites…",
136
+ tabAll: "All",
137
+ tabInstalled: "Installed",
138
+ tabUninstalled: "Uninstalled",
139
+ market: "Sources",
140
+ addSource: "Add source",
141
+ sourceIdPh: "source id (lowercase alnum)",
142
+ sourceUrlPh: "git repository URL",
143
+ sourceUrlLocalPh: "local repository path (absolute or ~/…)",
144
+ sourceModeGit: "remote git",
145
+ sourceModeLocal: "local dir",
146
+ branchPh: "branch (optional)",
147
+ sourceLocal: "local",
148
+ editSource: "Edit source",
149
+ editSourceTitle: "Edit source",
150
+ addSourceTitle: "Add source",
151
+ save: "Save",
152
+ confirmDelete: "Delete",
153
+ refreshAll: "Refresh all",
154
+ detailTitle: "Suite details",
155
+ overviewSection: "Overview",
156
+ skillsSection: "Skills",
157
+ mcpSection: "MCP servers",
158
+ commandsSection: "Commands",
159
+ agentsSection: "Subagents",
160
+ hooksLabel: "Hooks",
161
+ sourceLabel: "Source",
162
+ dimensionLabel: "Dimension",
163
+ layoutLabel: "Layout",
164
+ statusLabel: "Status",
165
+ authorLabel: "Author",
166
+ keywordsLabel: "Keywords",
167
+ disabledLabel: "disabled",
168
+ notInstalledLabel: "not installed",
169
+ noSkills: "(no skills)",
170
+ noMcp: "(no MCP servers)",
171
+ loading: "Loading…",
172
+ lspSection: "LSP servers",
173
+ editorHint: "A source provides suites (Agent Plugins). Local directories are read in place (live working tree); git sources clone into ~/.dsh/agent-plugins/.sources/<id>.",
174
+ idHint: "lowercase letters / digits / hyphens, globally unique",
175
+ urlGitHint: "git repository URL, e.g. https://github.com/org/repo.git",
176
+ urlLocalHint: "absolute path or ~/…, read in place (never cloned, never deleted on removal)",
177
+ branchHint: "optional; defaults to the repository default branch",
178
+ idFixed: "id is fixed (the source identifier is globally unique)",
179
+ idAutoLabel: "Source ID (auto)",
180
+ idAutoHint: "Derived from the suite or repo name — no need to type it",
181
+ detailHint: "Click a skill or MCP server row to expand its details",
182
+ add: "Add",
183
+ remove: "Remove",
184
+ refresh: "Refresh",
185
+ install: "Install",
186
+ installing: "Installing…",
187
+ installedBadge: "Installed",
188
+ uninstall: "Uninstall",
189
+ uninstallConfirmTitle: "Uninstall suite",
190
+ uninstallConfirmDesc: "Removes the suite from the installed list; its skills and MCP tools stop injecting. The source clone stays.",
191
+ removeSourceConfirmTitle: "Remove source",
192
+ removeSourceConfirmDesc: "Deletes the local clone and all install records of this source.",
193
+ enable: "Enable",
194
+ disable: "Disable",
195
+ cancel: "Cancel",
196
+ confirm: "Confirm",
197
+ empty: "No matching suites",
198
+ installedEmpty: "No suites installed yet",
199
+ loadFail: "Failed to load the suite catalog, try again later",
200
+ actionFail: "Action failed",
201
+ version: "Version",
202
+ dimensionUser: "user",
203
+ dimensionProject: "project",
204
+ layoutV1: "portable v1",
205
+ layoutCC: "Claude Code",
206
+ layoutCodex: "Codex",
207
+ layoutSkills: "skill dir",
208
+ layoutUniversal: "universal",
209
+ layoutCursor: "Cursor",
210
+ layoutKimi: "Kimi",
211
+ layoutRemote: "remote reference",
212
+ remoteRef: "remote",
213
+ surfaceSkills: "skills",
214
+ surfaceMcp: "MCP",
215
+ surfaceHooks: "hooks",
216
+ surfaceCommands: "commands",
217
+ surfaceAgents: "subagents",
218
+ surfaceLsp: "LSP",
219
+ sourceNotCloned: "not cloned",
220
+ sourceCloned: "cloned",
221
+ errors: "validation issues",
222
+ grid: "grid",
223
+ list: "list",
224
+ openSettings: "Open in settings",
225
+ rootLabel: "Suite root",
226
+ dataLabel: "Suite data root",
227
+ countAll: "{n} suites",
228
+ countInstalled: "{n} installed",
229
+ countEnabled: "{n} enabled"
230
+ };
231
+ //#endregion
232
+ //#region src/client/api.ts
233
+ async function fetchOverview() {
234
+ const response = await fetch("/api/agent-plugins/overview", { credentials: "same-origin" });
235
+ if (!response.ok) throw new Error(`overview failed: ${response.status}`);
236
+ return response.json();
237
+ }
238
+ async function fetchSuiteDetail(sourceId, suiteId) {
239
+ const response = await fetch(`/api/agent-plugins/suite?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}`, { credentials: "same-origin" });
240
+ if (!response.ok) throw new Error(`suite detail failed: ${response.status}`);
241
+ return response.json();
242
+ }
243
+ async function fetchSkillContent(sourceId, suiteId, skill) {
244
+ const response = await fetch(`/api/agent-plugins/skill?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}&skill=${encodeURIComponent(skill)}`, { credentials: "same-origin" });
245
+ if (!response.ok) throw new Error(`skill content failed: ${response.status}`);
246
+ return response.json();
247
+ }
248
+ async function postAction(path, body) {
249
+ const response = await fetch(`/api/agent-plugins/${path}`, {
250
+ method: "POST",
251
+ credentials: "same-origin",
252
+ headers: { "content-type": "application/json" },
253
+ body: JSON.stringify(body)
254
+ });
255
+ const payload = await response.json();
256
+ if (!response.ok || payload.ok !== true) throw new Error(payload.error ?? `request failed: ${response.status}`);
257
+ return payload;
258
+ }
259
+ //#endregion
260
+ //#region src/client/ErrorBoundary.tsx
261
+ /**
262
+ * Error boundary for untrusted preview content.
263
+ *
264
+ * Skill/command/agent bodies and hook/LSP JSON are third-party content; a
265
+ * renderer throw must degrade to a plain-text fallback instead of unmounting
266
+ * the whole settings section (React has no built-in boundary).
267
+ */
268
+ var ErrorBoundary = class extends react.Component {
269
+ state = { error: void 0 };
270
+ static getDerivedStateFromError(error) {
271
+ return { error };
272
+ }
273
+ componentDidCatch(error, info) {
274
+ console.warn("[dsh-agent-plugins-market] preview render failed:", error, info);
275
+ }
276
+ render() {
277
+ if (this.state.error !== void 0) return this.props.fallback === void 0 ? (0, react.createElement)("pre", { className: "dsh-agent-plugins-fallback" }, `预览渲染失败:${this.state.error.message}`) : this.props.fallback(this.state.error);
278
+ return this.props.children;
279
+ }
280
+ };
281
+ //#endregion
282
+ //#region src/client/market.module.css
283
+ var market_module_default = {
284
+ "body": "qMtKNa_body",
285
+ "card": "qMtKNa_card",
286
+ "cardActions": "qMtKNa_cardActions",
287
+ "cardDesc": "qMtKNa_cardDesc",
288
+ "cardName": "qMtKNa_cardName",
289
+ "cardTitle": "qMtKNa_cardTitle",
290
+ "cardTop": "qMtKNa_cardTop",
291
+ "desc": "qMtKNa_desc",
292
+ "detailBody": "qMtKNa_detailBody",
293
+ "detailCell": "qMtKNa_detailCell",
294
+ "detailChevron": "qMtKNa_detailChevron",
295
+ "detailDesc": "qMtKNa_detailDesc",
296
+ "detailDialog": "qMtKNa_detailDialog",
297
+ "detailGrid": "qMtKNa_detailGrid",
298
+ "detailHead": "qMtKNa_detailHead",
299
+ "detailItem": "qMtKNa_detailItem",
300
+ "detailItemDesc": "qMtKNa_detailItemDesc",
301
+ "detailItemName": "qMtKNa_detailItemName",
302
+ "detailItemOpen": "qMtKNa_detailItemOpen",
303
+ "detailItemRow": "qMtKNa_detailItemRow",
304
+ "detailKey": "qMtKNa_detailKey",
305
+ "detailSection": "qMtKNa_detailSection",
306
+ "detailSections": "qMtKNa_detailSections",
307
+ "detailValue": "qMtKNa_detailValue",
308
+ "editorDialog": "qMtKNa_editorDialog",
309
+ "editorForm": "qMtKNa_editorForm",
310
+ "empty": "qMtKNa_empty",
311
+ "fieldGroup": "qMtKNa_fieldGroup",
312
+ "fieldHint": "qMtKNa_fieldHint",
313
+ "fieldLabel": "qMtKNa_fieldLabel",
314
+ "grid": "qMtKNa_grid",
315
+ "header": "qMtKNa_header",
316
+ "list": "qMtKNa_list",
317
+ "market": "qMtKNa_market",
318
+ "meta": "qMtKNa_meta",
319
+ "modalFooter": "qMtKNa_modalFooter",
320
+ "modalFooterLeft": "qMtKNa_modalFooterLeft",
321
+ "modeRow": "qMtKNa_modeRow",
322
+ "mono": "qMtKNa_mono",
323
+ "okState": "qMtKNa_okState",
324
+ "searchGroup": "qMtKNa_searchGroup",
325
+ "searchInput": "qMtKNa_searchInput",
326
+ "searchWrap": "qMtKNa_searchWrap",
327
+ "seg": "qMtKNa_seg",
328
+ "segOn": "qMtKNa_segOn",
329
+ "skillContent": "qMtKNa_skillContent",
330
+ "sourceTabsRow": "qMtKNa_sourceTabsRow",
331
+ "sourceTabsScroll": "qMtKNa_sourceTabsScroll",
332
+ "spacer": "qMtKNa_spacer",
333
+ "src": "qMtKNa_src",
334
+ "srcTab": "qMtKNa_srcTab",
335
+ "srcTabDel": "qMtKNa_srcTabDel",
336
+ "srcTabEdit": "qMtKNa_srcTabEdit",
337
+ "srcTabMain": "qMtKNa_srcTabMain",
338
+ "srcTabOn": "qMtKNa_srcTabOn",
339
+ "staticId": "qMtKNa_staticId",
340
+ "staticIdValue": "qMtKNa_staticIdValue",
341
+ "sub": "qMtKNa_sub",
342
+ "switchOff": "qMtKNa_switchOff",
343
+ "switchOn": "qMtKNa_switchOn",
344
+ "switchThumb": "qMtKNa_switchThumb",
345
+ "tab": "qMtKNa_tab",
346
+ "tabGap": "qMtKNa_tabGap",
347
+ "tabOn": "qMtKNa_tabOn",
348
+ "tabRow": "qMtKNa_tabRow",
349
+ "tag": "qMtKNa_tag",
350
+ "title": "qMtKNa_title",
351
+ "titleRow": "qMtKNa_titleRow",
352
+ "version": "qMtKNa_version",
353
+ "viewSwitch": "qMtKNa_viewSwitch",
354
+ "warnLine": "qMtKNa_warnLine"
355
+ };
356
+ //#endregion
357
+ //#region src/client/SuiteDetail.tsx
358
+ /**
359
+ * Suite detail modal: click one suite card to browse its internals.
360
+ *
361
+ * Sections: manifest overview, the skill list (each skill expands to its
362
+ * SKILL.md body through the safe MarkdownText renderer), the validated
363
+ * mcp.json servers (each expands to its full config), command/subagent file
364
+ * lists, hook/LSP counts, and validation diagnostics.
365
+ */
366
+ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
367
+ const [detail, setDetail] = (0, react.useState)(void 0);
368
+ const [error, setError] = (0, react.useState)(void 0);
369
+ const [openSkill, setOpenSkill] = (0, react.useState)(void 0);
370
+ const [skillText, setSkillText] = (0, react.useState)(void 0);
371
+ const [skillLoading, setSkillLoading] = (0, react.useState)(false);
372
+ const [openMcp, setOpenMcp] = (0, react.useState)(void 0);
373
+ const [openPreview, setOpenPreview] = (0, react.useState)(void 0);
374
+ (0, react.useEffect)(() => {
375
+ let cancelled = false;
376
+ setDetail(void 0);
377
+ setError(void 0);
378
+ fetchSuiteDetail(sourceId, suiteId).then((value) => {
379
+ if (!cancelled) setDetail(value);
380
+ }).catch((reason) => {
381
+ if (!cancelled) setError(reason instanceof Error ? reason.message : String(reason));
382
+ });
383
+ return () => {
384
+ cancelled = true;
385
+ };
386
+ }, [sourceId, suiteId]);
387
+ const toggleSkill = async (name) => {
388
+ if (openSkill === name) {
389
+ setOpenSkill(void 0);
390
+ return;
391
+ }
392
+ setOpenSkill(name);
393
+ setSkillLoading(true);
394
+ setSkillText(void 0);
395
+ try {
396
+ const content = await fetchSkillContent(sourceId, suiteId, name);
397
+ setSkillText(content.content);
398
+ } catch (reason) {
399
+ setSkillText(`⚠ ${reason instanceof Error ? reason.message : String(reason)}`);
400
+ } finally {
401
+ setSkillLoading(false);
402
+ }
403
+ };
404
+ const toggleMcp = (key) => {
405
+ setOpenMcp(openMcp === key ? void 0 : key);
406
+ };
407
+ const layoutLabel = detail === void 0 ? "" : detail.layout === "agent-plugin-v1" ? t("layoutV1") : detail.layout === "claude-code" ? t("layoutCC") : detail.layout === "codex" ? t("layoutCodex") : detail.layout === "remote" ? t("layoutRemote") : t("layoutSkills");
408
+ return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
409
+ open: true,
410
+ onClose,
411
+ title: detail === void 0 ? t("detailTitle") : `${detail.name}${detail.version === null ? "" : ` v${detail.version}`}`,
412
+ description: detail === void 0 ? void 0 : t("detailHint"),
413
+ closeLabel: t("cancel"),
414
+ className: market_module_default.detailDialog,
415
+ contentClassName: market_module_default.detailBody,
416
+ footer: (0, react.createElement)("div", { className: market_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
417
+ variant: "ghost",
418
+ onClick: onClose
419
+ }, t("cancel"))),
420
+ children: (0, react.createElement)(ErrorBoundary, {
421
+ fallback: (boundaryError) => (0, react.createElement)("div", { className: market_module_default.warnLine }, `${t("actionFail")}: ${boundaryError.message}`),
422
+ children: error !== void 0 ? (0, react.createElement)("div", { className: market_module_default.warnLine }, error) : detail === void 0 ? (0, react.createElement)("div", { className: market_module_default.empty }, t("loading")) : (0, react.createElement)("div", { className: market_module_default.detailSections }, (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, t("overviewSection")), (0, react.createElement)("div", { className: market_module_default.detailGrid }, (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("sourceLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.sourceId)), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("dimensionLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.dimension === "user" ? t("dimensionUser") : t("dimensionProject"))), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("layoutLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, layoutLabel)), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("statusLabel")), (0, react.createElement)("span", { className: detail.enabled ? market_module_default.okState : market_module_default.detailValue }, detail.installed ? detail.enabled ? t("installedBadge") : t("disabledLabel") : t("notInstalledLabel"))), detail.author === null ? null : (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("authorLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.author)), detail.keywords.length === 0 ? null : (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("keywordsLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.keywords.join(", ")))), detail.description === null ? null : (0, react.createElement)("p", { className: market_module_default.detailDesc }, detail.description), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("rootLabel")), (0, react.createElement)("span", { className: market_module_default.mono }, detail.root))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("skillsSection")} (${detail.skills.length})`), detail.skills.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.skills.map((skill) => (0, react.createElement)("div", {
423
+ key: skill.name,
424
+ className: market_module_default.detailItem
425
+ }, (0, react.createElement)("button", {
426
+ type: "button",
427
+ className: openSkill === skill.name ? market_module_default.detailItemOpen : market_module_default.detailItemRow,
428
+ onClick: () => {
429
+ toggleSkill(skill.name);
430
+ }
431
+ }, (0, react.createElement)("span", { className: market_module_default.detailItemName }, skill.name), (0, react.createElement)("span", { className: market_module_default.detailItemDesc }, skill.description), (0, react.createElement)("span", { className: market_module_default.detailChevron }, openSkill === skill.name ? "▾" : "▸")), openSkill !== skill.name ? null : (0, react.createElement)("div", { className: market_module_default.skillContent }, skillLoading ? t("loading") : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: skillText ?? "" }))))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("mcpSection")} (${detail.mcpServers.length})`), detail.mcpServers.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.mcpServers.map((server) => (0, react.createElement)("div", {
432
+ key: server.key,
433
+ className: market_module_default.detailItem
434
+ }, (0, react.createElement)("button", {
435
+ type: "button",
436
+ className: openMcp === server.key ? market_module_default.detailItemOpen : market_module_default.detailItemRow,
437
+ onClick: () => toggleMcp(server.key)
438
+ }, (0, react.createElement)("span", { className: market_module_default.detailItemName }, server.key), (0, react.createElement)("span", { className: market_module_default.detailItemDesc }, mcpSummary(server)), (0, react.createElement)("span", { className: market_module_default.detailChevron }, openMcp === server.key ? "▾" : "▸")), openMcp !== server.key ? null : (0, react.createElement)("pre", { className: market_module_default.mono }, JSON.stringify(server, null, 2))))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("commandsSection")} (${detail.commands.length})`), detail.commands.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.commands.map((command) => (0, react.createElement)(PreviewRow, {
439
+ key: `c:${command.name}`,
440
+ t,
441
+ name: `/${command.name}`,
442
+ description: command.description,
443
+ open: openPreview === `c:${command.name}`,
444
+ onToggle: () => setOpenPreview(openPreview === `c:${command.name}` ? void 0 : `c:${command.name}`),
445
+ children: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: command.content })
446
+ }))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("agentsSection")} (${detail.agents.length})`), detail.agents.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.agents.map((agent) => (0, react.createElement)(PreviewRow, {
447
+ key: `a:${agent.name}`,
448
+ t,
449
+ name: agent.name,
450
+ description: agent.description,
451
+ open: openPreview === `a:${agent.name}`,
452
+ onToggle: () => setOpenPreview(openPreview === `a:${agent.name}` ? void 0 : `a:${agent.name}`),
453
+ children: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: agent.content })
454
+ }))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("hooksLabel")} (${detail.hooks.count})`), detail.hooks.count === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.hooks.entries.map((hook, index) => (0, react.createElement)(PreviewRow, {
455
+ key: `h:${index}`,
456
+ t,
457
+ name: hook.event,
458
+ description: hook.command,
459
+ open: openPreview === `h:${index}`,
460
+ onToggle: () => setOpenPreview(openPreview === `h:${index}` ? void 0 : `h:${index}`),
461
+ children: (0, react.createElement)("pre", { className: market_module_default.mono }, JSON.stringify(hook, null, 2))
462
+ }))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("lspSection")} (${detail.lsp.length})`), detail.lsp.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.lsp.map((entry) => (0, react.createElement)(PreviewRow, {
463
+ key: `l:${entry.name}`,
464
+ t,
465
+ name: entry.name,
466
+ open: openPreview === `l:${entry.name}`,
467
+ onToggle: () => setOpenPreview(openPreview === `l:${entry.name}` ? void 0 : `l:${entry.name}`),
468
+ children: (0, react.createElement)("pre", { className: market_module_default.mono }, entry.content)
469
+ }))), detail.errors.length === 0 ? null : (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("errors")} (${detail.errors.length})`), detail.errors.map((entry, index) => (0, react.createElement)("div", {
470
+ key: index,
471
+ className: market_module_default.warnLine
472
+ }, entry))))
473
+ })
474
+ });
475
+ }
476
+ function mcpSummary(server) {
477
+ if (server.type === "stdio") return server.command ?? server.type;
478
+ return server.url ?? server.type;
479
+ }
480
+ function PreviewRow(props) {
481
+ const { t: _t, name, description, open, onToggle, children } = props;
482
+ return (0, react.createElement)("div", { className: market_module_default.detailItem }, (0, react.createElement)("button", {
483
+ type: "button",
484
+ className: open ? market_module_default.detailItemOpen : market_module_default.detailItemRow,
485
+ onClick: onToggle
486
+ }, (0, react.createElement)("span", { className: market_module_default.detailItemName }, name), description === void 0 ? null : (0, react.createElement)("span", { className: market_module_default.detailItemDesc }, description), (0, react.createElement)("span", { className: market_module_default.detailChevron }, open ? "▾" : "▸")), open ? (0, react.createElement)("div", { className: market_module_default.skillContent }, children) : null);
487
+ }
488
+ //#endregion
489
+ //#region src/client/MarketSection.tsx
490
+ /**
491
+ * The Agent Plugins Market settings section.
492
+ *
493
+ * Layout: repository sources run along the TOP as chips (全部 first), with
494
+ * edit-current / add / refresh-all controls on the right; below sit search,
495
+ * status tabs, and the card grid. Colors ride the dsh --dsw-alias-* tokens
496
+ * with light-mode fallbacks so the page follows the active theme.
497
+ */
498
+ const EMPTY_OVERVIEW = {
499
+ sources: [],
500
+ suites: [],
501
+ totals: {
502
+ all: 0,
503
+ installed: 0,
504
+ enabled: 0
505
+ },
506
+ roots: {
507
+ user: "",
508
+ data: ""
509
+ }
510
+ };
511
+ function MarketSection({ t }) {
512
+ const [overview, setOverview] = (0, react.useState)(EMPTY_OVERVIEW);
513
+ const [loading, setLoading] = (0, react.useState)(true);
514
+ const [search, setSearch] = (0, react.useState)("");
515
+ const [tab, setTab] = (0, react.useState)("all");
516
+ const [category, setCategory] = (0, react.useState)("all");
517
+ const [view, setView] = (0, react.useState)("grid");
518
+ const [busy, setBusy] = (0, react.useState)(void 0);
519
+ const [toast, setToast] = (0, react.useState)(void 0);
520
+ const [confirm, setConfirm] = (0, react.useState)(void 0);
521
+ const [editor, setEditor] = (0, react.useState)(void 0);
522
+ const [detail, setDetail] = (0, react.useState)(void 0);
523
+ const refresh = (0, react.useCallback)(async () => {
524
+ try {
525
+ setOverview(await fetchOverview());
526
+ } catch {
527
+ setToast({
528
+ key: Date.now(),
529
+ message: t("loadFail")
530
+ });
531
+ } finally {
532
+ setLoading(false);
533
+ }
534
+ }, [t]);
535
+ (0, react.useEffect)(() => {
536
+ refresh();
537
+ }, [refresh]);
538
+ const action = (0, react.useCallback)(async (key, path, body) => {
539
+ setBusy(key);
540
+ try {
541
+ await postAction(path, body);
542
+ await refresh();
543
+ return true;
544
+ } catch (error) {
545
+ setToast({
546
+ key: Date.now(),
547
+ message: `${t("actionFail")}: ${error instanceof Error ? error.message : String(error)}`
548
+ });
549
+ return false;
550
+ } finally {
551
+ setBusy(void 0);
552
+ }
553
+ }, [refresh, t]);
554
+ const scopeTotals = (0, react.useMemo)(() => {
555
+ if (category === "all") return overview.totals;
556
+ const scoped = overview.suites.filter((suite) => suite.sourceId === category);
557
+ return {
558
+ all: scoped.length,
559
+ installed: scoped.filter((suite) => suite.installed).length,
560
+ enabled: scoped.filter((suite) => suite.enabled).length
561
+ };
562
+ }, [overview, category]);
563
+ const filtered = (0, react.useMemo)(() => {
564
+ const needle = search.trim().toLowerCase();
565
+ return overview.suites.filter((suite) => {
566
+ if (category !== "all" && suite.sourceId !== category) return false;
567
+ if (tab === "installed" && !suite.installed) return false;
568
+ if (tab === "uninstalled" && suite.installed) return false;
569
+ if (needle === "") return true;
570
+ return `${suite.name} ${suite.description ?? ""} ${suite.keywords.join(" ")}`.toLowerCase().includes(needle);
571
+ });
572
+ }, [
573
+ overview,
574
+ search,
575
+ tab,
576
+ category
577
+ ]);
578
+ const openUninstall = (0, react.useCallback)((suite) => {
579
+ setConfirm({
580
+ kind: "uninstall",
581
+ sourceId: suite.sourceId,
582
+ suiteId: suite.suiteId
583
+ });
584
+ }, []);
585
+ const confirmAction = (0, react.useCallback)(async () => {
586
+ if (confirm === void 0) return;
587
+ if (confirm.kind === "uninstall" && confirm.suiteId !== void 0) await action(`u:${confirm.suiteId}`, "uninstall", {
588
+ sourceId: confirm.sourceId,
589
+ suiteId: confirm.suiteId
590
+ });
591
+ else if (confirm.kind === "removeSource") {
592
+ await action(`s:${confirm.sourceId}`, "sources/remove", { id: confirm.sourceId });
593
+ if (category === confirm.sourceId) setCategory("all");
594
+ }
595
+ setConfirm(void 0);
596
+ }, [
597
+ confirm,
598
+ action,
599
+ category
600
+ ]);
601
+ const selectedSource = category === "all" ? void 0 : overview.sources.find((source) => source.id === category);
602
+ return (0, react.createElement)(ErrorBoundary, {
603
+ fallback: (error) => (0, react.createElement)("div", { className: market_module_default.empty }, `${t("actionFail")}: ${error.message}`),
604
+ children: (0, react.createElement)("div", { className: market_module_default.market }, (0, react.createElement)("header", { className: market_module_default.header }, (0, react.createElement)("div", { className: market_module_default.titleRow }, (0, react.createElement)("h2", { className: market_module_default.title }, t("nav")), (0, react.createElement)("p", { className: market_module_default.sub }, t("subtitle")), (0, react.createElement)("div", { className: market_module_default.spacer }), (0, react.createElement)("div", { className: market_module_default.searchGroup }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
605
+ variant: "ghost",
606
+ size: "sm",
607
+ title: t("addSource"),
608
+ onClick: () => setEditor({ mode: "add" })
609
+ }, "+"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
610
+ variant: "ghost",
611
+ size: "sm",
612
+ title: t("refreshAll"),
613
+ onClick: () => {
614
+ action("s:refresh:all", "sources/refresh", {});
615
+ }
616
+ }, "↻"), (0, react.createElement)("div", { className: market_module_default.searchWrap }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
617
+ className: market_module_default.searchInput,
618
+ placeholder: t("searchPh"),
619
+ value: search,
620
+ onChange: (event) => setSearch(event.target.value)
621
+ })))), (0, react.createElement)("div", { className: market_module_default.sourceTabsRow }, (0, react.createElement)("div", { className: market_module_default.sourceTabsScroll }, (0, react.createElement)(SourceTab, {
622
+ key: "__all__",
623
+ t,
624
+ active: category === "all",
625
+ label: `${t("tabAll")} ${overview.totals.all}`,
626
+ onSelect: () => setCategory("all")
627
+ }), ...[...overview.sources].sort((a, b) => a.id.localeCompare(b.id)).map((source) => (0, react.createElement)(SourceTab, {
628
+ key: source.id,
629
+ t,
630
+ active: category === source.id,
631
+ label: `${source.id}${source.local === true ? ` · ${t("sourceLocal")}` : ""} ${source.suiteIds.length}${source.cloned === false ? " ⚠" : ""}`,
632
+ onSelect: () => setCategory(source.id),
633
+ onDelete: () => setConfirm({
634
+ kind: "removeSource",
635
+ sourceId: source.id
636
+ }),
637
+ onEdit: selectedSource?.id === source.id ? () => setEditor({
638
+ mode: "edit",
639
+ source
640
+ }) : void 0
641
+ })))), (0, react.createElement)("div", { className: market_module_default.tabRow }, (0, react.createElement)(TabButton, {
642
+ t,
643
+ active: tab === "all",
644
+ label: `${t("tabAll")} ${scopeTotals.all}`,
645
+ onClick: () => setTab("all")
646
+ }), (0, react.createElement)(TabButton, {
647
+ t,
648
+ active: tab === "installed",
649
+ label: `${t("tabInstalled")} ${scopeTotals.installed}`,
650
+ onClick: () => setTab("installed")
651
+ }), (0, react.createElement)(TabButton, {
652
+ t,
653
+ active: tab === "uninstalled",
654
+ label: `${t("tabUninstalled")} ${scopeTotals.all - scopeTotals.installed}`,
655
+ onClick: () => setTab("uninstalled")
656
+ }), (0, react.createElement)("div", { className: market_module_default.tabGap }), (0, react.createElement)("button", {
657
+ type: "button",
658
+ className: market_module_default.viewSwitch,
659
+ onClick: () => setView(view === "grid" ? "list" : "grid")
660
+ }, view === "grid" ? t("list") : t("grid")))), (0, react.createElement)("main", { className: view === "grid" ? market_module_default.grid : market_module_default.list }, loading ? (0, react.createElement)("div", { className: market_module_default.empty }, "…") : filtered.length === 0 ? (0, react.createElement)("div", { className: market_module_default.empty }, tab === "installed" ? t("installedEmpty") : t("empty")) : filtered.map((suite) => (0, react.createElement)(SuiteCard, {
661
+ key: `${suite.sourceId}/${suite.suiteId}`,
662
+ t,
663
+ suite,
664
+ busy: busy !== void 0,
665
+ onOpen: () => setDetail({
666
+ sourceId: suite.sourceId,
667
+ suiteId: suite.suiteId
668
+ }),
669
+ onInstall: () => {
670
+ action(`i:${suite.suiteId}`, "install", {
671
+ sourceId: suite.sourceId,
672
+ suiteId: suite.suiteId
673
+ });
674
+ },
675
+ onToggle: () => {
676
+ action(`e:${suite.suiteId}`, "set-enabled", {
677
+ sourceId: suite.sourceId,
678
+ suiteId: suite.suiteId,
679
+ enabled: !suite.enabled
680
+ });
681
+ },
682
+ onRefresh: () => {
683
+ action(`r:${suite.suiteId}`, "sources/refresh", { id: suite.sourceId });
684
+ },
685
+ onUninstall: () => openUninstall(suite)
686
+ }))), toast === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
687
+ key: toast.key,
688
+ text: toast.message,
689
+ onDone: () => setToast(void 0)
690
+ }), confirm === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
691
+ open: true,
692
+ onClose: () => setConfirm(void 0),
693
+ title: confirm.kind === "uninstall" ? t("uninstallConfirmTitle") : `${t("removeSourceConfirmTitle")}「${confirm.sourceId}」`,
694
+ closeLabel: t("cancel"),
695
+ description: confirm.kind === "uninstall" ? t("uninstallConfirmDesc") : t("removeSourceConfirmDesc"),
696
+ footer: (0, react.createElement)("div", { className: market_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
697
+ variant: "ghost",
698
+ onClick: () => setConfirm(void 0)
699
+ }, t("cancel")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
700
+ variant: "primary",
701
+ onClick: () => {
702
+ confirmAction();
703
+ }
704
+ }, t("confirmDelete")))
705
+ }), detail === void 0 ? null : (0, react.createElement)(SuiteDetailModal, {
706
+ t,
707
+ sourceId: detail.sourceId,
708
+ suiteId: detail.suiteId,
709
+ onClose: () => setDetail(void 0)
710
+ }), editor === void 0 ? null : (0, react.createElement)(SourceEditorModal, {
711
+ t,
712
+ editor,
713
+ busy: busy !== void 0,
714
+ onClose: () => setEditor(void 0),
715
+ onSave: async (url, branch, local) => {
716
+ const key = editor.mode === "edit" ? `s:edit:${editor.source.id}` : `s:add:${url}`;
717
+ const body = {
718
+ url,
719
+ ...branch === "" ? {} : { branch },
720
+ local
721
+ };
722
+ if (editor.mode === "add") {
723
+ setBusy(key);
724
+ try {
725
+ const derived = (await postAction("sources/add", body))["source"]?.id;
726
+ await refresh();
727
+ setEditor(void 0);
728
+ if (derived !== void 0) setCategory(derived);
729
+ return true;
730
+ } catch (error) {
731
+ setToast({
732
+ key: Date.now(),
733
+ message: `${t("actionFail")}: ${error instanceof Error ? error.message : String(error)}`
734
+ });
735
+ return false;
736
+ } finally {
737
+ setBusy(void 0);
738
+ }
739
+ }
740
+ const ok = await action(key, "sources/update", {
741
+ id: editor.source.id,
742
+ ...body
743
+ });
744
+ if (ok) setEditor(void 0);
745
+ return ok;
746
+ },
747
+ onRemove: async (id) => {
748
+ setConfirm({
749
+ kind: "removeSource",
750
+ sourceId: id
751
+ });
752
+ setEditor(void 0);
753
+ }
754
+ }))
755
+ });
756
+ }
757
+ function TabButton({ t: _t, active, label, onClick }) {
758
+ return (0, react.createElement)("button", {
759
+ type: "button",
760
+ className: active ? market_module_default.tabOn : market_module_default.tab,
761
+ onClick
762
+ }, label);
763
+ }
764
+ /** A source tab with a trailing delete control (deletion confirms at the section level). */
765
+ function SourceTab(props) {
766
+ const { t, active = false, label, onSelect, onDelete, onEdit } = props;
767
+ return (0, react.createElement)("div", { className: active ? market_module_default.srcTabOn : market_module_default.srcTab }, (0, react.createElement)("button", {
768
+ type: "button",
769
+ className: market_module_default.srcTabMain,
770
+ onClick: onSelect
771
+ }, label), onEdit === void 0 ? null : (0, react.createElement)("button", {
772
+ type: "button",
773
+ className: market_module_default.srcTabEdit,
774
+ title: t("editSource"),
775
+ onClick: (event) => {
776
+ event.stopPropagation();
777
+ onEdit();
778
+ }
779
+ }, "✎"), onDelete === void 0 ? null : (0, react.createElement)("button", {
780
+ type: "button",
781
+ className: market_module_default.srcTabDel,
782
+ title: t("remove"),
783
+ onClick: (event) => {
784
+ event.stopPropagation();
785
+ onDelete();
786
+ }
787
+ }, "×"));
788
+ }
789
+ function SourceEditorModal(props) {
790
+ const { t, editor } = props;
791
+ const [local, setLocal] = (0, react.useState)(editor.mode === "edit" && editor.source.local === true);
792
+ const [url, setUrl] = (0, react.useState)(editor.mode === "edit" ? editor.source.url : "");
793
+ const [branch, setBranch] = (0, react.useState)(editor.mode === "edit" ? editor.source.branch ?? "" : "");
794
+ const id = editor.mode === "edit" ? editor.source.id : "";
795
+ const title = editor.mode === "edit" ? t("editSourceTitle") : t("addSourceTitle");
796
+ return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
797
+ open: true,
798
+ onClose: props.onClose,
799
+ title,
800
+ description: t("editorHint"),
801
+ closeLabel: t("cancel"),
802
+ className: market_module_default.editorDialog,
803
+ footer: (0, react.createElement)("div", { className: market_module_default.modalFooter }, (0, react.createElement)("div", { className: market_module_default.modalFooterLeft }, editor.mode === "edit" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
804
+ variant: "ghost",
805
+ onClick: () => props.onRemove(id)
806
+ }, `🗑 ${t("remove")}`) : null), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
807
+ variant: "ghost",
808
+ onClick: props.onClose
809
+ }, t("cancel")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
810
+ variant: "primary",
811
+ disabled: props.busy,
812
+ onClick: () => {
813
+ props.onSave(url.trim(), branch.trim(), local);
814
+ }
815
+ }, t("save"))),
816
+ children: (0, react.createElement)("div", { className: market_module_default.editorForm }, (0, react.createElement)("div", { className: market_module_default.modeRow }, (0, react.createElement)("button", {
817
+ type: "button",
818
+ className: local ? market_module_default.seg : market_module_default.segOn,
819
+ onClick: () => setLocal(false)
820
+ }, t("sourceModeGit")), (0, react.createElement)("button", {
821
+ type: "button",
822
+ className: local ? market_module_default.segOn : market_module_default.seg,
823
+ onClick: () => setLocal(true)
824
+ }, t("sourceModeLocal"))), editor.mode === "edit" ? (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, t("sourceIdPh")), (0, react.createElement)("div", { className: market_module_default.staticId }, (0, react.createElement)("span", { className: market_module_default.staticIdValue }, id), (0, react.createElement)("span", { className: market_module_default.fieldHint }, t("idFixed")))) : null, (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, local ? t("sourceUrlLocalPh") : t("sourceUrlPh")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
825
+ placeholder: local ? t("sourceUrlLocalPh") : t("sourceUrlPh"),
826
+ value: url,
827
+ onChange: (event) => setUrl(event.target.value)
828
+ }), (0, react.createElement)("span", { className: market_module_default.fieldHint }, local ? t("urlLocalHint") : t("urlGitHint"))), local ? null : (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, t("branchPh")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
829
+ placeholder: t("branchPh"),
830
+ value: branch,
831
+ onChange: (event) => setBranch(event.target.value)
832
+ }), (0, react.createElement)("span", { className: market_module_default.fieldHint }, t("branchHint"))))
833
+ });
834
+ }
835
+ /** A green/gray switch control for suite enable state. */
836
+ function ToggleSwitch(props) {
837
+ return (0, react.createElement)("button", {
838
+ type: "button",
839
+ role: "switch",
840
+ "aria-checked": props.on,
841
+ title: props.title,
842
+ disabled: props.disabled,
843
+ className: props.on ? market_module_default.switchOn : market_module_default.switchOff,
844
+ onClick: (event) => {
845
+ event.stopPropagation();
846
+ props.onChange();
847
+ }
848
+ }, (0, react.createElement)("span", { className: market_module_default.switchThumb }));
849
+ }
850
+ function SuiteCard(props) {
851
+ const { t, suite, busy } = props;
852
+ const tags = [
853
+ [t("surfaceSkills"), suite.surfaces.skills],
854
+ [t("surfaceMcp"), suite.surfaces.mcp],
855
+ [t("surfaceHooks"), suite.surfaces.hooks],
856
+ [t("surfaceCommands"), suite.surfaces.commands],
857
+ [t("surfaceAgents"), suite.surfaces.agents],
858
+ [t("surfaceLsp"), suite.surfaces.lsp]
859
+ ].filter(([, count]) => count > 0);
860
+ const layoutLabel = suite.layout === "agent-plugin-v1" ? t("layoutV1") : suite.layout === "claude-code" ? t("layoutCC") : suite.layout === "codex" ? t("layoutCodex") : suite.layout === "universal" ? t("layoutUniversal") : suite.layout === "cursor" ? t("layoutCursor") : suite.layout === "kimi" ? t("layoutKimi") : suite.layout === "remote" ? t("layoutRemote") : t("layoutSkills");
861
+ const isRemote = suite.remoteUrl !== void 0;
862
+ const stop = (callback) => (event) => {
863
+ event.stopPropagation();
864
+ callback();
865
+ };
866
+ return (0, react.createElement)("article", {
867
+ className: market_module_default.card,
868
+ onClick: props.onOpen
869
+ }, (0, react.createElement)("div", { className: market_module_default.cardTop }, (0, react.createElement)("div", { className: market_module_default.cardTitle }, (0, react.createElement)("span", { className: market_module_default.cardName }, suite.name), suite.version === void 0 ? null : (0, react.createElement)("span", { className: market_module_default.version }, `v${suite.version}`)), (0, react.createElement)("div", { className: market_module_default.cardActions }, suite.installed ? (0, react.createElement)(ToggleSwitch, {
870
+ on: suite.enabled,
871
+ disabled: busy,
872
+ title: suite.enabled ? t("disable") : t("enable"),
873
+ onChange: props.onToggle
874
+ }) : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
875
+ variant: "primary",
876
+ size: "sm",
877
+ disabled: busy || isRemote,
878
+ title: isRemote ? suite.remoteUrl : void 0,
879
+ onClick: stop(props.onInstall)
880
+ }, isRemote ? t("remoteRef") : t("install")), suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
881
+ variant: "ghost",
882
+ size: "sm",
883
+ title: t("refresh"),
884
+ disabled: busy,
885
+ onClick: stop(props.onRefresh)
886
+ }, "↻") : null, suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
887
+ variant: "ghost",
888
+ size: "sm",
889
+ title: t("uninstall"),
890
+ disabled: busy,
891
+ onClick: stop(props.onUninstall)
892
+ }, "🗑") : null)), (0, react.createElement)("p", { className: market_module_default.desc }, suite.description ?? ""), (0, react.createElement)("div", { className: market_module_default.meta }, (0, react.createElement)("span", { className: market_module_default.src }, `${suite.sourceId} · ${isRemote ? t("remoteRef") : suite.dimension === "user" ? t("dimensionUser") : t("dimensionProject")}`), (0, react.createElement)("span", { className: market_module_default.tag }, layoutLabel), suite.installed ? (0, react.createElement)("span", { className: suite.enabled ? market_module_default.okState : market_module_default.tag }, suite.enabled ? `✓ ${t("installedBadge")}` : t("installedBadge")) : null, ...tags.map(([label, count]) => (0, react.createElement)("span", {
893
+ key: label,
894
+ className: market_module_default.tag
895
+ }, `${label} ${count}`)), suite.errors.length === 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
896
+ label: suite.errors.slice(0, 8).join(";"),
897
+ children: (0, react.createElement)("span", { className: market_module_default.warnLine }, `⚠ ${t("errors")} ${suite.errors.length}`)
898
+ })));
899
+ }
900
+ //#endregion
901
+ //#region src/client/index.ts
902
+ /**
903
+ * dsh-agent-plugins-market client: registers the Agent Plugins Market section inside the Web
904
+ * GUI's settings dialog (the same settings.section seat dshmarket uses).
905
+ * Mirrors the market's integration contract: the bundle's only externals are
906
+ * react and the injected `dsh.client.inject` module table, so it cannot reach
907
+ * packages the host does not serve.
908
+ */
909
+ const NS = "dsh-agent-plugins-market";
910
+ const name = "dsh-agent-plugins-market";
911
+ const inject = ["slots", "locale"];
912
+ /** Primitives this section renders with; absent exports degrade the whole section. */
913
+ const REQUIRED_PRIMITIVES = [
914
+ "Button",
915
+ "Input",
916
+ "Modal",
917
+ "Toast",
918
+ "Tooltip"
919
+ ];
920
+ /** Detect host primitives that predate the exports this UI relies on. */
921
+ function missingPrimitives(module, required = REQUIRED_PRIMITIVES) {
922
+ return required.filter((name) => module[name] === void 0);
923
+ }
924
+ function apply(ctx) {
925
+ ctx.effect(() => ctx.locale.register(NS, {
926
+ zh,
927
+ en
928
+ }), "dsh-agent-plugins: dictionaries");
929
+ const t = ctx.locale.bind(NS);
930
+ const gaps = missingPrimitives(_deepseek_ai_dsh_client_ui_primitives);
931
+ if (gaps.length > 0) {
932
+ console.warn(`[dsh-agent-plugins-market] host ui-primitives missing ${gaps.join(", ")} — Agent Plugins Market section disabled (dsh web >= 0.1.0-rc.6 required)`);
933
+ return;
934
+ }
935
+ ctx.slots.inject("settings.section", () => ctx.slots.register({
936
+ name: "settings.section",
937
+ id: "agent-plugin",
938
+ order: 45,
939
+ label: () => t("nav"),
940
+ locale: NS,
941
+ inject: () => ({ t })
942
+ }, () => (0, react.createElement)(MarketSection, { t })));
943
+ }
944
+ //#endregion
945
+ exports.REQUIRED_PRIMITIVES = REQUIRED_PRIMITIVES;
946
+ exports.apply = apply;
947
+ exports.inject = inject;
948
+ exports.missingPrimitives = missingPrimitives;
949
+ exports.name = name;
950
+
951
+ //# sourceMappingURL=client.js.map
952
+ return module.exports;
953
+ }
954
+ });