dsh-vscode-mode 0.1.16 → 0.1.19
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 +17 -0
- package/lib/client.js +390 -21
- package/lib/client.js.map +1 -1
- package/lib/index.js +250 -26
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/addToConversation.ts +211 -0
- package/src/client/index.ts +16 -2
- package/src/client/styles/editor.css +6 -0
- package/src/client/styles/mcp.css +9 -0
- package/src/client/ui/EditorView.ts +168 -16
- package/src/client/ui/McpSettings.ts +32 -1
- package/src/compat.ts +3 -2
- package/src/devForm.ts +133 -0
- package/src/rpc.ts +74 -18
- package/src/shared/compat.ts +7 -0
- package/src/shared/rpc.ts +24 -2
- package/src/store.ts +6 -2
package/lib/client.js
CHANGED
|
@@ -29,7 +29,7 @@ window.__ModuleLoader__.load({
|
|
|
29
29
|
let react = require("react");
|
|
30
30
|
react = __toESM(react, 1);
|
|
31
31
|
//#region \0dsh-css:/home/runner/work/DSH_VsCodeMode/DSH_VsCodeMode/src/client/styles/editor.css.mjs
|
|
32
|
-
const css$1 = "/* dsh-vscode-mode 编辑区样式(原 ensureEdrvStyles 字符串,落盘为真 .css,由 tsdown CSS-inline 注入) */\n/* 浅色主题(对齐参考图:#f8f8f8 近白底 + 薄荷绿药丸 + 青绿文字 + 三文鱼 undo + 浅灰边框):\n 在 [data-edrv-view] 作用域内重定义 --dsw-alias-*,级联命中组件内联样式与 CSS。 */\n[data-edrv-view] { --edrv-tab-h: 34px; --dsw-alias-bg-base: #f8f8f8; --dsw-alias-bg-layer-1: #ffffff; --dsw-alias-bg-layer-2: #f0f4f4; --dsw-alias-bg-overlay: #ffffff; --dsw-alias-label-primary: #1f2933; --dsw-alias-label-secondary: #52606d; --dsw-alias-label-tertiary: #9aa5b1; --dsw-alias-border-l1: #e0e6e8; --dsw-alias-border-l2: #cbd2d9; --dsw-alias-brand-primary: #0f9d58; --dsw-alias-state-success-primary: #0f9d58; --dsw-alias-state-error-primary: #d9534f; --dsw-alias-state-warn-primary: #d97706; --dsw-alias-interactive-bg-hover: rgba(15,157,88,.08); }\n\n[data-edrv-view] .edrv-tabs { display: flex; align-items: center; gap: 2px; padding: 2px 8px 0; background: var(--dsw-alias-bg-layer-1, transparent); overflow-x: auto; scrollbar-width: thin; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px 0 12px; border: none; border-radius: 6px 6px 0 0; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 12px; cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-tab.edrv-tab-active { background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); box-shadow: inset 0 -2px 0 var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-tab .edrv-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dsw-alias-brand-primary, #4f8cff); flex-shrink: 0; }\n[data-edrv-view] .edrv-tab .edrv-tab-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 4px; color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; }\n[data-edrv-view] .edrv-tab .edrv-tab-x:hover { background: rgba(255,255,255,.12); color: var(--dsw-alias-label-primary, #eee); }\n[data-edrv-view] .edrv-tab-add { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-left: 2px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 14px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab-add:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-pathbar { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 10px; background: var(--dsw-alias-bg-layer-1, #ffffff); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); font-size: 12px; flex-shrink: 0; overflow: hidden; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-name { font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-full { flex: 1; min-width: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: rtl; text-align: left; }\n[data-edrv-view] .edrv-path-input { flex: 1; min-width: 140px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search-wrap { position: relative; flex-shrink: 0; display: flex; align-items: center; padding: 2px 8px 2px 4px; }\n[data-edrv-view] .edrv-search { width: 190px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-pop { position: absolute; top: calc(100% + 4px); right: 8px; width: min(460px, calc(100vw - 24px)); max-height: 300px; overflow: auto; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 10px; box-shadow: 0 6px 20px rgba(0,0,0,.4); z-index: 60; padding: 4px; }\n[data-edrv-view] .edrv-search-item { display: flex; flex-direction: column; gap: 1px; padding: 5px 8px; border-radius: 6px; cursor: pointer; }\n[data-edrv-view] .edrv-search-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.07)); }\n[data-edrv-view] .edrv-search-item .n { color: var(--dsw-alias-label-primary, #eee); font-size: 12px; word-break: break-all; }\n[data-edrv-view] .edrv-search-item .d { color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-search-empty { padding: 8px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #888); }\n[data-edrv-view] .edrv-btn-mini { font-size: 11px; padding: 2px 9px; border: none; border-radius: 999px; cursor: pointer; color: #fff; font-weight: 600; white-space: nowrap; }\n[data-edrv-view] .edrv-btn-keep { background: var(--dsw-alias-state-success-primary, #2e9e44); }\n[data-edrv-view] .edrv-btn-undo { background: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-btn-mini:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-statusbar { display: flex; align-items: center; gap: 10px; padding: 3px 10px; border-top: 1px solid var(--dsw-alias-border-l1, #333); background: var(--dsw-alias-bg-layer-1, transparent); font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); flex-shrink: 0; white-space: nowrap; overflow: hidden; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-path { flex: 1; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffchip { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-state-warn-primary, #b7791f); cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn { font-size: 12px; padding: 2px 6px; border: none; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; border-radius: 4px; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-mn-add-line { background: rgba(15,157,88,.10); }\n[data-edrv-view] .edrv-mn-gutter-add { color: #0f9d58 !important; font-weight: 700; display: flex !important; align-items: center; justify-content: center; }\n[data-edrv-view] .edrv-mn-gutter-add::before { content: \"+\"; }\n[data-edrv-view] .edrv-del-zone { background: #fdeaea; border-top: 1px solid rgba(217,83,79,.35); border-bottom: 1px solid rgba(217,83,79,.35); box-shadow: inset 0 0 0 1px rgba(217,83,79,.12); }\n[data-edrv-view] .edrv-del-row { white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 12.5px; line-height: 20px; color: #c0392b; }\n[data-edrv-view] .edrv-del-text { display: inline-block; white-space: pre; }\n[data-edrv-view] .edrv-minus-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: 100%; overflow: visible; pointer-events: none; z-index: 6; }\n[data-edrv-view] .edrv-minus-item { position: absolute; box-sizing: border-box; max-width: 100%; overflow: hidden; }\n[data-edrv-view] .edrv-minus-item::before { content: ''; position: absolute; left: 4px; top: 50%; width: 8px; height: 2px; transform: translateY(-50%); border-radius: 2px; background: #d9534f; }\n[data-edrv-view] .edrv-monaco-host { flex: 1; min-height: 0; position: relative; }\n[data-edrv-view] .edrv-monaco-host > div { position: absolute; inset: 0; }\n[data-edrv-view] .edrv-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 100%; color: var(--dsw-alias-label-tertiary, #777); font-size: 13px; }\n[data-edrv-view] .edrv-diffbar { position: absolute; left: 0; right: 0; bottom: 10px; margin: 0 auto; z-index: 25; width: fit-content; max-width: calc(100% - 20px); border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 4px 16px rgba(31,41,51,.12); overflow: visible; display: flex; flex-direction: column; }\n[data-edrv-view] .edrv-diffbar-row { display: flex; align-items: center; gap: 6px; height: 34px; padding: 0 8px; flex-wrap: nowrap; }\n[data-edrv-view] .edrv-diffbar-count { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); min-width: 42px; text-align: center; white-space: nowrap; cursor: pointer; }\n[data-edrv-view] .edrv-diffbar-count.edrv-count-file { min-width: 64px; cursor: default; }\n[data-edrv-view] .edrv-diffbar-file { flex: 1; min-width: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-pill { font-size: 11px; padding: 3px 10px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-weight: 600; }\n[data-edrv-view] .edrv-pill-keep { background: #e8f8e8; color: #0f7a45; border: 1px solid rgba(15,157,88,.4); }\n[data-edrv-view] .edrv-pill-undo { background: #fdeaea; color: #c0392b; border: 1px solid rgba(217,83,79,.4); }\n[data-edrv-view] .edrv-pill-ghost { background: #ffffff; color: var(--dsw-alias-label-secondary, #52606d); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-diffbar-menu { position: absolute; right: 8px; bottom: calc(100% + 6px); z-index: 45; min-width: 160px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 6px 20px rgba(31,41,51,.16); padding: 4px; display: flex; flex-direction: column; gap: 2px; }\n[data-edrv-view] .edrv-diffmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; }\n[data-edrv-view] .edrv-diffmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffbar-body { max-height: 130px; max-width: min(560px, calc(100vw - 40px)); overflow: auto; padding: 4px 8px 8px; display: flex; flex-direction: column; gap: 4px; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 6px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffrow-l { font-size: 11px; color: var(--dsw-alias-label-primary, #1f2933); min-width: 74px; font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-o { font-size: 11px; color: var(--dsw-alias-state-error-primary, #d9534f); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-n { font-size: 11px; color: var(--dsw-alias-state-success-primary, #0f9d58); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-tag { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-diffrow-stale { border-color: rgba(217,119,6,.5); cursor: default; }\n[data-edrv-view] .edrv-diffbox-others { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 2px 0; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); margin-top: 2px; }\n[data-edrv-view] .edrv-diffrow-file { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n/* 编辑区 hover 差异块的 Keep/Undo 浮层 */\n[data-edrv-view] .edrv-hoveract { position: absolute; z-index: 30; display: flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 8px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 4px 14px rgba(31,41,51,.14); }\n[data-edrv-view] .edrv-launch { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 40; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); box-shadow: 0 6px 24px rgba(0,0,0,.5); display: flex; flex-direction: column; max-height: 60%; overflow: hidden; }\n[data-edrv-view] .edrv-launch-head { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--dsw-alias-border-l1, #333); }\n[data-edrv-view] .edrv-launch-tab { font-size: 12px; padding: 3px 12px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; }\n[data-edrv-view] .edrv-launch-tab.on { background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-label-primary, #eee); font-weight: 600; }\n[data-edrv-view] .edrv-launch-body { flex: 1; min-height: 0; overflow: auto; padding: 6px 8px; display: flex; flex-direction: column; gap: 4px; }\n[data-edrv-view] .edrv-launch-row { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 6px; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-launch-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-launch-path { flex: 1; min-width: 0; font-size: 12px; color: var(--dsw-alias-label-primary, #eee); word-break: break-all; }\n[data-edrv-view] .edrv-launch-cnt { font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); white-space: nowrap; }\n[data-edrv-view] .edrv-launch-arch { display: flex; flex-direction: column; gap: 6px; }\n[data-edrv-view] .monaco-editor { overflow: hidden !important; }\n[data-edrv-view] .monaco-editor .sticky-widget { z-index: 30 !important; background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-content,\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-number { background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor, [data-edrv-view] .monaco-editor .margin, [data-edrv-view] .monaco-editor-background { background: transparent !important; }\n[data-edrv-view] .monaco-editor .scrollbar .slider { background: rgba(128,128,128,.3) !important; }\n[data-edrv-view] .edrv-loading { gap: 8px; padding: 20px; }\n[data-edrv-view] .edrv-loading-title { color: var(--dsw-alias-label-primary, #1f2933); font-size: 13px; }\n[data-edrv-view] .edrv-progress { width: min(360px, 72%); height: 6px; overflow: hidden; border-radius: 999px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-progress-value { height: 100%; border-radius: inherit; background: var(--dsw-alias-brand-primary, #0f9d58); transition: width .24s ease; }\n[data-edrv-view] .edrv-loading-percent { color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; font-variant-numeric: tabular-nums; }\n@media (prefers-reduced-motion: reduce) {\n [data-edrv-view] .edrv-progress-value { transition: none; }\n}\n\n";
|
|
32
|
+
const css$1 = "/* dsh-vscode-mode 编辑区样式(原 ensureEdrvStyles 字符串,落盘为真 .css,由 tsdown CSS-inline 注入) */\n/* 浅色主题(对齐参考图:#f8f8f8 近白底 + 薄荷绿药丸 + 青绿文字 + 三文鱼 undo + 浅灰边框):\n 在 [data-edrv-view] 作用域内重定义 --dsw-alias-*,级联命中组件内联样式与 CSS。 */\n[data-edrv-view] { --edrv-tab-h: 34px; --dsw-alias-bg-base: #f8f8f8; --dsw-alias-bg-layer-1: #ffffff; --dsw-alias-bg-layer-2: #f0f4f4; --dsw-alias-bg-overlay: #ffffff; --dsw-alias-label-primary: #1f2933; --dsw-alias-label-secondary: #52606d; --dsw-alias-label-tertiary: #9aa5b1; --dsw-alias-border-l1: #e0e6e8; --dsw-alias-border-l2: #cbd2d9; --dsw-alias-brand-primary: #0f9d58; --dsw-alias-state-success-primary: #0f9d58; --dsw-alias-state-error-primary: #d9534f; --dsw-alias-state-warn-primary: #d97706; --dsw-alias-interactive-bg-hover: rgba(15,157,88,.08); }\n\n[data-edrv-view] .edrv-tabs { display: flex; align-items: center; gap: 2px; padding: 2px 8px 0; background: var(--dsw-alias-bg-layer-1, transparent); overflow-x: auto; scrollbar-width: thin; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px 0 12px; border: none; border-radius: 6px 6px 0 0; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 12px; cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-tab.edrv-tab-active { background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); box-shadow: inset 0 -2px 0 var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-tab .edrv-tab-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dsw-alias-brand-primary, #4f8cff); flex-shrink: 0; }\n[data-edrv-view] .edrv-tab .edrv-tab-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 4px; color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; }\n[data-edrv-view] .edrv-tab .edrv-tab-x:hover { background: rgba(255,255,255,.12); color: var(--dsw-alias-label-primary, #eee); }\n[data-edrv-view] .edrv-tab-add { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; margin-left: 2px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); font-size: 14px; cursor: pointer; flex-shrink: 0; }\n[data-edrv-view] .edrv-tab-add:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-pathbar { display: flex; align-items: center; gap: 8px; height: 26px; padding: 0 10px; background: var(--dsw-alias-bg-layer-1, #ffffff); border-bottom: 1px solid var(--dsw-alias-border-l1, #e0e6e8); font-size: 12px; flex-shrink: 0; overflow: hidden; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-name { font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); white-space: nowrap; }\n[data-edrv-view] .edrv-pathbar .edrv-pb-full { flex: 1; min-width: 0; color: var(--dsw-alias-label-tertiary, #9aa5b1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: rtl; text-align: left; }\n[data-edrv-view] .edrv-path-input { flex: 1; min-width: 140px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search-wrap { position: relative; flex-shrink: 0; display: flex; align-items: center; padding: 2px 8px 2px 4px; }\n[data-edrv-view] .edrv-search { width: 190px; height: 24px; padding: 0 8px; border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 6px; background: var(--dsw-alias-bg-base, #111); color: var(--dsw-alias-label-primary, #eee); font-size: 12px; outline: none; }\n[data-edrv-view] .edrv-search:focus { border-color: var(--dsw-alias-brand-primary, #4f8cff); }\n[data-edrv-view] .edrv-search-pop { position: absolute; top: calc(100% + 4px); right: 8px; width: min(460px, calc(100vw - 24px)); max-height: 300px; overflow: auto; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); border-radius: 10px; box-shadow: 0 6px 20px rgba(0,0,0,.4); z-index: 60; padding: 4px; }\n[data-edrv-view] .edrv-search-item { display: flex; flex-direction: column; gap: 1px; padding: 5px 8px; border-radius: 6px; cursor: pointer; }\n[data-edrv-view] .edrv-search-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.07)); }\n[data-edrv-view] .edrv-search-item .n { color: var(--dsw-alias-label-primary, #eee); font-size: 12px; word-break: break-all; }\n[data-edrv-view] .edrv-search-item .d { color: var(--dsw-alias-label-tertiary, #888); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-search-empty { padding: 8px; font-size: 12px; color: var(--dsw-alias-label-tertiary, #888); }\n[data-edrv-view] .edrv-btn-mini { font-size: 11px; padding: 2px 9px; border: none; border-radius: 999px; cursor: pointer; color: #fff; font-weight: 600; white-space: nowrap; }\n[data-edrv-view] .edrv-btn-keep { background: var(--dsw-alias-state-success-primary, #2e9e44); }\n[data-edrv-view] .edrv-btn-undo { background: var(--dsw-alias-state-warn-primary, #d97706); }\n[data-edrv-view] .edrv-btn-mini:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-statusbar { display: flex; align-items: center; gap: 10px; padding: 3px 10px; border-top: 1px solid var(--dsw-alias-border-l1, #333); background: var(--dsw-alias-bg-layer-1, transparent); font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); flex-shrink: 0; white-space: nowrap; overflow: hidden; }\n[data-edrv-view] .edrv-statusbar .edrv-sp-path { flex: 1; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffchip { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-state-warn-primary, #b7791f); cursor: pointer; white-space: nowrap; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn { font-size: 12px; padding: 2px 6px; border: none; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; border-radius: 4px; flex-shrink: 0; }\n[data-edrv-view] .edrv-chip-btn:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-mn-add-line { background: rgba(15,157,88,.10); }\n[data-edrv-view] .edrv-mn-gutter-add { color: #0f9d58 !important; font-weight: 700; display: flex !important; align-items: center; justify-content: center; }\n[data-edrv-view] .edrv-mn-gutter-add::before { content: \"+\"; }\n[data-edrv-view] .edrv-del-zone { background: #fdeaea; border-top: 1px solid rgba(217,83,79,.35); border-bottom: 1px solid rgba(217,83,79,.35); box-shadow: inset 0 0 0 1px rgba(217,83,79,.12); }\n[data-edrv-view] .edrv-del-row { white-space: pre; font-family: var(--ds-font-family-code, ui-monospace, monospace); font-size: 12.5px; line-height: 20px; color: #c0392b; }\n[data-edrv-view] .edrv-del-text { display: inline-block; white-space: pre; }\n[data-edrv-view] .edrv-minus-overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: 100%; overflow: visible; pointer-events: none; z-index: 6; }\n[data-edrv-view] .edrv-minus-item { position: absolute; box-sizing: border-box; max-width: 100%; overflow: hidden; }\n[data-edrv-view] .edrv-minus-item::before { content: ''; position: absolute; left: 4px; top: 50%; width: 8px; height: 2px; transform: translateY(-50%); border-radius: 2px; background: #d9534f; }\n[data-edrv-view] .edrv-monaco-host { flex: 1; min-height: 0; position: relative; }\n[data-edrv-view] .edrv-monaco-host > div { position: absolute; inset: 0; }\n[data-edrv-view] .edrv-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 100%; color: var(--dsw-alias-label-tertiary, #777); font-size: 13px; }\n[data-edrv-view] .edrv-diffbar { position: absolute; left: 0; right: 0; bottom: 10px; margin: 0 auto; z-index: 25; width: fit-content; max-width: calc(100% - 20px); border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 4px 16px rgba(31,41,51,.12); overflow: visible; display: flex; flex-direction: column; }\n[data-edrv-view] .edrv-diffbar-row { display: flex; align-items: center; gap: 6px; height: 34px; padding: 0 8px; flex-wrap: nowrap; }\n[data-edrv-view] .edrv-diffbar-count { font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary, #1f2933); min-width: 42px; text-align: center; white-space: nowrap; cursor: pointer; }\n[data-edrv-view] .edrv-diffbar-count.edrv-count-file { min-width: 64px; cursor: default; }\n[data-edrv-view] .edrv-diffbar-file { flex: 1; min-width: 0; font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n[data-edrv-view] .edrv-pill { font-size: 11px; padding: 3px 10px; border: none; border-radius: 999px; cursor: pointer; white-space: nowrap; font-weight: 600; }\n[data-edrv-view] .edrv-pill-keep { background: #e8f8e8; color: #0f7a45; border: 1px solid rgba(15,157,88,.4); }\n[data-edrv-view] .edrv-pill-undo { background: #fdeaea; color: #c0392b; border: 1px solid rgba(217,83,79,.4); }\n[data-edrv-view] .edrv-pill-ghost { background: #ffffff; color: var(--dsw-alias-label-secondary, #52606d); border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-pill:disabled { opacity: .45; cursor: default; }\n[data-edrv-view] .edrv-diffbar-menu { position: absolute; right: 8px; bottom: calc(100% + 6px); z-index: 45; min-width: 160px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 6px 20px rgba(31,41,51,.16); padding: 4px; display: flex; flex-direction: column; gap: 2px; }\n[data-edrv-view] .edrv-diffmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; }\n[data-edrv-view] .edrv-diffmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffmenu-item.danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-diffmenu-sep { height: 1px; margin: 2px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n/* 编辑区 / Tab 右键菜单(添加文件/选中内容到对话) */\n[data-edrv-view] .edrv-ctxmenu { position: fixed; z-index: 71; min-width: 200px; max-width: 320px; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 8px 26px rgba(31,41,51,.2); padding: 4px; display: flex; flex-direction: column; gap: 1px; }\n[data-edrv-view] .edrv-ctxmenu-item { display: flex; align-items: center; gap: 8px; font-size: 12px; line-height: 18px; padding: 7px 10px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary, #1f2933); cursor: pointer; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-ctxmenu-item:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-ctxmenu-item.edrv-ctxmenu-danger { color: var(--dsw-alias-state-error-primary, #d9534f); }\n[data-edrv-view] .edrv-ctxmenu-sep { height: 1px; margin: 3px 4px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffbar-body { max-height: 130px; max-width: min(560px, calc(100vw - 40px)); overflow: auto; padding: 4px 8px 8px; display: flex; flex-direction: column; gap: 4px; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-diffrow { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 6px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-diffrow:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); }\n[data-edrv-view] .edrv-diffrow-l { font-size: 11px; color: var(--dsw-alias-label-primary, #1f2933); min-width: 74px; font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-o { font-size: 11px; color: var(--dsw-alias-state-error-primary, #d9534f); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-n { font-size: 11px; color: var(--dsw-alias-state-success-primary, #0f9d58); font-family: var(--ds-font-family-code, ui-monospace, monospace); }\n[data-edrv-view] .edrv-diffrow-tag { font-size: 11px; color: var(--dsw-alias-label-tertiary, #9aa5b1); }\n[data-edrv-view] .edrv-diffrow-stale { border-color: rgba(217,119,6,.5); cursor: default; }\n[data-edrv-view] .edrv-diffbox-others { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 4px 2px 0; border-top: 1px solid var(--dsw-alias-border-l1, #e0e6e8); margin-top: 2px; }\n[data-edrv-view] .edrv-diffrow-file { font-size: 11px; padding: 2px 10px; border: 1px solid var(--dsw-alias-border-l1, #e0e6e8); border-radius: 999px; background: var(--dsw-alias-bg-layer-2, #f0f4f4); color: var(--dsw-alias-label-secondary, #52606d); cursor: pointer; white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis; }\n[data-edrv-view] .edrv-diffrow-file:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15,157,88,.08)); color: var(--dsw-alias-label-primary, #1f2933); }\n/* 编辑区 hover 差异块的 Keep/Undo 浮层 */\n[data-edrv-view] .edrv-hoveract { position: absolute; z-index: 30; display: flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 8px; background: var(--dsw-alias-bg-overlay, #ffffff); border: 1px solid var(--dsw-alias-border-l2, #cbd2d9); box-shadow: 0 4px 14px rgba(31,41,51,.14); }\n[data-edrv-view] .edrv-launch { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 40; border-radius: 10px; background: var(--dsw-alias-bg-overlay, #1c1c1c); border: 1px solid var(--dsw-alias-border-l2, #555); box-shadow: 0 6px 24px rgba(0,0,0,.5); display: flex; flex-direction: column; max-height: 60%; overflow: hidden; }\n[data-edrv-view] .edrv-launch-head { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--dsw-alias-border-l1, #333); }\n[data-edrv-view] .edrv-launch-tab { font-size: 12px; padding: 3px 12px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-secondary, #aaa); cursor: pointer; }\n[data-edrv-view] .edrv-launch-tab.on { background: var(--dsw-alias-bg-layer-2, transparent); color: var(--dsw-alias-label-primary, #eee); font-weight: 600; }\n[data-edrv-view] .edrv-launch-body { flex: 1; min-height: 0; overflow: auto; padding: 6px 8px; display: flex; flex-direction: column; gap: 4px; }\n[data-edrv-view] .edrv-launch-row { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border: 1px solid var(--dsw-alias-border-l1, #333); border-radius: 6px; cursor: pointer; flex-wrap: wrap; }\n[data-edrv-view] .edrv-launch-row:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(255,255,255,.06)); }\n[data-edrv-view] .edrv-launch-path { flex: 1; min-width: 0; font-size: 12px; color: var(--dsw-alias-label-primary, #eee); word-break: break-all; }\n[data-edrv-view] .edrv-launch-cnt { font-size: 11px; color: var(--dsw-alias-label-tertiary, #888); white-space: nowrap; }\n[data-edrv-view] .edrv-launch-arch { display: flex; flex-direction: column; gap: 6px; }\n[data-edrv-view] .monaco-editor { overflow: hidden !important; }\n[data-edrv-view] .monaco-editor .sticky-widget { z-index: 30 !important; background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-content,\n[data-edrv-view] .monaco-editor .sticky-widget .sticky-line-number { background: var(--dsw-alias-bg-base, #f8f8f8) !important; }\n[data-edrv-view] .monaco-editor, [data-edrv-view] .monaco-editor .margin, [data-edrv-view] .monaco-editor-background { background: transparent !important; }\n[data-edrv-view] .monaco-editor .scrollbar .slider { background: rgba(128,128,128,.3) !important; }\n[data-edrv-view] .edrv-loading { gap: 8px; padding: 20px; }\n[data-edrv-view] .edrv-loading-title { color: var(--dsw-alias-label-primary, #1f2933); font-size: 13px; }\n[data-edrv-view] .edrv-progress { width: min(360px, 72%); height: 6px; overflow: hidden; border-radius: 999px; background: var(--dsw-alias-border-l1, #e0e6e8); }\n[data-edrv-view] .edrv-progress-value { height: 100%; border-radius: inherit; background: var(--dsw-alias-brand-primary, #0f9d58); transition: width .24s ease; }\n[data-edrv-view] .edrv-loading-percent { color: var(--dsw-alias-label-tertiary, #9aa5b1); font-size: 11px; font-variant-numeric: tabular-nums; }\n@media (prefers-reduced-motion: reduce) {\n [data-edrv-view] .edrv-progress-value { transition: none; }\n}\n\n";
|
|
33
33
|
const tagId$1 = "dsh-vscode-mode/editor.css";
|
|
34
34
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
35
35
|
const tag = document.createElement("style");
|
|
@@ -1304,6 +1304,7 @@ window.__ModuleLoader__.load({
|
|
|
1304
1304
|
function EditorView(props) {
|
|
1305
1305
|
const sessionId = props?.sessionId;
|
|
1306
1306
|
const schedule = props.schedule;
|
|
1307
|
+
const addToConversation = props.addToConversation;
|
|
1307
1308
|
const [monaco, setMonaco] = react.default.useState(null);
|
|
1308
1309
|
const [monacoErr, setMonacoErr] = react.default.useState(null);
|
|
1309
1310
|
const [records, setRecords] = react.default.useState({});
|
|
@@ -1326,6 +1327,7 @@ window.__ModuleLoader__.load({
|
|
|
1326
1327
|
const [hoverAct, setHoverAct] = react.default.useState(null);
|
|
1327
1328
|
const [diffIdx, setDiffIdx] = react.default.useState(0);
|
|
1328
1329
|
const [fileIdx, setFileIdx] = react.default.useState(0);
|
|
1330
|
+
const [tabMenu, setTabMenu] = react.default.useState(null);
|
|
1329
1331
|
const editorRef = react.default.useRef(null);
|
|
1330
1332
|
const monacoRef = react.default.useRef(null);
|
|
1331
1333
|
const modelsRef = react.default.useRef(/* @__PURE__ */ new Map());
|
|
@@ -1343,6 +1345,7 @@ window.__ModuleLoader__.load({
|
|
|
1343
1345
|
const hoverEditorRef = react.default.useRef(false);
|
|
1344
1346
|
const hoverPanelRef = react.default.useRef(false);
|
|
1345
1347
|
const batchBusyRef = react.default.useRef(false);
|
|
1348
|
+
const menuHandlersRef = react.default.useRef(null);
|
|
1346
1349
|
const diffRendererRef = react.default.useRef(null);
|
|
1347
1350
|
if (!diffRendererRef.current) diffRendererRef.current = createDiffRenderer((sid, t) => dbg(sid, t));
|
|
1348
1351
|
const currentRecords = react.default.useMemo(() => {
|
|
@@ -1381,9 +1384,12 @@ window.__ModuleLoader__.load({
|
|
|
1381
1384
|
return next;
|
|
1382
1385
|
});
|
|
1383
1386
|
};
|
|
1384
|
-
const refreshRecords = () => {
|
|
1387
|
+
const refreshRecords = (skipStale) => {
|
|
1385
1388
|
if (!sessionId) return;
|
|
1386
|
-
rpc("edrv.list", {
|
|
1389
|
+
rpc("edrv.list", {
|
|
1390
|
+
sessionId,
|
|
1391
|
+
...skipStale ? { skipStale: true } : {}
|
|
1392
|
+
}).then((res) => {
|
|
1387
1393
|
if (!res || !res.ok || !Array.isArray(res.records)) return;
|
|
1388
1394
|
const map = {};
|
|
1389
1395
|
for (const r of res.records) {
|
|
@@ -1488,6 +1494,14 @@ window.__ModuleLoader__.load({
|
|
|
1488
1494
|
setStatus("加载中…");
|
|
1489
1495
|
loadContent(active, sessionId);
|
|
1490
1496
|
}, [active, sessionId]);
|
|
1497
|
+
react.default.useEffect(() => {
|
|
1498
|
+
if (!tabMenu) return;
|
|
1499
|
+
const onKey = (e) => {
|
|
1500
|
+
if (e.key === "Escape") dismissMenus();
|
|
1501
|
+
};
|
|
1502
|
+
window.addEventListener("keydown", onKey, true);
|
|
1503
|
+
return () => window.removeEventListener("keydown", onKey, true);
|
|
1504
|
+
}, [tabMenu]);
|
|
1491
1505
|
react.default.useEffect(() => {
|
|
1492
1506
|
if (monaco || monacoErr) return;
|
|
1493
1507
|
let alive = true;
|
|
@@ -1648,6 +1662,46 @@ window.__ModuleLoader__.load({
|
|
|
1648
1662
|
ed.onDidChangeCursorPosition((e) => {
|
|
1649
1663
|
setCursor("Ln " + e.position.lineNumber + ", Col " + e.position.column);
|
|
1650
1664
|
});
|
|
1665
|
+
const menuHandlers = () => menuHandlersRef.current;
|
|
1666
|
+
const pathOf = (edx) => {
|
|
1667
|
+
const uriPath = (edx?.getModel?.())?.uri?.path;
|
|
1668
|
+
return uriPath ? decodeURIComponent(String(uriPath).replace(/^\//, "")) : null;
|
|
1669
|
+
};
|
|
1670
|
+
const selectionOf = (edx) => {
|
|
1671
|
+
const s = edx?.getSelection?.();
|
|
1672
|
+
if (!s) return null;
|
|
1673
|
+
if (s.startLineNumber === s.endLineNumber && s.startColumn === s.endColumn) return null;
|
|
1674
|
+
return {
|
|
1675
|
+
startLine: s.startLineNumber,
|
|
1676
|
+
endLine: s.endLineNumber
|
|
1677
|
+
};
|
|
1678
|
+
};
|
|
1679
|
+
const selKey = ed.createContextKey("edrvSelection", false);
|
|
1680
|
+
ed.onDidChangeCursorSelection((e) => {
|
|
1681
|
+
const s = e?.selection;
|
|
1682
|
+
selKey.set(!!(s && (s.startLineNumber !== s.endLineNumber || s.startColumn !== s.endColumn)));
|
|
1683
|
+
});
|
|
1684
|
+
ed.addAction({
|
|
1685
|
+
id: "edrv.addFileRef",
|
|
1686
|
+
label: "添加文件到对话",
|
|
1687
|
+
contextMenuGroupId: "1_edrv",
|
|
1688
|
+
precondition: "editorTextFocus",
|
|
1689
|
+
run: (edx) => menuHandlers()?.addRefToChat(pathOf(edx))
|
|
1690
|
+
});
|
|
1691
|
+
ed.addAction({
|
|
1692
|
+
id: "edrv.addSelectionRef",
|
|
1693
|
+
label: "添加选中内容为引用",
|
|
1694
|
+
contextMenuGroupId: "1_edrv",
|
|
1695
|
+
precondition: "edrvSelection",
|
|
1696
|
+
run: (edx) => {
|
|
1697
|
+
const s = selectionOf(edx);
|
|
1698
|
+
const p = pathOf(edx);
|
|
1699
|
+
if (s && p) menuHandlers()?.addRefToChat(p, {
|
|
1700
|
+
startLine: s.startLine,
|
|
1701
|
+
endLine: s.endLine
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
});
|
|
1651
1705
|
const hideSoon = () => {
|
|
1652
1706
|
if (hoverEditorRef.current || hoverPanelRef.current || hideTimerRef.current) return;
|
|
1653
1707
|
hideTimerRef.current = setTimeout(() => {
|
|
@@ -1747,10 +1801,10 @@ window.__ModuleLoader__.load({
|
|
|
1747
1801
|
setFileIdx(next);
|
|
1748
1802
|
openFile(sum.pendingFiles[next].path, true);
|
|
1749
1803
|
};
|
|
1750
|
-
const reloadFile = () => {
|
|
1804
|
+
const reloadFile = (skipStale) => {
|
|
1751
1805
|
if (!active) return;
|
|
1752
1806
|
loadContent(active, sessionId);
|
|
1753
|
-
refreshRecords();
|
|
1807
|
+
refreshRecords(skipStale === true);
|
|
1754
1808
|
};
|
|
1755
1809
|
/**
|
|
1756
1810
|
* 关闭当前差异浮窗并清理 hover 锚点。
|
|
@@ -1798,11 +1852,77 @@ window.__ModuleLoader__.load({
|
|
|
1798
1852
|
return false;
|
|
1799
1853
|
});
|
|
1800
1854
|
};
|
|
1855
|
+
/**
|
|
1856
|
+
* 批量采纳/不采纳:一次 RPC 处理多个差异(Keep 整文件 / Keep All / Undo All)。
|
|
1857
|
+
* 单次 setRecords 合并全部结果,避免逐条往返读写整个 sidecar。
|
|
1858
|
+
* @author ddj 2026年08月25号
|
|
1859
|
+
* @param items 决策项数组(callId/scope/hunkIndex/decision)
|
|
1860
|
+
* @returns Promise<{ok:number; fail:number}> 成功/失败计数
|
|
1861
|
+
*/
|
|
1862
|
+
const actMany = (items) => {
|
|
1863
|
+
if (!items.length) return Promise.resolve({
|
|
1864
|
+
ok: 0,
|
|
1865
|
+
fail: 0
|
|
1866
|
+
});
|
|
1867
|
+
return rpc("edrv.decideBatch", {
|
|
1868
|
+
sessionId,
|
|
1869
|
+
items
|
|
1870
|
+
}).then((res) => {
|
|
1871
|
+
if (!res || !res.ok || !Array.isArray(res.results)) {
|
|
1872
|
+
setError(res?.error ? String(res.error) : "批量处理失败");
|
|
1873
|
+
return {
|
|
1874
|
+
ok: 0,
|
|
1875
|
+
fail: items.length
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
let ok = 0;
|
|
1879
|
+
let fail = 0;
|
|
1880
|
+
const next = {};
|
|
1881
|
+
for (const item of res.results) if (item && item.ok) {
|
|
1882
|
+
ok++;
|
|
1883
|
+
if (item.record) next[item.callId] = item.record;
|
|
1884
|
+
} else fail++;
|
|
1885
|
+
setRecords((prev) => Object.assign({}, prev, next));
|
|
1886
|
+
return {
|
|
1887
|
+
ok,
|
|
1888
|
+
fail
|
|
1889
|
+
};
|
|
1890
|
+
}).catch((e) => {
|
|
1891
|
+
setError("批量处理异常:" + String(e));
|
|
1892
|
+
return {
|
|
1893
|
+
ok: 0,
|
|
1894
|
+
fail: items.length
|
|
1895
|
+
};
|
|
1896
|
+
});
|
|
1897
|
+
};
|
|
1898
|
+
/**
|
|
1899
|
+
* 决策项构造(与单条 actHunk 的 scope 语义一致:create 记录走 call 作用域)。
|
|
1900
|
+
* @author ddj 2026年08月25号
|
|
1901
|
+
* @param r 差异区域/待处理项(callId/idx/create)
|
|
1902
|
+
* @param reject true=不采纳
|
|
1903
|
+
* @returns decideBatch items 元素
|
|
1904
|
+
*/
|
|
1905
|
+
const itemOf = (r, reject) => ({
|
|
1906
|
+
callId: r.callId,
|
|
1907
|
+
scope: r.create ? "call" : "hunk",
|
|
1908
|
+
hunkIndex: r.idx,
|
|
1909
|
+
decision: reject ? "rejected" : "accepted"
|
|
1910
|
+
});
|
|
1801
1911
|
const acceptFile = () => {
|
|
1802
|
-
|
|
1912
|
+
actMany(pendingRegions.map((r) => itemOf(r, false))).then(({ ok, fail }) => {
|
|
1913
|
+
reloadFile(true);
|
|
1914
|
+
emitRefresh();
|
|
1915
|
+
setStatus("已采纳 " + ok + " 处差异" + (fail ? "," + fail + " 处失败" : ""));
|
|
1916
|
+
if (fail) setError(fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
|
|
1917
|
+
});
|
|
1803
1918
|
};
|
|
1804
1919
|
const undoFile = () => {
|
|
1805
|
-
|
|
1920
|
+
actMany([...pendingRegions].reverse().map((r) => itemOf(r, true))).then(({ ok, fail }) => {
|
|
1921
|
+
reloadFile(true);
|
|
1922
|
+
emitRefresh();
|
|
1923
|
+
setStatus("已不采纳 " + ok + " 处差异" + (fail ? "," + fail + " 处失败" : ""));
|
|
1924
|
+
if (fail) setError(fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
|
|
1925
|
+
});
|
|
1806
1926
|
};
|
|
1807
1927
|
const allPending = react.default.useMemo(() => {
|
|
1808
1928
|
const out = [];
|
|
@@ -1820,7 +1940,7 @@ window.__ModuleLoader__.load({
|
|
|
1820
1940
|
return out;
|
|
1821
1941
|
}, [records]);
|
|
1822
1942
|
/**
|
|
1823
|
-
* 批量处理所有差异文件:采纳全部 / 不采纳全部。不采纳按 at
|
|
1943
|
+
* 批量处理所有差异文件:采纳全部 / 不采纳全部。不采纳按 at 降序(新改先回滚)排序后一次 RPC。
|
|
1824
1944
|
* @author ddj 2026年08月20号
|
|
1825
1945
|
* @param reject true=全部不采纳(回滚),false=全部采纳
|
|
1826
1946
|
*/
|
|
@@ -1828,17 +1948,15 @@ window.__ModuleLoader__.load({
|
|
|
1828
1948
|
if (batchBusyRef.current || !allPending.length) return;
|
|
1829
1949
|
batchBusyRef.current = true;
|
|
1830
1950
|
const list = reject ? [...allPending].sort((a, b) => a.at < b.at ? 1 : a.at > b.at ? -1 : b.idx - a.idx) : allPending;
|
|
1831
|
-
|
|
1832
|
-
const run = async () => {
|
|
1833
|
-
for (const r of list) if (await actHunk(r, reject, true)) ok++;
|
|
1834
|
-
else fail++;
|
|
1951
|
+
actMany(list.map((r) => itemOf(r, reject))).then(({ ok, fail }) => {
|
|
1835
1952
|
batchBusyRef.current = false;
|
|
1836
|
-
reloadFile();
|
|
1953
|
+
reloadFile(true);
|
|
1837
1954
|
emitRefresh();
|
|
1838
1955
|
setStatus((reject ? "已不采纳 " : "已采纳 ") + ok + " 处差异" + (fail ? "," + fail + " 处失败" : ""));
|
|
1839
1956
|
if (fail) setError(fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
|
|
1840
|
-
}
|
|
1841
|
-
|
|
1957
|
+
}).catch(() => {
|
|
1958
|
+
batchBusyRef.current = false;
|
|
1959
|
+
});
|
|
1842
1960
|
};
|
|
1843
1961
|
const acceptAllFiles = () => actAllPending(false);
|
|
1844
1962
|
const undoAllFiles = () => actAllPending(true);
|
|
@@ -1856,6 +1974,33 @@ window.__ModuleLoader__.load({
|
|
|
1856
1974
|
} else setError(res?.error ? String(res.error) : "回滚失败");
|
|
1857
1975
|
}).catch((e) => setError("回滚异常:" + String(e)));
|
|
1858
1976
|
};
|
|
1977
|
+
/**
|
|
1978
|
+
* 关闭 Tab 右键菜单。
|
|
1979
|
+
* @author ddj 2026年08月25号
|
|
1980
|
+
*/
|
|
1981
|
+
const dismissMenus = () => {
|
|
1982
|
+
setTabMenu(null);
|
|
1983
|
+
};
|
|
1984
|
+
/** 把「添加到对话」返回状态映射为状态栏文案。
|
|
1985
|
+
* @author ddj 2026年08月25号 */
|
|
1986
|
+
const statusOfAdd = (outcome, okText) => {
|
|
1987
|
+
if (outcome === "ok") return okText;
|
|
1988
|
+
if (outcome === "busy") return okText + "(输入框忙,已降级纯文本)";
|
|
1989
|
+
return "无法添加到对话(无会话或输入框不可用)";
|
|
1990
|
+
};
|
|
1991
|
+
/** 添加文件/选中区引用到对话(异步,状态栏反馈)。 */
|
|
1992
|
+
const addRefToChat = (path, range) => {
|
|
1993
|
+
if (!path) {
|
|
1994
|
+
setStatus("无活动文件");
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1997
|
+
if (!addToConversation) {
|
|
1998
|
+
setStatus("添加到对话不可用");
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
2001
|
+
addToConversation.appendReference(sessionId, path, range).then((o) => setStatus(statusOfAdd(o, "已添加文件引用")));
|
|
2002
|
+
};
|
|
2003
|
+
menuHandlersRef.current = { addRefToChat };
|
|
1859
2004
|
const openFile = (path, focusDiff) => {
|
|
1860
2005
|
if (!path) return;
|
|
1861
2006
|
addTab(path, true);
|
|
@@ -1902,6 +2047,15 @@ window.__ModuleLoader__.load({
|
|
|
1902
2047
|
flushSave();
|
|
1903
2048
|
setActive(t.path);
|
|
1904
2049
|
}
|
|
2050
|
+
},
|
|
2051
|
+
onContextMenu: (e) => {
|
|
2052
|
+
e.preventDefault();
|
|
2053
|
+
e.stopPropagation();
|
|
2054
|
+
setTabMenu({
|
|
2055
|
+
x: e.clientX,
|
|
2056
|
+
y: e.clientY,
|
|
2057
|
+
path: t.path
|
|
2058
|
+
});
|
|
1905
2059
|
}
|
|
1906
2060
|
}, react.default.createElement("span", { style: {
|
|
1907
2061
|
overflow: "hidden",
|
|
@@ -2100,6 +2254,42 @@ window.__ModuleLoader__.load({
|
|
|
2100
2254
|
},
|
|
2101
2255
|
onRefresh: reloadFile
|
|
2102
2256
|
}) : null;
|
|
2257
|
+
/**
|
|
2258
|
+
* 计算右键菜单固定定位(clamp 防越出视口)。
|
|
2259
|
+
* @author ddj 2026年08月25号
|
|
2260
|
+
*/
|
|
2261
|
+
const menuPos = (x, y) => ({
|
|
2262
|
+
left: Math.max(4, Math.min(x, (window.innerWidth || 800) - 224)),
|
|
2263
|
+
top: Math.max(4, Math.min(y, (window.innerHeight || 600) - 176))
|
|
2264
|
+
});
|
|
2265
|
+
const menuBackdrop = tabMenu ? react.default.createElement("div", {
|
|
2266
|
+
style: {
|
|
2267
|
+
position: "fixed",
|
|
2268
|
+
inset: 0,
|
|
2269
|
+
zIndex: 70
|
|
2270
|
+
},
|
|
2271
|
+
onClick: dismissMenus,
|
|
2272
|
+
onContextMenu: (e) => {
|
|
2273
|
+
e.preventDefault();
|
|
2274
|
+
dismissMenus();
|
|
2275
|
+
}
|
|
2276
|
+
}) : null;
|
|
2277
|
+
const tabMenuEl = tabMenu ? react.default.createElement("div", {
|
|
2278
|
+
className: "edrv-ctxmenu",
|
|
2279
|
+
style: menuPos(tabMenu.x, tabMenu.y)
|
|
2280
|
+
}, react.default.createElement("button", {
|
|
2281
|
+
className: "edrv-ctxmenu-item",
|
|
2282
|
+
onClick: () => {
|
|
2283
|
+
addRefToChat(tabMenu.path);
|
|
2284
|
+
dismissMenus();
|
|
2285
|
+
}
|
|
2286
|
+
}, "添加文件到对话"), react.default.createElement("div", { className: "edrv-ctxmenu-sep" }), react.default.createElement("button", {
|
|
2287
|
+
className: "edrv-ctxmenu-item edrv-ctxmenu-danger",
|
|
2288
|
+
onClick: () => {
|
|
2289
|
+
closeTab(tabMenu.path);
|
|
2290
|
+
dismissMenus();
|
|
2291
|
+
}
|
|
2292
|
+
}, "关闭标签页")) : null;
|
|
2103
2293
|
return react.default.createElement("div", {
|
|
2104
2294
|
"data-edrv-view": "1",
|
|
2105
2295
|
style: {
|
|
@@ -2116,7 +2306,7 @@ window.__ModuleLoader__.load({
|
|
|
2116
2306
|
minHeight: 0,
|
|
2117
2307
|
display: "flex",
|
|
2118
2308
|
flexDirection: "column"
|
|
2119
|
-
} }, body, hoverEl, overlay), statusBar);
|
|
2309
|
+
} }, body, hoverEl, overlay), menuBackdrop, tabMenuEl, statusBar);
|
|
2120
2310
|
}
|
|
2121
2311
|
//#endregion
|
|
2122
2312
|
//#region src/client/ui/DiffBadge.ts
|
|
@@ -2200,7 +2390,7 @@ window.__ModuleLoader__.load({
|
|
|
2200
2390
|
}
|
|
2201
2391
|
//#endregion
|
|
2202
2392
|
//#region \0dsh-css:/home/runner/work/DSH_VsCodeMode/DSH_VsCodeMode/src/client/styles/mcp.css.mjs
|
|
2203
|
-
const css = "/* dsh-vscode-mode MCP 管理界面样式。\n 全部使用 DSH 真实主题变量(--dsw-alias-*),不再用不存在的 fg-* 变量。 */\n.vsm-mcp-page{display:flex;flex-direction:column;gap:18px;width:100%;max-width:920px;box-sizing:border-box;color:var(--dsw-alias-label-primary,#e6e6e6);padding-bottom:32px}\n\n/* 顶部:标题 + 副标题 + 添加按钮 */\n.vsm-mcp-header{display:flex;align-items:flex-start;justify-content:space-between;gap:20px}\n.vsm-mcp-header h2{margin:0 0 4px;font-size:20px;font-weight:600;line-height:1.35;color:var(--dsw-alias-label-primary,#e6e6e6)}\n.vsm-mcp-header p{margin:0;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:13px;line-height:1.5}\n.vsm-primary{border:0;border-radius:6px;padding:8px 16px;background:var(--dsw-alias-button-primary-fill,#6d55ff);color:var(--dsw-alias-button-contrast-fill,#fff);font-size:13px;font-weight:500;cursor:pointer;white-space:nowrap}\n.vsm-primary:hover{background:var(--dsw-alias-button-primary-hover,#5a46e6)}\n.vsm-primary:disabled{opacity:.55;cursor:default}\n\n/* 子 Tab:我的 MCP / MCP 市场 */\n.vsm-mcp-tabs{display:flex;gap:24px;border-bottom:1px solid var(--dsw-alias-border-l2,#3a3a3a)}\n.vsm-mcp-tabs button{border:0;background:none;color:var(--dsw-alias-label-tertiary,#9aa5b1);padding:9px 2px 11px;cursor:pointer;font-size:14px;position:relative}\n.vsm-mcp-tabs button:hover{color:var(--dsw-alias-label-secondary,#c8c8c8)}\n.vsm-mcp-tabs button.active{color:var(--dsw-alias-label-primary,#fff);font-weight:500}\n.vsm-mcp-tabs button.active::after{content:\"\";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--dsw-alias-brand-primary,#6d55ff);border-radius:2px}\n\n/* 通用设置 */\n.vsm-general-page{display:flex;flex-direction:column;gap:10px;max-width:720px}\n.vsm-general-page h2{margin:0;font-size:20px;color:var(--dsw-alias-label-primary,#e6e6e6)}\n.vsm-general-page p{margin:0 0 8px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:13px}\n.vsm-general-row{display:flex;align-items:center;justify-content:space-between;gap:20px;padding:14px 0;border-bottom:1px solid var(--dsw-alias-border-l1,#333);color:var(--dsw-alias-label-primary,#eee);font-size:14px}\n.vsm-general-row select{min-width:220px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;background:var(--dsw-alias-bg-layer-1,#2b2b2b);color:var(--dsw-alias-label-primary,#eee);font:inherit}\n.vsm-general-row small{color:var(--dsw-alias-label-tertiary,#9aa5b1)}\n\n/* 服务卡片 */\n.vsm-mcp-card{border:1px solid var(--dsw-alias-border-l2,#3a3a3a);border-radius:10px;padding:14px 16px;margin-bottom:10px;background:var(--dsw-alias-bg-layer-2,transparent);transition:border-color .15s}\n.vsm-mcp-card:hover{border-color:var(--dsw-alias-border-l3,#555)}\n.vsm-mcp-card-head{display:flex;justify-content:space-between;align-items:center;gap:12px}\n.vsm-mcp-title{display:flex;align-items:center;gap:9px;font-weight:600;font-size:14px;color:var(--dsw-alias-label-primary,#e6e6e6);min-width:0}\n.vsm-mcp-source{font-size:11px;font-weight:400;padding:2px 7px;border-radius:4px;background:var(--dsw-alias-bg-mask-2,#ffffff22);color:var(--dsw-alias-label-tertiary,#9aa5b1);flex-shrink:0}\n.vsm-mcp-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;background:var(--dsw-alias-state-error-primary,#e05252)}\n.vsm-mcp-dot.connected{background:var(--dsw-alias-state-success-primary,#38bd75)}\n.vsm-mcp-dot.connecting{background:var(--dsw-alias-state-warn-primary,#e5b93f)}\n.vsm-mcp-dot.disabled{background:var(--dsw-alias-label-tertiary,#9aa5b1)}\n.vsm-mcp-actions{display:flex;align-items:center;gap:4px;flex-shrink:0}\n.vsm-mcp-actions button{border:0;background:none;color:var(--dsw-alias-label-tertiary,#9aa5b1);cursor:pointer;font-size:15px;width:28px;height:28px;border-radius:6px;line-height:1}\n.vsm-mcp-actions button:hover{color:var(--dsw-alias-label-primary,#fff);background:var(--dsw-alias-interactive-bg-hover,#ffffff14)}\n.vsm-mcp-actions button.vsm-danger:hover{color:var(--dsw-alias-state-error-primary,#f07878);background:var(--dsw-alias-interactive-bg-hover-danger,#ff000014)}\n.vsm-switch{font-size:14px !important}\n.vsm-switch.on{color:var(--dsw-alias-state-success-primary,#38bd75)}\n.vsm-mcp-meta{font-size:12px;color:var(--dsw-alias-label-tertiary,#9aa5b1);margin:9px 0}\n.vsm-mcp-error{color:var(--dsw-alias-state-error-primary,#f07878);font-size:12px;margin:8px 0}\n.vsm-mcp-banner{padding:9px 12px;border:1px solid var(--dsw-alias-state-error-secondary,#d9534f55);border-radius:6px;background:var(--dsw-alias-state-error-secondary,#d9534f1a);margin-bottom:10px}\n\n/* 工具 chips */\n.vsm-mcp-tools{display:flex;flex-wrap:wrap;gap:6px}\n.vsm-mcp-chip{font:12px var(--ds-font-family-code,ui-monospace,monospace);padding:4px 8px;border-radius:5px;background:var(--dsw-alias-bg-mask-2,#ffffff14);color:var(--dsw-alias-label-secondary,#c8c8c8);border:1px solid var(--dsw-alias-border-l1,#333)}\n\n/* 空态 / 加载态 */\n.vsm-mcp-empty{text-align:center;padding:56px 20px;color:var(--dsw-alias-label-tertiary,#9aa5b1);border:1px dashed var(--dsw-alias-border-l2,#3a3a3a);border-radius:8px;font-size:13px}\n\n/* 项目搜索下拉框 */\n.vsm-project-picker{position:relative;width:100%;z-index:4}\n.vsm-project-picker-trigger{width:100%;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,#3a3a3a);border-radius:8px;background:var(--dsw-alias-bg-layer-1,transparent);color:var(--dsw-alias-label-primary,#e6e6e6);cursor:pointer;text-align:left}\n.vsm-project-picker-trigger:hover{border-color:var(--dsw-alias-brand-primary,#6d55ff)}\n.vsm-project-picker-label{display:flex;flex-direction:column;min-width:0;font-size:13px;font-weight:500}\n.vsm-project-picker-label small{margin-top:3px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font:11px var(--ds-font-family-code,ui-monospace,monospace);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.vsm-project-picker-arrow{color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:16px}\n.vsm-project-picker-menu{position:absolute;top:calc(100% + 6px);left:0;right:0;padding:8px;border:1px solid var(--dsw-alias-border-l2,#3a3a3a);border-radius:9px;background:var(--dsw-alias-bg-overlay,#202020);box-shadow:0 12px 36px #0008}\n.vsm-project-picker-search{width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;background:var(--dsw-alias-bg-layer-1,#2b2b2b);color:var(--dsw-alias-label-primary,#eee);outline:none}\n.vsm-project-picker-search:focus{border-color:var(--dsw-alias-brand-primary,#6d55ff)}\n.vsm-project-picker-options{max-height:260px;overflow:auto;margin-top:6px}\n.vsm-project-option{display:flex;width:100%;flex-direction:column;gap:3px;padding:8px 9px;border:0;border-radius:6px;background:none;color:var(--dsw-alias-label-primary,#eee);cursor:pointer;text-align:left}\n.vsm-project-option:hover,.vsm-project-option.highlight{background:var(--dsw-alias-interactive-bg-hover,#ffffff14)}\n.vsm-project-option.selected{color:var(--dsw-alias-brand-primary,#6d55ff)}\n.vsm-project-option small{overflow:hidden;color:var(--dsw-alias-label-tertiary,#9aa5b1);font:11px var(--ds-font-family-code,ui-monospace,monospace);text-overflow:ellipsis;white-space:nowrap}\n.vsm-project-picker-empty{padding:18px 8px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:12px;text-align:center}\n\n/* 项目级 MCP 分组 */\n.vsm-project{border:1px solid var(--dsw-alias-border-l2,#3a3a3a);border-radius:12px;margin-bottom:14px;overflow:hidden;background:var(--dsw-alias-bg-layer-1,transparent)}\n.vsm-project-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l1,#333);background:var(--dsw-alias-bg-mask-1,#ffffff0a)}\n.vsm-project-title{display:flex;align-items:center;gap:10px;min-width:0}\n.vsm-project-icon{color:var(--dsw-alias-brand-primary,#6d55ff);font-size:15px;flex-shrink:0}\n.vsm-project-name{font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary,#e6e6e6);display:block}\n.vsm-project-path{font-size:11px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-family:var(--ds-font-family-code,ui-monospace,monospace);display:block;margin-top:2px;word-break:break-all}\n.vsm-primary.vsm-small{padding:5px 12px;font-size:12px}\n.vsm-project-empty{text-align:center;padding:26px 16px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:12px}\n.vsm-project .vsm-mcp-card{border:0;border-radius:0;margin:0;border-bottom:1px solid var(--dsw-alias-border-l1,#333);background:transparent}\n.vsm-project .vsm-mcp-card:last-child{border-bottom:0}\n.vsm-project .vsm-mcp-banner{border-radius:0;margin:0}\n\n/* 新增 MCP 弹窗 */\n.vsm-mcp-modal{position:fixed;inset:0;background:var(--dsw-alias-bg-mask-drop,#000000aa);display:flex;align-items:center;justify-content:center;z-index:50}\n.vsm-mcp-dialog{width:min(560px,calc(100vw - 40px));max-height:88vh;overflow:auto;padding:22px 24px;border-radius:12px;background:var(--dsw-alias-bg-overlay,#202020);border:1px solid var(--dsw-alias-border-l2,#444);box-shadow:0 16px 60px #000c;color:var(--dsw-alias-label-primary,#e6e6e6)}\n.vsm-mcp-dialog h3{margin:0 0 14px;font-size:16px;font-weight:600}\n.vsm-mcp-dialog label{display:flex;flex-direction:column;gap:6px;margin:12px 0;font-size:12px;color:var(--dsw-alias-label-secondary,#aaa)}\n.vsm-mcp-dialog input,.vsm-mcp-dialog select,.vsm-mcp-dialog textarea{font:inherit;color:var(--dsw-alias-label-primary,#eee);background:var(--dsw-alias-bg-layer-1,#2b2b2b);border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;padding:8px 10px}\n.vsm-mcp-dialog input:focus,.vsm-mcp-dialog select:focus,.vsm-mcp-dialog textarea:focus{outline:none;border-color:var(--dsw-alias-brand-primary,#6d55ff)}\n.vsm-mcp-dialog textarea{min-height:64px;resize:vertical;font-family:var(--ds-font-family-code,ui-monospace,monospace)}\n.vsm-mcp-dialog-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}\n.vsm-mcp-dialog-actions button{padding:8px 14px;border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;background:none;color:var(--dsw-alias-label-primary,#eee);cursor:pointer;font-size:13px}\n.vsm-mcp-dialog-actions button:hover{background:var(--dsw-alias-interactive-bg-hover,#ffffff14)}\n\n/* 兼容性小节 */\n.vsm-compat-h3{margin:16px 0 2px;font-size:14px;font-weight:600;color:var(--dsw-alias-label-secondary,#c8c8c8)}\n.vsm-compat-item{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding:10px 0;border-bottom:1px solid var(--dsw-alias-border-l1,#333);font-size:13px;color:var(--dsw-alias-label-primary,#eee)}\n.vsm-compat-item.ok .vsm-compat-name::before{content:\"● \";color:var(--dsw-alias-state-success-primary,#38bd75)}\n.vsm-compat-item.warn .vsm-compat-name::before{content:\"● \";color:var(--dsw-alias-state-warn-primary,#e5b93f)}\n.vsm-compat-name{font-weight:500;min-width:0}\n.vsm-compat-note{color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:12px;text-align:right;min-width:0}\n";
|
|
2393
|
+
const css = "/* dsh-vscode-mode MCP 管理界面样式。\n 全部使用 DSH 真实主题变量(--dsw-alias-*),不再用不存在的 fg-* 变量。 */\n.vsm-mcp-page{display:flex;flex-direction:column;gap:18px;width:100%;max-width:920px;box-sizing:border-box;color:var(--dsw-alias-label-primary,#e6e6e6);padding-bottom:32px}\n\n/* 顶部:标题 + 副标题 + 添加按钮 */\n.vsm-mcp-header{display:flex;align-items:flex-start;justify-content:space-between;gap:20px}\n.vsm-mcp-header h2{margin:0 0 4px;font-size:20px;font-weight:600;line-height:1.35;color:var(--dsw-alias-label-primary,#e6e6e6)}\n.vsm-mcp-header p{margin:0;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:13px;line-height:1.5}\n.vsm-primary{border:0;border-radius:6px;padding:8px 16px;background:var(--dsw-alias-button-primary-fill,#6d55ff);color:var(--dsw-alias-button-contrast-fill,#fff);font-size:13px;font-weight:500;cursor:pointer;white-space:nowrap}\n.vsm-primary:hover{background:var(--dsw-alias-button-primary-hover,#5a46e6)}\n.vsm-primary:disabled{opacity:.55;cursor:default}\n\n/* 子 Tab:我的 MCP / MCP 市场 */\n.vsm-mcp-tabs{display:flex;gap:24px;border-bottom:1px solid var(--dsw-alias-border-l2,#3a3a3a)}\n.vsm-mcp-tabs button{border:0;background:none;color:var(--dsw-alias-label-tertiary,#9aa5b1);padding:9px 2px 11px;cursor:pointer;font-size:14px;position:relative}\n.vsm-mcp-tabs button:hover{color:var(--dsw-alias-label-secondary,#c8c8c8)}\n.vsm-mcp-tabs button.active{color:var(--dsw-alias-label-primary,#fff);font-weight:500}\n.vsm-mcp-tabs button.active::after{content:\"\";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--dsw-alias-brand-primary,#6d55ff);border-radius:2px}\n\n/* 通用设置 */\n.vsm-general-page{display:flex;flex-direction:column;gap:10px;max-width:720px}\n.vsm-general-page h2{margin:0;font-size:20px;color:var(--dsw-alias-label-primary,#e6e6e6)}\n.vsm-general-page p{margin:0 0 8px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:13px}\n.vsm-general-row{display:flex;align-items:center;justify-content:space-between;gap:20px;padding:14px 0;border-bottom:1px solid var(--dsw-alias-border-l1,#333);color:var(--dsw-alias-label-primary,#eee);font-size:14px}\n.vsm-general-row select{min-width:220px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;background:var(--dsw-alias-bg-layer-1,#2b2b2b);color:var(--dsw-alias-label-primary,#eee);font:inherit}\n.vsm-general-row small{color:var(--dsw-alias-label-tertiary,#9aa5b1)}\n\n/* 服务卡片 */\n.vsm-mcp-card{border:1px solid var(--dsw-alias-border-l2,#3a3a3a);border-radius:10px;padding:14px 16px;margin-bottom:10px;background:var(--dsw-alias-bg-layer-2,transparent);transition:border-color .15s}\n.vsm-mcp-card:hover{border-color:var(--dsw-alias-border-l3,#555)}\n.vsm-mcp-card-head{display:flex;justify-content:space-between;align-items:center;gap:12px}\n.vsm-mcp-title{display:flex;align-items:center;gap:9px;font-weight:600;font-size:14px;color:var(--dsw-alias-label-primary,#e6e6e6);min-width:0}\n.vsm-mcp-source{font-size:11px;font-weight:400;padding:2px 7px;border-radius:4px;background:var(--dsw-alias-bg-mask-2,#ffffff22);color:var(--dsw-alias-label-tertiary,#9aa5b1);flex-shrink:0}\n.vsm-mcp-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;background:var(--dsw-alias-state-error-primary,#e05252)}\n.vsm-mcp-dot.connected{background:var(--dsw-alias-state-success-primary,#38bd75)}\n.vsm-mcp-dot.connecting{background:var(--dsw-alias-state-warn-primary,#e5b93f)}\n.vsm-mcp-dot.disabled{background:var(--dsw-alias-label-tertiary,#9aa5b1)}\n.vsm-mcp-actions{display:flex;align-items:center;gap:4px;flex-shrink:0}\n.vsm-mcp-actions button{border:0;background:none;color:var(--dsw-alias-label-tertiary,#9aa5b1);cursor:pointer;font-size:15px;width:28px;height:28px;border-radius:6px;line-height:1}\n.vsm-mcp-actions button:hover{color:var(--dsw-alias-label-primary,#fff);background:var(--dsw-alias-interactive-bg-hover,#ffffff14)}\n.vsm-mcp-actions button.vsm-danger:hover{color:var(--dsw-alias-state-error-primary,#f07878);background:var(--dsw-alias-interactive-bg-hover-danger,#ff000014)}\n.vsm-switch{font-size:14px !important}\n.vsm-switch.on{color:var(--dsw-alias-state-success-primary,#38bd75)}\n.vsm-mcp-meta{font-size:12px;color:var(--dsw-alias-label-tertiary,#9aa5b1);margin:9px 0}\n.vsm-mcp-error{color:var(--dsw-alias-state-error-primary,#f07878);font-size:12px;margin:8px 0}\n.vsm-mcp-banner{padding:9px 12px;border:1px solid var(--dsw-alias-state-error-secondary,#d9534f55);border-radius:6px;background:var(--dsw-alias-state-error-secondary,#d9534f1a);margin-bottom:10px}\n\n/* 工具 chips */\n.vsm-mcp-tools{display:flex;flex-wrap:wrap;gap:6px}\n.vsm-mcp-chip{font:12px var(--ds-font-family-code,ui-monospace,monospace);padding:4px 8px;border-radius:5px;background:var(--dsw-alias-bg-mask-2,#ffffff14);color:var(--dsw-alias-label-secondary,#c8c8c8);border:1px solid var(--dsw-alias-border-l1,#333)}\n\n/* 空态 / 加载态 */\n.vsm-mcp-empty{text-align:center;padding:56px 20px;color:var(--dsw-alias-label-tertiary,#9aa5b1);border:1px dashed var(--dsw-alias-border-l2,#3a3a3a);border-radius:8px;font-size:13px}\n\n/* 项目搜索下拉框 */\n.vsm-project-picker{position:relative;width:100%;z-index:4}\n.vsm-project-picker-trigger{width:100%;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,#3a3a3a);border-radius:8px;background:var(--dsw-alias-bg-layer-1,transparent);color:var(--dsw-alias-label-primary,#e6e6e6);cursor:pointer;text-align:left}\n.vsm-project-picker-trigger:hover{border-color:var(--dsw-alias-brand-primary,#6d55ff)}\n.vsm-project-picker-label{display:flex;flex-direction:column;min-width:0;font-size:13px;font-weight:500}\n.vsm-project-picker-label small{margin-top:3px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font:11px var(--ds-font-family-code,ui-monospace,monospace);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.vsm-project-picker-arrow{color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:16px}\n.vsm-project-picker-menu{position:absolute;top:calc(100% + 6px);left:0;right:0;padding:8px;border:1px solid var(--dsw-alias-border-l2,#3a3a3a);border-radius:9px;background:var(--dsw-alias-bg-overlay,#202020);box-shadow:0 12px 36px #0008}\n.vsm-project-picker-search{width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;background:var(--dsw-alias-bg-layer-1,#2b2b2b);color:var(--dsw-alias-label-primary,#eee);outline:none}\n.vsm-project-picker-search:focus{border-color:var(--dsw-alias-brand-primary,#6d55ff)}\n.vsm-project-picker-options{max-height:260px;overflow:auto;margin-top:6px}\n.vsm-project-option{display:flex;width:100%;flex-direction:column;gap:3px;padding:8px 9px;border:0;border-radius:6px;background:none;color:var(--dsw-alias-label-primary,#eee);cursor:pointer;text-align:left}\n.vsm-project-option:hover,.vsm-project-option.highlight{background:var(--dsw-alias-interactive-bg-hover,#ffffff14)}\n.vsm-project-option.selected{color:var(--dsw-alias-brand-primary,#6d55ff)}\n.vsm-project-option small{overflow:hidden;color:var(--dsw-alias-label-tertiary,#9aa5b1);font:11px var(--ds-font-family-code,ui-monospace,monospace);text-overflow:ellipsis;white-space:nowrap}\n.vsm-project-picker-empty{padding:18px 8px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:12px;text-align:center}\n\n/* 项目级 MCP 分组 */\n.vsm-project{border:1px solid var(--dsw-alias-border-l2,#3a3a3a);border-radius:12px;margin-bottom:14px;overflow:hidden;background:var(--dsw-alias-bg-layer-1,transparent)}\n.vsm-project-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border-bottom:1px solid var(--dsw-alias-border-l1,#333);background:var(--dsw-alias-bg-mask-1,#ffffff0a)}\n.vsm-project-title{display:flex;align-items:center;gap:10px;min-width:0}\n.vsm-project-icon{color:var(--dsw-alias-brand-primary,#6d55ff);font-size:15px;flex-shrink:0}\n.vsm-project-name{font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary,#e6e6e6);display:block}\n.vsm-project-path{font-size:11px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-family:var(--ds-font-family-code,ui-monospace,monospace);display:block;margin-top:2px;word-break:break-all}\n.vsm-primary.vsm-small{padding:5px 12px;font-size:12px}\n.vsm-project-empty{text-align:center;padding:26px 16px;color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:12px}\n.vsm-project .vsm-mcp-card{border:0;border-radius:0;margin:0;border-bottom:1px solid var(--dsw-alias-border-l1,#333);background:transparent}\n.vsm-project .vsm-mcp-card:last-child{border-bottom:0}\n.vsm-project .vsm-mcp-banner{border-radius:0;margin:0}\n\n/* 新增 MCP 弹窗 */\n.vsm-mcp-modal{position:fixed;inset:0;background:var(--dsw-alias-bg-mask-drop,#000000aa);display:flex;align-items:center;justify-content:center;z-index:50}\n.vsm-mcp-dialog{width:min(560px,calc(100vw - 40px));max-height:88vh;overflow:auto;padding:22px 24px;border-radius:12px;background:var(--dsw-alias-bg-overlay,#202020);border:1px solid var(--dsw-alias-border-l2,#444);box-shadow:0 16px 60px #000c;color:var(--dsw-alias-label-primary,#e6e6e6)}\n.vsm-mcp-dialog h3{margin:0 0 14px;font-size:16px;font-weight:600}\n.vsm-mcp-dialog label{display:flex;flex-direction:column;gap:6px;margin:12px 0;font-size:12px;color:var(--dsw-alias-label-secondary,#aaa)}\n.vsm-mcp-dialog input,.vsm-mcp-dialog select,.vsm-mcp-dialog textarea{font:inherit;color:var(--dsw-alias-label-primary,#eee);background:var(--dsw-alias-bg-layer-1,#2b2b2b);border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;padding:8px 10px}\n.vsm-mcp-dialog input:focus,.vsm-mcp-dialog select:focus,.vsm-mcp-dialog textarea:focus{outline:none;border-color:var(--dsw-alias-brand-primary,#6d55ff)}\n.vsm-mcp-dialog textarea{min-height:64px;resize:vertical;font-family:var(--ds-font-family-code,ui-monospace,monospace)}\n.vsm-mcp-dialog-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}\n.vsm-mcp-dialog-actions button{padding:8px 14px;border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;background:none;color:var(--dsw-alias-label-primary,#eee);cursor:pointer;font-size:13px}\n.vsm-mcp-dialog-actions button:hover{background:var(--dsw-alias-interactive-bg-hover,#ffffff14)}\n\n/* 兼容性小节 */\n.vsm-compat-h3{margin:16px 0 2px;font-size:14px;font-weight:600;color:var(--dsw-alias-label-secondary,#c8c8c8)}\n.vsm-compat-item{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding:10px 0;border-bottom:1px solid var(--dsw-alias-border-l1,#333);font-size:13px;color:var(--dsw-alias-label-primary,#eee)}\n.vsm-compat-item.ok .vsm-compat-name::before{content:\"● \";color:var(--dsw-alias-state-success-primary,#38bd75)}\n.vsm-compat-item.warn .vsm-compat-name::before{content:\"● \";color:var(--dsw-alias-state-warn-primary,#e5b93f)}\n.vsm-compat-name{font-weight:500;min-width:0}\n.vsm-compat-note{color:var(--dsw-alias-label-tertiary,#9aa5b1);font-size:12px;text-align:right;min-width:0}\n\n/* 开发形态开关 */\n.vsm-devform-note{display:block;margin-top:4px;font-size:11px;color:var(--dsw-alias-label-tertiary,#9aa5b1);word-break:break-all}\n.vsm-devform-actions{display:flex;flex-direction:column;align-items:flex-end;gap:6px;min-width:0}\n.vsm-devform-msg{color:var(--dsw-alias-state-warn-primary,#e5b93f);font-size:11px;text-align:right}\n.vsm-general-row button{border:1px solid var(--dsw-alias-border-l2,#555);border-radius:6px;padding:6px 12px;background:none;color:var(--dsw-alias-label-primary,#eee);cursor:pointer;font-size:12px;white-space:nowrap}\n.vsm-general-row button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,#ffffff14)}\n.vsm-general-row button:disabled{opacity:.55;cursor:default}\n.vsm-general-row button.vsm-devform-close{color:var(--dsw-alias-state-error-primary,#f07878);border-color:var(--dsw-alias-state-error-secondary,#d9534f55)}\n";
|
|
2204
2394
|
const tagId = "dsh-vscode-mode/mcp.css";
|
|
2205
2395
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
2206
2396
|
const tag = document.createElement("style");
|
|
@@ -2574,11 +2764,14 @@ window.__ModuleLoader__.load({
|
|
|
2574
2764
|
}));
|
|
2575
2765
|
return react.default.createElement("section", { className: "vsm-project" }, head, body);
|
|
2576
2766
|
}
|
|
2577
|
-
/**
|
|
2767
|
+
/** 通用设置:选择当前对话文件链接的打开器 + 开发形态开关。 */
|
|
2578
2768
|
function GeneralSettings({ registry }) {
|
|
2579
2769
|
const [tool, setTool] = react.default.useState(AUTO_OPEN_TOOL);
|
|
2580
2770
|
const [busy, setBusy] = react.default.useState(false);
|
|
2581
2771
|
const [error, setError] = react.default.useState("");
|
|
2772
|
+
const [devForm, setDevForm] = react.default.useState(null);
|
|
2773
|
+
const [devBusy, setDevBusy] = react.default.useState(false);
|
|
2774
|
+
const [devMessage, setDevMessage] = react.default.useState("");
|
|
2582
2775
|
const settings = react.default.useContext(SettingsContext);
|
|
2583
2776
|
const snapshot = settings?.getSnapshot?.();
|
|
2584
2777
|
const loading = !snapshot || snapshot.status === "loading";
|
|
@@ -2592,6 +2785,11 @@ window.__ModuleLoader__.load({
|
|
|
2592
2785
|
onChange();
|
|
2593
2786
|
return settings?.subscribe?.(onChange);
|
|
2594
2787
|
}, [settings]);
|
|
2788
|
+
react.default.useEffect(() => {
|
|
2789
|
+
rpc("vscode.devFormGet", {}).then((result) => {
|
|
2790
|
+
if (result.ok) setDevForm(result.devForm);
|
|
2791
|
+
}).catch(() => {});
|
|
2792
|
+
}, []);
|
|
2595
2793
|
const save = (value) => {
|
|
2596
2794
|
setTool(value);
|
|
2597
2795
|
setBusy(true);
|
|
@@ -2603,6 +2801,19 @@ window.__ModuleLoader__.load({
|
|
|
2603
2801
|
}
|
|
2604
2802
|
settings.set("fileOpenTool", value).catch((e) => setError(String(e))).finally(() => setBusy(false));
|
|
2605
2803
|
};
|
|
2804
|
+
const closeDevForm = () => {
|
|
2805
|
+
if (!window.confirm("关闭开发形态:插件将切换为正式版安装(版本依赖 + 删除工作区链接),pnpm 装配后需重启 DSH 生效。确认关闭?")) return;
|
|
2806
|
+
setDevBusy(true);
|
|
2807
|
+
setDevMessage("");
|
|
2808
|
+
rpc("vscode.devFormSet", { enabled: false }).then((result) => {
|
|
2809
|
+
if (!result.ok) {
|
|
2810
|
+
setDevMessage("关闭失败:" + String(result.error));
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2813
|
+
setDevForm(result.devForm);
|
|
2814
|
+
setDevMessage(result.restart ? "已切换为正式版,重启 DSH 后生效。" : "已关闭开发形态。");
|
|
2815
|
+
}).catch((e) => setDevMessage("关闭失败:" + String(e))).finally(() => setDevBusy(false));
|
|
2816
|
+
};
|
|
2606
2817
|
const options = [{
|
|
2607
2818
|
id: AUTO_OPEN_TOOL,
|
|
2608
2819
|
label: "自动选择",
|
|
@@ -2613,6 +2824,11 @@ window.__ModuleLoader__.load({
|
|
|
2613
2824
|
description: item.description
|
|
2614
2825
|
}))];
|
|
2615
2826
|
const currentOption = options.some((item) => item.id === tool) ? tool : AUTO_OPEN_TOOL;
|
|
2827
|
+
const devFormRow = devForm?.enabled ? react.default.createElement("div", { className: "vsm-general-row" }, react.default.createElement("span", null, "开发形态", react.default.createElement("small", { className: "vsm-devform-note" }, "工作区链接安装:" + devForm.path)), react.default.createElement("div", { className: "vsm-devform-actions" }, devMessage && react.default.createElement("small", { className: "vsm-devform-msg" }, devMessage), react.default.createElement("button", {
|
|
2828
|
+
className: "vsm-devform-close",
|
|
2829
|
+
disabled: devBusy,
|
|
2830
|
+
onClick: closeDevForm
|
|
2831
|
+
}, devBusy ? "切换中…" : "关闭开发形态"))) : null;
|
|
2616
2832
|
return react.default.createElement("section", { className: "vsm-general-page" }, react.default.createElement("h2", null, "通用"), react.default.createElement("p", null, "配置 DSH 对话中文件链接的打开工具。工具由当前运行时自动扫描。"), unavailable && react.default.createElement("div", { className: "vsm-mcp-error vsm-mcp-banner" }, "设置服务暂不可用,当前使用自动选择。"), error && react.default.createElement("div", { className: "vsm-mcp-error vsm-mcp-banner" }, error), react.default.createElement("label", { className: "vsm-general-row" }, react.default.createElement("span", null, "文件链接使用工具"), react.default.createElement("select", {
|
|
2617
2833
|
value: currentOption,
|
|
2618
2834
|
disabled: loading || unavailable || notReady || busy || snapshot?.writable === false,
|
|
@@ -2620,7 +2836,7 @@ window.__ModuleLoader__.load({
|
|
|
2620
2836
|
}, options.map((item) => react.default.createElement("option", {
|
|
2621
2837
|
key: item.id,
|
|
2622
2838
|
value: item.id
|
|
2623
|
-
}, item.label))), loading && react.default.createElement("small", null, "读取中…")));
|
|
2839
|
+
}, item.label))), loading && react.default.createElement("small", null, "读取中…")), devFormRow);
|
|
2624
2840
|
}
|
|
2625
2841
|
/** 兼容性小节:host 报告(RPC compat)+ 客户端本地适配项。 */
|
|
2626
2842
|
function CompatSection({ getSummary }) {
|
|
@@ -2644,7 +2860,8 @@ window.__ModuleLoader__.load({
|
|
|
2644
2860
|
className: "vsm-compat-item " + (item.active ? "ok" : "warn")
|
|
2645
2861
|
}, react.default.createElement("span", { className: "vsm-compat-name" }, item.name), react.default.createElement("span", { className: "vsm-compat-note" }, item.note ?? (item.active ? "正常" : "未生效"))));
|
|
2646
2862
|
const warnings = report?.warnings ?? [];
|
|
2647
|
-
|
|
2863
|
+
const devForm = report?.devForm;
|
|
2864
|
+
return react.default.createElement("section", { className: "vsm-general-page" }, react.default.createElement("h2", null, "兼容性"), react.default.createElement("p", null, "检测与其他插件 / DSH 版本的适配状态与已知问题。" + (report?.pluginVersion ? "(插件版本 " + report.pluginVersion + ")" : "")), error && react.default.createElement("div", { className: "vsm-mcp-error vsm-mcp-banner" }, error), devForm?.enabled && react.default.createElement(react.default.Fragment, null, react.default.createElement("h3", { className: "vsm-compat-h3" }, "开发形态"), react.default.createElement("div", { className: "vsm-compat-item ok" }, react.default.createElement("span", { className: "vsm-compat-name" }, "开发形态开启(工作区链接安装)"), react.default.createElement("span", { className: "vsm-compat-note" }, devForm.path))), react.default.createElement("h3", { className: "vsm-compat-h3" }, "外部插件与服务"), renderItems(report?.external), react.default.createElement("h3", { className: "vsm-compat-h3" }, "客户端适配"), renderItems(getSummary?.() ?? []), react.default.createElement("h3", { className: "vsm-compat-h3" }, "护栏"), renderItems(report?.guards), react.default.createElement("h3", { className: "vsm-compat-h3" }, "警告"), warnings.length ? warnings.map((w, index) => react.default.createElement("div", {
|
|
2648
2865
|
key: index,
|
|
2649
2866
|
className: "vsm-mcp-error vsm-mcp-banner"
|
|
2650
2867
|
}, w)) : react.default.createElement("div", { className: "vsm-compat-item ok" }, react.default.createElement("span", { className: "vsm-compat-name" }, "未检测到兼容性问题"), react.default.createElement("span", { className: "vsm-compat-note" }, "")));
|
|
@@ -2892,6 +3109,147 @@ window.__ModuleLoader__.load({
|
|
|
2892
3109
|
return typeof value === "string" && value.trim() ? value.trim() : AUTO_OPEN_TOOL;
|
|
2893
3110
|
}
|
|
2894
3111
|
//#endregion
|
|
3112
|
+
//#region src/client/addToConversation.ts
|
|
3113
|
+
/** DSH reference source 名(dsh-client-ui-reference 注册的 @file/@session 统一源)。 */
|
|
3114
|
+
const REF_SOURCE = "reference";
|
|
3115
|
+
/**
|
|
3116
|
+
* 生成 DSH @file 语法引用串:cwd 相对化、\ → /、含空白时按 @"path" 语法加引号。
|
|
3117
|
+
* cwd 外/无法相对化的路径回退原路径。
|
|
3118
|
+
* @author ddj 2026年08月25号
|
|
3119
|
+
* @param path 打开的文件路径(相对 cwd 或绝对)
|
|
3120
|
+
* @param cwd 会话工作区目录(可选)
|
|
3121
|
+
* @returns 引用串(如 @src/index.ts 或 @"a b.ts")
|
|
3122
|
+
*/
|
|
3123
|
+
function mentionOf(path, cwd) {
|
|
3124
|
+
const raw = String(path);
|
|
3125
|
+
let rel = raw;
|
|
3126
|
+
if (cwd) {
|
|
3127
|
+
const base = String(cwd).replace(/[\\/]+$/, "");
|
|
3128
|
+
const up = raw.replace(/\\/g, "/");
|
|
3129
|
+
const baseUp = base.replace(/\\/g, "/");
|
|
3130
|
+
if (up.startsWith(baseUp + "/")) rel = up.slice(baseUp.length + 1);
|
|
3131
|
+
else if (up === baseUp) rel = "";
|
|
3132
|
+
}
|
|
3133
|
+
rel = rel.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
3134
|
+
if (!rel) rel = raw.replace(/\\/g, "/");
|
|
3135
|
+
if (/[\u0000-\u001f\u007f-\u009f"]/u.test(rel)) return "@" + raw;
|
|
3136
|
+
return /\s/u.test(rel) ? `@"${rel}"` : `@${rel}`;
|
|
3137
|
+
}
|
|
3138
|
+
/** 引用标签:文件名 + 可选行区间(chip 内展示,不带 @ 前缀)。
|
|
3139
|
+
* @author ddj 2026年08月25号 */
|
|
3140
|
+
function labelOf(path, range) {
|
|
3141
|
+
const base = String(path).split(/[\\/]/).pop() || String(path);
|
|
3142
|
+
if (!range || range.endLine < range.startLine) return base;
|
|
3143
|
+
return range.startLine === range.endLine ? `${base} L${range.startLine}` : `${base} L${range.startLine}-${range.endLine}`;
|
|
3144
|
+
}
|
|
3145
|
+
/** 引用 ref:引用串 + 可选行区间(序列化直出,agent 据此读取对应片段)。
|
|
3146
|
+
* @author ddj 2026年08月25号 */
|
|
3147
|
+
function refOf(mention, range) {
|
|
3148
|
+
if (!range || range.endLine < range.startLine) return mention;
|
|
3149
|
+
return range.startLine === range.endLine ? `${mention} L${range.startLine}` : `${mention} L${range.startLine}-${range.endLine}`;
|
|
3150
|
+
}
|
|
3151
|
+
/** 构造 DSH 文件引用插入载荷(source=reference,发送序列化为 mention(+range) 文本)。 */
|
|
3152
|
+
function buildFileRef(path, cwd, range) {
|
|
3153
|
+
const mention = mentionOf(path, cwd);
|
|
3154
|
+
return {
|
|
3155
|
+
mention,
|
|
3156
|
+
reference: {
|
|
3157
|
+
source: REF_SOURCE,
|
|
3158
|
+
ref: refOf(mention, range),
|
|
3159
|
+
label: labelOf(path, range),
|
|
3160
|
+
appearance: "file",
|
|
3161
|
+
clipboardText: mention
|
|
3162
|
+
}
|
|
3163
|
+
};
|
|
3164
|
+
}
|
|
3165
|
+
/**
|
|
3166
|
+
* 解析会话输入门面;缺失时返回 undefined(动作侧守卫降级)。
|
|
3167
|
+
* @author ddj 2026年08月25号
|
|
3168
|
+
* @param ctx 客户端服务上下文
|
|
3169
|
+
* @param sessionId 会话 id
|
|
3170
|
+
* @returns SessionInput 或 undefined
|
|
3171
|
+
*/
|
|
3172
|
+
function inputFor(ctx, sessionId) {
|
|
3173
|
+
if (!sessionId) return void 0;
|
|
3174
|
+
try {
|
|
3175
|
+
const sessions = ctx.get("sessions");
|
|
3176
|
+
const conversation = ctx.get("conversation");
|
|
3177
|
+
const actx = sessions?.scope?.(sessionId);
|
|
3178
|
+
const shell = actx && conversation?.input?.for?.(actx);
|
|
3179
|
+
return shell && typeof shell.setDraft === "function" ? shell : void 0;
|
|
3180
|
+
} catch {
|
|
3181
|
+
return;
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
/** 取当前草稿长度与版本;无输入门面时返回 null。
|
|
3185
|
+
* @author ddj 2026年08月25号 */
|
|
3186
|
+
function draftCursor(input) {
|
|
3187
|
+
try {
|
|
3188
|
+
const s = input?.state?.getSnapshot?.();
|
|
3189
|
+
if (!s) return null;
|
|
3190
|
+
return {
|
|
3191
|
+
draft: String(s.draft ?? ""),
|
|
3192
|
+
draftRev: Number(s.draftRev ?? 0)
|
|
3193
|
+
};
|
|
3194
|
+
} catch {
|
|
3195
|
+
return null;
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
/** 从 sessions 列表快照读会话工作区目录(与 index.ts 既有读取方式一致)。
|
|
3199
|
+
* @author ddj 2026年08月25号 */
|
|
3200
|
+
function cwdOf(ctx, sessionId) {
|
|
3201
|
+
if (!sessionId) return void 0;
|
|
3202
|
+
try {
|
|
3203
|
+
return ctx.get("sessions")?.list?.getSnapshot?.()?.byId?.[sessionId]?.cwd;
|
|
3204
|
+
} catch {
|
|
3205
|
+
return;
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
/** 写入成功后的 composer 内联提示(门面可用时;失败静默)。
|
|
3209
|
+
* @author ddj 2026年08月25号 */
|
|
3210
|
+
function notify(input, text) {
|
|
3211
|
+
try {
|
|
3212
|
+
input.notify?.("info", text);
|
|
3213
|
+
} catch {}
|
|
3214
|
+
}
|
|
3215
|
+
/** 输入门面插入引用(拦截异常视作未应用,走降级)。
|
|
3216
|
+
* @author ddj 2026年08月25号 */
|
|
3217
|
+
function safeInsert(input, reference, span) {
|
|
3218
|
+
try {
|
|
3219
|
+
return input.insertReference(reference, span) === true;
|
|
3220
|
+
} catch {
|
|
3221
|
+
return false;
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
/**
|
|
3225
|
+
* 创建「添加到对话」动作集(apply 阶段构建一次,随 props 传给 EditorView)。
|
|
3226
|
+
* @author ddj 2026年08月25号
|
|
3227
|
+
* @param ctx 客户端服务上下文(sessions + conversation)
|
|
3228
|
+
* @returns 动作集
|
|
3229
|
+
*/
|
|
3230
|
+
function createAddToConversation(ctx) {
|
|
3231
|
+
const appendReference = async (sessionId, path, range) => {
|
|
3232
|
+
const input = inputFor(ctx, sessionId);
|
|
3233
|
+
if (!input) return "unavailable";
|
|
3234
|
+
const cur = draftCursor(input);
|
|
3235
|
+
if (!cur) return "unavailable";
|
|
3236
|
+
const { reference, mention } = buildFileRef(path, cwdOf(ctx, sessionId), range);
|
|
3237
|
+
if (!safeInsert(input, reference, {
|
|
3238
|
+
start: cur.draft.length,
|
|
3239
|
+
end: cur.draft.length,
|
|
3240
|
+
draftRev: cur.draftRev
|
|
3241
|
+
})) {
|
|
3242
|
+
const gap = cur.draft.length > 0 && !/\s$/.test(cur.draft) ? " " : "";
|
|
3243
|
+
input.setDraft(cur.draft + gap + mention + " ");
|
|
3244
|
+
notify(input, "已添加文件引用 " + mention);
|
|
3245
|
+
return "busy";
|
|
3246
|
+
}
|
|
3247
|
+
notify(input, "已添加文件引用 " + mention);
|
|
3248
|
+
return "ok";
|
|
3249
|
+
};
|
|
3250
|
+
return { appendReference };
|
|
3251
|
+
}
|
|
3252
|
+
//#endregion
|
|
2895
3253
|
//#region src/client/index.ts
|
|
2896
3254
|
/**
|
|
2897
3255
|
* dsh-vscode-mode client — 浏览器半入口:slot 注册 + 装配。
|
|
@@ -2914,6 +3272,7 @@ window.__ModuleLoader__.load({
|
|
|
2914
3272
|
"remote",
|
|
2915
3273
|
"workspaces",
|
|
2916
3274
|
"sessions",
|
|
3275
|
+
"conversation",
|
|
2917
3276
|
"settingsScope",
|
|
2918
3277
|
"webUiSettings"
|
|
2919
3278
|
];
|
|
@@ -2924,6 +3283,11 @@ window.__ModuleLoader__.load({
|
|
|
2924
3283
|
*/
|
|
2925
3284
|
function apply(ctx) {
|
|
2926
3285
|
const schedule = (fn, ms) => ctx.timeout(fn, ms);
|
|
3286
|
+
if (typeof window !== "undefined") {
|
|
3287
|
+
const preloadMonaco = () => loadMonaco(() => {}).catch(() => {});
|
|
3288
|
+
if (typeof window.requestIdleCallback === "function") window.requestIdleCallback(preloadMonaco, { timeout: 2e3 });
|
|
3289
|
+
else schedule(preloadMonaco, 300);
|
|
3290
|
+
}
|
|
2927
3291
|
const registry = createFileOpenerRegistry();
|
|
2928
3292
|
const workspaces = ctx.get("workspaces");
|
|
2929
3293
|
const sessions = ctx.get("sessions");
|
|
@@ -2931,6 +3295,8 @@ window.__ModuleLoader__.load({
|
|
|
2931
3295
|
const binder = pickSettingsBinder(ctx);
|
|
2932
3296
|
const settings = binder.scope;
|
|
2933
3297
|
let selected = autoValue("auto");
|
|
3298
|
+
/** 「添加到对话」动作集:编辑区/Tab 右键菜单注入文件引用与代码块(conversation 服务缺失时各动作安全降级)。 */
|
|
3299
|
+
const addToConversation = createAddToConversation(ctx);
|
|
2934
3300
|
/** 客户端侧兼容摘要(与 host 报告合并展示;惰性求值保证 HMR 后仍新鲜)。 */
|
|
2935
3301
|
const compatSummary = () => [
|
|
2936
3302
|
{
|
|
@@ -2992,7 +3358,10 @@ window.__ModuleLoader__.load({
|
|
|
2992
3358
|
order: 5,
|
|
2993
3359
|
label: "文件编辑",
|
|
2994
3360
|
inject: (sessionId) => ({ sessionId })
|
|
2995
|
-
}, (props) => react.default.createElement(EditorView, Object.assign({}, props, {
|
|
3361
|
+
}, (props) => react.default.createElement(EditorView, Object.assign({}, props, {
|
|
3362
|
+
schedule,
|
|
3363
|
+
addToConversation
|
|
3364
|
+
})));
|
|
2996
3365
|
registerSlotSafely(ctx, {
|
|
2997
3366
|
name: "conversation.session.header.utilities",
|
|
2998
3367
|
id: "edrv-diff-badge",
|