dsh-agent-plugins-market 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -26
- package/README.zh.md +39 -26
- package/client/client.js +1214 -181
- package/client/client.js.map +1 -1
- package/lib/application/catalog.js +23 -4
- package/lib/application/install-store.js +1 -1
- package/lib/application/mcp-service.js +185 -30
- package/lib/catalog/archive.js +15 -0
- package/lib/catalog/component-files.js +3 -1
- package/lib/catalog/manifests.js +124 -13
- package/lib/catalog/native-project.js +1 -1
- package/lib/catalog/project-config.js +0 -2
- package/lib/catalog/project-hooks.js +12 -7
- package/lib/catalog/scan-resolvers.js +117 -12
- package/lib/catalog/surfaces.js +86 -33
- package/lib/catalog/validate.js +205 -54
- package/lib/contracts/market.js +2 -0
- package/lib/index.js +6 -2
- package/lib/model/command-names.js +14 -0
- package/lib/model/layouts.js +35 -0
- package/lib/model/preset-source.js +8 -0
- package/lib/routes.js +31 -2
- package/lib/runtime/agent-role-router.js +176 -51
- package/lib/runtime/commands-mounts.js +3 -2
- package/lib/runtime/hooks-mounts.js +7 -4
- package/lib/runtime/host-locale.js +6 -12
- package/lib/runtime/mcp-client/connection.js +3 -2
- package/lib/runtime/mcp-client/oauth.js +82 -14
- package/lib/runtime/mcp-client/tools.js +2 -1
- package/lib/runtime/mcp-config.js +178 -34
- package/lib/runtime/mcp-direct-config.js +66 -14
- package/lib/runtime/mcp-mounts.js +15 -3
- package/lib/runtime/mcp-overrides.js +131 -1
- package/lib/runtime/mcp-redaction.js +8 -0
- package/lib/runtime/mcp-status.js +21 -5
- package/lib/runtime/plugin-message-source.js +4 -0
- package/lib/runtime/project-runtime.js +10 -8
- package/lib/runtime/server-config.js +49 -8
- package/lib/runtime/subagent-catalog.js +62 -22
- package/lib/runtime/tool-registry-observer.js +8 -4
- package/lib/runtime/user-commands.js +23 -8
- package/lib/runtime/user-hooks.js +102 -0
- package/lib/runtime/user-panels.js +34 -22
- package/lib/runtime/user-store.js +81 -19
- package/lib/types/application/catalog.d.ts +10 -1
- package/lib/types/application/install-store.d.ts +1 -1
- package/lib/types/application/mcp-service.d.ts +32 -3
- package/lib/types/application/queries.d.ts +6 -1
- package/lib/types/catalog/component-files.d.ts +1 -0
- package/lib/types/catalog/manifests.d.ts +6 -2
- package/lib/types/catalog/project-hooks.d.ts +15 -2
- package/lib/types/catalog/surfaces.d.ts +16 -4
- package/lib/types/catalog/validate.d.ts +72 -11
- package/lib/types/contracts/market.d.ts +72 -1
- package/lib/types/contracts/mcp-status.d.ts +11 -0
- package/lib/types/model/command-names.d.ts +12 -0
- package/lib/types/model/layouts.d.ts +21 -0
- package/lib/types/model/preset-source.d.ts +18 -0
- package/lib/types/model/types.d.ts +39 -2
- package/lib/types/runtime/agent-role-router.d.ts +90 -16
- package/lib/types/runtime/host-locale.d.ts +1 -1
- package/lib/types/runtime/mcp-client/oauth.d.ts +4 -0
- package/lib/types/runtime/mcp-config.d.ts +75 -13
- package/lib/types/runtime/mcp-direct-config.d.ts +23 -5
- package/lib/types/runtime/mcp-overrides.d.ts +44 -0
- package/lib/types/runtime/mcp-redaction.d.ts +6 -0
- package/lib/types/runtime/plugin-message-source.d.ts +24 -0
- package/lib/types/runtime/server-config.d.ts +26 -1
- package/lib/types/runtime/subagent-catalog.d.ts +14 -2
- package/lib/types/runtime/tool-registry-observer.d.ts +5 -3
- package/lib/types/runtime/user-commands.d.ts +5 -2
- package/lib/types/runtime/user-hooks.d.ts +22 -0
- package/lib/types/runtime/user-panels.d.ts +35 -15
- package/lib/types/runtime/user-store.d.ts +27 -10
- package/package.json +39 -35
- package/schemas/1.0.0/mcp.schema.json +0 -22
- package/schemas/1.1.0/mcp.schema.json +120 -0
- package/schemas/1.1.0/plugin.schema.json +65 -0
- package/schemas/README.md +25 -19
- package/schemas/agent-plugins/spec.md +23 -9
- package/schemas/com.deepseek.harness/namespace.schema.json +42 -0
- package/schemas/com.deepseek.harness/spec.md +52 -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=".qUlk6a_overlay {\n z-index: 2147483647;\n box-sizing: border-box;\n background: var(--dsw-alias-bg-mask-3);\n backdrop-filter: blur(3px);\n cursor: progress;\n outline: none;\n place-items: center;\n display: grid;\n position: fixed;\n overflow: hidden;\n}\n\n.qUlk6a_overlay[data-visible=\"false\"] {\n backdrop-filter: none;\n background: none;\n}\n\n.qUlk6a_overlay[data-visible=\"true\"] {\n animation: .14s ease-out qUlk6a_busy-enter;\n}\n\n.qUlk6a_content {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n width: min(360px, 100% - 32px);\n color: var(--dsw-alias-label-primary);\n text-align: center;\n border-radius: 8px;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n display: flex;\n}\n\n.qUlk6a_spinner {\n width: 28px;\n height: 28px;\n animation: .9s linear infinite qUlk6a_busy-spin;\n display: flex;\n}\n\n.qUlk6a_label {\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.qUlk6a_hintViewport {\n width: 100%;\n min-height: 54px;\n overflow: hidden;\n}\n\n.qUlk6a_hint {\n color: var(--dsw-alias-label-secondary);\n overflow-wrap: anywhere;\n margin: 0;\n font-size: 13px;\n line-height: 18px;\n animation: .3s ease-out qUlk6a_busy-hint;\n}\n\n.qUlk6a_warning {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n background: var(--dsw-alias-state-warn-tertiary, #fef5e7);\n overflow-wrap: anywhere;\n border-radius: 6px;\n margin: 0;\n padding: 6px 8px;\n font-size: 12px;\n line-height: 17px;\n}\n\n@keyframes qUlk6a_busy-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@keyframes qUlk6a_busy-enter {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 1;\n }\n}\n\n@keyframes qUlk6a_busy-hint {\n from {\n opacity: 0;\n transform: translateY(14px);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .qUlk6a_overlay, .qUlk6a_hint {\n animation: none;\n }\n\n .qUlk6a_spinner {\n animation-duration: 2.4s;\n }\n}\n._72qoAq_market {\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n gap: 24px;\n display: flex;\n container-type: inline-size;\n}\n\n._72qoAq_pageMode {\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: 0;\n}\n\n._72qoAq_marketControls {\n flex-direction: column;\n gap: 8px;\n min-height: 0;\n display: flex;\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\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:focus-visible, ._72qoAq_srcTabMain:focus-visible, ._72qoAq_srcTabEdit:focus-visible, ._72qoAq_srcTabDel: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_sourceTabsBox {\n min-width: 0;\n position: relative;\n}\n\n._72qoAq_sourceTabsRow {\n grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));\n gap: 4px;\n min-width: 0;\n display: grid;\n}\n\n._72qoAq_sourceTabsBoxFold {\n clip-path: inset(-6px);\n height: 52px;\n}\n\n._72qoAq_sourceTabsBoxFold:hover, ._72qoAq_sourceTabsBoxFold:has(:focus-visible) {\n clip-path: none;\n z-index: 20;\n}\n\n._72qoAq_sourceTabsBoxFold ._72qoAq_sourceTabsRow {\n box-sizing: border-box;\n background: var(--dsw-alias-bg-layer-1, #fff);\n border-radius: 10px;\n max-height: 58px;\n padding: 6px 6px 0;\n transition: max-height .16s, box-shadow .16s, padding-bottom .16s;\n position: absolute;\n inset: -6px -6px auto;\n overflow: hidden;\n -webkit-mask-image: linear-gradient(#000 78%, #0000 100%);\n mask-image: linear-gradient(#000 78%, #0000 100%);\n}\n\n._72qoAq_sourceTabsBoxFold:hover ._72qoAq_sourceTabsRow, ._72qoAq_sourceTabsBoxFold:has(:focus-visible) ._72qoAq_sourceTabsRow {\n z-index: 30;\n max-height: 420px;\n box-shadow: 0 0 0 1px var(--dsw-alias-border-l3, #d9dde3),\n 0 12px 28px #10182829;\n padding-bottom: 6px;\n -webkit-mask-image: none;\n mask-image: none;\n}\n\n._72qoAq_sourceTabsBoxFold._72qoAq_sourceTabsBoxPicked:hover, ._72qoAq_sourceTabsBoxFold._72qoAq_sourceTabsBoxPicked:has(:focus-visible) {\n clip-path: inset(-6px);\n}\n\n._72qoAq_sourceTabsBoxFold._72qoAq_sourceTabsBoxPicked:hover ._72qoAq_sourceTabsRow, ._72qoAq_sourceTabsBoxFold._72qoAq_sourceTabsBoxPicked:has(:focus-visible) ._72qoAq_sourceTabsRow {\n max-height: 58px;\n box-shadow: none;\n padding-bottom: 0;\n -webkit-mask-image: linear-gradient(#000 78%, #0000 100%);\n mask-image: linear-gradient(#000 78%, #0000 100%);\n}\n\n._72qoAq_unmanagedRow {\n color: var(--dsw-alias-label-secondary, #57606a);\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin-top: 6px;\n font-size: 12px;\n display: flex;\n}\n\n._72qoAq_unmanagedLabel {\n flex-shrink: 0;\n}\n\n._72qoAq_unmanagedChip {\n border: 1px dashed var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-layer-1, #fff);\n border-radius: 999px;\n align-items: center;\n gap: 2px;\n max-width: 220px;\n height: 22px;\n padding: 0 4px 0 8px;\n display: inline-flex;\n}\n\n._72qoAq_unmanagedChipName {\n white-space: nowrap;\n text-overflow: ellipsis;\n font-size: 12px;\n overflow: hidden;\n}\n\n._72qoAq_unmanagedAdopt {\n font: inherit;\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n cursor: pointer;\n background: none;\n border: none;\n flex-shrink: 0;\n padding: 0 4px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_unmanagedAdopt:disabled {\n cursor: default;\n opacity: .5;\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 margin-left: 4px;\n padding: 0 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: auto;\n max-width: 100%;\n height: 24px;\n padding: 0 10px;\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: 0;\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, #0f1115);\n border-color: var(--dsw-alias-brand-primary, #0f1115);\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 margin-left: 4px;\n padding: 0 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, ._72qoAq_list ._72qoAq_cardActions {\n flex: none;\n}\n\n._72qoAq_list ._72qoAq_meta, ._72qoAq_list ._72qoAq_tagRow {\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_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_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_confirmCheck {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: row;\n align-items: center;\n gap: 8px;\n font-size: 12px;\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(640px, 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_installConfirmCommit {\n color: var(--dsw-alias-label-secondary, #4b5563);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\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-state-warn-label, #dd8629);\n border: 1px solid var(--dsw-alias-state-warn-label, #dd8629);\n border-radius: 8px;\n padding: 8px 10px;\n font-size: 12px;\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-state-error-primary, #ec1313);\n color: var(--dsw-alias-state-error-primary, #ec1313);\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_sourceTabsRow {\n grid-template-columns: repeat(auto-fill, minmax(102px, 1fr));\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-label-secondary, #61666b);\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-brand-primary-new-colorprimary-new-color, #4176e6);\n margin: 0;\n}\n\n._72qoAq_pluginCard {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-3, #fff);\n border-radius: 12px;\n list-style: none;\n transition: border-color .16s, background .16s;\n container: _72qoAq_market-config / inline-size;\n}\n\n._72qoAq_pluginCard:hover {\n border-color: var(--dsw-alias-label-dimmed, #c8ccd4);\n}\n\n._72qoAq_pluginCardOpen {\n background: var(--dsw-alias-bg-layer-2, #f7f8fa);\n border-color: var(--dsw-alias-label-dimmed, #c8ccd4);\n}\n\n._72qoAq_pluginCard[data-busy=\"true\"] {\n opacity: .6;\n pointer-events: none;\n}\n\n._72qoAq_pluginCardHeader {\n appearance: none;\n width: 100%;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: 12px;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n display: flex;\n}\n\n._72qoAq_pluginCardHeader:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: -2px;\n}\n\n._72qoAq_pluginCardBody {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n flex-direction: column;\n gap: 8px;\n margin: 0 16px;\n padding: 4px 0 8px;\n display: flex;\n}\n\n._72qoAq_pluginCardRow {\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n padding: 8px 0 4px;\n display: flex;\n}\n\n._72qoAq_pluginCardText {\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_pluginCardTitle {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n._72qoAq_pluginCardDesc {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 13px;\n line-height: 1.5;\n}\n\n._72qoAq_pluginCardRowLabel {\n font-size: 13px;\n font-weight: 500;\n line-height: 20px;\n}\n\n@container _72qoAq_market-config (width <= 320px) {\n ._72qoAq_pluginCardRow {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n ._72qoAq_pluginCardText {\n overflow-wrap: anywhere;\n width: 100%;\n }\n\n ._72qoAq_regionSeg {\n flex-wrap: wrap;\n max-width: 100%;\n }\n}\n\n._72qoAq_pluginCardError {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n}\n\n._72qoAq_pluginFieldHead {\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n._72qoAq_pluginFieldBadges {\n align-items: center;\n gap: 6px;\n display: inline-flex;\n}\n\n._72qoAq_pluginFieldReset {\n appearance: none;\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n text-underline-offset: 2px;\n background: none;\n border: 0;\n padding: 0;\n font-size: 12px;\n line-height: 18px;\n text-decoration: underline;\n}\n\n._72qoAq_pluginFieldReset:disabled {\n cursor: default;\n opacity: .5;\n}\n\n._72qoAq_pluginCardReadonly {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n}\n\n._72qoAq_pluginCardFooter {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n margin-top: 4px;\n padding-top: 8px;\n display: flex;\n}\n\n._72qoAq_pluginCardFooter ._72qoAq_pluginCardError {\n margin-right: auto;\n}\n\n._72qoAq_pluginCardDiscard, ._72qoAq_pluginCardSave {\n appearance: none;\n font: inherit;\n cursor: pointer;\n border-radius: 8px;\n padding: 4px 12px;\n font-size: 13px;\n line-height: 20px;\n}\n\n._72qoAq_pluginCardDiscard {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n color: var(--dsw-alias-label-primary, #1f2328);\n background: none;\n}\n\n._72qoAq_pluginCardDiscard:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover, #0000000a);\n}\n\n._72qoAq_pluginCardSave {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n border: 1px solid #0000;\n}\n\n._72qoAq_pluginCardSave:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n._72qoAq_pluginCardDiscard:disabled, ._72qoAq_pluginCardSave:disabled {\n cursor: default;\n opacity: .5;\n}\n\n._72qoAq_pluginChevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n flex: none;\n transition: transform .16s;\n display: inline-flex;\n}\n\n._72qoAq_pluginChevronOpen {\n transform: rotate(180deg);\n}\n\n._72qoAq_regionSeg {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n flex: none;\n gap: 2px;\n padding: 2px;\n display: inline-flex;\n}\n\n._72qoAq_regionSegBtn {\n appearance: none;\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n padding: 3px 10px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_regionSegOn {\n appearance: none;\n font: inherit;\n cursor: pointer;\n background: var(--dsw-alias-bg-layer-2, #eef0f4);\n color: var(--dsw-alias-label-primary, #1f2328);\n border: none;\n border-radius: 6px;\n padding: 3px 10px;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n}\n\n._72qoAq_regionSegEffective {\n appearance: none;\n font: inherit;\n cursor: pointer;\n color: var(--dsw-alias-label-primary, #1f2328);\n background: none;\n border: none;\n border-radius: 6px;\n padding: 3px 10px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_regionSegBtn:disabled, ._72qoAq_regionSegOn:disabled {\n cursor: default;\n opacity: .5;\n}\n._5JDFMW_field {\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_field > label, ._5JDFMW_field > span, ._5JDFMW_field > ._5JDFMW_rowHead > span {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 600;\n}\n\n._5JDFMW_field input, ._5JDFMW_field select, ._5JDFMW_field textarea {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-1);\n width: 100%;\n min-width: 0;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n border-radius: 8px;\n padding: 7px 9px;\n font-size: 12px;\n}\n\n._5JDFMW_field textarea {\n resize: vertical;\n min-height: 240px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n line-height: 19px;\n}\n\n._5JDFMW_jsonArea {\n min-height: 220px;\n}\n\n._5JDFMW_field input:focus-visible, ._5JDFMW_field select:focus-visible, ._5JDFMW_field textarea:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n._5JDFMW_hint {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 400;\n line-height: 16px;\n}\n\n._5JDFMW_form {\n flex-direction: column;\n gap: 14px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_formGrid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 12px;\n display: grid;\n}\n\n._5JDFMW_full {\n grid-column: 1 / -1;\n}\n\n._5JDFMW_seg {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n flex: none;\n gap: 2px;\n padding: 2px;\n display: inline-flex;\n}\n\n._5JDFMW_seg button {\n height: 24px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n background: none;\n border: none;\n border-radius: 6px;\n padding: 0 10px;\n font-size: 12px;\n}\n\n._5JDFMW_seg button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._5JDFMW_seg button[aria-pressed=\"true\"] {\n background: var(--dsw-alias-interactive-bg-active);\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n}\n\n._5JDFMW_seg button:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n\n._5JDFMW_readonly {\n border: 1px dashed var(--dsw-alias-border-l3);\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n border-radius: 8px;\n padding: 7px 9px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n}\n\n._5JDFMW_rows {\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_row {\n align-items: center;\n gap: 6px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_row input {\n flex: auto;\n width: 0;\n min-width: 0;\n}\n\n._5JDFMW_rowKey {\n flex: 0 0 34%;\n}\n\n._5JDFMW_rowKeyNarrow {\n flex: 0 0 26%;\n}\n\n._5JDFMW_rowActions {\n flex: none;\n align-items: center;\n gap: 2px;\n display: flex;\n}\n\n._5JDFMW_iconBtn {\n width: 24px;\n height: 24px;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n justify-content: center;\n align-items: center;\n padding: 0;\n display: inline-flex;\n}\n\n._5JDFMW_iconBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n._5JDFMW_rowHead {\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n min-height: 24px;\n display: flex;\n}\n\n._5JDFMW_addIcon {\n width: 24px;\n height: 24px;\n color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n justify-content: center;\n align-items: center;\n padding: 0;\n display: inline-flex;\n}\n\n._5JDFMW_addIcon:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._5JDFMW_addIcon:disabled {\n cursor: default;\n opacity: .4;\n}\n\n._5JDFMW_addIcon svg {\n fill: none;\n stroke: currentColor;\n stroke-width: 1.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n display: block;\n}\n\n._5JDFMW_inlineCheck {\n color: var(--dsw-alias-label-primary);\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: inline-flex;\n}\n\n._5JDFMW_fieldset {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 12px;\n min-width: 0;\n margin: 0;\n padding: 2px 12px 12px;\n display: grid;\n}\n\n._5JDFMW_fieldset legend {\n color: var(--dsw-alias-label-secondary);\n padding: 0 4px;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n}\n\n._5JDFMW_fieldset > ._5JDFMW_hint, ._5JDFMW_fieldset > ._5JDFMW_full {\n grid-column: 1 / -1;\n}\n\n._5JDFMW_previewBox {\n border: 1px solid var(--dsw-alias-border-l2);\n box-sizing: border-box;\n border-radius: 8px;\n min-height: 300px;\n padding: 12px 14px;\n overflow-y: auto;\n}\n\n._5JDFMW_footer {\n flex: 1;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n._5JDFMW_footerHint {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n._5JDFMW_grow {\n flex: auto;\n}\n\n._5JDFMW_footerError {\n color: var(--dsw-alias-state-error-primary);\n font-size: 12px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._5JDFMW_seg button, ._5JDFMW_addIcon, ._5JDFMW_iconBtn {\n transition: none;\n }\n}\n\n@container (width <= 700px) {\n ._5JDFMW_formGrid, ._5JDFMW_fieldset {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n.IgyjIq_card[data-resource-state] {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-1);\n min-width: 0;\n max-width: 100%;\n color: var(--dsw-alias-label-primary);\n box-shadow: none;\n cursor: pointer;\n border-left-width: 3px;\n border-radius: 10px;\n gap: 4px 10px;\n padding: 11px 12px 11px 13px;\n transition: border-color .14s, background .14s;\n display: grid;\n position: relative;\n overflow: hidden;\n}\n\n.IgyjIq_card[data-resource-state=\"active\"] {\n border-left-color: var(--dsw-alias-state-success-primary);\n}\n\n.IgyjIq_card[data-resource-state=\"disabled\"] {\n border-left-color: var(--dsw-alias-label-tertiary);\n}\n\n.IgyjIq_card[data-resource-state=\"warning\"] {\n border-left-color: var(--dsw-alias-state-warn-primary);\n}\n\n.IgyjIq_card[data-resource-state=\"error\"] {\n border-left-color: var(--dsw-alias-state-error-primary);\n}\n\n.IgyjIq_card[data-resource-state]:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:hover .IgyjIq_rowActions, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:focus-within .IgyjIq_rowActions {\n z-index: 1;\n}\n\n.IgyjIq_collection[data-resource-view] {\n box-sizing: border-box;\n scrollbar-gutter: stable;\n align-content: start;\n align-items: stretch;\n width: 100%;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n}\n\n.IgyjIq_collection[data-resource-view=\"grid\"] {\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n grid-auto-rows: 122px;\n gap: 10px;\n padding-right: 4px;\n display: grid;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] {\n flex-direction: column;\n gap: 6px;\n padding-right: 4px;\n display: flex;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] > .IgyjIq_card {\n flex-shrink: 0;\n}\n\n.IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] {\n grid-template: \"IgyjIq_id IgyjIq_act\"\n \"IgyjIq_body IgyjIq_body\" minmax(0, 1fr)\n \"IgyjIq_foot IgyjIq_foot\"\n / minmax(0, 1fr) auto;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] > .IgyjIq_card[data-resource-state] {\n box-sizing: border-box;\n grid-template-columns: minmax(160px, .85fr) minmax(210px, 1.05fr) minmax(0, 1.5fr) auto;\n grid-template-areas: \"IgyjIq_id IgyjIq_foot IgyjIq_body IgyjIq_act\";\n align-items: center;\n gap: 16px;\n height: 56px;\n}\n\n@container (width <= 700px) {\n .IgyjIq_collection[data-resource-view=\"grid\"] {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n grid-auto-rows: max-content;\n gap: 4px;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] {\n grid-template: \"IgyjIq_id\"\n \"IgyjIq_body\"\n \"IgyjIq_foot\"\n / minmax(0, 1fr);\n align-content: start;\n gap: 4px;\n padding: 10px 10px 10px 13px;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] .IgyjIq_rowId, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] .IgyjIq_rowBody {\n overflow: hidden;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] .IgyjIq_rowActions {\n background: var(--dsw-alias-bg-layer-1);\n box-shadow: 0 0 6px 8px var(--dsw-alias-bg-layer-1);\n opacity: 0;\n border-radius: 16px;\n gap: 4px;\n margin-left: 0;\n padding: 4px 6px;\n transition: opacity .14s;\n position: absolute;\n top: 8px;\n bottom: auto;\n right: 8px;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:hover .IgyjIq_rowActions, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:focus-within .IgyjIq_rowActions {\n opacity: 1;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:hover, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:focus-within {\n background: var(--dsw-alias-bg-layer-1);\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-surface=\"mcp\"] .IgyjIq_provenanceChip, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-surface=\"lsp\"] .IgyjIq_provenanceChip {\n display: none;\n }\n\n .IgyjIq_collection[data-resource-view=\"list\"] > .IgyjIq_card[data-resource-state] {\n grid-template-columns: minmax(0, 1fr) auto;\n grid-template-areas: \"IgyjIq_id IgyjIq_act\"\n \"IgyjIq_foot IgyjIq_act\"\n \"IgyjIq_body IgyjIq_act\";\n height: auto;\n padding-block: 10px;\n }\n}\n\n@container (width <= 420px) {\n .IgyjIq_collection[data-resource-view=\"grid\"] {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.IgyjIq_rowId {\n grid-area: IgyjIq_id;\n align-items: center;\n gap: 7px;\n min-width: 0;\n min-height: 24px;\n display: flex;\n}\n\n.IgyjIq_rowBody {\n grid-area: IgyjIq_body;\n min-width: 0;\n overflow: hidden;\n}\n\n.IgyjIq_rowFoot {\n grid-area: IgyjIq_foot;\n align-items: center;\n gap: 7px;\n min-width: 0;\n min-height: 16px;\n display: flex;\n overflow: hidden;\n}\n\n.IgyjIq_rowActions {\n border-radius: 8px;\n flex: none;\n grid-area: IgyjIq_act;\n justify-content: flex-end;\n align-items: center;\n gap: 2px;\n margin-left: auto;\n display: flex;\n position: relative;\n}\n\n.IgyjIq_name {\n min-width: 0;\n color: var(--dsw-alias-label-primary);\n white-space: nowrap;\n font-size: 13px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.IgyjIq_nameMono {\n letter-spacing: -.01em;\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 12.5px;\n}\n\n.IgyjIq_version {\n color: var(--dsw-alias-label-tertiary);\n font-variant-numeric: tabular-nums;\n flex: none;\n font-size: 11px;\n}\n\n.IgyjIq_desc {\n max-height: 34px;\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 12px;\n line-height: 17px;\n overflow: hidden;\n}\n\n.IgyjIq_monoLine {\n max-height: 34px;\n color: var(--dsw-alias-label-tertiary);\n overflow-wrap: anywhere;\n margin: 0;\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 11.5px;\n line-height: 17px;\n overflow: hidden;\n}\n\n.IgyjIq_provenance, .IgyjIq_path {\n color: var(--dsw-alias-label-tertiary);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 0 auto;\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 11px;\n overflow: hidden;\n}\n\n.IgyjIq_count {\n color: var(--dsw-alias-label-tertiary);\n white-space: nowrap;\n flex: none;\n font-size: 11px;\n}\n\n.IgyjIq_countValue {\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n font-weight: 600;\n}\n\n.IgyjIq_separator {\n color: var(--dsw-alias-label-dimmed);\n flex: none;\n font-size: 11px;\n}\n\n.IgyjIq_iconBtn {\n width: 24px;\n height: 24px;\n color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n justify-content: center;\n align-items: center;\n padding: 0;\n display: inline-flex;\n}\n\n.IgyjIq_iconBtn:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.IgyjIq_iconBtn:disabled {\n cursor: default;\n opacity: .4;\n}\n\n.IgyjIq_iconBtnDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n.IgyjIq_iconBtn:focus-visible, .IgyjIq_rowActions :focus-visible, .IgyjIq_card[data-resource-state]:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n\n.IgyjIq_revealOnHover {\n opacity: 0;\n transition: opacity .14s;\n}\n\n.IgyjIq_card[data-resource-state]:hover .IgyjIq_revealOnHover, .IgyjIq_card[data-resource-state]:focus-within .IgyjIq_revealOnHover {\n opacity: 1;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] .IgyjIq_desc, .IgyjIq_collection[data-resource-view=\"list\"] .IgyjIq_monoLine {\n max-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 11.5px;\n display: block;\n overflow: hidden;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] .IgyjIq_revealOnHover {\n opacity: 1;\n}\n\n.IgyjIq_switchWrap, .IgyjIq_warnWrap {\n flex: none;\n align-items: center;\n display: inline-flex;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .IgyjIq_card[data-resource-state], .IgyjIq_revealOnHover, .IgyjIq_rowActions {\n transition: none;\n }\n}\n.sBXwgW_dialog[role=\"dialog\"] {\n box-sizing: border-box;\n max-width: calc(100vw - 48px);\n max-height: calc(100dvh - 48px);\n}\n\n.sBXwgW_dialog[role=\"dialog\"].sBXwgW_sizeSm {\n width: min(460px, 100vw - 48px);\n}\n\n.sBXwgW_dialog[role=\"dialog\"].sBXwgW_sizeMd {\n width: min(640px, 100vw - 48px);\n}\n\n.sBXwgW_dialog[role=\"dialog\"].sBXwgW_sizeLg {\n width: min(880px, 100vw - 48px);\n}\n\n.sBXwgW_body {\n overflow-wrap: anywhere;\n min-width: 0;\n min-height: 0;\n max-height: calc(100dvh - 200px);\n overflow-y: auto;\n}\n\n.sBXwgW_footer {\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n width: 100%;\n display: flex;\n}\n\n.sBXwgW_footer > :first-child {\n flex: 1;\n}\n\n.sBXwgW_footerSlot:empty {\n display: none;\n}\n\n.sBXwgW_frontmatter {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-markdown-code-block);\n color: var(--dsw-alias-label-tertiary);\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n border-radius: 8px;\n margin: 0 0 10px;\n padding: 8px 10px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11.5px;\n line-height: 18px;\n}\n\n.sBXwgW_preview {\n min-width: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 14px;\n line-height: 1.6;\n}\n\n.sBXwgW_preview pre, .sBXwgW_preview table {\n max-width: 100%;\n overflow: auto;\n}\n\n.sBXwgW_preview img {\n max-width: 100%;\n height: auto;\n}\n\n.sBXwgW_error {\n color: var(--dsw-alias-state-error-primary);\n margin: 8px 0;\n font-size: 13px;\n}\n\n.sBXwgW_pair {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 16px;\n display: grid;\n}\n\n.sBXwgW_row {\n align-items: center;\n gap: 6px;\n min-width: 0;\n display: flex;\n}\n\n.sBXwgW_row input {\n flex: 1;\n width: 0;\n}\n\n.sBXwgW_row button {\n flex: none;\n}\n\n@media (width <= 640px) {\n .sBXwgW_dialog[role=\"dialog\"] {\n width: calc(100vw - 16px);\n max-width: calc(100vw - 16px);\n max-height: calc(100dvh - 16px);\n }\n\n .sBXwgW_form {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n._9Lujra_rows {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n flex-direction: column;\n min-width: 0;\n display: flex;\n overflow: hidden;\n}\n\n._9Lujra_group {\n flex-direction: column;\n min-width: 0;\n display: flex;\n}\n\n._9Lujra_group + ._9Lujra_group ._9Lujra_row {\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n\n._9Lujra_row {\n box-sizing: border-box;\n width: 100%;\n color: inherit;\n text-align: left;\n font: inherit;\n background: none;\n border: none;\n grid-template-columns: minmax(110px, max-content) minmax(0, 1fr) 14px;\n align-items: center;\n gap: 12px;\n padding: 9px 12px;\n display: grid;\n}\n\nbutton._9Lujra_row {\n cursor: pointer;\n}\n\n._9Lujra_row:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n._9Lujra_row[aria-expanded=\"true\"] {\n background: var(--dsw-alias-state-business-tertiary);\n}\n\n._9Lujra_row:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n._9Lujra_name {\n color: var(--dsw-alias-label-primary);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11.5px;\n font-weight: 600;\n overflow: hidden;\n}\n\n._9Lujra_summary {\n color: var(--dsw-alias-label-tertiary);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 11.5px;\n overflow: hidden;\n}\n\n._9Lujra_chevron {\n color: var(--dsw-alias-label-tertiary);\n justify-self: end;\n display: inline-flex;\n}\n\n._9Lujra_chevron svg {\n display: block;\n}\n\n._9Lujra_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-interactive-bg-hover);\n padding: 12px 14px;\n}\n.HJ9x7a_shell {\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n gap: 16px;\n display: flex;\n container-type: inline-size;\n}\n\n.HJ9x7a_header {\n flex-direction: row;\n flex: none;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n min-height: 46px;\n display: flex;\n}\n\n.HJ9x7a_headerText {\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n display: flex;\n}\n\n.HJ9x7a_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.HJ9x7a_subtitle {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n.HJ9x7a_headerActions {\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.HJ9x7a_body {\n scrollbar-gutter: stable;\n flex-direction: column;\n flex: 1;\n gap: 12px;\n min-height: 0;\n display: flex;\n overflow-y: auto;\n}\n\n.HJ9x7a_busyLine {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: flex;\n}\n\n.HJ9x7a_busyLabel {\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n overflow: hidden;\n}\n\n.HJ9x7a_spinner {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex: none;\n font-size: 13px;\n display: inline-flex;\n}\n\n.HJ9x7a_spinning {\n animation: .9s linear infinite HJ9x7a_panel-spin;\n}\n\n@keyframes HJ9x7a_panel-spin {\n from {\n transform: rotate(0);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .HJ9x7a_spinning {\n animation-duration: 2.4s;\n }\n}\n\n.HJ9x7a_editorDialog {\n gap: 12px;\n max-width: 720px;\n}\n\n.HJ9x7a_editorDialog [class*=\"content\"] > [class*=\"body\"] {\n margin-top: 0;\n}\n\n.HJ9x7a_editorBody {\n flex-direction: column;\n gap: 12px;\n display: flex;\n}\n\n.HJ9x7a_editorFooter {\n flex-direction: row;\n flex: 1;\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n.HJ9x7a_editorError {\n color: var(--dsw-alias-state-error-primary, #c81e1e);\n margin-right: auto;\n font-size: 12px;\n}\n\n.HJ9x7a_confirmCheck {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: row;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: flex;\n}\n\n.HJ9x7a_empty {\n color: var(--dsw-alias-label-tertiary, #6b7280);\n text-align: center;\n padding: 24px 12px;\n font-size: 12px;\n}\n\n@container (width <= 540px) {\n .HJ9x7a_entryGrid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .HJ9x7a_entryRow {\n flex-wrap: wrap;\n }\n\n .HJ9x7a_entryActions {\n margin-left: auto;\n }\n\n .HJ9x7a_entryMain {\n flex-basis: 100%;\n }\n}\n\n.HJ9x7a_hero {\n background: var(--dsw-alias-interactive-bg-hover);\n border-radius: 10px;\n align-items: center;\n gap: 10px;\n padding: 12px 14px;\n display: flex;\n}\n\n.HJ9x7a_heroText {\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n display: flex;\n}\n\n.HJ9x7a_heroLine {\n flex-wrap: wrap;\n align-items: center;\n gap: 7px;\n display: flex;\n}\n\n.HJ9x7a_heroMono {\n overflow-wrap: anywhere;\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font: 12px / 18px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.HJ9x7a_block {\n margin-top: 18px;\n}\n\n.HJ9x7a_blockHead {\n color: var(--dsw-alias-label-secondary);\n letter-spacing: .04em;\n text-transform: uppercase;\n margin: 0 0 8px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.HJ9x7a_kvGrid {\n grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));\n gap: 10px 16px;\n margin: 0;\n display: grid;\n}\n\n.HJ9x7a_kvKey {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 16px;\n}\n\n.HJ9x7a_kvValue {\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: 3px 0 0;\n font-size: 12.5px;\n line-height: 18px;\n overflow: hidden;\n}\n\n.HJ9x7a_monoBlock {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-markdown-code-block);\n color: var(--dsw-alias-label-secondary);\n border-radius: 10px;\n margin: 0;\n padding: 12px 14px;\n font: 11.5px / 18px ui-monospace, Menlo, Consolas, monospace;\n overflow-x: auto;\n}\n\n.HJ9x7a_detailProse {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 13px;\n line-height: 21px;\n}\n\n.HJ9x7a_kvValueMono {\n font-family: ui-monospace, Menlo, Consolas, monospace;\n}\n.vavGuW_toolbar {\n flex: none;\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.vavGuW_search {\n flex: auto;\n align-items: center;\n min-width: 0;\n display: flex;\n}\n\n.vavGuW_searchInput {\n flex: auto;\n min-width: 0;\n}\n\n.vavGuW_searchInput input {\n font-size: 12px;\n line-height: 20px;\n}\n\n.vavGuW_segment {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n flex: none;\n align-items: center;\n gap: 2px;\n padding: 3px;\n display: flex;\n}\n\n.vavGuW_count {\n color: var(--dsw-alias-label-tertiary);\n font-variant-numeric: tabular-nums;\n}\n\n.vavGuW_segment svg {\n stroke: currentColor;\n stroke-width: 1.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n display: block;\n}\n\n@container (width <= 480px) {\n .vavGuW_toolbar {\n flex-wrap: wrap;\n justify-content: flex-end;\n }\n\n .vavGuW_search {\n flex-basis: 100%;\n }\n}\n._5BoKRG_editor {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-1);\n box-sizing: border-box;\n border-radius: 8px;\n flex-direction: column;\n display: flex;\n overflow: hidden;\n}\n\n._5BoKRG_editor .cm-editor {\n flex: 1;\n min-height: 0;\n}\n\n._5BoKRG_editor .cm-scroller {\n overflow: auto;\n}\n.G2mDja_form {\n background: var(--dsw-alias-bg-layer-2, #f7f8fa);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 10px;\n flex-direction: column;\n gap: 10px;\n padding: 12px 14px;\n display: flex;\n}\n\n.G2mDja_head {\n color: var(--dsw-alias-label-secondary, #667085);\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n}\n\n.G2mDja_error {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n background: var(--dsw-alias-interactive-bg-hover-danger, #ec13130d);\n overflow-wrap: anywhere;\n border-radius: 8px;\n padding: 8px 10px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.G2mDja_row {\n border-top: 1px solid var(--dsw-alias-border-l1, #eef1f5);\n flex-direction: column;\n gap: 6px;\n min-width: 0;\n padding-top: 8px;\n display: flex;\n}\n\n.G2mDja_ref {\n color: var(--dsw-alias-label-primary, #1f2328);\n font: 600 12px / 18px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.G2mDja_controls {\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.G2mDja_facts {\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.G2mDja_factOk, .G2mDja_factMiss {\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n}\n\n.G2mDja_factOk {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n background: var(--dsw-alias-state-success-tertiary, #e6faed);\n}\n\n.G2mDja_factMiss {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n background: var(--dsw-alias-state-warn-tertiary, #fef5e7);\n}\n\n.G2mDja_note {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 11px;\n line-height: 17px;\n}\n\n.G2mDja_editor {\n flex-direction: column;\n gap: 8px;\n display: flex;\n}\n\n.G2mDja_input {\n box-sizing: border-box;\n width: 100%;\n color: var(--dsw-alias-label-primary, #1f2328);\n background: var(--dsw-alias-bg-layer-1, #fff);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n padding: 7px 10px;\n font-size: 12px;\n}\n\n.G2mDja_input:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 1px;\n}\n\n.G2mDja_actions {\n align-items: center;\n gap: 8px;\n display: flex;\n}\n.HJ9x7a_shell {\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n gap: 16px;\n display: flex;\n container-type: inline-size;\n}\n\n.HJ9x7a_header {\n flex-direction: row;\n flex: none;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n min-height: 46px;\n display: flex;\n}\n\n.HJ9x7a_headerText {\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n display: flex;\n}\n\n.HJ9x7a_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.HJ9x7a_subtitle {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n.HJ9x7a_headerActions {\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.HJ9x7a_body {\n scrollbar-gutter: stable;\n flex-direction: column;\n flex: 1;\n gap: 12px;\n min-height: 0;\n display: flex;\n overflow-y: auto;\n}\n\n.HJ9x7a_busyLine {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: flex;\n}\n\n.HJ9x7a_busyLabel {\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n overflow: hidden;\n}\n\n.HJ9x7a_spinner {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex: none;\n font-size: 13px;\n display: inline-flex;\n}\n\n.HJ9x7a_spinning {\n animation: .9s linear infinite HJ9x7a_panel-spin;\n}\n\n@keyframes HJ9x7a_panel-spin {\n from {\n transform: rotate(0);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .HJ9x7a_spinning {\n animation-duration: 2.4s;\n }\n}\n\n.HJ9x7a_editorDialog {\n gap: 12px;\n max-width: 720px;\n}\n\n.HJ9x7a_editorDialog [class*=\"content\"] > [class*=\"body\"] {\n margin-top: 0;\n}\n\n.HJ9x7a_editorBody {\n flex-direction: column;\n gap: 12px;\n display: flex;\n}\n\n.HJ9x7a_editorFooter {\n flex-direction: row;\n flex: 1;\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n.HJ9x7a_editorError {\n color: var(--dsw-alias-state-error-primary, #c81e1e);\n margin-right: auto;\n font-size: 12px;\n}\n\n.HJ9x7a_confirmCheck {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: row;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: flex;\n}\n\n.HJ9x7a_empty {\n color: var(--dsw-alias-label-tertiary, #6b7280);\n text-align: center;\n padding: 24px 12px;\n font-size: 12px;\n}\n\n@container (width <= 540px) {\n .HJ9x7a_entryGrid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .HJ9x7a_entryRow {\n flex-wrap: wrap;\n }\n\n .HJ9x7a_entryActions {\n margin-left: auto;\n }\n\n .HJ9x7a_entryMain {\n flex-basis: 100%;\n }\n}\n\n.HJ9x7a_hero {\n background: var(--dsw-alias-interactive-bg-hover);\n border-radius: 10px;\n align-items: center;\n gap: 10px;\n padding: 12px 14px;\n display: flex;\n}\n\n.HJ9x7a_heroText {\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n display: flex;\n}\n\n.HJ9x7a_heroLine {\n flex-wrap: wrap;\n align-items: center;\n gap: 7px;\n display: flex;\n}\n\n.HJ9x7a_heroMono {\n overflow-wrap: anywhere;\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font: 12px / 18px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.HJ9x7a_block {\n margin-top: 18px;\n}\n\n.HJ9x7a_blockHead {\n color: var(--dsw-alias-label-secondary);\n letter-spacing: .04em;\n text-transform: uppercase;\n margin: 0 0 8px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.HJ9x7a_kvGrid {\n grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));\n gap: 10px 16px;\n margin: 0;\n display: grid;\n}\n\n.HJ9x7a_kvKey {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 16px;\n}\n\n.HJ9x7a_kvValue {\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: 3px 0 0;\n font-size: 12.5px;\n line-height: 18px;\n overflow: hidden;\n}\n\n.HJ9x7a_monoBlock {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-markdown-code-block);\n color: var(--dsw-alias-label-secondary);\n border-radius: 10px;\n margin: 0;\n padding: 12px 14px;\n font: 11.5px / 18px ui-monospace, Menlo, Consolas, monospace;\n overflow-x: auto;\n}\n\n.HJ9x7a_detailProse {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 13px;\n line-height: 21px;\n}\n\n.HJ9x7a_kvValueMono {\n font-family: ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_surface {\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n display: flex;\n}\n\n.AUWlZW_toolbar {\n flex: none;\n}\n\n@media (width <= 760px) {\n .AUWlZW_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.AUWlZW_reasonLabel {\n opacity: .85;\n flex: none;\n font-weight: 600;\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_detailBody {\n max-height: 72vh;\n overflow-y: auto;\n}\n\n.AUWlZW_modalFooter {\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n width: 100%;\n display: flex;\n}\n\n.AUWlZW_modalFooterHint {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n.AUWlZW_modalFooterGrow {\n flex: auto;\n}\n\n.AUWlZW_detail {\n flex-direction: column;\n gap: 16px;\n display: flex;\n}\n\n.AUWlZW_reasonBox {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n background: var(--dsw-alias-interactive-bg-hover-danger, #ec13130d);\n border-radius: 8px;\n flex-direction: column;\n gap: 4px;\n padding: 10px 12px;\n display: flex;\n}\n\n.AUWlZW_reasonText {\n overflow-wrap: anywhere;\n margin: 0;\n font-size: 12px;\n line-height: 18px;\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: minmax(140px, max-content) minmax(0, 1fr);\n align-items: center;\n gap: 12px;\n padding: 7px 0;\n display: grid;\n}\n\n.AUWlZW_tool:last-child {\n border-bottom: none;\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_toolbar {\n padding-left: 0;\n padding-right: 0;\n }\n\n .AUWlZW_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .AUWlZW_list .AUWlZW_cardTop {\n max-width: 100%;\n }\n\n .AUWlZW_tool {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .AUWlZW_toolDescription {\n display: none;\n }\n}\n\n.AUWlZW_retryEchoSuccess {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n white-space: nowrap;\n font-size: 12px;\n line-height: 18px;\n}\n\n@keyframes AUWlZW_lspStartingPulse {\n 50% {\n opacity: .35;\n }\n}\n\n.AUWlZW_reasonRaw {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n word-break: break-all;\n margin: 6px 0 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n line-height: 1.5;\n}\n\n.AUWlZW_seamBanner {\n border-left: 3px solid var(--dsw-alias-state-warn-primary, #b45309);\n background: var(--dsw-alias-state-warn-tertiary, #b4530914);\n border-radius: 8px;\n flex-direction: column;\n gap: 8px;\n margin: 0 0 12px;\n padding: 12px 14px;\n display: flex;\n}\n\n.AUWlZW_seamTitle {\n color: var(--dsw-alias-label-primary, #1f2329);\n font-size: 13px;\n font-weight: 600;\n}\n\n.AUWlZW_seamBody {\n color: var(--dsw-alias-label-secondary, #4e5969);\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.AUWlZW_seamPathLabel {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 11px;\n}\n\n.AUWlZW_seamPath {\n color: var(--dsw-alias-label-secondary, #4e5969);\n overflow-wrap: anywhere;\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_seamOther {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 0;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_seamDone {\n color: var(--dsw-alias-state-success-primary, #15803d);\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n.l0H8fW_workspace {\n min-width: 0;\n height: 100%;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n gap: 12px;\n display: flex;\n}\n\n.l0H8fW_pageMode {\n box-sizing: border-box;\n padding: 4px 0;\n}\n\n.l0H8fW_tabRow {\n border-bottom: 1px solid var(--dsw-alias-border-l2, #0000001a);\n scrollbar-width: none;\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 4px;\n display: flex;\n overflow-x: auto;\n}\n\n.l0H8fW_tab, .l0H8fW_tabOn {\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-radius: 8px 8px 0 0;\n flex: none;\n padding: 7px 14px;\n font-size: 13px;\n line-height: 20px;\n position: relative;\n}\n\n.l0H8fW_tab:hover {\n background: var(--dsw-alias-interactive-bg-hover, #2631480f);\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.l0H8fW_tabOn {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-weight: 600;\n}\n\n.l0H8fW_tabOn:after {\n background: var(--dsw-alias-brand-primary);\n content: \"\";\n border-radius: 2px;\n height: 2px;\n position: absolute;\n bottom: 0;\n left: 10px;\n right: 10px;\n}\n\n.l0H8fW_tabPanel {\n flex-direction: column;\n flex: 1;\n min-height: 0;\n display: flex;\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=".qUlk6a_overlay {\n z-index: 2147483647;\n box-sizing: border-box;\n background: var(--dsw-alias-bg-mask-3);\n backdrop-filter: blur(3px);\n cursor: progress;\n outline: none;\n place-items: center;\n display: grid;\n position: fixed;\n overflow: hidden;\n}\n\n.qUlk6a_overlay[data-visible=\"false\"] {\n backdrop-filter: none;\n background: none;\n}\n\n.qUlk6a_overlay[data-visible=\"true\"] {\n animation: .14s ease-out qUlk6a_busy-enter;\n}\n\n.qUlk6a_content {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n width: min(360px, 100% - 32px);\n color: var(--dsw-alias-label-primary);\n text-align: center;\n border-radius: 8px;\n flex-direction: column;\n align-items: center;\n gap: 12px;\n padding: 24px;\n display: flex;\n}\n\n.qUlk6a_spinner {\n width: 28px;\n height: 28px;\n animation: .9s linear infinite qUlk6a_busy-spin;\n display: flex;\n}\n\n.qUlk6a_label {\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.qUlk6a_hintViewport {\n width: 100%;\n min-height: 54px;\n overflow: hidden;\n}\n\n.qUlk6a_hint {\n color: var(--dsw-alias-label-secondary);\n overflow-wrap: anywhere;\n margin: 0;\n font-size: 13px;\n line-height: 18px;\n animation: .3s ease-out qUlk6a_busy-hint;\n}\n\n.qUlk6a_warning {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n background: var(--dsw-alias-state-warn-tertiary, #fef5e7);\n overflow-wrap: anywhere;\n border-radius: 6px;\n margin: 0;\n padding: 6px 8px;\n font-size: 12px;\n line-height: 17px;\n}\n\n@keyframes qUlk6a_busy-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n@keyframes qUlk6a_busy-enter {\n from {\n opacity: 0;\n }\n\n to {\n opacity: 1;\n }\n}\n\n@keyframes qUlk6a_busy-hint {\n from {\n opacity: 0;\n transform: translateY(14px);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .qUlk6a_overlay, .qUlk6a_hint {\n animation: none;\n }\n\n .qUlk6a_spinner {\n animation-duration: 2.4s;\n }\n}\n._72qoAq_market {\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n gap: 24px;\n display: flex;\n container-type: inline-size;\n}\n\n._72qoAq_pageMode {\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: 0;\n}\n\n._72qoAq_marketControls {\n flex-direction: column;\n gap: 8px;\n min-height: 0;\n display: flex;\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\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:focus-visible, ._72qoAq_srcTabMain:focus-visible, ._72qoAq_srcTabEdit:focus-visible, ._72qoAq_srcTabDel: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_sourceTabsBox {\n min-width: 0;\n position: relative;\n}\n\n._72qoAq_sourceTabsRow {\n grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));\n gap: 4px;\n min-width: 0;\n display: grid;\n}\n\n._72qoAq_sourceTabsBoxFold {\n clip-path: inset(-6px);\n height: 52px;\n}\n\n._72qoAq_sourceTabsBoxFold:hover, ._72qoAq_sourceTabsBoxFold:has(:focus-visible) {\n clip-path: none;\n z-index: 20;\n}\n\n._72qoAq_sourceTabsBoxFold ._72qoAq_sourceTabsRow {\n box-sizing: border-box;\n background: var(--dsw-alias-bg-layer-1, #fff);\n border-radius: 10px;\n max-height: 58px;\n padding: 6px 6px 0;\n transition: max-height .16s, box-shadow .16s, padding-bottom .16s;\n position: absolute;\n inset: -6px -6px auto;\n overflow: hidden;\n -webkit-mask-image: linear-gradient(#000 78%, #0000 100%);\n mask-image: linear-gradient(#000 78%, #0000 100%);\n}\n\n._72qoAq_sourceTabsBoxFold:hover ._72qoAq_sourceTabsRow, ._72qoAq_sourceTabsBoxFold:has(:focus-visible) ._72qoAq_sourceTabsRow {\n z-index: 30;\n max-height: 420px;\n box-shadow: 0 0 0 1px var(--dsw-alias-border-l3, #d9dde3),\n 0 12px 28px #10182829;\n padding-bottom: 6px;\n -webkit-mask-image: none;\n mask-image: none;\n}\n\n._72qoAq_sourceTabsBoxFold._72qoAq_sourceTabsBoxPicked:hover, ._72qoAq_sourceTabsBoxFold._72qoAq_sourceTabsBoxPicked:has(:focus-visible) {\n clip-path: inset(-6px);\n}\n\n._72qoAq_sourceTabsBoxFold._72qoAq_sourceTabsBoxPicked:hover ._72qoAq_sourceTabsRow, ._72qoAq_sourceTabsBoxFold._72qoAq_sourceTabsBoxPicked:has(:focus-visible) ._72qoAq_sourceTabsRow {\n max-height: 58px;\n box-shadow: none;\n padding-bottom: 0;\n -webkit-mask-image: linear-gradient(#000 78%, #0000 100%);\n mask-image: linear-gradient(#000 78%, #0000 100%);\n}\n\n._72qoAq_unmanagedRow {\n color: var(--dsw-alias-label-secondary, #57606a);\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin-top: 6px;\n font-size: 12px;\n display: flex;\n}\n\n._72qoAq_unmanagedLabel {\n flex-shrink: 0;\n}\n\n._72qoAq_unmanagedChip {\n border: 1px dashed var(--dsw-alias-border-l3, #d9dde3);\n background: var(--dsw-alias-bg-layer-1, #fff);\n border-radius: 999px;\n align-items: center;\n gap: 2px;\n max-width: 220px;\n height: 22px;\n padding: 0 4px 0 8px;\n display: inline-flex;\n}\n\n._72qoAq_unmanagedChipName {\n white-space: nowrap;\n text-overflow: ellipsis;\n font-size: 12px;\n overflow: hidden;\n}\n\n._72qoAq_unmanagedAdopt {\n font: inherit;\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n cursor: pointer;\n background: none;\n border: none;\n flex-shrink: 0;\n padding: 0 4px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_unmanagedAdopt:disabled {\n cursor: default;\n opacity: .5;\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 margin-left: 4px;\n padding: 0 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: auto;\n max-width: 100%;\n height: 24px;\n padding: 0 10px;\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: 0;\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, #0f1115);\n border-color: var(--dsw-alias-brand-primary, #0f1115);\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 margin-left: 4px;\n padding: 0 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, ._72qoAq_list ._72qoAq_cardActions {\n flex: none;\n}\n\n._72qoAq_list ._72qoAq_meta, ._72qoAq_list ._72qoAq_tagRow {\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_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_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_confirmCheck {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: row;\n align-items: center;\n gap: 8px;\n font-size: 12px;\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(640px, 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_installConfirmCommit {\n color: var(--dsw-alias-label-secondary, #4b5563);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\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-state-warn-label, #dd8629);\n border: 1px solid var(--dsw-alias-state-warn-label, #dd8629);\n border-radius: 8px;\n padding: 8px 10px;\n font-size: 12px;\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-state-error-primary, #ec1313);\n color: var(--dsw-alias-state-error-primary, #ec1313);\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_sourceTabsRow {\n grid-template-columns: repeat(auto-fill, minmax(102px, 1fr));\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-label-secondary, #61666b);\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-brand-primary-new-colorprimary-new-color, #4176e6);\n margin: 0;\n}\n\n._72qoAq_pluginCard {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-3, #fff);\n border-radius: 12px;\n list-style: none;\n transition: border-color .16s, background .16s;\n container: _72qoAq_market-config / inline-size;\n}\n\n._72qoAq_pluginCard:hover {\n border-color: var(--dsw-alias-label-dimmed, #c8ccd4);\n}\n\n._72qoAq_pluginCardOpen {\n background: var(--dsw-alias-bg-layer-2, #f7f8fa);\n border-color: var(--dsw-alias-label-dimmed, #c8ccd4);\n}\n\n._72qoAq_pluginCard[data-busy=\"true\"] {\n opacity: .6;\n pointer-events: none;\n}\n\n._72qoAq_pluginCardHeader {\n appearance: none;\n width: 100%;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: none;\n border: 0;\n border-radius: 12px;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n display: flex;\n}\n\n._72qoAq_pluginCardHeader:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: -2px;\n}\n\n._72qoAq_pluginCardBody {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n flex-direction: column;\n gap: 8px;\n margin: 0 16px;\n padding: 4px 0 8px;\n display: flex;\n}\n\n._72qoAq_pluginCardRow {\n justify-content: space-between;\n align-items: center;\n gap: 16px;\n padding: 8px 0 4px;\n display: flex;\n}\n\n._72qoAq_pluginCardText {\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n display: flex;\n}\n\n._72qoAq_pluginCardTitle {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n._72qoAq_pluginCardDesc {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 13px;\n line-height: 1.5;\n}\n\n._72qoAq_pluginCardRowLabel {\n font-size: 13px;\n font-weight: 500;\n line-height: 20px;\n}\n\n@container _72qoAq_market-config (width <= 320px) {\n ._72qoAq_pluginCardRow {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n ._72qoAq_pluginCardText {\n overflow-wrap: anywhere;\n width: 100%;\n }\n\n ._72qoAq_regionSeg {\n flex-wrap: wrap;\n max-width: 100%;\n }\n}\n\n._72qoAq_pluginCardError {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n}\n\n._72qoAq_pluginFieldHead {\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n._72qoAq_pluginFieldBadges {\n align-items: center;\n gap: 6px;\n display: inline-flex;\n}\n\n._72qoAq_pluginFieldReset {\n appearance: none;\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n text-underline-offset: 2px;\n background: none;\n border: 0;\n padding: 0;\n font-size: 12px;\n line-height: 18px;\n text-decoration: underline;\n}\n\n._72qoAq_pluginFieldReset:disabled {\n cursor: default;\n opacity: .5;\n}\n\n._72qoAq_pluginCardReadonly {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n}\n\n._72qoAq_pluginCardFooter {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n margin-top: 4px;\n padding-top: 8px;\n display: flex;\n}\n\n._72qoAq_pluginCardFooter ._72qoAq_pluginCardError {\n margin-right: auto;\n}\n\n._72qoAq_pluginCardDiscard, ._72qoAq_pluginCardSave {\n appearance: none;\n font: inherit;\n cursor: pointer;\n border-radius: 8px;\n padding: 4px 12px;\n font-size: 13px;\n line-height: 20px;\n}\n\n._72qoAq_pluginCardDiscard {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n color: var(--dsw-alias-label-primary, #1f2328);\n background: none;\n}\n\n._72qoAq_pluginCardDiscard:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover, #0000000a);\n}\n\n._72qoAq_pluginCardSave {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n border: 1px solid #0000;\n}\n\n._72qoAq_pluginCardSave:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n._72qoAq_pluginCardDiscard:disabled, ._72qoAq_pluginCardSave:disabled {\n cursor: default;\n opacity: .5;\n}\n\n._72qoAq_pluginChevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n flex: none;\n transition: transform .16s;\n display: inline-flex;\n}\n\n._72qoAq_pluginChevronOpen {\n transform: rotate(180deg);\n}\n\n._72qoAq_regionSeg {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n flex: none;\n gap: 2px;\n padding: 2px;\n display: inline-flex;\n}\n\n._72qoAq_regionSegBtn {\n appearance: none;\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n padding: 3px 10px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_regionSegOn {\n appearance: none;\n font: inherit;\n cursor: pointer;\n background: var(--dsw-alias-bg-layer-2, #eef0f4);\n color: var(--dsw-alias-label-primary, #1f2328);\n border: none;\n border-radius: 6px;\n padding: 3px 10px;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n}\n\n._72qoAq_regionSegEffective {\n appearance: none;\n font: inherit;\n cursor: pointer;\n color: var(--dsw-alias-label-primary, #1f2328);\n background: none;\n border: none;\n border-radius: 6px;\n padding: 3px 10px;\n font-size: 12px;\n line-height: 18px;\n}\n\n._72qoAq_regionSegBtn:disabled, ._72qoAq_regionSegOn:disabled {\n cursor: default;\n opacity: .5;\n}\n._5JDFMW_field {\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_field > label, ._5JDFMW_field > span, ._5JDFMW_field > ._5JDFMW_rowHead > span {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n font-weight: 600;\n}\n\n._5JDFMW_field input, ._5JDFMW_field select, ._5JDFMW_field textarea {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-1);\n width: 100%;\n min-width: 0;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n border-radius: 8px;\n padding: 7px 9px;\n font-size: 12px;\n}\n\n._5JDFMW_field textarea {\n resize: vertical;\n min-height: 240px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n line-height: 19px;\n}\n\n._5JDFMW_jsonArea {\n min-height: 220px;\n}\n\n._5JDFMW_fieldRow {\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_fieldRow > input {\n flex: auto;\n}\n\n._5JDFMW_field input:focus-visible, ._5JDFMW_field select:focus-visible, ._5JDFMW_field textarea:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n._5JDFMW_hint {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 400;\n line-height: 16px;\n}\n\n._5JDFMW_required {\n color: var(--dsw-alias-state-error-primary);\n margin-left: 4px;\n font-weight: 400;\n}\n\n._5JDFMW_emptyRows {\n border: 1px dashed var(--dsw-alias-border-l3);\n width: 100%;\n color: var(--dsw-alias-label-tertiary);\n font: inherit;\n text-align: left;\n cursor: pointer;\n background: none;\n border-radius: 8px;\n padding: 8px 10px;\n font-size: 11px;\n line-height: 16px;\n}\n\n._5JDFMW_emptyRows:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n._5JDFMW_form {\n flex-direction: column;\n gap: 10px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_editorBody {\n max-width: 620px;\n}\n\n._5JDFMW_formGrid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n align-items: start;\n gap: 10px;\n display: grid;\n}\n\n._5JDFMW_full {\n grid-column: 1 / -1;\n}\n\n._5JDFMW_seg {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n flex: none;\n gap: 2px;\n padding: 2px;\n display: inline-flex;\n}\n\n._5JDFMW_seg button {\n height: 24px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n background: none;\n border: none;\n border-radius: 6px;\n padding: 0 10px;\n font-size: 12px;\n}\n\n._5JDFMW_seg button:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._5JDFMW_seg button[aria-pressed=\"true\"] {\n background: var(--dsw-alias-interactive-bg-active);\n color: var(--dsw-alias-label-primary);\n font-weight: 600;\n}\n\n._5JDFMW_seg button:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n\n._5JDFMW_readonly {\n border: 1px dashed var(--dsw-alias-border-l3);\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n border-radius: 8px;\n padding: 7px 9px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n}\n\n._5JDFMW_rows {\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_row {\n align-items: center;\n gap: 6px;\n min-width: 0;\n display: flex;\n}\n\n._5JDFMW_row input {\n flex: auto;\n width: 0;\n min-width: 0;\n}\n\n._5JDFMW_rowKey {\n flex: 0 0 34%;\n}\n\n._5JDFMW_rowKeyNarrow {\n flex: 0 0 26%;\n}\n\n._5JDFMW_rowActions {\n flex: none;\n align-items: center;\n gap: 2px;\n display: flex;\n}\n\n._5JDFMW_iconBtn {\n width: 24px;\n height: 24px;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n justify-content: center;\n align-items: center;\n padding: 0;\n display: inline-flex;\n}\n\n._5JDFMW_iconBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n._5JDFMW_rowHead {\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n min-height: 24px;\n display: flex;\n}\n\n._5JDFMW_addIcon {\n width: 24px;\n height: 24px;\n color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n justify-content: center;\n align-items: center;\n padding: 0;\n display: inline-flex;\n}\n\n._5JDFMW_addIcon:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._5JDFMW_addIcon:disabled {\n cursor: default;\n opacity: .4;\n}\n\n._5JDFMW_addIcon svg {\n display: block;\n}\n\n._5JDFMW_inlineCheck {\n color: var(--dsw-alias-label-primary);\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: inline-flex;\n}\n\n._5JDFMW_fieldset {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 12px;\n min-width: 0;\n margin: 0;\n padding: 2px 12px 12px;\n display: grid;\n}\n\n._5JDFMW_fieldset legend {\n color: var(--dsw-alias-label-secondary);\n padding: 0 4px;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n}\n\n._5JDFMW_fieldset > ._5JDFMW_hint, ._5JDFMW_fieldset > ._5JDFMW_full {\n grid-column: 1 / -1;\n}\n\n._5JDFMW_previewBox {\n border: 1px solid var(--dsw-alias-border-l2);\n box-sizing: border-box;\n border-radius: 8px;\n min-height: 300px;\n padding: 12px 14px;\n overflow-y: auto;\n}\n\n._5JDFMW_footer {\n flex: 1;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n._5JDFMW_footerHint {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n._5JDFMW_grow {\n flex: auto;\n}\n\n._5JDFMW_footerError {\n color: var(--dsw-alias-state-error-primary);\n font-size: 12px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._5JDFMW_seg button, ._5JDFMW_addIcon, ._5JDFMW_iconBtn {\n transition: none;\n }\n}\n\n@container (width <= 700px) {\n ._5JDFMW_formGrid, ._5JDFMW_fieldset {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n.IgyjIq_card[data-resource-state] {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-1);\n min-width: 0;\n max-width: 100%;\n color: var(--dsw-alias-label-primary);\n box-shadow: none;\n cursor: pointer;\n border-left-width: 3px;\n border-radius: 10px;\n gap: 4px 10px;\n padding: 11px 12px 11px 13px;\n transition: border-color .14s, background .14s;\n display: grid;\n position: relative;\n overflow: hidden;\n}\n\n.IgyjIq_card[data-resource-state=\"active\"] {\n border-left-color: var(--dsw-alias-state-success-primary);\n}\n\n.IgyjIq_card[data-resource-state=\"disabled\"] {\n border-left-color: var(--dsw-alias-label-tertiary);\n}\n\n.IgyjIq_card[data-resource-state=\"warning\"] {\n border-left-color: var(--dsw-alias-state-warn-primary);\n}\n\n.IgyjIq_card[data-resource-state=\"error\"] {\n border-left-color: var(--dsw-alias-state-error-primary);\n}\n\n.IgyjIq_card[data-resource-state]:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:hover .IgyjIq_rowActions, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:focus-within .IgyjIq_rowActions {\n z-index: 1;\n}\n\n.IgyjIq_collection[data-resource-view] {\n box-sizing: border-box;\n scrollbar-gutter: stable;\n align-content: start;\n align-items: stretch;\n width: 100%;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n}\n\n.IgyjIq_collection[data-resource-view=\"grid\"] {\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n grid-auto-rows: 122px;\n gap: 10px;\n padding-right: 4px;\n display: grid;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] {\n flex-direction: column;\n gap: 6px;\n padding-right: 4px;\n display: flex;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] > .IgyjIq_card {\n flex-shrink: 0;\n}\n\n.IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] {\n grid-template: \"IgyjIq_id IgyjIq_act\"\n \"IgyjIq_body IgyjIq_body\" minmax(0, 1fr)\n \"IgyjIq_foot IgyjIq_foot\"\n / minmax(0, 1fr) auto;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] > .IgyjIq_card[data-resource-state] {\n box-sizing: border-box;\n grid-template-columns: minmax(160px, .85fr) minmax(210px, 1.05fr) minmax(0, 1.5fr) auto;\n grid-template-areas: \"IgyjIq_id IgyjIq_foot IgyjIq_body IgyjIq_act\";\n align-items: center;\n gap: 16px;\n height: 56px;\n}\n\n@container (width <= 700px) {\n .IgyjIq_collection[data-resource-view=\"grid\"] {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n grid-auto-rows: max-content;\n gap: 4px;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] {\n grid-template: \"IgyjIq_id\"\n \"IgyjIq_body\"\n \"IgyjIq_foot\"\n / minmax(0, 1fr);\n align-content: start;\n gap: 4px;\n padding: 10px 10px 10px 13px;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] .IgyjIq_rowId, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] .IgyjIq_rowBody {\n overflow: hidden;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state] .IgyjIq_rowActions {\n background: var(--dsw-alias-bg-layer-1);\n box-shadow: 0 0 6px 8px var(--dsw-alias-bg-layer-1);\n opacity: 0;\n border-radius: 16px;\n gap: 4px;\n margin-left: 0;\n padding: 4px 6px;\n transition: opacity .14s;\n position: absolute;\n top: 8px;\n bottom: auto;\n right: 8px;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:hover .IgyjIq_rowActions, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:focus-within .IgyjIq_rowActions {\n opacity: 1;\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:hover, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-state]:focus-within {\n background: var(--dsw-alias-bg-layer-1);\n }\n\n .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-surface=\"mcp\"] .IgyjIq_provenanceChip, .IgyjIq_collection[data-resource-view=\"grid\"] > .IgyjIq_card[data-resource-surface=\"lsp\"] .IgyjIq_provenanceChip {\n display: none;\n }\n\n .IgyjIq_collection[data-resource-view=\"list\"] > .IgyjIq_card[data-resource-state] {\n grid-template-columns: minmax(0, 1fr) auto;\n grid-template-areas: \"IgyjIq_id IgyjIq_act\"\n \"IgyjIq_foot IgyjIq_act\"\n \"IgyjIq_body IgyjIq_act\";\n height: auto;\n padding-block: 10px;\n }\n}\n\n@container (width <= 420px) {\n .IgyjIq_collection[data-resource-view=\"grid\"] {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.IgyjIq_rowId {\n grid-area: IgyjIq_id;\n align-items: center;\n gap: 7px;\n min-width: 0;\n min-height: 24px;\n display: flex;\n}\n\n.IgyjIq_rowBody {\n grid-area: IgyjIq_body;\n min-width: 0;\n overflow: hidden;\n}\n\n.IgyjIq_rowFoot {\n grid-area: IgyjIq_foot;\n align-items: center;\n gap: 7px;\n min-width: 0;\n min-height: 16px;\n display: flex;\n overflow: hidden;\n}\n\n.IgyjIq_rowActions {\n border-radius: 8px;\n flex: none;\n grid-area: IgyjIq_act;\n justify-content: flex-end;\n align-items: center;\n gap: 2px;\n margin-left: auto;\n display: flex;\n position: relative;\n}\n\n.IgyjIq_name {\n min-width: 0;\n color: var(--dsw-alias-label-primary);\n white-space: nowrap;\n font-size: 13px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.IgyjIq_nameMono {\n letter-spacing: -.01em;\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 12.5px;\n}\n\n.IgyjIq_version {\n color: var(--dsw-alias-label-tertiary);\n font-variant-numeric: tabular-nums;\n flex: none;\n font-size: 11px;\n}\n\n.IgyjIq_desc {\n max-height: 34px;\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 12px;\n line-height: 17px;\n overflow: hidden;\n}\n\n.IgyjIq_monoLine {\n max-height: 34px;\n color: var(--dsw-alias-label-tertiary);\n overflow-wrap: anywhere;\n margin: 0;\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 11.5px;\n line-height: 17px;\n overflow: hidden;\n}\n\n.IgyjIq_provenance, .IgyjIq_path {\n color: var(--dsw-alias-label-tertiary);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 0 auto;\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 11px;\n overflow: hidden;\n}\n\n.IgyjIq_count {\n color: var(--dsw-alias-label-tertiary);\n white-space: nowrap;\n flex: none;\n font-size: 11px;\n}\n\n.IgyjIq_countValue {\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n font-weight: 600;\n}\n\n.IgyjIq_separator {\n color: var(--dsw-alias-label-dimmed);\n flex: none;\n font-size: 11px;\n}\n\n.IgyjIq_iconBtn {\n width: 24px;\n height: 24px;\n color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n justify-content: center;\n align-items: center;\n padding: 0;\n display: inline-flex;\n}\n\n.IgyjIq_iconBtn:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.IgyjIq_iconBtn:disabled {\n cursor: default;\n opacity: .4;\n}\n\n.IgyjIq_iconBtnDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n.IgyjIq_iconBtn:focus-visible, .IgyjIq_rowActions :focus-visible, .IgyjIq_card[data-resource-state]:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n\n.IgyjIq_revealOnHover {\n opacity: 0;\n transition: opacity .14s;\n}\n\n.IgyjIq_card[data-resource-state]:hover .IgyjIq_revealOnHover, .IgyjIq_card[data-resource-state]:focus-within .IgyjIq_revealOnHover {\n opacity: 1;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] .IgyjIq_desc, .IgyjIq_collection[data-resource-view=\"list\"] .IgyjIq_monoLine {\n max-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 11.5px;\n display: block;\n overflow: hidden;\n}\n\n.IgyjIq_collection[data-resource-view=\"list\"] .IgyjIq_revealOnHover {\n opacity: 1;\n}\n\n.IgyjIq_switchWrap, .IgyjIq_warnWrap {\n flex: none;\n align-items: center;\n display: inline-flex;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .IgyjIq_card[data-resource-state], .IgyjIq_revealOnHover, .IgyjIq_rowActions {\n transition: none;\n }\n}\n.sBXwgW_dialog[role=\"dialog\"] {\n box-sizing: border-box;\n max-width: calc(100vw - 48px);\n max-height: calc(100dvh - 48px);\n}\n\n.sBXwgW_dialog[role=\"dialog\"].sBXwgW_sizeSm {\n width: min(460px, 100vw - 48px);\n}\n\n.sBXwgW_dialog[role=\"dialog\"].sBXwgW_sizeMd {\n width: min(640px, 100vw - 48px);\n}\n\n.sBXwgW_dialog[role=\"dialog\"].sBXwgW_sizeLg {\n width: min(880px, 100vw - 48px);\n}\n\n.sBXwgW_body {\n overflow-wrap: anywhere;\n min-width: 0;\n min-height: 0;\n max-height: calc(100dvh - 200px);\n overflow-y: auto;\n}\n\n.sBXwgW_footer {\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n width: 100%;\n display: flex;\n}\n\n.sBXwgW_footer > :first-child {\n flex: 1;\n}\n\n.sBXwgW_footerSlot:empty {\n display: none;\n}\n\n.sBXwgW_frontmatter {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-markdown-code-block);\n color: var(--dsw-alias-label-tertiary);\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n border-radius: 8px;\n margin: 0 0 10px;\n padding: 8px 10px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11.5px;\n line-height: 18px;\n}\n\n.sBXwgW_preview {\n min-width: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 14px;\n line-height: 1.6;\n}\n\n.sBXwgW_preview pre, .sBXwgW_preview table {\n max-width: 100%;\n overflow: auto;\n}\n\n.sBXwgW_preview img {\n max-width: 100%;\n height: auto;\n}\n\n.sBXwgW_error {\n color: var(--dsw-alias-state-error-primary);\n margin: 8px 0;\n font-size: 13px;\n}\n\n.sBXwgW_pair {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 16px;\n display: grid;\n}\n\n.sBXwgW_row {\n align-items: center;\n gap: 6px;\n min-width: 0;\n display: flex;\n}\n\n.sBXwgW_row input {\n flex: 1;\n width: 0;\n}\n\n.sBXwgW_row button {\n flex: none;\n}\n\n@media (width <= 640px) {\n .sBXwgW_dialog[role=\"dialog\"] {\n width: calc(100vw - 16px);\n max-width: calc(100vw - 16px);\n max-height: calc(100dvh - 16px);\n }\n\n .sBXwgW_form {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n._9Lujra_rows {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n flex-direction: column;\n min-width: 0;\n display: flex;\n overflow: hidden;\n}\n\n._9Lujra_group {\n flex-direction: column;\n min-width: 0;\n display: flex;\n}\n\n._9Lujra_group + ._9Lujra_group ._9Lujra_row {\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n\n._9Lujra_row {\n box-sizing: border-box;\n width: 100%;\n color: inherit;\n text-align: left;\n font: inherit;\n background: none;\n border: none;\n grid-template-columns: minmax(110px, max-content) minmax(0, 1fr) 14px;\n align-items: center;\n gap: 12px;\n padding: 9px 12px;\n display: grid;\n}\n\nbutton._9Lujra_row {\n cursor: pointer;\n}\n\n._9Lujra_row:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n._9Lujra_row[aria-expanded=\"true\"] {\n background: var(--dsw-alias-state-business-tertiary);\n}\n\n._9Lujra_row:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n._9Lujra_name {\n color: var(--dsw-alias-label-primary);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11.5px;\n font-weight: 600;\n overflow: hidden;\n}\n\n._9Lujra_summary {\n color: var(--dsw-alias-label-tertiary);\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 11.5px;\n overflow: hidden;\n}\n\n._9Lujra_chevron {\n color: var(--dsw-alias-label-tertiary);\n justify-self: end;\n display: inline-flex;\n}\n\n._9Lujra_chevron svg {\n display: block;\n}\n\n._9Lujra_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-interactive-bg-hover);\n padding: 12px 14px;\n}\n.HJ9x7a_shell {\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n gap: 16px;\n display: flex;\n container-type: inline-size;\n}\n\n.HJ9x7a_header {\n flex-direction: row;\n flex: none;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n min-height: 46px;\n display: flex;\n}\n\n.HJ9x7a_headerText {\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n display: flex;\n}\n\n.HJ9x7a_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.HJ9x7a_subtitle {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n.HJ9x7a_headerActions {\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.HJ9x7a_body {\n scrollbar-gutter: stable;\n flex-direction: column;\n flex: 1;\n gap: 12px;\n min-height: 0;\n display: flex;\n overflow-y: auto;\n}\n\n.HJ9x7a_busyLine {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: flex;\n}\n\n.HJ9x7a_busyLabel {\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n overflow: hidden;\n}\n\n.HJ9x7a_spinner {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex: none;\n font-size: 13px;\n display: inline-flex;\n}\n\n.HJ9x7a_spinning {\n animation: .9s linear infinite HJ9x7a_panel-spin;\n}\n\n@keyframes HJ9x7a_panel-spin {\n from {\n transform: rotate(0);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .HJ9x7a_spinning {\n animation-duration: 2.4s;\n }\n}\n\n.HJ9x7a_editorDialog {\n gap: 12px;\n max-width: 720px;\n}\n\n.HJ9x7a_editorDialog [class*=\"content\"] > [class*=\"body\"] {\n margin-top: 0;\n}\n\n.HJ9x7a_editorBody {\n flex-direction: column;\n gap: 12px;\n display: flex;\n}\n\n.HJ9x7a_editorFooter {\n flex-direction: row;\n flex: 1;\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n.HJ9x7a_editorError {\n color: var(--dsw-alias-state-error-primary, #c81e1e);\n margin-right: auto;\n font-size: 12px;\n}\n\n.HJ9x7a_confirmCheck {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: row;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: flex;\n}\n\n.HJ9x7a_empty {\n color: var(--dsw-alias-label-tertiary, #6b7280);\n text-align: center;\n padding: 24px 12px;\n font-size: 12px;\n}\n\n@container (width <= 540px) {\n .HJ9x7a_entryGrid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .HJ9x7a_entryRow {\n flex-wrap: wrap;\n }\n\n .HJ9x7a_entryActions {\n margin-left: auto;\n }\n\n .HJ9x7a_entryMain {\n flex-basis: 100%;\n }\n}\n\n.HJ9x7a_hero {\n background: var(--dsw-alias-interactive-bg-hover);\n border-radius: 10px;\n align-items: center;\n gap: 10px;\n padding: 12px 14px;\n display: flex;\n}\n\n.HJ9x7a_heroText {\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n display: flex;\n}\n\n.HJ9x7a_heroLine {\n flex-wrap: wrap;\n align-items: center;\n gap: 7px;\n display: flex;\n}\n\n.HJ9x7a_heroMono {\n overflow-wrap: anywhere;\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font: 12px / 18px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.HJ9x7a_block {\n margin-top: 18px;\n}\n\n.HJ9x7a_blockHead {\n color: var(--dsw-alias-label-secondary);\n letter-spacing: .04em;\n text-transform: uppercase;\n margin: 0 0 8px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.HJ9x7a_kvGrid {\n grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));\n gap: 10px 16px;\n margin: 0;\n display: grid;\n}\n\n.HJ9x7a_kvKey {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 16px;\n}\n\n.HJ9x7a_kvValue {\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: 3px 0 0;\n font-size: 12.5px;\n line-height: 18px;\n overflow: hidden;\n}\n\n.HJ9x7a_monoBlock {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-markdown-code-block);\n color: var(--dsw-alias-label-secondary);\n border-radius: 10px;\n margin: 0;\n padding: 12px 14px;\n font: 11.5px / 18px ui-monospace, Menlo, Consolas, monospace;\n overflow-x: auto;\n}\n\n.HJ9x7a_detailProse {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 13px;\n line-height: 21px;\n}\n\n.HJ9x7a_kvValueMono {\n font-family: ui-monospace, Menlo, Consolas, monospace;\n}\n.vavGuW_toolbar {\n flex: none;\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.vavGuW_search {\n flex: auto;\n align-items: center;\n min-width: 0;\n display: flex;\n}\n\n.vavGuW_searchInput {\n flex: auto;\n min-width: 0;\n}\n\n.vavGuW_searchInput input {\n font-size: 12px;\n line-height: 20px;\n}\n\n.vavGuW_segment {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n flex: none;\n align-items: center;\n gap: 2px;\n padding: 3px;\n display: flex;\n}\n\n.vavGuW_count {\n color: var(--dsw-alias-label-tertiary);\n font-variant-numeric: tabular-nums;\n}\n\n.vavGuW_segment svg {\n stroke: currentColor;\n stroke-width: 1.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n display: block;\n}\n\n@container (width <= 480px) {\n .vavGuW_toolbar {\n flex-wrap: wrap;\n justify-content: flex-end;\n }\n\n .vavGuW_search {\n flex-basis: 100%;\n }\n}\n._5BoKRG_editor {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-1);\n box-sizing: border-box;\n border-radius: 8px;\n flex-direction: column;\n display: flex;\n overflow: hidden;\n}\n\n._5BoKRG_editor .cm-editor {\n flex: 1;\n min-height: 0;\n}\n\n._5BoKRG_editor .cm-scroller {\n overflow: auto;\n}\n.G2mDja_form {\n background: var(--dsw-alias-bg-layer-2, #f7f8fa);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 10px;\n flex-direction: column;\n gap: 10px;\n padding: 12px 14px;\n display: flex;\n}\n\n.G2mDja_head {\n color: var(--dsw-alias-label-secondary, #667085);\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n}\n\n.G2mDja_error {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n background: var(--dsw-alias-interactive-bg-hover-danger, #ec13130d);\n overflow-wrap: anywhere;\n border-radius: 8px;\n padding: 8px 10px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.G2mDja_row {\n border-top: 1px solid var(--dsw-alias-border-l1, #eef1f5);\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n padding-top: 8px;\n display: flex;\n}\n\n.G2mDja_rowHead {\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.G2mDja_grow {\n flex: auto;\n}\n\n.G2mDja_where {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n overflow-wrap: anywhere;\n font-size: 11px;\n line-height: 17px;\n}\n\n.G2mDja_ref {\n color: var(--dsw-alias-label-primary, #1f2328);\n font: 600 12px / 18px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.G2mDja_controls {\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n display: flex;\n}\n\n.G2mDja_facts {\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.G2mDja_factOk, .G2mDja_factMiss {\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n}\n\n.G2mDja_factOk {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n background: var(--dsw-alias-state-success-tertiary, #e6faed);\n}\n\n.G2mDja_factMiss {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n background: var(--dsw-alias-state-warn-tertiary, #fef5e7);\n}\n\n.G2mDja_note {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 11px;\n line-height: 17px;\n}\n\n.G2mDja_editor {\n flex-direction: column;\n gap: 8px;\n display: flex;\n}\n\n.G2mDja_input {\n box-sizing: border-box;\n width: 100%;\n color: var(--dsw-alias-label-primary, #1f2328);\n background: var(--dsw-alias-bg-layer-1, #fff);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n padding: 7px 10px;\n font-size: 12px;\n}\n\n.G2mDja_input:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary, #4f6ef7);\n outline-offset: 1px;\n}\n\n.G2mDja_actions {\n align-items: center;\n gap: 8px;\n display: flex;\n}\n.HJ9x7a_shell {\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n gap: 16px;\n display: flex;\n container-type: inline-size;\n}\n\n.HJ9x7a_header {\n flex-direction: row;\n flex: none;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n min-height: 46px;\n display: flex;\n}\n\n.HJ9x7a_headerText {\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n display: flex;\n}\n\n.HJ9x7a_title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.HJ9x7a_subtitle {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 13px;\n line-height: 20px;\n}\n\n.HJ9x7a_headerActions {\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 6px;\n display: flex;\n}\n\n.HJ9x7a_body {\n scrollbar-gutter: stable;\n flex-direction: column;\n flex: 1;\n gap: 12px;\n min-height: 0;\n display: flex;\n overflow-y: auto;\n}\n\n.HJ9x7a_busyLine {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: flex;\n}\n\n.HJ9x7a_busyLabel {\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n overflow: hidden;\n}\n\n.HJ9x7a_spinner {\n color: var(--dsw-alias-label-secondary, #6b7280);\n flex: none;\n font-size: 13px;\n display: inline-flex;\n}\n\n.HJ9x7a_spinning {\n animation: .9s linear infinite HJ9x7a_panel-spin;\n}\n\n@keyframes HJ9x7a_panel-spin {\n from {\n transform: rotate(0);\n }\n\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .HJ9x7a_spinning {\n animation-duration: 2.4s;\n }\n}\n\n.HJ9x7a_editorDialog {\n gap: 12px;\n max-width: 720px;\n}\n\n.HJ9x7a_editorDialog [class*=\"content\"] > [class*=\"body\"] {\n margin-top: 0;\n}\n\n.HJ9x7a_editorBody {\n flex-direction: column;\n gap: 12px;\n display: flex;\n}\n\n.HJ9x7a_editorFooter {\n flex-direction: row;\n flex: 1;\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n display: flex;\n}\n\n.HJ9x7a_editorError {\n color: var(--dsw-alias-state-error-primary, #c81e1e);\n margin-right: auto;\n font-size: 12px;\n}\n\n.HJ9x7a_confirmCheck {\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: row;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n display: flex;\n}\n\n.HJ9x7a_empty {\n color: var(--dsw-alias-label-tertiary, #6b7280);\n text-align: center;\n padding: 24px 12px;\n font-size: 12px;\n}\n\n@container (width <= 540px) {\n .HJ9x7a_entryGrid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .HJ9x7a_entryRow {\n flex-wrap: wrap;\n }\n\n .HJ9x7a_entryActions {\n margin-left: auto;\n }\n\n .HJ9x7a_entryMain {\n flex-basis: 100%;\n }\n}\n\n.HJ9x7a_hero {\n background: var(--dsw-alias-interactive-bg-hover);\n border-radius: 10px;\n align-items: center;\n gap: 10px;\n padding: 12px 14px;\n display: flex;\n}\n\n.HJ9x7a_heroText {\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n display: flex;\n}\n\n.HJ9x7a_heroLine {\n flex-wrap: wrap;\n align-items: center;\n gap: 7px;\n display: flex;\n}\n\n.HJ9x7a_heroMono {\n overflow-wrap: anywhere;\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font: 12px / 18px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.HJ9x7a_block {\n margin-top: 18px;\n}\n\n.HJ9x7a_blockHead {\n color: var(--dsw-alias-label-secondary);\n letter-spacing: .04em;\n text-transform: uppercase;\n margin: 0 0 8px;\n font-size: 11px;\n font-weight: 600;\n}\n\n.HJ9x7a_kvGrid {\n grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));\n gap: 10px 16px;\n margin: 0;\n display: grid;\n}\n\n.HJ9x7a_kvKey {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n line-height: 16px;\n}\n\n.HJ9x7a_kvValue {\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: 3px 0 0;\n font-size: 12.5px;\n line-height: 18px;\n overflow: hidden;\n}\n\n.HJ9x7a_monoBlock {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-markdown-code-block);\n color: var(--dsw-alias-label-secondary);\n border-radius: 10px;\n margin: 0;\n padding: 12px 14px;\n font: 11.5px / 18px ui-monospace, Menlo, Consolas, monospace;\n overflow-x: auto;\n}\n\n.HJ9x7a_detailProse {\n color: var(--dsw-alias-label-secondary);\n margin: 0;\n font-size: 13px;\n line-height: 21px;\n}\n\n.HJ9x7a_kvValueMono {\n font-family: ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_surface {\n min-width: 0;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n display: flex;\n}\n\n.AUWlZW_toolbar {\n flex: none;\n}\n\n@media (width <= 760px) {\n .AUWlZW_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.AUWlZW_reasonLabel {\n opacity: .85;\n flex: none;\n font-weight: 600;\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_detailBody {\n max-height: 72vh;\n overflow-y: auto;\n}\n\n.AUWlZW_modalFooter {\n justify-content: flex-end;\n align-items: center;\n gap: 8px;\n width: 100%;\n display: flex;\n}\n\n.AUWlZW_modalFooterHint {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n.AUWlZW_modalFooterGrow {\n flex: auto;\n}\n\n.AUWlZW_detail {\n flex-direction: column;\n gap: 16px;\n display: flex;\n}\n\n.AUWlZW_reasonBox {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n background: var(--dsw-alias-interactive-bg-hover-danger, #ec13130d);\n border-radius: 8px;\n flex-direction: column;\n gap: 4px;\n padding: 10px 12px;\n display: flex;\n}\n\n.AUWlZW_reasonText {\n overflow-wrap: anywhere;\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.AUWlZW_reasonActions {\n flex-wrap: wrap;\n gap: 8px;\n margin-top: 4px;\n display: flex;\n}\n\n.AUWlZW_reasonHint {\n color: var(--dsw-alias-label-secondary, #4e5969);\n overflow-wrap: anywhere;\n margin: 2px 0 0;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_blockHeadRow {\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n display: flex;\n}\n\n.AUWlZW_blockSub {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 0 0 6px;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_starter, .AUWlZW_starterList {\n flex-wrap: wrap;\n gap: 8px;\n display: flex;\n}\n\n.AUWlZW_starterPaste {\n flex-direction: column;\n gap: 8px;\n display: flex;\n}\n\n.AUWlZW_pasteArea {\n box-sizing: border-box;\n width: 100%;\n min-height: 120px;\n color: var(--dsw-alias-label-primary, #1f2328);\n background: var(--dsw-alias-bg-layer-1, #fff);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n resize: vertical;\n border-radius: 8px;\n padding: 7px 9px;\n font: 12px / 19px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_pasteNote {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 0;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_pasteCheck {\n color: var(--dsw-alias-label-secondary, #4e5969);\n align-items: center;\n gap: 8px;\n font-size: 11px;\n line-height: 16px;\n display: inline-flex;\n}\n\n.AUWlZW_pasteOutcome {\n flex-direction: column;\n gap: 2px;\n display: flex;\n}\n\n.AUWlZW_pasteOutcome p {\n color: var(--dsw-alias-label-secondary, #4e5969);\n overflow-wrap: anywhere;\n margin: 0;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_toolSearch {\n flex: 0 220px;\n min-width: 0;\n display: block;\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: minmax(140px, max-content) minmax(0, 1fr) max-content;\n align-items: center;\n gap: 12px;\n padding: 7px 0 7px 2px;\n display: grid;\n}\n\n.AUWlZW_tool:last-child {\n border-bottom: none;\n}\n\n.AUWlZW_toolIdentity {\n align-items: center;\n gap: 8px;\n min-width: 0;\n display: flex;\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, .AUWlZW_toolNote {\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.AUWlZW_toolNameButton {\n cursor: pointer;\n text-align: left;\n background: none;\n border: none;\n padding: 0;\n}\n\n.AUWlZW_toolNameButton:hover {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n\n.AUWlZW_toolParams {\n grid-column: 1 / -1;\n padding: 8px 0 2px 11px;\n}\n\n.AUWlZW_toolParamsGrid {\n grid-template-columns: minmax(120px, max-content) minmax(60px, max-content) max-content minmax(0, 1fr);\n align-items: baseline;\n gap: 6px 12px;\n display: grid;\n}\n\n.AUWlZW_toolParam {\n display: contents;\n}\n\n.AUWlZW_toolParamName {\n color: var(--dsw-alias-label-primary, #1f2328);\n font: 11px / 16px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_toolParamType {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font: 10px / 16px ui-monospace, Menlo, Consolas, monospace;\n}\n\n.AUWlZW_toolParamRequired {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n font-size: 10px;\n line-height: 16px;\n}\n\n.AUWlZW_toolParamDesc {\n overflow-wrap: anywhere;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 10px;\n line-height: 16px;\n}\n\n.AUWlZW_toolParamsEmpty {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 0;\n font-size: 10px;\n line-height: 16px;\n}\n\n.AUWlZW_toolMore {\n color: var(--dsw-alias-label-secondary, #667085);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 6px;\n align-self: flex-start;\n margin-top: 8px;\n padding: 4px 8px;\n font-size: 11px;\n line-height: 17px;\n}\n\n.AUWlZW_toolMore:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n@media (width <= 760px) {\n .AUWlZW_toolbar {\n padding-left: 0;\n padding-right: 0;\n }\n\n .AUWlZW_grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .AUWlZW_list .AUWlZW_cardTop {\n max-width: 100%;\n }\n\n .AUWlZW_tool {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .AUWlZW_toolDescription {\n display: none;\n }\n}\n\n.AUWlZW_retryEchoSuccess {\n color: var(--dsw-alias-state-success-primary, #16a34a);\n white-space: nowrap;\n font-size: 12px;\n line-height: 18px;\n}\n\n@keyframes AUWlZW_lspStartingPulse {\n 50% {\n opacity: .35;\n }\n}\n\n.AUWlZW_reasonRaw {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n word-break: break-all;\n margin: 6px 0 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n line-height: 1.5;\n}\n\n.AUWlZW_seamBanner {\n border-left: 3px solid var(--dsw-alias-state-warn-primary, #b45309);\n background: var(--dsw-alias-state-warn-tertiary, #b4530914);\n border-radius: 8px;\n flex-direction: column;\n gap: 8px;\n margin: 0 0 12px;\n padding: 12px 14px;\n display: flex;\n}\n\n.AUWlZW_seamTitle {\n color: var(--dsw-alias-label-primary, #1f2329);\n font-size: 13px;\n font-weight: 600;\n}\n\n.AUWlZW_seamBody {\n color: var(--dsw-alias-label-secondary, #4e5969);\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.AUWlZW_seamPathLabel {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 11px;\n}\n\n.AUWlZW_seamPath {\n color: var(--dsw-alias-label-secondary, #4e5969);\n overflow-wrap: anywhere;\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_seamOther {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 0;\n font-size: 11px;\n line-height: 16px;\n}\n\n.AUWlZW_seamDone {\n color: var(--dsw-alias-state-success-primary, #15803d);\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n}\n.l0H8fW_workspace {\n min-width: 0;\n height: 100%;\n min-height: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n flex-direction: column;\n flex: 1;\n gap: 12px;\n display: flex;\n}\n\n.l0H8fW_pageMode {\n box-sizing: border-box;\n padding: 4px 0;\n}\n\n.l0H8fW_tabRow {\n border-bottom: 1px solid var(--dsw-alias-border-l2, #0000001a);\n scrollbar-width: none;\n flex-direction: row;\n flex: none;\n align-items: center;\n gap: 4px;\n display: flex;\n overflow-x: auto;\n}\n\n.l0H8fW_tab, .l0H8fW_tabOn {\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-radius: 8px 8px 0 0;\n flex: none;\n padding: 7px 14px;\n font-size: 13px;\n line-height: 20px;\n position: relative;\n}\n\n.l0H8fW_tab:hover {\n background: var(--dsw-alias-interactive-bg-hover, #2631480f);\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.l0H8fW_tabOn {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-weight: 600;\n}\n\n.l0H8fW_tabOn:after {\n background: var(--dsw-alias-brand-primary);\n content: \"\";\n border-radius: 2px;\n height: 2px;\n position: absolute;\n bottom: 0;\n left: 10px;\n right: 10px;\n}\n\n.l0H8fW_tabPanel {\n flex-direction: column;\n flex: 1;\n min-height: 0;\n display: flex;\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;
|
|
@@ -238,7 +238,7 @@ function ActiveOverlay$1({ target, t, visible, slow }) {
|
|
|
238
238
|
}, visible ? (0, react.createElement)("div", { className: busy_overlay_module_default.content }, (0, react.createElement)("span", {
|
|
239
239
|
className: busy_overlay_module_default.spinner,
|
|
240
240
|
"aria-hidden": true
|
|
241
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
241
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconLoadingOutlineMedium, { size: 28 })), (0, react.createElement)("strong", { className: busy_overlay_module_default.label }, t("panelWorking")), (0, react.createElement)("div", { className: busy_overlay_module_default.hintViewport }, (0, react.createElement)("p", {
|
|
242
242
|
key: message,
|
|
243
243
|
className: busy_overlay_module_default.hint
|
|
244
244
|
}, hints[message])), slow ? (0, react.createElement)("p", {
|
|
@@ -303,6 +303,7 @@ const MARKET_ROUTES = {
|
|
|
303
303
|
overview: `${MARKET_API_PREFIX}overview`,
|
|
304
304
|
mcpStatus: `${MARKET_API_PREFIX}mcp-status`,
|
|
305
305
|
addMcpServer: `${MARKET_API_PREFIX}mcp-servers/add`,
|
|
306
|
+
importMcpServers: `${MARKET_API_PREFIX}mcp-servers/import`,
|
|
306
307
|
lspStatus: `${MARKET_API_PREFIX}lsp-status`,
|
|
307
308
|
lspServers: `${MARKET_API_PREFIX}lsp-servers`,
|
|
308
309
|
addLspServer: `${MARKET_API_PREFIX}lsp-servers/add`,
|
|
@@ -326,6 +327,7 @@ const MARKET_ROUTES = {
|
|
|
326
327
|
mcpOverrides: `${MARKET_API_PREFIX}mcp-overrides`,
|
|
327
328
|
setMcpOverride: `${MARKET_API_PREFIX}set-mcp-override`,
|
|
328
329
|
setMcpServerEnabled: `${MARKET_API_PREFIX}set-mcp-server-enabled`,
|
|
330
|
+
setMcpServerTool: `${MARKET_API_PREFIX}set-mcp-server-tool`,
|
|
329
331
|
mcpRetry: `${MARKET_API_PREFIX}mcp-retry`,
|
|
330
332
|
mcpReauthorize: `${MARKET_API_PREFIX}mcp-reauthorize`,
|
|
331
333
|
mcpBackend: `${MARKET_API_PREFIX}mcp-backend`,
|
|
@@ -411,7 +413,7 @@ async function postOkJson(url, body, label) {
|
|
|
411
413
|
body: JSON.stringify(body)
|
|
412
414
|
}, MUTATION_TIMEOUT_MS);
|
|
413
415
|
const payload = await response.json();
|
|
414
|
-
if (!response.ok || payload.ok !== true) throw new Error(payload.error ?? `${label}: ${response.status}`);
|
|
416
|
+
if (!response.ok || payload.ok !== true) throw Object.assign(new Error(payload.error ?? `${label}: ${response.status}`), { fields: payload.fields });
|
|
415
417
|
return payload;
|
|
416
418
|
}
|
|
417
419
|
async function fetchServerConfig(kind, id) {
|
|
@@ -425,12 +427,13 @@ async function fetchServerConfig(kind, id) {
|
|
|
425
427
|
return body;
|
|
426
428
|
});
|
|
427
429
|
}
|
|
428
|
-
async function saveServerConfig(kind, id, config) {
|
|
430
|
+
async function saveServerConfig(kind, id, config, policy) {
|
|
429
431
|
return withBusyOperation(async () => {
|
|
430
432
|
await postAction("server-config/save", {
|
|
431
433
|
kind,
|
|
432
434
|
id,
|
|
433
|
-
config
|
|
435
|
+
config,
|
|
436
|
+
...policy === void 0 ? {} : { policy }
|
|
434
437
|
});
|
|
435
438
|
});
|
|
436
439
|
}
|
|
@@ -494,6 +497,26 @@ async function addMcpServer(name, config) {
|
|
|
494
497
|
});
|
|
495
498
|
});
|
|
496
499
|
}
|
|
500
|
+
/** Import several pasted services in one write; each entry reports its own outcome. */
|
|
501
|
+
async function importMcpServers(servers, overwrite) {
|
|
502
|
+
return withBusyOperation(async () => {
|
|
503
|
+
const payload = await postAction("mcp-servers/import", {
|
|
504
|
+
servers,
|
|
505
|
+
overwrite
|
|
506
|
+
});
|
|
507
|
+
return {
|
|
508
|
+
imported: Array.isArray(payload["imported"]) ? payload["imported"].filter((value) => typeof value === "string") : [],
|
|
509
|
+
skipped: Array.isArray(payload["skipped"]) ? payload["skipped"].flatMap((entry) => {
|
|
510
|
+
if (typeof entry !== "object" || entry === null) return [];
|
|
511
|
+
const { name, reason } = entry;
|
|
512
|
+
return typeof name === "string" && typeof reason === "string" ? [{
|
|
513
|
+
name,
|
|
514
|
+
reason
|
|
515
|
+
}] : [];
|
|
516
|
+
}) : []
|
|
517
|
+
};
|
|
518
|
+
});
|
|
519
|
+
}
|
|
497
520
|
/** Drop one server's OAuth grant so its next mount re-runs browser authorization. */
|
|
498
521
|
async function reauthorizeMcpServer(serverName) {
|
|
499
522
|
return withBusyOperation(async () => {
|
|
@@ -516,6 +539,24 @@ async function setMcpServerEnabled(suiteId, serverKey, enabled) {
|
|
|
516
539
|
});
|
|
517
540
|
});
|
|
518
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* Allow or deny one tool of a declared MCP server.
|
|
544
|
+
*
|
|
545
|
+
* @param suiteId - the source-qualified suite id the status row carries.
|
|
546
|
+
* @param serverKey - the server key inside that suite's declaration.
|
|
547
|
+
* @param tool - the tool's raw name inside the server's namespace.
|
|
548
|
+
* @param enabled - whether the tool is allowed.
|
|
549
|
+
*/
|
|
550
|
+
async function setMcpServerTool(suiteId, serverKey, tool, enabled) {
|
|
551
|
+
return withBusyOperation(async () => {
|
|
552
|
+
await postAction("set-mcp-server-tool", {
|
|
553
|
+
suiteId,
|
|
554
|
+
serverKey,
|
|
555
|
+
tool,
|
|
556
|
+
enabled
|
|
557
|
+
});
|
|
558
|
+
});
|
|
559
|
+
}
|
|
519
560
|
/** Enable or disable one declared language server by its status-row id. */
|
|
520
561
|
async function setLspServerEnabled(id, enabled) {
|
|
521
562
|
return withBusyOperation(async () => {
|
|
@@ -575,6 +616,7 @@ const zh = {
|
|
|
575
616
|
serverConfigReadOnly: "此服务由宿主管理,请在原始配置中编辑。",
|
|
576
617
|
lspServerName: "服务名称",
|
|
577
618
|
lspAddTitle: "新建 LSP 服务",
|
|
619
|
+
lspEditTitle: "编辑 LSP 服务",
|
|
578
620
|
detailMarkdown: "编辑 Markdown",
|
|
579
621
|
detailMetadata: "元数据",
|
|
580
622
|
detailForm: "表单",
|
|
@@ -597,13 +639,22 @@ const zh = {
|
|
|
597
639
|
detailInvalidJson: "JSON 无效",
|
|
598
640
|
detailUseJson: "当前字段类型无法使用表单,请在 JSON 中修正。",
|
|
599
641
|
detailTransport: "传输方式",
|
|
642
|
+
transportHintStdio: "在本机启动一个子进程,用命令与参数配置",
|
|
643
|
+
transportHintHttp: "连接远端服务,用 URL 与请求头配置",
|
|
644
|
+
transportHintSse: "旧式远端推送协议,用 URL 与请求头配置",
|
|
600
645
|
detailCommand: "命令",
|
|
646
|
+
detailCommandPh: "npx -y @modelcontextprotocol/server-github",
|
|
601
647
|
detailArgs: "参数",
|
|
602
648
|
detailEnv: "环境变量",
|
|
603
649
|
detailUrl: "URL",
|
|
650
|
+
detailUrlPh: "https://mcp.example.com/mcp",
|
|
604
651
|
detailHeaders: "请求头",
|
|
652
|
+
detailHeaderKeyPh: "Authorization",
|
|
605
653
|
detailCwd: "工作目录",
|
|
606
|
-
|
|
654
|
+
detailRequired: "必填",
|
|
655
|
+
detailEmptyRowsMap: "没有内容:点这里添加一行,也可以直接粘贴多行 KEY=VALUE",
|
|
656
|
+
detailEmptyRowsList: "没有内容:点这里添加一行",
|
|
657
|
+
mcpOauthAuto: "服务返回 401 时自动协商 OAuth 授权,无需在此配置",
|
|
607
658
|
detailExtensions: "语言扩展名映射",
|
|
608
659
|
detailKey: "键",
|
|
609
660
|
detailValue: "值",
|
|
@@ -687,7 +738,6 @@ const zh = {
|
|
|
687
738
|
editorScopeUser: "用户目录",
|
|
688
739
|
editorScopeLocal: "本地目录",
|
|
689
740
|
sourceSuiteUnit: "个套件",
|
|
690
|
-
oauthEnable: "启用 OAuth 流程",
|
|
691
741
|
personaRouteCurrent: "当前路由:",
|
|
692
742
|
idFixed: "id 不可修改(源标识全局唯一)",
|
|
693
743
|
progressStarting: "正在提交…",
|
|
@@ -759,13 +809,31 @@ const zh = {
|
|
|
759
809
|
mcpOrphaned: "来源缺失",
|
|
760
810
|
mcpForeign: "外部挂载",
|
|
761
811
|
mcpServerKeyLabel: "服务键",
|
|
812
|
+
mcpEnabledLabel: "启用此服务",
|
|
762
813
|
mcpSearch: "搜索 MCP 名称、来源或地址…",
|
|
763
814
|
mcpAll: "全部",
|
|
764
815
|
mcpPlugin: "插件",
|
|
765
816
|
mcpDirect: "用户",
|
|
766
817
|
mcpTools: "工具",
|
|
818
|
+
mcpToolsMore: "还有 {count} 个工具",
|
|
819
|
+
mcpToolsSearch: "搜索工具",
|
|
820
|
+
mcpToolsNoMatch: "没有匹配的工具",
|
|
821
|
+
mcpToolParams: "参数",
|
|
822
|
+
mcpToolParamRequired: "必填",
|
|
823
|
+
mcpToolNoParameters: "这个工具不需要参数",
|
|
767
824
|
mcpTool: "工具",
|
|
768
825
|
mcpReasonLabel: "原因",
|
|
826
|
+
mcpGuideCredentials: "缺少凭据:在凭据区填入后再重试。",
|
|
827
|
+
mcpGuideAuth: "服务要求授权:确认 token 未过期,或重新授权。",
|
|
828
|
+
mcpGuideTransport: "当前后端不支持这种传输方式:切换到内置客户端。",
|
|
829
|
+
mcpGuideBackend: "当前后端无法执行这项配置:切换到内置客户端。",
|
|
830
|
+
mcpGuideDns: "域名解析失败:检查地址拼写、代理与网络。",
|
|
831
|
+
mcpGuideTls: "TLS 握手失败:确认证书有效,服务可能要求专线或来源 IP 白名单。",
|
|
832
|
+
mcpGuideRefused: "连接被拒绝:确认服务已启动、端口与路径正确。",
|
|
833
|
+
mcpGuideTimeout: "连接超时:确认服务可达;本地服务可以调高启动超时。",
|
|
834
|
+
mcpGuideCommandMissing: "找不到命令:确认它在 PATH 中,或改用绝对路径。",
|
|
835
|
+
mcpGuideProcessExit: "进程提前退出:检查命令、参数与运行环境。",
|
|
836
|
+
mcpGuideProtocol: "握手失败:确认地址指向 MCP 端点,而不是普通网页。",
|
|
769
837
|
mcpRetrySuccess: "重连成功,服务已恢复",
|
|
770
838
|
mcpReauthorize: "重新授权",
|
|
771
839
|
mcpClose: "关闭",
|
|
@@ -800,6 +868,7 @@ const zh = {
|
|
|
800
868
|
mcpBackendHostMissing: "宿主 dsh-mcp-client 在当前环境不可用,无法切换到兼容模式。",
|
|
801
869
|
mcpZeroTools: "该服务已连接,但未声明任何工具。",
|
|
802
870
|
mcpCredentialTitle: "凭据配置",
|
|
871
|
+
mcpCredentialConfigure: "配置",
|
|
803
872
|
mcpCredentialConfigured: "已配置",
|
|
804
873
|
mcpCredentialMissing: "未配置",
|
|
805
874
|
mcpCredentialReadOnly: "由启动环境提供(只读;修改后需重启 DSH)",
|
|
@@ -813,8 +882,39 @@ const zh = {
|
|
|
813
882
|
mcpNoTools: "当前没有已注册工具",
|
|
814
883
|
mcpDirectBoundary: "用户 MCP 仅显示当前工具表中可观测的服务;宿主未提供配置与连接状态 API。",
|
|
815
884
|
mcpAddTitle: "新建 MCP 服务",
|
|
885
|
+
mcpEditTitle: "编辑 MCP 服务",
|
|
886
|
+
mcpStarterTemplates: "从模板开始",
|
|
887
|
+
mcpStarterPaste: "粘贴 JSON",
|
|
888
|
+
mcpPasteApply: "填入表单",
|
|
889
|
+
mcpPastePlaceholder: "粘贴 mcpServers 条目或单个服务定义",
|
|
890
|
+
mcpPasteFound: "识别到 {count} 条服务",
|
|
891
|
+
mcpPasteImport: "导入这些服务",
|
|
892
|
+
mcpPasteOverwrite: "覆盖同名服务",
|
|
893
|
+
mcpPasteImported: "已导入:{names}",
|
|
894
|
+
mcpPasteSkipped: "跳过:{detail}",
|
|
895
|
+
mcpPasteUnnamed: "没有服务名,无法导入",
|
|
896
|
+
mcpTemplateFilesystem: "文件系统",
|
|
897
|
+
mcpTemplateMemory: "记忆",
|
|
898
|
+
mcpTemplateFetch: "网页抓取",
|
|
899
|
+
mcpTemplateContext7: "Context7 文档",
|
|
900
|
+
mcpTemplateGithub: "GitHub",
|
|
816
901
|
mcpServerName: "服务名称",
|
|
817
902
|
mcpRetry: "重试",
|
|
903
|
+
mcpAdvanced: "高级设置",
|
|
904
|
+
mcpAdvancedSummary: "连接选项与超时",
|
|
905
|
+
mcpToolCallTimeout: "工具调用超时",
|
|
906
|
+
mcpStartupTimeout: "启动超时",
|
|
907
|
+
mcpTimeoutInvalid: "请输入 1 到 2147483647 之间的整数毫秒",
|
|
908
|
+
mcpTimeoutInherit: "留空则继承",
|
|
909
|
+
mcpTimeoutFromSuite: "套件声明值",
|
|
910
|
+
mcpTimeoutFromDefault: "内置默认值",
|
|
911
|
+
mcpTimeoutUserSet: "已由你设置",
|
|
912
|
+
mcpTimeoutClear: "清除",
|
|
913
|
+
mcpTimeoutClearLabel: "清除「{name}」",
|
|
914
|
+
mcpHostStartupUnsupported: "宿主兼容后端不支持启动超时;切换到内置客户端后即可设置。",
|
|
915
|
+
mcpHostToolsUnsupported: "宿主兼容后端不支持工具勾选;切换到内置客户端后即可按工具启用或停用。",
|
|
916
|
+
mcpAllowTool: "允许工具 {name}",
|
|
917
|
+
mcpToolSuiteLimited: "由套件声明限定",
|
|
818
918
|
mcpFilterAllHint: "全部:插件套件声明的 MCP 服务与用户自行添加的 MCP",
|
|
819
919
|
mcpFilterPluginHint: "插件:来自插件市场套件的 mcp.json 声明",
|
|
820
920
|
mcpFilterDirectHint: "用户:非套件来源的 MCP,来自本面板添加或宿主工具表观测",
|
|
@@ -881,6 +981,7 @@ const zh = {
|
|
|
881
981
|
panelFilterAll: "全部",
|
|
882
982
|
panelFilterDisabled: "已禁用",
|
|
883
983
|
panelAdd: "新增",
|
|
984
|
+
panelEdit: "编辑",
|
|
884
985
|
panelAddSkillTitle: "新建技能",
|
|
885
986
|
panelAddCommandTitle: "新建命令",
|
|
886
987
|
panelAddPersonaTitle: "新建代理角色",
|
|
@@ -922,6 +1023,7 @@ const en = {
|
|
|
922
1023
|
serverConfigReadOnly: "This service is managed by the host. Edit its original configuration.",
|
|
923
1024
|
lspServerName: "Server name",
|
|
924
1025
|
lspAddTitle: "New LSP server",
|
|
1026
|
+
lspEditTitle: "Edit LSP server",
|
|
925
1027
|
detailMarkdown: "Edit Markdown",
|
|
926
1028
|
detailMetadata: "Metadata",
|
|
927
1029
|
detailForm: "Form",
|
|
@@ -944,13 +1046,22 @@ const en = {
|
|
|
944
1046
|
detailInvalidJson: "Invalid JSON",
|
|
945
1047
|
detailUseJson: "These field types cannot be edited as a form. Correct them in JSON.",
|
|
946
1048
|
detailTransport: "Transport",
|
|
1049
|
+
transportHintStdio: "Starts a local subprocess, configured by command and arguments",
|
|
1050
|
+
transportHintHttp: "Connects to a remote service, configured by URL and headers",
|
|
1051
|
+
transportHintSse: "Legacy remote push protocol, configured by URL and headers",
|
|
947
1052
|
detailCommand: "Command",
|
|
1053
|
+
detailCommandPh: "npx -y @modelcontextprotocol/server-github",
|
|
948
1054
|
detailArgs: "Arguments",
|
|
949
1055
|
detailEnv: "Environment variables",
|
|
950
1056
|
detailUrl: "URL",
|
|
1057
|
+
detailUrlPh: "https://mcp.example.com/mcp",
|
|
951
1058
|
detailHeaders: "Headers",
|
|
1059
|
+
detailHeaderKeyPh: "Authorization",
|
|
952
1060
|
detailCwd: "Working directory",
|
|
953
|
-
|
|
1061
|
+
detailRequired: "Required",
|
|
1062
|
+
detailEmptyRowsMap: "Nothing yet: click to add a line, or paste several KEY=VALUE lines",
|
|
1063
|
+
detailEmptyRowsList: "Nothing yet: click to add a line",
|
|
1064
|
+
mcpOauthAuto: "OAuth is negotiated automatically when the server answers 401",
|
|
954
1065
|
detailExtensions: "Extension mapping",
|
|
955
1066
|
detailKey: "Key",
|
|
956
1067
|
detailValue: "Value",
|
|
@@ -1034,7 +1145,6 @@ const en = {
|
|
|
1034
1145
|
editorScopeUser: "User directory",
|
|
1035
1146
|
editorScopeLocal: "Local directory",
|
|
1036
1147
|
sourceSuiteUnit: "suites",
|
|
1037
|
-
oauthEnable: "Enable the OAuth flow",
|
|
1038
1148
|
personaRouteCurrent: "Current route: ",
|
|
1039
1149
|
idFixed: "id is fixed (the source identifier is globally unique)",
|
|
1040
1150
|
progressStarting: "Submitting…",
|
|
@@ -1106,13 +1216,31 @@ const en = {
|
|
|
1106
1216
|
mcpOrphaned: "Source missing",
|
|
1107
1217
|
mcpForeign: "Mounted elsewhere",
|
|
1108
1218
|
mcpServerKeyLabel: "Server key",
|
|
1219
|
+
mcpEnabledLabel: "Enable this service",
|
|
1109
1220
|
mcpSearch: "Search MCP names, sources, or endpoints…",
|
|
1110
1221
|
mcpAll: "All",
|
|
1111
1222
|
mcpPlugin: "Plugin",
|
|
1112
1223
|
mcpDirect: "User",
|
|
1113
1224
|
mcpTools: "tools",
|
|
1225
|
+
mcpToolsMore: "{count} more tools",
|
|
1226
|
+
mcpToolsSearch: "Search tools",
|
|
1227
|
+
mcpToolsNoMatch: "No matching tools",
|
|
1228
|
+
mcpToolParams: "Parameters",
|
|
1229
|
+
mcpToolParamRequired: "required",
|
|
1230
|
+
mcpToolNoParameters: "This tool takes no parameters",
|
|
1114
1231
|
mcpTool: "tool",
|
|
1115
1232
|
mcpReasonLabel: "Reason",
|
|
1233
|
+
mcpGuideCredentials: "Missing credential: fill it in the credentials area, then retry.",
|
|
1234
|
+
mcpGuideAuth: "The service asks for authorization: check that the token is current, or authorize again.",
|
|
1235
|
+
mcpGuideTransport: "This backend cannot speak that transport: switch to the built-in client.",
|
|
1236
|
+
mcpGuideBackend: "This backend cannot enforce that setting: switch to the built-in client.",
|
|
1237
|
+
mcpGuideDns: "Name resolution failed: check the address, the proxy and the network.",
|
|
1238
|
+
mcpGuideTls: "TLS handshake failed: check the certificate; the service may require a VPN or an IP allow-list.",
|
|
1239
|
+
mcpGuideRefused: "Connection refused: check that the service is running, and that the port and path are right.",
|
|
1240
|
+
mcpGuideTimeout: "Connection timed out: check that the service is reachable; a local server can raise its startup timeout.",
|
|
1241
|
+
mcpGuideCommandMissing: "Command not found: check that it is on PATH, or use an absolute path.",
|
|
1242
|
+
mcpGuideProcessExit: "The process exited early: check the command, its arguments and its environment.",
|
|
1243
|
+
mcpGuideProtocol: "Handshake failed: check that the address points at an MCP endpoint rather than a web page.",
|
|
1116
1244
|
mcpRetrySuccess: "Reconnected — the service is live again",
|
|
1117
1245
|
mcpReauthorize: "Re-authorize",
|
|
1118
1246
|
mcpClose: "Close",
|
|
@@ -1147,6 +1275,7 @@ const en = {
|
|
|
1147
1275
|
mcpBackendHostMissing: "The host dsh-mcp-client is not available here; compat mode cannot be enabled.",
|
|
1148
1276
|
mcpZeroTools: "Connected, but this service advertises no tools.",
|
|
1149
1277
|
mcpCredentialTitle: "Credential configuration",
|
|
1278
|
+
mcpCredentialConfigure: "Configure",
|
|
1150
1279
|
mcpCredentialConfigured: "configured",
|
|
1151
1280
|
mcpCredentialMissing: "not configured",
|
|
1152
1281
|
mcpCredentialReadOnly: "provided by the launch environment (read-only; restart DSH after changes)",
|
|
@@ -1160,8 +1289,39 @@ const en = {
|
|
|
1160
1289
|
mcpNoTools: "No registered tools",
|
|
1161
1290
|
mcpDirectBoundary: "User MCP entries only show services observed in the current tool registry; the host exposes no config or connection-status API.",
|
|
1162
1291
|
mcpAddTitle: "New MCP service",
|
|
1292
|
+
mcpEditTitle: "Edit MCP service",
|
|
1293
|
+
mcpStarterTemplates: "Start from a template",
|
|
1294
|
+
mcpStarterPaste: "Paste JSON",
|
|
1295
|
+
mcpPasteApply: "Fill the form",
|
|
1296
|
+
mcpPastePlaceholder: "Paste an mcpServers entry or a single server definition",
|
|
1297
|
+
mcpPasteFound: "Found {count} services",
|
|
1298
|
+
mcpPasteImport: "Import these services",
|
|
1299
|
+
mcpPasteOverwrite: "Overwrite existing names",
|
|
1300
|
+
mcpPasteImported: "Imported: {names}",
|
|
1301
|
+
mcpPasteSkipped: "Skipped: {detail}",
|
|
1302
|
+
mcpPasteUnnamed: "no service name, so it cannot be imported",
|
|
1303
|
+
mcpTemplateFilesystem: "Filesystem",
|
|
1304
|
+
mcpTemplateMemory: "Memory",
|
|
1305
|
+
mcpTemplateFetch: "Web fetch",
|
|
1306
|
+
mcpTemplateContext7: "Context7 docs",
|
|
1307
|
+
mcpTemplateGithub: "GitHub",
|
|
1163
1308
|
mcpServerName: "Server name",
|
|
1164
1309
|
mcpRetry: "Retry",
|
|
1310
|
+
mcpAdvanced: "Advanced settings",
|
|
1311
|
+
mcpAdvancedSummary: "Connection options and timeouts",
|
|
1312
|
+
mcpToolCallTimeout: "Tool call timeout",
|
|
1313
|
+
mcpStartupTimeout: "Startup timeout",
|
|
1314
|
+
mcpTimeoutInvalid: "Enter a whole number of milliseconds between 1 and 2147483647",
|
|
1315
|
+
mcpTimeoutInherit: "Empty inherits",
|
|
1316
|
+
mcpTimeoutFromSuite: "the suite declaration",
|
|
1317
|
+
mcpTimeoutFromDefault: "the built-in default",
|
|
1318
|
+
mcpTimeoutUserSet: "Set by you",
|
|
1319
|
+
mcpTimeoutClear: "Clear",
|
|
1320
|
+
mcpTimeoutClearLabel: "Clear {name}",
|
|
1321
|
+
mcpHostStartupUnsupported: "The host compatibility backend cannot enforce a startup timeout; switch to the built-in client to set one.",
|
|
1322
|
+
mcpHostToolsUnsupported: "The host compatibility backend cannot enforce tool filters; switch to the built-in client to choose tools.",
|
|
1323
|
+
mcpAllowTool: "Allow tool {name}",
|
|
1324
|
+
mcpToolSuiteLimited: "Limited by the suite declaration",
|
|
1165
1325
|
mcpFilterAllHint: "All: MCP services declared by plugin suites plus MCP you added",
|
|
1166
1326
|
mcpFilterPluginHint: "Plugin: mcp.json declarations from market suites",
|
|
1167
1327
|
mcpFilterDirectHint: "User: MCP observed in the host tool registry outside any suite",
|
|
@@ -1228,6 +1388,7 @@ const en = {
|
|
|
1228
1388
|
panelFilterAll: "All",
|
|
1229
1389
|
panelFilterDisabled: "Disabled",
|
|
1230
1390
|
panelAdd: "Add",
|
|
1391
|
+
panelEdit: "Edit",
|
|
1231
1392
|
panelAddSkillTitle: "New skill",
|
|
1232
1393
|
panelAddCommandTitle: "New command",
|
|
1233
1394
|
panelAddPersonaTitle: "New agent role",
|
|
@@ -1578,7 +1739,10 @@ function SourceTabsRow(props) {
|
|
|
1578
1739
|
//#region src/client/ui/form.module.css
|
|
1579
1740
|
var form_module_default = {
|
|
1580
1741
|
"addIcon": "_5JDFMW_addIcon",
|
|
1742
|
+
"editorBody": "_5JDFMW_editorBody",
|
|
1743
|
+
"emptyRows": "_5JDFMW_emptyRows",
|
|
1581
1744
|
"field": "_5JDFMW_field",
|
|
1745
|
+
"fieldRow": "_5JDFMW_fieldRow",
|
|
1582
1746
|
"fieldset": "_5JDFMW_fieldset",
|
|
1583
1747
|
"footer": "_5JDFMW_footer",
|
|
1584
1748
|
"footerError": "_5JDFMW_footerError",
|
|
@@ -1593,6 +1757,7 @@ var form_module_default = {
|
|
|
1593
1757
|
"jsonArea": "_5JDFMW_jsonArea",
|
|
1594
1758
|
"previewBox": "_5JDFMW_previewBox",
|
|
1595
1759
|
"readonly": "_5JDFMW_readonly",
|
|
1760
|
+
"required": "_5JDFMW_required",
|
|
1596
1761
|
"row": "_5JDFMW_row",
|
|
1597
1762
|
"rowActions": "_5JDFMW_rowActions",
|
|
1598
1763
|
"rowHead": "_5JDFMW_rowHead",
|
|
@@ -1818,7 +1983,7 @@ function SuiteCard(props) {
|
|
|
1818
1983
|
"aria-label": t("refresh"),
|
|
1819
1984
|
disabled: busy,
|
|
1820
1985
|
onClick: stop(props.onRefresh)
|
|
1821
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
1986
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutlineMedium)),
|
|
1822
1987
|
(0, react.createElement)("button", {
|
|
1823
1988
|
key: "uninstall",
|
|
1824
1989
|
type: "button",
|
|
@@ -1827,7 +1992,7 @@ function SuiteCard(props) {
|
|
|
1827
1992
|
"aria-label": t("uninstall"),
|
|
1828
1993
|
disabled: busy,
|
|
1829
1994
|
onClick: stop(props.onUninstall)
|
|
1830
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
1995
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineMedium)),
|
|
1831
1996
|
(0, react.createElement)("span", {
|
|
1832
1997
|
key: "toggle",
|
|
1833
1998
|
className: resource_card_module_default.switchWrap,
|
|
@@ -7833,7 +7998,7 @@ function DetailRow(props) {
|
|
|
7833
7998
|
}, header[0], header[1], (0, react.createElement)("span", {
|
|
7834
7999
|
className: detail_rows_module_default.chevron,
|
|
7835
8000
|
"aria-hidden": true
|
|
7836
|
-
}, open ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
8001
|
+
}, open ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium) : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineMedium))), open ? (0, react.createElement)("div", { className: detail_rows_module_default.body }, props.children) : null);
|
|
7837
8002
|
}
|
|
7838
8003
|
//#endregion
|
|
7839
8004
|
//#region src/client/ui/last-change.ts
|
|
@@ -8192,7 +8357,7 @@ function SearchFilterToolbar(props) {
|
|
|
8192
8357
|
"data-panel-toolbar": true
|
|
8193
8358
|
}, (0, react.createElement)("label", { className: SearchFilterToolbar_module_default.search }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
8194
8359
|
className: SearchFilterToolbar_module_default.searchInput,
|
|
8195
|
-
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
8360
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineMedium),
|
|
8196
8361
|
value: props.search,
|
|
8197
8362
|
placeholder: props.searchPlaceholder,
|
|
8198
8363
|
"aria-label": props.searchLabel,
|
|
@@ -8322,7 +8487,7 @@ function codePointSize$1(code) {
|
|
|
8322
8487
|
return code < 65536 ? 1 : 2;
|
|
8323
8488
|
}
|
|
8324
8489
|
//#endregion
|
|
8325
|
-
//#region node_modules/.pnpm/@codemirror+state@6.7.
|
|
8490
|
+
//#region node_modules/.pnpm/@codemirror+state@6.7.5/node_modules/@codemirror/state/dist/index.js
|
|
8326
8491
|
/**
|
|
8327
8492
|
The data structure for documents. @nonabstract
|
|
8328
8493
|
*/
|
|
@@ -11660,7 +11825,10 @@ function compare(a, startA, b, startB, length, comparator) {
|
|
|
11660
11825
|
if (!(a.point && b.point && cmpVal(a.point, b.point) && sameValues(a.activeForPoint(a.to), b.activeForPoint(b.to)))) comparator.comparePoint(pos, clipEnd, a.point, b.point);
|
|
11661
11826
|
boundChange = false;
|
|
11662
11827
|
} else {
|
|
11663
|
-
if (boundChange)
|
|
11828
|
+
if (boundChange) {
|
|
11829
|
+
comparator.boundChange(pos);
|
|
11830
|
+
boundChange = false;
|
|
11831
|
+
}
|
|
11664
11832
|
if (clipEnd > pos && !sameValues(a.active, b.active)) comparator.compareRange(pos, clipEnd, a.active, b.active);
|
|
11665
11833
|
if (bounds && clipEnd < endB && (dEnd || a.openEnd(end) != b.openEnd(end))) boundChange = true;
|
|
11666
11834
|
}
|
|
@@ -11916,7 +12084,7 @@ function keyName(event) {
|
|
|
11916
12084
|
return name;
|
|
11917
12085
|
}
|
|
11918
12086
|
//#endregion
|
|
11919
|
-
//#region node_modules/.pnpm/@codemirror+view@6.43.
|
|
12087
|
+
//#region node_modules/.pnpm/@codemirror+view@6.43.12/node_modules/@codemirror/view/dist/index.js
|
|
11920
12088
|
let nav = typeof navigator != "undefined" ? navigator : {
|
|
11921
12089
|
userAgent: "",
|
|
11922
12090
|
vendor: "",
|
|
@@ -13813,11 +13981,11 @@ var TileBuilder = class {
|
|
|
13813
13981
|
if (last.dom != mark.dom) last.setDOM(freeNode(mark.dom));
|
|
13814
13982
|
head = last;
|
|
13815
13983
|
} else {
|
|
13984
|
+
let { dom } = mark;
|
|
13816
13985
|
if (this.cache.reused.get(mark)) {
|
|
13817
|
-
|
|
13818
|
-
if (tile) tile.setDOM(freeNode(mark.dom));
|
|
13986
|
+
if (Tile.get(mark.dom)) dom = freeNode(mark.dom);
|
|
13819
13987
|
}
|
|
13820
|
-
let nw = MarkTile.of(mark.mark,
|
|
13988
|
+
let nw = MarkTile.of(mark.mark, dom);
|
|
13821
13989
|
head.append(nw);
|
|
13822
13990
|
head = nw;
|
|
13823
13991
|
}
|
|
@@ -14230,12 +14398,13 @@ var TileUpdate = class {
|
|
|
14230
14398
|
if (tile instanceof MarkTile) marks.push(tile);
|
|
14231
14399
|
else if (tile === null || tile === void 0 ? void 0 : tile.isLine()) line = tile;
|
|
14232
14400
|
else if (tile instanceof BlockWrapperTile);
|
|
14233
|
-
else if (parent.nodeName == "DIV" && !line
|
|
14401
|
+
else if (parent.nodeName == "DIV" && !line) line = new LineTile(parent, lineBaseAttrs);
|
|
14234
14402
|
else if (!line) marks.push(MarkTile.of(new MarkDecoration({
|
|
14235
14403
|
tagName: parent.nodeName.toLowerCase(),
|
|
14236
14404
|
attributes: getAttrs$1(parent)
|
|
14237
14405
|
}), parent));
|
|
14238
14406
|
}
|
|
14407
|
+
if (!line) return null;
|
|
14239
14408
|
return {
|
|
14240
14409
|
line,
|
|
14241
14410
|
marks
|
|
@@ -14927,18 +15096,20 @@ function blockAt(view, pos, side) {
|
|
|
14927
15096
|
return line;
|
|
14928
15097
|
}
|
|
14929
15098
|
function moveToLineBoundary(view, start, forward, includeWrap) {
|
|
14930
|
-
let
|
|
14931
|
-
let coords = !includeWrap ||
|
|
15099
|
+
let block = blockAt(view, start.head, start.assoc || -1);
|
|
15100
|
+
let coords = !includeWrap || block.type != BlockType.Text || !(view.lineWrapping || block.widgetLineBreaks) ? null : view.coordsAtPos(start.assoc < 0 && start.head > block.from ? start.head - 1 : start.head);
|
|
14932
15101
|
if (coords) {
|
|
14933
15102
|
let editorRect = view.dom.getBoundingClientRect();
|
|
14934
|
-
let direction = view.textDirectionAt(
|
|
15103
|
+
let direction = view.textDirectionAt(block.from);
|
|
14935
15104
|
let pos = view.posAtCoords({
|
|
14936
15105
|
x: forward == (direction == Direction.LTR) ? editorRect.right - 1 : editorRect.left + 1,
|
|
14937
15106
|
y: (coords.top + coords.bottom) / 2
|
|
14938
15107
|
});
|
|
14939
15108
|
if (pos != null) return EditorSelection.cursor(pos, forward ? -1 : 1);
|
|
14940
15109
|
}
|
|
14941
|
-
|
|
15110
|
+
let line = view.state.doc.lineAt(start.head);
|
|
15111
|
+
if (forward ? line.to == block.to : line.from == block.from) return view.visualLineSide(line, forward);
|
|
15112
|
+
return EditorSelection.cursor(forward ? block.to : block.from, forward ? -1 : 1);
|
|
14942
15113
|
}
|
|
14943
15114
|
function moveByChar(view, start, forward, by) {
|
|
14944
15115
|
let line = view.state.doc.lineAt(start.head), spans = view.bidiSpans(line);
|
|
@@ -16233,7 +16404,17 @@ observers.blur = (view) => {
|
|
|
16233
16404
|
observers.compositionstart = observers.compositionupdate = (view) => {
|
|
16234
16405
|
if (view.observer.editContext) return;
|
|
16235
16406
|
if (view.inputState.compositionFirstChange == null) view.inputState.compositionFirstChange = true;
|
|
16236
|
-
if (view.inputState.composing < 0)
|
|
16407
|
+
if (view.inputState.composing < 0) {
|
|
16408
|
+
let { main } = view.state.selection;
|
|
16409
|
+
if (!main.empty && view.lineBlockAt(main.from).from != view.lineBlockAt(main.to).from) view.dispatch({
|
|
16410
|
+
changes: view.state.selection.ranges.filter((r) => !r.empty).map((r) => ({
|
|
16411
|
+
from: r.from,
|
|
16412
|
+
to: r.to
|
|
16413
|
+
})),
|
|
16414
|
+
userEvent: "input"
|
|
16415
|
+
});
|
|
16416
|
+
view.inputState.composing = 0;
|
|
16417
|
+
}
|
|
16237
16418
|
};
|
|
16238
16419
|
observers.compositionend = (view) => {
|
|
16239
16420
|
if (view.observer.editContext) return;
|
|
@@ -18403,6 +18584,7 @@ var EditorView = class EditorView {
|
|
|
18403
18584
|
@internal
|
|
18404
18585
|
*/
|
|
18405
18586
|
this.measureRequests = [];
|
|
18587
|
+
this.clearAnnouncement = -1;
|
|
18406
18588
|
this.contentDOM = document.createElement("div");
|
|
18407
18589
|
this.scrollDOM = document.createElement("div");
|
|
18408
18590
|
this.scrollDOM.tabIndex = -1;
|
|
@@ -18711,8 +18893,14 @@ var EditorView = class EditorView {
|
|
|
18711
18893
|
showAnnouncements(trs) {
|
|
18712
18894
|
let first = true;
|
|
18713
18895
|
for (let tr of trs) for (let effect of tr.effects) if (effect.is(EditorView.announce)) {
|
|
18714
|
-
if (first)
|
|
18715
|
-
|
|
18896
|
+
if (first) {
|
|
18897
|
+
this.announceDOM.textContent = "";
|
|
18898
|
+
this.win.clearTimeout(this.clearAnnouncement);
|
|
18899
|
+
this.clearAnnouncement = this.win.setTimeout(() => {
|
|
18900
|
+
this.announceDOM.textContent = "\xA0";
|
|
18901
|
+
}, 200);
|
|
18902
|
+
first = false;
|
|
18903
|
+
}
|
|
18716
18904
|
let div = this.announceDOM.appendChild(document.createElement("div"));
|
|
18717
18905
|
div.textContent = effect.value;
|
|
18718
18906
|
}
|
|
@@ -19056,6 +19244,7 @@ var EditorView = class EditorView {
|
|
|
19056
19244
|
this.docView.destroy();
|
|
19057
19245
|
this.dom.remove();
|
|
19058
19246
|
this.observer.destroy();
|
|
19247
|
+
this.win.clearTimeout(this.clearAnnouncement);
|
|
19059
19248
|
if (this.measureScheduled > -1) this.win.cancelAnimationFrame(this.measureScheduled);
|
|
19060
19249
|
this.destroyed = true;
|
|
19061
19250
|
}
|
|
@@ -24734,7 +24923,7 @@ function createTokenType(extra, tagStr) {
|
|
|
24734
24923
|
}
|
|
24735
24924
|
Direction.RTL, Direction.LTR;
|
|
24736
24925
|
//#endregion
|
|
24737
|
-
//#region node_modules/.pnpm/@codemirror+commands@6.11.
|
|
24926
|
+
//#region node_modules/.pnpm/@codemirror+commands@6.11.1/node_modules/@codemirror/commands/dist/index.js
|
|
24738
24927
|
/**
|
|
24739
24928
|
Comment or uncomment the current selection. Will use line comments
|
|
24740
24929
|
if available, otherwise falling back to block comments.
|
|
@@ -25388,11 +25577,11 @@ const cursorLineBoundaryRight = (view) => moveSel(view, (range) => moveByLineBou
|
|
|
25388
25577
|
/**
|
|
25389
25578
|
Move the selection to the start of the line.
|
|
25390
25579
|
*/
|
|
25391
|
-
const cursorLineStart = (view) => moveSel(view, (range) =>
|
|
25580
|
+
const cursorLineStart = (view) => moveSel(view, (range) => view.moveToLineBoundary(range, false, false));
|
|
25392
25581
|
/**
|
|
25393
25582
|
Move the selection to the end of the line.
|
|
25394
25583
|
*/
|
|
25395
|
-
const cursorLineEnd = (view) => moveSel(view, (range) =>
|
|
25584
|
+
const cursorLineEnd = (view) => moveSel(view, (range) => view.moveToLineBoundary(range, true, false));
|
|
25396
25585
|
function toMatchingBracket(state, dispatch, extend) {
|
|
25397
25586
|
let found = false, selection = updateSel(state.selection, (range) => {
|
|
25398
25587
|
let matching = matchBrackets(state, range.head, -1) || matchBrackets(state, range.head, 1) || range.head > 0 && matchBrackets(state, range.head - 1, 1) || range.head < state.doc.length && matchBrackets(state, range.head + 1, -1);
|
|
@@ -34571,14 +34760,14 @@ function PanelActions(props) {
|
|
|
34571
34760
|
title: props.addLabel,
|
|
34572
34761
|
"aria-label": props.addLabel,
|
|
34573
34762
|
onClick: props.onAdd
|
|
34574
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
34763
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium)), props.onRefresh === void 0 ? null : (0, react.createElement)("button", {
|
|
34575
34764
|
type: "button",
|
|
34576
34765
|
className: resource_card_module_default.iconBtn,
|
|
34577
34766
|
disabled: props.busy,
|
|
34578
34767
|
title: props.refreshLabel,
|
|
34579
34768
|
"aria-label": props.refreshLabel,
|
|
34580
34769
|
onClick: props.onRefresh
|
|
34581
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
34770
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutlineMedium)));
|
|
34582
34771
|
}
|
|
34583
34772
|
/** Shared heading geometry for all resource tabs. */
|
|
34584
34773
|
function PanelHeader(props) {
|
|
@@ -34599,7 +34788,7 @@ function BusyIndicator(props) {
|
|
|
34599
34788
|
}, (0, react.createElement)("span", {
|
|
34600
34789
|
className: `${panel_module_default.spinner} ${panel_module_default.spinning}`,
|
|
34601
34790
|
"aria-hidden": true
|
|
34602
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
34791
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconLoadingOutlineMedium)), props.label === void 0 ? null : (0, react.createElement)("span", { className: panel_module_default.busyLabel }, props.label));
|
|
34603
34792
|
}
|
|
34604
34793
|
/** Hold the shared mask through local refresh/validation after the HTTP mutation finishes. */
|
|
34605
34794
|
function BusyLease() {
|
|
@@ -35131,8 +35320,61 @@ function MarketSection({ t, mode = "settings" }) {
|
|
|
35131
35320
|
}))
|
|
35132
35321
|
});
|
|
35133
35322
|
}
|
|
35134
|
-
|
|
35135
|
-
|
|
35323
|
+
/**
|
|
35324
|
+
* Read one timeout field: empty inherits (`null`), a positive whole number of
|
|
35325
|
+
* milliseconds within the timer range is the value, and anything else is
|
|
35326
|
+
* `undefined`, which leaves the editor unsaveable.
|
|
35327
|
+
*/
|
|
35328
|
+
function timeoutMsFromText(raw) {
|
|
35329
|
+
const text = raw.trim();
|
|
35330
|
+
if (text === "") return null;
|
|
35331
|
+
if (!/^\d+$/.test(text)) return void 0;
|
|
35332
|
+
const value = Number(text);
|
|
35333
|
+
return Number.isSafeInteger(value) && value > 0 && value <= 2147483647 ? value : void 0;
|
|
35334
|
+
}
|
|
35335
|
+
/** The same drafts, read off a document's policy half. */
|
|
35336
|
+
function policyDraftOfDocument(policy) {
|
|
35337
|
+
const text = (value) => typeof value === "number" || typeof value === "string" ? String(value) : "";
|
|
35338
|
+
return {
|
|
35339
|
+
toolCallTimeoutMs: text(policy["toolCallTimeoutMs"]),
|
|
35340
|
+
startupTimeoutMs: text(policy["startupTimeoutMs"])
|
|
35341
|
+
};
|
|
35342
|
+
}
|
|
35343
|
+
/**
|
|
35344
|
+
* Write the timeout drafts back into a document's policy half. An emptied field
|
|
35345
|
+
* asks for inheritance, which the document spells `null` — the value the save
|
|
35346
|
+
* route reads as "clear what was stored". An unparsable draft is left alone:
|
|
35347
|
+
* the editor's validity signal blocks that save instead of rewriting the value.
|
|
35348
|
+
*/
|
|
35349
|
+
function policyDocumentOfDraft(policy, draft) {
|
|
35350
|
+
const next = { ...policy };
|
|
35351
|
+
for (const [field, raw] of [["toolCallTimeoutMs", draft.toolCallTimeoutMs], ["startupTimeoutMs", draft.startupTimeoutMs]]) {
|
|
35352
|
+
const value = timeoutMsFromText(raw);
|
|
35353
|
+
if (value === void 0) {
|
|
35354
|
+
next[field] = raw;
|
|
35355
|
+
continue;
|
|
35356
|
+
}
|
|
35357
|
+
if (value === null) {
|
|
35358
|
+
if (field in policy) next[field] = null;
|
|
35359
|
+
else delete next[field];
|
|
35360
|
+
continue;
|
|
35361
|
+
}
|
|
35362
|
+
next[field] = value;
|
|
35363
|
+
}
|
|
35364
|
+
return next;
|
|
35365
|
+
}
|
|
35366
|
+
/**
|
|
35367
|
+
* The policy half of one save: only the entries the user changed, because a
|
|
35368
|
+
* value edited on one backend must not ride along to another, where the same
|
|
35369
|
+
* value can be refused. A key dropped from the document asks for inheritance,
|
|
35370
|
+
* which the route reads as `null`.
|
|
35371
|
+
*/
|
|
35372
|
+
function policyRequestOfDocuments(initial, current) {
|
|
35373
|
+
const request = {};
|
|
35374
|
+
for (const [field, value] of Object.entries(current)) if (JSON.stringify(value) !== JSON.stringify(initial[field])) request[field] = value;
|
|
35375
|
+
for (const field of Object.keys(initial)) if (!(field in current)) request[field] = null;
|
|
35376
|
+
return request;
|
|
35377
|
+
}
|
|
35136
35378
|
function parseServerConfig(text) {
|
|
35137
35379
|
const value = JSON.parse(text);
|
|
35138
35380
|
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("Configuration must be a JSON object");
|
|
@@ -35176,6 +35418,193 @@ function serverFormCompatible(config, kind) {
|
|
|
35176
35418
|
if (auth?.scope !== void 0 && typeof auth.scope !== "string") return false;
|
|
35177
35419
|
return true;
|
|
35178
35420
|
}
|
|
35421
|
+
/**
|
|
35422
|
+
* Common MCP services, in the three shapes a new service takes: a local
|
|
35423
|
+
* process with no credential, a local process behind one, and a remote
|
|
35424
|
+
* endpoint behind one. The GitHub entry points at the vendor's remote server
|
|
35425
|
+
* because the old npm package is no longer maintained.
|
|
35426
|
+
*/
|
|
35427
|
+
const MCP_TEMPLATES = [
|
|
35428
|
+
{
|
|
35429
|
+
id: "filesystem",
|
|
35430
|
+
labelKey: "mcpTemplateFilesystem",
|
|
35431
|
+
config: {
|
|
35432
|
+
type: "stdio",
|
|
35433
|
+
command: "npx",
|
|
35434
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem"]
|
|
35435
|
+
}
|
|
35436
|
+
},
|
|
35437
|
+
{
|
|
35438
|
+
id: "memory",
|
|
35439
|
+
labelKey: "mcpTemplateMemory",
|
|
35440
|
+
config: {
|
|
35441
|
+
type: "stdio",
|
|
35442
|
+
command: "npx",
|
|
35443
|
+
args: ["-y", "@modelcontextprotocol/server-memory"]
|
|
35444
|
+
}
|
|
35445
|
+
},
|
|
35446
|
+
{
|
|
35447
|
+
id: "fetch",
|
|
35448
|
+
labelKey: "mcpTemplateFetch",
|
|
35449
|
+
config: {
|
|
35450
|
+
type: "stdio",
|
|
35451
|
+
command: "uvx",
|
|
35452
|
+
args: ["mcp-server-fetch"]
|
|
35453
|
+
}
|
|
35454
|
+
},
|
|
35455
|
+
{
|
|
35456
|
+
id: "context7",
|
|
35457
|
+
labelKey: "mcpTemplateContext7",
|
|
35458
|
+
config: {
|
|
35459
|
+
type: "streamable-http",
|
|
35460
|
+
url: "https://mcp.context7.com/mcp",
|
|
35461
|
+
headers: { Authorization: "Bearer ${CONTEXT7_API_KEY}" }
|
|
35462
|
+
}
|
|
35463
|
+
},
|
|
35464
|
+
{
|
|
35465
|
+
id: "github",
|
|
35466
|
+
labelKey: "mcpTemplateGithub",
|
|
35467
|
+
config: {
|
|
35468
|
+
type: "streamable-http",
|
|
35469
|
+
url: "https://api.githubcopilot.com/mcp/",
|
|
35470
|
+
headers: { Authorization: "Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}" }
|
|
35471
|
+
}
|
|
35472
|
+
}
|
|
35473
|
+
];
|
|
35474
|
+
/**
|
|
35475
|
+
* Read one pasted configuration: a whole `mcpServers` map (its first entry
|
|
35476
|
+
* supplies the name), or a bare server definition. Claude-shaped files spell
|
|
35477
|
+
* the remote transport `http` and a stdio server `local`; a definition that
|
|
35478
|
+
* carries no transport is read from its command or url. The result is a form
|
|
35479
|
+
* document, not a validated server — the save path still validates it.
|
|
35480
|
+
*/
|
|
35481
|
+
/** Normalize one pasted definition: Claude-shaped aliases and an inferred transport. */
|
|
35482
|
+
function normalizePastedServer(body) {
|
|
35483
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) throw new Error("Configuration must be a JSON object");
|
|
35484
|
+
const config = { ...body };
|
|
35485
|
+
if (config["type"] === "local") config["type"] = "stdio";
|
|
35486
|
+
if (config["type"] === "http") config["type"] = "streamable-http";
|
|
35487
|
+
if (config["type"] === void 0) {
|
|
35488
|
+
if (typeof config["command"] === "string") config["type"] = "stdio";
|
|
35489
|
+
else if (typeof config["url"] === "string" || typeof config["httpUrl"] === "string") config["type"] = "streamable-http";
|
|
35490
|
+
}
|
|
35491
|
+
if (config["type"] !== "stdio" && config["url"] === void 0 && typeof config["httpUrl"] === "string") {
|
|
35492
|
+
config["url"] = config["httpUrl"];
|
|
35493
|
+
delete config["httpUrl"];
|
|
35494
|
+
}
|
|
35495
|
+
return config;
|
|
35496
|
+
}
|
|
35497
|
+
/**
|
|
35498
|
+
* Read every server out of one pasted document: an `mcpServers` map (each key
|
|
35499
|
+
* becomes the service name) or a bare definition (which carries no name).
|
|
35500
|
+
*/
|
|
35501
|
+
function parsePastedServers(text) {
|
|
35502
|
+
const parsed = JSON.parse(text);
|
|
35503
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Configuration must be a JSON object");
|
|
35504
|
+
const record = parsed;
|
|
35505
|
+
const servers = record["mcpServers"];
|
|
35506
|
+
if (typeof servers === "object" && servers !== null && !Array.isArray(servers)) {
|
|
35507
|
+
const entries = Object.entries(servers);
|
|
35508
|
+
if (entries.length === 0) throw new Error("mcpServers is empty");
|
|
35509
|
+
return entries.map(([name, body]) => ({
|
|
35510
|
+
name,
|
|
35511
|
+
config: normalizePastedServer(body)
|
|
35512
|
+
}));
|
|
35513
|
+
}
|
|
35514
|
+
return [{ config: normalizePastedServer(record) }];
|
|
35515
|
+
}
|
|
35516
|
+
/** The first server of a pasted document, for filling the form rather than importing. */
|
|
35517
|
+
function parsePastedServer(text) {
|
|
35518
|
+
const [first] = parsePastedServers(text);
|
|
35519
|
+
if (first === void 0) throw new Error("mcpServers is empty");
|
|
35520
|
+
return first;
|
|
35521
|
+
}
|
|
35522
|
+
/**
|
|
35523
|
+
* Read one pasted block into rows.
|
|
35524
|
+
*
|
|
35525
|
+
* The two separators that appear in MCP documentation are `=` and `:`, taking
|
|
35526
|
+
* whichever comes first on a line, and values arrive quoted about as often as
|
|
35527
|
+
* not — so a pasted `"KEY": "value"` lands as a full row instead of one long
|
|
35528
|
+
* value. A list (arguments) keeps whole lines.
|
|
35529
|
+
*/
|
|
35530
|
+
function rowsFromPastedText(text, map) {
|
|
35531
|
+
const lines = text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line !== "");
|
|
35532
|
+
if (!map) return lines.map((line) => ["", line]);
|
|
35533
|
+
const rows = [];
|
|
35534
|
+
for (const line of lines) {
|
|
35535
|
+
const equals = line.indexOf("=");
|
|
35536
|
+
const colon = line.indexOf(":");
|
|
35537
|
+
const separator = equals === -1 ? colon : colon === -1 ? equals : Math.min(equals, colon);
|
|
35538
|
+
if (separator <= 0) continue;
|
|
35539
|
+
const key = stripQuotes(line.slice(0, separator).trim());
|
|
35540
|
+
if (key === "") continue;
|
|
35541
|
+
rows.push([key, stripQuotes(line.slice(separator + 1).trim())]);
|
|
35542
|
+
}
|
|
35543
|
+
return rows;
|
|
35544
|
+
}
|
|
35545
|
+
/** Drop one pair of matching quotes, the shape a value is copied in. */
|
|
35546
|
+
function stripQuotes(value) {
|
|
35547
|
+
if (value.length >= 2 && (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'"))) return value.slice(1, -1);
|
|
35548
|
+
return value;
|
|
35549
|
+
}
|
|
35550
|
+
/** The namespace seat this client's own per-server policy rides. */
|
|
35551
|
+
const HARNESS_NAMESPACE = "com.deepseek.harness";
|
|
35552
|
+
function asRecord(value) {
|
|
35553
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
35554
|
+
}
|
|
35555
|
+
/**
|
|
35556
|
+
* Read one service document: the definition under `mcpServers`, and this
|
|
35557
|
+
* client's policy under the `com.deepseek.harness` namespace — the two seats
|
|
35558
|
+
* the Agent Plugins specification gives a portable `mcp.json` and its client
|
|
35559
|
+
* extension. A document that omits either half reads as an empty one.
|
|
35560
|
+
*/
|
|
35561
|
+
function parseServerDocument(text, key) {
|
|
35562
|
+
const parsed = JSON.parse(text);
|
|
35563
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Configuration must be a JSON object");
|
|
35564
|
+
const record = parsed;
|
|
35565
|
+
return {
|
|
35566
|
+
config: asRecord(asRecord(record["mcpServers"])?.[key]) ?? {},
|
|
35567
|
+
policy: asRecord(asRecord(asRecord(record["com.deepseek.harness"])?.["mcpServers"])?.[key]) ?? {}
|
|
35568
|
+
};
|
|
35569
|
+
}
|
|
35570
|
+
/** Write the document back in the shape the specification seats it in. */
|
|
35571
|
+
function composeServerDocument(key, config, policy) {
|
|
35572
|
+
const document = { mcpServers: { [key]: config } };
|
|
35573
|
+
if (Object.keys(policy).length > 0) document[HARNESS_NAMESPACE] = { mcpServers: { [key]: policy } };
|
|
35574
|
+
return JSON.stringify(document, null, 2);
|
|
35575
|
+
}
|
|
35576
|
+
/**
|
|
35577
|
+
* The policy half of a document, built from what the user stored. Suite
|
|
35578
|
+
* declarations stay out: the editor shows them as the value in force, and a
|
|
35579
|
+
* document that repeated them would invite an edit the client cannot honour.
|
|
35580
|
+
*/
|
|
35581
|
+
function serverPolicyDocument(policy) {
|
|
35582
|
+
if (policy === void 0) return {};
|
|
35583
|
+
const document = {};
|
|
35584
|
+
if (policy.toolCallTimeout.user !== null) document["toolCallTimeoutMs"] = policy.toolCallTimeout.user;
|
|
35585
|
+
if (policy.startupTimeout.user !== null) document["startupTimeoutMs"] = policy.startupTimeout.user;
|
|
35586
|
+
if (policy.deniedTools.user !== null) document["disabledTools"] = policy.deniedTools.user;
|
|
35587
|
+
if (policy.auth.user !== null) document["auth"] = { enabled: policy.auth.user };
|
|
35588
|
+
return document;
|
|
35589
|
+
}
|
|
35590
|
+
/**
|
|
35591
|
+
* Fold the API's field list into the map an editor renders. The first path
|
|
35592
|
+
* segment names the editor field; a nested key rides along with it, so a
|
|
35593
|
+
* rejected header lands on the headers field.
|
|
35594
|
+
*/
|
|
35595
|
+
function fieldErrorsOf(reason) {
|
|
35596
|
+
const fields = reason.fields;
|
|
35597
|
+
if (!Array.isArray(fields)) return void 0;
|
|
35598
|
+
const map = {};
|
|
35599
|
+
for (const entry of fields) {
|
|
35600
|
+
if (typeof entry !== "object" || entry === null) continue;
|
|
35601
|
+
const { field, message } = entry;
|
|
35602
|
+
if (typeof field !== "string" || field === "" || typeof message !== "string") continue;
|
|
35603
|
+
const key = field.split(".")[0] ?? field;
|
|
35604
|
+
map[key] = map[key] === void 0 ? message : `${map[key]}; ${message}`;
|
|
35605
|
+
}
|
|
35606
|
+
return Object.keys(map).length === 0 ? void 0 : map;
|
|
35607
|
+
}
|
|
35179
35608
|
//#endregion
|
|
35180
35609
|
//#region src/client/ui/ServerConfigEditor.tsx
|
|
35181
35610
|
/**
|
|
@@ -35189,11 +35618,17 @@ function serverFormCompatible(config, kind) {
|
|
|
35189
35618
|
/** One JSON document backs both modes. Invalid JSON is retained, never silently converted or reset. */
|
|
35190
35619
|
function ServerConfigEditor(props) {
|
|
35191
35620
|
const [mode, setMode] = (0, react.useState)("form");
|
|
35621
|
+
const [advancedOpen, setAdvancedOpen] = (0, react.useState)(false);
|
|
35192
35622
|
const [issues, setIssues] = (0, react.useState)({});
|
|
35193
35623
|
let parsed;
|
|
35624
|
+
let policy = {};
|
|
35194
35625
|
let parseError;
|
|
35195
35626
|
try {
|
|
35196
|
-
|
|
35627
|
+
if (props.kind === "mcp") {
|
|
35628
|
+
const document = parseServerDocument(props.text, props.serverKey ?? "");
|
|
35629
|
+
parsed = document.config;
|
|
35630
|
+
policy = document.policy;
|
|
35631
|
+
} else parsed = parseServerConfig(props.text);
|
|
35197
35632
|
} catch (error) {
|
|
35198
35633
|
parseError = error instanceof Error ? error.message : String(error);
|
|
35199
35634
|
}
|
|
@@ -35201,11 +35636,13 @@ function ServerConfigEditor(props) {
|
|
|
35201
35636
|
const compatible = config !== void 0 && serverFormCompatible(config, props.kind);
|
|
35202
35637
|
const hasIssue = Object.values(issues).some(Boolean);
|
|
35203
35638
|
const requiredValid = config !== void 0 && (props.kind === "lsp" ? typeof config.command === "string" && config.command.trim() !== "" && config.extensionToLanguage !== null && typeof config.extensionToLanguage === "object" && Object.keys(config.extensionToLanguage).length > 0 : config.type === "stdio" ? typeof config.command === "string" && config.command.trim() !== "" : ["sse", "streamable-http"].includes(String(config.type)) && typeof config.url === "string" && config.url.trim() !== "");
|
|
35204
|
-
const
|
|
35639
|
+
const timeouts = props.policy !== void 0 && props.policyDraft !== void 0 && props.onPolicyDraftChange !== void 0;
|
|
35640
|
+
const policyValid = !timeouts || timeoutMsFromText(props.policyDraft.toolCallTimeoutMs) !== void 0 && timeoutMsFromText(props.policyDraft.startupTimeoutMs) !== void 0;
|
|
35641
|
+
const valid = compatible && !hasIssue && requiredValid && policyValid;
|
|
35205
35642
|
(0, react.useEffect)(() => {
|
|
35206
35643
|
props.onValidityChange?.(valid);
|
|
35207
35644
|
}, [valid, props.onValidityChange]);
|
|
35208
|
-
const update = (next) => props.onChange(JSON.stringify(next, null, 2));
|
|
35645
|
+
const update = (next) => props.onChange(props.kind === "mcp" ? composeServerDocument(props.serverKey ?? "", next, policy) : JSON.stringify(next, null, 2));
|
|
35209
35646
|
const field = (key, value) => {
|
|
35210
35647
|
const next = { ...config };
|
|
35211
35648
|
if (value === void 0) delete next[key];
|
|
@@ -35220,15 +35657,31 @@ function ServerConfigEditor(props) {
|
|
|
35220
35657
|
};
|
|
35221
35658
|
});
|
|
35222
35659
|
};
|
|
35223
|
-
|
|
35224
|
-
|
|
35225
|
-
key
|
|
35226
|
-
|
|
35227
|
-
|
|
35228
|
-
|
|
35229
|
-
|
|
35230
|
-
|
|
35231
|
-
|
|
35660
|
+
/** The example a server's own documentation shows for this field. */
|
|
35661
|
+
const placeholderFor = (key) => {
|
|
35662
|
+
if (key === "command") return props.t("detailCommandPh");
|
|
35663
|
+
if (key === "url") return props.t("detailUrlPh");
|
|
35664
|
+
};
|
|
35665
|
+
/** The API's reason for one field, when it rejected a save. */
|
|
35666
|
+
const fieldError = (key) => props.fieldErrors?.[key] === void 0 ? null : (0, react.createElement)("span", { className: form_module_default.footerError }, props.fieldErrors[key]);
|
|
35667
|
+
const textField = (key, label, required = false, full = false) => {
|
|
35668
|
+
const placeholder = placeholderFor(key);
|
|
35669
|
+
return (0, react.createElement)("label", {
|
|
35670
|
+
className: full ? `${form_module_default.field} ${form_module_default.full}` : form_module_default.field,
|
|
35671
|
+
key
|
|
35672
|
+
}, (0, react.createElement)("span", null, label, required ? (0, react.createElement)("span", {
|
|
35673
|
+
key: "required",
|
|
35674
|
+
className: form_module_default.required,
|
|
35675
|
+
title: props.t("detailRequired"),
|
|
35676
|
+
"aria-hidden": true
|
|
35677
|
+
}, "*") : null), (0, react.createElement)("input", {
|
|
35678
|
+
value: typeof config?.[key] === "string" ? config[key] : "",
|
|
35679
|
+
required,
|
|
35680
|
+
...placeholder === void 0 ? {} : { placeholder },
|
|
35681
|
+
"aria-label": label,
|
|
35682
|
+
onChange: (event) => field(key, event.target.value === "" && !required ? void 0 : event.target.value)
|
|
35683
|
+
}), fieldError(key));
|
|
35684
|
+
};
|
|
35232
35685
|
const mapField = (key, label, addLabel, narrowKey = false) => (0, react.createElement)(StringRows, {
|
|
35233
35686
|
key,
|
|
35234
35687
|
label,
|
|
@@ -35238,34 +35691,96 @@ function ServerConfigEditor(props) {
|
|
|
35238
35691
|
narrowKey,
|
|
35239
35692
|
value: config?.[key],
|
|
35240
35693
|
onChange: (value) => field(key, value),
|
|
35241
|
-
onIssue: (bad) => issue(key, bad)
|
|
35694
|
+
onIssue: (bad) => issue(key, bad),
|
|
35695
|
+
...props.fieldErrors?.[key] === void 0 ? {} : { error: props.fieldErrors[key] }
|
|
35242
35696
|
});
|
|
35243
35697
|
const type = typeof config?.type === "string" ? config.type : "stdio";
|
|
35244
|
-
const
|
|
35245
|
-
|
|
35246
|
-
|
|
35247
|
-
"aria-label": props.t("detailTransport")
|
|
35248
|
-
disabled: hasIssue,
|
|
35249
|
-
onChange: (event) => {
|
|
35250
|
-
if (config === void 0) return;
|
|
35251
|
-
update(changeTransport(config, event.target.value));
|
|
35252
|
-
}
|
|
35698
|
+
const transportField = props.kind === "mcp" ? (0, react.createElement)("div", { className: form_module_default.field }, (0, react.createElement)("span", null, props.t("detailTransport")), (0, react.createElement)("div", {
|
|
35699
|
+
className: form_module_default.seg,
|
|
35700
|
+
role: "group",
|
|
35701
|
+
"aria-label": props.t("detailTransport")
|
|
35253
35702
|
}, [
|
|
35254
35703
|
"stdio",
|
|
35255
35704
|
"streamable-http",
|
|
35256
35705
|
"sse"
|
|
35257
|
-
].map((value) => (0, react.createElement)("
|
|
35706
|
+
].map((value) => (0, react.createElement)("button", {
|
|
35707
|
+
type: "button",
|
|
35258
35708
|
key: value,
|
|
35259
|
-
value
|
|
35709
|
+
"aria-pressed": type === value,
|
|
35710
|
+
disabled: hasIssue,
|
|
35711
|
+
onClick: () => {
|
|
35712
|
+
if (config === void 0) return;
|
|
35713
|
+
update(changeTransport(config, value));
|
|
35714
|
+
}
|
|
35260
35715
|
}, value)))) : null;
|
|
35261
35716
|
const identityRow = props.nameField === void 0 ? null : props.kind === "mcp" ? (0, react.createElement)("div", { className: form_module_default.formGrid }, (0, react.createElement)("label", { className: form_module_default.field }, (0, react.createElement)("span", null, props.nameField.label), props.nameField.control), transportField) : (0, react.createElement)("label", { className: form_module_default.field }, (0, react.createElement)("span", null, props.nameField.label), props.nameField.control);
|
|
35262
|
-
|
|
35717
|
+
/**
|
|
35718
|
+
* The advanced disclosure: one seat for the optional inputs. A stdio server
|
|
35719
|
+
* offers its working directory there, a remote one its OAuth block, and both
|
|
35720
|
+
* offer the client timeouts when the calling dialog supplies the policy.
|
|
35721
|
+
*/
|
|
35722
|
+
const advancedFields = [];
|
|
35723
|
+
if (props.createMode === true && config !== void 0) {
|
|
35724
|
+
if (props.kind === "lsp" || type === "stdio") advancedFields.push((0, react.createElement)(StringRows, {
|
|
35725
|
+
key: "args",
|
|
35726
|
+
label: props.t("detailArgs"),
|
|
35727
|
+
addLabel: props.t("detailAddArgs"),
|
|
35728
|
+
t: props.t,
|
|
35729
|
+
map: false,
|
|
35730
|
+
value: config.args,
|
|
35731
|
+
onChange: (value) => field("args", value),
|
|
35732
|
+
onIssue: (bad) => issue("args", bad)
|
|
35733
|
+
}), mapField("env", props.t("detailEnv"), props.t("detailAddEnv"), true));
|
|
35734
|
+
else advancedFields.push(mapField("headers", props.t("detailHeaders"), props.t("detailAddHeaders"), true));
|
|
35735
|
+
}
|
|
35736
|
+
if (config !== void 0) advancedFields.push(type === "stdio" ? textField("cwd", props.t("detailCwd"), false, true) : (0, react.createElement)("span", {
|
|
35737
|
+
key: "oauth",
|
|
35738
|
+
className: `${form_module_default.hint} ${form_module_default.full}`
|
|
35739
|
+
}, props.t("mcpOauthAuto")));
|
|
35740
|
+
if (timeouts) advancedFields.push((0, react.createElement)(TimeoutField, {
|
|
35741
|
+
key: "toolCallTimeout",
|
|
35742
|
+
label: props.t("mcpToolCallTimeout"),
|
|
35743
|
+
resolution: props.policy.toolCallTimeout,
|
|
35744
|
+
value: props.policyDraft.toolCallTimeoutMs,
|
|
35745
|
+
disabled: props.disabled === true,
|
|
35746
|
+
t: props.t,
|
|
35747
|
+
onChange: (value) => props.onPolicyDraftChange({
|
|
35748
|
+
...props.policyDraft,
|
|
35749
|
+
toolCallTimeoutMs: value
|
|
35750
|
+
})
|
|
35751
|
+
}), (0, react.createElement)(TimeoutField, {
|
|
35752
|
+
key: "startupTimeout",
|
|
35753
|
+
label: props.t("mcpStartupTimeout"),
|
|
35754
|
+
resolution: props.policy.startupTimeout,
|
|
35755
|
+
value: props.policyDraft.startupTimeoutMs,
|
|
35756
|
+
disabled: props.disabled === true,
|
|
35757
|
+
...props.backend === "host" ? { blocked: props.t("mcpHostStartupUnsupported") } : {},
|
|
35758
|
+
...props.backend === "host" && props.policy.startupTimeout.user !== null ? {
|
|
35759
|
+
clearLabel: props.t("mcpTimeoutClearLabel", { name: props.t("mcpStartupTimeout") }),
|
|
35760
|
+
onClear: () => props.onPolicyDraftChange({
|
|
35761
|
+
...props.policyDraft,
|
|
35762
|
+
startupTimeoutMs: ""
|
|
35763
|
+
})
|
|
35764
|
+
} : {},
|
|
35765
|
+
t: props.t,
|
|
35766
|
+
onChange: (value) => props.onPolicyDraftChange({
|
|
35767
|
+
...props.policyDraft,
|
|
35768
|
+
startupTimeoutMs: value
|
|
35769
|
+
})
|
|
35770
|
+
}));
|
|
35771
|
+
const advancedSection = props.kind !== "mcp" || advancedFields.length === 0 ? null : (0, react.createElement)(DetailRows, null, (0, react.createElement)(DetailRow, {
|
|
35772
|
+
name: props.t("mcpAdvanced"),
|
|
35773
|
+
summary: props.t("mcpAdvancedSummary"),
|
|
35774
|
+
open: advancedOpen,
|
|
35775
|
+
onToggle: () => setAdvancedOpen((value) => !value)
|
|
35776
|
+
}, (0, react.createElement)("div", { className: form_module_default.form }, advancedFields)));
|
|
35777
|
+
return (0, react.createElement)("div", { className: `${form_module_default.form} ${form_module_default.editorBody}` }, (0, react.createElement)("div", { className: form_module_default.seg }, ["form", "json"].map((value) => (0, react.createElement)("button", {
|
|
35263
35778
|
type: "button",
|
|
35264
35779
|
key: value,
|
|
35265
35780
|
"aria-pressed": mode === value,
|
|
35266
35781
|
disabled: props.disabled || value === "json" && hasIssue,
|
|
35267
35782
|
onClick: () => setMode(value)
|
|
35268
|
-
}, props.t(value === "form" ? "detailForm" : "detailJson")))), identityRow, parseError ? (0, react.createElement)("div", {
|
|
35783
|
+
}, props.t(value === "form" ? "detailForm" : "detailJson")))), identityRow, mode === "form" && props.kind === "mcp" && config !== void 0 ? (0, react.createElement)("span", { className: `${form_module_default.hint} ${form_module_default.full}` }, props.t(type === "stdio" ? "transportHintStdio" : type === "sse" ? "transportHintSse" : "transportHintHttp")) : null, parseError ? (0, react.createElement)("div", {
|
|
35269
35784
|
role: "alert",
|
|
35270
35785
|
className: detail_module_default.error
|
|
35271
35786
|
}, props.t("detailInvalidJson"), " ", parseError) : null, mode === "json" ? (0, react.createElement)("label", { className: form_module_default.field }, (0, react.createElement)("span", null, props.t("detailJsonConfig")), (0, react.createElement)("textarea", {
|
|
@@ -35286,43 +35801,47 @@ function ServerConfigEditor(props) {
|
|
|
35286
35801
|
margin: 0,
|
|
35287
35802
|
padding: 0
|
|
35288
35803
|
}
|
|
35289
|
-
}, props.nameField === void 0 ? transportField : null, props.kind === "lsp" || type === "stdio" ? [
|
|
35290
|
-
|
|
35291
|
-
|
|
35292
|
-
|
|
35293
|
-
|
|
35294
|
-
|
|
35295
|
-
|
|
35296
|
-
|
|
35297
|
-
|
|
35298
|
-
|
|
35299
|
-
onIssue: (bad) => issue("args", bad)
|
|
35300
|
-
}),
|
|
35301
|
-
mapField("env", props.t("detailEnv"), props.t("detailAddEnv"), true)
|
|
35302
|
-
] : [textField("url", props.t("detailUrl"), true, true), mapField("headers", props.t("detailHeaders"), props.t("detailAddHeaders"), true)], props.kind === "mcp" && type === "stdio" ? textField("cwd", props.t("detailCwd"), false, true) : null, props.kind === "mcp" && type !== "stdio" ? (0, react.createElement)("fieldset", { className: `${form_module_default.fieldset} ${form_module_default.full}` }, (0, react.createElement)("legend", null, "OAuth"), (0, react.createElement)("label", { className: form_module_default.inlineCheck }, (0, react.createElement)("input", {
|
|
35303
|
-
type: "checkbox",
|
|
35304
|
-
checked: auth.enabled !== false,
|
|
35305
|
-
onChange: (event) => field("auth", {
|
|
35306
|
-
...auth,
|
|
35307
|
-
enabled: event.target.checked
|
|
35308
|
-
})
|
|
35309
|
-
}), " ", props.t("oauthEnable")), (0, react.createElement)("label", { className: `${form_module_default.field} ${form_module_default.full}` }, (0, react.createElement)("span", null, props.t("detailScope")), (0, react.createElement)("input", {
|
|
35310
|
-
value: typeof auth.scope === "string" ? auth.scope : "",
|
|
35311
|
-
"aria-label": props.t("detailScope"),
|
|
35312
|
-
onChange: (event) => {
|
|
35313
|
-
const next = {
|
|
35314
|
-
...auth,
|
|
35315
|
-
scope: event.target.value
|
|
35316
|
-
};
|
|
35317
|
-
field("auth", next);
|
|
35318
|
-
}
|
|
35319
|
-
}))) : null, props.kind === "lsp" ? [mapField("extensionToLanguage", props.t("detailExtensions"), props.t("detailAddExtensions"), true), ...["initializationOptions", "configuration"].map((key) => (0, react.createElement)(JsonField, {
|
|
35804
|
+
}, props.nameField === void 0 ? transportField : null, props.kind === "lsp" || type === "stdio" ? [textField("command", props.t("detailCommand"), true, true), ...props.createMode === true ? [] : [(0, react.createElement)(StringRows, {
|
|
35805
|
+
key: "args",
|
|
35806
|
+
label: props.t("detailArgs"),
|
|
35807
|
+
addLabel: props.t("detailAddArgs"),
|
|
35808
|
+
t: props.t,
|
|
35809
|
+
map: false,
|
|
35810
|
+
value: config.args,
|
|
35811
|
+
onChange: (value) => field("args", value),
|
|
35812
|
+
onIssue: (bad) => issue("args", bad)
|
|
35813
|
+
}), mapField("env", props.t("detailEnv"), props.t("detailAddEnv"), true)]] : [textField("url", props.t("detailUrl"), true, true), ...props.createMode === true ? [] : [mapField("headers", props.t("detailHeaders"), props.t("detailAddHeaders"), true)]], props.kind === "lsp" ? [mapField("extensionToLanguage", props.t("detailExtensions"), props.t("detailAddExtensions"), true), ...["initializationOptions", "configuration"].map((key) => (0, react.createElement)(JsonField, {
|
|
35320
35814
|
key,
|
|
35321
35815
|
label: key,
|
|
35322
35816
|
value: config[key],
|
|
35323
35817
|
onChange: (value) => field(key, value),
|
|
35324
35818
|
onIssue: (bad) => issue(key, bad)
|
|
35325
|
-
}))] : null));
|
|
35819
|
+
}))] : null), advancedSection);
|
|
35820
|
+
}
|
|
35821
|
+
/**
|
|
35822
|
+
* One advanced timeout field: raw milliseconds text, with the effective value
|
|
35823
|
+
* as its placeholder, a line naming where an inherited value comes from, and an
|
|
35824
|
+
* optional control that empties the field back to inheritance.
|
|
35825
|
+
*/
|
|
35826
|
+
function TimeoutField(props) {
|
|
35827
|
+
const invalid = timeoutMsFromText(props.value) === void 0;
|
|
35828
|
+
const hint = invalid ? props.t("mcpTimeoutInvalid") : props.value.trim() === "" ? `${props.t("mcpTimeoutInherit")} · ${props.resolution.suite === null ? props.t("mcpTimeoutFromDefault") : props.t("mcpTimeoutFromSuite")}` : props.t("mcpTimeoutUserSet");
|
|
35829
|
+
return (0, react.createElement)("div", { className: `${form_module_default.field} ${form_module_default.full}` }, (0, react.createElement)("span", null, props.label), (0, react.createElement)("div", { className: form_module_default.fieldRow }, (0, react.createElement)("input", {
|
|
35830
|
+
type: "text",
|
|
35831
|
+
inputMode: "numeric",
|
|
35832
|
+
value: props.value,
|
|
35833
|
+
placeholder: String(props.resolution.effective),
|
|
35834
|
+
"aria-label": props.label,
|
|
35835
|
+
disabled: props.disabled || props.blocked !== void 0,
|
|
35836
|
+
onChange: (event) => props.onChange(event.target.value)
|
|
35837
|
+
}), props.onClear === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
35838
|
+
variant: "ghost",
|
|
35839
|
+
size: "sm",
|
|
35840
|
+
type: "button",
|
|
35841
|
+
disabled: props.disabled,
|
|
35842
|
+
...props.clearLabel === void 0 ? {} : { "aria-label": props.clearLabel },
|
|
35843
|
+
onClick: props.onClear
|
|
35844
|
+
}, props.t("mcpTimeoutClear"))), (0, react.createElement)("span", { className: invalid ? form_module_default.footerError : form_module_default.hint }, hint), props.blocked === void 0 ? null : (0, react.createElement)("span", { className: form_module_default.hint }, props.blocked));
|
|
35326
35845
|
}
|
|
35327
35846
|
/** The row editor behind a string list (arguments) and a string map (env, headers, extensions). */
|
|
35328
35847
|
function StringRows(props) {
|
|
@@ -35342,7 +35861,11 @@ function StringRows(props) {
|
|
|
35342
35861
|
title: props.addLabel,
|
|
35343
35862
|
"aria-label": `${props.t("panelAdd")} ${props.label}`,
|
|
35344
35863
|
onClick: () => change([...rows, ["", ""]])
|
|
35345
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
35864
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium))), rows.length === 0 ? (0, react.createElement)("button", {
|
|
35865
|
+
type: "button",
|
|
35866
|
+
className: form_module_default.emptyRows,
|
|
35867
|
+
onClick: () => change([["", ""]])
|
|
35868
|
+
}, props.map ? props.t("detailEmptyRowsMap") : props.t("detailEmptyRowsList")) : null, (0, react.createElement)("div", { className: form_module_default.rows }, rows.map(([key, value], index) => (0, react.createElement)("div", {
|
|
35346
35869
|
className: form_module_default.row,
|
|
35347
35870
|
key: index
|
|
35348
35871
|
}, props.map ? (0, react.createElement)("input", {
|
|
@@ -35353,17 +35876,28 @@ function StringRows(props) {
|
|
|
35353
35876
|
}) : null, (0, react.createElement)("input", {
|
|
35354
35877
|
value,
|
|
35355
35878
|
"aria-label": `${props.label} ${props.t("detailValue")} ${index + 1}`,
|
|
35356
|
-
onChange: (event) => change(rows.map((row, i) => i === index ? [row[0], event.target.value] : row))
|
|
35879
|
+
onChange: (event) => change(rows.map((row, i) => i === index ? [row[0], event.target.value] : row)),
|
|
35880
|
+
onPaste: (event) => {
|
|
35881
|
+
const pasted = event.clipboardData?.getData("text/plain") ?? "";
|
|
35882
|
+
if (!pasted.includes("\n")) return;
|
|
35883
|
+
const parsed = rowsFromPastedText(pasted, props.map);
|
|
35884
|
+
if (parsed.length === 0) return;
|
|
35885
|
+
event.preventDefault();
|
|
35886
|
+
change([...rows.filter(([key, value]) => key !== "" || value !== ""), ...parsed]);
|
|
35887
|
+
}
|
|
35357
35888
|
}), (0, react.createElement)("button", {
|
|
35358
35889
|
type: "button",
|
|
35359
35890
|
className: form_module_default.iconBtn,
|
|
35360
35891
|
title: props.t("panelDelete"),
|
|
35361
35892
|
"aria-label": `${props.t("panelDelete")} ${props.label} ${index + 1}`,
|
|
35362
35893
|
onClick: () => change(rows.filter((_, i) => i !== index))
|
|
35363
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
35894
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineMedium)))), invalid ? (0, react.createElement)("span", {
|
|
35364
35895
|
role: "alert",
|
|
35365
35896
|
className: form_module_default.footerError
|
|
35366
|
-
}, props.t("detailUniqueKeys")) : null)
|
|
35897
|
+
}, props.t("detailUniqueKeys")) : null, props.error === void 0 ? null : (0, react.createElement)("span", {
|
|
35898
|
+
role: "alert",
|
|
35899
|
+
className: form_module_default.footerError
|
|
35900
|
+
}, props.error)));
|
|
35367
35901
|
}
|
|
35368
35902
|
/** One free-form JSON field (an LSP's initialization options or configuration). */
|
|
35369
35903
|
function JsonField(props) {
|
|
@@ -35393,46 +35927,107 @@ function JsonField(props) {
|
|
|
35393
35927
|
}
|
|
35394
35928
|
//#endregion
|
|
35395
35929
|
//#region src/client/ui/ServerConfigDetail.tsx
|
|
35396
|
-
/**
|
|
35930
|
+
/**
|
|
35931
|
+
* One service's editor.
|
|
35932
|
+
*
|
|
35933
|
+
* The editor shows the document the specification seats a service in — the
|
|
35934
|
+
* portable definition under `mcpServers` plus this client's policy under the
|
|
35935
|
+
* `com.deepseek.harness` namespace — so every setting the client supports is
|
|
35936
|
+
* reachable as JSON. The form is a view over the same text and only writes the
|
|
35937
|
+
* half it owns, which is why a key the form has no control for survives an edit.
|
|
35938
|
+
*/
|
|
35397
35939
|
function ServerConfigDetail({ kind, id, t, onSaved, onDirtyChange }) {
|
|
35398
35940
|
const [text, setText] = (0, react.useState)();
|
|
35941
|
+
const [initialText, setInitialText] = (0, react.useState)();
|
|
35942
|
+
const [serverKey, setServerKey] = (0, react.useState)("");
|
|
35399
35943
|
const [editable, setEditable] = (0, react.useState)(false);
|
|
35400
35944
|
const [valid, setValid] = (0, react.useState)(false);
|
|
35401
35945
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
35402
35946
|
const [error, setError] = (0, react.useState)();
|
|
35403
35947
|
const [loading, setLoading] = (0, react.useState)(true);
|
|
35404
|
-
const [
|
|
35948
|
+
const [policy, setPolicy] = (0, react.useState)();
|
|
35949
|
+
const [backend, setBackend] = (0, react.useState)();
|
|
35950
|
+
const [fieldErrors, setFieldErrors] = (0, react.useState)();
|
|
35951
|
+
const requestToken = (0, react.useRef)(0);
|
|
35952
|
+
const dirty = text !== void 0 && text !== initialText;
|
|
35405
35953
|
(0, react.useEffect)(() => {
|
|
35406
35954
|
onDirtyChange?.(dirty);
|
|
35407
35955
|
}, [dirty, onDirtyChange]);
|
|
35408
|
-
|
|
35409
|
-
|
|
35410
|
-
|
|
35411
|
-
|
|
35956
|
+
/** The document's policy half, as the string drafts the timeout fields edit. */
|
|
35957
|
+
const policyDraft = () => {
|
|
35958
|
+
if (kind !== "mcp" || text === void 0) return {
|
|
35959
|
+
toolCallTimeoutMs: "",
|
|
35960
|
+
startupTimeoutMs: ""
|
|
35961
|
+
};
|
|
35962
|
+
try {
|
|
35963
|
+
return policyDraftOfDocument(parseServerDocument(text, serverKey).policy);
|
|
35964
|
+
} catch {
|
|
35965
|
+
return {
|
|
35966
|
+
toolCallTimeoutMs: "",
|
|
35967
|
+
startupTimeoutMs: ""
|
|
35968
|
+
};
|
|
35969
|
+
}
|
|
35970
|
+
};
|
|
35971
|
+
/** Write the timeout drafts back into the document's policy half. */
|
|
35972
|
+
const updatePolicy = (draft) => {
|
|
35973
|
+
if (text === void 0) return;
|
|
35974
|
+
try {
|
|
35975
|
+
const document = parseServerDocument(text, serverKey);
|
|
35976
|
+
setText(composeServerDocument(serverKey, document.config, policyDocumentOfDraft(document.policy, draft)));
|
|
35977
|
+
} catch {}
|
|
35978
|
+
};
|
|
35979
|
+
/**
|
|
35980
|
+
* Read the service again and rebuild every derived value from the response.
|
|
35981
|
+
* `silent` keeps the editor mounted for the read-back that follows a save, so
|
|
35982
|
+
* the user stays in the section they were editing.
|
|
35983
|
+
*/
|
|
35984
|
+
const load = async (silent = false) => {
|
|
35985
|
+
const token = ++requestToken.current;
|
|
35412
35986
|
setError(void 0);
|
|
35413
|
-
|
|
35414
|
-
|
|
35415
|
-
|
|
35987
|
+
setFieldErrors(void 0);
|
|
35988
|
+
if (!silent) {
|
|
35989
|
+
setLoading(true);
|
|
35990
|
+
setText(void 0);
|
|
35991
|
+
setInitialText(void 0);
|
|
35992
|
+
setPolicy(void 0);
|
|
35993
|
+
}
|
|
35994
|
+
try {
|
|
35995
|
+
const result = await fetchServerConfig(kind, id);
|
|
35996
|
+
if (requestToken.current !== token) return;
|
|
35997
|
+
const next = kind === "mcp" ? composeServerDocument(result.key, result.config, serverPolicyDocument(result.policy)) : JSON.stringify(result.config, null, 2);
|
|
35416
35998
|
setEditable(result.editable);
|
|
35417
|
-
|
|
35418
|
-
|
|
35419
|
-
|
|
35420
|
-
|
|
35421
|
-
|
|
35422
|
-
})
|
|
35999
|
+
setServerKey(result.key);
|
|
36000
|
+
setText(next);
|
|
36001
|
+
setInitialText(next);
|
|
36002
|
+
setPolicy(result.policy);
|
|
36003
|
+
setBackend(result.backend);
|
|
36004
|
+
} catch (reason) {
|
|
36005
|
+
if (requestToken.current === token) setError(String(reason));
|
|
36006
|
+
} finally {
|
|
36007
|
+
if (!silent && requestToken.current === token) setLoading(false);
|
|
36008
|
+
}
|
|
36009
|
+
};
|
|
36010
|
+
(0, react.useEffect)(() => {
|
|
36011
|
+
load();
|
|
35423
36012
|
return () => {
|
|
35424
|
-
|
|
36013
|
+
requestToken.current += 1;
|
|
35425
36014
|
};
|
|
35426
36015
|
}, [kind, id]);
|
|
35427
36016
|
const save = async () => {
|
|
35428
36017
|
setBusy(true);
|
|
35429
36018
|
setError(void 0);
|
|
36019
|
+
setFieldErrors(void 0);
|
|
35430
36020
|
try {
|
|
35431
|
-
|
|
35432
|
-
|
|
36021
|
+
if (kind === "mcp") {
|
|
36022
|
+
const document = parseServerDocument(text ?? "", serverKey);
|
|
36023
|
+
const initial = initialText === void 0 ? {} : parseServerDocument(initialText, serverKey).policy;
|
|
36024
|
+
await saveServerConfig(kind, id, document.config, policyRequestOfDocuments(initial, document.policy));
|
|
36025
|
+
} else await saveServerConfig(kind, id, parseServerConfig(text ?? ""));
|
|
36026
|
+
await load(true);
|
|
35433
36027
|
onSaved?.();
|
|
35434
36028
|
} catch (reason) {
|
|
35435
36029
|
setError(clientErrorMessage(t, reason));
|
|
36030
|
+
setFieldErrors(fieldErrorsOf(reason));
|
|
35436
36031
|
} finally {
|
|
35437
36032
|
setBusy(false);
|
|
35438
36033
|
}
|
|
@@ -35444,12 +36039,15 @@ function ServerConfigDetail({ kind, id, t, onSaved, onDirtyChange }) {
|
|
|
35444
36039
|
kind,
|
|
35445
36040
|
text,
|
|
35446
36041
|
t,
|
|
36042
|
+
serverKey,
|
|
35447
36043
|
disabled: busy || !editable,
|
|
35448
36044
|
onValidityChange: setValid,
|
|
35449
|
-
|
|
35450
|
-
|
|
35451
|
-
|
|
35452
|
-
}
|
|
36045
|
+
...policy === void 0 ? {} : { policy },
|
|
36046
|
+
policyDraft: policyDraft(),
|
|
36047
|
+
onPolicyDraftChange: updatePolicy,
|
|
36048
|
+
...backend === void 0 ? {} : { backend },
|
|
36049
|
+
...fieldErrors === void 0 ? {} : { fieldErrors },
|
|
36050
|
+
onChange: setText
|
|
35453
36051
|
}), loading || error && text === void 0 ? null : editable ? (0, react.createElement)(DetailFooterAction, { children: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
35454
36052
|
variant: "primary",
|
|
35455
36053
|
disabled: busy || !valid || !dirty,
|
|
@@ -35522,11 +36120,14 @@ var mcp_credential_module_default = {
|
|
|
35522
36120
|
"factOk": "G2mDja_factOk",
|
|
35523
36121
|
"facts": "G2mDja_facts",
|
|
35524
36122
|
"form": "G2mDja_form",
|
|
36123
|
+
"grow": "G2mDja_grow",
|
|
35525
36124
|
"head": "G2mDja_head",
|
|
35526
36125
|
"input": "G2mDja_input",
|
|
35527
36126
|
"note": "G2mDja_note",
|
|
35528
36127
|
"ref": "G2mDja_ref",
|
|
35529
|
-
"row": "G2mDja_row"
|
|
36128
|
+
"row": "G2mDja_row",
|
|
36129
|
+
"rowHead": "G2mDja_rowHead",
|
|
36130
|
+
"where": "G2mDja_where"
|
|
35530
36131
|
};
|
|
35531
36132
|
//#endregion
|
|
35532
36133
|
//#region src/client/McpCredentialEditor.tsx
|
|
@@ -35538,11 +36139,15 @@ var mcp_credential_module_default = {
|
|
|
35538
36139
|
* `credentials.set`, and never re-enters component state. Read-only
|
|
35539
36140
|
* launch-environment credentials render guidance instead of a form that could
|
|
35540
36141
|
* only fake success.
|
|
36142
|
+
*
|
|
36143
|
+
* One reference is one compact row: its name, its state, where the server uses
|
|
36144
|
+
* it, and a control that reveals the write field on demand.
|
|
35541
36145
|
*/
|
|
35542
36146
|
function McpCredentialEditor(props) {
|
|
35543
|
-
const { t, api, refs } = props;
|
|
36147
|
+
const { t, api, refs, usage } = props;
|
|
35544
36148
|
const [views, setViews] = (0, react.useState)({});
|
|
35545
36149
|
const [drafts, setDrafts] = (0, react.useState)({});
|
|
36150
|
+
const [open, setOpen] = (0, react.useState)({});
|
|
35546
36151
|
const [busy, setBusy] = (0, react.useState)(void 0);
|
|
35547
36152
|
const [error, setError] = (0, react.useState)(void 0);
|
|
35548
36153
|
const refKey = refs.join("|");
|
|
@@ -35606,15 +36211,29 @@ function McpCredentialEditor(props) {
|
|
|
35606
36211
|
return (0, react.createElement)("section", { className: mcp_credential_module_default.form }, busy === void 0 ? null : (0, react.createElement)(BusyIndicator, { overlay: true }), (0, react.createElement)("h4", { className: mcp_credential_module_default.head }, t("mcpCredentialTitle")), error === void 0 ? null : (0, react.createElement)("div", { className: mcp_credential_module_default.error }, error), refs.map((ref) => {
|
|
35607
36212
|
const view = views[ref];
|
|
35608
36213
|
const refBusy = busy === ref;
|
|
36214
|
+
const where = usage?.[ref] ?? [];
|
|
36215
|
+
const expanded = open[ref] === true;
|
|
36216
|
+
const configured = view?.configured === true;
|
|
35609
36217
|
return (0, react.createElement)("div", {
|
|
35610
36218
|
key: ref,
|
|
35611
36219
|
className: mcp_credential_module_default.row
|
|
35612
|
-
}, (0, react.createElement)("code", { className: mcp_credential_module_default.ref }, ref), view === void 0 ? (0, react.createElement)("
|
|
36220
|
+
}, (0, react.createElement)("div", { className: mcp_credential_module_default.rowHead }, (0, react.createElement)("code", { className: mcp_credential_module_default.ref }, ref), view === void 0 ? (0, react.createElement)("span", { className: mcp_credential_module_default.note }, api === void 0 ? t("mcpCredentialUnavailable") : t("loading")) : (0, react.createElement)("span", { className: configured ? mcp_credential_module_default.factOk : mcp_credential_module_default.factMiss }, configured ? t("mcpCredentialConfigured") : t("mcpCredentialMissing")), view?.source === void 0 ? null : (0, react.createElement)("span", { className: mcp_credential_module_default.note }, view.source), (0, react.createElement)("span", { className: mcp_credential_module_default.grow }), view === void 0 ? null : view.writable ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
36221
|
+
variant: "ghost",
|
|
36222
|
+
size: "sm",
|
|
36223
|
+
disabled: refBusy,
|
|
36224
|
+
"aria-expanded": expanded,
|
|
36225
|
+
"aria-label": `${t("mcpCredentialConfigure")} ${ref}`,
|
|
36226
|
+
onClick: () => setOpen((current) => ({
|
|
36227
|
+
...current,
|
|
36228
|
+
[ref]: !expanded
|
|
36229
|
+
}))
|
|
36230
|
+
}, t("mcpCredentialConfigure")) : (0, react.createElement)("span", { className: mcp_credential_module_default.note }, t("mcpCredentialReadOnly"))), where.length === 0 ? null : (0, react.createElement)("span", { className: mcp_credential_module_default.where }, where.join(" · ")), expanded && view?.writable === true ? (0, react.createElement)("div", { className: mcp_credential_module_default.editor }, (0, react.createElement)("input", {
|
|
35613
36231
|
className: mcp_credential_module_default.input,
|
|
35614
36232
|
type: "password",
|
|
35615
36233
|
autoComplete: "new-password",
|
|
35616
36234
|
value: drafts[ref] ?? "",
|
|
35617
36235
|
placeholder: t("mcpCredentialPlaceholder"),
|
|
36236
|
+
"aria-label": ref,
|
|
35618
36237
|
disabled: refBusy,
|
|
35619
36238
|
onChange: (event) => setDrafts((current) => ({
|
|
35620
36239
|
...current,
|
|
@@ -35625,12 +36244,12 @@ function McpCredentialEditor(props) {
|
|
|
35625
36244
|
size: "sm",
|
|
35626
36245
|
disabled: refBusy || (drafts[ref]?.trim() ?? "") === "",
|
|
35627
36246
|
onClick: () => void save(ref)
|
|
35628
|
-
}, t("mcpCredentialSave")),
|
|
36247
|
+
}, t("mcpCredentialSave")), configured ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
35629
36248
|
variant: "ghost",
|
|
35630
36249
|
size: "sm",
|
|
35631
36250
|
disabled: refBusy,
|
|
35632
36251
|
onClick: () => void unset(ref)
|
|
35633
|
-
}, t("mcpCredentialUnset")) : null)) :
|
|
36252
|
+
}, t("mcpCredentialUnset")) : null)) : null);
|
|
35634
36253
|
}));
|
|
35635
36254
|
}
|
|
35636
36255
|
//#endregion
|
|
@@ -35694,9 +36313,75 @@ function searchableFor(payload) {
|
|
|
35694
36313
|
searchableCache.set(payload, searchable);
|
|
35695
36314
|
return searchable;
|
|
35696
36315
|
}
|
|
36316
|
+
/**
|
|
36317
|
+
* Every tool worth listing: what the server registered, plus every name the
|
|
36318
|
+
* suite or the user mentions.
|
|
36319
|
+
*
|
|
36320
|
+
* A denied tool leaves the live registry, so the stored lists are the only
|
|
36321
|
+
* thing keeping it on screen and available to switch back on. The suite's
|
|
36322
|
+
* allow-list and deny list both read as suite-limited; the user's own denials
|
|
36323
|
+
* stay selectable.
|
|
36324
|
+
*/
|
|
36325
|
+
function mcpToolRows(entry) {
|
|
36326
|
+
const allowedNames = entry.suiteEnabledTools;
|
|
36327
|
+
const suiteDenied = new Set(entry.suiteDisabledTools ?? []);
|
|
36328
|
+
const userDenied = new Set(entry.userDisabledTools ?? []);
|
|
36329
|
+
const names = /* @__PURE__ */ new Set([
|
|
36330
|
+
...entry.tools.map((tool) => tool.name),
|
|
36331
|
+
...allowedNames ?? [],
|
|
36332
|
+
...suiteDenied,
|
|
36333
|
+
...userDenied
|
|
36334
|
+
]);
|
|
36335
|
+
const observed = new Map(entry.tools.map((tool) => [tool.name, tool]));
|
|
36336
|
+
return [...names].sort().map((name) => {
|
|
36337
|
+
const suiteLimited = allowedNames !== void 0 && !allowedNames.includes(name) || suiteDenied.has(name);
|
|
36338
|
+
const tool = observed.get(name);
|
|
36339
|
+
return {
|
|
36340
|
+
name,
|
|
36341
|
+
allowed: !suiteLimited && !userDenied.has(name),
|
|
36342
|
+
suiteLimited,
|
|
36343
|
+
...tool?.description === void 0 ? {} : { description: tool.description },
|
|
36344
|
+
...tool?.parameters === void 0 ? {} : { parameters: tool.parameters }
|
|
36345
|
+
};
|
|
36346
|
+
});
|
|
36347
|
+
}
|
|
36348
|
+
//#endregion
|
|
36349
|
+
//#region src/client/features/mcp-status/diagnostic-guidance.ts
|
|
36350
|
+
/** The locale key holding the advice for one classified failure. */
|
|
36351
|
+
const MCP_GUIDANCE_LABEL = {
|
|
36352
|
+
credentials: "mcpGuideCredentials",
|
|
36353
|
+
auth: "mcpGuideAuth",
|
|
36354
|
+
transport: "mcpGuideTransport",
|
|
36355
|
+
backend: "mcpGuideBackend",
|
|
36356
|
+
dns: "mcpGuideDns",
|
|
36357
|
+
tls: "mcpGuideTls",
|
|
36358
|
+
refused: "mcpGuideRefused",
|
|
36359
|
+
timeout: "mcpGuideTimeout",
|
|
36360
|
+
commandMissing: "mcpGuideCommandMissing",
|
|
36361
|
+
processExit: "mcpGuideProcessExit",
|
|
36362
|
+
protocol: "mcpGuideProtocol"
|
|
36363
|
+
};
|
|
36364
|
+
/** Classify one failure, or nothing when its wording matches no known shape. */
|
|
36365
|
+
function mcpGuidanceKey(code, reason) {
|
|
36366
|
+
const text = `${code ?? ""} ${reason ?? ""}`;
|
|
36367
|
+
if (code === "missing-credential") return "credentials";
|
|
36368
|
+
if (/credential|\$\{[A-Za-z_][A-Za-z0-9_]*\}/i.test(text)) return "credentials";
|
|
36369
|
+
if (code === "unsupported-transport") return "transport";
|
|
36370
|
+
if (/built-in backend|cannot enforce/i.test(text)) return "backend";
|
|
36371
|
+
if (/401|403|unauthor|oauth|forbidden|challenge/i.test(text)) return "auth";
|
|
36372
|
+
if (/ENOTFOUND|getaddrinfo|EAI_AGAIN|dns/i.test(text)) return "dns";
|
|
36373
|
+
if (/certificate|TLS|SSL|self.signed/i.test(text)) return "tls";
|
|
36374
|
+
if (/ECONNREFUSED|connection refused/i.test(text)) return "refused";
|
|
36375
|
+
if (/ETIMEDOUT|timed out|timeout/i.test(text)) return "timeout";
|
|
36376
|
+
if (/ENOENT|not found|no such file|spawn/i.test(text)) return "commandMissing";
|
|
36377
|
+
if (/exited|exit code|SIGTERM|SIGKILL|crash/i.test(text)) return "processExit";
|
|
36378
|
+
if (/jsonrpc|protocol|initialize|handshake/i.test(text)) return "protocol";
|
|
36379
|
+
}
|
|
35697
36380
|
//#endregion
|
|
35698
36381
|
//#region src/client/mcp-status.module.css
|
|
35699
36382
|
var mcp_status_module_default = {
|
|
36383
|
+
"blockHeadRow": "AUWlZW_blockHeadRow",
|
|
36384
|
+
"blockSub": "AUWlZW_blockSub",
|
|
35700
36385
|
"cardTop": "AUWlZW_cardTop",
|
|
35701
36386
|
"detail": "AUWlZW_detail",
|
|
35702
36387
|
"detailBody": "AUWlZW_detailBody",
|
|
@@ -35709,7 +36394,13 @@ var mcp_status_module_default = {
|
|
|
35709
36394
|
"modalFooter": "AUWlZW_modalFooter",
|
|
35710
36395
|
"modalFooterGrow": "AUWlZW_modalFooterGrow",
|
|
35711
36396
|
"modalFooterHint": "AUWlZW_modalFooterHint",
|
|
36397
|
+
"pasteArea": "AUWlZW_pasteArea",
|
|
36398
|
+
"pasteCheck": "AUWlZW_pasteCheck",
|
|
36399
|
+
"pasteNote": "AUWlZW_pasteNote",
|
|
36400
|
+
"pasteOutcome": "AUWlZW_pasteOutcome",
|
|
36401
|
+
"reasonActions": "AUWlZW_reasonActions",
|
|
35712
36402
|
"reasonBox": "AUWlZW_reasonBox",
|
|
36403
|
+
"reasonHint": "AUWlZW_reasonHint",
|
|
35713
36404
|
"reasonLabel": "AUWlZW_reasonLabel",
|
|
35714
36405
|
"reasonRaw": "AUWlZW_reasonRaw",
|
|
35715
36406
|
"reasonText": "AUWlZW_reasonText",
|
|
@@ -35721,12 +36412,28 @@ var mcp_status_module_default = {
|
|
|
35721
36412
|
"seamPath": "AUWlZW_seamPath",
|
|
35722
36413
|
"seamPathLabel": "AUWlZW_seamPathLabel",
|
|
35723
36414
|
"seamTitle": "AUWlZW_seamTitle",
|
|
36415
|
+
"starter": "AUWlZW_starter",
|
|
36416
|
+
"starterList": "AUWlZW_starterList",
|
|
36417
|
+
"starterPaste": "AUWlZW_starterPaste",
|
|
35724
36418
|
"surface": "AUWlZW_surface HJ9x7a_shell",
|
|
35725
36419
|
"tool": "AUWlZW_tool",
|
|
35726
36420
|
"toolbar": "AUWlZW_toolbar",
|
|
35727
36421
|
"toolDescription": "AUWlZW_toolDescription",
|
|
36422
|
+
"toolIdentity": "AUWlZW_toolIdentity",
|
|
35728
36423
|
"toolList": "AUWlZW_toolList",
|
|
35729
|
-
"
|
|
36424
|
+
"toolMore": "AUWlZW_toolMore",
|
|
36425
|
+
"toolName": "AUWlZW_toolName",
|
|
36426
|
+
"toolNameButton": "AUWlZW_toolNameButton",
|
|
36427
|
+
"toolNote": "AUWlZW_toolNote",
|
|
36428
|
+
"toolParam": "AUWlZW_toolParam",
|
|
36429
|
+
"toolParamDesc": "AUWlZW_toolParamDesc",
|
|
36430
|
+
"toolParamName": "AUWlZW_toolParamName",
|
|
36431
|
+
"toolParamRequired": "AUWlZW_toolParamRequired",
|
|
36432
|
+
"toolParams": "AUWlZW_toolParams",
|
|
36433
|
+
"toolParamsEmpty": "AUWlZW_toolParamsEmpty",
|
|
36434
|
+
"toolParamsGrid": "AUWlZW_toolParamsGrid",
|
|
36435
|
+
"toolParamType": "AUWlZW_toolParamType",
|
|
36436
|
+
"toolSearch": "AUWlZW_toolSearch"
|
|
35730
36437
|
};
|
|
35731
36438
|
//#endregion
|
|
35732
36439
|
//#region src/client/McpStatusPanel.tsx
|
|
@@ -35745,6 +36452,8 @@ const EMPTY_STATUS$1 = {
|
|
|
35745
36452
|
},
|
|
35746
36453
|
directObservationOnly: true
|
|
35747
36454
|
};
|
|
36455
|
+
/** How many tool rows a collapsed capability list shows before its expand row. */
|
|
36456
|
+
const TOOL_PAGE_SIZE = 8;
|
|
35748
36457
|
/** DSH-native MCP inventory with a per-state overview and per-service detail. */
|
|
35749
36458
|
function McpStatusPanel({ t, credentials }) {
|
|
35750
36459
|
const [payload, setPayload] = (0, react.useState)(EMPTY_STATUS$1);
|
|
@@ -35754,6 +36463,7 @@ function McpStatusPanel({ t, credentials }) {
|
|
|
35754
36463
|
const [search, setSearch] = (0, react.useState)("");
|
|
35755
36464
|
const [view, setView] = useWorkspaceView();
|
|
35756
36465
|
const [selected, setSelected] = (0, react.useState)(void 0);
|
|
36466
|
+
const [editing, setEditing] = (0, react.useState)();
|
|
35757
36467
|
const [adding, setAdding] = (0, react.useState)(false);
|
|
35758
36468
|
const observe = async (id) => {
|
|
35759
36469
|
const refreshed = await fetchMcpStatus();
|
|
@@ -35828,10 +36538,12 @@ function McpStatusPanel({ t, credentials }) {
|
|
|
35828
36538
|
entry,
|
|
35829
36539
|
t,
|
|
35830
36540
|
onClick: () => setSelected(entry),
|
|
35831
|
-
onToggle: () => toggle(entry)
|
|
36541
|
+
onToggle: () => toggle(entry),
|
|
36542
|
+
onEdit: () => setEditing(entry)
|
|
35832
36543
|
}))), adding ? (0, react.createElement)(McpAddModal, {
|
|
35833
36544
|
t,
|
|
35834
36545
|
onClose: () => setAdding(false),
|
|
36546
|
+
onChanged: refresh,
|
|
35835
36547
|
onSaved: () => {
|
|
35836
36548
|
setAdding(false);
|
|
35837
36549
|
refresh();
|
|
@@ -35840,6 +36552,7 @@ function McpStatusPanel({ t, credentials }) {
|
|
|
35840
36552
|
entry: selected,
|
|
35841
36553
|
t,
|
|
35842
36554
|
credentials,
|
|
36555
|
+
backend: payload.backend ?? "builtin",
|
|
35843
36556
|
onClose: () => {
|
|
35844
36557
|
setSelected(void 0);
|
|
35845
36558
|
refresh();
|
|
@@ -35847,6 +36560,11 @@ function McpStatusPanel({ t, credentials }) {
|
|
|
35847
36560
|
onRetry: retry,
|
|
35848
36561
|
onReauthorize: reauthorize,
|
|
35849
36562
|
onRefresh: observe
|
|
36563
|
+
}), editing === void 0 ? null : (0, react.createElement)(McpConfigModal, {
|
|
36564
|
+
entry: editing,
|
|
36565
|
+
t,
|
|
36566
|
+
onClose: () => setEditing(void 0),
|
|
36567
|
+
onSaved: refresh
|
|
35850
36568
|
}));
|
|
35851
36569
|
}
|
|
35852
36570
|
/** The state tag's tone; a healthy server reads as success. */
|
|
@@ -35888,7 +36606,7 @@ function mcpDotState(state) {
|
|
|
35888
36606
|
* configuration) live in the detail dialog, so a wall of failing cards stays
|
|
35889
36607
|
* scannable.
|
|
35890
36608
|
*/
|
|
35891
|
-
function McpCard({ entry, t, onClick, onToggle }) {
|
|
36609
|
+
function McpCard({ entry, t, onClick, onToggle, onEdit }) {
|
|
35892
36610
|
const interactive = {
|
|
35893
36611
|
role: "button",
|
|
35894
36612
|
tabIndex: 0,
|
|
@@ -35906,7 +36624,16 @@ function McpCard({ entry, t, onClick, onToggle }) {
|
|
|
35906
36624
|
state: entry.state === "connected" ? "active" : entry.state === "disabled" ? "disabled" : entry.state === "failed" || entry.state === "orphaned" ? "error" : "warning",
|
|
35907
36625
|
surface: "mcp",
|
|
35908
36626
|
...interactive
|
|
35909
|
-
}, (0, react.createElement)("div", { className: resource_card_module_default.rowId }, (0, react.createElement)("span", { className: `${resource_card_module_default.name} ${resource_card_module_default.nameMono}` }, entry.name), (0, react.createElement)(
|
|
36627
|
+
}, (0, react.createElement)("div", { className: resource_card_module_default.rowId }, (0, react.createElement)("span", { className: `${resource_card_module_default.name} ${resource_card_module_default.nameMono}` }, entry.name), (0, react.createElement)("span", { className: resource_card_module_default.provenanceChip }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: "neutral" }, entry.kind === "plugin" ? t("mcpPlugin") : t("mcpDirect")))), (0, react.createElement)("div", { className: resource_card_module_default.rowActions }, switchable ? (0, react.createElement)("button", {
|
|
36628
|
+
type: "button",
|
|
36629
|
+
className: resource_card_module_default.iconBtn,
|
|
36630
|
+
title: t("panelEdit"),
|
|
36631
|
+
"aria-label": `${t("panelEdit")} ${entry.name}`,
|
|
36632
|
+
onClick: (event) => {
|
|
36633
|
+
event.stopPropagation();
|
|
36634
|
+
onEdit();
|
|
36635
|
+
}
|
|
36636
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineMedium)) : null, (0, react.createElement)("span", {
|
|
35910
36637
|
className: resource_card_module_default.switchWrap,
|
|
35911
36638
|
onClick: (event) => event.stopPropagation()
|
|
35912
36639
|
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
@@ -35926,12 +36653,46 @@ function McpCard({ entry, t, onClick, onToggle }) {
|
|
|
35926
36653
|
* echo. The state pill is dropped entirely — the dot and the reason box carry
|
|
35927
36654
|
* that information without a second red stamp.
|
|
35928
36655
|
*/
|
|
35929
|
-
function McpDetailModal({ entry, t, credentials, onClose, onRetry, onReauthorize, onRefresh }) {
|
|
36656
|
+
function McpDetailModal({ entry, t, credentials, backend, onClose, onRetry, onReauthorize, onRefresh }) {
|
|
35930
36657
|
const [pending, setPending] = (0, react.useState)(false);
|
|
35931
|
-
const [dirty, setDirty] = (0, react.useState)(false);
|
|
35932
36658
|
const [confirmAuth, setConfirmAuth] = (0, react.useState)(false);
|
|
35933
36659
|
const [feedback, setFeedback] = (0, react.useState)();
|
|
36660
|
+
const [toolBusy, setToolBusy] = (0, react.useState)(false);
|
|
36661
|
+
const [toolsExpanded, setToolsExpanded] = (0, react.useState)(false);
|
|
36662
|
+
const [toolSearch, setToolSearch] = (0, react.useState)("");
|
|
36663
|
+
const [expandedTools, setExpandedTools] = (0, react.useState)({});
|
|
36664
|
+
const [enabledBusy, setEnabledBusy] = (0, react.useState)(false);
|
|
35934
36665
|
const actions = mcpDetailActions(entry);
|
|
36666
|
+
const guidance = mcpGuidanceKey(entry.code, entry.reason);
|
|
36667
|
+
const tools = mcpToolRows(entry);
|
|
36668
|
+
const needle = toolSearch.trim().toLowerCase();
|
|
36669
|
+
const matchingTools = needle === "" ? tools : tools.filter((tool) => tool.name.toLowerCase().includes(needle));
|
|
36670
|
+
const shownTools = toolsExpanded ? matchingTools : matchingTools.slice(0, TOOL_PAGE_SIZE);
|
|
36671
|
+
const hiddenToolCount = matchingTools.length - shownTools.length;
|
|
36672
|
+
const toolsEditable = entry.suiteId !== void 0 && entry.serverKey !== void 0 && entry.state !== "foreign";
|
|
36673
|
+
const toggleTool = (tool, enabled) => {
|
|
36674
|
+
const suiteId = entry.suiteId;
|
|
36675
|
+
const serverKey = entry.serverKey;
|
|
36676
|
+
if (suiteId === void 0 || serverKey === void 0) return;
|
|
36677
|
+
setToolBusy(true);
|
|
36678
|
+
setFeedback(void 0);
|
|
36679
|
+
setMcpServerTool(suiteId, serverKey, tool, enabled).then(() => onRefresh(entry.id)).catch((reason) => setFeedback({
|
|
36680
|
+
error: true,
|
|
36681
|
+
text: clientErrorMessage(t, reason)
|
|
36682
|
+
})).finally(() => setToolBusy(false));
|
|
36683
|
+
};
|
|
36684
|
+
/** Switch the whole server on or off through the same override the card's switch writes. */
|
|
36685
|
+
const toggleEnabled = () => {
|
|
36686
|
+
const suiteId = entry.suiteId;
|
|
36687
|
+
const serverKey = entry.serverKey;
|
|
36688
|
+
if (suiteId === void 0 || serverKey === void 0) return;
|
|
36689
|
+
setEnabledBusy(true);
|
|
36690
|
+
setFeedback(void 0);
|
|
36691
|
+
setMcpServerEnabled(suiteId, serverKey, entry.state === "disabled").then(() => onRefresh(entry.id)).catch((reason) => setFeedback({
|
|
36692
|
+
error: true,
|
|
36693
|
+
text: clientErrorMessage(t, reason)
|
|
36694
|
+
})).finally(() => setEnabledBusy(false));
|
|
36695
|
+
};
|
|
35935
36696
|
const run = async (authorize) => {
|
|
35936
36697
|
setConfirmAuth(false);
|
|
35937
36698
|
setPending(true);
|
|
@@ -35961,19 +36722,11 @@ function McpDetailModal({ entry, t, credentials, onClose, onRetry, onReauthorize
|
|
|
35961
36722
|
description: t("mcpServiceDetail"),
|
|
35962
36723
|
closeLabel: t("mcpClose"),
|
|
35963
36724
|
contentClassName: mcp_status_module_default.detailBody,
|
|
35964
|
-
footer: (0, react.createElement)("div", { className: mcp_status_module_default.modalFooter }, actions.
|
|
36725
|
+
footer: (0, react.createElement)("div", { className: mcp_status_module_default.modalFooter }, actions.reauthorize ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
35965
36726
|
variant: "ghost",
|
|
35966
36727
|
size: "sm",
|
|
35967
|
-
disabled: pending
|
|
35968
|
-
title:
|
|
35969
|
-
onClick: () => {
|
|
35970
|
-
run(false);
|
|
35971
|
-
}
|
|
35972
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16), t("mcpRetryConnection")) : null, actions.reauthorize ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
35973
|
-
variant: "ghost",
|
|
35974
|
-
size: "sm",
|
|
35975
|
-
disabled: pending || dirty,
|
|
35976
|
-
title: dirty ? t("mcpSaveFirst") : t("mcpReauthExplain"),
|
|
36728
|
+
disabled: pending,
|
|
36729
|
+
title: t("mcpReauthExplain"),
|
|
35977
36730
|
onClick: () => {
|
|
35978
36731
|
setConfirmAuth(true);
|
|
35979
36732
|
setFeedback(void 0);
|
|
@@ -35982,7 +36735,13 @@ function McpDetailModal({ entry, t, credentials, onClose, onRetry, onReauthorize
|
|
|
35982
36735
|
variant: "ghost",
|
|
35983
36736
|
disabled: pending,
|
|
35984
36737
|
onClick: onClose
|
|
35985
|
-
}, t("mcpClose"))),
|
|
36738
|
+
}, t("mcpClose")), entry.suiteId === void 0 || entry.serverKey === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
36739
|
+
checked: entry.state !== "disabled",
|
|
36740
|
+
disabled: pending || enabledBusy,
|
|
36741
|
+
label: t("mcpEnabledLabel"),
|
|
36742
|
+
title: t("mcpEnabledLabel"),
|
|
36743
|
+
onChange: () => toggleEnabled()
|
|
36744
|
+
})),
|
|
35986
36745
|
children: (0, react.createElement)("div", null, feedback ? (0, react.createElement)("p", {
|
|
35987
36746
|
role: feedback.error ? "alert" : "status",
|
|
35988
36747
|
className: feedback.error ? mcp_status_module_default.error : mcp_status_module_default.retryEchoSuccess
|
|
@@ -35994,45 +36753,154 @@ function McpDetailModal({ entry, t, credentials, onClose, onRetry, onReauthorize
|
|
|
35994
36753
|
onClick: () => setConfirmAuth(false)
|
|
35995
36754
|
}, t("cancel")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
35996
36755
|
variant: "primary",
|
|
35997
|
-
disabled:
|
|
36756
|
+
disabled: pending,
|
|
35998
36757
|
onClick: () => {
|
|
35999
36758
|
run(true);
|
|
36000
36759
|
}
|
|
36001
|
-
}, t("mcpConfirmReauth"))) : null,
|
|
36760
|
+
}, t("mcpConfirmReauth"))) : null, entry.state === "needs-credentials" ? (0, react.createElement)("p", { className: mcp_status_module_default.reasonText }, t("mcpConfigureCredentialsFirst")) : null, (0, react.createElement)("div", { className: panel_module_default.hero }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: mcpDotState(entry.state) }), (0, react.createElement)("div", { className: panel_module_default.heroText }, (0, react.createElement)("div", { className: panel_module_default.heroLine }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: mcpTagTone(entry.state) }, mcpStateLabel(t, entry.state)), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, null, entry.kind === "plugin" ? t("mcpPlugin") : t("mcpDirect")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: "quiet" }, entry.transport), entry.oauthDefault === true ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: "quiet" }, t("mcpOauthDefault")) : null), (0, react.createElement)("p", { className: panel_module_default.heroMono }, entry.endpoint ?? t("mcpObservedEndpoint")))), (0, react.createElement)("div", { className: panel_module_default.block }, (0, react.createElement)("h4", { className: panel_module_default.blockHead }, t("overviewSection")), (0, react.createElement)("dl", { className: panel_module_default.kvGrid }, kvCell(t("sourceLabel"), entry.kind === "plugin" ? entry.suiteId ?? entry.source ?? "—" : t("mcpDirect"), true), kvCell(t("detailTypeLabel"), entry.kind === "plugin" ? t("panelSourcePlugin") : t("panelSourceUser")), kvCell(t("detailTransport"), entry.transport, true), kvCell(t("mcpServerKeyLabel"), entry.serverKey ?? entry.name, true))), entry.state === "foreign" ? (0, react.createElement)("div", { className: mcp_status_module_default.reasonBox }, (0, react.createElement)("span", { className: mcp_status_module_default.reasonLabel }, t("mcpReasonLabel")), (0, react.createElement)("p", { className: mcp_status_module_default.reasonText }, entry.code === "duplicate-mount" ? t("mcpDuplicateHint") : t("mcpForeignHint")), entry.reason === void 0 ? null : (0, react.createElement)("p", { className: mcp_status_module_default.reasonRaw }, entry.reason)) : entry.reason === void 0 && !actions.retry ? null : (0, react.createElement)("div", { className: mcp_status_module_default.reasonBox }, entry.reason === void 0 ? null : (0, react.createElement)("span", { className: mcp_status_module_default.reasonLabel }, t("mcpReasonLabel")), entry.reason === void 0 ? null : (0, react.createElement)("p", { className: mcp_status_module_default.reasonText }, entry.reason), guidance === void 0 ? null : (0, react.createElement)("p", { className: mcp_status_module_default.reasonHint }, t(MCP_GUIDANCE_LABEL[guidance])), actions.retry ? (0, react.createElement)("div", { className: mcp_status_module_default.reasonActions }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
36761
|
+
variant: "outline",
|
|
36762
|
+
size: "sm",
|
|
36763
|
+
disabled: pending,
|
|
36764
|
+
title: t("mcpRetryPreservesCredentials"),
|
|
36765
|
+
onClick: () => {
|
|
36766
|
+
run(false);
|
|
36767
|
+
}
|
|
36768
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutlineMedium), t("mcpRetryConnection"))) : null), entry.kind === "direct" && !entry.managed ? (0, react.createElement)("div", { className: mcp_status_module_default.reasonBox }, (0, react.createElement)("p", { className: mcp_status_module_default.reasonText }, t("mcpDirectBoundary"))) : null, (0, react.createElement)("div", { className: panel_module_default.block }, (0, react.createElement)("div", { className: mcp_status_module_default.blockHeadRow }, (0, react.createElement)("h4", { className: panel_module_default.blockHead }, `${t("mcpTools")} (${tools.length})`), tools.length > TOOL_PAGE_SIZE ? (0, react.createElement)("label", { className: mcp_status_module_default.toolSearch }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
36769
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineMedium),
|
|
36770
|
+
value: toolSearch,
|
|
36771
|
+
placeholder: t("mcpToolsSearch"),
|
|
36772
|
+
"aria-label": t("mcpToolsSearch"),
|
|
36773
|
+
onChange: (event) => setToolSearch(event.target.value)
|
|
36774
|
+
})) : null), toolsEditable && backend === "host" ? (0, react.createElement)("p", { className: mcp_status_module_default.blockSub }, t("mcpHostToolsUnsupported")) : null, tools.length === 0 ? (0, react.createElement)("p", { className: panel_module_default.detailProse }, entry.advertisedTools === false && entry.state === "degraded" ? t("mcpZeroTools") : t("mcpNoTools")) : matchingTools.length === 0 ? (0, react.createElement)("p", { className: panel_module_default.detailProse }, t("mcpToolsNoMatch")) : (0, react.createElement)("div", { className: mcp_status_module_default.toolList }, shownTools.map((tool) => (0, react.createElement)("div", {
|
|
36775
|
+
key: tool.name,
|
|
36776
|
+
className: mcp_status_module_default.tool
|
|
36777
|
+
}, (0, react.createElement)("span", { className: mcp_status_module_default.toolIdentity }, toolsEditable ? (0, react.createElement)("input", {
|
|
36778
|
+
type: "checkbox",
|
|
36779
|
+
checked: tool.allowed,
|
|
36780
|
+
disabled: toolBusy || tool.suiteLimited || backend === "host",
|
|
36781
|
+
"aria-label": `${t("mcpAllowTool")} ${tool.name}`,
|
|
36782
|
+
onChange: (event) => toggleTool(tool.name, event.target.checked)
|
|
36783
|
+
}) : null, tool.parameters === void 0 ? (0, react.createElement)("span", { className: mcp_status_module_default.toolName }, tool.name) : (0, react.createElement)("button", {
|
|
36784
|
+
type: "button",
|
|
36785
|
+
className: `${mcp_status_module_default.toolName} ${mcp_status_module_default.toolNameButton}`,
|
|
36786
|
+
"aria-expanded": expandedTools[tool.name] === true,
|
|
36787
|
+
onClick: () => setExpandedTools((current) => ({
|
|
36788
|
+
...current,
|
|
36789
|
+
[tool.name]: current[tool.name] !== true
|
|
36790
|
+
}))
|
|
36791
|
+
}, tool.name)), (0, react.createElement)("span", { className: mcp_status_module_default.toolDescription }, tool.description ?? ""), (0, react.createElement)("span", { className: mcp_status_module_default.toolNote }, tool.suiteLimited ? t("mcpToolSuiteLimited") : ""), expandedTools[tool.name] === true ? (0, react.createElement)("div", { className: mcp_status_module_default.toolParams }, toolParameterRows(tool.parameters, t)) : null)), hiddenToolCount > 0 ? (0, react.createElement)("button", {
|
|
36792
|
+
type: "button",
|
|
36793
|
+
className: mcp_status_module_default.toolMore,
|
|
36794
|
+
onClick: () => setToolsExpanded(true)
|
|
36795
|
+
}, t("mcpToolsMore", { count: hiddenToolCount })) : null)), entry.credentialRefs?.length === 0 || entry.credentialRefs === void 0 ? null : (0, react.createElement)(McpCredentialEditor, {
|
|
36002
36796
|
t,
|
|
36003
36797
|
api: credentials,
|
|
36004
|
-
refs: entry.credentialRefs
|
|
36005
|
-
|
|
36798
|
+
refs: entry.credentialRefs,
|
|
36799
|
+
usage: credentialUsage(t, entry.config)
|
|
36800
|
+
}))
|
|
36801
|
+
});
|
|
36802
|
+
}
|
|
36803
|
+
/**
|
|
36804
|
+
* The editor dialog: one scroll column of form fields, opened from the detail
|
|
36805
|
+
* dialog's service-configuration block. Reporting and changing live in separate
|
|
36806
|
+
* dialogs, so neither has to share the other's layout.
|
|
36807
|
+
*/
|
|
36808
|
+
function McpConfigModal({ entry, t, onClose, onSaved }) {
|
|
36809
|
+
return (0, react.createElement)(DetailModal, {
|
|
36810
|
+
open: true,
|
|
36811
|
+
title: t("mcpEditTitle"),
|
|
36812
|
+
description: entry.name,
|
|
36813
|
+
closeLabel: t("cancel"),
|
|
36814
|
+
onClose,
|
|
36815
|
+
size: "md",
|
|
36816
|
+
contentClassName: mcp_status_module_default.detailBody,
|
|
36817
|
+
footer: (0, react.createElement)("div", { className: mcp_status_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
36818
|
+
variant: "ghost",
|
|
36819
|
+
onClick: onClose
|
|
36820
|
+
}, t("cancel"))),
|
|
36821
|
+
children: (0, react.createElement)(ServerConfigDetail, {
|
|
36006
36822
|
kind: "mcp",
|
|
36007
36823
|
id: entry.id,
|
|
36008
36824
|
t,
|
|
36009
|
-
|
|
36010
|
-
|
|
36011
|
-
onRefresh(entry.id).catch((reason) => setFeedback({
|
|
36012
|
-
error: true,
|
|
36013
|
-
text: t("mcpSavedStatusUnknown") + ": " + String(reason)
|
|
36014
|
-
}));
|
|
36015
|
-
}
|
|
36016
|
-
})), (0, react.createElement)("div", { className: panel_module_default.block }, (0, react.createElement)("h4", { className: panel_module_default.blockHead }, `${t("mcpTools")} (${entry.tools.length})`), entry.tools.length === 0 ? (0, react.createElement)("p", { className: panel_module_default.detailProse }, entry.advertisedTools === false && entry.state === "degraded" ? t("mcpZeroTools") : t("mcpNoTools")) : (0, react.createElement)("div", { className: mcp_status_module_default.toolList }, entry.tools.map((tool) => (0, react.createElement)("div", {
|
|
36017
|
-
key: tool.name,
|
|
36018
|
-
className: mcp_status_module_default.tool
|
|
36019
|
-
}, (0, react.createElement)("span", { className: mcp_status_module_default.toolName }, tool.name), tool.description === void 0 || tool.description === "" ? null : (0, react.createElement)("span", { className: mcp_status_module_default.toolDescription }, tool.description))))))
|
|
36825
|
+
onSaved
|
|
36826
|
+
})
|
|
36020
36827
|
});
|
|
36021
36828
|
}
|
|
36022
|
-
function McpAddModal({ t, onClose, onSaved }) {
|
|
36829
|
+
function McpAddModal({ t, onClose, onSaved, onChanged }) {
|
|
36023
36830
|
const [name, setName] = (0, react.useState)("");
|
|
36024
36831
|
const [config, setConfig] = (0, react.useState)("{\"type\":\"stdio\",\"command\":\"\"}");
|
|
36025
36832
|
const [valid, setValid] = (0, react.useState)(false);
|
|
36026
36833
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
36027
36834
|
const [error, setError] = (0, react.useState)();
|
|
36835
|
+
const [fieldErrors, setFieldErrors] = (0, react.useState)();
|
|
36836
|
+
const [templatesOpen, setTemplatesOpen] = (0, react.useState)(false);
|
|
36837
|
+
const [pasteOpen, setPasteOpen] = (0, react.useState)(false);
|
|
36838
|
+
const [pasteText, setPasteText] = (0, react.useState)("");
|
|
36839
|
+
const [pasteError, setPasteError] = (0, react.useState)();
|
|
36840
|
+
const [overwrite, setOverwrite] = (0, react.useState)(false);
|
|
36841
|
+
const [pasteOutcome, setPasteOutcome] = (0, react.useState)();
|
|
36842
|
+
const pasted = pasteOpen && pasteText.trim() !== "" ? parsePastedServersOrUndefined(pasteText) : void 0;
|
|
36843
|
+
const applyTemplate = (template) => {
|
|
36844
|
+
setConfig(JSON.stringify(template.config, null, 2));
|
|
36845
|
+
setTemplatesOpen(false);
|
|
36846
|
+
setPasteError(void 0);
|
|
36847
|
+
};
|
|
36848
|
+
const applyPaste = () => {
|
|
36849
|
+
try {
|
|
36850
|
+
const pasted = parsePastedServer(pasteText);
|
|
36851
|
+
if (pasted.name !== void 0 && name.trim() === "") setName(pasted.name);
|
|
36852
|
+
setConfig(JSON.stringify(pasted.config, null, 2));
|
|
36853
|
+
setPasteOpen(false);
|
|
36854
|
+
setPasteError(void 0);
|
|
36855
|
+
} catch (reason) {
|
|
36856
|
+
setPasteError(reason instanceof Error ? reason.message : String(reason));
|
|
36857
|
+
}
|
|
36858
|
+
};
|
|
36859
|
+
const runImport = () => {
|
|
36860
|
+
if (pasted === void 0) return;
|
|
36861
|
+
const named = pasted.filter((entry) => entry.name !== void 0 && entry.name !== "");
|
|
36862
|
+
const unnamed = pasted.length - named.length;
|
|
36863
|
+
if (named.length === 0) {
|
|
36864
|
+
setPasteOutcome({
|
|
36865
|
+
imported: [],
|
|
36866
|
+
skipped: [{
|
|
36867
|
+
name: "—",
|
|
36868
|
+
reason: t("mcpPasteUnnamed")
|
|
36869
|
+
}]
|
|
36870
|
+
});
|
|
36871
|
+
return;
|
|
36872
|
+
}
|
|
36873
|
+
setBusy(true);
|
|
36874
|
+
setPasteError(void 0);
|
|
36875
|
+
setPasteOutcome(void 0);
|
|
36876
|
+
importMcpServers(named.map((entry) => ({
|
|
36877
|
+
name: entry.name,
|
|
36878
|
+
config: entry.config
|
|
36879
|
+
})), overwrite).then((result) => {
|
|
36880
|
+
const skipped = [...result.skipped, ...unnamed === 0 ? [] : [{
|
|
36881
|
+
name: "—",
|
|
36882
|
+
reason: t("mcpPasteUnnamed")
|
|
36883
|
+
}]];
|
|
36884
|
+
setPasteOutcome({
|
|
36885
|
+
imported: result.imported,
|
|
36886
|
+
skipped
|
|
36887
|
+
});
|
|
36888
|
+
if (result.imported.length > 0) onChanged?.();
|
|
36889
|
+
}).catch((reason) => setPasteError(clientErrorMessage(t, reason))).finally(() => setBusy(false));
|
|
36890
|
+
};
|
|
36028
36891
|
const save = () => {
|
|
36029
36892
|
setBusy(true);
|
|
36030
36893
|
setError(void 0);
|
|
36031
|
-
|
|
36894
|
+
setFieldErrors(void 0);
|
|
36895
|
+
Promise.resolve().then(() => addMcpServer(name.trim(), parseServerConfig(config))).then(onSaved).catch((caught) => {
|
|
36896
|
+
setError(clientErrorMessage(t, caught));
|
|
36897
|
+
setFieldErrors(fieldErrorsOf(caught));
|
|
36898
|
+
}).finally(() => setBusy(false));
|
|
36032
36899
|
};
|
|
36033
36900
|
return (0, react.createElement)(DetailModal, {
|
|
36034
36901
|
open: true,
|
|
36035
36902
|
title: t("mcpAddTitle"),
|
|
36903
|
+
size: "md",
|
|
36036
36904
|
onClose: busy ? () => {} : onClose,
|
|
36037
36905
|
closeLabel: t("cancel"),
|
|
36038
36906
|
contentClassName: mcp_status_module_default.detailBody,
|
|
@@ -36045,12 +36913,67 @@ function McpAddModal({ t, onClose, onSaved }) {
|
|
|
36045
36913
|
disabled: busy || name.trim() === "" || !valid,
|
|
36046
36914
|
onClick: save
|
|
36047
36915
|
}, t("editorCreate"))),
|
|
36048
|
-
children: (0, react.createElement)("div", { className: mcp_status_module_default.detail }, (0, react.createElement)(
|
|
36916
|
+
children: (0, react.createElement)("div", { className: mcp_status_module_default.detail }, (0, react.createElement)("div", { className: mcp_status_module_default.starter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
36917
|
+
variant: "outline",
|
|
36918
|
+
size: "sm",
|
|
36919
|
+
type: "button",
|
|
36920
|
+
disabled: busy,
|
|
36921
|
+
"aria-expanded": templatesOpen,
|
|
36922
|
+
onClick: () => setTemplatesOpen((value) => !value)
|
|
36923
|
+
}, t("mcpStarterTemplates")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
36924
|
+
variant: "outline",
|
|
36925
|
+
size: "sm",
|
|
36926
|
+
type: "button",
|
|
36927
|
+
disabled: busy,
|
|
36928
|
+
"aria-expanded": pasteOpen,
|
|
36929
|
+
onClick: () => setPasteOpen((value) => !value)
|
|
36930
|
+
}, t("mcpStarterPaste"))), templatesOpen ? (0, react.createElement)("div", { className: mcp_status_module_default.starterList }, ...MCP_TEMPLATES.map((template) => (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
36931
|
+
key: template.id,
|
|
36932
|
+
variant: "ghost",
|
|
36933
|
+
size: "sm",
|
|
36934
|
+
type: "button",
|
|
36935
|
+
disabled: busy,
|
|
36936
|
+
onClick: () => applyTemplate(template)
|
|
36937
|
+
}, t(template.labelKey)))) : null, pasteOpen ? (0, react.createElement)("div", { className: mcp_status_module_default.starterPaste }, (0, react.createElement)("textarea", {
|
|
36938
|
+
className: mcp_status_module_default.pasteArea,
|
|
36939
|
+
value: pasteText,
|
|
36940
|
+
spellCheck: false,
|
|
36941
|
+
"aria-label": t("mcpStarterPaste"),
|
|
36942
|
+
placeholder: t("mcpPastePlaceholder"),
|
|
36943
|
+
disabled: busy,
|
|
36944
|
+
onChange: (event) => {
|
|
36945
|
+
setPasteText(event.target.value);
|
|
36946
|
+
setPasteOutcome(void 0);
|
|
36947
|
+
setPasteError(void 0);
|
|
36948
|
+
}
|
|
36949
|
+
}), pasted === void 0 ? null : (0, react.createElement)("p", { className: mcp_status_module_default.pasteNote }, t("mcpPasteFound", { count: pasted.length })), (0, react.createElement)("div", { className: mcp_status_module_default.starter }, pasted !== void 0 && pasted.length === 1 ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
36950
|
+
variant: "outline",
|
|
36951
|
+
size: "sm",
|
|
36952
|
+
type: "button",
|
|
36953
|
+
disabled: busy,
|
|
36954
|
+
onClick: applyPaste
|
|
36955
|
+
}, t("mcpPasteApply")) : null, pasted === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
36956
|
+
variant: "primary",
|
|
36957
|
+
size: "sm",
|
|
36958
|
+
type: "button",
|
|
36959
|
+
disabled: busy,
|
|
36960
|
+
onClick: runImport
|
|
36961
|
+
}, t("mcpPasteImport"))), pasted !== void 0 && pasted.length > 1 ? (0, react.createElement)("label", { className: mcp_status_module_default.pasteCheck }, (0, react.createElement)("input", {
|
|
36962
|
+
type: "checkbox",
|
|
36963
|
+
checked: overwrite,
|
|
36964
|
+
disabled: busy,
|
|
36965
|
+
onChange: (event) => setOverwrite(event.target.checked)
|
|
36966
|
+
}), " ", t("mcpPasteOverwrite")) : null, pasteOutcome === void 0 ? null : (0, react.createElement)("div", { className: mcp_status_module_default.pasteOutcome }, pasteOutcome.imported.length === 0 ? null : (0, react.createElement)("p", null, t("mcpPasteImported", { names: pasteOutcome.imported.join(", ") })), pasteOutcome.skipped.length === 0 ? null : (0, react.createElement)("p", null, t("mcpPasteSkipped", { detail: pasteOutcome.skipped.map((entry) => `${entry.name} (${entry.reason})`).join(", ") }))), pasteError === void 0 ? null : (0, react.createElement)("div", {
|
|
36967
|
+
role: "alert",
|
|
36968
|
+
className: mcp_status_module_default.error
|
|
36969
|
+
}, pasteError)) : null, (0, react.createElement)(ServerConfigEditor, {
|
|
36049
36970
|
kind: "mcp",
|
|
36050
36971
|
text: config,
|
|
36051
36972
|
onChange: setConfig,
|
|
36052
36973
|
t,
|
|
36053
36974
|
disabled: busy,
|
|
36975
|
+
createMode: true,
|
|
36976
|
+
...fieldErrors === void 0 ? {} : { fieldErrors },
|
|
36054
36977
|
onValidityChange: setValid,
|
|
36055
36978
|
nameField: {
|
|
36056
36979
|
label: t("mcpServerName"),
|
|
@@ -36081,6 +37004,57 @@ function mcpFilterHint(t, kind) {
|
|
|
36081
37004
|
if (kind === "disabled") return t("mcpFilterDisabledHint");
|
|
36082
37005
|
return t("mcpFilterAllHint");
|
|
36083
37006
|
}
|
|
37007
|
+
/**
|
|
37008
|
+
* Where each credential reference is used, as `<field label> <key>` entries read
|
|
37009
|
+
* from the server configuration: a token named in a request header and an
|
|
37010
|
+
* environment variable are the two seams the mount-time expander fills.
|
|
37011
|
+
*/
|
|
37012
|
+
/**
|
|
37013
|
+
* The parameters one tool advertises: name, type, whether it is required, and
|
|
37014
|
+
* the server's own description. A nested schema keeps its type name; the full
|
|
37015
|
+
* definition stays with the tool list the model already receives.
|
|
37016
|
+
*/
|
|
37017
|
+
function toolParameterRows(parameters, t) {
|
|
37018
|
+
const schema = parameters ?? {};
|
|
37019
|
+
const properties = schema.properties;
|
|
37020
|
+
if (properties === null || typeof properties !== "object" || Array.isArray(properties) || Object.keys(properties).length === 0) return (0, react.createElement)("p", { className: mcp_status_module_default.toolParamsEmpty }, t("mcpToolNoParameters"));
|
|
37021
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required.filter((value) => typeof value === "string") : []);
|
|
37022
|
+
return (0, react.createElement)("div", { className: mcp_status_module_default.toolParamsGrid }, ...Object.entries(properties).map(([name, raw]) => {
|
|
37023
|
+
const node = raw ?? {};
|
|
37024
|
+
const type = typeof node.type === "string" ? node.type : Array.isArray(node.enum) ? "enum" : "any";
|
|
37025
|
+
return (0, react.createElement)("div", {
|
|
37026
|
+
key: name,
|
|
37027
|
+
className: mcp_status_module_default.toolParam
|
|
37028
|
+
}, (0, react.createElement)("span", { className: mcp_status_module_default.toolParamName }, name), (0, react.createElement)("span", { className: mcp_status_module_default.toolParamType }, type), (0, react.createElement)("span", { className: mcp_status_module_default.toolParamRequired }, required.has(name) ? t("mcpToolParamRequired") : ""), (0, react.createElement)("span", { className: mcp_status_module_default.toolParamDesc }, typeof node.description === "string" ? node.description : ""));
|
|
37029
|
+
}));
|
|
37030
|
+
}
|
|
37031
|
+
/** Parse a pasted document, or nothing while it is still half-typed. */
|
|
37032
|
+
function parsePastedServersOrUndefined(text) {
|
|
37033
|
+
try {
|
|
37034
|
+
return parsePastedServers(text);
|
|
37035
|
+
} catch {
|
|
37036
|
+
return;
|
|
37037
|
+
}
|
|
37038
|
+
}
|
|
37039
|
+
function credentialUsage(t, config) {
|
|
37040
|
+
const usage = {};
|
|
37041
|
+
if (config === void 0) return usage;
|
|
37042
|
+
for (const [field, label] of [["headers", t("detailHeaders")], ["env", t("detailEnv")]]) {
|
|
37043
|
+
const values = config[field];
|
|
37044
|
+
if (typeof values !== "object" || values === null) continue;
|
|
37045
|
+
for (const [key, value] of Object.entries(values)) {
|
|
37046
|
+
if (typeof value !== "string") continue;
|
|
37047
|
+
for (const match of value.matchAll(/\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g)) {
|
|
37048
|
+
const name = match[1];
|
|
37049
|
+
if (name === void 0) continue;
|
|
37050
|
+
const entries = usage[name] ?? [];
|
|
37051
|
+
entries.push(`${label} ${key}`);
|
|
37052
|
+
usage[name] = entries;
|
|
37053
|
+
}
|
|
37054
|
+
}
|
|
37055
|
+
}
|
|
37056
|
+
return usage;
|
|
37057
|
+
}
|
|
36084
37058
|
//#endregion
|
|
36085
37059
|
//#region src/client/features/lsp-status/lsp-status-view-model.ts
|
|
36086
37060
|
/** Filter tabs in display order: scope first, the switched-off rows last. */
|
|
@@ -36189,6 +37163,7 @@ function LspStatusPanel({ t }) {
|
|
|
36189
37163
|
const [search, setSearch] = (0, react.useState)("");
|
|
36190
37164
|
const [view, setView] = useWorkspaceView();
|
|
36191
37165
|
const [selected, setSelected] = (0, react.useState)(void 0);
|
|
37166
|
+
const [editing, setEditing] = (0, react.useState)();
|
|
36192
37167
|
const [editorOpen, setEditorOpen] = (0, react.useState)(false);
|
|
36193
37168
|
const [seamMigration, setSeamMigration] = (0, react.useState)(void 0);
|
|
36194
37169
|
const refresh = () => {
|
|
@@ -36275,7 +37250,8 @@ function LspStatusPanel({ t }) {
|
|
|
36275
37250
|
entry,
|
|
36276
37251
|
t,
|
|
36277
37252
|
onOpen: () => setSelected(entry),
|
|
36278
|
-
onToggle: () => toggle(entry)
|
|
37253
|
+
onToggle: () => toggle(entry),
|
|
37254
|
+
onEdit: () => setEditing(entry)
|
|
36279
37255
|
}))), selected === void 0 ? null : (0, react.createElement)(LspDetailModal, {
|
|
36280
37256
|
entry: selected,
|
|
36281
37257
|
t,
|
|
@@ -36283,6 +37259,11 @@ function LspStatusPanel({ t }) {
|
|
|
36283
37259
|
setSelected(void 0);
|
|
36284
37260
|
refresh();
|
|
36285
37261
|
}
|
|
37262
|
+
}), editing === void 0 ? null : (0, react.createElement)(LspConfigModal, {
|
|
37263
|
+
entry: editing,
|
|
37264
|
+
t,
|
|
37265
|
+
onClose: () => setEditing(void 0),
|
|
37266
|
+
onSaved: refresh
|
|
36286
37267
|
}), editorOpen ? (0, react.createElement)(LspConfigEditor, {
|
|
36287
37268
|
t,
|
|
36288
37269
|
onClose: () => setEditorOpen(false),
|
|
@@ -36361,6 +37342,7 @@ function LspConfigEditor({ t, onClose, onSaved }) {
|
|
|
36361
37342
|
open: true,
|
|
36362
37343
|
onClose: busy ? () => {} : onClose,
|
|
36363
37344
|
title: t("lspAddTitle"),
|
|
37345
|
+
size: "md",
|
|
36364
37346
|
closeLabel: t("cancel"),
|
|
36365
37347
|
contentClassName: mcp_status_module_default.detailBody,
|
|
36366
37348
|
footer: (0, react.createElement)("div", { className: mcp_status_module_default.modalFooter }, (0, react.createElement)("span", { className: mcp_status_module_default.modalFooterHint }, t("editorFooterCreate")), (0, react.createElement)("div", { className: mcp_status_module_default.modalFooterGrow }), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
@@ -36380,6 +37362,7 @@ function LspConfigEditor({ t, onClose, onSaved }) {
|
|
|
36380
37362
|
onChange: setText,
|
|
36381
37363
|
t,
|
|
36382
37364
|
disabled: busy,
|
|
37365
|
+
createMode: true,
|
|
36383
37366
|
onValidityChange: setValid,
|
|
36384
37367
|
nameField: {
|
|
36385
37368
|
label: t("lspServerName"),
|
|
@@ -36413,7 +37396,7 @@ function lspTagTone(state) {
|
|
|
36413
37396
|
* row and the enable switch on its trailing edge; the command on the body row;
|
|
36414
37397
|
* the declaring suite and the extension count on the source row.
|
|
36415
37398
|
*/
|
|
36416
|
-
function LspRow({ entry, t, onOpen, onToggle }) {
|
|
37399
|
+
function LspRow({ entry, t, onOpen, onToggle, onEdit }) {
|
|
36417
37400
|
const interactive = {
|
|
36418
37401
|
role: "button",
|
|
36419
37402
|
tabIndex: 0,
|
|
@@ -36430,7 +37413,16 @@ function LspRow({ entry, t, onOpen, onToggle }) {
|
|
|
36430
37413
|
state: entry.state === "mounted" ? "active" : disabled ? "disabled" : entry.state === "failed" || entry.state === "conflict" ? "error" : "warning",
|
|
36431
37414
|
surface: "lsp",
|
|
36432
37415
|
...interactive
|
|
36433
|
-
}, (0, react.createElement)("div", { className: resource_card_module_default.rowId }, (0, react.createElement)("span", { className: `${resource_card_module_default.name} ${resource_card_module_default.nameMono}` }, entry.serverKey), (0, react.createElement)(
|
|
37416
|
+
}, (0, react.createElement)("div", { className: resource_card_module_default.rowId }, (0, react.createElement)("span", { className: `${resource_card_module_default.name} ${resource_card_module_default.nameMono}` }, entry.serverKey), (0, react.createElement)("span", { className: resource_card_module_default.provenanceChip }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: "neutral" }, entry.kind === "plugin" ? t("lspPlugin") : t("lspDirect")))), (0, react.createElement)("div", { className: resource_card_module_default.rowActions }, (0, react.createElement)("button", {
|
|
37417
|
+
type: "button",
|
|
37418
|
+
className: resource_card_module_default.iconBtn,
|
|
37419
|
+
title: t("panelEdit"),
|
|
37420
|
+
"aria-label": `${t("panelEdit")} ${entry.serverKey}`,
|
|
37421
|
+
onClick: (event) => {
|
|
37422
|
+
event.stopPropagation();
|
|
37423
|
+
onEdit();
|
|
37424
|
+
}
|
|
37425
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineMedium)), (0, react.createElement)("span", {
|
|
36434
37426
|
className: resource_card_module_default.switchWrap,
|
|
36435
37427
|
onClick: (event) => event.stopPropagation()
|
|
36436
37428
|
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
@@ -36455,16 +37447,37 @@ function LspDetailModal({ entry, t, onClose }) {
|
|
|
36455
37447
|
variant: "ghost",
|
|
36456
37448
|
onClick: onClose
|
|
36457
37449
|
}, t("detailDone"))),
|
|
36458
|
-
children: (0, react.createElement)("div", null, (0, react.createElement)("div", { className: panel_module_default.hero }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: lspDotState(entry.state) }), (0, react.createElement)("div", { className: panel_module_default.heroText }, (0, react.createElement)("div", { className: panel_module_default.heroLine }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: lspTagTone(entry.state) }, stateLabel(t, entry.state)), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, null, entry.kind === "plugin" ? t("lspPlugin") : t("lspDirect")), entry.kind === "plugin" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: "quiet" }, entry.suiteName) : null), (0, react.createElement)("p", { className: panel_module_default.heroMono }, [entry.command, ...entry.args].join(" ")))), (0, react.createElement)("div", { className: panel_module_default.block }, (0, react.createElement)("h4", { className: panel_module_default.blockHead }, t("overviewSection")), (0, react.createElement)("dl", { className: panel_module_default.kvGrid }, kv$1(t("sourceLabel"), entry.kind === "plugin" ? entry.suiteName : t("lspDirect"), false), kv$1(t("detailTypeLabel"), entry.kind === "plugin" ? t("panelSourcePlugin") : t("panelSourceUser"), false), kv$1(t("lspDeclaredInLabel"), entry.kind === "plugin" ? `lsp.json · ${entry.suiteName}` : "lsp.json", true)
|
|
37450
|
+
children: (0, react.createElement)("div", null, (0, react.createElement)("div", { className: panel_module_default.hero }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: lspDotState(entry.state) }), (0, react.createElement)("div", { className: panel_module_default.heroText }, (0, react.createElement)("div", { className: panel_module_default.heroLine }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: lspTagTone(entry.state) }, stateLabel(t, entry.state)), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, null, entry.kind === "plugin" ? t("lspPlugin") : t("lspDirect")), entry.kind === "plugin" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: "quiet" }, entry.suiteName) : null), (0, react.createElement)("p", { className: panel_module_default.heroMono }, [entry.command, ...entry.args].join(" ")))), (0, react.createElement)("div", { className: panel_module_default.block }, (0, react.createElement)("h4", { className: panel_module_default.blockHead }, t("overviewSection")), (0, react.createElement)("dl", { className: panel_module_default.kvGrid }, kv$1(t("sourceLabel"), entry.kind === "plugin" ? entry.suiteName : t("lspDirect"), false), kv$1(t("detailTypeLabel"), entry.kind === "plugin" ? t("panelSourcePlugin") : t("panelSourceUser"), false), kv$1(t("lspDeclaredInLabel"), entry.kind === "plugin" ? `lsp.json · ${entry.suiteName}` : "lsp.json", true))), entry.reason === void 0 ? null : (0, react.createElement)("div", { className: panel_module_default.block }, (0, react.createElement)("h4", { className: panel_module_default.blockHead }, t("lspReasonLabel")), (0, react.createElement)("div", { className: mcp_status_module_default.reasonBox }, (0, react.createElement)("p", { className: mcp_status_module_default.reasonText }, entry.reason))), (0, react.createElement)("div", { className: panel_module_default.block }, (0, react.createElement)("h4", { className: panel_module_default.blockHead }, `${t("detailExtensions")} (${Object.keys(entry.extensions).length})`), (0, react.createElement)(DetailRows, null, ...Object.entries(entry.extensions).map(([extension, language]) => (0, react.createElement)(DetailRow, {
|
|
36459
37451
|
key: extension,
|
|
36460
37452
|
name: extension,
|
|
36461
37453
|
summary: language,
|
|
36462
37454
|
expandable: false
|
|
36463
|
-
}))))
|
|
37455
|
+
})))))
|
|
37456
|
+
});
|
|
37457
|
+
}
|
|
37458
|
+
/**
|
|
37459
|
+
* The editor dialog for one language server: a form of its own, opened from the
|
|
37460
|
+
* card's edit action and sharing the add flow's dialog.
|
|
37461
|
+
*/
|
|
37462
|
+
function LspConfigModal({ entry, t, onClose, onSaved }) {
|
|
37463
|
+
return (0, react.createElement)(DetailModal, {
|
|
37464
|
+
open: true,
|
|
37465
|
+
title: t("lspEditTitle"),
|
|
37466
|
+
description: entry.serverKey,
|
|
37467
|
+
closeLabel: t("cancel"),
|
|
37468
|
+
onClose,
|
|
37469
|
+
size: "md",
|
|
37470
|
+
contentClassName: mcp_status_module_default.detailBody,
|
|
37471
|
+
footer: (0, react.createElement)("div", { className: mcp_status_module_default.modalFooter }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
37472
|
+
variant: "ghost",
|
|
37473
|
+
onClick: onClose
|
|
37474
|
+
}, t("cancel"))),
|
|
37475
|
+
children: (0, react.createElement)(ServerConfigDetail, {
|
|
36464
37476
|
kind: "lsp",
|
|
36465
37477
|
id: entry.id,
|
|
36466
|
-
t
|
|
36467
|
-
|
|
37478
|
+
t,
|
|
37479
|
+
onSaved
|
|
37480
|
+
})
|
|
36468
37481
|
});
|
|
36469
37482
|
}
|
|
36470
37483
|
/** One label/value pair in a detail dialog's overview grid. */
|
|
@@ -36483,6 +37496,22 @@ function stateLabel(t, state) {
|
|
|
36483
37496
|
return t("lspDisabled");
|
|
36484
37497
|
}
|
|
36485
37498
|
//#endregion
|
|
37499
|
+
//#region src/model/command-names.ts
|
|
37500
|
+
/**
|
|
37501
|
+
* The call name a command resource registers under.
|
|
37502
|
+
*
|
|
37503
|
+
* A command resource may live at any depth under its `commands/` directory,
|
|
37504
|
+
* but the host's slash-command grammar accepts single-segment names only, so
|
|
37505
|
+
* registration flattens the path separators: `git/commit` registers as
|
|
37506
|
+
* `git-commit`. The user panel renders the same call name, so a card never
|
|
37507
|
+
* advertises a slash name the host cannot accept.
|
|
37508
|
+
* @module model/command-names
|
|
37509
|
+
*/
|
|
37510
|
+
/** Flatten a resource path into the single-segment name a slash command registers under. */
|
|
37511
|
+
function commandCallName(name) {
|
|
37512
|
+
return name.replaceAll("/", "-").replaceAll("\\", "-").toLowerCase();
|
|
37513
|
+
}
|
|
37514
|
+
//#endregion
|
|
36486
37515
|
//#region src/client/features/personas/RoleMetadataFields.tsx
|
|
36487
37516
|
/** Structured controls edit the same frontmatter as the raw Markdown editor. */
|
|
36488
37517
|
function RoleMetadataFields(props) {
|
|
@@ -36638,7 +37667,7 @@ function UserEntryDetailModal(props) {
|
|
|
36638
37667
|
const [open, setOpen] = (0, react.useState)(false);
|
|
36639
37668
|
const updated = entry.updatedAt === void 0 || entry.updatedAt === null ? null : lastChangeLabel(t, entry.updatedAt);
|
|
36640
37669
|
const provenance = entry.origin === "user" ? t("panelSourceUser") : t("panelSourcePlugin");
|
|
36641
|
-
const title = kind === "commands" ? `/${entry.name}` : entry.name;
|
|
37670
|
+
const title = kind === "commands" ? `/${commandCallName(entry.name)}` : entry.name;
|
|
36642
37671
|
const docName = kind === "skills" ? "SKILL.md" : `${entry.name}.md`;
|
|
36643
37672
|
const metaPairs = Object.entries(entry.metadata).filter(([key]) => !HIDDEN_META.has(key));
|
|
36644
37673
|
return (0, react.createElement)(DetailModal, {
|
|
@@ -36942,7 +37971,7 @@ function UserPanelSurface(props) {
|
|
|
36942
37971
|
*/
|
|
36943
37972
|
function UserEntryRow(props) {
|
|
36944
37973
|
const { entry, t } = props;
|
|
36945
|
-
const title = props.kind === "commands" ? `/${entry.name}` : entry.name;
|
|
37974
|
+
const title = props.kind === "commands" ? `/${commandCallName(entry.name)}` : entry.name;
|
|
36946
37975
|
const mono = props.kind === "commands";
|
|
36947
37976
|
const locked = props.busy || entry.metadata["validationError"] !== void 0;
|
|
36948
37977
|
const stop = (callback) => (event) => {
|
|
@@ -36970,14 +37999,14 @@ function UserEntryRow(props) {
|
|
|
36970
37999
|
disabled: props.busy,
|
|
36971
38000
|
title: t("panelEditTitle"),
|
|
36972
38001
|
onClick: stop(props.onEdit)
|
|
36973
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
38002
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconEditOutlineMedium)), (0, react.createElement)("button", {
|
|
36974
38003
|
type: "button",
|
|
36975
38004
|
className: `${resource_card_module_default.iconBtn} ${resource_card_module_default.iconBtnDanger} ${resource_card_module_default.revealOnHover}`,
|
|
36976
38005
|
"aria-label": t("panelDelete"),
|
|
36977
38006
|
disabled: props.busy,
|
|
36978
38007
|
title: t("panelDelete"),
|
|
36979
38008
|
onClick: stop(props.onDelete)
|
|
36980
|
-
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
38009
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineMedium)), (0, react.createElement)("span", {
|
|
36981
38010
|
className: resource_card_module_default.switchWrap,
|
|
36982
38011
|
onClick: (event) => event.stopPropagation()
|
|
36983
38012
|
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
@@ -37109,7 +38138,7 @@ function renderTab(tab, t, credentials, mode) {
|
|
|
37109
38138
|
*
|
|
37110
38139
|
* @module client/McpPluginCard
|
|
37111
38140
|
*/
|
|
37112
|
-
/** Copy of the
|
|
38141
|
+
/** Copy of the boolean switches, in display order. */
|
|
37113
38142
|
const SWITCH_FIELDS = [
|
|
37114
38143
|
"mcpEnhanced",
|
|
37115
38144
|
"scanProjectLayouts",
|
|
@@ -37181,7 +38210,7 @@ function McpPluginCard(props) {
|
|
|
37181
38210
|
onClick: () => {
|
|
37182
38211
|
setOpen((current) => !current);
|
|
37183
38212
|
}
|
|
37184
|
-
}, (0, react.createElement)("div", { className: market_module_default.pluginCardText }, (0, react.createElement)("div", { className: market_module_default.pluginCardTitle }, t("nav")), (0, react.createElement)("div", { className: market_module_default.pluginCardDesc }, t("marketCardDesc"))), state.dirty ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: "neutral" }, t("settingUnsaved")) : null, (0, react.createElement)("span", { className: open ? `${market_module_default.pluginChevron} ${market_module_default.pluginChevronOpen}` : market_module_default.pluginChevron }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.
|
|
38213
|
+
}, (0, react.createElement)("div", { className: market_module_default.pluginCardText }, (0, react.createElement)("div", { className: market_module_default.pluginCardTitle }, t("nav")), (0, react.createElement)("div", { className: market_module_default.pluginCardDesc }, t("marketCardDesc"))), state.dirty ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Tag, { tone: "neutral" }, t("settingUnsaved")) : null, (0, react.createElement)("span", { className: open ? `${market_module_default.pluginChevron} ${market_module_default.pluginChevronOpen}` : market_module_default.pluginChevron }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium))), open ? (0, react.createElement)("div", { className: market_module_default.pluginCardBody }, state.writable ? null : (0, react.createElement)("p", {
|
|
37185
38214
|
className: market_module_default.pluginCardReadonly,
|
|
37186
38215
|
role: "status"
|
|
37187
38216
|
}, t("mcpCardReadonly")), SWITCH_FIELDS.map((field) => (0, react.createElement)(SwitchRow, {
|
|
@@ -37274,7 +38303,7 @@ var MarketPluginCardController = class {
|
|
|
37274
38303
|
failed = false;
|
|
37275
38304
|
disposed = false;
|
|
37276
38305
|
/**
|
|
37277
|
-
* @param scope - the
|
|
38306
|
+
* @param scope - the host configuration form for the market namespace.
|
|
37278
38307
|
* @param probe - reads the live host-client and region state from the market API.
|
|
37279
38308
|
*/
|
|
37280
38309
|
constructor(scope, probeSource) {
|
|
@@ -37778,20 +38807,24 @@ function apply(ctx) {
|
|
|
37778
38807
|
isSettingsSurfaceAvailable: () => settingsSurfaceAvailable,
|
|
37779
38808
|
subscribeLocale: ctx.locale.subscribe === void 0 ? void 0 : (listener) => ctx.locale.subscribe(listener)
|
|
37780
38809
|
}), "dsh-agent-plugins-market: legacy page mode");
|
|
37781
|
-
ctx.inject?.(["
|
|
37782
|
-
const service = scoped.
|
|
38810
|
+
ctx.inject?.(["configForms"], (scoped) => {
|
|
38811
|
+
const service = scoped.configForms;
|
|
37783
38812
|
const slots = scoped.slots;
|
|
37784
38813
|
if (service === void 0 || slots === void 0) return;
|
|
37785
|
-
|
|
37786
|
-
|
|
38814
|
+
let card;
|
|
38815
|
+
service.whileServed([NS], () => {
|
|
38816
|
+
card = new MarketPluginCardController(service.get(NS), fetchMcpBackend);
|
|
37787
38817
|
const dispose = slots.register({
|
|
37788
|
-
name: "
|
|
37789
|
-
|
|
38818
|
+
name: "plugins.item",
|
|
38819
|
+
id: NS,
|
|
38820
|
+
order: 50,
|
|
38821
|
+
label: () => t("nav"),
|
|
37790
38822
|
locale: NS,
|
|
37791
38823
|
inject: () => card.inject()
|
|
37792
38824
|
}, McpPluginCard);
|
|
37793
38825
|
return () => {
|
|
37794
|
-
card
|
|
38826
|
+
card?.dispose();
|
|
38827
|
+
card = void 0;
|
|
37795
38828
|
if (typeof dispose === "function") dispose();
|
|
37796
38829
|
};
|
|
37797
38830
|
});
|