dsh-agent-plugins-market 0.4.6 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +19 -11
  2. package/README.zh.md +19 -11
  3. package/client/client.js +850 -434
  4. package/client/client.js.map +1 -1
  5. package/lib/application/catalog.js +544 -0
  6. package/lib/application/details.js +139 -0
  7. package/lib/application/queries.js +1 -0
  8. package/lib/{discovery → catalog}/manifests.js +20 -12
  9. package/lib/catalog/native-project.js +73 -0
  10. package/lib/{paths.js → catalog/paths.js} +5 -1
  11. package/lib/{skills-parse.js → catalog/skills-parse.js} +7 -4
  12. package/lib/catalog/source-catalog.js +47 -0
  13. package/lib/{discovery.js → catalog/suite-scanner.js} +28 -86
  14. package/lib/{discovery → catalog}/surfaces.js +9 -11
  15. package/lib/{validate.js → catalog/validate.js} +3 -3
  16. package/lib/context.js +21 -23
  17. package/lib/contracts/market.js +30 -0
  18. package/lib/contracts/mcp-status.js +2 -0
  19. package/lib/index.js +42 -49
  20. package/lib/{state.js → model/state.js} +19 -1
  21. package/lib/model/types.js +21 -0
  22. package/lib/routes.js +58 -21
  23. package/lib/{commands-mounts.js → runtime/commands-mounts.js} +23 -15
  24. package/lib/{hooks-mounts.js → runtime/hooks-mounts.js} +4 -3
  25. package/lib/runtime/host-locale.js +67 -0
  26. package/lib/{mcp-config.js → runtime/mcp-config.js} +18 -8
  27. package/lib/{mcp-mounts.js → runtime/mcp-mounts.js} +16 -12
  28. package/lib/runtime/mcp-overrides.js +113 -0
  29. package/lib/{mcp-status.js → runtime/mcp-status.js} +13 -42
  30. package/lib/runtime/reconciler.js +51 -0
  31. package/lib/{skills-provider.js → runtime/skills-provider.js} +47 -35
  32. package/lib/runtime/tool-registry-observer.js +35 -0
  33. package/lib/types/application/catalog.d.ts +141 -0
  34. package/lib/types/application/details.d.ts +12 -0
  35. package/lib/types/application/queries.d.ts +37 -0
  36. package/lib/types/{discovery → catalog}/manifests.d.ts +1 -1
  37. package/lib/types/catalog/native-project.d.ts +17 -0
  38. package/lib/types/catalog/source-catalog.d.ts +3 -0
  39. package/lib/types/catalog/suite-scanner.d.ts +9 -0
  40. package/lib/types/{discovery → catalog}/surfaces.d.ts +1 -1
  41. package/lib/types/{validate.d.ts → catalog/validate.d.ts} +1 -1
  42. package/lib/types/context.d.ts +3 -2
  43. package/lib/types/contracts/market.d.ts +179 -0
  44. package/lib/types/contracts/mcp-status.d.ts +38 -0
  45. package/lib/types/index.d.ts +1 -1
  46. package/lib/types/{state.d.ts → model/state.d.ts} +1 -1
  47. package/lib/types/{types.d.ts → model/types.d.ts} +15 -43
  48. package/lib/types/routes.d.ts +2 -2
  49. package/lib/types/{commands-mounts.d.ts → runtime/commands-mounts.d.ts} +5 -3
  50. package/lib/types/{hooks-mounts.d.ts → runtime/hooks-mounts.d.ts} +1 -1
  51. package/lib/types/runtime/host-locale.d.ts +13 -0
  52. package/lib/types/{mcp-config.d.ts → runtime/mcp-config.d.ts} +6 -2
  53. package/lib/types/{mcp-mounts.d.ts → runtime/mcp-mounts.d.ts} +7 -2
  54. package/lib/types/runtime/mcp-overrides.d.ts +37 -0
  55. package/lib/types/runtime/mcp-status.d.ts +14 -0
  56. package/lib/types/runtime/reconciler.d.ts +36 -0
  57. package/lib/types/{skills-provider.d.ts → runtime/skills-provider.d.ts} +5 -3
  58. package/lib/types/runtime/tool-registry-observer.d.ts +14 -0
  59. package/package.json +34 -19
  60. package/schemas/README.md +2 -5
  61. package/lib/manager.js +0 -581
  62. package/lib/types/discovery.d.ts +0 -19
  63. package/lib/types/manager.d.ts +0 -124
  64. package/lib/types/mcp-status.d.ts +0 -51
  65. package/lib/types.js +0 -10
  66. /package/lib/{git.js → catalog/git.js} +0 -0
  67. /package/lib/types/{git.d.ts → catalog/git.d.ts} +0 -0
  68. /package/lib/types/{paths.d.ts → catalog/paths.d.ts} +0 -0
  69. /package/lib/types/{skills-parse.d.ts → catalog/skills-parse.d.ts} +0 -0
