dsh-vscode-mode 0.1.46 → 0.1.47

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/lib/client.js CHANGED
@@ -5804,8 +5804,8 @@ window.__ModuleLoader__.load({
5804
5804
  hint: "优先使用已安装 EmmyLua;未安装时回退 LuaLS 或 PATH 中的 lua-language-server"
5805
5805
  }, {
5806
5806
  id: "csharp",
5807
- label: "C#(Roslyn / OmniSharp)",
5808
- hint: "需 dotnet + ms-dotnettools.csharp 的 .roslyn 服务器,或手动指定"
5807
+ label: "C#(Roslyn / DotRush / OmniSharp)",
5808
+ hint: "优先自动发现 ms-dotnettools.csharp / DotRush 扩展(DotRush 需 .NET 10 运行时);也可手动指定"
5809
5809
  }];
5810
5810
  const PHASE_LABEL = {
5811
5811
  idle: "未启动",
@@ -5839,8 +5839,17 @@ window.__ModuleLoader__.load({
5839
5839
  label: "更新"
5840
5840
  }
5841
5841
  ];
5842
- /** 语言卡片:状态 + 启用开关 + 命令/路径配置 + 重新检测。 */
5843
- function LangCard({ lang, config, status, busy, onToggle, onSave, onRedetect }) {
5842
+ /** 环境安装按钮文案(按安装进行态)。 */
5843
+ function envButtonLabel(req, envStates) {
5844
+ const state = (envStates ?? []).find((s) => s.id === req.id);
5845
+ if (state?.phase === "downloading") return "下载中…";
5846
+ if (state?.phase === "extracting") return "安装中…";
5847
+ if (state?.phase === "done") return "已完成";
5848
+ if (state?.phase === "failed") return "重试";
5849
+ return "一键安装";
5850
+ }
5851
+ /** 语言卡片:状态 + 缺失环境提示(一键安装/官网下载) + 启用开关 + 命令/路径配置 + 重新检测。 */
5852
+ function LangCard({ lang, config, status, busy, envStates, onInstallEnv, onToggle, onSave, onRedetect }) {
5844
5853
  const [pathDraft, setPathDraft] = react.default.useState(config?.path ?? "");
5845
5854
  const [commandDraft, setCommandDraft] = react.default.useState(config?.command ?? "");
5846
5855
  react.default.useEffect(() => {
@@ -5852,7 +5861,23 @@ window.__ModuleLoader__.load({
5852
5861
  className: "vsm-switch " + (config?.enabled !== false ? "on" : ""),
5853
5862
  onClick: () => onToggle(lang.id, config?.enabled !== false ? false : true),
5854
5863
  "aria-label": "启用/禁用"
5855
- }, config?.enabled !== false ? "●" : "○"))), react.default.createElement("div", { className: "vsm-mcp-meta" }, PHASE_LABEL[phase] ?? phase, " · ", SOURCE_LABEL[status?.source] ?? status?.source, status?.providerName ? " · " + status.providerName : "", status?.version ? " · v" + status.version : "", phase === "ready" && status?.root ? " · " + String(status.root).split(/[\\/]/).pop() : ""), status?.reason ? react.default.createElement("div", { className: "vsm-mcp-error" }, status.reason) : null, react.default.createElement("div", { className: "vsm-lsp-form" }, react.default.createElement("label", null, react.default.createElement("span", null, "可执行文件路径(绝对路径,优先)"), react.default.createElement("input", {
5864
+ }, config?.enabled !== false ? "●" : "○"))), react.default.createElement("div", { className: "vsm-mcp-meta" }, PHASE_LABEL[phase] ?? phase, " · ", SOURCE_LABEL[status?.source] ?? status?.source, status?.providerName ? " · " + status.providerName : "", status?.version ? " · v" + status.version : "", phase === "ready" && status?.root ? " · " + String(status.root).split(/[\\/]/).pop() : ""), status?.reason ? react.default.createElement("div", { className: "vsm-mcp-error" }, status.reason) : null, Array.isArray(status?.missingEnv) && status.missingEnv.length ? react.default.createElement("div", { className: "vsm-lsp-hint" }, "缺少运行环境(一键安装后自动生效):", status.missingEnv.map((req) => react.default.createElement("div", {
5865
+ key: req.id,
5866
+ className: "vsm-mcp-actions"
5867
+ }, react.default.createElement("span", null, req.label, req.detail ? "(" + req.detail + ")" : ""), req.installable ? react.default.createElement("button", {
5868
+ className: "vsm-primary vsm-small",
5869
+ disabled: busy === "env:" + req.id,
5870
+ onClick: () => onInstallEnv(lang.id, req)
5871
+ }, envButtonLabel(req, envStates)) : null, req.manualUrl ? react.default.createElement("a", {
5872
+ href: req.manualUrl,
5873
+ target: "_blank",
5874
+ rel: "noreferrer",
5875
+ style: {
5876
+ color: "inherit",
5877
+ textDecoration: "underline",
5878
+ alignSelf: "center"
5879
+ }
5880
+ }, req.manualLabel ?? "官网下载") : null))) : null, react.default.createElement("div", { className: "vsm-lsp-form" }, react.default.createElement("label", null, react.default.createElement("span", null, "可执行文件路径(绝对路径,优先)"), react.default.createElement("input", {
5856
5881
  value: pathDraft,
5857
5882
  placeholder: "如 C:/.../lua-language-server.exe",
5858
5883
  onChange: (e) => setPathDraft(e.target.value)
@@ -5908,6 +5933,8 @@ window.__ModuleLoader__.load({
5908
5933
  const [busy, setBusy] = react.default.useState("");
5909
5934
  const [error, setError] = react.default.useState("");
5910
5935
  const [loading, setLoading] = react.default.useState(true);
5936
+ const [envStates, setEnvStates] = react.default.useState([]);
5937
+ const [envLang, setEnvLang] = react.default.useState("");
5911
5938
  const refreshServers = react.default.useCallback(() => {
5912
5939
  Promise.all([rpc("edrv.lsp.configGet", {}), rpc("edrv.lsp.status", {})]).then(([cfg, st]) => {
5913
5940
  if (cfg?.ok) setConfig(cfg.config ?? {});
@@ -5922,6 +5949,12 @@ window.__ModuleLoader__.load({
5922
5949
  setError("");
5923
5950
  }).catch((e) => setError(String(e)));
5924
5951
  }, []);
5952
+ const refreshEnvStates = react.default.useCallback(() => {
5953
+ return rpc("edrv.lsp.envState", {}).then((res) => {
5954
+ if (res?.ok) setEnvStates(res.states ?? []);
5955
+ return res?.states ?? [];
5956
+ }).catch(() => []);
5957
+ }, []);
5925
5958
  const refresh = react.default.useCallback(() => {
5926
5959
  setLoading(true);
5927
5960
  Promise.all([refreshServers(), refreshExt()]).finally(() => setLoading(false));
@@ -5941,9 +5974,56 @@ window.__ModuleLoader__.load({
5941
5974
  setServers((prev) => Array.isArray(list) ? [...prev.filter((s) => s.languageId !== languageId), ...list] : prev);
5942
5975
  };
5943
5976
  /** 重检测后通知编辑器:与 host 重新同步已打开的模型(触发重新 acquire)。 */
5944
- const notifyResync = (languageId) => {
5977
+ const notifyResync = react.default.useCallback((languageId) => {
5945
5978
  window.dispatchEvent(new CustomEvent("edrv:lsp-redetect", { detail: { languageId } }));
5979
+ }, []);
5980
+ /** 一键安装缺失环境:启动内置安装器(成功后进入轮询,完成自动重同步)。 */
5981
+ const installEnv = (languageId, req) => {
5982
+ const key = "env:" + req.id;
5983
+ setBusy(key);
5984
+ setError("");
5985
+ setEnvLang(languageId);
5986
+ rpc("edrv.lsp.envInstall", {
5987
+ languageId,
5988
+ id: req.id
5989
+ }).then((res) => {
5990
+ if (!res?.ok) {
5991
+ setError(res?.error ?? "无法启动安装");
5992
+ return;
5993
+ }
5994
+ refreshEnvStates();
5995
+ refreshServers();
5996
+ }).catch((e) => setError(String(e))).finally(() => setBusy(""));
5946
5997
  };
5998
+ react.default.useEffect(() => {
5999
+ if (!(envStates ?? []).some((s) => s.phase === "downloading" || s.phase === "extracting")) return;
6000
+ const timer = setInterval(() => {
6001
+ refreshEnvStates();
6002
+ refreshServers();
6003
+ }, 2e3);
6004
+ return () => clearInterval(timer);
6005
+ }, [
6006
+ envStates,
6007
+ refreshEnvStates,
6008
+ refreshServers
6009
+ ]);
6010
+ const prevEnvPhases = react.default.useRef({});
6011
+ react.default.useEffect(() => {
6012
+ const states = envStates ?? [];
6013
+ for (const s of states) {
6014
+ const prev = prevEnvPhases.current[s.id];
6015
+ if (prev && prev !== "done" && s.phase === "done" && envLang) {
6016
+ refreshServers();
6017
+ notifyResync(envLang);
6018
+ }
6019
+ prevEnvPhases.current[s.id] = s.phase;
6020
+ }
6021
+ }, [
6022
+ envStates,
6023
+ envLang,
6024
+ refreshServers,
6025
+ notifyResync
6026
+ ]);
5947
6027
  const saveLang = (languageId, path, command) => {
5948
6028
  setBusy(languageId);
5949
6029
  setError("");
@@ -6064,6 +6144,8 @@ window.__ModuleLoader__.load({
6064
6144
  config: config[lang.id] ?? {},
6065
6145
  status: servers.find((s) => s.languageId === lang.id),
6066
6146
  busy,
6147
+ envStates,
6148
+ onInstallEnv: installEnv,
6067
6149
  onToggle: toggleLang,
6068
6150
  onSave: saveLang,
6069
6151
  onRedetect: redetectLang