dsh-agent-plugins-market 0.4.5 → 0.5.0
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.
- package/README.md +20 -14
- package/README.zh.md +20 -14
- package/client/client.js +1117 -360
- package/client/client.js.map +1 -1
- package/lib/application/catalog.js +447 -0
- package/lib/application/details.js +136 -0
- package/lib/application/queries.js +1 -0
- package/lib/{discovery → catalog}/manifests.js +20 -12
- package/lib/{paths.js → catalog/paths.js} +5 -1
- package/lib/{skills-parse.js → catalog/skills-parse.js} +7 -4
- package/lib/catalog/source-catalog.js +38 -0
- package/lib/{discovery.js → catalog/suite-scanner.js} +29 -85
- package/lib/{discovery → catalog}/surfaces.js +9 -11
- package/lib/{validate.js → catalog/validate.js} +3 -3
- package/lib/context.js +11 -13
- package/lib/contracts/market.js +27 -0
- package/lib/contracts/mcp-status.js +2 -0
- package/lib/index.js +33 -46
- package/lib/{state.js → model/state.js} +2 -2
- package/lib/routes.js +23 -20
- package/lib/{commands-mounts.js → runtime/commands-mounts.js} +10 -11
- package/lib/{hooks-mounts.js → runtime/hooks-mounts.js} +1 -1
- package/lib/{mcp-config.js → runtime/mcp-config.js} +7 -4
- package/lib/runtime/mcp-status.js +114 -0
- package/lib/runtime/reconciler.js +46 -0
- package/lib/{skills-provider.js → runtime/skills-provider.js} +26 -23
- package/lib/runtime/tool-registry-observer.js +35 -0
- package/lib/types/application/catalog.d.ts +113 -0
- package/lib/types/application/details.d.ts +12 -0
- package/lib/types/application/queries.d.ts +33 -0
- package/lib/types/{discovery → catalog}/manifests.d.ts +1 -1
- package/lib/types/catalog/source-catalog.d.ts +3 -0
- package/lib/types/catalog/suite-scanner.d.ts +9 -0
- package/lib/types/{discovery → catalog}/surfaces.d.ts +1 -1
- package/lib/types/{validate.d.ts → catalog/validate.d.ts} +1 -1
- package/lib/types/context.d.ts +2 -2
- package/lib/types/contracts/market.d.ts +153 -0
- package/lib/types/contracts/mcp-status.d.ts +38 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/{types.d.ts → model/types.d.ts} +2 -42
- package/lib/types/routes.d.ts +2 -2
- package/lib/types/{commands-mounts.d.ts → runtime/commands-mounts.d.ts} +1 -1
- package/lib/types/{hooks-mounts.d.ts → runtime/hooks-mounts.d.ts} +1 -1
- package/lib/types/{mcp-config.d.ts → runtime/mcp-config.d.ts} +1 -1
- package/lib/types/{mcp-mounts.d.ts → runtime/mcp-mounts.d.ts} +1 -1
- package/lib/types/runtime/mcp-status.d.ts +13 -0
- package/lib/types/runtime/reconciler.d.ts +33 -0
- package/lib/types/{skills-provider.d.ts → runtime/skills-provider.d.ts} +3 -3
- package/lib/types/runtime/tool-registry-observer.d.ts +14 -0
- package/package.json +34 -19
- package/schemas/README.md +2 -5
- package/lib/manager.js +0 -570
- package/lib/types/discovery.d.ts +0 -16
- package/lib/types/manager.d.ts +0 -118
- /package/lib/{git.js → catalog/git.js} +0 -0
- /package/lib/{types.js → model/types.js} +0 -0
- /package/lib/{mcp-mounts.js → runtime/mcp-mounts.js} +0 -0
- /package/lib/types/{git.d.ts → catalog/git.d.ts} +0 -0
- /package/lib/types/{paths.d.ts → catalog/paths.d.ts} +0 -0
- /package/lib/types/{skills-parse.d.ts → catalog/skills-parse.d.ts} +0 -0
- /package/lib/types/{state.d.ts → model/state.d.ts} +0 -0
package/client/client.js
CHANGED
|
@@ -2,7 +2,7 @@ window.__ModuleLoader__.load({ id: "dsh-agent-plugins-market", factory: (require
|
|
|
2
2
|
|
|
3
3
|
var module = { exports: {} };
|
|
4
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\n.qMtKNa_progress, .qMtKNa_progressError {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-2, #7f7f7f0f);\n color: var(--dsw-alias-label-primary, #1f2328);\n border-radius: 8px;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n}\n\n.qMtKNa_progressError {\n border-color: var(--dsw-alias-danger, #e5484d);\n color: var(--dsw-alias-danger, #e5484d);\n}\n\n.qMtKNa_progressSpin {\n border: 2px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-top-color: var(--dsw-alias-brand-primary, #4f6ef7);\n border-radius: 50%;\n flex-shrink: 0;\n width: 14px;\n height: 14px;\n animation: .8s linear infinite qMtKNa_dshApmSpin;\n}\n\n@keyframes qMtKNa_dshApmSpin {\n to {\n transform: rotate(360deg);\n }\n}\n\n.qMtKNa_progressFail {\n flex-shrink: 0;\n font-size: 13px;\n}\n\n.qMtKNa_progressText {\n overflow-wrap: anywhere;\n min-width: 0;\n}\n";document.head.appendChild(s);}})();
|
|
5
|
+
(function(){if(typeof document!=="undefined"){var s=document.createElement("style");s.setAttribute("data-dsh-client","dsh-agent-plugins-market");s.textContent="._72qoAq_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: 24px;\n display: flex;\n}\n\n._72qoAq_pageMode {\n width: 100%;\n min-width: 0;\n}\n\n._72qoAq_marketControls {\n flex-direction: column;\n gap: 8px;\n min-height: 0;\n display: flex;\n}\n\n._72qoAq_mcpSurface {\n flex: 1;\n min-height: 0;\n display: flex;\n}\n\n._72qoAq_surfaceSwitch {\n border: 1px solid var(--dsw-alias-border-l2, #d4dce8);\n background: var(--dsw-alias-bg-layer-1, #fff);\n height: 26px;\n color: var(--dsw-alias-brand-primary, #4966f5);\n cursor: pointer;\n border-radius: 7px;\n flex: none;\n align-self: center;\n padding: 0 10px;\n font-size: 11px;\n}\n\n._72qoAq_surfaceSwitch:hover {\n background: var(--dsw-alias-bg-selected, #edf1ff);\n}\n\nhtml[data-dsh-agent-plugins-market-page] [data-pane=\"conversation\"], html[data-dsh-agent-plugins-market-page] [class*=\"centerCol\"] {\n position: relative;\n}\n\n._72qoAq_pageView {\n z-index: 60;\n background: var(--dsw-alias-bg-base, #f7f8fa);\n min-width: 0;\n min-height: 0;\n padding: 20px 24px;\n display: none;\n position: absolute;\n inset: 0;\n overflow: hidden;\n}\n\nhtml[data-dsh-agent-plugins-market-page] ._72qoAq_pageView {\n display: flex;\n}\n\nhtml[data-dsh-agent-plugins-market-page] [data-pane=\"conversation\"] > :not([data-dsh-agent-plugins-market-page-view]), html[data-dsh-agent-plugins-market-page] [class*=\"centerCol\"] > :not([data-dsh-agent-plugins-market-page-view]) {\n display: none !important;\n}\n\n._72qoAq_pageEntry {\n width: 100%;\n min-height: 32px;\n color: var(--dsw-alias-label-primary, #1f2328);\n cursor: pointer;\n font: inherit;\n text-align: left;\n background: none;\n border: none;\n border-radius: 8px;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n}\n\n._72qoAq_pageEntry:hover {\n background: var(--dsw-alias-bg-hover, #0000000d);\n}\n\n._72qoAq_pageEntry:active {\n background: var(--dsw-alias-bg-active, #00000014);\n}\n\n._72qoAq_pageEntry svg {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex-shrink: 0;\n}\n\n._72qoAq_pageEntry span {\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n overflow: hidden;\n}\n\n[data-dsh-frame][data-sidebar-collapsed] ._72qoAq_pageEntry {\n justify-content: center;\n padding-inline: 0;\n}\n\n[data-dsh-frame][data-sidebar-collapsed] ._72qoAq_pageEntry span {\n display: none;\n}\n\n._72qoAq_pageEntry:focus-visible, ._72qoAq_srcTabMain:focus-visible, ._72qoAq_srcTabEdit:focus-visible, ._72qoAq_srcTabDel:focus-visible, ._72qoAq_seg:focus-visible, ._72qoAq_segOn:focus-visible, ._72qoAq_detailItemRow:focus-visible, ._72qoAq_detailItemOpen:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\n}\n\n._72qoAq_header {\n flex-direction: column;\n flex-shrink: 0;\n gap: 8px;\n display: flex;\n}\n\n._72qoAq_titleRow {\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n._72qoAq_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n._72qoAq_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._72qoAq_spacer {\n flex: 1;\n}\n\n._72qoAq_searchGroup {\n align-items: center;\n gap: 2px;\n display: flex;\n}\n\n._72qoAq_body {\n flex: 1;\n align-items: flex-start;\n gap: 20px;\n min-height: 0;\n display: flex;\n}\n\n._72qoAq_sourceTabsRow {\n padding: 0;\n display: block;\n}\n\n._72qoAq_sourceTabsScroll {\n grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));\n gap: 4px;\n display: grid;\n}\n\n._72qoAq_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._72qoAq_srcTabEdit:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n._72qoAq_srcTabOn ._72qoAq_srcTabEdit, ._72qoAq_srcTabOn ._72qoAq_srcTabEdit:hover {\n color: var(--dsw-alias-label-primary-foreground, #fff);\n}\n\n._72qoAq_srcTab, ._72qoAq_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._72qoAq_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._72qoAq_srcTabMain:hover {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n\n._72qoAq_srcTabOn {\n background: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n border-color: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n}\n\n._72qoAq_srcTabOn ._72qoAq_srcTabMain {\n color: var(--dsw-alias-label-primary-foreground, #fff);\n font-weight: 600;\n}\n\n._72qoAq_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._72qoAq_srcTabDel:hover {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n._72qoAq_srcTabOn ._72qoAq_srcTabDel, ._72qoAq_srcTabOn ._72qoAq_srcTabDel:hover {\n color: var(--dsw-alias-label-primary-foreground, #fff);\n}\n\n._72qoAq_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._72qoAq_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._72qoAq_list ._72qoAq_card {\n flex-flow: wrap;\n align-items: center;\n gap: 8px 14px;\n}\n\n._72qoAq_list ._72qoAq_cardTop {\n flex: none;\n}\n\n._72qoAq_list ._72qoAq_cardDesc {\n -webkit-line-clamp: 1;\n flex: 1;\n min-width: 200px;\n min-height: 0;\n}\n\n._72qoAq_list ._72qoAq_cardActions {\n flex: none;\n}\n\n._72qoAq_list ._72qoAq_meta {\n flex-basis: 100%;\n}\n\n._72qoAq_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._72qoAq_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._72qoAq_cardTop {\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n._72qoAq_cardTitle {\n flex: 1;\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_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._72qoAq_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._72qoAq_cardActions {\n flex-shrink: 0;\n align-items: center;\n gap: 4px;\n display: flex;\n}\n\n._72qoAq_switchOn, ._72qoAq_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._72qoAq_switchOn {\n background: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n._72qoAq_switchOff {\n background: var(--dsw-alias-state-neutral, #d1d5db);\n}\n\n._72qoAq_switchOn:disabled, ._72qoAq_switchOff:disabled {\n opacity: .6;\n cursor: default;\n}\n\n._72qoAq_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._72qoAq_switchOn ._72qoAq_switchThumb {\n left: 19px;\n}\n\n._72qoAq_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._72qoAq_meta {\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n._72qoAq_src {\n color: var(--dsw-alias-label-secondary, #9ca3af);\n font-size: 12px;\n text-decoration: none;\n}\n\n._72qoAq_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._72qoAq_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._72qoAq_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._72qoAq_modalFooter {\n justify-content: flex-end;\n gap: 8px;\n width: 100%;\n display: flex;\n}\n\n._72qoAq_modalFooterLeft {\n gap: 8px;\n margin-right: auto;\n display: flex;\n}\n\n._72qoAq_editorDialog {\n width: min(500px, 92vw);\n}\n\n._72qoAq_editorForm {\n flex-direction: column;\n gap: 14px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_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._72qoAq_seg, ._72qoAq_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._72qoAq_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._72qoAq_fieldGroup {\n flex-direction: column;\n gap: 5px;\n display: flex;\n}\n\n._72qoAq_fieldLabel {\n color: var(--dsw-alias-label-secondary, #6b7280);\n font-size: 12px;\n font-weight: 600;\n}\n\n._72qoAq_fieldHint {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 12px;\n line-height: 16px;\n}\n\n._72qoAq_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._72qoAq_staticIdValue {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-size: 13px;\n font-weight: 600;\n}\n\n._72qoAq_detailDialog {\n width: min(800px, 94vw);\n}\n\n._72qoAq_detailBody {\n flex-direction: column;\n gap: 14px;\n max-height: 78vh;\n display: flex;\n overflow-y: auto;\n}\n\n._72qoAq_detailSections {\n flex-direction: column;\n gap: 14px;\n display: flex;\n}\n\n._72qoAq_detailSection {\n flex-direction: column;\n gap: 6px;\n display: flex;\n}\n\n._72qoAq_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._72qoAq_detailGrid {\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: 6px 14px;\n display: grid;\n}\n\n._72qoAq_detailCell {\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_detailKey {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 12px;\n}\n\n._72qoAq_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._72qoAq_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._72qoAq_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._72qoAq_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._72qoAq_detailItemRow, ._72qoAq_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._72qoAq_detailItemRow:hover {\n background: var(--dsw-alias-bg-hover, #0000000d);\n}\n\n._72qoAq_detailItemOpen {\n background: var(--dsw-alias-bg-selected, #4f6ef714);\n}\n\n._72qoAq_detailItemName {\n flex-shrink: 0;\n font-size: 13px;\n font-weight: 600;\n}\n\n._72qoAq_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._72qoAq_detailChevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n flex-shrink: 0;\n}\n\n._72qoAq_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\n._72qoAq_progress, ._72qoAq_progressError {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-2, #7f7f7f0f);\n color: var(--dsw-alias-label-primary, #1f2328);\n border-radius: 8px;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n}\n\n._72qoAq_progressError {\n border-color: var(--dsw-alias-danger, #e5484d);\n color: var(--dsw-alias-danger, #e5484d);\n}\n\n._72qoAq_progressSpin {\n border: 2px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-top-color: var(--dsw-alias-brand-primary, #4f6ef7);\n border-radius: 50%;\n flex-shrink: 0;\n width: 14px;\n height: 14px;\n animation: .8s linear infinite _72qoAq_dshApmSpin;\n}\n\n@keyframes _72qoAq_dshApmSpin {\n to {\n transform: rotate(360deg);\n }\n}\n\n._72qoAq_progressFail {\n flex-shrink: 0;\n font-size: 13px;\n}\n\n._72qoAq_progressText {\n overflow-wrap: anywhere;\n min-width: 0;\n}\n\n@media (width <= 720px) {\n ._72qoAq_pageView {\n padding: 14px;\n }\n\n ._72qoAq_titleRow {\n flex-wrap: wrap;\n }\n\n ._72qoAq_title {\n flex: 1 0 auto;\n }\n\n ._72qoAq_sub {\n white-space: normal;\n flex: 1 0 100%;\n order: 3;\n }\n\n ._72qoAq_searchGroup {\n flex: 1 0 100%;\n order: 4;\n }\n\n ._72qoAq_sourceTabsScroll {\n scrollbar-width: thin;\n padding-bottom: 2px;\n display: flex;\n overflow-x: auto;\n }\n\n ._72qoAq_srcTab, ._72qoAq_srcTabOn {\n flex: none;\n width: auto;\n min-width: 128px;\n }\n\n ._72qoAq_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n ._72qoAq_list ._72qoAq_cardTop, ._72qoAq_list ._72qoAq_cardActions {\n max-width: 100%;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._72qoAq_progressSpin, ._72qoAq_switchOn, ._72qoAq_switchOff, ._72qoAq_switchThumb {\n transition: none;\n animation: none;\n }\n}\n.vavGuW_toolbar {\n grid-template-columns: minmax(0, 1fr) 12px auto auto auto 8px auto;\n align-items: flex-end;\n gap: 0;\n min-width: 0;\n display: grid;\n}\n\n.vavGuW_filterGap, .vavGuW_viewGap {\n min-width: 0;\n}\n\n.vavGuW_search {\n box-sizing: border-box;\n align-items: center;\n width: 100%;\n min-width: 0;\n height: 36px;\n display: flex;\n}\n\n.vavGuW_search input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 36px;\n min-height: 36px;\n max-height: 36px;\n padding-top: 0;\n padding-bottom: 0;\n font-size: 12px;\n line-height: 20px;\n}\n\n.vavGuW_filter, .vavGuW_filterOn {\n min-width: 54px;\n height: 36px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n font: inherit;\n white-space: nowrap;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n justify-content: center;\n align-items: center;\n gap: 5px;\n padding: 7px 9px;\n font-size: 13px;\n display: inline-flex;\n}\n\n.vavGuW_filterOn {\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.vavGuW_filter svg, .vavGuW_filterOn svg, .vavGuW_viewSwitch svg {\n stroke: currentColor;\n stroke-width: 1.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.vavGuW_filterCount {\n font-variant-numeric: tabular-nums;\n}\n\n.vavGuW_viewSwitch {\n width: 34px;\n height: 36px;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n cursor: pointer;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n justify-content: center;\n align-items: center;\n display: inline-flex;\n}\n\n.vavGuW_viewSwitch:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.vavGuW_viewSwitch:focus-visible, .vavGuW_filter:focus-visible, .vavGuW_filterOn:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\n}\n\n@media (width <= 760px) {\n .vavGuW_toolbar {\n grid-template-columns: auto auto auto 8px auto;\n justify-content: end;\n overflow-x: auto;\n }\n\n .vavGuW_search {\n grid-column: 1 / -1;\n }\n\n .vavGuW_filterGap {\n display: none;\n }\n}\n.AUWlZW_surface {\n height: 100%;\n min-height: 0;\n max-height: 100%;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n.AUWlZW_header {\n flex: none;\n align-items: center;\n gap: 8px;\n padding: 4px 0 8px;\n display: flex;\n}\n\n.AUWlZW_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.AUWlZW_subtitle {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 2px 0 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n.AUWlZW_headerActions {\n align-items: center;\n gap: 8px;\n margin-left: auto;\n display: flex;\n}\n\n.AUWlZW_summary {\n color: var(--dsw-alias-label-secondary, #667085);\n white-space: nowrap;\n align-items: center;\n gap: 7px;\n font-size: 12px;\n display: inline-flex;\n}\n\n.AUWlZW_errorSummary {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n font-variant-numeric: tabular-nums;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n display: inline-flex;\n}\n\n.AUWlZW_summaryDotGreen, .AUWlZW_summaryDotRed {\n border-radius: 50%;\n width: 7px;\n height: 7px;\n}\n\n.AUWlZW_summaryDotGreen {\n background: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.AUWlZW_summaryDotRed {\n background: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.AUWlZW_toolbar {\n flex: none;\n margin-bottom: 24px;\n}\n\n.AUWlZW_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.AUWlZW_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.AUWlZW_list .AUWlZW_card {\n flex-flow: wrap;\n align-items: center;\n gap: 8px 14px;\n}\n\n.AUWlZW_list .AUWlZW_cardTop {\n flex: 0 260px;\n}\n\n.AUWlZW_list .AUWlZW_endpoint {\n -webkit-line-clamp: 1;\n flex: 200px;\n min-height: 0;\n}\n\n.AUWlZW_list .AUWlZW_meta {\n flex: 0 auto;\n}\n\n.AUWlZW_list .AUWlZW_cardReason {\n flex-basis: 100%;\n}\n\n.AUWlZW_card {\n min-width: 0;\n min-height: 0;\n color: inherit;\n background: var(--dsw-alias-bg-layer-1, #fff);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n cursor: pointer;\n font: inherit;\n text-align: left;\n border-radius: 12px;\n flex-direction: column;\n gap: 8px;\n padding: 12px 14px;\n display: flex;\n}\n\n.AUWlZW_card:hover {\n border-color: var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-hover, #00000009);\n}\n\n.AUWlZW_card:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\n}\n\n.AUWlZW_cardTop {\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.AUWlZW_statusDot {\n background: var(--dsw-alias-state-success-primary, #16a34a);\n border-radius: 50%;\n flex: none;\n width: 7px;\n height: 7px;\n}\n\n.AUWlZW_statusconnected {\n background: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.AUWlZW_statusdegraded {\n background: var(--dsw-alias-state-warn-primary, #b45309);\n}\n\n.AUWlZW_statusfailed {\n background: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.AUWlZW_statusdisabled {\n background: var(--dsw-alias-label-tertiary, #98a2b3);\n}\n\n.AUWlZW_service {\n flex: 1;\n min-width: 0;\n}\n\n.AUWlZW_name {\n color: var(--dsw-alias-label-primary, #1f2328);\n text-overflow: ellipsis;\n white-space: nowrap;\n font: 600 13px / 22px ui-monospace, Menlo, Consolas, monospace;\n display: block;\n overflow: hidden;\n}\n\n.AUWlZW_endpoint {\n min-height: 36px;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n -webkit-line-clamp: 2;\n overflow-wrap: anywhere;\n -webkit-box-orient: vertical;\n margin: 0;\n font: 12px / 18px ui-monospace, Menlo, Consolas, monospace;\n display: -webkit-box;\n overflow: hidden;\n}\n\n.AUWlZW_meta {\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.AUWlZW_sourcePlugin, .AUWlZW_sourceDirect, .AUWlZW_transport, .AUWlZW_toolCount {\n min-width: 0;\n max-width: 100%;\n color: var(--dsw-alias-label-secondary, #6b7280);\n border: 1px solid var(--dsw-alias-border-l3, #d9dde3);\n text-overflow: ellipsis;\n white-space: nowrap;\n border-radius: 4px;\n align-items: center;\n gap: 5px;\n padding: 1px 6px;\n font-size: 12px;\n line-height: 18px;\n display: inline-flex;\n}\n\n.AUWlZW_sourcePlugin svg, .AUWlZW_sourceDirect svg {\n color: currentColor;\n stroke: currentColor;\n stroke-width: 1.35px;\n stroke-linecap: round;\n stroke-linejoin: round;\n flex: none;\n width: 14px;\n height: 14px;\n}\n\n.AUWlZW_transport {\n font-family: ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_toolCount {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex: none;\n font-weight: 600;\n}\n\n.AUWlZW_cardReason {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n overflow-wrap: anywhere;\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.AUWlZW_state, .AUWlZW_detailState {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n white-space: nowrap;\n align-items: center;\n gap: 5px;\n font-size: 11px;\n display: inline-flex;\n}\n\n.AUWlZW_state:before, .AUWlZW_detailState:before {\n content: \"\";\n background: currentColor;\n border-radius: 50%;\n width: 6px;\n height: 6px;\n}\n\n.AUWlZW_stateconnected, .AUWlZW_detailStateconnected {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.AUWlZW_statedegraded, .AUWlZW_detailStatedegraded {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n}\n\n.AUWlZW_statefailed, .AUWlZW_detailStatefailed {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.AUWlZW_statedisabled, .AUWlZW_detailStatedisabled {\n color: var(--dsw-alias-label-tertiary, #98a2b3);\n}\n\n.AUWlZW_chevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 18px;\n}\n\n.AUWlZW_empty, .AUWlZW_detailEmpty {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-align: center;\n padding: 24px;\n font-size: 12px;\n}\n\n.AUWlZW_error {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n align-items: center;\n gap: 8px;\n margin: 16px 0;\n font-size: 12px;\n display: flex;\n}\n\n.AUWlZW_boundary {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n background: var(--dsw-alias-bg-layer-2, #f7f8fa);\n border-left: 2px solid var(--dsw-alias-border-l3, #d9dde3);\n margin: 10px 0 0;\n padding: 9px 10px;\n font-size: 11px;\n line-height: 17px;\n}\n\n.AUWlZW_detailDialog {\n width: min(720px, 94vw);\n}\n\n.AUWlZW_detailBody {\n max-height: 72vh;\n overflow-y: auto;\n}\n\n.AUWlZW_modalFooter {\n justify-content: flex-end;\n width: 100%;\n display: flex;\n}\n\n.AUWlZW_detail {\n flex-direction: column;\n gap: 16px;\n display: flex;\n}\n\n.AUWlZW_detailMeta {\n flex-wrap: wrap;\n gap: 6px;\n display: flex;\n}\n\n.AUWlZW_reason {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n background: var(--dsw-alias-bg-error, #dc26260f);\n border-left: 2px solid;\n padding: 9px 10px;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_detailSection {\n flex-direction: column;\n gap: 7px;\n display: flex;\n}\n\n.AUWlZW_detailHead {\n color: var(--dsw-alias-label-secondary, #667085);\n border-bottom: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n margin: 0;\n padding-bottom: 5px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.AUWlZW_config {\n max-height: 220px;\n color: var(--dsw-alias-label-primary, #344054);\n background: var(--dsw-alias-bg-layer-2, #f6f8fc);\n border: 1px solid var(--dsw-alias-border-l1, #e2e7ef);\n white-space: pre-wrap;\n word-break: break-word;\n border-radius: 7px;\n margin: 0;\n padding: 10px;\n font: 11px / 17px ui-monospace, Menlo, Consolas, monospace;\n overflow: auto;\n}\n\n.AUWlZW_toolList {\n flex-direction: column;\n display: flex;\n}\n\n.AUWlZW_tool {\n border-bottom: 1px solid var(--dsw-alias-border-l1, #eef1f5);\n grid-template-columns: 26px minmax(120px, auto) minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n padding: 7px 0;\n display: grid;\n}\n\n.AUWlZW_tool:last-child {\n border-bottom: none;\n}\n\n.AUWlZW_toolIndex {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n font: 10px / 16px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_toolName {\n color: var(--dsw-alias-label-primary, #1f2328);\n text-overflow: ellipsis;\n white-space: nowrap;\n font: 11px / 16px ui-monospace, Menlo, Consolas, monospace;\n overflow: hidden;\n}\n\n.AUWlZW_toolDescription {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 10px;\n overflow: hidden;\n}\n\n@media (width <= 760px) {\n .AUWlZW_header, .AUWlZW_toolbar {\n padding-left: 0;\n padding-right: 0;\n }\n\n .AUWlZW_header {\n flex-direction: column;\n }\n\n .AUWlZW_headerActions {\n justify-content: space-between;\n width: 100%;\n margin-left: 0;\n }\n\n .AUWlZW_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .AUWlZW_list .AUWlZW_cardTop, .AUWlZW_list .AUWlZW_meta {\n max-width: 100%;\n }\n\n .AUWlZW_tool {\n grid-template-columns: 26px minmax(0, 1fr);\n }\n\n .AUWlZW_toolDescription {\n display: none;\n }\n}\n";document.head.appendChild(s);}})();
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
//#region \0rolldown/runtime.js
|
|
8
8
|
var __create = Object.create;
|
|
@@ -29,7 +29,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
let react = require("react");
|
|
30
30
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
31
31
|
_deepseek_ai_dsh_client_ui_primitives = __toESM(_deepseek_ai_dsh_client_ui_primitives, 1);
|
|
32
|
+
let react_dom_client = require("react-dom/client");
|
|
32
33
|
//#region src/client/locales.ts
|
|
34
|
+
/** Chinese is the source-of-truth key set; English is checked against it below. */
|
|
33
35
|
const zh = {
|
|
34
36
|
nav: "Agent Plugins 市场",
|
|
35
37
|
subtitle: "发现与安装 Agent Plugins(agent-plugins.org 便携包)",
|
|
@@ -92,7 +94,7 @@ const zh = {
|
|
|
92
94
|
uninstall: "卸载",
|
|
93
95
|
uninstallConfirmTitle: "卸载 Agent Plugins",
|
|
94
96
|
uninstallConfirmDesc: "将从已安装列表移除该 Agent Plugins,其技能与 MCP 工具随即停止注入。仓库源克隆保留。",
|
|
95
|
-
removeSourceConfirmTitle: "
|
|
97
|
+
removeSourceConfirmTitle: "移除仓库源「{sourceId}」",
|
|
96
98
|
removeSourceConfirmDesc: "将删除该源的本地克隆与全部安装记录。",
|
|
97
99
|
enable: "启用",
|
|
98
100
|
disable: "禁用",
|
|
@@ -123,6 +125,8 @@ const zh = {
|
|
|
123
125
|
sourceNotCloned: "未克隆",
|
|
124
126
|
sourceCloned: "已克隆",
|
|
125
127
|
errors: "校验问题",
|
|
128
|
+
sourceErrorSeparator: ";",
|
|
129
|
+
viewMode: "视图模式",
|
|
126
130
|
grid: "网格",
|
|
127
131
|
list: "列表",
|
|
128
132
|
openSettings: "在设置中打开",
|
|
@@ -130,7 +134,32 @@ const zh = {
|
|
|
130
134
|
dataLabel: "Agent Plugins 数据目录",
|
|
131
135
|
countAll: "共 {n} 个 Agent Plugins",
|
|
132
136
|
countInstalled: "已装 {n}",
|
|
133
|
-
countEnabled: "启用 {n}"
|
|
137
|
+
countEnabled: "启用 {n}",
|
|
138
|
+
mcpStatusNav: "MCP 服务",
|
|
139
|
+
mcpStatusTitle: "MCP 服务",
|
|
140
|
+
mcpStatusSubtitle: "连接状态、来源和工具清单",
|
|
141
|
+
mcpSearch: "搜索 MCP 名称、来源或地址…",
|
|
142
|
+
mcpAll: "全部",
|
|
143
|
+
mcpPlugin: "Plugin",
|
|
144
|
+
mcpDirect: "直接安装",
|
|
145
|
+
mcpService: "服务",
|
|
146
|
+
mcpSource: "来源",
|
|
147
|
+
mcpTransport: "传输",
|
|
148
|
+
mcpTools: "工具",
|
|
149
|
+
mcpConnected: "已连接",
|
|
150
|
+
mcpDegraded: "降级",
|
|
151
|
+
mcpFailed: "失败",
|
|
152
|
+
mcpDisabled: "未启用",
|
|
153
|
+
mcpObservedEndpoint: "当前工具表观测",
|
|
154
|
+
mcpServiceDetail: "服务详情",
|
|
155
|
+
mcpConfig: "连接配置",
|
|
156
|
+
mcpSelectHint: "选择一个 MCP 服务查看配置与工具",
|
|
157
|
+
mcpEmpty: "没有匹配的 MCP 服务",
|
|
158
|
+
mcpNoTools: "当前没有已注册工具",
|
|
159
|
+
mcpDirectConfigUnavailable: "宿主未提供直接安装 MCP 的配置记录",
|
|
160
|
+
mcpDirectBoundary: "直接安装 MCP 仅显示当前工具表中可观测的服务;宿主未提供配置与连接状态 API。",
|
|
161
|
+
mcpBackToMarket: "返回市场",
|
|
162
|
+
mcpRetry: "重试"
|
|
134
163
|
};
|
|
135
164
|
const en = {
|
|
136
165
|
nav: "Agent Plugins Market",
|
|
@@ -194,7 +223,7 @@ const en = {
|
|
|
194
223
|
uninstall: "Uninstall",
|
|
195
224
|
uninstallConfirmTitle: "Uninstall suite",
|
|
196
225
|
uninstallConfirmDesc: "Removes the suite from the installed list; its skills and MCP tools stop injecting. The source clone stays.",
|
|
197
|
-
removeSourceConfirmTitle: "Remove source",
|
|
226
|
+
removeSourceConfirmTitle: "Remove source “{sourceId}”",
|
|
198
227
|
removeSourceConfirmDesc: "Deletes the local clone and all install records of this source.",
|
|
199
228
|
enable: "Enable",
|
|
200
229
|
disable: "Disable",
|
|
@@ -225,6 +254,8 @@ const en = {
|
|
|
225
254
|
sourceNotCloned: "not cloned",
|
|
226
255
|
sourceCloned: "cloned",
|
|
227
256
|
errors: "validation issues",
|
|
257
|
+
sourceErrorSeparator: "; ",
|
|
258
|
+
viewMode: "View mode",
|
|
228
259
|
grid: "grid",
|
|
229
260
|
list: "list",
|
|
230
261
|
openSettings: "Open in settings",
|
|
@@ -232,32 +263,92 @@ const en = {
|
|
|
232
263
|
dataLabel: "Suite data root",
|
|
233
264
|
countAll: "{n} suites",
|
|
234
265
|
countInstalled: "{n} installed",
|
|
235
|
-
countEnabled: "{n} enabled"
|
|
266
|
+
countEnabled: "{n} enabled",
|
|
267
|
+
mcpStatusNav: "MCP services",
|
|
268
|
+
mcpStatusTitle: "MCP services",
|
|
269
|
+
mcpStatusSubtitle: "Connection state, sources, and tools",
|
|
270
|
+
mcpSearch: "Search MCP names, sources, or endpoints…",
|
|
271
|
+
mcpAll: "All",
|
|
272
|
+
mcpPlugin: "Plugin",
|
|
273
|
+
mcpDirect: "Direct",
|
|
274
|
+
mcpService: "Service",
|
|
275
|
+
mcpSource: "Source",
|
|
276
|
+
mcpTransport: "Transport",
|
|
277
|
+
mcpTools: "tools",
|
|
278
|
+
mcpConnected: "connected",
|
|
279
|
+
mcpDegraded: "degraded",
|
|
280
|
+
mcpFailed: "failed",
|
|
281
|
+
mcpDisabled: "disabled",
|
|
282
|
+
mcpObservedEndpoint: "observed from tool registry",
|
|
283
|
+
mcpServiceDetail: "Service detail",
|
|
284
|
+
mcpConfig: "Connection config",
|
|
285
|
+
mcpSelectHint: "Select an MCP service to inspect config and tools",
|
|
286
|
+
mcpEmpty: "No matching MCP services",
|
|
287
|
+
mcpNoTools: "No registered tools",
|
|
288
|
+
mcpDirectConfigUnavailable: "The host does not expose direct-MCP configuration",
|
|
289
|
+
mcpDirectBoundary: "Direct MCP entries only show services observed in the current tool registry; the host exposes no config or connection-status API.",
|
|
290
|
+
mcpBackToMarket: "Back to market",
|
|
291
|
+
mcpRetry: "Retry"
|
|
236
292
|
};
|
|
237
293
|
//#endregion
|
|
294
|
+
//#region src/contracts/market.ts
|
|
295
|
+
/** Browser-safe market wire records and route constants shared by host and client. */
|
|
296
|
+
/** Prefix for all Agent Plugins Market HTTP routes. */
|
|
297
|
+
const MARKET_API_PREFIX = "/api/agent-plugins/";
|
|
298
|
+
/** Fixed Agent Plugins Market HTTP routes. */
|
|
299
|
+
const MARKET_ROUTES = {
|
|
300
|
+
overview: `${MARKET_API_PREFIX}overview`,
|
|
301
|
+
mcpStatus: `${MARKET_API_PREFIX}mcp-status`,
|
|
302
|
+
progress: `${MARKET_API_PREFIX}progress`,
|
|
303
|
+
config: `${MARKET_API_PREFIX}config`,
|
|
304
|
+
suite: `${MARKET_API_PREFIX}suite`,
|
|
305
|
+
skill: `${MARKET_API_PREFIX}skill`,
|
|
306
|
+
addSource: `${MARKET_API_PREFIX}sources/add`,
|
|
307
|
+
updateSource: `${MARKET_API_PREFIX}sources/update`,
|
|
308
|
+
removeSource: `${MARKET_API_PREFIX}sources/remove`,
|
|
309
|
+
refreshSource: `${MARKET_API_PREFIX}sources/refresh`,
|
|
310
|
+
install: `${MARKET_API_PREFIX}install`,
|
|
311
|
+
uninstall: `${MARKET_API_PREFIX}uninstall`,
|
|
312
|
+
setEnabled: `${MARKET_API_PREFIX}set-enabled`
|
|
313
|
+
};
|
|
314
|
+
/** Build a suite-detail URL without duplicating route or query encoding logic. */
|
|
315
|
+
function suiteRoute(sourceId, suiteId) {
|
|
316
|
+
return `${MARKET_ROUTES.suite}?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}`;
|
|
317
|
+
}
|
|
318
|
+
/** Build a skill-content URL without duplicating route or query encoding logic. */
|
|
319
|
+
function skillRoute(sourceId, suiteId, skill) {
|
|
320
|
+
return `${MARKET_ROUTES.skill}?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}&skill=${encodeURIComponent(skill)}`;
|
|
321
|
+
}
|
|
322
|
+
//#endregion
|
|
238
323
|
//#region src/client/api.ts
|
|
324
|
+
/** Typed fetch helpers over the host's `/api/agent-plugins/*` routes. */
|
|
239
325
|
async function fetchOverview() {
|
|
240
|
-
const response = await fetch(
|
|
326
|
+
const response = await fetch(MARKET_ROUTES.overview, { credentials: "same-origin" });
|
|
241
327
|
if (!response.ok) throw new Error(`overview failed: ${response.status}`);
|
|
242
328
|
return response.json();
|
|
243
329
|
}
|
|
244
330
|
async function fetchSourceProgress() {
|
|
245
|
-
const response = await fetch(
|
|
331
|
+
const response = await fetch(MARKET_ROUTES.progress, { credentials: "same-origin" });
|
|
246
332
|
if (!response.ok) throw new Error(`progress failed: ${response.status}`);
|
|
247
333
|
return response.json();
|
|
248
334
|
}
|
|
249
335
|
async function fetchSuiteDetail(sourceId, suiteId) {
|
|
250
|
-
const response = await fetch(
|
|
336
|
+
const response = await fetch(suiteRoute(sourceId, suiteId), { credentials: "same-origin" });
|
|
251
337
|
if (!response.ok) throw new Error(`suite detail failed: ${response.status}`);
|
|
252
338
|
return response.json();
|
|
253
339
|
}
|
|
340
|
+
async function fetchMcpStatus() {
|
|
341
|
+
const response = await fetch(MARKET_ROUTES.mcpStatus, { credentials: "same-origin" });
|
|
342
|
+
if (!response.ok) throw new Error(`MCP status failed: ${response.status}`);
|
|
343
|
+
return response.json();
|
|
344
|
+
}
|
|
254
345
|
async function fetchSkillContent(sourceId, suiteId, skill) {
|
|
255
|
-
const response = await fetch(
|
|
346
|
+
const response = await fetch(skillRoute(sourceId, suiteId, skill), { credentials: "same-origin" });
|
|
256
347
|
if (!response.ok) throw new Error(`skill content failed: ${response.status}`);
|
|
257
348
|
return response.json();
|
|
258
349
|
}
|
|
259
350
|
async function postAction(path, body) {
|
|
260
|
-
const response = await fetch(
|
|
351
|
+
const response = await fetch(`${MARKET_API_PREFIX}${path}`, {
|
|
261
352
|
method: "POST",
|
|
262
353
|
credentials: "same-origin",
|
|
263
354
|
headers: { "content-type": "application/json" },
|
|
@@ -268,6 +359,368 @@ async function postAction(path, body) {
|
|
|
268
359
|
return payload;
|
|
269
360
|
}
|
|
270
361
|
//#endregion
|
|
362
|
+
//#region src/client/features/market/market-resource.ts
|
|
363
|
+
/** Market overview cache, invalidation, and source-progress resource helpers. */
|
|
364
|
+
const EMPTY_OVERVIEW = {
|
|
365
|
+
sources: [],
|
|
366
|
+
suites: [],
|
|
367
|
+
totals: {
|
|
368
|
+
all: 0,
|
|
369
|
+
installed: 0,
|
|
370
|
+
enabled: 0
|
|
371
|
+
},
|
|
372
|
+
roots: {
|
|
373
|
+
user: "",
|
|
374
|
+
data: ""
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
let cachedOverview;
|
|
378
|
+
let inflightOverview;
|
|
379
|
+
/** Load the last overview immediately and revalidate one shared request. */
|
|
380
|
+
function loadOverview() {
|
|
381
|
+
const initial = cachedOverview ?? EMPTY_OVERVIEW;
|
|
382
|
+
if (inflightOverview === void 0) inflightOverview = fetchOverview().then((data) => {
|
|
383
|
+
cachedOverview = data;
|
|
384
|
+
return data;
|
|
385
|
+
}).finally(() => {
|
|
386
|
+
inflightOverview = void 0;
|
|
387
|
+
});
|
|
388
|
+
return {
|
|
389
|
+
initial,
|
|
390
|
+
revalidating: cachedOverview === void 0,
|
|
391
|
+
promise: inflightOverview
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
/** Invalidate the shared overview after a mutating action. */
|
|
395
|
+
function invalidateOverview() {
|
|
396
|
+
cachedOverview = void 0;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Poll source mutation progress until stopped. Poll failures remain silent
|
|
400
|
+
* because the add-source request is authoritative for mutation success.
|
|
401
|
+
*/
|
|
402
|
+
function startSourceProgressPolling(report, resolveStep = (step) => step) {
|
|
403
|
+
let stopped = false;
|
|
404
|
+
let timer;
|
|
405
|
+
const tick = async () => {
|
|
406
|
+
if (stopped) return;
|
|
407
|
+
try {
|
|
408
|
+
const progress = await fetchSourceProgress();
|
|
409
|
+
if (!stopped && progress.active) report({
|
|
410
|
+
step: resolveStep(progress.step),
|
|
411
|
+
error: void 0
|
|
412
|
+
});
|
|
413
|
+
} catch {}
|
|
414
|
+
if (!stopped) timer = setTimeout(() => {
|
|
415
|
+
tick();
|
|
416
|
+
}, 800);
|
|
417
|
+
};
|
|
418
|
+
timer = setTimeout(() => {
|
|
419
|
+
tick();
|
|
420
|
+
}, 400);
|
|
421
|
+
return { stop: () => {
|
|
422
|
+
stopped = true;
|
|
423
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
424
|
+
} };
|
|
425
|
+
}
|
|
426
|
+
//#endregion
|
|
427
|
+
//#region src/client/features/market/market-view-model.ts
|
|
428
|
+
const searchableCache$1 = /* @__PURE__ */ new WeakMap();
|
|
429
|
+
/** Derive visible cards and scope counts in one pass over a normalized payload. */
|
|
430
|
+
function deriveMarketViewModel(overview, search, filter, category) {
|
|
431
|
+
const searchable = searchableFor$1(overview);
|
|
432
|
+
const needle = search.trim().toLowerCase();
|
|
433
|
+
let all = 0;
|
|
434
|
+
let installed = 0;
|
|
435
|
+
let enabled = 0;
|
|
436
|
+
const visible = [];
|
|
437
|
+
for (const entry of searchable) {
|
|
438
|
+
const suite = entry.suite;
|
|
439
|
+
if (category !== "all" && suite.sourceId !== category) continue;
|
|
440
|
+
all++;
|
|
441
|
+
if (suite.installed) installed++;
|
|
442
|
+
if (suite.enabled) enabled++;
|
|
443
|
+
if (filter === "installed" && !suite.installed) continue;
|
|
444
|
+
if (filter === "uninstalled" && suite.installed) continue;
|
|
445
|
+
if (needle !== "" && !entry.haystack.includes(needle)) continue;
|
|
446
|
+
visible.push(suite);
|
|
447
|
+
}
|
|
448
|
+
return {
|
|
449
|
+
scopeTotals: {
|
|
450
|
+
all,
|
|
451
|
+
installed,
|
|
452
|
+
enabled
|
|
453
|
+
},
|
|
454
|
+
filtered: visible
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
function searchableFor$1(overview) {
|
|
458
|
+
const cached = searchableCache$1.get(overview);
|
|
459
|
+
if (cached !== void 0) return cached;
|
|
460
|
+
const searchable = overview.suites.map((suite) => ({
|
|
461
|
+
suite,
|
|
462
|
+
haystack: `${suite.name} ${suite.description ?? ""} ${suite.keywords.join(" ")}`.toLowerCase()
|
|
463
|
+
}));
|
|
464
|
+
searchableCache$1.set(overview, searchable);
|
|
465
|
+
return searchable;
|
|
466
|
+
}
|
|
467
|
+
//#endregion
|
|
468
|
+
//#region src/client/market.module.css
|
|
469
|
+
var market_module_default = {
|
|
470
|
+
"body": "_72qoAq_body",
|
|
471
|
+
"card": "_72qoAq_card",
|
|
472
|
+
"cardActions": "_72qoAq_cardActions",
|
|
473
|
+
"cardDesc": "_72qoAq_cardDesc",
|
|
474
|
+
"cardName": "_72qoAq_cardName",
|
|
475
|
+
"cardTitle": "_72qoAq_cardTitle",
|
|
476
|
+
"cardTop": "_72qoAq_cardTop",
|
|
477
|
+
"desc": "_72qoAq_desc",
|
|
478
|
+
"detailBody": "_72qoAq_detailBody",
|
|
479
|
+
"detailCell": "_72qoAq_detailCell",
|
|
480
|
+
"detailChevron": "_72qoAq_detailChevron",
|
|
481
|
+
"detailDesc": "_72qoAq_detailDesc",
|
|
482
|
+
"detailDialog": "_72qoAq_detailDialog",
|
|
483
|
+
"detailGrid": "_72qoAq_detailGrid",
|
|
484
|
+
"detailHead": "_72qoAq_detailHead",
|
|
485
|
+
"detailItem": "_72qoAq_detailItem",
|
|
486
|
+
"detailItemDesc": "_72qoAq_detailItemDesc",
|
|
487
|
+
"detailItemName": "_72qoAq_detailItemName",
|
|
488
|
+
"detailItemOpen": "_72qoAq_detailItemOpen",
|
|
489
|
+
"detailItemRow": "_72qoAq_detailItemRow",
|
|
490
|
+
"detailKey": "_72qoAq_detailKey",
|
|
491
|
+
"detailSection": "_72qoAq_detailSection",
|
|
492
|
+
"detailSections": "_72qoAq_detailSections",
|
|
493
|
+
"detailValue": "_72qoAq_detailValue",
|
|
494
|
+
"dshApmSpin": "_72qoAq_dshApmSpin",
|
|
495
|
+
"editorDialog": "_72qoAq_editorDialog",
|
|
496
|
+
"editorForm": "_72qoAq_editorForm",
|
|
497
|
+
"empty": "_72qoAq_empty",
|
|
498
|
+
"fieldGroup": "_72qoAq_fieldGroup",
|
|
499
|
+
"fieldHint": "_72qoAq_fieldHint",
|
|
500
|
+
"fieldLabel": "_72qoAq_fieldLabel",
|
|
501
|
+
"grid": "_72qoAq_grid",
|
|
502
|
+
"header": "_72qoAq_header",
|
|
503
|
+
"list": "_72qoAq_list",
|
|
504
|
+
"market": "_72qoAq_market",
|
|
505
|
+
"marketControls": "_72qoAq_marketControls",
|
|
506
|
+
"mcpSurface": "_72qoAq_mcpSurface",
|
|
507
|
+
"meta": "_72qoAq_meta",
|
|
508
|
+
"modalFooter": "_72qoAq_modalFooter",
|
|
509
|
+
"modalFooterLeft": "_72qoAq_modalFooterLeft",
|
|
510
|
+
"modeRow": "_72qoAq_modeRow",
|
|
511
|
+
"mono": "_72qoAq_mono",
|
|
512
|
+
"okState": "_72qoAq_okState",
|
|
513
|
+
"pageEntry": "_72qoAq_pageEntry",
|
|
514
|
+
"pageMode": "_72qoAq_pageMode",
|
|
515
|
+
"pageView": "_72qoAq_pageView",
|
|
516
|
+
"progress": "_72qoAq_progress",
|
|
517
|
+
"progressError": "_72qoAq_progressError",
|
|
518
|
+
"progressFail": "_72qoAq_progressFail",
|
|
519
|
+
"progressSpin": "_72qoAq_progressSpin",
|
|
520
|
+
"progressText": "_72qoAq_progressText",
|
|
521
|
+
"searchGroup": "_72qoAq_searchGroup",
|
|
522
|
+
"seg": "_72qoAq_seg",
|
|
523
|
+
"segOn": "_72qoAq_segOn",
|
|
524
|
+
"skillContent": "_72qoAq_skillContent",
|
|
525
|
+
"sourceTabsRow": "_72qoAq_sourceTabsRow",
|
|
526
|
+
"sourceTabsScroll": "_72qoAq_sourceTabsScroll",
|
|
527
|
+
"spacer": "_72qoAq_spacer",
|
|
528
|
+
"src": "_72qoAq_src",
|
|
529
|
+
"srcTab": "_72qoAq_srcTab",
|
|
530
|
+
"srcTabDel": "_72qoAq_srcTabDel",
|
|
531
|
+
"srcTabEdit": "_72qoAq_srcTabEdit",
|
|
532
|
+
"srcTabMain": "_72qoAq_srcTabMain",
|
|
533
|
+
"srcTabOn": "_72qoAq_srcTabOn",
|
|
534
|
+
"staticId": "_72qoAq_staticId",
|
|
535
|
+
"staticIdValue": "_72qoAq_staticIdValue",
|
|
536
|
+
"sub": "_72qoAq_sub",
|
|
537
|
+
"surfaceSwitch": "_72qoAq_surfaceSwitch",
|
|
538
|
+
"switchOff": "_72qoAq_switchOff",
|
|
539
|
+
"switchOn": "_72qoAq_switchOn",
|
|
540
|
+
"switchThumb": "_72qoAq_switchThumb",
|
|
541
|
+
"tag": "_72qoAq_tag",
|
|
542
|
+
"title": "_72qoAq_title",
|
|
543
|
+
"titleRow": "_72qoAq_titleRow",
|
|
544
|
+
"version": "_72qoAq_version",
|
|
545
|
+
"warnLine": "_72qoAq_warnLine"
|
|
546
|
+
};
|
|
547
|
+
//#endregion
|
|
548
|
+
//#region src/client/features/market/SourceTab.tsx
|
|
549
|
+
/** A source tab with trailing edit and delete controls. */
|
|
550
|
+
/** A source chip with a trailing delete control (deletion confirms at the section level). */
|
|
551
|
+
function SourceTab(props) {
|
|
552
|
+
const { t, active = false, label, onSelect, onDelete, onEdit } = props;
|
|
553
|
+
return (0, react.createElement)("div", { className: active ? market_module_default.srcTabOn : market_module_default.srcTab }, (0, react.createElement)("button", {
|
|
554
|
+
type: "button",
|
|
555
|
+
className: market_module_default.srcTabMain,
|
|
556
|
+
onClick: onSelect
|
|
557
|
+
}, label), onEdit === void 0 ? null : (0, react.createElement)("button", {
|
|
558
|
+
type: "button",
|
|
559
|
+
className: market_module_default.srcTabEdit,
|
|
560
|
+
title: t("editSource"),
|
|
561
|
+
onClick: (event) => {
|
|
562
|
+
event.stopPropagation();
|
|
563
|
+
onEdit();
|
|
564
|
+
}
|
|
565
|
+
}, "✎"), onDelete === void 0 ? null : (0, react.createElement)("button", {
|
|
566
|
+
type: "button",
|
|
567
|
+
className: market_module_default.srcTabDel,
|
|
568
|
+
title: t("remove"),
|
|
569
|
+
onClick: (event) => {
|
|
570
|
+
event.stopPropagation();
|
|
571
|
+
onDelete();
|
|
572
|
+
}
|
|
573
|
+
}, "×"));
|
|
574
|
+
}
|
|
575
|
+
//#endregion
|
|
576
|
+
//#region src/client/features/market/SourceEditorModal.tsx
|
|
577
|
+
/** Source editor modal for adding or editing a catalog source. */
|
|
578
|
+
function SourceEditorModal(props) {
|
|
579
|
+
const { t, editor } = props;
|
|
580
|
+
const [local, setLocal] = (0, react.useState)(editor.mode === "edit" && editor.source.local === true);
|
|
581
|
+
const [url, setUrl] = (0, react.useState)(editor.mode === "edit" ? editor.source.url : "");
|
|
582
|
+
const [branch, setBranch] = (0, react.useState)(editor.mode === "edit" ? editor.source.branch ?? "" : "");
|
|
583
|
+
const id = editor.mode === "edit" ? editor.source.id : "";
|
|
584
|
+
const title = editor.mode === "edit" ? t("editSourceTitle") : t("addSourceTitle");
|
|
585
|
+
return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
586
|
+
open: true,
|
|
587
|
+
onClose: props.onClose,
|
|
588
|
+
title,
|
|
589
|
+
description: t("editorHint"),
|
|
590
|
+
closeLabel: t("cancel"),
|
|
591
|
+
className: market_module_default.editorDialog,
|
|
592
|
+
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, {
|
|
593
|
+
variant: "ghost",
|
|
594
|
+
onClick: () => props.onRemove(id)
|
|
595
|
+
}, `🗑 ${t("remove")}`) : null), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
596
|
+
variant: "ghost",
|
|
597
|
+
onClick: props.onClose
|
|
598
|
+
}, t("cancel")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
599
|
+
variant: "primary",
|
|
600
|
+
disabled: props.busy,
|
|
601
|
+
onClick: () => {
|
|
602
|
+
props.onSave(url.trim(), branch.trim(), local);
|
|
603
|
+
}
|
|
604
|
+
}, t("save"))),
|
|
605
|
+
children: (0, react.createElement)("div", { className: market_module_default.editorForm }, (0, react.createElement)("div", { className: market_module_default.modeRow }, (0, react.createElement)("button", {
|
|
606
|
+
type: "button",
|
|
607
|
+
className: local ? market_module_default.seg : market_module_default.segOn,
|
|
608
|
+
onClick: () => setLocal(false)
|
|
609
|
+
}, t("sourceModeGit")), (0, react.createElement)("button", {
|
|
610
|
+
type: "button",
|
|
611
|
+
className: local ? market_module_default.segOn : market_module_default.seg,
|
|
612
|
+
onClick: () => setLocal(true)
|
|
613
|
+
}, 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, {
|
|
614
|
+
placeholder: local ? t("sourceUrlLocalPh") : t("sourceUrlPh"),
|
|
615
|
+
value: url,
|
|
616
|
+
onChange: (event) => setUrl(event.target.value)
|
|
617
|
+
}), (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, {
|
|
618
|
+
placeholder: t("branchPh"),
|
|
619
|
+
value: branch,
|
|
620
|
+
onChange: (event) => setBranch(event.target.value)
|
|
621
|
+
}), (0, react.createElement)("span", { className: market_module_default.fieldHint }, t("branchHint"))), props.progress.error === void 0 && props.progress.step === void 0 ? null : (0, react.createElement)("div", { className: props.progress.error === void 0 ? market_module_default.progress : market_module_default.progressError }, props.progress.error === void 0 ? (0, react.createElement)("span", { className: market_module_default.progressSpin }) : (0, react.createElement)("span", { className: market_module_default.progressFail }, "✕"), (0, react.createElement)("span", { className: market_module_default.progressText }, props.progress.error === void 0 ? props.progress.step : `${t("actionFail")}: ${props.progress.error}`)))
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
//#endregion
|
|
625
|
+
//#region src/client/ui/ToggleSwitch.tsx
|
|
626
|
+
/** Shared green/gray switch control used by suite cards. */
|
|
627
|
+
/** A green/gray switch control for suite enable state. */
|
|
628
|
+
function ToggleSwitch(props) {
|
|
629
|
+
return (0, react.createElement)("button", {
|
|
630
|
+
type: "button",
|
|
631
|
+
role: "switch",
|
|
632
|
+
"aria-checked": props.on,
|
|
633
|
+
title: props.title,
|
|
634
|
+
disabled: props.disabled,
|
|
635
|
+
className: props.on ? market_module_default.switchOn : market_module_default.switchOff,
|
|
636
|
+
onClick: (event) => {
|
|
637
|
+
event.stopPropagation();
|
|
638
|
+
props.onChange();
|
|
639
|
+
}
|
|
640
|
+
}, (0, react.createElement)("span", { className: market_module_default.switchThumb }));
|
|
641
|
+
}
|
|
642
|
+
//#endregion
|
|
643
|
+
//#region src/client/features/market/SuiteCard.tsx
|
|
644
|
+
/** A suite card in the market grid/list. */
|
|
645
|
+
function SuiteCard(props) {
|
|
646
|
+
const { t, suite, busy } = props;
|
|
647
|
+
const tags = [
|
|
648
|
+
[t("surfaceSkills"), suite.surfaces.skills],
|
|
649
|
+
[t("surfaceMcp"), suite.surfaces.mcp],
|
|
650
|
+
[t("surfaceHooks"), suite.surfaces.hooks],
|
|
651
|
+
[t("surfaceCommands"), suite.surfaces.commands],
|
|
652
|
+
[t("surfaceAgents"), suite.surfaces.agents],
|
|
653
|
+
[t("surfaceLsp"), suite.surfaces.lsp]
|
|
654
|
+
].filter(([, count]) => count > 0);
|
|
655
|
+
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");
|
|
656
|
+
const isRemote = suite.remoteUrl !== void 0;
|
|
657
|
+
const stop = (callback) => (event) => {
|
|
658
|
+
event.stopPropagation();
|
|
659
|
+
callback();
|
|
660
|
+
};
|
|
661
|
+
return (0, react.createElement)("article", {
|
|
662
|
+
className: market_module_default.card,
|
|
663
|
+
onClick: props.onOpen
|
|
664
|
+
}, (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, {
|
|
665
|
+
on: suite.enabled,
|
|
666
|
+
disabled: busy,
|
|
667
|
+
title: suite.enabled ? t("disable") : t("enable"),
|
|
668
|
+
onChange: props.onToggle
|
|
669
|
+
}) : isRemote ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
670
|
+
variant: "primary",
|
|
671
|
+
size: "sm",
|
|
672
|
+
disabled: busy,
|
|
673
|
+
title: suite.remoteUrl,
|
|
674
|
+
onClick: stop(props.onAddSource)
|
|
675
|
+
}, t("addSource")) : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
676
|
+
variant: "primary",
|
|
677
|
+
size: "sm",
|
|
678
|
+
disabled: busy,
|
|
679
|
+
onClick: stop(props.onInstall)
|
|
680
|
+
}, t("install")), suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
681
|
+
variant: "ghost",
|
|
682
|
+
size: "sm",
|
|
683
|
+
title: t("refresh"),
|
|
684
|
+
disabled: busy,
|
|
685
|
+
onClick: stop(props.onRefresh)
|
|
686
|
+
}, "↻") : null, suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
687
|
+
variant: "ghost",
|
|
688
|
+
size: "sm",
|
|
689
|
+
title: t("uninstall"),
|
|
690
|
+
disabled: busy,
|
|
691
|
+
onClick: stop(props.onUninstall)
|
|
692
|
+
}, "🗑") : 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", {
|
|
693
|
+
key: label,
|
|
694
|
+
className: market_module_default.tag
|
|
695
|
+
}, `${label} ${count}`)), suite.errors.length === 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
696
|
+
label: suite.errors.slice(0, 8).join(t("sourceErrorSeparator")),
|
|
697
|
+
children: (0, react.createElement)("span", { className: market_module_default.warnLine }, `⚠ ${t("errors")} ${suite.errors.length}`)
|
|
698
|
+
}), (suite.mcpErrors?.length ?? 0) === 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
699
|
+
label: suite.mcpErrors.slice(0, 8).join(t("sourceErrorSeparator")),
|
|
700
|
+
children: (0, react.createElement)("span", { className: market_module_default.warnLine }, `⚠ ${t("mcpSection")} ${suite.mcpErrors.length}`)
|
|
701
|
+
})));
|
|
702
|
+
}
|
|
703
|
+
//#endregion
|
|
704
|
+
//#region src/client/ui/StatusIcon.tsx
|
|
705
|
+
/** Shared status icon used by market and MCP status filter tabs. */
|
|
706
|
+
/** An SVG status icon for the all/installed/uninstalled filter tabs. */
|
|
707
|
+
function StatusIcon({ kind }) {
|
|
708
|
+
const common = {
|
|
709
|
+
width: 16,
|
|
710
|
+
height: 16,
|
|
711
|
+
viewBox: "0 0 16 16",
|
|
712
|
+
fill: "none",
|
|
713
|
+
"aria-hidden": true
|
|
714
|
+
};
|
|
715
|
+
if (kind === "installed") return (0, react.createElement)("svg", common, (0, react.createElement)("circle", {
|
|
716
|
+
cx: 8,
|
|
717
|
+
cy: 8,
|
|
718
|
+
r: 5.5
|
|
719
|
+
}), (0, react.createElement)("path", { d: "m5.5 8 1.7 1.7 3.4-3.4" }));
|
|
720
|
+
if (kind === "uninstalled") return (0, react.createElement)("svg", common, (0, react.createElement)("path", { d: "M8 2v8m-3-3 3 3 3-3M3 13h10" }));
|
|
721
|
+
return (0, react.createElement)("svg", common, (0, react.createElement)("path", { d: "M2.5 5 8 2.5 13.5 5 8 7.5 2.5 5Zm0 3L8 10.5 13.5 8M2.5 11 8 13.5 13.5 11" }));
|
|
722
|
+
}
|
|
723
|
+
//#endregion
|
|
271
724
|
//#region src/client/ErrorBoundary.tsx
|
|
272
725
|
/**
|
|
273
726
|
* Error boundary for untrusted preview content.
|
|
@@ -290,86 +743,18 @@ var ErrorBoundary = class extends react.Component {
|
|
|
290
743
|
}
|
|
291
744
|
};
|
|
292
745
|
//#endregion
|
|
293
|
-
//#region src/client/
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
"detailChevron": "qMtKNa_detailChevron",
|
|
306
|
-
"detailDesc": "qMtKNa_detailDesc",
|
|
307
|
-
"detailDialog": "qMtKNa_detailDialog",
|
|
308
|
-
"detailGrid": "qMtKNa_detailGrid",
|
|
309
|
-
"detailHead": "qMtKNa_detailHead",
|
|
310
|
-
"detailItem": "qMtKNa_detailItem",
|
|
311
|
-
"detailItemDesc": "qMtKNa_detailItemDesc",
|
|
312
|
-
"detailItemName": "qMtKNa_detailItemName",
|
|
313
|
-
"detailItemOpen": "qMtKNa_detailItemOpen",
|
|
314
|
-
"detailItemRow": "qMtKNa_detailItemRow",
|
|
315
|
-
"detailKey": "qMtKNa_detailKey",
|
|
316
|
-
"detailSection": "qMtKNa_detailSection",
|
|
317
|
-
"detailSections": "qMtKNa_detailSections",
|
|
318
|
-
"detailValue": "qMtKNa_detailValue",
|
|
319
|
-
"dshApmSpin": "qMtKNa_dshApmSpin",
|
|
320
|
-
"editorDialog": "qMtKNa_editorDialog",
|
|
321
|
-
"editorForm": "qMtKNa_editorForm",
|
|
322
|
-
"empty": "qMtKNa_empty",
|
|
323
|
-
"fieldGroup": "qMtKNa_fieldGroup",
|
|
324
|
-
"fieldHint": "qMtKNa_fieldHint",
|
|
325
|
-
"fieldLabel": "qMtKNa_fieldLabel",
|
|
326
|
-
"grid": "qMtKNa_grid",
|
|
327
|
-
"header": "qMtKNa_header",
|
|
328
|
-
"list": "qMtKNa_list",
|
|
329
|
-
"market": "qMtKNa_market",
|
|
330
|
-
"meta": "qMtKNa_meta",
|
|
331
|
-
"modalFooter": "qMtKNa_modalFooter",
|
|
332
|
-
"modalFooterLeft": "qMtKNa_modalFooterLeft",
|
|
333
|
-
"modeRow": "qMtKNa_modeRow",
|
|
334
|
-
"mono": "qMtKNa_mono",
|
|
335
|
-
"okState": "qMtKNa_okState",
|
|
336
|
-
"progress": "qMtKNa_progress",
|
|
337
|
-
"progressError": "qMtKNa_progressError",
|
|
338
|
-
"progressFail": "qMtKNa_progressFail",
|
|
339
|
-
"progressSpin": "qMtKNa_progressSpin",
|
|
340
|
-
"progressText": "qMtKNa_progressText",
|
|
341
|
-
"searchGroup": "qMtKNa_searchGroup",
|
|
342
|
-
"searchInput": "qMtKNa_searchInput",
|
|
343
|
-
"searchWrap": "qMtKNa_searchWrap",
|
|
344
|
-
"seg": "qMtKNa_seg",
|
|
345
|
-
"segOn": "qMtKNa_segOn",
|
|
346
|
-
"skillContent": "qMtKNa_skillContent",
|
|
347
|
-
"sourceTabsRow": "qMtKNa_sourceTabsRow",
|
|
348
|
-
"sourceTabsScroll": "qMtKNa_sourceTabsScroll",
|
|
349
|
-
"spacer": "qMtKNa_spacer",
|
|
350
|
-
"src": "qMtKNa_src",
|
|
351
|
-
"srcTab": "qMtKNa_srcTab",
|
|
352
|
-
"srcTabDel": "qMtKNa_srcTabDel",
|
|
353
|
-
"srcTabEdit": "qMtKNa_srcTabEdit",
|
|
354
|
-
"srcTabMain": "qMtKNa_srcTabMain",
|
|
355
|
-
"srcTabOn": "qMtKNa_srcTabOn",
|
|
356
|
-
"staticId": "qMtKNa_staticId",
|
|
357
|
-
"staticIdValue": "qMtKNa_staticIdValue",
|
|
358
|
-
"sub": "qMtKNa_sub",
|
|
359
|
-
"switchOff": "qMtKNa_switchOff",
|
|
360
|
-
"switchOn": "qMtKNa_switchOn",
|
|
361
|
-
"switchThumb": "qMtKNa_switchThumb",
|
|
362
|
-
"tab": "qMtKNa_tab",
|
|
363
|
-
"tabGap": "qMtKNa_tabGap",
|
|
364
|
-
"tabOn": "qMtKNa_tabOn",
|
|
365
|
-
"tabRow": "qMtKNa_tabRow",
|
|
366
|
-
"tag": "qMtKNa_tag",
|
|
367
|
-
"title": "qMtKNa_title",
|
|
368
|
-
"titleRow": "qMtKNa_titleRow",
|
|
369
|
-
"version": "qMtKNa_version",
|
|
370
|
-
"viewSwitch": "qMtKNa_viewSwitch",
|
|
371
|
-
"warnLine": "qMtKNa_warnLine"
|
|
372
|
-
};
|
|
746
|
+
//#region src/client/features/suite-detail/suite-detail-resource.ts
|
|
747
|
+
/** Create a request guard for one detail modal instance. */
|
|
748
|
+
function createLatestRequestGuard() {
|
|
749
|
+
let revision = 0;
|
|
750
|
+
return {
|
|
751
|
+
next: () => ++revision,
|
|
752
|
+
invalidate: () => {
|
|
753
|
+
revision++;
|
|
754
|
+
},
|
|
755
|
+
isCurrent: (requestId) => requestId === revision
|
|
756
|
+
};
|
|
757
|
+
}
|
|
373
758
|
//#endregion
|
|
374
759
|
//#region src/client/SuiteDetail.tsx
|
|
375
760
|
/**
|
|
@@ -386,12 +771,16 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
|
|
|
386
771
|
const [openSkill, setOpenSkill] = (0, react.useState)(void 0);
|
|
387
772
|
const [skillText, setSkillText] = (0, react.useState)(void 0);
|
|
388
773
|
const [skillLoading, setSkillLoading] = (0, react.useState)(false);
|
|
774
|
+
const skillRequestGuard = (0, react.useRef)(createLatestRequestGuard());
|
|
389
775
|
const [openMcp, setOpenMcp] = (0, react.useState)(void 0);
|
|
390
776
|
const [openPreview, setOpenPreview] = (0, react.useState)(void 0);
|
|
391
777
|
(0, react.useEffect)(() => {
|
|
392
778
|
let cancelled = false;
|
|
779
|
+
skillRequestGuard.current.invalidate();
|
|
393
780
|
setDetail(void 0);
|
|
394
781
|
setError(void 0);
|
|
782
|
+
setOpenSkill(void 0);
|
|
783
|
+
setSkillText(void 0);
|
|
395
784
|
fetchSuiteDetail(sourceId, suiteId).then((value) => {
|
|
396
785
|
if (!cancelled) setDetail(value);
|
|
397
786
|
}).catch((reason) => {
|
|
@@ -399,9 +788,11 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
|
|
|
399
788
|
});
|
|
400
789
|
return () => {
|
|
401
790
|
cancelled = true;
|
|
791
|
+
skillRequestGuard.current.invalidate();
|
|
402
792
|
};
|
|
403
793
|
}, [sourceId, suiteId]);
|
|
404
794
|
const toggleSkill = async (name) => {
|
|
795
|
+
const requestId = skillRequestGuard.current.next();
|
|
405
796
|
if (openSkill === name) {
|
|
406
797
|
setOpenSkill(void 0);
|
|
407
798
|
return;
|
|
@@ -411,17 +802,17 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
|
|
|
411
802
|
setSkillText(void 0);
|
|
412
803
|
try {
|
|
413
804
|
const content = await fetchSkillContent(sourceId, suiteId, name);
|
|
414
|
-
setSkillText(content.content);
|
|
805
|
+
if (skillRequestGuard.current.isCurrent(requestId)) setSkillText(content.content);
|
|
415
806
|
} catch (reason) {
|
|
416
|
-
setSkillText(`⚠ ${reason instanceof Error ? reason.message : String(reason)}`);
|
|
807
|
+
if (skillRequestGuard.current.isCurrent(requestId)) setSkillText(`⚠ ${reason instanceof Error ? reason.message : String(reason)}`);
|
|
417
808
|
} finally {
|
|
418
|
-
setSkillLoading(false);
|
|
809
|
+
if (skillRequestGuard.current.isCurrent(requestId)) setSkillLoading(false);
|
|
419
810
|
}
|
|
420
811
|
};
|
|
421
812
|
const toggleMcp = (key) => {
|
|
422
813
|
setOpenMcp(openMcp === key ? void 0 : key);
|
|
423
814
|
};
|
|
424
|
-
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");
|
|
815
|
+
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 === "universal" ? t("layoutUniversal") : detail.layout === "cursor" ? t("layoutCursor") : detail.layout === "kimi" ? t("layoutKimi") : detail.layout === "remote" ? t("layoutRemote") : t("layoutSkills");
|
|
425
816
|
return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
426
817
|
open: true,
|
|
427
818
|
onClose,
|
|
@@ -448,7 +839,7 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
|
|
|
448
839
|
}, (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.mcpErrors.length === 0 ? null : (0, react.createElement)("div", {
|
|
449
840
|
className: market_module_default.warnLine,
|
|
450
841
|
style: { margin: "0 0 6px" }
|
|
451
|
-
}, `⚠ ${detail.mcpErrors.join("
|
|
842
|
+
}, `⚠ ${detail.mcpErrors.join(t("sourceErrorSeparator"))}`), detail.mcpServers.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.mcpServers.map((server) => (0, react.createElement)("div", {
|
|
452
843
|
key: server.key,
|
|
453
844
|
className: market_module_default.detailItem
|
|
454
845
|
}, (0, react.createElement)("button", {
|
|
@@ -498,7 +889,7 @@ function mcpSummary(server) {
|
|
|
498
889
|
return server.url ?? server.type;
|
|
499
890
|
}
|
|
500
891
|
function PreviewRow(props) {
|
|
501
|
-
const {
|
|
892
|
+
const { name, description, open, onToggle, children } = props;
|
|
502
893
|
return (0, react.createElement)("div", { className: market_module_default.detailItem }, (0, react.createElement)("button", {
|
|
503
894
|
type: "button",
|
|
504
895
|
className: open ? market_module_default.detailItemOpen : market_module_default.detailItemRow,
|
|
@@ -506,6 +897,87 @@ function PreviewRow(props) {
|
|
|
506
897
|
}, (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);
|
|
507
898
|
}
|
|
508
899
|
//#endregion
|
|
900
|
+
//#region src/client/SearchFilterToolbar.module.css
|
|
901
|
+
var SearchFilterToolbar_module_default = {
|
|
902
|
+
"filter": "vavGuW_filter",
|
|
903
|
+
"filterCount": "vavGuW_filterCount",
|
|
904
|
+
"filterGap": "vavGuW_filterGap",
|
|
905
|
+
"filterOn": "vavGuW_filterOn",
|
|
906
|
+
"search": "vavGuW_search",
|
|
907
|
+
"toolbar": "vavGuW_toolbar",
|
|
908
|
+
"viewGap": "vavGuW_viewGap",
|
|
909
|
+
"viewSwitch": "vavGuW_viewSwitch"
|
|
910
|
+
};
|
|
911
|
+
//#endregion
|
|
912
|
+
//#region src/client/SearchFilterToolbar.tsx
|
|
913
|
+
/**
|
|
914
|
+
* Shared search, filter, and view controls for catalog-style settings panels.
|
|
915
|
+
*/
|
|
916
|
+
/**
|
|
917
|
+
* Render a consistent control row for searchable grid and list content.
|
|
918
|
+
*
|
|
919
|
+
* @param props - Search state, selectable filters, and view-mode state.
|
|
920
|
+
* @returns Search input, filter tabs, and an accessible grid/list toggle.
|
|
921
|
+
*/
|
|
922
|
+
function SearchFilterToolbar(props) {
|
|
923
|
+
const nextView = props.view === "grid" ? "list" : "grid";
|
|
924
|
+
const nextViewLabel = nextView === "grid" ? props.gridLabel : props.listLabel;
|
|
925
|
+
return (0, react.createElement)("div", { className: props.className === void 0 ? SearchFilterToolbar_module_default.toolbar : `${SearchFilterToolbar_module_default.toolbar} ${props.className}` }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
926
|
+
className: SearchFilterToolbar_module_default.search,
|
|
927
|
+
value: props.search,
|
|
928
|
+
placeholder: props.searchPlaceholder,
|
|
929
|
+
"aria-label": props.searchLabel,
|
|
930
|
+
onChange: (event) => props.onSearchChange(event.target.value)
|
|
931
|
+
}), (0, react.createElement)("div", { className: SearchFilterToolbar_module_default.filterGap }), ...props.filters.map((filter) => (0, react.createElement)("button", {
|
|
932
|
+
key: filter.id,
|
|
933
|
+
type: "button",
|
|
934
|
+
className: filter.active ? SearchFilterToolbar_module_default.filterOn : SearchFilterToolbar_module_default.filter,
|
|
935
|
+
title: `${filter.label} ${filter.count}`,
|
|
936
|
+
"aria-label": `${filter.label} ${filter.count}`,
|
|
937
|
+
onClick: filter.onSelect
|
|
938
|
+
}, filter.icon, (0, react.createElement)("span", { className: SearchFilterToolbar_module_default.filterCount }, filter.count))), (0, react.createElement)("div", { className: SearchFilterToolbar_module_default.viewGap }), (0, react.createElement)("button", {
|
|
939
|
+
type: "button",
|
|
940
|
+
className: SearchFilterToolbar_module_default.viewSwitch,
|
|
941
|
+
"aria-label": nextViewLabel,
|
|
942
|
+
title: nextViewLabel,
|
|
943
|
+
onClick: () => props.onViewChange(nextView)
|
|
944
|
+
}, (0, react.createElement)(ViewIcon, { mode: nextView })));
|
|
945
|
+
}
|
|
946
|
+
function ViewIcon({ mode }) {
|
|
947
|
+
const common = {
|
|
948
|
+
width: 16,
|
|
949
|
+
height: 16,
|
|
950
|
+
viewBox: "0 0 16 16",
|
|
951
|
+
fill: "none",
|
|
952
|
+
"aria-hidden": true
|
|
953
|
+
};
|
|
954
|
+
return mode === "list" ? (0, react.createElement)("svg", common, (0, react.createElement)("path", { d: "M3 4h10M3 8h10M3 12h10" })) : (0, react.createElement)("svg", common, (0, react.createElement)("rect", {
|
|
955
|
+
x: 2.5,
|
|
956
|
+
y: 2.5,
|
|
957
|
+
width: 4,
|
|
958
|
+
height: 4,
|
|
959
|
+
rx: .8
|
|
960
|
+
}), (0, react.createElement)("rect", {
|
|
961
|
+
x: 9.5,
|
|
962
|
+
y: 2.5,
|
|
963
|
+
width: 4,
|
|
964
|
+
height: 4,
|
|
965
|
+
rx: .8
|
|
966
|
+
}), (0, react.createElement)("rect", {
|
|
967
|
+
x: 2.5,
|
|
968
|
+
y: 9.5,
|
|
969
|
+
width: 4,
|
|
970
|
+
height: 4,
|
|
971
|
+
rx: .8
|
|
972
|
+
}), (0, react.createElement)("rect", {
|
|
973
|
+
x: 9.5,
|
|
974
|
+
y: 9.5,
|
|
975
|
+
width: 4,
|
|
976
|
+
height: 4,
|
|
977
|
+
rx: .8
|
|
978
|
+
}));
|
|
979
|
+
}
|
|
980
|
+
//#endregion
|
|
509
981
|
//#region src/client/MarketSection.tsx
|
|
510
982
|
/**
|
|
511
983
|
* The Agent Plugins Market settings section.
|
|
@@ -520,73 +992,17 @@ const PROGRESS_STEP_LABELS = {
|
|
|
520
992
|
cloning: "progressCloning",
|
|
521
993
|
reading: "progressReading"
|
|
522
994
|
};
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
*/
|
|
527
|
-
function startProgressPolling(report) {
|
|
528
|
-
let stopped = false;
|
|
529
|
-
const tick = async () => {
|
|
530
|
-
if (stopped) return;
|
|
531
|
-
try {
|
|
532
|
-
const progress = await fetchSourceProgress();
|
|
533
|
-
if (!stopped && progress.active) report({
|
|
534
|
-
step: progressStepLabel(progress.step),
|
|
535
|
-
error: void 0
|
|
536
|
-
});
|
|
537
|
-
} catch {}
|
|
538
|
-
if (!stopped) timer = setTimeout(tick, 800);
|
|
539
|
-
};
|
|
540
|
-
let timer = setTimeout(tick, 400);
|
|
541
|
-
return { stop: () => {
|
|
542
|
-
stopped = true;
|
|
543
|
-
clearTimeout(timer);
|
|
544
|
-
} };
|
|
995
|
+
function progressStepLabel(t, step) {
|
|
996
|
+
const key = PROGRESS_STEP_LABELS[step];
|
|
997
|
+
return key === void 0 ? step : t(key);
|
|
545
998
|
}
|
|
546
|
-
|
|
547
|
-
|
|
999
|
+
/** Keep parameterized copy compatible with hosts whose bound translator ignores params. */
|
|
1000
|
+
function interpolate(text, params) {
|
|
1001
|
+
return text.replace(/\{(\w+)\}/g, (match, key) => key in params ? String(params[key]) : match);
|
|
548
1002
|
}
|
|
549
|
-
|
|
550
|
-
sources: [],
|
|
551
|
-
suites: [],
|
|
552
|
-
totals: {
|
|
553
|
-
all: 0,
|
|
554
|
-
installed: 0,
|
|
555
|
-
enabled: 0
|
|
556
|
-
},
|
|
557
|
-
roots: {
|
|
558
|
-
user: "",
|
|
559
|
-
data: ""
|
|
560
|
-
}
|
|
561
|
-
};
|
|
562
|
-
/**
|
|
563
|
-
* Session-level overview cache: the first mount paints the last snapshot
|
|
564
|
-
* instantly (no empty-state flash on reopen), then revalidates in the
|
|
565
|
-
* background. Every refresh overwrites the cached copy.
|
|
566
|
-
*/
|
|
567
|
-
let cachedOverview;
|
|
568
|
-
let inflightOverview;
|
|
569
|
-
function loadOverview() {
|
|
570
|
-
const initial = cachedOverview ?? EMPTY_OVERVIEW;
|
|
571
|
-
if (inflightOverview === void 0) inflightOverview = fetchOverview().then((data) => {
|
|
572
|
-
cachedOverview = data;
|
|
573
|
-
return data;
|
|
574
|
-
}).finally(() => {
|
|
575
|
-
inflightOverview = void 0;
|
|
576
|
-
});
|
|
577
|
-
return {
|
|
578
|
-
initial,
|
|
579
|
-
revalidating: cachedOverview === void 0,
|
|
580
|
-
promise: inflightOverview
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
/** Invalidate the cached overview after any mutating action. */
|
|
584
|
-
function dropCachedOverview() {
|
|
585
|
-
cachedOverview = void 0;
|
|
586
|
-
}
|
|
587
|
-
function MarketSection({ t }) {
|
|
1003
|
+
function MarketSection({ t, mode = "settings" }) {
|
|
588
1004
|
const [overview, setOverview] = (0, react.useState)(() => loadOverview().initial);
|
|
589
|
-
const [loading, setLoading] = (0, react.useState)(() =>
|
|
1005
|
+
const [loading, setLoading] = (0, react.useState)(() => loadOverview().revalidating);
|
|
590
1006
|
const [search, setSearch] = (0, react.useState)("");
|
|
591
1007
|
const [tab, setTab] = (0, react.useState)("all");
|
|
592
1008
|
const [category, setCategory] = (0, react.useState)("all");
|
|
@@ -601,7 +1017,7 @@ function MarketSection({ t }) {
|
|
|
601
1017
|
error: void 0
|
|
602
1018
|
});
|
|
603
1019
|
const refresh = (0, react.useCallback)(async () => {
|
|
604
|
-
|
|
1020
|
+
invalidateOverview();
|
|
605
1021
|
try {
|
|
606
1022
|
const data = await loadOverview().promise;
|
|
607
1023
|
setOverview(data);
|
|
@@ -621,7 +1037,7 @@ function MarketSection({ t }) {
|
|
|
621
1037
|
setBusy(key);
|
|
622
1038
|
try {
|
|
623
1039
|
await postAction(path, body);
|
|
624
|
-
|
|
1040
|
+
invalidateOverview();
|
|
625
1041
|
await refresh();
|
|
626
1042
|
return true;
|
|
627
1043
|
} catch (error) {
|
|
@@ -634,25 +1050,7 @@ function MarketSection({ t }) {
|
|
|
634
1050
|
setBusy(void 0);
|
|
635
1051
|
}
|
|
636
1052
|
}, [refresh, t]);
|
|
637
|
-
const scopeTotals = (0, react.useMemo)(() =>
|
|
638
|
-
if (category === "all") return overview.totals;
|
|
639
|
-
const scoped = overview.suites.filter((suite) => suite.sourceId === category);
|
|
640
|
-
return {
|
|
641
|
-
all: scoped.length,
|
|
642
|
-
installed: scoped.filter((suite) => suite.installed).length,
|
|
643
|
-
enabled: scoped.filter((suite) => suite.enabled).length
|
|
644
|
-
};
|
|
645
|
-
}, [overview, category]);
|
|
646
|
-
const filtered = (0, react.useMemo)(() => {
|
|
647
|
-
const needle = search.trim().toLowerCase();
|
|
648
|
-
return overview.suites.filter((suite) => {
|
|
649
|
-
if (category !== "all" && suite.sourceId !== category) return false;
|
|
650
|
-
if (tab === "installed" && !suite.installed) return false;
|
|
651
|
-
if (tab === "uninstalled" && suite.installed) return false;
|
|
652
|
-
if (needle === "") return true;
|
|
653
|
-
return `${suite.name} ${suite.description ?? ""} ${suite.keywords.join(" ")}`.toLowerCase().includes(needle);
|
|
654
|
-
});
|
|
655
|
-
}, [
|
|
1053
|
+
const { scopeTotals, filtered } = (0, react.useMemo)(() => deriveMarketViewModel(overview, search, tab, category), [
|
|
656
1054
|
overview,
|
|
657
1055
|
search,
|
|
658
1056
|
tab,
|
|
@@ -684,7 +1082,7 @@ function MarketSection({ t }) {
|
|
|
684
1082
|
const selectedSource = category === "all" ? void 0 : overview.sources.find((source) => source.id === category);
|
|
685
1083
|
return (0, react.createElement)(ErrorBoundary, {
|
|
686
1084
|
fallback: (error) => (0, react.createElement)("div", { className: market_module_default.empty }, `${t("actionFail")}: ${error.message}`),
|
|
687
|
-
children: (0, react.createElement)("div", { className: market_module_default.market
|
|
1085
|
+
children: (0, react.createElement)("div", { className: mode === "page" ? `${market_module_default.market} ${market_module_default.pageMode}` : 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)("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, {
|
|
688
1086
|
variant: "ghost",
|
|
689
1087
|
size: "sm",
|
|
690
1088
|
title: t("addSource"),
|
|
@@ -696,12 +1094,7 @@ function MarketSection({ t }) {
|
|
|
696
1094
|
onClick: () => {
|
|
697
1095
|
action("s:refresh:all", "sources/refresh", {});
|
|
698
1096
|
}
|
|
699
|
-
}, "↻"), (0, react.createElement)("div", { className: market_module_default.
|
|
700
|
-
className: market_module_default.searchInput,
|
|
701
|
-
placeholder: t("searchPh"),
|
|
702
|
-
value: search,
|
|
703
|
-
onChange: (event) => setSearch(event.target.value)
|
|
704
|
-
})))), (0, react.createElement)("div", { className: market_module_default.sourceTabsRow }, (0, react.createElement)("div", { className: market_module_default.sourceTabsScroll }, (0, react.createElement)(SourceTab, {
|
|
1097
|
+
}, "↻"))), (0, react.createElement)("div", { className: market_module_default.marketControls }, (0, react.createElement)("div", { className: market_module_default.sourceTabsRow }, (0, react.createElement)("div", { className: market_module_default.sourceTabsScroll }, (0, react.createElement)(SourceTab, {
|
|
705
1098
|
key: "__all__",
|
|
706
1099
|
t,
|
|
707
1100
|
active: category === "all",
|
|
@@ -721,26 +1114,42 @@ function MarketSection({ t }) {
|
|
|
721
1114
|
mode: "edit",
|
|
722
1115
|
source
|
|
723
1116
|
}) : void 0
|
|
724
|
-
})))), (0, react.createElement)(
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
1117
|
+
})))), (0, react.createElement)(SearchFilterToolbar, {
|
|
1118
|
+
search,
|
|
1119
|
+
searchLabel: t("searchPh"),
|
|
1120
|
+
searchPlaceholder: t("searchPh"),
|
|
1121
|
+
onSearchChange: setSearch,
|
|
1122
|
+
filters: [
|
|
1123
|
+
{
|
|
1124
|
+
id: "all",
|
|
1125
|
+
label: t("tabAll"),
|
|
1126
|
+
count: scopeTotals.all,
|
|
1127
|
+
icon: (0, react.createElement)(StatusIcon, { kind: "all" }),
|
|
1128
|
+
active: tab === "all",
|
|
1129
|
+
onSelect: () => setTab("all")
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
id: "installed",
|
|
1133
|
+
label: t("tabInstalled"),
|
|
1134
|
+
count: scopeTotals.installed,
|
|
1135
|
+
icon: (0, react.createElement)(StatusIcon, { kind: "installed" }),
|
|
1136
|
+
active: tab === "installed",
|
|
1137
|
+
onSelect: () => setTab("installed")
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
id: "uninstalled",
|
|
1141
|
+
label: t("tabUninstalled"),
|
|
1142
|
+
count: scopeTotals.all - scopeTotals.installed,
|
|
1143
|
+
icon: (0, react.createElement)(StatusIcon, { kind: "uninstalled" }),
|
|
1144
|
+
active: tab === "uninstalled",
|
|
1145
|
+
onSelect: () => setTab("uninstalled")
|
|
1146
|
+
}
|
|
1147
|
+
],
|
|
1148
|
+
view,
|
|
1149
|
+
gridLabel: t("grid"),
|
|
1150
|
+
listLabel: t("list"),
|
|
1151
|
+
onViewChange: (nextView) => setView(nextView)
|
|
1152
|
+
}))), (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 }, t("loading")) : 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, {
|
|
744
1153
|
key: `${suite.sourceId}/${suite.suiteId}`,
|
|
745
1154
|
t,
|
|
746
1155
|
suite,
|
|
@@ -776,7 +1185,7 @@ function MarketSection({ t }) {
|
|
|
776
1185
|
}), confirm === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
777
1186
|
open: true,
|
|
778
1187
|
onClose: () => setConfirm(void 0),
|
|
779
|
-
title: confirm.kind === "uninstall" ? t("uninstallConfirmTitle") :
|
|
1188
|
+
title: confirm.kind === "uninstall" ? t("uninstallConfirmTitle") : interpolate(t("removeSourceConfirmTitle", { sourceId: confirm.sourceId }), { sourceId: confirm.sourceId }),
|
|
780
1189
|
closeLabel: t("cancel"),
|
|
781
1190
|
description: confirm.kind === "uninstall" ? t("uninstallConfirmDesc") : t("removeSourceConfirmDesc"),
|
|
782
1191
|
footer: (0, react.createElement)("div", { className: market_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
@@ -812,10 +1221,10 @@ function MarketSection({ t }) {
|
|
|
812
1221
|
step: t("progressStarting"),
|
|
813
1222
|
error: void 0
|
|
814
1223
|
});
|
|
815
|
-
const poll =
|
|
1224
|
+
const poll = startSourceProgressPolling(setProgress, (step) => progressStepLabel(t, step));
|
|
816
1225
|
try {
|
|
817
1226
|
const derived = (await postAction("sources/add", body))["source"]?.id;
|
|
818
|
-
|
|
1227
|
+
invalidateOverview();
|
|
819
1228
|
await refresh();
|
|
820
1229
|
setEditor(void 0);
|
|
821
1230
|
if (derived !== void 0) setCategory(derived);
|
|
@@ -852,165 +1261,483 @@ function MarketSection({ t }) {
|
|
|
852
1261
|
}))
|
|
853
1262
|
});
|
|
854
1263
|
}
|
|
855
|
-
|
|
1264
|
+
//#endregion
|
|
1265
|
+
//#region src/client/features/mcp-status/mcp-status-view-model.ts
|
|
1266
|
+
const searchableCache = /* @__PURE__ */ new WeakMap();
|
|
1267
|
+
/** Derive active rows, filter counts, and visible rows in one pass. */
|
|
1268
|
+
function deriveMcpStatusViewModel(payload, filter, search) {
|
|
1269
|
+
const searchable = searchableFor(payload);
|
|
1270
|
+
const activeEntries = searchable.map((item) => item.entry);
|
|
1271
|
+
const filterCounts = {
|
|
1272
|
+
all: 0,
|
|
1273
|
+
plugin: 0,
|
|
1274
|
+
direct: 0
|
|
1275
|
+
};
|
|
1276
|
+
let connected = 0;
|
|
1277
|
+
let failed = 0;
|
|
1278
|
+
const filtered = [];
|
|
1279
|
+
const needle = search.trim().toLowerCase();
|
|
1280
|
+
for (const item of searchable) {
|
|
1281
|
+
const entry = item.entry;
|
|
1282
|
+
filterCounts.all++;
|
|
1283
|
+
filterCounts[entry.kind]++;
|
|
1284
|
+
if (entry.state === "connected") connected++;
|
|
1285
|
+
if (entry.state === "failed") failed++;
|
|
1286
|
+
if (filter !== "all" && entry.kind !== filter) continue;
|
|
1287
|
+
if (needle !== "" && !item.haystack.includes(needle)) continue;
|
|
1288
|
+
filtered.push(entry);
|
|
1289
|
+
}
|
|
1290
|
+
return {
|
|
1291
|
+
activeEntries,
|
|
1292
|
+
filtered,
|
|
1293
|
+
filterCounts,
|
|
1294
|
+
visibleTotals: {
|
|
1295
|
+
all: activeEntries.length,
|
|
1296
|
+
connected,
|
|
1297
|
+
failed
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
function searchableFor(payload) {
|
|
1302
|
+
const cached = searchableCache.get(payload);
|
|
1303
|
+
if (cached !== void 0) return cached;
|
|
1304
|
+
const searchable = payload.entries.filter((entry) => entry.state !== "disabled").map((entry) => ({
|
|
1305
|
+
entry,
|
|
1306
|
+
haystack: `${entry.name} ${entry.source ?? ""} ${entry.endpoint ?? ""} ${entry.transport}`.toLowerCase()
|
|
1307
|
+
}));
|
|
1308
|
+
searchableCache.set(payload, searchable);
|
|
1309
|
+
return searchable;
|
|
1310
|
+
}
|
|
1311
|
+
//#endregion
|
|
1312
|
+
//#region src/client/mcp-status.module.css
|
|
1313
|
+
var mcp_status_module_default = {
|
|
1314
|
+
"boundary": "AUWlZW_boundary",
|
|
1315
|
+
"card": "AUWlZW_card",
|
|
1316
|
+
"cardReason": "AUWlZW_cardReason",
|
|
1317
|
+
"cardTop": "AUWlZW_cardTop",
|
|
1318
|
+
"chevron": "AUWlZW_chevron",
|
|
1319
|
+
"config": "AUWlZW_config",
|
|
1320
|
+
"detail": "AUWlZW_detail",
|
|
1321
|
+
"detailBody": "AUWlZW_detailBody",
|
|
1322
|
+
"detailDialog": "AUWlZW_detailDialog",
|
|
1323
|
+
"detailEmpty": "AUWlZW_detailEmpty",
|
|
1324
|
+
"detailHead": "AUWlZW_detailHead",
|
|
1325
|
+
"detailMeta": "AUWlZW_detailMeta",
|
|
1326
|
+
"detailSection": "AUWlZW_detailSection",
|
|
1327
|
+
"detailState": "AUWlZW_detailState",
|
|
1328
|
+
"detailStateconnected": "AUWlZW_detailStateconnected",
|
|
1329
|
+
"detailStatedegraded": "AUWlZW_detailStatedegraded",
|
|
1330
|
+
"detailStatedisabled": "AUWlZW_detailStatedisabled",
|
|
1331
|
+
"detailStatefailed": "AUWlZW_detailStatefailed",
|
|
1332
|
+
"empty": "AUWlZW_empty",
|
|
1333
|
+
"endpoint": "AUWlZW_endpoint",
|
|
1334
|
+
"error": "AUWlZW_error",
|
|
1335
|
+
"errorSummary": "AUWlZW_errorSummary",
|
|
1336
|
+
"grid": "AUWlZW_grid",
|
|
1337
|
+
"header": "AUWlZW_header",
|
|
1338
|
+
"headerActions": "AUWlZW_headerActions",
|
|
1339
|
+
"list": "AUWlZW_list",
|
|
1340
|
+
"meta": "AUWlZW_meta",
|
|
1341
|
+
"modalFooter": "AUWlZW_modalFooter",
|
|
1342
|
+
"name": "AUWlZW_name",
|
|
1343
|
+
"reason": "AUWlZW_reason",
|
|
1344
|
+
"service": "AUWlZW_service",
|
|
1345
|
+
"sourceDirect": "AUWlZW_sourceDirect",
|
|
1346
|
+
"sourcePlugin": "AUWlZW_sourcePlugin",
|
|
1347
|
+
"state": "AUWlZW_state",
|
|
1348
|
+
"stateconnected": "AUWlZW_stateconnected",
|
|
1349
|
+
"statedegraded": "AUWlZW_statedegraded",
|
|
1350
|
+
"statedisabled": "AUWlZW_statedisabled",
|
|
1351
|
+
"statefailed": "AUWlZW_statefailed",
|
|
1352
|
+
"statusconnected": "AUWlZW_statusconnected",
|
|
1353
|
+
"statusdegraded": "AUWlZW_statusdegraded",
|
|
1354
|
+
"statusdisabled": "AUWlZW_statusdisabled",
|
|
1355
|
+
"statusDot": "AUWlZW_statusDot",
|
|
1356
|
+
"statusfailed": "AUWlZW_statusfailed",
|
|
1357
|
+
"subtitle": "AUWlZW_subtitle",
|
|
1358
|
+
"summary": "AUWlZW_summary",
|
|
1359
|
+
"summaryDotGreen": "AUWlZW_summaryDotGreen",
|
|
1360
|
+
"summaryDotRed": "AUWlZW_summaryDotRed",
|
|
1361
|
+
"surface": "AUWlZW_surface",
|
|
1362
|
+
"title": "AUWlZW_title",
|
|
1363
|
+
"tool": "AUWlZW_tool",
|
|
1364
|
+
"toolbar": "AUWlZW_toolbar",
|
|
1365
|
+
"toolCount": "AUWlZW_toolCount",
|
|
1366
|
+
"toolDescription": "AUWlZW_toolDescription",
|
|
1367
|
+
"toolIndex": "AUWlZW_toolIndex",
|
|
1368
|
+
"toolList": "AUWlZW_toolList",
|
|
1369
|
+
"toolName": "AUWlZW_toolName",
|
|
1370
|
+
"transport": "AUWlZW_transport"
|
|
1371
|
+
};
|
|
1372
|
+
//#endregion
|
|
1373
|
+
//#region src/client/McpStatusPanel.tsx
|
|
1374
|
+
const EMPTY_STATUS = {
|
|
1375
|
+
entries: [],
|
|
1376
|
+
observedAt: "",
|
|
1377
|
+
totals: {
|
|
1378
|
+
all: 0,
|
|
1379
|
+
connected: 0,
|
|
1380
|
+
degraded: 0,
|
|
1381
|
+
failed: 0,
|
|
1382
|
+
disabled: 0
|
|
1383
|
+
},
|
|
1384
|
+
directObservationOnly: true
|
|
1385
|
+
};
|
|
1386
|
+
/** DSH-native MCP inventory: click a service card for a standard Modal detail. */
|
|
1387
|
+
function McpStatusPanel({ t }) {
|
|
1388
|
+
const [payload, setPayload] = (0, react.useState)(EMPTY_STATUS);
|
|
1389
|
+
const [loading, setLoading] = (0, react.useState)(true);
|
|
1390
|
+
const [error, setError] = (0, react.useState)(void 0);
|
|
1391
|
+
const [filter, setFilter] = (0, react.useState)("all");
|
|
1392
|
+
const [search, setSearch] = (0, react.useState)("");
|
|
1393
|
+
const [view, setView] = (0, react.useState)("grid");
|
|
1394
|
+
const [selected, setSelected] = (0, react.useState)(void 0);
|
|
1395
|
+
const refresh = () => {
|
|
1396
|
+
setLoading(true);
|
|
1397
|
+
setError(void 0);
|
|
1398
|
+
fetchMcpStatus().then(setPayload).catch((caught) => {
|
|
1399
|
+
setError(caught instanceof Error ? caught.message : String(caught));
|
|
1400
|
+
}).finally(() => setLoading(false));
|
|
1401
|
+
};
|
|
1402
|
+
(0, react.useEffect)(() => {
|
|
1403
|
+
refresh();
|
|
1404
|
+
}, []);
|
|
1405
|
+
const { activeEntries, filtered, filterCounts, visibleTotals } = deriveMcpStatusViewModel(payload, filter, search);
|
|
1406
|
+
return (0, react.createElement)("div", { className: mcp_status_module_default.surface }, (0, react.createElement)("header", { className: mcp_status_module_default.header }, (0, react.createElement)("div", {}, (0, react.createElement)("h2", { className: mcp_status_module_default.title }, t("mcpStatusTitle"))), (0, react.createElement)("div", { className: mcp_status_module_default.headerActions }, visibleTotals.failed > 0 ? (0, react.createElement)("span", {
|
|
1407
|
+
className: mcp_status_module_default.errorSummary,
|
|
1408
|
+
title: `${visibleTotals.failed} ${t("mcpFailed")}`
|
|
1409
|
+
}, (0, react.createElement)("span", { className: mcp_status_module_default.summaryDotRed }), visibleTotals.failed) : null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1410
|
+
variant: "ghost",
|
|
1411
|
+
size: "sm",
|
|
1412
|
+
onClick: refresh,
|
|
1413
|
+
disabled: loading,
|
|
1414
|
+
title: t("refresh")
|
|
1415
|
+
}, "↻"))), (0, react.createElement)(SearchFilterToolbar, {
|
|
1416
|
+
className: mcp_status_module_default.toolbar,
|
|
1417
|
+
search,
|
|
1418
|
+
searchLabel: t("mcpSearch"),
|
|
1419
|
+
searchPlaceholder: t("mcpSearch"),
|
|
1420
|
+
onSearchChange: setSearch,
|
|
1421
|
+
filters: [
|
|
1422
|
+
"all",
|
|
1423
|
+
"plugin",
|
|
1424
|
+
"direct"
|
|
1425
|
+
].map((kind) => ({
|
|
1426
|
+
id: kind,
|
|
1427
|
+
label: filterLabel(t, kind),
|
|
1428
|
+
count: filterCounts[kind],
|
|
1429
|
+
icon: (0, react.createElement)(McpFilterIcon, { kind }),
|
|
1430
|
+
active: filter === kind,
|
|
1431
|
+
onSelect: () => setFilter(kind)
|
|
1432
|
+
})),
|
|
1433
|
+
view,
|
|
1434
|
+
gridLabel: t("grid"),
|
|
1435
|
+
listLabel: t("list"),
|
|
1436
|
+
onViewChange: (nextView) => setView(nextView)
|
|
1437
|
+
}), error !== void 0 ? (0, react.createElement)("div", { className: mcp_status_module_default.error }, error, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1438
|
+
variant: "ghost",
|
|
1439
|
+
size: "sm",
|
|
1440
|
+
onClick: refresh
|
|
1441
|
+
}, t("mcpRetry"))) : loading && activeEntries.length === 0 ? (0, react.createElement)("div", { className: mcp_status_module_default.empty }, t("loading")) : filtered.length === 0 ? (0, react.createElement)("div", { className: mcp_status_module_default.empty }, t("mcpEmpty")) : (0, react.createElement)("div", { className: view === "grid" ? mcp_status_module_default.grid : mcp_status_module_default.list }, filtered.map((entry) => (0, react.createElement)(McpCard, {
|
|
1442
|
+
key: entry.id,
|
|
1443
|
+
entry,
|
|
1444
|
+
t,
|
|
1445
|
+
onClick: () => setSelected(entry)
|
|
1446
|
+
}))), selected === void 0 ? null : (0, react.createElement)(McpDetailModal, {
|
|
1447
|
+
entry: selected,
|
|
1448
|
+
t,
|
|
1449
|
+
onClose: () => setSelected(void 0)
|
|
1450
|
+
}));
|
|
1451
|
+
}
|
|
1452
|
+
function McpCard({ entry, t, onClick }) {
|
|
856
1453
|
return (0, react.createElement)("button", {
|
|
857
1454
|
type: "button",
|
|
858
|
-
className:
|
|
1455
|
+
className: mcp_status_module_default.card,
|
|
859
1456
|
onClick
|
|
860
|
-
},
|
|
1457
|
+
}, (0, react.createElement)("div", { className: mcp_status_module_default.cardTop }, (0, react.createElement)("span", {
|
|
1458
|
+
className: `${mcp_status_module_default.statusDot} ${mcp_status_module_default[`status${entry.state}`]}`,
|
|
1459
|
+
title: stateLabel(t, entry.state),
|
|
1460
|
+
"aria-label": stateLabel(t, entry.state)
|
|
1461
|
+
}), (0, react.createElement)("span", { className: mcp_status_module_default.service }, (0, react.createElement)("span", { className: mcp_status_module_default.name }, entry.name)), (0, react.createElement)("span", { className: mcp_status_module_default.toolCount }, `${t("mcpTools")} ${entry.tools.length}`)), (0, react.createElement)("p", { className: mcp_status_module_default.endpoint }, entry.endpoint ?? t("mcpObservedEndpoint")), (0, react.createElement)("div", { className: mcp_status_module_default.meta }, (0, react.createElement)(McpSourceBadge, {
|
|
1462
|
+
kind: entry.kind,
|
|
1463
|
+
label: entry.kind === "plugin" ? entry.source ?? "—" : t("mcpDirect"),
|
|
1464
|
+
t
|
|
1465
|
+
}), (0, react.createElement)("span", { className: mcp_status_module_default.transport }, entry.transport)), entry.reason === void 0 ? null : (0, react.createElement)("p", { className: mcp_status_module_default.cardReason }, entry.reason));
|
|
861
1466
|
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
const { t, active = false, label, onSelect, onDelete, onEdit } = props;
|
|
865
|
-
return (0, react.createElement)("div", { className: active ? market_module_default.srcTabOn : market_module_default.srcTab }, (0, react.createElement)("button", {
|
|
866
|
-
type: "button",
|
|
867
|
-
className: market_module_default.srcTabMain,
|
|
868
|
-
onClick: onSelect
|
|
869
|
-
}, label), onEdit === void 0 ? null : (0, react.createElement)("button", {
|
|
870
|
-
type: "button",
|
|
871
|
-
className: market_module_default.srcTabEdit,
|
|
872
|
-
title: t("editSource"),
|
|
873
|
-
onClick: (event) => {
|
|
874
|
-
event.stopPropagation();
|
|
875
|
-
onEdit();
|
|
876
|
-
}
|
|
877
|
-
}, "✎"), onDelete === void 0 ? null : (0, react.createElement)("button", {
|
|
878
|
-
type: "button",
|
|
879
|
-
className: market_module_default.srcTabDel,
|
|
880
|
-
title: t("remove"),
|
|
881
|
-
onClick: (event) => {
|
|
882
|
-
event.stopPropagation();
|
|
883
|
-
onDelete();
|
|
884
|
-
}
|
|
885
|
-
}, "×"));
|
|
1467
|
+
function McpSourceBadge({ kind, label, t }) {
|
|
1468
|
+
return (0, react.createElement)("span", { className: kind === "plugin" ? mcp_status_module_default.sourcePlugin : mcp_status_module_default.sourceDirect }, (0, react.createElement)(McpSourceIcon, { kind }), (0, react.createElement)("span", {}, kind === "plugin" ? label : t("mcpDirect")));
|
|
886
1469
|
}
|
|
887
|
-
function
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1470
|
+
function McpSourceIcon({ kind }) {
|
|
1471
|
+
const common = {
|
|
1472
|
+
width: 16,
|
|
1473
|
+
height: 16,
|
|
1474
|
+
viewBox: "0 0 16 16",
|
|
1475
|
+
fill: "none",
|
|
1476
|
+
"aria-hidden": true
|
|
1477
|
+
};
|
|
1478
|
+
return kind === "plugin" ? (0, react.createElement)("svg", common, (0, react.createElement)("path", { d: "M6 2.5v2H4A1.5 1.5 0 0 0 2.5 6v2h2a1.5 1.5 0 1 1 0 3h-2v2A1.5 1.5 0 0 0 4 14.5h2v-2a1.5 1.5 0 1 1 3 0v2h2a1.5 1.5 0 0 0 1.5-1.5v-2h-2a1.5 1.5 0 1 1 0-3h2V6A1.5 1.5 0 0 0 11 4.5H9v-2a1.5 1.5 0 1 0-3 0Z" })) : (0, react.createElement)("svg", common, (0, react.createElement)("circle", {
|
|
1479
|
+
cx: 8,
|
|
1480
|
+
cy: 5,
|
|
1481
|
+
r: 2.2
|
|
1482
|
+
}), (0, react.createElement)("path", { d: "M3.5 13c.6-2.2 2.1-3.3 4.5-3.3s3.9 1.1 4.5 3.3" }));
|
|
1483
|
+
}
|
|
1484
|
+
function McpFilterIcon({ kind }) {
|
|
1485
|
+
if (kind === "plugin") return (0, react.createElement)(McpSourceIcon, { kind: "plugin" });
|
|
1486
|
+
if (kind === "direct") return (0, react.createElement)(McpSourceIcon, { kind: "direct" });
|
|
1487
|
+
return (0, react.createElement)("svg", {
|
|
1488
|
+
width: 16,
|
|
1489
|
+
height: 16,
|
|
1490
|
+
viewBox: "0 0 16 16",
|
|
1491
|
+
fill: "none",
|
|
1492
|
+
"aria-hidden": true
|
|
1493
|
+
}, (0, react.createElement)("path", { d: "M2.5 5 8 2.5 13.5 5 8 7.5 2.5 5Zm0 3L8 10.5 13.5 8M2.5 11 8 13.5 13.5 11" }));
|
|
1494
|
+
}
|
|
1495
|
+
function McpDetailModal({ entry, t, onClose }) {
|
|
894
1496
|
return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
895
1497
|
open: true,
|
|
896
|
-
onClose
|
|
897
|
-
title,
|
|
898
|
-
description: t("
|
|
1498
|
+
onClose,
|
|
1499
|
+
title: entry.name,
|
|
1500
|
+
description: t("mcpServiceDetail"),
|
|
899
1501
|
closeLabel: t("cancel"),
|
|
900
|
-
className:
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
onClick: () => props.onRemove(id)
|
|
904
|
-
}, `🗑 ${t("remove")}`) : null), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1502
|
+
className: mcp_status_module_default.detailDialog,
|
|
1503
|
+
contentClassName: mcp_status_module_default.detailBody,
|
|
1504
|
+
footer: (0, react.createElement)("div", { className: mcp_status_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
905
1505
|
variant: "ghost",
|
|
906
|
-
onClick:
|
|
907
|
-
}, t("cancel"))
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
className: local ? market_module_default.seg : market_module_default.segOn,
|
|
917
|
-
onClick: () => setLocal(false)
|
|
918
|
-
}, t("sourceModeGit")), (0, react.createElement)("button", {
|
|
919
|
-
type: "button",
|
|
920
|
-
className: local ? market_module_default.segOn : market_module_default.seg,
|
|
921
|
-
onClick: () => setLocal(true)
|
|
922
|
-
}, 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, {
|
|
923
|
-
placeholder: local ? t("sourceUrlLocalPh") : t("sourceUrlPh"),
|
|
924
|
-
value: url,
|
|
925
|
-
onChange: (event) => setUrl(event.target.value)
|
|
926
|
-
}), (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, {
|
|
927
|
-
placeholder: t("branchPh"),
|
|
928
|
-
value: branch,
|
|
929
|
-
onChange: (event) => setBranch(event.target.value)
|
|
930
|
-
}), (0, react.createElement)("span", { className: market_module_default.fieldHint }, t("branchHint"))), props.progress.error === void 0 && props.progress.step === void 0 ? null : (0, react.createElement)("div", { className: props.progress.error === void 0 ? market_module_default.progress : market_module_default.progressError }, props.progress.error === void 0 ? (0, react.createElement)("span", { className: market_module_default.progressSpin }) : (0, react.createElement)("span", { className: market_module_default.progressFail }, "✕"), (0, react.createElement)("span", { className: market_module_default.progressText }, props.progress.error === void 0 ? props.progress.step : `${t("actionFail")}: ${props.progress.error}`)))
|
|
1506
|
+
onClick: onClose
|
|
1507
|
+
}, t("cancel"))),
|
|
1508
|
+
children: (0, react.createElement)("div", { className: mcp_status_module_default.detail }, (0, react.createElement)("div", { className: mcp_status_module_default.detailMeta }, (0, react.createElement)(McpSourceBadge, {
|
|
1509
|
+
kind: entry.kind,
|
|
1510
|
+
label: entry.kind === "plugin" ? entry.source ?? "—" : t("mcpDirect"),
|
|
1511
|
+
t
|
|
1512
|
+
}), (0, react.createElement)("span", { className: mcp_status_module_default.transport }, entry.transport), (0, react.createElement)("span", { className: `${mcp_status_module_default.state} ${mcp_status_module_default[`state${entry.state}`]}` }, stateLabel(t, entry.state))), entry.reason === void 0 ? null : (0, react.createElement)("div", { className: mcp_status_module_default.reason }, entry.reason), (0, react.createElement)("section", { className: mcp_status_module_default.detailSection }, (0, react.createElement)("h4", { className: mcp_status_module_default.detailHead }, t("mcpConfig")), entry.config === void 0 ? (0, react.createElement)("div", { className: mcp_status_module_default.detailEmpty }, t("mcpDirectConfigUnavailable")) : (0, react.createElement)("pre", { className: mcp_status_module_default.config }, JSON.stringify(entry.config, null, 2))), (0, react.createElement)("section", { className: mcp_status_module_default.detailSection }, (0, react.createElement)("h4", { className: mcp_status_module_default.detailHead }, `${t("mcpTools")} (${entry.tools.length})`), entry.tools.length === 0 ? (0, react.createElement)("div", { className: mcp_status_module_default.detailEmpty }, t("mcpNoTools")) : (0, react.createElement)("div", { className: mcp_status_module_default.toolList }, entry.tools.map((tool, index) => (0, react.createElement)("div", {
|
|
1513
|
+
key: tool.name,
|
|
1514
|
+
className: mcp_status_module_default.tool
|
|
1515
|
+
}, (0, react.createElement)("span", { className: mcp_status_module_default.toolIndex }, String(index + 1).padStart(2, "0")), (0, react.createElement)("span", { className: mcp_status_module_default.toolName }, tool.name), (0, react.createElement)("span", { className: mcp_status_module_default.toolDescription }, tool.description ?? ""))))))
|
|
931
1516
|
});
|
|
932
1517
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
role: "switch",
|
|
938
|
-
"aria-checked": props.on,
|
|
939
|
-
title: props.title,
|
|
940
|
-
disabled: props.disabled,
|
|
941
|
-
className: props.on ? market_module_default.switchOn : market_module_default.switchOff,
|
|
942
|
-
onClick: (event) => {
|
|
943
|
-
event.stopPropagation();
|
|
944
|
-
props.onChange();
|
|
945
|
-
}
|
|
946
|
-
}, (0, react.createElement)("span", { className: market_module_default.switchThumb }));
|
|
1518
|
+
function filterLabel(t, kind) {
|
|
1519
|
+
if (kind === "plugin") return t("mcpPlugin");
|
|
1520
|
+
if (kind === "direct") return t("mcpDirect");
|
|
1521
|
+
return t("mcpAll");
|
|
947
1522
|
}
|
|
948
|
-
function
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1523
|
+
function stateLabel(t, state) {
|
|
1524
|
+
if (state === "connected") return t("mcpConnected");
|
|
1525
|
+
if (state === "degraded") return t("mcpDegraded");
|
|
1526
|
+
if (state === "failed") return t("mcpFailed");
|
|
1527
|
+
return t("mcpDisabled");
|
|
1528
|
+
}
|
|
1529
|
+
//#endregion
|
|
1530
|
+
//#region src/client/page-mode-selection.ts
|
|
1531
|
+
/** Pure capability decision for the legacy page-mode fallback. */
|
|
1532
|
+
/**
|
|
1533
|
+
* Use the DOM page fallback only when the host has no settings page and does
|
|
1534
|
+
* expose a page shell for the fallback to mount into.
|
|
1535
|
+
*
|
|
1536
|
+
* @param settingsSurfaceAvailable - whether `settings.section` is live.
|
|
1537
|
+
* @param pageShellAvailable - whether the sidebar/conversation shell exists.
|
|
1538
|
+
* @returns true when the fallback is the only available market surface.
|
|
1539
|
+
*/
|
|
1540
|
+
function shouldUseLegacyPageMode(settingsSurfaceAvailable, pageShellAvailable) {
|
|
1541
|
+
return !settingsSurfaceAvailable && pageShellAvailable;
|
|
1542
|
+
}
|
|
1543
|
+
//#endregion
|
|
1544
|
+
//#region src/client/page-mode.tsx
|
|
1545
|
+
/**
|
|
1546
|
+
* Legacy Web page-mode adapter.
|
|
1547
|
+
*
|
|
1548
|
+
* Current DSH compositions expose `settings.section`; older compositions that
|
|
1549
|
+
* predate that slot can still host a top-level market panel through the DOM
|
|
1550
|
+
* shell used by the original page-mode integration. The adapter is deliberately
|
|
1551
|
+
* guarded by the live settings-slot state so one composition never renders two
|
|
1552
|
+
* market surfaces.
|
|
1553
|
+
*/
|
|
1554
|
+
const ACTIVE_ATTRIBUTE = "data-dsh-agent-plugins-market-page";
|
|
1555
|
+
const VIEW_ATTRIBUTE = "data-dsh-agent-plugins-market-page-view";
|
|
1556
|
+
const ENTRY_ATTRIBUTE = "data-dsh-agent-plugins-market-entry";
|
|
1557
|
+
const SURFACE_EVENT = "dsh-agent-plugins-market-settings-surface";
|
|
1558
|
+
const PANEL_EVENT = "dsh-panel-activate";
|
|
1559
|
+
const PANEL_NAME = "agent-plugins-market";
|
|
1560
|
+
/** Notify the page adapter that the settings-slot capability changed. */
|
|
1561
|
+
const LEGACY_PAGE_MODE_SURFACE_EVENT = SURFACE_EVENT;
|
|
1562
|
+
const SIDEBAR_COLUMN_SELECTOR = "[data-pane=\"sidebar\"], [class*=\"sidebarCol\"]";
|
|
1563
|
+
const CONVERSATION_COLUMN_SELECTOR = "[data-pane=\"conversation\"], [class*=\"centerCol\"]";
|
|
1564
|
+
const SIDEBAR_CONTEXT_SELECTOR = "[class*=\"sessionRow\"], [class*=\"projectRow\"], [class*=\"searchResultRow\"], [class*=\"searchResultWorkspace\"], [class*=\"newSession\"]";
|
|
1565
|
+
/**
|
|
1566
|
+
* Mount the page-mode fallback and its sidebar entry.
|
|
1567
|
+
*
|
|
1568
|
+
* The fallback remains dormant when the settings surface is present. It also
|
|
1569
|
+
* remains a no-op in non-browser runtimes or shells that expose neither the
|
|
1570
|
+
* sidebar nor the conversation column.
|
|
1571
|
+
*
|
|
1572
|
+
* @param options - page-mode dependencies and host capability probe.
|
|
1573
|
+
* @returns disposer that removes the injected entry, panel, listeners, and
|
|
1574
|
+
* active document marker.
|
|
1575
|
+
*/
|
|
1576
|
+
function mountLegacyPageMode(options) {
|
|
1577
|
+
if (typeof document === "undefined" || typeof MutationObserver === "undefined") return () => {};
|
|
1578
|
+
let stopped = false;
|
|
1579
|
+
let open = false;
|
|
1580
|
+
let root;
|
|
1581
|
+
let container;
|
|
1582
|
+
let entry;
|
|
1583
|
+
let entryLabel;
|
|
1584
|
+
let observer;
|
|
1585
|
+
const setActive = (next) => {
|
|
1586
|
+
open = next;
|
|
1587
|
+
if (open && !options.isSettingsSurfaceAvailable()) {
|
|
1588
|
+
document.documentElement.setAttribute(ACTIVE_ATTRIBUTE, "");
|
|
1589
|
+
document.dispatchEvent(new CustomEvent(PANEL_EVENT, { detail: PANEL_NAME }));
|
|
1590
|
+
} else document.documentElement.removeAttribute(ACTIVE_ATTRIBUTE);
|
|
963
1591
|
};
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1592
|
+
const removeView = () => {
|
|
1593
|
+
setActive(false);
|
|
1594
|
+
root?.unmount();
|
|
1595
|
+
root = void 0;
|
|
1596
|
+
container?.remove();
|
|
1597
|
+
container = void 0;
|
|
1598
|
+
};
|
|
1599
|
+
const renderView = () => {
|
|
1600
|
+
if (root === void 0) return;
|
|
1601
|
+
root.render((0, react.createElement)(MarketSection, {
|
|
1602
|
+
t: options.t,
|
|
1603
|
+
mode: "page"
|
|
1604
|
+
}));
|
|
1605
|
+
};
|
|
1606
|
+
const updateEntryCopy = () => {
|
|
1607
|
+
if (entryLabel === void 0 || entry === void 0) return;
|
|
1608
|
+
const label = options.t("nav");
|
|
1609
|
+
entryLabel.textContent = label;
|
|
1610
|
+
entry.title = label;
|
|
1611
|
+
entry.setAttribute("aria-label", label);
|
|
1612
|
+
};
|
|
1613
|
+
const ensureView = () => {
|
|
1614
|
+
if (stopped || options.isSettingsSurfaceAvailable()) {
|
|
1615
|
+
removeView();
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
const column = conversationColumn();
|
|
1619
|
+
if (!shouldUseLegacyPageMode(options.isSettingsSurfaceAvailable(), column !== void 0)) {
|
|
1620
|
+
removeView();
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
if (column === void 0) return;
|
|
1624
|
+
if (container !== void 0 && container.isConnected) return;
|
|
1625
|
+
root?.unmount();
|
|
1626
|
+
container?.remove();
|
|
1627
|
+
container = document.createElement("div");
|
|
1628
|
+
container.setAttribute(VIEW_ATTRIBUTE, "");
|
|
1629
|
+
container.className = market_module_default.pageView;
|
|
1630
|
+
column.appendChild(container);
|
|
1631
|
+
root = (0, react_dom_client.createRoot)(container);
|
|
1632
|
+
renderView();
|
|
1633
|
+
};
|
|
1634
|
+
const ensureEntry = () => {
|
|
1635
|
+
if (stopped || options.isSettingsSurfaceAvailable()) {
|
|
1636
|
+
entry?.remove();
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
const rootElement = sidebarRoot();
|
|
1640
|
+
const anchor = rootElement === void 0 ? void 0 : newSessionButton(rootElement);
|
|
1641
|
+
if (rootElement === void 0 || anchor === void 0 || anchor.parentElement === null) return;
|
|
1642
|
+
if (entry === void 0) {
|
|
1643
|
+
entry = createEntry(() => {
|
|
1644
|
+
setActive(!open);
|
|
1645
|
+
ensureView();
|
|
1646
|
+
});
|
|
1647
|
+
entryLabel = entry.querySelector("[data-dsh-agent-plugins-market-label]") ?? void 0;
|
|
1648
|
+
updateEntryCopy();
|
|
1649
|
+
}
|
|
1650
|
+
if (entry.parentElement !== anchor.parentElement || entry.previousSibling !== anchor) anchor.insertAdjacentElement("afterend", entry);
|
|
1651
|
+
};
|
|
1652
|
+
const observeShell = () => {
|
|
1653
|
+
if (stopped || observer !== void 0 || options.isSettingsSurfaceAvailable()) return;
|
|
1654
|
+
observer = new MutationObserver(ensure);
|
|
1655
|
+
observer.observe(document.body ?? document.documentElement, {
|
|
1656
|
+
childList: true,
|
|
1657
|
+
subtree: true
|
|
1658
|
+
});
|
|
1659
|
+
};
|
|
1660
|
+
const stopObservingShell = () => {
|
|
1661
|
+
observer?.disconnect();
|
|
1662
|
+
observer = void 0;
|
|
1663
|
+
};
|
|
1664
|
+
const ensure = () => {
|
|
1665
|
+
if (stopped) return;
|
|
1666
|
+
if (options.isSettingsSurfaceAvailable()) {
|
|
1667
|
+
stopObservingShell();
|
|
1668
|
+
removeView();
|
|
1669
|
+
entry?.remove();
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
observeShell();
|
|
1673
|
+
ensureView();
|
|
1674
|
+
ensureEntry();
|
|
1675
|
+
};
|
|
1676
|
+
const onLocale = () => {
|
|
1677
|
+
updateEntryCopy();
|
|
1678
|
+
renderView();
|
|
1679
|
+
};
|
|
1680
|
+
const onSurfaceChange = () => {
|
|
1681
|
+
ensure();
|
|
1682
|
+
};
|
|
1683
|
+
const unsubscribeLocale = options.subscribeLocale?.(onLocale);
|
|
1684
|
+
const onPanelActivate = (event) => {
|
|
1685
|
+
if (event.detail !== PANEL_NAME && open) setActive(false);
|
|
1686
|
+
};
|
|
1687
|
+
const onSidebarContextClick = (event) => {
|
|
1688
|
+
if (!open) return;
|
|
1689
|
+
const target = event.target;
|
|
1690
|
+
if (!(target instanceof HTMLElement) || target.closest(SIDEBAR_CONTEXT_SELECTOR) === null) return;
|
|
1691
|
+
setActive(false);
|
|
1692
|
+
};
|
|
1693
|
+
document.addEventListener(PANEL_EVENT, onPanelActivate);
|
|
1694
|
+
document.addEventListener(SURFACE_EVENT, onSurfaceChange);
|
|
1695
|
+
document.addEventListener("click", onSidebarContextClick, true);
|
|
1696
|
+
queueMicrotask(ensure);
|
|
1697
|
+
return () => {
|
|
1698
|
+
stopped = true;
|
|
1699
|
+
unsubscribeLocale?.();
|
|
1700
|
+
document.removeEventListener(PANEL_EVENT, onPanelActivate);
|
|
1701
|
+
document.removeEventListener(SURFACE_EVENT, onSurfaceChange);
|
|
1702
|
+
document.removeEventListener("click", onSidebarContextClick, true);
|
|
1703
|
+
stopObservingShell();
|
|
1704
|
+
entry?.remove();
|
|
1705
|
+
removeView();
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
function sidebarRoot() {
|
|
1709
|
+
const column = document.querySelector(SIDEBAR_COLUMN_SELECTOR);
|
|
1710
|
+
if (column === null) return void 0;
|
|
1711
|
+
return column.querySelector("[class*=\"logoRow\"]")?.parentElement ?? column.firstElementChild ?? void 0;
|
|
1712
|
+
}
|
|
1713
|
+
function newSessionButton(root) {
|
|
1714
|
+
const nested = root.querySelector("button[class*=\"newSession\"]");
|
|
1715
|
+
if (nested !== null) return nested;
|
|
1716
|
+
for (const child of root.children) if (child instanceof HTMLButtonElement) return child;
|
|
1717
|
+
}
|
|
1718
|
+
function conversationColumn() {
|
|
1719
|
+
return document.querySelector(CONVERSATION_COLUMN_SELECTOR) ?? void 0;
|
|
1720
|
+
}
|
|
1721
|
+
function createEntry(onClick) {
|
|
1722
|
+
const button = document.createElement("button");
|
|
1723
|
+
button.type = "button";
|
|
1724
|
+
button.setAttribute(ENTRY_ATTRIBUTE, "");
|
|
1725
|
+
button.className = market_module_default.pageEntry;
|
|
1726
|
+
button.innerHTML = "<svg viewBox=\"0 0 16 16\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.3\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"2\" y=\"2\" width=\"5\" height=\"5\" rx=\"1\"/><rect x=\"9\" y=\"2\" width=\"5\" height=\"5\" rx=\"1\"/><rect x=\"2\" y=\"9\" width=\"5\" height=\"5\" rx=\"1\"/><rect x=\"9\" y=\"9\" width=\"5\" height=\"5\" rx=\"1\"/></svg>";
|
|
1727
|
+
const label = document.createElement("span");
|
|
1728
|
+
label.dataset.dshAgentPluginsMarketLabel = "";
|
|
1729
|
+
button.append(label);
|
|
1730
|
+
button.addEventListener("click", onClick);
|
|
1731
|
+
return button;
|
|
1005
1732
|
}
|
|
1006
1733
|
//#endregion
|
|
1007
1734
|
//#region src/client/index.ts
|
|
1008
1735
|
/**
|
|
1009
1736
|
* dsh-agent-plugins-market client: registers the Agent Plugins Market section inside the Web
|
|
1010
|
-
* GUI's settings
|
|
1011
|
-
*
|
|
1012
|
-
*
|
|
1013
|
-
* packages the host does not serve.
|
|
1737
|
+
* GUI's settings page (the same settings.section seat dshmarket uses), with a
|
|
1738
|
+
* guarded legacy top-level page fallback for older shells. The bundle's
|
|
1739
|
+
* browser externals are React, ReactDOM, and the injected `dsh.client.inject`
|
|
1740
|
+
* module table, so it cannot reach packages the host does not serve.
|
|
1014
1741
|
*/
|
|
1015
1742
|
const NS = "dsh-agent-plugins-market";
|
|
1016
1743
|
const name = "dsh-agent-plugins-market";
|
|
@@ -1038,14 +1765,44 @@ function apply(ctx) {
|
|
|
1038
1765
|
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)`);
|
|
1039
1766
|
return;
|
|
1040
1767
|
}
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1768
|
+
let settingsSurfaceAvailable = false;
|
|
1769
|
+
ctx.effect(() => mountLegacyPageMode({
|
|
1770
|
+
t,
|
|
1771
|
+
isSettingsSurfaceAvailable: () => settingsSurfaceAvailable,
|
|
1772
|
+
subscribeLocale: ctx.locale.subscribe === void 0 ? void 0 : (listener) => ctx.locale.subscribe(listener)
|
|
1773
|
+
}), "dsh-agent-plugins-market: legacy page mode");
|
|
1774
|
+
ctx.slots.inject("settings.section", () => {
|
|
1775
|
+
settingsSurfaceAvailable = true;
|
|
1776
|
+
notifyPageModeSurfaceChange();
|
|
1777
|
+
const marketDispose = ctx.slots.register({
|
|
1778
|
+
name: "settings.section",
|
|
1779
|
+
id: "agent-plugin",
|
|
1780
|
+
order: 45,
|
|
1781
|
+
label: () => t("nav"),
|
|
1782
|
+
locale: NS,
|
|
1783
|
+
inject: () => ({ t })
|
|
1784
|
+
}, () => (0, react.createElement)(MarketSection, {
|
|
1785
|
+
t,
|
|
1786
|
+
mode: "settings"
|
|
1787
|
+
}));
|
|
1788
|
+
const mcpDispose = ctx.slots.register({
|
|
1789
|
+
name: "settings.section",
|
|
1790
|
+
id: "mcp-status",
|
|
1791
|
+
order: 46,
|
|
1792
|
+
label: () => t("mcpStatusNav"),
|
|
1793
|
+
locale: NS,
|
|
1794
|
+
inject: () => ({ t })
|
|
1795
|
+
}, () => (0, react.createElement)(McpStatusPanel, { t }));
|
|
1796
|
+
return () => {
|
|
1797
|
+
settingsSurfaceAvailable = false;
|
|
1798
|
+
notifyPageModeSurfaceChange();
|
|
1799
|
+
if (typeof mcpDispose === "function") mcpDispose();
|
|
1800
|
+
if (typeof marketDispose === "function") marketDispose();
|
|
1801
|
+
};
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
function notifyPageModeSurfaceChange() {
|
|
1805
|
+
if (typeof document !== "undefined") document.dispatchEvent(new Event(LEGACY_PAGE_MODE_SURFACE_EVENT));
|
|
1049
1806
|
}
|
|
1050
1807
|
//#endregion
|
|
1051
1808
|
exports.REQUIRED_PRIMITIVES = REQUIRED_PRIMITIVES;
|