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/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.mcpServers.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.mcpServers.map((server) => (0, react.createElement)("div", {
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
- function MarketSection({ t }) {
512
- const [overview, setOverview] = (0, react.useState)(EMPTY_OVERVIEW);
513
- const [loading, setLoading] = (0, react.useState)(true);
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
- setOverview(await fetchOverview());
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 }, (0, react.createElement)("header", { className: market_module_default.header }, (0, react.createElement)("div", { className: market_module_default.titleRow }, (0, react.createElement)("h2", { className: market_module_default.title }, t("nav")), (0, react.createElement)("p", { className: market_module_default.sub }, t("subtitle")), (0, react.createElement)("div", { className: market_module_default.spacer }), (0, react.createElement)("div", { className: market_module_default.searchGroup }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
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.searchWrap }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
617
- className: market_module_default.searchInput,
618
- placeholder: t("searchPh"),
619
- value: search,
620
- onChange: (event) => setSearch(event.target.value)
621
- })))), (0, react.createElement)("div", { className: market_module_default.sourceTabsRow }, (0, react.createElement)("div", { className: market_module_default.sourceTabsScroll }, (0, react.createElement)(SourceTab, {
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)("div", { className: market_module_default.tabRow }, (0, react.createElement)(TabButton, {
642
- t,
643
- active: tab === "all",
644
- label: `${t("tabAll")} ${scopeTotals.all}`,
645
- onClick: () => setTab("all")
646
- }), (0, react.createElement)(TabButton, {
647
- t,
648
- active: tab === "installed",
649
- label: `${t("tabInstalled")} ${scopeTotals.installed}`,
650
- onClick: () => setTab("installed")
651
- }), (0, react.createElement)(TabButton, {
652
- t,
653
- active: tab === "uninstalled",
654
- label: `${t("tabUninstalled")} ${scopeTotals.all - scopeTotals.installed}`,
655
- onClick: () => setTab("uninstalled")
656
- }), (0, react.createElement)("div", { className: market_module_default.tabGap }), (0, react.createElement)("button", {
657
- type: "button",
658
- className: market_module_default.viewSwitch,
659
- onClick: () => setView(view === "grid" ? "list" : "grid")
660
- }, view === "grid" ? t("list") : t("grid")))), (0, react.createElement)("main", { className: view === "grid" ? market_module_default.grid : market_module_default.list }, loading ? (0, react.createElement)("div", { className: market_module_default.empty }, "…") : filtered.length === 0 ? (0, react.createElement)("div", { className: market_module_default.empty }, tab === "installed" ? t("installedEmpty") : t("empty")) : filtered.map((suite) => (0, react.createElement)(SuiteCard, {
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") : `${t("removeSourceConfirmTitle")}「${confirm.sourceId}」`,
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 TabButton({ t: _t, active, label, onClick }) {
758
- return (0, react.createElement)("button", {
759
- type: "button",
760
- className: active ? market_module_default.tabOn : market_module_default.tab,
761
- onClick
762
- }, label);
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 || isRemote,
878
- title: isRemote ? suite.remoteUrl : void 0,
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
- }, isRemote ? t("remoteRef") : t("install")), suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
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 dialog (the same settings.section seat dshmarket uses).
905
- * Mirrors the market's integration contract: the bundle's only externals are
906
- * react and the injected `dsh.client.inject` module table, so it cannot reach
907
- * packages the host does not serve.
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
- ctx.slots.inject("settings.section", () => ctx.slots.register({
936
- name: "settings.section",
937
- id: "agent-plugin",
938
- order: 45,
939
- label: () => t("nav"),
940
- locale: NS,
941
- inject: () => ({ t })
942
- }, () => (0, react.createElement)(MarketSection, { t })));
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;