dsh-vscode-mode 0.1.51 → 0.1.52
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/index.js +24 -83
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -2
- package/src/lsp/config.ts +13 -29
- package/src/lsp/rpc.ts +14 -17
- package/src/lsp/settings.ts +0 -50
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vscode-mode",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.52",
|
|
4
4
|
"description": "DSH 上的类 VSCode 编码体验:Monaco 编辑器(文件页签/QuickOpen/状态栏,可驻 dsh-better-sidebar 侧边栏与对话同屏)+ Agent 编辑差异审查(整文件差异/采纳/拒绝/归档/回滚)+ 语言服务器(LSP)智能(跳转定义/引用/hover/大纲 + VSIX 扩展市场安装),状态持久化到工作区旁车",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
package/src/index.ts
CHANGED
|
@@ -20,7 +20,6 @@ import { sweepTreeCache } from './paths.js'
|
|
|
20
20
|
import { PLUGIN_NAME, buildReport } from './compat.js'
|
|
21
21
|
import { createLspManager } from './lsp/manager.js'
|
|
22
22
|
import { createLspRpc } from './lsp/rpc.js'
|
|
23
|
-
import { installLspSettingsSection } from './lsp/settings.js'
|
|
24
23
|
import { disposeAllServers } from './lsp/transport.js'
|
|
25
24
|
import { installRulesSection } from './rules.js'
|
|
26
25
|
import type { RpcHandlerMap } from './shared/rpc.js'
|
|
@@ -45,7 +44,7 @@ export function apply(ctx: Ctx, config?: unknown): void {
|
|
|
45
44
|
/** 兼容性警告收集(route 护栏等写入,启动日志一并输出)。 */
|
|
46
45
|
const warnings: string[] = []
|
|
47
46
|
setupOpenSettings(ctx, config, () => {})
|
|
48
|
-
|
|
47
|
+
/** LSP 配置为配置值模式:插件组合配置 + 会话内运行时覆盖(原 settings section 命名空间不合法,见 lsp/config.ts)。 */
|
|
49
48
|
/** 规则注入 section(~/.dsh/rules 与 <工作区>/.dsh/rules;旧版 DSH 无 systemPrompt 时静默降级)。 */
|
|
50
49
|
const rulesInstalled = installRulesSection(ctx)
|
|
51
50
|
if (!rulesInstalled) ctx.logger?.warn?.('[' + name + '] 未检测到 systemPrompt 服务,规则仅可管理不注入')
|
package/src/lsp/config.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dsh-vscode-mode host — LSP 配置读取与 provider 解析装配。
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* 配置来源优先级:运行时覆盖(设置页保存,重启失效)> 插件组合配置 > 默认。
|
|
4
|
+
* 原 settings section(ns dsh-vscode-mode.languageServers)命名空间不合法
|
|
5
|
+
* (DSH settings 仅允许 /^[a-z][a-z0-9-]*$/,点号命名空间永久不可注册),
|
|
6
|
+
* 已降级为配置值(插件组合配置 + 会话内运行时覆盖),不再尝试 settings 安装。
|
|
7
|
+
* 作者 ddj 2026-08-27 / 2026-09-02
|
|
5
8
|
*/
|
|
6
|
-
import type { Ctx } from '../store.js'
|
|
7
9
|
import { PROVIDER_RESOLVERS, type LspProviderSpec } from './providers.js'
|
|
8
10
|
import { provisionRuntime } from './dotnetProvision.js'
|
|
9
11
|
|
|
@@ -21,10 +23,10 @@ export interface LspConfig {
|
|
|
21
23
|
[languageId: string]: LspLangConfig | undefined
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
export const LSP_SETTINGS_NS = 'dsh-vscode-mode.languageServers'
|
|
25
26
|
export const LSP_LANGUAGES = ['lua', 'csharp'] as const
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
/** 清洗单语言配置:仅保留合法字段并剥离 undefined(稀疏覆盖语义,清空字段即回落组合配置)。 */
|
|
29
|
+
export function sanitizeLang(raw: unknown): LspLangConfig | undefined {
|
|
28
30
|
if (!raw || typeof raw !== 'object') return undefined
|
|
29
31
|
const obj = raw as Record<string, unknown>
|
|
30
32
|
const out: LspLangConfig = {}
|
|
@@ -46,25 +48,7 @@ export function configFromPlugin(config: unknown): LspConfig {
|
|
|
46
48
|
return out
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
/**
|
|
50
|
-
export function configFromSettings(ctx: Ctx): LspConfig {
|
|
51
|
-
try {
|
|
52
|
-
const settings = ctx.get('settings')
|
|
53
|
-
const descriptor = settings?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === LSP_SETTINGS_NS)
|
|
54
|
-
const value = descriptor?.value
|
|
55
|
-
if (!value || typeof value !== 'object') return {}
|
|
56
|
-
const out: LspConfig = {}
|
|
57
|
-
for (const lang of LSP_LANGUAGES) {
|
|
58
|
-
const v = sanitizeLang((value as Record<string, unknown>)[lang])
|
|
59
|
-
if (v) out[lang] = v
|
|
60
|
-
}
|
|
61
|
-
return out
|
|
62
|
-
} catch (error) {
|
|
63
|
-
return {}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** 合并配置:settings 覆盖插件配置。 */
|
|
51
|
+
/** 合并配置:上层(运行时覆盖/settings)覆盖插件组合配置。 */
|
|
68
52
|
export function mergeConfig(a: LspConfig, b: LspConfig): LspConfig {
|
|
69
53
|
const out: LspConfig = { ...a }
|
|
70
54
|
for (const lang of LSP_LANGUAGES) {
|
|
@@ -77,17 +61,17 @@ export function mergeConfig(a: LspConfig, b: LspConfig): LspConfig {
|
|
|
77
61
|
}
|
|
78
62
|
|
|
79
63
|
/**
|
|
80
|
-
* 解析某语言的 provider spec
|
|
81
|
-
* @author ddj 2026年08月27号
|
|
82
|
-
* @param ctx DSH 上下文
|
|
64
|
+
* 解析某语言的 provider spec(插件组合配置 + 运行时覆盖层合并后)。
|
|
65
|
+
* @author ddj 2026年08月27号 / 2026年09月02号
|
|
83
66
|
* @param pluginConfig 插件组合配置
|
|
84
67
|
* @param languageId 语言 id
|
|
68
|
+
* @param override 运行时覆盖层(设置页保存值,重启失效;缺省为空)
|
|
85
69
|
* @returns provider 规格
|
|
86
70
|
*/
|
|
87
|
-
export function resolveProviderSpec(
|
|
71
|
+
export function resolveProviderSpec(pluginConfig: unknown, languageId: string, override?: LspConfig): LspProviderSpec {
|
|
88
72
|
const resolver = PROVIDER_RESOLVERS[languageId]
|
|
89
73
|
if (!resolver) return { languageId, kind: 'none', argv: [], ready: false, reason: '不支持的语言:' + languageId }
|
|
90
|
-
const merged = mergeConfig(configFromPlugin(pluginConfig),
|
|
74
|
+
const merged = mergeConfig(configFromPlugin(pluginConfig), override ?? {})
|
|
91
75
|
const lang = merged[languageId]
|
|
92
76
|
if (lang && lang.enabled === false) {
|
|
93
77
|
return { languageId, kind: 'none', argv: [], ready: false, reason: '已在设置中禁用' }
|
package/src/lsp/rpc.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dsh-vscode-mode host — edrv.lsp.* RPC handlers。
|
|
3
3
|
* 文档跟踪(openDocs 集合 + root|lang 引用计数)→ 懒启动服务器、用完释放。
|
|
4
|
-
*
|
|
4
|
+
* LSP 配置降级为配置值:插件组合配置 + 会话内运行时覆盖层(原 settings section
|
|
5
|
+
* 命名空间不合法,永久不可注册,见 lsp/config.ts 头注释)。
|
|
6
|
+
* 作者 ddj 2026-08-27 / 2026-09-02
|
|
5
7
|
*/
|
|
6
8
|
import type { Ctx } from '../store.js'
|
|
7
9
|
import { searchRoot } from '../search/ripgrep.js'
|
|
8
10
|
import { sessionOf, cwdOf } from '../registry.js'
|
|
9
|
-
import { resolveProviderSpec, langOfPath, configFromPlugin,
|
|
11
|
+
import { resolveProviderSpec, langOfPath, configFromPlugin, mergeConfig, sanitizeLang, LSP_LANGUAGES, type LspConfig, type LspLangConfig } from './config.js'
|
|
10
12
|
import { clearProviderCache, candidatesFor } from './providers.js'
|
|
11
13
|
import { onRuntimeProvisioned, envInstallStates } from './dotnetProvision.js'
|
|
12
14
|
import { envRequirementsFor, installRequirement } from './envRequirements.js'
|
|
@@ -116,6 +118,8 @@ function createDocTracker() {
|
|
|
116
118
|
export function createLspRpc(deps: LspRpcDeps): { handlers: Partial<RpcHandlerMap>; disposeSession: (sessionId: string) => void } {
|
|
117
119
|
const { ctx, pluginConfig, manager } = deps
|
|
118
120
|
const tracker = createDocTracker()
|
|
121
|
+
/** 运行时覆盖层:设置页保存值(内存态,重启回落组合配置值;每 apply 新建,插件重载自动复位)。 */
|
|
122
|
+
const runtimeConfig: LspConfig = {}
|
|
119
123
|
|
|
120
124
|
// 运行时自动配置成功:清 provider 缓存并重置 C# 服务器,下一次文档同步即用新运行时重启
|
|
121
125
|
onRuntimeProvisioned(() => {
|
|
@@ -139,7 +143,7 @@ export function createLspRpc(deps: LspRpcDeps): { handlers: Partial<RpcHandlerMa
|
|
|
139
143
|
}
|
|
140
144
|
|
|
141
145
|
const acquireServer = (root: string, lang: string) =>
|
|
142
|
-
manager.acquire(root, lang, (languageId: string) => resolveProviderSpec(
|
|
146
|
+
manager.acquire(root, lang, (languageId: string) => resolveProviderSpec(pluginConfig, languageId, runtimeConfig))
|
|
143
147
|
|
|
144
148
|
const serverOf = (root: string, lang: string) =>
|
|
145
149
|
manager.peek(root, lang)
|
|
@@ -149,7 +153,7 @@ export function createLspRpc(deps: LspRpcDeps): { handlers: Partial<RpcHandlerMa
|
|
|
149
153
|
|
|
150
154
|
/** 当前 provider 检测结论 → 设置页 idle 状态(不启动 server);附带未满足的环境需求与候选服务器。 */
|
|
151
155
|
const detectedStatus = (languageId: string, root?: string): LspServerStatus => {
|
|
152
|
-
const spec = resolveProviderSpec(
|
|
156
|
+
const spec = resolveProviderSpec(pluginConfig, languageId, runtimeConfig)
|
|
153
157
|
const missingEnv = envRequirementsFor(languageId, dshHome())
|
|
154
158
|
const candidates = candidatesFor(languageId, spec)
|
|
155
159
|
return {
|
|
@@ -207,10 +211,8 @@ export function createLspRpc(deps: LspRpcDeps): { handlers: Partial<RpcHandlerMa
|
|
|
207
211
|
},
|
|
208
212
|
|
|
209
213
|
'edrv.lsp.configGet': async () => {
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
const merged: LspConfig = { ...plugin }
|
|
213
|
-
for (const lang of Object.keys(settings)) merged[lang] = { ...plugin[lang], ...settings[lang] }
|
|
214
|
+
// 配置值降级:插件组合配置 + 运行时覆盖层(原 settings section 已废弃)
|
|
215
|
+
const merged = mergeConfig(configFromPlugin(pluginConfig), runtimeConfig)
|
|
214
216
|
return { ok: true, config: merged as unknown as Record<string, unknown> }
|
|
215
217
|
},
|
|
216
218
|
|
|
@@ -219,21 +221,16 @@ export function createLspRpc(deps: LspRpcDeps): { handlers: Partial<RpcHandlerMa
|
|
|
219
221
|
if (!lang || !(LSP_LANGUAGES as readonly string[]).includes(lang)) {
|
|
220
222
|
return { ok: false, error: '不支持的语言:' + lang }
|
|
221
223
|
}
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
const target = next[lang]!
|
|
224
|
+
// 覆盖层基于当前运行时值增量修改;清空字段剥离 undefined → 回落组合配置
|
|
225
|
+
const target: LspLangConfig = { ...(runtimeConfig[lang] ?? {}) }
|
|
225
226
|
if (args.enabled !== undefined) target.enabled = args.enabled
|
|
226
227
|
if (args.command !== undefined) target.command = args.command || undefined
|
|
227
228
|
if (args.path !== undefined) target.path = args.path || undefined
|
|
229
|
+
runtimeConfig[lang] = sanitizeLang(target) ?? {}
|
|
228
230
|
try {
|
|
229
|
-
const settings = ctx.get('settings')
|
|
230
|
-
if (!settings?.update) return { ok: false, error: '设置服务不可用' }
|
|
231
|
-
await settings.update(LSP_SETTINGS_NS, { [lang]: target })
|
|
232
231
|
// 保存/切换后立即重新检测:清缓存 + 重置旧 server,旧状态不残留
|
|
233
232
|
const servers = await redetectLanguage(lang)
|
|
234
|
-
const
|
|
235
|
-
const stored = descriptor?.value as Record<string, unknown> | undefined
|
|
236
|
-
const merged: LspConfig = { ...configFromPlugin(pluginConfig), ...(stored as LspConfig) }
|
|
233
|
+
const merged = mergeConfig(configFromPlugin(pluginConfig), runtimeConfig)
|
|
237
234
|
return { ok: true, config: merged as unknown as Record<string, unknown>, servers }
|
|
238
235
|
} catch (error) {
|
|
239
236
|
return { ok: false, error: '配置保存失败:' + String(error) }
|
package/src/lsp/settings.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dsh-vscode-mode host — LSP 配置设置 section 安装(版本自适应;缺失/失败不抛错)。
|
|
3
|
-
* ns:dsh-vscode-mode.languageServers;每语言 { enabled, command, path }。
|
|
4
|
-
* 安装策略分派见 fileOpenSettings.runSettingsInstall(rc 线 legacy / alpha 线服务方法)。
|
|
5
|
-
* 作者 ddj 2026-08-27 / 2026-09-02
|
|
6
|
-
*/
|
|
7
|
-
import type { Ctx } from '../store.js'
|
|
8
|
-
import { LSP_LANGUAGES, LSP_SETTINGS_NS, type LspConfig } from './config.js'
|
|
9
|
-
import { loadSettingsDeps, runSettingsInstall, type SettingsDeps } from '../fileOpenSettings.js'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 安装 LSP 设置 section。
|
|
13
|
-
* @author ddj 2026年08月27号
|
|
14
|
-
* @param ctx DSH 上下文
|
|
15
|
-
* @param entry 初始配置
|
|
16
|
-
* @returns 是否成功安装
|
|
17
|
-
*/
|
|
18
|
-
export async function installLspSettingsSection(ctx: Ctx, entry: LspConfig): Promise<boolean> {
|
|
19
|
-
let deps: SettingsDeps | null = null
|
|
20
|
-
try {
|
|
21
|
-
deps = await loadSettingsDeps()
|
|
22
|
-
} catch {
|
|
23
|
-
/* 装载失败按缺失处理 */
|
|
24
|
-
}
|
|
25
|
-
if (!deps) return false
|
|
26
|
-
try {
|
|
27
|
-
// schemastery 无 .optional(),对象字段默认即可选;.default 必给避免 undefined 覆盖
|
|
28
|
-
const z = deps.z
|
|
29
|
-
const langShape: Record<string, unknown> = {}
|
|
30
|
-
for (const lang of LSP_LANGUAGES) {
|
|
31
|
-
langShape[lang] = z.object({
|
|
32
|
-
enabled: z.boolean(),
|
|
33
|
-
command: z.string(),
|
|
34
|
-
path: z.string(),
|
|
35
|
-
}).default({})
|
|
36
|
-
}
|
|
37
|
-
const schema = z.object(langShape).default({})
|
|
38
|
-
const strategy = await runSettingsInstall(ctx, LSP_SETTINGS_NS, schema, entry, {
|
|
39
|
-
setSource: () => {},
|
|
40
|
-
onChange: () => {},
|
|
41
|
-
})
|
|
42
|
-
return strategy === 'legacy' || strategy === 'service'
|
|
43
|
-
} catch (error) {
|
|
44
|
-
// 设置 section 安装失败不致命:降级为无设置 UI,LSP 核心功能不受影响
|
|
45
|
-
console.error('[dsh-vscode-mode] LSP 设置 section 安装失败:' + String(error))
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export type { SettingsDeps }
|