dsh-agent-plugins-market 0.4.4 → 0.4.6
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 +77 -45
- package/README.zh.md +77 -45
- package/client/client.js +810 -70
- package/client/client.js.map +1 -1
- package/lib/discovery.js +30 -28
- package/lib/index.js +5 -0
- package/lib/manager.js +96 -5
- package/lib/mcp-status.js +147 -0
- package/lib/routes.js +6 -0
- package/lib/types/discovery.d.ts +7 -4
- package/lib/types/manager.d.ts +37 -0
- package/lib/types/mcp-status.d.ts +51 -0
- package/lib/types/types.d.ts +2 -0
- package/package.json +9 -2
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";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=".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: 24px;\n display: flex;\n}\n\n.qMtKNa_pageMode {\n width: 100%;\n min-width: 0;\n}\n\n.qMtKNa_marketControls {\n flex-direction: column;\n gap: 8px;\n min-height: 0;\n display: flex;\n}\n\n.qMtKNa_mcpSurface {\n flex: 1;\n min-height: 0;\n display: flex;\n}\n\n.qMtKNa_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.qMtKNa_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.qMtKNa_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] .qMtKNa_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.qMtKNa_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.qMtKNa_pageEntry:hover {\n background: var(--dsw-alias-bg-hover, #0000000d);\n}\n\n.qMtKNa_pageEntry:active {\n background: var(--dsw-alias-bg-active, #00000014);\n}\n\n.qMtKNa_pageEntry svg {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex-shrink: 0;\n}\n\n.qMtKNa_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] .qMtKNa_pageEntry {\n justify-content: center;\n padding-inline: 0;\n}\n\n[data-dsh-frame][data-sidebar-collapsed] .qMtKNa_pageEntry span {\n display: none;\n}\n\n.qMtKNa_pageEntry:focus-visible, .qMtKNa_srcTabMain:focus-visible, .qMtKNa_srcTabEdit:focus-visible, .qMtKNa_srcTabDel:focus-visible, .qMtKNa_seg:focus-visible, .qMtKNa_segOn:focus-visible, .qMtKNa_detailItemRow:focus-visible, .qMtKNa_detailItemOpen:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\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: 8px;\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_searchGroup {\n align-items: center;\n gap: 2px;\n display: flex;\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(118px, 1fr));\n gap: 4px;\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, .qMtKNa_srcTabOn .qMtKNa_srcTabEdit:hover {\n color: var(--dsw-alias-label-primary-foreground, #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-new-colorprimary-new-color, #4176e6);\n border-color: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n}\n\n.qMtKNa_srcTabOn .qMtKNa_srcTabMain {\n color: var(--dsw-alias-label-primary-foreground, #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, .qMtKNa_srcTabOn .qMtKNa_srcTabDel:hover {\n color: var(--dsw-alias-label-primary-foreground, #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\n@media (width <= 720px) {\n .qMtKNa_pageView {\n padding: 14px;\n }\n\n .qMtKNa_titleRow {\n flex-wrap: wrap;\n }\n\n .qMtKNa_title {\n flex: 1 0 auto;\n }\n\n .qMtKNa_sub {\n white-space: normal;\n flex: 1 0 100%;\n order: 3;\n }\n\n .qMtKNa_searchGroup {\n flex: 1 0 100%;\n order: 4;\n }\n\n .qMtKNa_sourceTabsScroll {\n scrollbar-width: thin;\n padding-bottom: 2px;\n display: flex;\n overflow-x: auto;\n }\n\n .qMtKNa_srcTab, .qMtKNa_srcTabOn {\n flex: none;\n width: auto;\n min-width: 128px;\n }\n\n .qMtKNa_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .qMtKNa_list .qMtKNa_cardTop, .qMtKNa_list .qMtKNa_cardActions {\n max-width: 100%;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .qMtKNa_progressSpin, .qMtKNa_switchOn, .qMtKNa_switchOff, .qMtKNa_switchThumb {\n transition: none;\n animation: none;\n }\n}\n.R7YLDa_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.R7YLDa_filterGap, .R7YLDa_viewGap {\n min-width: 0;\n}\n\n.R7YLDa_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.R7YLDa_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.R7YLDa_filter, .R7YLDa_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.R7YLDa_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.R7YLDa_filter svg, .R7YLDa_filterOn svg, .R7YLDa_viewSwitch svg {\n stroke: currentColor;\n stroke-width: 1.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.R7YLDa_filterCount {\n font-variant-numeric: tabular-nums;\n}\n\n.R7YLDa_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.R7YLDa_viewSwitch:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.R7YLDa_viewSwitch:focus-visible, .R7YLDa_filter:focus-visible, .R7YLDa_filterOn:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\n}\n\n@media (width <= 760px) {\n .R7YLDa_toolbar {\n grid-template-columns: auto auto auto 8px auto;\n justify-content: end;\n overflow-x: auto;\n }\n\n .R7YLDa_search {\n grid-column: 1 / -1;\n }\n\n .R7YLDa_filterGap {\n display: none;\n }\n}\n.--KJaG_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.--KJaG_header {\n flex: none;\n align-items: center;\n gap: 8px;\n padding: 4px 0 8px;\n display: flex;\n}\n\n.--KJaG_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.--KJaG_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.--KJaG_headerActions {\n align-items: center;\n gap: 8px;\n margin-left: auto;\n display: flex;\n}\n\n.--KJaG_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.--KJaG_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.--KJaG_summaryDotGreen, .--KJaG_summaryDotRed {\n border-radius: 50%;\n width: 7px;\n height: 7px;\n}\n\n.--KJaG_summaryDotGreen {\n background: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.--KJaG_summaryDotRed {\n background: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.--KJaG_toolbar {\n flex: none;\n margin-bottom: 24px;\n}\n\n.--KJaG_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.--KJaG_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.--KJaG_list .--KJaG_card {\n flex-flow: wrap;\n align-items: center;\n gap: 8px 14px;\n}\n\n.--KJaG_list .--KJaG_cardTop {\n flex: 0 260px;\n}\n\n.--KJaG_list .--KJaG_endpoint {\n -webkit-line-clamp: 1;\n flex: 200px;\n min-height: 0;\n}\n\n.--KJaG_list .--KJaG_meta {\n flex: 0 auto;\n}\n\n.--KJaG_list .--KJaG_cardReason {\n flex-basis: 100%;\n}\n\n.--KJaG_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.--KJaG_card:hover {\n border-color: var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-hover, #00000009);\n}\n\n.--KJaG_card:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\n}\n\n.--KJaG_cardTop {\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.--KJaG_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.--KJaG_statusconnected {\n background: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.--KJaG_statusdegraded {\n background: var(--dsw-alias-state-warn-primary, #b45309);\n}\n\n.--KJaG_statusfailed {\n background: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.--KJaG_statusdisabled {\n background: var(--dsw-alias-label-tertiary, #98a2b3);\n}\n\n.--KJaG_service {\n flex: 1;\n min-width: 0;\n}\n\n.--KJaG_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.--KJaG_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.--KJaG_meta {\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.--KJaG_sourcePlugin, .--KJaG_sourceDirect, .--KJaG_transport, .--KJaG_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.--KJaG_sourcePlugin svg, .--KJaG_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.--KJaG_transport {\n font-family: ui-monospace, Menlo, Consolas, monospace;\n}\n\n.--KJaG_toolCount {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex: none;\n font-weight: 600;\n}\n\n.--KJaG_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.--KJaG_state, .--KJaG_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.--KJaG_state:before, .--KJaG_detailState:before {\n content: \"\";\n background: currentColor;\n border-radius: 50%;\n width: 6px;\n height: 6px;\n}\n\n.--KJaG_stateconnected, .--KJaG_detailStateconnected {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.--KJaG_statedegraded, .--KJaG_detailStatedegraded {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n}\n\n.--KJaG_statefailed, .--KJaG_detailStatefailed {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.--KJaG_statedisabled, .--KJaG_detailStatedisabled {\n color: var(--dsw-alias-label-tertiary, #98a2b3);\n}\n\n.--KJaG_chevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 18px;\n}\n\n.--KJaG_empty, .--KJaG_detailEmpty {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-align: center;\n padding: 24px;\n font-size: 12px;\n}\n\n.--KJaG_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.--KJaG_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.--KJaG_detailDialog {\n width: min(720px, 94vw);\n}\n\n.--KJaG_detailBody {\n max-height: 72vh;\n overflow-y: auto;\n}\n\n.--KJaG_modalFooter {\n justify-content: flex-end;\n width: 100%;\n display: flex;\n}\n\n.--KJaG_detail {\n flex-direction: column;\n gap: 16px;\n display: flex;\n}\n\n.--KJaG_detailMeta {\n flex-wrap: wrap;\n gap: 6px;\n display: flex;\n}\n\n.--KJaG_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.--KJaG_detailSection {\n flex-direction: column;\n gap: 7px;\n display: flex;\n}\n\n.--KJaG_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.--KJaG_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.--KJaG_toolList {\n flex-direction: column;\n display: flex;\n}\n\n.--KJaG_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.--KJaG_tool:last-child {\n border-bottom: none;\n}\n\n.--KJaG_toolIndex {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n font: 10px / 16px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.--KJaG_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.--KJaG_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 .--KJaG_header, .--KJaG_toolbar {\n padding-left: 0;\n padding-right: 0;\n }\n\n .--KJaG_header {\n flex-direction: column;\n }\n\n .--KJaG_headerActions {\n justify-content: space-between;\n width: 100%;\n margin-left: 0;\n }\n\n .--KJaG_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .--KJaG_list .--KJaG_cardTop, .--KJaG_list .--KJaG_meta {\n max-width: 100%;\n }\n\n .--KJaG_tool {\n grid-template-columns: 26px minmax(0, 1fr);\n }\n\n .--KJaG_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 便携包)",
|
|
@@ -77,6 +79,9 @@ const zh = {
|
|
|
77
79
|
urlLocalHint: "绝对路径或 ~/…,直接读取本地目录(不克隆、移除源时不会删除)",
|
|
78
80
|
branchHint: "可选;不填则跟踪默认分支",
|
|
79
81
|
idFixed: "id 不可修改(源标识全局唯一)",
|
|
82
|
+
progressStarting: "正在提交…",
|
|
83
|
+
progressCloning: "正在克隆仓库(git clone),可能需要几十秒…",
|
|
84
|
+
progressReading: "正在读取插件清单…",
|
|
80
85
|
idAutoLabel: "源 ID(自动生成)",
|
|
81
86
|
idAutoHint: "自动从插件清单名或仓库名解析,无需填写",
|
|
82
87
|
detailHint: "点击技能或 MCP 服务行可展开查看详情",
|
|
@@ -89,7 +94,7 @@ const zh = {
|
|
|
89
94
|
uninstall: "卸载",
|
|
90
95
|
uninstallConfirmTitle: "卸载 Agent Plugins",
|
|
91
96
|
uninstallConfirmDesc: "将从已安装列表移除该 Agent Plugins,其技能与 MCP 工具随即停止注入。仓库源克隆保留。",
|
|
92
|
-
removeSourceConfirmTitle: "
|
|
97
|
+
removeSourceConfirmTitle: "移除仓库源「{sourceId}」",
|
|
93
98
|
removeSourceConfirmDesc: "将删除该源的本地克隆与全部安装记录。",
|
|
94
99
|
enable: "启用",
|
|
95
100
|
disable: "禁用",
|
|
@@ -120,6 +125,8 @@ const zh = {
|
|
|
120
125
|
sourceNotCloned: "未克隆",
|
|
121
126
|
sourceCloned: "已克隆",
|
|
122
127
|
errors: "校验问题",
|
|
128
|
+
sourceErrorSeparator: ";",
|
|
129
|
+
viewMode: "视图模式",
|
|
123
130
|
grid: "网格",
|
|
124
131
|
list: "列表",
|
|
125
132
|
openSettings: "在设置中打开",
|
|
@@ -127,7 +134,32 @@ const zh = {
|
|
|
127
134
|
dataLabel: "Agent Plugins 数据目录",
|
|
128
135
|
countAll: "共 {n} 个 Agent Plugins",
|
|
129
136
|
countInstalled: "已装 {n}",
|
|
130
|
-
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: "重试"
|
|
131
163
|
};
|
|
132
164
|
const en = {
|
|
133
165
|
nav: "Agent Plugins Market",
|
|
@@ -176,6 +208,9 @@ const en = {
|
|
|
176
208
|
urlLocalHint: "absolute path or ~/…, read in place (never cloned, never deleted on removal)",
|
|
177
209
|
branchHint: "optional; defaults to the repository default branch",
|
|
178
210
|
idFixed: "id is fixed (the source identifier is globally unique)",
|
|
211
|
+
progressStarting: "Submitting…",
|
|
212
|
+
progressCloning: "Cloning the repository (git clone) — this can take tens of seconds…",
|
|
213
|
+
progressReading: "Reading plugin manifests…",
|
|
179
214
|
idAutoLabel: "Source ID (auto)",
|
|
180
215
|
idAutoHint: "Derived from the suite or repo name — no need to type it",
|
|
181
216
|
detailHint: "Click a skill or MCP server row to expand its details",
|
|
@@ -188,7 +223,7 @@ const en = {
|
|
|
188
223
|
uninstall: "Uninstall",
|
|
189
224
|
uninstallConfirmTitle: "Uninstall suite",
|
|
190
225
|
uninstallConfirmDesc: "Removes the suite from the installed list; its skills and MCP tools stop injecting. The source clone stays.",
|
|
191
|
-
removeSourceConfirmTitle: "Remove source",
|
|
226
|
+
removeSourceConfirmTitle: "Remove source “{sourceId}”",
|
|
192
227
|
removeSourceConfirmDesc: "Deletes the local clone and all install records of this source.",
|
|
193
228
|
enable: "Enable",
|
|
194
229
|
disable: "Disable",
|
|
@@ -219,6 +254,8 @@ const en = {
|
|
|
219
254
|
sourceNotCloned: "not cloned",
|
|
220
255
|
sourceCloned: "cloned",
|
|
221
256
|
errors: "validation issues",
|
|
257
|
+
sourceErrorSeparator: "; ",
|
|
258
|
+
viewMode: "View mode",
|
|
222
259
|
grid: "grid",
|
|
223
260
|
list: "list",
|
|
224
261
|
openSettings: "Open in settings",
|
|
@@ -226,7 +263,32 @@ const en = {
|
|
|
226
263
|
dataLabel: "Suite data root",
|
|
227
264
|
countAll: "{n} suites",
|
|
228
265
|
countInstalled: "{n} installed",
|
|
229
|
-
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"
|
|
230
292
|
};
|
|
231
293
|
//#endregion
|
|
232
294
|
//#region src/client/api.ts
|
|
@@ -235,11 +297,21 @@ async function fetchOverview() {
|
|
|
235
297
|
if (!response.ok) throw new Error(`overview failed: ${response.status}`);
|
|
236
298
|
return response.json();
|
|
237
299
|
}
|
|
300
|
+
async function fetchSourceProgress() {
|
|
301
|
+
const response = await fetch("/api/agent-plugins/progress", { credentials: "same-origin" });
|
|
302
|
+
if (!response.ok) throw new Error(`progress failed: ${response.status}`);
|
|
303
|
+
return response.json();
|
|
304
|
+
}
|
|
238
305
|
async function fetchSuiteDetail(sourceId, suiteId) {
|
|
239
306
|
const response = await fetch(`/api/agent-plugins/suite?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}`, { credentials: "same-origin" });
|
|
240
307
|
if (!response.ok) throw new Error(`suite detail failed: ${response.status}`);
|
|
241
308
|
return response.json();
|
|
242
309
|
}
|
|
310
|
+
async function fetchMcpStatus() {
|
|
311
|
+
const response = await fetch("/api/agent-plugins/mcp-status", { credentials: "same-origin" });
|
|
312
|
+
if (!response.ok) throw new Error(`MCP status failed: ${response.status}`);
|
|
313
|
+
return response.json();
|
|
314
|
+
}
|
|
243
315
|
async function fetchSkillContent(sourceId, suiteId, skill) {
|
|
244
316
|
const response = await fetch(`/api/agent-plugins/skill?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}&skill=${encodeURIComponent(skill)}`, { credentials: "same-origin" });
|
|
245
317
|
if (!response.ok) throw new Error(`skill content failed: ${response.status}`);
|
|
@@ -305,6 +377,7 @@ var market_module_default = {
|
|
|
305
377
|
"detailSection": "qMtKNa_detailSection",
|
|
306
378
|
"detailSections": "qMtKNa_detailSections",
|
|
307
379
|
"detailValue": "qMtKNa_detailValue",
|
|
380
|
+
"dshApmSpin": "qMtKNa_dshApmSpin",
|
|
308
381
|
"editorDialog": "qMtKNa_editorDialog",
|
|
309
382
|
"editorForm": "qMtKNa_editorForm",
|
|
310
383
|
"empty": "qMtKNa_empty",
|
|
@@ -315,15 +388,23 @@ var market_module_default = {
|
|
|
315
388
|
"header": "qMtKNa_header",
|
|
316
389
|
"list": "qMtKNa_list",
|
|
317
390
|
"market": "qMtKNa_market",
|
|
391
|
+
"marketControls": "qMtKNa_marketControls",
|
|
392
|
+
"mcpSurface": "qMtKNa_mcpSurface",
|
|
318
393
|
"meta": "qMtKNa_meta",
|
|
319
394
|
"modalFooter": "qMtKNa_modalFooter",
|
|
320
395
|
"modalFooterLeft": "qMtKNa_modalFooterLeft",
|
|
321
396
|
"modeRow": "qMtKNa_modeRow",
|
|
322
397
|
"mono": "qMtKNa_mono",
|
|
323
398
|
"okState": "qMtKNa_okState",
|
|
399
|
+
"pageEntry": "qMtKNa_pageEntry",
|
|
400
|
+
"pageMode": "qMtKNa_pageMode",
|
|
401
|
+
"pageView": "qMtKNa_pageView",
|
|
402
|
+
"progress": "qMtKNa_progress",
|
|
403
|
+
"progressError": "qMtKNa_progressError",
|
|
404
|
+
"progressFail": "qMtKNa_progressFail",
|
|
405
|
+
"progressSpin": "qMtKNa_progressSpin",
|
|
406
|
+
"progressText": "qMtKNa_progressText",
|
|
324
407
|
"searchGroup": "qMtKNa_searchGroup",
|
|
325
|
-
"searchInput": "qMtKNa_searchInput",
|
|
326
|
-
"searchWrap": "qMtKNa_searchWrap",
|
|
327
408
|
"seg": "qMtKNa_seg",
|
|
328
409
|
"segOn": "qMtKNa_segOn",
|
|
329
410
|
"skillContent": "qMtKNa_skillContent",
|
|
@@ -339,18 +420,14 @@ var market_module_default = {
|
|
|
339
420
|
"staticId": "qMtKNa_staticId",
|
|
340
421
|
"staticIdValue": "qMtKNa_staticIdValue",
|
|
341
422
|
"sub": "qMtKNa_sub",
|
|
423
|
+
"surfaceSwitch": "qMtKNa_surfaceSwitch",
|
|
342
424
|
"switchOff": "qMtKNa_switchOff",
|
|
343
425
|
"switchOn": "qMtKNa_switchOn",
|
|
344
426
|
"switchThumb": "qMtKNa_switchThumb",
|
|
345
|
-
"tab": "qMtKNa_tab",
|
|
346
|
-
"tabGap": "qMtKNa_tabGap",
|
|
347
|
-
"tabOn": "qMtKNa_tabOn",
|
|
348
|
-
"tabRow": "qMtKNa_tabRow",
|
|
349
427
|
"tag": "qMtKNa_tag",
|
|
350
428
|
"title": "qMtKNa_title",
|
|
351
429
|
"titleRow": "qMtKNa_titleRow",
|
|
352
430
|
"version": "qMtKNa_version",
|
|
353
|
-
"viewSwitch": "qMtKNa_viewSwitch",
|
|
354
431
|
"warnLine": "qMtKNa_warnLine"
|
|
355
432
|
};
|
|
356
433
|
//#endregion
|
|
@@ -404,7 +481,7 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
|
|
|
404
481
|
const toggleMcp = (key) => {
|
|
405
482
|
setOpenMcp(openMcp === key ? void 0 : key);
|
|
406
483
|
};
|
|
407
|
-
const layoutLabel = detail === void 0 ? "" : detail.layout === "agent-plugin-v1" ? t("layoutV1") : detail.layout === "claude-code" ? t("layoutCC") : detail.layout === "codex" ? t("layoutCodex") : detail.layout === "remote" ? t("layoutRemote") : t("layoutSkills");
|
|
484
|
+
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");
|
|
408
485
|
return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
409
486
|
open: true,
|
|
410
487
|
onClose,
|
|
@@ -428,7 +505,10 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
|
|
|
428
505
|
onClick: () => {
|
|
429
506
|
toggleSkill(skill.name);
|
|
430
507
|
}
|
|
431
|
-
}, (0, react.createElement)("span", { className: market_module_default.detailItemName }, skill.name), (0, react.createElement)("span", { className: market_module_default.detailItemDesc }, skill.description), (0, react.createElement)("span", { className: market_module_default.detailChevron }, openSkill === skill.name ? "▾" : "▸")), openSkill !== skill.name ? null : (0, react.createElement)("div", { className: market_module_default.skillContent }, skillLoading ? t("loading") : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: skillText ?? "" }))))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("mcpSection")} (${detail.mcpServers.length})`), detail.
|
|
508
|
+
}, (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", {
|
|
509
|
+
className: market_module_default.warnLine,
|
|
510
|
+
style: { margin: "0 0 6px" }
|
|
511
|
+
}, `⚠ ${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", {
|
|
432
512
|
key: server.key,
|
|
433
513
|
className: market_module_default.detailItem
|
|
434
514
|
}, (0, react.createElement)("button", {
|
|
@@ -486,6 +566,87 @@ function PreviewRow(props) {
|
|
|
486
566
|
}, (0, react.createElement)("span", { className: market_module_default.detailItemName }, name), description === void 0 ? null : (0, react.createElement)("span", { className: market_module_default.detailItemDesc }, description), (0, react.createElement)("span", { className: market_module_default.detailChevron }, open ? "▾" : "▸")), open ? (0, react.createElement)("div", { className: market_module_default.skillContent }, children) : null);
|
|
487
567
|
}
|
|
488
568
|
//#endregion
|
|
569
|
+
//#region src/client/SearchFilterToolbar.module.css
|
|
570
|
+
var SearchFilterToolbar_module_default = {
|
|
571
|
+
"filter": "R7YLDa_filter",
|
|
572
|
+
"filterCount": "R7YLDa_filterCount",
|
|
573
|
+
"filterGap": "R7YLDa_filterGap",
|
|
574
|
+
"filterOn": "R7YLDa_filterOn",
|
|
575
|
+
"search": "R7YLDa_search",
|
|
576
|
+
"toolbar": "R7YLDa_toolbar",
|
|
577
|
+
"viewGap": "R7YLDa_viewGap",
|
|
578
|
+
"viewSwitch": "R7YLDa_viewSwitch"
|
|
579
|
+
};
|
|
580
|
+
//#endregion
|
|
581
|
+
//#region src/client/SearchFilterToolbar.tsx
|
|
582
|
+
/**
|
|
583
|
+
* Shared search, filter, and view controls for catalog-style settings panels.
|
|
584
|
+
*/
|
|
585
|
+
/**
|
|
586
|
+
* Render a consistent control row for searchable grid and list content.
|
|
587
|
+
*
|
|
588
|
+
* @param props - Search state, selectable filters, and view-mode state.
|
|
589
|
+
* @returns Search input, filter tabs, and an accessible grid/list toggle.
|
|
590
|
+
*/
|
|
591
|
+
function SearchFilterToolbar(props) {
|
|
592
|
+
const nextView = props.view === "grid" ? "list" : "grid";
|
|
593
|
+
const nextViewLabel = nextView === "grid" ? props.gridLabel : props.listLabel;
|
|
594
|
+
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, {
|
|
595
|
+
className: SearchFilterToolbar_module_default.search,
|
|
596
|
+
value: props.search,
|
|
597
|
+
placeholder: props.searchPlaceholder,
|
|
598
|
+
"aria-label": props.searchLabel,
|
|
599
|
+
onChange: (event) => props.onSearchChange(event.target.value)
|
|
600
|
+
}), (0, react.createElement)("div", { className: SearchFilterToolbar_module_default.filterGap }), ...props.filters.map((filter) => (0, react.createElement)("button", {
|
|
601
|
+
key: filter.id,
|
|
602
|
+
type: "button",
|
|
603
|
+
className: filter.active ? SearchFilterToolbar_module_default.filterOn : SearchFilterToolbar_module_default.filter,
|
|
604
|
+
title: `${filter.label} ${filter.count}`,
|
|
605
|
+
"aria-label": `${filter.label} ${filter.count}`,
|
|
606
|
+
onClick: filter.onSelect
|
|
607
|
+
}, 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", {
|
|
608
|
+
type: "button",
|
|
609
|
+
className: SearchFilterToolbar_module_default.viewSwitch,
|
|
610
|
+
"aria-label": nextViewLabel,
|
|
611
|
+
title: nextViewLabel,
|
|
612
|
+
onClick: () => props.onViewChange(nextView)
|
|
613
|
+
}, (0, react.createElement)(ViewIcon, { mode: nextView })));
|
|
614
|
+
}
|
|
615
|
+
function ViewIcon({ mode }) {
|
|
616
|
+
const common = {
|
|
617
|
+
width: 16,
|
|
618
|
+
height: 16,
|
|
619
|
+
viewBox: "0 0 16 16",
|
|
620
|
+
fill: "none",
|
|
621
|
+
"aria-hidden": true
|
|
622
|
+
};
|
|
623
|
+
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", {
|
|
624
|
+
x: 2.5,
|
|
625
|
+
y: 2.5,
|
|
626
|
+
width: 4,
|
|
627
|
+
height: 4,
|
|
628
|
+
rx: .8
|
|
629
|
+
}), (0, react.createElement)("rect", {
|
|
630
|
+
x: 9.5,
|
|
631
|
+
y: 2.5,
|
|
632
|
+
width: 4,
|
|
633
|
+
height: 4,
|
|
634
|
+
rx: .8
|
|
635
|
+
}), (0, react.createElement)("rect", {
|
|
636
|
+
x: 2.5,
|
|
637
|
+
y: 9.5,
|
|
638
|
+
width: 4,
|
|
639
|
+
height: 4,
|
|
640
|
+
rx: .8
|
|
641
|
+
}), (0, react.createElement)("rect", {
|
|
642
|
+
x: 9.5,
|
|
643
|
+
y: 9.5,
|
|
644
|
+
width: 4,
|
|
645
|
+
height: 4,
|
|
646
|
+
rx: .8
|
|
647
|
+
}));
|
|
648
|
+
}
|
|
649
|
+
//#endregion
|
|
489
650
|
//#region src/client/MarketSection.tsx
|
|
490
651
|
/**
|
|
491
652
|
* The Agent Plugins Market settings section.
|
|
@@ -495,6 +656,41 @@ function PreviewRow(props) {
|
|
|
495
656
|
* status tabs, and the card grid. Colors ride the dsh --dsw-alias-* tokens
|
|
496
657
|
* with light-mode fallbacks so the page follows the active theme.
|
|
497
658
|
*/
|
|
659
|
+
/** Host step keys -> translation keys, resolved against the active t(). */
|
|
660
|
+
const PROGRESS_STEP_LABELS = {
|
|
661
|
+
cloning: "progressCloning",
|
|
662
|
+
reading: "progressReading"
|
|
663
|
+
};
|
|
664
|
+
/**
|
|
665
|
+
* Poll the host's source-mutation progress while an add-source request runs.
|
|
666
|
+
* Failures of the poll itself never surface: the add request is the authority.
|
|
667
|
+
*/
|
|
668
|
+
function startProgressPolling(report) {
|
|
669
|
+
let stopped = false;
|
|
670
|
+
const tick = async () => {
|
|
671
|
+
if (stopped) return;
|
|
672
|
+
try {
|
|
673
|
+
const progress = await fetchSourceProgress();
|
|
674
|
+
if (!stopped && progress.active) report({
|
|
675
|
+
step: progressStepLabel(progress.step),
|
|
676
|
+
error: void 0
|
|
677
|
+
});
|
|
678
|
+
} catch {}
|
|
679
|
+
if (!stopped) timer = setTimeout(tick, 800);
|
|
680
|
+
};
|
|
681
|
+
let timer = setTimeout(tick, 400);
|
|
682
|
+
return { stop: () => {
|
|
683
|
+
stopped = true;
|
|
684
|
+
clearTimeout(timer);
|
|
685
|
+
} };
|
|
686
|
+
}
|
|
687
|
+
function progressStepLabel(step) {
|
|
688
|
+
return PROGRESS_STEP_LABELS[step] ?? step;
|
|
689
|
+
}
|
|
690
|
+
/** Keep parameterized copy compatible with hosts whose bound translator ignores params. */
|
|
691
|
+
function interpolate(text, params) {
|
|
692
|
+
return text.replace(/\{(\w+)\}/g, (match, key) => key in params ? String(params[key]) : match);
|
|
693
|
+
}
|
|
498
694
|
const EMPTY_OVERVIEW = {
|
|
499
695
|
sources: [],
|
|
500
696
|
suites: [],
|
|
@@ -508,9 +704,34 @@ const EMPTY_OVERVIEW = {
|
|
|
508
704
|
data: ""
|
|
509
705
|
}
|
|
510
706
|
};
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
707
|
+
/**
|
|
708
|
+
* Session-level overview cache: the first mount paints the last snapshot
|
|
709
|
+
* instantly (no empty-state flash on reopen), then revalidates in the
|
|
710
|
+
* background. Every refresh overwrites the cached copy.
|
|
711
|
+
*/
|
|
712
|
+
let cachedOverview;
|
|
713
|
+
let inflightOverview;
|
|
714
|
+
function loadOverview() {
|
|
715
|
+
const initial = cachedOverview ?? EMPTY_OVERVIEW;
|
|
716
|
+
if (inflightOverview === void 0) inflightOverview = fetchOverview().then((data) => {
|
|
717
|
+
cachedOverview = data;
|
|
718
|
+
return data;
|
|
719
|
+
}).finally(() => {
|
|
720
|
+
inflightOverview = void 0;
|
|
721
|
+
});
|
|
722
|
+
return {
|
|
723
|
+
initial,
|
|
724
|
+
revalidating: cachedOverview === void 0,
|
|
725
|
+
promise: inflightOverview
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
/** Invalidate the cached overview after any mutating action. */
|
|
729
|
+
function dropCachedOverview() {
|
|
730
|
+
cachedOverview = void 0;
|
|
731
|
+
}
|
|
732
|
+
function MarketSection({ t, mode = "settings" }) {
|
|
733
|
+
const [overview, setOverview] = (0, react.useState)(() => loadOverview().initial);
|
|
734
|
+
const [loading, setLoading] = (0, react.useState)(() => cachedOverview === void 0);
|
|
514
735
|
const [search, setSearch] = (0, react.useState)("");
|
|
515
736
|
const [tab, setTab] = (0, react.useState)("all");
|
|
516
737
|
const [category, setCategory] = (0, react.useState)("all");
|
|
@@ -520,9 +741,15 @@ function MarketSection({ t }) {
|
|
|
520
741
|
const [confirm, setConfirm] = (0, react.useState)(void 0);
|
|
521
742
|
const [editor, setEditor] = (0, react.useState)(void 0);
|
|
522
743
|
const [detail, setDetail] = (0, react.useState)(void 0);
|
|
744
|
+
const [progress, setProgress] = (0, react.useState)({
|
|
745
|
+
step: void 0,
|
|
746
|
+
error: void 0
|
|
747
|
+
});
|
|
523
748
|
const refresh = (0, react.useCallback)(async () => {
|
|
749
|
+
dropCachedOverview();
|
|
524
750
|
try {
|
|
525
|
-
|
|
751
|
+
const data = await loadOverview().promise;
|
|
752
|
+
setOverview(data);
|
|
526
753
|
} catch {
|
|
527
754
|
setToast({
|
|
528
755
|
key: Date.now(),
|
|
@@ -539,6 +766,7 @@ function MarketSection({ t }) {
|
|
|
539
766
|
setBusy(key);
|
|
540
767
|
try {
|
|
541
768
|
await postAction(path, body);
|
|
769
|
+
dropCachedOverview();
|
|
542
770
|
await refresh();
|
|
543
771
|
return true;
|
|
544
772
|
} catch (error) {
|
|
@@ -601,7 +829,7 @@ function MarketSection({ t }) {
|
|
|
601
829
|
const selectedSource = category === "all" ? void 0 : overview.sources.find((source) => source.id === category);
|
|
602
830
|
return (0, react.createElement)(ErrorBoundary, {
|
|
603
831
|
fallback: (error) => (0, react.createElement)("div", { className: market_module_default.empty }, `${t("actionFail")}: ${error.message}`),
|
|
604
|
-
children: (0, react.createElement)("div", { className: market_module_default.market
|
|
832
|
+
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, {
|
|
605
833
|
variant: "ghost",
|
|
606
834
|
size: "sm",
|
|
607
835
|
title: t("addSource"),
|
|
@@ -613,12 +841,7 @@ function MarketSection({ t }) {
|
|
|
613
841
|
onClick: () => {
|
|
614
842
|
action("s:refresh:all", "sources/refresh", {});
|
|
615
843
|
}
|
|
616
|
-
}, "↻"), (0, react.createElement)("div", { className: market_module_default.
|
|
617
|
-
className: market_module_default.searchInput,
|
|
618
|
-
placeholder: t("searchPh"),
|
|
619
|
-
value: search,
|
|
620
|
-
onChange: (event) => setSearch(event.target.value)
|
|
621
|
-
})))), (0, react.createElement)("div", { className: market_module_default.sourceTabsRow }, (0, react.createElement)("div", { className: market_module_default.sourceTabsScroll }, (0, react.createElement)(SourceTab, {
|
|
844
|
+
}, "↻"))), (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, {
|
|
622
845
|
key: "__all__",
|
|
623
846
|
t,
|
|
624
847
|
active: category === "all",
|
|
@@ -638,26 +861,42 @@ function MarketSection({ t }) {
|
|
|
638
861
|
mode: "edit",
|
|
639
862
|
source
|
|
640
863
|
}) : void 0
|
|
641
|
-
})))), (0, react.createElement)(
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
864
|
+
})))), (0, react.createElement)(SearchFilterToolbar, {
|
|
865
|
+
search,
|
|
866
|
+
searchLabel: t("searchPh"),
|
|
867
|
+
searchPlaceholder: t("searchPh"),
|
|
868
|
+
onSearchChange: setSearch,
|
|
869
|
+
filters: [
|
|
870
|
+
{
|
|
871
|
+
id: "all",
|
|
872
|
+
label: t("tabAll"),
|
|
873
|
+
count: scopeTotals.all,
|
|
874
|
+
icon: (0, react.createElement)(StatusIcon, { kind: "all" }),
|
|
875
|
+
active: tab === "all",
|
|
876
|
+
onSelect: () => setTab("all")
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
id: "installed",
|
|
880
|
+
label: t("tabInstalled"),
|
|
881
|
+
count: scopeTotals.installed,
|
|
882
|
+
icon: (0, react.createElement)(StatusIcon, { kind: "installed" }),
|
|
883
|
+
active: tab === "installed",
|
|
884
|
+
onSelect: () => setTab("installed")
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
id: "uninstalled",
|
|
888
|
+
label: t("tabUninstalled"),
|
|
889
|
+
count: scopeTotals.all - scopeTotals.installed,
|
|
890
|
+
icon: (0, react.createElement)(StatusIcon, { kind: "uninstalled" }),
|
|
891
|
+
active: tab === "uninstalled",
|
|
892
|
+
onSelect: () => setTab("uninstalled")
|
|
893
|
+
}
|
|
894
|
+
],
|
|
895
|
+
view,
|
|
896
|
+
gridLabel: t("grid"),
|
|
897
|
+
listLabel: t("list"),
|
|
898
|
+
onViewChange: (nextView) => setView(nextView)
|
|
899
|
+
}))), (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, {
|
|
661
900
|
key: `${suite.sourceId}/${suite.suiteId}`,
|
|
662
901
|
t,
|
|
663
902
|
suite,
|
|
@@ -672,6 +911,9 @@ function MarketSection({ t }) {
|
|
|
672
911
|
suiteId: suite.suiteId
|
|
673
912
|
});
|
|
674
913
|
},
|
|
914
|
+
onAddSource: () => {
|
|
915
|
+
if (suite.remoteUrl !== void 0) action(`a:${suite.suiteId}`, "sources/add", { url: suite.remoteUrl });
|
|
916
|
+
},
|
|
675
917
|
onToggle: () => {
|
|
676
918
|
action(`e:${suite.suiteId}`, "set-enabled", {
|
|
677
919
|
sourceId: suite.sourceId,
|
|
@@ -690,7 +932,7 @@ function MarketSection({ t }) {
|
|
|
690
932
|
}), confirm === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
691
933
|
open: true,
|
|
692
934
|
onClose: () => setConfirm(void 0),
|
|
693
|
-
title: confirm.kind === "uninstall" ? t("uninstallConfirmTitle") :
|
|
935
|
+
title: confirm.kind === "uninstall" ? t("uninstallConfirmTitle") : interpolate(t("removeSourceConfirmTitle", { sourceId: confirm.sourceId }), { sourceId: confirm.sourceId }),
|
|
694
936
|
closeLabel: t("cancel"),
|
|
695
937
|
description: confirm.kind === "uninstall" ? t("uninstallConfirmDesc") : t("removeSourceConfirmDesc"),
|
|
696
938
|
footer: (0, react.createElement)("div", { className: market_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
@@ -711,6 +953,7 @@ function MarketSection({ t }) {
|
|
|
711
953
|
t,
|
|
712
954
|
editor,
|
|
713
955
|
busy: busy !== void 0,
|
|
956
|
+
progress,
|
|
714
957
|
onClose: () => setEditor(void 0),
|
|
715
958
|
onSave: async (url, branch, local) => {
|
|
716
959
|
const key = editor.mode === "edit" ? `s:edit:${editor.source.id}` : `s:add:${url}`;
|
|
@@ -721,8 +964,14 @@ function MarketSection({ t }) {
|
|
|
721
964
|
};
|
|
722
965
|
if (editor.mode === "add") {
|
|
723
966
|
setBusy(key);
|
|
967
|
+
setProgress({
|
|
968
|
+
step: t("progressStarting"),
|
|
969
|
+
error: void 0
|
|
970
|
+
});
|
|
971
|
+
const poll = startProgressPolling(setProgress);
|
|
724
972
|
try {
|
|
725
973
|
const derived = (await postAction("sources/add", body))["source"]?.id;
|
|
974
|
+
dropCachedOverview();
|
|
726
975
|
await refresh();
|
|
727
976
|
setEditor(void 0);
|
|
728
977
|
if (derived !== void 0) setCategory(derived);
|
|
@@ -732,8 +981,13 @@ function MarketSection({ t }) {
|
|
|
732
981
|
key: Date.now(),
|
|
733
982
|
message: `${t("actionFail")}: ${error instanceof Error ? error.message : String(error)}`
|
|
734
983
|
});
|
|
984
|
+
setProgress({
|
|
985
|
+
step: void 0,
|
|
986
|
+
error: error instanceof Error ? error.message : String(error)
|
|
987
|
+
});
|
|
735
988
|
return false;
|
|
736
989
|
} finally {
|
|
990
|
+
poll.stop();
|
|
737
991
|
setBusy(void 0);
|
|
738
992
|
}
|
|
739
993
|
}
|
|
@@ -754,12 +1008,21 @@ function MarketSection({ t }) {
|
|
|
754
1008
|
}))
|
|
755
1009
|
});
|
|
756
1010
|
}
|
|
757
|
-
function
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1011
|
+
function StatusIcon({ kind }) {
|
|
1012
|
+
const common = {
|
|
1013
|
+
width: 16,
|
|
1014
|
+
height: 16,
|
|
1015
|
+
viewBox: "0 0 16 16",
|
|
1016
|
+
fill: "none",
|
|
1017
|
+
"aria-hidden": true
|
|
1018
|
+
};
|
|
1019
|
+
if (kind === "installed") return (0, react.createElement)("svg", common, (0, react.createElement)("circle", {
|
|
1020
|
+
cx: 8,
|
|
1021
|
+
cy: 8,
|
|
1022
|
+
r: 5.5
|
|
1023
|
+
}), (0, react.createElement)("path", { d: "m5.5 8 1.7 1.7 3.4-3.4" }));
|
|
1024
|
+
if (kind === "uninstalled") return (0, react.createElement)("svg", common, (0, react.createElement)("path", { d: "M8 2v8m-3-3 3 3 3-3M3 13h10" }));
|
|
1025
|
+
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" }));
|
|
763
1026
|
}
|
|
764
1027
|
/** A source tab with a trailing delete control (deletion confirms at the section level). */
|
|
765
1028
|
function SourceTab(props) {
|
|
@@ -829,7 +1092,7 @@ function SourceEditorModal(props) {
|
|
|
829
1092
|
placeholder: t("branchPh"),
|
|
830
1093
|
value: branch,
|
|
831
1094
|
onChange: (event) => setBranch(event.target.value)
|
|
832
|
-
}), (0, react.createElement)("span", { className: market_module_default.fieldHint }, t("branchHint"))))
|
|
1095
|
+
}), (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}`)))
|
|
833
1096
|
});
|
|
834
1097
|
}
|
|
835
1098
|
/** A green/gray switch control for suite enable state. */
|
|
@@ -871,13 +1134,18 @@ function SuiteCard(props) {
|
|
|
871
1134
|
disabled: busy,
|
|
872
1135
|
title: suite.enabled ? t("disable") : t("enable"),
|
|
873
1136
|
onChange: props.onToggle
|
|
874
|
-
}) : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1137
|
+
}) : isRemote ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
875
1138
|
variant: "primary",
|
|
876
1139
|
size: "sm",
|
|
877
|
-
disabled: busy
|
|
878
|
-
title:
|
|
1140
|
+
disabled: busy,
|
|
1141
|
+
title: suite.remoteUrl,
|
|
1142
|
+
onClick: stop(props.onAddSource)
|
|
1143
|
+
}, t("addSource")) : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1144
|
+
variant: "primary",
|
|
1145
|
+
size: "sm",
|
|
1146
|
+
disabled: busy,
|
|
879
1147
|
onClick: stop(props.onInstall)
|
|
880
|
-
},
|
|
1148
|
+
}, t("install")), suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
881
1149
|
variant: "ghost",
|
|
882
1150
|
size: "sm",
|
|
883
1151
|
title: t("refresh"),
|
|
@@ -893,18 +1161,460 @@ function SuiteCard(props) {
|
|
|
893
1161
|
key: label,
|
|
894
1162
|
className: market_module_default.tag
|
|
895
1163
|
}, `${label} ${count}`)), suite.errors.length === 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
896
|
-
label: suite.errors.slice(0, 8).join("
|
|
1164
|
+
label: suite.errors.slice(0, 8).join(t("sourceErrorSeparator")),
|
|
897
1165
|
children: (0, react.createElement)("span", { className: market_module_default.warnLine }, `⚠ ${t("errors")} ${suite.errors.length}`)
|
|
1166
|
+
}), (suite.mcpErrors?.length ?? 0) === 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
1167
|
+
label: suite.mcpErrors.slice(0, 8).join(t("sourceErrorSeparator")),
|
|
1168
|
+
children: (0, react.createElement)("span", { className: market_module_default.warnLine }, `⚠ ${t("mcpSection")} ${suite.mcpErrors.length}`)
|
|
898
1169
|
})));
|
|
899
1170
|
}
|
|
900
1171
|
//#endregion
|
|
1172
|
+
//#region src/client/mcp-status.module.css
|
|
1173
|
+
var mcp_status_module_default = {
|
|
1174
|
+
"boundary": "--KJaG_boundary",
|
|
1175
|
+
"card": "--KJaG_card",
|
|
1176
|
+
"cardReason": "--KJaG_cardReason",
|
|
1177
|
+
"cardTop": "--KJaG_cardTop",
|
|
1178
|
+
"chevron": "--KJaG_chevron",
|
|
1179
|
+
"config": "--KJaG_config",
|
|
1180
|
+
"detail": "--KJaG_detail",
|
|
1181
|
+
"detailBody": "--KJaG_detailBody",
|
|
1182
|
+
"detailDialog": "--KJaG_detailDialog",
|
|
1183
|
+
"detailEmpty": "--KJaG_detailEmpty",
|
|
1184
|
+
"detailHead": "--KJaG_detailHead",
|
|
1185
|
+
"detailMeta": "--KJaG_detailMeta",
|
|
1186
|
+
"detailSection": "--KJaG_detailSection",
|
|
1187
|
+
"detailState": "--KJaG_detailState",
|
|
1188
|
+
"detailStateconnected": "--KJaG_detailStateconnected",
|
|
1189
|
+
"detailStatedegraded": "--KJaG_detailStatedegraded",
|
|
1190
|
+
"detailStatedisabled": "--KJaG_detailStatedisabled",
|
|
1191
|
+
"detailStatefailed": "--KJaG_detailStatefailed",
|
|
1192
|
+
"empty": "--KJaG_empty",
|
|
1193
|
+
"endpoint": "--KJaG_endpoint",
|
|
1194
|
+
"error": "--KJaG_error",
|
|
1195
|
+
"errorSummary": "--KJaG_errorSummary",
|
|
1196
|
+
"grid": "--KJaG_grid",
|
|
1197
|
+
"header": "--KJaG_header",
|
|
1198
|
+
"headerActions": "--KJaG_headerActions",
|
|
1199
|
+
"list": "--KJaG_list",
|
|
1200
|
+
"meta": "--KJaG_meta",
|
|
1201
|
+
"modalFooter": "--KJaG_modalFooter",
|
|
1202
|
+
"name": "--KJaG_name",
|
|
1203
|
+
"reason": "--KJaG_reason",
|
|
1204
|
+
"service": "--KJaG_service",
|
|
1205
|
+
"sourceDirect": "--KJaG_sourceDirect",
|
|
1206
|
+
"sourcePlugin": "--KJaG_sourcePlugin",
|
|
1207
|
+
"state": "--KJaG_state",
|
|
1208
|
+
"stateconnected": "--KJaG_stateconnected",
|
|
1209
|
+
"statedegraded": "--KJaG_statedegraded",
|
|
1210
|
+
"statedisabled": "--KJaG_statedisabled",
|
|
1211
|
+
"statefailed": "--KJaG_statefailed",
|
|
1212
|
+
"statusconnected": "--KJaG_statusconnected",
|
|
1213
|
+
"statusdegraded": "--KJaG_statusdegraded",
|
|
1214
|
+
"statusdisabled": "--KJaG_statusdisabled",
|
|
1215
|
+
"statusDot": "--KJaG_statusDot",
|
|
1216
|
+
"statusfailed": "--KJaG_statusfailed",
|
|
1217
|
+
"subtitle": "--KJaG_subtitle",
|
|
1218
|
+
"summary": "--KJaG_summary",
|
|
1219
|
+
"summaryDotGreen": "--KJaG_summaryDotGreen",
|
|
1220
|
+
"summaryDotRed": "--KJaG_summaryDotRed",
|
|
1221
|
+
"surface": "--KJaG_surface",
|
|
1222
|
+
"title": "--KJaG_title",
|
|
1223
|
+
"tool": "--KJaG_tool",
|
|
1224
|
+
"toolbar": "--KJaG_toolbar",
|
|
1225
|
+
"toolCount": "--KJaG_toolCount",
|
|
1226
|
+
"toolDescription": "--KJaG_toolDescription",
|
|
1227
|
+
"toolIndex": "--KJaG_toolIndex",
|
|
1228
|
+
"toolList": "--KJaG_toolList",
|
|
1229
|
+
"toolName": "--KJaG_toolName",
|
|
1230
|
+
"transport": "--KJaG_transport"
|
|
1231
|
+
};
|
|
1232
|
+
//#endregion
|
|
1233
|
+
//#region src/client/McpStatusPanel.tsx
|
|
1234
|
+
const EMPTY_STATUS = {
|
|
1235
|
+
entries: [],
|
|
1236
|
+
observedAt: "",
|
|
1237
|
+
totals: {
|
|
1238
|
+
all: 0,
|
|
1239
|
+
connected: 0,
|
|
1240
|
+
degraded: 0,
|
|
1241
|
+
failed: 0,
|
|
1242
|
+
disabled: 0
|
|
1243
|
+
},
|
|
1244
|
+
directObservationOnly: true
|
|
1245
|
+
};
|
|
1246
|
+
/** DSH-native MCP inventory: click a service card for a standard Modal detail. */
|
|
1247
|
+
function McpStatusPanel({ t }) {
|
|
1248
|
+
const [payload, setPayload] = (0, react.useState)(EMPTY_STATUS);
|
|
1249
|
+
const [loading, setLoading] = (0, react.useState)(true);
|
|
1250
|
+
const [error, setError] = (0, react.useState)(void 0);
|
|
1251
|
+
const [filter, setFilter] = (0, react.useState)("all");
|
|
1252
|
+
const [search, setSearch] = (0, react.useState)("");
|
|
1253
|
+
const [view, setView] = (0, react.useState)("grid");
|
|
1254
|
+
const [selected, setSelected] = (0, react.useState)(void 0);
|
|
1255
|
+
const refresh = () => {
|
|
1256
|
+
setLoading(true);
|
|
1257
|
+
setError(void 0);
|
|
1258
|
+
fetchMcpStatus().then(setPayload).catch((caught) => {
|
|
1259
|
+
setError(caught instanceof Error ? caught.message : String(caught));
|
|
1260
|
+
}).finally(() => setLoading(false));
|
|
1261
|
+
};
|
|
1262
|
+
(0, react.useEffect)(() => {
|
|
1263
|
+
refresh();
|
|
1264
|
+
}, []);
|
|
1265
|
+
const activeEntries = payload.entries.filter((entry) => entry.state !== "disabled");
|
|
1266
|
+
const visibleTotals = {
|
|
1267
|
+
all: activeEntries.length,
|
|
1268
|
+
connected: activeEntries.filter((entry) => entry.state === "connected").length,
|
|
1269
|
+
failed: activeEntries.filter((entry) => entry.state === "failed").length
|
|
1270
|
+
};
|
|
1271
|
+
const filtered = (0, react.useMemo)(() => {
|
|
1272
|
+
const query = search.trim().toLowerCase();
|
|
1273
|
+
return activeEntries.filter((entry) => {
|
|
1274
|
+
if (filter !== "all" && entry.kind !== filter) return false;
|
|
1275
|
+
if (query === "") return true;
|
|
1276
|
+
return `${entry.name} ${entry.source ?? ""} ${entry.endpoint ?? ""} ${entry.transport}`.toLowerCase().includes(query);
|
|
1277
|
+
});
|
|
1278
|
+
}, [
|
|
1279
|
+
activeEntries,
|
|
1280
|
+
filter,
|
|
1281
|
+
search
|
|
1282
|
+
]);
|
|
1283
|
+
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", {
|
|
1284
|
+
className: mcp_status_module_default.errorSummary,
|
|
1285
|
+
title: `${visibleTotals.failed} ${t("mcpFailed")}`
|
|
1286
|
+
}, (0, react.createElement)("span", { className: mcp_status_module_default.summaryDotRed }), visibleTotals.failed) : null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1287
|
+
variant: "ghost",
|
|
1288
|
+
size: "sm",
|
|
1289
|
+
onClick: refresh,
|
|
1290
|
+
disabled: loading,
|
|
1291
|
+
title: t("refresh")
|
|
1292
|
+
}, "↻"))), (0, react.createElement)(SearchFilterToolbar, {
|
|
1293
|
+
className: mcp_status_module_default.toolbar,
|
|
1294
|
+
search,
|
|
1295
|
+
searchLabel: t("mcpSearch"),
|
|
1296
|
+
searchPlaceholder: t("mcpSearch"),
|
|
1297
|
+
onSearchChange: setSearch,
|
|
1298
|
+
filters: [
|
|
1299
|
+
"all",
|
|
1300
|
+
"plugin",
|
|
1301
|
+
"direct"
|
|
1302
|
+
].map((kind) => ({
|
|
1303
|
+
id: kind,
|
|
1304
|
+
label: filterLabel(t, kind),
|
|
1305
|
+
count: kind === "all" ? visibleTotals.all : activeEntries.filter((entry) => entry.kind === kind).length,
|
|
1306
|
+
icon: (0, react.createElement)(McpFilterIcon, { kind }),
|
|
1307
|
+
active: filter === kind,
|
|
1308
|
+
onSelect: () => setFilter(kind)
|
|
1309
|
+
})),
|
|
1310
|
+
view,
|
|
1311
|
+
gridLabel: t("grid"),
|
|
1312
|
+
listLabel: t("list"),
|
|
1313
|
+
onViewChange: (nextView) => setView(nextView)
|
|
1314
|
+
}), error !== void 0 ? (0, react.createElement)("div", { className: mcp_status_module_default.error }, error, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1315
|
+
variant: "ghost",
|
|
1316
|
+
size: "sm",
|
|
1317
|
+
onClick: refresh
|
|
1318
|
+
}, 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, {
|
|
1319
|
+
key: entry.id,
|
|
1320
|
+
entry,
|
|
1321
|
+
t,
|
|
1322
|
+
onClick: () => setSelected(entry)
|
|
1323
|
+
}))), selected === void 0 ? null : (0, react.createElement)(McpDetailModal, {
|
|
1324
|
+
entry: selected,
|
|
1325
|
+
t,
|
|
1326
|
+
onClose: () => setSelected(void 0)
|
|
1327
|
+
}));
|
|
1328
|
+
}
|
|
1329
|
+
function McpCard({ entry, t, onClick }) {
|
|
1330
|
+
return (0, react.createElement)("button", {
|
|
1331
|
+
type: "button",
|
|
1332
|
+
className: mcp_status_module_default.card,
|
|
1333
|
+
onClick
|
|
1334
|
+
}, (0, react.createElement)("div", { className: mcp_status_module_default.cardTop }, (0, react.createElement)("span", {
|
|
1335
|
+
className: `${mcp_status_module_default.statusDot} ${mcp_status_module_default[`status${entry.state}`]}`,
|
|
1336
|
+
title: stateLabel(t, entry.state),
|
|
1337
|
+
"aria-label": stateLabel(t, entry.state)
|
|
1338
|
+
}), (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, {
|
|
1339
|
+
kind: entry.kind,
|
|
1340
|
+
label: entry.kind === "plugin" ? entry.source ?? "—" : t("mcpDirect"),
|
|
1341
|
+
t
|
|
1342
|
+
}), (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));
|
|
1343
|
+
}
|
|
1344
|
+
function McpSourceBadge({ kind, label, t }) {
|
|
1345
|
+
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")));
|
|
1346
|
+
}
|
|
1347
|
+
function McpSourceIcon({ kind }) {
|
|
1348
|
+
const common = {
|
|
1349
|
+
width: 16,
|
|
1350
|
+
height: 16,
|
|
1351
|
+
viewBox: "0 0 16 16",
|
|
1352
|
+
fill: "none",
|
|
1353
|
+
"aria-hidden": true
|
|
1354
|
+
};
|
|
1355
|
+
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", {
|
|
1356
|
+
cx: 8,
|
|
1357
|
+
cy: 5,
|
|
1358
|
+
r: 2.2
|
|
1359
|
+
}), (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" }));
|
|
1360
|
+
}
|
|
1361
|
+
function McpFilterIcon({ kind }) {
|
|
1362
|
+
if (kind === "plugin") return (0, react.createElement)(McpSourceIcon, { kind: "plugin" });
|
|
1363
|
+
if (kind === "direct") return (0, react.createElement)(McpSourceIcon, { kind: "direct" });
|
|
1364
|
+
return (0, react.createElement)("svg", {
|
|
1365
|
+
width: 16,
|
|
1366
|
+
height: 16,
|
|
1367
|
+
viewBox: "0 0 16 16",
|
|
1368
|
+
fill: "none",
|
|
1369
|
+
"aria-hidden": true
|
|
1370
|
+
}, (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" }));
|
|
1371
|
+
}
|
|
1372
|
+
function McpDetailModal({ entry, t, onClose }) {
|
|
1373
|
+
return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1374
|
+
open: true,
|
|
1375
|
+
onClose,
|
|
1376
|
+
title: entry.name,
|
|
1377
|
+
description: t("mcpServiceDetail"),
|
|
1378
|
+
closeLabel: t("cancel"),
|
|
1379
|
+
className: mcp_status_module_default.detailDialog,
|
|
1380
|
+
contentClassName: mcp_status_module_default.detailBody,
|
|
1381
|
+
footer: (0, react.createElement)("div", { className: mcp_status_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1382
|
+
variant: "ghost",
|
|
1383
|
+
onClick: onClose
|
|
1384
|
+
}, t("cancel"))),
|
|
1385
|
+
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, {
|
|
1386
|
+
kind: entry.kind,
|
|
1387
|
+
label: entry.kind === "plugin" ? entry.source ?? "—" : t("mcpDirect"),
|
|
1388
|
+
t
|
|
1389
|
+
}), (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", {
|
|
1390
|
+
key: tool.name,
|
|
1391
|
+
className: mcp_status_module_default.tool
|
|
1392
|
+
}, (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 ?? ""))))))
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
function filterLabel(t, kind) {
|
|
1396
|
+
if (kind === "plugin") return t("mcpPlugin");
|
|
1397
|
+
if (kind === "direct") return t("mcpDirect");
|
|
1398
|
+
return t("mcpAll");
|
|
1399
|
+
}
|
|
1400
|
+
function stateLabel(t, state) {
|
|
1401
|
+
if (state === "connected") return t("mcpConnected");
|
|
1402
|
+
if (state === "degraded") return t("mcpDegraded");
|
|
1403
|
+
if (state === "failed") return t("mcpFailed");
|
|
1404
|
+
return t("mcpDisabled");
|
|
1405
|
+
}
|
|
1406
|
+
//#endregion
|
|
1407
|
+
//#region src/client/page-mode-selection.ts
|
|
1408
|
+
/** Pure capability decision for the legacy page-mode fallback. */
|
|
1409
|
+
/**
|
|
1410
|
+
* Use the DOM page fallback only when the host has no settings page and does
|
|
1411
|
+
* expose a page shell for the fallback to mount into.
|
|
1412
|
+
*
|
|
1413
|
+
* @param settingsSurfaceAvailable - whether `settings.section` is live.
|
|
1414
|
+
* @param pageShellAvailable - whether the sidebar/conversation shell exists.
|
|
1415
|
+
* @returns true when the fallback is the only available market surface.
|
|
1416
|
+
*/
|
|
1417
|
+
function shouldUseLegacyPageMode(settingsSurfaceAvailable, pageShellAvailable) {
|
|
1418
|
+
return !settingsSurfaceAvailable && pageShellAvailable;
|
|
1419
|
+
}
|
|
1420
|
+
//#endregion
|
|
1421
|
+
//#region src/client/page-mode.tsx
|
|
1422
|
+
/**
|
|
1423
|
+
* Legacy Web page-mode adapter.
|
|
1424
|
+
*
|
|
1425
|
+
* Current DSH compositions expose `settings.section`; older compositions that
|
|
1426
|
+
* predate that slot can still host a top-level market panel through the DOM
|
|
1427
|
+
* shell used by the original page-mode integration. The adapter is deliberately
|
|
1428
|
+
* guarded by the live settings-slot state so one composition never renders two
|
|
1429
|
+
* market surfaces.
|
|
1430
|
+
*/
|
|
1431
|
+
const ACTIVE_ATTRIBUTE = "data-dsh-agent-plugins-market-page";
|
|
1432
|
+
const VIEW_ATTRIBUTE = "data-dsh-agent-plugins-market-page-view";
|
|
1433
|
+
const ENTRY_ATTRIBUTE = "data-dsh-agent-plugins-market-entry";
|
|
1434
|
+
const SURFACE_EVENT = "dsh-agent-plugins-market-settings-surface";
|
|
1435
|
+
const PANEL_EVENT = "dsh-panel-activate";
|
|
1436
|
+
const PANEL_NAME = "agent-plugins-market";
|
|
1437
|
+
/** Notify the page adapter that the settings-slot capability changed. */
|
|
1438
|
+
const LEGACY_PAGE_MODE_SURFACE_EVENT = SURFACE_EVENT;
|
|
1439
|
+
const SIDEBAR_COLUMN_SELECTOR = "[data-pane=\"sidebar\"], [class*=\"sidebarCol\"]";
|
|
1440
|
+
const CONVERSATION_COLUMN_SELECTOR = "[data-pane=\"conversation\"], [class*=\"centerCol\"]";
|
|
1441
|
+
const SIDEBAR_CONTEXT_SELECTOR = "[class*=\"sessionRow\"], [class*=\"projectRow\"], [class*=\"searchResultRow\"], [class*=\"searchResultWorkspace\"], [class*=\"newSession\"]";
|
|
1442
|
+
/**
|
|
1443
|
+
* Mount the page-mode fallback and its sidebar entry.
|
|
1444
|
+
*
|
|
1445
|
+
* The fallback remains dormant when the settings surface is present. It also
|
|
1446
|
+
* remains a no-op in non-browser runtimes or shells that expose neither the
|
|
1447
|
+
* sidebar nor the conversation column.
|
|
1448
|
+
*
|
|
1449
|
+
* @param options - page-mode dependencies and host capability probe.
|
|
1450
|
+
* @returns disposer that removes the injected entry, panel, listeners, and
|
|
1451
|
+
* active document marker.
|
|
1452
|
+
*/
|
|
1453
|
+
function mountLegacyPageMode(options) {
|
|
1454
|
+
if (typeof document === "undefined" || typeof MutationObserver === "undefined") return () => {};
|
|
1455
|
+
let stopped = false;
|
|
1456
|
+
let open = false;
|
|
1457
|
+
let root;
|
|
1458
|
+
let container;
|
|
1459
|
+
let entry;
|
|
1460
|
+
let entryLabel;
|
|
1461
|
+
let observer;
|
|
1462
|
+
const setActive = (next) => {
|
|
1463
|
+
open = next;
|
|
1464
|
+
if (open && !options.isSettingsSurfaceAvailable()) {
|
|
1465
|
+
document.documentElement.setAttribute(ACTIVE_ATTRIBUTE, "");
|
|
1466
|
+
document.dispatchEvent(new CustomEvent(PANEL_EVENT, { detail: PANEL_NAME }));
|
|
1467
|
+
} else document.documentElement.removeAttribute(ACTIVE_ATTRIBUTE);
|
|
1468
|
+
};
|
|
1469
|
+
const removeView = () => {
|
|
1470
|
+
setActive(false);
|
|
1471
|
+
root?.unmount();
|
|
1472
|
+
root = void 0;
|
|
1473
|
+
container?.remove();
|
|
1474
|
+
container = void 0;
|
|
1475
|
+
};
|
|
1476
|
+
const renderView = () => {
|
|
1477
|
+
if (root === void 0) return;
|
|
1478
|
+
root.render((0, react.createElement)(MarketSection, {
|
|
1479
|
+
t: options.t,
|
|
1480
|
+
mode: "page"
|
|
1481
|
+
}));
|
|
1482
|
+
};
|
|
1483
|
+
const updateEntryCopy = () => {
|
|
1484
|
+
if (entryLabel === void 0 || entry === void 0) return;
|
|
1485
|
+
const label = options.t("nav");
|
|
1486
|
+
entryLabel.textContent = label;
|
|
1487
|
+
entry.title = label;
|
|
1488
|
+
entry.setAttribute("aria-label", label);
|
|
1489
|
+
};
|
|
1490
|
+
const ensureView = () => {
|
|
1491
|
+
if (stopped || options.isSettingsSurfaceAvailable()) {
|
|
1492
|
+
removeView();
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
const column = conversationColumn();
|
|
1496
|
+
if (!shouldUseLegacyPageMode(options.isSettingsSurfaceAvailable(), column !== void 0)) {
|
|
1497
|
+
removeView();
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
if (column === void 0) return;
|
|
1501
|
+
if (container !== void 0 && container.isConnected) return;
|
|
1502
|
+
root?.unmount();
|
|
1503
|
+
container?.remove();
|
|
1504
|
+
container = document.createElement("div");
|
|
1505
|
+
container.setAttribute(VIEW_ATTRIBUTE, "");
|
|
1506
|
+
container.className = market_module_default.pageView;
|
|
1507
|
+
column.appendChild(container);
|
|
1508
|
+
root = (0, react_dom_client.createRoot)(container);
|
|
1509
|
+
renderView();
|
|
1510
|
+
};
|
|
1511
|
+
const ensureEntry = () => {
|
|
1512
|
+
if (stopped || options.isSettingsSurfaceAvailable()) {
|
|
1513
|
+
entry?.remove();
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1516
|
+
const rootElement = sidebarRoot();
|
|
1517
|
+
const anchor = rootElement === void 0 ? void 0 : newSessionButton(rootElement);
|
|
1518
|
+
if (rootElement === void 0 || anchor === void 0 || anchor.parentElement === null) return;
|
|
1519
|
+
if (entry === void 0) {
|
|
1520
|
+
entry = createEntry(() => {
|
|
1521
|
+
setActive(!open);
|
|
1522
|
+
ensureView();
|
|
1523
|
+
});
|
|
1524
|
+
entryLabel = entry.querySelector("[data-dsh-agent-plugins-market-label]") ?? void 0;
|
|
1525
|
+
updateEntryCopy();
|
|
1526
|
+
}
|
|
1527
|
+
if (entry.parentElement !== anchor.parentElement || entry.previousSibling !== anchor) anchor.insertAdjacentElement("afterend", entry);
|
|
1528
|
+
};
|
|
1529
|
+
const observeShell = () => {
|
|
1530
|
+
if (stopped || observer !== void 0 || options.isSettingsSurfaceAvailable()) return;
|
|
1531
|
+
observer = new MutationObserver(ensure);
|
|
1532
|
+
observer.observe(document.body ?? document.documentElement, {
|
|
1533
|
+
childList: true,
|
|
1534
|
+
subtree: true
|
|
1535
|
+
});
|
|
1536
|
+
};
|
|
1537
|
+
const stopObservingShell = () => {
|
|
1538
|
+
observer?.disconnect();
|
|
1539
|
+
observer = void 0;
|
|
1540
|
+
};
|
|
1541
|
+
const ensure = () => {
|
|
1542
|
+
if (stopped) return;
|
|
1543
|
+
if (options.isSettingsSurfaceAvailable()) {
|
|
1544
|
+
stopObservingShell();
|
|
1545
|
+
removeView();
|
|
1546
|
+
entry?.remove();
|
|
1547
|
+
return;
|
|
1548
|
+
}
|
|
1549
|
+
observeShell();
|
|
1550
|
+
ensureView();
|
|
1551
|
+
ensureEntry();
|
|
1552
|
+
};
|
|
1553
|
+
const onLocale = () => {
|
|
1554
|
+
updateEntryCopy();
|
|
1555
|
+
renderView();
|
|
1556
|
+
};
|
|
1557
|
+
const onSurfaceChange = () => {
|
|
1558
|
+
ensure();
|
|
1559
|
+
};
|
|
1560
|
+
const unsubscribeLocale = options.subscribeLocale?.(onLocale);
|
|
1561
|
+
const onPanelActivate = (event) => {
|
|
1562
|
+
if (event.detail !== PANEL_NAME && open) setActive(false);
|
|
1563
|
+
};
|
|
1564
|
+
const onSidebarContextClick = (event) => {
|
|
1565
|
+
if (!open) return;
|
|
1566
|
+
const target = event.target;
|
|
1567
|
+
if (!(target instanceof HTMLElement) || target.closest(SIDEBAR_CONTEXT_SELECTOR) === null) return;
|
|
1568
|
+
setActive(false);
|
|
1569
|
+
};
|
|
1570
|
+
document.addEventListener(PANEL_EVENT, onPanelActivate);
|
|
1571
|
+
document.addEventListener(SURFACE_EVENT, onSurfaceChange);
|
|
1572
|
+
document.addEventListener("click", onSidebarContextClick, true);
|
|
1573
|
+
queueMicrotask(ensure);
|
|
1574
|
+
return () => {
|
|
1575
|
+
stopped = true;
|
|
1576
|
+
unsubscribeLocale?.();
|
|
1577
|
+
document.removeEventListener(PANEL_EVENT, onPanelActivate);
|
|
1578
|
+
document.removeEventListener(SURFACE_EVENT, onSurfaceChange);
|
|
1579
|
+
document.removeEventListener("click", onSidebarContextClick, true);
|
|
1580
|
+
stopObservingShell();
|
|
1581
|
+
entry?.remove();
|
|
1582
|
+
removeView();
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
function sidebarRoot() {
|
|
1586
|
+
const column = document.querySelector(SIDEBAR_COLUMN_SELECTOR);
|
|
1587
|
+
if (column === null) return void 0;
|
|
1588
|
+
return column.querySelector("[class*=\"logoRow\"]")?.parentElement ?? column.firstElementChild ?? void 0;
|
|
1589
|
+
}
|
|
1590
|
+
function newSessionButton(root) {
|
|
1591
|
+
const nested = root.querySelector("button[class*=\"newSession\"]");
|
|
1592
|
+
if (nested !== null) return nested;
|
|
1593
|
+
for (const child of root.children) if (child instanceof HTMLButtonElement) return child;
|
|
1594
|
+
}
|
|
1595
|
+
function conversationColumn() {
|
|
1596
|
+
return document.querySelector(CONVERSATION_COLUMN_SELECTOR) ?? void 0;
|
|
1597
|
+
}
|
|
1598
|
+
function createEntry(onClick) {
|
|
1599
|
+
const button = document.createElement("button");
|
|
1600
|
+
button.type = "button";
|
|
1601
|
+
button.setAttribute(ENTRY_ATTRIBUTE, "");
|
|
1602
|
+
button.className = market_module_default.pageEntry;
|
|
1603
|
+
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>";
|
|
1604
|
+
const label = document.createElement("span");
|
|
1605
|
+
label.dataset.dshAgentPluginsMarketLabel = "";
|
|
1606
|
+
button.append(label);
|
|
1607
|
+
button.addEventListener("click", onClick);
|
|
1608
|
+
return button;
|
|
1609
|
+
}
|
|
1610
|
+
//#endregion
|
|
901
1611
|
//#region src/client/index.ts
|
|
902
1612
|
/**
|
|
903
1613
|
* dsh-agent-plugins-market client: registers the Agent Plugins Market section inside the Web
|
|
904
|
-
* GUI's settings
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
* packages the host does not serve.
|
|
1614
|
+
* GUI's settings page (the same settings.section seat dshmarket uses), with a
|
|
1615
|
+
* guarded legacy top-level page fallback for older shells. The bundle's
|
|
1616
|
+
* browser externals are React, ReactDOM, and the injected `dsh.client.inject`
|
|
1617
|
+
* module table, so it cannot reach packages the host does not serve.
|
|
908
1618
|
*/
|
|
909
1619
|
const NS = "dsh-agent-plugins-market";
|
|
910
1620
|
const name = "dsh-agent-plugins-market";
|
|
@@ -932,14 +1642,44 @@ function apply(ctx) {
|
|
|
932
1642
|
console.warn(`[dsh-agent-plugins-market] host ui-primitives missing ${gaps.join(", ")} — Agent Plugins Market section disabled (dsh web >= 0.1.0-rc.6 required)`);
|
|
933
1643
|
return;
|
|
934
1644
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1645
|
+
let settingsSurfaceAvailable = false;
|
|
1646
|
+
ctx.effect(() => mountLegacyPageMode({
|
|
1647
|
+
t,
|
|
1648
|
+
isSettingsSurfaceAvailable: () => settingsSurfaceAvailable,
|
|
1649
|
+
subscribeLocale: ctx.locale.subscribe === void 0 ? void 0 : (listener) => ctx.locale.subscribe(listener)
|
|
1650
|
+
}), "dsh-agent-plugins-market: legacy page mode");
|
|
1651
|
+
ctx.slots.inject("settings.section", () => {
|
|
1652
|
+
settingsSurfaceAvailable = true;
|
|
1653
|
+
notifyPageModeSurfaceChange();
|
|
1654
|
+
const marketDispose = ctx.slots.register({
|
|
1655
|
+
name: "settings.section",
|
|
1656
|
+
id: "agent-plugin",
|
|
1657
|
+
order: 45,
|
|
1658
|
+
label: () => t("nav"),
|
|
1659
|
+
locale: NS,
|
|
1660
|
+
inject: () => ({ t })
|
|
1661
|
+
}, () => (0, react.createElement)(MarketSection, {
|
|
1662
|
+
t,
|
|
1663
|
+
mode: "settings"
|
|
1664
|
+
}));
|
|
1665
|
+
const mcpDispose = ctx.slots.register({
|
|
1666
|
+
name: "settings.section",
|
|
1667
|
+
id: "mcp-status",
|
|
1668
|
+
order: 46,
|
|
1669
|
+
label: () => t("mcpStatusNav"),
|
|
1670
|
+
locale: NS,
|
|
1671
|
+
inject: () => ({ t })
|
|
1672
|
+
}, () => (0, react.createElement)(McpStatusPanel, { t }));
|
|
1673
|
+
return () => {
|
|
1674
|
+
settingsSurfaceAvailable = false;
|
|
1675
|
+
notifyPageModeSurfaceChange();
|
|
1676
|
+
if (typeof mcpDispose === "function") mcpDispose();
|
|
1677
|
+
if (typeof marketDispose === "function") marketDispose();
|
|
1678
|
+
};
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
function notifyPageModeSurfaceChange() {
|
|
1682
|
+
if (typeof document !== "undefined") document.dispatchEvent(new Event(LEGACY_PAGE_MODE_SURFACE_EVENT));
|
|
943
1683
|
}
|
|
944
1684
|
//#endregion
|
|
945
1685
|
exports.REQUIRED_PRIMITIVES = REQUIRED_PRIMITIVES;
|