package/client/client.js CHANGED
@@ -2,7 +2,7 @@ window.__ModuleLoader__.load({ id: "dsh-agent-plugins-market", factory: (require
2
2
 
3
3
  var module = { exports: {} };
4
4
  var exports = module.exports;
5
- (function(){if(typeof document!=="undefined"){var s=document.createElement("style");s.setAttribute("data-dsh-client","dsh-agent-plugins-market");s.textContent=".qMtKNa_market {\n min-width: 0;\n height: 100%;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n gap: 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);}})();
5
+ (function(){if(typeof document!=="undefined"){var s=document.createElement("style");s.setAttribute("data-dsh-client","dsh-agent-plugins-market");s.textContent="._72qoAq_market {\n min-width: 0;\n height: 100%;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n gap: 24px;\n display: flex;\n}\n\n._72qoAq_pageMode {\n width: 100%;\n min-width: 0;\n}\n\n._72qoAq_marketControls {\n flex-direction: column;\n gap: 8px;\n min-height: 0;\n display: flex;\n}\n\n._72qoAq_mcpSurface {\n flex: 1;\n min-height: 0;\n display: flex;\n}\n\n._72qoAq_surfaceSwitch {\n border: 1px solid var(--dsw-alias-border-l2, #d4dce8);\n background: var(--dsw-alias-bg-layer-1, #fff);\n height: 26px;\n color: var(--dsw-alias-brand-primary, #4966f5);\n cursor: pointer;\n border-radius: 7px;\n flex: none;\n align-self: center;\n padding: 0 10px;\n font-size: 11px;\n}\n\n._72qoAq_surfaceSwitch:hover {\n background: var(--dsw-alias-bg-selected, #edf1ff);\n}\n\nhtml[data-dsh-agent-plugins-market-page] [data-pane=\"conversation\"], html[data-dsh-agent-plugins-market-page] [class*=\"centerCol\"] {\n position: relative;\n}\n\n._72qoAq_pageView {\n z-index: 60;\n background: var(--dsw-alias-bg-base, #f7f8fa);\n min-width: 0;\n min-height: 0;\n padding: 20px 24px;\n display: none;\n position: absolute;\n inset: 0;\n overflow: hidden;\n}\n\nhtml[data-dsh-agent-plugins-market-page] ._72qoAq_pageView {\n display: flex;\n}\n\nhtml[data-dsh-agent-plugins-market-page] [data-pane=\"conversation\"] > :not([data-dsh-agent-plugins-market-page-view]), html[data-dsh-agent-plugins-market-page] [class*=\"centerCol\"] > :not([data-dsh-agent-plugins-market-page-view]) {\n display: none !important;\n}\n\n._72qoAq_pageEntry {\n width: 100%;\n min-height: 32px;\n color: var(--dsw-alias-label-primary, #1f2328);\n cursor: pointer;\n font: inherit;\n text-align: left;\n background: none;\n border: none;\n border-radius: 8px;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n}\n\n._72qoAq_pageEntry:hover {\n background: var(--dsw-alias-bg-hover, #0000000d);\n}\n\n._72qoAq_pageEntry:active {\n background: var(--dsw-alias-bg-active, #00000014);\n}\n\n._72qoAq_pageEntry svg {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex-shrink: 0;\n}\n\n._72qoAq_pageEntry span {\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n overflow: hidden;\n}\n\n[data-dsh-frame][data-sidebar-collapsed] ._72qoAq_pageEntry {\n justify-content: center;\n padding-inline: 0;\n}\n\n[data-dsh-frame][data-sidebar-collapsed] ._72qoAq_pageEntry span {\n display: none;\n}\n\n._72qoAq_pageEntry:focus-visible, ._72qoAq_srcTabMain:focus-visible, ._72qoAq_srcTabEdit:focus-visible, ._72qoAq_srcTabDel:focus-visible, ._72qoAq_seg:focus-visible, ._72qoAq_segOn:focus-visible, ._72qoAq_detailItemRow:focus-visible, ._72qoAq_detailItemOpen:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\n}\n\n._72qoAq_header {\n flex-direction: column;\n flex-shrink: 0;\n gap: 8px;\n display: flex;\n}\n\n._72qoAq_titleRow {\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n._72qoAq_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n._72qoAq_sub {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n align-items: center;\n gap: 8px;\n min-width: 0;\n margin: 0;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n overflow: hidden;\n}\n\n._72qoAq_spacer {\n flex: 1;\n}\n\n._72qoAq_searchGroup {\n align-items: center;\n gap: 2px;\n display: flex;\n}\n\n._72qoAq_body {\n flex: 1;\n align-items: flex-start;\n gap: 20px;\n min-height: 0;\n display: flex;\n}\n\n._72qoAq_sourceTabsRow {\n padding: 0;\n display: block;\n}\n\n._72qoAq_sourceTabsScroll {\n grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));\n gap: 4px;\n display: grid;\n}\n\n._72qoAq_srcTabEdit {\n font: inherit;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n cursor: pointer;\n background: none;\n border: none;\n flex-shrink: 0;\n padding: 2px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_srcTabEdit:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n._72qoAq_srcTabOn ._72qoAq_srcTabEdit, ._72qoAq_srcTabOn ._72qoAq_srcTabEdit:hover {\n color: var(--dsw-alias-label-primary-foreground, #fff);\n}\n\n._72qoAq_srcTab, ._72qoAq_srcTabOn {\n border: 1px solid var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-layer-1, #fff);\n border-radius: 999px;\n justify-content: center;\n align-items: center;\n width: 100%;\n height: 24px;\n display: inline-flex;\n overflow: hidden;\n}\n\n._72qoAq_srcTabMain {\n font: inherit;\n color: var(--dsw-alias-label-primary, #1f2328);\n cursor: pointer;\n white-space: nowrap;\n text-overflow: ellipsis;\n background: none;\n border: none;\n flex: 1;\n min-width: 0;\n padding: 2px 2px 2px 10px;\n font-size: 12px;\n line-height: 18px;\n overflow: hidden;\n}\n\n._72qoAq_srcTabMain:hover {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n\n._72qoAq_srcTabOn {\n background: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n border-color: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n}\n\n._72qoAq_srcTabOn ._72qoAq_srcTabMain {\n color: var(--dsw-alias-label-primary-foreground, #fff);\n font-weight: 600;\n}\n\n._72qoAq_srcTabDel {\n font: inherit;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n cursor: pointer;\n background: none;\n border: none;\n flex-shrink: 0;\n padding: 2px 8px 2px 2px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_srcTabDel:hover {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n._72qoAq_srcTabOn ._72qoAq_srcTabDel, ._72qoAq_srcTabOn ._72qoAq_srcTabDel:hover {\n color: var(--dsw-alias-label-primary-foreground, #fff);\n}\n\n._72qoAq_grid {\n scrollbar-gutter: stable;\n flex: 1;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n align-content: start;\n gap: 12px;\n min-width: 0;\n min-height: 0;\n padding-right: 4px;\n display: grid;\n overflow-y: auto;\n}\n\n._72qoAq_list {\n scrollbar-gutter: stable;\n flex-direction: column;\n flex: 1;\n gap: 8px;\n min-width: 0;\n min-height: 0;\n padding-right: 4px;\n display: flex;\n overflow-y: auto;\n}\n\n._72qoAq_list ._72qoAq_card {\n flex-flow: wrap;\n align-items: center;\n gap: 8px 14px;\n}\n\n._72qoAq_list ._72qoAq_cardTop {\n flex: none;\n}\n\n._72qoAq_list ._72qoAq_cardDesc {\n -webkit-line-clamp: 1;\n flex: 1;\n min-width: 200px;\n min-height: 0;\n}\n\n._72qoAq_list ._72qoAq_cardActions {\n flex: none;\n}\n\n._72qoAq_list ._72qoAq_meta {\n flex-basis: 100%;\n}\n\n._72qoAq_empty {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-align: center;\n grid-column: 1 / -1;\n padding: 48px 0;\n font-size: 13px;\n}\n\n._72qoAq_card {\n background: var(--dsw-alias-bg-layer-1, #fff);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 12px;\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n padding: 12px 14px;\n display: flex;\n}\n\n._72qoAq_cardTop {\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n._72qoAq_cardTitle {\n flex: 1;\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_cardName {\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n font-weight: 600;\n line-height: 22px;\n overflow: hidden;\n}\n\n._72qoAq_version {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-variant-numeric: tabular-nums;\n flex-shrink: 0;\n font-size: 12px;\n line-height: 20px;\n}\n\n._72qoAq_cardActions {\n flex-shrink: 0;\n align-items: center;\n gap: 4px;\n display: flex;\n}\n\n._72qoAq_switchOn, ._72qoAq_switchOff {\n cursor: pointer;\n border: none;\n border-radius: 999px;\n flex-shrink: 0;\n width: 38px;\n height: 22px;\n padding: 0;\n transition: background-color .15s;\n position: relative;\n}\n\n._72qoAq_switchOn {\n background: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n._72qoAq_switchOff {\n background: var(--dsw-alias-state-neutral, #d1d5db);\n}\n\n._72qoAq_switchOn:disabled, ._72qoAq_switchOff:disabled {\n opacity: .6;\n cursor: default;\n}\n\n._72qoAq_switchThumb {\n pointer-events: none;\n background: #fff;\n border-radius: 50%;\n width: 16px;\n height: 16px;\n transition: left .15s;\n position: absolute;\n top: 3px;\n left: 3px;\n box-shadow: 0 1px 2px #0003;\n}\n\n._72qoAq_switchOn ._72qoAq_switchThumb {\n left: 19px;\n}\n\n._72qoAq_desc {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n min-height: 36px;\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n display: -webkit-box;\n overflow: hidden;\n}\n\n._72qoAq_meta {\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n._72qoAq_src {\n color: var(--dsw-alias-label-secondary, #9ca3af);\n font-size: 12px;\n text-decoration: none;\n}\n\n._72qoAq_tag {\n border: 1px solid var(--dsw-alias-border-l3, #d9dde3);\n color: var(--dsw-alias-label-secondary, #6b7280);\n border-radius: 4px;\n flex-shrink: 0;\n padding: 1px 6px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_okState {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n white-space: nowrap;\n font-size: 12px;\n font-weight: 600;\n}\n\n._72qoAq_warnLine {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n cursor: help;\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n}\n\n._72qoAq_modalFooter {\n justify-content: flex-end;\n gap: 8px;\n width: 100%;\n display: flex;\n}\n\n._72qoAq_modalFooterLeft {\n gap: 8px;\n margin-right: auto;\n display: flex;\n}\n\n._72qoAq_editorDialog {\n width: min(500px, 92vw);\n}\n\n._72qoAq_installConfirmBody {\n flex-direction: column;\n gap: 10px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_installConfirmSuite {\n color: var(--dsw-alias-label-primary, #111827);\n font-weight: 600;\n}\n\n._72qoAq_installConfirmMeta {\n color: var(--dsw-alias-label-secondary, #4b5563);\n font-size: 12px;\n}\n\n._72qoAq_installConfirmTags {\n flex-wrap: wrap;\n gap: 6px;\n display: flex;\n}\n\n._72qoAq_installConfirmWarn {\n color: var(--dsw-alias-danger, #b45309);\n border: 1px solid var(--dsw-alias-danger, #b45309);\n border-radius: 8px;\n padding: 8px 10px;\n font-size: 12px;\n}\n\n._72qoAq_editorForm {\n flex-direction: column;\n gap: 14px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_modeRow {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-2, #f3f4f6);\n border-radius: 10px;\n align-self: flex-start;\n gap: 6px;\n padding: 3px;\n display: flex;\n}\n\n._72qoAq_seg, ._72qoAq_segOn {\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 8px;\n padding: 5px 14px;\n font-size: 13px;\n line-height: 20px;\n}\n\n._72qoAq_segOn {\n background: var(--dsw-alias-bg-layer-1, #fff);\n color: var(--dsw-alias-label-primary, #1f2328);\n font-weight: 600;\n box-shadow: 0 1px 2px #00000014;\n}\n\n._72qoAq_fieldGroup {\n flex-direction: column;\n gap: 5px;\n display: flex;\n}\n\n._72qoAq_fieldLabel {\n color: var(--dsw-alias-label-secondary, #6b7280);\n font-size: 12px;\n font-weight: 600;\n}\n\n._72qoAq_fieldHint {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 12px;\n line-height: 16px;\n}\n\n._72qoAq_staticId {\n border: 1px dashed var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-layer-2, #f3f4f6);\n border-radius: 8px;\n align-items: center;\n gap: 8px;\n padding: 7px 10px;\n display: flex;\n}\n\n._72qoAq_staticIdValue {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-size: 13px;\n font-weight: 600;\n}\n\n._72qoAq_detailDialog {\n width: min(800px, 94vw);\n}\n\n._72qoAq_detailBody {\n flex-direction: column;\n gap: 14px;\n max-height: 78vh;\n display: flex;\n overflow-y: auto;\n}\n\n._72qoAq_detailSections {\n flex-direction: column;\n gap: 14px;\n display: flex;\n}\n\n._72qoAq_detailSection {\n flex-direction: column;\n gap: 6px;\n display: flex;\n}\n\n._72qoAq_detailHead {\n color: var(--dsw-alias-label-secondary, #6b7280);\n border-bottom: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n margin: 0;\n padding-bottom: 4px;\n font-size: 13px;\n font-weight: 600;\n}\n\n._72qoAq_detailGrid {\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: 6px 14px;\n display: grid;\n}\n\n._72qoAq_detailCell {\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_detailKey {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 12px;\n}\n\n._72qoAq_detailValue {\n color: var(--dsw-alias-label-primary, #1f2328);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n overflow: hidden;\n}\n\n._72qoAq_detailDesc {\n color: var(--dsw-alias-label-secondary, #6b7280);\n margin: 4px 0 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n._72qoAq_mono {\n word-break: break-all;\n white-space: pre-wrap;\n color: var(--dsw-alias-label-primary, #1f2328);\n margin: 0;\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_detailItem {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n flex-direction: column;\n display: flex;\n overflow: hidden;\n}\n\n._72qoAq_detailItemRow, ._72qoAq_detailItemOpen {\n width: 100%;\n font: inherit;\n text-align: left;\n cursor: pointer;\n color: var(--dsw-alias-label-primary, #1f2328);\n background: none;\n border: none;\n align-items: center;\n gap: 8px;\n padding: 7px 10px;\n display: flex;\n}\n\n._72qoAq_detailItemRow:hover {\n background: var(--dsw-alias-bg-hover, #0000000d);\n}\n\n._72qoAq_detailItemOpen {\n background: var(--dsw-alias-bg-selected, #4f6ef714);\n}\n\n._72qoAq_detailItemName {\n flex-shrink: 0;\n font-size: 13px;\n font-weight: 600;\n}\n\n._72qoAq_detailItemDesc {\n min-width: 0;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n font-size: 12px;\n overflow: hidden;\n}\n\n._72qoAq_detailChevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n flex-shrink: 0;\n}\n\n._72qoAq_skillContent {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n max-height: 320px;\n color: var(--dsw-alias-label-primary, #1f2328);\n padding: 10px 12px;\n font-size: 13px;\n line-height: 20px;\n overflow-y: auto;\n}\n\n._72qoAq_progress, ._72qoAq_progressError {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-2, #7f7f7f0f);\n color: var(--dsw-alias-label-primary, #1f2328);\n border-radius: 8px;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n}\n\n._72qoAq_progressError {\n border-color: var(--dsw-alias-danger, #e5484d);\n color: var(--dsw-alias-danger, #e5484d);\n}\n\n._72qoAq_progressSpin {\n border: 2px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-top-color: var(--dsw-alias-brand-primary, #4f6ef7);\n border-radius: 50%;\n flex-shrink: 0;\n width: 14px;\n height: 14px;\n animation: .8s linear infinite _72qoAq_dshApmSpin;\n}\n\n@keyframes _72qoAq_dshApmSpin {\n to {\n transform: rotate(360deg);\n }\n}\n\n._72qoAq_progressFail {\n flex-shrink: 0;\n font-size: 13px;\n}\n\n._72qoAq_progressText {\n overflow-wrap: anywhere;\n min-width: 0;\n}\n\n@media (width <= 720px) {\n ._72qoAq_pageView {\n padding: 14px;\n }\n\n ._72qoAq_titleRow {\n flex-wrap: wrap;\n }\n\n ._72qoAq_title {\n flex: 1 0 auto;\n }\n\n ._72qoAq_sub {\n white-space: normal;\n flex: 1 0 100%;\n order: 3;\n }\n\n ._72qoAq_searchGroup {\n flex: 1 0 100%;\n order: 4;\n }\n\n ._72qoAq_sourceTabsScroll {\n scrollbar-width: thin;\n padding-bottom: 2px;\n display: flex;\n overflow-x: auto;\n }\n\n ._72qoAq_srcTab, ._72qoAq_srcTabOn {\n flex: none;\n width: auto;\n min-width: 128px;\n }\n\n ._72qoAq_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n ._72qoAq_list ._72qoAq_cardTop, ._72qoAq_list ._72qoAq_cardActions {\n max-width: 100%;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._72qoAq_progressSpin, ._72qoAq_switchOn, ._72qoAq_switchOff, ._72qoAq_switchThumb {\n transition: none;\n animation: none;\n }\n}\n\n._72qoAq_surfaceToggles {\n flex-wrap: wrap;\n align-items: center;\n gap: 4px 14px;\n display: flex;\n}\n\n._72qoAq_surfaceToggle {\n color: var(--dsw-alias-text-2, #5a6070);\n cursor: pointer;\n user-select: none;\n align-items: center;\n gap: 5px;\n font-size: 12px;\n display: inline-flex;\n}\n\n._72qoAq_surfaceToggle input[type=\"checkbox\"] {\n accent-color: var(--dsw-alias-accent, #4b6bfb);\n margin: 0;\n}\n\n._72qoAq_mcpOverrideForm {\n border: 1px solid var(--dsw-alias-border, #d8dbe2);\n border-radius: 8px;\n flex-direction: column;\n gap: 8px;\n margin: 0 0 10px;\n padding: 10px;\n display: flex;\n}\n\n._72qoAq_mcpOverrideCheck {\n cursor: pointer;\n user-select: none;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n display: inline-flex;\n}\n\n._72qoAq_mcpOverrideInput {\n box-sizing: border-box;\n width: 100%;\n padding: 6px 8px;\n font-size: 12px;\n}\n\n._72qoAq_mcpOverrideArea {\n box-sizing: border-box;\n resize: vertical;\n width: 100%;\n padding: 6px 8px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12px;\n}\n\n._72qoAq_mcpOverrideActions {\n gap: 8px;\n display: flex;\n}\n.vavGuW_toolbar {\n grid-template-columns: minmax(0, 1fr) 12px auto auto auto 8px auto;\n align-items: flex-end;\n gap: 0;\n min-width: 0;\n display: grid;\n}\n\n.vavGuW_filterGap, .vavGuW_viewGap {\n min-width: 0;\n}\n\n.vavGuW_search {\n box-sizing: border-box;\n align-items: center;\n width: 100%;\n min-width: 0;\n height: 36px;\n display: flex;\n}\n\n.vavGuW_search input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 36px;\n min-height: 36px;\n max-height: 36px;\n padding-top: 0;\n padding-bottom: 0;\n font-size: 12px;\n line-height: 20px;\n}\n\n.vavGuW_filter, .vavGuW_filterOn {\n min-width: 54px;\n height: 36px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n font: inherit;\n white-space: nowrap;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n justify-content: center;\n align-items: center;\n gap: 5px;\n padding: 7px 9px;\n font-size: 13px;\n display: inline-flex;\n}\n\n.vavGuW_filterOn {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n border-bottom-color: var(--dsw-alias-brand-primary, #4f6ef7);\n font-weight: 600;\n}\n\n.vavGuW_filter svg, .vavGuW_filterOn svg, .vavGuW_viewSwitch svg {\n stroke: currentColor;\n stroke-width: 1.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n.vavGuW_filterCount {\n font-variant-numeric: tabular-nums;\n}\n\n.vavGuW_viewSwitch {\n width: 34px;\n height: 36px;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n cursor: pointer;\n background: none;\n border: none;\n border-bottom: 2px solid #0000;\n justify-content: center;\n align-items: center;\n display: inline-flex;\n}\n\n.vavGuW_viewSwitch:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.vavGuW_viewSwitch:focus-visible, .vavGuW_filter:focus-visible, .vavGuW_filterOn:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\n}\n\n@media (width <= 760px) {\n .vavGuW_toolbar {\n grid-template-columns: auto auto auto 8px auto;\n justify-content: end;\n overflow-x: auto;\n }\n\n .vavGuW_search {\n grid-column: 1 / -1;\n }\n\n .vavGuW_filterGap {\n display: none;\n }\n}\n.AUWlZW_surface {\n height: 100%;\n min-height: 0;\n max-height: 100%;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n display: flex;\n overflow: hidden;\n}\n\n.AUWlZW_header {\n flex: none;\n align-items: center;\n gap: 8px;\n padding: 4px 0 8px;\n display: flex;\n}\n\n.AUWlZW_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.AUWlZW_subtitle {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 2px 0 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n.AUWlZW_headerActions {\n align-items: center;\n gap: 8px;\n margin-left: auto;\n display: flex;\n}\n\n.AUWlZW_summary {\n color: var(--dsw-alias-label-secondary, #667085);\n white-space: nowrap;\n align-items: center;\n gap: 7px;\n font-size: 12px;\n display: inline-flex;\n}\n\n.AUWlZW_errorSummary {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n font-variant-numeric: tabular-nums;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n display: inline-flex;\n}\n\n.AUWlZW_summaryDotGreen, .AUWlZW_summaryDotRed {\n border-radius: 50%;\n width: 7px;\n height: 7px;\n}\n\n.AUWlZW_summaryDotGreen {\n background: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.AUWlZW_summaryDotRed {\n background: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.AUWlZW_toolbar {\n flex: none;\n margin-bottom: 24px;\n}\n\n.AUWlZW_grid {\n scrollbar-gutter: stable;\n flex: 1;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n align-content: start;\n gap: 12px;\n min-width: 0;\n min-height: 0;\n padding-right: 4px;\n display: grid;\n overflow-y: auto;\n}\n\n.AUWlZW_list {\n scrollbar-gutter: stable;\n flex-direction: column;\n flex: 1;\n gap: 8px;\n min-width: 0;\n min-height: 0;\n padding-right: 4px;\n display: flex;\n overflow-y: auto;\n}\n\n.AUWlZW_list .AUWlZW_card {\n flex-flow: wrap;\n align-items: center;\n gap: 8px 14px;\n}\n\n.AUWlZW_list .AUWlZW_cardTop {\n flex: 0 260px;\n}\n\n.AUWlZW_list .AUWlZW_endpoint {\n -webkit-line-clamp: 1;\n flex: 200px;\n min-height: 0;\n}\n\n.AUWlZW_list .AUWlZW_meta {\n flex: 0 auto;\n}\n\n.AUWlZW_list .AUWlZW_cardReason {\n flex-basis: 100%;\n}\n\n.AUWlZW_card {\n min-width: 0;\n min-height: 0;\n color: inherit;\n background: var(--dsw-alias-bg-layer-1, #fff);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n cursor: pointer;\n font: inherit;\n text-align: left;\n border-radius: 12px;\n flex-direction: column;\n gap: 8px;\n padding: 12px 14px;\n display: flex;\n}\n\n.AUWlZW_card:hover {\n border-color: var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-hover, #00000009);\n}\n\n.AUWlZW_card:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 2px;\n}\n\n.AUWlZW_cardTop {\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.AUWlZW_statusDot {\n background: var(--dsw-alias-state-success-primary, #16a34a);\n border-radius: 50%;\n flex: none;\n width: 7px;\n height: 7px;\n}\n\n.AUWlZW_statusconnected {\n background: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.AUWlZW_statusdegraded {\n background: var(--dsw-alias-state-warn-primary, #b45309);\n}\n\n.AUWlZW_statusfailed {\n background: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.AUWlZW_statusdisabled {\n background: var(--dsw-alias-label-tertiary, #98a2b3);\n}\n\n.AUWlZW_service {\n flex: 1;\n min-width: 0;\n}\n\n.AUWlZW_name {\n color: var(--dsw-alias-label-primary, #1f2328);\n text-overflow: ellipsis;\n white-space: nowrap;\n font: 600 13px / 22px ui-monospace, Menlo, Consolas, monospace;\n display: block;\n overflow: hidden;\n}\n\n.AUWlZW_endpoint {\n min-height: 36px;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n -webkit-line-clamp: 2;\n overflow-wrap: anywhere;\n -webkit-box-orient: vertical;\n margin: 0;\n font: 12px / 18px ui-monospace, Menlo, Consolas, monospace;\n display: -webkit-box;\n overflow: hidden;\n}\n\n.AUWlZW_meta {\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.AUWlZW_sourcePlugin, .AUWlZW_sourceDirect, .AUWlZW_transport, .AUWlZW_toolCount {\n min-width: 0;\n max-width: 100%;\n color: var(--dsw-alias-label-secondary, #6b7280);\n border: 1px solid var(--dsw-alias-border-l3, #d9dde3);\n text-overflow: ellipsis;\n white-space: nowrap;\n border-radius: 4px;\n align-items: center;\n gap: 5px;\n padding: 1px 6px;\n font-size: 12px;\n line-height: 18px;\n display: inline-flex;\n}\n\n.AUWlZW_sourcePlugin svg, .AUWlZW_sourceDirect svg {\n color: currentColor;\n stroke: currentColor;\n stroke-width: 1.35px;\n stroke-linecap: round;\n stroke-linejoin: round;\n flex: none;\n width: 14px;\n height: 14px;\n}\n\n.AUWlZW_transport {\n font-family: ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_toolCount {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex: none;\n font-weight: 600;\n}\n\n.AUWlZW_cardReason {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n overflow-wrap: anywhere;\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.AUWlZW_state, .AUWlZW_detailState {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n white-space: nowrap;\n align-items: center;\n gap: 5px;\n font-size: 11px;\n display: inline-flex;\n}\n\n.AUWlZW_state:before, .AUWlZW_detailState:before {\n content: \"\";\n background: currentColor;\n border-radius: 50%;\n width: 6px;\n height: 6px;\n}\n\n.AUWlZW_stateconnected, .AUWlZW_detailStateconnected {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n}\n\n.AUWlZW_statedegraded, .AUWlZW_detailStatedegraded {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n}\n\n.AUWlZW_statefailed, .AUWlZW_detailStatefailed {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.AUWlZW_statedisabled, .AUWlZW_detailStatedisabled {\n color: var(--dsw-alias-label-tertiary, #98a2b3);\n}\n\n.AUWlZW_chevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 18px;\n}\n\n.AUWlZW_empty, .AUWlZW_detailEmpty {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-align: center;\n padding: 24px;\n font-size: 12px;\n}\n\n.AUWlZW_error {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n align-items: center;\n gap: 8px;\n margin: 16px 0;\n font-size: 12px;\n display: flex;\n}\n\n.AUWlZW_boundary {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n background: var(--dsw-alias-bg-layer-2, #f7f8fa);\n border-left: 2px solid var(--dsw-alias-border-l3, #d9dde3);\n margin: 10px 0 0;\n padding: 9px 10px;\n font-size: 11px;\n line-height: 17px;\n}\n\n.AUWlZW_detailDialog {\n width: min(720px, 94vw);\n}\n\n.AUWlZW_detailBody {\n max-height: 72vh;\n overflow-y: auto;\n}\n\n.AUWlZW_modalFooter {\n justify-content: flex-end;\n width: 100%;\n display: flex;\n}\n\n.AUWlZW_detail {\n flex-direction: column;\n gap: 16px;\n display: flex;\n}\n\n.AUWlZW_detailMeta {\n flex-wrap: wrap;\n gap: 6px;\n display: flex;\n}\n\n.AUWlZW_reason {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n background: var(--dsw-alias-bg-error, #dc26260f);\n border-left: 2px solid;\n padding: 9px 10px;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_detailSection {\n flex-direction: column;\n gap: 7px;\n display: flex;\n}\n\n.AUWlZW_detailHead {\n color: var(--dsw-alias-label-secondary, #667085);\n border-bottom: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n margin: 0;\n padding-bottom: 5px;\n font-size: 12px;\n font-weight: 600;\n}\n\n.AUWlZW_config {\n max-height: 220px;\n color: var(--dsw-alias-label-primary, #344054);\n background: var(--dsw-alias-bg-layer-2, #f6f8fc);\n border: 1px solid var(--dsw-alias-border-l1, #e2e7ef);\n white-space: pre-wrap;\n word-break: break-word;\n border-radius: 7px;\n margin: 0;\n padding: 10px;\n font: 11px / 17px ui-monospace, Menlo, Consolas, monospace;\n overflow: auto;\n}\n\n.AUWlZW_toolList {\n flex-direction: column;\n display: flex;\n}\n\n.AUWlZW_tool {\n border-bottom: 1px solid var(--dsw-alias-border-l1, #eef1f5);\n grid-template-columns: 26px minmax(120px, auto) minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n padding: 7px 0;\n display: grid;\n}\n\n.AUWlZW_tool:last-child {\n border-bottom: none;\n}\n\n.AUWlZW_toolIndex {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n font: 10px / 16px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_toolName {\n color: var(--dsw-alias-label-primary, #1f2328);\n text-overflow: ellipsis;\n white-space: nowrap;\n font: 11px / 16px ui-monospace, Menlo, Consolas, monospace;\n overflow: hidden;\n}\n\n.AUWlZW_toolDescription {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 10px;\n overflow: hidden;\n}\n\n@media (width <= 760px) {\n .AUWlZW_header, .AUWlZW_toolbar {\n padding-left: 0;\n padding-right: 0;\n }\n\n .AUWlZW_header {\n flex-direction: column;\n }\n\n .AUWlZW_headerActions {\n justify-content: space-between;\n width: 100%;\n margin-left: 0;\n }\n\n .AUWlZW_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .AUWlZW_list .AUWlZW_cardTop, .AUWlZW_list .AUWlZW_meta {\n max-width: 100%;\n }\n\n .AUWlZW_tool {\n grid-template-columns: 26px minmax(0, 1fr);\n }\n\n .AUWlZW_toolDescription {\n display: none;\n }\n}\n";document.head.appendChild(s);}})();
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  //#region \0rolldown/runtime.js
8
8
  var __create = Object.create;
@@ -69,6 +69,19 @@ const zh = {
69
69
  keywordsLabel: "关键词",
70
70
  disabledLabel: "已停用",
71
71
  notInstalledLabel: "未安装",
72
+ surfaceTogglesSection: "运行时注入开关",
73
+ surfaceTogglesHint: "按能力面控制注入:关闭后立即卸载对应注入(技能 / MCP / Hooks / 命令 / 子代理)",
74
+ mcpOverrideEdit: "编辑覆盖",
75
+ mcpOverrideSave: "保存覆盖",
76
+ mcpOverrideReset: "重置为源配置",
77
+ mcpOverrideEnabled: "挂载此服务",
78
+ mcpOverrideUrlLabel: "URL 覆盖",
79
+ mcpOverrideHeadersLabel: "Headers 覆盖(每行 KEY=VALUE)",
80
+ mcpOverrideEnvLabel: "Env 覆盖(每行 KEY=VALUE)",
81
+ mcpOverrideArgsLabel: "Args 覆盖(每行一个参数)",
82
+ mcpOverrideKvHint: "值可写 ${ENV_NAME} 引用进程环境变量,密钥不必明文保存。",
83
+ mcpOverriddenBadge: "已覆盖",
84
+ mcpOverrideDisabledBadge: "已停用",
72
85
  noSkills: "(无技能)",
73
86
  noMcp: "(无 MCP 服务)",
74
87
  loading: "加载中…",
@@ -94,6 +107,12 @@ const zh = {
94
107
  uninstall: "卸载",
95
108
  uninstallConfirmTitle: "卸载 Agent Plugins",
96
109
  uninstallConfirmDesc: "将从已安装列表移除该 Agent Plugins,其技能与 MCP 工具随即停止注入。仓库源克隆保留。",
110
+ installConfirmTitle: "确认安装",
111
+ installConfirmDesc: "启用后以下能力将注入当前会话。请确认来源可信,详情可查看插件卡片。",
112
+ installAndEnable: "确认安装",
113
+ installConfirmNoSurfaces: "该套件未声明任何运行时能力。",
114
+ installConfirmExecutable: "风险提示:启用后将启动该套件的 MCP 子进程并挂载 hooks(第三方代码)。请确认来源可信后再启用。",
115
+ installConfirmSource: "来源",
97
116
  removeSourceConfirmTitle: "移除仓库源「{sourceId}」",
98
117
  removeSourceConfirmDesc: "将删除该源的本地克隆与全部安装记录。",
99
118
  enable: "启用",
@@ -115,6 +134,7 @@ const zh = {
115
134
  layoutCursor: "Cursor",
116
135
  layoutKimi: "Kimi",
117
136
  layoutRemote: "远程引用",
137
+ layoutProjectNative: "项目原生",
118
138
  remoteRef: "远程",
119
139
  surfaceSkills: "技能",
120
140
  surfaceMcp: "MCP",
@@ -198,6 +218,19 @@ const en = {
198
218
  keywordsLabel: "Keywords",
199
219
  disabledLabel: "disabled",
200
220
  notInstalledLabel: "not installed",
221
+ surfaceTogglesSection: "Runtime injection toggles",
222
+ surfaceTogglesHint: "Control injection per surface: turning one off unmounts that surface immediately (skills / MCP / hooks / commands / subagents)",
223
+ mcpOverrideEdit: "Edit override",
224
+ mcpOverrideSave: "Save override",
225
+ mcpOverrideReset: "Reset to source config",
226
+ mcpOverrideEnabled: "Mount this server",
227
+ mcpOverrideUrlLabel: "URL override",
228
+ mcpOverrideHeadersLabel: "Headers override (one KEY=VALUE per line)",
229
+ mcpOverrideEnvLabel: "Env override (one KEY=VALUE per line)",
230
+ mcpOverrideArgsLabel: "Args override (one argument per line)",
231
+ mcpOverrideKvHint: "Values may reference process env vars as ${ENV_NAME} so secrets never persist here.",
232
+ mcpOverriddenBadge: "overridden",
233
+ mcpOverrideDisabledBadge: "disabled",
201
234
  noSkills: "(no skills)",
202
235
  noMcp: "(no MCP servers)",
203
236
  loading: "Loading…",
@@ -223,6 +256,12 @@ const en = {
223
256
  uninstall: "Uninstall",
224
257
  uninstallConfirmTitle: "Uninstall suite",
225
258
  uninstallConfirmDesc: "Removes the suite from the installed list; its skills and MCP tools stop injecting. The source clone stays.",
259
+ installConfirmTitle: "Confirm install",
260
+ installConfirmDesc: "Once enabled, the surfaces below inject into your sessions. Confirm you trust the source; see the suite card for details.",
261
+ installAndEnable: "Install",
262
+ installConfirmNoSurfaces: "This suite declares no runtime surfaces.",
263
+ installConfirmExecutable: "Risk notice: enabling starts this suite's MCP child processes and mounts hooks (third-party code). Enable only if you trust the source.",
264
+ installConfirmSource: "Source",
226
265
  removeSourceConfirmTitle: "Remove source “{sourceId}”",
227
266
  removeSourceConfirmDesc: "Deletes the local clone and all install records of this source.",
228
267
  enable: "Enable",
@@ -244,6 +283,7 @@ const en = {
244
283
  layoutCursor: "Cursor",
245
284
  layoutKimi: "Kimi",
246
285
  layoutRemote: "remote reference",
286
+ layoutProjectNative: "project native",
247
287
  remoteRef: "remote",
248
288
  surfaceSkills: "skills",
249
289
  surfaceMcp: "MCP",
@@ -291,34 +331,67 @@ const en = {
291
331
  mcpRetry: "Retry"
292
332
  };
293
333
  //#endregion
334
+ //#region src/contracts/market.ts
335
+ /** Browser-safe market wire records and route constants shared by host and client. */
336
+ /** Prefix for all Agent Plugins Market HTTP routes. */
337
+ const MARKET_API_PREFIX = "/api/agent-plugins/";
338
+ /** Fixed Agent Plugins Market HTTP routes. */
339
+ const MARKET_ROUTES = {
340
+ overview: `${MARKET_API_PREFIX}overview`,
341
+ mcpStatus: `${MARKET_API_PREFIX}mcp-status`,
342
+ progress: `${MARKET_API_PREFIX}progress`,
343
+ config: `${MARKET_API_PREFIX}config`,
344
+ suite: `${MARKET_API_PREFIX}suite`,
345
+ skill: `${MARKET_API_PREFIX}skill`,
346
+ addSource: `${MARKET_API_PREFIX}sources/add`,
347
+ updateSource: `${MARKET_API_PREFIX}sources/update`,
348
+ removeSource: `${MARKET_API_PREFIX}sources/remove`,
349
+ refreshSource: `${MARKET_API_PREFIX}sources/refresh`,
350
+ install: `${MARKET_API_PREFIX}install`,
351
+ uninstall: `${MARKET_API_PREFIX}uninstall`,
352
+ setEnabled: `${MARKET_API_PREFIX}set-enabled`,
353
+ setSurface: `${MARKET_API_PREFIX}set-surface`,
354
+ mcpOverrides: `${MARKET_API_PREFIX}mcp-overrides`,
355
+ setMcpOverride: `${MARKET_API_PREFIX}set-mcp-override`
356
+ };
357
+ /** Build a suite-detail URL without duplicating route or query encoding logic. */
358
+ function suiteRoute(sourceId, suiteId) {
359
+ return `${MARKET_ROUTES.suite}?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}`;
360
+ }
361
+ /** Build a skill-content URL without duplicating route or query encoding logic. */
362
+ function skillRoute(sourceId, suiteId, skill) {
363
+ return `${MARKET_ROUTES.skill}?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}&skill=${encodeURIComponent(skill)}`;
364
+ }
365
+ //#endregion
294
366
  //#region src/client/api.ts
367
+ /** Typed fetch helpers over the host's `/api/agent-plugins/*` routes. */
295
368
  async function fetchOverview() {
296
- const response = await fetch("/api/agent-plugins/overview", { credentials: "same-origin" });
369
+ const response = await fetch(MARKET_ROUTES.overview, { credentials: "same-origin" });
297
370
  if (!response.ok) throw new Error(`overview failed: ${response.status}`);
298
371
  return response.json();
299
372
  }
300
373
  async function fetchSourceProgress() {
301
- const response = await fetch("/api/agent-plugins/progress", { credentials: "same-origin" });
374
+ const response = await fetch(MARKET_ROUTES.progress, { credentials: "same-origin" });
302
375
  if (!response.ok) throw new Error(`progress failed: ${response.status}`);
303
376
  return response.json();
304
377
  }
305
378
  async function fetchSuiteDetail(sourceId, suiteId) {
306
- const response = await fetch(`/api/agent-plugins/suite?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}`, { credentials: "same-origin" });
379
+ const response = await fetch(suiteRoute(sourceId, suiteId), { credentials: "same-origin" });
307
380
  if (!response.ok) throw new Error(`suite detail failed: ${response.status}`);
308
381
  return response.json();
309
382
  }
310
383
  async function fetchMcpStatus() {
311
- const response = await fetch("/api/agent-plugins/mcp-status", { credentials: "same-origin" });
384
+ const response = await fetch(MARKET_ROUTES.mcpStatus, { credentials: "same-origin" });
312
385
  if (!response.ok) throw new Error(`MCP status failed: ${response.status}`);
313
386
  return response.json();
314
387
  }
315
388
  async function fetchSkillContent(sourceId, suiteId, skill) {
316
- const response = await fetch(`/api/agent-plugins/skill?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}&skill=${encodeURIComponent(skill)}`, { credentials: "same-origin" });
389
+ const response = await fetch(skillRoute(sourceId, suiteId, skill), { credentials: "same-origin" });
317
390
  if (!response.ok) throw new Error(`skill content failed: ${response.status}`);
318
391
  return response.json();
319
392
  }
320
393
  async function postAction(path, body) {
321
- const response = await fetch(`/api/agent-plugins/${path}`, {
394
+ const response = await fetch(`${MARKET_API_PREFIX}${path}`, {
322
395
  method: "POST",
323
396
  credentials: "same-origin",
324
397
  headers: { "content-type": "application/json" },
@@ -329,6 +402,435 @@ async function postAction(path, body) {
329
402
  return payload;
330
403
  }
331
404
  //#endregion
405
+ //#region src/client/features/market/market-resource.ts
406
+ /** Market overview cache, invalidation, and source-progress resource helpers. */
407
+ const EMPTY_OVERVIEW = {
408
+ sources: [],
409
+ suites: [],
410
+ totals: {
411
+ all: 0,
412
+ installed: 0,
413
+ enabled: 0
414
+ },
415
+ roots: {
416
+ user: "",
417
+ data: ""
418
+ }
419
+ };
420
+ let cachedOverview;
421
+ let inflightOverview;
422
+ /** Load the last overview immediately and revalidate one shared request. */
423
+ function loadOverview() {
424
+ const initial = cachedOverview ?? EMPTY_OVERVIEW;
425
+ if (inflightOverview === void 0) inflightOverview = fetchOverview().then((data) => {
426
+ cachedOverview = data;
427
+ return data;
428
+ }).finally(() => {
429
+ inflightOverview = void 0;
430
+ });
431
+ return {
432
+ initial,
433
+ revalidating: cachedOverview === void 0,
434
+ promise: inflightOverview
435
+ };
436
+ }
437
+ /** Invalidate the shared overview after a mutating action. */
438
+ function invalidateOverview() {
439
+ cachedOverview = void 0;
440
+ }
441
+ /**
442
+ * Poll source mutation progress until stopped. Poll failures remain silent
443
+ * because the add-source request is authoritative for mutation success.
444
+ */
445
+ function startSourceProgressPolling(report, resolveStep = (step) => step) {
446
+ let stopped = false;
447
+ let timer;
448
+ const tick = async () => {
449
+ if (stopped) return;
450
+ try {
451
+ const progress = await fetchSourceProgress();
452
+ if (!stopped && progress.active) report({
453
+ step: resolveStep(progress.step),
454
+ error: void 0
455
+ });
456
+ } catch {}
457
+ if (!stopped) timer = setTimeout(() => {
458
+ tick();
459
+ }, 800);
460
+ };
461
+ timer = setTimeout(() => {
462
+ tick();
463
+ }, 400);
464
+ return { stop: () => {
465
+ stopped = true;
466
+ if (timer !== void 0) clearTimeout(timer);
467
+ } };
468
+ }
469
+ //#endregion
470
+ //#region src/client/features/market/market-view-model.ts
471
+ const searchableCache$1 = /* @__PURE__ */ new WeakMap();
472
+ /** Derive visible cards and scope counts in one pass over a normalized payload. */
473
+ function deriveMarketViewModel(overview, search, filter, category) {
474
+ const searchable = searchableFor$1(overview);
475
+ const needle = search.trim().toLowerCase();
476
+ let all = 0;
477
+ let installed = 0;
478
+ let enabled = 0;
479
+ const visible = [];
480
+ for (const entry of searchable) {
481
+ const suite = entry.suite;
482
+ if (category !== "all" && suite.sourceId !== category) continue;
483
+ all++;
484
+ if (suite.installed) installed++;
485
+ if (suite.enabled) enabled++;
486
+ if (filter === "installed" && !suite.installed) continue;
487
+ if (filter === "uninstalled" && suite.installed) continue;
488
+ if (needle !== "" && !entry.haystack.includes(needle)) continue;
489
+ visible.push(suite);
490
+ }
491
+ return {
492
+ scopeTotals: {
493
+ all,
494
+ installed,
495
+ enabled
496
+ },
497
+ filtered: visible
498
+ };
499
+ }
500
+ function searchableFor$1(overview) {
501
+ const cached = searchableCache$1.get(overview);
502
+ if (cached !== void 0) return cached;
503
+ const searchable = overview.suites.map((suite) => ({
504
+ suite,
505
+ haystack: `${suite.name} ${suite.description ?? ""} ${suite.keywords.join(" ")}`.toLowerCase()
506
+ }));
507
+ searchableCache$1.set(overview, searchable);
508
+ return searchable;
509
+ }
510
+ //#endregion
511
+ //#region src/client/market.module.css
512
+ var market_module_default = {
513
+ "body": "_72qoAq_body",
514
+ "card": "_72qoAq_card",
515
+ "cardActions": "_72qoAq_cardActions",
516
+ "cardDesc": "_72qoAq_cardDesc",
517
+ "cardName": "_72qoAq_cardName",
518
+ "cardTitle": "_72qoAq_cardTitle",
519
+ "cardTop": "_72qoAq_cardTop",
520
+ "desc": "_72qoAq_desc",
521
+ "detailBody": "_72qoAq_detailBody",
522
+ "detailCell": "_72qoAq_detailCell",
523
+ "detailChevron": "_72qoAq_detailChevron",
524
+ "detailDesc": "_72qoAq_detailDesc",
525
+ "detailDialog": "_72qoAq_detailDialog",
526
+ "detailGrid": "_72qoAq_detailGrid",
527
+ "detailHead": "_72qoAq_detailHead",
528
+ "detailItem": "_72qoAq_detailItem",
529
+ "detailItemDesc": "_72qoAq_detailItemDesc",
530
+ "detailItemName": "_72qoAq_detailItemName",
531
+ "detailItemOpen": "_72qoAq_detailItemOpen",
532
+ "detailItemRow": "_72qoAq_detailItemRow",
533
+ "detailKey": "_72qoAq_detailKey",
534
+ "detailSection": "_72qoAq_detailSection",
535
+ "detailSections": "_72qoAq_detailSections",
536
+ "detailValue": "_72qoAq_detailValue",
537
+ "dshApmSpin": "_72qoAq_dshApmSpin",
538
+ "editorDialog": "_72qoAq_editorDialog",
539
+ "editorForm": "_72qoAq_editorForm",
540
+ "empty": "_72qoAq_empty",
541
+ "fieldGroup": "_72qoAq_fieldGroup",
542
+ "fieldHint": "_72qoAq_fieldHint",
543
+ "fieldLabel": "_72qoAq_fieldLabel",
544
+ "grid": "_72qoAq_grid",
545
+ "header": "_72qoAq_header",
546
+ "installConfirmBody": "_72qoAq_installConfirmBody",
547
+ "installConfirmMeta": "_72qoAq_installConfirmMeta",
548
+ "installConfirmSuite": "_72qoAq_installConfirmSuite",
549
+ "installConfirmTags": "_72qoAq_installConfirmTags",
550
+ "installConfirmWarn": "_72qoAq_installConfirmWarn",
551
+ "list": "_72qoAq_list",
552
+ "market": "_72qoAq_market",
553
+ "marketControls": "_72qoAq_marketControls",
554
+ "mcpOverrideActions": "_72qoAq_mcpOverrideActions",
555
+ "mcpOverrideArea": "_72qoAq_mcpOverrideArea",
556
+ "mcpOverrideCheck": "_72qoAq_mcpOverrideCheck",
557
+ "mcpOverrideForm": "_72qoAq_mcpOverrideForm",
558
+ "mcpOverrideInput": "_72qoAq_mcpOverrideInput",
559
+ "mcpSurface": "_72qoAq_mcpSurface",
560
+ "meta": "_72qoAq_meta",
561
+ "modalFooter": "_72qoAq_modalFooter",
562
+ "modalFooterLeft": "_72qoAq_modalFooterLeft",
563
+ "modeRow": "_72qoAq_modeRow",
564
+ "mono": "_72qoAq_mono",
565
+ "okState": "_72qoAq_okState",
566
+ "pageEntry": "_72qoAq_pageEntry",
567
+ "pageMode": "_72qoAq_pageMode",
568
+ "pageView": "_72qoAq_pageView",
569
+ "progress": "_72qoAq_progress",
570
+ "progressError": "_72qoAq_progressError",
571
+ "progressFail": "_72qoAq_progressFail",
572
+ "progressSpin": "_72qoAq_progressSpin",
573
+ "progressText": "_72qoAq_progressText",
574
+ "searchGroup": "_72qoAq_searchGroup",
575
+ "seg": "_72qoAq_seg",
576
+ "segOn": "_72qoAq_segOn",
577
+ "skillContent": "_72qoAq_skillContent",
578
+ "sourceTabsRow": "_72qoAq_sourceTabsRow",
579
+ "sourceTabsScroll": "_72qoAq_sourceTabsScroll",
580
+ "spacer": "_72qoAq_spacer",
581
+ "src": "_72qoAq_src",
582
+ "srcTab": "_72qoAq_srcTab",
583
+ "srcTabDel": "_72qoAq_srcTabDel",
584
+ "srcTabEdit": "_72qoAq_srcTabEdit",
585
+ "srcTabMain": "_72qoAq_srcTabMain",
586
+ "srcTabOn": "_72qoAq_srcTabOn",
587
+ "staticId": "_72qoAq_staticId",
588
+ "staticIdValue": "_72qoAq_staticIdValue",
589
+ "sub": "_72qoAq_sub",
590
+ "surfaceSwitch": "_72qoAq_surfaceSwitch",
591
+ "surfaceToggle": "_72qoAq_surfaceToggle",
592
+ "surfaceToggles": "_72qoAq_surfaceToggles",
593
+ "switchOff": "_72qoAq_switchOff",
594
+ "switchOn": "_72qoAq_switchOn",
595
+ "switchThumb": "_72qoAq_switchThumb",
596
+ "tag": "_72qoAq_tag",
597
+ "title": "_72qoAq_title",
598
+ "titleRow": "_72qoAq_titleRow",
599
+ "version": "_72qoAq_version",
600
+ "warnLine": "_72qoAq_warnLine"
601
+ };
602
+ //#endregion
603
+ //#region src/client/features/market/SourceTab.tsx
604
+ /** A source tab with trailing edit and delete controls. */
605
+ /** A source chip with a trailing delete control (deletion confirms at the section level). */
606
+ function SourceTab(props) {
607
+ const { t, active = false, label, onSelect, onDelete, onEdit } = props;
608
+ return (0, react.createElement)("div", { className: active ? market_module_default.srcTabOn : market_module_default.srcTab }, (0, react.createElement)("button", {
609
+ type: "button",
610
+ className: market_module_default.srcTabMain,
611
+ onClick: onSelect
612
+ }, label), onEdit === void 0 ? null : (0, react.createElement)("button", {
613
+ type: "button",
614
+ className: market_module_default.srcTabEdit,
615
+ title: t("editSource"),
616
+ onClick: (event) => {
617
+ event.stopPropagation();
618
+ onEdit();
619
+ }
620
+ }, "✎"), onDelete === void 0 ? null : (0, react.createElement)("button", {
621
+ type: "button",
622
+ className: market_module_default.srcTabDel,
623
+ title: t("remove"),
624
+ onClick: (event) => {
625
+ event.stopPropagation();
626
+ onDelete();
627
+ }
628
+ }, "×"));
629
+ }
630
+ //#endregion
631
+ //#region src/client/features/market/SourceEditorModal.tsx
632
+ /** Source editor modal for adding or editing a catalog source. */
633
+ function SourceEditorModal(props) {
634
+ const { t, editor } = props;
635
+ const [local, setLocal] = (0, react.useState)(editor.mode === "edit" && editor.source.local === true);
636
+ const [url, setUrl] = (0, react.useState)(editor.mode === "edit" ? editor.source.url : "");
637
+ const [branch, setBranch] = (0, react.useState)(editor.mode === "edit" ? editor.source.branch ?? "" : "");
638
+ const id = editor.mode === "edit" ? editor.source.id : "";
639
+ const title = editor.mode === "edit" ? t("editSourceTitle") : t("addSourceTitle");
640
+ return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
641
+ open: true,
642
+ onClose: props.onClose,
643
+ title,
644
+ description: t("editorHint"),
645
+ closeLabel: t("cancel"),
646
+ className: market_module_default.editorDialog,
647
+ footer: (0, react.createElement)("div", { className: market_module_default.modalFooter }, (0, react.createElement)("div", { className: market_module_default.modalFooterLeft }, editor.mode === "edit" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
648
+ variant: "ghost",
649
+ onClick: () => props.onRemove(id)
650
+ }, `🗑 ${t("remove")}`) : null), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
651
+ variant: "ghost",
652
+ onClick: props.onClose
653
+ }, t("cancel")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
654
+ variant: "primary",
655
+ disabled: props.busy,
656
+ onClick: () => {
657
+ props.onSave(url.trim(), branch.trim(), local);
658
+ }
659
+ }, t("save"))),
660
+ children: (0, react.createElement)("div", { className: market_module_default.editorForm }, (0, react.createElement)("div", { className: market_module_default.modeRow }, (0, react.createElement)("button", {
661
+ type: "button",
662
+ className: local ? market_module_default.seg : market_module_default.segOn,
663
+ onClick: () => setLocal(false)
664
+ }, t("sourceModeGit")), (0, react.createElement)("button", {
665
+ type: "button",
666
+ className: local ? market_module_default.segOn : market_module_default.seg,
667
+ onClick: () => setLocal(true)
668
+ }, t("sourceModeLocal"))), editor.mode === "edit" ? (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, t("sourceIdPh")), (0, react.createElement)("div", { className: market_module_default.staticId }, (0, react.createElement)("span", { className: market_module_default.staticIdValue }, id), (0, react.createElement)("span", { className: market_module_default.fieldHint }, t("idFixed")))) : null, (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, local ? t("sourceUrlLocalPh") : t("sourceUrlPh")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
669
+ placeholder: local ? t("sourceUrlLocalPh") : t("sourceUrlPh"),
670
+ value: url,
671
+ onChange: (event) => setUrl(event.target.value)
672
+ }), (0, react.createElement)("span", { className: market_module_default.fieldHint }, local ? t("urlLocalHint") : t("urlGitHint"))), local ? null : (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, t("branchPh")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
673
+ placeholder: t("branchPh"),
674
+ value: branch,
675
+ onChange: (event) => setBranch(event.target.value)
676
+ }), (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}`)))
677
+ });
678
+ }
679
+ //#endregion
680
+ //#region src/client/features/market/InstallConfirmModal.tsx
681
+ /** Pre-install confirmation modal: concise surface counts plus a risk notice. */
682
+ /** Surface count tags shown on the card; keys mirror SuiteCard's tag list. */
683
+ const SURFACE_TAGS = [
684
+ {
685
+ key: "skills",
686
+ labelKey: "surfaceSkills"
687
+ },
688
+ {
689
+ key: "mcp",
690
+ labelKey: "surfaceMcp"
691
+ },
692
+ {
693
+ key: "hooks",
694
+ labelKey: "surfaceHooks"
695
+ },
696
+ {
697
+ key: "commands",
698
+ labelKey: "surfaceCommands"
699
+ },
700
+ {
701
+ key: "agents",
702
+ labelKey: "surfaceAgents"
703
+ }
704
+ ];
705
+ function InstallConfirmModal(props) {
706
+ const { t, state, busy } = props;
707
+ const surfaces = state.suite.surfaces;
708
+ const tags = SURFACE_TAGS.filter((tag) => surfaces[tag.key] > 0);
709
+ const executable = surfaces.mcp > 0 || surfaces.hooks > 0;
710
+ return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
711
+ open: true,
712
+ onClose: props.onClose,
713
+ title: t("installConfirmTitle"),
714
+ description: t("installConfirmDesc"),
715
+ closeLabel: t("cancel"),
716
+ className: market_module_default.editorDialog,
717
+ footer: (0, react.createElement)("div", { className: market_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
718
+ variant: "ghost",
719
+ disabled: busy,
720
+ onClick: props.onClose
721
+ }, t("cancel")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
722
+ variant: "primary",
723
+ disabled: busy,
724
+ onClick: () => {
725
+ props.onConfirm();
726
+ }
727
+ }, t("installAndEnable"))),
728
+ children: (0, react.createElement)("div", { className: market_module_default.installConfirmBody }, (0, react.createElement)("div", { className: market_module_default.installConfirmSuite }, `${state.suite.sourceId} / ${state.suite.name}`), state.suite.version === void 0 ? null : (0, react.createElement)("div", { className: market_module_default.installConfirmMeta }, `${t("version")}: v${state.suite.version}`), tags.length === 0 ? (0, react.createElement)("div", { className: market_module_default.installConfirmMeta }, t("installConfirmNoSurfaces")) : (0, react.createElement)("div", { className: market_module_default.installConfirmTags }, tags.map((tag) => (0, react.createElement)("span", {
729
+ key: tag.key,
730
+ className: market_module_default.tag
731
+ }, `${t(tag.labelKey)} ${surfaces[tag.key]}`))), executable ? (0, react.createElement)("div", { className: market_module_default.installConfirmWarn }, t("installConfirmExecutable")) : null)
732
+ });
733
+ }
734
+ //#endregion
735
+ //#region src/client/ui/ToggleSwitch.tsx
736
+ /** Shared green/gray switch control used by suite cards. */
737
+ /** A green/gray switch control for suite enable state. */
738
+ function ToggleSwitch(props) {
739
+ return (0, react.createElement)("button", {
740
+ type: "button",
741
+ role: "switch",
742
+ "aria-checked": props.on,
743
+ title: props.title,
744
+ disabled: props.disabled,
745
+ className: props.on ? market_module_default.switchOn : market_module_default.switchOff,
746
+ onClick: (event) => {
747
+ event.stopPropagation();
748
+ props.onChange();
749
+ }
750
+ }, (0, react.createElement)("span", { className: market_module_default.switchThumb }));
751
+ }
752
+ //#endregion
753
+ //#region src/client/features/market/SuiteCard.tsx
754
+ /** A suite card in the market grid/list. */
755
+ function SuiteCard(props) {
756
+ const { t, suite, busy } = props;
757
+ const tags = [
758
+ [t("surfaceSkills"), suite.surfaces.skills],
759
+ [t("surfaceMcp"), suite.surfaces.mcp],
760
+ [t("surfaceHooks"), suite.surfaces.hooks],
761
+ [t("surfaceCommands"), suite.surfaces.commands],
762
+ [t("surfaceAgents"), suite.surfaces.agents],
763
+ [t("surfaceLsp"), suite.surfaces.lsp]
764
+ ].filter(([, count]) => count > 0);
765
+ const layoutLabel = suite.layout === "agent-plugin-v1" ? t("layoutV1") : suite.layout === "claude-code" ? t("layoutCC") : suite.layout === "codex" ? t("layoutCodex") : suite.layout === "universal" ? t("layoutUniversal") : suite.layout === "cursor" ? t("layoutCursor") : suite.layout === "kimi" ? t("layoutKimi") : suite.layout === "remote" ? t("layoutRemote") : suite.layout === "project-native" ? t("layoutProjectNative") : t("layoutSkills");
766
+ const isRemote = suite.remoteUrl !== void 0;
767
+ const stop = (callback) => (event) => {
768
+ event.stopPropagation();
769
+ callback();
770
+ };
771
+ return (0, react.createElement)("article", {
772
+ className: market_module_default.card,
773
+ onClick: props.onOpen
774
+ }, (0, react.createElement)("div", { className: market_module_default.cardTop }, (0, react.createElement)("div", { className: market_module_default.cardTitle }, (0, react.createElement)("span", { className: market_module_default.cardName }, suite.name), suite.version === void 0 ? null : (0, react.createElement)("span", { className: market_module_default.version }, `v${suite.version}`)), (0, react.createElement)("div", { className: market_module_default.cardActions }, suite.installed ? (0, react.createElement)(ToggleSwitch, {
775
+ on: suite.enabled,
776
+ disabled: busy,
777
+ title: suite.enabled ? t("disable") : t("enable"),
778
+ onChange: props.onToggle
779
+ }) : isRemote ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
780
+ variant: "primary",
781
+ size: "sm",
782
+ disabled: busy,
783
+ title: suite.remoteUrl,
784
+ onClick: stop(props.onAddSource)
785
+ }, t("addSource")) : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
786
+ variant: "primary",
787
+ size: "sm",
788
+ disabled: busy,
789
+ onClick: stop(props.onInstall)
790
+ }, t("install")), suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
791
+ variant: "ghost",
792
+ size: "sm",
793
+ title: t("refresh"),
794
+ disabled: busy,
795
+ onClick: stop(props.onRefresh)
796
+ }, "↻") : null, suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
797
+ variant: "ghost",
798
+ size: "sm",
799
+ title: t("uninstall"),
800
+ disabled: busy,
801
+ onClick: stop(props.onUninstall)
802
+ }, "🗑") : null)), (0, react.createElement)("p", { className: market_module_default.desc }, suite.description ?? ""), (0, react.createElement)("div", { className: market_module_default.meta }, (0, react.createElement)("span", { className: market_module_default.src }, `${suite.sourceId} · ${isRemote ? t("remoteRef") : suite.dimension === "user" ? t("dimensionUser") : t("dimensionProject")}`), (0, react.createElement)("span", { className: market_module_default.tag }, layoutLabel), suite.installed ? (0, react.createElement)("span", { className: suite.enabled ? market_module_default.okState : market_module_default.tag }, suite.enabled ? `✓ ${t("installedBadge")}` : t("installedBadge")) : null, ...tags.map(([label, count]) => (0, react.createElement)("span", {
803
+ key: label,
804
+ className: market_module_default.tag
805
+ }, `${label} ${count}`)), suite.errors.length === 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
806
+ label: suite.errors.slice(0, 8).join(t("sourceErrorSeparator")),
807
+ children: (0, react.createElement)("span", { className: market_module_default.warnLine }, `⚠ ${t("errors")} ${suite.errors.length}`)
808
+ }), (suite.mcpErrors?.length ?? 0) === 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
809
+ label: suite.mcpErrors.slice(0, 8).join(t("sourceErrorSeparator")),
810
+ children: (0, react.createElement)("span", { className: market_module_default.warnLine }, `⚠ ${t("mcpSection")} ${suite.mcpErrors.length}`)
811
+ })));
812
+ }
813
+ //#endregion
814
+ //#region src/client/ui/StatusIcon.tsx
815
+ /** Shared status icon used by market and MCP status filter tabs. */
816
+ /** An SVG status icon for the all/installed/uninstalled filter tabs. */
817
+ function StatusIcon({ kind }) {
818
+ const common = {
819
+ width: 16,
820
+ height: 16,
821
+ viewBox: "0 0 16 16",
822
+ fill: "none",
823
+ "aria-hidden": true
824
+ };
825
+ if (kind === "installed") return (0, react.createElement)("svg", common, (0, react.createElement)("circle", {
826
+ cx: 8,
827
+ cy: 8,
828
+ r: 5.5
829
+ }), (0, react.createElement)("path", { d: "m5.5 8 1.7 1.7 3.4-3.4" }));
830
+ if (kind === "uninstalled") return (0, react.createElement)("svg", common, (0, react.createElement)("path", { d: "M8 2v8m-3-3 3 3 3-3M3 13h10" }));
831
+ 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" }));
832
+ }
833
+ //#endregion
332
834
  //#region src/client/ErrorBoundary.tsx
333
835
  /**
334
836
  * Error boundary for untrusted preview content.
@@ -351,85 +853,18 @@ var ErrorBoundary = class extends react.Component {
351
853
  }
352
854
  };
353
855
  //#endregion
354
- //#region src/client/market.module.css
355
- var market_module_default = {
356
- "body": "qMtKNa_body",
357
- "card": "qMtKNa_card",
358
- "cardActions": "qMtKNa_cardActions",
359
- "cardDesc": "qMtKNa_cardDesc",
360
- "cardName": "qMtKNa_cardName",
361
- "cardTitle": "qMtKNa_cardTitle",
362
- "cardTop": "qMtKNa_cardTop",
363
- "desc": "qMtKNa_desc",
364
- "detailBody": "qMtKNa_detailBody",
365
- "detailCell": "qMtKNa_detailCell",
366
- "detailChevron": "qMtKNa_detailChevron",
367
- "detailDesc": "qMtKNa_detailDesc",
368
- "detailDialog": "qMtKNa_detailDialog",
369
- "detailGrid": "qMtKNa_detailGrid",
370
- "detailHead": "qMtKNa_detailHead",
371
- "detailItem": "qMtKNa_detailItem",
372
- "detailItemDesc": "qMtKNa_detailItemDesc",
373
- "detailItemName": "qMtKNa_detailItemName",
374
- "detailItemOpen": "qMtKNa_detailItemOpen",
375
- "detailItemRow": "qMtKNa_detailItemRow",
376
- "detailKey": "qMtKNa_detailKey",
377
- "detailSection": "qMtKNa_detailSection",
378
- "detailSections": "qMtKNa_detailSections",
379
- "detailValue": "qMtKNa_detailValue",
380
- "dshApmSpin": "qMtKNa_dshApmSpin",
381
- "editorDialog": "qMtKNa_editorDialog",
382
- "editorForm": "qMtKNa_editorForm",
383
- "empty": "qMtKNa_empty",
384
- "fieldGroup": "qMtKNa_fieldGroup",
385
- "fieldHint": "qMtKNa_fieldHint",
386
- "fieldLabel": "qMtKNa_fieldLabel",
387
- "grid": "qMtKNa_grid",
388
- "header": "qMtKNa_header",
389
- "list": "qMtKNa_list",
390
- "market": "qMtKNa_market",
391
- "marketControls": "qMtKNa_marketControls",
392
- "mcpSurface": "qMtKNa_mcpSurface",
393
- "meta": "qMtKNa_meta",
394
- "modalFooter": "qMtKNa_modalFooter",
395
- "modalFooterLeft": "qMtKNa_modalFooterLeft",
396
- "modeRow": "qMtKNa_modeRow",
397
- "mono": "qMtKNa_mono",
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",
407
- "searchGroup": "qMtKNa_searchGroup",
408
- "seg": "qMtKNa_seg",
409
- "segOn": "qMtKNa_segOn",
410
- "skillContent": "qMtKNa_skillContent",
411
- "sourceTabsRow": "qMtKNa_sourceTabsRow",
412
- "sourceTabsScroll": "qMtKNa_sourceTabsScroll",
413
- "spacer": "qMtKNa_spacer",
414
- "src": "qMtKNa_src",
415
- "srcTab": "qMtKNa_srcTab",
416
- "srcTabDel": "qMtKNa_srcTabDel",
417
- "srcTabEdit": "qMtKNa_srcTabEdit",
418
- "srcTabMain": "qMtKNa_srcTabMain",
419
- "srcTabOn": "qMtKNa_srcTabOn",
420
- "staticId": "qMtKNa_staticId",
421
- "staticIdValue": "qMtKNa_staticIdValue",
422
- "sub": "qMtKNa_sub",
423
- "surfaceSwitch": "qMtKNa_surfaceSwitch",
424
- "switchOff": "qMtKNa_switchOff",
425
- "switchOn": "qMtKNa_switchOn",
426
- "switchThumb": "qMtKNa_switchThumb",
427
- "tag": "qMtKNa_tag",
428
- "title": "qMtKNa_title",
429
- "titleRow": "qMtKNa_titleRow",
430
- "version": "qMtKNa_version",
431
- "warnLine": "qMtKNa_warnLine"
432
- };
856
+ //#region src/client/features/suite-detail/suite-detail-resource.ts
857
+ /** Create a request guard for one detail modal instance. */
858
+ function createLatestRequestGuard() {
859
+ let revision = 0;
860
+ return {
861
+ next: () => ++revision,
862
+ invalidate: () => {
863
+ revision++;
864
+ },
865
+ isCurrent: (requestId) => requestId === revision
866
+ };
867
+ }
433
868
  //#endregion
434
869
  //#region src/client/SuiteDetail.tsx
435
870
  /**
@@ -440,18 +875,30 @@ var market_module_default = {
440
875
  * mcp.json servers (each expands to its full config), command/subagent file
441
876
  * lists, hook/LSP counts, and validation diagnostics.
442
877
  */
878
+ /** Toggleable surface keys paired with their translation keys. */
879
+ const SURFACE_TOGGLE_ROWS = [
880
+ ["skills", "surfaceSkills"],
881
+ ["mcp", "surfaceMcp"],
882
+ ["hooks", "surfaceHooks"],
883
+ ["commands", "surfaceCommands"],
884
+ ["agents", "surfaceAgents"]
885
+ ];
443
886
  function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
444
887
  const [detail, setDetail] = (0, react.useState)(void 0);
445
888
  const [error, setError] = (0, react.useState)(void 0);
446
889
  const [openSkill, setOpenSkill] = (0, react.useState)(void 0);
447
890
  const [skillText, setSkillText] = (0, react.useState)(void 0);
448
891
  const [skillLoading, setSkillLoading] = (0, react.useState)(false);
892
+ const skillRequestGuard = (0, react.useRef)(createLatestRequestGuard());
449
893
  const [openMcp, setOpenMcp] = (0, react.useState)(void 0);
450
894
  const [openPreview, setOpenPreview] = (0, react.useState)(void 0);
451
895
  (0, react.useEffect)(() => {
452
896
  let cancelled = false;
897
+ skillRequestGuard.current.invalidate();
453
898
  setDetail(void 0);
454
899
  setError(void 0);
900
+ setOpenSkill(void 0);
901
+ setSkillText(void 0);
455
902
  fetchSuiteDetail(sourceId, suiteId).then((value) => {
456
903
  if (!cancelled) setDetail(value);
457
904
  }).catch((reason) => {
@@ -459,9 +906,11 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
459
906
  });
460
907
  return () => {
461
908
  cancelled = true;
909
+ skillRequestGuard.current.invalidate();
462
910
  };
463
911
  }, [sourceId, suiteId]);
464
912
  const toggleSkill = async (name) => {
913
+ const requestId = skillRequestGuard.current.next();
465
914
  if (openSkill === name) {
466
915
  setOpenSkill(void 0);
467
916
  return;
@@ -471,17 +920,53 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
471
920
  setSkillText(void 0);
472
921
  try {
473
922
  const content = await fetchSkillContent(sourceId, suiteId, name);
474
- setSkillText(content.content);
923
+ if (skillRequestGuard.current.isCurrent(requestId)) setSkillText(content.content);
924
+ } catch (reason) {
925
+ if (skillRequestGuard.current.isCurrent(requestId)) setSkillText(`⚠ ${reason instanceof Error ? reason.message : String(reason)}`);
926
+ } finally {
927
+ if (skillRequestGuard.current.isCurrent(requestId)) setSkillLoading(false);
928
+ }
929
+ };
930
+ const toggleMcp = (key) => {
931
+ setOpenMcp(openMcp === key ? void 0 : key);
932
+ };
933
+ const [surfaceBusy, setSurfaceBusy] = (0, react.useState)(false);
934
+ const toggleSurface = async (surface, enabled) => {
935
+ setSurfaceBusy(true);
936
+ try {
937
+ await postAction("set-surface", {
938
+ sourceId,
939
+ suiteId,
940
+ surface,
941
+ enabled
942
+ });
943
+ const next = await fetchSuiteDetail(sourceId, suiteId);
944
+ setDetail(next);
945
+ } catch (reason) {
946
+ setError(reason instanceof Error ? reason.message : String(reason));
947
+ } finally {
948
+ setSurfaceBusy(false);
949
+ }
950
+ };
951
+ /** Save or clear one server's MCP override, then refresh the detail. */
952
+ const saveMcpOverride = async (serverKey, patch) => {
953
+ setSurfaceBusy(true);
954
+ try {
955
+ await postAction("set-mcp-override", {
956
+ sourceId,
957
+ suiteId,
958
+ serverKey,
959
+ override: patch
960
+ });
961
+ const next = await fetchSuiteDetail(sourceId, suiteId);
962
+ setDetail(next);
475
963
  } catch (reason) {
476
- setSkillText(`⚠ ${reason instanceof Error ? reason.message : String(reason)}`);
964
+ setError(reason instanceof Error ? reason.message : String(reason));
477
965
  } finally {
478
- setSkillLoading(false);
966
+ setSurfaceBusy(false);
479
967
  }
480
968
  };
481
- const toggleMcp = (key) => {
482
- setOpenMcp(openMcp === key ? void 0 : key);
483
- };
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");
969
+ 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") : detail.layout === "project-native" ? t("layoutProjectNative") : t("layoutSkills");
485
970
  return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
486
971
  open: true,
487
972
  onClose,
@@ -496,7 +981,20 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
496
981
  }, t("cancel"))),
497
982
  children: (0, react.createElement)(ErrorBoundary, {
498
983
  fallback: (boundaryError) => (0, react.createElement)("div", { className: market_module_default.warnLine }, `${t("actionFail")}: ${boundaryError.message}`),
499
- children: error !== void 0 ? (0, react.createElement)("div", { className: market_module_default.warnLine }, error) : detail === void 0 ? (0, react.createElement)("div", { className: market_module_default.empty }, t("loading")) : (0, react.createElement)("div", { className: market_module_default.detailSections }, (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, t("overviewSection")), (0, react.createElement)("div", { className: market_module_default.detailGrid }, (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("sourceLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.sourceId)), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("dimensionLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.dimension === "user" ? t("dimensionUser") : t("dimensionProject"))), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("layoutLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, layoutLabel)), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("statusLabel")), (0, react.createElement)("span", { className: detail.enabled ? market_module_default.okState : market_module_default.detailValue }, detail.installed ? detail.enabled ? t("installedBadge") : t("disabledLabel") : t("notInstalledLabel"))), detail.author === null ? null : (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("authorLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.author)), detail.keywords.length === 0 ? null : (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("keywordsLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.keywords.join(", ")))), detail.description === null ? null : (0, react.createElement)("p", { className: market_module_default.detailDesc }, detail.description), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("rootLabel")), (0, react.createElement)("span", { className: market_module_default.mono }, detail.root))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("skillsSection")} (${detail.skills.length})`), detail.skills.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.skills.map((skill) => (0, react.createElement)("div", {
984
+ children: error !== void 0 ? (0, react.createElement)("div", { className: market_module_default.warnLine }, error) : detail === void 0 ? (0, react.createElement)("div", { className: market_module_default.empty }, t("loading")) : (0, react.createElement)("div", { className: market_module_default.detailSections }, (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, t("overviewSection")), (0, react.createElement)("div", { className: market_module_default.detailGrid }, (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("sourceLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.sourceId)), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("dimensionLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.dimension === "user" ? t("dimensionUser") : t("dimensionProject"))), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("layoutLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, layoutLabel)), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("statusLabel")), (0, react.createElement)("span", { className: detail.enabled ? market_module_default.okState : market_module_default.detailValue }, detail.installed ? detail.enabled ? t("installedBadge") : t("disabledLabel") : t("notInstalledLabel"))), detail.author === null ? null : (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("authorLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.author)), detail.keywords.length === 0 ? null : (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("keywordsLabel")), (0, react.createElement)("span", { className: market_module_default.detailValue }, detail.keywords.join(", ")))), detail.description === null ? null : (0, react.createElement)("p", { className: market_module_default.detailDesc }, detail.description), (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("rootLabel")), (0, react.createElement)("span", { className: market_module_default.mono }, detail.root)), detail.installed === false || detail.surfaceToggles === null ? null : (0, react.createElement)("div", { className: market_module_default.detailCell }, (0, react.createElement)("span", { className: market_module_default.detailKey }, t("surfaceTogglesSection")), (0, react.createElement)("div", {
985
+ className: market_module_default.surfaceToggles,
986
+ title: t("surfaceTogglesHint")
987
+ }, ...SURFACE_TOGGLE_ROWS.map(([key, labelKey]) => (0, react.createElement)("label", {
988
+ key,
989
+ className: market_module_default.surfaceToggle
990
+ }, (0, react.createElement)("input", {
991
+ type: "checkbox",
992
+ checked: detail.surfaceToggles[key],
993
+ disabled: surfaceBusy,
994
+ onChange: (event) => {
995
+ toggleSurface(key, event.target.checked);
996
+ }
997
+ }), t(labelKey)))))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("skillsSection")} (${detail.skills.length})`), detail.skills.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.skills.map((skill) => (0, react.createElement)("div", {
500
998
  key: skill.name,
501
999
  className: market_module_default.detailItem
502
1000
  }, (0, react.createElement)("button", {
@@ -508,14 +1006,27 @@ function SuiteDetailModal({ t, sourceId, suiteId, onClose }) {
508
1006
  }, (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
1007
  className: market_module_default.warnLine,
510
1008
  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", {
512
- key: server.key,
513
- className: market_module_default.detailItem
514
- }, (0, react.createElement)("button", {
515
- type: "button",
516
- className: openMcp === server.key ? market_module_default.detailItemOpen : market_module_default.detailItemRow,
517
- onClick: () => toggleMcp(server.key)
518
- }, (0, react.createElement)("span", { className: market_module_default.detailItemName }, server.key), (0, react.createElement)("span", { className: market_module_default.detailItemDesc }, mcpSummary(server)), (0, react.createElement)("span", { className: market_module_default.detailChevron }, openMcp === server.key ? "▾" : "▸")), openMcp !== server.key ? null : (0, react.createElement)("pre", { className: market_module_default.mono }, JSON.stringify(server, null, 2))))), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("commandsSection")} (${detail.commands.length})`), detail.commands.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.commands.map((command) => (0, react.createElement)(PreviewRow, {
1009
+ }, `⚠ ${detail.mcpErrors.join(t("sourceErrorSeparator"))}`), detail.mcpServers.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.mcpServers.map((server) => {
1010
+ const override = detail.mcpOverrides?.[server.key];
1011
+ const overridden = override !== void 0 && Object.keys(override).length > 0;
1012
+ const disabled = override?.enabled === false;
1013
+ return (0, react.createElement)("div", {
1014
+ key: server.key,
1015
+ className: market_module_default.detailItem
1016
+ }, (0, react.createElement)("button", {
1017
+ type: "button",
1018
+ className: openMcp === server.key ? market_module_default.detailItemOpen : market_module_default.detailItemRow,
1019
+ onClick: () => toggleMcp(server.key)
1020
+ }, (0, react.createElement)("span", { className: market_module_default.detailItemName }, server.key), (0, react.createElement)("span", { className: market_module_default.detailItemDesc }, `${mcpSummary(server)}${disabled ? ` · ${t("mcpOverrideDisabledBadge")}` : overridden ? ` · ${t("mcpOverriddenBadge")}` : ""}`), (0, react.createElement)("span", { className: market_module_default.detailChevron }, openMcp === server.key ? "▾" : "▸")), openMcp === server.key ? (0, react.createElement)("div", { className: market_module_default.skillContent }, detail.installed && detail.surfaceToggles?.mcp !== false ? (0, react.createElement)(McpOverrideEditor, {
1021
+ t,
1022
+ serverKey: server.key,
1023
+ transport: server.type,
1024
+ override: override ?? {},
1025
+ busy: surfaceBusy,
1026
+ onSave: (patch) => saveMcpOverride(server.key, patch),
1027
+ onReset: () => saveMcpOverride(server.key, null)
1028
+ }) : null, (0, react.createElement)("pre", { className: market_module_default.mono }, JSON.stringify(server, null, 2))) : null);
1029
+ })), (0, react.createElement)("section", { className: market_module_default.detailSection }, (0, react.createElement)("h4", { className: market_module_default.detailHead }, `${t("commandsSection")} (${detail.commands.length})`), detail.commands.length === 0 ? (0, react.createElement)("div", { className: market_module_default.sidebarEmpty }, "—") : detail.commands.map((command) => (0, react.createElement)(PreviewRow, {
519
1030
  key: `c:${command.name}`,
520
1031
  t,
521
1032
  name: `/${command.name}`,
@@ -557,8 +1068,110 @@ function mcpSummary(server) {
557
1068
  if (server.type === "stdio") return server.command ?? server.type;
558
1069
  return server.url ?? server.type;
559
1070
  }
1071
+ /** Parse `KEY=VALUE` lines into a record; blank and comment lines are skipped. */
1072
+ function parseKvLines(text) {
1073
+ const result = {};
1074
+ for (const line of text.split("\n")) {
1075
+ const trimmed = line.trim();
1076
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
1077
+ const eq = trimmed.indexOf("=");
1078
+ if (eq <= 0) continue;
1079
+ result[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim();
1080
+ }
1081
+ return Object.keys(result).length > 0 ? result : void 0;
1082
+ }
1083
+ /** Format a record back into sorted `KEY=VALUE` lines for editing. */
1084
+ function formatKvLines(map) {
1085
+ if (map === void 0) return "";
1086
+ return Object.keys(map).sort().map((key) => `${key}=${map[key]}`).join("\n");
1087
+ }
1088
+ /**
1089
+ * Per-server MCP override editor: enable/disable plus connection-input
1090
+ * replacement (url/headers for http servers, args/env for stdio). The
1091
+ * suite's own mcp.json stays source-owned; everything here persists as a
1092
+ * user override layered on top at mount time.
1093
+ */
1094
+ function McpOverrideEditor(props) {
1095
+ const { t, transport, override, busy } = props;
1096
+ const [draft, setDraft] = (0, react.useState)(override);
1097
+ const kvHint = t("mcpOverrideKvHint");
1098
+ const isHttp = transport !== "stdio";
1099
+ /** Gather the draft fields into one sanitized override patch and save it. */
1100
+ const submit = () => {
1101
+ const patch = {};
1102
+ patch["enabled"] = draft["enabled"] !== false;
1103
+ if (isHttp && typeof draft["url"] === "string" && draft["url"] !== "") patch["url"] = draft["url"];
1104
+ const headers = parseKvLines(isHttp ? String(draft["__headers"] ?? "") : "");
1105
+ if (headers !== void 0) patch["headers"] = headers;
1106
+ const env = parseKvLines(!isHttp ? String(draft["__env"] ?? "") : "");
1107
+ if (env !== void 0) patch["env"] = env;
1108
+ const args = (!isHttp ? String(draft["__args"] ?? "") : "").split("\n").map((line) => line.trim()).filter((line) => line !== "");
1109
+ if (args.length > 0) patch["args"] = args;
1110
+ props.onSave(patch);
1111
+ };
1112
+ return (0, react.createElement)("div", { className: market_module_default.mcpOverrideForm }, (0, react.createElement)("label", { className: market_module_default.mcpOverrideCheck }, (0, react.createElement)("input", {
1113
+ type: "checkbox",
1114
+ checked: draft["enabled"] !== false,
1115
+ disabled: busy,
1116
+ onChange: (event) => setDraft({
1117
+ ...draft,
1118
+ enabled: event.target.checked
1119
+ })
1120
+ }), t("mcpOverrideEnabled")), isHttp ? (0, react.createElement)("input", {
1121
+ className: market_module_default.mcpOverrideInput,
1122
+ value: typeof draft["url"] === "string" ? draft["url"] : "",
1123
+ placeholder: t("mcpOverrideUrlLabel"),
1124
+ disabled: busy,
1125
+ onChange: (event) => setDraft({
1126
+ ...draft,
1127
+ url: event.target.value
1128
+ })
1129
+ }) : null, isHttp ? (0, react.createElement)("textarea", {
1130
+ className: market_module_default.mcpOverrideArea,
1131
+ rows: 3,
1132
+ placeholder: t("mcpOverrideHeadersLabel"),
1133
+ title: kvHint,
1134
+ value: typeof draft["__headers"] === "string" ? draft["__headers"] : formatKvLines(override["headers"]),
1135
+ disabled: busy,
1136
+ onChange: (event) => setDraft({
1137
+ ...draft,
1138
+ __headers: event.target.value
1139
+ })
1140
+ }) : null, !isHttp ? (0, react.createElement)("textarea", {
1141
+ className: market_module_default.mcpOverrideArea,
1142
+ rows: 3,
1143
+ placeholder: t("mcpOverrideEnvLabel"),
1144
+ title: kvHint,
1145
+ value: typeof draft["__env"] === "string" ? draft["__env"] : formatKvLines(override["env"]),
1146
+ disabled: busy,
1147
+ onChange: (event) => setDraft({
1148
+ ...draft,
1149
+ __env: event.target.value
1150
+ })
1151
+ }) : null, !isHttp ? (0, react.createElement)("textarea", {
1152
+ className: market_module_default.mcpOverrideArea,
1153
+ rows: 3,
1154
+ placeholder: t("mcpOverrideArgsLabel"),
1155
+ value: typeof draft["__args"] === "string" ? draft["__args"] : Array.isArray(override["args"]) ? override["args"].join("\n") : "",
1156
+ disabled: busy,
1157
+ onChange: (event) => setDraft({
1158
+ ...draft,
1159
+ __args: event.target.value
1160
+ })
1161
+ }) : null, (0, react.createElement)("div", { className: market_module_default.mcpOverrideActions }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1162
+ variant: "primary",
1163
+ size: "sm",
1164
+ disabled: busy,
1165
+ onClick: submit
1166
+ }, t("mcpOverrideSave")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1167
+ variant: "ghost",
1168
+ size: "sm",
1169
+ disabled: busy,
1170
+ onClick: () => void props.onReset()
1171
+ }, t("mcpOverrideReset"))), (0, react.createElement)("div", { className: market_module_default.detailItemDesc }, kvHint));
1172
+ }
560
1173
  function PreviewRow(props) {
561
- const { t: _t, name, description, open, onToggle, children } = props;
1174
+ const { name, description, open, onToggle, children } = props;
562
1175
  return (0, react.createElement)("div", { className: market_module_default.detailItem }, (0, react.createElement)("button", {
563
1176
  type: "button",
564
1177
  className: open ? market_module_default.detailItemOpen : market_module_default.detailItemRow,
@@ -568,14 +1181,14 @@ function PreviewRow(props) {
568
1181
  //#endregion
569
1182
  //#region src/client/SearchFilterToolbar.module.css
570
1183
  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"
1184
+ "filter": "vavGuW_filter",
1185
+ "filterCount": "vavGuW_filterCount",
1186
+ "filterGap": "vavGuW_filterGap",
1187
+ "filterOn": "vavGuW_filterOn",
1188
+ "search": "vavGuW_search",
1189
+ "toolbar": "vavGuW_toolbar",
1190
+ "viewGap": "vavGuW_viewGap",
1191
+ "viewSwitch": "vavGuW_viewSwitch"
579
1192
  };
580
1193
  //#endregion
581
1194
  //#region src/client/SearchFilterToolbar.tsx
@@ -661,77 +1274,17 @@ const PROGRESS_STEP_LABELS = {
661
1274
  cloning: "progressCloning",
662
1275
  reading: "progressReading"
663
1276
  };
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;
1277
+ function progressStepLabel(t, step) {
1278
+ const key = PROGRESS_STEP_LABELS[step];
1279
+ return key === void 0 ? step : t(key);
689
1280
  }
690
1281
  /** Keep parameterized copy compatible with hosts whose bound translator ignores params. */
691
1282
  function interpolate(text, params) {
692
1283
  return text.replace(/\{(\w+)\}/g, (match, key) => key in params ? String(params[key]) : match);
693
1284
  }
694
- const EMPTY_OVERVIEW = {
695
- sources: [],
696
- suites: [],
697
- totals: {
698
- all: 0,
699
- installed: 0,
700
- enabled: 0
701
- },
702
- roots: {
703
- user: "",
704
- data: ""
705
- }
706
- };
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
1285
  function MarketSection({ t, mode = "settings" }) {
733
1286
  const [overview, setOverview] = (0, react.useState)(() => loadOverview().initial);
734
- const [loading, setLoading] = (0, react.useState)(() => cachedOverview === void 0);
1287
+ const [loading, setLoading] = (0, react.useState)(() => loadOverview().revalidating);
735
1288
  const [search, setSearch] = (0, react.useState)("");
736
1289
  const [tab, setTab] = (0, react.useState)("all");
737
1290
  const [category, setCategory] = (0, react.useState)("all");
@@ -739,6 +1292,7 @@ function MarketSection({ t, mode = "settings" }) {
739
1292
  const [busy, setBusy] = (0, react.useState)(void 0);
740
1293
  const [toast, setToast] = (0, react.useState)(void 0);
741
1294
  const [confirm, setConfirm] = (0, react.useState)(void 0);
1295
+ const [installConfirm, setInstallConfirm] = (0, react.useState)(void 0);
742
1296
  const [editor, setEditor] = (0, react.useState)(void 0);
743
1297
  const [detail, setDetail] = (0, react.useState)(void 0);
744
1298
  const [progress, setProgress] = (0, react.useState)({
@@ -746,7 +1300,7 @@ function MarketSection({ t, mode = "settings" }) {
746
1300
  error: void 0
747
1301
  });
748
1302
  const refresh = (0, react.useCallback)(async () => {
749
- dropCachedOverview();
1303
+ invalidateOverview();
750
1304
  try {
751
1305
  const data = await loadOverview().promise;
752
1306
  setOverview(data);
@@ -766,7 +1320,7 @@ function MarketSection({ t, mode = "settings" }) {
766
1320
  setBusy(key);
767
1321
  try {
768
1322
  await postAction(path, body);
769
- dropCachedOverview();
1323
+ invalidateOverview();
770
1324
  await refresh();
771
1325
  return true;
772
1326
  } catch (error) {
@@ -779,25 +1333,7 @@ function MarketSection({ t, mode = "settings" }) {
779
1333
  setBusy(void 0);
780
1334
  }
781
1335
  }, [refresh, t]);
782
- const scopeTotals = (0, react.useMemo)(() => {
783
- if (category === "all") return overview.totals;
784
- const scoped = overview.suites.filter((suite) => suite.sourceId === category);
785
- return {
786
- all: scoped.length,
787
- installed: scoped.filter((suite) => suite.installed).length,
788
- enabled: scoped.filter((suite) => suite.enabled).length
789
- };
790
- }, [overview, category]);
791
- const filtered = (0, react.useMemo)(() => {
792
- const needle = search.trim().toLowerCase();
793
- return overview.suites.filter((suite) => {
794
- if (category !== "all" && suite.sourceId !== category) return false;
795
- if (tab === "installed" && !suite.installed) return false;
796
- if (tab === "uninstalled" && suite.installed) return false;
797
- if (needle === "") return true;
798
- return `${suite.name} ${suite.description ?? ""} ${suite.keywords.join(" ")}`.toLowerCase().includes(needle);
799
- });
800
- }, [
1336
+ const { scopeTotals, filtered } = (0, react.useMemo)(() => deriveMarketViewModel(overview, search, tab, category), [
801
1337
  overview,
802
1338
  search,
803
1339
  tab,
@@ -906,10 +1442,7 @@ function MarketSection({ t, mode = "settings" }) {
906
1442
  suiteId: suite.suiteId
907
1443
  }),
908
1444
  onInstall: () => {
909
- action(`i:${suite.suiteId}`, "install", {
910
- sourceId: suite.sourceId,
911
- suiteId: suite.suiteId
912
- });
1445
+ setInstallConfirm({ suite });
913
1446
  },
914
1447
  onAddSource: () => {
915
1448
  if (suite.remoteUrl !== void 0) action(`a:${suite.suiteId}`, "sources/add", { url: suite.remoteUrl });
@@ -929,6 +1462,19 @@ function MarketSection({ t, mode = "settings" }) {
929
1462
  key: toast.key,
930
1463
  text: toast.message,
931
1464
  onDone: () => setToast(void 0)
1465
+ }), installConfirm === void 0 ? null : (0, react.createElement)(InstallConfirmModal, {
1466
+ t,
1467
+ state: installConfirm,
1468
+ busy: busy !== void 0,
1469
+ onClose: () => setInstallConfirm(void 0),
1470
+ onConfirm: async () => {
1471
+ const ok = await action(`i:${installConfirm.suite.suiteId}`, "install", {
1472
+ sourceId: installConfirm.suite.sourceId,
1473
+ suiteId: installConfirm.suite.suiteId
1474
+ });
1475
+ if (ok) setInstallConfirm(void 0);
1476
+ return ok;
1477
+ }
932
1478
  }), confirm === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
933
1479
  open: true,
934
1480
  onClose: () => setConfirm(void 0),
@@ -968,10 +1514,10 @@ function MarketSection({ t, mode = "settings" }) {
968
1514
  step: t("progressStarting"),
969
1515
  error: void 0
970
1516
  });
971
- const poll = startProgressPolling(setProgress);
1517
+ const poll = startSourceProgressPolling(setProgress, (step) => progressStepLabel(t, step));
972
1518
  try {
973
1519
  const derived = (await postAction("sources/add", body))["source"]?.id;
974
- dropCachedOverview();
1520
+ invalidateOverview();
975
1521
  await refresh();
976
1522
  setEditor(void 0);
977
1523
  if (derived !== void 0) setCategory(derived);
@@ -1008,226 +1554,113 @@ function MarketSection({ t, mode = "settings" }) {
1008
1554
  }))
1009
1555
  });
1010
1556
  }
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
1557
+ //#endregion
1558
+ //#region src/client/features/mcp-status/mcp-status-view-model.ts
1559
+ const searchableCache = /* @__PURE__ */ new WeakMap();
1560
+ /** Derive active rows, filter counts, and visible rows in one pass. */
1561
+ function deriveMcpStatusViewModel(payload, filter, search) {
1562
+ const searchable = searchableFor(payload);
1563
+ const activeEntries = searchable.map((item) => item.entry);
1564
+ const filterCounts = {
1565
+ all: 0,
1566
+ plugin: 0,
1567
+ direct: 0
1018
1568
  };
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" }));
1026
- }
1027
- /** A source tab with a trailing delete control (deletion confirms at the section level). */
1028
- function SourceTab(props) {
1029
- const { t, active = false, label, onSelect, onDelete, onEdit } = props;
1030
- return (0, react.createElement)("div", { className: active ? market_module_default.srcTabOn : market_module_default.srcTab }, (0, react.createElement)("button", {
1031
- type: "button",
1032
- className: market_module_default.srcTabMain,
1033
- onClick: onSelect
1034
- }, label), onEdit === void 0 ? null : (0, react.createElement)("button", {
1035
- type: "button",
1036
- className: market_module_default.srcTabEdit,
1037
- title: t("editSource"),
1038
- onClick: (event) => {
1039
- event.stopPropagation();
1040
- onEdit();
1041
- }
1042
- }, "✎"), onDelete === void 0 ? null : (0, react.createElement)("button", {
1043
- type: "button",
1044
- className: market_module_default.srcTabDel,
1045
- title: t("remove"),
1046
- onClick: (event) => {
1047
- event.stopPropagation();
1048
- onDelete();
1049
- }
1050
- }, "×"));
1051
- }
1052
- function SourceEditorModal(props) {
1053
- const { t, editor } = props;
1054
- const [local, setLocal] = (0, react.useState)(editor.mode === "edit" && editor.source.local === true);
1055
- const [url, setUrl] = (0, react.useState)(editor.mode === "edit" ? editor.source.url : "");
1056
- const [branch, setBranch] = (0, react.useState)(editor.mode === "edit" ? editor.source.branch ?? "" : "");
1057
- const id = editor.mode === "edit" ? editor.source.id : "";
1058
- const title = editor.mode === "edit" ? t("editSourceTitle") : t("addSourceTitle");
1059
- return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
1060
- open: true,
1061
- onClose: props.onClose,
1062
- title,
1063
- description: t("editorHint"),
1064
- closeLabel: t("cancel"),
1065
- className: market_module_default.editorDialog,
1066
- footer: (0, react.createElement)("div", { className: market_module_default.modalFooter }, (0, react.createElement)("div", { className: market_module_default.modalFooterLeft }, editor.mode === "edit" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1067
- variant: "ghost",
1068
- onClick: () => props.onRemove(id)
1069
- }, `🗑 ${t("remove")}`) : null), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1070
- variant: "ghost",
1071
- onClick: props.onClose
1072
- }, t("cancel")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1073
- variant: "primary",
1074
- disabled: props.busy,
1075
- onClick: () => {
1076
- props.onSave(url.trim(), branch.trim(), local);
1077
- }
1078
- }, t("save"))),
1079
- children: (0, react.createElement)("div", { className: market_module_default.editorForm }, (0, react.createElement)("div", { className: market_module_default.modeRow }, (0, react.createElement)("button", {
1080
- type: "button",
1081
- className: local ? market_module_default.seg : market_module_default.segOn,
1082
- onClick: () => setLocal(false)
1083
- }, t("sourceModeGit")), (0, react.createElement)("button", {
1084
- type: "button",
1085
- className: local ? market_module_default.segOn : market_module_default.seg,
1086
- onClick: () => setLocal(true)
1087
- }, t("sourceModeLocal"))), editor.mode === "edit" ? (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, t("sourceIdPh")), (0, react.createElement)("div", { className: market_module_default.staticId }, (0, react.createElement)("span", { className: market_module_default.staticIdValue }, id), (0, react.createElement)("span", { className: market_module_default.fieldHint }, t("idFixed")))) : null, (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, local ? t("sourceUrlLocalPh") : t("sourceUrlPh")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
1088
- placeholder: local ? t("sourceUrlLocalPh") : t("sourceUrlPh"),
1089
- value: url,
1090
- onChange: (event) => setUrl(event.target.value)
1091
- }), (0, react.createElement)("span", { className: market_module_default.fieldHint }, local ? t("urlLocalHint") : t("urlGitHint"))), local ? null : (0, react.createElement)("div", { className: market_module_default.fieldGroup }, (0, react.createElement)("label", { className: market_module_default.fieldLabel }, t("branchPh")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
1092
- placeholder: t("branchPh"),
1093
- value: branch,
1094
- onChange: (event) => setBranch(event.target.value)
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}`)))
1096
- });
1097
- }
1098
- /** A green/gray switch control for suite enable state. */
1099
- function ToggleSwitch(props) {
1100
- return (0, react.createElement)("button", {
1101
- type: "button",
1102
- role: "switch",
1103
- "aria-checked": props.on,
1104
- title: props.title,
1105
- disabled: props.disabled,
1106
- className: props.on ? market_module_default.switchOn : market_module_default.switchOff,
1107
- onClick: (event) => {
1108
- event.stopPropagation();
1109
- props.onChange();
1569
+ let connected = 0;
1570
+ let failed = 0;
1571
+ const filtered = [];
1572
+ const needle = search.trim().toLowerCase();
1573
+ for (const item of searchable) {
1574
+ const entry = item.entry;
1575
+ filterCounts.all++;
1576
+ filterCounts[entry.kind]++;
1577
+ if (entry.state === "connected") connected++;
1578
+ if (entry.state === "failed") failed++;
1579
+ if (filter !== "all" && entry.kind !== filter) continue;
1580
+ if (needle !== "" && !item.haystack.includes(needle)) continue;
1581
+ filtered.push(entry);
1582
+ }
1583
+ return {
1584
+ activeEntries,
1585
+ filtered,
1586
+ filterCounts,
1587
+ visibleTotals: {
1588
+ all: activeEntries.length,
1589
+ connected,
1590
+ failed
1110
1591
  }
1111
- }, (0, react.createElement)("span", { className: market_module_default.switchThumb }));
1112
- }
1113
- function SuiteCard(props) {
1114
- const { t, suite, busy } = props;
1115
- const tags = [
1116
- [t("surfaceSkills"), suite.surfaces.skills],
1117
- [t("surfaceMcp"), suite.surfaces.mcp],
1118
- [t("surfaceHooks"), suite.surfaces.hooks],
1119
- [t("surfaceCommands"), suite.surfaces.commands],
1120
- [t("surfaceAgents"), suite.surfaces.agents],
1121
- [t("surfaceLsp"), suite.surfaces.lsp]
1122
- ].filter(([, count]) => count > 0);
1123
- const layoutLabel = suite.layout === "agent-plugin-v1" ? t("layoutV1") : suite.layout === "claude-code" ? t("layoutCC") : suite.layout === "codex" ? t("layoutCodex") : suite.layout === "universal" ? t("layoutUniversal") : suite.layout === "cursor" ? t("layoutCursor") : suite.layout === "kimi" ? t("layoutKimi") : suite.layout === "remote" ? t("layoutRemote") : t("layoutSkills");
1124
- const isRemote = suite.remoteUrl !== void 0;
1125
- const stop = (callback) => (event) => {
1126
- event.stopPropagation();
1127
- callback();
1128
1592
  };
1129
- return (0, react.createElement)("article", {
1130
- className: market_module_default.card,
1131
- onClick: props.onOpen
1132
- }, (0, react.createElement)("div", { className: market_module_default.cardTop }, (0, react.createElement)("div", { className: market_module_default.cardTitle }, (0, react.createElement)("span", { className: market_module_default.cardName }, suite.name), suite.version === void 0 ? null : (0, react.createElement)("span", { className: market_module_default.version }, `v${suite.version}`)), (0, react.createElement)("div", { className: market_module_default.cardActions }, suite.installed ? (0, react.createElement)(ToggleSwitch, {
1133
- on: suite.enabled,
1134
- disabled: busy,
1135
- title: suite.enabled ? t("disable") : t("enable"),
1136
- onChange: props.onToggle
1137
- }) : isRemote ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1138
- variant: "primary",
1139
- size: "sm",
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,
1147
- onClick: stop(props.onInstall)
1148
- }, t("install")), suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1149
- variant: "ghost",
1150
- size: "sm",
1151
- title: t("refresh"),
1152
- disabled: busy,
1153
- onClick: stop(props.onRefresh)
1154
- }, "↻") : null, suite.installed ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1155
- variant: "ghost",
1156
- size: "sm",
1157
- title: t("uninstall"),
1158
- disabled: busy,
1159
- onClick: stop(props.onUninstall)
1160
- }, "🗑") : null)), (0, react.createElement)("p", { className: market_module_default.desc }, suite.description ?? ""), (0, react.createElement)("div", { className: market_module_default.meta }, (0, react.createElement)("span", { className: market_module_default.src }, `${suite.sourceId} · ${isRemote ? t("remoteRef") : suite.dimension === "user" ? t("dimensionUser") : t("dimensionProject")}`), (0, react.createElement)("span", { className: market_module_default.tag }, layoutLabel), suite.installed ? (0, react.createElement)("span", { className: suite.enabled ? market_module_default.okState : market_module_default.tag }, suite.enabled ? `✓ ${t("installedBadge")}` : t("installedBadge")) : null, ...tags.map(([label, count]) => (0, react.createElement)("span", {
1161
- key: label,
1162
- className: market_module_default.tag
1163
- }, `${label} ${count}`)), suite.errors.length === 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
1164
- label: suite.errors.slice(0, 8).join(t("sourceErrorSeparator")),
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}`)
1169
- })));
1593
+ }
1594
+ function searchableFor(payload) {
1595
+ const cached = searchableCache.get(payload);
1596
+ if (cached !== void 0) return cached;
1597
+ const searchable = payload.entries.filter((entry) => entry.state !== "disabled").map((entry) => ({
1598
+ entry,
1599
+ haystack: `${entry.name} ${entry.source ?? ""} ${entry.endpoint ?? ""} ${entry.transport}`.toLowerCase()
1600
+ }));
1601
+ searchableCache.set(payload, searchable);
1602
+ return searchable;
1170
1603
  }
1171
1604
  //#endregion
1172
1605
  //#region src/client/mcp-status.module.css
1173
1606
  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"
1607
+ "boundary": "AUWlZW_boundary",
1608
+ "card": "AUWlZW_card",
1609
+ "cardReason": "AUWlZW_cardReason",
1610
+ "cardTop": "AUWlZW_cardTop",
1611
+ "chevron": "AUWlZW_chevron",
1612
+ "config": "AUWlZW_config",
1613
+ "detail": "AUWlZW_detail",
1614
+ "detailBody": "AUWlZW_detailBody",
1615
+ "detailDialog": "AUWlZW_detailDialog",
1616
+ "detailEmpty": "AUWlZW_detailEmpty",
1617
+ "detailHead": "AUWlZW_detailHead",
1618
+ "detailMeta": "AUWlZW_detailMeta",
1619
+ "detailSection": "AUWlZW_detailSection",
1620
+ "detailState": "AUWlZW_detailState",
1621
+ "detailStateconnected": "AUWlZW_detailStateconnected",
1622
+ "detailStatedegraded": "AUWlZW_detailStatedegraded",
1623
+ "detailStatedisabled": "AUWlZW_detailStatedisabled",
1624
+ "detailStatefailed": "AUWlZW_detailStatefailed",
1625
+ "empty": "AUWlZW_empty",
1626
+ "endpoint": "AUWlZW_endpoint",
1627
+ "error": "AUWlZW_error",
1628
+ "errorSummary": "AUWlZW_errorSummary",
1629
+ "grid": "AUWlZW_grid",
1630
+ "header": "AUWlZW_header",
1631
+ "headerActions": "AUWlZW_headerActions",
1632
+ "list": "AUWlZW_list",
1633
+ "meta": "AUWlZW_meta",
1634
+ "modalFooter": "AUWlZW_modalFooter",
1635
+ "name": "AUWlZW_name",
1636
+ "reason": "AUWlZW_reason",
1637
+ "service": "AUWlZW_service",
1638
+ "sourceDirect": "AUWlZW_sourceDirect",
1639
+ "sourcePlugin": "AUWlZW_sourcePlugin",
1640
+ "state": "AUWlZW_state",
1641
+ "stateconnected": "AUWlZW_stateconnected",
1642
+ "statedegraded": "AUWlZW_statedegraded",
1643
+ "statedisabled": "AUWlZW_statedisabled",
1644
+ "statefailed": "AUWlZW_statefailed",
1645
+ "statusconnected": "AUWlZW_statusconnected",
1646
+ "statusdegraded": "AUWlZW_statusdegraded",
1647
+ "statusdisabled": "AUWlZW_statusdisabled",
1648
+ "statusDot": "AUWlZW_statusDot",
1649
+ "statusfailed": "AUWlZW_statusfailed",
1650
+ "subtitle": "AUWlZW_subtitle",
1651
+ "summary": "AUWlZW_summary",
1652
+ "summaryDotGreen": "AUWlZW_summaryDotGreen",
1653
+ "summaryDotRed": "AUWlZW_summaryDotRed",
1654
+ "surface": "AUWlZW_surface",
1655
+ "title": "AUWlZW_title",
1656
+ "tool": "AUWlZW_tool",
1657
+ "toolbar": "AUWlZW_toolbar",
1658
+ "toolCount": "AUWlZW_toolCount",
1659
+ "toolDescription": "AUWlZW_toolDescription",
1660
+ "toolIndex": "AUWlZW_toolIndex",
1661
+ "toolList": "AUWlZW_toolList",
1662
+ "toolName": "AUWlZW_toolName",
1663
+ "transport": "AUWlZW_transport"
1231
1664
  };
1232
1665
  //#endregion
1233
1666
  //#region src/client/McpStatusPanel.tsx
@@ -1262,24 +1695,7 @@ function McpStatusPanel({ t }) {
1262
1695
  (0, react.useEffect)(() => {
1263
1696
  refresh();
1264
1697
  }, []);
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
- ]);
1698
+ const { activeEntries, filtered, filterCounts, visibleTotals } = deriveMcpStatusViewModel(payload, filter, search);
1283
1699
  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
1700
  className: mcp_status_module_default.errorSummary,
1285
1701
  title: `${visibleTotals.failed} ${t("mcpFailed")}`
@@ -1302,7 +1718,7 @@ function McpStatusPanel({ t }) {
1302
1718
  ].map((kind) => ({
1303
1719
  id: kind,
1304
1720
  label: filterLabel(t, kind),
1305
- count: kind === "all" ? visibleTotals.all : activeEntries.filter((entry) => entry.kind === kind).length,
1721
+ count: filterCounts[kind],
1306
1722
  icon: (0, react.createElement)(McpFilterIcon, { kind }),
1307
1723
  active: filter === kind,
1308
1724
  onSelect: () => setFilter(kind)