dsh-vscode-mode 0.1.63 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/lib/client.js +1737 -98
- package/lib/client.js.map +1 -1
- package/lib/index.js +482 -20
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/client/commandBridge.ts +85 -0
- package/src/client/commandGlobals.ts +13 -0
- package/src/client/commandPaletteStore.ts +212 -0
- package/src/client/commandRegistry.ts +150 -0
- package/src/client/commandSearch.ts +89 -0
- package/src/client/editorModelState.ts +30 -0
- package/src/client/index.ts +32 -0
- package/src/client/keybindings.ts +71 -17
- package/src/client/monaco/loader.ts +24 -0
- package/src/client/snippets/provider.ts +172 -0
- package/src/client/styles/editor.css +51 -0
- package/src/client/ui/CommandPalette.ts +194 -0
- package/src/client/ui/ConversationDiffDock.ts +17 -9
- package/src/client/ui/EditorView.ts +185 -4
- package/src/client/ui/KeybindingsPanel.ts +1 -1
- package/src/client/ui/QuickOpen.ts +11 -3
- package/src/client/ui/SnippetsPicker.ts +296 -0
- package/src/client/ui/commandCatalog.ts +204 -0
- package/src/rpc.ts +78 -0
- package/src/shared/keybindings.ts +9 -1
- package/src/shared/rpc.ts +11 -0
- package/src/shared/snippets.ts +156 -0
- package/src/snippets.ts +427 -0
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["STDOUT_CAP","STDERR_CAP","GRACE_MS","PROVIDER_VERSION","STDERR_CAP","fullPolicy","requireWorkspace","Buffer","value"],"sources":["../src/mcp.ts","../src/shared/keybindings.ts","../src/shared/integration.ts","../src/shared/logger.ts","../src/log.ts","../src/fileOpenSettings.ts","../src/devForm.ts","../src/dshVersion.ts","../src/shared/rpc.ts","../src/paths.ts","../src/compat.ts","../src/routes.ts","../src/shared/diff.ts","../src/model.ts","../src/store.ts","../src/registry.ts","../src/tree.ts","../src/treeRead.ts","../src/treeIndex.ts","../src/capture.ts","../src/search/query.ts","../src/search/ripgrep.ts","../src/search/fallback.ts","../src/search/ranker.ts","../src/search/orchestrator.ts","../src/search/content.ts","../src/revert.ts","../src/rules.ts","../src/mcpProject.ts","../src/unityBridge.ts","../src/integrate.ts","../src/externalHandoff.ts","../src/reveal.ts","../src/debugLog.ts","../src/perf.ts","../src/perfPatch.ts","../src/rpc.ts","../src/mcpIsolation.ts","../src/workspace.ts","../src/lsp/jsonrpc.ts","../src/lsp/transport.ts","../src/shared/lsp.ts","../src/lsp/client.ts","../src/lsp/uri.ts","../src/lsp/derive.ts","../src/lsp/server.ts","../src/lsp/manager.ts","../src/lsp/zip.ts","../src/lsp/extmgr.ts","../src/lsp/providers.ts","../src/lsp/dotnetProvision.ts","../src/lsp/config.ts","../src/lsp/envRequirements.ts","../src/lsp/rpc.ts","../src/shared/ai.ts","../src/ai/inline.ts","../src/ai/rpc.ts","../src/index.ts"],"sourcesContent":["/**\n * dsh-vscode-mode host — MCP 运行时管理适配层。\n * 只操作已装配的 @deepseek-ai/dsh-mcp-client loader entry,不在浏览器侧连接 MCP。\n * 身份常量(包名/条目前缀/新旧格式判定)统一由 compat 层持有,本模块再导出保持既有 import 面。\n * 作者 ddj 2026年08月22号\n */\nimport {\n LEGACY_PROJECT_PREFIX,\n MCP_PACKAGE,\n PROJECT_ENTRY_PREFIX,\n isProjectEntryId,\n} from './compat.js'\nimport type { MpcConfig, MpcServer, MpcTool } from './shared/mcp.js'\nimport type { Ctx } from './store.js'\n\nexport { LEGACY_PROJECT_PREFIX, MCP_PACKAGE, PROJECT_ENTRY_PREFIX, isProjectEntryId }\n\n/** 列出当前 loader 中的 MCP entry。 */\nfunction entriesOf(ctx: Ctx): any[] {\n const loader = ctx.get('loader')\n if (!loader || typeof loader.entries !== 'function') return []\n return [...loader.entries()].filter((entry) => entry?.options?.name === MCP_PACKAGE)\n}\nexport { entriesOf }\n\n/** 脱敏配置并保留可编辑字段的存在性。 */\nexport function publicConfig(config: Record<string, unknown>): MpcConfig {\n const out = { ...config } as Record<string, unknown>\n if (out.env && typeof out.env === 'object') out.env = Object.fromEntries(Object.keys(out.env as object).map((key) => [key, '••••••']))\n if (out.headers && typeof out.headers === 'object') out.headers = Object.fromEntries(Object.keys(out.headers as object).map((key) => [key, '••••••']))\n return out as unknown as MpcConfig\n}\n\n/** 从工具注册表读取服务器命名空间下的工具摘要。 */\nexport function toolsOf(ctx: Ctx, serverName: string): MpcTool[] {\n const tools = ctx.get('tools')\n const view = tools?.view?.(void 0)\n const visible = view?.visible\n if (!(visible instanceof Map)) return []\n const prefix = `mcp__${serverName}__`\n return [...visible.entries()].filter(([name]) => String(name).startsWith(prefix)).map(([name, definition]) => ({\n name: String(name).slice(prefix.length),\n description: typeof definition?.description === 'string' ? definition.description : undefined,\n }))\n}\n\n/** 将 loader entry 映射为设置页摘要。 */\nexport function serverOf(ctx: Ctx, entry: any): MpcServer {\n const config = (entry.options?.config ?? {}) as Record<string, unknown>\n const serverName = typeof config.serverName === 'string' ? config.serverName : entry.options?.id ?? 'unknown'\n const tools = toolsOf(ctx, serverName)\n const state = entry.fiber?.state\n return {\n id: String(entry.id ?? entry.options?.id ?? serverName),\n serverName,\n enabled: entry.disabled !== true,\n transport: config.transport === 'streamable-http' ? 'streamable-http' : 'stdio',\n config: publicConfig(config),\n status: state === 2 ? 'connected' : state === 1 ? 'connecting' : 'error',\n toolCount: tools.length,\n tools,\n error: state === 3 ? 'MCP 插件未正常运行' : undefined,\n }\n}\n\n/** 校验 MCP 配置。 */\nexport function validateConfig(config: MpcConfig): void {\n if (!/^[A-Za-z0-9_-]{1,32}$/.test(config.serverName)) throw new Error('serverName 只能包含字母、数字、下划线和连字符(最多 32 位)')\n if (config.transport === 'stdio' && !config.command?.trim()) throw new Error('stdio MCP 必须填写 command')\n if (config.transport === 'streamable-http' && !/^https?:\\/\\//.test(config.url ?? '')) throw new Error('HTTP MCP 必须填写 http(s) URL')\n}\n\n/** 列出全局(profile)MCP 服务,过滤掉新旧格式的项目级条目。 */\nexport function listMcp(ctx: Ctx): { servers: MpcServer[] } {\n return { servers: entriesOf(ctx).filter((entry) => !isProjectEntryId(String(entry.id ?? entry.options?.id ?? ''))).map((entry) => serverOf(ctx, entry)) }\n}\n\n/** 保存 MCP 服务配置并触发 loader 热更新。 */\nexport async function saveMcp(ctx: Ctx, config: MpcConfig): Promise<MpcServer> {\n validateConfig(config)\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const existing = entriesOf(ctx).find((entry) => !isProjectEntryId(String(entry.id ?? entry.options?.id ?? '')) && entry.options?.config?.serverName === config.serverName)\n if (existing) {\n await loader.update(existing.id, { config: { ...config } })\n return serverOf(ctx, loader.resolve(existing.id))\n }\n const id = await loader.create({ name: MCP_PACKAGE, config: { ...config } })\n return serverOf(ctx, loader.resolve(id))\n}\n\n/** 删除 MCP 服务。 */\nexport async function removeMcp(ctx: Ctx, id: string): Promise<void> {\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id) === id)\n if (!entry) throw new Error('MCP 服务不存在')\n await loader.remove(entry.id)\n}\n\n/** 切换 MCP 服务启用状态。 */\nexport async function toggleMcp(ctx: Ctx, id: string, enabled: boolean): Promise<MpcServer> {\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id) === id)\n if (!entry) throw new Error('MCP 服务不存在')\n await loader.update(entry.id, { disabled: !enabled })\n return serverOf(ctx, loader.resolve(entry.id))\n}\n\n/** 重新加载 MCP 服务。 */\nexport async function refreshMcp(ctx: Ctx, id: string): Promise<MpcServer> {\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id) === id)\n if (!entry) throw new Error('MCP 服务不存在')\n await loader.update(entry.id, { config: { ...(entry.options?.config ?? {}) } })\n return serverOf(ctx, loader.resolve(entry.id))\n}\n\nexport type { MpcConfig, MpcServer }\nexport const mcpPackageName = MCP_PACKAGE\n","/**\n * dsh-vscode-mode shared — 快捷键命令目录与默认键位(双面契约)。\n * 纯数据模块:host(settings schema 默认值)与 client(执行匹配/设置页)共用。\n * 键位格式:修饰符 + 主键,`+` 连接,如 `Ctrl+Shift+F`;空串 = 未绑定;\n * `|` 连接多个候选(任一命中即触发),如 `Alt+ArrowLeft|Ctrl+Alt+-`。\n * 作者 ddj 2026年08月26号\n */\n\n/** 命令 id → 默认键位(可为多候选)。命令目录以此为准,新增命令只需加一项。 */\nexport const KEYBINDING_DEFAULTS: Record<string, string> = {\n 'edrv.save': 'Ctrl+S',\n 'edrv.quickOpen': 'Ctrl+P',\n 'edrv.toggleSidebar': 'Ctrl+B',\n 'edrv.searchInFiles': 'Ctrl+Shift+F',\n 'edrv.navigateBack': 'Alt+ArrowLeft|Ctrl+Alt+-',\n 'edrv.navigateForward': 'Alt+ArrowRight|Ctrl+Shift+-',\n // 页签循环:主候选避开浏览器保留键(Ctrl+Tab / Ctrl+PgUp/PgDn 会被浏览器截获)\n 'edrv.nextTab': 'Ctrl+Alt+ArrowRight|Ctrl+PageDown',\n 'edrv.prevTab': 'Ctrl+Alt+ArrowLeft|Ctrl+PageUp',\n}\n\n/**\n * 返回默认键位的独立副本(调用方修改不污染目录)。\n * @author ddj 2026年08月26号\n * @returns 默认键位映射\n */\nexport function defaultKeybindings(): Record<string, string> {\n return { ...KEYBINDING_DEFAULTS }\n}\n\n/**\n * 规整外部键位数据:只保留已知命令 id 且为字符串的值,未知 id 丢弃。\n * 防止用户文档/旧版本写入的未知命令污染执行匹配。\n * @author ddj 2026年08月26号\n * @param raw 原始设置值\n * @returns 规整后的键位映射(缺省项不补默认值,由调用方按需合并)\n */\nexport function normalizeKeybindings(raw: unknown): Record<string, string> {\n const out: Record<string, string> = {}\n if (!raw || typeof raw !== 'object') return out\n for (const [id, chord] of Object.entries(raw as Record<string, unknown>)) {\n if (id in KEYBINDING_DEFAULTS && typeof chord === 'string') out[id] = chord\n }\n return out\n}\n","/**\n * dsh-vscode-mode shared — 系统集成载荷契约(Windows 右键菜单 + Unity 一键安装/更新)。\n * Purity rule: no node/react imports(platform 用 string 表示)。\n * 作者 ddj 2026-09-07\n */\n\n/** Unity 内嵌包名(UPM 包名,同时是项目 Packages/ 下的目录名)。 */\nexport const UNITY_PACKAGE_NAME = 'com.dsh.editor'\n/** 注册表菜单键叶子名(HKCU\\Software\\Classes\\*\\shell\\<leaf>)。 */\nexport const SHELL_MENU_LEAF = 'DSHEditor'\n/** 深链基址默认值(DSH Web GUI 默认端口,dsh-web.cmd 实证)。 */\nexport const INTEGRATION_BASE_DEFAULT = 'http://127.0.0.1:3080'\n\n/** launcher 安装态。 */\nexport interface ShellLauncherState {\n /** launcher 文件是否已安装(编译 exe 或降级 ps1)。 */\n present: boolean\n /** 是否为已编译 exe(false = 降级 ps1)。 */\n compiled: boolean\n /** launcher 文件绝对路径(未安装时为期望路径)。 */\n path: string\n}\n\n/** 一条右键菜单注册条目(跨平台:Windows 三键 / Linux 两项 / macOS 快速操作)。 */\nexport interface ShellMenuEntry {\n /** 条目 id(files/dir/dirBackground/nautilus/dolphin/finder)。 */\n id: string\n /** 展示名。 */\n label: string\n /** 是否已注册。 */\n registered: boolean\n /** 是否需手动创建(macOS Automator 配方)。 */\n manual?: boolean\n}\n\n/** 系统集成状态(edrv.integration.status/register/unregister 载荷)。 */\nexport interface ShellIntegrationStatus {\n /** 宿主平台('win32'/'linux'/'darwin')。 */\n platform: string\n launcher: ShellLauncherState\n /** 菜单注册条目(按平台)。 */\n entries: ShellMenuEntry[]\n /** 深链基址(设置 integrationBaseUrl)。 */\n baseUrl: string\n /** Unity 包源目录(随插件分发的 unity/com.dsh.editor 绝对路径)。 */\n unityPackagePath: string\n}\n\n/** 一个已登记 Unity 项目的安装状态(edrv.unity.* 载荷)。 */\nexport interface UnityProjectEntry {\n /** 项目根(归一化绝对路径)。 */\n path: string\n /** 目录名(展示标题)。 */\n title: string\n /** 已安装版本(未安装 → null)。 */\n installedVersion: string | null\n /** 已安装且版本等于包源版本。 */\n upToDate: boolean\n /** 项目目录不存在。 */\n missingDir: boolean\n /** 非法原因(非 Unity 项目根等)。 */\n error?: string\n}\n\n/** edrv.unity.list 载荷。 */\nexport interface UnityListPayload {\n /** 包源版本(unity/com.dsh.editor/package.json 的 version)。 */\n sourceVersion: string | null\n /** 包源目录绝对路径。 */\n sourcePath: string\n /** 已登记项目及安装状态。 */\n projects: UnityProjectEntry[]\n}\n","/**\n * dsh-vscode-mode — 统一日志核心(双面共享,平台中立)。\n * 输出规范:\n * - 格式:`[dsh-vscode-mode][:scope] 消息`;前缀只在模块内部拼接,业务代码禁止手写前缀\n * - 级别语义:debug=诊断明细 / info=装配与路由里程碑 / warn=降级与兼容回退 / error=失败\n * - 出口:host 面经 bindHostLog(ctx) 绑定 ctx.logger(缺失回退 console);client 面固定 console\n * - 诊断文件通道(edrv.debug → ~/.dsh/dsh-vscode-mode/logs/)见 debugLog.ts,与本模块前缀共用\n * 新增日志一律 `import { log } from '../log.js'`(client 为 './log.js')后调 log.debug/info/warn/error;\n * 子域日志用 log.child('scope'),禁止另起 console。\n * 作者 ddj 2026-09-08\n */\n\n/** 插件统一日志前缀(与包安装名一致)。 */\nexport const LOG_PREFIX = '[dsh-vscode-mode]'\n\n/** 日志级别(与 console 方法名对齐)。 */\nexport type LoggerLevel = 'debug' | 'info' | 'warn' | 'error'\n\n/** 日志出口:接收拼好前缀的整行(host 面接 ctx.logger,client 面接 console)。 */\nexport type LoggerSink = (level: LoggerLevel, line: string) => void\n\n/** 默认级别到 console 方法名的映射。 */\nconst CONSOLE_METHODS: Record<LoggerLevel, string> = { debug: 'debug', info: 'info', warn: 'warn', error: 'error' }\n\n/**\n * 默认出口:console(级别直映方法;方法缺失时静默丢弃,不抛错)。\n * @author ddj 2026年09月08号\n * @returns console 出口\n */\nexport function consoleSink(): LoggerSink {\n return (level, line) => {\n const emit = (console as unknown as Record<string, unknown>)[CONSOLE_METHODS[level]]\n if (typeof emit === 'function') (emit as (message: string) => void).call(console, line)\n }\n}\n\n/**\n * DSH host 出口工厂:转接 ctx.logger(方法级可选调用,缺服务/缺方法回退 console)。\n * @author ddj 2026年09月08号\n * @param ctx DSH host 上下文\n * @returns 日志出口\n */\nexport function ctxLogSink(ctx: unknown): LoggerSink {\n const base = consoleSink()\n return (level, line) => {\n const logger = (ctx as { logger?: Record<string, unknown> } | null | undefined)?.logger\n const emit = logger?.[level]\n if (typeof emit === 'function') (emit as (message: string) => void).call(logger, line)\n else base(level, line)\n }\n}\n\n/**\n * 拼一行日志:`[dsh-vscode-mode][:scope] 消息`(scope 为空省略冒号段)。\n * @author ddj 2026年09月08号\n * @param scope 子域(可空)\n * @param message 消息文本\n * @returns 整行文本\n */\nexport function formatLine(scope: string, message: string): string {\n const text = String(message)\n return scope ? LOG_PREFIX + ':' + scope + ' ' + text : LOG_PREFIX + ' ' + text\n}\n\n/** 日志器实例(四级别统一入口 + 换出口/派生子域)。 */\nexport interface PluginLogger {\n debug(message: string): void\n info(message: string): void\n warn(message: string): void\n error(message: string): void\n /** 更换出口(同一实例树共享,host 装配期绑定 ctx.logger 用;client 单例不调用)。 */\n bind(sink: LoggerSink): void\n /** 派生带子域前缀的新实例(共享出口,如 log.child('debug') → `[dsh-vscode-mode:debug]`)。 */\n child(scope: string): PluginLogger\n}\n\n/** 实例树共享的出口状态(bind 换出口对整棵树生效)。 */\ninterface SinkState {\n sink: LoggerSink\n}\n\n/**\n * 日志器工厂(内部):emit 时读共享出口状态,保证父 bind 后子实例跟随。\n * @author ddj 2026年09月08号\n * @param state 共享出口状态\n * @param scope 子域文本(可空)\n * @returns 日志器\n */\nfunction makeLogger(state: SinkState, scope: string): PluginLogger {\n const emit = (level: LoggerLevel, message: string): void => state.sink(level, formatLine(scope, message))\n return {\n debug: (message) => emit('debug', message),\n info: (message) => emit('info', message),\n warn: (message) => emit('warn', message),\n error: (message) => emit('error', message),\n bind(next: LoggerSink): void {\n state.sink = next\n },\n child(next: string): PluginLogger {\n return makeLogger(state, scope ? scope + '.' + next : next)\n },\n }\n}\n\n/**\n * 创建插件日志器(默认 console 出口;host 面单例由 bindHostLog 换到 ctx.logger)。\n * @author ddj 2026年09月08号\n * @param sink 初始出口(缺省 console)\n * @param scope 初始子域(业务方一般经 child 派生,不直接传)\n * @returns 日志器\n */\nexport function createLogger(sink: LoggerSink = consoleSink(), scope = ''): PluginLogger {\n return makeLogger({ sink }, scope)\n}\n","/**\n * dsh-vscode-mode host — 日志单例(全 host 面唯一日志入口)。\n * 默认 console 出口;apply() 首行调 bindHostLog(ctx) 切到 ctx.logger(缺失回退 console)。\n * 用法:`import { log } from './log.js'` → `log.debug/info/warn/error(msg)`;子域用 `log.child('scope')`。\n * 作者 ddj 2026-09-08\n */\nimport { createLogger, ctxLogSink } from './shared/logger.js'\n\n/** host 面插件日志单例(格式/级别语义见 shared/logger.ts 头注释)。 */\nexport const log = createLogger()\n\n/**\n * 装配期绑定 host 日志出口:ctx.logger 可用时全部日志转经 DSH 日志系统。\n * @author ddj 2026年09月08号\n * @param ctx DSH host 上下文(logger 服务缺失时保持 console 出口)\n */\nexport function bindHostLog(ctx: unknown): void {\n log.bind(ctxLogSink(ctx))\n}\n","/**\n * dsh-vscode-mode host — 文件链接打开工具 + 快捷键的持久化设置。\n * 依赖守卫:schemastery 动态加载;@deepseek-ai/dsh-settings 仅作 legacy 探测——\n * rc 线导出 installSettingsSection free function,0.1.2-alpha 起移除(改由 settings\n * 服务的 installSection 方法承载,见 runSettingsInstall 三策略)。\n * 缺失/任一策略失败时插件仍可加载(fileOpenTool 降级为配置值,compat 报告可见),\n * 全程 try/catch,不产生未捕获 rejection。\n * 作者 ddj 2026年08月24号 / 2026年08月26号 / 2026年09月02号\n */\nimport type { Ctx } from './store.js'\nimport { KEYBINDING_DEFAULTS } from './shared/keybindings.js'\nimport { INTEGRATION_BASE_DEFAULT } from './shared/integration.js'\nimport type { AiConfigPatch, AiConfigView } from './shared/ai.js'\nimport { log } from './log.js'\n\nexport const FILE_OPEN_SETTINGS_NS = 'dsh-vscode-mode'\nexport const FILE_OPEN_DEFAULT = 'auto'\nexport interface FileOpenSettings { fileOpenTool: string; integrationBaseUrl: string }\nexport interface FileOpenSettingsState { value: string; revision?: number; update: (value: string, expectedRevision?: number) => Promise<void> }\n\n/** AI 内联补全配置默认值(默认关闭;路由空 = 自动;档位空 = 跟随模型默认)。 */\nexport const AI_CONFIG_DEFAULT: { enabled: boolean; provider: string; model: string; effort: string } = {\n enabled: false,\n provider: '',\n model: '',\n effort: '',\n}\n\ntype SettingsProvider = {\n update?: (ns: string, patch: object, expectedRevision?: number) => Promise<void>\n describe?: (options?: unknown) => Array<{ ns?: string; value?: unknown; revision?: number }>\n get?: (ns: string) => unknown\n}\n\n/** 动态依赖的装载结果(宽松类型:dsh-settings 无本地类型声明)。 */\nexport interface SettingsDeps {\n installSettingsSection?: (ctx: Ctx, ns: string, schema: unknown, entry: object, hooks: object) => void\n z: {\n object: (shape: Record<string, unknown>) => { default: (value: Record<string, unknown>) => unknown }\n string: () => { default: (value: string) => unknown }\n boolean: () => { default: (value: boolean) => unknown }\n number: () => { default: (value: number) => unknown }\n }\n}\n\nexport type SettingsDepsLoader = () => Promise<SettingsDeps | null>\n\nlet depsPromise: Promise<SettingsDeps | null> | undefined\n\n/**\n * 动态加载设置依赖(模块级缓存;任一缺失/失败返回 null 而非抛错)。\n * installSettingsSection 仅在 rc 线 dsh-settings 中存在时提供(alpha 起移除,\n * 属性探测得到 undefined,不抛错)。\n * @author ddj 2026年08月24号\n * @returns 设置依赖或 null\n */\nexport function loadSettingsDeps(): Promise<SettingsDeps | null> {\n if (!depsPromise) {\n depsPromise = Promise.all([import('@deepseek-ai/dsh-settings'), import('schemastery')])\n .then(([dshSettings, schemastery]) => ({\n // dsh-settings 类型声明随版本变化(rc.8 有 d.ts、alpha 已移除导出),统一经 unknown 松绑\n installSettingsSection: (dshSettings as unknown as { installSettingsSection?: SettingsDeps['installSettingsSection'] }).installSettingsSection,\n z: (schemastery as unknown as { default: SettingsDeps['z'] }).default,\n }))\n .catch(() => null)\n }\n return depsPromise\n}\n\n/** 设置 section 安装策略(版本适配机制的观测值)。 */\nexport type SettingsInstallStrategy = 'legacy' | 'service' | 'none' | 'unknown'\n\nconst INSTALL_UNMOUNTED = '设置 section 尚未装配'\nconst INSTALL_LEGACY = 'rc 线:dsh-settings.installSettingsSection'\nconst INSTALL_SERVICE = '0.1.2-alpha 线:settings 服务 installSection'\nconst INSTALL_NONE = '两路均不可用:设置持久化降级为配置值'\n\ninterface ObservedInstall { strategy: SettingsInstallStrategy; note: string }\nlet observedInstall: ObservedInstall = { strategy: 'unknown', note: INSTALL_UNMOUNTED }\n\n/** 记录最近一次安装策略(供兼容报告展示;失败路径也记录,便于诊断)。 */\nfunction recordInstall(strategy: SettingsInstallStrategy, note: string): SettingsInstallStrategy {\n observedInstall = { strategy, note }\n return strategy\n}\n\n/** 读取观测到的安装策略(供报告;测试可用 reset 复位)。 */\nexport function settingsInstallStrategy(): SettingsInstallStrategy {\n return observedInstall.strategy\n}\n\n/** 读取观测到的安装策略说明文案。 */\nexport function settingsInstallNote(): string {\n return observedInstall.note\n}\n\n/** 复位安装策略观测(测试隔离用)。 */\nexport function resetSettingsInstallObserved(): void {\n observedInstall = { strategy: 'unknown', note: INSTALL_UNMOUNTED }\n}\n\n/**\n * 设置 section 版本自适应安装(核心策略分派)。\n * legacy:dsh-settings 仍导出 installSettingsSection(rc 线)→ 原样调用,行为与旧版一致。\n * service:该导出已移除(0.1.2-alpha 起)→ 经 ctx.inject(['settings']) 走服务方法\n * provider.installSection(owner, ns, schema, entry, hooks)(等义封装,含\n * base 层与 fiber 卸载回退)。回调内方法缺失再降级记录 none。\n * none:两条路由都不存在 → 仅记录并告警,调用方按配置值运行。\n * 全程不抛错、不产生未捕获 rejection。\n * @author ddj 2026年09月02号\n * @param ctx DSH host 上下文(inject 可选探测)\n * @param ns 设置命名空间\n * @param schema schemastery schema\n * @param entry 初始设置值(作为 base 层)\n * @param hooks 设置源绑定与变更回调\n * @param loader 依赖装载器(测试注入)\n * @returns 采用/观测到的策略\n */\nexport async function runSettingsInstall(\n ctx: Ctx,\n ns: string,\n schema: unknown,\n entry: object,\n hooks: { setSource: (source: () => unknown) => void; onChange: () => void; validate?: unknown },\n loader: SettingsDepsLoader = loadSettingsDeps,\n): Promise<SettingsInstallStrategy> {\n let deps: SettingsDeps | null = null\n try {\n deps = await loader()\n } catch {\n /* 装载失败按缺失处理 */\n }\n if (!deps) {\n log.warn('设置依赖不可用,section ' + ns + ' 未安装(配置回退)')\n return recordInstall('none', INSTALL_NONE)\n }\n const legacy = deps.installSettingsSection\n if (typeof legacy === 'function') {\n try {\n legacy(ctx, ns, schema, entry, hooks)\n return recordInstall('legacy', INSTALL_LEGACY)\n } catch (error) {\n log.warn('legacy 设置安装失败,尝试服务路由:' + String(error))\n }\n }\n const ctxInject = (ctx as unknown as { inject?: (services: string[], callback: (sctx: unknown) => void) => unknown }).inject\n if (typeof ctxInject !== 'function') return recordInstall('none', INSTALL_NONE)\n try {\n ctxInject(['settings'], (sctx: unknown) => {\n const sc = sctx as { get?: (name: string) => unknown; settings?: unknown }\n const provider = typeof sc.get === 'function' ? sc.get('settings') : sc.settings\n const install = (provider as { installSection?: unknown } | undefined)?.installSection\n if (typeof install !== 'function') {\n log.warn('settings 服务无 installSection(DSH 版本 API 变化),section ' + ns + ' 降级为配置值')\n recordInstall('none', INSTALL_NONE)\n return\n }\n try {\n install.call(provider, ctx, ns, schema, entry, hooks)\n recordInstall('service', INSTALL_SERVICE)\n } catch (error) {\n log.warn('settings.installSection 安装失败(' + String(error) + '),section ' + ns + ' 降级为配置值')\n recordInstall('none', INSTALL_NONE)\n }\n })\n } catch (error) {\n log.warn('settings 服务路由不可用(' + String(error) + ')')\n return recordInstall('none', INSTALL_NONE)\n }\n // inject 回调若同步执行(settings 已就绪)会覆写观测值;仍未执行(unknown)时乐观按 service 记录\n if (observedInstall.strategy !== 'unknown') return observedInstall.strategy\n return recordInstall('service', '已调度 settings 服务 installSection(等待 settings 就绪)')\n}\n\n/**\n * 按命令目录构建 keybindings 显式键形状(每键独立默认值)。\n * @author ddj 2026年08月26号\n * @param z schemastery 命名空间\n * @returns keybindings 字段形状\n */\nfunction keybindingsShape(z: SettingsDeps['z']): Record<string, unknown> {\n const shape: Record<string, unknown> = {}\n for (const [id, chord] of Object.entries(KEYBINDING_DEFAULTS)) shape[id] = z.string().default(chord)\n return shape\n}\n\nfunction normalizeValue(value: unknown): string {\n if (typeof value !== 'string' || value.trim() === '') return FILE_OPEN_DEFAULT\n return value.trim()\n}\n\nfunction configValue(config: unknown): string {\n return normalizeValue((config as { fileOpenTool?: unknown } | undefined)?.fileOpenTool)\n}\n\n/** 配置/设置里的深链基址(缺省/非法回退默认值)。 */\nfunction baseValueOf(config: unknown): string {\n const raw = (config as { integrationBaseUrl?: unknown } | undefined)?.integrationBaseUrl\n return typeof raw === 'string' && raw.trim() ? raw.trim() : INTEGRATION_BASE_DEFAULT\n}\n\n/**\n * 安装设置 section(版本自适应;任一策略不可用返回 false 不抛错)。\n * @author ddj 2026年08月24号 / 2026年09月02号\n * @param ctx DSH host 上下文\n * @param ns 设置命名空间\n * @param entry 初始设置值\n * @param hooks 设置源绑定与变更回调\n * @param loader 依赖装载器(测试注入)\n * @returns 是否成功安装\n */\nexport async function installOpenSettingsSection(\n ctx: Ctx,\n ns: string,\n entry: FileOpenSettings,\n hooks: { setSource: (source: () => FileOpenSettings) => void; onChange: () => void },\n loader: SettingsDepsLoader = loadSettingsDeps,\n): Promise<boolean> {\n let deps: SettingsDeps | null = null\n try {\n deps = await loader()\n } catch {\n /* 装载失败按缺失处理 */\n }\n if (!deps) return false\n const schema = deps.z.object({\n fileOpenTool: deps.z.string().default(FILE_OPEN_DEFAULT),\n keybindings: deps.z.object(keybindingsShape(deps.z)).default({ ...KEYBINDING_DEFAULTS }),\n sidebarMinWidth: deps.z.number().default(300),\n integrationBaseUrl: deps.z.string().default(INTEGRATION_BASE_DEFAULT),\n // AI 内联补全(默认关;provider/model 空 = 自动路由;effort 空 = 跟随模型默认)\n aiInline: deps.z.boolean().default(AI_CONFIG_DEFAULT.enabled),\n aiProvider: deps.z.string().default(AI_CONFIG_DEFAULT.provider),\n aiModel: deps.z.string().default(AI_CONFIG_DEFAULT.model),\n aiEffort: deps.z.string().default(AI_CONFIG_DEFAULT.effort),\n })\n const strategy = await runSettingsInstall(ctx, ns, schema, entry, {\n setSource: (source) => hooks.setSource(source as () => FileOpenSettings),\n onChange: hooks.onChange,\n }, loader)\n return strategy === 'legacy' || strategy === 'service'\n}\n\n/** AI 配置脏值读取(settings 未就绪时回退默认)。 */\nfunction aiValueOf(stored: unknown): { enabled: boolean; provider: string; model: string; effort: string } {\n const raw = (stored ?? {}) as Record<string, unknown>\n return {\n enabled: raw.aiInline === true,\n provider: typeof raw.aiProvider === 'string' ? raw.aiProvider : AI_CONFIG_DEFAULT.provider,\n model: typeof raw.aiModel === 'string' ? raw.aiModel : AI_CONFIG_DEFAULT.model,\n effort: typeof raw.aiEffort === 'string' ? raw.aiEffort : AI_CONFIG_DEFAULT.effort,\n }\n}\n\n/**\n * 注册设置命名空间,并提供 host 侧的读取与更新状态。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文\n * @param config 插件组合配置\n * @param onChange 设置变化回调\n * @returns 设置状态(fileOpenTool 值 + AI 补全配置读写)\n */\nexport function setupOpenSettings(ctx: Ctx, config: unknown, onChange: (value: string) => void): FileOpenSettingsState & { ai: () => AiConfigView; aiUpdate: (patch: AiConfigPatch, expectedRevision?: number) => Promise<AiConfigView> } {\n let current = configValue(config)\n let revision: number | undefined\n let provider: SettingsProvider | undefined\n const notify = (value: unknown): void => { current = normalizeValue(value); onChange(current) }\n const syncRevision = (): void => {\n const descriptor = provider?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n revision = descriptor?.revision\n }\n const setSource = (source: () => FileOpenSettings): void => notify(source().fileOpenTool)\n const settingsChange = (): void => syncRevision()\n\n /** AI 配置当前值(settings 未就绪回退默认)。 */\n let aiCurrent: AiConfigView = { ...AI_CONFIG_DEFAULT }\n const aiSync = (): void => {\n const descriptor = provider?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const stored = descriptor?.value\n aiCurrent = stored !== undefined ? aiValueOf(stored) : aiCurrent\n }\n\n void installOpenSettingsSection(ctx, FILE_OPEN_SETTINGS_NS, { fileOpenTool: current, integrationBaseUrl: baseValueOf(config) }, {\n setSource: (source) => {\n notify(source().fileOpenTool)\n aiCurrent = aiValueOf(source())\n syncRevision()\n },\n onChange: settingsChange,\n })\n ctx.inject?.(['settings'], (settingsCtx: Ctx) => {\n provider = settingsCtx.get('settings')\n aiSync()\n syncRevision()\n })\n\n return {\n get value() { return current },\n get revision() { return revision },\n update: async (value: string, expectedRevision?: number): Promise<void> => {\n const next = normalizeValue(value)\n if (!provider?.update) { notify(next); return }\n await provider.update(FILE_OPEN_SETTINGS_NS, { fileOpenTool: next }, expectedRevision)\n const descriptor = provider.describe?.({ redactSecrets: true })?.find((item: { ns?: string; value?: unknown }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const stored = descriptor?.value as { fileOpenTool?: unknown } | undefined\n notify(stored?.fileOpenTool ?? next)\n syncRevision()\n },\n ai: () => aiCurrent,\n aiUpdate: async (patch: AiConfigPatch, expectedRevision?: number): Promise<AiConfigView> => {\n if (!provider?.update) {\n // settings 不可用:内存态生效(重启回落默认),保持与 fileOpenTool 的降级语义一致\n if (patch.enabled !== undefined) aiCurrent.enabled = patch.enabled\n if (patch.provider !== undefined) aiCurrent.provider = patch.provider\n if (patch.model !== undefined) aiCurrent.model = patch.model\n if (patch.effort !== undefined) aiCurrent.effort = patch.effort\n return aiCurrent\n }\n const stored = { ...aiCurrent }\n const body: Record<string, unknown> = {}\n if (patch.enabled !== undefined) { stored.enabled = patch.enabled; body.aiInline = patch.enabled }\n if (patch.provider !== undefined) { stored.provider = patch.provider; body.aiProvider = patch.provider }\n if (patch.model !== undefined) { stored.model = patch.model; body.aiModel = patch.model }\n if (patch.effort !== undefined) { stored.effort = patch.effort; body.aiEffort = patch.effort }\n await provider.update(FILE_OPEN_SETTINGS_NS, body, expectedRevision)\n aiSync()\n return aiCurrent\n },\n }\n}\n\nexport function normalizeFileOpenTool(value: unknown): string { return normalizeValue(value) }\n","/**\n * dsh-vscode-mode host — 开发形态管理(安装形态切换)。\n * 开发形态 = profile 中以 link: 依赖 + junction 指向工作区的安装(用于插件开发);\n * 关闭 = 改回版本依赖 + 删 junction + pnpm install 装配正式版。\n * 切换后需重启 DSH 生效(运行中的代码仍是旧形态)。\n * 与 compat.ts 存在模块环(devForm 用 pluginVersionOf、compat 用 readDevForm),\n * 双方仅在函数体内交叉使用,模块求值期无依赖,ESM 安全。\n * 作者 ddj 2026-08-24\n */\nimport { existsSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { homedir } from 'node:os'\nimport { PLUGIN_NAME, pluginVersionOf } from './compat.js'\nimport type { DevFormInfo } from './shared/compat.js'\nimport type { Ctx } from './store.js'\n\n/** 扫描 $DSH_HOME/profiles 找到依赖本插件的 profile 目录(无 env 依赖,多 profile 安全)。 */\nexport function findProfileDir(): string | undefined {\n const home = process.env.DSH_HOME ?? join(homedir(), '.dsh')\n try {\n for (const name of readdirSync(join(home, 'profiles'))) {\n const pkgFile = join(home, 'profiles', name, 'package.json')\n if (!existsSync(pkgFile)) continue\n try {\n const pkg = JSON.parse(readFileSync(pkgFile, 'utf8')) as { dependencies?: Record<string, unknown> } | undefined\n if (pkg?.dependencies?.[PLUGIN_NAME]) return dirname(pkgFile)\n } catch {\n /* 坏 manifest 跳过该 profile */\n }\n }\n } catch {\n /* profiles 目录不存在时放弃 */\n }\n return undefined\n}\n\n/**\n * 读取当前开发形态(manifest link: 判定)。\n * @author ddj 2026年08月24号\n * @returns 开发形态状态\n */\nexport function readDevForm(): DevFormInfo {\n const profileDir = findProfileDir()\n if (!profileDir) return { enabled: false }\n try {\n const text = readFileSync(join(profileDir, 'package.json'), 'utf8').replace(/^\\uFEFF/, '')\n const pkg = JSON.parse(text) as { dependencies?: Record<string, unknown> } | undefined\n const spec = pkg?.dependencies?.[PLUGIN_NAME]\n if (typeof spec === 'string' && spec.startsWith('link:')) {\n return { enabled: true, path: spec.slice('link:'.length) }\n }\n } catch {\n /* manifest 不可读视为非开发形态 */\n }\n return { enabled: false }\n}\n\n/**\n * 规划切换后的 manifest 文本(纯函数,可单测;非法 JSON 抛错)。\n * @author ddj 2026年08月24号\n * @param text 原 manifest 文本\n * @param enabled 目标形态(true=link:,false=版本)\n * @param path 工作区路径(开启时必填)\n * @param version 版本号(关闭时使用,写入 ^<version>)\n * @returns 新 manifest 文本(无 BOM,2 空格缩进)\n */\nexport function planManifest(text: string, enabled: boolean, path: string, version: string): string {\n const data = JSON.parse(text.replace(/^\\uFEFF/, '')) as { dependencies?: Record<string, unknown> }\n if (!data.dependencies || typeof data.dependencies !== 'object') {\n throw new Error('profile package.json 缺少 dependencies 字段')\n }\n data.dependencies[PLUGIN_NAME] = enabled ? 'link:' + path.replace(/\\\\/g, '/') : '^' + version\n return JSON.stringify(data, null, 2) + '\\n'\n}\n\n/** 建立或移除 node_modules 下的开发 junction(目标不存在时开启失败)。 */\nfunction applyJunction(profileDir: string, enabled: boolean, target: string): void {\n const linkDir = join(profileDir, 'node_modules', PLUGIN_NAME)\n if (existsSync(linkDir)) rmSync(linkDir, { recursive: true, force: true })\n if (!enabled) return\n if (!existsSync(target)) throw new Error('工作区路径不存在:' + target)\n symlinkSync(target, linkDir, 'junction')\n}\n\n/**\n * 切换开发形态:改 manifest → 建/删 junction → pnpm install(subprocess)。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文(subprocess 服务)\n * @param enabled 目标形态\n * @param path 工作区绝对路径(开启时必填)\n * @returns 切换结果(restart=true 表示需重启 DSH 生效)\n */\nexport async function setDevForm(ctx: Ctx, enabled: boolean, path?: string): Promise<{ ok: boolean; error?: string; restart: boolean }> {\n const profileDir = findProfileDir()\n if (!profileDir) return { ok: false, error: '未找到依赖本插件的 profile(检查 DSH_HOME/profiles)', restart: false }\n const current = readDevForm()\n const target = (path ?? current.path ?? '').replace(/\\\\/g, '/')\n if (enabled && !target) return { ok: false, error: '开启开发形态需要提供工作区路径(path 参数)', restart: false }\n if (enabled === current.enabled && (!enabled || target === current.path)) {\n return { ok: true, restart: false }\n }\n try {\n const pkgFile = join(profileDir, 'package.json')\n const version = pluginVersionOf()\n if (!version) return { ok: false, error: '读取插件版本失败,无法写入版本依赖', restart: false }\n const next = planManifest(readFileSync(pkgFile, 'utf8').replace(/^\\uFEFF/, ''), enabled, target, version)\n writeFileSync(pkgFile, next, 'utf8')\n applyJunction(profileDir, enabled, target)\n const installError = await runPnpmInstall(ctx, profileDir)\n return { ok: !installError, error: installError, restart: true }\n } catch (error) {\n return { ok: false, error: String(error), restart: false }\n }\n}\n\n/** 在 profile 目录执行 pnpm install(subprocess 契约:spawn({argv,cwd,stdio,graceMs}))。 */\nasync function runPnpmInstall(ctx: Ctx, profileDir: string): Promise<string | undefined> {\n const sub = ctx.get('subprocess')\n if (!sub || typeof sub.spawn !== 'function') return 'manifest/junction 已更新,但缺少 subprocess:请手动在 profile 目录运行 pnpm install'\n const handle = sub.spawn({\n argv: ['pnpm', 'install'],\n cwd: profileDir,\n stdio: { stdout: { maxBytes: 1 << 16 }, stderr: { maxBytes: 1 << 16 }, stdin: 'ignore' },\n graceMs: 120000,\n })\n const outcome = await handle.done\n const code = outcome?.exitCode ?? outcome?.code\n if (code !== 0) {\n const stderr = handle.collected?.stderr?.readFrom(0).text ?? ''\n return 'pnpm install 失败(exit ' + code + '):' + stderr.slice(0, 500)\n }\n return undefined\n}\n","/**\n * dsh-vscode-mode host — DSH 核心版本探测与区间匹配(版本适配机制的地基)。\n * 约定:以运行时可解析的 @deepseek-ai/dsh-settings 包版本代表 DSH 核心版本——\n * 核心包发布锁步同版(rc.2 / alpha.2 全树同版实证),且该包是插件动态依赖面、\n * exports 已放行 ./package.json。解析失败按候选降级(dsh-web-app / dsh-base / dsh),\n * 全部失败返回空串(报告显示\"未探测\",功能按能力探测运行)。\n * 纯函数(parse / compare / inRange / familyLabel)可在 node 环境单测。\n * 作者 ddj 2026-09-02\n */\nimport { readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\n\n/** 归一化版本:主/次/补丁 + 预发布标识数组(0.1.2-alpha.2 → pre=['alpha','2'])。 */\nexport interface DshVersion {\n major: number\n minor: number\n patch: number\n pre: string[]\n}\n\nconst VERSION_RE = /^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/\n\n/** 解析版本串;非法返回 null(不抛错)。 */\nexport function parseDshVersion(input: string): DshVersion | null {\n const match = VERSION_RE.exec(input.trim())\n if (!match) return null\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n pre: match[4] ? match[4].split('.') : [],\n }\n}\n\n/** 预发布标识比较:纯数字按值;数字段 < 字母段;字母按字典序(semver 规则)。 */\nfunction comparePreId(a: string, b: string): number {\n const numericA = /^\\d+$/.test(a)\n const numericB = /^\\d+$/.test(b)\n if (numericA && numericB) return Number(a) - Number(b)\n if (numericA !== numericB) return numericA ? -1 : 1\n return a < b ? -1 : a > b ? 1 : 0\n}\n\n/** 比较两个已解析版本:a<b → -1;相等 → 0;a>b → 1。 */\nexport function compareDshVersions(a: DshVersion, b: DshVersion): number {\n for (const key of ['major', 'minor', 'patch'] as const) {\n if (a[key] !== b[key]) return a[key] < b[key] ? -1 : 1\n }\n const samePre = a.pre.length === b.pre.length && a.pre.every((part, index) => part === b.pre[index])\n if (samePre) return 0\n if (a.pre.length === 0) return 1\n if (b.pre.length === 0) return -1\n const length = Math.max(a.pre.length, b.pre.length)\n for (let i = 0; i < length; i++) {\n const left = a.pre[i]\n const right = b.pre[i]\n if (left === undefined) return -1\n if (right === undefined) return 1\n const cmp = comparePreId(left, right)\n if (cmp !== 0) return cmp\n }\n return 0\n}\n\n/** 版本区间(含端点):from/to 为空表示该侧不设界。 */\nexport interface DshRange {\n from?: string\n to?: string\n}\n\n/** 版本是否落在区间内(入参解析失败一律不命中)。 */\nexport function inDshRange(version: DshVersion | null | undefined, range: DshRange): boolean {\n if (!version) return false\n if (range.from) {\n const lower = parseDshVersion(range.from)\n if (!lower || compareDshVersions(version, lower) < 0) return false\n }\n if (range.to) {\n const upper = parseDshVersion(range.to)\n if (!upper || compareDshVersions(version, upper) > 0) return false\n }\n return true\n}\n\n/** 版本线标签:报告与文档展示版本归属;不可解析返回 '未知'。 */\nexport function familyLabel(input: string): string {\n const version = parseDshVersion(input)\n if (!version) return '未知'\n if (inDshRange(version, { from: '0.1.3-alpha.1' })) return '0.1.3-alpha 及更新(对话文件链接=remote.session.openWorkspacePath)'\n if (inDshRange(version, { from: '0.1.2-alpha.1' })) return '0.1.2-alpha 及更新(设置 API=settings.installSection)'\n return '0.1.0/0.1.1 rc 线(设置 API=installSettingsSection)'\n}\n\n/** 探测候选:按与插件运行环境相关性排序,逐个尝试解析 package.json。 */\nconst VERSION_CANDIDATES = [\n '@deepseek-ai/dsh-settings/package.json',\n '@deepseek-ai/dsh-web-app/package.json',\n '@deepseek-ai/dsh-base/package.json',\n '@deepseek-ai/dsh/package.json',\n]\n\nlet detectedVersion: string | undefined\n\n/** 探测运行中 DSH 核心版本(模块级缓存;失败空串,不抛错)。 */\nexport function detectDshVersion(): string {\n if (detectedVersion !== undefined) return detectedVersion\n detectedVersion = ''\n const require = createRequire(import.meta.url)\n for (const specifier of VERSION_CANDIDATES) {\n try {\n const file = require.resolve(specifier)\n const pkg = JSON.parse(readFileSync(file, 'utf8')) as { version?: unknown }\n if (typeof pkg.version === 'string' && parseDshVersion(pkg.version) !== null) {\n detectedVersion = pkg.version\n break\n }\n } catch {\n /* exports 未放行或包缺失:尝试下一个候选 */\n }\n }\n return detectedVersion\n}\n","/**\n * dsh-vscode-mode RPC contract — method names, per-method request/ok payloads,\n * and the typed handler map shared by the host dispatcher and the client\n * fetch wrapper. 载荷形状与历史实现一字不差,仅把隐式约定类型化。\n *\n * Purity rule: no node/react imports (same as types.ts).\n * 作者 ddj 2026-08-20\n */\nimport type {\n ArchiveBatch,\n ArchiveEntry,\n RecordView,\n StaleHunk,\n} from './types.js'\nimport type { MpcConfig, MpcProject, MpcProjectSaveInput, MpcServer } from './mcp.js'\nimport type { CompatReport, DevFormInfo } from './compat.js'\nimport type { ShellIntegrationStatus, UnityListPayload, UnityProjectEntry } from './integration.js'\nimport type { RuleInfo, RuleProject, RuleRefInput, RuleSaveInput } from './rules.js'\nimport type { LspEnvInstallState, LspExtInfo, LspExtUpdate, LspHover, LspLocation, LspMarketItem, LspPosition, LspSemanticTokens, LspServerStatus, LspSymbol } from './lsp.js'\nimport type { AiConfigPatch, AiConfigView, AiDirectoryView, AiInlineRequest, AiInlineResult } from './ai.js'\n\n/** webServer 精确路由。 */\nexport const RPC_PATH = '/edrv/rpc'\n\n/**\n * 图片扩展名(小写、无点)→ MIME。edrv.read base64 响应与 client 图片预览共用,\n * 收敛在此避免 host/client 两处漂移。\n * @author ddj 2026年09月08号\n */\nexport const IMAGE_MIME: Record<string, string> = {\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n webp: 'image/webp',\n bmp: 'image/bmp',\n ico: 'image/x-icon',\n avif: 'image/avif',\n svg: 'image/svg+xml',\n}\n\n/**\n * 路径 → 图片 MIME:按 basename 扩展名小写查 {@link IMAGE_MIME},未命中回退 application/octet-stream。\n * @author ddj 2026年09月08号\n * @param path 文件路径(`/` 或 `\\` 分隔均可)\n * @returns MIME 字符串\n */\nexport function imageMimeOf(path: string): string {\n const base = String(path || '').split(/[\\\\/]/).pop() || ''\n const dot = base.lastIndexOf('.')\n const ext = dot > 0 ? base.slice(dot + 1).toLowerCase() : ''\n return IMAGE_MIME[ext] ?? 'application/octet-stream'\n}\n\n/** PDF 统一 MIME(host base64 响应与 client PDF 面板同源,避免两处漂移)。 */\nexport const PDF_MIME = 'application/pdf'\n\n/**\n * 路径 → 二进制预览 MIME:PDF 特判 {@link PDF_MIME},其余走图片表回退 octet-stream。\n * @author ddj 2026年09月22号\n * @param path 文件路径(`/` 或 `\\` 分隔均可)\n * @returns MIME 字符串\n */\nexport function binaryMimeOf(path: string): string {\n const base = String(path || '').split(/[\\\\/]/).pop() || ''\n const dot = base.lastIndexOf('.')\n if (dot > 0 && base.slice(dot + 1).toLowerCase() === 'pdf') return PDF_MIME\n return imageMimeOf(path)\n}\n\n/** 决策作用域:call=整条记录,hunk=单个差异块。 */\nexport type RpcScope = 'call' | 'hunk'\n\n/** 目录树单项(edrv.listDir 返回;path 相对工作区根,'/' 分隔)。 */\nexport interface TreeEntry {\n name: string\n path: string\n type: 'file' | 'directory' | 'other'\n size?: number\n}\n\n/** 内容搜索单条命中(edrv.searchContent 返回;path 相对工作区根,列为 1-based UTF-16)。 */\nexport interface SearchContentMatch {\n path: string\n line: number\n startColumn: number\n endColumn: number\n text: string\n}\n\n// --region 会话性能管理(edrv.perf.*)\n/** 一个已持久化会话的体积/活跃信息(edrv.perf.inventory 每行)。 */\nexport interface PerfSession {\n sessionId: string\n workspaceKey: string\n bytes: number\n mtime: number\n active: boolean\n}\n\n/** 一个工作区的会话聚合(edrv.perf.inventory)。 */\nexport interface PerfWorkspace {\n workspaceKey: string\n sessionCount: number\n totalBytes: number\n minMtime: number\n maxMtime: number\n}\n\n/** 会话盘点汇总。 */\nexport interface PerfTotals {\n workspaces: number\n sessions: number\n totalBytes: number\n}\n\n/** 一次移出/恢复操作中的单个会话条目。 */\nexport interface PerfMoveItem {\n workspaceKey: string\n sessionId: string\n bytes: number\n}\n\n/** 一次移出操作的失败项。 */\nexport interface PerfMoveFailure {\n workspaceKey: string\n sessionId: string\n error: string\n}\n\n/** 侧车摘要(edrv.perf.sidecarSummary):紧凑关键字段,不整份读 sidecar 进对话。 */\nexport interface SidecarPerfSummary {\n active: number\n pendingByFile: { path: string; pending: number }[]\n archiveBytes: number\n}\n// --endregion\n\n/** 一条批量决策项(decideBatch 的 items 元素,与 accept/reject 单条参数同构)。 */\nexport interface DecideItem {\n callId: string\n scope?: RpcScope\n hunkIndex?: number\n decision: 'accepted' | 'rejected'\n}\n\n/** 批量决策逐项结果。 */\nexport interface DecideResult {\n callId: string\n ok: boolean\n error?: string\n record?: RecordView\n}\n\n/** 每个方法的请求参数(sessionId 为公共可选字段)。 */\nexport interface RpcRequestMap {\n 'edrv.list': { sessionId?: string; callIds?: string[]; skipStale?: boolean }\n 'edrv.accept': { sessionId?: string; callId: string; scope?: RpcScope; hunkIndex?: number }\n 'edrv.reject': { sessionId?: string; callId: string; scope?: RpcScope; hunkIndex?: number }\n 'edrv.decideBatch': { sessionId?: string; items: DecideItem[] }\n 'edrv.read': { sessionId?: string; path: string; encoding?: 'base64' }\n 'edrv.original': { sessionId?: string; path: string }\n 'edrv.save': { sessionId?: string; path: string; content: string }\n 'edrv.saveBinary': { sessionId?: string; path: string; content: string; encoding: 'base64' }\n 'edrv.archiveList': { sessionId?: string }\n 'edrv.archiveRead': { sessionId?: string; path?: string }\n 'edrv.rollback': { sessionId?: string; path: string; batch?: number }\n 'edrv.debug': { sessionId?: string; text: string }\n 'edrv.searchFiles': { sessionId?: string; query: string }\n 'edrv.searchContent': { sessionId?: string; query: string; matchCase?: boolean; wholeWord?: boolean; regex?: boolean; maxResults?: number; include?: string[]; exclude?: string[] }\n 'edrv.listDir': { sessionId?: string; path: string; force?: boolean }\n 'edrv.revealInExplorer': { sessionId?: string; path: string }\n 'mcp.list': {}\n 'mcp.save': { config: MpcConfig }\n 'mcp.remove': { id: string }\n 'mcp.toggle': { id: string; enabled: boolean }\n 'mcp.refresh': { id: string }\n 'mcp.projects': {}\n 'mcp.projectSave': MpcProjectSaveInput\n 'mcp.projectRemove': { workspacePath: string; serverName: string }\n 'mcp.projectToggle': { workspacePath: string; serverName: string; enabled: boolean }\n 'mcp.projectRefresh': { workspacePath: string; serverName: string }\n 'vscode.fileOpenSettingsGet': {}\n 'vscode.fileOpenSettingsUpdate': { fileOpenTool: string; integrationBaseUrl?: string; expectedRevision?: number }\n 'edrv.integration.status': {}\n 'edrv.integration.register': {}\n 'edrv.integration.unregister': {}\n 'edrv.unity.list': {}\n 'edrv.unity.add': { path: string }\n 'edrv.unity.remove': { path: string }\n 'edrv.unity.install': { path: string }\n 'edrv.externalStat': { path: string }\n 'edrv.external.handoff': { paths: string[]; line?: number; column?: number }\n 'edrv.external.pending': {}\n 'edrv.external.pendingState': { token: string; take?: boolean }\n 'vscode.devFormGet': {}\n 'vscode.devFormSet': { enabled: boolean; path?: string }\n 'compat': {}\n 'edrv.lsp.status': { sessionId?: string }\n 'edrv.lsp.detect': {}\n 'edrv.lsp.sync': { sessionId?: string; path: string; text: string; version: number }\n 'edrv.lsp.close': { sessionId?: string; path: string }\n 'edrv.lsp.definition': { sessionId?: string; path: string; position: LspPosition }\n 'edrv.lsp.references': { sessionId?: string; path: string; position: LspPosition; includeDeclaration?: boolean }\n 'edrv.lsp.documentSymbol': { sessionId?: string; path: string }\n 'edrv.lsp.workspaceSymbol': { sessionId?: string; query: string }\n 'edrv.lsp.hover': { sessionId?: string; path: string; position: LspPosition }\n 'edrv.lsp.semanticTokens': { sessionId?: string; path: string }\n 'edrv.lsp.redetect': { languageId: string }\n 'edrv.lsp.envInstall': { languageId: string; id: string }\n 'edrv.lsp.envState': {}\n 'edrv.lsp.configGet': {}\n 'edrv.lsp.configUpdate': { languageId: string; enabled?: boolean; command?: string; path?: string }\n 'edrv.lsp.ext.list': {}\n 'edrv.lsp.ext.install': { vsixPath?: string; namespace?: string; name?: string; version?: string }\n 'edrv.lsp.ext.uninstall': { id: string }\n 'edrv.lsp.ext.update': { id: string }\n 'edrv.lsp.ext.updates': {}\n 'edrv.lsp.ext.market': { query: string; size?: number }\n 'edrv.ai.inline': AiInlineRequest\n 'edrv.ai.models': { force?: boolean }\n 'edrv.ai.configGet': {}\n 'edrv.ai.configUpdate': AiConfigPatch\n 'edrv.perf.inventory': { sessionId?: string }\n 'edrv.perf.sessionSize': { sessionId?: string; cwd: string }\n 'edrv.perf.movePlan': { workspaceKey?: string; sessionIds?: string[]; minBytes?: number; olderThanDays?: number }\n 'edrv.perf.moveOut': { workspaceKey: string; sessionIds: string[]; dryRun?: boolean }\n 'edrv.perf.restore': { workspaceKey: string; sessionId: string }\n 'edrv.perf.purgeArchive': { olderThanDays: number }\n 'edrv.perf.sidecarSummary': { sessionId?: string }\n 'edrv.perf.configGet': {}\n 'edrv.perf.configApply': {}\n 'edrv.perf.configUndo': {}\n 'rules.list': {}\n 'rules.read': RuleRefInput\n 'rules.save': RuleSaveInput\n 'rules.remove': RuleRefInput\n 'rules.toggle': RuleRefInput & { enabled: boolean }\n}\n\nexport type RpcMethod = keyof RpcRequestMap\n\n/** 每个方法成功(ok:true)时的附加载荷。 */\nexport interface RpcOkMap {\n 'edrv.list': { records: RecordView[] }\n 'edrv.accept': { record: RecordView }\n 'edrv.reject': { record: RecordView }\n 'edrv.decideBatch': { results: DecideResult[] }\n 'edrv.read': { content: string; size: number; encoding?: 'base64'; mime?: string }\n 'edrv.original': { content: string; size: number; stale: StaleHunk[]; fallback: boolean }\n 'edrv.save': object\n 'edrv.saveBinary': object\n 'edrv.archiveList': { entries: ArchiveEntry[] }\n 'edrv.archiveRead': { batches: ArchiveBatch[] }\n 'edrv.rollback': { path: string; batch: number | null }\n 'edrv.debug': object\n 'edrv.searchFiles': { files: string[]; truncated: boolean }\n 'edrv.searchContent': { matches: SearchContentMatch[]; truncated: boolean; warning?: string }\n 'edrv.listDir': { root: string; path: string; entries: TreeEntry[] }\n 'edrv.revealInExplorer': { revealed: string }\n 'mcp.list': { servers: MpcServer[] }\n 'mcp.save': { server: MpcServer }\n 'mcp.remove': object\n 'mcp.toggle': { server: MpcServer }\n 'mcp.refresh': { server: MpcServer }\n 'mcp.projects': { projects: MpcProject[] }\n 'mcp.projectSave': { project: MpcProject }\n 'mcp.projectRemove': { project: MpcProject }\n 'mcp.projectToggle': { project: MpcProject }\n 'mcp.projectRefresh': { project: MpcProject }\n 'vscode.fileOpenSettingsGet': { fileOpenTool: string; integrationBaseUrl: string; revision?: number }\n 'vscode.fileOpenSettingsUpdate': { fileOpenTool: string; integrationBaseUrl: string; revision?: number }\n 'edrv.integration.status': ShellIntegrationStatus\n 'edrv.integration.register': ShellIntegrationStatus\n 'edrv.integration.unregister': ShellIntegrationStatus\n 'edrv.unity.list': UnityListPayload\n 'edrv.unity.add': { project: UnityProjectEntry }\n 'edrv.unity.remove': object\n 'edrv.unity.install': { project: UnityProjectEntry }\n 'edrv.externalStat': { kind: 'file' | 'directory' | 'missing' }\n 'edrv.external.handoff': { clients: number; token: string }\n 'edrv.external.pending': { open: { paths: string[]; line?: number; column?: number } | null }\n 'edrv.external.pendingState': { delivered: boolean }\n 'vscode.devFormGet': { devForm: DevFormInfo }\n 'vscode.devFormSet': { devForm: DevFormInfo; restart: boolean }\n 'compat': { report: CompatReport }\n 'edrv.lsp.status': { servers: LspServerStatus[] }\n 'edrv.lsp.detect': { servers: LspServerStatus[] }\n 'edrv.lsp.sync': object\n 'edrv.lsp.close': object\n 'edrv.lsp.definition': { locations: LspLocation[]; truncated?: boolean }\n 'edrv.lsp.references': { locations: LspLocation[]; truncated?: boolean }\n 'edrv.lsp.documentSymbol': { symbols: LspSymbol[] }\n 'edrv.lsp.workspaceSymbol': { symbols: LspSymbol[]; truncated?: boolean }\n 'edrv.lsp.hover': { hover?: LspHover }\n 'edrv.lsp.semanticTokens': { tokens?: LspSemanticTokens }\n 'edrv.lsp.redetect': { servers: LspServerStatus[] }\n 'edrv.lsp.envInstall': { started: boolean }\n 'edrv.lsp.envState': { states: LspEnvInstallState[] }\n 'edrv.lsp.configGet': { config: Record<string, unknown> }\n 'edrv.lsp.configUpdate': { config: Record<string, unknown>; servers?: LspServerStatus[] }\n 'edrv.lsp.ext.list': { extensions: LspExtInfo[] }\n 'edrv.lsp.ext.install': { extension: LspExtInfo; updated?: boolean }\n 'edrv.lsp.ext.uninstall': object\n 'edrv.lsp.ext.update': { extension: LspExtInfo; updated: boolean }\n 'edrv.lsp.ext.updates': { updates: LspExtUpdate[] }\n 'edrv.lsp.ext.market': { extensions: LspMarketItem[] }\n 'edrv.ai.inline': AiInlineResult\n 'edrv.ai.models': AiDirectoryView\n 'edrv.ai.configGet': AiConfigView\n 'edrv.ai.configUpdate': AiConfigView\n 'edrv.perf.inventory': { workspaces: PerfWorkspace[]; sessions: PerfSession[]; totals: PerfTotals; activeIds: string[] }\n 'edrv.perf.sessionSize': { bytes: number; exists: boolean }\n 'edrv.perf.movePlan': { items: PerfMoveItem[]; reclaimedBytes: number }\n 'edrv.perf.moveOut': { moved: PerfMoveItem[]; failures: PerfMoveFailure[]; reclaimedBytes: number }\n 'edrv.perf.restore': { restored: boolean; error?: string }\n 'edrv.perf.purgeArchive': { removed: number; reclaimedBytes: number }\n 'edrv.perf.sidecarSummary': SidecarPerfSummary\n 'edrv.perf.configGet': { profileDir?: string; patchPath?: string; applied: boolean; block: string; backup?: string }\n 'edrv.perf.configApply': { applied: boolean; backup: string; restart: boolean }\n 'edrv.perf.configUndo': { restored: boolean; error?: string; backup?: string }\n 'rules.list': { user: RuleInfo[]; projects: RuleProject[] }\n 'rules.read': { content: string }\n 'rules.save': { rule: RuleInfo }\n 'rules.remove': object\n 'rules.toggle': { rule: RuleInfo }\n}\n\n/** 统一响应:{ok:true, ...payload} 或 {ok:false, error}。 */\nexport type RpcResult<M extends RpcMethod> =\n | ({ ok: true } & RpcOkMap[M])\n | { ok: false; error: string }\n\n/** 每个方法的 handler 签名(host 分发表与 client 类型检查共用)。 */\nexport type RpcHandler<M extends RpcMethod> = (\n args: RpcRequestMap[M],\n) => Promise<RpcResult<M>>\n\n/** host RPC 分发表:method → handler。 */\nexport type RpcHandlerMap = {\n [M in RpcMethod]: RpcHandler<M>\n}\n","/**\n * dsh-vscode-mode host — 路径常量与动态路径统一出口(PathConst)。\n * 所有 host 侧文件路径/缓存键/路由前缀从这里取,避免散落内联:\n * - 静态:插件缓存根(~/.dsh/dsh-vscode-mode/cache,下分 workspace/ 工作区级与\n * user/ 用户级)、日志根、工作区侧车名、路由前缀、静态资源目录(import.meta.url 派生)\n * - 动态:每工作区树缓存文件(workspace/<id>/tree.v<schema>.json)、home 解析\n * (DSH_HOME → ~/.dsh)\n * - 清理:缓存 sweep(分级:工作区级按版本/TTL/空目录、用户级按版本/保留期、根级残留)\n * 纯函数可单测;raw fs 写入与引擎自身插件(settings-file 用 node:fs + DSH_HOME)一致。\n * 作者 ddj 2026-09-01\n */\nimport { createHash } from 'node:crypto'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { readdir, rm, stat } from 'node:fs/promises'\nimport { RPC_PATH } from './shared/rpc.js'\n\n// --region 常量\n/** 插件 id(也是 .dsh 下插件工作区目录名)。 */\nexport const PLUGIN_ID = 'dsh-vscode-mode'\n/** DSH 工作区目录名(默认 home 下)。 */\nexport const DSH_DIR_NAME = '.dsh'\n/** home 覆盖环境变量(与引擎 resolveDshHome 一致)。 */\nexport const DSH_HOME_ENV = 'DSH_HOME'\n/** 树缓存 schema 版本(文件名携带;版本递增即触发旧版清理)。 */\nexport const TREE_CACHE_SCHEMA = 1\n/** LSP provider 发现缓存 schema 版本(格式变更即递增,旧文件自动失效)。 */\nexport const LSP_SPEC_CACHE_SCHEMA = 4\n/** 树缓存保留期:超期文件视为废弃(工作区搬迁/废弃残留)。 */\nexport const TREE_RETENTION_MS = 30 * 24 * 60 * 60 * 1000\n/** 插件缓存目录总预算:超限按 mtime 从旧到新删文件,防任意增长撑爆磁盘(最后兜底)。 */\nexport const CACHE_TOTAL_CAP = 200 * 1024 * 1024\n\n/** 工作区根侧车:审查记录(用户数据,随项目走,不迁移)。 */\nexport const SIDECAR = '.dsh-edit-review.json'\n/** 工作区根侧车:归档(用户数据)。 */\nexport const SIDECAR_ARCHIVE = '.dsh-edit-review-archive.json'\n/** 旧 debug 日志文件名(工作区,迁移后由插件清理)。 */\nexport const DEBUG_LOG = '.dsh-edit-review-debug.log'\n/** 旧树缓存 sidecar 名(工作区,迁移后由插件清理;缓存可重建,删除无损)。 */\nexport const LEGACY_TREE_SIDECARS = ['.dsh-edit-review-tree.json', '.dsh-vscode-mode-tree.json']\n\n/** RPC 精确路由(shared 定义,这里统一出口)。 */\nexport { RPC_PATH }\n/** 路由前缀(兼容性检查用)。 */\nexport const ROUTE_PREFIX = '/edrv'\n/** Monaco 静态资源前缀。 */\nexport const VENDOR_PREFIX = '/edrv/vendor'\n// --endregion\n\n/** 稳定短哈希(cwd → 缓存文件名段;sha1 截断,跨运行稳定)。 */\nexport function hashOf(text: string): string {\n return createHash('sha1').update(String(text)).digest('hex').slice(0, 16)\n}\n\n// --region DSH 会话定位编码\n/**\n * 可读安全路径段编码:非安全码位 → ~XXXX 大写十六进制(`~` 本身也转义)。\n * 与 DSH 引擎 dsh-session-persistence-jsonl 的 encodeSegment 逐字节一致,\n * 用于从 cwd/id 反推 `~/.dsh/sessions` 下的会话目录,纯函数可单测。\n * @author ddj 2026年09月02号\n * @param raw 原始路径段(非空)\n * @returns 路径安全段(`.`/`..` 特判为 ~002E / ~002E~002E)\n */\nexport function encodeSegment(raw: string): string {\n if (raw.length === 0) throw new Error('cannot encode an empty path segment')\n if (raw === '.') return '~002E'\n if (raw === '..') return '~002E~002E'\n let out = ''\n for (let i = 0; i < raw.length; i++) {\n const code = raw.charCodeAt(i)\n const ch = String.fromCharCode(code)\n if (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) out += ch\n else out += '~' + code.toString(16).toUpperCase().padStart(4, '0')\n }\n return out\n}\n\n/**\n * DSH 工作区目录键:cwd → `--<可读键>--`。分隔符(/ \\ :)折叠为单个 `-`,\n * 其余非安全码位转 ~XXXX,`--` 包裹、251 截断。与引擎 projectKey 一致。\n * @author ddj 2026年09月02号\n * @param cwd 会话工作区绝对路径(非空)\n * @returns `~/.dsh/sessions` 下的工作区目录名\n */\nexport function sessionWorkspaceKey(cwd: string): string {\n if (cwd.length === 0) throw new Error('cannot encode an empty project path')\n let readable = ''\n let separatorRun = false\n for (let i = 0; i < cwd.length; i++) {\n const code = cwd.charCodeAt(i)\n const ch = String.fromCharCode(code)\n if (ch === '/' || ch === '\\\\' || ch === ':') {\n if (!separatorRun) readable += '-'\n separatorRun = true\n } else if (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) {\n readable += ch\n separatorRun = false\n } else {\n readable += '~' + code.toString(16).toUpperCase().padStart(4, '0')\n separatorRun = false\n }\n }\n return `--${(readable.replace(/^-+/, '') || 'root').slice(0, 251)}--`\n}\n\n/** DSH 会话目录段:id → 路径安全段(与引擎 encodeSegment 一致)。 */\nexport function sessionIdSegment(id: string): string {\n return encodeSegment(id)\n}\n\n/** DSH 会话根目录(~/.dsh/sessions;引擎 dsh-base 默认 root)。 */\nexport function sessionsRoot(home = dshHome()): string {\n return join(home, 'sessions')\n}\n// --endregion\n\n/**\n * 解析 DSH home:DSH_HOME(去空白)→ ~/.dsh。\n * @author ddj 2026年09月01号\n * @param env 环境映射(缺省 process.env;测试可注入)\n * @returns 归一化的 DSH home 绝对路径\n */\nexport function dshHome(env: Record<string, string | undefined> = process.env): string {\n const value = env[DSH_HOME_ENV]\n if (value && value.trim()) return value\n return join(homedir(), DSH_DIR_NAME)\n}\n\n/** 插件缓存根(~/.dsh/dsh-vscode-mode/cache,下分 workspace/ 与 user/ 两级)。 */\nexport function pluginCacheRoot(home = dshHome()): string {\n return join(home, PLUGIN_ID, 'cache')\n}\n\n/** 工作区级缓存目录:按工作区 id(cwd hash)隔离,换工作区即失效。 */\nexport function workspaceCacheDir(workspaceId: string, home = dshHome()): string {\n return join(pluginCacheRoot(home), 'workspace', workspaceId)\n}\n\n/** 用户级缓存目录(跨工作区共享;当前无实例,预留供全局偏好类缓存使用)。 */\nexport function userCacheDir(home = dshHome()): string {\n return join(pluginCacheRoot(home), 'user')\n}\n\n/** LSP provider 发现结果缓存文件(用户级:user/lsp-specs.v<schema>.json,跨会话/跨重启共享)。 */\nexport function lspSpecCacheFile(home = dshHome(), schema = LSP_SPEC_CACHE_SCHEMA): string {\n return join(userCacheDir(home), 'lsp-specs.v' + schema + '.json')\n}\n\n/** 插件日志根(~/.dsh/dsh-vscode-mode/logs,用户级)。 */\nexport function pluginLogRoot(home = dshHome()): string {\n return join(home, PLUGIN_ID, 'logs')\n}\n\n/** 每工作区树缓存文件(工作区级:workspace/<id>/tree.v<schema>.json,文件名含版本便于 sweep)。 */\nexport function treeCacheFile(cwd: string, home = dshHome(), schema = TREE_CACHE_SCHEMA): string {\n return join(workspaceCacheDir(hashOf(cwd), home), 'tree.v' + schema + '.json')\n}\n\n/** 每工作区 debug 日志文件(用户级日志根下,按 cwd hash 隔离)。 */\nexport function debugLogFile(cwd: string, home = dshHome()): string {\n return join(pluginLogRoot(home), 'debug.' + hashOf(cwd) + '.log')\n}\n\n/** 插件包 assets 目录(import.meta.url 派生;config.imageDir 可覆盖,见 imageDirOf)。 */\nexport function assetsDirOf(moduleUrl: string): string {\n return join(dirname(fileURLToPath(moduleUrl)), '..', 'assets')\n}\n\n/** Monaco AMD 静态目录(随包发布)。 */\nexport function vendorDirOf(moduleUrl: string): string {\n return join(assetsDirOf(moduleUrl), 'vendor')\n}\n\n/** 图标目录:config.imageDir 覆盖优先,否则插件包 assets/。 */\nexport function imageDirOf(config: unknown, moduleUrl: string): string {\n const cfg = config as { imageDir?: unknown } | undefined\n if (cfg && typeof cfg.imageDir === 'string' && cfg.imageDir) return cfg.imageDir.replace(/\\\\/g, '/')\n return assetsDirOf(moduleUrl)\n}\n\n// --region 缓存清理\n/** 树缓存文件名 → schema 版本(不匹配返回 null)。 */\nexport function treeSchemaOf(filename: string): number | null {\n const m = /^tree\\.v(\\d+)\\./.exec(filename)\n return m ? Number(m[1]) : null\n}\n\n/** 按「schema 版本 + 保留期」清扫某目录内文件(目录级,返回相对路径清单)。 */\nasync function sweepDirFiles(dir: string, removed: string[], now: number, dropAll: boolean): Promise<void> {\n const names = await readdir(dir).catch(() => [])\n for (const name of names) {\n const full = join(dir, name)\n let drop = dropAll\n if (!drop) {\n const schema = treeSchemaOf(name)\n if (schema === null) drop = true // 未知残留\n else if (schema !== TREE_CACHE_SCHEMA) drop = true // 旧版本\n else {\n try {\n const info = await stat(full)\n if (now - info.mtimeMs > TREE_RETENTION_MS) drop = true\n } catch (error) { drop = true }\n }\n }\n if (!drop) continue\n try {\n await rm(full, { force: true })\n removed.push(name)\n } catch (error) { /* 删除失败静默 */ }\n }\n}\n\n/** 清扫工作区级缓存:逐工作区目录按版本/TTL 清文件,空目录删除。 */\nasync function sweepWorkspaceTier(dir: string, removed: string[], now: number): Promise<void> {\n const ids = await readdir(dir).catch(() => [])\n for (const id of ids) {\n const wsDir = join(dir, id)\n await sweepDirFiles(wsDir, removed, now, false)\n const rest = await readdir(wsDir).catch(() => [])\n if (!rest.length) await rm(wsDir, { recursive: true, force: true }).catch(() => {})\n }\n}\n\n/** 总预算兜底:递归收集全部缓存文件,按 mtime 从旧到新删,直到总大小 ≤ 预算。 */\nasync function sweepByTotalCap(root: string, removed: string[], cap: number): Promise<void> {\n const files: { path: string; mtime: number; size: number }[] = []\n const walk = async (dir: string): Promise<void> => {\n const names = await readdir(dir).catch(() => [])\n for (const name of names) {\n const full = join(dir, name)\n try {\n const info = await stat(full)\n if (info.isDirectory()) await walk(full)\n else files.push({ path: full, mtime: info.mtimeMs, size: info.size })\n } catch (error) { /* 忽略不可读项 */ }\n }\n }\n await walk(root)\n let total = files.reduce((sum, f) => sum + f.size, 0)\n files.sort((a, b) => a.mtime - b.mtime)\n for (const f of files) {\n if (total <= cap) break\n try {\n await rm(f.path, { force: true })\n total -= f.size\n removed.push(f.path.slice(root.length + 1))\n } catch (error) { /* 删除失败静默 */ }\n }\n}\n\n/**\n * 清理插件缓存根(分级 + 总预算兜底):\n * - 根级残留文件(旧扁平格式/未知)→ 删\n * - workspace/ 工作区级 → 按「schema 版本 + 保留期」清文件,空目录删除\n * - user/ 用户级 → 按「schema 版本 + 保留期」清文件\n * - 总大小超预算 → 按最旧先删(最后防线,防任意增长撑爆磁盘)\n * best-effort 静默。\n * @author ddj 2026年09月01号\n * @param home DSH home(测试可注入)\n * @param cap 总预算字节数(缺省 CACHE_TOTAL_CAP;测试可注入小预算)\n * @returns 删除的文件相对路径清单\n */\nexport async function sweepTreeCache(home = dshHome(), cap = CACHE_TOTAL_CAP): Promise<string[]> {\n const dir = pluginCacheRoot(home)\n const names = await readdir(dir).catch(() => [])\n if (!names.length) return []\n const removed: string[] = []\n const now = Date.now()\n await Promise.all(names.map(async (name) => {\n const full = join(dir, name)\n try {\n const info = await stat(full)\n if (info.isDirectory()) {\n if (name === 'workspace') await sweepWorkspaceTier(full, removed, now)\n else if (name === 'user') await sweepDirFiles(full, removed, now, false)\n else {\n await rm(full, { recursive: true, force: true })\n removed.push(name)\n }\n } else {\n await rm(full, { force: true })\n removed.push(name) // 根级残留(迁移前扁平格式/未知文件)\n }\n } catch (error) { /* stat 失败忽略 */ }\n }))\n await sweepByTotalCap(dir, removed, cap)\n return removed\n}\n// --endregion\n","/**\n * dsh-vscode-mode host — 兼容层:与其他插件 / DSH 版本的统一探测、适配、护栏与自诊断。\n * 职责:身份常量(包名 / MCP 条目前缀 / 路由前缀)、外部插件探测、路由冲突与重复装配检测、\n * 兼容性报告构建(RPC edrv.compat 与启动日志共用)。\n * 注意:与 mcp.ts 存在模块环(compat 提供身份常量、mcp 提供 entriesOf),\n * 双方仅在函数体内交叉使用导出,模块求值期无依赖,ESM 安全。\n * 作者 ddj 2026-08-24\n */\nimport { readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { entriesOf } from './mcp.js'\nimport { loadSettingsDeps, settingsInstallNote, settingsInstallStrategy } from './fileOpenSettings.js'\nimport { readDevForm } from './devForm.js'\nimport { compareDshVersions, detectDshVersion, familyLabel, parseDshVersion } from './dshVersion.js'\nimport type { CompatAdapter, CompatReport } from './shared/compat.js'\nimport type { Ctx } from './store.js'\nimport { ROUTE_PREFIX } from './paths.js'\n\nexport { ROUTE_PREFIX }\n\nexport const PLUGIN_NAME = 'dsh-vscode-mode'\nexport const MCP_PACKAGE = '@deepseek-ai/dsh-mcp-client'\n/** 项目级 MCP 的 loader entry id 固定前缀(区分 profile 全局 MCP;loader id 不能用 ':',故用 '.')。 */\nexport const PROJECT_ENTRY_PREFIX = 'vsm-mcp.'\n/** 旧版项目 MCP 条目前缀(升级残留识别,不显示为全局 MCP)。 */\nexport const LEGACY_PROJECT_PREFIX = 'vsm-mcp:'\n\n/** 判断新旧格式项目 MCP 条目 id(旧残留不被视为全局 MCP)。 */\nexport function isProjectEntryId(id: string): boolean {\n return id.startsWith(PROJECT_ENTRY_PREFIX) || id.startsWith(LEGACY_PROJECT_PREFIX)\n}\n\n/** 从项目条目 id 解析 workspace hash(新旧格式通用)。 */\nexport function entryHash(id: string): string | undefined {\n if (id.startsWith(PROJECT_ENTRY_PREFIX)) return id.slice(PROJECT_ENTRY_PREFIX.length).split('.')[0]\n if (id.startsWith(LEGACY_PROJECT_PREFIX)) return id.slice(LEGACY_PROJECT_PREFIX.length).split(':')[0]\n return undefined\n}\n\n/** 读取随包 package.json 版本号(缺失/解析失败降级为空串)。 */\nexport function pluginVersionOf(): string {\n try {\n const file = join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json')\n const pkg = JSON.parse(readFileSync(file, 'utf8')) as { version?: unknown }\n return typeof pkg.version === 'string' ? pkg.version : ''\n } catch {\n return ''\n }\n}\n\n/** 探测外部插件/服务适配状态(depsAvailable 由调用方注入,便于测试)。 */\nexport function detectExternal(ctx: Ctx, depsAvailable: boolean): CompatAdapter[] {\n const mcpCount = entriesOf(ctx).length\n const settings = ctx.get('settings') as { describe?: unknown; update?: unknown } | undefined\n const hasSettings = Boolean(settings?.describe || settings?.update)\n const sub = ctx.get('subprocess') as { spawn?: unknown } | undefined\n return [\n { name: MCP_PACKAGE, active: mcpCount > 0, note: mcpCount > 0 ? mcpCount + ' 个 MCP 服务条目' : '未检测到 MCP 条目(MCP 管理页显示为空)' },\n { name: '设置持久化(@deepseek-ai/dsh-settings)', active: depsAvailable, note: depsAvailable ? '设置 section 已安装' : '未安装:fileOpenTool 持久化降级为配置值' },\n { name: 'settings 服务', active: hasSettings, note: hasSettings ? '可读写设置' : '不可用(设置读写走配置回退)' },\n { name: '文件浏览器打开(subprocess 服务)', active: typeof sub?.spawn === 'function', note: typeof sub?.spawn === 'function' ? '可定位/打开 OS 文件浏览器' : '不可用(右键「在文件浏览器中打开」将提示失败)' },\n ]\n}\n\n/** 本插件已注册的路由(kind → path 集合),冲突检测时排除自身,避免自误报。 */\nconst ownRoutes = { exact: new Set<string>(), prefixes: new Set<string>() }\n\n/** 清空本插件路由记录(registerRoutes 装配开始时调用,热重载不残留)。 */\nexport function resetOwnRoutes(): void {\n ownRoutes.exact.clear()\n ownRoutes.prefixes.clear()\n}\n\n/** 记录本插件路由(routes.ts 注册成功时调用)。 */\nexport function noteOwnRoute(kind: 'exact' | 'prefix', path: string): void {\n const table = kind === 'exact' ? ownRoutes.exact : ownRoutes.prefixes\n table.add(path)\n}\n\n/** 检测路由前缀占用与重叠(排除本插件自有路由;内部表不可读视为无冲突)。 */\nexport function routeConflict(web: unknown, prefix: string): string | null {\n try {\n const w = web as { exact?: Map<unknown, unknown>; prefixes?: Map<unknown, unknown> } | undefined\n const exact = w?.exact\n const prefixes = w?.prefixes\n if (exact instanceof Map) {\n for (const path of exact.keys()) {\n const other = String(path)\n if (other.startsWith(prefix + '/') && !ownRoutes.exact.has(other)) {\n return '精确路由 ' + other + ' 与 ' + prefix + ' 前缀重叠(可能来自热重载残留或其他插件)'\n }\n }\n }\n if (prefixes instanceof Map) {\n for (const path of prefixes.keys()) {\n const other = String(path)\n if (other !== prefix && (other.startsWith(prefix + '/') || prefix.startsWith(other + '/')) && !ownRoutes.prefixes.has(other)) {\n return '路由前缀 ' + prefix + ' 与 ' + other + ' 重叠'\n }\n }\n }\n } catch {\n /* 内部表不可读时放弃检查 */\n }\n return null\n}\n\n/** 检测本插件是否被重复装配(bundle 层 + 用户层重复 insert 的自诊断)。 */\nexport function duplicateEntries(ctx: Ctx): string[] {\n const loader = ctx.get('loader') as { entries?: () => Iterable<{ id?: unknown; options?: { name?: unknown } }> } | undefined\n if (!loader || typeof loader.entries !== 'function') return []\n const own = [...loader.entries()].filter((entry) => String(entry.options?.name ?? entry.id ?? '') === PLUGIN_NAME)\n if (own.length > 1) {\n return ['检测到 ' + own.length + ' 个 ' + PLUGIN_NAME + ' loader 条目(重复装配)。请删除 profile 用户层 cordis.patch.yml 的重复 insert(或运行 dev_fix_patch 清理)']\n }\n return []\n}\n\n/** 护栏适配状态:路由前缀唯一性 + 插件装配唯一性。 */\nexport function detectGuards(ctx: Ctx): CompatAdapter[] {\n const web = ctx.get('webServer')\n const conflict = web ? routeConflict(web, ROUTE_PREFIX) : null\n const duplicates = duplicateEntries(ctx)\n return [\n { name: '路由前缀 ' + ROUTE_PREFIX, active: !conflict, note: conflict ?? '无冲突' },\n { name: '插件装配唯一性', active: duplicates.length === 0, note: duplicates[0] ?? '唯一装配' },\n ]\n}\n\n/** 已实测覆盖的最高 DSH 版本(适配矩阵上界,超过则提示,见 buildReport)。 */\nconst TESTED_DSH_MAX = '0.1.3-alpha.2'\n\n/** 版本适配机制状态行:DSH 版本探测 + 设置 section 安装策略。 */\nexport function versionAdapters(dshVersion: string): CompatAdapter[] {\n const adapters: CompatAdapter[] = []\n const parsed = parseDshVersion(dshVersion)\n if (dshVersion === '') {\n adapters.push({ name: 'DSH 版本', active: false, note: '未探测到版本号(能力探测模式运行)' })\n } else if (!parsed) {\n adapters.push({ name: 'DSH 版本', active: false, note: '无法解析版本号 ' + dshVersion + '(能力探测模式运行)' })\n } else {\n adapters.push({ name: 'DSH 版本', active: true, note: dshVersion + ' · ' + familyLabel(dshVersion) })\n }\n const strategy = settingsInstallStrategy()\n adapters.push({\n name: '设置 section 安装(版本适配)',\n active: strategy === 'legacy' || strategy === 'service',\n note: settingsInstallNote(),\n })\n return adapters\n}\n\n/**\n * 构建完整兼容性报告(RPC 与启动日志共用)。\n * @author ddj 2026年08月24号 / 2026年09月02号\n * @param ctx DSH host 上下文\n * @param options 测试注入:depsAvailable 跳过动态导入、version 固定插件版本、dshVersion 固定 DSH 版本\n * @returns 兼容性报告\n */\nexport async function buildReport(\n ctx: Ctx,\n options?: { depsAvailable?: boolean; version?: string; dshVersion?: string },\n): Promise<CompatReport> {\n const deps = options?.depsAvailable ?? (await loadSettingsDeps()) !== null\n const dshVersion = options?.dshVersion ?? detectDshVersion()\n const external = detectExternal(ctx, deps)\n const guards = detectGuards(ctx)\n const adapters = versionAdapters(dshVersion)\n const warnings: string[] = []\n if (!deps) warnings.push('未安装 @deepseek-ai/dsh-settings:文件打开工具设置持久化不可用(降级为配置值)')\n const strategy = settingsInstallStrategy()\n if (strategy === 'none') warnings.push('设置 section 安装不可用:' + settingsInstallNote())\n const parsed = parseDshVersion(dshVersion)\n const testedMax = parseDshVersion(TESTED_DSH_MAX)\n if (parsed && testedMax && compareDshVersions(parsed, testedMax) > 0) {\n warnings.push('DSH ' + dshVersion + ' 高于已实测版本(' + TESTED_DSH_MAX + '):设置 API 按能力探测运行,异常时请回报适配矩阵')\n }\n for (const guard of guards) {\n if (!guard.active && guard.note) warnings.push(guard.note)\n }\n return {\n pluginVersion: options?.version ?? pluginVersionOf(),\n external,\n guards,\n adapters,\n warnings,\n devForm: readDevForm(),\n dshVersion,\n }\n}\n","/**\n * dsh-vscode-mode host — webServer 路由注册(/edrv/rpc、/edrv/assets/*、/edrv/vendor/*)。\n * 迁移自原 src/index.ts 的路由部分,路径/行为一字不改。\n * 作者 ddj 2026-08-20\n */\nimport { readFile, stat } from 'node:fs/promises'\nimport { extname, join, normalize, resolve, sep } from 'node:path'\nimport { ROUTE_PREFIX, noteOwnRoute, resetOwnRoutes, routeConflict } from './compat.js'\nimport { RPC_PATH } from './shared/rpc.js'\nimport type { RpcMethod, RpcRequestMap } from './shared/rpc.js'\nimport type { Ctx } from './store.js'\nimport { VENDOR_PREFIX, imageDirOf, vendorDirOf } from './paths.js'\n\nconst IMG_ROUTES = [\n { url: '/edrv/assets/compare-idle.png', file: 'compare_idle.png' },\n { url: '/edrv/assets/compare-select.png', file: 'compare_select.png' },\n]\n\n/** Monaco AMD 构建静态资源(随包发布,离线可用;前缀路由 /edrv/vendor/*)。 */\nconst VENDOR_MIME: Record<string, string> = {\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json',\n '.map': 'application/json',\n '.ts': 'text/plain; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.html': 'text/html; charset=utf-8',\n '.md': 'text/markdown',\n '.bcmap': 'application/octet-stream',\n '.pfb': 'application/octet-stream',\n}\n\n/** 图标目录(paths.ts 统一解析:config.imageDir 覆盖优先,否则插件包 assets/)。 */\nconst imgDirOf = (config: unknown): string => imageDirOf(config, import.meta.url)\n\n/** Monaco AMD 静态目录(随包发布,paths.ts 统一解析)。 */\nconst vendorDir = vendorDirOf(import.meta.url)\n\n/**\n * 注册全部 webServer 路由(带兼容护栏:前缀冲突预警 + 注册失败降级跳过)。\n * @author ddj 2026年08月20号\n * @param ctx DSH 上下文\n * @param config 插件配置(可选 imageDir 等)\n * @param handleRpc RPC 分发入口(method,args → RpcResult)\n * @param onWarning 兼容性警告收集(可选)\n */\nexport function registerRoutes(\n ctx: Ctx,\n config: unknown,\n handleRpc: <M extends RpcMethod>(method: M, args: RpcRequestMap[M]) => Promise<unknown>,\n onWarning?: (warning: string) => void,\n): void {\n const imgDir = imgDirOf(config)\n const web = ctx.get('webServer')\n if (!web) return\n\n resetOwnRoutes()\n const conflict = routeConflict(web, ROUTE_PREFIX)\n if (conflict) onWarning?.('兼容性:' + conflict)\n\n /** 护栏注册:重复路由抛错时降级为警告并跳过,不让单条路由拖垮装配。 */\n const guarded = (route: { kind: 'exact' | 'prefix'; path: string; handler?: unknown }, label: string): (() => void) | undefined => {\n try {\n const dispose = web.register(route)\n noteOwnRoute(route.kind, route.path)\n return dispose\n } catch (error) {\n onWarning?.('兼容性:' + label + ' 注册失败(' + String(error) + ')')\n return undefined\n }\n }\n\n ctx.effect(() => guarded({\n kind: 'exact',\n path: RPC_PATH,\n handler: async (req: unknown, res: { statusCode?: number; setHeader: (k: string, v: string) => void; end: (b?: string) => void }) => {\n try {\n const chunks: Uint8Array[] = []\n for await (const chunk of req as AsyncIterable<Uint8Array>) chunks.push(chunk)\n let input: { method?: string; args?: unknown } = {}\n try {\n input = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}')\n } catch (error) {\n input = {}\n }\n const method = (typeof input.method === 'string' ? input.method : '') as RpcMethod\n const result = await handleRpc(method, (input.args ?? {}) as never)\n res.statusCode = 200\n res.setHeader('content-type', 'application/json')\n res.end(JSON.stringify(result))\n } catch (error) {\n res.statusCode = 500\n res.end(JSON.stringify({ ok: false, error: String(error) }))\n }\n },\n }, '/edrv/rpc 精确路由'), 'edrv: routes')\n\n for (const r of IMG_ROUTES) {\n ctx.effect(() => guarded({\n kind: 'exact',\n path: r.url,\n handler: async (req: unknown, res: { statusCode?: number; setHeader: (k: string, v: string) => void; end: (b?: string | Uint8Array) => void }) => {\n try {\n const body = await readFile(imgDir + '/' + r.file)\n res.statusCode = 200\n res.setHeader('content-type', 'image/png')\n res.setHeader('cache-control', 'no-cache')\n res.end(body)\n } catch (error) {\n res.statusCode = 404\n res.end()\n }\n },\n }, '静态资源 ' + r.file), 'edrv: routes')\n }\n\n // Monaco Editor AMD 构建:/edrv/vendor/* → assets/vendor/*(路径穿越防护 + 按扩展名 MIME)\n // ETag 协商缓存:弱 etag(mtime+size),配合 max-age 让浏览器 304 复用,插件升级内容变化自动失效。\n ctx.effect(() => guarded({\n kind: 'prefix',\n path: VENDOR_PREFIX,\n handler: async (req: { method?: string; url?: string; headers?: Record<string, string | string[] | undefined> }, res: { statusCode?: number; setHeader: (k: string, v: string) => void; end: (b?: string | Uint8Array) => void }) => {\n try {\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n res.statusCode = 405\n res.end()\n return\n }\n const pathname = new URL(req.url ?? '/', 'http://x').pathname\n const rel = decodeURIComponent(pathname.slice(VENDOR_PREFIX.length)).replace(/^\\/+/, '')\n if (!rel) { res.statusCode = 404; res.end(); return }\n const target = resolve(normalize(join(vendorDir, rel)))\n if (target !== vendorDir && !target.startsWith(vendorDir + sep)) {\n res.statusCode = 403\n res.end()\n return\n }\n const info = await stat(target).catch(() => null)\n if (!info || !info.isFile()) { res.statusCode = 404; res.end(); return }\n const etag = 'W/\"' + info.mtimeMs.toString(16) + '-' + info.size.toString(16) + '\"'\n const reqEtag = (() => {\n const raw = req.headers?.['if-none-match']\n if (Array.isArray(raw)) return raw[0]\n return raw\n })()\n if (reqEtag === etag) {\n res.statusCode = 304\n res.setHeader('etag', etag)\n res.end()\n return\n }\n const body = await readFile(target)\n res.statusCode = 200\n res.setHeader('content-type', VENDOR_MIME[extname(target)] ?? 'application/octet-stream')\n res.setHeader('cache-control', 'public, max-age=3600')\n res.setHeader('etag', etag)\n res.end(body)\n } catch (error) {\n res.statusCode = 404\n res.end()\n }\n },\n }, '/edrv/vendor 前缀路由'), 'edrv: routes')\n}\n","/**\n * dsh-vscode-mode shared diff primitives — 快照指纹、hunk 规范化与安全定位。\n * 不依赖 Node/React,host 与 browser 共用,避免各层用不同 indexOf 语义。\n * 作者 ddj 2026-08-24\n */\nimport type { Hunk, RecordBase } from './types.js'\n\n/** 文件读取状态,区分真实空文件与无法读取/过大的文件。 */\nexport type ReadState =\n | { kind: 'content'; content: string }\n | { kind: 'missing' }\n | { kind: 'unavailable' }\n\n/** 文本中的一个半开区间 [start,end)。 */\nexport interface TextRange {\n start: number\n end: number\n}\n\n/** 一条 hunk 在当前内容中的定位结果。 */\nexport interface HunkLocation extends TextRange {\n idx: number\n hunk: Hunk\n matched: boolean\n}\n\n/** 统一取对应 hunk;callHunk 只用于旧记录缺失 hunks 时兼容。 */\nexport function preciseHunk(record: Pick<RecordBase, 'hunks' | 'callHunk'>, idx: number): Hunk | null {\n return hunkOf(record, idx)\n}\n\n/** 轻量、确定性的字符串指纹;不引入 Node crypto。 */\nexport function fingerprint(text: string | null | undefined): string | null {\n if (typeof text !== 'string') return null\n let hash = 2166136261\n for (let i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i)\n hash = Math.imul(hash, 16777619)\n }\n return 'fnv1a:' + (hash >>> 0).toString(16) + ':' + text.length\n}\n\n/** 取记录第 idx 个有效 hunk;只有记录缺 hunk 时才回退 callHunk。 */\nexport function hunkOf(record: Pick<RecordBase, 'hunks' | 'callHunk'>, idx: number): Hunk | null {\n const hunk = Array.isArray(record.hunks) ? record.hunks[idx] : undefined\n if (hunk && typeof hunk.newText === 'string') return hunk\n if (idx === 0 && record.callHunk && typeof record.callHunk.newText === 'string') return record.callHunk\n return null\n}\n\n/** hunk 是否表示没有实际内容变化。 */\nexport function isNoopHunk(hunk: Hunk | null | undefined): boolean {\n return !!hunk && hunk.oldText !== null && hunk.oldText === hunk.newText\n}\n\n/**\n * 差异比较口径归一化:剥离 UTF-8 BOM、统一 CRLF 为 LF。\n * 背景:外部工具(pwsh/编辑器)可能改变 BOM/行尾,导致 after 指纹与 hunk\n * 定位在内容语义未变的情况下误报 conflict,把待确认修改从 UI 排除。\n * @author ddj 2026年09月09号\n */\nexport function normalizeForCompare(text: string): string {\n return text.replace(/^\\uFEFF/, '').replace(/\\r\\n/g, '\\n')\n}\n\n/** 归一化一个 hunk 的两侧文本(与 normalizeForCompare 同口径)。 */\nexport function normalizeHunk(hunk: Hunk): Hunk {\n return {\n oldText: hunk.oldText === null ? null : normalizeForCompare(hunk.oldText),\n newText: normalizeForCompare(hunk.newText),\n }\n}\n\n/** splitLines 的空文本语义:真实空文件没有一行变更内容。 */\nexport function splitLines(text: string): string[] {\n return text.length ? text.split('\\n') : []\n}\n\n/** 为执行后 hunk 写入快照坐标;空 newText 通过 before/after 公共边界定位删除点。 */\nexport function annotateHunk(hunk: Hunk, before: string | null, after: string | null): Hunk {\n return annotateHunks([hunk], before, after)[0]\n}\n\n/** 按文件顺序为多 hunk 写入不重复的 after 坐标。 */\nexport function annotateHunks(hunks: Hunk[], before: string | null, after: string | null): Hunk[] {\n if (typeof after !== 'string') return hunks\n let cursor = 0\n return hunks.map((hunk) => {\n if (hunk.newText.length > 0) {\n const start = after.indexOf(hunk.newText, cursor)\n if (start >= 0) {\n cursor = start + hunk.newText.length\n return { ...hunk, afterStart: start, afterEnd: cursor }\n }\n return hunk\n }\n if (hunks.length !== 1 || typeof before !== 'string' || before === after || hunk.oldText === null) return hunk\n const prefix = commonPrefix(before, after)\n const suffix = commonSuffix(before, after, prefix)\n const removedStart = prefix\n const removedEnd = Math.max(removedStart, before.length - suffix)\n return { ...hunk, afterStart: removedStart, afterEnd: removedStart, beforeStart: removedStart, beforeEnd: removedEnd }\n })\n}\n\n/** 计算两个文本的最长公共前缀长度。 */\nfunction commonPrefix(left: string, right: string): number {\n const limit = Math.min(left.length, right.length)\n let i = 0\n while (i < limit && left.charCodeAt(i) === right.charCodeAt(i)) i++\n return i\n}\n\n/** 计算不与 prefix 重叠的最长公共后缀长度。 */\nfunction commonSuffix(left: string, right: string, prefix: number): number {\n const limit = Math.min(left.length, right.length) - prefix\n let i = 0\n while (i < limit && left.charCodeAt(left.length - 1 - i) === right.charCodeAt(right.length - 1 - i)) i++\n return i\n}\n\n/** 计算 index 前的 0 基行数。 */\nexport function lineBefore(text: string, index: number): number {\n let n = 0\n const end = Math.max(0, Math.min(index, text.length))\n for (let i = 0; i < end; i++) if (text.charCodeAt(i) === 10) n++\n return n\n}\n\n/** 找出文本的全部非重叠出现位置。 */\nfunction allMatches(content: string, needle: string): TextRange[] {\n if (!needle.length) return []\n const out: TextRange[] = []\n let from = 0\n while (from <= content.length - needle.length) {\n const at = content.indexOf(needle, from)\n if (at < 0) break\n out.push({ start: at, end: at + needle.length })\n from = at + Math.max(1, needle.length)\n }\n return out\n}\n\n/**\n * 从 after 快照定位所有 hunk,按 hunk 顺序优先选未占用且靠近前一块的候选。\n * 若 hunk 带 afterStart/afterEnd,则优先验证快照坐标,避免重复文本错配。\n * @author ddj 2026年08月24号\n * @param content 当前文件内容\n * @param hunks 待定位 hunk\n * @returns 每个 hunk 一个结果,matched=false 表示冲突/stale\n */\nexport function locateHunks(content: string, hunks: Hunk[]): HunkLocation[] {\n const locations: HunkLocation[] = []\n let cursor = 0\n const occupied: TextRange[] = []\n for (let idx = 0; idx < hunks.length; idx++) {\n const hunk = hunks[idx]\n const newText = hunk.newText\n const snapshot = Number.isInteger(hunk.afterStart) && Number.isInteger(hunk.afterEnd)\n ? { start: hunk.afterStart as number, end: hunk.afterEnd as number }\n : null\n const snapshotMatches = snapshot && snapshot.start >= 0 && snapshot.end >= snapshot.start\n && (newText.length === 0 || content.slice(snapshot.start, snapshot.end) === newText)\n ? snapshot\n : null\n const candidates = snapshotMatches ? [snapshotMatches] : allMatches(content, newText)\n const candidate = candidates.find((range) => range.start >= cursor && !occupied.some((used) => overlaps(range, used)))\n ?? candidates.find((range) => !occupied.some((used) => overlaps(range, used)))\n if (candidate) {\n locations.push({ idx, hunk, ...candidate, matched: true })\n occupied.push(candidate)\n cursor = Math.max(cursor, candidate.end)\n continue\n }\n if (newText.length === 0 && hunk.afterStart === undefined && hunk.afterEnd === undefined && content.length === 0) {\n const point = { start: 0, end: 0 }\n locations.push({ idx, hunk, ...point, matched: true })\n continue\n }\n if (newText.length === 0 && hunk.afterStart !== undefined && hunk.afterEnd !== undefined\n && hunk.afterStart === hunk.afterEnd && hunk.afterStart >= 0 && hunk.afterStart <= content.length) {\n const point = { start: hunk.afterStart, end: hunk.afterEnd }\n if (!occupied.some((used) => overlaps(point, used))) {\n locations.push({ idx, hunk, ...point, matched: true })\n occupied.push(point)\n cursor = Math.max(cursor, point.end)\n continue\n }\n }\n locations.push({ idx, hunk, start: -1, end: -1, matched: false })\n }\n return locations\n}\n\n/** 判断两个半开区间是否重叠。零长度区间只与同一位置的零长度区间重叠。 */\nfunction overlaps(left: TextRange, right: TextRange): boolean {\n if (left.start === left.end || right.start === right.end) return left.start === right.start && left.end === right.end\n return left.start < right.end && right.start < left.end\n}\n\n/** 在可定位区间上执行一次 hunk 反向替换。 */\nexport function replaceRange(content: string, location: HunkLocation, reverse = false): string | null {\n if (!location.matched || location.start < 0) return null\n const replacement = reverse ? (location.hunk.oldText ?? '') : location.hunk.newText\n return content.slice(0, location.start) + replacement + content.slice(location.end)\n}\n\n/** 按当前内容中出现的位置从后向前应用 hunk,避免前块长度变化影响后块。 */\nexport function applyLocations(content: string, locations: HunkLocation[], reverse = false): { content: string; stale: number[] } {\n const stale = locations.filter((location) => !location.matched).map((location) => location.idx)\n let out = content\n const matched = locations.filter((location) => location.matched).sort((a, b) => b.start - a.start)\n for (const location of matched) {\n const next = replaceRange(out, location, reverse)\n if (next === null) stale.push(location.idx)\n else out = next\n }\n return { content: out, stale: stale.sort((a, b) => a - b) }\n}\n","/**\n * dsh-vscode-mode host — 纯域逻辑(无 ctx/fs/IO 依赖,可直接单测)。\n * 迁移自原 src/index.ts 的纯函数部分,语义一字不改。\n * 作者 ddj 2026-08-20\n */\nimport type { Decision, DiffRecord, Hunk, RecordSummary } from './shared/types.js'\nimport { applyLocations, fingerprint, isNoopHunk, locateHunks, preciseHunk } from './shared/diff.js'\n\n/** 工作区记录桶上限(超过后按 at 最旧剔除)。 */\nexport const MAX_RECORDS = 200\n\n/**\n * 归一化一条持久化记录(容忍旧版/损坏字段)。\n * @author ddj 2026年08月20号\n * @param raw 反序列化的原始记录\n * @returns 合法记录或 null\n */\nexport function normalizeRecord(raw: unknown): DiffRecord | null {\n if (!raw || typeof raw !== 'object') return null\n const r = raw as Record<string, unknown>\n if (typeof r.callId !== 'string' || typeof r.path !== 'string') return null\n const hunks: Hunk[] = Array.isArray(r.hunks)\n ? (r.hunks as unknown[]).filter((h) => h && typeof (h as { newText?: unknown }).newText === 'string').map((h) => {\n const item = h as Record<string, unknown>\n return {\n oldText: typeof item.oldText === 'string' ? item.oldText : null,\n newText: item.newText as string,\n ...(Number.isInteger(item.afterStart) ? { afterStart: item.afterStart as number } : {}),\n ...(Number.isInteger(item.afterEnd) ? { afterEnd: item.afterEnd as number } : {}),\n ...(Number.isInteger(item.beforeStart) ? { beforeStart: item.beforeStart as number } : {}),\n ...(Number.isInteger(item.beforeEnd) ? { beforeEnd: item.beforeEnd as number } : {}),\n }\n })\n : []\n const toolName: DiffRecord['toolName'] = r.toolName === 'write' ? 'write' : 'edit'\n const rawDecisions = r.decisions && typeof r.decisions === 'object' ? r.decisions as Record<string, unknown> : {}\n const call = rawDecisions.call === 'accepted' || rawDecisions.call === 'rejected' ? rawDecisions.call : 'pending'\n const rawPerHunk = Array.isArray(rawDecisions.perHunk) ? rawDecisions.perHunk : []\n const perHunk = hunks.map((_, i) => {\n const value = rawPerHunk[i]\n if (value === 'accepted' || value === 'rejected') return value\n return call === 'accepted' || call === 'rejected' ? call : 'pending'\n })\n const before = typeof r.before === 'string' ? r.before : null\n const hasAfter = Object.prototype.hasOwnProperty.call(r, 'after')\n const after = typeof r.after === 'string' ? r.after : null\n return {\n callId: r.callId,\n toolName,\n path: r.path,\n before,\n after,\n baseFingerprint: typeof r.baseFingerprint === 'string' ? r.baseFingerprint : fingerprint(before),\n afterFingerprint: typeof r.afterFingerprint === 'string' ? r.afterFingerprint : fingerprint(after),\n legacy: !hasAfter,\n conflict: r.conflict === true,\n create: r.create === true,\n callHunk: r.callHunk && typeof (r.callHunk as { oldText?: unknown }).oldText === 'string' && typeof (r.callHunk as { newText?: unknown }).newText === 'string'\n ? { oldText: (r.callHunk as { oldText: string }).oldText, newText: (r.callHunk as { newText: string }).newText }\n : null,\n hunks,\n decisions: { call: call as Decision, perHunk },\n note: typeof r.note === 'string' ? r.note : null,\n superseded: r.superseded === true,\n archived: r.archived === true,\n batch: Number.isInteger(r.batch) ? (r.batch as number) : 0,\n at: typeof r.at === 'string' ? r.at : new Date().toISOString(),\n }\n}\n\n/**\n * 写决策到记录(scope=call 整体 / hunk 单个块)。\n * @author ddj 2026年08月20号\n * @param record 记录\n * @param scope 作用域\n * @param idx hunk 下标(仅 scope=hunk 时生效)\n * @param value 决策值\n * @returns 更新后的记录(原对象就地修改)\n */\nexport function markDecision(record: DiffRecord, scope: string, idx: number | undefined, value: Decision): DiffRecord {\n const dec = record.decisions\n if (scope === 'hunk' && Array.isArray(dec.perHunk) && Number.isInteger(idx)) {\n const i = idx as number\n if (i >= 0 && i < dec.perHunk.length) dec.perHunk[i] = value\n } else {\n dec.call = value\n if (Array.isArray(dec.perHunk)) dec.perHunk = dec.perHunk.map(() => value)\n }\n record.at = new Date().toISOString()\n return record\n}\n\n/** 记录是否已无任何待决策差异(superseded 或全部已决策)。 */\nexport function recordResolved(record: DiffRecord): boolean {\n if (record.superseded === true) return true\n const hunks = Array.isArray(record.hunks) ? record.hunks : []\n const perHunk = Array.isArray(record.decisions.perHunk) ? record.decisions.perHunk : []\n const count = Math.max(hunks.length, perHunk.length)\n if (!count) return record.decisions.call === 'accepted' || record.decisions.call === 'rejected'\n for (let idx = 0; idx < count; idx++) {\n const precise = preciseHunk(record, idx)\n const value = perHunk[idx] ?? record.decisions.call\n if (isNoopHunk(precise) && value === 'pending') return false\n if (value !== 'accepted' && value !== 'rejected') return false\n }\n return true\n}\n\n/**\n * 记录决策摘要(采纳/拒绝/待处理计数,superseded 标记)。\n * @author ddj 2026年08月20号\n * @param record 记录\n * @returns 摘要\n */\nexport function recSummary(record: DiffRecord): RecordSummary {\n const hunks = Array.isArray(record.hunks) ? record.hunks : []\n const perHunk = Array.isArray(record.decisions.perHunk) ? record.decisions.perHunk : []\n const n = Math.max(1, hunks.length, perHunk.length)\n let accepted = 0\n let rejected = 0\n let pending = 0\n for (let i = 0; i < n; i++) {\n const hunk = preciseHunk(record, i)\n const value = perHunk[i] ?? record.decisions.call\n if (i < hunks.length && isNoopHunk(hunk) && value === 'pending') continue\n if (value === 'accepted') accepted++\n else if (value === 'rejected') rejected++\n else pending++\n }\n return { accepted, rejected, pending, superseded: record.superseded === true }\n}\n\n/**\n * 重建\"本批次修改前\"内容:把仍待处理(pending)的差异块按 新→旧 顺序从当前内容反解\n * (newText → oldText)。已采纳/已拒绝的块跳过。反解失败的块标记为 stale。\n * @author ddj 2026年08月20号\n * @param records 该文件的活动记录\n * @param content 当前磁盘内容\n * @returns 重建内容与 stale 定位\n */\nexport function reconstructOriginal(records: DiffRecord[], content: string): { content: string; stale: Array<{ callId: string; idx: number }> } {\n const pending: Array<{ rec: DiffRecord; idx: number; hunk: Hunk }> = []\n for (const rec of records) {\n for (let i = 0; i < rec.hunks.length; i++) {\n const st = rec.decisions.perHunk[i] ?? rec.decisions.call\n const hunk = preciseHunk(rec, i)\n if (st === 'pending' && hunk && !isNoopHunk(hunk)) pending.push({ rec, idx: i, hunk })\n }\n }\n pending.sort((a, b) => (a.rec.at < b.rec.at ? 1 : a.rec.at > b.rec.at ? -1 : 0))\n const locations = locateHunks(content, pending.map((item) => item.hunk))\n const rebuilt = applyLocations(content, locations, true)\n return {\n content: rebuilt.content,\n stale: rebuilt.stale.map((idx) => ({ callId: pending[idx].rec.callId, idx: pending[idx].idx })),\n }\n}\n\n/** 文件当前最大批次号(无记录为 0)。 */\nexport function fileMaxBatch(records: Map<string, DiffRecord>, path: string): number {\n let m = 0\n for (const r of records.values()) {\n if (r.path === path && Number.isInteger(r.batch) && r.batch > m) m = r.batch\n }\n return m\n}\n\n/** 记录桶裁剪:超出 MAX_RECORDS 时剔除最旧的。 */\nexport function prune(map: Map<string, DiffRecord>, max = MAX_RECORDS): void {\n if (map.size <= max) return\n const sorted = [...map.values()].sort((a, b) => (a.at < b.at ? -1 : 1))\n for (let i = 0; i < sorted.length - max; i++) map.delete(sorted[i].callId)\n}\n\n/** 按批次分组记录。 */\nexport function groupByBatch(recs: DiffRecord[]): Map<number | null, DiffRecord[]> {\n const map = new Map<number | null, DiffRecord[]>()\n for (const r of recs) {\n const k = Number.isInteger(r.batch) ? r.batch : null\n if (!map.has(k)) map.set(k, [])\n map.get(k)!.push(r)\n }\n return map\n}\n\n/**\n * 归档条目构造(一条批次一条)。\n * @author ddj 2026年08月20号\n * @param recs 同批次记录(非空)\n * @param cwd 工作区\n * @param reason 归档原因\n */\nexport function archiveEntryFor(recs: DiffRecord[], cwd: string, reason: string): {\n at: string\n cwd: string\n path: string\n batch: number | null\n reason: string\n records: Array<Record<string, unknown>>\n} {\n const first = recs[0]\n return {\n at: new Date().toISOString(),\n cwd,\n path: first.path,\n batch: Number.isInteger(first.batch) ? first.batch : null,\n reason,\n records: recs.map((r) => ({\n callId: r.callId,\n toolName: r.toolName,\n path: r.path,\n create: r.create === true,\n callHunk: r.callHunk,\n hunks: r.hunks,\n decisions: r.decisions,\n note: r.note ?? null,\n before: typeof r.before === 'string' ? r.before : null,\n after: typeof r.after === 'string' ? r.after : null,\n baseFingerprint: r.baseFingerprint ?? null,\n afterFingerprint: r.afterFingerprint ?? null,\n conflict: r.conflict === true,\n legacy: r.legacy === true,\n superseded: r.superseded === true,\n batch: Number.isInteger(r.batch) ? r.batch : null,\n at: r.at,\n summary: recSummary(r),\n })),\n }\n}\n","/**\n * dsh-vscode-mode host — 存储层(sidecar 读写合并 + 归档持久化 + stale 检测)。\n * 迁移自原 src/index.ts 的 fs/ctx IO 部分,语义一字不改。\n * 作者 ddj 2026-08-20\n */\nimport type { ArchiveBatch, ArchiveData, DiffRecord, SidecarData } from './shared/types.js'\nimport type { ReadState } from './shared/diff.js'\nimport { fingerprint, isNoopHunk, locateHunks, normalizeForCompare, normalizeHunk, preciseHunk } from './shared/diff.js'\nimport { archiveEntryFor, groupByBatch, normalizeRecord } from './model.js'\nimport { SIDECAR, SIDECAR_ARCHIVE } from './paths.js'\nimport { log } from './log.js'\n\nexport { SIDECAR, SIDECAR_ARCHIVE }\nexport const READ_CAP = 8 * 1024 * 1024\n/** 二进制预览/写回上限(PDF 等整文件 base64 传输;文本侧仍用 READ_CAP)。 */\nexport const BINARY_READ_CAP = 32 * 1024 * 1024\n\n/** DSH 上下文与会话类型较宽松:本地无 dsh 类型声明,显式 any + 文档约束。 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Ctx = any\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Session = any\n\n/** 会话沙箱策略(policyOf):可能不存在,调用方需容忍 undefined。 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function policyOf(ctx: Ctx, session: Session | undefined): any {\n const svc = ctx.get('sandboxPolicy')\n if (!svc) return undefined\n return session ? svc.resolve({ session }) : svc.resolve()\n}\n\n/** 按会话 cwd 解析目标路径。 */\nexport async function resolveTarget(ctx: Ctx, session: Session | undefined, path: string): Promise<string> {\n const fs = ctx.get('fs')\n const cwd = session?.header?.cwd\n return fs.resolve(path, cwd ? { cwd } : {})\n}\n\n/** 读取工作区主 sidecar 文本(缺失/失败 → null)。 */\nasync function readSidecarText(ctx: Ctx, cwd: string | null): Promise<string | null> {\n const fs = ctx.get('fs')\n if (!fs || !cwd) return null\n try {\n return await fs.readText(await fs.resolve(SIDECAR, { cwd }))\n } catch (error) {\n return null\n }\n}\n\n/**\n * 解析主 sidecar:v2 直接返回;v1 迁移为 v2 结构(按会话 cwd 分桶)。\n * @author ddj 2026年08月20号\n * @param text sidecar 文本\n * @returns v2 数据或 null\n */\nexport function parseSidecar(text: string | null): SidecarData | null {\n if (!text) return null\n try {\n const data = JSON.parse(text)\n if (data && typeof data === 'object' && data.version === 2 && data.workspaces && typeof data.workspaces === 'object') {\n return data as SidecarData\n }\n if (data && data.version === 1 && data.sessions && typeof data.sessions === 'object') {\n const workspaces: SidecarData['workspaces'] = {}\n for (const bucket of Object.values(data.sessions)) {\n const b = bucket as { cwd?: unknown; records?: unknown; at?: unknown }\n if (typeof b.cwd === 'string' && b.records) {\n workspaces[b.cwd] = { at: typeof b.at === 'number' ? b.at : Date.now(), records: b.records as Record<string, DiffRecord> }\n }\n }\n return { version: 2, updatedAt: typeof data.updatedAt === 'string' ? data.updatedAt : new Date().toISOString(), workspaces }\n }\n return null\n } catch (error) {\n return null\n }\n}\n\n/** 加载某工作区的记录桶(内存 Map;缺失 → 空)。 */\nexport async function loadBucket(ctx: Ctx, cwd: string): Promise<Map<string, DiffRecord>> {\n const text = await readSidecarText(ctx, cwd)\n const data = parseSidecar(text)\n const map = new Map<string, DiffRecord>()\n if (data && data.workspaces[cwd] && typeof data.workspaces[cwd].records === 'object') {\n for (const rec of Object.values(data.workspaces[cwd].records)) {\n const n = normalizeRecord(rec)\n if (n) map.set(n.callId, n)\n }\n }\n return map\n}\n\n/** 保存某工作区的记录桶(写前合并,不覆盖其他工作区)。 */\nexport async function saveBucket(ctx: Ctx, cwd: string, recsMap: Map<string, DiffRecord>, session?: Session): Promise<void> {\n const fs = ctx.get('fs')\n if (!fs || !cwd) return\n try {\n const target = await fs.resolve(SIDECAR, { cwd })\n const existing = parseSidecar(await readSidecarText(ctx, cwd)) ?? { version: 2, updatedAt: '', workspaces: {} } as SidecarData\n existing.workspaces[cwd] = { at: Date.now(), records: Object.fromEntries(recsMap) }\n existing.updatedAt = new Date().toISOString()\n await fs.writeText(target, JSON.stringify(existing), void 0, void 0, policyOf(ctx, session))\n } catch (error) {\n log.error('saveBucket failed: ' + String(error))\n }\n}\n\n/**\n * 读取记录目标文件内容(按 path 缓存一次;缺失/过大/失败 → null/'' 占位)。\n * @author ddj 2026年08月20号\n * @param cache path → 内容(null=缺失/读取失败,''=过大跳过)\n */\nexport async function readForCache(ctx: Ctx, session: Session, cache: Map<string, ReadState>, path: string): Promise<ReadState> {\n const cached = cache.get(path)\n if (cached) return cached\n const fs = ctx.get('fs')\n if (!fs) { const state: ReadState = { kind: 'unavailable' }; cache.set(path, state); return state }\n try {\n const target = await resolveTarget(ctx, session, path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') { const state: ReadState = { kind: 'missing' }; cache.set(path, state); return state }\n if ((info.size ?? 0) > READ_CAP) { const state: ReadState = { kind: 'unavailable' }; cache.set(path, state); return state }\n const state: ReadState = { kind: 'content', content: await fs.readText(target) }\n cache.set(path, state)\n return state\n } catch (error) {\n const state: ReadState = { kind: 'unavailable' }\n cache.set(path, state)\n return state\n }\n}\n\n/**\n * 判断记录是否已无任何可操作差异(stale):待决策 hunk 的新文本在磁盘均找不到,\n * 或新建文件已不存在,或全为空差异。满足则应由 host 自动归档。\n * @author ddj 2026年08月20号\n */\nexport async function recordIsStale(ctx: Ctx, session: Session, cache: Map<string, ReadState>, rec: DiffRecord): Promise<boolean> {\n if (rec.superseded === true) return true\n if (!Array.isArray(rec.hunks) || !rec.hunks.length) return true\n const state = await readForCache(ctx, session, cache, rec.path)\n if (state.kind === 'unavailable') return false\n if (state.kind === 'missing') return true\n if (rec.create === true) return false\n const pending = rec.hunks.map((_, idx) => ({ idx, hunk: preciseHunk(rec, idx), status: rec.decisions.perHunk[idx] ?? rec.decisions.call }))\n .filter((item) => item.status === 'pending' && item.hunk && !isNoopHunk(item.hunk))\n if (!pending.length) return true\n const currentFingerprint = fingerprint(state.content)\n if (rec.afterFingerprint && currentFingerprint === rec.afterFingerprint) { rec.conflict = false; return false }\n // 归一化口径对比:外部工具可能改变 BOM/行尾,内容语义未变不应判冲突\n const normalizedContent = normalizeForCompare(state.content)\n if (rec.after != null && fingerprint(normalizeForCompare(rec.after)) === fingerprint(normalizedContent)) { rec.conflict = false; return false }\n const locations = locateHunks(normalizedContent, pending.map((item) => normalizeHunk(item.hunk!)))\n if (locations.some((location) => location.matched)) { rec.conflict = false; return false }\n rec.conflict = true\n return false\n}\n\n/**\n * edrv.list 全量轮询时自动清理 stale 记录:标记 superseded 并归档,\n * 防止\"幽灵差异\"长期留在审查列表且无法操作。\n * @author ddj 2026年08月20号\n * @returns 自动归档条数\n */\nexport async function autoArchiveStale(ctx: Ctx, session: Session, cwd: string, bucket: Map<string, DiffRecord>): Promise<number> {\n const fs = ctx.get('fs')\n if (!fs) return 0\n const cache = new Map<string, ReadState>()\n const stale: DiffRecord[] = []\n for (const rec of bucket.values()) {\n if (rec.archived || rec.superseded === true) continue\n if (await recordIsStale(ctx, session, cache, rec)) stale.push(rec)\n }\n if (!stale.length) return 0\n for (const r of stale) { r.superseded = true; r.at = new Date().toISOString() }\n await archiveRecords(ctx, session, cwd, bucket, stale, '差异无法定位(已被后续修改覆盖),自动归档')\n return stale.length\n}\n\n/** 读取归档 sidecar 文本(缺失/失败 → null)。 */\nexport async function readArchiveText(ctx: Ctx, cwd: string | null): Promise<string | null> {\n const fs = ctx.get('fs')\n if (!fs || !cwd) return null\n try {\n return await fs.readText(await fs.resolve(SIDECAR_ARCHIVE, { cwd }))\n } catch (error) {\n return null\n }\n}\n\n/** 解析归档 sidecar(损坏 → 空数组)。 */\nexport function parseArchive(text: string | null): ArchiveBatch[] {\n if (!text) return []\n try {\n const data = JSON.parse(text)\n if (data && typeof data === 'object' && Array.isArray(data.batches)) return data.batches as ArchiveBatch[]\n } catch (error) { /* 忽略损坏 */ }\n return []\n}\n\n/** 追加归档条目(按 cwd+path+batch 合并,同 callId 去重)。 */\nexport async function appendArchiveEntries(ctx: Ctx, cwd: string, entries: Array<ReturnType<typeof archiveEntryFor>>, session?: Session): Promise<void> {\n const fs = ctx.get('fs')\n if (!fs || !cwd) return\n try {\n const target = await fs.resolve(SIDECAR_ARCHIVE, { cwd })\n const existing = parseArchive(await readArchiveText(ctx, cwd))\n for (const e of entries) {\n const idx = existing.findIndex((x) => x.cwd === e.cwd && x.path === e.path && x.batch === e.batch)\n if (idx >= 0) {\n const exist = existing[idx]\n const seen = new Set((exist.records || []).map((r) => r.callId))\n for (const rec of e.records) {\n if (!seen.has(String(rec.callId))) {\n exist.records.push(rec as unknown as ArchiveBatch['records'][number])\n seen.add(String(rec.callId))\n }\n }\n exist.lastAt = e.at\n exist.reason = e.reason\n } else {\n existing.push(e as unknown as ArchiveBatch)\n }\n }\n const data: ArchiveData = { version: 1, updatedAt: new Date().toISOString(), batches: existing }\n await fs.writeText(target, JSON.stringify(data), void 0, void 0, policyOf(ctx, session))\n } catch (error) {\n log.error('appendArchiveEntries failed: ' + String(error))\n }\n}\n\n/**\n * 归档记录:标记 archived、按批次写入归档、落盘工作区桶。\n * @param opts.deferSave 为 true 时只写归档、不落盘桶(由批量调用方统一 saveBucket 一次)\n */\nexport async function archiveRecords(\n ctx: Ctx,\n session: Session,\n cwd: string,\n bucket: Map<string, DiffRecord>,\n recs: DiffRecord[],\n reason: string,\n opts?: { deferSave?: boolean },\n): Promise<void> {\n if (!recs.length) return\n const fresh = recs.filter((r) => !r.archived)\n for (const r of recs) r.archived = true\n const entries: Array<ReturnType<typeof archiveEntryFor>> = []\n for (const list of groupByBatch(recs).values()) entries.push(archiveEntryFor(list, cwd, reason))\n await appendArchiveEntries(ctx, cwd, entries, session)\n if (fresh.length && !opts?.deferSave) await saveBucket(ctx, cwd, bucket, session)\n}\n","/**\n * dsh-vscode-mode host — 工作区记录桶注册表与会话助手。\n * 迁移自原 src/index.ts 的 registry/sessionOf/cwdOf/bucketOf,语义不改。\n * 作者 ddj 2026-08-20\n */\nimport type { DiffRecord } from './shared/types.js'\nimport type { Ctx, Session } from './store.js'\nimport { loadBucket } from './store.js'\n\n/** cwd → 记录桶(内存缓存;随会话销毁清理)。 */\nexport type Registry = Map<string, Map<string, DiffRecord>>\n\n/** 按 sessionId 取会话;缺省时仅当唯一活跃会话才返回。 */\nexport function sessionOf(ctx: Ctx, sessionId?: string): Session | undefined {\n const sessions = ctx.get('sessions')\n if (!sessions) return undefined\n if (sessionId) return sessions.get(sessionId)\n const live = sessions.list().filter((s: Session) => s.id)\n return live.length === 1 ? live[0] : undefined\n}\n\n/** 会话工作区 cwd。 */\nexport function cwdOf(session: Session | undefined): string | null {\n return session?.header?.cwd ?? null\n}\n\n/** 取(或加载)某工作区记录桶。 */\nexport function bucketOf(registry: Registry, ctx: Ctx, cwd: string): Promise<Map<string, DiffRecord>> {\n const existing = registry.get(cwd)\n if (existing) return Promise.resolve(existing)\n return loadBucket(ctx, cwd).then((map) => {\n registry.set(cwd, map)\n return map\n })\n}\n","/**\n * dsh-vscode-mode host — 目录树纯函数(edrv.listDir 的数据整形与守卫)。\n * 不触 fs/node,仅结构类型,可单测;RPC handler 只做装配,判定都收在这里。\n * 作者 ddj 2026-08-26\n */\nimport type { TreeEntry } from './shared/rpc.js'\n\n/** fs.listDir 返回项的结构最小视图(不引 dsh-fs,保持纯函数零依赖)。 */\nexport interface DirChildLike {\n name: string\n type: 'file' | 'directory' | 'other'\n size?: number\n}\n\n/** 目录在文件前、名称按小写字母序的比较器(对齐 VSCode 资源管理器习惯)。 */\nfunction entryOrder(a: { name: string; type: string }, b: { name: string; type: string }): number {\n const aDir = a.type === 'directory' ? 0 : 1\n const bDir = b.type === 'directory' ? 0 : 1\n if (aDir !== bDir) return aDir - bDir\n const la = a.name.toLocaleLowerCase('en-US')\n const lb = b.name.toLocaleLowerCase('en-US')\n return la < lb ? -1 : la > lb ? 1 : 0\n}\n\n/**\n * 归一化目录相对路径:去空白、反斜杠→斜杠、去首尾斜杠、`.`→''。\n * 任一路径段为 `..` 返回 null(拒绝越界)。\n * @author ddj 2026年08月26号\n * @param path 原始相对路径('' 表示根目录)\n * @returns 归一化相对路径('' = 根),非法返回 null\n */\nexport function normalizeRel(path: string | undefined | null): string | null {\n const rel = String(path ?? '').trim().replace(/\\\\/g, '/').replace(/^\\/+|\\/+$/g, '')\n if (!rel) return ''\n const segs = rel.split('/').filter((seg) => seg !== '.')\n if (!segs.length) return ''\n for (const seg of segs) {\n if (seg === '..') return null\n }\n return segs.join('/')\n}\n\n/**\n * fs.listDir 结果 → TreeEntry 数组:相对路径拼接 + 目录优先排序。\n * @author ddj 2026年08月26号\n * @param rel 父目录相对路径('' = 根)\n * @param children 目录子项\n * @returns 排序后的树条目\n */\nexport function toTreeEntries(rel: string, children: DirChildLike[]): TreeEntry[] {\n const out: TreeEntry[] = []\n for (const child of children) {\n if (!child || typeof child.name !== 'string' || !child.name) continue\n out.push({\n name: child.name,\n path: rel ? rel + '/' + child.name : child.name,\n type: child.type === 'directory' ? 'directory' : child.type === 'file' ? 'file' : 'other',\n size: typeof child.size === 'number' ? child.size : undefined,\n })\n }\n return out.sort(entryOrder)\n}\n","/**\n * dsh-vscode-mode host — 目录快速列取(edrv.listDir 数据来源,树索引 miss 时走这里)。\n * dsh-fs.listDir 对每个子项顺序 realpath+stat(2 次 open/项),在本部署被中介的\n * open(0.3–3s/次)下大目录呈分钟级;这里用原生 readdir(withFileTypes) 一次取型\n * (O(1) open),仅对 symlink/junction(Windows junction 在 dirent 中报 symlink,\n * 已实测)并行 follow-stat 判型,延迟按轮摊平而非按条目累加。\n * 结果形状与 dsh-fs 一致(name/type),由调用方 toTreeEntries 整形排序。\n * 作者 ddj 2026-08-31\n */\nimport { readdir, stat } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { DirChildLike } from './tree.js'\n\n// --region 常量\n/** symlink 并行 stat 分块并发数(并行摊平单次 open 延迟)。 */\nexport const SYMLINK_CONCURRENCY = 32\n/** symlink 并行 stat 总数上限:超出部分按 other(防御病态 symlink 目录)。 */\nexport const MAX_SYMLINK_STATS = 256\n// --endregion\n\n/** 列取失败(带稳定语义 code,调用方转文案)。 */\nexport class DirListError extends Error {\n constructor(\n readonly code: 'not-found' | 'not-dir' | 'permission' | 'io',\n message: string,\n ) {\n super(message)\n }\n}\n\n/** node fs 错误码 → 稳定语义错误。 */\nfunction codeOf(err: unknown): DirListError {\n const code = (err as NodeJS.ErrnoException | undefined)?.code\n if (code === 'ENOENT') return new DirListError('not-found', '目录不存在')\n if (code === 'ENOTDIR') return new DirListError('not-dir', '不是目录')\n if (code === 'EACCES' || code === 'EPERM' || code === 'EBUSY') return new DirListError('permission', '权限不足')\n return new DirListError('io', String((err as Error | undefined)?.message ?? err))\n}\n\n/** 并行 stat 一批绝对路径 → 目录/文件/other(follow symlink,失败按 other)。 */\nasync function statTypes(paths: string[], out: Map<string, 'directory' | 'file' | 'other'>): Promise<void> {\n const cap = Math.min(paths.length, MAX_SYMLINK_STATS)\n for (let i = 0; i < cap; i += SYMLINK_CONCURRENCY) {\n const chunk = paths.slice(i, i + SYMLINK_CONCURRENCY)\n await Promise.all(chunk.map(async (p) => {\n try {\n const info = await stat(p)\n out.set(p, info.isDirectory() ? 'directory' : info.isFile() ? 'file' : 'other')\n } catch (error) {\n out.set(p, 'other')\n }\n }))\n }\n}\n\n/**\n * 快速列取目录:一次 readdir(withFileTypes) 判型;symlink 并行 follow-stat。\n * @author ddj 2026年08月31号\n * @param absDir 绝对目录路径(fs.resolve 后的 targetKey)\n * @returns 子项列表(name/type;size 缺省,树界面不展示大小)\n * @throws DirListError 目录不存在/不是目录/权限不足/IO 失败\n */\nexport async function listDirCheap(absDir: string): Promise<DirChildLike[]> {\n let dirents\n try {\n dirents = await readdir(absDir, { withFileTypes: true, encoding: 'utf8' })\n } catch (error) {\n throw codeOf(error)\n }\n const out: DirChildLike[] = []\n const syms: string[] = []\n for (const d of dirents) {\n if (d.isDirectory()) out.push({ name: d.name, type: 'directory' })\n else if (d.isFile()) out.push({ name: d.name, type: 'file' })\n else if (d.isSymbolicLink()) syms.push(d.name)\n else out.push({ name: d.name, type: 'other' })\n }\n if (syms.length) {\n const symAbs = syms.map((name) => join(absDir, name))\n const types = new Map<string, 'directory' | 'file' | 'other'>()\n await statTypes(symAbs, types)\n for (let i = 0; i < syms.length; i++) {\n out.push({ name: syms[i], type: types.get(symAbs[i]) ?? 'other' })\n }\n }\n return out\n}\n","/**\n * dsh-vscode-mode host — 工作区目录树索引(.sln 式结构缓存,层 2)。\n * 内存 Map<cwd, 索引> + 落盘缓存文件(工作区级:\n * ~/.dsh/dsh-vscode-mode/cache/workspace/<cwdHash>/tree.v<schema>.json,路径统一走\n * paths.ts PathConst):命中(ts 新鲜且未失效)内存直出 0 IO;列取结果 putIndex 更新\n * 并防抖落盘;agent 写入/手动保存 invalidateIndex 父目录+祖先 → 3s 防抖后台 re-heal\n * (并行、单轮有界、合并并发轮);TTL 兜底外部改动。缓存写读走原生 node:fs(与引擎\n * settings-file 一致,不占用工作区;沙箱只约束 ctx fs)。文件只存 {name,type}(path 由\n * 目录 rel 还原),落盘上限 400 目录/1500 条目/8MB 硬跳过——只是暖启动快照,正确性\n * 不依赖它。首次使用某 cwd 时清理旧工作区树 sidecar\n * (.dsh-edit-review-tree.json/.dsh-vscode-mode-tree.json,缓存可重建,删除无损)。\n * 纯函数部分导出可单测。\n * 作者 ddj 2026-08-31 / 2026-09-01\n */\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport type { TreeEntry } from './shared/rpc.js'\nimport type { Ctx } from './store.js'\nimport { toTreeEntries } from './tree.js'\nimport { DirListError, listDirCheap } from './treeRead.js'\nimport { LEGACY_TREE_SIDECARS, treeCacheFile } from './paths.js'\n\n// --region 常量\n/** 命中新鲜度:超过则视为过期,按需重列。 */\nexport const TREE_TTL_MS = 60_000\n/** 内存目录上限:超出按 ts 逐出最旧(常驻目录命中保活,不会误逐)。 */\nexport const MEM_MAX_DIRS = 2000\n/** 落盘目录上限(按 ts 裁旧)。 */\nexport const PERSIST_MAX_DIRS = 400\n/** 落盘单目录条目上限:超出截断并标 full=false(截断仍可即时渲染,客户端后台刷新补全)。 */\nexport const PERSIST_DIR_ENTRIES = 1500\n/** 落盘序列化硬上限:超出跳过落盘(内存索引照常工作)。 */\nexport const PERSIST_MAX_BYTES = 8 * 1024 * 1024\n/** 落盘防抖:变更后静默 10s 再写一次。 */\nexport const PERSIST_DEBOUNCE_MS = 10_000\n/** re-heal 防抖:写入密集期合并为 3s 后一轮。 */\nexport const HEAL_DEBOUNCE_MS = 3000\n/** re-heal 单轮目录数上限(并行,防 IO 风暴)。 */\nexport const HEAL_ROUND_MAX = 20\n// --endregion\n\n/** 索引条目(文件瘦身格式:不含 path,加载时由目录 rel 还原)。 */\nexport interface TreeIndexEntry {\n name: string\n type: 'file' | 'directory' | 'other'\n}\n\n/** 单个目录的索引(ts=最近确认时间;full=false 表示条目被落盘截断过)。 */\nexport interface TreeIndexDir {\n ts: number\n full: boolean\n entries: TreeEntry[]\n}\n\n/** 索引数据(内存全量;落盘前经 trimPersist 裁剪)。 */\nexport interface TreeIndexData {\n v: 1\n root: string | null\n dirs: Record<string, TreeIndexDir>\n}\n\n/** 每 cwd 的索引运行时状态。 */\ninterface IndexState {\n ctx: Ctx\n cwd: string\n data: TreeIndexData\n stale: Set<string>\n dirty: boolean\n persistTimer: ReturnType<typeof setTimeout> | null\n healTimer: ReturnType<typeof setTimeout> | null\n pending: Map<string, Promise<{ entries: TreeEntry[] } | { error: string }>>\n loading: boolean\n loadPromise: Promise<void> | null\n}\n\n/** cwd → 索引状态(随会话销毁清理)。 */\nconst states = new Map<string, IndexState>()\n/** 单调时钟:连续 put 的 ts 严格递增(同毫秒不并列,逐出/裁剪顺序可预期)。 */\nlet clock = 0\n\n/** 取下一时间戳(不小于真实时间且严格递增)。 */\nfunction nextTs(): number {\n clock = Math.max(Date.now(), clock + 1)\n return clock\n}\n\n// --region 纯函数(可单测)\n/** 条目原始值 → 合法条目(非法返回 null)。 */\nexport function entryOf(raw: unknown): TreeIndexEntry | null {\n if (!raw || typeof raw !== 'object') return null\n const e = raw as { name?: unknown; type?: unknown }\n if (typeof e.name !== 'string' || !e.name) return null\n const type = e.type === 'directory' ? 'directory' : e.type === 'file' ? 'file' : 'other'\n return { name: e.name, type }\n}\n\n/** 写入路径 → 相对工作区根的 rel(绝对路径按 cwd 前缀裁剪;越界/非法 → null)。 */\nexport function relOf(cwd: string, path: string): string | null {\n let rel = String(path ?? '').trim().replace(/\\\\/g, '/')\n const c = cwd.replace(/\\\\/g, '/').replace(/\\/+$/, '')\n const cl = c.toLowerCase()\n const pl = rel.toLowerCase()\n if (pl.startsWith(cl + '/')) rel = rel.slice(cl.length + 1)\n else if (rel.startsWith('/') || /^[a-z]:\\//i.test(rel)) return null\n rel = rel.replace(/^\\/+|\\/+$/g, '')\n if (!rel) return null\n const segs = rel.split('/').filter((s) => s !== '' && s !== '.')\n if (!segs.length) return null\n for (const s of segs) {\n if (s === '..') return null\n }\n return segs.join('/')\n}\n\n/** rel 的父目录 + 全部祖先('a/b/c' → ['a/b','a',''];'a' → [''])。 */\nexport function ancestorsOf(rel: string): string[] {\n const segs = rel.split('/')\n const out: string[] = []\n for (let i = segs.length - 1; i >= 1; i--) out.push(segs.slice(0, i).join('/'))\n out.push('')\n return out\n}\n\n/** 序列化索引数据。 */\nexport function indexSerialize(data: TreeIndexData): string {\n const lean: { v: 1; root: string | null; dirs: Record<string, { ts: number; full: boolean; entries: TreeIndexEntry[] }> } = { v: 1, root: data.root, dirs: {} }\n for (const [rel, dir] of Object.entries(data.dirs)) {\n lean.dirs[rel] = { ts: dir.ts, full: dir.full, entries: dir.entries.map((e) => ({ name: e.name, type: e.type })) }\n }\n return JSON.stringify(lean)\n}\n\n/** 解析索引文本;损坏/格式不符 → null。 */\nexport function indexParse(text: string | null): TreeIndexData | null {\n if (!text) return null\n try {\n const raw = JSON.parse(text) as { v?: unknown; root?: unknown; dirs?: unknown }\n if (!raw || raw.v !== 1 || !raw.dirs || typeof raw.dirs !== 'object') return null\n const dirs: Record<string, TreeIndexDir> = {}\n for (const [rel, d] of Object.entries(raw.dirs)) {\n if (!d || typeof d !== 'object') continue\n const dir = d as { ts?: unknown; full?: unknown; entries?: unknown }\n if (!Array.isArray(dir.entries)) continue\n const entries: TreeEntry[] = []\n for (const rawEntry of dir.entries) {\n const e = entryOf(rawEntry)\n if (!e) continue\n entries.push({ name: e.name, path: rel ? rel + '/' + e.name : e.name, type: e.type })\n }\n if (!entries.length) continue\n dirs[rel] = { ts: typeof dir.ts === 'number' ? dir.ts : 0, full: dir.full === true, entries }\n }\n return { v: 1, root: typeof raw.root === 'string' ? raw.root : null, dirs }\n } catch (error) {\n return null\n }\n}\n\n/** 落盘裁剪:目录按 ts 取新裁旧、单目录超限截断标 full=false(内存不受影响)。 */\nexport function trimPersist(data: TreeIndexData, maxDirs = PERSIST_MAX_DIRS, maxEntries = PERSIST_DIR_ENTRIES): TreeIndexData {\n const dirs: Record<string, TreeIndexDir> = {}\n const sorted = Object.entries(data.dirs).sort((a, b) => b[1].ts - a[1].ts)\n for (const [rel, dir] of sorted) {\n if (Object.keys(dirs).length >= maxDirs) break\n const full = dir.entries.length <= maxEntries\n dirs[rel] = { ts: dir.ts, full, entries: full ? dir.entries : dir.entries.slice(0, maxEntries) }\n }\n return { v: 1, root: data.root, dirs }\n}\n// --endregion\n\n// --region 状态机\n/** 取(或建)某 cwd 的索引状态,并惰性加载落盘快照(合并:文件 ts 更新才采纳)。 */\nfunction ensureState(ctx: Ctx, cwd: string): IndexState {\n const existing = states.get(cwd)\n if (existing) return existing\n const state: IndexState = {\n ctx,\n cwd,\n data: { v: 1, root: null, dirs: {} },\n stale: new Set(),\n dirty: false,\n persistTimer: null,\n healTimer: null,\n pending: new Map(),\n loading: false,\n loadPromise: null,\n }\n states.set(cwd, state)\n state.loadPromise = loadIndex(state)\n // 首次使用该工作区:清理旧版本在工作区根留下的树缓存 sidecar(缓存可重建,删除无损)\n void removeLegacyTreeSidecars(state.cwd)\n return state\n}\n\n/** 清理旧工作区树 sidecar(.dsh-edit-review-tree.json/.dsh-vscode-mode-tree.json)。 */\nexport async function removeLegacyTreeSidecars(cwd: string): Promise<void> {\n await Promise.all(LEGACY_TREE_SIDECARS.map(async (name) => {\n try {\n await rm(join(cwd, name), { force: true })\n } catch (error) { /* 删除失败静默 */ }\n }))\n}\n\n/** 惰性加载落盘快照一次(缺失/损坏 → 空索引;失败静默)。 */\nasync function loadIndex(state: IndexState): Promise<void> {\n if (state.loading) return\n state.loading = true\n try {\n const parsed = indexParse(await readFile(treeCacheFile(state.cwd), 'utf8'))\n if (!parsed) return\n for (const [rel, dir] of Object.entries(parsed.dirs)) {\n const cur = state.data.dirs[rel]\n if (!cur || dir.ts > cur.ts) state.data.dirs[rel] = dir\n }\n if (parsed.root && !state.data.root) state.data.root = parsed.root\n } catch (error) { /* 缺失/损坏/失败均按空索引 */ }\n finally {\n state.loading = false\n }\n}\n\n/** 命中:新鲜且未失效 → 条目(并刷新 ts 保活);否则 null。 */\nexport function hitIndex(cwd: string, rel: string): TreeEntry[] | null {\n const state = states.get(cwd)\n if (!state) return null\n const dir = state.data.dirs[rel]\n if (!dir || state.stale.has(rel)) return null\n const now = Date.now()\n if (now - dir.ts > TREE_TTL_MS) return null\n dir.ts = now\n return dir.entries\n}\n\n/** 更新某目录条目:写内存 + 打脏 + 防抖落盘;stale 撤销。 */\nexport function putIndex(ctx: Ctx, cwd: string, rel: string, entries: TreeEntry[]): void {\n const state = ensureState(ctx, cwd)\n const dirs = state.data.dirs\n if (!dirs[rel] && Object.keys(dirs).length >= MEM_MAX_DIRS) {\n let oldest = rel\n let oldestTs = Infinity\n for (const [k, v] of Object.entries(dirs)) {\n if (v.ts < oldestTs) {\n oldestTs = v.ts\n oldest = k\n }\n }\n delete dirs[oldest]\n }\n dirs[rel] = { ts: nextTs(), full: entries.length <= PERSIST_DIR_ENTRIES, entries }\n state.stale.delete(rel)\n state.dirty = true\n schedulePersist(state)\n}\n\n/** 写入路径失效:父目录+祖先进 stale,并调度后台 re-heal。 */\nexport function invalidateIndex(ctx: Ctx, cwd: string, path: string): void {\n const rel = relOf(cwd, path)\n if (rel === null) return\n const state = ensureState(ctx, cwd)\n for (const anc of ancestorsOf(rel)) state.stale.add(anc)\n scheduleHeal(state)\n}\n\n/** 调度 re-heal(防抖合并;已有定时器则复用)。 */\nfunction scheduleHeal(state: IndexState): void {\n if (state.healTimer) return\n state.healTimer = setTimeout(() => {\n state.healTimer = null\n void healRound(state)\n }, HEAL_DEBOUNCE_MS)\n}\n\n/** 后台自愈一轮:并行重列 ≤HEAL_ROUND_MAX 个 stale 目录;失败移出(交给 TTL/展开路径自愈)。 */\nasync function healRound(state: IndexState): Promise<void> {\n if (!state.stale.size) return\n const targets = [...state.stale].slice(0, HEAL_ROUND_MAX)\n await Promise.all(targets.map(async (rel) => {\n const res = await listDirCached(state.ctx, state.cwd, rel, true)\n if ('error' in res) state.stale.delete(rel)\n }))\n if (state.stale.size) scheduleHeal(state)\n}\n\n/** 调度落盘(防抖;已有定时器则重置)。 */\nfunction schedulePersist(state: IndexState): void {\n if (state.persistTimer) clearTimeout(state.persistTimer)\n state.persistTimer = setTimeout(() => {\n state.persistTimer = null\n void persistNow(state)\n }, PERSIST_DEBOUNCE_MS)\n}\n\n/** 落盘快照(裁剪 + 序列化 + 超限跳过;raw fs 写 ~/.dsh 缓存根,失败静默)。 */\nasync function persistNow(state: IndexState): Promise<void> {\n if (!state.dirty) return\n try {\n const json = indexSerialize(trimPersist(state.data))\n if (json.length > PERSIST_MAX_BYTES) {\n state.dirty = false\n return\n }\n await mkdir(dirname(treeCacheFile(state.cwd)), { recursive: true })\n await writeFile(treeCacheFile(state.cwd), json, 'utf8')\n state.dirty = false\n } catch (error) { /* 写缓存失败静默:内存索引不受影响 */ }\n}\n\n/** 清理某 cwd 索引(会话销毁时):清定时器,dirty 则尽力补写一次。 */\nexport function disposeIndex(cwd: string): void {\n const state = states.get(cwd)\n if (!state) return\n if (state.persistTimer) {\n clearTimeout(state.persistTimer)\n state.persistTimer = null\n }\n if (state.healTimer) {\n clearTimeout(state.healTimer)\n state.healTimer = null\n }\n if (state.dirty) void persistNow(state)\n states.delete(cwd)\n}\n// --endregion\n\n/** 错误 → 用户文案(DirListError 用自身 message,其余带上下文)。 */\nfunction errorText(error: unknown): string {\n if (error instanceof DirListError) return error.message\n return '读取目录失败:' + String(error)\n}\n\n/**\n * 目录列取统一入口(RPC handler 用):命中索引直出;失效/force 走快路径\n * (resolve + listDirCheap + putIndex);同 (cwd,rel) 在途请求复用同一 Promise。\n * @author ddj 2026年08月31号 / 2026年09月01号\n * @param ctx DSH 上下文(仅用于工作区 IO)\n * @param cwd 工作区根\n * @param rel 归一化相对路径('' = 根)\n * @param force 跳过索引命中,强制实列\n * @returns 目录条目与工作区根,或错误文案\n */\nexport async function listDirCached(\n ctx: Ctx,\n cwd: string,\n rel: string,\n force: boolean,\n): Promise<{ entries: TreeEntry[]; root: string } | { error: string }> {\n const state = ensureState(ctx, cwd)\n // 首次请求等待落盘快照加载完成(此后命中快照;加载失败则照常实列)\n if (state.loadPromise) await state.loadPromise\n const fs = ctx.get('fs')\n if (!fs) return { error: '缺少 fs' }\n if (!state.data.root) {\n try {\n state.data.root = String(fs.processPath(await fs.resolve('.', { cwd })))\n } catch (error) {\n return { error: errorText(error) }\n }\n }\n const root = state.data.root as string\n if (!force) {\n const hit = hitIndex(cwd, rel)\n if (hit) return { entries: hit, root }\n }\n const inflight = state.pending.get(rel)\n if (inflight) {\n const res = await inflight\n return 'entries' in res ? { entries: res.entries, root } : res\n }\n const task = (async (): Promise<{ entries: TreeEntry[] } | { error: string }> => {\n try {\n const target = await fs.resolve(rel || '.', { cwd })\n const children = await listDirCheap(target.targetKey)\n const entries = toTreeEntries(rel, children)\n putIndex(ctx, cwd, rel, entries)\n return { entries }\n } catch (error) {\n // 目录已被外部删除:从索引移除,避免陈旧条目长期滞留\n if (error instanceof DirListError && error.code === 'not-found') {\n if (state.data.dirs[rel]) {\n delete state.data.dirs[rel]\n state.dirty = true\n schedulePersist(state)\n }\n state.stale.delete(rel)\n }\n return { error: errorText(error) }\n }\n })()\n state.pending.set(rel, task)\n try {\n const res = await task\n return 'entries' in res ? { entries: res.entries, root } : res\n } finally {\n if (state.pending.get(rel) === task) state.pending.delete(rel)\n }\n}\n","/**\n * dsh-vscode-mode host — 捕获层:监听 tools/result,把 edit/write 差异落成审查记录。\n * 迁移自原 src/index.ts 的 tools/result 处理,语义不改。\n * 作者 ddj 2026-08-20\n */\nimport type { DiffRecord, Hunk } from './shared/types.js'\nimport { annotateHunks, fingerprint } from './shared/diff.js'\nimport type { Ctx, Session } from './store.js'\nimport { loadBucket, saveBucket } from './store.js'\nimport { fileMaxBatch, prune } from './model.js'\nimport type { Registry } from './registry.js'\nimport { cwdOf } from './registry.js'\nimport { invalidateIndex } from './treeIndex.js'\nimport { log } from './log.js'\n\n/** 校验并提取工具 result meta 中的文件 hunk。 */\nfunction validHunks(raw: unknown): Hunk[] {\n if (!Array.isArray(raw)) return []\n const hunks: Hunk[] = []\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const hunk = item as Record<string, unknown>\n if (typeof hunk.newText !== 'string') continue\n if (hunk.oldText !== null && typeof hunk.oldText !== 'string') continue\n hunks.push({ oldText: hunk.oldText as string | null, newText: hunk.newText })\n }\n return hunks\n}\n\n/** 已有文件 write 的元数据缺失时,用权威整文件快照保底。 */\nfunction fallbackHunks(toolName: string, args: Record<string, unknown>, before: string | null, after: string | null, create: boolean): Hunk[] {\n if (create) return [{ oldText: null, newText: after ?? (typeof args.content === 'string' ? args.content : '') }]\n if (toolName === 'edit' && typeof args.old_string === 'string' && typeof args.new_string === 'string') {\n return [{ oldText: args.old_string, newText: args.new_string }]\n }\n if (toolName === 'write' && before !== null && after !== null && before !== after) {\n return [{ oldText: before, newText: after }]\n }\n if (toolName === 'write' && after !== null) return [{ oldText: null, newText: after }]\n return []\n}\n\n/**\n * 捕获一次工具执行结果(tools/result):edit/write 成功时构造记录、\n * 递增文件批次、融合归档被后续修改取代的旧差异、落盘。\n * @author ddj 2026年08月20号\n * @param ctx DSH 上下文\n * @param registry 工作区记录桶注册表\n * @param exec 工具执行描述(name/arguments/callId/agent.session)\n * @param result 执行结果(value/meta/isError)\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function captureToolResult(ctx: Ctx, registry: Registry, exec: any, result: any): Promise<void> {\n const session: Session | undefined = exec?.agent?.session\n if (!session || (exec?.name !== 'edit' && exec?.name !== 'write')) return\n if (result?.isError || !result?.value) return\n try {\n const cwd = cwdOf(session)\n if (!cwd) return\n const value = result.value\n const args = (exec.arguments || {}) as Record<string, unknown>\n const path = typeof value.path === 'string' ? value.path : args.file_path\n if (typeof path !== 'string' || !path) return\n const before = typeof value.before === 'string' ? value.before : null\n const after = typeof value.after === 'string' ? value.after : (typeof args.content === 'string' ? args.content : null)\n const create = exec.name === 'write' && value.before === null\n const callHunk = exec.name === 'edit' && typeof args.old_string === 'string' && typeof args.new_string === 'string'\n ? { oldText: args.old_string, newText: args.new_string }\n : null\n const metaHunks = validHunks(result.meta?.diffs)\n const rawHunks = metaHunks.length ? metaHunks : fallbackHunks(exec.name, args, before, after, create)\n const hunks = annotateHunks(rawHunks, before, after)\n if (!hunks.length || typeof exec.callId !== 'string') return\n const record: DiffRecord = {\n callId: exec.callId,\n toolName: exec.name,\n path,\n before,\n after,\n baseFingerprint: fingerprint(before),\n afterFingerprint: fingerprint(after),\n legacy: false,\n conflict: false,\n create,\n callHunk,\n hunks,\n decisions: { call: 'pending', perHunk: hunks.map(() => 'pending') },\n note: create ? '新建文件:全部拒绝将删除该文件' : before === null ? '未捕获修改前内容(大文件)' : null,\n superseded: false,\n archived: false,\n batch: 0,\n at: new Date().toISOString(),\n }\n let bucket = registry.get(cwd)\n if (!bucket) { bucket = await loadBucket(ctx, cwd); registry.set(cwd, bucket) }\n record.batch = fileMaxBatch(bucket, path) + 1\n bucket.set(exec.callId, record)\n // 同一文件的多次 edit/write 都保留为独立记录,便于逐条审查。\n // 旧实现按文件 batch 自动归档 prior,会导致界面看起来每个文件只剩一条差异。\n prune(bucket)\n await saveBucket(ctx, cwd, bucket, session)\n // agent 写盘后目录树可能变化(新建/删除文件/目录):父目录+祖先进失效,后台自愈。\n invalidateIndex(ctx, cwd, path)\n } catch (error) {\n log.error('capture failed: ' + String(error))\n }\n}\n","/**\n * dsh-vscode-mode host — 搜索 query 与路径规范化。\n * 查询只按字面连续片段比较,不解释为正则或 shell 语句。\n * 作者 ddj 2026年08月24号\n */\nimport { isAbsolute, resolve } from 'node:path'\nimport type { PreparedQuery } from './types.js'\n\n/**\n * 规范化用户搜索文本。\n * @author ddj 2026年08月24号\n * @param raw 原始搜索文本\n * @returns 用于比较和缓存的 query\n */\nexport function prepareQuery(raw: unknown): PreparedQuery {\n const value = String(raw ?? '').trim()\n return { raw: value, text: value.replaceAll('\\\\', '/').toLocaleLowerCase('en-US') }\n}\n\n/**\n * 归一化路径分隔符并移除无意义前缀。\n * @author ddj 2026年08月24号\n * @param value 原始路径\n * @returns 比较用路径\n */\nexport function pathText(value: string): string {\n return value.replaceAll('\\\\', '/').replace(/^\\.\\//, '')\n}\n\n/**\n * 生成不区分大小写的路径 key。\n * @author ddj 2026年08月24号\n * @param value 原始路径\n * @returns 去重 key\n */\nexport function pathKey(value: string): string {\n return pathText(value).toLocaleLowerCase('en-US')\n}\n\n/**\n * 将相对文件路径映射到 provider 根目录。\n * @author ddj 2026年08月24号\n * @param value 文件路径\n * @param root 工作区根目录\n * @returns 可供 edrv.read 使用的路径\n */\nexport function displayPath(value: string, root: string): string {\n const normalized = pathText(value)\n if (isAbsolute(normalized) || /^[A-Za-z]:\\//.test(normalized) || normalized.startsWith('//')) return normalized\n return resolve(root, normalized)\n}\n\n/**\n * 判断路径是否包含连续 query。\n * @author ddj 2026年08月24号\n * @param value 文件路径\n * @param query 已规范化 query\n * @returns 是否命中\n */\nexport function pathMatch(value: string, query: PreparedQuery): boolean {\n return pathText(value).toLocaleLowerCase('en-US').includes(query.text)\n}\n","/**\n * dsh-vscode-mode host — ripgrep 文件发现 provider。\n * 通过独立 argv 调用打包 rg,避免先构建巨型全量文件数组。\n * 作者 ddj 2026年08月24号\n */\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { createRequire } from 'node:module'\nimport type { Ctx, Session } from '../store.js'\nimport { policyOf } from '../store.js'\nimport { prepareQuery, pathText } from './query.js'\nimport type { WorkspaceSearchInput, WorkspaceSearchProvider, WorkspaceSearchResult } from './types.js'\n\nconst STDOUT_CAP = 4 << 20\nconst STDERR_CAP = 64 << 10\nconst GRACE_MS = 20_000\n\n/** 默认排除目录(文件/内容搜索共用,导出供 provider 复用)。 */\nexport const EXCLUDES = [\n 'node_modules', '.git', '.tmp', '.cache', 'dist', 'build', 'vendor',\n 'coverage', '__pycache__', '.pnpm-store', '.npm-cache', '.codegraph', '.workbuddy',\n]\n\n/**\n * 默认排除文件(glob 模式,文件/内容搜索共用)。\n * 插件自身 sidecar(内容搜索会命中其历史编辑文本,且单行巨型 JSON 会撑爆输出上限);\n * *.map 源映射(纯构建产物,内容搜索无意义且常为单行巨文件)。\n */\nexport const FILE_EXCLUDES = [\n '**/.dsh-edit-review.json',\n '**/.dsh-edit-review-archive.json',\n '**/.dsh-edit-review-debug.log',\n '**/*.map',\n]\n\ninterface SearchHandle {\n done: Promise<{ exitCode: number | null; code?: number | null }>\n collected?: {\n stdout?: { readFrom(offset: number): { text: string; lossy?: boolean } }\n stderr?: { readFrom(offset: number): { text: string } }\n }\n}\n\ninterface SearchSubprocess {\n spawn(spec: {\n argv: readonly string[]\n cwd: string\n stdio: { stdin: 'ignore'; stdout: { maxBytes: number }; stderr: { maxBytes: number } }\n graceMs: number\n signal?: AbortSignal\n }): SearchHandle\n}\n\n/**\n * 将 query 转成 rg 的字面 glob。\n * @author ddj 2026年08月24号\n * @param query 已规范化 query\n * @returns 安全 glob\n */\nexport function queryGlob(query: string): string {\n const value = pathText(query)\n const escaped = value.replace(/[\\*?\\[\\]{}!]/g, (char) => '\\\\' + char)\n return '**/*' + escaped + '*'\n}\n\n/**\n * 返回当前平台的 rg 可执行文件路径,不让可选依赖影响模块加载。\n * @author ddj 2026年08月24号\n * @returns rg 路径或 null\n */\nexport function ripgrepPath(): string | null {\n try {\n const require = createRequire(import.meta.url)\n const ripgrep = require('@vscode/ripgrep') as { rgPath?: unknown }\n if (typeof ripgrep.rgPath !== 'string' || !existsSync(ripgrep.rgPath)) return null\n return join(ripgrep.rgPath)\n } catch (error) {\n return null\n }\n}\n\n/**\n * 解析会话搜索根目录,并转换到 subprocess 执行世界。\n * @author ddj 2026年08月24号\n * @param ctx DSH 上下文\n * @param session 当前会话\n * @returns subprocess 可访问的根目录\n */\nexport async function searchRoot(ctx: Ctx, session: Session): Promise<string> {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs')\n const policy = policyOf(ctx, session)\n const cwd = session?.header?.cwd\n const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', cwd ? { cwd } : {})\n return fs.processPath(rootTarget)\n}\n\n/**\n * 读取收集输出并解析为路径候选。\n * @author ddj 2026年08月24号\n * @param handle subprocess handle\n * @param maxResults 候选上限\n * @returns 路径与完整性状态\n */\nexport function parseOutput(handle: SearchHandle, maxResults: number): { files: string[]; truncated: boolean; complete: boolean } {\n const reader = handle.collected?.stdout\n if (!reader) return { files: [], truncated: false, complete: false }\n const output = reader.readFrom(0)\n const values = output.text.split(/\\r?\\n/).map((line) => line.trim()).filter(Boolean)\n const unique = [...new Set(values)]\n const truncated = Boolean(output.lossy) || unique.length > maxResults\n return { files: unique.slice(0, maxResults).map(pathText), truncated, complete: !truncated }\n}\n\n/**\n * 读取已收集的 stderr(无收集器 → 空文本)。\n * @author ddj 2026年08月27号\n * @param handle subprocess handle\n * @returns stderr 文本\n */\nexport function readStderr(handle: SearchHandle): { text: string } {\n const reader = handle.collected?.stderr\n return reader ? reader.readFrom(0) : { text: '' }\n}\n\n/**\n * 取 stderr 首条非空行(去 \\r,截断 300 字符防撑爆 UI)。\n * @author ddj 2026年08月27号\n * @param text stderr 全文\n * @returns 首条诊断行(无则空串)\n */\nexport function firstStderrLine(text: string): string {\n for (const raw of String(text ?? '').split(/\\r?\\n/)) {\n const line = raw.trim()\n if (!line) continue\n return line.length > 300 ? line.slice(0, 300) + '…' : line\n }\n return ''\n}\n\n/**\n * 分类 rg 非 0/1 退出:pattern=模式错误(正则/glob 无效,无结果),\n * partial=遍历错误(rg 已输出的命中仍有效,结果不完整),hard=硬失败(其他退出码/超时被杀)。\n * @author ddj 2026年08月27号\n * @param code 退出码(null/undefined = 被终止,通常为 20s 超时)\n * @param stderrText stderr 全文\n * @returns 分类与中文提示文案(partial 的 message 即 warning 内容)\n */\nexport function rgExitFailure(code: number | null | undefined, stderrText: string): { kind: 'pattern' | 'partial' | 'hard'; message: string } {\n const detail = firstStderrLine(stderrText)\n if (/regex parse error/i.test(detail)) return { kind: 'pattern', message: '正则表达式无效:' + detail }\n if (/error parsing glob/i.test(detail)) return { kind: 'pattern', message: '文件过滤模式无效:' + detail }\n if (code === 2) {\n const count = String(stderrText ?? '').split(/\\r?\\n/).filter((line) => line.trim()).length\n const suffix = count > 1 ? '(共 ' + count + ' 处)' : ''\n return { kind: 'partial', message: (detail ? '部分路径无法访问,结果可能不完整:' + detail + suffix : '部分路径无法访问,结果可能不完整') }\n }\n if (code === null || code === undefined) return { kind: 'hard', message: '搜索超时(20 秒内未完成,已终止)' }\n return { kind: 'hard', message: 'ripgrep 退出码:' + String(code) + (detail ? '(' + detail + ')' : '') }\n}\n\n/**\n * 使用打包 ripgrep 搜索工作区文件。\n * @author ddj 2026年08月24号\n * @param input provider 输入\n * @returns 有界搜索结果\n */\nexport async function searchRipgrep(input: WorkspaceSearchInput): Promise<WorkspaceSearchResult> {\n const sub = input.ctx.get('subprocess') as SearchSubprocess | undefined\n if (!sub) throw new Error('缺少 subprocess')\n const binary = ripgrepPath()\n if (!binary) throw new Error('ripgrep 不可用')\n const root = input.root ?? await searchRoot(input.ctx, input.session)\n const query = prepareQuery(input.query)\n const argv = [binary, '--no-config', '--files', '--hidden', '--no-ignore', '--glob-case-insensitive', '--glob', queryGlob(query.text)]\n for (const excluded of EXCLUDES) argv.push('--glob', '!**/' + excluded + '/**')\n for (const excluded of FILE_EXCLUDES) argv.push('--glob', '!' + excluded)\n argv.push('--', root)\n const handle = sub.spawn({\n argv,\n cwd: root,\n stdio: { stdin: 'ignore', stdout: { maxBytes: STDOUT_CAP }, stderr: { maxBytes: STDERR_CAP } },\n graceMs: GRACE_MS,\n signal: input.signal,\n })\n let outcome: { exitCode: number | null; code?: number | null }\n try {\n outcome = await handle.done\n } catch (error) {\n throw new Error('ripgrep 启动失败:' + String(error))\n }\n const code = outcome.exitCode ?? outcome.code\n if (code !== 0 && code !== 1) {\n const failure = rgExitFailure(code, readStderr(handle).text)\n if (failure.kind !== 'partial') throw new Error(failure.message)\n // 遍历错误:已收集的文件列表仍有效,保留并标记不完整(warning 供上层展示,编排层丢弃不抛错)\n const parsed = parseOutput(handle, input.maxResults)\n return { ...parsed, warning: failure.message, complete: false, source: 'ripgrep' }\n }\n const parsed = parseOutput(handle, input.maxResults)\n if (!handle.collected?.stdout) throw new Error('ripgrep stdout 不可用')\n return { ...parsed, source: 'ripgrep' }\n}\n\n/**\n * 构造 ripgrep provider。\n * @author ddj 2026年08月24号\n * @returns provider 实例\n */\nexport function newRgProvider(): WorkspaceSearchProvider {\n return { search: searchRipgrep }\n}\n","/**\n * dsh-vscode-mode host — fs.listDir 查询感知 fallback。\n * provider 不可用时边遍历边匹配,不再伪装有限全量扫描为完整索引。\n * 作者 ddj 2026年08月24号\n */\nimport type { Ctx, Session } from '../store.js'\nimport { policyOf } from '../store.js'\nimport { pathText, pathMatch } from './query.js'\nimport { searchRoot } from './ripgrep.js'\nimport type { WorkspaceSearchInput, WorkspaceSearchProvider, WorkspaceSearchResult } from './types.js'\n\ninterface FsTarget { displayPath?: string }\ninterface FsEntry { name: string; type: 'file' | 'directory' | 'other'; target: FsTarget }\ninterface SearchFs {\n resolve(path: string, opts?: { cwd?: string; signal?: AbortSignal }): Promise<FsTarget>\n listDir(target: FsTarget, signal?: AbortSignal): Promise<FsEntry[]>\n}\n\nconst RESULT_CAP = 500\nconst EXCLUDED = new Set(['node_modules', '.git', '.tmp', '.cache', 'dist', 'build', 'vendor', 'coverage', '__pycache__', '.pnpm-store', '.npm-cache', '.codegraph', '.workbuddy', '.dsh-edit-review.json', '.dsh-edit-review-archive.json', '.dsh-edit-review-debug.log'])\n\n/**\n * 在一个目录树中递归查找匹配文件。\n * @author ddj 2026年08月24号\n * @param fs 文件系统能力\n * @param target 当前目录目标\n * @param input 搜索输入\n * @param files 已保留候选\n * @param signal 取消信号\n * @returns 是否因达到上限而截断\n */\nasync function walk(fs: SearchFs, target: FsTarget, input: WorkspaceSearchInput, files: string[], signal: AbortSignal): Promise<boolean> {\n if (signal.aborted) throw new DOMException('搜索已取消', 'AbortError')\n const entries = await fs.listDir(target, signal)\n for (const entry of entries) {\n if (signal.aborted) throw new DOMException('搜索已取消', 'AbortError')\n if (entry.type === 'directory') {\n if (EXCLUDED.has(entry.name)) continue\n if (await walk(fs, entry.target, input, files, signal)) return true\n continue\n }\n if (entry.type !== 'file') continue\n const path = pathText(entry.target.displayPath ?? entry.name)\n if (!pathMatch(path, { raw: input.query, text: pathText(input.query).toLocaleLowerCase('en-US') })) continue\n files.push(path)\n if (files.length >= Math.min(input.maxResults, RESULT_CAP)) return true\n }\n return false\n}\n\n/**\n * 使用 ctx.fs.listDir 搜索文件。\n * @author ddj 2026年08月24号\n * @param input provider 输入\n * @returns 有界 fallback 结果\n */\nexport async function searchFallback(input: WorkspaceSearchInput): Promise<WorkspaceSearchResult> {\n const fs = input.ctx.get('fs') as SearchFs | undefined\n if (!fs) throw new Error('缺少 fs')\n const policy = policyOf(input.ctx, input.session)\n const cwd = input.session?.header?.cwd\n const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', cwd ? { cwd, signal: input.signal } : { signal: input.signal })\n const signal = input.signal ?? new AbortController().signal\n const files: string[] = []\n const truncated = await walk(fs, rootTarget, input, files, signal)\n return { files, truncated, complete: !truncated, source: 'fallback' }\n}\n\n/**\n * 构造 fallback provider。\n * @author ddj 2026年08月24号\n * @returns provider 实例\n */\nexport function newFallback(): WorkspaceSearchProvider {\n return { search: searchFallback }\n}\n","/**\n * dsh-vscode-mode host — 可替换的连续匹配排序器。\n * 第一版保持 basename 优先和稳定路径序,后续可接 fuzzy scorer。\n * 作者 ddj 2026年08月24号\n */\nimport type { CandidateRanker, PreparedQuery, SearchCandidate } from './types.js'\nimport { pathText } from './query.js'\n\n/**\n * 生成搜索候选。\n * @author ddj 2026年08月24号\n * @param path 文件路径\n * @param source 候选来源\n * @returns 内部候选\n */\nexport function candidateOf(path: string, source: SearchCandidate['source']): SearchCandidate {\n const normalizedPath = pathText(path)\n const basename = normalizedPath.split('/').pop() ?? normalizedPath\n return { path, basename, normalizedPath: normalizedPath.toLocaleLowerCase('en-US'), source }\n}\n\n/**\n * 对连续匹配候选进行排序。\n * @author ddj 2026年08月24号\n * @param candidates 候选列表\n * @param query 已规范化 query\n * @returns 排序后的候选\n */\nexport function rankCandidates(candidates: SearchCandidate[], query: PreparedQuery): SearchCandidate[] {\n const text = query.text\n const score = (candidate: SearchCandidate): number => {\n const base = candidate.basename.toLocaleLowerCase('en-US')\n if (base.startsWith(text)) return 0\n if (base.includes(text)) return 1\n if (candidate.normalizedPath.includes(text)) return 2\n return 3\n }\n return [...candidates].sort((left, right) => score(left) - score(right) || left.normalizedPath.localeCompare(right.normalizedPath, 'en-US'))\n}\n\n/**\n * 默认候选排序器。\n * @author ddj 2026年08月24号\n * @returns 排序器\n */\nexport function substringRanker(): CandidateRanker {\n return { rank: rankCandidates }\n}\n","/**\n * dsh-vscode-mode host — 搜索编排、缓存和旧任务取消。\n * 对外只返回旧 RPC 所需的 files/truncated,内部保留 provider 边界。\n * 作者 ddj 2026年08月24号\n */\nimport type { Ctx, Session } from '../store.js'\nimport { policyOf } from '../store.js'\nimport { pathKey, pathMatch, pathText, prepareQuery } from './query.js'\nimport { searchRoot } from './ripgrep.js'\nimport { newRgProvider } from './ripgrep.js'\nimport { newFallback } from './fallback.js'\nimport { candidateOf, rankCandidates } from './ranker.js'\nimport type { CandidateRanker, SearchCandidate, WorkspaceSearchProvider, WorkspaceSearchResult } from './types.js'\n\nconst CACHE_TTL = 60_000\nconst CACHE_LIMIT = 100\nconst RESULT_LIMIT = 50\nconst PROVIDER_VERSION = 'ripgrep-v1'\nconst POLICY_VERSION = 'search-policy-v1'\n\ntype CacheEntry<T> = { at: number; result: T }\ntype SearchRequest = { session: Session; cwd: string; query: string; activePaths: string[] }\ntype SearchResponse = { files: string[]; truncated: boolean }\n\n/**\n * 短期有界搜索缓存(泛型:文件/内容搜索共用;clone 由调用方保证写隔离)。\n * @author ddj 2026年08月24号\n * @param clone 结果写隔离克隆(缺省恒等)\n */\nexport class SearchCache<T> {\n private readonly entries = new Map<string, CacheEntry<T>>()\n\n /**\n * 创建缓存。\n * @author ddj 2026年08月24号\n * @param clone 结果克隆函数(缺省直接引用)\n */\n constructor(private readonly clone: (value: T) => T = (value) => value) {}\n\n /**\n * 读取未过期条目。\n * @author ddj 2026年08月24号\n * @param key 缓存 key\n * @param now 当前时间\n * @returns 缓存结果或 undefined\n */\n get(key: string, now = Date.now()): T | undefined {\n const entry = this.entries.get(key)\n if (!entry) return undefined\n if (now - entry.at >= CACHE_TTL) { this.entries.delete(key); return undefined }\n this.entries.delete(key)\n this.entries.set(key, entry)\n return this.clone(entry.result)\n }\n\n /**\n * 写入成功 provider 结果。\n * @author ddj 2026年08月24号\n * @param key 缓存 key\n * @param result provider 结果\n * @param now 当前时间\n */\n set(key: string, result: T, now = Date.now()): void {\n this.entries.delete(key)\n this.entries.set(key, { at: now, result: this.clone(result) })\n while (this.entries.size > CACHE_LIMIT) this.entries.delete(this.entries.keys().next().value as string)\n }\n\n /**\n * 清理指定根目录的缓存。\n * @author ddj 2026年08月24号\n * @param root 工作区根目录\n */\n clearRoot(root: string): void {\n for (const key of this.entries.keys()) if (key.startsWith(root + '|')) this.entries.delete(key)\n }\n\n /**\n * 清空全部缓存。\n * @author ddj 2026年08月24号\n */\n clear(): void { this.entries.clear() }\n}\n\n/**\n * 获取 policy 版本,未知策略使用固定插件版本。\n * @author ddj 2026年08月24号\n * @param ctx DSH 上下文\n * @param session 当前会话\n * @returns 稳定版本文本\n */\nfunction policyVersion(ctx: Ctx, session: Session): string {\n const policy = policyOf(ctx, session)\n const version = policy?.version ?? policy?.policyVersion\n return typeof version === 'string' || typeof version === 'number' ? String(version) : POLICY_VERSION\n}\n\n/**\n * 将 root 内绝对路径统一成相对显示路径。\n * @author ddj 2026年08月24号\n * @param value 原始路径\n * @param root 搜索根\n * @returns 兼容 edrv.read 的路径\n */\nfunction displayPath(value: string, root: string): string {\n const path = pathText(value)\n const base = pathText(root).replace(/\\/$/, '')\n const lowerPath = path.toLocaleLowerCase('en-US')\n const lowerBase = base.toLocaleLowerCase('en-US')\n if (lowerPath === lowerBase) return '.'\n if (lowerPath.startsWith(lowerBase + '/')) return path.slice(base.length + 1)\n return path\n}\n\n/**\n * 为显示路径生成跨绝对/相对形式的去重 key。\n * @author ddj 2026年08月24号\n * @param value 原始路径\n * @param root 搜索根\n * @returns 去重 key\n */\nfunction displayKey(value: string, root: string): string {\n return pathKey(displayPath(value, root))\n}\n\n/**\n * 合并 provider 与 active diff 候选并去重。\n * @author ddj 2026年08月24号\n * @param result provider 结果\n * @param activePaths 活跃差异路径\n * @param root 搜索根\n * @param query 已规范化 query\n * @returns 候选列表\n */\nfunction mergeCandidates(result: WorkspaceSearchResult, activePaths: string[], root: string, query: ReturnType<typeof prepareQuery>): SearchCandidate[] {\n const candidates = new Map<string, SearchCandidate>()\n for (const path of result.files) {\n const shown = displayPath(path, root)\n if (pathMatch(shown, query)) candidates.set(displayKey(path, root), candidateOf(shown, 'workspace'))\n }\n for (const path of activePaths) {\n const shown = displayPath(path, root)\n if (!pathMatch(shown, query)) continue\n const key = displayKey(path, root)\n if (!candidates.has(key)) candidates.set(key, candidateOf(shown, 'active-diff'))\n }\n return [...candidates.values()]\n}\n\n/**\n * 搜索编排器。\n * @author ddj 2026年08月24号\n */\nexport class SearchOrchestrator {\n private readonly cache = new SearchCache<WorkspaceSearchResult>((r) => ({ ...r, files: [...r.files] }))\n private readonly inflight = new Map<string, AbortController>()\n private readonly rootsByCwd = new Map<string, Set<string>>()\n private readonly provider: WorkspaceSearchProvider\n private readonly fallback: WorkspaceSearchProvider\n private readonly ranker: CandidateRanker\n\n /**\n * 创建搜索编排器。\n * @author ddj 2026年08月24号\n * @param ctx DSH 上下文\n * @param provider 主 provider,可替换测试\n * @param fallback 降级 provider,可替换测试\n * @param ranker 排序器,可替换测试\n */\n constructor(private readonly ctx: Ctx, provider = newRgProvider(), fallback = newFallback(), ranker: CandidateRanker = { rank: rankCandidates }) {\n this.provider = provider\n this.fallback = fallback\n this.ranker = ranker\n }\n\n /**\n * 执行一次工作区搜索。\n * @author ddj 2026年08月24号\n * @param request 搜索请求\n * @returns 旧 RPC 响应字段\n */\n async search(request: SearchRequest): Promise<SearchResponse> {\n const query = prepareQuery(request.query)\n if (query.text.length < 2) return { files: [], truncated: false }\n let root: string\n try { root = await searchRoot(this.ctx, request.session) } catch (error) {\n return this.rankActive(request.activePaths, request.cwd, query)\n }\n const rootKey = pathText(root)\n const roots = this.rootsByCwd.get(request.cwd) ?? new Set<string>()\n roots.add(rootKey)\n this.rootsByCwd.set(request.cwd, roots)\n const key = [rootKey, query.text, policyVersion(this.ctx, request.session), PROVIDER_VERSION].join('|')\n const cached = this.cache.get(key)\n if (cached) return this.finish(cached, request.activePaths, root, query)\n this.inflight.get(root)?.abort()\n const controller = new AbortController()\n this.inflight.set(root, controller)\n try {\n let result: WorkspaceSearchResult\n let providerOk = true\n try {\n result = await this.provider.search({ ctx: this.ctx, session: request.session, cwd: request.cwd, query: query.raw, maxResults: 500, signal: controller.signal, root })\n } catch (error) {\n providerOk = false\n if (controller.signal.aborted) return { files: [], truncated: false }\n try {\n result = await this.fallback.search({ ctx: this.ctx, session: request.session, cwd: request.cwd, query: query.raw, maxResults: 500, signal: controller.signal, root })\n } catch (fallbackError) {\n return this.rankActive(request.activePaths, root, query)\n }\n }\n if (controller.signal.aborted) return { files: [], truncated: false }\n if (providerOk) this.cache.set(key, result)\n return this.finish(result, request.activePaths, root, query)\n } finally {\n if (this.inflight.get(root) === controller) this.inflight.delete(root)\n }\n }\n\n /**\n * 清理会话对应根目录的缓存和在途搜索。\n * @author ddj 2026年08月24号\n * @param cwd 会话工作区\n */\n dispose(cwd: string): void {\n const roots = this.rootsByCwd.get(cwd) ?? new Set<string>([cwd])\n for (const root of roots) {\n this.inflight.get(root)?.abort()\n this.inflight.delete(root)\n this.cache.clearRoot(root)\n }\n this.rootsByCwd.delete(cwd)\n }\n\n /**\n * 清理全部状态。\n * @author ddj 2026年08月24号\n */\n disposeAll(): void {\n for (const controller of this.inflight.values()) controller.abort()\n this.inflight.clear()\n this.rootsByCwd.clear()\n this.cache.clear()\n }\n\n /**\n * 将 provider 结果与 active diff 合并、排序和截断。\n * @author ddj 2026年08月24号\n * @param result provider 结果\n * @param activePaths active diff 路径\n * @param root 搜索根\n * @param query 已规范化 query\n * @returns 旧 RPC 响应字段\n */\n private finish(result: WorkspaceSearchResult, activePaths: string[], root: string, query: ReturnType<typeof prepareQuery>): SearchResponse {\n const candidates = this.ranker.rank(mergeCandidates(result, activePaths, root, query), query)\n return { files: candidates.slice(0, RESULT_LIMIT).map((candidate) => candidate.path), truncated: result.truncated || candidates.length > RESULT_LIMIT }\n }\n\n /**\n * provider 失败时仅保留 active diff 命中。\n * @author ddj 2026年08月24号\n * @param paths active diff 路径\n * @param root 搜索根\n * @param query 已规范化 query\n * @returns 旧 RPC 响应字段\n */\n private rankActive(paths: string[], root: string, query: ReturnType<typeof prepareQuery>): SearchResponse {\n const result: WorkspaceSearchResult = { files: [], truncated: false, complete: true, source: 'active-diff' }\n return this.finish(result, paths, root, query)\n }\n}\n\n/**\n * 创建默认编排器。\n * @author ddj 2026年08月24号\n * @param ctx DSH 上下文\n * @returns 搜索编排器\n */\nexport function newSearcher(ctx: Ctx): SearchOrchestrator {\n return new SearchOrchestrator(ctx)\n}\n","/**\n * dsh-vscode-mode host — 工作区内容搜索(rg --json 主路径 + 有界编排)。\n * 命中列由 rg 行内字节偏移转 UTF-16(1-based),可直接供 Monaco 跳转/高亮。\n * 无 fallback:provider 失败抛错,由 RPC 层转错误响应(避免整树读文件)。\n * 作者 ddj 2026年08月26号\n */\nimport type { Ctx, Session } from '../store.js'\nimport { pathText } from './query.js'\nimport { EXCLUDES, FILE_EXCLUDES, readStderr, rgExitFailure, ripgrepPath, searchRoot } from './ripgrep.js'\nimport { SearchCache } from './orchestrator.js'\nimport type { ContentMatch, ContentSearchInput, ContentSearchProvider, ContentSearchResult } from './types.js'\n\nconst STDOUT_CAP = 16 << 20\nconst STDERR_CAP = 64 << 10\nconst GRACE_MS = 20_000\nconst DEFAULT_MAX_MATCHES = 500\nconst DEFAULT_MAX_FILES = 100\nconst CACHE_TTL = 60_000\nconst CACHE_LIMIT = 100\nconst PROVIDER_VERSION = 'content-ripgrep-v1'\n/** 单行 JSON 记录上限:巨型单行文件(源映射/打包产物)的命中行对搜索 UI 无意义,直接跳过。 */\nconst MAX_RECORD_LINE = 1 << 20\n\n/** rg --json 单条 match 记录的宽松形状(未知字段忽略)。 */\ninterface RgJsonItem {\n type?: string\n data?: {\n path?: { text?: string }\n lines?: { text?: string }\n line_number?: number\n submatches?: Array<{ start?: number; end?: number }>\n }\n}\n\n/** 内容搜索请求(RPC 参数映射)。 */\nexport interface ContentSearchRequest {\n session: Session\n cwd: string\n query: string\n matchCase?: boolean\n wholeWord?: boolean\n regex?: boolean\n maxResults?: number\n /** 正选 glob(仅在这些文件内搜索)。 */\n include?: string[]\n /** 排除 glob(这些文件不参与搜索)。 */\n exclude?: string[]\n}\n\ntype ContentSearchResponse = { matches: ContentMatch[]; truncated: boolean; warning?: string }\n\n/**\n * 把行内字节偏移转成 UTF-16 列(1-based;越界钳到行尾)。\n * @author ddj 2026年08月26号\n * @param text 行文本\n * @param byteOffset 行内字节偏移(rg submatches.start/end,实测为行相对)\n * @returns 1-based UTF-16 列\n */\nexport function byteToUtf16Col(text: string, byteOffset: number): number {\n let bytes = 0\n let col = 1\n for (const char of text) {\n if (bytes >= byteOffset) break\n bytes += Buffer.byteLength(char)\n col++\n }\n return col\n}\n\n/**\n * 根内绝对路径 → 工作区相对显示路径(供 edrv.read 与面板展示)。\n * @author ddj 2026年08月26号\n * @param value rg 输出路径\n * @param root 搜索根(subprocess 执行世界)\n * @returns 相对路径(根外路径原样返回)\n */\nexport function displayPathOf(value: string | undefined, root: string): string {\n const path = pathText(String(value ?? ''))\n if (!path) return path\n const base = pathText(root).replace(/\\/$/, '')\n const lowerPath = path.toLocaleLowerCase('en-US')\n const lowerBase = base.toLocaleLowerCase('en-US')\n if (lowerPath === lowerBase) return '.'\n if (lowerPath.startsWith(lowerBase + '/')) return path.slice(base.length + 1)\n return path\n}\n\n/**\n * 解析 rg --json 输出为扁平命中列表(多子匹配展开,列转 UTF-16)。\n * @author ddj 2026年08月26号\n * @param text stdout 文本\n * @param root 搜索根\n * @returns 命中列表\n */\nexport function parseRgJsonLines(text: string, root: string): ContentMatch[] {\n const matches: ContentMatch[] = []\n for (const line of text.split(/\\r?\\n/)) {\n const trimmed = line.trim()\n if (!trimmed) continue\n let item: RgJsonItem\n try {\n item = JSON.parse(trimmed) as RgJsonItem\n } catch {\n continue\n }\n if (item?.type !== 'match' || !item.data) continue\n const data = item.data\n const path = displayPathOf(data.path?.text, root)\n const lineText = (data.lines?.text ?? '').replace(/\\r?\\n$/, '').replace(/\\r$/, '')\n if (lineText.length > MAX_RECORD_LINE) continue\n const lineNumber = data.line_number ?? 0\n for (const sub of data.submatches ?? []) {\n matches.push({\n path,\n line: lineNumber,\n startColumn: byteToUtf16Col(lineText, sub.start ?? 0),\n endColumn: byteToUtf16Col(lineText, sub.end ?? 0),\n text: lineText,\n })\n }\n }\n return matches\n}\n\n/**\n * 命中截断:匹配数/文件数双上限,超限标记 truncated。\n * @author ddj 2026年08月26号\n * @param matches 全部命中\n * @param maxMatches 匹配数上限\n * @param maxFiles 文件数上限\n * @returns 截断后的命中与标志\n */\nexport function applyCaps(matches: ContentMatch[], maxMatches: number, maxFiles: number): { matches: ContentMatch[]; truncated: boolean } {\n const seen = new Set<string>()\n const out: ContentMatch[] = []\n let truncated = false\n for (const match of matches) {\n if (out.length >= maxMatches) { truncated = true; break }\n if (!seen.has(match.path)) {\n if (seen.size >= maxFiles) { truncated = true; break }\n seen.add(match.path)\n }\n out.push(match)\n }\n return { matches: out, truncated }\n}\n\n/**\n * 构造 rg 内容搜索 argv(pattern 放 `--` 后首位置,支持前导 `-` 的查询)。\n * include/exclude 为用户 glob(gitignore 式,原样透传不转义),\n * 分别转正选 `--glob` 与排除 `--glob !`。\n * @author ddj 2026年08月26号\n * @param binary rg 路径\n * @param root 搜索根\n * @param input 搜索输入\n * @returns argv 数组\n */\nexport function contentArgv(binary: string, root: string, input: ContentSearchInput): string[] {\n const argv = [binary, '--no-config', '--json', '--line-number', '--no-heading', '--color', 'never', '--hidden', '--no-ignore']\n if (input.matchCase === true) argv.push('--case-sensitive')\n if (input.wholeWord === true) argv.push('--word-regexp')\n if (input.regex !== true) argv.push('--fixed-strings')\n for (const excluded of EXCLUDES) argv.push('--glob', '!**/' + excluded + '/**')\n for (const excluded of FILE_EXCLUDES) argv.push('--glob', '!' + excluded)\n for (const pattern of input.include ?? []) {\n const glob = String(pattern).trim()\n if (glob) argv.push('--glob', glob)\n }\n for (const pattern of input.exclude ?? []) {\n const glob = String(pattern).trim()\n if (glob) argv.push('--glob', '!' + glob)\n }\n argv.push('--', input.query, root)\n return argv\n}\n\n/**\n * 使用打包 ripgrep 搜索文件内容。\n * @author ddj 2026年08月26号\n * @param input provider 输入\n * @returns 有界内容搜索结果\n */\nexport async function searchRipgrepContent(input: ContentSearchInput): Promise<ContentSearchResult> {\n const sub = input.ctx.get('subprocess') as { spawn(spec: unknown): { done: Promise<{ exitCode: number | null; code?: number | null }>; collected?: { stdout?: { readFrom(offset: number): { text: string; lossy?: boolean } }; stderr?: { readFrom(offset: number): { text: string } } } } } | undefined\n if (!sub) throw new Error('缺少 subprocess')\n const binary = ripgrepPath()\n if (!binary) throw new Error('ripgrep 不可用')\n const root = input.root ?? await searchRoot(input.ctx, input.session)\n const handle = sub.spawn({\n argv: contentArgv(binary, root, input),\n cwd: root,\n stdio: { stdin: 'ignore', stdout: { maxBytes: STDOUT_CAP }, stderr: { maxBytes: STDERR_CAP } },\n graceMs: GRACE_MS,\n signal: input.signal,\n })\n let outcome: { exitCode: number | null; code?: number | null }\n try {\n outcome = await handle.done\n } catch (error) {\n throw new Error('ripgrep 启动失败:' + String(error))\n }\n const code = outcome.exitCode ?? outcome.code\n const failure = code !== 0 && code !== 1 ? rgExitFailure(code, readStderr(handle).text) : null\n if (failure && failure.kind !== 'partial') throw new Error(failure.message)\n const reader = handle.collected?.stdout\n if (!reader) throw new Error('ripgrep stdout 不可用')\n const output = reader.readFrom(0)\n const all = parseRgJsonLines(output.text, root)\n const maxMatches = Math.max(1, Math.min(input.maxResults ?? DEFAULT_MAX_MATCHES, DEFAULT_MAX_MATCHES))\n const capped = applyCaps(all, maxMatches, DEFAULT_MAX_FILES)\n const truncated = Boolean(output.lossy) || capped.truncated\n const result: ContentSearchResult = { ...capped, complete: !truncated, source: 'ripgrep' }\n // 遍历错误(退出码 2):rg 已输出的命中仍有效,保留结果、标记不完整并附部分结果提示\n if (failure) {\n result.complete = false\n result.warning = failure.message\n }\n return result\n}\n\n/**\n * 内容搜索编排器:短期缓存 + 同根在途取消 + 会话清理。\n * @author ddj 2026年08月26号\n */\nexport class ContentSearcher {\n private readonly cache = new SearchCache<ContentSearchResult>((r) => ({ ...r, matches: [...r.matches] }))\n private readonly inflight = new Map<string, AbortController>()\n private readonly rootsByCwd = new Map<string, Set<string>>()\n\n /**\n * 创建内容搜索编排器。\n * @author ddj 2026年08月26号\n * @param ctx DSH 上下文\n * @param provider 内容搜索 provider(测试可替换)\n */\n constructor(private readonly ctx: Ctx, private readonly provider: ContentSearchProvider = { search: searchRipgrepContent }) {}\n\n /**\n * 执行一次工作区内容搜索。\n * @author ddj 2026年08月26号\n * @param request 搜索请求\n * @returns RPC 响应字段(provider 失败抛错,abort 返回空)\n */\n async search(request: ContentSearchRequest): Promise<ContentSearchResponse> {\n const query = String(request.query ?? '').trim()\n if (query.length < 2) return { matches: [], truncated: false }\n let root: string\n try {\n root = await searchRoot(this.ctx, request.session)\n } catch {\n return { matches: [], truncated: false }\n }\n const rootKey = pathText(root)\n const roots = this.rootsByCwd.get(request.cwd) ?? new Set<string>()\n roots.add(rootKey)\n this.rootsByCwd.set(request.cwd, roots)\n const includeKey = (request.include ?? []).join(',')\n const excludeKey = (request.exclude ?? []).join(',')\n const key = [rootKey, query, request.matchCase ? 'mc' : '', request.wholeWord ? 'ww' : '', request.regex ? 'rx' : '', includeKey, excludeKey, PROVIDER_VERSION].join('|')\n const cached = this.cache.get(key)\n if (cached) return { matches: cached.matches, truncated: cached.truncated, warning: cached.warning }\n this.inflight.get(root)?.abort()\n const controller = new AbortController()\n this.inflight.set(root, controller)\n try {\n const result = await this.provider.search({\n ctx: this.ctx,\n session: request.session,\n cwd: request.cwd,\n query,\n matchCase: request.matchCase,\n wholeWord: request.wholeWord,\n regex: request.regex,\n maxResults: request.maxResults,\n include: request.include,\n exclude: request.exclude,\n signal: controller.signal,\n root,\n })\n if (controller.signal.aborted) return { matches: [], truncated: false }\n this.cache.set(key, result)\n return { matches: result.matches, truncated: result.truncated, warning: result.warning }\n } catch (error) {\n if (controller.signal.aborted) return { matches: [], truncated: false }\n throw error\n } finally {\n if (this.inflight.get(root) === controller) this.inflight.delete(root)\n }\n }\n\n /**\n * 清理会话对应根目录的缓存和在途搜索。\n * @author ddj 2026年08月26号\n * @param cwd 会话工作区\n */\n dispose(cwd: string): void {\n const roots = this.rootsByCwd.get(cwd) ?? new Set<string>([cwd])\n for (const root of roots) {\n this.inflight.get(root)?.abort()\n this.inflight.delete(root)\n this.cache.clearRoot(root)\n }\n this.rootsByCwd.delete(cwd)\n }\n\n /**\n * 清理全部状态。\n * @author ddj 2026年08月26号\n */\n disposeAll(): void {\n for (const controller of this.inflight.values()) controller.abort()\n this.inflight.clear()\n this.rootsByCwd.clear()\n this.cache.clear()\n }\n}\n\n/**\n * 创建默认内容搜索编排器。\n * @author ddj 2026年08月26号\n * @param ctx DSH 上下文\n * @returns 内容搜索编排器\n */\nexport function newContentSearcher(ctx: Ctx): ContentSearcher {\n return new ContentSearcher(ctx)\n}\n","/**\n * dsh-vscode-mode host — 回滚/删除(fs + subprocess 操作)。\n * 迁移自原 src/index.ts 的 revertCall/revertHunk/deleteCreated/restoreFile,语义不改。\n * 作者 ddj 2026-08-20\n */\nimport type { DiffRecord } from './shared/types.js'\nimport type { Ctx, Session } from './store.js'\nimport { policyOf, resolveTarget } from './store.js'\nimport { applyLocations, locateHunks, preciseHunk } from './shared/diff.js'\n\nexport type Result = { ok: true } | { ok: false; error: string }\n\n/**\n * 删除新建文件(拒绝创建时):subprocess 删除,路径先经 fs.contains 校验工作区边界。\n * @author ddj 2026年08月20号\n * @returns 成功或失败原因\n */\nexport async function deleteCreated(ctx: Ctx, session: Session, record: DiffRecord): Promise<Result> {\n const sub = ctx.get('subprocess')\n const fs = ctx.get('fs')\n if (!sub || !fs) return { ok: false, error: '回滚不可用:缺少 subprocess/fs' }\n const policy = policyOf(ctx, session)\n const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', {})\n const target = await resolveTarget(ctx, session, record.path)\n if (!fs.contains(rootTarget, target)) return { ok: false, error: '拒绝删除:目标不在会话工作区内' }\n const p = fs.processPath(target)\n // subprocess 契约:spawn({ argv, stdio, graceMs }),done → { exitCode },输出走 handle.collected\n const attempt = async (argv: string[]): Promise<void> => {\n const handle = sub.spawn({\n argv,\n stdio: { stdout: { maxBytes: 1 << 16 }, stderr: { maxBytes: 1 << 16 }, stdin: 'ignore' },\n graceMs: 10000,\n })\n const outcome = await handle.done\n const code = outcome?.exitCode ?? outcome?.code\n if (code !== 0) {\n const err = handle.collected?.stderr?.readFrom(0).text ?? ''\n throw new Error('exit ' + code + ' ' + err)\n }\n }\n try {\n await attempt(['powershell', '-NoProfile', '-NonInteractive', '-Command', 'Remove-Item -LiteralPath \"' + p + '\" -Force'])\n return { ok: true }\n } catch (error) {\n try {\n await attempt(['/bin/rm', '-f', '--', p])\n return { ok: true }\n } catch (error2) {\n return { ok: false, error: '删除失败(文件仍存在):' + String(error) + ' / ' + String(error2) }\n }\n }\n}\n\n/** 整调用回滚:write/编辑用 before 整文件恢复;新建文件转 deleteCreated。 */\nexport async function revertCall(ctx: Ctx, session: Session, record: DiffRecord): Promise<Result> {\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '回滚不可用:缺少 fs' }\n if (record.before === null) {\n if (!record.create) return { ok: false, error: '无法回滚:缺少修改前内容(大文件或旧记录)' }\n return deleteCreated(ctx, session, record)\n }\n try {\n const target = await resolveTarget(ctx, session, record.path)\n await fs.writeText(target, record.before, void 0, void 0, policyOf(ctx, session))\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '回滚失败:' + String(error) }\n }\n}\n\n/** 单 hunk 回滚:用 callHunk(edit 单 hunk 精确串)经 fs.editText 反替换。 */\nexport async function revertHunk(ctx: Ctx, session: Session, record: DiffRecord, idx: number): Promise<Result> {\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '回滚不可用:缺少 fs' }\n const precise = preciseHunk(record, idx)\n if (!precise) return { ok: false, error: '找不到该差异块' }\n try {\n const target = await resolveTarget(ctx, session, record.path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') return { ok: false, error: '回滚失败:文件不存在' }\n if ((info.size ?? 0) > 8 * 1024 * 1024) return { ok: false, error: '回滚失败:文件过大,无法安全定位' }\n const content = await fs.readText(target)\n const location = locateHunks(content, [precise])[0]\n if (!location?.matched) return { ok: false, error: '回滚失败:该区域可能已被后续修改影响' }\n const result = applyLocations(content, [location], true)\n await fs.writeText(target, result.content, void 0, void 0, policyOf(ctx, session))\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '回滚失败:该区域可能已被后续修改影响(' + String(error) + ')' }\n }\n}\n\n/**\n * 恢复文件到记录对应状态(批次回滚用):返回错误文案或 null(成功)。\n * @author ddj 2026年08月20号\n */\nexport async function restoreFile(ctx: Ctx, session: Session, rec: DiffRecord): Promise<string | null> {\n const fs = ctx.get('fs')\n if (!fs) return '缺少 fs'\n if (rec.before === null || rec.before === undefined) {\n if (rec.create === true) {\n const out = await deleteCreated(ctx, session, rec)\n return out.ok ? null : out.error\n }\n return '缺少修改前内容(大文件或旧记录),无法回滚'\n }\n try {\n const target = await resolveTarget(ctx, session, rec.path)\n await fs.writeText(target, rec.before, void 0, void 0, policyOf(ctx, session))\n return null\n } catch (error) {\n return '回滚失败:' + String(error)\n }\n}\n","/**\n * dsh-vscode-mode host — 规则管理(Codebuddy/Cursor 式 .mdc 规则)。\n * - 存储:用户规则 ~/.dsh/rules/*.mdc;项目规则 <工作区>/.dsh/rules/*.mdc(随仓库共享)。\n * - 格式:frontmatter(description / alwaysApply / globs / enabled)+ markdown 正文;\n * 类型映射 总是=always / 自动=auto(globs) / 手动=manual(仅索引);enabled 为本插件扩展字段,缺省 true。\n * - 生效:host 注册 systemPrompt.section(order 400),每次装配同步读取(mtime 缓存),\n * 项目规则按 AssembleContext.agent.id → 会话 cwd 注入;旧版 DSH 缺服务时优雅降级。\n * --region 划分:常量 / frontmatter 解析(纯)/ 文件名与开关(纯)/ 注入渲染(纯)/ IO / systemPrompt 装配\n * 作者 ddj 2026年09月03号\n */\nimport { existsSync, mkdirSync, readFileSync, readdirSync, statSync } from 'node:fs'\nimport { mkdir, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises'\nimport { Buffer } from 'node:buffer'\nimport { join } from 'node:path'\nimport { dshHome } from './paths.js'\nimport type { RuleInfo, RuleProject, RuleRefInput, RuleScope, RuleSaveInput } from './shared/rules.js'\nimport type { Ctx } from './store.js'\n\n// --region 常量与目录定位\n/** 规则文件名白名单:字母数字开头,仅字母数字点横下划线,.mdc 后缀(天然拒绝路径分隔符)。 */\nexport const RULE_FILE_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*\\.mdc$/\n/** Windows 保留设备名(防意外创建系统设备文件)。 */\nconst RESERVED_NAME_RE = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\\..*)?$/i\n/** 单目录最多加载的规则文件数(防失控目录拖垮装配)。 */\nconst RULE_DIR_CAP = 200\n/** 注入时单条规则正文字节上限(超出截断)。 */\nconst RULE_SINGLE_CAP = 16 * 1024\n/** 注入时单个作用域(用户/项目)总字节预算。 */\nconst RULE_SCOPE_CAP = 64 * 1024\n/** systemPrompt section 名(同层唯一)。 */\nconst SECTION_NAME = 'dsh-vscode-mode:rules'\n/** section 顺序:persona(0) 与 PLAN_POLICY(500) 之间,规则先于计划策略被读到。 */\nconst SECTION_ORDER = 400\n\n/**\n * 用户规则目录(~/.dsh/rules)。\n * @author ddj 2026年09月03号\n * @param home DSH home(缺省自动解析)\n * @returns 绝对路径\n */\nexport function userRulesDir(home = dshHome()): string {\n return join(home, 'rules')\n}\n\n/**\n * 项目规则目录(<工作区>/.dsh/rules)。\n * @author ddj 2026年09月03号\n * @param workspacePath 工作区绝对路径\n * @returns 绝对路径\n */\nexport function projectRulesDir(workspacePath: string): string {\n return join(workspacePath, '.dsh', 'rules')\n}\n// --endregion\n\n// --region frontmatter 解析(纯函数)\n/** parseRuleMdc 的产出:frontmatter 字段 + 正文 + 可选解析错误。 */\nexport interface ParsedRule {\n description: string\n alwaysApply: boolean\n globs: string[]\n enabled: boolean\n body: string\n error?: string\n}\n\n/**\n * 去除值两侧成对引号。\n * @author ddj 2026年09月03号\n * @param raw 原始值\n * @returns 去引号后的值\n */\nfunction stripQuotes(raw: string): string {\n const value = raw.trim()\n if (value.length >= 2 && ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\")))) {\n return value.slice(1, -1)\n }\n return value\n}\n\n/**\n * 解析 globs 值:内联逗号分隔串,或空值后接 YAML 短横列表。\n * @author ddj 2026年09月03号\n * @param value 内联值(可为空)\n * @param listLines 后续短横列表行内容(去掉 `- ` 前缀)\n * @returns glob 数组\n */\nfunction parseGlobs(value: string, listLines: string[]): string[] {\n const inline = stripQuotes(value)\n const items = inline ? inline.split(',') : listLines\n return items.map((item) => stripQuotes(item)).filter(Boolean)\n}\n\n/**\n * 容错解析一条 .mdc 规则:首行 `---` 且 100 行内有闭合 `---` 才视为 frontmatter,\n * 否则整个文本当正文(类型 manual、enabled=true)。解析永不抛错。\n * @author ddj 2026年09月03号\n * @param text 文件全文\n * @returns 解析结果\n */\nexport function parseRuleMdc(text: string): ParsedRule {\n const lines = text.replace(/^\\uFEFF/, '').split(/\\r?\\n/)\n if (lines[0]?.trim() !== '---') return { description: '', alwaysApply: false, globs: [], enabled: true, body: text }\n let close = -1\n for (let i = 1; i < lines.length && i <= 101; i++) {\n if (lines[i].trim() === '---') { close = i; break }\n }\n if (close < 0) return { description: '', alwaysApply: false, globs: [], enabled: true, body: text }\n const result: ParsedRule = { description: '', alwaysApply: false, globs: [], enabled: true, body: lines.slice(close + 1).join('\\n') }\n for (let i = 1; i < close; i++) {\n const match = /^([A-Za-z_-]+)[ \\t]*:[ \\t]?(.*)$/.exec(lines[i])\n if (!match) continue\n const [, key, raw] = match\n if (key === 'description') result.description = stripQuotes(raw)\n else if (key === 'alwaysApply') result.alwaysApply = stripQuotes(raw).toLowerCase() === 'true'\n else if (key === 'enabled') result.enabled = stripQuotes(raw).toLowerCase() !== 'false'\n else if (key === 'globs') {\n const listLines: string[] = []\n for (let j = i + 1; j < close; j++) {\n const item = /^[ \\t]*-[ \\t]*(.+)$/.exec(lines[j])\n if (!item) break\n listLines.push(item[1])\n }\n result.globs = parseGlobs(raw, listLines)\n }\n }\n return result\n}\n\n/**\n * 由 frontmatter 推导规则类型:总是 / 自动(有 globs)/ 手动。\n * @author ddj 2026年09月03号\n * @param parsed 解析结果\n * @returns 规则类型\n */\nexport function ruleTypeOf(parsed: ParsedRule): 'always' | 'auto' | 'manual' {\n if (parsed.alwaysApply) return 'always'\n if (parsed.globs.length) return 'auto'\n return 'manual'\n}\n// --endregion\n\n// --region 文件名与开关改写(纯函数)\n/**\n * 校验规则文件名(白名单 + Windows 保留名拒绝)。\n * @author ddj 2026年09月03号\n * @param name 文件名(含后缀)\n * @returns 错误文案;null=合法\n */\nexport function validateRuleFile(name: string): string | null {\n if (!RULE_FILE_RE.test(name)) return '文件名不合法:仅允许字母数字开头,含字母/数字/点/横线/下划线,.mdc 后缀'\n if (RESERVED_NAME_RE.test(name)) return '文件名是 Windows 保留设备名,不允许'\n return null\n}\n\n/**\n * 只改写 frontmatter 的 enabled 行(保留 BOM、CRLF 与其余内容不动);无规则 frontmatter 返回 null。\n * @author ddj 2026年09月03号\n * @param text 文件全文\n * @param enabled 目标开关状态\n * @returns 改写后的全文;null=无法安全改写\n */\nexport function toggleEnabledLine(text: string, enabled: boolean): string | null {\n const hasBom = text.startsWith('\\uFEFF')\n const rest = hasBom ? text.slice(1) : text\n const eol = rest.includes('\\r\\n') ? '\\r\\n' : '\\n'\n const lines = rest.split(/\\r?\\n/)\n if (lines[0]?.trim() !== '---') return null\n let close = -1\n for (let i = 1; i < lines.length && i <= 101; i++) {\n if (lines[i].trim() === '---') { close = i; break }\n }\n if (close < 0) return null\n const line = 'enabled: ' + (enabled ? 'true' : 'false')\n let replaced = false\n for (let i = 1; i < close; i++) {\n if (/^[ \\t]*enabled[ \\t]*:/.test(lines[i])) { lines[i] = line; replaced = true; break }\n }\n if (!replaced) lines.splice(1, 0, line)\n return (hasBom ? '\\uFEFF' : '') + lines.join(eol)\n}\n// --endregion\n\n// --region 注入渲染(纯函数)\n/** 一条已加载规则:元信息 + 正文(注入渲染输入)。 */\nexport interface LoadedRule {\n info: RuleInfo\n body: string\n}\n\n/**\n * 渲染单条规则块:标题 + 描述 + 截断后的正文;auto 类型追加 glob 条件说明。\n * @author ddj 2026年09月03号\n * @param rule 已加载规则\n * @returns 文本块(含尾空行)\n */\nfunction ruleBlock(rule: LoadedRule): string {\n let body = rule.body\n if (body.length > RULE_SINGLE_CAP) body = body.slice(0, RULE_SINGLE_CAP) + '\\n…(规则正文超长已截断)'\n const condition = rule.info.type === 'auto' && rule.info.globs.length\n ? '(当处理匹配 ' + rule.info.globs.join(', ') + ' 的文件时应用)'\n : ''\n const desc = rule.info.description ? '\\n' + rule.info.description : ''\n return '#### ' + rule.info.file + condition + desc + '\\n' + body + '\\n'\n}\n\n/**\n * 渲染一个作用域(用户/项目)的注入段:总是全文 / 自动带条件 / 手动仅索引行。\n * @author ddj 2026年09月03号\n * @param title 段标题\n * @param rules 已加载规则\n * @returns 段文本;无启用规则时返回空串\n */\nfunction renderScope(title: string, rules: LoadedRule[]): string {\n const enabled = rules.filter((rule) => rule.info.enabled && !rule.info.error)\n const always = enabled.filter((rule) => rule.info.type === 'always')\n const auto = enabled.filter((rule) => rule.info.type === 'auto')\n const manual = enabled.filter((rule) => rule.info.type === 'manual')\n if (!always.length && !auto.length && !manual.length) return ''\n const out: string[] = ['## ' + title, '']\n let budget = RULE_SCOPE_CAP\n let omitted = false\n const push = (block: string): void => {\n if (block.length > budget) { omitted = true; return }\n budget -= block.length\n out.push(block)\n }\n if (always.length) {\n out.push('### 总是生效', '')\n for (const rule of always) push(ruleBlock(rule))\n }\n if (auto.length) {\n out.push('### 按文件匹配生效', '')\n for (const rule of auto) push(ruleBlock(rule))\n }\n if (manual.length) {\n out.push('### 可按需读取(未自动生效;需要时读取对应文件)', '')\n for (const rule of manual) {\n const desc = rule.info.description ? ' — ' + rule.info.description : ''\n push('- ' + rule.info.file + desc + '(路径: ' + rule.info.absPath + ')\\n')\n }\n }\n if (omitted) out.push('', '(部分规则因总长度预算被省略,请精简规则文件)')\n return out.join('\\n') + '\\n'\n}\n\n/**\n * 渲染规则注入 section 全文:用户规则段 + 项目规则段;两者皆空返回空串(空 section 无害)。\n * @author ddj 2026年09月03号\n * @param user 用户规则\n * @param project 当前工作区项目规则\n * @param workspacePath 项目段标注的工作区路径(缺省跳过项目段)\n * @returns 注入文本\n */\nexport function renderRulesSection(user: LoadedRule[], project: LoadedRule[], workspacePath?: string): string {\n const userText = renderScope('用户规则(用户配置,必须遵守)', user)\n const projectText = workspacePath ? renderScope('项目规则(工作区 ' + workspacePath + ',必须遵守)', project) : ''\n return [userText, projectText].filter(Boolean).join('\\n')\n}\n// --endregion\n\n// --region IO(列表 / 读 / 存 / 删 / 开关)\n/** 单目录规则元信息列表(仅 *.mdc,最多 RULE_DIR_CAP 个;目录缺失返回空)。 */\nasync function listRulesDir(dir: string, scope: RuleScope): Promise<RuleInfo[]> {\n const names = await readdir(dir).catch(() => [] as string[])\n const mdcs = names.filter((name) => name.endsWith('.mdc')).sort().slice(0, RULE_DIR_CAP)\n const out: RuleInfo[] = []\n for (const file of mdcs) {\n const absPath = join(dir, file)\n const info = await stat(absPath).catch(() => null)\n if (!info || !info.isFile()) continue\n const parsed = parseRuleMdc(await readFile(absPath, 'utf8').catch(() => ''))\n out.push(toRuleInfo(scope, file, absPath, parsed, info.size, info.mtimeMs))\n }\n return out\n}\n\n/** 已注册 workspace 列表(项目 Tab 与写入校验共用)。 */\nfunction workspaceList(ctx: Ctx): Array<{ path: string; title?: string }> {\n const list = ctx.get('workspaceRegistry')?.list?.() ?? []\n return (list as Array<{ path?: string; title?: string }>).filter(\n (item): item is { path: string; title?: string } => Boolean(item) && typeof item.path === 'string' && item.path !== '',\n )\n}\n\n/** 用户显式 GUI 写操作的策略:danger-full-access(照抄 mcpProject.fullPolicy)。 */\nfunction fullPolicy(ctx: Ctx): unknown {\n const svc = ctx.get('sandboxPolicy')\n if (!svc || typeof svc.resolve !== 'function') return undefined\n return svc.resolve({ mode: 'danger-full-access' })\n}\n\n/** 校验项目作用域的 workspacePath 已注册为 DSH workspace(防 RPC 写任意目录)。 */\nfunction requireWorkspace(ctx: Ctx, workspacePath: string | undefined): { path: string; title?: string } {\n const workspace = workspaceList(ctx).find((item) => item.path === workspacePath)\n if (!workspace) throw new Error('项目未注册为 DSH workspace,不能管理项目规则')\n return workspace as { path: string; title?: string }\n}\n\n/** 按作用域解析规则目录(project 先过 requireWorkspace)。 */\nfunction dirOf(ctx: Ctx, scope: RuleScope, workspacePath?: string): string {\n if (scope === 'project') return projectRulesDir(requireWorkspace(ctx, workspacePath).path)\n return userRulesDir()\n}\n\n/**\n * 规则总列表:用户规则 + 各已注册工作区的项目规则。\n * @author ddj 2026年09月03号\n * @param ctx DSH 上下文\n * @returns rules.list 载荷\n */\nexport async function rulesList(ctx: Ctx): Promise<{ user: RuleInfo[]; projects: RuleProject[] }> {\n const user = await listRulesDir(userRulesDir(), 'user')\n const projects: RuleProject[] = []\n for (const workspace of workspaceList(ctx)) {\n const dir = projectRulesDir(workspace.path)\n const exists = existsSync(dir)\n const rules = exists ? await listRulesDir(dir, 'project') : []\n projects.push({ workspacePath: workspace.path, title: workspace.title ?? '', rules, missingDir: exists ? undefined : true })\n }\n return { user, projects }\n}\n\n/**\n * 读取一条规则全文(编辑器回填用)。\n * @author ddj 2026年09月03号\n * @param ctx DSH 上下文\n * @param ref 作用域 + 文件名(+ 项目工作区)\n * @returns 文件全文\n */\nexport async function rulesRead(ctx: Ctx, ref: RuleRefInput): Promise<string> {\n const dir = dirOf(ctx, ref.scope, ref.workspacePath)\n return readFile(join(dir, ref.file), 'utf8')\n}\n\n/**\n * 组装规则元信息视图(rulesSave / rulesToggle / 注入缓存共用)。\n * @author ddj 2026年09月03号\n * @param scope 作用域\n * @param file 文件名\n * @param absPath 绝对路径\n * @param parsed 解析结果\n * @param size 字节数\n * @param mtime 修改时间毫秒\n * @returns 规则元信息\n */\nfunction toRuleInfo(scope: RuleScope, file: string, absPath: string, parsed: ParsedRule, size: number, mtime: number): RuleInfo {\n return {\n scope, file, absPath,\n relHint: scope === 'project' ? '.dsh/rules/' : 'rules/',\n description: parsed.description, type: ruleTypeOf(parsed), globs: parsed.globs, enabled: parsed.enabled,\n size, mtime, error: parsed.error,\n }\n}\n\n/**\n * 保存(新建或覆盖)一条规则:project 作用域写盘走 ctx fs + danger-full-access(镜像 mcpProject)。\n * @author ddj 2026年09月03号\n * @param ctx DSH 上下文\n * @param input 保存入参\n * @returns 保存后的规则元信息\n */\nexport async function rulesSave(ctx: Ctx, input: RuleSaveInput): Promise<RuleInfo> {\n const invalid = validateRuleFile(input.file)\n if (invalid) throw new Error(invalid)\n const dir = dirOf(ctx, input.scope, input.workspacePath)\n await mkdir(dir, { recursive: true })\n const absPath = join(dir, input.file)\n const content = String(input.content ?? '')\n if (input.scope === 'project') {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve('.dsh/rules/' + input.file, { cwd: requireWorkspace(ctx, input.workspacePath).path })\n await fs.writeText(target, content, void 0, void 0, fullPolicy(ctx))\n } else {\n await writeFile(absPath, content, 'utf8')\n }\n const info = await stat(absPath).catch(() => null)\n return toRuleInfo(input.scope, input.file, absPath, parseRuleMdc(content), info?.size ?? Buffer.byteLength(content), info?.mtimeMs ?? Date.now())\n}\n\n/**\n * 删除一条规则文件(project 作用域同样先过 workspace 注册校验)。\n * @author ddj 2026年09月03号\n * @param ref 作用域 + 文件名(+ 项目工作区)\n */\nexport async function rulesRemove(ctx: Ctx, ref: RuleRefInput): Promise<void> {\n const dir = dirOf(ctx, ref.scope, ref.workspacePath)\n await rm(join(dir, ref.file), { force: true })\n}\n\n/**\n * 切换规则启用开关:只改写 frontmatter enabled 行,其余内容零改动。\n * @author ddj 2026年09月03号\n * @param ref 作用域 + 文件名(+ 项目工作区)\n * @param enabled 目标状态\n * @returns 更新后的规则元信息\n */\nexport async function rulesToggle(ctx: Ctx, ref: RuleRefInput, enabled: boolean): Promise<RuleInfo> {\n const dir = dirOf(ctx, ref.scope, ref.workspacePath)\n const absPath = join(dir, ref.file)\n const text = await readRuleText(ctx, ref, absPath)\n if (text === null) throw new Error('规则文件不存在:' + ref.file)\n const next = toggleEnabledLine(text, enabled)\n if (next === null) throw new Error('规则缺少 frontmatter(首行需为 ---),无法记录开关状态')\n if (next !== text) await rulesSaveContent(ctx, ref, absPath, next)\n return await ruleInfoOf(ref, absPath, next)\n}\n\n/** 按作用域读规则全文:project 与写盘同通道走 ctx fs,user 走 node fs;缺失返回 null。 */\nasync function readRuleText(ctx: Ctx, ref: RuleRefInput, absPath: string): Promise<string | null> {\n if (ref.scope !== 'project') return readFile(absPath, 'utf8').catch(() => null)\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve('.dsh/rules/' + ref.file, { cwd: requireWorkspace(ctx, ref.workspacePath).path })\n try {\n return await fs.readText(target)\n } catch {\n return null\n }\n}\n\n/** rulesToggle 的写盘通道:与 rulesSave 相同(project 走 ctx fs + fullPolicy,user 走 node fs)。 */\nasync function rulesSaveContent(ctx: Ctx, ref: RuleRefInput, absPath: string, content: string): Promise<void> {\n if (ref.scope !== 'project') {\n await writeFile(absPath, content, 'utf8')\n return\n }\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve('.dsh/rules/' + ref.file, { cwd: requireWorkspace(ctx, ref.workspacePath).path })\n await fs.writeText(target, content, void 0, void 0, fullPolicy(ctx))\n}\n\n/** 重建单条规则元信息(toggle 后回传 UI;stat 失败时用内容长度 + 当前时间兜底)。 */\nasync function ruleInfoOf(ref: RuleRefInput, absPath: string, content: string): Promise<RuleInfo> {\n const info = await stat(absPath).catch(() => null)\n return toRuleInfo(ref.scope, ref.file, absPath, parseRuleMdc(content), info?.size ?? Buffer.byteLength(content), info?.mtimeMs ?? Date.now())\n}\n// --endregion\n\n// --region systemPrompt 装配(注入生效通道)\n/** 注入读取的 mtime 缓存项:mtimeMs+size 命中即复用解析结果,避免每次装配读盘解析。 */\ninterface InjCacheEntry {\n mtimeMs: number\n size: number\n parsed: ParsedRule\n}\nconst injCache = new Map<string, InjCacheEntry>()\n\n/**\n * 同步读取一个规则目录(装配 provider 内专用):仅 *.mdc,mtime 缓存,异常静默为空。\n * @author ddj 2026年09月03号\n * @param dir 规则目录\n * @param scope 作用域\n * @param relHint 相对提示\n * @returns 已加载规则列表\n */\nfunction readRulesSync(dir: string, scope: RuleScope): LoadedRule[] {\n if (!existsSync(dir)) return []\n let names: string[]\n try {\n names = readdirSync(dir)\n } catch {\n return []\n }\n const out: LoadedRule[] = []\n for (const file of names.filter((name) => name.endsWith('.mdc')).sort().slice(0, RULE_DIR_CAP)) {\n const absPath = join(dir, file)\n let info: { mtimeMs: number; size: number; isFile(): boolean }\n try {\n info = statSync(absPath)\n } catch {\n continue\n }\n if (!info.isFile()) continue\n const cached = injCache.get(absPath)\n let parsed: ParsedRule\n if (cached && cached.mtimeMs === info.mtimeMs && cached.size === info.size) {\n parsed = cached.parsed\n } else {\n try {\n parsed = parseRuleMdc(readFileSync(absPath, 'utf8'))\n } catch {\n continue\n }\n injCache.set(absPath, { mtimeMs: info.mtimeMs, size: info.size, parsed })\n }\n out.push({\n info: toRuleInfo(scope, file, absPath, parsed, info.size, info.mtimeMs),\n body: parsed.body,\n })\n }\n return out\n}\n\n/** 从装配上下文解析会话工作区 cwd(agent.id → sessions → header.cwd;缺链返回 null)。 */\nfunction cwdFromAssemble(ctx: Ctx, asm: { agent?: { id?: unknown } } | undefined): string | null {\n const id = asm?.agent?.id\n if (typeof id !== 'string' || !id) return null\n const session = ctx.get('sessions')?.get?.(id)\n const cwd = session?.header?.cwd\n return typeof cwd === 'string' && cwd ? cwd : null\n}\n\n/**\n * 安装规则注入 section(可选探测 systemPrompt 服务;失败/缺失返回 false,不致命)。\n * @author ddj 2026年09月03号\n * @param ctx DSH host 上下文\n * @returns 是否成功注册\n */\nexport function installRulesSection(ctx: Ctx): boolean {\n const sp = ctx.get('systemPrompt')\n if (!sp || typeof sp.section !== 'function') return false\n const provider = (asm: { agent?: { id?: unknown } }): string => {\n try {\n const user = readRulesSync(userRulesDir(), 'user')\n const cwd = cwdFromAssemble(ctx, asm)\n const project = cwd ? readRulesSync(projectRulesDir(cwd), 'project') : []\n return renderRulesSection(user, project, cwd ?? undefined)\n } catch {\n return ''\n }\n }\n ctx.effect(() => sp.section({ name: SECTION_NAME, order: SECTION_ORDER, text: provider }), 'vscode-mode: rules section')\n return true\n}\n// --endregion\n","/**\n * dsh-vscode-mode host — 项目级 MCP 管理。\n * 配置以项目根目录 .mcp.json(mcpServers 格式,对齐 Claude Code/Cursor)存储;\n * 工具经 loader 动态激活(entry id 带 PROJECT_ENTRY_PREFIX,全局生效)。\n * 重启后由本项目从各 .mcp.json 恢复激活;.mcp.json 为持久真相,reconcile 以文件为准。\n * 作者 ddj 2026年08月22号\n */\nimport { createHash } from 'node:crypto'\nimport { PROJECT_ENTRY_PREFIX, entriesOf, serverOf, validateConfig } from './mcp.js'\nimport type { MpcConfig, MpcProject, MpcServer } from './shared/mcp.js'\nimport type { Ctx } from './store.js'\n\nconst FILE_NAME = '.mcp.json'\n\n/** 校验项目路径属于 DSH 已注册 workspace,避免 RPC 写入任意目录。 */\nfunction requireWorkspace(ctx: Ctx, workspacePath: string): { path: string; title?: string } {\n const workspace = (ctx.get('workspaceRegistry')?.list?.() ?? []).find((item: { path: string }) => item.path === workspacePath)\n if (!workspace) throw new Error('项目未注册为 DSH workspace,不能管理项目 MCP')\n return workspace\n}\n\n/** 用户显式 GUI 管理操作的写策略:danger-full-access(写入路径固定为 workspacePath/.mcp.json)。 */\nfunction fullPolicy(ctx: Ctx): unknown {\n const svc = ctx.get('sandboxPolicy')\n if (!svc || typeof svc.resolve !== 'function') return undefined\n return svc.resolve({ mode: 'danger-full-access' })\n}\n\n/** workspace 路径 → 确定性短哈希(entry id 归属段,重启后稳定可解码)。 */\nexport function hashWorkspace(path: string): string {\n return createHash('sha1').update(path).digest('hex').slice(0, 10)\n}\n\n/** 项目 MCP 的 loader entry id:vsm-mcp.<pathHash>.<serverName>(loader id 不能用冒号)。 */\nexport function projectEntryId(workspacePath: string, serverName: string): string {\n return PROJECT_ENTRY_PREFIX + hashWorkspace(workspacePath) + '.' + serverName\n}\n\n/** 读取项目 .mcp.json 顶层对象(缺失 → 空;非法 → 抛错带文案)。 */\nasync function readProjectJson(ctx: Ctx, workspacePath: string): Promise<Record<string, unknown>> {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve(FILE_NAME, { cwd: workspacePath })\n let text: string\n try {\n text = await fs.readText(target)\n } catch (error) {\n return {}\n }\n let data: unknown\n try {\n data = JSON.parse(text)\n } catch (error) {\n throw new Error('.mcp.json 解析失败:' + String(error))\n }\n if (data === null || typeof data !== 'object' || Array.isArray(data)) throw new Error('.mcp.json 顶层必须是对象')\n return data as Record<string, unknown>\n}\n\n/** 读取并校验 .mcp.json 的 mcpServers 映射(纯函数,可单测)。 */\nexport function serversOf(data: Record<string, unknown>): Record<string, Record<string, unknown>> {\n const raw = data.mcpServers\n if (raw === undefined) return {}\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('.mcp.json 的 mcpServers 必须是对象')\n const out: Record<string, Record<string, unknown>> = {}\n for (const [name, value] of Object.entries(raw)) {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) continue\n out[name] = value as Record<string, unknown>\n }\n return out\n}\n\n/** 把 .mcp.json 单条 server 定义归一化为 MpcConfig(缺传输必填 → null,纯函数可单测)。 */\nexport function configFromDef(def: Record<string, unknown> | undefined, serverName: string): MpcConfig | null {\n if (!def) return null\n const transport = typeof def.url === 'string' ? 'streamable-http' : 'stdio'\n const config: MpcConfig = { serverName, transport }\n if (transport === 'stdio') {\n config.command = typeof def.command === 'string' ? def.command : ''\n config.args = Array.isArray(def.args) ? def.args.map(String) : []\n if (typeof def.cwd === 'string') config.cwd = def.cwd\n if (def.env && typeof def.env === 'object') config.env = Object.fromEntries(Object.entries(def.env as Record<string, unknown>).map(([k, v]) => [k, String(v)]))\n } else {\n config.url = def.url as string\n if (def.headers && typeof def.headers === 'object') config.headers = Object.fromEntries(Object.entries(def.headers as Record<string, unknown>).map(([k, v]) => [k, String(v)]))\n }\n if (typeof def.toolCallTimeoutMs === 'number') config.toolCallTimeoutMs = def.toolCallTimeoutMs\n return config\n}\n\n/** 写回 .mcp.json(保留顶层未知字段与其余 mcpServers,仅改目标 serverName)。 */\nasync function writeProjectJson(ctx: Ctx, workspacePath: string, data: Record<string, unknown>, mcpServers: Record<string, Record<string, unknown>>): Promise<void> {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve(FILE_NAME, { cwd: workspacePath })\n const next = { ...data, mcpServers }\n await fs.writeText(target, JSON.stringify(next, null, 2) + '\\n', void 0, void 0, fullPolicy(ctx))\n}\n\n/** 查重:目标 serverName 是否已被其他 loader entry(全局或他项目)占用。 */\nfunction findConflict(ctx: Ctx, workspacePath: string, serverName: string): string | null {\n const ownId = projectEntryId(workspacePath, serverName)\n for (const entry of entriesOf(ctx)) {\n if (String(entry.id ?? entry.options?.id ?? '') === ownId) continue\n if (entry.options?.config?.serverName === serverName) {\n return 'serverName \"' + serverName + '\" 已被另一个 MCP 使用(全局或其他项目),请换一个名称'\n }\n }\n return null\n}\n\n/** 激活一个项目 MCP:校验 + 查重 + loader.create。 */\nexport async function activateProjectMcp(ctx: Ctx, workspacePath: string, config: MpcConfig): Promise<MpcServer> {\n validateConfig(config)\n const conflict = findConflict(ctx, workspacePath, config.serverName)\n if (conflict) throw new Error(conflict)\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const id = projectEntryId(workspacePath, config.serverName)\n const existing = entriesOf(ctx).find((entry) => String(entry.id ?? entry.options?.id ?? '') === id)\n if (existing) {\n await loader.update(existing.id, { config: { ...config } })\n return serverOf(ctx, loader.resolve(existing.id))\n }\n const created = await loader.create({ id, name: '@deepseek-ai/dsh-mcp-client', config: { ...config } })\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id ?? candidate.options?.id ?? '') === id)\n if (!entry) throw new Error('MCP 已创建但未能找到 entry(id=' + id + ')')\n return serverOf(ctx, entry)\n}\n\n/** 停用一个项目 MCP(按 entry id)。 */\nexport async function deactivateMcp(ctx: Ctx, entryId: string): Promise<void> {\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id ?? candidate.options?.id ?? '') === entryId)\n if (!entry) return\n await loader.remove(entry.id)\n}\n\n/** 以 .mcp.json 为真相 reconcile 该项目的激活状态(幂等)。 */\nexport async function reconcileProject(ctx: Ctx, workspacePath: string): Promise<void> {\n const data = await readProjectJson(ctx, workspacePath)\n const fileServers = new Set(Object.keys(serversOf(data)))\n const prefix = PROJECT_ENTRY_PREFIX + hashWorkspace(workspacePath) + '.'\n for (const entry of entriesOf(ctx)) {\n const id = String(entry.id ?? entry.options?.id ?? '')\n if (!id.startsWith(prefix)) continue\n const serverName = id.slice(prefix.length)\n if (fileServers.has(serverName)) continue\n await deactivateMcp(ctx, id)\n }\n for (const serverName of fileServers) {\n const config = await configOfServer(ctx, workspacePath, serverName)\n if (config === null) continue\n const id = projectEntryId(workspacePath, serverName)\n if (entriesOf(ctx).some((entry) => String(entry.id ?? entry.options?.id ?? '') === id)) continue\n await activateProjectMcp(ctx, workspacePath, { ...config, serverName })\n }\n}\n\n/** 把 .mcp.json 单条 server 定义归一化为 MpcConfig(缺传输必填 → null)。 */\nasync function configOfServer(ctx: Ctx, workspacePath: string, serverName: string): Promise<MpcConfig | null> {\n const data = await readProjectJson(ctx, workspacePath)\n return configFromDef(serversOf(data)[serverName], serverName)\n}\n\n/** 单个项目的完整视图(fileData + 激活状态合并)。 */\nasync function projectOf(ctx: Ctx, workspacePath: string, title: string): Promise<MpcProject> {\n const fs = ctx.get('fs')\n if (!fs) return { workspacePath, title, servers: [], source: 'project' }\n try {\n const target = await fs.resolve(workspacePath)\n const info = await fs.stat(target)\n if (!info || info.type !== 'directory') return { workspacePath, title, servers: [], source: 'project', missingDir: true }\n } catch (error) {\n return { workspacePath, title, servers: [], source: 'project', missingDir: true }\n }\n await reconcileProject(ctx, workspacePath)\n let servers: MpcServer[] = []\n let fileError: string | undefined\n try {\n const data = await readProjectJson(ctx, workspacePath)\n const prefix = PROJECT_ENTRY_PREFIX + hashWorkspace(workspacePath) + '.'\n servers = entriesOf(ctx).filter((entry) => String(entry.id ?? entry.options?.id ?? '').startsWith(prefix)).map((entry) => serverOf(ctx, entry))\n servers.sort((a, b) => (a.serverName < b.serverName ? -1 : 1))\n } catch (error) {\n fileError = String(error)\n }\n return { workspacePath, title, servers, source: 'project', fileError }\n}\n\n/** 列出全部项目及其项目级 MCP。 */\nexport async function listProjects(ctx: Ctx): Promise<{ projects: MpcProject[] }> {\n const registry = ctx.get('workspaceRegistry')\n const workspaces = registry?.list?.() ?? []\n const projects: MpcProject[] = []\n for (const ws of workspaces) projects.push(await projectOf(ctx, ws.path, ws.title ?? ''))\n return { projects }\n}\n\n/** 保存(新增/更新)一个项目 MCP:写 .mcp.json → 激活。 */\nexport async function projectSave(ctx: Ctx, workspacePath: string, serverName: string, config: MpcConfig): Promise<MpcProject> {\n const workspace = requireWorkspace(ctx, workspacePath)\n validateConfig({ ...config, serverName })\n const conflict = findConflict(ctx, workspacePath, serverName)\n if (conflict) throw new Error(conflict)\n const data = await readProjectJson(ctx, workspacePath)\n const servers = serversOf(data)\n const next = { ...config } as unknown as Record<string, unknown>\n delete next.serverName\n delete next.transport\n delete next.disabled // disabled 由 projectToggle 管理,保存恒为启用\n servers[serverName] = next\n await writeProjectJson(ctx, workspacePath, data, servers)\n await activateProjectMcp(ctx, workspacePath, { ...config, serverName })\n return projectOf(ctx, workspacePath, workspace.title ?? '')\n}\n\n/** 删除一个项目 MCP:停用 → 从 .mcp.json 移除。 */\nexport async function projectRemove(ctx: Ctx, workspacePath: string, serverName: string): Promise<MpcProject> {\n const workspace = requireWorkspace(ctx, workspacePath)\n await deactivateMcp(ctx, projectEntryId(workspacePath, serverName))\n const data = await readProjectJson(ctx, workspacePath)\n const servers = serversOf(data)\n delete servers[serverName]\n await writeProjectJson(ctx, workspacePath, data, servers)\n return projectOf(ctx, workspacePath, workspace.title ?? '')\n}\n\n/** 切换项目 MCP 启用状态(持久化到 .mcp.json + loader.update)。 */\nexport async function projectToggle(ctx: Ctx, workspacePath: string, serverName: string, enabled: boolean): Promise<MpcProject> {\n const workspace = requireWorkspace(ctx, workspacePath)\n const data = await readProjectJson(ctx, workspacePath)\n const servers = serversOf(data)\n const def = servers[serverName]\n if (!def) throw new Error('项目中不存在该 MCP')\n if (enabled) delete def.disabled\n else def.disabled = true\n await writeProjectJson(ctx, workspacePath, data, servers)\n const loader = ctx.get('loader')\n if (loader) {\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id ?? candidate.options?.id ?? '') === projectEntryId(workspacePath, serverName))\n if (entry) await loader.update(entry.id, { disabled: !enabled })\n }\n return projectOf(ctx, workspacePath, workspace.title ?? '')\n}\n\n/** 刷新(重连)项目 MCP。 */\nexport async function projectRefresh(ctx: Ctx, workspacePath: string, serverName: string): Promise<MpcProject> {\n const workspace = requireWorkspace(ctx, workspacePath)\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const id = projectEntryId(workspacePath, serverName)\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id ?? candidate.options?.id ?? '') === id)\n if (!entry) throw new Error('该项目 MCP 未激活')\n await loader.update(entry.id, { config: { ...(entry.options?.config ?? {}) } })\n return projectOf(ctx, workspacePath, workspace.title ?? '')\n}\n","/**\n * dsh-vscode-mode host — Unity 内嵌包一键安装/更新。\n * 机制:把包源目录 unity/com.dsh.editor 复制为 <Unity项目根>/Packages/com.dsh.editor\n * (Unity 内嵌包自动发现,无需改 manifest.json);安装/更新同入口(整目录替换);\n * 卸载 = 删除目标目录。登记清单存 ~/.dsh/dsh-vscode-mode/unity-projects.json。\n * 安全:只触碰固定目标目录;项目根须含 Assets + ProjectSettings;目标已存在且\n * package.json name 不是本包 → 拒绝覆盖。纯路径构造与项目特征判定可单测。\n * 作者 ddj 2026-09-07\n */\nimport { cp, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises'\nimport { basename, dirname, join, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { dshHome, PLUGIN_ID } from './paths.js'\nimport { UNITY_PACKAGE_NAME } from './shared/integration.js'\nimport type { UnityListPayload, UnityProjectEntry } from './shared/integration.js'\n\n/** Unity 项目特征目录。 */\nconst UNITY_MARKERS = ['Assets', 'ProjectSettings']\n/** 登记清单文件名。 */\nconst PROJECTS_FILE = 'unity-projects.json'\n/** 包源目录相对插件包根的位置。 */\nconst UNITY_DIR_NAME = 'unity'\n\n/**\n * 包源目录(随插件包分发的 unity/com.dsh.editor 绝对路径)。\n * @author ddj 2026年09月07号\n * @param moduleUrl 模块 URL(缺省 import.meta.url;测试注入)\n * @returns 包源目录绝对路径\n */\nexport function unitySourceDir(moduleUrl: string = import.meta.url): string {\n return join(dirname(fileURLToPath(moduleUrl)), '..', UNITY_DIR_NAME, UNITY_PACKAGE_NAME)\n}\n\n/**\n * 项目登记清单文件(~/.dsh/dsh-vscode-mode/unity-projects.json)。\n * @author ddj 2026年09月07号\n * @param home DSH home(测试可注入)\n * @returns 清单文件绝对路径\n */\nexport function unityProjectsFile(home = dshHome()): string {\n return join(home, PLUGIN_ID, PROJECTS_FILE)\n}\n\n/**\n * 归一化用户输入的项目根:去首尾空白/引号/尾部分隔符。\n * @author ddj 2026年09月07号\n * @param raw 原始输入\n * @returns 归一化绝对路径\n */\nexport function normalizeUnityRoot(raw: string): string {\n return String(raw ?? '').trim().replace(/^[\"']|[\"']$/g, '').replace(/[\\\\/]+$/, '')\n}\n\n/**\n * 目录名清单是否满足 Unity 项目特征(Assets + ProjectSettings 同时存在)。\n * @author ddj 2026年09月07号\n * @param entries 项目根下的目录名清单\n * @returns 是否 Unity 项目根\n */\nexport function isUnityProject(entries: string[]): boolean {\n return UNITY_MARKERS.every((marker) => entries.includes(marker))\n}\n\n/**\n * 内嵌包目标目录(固定:<root>/Packages/com.dsh.editor)。\n * @author ddj 2026年09月07号\n * @param root Unity 项目根\n * @returns 目标目录绝对路径\n */\nexport function unityTargetOf(root: string): string {\n return join(root, 'Packages', UNITY_PACKAGE_NAME)\n}\n\n/**\n * 读 package.json 的 version(缺失/非法 → null)。\n * @author ddj 2026年09月07号\n * @param pkgFile package.json 绝对路径\n * @returns 版本号或 null\n */\nexport async function readPackageVersion(pkgFile: string): Promise<string | null> {\n try {\n const data = JSON.parse(await readFile(pkgFile, 'utf8')) as { version?: unknown }\n return typeof data?.version === 'string' && data.version ? data.version : null\n } catch {\n return null\n }\n}\n\n/** 登记清单单条记录。 */\ninterface ProjectRecord { path: string; addedAt: string }\n\n/** 读登记清单(缺失/非法 → 空数组)。 */\nasync function readProjects(home = dshHome()): Promise<ProjectRecord[]> {\n try {\n const data: unknown = JSON.parse(await readFile(unityProjectsFile(home), 'utf8'))\n if (!Array.isArray(data)) return []\n return (data as unknown[])\n .filter((item): item is ProjectRecord => !!item && typeof (item as ProjectRecord).path === 'string')\n .map((item) => ({ path: String(item.path), addedAt: String(item.addedAt ?? '') }))\n } catch {\n return []\n }\n}\n\n/** 写登记清单(父目录按需创建)。 */\nasync function writeProjects(records: ProjectRecord[], home = dshHome()): Promise<void> {\n const file = unityProjectsFile(home)\n await mkdir(dirname(file), { recursive: true })\n await writeFile(file, JSON.stringify(records, null, 2) + '\\n', 'utf8')\n}\n\n/**\n * 单个项目的安装状态视图(版本对比 + 合法性)。\n * @author ddj 2026年09月07号\n * @param rawPath 项目路径(原始输入)\n * @param moduleUrl 模块 URL(测试注入)\n * @returns 项目状态\n */\nexport async function unityEntryOf(rawPath: string, moduleUrl: string = import.meta.url): Promise<UnityProjectEntry> {\n const root = normalizeUnityRoot(rawPath)\n const entry: UnityProjectEntry = { path: root, title: basename(root) || root, installedVersion: null, upToDate: false, missingDir: false }\n let names: string[] = []\n try {\n names = await readdir(root)\n } catch {\n entry.missingDir = true\n return entry\n }\n if (!isUnityProject(names)) {\n entry.error = '不是 Unity 项目根(缺少 Assets 或 ProjectSettings 目录)'\n return entry\n }\n const installed = await readPackageVersion(join(unityTargetOf(root), 'package.json'))\n entry.installedVersion = installed\n const sourceVersion = await readPackageVersion(join(unitySourceDir(moduleUrl), 'package.json'))\n entry.upToDate = installed !== null && installed === sourceVersion\n return entry\n}\n\n/**\n * 列出登记项目与包源版本。\n * @author ddj 2026年09月07号\n * @param moduleUrl 模块 URL(测试注入)\n * @param home DSH home(测试注入)\n * @returns 列表载荷\n */\nexport async function unityList(moduleUrl: string = import.meta.url, home = dshHome()): Promise<UnityListPayload> {\n const source = unitySourceDir(moduleUrl)\n const records = await readProjects(home)\n const projects: UnityProjectEntry[] = []\n for (const record of records) projects.push(await unityEntryOf(record.path, moduleUrl))\n return { sourceVersion: await readPackageVersion(join(source, 'package.json')), sourcePath: source, projects }\n}\n\n/**\n * 登记一个 Unity 项目(校验通过才入清单,重复登记幂等)。\n * @author ddj 2026年09月07号\n * @param rawPath 项目路径(原始输入)\n * @param moduleUrl 模块 URL(测试注入)\n * @param home DSH home(测试注入)\n * @returns 项目状态\n */\nexport async function unityAdd(rawPath: string, moduleUrl: string = import.meta.url, home = dshHome()): Promise<UnityProjectEntry> {\n const root = normalizeUnityRoot(rawPath)\n const entry = await unityEntryOf(root, moduleUrl)\n if (entry.missingDir) throw new Error('目录不存在:' + root)\n if (entry.error) throw new Error(entry.error)\n const records = await readProjects(home)\n if (!records.some((record) => normalizeUnityRoot(record.path) === root)) {\n records.push({ path: root, addedAt: new Date().toISOString() })\n await writeProjects(records, home)\n }\n return entry\n}\n\n/**\n * 移除一个项目的登记(不删除已安装的包目录)。\n * @author ddj 2026年09月07号\n * @param rawPath 项目路径(原始输入)\n * @param home DSH home(测试注入)\n */\nexport async function unityRemove(rawPath: string, home = dshHome()): Promise<void> {\n const root = normalizeUnityRoot(rawPath)\n const records = await readProjects(home)\n await writeProjects(records.filter((record) => normalizeUnityRoot(record.path) !== root), home)\n}\n\n/**\n * 一键安装/更新:整目录替换 <root>/Packages/com.dsh.editor 为包源内容。\n * @author ddj 2026年09月07号\n * @param rawPath 项目路径(原始输入)\n * @param moduleUrl 模块 URL(测试注入)\n * @returns 安装后项目状态\n */\nexport async function unityInstall(rawPath: string, moduleUrl: string = import.meta.url): Promise<UnityProjectEntry> {\n const root = normalizeUnityRoot(rawPath)\n const source = unitySourceDir(moduleUrl)\n const target = unityTargetOf(root)\n await validateInstallTarget(root, source, target)\n await rm(target, { recursive: true, force: true })\n await mkdir(join(target, '..'), { recursive: true })\n await cp(source, target, { recursive: true })\n return unityEntryOf(root, moduleUrl)\n}\n\n/**\n * 安装前校验:Unity 项目根 + 目标不与包源重叠 + 已存在目标必须是本包。\n * @author ddj 2026年09月07号\n * @param root 项目根\n * @param source 包源目录\n * @param target 目标目录\n */\nasync function validateInstallTarget(root: string, source: string, target: string): Promise<void> {\n let names: string[] = []\n try {\n names = await readdir(root)\n } catch {\n throw new Error('目录不存在:' + root)\n }\n if (!isUnityProject(names)) throw new Error('不是 Unity 项目根(缺少 Assets 或 ProjectSettings 目录)')\n if (target === source || target.startsWith(source + sep) || source.startsWith(target + sep)) {\n throw new Error('目标目录与包源重叠,拒绝安装')\n }\n const text = await readFile(join(target, 'package.json'), 'utf8').catch((error: NodeJS.ErrnoException) => {\n if (error?.code === 'ENOENT') return null\n throw error\n })\n if (text === null) return\n let name: unknown = null\n try {\n name = (JSON.parse(text) as { name?: unknown }).name\n } catch { /* 解析失败按未知包处理 */ }\n if (name !== UNITY_PACKAGE_NAME) throw new Error('目标目录已存在且不是 DSH 包,拒绝覆盖:' + target)\n}\n","/**\n * dsh-vscode-mode host — 资源管理器右键菜单「在 DSH 文件编辑中打开」(跨平台)。\n * - Windows:launcher(assets/shell/dsh-open.cs 经 csc 编译 WinExe,csc 缺失降级 ps1)安装到\n * ~/.dsh/dsh-vscode-mode/shell/,HKCU\\Software\\Classes 三类菜单键(`*`/Directory/Directory\\Background)。\n * - Linux:dsh-open.sh + GNOME Files(Nautilus)右键脚本 + KDE Dolphin 服务菜单(纯文件写入)。\n * - macOS:dsh-open.sh(Finder 快速操作由用户按配方手动创建,自动检测/移除)。\n * 生命周期:注册成功写 marker(shell/registered.json)→ 插件卸载/reload 清理注册痕迹,\n * 启动时 marker 存在则自动恢复(更新插件不丢注册);用户显式「移除注册」删 marker 永不自动恢复。\n * 所有 reg/csc 调用经 subprocess 服务 argv 数组(卸载清理用 child_process 直调,teardown 可靠)。\n * 纯函数(键路径/命令行/ini/脚本内容)可单测。\n * 作者 ddj 2026-09-07\n */\nimport { spawn } from 'node:child_process'\nimport { chmod, copyFile, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { assetsDirOf, dshHome, PLUGIN_ID } from './paths.js'\nimport { INTEGRATION_BASE_DEFAULT, SHELL_MENU_LEAF } from './shared/integration.js'\nimport { unitySourceDir } from './unityBridge.js'\nimport type { ShellIntegrationStatus, ShellLauncherState, ShellMenuEntry } from './shared/integration.js'\nimport type { Ctx } from './store.js'\n\n/** 菜单显示名(Windows 键默认值 / Linux 菜单项名 / macOS workflow 名)。 */\nexport const MENU_LABEL = '在 DSH 文件编辑中打开'\n/** 编译 launcher 文件名(Windows)。 */\nexport const LAUNCHER_EXE = 'dsh-open.exe'\n/** launcher C# 源文件名。 */\nexport const LAUNCHER_CS = 'dsh-open.cs'\n/** 降级 launcher 脚本名(Windows)。 */\nexport const LAUNCHER_PS1 = 'dsh-open.ps1'\n/** POSIX launcher 脚本名(Linux/macOS 通用)。 */\nexport const LAUNCHER_SH = 'dsh-open.sh'\n/** 深链基址配置文件名。 */\nexport const INI_NAME = 'dsh-open.ini'\n/** 注册 marker 文件名(存在 = 用户注册过且未显式移除)。 */\nexport const MARKER_NAME = 'registered.json'\n/** command 中文件路径占位符(多选时资源管理器逐项展开重复该占位符)。 */\nexport const FILE_TOKEN = '%1'\n/** 文件夹空白处场景的路径占位符。 */\nexport const BACKGROUND_TOKEN = '%V'\n/** Icon 值名。 */\nexport const REG_VALUE_NAME_ICON = 'Icon'\n/** Nautilus 右键脚本文件名。 */\nexport const NAUTILUS_NAME = MENU_LABEL\n/** Dolphin 服务菜单文件名。 */\nexport const DOLPHIN_NAME = 'dsh-editor.desktop'\n/** Finder 快速操作(workflow 包)目录名。 */\nexport const FINDER_NAME = MENU_LABEL + '.workflow'\n/** DSH 小鲸鱼图标文件名(右键菜单 Icon,注册时复制到安装目录)。 */\nexport const WHALE_ICO = 'dsh-whale.ico'\n\n/** 一次 argv 运行结果(退出码 + 输出)。 */\ninterface RunOutcome { code: number | null; output: string }\n\n/** 注册 marker 内容。 */\ninterface RegistrationMarker { baseUrl: string; at: string }\n\n/**\n * reg.exe 路径(SystemRoot 派生;env 可注入便于测试)。\n * @author ddj 2026年09月07号\n * @param env 环境映射(缺省 process.env)\n * @returns reg.exe 绝对路径\n */\nexport function regExe(env: Record<string, string | undefined> = process.env): string {\n return join(systemRoot(env), 'System32', 'reg.exe')\n}\n\n/**\n * csc.exe 候选列表(.NET Framework 4.x 常驻路径,按存在性取首个)。\n * @author ddj 2026年09月07号\n * @param env 环境映射(缺省 process.env)\n * @returns 候选绝对路径列表\n */\nexport function cscCandidates(env: Record<string, string | undefined> = process.env): string[] {\n const root = systemRoot(env)\n return [\n join(root, 'Microsoft.NET', 'Framework64', 'v4.0.30319', 'csc.exe'),\n join(root, 'Microsoft.NET', 'Framework', 'v4.0.30319', 'csc.exe'),\n ]\n}\n\n/**\n * Windows 三类菜单键完整路径。\n * @author ddj 2026年09月07号\n * @param leaf 菜单键叶子名(缺省 DSHEditor)\n * @returns files/dir/background 三个键路径\n */\nexport function menuKeyPaths(leaf: string = SHELL_MENU_LEAF): { files: string; dir: string; background: string } {\n const root = 'HKCU\\\\Software\\\\Classes'\n return {\n files: root + '\\\\*\\\\shell\\\\' + leaf,\n dir: root + '\\\\Directory\\\\shell\\\\' + leaf,\n background: root + '\\\\Directory\\\\Background\\\\shell\\\\' + leaf,\n }\n}\n\n/**\n * launcher 安装目录(~/.dsh/dsh-vscode-mode/shell)。\n * @author ddj 2026年09月07号\n * @param home DSH home(测试可注入)\n * @returns 安装目录绝对路径\n */\nexport function shellInstallDir(home = dshHome()): string {\n return join(home, PLUGIN_ID, 'shell')\n}\n\n/**\n * Nautilus 右键脚本路径(~/.local/share/nautilus/scripts/)。\n * @author ddj 2026年09月07号\n * @param home 用户 home(测试可注入)\n */\nexport function nautilusPath(home = homedir()): string {\n return join(home, '.local', 'share', 'nautilus', 'scripts', NAUTILUS_NAME)\n}\n\n/**\n * Dolphin 服务菜单路径(新 kio/servicemenus + 旧 kservices5,两个都写)。\n * @author ddj 2026年09月07号\n * @param home 用户 home(测试可注入)\n */\nexport function dolphinMenuPaths(home = homedir()): string[] {\n return [\n join(home, '.local', 'share', 'kio', 'servicemenus', DOLPHIN_NAME),\n join(home, '.local', 'share', 'kservices5', 'ServiceMenus', DOLPHIN_NAME),\n ]\n}\n\n/**\n * Finder 快速操作 workflow 包路径(~/Library/Services/)。\n * @author ddj 2026年09月07号\n * @param home 用户 home(测试可注入)\n */\nexport function finderWorkflowPath(home = homedir()): string {\n return join(home, 'Library', 'Services', FINDER_NAME)\n}\n\n/**\n * 注册 marker 文件路径(shell/registered.json)。\n * @author ddj 2026年09月07号\n * @param home DSH home(测试可注入)\n */\nexport function markerFile(home = dshHome()): string {\n return join(shellInstallDir(home), MARKER_NAME)\n}\n\n/**\n * command 默认值(Windows 编译 exe 版)。\n * @author ddj 2026年09月07号\n * @param exePath launcher 绝对路径\n * @param token 路径占位符\n * @returns 注册表 command 值\n */\nexport function commandValue(exePath: string, token: string = FILE_TOKEN): string {\n return '\"' + exePath + '\" \"' + token + '\"'\n}\n\n/**\n * command 默认值(Windows 降级 ps1 版:隐藏窗口运行脚本)。\n * @author ddj 2026年09月07号\n * @param ps1Path launcher 脚本绝对路径\n * @param token 路径占位符\n * @param powerShell powershell.exe 路径(测试可注入)\n * @returns 注册表 command 值\n */\nexport function ps1CommandValue(ps1Path: string, token: string = FILE_TOKEN, powerShell = powerShellExe()): string {\n return '\"' + powerShell + '\" -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File \"' + ps1Path + '\" \"' + token + '\"'\n}\n\n/**\n * dsh-open.ini 内容(base 行驱动 launcher 深链基址,三平台共用)。\n * @author ddj 2026年09月07号\n * @param baseUrl 深链基址\n * @returns ini 文件全文\n */\nexport function iniContent(baseUrl: string): string {\n return '[dsh]\\nbase=' + (baseUrl.trim() || INTEGRATION_BASE_DEFAULT) + '\\n'\n}\n\n/**\n * Nautilus 右键脚本内容(多选经 NAUTILUS_SCRIPT_SELECTED_FILE_PATHS 一次传给 launcher)。\n * @author ddj 2026年09月07号\n * @param launcherPath dsh-open.sh 绝对路径\n * @returns 脚本全文(#!/usr/bin/env bash)\n */\nexport function nautilusScript(launcherPath: string): string {\n return [\n '#!/usr/bin/env bash',\n '# 由 dsh-vscode-mode 生成:GNOME Files(Nautilus)右键脚本 → DSH 文件编辑',\n 'launcher=\"$HOME/.dsh/dsh-vscode-mode/shell/' + LAUNCHER_SH + '\"',\n 'args=()',\n 'while IFS= read -r line; do',\n ' [ -n \"$line\" ] && args+=(\"$line\")',\n 'done <<< \"${NAUTILUS_SCRIPT_SELECTED_FILE_PATHS:-}\"',\n 'exec \"$launcher\" \"${args[@]}\"',\n '',\n ].join('\\n')\n}\n\n/**\n * Dolphin 服务菜单内容(%F 多选传参)。\n * @author ddj 2026年09月07号\n * @param launcherPath dsh-open.sh 绝对路径\n * @returns .desktop 全文\n */\nexport function dolphinMenu(launcherPath: string): string {\n return [\n '[Desktop Entry]',\n 'Type=Service',\n 'X-KDE-ServiceTypes=KonqPopupMenu/Plugin',\n 'MimeType=all/allfiles;inode/directory;',\n 'Actions=openInDshEditor',\n '[Desktop Action openInDshEditor]',\n 'Name=' + MENU_LABEL,\n 'Icon=utilities-terminal',\n 'Exec=\"' + launcherPath + '\" %F',\n '',\n ].join('\\n')\n}\n\n/** SystemRoot 解析(env 可注入)。 */\nfunction systemRoot(env: Record<string, string | undefined>): string {\n return env.SystemRoot || 'C:\\\\Windows'\n}\n\n/** powershell.exe 路径(Windows 降级注册用)。 */\nfunction powerShellExe(env: Record<string, string | undefined> = process.env): string {\n return join(systemRoot(env), 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe')\n}\n\n/** POSIX launcher 脚本安装路径。 */\nfunction shLauncherPath(home = dshHome()): string {\n return join(shellInstallDir(home), LAUNCHER_SH)\n}\n\n/**\n * 经 subprocess 服务运行一个命令(argv 数组,无 shell 插值)。\n * ⚠️ stdio 必须 'inherit':受管 host 环境禁止管道 stdio(node spawn pipe → EPERM),\n * inherit 直写宿主控制台且不建管道;本模块只需退出码(reg query 缺键 = 退出码 1)。\n * done 契约宽松归一化:{exitCode,signal} / {code} / undefined / 抛错(spawn 失败)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param argv 命令与参数\n * @param cwd 工作目录(须已存在)\n * @returns 退出码(0=成功)\n */\nasync function runArgv(ctx: Ctx, argv: string[], cwd = dshHome()): Promise<RunOutcome> {\n const sub = ctx.get('subprocess')\n if (!sub || typeof sub.spawn !== 'function') throw new Error('缺少 subprocess 服务')\n let handle: { done: Promise<unknown> }\n try {\n handle = sub.spawn({\n argv,\n cwd,\n stdio: { stdout: 'inherit', stderr: 'inherit', stdin: 'ignore' },\n graceMs: 10000,\n })\n } catch (error) {\n return { code: 1, output: String(error) }\n }\n try {\n return normalizeOutcome(await handle.done)\n } catch (error) {\n return { code: 1, output: String(error) }\n }\n}\n\n/** 归一化 done 结果(契约宽松:{exitCode,signal} / {code} / 字符串 / undefined)。 */\nfunction normalizeOutcome(result: unknown): RunOutcome {\n if (result == null) return { code: 0, output: '' }\n if (typeof result === 'string') return { code: 0, output: result }\n const record = result as { exitCode?: unknown; code?: unknown }\n if (typeof record.exitCode === 'number') return { code: record.exitCode, output: '' }\n if (typeof record.code === 'number') return { code: record.code, output: '' }\n return { code: 0, output: '' }\n}\n\n/** 文件存在性探测(best-effort)。 */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n return (await stat(path)).isFile()\n } catch {\n return false\n }\n}\n\n/** Windows:探测一个注册表键是否存在(reg query 缺键 = 退出码 1,无需读输出)。 */\nasync function keyExists(ctx: Ctx, key: string): Promise<boolean> {\n const outcome = await runArgv(ctx, [regExe(), 'query', key, '/ve'])\n return outcome.code === 0\n}\n\n/** 读注册 marker(缺失/非法 → null)。 */\nasync function readMarker(home = dshHome()): Promise<RegistrationMarker | null> {\n try {\n const data = JSON.parse(await readFile(markerFile(home), 'utf8')) as { baseUrl?: unknown; at?: unknown }\n if (typeof data?.baseUrl !== 'string' || !data.baseUrl) return null\n return { baseUrl: data.baseUrl, at: typeof data.at === 'string' ? data.at : '' }\n } catch {\n return null\n }\n}\n\n/** 写注册 marker(父目录已存在)。 */\nasync function saveMarker(baseUrl: string, home = dshHome()): Promise<void> {\n const data: RegistrationMarker = { baseUrl, at: new Date().toISOString() }\n await writeFile(markerFile(home), JSON.stringify(data, null, 2) + '\\n', 'utf8')\n}\n\n/** 复制 POSIX launcher 并加执行位(三平台 ini 同写)。 */\nasync function installPosix(dir: string, baseUrl: string): Promise<void> {\n await copyFile(join(assetsDirOf(import.meta.url), 'shell', LAUNCHER_SH), join(dir, LAUNCHER_SH))\n await chmod(join(dir, LAUNCHER_SH), 0o755)\n await writeFile(join(dir, INI_NAME), iniContent(baseUrl), 'utf8')\n}\n\n/** 写 Nautilus 右键脚本(父目录按需创建 + 执行位)。 */\nasync function writeNautilus(home: string, launcherPath: string): Promise<void> {\n const script = nautilusPath(home)\n await mkdir(join(script, '..'), { recursive: true })\n await writeFile(script, nautilusScript(launcherPath), 'utf8')\n await chmod(script, 0o755)\n}\n\n/** 写 Dolphin 服务菜单(新/旧两个路径,父目录按需创建)。 */\nasync function writeDolphinMenus(home: string, launcherPath: string): Promise<void> {\n for (const menu of dolphinMenuPaths(home)) {\n await mkdir(join(menu, '..'), { recursive: true })\n await writeFile(menu, dolphinMenu(launcherPath), 'utf8')\n }\n}\n\n/** Linux:移除 Nautilus 脚本与 Dolphin 服务菜单(仅本插件自有文件)。 */\nasync function removePosixFiles(home: string): Promise<void> {\n await rm(nautilusPath(home), { force: true })\n for (const menu of dolphinMenuPaths(home)) await rm(menu, { force: true })\n}\n\n/** macOS:移除 Finder 快速操作(仅当其内容引用本插件 launcher,防误删用户手工产物)。 */\nasync function dropFinderMenu(home: string): Promise<void> {\n const dir = finderWorkflowPath(home)\n let text = ''\n try {\n text = await readFile(join(dir, 'Contents', 'document.wflow'), 'utf8')\n } catch {\n return\n }\n if (!text.includes('dsh-open')) return\n await rm(dir, { recursive: true, force: true })\n}\n\n/** 卸载清理专用:直调 reg delete(subprocess 服务在 teardown 可能已卸载)。⚠️ stdio 'ignore':受管环境禁管道。 */\nfunction regDeleteDirect(key: string): Promise<void> {\n return new Promise((resolve) => {\n try {\n const child = spawn(regExe(), ['delete', key, '/f'], { windowsHide: true, timeout: 5000, stdio: 'ignore' })\n child.once('close', () => resolve())\n child.once('error', () => resolve())\n } catch {\n resolve()\n }\n })\n}\n\n/**\n * 查询系统集成状态(按平台探测条目注册状态 + launcher 安装态)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param baseUrl 深链基址(设置 integrationBaseUrl)\n * @returns 集成状态\n */\nexport async function shellMenuStatus(ctx: Ctx, baseUrl: string): Promise<ShellIntegrationStatus> {\n const dir = shellInstallDir()\n const platform = process.platform\n let launcher: ShellLauncherState\n let entries: ShellMenuEntry[] = []\n if (platform === 'win32') {\n const exe = join(dir, LAUNCHER_EXE)\n const ps1 = join(dir, LAUNCHER_PS1)\n const compiled = await fileExists(exe)\n const ps1Present = await fileExists(ps1)\n launcher = { present: compiled || ps1Present, compiled, path: compiled ? exe : ps1 }\n entries = [\n { id: 'files', label: '文件', registered: await keyExists(ctx, menuKeyPaths().files) },\n { id: 'dir', label: '文件夹', registered: await keyExists(ctx, menuKeyPaths().dir) },\n { id: 'dirBackground', label: '文件夹空白处', registered: await keyExists(ctx, menuKeyPaths().background) },\n ]\n } else {\n const sh = shLauncherPath()\n launcher = { present: await fileExists(sh), compiled: false, path: sh }\n if (platform === 'linux') {\n const menus = dolphinMenuPaths()\n entries = [\n { id: 'nautilus', label: 'GNOME Files(Nautilus)', registered: await fileExists(nautilusPath()) },\n { id: 'dolphin', label: 'KDE Dolphin', registered: (await fileExists(menus[0])) || (await fileExists(menus[1])) },\n ]\n } else if (platform === 'darwin') {\n entries = [{ id: 'finder', label: 'Finder 快速操作', registered: await fileExists(finderWorkflowPath()), manual: true }]\n }\n }\n return { platform, launcher, entries, baseUrl, unityPackagePath: unitySourceDir() }\n}\n\n/**\n * 注册右键菜单(平台分发):写 ini → 安装 launcher → 首次备份(Windows)→ 写菜单;\n * 成功后写 marker(驱动卸载清理与重启自动恢复)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param baseUrl 深链基址\n * @returns 注册后状态\n */\nexport async function shellMenuRegister(ctx: Ctx, baseUrl: string): Promise<ShellIntegrationStatus> {\n const dir = shellInstallDir()\n await mkdir(dir, { recursive: true })\n if (process.platform === 'win32') {\n await writeFile(join(dir, INI_NAME), iniContent(baseUrl), 'utf8')\n await installIcon(dir)\n const compiled = await installLauncher(ctx, dir, true)\n if (!(await readMarker())) await backupKeys(ctx, dir)\n await writeMenuKeys(ctx, dir, compiled)\n } else if (process.platform === 'linux') {\n await installPosix(dir, baseUrl)\n const launcherPath = join(dir, LAUNCHER_SH)\n await writeNautilus(homedir(), launcherPath)\n await writeDolphinMenus(homedir(), launcherPath)\n } else if (process.platform === 'darwin') {\n // macOS 菜单由用户按 Automator 配方手动创建(UI 提供一键复制);这里仅安装 launcher\n await installPosix(dir, baseUrl)\n }\n await saveMarker(baseUrl)\n return shellMenuStatus(ctx, baseUrl)\n}\n\n/**\n * 移除右键菜单注册(平台分发)+ 删除 marker(显式移除后重启不再自动恢复)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param baseUrl 深链基址\n * @returns 移除后状态\n */\nexport async function shellMenuRemove(ctx: Ctx, baseUrl: string): Promise<ShellIntegrationStatus> {\n if (process.platform === 'win32') {\n const paths = menuKeyPaths()\n for (const key of [paths.files, paths.dir, paths.background]) {\n await runArgv(ctx, [regExe(), 'delete', key, '/f'])\n }\n } else if (process.platform === 'linux') {\n await removePosixFiles(homedir())\n } else if (process.platform === 'darwin') {\n await dropFinderMenu(homedir())\n }\n await rm(markerFile(), { force: true })\n return shellMenuStatus(ctx, baseUrl)\n}\n\n/**\n * 系统集成生命周期(index.ts 经 ctx.effect 挂载):\n * 启动时 marker 存在 → 幂等自动恢复注册(插件更新/reload 不丢注册);\n * 返回的 disposer 在插件卸载/reload 时清理注册痕迹(marker 保留供下次恢复)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @returns 卸载清理 disposer\n */\nexport function shellMenuLifecycle(ctx: Ctx): () => void {\n void restoreOnLoad(ctx).catch(() => {})\n return () => {\n void cleanupOnUnload().catch(() => {})\n }\n}\n\n/** 启动自动恢复:marker 存在才执行(幂等;exe 已存在跳过编译)。 */\nasync function restoreOnLoad(ctx: Ctx): Promise<void> {\n const marker = await readMarker()\n if (!marker) return\n await shellMenuRegister(ctx, marker.baseUrl)\n}\n\n/** 卸载清理:marker 存在 → 按平台移除注册痕迹(launcher 文件与 marker 保留)。 */\nasync function cleanupOnUnload(): Promise<void> {\n const marker = await readMarker()\n if (!marker) return\n if (process.platform === 'win32') {\n const paths = menuKeyPaths()\n for (const key of [paths.files, paths.dir, paths.background]) await regDeleteDirect(key)\n } else if (process.platform === 'linux') {\n await removePosixFiles(homedir())\n } else if (process.platform === 'darwin') {\n await dropFinderMenu(homedir())\n }\n}\n\n/**\n * 安装 Windows launcher:优先 csc 编译 exe(无控制台闪窗),任一候选失败降级复制 ps1。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param dir 安装目录(已存在)\n * @param force 是否强制重编译(自动恢复时 false:exe 已存在直接复用)\n * @returns 是否编译成功(false=降级 ps1)\n */\nasync function installLauncher(ctx: Ctx, dir: string, force: boolean): Promise<boolean> {\n const exe = join(dir, LAUNCHER_EXE)\n if (!force && await fileExists(exe)) return true\n const shellAssets = join(assetsDirOf(import.meta.url), 'shell')\n for (const candidate of cscCandidates()) {\n if (!(await fileExists(candidate))) continue\n try {\n await copyFile(join(shellAssets, LAUNCHER_CS), join(dir, LAUNCHER_CS))\n const outcome = await runArgv(ctx, [\n candidate,\n '/nologo',\n '/target:winexe',\n '/r:System.Windows.Forms.dll',\n '/r:System.Web.Extensions.dll',\n '/out:' + exe,\n join(dir, LAUNCHER_CS),\n ], dir)\n if (outcome.code === 0 && await fileExists(exe)) return true\n } catch { /* 任一候选失败继续降级 */ }\n }\n await copyFile(join(shellAssets, LAUNCHER_PS1), join(dir, LAUNCHER_PS1))\n return false\n}\n\n/**\n * 首次注册前备份 Windows 三类既有键(best-effort,键不存在时导出失败忽略)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param dir 备份文件落盘目录\n */\nasync function backupKeys(ctx: Ctx, dir: string): Promise<void> {\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const paths = menuKeyPaths()\n const targets: Array<[string, string]> = [\n [paths.files, 'files'],\n [paths.dir, 'dir'],\n [paths.background, 'background'],\n ]\n for (const [key, name] of targets) {\n await runArgv(ctx, [regExe(), 'export', key, join(dir, 'backup-' + name + '-' + stamp + '.reg'), '/y'], dir)\n }\n}\n\n/** 复制 DSH 小鲸鱼 ico 到安装目录(右键菜单 Icon 用;缺失不阻塞注册)。 */\nasync function installIcon(dir: string): Promise<void> {\n try {\n await copyFile(join(assetsDirOf(import.meta.url), 'shell', WHALE_ICO), join(dir, WHALE_ICO))\n } catch { /* 图标缺失不阻塞注册 */ }\n}\n\n/**\n * 写 Windows 三类菜单键(显示名 + Icon + command 子键)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param dir launcher 安装目录\n * @param compiled 是否为编译 exe(否则 ps1 command)\n */\nasync function writeMenuKeys(ctx: Ctx, dir: string, compiled: boolean): Promise<void> {\n const launcherPath = compiled ? join(dir, LAUNCHER_EXE) : join(dir, LAUNCHER_PS1)\n const iconPath = (await fileExists(join(dir, WHALE_ICO))) ? join(dir, WHALE_ICO) : launcherPath\n const keys: Array<[string, string]> = [\n [menuKeyPaths().files, FILE_TOKEN],\n [menuKeyPaths().dir, FILE_TOKEN],\n [menuKeyPaths().background, BACKGROUND_TOKEN],\n ]\n for (const [key, token] of keys) {\n const command = compiled ? commandValue(launcherPath, token) : ps1CommandValue(launcherPath, token)\n await addMenuKey(ctx, key, iconPath, command)\n }\n}\n\n/** 写一个 Windows 菜单键:默认值(显示名)+ Icon + command 子键。 */\nasync function addMenuKey(ctx: Ctx, key: string, iconPath: string, command: string): Promise<void> {\n const reg = regExe()\n await runArgv(ctx, [reg, 'add', key, '/ve', '/t', 'REG_SZ', '/d', MENU_LABEL, '/f'])\n await runArgv(ctx, [reg, 'add', key, '/v', REG_VALUE_NAME_ICON, '/t', 'REG_SZ', '/d', iconPath, '/f'])\n await runArgv(ctx, [reg, 'add', key + '\\\\command', '/ve', '/t', 'REG_SZ', '/d', command, '/f'])\n}\n","/**\n * dsh-vscode-mode host — 深链移交(避免重复打开 DSH 页面)。\n * launcher 投递待打开请求(edrv.external.handoff)→ 已打开页面 3s 轮询领取(edrv.external.pending)\n * 并就地执行打开规则;15s 内无页面轮询过 = 无活跃页面 → launcher 回退打开新页。\n * token 防多实例串扰;TTL 兜底防陈旧悬挂。模块级状态(host 单进程单例)。\n * 作者 ddj 2026-09-08\n */\nimport { randomUUID } from 'node:crypto'\n\n/** 一次外部打开请求(launcher 投递)。 */\nexport interface ExternalOpenRequest {\n paths: string[]\n line?: number\n column?: number\n}\n\n/** 待打开 TTL:超时未领取即丢弃(launcher 回退已自行处理)。 */\nconst PENDING_TTL_MS = 60_000\n/** 活跃页面判定窗口:窗口内有过 pending 轮询 = 有页面在。 */\nconst PRESENCE_WINDOW_MS = 15_000\n\nlet pending: (ExternalOpenRequest & { token: string; at: number }) | null = null\nlet lastPollAt = 0\n\n/**\n * 投递一次外部打开请求;返回活跃页面数(0 = launcher 应回退开新页)与移交 token。\n * @author ddj 2026年09月08号\n * @param req 打开请求\n * @returns 活跃页面数与 token\n */\nexport function handoffOpen(req: ExternalOpenRequest): { clients: number; token: string } {\n const token = randomUUID()\n pending = { ...req, token, at: Date.now() }\n return { token, clients: clientsAlive() ? 1 : 0 }\n}\n\n/**\n * 页面轮询:刷新活跃态并领取待打开请求(取走即清,多页面仅一方执行)。\n * @author ddj 2026年09月08号\n * @returns 待打开请求或 null\n */\nexport function pollPending(): ExternalOpenRequest | null {\n lastPollAt = Date.now()\n if (!pending) return null\n if (Date.now() - pending.at > PENDING_TTL_MS) {\n pending = null\n return null\n }\n const taken: ExternalOpenRequest = { paths: pending.paths, line: pending.line, column: pending.column }\n pending = null\n return taken\n}\n\n/**\n * 查询移交是否已被页面领取(take=true 时未领取则取走清除,供 launcher 回退开新页)。\n * @author ddj 2026年09月08号\n * @param token 移交 token\n * @param take 未领取时是否取走清除\n * @returns delivered=true = 已有页面领取(或已被更新的请求取代)\n */\nexport function pendingState(token: string, take: boolean): { delivered: boolean } {\n const delivered = pending === null || pending.token !== token\n if (take && !delivered) pending = null\n return { delivered }\n}\n\n/** 活跃页面判定。 */\nfunction clientsAlive(): boolean {\n return Date.now() - lastPollAt <= PRESENCE_WINDOW_MS\n}\n","/**\n * dsh-vscode-mode host — 在 OS 文件浏览器中打开/定位路径(reveal 能力)。\n * 纯函数 revealCommand 平台分发 + revealInExplorer 经 ctx.subprocess.spawn 发射\n * (argv 数组、无 shell 插值,沿 workspace/revert 的 subprocess 契约)。\n * 文件 → 资源管理器选中定位;目录 → 打开目录;Linux 无通用定位协议 → 打开所在目录。\n * 作者 ddj 2026-08-27\n */\nimport { dirname } from 'node:path'\nimport type { Ctx } from './store.js'\n\n/** reveal 结果(沿 revert.ts 的 Result 风格)。 */\nexport type RevealResult = { ok: true } | { ok: false; error: string }\n\n/**\n * 构造平台 opener 的 argv(纯函数,platform 可注入便于单测)。\n * @author ddj 2026年08月27号\n * @param absPath 绝对路径\n * @param isDir 是否为目录\n * @param platform 目标平台(缺省当前进程平台)\n * @returns opener argv(无 shell 插值)\n */\nexport function revealCommand(absPath: string, isDir: boolean, platform: NodeJS.Platform = process.platform): { argv: string[] } {\n switch (platform) {\n case 'darwin':\n return { argv: ['open', '-R', absPath] }\n case 'win32':\n // 文件 → 定位并选中;目录 → 直接打开该目录\n return isDir\n ? { argv: ['explorer.exe', absPath] }\n : { argv: ['explorer.exe', '/select,', absPath] }\n default:\n // Linux 无通用 select 协议:文件打开所在目录、目录打开自身(KISS,对齐 better-sidebar)\n return { argv: ['xdg-open', isDir ? absPath : dirname(absPath)] }\n }\n}\n\n/**\n * 经 host subprocess 服务发射 opener(fire-and-forget 语义)。\n * Explorer 为 GUI 分离进程,非零退出码不视为失败;仅 spawn 级错误回失败。\n * @author ddj 2026年08月27号\n * @param ctx DSH host 上下文\n * @param absPath 绝对路径\n * @param isDir 是否为目录\n * @returns 成功或失败原因\n */\nexport async function revealInExplorer(ctx: Ctx, absPath: string, isDir: boolean): Promise<RevealResult> {\n const sub = ctx.get('subprocess')\n if (!sub || typeof sub.spawn !== 'function') {\n return { ok: false, error: '打开文件浏览器不可用:缺少 subprocess 服务' }\n }\n const { argv } = revealCommand(absPath, isDir)\n try {\n const handle = sub.spawn({\n argv,\n cwd: dirname(absPath),\n stdio: { stdout: { maxBytes: 1 << 16 }, stderr: { maxBytes: 1 << 16 }, stdin: 'ignore' },\n graceMs: 10000,\n })\n await handle.done\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '打开失败:' + String(error) }\n }\n}\n","/**\n * dsh-vscode-mode host — 诊断文件通道(client 上报 → 缓冲批量落盘)。\n * 通道:edrv.debug RPC → 内存缓冲(满/空闲触发)→ 串行读改写\n * `~/.dsh/dsh-vscode-mode/logs/debug.<cwdHash>.log`(512KB 上限截断保留尾部)。\n * 设计:console 不一定落盘,文件可靠;写失败静默忽略(调试日志不阻塞业务)。\n * 迁移自 src/rpc.ts(enqueueDebug/flushDebug),逻辑一字不改,仅终端回显改走统一日志器。\n * 作者 ddj 2026-09-08\n */\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { DEBUG_LOG, debugLogFile, pluginLogRoot } from './paths.js'\nimport { log } from './log.js'\nimport type { Ctx } from './store.js'\n\n/** cwd → 内存缓冲:行数组 + 累计字节数 + 待触发 flush 定时器(攒批落盘,避免每条日志全文件读改写)。 */\nconst debugBuffers = new Map<string, { lines: string[]; len: number; timer: ReturnType<typeof setTimeout> | null }>()\n/** cwd → Promise 链:串行化 debug 日志落盘(fs read+write 非原子,避免并发丢行)。 */\nconst debugWriteQueues = new Map<string, Promise<void>>()\n/** debug 日志单文件上限:超限截断保留尾部,防文件无限增长拖慢每次追加。 */\nconst DEBUG_LOG_CAP = 512 * 1024\n/** debug 日志批量缓冲上限:攒满即落盘(一次读改写),上限内不逐条写文件。 */\nconst DEBUG_BUF_CAP = 32 * 1024\n/** debug 日志空闲 flush 延迟:缓冲未满时,静默一段时间后落盘一次。 */\nconst DEBUG_FLUSH_IDLE_MS = 1000\n/** cwd → 已清理旧工作区 debug 日志标记(一次性)。 */\nconst debugLegacyCleaned = new Set<string>()\n/** 诊断回显日志器(终端回显统一带 `[dsh-vscode-mode:debug]` 前缀)。 */\nconst debugLog = log.child('debug')\n\n/**\n * 批量落盘一条 debug 日志缓冲:读旧文件 → 追加 → 超上限截断保留尾部 → 一次写回。\n * 串行链保证同一 cwd 的读改写不交错丢行;写失败静默忽略(调试日志不阻塞业务)。\n * @author ddj 2026年09月08号\n * @param cwd 工作区(日志落 ~/.dsh/dsh-vscode-mode/logs/debug.<cwdHash>.log)\n * @param batch 本批日志行\n */\nfunction flushDebug(cwd: string, batch: string[]): Promise<void> {\n const prev = debugWriteQueues.get(cwd) ?? Promise.resolve()\n const task = prev.then(async () => {\n try {\n await mkdir(pluginLogRoot(), { recursive: true })\n const target = debugLogFile(cwd)\n const old = await readFile(target, 'utf8').catch(() => '')\n const appended = old + batch.map((l) => new Date().toISOString() + ' ' + l + '\\n').join('')\n const next = appended.length > DEBUG_LOG_CAP ? appended.slice(-Math.floor(DEBUG_LOG_CAP / 2)) : appended\n await writeFile(target, next, 'utf8')\n // 迁移后一次性清理旧工作区 debug 日志(best-effort)\n if (!debugLegacyCleaned.has(cwd)) {\n debugLegacyCleaned.add(cwd)\n await rm(join(cwd, DEBUG_LOG), { force: true }).catch(() => {})\n }\n } catch (e) { /* 写日志失败忽略 */ }\n })\n debugWriteQueues.set(cwd, task)\n return task\n}\n\n/**\n * 记录一条 client 上报的诊断日志:入队缓冲批量落盘 + 终端回显(`[dsh-vscode-mode:debug]` 前缀)。\n * @author ddj 2026年09月08号\n * @param _ctx DSH 上下文(入参保留:诊断通道按 cwd 隔离,当前不需要 ctx,未来过滤用)\n * @param cwd 工作区(日志文件按 cwd hash 隔离)\n * @param text 单条日志文本(不含换行)\n */\nexport function debugRecord(_ctx: Ctx, cwd: string, text: string): void {\n const st = debugBuffers.get(cwd) ?? { lines: [], len: 0, timer: null }\n st.lines.push(text)\n st.len += text.length\n const flush = () => {\n st.timer = null\n const batch = st.lines\n st.lines = []\n st.len = 0\n void flushDebug(cwd, batch)\n }\n if (st.len >= DEBUG_BUF_CAP) {\n if (st.timer) clearTimeout(st.timer)\n flush()\n } else if (!st.timer) {\n st.timer = setTimeout(flush, DEBUG_FLUSH_IDLE_MS)\n }\n debugBuffers.set(cwd, st)\n debugLog.error(text)\n}\n","/**\n * dsh-vscode-mode host — DSH 会话性能管理(会话卫生 + 体积 stat + 侧车摘要)。\n * 职责:\n * - 盘点 ~/.dsh/sessions 全部工作区会话(每会话仅 stat 日志文件,不解压,轻量);\n * - 移出/恢复/清除:会话目录在 ~/.dsh/sessions 与 ~/.dsh/sessions-archive 间可逆搬迁;\n * - 当前会话体积 stat(对话头部指示器用,纯 stat);\n * - 侧车摘要:agent/脚本取关键字段,避免整份读 .dsh-edit-review.json 进对话。\n * 纯函数可单测(路径编码/移出规划);fs 操作 best-effort 返回逐项结果不抛。\n * 作者 ddj 2026-09-02\n */\nimport { mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises'\nimport { dirname, join, resolve, sep } from 'node:path'\nimport { parseSidecar } from './store.js'\nimport { recSummary } from './model.js'\nimport { SIDECAR, SIDECAR_ARCHIVE, dshHome, sessionIdSegment, sessionWorkspaceKey, sessionsRoot } from './paths.js'\nimport type { PerfMoveFailure, PerfMoveItem, PerfSession, PerfTotals, PerfWorkspace, SidecarPerfSummary } from './shared/rpc.js'\nimport type { Ctx } from './store.js'\n\n/** 会话日志文件名(zstd 优先,降级纯 jsonl)。 */\nconst LOG_NAMES = ['session.jsonl.zstd', 'session.jsonl']\n\n/** 归档根(~/.dsh/sessions-archive,与 sessions 同级,可逆移出的落点)。 */\nexport function sessionsArchiveRoot(home = dshHome()): string {\n return join(home, 'sessions-archive')\n}\n\n/** 会话盘点结果(工作区聚合 + 会话明细 + 汇总)。 */\nexport interface SessionInventory {\n workspaces: PerfWorkspace[]\n sessions: PerfSession[]\n totals: PerfTotals\n}\n\n/** 移出规划条件:显式集合或规则(minBytes / olderThanDays)。 */\nexport interface MoveCriteria {\n workspaceKey?: string\n sessionIds?: string[]\n minBytes?: number\n olderThanDays?: number\n}\n\n/** 路径段校验:非空、非 . / ..、不含分隔符与 Windows 非法字符(防 join 逃逸)。 */\nexport function validDirName(name: string): boolean {\n return typeof name === 'string' && name.length > 0 && name !== '.' && name !== '..' && !/[/\\\\]/.test(name) && !/[:*?\"<>|]/.test(name)\n}\n\n/** target 必须落在 root 内(自身或其子路径),防路径穿越。 */\nexport function withinDir(target: string, root: string): boolean {\n const rel = resolve(target)\n const base = resolve(root)\n return rel === base || rel.startsWith(base + sep)\n}\n\n/** stat 一个会话目录里的日志文件(首个存在的),缺失 → null。 */\nexport async function statSessionLog(sessionDir: string): Promise<{ size: number; mtimeMs: number } | null> {\n for (const name of LOG_NAMES) {\n try {\n const info = await stat(join(sessionDir, name))\n if (info.isFile()) return { size: info.size, mtimeMs: info.mtimeMs }\n } catch (error) { /* 尝试下一个日志名 */ }\n }\n return null\n}\n\n/**\n * 盘点 ~/.dsh/sessions:按工作区分组,每会话仅 stat 日志文件体积与 mtime。\n * 不解压日志(V8 展开成本高),活跃标记由调用方传入后置。\n * @author ddj 2026年09月02号\n * @param home DSH home(测试可注入)\n * @param archive 归档根(默认 sessions-archive;测试可注入)\n * @returns 工作区聚合(按体积降序)+ 会话明细(按体积降序)+ 汇总\n */\nexport async function scanSessionInventory(home = dshHome(), archive = sessionsArchiveRoot(home)): Promise<SessionInventory> {\n void archive\n const root = sessionsRoot(home)\n const workspaces: PerfWorkspace[] = []\n const sessions: PerfSession[] = []\n let totalBytes = 0\n let totalCount = 0\n const wsDirs = await readdir(root, { withFileTypes: true }).catch(() => [])\n for (const ws of wsDirs) {\n if (!ws.isDirectory() || !validDirName(ws.name)) continue\n const wsDir = join(root, ws.name)\n const wsSessions: PerfSession[] = []\n let wsBytes = 0\n let minMtime = Number.POSITIVE_INFINITY\n let maxMtime = 0\n const sessionDirs = await readdir(wsDir, { withFileTypes: true }).catch(() => [])\n for (const sd of sessionDirs) {\n if (!sd.isDirectory()) continue\n const info = await statSessionLog(join(wsDir, sd.name))\n if (!info) continue\n const row: PerfSession = { sessionId: sd.name, workspaceKey: ws.name, bytes: info.size, mtime: info.mtimeMs, active: false }\n wsSessions.push(row)\n wsBytes += info.size\n totalBytes += info.size\n totalCount += 1\n if (info.mtimeMs < minMtime) minMtime = info.mtimeMs\n if (info.mtimeMs > maxMtime) maxMtime = info.mtimeMs\n }\n wsSessions.sort((a, b) => b.bytes - a.bytes)\n sessions.push(...wsSessions)\n workspaces.push({\n workspaceKey: ws.name,\n sessionCount: wsSessions.length,\n totalBytes: wsBytes,\n minMtime: Number.isFinite(minMtime) ? minMtime : 0,\n maxMtime,\n })\n }\n workspaces.sort((a, b) => b.totalBytes - a.totalBytes)\n return { workspaces, sessions, totals: { workspaces: workspaces.length, sessions: totalCount, totalBytes } }\n}\n\n/** 标记活跃会话(live id 与目录段名双向匹配,兼容编码差异)。 */\nexport function markActiveSessions(sessions: PerfSession[], activeIds: Iterable<string>): void {\n const raw = new Set(activeIds)\n const encoded = new Set<string>()\n for (const id of raw) encoded.add(sessionIdSegment(id))\n for (const s of sessions) {\n if (raw.has(s.sessionId) || encoded.has(s.sessionId)) s.active = true\n }\n}\n\n/**\n * 移出规划(纯函数):从盘点中按「显式集合」或「规则(minBytes / olderThanDays)」\n * 圈选可移出会话。活跃会话一律排除;无显式集合且无规则时不选(防误移)。\n * @author ddj 2026年09月02号\n * @param inventory 盘点结果\n * @param criteria 圈选条件\n * @returns 待移出清单与释放字节\n */\nexport function planMoveOut(inventory: SessionInventory, criteria: MoveCriteria): { items: PerfMoveItem[]; reclaimedBytes: number } {\n const items: PerfMoveItem[] = []\n const explicit = Array.isArray(criteria.sessionIds) && criteria.sessionIds.length > 0\n const cutoff = criteria.olderThanDays ? Date.now() - criteria.olderThanDays * 24 * 60 * 60 * 1000 : 0\n for (const s of inventory.sessions) {\n if (s.active) continue\n if (criteria.workspaceKey && s.workspaceKey !== criteria.workspaceKey) continue\n if (explicit) {\n if (!criteria.sessionIds!.includes(s.sessionId)) continue\n } else {\n if (criteria.minBytes && s.bytes < criteria.minBytes) continue\n if (criteria.olderThanDays && s.mtime > cutoff) continue\n if (!criteria.minBytes && !criteria.olderThanDays) continue\n }\n items.push({ workspaceKey: s.workspaceKey, sessionId: s.sessionId, bytes: s.bytes })\n }\n return { items, reclaimedBytes: items.reduce((sum, i) => sum + i.bytes, 0) }\n}\n\n/** 移出执行结果。 */\nexport interface MoveOutResult {\n moved: PerfMoveItem[]\n failures: PerfMoveFailure[]\n reclaimedBytes: number\n}\n\n/**\n * 移出会话目录到归档区(同卷 rename,可逆)。活跃会话拒绝;路径越界拒绝;\n * 逐项 best-effort,成功项写归档 manifest。默认不 dry-run(dryRun 时只校验不搬迁)。\n * @author ddj 2026年09月02号\n * @param home DSH home\n * @param archive 归档根\n * @param items 待移出清单(来自 planMoveOut 或用户确认)\n * @param activeIds 活跃会话 id 集合(执行期再校验一次)\n * @param dryRun 仅校验不搬迁\n */\nexport async function moveOutSessions(home: string, archive: string, items: PerfMoveItem[], activeIds: Iterable<string>, dryRun = false): Promise<MoveOutResult> {\n const root = sessionsRoot(home)\n const rawActive = new Set(activeIds)\n const encodedActive = new Set<string>()\n for (const id of rawActive) encodedActive.add(sessionIdSegment(id))\n const isActive = (id: string): boolean => rawActive.has(id) || encodedActive.has(id)\n const moved: PerfMoveItem[] = []\n const failures: PerfMoveFailure[] = []\n for (const item of items) {\n if (!validDirName(item.workspaceKey)) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '工作区键不合法' })\n continue\n }\n if (isActive(item.sessionId)) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '活跃会话,拒绝移出' })\n continue\n }\n const seg = sessionIdSegment(item.sessionId)\n const src = join(root, item.workspaceKey, seg)\n const dst = join(archive, item.workspaceKey, seg)\n if (!withinDir(src, root) || !withinDir(dst, archive)) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '路径越界,拒绝执行' })\n continue\n }\n if (dryRun) {\n try {\n const info = await stat(src)\n if (info.isDirectory()) moved.push({ ...item, bytes: (await statSessionLog(src))?.size ?? item.bytes })\n else failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '源目录不存在' })\n } catch (error) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '源目录不存在' })\n }\n continue\n }\n try {\n await mkdir(dirname(dst), { recursive: true })\n await rename(src, dst)\n const bytes = (await statSessionLog(dst))?.size ?? item.bytes\n moved.push({ ...item, bytes })\n } catch (error) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: String(error) })\n }\n }\n if (moved.length && !dryRun) await appendMoveManifest(archive, moved)\n return { moved, failures, reclaimedBytes: moved.reduce((sum, i) => sum + i.bytes, 0) }\n}\n\n/** 恢复单个会话:归档 → sessions。目标已存在则拒绝(不覆盖)。 */\nexport async function restoreSession(home: string, archive: string, workspaceKey: string, sessionId: string): Promise<{ ok: boolean; error?: string }> {\n if (!validDirName(workspaceKey)) return { ok: false, error: '工作区键不合法' }\n const seg = sessionIdSegment(sessionId)\n const root = sessionsRoot(home)\n const src = join(archive, workspaceKey, seg)\n const dst = join(root, workspaceKey, seg)\n if (!withinDir(src, archive) || !withinDir(dst, root)) return { ok: false, error: '路径越界,拒绝执行' }\n try {\n await stat(src)\n } catch (error) {\n return { ok: false, error: '归档中不存在该会话' }\n }\n try {\n await stat(dst)\n return { ok: false, error: '目标位置已存在同名会话' }\n } catch (error) { /* 目标不存在,可恢复 */ }\n try {\n await mkdir(dirname(dst), { recursive: true })\n await rename(src, dst)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n}\n\n/** 清除归档区早于 N 天的会话(破坏性,仅限归档区)。 */\nexport async function purgeArchive(archive: string, olderThanDays: number): Promise<{ removed: number; reclaimedBytes: number }> {\n const cutoff = Date.now() - olderThanDays * 24 * 60 * 60 * 1000\n let removed = 0\n let reclaimedBytes = 0\n const wsDirs = await readdir(archive, { withFileTypes: true }).catch(() => [])\n for (const ws of wsDirs) {\n if (!ws.isDirectory()) continue\n const wsDir = join(archive, ws.name)\n const sessionDirs = await readdir(wsDir, { withFileTypes: true }).catch(() => [])\n for (const sd of sessionDirs) {\n if (!sd.isDirectory()) continue\n const info = await statSessionLog(join(wsDir, sd.name))\n if (!info || info.mtimeMs > cutoff) continue\n try {\n await rm(join(wsDir, sd.name), { recursive: true, force: true })\n removed += 1\n reclaimedBytes += info.size\n } catch (error) { /* 删除失败跳过 */ }\n }\n }\n return { removed, reclaimedBytes }\n}\n\n/** 当前会话持久化体积(对话头部指示器用):仅 stat,近零成本。 */\nexport async function sessionSizeOf(home: string, cwd: string, sessionId: string): Promise<{ bytes: number; exists: boolean }> {\n const dir = join(sessionsRoot(home), sessionWorkspaceKey(cwd), sessionIdSegment(sessionId))\n for (const name of LOG_NAMES) {\n try {\n const info = await stat(join(dir, name))\n if (info.isFile()) return { bytes: info.size, exists: true }\n } catch (error) { /* 尝试下一个日志名 */ }\n }\n return { bytes: 0, exists: false }\n}\n\n/**\n * 侧车摘要:返回活跃记录数、每文件 pending 计数、归档体积。\n * agent/脚本取关键字段即可,不必整份读 .dsh-edit-review.json(避免大对象进对话)。\n * @author ddj 2026年09月02号\n * @param ctx DSH host 上下文(fs 服务)\n * @param cwd 工作区路径(null 时返回空摘要)\n */\nexport async function sidecarSummaryOf(ctx: Ctx, cwd: string | null): Promise<SidecarPerfSummary> {\n const fs = ctx.get('fs')\n const summary: SidecarPerfSummary = { active: 0, pendingByFile: [], archiveBytes: 0 }\n if (!fs || !cwd) return summary\n try {\n const text = await fs.readText(await fs.resolve(SIDECAR, { cwd }))\n const data = parseSidecar(text)\n const recs = data?.workspaces?.[cwd]?.records\n if (recs) {\n const byFile = new Map<string, number>()\n let active = 0\n for (const rec of Object.values(recs)) {\n if (rec.archived) continue\n active += 1\n const sm = recSummary(rec)\n if (sm.pending > 0 && rec.path) byFile.set(rec.path, (byFile.get(rec.path) ?? 0) + sm.pending)\n }\n summary.active = active\n summary.pendingByFile = [...byFile.entries()].map(([path, pending]) => ({ path, pending })).sort((a, b) => b.pending - a.pending)\n }\n try {\n const info = await fs.stat(await fs.resolve(SIDECAR_ARCHIVE, { cwd }))\n summary.archiveBytes = info?.size ?? 0\n } catch (error) { /* 归档缺失忽略 */ }\n } catch (error) { /* sidecar 不可读返回空摘要 */ }\n return summary\n}\n\n/** 归档 manifest 条目。 */\ninterface MoveManifestEntry { at: string; workspaceKey: string; sessionId: string }\n\n/** 归档 manifest(可逆移出的索引,供恢复/审计)。 */\ninterface MoveManifest { version: 1; items: MoveManifestEntry[] }\n\n/** 解析归档 manifest(损坏/缺失 → 空)。 */\nfunction parseMoveManifest(text: string | null): MoveManifest {\n if (!text) return { version: 1, items: [] }\n try {\n const data = JSON.parse(text) as MoveManifest\n return { version: 1, items: Array.isArray(data.items) ? data.items : [] }\n } catch (error) {\n return { version: 1, items: [] }\n }\n}\n\n/** 追加移出记录到归档 manifest(best-effort,失败不影响主流程)。 */\nasync function appendMoveManifest(archive: string, items: PerfMoveItem[]): Promise<void> {\n try {\n const file = join(archive, '.manifest.json')\n const prev = parseMoveManifest(await readFile(file, 'utf8').catch(() => null))\n const at = new Date().toISOString()\n for (const item of items) prev.items.push({ at, workspaceKey: item.workspaceKey, sessionId: item.sessionId })\n await mkdir(archive, { recursive: true })\n await writeFile(file, JSON.stringify(prev, null, 2), 'utf8')\n } catch (error) { /* manifest 写失败静默 */ }\n}\n","/**\n * dsh-vscode-mode host — profile patch 压缩调优(文本行级,零 YAML 依赖)。\n * 在 ~/.dsh/profiles/<profile>/cordis.patch.yml 末尾追加/移除一段带标记注释的\n * id 定向覆盖块(compaction-basic / tool-result-pruner 更低阈值)。\n * 纯文本函数可单测:幂等追加、整段移除、无块原样返回。\n * 作者 ddj 2026-09-02\n */\n\n/** 性能块起始标记注释(文件内唯一锚点)。 */\nexport const PERF_MARK_START = '# dsh-vscode-mode perf tuning (start)'\n/** 性能块结束标记注释。 */\nexport const PERF_MARK_END = '# dsh-vscode-mode perf tuning (end)'\n\n/**\n * 建议的压缩调优 YAML 块(顶层 loader patch 条目,id 定向覆盖)。\n * - compaction-basic:thresholdRatio 0.8→0.6、retainRatio 0.16→0.12(更早触发压缩);\n * - tool-result-pruner:thresholdChars 8192→4096、head/tail 同步收窄(大 tool result 提前截断)。\n * 注意:压缩只降低模型可见上下文压力,不重写已持久化会话日志(append-only)。\n * @author ddj 2026年09月02号\n * @returns 带前后标记注释与尾换行的 YAML 块\n */\nexport function perfConfigBlock(): string {\n return [\n PERF_MARK_START,\n '# 更早触发会话内压缩:降低模型可见上下文压力(仅影响后续轮次,不缩小已持久化日志)。',\n '- id: compaction-basic',\n ' config:',\n ' thresholdRatio: 0.6',\n ' retainRatio: 0.12',\n '- id: tool-result-pruner',\n ' config:',\n ' thresholdChars: 4096',\n ' headChars: 2048',\n ' tailChars: 512',\n PERF_MARK_END,\n '',\n ].join('\\n')\n}\n\n/** 当前文本是否已包含性能块。 */\nexport function patchHasPerfConfig(text: string): boolean {\n return text.includes(PERF_MARK_START)\n}\n\n/**\n * 移除性能块(起止标记注释之间的整段,含所在行),无块时原样返回。\n * 移除后压缩多余空行、确保以单个换行结尾。\n * @author ddj 2026年09月02号\n * @param text 原 patch 文本\n * @returns 移除后的文本\n */\nexport function patchRemovePerfConfig(text: string): string {\n const start = text.indexOf(PERF_MARK_START)\n if (start === -1) return text\n const end = text.indexOf(PERF_MARK_END, start)\n const lineStart = text.lastIndexOf('\\n', start - 1) + 1\n if (end === -1) return text.slice(0, lineStart).replace(/\\n+$/, '\\n')\n const after = (() => {\n const nl = text.indexOf('\\n', end)\n return nl === -1 ? text.length : nl + 1\n })()\n const removed = (text.slice(0, lineStart) + text.slice(after)).replace(/\\n{3,}/g, '\\n\\n')\n return removed.replace(/\\n+$/, '\\n')\n}\n\n/**\n * 幂等追加性能块:已有块先整段移除再追加到文件末尾(保证全文件只有一份、位置固定)。\n * @author ddj 2026年09月02号\n * @param text 原 patch 文本\n * @returns 追加后的文本\n */\nexport function patchInsertPerfConfig(text: string): string {\n const base = patchRemovePerfConfig(text)\n const trimmed = base.replace(/\\n+$/, '')\n return trimmed + '\\n' + perfConfigBlock()\n}\n","/**\n * dsh-vscode-mode host — RPC 分发:类型化方法表替代巨型 switch。\n * 迁移自原 src/index.ts 的 handleRpc,方法名/载荷/错误文案一字不改。\n * 新功能 = shared/rpc.ts 加方法 + 这里加一个 handler,不改其他模块。\n * 作者 ddj 2026-08-20\n */\nimport type { DecideItem, DecideResult, RpcHandlerMap, RpcMethod, RpcRequestMap, RpcResult, RpcScope } from './shared/rpc.js'\nimport { binaryMimeOf } from './shared/rpc.js'\nimport type { DiffRecord, RecordView } from './shared/types.js'\nimport type { Ctx, Session } from './store.js'\nimport {\n BINARY_READ_CAP,\n READ_CAP,\n appendArchiveEntries,\n archiveRecords,\n autoArchiveStale,\n parseArchive,\n policyOf,\n readArchiveText,\n resolveTarget,\n saveBucket,\n} from './store.js'\nimport { mkdir, readFile, rm, writeFile, readdir } from 'node:fs/promises'\nimport { basename, join } from 'node:path'\nimport { archiveEntryFor, markDecision, recordResolved, reconstructOriginal } from './model.js'\nimport type { Registry } from './registry.js'\nimport { bucketOf, cwdOf, sessionOf } from './registry.js'\nimport type { SearchOrchestrator } from './search/orchestrator.js'\nimport { newSearcher } from './search/orchestrator.js'\nimport type { ContentSearcher } from './search/content.js'\nimport { newContentSearcher } from './search/content.js'\nimport { restoreFile, revertCall, revertHunk } from './revert.js'\nimport { rulesList, rulesRead, rulesRemove, rulesSave, rulesToggle } from './rules.js'\nimport { listMcp, refreshMcp, removeMcp, saveMcp, toggleMcp } from './mcp.js'\nimport { listProjects, projectRefresh, projectRemove, projectSave, projectToggle } from './mcpProject.js'\nimport { normalizeFileOpenTool, FILE_OPEN_DEFAULT, FILE_OPEN_SETTINGS_NS } from './fileOpenSettings.js'\nimport { INTEGRATION_BASE_DEFAULT } from './shared/integration.js'\nimport { shellMenuRegister, shellMenuRemove, shellMenuStatus } from './integrate.js'\nimport { unityAdd, unityInstall, unityList, unityRemove } from './unityBridge.js'\nimport { handoffOpen, pendingState, pollPending } from './externalHandoff.js'\nimport { buildReport } from './compat.js'\nimport { findProfileDir, readDevForm, setDevForm } from './devForm.js'\nimport { normalizeRel } from './tree.js'\nimport { invalidateIndex, listDirCached } from './treeIndex.js'\nimport { revealInExplorer } from './reveal.js'\nimport { dshHome } from './paths.js'\nimport { debugRecord } from './debugLog.js'\nimport { markActiveSessions, moveOutSessions, planMoveOut, purgeArchive, restoreSession, scanSessionInventory, sessionsArchiveRoot, sessionSizeOf, sidecarSummaryOf } from './perf.js'\nimport { patchHasPerfConfig, patchInsertPerfConfig, patchRemovePerfConfig, perfConfigBlock } from './perfPatch.js'\n\n/** cwd → 上次 stale 自动清理时间:全量轮询(EditorView/DiffBadge/Dock 各自 5s)节流,避免每轮都读文件算指纹。 */\nconst staleCheckedAt = new Map<string, number>()\n/** stale 自动清理最小间隔。 */\nconst STALE_CHECK_MIN_MS = 10_000\n\n/** 记录 → 客户端视图(不含 before 全文,仅长度)。 */\nfunction recView(record: DiffRecord): RecordView {\n return {\n callId: record.callId,\n toolName: record.toolName,\n path: record.path,\n beforeLen: typeof record.before === 'string' ? record.before.length : 0,\n create: record.create === true,\n callHunk: record.callHunk,\n hunks: record.hunks,\n decisions: record.decisions,\n note: record.note ?? null,\n superseded: record.superseded === true,\n after: record.after ?? null,\n baseFingerprint: record.baseFingerprint ?? null,\n afterFingerprint: record.afterFingerprint ?? null,\n conflict: record.conflict === true,\n legacy: record.legacy === true,\n at: record.at,\n }\n}\n\n/** 会话/工作区公共前置:返回 {session,cwd} 或错误文案。 */\nasync function requireSession(ctx: Ctx, sessionId: string | undefined): Promise<\n { session: Session; cwd: string } | { err: string }\n> {\n const session = sessionOf(ctx, sessionId)\n if (!session) return { err: '会话不存在' }\n const cwd = cwdOf(session)\n if (!cwd) return { err: '会话无工作区' }\n return { session, cwd }\n}\n\n/**\n * 手动保存收尾(edrv.save / edrv.saveBinary 共用):目录树失效 + 该路径 pending\n * 文本差异记录标记 superseded 并归档(旧文本 diff 不得再应用到新内容上)。\n * @author ddj 2026年09月22号\n * @param ctx DSH 上下文\n * @param registry 差异记录桶注册表\n * @param sc requireSession 成功结果(session + cwd)\n * @param path 保存的文件路径\n */\nasync function afterManualSave(\n ctx: Ctx,\n registry: Registry,\n sc: { session: Session; cwd: string },\n path: string,\n): Promise<void> {\n // 手动保存后目录树可能变化(新建/删除文件):父目录+祖先进失效,后台自愈。\n invalidateIndex(ctx, sc.cwd, path)\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n let changed = false\n for (const rec of bucket.values()) {\n if (rec.path === path && rec.superseded !== true) { rec.superseded = true; rec.at = new Date().toISOString(); changed = true }\n }\n if (changed) {\n const done: DiffRecord[] = []\n for (const rec of bucket.values()) if (rec.path === path && rec.superseded) done.push(rec)\n if (done.length) await archiveRecords(ctx, sc.session, sc.cwd, bucket, done, '被手动编辑覆盖')\n else await saveBucket(ctx, sc.cwd, bucket, sc.session)\n }\n}\n\n/**\n * 批量决策核心:一次会话/桶解析 + 逐项处理 + 统一落盘(accept/reject 单条与 decideBatch 共用)。\n * rejected 项先做回滚,失败记入该项 error 且不改决策;本批次新增\"已解决\"记录一次性归档,\n * 有任何成功项则整桶只写盘一次,避免逐条读写整个 sidecar。\n * @author ddj 2026年08月25号\n * @param items 决策项(按数组顺序处理,rejected 的先后即回滚顺序)\n * @returns 逐项结果(ok 项含更新后的记录视图)\n */\nasync function applyDecisions(\n ctx: Ctx,\n session: Session,\n cwd: string,\n bucket: Map<string, DiffRecord>,\n items: DecideItem[],\n): Promise<DecideResult[]> {\n const results: DecideResult[] = []\n const resolved: DiffRecord[] = []\n let changed = false\n for (const item of items) {\n const record = bucket.get(item.callId)\n if (!record) {\n results.push({ callId: item.callId, ok: false, error: '记录不存在' })\n continue\n }\n if (item.decision === 'rejected') {\n const scope: RpcScope = item.scope ?? 'call'\n const outcome = scope === 'hunk' ? await revertHunk(ctx, session, record, item.hunkIndex ?? -1) : await revertCall(ctx, session, record)\n if (!outcome.ok) {\n results.push({ callId: item.callId, ok: false, error: outcome.error })\n continue\n }\n }\n const wasResolved = recordResolved(record)\n markDecision(record, item.scope ?? 'call', item.hunkIndex, item.decision)\n changed = true\n if (!wasResolved && recordResolved(record)) resolved.push(record)\n results.push({ callId: item.callId, ok: true, record: recView(record) })\n }\n if (resolved.length) {\n const reason = items.some((item) => item.decision === 'rejected') ? '已处理(回滚)' : '已处理'\n await archiveRecords(ctx, session, cwd, bucket, resolved, reason, { deferSave: true })\n }\n if (changed) await saveBucket(ctx, cwd, bucket, session)\n return results\n}\n\n/** 当前活跃会话 id 集合(live sessions,用于移出/恢复护栏)。 */\nfunction activeSessionIds(ctx: Ctx): Set<string> {\n const sessions = ctx.get('sessions')\n if (!sessions || typeof sessions.list !== 'function') return new Set()\n return new Set((sessions.list() as Session[]).map((s) => s.id).filter(Boolean))\n}\n\n/** profile patch 文件定位(依赖本插件的 profile,同 devForm)。 */\nasync function patchFileInfo(): Promise<{ profileDir?: string; patchPath?: string }> {\n const profileDir = findProfileDir()\n if (!profileDir) return {}\n return { profileDir, patchPath: join(profileDir, 'cordis.patch.yml') }\n}\n\n/** 最新一次压缩配置备份文件名(cordis.patch.yml.bak-<ts>,按名倒序取新)。 */\nasync function latestPatchBackup(patchPath: string): Promise<string | undefined> {\n const dir = join(patchPath, '..')\n const base = basename(patchPath)\n const names = await readdir(dir).catch(() => [])\n return names.filter((n) => n.startsWith(base + '.bak-')).sort().reverse()[0]\n}\n\n/** 读取设置中的深链基址(缺省/非法回退默认 3080)。 */\nasync function integrationBaseUrlOf(ctx: Ctx): Promise<string> {\n const settings = ctx.get('settings')\n const descriptor = settings?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const value = descriptor?.value as { integrationBaseUrl?: unknown } | undefined\n const raw = typeof value?.integrationBaseUrl === 'string' ? value.integrationBaseUrl.trim() : ''\n return raw || INTEGRATION_BASE_DEFAULT\n}\n\n/** 各方法 handler 表(类型由 shared/rpc 的 RpcHandlerMap 约束)。 */\nexport function buildHandlers(\n ctx: Ctx,\n registry: Registry,\n searcher = newSearcher(ctx),\n contentSearcher = newContentSearcher(ctx),\n lspHandlers?: Partial<RpcHandlerMap>,\n aiHandlers?: Partial<RpcHandlerMap>,\n): RpcHandlerMap {\n return {\n // edrv.lsp.* 由 createLspRpc 一次性提供(tracker 跨请求保留),这里并入。\n ...((lspHandlers ?? {}) as RpcHandlerMap),\n // edrv.ai.* 由 createAiRpc 提供(AI 内联补全/模型目录/配置读写),这里并入。\n ...((aiHandlers ?? {}) as RpcHandlerMap),\n 'edrv.list': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const want = Array.isArray(args.callIds) ? new Set(args.callIds) : null\n // 全量轮询时自动清理 stale 幽灵差异(批量决策后的即时刷新可 skipStale 跳过);\n // 三个组件各自 5s 全量 list,stale 检查节流到 STALE_CHECK_MIN_MS 一次,\n // 避免每轮都对全部记录读文件 + 算指纹(keepall 期间多组件同时刷新的主要 host 开销)。\n if (!want && args.skipStale !== true) {\n const now = Date.now()\n if (now - (staleCheckedAt.get(sc.cwd) ?? 0) > STALE_CHECK_MIN_MS) {\n staleCheckedAt.set(sc.cwd, now)\n await autoArchiveStale(ctx, sc.session, sc.cwd, bucket)\n }\n }\n const out: RecordView[] = []\n for (const rec of bucket.values()) {\n // 面板全量查询过滤已归档;聊天条按 callId 查询保留(状态徽章仍需正确显示)\n if (!want && rec.archived) continue\n if (want && !want.has(rec.callId)) continue\n out.push(recView(rec))\n }\n out.sort((a, b) => (a.at < b.at ? -1 : 1))\n return { ok: true, records: out }\n },\n 'edrv.accept': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const results = await applyDecisions(ctx, sc.session, sc.cwd, bucket, [{ callId: args.callId, scope: args.scope, hunkIndex: args.hunkIndex, decision: 'accepted' }])\n const item = results[0]\n if (!item?.ok) return { ok: false, error: item?.error ?? '操作失败' }\n return { ok: true, record: item.record! }\n },\n 'edrv.reject': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const results = await applyDecisions(ctx, sc.session, sc.cwd, bucket, [{ callId: args.callId, scope: args.scope, hunkIndex: args.hunkIndex, decision: 'rejected' }])\n const item = results[0]\n if (!item?.ok) return { ok: false, error: item?.error ?? '操作失败' }\n return { ok: true, record: item.record! }\n },\n 'edrv.decideBatch': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const results = await applyDecisions(ctx, sc.session, sc.cwd, bucket, Array.isArray(args.items) ? args.items : [])\n return { ok: true, results }\n },\n 'edrv.read': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await resolveTarget(ctx, sc.session, args.path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') {\n // 带上解析后的真实路径:跳转失败时可直接看出是路径解析错还是目标本身不存在\n return { ok: false, error: '文件不存在', resolvedPath: fs.processPath(target) }\n }\n if ((info.size ?? 0) > BINARY_READ_CAP) return { ok: false, error: '文件过大(>32MB),不支持整文件预览' }\n if (args.encoding === 'base64') {\n // 图片/PDF 等二进制预览:readBytes 无解码、无二进制拒绝;超上限已由上方 stat 拦截\n const bytes = await fs.readBytes(target, undefined, BINARY_READ_CAP)\n const content = Buffer.from(bytes).toString('base64')\n return { ok: true, content, size: bytes.byteLength, encoding: 'base64', mime: binaryMimeOf(args.path) }\n }\n if ((info.size ?? 0) > READ_CAP) return { ok: false, error: '文件过大(>8MB),不支持整文件预览' }\n const content = await fs.readText(target)\n return { ok: true, content, size: content.length }\n } catch (error) {\n return { ok: false, error: '读取失败:' + String(error) }\n }\n },\n 'edrv.original': async (args) => {\n // 重建\"本批次修改前\"内容:DiffEditor 原始侧。仅反解 pending 块;\n // 全部反解失败时回退到最早记录的整体 before(若存在)。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await resolveTarget(ctx, sc.session, args.path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') return { ok: false, error: '文件不存在' }\n if ((info.size ?? 0) > READ_CAP) return { ok: false, error: '文件过大(>8MB),不支持差异重建' }\n const content = await fs.readText(target)\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const records = [...bucket.values()].filter((r) => r.path === args.path && !r.archived).sort((a, b) => (a.at < b.at ? -1 : 1))\n if (!records.length) return { ok: true, content, size: content.length, stale: [], fallback: false }\n const rebuilt = reconstructOriginal(records, content)\n if (rebuilt.stale.length && records[0].before !== null) {\n return { ok: true, content: records[0].before, size: records[0].before.length, stale: rebuilt.stale, fallback: true }\n }\n return { ok: true, content: rebuilt.content, size: rebuilt.content.length, stale: rebuilt.stale, fallback: false }\n } catch (error) {\n return { ok: false, error: '重建失败:' + String(error) }\n }\n },\n 'edrv.save': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await resolveTarget(ctx, sc.session, args.path)\n await fs.writeText(target, args.content, void 0, void 0, policyOf(ctx, sc.session))\n await afterManualSave(ctx, registry, sc, args.path)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '保存失败:' + String(error) }\n }\n },\n 'edrv.saveBinary': async (args) => {\n if (args.encoding !== 'base64') return { ok: false, error: '仅支持 base64 编码' }\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await resolveTarget(ctx, sc.session, args.path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') return { ok: false, error: '文件不存在' }\n // fs 服务仅提供文本写(writeText/editText),二进制回写经 node:fs 直写解析后的\n // 真实路径;以工作区边界 + 大小上限 + 用户显式保存动作三重约束兜底(对齐\n // revert.ts deleteCreated 的 contains 用法)。\n const rootTarget = await fs.resolve(policyOf(ctx, sc.session)?.workspaceRoot ?? '.', {})\n if (!fs.contains(rootTarget, target)) return { ok: false, error: '拒绝保存:目标不在会话工作区内' }\n const bytes = Buffer.from(args.content, 'base64')\n if (bytes.byteLength === 0) return { ok: false, error: '内容为空,拒绝写回' }\n if (bytes.byteLength > BINARY_READ_CAP) return { ok: false, error: '内容过大(>32MB),拒绝写回' }\n await writeFile(fs.processPath(target), bytes)\n await afterManualSave(ctx, registry, sc, args.path)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '二进制保存失败:' + String(error) }\n }\n },\n 'edrv.archiveList': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const batches = parseArchive(await readArchiveText(ctx, sc.cwd)).filter((b) => b.cwd === sc.cwd)\n const entries = batches.map((b) => {\n const recs = Array.isArray(b.records) ? b.records : []\n const sum = recs.reduce((s, r) => {\n const sm = r.summary || { accepted: 0, rejected: 0, pending: 0, superseded: false }\n s.accepted += sm.accepted || 0\n s.rejected += sm.rejected || 0\n s.pending += sm.pending || 0\n if (sm.superseded) s.superseded++\n return s\n }, { accepted: 0, rejected: 0, pending: 0, superseded: 0 })\n return { at: b.at, lastAt: b.lastAt || b.at, path: b.path, batch: b.batch ?? null, reason: b.reason ?? null, nRecords: recs.length, summary: sum }\n })\n entries.sort((a, b) => (Number(b.batch ?? -1) - Number(a.batch ?? -1)) || (a.at < b.at ? 1 : -1))\n return { ok: true, entries }\n },\n 'edrv.archiveRead': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const batchPath = args.path\n const batches = parseArchive(await readArchiveText(ctx, sc.cwd)).filter((b) => b.cwd === sc.cwd && (!batchPath || b.path === batchPath))\n return { ok: true, batches }\n },\n 'edrv.rollback': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n const batch = args.batch\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n let affected: DiffRecord[] = []\n let beforeRec: DiffRecord | null = null\n if (batch !== undefined) {\n const all = parseArchive(await readArchiveText(ctx, sc.cwd)).filter((b) => b.cwd === sc.cwd && b.path === args.path)\n const recs: DiffRecord[] = []\n for (const b of all) if (b.batch === batch) for (const r of (b.records || [])) recs.push(r as unknown as DiffRecord)\n if (!recs.length) return { ok: false, error: '归档中找不到该批次' }\n recs.sort((a, b2) => (a.at < b2.at ? -1 : 1))\n beforeRec = recs[0]\n affected = recs\n } else {\n for (const r of bucket.values()) if (r.path === args.path && !r.archived) affected.push(r)\n if (!affected.length) return { ok: false, error: '该文件没有可回滚的差异' }\n affected.sort((a, b2) => (a.at < b2.at ? -1 : 1))\n beforeRec = affected[0]\n }\n const rerr = await restoreFile(ctx, sc.session, beforeRec)\n if (rerr) return { ok: false, error: rerr }\n if (batch === undefined) {\n await archiveRecords(ctx, sc.session, sc.cwd, bucket, affected, '已回滚')\n } else {\n const all = parseArchive(await readArchiveText(ctx, sc.cwd)).filter((b) => b.cwd === sc.cwd && b.path === args.path && b.batch === batch)\n const sumRecs = all.reduce((s, b) => s + ((b.records || []).length), 0)\n const logRec = Object.assign({}, affected[0], { note: (affected[0].note ? affected[0].note + ';' : '') + '回滚至本批次前(批次 ' + batch + ')' })\n await appendArchiveEntries(ctx, sc.cwd, [archiveEntryFor([logRec], sc.cwd, '已回滚(批次 ' + batch + ',' + sumRecs + ' 条)')], sc.session)\n // 批次回滚恢复的是旧内容,文件当前活跃差异已失效,一并归档\n const activeRecs: DiffRecord[] = []\n for (const r of bucket.values()) if (r.path === args.path && !r.archived) activeRecs.push(r)\n if (activeRecs.length) await archiveRecords(ctx, sc.session, sc.cwd, bucket, activeRecs, '已回滚(批次回滚覆盖)')\n }\n return { ok: true, path: args.path, batch: batch ?? null }\n },\n 'edrv.debug': async (args) => {\n // 诊断日志:client 上报 → debugLog 模块缓冲批量落盘 ~/.dsh/dsh-vscode-mode/logs/\n // (console 不一定落盘,文件可靠)。只出现在调试开关开启时(client dbg 默认关)。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n debugRecord(ctx, sc.cwd, String(args.text ?? ''))\n return { ok: true }\n },\n 'edrv.searchFiles': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const activePaths: string[] = []\n for (const record of bucket.values()) if (record.path) activePaths.push(record.path)\n const result = await searcher.search({ session: sc.session, cwd: sc.cwd, query: args.query, activePaths })\n return { ok: true, ...result }\n },\n 'edrv.searchContent': async (args) => {\n // 工作区内容搜索:rg --json 主路径;provider 失败转错误响应(无 fallback)。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const result = await contentSearcher.search({\n session: sc.session,\n cwd: sc.cwd,\n query: args.query,\n matchCase: args.matchCase,\n wholeWord: args.wholeWord,\n regex: args.regex,\n maxResults: args.maxResults,\n include: args.include,\n exclude: args.exclude,\n })\n return { ok: true, ...result }\n } catch (error) {\n return { ok: false, error: '搜索失败:' + String(error) }\n }\n },\n 'edrv.listDir': async (args) => {\n // 目录树(侧边栏文件管理用):树索引命中直出(内存,0 IO);失效/force 时\n // 走快路径(resolve + listDirCheap + putIndex);同路径在途请求去重复用。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const rel = normalizeRel(args.path)\n if (rel === null) return { ok: false, error: '路径不合法' }\n const res = await listDirCached(ctx, sc.cwd, rel, args.force === true)\n if ('error' in res) return { ok: false, error: res.error }\n return { ok: true, root: res.root, path: rel, entries: res.entries }\n },\n 'edrv.revealInExplorer': async (args) => {\n // 在 OS 文件浏览器中打开/定位路径(树行/编辑器右键菜单用),相对工作区解析。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const rel = normalizeRel(args.path)\n if (rel === null) return { ok: false, error: '路径不合法' }\n const target = await fs.resolve(rel || '.', { cwd: sc.cwd })\n const info = await fs.stat(target)\n if (!info) return { ok: false, error: '路径不存在' }\n const abs = fs.processPath(target)\n const outcome = await revealInExplorer(ctx, abs, info.type === 'directory')\n if (!outcome.ok) return { ok: false, error: outcome.error }\n return { ok: true, revealed: abs }\n } catch (error) {\n return { ok: false, error: '打开失败:' + String(error) }\n }\n },\n 'mcp.list': async () => ({ ok: true, ...listMcp(ctx) }),\n 'mcp.save': async (args) => {\n try { return { ok: true, server: await saveMcp(ctx, args.config) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.remove': async (args) => {\n try { await removeMcp(ctx, args.id); return { ok: true } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.toggle': async (args) => {\n try { return { ok: true, server: await toggleMcp(ctx, args.id, args.enabled) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.refresh': async (args) => {\n try { return { ok: true, server: await refreshMcp(ctx, args.id) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projects': async () => {\n try { return { ok: true, ...await listProjects(ctx) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projectSave': async (args) => {\n try { return { ok: true, project: await projectSave(ctx, args.workspacePath, args.serverName, args.config) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projectRemove': async (args) => {\n try { return { ok: true, project: await projectRemove(ctx, args.workspacePath, args.serverName) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projectToggle': async (args) => {\n try { return { ok: true, project: await projectToggle(ctx, args.workspacePath, args.serverName, args.enabled) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projectRefresh': async (args) => {\n try { return { ok: true, project: await projectRefresh(ctx, args.workspacePath, args.serverName) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'vscode.fileOpenSettingsGet': async () => {\n const settings = ctx.get('settings')\n const descriptor = settings?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const value = descriptor?.value as { fileOpenTool?: unknown } | undefined\n return { ok: true, fileOpenTool: normalizeFileOpenTool(value?.fileOpenTool ?? FILE_OPEN_DEFAULT), integrationBaseUrl: await integrationBaseUrlOf(ctx), revision: descriptor?.revision }\n },\n 'vscode.fileOpenSettingsUpdate': async (args) => {\n const settings = ctx.get('settings')\n if (!settings?.update) return { ok: false, error: '设置服务不可用' }\n try {\n const patch: Record<string, unknown> = { fileOpenTool: normalizeFileOpenTool(args.fileOpenTool) }\n if (typeof args.integrationBaseUrl === 'string' && args.integrationBaseUrl.trim()) patch.integrationBaseUrl = args.integrationBaseUrl.trim()\n await settings.update(FILE_OPEN_SETTINGS_NS, patch, args.expectedRevision)\n const descriptor = settings.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const value = descriptor?.value as { fileOpenTool?: unknown } | undefined\n return { ok: true, fileOpenTool: normalizeFileOpenTool(value?.fileOpenTool), integrationBaseUrl: await integrationBaseUrlOf(ctx), revision: descriptor?.revision }\n } catch (error) { return { ok: false, error: String(error) }\n }\n },\n 'compat': async () => ({ ok: true, report: await buildReport(ctx) }),\n 'vscode.devFormGet': async () => ({ ok: true, devForm: readDevForm() }),\n 'vscode.devFormSet': async (args) => {\n try {\n const result = await setDevForm(ctx, args.enabled === true, args.path)\n if (!result.ok) return { ok: false, error: result.error ?? '切换开发形态失败' }\n return { ok: true, devForm: readDevForm(), restart: result.restart }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.integration.status': async () => {\n try {\n return { ok: true, ...(await shellMenuStatus(ctx, await integrationBaseUrlOf(ctx))) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.integration.register': async () => {\n try {\n return { ok: true, ...(await shellMenuRegister(ctx, await integrationBaseUrlOf(ctx))) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.integration.unregister': async () => {\n try {\n return { ok: true, ...(await shellMenuRemove(ctx, await integrationBaseUrlOf(ctx))) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.unity.list': async () => {\n try {\n return { ok: true, ...(await unityList()) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.unity.add': async (args) => {\n try {\n return { ok: true, project: await unityAdd(args.path) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.unity.remove': async (args) => {\n try {\n await unityRemove(args.path)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.unity.install': async (args) => {\n try {\n return { ok: true, project: await unityInstall(args.path) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.externalStat': async (args) => {\n // 深链判型(无会话依赖):绝对路径直过 resolve;缺失/其他类型归入 missing\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await fs.resolve(args.path)\n const info = await fs.stat(target)\n if (!info || info.type === 'other') return { ok: true, kind: 'missing' }\n return { ok: true, kind: info.type === 'directory' ? 'directory' : 'file' }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.external.handoff': async (args) => ({\n ok: true,\n ...handoffOpen({ paths: args.paths, line: args.line, column: args.column }),\n }),\n 'edrv.external.pending': async () => ({ ok: true, open: pollPending() }),\n 'edrv.external.pendingState': async (args) => ({\n ok: true,\n delivered: pendingState(args.token, args.take === true).delivered,\n }),\n 'edrv.perf.inventory': async () => {\n try {\n const home = dshHome()\n const inventory = await scanSessionInventory(home, sessionsArchiveRoot(home))\n const active = activeSessionIds(ctx)\n markActiveSessions(inventory.sessions, active)\n return { ok: true, ...inventory, activeIds: [...active] }\n } catch (error) {\n return { ok: false, error: '盘点失败:' + String(error) }\n }\n },\n 'edrv.perf.sessionSize': async (args) => {\n try {\n const size = await sessionSizeOf(dshHome(), args.cwd, args.sessionId ?? '')\n return { ok: true, ...size }\n } catch (error) {\n return { ok: false, error: '读取会话体积失败:' + String(error) }\n }\n },\n 'edrv.perf.movePlan': async (args) => {\n try {\n const home = dshHome()\n const inventory = await scanSessionInventory(home, sessionsArchiveRoot(home))\n markActiveSessions(inventory.sessions, activeSessionIds(ctx))\n const plan = planMoveOut(inventory, { workspaceKey: args.workspaceKey, sessionIds: args.sessionIds, minBytes: args.minBytes, olderThanDays: args.olderThanDays })\n return { ok: true, ...plan }\n } catch (error) {\n return { ok: false, error: '移出规划失败:' + String(error) }\n }\n },\n 'edrv.perf.moveOut': async (args) => {\n try {\n const home = dshHome()\n const items = (args.sessionIds ?? []).map((sessionId) => ({ workspaceKey: args.workspaceKey, sessionId, bytes: 0 }))\n const result = await moveOutSessions(home, sessionsArchiveRoot(home), items, activeSessionIds(ctx), args.dryRun === true)\n return { ok: true, ...result }\n } catch (error) {\n return { ok: false, error: '移出失败:' + String(error) }\n }\n },\n 'edrv.perf.restore': async (args) => {\n try {\n const result = await restoreSession(dshHome(), sessionsArchiveRoot(dshHome()), args.workspaceKey, args.sessionId)\n return result.ok ? { ok: true, restored: true } : { ok: false, error: result.error ?? '恢复失败' }\n } catch (error) {\n return { ok: false, error: '恢复失败:' + String(error) }\n }\n },\n 'edrv.perf.purgeArchive': async (args) => {\n try {\n const result = await purgeArchive(sessionsArchiveRoot(dshHome()), args.olderThanDays)\n return { ok: true, ...result }\n } catch (error) {\n return { ok: false, error: '清除失败:' + String(error) }\n }\n },\n 'edrv.perf.sidecarSummary': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n const cwd = 'err' in sc ? null : sc.cwd\n try {\n const summary = await sidecarSummaryOf(ctx, cwd)\n return { ok: true, ...summary }\n } catch (error) {\n return { ok: false, error: '读取侧车摘要失败:' + String(error) }\n }\n },\n 'edrv.perf.configGet': async () => {\n try {\n const { profileDir, patchPath } = await patchFileInfo()\n const block = perfConfigBlock()\n if (!patchPath) return { ok: true, applied: false, block }\n const text = await readFile(patchPath, 'utf8').catch(() => '')\n const backup = await latestPatchBackup(patchPath)\n return { ok: true, profileDir, patchPath, applied: patchHasPerfConfig(text), block, backup }\n } catch (error) {\n return { ok: false, error: '读取压缩配置失败:' + String(error) }\n }\n },\n 'edrv.perf.configApply': async () => {\n try {\n const { patchPath } = await patchFileInfo()\n if (!patchPath) return { ok: false, error: '未找到依赖本插件的 profile(检查 DSH_HOME/profiles)' }\n const text = await readFile(patchPath, 'utf8').catch(() => '')\n const backup = patchPath + '.bak-' + Date.now()\n if (text) await writeFile(backup, text, 'utf8')\n await mkdir(join(patchPath, '..'), { recursive: true })\n await writeFile(patchPath, patchInsertPerfConfig(text), 'utf8')\n return { ok: true, applied: true, backup, restart: true }\n } catch (error) {\n return { ok: false, error: '写入压缩配置失败:' + String(error) }\n }\n },\n 'edrv.perf.configUndo': async () => {\n try {\n const { patchPath } = await patchFileInfo()\n if (!patchPath) return { ok: false, error: '未找到依赖本插件的 profile(检查 DSH_HOME/profiles)' }\n const backup = await latestPatchBackup(patchPath)\n if (backup) {\n const backupPath = join(join(patchPath, '..'), backup)\n const saved = await readFile(backupPath, 'utf8').catch(() => null)\n if (saved !== null) {\n await writeFile(patchPath, saved, 'utf8')\n await rm(backupPath, { force: true }).catch(() => {})\n return { ok: true, restored: true, backup }\n }\n }\n const text = await readFile(patchPath, 'utf8').catch(() => '')\n if (!patchHasPerfConfig(text)) return { ok: false, error: '没有可撤销的压缩配置' }\n await writeFile(patchPath, patchRemovePerfConfig(text), 'utf8')\n return { ok: true, restored: true }\n } catch (error) {\n return { ok: false, error: '撤销压缩配置失败:' + String(error) }\n }\n },\n 'rules.list': async () => {\n try {\n return { ok: true, ...(await rulesList(ctx)) }\n } catch (error) {\n return { ok: false, error: '读取规则失败:' + String(error) }\n }\n },\n 'rules.read': async (args) => {\n try {\n return { ok: true, content: await rulesRead(ctx, args) }\n } catch (error) {\n return { ok: false, error: '读取规则失败:' + String(error) }\n }\n },\n 'rules.save': async (args) => {\n try {\n return { ok: true, rule: await rulesSave(ctx, args) }\n } catch (error) {\n return { ok: false, error: '保存规则失败:' + String(error) }\n }\n },\n 'rules.remove': async (args) => {\n try {\n await rulesRemove(ctx, args)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '删除规则失败:' + String(error) }\n }\n },\n 'rules.toggle': async (args) => {\n try {\n return { ok: true, rule: await rulesToggle(ctx, args, args.enabled === true) }\n } catch (error) {\n return { ok: false, error: '切换规则失败:' + String(error) }\n }\n },\n }\n}\n\n/**\n * 统一入口:按方法分发到 handler 表。\n * @author ddj 2026年08月20号 / 2026年08月26号\n */\nexport async function handleRpc<M extends RpcMethod>(\n ctx: Ctx,\n registry: Registry,\n method: M,\n args: RpcRequestMap[M],\n searcher = newSearcher(ctx),\n contentSearcher = newContentSearcher(ctx),\n lspHandlers?: Partial<RpcHandlerMap>,\n aiHandlers?: Partial<RpcHandlerMap>,\n): Promise<RpcResult<M>> {\n const handlers = buildHandlers(ctx, registry, searcher, contentSearcher, lspHandlers, aiHandlers)\n const handler = handlers[method]\n if (!handler) return { ok: false, error: '未知方法: ' + String(method) } as RpcResult<M>\n return handler(args)\n}\n","/**\n * dsh-vscode-mode host — 项目 MCP 的 agent 级隔离。\n * 项目 MCP 连接仍由 Host 维护,但每个 agent 只继承当前 workspace 的项目工具;\n * tools.restrict() 负责模型可见性,tools.guard() 负责执行层兜底拒绝。\n * 作者 ddj 2026年08月22号\n */\nimport { LEGACY_PROJECT_PREFIX, entryHash, isProjectEntryId } from './compat.js'\nimport { entriesOf } from './mcp.js'\nimport { hashWorkspace } from './mcpProject.js'\nimport type { Ctx } from './store.js'\nimport { log } from './log.js'\n\nconst UNKNOWN_PROJECT = '__unknown_project__'\n\ntype ToolProjects = Map<string, string>\ntype AgentState = { dispose?: () => void; denyKey: string }\n\n/** 统一 workspace 路径,供 cwd 父路径匹配。 */\nexport function normalizePath(path: string): string {\n const value = String(path ?? '').replace(/\\\\/g, '/').replace(/\\/+/g, '/')\n return value.replace(/\\/$/, '').toLowerCase()\n}\n\n/** 在已注册 workspace 中匹配 cwd,优先最长父路径。 */\nexport function matchWorkspace(cwd: string | undefined, paths: string[]): string | undefined {\n if (!cwd) return undefined\n const target = normalizePath(cwd)\n const matches = paths.filter((path) => {\n const root = normalizePath(path)\n return target === root || target.startsWith(root + '/')\n })\n matches.sort((a, b) => normalizePath(b).length - normalizePath(a).length)\n return matches[0]\n}\n\n/** 根据 entry id 判断是否为新旧格式项目 MCP(兼容层统一判定)。 */\nexport const isProjectEntry = isProjectEntryId\n\n/** 兼容:旧版前缀常量名(mcpIsolation 历史导出,语义不变)。 */\nexport const LEGACY_PREFIX = LEGACY_PROJECT_PREFIX\n\n/** 返回一个 agent 不应继承的项目工具名。 */\nexport function denyTools(toolProjects: ToolProjects, currentPath: string | undefined): string[] {\n return [...toolProjects.entries()].filter(([, owner]) => owner !== currentPath).map(([name]) => name).sort()\n}\n\n/** 从 loader entry 和工具注册表建立工具到项目路径的映射。 */\nfunction projectTools(ctx: Ctx): ToolProjects {\n const result: ToolProjects = new Map()\n const registry = ctx.get('workspaceRegistry')\n const workspaces = registry?.list?.() ?? []\n const byHash: Map<string, string> = new Map(workspaces.map((ws: { path: string }) => [hashWorkspace(ws.path), ws.path] as [string, string]))\n const visible = ctx.get('tools')?.view?.(void 0)?.visible\n if (!(visible instanceof Map)) return result\n for (const entry of entriesOf(ctx)) {\n const id = String(entry.id ?? entry.options?.id ?? '')\n if (!isProjectEntry(id)) continue\n const hash = entryHash(id)\n const owner = hash ? byHash.get(hash) ?? UNKNOWN_PROJECT : UNKNOWN_PROJECT\n const serverName = entry.options?.config?.serverName\n if (typeof serverName !== 'string') continue\n const prefix = `mcp__${serverName}__`\n for (const name of visible.keys()) if (String(name).startsWith(prefix)) result.set(String(name), owner)\n }\n return result\n}\n\n/** 取得 agent 当前 cwd 所属 workspace。 */\nfunction agentWorkspace(ctx: Ctx, agent: any): string | undefined {\n const cwd = agent?.session?.header?.cwd\n const paths = (ctx.get('workspaceRegistry')?.list?.() ?? []).map((ws: { path: string }) => ws.path)\n return matchWorkspace(cwd, paths)\n}\n\n/** 同步一个 agent 的项目工具 deny 列表。 */\nfunction syncAgent(ctx: Ctx, state: AgentState, agent: any, tools: ToolProjects): void {\n const current = agentWorkspace(ctx, agent)\n const denied = denyTools(tools, current)\n const nextKey = denied.join('\\n')\n if (state.denyKey === nextKey) return\n state.dispose?.()\n state.dispose = undefined\n if (denied.length > 0) {\n try {\n state.dispose = agent.ctx.tools.restrict({ deny: denied })\n } catch (error) {\n log.warn('MCP agent restriction failed: ' + String(error))\n return\n }\n }\n state.denyKey = nextKey\n}\n\n/** 为当前 Host 安装项目 MCP 的 agent restriction 与执行 guard。 */\nexport function installIsolation(ctx: Ctx): void {\n const tools = ctx.get('tools')\n const agents = ctx.get('agents')\n if (!tools || !agents) return\n const states = new Map<any, AgentState>()\n let toolProjects = projectTools(ctx)\n let scheduled = false\n let syncing = false\n\n const syncAll = () => {\n if (syncing) return\n syncing = true\n try {\n toolProjects = projectTools(ctx)\n for (const agent of agents.list?.() ?? []) {\n const state = states.get(agent) ?? { denyKey: '' }\n states.set(agent, state)\n syncAgent(ctx, state, agent, toolProjects)\n }\n } finally {\n syncing = false\n }\n }\n const scheduleSync = () => {\n if (scheduled) return\n scheduled = true\n queueMicrotask(() => {\n scheduled = false\n syncAll()\n })\n }\n const onCreated = ctx.on('agent/created', ({ agent }: { agent: any }) => {\n const state = { denyKey: '' }\n states.set(agent, state)\n syncAgent(ctx, state, agent, toolProjects)\n })\n const onDisposed = ctx.on('agent/disposed', ({ agent }: { agent: any }) => {\n const state = states.get(agent)\n state?.dispose?.()\n states.delete(agent)\n })\n const onToolsChange = ctx.on('tools/change', scheduleSync)\n const stopGuard = tools.guard((exec: any) => {\n const owner = toolProjects.get(String(exec?.name ?? ''))\n if (!owner) return undefined\n const current = agentWorkspace(ctx, exec.agent)\n if (owner === current) return undefined\n return current === undefined\n ? '项目 MCP 需要在已注册工作区的对话中使用'\n : '已拒绝:当前对话工作区不能使用其他项目的 MCP'\n })\n syncAll()\n ctx.effect(() => () => {\n onCreated?.()\n onDisposed?.()\n onToolsChange?.()\n stopGuard?.()\n for (const state of states.values()) state.dispose?.()\n states.clear()\n }, 'vscode-mode:mcp-isolation')\n}\n","/**\n * dsh-vscode-mode host — 工作区文件清单扫描与缓存(快速打开/搜索用)。\n * 迁移自原 src/index.ts 的 listWorkspaceFiles,语义不改。\n * 作者 ddj 2026-08-20\n */\nimport type { Ctx, Session } from './store.js'\nimport { policyOf } from './store.js'\nimport { log } from './log.js'\n\n/** 文件清单缓存 TTL 与扫描上限(避免大工作区反复全量扫描)。 */\nconst FILE_INDEX_TTL = 60_000\nconst SCAN_CAP = 6000\n/** cwd → { at, files }(随会话销毁清理)。 */\nconst fileIndex = new Map<string, { at: number; files: string[] }>()\n\n/**\n * 扫描工作区文件清单(快速打开/搜索用):subprocess(Windows powershell / POSIX find),\n * 排除常见重目录,容量上限 SCAN_CAP;结果缓存(TTL FILE_INDEX_TTL)。失败返回 null。\n * @author ddj 2026年08月20号\n * @param ctx DSH 上下文\n * @param session 会话(取工作区根)\n * @param cwd 工作区目录\n * @returns 绝对路径清单;不可用(无 subprocess/fs)或扫描失败返回 null\n */\nexport async function listWorkspaceFiles(ctx: Ctx, session: Session, cwd: string): Promise<string[] | null> {\n const cached = fileIndex.get(cwd)\n if (cached && Date.now() - cached.at < FILE_INDEX_TTL) return cached.files\n const sub = ctx.get('subprocess')\n const fs = ctx.get('fs')\n if (!sub || !fs) return null\n const policy = policyOf(ctx, session)\n let root: string\n try {\n const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', {})\n root = fs.processPath(rootTarget)\n } catch (error) {\n root = cwd\n }\n const lines: string[] = []\n const run = async (argv: string[]): Promise<void> => {\n const handle = sub.spawn({\n argv,\n stdio: { stdout: { maxBytes: 8 << 20 }, stderr: { maxBytes: 1 << 16 }, stdin: 'ignore' },\n graceMs: 20000,\n })\n const outcome = await handle.done\n const code = outcome?.exitCode ?? outcome?.code\n if (code !== 0) throw new Error('scan exit ' + code)\n const text = handle.collected?.stdout?.readFrom(0).text ?? ''\n for (const ln of text.split(/\\r?\\n/)) {\n const s = ln.trim()\n if (s) lines.push(s)\n }\n }\n try {\n if (process.platform === 'win32') {\n const cmd = 'Get-ChildItem -LiteralPath \"' + String(root).replace(/\"/g, '\"\"') + '\" -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $_.FullName -notmatch \\'(node_modules|\\\\.git|\\\\.tmp|\\\\.cache|dist|build|vendor|coverage|__pycache__)\\' } | Select-Object -First ' + SCAN_CAP + ' | ForEach-Object { $_.FullName }'\n await run(['powershell', '-NoProfile', '-NonInteractive', '-Command', cmd])\n } else {\n const cmd = 'find ' + JSON.stringify(root) + ' -type f -not -path \\'*/node_modules/*\\' -not -path \\'*/.git/*\\' -not -path \\'*/.tmp/*\\' -not -path \\'*/.cache/*\\' -not -path \\'*/dist/*\\' -not -path \\'*/build/*\\' -not -path \\'*/vendor/*\\' -not -path \\'*/coverage/*\\' 2>/dev/null | head -n ' + SCAN_CAP\n await run(['/bin/sh', '-c', cmd])\n }\n } catch (error) {\n log.error('scan failed: ' + String(error))\n return null\n }\n const files = lines.slice(0, SCAN_CAP)\n if (files.length) fileIndex.set(cwd, { at: Date.now(), files })\n return files\n}\n\n/** 会话销毁时清理文件索引缓存。 */\nexport function dropFileIndex(cwd: string): void {\n fileIndex.delete(cwd)\n}\n","/**\n * dsh-vscode-mode host — LSP JSON-RPC 帧编解码(纯函数,node 可测)。\n * LSP over stdio 用 Content-Length 帧:\n * Content-Length: <n>\\r\\n\\r\\n<恰好 n 字节 JSON>\n * 导出:encodeMessage(对象→帧 Buffer)、createFrameParser(流式粘包/拆包)、parseFrame(单帧)。\n * 作者 ddj 2026-08-27\n */\n\nconst HEADER_END = '\\r\\n\\r\\n'\n\n/** 消息头正则(仅取 Content-Length;其它头忽略)。 */\nconst HEADER_RE = /^Content-Length:\\s*(\\d+)\\s*$/im\n\n/** 将对象编码为带 Content-Length 头的帧。 */\nexport function encodeMessage(message: unknown): Buffer {\n const body = JSON.stringify(message)\n const head = 'Content-Length: ' + Buffer.byteLength(body, 'utf8') + '\\r\\n\\r\\n'\n return Buffer.from(head + body, 'utf8')\n}\n\n/**\n * 尝试从 buffer 解析单个帧;成功返回 { body, rest },数据不足返回 null。\n * @author ddj 2026年08月27号\n * @param buffer 已累积的字节\n * @returns 解析结果(rest 为剩余未消费字节)\n */\nexport function parseFrame(buffer: Buffer): { body: string; rest: Buffer } | null {\n const headEnd = buffer.indexOf(HEADER_END)\n if (headEnd < 0) return null\n const header = buffer.subarray(0, headEnd).toString('utf8')\n const m = HEADER_RE.exec(header)\n if (!m) {\n // 非法头:丢弃直到下一个帧头,避免死循环\n const next = buffer.indexOf('Content-Length:')\n return next >= 0 ? parseFrame(buffer.subarray(next)) : null\n }\n const length = Number(m[1])\n const bodyStart = headEnd + HEADER_END.length\n if (buffer.length < bodyStart + length) return null\n const body = buffer.subarray(bodyStart, bodyStart + length).toString('utf8')\n return { body, rest: buffer.subarray(bodyStart + length) }\n}\n\n/** 帧解析器:push 数据块,吐出完整消息(可能拆包后重组、也可能一包多帧)。 */\nexport function createFrameParser(): {\n push(chunk: Buffer): unknown[]\n clear(): void\n} {\n let buffer: Buffer = Buffer.alloc(0)\n return {\n push(chunk: Buffer): unknown[] {\n if (chunk.length) buffer = Buffer.concat([buffer, chunk]) as Buffer\n const out: unknown[] = []\n for (;;) {\n const parsed = parseFrame(buffer)\n if (!parsed) break\n buffer = parsed.rest\n try {\n out.push(JSON.parse(parsed.body))\n } catch (error) {\n out.push({ jsonrpc: '2.0', error: { code: -32700, message: 'Parse error: ' + String(error) }, id: null })\n }\n }\n return out\n },\n clear(): void {\n buffer = Buffer.alloc(0)\n },\n }\n}\n\n/** 构造标准 JSON-RPC 请求消息。 */\nexport function requestMessage(id: number, method: string, params: unknown): Record<string, unknown> {\n return { jsonrpc: '2.0', id, method, params }\n}\n\n/** 构造标准 JSON-RPC 通知消息(无 id,fire-and-forget)。 */\nexport function notifyMessage(method: string, params: unknown): Record<string, unknown> {\n return { jsonrpc: '2.0', method, params }\n}\n\n/** 构造标准 JSON-RPC 响应消息。 */\nexport function responseMessage(id: number | string | null, result: unknown, error?: unknown): Record<string, unknown> {\n if (error !== undefined) return { jsonrpc: '2.0', id, error }\n return { jsonrpc: '2.0', id, result }\n}\n","/**\n * dsh-vscode-mode host — LSP 语言服务器进程传输层。\n * 基于 node:child_process.spawn(stdio pipe 双向流)。刻意不用 DSH ctx.subprocess\n * 抽象:LSP 需要持续写 stdin + 流式读 stdout,而该抽象 stdin 不可写、输出为一次性收集。\n * 作者 ddj 2026-08-27\n */\nimport { spawn, type ChildProcess } from 'node:child_process'\nimport { createFrameParser } from './jsonrpc.js'\n\nconst STDERR_CAP = 256 << 10\n\nexport interface TransportSpec {\n argv: string[]\n cwd?: string\n env?: Record<string, string>\n}\n\nexport interface Transport {\n /** 写一行帧到 stdin(自动加换行)。 */\n write(chunk: Buffer): boolean\n /** 推送 stdout 解析出的原始消息(内部由帧解析器调用)。 */\n onMessage: ((message: unknown) => void) | null\n /** stderr 收集缓冲(有界,供诊断)。 */\n stderr(): string\n /** 进程退出/崩溃回调(code/signal)。 */\n onExit: ((code: number | null, signal: string | null) => void) | null\n /** 优雅关闭后强杀(Windows 下连带进程树)。 */\n dispose(): void\n /** 是否仍存活。 */\n readonly alive: boolean\n readonly pid: number | undefined\n}\n\nconst running = new Set<ChildProcess>()\n\n/** 当前仍在运行的 LSP 子进程(供 disposeAll / 诊断)。 */\nexport function liveChildren(): ReadonlySet<ChildProcess> {\n return running\n}\n\n/**\n * 启动语言服务器进程。\n * @author ddj 2026年08月27号\n * @param spec 启动参数(argv 数组,不经 shell,Windows 引号安全)\n * @param onMessage stdout 消息回调\n * @param logger 诊断日志(可选)\n * @returns 传输句柄\n */\nexport function spawnServer(spec: TransportSpec, onMessage: (message: unknown) => void, logger?: (line: string) => void): Transport {\n const { argv, cwd, env } = spec\n const child = spawn(argv[0], argv.slice(1), {\n cwd,\n env: { ...process.env, ...env },\n stdio: ['pipe', 'pipe', 'pipe'],\n windowsHide: true,\n })\n running.add(child)\n let stderrBuf = Buffer.alloc(0)\n let alive = true\n const parser = createFrameParser()\n\n child.stderr.on('data', (chunk: Buffer) => {\n if (stderrBuf.length < STDERR_CAP) {\n stderrBuf = Buffer.concat([stderrBuf, chunk], Math.min(stderrBuf.length + chunk.length, STDERR_CAP))\n }\n logger?.(chunk.toString('utf8'))\n })\n\n let exited = false\n const emitExit = (code: number | null, signal: string | null): void => {\n if (exited) return\n exited = true\n alive = false\n running.delete(child)\n transport.onExit?.(code, signal)\n }\n child.on('error', (error) => {\n logger?.('spawn error: ' + String(error))\n emitExit(null, null)\n })\n child.on('exit', (code, signal) => emitExit(code, signal))\n child.on('close', (code, signal) => emitExit(code, signal))\n\n const transport: Transport = {\n write(chunk: Buffer): boolean {\n if (!alive || !child.stdin.writable) return false\n child.stdin.write(chunk)\n return true\n },\n onMessage,\n stderr(): string {\n return stderrBuf.toString('utf8')\n },\n onExit: null,\n dispose(): void {\n if (!alive) return\n // 先 SIGTERM 让服务器有机会清理,1.5s 后强杀进程树\n child.kill()\n const timer = setTimeout(() => {\n if (!alive) return\n alive = false\n running.delete(child)\n try {\n if (process.platform === 'win32') {\n spawn('taskkill', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' })\n } else {\n child.kill('SIGKILL')\n }\n } catch (error) {\n logger?.('force kill error: ' + String(error))\n }\n }, 1500)\n timer.unref?.()\n },\n get alive() {\n return alive\n },\n get pid() {\n return child.pid\n },\n }\n // stdout 帧解析 → onMessage(LSP 响应/通知;onMessage 由 client 接管后动态生效)\n child.stdout.on('data', (chunk: Buffer) => {\n for (const message of parser.push(chunk)) transport.onMessage?.(message)\n })\n return transport\n}\n\n/** 强杀全部运行中的 LSP 子进程(插件卸载/退出用)。 */\nexport function disposeAllServers(): void {\n for (const child of running) {\n try {\n if (process.platform === 'win32' && child.pid) {\n spawn('taskkill', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' })\n } else {\n child.kill('SIGKILL')\n }\n } catch (error) {\n /* 忽略单个清理失败 */\n }\n }\n running.clear()\n}\n","/**\n * dsh-vscode-mode shared — 语言服务器 RPC 契约(双面,禁 node/react)。\n * LSP 请求/响应的 JSON 载荷形状 + 纯函数辅助(Monaco↔LSP 坐标换算等)。\n * 只描述\"过 RPC 的载荷\",宿主与语言服务器之间的帧级交互在 host 侧 src/lsp/ 内。\n * 作者 ddj 2026-08-27\n */\n\n/** LSP Position(0-based:line 行号从 0,character UTF-16 列从 0)。 */\nexport interface LspPosition {\n line: number\n character: number\n}\n\n/** LSP Range(start/end 均 0-based,包含 start、排除 end)。 */\nexport interface LspRange {\n start: LspPosition\n end: LspPosition\n}\n\n/** LSP Location:uri 为 file:// 绝对路径;root 用于还原为工作区相对路径。 */\nexport interface LspLocation {\n uri: string\n range: LspRange\n root?: string\n}\n\n/** 跳转结果(definition 常返回 LocationLink,归一化为 targetUri + targetRange + 可选 originSelectionRange)。 */\nexport interface LspLocationLink {\n targetUri: string\n targetRange: LspRange\n targetSelectionRange: LspRange\n originSelectionRange?: LspRange\n}\n\n/** 归一化后的符号(documentSymbol/workspaceSymbol 统一形状)。kind 为 LSP SymbolKind 数值。 */\nexport interface LspSymbol {\n name: string\n kind: number\n range: LspRange\n selectionRange: LspRange\n detail?: string\n containerName?: string\n children?: LspSymbol[]\n}\n\n/** hover 内容(markdown/纯文本行数组)。 */\nexport interface LspHover {\n contents: string[]\n range?: LspRange\n}\n\n/** LSP semantic token 标准类型(host 归一化后,client 与 Monaco 共用)。 */\nexport const LSP_SEMANTIC_TOKEN_TYPES = [\n 'namespace', 'type', 'class', 'enum', 'interface', 'struct', 'typeParameter',\n 'parameter', 'variable', 'property', 'enumMember', 'event', 'function', 'method',\n 'macro', 'label', 'comment', 'string', 'keyword', 'number', 'regexp', 'operator',\n 'decorator',\n] as const\n\n/** LSP semantic token 标准修饰符(host 归一化后,client 与 Monaco 共用)。 */\nexport const LSP_SEMANTIC_TOKEN_MODIFIERS = [\n 'declaration', 'definition', 'readonly', 'static', 'deprecated', 'abstract',\n 'async', 'modification', 'documentation', 'defaultLibrary', 'global', 'local', 'mutable',\n] as const\n\n/** 归一化后的 LSP semanticTokens/full 结果(data 使用 LSP delta 编码)。 */\nexport interface LspSemanticTokens {\n data: number[]\n resultId?: string\n}\n\n/** 语义 token 解码后的绝对范围(LSP 0-based;type 为插件固定 legend 与 type 名)。 */\nexport interface LspSemanticTokenRange {\n start: LspPosition\n end: LspPosition\n type: string\n modifiers: number\n}\n\n/** 语义 token 中可作为\"可导航标识符\"的类型(ctrl+hover 下划线判定用)。 */\nexport const LSP_NAVIGABLE_TOKEN_TYPES: ReadonlySet<string> = new Set([\n 'variable', 'parameter', 'property', 'function', 'method', 'class', 'enum',\n 'struct', 'interface', 'namespace', 'typeParameter', 'enumMember', 'event', 'type',\n])\n\n/**\n * 语义 token 是否属于可导航标识符。\n * @author ddj 2026年09月02号\n * @param type 语义 token 类型名(插件固定 legend)\n * @returns 是否可导航\n */\nexport function isNavigableTokenType(type: string): boolean {\n return LSP_NAVIGABLE_TOKEN_TYPES.has(type)\n}\n\n/**\n * 解码 LSP delta 编码的语义 token 流为绝对范围数组。\n * @author ddj 2026年09月02号\n * @param data 5 元组 delta 流(host normalizeSemanticData 产物,类型索引对应固定 legend)\n * @param types 固定 legend 类型表(缺省 LSP_SEMANTIC_TOKEN_TYPES)\n * @returns 绝对范围列表(保持文档顺序)\n */\nexport function decodeSemanticTokens(\n data: number[],\n types: readonly string[] = LSP_SEMANTIC_TOKEN_TYPES,\n): LspSemanticTokenRange[] {\n const out: LspSemanticTokenRange[] = []\n let line = 0\n let character = 0\n for (let i = 0; i + 4 < data.length; i += 5) {\n const deltaLine = data[i] ?? 0\n const deltaCharacter = data[i + 1] ?? 0\n const length = Math.max(0, data[i + 2] ?? 0)\n const typeIndex = data[i + 3] ?? 0\n const modifiers = data[i + 4] ?? 0\n line += deltaLine\n character = deltaLine === 0 ? character + deltaCharacter : deltaCharacter\n out.push({\n start: { line, character },\n end: { line, character: character + length },\n type: types[typeIndex] ?? 'variable',\n modifiers,\n })\n }\n return out\n}\n\n/** LSP 服务器能力子集:本插件会用到的方法。 */\nexport interface LspServerCapabilities {\n definition: boolean\n declaration: boolean\n references: boolean\n documentSymbol: boolean\n workspaceSymbol: boolean\n hover: boolean\n semanticTokens: boolean\n semanticTokenTypes?: string[]\n semanticTokenModifiers?: string[]\n}\n\n/** 服务器进程/会话状态。 */\nexport type LspServerPhase =\n | 'idle' // 未启动(惰性)\n | 'starting' // 启动中(initialize 握手)\n | 'ready' // 就绪\n | 'indexing' // 工作区索引中\n | 'unavailable' // 连续失败,停止自动重启\n | 'stopped' // 已停止(禁用/卸载/会话结束)\n\n/** 单条缺失环境需求(edrv.lsp.status.missingEnv 元素,仅含未满足项)。 */\nexport interface LspMissingEnv {\n id: string // 需求标识(如 dotnet-runtime:10,同时是安装器键)\n label: string // 显示名(如 '.NET 运行时 10.0')\n detail?: string // 说明(哪个服务器需要)\n installable: boolean // 支持一键安装\n manualUrl?: string // 官网手动下载地址\n manualLabel?: string\n}\n\n/** 环境安装进行态(edrv.lsp.envState 载荷元素)。 */\nexport interface LspEnvInstallState {\n id: string\n phase: 'idle' | 'downloading' | 'extracting' | 'done' | 'failed'\n message?: string\n}\n\n/** 同语言检测到的候选服务器(candidates 元素;chosen 标记当前选用者)。 */\nexport interface LspCandidate {\n name: string // 显示名(如 EmmyLua / LuaLS / Roslyn)\n version?: string // 扩展清单版本\n path?: string // 服务器入口路径(argv 比对用)\n chosen?: boolean // 是否为当前解析选用的服务器\n}\n\n/** 单语言服务器状态(edrv.lsp.status 载荷元素)。 */\nexport interface LspServerStatus {\n languageId: string\n source: 'extension' | 'discover' | 'manual' | 'none'\n phase: LspServerPhase\n version?: string\n reason?: string // unavailable/不可用原因(缺 dotnet、找不到服务器等)\n progress?: number // LSP 工作区解析进度(0–100,未知时省略)\n progressMessage?: string\n root?: string // 绑定工作区根(相对显示)\n providerName?: string // provider 名称(如 EmmyLua / LuaLS)\n missingEnv?: LspMissingEnv[] // 未满足的环境需求(无则省略)\n candidates?: LspCandidate[] // 同语言检测到的候选服务器(设置页展示用,无则省略)\n}\n\n/**\n * Monaco 位置(1-based lineNumber/column)→ LSP Position(0-based)。\n * @author ddj 2026年08月27号\n * @param lineNumber Monaco 行(≥1)\n * @param column Monaco 列(≥1)\n * @returns LSP 0-based position\n */\nexport function monoToLsp(lineNumber: number, column: number): LspPosition {\n return { line: Math.max(0, lineNumber - 1), character: Math.max(0, column - 1) }\n}\n\n/**\n * LSP Position(0-based)→ Monaco 位置(1-based)。\n * @author ddj 2026年08月27号\n * @param pos LSP position\n * @returns { lineNumber, column }(均 ≥1)\n */\nexport function lspToMono(pos: LspPosition): { lineNumber: number; column: number } {\n return { lineNumber: Math.max(1, pos.line + 1), column: Math.max(1, pos.character + 1) }\n}\n\n/** file:// URI → 路径(仅做规范化解码;Windows file:///C:/... 保留)。 */\nexport function fileUriToPath(uri: string): string {\n if (!uri) return ''\n const rest = uri.replace(/^file:\\/\\//, '')\n const decoded = decodeURIComponent(rest)\n return decoded.replace(/^\\/([A-Za-z]:)/, '$1') // file:///C:/x → C:/x\n}\n\n/** 已装扩展信息(edrv.lsp.ext.list 载荷元素)。 */\nexport interface LspExtInfo {\n id: string // publisher.name\n namespace: string\n name: string\n version: string\n displayName?: string\n description?: string\n}\n\n/** Open VSX 市场搜索结果项(edrv.lsp.ext.market 载荷元素)。 */\nexport interface LspMarketItem {\n namespace: string\n name: string\n id: string\n version: string\n displayName?: string\n description?: string\n download?: string\n}\n\n/** 有更新的已装扩展(edrv.lsp.ext.updates 载荷元素)。 */\nexport interface LspExtUpdate {\n id: string\n current: string\n latest: string\n displayName?: string\n}\n","/**\n * dsh-vscode-mode host — LSP 客户端(JSON-RPC over stdio)。\n * 职责:请求/通知/握手/超时/服务器端请求处理/生命周期。transport 无关性:\n * 只依赖 write/onMessage 契约,便于单测时注入假传输。\n * 作者 ddj 2026-08-27\n */\nimport { createFrameParser, encodeMessage, requestMessage, notifyMessage } from './jsonrpc.js'\nimport { LSP_SEMANTIC_TOKEN_TYPES, LSP_SEMANTIC_TOKEN_MODIFIERS, type LspServerCapabilities } from '../shared/lsp.js'\n\nexport interface LspClientEvents {\n onReady?: (capabilities: LspServerCapabilities) => void\n onExit?: (code: number | null, signal: string | null) => void\n onLog?: (line: string) => void\n onProgress?: (params: unknown) => void\n}\n\nconst DEFAULT_TIMEOUT_MS = 20_000\n\nexport class LspError extends Error {\n code: number\n constructor(code: number, message: string) {\n super(message)\n this.code = code\n }\n}\n\nexport interface LspClientTransport {\n write(chunk: Buffer): boolean\n dispose(): void\n readonly alive: boolean\n onMessage: ((message: unknown) => void) | null\n onExit: ((code: number | null, signal: string | null) => void) | null\n}\n\nexport interface LspClient {\n request<T>(method: string, params: unknown, timeoutMs?: number): Promise<T>\n notify(method: string, params: unknown): void\n initialize(rootUri: string, workspaceFolders: string[]): Promise<LspServerCapabilities>\n shutdown(): Promise<void>\n readonly alive: boolean\n}\n\n/**\n * 创建 LSP 客户端。\n * @author ddj 2026年08月27号\n * @param transport 传输句柄(write/onMessage/alive/dispose)\n * @param events 事件回调\n * @returns LSP 客户端\n */\nexport function createLspClient(\n transport: LspClientTransport,\n events: LspClientEvents = {},\n): LspClient {\n let nextId = 1\n let alive = transport.alive\n const pending = new Map<number, { resolve: (v: unknown) => void; reject: (e: Error) => void; timer: ReturnType<typeof setTimeout> }>()\n let serverCapabilities: LspServerCapabilities = {\n definition: false,\n declaration: false,\n references: false,\n documentSymbol: false,\n workspaceSymbol: false,\n hover: false,\n semanticTokens: false,\n semanticTokenTypes: [],\n semanticTokenModifiers: [],\n }\n\n const log = (line: string): void => events.onLog?.(line)\n const parser = createFrameParser()\n\n transport.onMessage = (message: unknown): void => {\n const msg = message as { id?: unknown; method?: unknown; params?: unknown; result?: unknown; error?: unknown }\n // 服务器端请求/通知带 method(请求还带 id);响应带 id + result/error、无 method。先判 method 再判 id。\n if (typeof msg.method === 'string') {\n if (msg.method === '$/progress') events.onProgress?.(msg.params)\n void handleServerRequest(msg as { method: string; params?: unknown; id?: unknown })\n return\n }\n if (typeof msg.id === 'number' || typeof msg.id === 'string') {\n const entry = pending.get(Number(msg.id))\n if (!entry) return\n pending.delete(Number(msg.id))\n clearTimeout(entry.timer)\n if (msg.error) {\n const err = msg.error as { code?: number; message?: string }\n entry.reject(new LspError(err.code ?? -32000, err.message ?? 'LSP error'))\n } else {\n entry.resolve(msg.result)\n }\n }\n }\n\n /** 服务器端请求:消息/日志类打日志,配置/能力类回 result:null,其余回 method not found。 */\n const handleServerRequest = async (msg: { method: string; params?: unknown; id?: unknown }): Promise<void> => {\n const { method, params, id } = msg\n const respond = (payload: Record<string, unknown>): void => {\n transport.write(encodeMessage(payload))\n }\n try {\n if (method === 'window/logMessage' || method === 'window/showMessage' || method === 'window/showMessageRequest') {\n const p = params as { type?: number; message?: string }\n log('[server ' + (p?.type ?? '') + '] ' + String(p?.message ?? ''))\n if (id !== undefined) respond({ jsonrpc: '2.0', id, result: null })\n return\n }\n if (method === 'workspace/configuration') {\n const p = params as { items?: unknown[] }\n const items = Array.isArray(p?.items) ? p.items.map(() => null) : []\n if (id !== undefined) respond({ jsonrpc: '2.0', id, result: items })\n return\n }\n // 客户端能力协商类:标准行为是确认(result:null),否则部分服务器(如 LuaLS)会中断工作区初始化\n if (method === 'window/workDoneProgress/create' || method === 'client/registerCapability' || method === 'workspace/workspaceFolders') {\n if (id !== undefined) respond({ jsonrpc: '2.0', id, result: null })\n return\n }\n if (id !== undefined) {\n respond({ jsonrpc: '2.0', id, error: { code: -32601, message: 'Method not found: ' + method } })\n }\n } catch (error) {\n log('server request handler error: ' + String(error))\n if (id !== undefined) {\n respond({ jsonrpc: '2.0', id, error: { code: -32603, message: String(error) } })\n }\n }\n }\n\n const transportExit = transport.onExit\n transport.onExit = (code, signal): void => {\n alive = false\n for (const entry of pending.values()) {\n clearTimeout(entry.timer)\n entry.reject(new Error('LSP 服务器已退出(' + String(code) + '/' + String(signal) + ')'))\n }\n pending.clear()\n events.onExit?.(code, signal)\n transportExit?.(code, signal)\n }\n\n const client: LspClient = {\n async request<T>(method: string, params: unknown, timeoutMs = DEFAULT_TIMEOUT_MS): Promise<T> {\n if (!alive) throw new Error('LSP 服务器未运行')\n const id = nextId++\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n pending.delete(id)\n reject(new Error('LSP 请求超时:' + method + '(' + timeoutMs + 'ms)'))\n }, timeoutMs)\n pending.set(id, { resolve: resolve as (v: unknown) => void, reject, timer })\n transport.write(encodeMessage(requestMessage(id, method, params)))\n })\n },\n notify(method: string, params: unknown): void {\n if (!alive) return\n transport.write(encodeMessage(notifyMessage(method, params)))\n },\n async initialize(rootUri: string, workspaceFolders: string[]): Promise<LspServerCapabilities> {\n const init = await client.request<{\n capabilities?: {\n definitionProvider?: unknown\n declarationProvider?: unknown\n referencesProvider?: unknown\n documentSymbolProvider?: unknown\n workspaceSymbolProvider?: unknown\n hoverProvider?: unknown\n semanticTokensProvider?: {\n legend?: { tokenTypes?: unknown; tokenModifiers?: unknown }\n }\n }\n }>('initialize', {\n processId: process.pid,\n rootUri: rootUri || null,\n rootPath: null,\n workspaceFolders: workspaceFolders.length\n ? workspaceFolders.map((uri) => ({ uri, name: uri }))\n : null,\n capabilities: {\n window: { workDoneProgress: true },\n workspace: { configuration: true },\n textDocument: {\n synchronization: { dynamicRegistration: false, willSave: false, didSave: true },\n definition: { dynamicRegistration: false },\n declaration: { dynamicRegistration: false },\n references: { dynamicRegistration: false },\n documentSymbol: { dynamicRegistration: false },\n hover: { dynamicRegistration: false },\n semanticTokens: {\n dynamicRegistration: false,\n requests: { range: false, full: { delta: false } },\n tokenTypes: [...LSP_SEMANTIC_TOKEN_TYPES],\n tokenModifiers: [...LSP_SEMANTIC_TOKEN_MODIFIERS],\n formats: ['relative'],\n },\n },\n },\n })\n const caps = init?.capabilities ?? {}\n const legend = caps.semanticTokensProvider?.legend\n serverCapabilities = {\n definition: Boolean(caps.definitionProvider),\n declaration: Boolean(caps.declarationProvider),\n references: Boolean(caps.referencesProvider),\n documentSymbol: Boolean(caps.documentSymbolProvider),\n workspaceSymbol: Boolean(caps.workspaceSymbolProvider),\n hover: Boolean(caps.hoverProvider),\n semanticTokens: Boolean(caps.semanticTokensProvider),\n semanticTokenTypes: Array.isArray(legend?.tokenTypes)\n ? legend.tokenTypes.filter((item): item is string => typeof item === 'string')\n : [...LSP_SEMANTIC_TOKEN_TYPES],\n semanticTokenModifiers: Array.isArray(legend?.tokenModifiers)\n ? legend.tokenModifiers.filter((item): item is string => typeof item === 'string')\n : [...LSP_SEMANTIC_TOKEN_MODIFIERS],\n }\n client.notify('initialized', {})\n events.onReady?.(serverCapabilities)\n return serverCapabilities\n },\n async shutdown(): Promise<void> {\n try {\n await client.request<unknown>('shutdown', null, 3000)\n } catch (error) {\n log('shutdown: ' + String(error))\n }\n try {\n client.notify('exit', null)\n } catch (error) {\n log('exit: ' + String(error))\n }\n },\n get alive() {\n return alive\n },\n }\n return client\n}\n","/**\n * dsh-vscode-mode host — 路径 ↔ file:// URI 转换(纯函数,node 可测)。\n * LSP 的 uri 字段必须是 file:// 绝对 URI;客户端 Monaco 用 edrv:///<encodeURI(path)>。\n * 作者 ddj 2026-08-27\n */\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { isAbsolute, resolve as resolvePath } from 'node:path'\n\n/**\n * 绝对路径 → file:// URI(Windows 盘符保留:D:/x → file:///D:/x)。\n * @author ddj 2026年08月27号\n * @param absPath 绝对路径(正/反斜杠均可)\n * @returns file:// URI\n */\nexport function pathToFileUri(absPath: string): string {\n const normalized = absPath.replace(/\\\\/g, '/')\n const drive = /^([A-Za-z]:)(?:\\/(.*))?$/.exec(normalized)\n if (drive) {\n const tail = drive[2] ? '/' + drive[2].split('/').map(encodeURIComponent).join('/') : ''\n return 'file:///' + drive[1] + tail\n }\n return pathToFileURL(normalized).toString()\n}\n\n/**\n * file:// URI → 绝对路径(Windows file:///C:/x → C:\\x)。\n * @author ddj 2026年08月27号\n * @param uri file:// URI\n * @returns 绝对路径\n */\nexport function fileUriToPath(fileUri: string): string {\n try {\n return fileURLToPath(fileUri)\n } catch (error) {\n return String(error)\n }\n}\n\n/**\n * 将(可能相对的)路径解析为绝对路径后转 file:// URI。\n * @author ddj 2026年08月27号\n * @param path 相对或绝对路径\n * @param cwd 解析相对路径的基准(可选)\n * @returns file:// URI\n */\nexport function resolveToFileUri(path: string, cwd?: string): string {\n const abs = isAbsolute(path) ? path : cwd ? resolvePath(cwd, path) : resolvePath(path)\n return pathToFileUri(abs)\n}\n\n/**\n * 判定绝对路径是否在给定根目录(含)内。\n * @author ddj 2026年08月27号\n * @param root 根目录绝对路径\n * @param target 目标绝对路径\n * @returns 是否在根内\n */\nexport function isInside(root: string, target: string): boolean {\n const r = root.replace(/\\\\/g, '/').replace(/\\/+$/, '') + '/'\n const t = target.replace(/\\\\/g, '/')\n return t === r.slice(0, -1) || t.startsWith(r)\n}\n","/**\n * dsh-vscode-mode host — 定义查找降级链的纯推导函数。\n * 背景:EmmyLua 对局部变量/参数/表字段的 textDocument/definition 常返回空,\n * 但 references(includeDeclaration) 能给出包含声明的条目。\n * 本函数从引用列表推导\"声明位置\":同文件、词文本与点击处一致,且点击位置落在某条目内时,\n * 取列表首个(EmmyLua 对局部/参数把声明排在引用首位;点击处即首个时按\"点击了声明\"处理)。\n * 词文本必须与点击词一致,否则拒绝(宁可空,不误跳)。\n * 作者 ddj 2026-09-02\n */\nimport type { LspLocation, LspPosition, LspRange } from '../shared/lsp.js'\n\n/** file:// URI(或裸路径)→ 归一化绝对路径(小写、/ 分隔)。 */\nfunction normAbs(uri: string): string {\n const path = String(uri ?? '').replace(/^file:\\/\\/\\/?/, '')\n return decodeURIComponent(path).replace(/\\\\/g, '/').replace(/^\\/([A-Za-z]:)/, '$1').toLowerCase()\n}\n\n/** 取文档 text 在 LSP range(0-based)内的切片。 */\nfunction sliceRange(text: string, range: LspRange): string {\n const lines = text.split(/\\r\\n|\\r|\\n/)\n const start = range.start\n const end = range.end\n const startLine = Math.max(0, start.line)\n const endLine = Math.max(startLine, end.line)\n if (startLine >= lines.length || endLine >= lines.length) return ''\n const startChar = Math.max(0, start.character)\n if (startLine === endLine) {\n return lines[startLine].slice(startChar, Math.max(startChar, end.character))\n }\n const first = lines[startLine].slice(startChar)\n const middle = lines.slice(startLine + 1, endLine)\n const last = lines[endLine].slice(0, Math.max(0, end.character))\n return [first, ...middle, last].join('\\n')\n}\n\n/** LSP position 是否落在 range 内(start 包含、end 排除;零宽按点匹配)。 */\nfunction posInLspRange(pos: LspPosition, range: LspRange): boolean {\n const start = range.start\n const end = range.end ?? start\n if (start.line === end.line && start.character === end.character) {\n return pos.line === start.line && pos.character === start.character\n }\n if (pos.line < start.line || pos.line > end.line) return false\n if (pos.line === start.line && pos.character < start.character) return false\n if (pos.line === end.line && pos.character >= end.character) return false\n return true\n}\n\n/** 两个 range 是否完全一致。 */\nfunction sameRange(a: LspRange, b: LspRange): boolean {\n return a.start.line === b.start.line && a.start.character === b.start.character &&\n a.end.line === b.end.line && a.end.character === b.end.character\n}\n\n/** range 长度(行/列均按 0-based 差估算,仅用于取\"最小包裹\"排序)。 */\nfunction rangeSize(r: LspRange): number {\n return (r.end.line - r.start.line) * 1_000_000 + (r.end.line === r.start.line ? r.end.character - r.start.character : r.end.character)\n}\n\n/**\n * 从引用列表推导定义位置。\n * @author ddj 2026年09月02号\n * @param queryPos 查询位置(LSP 0-based)\n * @param locations references(includeDeclaration) 结果\n * @param docText 当前文档全文(词文本一致校验)\n * @param docAbsPath 当前文档绝对路径(root+相对路径,与 loc.uri 归一化后比较)\n * @returns 推导出的定义位置;无法确定返回 null\n */\nexport function deriveDefinitionFromLocations(\n queryPos: LspPosition,\n locations: LspLocation[],\n docText: string,\n docAbsPath: string,\n): LspLocation | null {\n if (!locations.length) return null\n const docAbs = normAbs(docAbsPath)\n\n // 点击位置落在的条目(多个时取最小包裹 = 最贴近词的 range)\n const containing = locations\n .filter((loc) => posInLspRange(queryPos, loc.range))\n .sort((a, b) => rangeSize(a.range) - rangeSize(b.range))[0]\n if (!containing) return null\n const queryWord = sliceRange(docText, containing.range)\n if (!queryWord) return null\n\n // 同文件 + 词文本一致的候选(按服务器返回顺序)\n const candidates = locations.filter((loc) => {\n return normAbs(loc.uri) === docAbs && sliceRange(docText, loc.range) === queryWord\n })\n if (!candidates.length) return null\n\n // 点击处即候选首个(且与查询词重合)→ 点击的就是声明,返回自身\n // 否则取首个(EmmyLua 对局部/参数把声明排在引用首位)\n const first = candidates[0]\n return sameRange(first.range, containing.range) ? containing : first\n}\n","/**\n * dsh-vscode-mode host — 单语言服务器会话(绑定 工作区根 + 语言)。\n * 负责:启动传输 + LSP 客户端握手、文档同步(didOpen/didChange/didSave/didClose)、\n * 请求封装(definition/references/documentSymbol/workspaceSymbol/hover)、状态上报。\n * 作者 ddj 2026-08-27\n */\nimport { spawnServer, type Transport } from './transport.js'\nimport { createLspClient, type LspClient } from './client.js'\nimport { pathToFileUri } from './uri.js'\nimport { deriveDefinitionFromLocations } from './derive.js'\nimport type { LspProviderSpec } from './providers.js'\nimport { LSP_SEMANTIC_TOKEN_MODIFIERS, LSP_SEMANTIC_TOKEN_TYPES } from '../shared/lsp.js'\nimport type {\n LspLocation,\n LspSemanticTokens,\n LspServerCapabilities,\n LspServerPhase,\n LspServerStatus,\n LspSymbol,\n} from '../shared/lsp.js'\n\nexport interface LspServer {\n readonly languageId: string\n readonly root: string\n readonly phase: LspServerPhase\n readonly capabilities: LspServerCapabilities\n onStateChange: ((status: LspServerStatus) => void) | null\n status(): LspServerStatus\n start(): Promise<boolean>\n sync(path: string, text: string, version: number): void\n close(path: string): void\n definition(path: string, line: number, character: number): Promise<LspLocation[]>\n references(path: string, line: number, character: number, includeDeclaration: boolean): Promise<LspLocation[]>\n documentSymbol(path: string): Promise<LspSymbol[]>\n workspaceSymbol(query: string): Promise<LspSymbol[]>\n hover(path: string, line: number, character: number): Promise<{ contents: string[] } | null>\n semanticTokens(path: string): Promise<LspSemanticTokens | null>\n dispose(): Promise<void>\n}\n\n/** 文档注册表:path(工作区相对) → { version, text, uri }。 */\ninterface OpenDoc {\n path: string\n uri: string\n version: number\n text: string\n}\n\nconst RESTARTABLE = true\n\n/**\n * 创建语言服务器会话。\n * @author ddj 2026年08月27号\n * @param spec provider 规格(argv/cwd)\n * @param root 工作区根(绝对路径)\n * @param languageId 语言 id\n * @param logger 诊断日志\n * @returns 会话句柄\n */\nexport function createLspServer(spec: LspProviderSpec, root: string, languageId: string, logger?: (line: string) => void): LspServer {\n const rootUri = pathToFileUri(root)\n const docs = new Map<string, OpenDoc>()\n let phase: LspServerPhase = 'idle'\n let transport: Transport | null = null\n let client: LspClient | null = null\n let capabilities: LspServerCapabilities = {\n definition: false,\n declaration: false,\n references: false,\n documentSymbol: false,\n workspaceSymbol: false,\n hover: false,\n semanticTokens: false,\n semanticTokenTypes: [...LSP_SEMANTIC_TOKEN_TYPES],\n semanticTokenModifiers: [...LSP_SEMANTIC_TOKEN_MODIFIERS],\n }\n let disposed = false\n let readyWait: Promise<boolean> = Promise.resolve(false)\n let resolveReady: ((ready: boolean) => void) | null = null\n let lastProgress: { value?: number; message?: string } = {}\n let lastStatus: LspServerStatus = {\n languageId,\n source: spec.kind,\n phase: 'idle',\n reason: spec.ready ? undefined : spec.reason,\n root,\n version: spec.version,\n providerName: spec.providerName ?? (spec.version ? '语言服务器扩展' : undefined),\n }\n\n const log = (line: string): void => logger?.('[' + languageId + '@' + root + '] ' + line)\n const providerInfo = {\n version: spec.version,\n providerName: spec.providerName ?? (spec.version ? 'EmmyLua' : undefined),\n }\n\n const setPhase = (next: LspServerPhase, reason?: string): void => {\n phase = next\n lastStatus = { languageId, source: spec.kind, phase: next, reason, root, ...providerInfo, ...progressFields() }\n server.onStateChange?.(lastStatus)\n }\n\n /** 返回当前进度字段,避免空进度污染状态载荷。 */\n const progressFields = (): Pick<LspServerStatus, 'progress' | 'progressMessage'> => ({\n progress: lastProgress.value,\n progressMessage: lastProgress.message,\n })\n\n /** 处理 LSP $/progress 通知并映射为编辑器状态。 */\n const applyProgress = (params: unknown): void => {\n const value = params as { value?: unknown }\n const report = value?.value as { kind?: unknown; percentage?: unknown; message?: unknown } | undefined\n if (report?.kind === 'begin') {\n lastProgress = { value: 0, message: typeof report.message === 'string' ? report.message : '正在解析工作区' }\n if (phase === 'ready') phase = 'indexing'\n } else if (report?.kind === 'end') {\n lastProgress = { value: 100, message: typeof report.message === 'string' ? report.message : '解析完成' }\n if (phase === 'indexing') phase = 'ready'\n } else if (typeof report?.percentage === 'number') {\n lastProgress = { value: Math.max(0, Math.min(100, report.percentage)), message: typeof report.message === 'string' ? report.message : lastProgress.message }\n if (phase === 'ready') phase = 'indexing'\n } else if (typeof report?.message === 'string') {\n lastProgress = { ...lastProgress, message: report.message }\n }\n lastStatus = { ...lastStatus, phase, ...progressFields() }\n server.onStateChange?.(lastStatus)\n }\n\n const ensureClient = (): LspClient => {\n if (!client) throw new Error('LSP 服务器未启动')\n return client\n }\n\n const server: LspServer = {\n languageId,\n root,\n get phase() {\n return phase\n },\n get capabilities() {\n return capabilities\n },\n status(): LspServerStatus {\n return lastStatus\n },\n onStateChange: null,\n\n async start(): Promise<boolean> {\n if (disposed) return false\n if (phase === 'starting') return readyWait\n if (phase === 'ready' || phase === 'indexing') return true\n readyWait = new Promise((resolve) => { resolveReady = resolve })\n lastProgress = {}\n setPhase('starting')\n try {\n transport = spawnServer(\n { argv: spec.argv, cwd: spec.cwd ?? root, env: spec.env },\n (message) => { /* 由 client 接管 */ },\n (line) => log('stderr: ' + line),\n )\n client = createLspClient(transport, {\n onReady: (caps) => {\n capabilities = caps\n // 重放已打开文档(崩溃重启后恢复服务器侧状态)\n for (const doc of docs.values()) {\n client?.notify('textDocument/didOpen', {\n textDocument: { uri: doc.uri, languageId, version: doc.version, text: doc.text },\n })\n }\n setPhase('ready')\n resolveReady?.(true)\n resolveReady = null\n log('ready: definition=' + caps.definition + ' references=' + caps.references + ' symbols=' + caps.documentSymbol)\n },\n onProgress: (params) => applyProgress(params),\n onExit: (code, signal) => {\n if (disposed) return\n resolveReady?.(false)\n resolveReady = null\n log('server exited (' + String(code) + '/' + String(signal) + ')')\n client = null\n transport = null\n if (RESTARTABLE) setPhase('idle', '服务器已退出(' + String(code) + '/' + String(signal) + '),等待重启')\n else setPhase('stopped', '服务器已退出')\n },\n onLog: (line) => log('lsp: ' + line),\n })\n // 让 client 接管 stdout 消息\n const caps = await client.initialize(rootUri, [rootUri])\n // DotRush 服务器阻塞等待带 dotrush 段的配置通知才继续初始化(加载工作区),\n // 不发则所有文档类查询返回空;官方 VSCode 扩展经 configurationSection 自动发送。\n // 按 csharp 语言统一发送:手动配置的 DotRush 与其它 C# 服务器(OmniSharp 等)\n // 对不认识的配置段按协议忽略,均安全\n if (languageId === 'csharp') {\n client.notify('workspace/didChangeConfiguration', { settings: { dotrush: { roslyn: {} } } })\n }\n capabilities = caps\n return true\n } catch (error) {\n log('start failed: ' + String(error))\n setPhase('unavailable', '启动失败:' + String(error))\n resolveReady?.(false)\n resolveReady = null\n try { await server.dispose() } catch { /* 忽略 */ }\n return false\n }\n },\n\n sync(path: string, text: string, version: number): void {\n const existing = docs.get(path)\n const uri = existing?.uri ?? pathToFileUri(root + '/' + path.split('/').join('/'))\n if (existing) {\n existing.version = version\n existing.text = text\n if (phase === 'ready' || phase === 'indexing') {\n client?.notify('textDocument/didChange', {\n textDocument: { uri, version },\n contentChanges: [{ text }],\n })\n }\n return\n }\n docs.set(path, { path, uri, version, text })\n if (phase === 'ready' || phase === 'indexing') {\n client?.notify('textDocument/didOpen', {\n textDocument: { uri, languageId, version, text },\n })\n }\n },\n\n close(path: string): void {\n const doc = docs.get(path)\n if (!doc) return\n docs.delete(path)\n if (phase === 'ready' || phase === 'indexing') {\n client?.notify('textDocument/didClose', { textDocument: { uri: doc.uri } })\n }\n },\n\n async definition(path: string, line: number, character: number): Promise<LspLocation[]> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait)) return []\n const client = ensureClient()\n const position = { line, character }\n // ① 标准定义(方法/跨文件命名空间等)\n const direct = normalizeLocations(\n await client.request<unknown>(\n 'textDocument/definition',\n { textDocument: { uri: doc.uri }, position },\n ),\n )\n if (direct.length) return direct\n // ② 声明(服务器能力支持时):EmmyLua 对局部变量/参数/表字段 definition 常返回空,declaration 更准\n if (capabilities.declaration) {\n try {\n const decl = normalizeLocations(\n await client.request<unknown>(\n 'textDocument/declaration',\n { textDocument: { uri: doc.uri }, position },\n ),\n )\n if (decl.length) {\n log('definition fallback → declaration (' + path + ':' + line + ':' + character + ')')\n return decl\n }\n } catch (error) {\n log('declaration request failed: ' + String(error))\n }\n }\n // ③ 引用推导:definition/declaration 均空时,从 references(includeDeclaration) 推导声明\n // (EmmyLua 局部/参数把声明排在引用首位;词文本不一致则拒绝,宁可空不误跳)\n try {\n const refs = normalizeLocations(\n await client.request<unknown>(\n 'textDocument/references',\n {\n textDocument: { uri: doc.uri },\n position,\n context: { includeDeclaration: true },\n },\n ),\n )\n const derived = deriveDefinitionFromLocations(position, refs, doc.text, doc.uri)\n if (derived) {\n log('definition fallback → references-derived (' + path + ':' + line + ':' + character + ')')\n return [derived]\n }\n } catch (error) {\n log('references fallback failed: ' + String(error))\n }\n return []\n },\n\n async references(path: string, line: number, character: number, includeDeclaration: boolean): Promise<LspLocation[]> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait)) return []\n const result = await ensureClient().request<unknown>(\n 'textDocument/references',\n {\n textDocument: { uri: doc.uri },\n position: { line, character },\n context: { includeDeclaration },\n },\n )\n return normalizeLocations(result)\n },\n\n async documentSymbol(path: string): Promise<LspSymbol[]> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait)) return []\n const result = await ensureClient().request<unknown>('textDocument/documentSymbol', { textDocument: { uri: doc.uri } })\n if (!Array.isArray(result)) return []\n return (result as unknown[]).map(normalizeSymbol).filter((s): s is LspSymbol => s !== null)\n },\n\n async workspaceSymbol(query: string): Promise<LspSymbol[]> {\n if (!(await readyWait)) return []\n const result = await ensureClient().request<unknown>('workspace/symbol', { query })\n if (!Array.isArray(result)) return []\n return (result as unknown[]).map(normalizeSymbol).filter((s): s is LspSymbol => s !== null)\n },\n\n async hover(path: string, line: number, character: number): Promise<{ contents: string[] } | null> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait)) return null\n const result = await ensureClient().request<{ contents?: unknown; range?: unknown } | null>(\n 'textDocument/hover',\n { textDocument: { uri: doc.uri }, position: { line, character } },\n )\n if (!result || !result.contents) return null\n return { contents: stringifyHoverContents(result.contents) }\n },\n\n /** 查询全文 semantic tokens,并将服务器 legend 归一到插件固定 legend。 */\n async semanticTokens(path: string): Promise<LspSemanticTokens | null> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait) || !capabilities.semanticTokens) return null\n const result = await ensureClient().request<{ data?: unknown; resultId?: unknown } | null>(\n 'textDocument/semanticTokens/full',\n { textDocument: { uri: doc.uri } },\n )\n if (!result || !Array.isArray(result.data)) return null\n return {\n data: normalizeSemanticData(\n result.data,\n capabilities.semanticTokenTypes ?? [],\n capabilities.semanticTokenModifiers ?? [],\n ),\n resultId: typeof result.resultId === 'string' ? result.resultId : undefined,\n }\n },\n\n async dispose(): Promise<void> {\n disposed = true\n resolveReady?.(false)\n resolveReady = null\n if (client) {\n await client.shutdown().catch(() => {})\n client = null\n }\n if (transport) {\n transport.dispose()\n transport = null\n }\n setPhase('stopped')\n },\n }\n return server\n}\n\n/** 归一化 definition/references 结果(Location | Location[] | LocationLink[])。 */\nfunction normalizeLocations(result: unknown): LspLocation[] {\n if (!Array.isArray(result)) return []\n const out: LspLocation[] = []\n for (const item of result) {\n if (!item || typeof item !== 'object') continue\n const obj = item as { uri?: unknown; range?: unknown; targetUri?: unknown; targetRange?: unknown; targetSelectionRange?: unknown }\n const uri = typeof obj.targetUri === 'string' ? obj.targetUri : typeof obj.uri === 'string' ? obj.uri : ''\n const range = (obj.targetRange ?? obj.range) as { start?: { line?: unknown; character?: unknown }; end?: { line?: unknown; character?: unknown } } | undefined\n if (!uri || !range || !range.start || !range.end) continue\n out.push({\n uri,\n range: {\n start: { line: toInt(range.start.line), character: toInt(range.start.character) },\n end: { line: toInt(range.end.line), character: toInt(range.end.character) },\n },\n })\n }\n return out\n}\n\n/** 归一化 documentSymbol/workspaceSymbol 结果(DocumentSymbol | SymbolInformation)。 */\nfunction normalizeSymbol(item: unknown): LspSymbol | null {\n if (!item || typeof item !== 'object') return null\n const obj = item as {\n name?: unknown\n kind?: unknown\n detail?: unknown\n containerName?: unknown\n range?: { start?: unknown; end?: unknown }\n selectionRange?: { start?: unknown; end?: unknown }\n children?: unknown\n location?: { uri?: unknown; range?: unknown }\n }\n if (typeof obj.name !== 'string') return null\n const selection = obj.selectionRange ?? (obj.location && (obj.location as { range?: unknown }).range)\n const range = obj.range ?? selection\n if (!range || typeof range !== 'object') return null\n const r = range as { start?: { line?: unknown; character?: unknown }; end?: { line?: unknown; character?: unknown } }\n if (!r.start || !r.end) return null\n const symbol: LspSymbol = {\n name: obj.name,\n kind: toInt(obj.kind),\n range: { start: { line: toInt((r.start as { line?: unknown }).line), character: toInt((r.start as { character?: unknown }).character) }, end: { line: toInt((r.end as { line?: unknown }).line), character: toInt((r.end as { character?: unknown }).character) } },\n selectionRange: selection\n ? { start: { line: toInt(((selection as { start?: { line?: unknown } }).start as { line?: unknown } | undefined)?.line ?? toInt((r.start as { line?: unknown }).line)), character: toInt(((selection as { start?: { character?: unknown } }).start as { character?: unknown } | undefined)?.character ?? toInt((r.start as { character?: unknown }).character)) }, end: { line: toInt(((selection as { end?: { line?: unknown } }).end as { line?: unknown } | undefined)?.line ?? toInt((r.end as { line?: unknown }).line)), character: toInt(((selection as { end?: { character?: unknown } }).end as { character?: unknown } | undefined)?.character ?? toInt((r.end as { character?: unknown }).character)) } }\n : { start: { line: toInt((r.start as { line?: unknown }).line), character: toInt((r.start as { character?: unknown }).character) }, end: { line: toInt((r.end as { line?: unknown }).line), character: toInt((r.end as { character?: unknown }).character) } },\n }\n if (typeof obj.detail === 'string' && obj.detail) symbol.detail = obj.detail\n if (typeof obj.containerName === 'string' && obj.containerName) symbol.containerName = obj.containerName\n if (Array.isArray(obj.children)) {\n const kids = obj.children.map(normalizeSymbol).filter((s): s is LspSymbol => s !== null)\n if (kids.length) symbol.children = kids\n }\n return symbol\n}\n\n/** hover contents → 文本行(MarkupContent | MarkedString | MarkedString[])。 */\nfunction stringifyHoverContents(contents: unknown): string[] {\n if (typeof contents === 'string') return [contents]\n if (Array.isArray(contents)) return contents.map(stringifyHoverContents).flat().filter(Boolean)\n if (contents && typeof contents === 'object') {\n const value = (contents as { value?: unknown }).value\n if (typeof value === 'string') return [value]\n }\n return []\n}\n\nfunction toInt(value: unknown): number {\n const n = Number(value)\n return Number.isFinite(n) ? Math.max(0, Math.floor(n)) : 0\n}\n\n/** 把服务器 legend 下的 5 元组流转换为插件固定 legend 下的 5 元组流。 */\nfunction normalizeSemanticData(data: unknown[], types: string[], modifiers: string[]): number[] {\n const out: number[] = []\n let previousLine = 0\n let previousCharacter = 0\n let outputLine = 0\n let outputCharacter = 0\n for (let i = 0; i + 4 < data.length; i += 5) {\n const deltaLine = toInt(data[i])\n const deltaCharacter = toInt(data[i + 1])\n const length = toInt(data[i + 2])\n const sourceType = types[toInt(data[i + 3])] ?? 'variable'\n const sourceModifiers = toInt(data[i + 4])\n const line = previousLine + deltaLine\n const character = deltaLine === 0 ? previousCharacter + deltaCharacter : deltaCharacter\n const typeIndex = Math.max(0, LSP_SEMANTIC_TOKEN_TYPES.indexOf(sourceType as never))\n let modifierBits = 0\n for (let bit = 0; bit < modifiers.length; bit++) {\n if ((sourceModifiers & (1 << bit)) === 0) continue\n const modifier = modifiers[bit]\n const targetBit = LSP_SEMANTIC_TOKEN_MODIFIERS.indexOf(modifier as never)\n if (targetBit >= 0) modifierBits |= 1 << targetBit\n }\n const outputDeltaLine = line - outputLine\n const outputDeltaCharacter = outputDeltaLine === 0 ? character - outputCharacter : character\n out.push(outputDeltaLine, outputDeltaCharacter, length, typeIndex, modifierBits)\n previousLine = line\n previousCharacter = character\n outputLine = line\n outputCharacter = character\n }\n return out\n}\n","/**\n * dsh-vscode-mode host — LSP 服务器管理器。\n * 实例注册表(key=root|languageId,refcount 共享),崩溃退避重启,session/disposed 清理。\n * 作者 ddj 2026-08-27\n */\nimport { createLspServer, type LspServer } from './server.js'\nimport type { LspProviderSpec } from './providers.js'\nimport type { LspServerStatus } from '../shared/lsp.js'\n\ninterface Entry {\n key: string\n server: LspServer\n refs: number\n failures: number\n restartTimer: ReturnType<typeof setTimeout> | null\n}\n\nconst BACKOFF_MS = [1000, 5000, 30000]\nconst MAX_FAILURES = 3\n\nexport interface LspManager {\n /** 获取(或惰性创建)某工作区+语言的服务器;refs+1。 */\n acquire(root: string, languageId: string, resolveSpec: (languageId: string) => LspProviderSpec): LspServer\n /** 释放引用;refs 归零时停止服务器。 */\n release(root: string, languageId: string): void\n /** 释放工作区下全部语言(session/disposed 用)。 */\n releaseRoot(root: string): void\n /** 重置单个工作区语言 server(重新检测 provider 用)。 */\n reset(root: string, languageId: string): void\n /** 重置全部工作区的指定语言 server。 */\n resetLanguage(languageId: string): void\n /** 状态快照。 */\n statusAll(): LspServerStatus[]\n /** 查询已注册的工作区+语言服务器,不增加引用计数。 */\n peek(root: string, languageId: string): LspServer | undefined\n /** 停止并清空全部(卸载/退出)。 */\n disposeAll(): Promise<void>\n /** 监听状态变化(用于 UI)。 */\n onStatusChange: ((status: LspServerStatus) => void) | null\n}\n\n/**\n * 创建 LSP 管理器。\n * @author ddj 2026年08月27号\n * @param logger 诊断日志\n * @returns 管理器\n */\nexport function createLspManager(logger?: (line: string) => void): LspManager {\n const entries = new Map<string, Entry>()\n const keyOf = (root: string, languageId: string): string => root + '|' + languageId\n\n const log = (line: string): void => logger?.('[lsp-manager] ' + line)\n\n /** 同步摘除注册表项并后台回收(refs 归零/工作区清理用;statusAll 立即可见归零)。 */\n const dropEntry = (entry: Entry): void => {\n if (entry.restartTimer) {\n clearTimeout(entry.restartTimer)\n entry.restartTimer = null\n }\n entries.delete(entry.key)\n void entry.server.dispose().catch(() => {})\n }\n\n const scheduleRestart = (entry: Entry): void => {\n if (entry.restartTimer) return\n if (entry.failures >= MAX_FAILURES) {\n log('unavailable after ' + entry.failures + ' failures: ' + entry.key)\n return\n }\n const delay = BACKOFF_MS[Math.min(entry.failures, BACKOFF_MS.length - 1)]\n entry.restartTimer = setTimeout(() => {\n entry.restartTimer = null\n if (!entries.has(entry.key)) return\n void (async () => {\n const ok = await entry.server.start()\n if (!ok) entry.failures++\n else entry.failures = 0\n if (!ok && entries.has(entry.key)) scheduleRestart(entry)\n })()\n }, delay)\n }\n\n const manager: LspManager = {\n acquire(root: string, languageId: string, resolveSpec: (languageId: string) => LspProviderSpec): LspServer {\n const key = keyOf(root, languageId)\n let entry = entries.get(key)\n if (!entry) {\n const spec = resolveSpec(languageId)\n const server = createLspServer(spec, root, languageId, log)\n server.onStateChange = (status) => manager.onStatusChange?.(status)\n entry = { key, server, refs: 0, failures: 0, restartTimer: null }\n entries.set(key, entry)\n // 惰性启动:若 spec ready 才启动,否则保持 idle(供 status 展示 reason)\n if (spec.ready) {\n void server.start().then((ok) => {\n if (!ok && entries.has(key)) entry!.failures++\n })\n }\n }\n entry.refs++\n return entry.server\n },\n\n release(root: string, languageId: string): void {\n const entry = entries.get(keyOf(root, languageId))\n if (!entry) return\n entry.refs = Math.max(0, entry.refs - 1)\n if (entry.refs === 0) dropEntry(entry)\n },\n\n releaseRoot(root: string): void {\n for (const entry of [...entries.values()]) {\n if (entry.server.root === root) dropEntry(entry)\n }\n },\n\n reset(root: string, languageId: string): void {\n const entry = entries.get(keyOf(root, languageId))\n if (entry) dropEntry(entry)\n },\n\n resetLanguage(languageId: string): void {\n for (const entry of [...entries.values()]) {\n if (entry.server.languageId === languageId) dropEntry(entry)\n }\n },\n\n statusAll(): LspServerStatus[] {\n return [...entries.values()].map((entry) => entry.server.status())\n },\n\n peek(root: string, languageId: string): LspServer | undefined {\n return entries.get(keyOf(root, languageId))?.server\n },\n\n async disposeAll(): Promise<void> {\n const list = [...entries.values()]\n entries.clear()\n for (const entry of list) {\n if (entry.restartTimer) clearTimeout(entry.restartTimer)\n await entry.server.dispose()\n }\n },\n\n onStatusChange: null,\n }\n return manager\n}\n","/**\n * dsh-vscode-mode host — 纯 Node ZIP 解压(零依赖,跨平台)。\n * 供 extmgr 解包 VSIX 使用;只实现 VSIX 需要的子集:\n * 读取 EOCD + 中央目录,支持 stored(0)/deflate(8),忽略 zip64(VSIX < 4GB)。\n * 作者 ddj 2026-08-27\n */\nimport { inflateRawSync } from 'node:zlib'\n\n/** 单条解压结果:相对路径 + 内容(目录条目 path 以 / 结尾)。 */\nexport interface ZipEntry {\n path: string\n data: Buffer\n isDirectory: boolean\n}\n\nconst EOCD_SIG = 0x06054b50\nconst CDIR_SIG = 0x02014b50\nconst LHDR_SIG = 0x04034b50\n\n/**\n * 解析 ZIP 缓冲区 → 条目列表(不解压内容,仅元数据)。\n * @author ddj 2026年08月27号\n * @param buf zip 字节\n * @returns 条目元数据\n */\nexport function zipEntries(buf: Buffer): { name: string; method: number; compressed: number; uncompressed: number; localOffset: number }[] {\n const eocd = findEocd(buf)\n if (eocd < 0) throw new Error('不是有效的 ZIP 文件(找不到 EOCD)')\n const total = buf.readUInt16LE(eocd + 10)\n let offset = buf.readUInt32LE(eocd + 16)\n const out: { name: string; method: number; compressed: number; uncompressed: number; localOffset: number }[] = []\n for (let i = 0; i < total; i++) {\n if (buf.readUInt32LE(offset) !== CDIR_SIG) throw new Error('ZIP 中央目录损坏')\n const method = buf.readUInt16LE(offset + 10)\n const compressed = buf.readUInt32LE(offset + 20)\n const uncompressed = buf.readUInt32LE(offset + 24)\n const nameLen = buf.readUInt16LE(offset + 28)\n const extraLen = buf.readUInt16LE(offset + 30)\n const commentLen = buf.readUInt16LE(offset + 32)\n const localOffset = buf.readUInt32LE(offset + 42)\n const name = buf.subarray(offset + 46, offset + 46 + nameLen).toString('utf8')\n out.push({ name, method, compressed, uncompressed, localOffset })\n offset += 46 + nameLen + extraLen + commentLen\n }\n return out\n}\n\n/**\n * 解压 ZIP → 条目列表(目录条目含尾部 /)。\n * @author ddj 2026年08月27号\n * @param buf zip 字节\n * @returns 条目(含内容)\n */\nexport function unzip(buf: Buffer): ZipEntry[] {\n const metas = zipEntries(buf)\n const out: ZipEntry[] = []\n for (const meta of metas) {\n const lh = meta.localOffset\n if (buf.readUInt32LE(lh) !== LHDR_SIG) throw new Error('ZIP 本地头损坏:' + meta.name)\n const nameLen = buf.readUInt16LE(lh + 26)\n const extraLen = buf.readUInt16LE(lh + 28)\n const dataStart = lh + 30 + nameLen + extraLen\n const isDir = /\\/$/.test(meta.name)\n let data: Buffer = Buffer.alloc(0)\n if (!isDir && meta.compressed > 0) {\n const raw = buf.subarray(dataStart, dataStart + meta.compressed)\n data = meta.method === 8 ? Buffer.from(inflateRawSync(raw)) : meta.method === 0 ? Buffer.from(raw) : Buffer.alloc(0)\n }\n out.push({ path: meta.name, data, isDirectory: isDir })\n }\n return out\n}\n\n/** 定位 EOCD(从尾部向前扫,容忍尾部注释)。 */\nfunction findEocd(buf: Buffer): number {\n const maxScan = Math.min(buf.length, 65557)\n for (let i = buf.length - 22; i >= buf.length - maxScan; i--) {\n if (i < 0) break\n if (buf.readUInt32LE(i) === EOCD_SIG) return i\n }\n return -1\n}\n","/**\n * dsh-vscode-mode host — VSIX 扩展管理器(extmgr)。\n * 管理 DSH 专属扩展目录(~/.dsh/dsh-vscode-mode/extensions/),支持:\n * 本地 .vsix 安装、Open VSX 市场搜索/下载安装、卸载、更新检测与安装。\n * 已装扩展作为 LSP provider 的\"扩展源\"(kind=extension),见 providers.ts。\n * 作者 ddj 2026-08-27\n */\nimport { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { unzip } from './zip.js'\nimport { dshHome, PLUGIN_ID } from '../paths.js'\n\n/** 单个已装扩展信息(edrv.lsp.ext.list 载荷元素)。 */\nexport interface ExtInfo {\n id: string // publisher.name\n namespace: string\n name: string\n version: string\n displayName?: string\n description?: string\n dirName: string // 目录名 publisher.name-version\n dir: string // 绝对路径\n}\n\n/** Open VSX 市场搜索结果(edrv.lsp.ext.market 载荷元素)。 */\nexport interface MarketItem {\n namespace: string\n name: string\n id: string\n version: string\n displayName?: string\n description?: string\n download?: string\n}\n\nconst OPEN_VSX = 'https://open-vsx.org'\nconst META_FILE = 'package.json'\n/** 当前平台(与 VSCode platform 命名对齐:win32-x64/darwin-arm64/linux-x64)。 */\nconst PLATFORM = (() => {\n if (process.platform === 'win32') return process.arch === 'arm64' ? 'win32-arm64' : 'win32-x64'\n if (process.platform === 'darwin') return process.arch === 'arm64' ? 'darwin-arm64' : 'darwin-x64'\n return process.arch === 'arm64' ? 'linux-arm64' : 'linux-x64'\n})()\n\n/** DSH 专属扩展目录。 */\nexport function extensionsRoot(home = dshHome()): string {\n return join(home, PLUGIN_ID, 'extensions')\n}\n\n/** 从 VSIX 字节里读 extension/package.json 清单。 */\nexport function vsixManifest(vsix: Buffer): Record<string, unknown> {\n for (const entry of unzip(vsix)) {\n if (entry.path === 'extension/package.json' || entry.path === 'extension\\\\package.json') {\n return JSON.parse(entry.data.toString('utf8')) as Record<string, unknown>\n }\n }\n throw new Error('VSIX 缺少 extension/package.json')\n}\n\n/**\n * 解包 VSIX 到目录(仅取 extension/ 子树,剥前缀;返回清单)。\n * @author ddj 2026年08月27号\n * @param vsix vsix 字节\n * @param dest 目标目录(已存在则先清空)\n * @returns 清单对象\n */\nexport function unpackVsix(vsix: Buffer, dest: string): Record<string, unknown> {\n rmSync(dest, { recursive: true, force: true })\n mkdirSync(dest, { recursive: true })\n let manifest: Record<string, unknown> | null = null\n for (const entry of unzip(vsix)) {\n const rel = entry.path.replace(/^extension[\\\\/]/, '')\n if (!rel || entry.path.startsWith('..')) continue\n const safe = rel.split(/[\\\\/]/).filter((part) => part && part !== '..' && part !== '.').join('/')\n if (!safe) continue\n const target = join(dest, ...safe.split('/'))\n if (entry.isDirectory) {\n mkdirSync(target, { recursive: true })\n continue\n }\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, entry.data)\n if (rel === 'package.json') manifest = JSON.parse(entry.data.toString('utf8')) as Record<string, unknown>\n }\n if (!manifest) throw new Error('VSIX 解包后缺少 package.json')\n return manifest\n}\n\n/** 扩展信息(清单 + 目录)。 */\nexport function extInfoOf(manifest: Record<string, unknown>, dir: string): ExtInfo {\n const namespace = String(manifest.publisher ?? 'unknown')\n const name = String(manifest.name ?? 'unknown')\n const version = String(manifest.version ?? '0.0.0')\n return {\n id: namespace + '.' + name,\n namespace,\n name,\n version,\n displayName: typeof manifest.displayName === 'string' ? manifest.displayName : undefined,\n description: typeof manifest.description === 'string' ? manifest.description : undefined,\n dirName: basename(dir),\n dir,\n }\n}\n\n/** 安装本地 .vsix 文件(已存在同 id 则升级替换)。 */\nexport async function installVsixFile(vsixPath: string, home = dshHome()): Promise<ExtInfo> {\n const vsix = readFileSync(vsixPath)\n return installVsixBuffer(vsix, home)\n}\n\n/** 安装 VSIX 字节(解包进 extensionsRoot;同名旧版本先清)。 */\nexport function installVsixBuffer(vsix: Buffer, home = dshHome()): ExtInfo {\n const manifest = vsixManifest(vsix)\n const info = extInfoOf(manifest, '')\n const target = join(extensionsRoot(home), info.id + '-' + info.version)\n const unpacked = unpackVsix(vsix, target)\n return extInfoOf(unpacked, target)\n}\n/** 扫描已装扩展目录。 */\nexport function listInstalled(home = dshHome()): ExtInfo[] {\n const root = extensionsRoot(home)\n if (!existsSync(root)) return []\n const out: ExtInfo[] = []\n for (const dir of readdirSync(root)) {\n const full = join(root, dir)\n const meta = join(full, META_FILE)\n if (!existsSync(meta)) continue\n try {\n const manifest = JSON.parse(readFileSync(meta, 'utf8')) as Record<string, unknown>\n out.push(extInfoOf(manifest, full))\n } catch (error) {\n /* 坏清单目录跳过 */\n }\n }\n return out\n}\n\n/** 卸载扩展(按 id)。 */\nexport function uninstall(id: string, home = dshHome()): boolean {\n const target = listInstalled(home).find((e) => e.id === id)?.dir\n if (!target) return false\n rmSync(target, { recursive: true, force: true })\n return true\n}\n\n/** Open VSX 单扩展元数据(latest + 下载 URL)。 */\nexport async function marketGet(namespace: string, name: string, version?: string): Promise<Record<string, unknown> | null> {\n const path = version ? namespace + '/' + name + '/' + version : namespace + '/' + name\n const res = await fetch(OPEN_VSX + '/api/' + path, { headers: { accept: 'application/json' } })\n if (!res.ok) return null\n return (await res.json()) as Record<string, unknown>\n}\n\n/** Open VSX 搜索。 */\nexport async function marketSearch(query: string, size = 12): Promise<MarketItem[]> {\n const url = OPEN_VSX + '/api/-/search?query=' + encodeURIComponent(query) + '&size=' + size\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error('市场搜索失败:HTTP ' + res.status)\n const data = (await res.json()) as { extensions?: unknown[] }\n return ((data.extensions ?? []) as Record<string, unknown>[]).map((item) => ({\n namespace: String(item.namespace ?? ''),\n name: String(item.name ?? ''),\n id: String(item.namespace ?? '') + '.' + String(item.name ?? ''),\n version: String(item.version ?? ''),\n displayName: typeof item.displayName === 'string' ? item.displayName : undefined,\n description: typeof item.description === 'string' ? item.description : undefined,\n download: typeof (item.files as { download?: unknown } | undefined)?.download === 'string' ? (item.files as { download: string }).download : undefined,\n }))\n}\n\n/** 平台匹配的 VSIX 下载 URL(探测平台变体,失败回退 API 默认)。 */\nexport async function resolveDownload(namespace: string, name: string, version: string): Promise<string> {\n const candidate = OPEN_VSX + '/api/' + namespace + '/' + name + '/' + PLATFORM + '/' + version +\n '/file/' + namespace + '.' + name + '-' + version + '@' + PLATFORM + '.vsix'\n try {\n const head = await fetch(candidate, { method: 'HEAD' })\n if (head.ok) return candidate\n } catch (error) {\n /* 探测失败走默认 */\n }\n const meta = await marketGet(namespace, name, version)\n const download = (meta?.files as { download?: unknown } | undefined)?.download\n if (typeof download === 'string') return download\n throw new Error('市场未提供 ' + namespace + '.' + name + '@' + version + ' 的下载地址')\n}\n\n/** 从 Open VSX 安装/更新扩展。 */\nexport async function installFromMarket(namespace: string, name: string, version?: string): Promise<ExtInfo> {\n const meta = await marketGet(namespace, name, version)\n if (!meta) throw new Error('市场找不到 ' + namespace + '.' + name + (version ? '@' + version : ''))\n const ver = version ?? String(meta.version ?? '')\n const url = await resolveDownload(namespace, name, ver)\n const res = await fetch(url)\n if (!res.ok) throw new Error('下载失败:HTTP ' + res.status)\n const vsix = Buffer.from(await res.arrayBuffer())\n return installVsixBuffer(vsix)\n}\n\n/** 更新已装扩展(对比市场最新版;返回 null 表示已最新)。 */\nexport async function updateExtension(id: string): Promise<ExtInfo | null> {\n const installed = listInstalled().find((e) => e.id === id)\n if (!installed) throw new Error('扩展未安装:' + id)\n const meta = await marketGet(installed.namespace, installed.name)\n const latest = String(meta?.version ?? '')\n if (!latest || latest === installed.version) return null\n return installFromMarket(installed.namespace, installed.name, latest)\n}\n","/**\n * dsh-vscode-mode host — 语言服务器 provider 解析。\n * 优先级:手动配置 > extmgr 扩展源(Phase 2 挂载) > 自动发现(~/.vscode/extensions、\n * ~/.dsh/dsh-vscode-mode/extensions、PATH)。C# 自动发现覆盖 ms-dotnettools.csharp\n * (Roslyn/OmniSharp)与 DotRush(自带 DotRush.dll 服务器,需对应 .NET 运行时)。\n * 产物 LspProviderSpec:{ ready, argv, cwd, reason },供 manager 启动服务器。\n * 作者 ddj 2026-08-27\n */\nimport { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, rmSync, type Dirent } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join, sep } from 'node:path'\nimport { isAbsolute } from 'node:path'\nimport { extensionsRoot } from './extmgr.js'\nimport { dshHome, lspSpecCacheFile } from '../paths.js'\nimport type { LspCandidate } from '../shared/lsp.js'\n\n/** provider 来源标记(与 shared/lsp.ts 的 status.source 一致)。 */\nexport type LspProviderKind = 'extension' | 'discover' | 'manual' | 'none'\n\nexport interface LspProviderSpec {\n languageId: string\n kind: LspProviderKind\n argv: string[]\n cwd?: string\n env?: Record<string, string>\n /** 需自动配置的 .NET 运行时大版本(发现 DotRush 但缺运行时时设置,见 dotnetProvision.ts)。 */\n provisionRuntime?: number\n ready: boolean\n reason?: string\n version?: string\n providerName?: string\n}\n\n/** 语言 → 扩展名(用于判断哪些文件触发该语言服务器)。 */\nexport const LSP_LANG_EXT: Record<string, string[]> = {\n lua: ['lua'],\n csharp: ['cs', 'csx'],\n}\n\n/** 平台目录名(LuaLS/OmniSharp 的 server/bin/<平台>)。 */\nexport function platformServerDir(platform = process.platform): string {\n if (platform === 'win32') return 'Windows'\n if (platform === 'darwin') return 'macOS'\n return 'Linux'\n}\n\n/** exe 后缀(Windows 为 .exe)。 */\nexport function exeSuffix(platform = process.platform): string {\n return platform === 'win32' ? '.exe' : ''\n}\n\n/** 列出目录下匹配前缀的子目录(如 ~/.vscode/extensions/sumneko.lua-*)。 */\nexport function listMatchingDirs(dir: string, prefix: string): string[] {\n if (!existsSync(dir)) return []\n let entries: Dirent[]\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch (error) {\n return []\n }\n return entries.filter((e) => e.isDirectory() && e.name.startsWith(prefix)).map((e) => join(dir, e.name))\n}\n\n/**\n * VSCode 扩展目录(~/.vscode/extensions、~/.vscode-server/extensions + extmgr 目录;无则空数组)。\n * 测试可用 DSH_LSP_EXT_DIRS(平台路径分隔符分隔)完全覆盖扫描列表,避免受真实机器扩展影响。\n * @author ddj 2026年09月03号\n */\nexport function vscodeExtensionsDirs(home = dshHome()): string[] {\n const override = process.env.DSH_LSP_EXT_DIRS\n if (override) {\n return override.split(sep === '\\\\' ? ';' : ':').map((dir) => dir.trim()).filter((dir) => dir && existsSync(dir))\n }\n const userHome = homedir()\n return [\n join(userHome, '.vscode', 'extensions'),\n join(userHome, '.vscode-server', 'extensions'),\n extensionsRoot(home),\n ].filter((dir) => existsSync(dir))\n}\n\n// --region 扩展源 provider 挂载点(extmgr 安装扩展后注册;kind=extension)\n/** 扩展源 provider 注册表:languageId → 启动参数。 */\nconst extProviders = new Map<string, { argv: string[]; cwd?: string; version?: string }>()\n\n/**\n * 注册扩展源 provider(extmgr 安装的 VSIX 扩展调用;覆盖/清除传空 argv 可注销)。\n * @author ddj 2026年08月27号\n * @param languageId 语言 id\n * @param argv 启动参数(argv[0] 为可执行)\n * @param cwd 工作目录\n * @param version 扩展版本(诊断展示)\n */\nexport function registerExtensionProvider(languageId: string, argv: string[], cwd?: string, version?: string): void {\n if (!argv.length) {\n extProviders.delete(languageId)\n return\n }\n extProviders.set(languageId, { argv, cwd, version })\n}\n\n/** 取扩展源 provider spec(未注册返回 null)。 */\nexport function extensionProviderFor(languageId: string): LspProviderSpec | null {\n const p = extProviders.get(languageId)\n if (!p || !p.argv.length) return null\n return { languageId, kind: 'extension', argv: p.argv, cwd: p.cwd, ready: true, version: p.version, providerName: '语言服务器扩展' }\n}\n\n/** 清空全部扩展源注册(插件卸载/扩展目录重建时)。 */\nexport function clearExtensionProviders(): void {\n extProviders.clear()\n}\n// --endregion\n\n/** PATH 中查找可执行文件(不含扩展名校验,交由 spawn 报错)。 */\nexport function findInPath(name: string): string | null {\n const pathEnv = process.env.PATH ?? ''\n const exts = process.platform === 'win32' ? ['', '.exe', '.cmd', '.bat'] : ['']\n for (const dir of pathEnv.split(sep === '\\\\' ? ';' : ':')) {\n if (!dir) continue\n for (const ext of exts) {\n const candidate = join(dir, name + ext)\n if (existsSync(candidate)) return candidate\n }\n }\n return null\n}\n\n/** dotnet 候选(PATH 命中 + 常见安装路径 + 用户级安装位置),仅保留真实存在者。 */\nexport function dotnetCandidates(): string[] {\n const localAppData = process.env.LOCALAPPDATA\n const out = [\n findInPath('dotnet'),\n 'C:/Program Files/dotnet/dotnet.exe',\n 'C:/Program Files (x86)/dotnet/dotnet.exe',\n localAppData ? join(localAppData, 'Microsoft', 'dotnet', 'dotnet.exe') : null,\n ]\n return out.filter((p): p is string => !!p && existsSync(p))\n}\n\n/** 查找 dotnet(PATH + 常见安装路径)。 */\nexport function findDotnet(): string | null {\n return dotnetCandidates()[0] ?? null\n}\n\n/**\n * 查找具备指定 .NET 运行时大版本的 dotnet(按 dotnetCandidates 顺序探测)。\n * @author ddj 2026年09月03号\n * @param minMajor 运行时最低大版本(如 10)\n * @param candidates dotnet 候选路径(缺省 dotnetCandidates();测试可注入)\n * @returns 满足条件的 dotnet 路径;无满足者返回 null\n */\nexport function dotnetWithRuntime(minMajor: number, candidates: string[] = dotnetCandidates()): string | null {\n for (const dotnet of candidates) {\n const sharedDir = join(dirname(dotnet), 'shared', 'Microsoft.NETCore.App')\n let versions: string[] = []\n try {\n versions = readdirSync(sharedDir)\n } catch (error) {\n continue\n }\n const found = versions.some((name) => {\n const major = Number.parseInt(name.split('.')[0] ?? '', 10)\n return Number.isInteger(major) && major >= minMajor\n })\n if (found) return dotnet\n }\n return null\n}\n\n/**\n * 探测含 .NET SDK 的 dotnet 根目录(MSBuild 工程求值与 restore 需要,runtime-only 不够)。\n * @author ddj 2026年09月03号\n * @param candidates dotnet 候选路径(缺省 dotnetCandidates();测试可注入)\n * @returns 含 SDK 的 dotnet 根目录;无则 null\n */\nexport function findSdkRoot(candidates: string[] = dotnetCandidates()): string | null {\n for (const dotnet of candidates) {\n const root = dirname(dotnet)\n if (sdkVersionOf(root)) return root\n }\n return null\n}\n\n/**\n * dotnet 根目录下最新 SDK 版本号(无 SDK 返回 null)。\n * @author ddj 2026年09月03号\n * @param root dotnet 根目录\n * @returns SDK 版本号\n */\nexport function sdkVersionOf(root: string): string | null {\n try {\n const versions = readdirSync(join(root, 'sdk')).filter((name) => /^\\d+\\.\\d+/.test(name))\n if (!versions.length) return null\n return versions.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }))[0] ?? null\n } catch (error) {\n return null\n }\n}\n\n/**\n * C# 服务器所需的 MSBuild 环境变量(SDK 解析 + restore 的 muxer 定位)。\n * @author ddj 2026年09月03号\n * @param sdkRoot 含 SDK 的 dotnet 根目录\n * @returns 环境变量表\n */\nexport function sdkEnvOf(sdkRoot: string): Record<string, string> {\n const version = sdkVersionOf(sdkRoot)\n const env: Record<string, string> = {\n DOTNET_ROOT: sdkRoot,\n DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR: sdkRoot,\n }\n if (version) env.DOTNET_SDK_PATH = join(sdkRoot, 'sdk', version)\n return env\n}\n\n/** 读扩展目录 package.json 的 version(读取失败不影响入口使用,返回 undefined)。 */\nfunction manifestVersionOf(extDir: string): string | undefined {\n try {\n const manifest = JSON.parse(readFileSync(join(extDir, 'package.json'), 'utf8')) as { version?: unknown }\n return typeof manifest.version === 'string' ? manifest.version : undefined\n } catch (error) {\n return undefined\n }\n}\n\n/** EmmyLua 自动发现候选(tangzx.emmylua-* / server/emmylua_ls)。 */\nexport function candidateEmmyLua(home = dshHome()): { path: string; version?: string } | null {\n const candidates: { path: string; version?: string }[] = []\n for (const dir of vscodeExtensionsDirs(home)) {\n for (const extDir of listMatchingDirs(dir, 'tangzx.emmylua-')) {\n const server = join(extDir, 'server', 'emmylua_ls' + exeSuffix())\n if (!existsSync(server)) continue\n candidates.push({ path: server, version: manifestVersionOf(extDir) })\n }\n }\n candidates.sort((a, b) => (b.version ?? '').localeCompare(a.version ?? '', undefined, { numeric: true }) || a.path.localeCompare(b.path))\n return candidates[0] ?? null\n}\n\n/**\n * LuaLS 自动发现候选(VSCode 扩展目录 + extmgr 目录下 sumneko.lua-* 的 server/bin 可执行)。\n * 多版本并存时按清单版本降序、路径升序排序(与 EmmyLua/DotRush 发现的排序策略一致)。\n * @author ddj 2026年09月03号\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns 排序后的候选列表(首个为建议选用者)\n */\nexport function candidateLuaServers(home = dshHome()): { path: string; version?: string }[] {\n const plat = platformServerDir()\n const suffix = exeSuffix()\n const out: { path: string; version?: string }[] = []\n for (const dir of vscodeExtensionsDirs(home)) {\n for (const extDir of listMatchingDirs(dir, 'sumneko.lua-')) {\n const binDir = join(extDir, 'server', 'bin')\n const binName = 'lua-language-server' + suffix\n // 新布局(3.x 平台变体 vsix):server/bin/xxx.exe;旧布局:server/bin/<平台>/xxx.exe\n const bin = existsSync(join(binDir, binName)) ? join(binDir, binName) : join(binDir, plat, binName)\n if (existsSync(bin) && !out.some((c) => c.path === bin)) out.push({ path: bin, version: manifestVersionOf(extDir) })\n }\n }\n return out.sort((a, b) => (b.version ?? '').localeCompare(a.version ?? '', undefined, { numeric: true }) || a.path.localeCompare(b.path))\n}\n\n/** C# 服务器发现结果(ms-Roslyn / DotRush / OmniSharp + 系统 dotnet;各取清单版本最高者)。 */\nexport interface CSharpCandidates {\n roslynDll?: string\n roslynVersion?: string\n dotrushDll?: string\n dotrushVersion?: string\n omnisharpExe?: string\n dotnet?: string\n}\n\n/**\n * C# 自动发现候选:ms-dotnettools.csharp 的 Roslyn dll(需 dotnet)/ OmniSharp 可执行,\n * 以及 DotRush 扩展自带服务器(extension/bin/LanguageServer/DotRush.dll,需对应 .NET 运行时)。\n * 同类多版本并存时取清单版本最高者(与 EmmyLua/DotRush 发现的排序策略一致)。\n * @author ddj 2026年09月03号\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns 发现结果\n */\nexport function candidateCSharpServers(home = dshHome()): CSharpCandidates {\n const out: CSharpCandidates = {}\n /** 命中收集 → 清单版本降序取最高(平级按路径稳定排序)。 */\n const bestOf = (hits: { entry: string; version?: string }[]): { entry: string; version?: string } | null =>\n hits.sort((a, b) => (b.version ?? '').localeCompare(a.version ?? '', undefined, { numeric: true }) || a.entry.localeCompare(b.entry))[0] ?? null\n const roslynHits: { entry: string; version?: string }[] = []\n const omniHits: { entry: string; version?: string }[] = []\n const dotrushHits: { entry: string; version?: string }[] = []\n for (const dir of vscodeExtensionsDirs(home)) {\n for (const extDir of listMatchingDirs(dir, 'ms-dotnettools.csharp-')) {\n const version = manifestVersionOf(extDir)\n const roslyn = join(extDir, '.roslyn', 'Microsoft.CodeAnalysis.LanguageServer.dll')\n if (existsSync(roslyn)) roslynHits.push({ entry: roslyn, version })\n const omni = join(extDir, '.omnisharp', 'OmniSharp' + exeSuffix())\n if (existsSync(omni)) omniHits.push({ entry: omni, version })\n }\n for (const extDir of listMatchingDirs(dir, 'nromanov.dotrush-')) {\n const dll = join(extDir, 'extension', 'bin', 'LanguageServer', 'DotRush.dll')\n if (!existsSync(dll)) continue\n dotrushHits.push({ entry: dll, version: manifestVersionOf(extDir) })\n }\n }\n const roslynBest = bestOf(roslynHits)\n if (roslynBest) {\n out.roslynDll = roslynBest.entry\n out.roslynVersion = roslynBest.version\n }\n const omniBest = bestOf(omniHits)\n if (omniBest) out.omnisharpExe = omniBest.entry\n const dotrushBest = bestOf(dotrushHits)\n if (dotrushBest) {\n out.dotrushDll = dotrushBest.entry\n out.dotrushVersion = dotrushBest.version\n }\n const dotnet = findDotnet()\n if (dotnet) out.dotnet = dotnet\n return out\n}\n\n/**\n * 从服务器 dll 同目录的 *.runtimeconfig.json 解析所需 .NET 运行时大版本。\n * @author ddj 2026年09月03号\n * @param dllDir 服务器 dll 所在目录\n * @returns 运行时大版本;无清单或解析失败返回 null\n */\nexport function runtimeMajorOf(dllDir: string): number | null {\n try {\n for (const name of readdirSync(dllDir)) {\n if (!name.endsWith('.runtimeconfig.json')) continue\n const config = JSON.parse(readFileSync(join(dllDir, name), 'utf8')) as { runtimeOptions?: { framework?: { version?: unknown } } }\n const version = config.runtimeOptions?.framework?.version\n if (typeof version !== 'string') continue\n const major = Number.parseInt(version.split('.')[0] ?? '', 10)\n if (Number.isInteger(major)) return major\n }\n } catch (error) { /* 清单读取失败按无约束处理 */ }\n return null\n}\n\n/**\n * 解析 DotRush 启动参数:优先扩展内置 SDK dotnet,否则找满足其运行时大版本的 dotnet。\n * @author ddj 2026年09月03号\n * @param dll DotRush.dll 绝对路径\n * @returns argv 可直接启动;reason 为不可启动的原因\n */\nfunction dotrushLaunch(dll: string): { argv: string[] } | { reason: string } {\n const sdkDotnet = join(dirname(dirname(dll)), 'Sdk', 'dotnet' + exeSuffix())\n const major = runtimeMajorOf(dirname(dll))\n const dotnet = existsSync(sdkDotnet) ? sdkDotnet : major !== null ? dotnetWithRuntime(major) : findDotnet()\n if (dotnet) return { argv: [dotnet, dll] }\n return { reason: 'DotRush 需 .NET ' + (major ?? '') + ' 运行时,未找到满足的 dotnet' }\n}\n\n/**\n * 手动配置归一化:path 指向可执行文件/目录,command 为可执行名(PATH 解析)。\n * 未配置时返回空 reason(由各 resolve 兜底输出语言相关安装指引文案)。\n * @author ddj 2026年08月27号\n */\nexport function manualSpec(manual: { command?: string; path?: string } | undefined): { argv: string[]; cwd?: string; ready: boolean; reason?: string } {\n if (!manual) return { argv: [], ready: false }\n const pathValue = typeof manual.path === 'string' && manual.path.trim() ? manual.path.trim() : ''\n const commandValue = typeof manual.command === 'string' && manual.command.trim() ? manual.command.trim() : ''\n if (!pathValue && !commandValue) return { argv: [], ready: false }\n if (pathValue) {\n if (!existsSync(pathValue)) return { argv: [], ready: false, reason: '路径不存在:' + pathValue }\n return { argv: [pathValue], ready: true }\n }\n const found = findInPath(commandValue)\n if (!found) return { argv: [], ready: false, reason: 'PATH 中找不到命令:' + commandValue }\n return { argv: [found], ready: true }\n}\n\n/**\n * 解析 Lua provider(优先级:手动 > 扩展源 > 自动发现)。\n * @author ddj 2026年08月27号\n * @param manual 手动配置\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns provider 规格\n */\nexport function resolveLuaProvider(manual?: { command?: string; path?: string }, home = dshHome()): LspProviderSpec {\n const base = { languageId: 'lua' }\n const manualResolved = manualSpec(manual)\n if (manualResolved.ready) return { ...base, kind: 'manual', argv: manualResolved.argv, cwd: manualResolved.cwd, ready: true }\n return resolveCached('lua', manual, home, (h) => {\n const ext = extensionProviderFor('lua')\n if (ext) return ext\n const emmy = candidateEmmyLua(h)\n if (emmy) return { ...base, kind: 'extension', argv: [emmy.path], ready: true, version: emmy.version, providerName: 'EmmyLua' }\n const candidates = candidateLuaServers(h)\n const best = candidates[0]\n if (best) return { ...base, kind: 'discover', argv: [best.path], cwd: undefined, ready: true, version: best.version, providerName: 'LuaLS' }\n const inPath = findInPath('lua-language-server' + exeSuffix())\n if (inPath) return { ...base, kind: 'discover', argv: [inPath], ready: true }\n return { ...base, kind: 'none', argv: [], ready: false, reason: manualResolved.reason ?? '未发现 lua-language-server(可安装 LuaLS 或手动指定路径)' }\n })\n}\n\n/**\n * 解析 C# provider(优先级:手动 > 扩展源 > 自动发现;Roslyn dll 需 dotnet;\n * DotRush 需满足其运行时的 dotnet;或 OmniSharp)。\n * @author ddj 2026年08月27号\n * @param manual 手动配置\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns provider 规格\n */\nexport function resolveCSharpProvider(manual?: { command?: string; path?: string }, home = dshHome()): LspProviderSpec {\n const base = { languageId: 'csharp' }\n const manualResolved = manualSpec(manual)\n if (manualResolved.ready) return { ...base, kind: 'manual', argv: manualResolved.argv, cwd: manualResolved.cwd, ready: true }\n return resolveCached('csharp', manual, home, (h) => {\n const ext = extensionProviderFor('csharp')\n if (ext) return ext\n const discovered = candidateCSharpServers(h)\n // SDK 环境注入:runtime-only 的 dotnet 会导致 MSBuild 求值/restore 退化\n const sdkRoot = findSdkRoot()\n const msbuildEnv = sdkRoot ? sdkEnvOf(sdkRoot) : undefined\n if (discovered.roslynDll && discovered.dotnet) {\n return { ...base, kind: 'discover', argv: [discovered.dotnet, discovered.roslynDll, '--stdio'], env: msbuildEnv, ready: true }\n }\n let dotrushReason: string | null = null\n let provisionMajor: number | undefined\n if (discovered.dotrushDll) {\n const major = runtimeMajorOf(dirname(discovered.dotrushDll))\n const launch = dotrushLaunch(discovered.dotrushDll)\n if ('argv' in launch) {\n return { ...base, kind: 'discover', argv: launch.argv, env: msbuildEnv, ready: true, version: discovered.dotrushVersion, providerName: 'DotRush' }\n }\n dotrushReason = launch.reason\n provisionMajor = major ?? undefined\n }\n if (discovered.omnisharpExe) {\n return { ...base, kind: 'discover', argv: [discovered.omnisharpExe, '--stdio'], ready: true }\n }\n const reasons: string[] = []\n if (dotrushReason) {\n reasons.push(dotrushReason)\n } else {\n if (!discovered.dotnet) reasons.push('未找到 dotnet')\n reasons.push('未发现 ms-dotnettools.csharp / DotRush 扩展')\n }\n return { ...base, kind: 'none', argv: [], ready: false, provisionRuntime: provisionMajor, reason: reasons.join(';') + '(可手动指定 Roslyn/OmniSharp 入口)' }\n })\n}\n\n/** 语言 → provider 解析器(可扩展;Phase 2 由 extmgr 注册扩展源 provider)。 */\nexport type ProviderResolver = (manual?: { command?: string; path?: string }) => LspProviderSpec\n\nexport const PROVIDER_RESOLVERS: Record<string, ProviderResolver> = {\n lua: resolveLuaProvider,\n csharp: resolveCSharpProvider,\n}\n\n/**\n * 汇总某语言当前检测到的候选服务器(每类服务器一条、取该类最高版本;设置页展示用)。\n * chosen 以候选路径命中 spec.argv 判定;未选用(kind=none/manual 不匹配)时不标记。\n * @author ddj 2026年09月03号\n * @param languageId 语言 id\n * @param spec 已解析的 provider 规格\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns 候选列表(不支持的语言/检测异常返回空)\n */\nexport function candidatesFor(languageId: string, spec: LspProviderSpec, home = dshHome()): LspCandidate[] {\n /** 候选路径命中 spec.argv 时补 chosen 标记。 */\n const markChosen = (candidate: LspCandidate): LspCandidate =>\n spec.ready && candidate.path && spec.argv.includes(candidate.path) ? { ...candidate, chosen: true } : candidate\n try {\n if (languageId === 'lua') {\n const out: LspCandidate[] = []\n const emmy = candidateEmmyLua(home)\n if (emmy) out.push(markChosen({ name: 'EmmyLua', version: emmy.version, path: emmy.path }))\n const lua = candidateLuaServers(home)[0]\n if (lua) out.push(markChosen({ name: 'LuaLS(sumneko.lua)', version: lua.version, path: lua.path }))\n const inPath = findInPath('lua-language-server' + exeSuffix())\n if (inPath) out.push(markChosen({ name: 'lua-language-server(PATH)', path: inPath }))\n return out\n }\n if (languageId === 'csharp') {\n const out: LspCandidate[] = []\n const found = candidateCSharpServers(home)\n if (found.roslynDll) out.push(markChosen({ name: 'Roslyn(ms-dotnettools.csharp)', version: found.roslynVersion, path: found.roslynDll }))\n if (found.dotrushDll) out.push(markChosen({ name: 'DotRush', version: found.dotrushVersion, path: found.dotrushDll }))\n if (found.omnisharpExe) out.push(markChosen({ name: 'OmniSharp', path: found.omnisharpExe }))\n return out\n }\n return []\n } catch (error) {\n return []\n }\n}\n\n/** 手动配置是否为绝对路径可执行(供设置页判断输入类型)。 */\nexport function looksAbsolute(value: string): boolean {\n return isAbsolute(value)\n}\n\n// --region provider 发现结果缓存(进程级 + 磁盘持久化)\n/**\n * 发现结果缓存:只缓存\"自动发现/扩展源\"结论,不缓存 manual(用户改配置要立即生效)。\n * 进程内 Map 命中优先;未命中读磁盘缓存(跨会话/跨重启共享);仍无才真扫描。\n * 缓存条目按\"配置签名 + 扩展目录指纹\"校验,任一变化即失效重扫。\n * 作者 ddj 2026年08月28号\n */\n\n/** 缓存条目:spec + 生成时的环境指纹。 */\ninterface SpecCacheEntry {\n spec: LspProviderSpec\n fingerprint: string\n at: number\n}\n\n/** 进程级缓存(home|languageId → 条目),同一 DSH home 的不同会话共享。 */\nconst specCache = new Map<string, SpecCacheEntry>()\n/** 磁盘缓存是否已载入本进程(home → loaded),不同 profile 不串缓存。 */\nconst diskLoaded = new Set<string>()\n/** 自动发现成功结果的复用时长;过期后才检查目录指纹。 */\nconst SPEC_CACHE_TTL_MS = 30 * 60 * 1000\n/** 未发现结果的短缓存时长,避免缺失服务器时反复扫描 PATH。 */\nconst SPEC_NEGATIVE_CACHE_MS = 60 * 1000\n\n/** 生成带 home 的缓存键,避免不同 profile 的 provider 结果串用。 */\nfunction cacheEntryKey(home: string, languageId: string): string {\n return home + '|' + languageId\n}\n\n/**\n * 构造缓存 key:语言 + 手动配置(manual 结果不缓存,故只参与\"是否走缓存\"判定)。\n * @author ddj 2026年08月28号\n * @param languageId 语言 id\n * @param manual 手动配置\n * @returns 缓存 key(manual 有效时返回空串表示跳过缓存)\n */\nfunction cacheKeyOf(languageId: string, manual?: { command?: string; path?: string }): string {\n const pathValue = manual?.path?.trim() ?? ''\n const commandValue = manual?.command?.trim() ?? ''\n if (pathValue || commandValue) return '' // 手动配置:不缓存,立即生效\n return languageId\n}\n\n/**\n * 环境指纹:扩展目录清单 + 平台。目录增删/换平台即失效(防缓存陈旧指向已删扩展)。\n * @author ddj 2026年08月28号\n * @param home DSH home\n * @returns 指纹串\n */\nfunction fingerprintOf(home: string): string {\n const dirs = vscodeExtensionsDirs(home)\n const marks = dirs.map((dir) => {\n try {\n return readdirSync(dir).sort().join(',')\n } catch (error) {\n return '?'\n }\n })\n return process.platform + '|' + (findSdkRoot() ?? 'no-sdk') + '|' + marks.join('|')\n}\n\n/**\n * 读取磁盘缓存(幂等:每进程只载一次;schema 文件名已隔离版本)。\n * @author ddj 2026年08月28号\n * @param home DSH home\n */\nfunction loadDiskCache(home: string): void {\n if (diskLoaded.has(home)) return\n diskLoaded.add(home)\n const file = lspSpecCacheFile(home)\n try {\n const raw = JSON.parse(readFileSync(file, 'utf8')) as Record<string, SpecCacheEntry>\n for (const [languageId, entry] of Object.entries(raw)) {\n if (entry && typeof entry === 'object' && entry.spec && typeof entry.fingerprint === 'string') {\n specCache.set(cacheEntryKey(home, languageId), entry)\n }\n }\n } catch (error) { /* 首次运行/损坏:静默降级为真扫描 */ }\n}\n\n/**\n * 写回磁盘缓存(best-effort;写失败不影响本次解析结果)。\n * @author ddj 2026年08月28号\n * @param home DSH home\n */\nfunction saveDiskCache(home: string): void {\n const file = lspSpecCacheFile(home)\n try {\n mkdirSync(dirname(file), { recursive: true })\n const out: Record<string, SpecCacheEntry> = {}\n const prefix = home + '|'\n for (const [key, entry] of specCache) if (key.startsWith(prefix)) out[key.slice(prefix.length)] = entry\n writeFileSync(file, JSON.stringify(out), 'utf8')\n } catch (error) { /* 写入失败静默 */ }\n}\n\n/**\n * 带缓存执行 provider 解析(自动发现路径专用)。\n * @author ddj 2026年08月28号\n * @param languageId 语言 id\n * @param manual 手动配置\n * @param home DSH home\n * @param resolve 真解析函数(未命中时调用)\n * @returns provider 规格\n */\nfunction resolveCached(\n languageId: string,\n manual: { command?: string; path?: string } | undefined,\n home: string,\n resolve: (h: string) => LspProviderSpec,\n): LspProviderSpec {\n const key = cacheKeyOf(languageId, manual)\n if (!key) return resolve(home) // 手动配置:不走缓存\n loadDiskCache(home)\n const fullKey = cacheEntryKey(home, key)\n const hit = specCache.get(fullKey)\n if (hit && isCacheFresh(hit)) return hit.spec\n const fingerprint = fingerprintOf(home)\n if (hit && hit.fingerprint === fingerprint) {\n hit.at = Date.now()\n return hit.spec\n }\n const spec = resolve(home)\n specCache.set(fullKey, { spec, fingerprint, at: Date.now() })\n saveDiskCache(home)\n return spec\n}\n\n/** 判断缓存条目是否仍可直接复用,不触发扩展目录扫描。 */\nfunction isCacheFresh(entry: SpecCacheEntry): boolean {\n const age = Date.now() - entry.at\n const ttl = entry.spec.kind === 'none' ? SPEC_NEGATIVE_CACHE_MS : SPEC_CACHE_TTL_MS\n if (age < 0 || age >= ttl) return false\n const executable = entry.spec.argv[0]\n return !entry.spec.ready || !executable || existsSync(executable)\n}\n\n/**\n * 清空 provider 发现缓存(扩展安装/卸载、配置变更后调用;进程级 + 删磁盘文件)。\n * @author ddj 2026年08月28号\n * @param home DSH home(缺省真实)\n */\nexport function clearProviderCache(home = dshHome()): void {\n const prefix = home + '|'\n for (const key of specCache.keys()) if (key.startsWith(prefix)) specCache.delete(key)\n diskLoaded.delete(home)\n try {\n rmSync(lspSpecCacheFile(home), { force: true })\n } catch (error) { /* 删除失败静默 */ }\n}\n// --endregion\n","/**\n * dsh-vscode-mode host — C# 服务器 .NET 运行时自动配置。\n * DotRush 等服务器需要 .NET 运行时;缺失时从官方 release 元数据解析下载地址,\n * sha512 校验后解压到用户级 dotnet 目录(win: %LOCALAPPDATA%\\Microsoft\\dotnet,\n * unix: ~/.dotnet),成功后通知监听者重载 provider——用户零手动操作。\n * 失败静默降级(保留原 reason 文案),10 分钟退避重试。\n * 安装全程有状态机(envInstallStates)供设置页一键安装与进度轮询使用。\n * 作者 ddj 2026年09月03号\n */\nimport { spawn } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { dotnetWithRuntime } from './providers.js'\nimport type { LspEnvInstallState } from '../shared/lsp.js'\nimport { unzip } from './zip.js'\n\n/** release 元数据 files 元素子集(官方 releases.json)。 */\nexport interface RuntimeAsset {\n name: string\n url: string\n hash: string\n}\n\nconst META_BASE = 'https://builds.dotnet.microsoft.com/dotnet/release-metadata'\nconst RETRY_MS = 10 * 60 * 1000\n\n/** 同 major 去重(in-flight)。 */\nconst inFlight = new Map<number, Promise<boolean>>()\n/** 失败时间戳(退避重试)。 */\nconst failedAt = new Map<number, number>()\n/** 配置成功监听者(重载 provider 缓存与服务器)。 */\nconst listeners = new Set<() => void>()\n/** 安装进行态(major → phase/message),供设置页轮询展示。 */\nconst installStates = new Map<number, { phase: LspEnvInstallState['phase']; message?: string }>()\n\n/** 需求 id(与 envRequirements 的 id 一致)。 */\nexport function runtimeRequirementId(major: number): string {\n return 'dotnet-runtime:' + major\n}\n\n/** 当前安装进行态快照(edrv.lsp.envState 载荷)。 */\nexport function envInstallStates(): LspEnvInstallState[] {\n return [...installStates.entries()].map(([major, state]) => ({\n id: runtimeRequirementId(major),\n phase: state.phase,\n message: state.message,\n }))\n}\n\n/** 注册配置成功监听(成功后由 rpc 侧清缓存并重置服务器)。 */\nexport function onRuntimeProvisioned(listener: () => void): void {\n listeners.add(listener)\n}\n\n/** 平台 → 官方运行时资产文件名。 */\nfunction assetNameFor(platform: string, arch: string): string {\n const archPart = arch === 'arm64' ? 'arm64' : 'x64'\n if (platform === 'win32') return 'dotnet-runtime-win-' + archPart + '.zip'\n if (platform === 'darwin') return 'dotnet-runtime-osx-' + archPart + '.tar.gz'\n return 'dotnet-runtime-linux-' + archPart + '.tar.gz'\n}\n\n/** 用户级 dotnet 安装目录(与 providers 的发现候选位置一致)。 */\nexport function userDotnetDir(): string {\n if (process.platform === 'win32') {\n return join(process.env.LOCALAPPDATA ?? join(homedir(), 'AppData', 'Local'), 'Microsoft', 'dotnet')\n }\n return join(homedir(), '.dotnet')\n}\n\n/** 从 release 元数据 files 里挑当前平台资产(纯函数,测试可注入平台)。 */\nexport function pickRuntimeAsset(files: RuntimeAsset[], platform = process.platform, arch = process.arch): RuntimeAsset | null {\n const name = assetNameFor(platform, arch)\n return files.find((f) => f.name === name) ?? null\n}\n\n/** 是否允许自动配置(测试隔离 + 显式开关)。 */\nfunction allowed(): boolean {\n if (process.env.DSH_LSP_AUTO_RUNTIME === '0') return false\n if (process.env.DSH_LSP_EXT_DIRS) return false // 测试环境不下载\n return true\n}\n\nfunction setState(major: number, phase: LspEnvInstallState['phase'], message?: string): void {\n installStates.set(major, { phase, message })\n}\n\nfunction notifyListeners(): void {\n for (const listener of listeners) {\n try {\n listener()\n } catch { /* 单个监听失败不影响其它 */ }\n }\n}\n\n/**\n * 触发运行时自动配置(幂等:同 major 去重;失败 10 分钟退避;已满足则直接成功回调)。\n * 静默自动路径与设置页一键安装共用;进度经 envInstallStates 暴露。\n * @author ddj 2026年09月03号\n * @param major 运行时大版本\n */\nexport function provisionRuntime(major: number): void {\n if (inFlight.has(major)) return\n const failed = failedAt.get(major)\n if (failed && Date.now() - failed < RETRY_MS) return\n const task = runProvision(major)\n .catch(() => false)\n .then((ok) => {\n inFlight.delete(major)\n if (ok) {\n failedAt.delete(major)\n setState(major, 'done')\n notifyListeners()\n } else {\n failedAt.set(major, Date.now())\n setState(major, 'failed')\n }\n return ok\n })\n inFlight.set(major, task)\n}\n\n/**\n * 一键安装入口(设置页按钮):校验允许后触发 provisionRuntime。\n * @author ddj 2026年09月03号\n * @param major 运行时大版本\n * @returns 是否成功启动(已满足/进行中/被禁用时返回 false)\n */\nexport function startEnvInstall(major: number): boolean {\n if (dotnetWithRuntime(major)) {\n setState(major, 'done')\n return false\n }\n if (!allowed() || inFlight.has(major)) return false\n const failed = failedAt.get(major)\n if (failed && Date.now() - failed < RETRY_MS && installStates.get(major)?.phase === 'failed') {\n // 退避期内失败态:允许用户手动重试(清除退避标记)\n failedAt.delete(major)\n }\n provisionRuntime(major)\n return inFlight.has(major)\n}\n\nasync function runProvision(major: number): Promise<boolean> {\n if (dotnetWithRuntime(major)) return true\n setState(major, 'downloading')\n const meta = await fetchJson(META_BASE + '/' + major + '.0/releases.json')\n const release = meta?.releases?.[0]\n const files = release?.runtime?.files\n if (!Array.isArray(files)) return false\n const asset = pickRuntimeAsset(files as RuntimeAsset[])\n if (!asset?.url || !asset.hash) return false\n const buf = await downloadVerified(asset.url, asset.hash)\n if (!buf) return false\n setState(major, 'extracting')\n const dir = userDotnetDir()\n const created = !existsSync(dir)\n try {\n const ok = await extractTo(buf, dir)\n if (!ok) throw new Error('解压失败')\n } catch (error) {\n if (created) rmSync(dir, { recursive: true, force: true })\n return false\n }\n return dotnetWithRuntime(major) !== null\n}\n\n/** 拉取 JSON(30s 超时,失败返回 null)。 */\nasync function fetchJson(url: string): Promise<{ releases?: { runtime?: { files?: unknown } }[] } | null> {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(30000) })\n if (!res.ok) return null\n return await res.json()\n } catch {\n return null\n }\n}\n\n/** 下载并按官方 sha512 校验(5 分钟超时,不匹配返回 null)。 */\nasync function downloadVerified(url: string, sha512: string): Promise<Buffer | null> {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(300000) })\n if (!res.ok) return null\n const buf = Buffer.from(await res.arrayBuffer())\n const actual = createHash('sha512').update(buf).digest('hex').toLowerCase()\n return actual === sha512.toLowerCase() ? buf : null\n } catch {\n return null\n }\n}\n\n/** 解压到目录:win 走 zip(PK 头),unix 落临时包交系统 tar。 */\nasync function extractTo(buf: Buffer, dir: string): Promise<boolean> {\n mkdirSync(dir, { recursive: true })\n if (buf.subarray(0, 2).toString('ascii') === 'PK') {\n for (const entry of unzip(buf)) {\n if (!entry.path || entry.path.startsWith('..')) continue\n const parts = entry.path.split(/[\\\\/]/).filter((p) => p && p !== '..' && p !== '.')\n if (!parts.length) continue\n const target = join(dir, ...parts)\n if (entry.isDirectory) {\n mkdirSync(target, { recursive: true })\n continue\n }\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, entry.data)\n }\n return true\n }\n const tmp = join(tmpdir(), 'dsh-dotnet-' + Date.now() + '.tar.gz')\n try {\n writeFileSync(tmp, buf)\n return await new Promise<boolean>((resolve) => {\n const child = spawn('tar', ['-xzf', tmp, '-C', dir], { stdio: 'ignore' })\n child.on('exit', (code) => resolve(code === 0))\n child.on('error', () => resolve(false))\n })\n } finally {\n rmSync(tmp, { force: true })\n }\n}\n","/**\n * dsh-vscode-mode host — LSP 配置读取与 provider 解析装配。\n * 配置来源优先级:运行时覆盖(设置页保存,重启失效)> 插件组合配置 > 默认。\n * 原 settings section(ns dsh-vscode-mode.languageServers)命名空间不合法\n * (DSH settings 仅允许 /^[a-z][a-z0-9-]*$/,点号命名空间永久不可注册),\n * 已降级为配置值(插件组合配置 + 会话内运行时覆盖),不再尝试 settings 安装。\n * 作者 ddj 2026-08-27 / 2026-09-02\n */\nimport { PROVIDER_RESOLVERS, type LspProviderSpec } from './providers.js'\nimport { provisionRuntime } from './dotnetProvision.js'\n\n/** 单语言配置。 */\nexport interface LspLangConfig {\n enabled?: boolean\n command?: string\n path?: string\n}\n\n/** LSP 配置(按语言)。 */\nexport interface LspConfig {\n lua?: LspLangConfig\n csharp?: LspLangConfig\n [languageId: string]: LspLangConfig | undefined\n}\n\nexport const LSP_LANGUAGES = ['lua', 'csharp'] as const\n\n/** 清洗单语言配置:仅保留合法字段并剥离 undefined(稀疏覆盖语义,清空字段即回落组合配置)。 */\nexport function sanitizeLang(raw: unknown): LspLangConfig | undefined {\n if (!raw || typeof raw !== 'object') return undefined\n const obj = raw as Record<string, unknown>\n const out: LspLangConfig = {}\n if (typeof obj.enabled === 'boolean') out.enabled = obj.enabled\n if (typeof obj.command === 'string') out.command = obj.command\n if (typeof obj.path === 'string') out.path = obj.path\n return out\n}\n\n/** 从插件组合配置读取。 */\nexport function configFromPlugin(config: unknown): LspConfig {\n const raw = (config as { languageServers?: unknown } | undefined)?.languageServers\n if (!raw || typeof raw !== 'object') return {}\n const out: LspConfig = {}\n for (const lang of LSP_LANGUAGES) {\n const v = sanitizeLang((raw as Record<string, unknown>)[lang])\n if (v) out[lang] = v\n }\n return out\n}\n\n/** 合并配置:上层(运行时覆盖/settings)覆盖插件组合配置。 */\nexport function mergeConfig(a: LspConfig, b: LspConfig): LspConfig {\n const out: LspConfig = { ...a }\n for (const lang of LSP_LANGUAGES) {\n const av = a[lang]\n const bv = b[lang]\n if (bv) out[lang] = { ...av, ...bv }\n else if (av) out[lang] = av\n }\n return out\n}\n\n/**\n * 解析某语言的 provider spec(插件组合配置 + 运行时覆盖层合并后)。\n * @author ddj 2026年08月27号 / 2026年09月02号\n * @param pluginConfig 插件组合配置\n * @param languageId 语言 id\n * @param override 运行时覆盖层(设置页保存值,重启失效;缺省为空)\n * @returns provider 规格\n */\nexport function resolveProviderSpec(pluginConfig: unknown, languageId: string, override?: LspConfig): LspProviderSpec {\n const resolver = PROVIDER_RESOLVERS[languageId]\n if (!resolver) return { languageId, kind: 'none', argv: [], ready: false, reason: '不支持的语言:' + languageId }\n const merged = mergeConfig(configFromPlugin(pluginConfig), override ?? {})\n const lang = merged[languageId]\n if (lang && lang.enabled === false) {\n return { languageId, kind: 'none', argv: [], ready: false, reason: '已在设置中禁用' }\n }\n const spec = resolver({ command: lang?.command, path: lang?.path })\n // DotRush 缺运行时:后台自动下载官方 .NET runtime(用户零操作),完成后经监听者重载\n if (spec.provisionRuntime) provisionRuntime(spec.provisionRuntime)\n return spec\n}\n\n/** 语言 → 扩展名(供客户端判断是否触发 LSP)。 */\nexport function langOfPath(path: string): string | null {\n const base = String(path || '').split(/[\\\\/]/).pop() || ''\n const dot = base.lastIndexOf('.')\n if (dot <= 0) return null\n const ext = base.slice(dot + 1).toLowerCase()\n for (const [lang, exts] of Object.entries({ lua: ['lua'], csharp: ['cs', 'csx'] })) {\n if (exts.includes(ext)) return lang\n }\n return null\n}\n","/**\n * dsh-vscode-mode host — LSP 环境需求检测注册表。\n * 每个语言注册一个检测器:扫描当前环境,返回未满足的需求清单(含一键安装与官网链接信息)。\n * 新接入 LSP:在 CHECKERS 加一个检测器条目;需要内置安装器时在 INSTALLERS 注册同前缀安装函数。\n * 检测在 status/redetect/configUpdate 时执行(不缓存),保证安装完成后状态即时刷新。\n * 作者 ddj 2026年09月03号\n */\nimport { dirname } from 'node:path'\nimport { candidateCSharpServers, dotnetWithRuntime, runtimeMajorOf } from './providers.js'\nimport { startEnvInstall } from './dotnetProvision.js'\nimport type { LspMissingEnv } from '../shared/lsp.js'\n\n/** dotnet 运行时需求构造(DotRush / ms-Roslyn 共用)。 */\nfunction dotnetRuntimeRequirement(major: number, detail: string): LspMissingEnv {\n return {\n id: 'dotnet-runtime:' + major,\n label: '.NET 运行时 ' + major + '.0',\n detail,\n installable: true,\n manualUrl: 'https://dotnet.microsoft.com/download/dotnet/' + major + '.0',\n manualLabel: '官网下载',\n }\n}\n\n/** csharp 检测器:DotRush 缺运行时 / ms-Roslyn 缺 dotnet。 */\nfunction checkCSharp(home: string): LspMissingEnv[] {\n const found = candidateCSharpServers(home)\n const missing: LspMissingEnv[] = []\n if (found.dotrushDll) {\n const major = runtimeMajorOf(dirname(found.dotrushDll))\n if (major !== null && dotnetWithRuntime(major) === null) {\n missing.push(dotnetRuntimeRequirement(major, 'DotRush 语言服务器运行所需'))\n }\n return missing\n }\n if (found.roslynDll && !found.dotnet) {\n // 官方 Roslyn 服务器分支未实测,保守按 LTS 8 基线提示\n missing.push(dotnetRuntimeRequirement(8, 'Roslyn 语言服务器运行所需'))\n }\n return missing\n}\n\n/** lua 检测器:EmmyLua/LuaLS 自带运行时,无外部依赖。 */\nfunction checkLua(): LspMissingEnv[] {\n return []\n}\n\n/** 检测器注册表(按 languageId;新 LSP 在此加条目即可)。 */\nconst CHECKERS: Record<string, (home: string) => LspMissingEnv[]> = {\n lua: checkLua,\n csharp: checkCSharp,\n}\n\n/** 安装器注册表(按需求 id 前缀匹配;新依赖类型在此加条目)。 */\nconst INSTALLERS: { prefix: string; run: (id: string) => boolean }[] = [\n {\n prefix: 'dotnet-runtime:',\n run: (id) => {\n const major = Number.parseInt(id.slice('dotnet-runtime:'.length), 10)\n return Number.isInteger(major) ? startEnvInstall(major) : false\n },\n },\n]\n\n/**\n * 检测某语言未满足的环境需求(仅返回缺失项;检测器异常按无需求处理)。\n * @author ddj 2026年09月03号\n * @param languageId 语言 id\n * @param home DSH home(测试可注入临时目录)\n * @returns 缺失需求清单\n */\nexport function envRequirementsFor(languageId: string, home: string): LspMissingEnv[] {\n const checker = CHECKERS[languageId]\n if (!checker) return []\n try {\n return checker(home)\n } catch {\n return []\n }\n}\n\n/**\n * 尝试一键安装某条需求(存在内置安装器时启动,进行中/已满足返回 false)。\n * @author ddj 2026年09月03号\n * @param id 需求标识(如 dotnet-runtime:10)\n * @returns 是否成功启动安装\n */\nexport function installRequirement(id: string): boolean {\n const installer = INSTALLERS.find((it) => id.startsWith(it.prefix))\n if (!installer) return false\n return installer.run(id)\n}\n","/**\n * dsh-vscode-mode host — edrv.lsp.* RPC handlers。\n * 文档跟踪(openDocs 集合 + root|lang 引用计数)→ 懒启动服务器、用完释放。\n * LSP 配置降级为配置值:插件组合配置 + 会话内运行时覆盖层(原 settings section\n * 命名空间不合法,永久不可注册,见 lsp/config.ts 头注释)。\n * 作者 ddj 2026-08-27 / 2026-09-02\n */\nimport type { Ctx } from '../store.js'\nimport { searchRoot } from '../search/ripgrep.js'\nimport { sessionOf, cwdOf } from '../registry.js'\nimport { resolveProviderSpec, langOfPath, configFromPlugin, mergeConfig, sanitizeLang, LSP_LANGUAGES, type LspConfig, type LspLangConfig } from './config.js'\nimport { clearProviderCache, candidatesFor } from './providers.js'\nimport { onRuntimeProvisioned, envInstallStates } from './dotnetProvision.js'\nimport { envRequirementsFor, installRequirement } from './envRequirements.js'\nimport type { LspManager } from './manager.js'\nimport type { RpcHandlerMap } from '../shared/rpc.js'\nimport type { LspLocation, LspServerStatus } from '../shared/lsp.js'\nimport { installFromMarket, installVsixFile, listInstalled, marketGet, marketSearch, uninstall, updateExtension, type ExtInfo } from './extmgr.js'\nimport { dshHome } from '../paths.js'\n\nexport interface LspRpcDeps {\n ctx: Ctx\n pluginConfig: unknown\n manager: LspManager\n}\n\n/**\n * 打开文档跟踪:openDocs(docKey→sessionId) + rootLangRefs 计数 + sessionAcquired 归属。\n * 保证 manager 的 acquire/release 一一配对(多会话共享同一 root|lang 也平衡)。\n */\nfunction createDocTracker() {\n const openDocs = new Map<string, Set<string>>()\n const rootLangRefs = new Map<string, number>()\n const sessionDocs = new Map<string, Set<string>>()\n const keyOf = (root: string, lang: string, path: string): string => root + '|' + lang + '|' + path\n const rootLangOf = (docKey: string): string => docKey.slice(0, docKey.lastIndexOf('|'))\n const rememberDoc = (sessionId: string, docKey: string): void => {\n const docs = sessionDocs.get(sessionId) ?? new Set<string>()\n docs.add(docKey)\n sessionDocs.set(sessionId, docs)\n }\n const forgetDoc = (sessionId: string, docKey: string): void => {\n const docs = sessionDocs.get(sessionId)\n docs?.delete(docKey)\n if (docs?.size === 0) sessionDocs.delete(sessionId)\n }\n const releaseRef = (rl: string): boolean => {\n const next = (rootLangRefs.get(rl) ?? 1) - 1\n if (next <= 0) {\n rootLangRefs.delete(rl)\n return true\n }\n rootLangRefs.set(rl, next)\n return false\n }\n return {\n /** 记录文档打开;同一文档可由多个会话打开,但每个会话只计一次。 */\n open(root: string, lang: string, path: string, sessionId: string): boolean {\n const docKey = keyOf(root, lang, path)\n const owners = openDocs.get(docKey) ?? new Set<string>()\n if (owners.has(sessionId)) return false\n owners.add(sessionId)\n openDocs.set(docKey, owners)\n rememberDoc(sessionId, docKey)\n const rl = root + '|' + lang\n const count = rootLangRefs.get(rl) ?? 0\n rootLangRefs.set(rl, count + 1)\n return count === 0\n },\n /** 记录文档关闭;返回 true 表示 root|lang 已无文档(应 release)。 */\n close(root: string, lang: string, path: string, sessionId: string): boolean {\n const docKey = keyOf(root, lang, path)\n const owners = openDocs.get(docKey)\n if (!owners?.has(sessionId)) return false\n owners.delete(sessionId)\n if (owners.size === 0) openDocs.delete(docKey)\n forgetDoc(sessionId, docKey)\n return releaseRef(root + '|' + lang)\n },\n /** 关闭某会话全部文档;返回全局引用归零、需要 release 的 root|lang。 */\n closeSession(sessionId: string): string[] {\n const docs = sessionDocs.get(sessionId)\n if (!docs) return []\n const toRelease = new Set<string>()\n for (const docKey of docs) {\n const owners = openDocs.get(docKey)\n owners?.delete(sessionId)\n if (owners?.size === 0) openDocs.delete(docKey)\n if (releaseRef(rootLangOf(docKey))) toRelease.add(rootLangOf(docKey))\n }\n sessionDocs.delete(sessionId)\n return [...toRelease]\n },\n /** 清除指定语言的文档归属,让当前客户端重新同步时重新 acquire。 */\n resetLanguage(languageId: string): void {\n for (const [docKey, owners] of openDocs) {\n if (!docKey.includes('|' + languageId + '|')) continue\n for (const sessionId of owners) forgetDoc(sessionId, docKey)\n openDocs.delete(docKey)\n }\n for (const key of [...rootLangRefs.keys()]) if (key.endsWith('|' + languageId)) rootLangRefs.delete(key)\n },\n /** 返回指定会话已打开的文档路径,用于重检测后恢复同步。 */\n pathsFor(sessionId: string, languageId: string): string[] {\n const docs = sessionDocs.get(sessionId)\n if (!docs) return []\n return [...docs].filter((key) => key.includes('|' + languageId + '|')).map((key) => key.slice(key.lastIndexOf('|') + 1))\n },\n }\n}\n\n/**\n * 构造 edrv.lsp.* handlers(一次性创建,tracker 状态跨请求保留)。\n * @author ddj 2026年08月27号\n * @param deps 依赖(ctx/pluginConfig/manager)\n * @returns { handlers, disposeSession } handlers 为局部 map,disposeSession 供 session/disposed 清理\n */\nexport function createLspRpc(deps: LspRpcDeps): { handlers: Partial<RpcHandlerMap>; disposeSession: (sessionId: string) => void } {\n const { ctx, pluginConfig, manager } = deps\n const tracker = createDocTracker()\n /** 运行时覆盖层:设置页保存值(内存态,重启回落组合配置值;每 apply 新建,插件重载自动复位)。 */\n const runtimeConfig: LspConfig = {}\n\n // 运行时自动配置成功:清 provider 缓存并重置 C# 服务器,下一次文档同步即用新运行时重启\n onRuntimeProvisioned(() => {\n clearProviderCache()\n manager.resetLanguage('csharp')\n })\n\n /** 解析会话与工作区根(失败 → null + error)。 */\n const rootOf = async (sessionId: string | undefined): Promise<{ root: string; sessionId: string } | { err: string }> => {\n const session = sessionOf(ctx, sessionId)\n if (!session) return { err: '会话不存在' }\n const cwd = cwdOf(session)\n if (!cwd) return { err: '会话无工作区' }\n try {\n const root = await searchRoot(ctx, session)\n const sid = typeof session.id === 'string' && session.id ? session.id : sessionId ?? ''\n return { root, sessionId: sid }\n } catch (error) {\n return { err: String(error) }\n }\n }\n\n const acquireServer = (root: string, lang: string) =>\n manager.acquire(root, lang, (languageId: string) => resolveProviderSpec(pluginConfig, languageId, runtimeConfig))\n\n const serverOf = (root: string, lang: string) =>\n manager.peek(root, lang)\n\n const rootLocations = (locations: LspLocation[], root: string): LspLocation[] =>\n locations.map((location) => ({ ...location, root }))\n\n /** 当前 provider 检测结论 → 设置页 idle 状态(不启动 server);附带未满足的环境需求与候选服务器。 */\n const detectedStatus = (languageId: string, root?: string): LspServerStatus => {\n const spec = resolveProviderSpec(pluginConfig, languageId, runtimeConfig)\n const missingEnv = envRequirementsFor(languageId, dshHome())\n const candidates = candidatesFor(languageId, spec)\n return {\n languageId,\n source: spec.kind,\n phase: 'idle',\n reason: spec.ready ? undefined : spec.reason,\n version: spec.version,\n providerName: spec.providerName,\n root,\n missingEnv: missingEnv.length ? missingEnv : undefined,\n candidates: candidates.length ? candidates : undefined,\n }\n }\n\n /**\n * 清发现缓存并重置旧 server(保留 tracker 文档记录);\n * 下一次模型同步会按最新配置重新 acquire,已打开文档无需重开。\n * 作者 ddj 2026年09月02号\n * @param languageId 语言 id\n * @param sessionId 会话语境(缺省重置全部工作区该语言)\n * @returns 检测后的 idle 状态列表\n */\n const redetectLanguage = async (languageId: string, sessionId?: string): Promise<LspServerStatus[]> => {\n clearProviderCache()\n if (sessionId) {\n const sc = await rootOf(sessionId)\n if ('err' in sc) return []\n manager.reset(sc.root, languageId)\n return [detectedStatus(languageId, sc.root)]\n }\n const roots = [...new Set(manager.statusAll().filter((s) => s.languageId === languageId).map((s) => s.root))]\n manager.resetLanguage(languageId)\n return roots.length ? roots.map((root) => detectedStatus(languageId, root)) : [detectedStatus(languageId)]\n }\n\n const disposeSession = (sessionId: string): void => {\n for (const rl of tracker.closeSession(sessionId)) {\n const sep = rl.lastIndexOf('|')\n manager.release(rl.slice(0, sep), rl.slice(sep + 1))\n }\n }\n\n const handlers: Partial<RpcHandlerMap> = {\n 'edrv.lsp.status': async (args) => {\n if (!args.sessionId) return { ok: true, servers: manager.statusAll() }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n return { ok: true, servers: manager.statusAll().filter((status) => status.root === sc.root) }\n },\n\n 'edrv.lsp.detect': async () => {\n // 全支持语言的检测结果(不启动服务器):设置页动态渲染卡片 + 候选展示\n return { ok: true, servers: LSP_LANGUAGES.map((lang) => detectedStatus(lang)) }\n },\n\n 'edrv.lsp.configGet': async () => {\n // 配置值降级:插件组合配置 + 运行时覆盖层(原 settings section 已废弃)\n const merged = mergeConfig(configFromPlugin(pluginConfig), runtimeConfig)\n return { ok: true, config: merged as unknown as Record<string, unknown> }\n },\n\n 'edrv.lsp.configUpdate': async (args) => {\n const lang = args.languageId\n if (!lang || !(LSP_LANGUAGES as readonly string[]).includes(lang)) {\n return { ok: false, error: '不支持的语言:' + lang }\n }\n // 覆盖层基于当前运行时值增量修改;清空字段剥离 undefined → 回落组合配置\n const target: LspLangConfig = { ...(runtimeConfig[lang] ?? {}) }\n if (args.enabled !== undefined) target.enabled = args.enabled\n if (args.command !== undefined) target.command = args.command || undefined\n if (args.path !== undefined) target.path = args.path || undefined\n runtimeConfig[lang] = sanitizeLang(target) ?? {}\n try {\n // 保存/切换后立即重新检测:清缓存 + 重置旧 server,旧状态不残留\n const servers = await redetectLanguage(lang)\n const merged = mergeConfig(configFromPlugin(pluginConfig), runtimeConfig)\n return { ok: true, config: merged as unknown as Record<string, unknown>, servers }\n } catch (error) {\n return { ok: false, error: '配置保存失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.sync': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const first = tracker.open(sc.root, lang, args.path, sc.sessionId)\n const server = first ? acquireServer(sc.root, lang) : serverOf(sc.root, lang)\n if (!server) return { ok: false, error: '语言服务器未注册' }\n server.sync(args.path, args.text, args.version)\n return { ok: true }\n },\n\n 'edrv.lsp.close': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: true }\n if (tracker.close(sc.root, lang, args.path, sc.sessionId)) {\n manager.release(sc.root, lang)\n }\n return { ok: true }\n },\n\n 'edrv.lsp.definition': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, locations: [] }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, locations: [] }\n const locations = await server.definition(args.path, args.position.line, args.position.character)\n const rooted = rootLocations(locations, sc.root)\n const truncated = rooted.length > 500\n return { ok: true, locations: truncated ? rooted.slice(0, 500) : rooted, truncated: truncated || undefined }\n } catch (error) {\n return { ok: false, error: 'LSP 定义查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.references': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, locations: [] }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, locations: [] }\n const locations = await server.references(args.path, args.position.line, args.position.character, args.includeDeclaration !== false)\n const rooted = rootLocations(locations, sc.root)\n const truncated = rooted.length > 500\n return { ok: true, locations: truncated ? rooted.slice(0, 500) : rooted, truncated: truncated || undefined }\n } catch (error) {\n return { ok: false, error: 'LSP 引用查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.documentSymbol': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, symbols: [] }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, symbols: [] }\n const symbols = await server.documentSymbol(args.path)\n return { ok: true, symbols }\n } catch (error) {\n return { ok: false, error: 'LSP 大纲查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.workspaceSymbol': async (args) => {\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const out: { symbols: never[]; truncated?: boolean } = { symbols: [] }\n for (const lang of ['lua', 'csharp']) {\n const existing = serverOf(sc.root, lang)\n if (!existing) continue\n try {\n const symbols = await existing.workspaceSymbol(args.query)\n if (symbols.length) out.symbols.push(...(symbols as never[]))\n } catch (error) {\n /* 单语言失败忽略 */\n }\n }\n const truncated = out.symbols.length > 500\n return { ok: true, symbols: out.symbols.slice(0, 500), truncated: truncated || undefined }\n },\n\n 'edrv.lsp.hover': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, hover: undefined }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, hover: undefined }\n const hover = await server.hover(args.path, args.position.line, args.position.character)\n return { ok: true, hover: hover ?? undefined }\n } catch (error) {\n return { ok: false, error: 'LSP hover 查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.semanticTokens': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, tokens: undefined }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, tokens: undefined }\n return { ok: true, tokens: (await server.semanticTokens(args.path)) ?? undefined }\n } catch (error) {\n return { ok: false, error: 'LSP 语义分色查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.redetect': async (args) => {\n if (!(LSP_LANGUAGES as readonly string[]).includes(args.languageId)) {\n return { ok: false, error: '不支持的语言:' + args.languageId }\n }\n try {\n return { ok: true, servers: await redetectLanguage(args.languageId) }\n } catch (error) {\n return { ok: false, error: '重新检测失败:' + String(error) }\n }\n },\n\n // 环境需求:一键安装(内置安装器)与安装进度查询\n 'edrv.lsp.envInstall': async (args) => {\n if (!installRequirement(args.id)) {\n return { ok: false, started: false, error: '该需求不支持一键安装:' + args.id }\n }\n return { ok: true, started: true }\n },\n\n 'edrv.lsp.envState': async () => {\n return { ok: true, states: envInstallStates() }\n },\n\n // --region 扩展管理(edrv.lsp.ext.*:已装/市场/安装/卸载/更新)\n 'edrv.lsp.ext.list': async () => ({ ok: true, extensions: listInstalled() }),\n\n 'edrv.lsp.ext.market': async (args) => {\n try {\n const items = await marketSearch(args.query, args.size ?? 12)\n return { ok: true, extensions: items }\n } catch (error) {\n return { ok: false, error: '市场搜索失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.ext.install': async (args) => {\n try {\n let info: ExtInfo\n if (args.vsixPath) info = await installVsixFile(args.vsixPath)\n else if (args.namespace && args.name) info = await installFromMarket(args.namespace, args.name, args.version)\n else return { ok: false, error: '缺少安装源(vsixPath 或 namespace+name)' }\n clearProviderCache() // 新扩展可能成为 Lua provider,立即丢弃旧发现结果\n return { ok: true, extension: info }\n } catch (error) {\n return { ok: false, error: '安装失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.ext.uninstall': async (args) => {\n const ok = uninstall(args.id)\n if (ok) clearProviderCache()\n return ok ? { ok: true } : { ok: false, error: '扩展未安装:' + args.id }\n },\n\n 'edrv.lsp.ext.update': async (args) => {\n try {\n const updated = await updateExtension(args.id)\n if (!updated) {\n const current = listInstalled().find((e) => e.id === args.id)\n return current ? { ok: true, extension: current, updated: false } : { ok: false, error: '扩展未安装:' + args.id }\n }\n clearProviderCache()\n return { ok: true, extension: updated, updated: true }\n } catch (error) {\n return { ok: false, error: '更新失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.ext.updates': async () => {\n try {\n const updates = []\n for (const ext of listInstalled()) {\n const meta = await marketGet(ext.namespace, ext.name)\n const latest = String(meta?.version ?? '')\n if (latest && latest !== ext.version) updates.push({ id: ext.id, current: ext.version, latest, displayName: ext.displayName })\n }\n return { ok: true, updates }\n } catch (error) {\n return { ok: false, error: '检查更新失败:' + String(error) }\n }\n },\n // --endregion\n }\n return { handlers, disposeSession }\n}\n","/**\n * dsh-vscode-mode shared — AI 内联补全契约与纯函数(双面,禁 node/react)。\n * 只放\"过 RPC 的载荷形状\"与无副作用变换:窗口裁剪、prompt 拼装、输出清理。\n * host 与语言模型之间的流式交互在 host 侧 src/ai/inline.ts。\n * 作者 ddj\n */\n\n/** 上下文窗口:前缀字符上限(含未保存编辑的当前文档)。 */\nexport const AI_PREFIX_MAX = 2000\n/** 上下文窗口:后缀字符上限(光标之后不参与补全语义的部分)。 */\nexport const AI_SUFFIX_MAX = 500\n/** 触发门槛:前缀至少 4 个字符才请求(省掉空转调用)。 */\nexport const AI_MIN_PREFIX = 4\n/** 单次补全输出上限(token 预算 + 行数双约束,早停兜底)。 */\nexport const AI_MAX_TOKENS = 120\n/** 输出行数上限:超过即截断(ghost text 太长不可用)。 */\nexport const AI_MAX_LINES = 3\n/** 流式早停:已收字符数达到该值即 abort(省尾部延迟)。 */\nexport const AI_EARLY_STOP_CHARS = 300\n/** 补全请求超时(毫秒):codebuddy CLI 网关实测 TTFT 3.5~8.4s 抖动(debug 实证),\n * 12s 内无任何 token 即放弃;token 一到仍按行数/字符早停。 */\nexport const AI_TIMEOUT_MS = 12000\n\n/** client → host 的补全请求载荷。 */\nexport interface AiInlineRequest {\n /** 当前文档工作区相对路径(语言提示用)。 */\n path: string\n /** 光标前文本(client 已裁剪到 AI_PREFIX_MAX)。 */\n prefix: string\n /** 光标后文本(client 已裁剪到 AI_SUFFIX_MAX)。 */\n suffix: string\n}\n\n/** host → client 的补全结果(text 为空 = 无建议)。 */\nexport interface AiInlineResult {\n /** 建议插入文本(已清理:剥围栏/截行数/去重复)。 */\n text: string\n /** 失败原因(ok:false 或 text 为空时的诊断文案,供状态栏展示)。 */\n note?: string\n}\n\n/** 模型目录条目(含该模型的思考档位元数据)。 */\nexport interface AiModelEntry {\n provider: string\n model: string\n name: string\n /** 无 reasoning 元数据 = 空数组(UI 隐藏档位选择器)。 */\n efforts: Array<{ id: string; name: string }>\n /** 模型默认档位 id(无则空)。 */\n defaultEffort: string\n}\n\n/** 模型目录视图(edrv.ai.models 载荷)。 */\nexport interface AiDirectoryView {\n providers: Array<{ id: string; name: string; models: AiModelEntry[] }>\n /** 目录不可用原因(llm 服务缺失等;ok:false 时亦有 error,此为软降级说明)。 */\n note?: string\n}\n\n/** AI 补全配置视图(edrv.ai.configGet 载荷)。 */\nexport interface AiConfigView {\n enabled: boolean\n /** 空 = 自动选首个 provider/model。 */\n provider: string\n /** 空 = 自动选该 provider 首个模型。 */\n model: string\n /** 空 = 跟随模型默认(请求不携带 reasoningEffort)。 */\n effort: string\n}\n\n/** AI 补全配置更新载荷(edrv.ai.configUpdate)。 */\nexport interface AiConfigPatch {\n enabled?: boolean\n provider?: string\n model?: string\n /** 空 = 清除(跟随默认)。 */\n effort?: string\n}\n\n/**\n * 按 AI_PREFIX_MAX/AI_SUFFIX_MAX 裁剪前后缀(client 侧发请求前调用)。\n * @author ddj\n * @param prefix 光标前全文\n * @param suffix 光标后全文\n * @returns 裁剪后的窗口\n */\nexport function trimInlineWindow(prefix: string, suffix: string): { prefix: string; suffix: string } {\n const pre = typeof prefix === 'string' ? prefix : ''\n const suf = typeof suffix === 'string' ? suffix : ''\n return {\n prefix: pre.length > AI_PREFIX_MAX ? pre.slice(pre.length - AI_PREFIX_MAX) : pre,\n suffix: suf.length > AI_SUFFIX_MAX ? suf.slice(0, AI_SUFFIX_MAX) : suf,\n }\n}\n\n/**\n * 是否值得发起补全请求:前缀达标且非纯空白(空行/行首不请求)。\n * @author ddj\n * @param prefix 光标前文本\n * @returns 是否可请求\n */\nexport function inlineWorth(prefix: string): boolean {\n const pre = typeof prefix === 'string' ? prefix : ''\n if (pre.length < AI_MIN_PREFIX) return false\n // 只拦\"整体无内容\"(纯空白);结尾空白(如 `local a = `)是最自然的补全触发\n // 形态,必须放行——原尾字符守卫把这类场景全数拦截(debug 实证 H4)\n return pre.trim().length > 0\n}\n\n/**\n * 拼装补全 user 消息文本:语言/文件名 + 前缀 + 补全点标记 + 后缀。\n * host 侧与单测共用,保证请求形状一致。\n * @author ddj\n * @param req 补全请求(已裁剪)\n * @returns 用户消息文本\n */\nexport function buildInlinePrompt(req: AiInlineRequest): string {\n const name = String(req.path || '').split(/[\\\\/]/).pop() || 'untitled'\n return [\n '文件:' + name,\n '现有代码(光标位于 <CURSOR> 标记处):',\n req.prefix + '<CURSOR>' + req.suffix,\n ].join('\\n')\n}\n\n/** 补全 system 提示词:硬约束输出形态(只给插入文本)。 */\nexport const AI_INLINE_SYSTEM =\n '你是代码自动补全引擎。只输出应插入 <CURSOR> 处的代码文本:' +\n '禁止任何解释、注释性语句、markdown 代码围栏或对原文的复述;' +\n '最多 ' + AI_MAX_LINES + ' 行,从光标处自然衔接前文,不要重复前缀已有内容;' +\n '无法给出高置信度补全时输出空文本。'\n\n/**\n * 清理模型输出:剥 markdown 围栏、剥对 <CURSOR> 标记的复述、按行数截断、去首尾空行。\n * 产出空文本的判定也在这里(纯函数,单测覆盖)。\n * @author ddj\n * @param raw 模型原始输出\n * @param prefix 请求时的前缀(复述检测)\n * @returns 清理后的插入文本(可能为空串)\n */\nexport function cleanInlineText(raw: string, prefix: string): string {\n let text = typeof raw === 'string' ? raw : ''\n if (!text) return ''\n // markdown 围栏剥离(```lang … ``` 或 ```…```)\n const fenced = /^```[^\\n]*\\n([\\s\\S]*?)\\n?```$/.exec(text.trim())\n if (fenced) text = fenced[1] ?? ''\n // 模型复述了标记本身:取标记之后的部分\n const cursorAt = text.indexOf('<CURSOR>')\n if (cursorAt >= 0) text = text.slice(cursorAt + '<CURSOR>'.length)\n // 整体就是前缀结尾片段的复述:剥掉(防\"从行首重抄一遍\"类退化输出)\n const tailPrefix = prefix.length > 0 ? prefix.slice(-40) : ''\n if (tailPrefix && text.startsWith(tailPrefix)) text = text.slice(tailPrefix.length)\n // 行数截断 + 行尾空白清理\n const lines = text.split('\\n').slice(0, AI_MAX_LINES).map((l) => l.replace(/\\s+$/, ''))\n while (lines.length > 0 && lines[0] === '') lines.shift()\n while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop()\n return lines.join('\\n')\n}\n","/**\n * dsh-vscode-mode host — AI 内联补全服务。\n * 一次性非会话调用:配置解析(开关→provider/model 路由→思考档位)→ ctx.llm.stream\n * 流式汇聚(只收 text-delta,reasoning-delta 天然不进补全)→ 早停 → 输出清理。\n * llm 服务经 ctx.get('llm') 惰性获取(不用 inject:缺失时插件仍加载,AI 补全降级)。\n * 模型目录(edrv.ai.models):listProviders/listModels/resolveModelInfo 逐模型取档位,\n * 进程级缓存 5 分钟,单模型 resolve 失败降级为无档位条目。\n * 作者 ddj\n */\nimport type { Ctx } from '../store.js'\nimport { log } from '../log.js'\nimport type { LlmRuntimeLike, StreamChunk } from './llmTypes.js'\nimport {\n AI_EARLY_STOP_CHARS, AI_INLINE_SYSTEM, AI_MAX_LINES, AI_MAX_TOKENS, AI_TIMEOUT_MS,\n buildInlinePrompt, cleanInlineText,\n type AiConfigView, type AiDirectoryView, type AiInlineRequest, type AiInlineResult,\n} from '../shared/ai.js'\n\n/** AI 补全配置来源(settings section,fileOpenSettings.ts 提供 getter)。 */\nexport interface AiConfigSource {\n get(): AiConfigView\n}\n\n/** host 补全服务依赖(装配时一次性注入)。 */\nexport interface AiInlineDeps {\n ctx: Ctx\n config: AiConfigSource\n}\n\n/** 模型目录缓存(进程级:5 分钟 TTL,避免每次打开设置页都逐模型 resolve)。 */\nconst DIR_TTL_MS = 5 * 60 * 1000\nlet dirCache: { view: AiDirectoryView; at: number } | null = null\n\n/** 复位目录缓存(测试隔离用)。 */\nexport function resetAiDirCache(): void {\n dirCache = null\n}\n\n/**\n * 取 llm 运行时(惰性;缺失/未装配返回 null 并给诊断)。\n * @author ddj\n * @param ctx DSH 上下文\n * @returns llm 运行时或 null\n */\nfunction llmOf(ctx: Ctx): LlmRuntimeLike | null {\n try {\n const llm = ctx.get('llm') as LlmRuntimeLike | undefined\n return llm && typeof llm.stream === 'function' ? llm : null\n } catch {\n return null\n }\n}\n\n/**\n * 解析请求路由:用户配置优先(provider/model 均非空),否则取目录首个 provider+model。\n * @author ddj\n * @param llm llm 运行时\n * @param cfg AI 配置\n * @returns 路由(provider/model);不可路由返回 null\n */\nasync function routeOf(llm: LlmRuntimeLike, cfg: AiConfigView): Promise<{ provider: string; model: string } | null> {\n if (cfg.provider && cfg.model) return { provider: cfg.provider, model: cfg.model }\n const providers = llm.listProviders()\n if (!providers.length) return null\n const provider = cfg.provider || providers[0].id\n const models = await llm.listModels(provider).catch(() => [])\n if (!models.length) return null\n return { provider, model: models[0].id }\n}\n\n/**\n * 单次 AI 内联补全。\n * @author ddj\n * @param deps 服务依赖\n * @param req 补全请求(client 已裁剪窗口)\n * @returns 补全结果(text 空 = 无建议)\n */\nexport async function aiInlineComplete(deps: AiInlineDeps, req: AiInlineRequest): Promise<AiInlineResult> {\n const cfg = deps.config.get()\n if (!cfg.enabled) return { text: '' }\n if (!req || typeof req.prefix !== 'string' || !req.prefix) return { text: '' }\n const llm = llmOf(deps.ctx)\n if (!llm) return { text: '', note: 'llm 服务不可用' }\n const route = await routeOf(llm, cfg)\n if (!route) return { text: '', note: '未找到可用模型(请检查 DSH 模型配置)' }\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(new Error('timeout')), AI_TIMEOUT_MS)\n try {\n const stream = llm.stream({\n provider: route.provider,\n model: route.model,\n ...(cfg.effort ? { reasoningEffort: cfg.effort } : {}),\n messages: [\n {\n role: 'user',\n content: [{ type: 'text', text: buildInlinePrompt(req) }],\n source: { kind: 'user' },\n } as never,\n ],\n system: AI_INLINE_SYSTEM,\n temperature: 0.2,\n maxTokens: AI_MAX_TOKENS,\n // 不传 stop:llm-pi-ai 等适配器不支持该选项(UNSUPPORTED_OPTION 直接 error finish);\n // 截断由行数/字符早停兜底\n signal: controller.signal,\n })\n let text = ''\n let aborted = false\n let failNote = ''\n let reasoningChars = 0\n for await (const chunk of stream) {\n const c = chunk as StreamChunk\n if (c.type === 'text-delta') {\n text += c.text\n // 早停:满 3 行或 300 字符即掐断流,省尾部 token 延迟\n if (text.split('\\n').length > AI_MAX_LINES || text.length >= AI_EARLY_STOP_CHARS) {\n controller.abort(new Error('early-stop'))\n aborted = true\n }\n } else if (c.type === 'reasoning-delta') {\n reasoningChars += c.text.length\n } else if (c.type === 'finish') {\n // 适配器失败走 finish(error/aborted) 而非抛异常:检查 reason.kind 带回诊断\n const kind = (c.reason as { kind?: string })?.kind\n if (kind === 'error' || kind === 'aborted') {\n const failure = (c.reason as { failure?: { code?: string; message?: string } }).failure\n failNote = (failure?.code ?? kind) + ': ' + (failure?.message ?? '模型调用失败')\n log.debug('[ai-inline] 流失败:' + failNote)\n }\n break\n } else if (c.type === 'usage' || c.type === 'block-start' || c.type === 'block-end') {\n // 汇聚无关块:跳过\n } else if (c.type === 'tool-call-delta') {\n // 工具块不进补全\n }\n if (aborted) break\n }\n if (failNote) return { text: '', note: 'AI 补全失败:' + failNote }\n const clean = cleanInlineText(text, req.prefix)\n if (!clean) {\n // 思考型模型常见症状:正文空但思考有内容 → 明确提示换非思考模型(debug 实证 isd/deepseek-v4-flash)\n if (text.length === 0 && reasoningChars > 0) {\n log.debug('[ai-inline] 仅思考无正文(reasoning ' + reasoningChars + ' 字符)')\n return { text: '', note: '该模型只返回了思考没有正文,请在设置页换非思考模型' }\n }\n log.debug('[ai-inline] 空输出(原始 ' + text.length + ' 字符)')\n return { text: '' }\n }\n return { text: clean }\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n log.debug('[ai-inline] 失败:' + msg)\n return { text: '', note: 'AI 补全失败:' + msg }\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * 模型目录视图(edrv.ai.models):DSH 已配置 provider 全量 + 逐模型思考档位。\n * @author ddj\n * @param ctx DSH 上下文\n * @param force 跳过缓存强制刷新\n * @returns 目录视图(llm 缺失时 note 说明 + 空目录)\n */\nexport async function aiModels(ctx: Ctx, force = false): Promise<AiDirectoryView> {\n if (!force && dirCache && Date.now() - dirCache.at < DIR_TTL_MS) return dirCache.view\n const llm = llmOf(ctx)\n if (!llm) {\n return { providers: [], note: 'llm 服务不可用(无法枚举模型)' }\n }\n const out: AiDirectoryView = { providers: [] }\n for (const p of llm.listProviders()) {\n const models = await llm.listModels(p.id).catch(() => [])\n const entries = []\n for (const m of models) {\n let efforts: Array<{ id: string; name: string }> = []\n let def = ''\n try {\n const info = await llm.resolveModelInfo(p.id, m.id)\n efforts = (info.reasoning?.efforts ?? []).map((e: { id: string; name: string }) => ({ id: e.id, name: e.name }))\n def = info.reasoning?.defaultEffort ?? ''\n } catch {\n // 单模型元数据失败:降级为无档位条目(不影响目录其余部分)\n }\n entries.push({ provider: p.id, model: m.id, name: m.name || m.id, efforts, defaultEffort: def })\n }\n out.providers.push({ id: p.id, name: p.name || p.id, models: entries })\n }\n dirCache = { view: out, at: Date.now() }\n return out\n}\n","/**\n * dsh-vscode-mode host — edrv.ai.* RPC handlers。\n * inline:AI 内联补全(一次调用一次结果,无状态);models:模型目录(缓存);\n * configGet/configUpdate:settings section 的 AI 字段读写。\n * 作者 ddj\n */\nimport type { RpcHandlerMap } from '../shared/rpc.js'\nimport type { FileOpenSettingsState } from '../fileOpenSettings.js'\nimport type { AiConfigView } from '../shared/ai.js'\nimport { aiInlineComplete, aiModels, type AiInlineDeps } from './inline.js'\n\n/** AI RPC 依赖(settings 状态由 index.ts 装配时桥接)。 */\nexport interface AiRpcDeps {\n ctx: AiInlineDeps['ctx']\n settings: FileOpenSettingsState & {\n ai: () => AiConfigView\n aiUpdate: (patch: import('../shared/ai.js').AiConfigPatch, expectedRevision?: number) => Promise<AiConfigView>\n }\n}\n\n/**\n * 构造 edrv.ai.* handlers(一次性创建,无跨请求状态——目录缓存在 inline.ts 模块级)。\n * @author ddj\n * @param deps 依赖(ctx/settings)\n * @returns handlers\n */\nexport function createAiRpc(deps: AiRpcDeps): { handlers: Partial<RpcHandlerMap> } {\n const handlers: Partial<RpcHandlerMap> = {\n 'edrv.ai.inline': async (args) => ({ ok: true, ...(await aiInlineComplete({ ctx: deps.ctx, config: { get: () => deps.settings.ai() } }, args)) }),\n 'edrv.ai.models': async (args) => ({ ok: true, ...(await aiModels(deps.ctx, args?.force === true)) }),\n 'edrv.ai.configGet': async () => ({ ok: true, ...deps.settings.ai() }),\n 'edrv.ai.configUpdate': async (args) => ({ ok: true, ...(await deps.settings.aiUpdate(args)) }),\n }\n return { handlers }\n}\n","/**\n * @dsh-external 生态 → dsh-vscode-mode:DSH 上的类 VSCode 编码体验(Host 半入口)。\n * 职责:装配 capture(tools/result 捕获 edit/write 差异)、RPC 分发(edrv.* / mcp.* / vscode.* / compat)、\n * webServer 路由(/edrv/rpc、/edrv/assets/*、/edrv/vendor/*)、工作区旁车持久化、\n * 兼容层装配(依赖守卫 + 重复装配自诊断 + 启动日志兼容性报告)。\n * 结构:shared/(双面契约) + model/store/capture/workspace/revert/registry/rpc/routes/compat(host 模块)\n * + log/debugLog(统一日志:bindHostLog 绑定 ctx.logger,edrv.debug 诊断文件通道)。\n * 作者 ddj 2026-08-20\n */\nimport { registerRoutes } from './routes.js'\nimport { captureToolResult } from './capture.js'\nimport { handleRpc } from './rpc.js'\nimport { newSearcher } from './search/orchestrator.js'\nimport { newContentSearcher } from './search/content.js'\nimport { installIsolation } from './mcpIsolation.js'\nimport { dropFileIndex } from './workspace.js'\nimport { cwdOf } from './registry.js'\nimport { setupOpenSettings } from './fileOpenSettings.js'\nimport { shellMenuLifecycle } from './integrate.js'\nimport { disposeIndex } from './treeIndex.js'\nimport { sweepTreeCache } from './paths.js'\nimport { buildReport } from './compat.js'\nimport { bindHostLog, log } from './log.js'\nimport { createLspManager } from './lsp/manager.js'\nimport { createLspRpc } from './lsp/rpc.js'\nimport { disposeAllServers } from './lsp/transport.js'\nimport { createAiRpc } from './ai/rpc.js'\nimport { installRulesSection } from './rules.js'\nimport type { RpcHandlerMap } from './shared/rpc.js'\nimport type { Registry } from './registry.js'\nimport type { Ctx } from './store.js'\n\nexport const name = \"dsh-vscode-mode\"\nexport const inject = ['sessions', 'fs', 'webServer', 'loader', 'tools', 'workspaceRegistry', 'agents']\n\n/**\n * 装配插件:挂事件监听、注册路由、安装兼容层。\n * @author ddj 2026年08月20号\n * @param ctx DSH 上下文(sessions/fs/webServer 由 inject 提供;sandboxPolicy/subprocess 惰性获取)\n * @param config 插件配置(可选 imageDir 覆盖图标目录)\n */\nexport function apply(ctx: Ctx, config?: unknown): void {\n // 统一日志出口:全部 host 日志经 ctx.logger(缺失时回退 console),此后任何模块 log.* 即生效\n bindHostLog(ctx)\n const registry: Registry = new Map()\n const searcher = newSearcher(ctx)\n const contentSearcher = newContentSearcher(ctx)\n /** LSP 服务器管理器(语言智能:跳转/引用/大纲;诊断行带模块内前缀如 [lsp-manager])。 */\n const lspManager = createLspManager((line) => log.debug(line))\n /** 兼容性警告收集(route 护栏等写入,启动日志一并输出)。 */\n const warnings: string[] = []\n /** 设置状态(fileOpenTool + AI 补全配置读写;settings 不可用时内存态降级)。 */\n const openSettings = setupOpenSettings(ctx, config, () => {})\n /** LSP 配置为配置值模式:插件组合配置 + 会话内运行时覆盖(原 settings section 命名空间不合法,见 lsp/config.ts)。 */\n /** 规则注入 section(~/.dsh/rules 与 <工作区>/.dsh/rules;旧版 DSH 无 systemPrompt 时静默降级)。 */\n const rulesInstalled = installRulesSection(ctx)\n if (!rulesInstalled) log.warn('未检测到 systemPrompt 服务,规则仅可管理不注入')\n /** LSP RPC 与会话清理(一次性创建,tracker 状态跨请求保留)。 */\n const lspRpc = createLspRpc({ ctx, pluginConfig: config, manager: lspManager })\n const lspHandlers: Partial<RpcHandlerMap> = lspRpc.handlers\n /** AI 内联补全 RPC(settings 状态桥接 + llm 惰性获取)。 */\n const aiRpc = createAiRpc({ ctx, settings: openSettings })\n const aiHandlers: Partial<RpcHandlerMap> = aiRpc.handlers\n\n ctx.on('tools/result', (exec: unknown, result: unknown) => {\n void captureToolResult(ctx, registry, exec, result)\n })\n\n ctx.on('session/disposed', (session: unknown) => {\n const cwd = cwdOf(session as never)\n if (cwd) {\n registry.delete(cwd)\n dropFileIndex(cwd)\n searcher.dispose(cwd)\n contentSearcher.dispose(cwd)\n disposeIndex(cwd)\n }\n const sid = (session as { id?: unknown })?.id\n if (typeof sid === 'string') lspRpc.disposeSession(sid)\n })\n\n registerRoutes(ctx, config, (method, args) => handleRpc(ctx, registry, method, args, searcher, contentSearcher, lspHandlers, aiHandlers), (warning) => warnings.push(warning))\n installIsolation(ctx)\n // 系统集成生命周期:启动自动恢复右键菜单注册(marker 存在时);插件卸载/reload 清理注册痕迹\n ctx.effect(() => shellMenuLifecycle(ctx))\n // 启动清理缓存目录:非当前 schema / 超保留期 / 未知残留(best-effort,不阻塞装配)\n void sweepTreeCache()\n void logCompatSummary(ctx, warnings)\n // 卸载/重启时强杀 LSP 子进程(防残留)\n ctx.effect(() => () => {\n void lspManager.disposeAll().catch(() => {})\n disposeAllServers()\n })\n\n log.info('编辑差异审查已装配(/edrv/rpc 路由就绪,项目 MCP 隔离已启用,语言服务器 LSP 已接入,规则注入' + (rulesInstalled ? '已接入' : '未接入') + ')')\n}\n\n/**\n * 异步输出兼容性报告摘要(含重复装配/路由冲突自诊断)。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文\n * @param warnings 装配期收集的兼容性警告\n */\nasync function logCompatSummary(ctx: Ctx, warnings: string[]): Promise<void> {\n try {\n const report = await buildReport(ctx)\n for (const warning of warnings) report.warnings.push(warning)\n const dsh = report.dshVersion ? 'DSH ' + report.dshVersion : 'DSH 未探测'\n const head = '兼容性:' + dsh + ' · ' + report.external.length + ' 项外部适配 / ' + report.guards.length + ' 项护栏 / ' + (report.adapters?.length ?? 0) + ' 项版本适配'\n if (report.warnings.length) {\n log.warn(head + ',警告 ' + report.warnings.length + ' 条:' + report.warnings.join(';'))\n } else {\n log.info(head + ',无警告')\n }\n } catch (error) {\n log.warn('兼容性报告生成失败:' + String(error))\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["STDOUT_CAP","STDERR_CAP","GRACE_MS","PROVIDER_VERSION","STDERR_CAP","RESERVED_NAME_RE","workspaceList","fullPolicy","requireWorkspace","dirOf","Buffer","fullPolicy","requireWorkspace","Buffer","value"],"sources":["../src/mcp.ts","../src/shared/keybindings.ts","../src/shared/integration.ts","../src/shared/logger.ts","../src/log.ts","../src/fileOpenSettings.ts","../src/devForm.ts","../src/dshVersion.ts","../src/shared/rpc.ts","../src/paths.ts","../src/compat.ts","../src/routes.ts","../src/shared/diff.ts","../src/model.ts","../src/store.ts","../src/registry.ts","../src/tree.ts","../src/treeRead.ts","../src/treeIndex.ts","../src/capture.ts","../src/search/query.ts","../src/search/ripgrep.ts","../src/search/fallback.ts","../src/search/ranker.ts","../src/search/orchestrator.ts","../src/search/content.ts","../src/revert.ts","../src/rules.ts","../src/snippets.ts","../src/mcpProject.ts","../src/unityBridge.ts","../src/integrate.ts","../src/externalHandoff.ts","../src/reveal.ts","../src/debugLog.ts","../src/perf.ts","../src/perfPatch.ts","../src/rpc.ts","../src/mcpIsolation.ts","../src/workspace.ts","../src/lsp/jsonrpc.ts","../src/lsp/transport.ts","../src/shared/lsp.ts","../src/lsp/client.ts","../src/lsp/uri.ts","../src/lsp/derive.ts","../src/lsp/server.ts","../src/lsp/manager.ts","../src/lsp/zip.ts","../src/lsp/extmgr.ts","../src/lsp/providers.ts","../src/lsp/dotnetProvision.ts","../src/lsp/config.ts","../src/lsp/envRequirements.ts","../src/lsp/rpc.ts","../src/shared/ai.ts","../src/ai/inline.ts","../src/ai/rpc.ts","../src/index.ts"],"sourcesContent":["/**\n * dsh-vscode-mode host — MCP 运行时管理适配层。\n * 只操作已装配的 @deepseek-ai/dsh-mcp-client loader entry,不在浏览器侧连接 MCP。\n * 身份常量(包名/条目前缀/新旧格式判定)统一由 compat 层持有,本模块再导出保持既有 import 面。\n * 作者 ddj 2026年08月22号\n */\nimport {\n LEGACY_PROJECT_PREFIX,\n MCP_PACKAGE,\n PROJECT_ENTRY_PREFIX,\n isProjectEntryId,\n} from './compat.js'\nimport type { MpcConfig, MpcServer, MpcTool } from './shared/mcp.js'\nimport type { Ctx } from './store.js'\n\nexport { LEGACY_PROJECT_PREFIX, MCP_PACKAGE, PROJECT_ENTRY_PREFIX, isProjectEntryId }\n\n/** 列出当前 loader 中的 MCP entry。 */\nfunction entriesOf(ctx: Ctx): any[] {\n const loader = ctx.get('loader')\n if (!loader || typeof loader.entries !== 'function') return []\n return [...loader.entries()].filter((entry) => entry?.options?.name === MCP_PACKAGE)\n}\nexport { entriesOf }\n\n/** 脱敏配置并保留可编辑字段的存在性。 */\nexport function publicConfig(config: Record<string, unknown>): MpcConfig {\n const out = { ...config } as Record<string, unknown>\n if (out.env && typeof out.env === 'object') out.env = Object.fromEntries(Object.keys(out.env as object).map((key) => [key, '••••••']))\n if (out.headers && typeof out.headers === 'object') out.headers = Object.fromEntries(Object.keys(out.headers as object).map((key) => [key, '••••••']))\n return out as unknown as MpcConfig\n}\n\n/** 从工具注册表读取服务器命名空间下的工具摘要。 */\nexport function toolsOf(ctx: Ctx, serverName: string): MpcTool[] {\n const tools = ctx.get('tools')\n const view = tools?.view?.(void 0)\n const visible = view?.visible\n if (!(visible instanceof Map)) return []\n const prefix = `mcp__${serverName}__`\n return [...visible.entries()].filter(([name]) => String(name).startsWith(prefix)).map(([name, definition]) => ({\n name: String(name).slice(prefix.length),\n description: typeof definition?.description === 'string' ? definition.description : undefined,\n }))\n}\n\n/** 将 loader entry 映射为设置页摘要。 */\nexport function serverOf(ctx: Ctx, entry: any): MpcServer {\n const config = (entry.options?.config ?? {}) as Record<string, unknown>\n const serverName = typeof config.serverName === 'string' ? config.serverName : entry.options?.id ?? 'unknown'\n const tools = toolsOf(ctx, serverName)\n const state = entry.fiber?.state\n return {\n id: String(entry.id ?? entry.options?.id ?? serverName),\n serverName,\n enabled: entry.disabled !== true,\n transport: config.transport === 'streamable-http' ? 'streamable-http' : 'stdio',\n config: publicConfig(config),\n status: state === 2 ? 'connected' : state === 1 ? 'connecting' : 'error',\n toolCount: tools.length,\n tools,\n error: state === 3 ? 'MCP 插件未正常运行' : undefined,\n }\n}\n\n/** 校验 MCP 配置。 */\nexport function validateConfig(config: MpcConfig): void {\n if (!/^[A-Za-z0-9_-]{1,32}$/.test(config.serverName)) throw new Error('serverName 只能包含字母、数字、下划线和连字符(最多 32 位)')\n if (config.transport === 'stdio' && !config.command?.trim()) throw new Error('stdio MCP 必须填写 command')\n if (config.transport === 'streamable-http' && !/^https?:\\/\\//.test(config.url ?? '')) throw new Error('HTTP MCP 必须填写 http(s) URL')\n}\n\n/** 列出全局(profile)MCP 服务,过滤掉新旧格式的项目级条目。 */\nexport function listMcp(ctx: Ctx): { servers: MpcServer[] } {\n return { servers: entriesOf(ctx).filter((entry) => !isProjectEntryId(String(entry.id ?? entry.options?.id ?? ''))).map((entry) => serverOf(ctx, entry)) }\n}\n\n/** 保存 MCP 服务配置并触发 loader 热更新。 */\nexport async function saveMcp(ctx: Ctx, config: MpcConfig): Promise<MpcServer> {\n validateConfig(config)\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const existing = entriesOf(ctx).find((entry) => !isProjectEntryId(String(entry.id ?? entry.options?.id ?? '')) && entry.options?.config?.serverName === config.serverName)\n if (existing) {\n await loader.update(existing.id, { config: { ...config } })\n return serverOf(ctx, loader.resolve(existing.id))\n }\n const id = await loader.create({ name: MCP_PACKAGE, config: { ...config } })\n return serverOf(ctx, loader.resolve(id))\n}\n\n/** 删除 MCP 服务。 */\nexport async function removeMcp(ctx: Ctx, id: string): Promise<void> {\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id) === id)\n if (!entry) throw new Error('MCP 服务不存在')\n await loader.remove(entry.id)\n}\n\n/** 切换 MCP 服务启用状态。 */\nexport async function toggleMcp(ctx: Ctx, id: string, enabled: boolean): Promise<MpcServer> {\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id) === id)\n if (!entry) throw new Error('MCP 服务不存在')\n await loader.update(entry.id, { disabled: !enabled })\n return serverOf(ctx, loader.resolve(entry.id))\n}\n\n/** 重新加载 MCP 服务。 */\nexport async function refreshMcp(ctx: Ctx, id: string): Promise<MpcServer> {\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id) === id)\n if (!entry) throw new Error('MCP 服务不存在')\n await loader.update(entry.id, { config: { ...(entry.options?.config ?? {}) } })\n return serverOf(ctx, loader.resolve(entry.id))\n}\n\nexport type { MpcConfig, MpcServer }\nexport const mcpPackageName = MCP_PACKAGE\n","/**\n * dsh-vscode-mode shared — 快捷键命令目录与默认键位(双面契约)。\n * 纯数据模块:host(settings schema 默认值)与 client(执行匹配/设置页)共用。\n * 键位格式:修饰符 + 主键,`+` 连接,如 `Ctrl+Shift+F`;空串 = 未绑定;\n * `|` 连接多个候选(任一命中即触发),如 `Alt+ArrowLeft|Ctrl+Alt+-`。\n * 约束:本模块被 host 与 client 两半共用,**禁止 import client 侧模块**(React/浏览器 API)。\n * 与 client/ui/commandCatalog 的一致性由 tests/commands.test.ts 断言兜底。\n * 作者 ddj 2026年08月26号 / 2026年09月10号\n */\n\n/** 命令 id → 默认键位(可为多候选)。命令目录以此为准,新增命令只需加一项。 */\nexport const KEYBINDING_DEFAULTS: Record<string, string> = {\n 'edrv.save': 'Ctrl+S',\n 'edrv.quickOpen': 'Ctrl+P',\n 'edrv.toggleSidebar': 'Ctrl+B',\n 'edrv.searchInFiles': 'Ctrl+Shift+F',\n 'edrv.navigateBack': 'Alt+ArrowLeft|Ctrl+Alt+-',\n 'edrv.navigateForward': 'Alt+ArrowRight|Ctrl+Shift+-',\n // 页签循环:主候选避开浏览器保留键(Ctrl+Tab / Ctrl+PgUp/PgDn 会被浏览器截获)\n 'edrv.nextTab': 'Ctrl+Alt+ArrowRight|Ctrl+PageDown',\n 'edrv.prevTab': 'Ctrl+Alt+ArrowLeft|Ctrl+PageUp',\n // 命令栏(Ctrl+Shift+P 主候选;F1 为 VS Code 同款第二候选)与编辑行导航\n 'edrv.showCommands': 'Ctrl+Shift+P|F1',\n 'edrv.nextEditorRow': 'Ctrl+Alt+ArrowDown',\n 'edrv.prevEditorRow': 'Ctrl+Alt+ArrowUp',\n // 添加选中内容为引用:把当前选区追加进对话输入框(Ctrl+U,VS Code 同款)\n 'edrv.addSelectionRef': 'Ctrl+U',\n}\n\n/**\n * 返回默认键位的独立副本(调用方修改不污染目录)。\n * @author ddj 2026年08月26号\n * @returns 默认键位映射\n */\nexport function defaultKeybindings(): Record<string, string> {\n return { ...KEYBINDING_DEFAULTS }\n}\n\n/**\n * 规整外部键位数据:只保留已知命令 id 且为字符串的值,未知 id 丢弃。\n * 防止用户文档/旧版本写入的未知命令污染执行匹配。\n * @author ddj 2026年08月26号\n * @param raw 原始设置值\n * @returns 规整后的键位映射(缺省项不补默认值,由调用方按需合并)\n */\nexport function normalizeKeybindings(raw: unknown): Record<string, string> {\n const out: Record<string, string> = {}\n if (!raw || typeof raw !== 'object') return out\n for (const [id, chord] of Object.entries(raw as Record<string, unknown>)) {\n if (id in KEYBINDING_DEFAULTS && typeof chord === 'string') out[id] = chord\n }\n return out\n}\n","/**\n * dsh-vscode-mode shared — 系统集成载荷契约(Windows 右键菜单 + Unity 一键安装/更新)。\n * Purity rule: no node/react imports(platform 用 string 表示)。\n * 作者 ddj 2026-09-07\n */\n\n/** Unity 内嵌包名(UPM 包名,同时是项目 Packages/ 下的目录名)。 */\nexport const UNITY_PACKAGE_NAME = 'com.dsh.editor'\n/** 注册表菜单键叶子名(HKCU\\Software\\Classes\\*\\shell\\<leaf>)。 */\nexport const SHELL_MENU_LEAF = 'DSHEditor'\n/** 深链基址默认值(DSH Web GUI 默认端口,dsh-web.cmd 实证)。 */\nexport const INTEGRATION_BASE_DEFAULT = 'http://127.0.0.1:3080'\n\n/** launcher 安装态。 */\nexport interface ShellLauncherState {\n /** launcher 文件是否已安装(编译 exe 或降级 ps1)。 */\n present: boolean\n /** 是否为已编译 exe(false = 降级 ps1)。 */\n compiled: boolean\n /** launcher 文件绝对路径(未安装时为期望路径)。 */\n path: string\n}\n\n/** 一条右键菜单注册条目(跨平台:Windows 三键 / Linux 两项 / macOS 快速操作)。 */\nexport interface ShellMenuEntry {\n /** 条目 id(files/dir/dirBackground/nautilus/dolphin/finder)。 */\n id: string\n /** 展示名。 */\n label: string\n /** 是否已注册。 */\n registered: boolean\n /** 是否需手动创建(macOS Automator 配方)。 */\n manual?: boolean\n}\n\n/** 系统集成状态(edrv.integration.status/register/unregister 载荷)。 */\nexport interface ShellIntegrationStatus {\n /** 宿主平台('win32'/'linux'/'darwin')。 */\n platform: string\n launcher: ShellLauncherState\n /** 菜单注册条目(按平台)。 */\n entries: ShellMenuEntry[]\n /** 深链基址(设置 integrationBaseUrl)。 */\n baseUrl: string\n /** Unity 包源目录(随插件分发的 unity/com.dsh.editor 绝对路径)。 */\n unityPackagePath: string\n}\n\n/** 一个已登记 Unity 项目的安装状态(edrv.unity.* 载荷)。 */\nexport interface UnityProjectEntry {\n /** 项目根(归一化绝对路径)。 */\n path: string\n /** 目录名(展示标题)。 */\n title: string\n /** 已安装版本(未安装 → null)。 */\n installedVersion: string | null\n /** 已安装且版本等于包源版本。 */\n upToDate: boolean\n /** 项目目录不存在。 */\n missingDir: boolean\n /** 非法原因(非 Unity 项目根等)。 */\n error?: string\n}\n\n/** edrv.unity.list 载荷。 */\nexport interface UnityListPayload {\n /** 包源版本(unity/com.dsh.editor/package.json 的 version)。 */\n sourceVersion: string | null\n /** 包源目录绝对路径。 */\n sourcePath: string\n /** 已登记项目及安装状态。 */\n projects: UnityProjectEntry[]\n}\n","/**\n * dsh-vscode-mode — 统一日志核心(双面共享,平台中立)。\n * 输出规范:\n * - 格式:`[dsh-vscode-mode][:scope] 消息`;前缀只在模块内部拼接,业务代码禁止手写前缀\n * - 级别语义:debug=诊断明细 / info=装配与路由里程碑 / warn=降级与兼容回退 / error=失败\n * - 出口:host 面经 bindHostLog(ctx) 绑定 ctx.logger(缺失回退 console);client 面固定 console\n * - 诊断文件通道(edrv.debug → ~/.dsh/dsh-vscode-mode/logs/)见 debugLog.ts,与本模块前缀共用\n * 新增日志一律 `import { log } from '../log.js'`(client 为 './log.js')后调 log.debug/info/warn/error;\n * 子域日志用 log.child('scope'),禁止另起 console。\n * 作者 ddj 2026-09-08\n */\n\n/** 插件统一日志前缀(与包安装名一致)。 */\nexport const LOG_PREFIX = '[dsh-vscode-mode]'\n\n/** 日志级别(与 console 方法名对齐)。 */\nexport type LoggerLevel = 'debug' | 'info' | 'warn' | 'error'\n\n/** 日志出口:接收拼好前缀的整行(host 面接 ctx.logger,client 面接 console)。 */\nexport type LoggerSink = (level: LoggerLevel, line: string) => void\n\n/** 默认级别到 console 方法名的映射。 */\nconst CONSOLE_METHODS: Record<LoggerLevel, string> = { debug: 'debug', info: 'info', warn: 'warn', error: 'error' }\n\n/**\n * 默认出口:console(级别直映方法;方法缺失时静默丢弃,不抛错)。\n * @author ddj 2026年09月08号\n * @returns console 出口\n */\nexport function consoleSink(): LoggerSink {\n return (level, line) => {\n const emit = (console as unknown as Record<string, unknown>)[CONSOLE_METHODS[level]]\n if (typeof emit === 'function') (emit as (message: string) => void).call(console, line)\n }\n}\n\n/**\n * DSH host 出口工厂:转接 ctx.logger(方法级可选调用,缺服务/缺方法回退 console)。\n * @author ddj 2026年09月08号\n * @param ctx DSH host 上下文\n * @returns 日志出口\n */\nexport function ctxLogSink(ctx: unknown): LoggerSink {\n const base = consoleSink()\n return (level, line) => {\n const logger = (ctx as { logger?: Record<string, unknown> } | null | undefined)?.logger\n const emit = logger?.[level]\n if (typeof emit === 'function') (emit as (message: string) => void).call(logger, line)\n else base(level, line)\n }\n}\n\n/**\n * 拼一行日志:`[dsh-vscode-mode][:scope] 消息`(scope 为空省略冒号段)。\n * @author ddj 2026年09月08号\n * @param scope 子域(可空)\n * @param message 消息文本\n * @returns 整行文本\n */\nexport function formatLine(scope: string, message: string): string {\n const text = String(message)\n return scope ? LOG_PREFIX + ':' + scope + ' ' + text : LOG_PREFIX + ' ' + text\n}\n\n/** 日志器实例(四级别统一入口 + 换出口/派生子域)。 */\nexport interface PluginLogger {\n debug(message: string): void\n info(message: string): void\n warn(message: string): void\n error(message: string): void\n /** 更换出口(同一实例树共享,host 装配期绑定 ctx.logger 用;client 单例不调用)。 */\n bind(sink: LoggerSink): void\n /** 派生带子域前缀的新实例(共享出口,如 log.child('debug') → `[dsh-vscode-mode:debug]`)。 */\n child(scope: string): PluginLogger\n}\n\n/** 实例树共享的出口状态(bind 换出口对整棵树生效)。 */\ninterface SinkState {\n sink: LoggerSink\n}\n\n/**\n * 日志器工厂(内部):emit 时读共享出口状态,保证父 bind 后子实例跟随。\n * @author ddj 2026年09月08号\n * @param state 共享出口状态\n * @param scope 子域文本(可空)\n * @returns 日志器\n */\nfunction makeLogger(state: SinkState, scope: string): PluginLogger {\n const emit = (level: LoggerLevel, message: string): void => state.sink(level, formatLine(scope, message))\n return {\n debug: (message) => emit('debug', message),\n info: (message) => emit('info', message),\n warn: (message) => emit('warn', message),\n error: (message) => emit('error', message),\n bind(next: LoggerSink): void {\n state.sink = next\n },\n child(next: string): PluginLogger {\n return makeLogger(state, scope ? scope + '.' + next : next)\n },\n }\n}\n\n/**\n * 创建插件日志器(默认 console 出口;host 面单例由 bindHostLog 换到 ctx.logger)。\n * @author ddj 2026年09月08号\n * @param sink 初始出口(缺省 console)\n * @param scope 初始子域(业务方一般经 child 派生,不直接传)\n * @returns 日志器\n */\nexport function createLogger(sink: LoggerSink = consoleSink(), scope = ''): PluginLogger {\n return makeLogger({ sink }, scope)\n}\n","/**\n * dsh-vscode-mode host — 日志单例(全 host 面唯一日志入口)。\n * 默认 console 出口;apply() 首行调 bindHostLog(ctx) 切到 ctx.logger(缺失回退 console)。\n * 用法:`import { log } from './log.js'` → `log.debug/info/warn/error(msg)`;子域用 `log.child('scope')`。\n * 作者 ddj 2026-09-08\n */\nimport { createLogger, ctxLogSink } from './shared/logger.js'\n\n/** host 面插件日志单例(格式/级别语义见 shared/logger.ts 头注释)。 */\nexport const log = createLogger()\n\n/**\n * 装配期绑定 host 日志出口:ctx.logger 可用时全部日志转经 DSH 日志系统。\n * @author ddj 2026年09月08号\n * @param ctx DSH host 上下文(logger 服务缺失时保持 console 出口)\n */\nexport function bindHostLog(ctx: unknown): void {\n log.bind(ctxLogSink(ctx))\n}\n","/**\n * dsh-vscode-mode host — 文件链接打开工具 + 快捷键的持久化设置。\n * 依赖守卫:schemastery 动态加载;@deepseek-ai/dsh-settings 仅作 legacy 探测——\n * rc 线导出 installSettingsSection free function,0.1.2-alpha 起移除(改由 settings\n * 服务的 installSection 方法承载,见 runSettingsInstall 三策略)。\n * 缺失/任一策略失败时插件仍可加载(fileOpenTool 降级为配置值,compat 报告可见),\n * 全程 try/catch,不产生未捕获 rejection。\n * 作者 ddj 2026年08月24号 / 2026年08月26号 / 2026年09月02号\n */\nimport type { Ctx } from './store.js'\nimport { KEYBINDING_DEFAULTS } from './shared/keybindings.js'\nimport { INTEGRATION_BASE_DEFAULT } from './shared/integration.js'\nimport type { AiConfigPatch, AiConfigView } from './shared/ai.js'\nimport { log } from './log.js'\n\nexport const FILE_OPEN_SETTINGS_NS = 'dsh-vscode-mode'\nexport const FILE_OPEN_DEFAULT = 'auto'\nexport interface FileOpenSettings { fileOpenTool: string; integrationBaseUrl: string }\nexport interface FileOpenSettingsState { value: string; revision?: number; update: (value: string, expectedRevision?: number) => Promise<void> }\n\n/** AI 内联补全配置默认值(默认关闭;路由空 = 自动;档位空 = 跟随模型默认)。 */\nexport const AI_CONFIG_DEFAULT: { enabled: boolean; provider: string; model: string; effort: string } = {\n enabled: false,\n provider: '',\n model: '',\n effort: '',\n}\n\ntype SettingsProvider = {\n update?: (ns: string, patch: object, expectedRevision?: number) => Promise<void>\n describe?: (options?: unknown) => Array<{ ns?: string; value?: unknown; revision?: number }>\n get?: (ns: string) => unknown\n}\n\n/** 动态依赖的装载结果(宽松类型:dsh-settings 无本地类型声明)。 */\nexport interface SettingsDeps {\n installSettingsSection?: (ctx: Ctx, ns: string, schema: unknown, entry: object, hooks: object) => void\n z: {\n object: (shape: Record<string, unknown>) => { default: (value: Record<string, unknown>) => unknown }\n string: () => { default: (value: string) => unknown }\n boolean: () => { default: (value: boolean) => unknown }\n number: () => { default: (value: number) => unknown }\n }\n}\n\nexport type SettingsDepsLoader = () => Promise<SettingsDeps | null>\n\nlet depsPromise: Promise<SettingsDeps | null> | undefined\n\n/**\n * 动态加载设置依赖(模块级缓存;任一缺失/失败返回 null 而非抛错)。\n * installSettingsSection 仅在 rc 线 dsh-settings 中存在时提供(alpha 起移除,\n * 属性探测得到 undefined,不抛错)。\n * @author ddj 2026年08月24号\n * @returns 设置依赖或 null\n */\nexport function loadSettingsDeps(): Promise<SettingsDeps | null> {\n if (!depsPromise) {\n depsPromise = Promise.all([import('@deepseek-ai/dsh-settings'), import('schemastery')])\n .then(([dshSettings, schemastery]) => ({\n // dsh-settings 类型声明随版本变化(rc.8 有 d.ts、alpha 已移除导出),统一经 unknown 松绑\n installSettingsSection: (dshSettings as unknown as { installSettingsSection?: SettingsDeps['installSettingsSection'] }).installSettingsSection,\n z: (schemastery as unknown as { default: SettingsDeps['z'] }).default,\n }))\n .catch(() => null)\n }\n return depsPromise\n}\n\n/** 设置 section 安装策略(版本适配机制的观测值)。 */\nexport type SettingsInstallStrategy = 'legacy' | 'service' | 'none' | 'unknown'\n\nconst INSTALL_UNMOUNTED = '设置 section 尚未装配'\nconst INSTALL_LEGACY = 'rc 线:dsh-settings.installSettingsSection'\nconst INSTALL_SERVICE = '0.1.2-alpha 线:settings 服务 installSection'\nconst INSTALL_NONE = '两路均不可用:设置持久化降级为配置值'\n\ninterface ObservedInstall { strategy: SettingsInstallStrategy; note: string }\nlet observedInstall: ObservedInstall = { strategy: 'unknown', note: INSTALL_UNMOUNTED }\n\n/** 记录最近一次安装策略(供兼容报告展示;失败路径也记录,便于诊断)。 */\nfunction recordInstall(strategy: SettingsInstallStrategy, note: string): SettingsInstallStrategy {\n observedInstall = { strategy, note }\n return strategy\n}\n\n/** 读取观测到的安装策略(供报告;测试可用 reset 复位)。 */\nexport function settingsInstallStrategy(): SettingsInstallStrategy {\n return observedInstall.strategy\n}\n\n/** 读取观测到的安装策略说明文案。 */\nexport function settingsInstallNote(): string {\n return observedInstall.note\n}\n\n/** 复位安装策略观测(测试隔离用)。 */\nexport function resetSettingsInstallObserved(): void {\n observedInstall = { strategy: 'unknown', note: INSTALL_UNMOUNTED }\n}\n\n/**\n * 设置 section 版本自适应安装(核心策略分派)。\n * legacy:dsh-settings 仍导出 installSettingsSection(rc 线)→ 原样调用,行为与旧版一致。\n * service:该导出已移除(0.1.2-alpha 起)→ 经 ctx.inject(['settings']) 走服务方法\n * provider.installSection(owner, ns, schema, entry, hooks)(等义封装,含\n * base 层与 fiber 卸载回退)。回调内方法缺失再降级记录 none。\n * none:两条路由都不存在 → 仅记录并告警,调用方按配置值运行。\n * 全程不抛错、不产生未捕获 rejection。\n * @author ddj 2026年09月02号\n * @param ctx DSH host 上下文(inject 可选探测)\n * @param ns 设置命名空间\n * @param schema schemastery schema\n * @param entry 初始设置值(作为 base 层)\n * @param hooks 设置源绑定与变更回调\n * @param loader 依赖装载器(测试注入)\n * @returns 采用/观测到的策略\n */\nexport async function runSettingsInstall(\n ctx: Ctx,\n ns: string,\n schema: unknown,\n entry: object,\n hooks: { setSource: (source: () => unknown) => void; onChange: () => void; validate?: unknown },\n loader: SettingsDepsLoader = loadSettingsDeps,\n): Promise<SettingsInstallStrategy> {\n let deps: SettingsDeps | null = null\n try {\n deps = await loader()\n } catch {\n /* 装载失败按缺失处理 */\n }\n if (!deps) {\n log.warn('设置依赖不可用,section ' + ns + ' 未安装(配置回退)')\n return recordInstall('none', INSTALL_NONE)\n }\n const legacy = deps.installSettingsSection\n if (typeof legacy === 'function') {\n try {\n legacy(ctx, ns, schema, entry, hooks)\n return recordInstall('legacy', INSTALL_LEGACY)\n } catch (error) {\n log.warn('legacy 设置安装失败,尝试服务路由:' + String(error))\n }\n }\n const ctxInject = (ctx as unknown as { inject?: (services: string[], callback: (sctx: unknown) => void) => unknown }).inject\n if (typeof ctxInject !== 'function') return recordInstall('none', INSTALL_NONE)\n try {\n ctxInject(['settings'], (sctx: unknown) => {\n const sc = sctx as { get?: (name: string) => unknown; settings?: unknown }\n const provider = typeof sc.get === 'function' ? sc.get('settings') : sc.settings\n const install = (provider as { installSection?: unknown } | undefined)?.installSection\n if (typeof install !== 'function') {\n log.warn('settings 服务无 installSection(DSH 版本 API 变化),section ' + ns + ' 降级为配置值')\n recordInstall('none', INSTALL_NONE)\n return\n }\n try {\n install.call(provider, ctx, ns, schema, entry, hooks)\n recordInstall('service', INSTALL_SERVICE)\n } catch (error) {\n log.warn('settings.installSection 安装失败(' + String(error) + '),section ' + ns + ' 降级为配置值')\n recordInstall('none', INSTALL_NONE)\n }\n })\n } catch (error) {\n log.warn('settings 服务路由不可用(' + String(error) + ')')\n return recordInstall('none', INSTALL_NONE)\n }\n // inject 回调若同步执行(settings 已就绪)会覆写观测值;仍未执行(unknown)时乐观按 service 记录\n if (observedInstall.strategy !== 'unknown') return observedInstall.strategy\n return recordInstall('service', '已调度 settings 服务 installSection(等待 settings 就绪)')\n}\n\n/**\n * 按命令目录构建 keybindings 显式键形状(每键独立默认值)。\n * @author ddj 2026年08月26号\n * @param z schemastery 命名空间\n * @returns keybindings 字段形状\n */\nfunction keybindingsShape(z: SettingsDeps['z']): Record<string, unknown> {\n const shape: Record<string, unknown> = {}\n for (const [id, chord] of Object.entries(KEYBINDING_DEFAULTS)) shape[id] = z.string().default(chord)\n return shape\n}\n\nfunction normalizeValue(value: unknown): string {\n if (typeof value !== 'string' || value.trim() === '') return FILE_OPEN_DEFAULT\n return value.trim()\n}\n\nfunction configValue(config: unknown): string {\n return normalizeValue((config as { fileOpenTool?: unknown } | undefined)?.fileOpenTool)\n}\n\n/** 配置/设置里的深链基址(缺省/非法回退默认值)。 */\nfunction baseValueOf(config: unknown): string {\n const raw = (config as { integrationBaseUrl?: unknown } | undefined)?.integrationBaseUrl\n return typeof raw === 'string' && raw.trim() ? raw.trim() : INTEGRATION_BASE_DEFAULT\n}\n\n/**\n * 安装设置 section(版本自适应;任一策略不可用返回 false 不抛错)。\n * @author ddj 2026年08月24号 / 2026年09月02号\n * @param ctx DSH host 上下文\n * @param ns 设置命名空间\n * @param entry 初始设置值\n * @param hooks 设置源绑定与变更回调\n * @param loader 依赖装载器(测试注入)\n * @returns 是否成功安装\n */\nexport async function installOpenSettingsSection(\n ctx: Ctx,\n ns: string,\n entry: FileOpenSettings,\n hooks: { setSource: (source: () => FileOpenSettings) => void; onChange: () => void },\n loader: SettingsDepsLoader = loadSettingsDeps,\n): Promise<boolean> {\n let deps: SettingsDeps | null = null\n try {\n deps = await loader()\n } catch {\n /* 装载失败按缺失处理 */\n }\n if (!deps) return false\n const schema = deps.z.object({\n fileOpenTool: deps.z.string().default(FILE_OPEN_DEFAULT),\n keybindings: deps.z.object(keybindingsShape(deps.z)).default({ ...KEYBINDING_DEFAULTS }),\n sidebarMinWidth: deps.z.number().default(300),\n integrationBaseUrl: deps.z.string().default(INTEGRATION_BASE_DEFAULT),\n // AI 内联补全(默认关;provider/model 空 = 自动路由;effort 空 = 跟随模型默认)\n aiInline: deps.z.boolean().default(AI_CONFIG_DEFAULT.enabled),\n aiProvider: deps.z.string().default(AI_CONFIG_DEFAULT.provider),\n aiModel: deps.z.string().default(AI_CONFIG_DEFAULT.model),\n aiEffort: deps.z.string().default(AI_CONFIG_DEFAULT.effort),\n })\n const strategy = await runSettingsInstall(ctx, ns, schema, entry, {\n setSource: (source) => hooks.setSource(source as () => FileOpenSettings),\n onChange: hooks.onChange,\n }, loader)\n return strategy === 'legacy' || strategy === 'service'\n}\n\n/** AI 配置脏值读取(settings 未就绪时回退默认)。 */\nfunction aiValueOf(stored: unknown): { enabled: boolean; provider: string; model: string; effort: string } {\n const raw = (stored ?? {}) as Record<string, unknown>\n return {\n enabled: raw.aiInline === true,\n provider: typeof raw.aiProvider === 'string' ? raw.aiProvider : AI_CONFIG_DEFAULT.provider,\n model: typeof raw.aiModel === 'string' ? raw.aiModel : AI_CONFIG_DEFAULT.model,\n effort: typeof raw.aiEffort === 'string' ? raw.aiEffort : AI_CONFIG_DEFAULT.effort,\n }\n}\n\n/**\n * 注册设置命名空间,并提供 host 侧的读取与更新状态。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文\n * @param config 插件组合配置\n * @param onChange 设置变化回调\n * @returns 设置状态(fileOpenTool 值 + AI 补全配置读写)\n */\nexport function setupOpenSettings(ctx: Ctx, config: unknown, onChange: (value: string) => void): FileOpenSettingsState & { ai: () => AiConfigView; aiUpdate: (patch: AiConfigPatch, expectedRevision?: number) => Promise<AiConfigView> } {\n let current = configValue(config)\n let revision: number | undefined\n let provider: SettingsProvider | undefined\n const notify = (value: unknown): void => { current = normalizeValue(value); onChange(current) }\n const syncRevision = (): void => {\n const descriptor = provider?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n revision = descriptor?.revision\n }\n const setSource = (source: () => FileOpenSettings): void => notify(source().fileOpenTool)\n const settingsChange = (): void => syncRevision()\n\n /** AI 配置当前值(settings 未就绪回退默认)。 */\n let aiCurrent: AiConfigView = { ...AI_CONFIG_DEFAULT }\n const aiSync = (): void => {\n const descriptor = provider?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const stored = descriptor?.value\n aiCurrent = stored !== undefined ? aiValueOf(stored) : aiCurrent\n }\n\n void installOpenSettingsSection(ctx, FILE_OPEN_SETTINGS_NS, { fileOpenTool: current, integrationBaseUrl: baseValueOf(config) }, {\n setSource: (source) => {\n notify(source().fileOpenTool)\n aiCurrent = aiValueOf(source())\n syncRevision()\n },\n onChange: settingsChange,\n })\n ctx.inject?.(['settings'], (settingsCtx: Ctx) => {\n provider = settingsCtx.get('settings')\n aiSync()\n syncRevision()\n })\n\n return {\n get value() { return current },\n get revision() { return revision },\n update: async (value: string, expectedRevision?: number): Promise<void> => {\n const next = normalizeValue(value)\n if (!provider?.update) { notify(next); return }\n await provider.update(FILE_OPEN_SETTINGS_NS, { fileOpenTool: next }, expectedRevision)\n const descriptor = provider.describe?.({ redactSecrets: true })?.find((item: { ns?: string; value?: unknown }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const stored = descriptor?.value as { fileOpenTool?: unknown } | undefined\n notify(stored?.fileOpenTool ?? next)\n syncRevision()\n },\n ai: () => aiCurrent,\n aiUpdate: async (patch: AiConfigPatch, expectedRevision?: number): Promise<AiConfigView> => {\n if (!provider?.update) {\n // settings 不可用:内存态生效(重启回落默认),保持与 fileOpenTool 的降级语义一致\n if (patch.enabled !== undefined) aiCurrent.enabled = patch.enabled\n if (patch.provider !== undefined) aiCurrent.provider = patch.provider\n if (patch.model !== undefined) aiCurrent.model = patch.model\n if (patch.effort !== undefined) aiCurrent.effort = patch.effort\n return aiCurrent\n }\n const stored = { ...aiCurrent }\n const body: Record<string, unknown> = {}\n if (patch.enabled !== undefined) { stored.enabled = patch.enabled; body.aiInline = patch.enabled }\n if (patch.provider !== undefined) { stored.provider = patch.provider; body.aiProvider = patch.provider }\n if (patch.model !== undefined) { stored.model = patch.model; body.aiModel = patch.model }\n if (patch.effort !== undefined) { stored.effort = patch.effort; body.aiEffort = patch.effort }\n await provider.update(FILE_OPEN_SETTINGS_NS, body, expectedRevision)\n aiSync()\n return aiCurrent\n },\n }\n}\n\nexport function normalizeFileOpenTool(value: unknown): string { return normalizeValue(value) }\n","/**\n * dsh-vscode-mode host — 开发形态管理(安装形态切换)。\n * 开发形态 = profile 中以 link: 依赖 + junction 指向工作区的安装(用于插件开发);\n * 关闭 = 改回版本依赖 + 删 junction + pnpm install 装配正式版。\n * 切换后需重启 DSH 生效(运行中的代码仍是旧形态)。\n * 与 compat.ts 存在模块环(devForm 用 pluginVersionOf、compat 用 readDevForm),\n * 双方仅在函数体内交叉使用,模块求值期无依赖,ESM 安全。\n * 作者 ddj 2026-08-24\n */\nimport { existsSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { homedir } from 'node:os'\nimport { PLUGIN_NAME, pluginVersionOf } from './compat.js'\nimport type { DevFormInfo } from './shared/compat.js'\nimport type { Ctx } from './store.js'\n\n/** 扫描 $DSH_HOME/profiles 找到依赖本插件的 profile 目录(无 env 依赖,多 profile 安全)。 */\nexport function findProfileDir(): string | undefined {\n const home = process.env.DSH_HOME ?? join(homedir(), '.dsh')\n try {\n for (const name of readdirSync(join(home, 'profiles'))) {\n const pkgFile = join(home, 'profiles', name, 'package.json')\n if (!existsSync(pkgFile)) continue\n try {\n const pkg = JSON.parse(readFileSync(pkgFile, 'utf8')) as { dependencies?: Record<string, unknown> } | undefined\n if (pkg?.dependencies?.[PLUGIN_NAME]) return dirname(pkgFile)\n } catch {\n /* 坏 manifest 跳过该 profile */\n }\n }\n } catch {\n /* profiles 目录不存在时放弃 */\n }\n return undefined\n}\n\n/**\n * 读取当前开发形态(manifest link: 判定)。\n * @author ddj 2026年08月24号\n * @returns 开发形态状态\n */\nexport function readDevForm(): DevFormInfo {\n const profileDir = findProfileDir()\n if (!profileDir) return { enabled: false }\n try {\n const text = readFileSync(join(profileDir, 'package.json'), 'utf8').replace(/^\\uFEFF/, '')\n const pkg = JSON.parse(text) as { dependencies?: Record<string, unknown> } | undefined\n const spec = pkg?.dependencies?.[PLUGIN_NAME]\n if (typeof spec === 'string' && spec.startsWith('link:')) {\n return { enabled: true, path: spec.slice('link:'.length) }\n }\n } catch {\n /* manifest 不可读视为非开发形态 */\n }\n return { enabled: false }\n}\n\n/**\n * 规划切换后的 manifest 文本(纯函数,可单测;非法 JSON 抛错)。\n * @author ddj 2026年08月24号\n * @param text 原 manifest 文本\n * @param enabled 目标形态(true=link:,false=版本)\n * @param path 工作区路径(开启时必填)\n * @param version 版本号(关闭时使用,写入 ^<version>)\n * @returns 新 manifest 文本(无 BOM,2 空格缩进)\n */\nexport function planManifest(text: string, enabled: boolean, path: string, version: string): string {\n const data = JSON.parse(text.replace(/^\\uFEFF/, '')) as { dependencies?: Record<string, unknown> }\n if (!data.dependencies || typeof data.dependencies !== 'object') {\n throw new Error('profile package.json 缺少 dependencies 字段')\n }\n data.dependencies[PLUGIN_NAME] = enabled ? 'link:' + path.replace(/\\\\/g, '/') : '^' + version\n return JSON.stringify(data, null, 2) + '\\n'\n}\n\n/** 建立或移除 node_modules 下的开发 junction(目标不存在时开启失败)。 */\nfunction applyJunction(profileDir: string, enabled: boolean, target: string): void {\n const linkDir = join(profileDir, 'node_modules', PLUGIN_NAME)\n if (existsSync(linkDir)) rmSync(linkDir, { recursive: true, force: true })\n if (!enabled) return\n if (!existsSync(target)) throw new Error('工作区路径不存在:' + target)\n symlinkSync(target, linkDir, 'junction')\n}\n\n/**\n * 切换开发形态:改 manifest → 建/删 junction → pnpm install(subprocess)。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文(subprocess 服务)\n * @param enabled 目标形态\n * @param path 工作区绝对路径(开启时必填)\n * @returns 切换结果(restart=true 表示需重启 DSH 生效)\n */\nexport async function setDevForm(ctx: Ctx, enabled: boolean, path?: string): Promise<{ ok: boolean; error?: string; restart: boolean }> {\n const profileDir = findProfileDir()\n if (!profileDir) return { ok: false, error: '未找到依赖本插件的 profile(检查 DSH_HOME/profiles)', restart: false }\n const current = readDevForm()\n const target = (path ?? current.path ?? '').replace(/\\\\/g, '/')\n if (enabled && !target) return { ok: false, error: '开启开发形态需要提供工作区路径(path 参数)', restart: false }\n if (enabled === current.enabled && (!enabled || target === current.path)) {\n return { ok: true, restart: false }\n }\n try {\n const pkgFile = join(profileDir, 'package.json')\n const version = pluginVersionOf()\n if (!version) return { ok: false, error: '读取插件版本失败,无法写入版本依赖', restart: false }\n const next = planManifest(readFileSync(pkgFile, 'utf8').replace(/^\\uFEFF/, ''), enabled, target, version)\n writeFileSync(pkgFile, next, 'utf8')\n applyJunction(profileDir, enabled, target)\n const installError = await runPnpmInstall(ctx, profileDir)\n return { ok: !installError, error: installError, restart: true }\n } catch (error) {\n return { ok: false, error: String(error), restart: false }\n }\n}\n\n/** 在 profile 目录执行 pnpm install(subprocess 契约:spawn({argv,cwd,stdio,graceMs}))。 */\nasync function runPnpmInstall(ctx: Ctx, profileDir: string): Promise<string | undefined> {\n const sub = ctx.get('subprocess')\n if (!sub || typeof sub.spawn !== 'function') return 'manifest/junction 已更新,但缺少 subprocess:请手动在 profile 目录运行 pnpm install'\n const handle = sub.spawn({\n argv: ['pnpm', 'install'],\n cwd: profileDir,\n stdio: { stdout: { maxBytes: 1 << 16 }, stderr: { maxBytes: 1 << 16 }, stdin: 'ignore' },\n graceMs: 120000,\n })\n const outcome = await handle.done\n const code = outcome?.exitCode ?? outcome?.code\n if (code !== 0) {\n const stderr = handle.collected?.stderr?.readFrom(0).text ?? ''\n return 'pnpm install 失败(exit ' + code + '):' + stderr.slice(0, 500)\n }\n return undefined\n}\n","/**\n * dsh-vscode-mode host — DSH 核心版本探测与区间匹配(版本适配机制的地基)。\n * 约定:以运行时可解析的 @deepseek-ai/dsh-settings 包版本代表 DSH 核心版本——\n * 核心包发布锁步同版(rc.2 / alpha.2 全树同版实证),且该包是插件动态依赖面、\n * exports 已放行 ./package.json。解析失败按候选降级(dsh-web-app / dsh-base / dsh),\n * 全部失败返回空串(报告显示\"未探测\",功能按能力探测运行)。\n * 纯函数(parse / compare / inRange / familyLabel)可在 node 环境单测。\n * 作者 ddj 2026-09-02\n */\nimport { readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\n\n/** 归一化版本:主/次/补丁 + 预发布标识数组(0.1.2-alpha.2 → pre=['alpha','2'])。 */\nexport interface DshVersion {\n major: number\n minor: number\n patch: number\n pre: string[]\n}\n\nconst VERSION_RE = /^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/\n\n/** 解析版本串;非法返回 null(不抛错)。 */\nexport function parseDshVersion(input: string): DshVersion | null {\n const match = VERSION_RE.exec(input.trim())\n if (!match) return null\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n pre: match[4] ? match[4].split('.') : [],\n }\n}\n\n/** 预发布标识比较:纯数字按值;数字段 < 字母段;字母按字典序(semver 规则)。 */\nfunction comparePreId(a: string, b: string): number {\n const numericA = /^\\d+$/.test(a)\n const numericB = /^\\d+$/.test(b)\n if (numericA && numericB) return Number(a) - Number(b)\n if (numericA !== numericB) return numericA ? -1 : 1\n return a < b ? -1 : a > b ? 1 : 0\n}\n\n/** 比较两个已解析版本:a<b → -1;相等 → 0;a>b → 1。 */\nexport function compareDshVersions(a: DshVersion, b: DshVersion): number {\n for (const key of ['major', 'minor', 'patch'] as const) {\n if (a[key] !== b[key]) return a[key] < b[key] ? -1 : 1\n }\n const samePre = a.pre.length === b.pre.length && a.pre.every((part, index) => part === b.pre[index])\n if (samePre) return 0\n if (a.pre.length === 0) return 1\n if (b.pre.length === 0) return -1\n const length = Math.max(a.pre.length, b.pre.length)\n for (let i = 0; i < length; i++) {\n const left = a.pre[i]\n const right = b.pre[i]\n if (left === undefined) return -1\n if (right === undefined) return 1\n const cmp = comparePreId(left, right)\n if (cmp !== 0) return cmp\n }\n return 0\n}\n\n/** 版本区间(含端点):from/to 为空表示该侧不设界。 */\nexport interface DshRange {\n from?: string\n to?: string\n}\n\n/** 版本是否落在区间内(入参解析失败一律不命中)。 */\nexport function inDshRange(version: DshVersion | null | undefined, range: DshRange): boolean {\n if (!version) return false\n if (range.from) {\n const lower = parseDshVersion(range.from)\n if (!lower || compareDshVersions(version, lower) < 0) return false\n }\n if (range.to) {\n const upper = parseDshVersion(range.to)\n if (!upper || compareDshVersions(version, upper) > 0) return false\n }\n return true\n}\n\n/** 版本线标签:报告与文档展示版本归属;不可解析返回 '未知'。 */\nexport function familyLabel(input: string): string {\n const version = parseDshVersion(input)\n if (!version) return '未知'\n if (inDshRange(version, { from: '0.1.3-alpha.1' })) return '0.1.3-alpha 及更新(对话文件链接=remote.session.openWorkspacePath)'\n if (inDshRange(version, { from: '0.1.2-alpha.1' })) return '0.1.2-alpha 及更新(设置 API=settings.installSection)'\n return '0.1.0/0.1.1 rc 线(设置 API=installSettingsSection)'\n}\n\n/** 探测候选:按与插件运行环境相关性排序,逐个尝试解析 package.json。 */\nconst VERSION_CANDIDATES = [\n '@deepseek-ai/dsh-settings/package.json',\n '@deepseek-ai/dsh-web-app/package.json',\n '@deepseek-ai/dsh-base/package.json',\n '@deepseek-ai/dsh/package.json',\n]\n\nlet detectedVersion: string | undefined\n\n/** 探测运行中 DSH 核心版本(模块级缓存;失败空串,不抛错)。 */\nexport function detectDshVersion(): string {\n if (detectedVersion !== undefined) return detectedVersion\n detectedVersion = ''\n const require = createRequire(import.meta.url)\n for (const specifier of VERSION_CANDIDATES) {\n try {\n const file = require.resolve(specifier)\n const pkg = JSON.parse(readFileSync(file, 'utf8')) as { version?: unknown }\n if (typeof pkg.version === 'string' && parseDshVersion(pkg.version) !== null) {\n detectedVersion = pkg.version\n break\n }\n } catch {\n /* exports 未放行或包缺失:尝试下一个候选 */\n }\n }\n return detectedVersion\n}\n","/**\n * dsh-vscode-mode RPC contract — method names, per-method request/ok payloads,\n * and the typed handler map shared by the host dispatcher and the client\n * fetch wrapper. 载荷形状与历史实现一字不差,仅把隐式约定类型化。\n *\n * Purity rule: no node/react imports (same as types.ts).\n * 作者 ddj 2026-08-20\n */\nimport type {\n ArchiveBatch,\n ArchiveEntry,\n RecordView,\n StaleHunk,\n} from './types.js'\nimport type { MpcConfig, MpcProject, MpcProjectSaveInput, MpcServer } from './mcp.js'\nimport type { CompatReport, DevFormInfo } from './compat.js'\nimport type { ShellIntegrationStatus, UnityListPayload, UnityProjectEntry } from './integration.js'\nimport type { RuleInfo, RuleProject, RuleRefInput, RuleSaveInput } from './rules.js'\nimport type { SnippetEntry, SnippetInfo, SnippetProject, SnippetRefInput, SnippetSaveInput } from './snippets.js'\nimport type { LspEnvInstallState, LspExtInfo, LspExtUpdate, LspHover, LspLocation, LspMarketItem, LspPosition, LspSemanticTokens, LspServerStatus, LspSymbol } from './lsp.js'\nimport type { AiConfigPatch, AiConfigView, AiDirectoryView, AiInlineRequest, AiInlineResult } from './ai.js'\n\n/** webServer 精确路由。 */\nexport const RPC_PATH = '/edrv/rpc'\n\n/**\n * 图片扩展名(小写、无点)→ MIME。edrv.read base64 响应与 client 图片预览共用,\n * 收敛在此避免 host/client 两处漂移。\n * @author ddj 2026年09月08号\n */\nexport const IMAGE_MIME: Record<string, string> = {\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n webp: 'image/webp',\n bmp: 'image/bmp',\n ico: 'image/x-icon',\n avif: 'image/avif',\n svg: 'image/svg+xml',\n}\n\n/**\n * 路径 → 图片 MIME:按 basename 扩展名小写查 {@link IMAGE_MIME},未命中回退 application/octet-stream。\n * @author ddj 2026年09月08号\n * @param path 文件路径(`/` 或 `\\` 分隔均可)\n * @returns MIME 字符串\n */\nexport function imageMimeOf(path: string): string {\n const base = String(path || '').split(/[\\\\/]/).pop() || ''\n const dot = base.lastIndexOf('.')\n const ext = dot > 0 ? base.slice(dot + 1).toLowerCase() : ''\n return IMAGE_MIME[ext] ?? 'application/octet-stream'\n}\n\n/** PDF 统一 MIME(host base64 响应与 client PDF 面板同源,避免两处漂移)。 */\nexport const PDF_MIME = 'application/pdf'\n\n/**\n * 路径 → 二进制预览 MIME:PDF 特判 {@link PDF_MIME},其余走图片表回退 octet-stream。\n * @author ddj 2026年09月22号\n * @param path 文件路径(`/` 或 `\\` 分隔均可)\n * @returns MIME 字符串\n */\nexport function binaryMimeOf(path: string): string {\n const base = String(path || '').split(/[\\\\/]/).pop() || ''\n const dot = base.lastIndexOf('.')\n if (dot > 0 && base.slice(dot + 1).toLowerCase() === 'pdf') return PDF_MIME\n return imageMimeOf(path)\n}\n\n/** 决策作用域:call=整条记录,hunk=单个差异块。 */\nexport type RpcScope = 'call' | 'hunk'\n\n/** 目录树单项(edrv.listDir 返回;path 相对工作区根,'/' 分隔)。 */\nexport interface TreeEntry {\n name: string\n path: string\n type: 'file' | 'directory' | 'other'\n size?: number\n}\n\n/** 内容搜索单条命中(edrv.searchContent 返回;path 相对工作区根,列为 1-based UTF-16)。 */\nexport interface SearchContentMatch {\n path: string\n line: number\n startColumn: number\n endColumn: number\n text: string\n}\n\n// --region 会话性能管理(edrv.perf.*)\n/** 一个已持久化会话的体积/活跃信息(edrv.perf.inventory 每行)。 */\nexport interface PerfSession {\n sessionId: string\n workspaceKey: string\n bytes: number\n mtime: number\n active: boolean\n}\n\n/** 一个工作区的会话聚合(edrv.perf.inventory)。 */\nexport interface PerfWorkspace {\n workspaceKey: string\n sessionCount: number\n totalBytes: number\n minMtime: number\n maxMtime: number\n}\n\n/** 会话盘点汇总。 */\nexport interface PerfTotals {\n workspaces: number\n sessions: number\n totalBytes: number\n}\n\n/** 一次移出/恢复操作中的单个会话条目。 */\nexport interface PerfMoveItem {\n workspaceKey: string\n sessionId: string\n bytes: number\n}\n\n/** 一次移出操作的失败项。 */\nexport interface PerfMoveFailure {\n workspaceKey: string\n sessionId: string\n error: string\n}\n\n/** 侧车摘要(edrv.perf.sidecarSummary):紧凑关键字段,不整份读 sidecar 进对话。 */\nexport interface SidecarPerfSummary {\n active: number\n pendingByFile: { path: string; pending: number }[]\n archiveBytes: number\n}\n// --endregion\n\n/** 一条批量决策项(decideBatch 的 items 元素,与 accept/reject 单条参数同构)。 */\nexport interface DecideItem {\n callId: string\n scope?: RpcScope\n hunkIndex?: number\n decision: 'accepted' | 'rejected'\n}\n\n/** 批量决策逐项结果。 */\nexport interface DecideResult {\n callId: string\n ok: boolean\n error?: string\n record?: RecordView\n}\n\n/** 每个方法的请求参数(sessionId 为公共可选字段)。 */\nexport interface RpcRequestMap {\n 'edrv.list': { sessionId?: string; callIds?: string[]; skipStale?: boolean }\n 'edrv.accept': { sessionId?: string; callId: string; scope?: RpcScope; hunkIndex?: number }\n 'edrv.reject': { sessionId?: string; callId: string; scope?: RpcScope; hunkIndex?: number }\n 'edrv.decideBatch': { sessionId?: string; items: DecideItem[] }\n 'edrv.read': { sessionId?: string; path: string; encoding?: 'base64' }\n 'edrv.original': { sessionId?: string; path: string }\n 'edrv.save': { sessionId?: string; path: string; content: string }\n 'edrv.saveBinary': { sessionId?: string; path: string; content: string; encoding: 'base64' }\n 'edrv.archiveList': { sessionId?: string }\n 'edrv.archiveRead': { sessionId?: string; path?: string }\n 'edrv.rollback': { sessionId?: string; path: string; batch?: number }\n 'edrv.debug': { sessionId?: string; text: string }\n 'edrv.searchFiles': { sessionId?: string; query: string }\n 'edrv.searchContent': { sessionId?: string; query: string; matchCase?: boolean; wholeWord?: boolean; regex?: boolean; maxResults?: number; include?: string[]; exclude?: string[] }\n 'edrv.listDir': { sessionId?: string; path: string; force?: boolean }\n 'edrv.revealInExplorer': { sessionId?: string; path: string }\n 'mcp.list': {}\n 'mcp.save': { config: MpcConfig }\n 'mcp.remove': { id: string }\n 'mcp.toggle': { id: string; enabled: boolean }\n 'mcp.refresh': { id: string }\n 'mcp.projects': {}\n 'mcp.projectSave': MpcProjectSaveInput\n 'mcp.projectRemove': { workspacePath: string; serverName: string }\n 'mcp.projectToggle': { workspacePath: string; serverName: string; enabled: boolean }\n 'mcp.projectRefresh': { workspacePath: string; serverName: string }\n 'vscode.fileOpenSettingsGet': {}\n 'vscode.fileOpenSettingsUpdate': { fileOpenTool: string; integrationBaseUrl?: string; expectedRevision?: number }\n 'edrv.integration.status': {}\n 'edrv.integration.register': {}\n 'edrv.integration.unregister': {}\n 'edrv.unity.list': {}\n 'edrv.unity.add': { path: string }\n 'edrv.unity.remove': { path: string }\n 'edrv.unity.install': { path: string }\n 'edrv.externalStat': { path: string }\n 'edrv.external.handoff': { paths: string[]; line?: number; column?: number }\n 'edrv.external.pending': {}\n 'edrv.external.pendingState': { token: string; take?: boolean }\n 'vscode.devFormGet': {}\n 'vscode.devFormSet': { enabled: boolean; path?: string }\n 'compat': {}\n 'edrv.lsp.status': { sessionId?: string }\n 'edrv.lsp.detect': {}\n 'edrv.lsp.sync': { sessionId?: string; path: string; text: string; version: number }\n 'edrv.lsp.close': { sessionId?: string; path: string }\n 'edrv.lsp.definition': { sessionId?: string; path: string; position: LspPosition }\n 'edrv.lsp.references': { sessionId?: string; path: string; position: LspPosition; includeDeclaration?: boolean }\n 'edrv.lsp.documentSymbol': { sessionId?: string; path: string }\n 'edrv.lsp.workspaceSymbol': { sessionId?: string; query: string }\n 'edrv.lsp.hover': { sessionId?: string; path: string; position: LspPosition }\n 'edrv.lsp.semanticTokens': { sessionId?: string; path: string }\n 'edrv.lsp.redetect': { languageId: string }\n 'edrv.lsp.envInstall': { languageId: string; id: string }\n 'edrv.lsp.envState': {}\n 'edrv.lsp.configGet': {}\n 'edrv.lsp.configUpdate': { languageId: string; enabled?: boolean; command?: string; path?: string }\n 'edrv.lsp.ext.list': {}\n 'edrv.lsp.ext.install': { vsixPath?: string; namespace?: string; name?: string; version?: string }\n 'edrv.lsp.ext.uninstall': { id: string }\n 'edrv.lsp.ext.update': { id: string }\n 'edrv.lsp.ext.updates': {}\n 'edrv.lsp.ext.market': { query: string; size?: number }\n 'edrv.ai.inline': AiInlineRequest\n 'edrv.ai.models': { force?: boolean }\n 'edrv.ai.configGet': {}\n 'edrv.ai.configUpdate': AiConfigPatch\n 'edrv.perf.inventory': { sessionId?: string }\n 'edrv.perf.sessionSize': { sessionId?: string; cwd: string }\n 'edrv.perf.movePlan': { workspaceKey?: string; sessionIds?: string[]; minBytes?: number; olderThanDays?: number }\n 'edrv.perf.moveOut': { workspaceKey: string; sessionIds: string[]; dryRun?: boolean }\n 'edrv.perf.restore': { workspaceKey: string; sessionId: string }\n 'edrv.perf.purgeArchive': { olderThanDays: number }\n 'edrv.perf.sidecarSummary': { sessionId?: string }\n 'edrv.perf.configGet': {}\n 'edrv.perf.configApply': {}\n 'edrv.perf.configUndo': {}\n 'rules.list': {}\n 'rules.read': RuleRefInput\n 'rules.save': RuleSaveInput\n 'rules.remove': RuleRefInput\n 'rules.toggle': RuleRefInput & { enabled: boolean }\n 'snippets.list': {}\n 'snippets.read': SnippetRefInput\n 'snippets.save': SnippetSaveInput\n 'snippets.remove': SnippetRefInput\n 'snippets.entries': { sessionId?: string }\n}\n\nexport type RpcMethod = keyof RpcRequestMap\n\n/** 每个方法成功(ok:true)时的附加载荷。 */\nexport interface RpcOkMap {\n 'edrv.list': { records: RecordView[] }\n 'edrv.accept': { record: RecordView }\n 'edrv.reject': { record: RecordView }\n 'edrv.decideBatch': { results: DecideResult[] }\n 'edrv.read': { content: string; size: number; encoding?: 'base64'; mime?: string }\n 'edrv.original': { content: string; size: number; stale: StaleHunk[]; fallback: boolean }\n 'edrv.save': object\n 'edrv.saveBinary': object\n 'edrv.archiveList': { entries: ArchiveEntry[] }\n 'edrv.archiveRead': { batches: ArchiveBatch[] }\n 'edrv.rollback': { path: string; batch: number | null }\n 'edrv.debug': object\n 'edrv.searchFiles': { files: string[]; truncated: boolean }\n 'edrv.searchContent': { matches: SearchContentMatch[]; truncated: boolean; warning?: string }\n 'edrv.listDir': { root: string; path: string; entries: TreeEntry[] }\n 'edrv.revealInExplorer': { revealed: string }\n 'mcp.list': { servers: MpcServer[] }\n 'mcp.save': { server: MpcServer }\n 'mcp.remove': object\n 'mcp.toggle': { server: MpcServer }\n 'mcp.refresh': { server: MpcServer }\n 'mcp.projects': { projects: MpcProject[] }\n 'mcp.projectSave': { project: MpcProject }\n 'mcp.projectRemove': { project: MpcProject }\n 'mcp.projectToggle': { project: MpcProject }\n 'mcp.projectRefresh': { project: MpcProject }\n 'vscode.fileOpenSettingsGet': { fileOpenTool: string; integrationBaseUrl: string; revision?: number }\n 'vscode.fileOpenSettingsUpdate': { fileOpenTool: string; integrationBaseUrl: string; revision?: number }\n 'edrv.integration.status': ShellIntegrationStatus\n 'edrv.integration.register': ShellIntegrationStatus\n 'edrv.integration.unregister': ShellIntegrationStatus\n 'edrv.unity.list': UnityListPayload\n 'edrv.unity.add': { project: UnityProjectEntry }\n 'edrv.unity.remove': object\n 'edrv.unity.install': { project: UnityProjectEntry }\n 'edrv.externalStat': { kind: 'file' | 'directory' | 'missing' }\n 'edrv.external.handoff': { clients: number; token: string }\n 'edrv.external.pending': { open: { paths: string[]; line?: number; column?: number } | null }\n 'edrv.external.pendingState': { delivered: boolean }\n 'vscode.devFormGet': { devForm: DevFormInfo }\n 'vscode.devFormSet': { devForm: DevFormInfo; restart: boolean }\n 'compat': { report: CompatReport }\n 'edrv.lsp.status': { servers: LspServerStatus[] }\n 'edrv.lsp.detect': { servers: LspServerStatus[] }\n 'edrv.lsp.sync': object\n 'edrv.lsp.close': object\n 'edrv.lsp.definition': { locations: LspLocation[]; truncated?: boolean }\n 'edrv.lsp.references': { locations: LspLocation[]; truncated?: boolean }\n 'edrv.lsp.documentSymbol': { symbols: LspSymbol[] }\n 'edrv.lsp.workspaceSymbol': { symbols: LspSymbol[]; truncated?: boolean }\n 'edrv.lsp.hover': { hover?: LspHover }\n 'edrv.lsp.semanticTokens': { tokens?: LspSemanticTokens }\n 'edrv.lsp.redetect': { servers: LspServerStatus[] }\n 'edrv.lsp.envInstall': { started: boolean }\n 'edrv.lsp.envState': { states: LspEnvInstallState[] }\n 'edrv.lsp.configGet': { config: Record<string, unknown> }\n 'edrv.lsp.configUpdate': { config: Record<string, unknown>; servers?: LspServerStatus[] }\n 'edrv.lsp.ext.list': { extensions: LspExtInfo[] }\n 'edrv.lsp.ext.install': { extension: LspExtInfo; updated?: boolean }\n 'edrv.lsp.ext.uninstall': object\n 'edrv.lsp.ext.update': { extension: LspExtInfo; updated: boolean }\n 'edrv.lsp.ext.updates': { updates: LspExtUpdate[] }\n 'edrv.lsp.ext.market': { extensions: LspMarketItem[] }\n 'edrv.ai.inline': AiInlineResult\n 'edrv.ai.models': AiDirectoryView\n 'edrv.ai.configGet': AiConfigView\n 'edrv.ai.configUpdate': AiConfigView\n 'edrv.perf.inventory': { workspaces: PerfWorkspace[]; sessions: PerfSession[]; totals: PerfTotals; activeIds: string[] }\n 'edrv.perf.sessionSize': { bytes: number; exists: boolean }\n 'edrv.perf.movePlan': { items: PerfMoveItem[]; reclaimedBytes: number }\n 'edrv.perf.moveOut': { moved: PerfMoveItem[]; failures: PerfMoveFailure[]; reclaimedBytes: number }\n 'edrv.perf.restore': { restored: boolean; error?: string }\n 'edrv.perf.purgeArchive': { removed: number; reclaimedBytes: number }\n 'edrv.perf.sidecarSummary': SidecarPerfSummary\n 'edrv.perf.configGet': { profileDir?: string; patchPath?: string; applied: boolean; block: string; backup?: string }\n 'edrv.perf.configApply': { applied: boolean; backup: string; restart: boolean }\n 'edrv.perf.configUndo': { restored: boolean; error?: string; backup?: string }\n 'rules.list': { user: RuleInfo[]; projects: RuleProject[] }\n 'rules.read': { content: string }\n 'rules.save': { rule: RuleInfo }\n 'rules.remove': object\n 'rules.toggle': { rule: RuleInfo }\n 'snippets.list': { user: SnippetInfo[]; projects: SnippetProject[] }\n 'snippets.read': { content: string }\n 'snippets.save': { file: SnippetInfo }\n 'snippets.remove': object\n 'snippets.entries': { entries: SnippetEntry[] }\n}\n\n/** 统一响应:{ok:true, ...payload} 或 {ok:false, error}。 */\nexport type RpcResult<M extends RpcMethod> =\n | ({ ok: true } & RpcOkMap[M])\n | { ok: false; error: string }\n\n/** 每个方法的 handler 签名(host 分发表与 client 类型检查共用)。 */\nexport type RpcHandler<M extends RpcMethod> = (\n args: RpcRequestMap[M],\n) => Promise<RpcResult<M>>\n\n/** host RPC 分发表:method → handler。 */\nexport type RpcHandlerMap = {\n [M in RpcMethod]: RpcHandler<M>\n}\n","/**\n * dsh-vscode-mode host — 路径常量与动态路径统一出口(PathConst)。\n * 所有 host 侧文件路径/缓存键/路由前缀从这里取,避免散落内联:\n * - 静态:插件缓存根(~/.dsh/dsh-vscode-mode/cache,下分 workspace/ 工作区级与\n * user/ 用户级)、日志根、工作区侧车名、路由前缀、静态资源目录(import.meta.url 派生)\n * - 动态:每工作区树缓存文件(workspace/<id>/tree.v<schema>.json)、home 解析\n * (DSH_HOME → ~/.dsh)\n * - 清理:缓存 sweep(分级:工作区级按版本/TTL/空目录、用户级按版本/保留期、根级残留)\n * 纯函数可单测;raw fs 写入与引擎自身插件(settings-file 用 node:fs + DSH_HOME)一致。\n * 作者 ddj 2026-09-01\n */\nimport { createHash } from 'node:crypto'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { readdir, rm, stat } from 'node:fs/promises'\nimport { RPC_PATH } from './shared/rpc.js'\n\n// --region 常量\n/** 插件 id(也是 .dsh 下插件工作区目录名)。 */\nexport const PLUGIN_ID = 'dsh-vscode-mode'\n/** DSH 工作区目录名(默认 home 下)。 */\nexport const DSH_DIR_NAME = '.dsh'\n/** home 覆盖环境变量(与引擎 resolveDshHome 一致)。 */\nexport const DSH_HOME_ENV = 'DSH_HOME'\n/** 树缓存 schema 版本(文件名携带;版本递增即触发旧版清理)。 */\nexport const TREE_CACHE_SCHEMA = 1\n/** LSP provider 发现缓存 schema 版本(格式变更即递增,旧文件自动失效)。 */\nexport const LSP_SPEC_CACHE_SCHEMA = 4\n/** 树缓存保留期:超期文件视为废弃(工作区搬迁/废弃残留)。 */\nexport const TREE_RETENTION_MS = 30 * 24 * 60 * 60 * 1000\n/** 插件缓存目录总预算:超限按 mtime 从旧到新删文件,防任意增长撑爆磁盘(最后兜底)。 */\nexport const CACHE_TOTAL_CAP = 200 * 1024 * 1024\n\n/** 工作区根侧车:审查记录(用户数据,随项目走,不迁移)。 */\nexport const SIDECAR = '.dsh-edit-review.json'\n/** 工作区根侧车:归档(用户数据)。 */\nexport const SIDECAR_ARCHIVE = '.dsh-edit-review-archive.json'\n/** 旧 debug 日志文件名(工作区,迁移后由插件清理)。 */\nexport const DEBUG_LOG = '.dsh-edit-review-debug.log'\n/** 旧树缓存 sidecar 名(工作区,迁移后由插件清理;缓存可重建,删除无损)。 */\nexport const LEGACY_TREE_SIDECARS = ['.dsh-edit-review-tree.json', '.dsh-vscode-mode-tree.json']\n\n/** RPC 精确路由(shared 定义,这里统一出口)。 */\nexport { RPC_PATH }\n/** 路由前缀(兼容性检查用)。 */\nexport const ROUTE_PREFIX = '/edrv'\n/** Monaco 静态资源前缀。 */\nexport const VENDOR_PREFIX = '/edrv/vendor'\n// --endregion\n\n/** 稳定短哈希(cwd → 缓存文件名段;sha1 截断,跨运行稳定)。 */\nexport function hashOf(text: string): string {\n return createHash('sha1').update(String(text)).digest('hex').slice(0, 16)\n}\n\n// --region DSH 会话定位编码\n/**\n * 可读安全路径段编码:非安全码位 → ~XXXX 大写十六进制(`~` 本身也转义)。\n * 与 DSH 引擎 dsh-session-persistence-jsonl 的 encodeSegment 逐字节一致,\n * 用于从 cwd/id 反推 `~/.dsh/sessions` 下的会话目录,纯函数可单测。\n * @author ddj 2026年09月02号\n * @param raw 原始路径段(非空)\n * @returns 路径安全段(`.`/`..` 特判为 ~002E / ~002E~002E)\n */\nexport function encodeSegment(raw: string): string {\n if (raw.length === 0) throw new Error('cannot encode an empty path segment')\n if (raw === '.') return '~002E'\n if (raw === '..') return '~002E~002E'\n let out = ''\n for (let i = 0; i < raw.length; i++) {\n const code = raw.charCodeAt(i)\n const ch = String.fromCharCode(code)\n if (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) out += ch\n else out += '~' + code.toString(16).toUpperCase().padStart(4, '0')\n }\n return out\n}\n\n/**\n * DSH 工作区目录键:cwd → `--<可读键>--`。分隔符(/ \\ :)折叠为单个 `-`,\n * 其余非安全码位转 ~XXXX,`--` 包裹、251 截断。与引擎 projectKey 一致。\n * @author ddj 2026年09月02号\n * @param cwd 会话工作区绝对路径(非空)\n * @returns `~/.dsh/sessions` 下的工作区目录名\n */\nexport function sessionWorkspaceKey(cwd: string): string {\n if (cwd.length === 0) throw new Error('cannot encode an empty project path')\n let readable = ''\n let separatorRun = false\n for (let i = 0; i < cwd.length; i++) {\n const code = cwd.charCodeAt(i)\n const ch = String.fromCharCode(code)\n if (ch === '/' || ch === '\\\\' || ch === ':') {\n if (!separatorRun) readable += '-'\n separatorRun = true\n } else if (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) {\n readable += ch\n separatorRun = false\n } else {\n readable += '~' + code.toString(16).toUpperCase().padStart(4, '0')\n separatorRun = false\n }\n }\n return `--${(readable.replace(/^-+/, '') || 'root').slice(0, 251)}--`\n}\n\n/** DSH 会话目录段:id → 路径安全段(与引擎 encodeSegment 一致)。 */\nexport function sessionIdSegment(id: string): string {\n return encodeSegment(id)\n}\n\n/** DSH 会话根目录(~/.dsh/sessions;引擎 dsh-base 默认 root)。 */\nexport function sessionsRoot(home = dshHome()): string {\n return join(home, 'sessions')\n}\n// --endregion\n\n/**\n * 解析 DSH home:DSH_HOME(去空白)→ ~/.dsh。\n * @author ddj 2026年09月01号\n * @param env 环境映射(缺省 process.env;测试可注入)\n * @returns 归一化的 DSH home 绝对路径\n */\nexport function dshHome(env: Record<string, string | undefined> = process.env): string {\n const value = env[DSH_HOME_ENV]\n if (value && value.trim()) return value\n return join(homedir(), DSH_DIR_NAME)\n}\n\n/** 插件缓存根(~/.dsh/dsh-vscode-mode/cache,下分 workspace/ 与 user/ 两级)。 */\nexport function pluginCacheRoot(home = dshHome()): string {\n return join(home, PLUGIN_ID, 'cache')\n}\n\n/** 工作区级缓存目录:按工作区 id(cwd hash)隔离,换工作区即失效。 */\nexport function workspaceCacheDir(workspaceId: string, home = dshHome()): string {\n return join(pluginCacheRoot(home), 'workspace', workspaceId)\n}\n\n/** 用户级缓存目录(跨工作区共享;当前无实例,预留供全局偏好类缓存使用)。 */\nexport function userCacheDir(home = dshHome()): string {\n return join(pluginCacheRoot(home), 'user')\n}\n\n/** LSP provider 发现结果缓存文件(用户级:user/lsp-specs.v<schema>.json,跨会话/跨重启共享)。 */\nexport function lspSpecCacheFile(home = dshHome(), schema = LSP_SPEC_CACHE_SCHEMA): string {\n return join(userCacheDir(home), 'lsp-specs.v' + schema + '.json')\n}\n\n/** 插件日志根(~/.dsh/dsh-vscode-mode/logs,用户级)。 */\nexport function pluginLogRoot(home = dshHome()): string {\n return join(home, PLUGIN_ID, 'logs')\n}\n\n/** 每工作区树缓存文件(工作区级:workspace/<id>/tree.v<schema>.json,文件名含版本便于 sweep)。 */\nexport function treeCacheFile(cwd: string, home = dshHome(), schema = TREE_CACHE_SCHEMA): string {\n return join(workspaceCacheDir(hashOf(cwd), home), 'tree.v' + schema + '.json')\n}\n\n/** 每工作区 debug 日志文件(用户级日志根下,按 cwd hash 隔离)。 */\nexport function debugLogFile(cwd: string, home = dshHome()): string {\n return join(pluginLogRoot(home), 'debug.' + hashOf(cwd) + '.log')\n}\n\n/** 插件包 assets 目录(import.meta.url 派生;config.imageDir 可覆盖,见 imageDirOf)。 */\nexport function assetsDirOf(moduleUrl: string): string {\n return join(dirname(fileURLToPath(moduleUrl)), '..', 'assets')\n}\n\n/** Monaco AMD 静态目录(随包发布)。 */\nexport function vendorDirOf(moduleUrl: string): string {\n return join(assetsDirOf(moduleUrl), 'vendor')\n}\n\n/** 图标目录:config.imageDir 覆盖优先,否则插件包 assets/。 */\nexport function imageDirOf(config: unknown, moduleUrl: string): string {\n const cfg = config as { imageDir?: unknown } | undefined\n if (cfg && typeof cfg.imageDir === 'string' && cfg.imageDir) return cfg.imageDir.replace(/\\\\/g, '/')\n return assetsDirOf(moduleUrl)\n}\n\n// --region 缓存清理\n/** 树缓存文件名 → schema 版本(不匹配返回 null)。 */\nexport function treeSchemaOf(filename: string): number | null {\n const m = /^tree\\.v(\\d+)\\./.exec(filename)\n return m ? Number(m[1]) : null\n}\n\n/** 按「schema 版本 + 保留期」清扫某目录内文件(目录级,返回相对路径清单)。 */\nasync function sweepDirFiles(dir: string, removed: string[], now: number, dropAll: boolean): Promise<void> {\n const names = await readdir(dir).catch(() => [])\n for (const name of names) {\n const full = join(dir, name)\n let drop = dropAll\n if (!drop) {\n const schema = treeSchemaOf(name)\n if (schema === null) drop = true // 未知残留\n else if (schema !== TREE_CACHE_SCHEMA) drop = true // 旧版本\n else {\n try {\n const info = await stat(full)\n if (now - info.mtimeMs > TREE_RETENTION_MS) drop = true\n } catch (error) { drop = true }\n }\n }\n if (!drop) continue\n try {\n await rm(full, { force: true })\n removed.push(name)\n } catch (error) { /* 删除失败静默 */ }\n }\n}\n\n/** 清扫工作区级缓存:逐工作区目录按版本/TTL 清文件,空目录删除。 */\nasync function sweepWorkspaceTier(dir: string, removed: string[], now: number): Promise<void> {\n const ids = await readdir(dir).catch(() => [])\n for (const id of ids) {\n const wsDir = join(dir, id)\n await sweepDirFiles(wsDir, removed, now, false)\n const rest = await readdir(wsDir).catch(() => [])\n if (!rest.length) await rm(wsDir, { recursive: true, force: true }).catch(() => {})\n }\n}\n\n/** 总预算兜底:递归收集全部缓存文件,按 mtime 从旧到新删,直到总大小 ≤ 预算。 */\nasync function sweepByTotalCap(root: string, removed: string[], cap: number): Promise<void> {\n const files: { path: string; mtime: number; size: number }[] = []\n const walk = async (dir: string): Promise<void> => {\n const names = await readdir(dir).catch(() => [])\n for (const name of names) {\n const full = join(dir, name)\n try {\n const info = await stat(full)\n if (info.isDirectory()) await walk(full)\n else files.push({ path: full, mtime: info.mtimeMs, size: info.size })\n } catch (error) { /* 忽略不可读项 */ }\n }\n }\n await walk(root)\n let total = files.reduce((sum, f) => sum + f.size, 0)\n files.sort((a, b) => a.mtime - b.mtime)\n for (const f of files) {\n if (total <= cap) break\n try {\n await rm(f.path, { force: true })\n total -= f.size\n removed.push(f.path.slice(root.length + 1))\n } catch (error) { /* 删除失败静默 */ }\n }\n}\n\n/**\n * 清理插件缓存根(分级 + 总预算兜底):\n * - 根级残留文件(旧扁平格式/未知)→ 删\n * - workspace/ 工作区级 → 按「schema 版本 + 保留期」清文件,空目录删除\n * - user/ 用户级 → 按「schema 版本 + 保留期」清文件\n * - 总大小超预算 → 按最旧先删(最后防线,防任意增长撑爆磁盘)\n * best-effort 静默。\n * @author ddj 2026年09月01号\n * @param home DSH home(测试可注入)\n * @param cap 总预算字节数(缺省 CACHE_TOTAL_CAP;测试可注入小预算)\n * @returns 删除的文件相对路径清单\n */\nexport async function sweepTreeCache(home = dshHome(), cap = CACHE_TOTAL_CAP): Promise<string[]> {\n const dir = pluginCacheRoot(home)\n const names = await readdir(dir).catch(() => [])\n if (!names.length) return []\n const removed: string[] = []\n const now = Date.now()\n await Promise.all(names.map(async (name) => {\n const full = join(dir, name)\n try {\n const info = await stat(full)\n if (info.isDirectory()) {\n if (name === 'workspace') await sweepWorkspaceTier(full, removed, now)\n else if (name === 'user') await sweepDirFiles(full, removed, now, false)\n else {\n await rm(full, { recursive: true, force: true })\n removed.push(name)\n }\n } else {\n await rm(full, { force: true })\n removed.push(name) // 根级残留(迁移前扁平格式/未知文件)\n }\n } catch (error) { /* stat 失败忽略 */ }\n }))\n await sweepByTotalCap(dir, removed, cap)\n return removed\n}\n// --endregion\n","/**\n * dsh-vscode-mode host — 兼容层:与其他插件 / DSH 版本的统一探测、适配、护栏与自诊断。\n * 职责:身份常量(包名 / MCP 条目前缀 / 路由前缀)、外部插件探测、路由冲突与重复装配检测、\n * 兼容性报告构建(RPC edrv.compat 与启动日志共用)。\n * 注意:与 mcp.ts 存在模块环(compat 提供身份常量、mcp 提供 entriesOf),\n * 双方仅在函数体内交叉使用导出,模块求值期无依赖,ESM 安全。\n * 作者 ddj 2026-08-24\n */\nimport { readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { entriesOf } from './mcp.js'\nimport { loadSettingsDeps, settingsInstallNote, settingsInstallStrategy } from './fileOpenSettings.js'\nimport { readDevForm } from './devForm.js'\nimport { compareDshVersions, detectDshVersion, familyLabel, parseDshVersion } from './dshVersion.js'\nimport type { CompatAdapter, CompatReport } from './shared/compat.js'\nimport type { Ctx } from './store.js'\nimport { ROUTE_PREFIX } from './paths.js'\n\nexport { ROUTE_PREFIX }\n\nexport const PLUGIN_NAME = 'dsh-vscode-mode'\nexport const MCP_PACKAGE = '@deepseek-ai/dsh-mcp-client'\n/** 项目级 MCP 的 loader entry id 固定前缀(区分 profile 全局 MCP;loader id 不能用 ':',故用 '.')。 */\nexport const PROJECT_ENTRY_PREFIX = 'vsm-mcp.'\n/** 旧版项目 MCP 条目前缀(升级残留识别,不显示为全局 MCP)。 */\nexport const LEGACY_PROJECT_PREFIX = 'vsm-mcp:'\n\n/** 判断新旧格式项目 MCP 条目 id(旧残留不被视为全局 MCP)。 */\nexport function isProjectEntryId(id: string): boolean {\n return id.startsWith(PROJECT_ENTRY_PREFIX) || id.startsWith(LEGACY_PROJECT_PREFIX)\n}\n\n/** 从项目条目 id 解析 workspace hash(新旧格式通用)。 */\nexport function entryHash(id: string): string | undefined {\n if (id.startsWith(PROJECT_ENTRY_PREFIX)) return id.slice(PROJECT_ENTRY_PREFIX.length).split('.')[0]\n if (id.startsWith(LEGACY_PROJECT_PREFIX)) return id.slice(LEGACY_PROJECT_PREFIX.length).split(':')[0]\n return undefined\n}\n\n/** 读取随包 package.json 版本号(缺失/解析失败降级为空串)。 */\nexport function pluginVersionOf(): string {\n try {\n const file = join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json')\n const pkg = JSON.parse(readFileSync(file, 'utf8')) as { version?: unknown }\n return typeof pkg.version === 'string' ? pkg.version : ''\n } catch {\n return ''\n }\n}\n\n/** 探测外部插件/服务适配状态(depsAvailable 由调用方注入,便于测试)。 */\nexport function detectExternal(ctx: Ctx, depsAvailable: boolean): CompatAdapter[] {\n const mcpCount = entriesOf(ctx).length\n const settings = ctx.get('settings') as { describe?: unknown; update?: unknown } | undefined\n const hasSettings = Boolean(settings?.describe || settings?.update)\n const sub = ctx.get('subprocess') as { spawn?: unknown } | undefined\n return [\n { name: MCP_PACKAGE, active: mcpCount > 0, note: mcpCount > 0 ? mcpCount + ' 个 MCP 服务条目' : '未检测到 MCP 条目(MCP 管理页显示为空)' },\n { name: '设置持久化(@deepseek-ai/dsh-settings)', active: depsAvailable, note: depsAvailable ? '设置 section 已安装' : '未安装:fileOpenTool 持久化降级为配置值' },\n { name: 'settings 服务', active: hasSettings, note: hasSettings ? '可读写设置' : '不可用(设置读写走配置回退)' },\n { name: '文件浏览器打开(subprocess 服务)', active: typeof sub?.spawn === 'function', note: typeof sub?.spawn === 'function' ? '可定位/打开 OS 文件浏览器' : '不可用(右键「在文件浏览器中打开」将提示失败)' },\n ]\n}\n\n/** 本插件已注册的路由(kind → path 集合),冲突检测时排除自身,避免自误报。 */\nconst ownRoutes = { exact: new Set<string>(), prefixes: new Set<string>() }\n\n/** 清空本插件路由记录(registerRoutes 装配开始时调用,热重载不残留)。 */\nexport function resetOwnRoutes(): void {\n ownRoutes.exact.clear()\n ownRoutes.prefixes.clear()\n}\n\n/** 记录本插件路由(routes.ts 注册成功时调用)。 */\nexport function noteOwnRoute(kind: 'exact' | 'prefix', path: string): void {\n const table = kind === 'exact' ? ownRoutes.exact : ownRoutes.prefixes\n table.add(path)\n}\n\n/** 检测路由前缀占用与重叠(排除本插件自有路由;内部表不可读视为无冲突)。 */\nexport function routeConflict(web: unknown, prefix: string): string | null {\n try {\n const w = web as { exact?: Map<unknown, unknown>; prefixes?: Map<unknown, unknown> } | undefined\n const exact = w?.exact\n const prefixes = w?.prefixes\n if (exact instanceof Map) {\n for (const path of exact.keys()) {\n const other = String(path)\n if (other.startsWith(prefix + '/') && !ownRoutes.exact.has(other)) {\n return '精确路由 ' + other + ' 与 ' + prefix + ' 前缀重叠(可能来自热重载残留或其他插件)'\n }\n }\n }\n if (prefixes instanceof Map) {\n for (const path of prefixes.keys()) {\n const other = String(path)\n if (other !== prefix && (other.startsWith(prefix + '/') || prefix.startsWith(other + '/')) && !ownRoutes.prefixes.has(other)) {\n return '路由前缀 ' + prefix + ' 与 ' + other + ' 重叠'\n }\n }\n }\n } catch {\n /* 内部表不可读时放弃检查 */\n }\n return null\n}\n\n/** 检测本插件是否被重复装配(bundle 层 + 用户层重复 insert 的自诊断)。 */\nexport function duplicateEntries(ctx: Ctx): string[] {\n const loader = ctx.get('loader') as { entries?: () => Iterable<{ id?: unknown; options?: { name?: unknown } }> } | undefined\n if (!loader || typeof loader.entries !== 'function') return []\n const own = [...loader.entries()].filter((entry) => String(entry.options?.name ?? entry.id ?? '') === PLUGIN_NAME)\n if (own.length > 1) {\n return ['检测到 ' + own.length + ' 个 ' + PLUGIN_NAME + ' loader 条目(重复装配)。请删除 profile 用户层 cordis.patch.yml 的重复 insert(或运行 dev_fix_patch 清理)']\n }\n return []\n}\n\n/** 护栏适配状态:路由前缀唯一性 + 插件装配唯一性。 */\nexport function detectGuards(ctx: Ctx): CompatAdapter[] {\n const web = ctx.get('webServer')\n const conflict = web ? routeConflict(web, ROUTE_PREFIX) : null\n const duplicates = duplicateEntries(ctx)\n return [\n { name: '路由前缀 ' + ROUTE_PREFIX, active: !conflict, note: conflict ?? '无冲突' },\n { name: '插件装配唯一性', active: duplicates.length === 0, note: duplicates[0] ?? '唯一装配' },\n ]\n}\n\n/** 已实测覆盖的最高 DSH 版本(适配矩阵上界,超过则提示,见 buildReport)。 */\nconst TESTED_DSH_MAX = '0.1.3-alpha.2'\n\n/** 版本适配机制状态行:DSH 版本探测 + 设置 section 安装策略。 */\nexport function versionAdapters(dshVersion: string): CompatAdapter[] {\n const adapters: CompatAdapter[] = []\n const parsed = parseDshVersion(dshVersion)\n if (dshVersion === '') {\n adapters.push({ name: 'DSH 版本', active: false, note: '未探测到版本号(能力探测模式运行)' })\n } else if (!parsed) {\n adapters.push({ name: 'DSH 版本', active: false, note: '无法解析版本号 ' + dshVersion + '(能力探测模式运行)' })\n } else {\n adapters.push({ name: 'DSH 版本', active: true, note: dshVersion + ' · ' + familyLabel(dshVersion) })\n }\n const strategy = settingsInstallStrategy()\n adapters.push({\n name: '设置 section 安装(版本适配)',\n active: strategy === 'legacy' || strategy === 'service',\n note: settingsInstallNote(),\n })\n return adapters\n}\n\n/**\n * 构建完整兼容性报告(RPC 与启动日志共用)。\n * @author ddj 2026年08月24号 / 2026年09月02号\n * @param ctx DSH host 上下文\n * @param options 测试注入:depsAvailable 跳过动态导入、version 固定插件版本、dshVersion 固定 DSH 版本\n * @returns 兼容性报告\n */\nexport async function buildReport(\n ctx: Ctx,\n options?: { depsAvailable?: boolean; version?: string; dshVersion?: string },\n): Promise<CompatReport> {\n const deps = options?.depsAvailable ?? (await loadSettingsDeps()) !== null\n const dshVersion = options?.dshVersion ?? detectDshVersion()\n const external = detectExternal(ctx, deps)\n const guards = detectGuards(ctx)\n const adapters = versionAdapters(dshVersion)\n const warnings: string[] = []\n if (!deps) warnings.push('未安装 @deepseek-ai/dsh-settings:文件打开工具设置持久化不可用(降级为配置值)')\n const strategy = settingsInstallStrategy()\n if (strategy === 'none') warnings.push('设置 section 安装不可用:' + settingsInstallNote())\n const parsed = parseDshVersion(dshVersion)\n const testedMax = parseDshVersion(TESTED_DSH_MAX)\n if (parsed && testedMax && compareDshVersions(parsed, testedMax) > 0) {\n warnings.push('DSH ' + dshVersion + ' 高于已实测版本(' + TESTED_DSH_MAX + '):设置 API 按能力探测运行,异常时请回报适配矩阵')\n }\n for (const guard of guards) {\n if (!guard.active && guard.note) warnings.push(guard.note)\n }\n return {\n pluginVersion: options?.version ?? pluginVersionOf(),\n external,\n guards,\n adapters,\n warnings,\n devForm: readDevForm(),\n dshVersion,\n }\n}\n","/**\n * dsh-vscode-mode host — webServer 路由注册(/edrv/rpc、/edrv/assets/*、/edrv/vendor/*)。\n * 迁移自原 src/index.ts 的路由部分,路径/行为一字不改。\n * 作者 ddj 2026-08-20\n */\nimport { readFile, stat } from 'node:fs/promises'\nimport { extname, join, normalize, resolve, sep } from 'node:path'\nimport { ROUTE_PREFIX, noteOwnRoute, resetOwnRoutes, routeConflict } from './compat.js'\nimport { RPC_PATH } from './shared/rpc.js'\nimport type { RpcMethod, RpcRequestMap } from './shared/rpc.js'\nimport type { Ctx } from './store.js'\nimport { VENDOR_PREFIX, imageDirOf, vendorDirOf } from './paths.js'\n\nconst IMG_ROUTES = [\n { url: '/edrv/assets/compare-idle.png', file: 'compare_idle.png' },\n { url: '/edrv/assets/compare-select.png', file: 'compare_select.png' },\n]\n\n/** Monaco AMD 构建静态资源(随包发布,离线可用;前缀路由 /edrv/vendor/*)。 */\nconst VENDOR_MIME: Record<string, string> = {\n '.js': 'text/javascript; charset=utf-8',\n '.mjs': 'text/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json',\n '.map': 'application/json',\n '.ts': 'text/plain; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.html': 'text/html; charset=utf-8',\n '.md': 'text/markdown',\n '.bcmap': 'application/octet-stream',\n '.pfb': 'application/octet-stream',\n}\n\n/** 图标目录(paths.ts 统一解析:config.imageDir 覆盖优先,否则插件包 assets/)。 */\nconst imgDirOf = (config: unknown): string => imageDirOf(config, import.meta.url)\n\n/** Monaco AMD 静态目录(随包发布,paths.ts 统一解析)。 */\nconst vendorDir = vendorDirOf(import.meta.url)\n\n/**\n * 注册全部 webServer 路由(带兼容护栏:前缀冲突预警 + 注册失败降级跳过)。\n * @author ddj 2026年08月20号\n * @param ctx DSH 上下文\n * @param config 插件配置(可选 imageDir 等)\n * @param handleRpc RPC 分发入口(method,args → RpcResult)\n * @param onWarning 兼容性警告收集(可选)\n */\nexport function registerRoutes(\n ctx: Ctx,\n config: unknown,\n handleRpc: <M extends RpcMethod>(method: M, args: RpcRequestMap[M]) => Promise<unknown>,\n onWarning?: (warning: string) => void,\n): void {\n const imgDir = imgDirOf(config)\n const web = ctx.get('webServer')\n if (!web) return\n\n resetOwnRoutes()\n const conflict = routeConflict(web, ROUTE_PREFIX)\n if (conflict) onWarning?.('兼容性:' + conflict)\n\n /** 护栏注册:重复路由抛错时降级为警告并跳过,不让单条路由拖垮装配。 */\n const guarded = (route: { kind: 'exact' | 'prefix'; path: string; handler?: unknown }, label: string): (() => void) | undefined => {\n try {\n const dispose = web.register(route)\n noteOwnRoute(route.kind, route.path)\n return dispose\n } catch (error) {\n onWarning?.('兼容性:' + label + ' 注册失败(' + String(error) + ')')\n return undefined\n }\n }\n\n ctx.effect(() => guarded({\n kind: 'exact',\n path: RPC_PATH,\n handler: async (req: unknown, res: { statusCode?: number; setHeader: (k: string, v: string) => void; end: (b?: string) => void }) => {\n try {\n const chunks: Uint8Array[] = []\n for await (const chunk of req as AsyncIterable<Uint8Array>) chunks.push(chunk)\n let input: { method?: string; args?: unknown } = {}\n try {\n input = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}')\n } catch (error) {\n input = {}\n }\n const method = (typeof input.method === 'string' ? input.method : '') as RpcMethod\n const result = await handleRpc(method, (input.args ?? {}) as never)\n res.statusCode = 200\n res.setHeader('content-type', 'application/json')\n res.end(JSON.stringify(result))\n } catch (error) {\n res.statusCode = 500\n res.end(JSON.stringify({ ok: false, error: String(error) }))\n }\n },\n }, '/edrv/rpc 精确路由'), 'edrv: routes')\n\n for (const r of IMG_ROUTES) {\n ctx.effect(() => guarded({\n kind: 'exact',\n path: r.url,\n handler: async (req: unknown, res: { statusCode?: number; setHeader: (k: string, v: string) => void; end: (b?: string | Uint8Array) => void }) => {\n try {\n const body = await readFile(imgDir + '/' + r.file)\n res.statusCode = 200\n res.setHeader('content-type', 'image/png')\n res.setHeader('cache-control', 'no-cache')\n res.end(body)\n } catch (error) {\n res.statusCode = 404\n res.end()\n }\n },\n }, '静态资源 ' + r.file), 'edrv: routes')\n }\n\n // Monaco Editor AMD 构建:/edrv/vendor/* → assets/vendor/*(路径穿越防护 + 按扩展名 MIME)\n // ETag 协商缓存:弱 etag(mtime+size),配合 max-age 让浏览器 304 复用,插件升级内容变化自动失效。\n ctx.effect(() => guarded({\n kind: 'prefix',\n path: VENDOR_PREFIX,\n handler: async (req: { method?: string; url?: string; headers?: Record<string, string | string[] | undefined> }, res: { statusCode?: number; setHeader: (k: string, v: string) => void; end: (b?: string | Uint8Array) => void }) => {\n try {\n if (req.method !== 'GET' && req.method !== 'HEAD') {\n res.statusCode = 405\n res.end()\n return\n }\n const pathname = new URL(req.url ?? '/', 'http://x').pathname\n const rel = decodeURIComponent(pathname.slice(VENDOR_PREFIX.length)).replace(/^\\/+/, '')\n if (!rel) { res.statusCode = 404; res.end(); return }\n const target = resolve(normalize(join(vendorDir, rel)))\n if (target !== vendorDir && !target.startsWith(vendorDir + sep)) {\n res.statusCode = 403\n res.end()\n return\n }\n const info = await stat(target).catch(() => null)\n if (!info || !info.isFile()) { res.statusCode = 404; res.end(); return }\n const etag = 'W/\"' + info.mtimeMs.toString(16) + '-' + info.size.toString(16) + '\"'\n const reqEtag = (() => {\n const raw = req.headers?.['if-none-match']\n if (Array.isArray(raw)) return raw[0]\n return raw\n })()\n if (reqEtag === etag) {\n res.statusCode = 304\n res.setHeader('etag', etag)\n res.end()\n return\n }\n const body = await readFile(target)\n res.statusCode = 200\n res.setHeader('content-type', VENDOR_MIME[extname(target)] ?? 'application/octet-stream')\n res.setHeader('cache-control', 'public, max-age=3600')\n res.setHeader('etag', etag)\n res.end(body)\n } catch (error) {\n res.statusCode = 404\n res.end()\n }\n },\n }, '/edrv/vendor 前缀路由'), 'edrv: routes')\n}\n","/**\n * dsh-vscode-mode shared diff primitives — 快照指纹、hunk 规范化与安全定位。\n * 不依赖 Node/React,host 与 browser 共用,避免各层用不同 indexOf 语义。\n * 作者 ddj 2026-08-24\n */\nimport type { Hunk, RecordBase } from './types.js'\n\n/** 文件读取状态,区分真实空文件与无法读取/过大的文件。 */\nexport type ReadState =\n | { kind: 'content'; content: string }\n | { kind: 'missing' }\n | { kind: 'unavailable' }\n\n/** 文本中的一个半开区间 [start,end)。 */\nexport interface TextRange {\n start: number\n end: number\n}\n\n/** 一条 hunk 在当前内容中的定位结果。 */\nexport interface HunkLocation extends TextRange {\n idx: number\n hunk: Hunk\n matched: boolean\n}\n\n/** 统一取对应 hunk;callHunk 只用于旧记录缺失 hunks 时兼容。 */\nexport function preciseHunk(record: Pick<RecordBase, 'hunks' | 'callHunk'>, idx: number): Hunk | null {\n return hunkOf(record, idx)\n}\n\n/** 轻量、确定性的字符串指纹;不引入 Node crypto。 */\nexport function fingerprint(text: string | null | undefined): string | null {\n if (typeof text !== 'string') return null\n let hash = 2166136261\n for (let i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i)\n hash = Math.imul(hash, 16777619)\n }\n return 'fnv1a:' + (hash >>> 0).toString(16) + ':' + text.length\n}\n\n/** 取记录第 idx 个有效 hunk;只有记录缺 hunk 时才回退 callHunk。 */\nexport function hunkOf(record: Pick<RecordBase, 'hunks' | 'callHunk'>, idx: number): Hunk | null {\n const hunk = Array.isArray(record.hunks) ? record.hunks[idx] : undefined\n if (hunk && typeof hunk.newText === 'string') return hunk\n if (idx === 0 && record.callHunk && typeof record.callHunk.newText === 'string') return record.callHunk\n return null\n}\n\n/** hunk 是否表示没有实际内容变化。 */\nexport function isNoopHunk(hunk: Hunk | null | undefined): boolean {\n return !!hunk && hunk.oldText !== null && hunk.oldText === hunk.newText\n}\n\n/**\n * 差异比较口径归一化:剥离 UTF-8 BOM、统一 CRLF 为 LF。\n * 背景:外部工具(pwsh/编辑器)可能改变 BOM/行尾,导致 after 指纹与 hunk\n * 定位在内容语义未变的情况下误报 conflict,把待确认修改从 UI 排除。\n * @author ddj 2026年09月09号\n */\nexport function normalizeForCompare(text: string): string {\n return text.replace(/^\\uFEFF/, '').replace(/\\r\\n/g, '\\n')\n}\n\n/** 归一化一个 hunk 的两侧文本(与 normalizeForCompare 同口径)。 */\nexport function normalizeHunk(hunk: Hunk): Hunk {\n return {\n oldText: hunk.oldText === null ? null : normalizeForCompare(hunk.oldText),\n newText: normalizeForCompare(hunk.newText),\n }\n}\n\n/** splitLines 的空文本语义:真实空文件没有一行变更内容。 */\nexport function splitLines(text: string): string[] {\n return text.length ? text.split('\\n') : []\n}\n\n/** 为执行后 hunk 写入快照坐标;空 newText 通过 before/after 公共边界定位删除点。 */\nexport function annotateHunk(hunk: Hunk, before: string | null, after: string | null): Hunk {\n return annotateHunks([hunk], before, after)[0]\n}\n\n/** 按文件顺序为多 hunk 写入不重复的 after 坐标。 */\nexport function annotateHunks(hunks: Hunk[], before: string | null, after: string | null): Hunk[] {\n if (typeof after !== 'string') return hunks\n let cursor = 0\n return hunks.map((hunk) => {\n if (hunk.newText.length > 0) {\n const start = after.indexOf(hunk.newText, cursor)\n if (start >= 0) {\n cursor = start + hunk.newText.length\n return { ...hunk, afterStart: start, afterEnd: cursor }\n }\n return hunk\n }\n if (hunks.length !== 1 || typeof before !== 'string' || before === after || hunk.oldText === null) return hunk\n const prefix = commonPrefix(before, after)\n const suffix = commonSuffix(before, after, prefix)\n const removedStart = prefix\n const removedEnd = Math.max(removedStart, before.length - suffix)\n return { ...hunk, afterStart: removedStart, afterEnd: removedStart, beforeStart: removedStart, beforeEnd: removedEnd }\n })\n}\n\n/** 计算两个文本的最长公共前缀长度。 */\nfunction commonPrefix(left: string, right: string): number {\n const limit = Math.min(left.length, right.length)\n let i = 0\n while (i < limit && left.charCodeAt(i) === right.charCodeAt(i)) i++\n return i\n}\n\n/** 计算不与 prefix 重叠的最长公共后缀长度。 */\nfunction commonSuffix(left: string, right: string, prefix: number): number {\n const limit = Math.min(left.length, right.length) - prefix\n let i = 0\n while (i < limit && left.charCodeAt(left.length - 1 - i) === right.charCodeAt(right.length - 1 - i)) i++\n return i\n}\n\n/** 计算 index 前的 0 基行数。 */\nexport function lineBefore(text: string, index: number): number {\n let n = 0\n const end = Math.max(0, Math.min(index, text.length))\n for (let i = 0; i < end; i++) if (text.charCodeAt(i) === 10) n++\n return n\n}\n\n/** 找出文本的全部非重叠出现位置。 */\nfunction allMatches(content: string, needle: string): TextRange[] {\n if (!needle.length) return []\n const out: TextRange[] = []\n let from = 0\n while (from <= content.length - needle.length) {\n const at = content.indexOf(needle, from)\n if (at < 0) break\n out.push({ start: at, end: at + needle.length })\n from = at + Math.max(1, needle.length)\n }\n return out\n}\n\n/**\n * 从 after 快照定位所有 hunk,按 hunk 顺序优先选未占用且靠近前一块的候选。\n * 若 hunk 带 afterStart/afterEnd,则优先验证快照坐标,避免重复文本错配。\n * @author ddj 2026年08月24号\n * @param content 当前文件内容\n * @param hunks 待定位 hunk\n * @returns 每个 hunk 一个结果,matched=false 表示冲突/stale\n */\nexport function locateHunks(content: string, hunks: Hunk[]): HunkLocation[] {\n const locations: HunkLocation[] = []\n let cursor = 0\n const occupied: TextRange[] = []\n for (let idx = 0; idx < hunks.length; idx++) {\n const hunk = hunks[idx]\n const newText = hunk.newText\n const snapshot = Number.isInteger(hunk.afterStart) && Number.isInteger(hunk.afterEnd)\n ? { start: hunk.afterStart as number, end: hunk.afterEnd as number }\n : null\n const snapshotMatches = snapshot && snapshot.start >= 0 && snapshot.end >= snapshot.start\n && (newText.length === 0 || content.slice(snapshot.start, snapshot.end) === newText)\n ? snapshot\n : null\n const candidates = snapshotMatches ? [snapshotMatches] : allMatches(content, newText)\n const candidate = candidates.find((range) => range.start >= cursor && !occupied.some((used) => overlaps(range, used)))\n ?? candidates.find((range) => !occupied.some((used) => overlaps(range, used)))\n if (candidate) {\n locations.push({ idx, hunk, ...candidate, matched: true })\n occupied.push(candidate)\n cursor = Math.max(cursor, candidate.end)\n continue\n }\n if (newText.length === 0 && hunk.afterStart === undefined && hunk.afterEnd === undefined && content.length === 0) {\n const point = { start: 0, end: 0 }\n locations.push({ idx, hunk, ...point, matched: true })\n continue\n }\n if (newText.length === 0 && hunk.afterStart !== undefined && hunk.afterEnd !== undefined\n && hunk.afterStart === hunk.afterEnd && hunk.afterStart >= 0 && hunk.afterStart <= content.length) {\n const point = { start: hunk.afterStart, end: hunk.afterEnd }\n if (!occupied.some((used) => overlaps(point, used))) {\n locations.push({ idx, hunk, ...point, matched: true })\n occupied.push(point)\n cursor = Math.max(cursor, point.end)\n continue\n }\n }\n locations.push({ idx, hunk, start: -1, end: -1, matched: false })\n }\n return locations\n}\n\n/** 判断两个半开区间是否重叠。零长度区间只与同一位置的零长度区间重叠。 */\nfunction overlaps(left: TextRange, right: TextRange): boolean {\n if (left.start === left.end || right.start === right.end) return left.start === right.start && left.end === right.end\n return left.start < right.end && right.start < left.end\n}\n\n/** 在可定位区间上执行一次 hunk 反向替换。 */\nexport function replaceRange(content: string, location: HunkLocation, reverse = false): string | null {\n if (!location.matched || location.start < 0) return null\n const replacement = reverse ? (location.hunk.oldText ?? '') : location.hunk.newText\n return content.slice(0, location.start) + replacement + content.slice(location.end)\n}\n\n/** 按当前内容中出现的位置从后向前应用 hunk,避免前块长度变化影响后块。 */\nexport function applyLocations(content: string, locations: HunkLocation[], reverse = false): { content: string; stale: number[] } {\n const stale = locations.filter((location) => !location.matched).map((location) => location.idx)\n let out = content\n const matched = locations.filter((location) => location.matched).sort((a, b) => b.start - a.start)\n for (const location of matched) {\n const next = replaceRange(out, location, reverse)\n if (next === null) stale.push(location.idx)\n else out = next\n }\n return { content: out, stale: stale.sort((a, b) => a - b) }\n}\n","/**\n * dsh-vscode-mode host — 纯域逻辑(无 ctx/fs/IO 依赖,可直接单测)。\n * 迁移自原 src/index.ts 的纯函数部分,语义一字不改。\n * 作者 ddj 2026-08-20\n */\nimport type { Decision, DiffRecord, Hunk, RecordSummary } from './shared/types.js'\nimport { applyLocations, fingerprint, isNoopHunk, locateHunks, preciseHunk } from './shared/diff.js'\n\n/** 工作区记录桶上限(超过后按 at 最旧剔除)。 */\nexport const MAX_RECORDS = 200\n\n/**\n * 归一化一条持久化记录(容忍旧版/损坏字段)。\n * @author ddj 2026年08月20号\n * @param raw 反序列化的原始记录\n * @returns 合法记录或 null\n */\nexport function normalizeRecord(raw: unknown): DiffRecord | null {\n if (!raw || typeof raw !== 'object') return null\n const r = raw as Record<string, unknown>\n if (typeof r.callId !== 'string' || typeof r.path !== 'string') return null\n const hunks: Hunk[] = Array.isArray(r.hunks)\n ? (r.hunks as unknown[]).filter((h) => h && typeof (h as { newText?: unknown }).newText === 'string').map((h) => {\n const item = h as Record<string, unknown>\n return {\n oldText: typeof item.oldText === 'string' ? item.oldText : null,\n newText: item.newText as string,\n ...(Number.isInteger(item.afterStart) ? { afterStart: item.afterStart as number } : {}),\n ...(Number.isInteger(item.afterEnd) ? { afterEnd: item.afterEnd as number } : {}),\n ...(Number.isInteger(item.beforeStart) ? { beforeStart: item.beforeStart as number } : {}),\n ...(Number.isInteger(item.beforeEnd) ? { beforeEnd: item.beforeEnd as number } : {}),\n }\n })\n : []\n const toolName: DiffRecord['toolName'] = r.toolName === 'write' ? 'write' : 'edit'\n const rawDecisions = r.decisions && typeof r.decisions === 'object' ? r.decisions as Record<string, unknown> : {}\n const call = rawDecisions.call === 'accepted' || rawDecisions.call === 'rejected' ? rawDecisions.call : 'pending'\n const rawPerHunk = Array.isArray(rawDecisions.perHunk) ? rawDecisions.perHunk : []\n const perHunk = hunks.map((_, i) => {\n const value = rawPerHunk[i]\n if (value === 'accepted' || value === 'rejected') return value\n return call === 'accepted' || call === 'rejected' ? call : 'pending'\n })\n const before = typeof r.before === 'string' ? r.before : null\n const hasAfter = Object.prototype.hasOwnProperty.call(r, 'after')\n const after = typeof r.after === 'string' ? r.after : null\n return {\n callId: r.callId,\n toolName,\n path: r.path,\n before,\n after,\n baseFingerprint: typeof r.baseFingerprint === 'string' ? r.baseFingerprint : fingerprint(before),\n afterFingerprint: typeof r.afterFingerprint === 'string' ? r.afterFingerprint : fingerprint(after),\n legacy: !hasAfter,\n conflict: r.conflict === true,\n create: r.create === true,\n callHunk: r.callHunk && typeof (r.callHunk as { oldText?: unknown }).oldText === 'string' && typeof (r.callHunk as { newText?: unknown }).newText === 'string'\n ? { oldText: (r.callHunk as { oldText: string }).oldText, newText: (r.callHunk as { newText: string }).newText }\n : null,\n hunks,\n decisions: { call: call as Decision, perHunk },\n note: typeof r.note === 'string' ? r.note : null,\n superseded: r.superseded === true,\n archived: r.archived === true,\n batch: Number.isInteger(r.batch) ? (r.batch as number) : 0,\n at: typeof r.at === 'string' ? r.at : new Date().toISOString(),\n }\n}\n\n/**\n * 写决策到记录(scope=call 整体 / hunk 单个块)。\n * @author ddj 2026年08月20号\n * @param record 记录\n * @param scope 作用域\n * @param idx hunk 下标(仅 scope=hunk 时生效)\n * @param value 决策值\n * @returns 更新后的记录(原对象就地修改)\n */\nexport function markDecision(record: DiffRecord, scope: string, idx: number | undefined, value: Decision): DiffRecord {\n const dec = record.decisions\n if (scope === 'hunk' && Array.isArray(dec.perHunk) && Number.isInteger(idx)) {\n const i = idx as number\n if (i >= 0 && i < dec.perHunk.length) dec.perHunk[i] = value\n } else {\n dec.call = value\n if (Array.isArray(dec.perHunk)) dec.perHunk = dec.perHunk.map(() => value)\n }\n record.at = new Date().toISOString()\n return record\n}\n\n/** 记录是否已无任何待决策差异(superseded 或全部已决策)。 */\nexport function recordResolved(record: DiffRecord): boolean {\n if (record.superseded === true) return true\n const hunks = Array.isArray(record.hunks) ? record.hunks : []\n const perHunk = Array.isArray(record.decisions.perHunk) ? record.decisions.perHunk : []\n const count = Math.max(hunks.length, perHunk.length)\n if (!count) return record.decisions.call === 'accepted' || record.decisions.call === 'rejected'\n for (let idx = 0; idx < count; idx++) {\n const precise = preciseHunk(record, idx)\n const value = perHunk[idx] ?? record.decisions.call\n if (isNoopHunk(precise) && value === 'pending') return false\n if (value !== 'accepted' && value !== 'rejected') return false\n }\n return true\n}\n\n/**\n * 记录决策摘要(采纳/拒绝/待处理计数,superseded 标记)。\n * @author ddj 2026年08月20号\n * @param record 记录\n * @returns 摘要\n */\nexport function recSummary(record: DiffRecord): RecordSummary {\n const hunks = Array.isArray(record.hunks) ? record.hunks : []\n const perHunk = Array.isArray(record.decisions.perHunk) ? record.decisions.perHunk : []\n const n = Math.max(1, hunks.length, perHunk.length)\n let accepted = 0\n let rejected = 0\n let pending = 0\n for (let i = 0; i < n; i++) {\n const hunk = preciseHunk(record, i)\n const value = perHunk[i] ?? record.decisions.call\n if (i < hunks.length && isNoopHunk(hunk) && value === 'pending') continue\n if (value === 'accepted') accepted++\n else if (value === 'rejected') rejected++\n else pending++\n }\n return { accepted, rejected, pending, superseded: record.superseded === true }\n}\n\n/**\n * 重建\"本批次修改前\"内容:把仍待处理(pending)的差异块按 新→旧 顺序从当前内容反解\n * (newText → oldText)。已采纳/已拒绝的块跳过。反解失败的块标记为 stale。\n * @author ddj 2026年08月20号\n * @param records 该文件的活动记录\n * @param content 当前磁盘内容\n * @returns 重建内容与 stale 定位\n */\nexport function reconstructOriginal(records: DiffRecord[], content: string): { content: string; stale: Array<{ callId: string; idx: number }> } {\n const pending: Array<{ rec: DiffRecord; idx: number; hunk: Hunk }> = []\n for (const rec of records) {\n for (let i = 0; i < rec.hunks.length; i++) {\n const st = rec.decisions.perHunk[i] ?? rec.decisions.call\n const hunk = preciseHunk(rec, i)\n if (st === 'pending' && hunk && !isNoopHunk(hunk)) pending.push({ rec, idx: i, hunk })\n }\n }\n pending.sort((a, b) => (a.rec.at < b.rec.at ? 1 : a.rec.at > b.rec.at ? -1 : 0))\n const locations = locateHunks(content, pending.map((item) => item.hunk))\n const rebuilt = applyLocations(content, locations, true)\n return {\n content: rebuilt.content,\n stale: rebuilt.stale.map((idx) => ({ callId: pending[idx].rec.callId, idx: pending[idx].idx })),\n }\n}\n\n/** 文件当前最大批次号(无记录为 0)。 */\nexport function fileMaxBatch(records: Map<string, DiffRecord>, path: string): number {\n let m = 0\n for (const r of records.values()) {\n if (r.path === path && Number.isInteger(r.batch) && r.batch > m) m = r.batch\n }\n return m\n}\n\n/** 记录桶裁剪:超出 MAX_RECORDS 时剔除最旧的。 */\nexport function prune(map: Map<string, DiffRecord>, max = MAX_RECORDS): void {\n if (map.size <= max) return\n const sorted = [...map.values()].sort((a, b) => (a.at < b.at ? -1 : 1))\n for (let i = 0; i < sorted.length - max; i++) map.delete(sorted[i].callId)\n}\n\n/** 按批次分组记录。 */\nexport function groupByBatch(recs: DiffRecord[]): Map<number | null, DiffRecord[]> {\n const map = new Map<number | null, DiffRecord[]>()\n for (const r of recs) {\n const k = Number.isInteger(r.batch) ? r.batch : null\n if (!map.has(k)) map.set(k, [])\n map.get(k)!.push(r)\n }\n return map\n}\n\n/**\n * 归档条目构造(一条批次一条)。\n * @author ddj 2026年08月20号\n * @param recs 同批次记录(非空)\n * @param cwd 工作区\n * @param reason 归档原因\n */\nexport function archiveEntryFor(recs: DiffRecord[], cwd: string, reason: string): {\n at: string\n cwd: string\n path: string\n batch: number | null\n reason: string\n records: Array<Record<string, unknown>>\n} {\n const first = recs[0]\n return {\n at: new Date().toISOString(),\n cwd,\n path: first.path,\n batch: Number.isInteger(first.batch) ? first.batch : null,\n reason,\n records: recs.map((r) => ({\n callId: r.callId,\n toolName: r.toolName,\n path: r.path,\n create: r.create === true,\n callHunk: r.callHunk,\n hunks: r.hunks,\n decisions: r.decisions,\n note: r.note ?? null,\n before: typeof r.before === 'string' ? r.before : null,\n after: typeof r.after === 'string' ? r.after : null,\n baseFingerprint: r.baseFingerprint ?? null,\n afterFingerprint: r.afterFingerprint ?? null,\n conflict: r.conflict === true,\n legacy: r.legacy === true,\n superseded: r.superseded === true,\n batch: Number.isInteger(r.batch) ? r.batch : null,\n at: r.at,\n summary: recSummary(r),\n })),\n }\n}\n","/**\n * dsh-vscode-mode host — 存储层(sidecar 读写合并 + 归档持久化 + stale 检测)。\n * 迁移自原 src/index.ts 的 fs/ctx IO 部分,语义一字不改。\n * 作者 ddj 2026-08-20\n */\nimport type { ArchiveBatch, ArchiveData, DiffRecord, SidecarData } from './shared/types.js'\nimport type { ReadState } from './shared/diff.js'\nimport { fingerprint, isNoopHunk, locateHunks, normalizeForCompare, normalizeHunk, preciseHunk } from './shared/diff.js'\nimport { archiveEntryFor, groupByBatch, normalizeRecord } from './model.js'\nimport { SIDECAR, SIDECAR_ARCHIVE } from './paths.js'\nimport { log } from './log.js'\n\nexport { SIDECAR, SIDECAR_ARCHIVE }\nexport const READ_CAP = 8 * 1024 * 1024\n/** 二进制预览/写回上限(PDF 等整文件 base64 传输;文本侧仍用 READ_CAP)。 */\nexport const BINARY_READ_CAP = 32 * 1024 * 1024\n\n/** DSH 上下文与会话类型较宽松:本地无 dsh 类型声明,显式 any + 文档约束。 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Ctx = any\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Session = any\n\n/** 会话沙箱策略(policyOf):可能不存在,调用方需容忍 undefined。 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function policyOf(ctx: Ctx, session: Session | undefined): any {\n const svc = ctx.get('sandboxPolicy')\n if (!svc) return undefined\n return session ? svc.resolve({ session }) : svc.resolve()\n}\n\n/** 按会话 cwd 解析目标路径。 */\nexport async function resolveTarget(ctx: Ctx, session: Session | undefined, path: string): Promise<string> {\n const fs = ctx.get('fs')\n const cwd = session?.header?.cwd\n return fs.resolve(path, cwd ? { cwd } : {})\n}\n\n/** 读取工作区主 sidecar 文本(缺失/失败 → null)。 */\nasync function readSidecarText(ctx: Ctx, cwd: string | null): Promise<string | null> {\n const fs = ctx.get('fs')\n if (!fs || !cwd) return null\n try {\n return await fs.readText(await fs.resolve(SIDECAR, { cwd }))\n } catch (error) {\n return null\n }\n}\n\n/**\n * 解析主 sidecar:v2 直接返回;v1 迁移为 v2 结构(按会话 cwd 分桶)。\n * @author ddj 2026年08月20号\n * @param text sidecar 文本\n * @returns v2 数据或 null\n */\nexport function parseSidecar(text: string | null): SidecarData | null {\n if (!text) return null\n try {\n const data = JSON.parse(text)\n if (data && typeof data === 'object' && data.version === 2 && data.workspaces && typeof data.workspaces === 'object') {\n return data as SidecarData\n }\n if (data && data.version === 1 && data.sessions && typeof data.sessions === 'object') {\n const workspaces: SidecarData['workspaces'] = {}\n for (const bucket of Object.values(data.sessions)) {\n const b = bucket as { cwd?: unknown; records?: unknown; at?: unknown }\n if (typeof b.cwd === 'string' && b.records) {\n workspaces[b.cwd] = { at: typeof b.at === 'number' ? b.at : Date.now(), records: b.records as Record<string, DiffRecord> }\n }\n }\n return { version: 2, updatedAt: typeof data.updatedAt === 'string' ? data.updatedAt : new Date().toISOString(), workspaces }\n }\n return null\n } catch (error) {\n return null\n }\n}\n\n/** 加载某工作区的记录桶(内存 Map;缺失 → 空)。 */\nexport async function loadBucket(ctx: Ctx, cwd: string): Promise<Map<string, DiffRecord>> {\n const text = await readSidecarText(ctx, cwd)\n const data = parseSidecar(text)\n const map = new Map<string, DiffRecord>()\n if (data && data.workspaces[cwd] && typeof data.workspaces[cwd].records === 'object') {\n for (const rec of Object.values(data.workspaces[cwd].records)) {\n const n = normalizeRecord(rec)\n if (n) map.set(n.callId, n)\n }\n }\n return map\n}\n\n/** 保存某工作区的记录桶(写前合并,不覆盖其他工作区)。 */\nexport async function saveBucket(ctx: Ctx, cwd: string, recsMap: Map<string, DiffRecord>, session?: Session): Promise<void> {\n const fs = ctx.get('fs')\n if (!fs || !cwd) return\n try {\n const target = await fs.resolve(SIDECAR, { cwd })\n const existing = parseSidecar(await readSidecarText(ctx, cwd)) ?? { version: 2, updatedAt: '', workspaces: {} } as SidecarData\n existing.workspaces[cwd] = { at: Date.now(), records: Object.fromEntries(recsMap) }\n existing.updatedAt = new Date().toISOString()\n await fs.writeText(target, JSON.stringify(existing), void 0, void 0, policyOf(ctx, session))\n } catch (error) {\n log.error('saveBucket failed: ' + String(error))\n }\n}\n\n/**\n * 读取记录目标文件内容(按 path 缓存一次;缺失/过大/失败 → null/'' 占位)。\n * @author ddj 2026年08月20号\n * @param cache path → 内容(null=缺失/读取失败,''=过大跳过)\n */\nexport async function readForCache(ctx: Ctx, session: Session, cache: Map<string, ReadState>, path: string): Promise<ReadState> {\n const cached = cache.get(path)\n if (cached) return cached\n const fs = ctx.get('fs')\n if (!fs) { const state: ReadState = { kind: 'unavailable' }; cache.set(path, state); return state }\n try {\n const target = await resolveTarget(ctx, session, path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') { const state: ReadState = { kind: 'missing' }; cache.set(path, state); return state }\n if ((info.size ?? 0) > READ_CAP) { const state: ReadState = { kind: 'unavailable' }; cache.set(path, state); return state }\n const state: ReadState = { kind: 'content', content: await fs.readText(target) }\n cache.set(path, state)\n return state\n } catch (error) {\n const state: ReadState = { kind: 'unavailable' }\n cache.set(path, state)\n return state\n }\n}\n\n/**\n * 判断记录是否已无任何可操作差异(stale):待决策 hunk 的新文本在磁盘均找不到,\n * 或新建文件已不存在,或全为空差异。满足则应由 host 自动归档。\n * @author ddj 2026年08月20号\n */\nexport async function recordIsStale(ctx: Ctx, session: Session, cache: Map<string, ReadState>, rec: DiffRecord): Promise<boolean> {\n if (rec.superseded === true) return true\n if (!Array.isArray(rec.hunks) || !rec.hunks.length) return true\n const state = await readForCache(ctx, session, cache, rec.path)\n if (state.kind === 'unavailable') return false\n if (state.kind === 'missing') return true\n if (rec.create === true) return false\n const pending = rec.hunks.map((_, idx) => ({ idx, hunk: preciseHunk(rec, idx), status: rec.decisions.perHunk[idx] ?? rec.decisions.call }))\n .filter((item) => item.status === 'pending' && item.hunk && !isNoopHunk(item.hunk))\n if (!pending.length) return true\n const currentFingerprint = fingerprint(state.content)\n if (rec.afterFingerprint && currentFingerprint === rec.afterFingerprint) { rec.conflict = false; return false }\n // 归一化口径对比:外部工具可能改变 BOM/行尾,内容语义未变不应判冲突\n const normalizedContent = normalizeForCompare(state.content)\n if (rec.after != null && fingerprint(normalizeForCompare(rec.after)) === fingerprint(normalizedContent)) { rec.conflict = false; return false }\n const locations = locateHunks(normalizedContent, pending.map((item) => normalizeHunk(item.hunk!)))\n if (locations.some((location) => location.matched)) { rec.conflict = false; return false }\n rec.conflict = true\n return false\n}\n\n/**\n * edrv.list 全量轮询时自动清理 stale 记录:标记 superseded 并归档,\n * 防止\"幽灵差异\"长期留在审查列表且无法操作。\n * @author ddj 2026年08月20号\n * @returns 自动归档条数\n */\nexport async function autoArchiveStale(ctx: Ctx, session: Session, cwd: string, bucket: Map<string, DiffRecord>): Promise<number> {\n const fs = ctx.get('fs')\n if (!fs) return 0\n const cache = new Map<string, ReadState>()\n const stale: DiffRecord[] = []\n for (const rec of bucket.values()) {\n if (rec.archived || rec.superseded === true) continue\n if (await recordIsStale(ctx, session, cache, rec)) stale.push(rec)\n }\n if (!stale.length) return 0\n for (const r of stale) { r.superseded = true; r.at = new Date().toISOString() }\n await archiveRecords(ctx, session, cwd, bucket, stale, '差异无法定位(已被后续修改覆盖),自动归档')\n return stale.length\n}\n\n/** 读取归档 sidecar 文本(缺失/失败 → null)。 */\nexport async function readArchiveText(ctx: Ctx, cwd: string | null): Promise<string | null> {\n const fs = ctx.get('fs')\n if (!fs || !cwd) return null\n try {\n return await fs.readText(await fs.resolve(SIDECAR_ARCHIVE, { cwd }))\n } catch (error) {\n return null\n }\n}\n\n/** 解析归档 sidecar(损坏 → 空数组)。 */\nexport function parseArchive(text: string | null): ArchiveBatch[] {\n if (!text) return []\n try {\n const data = JSON.parse(text)\n if (data && typeof data === 'object' && Array.isArray(data.batches)) return data.batches as ArchiveBatch[]\n } catch (error) { /* 忽略损坏 */ }\n return []\n}\n\n/** 追加归档条目(按 cwd+path+batch 合并,同 callId 去重)。 */\nexport async function appendArchiveEntries(ctx: Ctx, cwd: string, entries: Array<ReturnType<typeof archiveEntryFor>>, session?: Session): Promise<void> {\n const fs = ctx.get('fs')\n if (!fs || !cwd) return\n try {\n const target = await fs.resolve(SIDECAR_ARCHIVE, { cwd })\n const existing = parseArchive(await readArchiveText(ctx, cwd))\n for (const e of entries) {\n const idx = existing.findIndex((x) => x.cwd === e.cwd && x.path === e.path && x.batch === e.batch)\n if (idx >= 0) {\n const exist = existing[idx]\n const seen = new Set((exist.records || []).map((r) => r.callId))\n for (const rec of e.records) {\n if (!seen.has(String(rec.callId))) {\n exist.records.push(rec as unknown as ArchiveBatch['records'][number])\n seen.add(String(rec.callId))\n }\n }\n exist.lastAt = e.at\n exist.reason = e.reason\n } else {\n existing.push(e as unknown as ArchiveBatch)\n }\n }\n const data: ArchiveData = { version: 1, updatedAt: new Date().toISOString(), batches: existing }\n await fs.writeText(target, JSON.stringify(data), void 0, void 0, policyOf(ctx, session))\n } catch (error) {\n log.error('appendArchiveEntries failed: ' + String(error))\n }\n}\n\n/**\n * 归档记录:标记 archived、按批次写入归档、落盘工作区桶。\n * @param opts.deferSave 为 true 时只写归档、不落盘桶(由批量调用方统一 saveBucket 一次)\n */\nexport async function archiveRecords(\n ctx: Ctx,\n session: Session,\n cwd: string,\n bucket: Map<string, DiffRecord>,\n recs: DiffRecord[],\n reason: string,\n opts?: { deferSave?: boolean },\n): Promise<void> {\n if (!recs.length) return\n const fresh = recs.filter((r) => !r.archived)\n for (const r of recs) r.archived = true\n const entries: Array<ReturnType<typeof archiveEntryFor>> = []\n for (const list of groupByBatch(recs).values()) entries.push(archiveEntryFor(list, cwd, reason))\n await appendArchiveEntries(ctx, cwd, entries, session)\n if (fresh.length && !opts?.deferSave) await saveBucket(ctx, cwd, bucket, session)\n}\n","/**\n * dsh-vscode-mode host — 工作区记录桶注册表与会话助手。\n * 迁移自原 src/index.ts 的 registry/sessionOf/cwdOf/bucketOf,语义不改。\n * 作者 ddj 2026-08-20\n */\nimport type { DiffRecord } from './shared/types.js'\nimport type { Ctx, Session } from './store.js'\nimport { loadBucket } from './store.js'\n\n/** cwd → 记录桶(内存缓存;随会话销毁清理)。 */\nexport type Registry = Map<string, Map<string, DiffRecord>>\n\n/** 按 sessionId 取会话;缺省时仅当唯一活跃会话才返回。 */\nexport function sessionOf(ctx: Ctx, sessionId?: string): Session | undefined {\n const sessions = ctx.get('sessions')\n if (!sessions) return undefined\n if (sessionId) return sessions.get(sessionId)\n const live = sessions.list().filter((s: Session) => s.id)\n return live.length === 1 ? live[0] : undefined\n}\n\n/** 会话工作区 cwd。 */\nexport function cwdOf(session: Session | undefined): string | null {\n return session?.header?.cwd ?? null\n}\n\n/** 取(或加载)某工作区记录桶。 */\nexport function bucketOf(registry: Registry, ctx: Ctx, cwd: string): Promise<Map<string, DiffRecord>> {\n const existing = registry.get(cwd)\n if (existing) return Promise.resolve(existing)\n return loadBucket(ctx, cwd).then((map) => {\n registry.set(cwd, map)\n return map\n })\n}\n","/**\n * dsh-vscode-mode host — 目录树纯函数(edrv.listDir 的数据整形与守卫)。\n * 不触 fs/node,仅结构类型,可单测;RPC handler 只做装配,判定都收在这里。\n * 作者 ddj 2026-08-26\n */\nimport type { TreeEntry } from './shared/rpc.js'\n\n/** fs.listDir 返回项的结构最小视图(不引 dsh-fs,保持纯函数零依赖)。 */\nexport interface DirChildLike {\n name: string\n type: 'file' | 'directory' | 'other'\n size?: number\n}\n\n/** 目录在文件前、名称按小写字母序的比较器(对齐 VSCode 资源管理器习惯)。 */\nfunction entryOrder(a: { name: string; type: string }, b: { name: string; type: string }): number {\n const aDir = a.type === 'directory' ? 0 : 1\n const bDir = b.type === 'directory' ? 0 : 1\n if (aDir !== bDir) return aDir - bDir\n const la = a.name.toLocaleLowerCase('en-US')\n const lb = b.name.toLocaleLowerCase('en-US')\n return la < lb ? -1 : la > lb ? 1 : 0\n}\n\n/**\n * 归一化目录相对路径:去空白、反斜杠→斜杠、去首尾斜杠、`.`→''。\n * 任一路径段为 `..` 返回 null(拒绝越界)。\n * @author ddj 2026年08月26号\n * @param path 原始相对路径('' 表示根目录)\n * @returns 归一化相对路径('' = 根),非法返回 null\n */\nexport function normalizeRel(path: string | undefined | null): string | null {\n const rel = String(path ?? '').trim().replace(/\\\\/g, '/').replace(/^\\/+|\\/+$/g, '')\n if (!rel) return ''\n const segs = rel.split('/').filter((seg) => seg !== '.')\n if (!segs.length) return ''\n for (const seg of segs) {\n if (seg === '..') return null\n }\n return segs.join('/')\n}\n\n/**\n * fs.listDir 结果 → TreeEntry 数组:相对路径拼接 + 目录优先排序。\n * @author ddj 2026年08月26号\n * @param rel 父目录相对路径('' = 根)\n * @param children 目录子项\n * @returns 排序后的树条目\n */\nexport function toTreeEntries(rel: string, children: DirChildLike[]): TreeEntry[] {\n const out: TreeEntry[] = []\n for (const child of children) {\n if (!child || typeof child.name !== 'string' || !child.name) continue\n out.push({\n name: child.name,\n path: rel ? rel + '/' + child.name : child.name,\n type: child.type === 'directory' ? 'directory' : child.type === 'file' ? 'file' : 'other',\n size: typeof child.size === 'number' ? child.size : undefined,\n })\n }\n return out.sort(entryOrder)\n}\n","/**\n * dsh-vscode-mode host — 目录快速列取(edrv.listDir 数据来源,树索引 miss 时走这里)。\n * dsh-fs.listDir 对每个子项顺序 realpath+stat(2 次 open/项),在本部署被中介的\n * open(0.3–3s/次)下大目录呈分钟级;这里用原生 readdir(withFileTypes) 一次取型\n * (O(1) open),仅对 symlink/junction(Windows junction 在 dirent 中报 symlink,\n * 已实测)并行 follow-stat 判型,延迟按轮摊平而非按条目累加。\n * 结果形状与 dsh-fs 一致(name/type),由调用方 toTreeEntries 整形排序。\n * 作者 ddj 2026-08-31\n */\nimport { readdir, stat } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { DirChildLike } from './tree.js'\n\n// --region 常量\n/** symlink 并行 stat 分块并发数(并行摊平单次 open 延迟)。 */\nexport const SYMLINK_CONCURRENCY = 32\n/** symlink 并行 stat 总数上限:超出部分按 other(防御病态 symlink 目录)。 */\nexport const MAX_SYMLINK_STATS = 256\n// --endregion\n\n/** 列取失败(带稳定语义 code,调用方转文案)。 */\nexport class DirListError extends Error {\n constructor(\n readonly code: 'not-found' | 'not-dir' | 'permission' | 'io',\n message: string,\n ) {\n super(message)\n }\n}\n\n/** node fs 错误码 → 稳定语义错误。 */\nfunction codeOf(err: unknown): DirListError {\n const code = (err as NodeJS.ErrnoException | undefined)?.code\n if (code === 'ENOENT') return new DirListError('not-found', '目录不存在')\n if (code === 'ENOTDIR') return new DirListError('not-dir', '不是目录')\n if (code === 'EACCES' || code === 'EPERM' || code === 'EBUSY') return new DirListError('permission', '权限不足')\n return new DirListError('io', String((err as Error | undefined)?.message ?? err))\n}\n\n/** 并行 stat 一批绝对路径 → 目录/文件/other(follow symlink,失败按 other)。 */\nasync function statTypes(paths: string[], out: Map<string, 'directory' | 'file' | 'other'>): Promise<void> {\n const cap = Math.min(paths.length, MAX_SYMLINK_STATS)\n for (let i = 0; i < cap; i += SYMLINK_CONCURRENCY) {\n const chunk = paths.slice(i, i + SYMLINK_CONCURRENCY)\n await Promise.all(chunk.map(async (p) => {\n try {\n const info = await stat(p)\n out.set(p, info.isDirectory() ? 'directory' : info.isFile() ? 'file' : 'other')\n } catch (error) {\n out.set(p, 'other')\n }\n }))\n }\n}\n\n/**\n * 快速列取目录:一次 readdir(withFileTypes) 判型;symlink 并行 follow-stat。\n * @author ddj 2026年08月31号\n * @param absDir 绝对目录路径(fs.resolve 后的 targetKey)\n * @returns 子项列表(name/type;size 缺省,树界面不展示大小)\n * @throws DirListError 目录不存在/不是目录/权限不足/IO 失败\n */\nexport async function listDirCheap(absDir: string): Promise<DirChildLike[]> {\n let dirents\n try {\n dirents = await readdir(absDir, { withFileTypes: true, encoding: 'utf8' })\n } catch (error) {\n throw codeOf(error)\n }\n const out: DirChildLike[] = []\n const syms: string[] = []\n for (const d of dirents) {\n if (d.isDirectory()) out.push({ name: d.name, type: 'directory' })\n else if (d.isFile()) out.push({ name: d.name, type: 'file' })\n else if (d.isSymbolicLink()) syms.push(d.name)\n else out.push({ name: d.name, type: 'other' })\n }\n if (syms.length) {\n const symAbs = syms.map((name) => join(absDir, name))\n const types = new Map<string, 'directory' | 'file' | 'other'>()\n await statTypes(symAbs, types)\n for (let i = 0; i < syms.length; i++) {\n out.push({ name: syms[i], type: types.get(symAbs[i]) ?? 'other' })\n }\n }\n return out\n}\n","/**\n * dsh-vscode-mode host — 工作区目录树索引(.sln 式结构缓存,层 2)。\n * 内存 Map<cwd, 索引> + 落盘缓存文件(工作区级:\n * ~/.dsh/dsh-vscode-mode/cache/workspace/<cwdHash>/tree.v<schema>.json,路径统一走\n * paths.ts PathConst):命中(ts 新鲜且未失效)内存直出 0 IO;列取结果 putIndex 更新\n * 并防抖落盘;agent 写入/手动保存 invalidateIndex 父目录+祖先 → 3s 防抖后台 re-heal\n * (并行、单轮有界、合并并发轮);TTL 兜底外部改动。缓存写读走原生 node:fs(与引擎\n * settings-file 一致,不占用工作区;沙箱只约束 ctx fs)。文件只存 {name,type}(path 由\n * 目录 rel 还原),落盘上限 400 目录/1500 条目/8MB 硬跳过——只是暖启动快照,正确性\n * 不依赖它。首次使用某 cwd 时清理旧工作区树 sidecar\n * (.dsh-edit-review-tree.json/.dsh-vscode-mode-tree.json,缓存可重建,删除无损)。\n * 纯函数部分导出可单测。\n * 作者 ddj 2026-08-31 / 2026-09-01\n */\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport type { TreeEntry } from './shared/rpc.js'\nimport type { Ctx } from './store.js'\nimport { toTreeEntries } from './tree.js'\nimport { DirListError, listDirCheap } from './treeRead.js'\nimport { LEGACY_TREE_SIDECARS, treeCacheFile } from './paths.js'\n\n// --region 常量\n/** 命中新鲜度:超过则视为过期,按需重列。 */\nexport const TREE_TTL_MS = 60_000\n/** 内存目录上限:超出按 ts 逐出最旧(常驻目录命中保活,不会误逐)。 */\nexport const MEM_MAX_DIRS = 2000\n/** 落盘目录上限(按 ts 裁旧)。 */\nexport const PERSIST_MAX_DIRS = 400\n/** 落盘单目录条目上限:超出截断并标 full=false(截断仍可即时渲染,客户端后台刷新补全)。 */\nexport const PERSIST_DIR_ENTRIES = 1500\n/** 落盘序列化硬上限:超出跳过落盘(内存索引照常工作)。 */\nexport const PERSIST_MAX_BYTES = 8 * 1024 * 1024\n/** 落盘防抖:变更后静默 10s 再写一次。 */\nexport const PERSIST_DEBOUNCE_MS = 10_000\n/** re-heal 防抖:写入密集期合并为 3s 后一轮。 */\nexport const HEAL_DEBOUNCE_MS = 3000\n/** re-heal 单轮目录数上限(并行,防 IO 风暴)。 */\nexport const HEAL_ROUND_MAX = 20\n// --endregion\n\n/** 索引条目(文件瘦身格式:不含 path,加载时由目录 rel 还原)。 */\nexport interface TreeIndexEntry {\n name: string\n type: 'file' | 'directory' | 'other'\n}\n\n/** 单个目录的索引(ts=最近确认时间;full=false 表示条目被落盘截断过)。 */\nexport interface TreeIndexDir {\n ts: number\n full: boolean\n entries: TreeEntry[]\n}\n\n/** 索引数据(内存全量;落盘前经 trimPersist 裁剪)。 */\nexport interface TreeIndexData {\n v: 1\n root: string | null\n dirs: Record<string, TreeIndexDir>\n}\n\n/** 每 cwd 的索引运行时状态。 */\ninterface IndexState {\n ctx: Ctx\n cwd: string\n data: TreeIndexData\n stale: Set<string>\n dirty: boolean\n persistTimer: ReturnType<typeof setTimeout> | null\n healTimer: ReturnType<typeof setTimeout> | null\n pending: Map<string, Promise<{ entries: TreeEntry[] } | { error: string }>>\n loading: boolean\n loadPromise: Promise<void> | null\n}\n\n/** cwd → 索引状态(随会话销毁清理)。 */\nconst states = new Map<string, IndexState>()\n/** 单调时钟:连续 put 的 ts 严格递增(同毫秒不并列,逐出/裁剪顺序可预期)。 */\nlet clock = 0\n\n/** 取下一时间戳(不小于真实时间且严格递增)。 */\nfunction nextTs(): number {\n clock = Math.max(Date.now(), clock + 1)\n return clock\n}\n\n// --region 纯函数(可单测)\n/** 条目原始值 → 合法条目(非法返回 null)。 */\nexport function entryOf(raw: unknown): TreeIndexEntry | null {\n if (!raw || typeof raw !== 'object') return null\n const e = raw as { name?: unknown; type?: unknown }\n if (typeof e.name !== 'string' || !e.name) return null\n const type = e.type === 'directory' ? 'directory' : e.type === 'file' ? 'file' : 'other'\n return { name: e.name, type }\n}\n\n/** 写入路径 → 相对工作区根的 rel(绝对路径按 cwd 前缀裁剪;越界/非法 → null)。 */\nexport function relOf(cwd: string, path: string): string | null {\n let rel = String(path ?? '').trim().replace(/\\\\/g, '/')\n const c = cwd.replace(/\\\\/g, '/').replace(/\\/+$/, '')\n const cl = c.toLowerCase()\n const pl = rel.toLowerCase()\n if (pl.startsWith(cl + '/')) rel = rel.slice(cl.length + 1)\n else if (rel.startsWith('/') || /^[a-z]:\\//i.test(rel)) return null\n rel = rel.replace(/^\\/+|\\/+$/g, '')\n if (!rel) return null\n const segs = rel.split('/').filter((s) => s !== '' && s !== '.')\n if (!segs.length) return null\n for (const s of segs) {\n if (s === '..') return null\n }\n return segs.join('/')\n}\n\n/** rel 的父目录 + 全部祖先('a/b/c' → ['a/b','a',''];'a' → [''])。 */\nexport function ancestorsOf(rel: string): string[] {\n const segs = rel.split('/')\n const out: string[] = []\n for (let i = segs.length - 1; i >= 1; i--) out.push(segs.slice(0, i).join('/'))\n out.push('')\n return out\n}\n\n/** 序列化索引数据。 */\nexport function indexSerialize(data: TreeIndexData): string {\n const lean: { v: 1; root: string | null; dirs: Record<string, { ts: number; full: boolean; entries: TreeIndexEntry[] }> } = { v: 1, root: data.root, dirs: {} }\n for (const [rel, dir] of Object.entries(data.dirs)) {\n lean.dirs[rel] = { ts: dir.ts, full: dir.full, entries: dir.entries.map((e) => ({ name: e.name, type: e.type })) }\n }\n return JSON.stringify(lean)\n}\n\n/** 解析索引文本;损坏/格式不符 → null。 */\nexport function indexParse(text: string | null): TreeIndexData | null {\n if (!text) return null\n try {\n const raw = JSON.parse(text) as { v?: unknown; root?: unknown; dirs?: unknown }\n if (!raw || raw.v !== 1 || !raw.dirs || typeof raw.dirs !== 'object') return null\n const dirs: Record<string, TreeIndexDir> = {}\n for (const [rel, d] of Object.entries(raw.dirs)) {\n if (!d || typeof d !== 'object') continue\n const dir = d as { ts?: unknown; full?: unknown; entries?: unknown }\n if (!Array.isArray(dir.entries)) continue\n const entries: TreeEntry[] = []\n for (const rawEntry of dir.entries) {\n const e = entryOf(rawEntry)\n if (!e) continue\n entries.push({ name: e.name, path: rel ? rel + '/' + e.name : e.name, type: e.type })\n }\n if (!entries.length) continue\n dirs[rel] = { ts: typeof dir.ts === 'number' ? dir.ts : 0, full: dir.full === true, entries }\n }\n return { v: 1, root: typeof raw.root === 'string' ? raw.root : null, dirs }\n } catch (error) {\n return null\n }\n}\n\n/** 落盘裁剪:目录按 ts 取新裁旧、单目录超限截断标 full=false(内存不受影响)。 */\nexport function trimPersist(data: TreeIndexData, maxDirs = PERSIST_MAX_DIRS, maxEntries = PERSIST_DIR_ENTRIES): TreeIndexData {\n const dirs: Record<string, TreeIndexDir> = {}\n const sorted = Object.entries(data.dirs).sort((a, b) => b[1].ts - a[1].ts)\n for (const [rel, dir] of sorted) {\n if (Object.keys(dirs).length >= maxDirs) break\n const full = dir.entries.length <= maxEntries\n dirs[rel] = { ts: dir.ts, full, entries: full ? dir.entries : dir.entries.slice(0, maxEntries) }\n }\n return { v: 1, root: data.root, dirs }\n}\n// --endregion\n\n// --region 状态机\n/** 取(或建)某 cwd 的索引状态,并惰性加载落盘快照(合并:文件 ts 更新才采纳)。 */\nfunction ensureState(ctx: Ctx, cwd: string): IndexState {\n const existing = states.get(cwd)\n if (existing) return existing\n const state: IndexState = {\n ctx,\n cwd,\n data: { v: 1, root: null, dirs: {} },\n stale: new Set(),\n dirty: false,\n persistTimer: null,\n healTimer: null,\n pending: new Map(),\n loading: false,\n loadPromise: null,\n }\n states.set(cwd, state)\n state.loadPromise = loadIndex(state)\n // 首次使用该工作区:清理旧版本在工作区根留下的树缓存 sidecar(缓存可重建,删除无损)\n void removeLegacyTreeSidecars(state.cwd)\n return state\n}\n\n/** 清理旧工作区树 sidecar(.dsh-edit-review-tree.json/.dsh-vscode-mode-tree.json)。 */\nexport async function removeLegacyTreeSidecars(cwd: string): Promise<void> {\n await Promise.all(LEGACY_TREE_SIDECARS.map(async (name) => {\n try {\n await rm(join(cwd, name), { force: true })\n } catch (error) { /* 删除失败静默 */ }\n }))\n}\n\n/** 惰性加载落盘快照一次(缺失/损坏 → 空索引;失败静默)。 */\nasync function loadIndex(state: IndexState): Promise<void> {\n if (state.loading) return\n state.loading = true\n try {\n const parsed = indexParse(await readFile(treeCacheFile(state.cwd), 'utf8'))\n if (!parsed) return\n for (const [rel, dir] of Object.entries(parsed.dirs)) {\n const cur = state.data.dirs[rel]\n if (!cur || dir.ts > cur.ts) state.data.dirs[rel] = dir\n }\n if (parsed.root && !state.data.root) state.data.root = parsed.root\n } catch (error) { /* 缺失/损坏/失败均按空索引 */ }\n finally {\n state.loading = false\n }\n}\n\n/** 命中:新鲜且未失效 → 条目(并刷新 ts 保活);否则 null。 */\nexport function hitIndex(cwd: string, rel: string): TreeEntry[] | null {\n const state = states.get(cwd)\n if (!state) return null\n const dir = state.data.dirs[rel]\n if (!dir || state.stale.has(rel)) return null\n const now = Date.now()\n if (now - dir.ts > TREE_TTL_MS) return null\n dir.ts = now\n return dir.entries\n}\n\n/** 更新某目录条目:写内存 + 打脏 + 防抖落盘;stale 撤销。 */\nexport function putIndex(ctx: Ctx, cwd: string, rel: string, entries: TreeEntry[]): void {\n const state = ensureState(ctx, cwd)\n const dirs = state.data.dirs\n if (!dirs[rel] && Object.keys(dirs).length >= MEM_MAX_DIRS) {\n let oldest = rel\n let oldestTs = Infinity\n for (const [k, v] of Object.entries(dirs)) {\n if (v.ts < oldestTs) {\n oldestTs = v.ts\n oldest = k\n }\n }\n delete dirs[oldest]\n }\n dirs[rel] = { ts: nextTs(), full: entries.length <= PERSIST_DIR_ENTRIES, entries }\n state.stale.delete(rel)\n state.dirty = true\n schedulePersist(state)\n}\n\n/** 写入路径失效:父目录+祖先进 stale,并调度后台 re-heal。 */\nexport function invalidateIndex(ctx: Ctx, cwd: string, path: string): void {\n const rel = relOf(cwd, path)\n if (rel === null) return\n const state = ensureState(ctx, cwd)\n for (const anc of ancestorsOf(rel)) state.stale.add(anc)\n scheduleHeal(state)\n}\n\n/** 调度 re-heal(防抖合并;已有定时器则复用)。 */\nfunction scheduleHeal(state: IndexState): void {\n if (state.healTimer) return\n state.healTimer = setTimeout(() => {\n state.healTimer = null\n void healRound(state)\n }, HEAL_DEBOUNCE_MS)\n}\n\n/** 后台自愈一轮:并行重列 ≤HEAL_ROUND_MAX 个 stale 目录;失败移出(交给 TTL/展开路径自愈)。 */\nasync function healRound(state: IndexState): Promise<void> {\n if (!state.stale.size) return\n const targets = [...state.stale].slice(0, HEAL_ROUND_MAX)\n await Promise.all(targets.map(async (rel) => {\n const res = await listDirCached(state.ctx, state.cwd, rel, true)\n if ('error' in res) state.stale.delete(rel)\n }))\n if (state.stale.size) scheduleHeal(state)\n}\n\n/** 调度落盘(防抖;已有定时器则重置)。 */\nfunction schedulePersist(state: IndexState): void {\n if (state.persistTimer) clearTimeout(state.persistTimer)\n state.persistTimer = setTimeout(() => {\n state.persistTimer = null\n void persistNow(state)\n }, PERSIST_DEBOUNCE_MS)\n}\n\n/** 落盘快照(裁剪 + 序列化 + 超限跳过;raw fs 写 ~/.dsh 缓存根,失败静默)。 */\nasync function persistNow(state: IndexState): Promise<void> {\n if (!state.dirty) return\n try {\n const json = indexSerialize(trimPersist(state.data))\n if (json.length > PERSIST_MAX_BYTES) {\n state.dirty = false\n return\n }\n await mkdir(dirname(treeCacheFile(state.cwd)), { recursive: true })\n await writeFile(treeCacheFile(state.cwd), json, 'utf8')\n state.dirty = false\n } catch (error) { /* 写缓存失败静默:内存索引不受影响 */ }\n}\n\n/** 清理某 cwd 索引(会话销毁时):清定时器,dirty 则尽力补写一次。 */\nexport function disposeIndex(cwd: string): void {\n const state = states.get(cwd)\n if (!state) return\n if (state.persistTimer) {\n clearTimeout(state.persistTimer)\n state.persistTimer = null\n }\n if (state.healTimer) {\n clearTimeout(state.healTimer)\n state.healTimer = null\n }\n if (state.dirty) void persistNow(state)\n states.delete(cwd)\n}\n// --endregion\n\n/** 错误 → 用户文案(DirListError 用自身 message,其余带上下文)。 */\nfunction errorText(error: unknown): string {\n if (error instanceof DirListError) return error.message\n return '读取目录失败:' + String(error)\n}\n\n/**\n * 目录列取统一入口(RPC handler 用):命中索引直出;失效/force 走快路径\n * (resolve + listDirCheap + putIndex);同 (cwd,rel) 在途请求复用同一 Promise。\n * @author ddj 2026年08月31号 / 2026年09月01号\n * @param ctx DSH 上下文(仅用于工作区 IO)\n * @param cwd 工作区根\n * @param rel 归一化相对路径('' = 根)\n * @param force 跳过索引命中,强制实列\n * @returns 目录条目与工作区根,或错误文案\n */\nexport async function listDirCached(\n ctx: Ctx,\n cwd: string,\n rel: string,\n force: boolean,\n): Promise<{ entries: TreeEntry[]; root: string } | { error: string }> {\n const state = ensureState(ctx, cwd)\n // 首次请求等待落盘快照加载完成(此后命中快照;加载失败则照常实列)\n if (state.loadPromise) await state.loadPromise\n const fs = ctx.get('fs')\n if (!fs) return { error: '缺少 fs' }\n if (!state.data.root) {\n try {\n state.data.root = String(fs.processPath(await fs.resolve('.', { cwd })))\n } catch (error) {\n return { error: errorText(error) }\n }\n }\n const root = state.data.root as string\n if (!force) {\n const hit = hitIndex(cwd, rel)\n if (hit) return { entries: hit, root }\n }\n const inflight = state.pending.get(rel)\n if (inflight) {\n const res = await inflight\n return 'entries' in res ? { entries: res.entries, root } : res\n }\n const task = (async (): Promise<{ entries: TreeEntry[] } | { error: string }> => {\n try {\n const target = await fs.resolve(rel || '.', { cwd })\n const children = await listDirCheap(target.targetKey)\n const entries = toTreeEntries(rel, children)\n putIndex(ctx, cwd, rel, entries)\n return { entries }\n } catch (error) {\n // 目录已被外部删除:从索引移除,避免陈旧条目长期滞留\n if (error instanceof DirListError && error.code === 'not-found') {\n if (state.data.dirs[rel]) {\n delete state.data.dirs[rel]\n state.dirty = true\n schedulePersist(state)\n }\n state.stale.delete(rel)\n }\n return { error: errorText(error) }\n }\n })()\n state.pending.set(rel, task)\n try {\n const res = await task\n return 'entries' in res ? { entries: res.entries, root } : res\n } finally {\n if (state.pending.get(rel) === task) state.pending.delete(rel)\n }\n}\n","/**\n * dsh-vscode-mode host — 捕获层:监听 tools/result,把 edit/write 差异落成审查记录。\n * 迁移自原 src/index.ts 的 tools/result 处理,语义不改。\n * 作者 ddj 2026-08-20\n */\nimport type { DiffRecord, Hunk } from './shared/types.js'\nimport { annotateHunks, fingerprint } from './shared/diff.js'\nimport type { Ctx, Session } from './store.js'\nimport { loadBucket, saveBucket } from './store.js'\nimport { fileMaxBatch, prune } from './model.js'\nimport type { Registry } from './registry.js'\nimport { cwdOf } from './registry.js'\nimport { invalidateIndex } from './treeIndex.js'\nimport { log } from './log.js'\n\n/** 校验并提取工具 result meta 中的文件 hunk。 */\nfunction validHunks(raw: unknown): Hunk[] {\n if (!Array.isArray(raw)) return []\n const hunks: Hunk[] = []\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const hunk = item as Record<string, unknown>\n if (typeof hunk.newText !== 'string') continue\n if (hunk.oldText !== null && typeof hunk.oldText !== 'string') continue\n hunks.push({ oldText: hunk.oldText as string | null, newText: hunk.newText })\n }\n return hunks\n}\n\n/** 已有文件 write 的元数据缺失时,用权威整文件快照保底。 */\nfunction fallbackHunks(toolName: string, args: Record<string, unknown>, before: string | null, after: string | null, create: boolean): Hunk[] {\n if (create) return [{ oldText: null, newText: after ?? (typeof args.content === 'string' ? args.content : '') }]\n if (toolName === 'edit' && typeof args.old_string === 'string' && typeof args.new_string === 'string') {\n return [{ oldText: args.old_string, newText: args.new_string }]\n }\n if (toolName === 'write' && before !== null && after !== null && before !== after) {\n return [{ oldText: before, newText: after }]\n }\n if (toolName === 'write' && after !== null) return [{ oldText: null, newText: after }]\n return []\n}\n\n/**\n * 捕获一次工具执行结果(tools/result):edit/write 成功时构造记录、\n * 递增文件批次、融合归档被后续修改取代的旧差异、落盘。\n * @author ddj 2026年08月20号\n * @param ctx DSH 上下文\n * @param registry 工作区记录桶注册表\n * @param exec 工具执行描述(name/arguments/callId/agent.session)\n * @param result 执行结果(value/meta/isError)\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function captureToolResult(ctx: Ctx, registry: Registry, exec: any, result: any): Promise<void> {\n const session: Session | undefined = exec?.agent?.session\n if (!session || (exec?.name !== 'edit' && exec?.name !== 'write')) return\n if (result?.isError || !result?.value) return\n try {\n const cwd = cwdOf(session)\n if (!cwd) return\n const value = result.value\n const args = (exec.arguments || {}) as Record<string, unknown>\n const path = typeof value.path === 'string' ? value.path : args.file_path\n if (typeof path !== 'string' || !path) return\n const before = typeof value.before === 'string' ? value.before : null\n const after = typeof value.after === 'string' ? value.after : (typeof args.content === 'string' ? args.content : null)\n const create = exec.name === 'write' && value.before === null\n const callHunk = exec.name === 'edit' && typeof args.old_string === 'string' && typeof args.new_string === 'string'\n ? { oldText: args.old_string, newText: args.new_string }\n : null\n const metaHunks = validHunks(result.meta?.diffs)\n const rawHunks = metaHunks.length ? metaHunks : fallbackHunks(exec.name, args, before, after, create)\n const hunks = annotateHunks(rawHunks, before, after)\n if (!hunks.length || typeof exec.callId !== 'string') return\n const record: DiffRecord = {\n callId: exec.callId,\n toolName: exec.name,\n path,\n before,\n after,\n baseFingerprint: fingerprint(before),\n afterFingerprint: fingerprint(after),\n legacy: false,\n conflict: false,\n create,\n callHunk,\n hunks,\n decisions: { call: 'pending', perHunk: hunks.map(() => 'pending') },\n note: create ? '新建文件:全部拒绝将删除该文件' : before === null ? '未捕获修改前内容(大文件)' : null,\n superseded: false,\n archived: false,\n batch: 0,\n at: new Date().toISOString(),\n }\n let bucket = registry.get(cwd)\n if (!bucket) { bucket = await loadBucket(ctx, cwd); registry.set(cwd, bucket) }\n record.batch = fileMaxBatch(bucket, path) + 1\n bucket.set(exec.callId, record)\n // 同一文件的多次 edit/write 都保留为独立记录,便于逐条审查。\n // 旧实现按文件 batch 自动归档 prior,会导致界面看起来每个文件只剩一条差异。\n prune(bucket)\n await saveBucket(ctx, cwd, bucket, session)\n // agent 写盘后目录树可能变化(新建/删除文件/目录):父目录+祖先进失效,后台自愈。\n invalidateIndex(ctx, cwd, path)\n } catch (error) {\n log.error('capture failed: ' + String(error))\n }\n}\n","/**\n * dsh-vscode-mode host — 搜索 query 与路径规范化。\n * 查询只按字面连续片段比较,不解释为正则或 shell 语句。\n * 作者 ddj 2026年08月24号\n */\nimport { isAbsolute, resolve } from 'node:path'\nimport type { PreparedQuery } from './types.js'\n\n/**\n * 规范化用户搜索文本。\n * @author ddj 2026年08月24号\n * @param raw 原始搜索文本\n * @returns 用于比较和缓存的 query\n */\nexport function prepareQuery(raw: unknown): PreparedQuery {\n const value = String(raw ?? '').trim()\n return { raw: value, text: value.replaceAll('\\\\', '/').toLocaleLowerCase('en-US') }\n}\n\n/**\n * 归一化路径分隔符并移除无意义前缀。\n * @author ddj 2026年08月24号\n * @param value 原始路径\n * @returns 比较用路径\n */\nexport function pathText(value: string): string {\n return value.replaceAll('\\\\', '/').replace(/^\\.\\//, '')\n}\n\n/**\n * 生成不区分大小写的路径 key。\n * @author ddj 2026年08月24号\n * @param value 原始路径\n * @returns 去重 key\n */\nexport function pathKey(value: string): string {\n return pathText(value).toLocaleLowerCase('en-US')\n}\n\n/**\n * 将相对文件路径映射到 provider 根目录。\n * @author ddj 2026年08月24号\n * @param value 文件路径\n * @param root 工作区根目录\n * @returns 可供 edrv.read 使用的路径\n */\nexport function displayPath(value: string, root: string): string {\n const normalized = pathText(value)\n if (isAbsolute(normalized) || /^[A-Za-z]:\\//.test(normalized) || normalized.startsWith('//')) return normalized\n return resolve(root, normalized)\n}\n\n/**\n * 判断路径是否包含连续 query。\n * @author ddj 2026年08月24号\n * @param value 文件路径\n * @param query 已规范化 query\n * @returns 是否命中\n */\nexport function pathMatch(value: string, query: PreparedQuery): boolean {\n return pathText(value).toLocaleLowerCase('en-US').includes(query.text)\n}\n","/**\n * dsh-vscode-mode host — ripgrep 文件发现 provider。\n * 通过独立 argv 调用打包 rg,避免先构建巨型全量文件数组。\n * 作者 ddj 2026年08月24号\n */\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { createRequire } from 'node:module'\nimport type { Ctx, Session } from '../store.js'\nimport { policyOf } from '../store.js'\nimport { prepareQuery, pathText } from './query.js'\nimport type { WorkspaceSearchInput, WorkspaceSearchProvider, WorkspaceSearchResult } from './types.js'\n\nconst STDOUT_CAP = 4 << 20\nconst STDERR_CAP = 64 << 10\nconst GRACE_MS = 20_000\n\n/** 默认排除目录(文件/内容搜索共用,导出供 provider 复用)。 */\nexport const EXCLUDES = [\n 'node_modules', '.git', '.tmp', '.cache', 'dist', 'build', 'vendor',\n 'coverage', '__pycache__', '.pnpm-store', '.npm-cache', '.codegraph', '.workbuddy',\n]\n\n/**\n * 默认排除文件(glob 模式,文件/内容搜索共用)。\n * 插件自身 sidecar(内容搜索会命中其历史编辑文本,且单行巨型 JSON 会撑爆输出上限);\n * *.map 源映射(纯构建产物,内容搜索无意义且常为单行巨文件)。\n */\nexport const FILE_EXCLUDES = [\n '**/.dsh-edit-review.json',\n '**/.dsh-edit-review-archive.json',\n '**/.dsh-edit-review-debug.log',\n '**/*.map',\n]\n\ninterface SearchHandle {\n done: Promise<{ exitCode: number | null; code?: number | null }>\n collected?: {\n stdout?: { readFrom(offset: number): { text: string; lossy?: boolean } }\n stderr?: { readFrom(offset: number): { text: string } }\n }\n}\n\ninterface SearchSubprocess {\n spawn(spec: {\n argv: readonly string[]\n cwd: string\n stdio: { stdin: 'ignore'; stdout: { maxBytes: number }; stderr: { maxBytes: number } }\n graceMs: number\n signal?: AbortSignal\n }): SearchHandle\n}\n\n/**\n * 将 query 转成 rg 的字面 glob。\n * @author ddj 2026年08月24号\n * @param query 已规范化 query\n * @returns 安全 glob\n */\nexport function queryGlob(query: string): string {\n const value = pathText(query)\n const escaped = value.replace(/[\\*?\\[\\]{}!]/g, (char) => '\\\\' + char)\n return '**/*' + escaped + '*'\n}\n\n/**\n * 返回当前平台的 rg 可执行文件路径,不让可选依赖影响模块加载。\n * @author ddj 2026年08月24号\n * @returns rg 路径或 null\n */\nexport function ripgrepPath(): string | null {\n try {\n const require = createRequire(import.meta.url)\n const ripgrep = require('@vscode/ripgrep') as { rgPath?: unknown }\n if (typeof ripgrep.rgPath !== 'string' || !existsSync(ripgrep.rgPath)) return null\n return join(ripgrep.rgPath)\n } catch (error) {\n return null\n }\n}\n\n/**\n * 解析会话搜索根目录,并转换到 subprocess 执行世界。\n * @author ddj 2026年08月24号\n * @param ctx DSH 上下文\n * @param session 当前会话\n * @returns subprocess 可访问的根目录\n */\nexport async function searchRoot(ctx: Ctx, session: Session): Promise<string> {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs')\n const policy = policyOf(ctx, session)\n const cwd = session?.header?.cwd\n const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', cwd ? { cwd } : {})\n return fs.processPath(rootTarget)\n}\n\n/**\n * 读取收集输出并解析为路径候选。\n * @author ddj 2026年08月24号\n * @param handle subprocess handle\n * @param maxResults 候选上限\n * @returns 路径与完整性状态\n */\nexport function parseOutput(handle: SearchHandle, maxResults: number): { files: string[]; truncated: boolean; complete: boolean } {\n const reader = handle.collected?.stdout\n if (!reader) return { files: [], truncated: false, complete: false }\n const output = reader.readFrom(0)\n const values = output.text.split(/\\r?\\n/).map((line) => line.trim()).filter(Boolean)\n const unique = [...new Set(values)]\n const truncated = Boolean(output.lossy) || unique.length > maxResults\n return { files: unique.slice(0, maxResults).map(pathText), truncated, complete: !truncated }\n}\n\n/**\n * 读取已收集的 stderr(无收集器 → 空文本)。\n * @author ddj 2026年08月27号\n * @param handle subprocess handle\n * @returns stderr 文本\n */\nexport function readStderr(handle: SearchHandle): { text: string } {\n const reader = handle.collected?.stderr\n return reader ? reader.readFrom(0) : { text: '' }\n}\n\n/**\n * 取 stderr 首条非空行(去 \\r,截断 300 字符防撑爆 UI)。\n * @author ddj 2026年08月27号\n * @param text stderr 全文\n * @returns 首条诊断行(无则空串)\n */\nexport function firstStderrLine(text: string): string {\n for (const raw of String(text ?? '').split(/\\r?\\n/)) {\n const line = raw.trim()\n if (!line) continue\n return line.length > 300 ? line.slice(0, 300) + '…' : line\n }\n return ''\n}\n\n/**\n * 分类 rg 非 0/1 退出:pattern=模式错误(正则/glob 无效,无结果),\n * partial=遍历错误(rg 已输出的命中仍有效,结果不完整),hard=硬失败(其他退出码/超时被杀)。\n * @author ddj 2026年08月27号\n * @param code 退出码(null/undefined = 被终止,通常为 20s 超时)\n * @param stderrText stderr 全文\n * @returns 分类与中文提示文案(partial 的 message 即 warning 内容)\n */\nexport function rgExitFailure(code: number | null | undefined, stderrText: string): { kind: 'pattern' | 'partial' | 'hard'; message: string } {\n const detail = firstStderrLine(stderrText)\n if (/regex parse error/i.test(detail)) return { kind: 'pattern', message: '正则表达式无效:' + detail }\n if (/error parsing glob/i.test(detail)) return { kind: 'pattern', message: '文件过滤模式无效:' + detail }\n if (code === 2) {\n const count = String(stderrText ?? '').split(/\\r?\\n/).filter((line) => line.trim()).length\n const suffix = count > 1 ? '(共 ' + count + ' 处)' : ''\n return { kind: 'partial', message: (detail ? '部分路径无法访问,结果可能不完整:' + detail + suffix : '部分路径无法访问,结果可能不完整') }\n }\n if (code === null || code === undefined) return { kind: 'hard', message: '搜索超时(20 秒内未完成,已终止)' }\n return { kind: 'hard', message: 'ripgrep 退出码:' + String(code) + (detail ? '(' + detail + ')' : '') }\n}\n\n/**\n * 使用打包 ripgrep 搜索工作区文件。\n * @author ddj 2026年08月24号\n * @param input provider 输入\n * @returns 有界搜索结果\n */\nexport async function searchRipgrep(input: WorkspaceSearchInput): Promise<WorkspaceSearchResult> {\n const sub = input.ctx.get('subprocess') as SearchSubprocess | undefined\n if (!sub) throw new Error('缺少 subprocess')\n const binary = ripgrepPath()\n if (!binary) throw new Error('ripgrep 不可用')\n const root = input.root ?? await searchRoot(input.ctx, input.session)\n const query = prepareQuery(input.query)\n const argv = [binary, '--no-config', '--files', '--hidden', '--no-ignore', '--glob-case-insensitive', '--glob', queryGlob(query.text)]\n for (const excluded of EXCLUDES) argv.push('--glob', '!**/' + excluded + '/**')\n for (const excluded of FILE_EXCLUDES) argv.push('--glob', '!' + excluded)\n argv.push('--', root)\n const handle = sub.spawn({\n argv,\n cwd: root,\n stdio: { stdin: 'ignore', stdout: { maxBytes: STDOUT_CAP }, stderr: { maxBytes: STDERR_CAP } },\n graceMs: GRACE_MS,\n signal: input.signal,\n })\n let outcome: { exitCode: number | null; code?: number | null }\n try {\n outcome = await handle.done\n } catch (error) {\n throw new Error('ripgrep 启动失败:' + String(error))\n }\n const code = outcome.exitCode ?? outcome.code\n if (code !== 0 && code !== 1) {\n const failure = rgExitFailure(code, readStderr(handle).text)\n if (failure.kind !== 'partial') throw new Error(failure.message)\n // 遍历错误:已收集的文件列表仍有效,保留并标记不完整(warning 供上层展示,编排层丢弃不抛错)\n const parsed = parseOutput(handle, input.maxResults)\n return { ...parsed, warning: failure.message, complete: false, source: 'ripgrep' }\n }\n const parsed = parseOutput(handle, input.maxResults)\n if (!handle.collected?.stdout) throw new Error('ripgrep stdout 不可用')\n return { ...parsed, source: 'ripgrep' }\n}\n\n/**\n * 构造 ripgrep provider。\n * @author ddj 2026年08月24号\n * @returns provider 实例\n */\nexport function newRgProvider(): WorkspaceSearchProvider {\n return { search: searchRipgrep }\n}\n","/**\n * dsh-vscode-mode host — fs.listDir 查询感知 fallback。\n * provider 不可用时边遍历边匹配,不再伪装有限全量扫描为完整索引。\n * 作者 ddj 2026年08月24号\n */\nimport type { Ctx, Session } from '../store.js'\nimport { policyOf } from '../store.js'\nimport { pathText, pathMatch } from './query.js'\nimport { searchRoot } from './ripgrep.js'\nimport type { WorkspaceSearchInput, WorkspaceSearchProvider, WorkspaceSearchResult } from './types.js'\n\ninterface FsTarget { displayPath?: string }\ninterface FsEntry { name: string; type: 'file' | 'directory' | 'other'; target: FsTarget }\ninterface SearchFs {\n resolve(path: string, opts?: { cwd?: string; signal?: AbortSignal }): Promise<FsTarget>\n listDir(target: FsTarget, signal?: AbortSignal): Promise<FsEntry[]>\n}\n\nconst RESULT_CAP = 500\nconst EXCLUDED = new Set(['node_modules', '.git', '.tmp', '.cache', 'dist', 'build', 'vendor', 'coverage', '__pycache__', '.pnpm-store', '.npm-cache', '.codegraph', '.workbuddy', '.dsh-edit-review.json', '.dsh-edit-review-archive.json', '.dsh-edit-review-debug.log'])\n\n/**\n * 在一个目录树中递归查找匹配文件。\n * @author ddj 2026年08月24号\n * @param fs 文件系统能力\n * @param target 当前目录目标\n * @param input 搜索输入\n * @param files 已保留候选\n * @param signal 取消信号\n * @returns 是否因达到上限而截断\n */\nasync function walk(fs: SearchFs, target: FsTarget, input: WorkspaceSearchInput, files: string[], signal: AbortSignal): Promise<boolean> {\n if (signal.aborted) throw new DOMException('搜索已取消', 'AbortError')\n const entries = await fs.listDir(target, signal)\n for (const entry of entries) {\n if (signal.aborted) throw new DOMException('搜索已取消', 'AbortError')\n if (entry.type === 'directory') {\n if (EXCLUDED.has(entry.name)) continue\n if (await walk(fs, entry.target, input, files, signal)) return true\n continue\n }\n if (entry.type !== 'file') continue\n const path = pathText(entry.target.displayPath ?? entry.name)\n if (!pathMatch(path, { raw: input.query, text: pathText(input.query).toLocaleLowerCase('en-US') })) continue\n files.push(path)\n if (files.length >= Math.min(input.maxResults, RESULT_CAP)) return true\n }\n return false\n}\n\n/**\n * 使用 ctx.fs.listDir 搜索文件。\n * @author ddj 2026年08月24号\n * @param input provider 输入\n * @returns 有界 fallback 结果\n */\nexport async function searchFallback(input: WorkspaceSearchInput): Promise<WorkspaceSearchResult> {\n const fs = input.ctx.get('fs') as SearchFs | undefined\n if (!fs) throw new Error('缺少 fs')\n const policy = policyOf(input.ctx, input.session)\n const cwd = input.session?.header?.cwd\n const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', cwd ? { cwd, signal: input.signal } : { signal: input.signal })\n const signal = input.signal ?? new AbortController().signal\n const files: string[] = []\n const truncated = await walk(fs, rootTarget, input, files, signal)\n return { files, truncated, complete: !truncated, source: 'fallback' }\n}\n\n/**\n * 构造 fallback provider。\n * @author ddj 2026年08月24号\n * @returns provider 实例\n */\nexport function newFallback(): WorkspaceSearchProvider {\n return { search: searchFallback }\n}\n","/**\n * dsh-vscode-mode host — 可替换的连续匹配排序器。\n * 第一版保持 basename 优先和稳定路径序,后续可接 fuzzy scorer。\n * 作者 ddj 2026年08月24号\n */\nimport type { CandidateRanker, PreparedQuery, SearchCandidate } from './types.js'\nimport { pathText } from './query.js'\n\n/**\n * 生成搜索候选。\n * @author ddj 2026年08月24号\n * @param path 文件路径\n * @param source 候选来源\n * @returns 内部候选\n */\nexport function candidateOf(path: string, source: SearchCandidate['source']): SearchCandidate {\n const normalizedPath = pathText(path)\n const basename = normalizedPath.split('/').pop() ?? normalizedPath\n return { path, basename, normalizedPath: normalizedPath.toLocaleLowerCase('en-US'), source }\n}\n\n/**\n * 对连续匹配候选进行排序。\n * @author ddj 2026年08月24号\n * @param candidates 候选列表\n * @param query 已规范化 query\n * @returns 排序后的候选\n */\nexport function rankCandidates(candidates: SearchCandidate[], query: PreparedQuery): SearchCandidate[] {\n const text = query.text\n const score = (candidate: SearchCandidate): number => {\n const base = candidate.basename.toLocaleLowerCase('en-US')\n if (base.startsWith(text)) return 0\n if (base.includes(text)) return 1\n if (candidate.normalizedPath.includes(text)) return 2\n return 3\n }\n return [...candidates].sort((left, right) => score(left) - score(right) || left.normalizedPath.localeCompare(right.normalizedPath, 'en-US'))\n}\n\n/**\n * 默认候选排序器。\n * @author ddj 2026年08月24号\n * @returns 排序器\n */\nexport function substringRanker(): CandidateRanker {\n return { rank: rankCandidates }\n}\n","/**\n * dsh-vscode-mode host — 搜索编排、缓存和旧任务取消。\n * 对外只返回旧 RPC 所需的 files/truncated,内部保留 provider 边界。\n * 作者 ddj 2026年08月24号\n */\nimport type { Ctx, Session } from '../store.js'\nimport { policyOf } from '../store.js'\nimport { pathKey, pathMatch, pathText, prepareQuery } from './query.js'\nimport { searchRoot } from './ripgrep.js'\nimport { newRgProvider } from './ripgrep.js'\nimport { newFallback } from './fallback.js'\nimport { candidateOf, rankCandidates } from './ranker.js'\nimport type { CandidateRanker, SearchCandidate, WorkspaceSearchProvider, WorkspaceSearchResult } from './types.js'\n\nconst CACHE_TTL = 60_000\nconst CACHE_LIMIT = 100\nconst RESULT_LIMIT = 50\nconst PROVIDER_VERSION = 'ripgrep-v1'\nconst POLICY_VERSION = 'search-policy-v1'\n\ntype CacheEntry<T> = { at: number; result: T }\ntype SearchRequest = { session: Session; cwd: string; query: string; activePaths: string[] }\ntype SearchResponse = { files: string[]; truncated: boolean }\n\n/**\n * 短期有界搜索缓存(泛型:文件/内容搜索共用;clone 由调用方保证写隔离)。\n * @author ddj 2026年08月24号\n * @param clone 结果写隔离克隆(缺省恒等)\n */\nexport class SearchCache<T> {\n private readonly entries = new Map<string, CacheEntry<T>>()\n\n /**\n * 创建缓存。\n * @author ddj 2026年08月24号\n * @param clone 结果克隆函数(缺省直接引用)\n */\n constructor(private readonly clone: (value: T) => T = (value) => value) {}\n\n /**\n * 读取未过期条目。\n * @author ddj 2026年08月24号\n * @param key 缓存 key\n * @param now 当前时间\n * @returns 缓存结果或 undefined\n */\n get(key: string, now = Date.now()): T | undefined {\n const entry = this.entries.get(key)\n if (!entry) return undefined\n if (now - entry.at >= CACHE_TTL) { this.entries.delete(key); return undefined }\n this.entries.delete(key)\n this.entries.set(key, entry)\n return this.clone(entry.result)\n }\n\n /**\n * 写入成功 provider 结果。\n * @author ddj 2026年08月24号\n * @param key 缓存 key\n * @param result provider 结果\n * @param now 当前时间\n */\n set(key: string, result: T, now = Date.now()): void {\n this.entries.delete(key)\n this.entries.set(key, { at: now, result: this.clone(result) })\n while (this.entries.size > CACHE_LIMIT) this.entries.delete(this.entries.keys().next().value as string)\n }\n\n /**\n * 清理指定根目录的缓存。\n * @author ddj 2026年08月24号\n * @param root 工作区根目录\n */\n clearRoot(root: string): void {\n for (const key of this.entries.keys()) if (key.startsWith(root + '|')) this.entries.delete(key)\n }\n\n /**\n * 清空全部缓存。\n * @author ddj 2026年08月24号\n */\n clear(): void { this.entries.clear() }\n}\n\n/**\n * 获取 policy 版本,未知策略使用固定插件版本。\n * @author ddj 2026年08月24号\n * @param ctx DSH 上下文\n * @param session 当前会话\n * @returns 稳定版本文本\n */\nfunction policyVersion(ctx: Ctx, session: Session): string {\n const policy = policyOf(ctx, session)\n const version = policy?.version ?? policy?.policyVersion\n return typeof version === 'string' || typeof version === 'number' ? String(version) : POLICY_VERSION\n}\n\n/**\n * 将 root 内绝对路径统一成相对显示路径。\n * @author ddj 2026年08月24号\n * @param value 原始路径\n * @param root 搜索根\n * @returns 兼容 edrv.read 的路径\n */\nfunction displayPath(value: string, root: string): string {\n const path = pathText(value)\n const base = pathText(root).replace(/\\/$/, '')\n const lowerPath = path.toLocaleLowerCase('en-US')\n const lowerBase = base.toLocaleLowerCase('en-US')\n if (lowerPath === lowerBase) return '.'\n if (lowerPath.startsWith(lowerBase + '/')) return path.slice(base.length + 1)\n return path\n}\n\n/**\n * 为显示路径生成跨绝对/相对形式的去重 key。\n * @author ddj 2026年08月24号\n * @param value 原始路径\n * @param root 搜索根\n * @returns 去重 key\n */\nfunction displayKey(value: string, root: string): string {\n return pathKey(displayPath(value, root))\n}\n\n/**\n * 合并 provider 与 active diff 候选并去重。\n * @author ddj 2026年08月24号\n * @param result provider 结果\n * @param activePaths 活跃差异路径\n * @param root 搜索根\n * @param query 已规范化 query\n * @returns 候选列表\n */\nfunction mergeCandidates(result: WorkspaceSearchResult, activePaths: string[], root: string, query: ReturnType<typeof prepareQuery>): SearchCandidate[] {\n const candidates = new Map<string, SearchCandidate>()\n for (const path of result.files) {\n const shown = displayPath(path, root)\n if (pathMatch(shown, query)) candidates.set(displayKey(path, root), candidateOf(shown, 'workspace'))\n }\n for (const path of activePaths) {\n const shown = displayPath(path, root)\n if (!pathMatch(shown, query)) continue\n const key = displayKey(path, root)\n if (!candidates.has(key)) candidates.set(key, candidateOf(shown, 'active-diff'))\n }\n return [...candidates.values()]\n}\n\n/**\n * 搜索编排器。\n * @author ddj 2026年08月24号\n */\nexport class SearchOrchestrator {\n private readonly cache = new SearchCache<WorkspaceSearchResult>((r) => ({ ...r, files: [...r.files] }))\n private readonly inflight = new Map<string, AbortController>()\n private readonly rootsByCwd = new Map<string, Set<string>>()\n private readonly provider: WorkspaceSearchProvider\n private readonly fallback: WorkspaceSearchProvider\n private readonly ranker: CandidateRanker\n\n /**\n * 创建搜索编排器。\n * @author ddj 2026年08月24号\n * @param ctx DSH 上下文\n * @param provider 主 provider,可替换测试\n * @param fallback 降级 provider,可替换测试\n * @param ranker 排序器,可替换测试\n */\n constructor(private readonly ctx: Ctx, provider = newRgProvider(), fallback = newFallback(), ranker: CandidateRanker = { rank: rankCandidates }) {\n this.provider = provider\n this.fallback = fallback\n this.ranker = ranker\n }\n\n /**\n * 执行一次工作区搜索。\n * @author ddj 2026年08月24号\n * @param request 搜索请求\n * @returns 旧 RPC 响应字段\n */\n async search(request: SearchRequest): Promise<SearchResponse> {\n const query = prepareQuery(request.query)\n if (query.text.length < 2) return { files: [], truncated: false }\n let root: string\n try { root = await searchRoot(this.ctx, request.session) } catch (error) {\n return this.rankActive(request.activePaths, request.cwd, query)\n }\n const rootKey = pathText(root)\n const roots = this.rootsByCwd.get(request.cwd) ?? new Set<string>()\n roots.add(rootKey)\n this.rootsByCwd.set(request.cwd, roots)\n const key = [rootKey, query.text, policyVersion(this.ctx, request.session), PROVIDER_VERSION].join('|')\n const cached = this.cache.get(key)\n if (cached) return this.finish(cached, request.activePaths, root, query)\n this.inflight.get(root)?.abort()\n const controller = new AbortController()\n this.inflight.set(root, controller)\n try {\n let result: WorkspaceSearchResult\n let providerOk = true\n try {\n result = await this.provider.search({ ctx: this.ctx, session: request.session, cwd: request.cwd, query: query.raw, maxResults: 500, signal: controller.signal, root })\n } catch (error) {\n providerOk = false\n if (controller.signal.aborted) return { files: [], truncated: false }\n try {\n result = await this.fallback.search({ ctx: this.ctx, session: request.session, cwd: request.cwd, query: query.raw, maxResults: 500, signal: controller.signal, root })\n } catch (fallbackError) {\n return this.rankActive(request.activePaths, root, query)\n }\n }\n if (controller.signal.aborted) return { files: [], truncated: false }\n if (providerOk) this.cache.set(key, result)\n return this.finish(result, request.activePaths, root, query)\n } finally {\n if (this.inflight.get(root) === controller) this.inflight.delete(root)\n }\n }\n\n /**\n * 清理会话对应根目录的缓存和在途搜索。\n * @author ddj 2026年08月24号\n * @param cwd 会话工作区\n */\n dispose(cwd: string): void {\n const roots = this.rootsByCwd.get(cwd) ?? new Set<string>([cwd])\n for (const root of roots) {\n this.inflight.get(root)?.abort()\n this.inflight.delete(root)\n this.cache.clearRoot(root)\n }\n this.rootsByCwd.delete(cwd)\n }\n\n /**\n * 清理全部状态。\n * @author ddj 2026年08月24号\n */\n disposeAll(): void {\n for (const controller of this.inflight.values()) controller.abort()\n this.inflight.clear()\n this.rootsByCwd.clear()\n this.cache.clear()\n }\n\n /**\n * 将 provider 结果与 active diff 合并、排序和截断。\n * @author ddj 2026年08月24号\n * @param result provider 结果\n * @param activePaths active diff 路径\n * @param root 搜索根\n * @param query 已规范化 query\n * @returns 旧 RPC 响应字段\n */\n private finish(result: WorkspaceSearchResult, activePaths: string[], root: string, query: ReturnType<typeof prepareQuery>): SearchResponse {\n const candidates = this.ranker.rank(mergeCandidates(result, activePaths, root, query), query)\n return { files: candidates.slice(0, RESULT_LIMIT).map((candidate) => candidate.path), truncated: result.truncated || candidates.length > RESULT_LIMIT }\n }\n\n /**\n * provider 失败时仅保留 active diff 命中。\n * @author ddj 2026年08月24号\n * @param paths active diff 路径\n * @param root 搜索根\n * @param query 已规范化 query\n * @returns 旧 RPC 响应字段\n */\n private rankActive(paths: string[], root: string, query: ReturnType<typeof prepareQuery>): SearchResponse {\n const result: WorkspaceSearchResult = { files: [], truncated: false, complete: true, source: 'active-diff' }\n return this.finish(result, paths, root, query)\n }\n}\n\n/**\n * 创建默认编排器。\n * @author ddj 2026年08月24号\n * @param ctx DSH 上下文\n * @returns 搜索编排器\n */\nexport function newSearcher(ctx: Ctx): SearchOrchestrator {\n return new SearchOrchestrator(ctx)\n}\n","/**\n * dsh-vscode-mode host — 工作区内容搜索(rg --json 主路径 + 有界编排)。\n * 命中列由 rg 行内字节偏移转 UTF-16(1-based),可直接供 Monaco 跳转/高亮。\n * 无 fallback:provider 失败抛错,由 RPC 层转错误响应(避免整树读文件)。\n * 作者 ddj 2026年08月26号\n */\nimport type { Ctx, Session } from '../store.js'\nimport { pathText } from './query.js'\nimport { EXCLUDES, FILE_EXCLUDES, readStderr, rgExitFailure, ripgrepPath, searchRoot } from './ripgrep.js'\nimport { SearchCache } from './orchestrator.js'\nimport type { ContentMatch, ContentSearchInput, ContentSearchProvider, ContentSearchResult } from './types.js'\n\nconst STDOUT_CAP = 16 << 20\nconst STDERR_CAP = 64 << 10\nconst GRACE_MS = 20_000\nconst DEFAULT_MAX_MATCHES = 500\nconst DEFAULT_MAX_FILES = 100\nconst CACHE_TTL = 60_000\nconst CACHE_LIMIT = 100\nconst PROVIDER_VERSION = 'content-ripgrep-v1'\n/** 单行 JSON 记录上限:巨型单行文件(源映射/打包产物)的命中行对搜索 UI 无意义,直接跳过。 */\nconst MAX_RECORD_LINE = 1 << 20\n\n/** rg --json 单条 match 记录的宽松形状(未知字段忽略)。 */\ninterface RgJsonItem {\n type?: string\n data?: {\n path?: { text?: string }\n lines?: { text?: string }\n line_number?: number\n submatches?: Array<{ start?: number; end?: number }>\n }\n}\n\n/** 内容搜索请求(RPC 参数映射)。 */\nexport interface ContentSearchRequest {\n session: Session\n cwd: string\n query: string\n matchCase?: boolean\n wholeWord?: boolean\n regex?: boolean\n maxResults?: number\n /** 正选 glob(仅在这些文件内搜索)。 */\n include?: string[]\n /** 排除 glob(这些文件不参与搜索)。 */\n exclude?: string[]\n}\n\ntype ContentSearchResponse = { matches: ContentMatch[]; truncated: boolean; warning?: string }\n\n/**\n * 把行内字节偏移转成 UTF-16 列(1-based;越界钳到行尾)。\n * @author ddj 2026年08月26号\n * @param text 行文本\n * @param byteOffset 行内字节偏移(rg submatches.start/end,实测为行相对)\n * @returns 1-based UTF-16 列\n */\nexport function byteToUtf16Col(text: string, byteOffset: number): number {\n let bytes = 0\n let col = 1\n for (const char of text) {\n if (bytes >= byteOffset) break\n bytes += Buffer.byteLength(char)\n col++\n }\n return col\n}\n\n/**\n * 根内绝对路径 → 工作区相对显示路径(供 edrv.read 与面板展示)。\n * @author ddj 2026年08月26号\n * @param value rg 输出路径\n * @param root 搜索根(subprocess 执行世界)\n * @returns 相对路径(根外路径原样返回)\n */\nexport function displayPathOf(value: string | undefined, root: string): string {\n const path = pathText(String(value ?? ''))\n if (!path) return path\n const base = pathText(root).replace(/\\/$/, '')\n const lowerPath = path.toLocaleLowerCase('en-US')\n const lowerBase = base.toLocaleLowerCase('en-US')\n if (lowerPath === lowerBase) return '.'\n if (lowerPath.startsWith(lowerBase + '/')) return path.slice(base.length + 1)\n return path\n}\n\n/**\n * 解析 rg --json 输出为扁平命中列表(多子匹配展开,列转 UTF-16)。\n * @author ddj 2026年08月26号\n * @param text stdout 文本\n * @param root 搜索根\n * @returns 命中列表\n */\nexport function parseRgJsonLines(text: string, root: string): ContentMatch[] {\n const matches: ContentMatch[] = []\n for (const line of text.split(/\\r?\\n/)) {\n const trimmed = line.trim()\n if (!trimmed) continue\n let item: RgJsonItem\n try {\n item = JSON.parse(trimmed) as RgJsonItem\n } catch {\n continue\n }\n if (item?.type !== 'match' || !item.data) continue\n const data = item.data\n const path = displayPathOf(data.path?.text, root)\n const lineText = (data.lines?.text ?? '').replace(/\\r?\\n$/, '').replace(/\\r$/, '')\n if (lineText.length > MAX_RECORD_LINE) continue\n const lineNumber = data.line_number ?? 0\n for (const sub of data.submatches ?? []) {\n matches.push({\n path,\n line: lineNumber,\n startColumn: byteToUtf16Col(lineText, sub.start ?? 0),\n endColumn: byteToUtf16Col(lineText, sub.end ?? 0),\n text: lineText,\n })\n }\n }\n return matches\n}\n\n/**\n * 命中截断:匹配数/文件数双上限,超限标记 truncated。\n * @author ddj 2026年08月26号\n * @param matches 全部命中\n * @param maxMatches 匹配数上限\n * @param maxFiles 文件数上限\n * @returns 截断后的命中与标志\n */\nexport function applyCaps(matches: ContentMatch[], maxMatches: number, maxFiles: number): { matches: ContentMatch[]; truncated: boolean } {\n const seen = new Set<string>()\n const out: ContentMatch[] = []\n let truncated = false\n for (const match of matches) {\n if (out.length >= maxMatches) { truncated = true; break }\n if (!seen.has(match.path)) {\n if (seen.size >= maxFiles) { truncated = true; break }\n seen.add(match.path)\n }\n out.push(match)\n }\n return { matches: out, truncated }\n}\n\n/**\n * 构造 rg 内容搜索 argv(pattern 放 `--` 后首位置,支持前导 `-` 的查询)。\n * include/exclude 为用户 glob(gitignore 式,原样透传不转义),\n * 分别转正选 `--glob` 与排除 `--glob !`。\n * @author ddj 2026年08月26号\n * @param binary rg 路径\n * @param root 搜索根\n * @param input 搜索输入\n * @returns argv 数组\n */\nexport function contentArgv(binary: string, root: string, input: ContentSearchInput): string[] {\n const argv = [binary, '--no-config', '--json', '--line-number', '--no-heading', '--color', 'never', '--hidden', '--no-ignore']\n if (input.matchCase === true) argv.push('--case-sensitive')\n if (input.wholeWord === true) argv.push('--word-regexp')\n if (input.regex !== true) argv.push('--fixed-strings')\n for (const excluded of EXCLUDES) argv.push('--glob', '!**/' + excluded + '/**')\n for (const excluded of FILE_EXCLUDES) argv.push('--glob', '!' + excluded)\n for (const pattern of input.include ?? []) {\n const glob = String(pattern).trim()\n if (glob) argv.push('--glob', glob)\n }\n for (const pattern of input.exclude ?? []) {\n const glob = String(pattern).trim()\n if (glob) argv.push('--glob', '!' + glob)\n }\n argv.push('--', input.query, root)\n return argv\n}\n\n/**\n * 使用打包 ripgrep 搜索文件内容。\n * @author ddj 2026年08月26号\n * @param input provider 输入\n * @returns 有界内容搜索结果\n */\nexport async function searchRipgrepContent(input: ContentSearchInput): Promise<ContentSearchResult> {\n const sub = input.ctx.get('subprocess') as { spawn(spec: unknown): { done: Promise<{ exitCode: number | null; code?: number | null }>; collected?: { stdout?: { readFrom(offset: number): { text: string; lossy?: boolean } }; stderr?: { readFrom(offset: number): { text: string } } } } } | undefined\n if (!sub) throw new Error('缺少 subprocess')\n const binary = ripgrepPath()\n if (!binary) throw new Error('ripgrep 不可用')\n const root = input.root ?? await searchRoot(input.ctx, input.session)\n const handle = sub.spawn({\n argv: contentArgv(binary, root, input),\n cwd: root,\n stdio: { stdin: 'ignore', stdout: { maxBytes: STDOUT_CAP }, stderr: { maxBytes: STDERR_CAP } },\n graceMs: GRACE_MS,\n signal: input.signal,\n })\n let outcome: { exitCode: number | null; code?: number | null }\n try {\n outcome = await handle.done\n } catch (error) {\n throw new Error('ripgrep 启动失败:' + String(error))\n }\n const code = outcome.exitCode ?? outcome.code\n const failure = code !== 0 && code !== 1 ? rgExitFailure(code, readStderr(handle).text) : null\n if (failure && failure.kind !== 'partial') throw new Error(failure.message)\n const reader = handle.collected?.stdout\n if (!reader) throw new Error('ripgrep stdout 不可用')\n const output = reader.readFrom(0)\n const all = parseRgJsonLines(output.text, root)\n const maxMatches = Math.max(1, Math.min(input.maxResults ?? DEFAULT_MAX_MATCHES, DEFAULT_MAX_MATCHES))\n const capped = applyCaps(all, maxMatches, DEFAULT_MAX_FILES)\n const truncated = Boolean(output.lossy) || capped.truncated\n const result: ContentSearchResult = { ...capped, complete: !truncated, source: 'ripgrep' }\n // 遍历错误(退出码 2):rg 已输出的命中仍有效,保留结果、标记不完整并附部分结果提示\n if (failure) {\n result.complete = false\n result.warning = failure.message\n }\n return result\n}\n\n/**\n * 内容搜索编排器:短期缓存 + 同根在途取消 + 会话清理。\n * @author ddj 2026年08月26号\n */\nexport class ContentSearcher {\n private readonly cache = new SearchCache<ContentSearchResult>((r) => ({ ...r, matches: [...r.matches] }))\n private readonly inflight = new Map<string, AbortController>()\n private readonly rootsByCwd = new Map<string, Set<string>>()\n\n /**\n * 创建内容搜索编排器。\n * @author ddj 2026年08月26号\n * @param ctx DSH 上下文\n * @param provider 内容搜索 provider(测试可替换)\n */\n constructor(private readonly ctx: Ctx, private readonly provider: ContentSearchProvider = { search: searchRipgrepContent }) {}\n\n /**\n * 执行一次工作区内容搜索。\n * @author ddj 2026年08月26号\n * @param request 搜索请求\n * @returns RPC 响应字段(provider 失败抛错,abort 返回空)\n */\n async search(request: ContentSearchRequest): Promise<ContentSearchResponse> {\n const query = String(request.query ?? '').trim()\n if (query.length < 2) return { matches: [], truncated: false }\n let root: string\n try {\n root = await searchRoot(this.ctx, request.session)\n } catch {\n return { matches: [], truncated: false }\n }\n const rootKey = pathText(root)\n const roots = this.rootsByCwd.get(request.cwd) ?? new Set<string>()\n roots.add(rootKey)\n this.rootsByCwd.set(request.cwd, roots)\n const includeKey = (request.include ?? []).join(',')\n const excludeKey = (request.exclude ?? []).join(',')\n const key = [rootKey, query, request.matchCase ? 'mc' : '', request.wholeWord ? 'ww' : '', request.regex ? 'rx' : '', includeKey, excludeKey, PROVIDER_VERSION].join('|')\n const cached = this.cache.get(key)\n if (cached) return { matches: cached.matches, truncated: cached.truncated, warning: cached.warning }\n this.inflight.get(root)?.abort()\n const controller = new AbortController()\n this.inflight.set(root, controller)\n try {\n const result = await this.provider.search({\n ctx: this.ctx,\n session: request.session,\n cwd: request.cwd,\n query,\n matchCase: request.matchCase,\n wholeWord: request.wholeWord,\n regex: request.regex,\n maxResults: request.maxResults,\n include: request.include,\n exclude: request.exclude,\n signal: controller.signal,\n root,\n })\n if (controller.signal.aborted) return { matches: [], truncated: false }\n this.cache.set(key, result)\n return { matches: result.matches, truncated: result.truncated, warning: result.warning }\n } catch (error) {\n if (controller.signal.aborted) return { matches: [], truncated: false }\n throw error\n } finally {\n if (this.inflight.get(root) === controller) this.inflight.delete(root)\n }\n }\n\n /**\n * 清理会话对应根目录的缓存和在途搜索。\n * @author ddj 2026年08月26号\n * @param cwd 会话工作区\n */\n dispose(cwd: string): void {\n const roots = this.rootsByCwd.get(cwd) ?? new Set<string>([cwd])\n for (const root of roots) {\n this.inflight.get(root)?.abort()\n this.inflight.delete(root)\n this.cache.clearRoot(root)\n }\n this.rootsByCwd.delete(cwd)\n }\n\n /**\n * 清理全部状态。\n * @author ddj 2026年08月26号\n */\n disposeAll(): void {\n for (const controller of this.inflight.values()) controller.abort()\n this.inflight.clear()\n this.rootsByCwd.clear()\n this.cache.clear()\n }\n}\n\n/**\n * 创建默认内容搜索编排器。\n * @author ddj 2026年08月26号\n * @param ctx DSH 上下文\n * @returns 内容搜索编排器\n */\nexport function newContentSearcher(ctx: Ctx): ContentSearcher {\n return new ContentSearcher(ctx)\n}\n","/**\n * dsh-vscode-mode host — 回滚/删除(fs + subprocess 操作)。\n * 迁移自原 src/index.ts 的 revertCall/revertHunk/deleteCreated/restoreFile,语义不改。\n * 作者 ddj 2026-08-20\n */\nimport type { DiffRecord } from './shared/types.js'\nimport type { Ctx, Session } from './store.js'\nimport { policyOf, resolveTarget } from './store.js'\nimport { applyLocations, locateHunks, preciseHunk } from './shared/diff.js'\n\nexport type Result = { ok: true } | { ok: false; error: string }\n\n/**\n * 删除新建文件(拒绝创建时):subprocess 删除,路径先经 fs.contains 校验工作区边界。\n * @author ddj 2026年08月20号\n * @returns 成功或失败原因\n */\nexport async function deleteCreated(ctx: Ctx, session: Session, record: DiffRecord): Promise<Result> {\n const sub = ctx.get('subprocess')\n const fs = ctx.get('fs')\n if (!sub || !fs) return { ok: false, error: '回滚不可用:缺少 subprocess/fs' }\n const policy = policyOf(ctx, session)\n const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', {})\n const target = await resolveTarget(ctx, session, record.path)\n if (!fs.contains(rootTarget, target)) return { ok: false, error: '拒绝删除:目标不在会话工作区内' }\n const p = fs.processPath(target)\n // subprocess 契约:spawn({ argv, stdio, graceMs }),done → { exitCode },输出走 handle.collected\n const attempt = async (argv: string[]): Promise<void> => {\n const handle = sub.spawn({\n argv,\n stdio: { stdout: { maxBytes: 1 << 16 }, stderr: { maxBytes: 1 << 16 }, stdin: 'ignore' },\n graceMs: 10000,\n })\n const outcome = await handle.done\n const code = outcome?.exitCode ?? outcome?.code\n if (code !== 0) {\n const err = handle.collected?.stderr?.readFrom(0).text ?? ''\n throw new Error('exit ' + code + ' ' + err)\n }\n }\n try {\n await attempt(['powershell', '-NoProfile', '-NonInteractive', '-Command', 'Remove-Item -LiteralPath \"' + p + '\" -Force'])\n return { ok: true }\n } catch (error) {\n try {\n await attempt(['/bin/rm', '-f', '--', p])\n return { ok: true }\n } catch (error2) {\n return { ok: false, error: '删除失败(文件仍存在):' + String(error) + ' / ' + String(error2) }\n }\n }\n}\n\n/** 整调用回滚:write/编辑用 before 整文件恢复;新建文件转 deleteCreated。 */\nexport async function revertCall(ctx: Ctx, session: Session, record: DiffRecord): Promise<Result> {\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '回滚不可用:缺少 fs' }\n if (record.before === null) {\n if (!record.create) return { ok: false, error: '无法回滚:缺少修改前内容(大文件或旧记录)' }\n return deleteCreated(ctx, session, record)\n }\n try {\n const target = await resolveTarget(ctx, session, record.path)\n await fs.writeText(target, record.before, void 0, void 0, policyOf(ctx, session))\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '回滚失败:' + String(error) }\n }\n}\n\n/** 单 hunk 回滚:用 callHunk(edit 单 hunk 精确串)经 fs.editText 反替换。 */\nexport async function revertHunk(ctx: Ctx, session: Session, record: DiffRecord, idx: number): Promise<Result> {\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '回滚不可用:缺少 fs' }\n const precise = preciseHunk(record, idx)\n if (!precise) return { ok: false, error: '找不到该差异块' }\n try {\n const target = await resolveTarget(ctx, session, record.path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') return { ok: false, error: '回滚失败:文件不存在' }\n if ((info.size ?? 0) > 8 * 1024 * 1024) return { ok: false, error: '回滚失败:文件过大,无法安全定位' }\n const content = await fs.readText(target)\n const location = locateHunks(content, [precise])[0]\n if (!location?.matched) return { ok: false, error: '回滚失败:该区域可能已被后续修改影响' }\n const result = applyLocations(content, [location], true)\n await fs.writeText(target, result.content, void 0, void 0, policyOf(ctx, session))\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '回滚失败:该区域可能已被后续修改影响(' + String(error) + ')' }\n }\n}\n\n/**\n * 恢复文件到记录对应状态(批次回滚用):返回错误文案或 null(成功)。\n * @author ddj 2026年08月20号\n */\nexport async function restoreFile(ctx: Ctx, session: Session, rec: DiffRecord): Promise<string | null> {\n const fs = ctx.get('fs')\n if (!fs) return '缺少 fs'\n if (rec.before === null || rec.before === undefined) {\n if (rec.create === true) {\n const out = await deleteCreated(ctx, session, rec)\n return out.ok ? null : out.error\n }\n return '缺少修改前内容(大文件或旧记录),无法回滚'\n }\n try {\n const target = await resolveTarget(ctx, session, rec.path)\n await fs.writeText(target, rec.before, void 0, void 0, policyOf(ctx, session))\n return null\n } catch (error) {\n return '回滚失败:' + String(error)\n }\n}\n","/**\n * dsh-vscode-mode host — 规则管理(Codebuddy/Cursor 式 .mdc 规则)。\n * - 存储:用户规则 ~/.dsh/rules/*.mdc;项目规则 <工作区>/.dsh/rules/*.mdc(随仓库共享)。\n * - 格式:frontmatter(description / alwaysApply / globs / enabled)+ markdown 正文;\n * 类型映射 总是=always / 自动=auto(globs) / 手动=manual(仅索引);enabled 为本插件扩展字段,缺省 true。\n * - 生效:host 注册 systemPrompt.section(order 400),每次装配同步读取(mtime 缓存),\n * 项目规则按 AssembleContext.agent.id → 会话 cwd 注入;旧版 DSH 缺服务时优雅降级。\n * --region 划分:常量 / frontmatter 解析(纯)/ 文件名与开关(纯)/ 注入渲染(纯)/ IO / systemPrompt 装配\n * 作者 ddj 2026年09月03号\n */\nimport { existsSync, mkdirSync, readFileSync, readdirSync, statSync } from 'node:fs'\nimport { mkdir, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises'\nimport { Buffer } from 'node:buffer'\nimport { join } from 'node:path'\nimport { dshHome } from './paths.js'\nimport type { RuleInfo, RuleProject, RuleRefInput, RuleScope, RuleSaveInput } from './shared/rules.js'\nimport type { Ctx } from './store.js'\n\n// --region 常量与目录定位\n/** 规则文件名白名单:字母数字开头,仅字母数字点横下划线,.mdc 后缀(天然拒绝路径分隔符)。 */\nexport const RULE_FILE_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*\\.mdc$/\n/** Windows 保留设备名(防意外创建系统设备文件)。 */\nconst RESERVED_NAME_RE = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\\..*)?$/i\n/** 单目录最多加载的规则文件数(防失控目录拖垮装配)。 */\nconst RULE_DIR_CAP = 200\n/** 注入时单条规则正文字节上限(超出截断)。 */\nconst RULE_SINGLE_CAP = 16 * 1024\n/** 注入时单个作用域(用户/项目)总字节预算。 */\nconst RULE_SCOPE_CAP = 64 * 1024\n/** systemPrompt section 名(同层唯一)。 */\nconst SECTION_NAME = 'dsh-vscode-mode:rules'\n/** section 顺序:persona(0) 与 PLAN_POLICY(500) 之间,规则先于计划策略被读到。 */\nconst SECTION_ORDER = 400\n\n/**\n * 用户规则目录(~/.dsh/rules)。\n * @author ddj 2026年09月03号\n * @param home DSH home(缺省自动解析)\n * @returns 绝对路径\n */\nexport function userRulesDir(home = dshHome()): string {\n return join(home, 'rules')\n}\n\n/**\n * 项目规则目录(<工作区>/.dsh/rules)。\n * @author ddj 2026年09月03号\n * @param workspacePath 工作区绝对路径\n * @returns 绝对路径\n */\nexport function projectRulesDir(workspacePath: string): string {\n return join(workspacePath, '.dsh', 'rules')\n}\n// --endregion\n\n// --region frontmatter 解析(纯函数)\n/** parseRuleMdc 的产出:frontmatter 字段 + 正文 + 可选解析错误。 */\nexport interface ParsedRule {\n description: string\n alwaysApply: boolean\n globs: string[]\n enabled: boolean\n body: string\n error?: string\n}\n\n/**\n * 去除值两侧成对引号。\n * @author ddj 2026年09月03号\n * @param raw 原始值\n * @returns 去引号后的值\n */\nfunction stripQuotes(raw: string): string {\n const value = raw.trim()\n if (value.length >= 2 && ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\")))) {\n return value.slice(1, -1)\n }\n return value\n}\n\n/**\n * 解析 globs 值:内联逗号分隔串,或空值后接 YAML 短横列表。\n * @author ddj 2026年09月03号\n * @param value 内联值(可为空)\n * @param listLines 后续短横列表行内容(去掉 `- ` 前缀)\n * @returns glob 数组\n */\nfunction parseGlobs(value: string, listLines: string[]): string[] {\n const inline = stripQuotes(value)\n const items = inline ? inline.split(',') : listLines\n return items.map((item) => stripQuotes(item)).filter(Boolean)\n}\n\n/**\n * 容错解析一条 .mdc 规则:首行 `---` 且 100 行内有闭合 `---` 才视为 frontmatter,\n * 否则整个文本当正文(类型 manual、enabled=true)。解析永不抛错。\n * @author ddj 2026年09月03号\n * @param text 文件全文\n * @returns 解析结果\n */\nexport function parseRuleMdc(text: string): ParsedRule {\n const lines = text.replace(/^\\uFEFF/, '').split(/\\r?\\n/)\n if (lines[0]?.trim() !== '---') return { description: '', alwaysApply: false, globs: [], enabled: true, body: text }\n let close = -1\n for (let i = 1; i < lines.length && i <= 101; i++) {\n if (lines[i].trim() === '---') { close = i; break }\n }\n if (close < 0) return { description: '', alwaysApply: false, globs: [], enabled: true, body: text }\n const result: ParsedRule = { description: '', alwaysApply: false, globs: [], enabled: true, body: lines.slice(close + 1).join('\\n') }\n for (let i = 1; i < close; i++) {\n const match = /^([A-Za-z_-]+)[ \\t]*:[ \\t]?(.*)$/.exec(lines[i])\n if (!match) continue\n const [, key, raw] = match\n if (key === 'description') result.description = stripQuotes(raw)\n else if (key === 'alwaysApply') result.alwaysApply = stripQuotes(raw).toLowerCase() === 'true'\n else if (key === 'enabled') result.enabled = stripQuotes(raw).toLowerCase() !== 'false'\n else if (key === 'globs') {\n const listLines: string[] = []\n for (let j = i + 1; j < close; j++) {\n const item = /^[ \\t]*-[ \\t]*(.+)$/.exec(lines[j])\n if (!item) break\n listLines.push(item[1])\n }\n result.globs = parseGlobs(raw, listLines)\n }\n }\n return result\n}\n\n/**\n * 由 frontmatter 推导规则类型:总是 / 自动(有 globs)/ 手动。\n * @author ddj 2026年09月03号\n * @param parsed 解析结果\n * @returns 规则类型\n */\nexport function ruleTypeOf(parsed: ParsedRule): 'always' | 'auto' | 'manual' {\n if (parsed.alwaysApply) return 'always'\n if (parsed.globs.length) return 'auto'\n return 'manual'\n}\n// --endregion\n\n// --region 文件名与开关改写(纯函数)\n/**\n * 校验规则文件名(白名单 + Windows 保留名拒绝)。\n * @author ddj 2026年09月03号\n * @param name 文件名(含后缀)\n * @returns 错误文案;null=合法\n */\nexport function validateRuleFile(name: string): string | null {\n if (!RULE_FILE_RE.test(name)) return '文件名不合法:仅允许字母数字开头,含字母/数字/点/横线/下划线,.mdc 后缀'\n if (RESERVED_NAME_RE.test(name)) return '文件名是 Windows 保留设备名,不允许'\n return null\n}\n\n/**\n * 只改写 frontmatter 的 enabled 行(保留 BOM、CRLF 与其余内容不动);无规则 frontmatter 返回 null。\n * @author ddj 2026年09月03号\n * @param text 文件全文\n * @param enabled 目标开关状态\n * @returns 改写后的全文;null=无法安全改写\n */\nexport function toggleEnabledLine(text: string, enabled: boolean): string | null {\n const hasBom = text.startsWith('\\uFEFF')\n const rest = hasBom ? text.slice(1) : text\n const eol = rest.includes('\\r\\n') ? '\\r\\n' : '\\n'\n const lines = rest.split(/\\r?\\n/)\n if (lines[0]?.trim() !== '---') return null\n let close = -1\n for (let i = 1; i < lines.length && i <= 101; i++) {\n if (lines[i].trim() === '---') { close = i; break }\n }\n if (close < 0) return null\n const line = 'enabled: ' + (enabled ? 'true' : 'false')\n let replaced = false\n for (let i = 1; i < close; i++) {\n if (/^[ \\t]*enabled[ \\t]*:/.test(lines[i])) { lines[i] = line; replaced = true; break }\n }\n if (!replaced) lines.splice(1, 0, line)\n return (hasBom ? '\\uFEFF' : '') + lines.join(eol)\n}\n// --endregion\n\n// --region 注入渲染(纯函数)\n/** 一条已加载规则:元信息 + 正文(注入渲染输入)。 */\nexport interface LoadedRule {\n info: RuleInfo\n body: string\n}\n\n/**\n * 渲染单条规则块:标题 + 描述 + 截断后的正文;auto 类型追加 glob 条件说明。\n * @author ddj 2026年09月03号\n * @param rule 已加载规则\n * @returns 文本块(含尾空行)\n */\nfunction ruleBlock(rule: LoadedRule): string {\n let body = rule.body\n if (body.length > RULE_SINGLE_CAP) body = body.slice(0, RULE_SINGLE_CAP) + '\\n…(规则正文超长已截断)'\n const condition = rule.info.type === 'auto' && rule.info.globs.length\n ? '(当处理匹配 ' + rule.info.globs.join(', ') + ' 的文件时应用)'\n : ''\n const desc = rule.info.description ? '\\n' + rule.info.description : ''\n return '#### ' + rule.info.file + condition + desc + '\\n' + body + '\\n'\n}\n\n/**\n * 渲染一个作用域(用户/项目)的注入段:总是全文 / 自动带条件 / 手动仅索引行。\n * @author ddj 2026年09月03号\n * @param title 段标题\n * @param rules 已加载规则\n * @returns 段文本;无启用规则时返回空串\n */\nfunction renderScope(title: string, rules: LoadedRule[]): string {\n const enabled = rules.filter((rule) => rule.info.enabled && !rule.info.error)\n const always = enabled.filter((rule) => rule.info.type === 'always')\n const auto = enabled.filter((rule) => rule.info.type === 'auto')\n const manual = enabled.filter((rule) => rule.info.type === 'manual')\n if (!always.length && !auto.length && !manual.length) return ''\n const out: string[] = ['## ' + title, '']\n let budget = RULE_SCOPE_CAP\n let omitted = false\n const push = (block: string): void => {\n if (block.length > budget) { omitted = true; return }\n budget -= block.length\n out.push(block)\n }\n if (always.length) {\n out.push('### 总是生效', '')\n for (const rule of always) push(ruleBlock(rule))\n }\n if (auto.length) {\n out.push('### 按文件匹配生效', '')\n for (const rule of auto) push(ruleBlock(rule))\n }\n if (manual.length) {\n out.push('### 可按需读取(未自动生效;需要时读取对应文件)', '')\n for (const rule of manual) {\n const desc = rule.info.description ? ' — ' + rule.info.description : ''\n push('- ' + rule.info.file + desc + '(路径: ' + rule.info.absPath + ')\\n')\n }\n }\n if (omitted) out.push('', '(部分规则因总长度预算被省略,请精简规则文件)')\n return out.join('\\n') + '\\n'\n}\n\n/**\n * 渲染规则注入 section 全文:用户规则段 + 项目规则段;两者皆空返回空串(空 section 无害)。\n * @author ddj 2026年09月03号\n * @param user 用户规则\n * @param project 当前工作区项目规则\n * @param workspacePath 项目段标注的工作区路径(缺省跳过项目段)\n * @returns 注入文本\n */\nexport function renderRulesSection(user: LoadedRule[], project: LoadedRule[], workspacePath?: string): string {\n const userText = renderScope('用户规则(用户配置,必须遵守)', user)\n const projectText = workspacePath ? renderScope('项目规则(工作区 ' + workspacePath + ',必须遵守)', project) : ''\n return [userText, projectText].filter(Boolean).join('\\n')\n}\n// --endregion\n\n// --region IO(列表 / 读 / 存 / 删 / 开关)\n/** 单目录规则元信息列表(仅 *.mdc,最多 RULE_DIR_CAP 个;目录缺失返回空)。 */\nasync function listRulesDir(dir: string, scope: RuleScope): Promise<RuleInfo[]> {\n const names = await readdir(dir).catch(() => [] as string[])\n const mdcs = names.filter((name) => name.endsWith('.mdc')).sort().slice(0, RULE_DIR_CAP)\n const out: RuleInfo[] = []\n for (const file of mdcs) {\n const absPath = join(dir, file)\n const info = await stat(absPath).catch(() => null)\n if (!info || !info.isFile()) continue\n const parsed = parseRuleMdc(await readFile(absPath, 'utf8').catch(() => ''))\n out.push(toRuleInfo(scope, file, absPath, parsed, info.size, info.mtimeMs))\n }\n return out\n}\n\n/** 已注册 workspace 列表(项目 Tab 与写入校验共用)。 */\nfunction workspaceList(ctx: Ctx): Array<{ path: string; title?: string }> {\n const list = ctx.get('workspaceRegistry')?.list?.() ?? []\n return (list as Array<{ path?: string; title?: string }>).filter(\n (item): item is { path: string; title?: string } => Boolean(item) && typeof item.path === 'string' && item.path !== '',\n )\n}\n\n/** 用户显式 GUI 写操作的策略:danger-full-access(照抄 mcpProject.fullPolicy)。 */\nfunction fullPolicy(ctx: Ctx): unknown {\n const svc = ctx.get('sandboxPolicy')\n if (!svc || typeof svc.resolve !== 'function') return undefined\n return svc.resolve({ mode: 'danger-full-access' })\n}\n\n/** 校验项目作用域的 workspacePath 已注册为 DSH workspace(防 RPC 写任意目录)。 */\nfunction requireWorkspace(ctx: Ctx, workspacePath: string | undefined): { path: string; title?: string } {\n const workspace = workspaceList(ctx).find((item) => item.path === workspacePath)\n if (!workspace) throw new Error('项目未注册为 DSH workspace,不能管理项目规则')\n return workspace as { path: string; title?: string }\n}\n\n/** 按作用域解析规则目录(project 先过 requireWorkspace)。 */\nfunction dirOf(ctx: Ctx, scope: RuleScope, workspacePath?: string): string {\n if (scope === 'project') return projectRulesDir(requireWorkspace(ctx, workspacePath).path)\n return userRulesDir()\n}\n\n/**\n * 规则总列表:用户规则 + 各已注册工作区的项目规则。\n * @author ddj 2026年09月03号\n * @param ctx DSH 上下文\n * @returns rules.list 载荷\n */\nexport async function rulesList(ctx: Ctx): Promise<{ user: RuleInfo[]; projects: RuleProject[] }> {\n const user = await listRulesDir(userRulesDir(), 'user')\n const projects: RuleProject[] = []\n for (const workspace of workspaceList(ctx)) {\n const dir = projectRulesDir(workspace.path)\n const exists = existsSync(dir)\n const rules = exists ? await listRulesDir(dir, 'project') : []\n projects.push({ workspacePath: workspace.path, title: workspace.title ?? '', rules, missingDir: exists ? undefined : true })\n }\n return { user, projects }\n}\n\n/**\n * 读取一条规则全文(编辑器回填用)。\n * @author ddj 2026年09月03号\n * @param ctx DSH 上下文\n * @param ref 作用域 + 文件名(+ 项目工作区)\n * @returns 文件全文\n */\nexport async function rulesRead(ctx: Ctx, ref: RuleRefInput): Promise<string> {\n const dir = dirOf(ctx, ref.scope, ref.workspacePath)\n return readFile(join(dir, ref.file), 'utf8')\n}\n\n/**\n * 组装规则元信息视图(rulesSave / rulesToggle / 注入缓存共用)。\n * @author ddj 2026年09月03号\n * @param scope 作用域\n * @param file 文件名\n * @param absPath 绝对路径\n * @param parsed 解析结果\n * @param size 字节数\n * @param mtime 修改时间毫秒\n * @returns 规则元信息\n */\nfunction toRuleInfo(scope: RuleScope, file: string, absPath: string, parsed: ParsedRule, size: number, mtime: number): RuleInfo {\n return {\n scope, file, absPath,\n relHint: scope === 'project' ? '.dsh/rules/' : 'rules/',\n description: parsed.description, type: ruleTypeOf(parsed), globs: parsed.globs, enabled: parsed.enabled,\n size, mtime, error: parsed.error,\n }\n}\n\n/**\n * 保存(新建或覆盖)一条规则:project 作用域写盘走 ctx fs + danger-full-access(镜像 mcpProject)。\n * @author ddj 2026年09月03号\n * @param ctx DSH 上下文\n * @param input 保存入参\n * @returns 保存后的规则元信息\n */\nexport async function rulesSave(ctx: Ctx, input: RuleSaveInput): Promise<RuleInfo> {\n const invalid = validateRuleFile(input.file)\n if (invalid) throw new Error(invalid)\n const dir = dirOf(ctx, input.scope, input.workspacePath)\n await mkdir(dir, { recursive: true })\n const absPath = join(dir, input.file)\n const content = String(input.content ?? '')\n if (input.scope === 'project') {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve('.dsh/rules/' + input.file, { cwd: requireWorkspace(ctx, input.workspacePath).path })\n await fs.writeText(target, content, void 0, void 0, fullPolicy(ctx))\n } else {\n await writeFile(absPath, content, 'utf8')\n }\n const info = await stat(absPath).catch(() => null)\n return toRuleInfo(input.scope, input.file, absPath, parseRuleMdc(content), info?.size ?? Buffer.byteLength(content), info?.mtimeMs ?? Date.now())\n}\n\n/**\n * 删除一条规则文件(project 作用域同样先过 workspace 注册校验)。\n * @author ddj 2026年09月03号\n * @param ref 作用域 + 文件名(+ 项目工作区)\n */\nexport async function rulesRemove(ctx: Ctx, ref: RuleRefInput): Promise<void> {\n const dir = dirOf(ctx, ref.scope, ref.workspacePath)\n await rm(join(dir, ref.file), { force: true })\n}\n\n/**\n * 切换规则启用开关:只改写 frontmatter enabled 行,其余内容零改动。\n * @author ddj 2026年09月03号\n * @param ref 作用域 + 文件名(+ 项目工作区)\n * @param enabled 目标状态\n * @returns 更新后的规则元信息\n */\nexport async function rulesToggle(ctx: Ctx, ref: RuleRefInput, enabled: boolean): Promise<RuleInfo> {\n const dir = dirOf(ctx, ref.scope, ref.workspacePath)\n const absPath = join(dir, ref.file)\n const text = await readRuleText(ctx, ref, absPath)\n if (text === null) throw new Error('规则文件不存在:' + ref.file)\n const next = toggleEnabledLine(text, enabled)\n if (next === null) throw new Error('规则缺少 frontmatter(首行需为 ---),无法记录开关状态')\n if (next !== text) await rulesSaveContent(ctx, ref, absPath, next)\n return await ruleInfoOf(ref, absPath, next)\n}\n\n/** 按作用域读规则全文:project 与写盘同通道走 ctx fs,user 走 node fs;缺失返回 null。 */\nasync function readRuleText(ctx: Ctx, ref: RuleRefInput, absPath: string): Promise<string | null> {\n if (ref.scope !== 'project') return readFile(absPath, 'utf8').catch(() => null)\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve('.dsh/rules/' + ref.file, { cwd: requireWorkspace(ctx, ref.workspacePath).path })\n try {\n return await fs.readText(target)\n } catch {\n return null\n }\n}\n\n/** rulesToggle 的写盘通道:与 rulesSave 相同(project 走 ctx fs + fullPolicy,user 走 node fs)。 */\nasync function rulesSaveContent(ctx: Ctx, ref: RuleRefInput, absPath: string, content: string): Promise<void> {\n if (ref.scope !== 'project') {\n await writeFile(absPath, content, 'utf8')\n return\n }\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve('.dsh/rules/' + ref.file, { cwd: requireWorkspace(ctx, ref.workspacePath).path })\n await fs.writeText(target, content, void 0, void 0, fullPolicy(ctx))\n}\n\n/** 重建单条规则元信息(toggle 后回传 UI;stat 失败时用内容长度 + 当前时间兜底)。 */\nasync function ruleInfoOf(ref: RuleRefInput, absPath: string, content: string): Promise<RuleInfo> {\n const info = await stat(absPath).catch(() => null)\n return toRuleInfo(ref.scope, ref.file, absPath, parseRuleMdc(content), info?.size ?? Buffer.byteLength(content), info?.mtimeMs ?? Date.now())\n}\n// --endregion\n\n// --region systemPrompt 装配(注入生效通道)\n/** 注入读取的 mtime 缓存项:mtimeMs+size 命中即复用解析结果,避免每次装配读盘解析。 */\ninterface InjCacheEntry {\n mtimeMs: number\n size: number\n parsed: ParsedRule\n}\nconst injCache = new Map<string, InjCacheEntry>()\n\n/**\n * 同步读取一个规则目录(装配 provider 内专用):仅 *.mdc,mtime 缓存,异常静默为空。\n * @author ddj 2026年09月03号\n * @param dir 规则目录\n * @param scope 作用域\n * @param relHint 相对提示\n * @returns 已加载规则列表\n */\nfunction readRulesSync(dir: string, scope: RuleScope): LoadedRule[] {\n if (!existsSync(dir)) return []\n let names: string[]\n try {\n names = readdirSync(dir)\n } catch {\n return []\n }\n const out: LoadedRule[] = []\n for (const file of names.filter((name) => name.endsWith('.mdc')).sort().slice(0, RULE_DIR_CAP)) {\n const absPath = join(dir, file)\n let info: { mtimeMs: number; size: number; isFile(): boolean }\n try {\n info = statSync(absPath)\n } catch {\n continue\n }\n if (!info.isFile()) continue\n const cached = injCache.get(absPath)\n let parsed: ParsedRule\n if (cached && cached.mtimeMs === info.mtimeMs && cached.size === info.size) {\n parsed = cached.parsed\n } else {\n try {\n parsed = parseRuleMdc(readFileSync(absPath, 'utf8'))\n } catch {\n continue\n }\n injCache.set(absPath, { mtimeMs: info.mtimeMs, size: info.size, parsed })\n }\n out.push({\n info: toRuleInfo(scope, file, absPath, parsed, info.size, info.mtimeMs),\n body: parsed.body,\n })\n }\n return out\n}\n\n/** 从装配上下文解析会话工作区 cwd(agent.id → sessions → header.cwd;缺链返回 null)。 */\nfunction cwdFromAssemble(ctx: Ctx, asm: { agent?: { id?: unknown } } | undefined): string | null {\n const id = asm?.agent?.id\n if (typeof id !== 'string' || !id) return null\n const session = ctx.get('sessions')?.get?.(id)\n const cwd = session?.header?.cwd\n return typeof cwd === 'string' && cwd ? cwd : null\n}\n\n/**\n * 安装规则注入 section(可选探测 systemPrompt 服务;失败/缺失返回 false,不致命)。\n * @author ddj 2026年09月03号\n * @param ctx DSH host 上下文\n * @returns 是否成功注册\n */\nexport function installRulesSection(ctx: Ctx): boolean {\n const sp = ctx.get('systemPrompt')\n if (!sp || typeof sp.section !== 'function') return false\n const provider = (asm: { agent?: { id?: unknown } }): string => {\n try {\n const user = readRulesSync(userRulesDir(), 'user')\n const cwd = cwdFromAssemble(ctx, asm)\n const project = cwd ? readRulesSync(projectRulesDir(cwd), 'project') : []\n return renderRulesSection(user, project, cwd ?? undefined)\n } catch {\n return ''\n }\n }\n ctx.effect(() => sp.section({ name: SECTION_NAME, order: SECTION_ORDER, text: provider }), 'vscode-mode: rules section')\n return true\n}\n// --endregion\n","/**\n * dsh-vscode-mode host — 代码片段管理(VS Code 兼容 .code-snippets 文件)。\n * - 存储:全局片段 ~/.dsh/snippets/*.code-snippets;项目片段 <工作区>/.dsh/snippets/*.code-snippets\n * (随仓库共享)。文件名约定与 VS Code 一致:`<language>.code-snippets`(`global.code-snippets`\n * 表示全语言生效)。\n * - 格式:顶层对象 { \"<片段名>\": { prefix, body, description?, scope? } };body 支持字符串或\n * 字符串数组(数组按行拼接)。解析容错:单文件 JSON 损坏只影响该文件(error 字段提示)。\n * - 生效:client 侧 Monaco completion provider 按 model 语言拉取 snippetsEntries 后过滤展开;\n * 与 rules.ts 同一套 IO 通道(user 走 node fs;project 走 ctx fs + danger-full-access)。\n * --region 划分:常量与目录定位 / JSON 解析(纯)/ 条目展开(纯)/ 文件名与模板(纯)/ IO\n * 作者 ddj 2026年09月10号\n */\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises'\nimport { Buffer } from 'node:buffer'\nimport { join } from 'node:path'\nimport { dshHome } from './paths.js'\nimport type {\n SnippetEntry,\n SnippetInfo,\n SnippetProject,\n SnippetRefInput,\n SnippetSaveInput,\n SnippetScope,\n} from './shared/snippets.js'\nimport type { Ctx } from './store.js'\n\n/** 文件名与模板的纯函数定义在 shared(host 与 client 共用,避免两处漂移),此处透传便于 host 调用方单点导入。 */\nexport { normalizeSnippetFileName, snippetFileTemplate } from './shared/snippets.js'\n\n// --region 常量与目录定位\n/** 片段文件名白名单:字母数字开头,仅字母数字点横下划线,.code-snippets 后缀(天然拒绝路径分隔符)。 */\nexport const SNIPPET_FILE_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*\\.code-snippets$/\n/** Windows 保留设备名(防意外创建系统设备文件)。 */\nconst RESERVED_NAME_RE = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\\..*)?$/i\n/** 单目录最多加载的片段文件数(防失控目录拖垮装配)。 */\nconst SNIPPET_DIR_CAP = 200\n/** 单条片段正文字节上限(超出截断,防超长片段撑爆补全载荷)。 */\nconst SNIPPET_SINGLE_CAP = 16 * 1024\n\n/**\n * 全局片段目录(~/.dsh/snippets)。\n * @author ddj 2026年09月10号\n * @param home DSH home(缺省自动解析)\n * @returns 绝对路径\n */\nexport function userSnippetsDir(home = dshHome()): string {\n return join(home, 'snippets')\n}\n\n/**\n * 项目片段目录(<工作区>/.dsh/snippets)。\n * @author ddj 2026年09月10号\n * @param workspacePath 工作区绝对路径\n * @returns 绝对路径\n */\nexport function projectSnippetsDir(workspacePath: string): string {\n return join(workspacePath, '.dsh', 'snippets')\n}\n\n/**\n * 判定绝对路径是否落在全局片段目录内(edrv.read / edrv.save 的片段分支依据)。\n * 归一化分隔符后按前缀比较;不在目录内返回 false。\n * @author ddj 2026年09月10号\n * @param path 待判定路径\n * @param home DSH home(缺省自动解析)\n * @returns 是否为全局片段文件\n */\nexport function isSnippetFilePath(path: string, home = dshHome()): boolean {\n const raw = String(path ?? '')\n if (!raw) return false\n return resolveSnippetPath(raw, userSnippetsDir(home)) !== null\n}\n\n/**\n * 归一化并校验「路径是否位于 dir 直下」(拒绝 `..` 穿越与子目录)。\n * @author ddj 2026年09月10号\n * @param path 待判定路径\n * @param dir 目标目录\n * @returns 命中时返回归一化后的绝对路径(`/` 分隔);否则 null\n */\nfunction resolveSnippetPath(path: string, dir: string): string | null {\n const norm = (text: string): string => String(text).replace(/\\\\/g, '/').replace(/\\/+$/, '')\n const target = norm(path)\n const base = norm(dir)\n if (!target.startsWith(base + '/')) return null\n const rest = target.slice(base.length + 1)\n // 仅允许目录直下的单层文件名(防子目录与穿越)\n if (!rest || rest.includes('/')) return null\n return SNIPPET_FILE_RE.test(rest) ? target : null\n}\n// --endregion\n\n// --region JSON 解析(纯函数)\n/** 一条片段的原始 JSON 声明(宽容:字段可能缺失或类型不符)。 */\ninterface RawSnippet {\n prefix?: unknown\n body?: unknown\n description?: unknown\n scope?: unknown\n}\n\n/** parseSnippetsJson 的产出:条目映射 + 可选解析错误。 */\nexport interface ParsedSnippets {\n entries: Record<string, ParsedEntry>\n error?: string\n}\n\n/** 已解析的单条片段(正文已归一为字符串)。 */\nexport interface ParsedEntry {\n prefix: string\n body: string\n description: string\n scope: string[]\n}\n\n/**\n * 归一化片段正文:字符串原样;字符串数组按行拼接(VS Code 语义)。\n * @author ddj 2026年09月10号\n * @param raw body 原始值\n * @returns 正文文本;非法类型返回空串\n */\nexport function normalizeBody(raw: unknown): string {\n if (typeof raw === 'string') return raw\n if (Array.isArray(raw)) return raw.filter((line) => typeof line === 'string').join('\\n')\n return ''\n}\n\n/**\n * 归一化片段前缀:字符串去空白;字符串数组取首项;其余为空串。\n * @author ddj 2026年09月10号\n * @param raw prefix 原始值\n * @returns 前缀文本\n */\nexport function normalizePrefix(raw: unknown): string {\n if (typeof raw === 'string') return raw.trim()\n if (Array.isArray(raw)) {\n const first = raw.find((item) => typeof item === 'string')\n return typeof first === 'string' ? first.trim() : ''\n }\n return ''\n}\n\n/**\n * 归一化 scope:字符串或字符串数组,去空白并小写;其余为空数组(= 全语言)。\n * @author ddj 2026年09月10号\n * @param raw scope 原始值\n * @returns 语言 id 数组\n */\nexport function normalizeScope(raw: unknown): string[] {\n const list = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : []\n return list\n .filter((item): item is string => typeof item === 'string')\n .map((item) => item.trim().toLowerCase())\n .filter(Boolean)\n}\n\n/**\n * 容错解析一个 .code-snippets 文件:顶层须为对象,逐条归一化;单条非法即跳过。\n * 解析永不抛错(失败以 error 文案返回)。\n * @author ddj 2026年09月10号\n * @param text 文件全文\n * @returns 解析结果(entries 为片段名 → 已解析条目)\n */\nexport function parseSnippetsJson(text: string): ParsedSnippets {\n const trimmed = String(text ?? '').replace(/^\\uFEFF/, '').trim()\n if (!trimmed) return { entries: {} }\n let data: unknown\n try {\n data = JSON.parse(trimmed)\n } catch (error) {\n return { entries: {}, error: 'JSON 解析失败:' + String(error) }\n }\n if (!data || typeof data !== 'object' || Array.isArray(data)) {\n return { entries: {}, error: '顶层必须是对象({ \"片段名\": { prefix, body } })' }\n }\n const entries: Record<string, ParsedEntry> = {}\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (!value || typeof value !== 'object' || Array.isArray(value)) continue\n const raw = value as RawSnippet\n const body = normalizeBody(raw.body)\n if (!body) continue // body 缺失/非法:该条静默跳过(不污染整体)\n entries[key] = {\n prefix: normalizePrefix(raw.prefix),\n body: body.length > SNIPPET_SINGLE_CAP ? body.slice(0, SNIPPET_SINGLE_CAP) : body,\n description: typeof raw.description === 'string' ? raw.description : '',\n scope: normalizeScope(raw.scope),\n }\n }\n return { entries }\n}\n// --endregion\n\n// --region 条目展开(纯函数)\n/**\n * 由文件名推导语言 id:`<language>.code-snippets` → language;`global`/无法识别返回空串。\n * @author ddj 2026年09月10号\n * @param file 片段文件名(含后缀)\n * @returns 语言 id(空串 = 全语言)\n */\nexport function languageOfSnippetFile(file: string): string {\n const base = String(file ?? '').replace(/\\.code-snippets$/i, '')\n if (!base || base.toLowerCase() === 'global') return ''\n return base.toLowerCase()\n}\n\n/**\n * 把「一个文件的解析结果」展开为补全条目:文件语言与条目 scope 取交集。\n * 条目 scope 为空 → 跟随文件语言;文件语言为空(global)→ 该条目对全语言生效。\n * @author ddj 2026年09月10号\n * @param info 文件元信息\n * @param parsed 解析结果\n * @returns 条目数组(含来源信息)\n */\nexport function entriesOfFile(info: SnippetInfo, parsed: ParsedSnippets): SnippetEntry[] {\n const fileLanguage = info.language\n const out: SnippetEntry[] = []\n for (const [key, entry] of Object.entries(parsed.entries)) {\n // 条目 scope 覆盖文件语言:有 scope 时按 scope,无 scope 时继承文件语言(空=全语言)\n const languages = entry.scope.length ? entry.scope : [fileLanguage]\n for (const language of languages) {\n out.push({\n key,\n prefix: entry.prefix,\n body: entry.body,\n description: entry.description,\n scope: info.scope,\n file: info.file,\n language,\n })\n }\n }\n return out\n}\n\n/**\n * 展开全部文件的条目(补全 provider 载荷)。\n * @author ddj 2026年09月10号\n * @param loaded 已加载的文件(元信息 + 解析结果)\n * @returns 条目数组(项目文件靠后,同 key 时项目覆盖全局)\n */\nexport function flattenSnippetEntries(loaded: Array<{ info: SnippetInfo; parsed: ParsedSnippets }>): SnippetEntry[] {\n const out: SnippetEntry[] = []\n for (const item of loaded) out.push(...entriesOfFile(item.info, item.parsed))\n return out\n}\n// --endregion\n\n// --region 文件名与模板(纯函数)\n/**\n * 校验片段文件名(白名单 + Windows 保留名拒绝)。\n * @author ddj 2026年09月10号\n * @param name 文件名(含后缀)\n * @returns 错误文案;null=合法\n */\nexport function validateSnippetFile(name: string): string | null {\n if (!SNIPPET_FILE_RE.test(name)) return '文件名不合法:仅允许字母数字开头,含字母/数字/点/横线/下划线,.code-snippets 后缀'\n if (RESERVED_NAME_RE.test(name)) return '文件名是 Windows 保留设备名,不允许'\n return null\n}\n// --endregion\n\n// --region IO(列表 / 读 / 存 / 删 / 条目)\n/**\n * 组装片段文件元信息视图(列表与补全载荷共用)。\n * @author ddj 2026年09月10号\n * @param scope 作用域\n * @param file 文件名\n * @param absPath 绝对路径\n * @param parsed 解析结果\n * @param size 字节数\n * @param mtime 修改时间毫秒\n * @returns 片段文件元信息\n */\nfunction toSnippetInfo(scope: SnippetScope, file: string, absPath: string, parsed: ParsedSnippets, size: number, mtime: number): SnippetInfo {\n return {\n scope,\n file,\n absPath,\n relHint: scope === 'project' ? '.dsh/snippets/' : 'snippets/',\n language: languageOfSnippetFile(file),\n count: Object.keys(parsed.entries).length,\n size,\n mtime,\n error: parsed.error,\n }\n}\n\n/** 单目录片段文件列表(仅 *.code-snippets,最多 SNIPPET_DIR_CAP 个;目录缺失返回空)。 */\nasync function listSnippetsDir(dir: string, scope: SnippetScope): Promise<SnippetInfo[]> {\n const names = await readdir(dir).catch(() => [] as string[])\n const files = names.filter((name) => /\\.code-snippets$/i.test(name)).sort().slice(0, SNIPPET_DIR_CAP)\n const out: SnippetInfo[] = []\n for (const file of files) {\n const absPath = join(dir, file)\n const info = await stat(absPath).catch(() => null)\n if (!info || !info.isFile()) continue\n const parsed = parseSnippetsJson(await readFile(absPath, 'utf8').catch(() => ''))\n out.push(toSnippetInfo(scope, file, absPath, parsed, info.size, info.mtimeMs))\n }\n return out\n}\n\n/** 已注册 workspace 列表(项目页与写入校验共用)。 */\nfunction workspaceList(ctx: Ctx): Array<{ path: string; title?: string }> {\n const list = ctx.get('workspaceRegistry')?.list?.() ?? []\n return (list as Array<{ path?: string; title?: string }>).filter(\n (item): item is { path: string; title?: string } => Boolean(item) && typeof item.path === 'string' && item.path !== '',\n )\n}\n\n/** 用户显式 GUI 写操作的策略:danger-full-access(照抄 rules.fullPolicy)。 */\nfunction fullPolicy(ctx: Ctx): unknown {\n const svc = ctx.get('sandboxPolicy')\n if (!svc || typeof svc.resolve !== 'function') return undefined\n return svc.resolve({ mode: 'danger-full-access' })\n}\n\n/**\n * 校验项目作用域的 workspacePath 已注册为 DSH workspace(防 RPC 写任意目录)。\n * @author ddj 2026年09月10号\n * @param ctx DSH 上下文\n * @param workspacePath 目标项目路径\n * @returns 命中的工作区项\n */\nfunction requireWorkspace(ctx: Ctx, workspacePath: string | undefined): { path: string; title?: string } {\n const workspace = workspaceList(ctx).find((item) => item.path === workspacePath)\n if (!workspace) throw new Error('项目未注册为 DSH workspace,不能管理项目片段')\n return workspace as { path: string; title?: string }\n}\n\n/** 按作用域解析片段目录(project 先过 requireWorkspace)。 */\nfunction dirOf(ctx: Ctx, scope: SnippetScope, workspacePath?: string): string {\n if (scope === 'project') return projectSnippetsDir(requireWorkspace(ctx, workspacePath).path)\n return userSnippetsDir()\n}\n\n/**\n * 片段文件总列表:全局片段 + 各已注册工作区的项目片段。\n * @author ddj 2026年09月10号\n * @param ctx DSH 上下文\n * @returns snippets.list 载荷\n */\nexport async function snippetsList(ctx: Ctx): Promise<{ user: SnippetInfo[]; projects: SnippetProject[] }> {\n const user = await listSnippetsDir(userSnippetsDir(), 'user')\n const projects: SnippetProject[] = []\n for (const workspace of workspaceList(ctx)) {\n const dir = projectSnippetsDir(workspace.path)\n const exists = existsSync(dir)\n const files = exists ? await listSnippetsDir(dir, 'project') : []\n projects.push({ workspacePath: workspace.path, title: workspace.title ?? '', files, missingDir: exists ? undefined : true })\n }\n return { user, projects }\n}\n\n/**\n * 读取一个片段文件全文(编辑界面打开用)。\n * @author ddj 2026年09月10号\n * @param ctx DSH 上下文\n * @param ref 作用域 + 文件名(+ 项目工作区)\n * @returns 文件全文\n */\nexport async function snippetsRead(ctx: Ctx, ref: SnippetRefInput): Promise<string> {\n const dir = dirOf(ctx, ref.scope, ref.workspacePath)\n return readFile(join(dir, ref.file), 'utf8')\n}\n\n/**\n * 保存(新建或覆盖)一个片段文件:project 作用域写盘走 ctx fs + danger-full-access(镜像 rules)。\n * @author ddj 2026年09月10号\n * @param ctx DSH 上下文\n * @param input 保存入参\n * @returns 保存后的片段文件元信息\n */\nexport async function snippetsSave(ctx: Ctx, input: SnippetSaveInput): Promise<SnippetInfo> {\n const invalid = validateSnippetFile(input.file)\n if (invalid) throw new Error(invalid)\n const dir = dirOf(ctx, input.scope, input.workspacePath)\n await mkdir(dir, { recursive: true })\n const absPath = join(dir, input.file)\n const content = String(input.content ?? '')\n if (input.scope === 'project') {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve('.dsh/snippets/' + input.file, { cwd: requireWorkspace(ctx, input.workspacePath).path })\n await fs.writeText(target, content, void 0, void 0, fullPolicy(ctx))\n } else {\n await writeFile(absPath, content, 'utf8')\n }\n const info = await stat(absPath).catch(() => null)\n return toSnippetInfo(input.scope, input.file, absPath, parseSnippetsJson(content), info?.size ?? Buffer.byteLength(content), info?.mtimeMs ?? Date.now())\n}\n\n/**\n * 删除一个片段文件(project 作用域同样先过 workspace 注册校验)。\n * @author ddj 2026年09月10号\n * @param ctx DSH 上下文\n * @param ref 作用域 + 文件名(+ 项目工作区)\n */\nexport async function snippetsRemove(ctx: Ctx, ref: SnippetRefInput): Promise<void> {\n const dir = dirOf(ctx, ref.scope, ref.workspacePath)\n await rm(join(dir, ref.file), { force: true })\n}\n\n/**\n * 补全 provider 载荷:全局片段 + 指定工作区项目片段的全部条目。\n * 项目条目排在全局之后(同 key 时后出现的项目条目在 client 侧优先)。\n * @author ddj 2026年09月10号\n * @param ctx DSH 上下文\n * @param workspacePath 当前会话工作区(可选;未注册则仅全局片段)\n * @returns snippets.entries 载荷\n */\nexport async function snippetsEntries(ctx: Ctx, workspacePath?: string): Promise<{ entries: SnippetEntry[] }> {\n const loaded: Array<{ info: SnippetInfo; parsed: ParsedSnippets }> = []\n const load = async (dir: string, scope: SnippetScope): Promise<void> => {\n for (const info of await listSnippetsDir(dir, scope)) {\n const parsed = parseSnippetsJson(await readFile(info.absPath, 'utf8').catch(() => ''))\n if (parsed.error) continue // 损坏文件不影响其他片段\n loaded.push({ info, parsed })\n }\n }\n await load(userSnippetsDir(), 'user')\n const registered = workspaceList(ctx).some((item) => item.path === workspacePath)\n if (workspacePath && registered) await load(projectSnippetsDir(workspacePath), 'project')\n return { entries: flattenSnippetEntries(loaded) }\n}\n// --endregion\n","/**\n * dsh-vscode-mode host — 项目级 MCP 管理。\n * 配置以项目根目录 .mcp.json(mcpServers 格式,对齐 Claude Code/Cursor)存储;\n * 工具经 loader 动态激活(entry id 带 PROJECT_ENTRY_PREFIX,全局生效)。\n * 重启后由本项目从各 .mcp.json 恢复激活;.mcp.json 为持久真相,reconcile 以文件为准。\n * 作者 ddj 2026年08月22号\n */\nimport { createHash } from 'node:crypto'\nimport { PROJECT_ENTRY_PREFIX, entriesOf, serverOf, validateConfig } from './mcp.js'\nimport type { MpcConfig, MpcProject, MpcServer } from './shared/mcp.js'\nimport type { Ctx } from './store.js'\n\nconst FILE_NAME = '.mcp.json'\n\n/** 校验项目路径属于 DSH 已注册 workspace,避免 RPC 写入任意目录。 */\nfunction requireWorkspace(ctx: Ctx, workspacePath: string): { path: string; title?: string } {\n const workspace = (ctx.get('workspaceRegistry')?.list?.() ?? []).find((item: { path: string }) => item.path === workspacePath)\n if (!workspace) throw new Error('项目未注册为 DSH workspace,不能管理项目 MCP')\n return workspace\n}\n\n/** 用户显式 GUI 管理操作的写策略:danger-full-access(写入路径固定为 workspacePath/.mcp.json)。 */\nfunction fullPolicy(ctx: Ctx): unknown {\n const svc = ctx.get('sandboxPolicy')\n if (!svc || typeof svc.resolve !== 'function') return undefined\n return svc.resolve({ mode: 'danger-full-access' })\n}\n\n/** workspace 路径 → 确定性短哈希(entry id 归属段,重启后稳定可解码)。 */\nexport function hashWorkspace(path: string): string {\n return createHash('sha1').update(path).digest('hex').slice(0, 10)\n}\n\n/** 项目 MCP 的 loader entry id:vsm-mcp.<pathHash>.<serverName>(loader id 不能用冒号)。 */\nexport function projectEntryId(workspacePath: string, serverName: string): string {\n return PROJECT_ENTRY_PREFIX + hashWorkspace(workspacePath) + '.' + serverName\n}\n\n/** 读取项目 .mcp.json 顶层对象(缺失 → 空;非法 → 抛错带文案)。 */\nasync function readProjectJson(ctx: Ctx, workspacePath: string): Promise<Record<string, unknown>> {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve(FILE_NAME, { cwd: workspacePath })\n let text: string\n try {\n text = await fs.readText(target)\n } catch (error) {\n return {}\n }\n let data: unknown\n try {\n data = JSON.parse(text)\n } catch (error) {\n throw new Error('.mcp.json 解析失败:' + String(error))\n }\n if (data === null || typeof data !== 'object' || Array.isArray(data)) throw new Error('.mcp.json 顶层必须是对象')\n return data as Record<string, unknown>\n}\n\n/** 读取并校验 .mcp.json 的 mcpServers 映射(纯函数,可单测)。 */\nexport function serversOf(data: Record<string, unknown>): Record<string, Record<string, unknown>> {\n const raw = data.mcpServers\n if (raw === undefined) return {}\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('.mcp.json 的 mcpServers 必须是对象')\n const out: Record<string, Record<string, unknown>> = {}\n for (const [name, value] of Object.entries(raw)) {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) continue\n out[name] = value as Record<string, unknown>\n }\n return out\n}\n\n/** 把 .mcp.json 单条 server 定义归一化为 MpcConfig(缺传输必填 → null,纯函数可单测)。 */\nexport function configFromDef(def: Record<string, unknown> | undefined, serverName: string): MpcConfig | null {\n if (!def) return null\n const transport = typeof def.url === 'string' ? 'streamable-http' : 'stdio'\n const config: MpcConfig = { serverName, transport }\n if (transport === 'stdio') {\n config.command = typeof def.command === 'string' ? def.command : ''\n config.args = Array.isArray(def.args) ? def.args.map(String) : []\n if (typeof def.cwd === 'string') config.cwd = def.cwd\n if (def.env && typeof def.env === 'object') config.env = Object.fromEntries(Object.entries(def.env as Record<string, unknown>).map(([k, v]) => [k, String(v)]))\n } else {\n config.url = def.url as string\n if (def.headers && typeof def.headers === 'object') config.headers = Object.fromEntries(Object.entries(def.headers as Record<string, unknown>).map(([k, v]) => [k, String(v)]))\n }\n if (typeof def.toolCallTimeoutMs === 'number') config.toolCallTimeoutMs = def.toolCallTimeoutMs\n return config\n}\n\n/** 写回 .mcp.json(保留顶层未知字段与其余 mcpServers,仅改目标 serverName)。 */\nasync function writeProjectJson(ctx: Ctx, workspacePath: string, data: Record<string, unknown>, mcpServers: Record<string, Record<string, unknown>>): Promise<void> {\n const fs = ctx.get('fs')\n if (!fs) throw new Error('缺少 fs 服务')\n const target = await fs.resolve(FILE_NAME, { cwd: workspacePath })\n const next = { ...data, mcpServers }\n await fs.writeText(target, JSON.stringify(next, null, 2) + '\\n', void 0, void 0, fullPolicy(ctx))\n}\n\n/** 查重:目标 serverName 是否已被其他 loader entry(全局或他项目)占用。 */\nfunction findConflict(ctx: Ctx, workspacePath: string, serverName: string): string | null {\n const ownId = projectEntryId(workspacePath, serverName)\n for (const entry of entriesOf(ctx)) {\n if (String(entry.id ?? entry.options?.id ?? '') === ownId) continue\n if (entry.options?.config?.serverName === serverName) {\n return 'serverName \"' + serverName + '\" 已被另一个 MCP 使用(全局或其他项目),请换一个名称'\n }\n }\n return null\n}\n\n/** 激活一个项目 MCP:校验 + 查重 + loader.create。 */\nexport async function activateProjectMcp(ctx: Ctx, workspacePath: string, config: MpcConfig): Promise<MpcServer> {\n validateConfig(config)\n const conflict = findConflict(ctx, workspacePath, config.serverName)\n if (conflict) throw new Error(conflict)\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const id = projectEntryId(workspacePath, config.serverName)\n const existing = entriesOf(ctx).find((entry) => String(entry.id ?? entry.options?.id ?? '') === id)\n if (existing) {\n await loader.update(existing.id, { config: { ...config } })\n return serverOf(ctx, loader.resolve(existing.id))\n }\n const created = await loader.create({ id, name: '@deepseek-ai/dsh-mcp-client', config: { ...config } })\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id ?? candidate.options?.id ?? '') === id)\n if (!entry) throw new Error('MCP 已创建但未能找到 entry(id=' + id + ')')\n return serverOf(ctx, entry)\n}\n\n/** 停用一个项目 MCP(按 entry id)。 */\nexport async function deactivateMcp(ctx: Ctx, entryId: string): Promise<void> {\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id ?? candidate.options?.id ?? '') === entryId)\n if (!entry) return\n await loader.remove(entry.id)\n}\n\n/** 以 .mcp.json 为真相 reconcile 该项目的激活状态(幂等)。 */\nexport async function reconcileProject(ctx: Ctx, workspacePath: string): Promise<void> {\n const data = await readProjectJson(ctx, workspacePath)\n const fileServers = new Set(Object.keys(serversOf(data)))\n const prefix = PROJECT_ENTRY_PREFIX + hashWorkspace(workspacePath) + '.'\n for (const entry of entriesOf(ctx)) {\n const id = String(entry.id ?? entry.options?.id ?? '')\n if (!id.startsWith(prefix)) continue\n const serverName = id.slice(prefix.length)\n if (fileServers.has(serverName)) continue\n await deactivateMcp(ctx, id)\n }\n for (const serverName of fileServers) {\n const config = await configOfServer(ctx, workspacePath, serverName)\n if (config === null) continue\n const id = projectEntryId(workspacePath, serverName)\n if (entriesOf(ctx).some((entry) => String(entry.id ?? entry.options?.id ?? '') === id)) continue\n await activateProjectMcp(ctx, workspacePath, { ...config, serverName })\n }\n}\n\n/** 把 .mcp.json 单条 server 定义归一化为 MpcConfig(缺传输必填 → null)。 */\nasync function configOfServer(ctx: Ctx, workspacePath: string, serverName: string): Promise<MpcConfig | null> {\n const data = await readProjectJson(ctx, workspacePath)\n return configFromDef(serversOf(data)[serverName], serverName)\n}\n\n/** 单个项目的完整视图(fileData + 激活状态合并)。 */\nasync function projectOf(ctx: Ctx, workspacePath: string, title: string): Promise<MpcProject> {\n const fs = ctx.get('fs')\n if (!fs) return { workspacePath, title, servers: [], source: 'project' }\n try {\n const target = await fs.resolve(workspacePath)\n const info = await fs.stat(target)\n if (!info || info.type !== 'directory') return { workspacePath, title, servers: [], source: 'project', missingDir: true }\n } catch (error) {\n return { workspacePath, title, servers: [], source: 'project', missingDir: true }\n }\n await reconcileProject(ctx, workspacePath)\n let servers: MpcServer[] = []\n let fileError: string | undefined\n try {\n const data = await readProjectJson(ctx, workspacePath)\n const prefix = PROJECT_ENTRY_PREFIX + hashWorkspace(workspacePath) + '.'\n servers = entriesOf(ctx).filter((entry) => String(entry.id ?? entry.options?.id ?? '').startsWith(prefix)).map((entry) => serverOf(ctx, entry))\n servers.sort((a, b) => (a.serverName < b.serverName ? -1 : 1))\n } catch (error) {\n fileError = String(error)\n }\n return { workspacePath, title, servers, source: 'project', fileError }\n}\n\n/** 列出全部项目及其项目级 MCP。 */\nexport async function listProjects(ctx: Ctx): Promise<{ projects: MpcProject[] }> {\n const registry = ctx.get('workspaceRegistry')\n const workspaces = registry?.list?.() ?? []\n const projects: MpcProject[] = []\n for (const ws of workspaces) projects.push(await projectOf(ctx, ws.path, ws.title ?? ''))\n return { projects }\n}\n\n/** 保存(新增/更新)一个项目 MCP:写 .mcp.json → 激活。 */\nexport async function projectSave(ctx: Ctx, workspacePath: string, serverName: string, config: MpcConfig): Promise<MpcProject> {\n const workspace = requireWorkspace(ctx, workspacePath)\n validateConfig({ ...config, serverName })\n const conflict = findConflict(ctx, workspacePath, serverName)\n if (conflict) throw new Error(conflict)\n const data = await readProjectJson(ctx, workspacePath)\n const servers = serversOf(data)\n const next = { ...config } as unknown as Record<string, unknown>\n delete next.serverName\n delete next.transport\n delete next.disabled // disabled 由 projectToggle 管理,保存恒为启用\n servers[serverName] = next\n await writeProjectJson(ctx, workspacePath, data, servers)\n await activateProjectMcp(ctx, workspacePath, { ...config, serverName })\n return projectOf(ctx, workspacePath, workspace.title ?? '')\n}\n\n/** 删除一个项目 MCP:停用 → 从 .mcp.json 移除。 */\nexport async function projectRemove(ctx: Ctx, workspacePath: string, serverName: string): Promise<MpcProject> {\n const workspace = requireWorkspace(ctx, workspacePath)\n await deactivateMcp(ctx, projectEntryId(workspacePath, serverName))\n const data = await readProjectJson(ctx, workspacePath)\n const servers = serversOf(data)\n delete servers[serverName]\n await writeProjectJson(ctx, workspacePath, data, servers)\n return projectOf(ctx, workspacePath, workspace.title ?? '')\n}\n\n/** 切换项目 MCP 启用状态(持久化到 .mcp.json + loader.update)。 */\nexport async function projectToggle(ctx: Ctx, workspacePath: string, serverName: string, enabled: boolean): Promise<MpcProject> {\n const workspace = requireWorkspace(ctx, workspacePath)\n const data = await readProjectJson(ctx, workspacePath)\n const servers = serversOf(data)\n const def = servers[serverName]\n if (!def) throw new Error('项目中不存在该 MCP')\n if (enabled) delete def.disabled\n else def.disabled = true\n await writeProjectJson(ctx, workspacePath, data, servers)\n const loader = ctx.get('loader')\n if (loader) {\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id ?? candidate.options?.id ?? '') === projectEntryId(workspacePath, serverName))\n if (entry) await loader.update(entry.id, { disabled: !enabled })\n }\n return projectOf(ctx, workspacePath, workspace.title ?? '')\n}\n\n/** 刷新(重连)项目 MCP。 */\nexport async function projectRefresh(ctx: Ctx, workspacePath: string, serverName: string): Promise<MpcProject> {\n const workspace = requireWorkspace(ctx, workspacePath)\n const loader = ctx.get('loader')\n if (!loader) throw new Error('缺少 loader 服务')\n const id = projectEntryId(workspacePath, serverName)\n const entry = entriesOf(ctx).find((candidate) => String(candidate.id ?? candidate.options?.id ?? '') === id)\n if (!entry) throw new Error('该项目 MCP 未激活')\n await loader.update(entry.id, { config: { ...(entry.options?.config ?? {}) } })\n return projectOf(ctx, workspacePath, workspace.title ?? '')\n}\n","/**\n * dsh-vscode-mode host — Unity 内嵌包一键安装/更新。\n * 机制:把包源目录 unity/com.dsh.editor 复制为 <Unity项目根>/Packages/com.dsh.editor\n * (Unity 内嵌包自动发现,无需改 manifest.json);安装/更新同入口(整目录替换);\n * 卸载 = 删除目标目录。登记清单存 ~/.dsh/dsh-vscode-mode/unity-projects.json。\n * 安全:只触碰固定目标目录;项目根须含 Assets + ProjectSettings;目标已存在且\n * package.json name 不是本包 → 拒绝覆盖。纯路径构造与项目特征判定可单测。\n * 作者 ddj 2026-09-07\n */\nimport { cp, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises'\nimport { basename, dirname, join, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { dshHome, PLUGIN_ID } from './paths.js'\nimport { UNITY_PACKAGE_NAME } from './shared/integration.js'\nimport type { UnityListPayload, UnityProjectEntry } from './shared/integration.js'\n\n/** Unity 项目特征目录。 */\nconst UNITY_MARKERS = ['Assets', 'ProjectSettings']\n/** 登记清单文件名。 */\nconst PROJECTS_FILE = 'unity-projects.json'\n/** 包源目录相对插件包根的位置。 */\nconst UNITY_DIR_NAME = 'unity'\n\n/**\n * 包源目录(随插件包分发的 unity/com.dsh.editor 绝对路径)。\n * @author ddj 2026年09月07号\n * @param moduleUrl 模块 URL(缺省 import.meta.url;测试注入)\n * @returns 包源目录绝对路径\n */\nexport function unitySourceDir(moduleUrl: string = import.meta.url): string {\n return join(dirname(fileURLToPath(moduleUrl)), '..', UNITY_DIR_NAME, UNITY_PACKAGE_NAME)\n}\n\n/**\n * 项目登记清单文件(~/.dsh/dsh-vscode-mode/unity-projects.json)。\n * @author ddj 2026年09月07号\n * @param home DSH home(测试可注入)\n * @returns 清单文件绝对路径\n */\nexport function unityProjectsFile(home = dshHome()): string {\n return join(home, PLUGIN_ID, PROJECTS_FILE)\n}\n\n/**\n * 归一化用户输入的项目根:去首尾空白/引号/尾部分隔符。\n * @author ddj 2026年09月07号\n * @param raw 原始输入\n * @returns 归一化绝对路径\n */\nexport function normalizeUnityRoot(raw: string): string {\n return String(raw ?? '').trim().replace(/^[\"']|[\"']$/g, '').replace(/[\\\\/]+$/, '')\n}\n\n/**\n * 目录名清单是否满足 Unity 项目特征(Assets + ProjectSettings 同时存在)。\n * @author ddj 2026年09月07号\n * @param entries 项目根下的目录名清单\n * @returns 是否 Unity 项目根\n */\nexport function isUnityProject(entries: string[]): boolean {\n return UNITY_MARKERS.every((marker) => entries.includes(marker))\n}\n\n/**\n * 内嵌包目标目录(固定:<root>/Packages/com.dsh.editor)。\n * @author ddj 2026年09月07号\n * @param root Unity 项目根\n * @returns 目标目录绝对路径\n */\nexport function unityTargetOf(root: string): string {\n return join(root, 'Packages', UNITY_PACKAGE_NAME)\n}\n\n/**\n * 读 package.json 的 version(缺失/非法 → null)。\n * @author ddj 2026年09月07号\n * @param pkgFile package.json 绝对路径\n * @returns 版本号或 null\n */\nexport async function readPackageVersion(pkgFile: string): Promise<string | null> {\n try {\n const data = JSON.parse(await readFile(pkgFile, 'utf8')) as { version?: unknown }\n return typeof data?.version === 'string' && data.version ? data.version : null\n } catch {\n return null\n }\n}\n\n/** 登记清单单条记录。 */\ninterface ProjectRecord { path: string; addedAt: string }\n\n/** 读登记清单(缺失/非法 → 空数组)。 */\nasync function readProjects(home = dshHome()): Promise<ProjectRecord[]> {\n try {\n const data: unknown = JSON.parse(await readFile(unityProjectsFile(home), 'utf8'))\n if (!Array.isArray(data)) return []\n return (data as unknown[])\n .filter((item): item is ProjectRecord => !!item && typeof (item as ProjectRecord).path === 'string')\n .map((item) => ({ path: String(item.path), addedAt: String(item.addedAt ?? '') }))\n } catch {\n return []\n }\n}\n\n/** 写登记清单(父目录按需创建)。 */\nasync function writeProjects(records: ProjectRecord[], home = dshHome()): Promise<void> {\n const file = unityProjectsFile(home)\n await mkdir(dirname(file), { recursive: true })\n await writeFile(file, JSON.stringify(records, null, 2) + '\\n', 'utf8')\n}\n\n/**\n * 单个项目的安装状态视图(版本对比 + 合法性)。\n * @author ddj 2026年09月07号\n * @param rawPath 项目路径(原始输入)\n * @param moduleUrl 模块 URL(测试注入)\n * @returns 项目状态\n */\nexport async function unityEntryOf(rawPath: string, moduleUrl: string = import.meta.url): Promise<UnityProjectEntry> {\n const root = normalizeUnityRoot(rawPath)\n const entry: UnityProjectEntry = { path: root, title: basename(root) || root, installedVersion: null, upToDate: false, missingDir: false }\n let names: string[] = []\n try {\n names = await readdir(root)\n } catch {\n entry.missingDir = true\n return entry\n }\n if (!isUnityProject(names)) {\n entry.error = '不是 Unity 项目根(缺少 Assets 或 ProjectSettings 目录)'\n return entry\n }\n const installed = await readPackageVersion(join(unityTargetOf(root), 'package.json'))\n entry.installedVersion = installed\n const sourceVersion = await readPackageVersion(join(unitySourceDir(moduleUrl), 'package.json'))\n entry.upToDate = installed !== null && installed === sourceVersion\n return entry\n}\n\n/**\n * 列出登记项目与包源版本。\n * @author ddj 2026年09月07号\n * @param moduleUrl 模块 URL(测试注入)\n * @param home DSH home(测试注入)\n * @returns 列表载荷\n */\nexport async function unityList(moduleUrl: string = import.meta.url, home = dshHome()): Promise<UnityListPayload> {\n const source = unitySourceDir(moduleUrl)\n const records = await readProjects(home)\n const projects: UnityProjectEntry[] = []\n for (const record of records) projects.push(await unityEntryOf(record.path, moduleUrl))\n return { sourceVersion: await readPackageVersion(join(source, 'package.json')), sourcePath: source, projects }\n}\n\n/**\n * 登记一个 Unity 项目(校验通过才入清单,重复登记幂等)。\n * @author ddj 2026年09月07号\n * @param rawPath 项目路径(原始输入)\n * @param moduleUrl 模块 URL(测试注入)\n * @param home DSH home(测试注入)\n * @returns 项目状态\n */\nexport async function unityAdd(rawPath: string, moduleUrl: string = import.meta.url, home = dshHome()): Promise<UnityProjectEntry> {\n const root = normalizeUnityRoot(rawPath)\n const entry = await unityEntryOf(root, moduleUrl)\n if (entry.missingDir) throw new Error('目录不存在:' + root)\n if (entry.error) throw new Error(entry.error)\n const records = await readProjects(home)\n if (!records.some((record) => normalizeUnityRoot(record.path) === root)) {\n records.push({ path: root, addedAt: new Date().toISOString() })\n await writeProjects(records, home)\n }\n return entry\n}\n\n/**\n * 移除一个项目的登记(不删除已安装的包目录)。\n * @author ddj 2026年09月07号\n * @param rawPath 项目路径(原始输入)\n * @param home DSH home(测试注入)\n */\nexport async function unityRemove(rawPath: string, home = dshHome()): Promise<void> {\n const root = normalizeUnityRoot(rawPath)\n const records = await readProjects(home)\n await writeProjects(records.filter((record) => normalizeUnityRoot(record.path) !== root), home)\n}\n\n/**\n * 一键安装/更新:整目录替换 <root>/Packages/com.dsh.editor 为包源内容。\n * @author ddj 2026年09月07号\n * @param rawPath 项目路径(原始输入)\n * @param moduleUrl 模块 URL(测试注入)\n * @returns 安装后项目状态\n */\nexport async function unityInstall(rawPath: string, moduleUrl: string = import.meta.url): Promise<UnityProjectEntry> {\n const root = normalizeUnityRoot(rawPath)\n const source = unitySourceDir(moduleUrl)\n const target = unityTargetOf(root)\n await validateInstallTarget(root, source, target)\n await rm(target, { recursive: true, force: true })\n await mkdir(join(target, '..'), { recursive: true })\n await cp(source, target, { recursive: true })\n return unityEntryOf(root, moduleUrl)\n}\n\n/**\n * 安装前校验:Unity 项目根 + 目标不与包源重叠 + 已存在目标必须是本包。\n * @author ddj 2026年09月07号\n * @param root 项目根\n * @param source 包源目录\n * @param target 目标目录\n */\nasync function validateInstallTarget(root: string, source: string, target: string): Promise<void> {\n let names: string[] = []\n try {\n names = await readdir(root)\n } catch {\n throw new Error('目录不存在:' + root)\n }\n if (!isUnityProject(names)) throw new Error('不是 Unity 项目根(缺少 Assets 或 ProjectSettings 目录)')\n if (target === source || target.startsWith(source + sep) || source.startsWith(target + sep)) {\n throw new Error('目标目录与包源重叠,拒绝安装')\n }\n const text = await readFile(join(target, 'package.json'), 'utf8').catch((error: NodeJS.ErrnoException) => {\n if (error?.code === 'ENOENT') return null\n throw error\n })\n if (text === null) return\n let name: unknown = null\n try {\n name = (JSON.parse(text) as { name?: unknown }).name\n } catch { /* 解析失败按未知包处理 */ }\n if (name !== UNITY_PACKAGE_NAME) throw new Error('目标目录已存在且不是 DSH 包,拒绝覆盖:' + target)\n}\n","/**\n * dsh-vscode-mode host — 资源管理器右键菜单「在 DSH 文件编辑中打开」(跨平台)。\n * - Windows:launcher(assets/shell/dsh-open.cs 经 csc 编译 WinExe,csc 缺失降级 ps1)安装到\n * ~/.dsh/dsh-vscode-mode/shell/,HKCU\\Software\\Classes 三类菜单键(`*`/Directory/Directory\\Background)。\n * - Linux:dsh-open.sh + GNOME Files(Nautilus)右键脚本 + KDE Dolphin 服务菜单(纯文件写入)。\n * - macOS:dsh-open.sh(Finder 快速操作由用户按配方手动创建,自动检测/移除)。\n * 生命周期:注册成功写 marker(shell/registered.json)→ 插件卸载/reload 清理注册痕迹,\n * 启动时 marker 存在则自动恢复(更新插件不丢注册);用户显式「移除注册」删 marker 永不自动恢复。\n * 所有 reg/csc 调用经 subprocess 服务 argv 数组(卸载清理用 child_process 直调,teardown 可靠)。\n * 纯函数(键路径/命令行/ini/脚本内容)可单测。\n * 作者 ddj 2026-09-07\n */\nimport { spawn } from 'node:child_process'\nimport { chmod, copyFile, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { assetsDirOf, dshHome, PLUGIN_ID } from './paths.js'\nimport { INTEGRATION_BASE_DEFAULT, SHELL_MENU_LEAF } from './shared/integration.js'\nimport { unitySourceDir } from './unityBridge.js'\nimport type { ShellIntegrationStatus, ShellLauncherState, ShellMenuEntry } from './shared/integration.js'\nimport type { Ctx } from './store.js'\n\n/** 菜单显示名(Windows 键默认值 / Linux 菜单项名 / macOS workflow 名)。 */\nexport const MENU_LABEL = '在 DSH 文件编辑中打开'\n/** 编译 launcher 文件名(Windows)。 */\nexport const LAUNCHER_EXE = 'dsh-open.exe'\n/** launcher C# 源文件名。 */\nexport const LAUNCHER_CS = 'dsh-open.cs'\n/** 降级 launcher 脚本名(Windows)。 */\nexport const LAUNCHER_PS1 = 'dsh-open.ps1'\n/** POSIX launcher 脚本名(Linux/macOS 通用)。 */\nexport const LAUNCHER_SH = 'dsh-open.sh'\n/** 深链基址配置文件名。 */\nexport const INI_NAME = 'dsh-open.ini'\n/** 注册 marker 文件名(存在 = 用户注册过且未显式移除)。 */\nexport const MARKER_NAME = 'registered.json'\n/** command 中文件路径占位符(多选时资源管理器逐项展开重复该占位符)。 */\nexport const FILE_TOKEN = '%1'\n/** 文件夹空白处场景的路径占位符。 */\nexport const BACKGROUND_TOKEN = '%V'\n/** Icon 值名。 */\nexport const REG_VALUE_NAME_ICON = 'Icon'\n/** Nautilus 右键脚本文件名。 */\nexport const NAUTILUS_NAME = MENU_LABEL\n/** Dolphin 服务菜单文件名。 */\nexport const DOLPHIN_NAME = 'dsh-editor.desktop'\n/** Finder 快速操作(workflow 包)目录名。 */\nexport const FINDER_NAME = MENU_LABEL + '.workflow'\n/** DSH 小鲸鱼图标文件名(右键菜单 Icon,注册时复制到安装目录)。 */\nexport const WHALE_ICO = 'dsh-whale.ico'\n\n/** 一次 argv 运行结果(退出码 + 输出)。 */\ninterface RunOutcome { code: number | null; output: string }\n\n/** 注册 marker 内容。 */\ninterface RegistrationMarker { baseUrl: string; at: string }\n\n/**\n * reg.exe 路径(SystemRoot 派生;env 可注入便于测试)。\n * @author ddj 2026年09月07号\n * @param env 环境映射(缺省 process.env)\n * @returns reg.exe 绝对路径\n */\nexport function regExe(env: Record<string, string | undefined> = process.env): string {\n return join(systemRoot(env), 'System32', 'reg.exe')\n}\n\n/**\n * csc.exe 候选列表(.NET Framework 4.x 常驻路径,按存在性取首个)。\n * @author ddj 2026年09月07号\n * @param env 环境映射(缺省 process.env)\n * @returns 候选绝对路径列表\n */\nexport function cscCandidates(env: Record<string, string | undefined> = process.env): string[] {\n const root = systemRoot(env)\n return [\n join(root, 'Microsoft.NET', 'Framework64', 'v4.0.30319', 'csc.exe'),\n join(root, 'Microsoft.NET', 'Framework', 'v4.0.30319', 'csc.exe'),\n ]\n}\n\n/**\n * Windows 三类菜单键完整路径。\n * @author ddj 2026年09月07号\n * @param leaf 菜单键叶子名(缺省 DSHEditor)\n * @returns files/dir/background 三个键路径\n */\nexport function menuKeyPaths(leaf: string = SHELL_MENU_LEAF): { files: string; dir: string; background: string } {\n const root = 'HKCU\\\\Software\\\\Classes'\n return {\n files: root + '\\\\*\\\\shell\\\\' + leaf,\n dir: root + '\\\\Directory\\\\shell\\\\' + leaf,\n background: root + '\\\\Directory\\\\Background\\\\shell\\\\' + leaf,\n }\n}\n\n/**\n * launcher 安装目录(~/.dsh/dsh-vscode-mode/shell)。\n * @author ddj 2026年09月07号\n * @param home DSH home(测试可注入)\n * @returns 安装目录绝对路径\n */\nexport function shellInstallDir(home = dshHome()): string {\n return join(home, PLUGIN_ID, 'shell')\n}\n\n/**\n * Nautilus 右键脚本路径(~/.local/share/nautilus/scripts/)。\n * @author ddj 2026年09月07号\n * @param home 用户 home(测试可注入)\n */\nexport function nautilusPath(home = homedir()): string {\n return join(home, '.local', 'share', 'nautilus', 'scripts', NAUTILUS_NAME)\n}\n\n/**\n * Dolphin 服务菜单路径(新 kio/servicemenus + 旧 kservices5,两个都写)。\n * @author ddj 2026年09月07号\n * @param home 用户 home(测试可注入)\n */\nexport function dolphinMenuPaths(home = homedir()): string[] {\n return [\n join(home, '.local', 'share', 'kio', 'servicemenus', DOLPHIN_NAME),\n join(home, '.local', 'share', 'kservices5', 'ServiceMenus', DOLPHIN_NAME),\n ]\n}\n\n/**\n * Finder 快速操作 workflow 包路径(~/Library/Services/)。\n * @author ddj 2026年09月07号\n * @param home 用户 home(测试可注入)\n */\nexport function finderWorkflowPath(home = homedir()): string {\n return join(home, 'Library', 'Services', FINDER_NAME)\n}\n\n/**\n * 注册 marker 文件路径(shell/registered.json)。\n * @author ddj 2026年09月07号\n * @param home DSH home(测试可注入)\n */\nexport function markerFile(home = dshHome()): string {\n return join(shellInstallDir(home), MARKER_NAME)\n}\n\n/**\n * command 默认值(Windows 编译 exe 版)。\n * @author ddj 2026年09月07号\n * @param exePath launcher 绝对路径\n * @param token 路径占位符\n * @returns 注册表 command 值\n */\nexport function commandValue(exePath: string, token: string = FILE_TOKEN): string {\n return '\"' + exePath + '\" \"' + token + '\"'\n}\n\n/**\n * command 默认值(Windows 降级 ps1 版:隐藏窗口运行脚本)。\n * @author ddj 2026年09月07号\n * @param ps1Path launcher 脚本绝对路径\n * @param token 路径占位符\n * @param powerShell powershell.exe 路径(测试可注入)\n * @returns 注册表 command 值\n */\nexport function ps1CommandValue(ps1Path: string, token: string = FILE_TOKEN, powerShell = powerShellExe()): string {\n return '\"' + powerShell + '\" -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File \"' + ps1Path + '\" \"' + token + '\"'\n}\n\n/**\n * dsh-open.ini 内容(base 行驱动 launcher 深链基址,三平台共用)。\n * @author ddj 2026年09月07号\n * @param baseUrl 深链基址\n * @returns ini 文件全文\n */\nexport function iniContent(baseUrl: string): string {\n return '[dsh]\\nbase=' + (baseUrl.trim() || INTEGRATION_BASE_DEFAULT) + '\\n'\n}\n\n/**\n * Nautilus 右键脚本内容(多选经 NAUTILUS_SCRIPT_SELECTED_FILE_PATHS 一次传给 launcher)。\n * @author ddj 2026年09月07号\n * @param launcherPath dsh-open.sh 绝对路径\n * @returns 脚本全文(#!/usr/bin/env bash)\n */\nexport function nautilusScript(launcherPath: string): string {\n return [\n '#!/usr/bin/env bash',\n '# 由 dsh-vscode-mode 生成:GNOME Files(Nautilus)右键脚本 → DSH 文件编辑',\n 'launcher=\"$HOME/.dsh/dsh-vscode-mode/shell/' + LAUNCHER_SH + '\"',\n 'args=()',\n 'while IFS= read -r line; do',\n ' [ -n \"$line\" ] && args+=(\"$line\")',\n 'done <<< \"${NAUTILUS_SCRIPT_SELECTED_FILE_PATHS:-}\"',\n 'exec \"$launcher\" \"${args[@]}\"',\n '',\n ].join('\\n')\n}\n\n/**\n * Dolphin 服务菜单内容(%F 多选传参)。\n * @author ddj 2026年09月07号\n * @param launcherPath dsh-open.sh 绝对路径\n * @returns .desktop 全文\n */\nexport function dolphinMenu(launcherPath: string): string {\n return [\n '[Desktop Entry]',\n 'Type=Service',\n 'X-KDE-ServiceTypes=KonqPopupMenu/Plugin',\n 'MimeType=all/allfiles;inode/directory;',\n 'Actions=openInDshEditor',\n '[Desktop Action openInDshEditor]',\n 'Name=' + MENU_LABEL,\n 'Icon=utilities-terminal',\n 'Exec=\"' + launcherPath + '\" %F',\n '',\n ].join('\\n')\n}\n\n/** SystemRoot 解析(env 可注入)。 */\nfunction systemRoot(env: Record<string, string | undefined>): string {\n return env.SystemRoot || 'C:\\\\Windows'\n}\n\n/** powershell.exe 路径(Windows 降级注册用)。 */\nfunction powerShellExe(env: Record<string, string | undefined> = process.env): string {\n return join(systemRoot(env), 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe')\n}\n\n/** POSIX launcher 脚本安装路径。 */\nfunction shLauncherPath(home = dshHome()): string {\n return join(shellInstallDir(home), LAUNCHER_SH)\n}\n\n/**\n * 经 subprocess 服务运行一个命令(argv 数组,无 shell 插值)。\n * ⚠️ stdio 必须 'inherit':受管 host 环境禁止管道 stdio(node spawn pipe → EPERM),\n * inherit 直写宿主控制台且不建管道;本模块只需退出码(reg query 缺键 = 退出码 1)。\n * done 契约宽松归一化:{exitCode,signal} / {code} / undefined / 抛错(spawn 失败)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param argv 命令与参数\n * @param cwd 工作目录(须已存在)\n * @returns 退出码(0=成功)\n */\nasync function runArgv(ctx: Ctx, argv: string[], cwd = dshHome()): Promise<RunOutcome> {\n const sub = ctx.get('subprocess')\n if (!sub || typeof sub.spawn !== 'function') throw new Error('缺少 subprocess 服务')\n let handle: { done: Promise<unknown> }\n try {\n handle = sub.spawn({\n argv,\n cwd,\n stdio: { stdout: 'inherit', stderr: 'inherit', stdin: 'ignore' },\n graceMs: 10000,\n })\n } catch (error) {\n return { code: 1, output: String(error) }\n }\n try {\n return normalizeOutcome(await handle.done)\n } catch (error) {\n return { code: 1, output: String(error) }\n }\n}\n\n/** 归一化 done 结果(契约宽松:{exitCode,signal} / {code} / 字符串 / undefined)。 */\nfunction normalizeOutcome(result: unknown): RunOutcome {\n if (result == null) return { code: 0, output: '' }\n if (typeof result === 'string') return { code: 0, output: result }\n const record = result as { exitCode?: unknown; code?: unknown }\n if (typeof record.exitCode === 'number') return { code: record.exitCode, output: '' }\n if (typeof record.code === 'number') return { code: record.code, output: '' }\n return { code: 0, output: '' }\n}\n\n/** 文件存在性探测(best-effort)。 */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n return (await stat(path)).isFile()\n } catch {\n return false\n }\n}\n\n/** Windows:探测一个注册表键是否存在(reg query 缺键 = 退出码 1,无需读输出)。 */\nasync function keyExists(ctx: Ctx, key: string): Promise<boolean> {\n const outcome = await runArgv(ctx, [regExe(), 'query', key, '/ve'])\n return outcome.code === 0\n}\n\n/** 读注册 marker(缺失/非法 → null)。 */\nasync function readMarker(home = dshHome()): Promise<RegistrationMarker | null> {\n try {\n const data = JSON.parse(await readFile(markerFile(home), 'utf8')) as { baseUrl?: unknown; at?: unknown }\n if (typeof data?.baseUrl !== 'string' || !data.baseUrl) return null\n return { baseUrl: data.baseUrl, at: typeof data.at === 'string' ? data.at : '' }\n } catch {\n return null\n }\n}\n\n/** 写注册 marker(父目录已存在)。 */\nasync function saveMarker(baseUrl: string, home = dshHome()): Promise<void> {\n const data: RegistrationMarker = { baseUrl, at: new Date().toISOString() }\n await writeFile(markerFile(home), JSON.stringify(data, null, 2) + '\\n', 'utf8')\n}\n\n/** 复制 POSIX launcher 并加执行位(三平台 ini 同写)。 */\nasync function installPosix(dir: string, baseUrl: string): Promise<void> {\n await copyFile(join(assetsDirOf(import.meta.url), 'shell', LAUNCHER_SH), join(dir, LAUNCHER_SH))\n await chmod(join(dir, LAUNCHER_SH), 0o755)\n await writeFile(join(dir, INI_NAME), iniContent(baseUrl), 'utf8')\n}\n\n/** 写 Nautilus 右键脚本(父目录按需创建 + 执行位)。 */\nasync function writeNautilus(home: string, launcherPath: string): Promise<void> {\n const script = nautilusPath(home)\n await mkdir(join(script, '..'), { recursive: true })\n await writeFile(script, nautilusScript(launcherPath), 'utf8')\n await chmod(script, 0o755)\n}\n\n/** 写 Dolphin 服务菜单(新/旧两个路径,父目录按需创建)。 */\nasync function writeDolphinMenus(home: string, launcherPath: string): Promise<void> {\n for (const menu of dolphinMenuPaths(home)) {\n await mkdir(join(menu, '..'), { recursive: true })\n await writeFile(menu, dolphinMenu(launcherPath), 'utf8')\n }\n}\n\n/** Linux:移除 Nautilus 脚本与 Dolphin 服务菜单(仅本插件自有文件)。 */\nasync function removePosixFiles(home: string): Promise<void> {\n await rm(nautilusPath(home), { force: true })\n for (const menu of dolphinMenuPaths(home)) await rm(menu, { force: true })\n}\n\n/** macOS:移除 Finder 快速操作(仅当其内容引用本插件 launcher,防误删用户手工产物)。 */\nasync function dropFinderMenu(home: string): Promise<void> {\n const dir = finderWorkflowPath(home)\n let text = ''\n try {\n text = await readFile(join(dir, 'Contents', 'document.wflow'), 'utf8')\n } catch {\n return\n }\n if (!text.includes('dsh-open')) return\n await rm(dir, { recursive: true, force: true })\n}\n\n/** 卸载清理专用:直调 reg delete(subprocess 服务在 teardown 可能已卸载)。⚠️ stdio 'ignore':受管环境禁管道。 */\nfunction regDeleteDirect(key: string): Promise<void> {\n return new Promise((resolve) => {\n try {\n const child = spawn(regExe(), ['delete', key, '/f'], { windowsHide: true, timeout: 5000, stdio: 'ignore' })\n child.once('close', () => resolve())\n child.once('error', () => resolve())\n } catch {\n resolve()\n }\n })\n}\n\n/**\n * 查询系统集成状态(按平台探测条目注册状态 + launcher 安装态)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param baseUrl 深链基址(设置 integrationBaseUrl)\n * @returns 集成状态\n */\nexport async function shellMenuStatus(ctx: Ctx, baseUrl: string): Promise<ShellIntegrationStatus> {\n const dir = shellInstallDir()\n const platform = process.platform\n let launcher: ShellLauncherState\n let entries: ShellMenuEntry[] = []\n if (platform === 'win32') {\n const exe = join(dir, LAUNCHER_EXE)\n const ps1 = join(dir, LAUNCHER_PS1)\n const compiled = await fileExists(exe)\n const ps1Present = await fileExists(ps1)\n launcher = { present: compiled || ps1Present, compiled, path: compiled ? exe : ps1 }\n entries = [\n { id: 'files', label: '文件', registered: await keyExists(ctx, menuKeyPaths().files) },\n { id: 'dir', label: '文件夹', registered: await keyExists(ctx, menuKeyPaths().dir) },\n { id: 'dirBackground', label: '文件夹空白处', registered: await keyExists(ctx, menuKeyPaths().background) },\n ]\n } else {\n const sh = shLauncherPath()\n launcher = { present: await fileExists(sh), compiled: false, path: sh }\n if (platform === 'linux') {\n const menus = dolphinMenuPaths()\n entries = [\n { id: 'nautilus', label: 'GNOME Files(Nautilus)', registered: await fileExists(nautilusPath()) },\n { id: 'dolphin', label: 'KDE Dolphin', registered: (await fileExists(menus[0])) || (await fileExists(menus[1])) },\n ]\n } else if (platform === 'darwin') {\n entries = [{ id: 'finder', label: 'Finder 快速操作', registered: await fileExists(finderWorkflowPath()), manual: true }]\n }\n }\n return { platform, launcher, entries, baseUrl, unityPackagePath: unitySourceDir() }\n}\n\n/**\n * 注册右键菜单(平台分发):写 ini → 安装 launcher → 首次备份(Windows)→ 写菜单;\n * 成功后写 marker(驱动卸载清理与重启自动恢复)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param baseUrl 深链基址\n * @returns 注册后状态\n */\nexport async function shellMenuRegister(ctx: Ctx, baseUrl: string): Promise<ShellIntegrationStatus> {\n const dir = shellInstallDir()\n await mkdir(dir, { recursive: true })\n if (process.platform === 'win32') {\n await writeFile(join(dir, INI_NAME), iniContent(baseUrl), 'utf8')\n await installIcon(dir)\n const compiled = await installLauncher(ctx, dir, true)\n if (!(await readMarker())) await backupKeys(ctx, dir)\n await writeMenuKeys(ctx, dir, compiled)\n } else if (process.platform === 'linux') {\n await installPosix(dir, baseUrl)\n const launcherPath = join(dir, LAUNCHER_SH)\n await writeNautilus(homedir(), launcherPath)\n await writeDolphinMenus(homedir(), launcherPath)\n } else if (process.platform === 'darwin') {\n // macOS 菜单由用户按 Automator 配方手动创建(UI 提供一键复制);这里仅安装 launcher\n await installPosix(dir, baseUrl)\n }\n await saveMarker(baseUrl)\n return shellMenuStatus(ctx, baseUrl)\n}\n\n/**\n * 移除右键菜单注册(平台分发)+ 删除 marker(显式移除后重启不再自动恢复)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param baseUrl 深链基址\n * @returns 移除后状态\n */\nexport async function shellMenuRemove(ctx: Ctx, baseUrl: string): Promise<ShellIntegrationStatus> {\n if (process.platform === 'win32') {\n const paths = menuKeyPaths()\n for (const key of [paths.files, paths.dir, paths.background]) {\n await runArgv(ctx, [regExe(), 'delete', key, '/f'])\n }\n } else if (process.platform === 'linux') {\n await removePosixFiles(homedir())\n } else if (process.platform === 'darwin') {\n await dropFinderMenu(homedir())\n }\n await rm(markerFile(), { force: true })\n return shellMenuStatus(ctx, baseUrl)\n}\n\n/**\n * 系统集成生命周期(index.ts 经 ctx.effect 挂载):\n * 启动时 marker 存在 → 幂等自动恢复注册(插件更新/reload 不丢注册);\n * 返回的 disposer 在插件卸载/reload 时清理注册痕迹(marker 保留供下次恢复)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @returns 卸载清理 disposer\n */\nexport function shellMenuLifecycle(ctx: Ctx): () => void {\n void restoreOnLoad(ctx).catch(() => {})\n return () => {\n void cleanupOnUnload().catch(() => {})\n }\n}\n\n/** 启动自动恢复:marker 存在才执行(幂等;exe 已存在跳过编译)。 */\nasync function restoreOnLoad(ctx: Ctx): Promise<void> {\n const marker = await readMarker()\n if (!marker) return\n await shellMenuRegister(ctx, marker.baseUrl)\n}\n\n/** 卸载清理:marker 存在 → 按平台移除注册痕迹(launcher 文件与 marker 保留)。 */\nasync function cleanupOnUnload(): Promise<void> {\n const marker = await readMarker()\n if (!marker) return\n if (process.platform === 'win32') {\n const paths = menuKeyPaths()\n for (const key of [paths.files, paths.dir, paths.background]) await regDeleteDirect(key)\n } else if (process.platform === 'linux') {\n await removePosixFiles(homedir())\n } else if (process.platform === 'darwin') {\n await dropFinderMenu(homedir())\n }\n}\n\n/**\n * 安装 Windows launcher:优先 csc 编译 exe(无控制台闪窗),任一候选失败降级复制 ps1。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param dir 安装目录(已存在)\n * @param force 是否强制重编译(自动恢复时 false:exe 已存在直接复用)\n * @returns 是否编译成功(false=降级 ps1)\n */\nasync function installLauncher(ctx: Ctx, dir: string, force: boolean): Promise<boolean> {\n const exe = join(dir, LAUNCHER_EXE)\n if (!force && await fileExists(exe)) return true\n const shellAssets = join(assetsDirOf(import.meta.url), 'shell')\n for (const candidate of cscCandidates()) {\n if (!(await fileExists(candidate))) continue\n try {\n await copyFile(join(shellAssets, LAUNCHER_CS), join(dir, LAUNCHER_CS))\n const outcome = await runArgv(ctx, [\n candidate,\n '/nologo',\n '/target:winexe',\n '/r:System.Windows.Forms.dll',\n '/r:System.Web.Extensions.dll',\n '/out:' + exe,\n join(dir, LAUNCHER_CS),\n ], dir)\n if (outcome.code === 0 && await fileExists(exe)) return true\n } catch { /* 任一候选失败继续降级 */ }\n }\n await copyFile(join(shellAssets, LAUNCHER_PS1), join(dir, LAUNCHER_PS1))\n return false\n}\n\n/**\n * 首次注册前备份 Windows 三类既有键(best-effort,键不存在时导出失败忽略)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param dir 备份文件落盘目录\n */\nasync function backupKeys(ctx: Ctx, dir: string): Promise<void> {\n const stamp = new Date().toISOString().replace(/[:.]/g, '-')\n const paths = menuKeyPaths()\n const targets: Array<[string, string]> = [\n [paths.files, 'files'],\n [paths.dir, 'dir'],\n [paths.background, 'background'],\n ]\n for (const [key, name] of targets) {\n await runArgv(ctx, [regExe(), 'export', key, join(dir, 'backup-' + name + '-' + stamp + '.reg'), '/y'], dir)\n }\n}\n\n/** 复制 DSH 小鲸鱼 ico 到安装目录(右键菜单 Icon 用;缺失不阻塞注册)。 */\nasync function installIcon(dir: string): Promise<void> {\n try {\n await copyFile(join(assetsDirOf(import.meta.url), 'shell', WHALE_ICO), join(dir, WHALE_ICO))\n } catch { /* 图标缺失不阻塞注册 */ }\n}\n\n/**\n * 写 Windows 三类菜单键(显示名 + Icon + command 子键)。\n * @author ddj 2026年09月07号\n * @param ctx DSH 上下文\n * @param dir launcher 安装目录\n * @param compiled 是否为编译 exe(否则 ps1 command)\n */\nasync function writeMenuKeys(ctx: Ctx, dir: string, compiled: boolean): Promise<void> {\n const launcherPath = compiled ? join(dir, LAUNCHER_EXE) : join(dir, LAUNCHER_PS1)\n const iconPath = (await fileExists(join(dir, WHALE_ICO))) ? join(dir, WHALE_ICO) : launcherPath\n const keys: Array<[string, string]> = [\n [menuKeyPaths().files, FILE_TOKEN],\n [menuKeyPaths().dir, FILE_TOKEN],\n [menuKeyPaths().background, BACKGROUND_TOKEN],\n ]\n for (const [key, token] of keys) {\n const command = compiled ? commandValue(launcherPath, token) : ps1CommandValue(launcherPath, token)\n await addMenuKey(ctx, key, iconPath, command)\n }\n}\n\n/** 写一个 Windows 菜单键:默认值(显示名)+ Icon + command 子键。 */\nasync function addMenuKey(ctx: Ctx, key: string, iconPath: string, command: string): Promise<void> {\n const reg = regExe()\n await runArgv(ctx, [reg, 'add', key, '/ve', '/t', 'REG_SZ', '/d', MENU_LABEL, '/f'])\n await runArgv(ctx, [reg, 'add', key, '/v', REG_VALUE_NAME_ICON, '/t', 'REG_SZ', '/d', iconPath, '/f'])\n await runArgv(ctx, [reg, 'add', key + '\\\\command', '/ve', '/t', 'REG_SZ', '/d', command, '/f'])\n}\n","/**\n * dsh-vscode-mode host — 深链移交(避免重复打开 DSH 页面)。\n * launcher 投递待打开请求(edrv.external.handoff)→ 已打开页面 3s 轮询领取(edrv.external.pending)\n * 并就地执行打开规则;15s 内无页面轮询过 = 无活跃页面 → launcher 回退打开新页。\n * token 防多实例串扰;TTL 兜底防陈旧悬挂。模块级状态(host 单进程单例)。\n * 作者 ddj 2026-09-08\n */\nimport { randomUUID } from 'node:crypto'\n\n/** 一次外部打开请求(launcher 投递)。 */\nexport interface ExternalOpenRequest {\n paths: string[]\n line?: number\n column?: number\n}\n\n/** 待打开 TTL:超时未领取即丢弃(launcher 回退已自行处理)。 */\nconst PENDING_TTL_MS = 60_000\n/** 活跃页面判定窗口:窗口内有过 pending 轮询 = 有页面在。 */\nconst PRESENCE_WINDOW_MS = 15_000\n\nlet pending: (ExternalOpenRequest & { token: string; at: number }) | null = null\nlet lastPollAt = 0\n\n/**\n * 投递一次外部打开请求;返回活跃页面数(0 = launcher 应回退开新页)与移交 token。\n * @author ddj 2026年09月08号\n * @param req 打开请求\n * @returns 活跃页面数与 token\n */\nexport function handoffOpen(req: ExternalOpenRequest): { clients: number; token: string } {\n const token = randomUUID()\n pending = { ...req, token, at: Date.now() }\n return { token, clients: clientsAlive() ? 1 : 0 }\n}\n\n/**\n * 页面轮询:刷新活跃态并领取待打开请求(取走即清,多页面仅一方执行)。\n * @author ddj 2026年09月08号\n * @returns 待打开请求或 null\n */\nexport function pollPending(): ExternalOpenRequest | null {\n lastPollAt = Date.now()\n if (!pending) return null\n if (Date.now() - pending.at > PENDING_TTL_MS) {\n pending = null\n return null\n }\n const taken: ExternalOpenRequest = { paths: pending.paths, line: pending.line, column: pending.column }\n pending = null\n return taken\n}\n\n/**\n * 查询移交是否已被页面领取(take=true 时未领取则取走清除,供 launcher 回退开新页)。\n * @author ddj 2026年09月08号\n * @param token 移交 token\n * @param take 未领取时是否取走清除\n * @returns delivered=true = 已有页面领取(或已被更新的请求取代)\n */\nexport function pendingState(token: string, take: boolean): { delivered: boolean } {\n const delivered = pending === null || pending.token !== token\n if (take && !delivered) pending = null\n return { delivered }\n}\n\n/** 活跃页面判定。 */\nfunction clientsAlive(): boolean {\n return Date.now() - lastPollAt <= PRESENCE_WINDOW_MS\n}\n","/**\n * dsh-vscode-mode host — 在 OS 文件浏览器中打开/定位路径(reveal 能力)。\n * 纯函数 revealCommand 平台分发 + revealInExplorer 经 ctx.subprocess.spawn 发射\n * (argv 数组、无 shell 插值,沿 workspace/revert 的 subprocess 契约)。\n * 文件 → 资源管理器选中定位;目录 → 打开目录;Linux 无通用定位协议 → 打开所在目录。\n * 作者 ddj 2026-08-27\n */\nimport { dirname } from 'node:path'\nimport type { Ctx } from './store.js'\n\n/** reveal 结果(沿 revert.ts 的 Result 风格)。 */\nexport type RevealResult = { ok: true } | { ok: false; error: string }\n\n/**\n * 构造平台 opener 的 argv(纯函数,platform 可注入便于单测)。\n * @author ddj 2026年08月27号\n * @param absPath 绝对路径\n * @param isDir 是否为目录\n * @param platform 目标平台(缺省当前进程平台)\n * @returns opener argv(无 shell 插值)\n */\nexport function revealCommand(absPath: string, isDir: boolean, platform: NodeJS.Platform = process.platform): { argv: string[] } {\n switch (platform) {\n case 'darwin':\n return { argv: ['open', '-R', absPath] }\n case 'win32':\n // 文件 → 定位并选中;目录 → 直接打开该目录\n return isDir\n ? { argv: ['explorer.exe', absPath] }\n : { argv: ['explorer.exe', '/select,', absPath] }\n default:\n // Linux 无通用 select 协议:文件打开所在目录、目录打开自身(KISS,对齐 better-sidebar)\n return { argv: ['xdg-open', isDir ? absPath : dirname(absPath)] }\n }\n}\n\n/**\n * 经 host subprocess 服务发射 opener(fire-and-forget 语义)。\n * Explorer 为 GUI 分离进程,非零退出码不视为失败;仅 spawn 级错误回失败。\n * @author ddj 2026年08月27号\n * @param ctx DSH host 上下文\n * @param absPath 绝对路径\n * @param isDir 是否为目录\n * @returns 成功或失败原因\n */\nexport async function revealInExplorer(ctx: Ctx, absPath: string, isDir: boolean): Promise<RevealResult> {\n const sub = ctx.get('subprocess')\n if (!sub || typeof sub.spawn !== 'function') {\n return { ok: false, error: '打开文件浏览器不可用:缺少 subprocess 服务' }\n }\n const { argv } = revealCommand(absPath, isDir)\n try {\n const handle = sub.spawn({\n argv,\n cwd: dirname(absPath),\n stdio: { stdout: { maxBytes: 1 << 16 }, stderr: { maxBytes: 1 << 16 }, stdin: 'ignore' },\n graceMs: 10000,\n })\n await handle.done\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '打开失败:' + String(error) }\n }\n}\n","/**\n * dsh-vscode-mode host — 诊断文件通道(client 上报 → 缓冲批量落盘)。\n * 通道:edrv.debug RPC → 内存缓冲(满/空闲触发)→ 串行读改写\n * `~/.dsh/dsh-vscode-mode/logs/debug.<cwdHash>.log`(512KB 上限截断保留尾部)。\n * 设计:console 不一定落盘,文件可靠;写失败静默忽略(调试日志不阻塞业务)。\n * 迁移自 src/rpc.ts(enqueueDebug/flushDebug),逻辑一字不改,仅终端回显改走统一日志器。\n * 作者 ddj 2026-09-08\n */\nimport { mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { DEBUG_LOG, debugLogFile, pluginLogRoot } from './paths.js'\nimport { log } from './log.js'\nimport type { Ctx } from './store.js'\n\n/** cwd → 内存缓冲:行数组 + 累计字节数 + 待触发 flush 定时器(攒批落盘,避免每条日志全文件读改写)。 */\nconst debugBuffers = new Map<string, { lines: string[]; len: number; timer: ReturnType<typeof setTimeout> | null }>()\n/** cwd → Promise 链:串行化 debug 日志落盘(fs read+write 非原子,避免并发丢行)。 */\nconst debugWriteQueues = new Map<string, Promise<void>>()\n/** debug 日志单文件上限:超限截断保留尾部,防文件无限增长拖慢每次追加。 */\nconst DEBUG_LOG_CAP = 512 * 1024\n/** debug 日志批量缓冲上限:攒满即落盘(一次读改写),上限内不逐条写文件。 */\nconst DEBUG_BUF_CAP = 32 * 1024\n/** debug 日志空闲 flush 延迟:缓冲未满时,静默一段时间后落盘一次。 */\nconst DEBUG_FLUSH_IDLE_MS = 1000\n/** cwd → 已清理旧工作区 debug 日志标记(一次性)。 */\nconst debugLegacyCleaned = new Set<string>()\n/** 诊断回显日志器(终端回显统一带 `[dsh-vscode-mode:debug]` 前缀)。 */\nconst debugLog = log.child('debug')\n\n/**\n * 批量落盘一条 debug 日志缓冲:读旧文件 → 追加 → 超上限截断保留尾部 → 一次写回。\n * 串行链保证同一 cwd 的读改写不交错丢行;写失败静默忽略(调试日志不阻塞业务)。\n * @author ddj 2026年09月08号\n * @param cwd 工作区(日志落 ~/.dsh/dsh-vscode-mode/logs/debug.<cwdHash>.log)\n * @param batch 本批日志行\n */\nfunction flushDebug(cwd: string, batch: string[]): Promise<void> {\n const prev = debugWriteQueues.get(cwd) ?? Promise.resolve()\n const task = prev.then(async () => {\n try {\n await mkdir(pluginLogRoot(), { recursive: true })\n const target = debugLogFile(cwd)\n const old = await readFile(target, 'utf8').catch(() => '')\n const appended = old + batch.map((l) => new Date().toISOString() + ' ' + l + '\\n').join('')\n const next = appended.length > DEBUG_LOG_CAP ? appended.slice(-Math.floor(DEBUG_LOG_CAP / 2)) : appended\n await writeFile(target, next, 'utf8')\n // 迁移后一次性清理旧工作区 debug 日志(best-effort)\n if (!debugLegacyCleaned.has(cwd)) {\n debugLegacyCleaned.add(cwd)\n await rm(join(cwd, DEBUG_LOG), { force: true }).catch(() => {})\n }\n } catch (e) { /* 写日志失败忽略 */ }\n })\n debugWriteQueues.set(cwd, task)\n return task\n}\n\n/**\n * 记录一条 client 上报的诊断日志:入队缓冲批量落盘 + 终端回显(`[dsh-vscode-mode:debug]` 前缀)。\n * @author ddj 2026年09月08号\n * @param _ctx DSH 上下文(入参保留:诊断通道按 cwd 隔离,当前不需要 ctx,未来过滤用)\n * @param cwd 工作区(日志文件按 cwd hash 隔离)\n * @param text 单条日志文本(不含换行)\n */\nexport function debugRecord(_ctx: Ctx, cwd: string, text: string): void {\n const st = debugBuffers.get(cwd) ?? { lines: [], len: 0, timer: null }\n st.lines.push(text)\n st.len += text.length\n const flush = () => {\n st.timer = null\n const batch = st.lines\n st.lines = []\n st.len = 0\n void flushDebug(cwd, batch)\n }\n if (st.len >= DEBUG_BUF_CAP) {\n if (st.timer) clearTimeout(st.timer)\n flush()\n } else if (!st.timer) {\n st.timer = setTimeout(flush, DEBUG_FLUSH_IDLE_MS)\n }\n debugBuffers.set(cwd, st)\n debugLog.error(text)\n}\n","/**\n * dsh-vscode-mode host — DSH 会话性能管理(会话卫生 + 体积 stat + 侧车摘要)。\n * 职责:\n * - 盘点 ~/.dsh/sessions 全部工作区会话(每会话仅 stat 日志文件,不解压,轻量);\n * - 移出/恢复/清除:会话目录在 ~/.dsh/sessions 与 ~/.dsh/sessions-archive 间可逆搬迁;\n * - 当前会话体积 stat(对话头部指示器用,纯 stat);\n * - 侧车摘要:agent/脚本取关键字段,避免整份读 .dsh-edit-review.json 进对话。\n * 纯函数可单测(路径编码/移出规划);fs 操作 best-effort 返回逐项结果不抛。\n * 作者 ddj 2026-09-02\n */\nimport { mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises'\nimport { dirname, join, resolve, sep } from 'node:path'\nimport { parseSidecar } from './store.js'\nimport { recSummary } from './model.js'\nimport { SIDECAR, SIDECAR_ARCHIVE, dshHome, sessionIdSegment, sessionWorkspaceKey, sessionsRoot } from './paths.js'\nimport type { PerfMoveFailure, PerfMoveItem, PerfSession, PerfTotals, PerfWorkspace, SidecarPerfSummary } from './shared/rpc.js'\nimport type { Ctx } from './store.js'\n\n/** 会话日志文件名(zstd 优先,降级纯 jsonl)。 */\nconst LOG_NAMES = ['session.jsonl.zstd', 'session.jsonl']\n\n/** 归档根(~/.dsh/sessions-archive,与 sessions 同级,可逆移出的落点)。 */\nexport function sessionsArchiveRoot(home = dshHome()): string {\n return join(home, 'sessions-archive')\n}\n\n/** 会话盘点结果(工作区聚合 + 会话明细 + 汇总)。 */\nexport interface SessionInventory {\n workspaces: PerfWorkspace[]\n sessions: PerfSession[]\n totals: PerfTotals\n}\n\n/** 移出规划条件:显式集合或规则(minBytes / olderThanDays)。 */\nexport interface MoveCriteria {\n workspaceKey?: string\n sessionIds?: string[]\n minBytes?: number\n olderThanDays?: number\n}\n\n/** 路径段校验:非空、非 . / ..、不含分隔符与 Windows 非法字符(防 join 逃逸)。 */\nexport function validDirName(name: string): boolean {\n return typeof name === 'string' && name.length > 0 && name !== '.' && name !== '..' && !/[/\\\\]/.test(name) && !/[:*?\"<>|]/.test(name)\n}\n\n/** target 必须落在 root 内(自身或其子路径),防路径穿越。 */\nexport function withinDir(target: string, root: string): boolean {\n const rel = resolve(target)\n const base = resolve(root)\n return rel === base || rel.startsWith(base + sep)\n}\n\n/** stat 一个会话目录里的日志文件(首个存在的),缺失 → null。 */\nexport async function statSessionLog(sessionDir: string): Promise<{ size: number; mtimeMs: number } | null> {\n for (const name of LOG_NAMES) {\n try {\n const info = await stat(join(sessionDir, name))\n if (info.isFile()) return { size: info.size, mtimeMs: info.mtimeMs }\n } catch (error) { /* 尝试下一个日志名 */ }\n }\n return null\n}\n\n/**\n * 盘点 ~/.dsh/sessions:按工作区分组,每会话仅 stat 日志文件体积与 mtime。\n * 不解压日志(V8 展开成本高),活跃标记由调用方传入后置。\n * @author ddj 2026年09月02号\n * @param home DSH home(测试可注入)\n * @param archive 归档根(默认 sessions-archive;测试可注入)\n * @returns 工作区聚合(按体积降序)+ 会话明细(按体积降序)+ 汇总\n */\nexport async function scanSessionInventory(home = dshHome(), archive = sessionsArchiveRoot(home)): Promise<SessionInventory> {\n void archive\n const root = sessionsRoot(home)\n const workspaces: PerfWorkspace[] = []\n const sessions: PerfSession[] = []\n let totalBytes = 0\n let totalCount = 0\n const wsDirs = await readdir(root, { withFileTypes: true }).catch(() => [])\n for (const ws of wsDirs) {\n if (!ws.isDirectory() || !validDirName(ws.name)) continue\n const wsDir = join(root, ws.name)\n const wsSessions: PerfSession[] = []\n let wsBytes = 0\n let minMtime = Number.POSITIVE_INFINITY\n let maxMtime = 0\n const sessionDirs = await readdir(wsDir, { withFileTypes: true }).catch(() => [])\n for (const sd of sessionDirs) {\n if (!sd.isDirectory()) continue\n const info = await statSessionLog(join(wsDir, sd.name))\n if (!info) continue\n const row: PerfSession = { sessionId: sd.name, workspaceKey: ws.name, bytes: info.size, mtime: info.mtimeMs, active: false }\n wsSessions.push(row)\n wsBytes += info.size\n totalBytes += info.size\n totalCount += 1\n if (info.mtimeMs < minMtime) minMtime = info.mtimeMs\n if (info.mtimeMs > maxMtime) maxMtime = info.mtimeMs\n }\n wsSessions.sort((a, b) => b.bytes - a.bytes)\n sessions.push(...wsSessions)\n workspaces.push({\n workspaceKey: ws.name,\n sessionCount: wsSessions.length,\n totalBytes: wsBytes,\n minMtime: Number.isFinite(minMtime) ? minMtime : 0,\n maxMtime,\n })\n }\n workspaces.sort((a, b) => b.totalBytes - a.totalBytes)\n return { workspaces, sessions, totals: { workspaces: workspaces.length, sessions: totalCount, totalBytes } }\n}\n\n/** 标记活跃会话(live id 与目录段名双向匹配,兼容编码差异)。 */\nexport function markActiveSessions(sessions: PerfSession[], activeIds: Iterable<string>): void {\n const raw = new Set(activeIds)\n const encoded = new Set<string>()\n for (const id of raw) encoded.add(sessionIdSegment(id))\n for (const s of sessions) {\n if (raw.has(s.sessionId) || encoded.has(s.sessionId)) s.active = true\n }\n}\n\n/**\n * 移出规划(纯函数):从盘点中按「显式集合」或「规则(minBytes / olderThanDays)」\n * 圈选可移出会话。活跃会话一律排除;无显式集合且无规则时不选(防误移)。\n * @author ddj 2026年09月02号\n * @param inventory 盘点结果\n * @param criteria 圈选条件\n * @returns 待移出清单与释放字节\n */\nexport function planMoveOut(inventory: SessionInventory, criteria: MoveCriteria): { items: PerfMoveItem[]; reclaimedBytes: number } {\n const items: PerfMoveItem[] = []\n const explicit = Array.isArray(criteria.sessionIds) && criteria.sessionIds.length > 0\n const cutoff = criteria.olderThanDays ? Date.now() - criteria.olderThanDays * 24 * 60 * 60 * 1000 : 0\n for (const s of inventory.sessions) {\n if (s.active) continue\n if (criteria.workspaceKey && s.workspaceKey !== criteria.workspaceKey) continue\n if (explicit) {\n if (!criteria.sessionIds!.includes(s.sessionId)) continue\n } else {\n if (criteria.minBytes && s.bytes < criteria.minBytes) continue\n if (criteria.olderThanDays && s.mtime > cutoff) continue\n if (!criteria.minBytes && !criteria.olderThanDays) continue\n }\n items.push({ workspaceKey: s.workspaceKey, sessionId: s.sessionId, bytes: s.bytes })\n }\n return { items, reclaimedBytes: items.reduce((sum, i) => sum + i.bytes, 0) }\n}\n\n/** 移出执行结果。 */\nexport interface MoveOutResult {\n moved: PerfMoveItem[]\n failures: PerfMoveFailure[]\n reclaimedBytes: number\n}\n\n/**\n * 移出会话目录到归档区(同卷 rename,可逆)。活跃会话拒绝;路径越界拒绝;\n * 逐项 best-effort,成功项写归档 manifest。默认不 dry-run(dryRun 时只校验不搬迁)。\n * @author ddj 2026年09月02号\n * @param home DSH home\n * @param archive 归档根\n * @param items 待移出清单(来自 planMoveOut 或用户确认)\n * @param activeIds 活跃会话 id 集合(执行期再校验一次)\n * @param dryRun 仅校验不搬迁\n */\nexport async function moveOutSessions(home: string, archive: string, items: PerfMoveItem[], activeIds: Iterable<string>, dryRun = false): Promise<MoveOutResult> {\n const root = sessionsRoot(home)\n const rawActive = new Set(activeIds)\n const encodedActive = new Set<string>()\n for (const id of rawActive) encodedActive.add(sessionIdSegment(id))\n const isActive = (id: string): boolean => rawActive.has(id) || encodedActive.has(id)\n const moved: PerfMoveItem[] = []\n const failures: PerfMoveFailure[] = []\n for (const item of items) {\n if (!validDirName(item.workspaceKey)) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '工作区键不合法' })\n continue\n }\n if (isActive(item.sessionId)) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '活跃会话,拒绝移出' })\n continue\n }\n const seg = sessionIdSegment(item.sessionId)\n const src = join(root, item.workspaceKey, seg)\n const dst = join(archive, item.workspaceKey, seg)\n if (!withinDir(src, root) || !withinDir(dst, archive)) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '路径越界,拒绝执行' })\n continue\n }\n if (dryRun) {\n try {\n const info = await stat(src)\n if (info.isDirectory()) moved.push({ ...item, bytes: (await statSessionLog(src))?.size ?? item.bytes })\n else failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '源目录不存在' })\n } catch (error) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: '源目录不存在' })\n }\n continue\n }\n try {\n await mkdir(dirname(dst), { recursive: true })\n await rename(src, dst)\n const bytes = (await statSessionLog(dst))?.size ?? item.bytes\n moved.push({ ...item, bytes })\n } catch (error) {\n failures.push({ workspaceKey: item.workspaceKey, sessionId: item.sessionId, error: String(error) })\n }\n }\n if (moved.length && !dryRun) await appendMoveManifest(archive, moved)\n return { moved, failures, reclaimedBytes: moved.reduce((sum, i) => sum + i.bytes, 0) }\n}\n\n/** 恢复单个会话:归档 → sessions。目标已存在则拒绝(不覆盖)。 */\nexport async function restoreSession(home: string, archive: string, workspaceKey: string, sessionId: string): Promise<{ ok: boolean; error?: string }> {\n if (!validDirName(workspaceKey)) return { ok: false, error: '工作区键不合法' }\n const seg = sessionIdSegment(sessionId)\n const root = sessionsRoot(home)\n const src = join(archive, workspaceKey, seg)\n const dst = join(root, workspaceKey, seg)\n if (!withinDir(src, archive) || !withinDir(dst, root)) return { ok: false, error: '路径越界,拒绝执行' }\n try {\n await stat(src)\n } catch (error) {\n return { ok: false, error: '归档中不存在该会话' }\n }\n try {\n await stat(dst)\n return { ok: false, error: '目标位置已存在同名会话' }\n } catch (error) { /* 目标不存在,可恢复 */ }\n try {\n await mkdir(dirname(dst), { recursive: true })\n await rename(src, dst)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n}\n\n/** 清除归档区早于 N 天的会话(破坏性,仅限归档区)。 */\nexport async function purgeArchive(archive: string, olderThanDays: number): Promise<{ removed: number; reclaimedBytes: number }> {\n const cutoff = Date.now() - olderThanDays * 24 * 60 * 60 * 1000\n let removed = 0\n let reclaimedBytes = 0\n const wsDirs = await readdir(archive, { withFileTypes: true }).catch(() => [])\n for (const ws of wsDirs) {\n if (!ws.isDirectory()) continue\n const wsDir = join(archive, ws.name)\n const sessionDirs = await readdir(wsDir, { withFileTypes: true }).catch(() => [])\n for (const sd of sessionDirs) {\n if (!sd.isDirectory()) continue\n const info = await statSessionLog(join(wsDir, sd.name))\n if (!info || info.mtimeMs > cutoff) continue\n try {\n await rm(join(wsDir, sd.name), { recursive: true, force: true })\n removed += 1\n reclaimedBytes += info.size\n } catch (error) { /* 删除失败跳过 */ }\n }\n }\n return { removed, reclaimedBytes }\n}\n\n/** 当前会话持久化体积(对话头部指示器用):仅 stat,近零成本。 */\nexport async function sessionSizeOf(home: string, cwd: string, sessionId: string): Promise<{ bytes: number; exists: boolean }> {\n const dir = join(sessionsRoot(home), sessionWorkspaceKey(cwd), sessionIdSegment(sessionId))\n for (const name of LOG_NAMES) {\n try {\n const info = await stat(join(dir, name))\n if (info.isFile()) return { bytes: info.size, exists: true }\n } catch (error) { /* 尝试下一个日志名 */ }\n }\n return { bytes: 0, exists: false }\n}\n\n/**\n * 侧车摘要:返回活跃记录数、每文件 pending 计数、归档体积。\n * agent/脚本取关键字段即可,不必整份读 .dsh-edit-review.json(避免大对象进对话)。\n * @author ddj 2026年09月02号\n * @param ctx DSH host 上下文(fs 服务)\n * @param cwd 工作区路径(null 时返回空摘要)\n */\nexport async function sidecarSummaryOf(ctx: Ctx, cwd: string | null): Promise<SidecarPerfSummary> {\n const fs = ctx.get('fs')\n const summary: SidecarPerfSummary = { active: 0, pendingByFile: [], archiveBytes: 0 }\n if (!fs || !cwd) return summary\n try {\n const text = await fs.readText(await fs.resolve(SIDECAR, { cwd }))\n const data = parseSidecar(text)\n const recs = data?.workspaces?.[cwd]?.records\n if (recs) {\n const byFile = new Map<string, number>()\n let active = 0\n for (const rec of Object.values(recs)) {\n if (rec.archived) continue\n active += 1\n const sm = recSummary(rec)\n if (sm.pending > 0 && rec.path) byFile.set(rec.path, (byFile.get(rec.path) ?? 0) + sm.pending)\n }\n summary.active = active\n summary.pendingByFile = [...byFile.entries()].map(([path, pending]) => ({ path, pending })).sort((a, b) => b.pending - a.pending)\n }\n try {\n const info = await fs.stat(await fs.resolve(SIDECAR_ARCHIVE, { cwd }))\n summary.archiveBytes = info?.size ?? 0\n } catch (error) { /* 归档缺失忽略 */ }\n } catch (error) { /* sidecar 不可读返回空摘要 */ }\n return summary\n}\n\n/** 归档 manifest 条目。 */\ninterface MoveManifestEntry { at: string; workspaceKey: string; sessionId: string }\n\n/** 归档 manifest(可逆移出的索引,供恢复/审计)。 */\ninterface MoveManifest { version: 1; items: MoveManifestEntry[] }\n\n/** 解析归档 manifest(损坏/缺失 → 空)。 */\nfunction parseMoveManifest(text: string | null): MoveManifest {\n if (!text) return { version: 1, items: [] }\n try {\n const data = JSON.parse(text) as MoveManifest\n return { version: 1, items: Array.isArray(data.items) ? data.items : [] }\n } catch (error) {\n return { version: 1, items: [] }\n }\n}\n\n/** 追加移出记录到归档 manifest(best-effort,失败不影响主流程)。 */\nasync function appendMoveManifest(archive: string, items: PerfMoveItem[]): Promise<void> {\n try {\n const file = join(archive, '.manifest.json')\n const prev = parseMoveManifest(await readFile(file, 'utf8').catch(() => null))\n const at = new Date().toISOString()\n for (const item of items) prev.items.push({ at, workspaceKey: item.workspaceKey, sessionId: item.sessionId })\n await mkdir(archive, { recursive: true })\n await writeFile(file, JSON.stringify(prev, null, 2), 'utf8')\n } catch (error) { /* manifest 写失败静默 */ }\n}\n","/**\n * dsh-vscode-mode host — profile patch 压缩调优(文本行级,零 YAML 依赖)。\n * 在 ~/.dsh/profiles/<profile>/cordis.patch.yml 末尾追加/移除一段带标记注释的\n * id 定向覆盖块(compaction-basic / tool-result-pruner 更低阈值)。\n * 纯文本函数可单测:幂等追加、整段移除、无块原样返回。\n * 作者 ddj 2026-09-02\n */\n\n/** 性能块起始标记注释(文件内唯一锚点)。 */\nexport const PERF_MARK_START = '# dsh-vscode-mode perf tuning (start)'\n/** 性能块结束标记注释。 */\nexport const PERF_MARK_END = '# dsh-vscode-mode perf tuning (end)'\n\n/**\n * 建议的压缩调优 YAML 块(顶层 loader patch 条目,id 定向覆盖)。\n * - compaction-basic:thresholdRatio 0.8→0.6、retainRatio 0.16→0.12(更早触发压缩);\n * - tool-result-pruner:thresholdChars 8192→4096、head/tail 同步收窄(大 tool result 提前截断)。\n * 注意:压缩只降低模型可见上下文压力,不重写已持久化会话日志(append-only)。\n * @author ddj 2026年09月02号\n * @returns 带前后标记注释与尾换行的 YAML 块\n */\nexport function perfConfigBlock(): string {\n return [\n PERF_MARK_START,\n '# 更早触发会话内压缩:降低模型可见上下文压力(仅影响后续轮次,不缩小已持久化日志)。',\n '- id: compaction-basic',\n ' config:',\n ' thresholdRatio: 0.6',\n ' retainRatio: 0.12',\n '- id: tool-result-pruner',\n ' config:',\n ' thresholdChars: 4096',\n ' headChars: 2048',\n ' tailChars: 512',\n PERF_MARK_END,\n '',\n ].join('\\n')\n}\n\n/** 当前文本是否已包含性能块。 */\nexport function patchHasPerfConfig(text: string): boolean {\n return text.includes(PERF_MARK_START)\n}\n\n/**\n * 移除性能块(起止标记注释之间的整段,含所在行),无块时原样返回。\n * 移除后压缩多余空行、确保以单个换行结尾。\n * @author ddj 2026年09月02号\n * @param text 原 patch 文本\n * @returns 移除后的文本\n */\nexport function patchRemovePerfConfig(text: string): string {\n const start = text.indexOf(PERF_MARK_START)\n if (start === -1) return text\n const end = text.indexOf(PERF_MARK_END, start)\n const lineStart = text.lastIndexOf('\\n', start - 1) + 1\n if (end === -1) return text.slice(0, lineStart).replace(/\\n+$/, '\\n')\n const after = (() => {\n const nl = text.indexOf('\\n', end)\n return nl === -1 ? text.length : nl + 1\n })()\n const removed = (text.slice(0, lineStart) + text.slice(after)).replace(/\\n{3,}/g, '\\n\\n')\n return removed.replace(/\\n+$/, '\\n')\n}\n\n/**\n * 幂等追加性能块:已有块先整段移除再追加到文件末尾(保证全文件只有一份、位置固定)。\n * @author ddj 2026年09月02号\n * @param text 原 patch 文本\n * @returns 追加后的文本\n */\nexport function patchInsertPerfConfig(text: string): string {\n const base = patchRemovePerfConfig(text)\n const trimmed = base.replace(/\\n+$/, '')\n return trimmed + '\\n' + perfConfigBlock()\n}\n","/**\n * dsh-vscode-mode host — RPC 分发:类型化方法表替代巨型 switch。\n * 迁移自原 src/index.ts 的 handleRpc,方法名/载荷/错误文案一字不改。\n * 新功能 = shared/rpc.ts 加方法 + 这里加一个 handler,不改其他模块。\n * 作者 ddj 2026-08-20\n */\nimport type { DecideItem, DecideResult, RpcHandlerMap, RpcMethod, RpcRequestMap, RpcResult, RpcScope } from './shared/rpc.js'\nimport { binaryMimeOf } from './shared/rpc.js'\nimport type { DiffRecord, RecordView } from './shared/types.js'\nimport type { Ctx, Session } from './store.js'\nimport {\n BINARY_READ_CAP,\n READ_CAP,\n appendArchiveEntries,\n archiveRecords,\n autoArchiveStale,\n parseArchive,\n policyOf,\n readArchiveText,\n resolveTarget,\n saveBucket,\n} from './store.js'\nimport { mkdir, readFile, rm, writeFile, readdir } from 'node:fs/promises'\nimport { basename, join } from 'node:path'\nimport { archiveEntryFor, markDecision, recordResolved, reconstructOriginal } from './model.js'\nimport type { Registry } from './registry.js'\nimport { bucketOf, cwdOf, sessionOf } from './registry.js'\nimport type { SearchOrchestrator } from './search/orchestrator.js'\nimport { newSearcher } from './search/orchestrator.js'\nimport type { ContentSearcher } from './search/content.js'\nimport { newContentSearcher } from './search/content.js'\nimport { restoreFile, revertCall, revertHunk } from './revert.js'\nimport { rulesList, rulesRead, rulesRemove, rulesSave, rulesToggle } from './rules.js'\nimport { isSnippetFilePath, snippetsEntries, snippetsList, snippetsRead, snippetsRemove, snippetsSave } from './snippets.js'\nimport { listMcp, refreshMcp, removeMcp, saveMcp, toggleMcp } from './mcp.js'\nimport { listProjects, projectRefresh, projectRemove, projectSave, projectToggle } from './mcpProject.js'\nimport { normalizeFileOpenTool, FILE_OPEN_DEFAULT, FILE_OPEN_SETTINGS_NS } from './fileOpenSettings.js'\nimport { INTEGRATION_BASE_DEFAULT } from './shared/integration.js'\nimport { shellMenuRegister, shellMenuRemove, shellMenuStatus } from './integrate.js'\nimport { unityAdd, unityInstall, unityList, unityRemove } from './unityBridge.js'\nimport { handoffOpen, pendingState, pollPending } from './externalHandoff.js'\nimport { buildReport } from './compat.js'\nimport { findProfileDir, readDevForm, setDevForm } from './devForm.js'\nimport { normalizeRel } from './tree.js'\nimport { invalidateIndex, listDirCached } from './treeIndex.js'\nimport { revealInExplorer } from './reveal.js'\nimport { dshHome } from './paths.js'\nimport { debugRecord } from './debugLog.js'\nimport { markActiveSessions, moveOutSessions, planMoveOut, purgeArchive, restoreSession, scanSessionInventory, sessionsArchiveRoot, sessionSizeOf, sidecarSummaryOf } from './perf.js'\nimport { patchHasPerfConfig, patchInsertPerfConfig, patchRemovePerfConfig, perfConfigBlock } from './perfPatch.js'\n\n/** cwd → 上次 stale 自动清理时间:全量轮询(EditorView/DiffBadge/Dock 各自 5s)节流,避免每轮都读文件算指纹。 */\nconst staleCheckedAt = new Map<string, number>()\n/** stale 自动清理最小间隔。 */\nconst STALE_CHECK_MIN_MS = 10_000\n\n/** 记录 → 客户端视图(不含 before 全文,仅长度)。 */\nfunction recView(record: DiffRecord): RecordView {\n return {\n callId: record.callId,\n toolName: record.toolName,\n path: record.path,\n beforeLen: typeof record.before === 'string' ? record.before.length : 0,\n create: record.create === true,\n callHunk: record.callHunk,\n hunks: record.hunks,\n decisions: record.decisions,\n note: record.note ?? null,\n superseded: record.superseded === true,\n after: record.after ?? null,\n baseFingerprint: record.baseFingerprint ?? null,\n afterFingerprint: record.afterFingerprint ?? null,\n conflict: record.conflict === true,\n legacy: record.legacy === true,\n at: record.at,\n }\n}\n\n/** 会话/工作区公共前置:返回 {session,cwd} 或错误文案。 */\nasync function requireSession(ctx: Ctx, sessionId: string | undefined): Promise<\n { session: Session; cwd: string } | { err: string }\n> {\n const session = sessionOf(ctx, sessionId)\n if (!session) return { err: '会话不存在' }\n const cwd = cwdOf(session)\n if (!cwd) return { err: '会话无工作区' }\n return { session, cwd }\n}\n\n/** 片段文件保存时的沙箱策略:用户显式 GUI 写操作,放开到 danger-full-access(镜像 rules.fullPolicy)。 */\nfunction snippetPolicy(ctx: Ctx): unknown {\n const svc = ctx.get('sandboxPolicy')\n if (!svc || typeof svc.resolve !== 'function') return undefined\n return svc.resolve({ mode: 'danger-full-access' })\n}\n\n/**\n * 片段文件路径解析:命中全局片段目录(~/.dsh/snippets)返回归一化绝对路径,否则 null。\n * 全局片段位于工作区之外,edrv.read / edrv.save 需绕开 resolveTarget 的 cwd 语义直读直写。\n * @author ddj 2026年09月10号\n * @param path 客户端请求路径(绝对路径)\n * @returns 归一化后的绝对路径或 null\n */\nfunction snippetTargetOf(path: string): string | null {\n return isSnippetFilePath(path) ? path.replace(/\\\\/g, '/') : null\n}\n\n/**\n * 手动保存收尾(edrv.save / edrv.saveBinary 共用):目录树失效 + 该路径 pending\n * 文本差异记录标记 superseded 并归档(旧文本 diff 不得再应用到新内容上)。\n * @author ddj 2026年09月22号\n * @param ctx DSH 上下文\n * @param registry 差异记录桶注册表\n * @param sc requireSession 成功结果(session + cwd)\n * @param path 保存的文件路径\n */\nasync function afterManualSave(\n ctx: Ctx,\n registry: Registry,\n sc: { session: Session; cwd: string },\n path: string,\n): Promise<void> {\n // 手动保存后目录树可能变化(新建/删除文件):父目录+祖先进失效,后台自愈。\n invalidateIndex(ctx, sc.cwd, path)\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n let changed = false\n for (const rec of bucket.values()) {\n if (rec.path === path && rec.superseded !== true) { rec.superseded = true; rec.at = new Date().toISOString(); changed = true }\n }\n if (changed) {\n const done: DiffRecord[] = []\n for (const rec of bucket.values()) if (rec.path === path && rec.superseded) done.push(rec)\n if (done.length) await archiveRecords(ctx, sc.session, sc.cwd, bucket, done, '被手动编辑覆盖')\n else await saveBucket(ctx, sc.cwd, bucket, sc.session)\n }\n}\n\n/**\n * 批量决策核心:一次会话/桶解析 + 逐项处理 + 统一落盘(accept/reject 单条与 decideBatch 共用)。\n * rejected 项先做回滚,失败记入该项 error 且不改决策;本批次新增\"已解决\"记录一次性归档,\n * 有任何成功项则整桶只写盘一次,避免逐条读写整个 sidecar。\n * @author ddj 2026年08月25号\n * @param items 决策项(按数组顺序处理,rejected 的先后即回滚顺序)\n * @returns 逐项结果(ok 项含更新后的记录视图)\n */\nasync function applyDecisions(\n ctx: Ctx,\n session: Session,\n cwd: string,\n bucket: Map<string, DiffRecord>,\n items: DecideItem[],\n): Promise<DecideResult[]> {\n const results: DecideResult[] = []\n const resolved: DiffRecord[] = []\n let changed = false\n for (const item of items) {\n const record = bucket.get(item.callId)\n if (!record) {\n results.push({ callId: item.callId, ok: false, error: '记录不存在' })\n continue\n }\n if (item.decision === 'rejected') {\n const scope: RpcScope = item.scope ?? 'call'\n const outcome = scope === 'hunk' ? await revertHunk(ctx, session, record, item.hunkIndex ?? -1) : await revertCall(ctx, session, record)\n if (!outcome.ok) {\n results.push({ callId: item.callId, ok: false, error: outcome.error })\n continue\n }\n }\n const wasResolved = recordResolved(record)\n markDecision(record, item.scope ?? 'call', item.hunkIndex, item.decision)\n changed = true\n if (!wasResolved && recordResolved(record)) resolved.push(record)\n results.push({ callId: item.callId, ok: true, record: recView(record) })\n }\n if (resolved.length) {\n const reason = items.some((item) => item.decision === 'rejected') ? '已处理(回滚)' : '已处理'\n await archiveRecords(ctx, session, cwd, bucket, resolved, reason, { deferSave: true })\n }\n if (changed) await saveBucket(ctx, cwd, bucket, session)\n return results\n}\n\n/** 当前活跃会话 id 集合(live sessions,用于移出/恢复护栏)。 */\nfunction activeSessionIds(ctx: Ctx): Set<string> {\n const sessions = ctx.get('sessions')\n if (!sessions || typeof sessions.list !== 'function') return new Set()\n return new Set((sessions.list() as Session[]).map((s) => s.id).filter(Boolean))\n}\n\n/** profile patch 文件定位(依赖本插件的 profile,同 devForm)。 */\nasync function patchFileInfo(): Promise<{ profileDir?: string; patchPath?: string }> {\n const profileDir = findProfileDir()\n if (!profileDir) return {}\n return { profileDir, patchPath: join(profileDir, 'cordis.patch.yml') }\n}\n\n/** 最新一次压缩配置备份文件名(cordis.patch.yml.bak-<ts>,按名倒序取新)。 */\nasync function latestPatchBackup(patchPath: string): Promise<string | undefined> {\n const dir = join(patchPath, '..')\n const base = basename(patchPath)\n const names = await readdir(dir).catch(() => [])\n return names.filter((n) => n.startsWith(base + '.bak-')).sort().reverse()[0]\n}\n\n/** 读取设置中的深链基址(缺省/非法回退默认 3080)。 */\nasync function integrationBaseUrlOf(ctx: Ctx): Promise<string> {\n const settings = ctx.get('settings')\n const descriptor = settings?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const value = descriptor?.value as { integrationBaseUrl?: unknown } | undefined\n const raw = typeof value?.integrationBaseUrl === 'string' ? value.integrationBaseUrl.trim() : ''\n return raw || INTEGRATION_BASE_DEFAULT\n}\n\n/** 各方法 handler 表(类型由 shared/rpc 的 RpcHandlerMap 约束)。 */\nexport function buildHandlers(\n ctx: Ctx,\n registry: Registry,\n searcher = newSearcher(ctx),\n contentSearcher = newContentSearcher(ctx),\n lspHandlers?: Partial<RpcHandlerMap>,\n aiHandlers?: Partial<RpcHandlerMap>,\n): RpcHandlerMap {\n return {\n // edrv.lsp.* 由 createLspRpc 一次性提供(tracker 跨请求保留),这里并入。\n ...((lspHandlers ?? {}) as RpcHandlerMap),\n // edrv.ai.* 由 createAiRpc 提供(AI 内联补全/模型目录/配置读写),这里并入。\n ...((aiHandlers ?? {}) as RpcHandlerMap),\n 'edrv.list': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const want = Array.isArray(args.callIds) ? new Set(args.callIds) : null\n // 全量轮询时自动清理 stale 幽灵差异(批量决策后的即时刷新可 skipStale 跳过);\n // 三个组件各自 5s 全量 list,stale 检查节流到 STALE_CHECK_MIN_MS 一次,\n // 避免每轮都对全部记录读文件 + 算指纹(keepall 期间多组件同时刷新的主要 host 开销)。\n if (!want && args.skipStale !== true) {\n const now = Date.now()\n if (now - (staleCheckedAt.get(sc.cwd) ?? 0) > STALE_CHECK_MIN_MS) {\n staleCheckedAt.set(sc.cwd, now)\n await autoArchiveStale(ctx, sc.session, sc.cwd, bucket)\n }\n }\n const out: RecordView[] = []\n for (const rec of bucket.values()) {\n // 面板全量查询过滤已归档;聊天条按 callId 查询保留(状态徽章仍需正确显示)\n if (!want && rec.archived) continue\n if (want && !want.has(rec.callId)) continue\n out.push(recView(rec))\n }\n out.sort((a, b) => (a.at < b.at ? -1 : 1))\n return { ok: true, records: out }\n },\n 'edrv.accept': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const results = await applyDecisions(ctx, sc.session, sc.cwd, bucket, [{ callId: args.callId, scope: args.scope, hunkIndex: args.hunkIndex, decision: 'accepted' }])\n const item = results[0]\n if (!item?.ok) return { ok: false, error: item?.error ?? '操作失败' }\n return { ok: true, record: item.record! }\n },\n 'edrv.reject': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const results = await applyDecisions(ctx, sc.session, sc.cwd, bucket, [{ callId: args.callId, scope: args.scope, hunkIndex: args.hunkIndex, decision: 'rejected' }])\n const item = results[0]\n if (!item?.ok) return { ok: false, error: item?.error ?? '操作失败' }\n return { ok: true, record: item.record! }\n },\n 'edrv.decideBatch': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const results = await applyDecisions(ctx, sc.session, sc.cwd, bucket, Array.isArray(args.items) ? args.items : [])\n return { ok: true, results }\n },\n 'edrv.read': async (args) => {\n // 全局片段文件(~/.dsh/snippets/*.code-snippets)在工作区之外:直读,不走会话 cwd 解析\n const snippetTarget = snippetTargetOf(args.path)\n if (snippetTarget && args.encoding !== 'base64') {\n try {\n const content = await readFile(snippetTarget, 'utf8')\n return { ok: true, content, size: content.length }\n } catch (error) {\n return { ok: false, error: '读取片段文件失败:' + String(error), resolvedPath: snippetTarget }\n }\n }\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await resolveTarget(ctx, sc.session, args.path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') {\n // 带上解析后的真实路径:跳转失败时可直接看出是路径解析错还是目标本身不存在\n return { ok: false, error: '文件不存在', resolvedPath: fs.processPath(target) }\n }\n if ((info.size ?? 0) > BINARY_READ_CAP) return { ok: false, error: '文件过大(>32MB),不支持整文件预览' }\n if (args.encoding === 'base64') {\n // 图片/PDF 等二进制预览:readBytes 无解码、无二进制拒绝;超上限已由上方 stat 拦截\n const bytes = await fs.readBytes(target, undefined, BINARY_READ_CAP)\n const content = Buffer.from(bytes).toString('base64')\n return { ok: true, content, size: bytes.byteLength, encoding: 'base64', mime: binaryMimeOf(args.path) }\n }\n if ((info.size ?? 0) > READ_CAP) return { ok: false, error: '文件过大(>8MB),不支持整文件预览' }\n const content = await fs.readText(target)\n return { ok: true, content, size: content.length }\n } catch (error) {\n return { ok: false, error: '读取失败:' + String(error) }\n }\n },\n 'edrv.original': async (args) => {\n // 重建\"本批次修改前\"内容:DiffEditor 原始侧。仅反解 pending 块;\n // 全部反解失败时回退到最早记录的整体 before(若存在)。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await resolveTarget(ctx, sc.session, args.path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') return { ok: false, error: '文件不存在' }\n if ((info.size ?? 0) > READ_CAP) return { ok: false, error: '文件过大(>8MB),不支持差异重建' }\n const content = await fs.readText(target)\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const records = [...bucket.values()].filter((r) => r.path === args.path && !r.archived).sort((a, b) => (a.at < b.at ? -1 : 1))\n if (!records.length) return { ok: true, content, size: content.length, stale: [], fallback: false }\n const rebuilt = reconstructOriginal(records, content)\n if (rebuilt.stale.length && records[0].before !== null) {\n return { ok: true, content: records[0].before, size: records[0].before.length, stale: rebuilt.stale, fallback: true }\n }\n return { ok: true, content: rebuilt.content, size: rebuilt.content.length, stale: rebuilt.stale, fallback: false }\n } catch (error) {\n return { ok: false, error: '重建失败:' + String(error) }\n }\n },\n 'edrv.save': async (args) => {\n // 全局片段文件:直写(工作区外),且不进差异审查(片段变更不是 agent 编辑产物)\n const snippetTarget = snippetTargetOf(args.path)\n if (snippetTarget) {\n try {\n await writeFile(snippetTarget, args.content, 'utf8')\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '保存片段文件失败:' + String(error) }\n }\n }\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await resolveTarget(ctx, sc.session, args.path)\n await fs.writeText(target, args.content, void 0, void 0, policyOf(ctx, sc.session))\n await afterManualSave(ctx, registry, sc, args.path)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '保存失败:' + String(error) }\n }\n },\n 'edrv.saveBinary': async (args) => {\n if (args.encoding !== 'base64') return { ok: false, error: '仅支持 base64 编码' }\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await resolveTarget(ctx, sc.session, args.path)\n const info = await fs.stat(target)\n if (!info || info.type !== 'file') return { ok: false, error: '文件不存在' }\n // fs 服务仅提供文本写(writeText/editText),二进制回写经 node:fs 直写解析后的\n // 真实路径;以工作区边界 + 大小上限 + 用户显式保存动作三重约束兜底(对齐\n // revert.ts deleteCreated 的 contains 用法)。\n const rootTarget = await fs.resolve(policyOf(ctx, sc.session)?.workspaceRoot ?? '.', {})\n if (!fs.contains(rootTarget, target)) return { ok: false, error: '拒绝保存:目标不在会话工作区内' }\n const bytes = Buffer.from(args.content, 'base64')\n if (bytes.byteLength === 0) return { ok: false, error: '内容为空,拒绝写回' }\n if (bytes.byteLength > BINARY_READ_CAP) return { ok: false, error: '内容过大(>32MB),拒绝写回' }\n await writeFile(fs.processPath(target), bytes)\n await afterManualSave(ctx, registry, sc, args.path)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '二进制保存失败:' + String(error) }\n }\n },\n 'edrv.archiveList': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const batches = parseArchive(await readArchiveText(ctx, sc.cwd)).filter((b) => b.cwd === sc.cwd)\n const entries = batches.map((b) => {\n const recs = Array.isArray(b.records) ? b.records : []\n const sum = recs.reduce((s, r) => {\n const sm = r.summary || { accepted: 0, rejected: 0, pending: 0, superseded: false }\n s.accepted += sm.accepted || 0\n s.rejected += sm.rejected || 0\n s.pending += sm.pending || 0\n if (sm.superseded) s.superseded++\n return s\n }, { accepted: 0, rejected: 0, pending: 0, superseded: 0 })\n return { at: b.at, lastAt: b.lastAt || b.at, path: b.path, batch: b.batch ?? null, reason: b.reason ?? null, nRecords: recs.length, summary: sum }\n })\n entries.sort((a, b) => (Number(b.batch ?? -1) - Number(a.batch ?? -1)) || (a.at < b.at ? 1 : -1))\n return { ok: true, entries }\n },\n 'edrv.archiveRead': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const batchPath = args.path\n const batches = parseArchive(await readArchiveText(ctx, sc.cwd)).filter((b) => b.cwd === sc.cwd && (!batchPath || b.path === batchPath))\n return { ok: true, batches }\n },\n 'edrv.rollback': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n const batch = args.batch\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n let affected: DiffRecord[] = []\n let beforeRec: DiffRecord | null = null\n if (batch !== undefined) {\n const all = parseArchive(await readArchiveText(ctx, sc.cwd)).filter((b) => b.cwd === sc.cwd && b.path === args.path)\n const recs: DiffRecord[] = []\n for (const b of all) if (b.batch === batch) for (const r of (b.records || [])) recs.push(r as unknown as DiffRecord)\n if (!recs.length) return { ok: false, error: '归档中找不到该批次' }\n recs.sort((a, b2) => (a.at < b2.at ? -1 : 1))\n beforeRec = recs[0]\n affected = recs\n } else {\n for (const r of bucket.values()) if (r.path === args.path && !r.archived) affected.push(r)\n if (!affected.length) return { ok: false, error: '该文件没有可回滚的差异' }\n affected.sort((a, b2) => (a.at < b2.at ? -1 : 1))\n beforeRec = affected[0]\n }\n const rerr = await restoreFile(ctx, sc.session, beforeRec)\n if (rerr) return { ok: false, error: rerr }\n if (batch === undefined) {\n await archiveRecords(ctx, sc.session, sc.cwd, bucket, affected, '已回滚')\n } else {\n const all = parseArchive(await readArchiveText(ctx, sc.cwd)).filter((b) => b.cwd === sc.cwd && b.path === args.path && b.batch === batch)\n const sumRecs = all.reduce((s, b) => s + ((b.records || []).length), 0)\n const logRec = Object.assign({}, affected[0], { note: (affected[0].note ? affected[0].note + ';' : '') + '回滚至本批次前(批次 ' + batch + ')' })\n await appendArchiveEntries(ctx, sc.cwd, [archiveEntryFor([logRec], sc.cwd, '已回滚(批次 ' + batch + ',' + sumRecs + ' 条)')], sc.session)\n // 批次回滚恢复的是旧内容,文件当前活跃差异已失效,一并归档\n const activeRecs: DiffRecord[] = []\n for (const r of bucket.values()) if (r.path === args.path && !r.archived) activeRecs.push(r)\n if (activeRecs.length) await archiveRecords(ctx, sc.session, sc.cwd, bucket, activeRecs, '已回滚(批次回滚覆盖)')\n }\n return { ok: true, path: args.path, batch: batch ?? null }\n },\n 'edrv.debug': async (args) => {\n // 诊断日志:client 上报 → debugLog 模块缓冲批量落盘 ~/.dsh/dsh-vscode-mode/logs/\n // (console 不一定落盘,文件可靠)。只出现在调试开关开启时(client dbg 默认关)。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n debugRecord(ctx, sc.cwd, String(args.text ?? ''))\n return { ok: true }\n },\n 'edrv.searchFiles': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const bucket = await bucketOf(registry, ctx, sc.cwd)\n const activePaths: string[] = []\n for (const record of bucket.values()) if (record.path) activePaths.push(record.path)\n const result = await searcher.search({ session: sc.session, cwd: sc.cwd, query: args.query, activePaths })\n return { ok: true, ...result }\n },\n 'edrv.searchContent': async (args) => {\n // 工作区内容搜索:rg --json 主路径;provider 失败转错误响应(无 fallback)。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const result = await contentSearcher.search({\n session: sc.session,\n cwd: sc.cwd,\n query: args.query,\n matchCase: args.matchCase,\n wholeWord: args.wholeWord,\n regex: args.regex,\n maxResults: args.maxResults,\n include: args.include,\n exclude: args.exclude,\n })\n return { ok: true, ...result }\n } catch (error) {\n return { ok: false, error: '搜索失败:' + String(error) }\n }\n },\n 'edrv.listDir': async (args) => {\n // 目录树(侧边栏文件管理用):树索引命中直出(内存,0 IO);失效/force 时\n // 走快路径(resolve + listDirCheap + putIndex);同路径在途请求去重复用。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const rel = normalizeRel(args.path)\n if (rel === null) return { ok: false, error: '路径不合法' }\n const res = await listDirCached(ctx, sc.cwd, rel, args.force === true)\n if ('error' in res) return { ok: false, error: res.error }\n return { ok: true, root: res.root, path: rel, entries: res.entries }\n },\n 'edrv.revealInExplorer': async (args) => {\n // 在 OS 文件浏览器中打开/定位路径(树行/编辑器右键菜单用),相对工作区解析。\n const sc = await requireSession(ctx, args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const rel = normalizeRel(args.path)\n if (rel === null) return { ok: false, error: '路径不合法' }\n const target = await fs.resolve(rel || '.', { cwd: sc.cwd })\n const info = await fs.stat(target)\n if (!info) return { ok: false, error: '路径不存在' }\n const abs = fs.processPath(target)\n const outcome = await revealInExplorer(ctx, abs, info.type === 'directory')\n if (!outcome.ok) return { ok: false, error: outcome.error }\n return { ok: true, revealed: abs }\n } catch (error) {\n return { ok: false, error: '打开失败:' + String(error) }\n }\n },\n 'mcp.list': async () => ({ ok: true, ...listMcp(ctx) }),\n 'mcp.save': async (args) => {\n try { return { ok: true, server: await saveMcp(ctx, args.config) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.remove': async (args) => {\n try { await removeMcp(ctx, args.id); return { ok: true } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.toggle': async (args) => {\n try { return { ok: true, server: await toggleMcp(ctx, args.id, args.enabled) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.refresh': async (args) => {\n try { return { ok: true, server: await refreshMcp(ctx, args.id) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projects': async () => {\n try { return { ok: true, ...await listProjects(ctx) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projectSave': async (args) => {\n try { return { ok: true, project: await projectSave(ctx, args.workspacePath, args.serverName, args.config) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projectRemove': async (args) => {\n try { return { ok: true, project: await projectRemove(ctx, args.workspacePath, args.serverName) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projectToggle': async (args) => {\n try { return { ok: true, project: await projectToggle(ctx, args.workspacePath, args.serverName, args.enabled) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'mcp.projectRefresh': async (args) => {\n try { return { ok: true, project: await projectRefresh(ctx, args.workspacePath, args.serverName) } }\n catch (error) { return { ok: false, error: String(error) } }\n },\n 'vscode.fileOpenSettingsGet': async () => {\n const settings = ctx.get('settings')\n const descriptor = settings?.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const value = descriptor?.value as { fileOpenTool?: unknown } | undefined\n return { ok: true, fileOpenTool: normalizeFileOpenTool(value?.fileOpenTool ?? FILE_OPEN_DEFAULT), integrationBaseUrl: await integrationBaseUrlOf(ctx), revision: descriptor?.revision }\n },\n 'vscode.fileOpenSettingsUpdate': async (args) => {\n const settings = ctx.get('settings')\n if (!settings?.update) return { ok: false, error: '设置服务不可用' }\n try {\n const patch: Record<string, unknown> = { fileOpenTool: normalizeFileOpenTool(args.fileOpenTool) }\n if (typeof args.integrationBaseUrl === 'string' && args.integrationBaseUrl.trim()) patch.integrationBaseUrl = args.integrationBaseUrl.trim()\n await settings.update(FILE_OPEN_SETTINGS_NS, patch, args.expectedRevision)\n const descriptor = settings.describe?.({ redactSecrets: true })?.find((item: { ns?: string }) => item.ns === FILE_OPEN_SETTINGS_NS)\n const value = descriptor?.value as { fileOpenTool?: unknown } | undefined\n return { ok: true, fileOpenTool: normalizeFileOpenTool(value?.fileOpenTool), integrationBaseUrl: await integrationBaseUrlOf(ctx), revision: descriptor?.revision }\n } catch (error) { return { ok: false, error: String(error) }\n }\n },\n 'compat': async () => ({ ok: true, report: await buildReport(ctx) }),\n 'vscode.devFormGet': async () => ({ ok: true, devForm: readDevForm() }),\n 'vscode.devFormSet': async (args) => {\n try {\n const result = await setDevForm(ctx, args.enabled === true, args.path)\n if (!result.ok) return { ok: false, error: result.error ?? '切换开发形态失败' }\n return { ok: true, devForm: readDevForm(), restart: result.restart }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.integration.status': async () => {\n try {\n return { ok: true, ...(await shellMenuStatus(ctx, await integrationBaseUrlOf(ctx))) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.integration.register': async () => {\n try {\n return { ok: true, ...(await shellMenuRegister(ctx, await integrationBaseUrlOf(ctx))) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.integration.unregister': async () => {\n try {\n return { ok: true, ...(await shellMenuRemove(ctx, await integrationBaseUrlOf(ctx))) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.unity.list': async () => {\n try {\n return { ok: true, ...(await unityList()) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.unity.add': async (args) => {\n try {\n return { ok: true, project: await unityAdd(args.path) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.unity.remove': async (args) => {\n try {\n await unityRemove(args.path)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.unity.install': async (args) => {\n try {\n return { ok: true, project: await unityInstall(args.path) }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.externalStat': async (args) => {\n // 深链判型(无会话依赖):绝对路径直过 resolve;缺失/其他类型归入 missing\n const fs = ctx.get('fs')\n if (!fs) return { ok: false, error: '缺少 fs' }\n try {\n const target = await fs.resolve(args.path)\n const info = await fs.stat(target)\n if (!info || info.type === 'other') return { ok: true, kind: 'missing' }\n return { ok: true, kind: info.type === 'directory' ? 'directory' : 'file' }\n } catch (error) {\n return { ok: false, error: String(error) }\n }\n },\n 'edrv.external.handoff': async (args) => ({\n ok: true,\n ...handoffOpen({ paths: args.paths, line: args.line, column: args.column }),\n }),\n 'edrv.external.pending': async () => ({ ok: true, open: pollPending() }),\n 'edrv.external.pendingState': async (args) => ({\n ok: true,\n delivered: pendingState(args.token, args.take === true).delivered,\n }),\n 'edrv.perf.inventory': async () => {\n try {\n const home = dshHome()\n const inventory = await scanSessionInventory(home, sessionsArchiveRoot(home))\n const active = activeSessionIds(ctx)\n markActiveSessions(inventory.sessions, active)\n return { ok: true, ...inventory, activeIds: [...active] }\n } catch (error) {\n return { ok: false, error: '盘点失败:' + String(error) }\n }\n },\n 'edrv.perf.sessionSize': async (args) => {\n try {\n const size = await sessionSizeOf(dshHome(), args.cwd, args.sessionId ?? '')\n return { ok: true, ...size }\n } catch (error) {\n return { ok: false, error: '读取会话体积失败:' + String(error) }\n }\n },\n 'edrv.perf.movePlan': async (args) => {\n try {\n const home = dshHome()\n const inventory = await scanSessionInventory(home, sessionsArchiveRoot(home))\n markActiveSessions(inventory.sessions, activeSessionIds(ctx))\n const plan = planMoveOut(inventory, { workspaceKey: args.workspaceKey, sessionIds: args.sessionIds, minBytes: args.minBytes, olderThanDays: args.olderThanDays })\n return { ok: true, ...plan }\n } catch (error) {\n return { ok: false, error: '移出规划失败:' + String(error) }\n }\n },\n 'edrv.perf.moveOut': async (args) => {\n try {\n const home = dshHome()\n const items = (args.sessionIds ?? []).map((sessionId) => ({ workspaceKey: args.workspaceKey, sessionId, bytes: 0 }))\n const result = await moveOutSessions(home, sessionsArchiveRoot(home), items, activeSessionIds(ctx), args.dryRun === true)\n return { ok: true, ...result }\n } catch (error) {\n return { ok: false, error: '移出失败:' + String(error) }\n }\n },\n 'edrv.perf.restore': async (args) => {\n try {\n const result = await restoreSession(dshHome(), sessionsArchiveRoot(dshHome()), args.workspaceKey, args.sessionId)\n return result.ok ? { ok: true, restored: true } : { ok: false, error: result.error ?? '恢复失败' }\n } catch (error) {\n return { ok: false, error: '恢复失败:' + String(error) }\n }\n },\n 'edrv.perf.purgeArchive': async (args) => {\n try {\n const result = await purgeArchive(sessionsArchiveRoot(dshHome()), args.olderThanDays)\n return { ok: true, ...result }\n } catch (error) {\n return { ok: false, error: '清除失败:' + String(error) }\n }\n },\n 'edrv.perf.sidecarSummary': async (args) => {\n const sc = await requireSession(ctx, args.sessionId)\n const cwd = 'err' in sc ? null : sc.cwd\n try {\n const summary = await sidecarSummaryOf(ctx, cwd)\n return { ok: true, ...summary }\n } catch (error) {\n return { ok: false, error: '读取侧车摘要失败:' + String(error) }\n }\n },\n 'edrv.perf.configGet': async () => {\n try {\n const { profileDir, patchPath } = await patchFileInfo()\n const block = perfConfigBlock()\n if (!patchPath) return { ok: true, applied: false, block }\n const text = await readFile(patchPath, 'utf8').catch(() => '')\n const backup = await latestPatchBackup(patchPath)\n return { ok: true, profileDir, patchPath, applied: patchHasPerfConfig(text), block, backup }\n } catch (error) {\n return { ok: false, error: '读取压缩配置失败:' + String(error) }\n }\n },\n 'edrv.perf.configApply': async () => {\n try {\n const { patchPath } = await patchFileInfo()\n if (!patchPath) return { ok: false, error: '未找到依赖本插件的 profile(检查 DSH_HOME/profiles)' }\n const text = await readFile(patchPath, 'utf8').catch(() => '')\n const backup = patchPath + '.bak-' + Date.now()\n if (text) await writeFile(backup, text, 'utf8')\n await mkdir(join(patchPath, '..'), { recursive: true })\n await writeFile(patchPath, patchInsertPerfConfig(text), 'utf8')\n return { ok: true, applied: true, backup, restart: true }\n } catch (error) {\n return { ok: false, error: '写入压缩配置失败:' + String(error) }\n }\n },\n 'edrv.perf.configUndo': async () => {\n try {\n const { patchPath } = await patchFileInfo()\n if (!patchPath) return { ok: false, error: '未找到依赖本插件的 profile(检查 DSH_HOME/profiles)' }\n const backup = await latestPatchBackup(patchPath)\n if (backup) {\n const backupPath = join(join(patchPath, '..'), backup)\n const saved = await readFile(backupPath, 'utf8').catch(() => null)\n if (saved !== null) {\n await writeFile(patchPath, saved, 'utf8')\n await rm(backupPath, { force: true }).catch(() => {})\n return { ok: true, restored: true, backup }\n }\n }\n const text = await readFile(patchPath, 'utf8').catch(() => '')\n if (!patchHasPerfConfig(text)) return { ok: false, error: '没有可撤销的压缩配置' }\n await writeFile(patchPath, patchRemovePerfConfig(text), 'utf8')\n return { ok: true, restored: true }\n } catch (error) {\n return { ok: false, error: '撤销压缩配置失败:' + String(error) }\n }\n },\n 'rules.list': async () => {\n try {\n return { ok: true, ...(await rulesList(ctx)) }\n } catch (error) {\n return { ok: false, error: '读取规则失败:' + String(error) }\n }\n },\n 'rules.read': async (args) => {\n try {\n return { ok: true, content: await rulesRead(ctx, args) }\n } catch (error) {\n return { ok: false, error: '读取规则失败:' + String(error) }\n }\n },\n 'rules.save': async (args) => {\n try {\n return { ok: true, rule: await rulesSave(ctx, args) }\n } catch (error) {\n return { ok: false, error: '保存规则失败:' + String(error) }\n }\n },\n 'rules.remove': async (args) => {\n try {\n await rulesRemove(ctx, args)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '删除规则失败:' + String(error) }\n }\n },\n 'rules.toggle': async (args) => {\n try {\n return { ok: true, rule: await rulesToggle(ctx, args, args.enabled === true) }\n } catch (error) {\n return { ok: false, error: '切换规则失败:' + String(error) }\n }\n },\n 'snippets.list': async () => {\n try {\n return { ok: true, ...(await snippetsList(ctx)) }\n } catch (error) {\n return { ok: false, error: '读取代码片段失败:' + String(error) }\n }\n },\n 'snippets.read': async (args) => {\n try {\n return { ok: true, content: await snippetsRead(ctx, args) }\n } catch (error) {\n return { ok: false, error: '读取代码片段失败:' + String(error) }\n }\n },\n 'snippets.save': async (args) => {\n try {\n return { ok: true, file: await snippetsSave(ctx, args) }\n } catch (error) {\n return { ok: false, error: '保存代码片段失败:' + String(error) }\n }\n },\n 'snippets.remove': async (args) => {\n try {\n await snippetsRemove(ctx, args)\n return { ok: true }\n } catch (error) {\n return { ok: false, error: '删除代码片段失败:' + String(error) }\n }\n },\n 'snippets.entries': async (args) => {\n try {\n // 当前会话工作区用于叠加项目片段;会话缺失时仅返回全局片段(不报错,补全仍可用)\n const sc = await requireSession(ctx, args.sessionId)\n const cwd = 'err' in sc ? undefined : sc.cwd\n return { ok: true, ...(await snippetsEntries(ctx, cwd)) }\n } catch (error) {\n return { ok: false, error: '读取代码片段条目失败:' + String(error) }\n }\n },\n }\n}\n\n/**\n * 统一入口:按方法分发到 handler 表。\n * @author ddj 2026年08月20号 / 2026年08月26号\n */\nexport async function handleRpc<M extends RpcMethod>(\n ctx: Ctx,\n registry: Registry,\n method: M,\n args: RpcRequestMap[M],\n searcher = newSearcher(ctx),\n contentSearcher = newContentSearcher(ctx),\n lspHandlers?: Partial<RpcHandlerMap>,\n aiHandlers?: Partial<RpcHandlerMap>,\n): Promise<RpcResult<M>> {\n const handlers = buildHandlers(ctx, registry, searcher, contentSearcher, lspHandlers, aiHandlers)\n const handler = handlers[method]\n if (!handler) return { ok: false, error: '未知方法: ' + String(method) } as RpcResult<M>\n return handler(args)\n}\n","/**\n * dsh-vscode-mode host — 项目 MCP 的 agent 级隔离。\n * 项目 MCP 连接仍由 Host 维护,但每个 agent 只继承当前 workspace 的项目工具;\n * tools.restrict() 负责模型可见性,tools.guard() 负责执行层兜底拒绝。\n * 作者 ddj 2026年08月22号\n */\nimport { LEGACY_PROJECT_PREFIX, entryHash, isProjectEntryId } from './compat.js'\nimport { entriesOf } from './mcp.js'\nimport { hashWorkspace } from './mcpProject.js'\nimport type { Ctx } from './store.js'\nimport { log } from './log.js'\n\nconst UNKNOWN_PROJECT = '__unknown_project__'\n\ntype ToolProjects = Map<string, string>\ntype AgentState = { dispose?: () => void; denyKey: string }\n\n/** 统一 workspace 路径,供 cwd 父路径匹配。 */\nexport function normalizePath(path: string): string {\n const value = String(path ?? '').replace(/\\\\/g, '/').replace(/\\/+/g, '/')\n return value.replace(/\\/$/, '').toLowerCase()\n}\n\n/** 在已注册 workspace 中匹配 cwd,优先最长父路径。 */\nexport function matchWorkspace(cwd: string | undefined, paths: string[]): string | undefined {\n if (!cwd) return undefined\n const target = normalizePath(cwd)\n const matches = paths.filter((path) => {\n const root = normalizePath(path)\n return target === root || target.startsWith(root + '/')\n })\n matches.sort((a, b) => normalizePath(b).length - normalizePath(a).length)\n return matches[0]\n}\n\n/** 根据 entry id 判断是否为新旧格式项目 MCP(兼容层统一判定)。 */\nexport const isProjectEntry = isProjectEntryId\n\n/** 兼容:旧版前缀常量名(mcpIsolation 历史导出,语义不变)。 */\nexport const LEGACY_PREFIX = LEGACY_PROJECT_PREFIX\n\n/** 返回一个 agent 不应继承的项目工具名。 */\nexport function denyTools(toolProjects: ToolProjects, currentPath: string | undefined): string[] {\n return [...toolProjects.entries()].filter(([, owner]) => owner !== currentPath).map(([name]) => name).sort()\n}\n\n/** 从 loader entry 和工具注册表建立工具到项目路径的映射。 */\nfunction projectTools(ctx: Ctx): ToolProjects {\n const result: ToolProjects = new Map()\n const registry = ctx.get('workspaceRegistry')\n const workspaces = registry?.list?.() ?? []\n const byHash: Map<string, string> = new Map(workspaces.map((ws: { path: string }) => [hashWorkspace(ws.path), ws.path] as [string, string]))\n const visible = ctx.get('tools')?.view?.(void 0)?.visible\n if (!(visible instanceof Map)) return result\n for (const entry of entriesOf(ctx)) {\n const id = String(entry.id ?? entry.options?.id ?? '')\n if (!isProjectEntry(id)) continue\n const hash = entryHash(id)\n const owner = hash ? byHash.get(hash) ?? UNKNOWN_PROJECT : UNKNOWN_PROJECT\n const serverName = entry.options?.config?.serverName\n if (typeof serverName !== 'string') continue\n const prefix = `mcp__${serverName}__`\n for (const name of visible.keys()) if (String(name).startsWith(prefix)) result.set(String(name), owner)\n }\n return result\n}\n\n/** 取得 agent 当前 cwd 所属 workspace。 */\nfunction agentWorkspace(ctx: Ctx, agent: any): string | undefined {\n const cwd = agent?.session?.header?.cwd\n const paths = (ctx.get('workspaceRegistry')?.list?.() ?? []).map((ws: { path: string }) => ws.path)\n return matchWorkspace(cwd, paths)\n}\n\n/** 同步一个 agent 的项目工具 deny 列表。 */\nfunction syncAgent(ctx: Ctx, state: AgentState, agent: any, tools: ToolProjects): void {\n const current = agentWorkspace(ctx, agent)\n const denied = denyTools(tools, current)\n const nextKey = denied.join('\\n')\n if (state.denyKey === nextKey) return\n state.dispose?.()\n state.dispose = undefined\n if (denied.length > 0) {\n try {\n state.dispose = agent.ctx.tools.restrict({ deny: denied })\n } catch (error) {\n log.warn('MCP agent restriction failed: ' + String(error))\n return\n }\n }\n state.denyKey = nextKey\n}\n\n/** 为当前 Host 安装项目 MCP 的 agent restriction 与执行 guard。 */\nexport function installIsolation(ctx: Ctx): void {\n const tools = ctx.get('tools')\n const agents = ctx.get('agents')\n if (!tools || !agents) return\n const states = new Map<any, AgentState>()\n let toolProjects = projectTools(ctx)\n let scheduled = false\n let syncing = false\n\n const syncAll = () => {\n if (syncing) return\n syncing = true\n try {\n toolProjects = projectTools(ctx)\n for (const agent of agents.list?.() ?? []) {\n const state = states.get(agent) ?? { denyKey: '' }\n states.set(agent, state)\n syncAgent(ctx, state, agent, toolProjects)\n }\n } finally {\n syncing = false\n }\n }\n const scheduleSync = () => {\n if (scheduled) return\n scheduled = true\n queueMicrotask(() => {\n scheduled = false\n syncAll()\n })\n }\n const onCreated = ctx.on('agent/created', ({ agent }: { agent: any }) => {\n const state = { denyKey: '' }\n states.set(agent, state)\n syncAgent(ctx, state, agent, toolProjects)\n })\n const onDisposed = ctx.on('agent/disposed', ({ agent }: { agent: any }) => {\n const state = states.get(agent)\n state?.dispose?.()\n states.delete(agent)\n })\n const onToolsChange = ctx.on('tools/change', scheduleSync)\n const stopGuard = tools.guard((exec: any) => {\n const owner = toolProjects.get(String(exec?.name ?? ''))\n if (!owner) return undefined\n const current = agentWorkspace(ctx, exec.agent)\n if (owner === current) return undefined\n return current === undefined\n ? '项目 MCP 需要在已注册工作区的对话中使用'\n : '已拒绝:当前对话工作区不能使用其他项目的 MCP'\n })\n syncAll()\n ctx.effect(() => () => {\n onCreated?.()\n onDisposed?.()\n onToolsChange?.()\n stopGuard?.()\n for (const state of states.values()) state.dispose?.()\n states.clear()\n }, 'vscode-mode:mcp-isolation')\n}\n","/**\n * dsh-vscode-mode host — 工作区文件清单扫描与缓存(快速打开/搜索用)。\n * 迁移自原 src/index.ts 的 listWorkspaceFiles,语义不改。\n * 作者 ddj 2026-08-20\n */\nimport type { Ctx, Session } from './store.js'\nimport { policyOf } from './store.js'\nimport { log } from './log.js'\n\n/** 文件清单缓存 TTL 与扫描上限(避免大工作区反复全量扫描)。 */\nconst FILE_INDEX_TTL = 60_000\nconst SCAN_CAP = 6000\n/** cwd → { at, files }(随会话销毁清理)。 */\nconst fileIndex = new Map<string, { at: number; files: string[] }>()\n\n/**\n * 扫描工作区文件清单(快速打开/搜索用):subprocess(Windows powershell / POSIX find),\n * 排除常见重目录,容量上限 SCAN_CAP;结果缓存(TTL FILE_INDEX_TTL)。失败返回 null。\n * @author ddj 2026年08月20号\n * @param ctx DSH 上下文\n * @param session 会话(取工作区根)\n * @param cwd 工作区目录\n * @returns 绝对路径清单;不可用(无 subprocess/fs)或扫描失败返回 null\n */\nexport async function listWorkspaceFiles(ctx: Ctx, session: Session, cwd: string): Promise<string[] | null> {\n const cached = fileIndex.get(cwd)\n if (cached && Date.now() - cached.at < FILE_INDEX_TTL) return cached.files\n const sub = ctx.get('subprocess')\n const fs = ctx.get('fs')\n if (!sub || !fs) return null\n const policy = policyOf(ctx, session)\n let root: string\n try {\n const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', {})\n root = fs.processPath(rootTarget)\n } catch (error) {\n root = cwd\n }\n const lines: string[] = []\n const run = async (argv: string[]): Promise<void> => {\n const handle = sub.spawn({\n argv,\n stdio: { stdout: { maxBytes: 8 << 20 }, stderr: { maxBytes: 1 << 16 }, stdin: 'ignore' },\n graceMs: 20000,\n })\n const outcome = await handle.done\n const code = outcome?.exitCode ?? outcome?.code\n if (code !== 0) throw new Error('scan exit ' + code)\n const text = handle.collected?.stdout?.readFrom(0).text ?? ''\n for (const ln of text.split(/\\r?\\n/)) {\n const s = ln.trim()\n if (s) lines.push(s)\n }\n }\n try {\n if (process.platform === 'win32') {\n const cmd = 'Get-ChildItem -LiteralPath \"' + String(root).replace(/\"/g, '\"\"') + '\" -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $_.FullName -notmatch \\'(node_modules|\\\\.git|\\\\.tmp|\\\\.cache|dist|build|vendor|coverage|__pycache__)\\' } | Select-Object -First ' + SCAN_CAP + ' | ForEach-Object { $_.FullName }'\n await run(['powershell', '-NoProfile', '-NonInteractive', '-Command', cmd])\n } else {\n const cmd = 'find ' + JSON.stringify(root) + ' -type f -not -path \\'*/node_modules/*\\' -not -path \\'*/.git/*\\' -not -path \\'*/.tmp/*\\' -not -path \\'*/.cache/*\\' -not -path \\'*/dist/*\\' -not -path \\'*/build/*\\' -not -path \\'*/vendor/*\\' -not -path \\'*/coverage/*\\' 2>/dev/null | head -n ' + SCAN_CAP\n await run(['/bin/sh', '-c', cmd])\n }\n } catch (error) {\n log.error('scan failed: ' + String(error))\n return null\n }\n const files = lines.slice(0, SCAN_CAP)\n if (files.length) fileIndex.set(cwd, { at: Date.now(), files })\n return files\n}\n\n/** 会话销毁时清理文件索引缓存。 */\nexport function dropFileIndex(cwd: string): void {\n fileIndex.delete(cwd)\n}\n","/**\n * dsh-vscode-mode host — LSP JSON-RPC 帧编解码(纯函数,node 可测)。\n * LSP over stdio 用 Content-Length 帧:\n * Content-Length: <n>\\r\\n\\r\\n<恰好 n 字节 JSON>\n * 导出:encodeMessage(对象→帧 Buffer)、createFrameParser(流式粘包/拆包)、parseFrame(单帧)。\n * 作者 ddj 2026-08-27\n */\n\nconst HEADER_END = '\\r\\n\\r\\n'\n\n/** 消息头正则(仅取 Content-Length;其它头忽略)。 */\nconst HEADER_RE = /^Content-Length:\\s*(\\d+)\\s*$/im\n\n/** 将对象编码为带 Content-Length 头的帧。 */\nexport function encodeMessage(message: unknown): Buffer {\n const body = JSON.stringify(message)\n const head = 'Content-Length: ' + Buffer.byteLength(body, 'utf8') + '\\r\\n\\r\\n'\n return Buffer.from(head + body, 'utf8')\n}\n\n/**\n * 尝试从 buffer 解析单个帧;成功返回 { body, rest },数据不足返回 null。\n * @author ddj 2026年08月27号\n * @param buffer 已累积的字节\n * @returns 解析结果(rest 为剩余未消费字节)\n */\nexport function parseFrame(buffer: Buffer): { body: string; rest: Buffer } | null {\n const headEnd = buffer.indexOf(HEADER_END)\n if (headEnd < 0) return null\n const header = buffer.subarray(0, headEnd).toString('utf8')\n const m = HEADER_RE.exec(header)\n if (!m) {\n // 非法头:丢弃直到下一个帧头,避免死循环\n const next = buffer.indexOf('Content-Length:')\n return next >= 0 ? parseFrame(buffer.subarray(next)) : null\n }\n const length = Number(m[1])\n const bodyStart = headEnd + HEADER_END.length\n if (buffer.length < bodyStart + length) return null\n const body = buffer.subarray(bodyStart, bodyStart + length).toString('utf8')\n return { body, rest: buffer.subarray(bodyStart + length) }\n}\n\n/** 帧解析器:push 数据块,吐出完整消息(可能拆包后重组、也可能一包多帧)。 */\nexport function createFrameParser(): {\n push(chunk: Buffer): unknown[]\n clear(): void\n} {\n let buffer: Buffer = Buffer.alloc(0)\n return {\n push(chunk: Buffer): unknown[] {\n if (chunk.length) buffer = Buffer.concat([buffer, chunk]) as Buffer\n const out: unknown[] = []\n for (;;) {\n const parsed = parseFrame(buffer)\n if (!parsed) break\n buffer = parsed.rest\n try {\n out.push(JSON.parse(parsed.body))\n } catch (error) {\n out.push({ jsonrpc: '2.0', error: { code: -32700, message: 'Parse error: ' + String(error) }, id: null })\n }\n }\n return out\n },\n clear(): void {\n buffer = Buffer.alloc(0)\n },\n }\n}\n\n/** 构造标准 JSON-RPC 请求消息。 */\nexport function requestMessage(id: number, method: string, params: unknown): Record<string, unknown> {\n return { jsonrpc: '2.0', id, method, params }\n}\n\n/** 构造标准 JSON-RPC 通知消息(无 id,fire-and-forget)。 */\nexport function notifyMessage(method: string, params: unknown): Record<string, unknown> {\n return { jsonrpc: '2.0', method, params }\n}\n\n/** 构造标准 JSON-RPC 响应消息。 */\nexport function responseMessage(id: number | string | null, result: unknown, error?: unknown): Record<string, unknown> {\n if (error !== undefined) return { jsonrpc: '2.0', id, error }\n return { jsonrpc: '2.0', id, result }\n}\n","/**\n * dsh-vscode-mode host — LSP 语言服务器进程传输层。\n * 基于 node:child_process.spawn(stdio pipe 双向流)。刻意不用 DSH ctx.subprocess\n * 抽象:LSP 需要持续写 stdin + 流式读 stdout,而该抽象 stdin 不可写、输出为一次性收集。\n * 作者 ddj 2026-08-27\n */\nimport { spawn, type ChildProcess } from 'node:child_process'\nimport { createFrameParser } from './jsonrpc.js'\n\nconst STDERR_CAP = 256 << 10\n\nexport interface TransportSpec {\n argv: string[]\n cwd?: string\n env?: Record<string, string>\n}\n\nexport interface Transport {\n /** 写一行帧到 stdin(自动加换行)。 */\n write(chunk: Buffer): boolean\n /** 推送 stdout 解析出的原始消息(内部由帧解析器调用)。 */\n onMessage: ((message: unknown) => void) | null\n /** stderr 收集缓冲(有界,供诊断)。 */\n stderr(): string\n /** 进程退出/崩溃回调(code/signal)。 */\n onExit: ((code: number | null, signal: string | null) => void) | null\n /** 优雅关闭后强杀(Windows 下连带进程树)。 */\n dispose(): void\n /** 是否仍存活。 */\n readonly alive: boolean\n readonly pid: number | undefined\n}\n\nconst running = new Set<ChildProcess>()\n\n/** 当前仍在运行的 LSP 子进程(供 disposeAll / 诊断)。 */\nexport function liveChildren(): ReadonlySet<ChildProcess> {\n return running\n}\n\n/**\n * 启动语言服务器进程。\n * @author ddj 2026年08月27号\n * @param spec 启动参数(argv 数组,不经 shell,Windows 引号安全)\n * @param onMessage stdout 消息回调\n * @param logger 诊断日志(可选)\n * @returns 传输句柄\n */\nexport function spawnServer(spec: TransportSpec, onMessage: (message: unknown) => void, logger?: (line: string) => void): Transport {\n const { argv, cwd, env } = spec\n const child = spawn(argv[0], argv.slice(1), {\n cwd,\n env: { ...process.env, ...env },\n stdio: ['pipe', 'pipe', 'pipe'],\n windowsHide: true,\n })\n running.add(child)\n let stderrBuf = Buffer.alloc(0)\n let alive = true\n const parser = createFrameParser()\n\n child.stderr.on('data', (chunk: Buffer) => {\n if (stderrBuf.length < STDERR_CAP) {\n stderrBuf = Buffer.concat([stderrBuf, chunk], Math.min(stderrBuf.length + chunk.length, STDERR_CAP))\n }\n logger?.(chunk.toString('utf8'))\n })\n\n let exited = false\n const emitExit = (code: number | null, signal: string | null): void => {\n if (exited) return\n exited = true\n alive = false\n running.delete(child)\n transport.onExit?.(code, signal)\n }\n child.on('error', (error) => {\n logger?.('spawn error: ' + String(error))\n emitExit(null, null)\n })\n child.on('exit', (code, signal) => emitExit(code, signal))\n child.on('close', (code, signal) => emitExit(code, signal))\n\n const transport: Transport = {\n write(chunk: Buffer): boolean {\n if (!alive || !child.stdin.writable) return false\n child.stdin.write(chunk)\n return true\n },\n onMessage,\n stderr(): string {\n return stderrBuf.toString('utf8')\n },\n onExit: null,\n dispose(): void {\n if (!alive) return\n // 先 SIGTERM 让服务器有机会清理,1.5s 后强杀进程树\n child.kill()\n const timer = setTimeout(() => {\n if (!alive) return\n alive = false\n running.delete(child)\n try {\n if (process.platform === 'win32') {\n spawn('taskkill', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' })\n } else {\n child.kill('SIGKILL')\n }\n } catch (error) {\n logger?.('force kill error: ' + String(error))\n }\n }, 1500)\n timer.unref?.()\n },\n get alive() {\n return alive\n },\n get pid() {\n return child.pid\n },\n }\n // stdout 帧解析 → onMessage(LSP 响应/通知;onMessage 由 client 接管后动态生效)\n child.stdout.on('data', (chunk: Buffer) => {\n for (const message of parser.push(chunk)) transport.onMessage?.(message)\n })\n return transport\n}\n\n/** 强杀全部运行中的 LSP 子进程(插件卸载/退出用)。 */\nexport function disposeAllServers(): void {\n for (const child of running) {\n try {\n if (process.platform === 'win32' && child.pid) {\n spawn('taskkill', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' })\n } else {\n child.kill('SIGKILL')\n }\n } catch (error) {\n /* 忽略单个清理失败 */\n }\n }\n running.clear()\n}\n","/**\n * dsh-vscode-mode shared — 语言服务器 RPC 契约(双面,禁 node/react)。\n * LSP 请求/响应的 JSON 载荷形状 + 纯函数辅助(Monaco↔LSP 坐标换算等)。\n * 只描述\"过 RPC 的载荷\",宿主与语言服务器之间的帧级交互在 host 侧 src/lsp/ 内。\n * 作者 ddj 2026-08-27\n */\n\n/** LSP Position(0-based:line 行号从 0,character UTF-16 列从 0)。 */\nexport interface LspPosition {\n line: number\n character: number\n}\n\n/** LSP Range(start/end 均 0-based,包含 start、排除 end)。 */\nexport interface LspRange {\n start: LspPosition\n end: LspPosition\n}\n\n/** LSP Location:uri 为 file:// 绝对路径;root 用于还原为工作区相对路径。 */\nexport interface LspLocation {\n uri: string\n range: LspRange\n root?: string\n}\n\n/** 跳转结果(definition 常返回 LocationLink,归一化为 targetUri + targetRange + 可选 originSelectionRange)。 */\nexport interface LspLocationLink {\n targetUri: string\n targetRange: LspRange\n targetSelectionRange: LspRange\n originSelectionRange?: LspRange\n}\n\n/** 归一化后的符号(documentSymbol/workspaceSymbol 统一形状)。kind 为 LSP SymbolKind 数值。 */\nexport interface LspSymbol {\n name: string\n kind: number\n range: LspRange\n selectionRange: LspRange\n detail?: string\n containerName?: string\n children?: LspSymbol[]\n}\n\n/** hover 内容(markdown/纯文本行数组)。 */\nexport interface LspHover {\n contents: string[]\n range?: LspRange\n}\n\n/** LSP semantic token 标准类型(host 归一化后,client 与 Monaco 共用)。 */\nexport const LSP_SEMANTIC_TOKEN_TYPES = [\n 'namespace', 'type', 'class', 'enum', 'interface', 'struct', 'typeParameter',\n 'parameter', 'variable', 'property', 'enumMember', 'event', 'function', 'method',\n 'macro', 'label', 'comment', 'string', 'keyword', 'number', 'regexp', 'operator',\n 'decorator',\n] as const\n\n/** LSP semantic token 标准修饰符(host 归一化后,client 与 Monaco 共用)。 */\nexport const LSP_SEMANTIC_TOKEN_MODIFIERS = [\n 'declaration', 'definition', 'readonly', 'static', 'deprecated', 'abstract',\n 'async', 'modification', 'documentation', 'defaultLibrary', 'global', 'local', 'mutable',\n] as const\n\n/** 归一化后的 LSP semanticTokens/full 结果(data 使用 LSP delta 编码)。 */\nexport interface LspSemanticTokens {\n data: number[]\n resultId?: string\n}\n\n/** 语义 token 解码后的绝对范围(LSP 0-based;type 为插件固定 legend 与 type 名)。 */\nexport interface LspSemanticTokenRange {\n start: LspPosition\n end: LspPosition\n type: string\n modifiers: number\n}\n\n/** 语义 token 中可作为\"可导航标识符\"的类型(ctrl+hover 下划线判定用)。 */\nexport const LSP_NAVIGABLE_TOKEN_TYPES: ReadonlySet<string> = new Set([\n 'variable', 'parameter', 'property', 'function', 'method', 'class', 'enum',\n 'struct', 'interface', 'namespace', 'typeParameter', 'enumMember', 'event', 'type',\n])\n\n/**\n * 语义 token 是否属于可导航标识符。\n * @author ddj 2026年09月02号\n * @param type 语义 token 类型名(插件固定 legend)\n * @returns 是否可导航\n */\nexport function isNavigableTokenType(type: string): boolean {\n return LSP_NAVIGABLE_TOKEN_TYPES.has(type)\n}\n\n/**\n * 解码 LSP delta 编码的语义 token 流为绝对范围数组。\n * @author ddj 2026年09月02号\n * @param data 5 元组 delta 流(host normalizeSemanticData 产物,类型索引对应固定 legend)\n * @param types 固定 legend 类型表(缺省 LSP_SEMANTIC_TOKEN_TYPES)\n * @returns 绝对范围列表(保持文档顺序)\n */\nexport function decodeSemanticTokens(\n data: number[],\n types: readonly string[] = LSP_SEMANTIC_TOKEN_TYPES,\n): LspSemanticTokenRange[] {\n const out: LspSemanticTokenRange[] = []\n let line = 0\n let character = 0\n for (let i = 0; i + 4 < data.length; i += 5) {\n const deltaLine = data[i] ?? 0\n const deltaCharacter = data[i + 1] ?? 0\n const length = Math.max(0, data[i + 2] ?? 0)\n const typeIndex = data[i + 3] ?? 0\n const modifiers = data[i + 4] ?? 0\n line += deltaLine\n character = deltaLine === 0 ? character + deltaCharacter : deltaCharacter\n out.push({\n start: { line, character },\n end: { line, character: character + length },\n type: types[typeIndex] ?? 'variable',\n modifiers,\n })\n }\n return out\n}\n\n/** LSP 服务器能力子集:本插件会用到的方法。 */\nexport interface LspServerCapabilities {\n definition: boolean\n declaration: boolean\n references: boolean\n documentSymbol: boolean\n workspaceSymbol: boolean\n hover: boolean\n semanticTokens: boolean\n semanticTokenTypes?: string[]\n semanticTokenModifiers?: string[]\n}\n\n/** 服务器进程/会话状态。 */\nexport type LspServerPhase =\n | 'idle' // 未启动(惰性)\n | 'starting' // 启动中(initialize 握手)\n | 'ready' // 就绪\n | 'indexing' // 工作区索引中\n | 'unavailable' // 连续失败,停止自动重启\n | 'stopped' // 已停止(禁用/卸载/会话结束)\n\n/** 单条缺失环境需求(edrv.lsp.status.missingEnv 元素,仅含未满足项)。 */\nexport interface LspMissingEnv {\n id: string // 需求标识(如 dotnet-runtime:10,同时是安装器键)\n label: string // 显示名(如 '.NET 运行时 10.0')\n detail?: string // 说明(哪个服务器需要)\n installable: boolean // 支持一键安装\n manualUrl?: string // 官网手动下载地址\n manualLabel?: string\n}\n\n/** 环境安装进行态(edrv.lsp.envState 载荷元素)。 */\nexport interface LspEnvInstallState {\n id: string\n phase: 'idle' | 'downloading' | 'extracting' | 'done' | 'failed'\n message?: string\n}\n\n/** 同语言检测到的候选服务器(candidates 元素;chosen 标记当前选用者)。 */\nexport interface LspCandidate {\n name: string // 显示名(如 EmmyLua / LuaLS / Roslyn)\n version?: string // 扩展清单版本\n path?: string // 服务器入口路径(argv 比对用)\n chosen?: boolean // 是否为当前解析选用的服务器\n}\n\n/** 单语言服务器状态(edrv.lsp.status 载荷元素)。 */\nexport interface LspServerStatus {\n languageId: string\n source: 'extension' | 'discover' | 'manual' | 'none'\n phase: LspServerPhase\n version?: string\n reason?: string // unavailable/不可用原因(缺 dotnet、找不到服务器等)\n progress?: number // LSP 工作区解析进度(0–100,未知时省略)\n progressMessage?: string\n root?: string // 绑定工作区根(相对显示)\n providerName?: string // provider 名称(如 EmmyLua / LuaLS)\n missingEnv?: LspMissingEnv[] // 未满足的环境需求(无则省略)\n candidates?: LspCandidate[] // 同语言检测到的候选服务器(设置页展示用,无则省略)\n}\n\n/**\n * Monaco 位置(1-based lineNumber/column)→ LSP Position(0-based)。\n * @author ddj 2026年08月27号\n * @param lineNumber Monaco 行(≥1)\n * @param column Monaco 列(≥1)\n * @returns LSP 0-based position\n */\nexport function monoToLsp(lineNumber: number, column: number): LspPosition {\n return { line: Math.max(0, lineNumber - 1), character: Math.max(0, column - 1) }\n}\n\n/**\n * LSP Position(0-based)→ Monaco 位置(1-based)。\n * @author ddj 2026年08月27号\n * @param pos LSP position\n * @returns { lineNumber, column }(均 ≥1)\n */\nexport function lspToMono(pos: LspPosition): { lineNumber: number; column: number } {\n return { lineNumber: Math.max(1, pos.line + 1), column: Math.max(1, pos.character + 1) }\n}\n\n/** file:// URI → 路径(仅做规范化解码;Windows file:///C:/... 保留)。 */\nexport function fileUriToPath(uri: string): string {\n if (!uri) return ''\n const rest = uri.replace(/^file:\\/\\//, '')\n const decoded = decodeURIComponent(rest)\n return decoded.replace(/^\\/([A-Za-z]:)/, '$1') // file:///C:/x → C:/x\n}\n\n/** 已装扩展信息(edrv.lsp.ext.list 载荷元素)。 */\nexport interface LspExtInfo {\n id: string // publisher.name\n namespace: string\n name: string\n version: string\n displayName?: string\n description?: string\n}\n\n/** Open VSX 市场搜索结果项(edrv.lsp.ext.market 载荷元素)。 */\nexport interface LspMarketItem {\n namespace: string\n name: string\n id: string\n version: string\n displayName?: string\n description?: string\n download?: string\n}\n\n/** 有更新的已装扩展(edrv.lsp.ext.updates 载荷元素)。 */\nexport interface LspExtUpdate {\n id: string\n current: string\n latest: string\n displayName?: string\n}\n","/**\n * dsh-vscode-mode host — LSP 客户端(JSON-RPC over stdio)。\n * 职责:请求/通知/握手/超时/服务器端请求处理/生命周期。transport 无关性:\n * 只依赖 write/onMessage 契约,便于单测时注入假传输。\n * 作者 ddj 2026-08-27\n */\nimport { createFrameParser, encodeMessage, requestMessage, notifyMessage } from './jsonrpc.js'\nimport { LSP_SEMANTIC_TOKEN_TYPES, LSP_SEMANTIC_TOKEN_MODIFIERS, type LspServerCapabilities } from '../shared/lsp.js'\n\nexport interface LspClientEvents {\n onReady?: (capabilities: LspServerCapabilities) => void\n onExit?: (code: number | null, signal: string | null) => void\n onLog?: (line: string) => void\n onProgress?: (params: unknown) => void\n}\n\nconst DEFAULT_TIMEOUT_MS = 20_000\n\nexport class LspError extends Error {\n code: number\n constructor(code: number, message: string) {\n super(message)\n this.code = code\n }\n}\n\nexport interface LspClientTransport {\n write(chunk: Buffer): boolean\n dispose(): void\n readonly alive: boolean\n onMessage: ((message: unknown) => void) | null\n onExit: ((code: number | null, signal: string | null) => void) | null\n}\n\nexport interface LspClient {\n request<T>(method: string, params: unknown, timeoutMs?: number): Promise<T>\n notify(method: string, params: unknown): void\n initialize(rootUri: string, workspaceFolders: string[]): Promise<LspServerCapabilities>\n shutdown(): Promise<void>\n readonly alive: boolean\n}\n\n/**\n * 创建 LSP 客户端。\n * @author ddj 2026年08月27号\n * @param transport 传输句柄(write/onMessage/alive/dispose)\n * @param events 事件回调\n * @returns LSP 客户端\n */\nexport function createLspClient(\n transport: LspClientTransport,\n events: LspClientEvents = {},\n): LspClient {\n let nextId = 1\n let alive = transport.alive\n const pending = new Map<number, { resolve: (v: unknown) => void; reject: (e: Error) => void; timer: ReturnType<typeof setTimeout> }>()\n let serverCapabilities: LspServerCapabilities = {\n definition: false,\n declaration: false,\n references: false,\n documentSymbol: false,\n workspaceSymbol: false,\n hover: false,\n semanticTokens: false,\n semanticTokenTypes: [],\n semanticTokenModifiers: [],\n }\n\n const log = (line: string): void => events.onLog?.(line)\n const parser = createFrameParser()\n\n transport.onMessage = (message: unknown): void => {\n const msg = message as { id?: unknown; method?: unknown; params?: unknown; result?: unknown; error?: unknown }\n // 服务器端请求/通知带 method(请求还带 id);响应带 id + result/error、无 method。先判 method 再判 id。\n if (typeof msg.method === 'string') {\n if (msg.method === '$/progress') events.onProgress?.(msg.params)\n void handleServerRequest(msg as { method: string; params?: unknown; id?: unknown })\n return\n }\n if (typeof msg.id === 'number' || typeof msg.id === 'string') {\n const entry = pending.get(Number(msg.id))\n if (!entry) return\n pending.delete(Number(msg.id))\n clearTimeout(entry.timer)\n if (msg.error) {\n const err = msg.error as { code?: number; message?: string }\n entry.reject(new LspError(err.code ?? -32000, err.message ?? 'LSP error'))\n } else {\n entry.resolve(msg.result)\n }\n }\n }\n\n /** 服务器端请求:消息/日志类打日志,配置/能力类回 result:null,其余回 method not found。 */\n const handleServerRequest = async (msg: { method: string; params?: unknown; id?: unknown }): Promise<void> => {\n const { method, params, id } = msg\n const respond = (payload: Record<string, unknown>): void => {\n transport.write(encodeMessage(payload))\n }\n try {\n if (method === 'window/logMessage' || method === 'window/showMessage' || method === 'window/showMessageRequest') {\n const p = params as { type?: number; message?: string }\n log('[server ' + (p?.type ?? '') + '] ' + String(p?.message ?? ''))\n if (id !== undefined) respond({ jsonrpc: '2.0', id, result: null })\n return\n }\n if (method === 'workspace/configuration') {\n const p = params as { items?: unknown[] }\n const items = Array.isArray(p?.items) ? p.items.map(() => null) : []\n if (id !== undefined) respond({ jsonrpc: '2.0', id, result: items })\n return\n }\n // 客户端能力协商类:标准行为是确认(result:null),否则部分服务器(如 LuaLS)会中断工作区初始化\n if (method === 'window/workDoneProgress/create' || method === 'client/registerCapability' || method === 'workspace/workspaceFolders') {\n if (id !== undefined) respond({ jsonrpc: '2.0', id, result: null })\n return\n }\n if (id !== undefined) {\n respond({ jsonrpc: '2.0', id, error: { code: -32601, message: 'Method not found: ' + method } })\n }\n } catch (error) {\n log('server request handler error: ' + String(error))\n if (id !== undefined) {\n respond({ jsonrpc: '2.0', id, error: { code: -32603, message: String(error) } })\n }\n }\n }\n\n const transportExit = transport.onExit\n transport.onExit = (code, signal): void => {\n alive = false\n for (const entry of pending.values()) {\n clearTimeout(entry.timer)\n entry.reject(new Error('LSP 服务器已退出(' + String(code) + '/' + String(signal) + ')'))\n }\n pending.clear()\n events.onExit?.(code, signal)\n transportExit?.(code, signal)\n }\n\n const client: LspClient = {\n async request<T>(method: string, params: unknown, timeoutMs = DEFAULT_TIMEOUT_MS): Promise<T> {\n if (!alive) throw new Error('LSP 服务器未运行')\n const id = nextId++\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n pending.delete(id)\n reject(new Error('LSP 请求超时:' + method + '(' + timeoutMs + 'ms)'))\n }, timeoutMs)\n pending.set(id, { resolve: resolve as (v: unknown) => void, reject, timer })\n transport.write(encodeMessage(requestMessage(id, method, params)))\n })\n },\n notify(method: string, params: unknown): void {\n if (!alive) return\n transport.write(encodeMessage(notifyMessage(method, params)))\n },\n async initialize(rootUri: string, workspaceFolders: string[]): Promise<LspServerCapabilities> {\n const init = await client.request<{\n capabilities?: {\n definitionProvider?: unknown\n declarationProvider?: unknown\n referencesProvider?: unknown\n documentSymbolProvider?: unknown\n workspaceSymbolProvider?: unknown\n hoverProvider?: unknown\n semanticTokensProvider?: {\n legend?: { tokenTypes?: unknown; tokenModifiers?: unknown }\n }\n }\n }>('initialize', {\n processId: process.pid,\n rootUri: rootUri || null,\n rootPath: null,\n workspaceFolders: workspaceFolders.length\n ? workspaceFolders.map((uri) => ({ uri, name: uri }))\n : null,\n capabilities: {\n window: { workDoneProgress: true },\n workspace: { configuration: true },\n textDocument: {\n synchronization: { dynamicRegistration: false, willSave: false, didSave: true },\n definition: { dynamicRegistration: false },\n declaration: { dynamicRegistration: false },\n references: { dynamicRegistration: false },\n documentSymbol: { dynamicRegistration: false },\n hover: { dynamicRegistration: false },\n semanticTokens: {\n dynamicRegistration: false,\n requests: { range: false, full: { delta: false } },\n tokenTypes: [...LSP_SEMANTIC_TOKEN_TYPES],\n tokenModifiers: [...LSP_SEMANTIC_TOKEN_MODIFIERS],\n formats: ['relative'],\n },\n },\n },\n })\n const caps = init?.capabilities ?? {}\n const legend = caps.semanticTokensProvider?.legend\n serverCapabilities = {\n definition: Boolean(caps.definitionProvider),\n declaration: Boolean(caps.declarationProvider),\n references: Boolean(caps.referencesProvider),\n documentSymbol: Boolean(caps.documentSymbolProvider),\n workspaceSymbol: Boolean(caps.workspaceSymbolProvider),\n hover: Boolean(caps.hoverProvider),\n semanticTokens: Boolean(caps.semanticTokensProvider),\n semanticTokenTypes: Array.isArray(legend?.tokenTypes)\n ? legend.tokenTypes.filter((item): item is string => typeof item === 'string')\n : [...LSP_SEMANTIC_TOKEN_TYPES],\n semanticTokenModifiers: Array.isArray(legend?.tokenModifiers)\n ? legend.tokenModifiers.filter((item): item is string => typeof item === 'string')\n : [...LSP_SEMANTIC_TOKEN_MODIFIERS],\n }\n client.notify('initialized', {})\n events.onReady?.(serverCapabilities)\n return serverCapabilities\n },\n async shutdown(): Promise<void> {\n try {\n await client.request<unknown>('shutdown', null, 3000)\n } catch (error) {\n log('shutdown: ' + String(error))\n }\n try {\n client.notify('exit', null)\n } catch (error) {\n log('exit: ' + String(error))\n }\n },\n get alive() {\n return alive\n },\n }\n return client\n}\n","/**\n * dsh-vscode-mode host — 路径 ↔ file:// URI 转换(纯函数,node 可测)。\n * LSP 的 uri 字段必须是 file:// 绝对 URI;客户端 Monaco 用 edrv:///<encodeURI(path)>。\n * 作者 ddj 2026-08-27\n */\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { isAbsolute, resolve as resolvePath } from 'node:path'\n\n/**\n * 绝对路径 → file:// URI(Windows 盘符保留:D:/x → file:///D:/x)。\n * @author ddj 2026年08月27号\n * @param absPath 绝对路径(正/反斜杠均可)\n * @returns file:// URI\n */\nexport function pathToFileUri(absPath: string): string {\n const normalized = absPath.replace(/\\\\/g, '/')\n const drive = /^([A-Za-z]:)(?:\\/(.*))?$/.exec(normalized)\n if (drive) {\n const tail = drive[2] ? '/' + drive[2].split('/').map(encodeURIComponent).join('/') : ''\n return 'file:///' + drive[1] + tail\n }\n return pathToFileURL(normalized).toString()\n}\n\n/**\n * file:// URI → 绝对路径(Windows file:///C:/x → C:\\x)。\n * @author ddj 2026年08月27号\n * @param uri file:// URI\n * @returns 绝对路径\n */\nexport function fileUriToPath(fileUri: string): string {\n try {\n return fileURLToPath(fileUri)\n } catch (error) {\n return String(error)\n }\n}\n\n/**\n * 将(可能相对的)路径解析为绝对路径后转 file:// URI。\n * @author ddj 2026年08月27号\n * @param path 相对或绝对路径\n * @param cwd 解析相对路径的基准(可选)\n * @returns file:// URI\n */\nexport function resolveToFileUri(path: string, cwd?: string): string {\n const abs = isAbsolute(path) ? path : cwd ? resolvePath(cwd, path) : resolvePath(path)\n return pathToFileUri(abs)\n}\n\n/**\n * 判定绝对路径是否在给定根目录(含)内。\n * @author ddj 2026年08月27号\n * @param root 根目录绝对路径\n * @param target 目标绝对路径\n * @returns 是否在根内\n */\nexport function isInside(root: string, target: string): boolean {\n const r = root.replace(/\\\\/g, '/').replace(/\\/+$/, '') + '/'\n const t = target.replace(/\\\\/g, '/')\n return t === r.slice(0, -1) || t.startsWith(r)\n}\n","/**\n * dsh-vscode-mode host — 定义查找降级链的纯推导函数。\n * 背景:EmmyLua 对局部变量/参数/表字段的 textDocument/definition 常返回空,\n * 但 references(includeDeclaration) 能给出包含声明的条目。\n * 本函数从引用列表推导\"声明位置\":同文件、词文本与点击处一致,且点击位置落在某条目内时,\n * 取列表首个(EmmyLua 对局部/参数把声明排在引用首位;点击处即首个时按\"点击了声明\"处理)。\n * 词文本必须与点击词一致,否则拒绝(宁可空,不误跳)。\n * 作者 ddj 2026-09-02\n */\nimport type { LspLocation, LspPosition, LspRange } from '../shared/lsp.js'\n\n/** file:// URI(或裸路径)→ 归一化绝对路径(小写、/ 分隔)。 */\nfunction normAbs(uri: string): string {\n const path = String(uri ?? '').replace(/^file:\\/\\/\\/?/, '')\n return decodeURIComponent(path).replace(/\\\\/g, '/').replace(/^\\/([A-Za-z]:)/, '$1').toLowerCase()\n}\n\n/** 取文档 text 在 LSP range(0-based)内的切片。 */\nfunction sliceRange(text: string, range: LspRange): string {\n const lines = text.split(/\\r\\n|\\r|\\n/)\n const start = range.start\n const end = range.end\n const startLine = Math.max(0, start.line)\n const endLine = Math.max(startLine, end.line)\n if (startLine >= lines.length || endLine >= lines.length) return ''\n const startChar = Math.max(0, start.character)\n if (startLine === endLine) {\n return lines[startLine].slice(startChar, Math.max(startChar, end.character))\n }\n const first = lines[startLine].slice(startChar)\n const middle = lines.slice(startLine + 1, endLine)\n const last = lines[endLine].slice(0, Math.max(0, end.character))\n return [first, ...middle, last].join('\\n')\n}\n\n/** LSP position 是否落在 range 内(start 包含、end 排除;零宽按点匹配)。 */\nfunction posInLspRange(pos: LspPosition, range: LspRange): boolean {\n const start = range.start\n const end = range.end ?? start\n if (start.line === end.line && start.character === end.character) {\n return pos.line === start.line && pos.character === start.character\n }\n if (pos.line < start.line || pos.line > end.line) return false\n if (pos.line === start.line && pos.character < start.character) return false\n if (pos.line === end.line && pos.character >= end.character) return false\n return true\n}\n\n/** 两个 range 是否完全一致。 */\nfunction sameRange(a: LspRange, b: LspRange): boolean {\n return a.start.line === b.start.line && a.start.character === b.start.character &&\n a.end.line === b.end.line && a.end.character === b.end.character\n}\n\n/** range 长度(行/列均按 0-based 差估算,仅用于取\"最小包裹\"排序)。 */\nfunction rangeSize(r: LspRange): number {\n return (r.end.line - r.start.line) * 1_000_000 + (r.end.line === r.start.line ? r.end.character - r.start.character : r.end.character)\n}\n\n/**\n * 从引用列表推导定义位置。\n * @author ddj 2026年09月02号\n * @param queryPos 查询位置(LSP 0-based)\n * @param locations references(includeDeclaration) 结果\n * @param docText 当前文档全文(词文本一致校验)\n * @param docAbsPath 当前文档绝对路径(root+相对路径,与 loc.uri 归一化后比较)\n * @returns 推导出的定义位置;无法确定返回 null\n */\nexport function deriveDefinitionFromLocations(\n queryPos: LspPosition,\n locations: LspLocation[],\n docText: string,\n docAbsPath: string,\n): LspLocation | null {\n if (!locations.length) return null\n const docAbs = normAbs(docAbsPath)\n\n // 点击位置落在的条目(多个时取最小包裹 = 最贴近词的 range)\n const containing = locations\n .filter((loc) => posInLspRange(queryPos, loc.range))\n .sort((a, b) => rangeSize(a.range) - rangeSize(b.range))[0]\n if (!containing) return null\n const queryWord = sliceRange(docText, containing.range)\n if (!queryWord) return null\n\n // 同文件 + 词文本一致的候选(按服务器返回顺序)\n const candidates = locations.filter((loc) => {\n return normAbs(loc.uri) === docAbs && sliceRange(docText, loc.range) === queryWord\n })\n if (!candidates.length) return null\n\n // 点击处即候选首个(且与查询词重合)→ 点击的就是声明,返回自身\n // 否则取首个(EmmyLua 对局部/参数把声明排在引用首位)\n const first = candidates[0]\n return sameRange(first.range, containing.range) ? containing : first\n}\n","/**\n * dsh-vscode-mode host — 单语言服务器会话(绑定 工作区根 + 语言)。\n * 负责:启动传输 + LSP 客户端握手、文档同步(didOpen/didChange/didSave/didClose)、\n * 请求封装(definition/references/documentSymbol/workspaceSymbol/hover)、状态上报。\n * 作者 ddj 2026-08-27\n */\nimport { spawnServer, type Transport } from './transport.js'\nimport { createLspClient, type LspClient } from './client.js'\nimport { pathToFileUri } from './uri.js'\nimport { deriveDefinitionFromLocations } from './derive.js'\nimport type { LspProviderSpec } from './providers.js'\nimport { LSP_SEMANTIC_TOKEN_MODIFIERS, LSP_SEMANTIC_TOKEN_TYPES } from '../shared/lsp.js'\nimport type {\n LspLocation,\n LspSemanticTokens,\n LspServerCapabilities,\n LspServerPhase,\n LspServerStatus,\n LspSymbol,\n} from '../shared/lsp.js'\n\nexport interface LspServer {\n readonly languageId: string\n readonly root: string\n readonly phase: LspServerPhase\n readonly capabilities: LspServerCapabilities\n onStateChange: ((status: LspServerStatus) => void) | null\n status(): LspServerStatus\n start(): Promise<boolean>\n sync(path: string, text: string, version: number): void\n close(path: string): void\n definition(path: string, line: number, character: number): Promise<LspLocation[]>\n references(path: string, line: number, character: number, includeDeclaration: boolean): Promise<LspLocation[]>\n documentSymbol(path: string): Promise<LspSymbol[]>\n workspaceSymbol(query: string): Promise<LspSymbol[]>\n hover(path: string, line: number, character: number): Promise<{ contents: string[] } | null>\n semanticTokens(path: string): Promise<LspSemanticTokens | null>\n dispose(): Promise<void>\n}\n\n/** 文档注册表:path(工作区相对) → { version, text, uri }。 */\ninterface OpenDoc {\n path: string\n uri: string\n version: number\n text: string\n}\n\nconst RESTARTABLE = true\n\n/**\n * 创建语言服务器会话。\n * @author ddj 2026年08月27号\n * @param spec provider 规格(argv/cwd)\n * @param root 工作区根(绝对路径)\n * @param languageId 语言 id\n * @param logger 诊断日志\n * @returns 会话句柄\n */\nexport function createLspServer(spec: LspProviderSpec, root: string, languageId: string, logger?: (line: string) => void): LspServer {\n const rootUri = pathToFileUri(root)\n const docs = new Map<string, OpenDoc>()\n let phase: LspServerPhase = 'idle'\n let transport: Transport | null = null\n let client: LspClient | null = null\n let capabilities: LspServerCapabilities = {\n definition: false,\n declaration: false,\n references: false,\n documentSymbol: false,\n workspaceSymbol: false,\n hover: false,\n semanticTokens: false,\n semanticTokenTypes: [...LSP_SEMANTIC_TOKEN_TYPES],\n semanticTokenModifiers: [...LSP_SEMANTIC_TOKEN_MODIFIERS],\n }\n let disposed = false\n let readyWait: Promise<boolean> = Promise.resolve(false)\n let resolveReady: ((ready: boolean) => void) | null = null\n let lastProgress: { value?: number; message?: string } = {}\n let lastStatus: LspServerStatus = {\n languageId,\n source: spec.kind,\n phase: 'idle',\n reason: spec.ready ? undefined : spec.reason,\n root,\n version: spec.version,\n providerName: spec.providerName ?? (spec.version ? '语言服务器扩展' : undefined),\n }\n\n const log = (line: string): void => logger?.('[' + languageId + '@' + root + '] ' + line)\n const providerInfo = {\n version: spec.version,\n providerName: spec.providerName ?? (spec.version ? 'EmmyLua' : undefined),\n }\n\n const setPhase = (next: LspServerPhase, reason?: string): void => {\n phase = next\n lastStatus = { languageId, source: spec.kind, phase: next, reason, root, ...providerInfo, ...progressFields() }\n server.onStateChange?.(lastStatus)\n }\n\n /** 返回当前进度字段,避免空进度污染状态载荷。 */\n const progressFields = (): Pick<LspServerStatus, 'progress' | 'progressMessage'> => ({\n progress: lastProgress.value,\n progressMessage: lastProgress.message,\n })\n\n /** 处理 LSP $/progress 通知并映射为编辑器状态。 */\n const applyProgress = (params: unknown): void => {\n const value = params as { value?: unknown }\n const report = value?.value as { kind?: unknown; percentage?: unknown; message?: unknown } | undefined\n if (report?.kind === 'begin') {\n lastProgress = { value: 0, message: typeof report.message === 'string' ? report.message : '正在解析工作区' }\n if (phase === 'ready') phase = 'indexing'\n } else if (report?.kind === 'end') {\n lastProgress = { value: 100, message: typeof report.message === 'string' ? report.message : '解析完成' }\n if (phase === 'indexing') phase = 'ready'\n } else if (typeof report?.percentage === 'number') {\n lastProgress = { value: Math.max(0, Math.min(100, report.percentage)), message: typeof report.message === 'string' ? report.message : lastProgress.message }\n if (phase === 'ready') phase = 'indexing'\n } else if (typeof report?.message === 'string') {\n lastProgress = { ...lastProgress, message: report.message }\n }\n lastStatus = { ...lastStatus, phase, ...progressFields() }\n server.onStateChange?.(lastStatus)\n }\n\n const ensureClient = (): LspClient => {\n if (!client) throw new Error('LSP 服务器未启动')\n return client\n }\n\n const server: LspServer = {\n languageId,\n root,\n get phase() {\n return phase\n },\n get capabilities() {\n return capabilities\n },\n status(): LspServerStatus {\n return lastStatus\n },\n onStateChange: null,\n\n async start(): Promise<boolean> {\n if (disposed) return false\n if (phase === 'starting') return readyWait\n if (phase === 'ready' || phase === 'indexing') return true\n readyWait = new Promise((resolve) => { resolveReady = resolve })\n lastProgress = {}\n setPhase('starting')\n try {\n transport = spawnServer(\n { argv: spec.argv, cwd: spec.cwd ?? root, env: spec.env },\n (message) => { /* 由 client 接管 */ },\n (line) => log('stderr: ' + line),\n )\n client = createLspClient(transport, {\n onReady: (caps) => {\n capabilities = caps\n // 重放已打开文档(崩溃重启后恢复服务器侧状态)\n for (const doc of docs.values()) {\n client?.notify('textDocument/didOpen', {\n textDocument: { uri: doc.uri, languageId, version: doc.version, text: doc.text },\n })\n }\n setPhase('ready')\n resolveReady?.(true)\n resolveReady = null\n log('ready: definition=' + caps.definition + ' references=' + caps.references + ' symbols=' + caps.documentSymbol)\n },\n onProgress: (params) => applyProgress(params),\n onExit: (code, signal) => {\n if (disposed) return\n resolveReady?.(false)\n resolveReady = null\n log('server exited (' + String(code) + '/' + String(signal) + ')')\n client = null\n transport = null\n if (RESTARTABLE) setPhase('idle', '服务器已退出(' + String(code) + '/' + String(signal) + '),等待重启')\n else setPhase('stopped', '服务器已退出')\n },\n onLog: (line) => log('lsp: ' + line),\n })\n // 让 client 接管 stdout 消息\n const caps = await client.initialize(rootUri, [rootUri])\n // DotRush 服务器阻塞等待带 dotrush 段的配置通知才继续初始化(加载工作区),\n // 不发则所有文档类查询返回空;官方 VSCode 扩展经 configurationSection 自动发送。\n // 按 csharp 语言统一发送:手动配置的 DotRush 与其它 C# 服务器(OmniSharp 等)\n // 对不认识的配置段按协议忽略,均安全\n if (languageId === 'csharp') {\n client.notify('workspace/didChangeConfiguration', { settings: { dotrush: { roslyn: {} } } })\n }\n capabilities = caps\n return true\n } catch (error) {\n log('start failed: ' + String(error))\n setPhase('unavailable', '启动失败:' + String(error))\n resolveReady?.(false)\n resolveReady = null\n try { await server.dispose() } catch { /* 忽略 */ }\n return false\n }\n },\n\n sync(path: string, text: string, version: number): void {\n const existing = docs.get(path)\n const uri = existing?.uri ?? pathToFileUri(root + '/' + path.split('/').join('/'))\n if (existing) {\n existing.version = version\n existing.text = text\n if (phase === 'ready' || phase === 'indexing') {\n client?.notify('textDocument/didChange', {\n textDocument: { uri, version },\n contentChanges: [{ text }],\n })\n }\n return\n }\n docs.set(path, { path, uri, version, text })\n if (phase === 'ready' || phase === 'indexing') {\n client?.notify('textDocument/didOpen', {\n textDocument: { uri, languageId, version, text },\n })\n }\n },\n\n close(path: string): void {\n const doc = docs.get(path)\n if (!doc) return\n docs.delete(path)\n if (phase === 'ready' || phase === 'indexing') {\n client?.notify('textDocument/didClose', { textDocument: { uri: doc.uri } })\n }\n },\n\n async definition(path: string, line: number, character: number): Promise<LspLocation[]> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait)) return []\n const client = ensureClient()\n const position = { line, character }\n // ① 标准定义(方法/跨文件命名空间等)\n const direct = normalizeLocations(\n await client.request<unknown>(\n 'textDocument/definition',\n { textDocument: { uri: doc.uri }, position },\n ),\n )\n if (direct.length) return direct\n // ② 声明(服务器能力支持时):EmmyLua 对局部变量/参数/表字段 definition 常返回空,declaration 更准\n if (capabilities.declaration) {\n try {\n const decl = normalizeLocations(\n await client.request<unknown>(\n 'textDocument/declaration',\n { textDocument: { uri: doc.uri }, position },\n ),\n )\n if (decl.length) {\n log('definition fallback → declaration (' + path + ':' + line + ':' + character + ')')\n return decl\n }\n } catch (error) {\n log('declaration request failed: ' + String(error))\n }\n }\n // ③ 引用推导:definition/declaration 均空时,从 references(includeDeclaration) 推导声明\n // (EmmyLua 局部/参数把声明排在引用首位;词文本不一致则拒绝,宁可空不误跳)\n try {\n const refs = normalizeLocations(\n await client.request<unknown>(\n 'textDocument/references',\n {\n textDocument: { uri: doc.uri },\n position,\n context: { includeDeclaration: true },\n },\n ),\n )\n const derived = deriveDefinitionFromLocations(position, refs, doc.text, doc.uri)\n if (derived) {\n log('definition fallback → references-derived (' + path + ':' + line + ':' + character + ')')\n return [derived]\n }\n } catch (error) {\n log('references fallback failed: ' + String(error))\n }\n return []\n },\n\n async references(path: string, line: number, character: number, includeDeclaration: boolean): Promise<LspLocation[]> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait)) return []\n const result = await ensureClient().request<unknown>(\n 'textDocument/references',\n {\n textDocument: { uri: doc.uri },\n position: { line, character },\n context: { includeDeclaration },\n },\n )\n return normalizeLocations(result)\n },\n\n async documentSymbol(path: string): Promise<LspSymbol[]> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait)) return []\n const result = await ensureClient().request<unknown>('textDocument/documentSymbol', { textDocument: { uri: doc.uri } })\n if (!Array.isArray(result)) return []\n return (result as unknown[]).map(normalizeSymbol).filter((s): s is LspSymbol => s !== null)\n },\n\n async workspaceSymbol(query: string): Promise<LspSymbol[]> {\n if (!(await readyWait)) return []\n const result = await ensureClient().request<unknown>('workspace/symbol', { query })\n if (!Array.isArray(result)) return []\n return (result as unknown[]).map(normalizeSymbol).filter((s): s is LspSymbol => s !== null)\n },\n\n async hover(path: string, line: number, character: number): Promise<{ contents: string[] } | null> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait)) return null\n const result = await ensureClient().request<{ contents?: unknown; range?: unknown } | null>(\n 'textDocument/hover',\n { textDocument: { uri: doc.uri }, position: { line, character } },\n )\n if (!result || !result.contents) return null\n return { contents: stringifyHoverContents(result.contents) }\n },\n\n /** 查询全文 semantic tokens,并将服务器 legend 归一到插件固定 legend。 */\n async semanticTokens(path: string): Promise<LspSemanticTokens | null> {\n const doc = docs.get(path)\n if (!doc || !(await readyWait) || !capabilities.semanticTokens) return null\n const result = await ensureClient().request<{ data?: unknown; resultId?: unknown } | null>(\n 'textDocument/semanticTokens/full',\n { textDocument: { uri: doc.uri } },\n )\n if (!result || !Array.isArray(result.data)) return null\n return {\n data: normalizeSemanticData(\n result.data,\n capabilities.semanticTokenTypes ?? [],\n capabilities.semanticTokenModifiers ?? [],\n ),\n resultId: typeof result.resultId === 'string' ? result.resultId : undefined,\n }\n },\n\n async dispose(): Promise<void> {\n disposed = true\n resolveReady?.(false)\n resolveReady = null\n if (client) {\n await client.shutdown().catch(() => {})\n client = null\n }\n if (transport) {\n transport.dispose()\n transport = null\n }\n setPhase('stopped')\n },\n }\n return server\n}\n\n/** 归一化 definition/references 结果(Location | Location[] | LocationLink[])。 */\nfunction normalizeLocations(result: unknown): LspLocation[] {\n if (!Array.isArray(result)) return []\n const out: LspLocation[] = []\n for (const item of result) {\n if (!item || typeof item !== 'object') continue\n const obj = item as { uri?: unknown; range?: unknown; targetUri?: unknown; targetRange?: unknown; targetSelectionRange?: unknown }\n const uri = typeof obj.targetUri === 'string' ? obj.targetUri : typeof obj.uri === 'string' ? obj.uri : ''\n const range = (obj.targetRange ?? obj.range) as { start?: { line?: unknown; character?: unknown }; end?: { line?: unknown; character?: unknown } } | undefined\n if (!uri || !range || !range.start || !range.end) continue\n out.push({\n uri,\n range: {\n start: { line: toInt(range.start.line), character: toInt(range.start.character) },\n end: { line: toInt(range.end.line), character: toInt(range.end.character) },\n },\n })\n }\n return out\n}\n\n/** 归一化 documentSymbol/workspaceSymbol 结果(DocumentSymbol | SymbolInformation)。 */\nfunction normalizeSymbol(item: unknown): LspSymbol | null {\n if (!item || typeof item !== 'object') return null\n const obj = item as {\n name?: unknown\n kind?: unknown\n detail?: unknown\n containerName?: unknown\n range?: { start?: unknown; end?: unknown }\n selectionRange?: { start?: unknown; end?: unknown }\n children?: unknown\n location?: { uri?: unknown; range?: unknown }\n }\n if (typeof obj.name !== 'string') return null\n const selection = obj.selectionRange ?? (obj.location && (obj.location as { range?: unknown }).range)\n const range = obj.range ?? selection\n if (!range || typeof range !== 'object') return null\n const r = range as { start?: { line?: unknown; character?: unknown }; end?: { line?: unknown; character?: unknown } }\n if (!r.start || !r.end) return null\n const symbol: LspSymbol = {\n name: obj.name,\n kind: toInt(obj.kind),\n range: { start: { line: toInt((r.start as { line?: unknown }).line), character: toInt((r.start as { character?: unknown }).character) }, end: { line: toInt((r.end as { line?: unknown }).line), character: toInt((r.end as { character?: unknown }).character) } },\n selectionRange: selection\n ? { start: { line: toInt(((selection as { start?: { line?: unknown } }).start as { line?: unknown } | undefined)?.line ?? toInt((r.start as { line?: unknown }).line)), character: toInt(((selection as { start?: { character?: unknown } }).start as { character?: unknown } | undefined)?.character ?? toInt((r.start as { character?: unknown }).character)) }, end: { line: toInt(((selection as { end?: { line?: unknown } }).end as { line?: unknown } | undefined)?.line ?? toInt((r.end as { line?: unknown }).line)), character: toInt(((selection as { end?: { character?: unknown } }).end as { character?: unknown } | undefined)?.character ?? toInt((r.end as { character?: unknown }).character)) } }\n : { start: { line: toInt((r.start as { line?: unknown }).line), character: toInt((r.start as { character?: unknown }).character) }, end: { line: toInt((r.end as { line?: unknown }).line), character: toInt((r.end as { character?: unknown }).character) } },\n }\n if (typeof obj.detail === 'string' && obj.detail) symbol.detail = obj.detail\n if (typeof obj.containerName === 'string' && obj.containerName) symbol.containerName = obj.containerName\n if (Array.isArray(obj.children)) {\n const kids = obj.children.map(normalizeSymbol).filter((s): s is LspSymbol => s !== null)\n if (kids.length) symbol.children = kids\n }\n return symbol\n}\n\n/** hover contents → 文本行(MarkupContent | MarkedString | MarkedString[])。 */\nfunction stringifyHoverContents(contents: unknown): string[] {\n if (typeof contents === 'string') return [contents]\n if (Array.isArray(contents)) return contents.map(stringifyHoverContents).flat().filter(Boolean)\n if (contents && typeof contents === 'object') {\n const value = (contents as { value?: unknown }).value\n if (typeof value === 'string') return [value]\n }\n return []\n}\n\nfunction toInt(value: unknown): number {\n const n = Number(value)\n return Number.isFinite(n) ? Math.max(0, Math.floor(n)) : 0\n}\n\n/** 把服务器 legend 下的 5 元组流转换为插件固定 legend 下的 5 元组流。 */\nfunction normalizeSemanticData(data: unknown[], types: string[], modifiers: string[]): number[] {\n const out: number[] = []\n let previousLine = 0\n let previousCharacter = 0\n let outputLine = 0\n let outputCharacter = 0\n for (let i = 0; i + 4 < data.length; i += 5) {\n const deltaLine = toInt(data[i])\n const deltaCharacter = toInt(data[i + 1])\n const length = toInt(data[i + 2])\n const sourceType = types[toInt(data[i + 3])] ?? 'variable'\n const sourceModifiers = toInt(data[i + 4])\n const line = previousLine + deltaLine\n const character = deltaLine === 0 ? previousCharacter + deltaCharacter : deltaCharacter\n const typeIndex = Math.max(0, LSP_SEMANTIC_TOKEN_TYPES.indexOf(sourceType as never))\n let modifierBits = 0\n for (let bit = 0; bit < modifiers.length; bit++) {\n if ((sourceModifiers & (1 << bit)) === 0) continue\n const modifier = modifiers[bit]\n const targetBit = LSP_SEMANTIC_TOKEN_MODIFIERS.indexOf(modifier as never)\n if (targetBit >= 0) modifierBits |= 1 << targetBit\n }\n const outputDeltaLine = line - outputLine\n const outputDeltaCharacter = outputDeltaLine === 0 ? character - outputCharacter : character\n out.push(outputDeltaLine, outputDeltaCharacter, length, typeIndex, modifierBits)\n previousLine = line\n previousCharacter = character\n outputLine = line\n outputCharacter = character\n }\n return out\n}\n","/**\n * dsh-vscode-mode host — LSP 服务器管理器。\n * 实例注册表(key=root|languageId,refcount 共享),崩溃退避重启,session/disposed 清理。\n * 作者 ddj 2026-08-27\n */\nimport { createLspServer, type LspServer } from './server.js'\nimport type { LspProviderSpec } from './providers.js'\nimport type { LspServerStatus } from '../shared/lsp.js'\n\ninterface Entry {\n key: string\n server: LspServer\n refs: number\n failures: number\n restartTimer: ReturnType<typeof setTimeout> | null\n}\n\nconst BACKOFF_MS = [1000, 5000, 30000]\nconst MAX_FAILURES = 3\n\nexport interface LspManager {\n /** 获取(或惰性创建)某工作区+语言的服务器;refs+1。 */\n acquire(root: string, languageId: string, resolveSpec: (languageId: string) => LspProviderSpec): LspServer\n /** 释放引用;refs 归零时停止服务器。 */\n release(root: string, languageId: string): void\n /** 释放工作区下全部语言(session/disposed 用)。 */\n releaseRoot(root: string): void\n /** 重置单个工作区语言 server(重新检测 provider 用)。 */\n reset(root: string, languageId: string): void\n /** 重置全部工作区的指定语言 server。 */\n resetLanguage(languageId: string): void\n /** 状态快照。 */\n statusAll(): LspServerStatus[]\n /** 查询已注册的工作区+语言服务器,不增加引用计数。 */\n peek(root: string, languageId: string): LspServer | undefined\n /** 停止并清空全部(卸载/退出)。 */\n disposeAll(): Promise<void>\n /** 监听状态变化(用于 UI)。 */\n onStatusChange: ((status: LspServerStatus) => void) | null\n}\n\n/**\n * 创建 LSP 管理器。\n * @author ddj 2026年08月27号\n * @param logger 诊断日志\n * @returns 管理器\n */\nexport function createLspManager(logger?: (line: string) => void): LspManager {\n const entries = new Map<string, Entry>()\n const keyOf = (root: string, languageId: string): string => root + '|' + languageId\n\n const log = (line: string): void => logger?.('[lsp-manager] ' + line)\n\n /** 同步摘除注册表项并后台回收(refs 归零/工作区清理用;statusAll 立即可见归零)。 */\n const dropEntry = (entry: Entry): void => {\n if (entry.restartTimer) {\n clearTimeout(entry.restartTimer)\n entry.restartTimer = null\n }\n entries.delete(entry.key)\n void entry.server.dispose().catch(() => {})\n }\n\n const scheduleRestart = (entry: Entry): void => {\n if (entry.restartTimer) return\n if (entry.failures >= MAX_FAILURES) {\n log('unavailable after ' + entry.failures + ' failures: ' + entry.key)\n return\n }\n const delay = BACKOFF_MS[Math.min(entry.failures, BACKOFF_MS.length - 1)]\n entry.restartTimer = setTimeout(() => {\n entry.restartTimer = null\n if (!entries.has(entry.key)) return\n void (async () => {\n const ok = await entry.server.start()\n if (!ok) entry.failures++\n else entry.failures = 0\n if (!ok && entries.has(entry.key)) scheduleRestart(entry)\n })()\n }, delay)\n }\n\n const manager: LspManager = {\n acquire(root: string, languageId: string, resolveSpec: (languageId: string) => LspProviderSpec): LspServer {\n const key = keyOf(root, languageId)\n let entry = entries.get(key)\n if (!entry) {\n const spec = resolveSpec(languageId)\n const server = createLspServer(spec, root, languageId, log)\n server.onStateChange = (status) => manager.onStatusChange?.(status)\n entry = { key, server, refs: 0, failures: 0, restartTimer: null }\n entries.set(key, entry)\n // 惰性启动:若 spec ready 才启动,否则保持 idle(供 status 展示 reason)\n if (spec.ready) {\n void server.start().then((ok) => {\n if (!ok && entries.has(key)) entry!.failures++\n })\n }\n }\n entry.refs++\n return entry.server\n },\n\n release(root: string, languageId: string): void {\n const entry = entries.get(keyOf(root, languageId))\n if (!entry) return\n entry.refs = Math.max(0, entry.refs - 1)\n if (entry.refs === 0) dropEntry(entry)\n },\n\n releaseRoot(root: string): void {\n for (const entry of [...entries.values()]) {\n if (entry.server.root === root) dropEntry(entry)\n }\n },\n\n reset(root: string, languageId: string): void {\n const entry = entries.get(keyOf(root, languageId))\n if (entry) dropEntry(entry)\n },\n\n resetLanguage(languageId: string): void {\n for (const entry of [...entries.values()]) {\n if (entry.server.languageId === languageId) dropEntry(entry)\n }\n },\n\n statusAll(): LspServerStatus[] {\n return [...entries.values()].map((entry) => entry.server.status())\n },\n\n peek(root: string, languageId: string): LspServer | undefined {\n return entries.get(keyOf(root, languageId))?.server\n },\n\n async disposeAll(): Promise<void> {\n const list = [...entries.values()]\n entries.clear()\n for (const entry of list) {\n if (entry.restartTimer) clearTimeout(entry.restartTimer)\n await entry.server.dispose()\n }\n },\n\n onStatusChange: null,\n }\n return manager\n}\n","/**\n * dsh-vscode-mode host — 纯 Node ZIP 解压(零依赖,跨平台)。\n * 供 extmgr 解包 VSIX 使用;只实现 VSIX 需要的子集:\n * 读取 EOCD + 中央目录,支持 stored(0)/deflate(8),忽略 zip64(VSIX < 4GB)。\n * 作者 ddj 2026-08-27\n */\nimport { inflateRawSync } from 'node:zlib'\n\n/** 单条解压结果:相对路径 + 内容(目录条目 path 以 / 结尾)。 */\nexport interface ZipEntry {\n path: string\n data: Buffer\n isDirectory: boolean\n}\n\nconst EOCD_SIG = 0x06054b50\nconst CDIR_SIG = 0x02014b50\nconst LHDR_SIG = 0x04034b50\n\n/**\n * 解析 ZIP 缓冲区 → 条目列表(不解压内容,仅元数据)。\n * @author ddj 2026年08月27号\n * @param buf zip 字节\n * @returns 条目元数据\n */\nexport function zipEntries(buf: Buffer): { name: string; method: number; compressed: number; uncompressed: number; localOffset: number }[] {\n const eocd = findEocd(buf)\n if (eocd < 0) throw new Error('不是有效的 ZIP 文件(找不到 EOCD)')\n const total = buf.readUInt16LE(eocd + 10)\n let offset = buf.readUInt32LE(eocd + 16)\n const out: { name: string; method: number; compressed: number; uncompressed: number; localOffset: number }[] = []\n for (let i = 0; i < total; i++) {\n if (buf.readUInt32LE(offset) !== CDIR_SIG) throw new Error('ZIP 中央目录损坏')\n const method = buf.readUInt16LE(offset + 10)\n const compressed = buf.readUInt32LE(offset + 20)\n const uncompressed = buf.readUInt32LE(offset + 24)\n const nameLen = buf.readUInt16LE(offset + 28)\n const extraLen = buf.readUInt16LE(offset + 30)\n const commentLen = buf.readUInt16LE(offset + 32)\n const localOffset = buf.readUInt32LE(offset + 42)\n const name = buf.subarray(offset + 46, offset + 46 + nameLen).toString('utf8')\n out.push({ name, method, compressed, uncompressed, localOffset })\n offset += 46 + nameLen + extraLen + commentLen\n }\n return out\n}\n\n/**\n * 解压 ZIP → 条目列表(目录条目含尾部 /)。\n * @author ddj 2026年08月27号\n * @param buf zip 字节\n * @returns 条目(含内容)\n */\nexport function unzip(buf: Buffer): ZipEntry[] {\n const metas = zipEntries(buf)\n const out: ZipEntry[] = []\n for (const meta of metas) {\n const lh = meta.localOffset\n if (buf.readUInt32LE(lh) !== LHDR_SIG) throw new Error('ZIP 本地头损坏:' + meta.name)\n const nameLen = buf.readUInt16LE(lh + 26)\n const extraLen = buf.readUInt16LE(lh + 28)\n const dataStart = lh + 30 + nameLen + extraLen\n const isDir = /\\/$/.test(meta.name)\n let data: Buffer = Buffer.alloc(0)\n if (!isDir && meta.compressed > 0) {\n const raw = buf.subarray(dataStart, dataStart + meta.compressed)\n data = meta.method === 8 ? Buffer.from(inflateRawSync(raw)) : meta.method === 0 ? Buffer.from(raw) : Buffer.alloc(0)\n }\n out.push({ path: meta.name, data, isDirectory: isDir })\n }\n return out\n}\n\n/** 定位 EOCD(从尾部向前扫,容忍尾部注释)。 */\nfunction findEocd(buf: Buffer): number {\n const maxScan = Math.min(buf.length, 65557)\n for (let i = buf.length - 22; i >= buf.length - maxScan; i--) {\n if (i < 0) break\n if (buf.readUInt32LE(i) === EOCD_SIG) return i\n }\n return -1\n}\n","/**\n * dsh-vscode-mode host — VSIX 扩展管理器(extmgr)。\n * 管理 DSH 专属扩展目录(~/.dsh/dsh-vscode-mode/extensions/),支持:\n * 本地 .vsix 安装、Open VSX 市场搜索/下载安装、卸载、更新检测与安装。\n * 已装扩展作为 LSP provider 的\"扩展源\"(kind=extension),见 providers.ts。\n * 作者 ddj 2026-08-27\n */\nimport { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport { unzip } from './zip.js'\nimport { dshHome, PLUGIN_ID } from '../paths.js'\n\n/** 单个已装扩展信息(edrv.lsp.ext.list 载荷元素)。 */\nexport interface ExtInfo {\n id: string // publisher.name\n namespace: string\n name: string\n version: string\n displayName?: string\n description?: string\n dirName: string // 目录名 publisher.name-version\n dir: string // 绝对路径\n}\n\n/** Open VSX 市场搜索结果(edrv.lsp.ext.market 载荷元素)。 */\nexport interface MarketItem {\n namespace: string\n name: string\n id: string\n version: string\n displayName?: string\n description?: string\n download?: string\n}\n\nconst OPEN_VSX = 'https://open-vsx.org'\nconst META_FILE = 'package.json'\n/** 当前平台(与 VSCode platform 命名对齐:win32-x64/darwin-arm64/linux-x64)。 */\nconst PLATFORM = (() => {\n if (process.platform === 'win32') return process.arch === 'arm64' ? 'win32-arm64' : 'win32-x64'\n if (process.platform === 'darwin') return process.arch === 'arm64' ? 'darwin-arm64' : 'darwin-x64'\n return process.arch === 'arm64' ? 'linux-arm64' : 'linux-x64'\n})()\n\n/** DSH 专属扩展目录。 */\nexport function extensionsRoot(home = dshHome()): string {\n return join(home, PLUGIN_ID, 'extensions')\n}\n\n/** 从 VSIX 字节里读 extension/package.json 清单。 */\nexport function vsixManifest(vsix: Buffer): Record<string, unknown> {\n for (const entry of unzip(vsix)) {\n if (entry.path === 'extension/package.json' || entry.path === 'extension\\\\package.json') {\n return JSON.parse(entry.data.toString('utf8')) as Record<string, unknown>\n }\n }\n throw new Error('VSIX 缺少 extension/package.json')\n}\n\n/**\n * 解包 VSIX 到目录(仅取 extension/ 子树,剥前缀;返回清单)。\n * @author ddj 2026年08月27号\n * @param vsix vsix 字节\n * @param dest 目标目录(已存在则先清空)\n * @returns 清单对象\n */\nexport function unpackVsix(vsix: Buffer, dest: string): Record<string, unknown> {\n rmSync(dest, { recursive: true, force: true })\n mkdirSync(dest, { recursive: true })\n let manifest: Record<string, unknown> | null = null\n for (const entry of unzip(vsix)) {\n const rel = entry.path.replace(/^extension[\\\\/]/, '')\n if (!rel || entry.path.startsWith('..')) continue\n const safe = rel.split(/[\\\\/]/).filter((part) => part && part !== '..' && part !== '.').join('/')\n if (!safe) continue\n const target = join(dest, ...safe.split('/'))\n if (entry.isDirectory) {\n mkdirSync(target, { recursive: true })\n continue\n }\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, entry.data)\n if (rel === 'package.json') manifest = JSON.parse(entry.data.toString('utf8')) as Record<string, unknown>\n }\n if (!manifest) throw new Error('VSIX 解包后缺少 package.json')\n return manifest\n}\n\n/** 扩展信息(清单 + 目录)。 */\nexport function extInfoOf(manifest: Record<string, unknown>, dir: string): ExtInfo {\n const namespace = String(manifest.publisher ?? 'unknown')\n const name = String(manifest.name ?? 'unknown')\n const version = String(manifest.version ?? '0.0.0')\n return {\n id: namespace + '.' + name,\n namespace,\n name,\n version,\n displayName: typeof manifest.displayName === 'string' ? manifest.displayName : undefined,\n description: typeof manifest.description === 'string' ? manifest.description : undefined,\n dirName: basename(dir),\n dir,\n }\n}\n\n/** 安装本地 .vsix 文件(已存在同 id 则升级替换)。 */\nexport async function installVsixFile(vsixPath: string, home = dshHome()): Promise<ExtInfo> {\n const vsix = readFileSync(vsixPath)\n return installVsixBuffer(vsix, home)\n}\n\n/** 安装 VSIX 字节(解包进 extensionsRoot;同名旧版本先清)。 */\nexport function installVsixBuffer(vsix: Buffer, home = dshHome()): ExtInfo {\n const manifest = vsixManifest(vsix)\n const info = extInfoOf(manifest, '')\n const target = join(extensionsRoot(home), info.id + '-' + info.version)\n const unpacked = unpackVsix(vsix, target)\n return extInfoOf(unpacked, target)\n}\n/** 扫描已装扩展目录。 */\nexport function listInstalled(home = dshHome()): ExtInfo[] {\n const root = extensionsRoot(home)\n if (!existsSync(root)) return []\n const out: ExtInfo[] = []\n for (const dir of readdirSync(root)) {\n const full = join(root, dir)\n const meta = join(full, META_FILE)\n if (!existsSync(meta)) continue\n try {\n const manifest = JSON.parse(readFileSync(meta, 'utf8')) as Record<string, unknown>\n out.push(extInfoOf(manifest, full))\n } catch (error) {\n /* 坏清单目录跳过 */\n }\n }\n return out\n}\n\n/** 卸载扩展(按 id)。 */\nexport function uninstall(id: string, home = dshHome()): boolean {\n const target = listInstalled(home).find((e) => e.id === id)?.dir\n if (!target) return false\n rmSync(target, { recursive: true, force: true })\n return true\n}\n\n/** Open VSX 单扩展元数据(latest + 下载 URL)。 */\nexport async function marketGet(namespace: string, name: string, version?: string): Promise<Record<string, unknown> | null> {\n const path = version ? namespace + '/' + name + '/' + version : namespace + '/' + name\n const res = await fetch(OPEN_VSX + '/api/' + path, { headers: { accept: 'application/json' } })\n if (!res.ok) return null\n return (await res.json()) as Record<string, unknown>\n}\n\n/** Open VSX 搜索。 */\nexport async function marketSearch(query: string, size = 12): Promise<MarketItem[]> {\n const url = OPEN_VSX + '/api/-/search?query=' + encodeURIComponent(query) + '&size=' + size\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error('市场搜索失败:HTTP ' + res.status)\n const data = (await res.json()) as { extensions?: unknown[] }\n return ((data.extensions ?? []) as Record<string, unknown>[]).map((item) => ({\n namespace: String(item.namespace ?? ''),\n name: String(item.name ?? ''),\n id: String(item.namespace ?? '') + '.' + String(item.name ?? ''),\n version: String(item.version ?? ''),\n displayName: typeof item.displayName === 'string' ? item.displayName : undefined,\n description: typeof item.description === 'string' ? item.description : undefined,\n download: typeof (item.files as { download?: unknown } | undefined)?.download === 'string' ? (item.files as { download: string }).download : undefined,\n }))\n}\n\n/** 平台匹配的 VSIX 下载 URL(探测平台变体,失败回退 API 默认)。 */\nexport async function resolveDownload(namespace: string, name: string, version: string): Promise<string> {\n const candidate = OPEN_VSX + '/api/' + namespace + '/' + name + '/' + PLATFORM + '/' + version +\n '/file/' + namespace + '.' + name + '-' + version + '@' + PLATFORM + '.vsix'\n try {\n const head = await fetch(candidate, { method: 'HEAD' })\n if (head.ok) return candidate\n } catch (error) {\n /* 探测失败走默认 */\n }\n const meta = await marketGet(namespace, name, version)\n const download = (meta?.files as { download?: unknown } | undefined)?.download\n if (typeof download === 'string') return download\n throw new Error('市场未提供 ' + namespace + '.' + name + '@' + version + ' 的下载地址')\n}\n\n/** 从 Open VSX 安装/更新扩展。 */\nexport async function installFromMarket(namespace: string, name: string, version?: string): Promise<ExtInfo> {\n const meta = await marketGet(namespace, name, version)\n if (!meta) throw new Error('市场找不到 ' + namespace + '.' + name + (version ? '@' + version : ''))\n const ver = version ?? String(meta.version ?? '')\n const url = await resolveDownload(namespace, name, ver)\n const res = await fetch(url)\n if (!res.ok) throw new Error('下载失败:HTTP ' + res.status)\n const vsix = Buffer.from(await res.arrayBuffer())\n return installVsixBuffer(vsix)\n}\n\n/** 更新已装扩展(对比市场最新版;返回 null 表示已最新)。 */\nexport async function updateExtension(id: string): Promise<ExtInfo | null> {\n const installed = listInstalled().find((e) => e.id === id)\n if (!installed) throw new Error('扩展未安装:' + id)\n const meta = await marketGet(installed.namespace, installed.name)\n const latest = String(meta?.version ?? '')\n if (!latest || latest === installed.version) return null\n return installFromMarket(installed.namespace, installed.name, latest)\n}\n","/**\n * dsh-vscode-mode host — 语言服务器 provider 解析。\n * 优先级:手动配置 > extmgr 扩展源(Phase 2 挂载) > 自动发现(~/.vscode/extensions、\n * ~/.dsh/dsh-vscode-mode/extensions、PATH)。C# 自动发现覆盖 ms-dotnettools.csharp\n * (Roslyn/OmniSharp)与 DotRush(自带 DotRush.dll 服务器,需对应 .NET 运行时)。\n * 产物 LspProviderSpec:{ ready, argv, cwd, reason },供 manager 启动服务器。\n * 作者 ddj 2026-08-27\n */\nimport { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, rmSync, type Dirent } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join, sep } from 'node:path'\nimport { isAbsolute } from 'node:path'\nimport { extensionsRoot } from './extmgr.js'\nimport { dshHome, lspSpecCacheFile } from '../paths.js'\nimport type { LspCandidate } from '../shared/lsp.js'\n\n/** provider 来源标记(与 shared/lsp.ts 的 status.source 一致)。 */\nexport type LspProviderKind = 'extension' | 'discover' | 'manual' | 'none'\n\nexport interface LspProviderSpec {\n languageId: string\n kind: LspProviderKind\n argv: string[]\n cwd?: string\n env?: Record<string, string>\n /** 需自动配置的 .NET 运行时大版本(发现 DotRush 但缺运行时时设置,见 dotnetProvision.ts)。 */\n provisionRuntime?: number\n ready: boolean\n reason?: string\n version?: string\n providerName?: string\n}\n\n/** 语言 → 扩展名(用于判断哪些文件触发该语言服务器)。 */\nexport const LSP_LANG_EXT: Record<string, string[]> = {\n lua: ['lua'],\n csharp: ['cs', 'csx'],\n}\n\n/** 平台目录名(LuaLS/OmniSharp 的 server/bin/<平台>)。 */\nexport function platformServerDir(platform = process.platform): string {\n if (platform === 'win32') return 'Windows'\n if (platform === 'darwin') return 'macOS'\n return 'Linux'\n}\n\n/** exe 后缀(Windows 为 .exe)。 */\nexport function exeSuffix(platform = process.platform): string {\n return platform === 'win32' ? '.exe' : ''\n}\n\n/** 列出目录下匹配前缀的子目录(如 ~/.vscode/extensions/sumneko.lua-*)。 */\nexport function listMatchingDirs(dir: string, prefix: string): string[] {\n if (!existsSync(dir)) return []\n let entries: Dirent[]\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch (error) {\n return []\n }\n return entries.filter((e) => e.isDirectory() && e.name.startsWith(prefix)).map((e) => join(dir, e.name))\n}\n\n/**\n * VSCode 扩展目录(~/.vscode/extensions、~/.vscode-server/extensions + extmgr 目录;无则空数组)。\n * 测试可用 DSH_LSP_EXT_DIRS(平台路径分隔符分隔)完全覆盖扫描列表,避免受真实机器扩展影响。\n * @author ddj 2026年09月03号\n */\nexport function vscodeExtensionsDirs(home = dshHome()): string[] {\n const override = process.env.DSH_LSP_EXT_DIRS\n if (override) {\n return override.split(sep === '\\\\' ? ';' : ':').map((dir) => dir.trim()).filter((dir) => dir && existsSync(dir))\n }\n const userHome = homedir()\n return [\n join(userHome, '.vscode', 'extensions'),\n join(userHome, '.vscode-server', 'extensions'),\n extensionsRoot(home),\n ].filter((dir) => existsSync(dir))\n}\n\n// --region 扩展源 provider 挂载点(extmgr 安装扩展后注册;kind=extension)\n/** 扩展源 provider 注册表:languageId → 启动参数。 */\nconst extProviders = new Map<string, { argv: string[]; cwd?: string; version?: string }>()\n\n/**\n * 注册扩展源 provider(extmgr 安装的 VSIX 扩展调用;覆盖/清除传空 argv 可注销)。\n * @author ddj 2026年08月27号\n * @param languageId 语言 id\n * @param argv 启动参数(argv[0] 为可执行)\n * @param cwd 工作目录\n * @param version 扩展版本(诊断展示)\n */\nexport function registerExtensionProvider(languageId: string, argv: string[], cwd?: string, version?: string): void {\n if (!argv.length) {\n extProviders.delete(languageId)\n return\n }\n extProviders.set(languageId, { argv, cwd, version })\n}\n\n/** 取扩展源 provider spec(未注册返回 null)。 */\nexport function extensionProviderFor(languageId: string): LspProviderSpec | null {\n const p = extProviders.get(languageId)\n if (!p || !p.argv.length) return null\n return { languageId, kind: 'extension', argv: p.argv, cwd: p.cwd, ready: true, version: p.version, providerName: '语言服务器扩展' }\n}\n\n/** 清空全部扩展源注册(插件卸载/扩展目录重建时)。 */\nexport function clearExtensionProviders(): void {\n extProviders.clear()\n}\n// --endregion\n\n/** PATH 中查找可执行文件(不含扩展名校验,交由 spawn 报错)。 */\nexport function findInPath(name: string): string | null {\n const pathEnv = process.env.PATH ?? ''\n const exts = process.platform === 'win32' ? ['', '.exe', '.cmd', '.bat'] : ['']\n for (const dir of pathEnv.split(sep === '\\\\' ? ';' : ':')) {\n if (!dir) continue\n for (const ext of exts) {\n const candidate = join(dir, name + ext)\n if (existsSync(candidate)) return candidate\n }\n }\n return null\n}\n\n/** dotnet 候选(PATH 命中 + 常见安装路径 + 用户级安装位置),仅保留真实存在者。 */\nexport function dotnetCandidates(): string[] {\n const localAppData = process.env.LOCALAPPDATA\n const out = [\n findInPath('dotnet'),\n 'C:/Program Files/dotnet/dotnet.exe',\n 'C:/Program Files (x86)/dotnet/dotnet.exe',\n localAppData ? join(localAppData, 'Microsoft', 'dotnet', 'dotnet.exe') : null,\n ]\n return out.filter((p): p is string => !!p && existsSync(p))\n}\n\n/** 查找 dotnet(PATH + 常见安装路径)。 */\nexport function findDotnet(): string | null {\n return dotnetCandidates()[0] ?? null\n}\n\n/**\n * 查找具备指定 .NET 运行时大版本的 dotnet(按 dotnetCandidates 顺序探测)。\n * @author ddj 2026年09月03号\n * @param minMajor 运行时最低大版本(如 10)\n * @param candidates dotnet 候选路径(缺省 dotnetCandidates();测试可注入)\n * @returns 满足条件的 dotnet 路径;无满足者返回 null\n */\nexport function dotnetWithRuntime(minMajor: number, candidates: string[] = dotnetCandidates()): string | null {\n for (const dotnet of candidates) {\n const sharedDir = join(dirname(dotnet), 'shared', 'Microsoft.NETCore.App')\n let versions: string[] = []\n try {\n versions = readdirSync(sharedDir)\n } catch (error) {\n continue\n }\n const found = versions.some((name) => {\n const major = Number.parseInt(name.split('.')[0] ?? '', 10)\n return Number.isInteger(major) && major >= minMajor\n })\n if (found) return dotnet\n }\n return null\n}\n\n/**\n * 探测含 .NET SDK 的 dotnet 根目录(MSBuild 工程求值与 restore 需要,runtime-only 不够)。\n * @author ddj 2026年09月03号\n * @param candidates dotnet 候选路径(缺省 dotnetCandidates();测试可注入)\n * @returns 含 SDK 的 dotnet 根目录;无则 null\n */\nexport function findSdkRoot(candidates: string[] = dotnetCandidates()): string | null {\n for (const dotnet of candidates) {\n const root = dirname(dotnet)\n if (sdkVersionOf(root)) return root\n }\n return null\n}\n\n/**\n * dotnet 根目录下最新 SDK 版本号(无 SDK 返回 null)。\n * @author ddj 2026年09月03号\n * @param root dotnet 根目录\n * @returns SDK 版本号\n */\nexport function sdkVersionOf(root: string): string | null {\n try {\n const versions = readdirSync(join(root, 'sdk')).filter((name) => /^\\d+\\.\\d+/.test(name))\n if (!versions.length) return null\n return versions.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }))[0] ?? null\n } catch (error) {\n return null\n }\n}\n\n/**\n * C# 服务器所需的 MSBuild 环境变量(SDK 解析 + restore 的 muxer 定位)。\n * @author ddj 2026年09月03号\n * @param sdkRoot 含 SDK 的 dotnet 根目录\n * @returns 环境变量表\n */\nexport function sdkEnvOf(sdkRoot: string): Record<string, string> {\n const version = sdkVersionOf(sdkRoot)\n const env: Record<string, string> = {\n DOTNET_ROOT: sdkRoot,\n DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR: sdkRoot,\n }\n if (version) env.DOTNET_SDK_PATH = join(sdkRoot, 'sdk', version)\n return env\n}\n\n/** 读扩展目录 package.json 的 version(读取失败不影响入口使用,返回 undefined)。 */\nfunction manifestVersionOf(extDir: string): string | undefined {\n try {\n const manifest = JSON.parse(readFileSync(join(extDir, 'package.json'), 'utf8')) as { version?: unknown }\n return typeof manifest.version === 'string' ? manifest.version : undefined\n } catch (error) {\n return undefined\n }\n}\n\n/** EmmyLua 自动发现候选(tangzx.emmylua-* / server/emmylua_ls)。 */\nexport function candidateEmmyLua(home = dshHome()): { path: string; version?: string } | null {\n const candidates: { path: string; version?: string }[] = []\n for (const dir of vscodeExtensionsDirs(home)) {\n for (const extDir of listMatchingDirs(dir, 'tangzx.emmylua-')) {\n const server = join(extDir, 'server', 'emmylua_ls' + exeSuffix())\n if (!existsSync(server)) continue\n candidates.push({ path: server, version: manifestVersionOf(extDir) })\n }\n }\n candidates.sort((a, b) => (b.version ?? '').localeCompare(a.version ?? '', undefined, { numeric: true }) || a.path.localeCompare(b.path))\n return candidates[0] ?? null\n}\n\n/**\n * LuaLS 自动发现候选(VSCode 扩展目录 + extmgr 目录下 sumneko.lua-* 的 server/bin 可执行)。\n * 多版本并存时按清单版本降序、路径升序排序(与 EmmyLua/DotRush 发现的排序策略一致)。\n * @author ddj 2026年09月03号\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns 排序后的候选列表(首个为建议选用者)\n */\nexport function candidateLuaServers(home = dshHome()): { path: string; version?: string }[] {\n const plat = platformServerDir()\n const suffix = exeSuffix()\n const out: { path: string; version?: string }[] = []\n for (const dir of vscodeExtensionsDirs(home)) {\n for (const extDir of listMatchingDirs(dir, 'sumneko.lua-')) {\n const binDir = join(extDir, 'server', 'bin')\n const binName = 'lua-language-server' + suffix\n // 新布局(3.x 平台变体 vsix):server/bin/xxx.exe;旧布局:server/bin/<平台>/xxx.exe\n const bin = existsSync(join(binDir, binName)) ? join(binDir, binName) : join(binDir, plat, binName)\n if (existsSync(bin) && !out.some((c) => c.path === bin)) out.push({ path: bin, version: manifestVersionOf(extDir) })\n }\n }\n return out.sort((a, b) => (b.version ?? '').localeCompare(a.version ?? '', undefined, { numeric: true }) || a.path.localeCompare(b.path))\n}\n\n/** C# 服务器发现结果(ms-Roslyn / DotRush / OmniSharp + 系统 dotnet;各取清单版本最高者)。 */\nexport interface CSharpCandidates {\n roslynDll?: string\n roslynVersion?: string\n dotrushDll?: string\n dotrushVersion?: string\n omnisharpExe?: string\n dotnet?: string\n}\n\n/**\n * C# 自动发现候选:ms-dotnettools.csharp 的 Roslyn dll(需 dotnet)/ OmniSharp 可执行,\n * 以及 DotRush 扩展自带服务器(extension/bin/LanguageServer/DotRush.dll,需对应 .NET 运行时)。\n * 同类多版本并存时取清单版本最高者(与 EmmyLua/DotRush 发现的排序策略一致)。\n * @author ddj 2026年09月03号\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns 发现结果\n */\nexport function candidateCSharpServers(home = dshHome()): CSharpCandidates {\n const out: CSharpCandidates = {}\n /** 命中收集 → 清单版本降序取最高(平级按路径稳定排序)。 */\n const bestOf = (hits: { entry: string; version?: string }[]): { entry: string; version?: string } | null =>\n hits.sort((a, b) => (b.version ?? '').localeCompare(a.version ?? '', undefined, { numeric: true }) || a.entry.localeCompare(b.entry))[0] ?? null\n const roslynHits: { entry: string; version?: string }[] = []\n const omniHits: { entry: string; version?: string }[] = []\n const dotrushHits: { entry: string; version?: string }[] = []\n for (const dir of vscodeExtensionsDirs(home)) {\n for (const extDir of listMatchingDirs(dir, 'ms-dotnettools.csharp-')) {\n const version = manifestVersionOf(extDir)\n const roslyn = join(extDir, '.roslyn', 'Microsoft.CodeAnalysis.LanguageServer.dll')\n if (existsSync(roslyn)) roslynHits.push({ entry: roslyn, version })\n const omni = join(extDir, '.omnisharp', 'OmniSharp' + exeSuffix())\n if (existsSync(omni)) omniHits.push({ entry: omni, version })\n }\n for (const extDir of listMatchingDirs(dir, 'nromanov.dotrush-')) {\n const dll = join(extDir, 'extension', 'bin', 'LanguageServer', 'DotRush.dll')\n if (!existsSync(dll)) continue\n dotrushHits.push({ entry: dll, version: manifestVersionOf(extDir) })\n }\n }\n const roslynBest = bestOf(roslynHits)\n if (roslynBest) {\n out.roslynDll = roslynBest.entry\n out.roslynVersion = roslynBest.version\n }\n const omniBest = bestOf(omniHits)\n if (omniBest) out.omnisharpExe = omniBest.entry\n const dotrushBest = bestOf(dotrushHits)\n if (dotrushBest) {\n out.dotrushDll = dotrushBest.entry\n out.dotrushVersion = dotrushBest.version\n }\n const dotnet = findDotnet()\n if (dotnet) out.dotnet = dotnet\n return out\n}\n\n/**\n * 从服务器 dll 同目录的 *.runtimeconfig.json 解析所需 .NET 运行时大版本。\n * @author ddj 2026年09月03号\n * @param dllDir 服务器 dll 所在目录\n * @returns 运行时大版本;无清单或解析失败返回 null\n */\nexport function runtimeMajorOf(dllDir: string): number | null {\n try {\n for (const name of readdirSync(dllDir)) {\n if (!name.endsWith('.runtimeconfig.json')) continue\n const config = JSON.parse(readFileSync(join(dllDir, name), 'utf8')) as { runtimeOptions?: { framework?: { version?: unknown } } }\n const version = config.runtimeOptions?.framework?.version\n if (typeof version !== 'string') continue\n const major = Number.parseInt(version.split('.')[0] ?? '', 10)\n if (Number.isInteger(major)) return major\n }\n } catch (error) { /* 清单读取失败按无约束处理 */ }\n return null\n}\n\n/**\n * 解析 DotRush 启动参数:优先扩展内置 SDK dotnet,否则找满足其运行时大版本的 dotnet。\n * @author ddj 2026年09月03号\n * @param dll DotRush.dll 绝对路径\n * @returns argv 可直接启动;reason 为不可启动的原因\n */\nfunction dotrushLaunch(dll: string): { argv: string[] } | { reason: string } {\n const sdkDotnet = join(dirname(dirname(dll)), 'Sdk', 'dotnet' + exeSuffix())\n const major = runtimeMajorOf(dirname(dll))\n const dotnet = existsSync(sdkDotnet) ? sdkDotnet : major !== null ? dotnetWithRuntime(major) : findDotnet()\n if (dotnet) return { argv: [dotnet, dll] }\n return { reason: 'DotRush 需 .NET ' + (major ?? '') + ' 运行时,未找到满足的 dotnet' }\n}\n\n/**\n * 手动配置归一化:path 指向可执行文件/目录,command 为可执行名(PATH 解析)。\n * 未配置时返回空 reason(由各 resolve 兜底输出语言相关安装指引文案)。\n * @author ddj 2026年08月27号\n */\nexport function manualSpec(manual: { command?: string; path?: string } | undefined): { argv: string[]; cwd?: string; ready: boolean; reason?: string } {\n if (!manual) return { argv: [], ready: false }\n const pathValue = typeof manual.path === 'string' && manual.path.trim() ? manual.path.trim() : ''\n const commandValue = typeof manual.command === 'string' && manual.command.trim() ? manual.command.trim() : ''\n if (!pathValue && !commandValue) return { argv: [], ready: false }\n if (pathValue) {\n if (!existsSync(pathValue)) return { argv: [], ready: false, reason: '路径不存在:' + pathValue }\n return { argv: [pathValue], ready: true }\n }\n const found = findInPath(commandValue)\n if (!found) return { argv: [], ready: false, reason: 'PATH 中找不到命令:' + commandValue }\n return { argv: [found], ready: true }\n}\n\n/**\n * 解析 Lua provider(优先级:手动 > 扩展源 > 自动发现)。\n * @author ddj 2026年08月27号\n * @param manual 手动配置\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns provider 规格\n */\nexport function resolveLuaProvider(manual?: { command?: string; path?: string }, home = dshHome()): LspProviderSpec {\n const base = { languageId: 'lua' }\n const manualResolved = manualSpec(manual)\n if (manualResolved.ready) return { ...base, kind: 'manual', argv: manualResolved.argv, cwd: manualResolved.cwd, ready: true }\n return resolveCached('lua', manual, home, (h) => {\n const ext = extensionProviderFor('lua')\n if (ext) return ext\n const emmy = candidateEmmyLua(h)\n if (emmy) return { ...base, kind: 'extension', argv: [emmy.path], ready: true, version: emmy.version, providerName: 'EmmyLua' }\n const candidates = candidateLuaServers(h)\n const best = candidates[0]\n if (best) return { ...base, kind: 'discover', argv: [best.path], cwd: undefined, ready: true, version: best.version, providerName: 'LuaLS' }\n const inPath = findInPath('lua-language-server' + exeSuffix())\n if (inPath) return { ...base, kind: 'discover', argv: [inPath], ready: true }\n return { ...base, kind: 'none', argv: [], ready: false, reason: manualResolved.reason ?? '未发现 lua-language-server(可安装 LuaLS 或手动指定路径)' }\n })\n}\n\n/**\n * 解析 C# provider(优先级:手动 > 扩展源 > 自动发现;Roslyn dll 需 dotnet;\n * DotRush 需满足其运行时的 dotnet;或 OmniSharp)。\n * @author ddj 2026年08月27号\n * @param manual 手动配置\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns provider 规格\n */\nexport function resolveCSharpProvider(manual?: { command?: string; path?: string }, home = dshHome()): LspProviderSpec {\n const base = { languageId: 'csharp' }\n const manualResolved = manualSpec(manual)\n if (manualResolved.ready) return { ...base, kind: 'manual', argv: manualResolved.argv, cwd: manualResolved.cwd, ready: true }\n return resolveCached('csharp', manual, home, (h) => {\n const ext = extensionProviderFor('csharp')\n if (ext) return ext\n const discovered = candidateCSharpServers(h)\n // SDK 环境注入:runtime-only 的 dotnet 会导致 MSBuild 求值/restore 退化\n const sdkRoot = findSdkRoot()\n const msbuildEnv = sdkRoot ? sdkEnvOf(sdkRoot) : undefined\n if (discovered.roslynDll && discovered.dotnet) {\n return { ...base, kind: 'discover', argv: [discovered.dotnet, discovered.roslynDll, '--stdio'], env: msbuildEnv, ready: true }\n }\n let dotrushReason: string | null = null\n let provisionMajor: number | undefined\n if (discovered.dotrushDll) {\n const major = runtimeMajorOf(dirname(discovered.dotrushDll))\n const launch = dotrushLaunch(discovered.dotrushDll)\n if ('argv' in launch) {\n return { ...base, kind: 'discover', argv: launch.argv, env: msbuildEnv, ready: true, version: discovered.dotrushVersion, providerName: 'DotRush' }\n }\n dotrushReason = launch.reason\n provisionMajor = major ?? undefined\n }\n if (discovered.omnisharpExe) {\n return { ...base, kind: 'discover', argv: [discovered.omnisharpExe, '--stdio'], ready: true }\n }\n const reasons: string[] = []\n if (dotrushReason) {\n reasons.push(dotrushReason)\n } else {\n if (!discovered.dotnet) reasons.push('未找到 dotnet')\n reasons.push('未发现 ms-dotnettools.csharp / DotRush 扩展')\n }\n return { ...base, kind: 'none', argv: [], ready: false, provisionRuntime: provisionMajor, reason: reasons.join(';') + '(可手动指定 Roslyn/OmniSharp 入口)' }\n })\n}\n\n/** 语言 → provider 解析器(可扩展;Phase 2 由 extmgr 注册扩展源 provider)。 */\nexport type ProviderResolver = (manual?: { command?: string; path?: string }) => LspProviderSpec\n\nexport const PROVIDER_RESOLVERS: Record<string, ProviderResolver> = {\n lua: resolveLuaProvider,\n csharp: resolveCSharpProvider,\n}\n\n/**\n * 汇总某语言当前检测到的候选服务器(每类服务器一条、取该类最高版本;设置页展示用)。\n * chosen 以候选路径命中 spec.argv 判定;未选用(kind=none/manual 不匹配)时不标记。\n * @author ddj 2026年09月03号\n * @param languageId 语言 id\n * @param spec 已解析的 provider 规格\n * @param home DSH home(缺省真实;测试可注入临时目录)\n * @returns 候选列表(不支持的语言/检测异常返回空)\n */\nexport function candidatesFor(languageId: string, spec: LspProviderSpec, home = dshHome()): LspCandidate[] {\n /** 候选路径命中 spec.argv 时补 chosen 标记。 */\n const markChosen = (candidate: LspCandidate): LspCandidate =>\n spec.ready && candidate.path && spec.argv.includes(candidate.path) ? { ...candidate, chosen: true } : candidate\n try {\n if (languageId === 'lua') {\n const out: LspCandidate[] = []\n const emmy = candidateEmmyLua(home)\n if (emmy) out.push(markChosen({ name: 'EmmyLua', version: emmy.version, path: emmy.path }))\n const lua = candidateLuaServers(home)[0]\n if (lua) out.push(markChosen({ name: 'LuaLS(sumneko.lua)', version: lua.version, path: lua.path }))\n const inPath = findInPath('lua-language-server' + exeSuffix())\n if (inPath) out.push(markChosen({ name: 'lua-language-server(PATH)', path: inPath }))\n return out\n }\n if (languageId === 'csharp') {\n const out: LspCandidate[] = []\n const found = candidateCSharpServers(home)\n if (found.roslynDll) out.push(markChosen({ name: 'Roslyn(ms-dotnettools.csharp)', version: found.roslynVersion, path: found.roslynDll }))\n if (found.dotrushDll) out.push(markChosen({ name: 'DotRush', version: found.dotrushVersion, path: found.dotrushDll }))\n if (found.omnisharpExe) out.push(markChosen({ name: 'OmniSharp', path: found.omnisharpExe }))\n return out\n }\n return []\n } catch (error) {\n return []\n }\n}\n\n/** 手动配置是否为绝对路径可执行(供设置页判断输入类型)。 */\nexport function looksAbsolute(value: string): boolean {\n return isAbsolute(value)\n}\n\n// --region provider 发现结果缓存(进程级 + 磁盘持久化)\n/**\n * 发现结果缓存:只缓存\"自动发现/扩展源\"结论,不缓存 manual(用户改配置要立即生效)。\n * 进程内 Map 命中优先;未命中读磁盘缓存(跨会话/跨重启共享);仍无才真扫描。\n * 缓存条目按\"配置签名 + 扩展目录指纹\"校验,任一变化即失效重扫。\n * 作者 ddj 2026年08月28号\n */\n\n/** 缓存条目:spec + 生成时的环境指纹。 */\ninterface SpecCacheEntry {\n spec: LspProviderSpec\n fingerprint: string\n at: number\n}\n\n/** 进程级缓存(home|languageId → 条目),同一 DSH home 的不同会话共享。 */\nconst specCache = new Map<string, SpecCacheEntry>()\n/** 磁盘缓存是否已载入本进程(home → loaded),不同 profile 不串缓存。 */\nconst diskLoaded = new Set<string>()\n/** 自动发现成功结果的复用时长;过期后才检查目录指纹。 */\nconst SPEC_CACHE_TTL_MS = 30 * 60 * 1000\n/** 未发现结果的短缓存时长,避免缺失服务器时反复扫描 PATH。 */\nconst SPEC_NEGATIVE_CACHE_MS = 60 * 1000\n\n/** 生成带 home 的缓存键,避免不同 profile 的 provider 结果串用。 */\nfunction cacheEntryKey(home: string, languageId: string): string {\n return home + '|' + languageId\n}\n\n/**\n * 构造缓存 key:语言 + 手动配置(manual 结果不缓存,故只参与\"是否走缓存\"判定)。\n * @author ddj 2026年08月28号\n * @param languageId 语言 id\n * @param manual 手动配置\n * @returns 缓存 key(manual 有效时返回空串表示跳过缓存)\n */\nfunction cacheKeyOf(languageId: string, manual?: { command?: string; path?: string }): string {\n const pathValue = manual?.path?.trim() ?? ''\n const commandValue = manual?.command?.trim() ?? ''\n if (pathValue || commandValue) return '' // 手动配置:不缓存,立即生效\n return languageId\n}\n\n/**\n * 环境指纹:扩展目录清单 + 平台。目录增删/换平台即失效(防缓存陈旧指向已删扩展)。\n * @author ddj 2026年08月28号\n * @param home DSH home\n * @returns 指纹串\n */\nfunction fingerprintOf(home: string): string {\n const dirs = vscodeExtensionsDirs(home)\n const marks = dirs.map((dir) => {\n try {\n return readdirSync(dir).sort().join(',')\n } catch (error) {\n return '?'\n }\n })\n return process.platform + '|' + (findSdkRoot() ?? 'no-sdk') + '|' + marks.join('|')\n}\n\n/**\n * 读取磁盘缓存(幂等:每进程只载一次;schema 文件名已隔离版本)。\n * @author ddj 2026年08月28号\n * @param home DSH home\n */\nfunction loadDiskCache(home: string): void {\n if (diskLoaded.has(home)) return\n diskLoaded.add(home)\n const file = lspSpecCacheFile(home)\n try {\n const raw = JSON.parse(readFileSync(file, 'utf8')) as Record<string, SpecCacheEntry>\n for (const [languageId, entry] of Object.entries(raw)) {\n if (entry && typeof entry === 'object' && entry.spec && typeof entry.fingerprint === 'string') {\n specCache.set(cacheEntryKey(home, languageId), entry)\n }\n }\n } catch (error) { /* 首次运行/损坏:静默降级为真扫描 */ }\n}\n\n/**\n * 写回磁盘缓存(best-effort;写失败不影响本次解析结果)。\n * @author ddj 2026年08月28号\n * @param home DSH home\n */\nfunction saveDiskCache(home: string): void {\n const file = lspSpecCacheFile(home)\n try {\n mkdirSync(dirname(file), { recursive: true })\n const out: Record<string, SpecCacheEntry> = {}\n const prefix = home + '|'\n for (const [key, entry] of specCache) if (key.startsWith(prefix)) out[key.slice(prefix.length)] = entry\n writeFileSync(file, JSON.stringify(out), 'utf8')\n } catch (error) { /* 写入失败静默 */ }\n}\n\n/**\n * 带缓存执行 provider 解析(自动发现路径专用)。\n * @author ddj 2026年08月28号\n * @param languageId 语言 id\n * @param manual 手动配置\n * @param home DSH home\n * @param resolve 真解析函数(未命中时调用)\n * @returns provider 规格\n */\nfunction resolveCached(\n languageId: string,\n manual: { command?: string; path?: string } | undefined,\n home: string,\n resolve: (h: string) => LspProviderSpec,\n): LspProviderSpec {\n const key = cacheKeyOf(languageId, manual)\n if (!key) return resolve(home) // 手动配置:不走缓存\n loadDiskCache(home)\n const fullKey = cacheEntryKey(home, key)\n const hit = specCache.get(fullKey)\n if (hit && isCacheFresh(hit)) return hit.spec\n const fingerprint = fingerprintOf(home)\n if (hit && hit.fingerprint === fingerprint) {\n hit.at = Date.now()\n return hit.spec\n }\n const spec = resolve(home)\n specCache.set(fullKey, { spec, fingerprint, at: Date.now() })\n saveDiskCache(home)\n return spec\n}\n\n/** 判断缓存条目是否仍可直接复用,不触发扩展目录扫描。 */\nfunction isCacheFresh(entry: SpecCacheEntry): boolean {\n const age = Date.now() - entry.at\n const ttl = entry.spec.kind === 'none' ? SPEC_NEGATIVE_CACHE_MS : SPEC_CACHE_TTL_MS\n if (age < 0 || age >= ttl) return false\n const executable = entry.spec.argv[0]\n return !entry.spec.ready || !executable || existsSync(executable)\n}\n\n/**\n * 清空 provider 发现缓存(扩展安装/卸载、配置变更后调用;进程级 + 删磁盘文件)。\n * @author ddj 2026年08月28号\n * @param home DSH home(缺省真实)\n */\nexport function clearProviderCache(home = dshHome()): void {\n const prefix = home + '|'\n for (const key of specCache.keys()) if (key.startsWith(prefix)) specCache.delete(key)\n diskLoaded.delete(home)\n try {\n rmSync(lspSpecCacheFile(home), { force: true })\n } catch (error) { /* 删除失败静默 */ }\n}\n// --endregion\n","/**\n * dsh-vscode-mode host — C# 服务器 .NET 运行时自动配置。\n * DotRush 等服务器需要 .NET 运行时;缺失时从官方 release 元数据解析下载地址,\n * sha512 校验后解压到用户级 dotnet 目录(win: %LOCALAPPDATA%\\Microsoft\\dotnet,\n * unix: ~/.dotnet),成功后通知监听者重载 provider——用户零手动操作。\n * 失败静默降级(保留原 reason 文案),10 分钟退避重试。\n * 安装全程有状态机(envInstallStates)供设置页一键安装与进度轮询使用。\n * 作者 ddj 2026年09月03号\n */\nimport { spawn } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { dotnetWithRuntime } from './providers.js'\nimport type { LspEnvInstallState } from '../shared/lsp.js'\nimport { unzip } from './zip.js'\n\n/** release 元数据 files 元素子集(官方 releases.json)。 */\nexport interface RuntimeAsset {\n name: string\n url: string\n hash: string\n}\n\nconst META_BASE = 'https://builds.dotnet.microsoft.com/dotnet/release-metadata'\nconst RETRY_MS = 10 * 60 * 1000\n\n/** 同 major 去重(in-flight)。 */\nconst inFlight = new Map<number, Promise<boolean>>()\n/** 失败时间戳(退避重试)。 */\nconst failedAt = new Map<number, number>()\n/** 配置成功监听者(重载 provider 缓存与服务器)。 */\nconst listeners = new Set<() => void>()\n/** 安装进行态(major → phase/message),供设置页轮询展示。 */\nconst installStates = new Map<number, { phase: LspEnvInstallState['phase']; message?: string }>()\n\n/** 需求 id(与 envRequirements 的 id 一致)。 */\nexport function runtimeRequirementId(major: number): string {\n return 'dotnet-runtime:' + major\n}\n\n/** 当前安装进行态快照(edrv.lsp.envState 载荷)。 */\nexport function envInstallStates(): LspEnvInstallState[] {\n return [...installStates.entries()].map(([major, state]) => ({\n id: runtimeRequirementId(major),\n phase: state.phase,\n message: state.message,\n }))\n}\n\n/** 注册配置成功监听(成功后由 rpc 侧清缓存并重置服务器)。 */\nexport function onRuntimeProvisioned(listener: () => void): void {\n listeners.add(listener)\n}\n\n/** 平台 → 官方运行时资产文件名。 */\nfunction assetNameFor(platform: string, arch: string): string {\n const archPart = arch === 'arm64' ? 'arm64' : 'x64'\n if (platform === 'win32') return 'dotnet-runtime-win-' + archPart + '.zip'\n if (platform === 'darwin') return 'dotnet-runtime-osx-' + archPart + '.tar.gz'\n return 'dotnet-runtime-linux-' + archPart + '.tar.gz'\n}\n\n/** 用户级 dotnet 安装目录(与 providers 的发现候选位置一致)。 */\nexport function userDotnetDir(): string {\n if (process.platform === 'win32') {\n return join(process.env.LOCALAPPDATA ?? join(homedir(), 'AppData', 'Local'), 'Microsoft', 'dotnet')\n }\n return join(homedir(), '.dotnet')\n}\n\n/** 从 release 元数据 files 里挑当前平台资产(纯函数,测试可注入平台)。 */\nexport function pickRuntimeAsset(files: RuntimeAsset[], platform = process.platform, arch = process.arch): RuntimeAsset | null {\n const name = assetNameFor(platform, arch)\n return files.find((f) => f.name === name) ?? null\n}\n\n/** 是否允许自动配置(测试隔离 + 显式开关)。 */\nfunction allowed(): boolean {\n if (process.env.DSH_LSP_AUTO_RUNTIME === '0') return false\n if (process.env.DSH_LSP_EXT_DIRS) return false // 测试环境不下载\n return true\n}\n\nfunction setState(major: number, phase: LspEnvInstallState['phase'], message?: string): void {\n installStates.set(major, { phase, message })\n}\n\nfunction notifyListeners(): void {\n for (const listener of listeners) {\n try {\n listener()\n } catch { /* 单个监听失败不影响其它 */ }\n }\n}\n\n/**\n * 触发运行时自动配置(幂等:同 major 去重;失败 10 分钟退避;已满足则直接成功回调)。\n * 静默自动路径与设置页一键安装共用;进度经 envInstallStates 暴露。\n * @author ddj 2026年09月03号\n * @param major 运行时大版本\n */\nexport function provisionRuntime(major: number): void {\n if (inFlight.has(major)) return\n const failed = failedAt.get(major)\n if (failed && Date.now() - failed < RETRY_MS) return\n const task = runProvision(major)\n .catch(() => false)\n .then((ok) => {\n inFlight.delete(major)\n if (ok) {\n failedAt.delete(major)\n setState(major, 'done')\n notifyListeners()\n } else {\n failedAt.set(major, Date.now())\n setState(major, 'failed')\n }\n return ok\n })\n inFlight.set(major, task)\n}\n\n/**\n * 一键安装入口(设置页按钮):校验允许后触发 provisionRuntime。\n * @author ddj 2026年09月03号\n * @param major 运行时大版本\n * @returns 是否成功启动(已满足/进行中/被禁用时返回 false)\n */\nexport function startEnvInstall(major: number): boolean {\n if (dotnetWithRuntime(major)) {\n setState(major, 'done')\n return false\n }\n if (!allowed() || inFlight.has(major)) return false\n const failed = failedAt.get(major)\n if (failed && Date.now() - failed < RETRY_MS && installStates.get(major)?.phase === 'failed') {\n // 退避期内失败态:允许用户手动重试(清除退避标记)\n failedAt.delete(major)\n }\n provisionRuntime(major)\n return inFlight.has(major)\n}\n\nasync function runProvision(major: number): Promise<boolean> {\n if (dotnetWithRuntime(major)) return true\n setState(major, 'downloading')\n const meta = await fetchJson(META_BASE + '/' + major + '.0/releases.json')\n const release = meta?.releases?.[0]\n const files = release?.runtime?.files\n if (!Array.isArray(files)) return false\n const asset = pickRuntimeAsset(files as RuntimeAsset[])\n if (!asset?.url || !asset.hash) return false\n const buf = await downloadVerified(asset.url, asset.hash)\n if (!buf) return false\n setState(major, 'extracting')\n const dir = userDotnetDir()\n const created = !existsSync(dir)\n try {\n const ok = await extractTo(buf, dir)\n if (!ok) throw new Error('解压失败')\n } catch (error) {\n if (created) rmSync(dir, { recursive: true, force: true })\n return false\n }\n return dotnetWithRuntime(major) !== null\n}\n\n/** 拉取 JSON(30s 超时,失败返回 null)。 */\nasync function fetchJson(url: string): Promise<{ releases?: { runtime?: { files?: unknown } }[] } | null> {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(30000) })\n if (!res.ok) return null\n return await res.json()\n } catch {\n return null\n }\n}\n\n/** 下载并按官方 sha512 校验(5 分钟超时,不匹配返回 null)。 */\nasync function downloadVerified(url: string, sha512: string): Promise<Buffer | null> {\n try {\n const res = await fetch(url, { signal: AbortSignal.timeout(300000) })\n if (!res.ok) return null\n const buf = Buffer.from(await res.arrayBuffer())\n const actual = createHash('sha512').update(buf).digest('hex').toLowerCase()\n return actual === sha512.toLowerCase() ? buf : null\n } catch {\n return null\n }\n}\n\n/** 解压到目录:win 走 zip(PK 头),unix 落临时包交系统 tar。 */\nasync function extractTo(buf: Buffer, dir: string): Promise<boolean> {\n mkdirSync(dir, { recursive: true })\n if (buf.subarray(0, 2).toString('ascii') === 'PK') {\n for (const entry of unzip(buf)) {\n if (!entry.path || entry.path.startsWith('..')) continue\n const parts = entry.path.split(/[\\\\/]/).filter((p) => p && p !== '..' && p !== '.')\n if (!parts.length) continue\n const target = join(dir, ...parts)\n if (entry.isDirectory) {\n mkdirSync(target, { recursive: true })\n continue\n }\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, entry.data)\n }\n return true\n }\n const tmp = join(tmpdir(), 'dsh-dotnet-' + Date.now() + '.tar.gz')\n try {\n writeFileSync(tmp, buf)\n return await new Promise<boolean>((resolve) => {\n const child = spawn('tar', ['-xzf', tmp, '-C', dir], { stdio: 'ignore' })\n child.on('exit', (code) => resolve(code === 0))\n child.on('error', () => resolve(false))\n })\n } finally {\n rmSync(tmp, { force: true })\n }\n}\n","/**\n * dsh-vscode-mode host — LSP 配置读取与 provider 解析装配。\n * 配置来源优先级:运行时覆盖(设置页保存,重启失效)> 插件组合配置 > 默认。\n * 原 settings section(ns dsh-vscode-mode.languageServers)命名空间不合法\n * (DSH settings 仅允许 /^[a-z][a-z0-9-]*$/,点号命名空间永久不可注册),\n * 已降级为配置值(插件组合配置 + 会话内运行时覆盖),不再尝试 settings 安装。\n * 作者 ddj 2026-08-27 / 2026-09-02\n */\nimport { PROVIDER_RESOLVERS, type LspProviderSpec } from './providers.js'\nimport { provisionRuntime } from './dotnetProvision.js'\n\n/** 单语言配置。 */\nexport interface LspLangConfig {\n enabled?: boolean\n command?: string\n path?: string\n}\n\n/** LSP 配置(按语言)。 */\nexport interface LspConfig {\n lua?: LspLangConfig\n csharp?: LspLangConfig\n [languageId: string]: LspLangConfig | undefined\n}\n\nexport const LSP_LANGUAGES = ['lua', 'csharp'] as const\n\n/** 清洗单语言配置:仅保留合法字段并剥离 undefined(稀疏覆盖语义,清空字段即回落组合配置)。 */\nexport function sanitizeLang(raw: unknown): LspLangConfig | undefined {\n if (!raw || typeof raw !== 'object') return undefined\n const obj = raw as Record<string, unknown>\n const out: LspLangConfig = {}\n if (typeof obj.enabled === 'boolean') out.enabled = obj.enabled\n if (typeof obj.command === 'string') out.command = obj.command\n if (typeof obj.path === 'string') out.path = obj.path\n return out\n}\n\n/** 从插件组合配置读取。 */\nexport function configFromPlugin(config: unknown): LspConfig {\n const raw = (config as { languageServers?: unknown } | undefined)?.languageServers\n if (!raw || typeof raw !== 'object') return {}\n const out: LspConfig = {}\n for (const lang of LSP_LANGUAGES) {\n const v = sanitizeLang((raw as Record<string, unknown>)[lang])\n if (v) out[lang] = v\n }\n return out\n}\n\n/** 合并配置:上层(运行时覆盖/settings)覆盖插件组合配置。 */\nexport function mergeConfig(a: LspConfig, b: LspConfig): LspConfig {\n const out: LspConfig = { ...a }\n for (const lang of LSP_LANGUAGES) {\n const av = a[lang]\n const bv = b[lang]\n if (bv) out[lang] = { ...av, ...bv }\n else if (av) out[lang] = av\n }\n return out\n}\n\n/**\n * 解析某语言的 provider spec(插件组合配置 + 运行时覆盖层合并后)。\n * @author ddj 2026年08月27号 / 2026年09月02号\n * @param pluginConfig 插件组合配置\n * @param languageId 语言 id\n * @param override 运行时覆盖层(设置页保存值,重启失效;缺省为空)\n * @returns provider 规格\n */\nexport function resolveProviderSpec(pluginConfig: unknown, languageId: string, override?: LspConfig): LspProviderSpec {\n const resolver = PROVIDER_RESOLVERS[languageId]\n if (!resolver) return { languageId, kind: 'none', argv: [], ready: false, reason: '不支持的语言:' + languageId }\n const merged = mergeConfig(configFromPlugin(pluginConfig), override ?? {})\n const lang = merged[languageId]\n if (lang && lang.enabled === false) {\n return { languageId, kind: 'none', argv: [], ready: false, reason: '已在设置中禁用' }\n }\n const spec = resolver({ command: lang?.command, path: lang?.path })\n // DotRush 缺运行时:后台自动下载官方 .NET runtime(用户零操作),完成后经监听者重载\n if (spec.provisionRuntime) provisionRuntime(spec.provisionRuntime)\n return spec\n}\n\n/** 语言 → 扩展名(供客户端判断是否触发 LSP)。 */\nexport function langOfPath(path: string): string | null {\n const base = String(path || '').split(/[\\\\/]/).pop() || ''\n const dot = base.lastIndexOf('.')\n if (dot <= 0) return null\n const ext = base.slice(dot + 1).toLowerCase()\n for (const [lang, exts] of Object.entries({ lua: ['lua'], csharp: ['cs', 'csx'] })) {\n if (exts.includes(ext)) return lang\n }\n return null\n}\n","/**\n * dsh-vscode-mode host — LSP 环境需求检测注册表。\n * 每个语言注册一个检测器:扫描当前环境,返回未满足的需求清单(含一键安装与官网链接信息)。\n * 新接入 LSP:在 CHECKERS 加一个检测器条目;需要内置安装器时在 INSTALLERS 注册同前缀安装函数。\n * 检测在 status/redetect/configUpdate 时执行(不缓存),保证安装完成后状态即时刷新。\n * 作者 ddj 2026年09月03号\n */\nimport { dirname } from 'node:path'\nimport { candidateCSharpServers, dotnetWithRuntime, runtimeMajorOf } from './providers.js'\nimport { startEnvInstall } from './dotnetProvision.js'\nimport type { LspMissingEnv } from '../shared/lsp.js'\n\n/** dotnet 运行时需求构造(DotRush / ms-Roslyn 共用)。 */\nfunction dotnetRuntimeRequirement(major: number, detail: string): LspMissingEnv {\n return {\n id: 'dotnet-runtime:' + major,\n label: '.NET 运行时 ' + major + '.0',\n detail,\n installable: true,\n manualUrl: 'https://dotnet.microsoft.com/download/dotnet/' + major + '.0',\n manualLabel: '官网下载',\n }\n}\n\n/** csharp 检测器:DotRush 缺运行时 / ms-Roslyn 缺 dotnet。 */\nfunction checkCSharp(home: string): LspMissingEnv[] {\n const found = candidateCSharpServers(home)\n const missing: LspMissingEnv[] = []\n if (found.dotrushDll) {\n const major = runtimeMajorOf(dirname(found.dotrushDll))\n if (major !== null && dotnetWithRuntime(major) === null) {\n missing.push(dotnetRuntimeRequirement(major, 'DotRush 语言服务器运行所需'))\n }\n return missing\n }\n if (found.roslynDll && !found.dotnet) {\n // 官方 Roslyn 服务器分支未实测,保守按 LTS 8 基线提示\n missing.push(dotnetRuntimeRequirement(8, 'Roslyn 语言服务器运行所需'))\n }\n return missing\n}\n\n/** lua 检测器:EmmyLua/LuaLS 自带运行时,无外部依赖。 */\nfunction checkLua(): LspMissingEnv[] {\n return []\n}\n\n/** 检测器注册表(按 languageId;新 LSP 在此加条目即可)。 */\nconst CHECKERS: Record<string, (home: string) => LspMissingEnv[]> = {\n lua: checkLua,\n csharp: checkCSharp,\n}\n\n/** 安装器注册表(按需求 id 前缀匹配;新依赖类型在此加条目)。 */\nconst INSTALLERS: { prefix: string; run: (id: string) => boolean }[] = [\n {\n prefix: 'dotnet-runtime:',\n run: (id) => {\n const major = Number.parseInt(id.slice('dotnet-runtime:'.length), 10)\n return Number.isInteger(major) ? startEnvInstall(major) : false\n },\n },\n]\n\n/**\n * 检测某语言未满足的环境需求(仅返回缺失项;检测器异常按无需求处理)。\n * @author ddj 2026年09月03号\n * @param languageId 语言 id\n * @param home DSH home(测试可注入临时目录)\n * @returns 缺失需求清单\n */\nexport function envRequirementsFor(languageId: string, home: string): LspMissingEnv[] {\n const checker = CHECKERS[languageId]\n if (!checker) return []\n try {\n return checker(home)\n } catch {\n return []\n }\n}\n\n/**\n * 尝试一键安装某条需求(存在内置安装器时启动,进行中/已满足返回 false)。\n * @author ddj 2026年09月03号\n * @param id 需求标识(如 dotnet-runtime:10)\n * @returns 是否成功启动安装\n */\nexport function installRequirement(id: string): boolean {\n const installer = INSTALLERS.find((it) => id.startsWith(it.prefix))\n if (!installer) return false\n return installer.run(id)\n}\n","/**\n * dsh-vscode-mode host — edrv.lsp.* RPC handlers。\n * 文档跟踪(openDocs 集合 + root|lang 引用计数)→ 懒启动服务器、用完释放。\n * LSP 配置降级为配置值:插件组合配置 + 会话内运行时覆盖层(原 settings section\n * 命名空间不合法,永久不可注册,见 lsp/config.ts 头注释)。\n * 作者 ddj 2026-08-27 / 2026-09-02\n */\nimport type { Ctx } from '../store.js'\nimport { searchRoot } from '../search/ripgrep.js'\nimport { sessionOf, cwdOf } from '../registry.js'\nimport { resolveProviderSpec, langOfPath, configFromPlugin, mergeConfig, sanitizeLang, LSP_LANGUAGES, type LspConfig, type LspLangConfig } from './config.js'\nimport { clearProviderCache, candidatesFor } from './providers.js'\nimport { onRuntimeProvisioned, envInstallStates } from './dotnetProvision.js'\nimport { envRequirementsFor, installRequirement } from './envRequirements.js'\nimport type { LspManager } from './manager.js'\nimport type { RpcHandlerMap } from '../shared/rpc.js'\nimport type { LspLocation, LspServerStatus } from '../shared/lsp.js'\nimport { installFromMarket, installVsixFile, listInstalled, marketGet, marketSearch, uninstall, updateExtension, type ExtInfo } from './extmgr.js'\nimport { dshHome } from '../paths.js'\n\nexport interface LspRpcDeps {\n ctx: Ctx\n pluginConfig: unknown\n manager: LspManager\n}\n\n/**\n * 打开文档跟踪:openDocs(docKey→sessionId) + rootLangRefs 计数 + sessionAcquired 归属。\n * 保证 manager 的 acquire/release 一一配对(多会话共享同一 root|lang 也平衡)。\n */\nfunction createDocTracker() {\n const openDocs = new Map<string, Set<string>>()\n const rootLangRefs = new Map<string, number>()\n const sessionDocs = new Map<string, Set<string>>()\n const keyOf = (root: string, lang: string, path: string): string => root + '|' + lang + '|' + path\n const rootLangOf = (docKey: string): string => docKey.slice(0, docKey.lastIndexOf('|'))\n const rememberDoc = (sessionId: string, docKey: string): void => {\n const docs = sessionDocs.get(sessionId) ?? new Set<string>()\n docs.add(docKey)\n sessionDocs.set(sessionId, docs)\n }\n const forgetDoc = (sessionId: string, docKey: string): void => {\n const docs = sessionDocs.get(sessionId)\n docs?.delete(docKey)\n if (docs?.size === 0) sessionDocs.delete(sessionId)\n }\n const releaseRef = (rl: string): boolean => {\n const next = (rootLangRefs.get(rl) ?? 1) - 1\n if (next <= 0) {\n rootLangRefs.delete(rl)\n return true\n }\n rootLangRefs.set(rl, next)\n return false\n }\n return {\n /** 记录文档打开;同一文档可由多个会话打开,但每个会话只计一次。 */\n open(root: string, lang: string, path: string, sessionId: string): boolean {\n const docKey = keyOf(root, lang, path)\n const owners = openDocs.get(docKey) ?? new Set<string>()\n if (owners.has(sessionId)) return false\n owners.add(sessionId)\n openDocs.set(docKey, owners)\n rememberDoc(sessionId, docKey)\n const rl = root + '|' + lang\n const count = rootLangRefs.get(rl) ?? 0\n rootLangRefs.set(rl, count + 1)\n return count === 0\n },\n /** 记录文档关闭;返回 true 表示 root|lang 已无文档(应 release)。 */\n close(root: string, lang: string, path: string, sessionId: string): boolean {\n const docKey = keyOf(root, lang, path)\n const owners = openDocs.get(docKey)\n if (!owners?.has(sessionId)) return false\n owners.delete(sessionId)\n if (owners.size === 0) openDocs.delete(docKey)\n forgetDoc(sessionId, docKey)\n return releaseRef(root + '|' + lang)\n },\n /** 关闭某会话全部文档;返回全局引用归零、需要 release 的 root|lang。 */\n closeSession(sessionId: string): string[] {\n const docs = sessionDocs.get(sessionId)\n if (!docs) return []\n const toRelease = new Set<string>()\n for (const docKey of docs) {\n const owners = openDocs.get(docKey)\n owners?.delete(sessionId)\n if (owners?.size === 0) openDocs.delete(docKey)\n if (releaseRef(rootLangOf(docKey))) toRelease.add(rootLangOf(docKey))\n }\n sessionDocs.delete(sessionId)\n return [...toRelease]\n },\n /** 清除指定语言的文档归属,让当前客户端重新同步时重新 acquire。 */\n resetLanguage(languageId: string): void {\n for (const [docKey, owners] of openDocs) {\n if (!docKey.includes('|' + languageId + '|')) continue\n for (const sessionId of owners) forgetDoc(sessionId, docKey)\n openDocs.delete(docKey)\n }\n for (const key of [...rootLangRefs.keys()]) if (key.endsWith('|' + languageId)) rootLangRefs.delete(key)\n },\n /** 返回指定会话已打开的文档路径,用于重检测后恢复同步。 */\n pathsFor(sessionId: string, languageId: string): string[] {\n const docs = sessionDocs.get(sessionId)\n if (!docs) return []\n return [...docs].filter((key) => key.includes('|' + languageId + '|')).map((key) => key.slice(key.lastIndexOf('|') + 1))\n },\n }\n}\n\n/**\n * 构造 edrv.lsp.* handlers(一次性创建,tracker 状态跨请求保留)。\n * @author ddj 2026年08月27号\n * @param deps 依赖(ctx/pluginConfig/manager)\n * @returns { handlers, disposeSession } handlers 为局部 map,disposeSession 供 session/disposed 清理\n */\nexport function createLspRpc(deps: LspRpcDeps): { handlers: Partial<RpcHandlerMap>; disposeSession: (sessionId: string) => void } {\n const { ctx, pluginConfig, manager } = deps\n const tracker = createDocTracker()\n /** 运行时覆盖层:设置页保存值(内存态,重启回落组合配置值;每 apply 新建,插件重载自动复位)。 */\n const runtimeConfig: LspConfig = {}\n\n // 运行时自动配置成功:清 provider 缓存并重置 C# 服务器,下一次文档同步即用新运行时重启\n onRuntimeProvisioned(() => {\n clearProviderCache()\n manager.resetLanguage('csharp')\n })\n\n /** 解析会话与工作区根(失败 → null + error)。 */\n const rootOf = async (sessionId: string | undefined): Promise<{ root: string; sessionId: string } | { err: string }> => {\n const session = sessionOf(ctx, sessionId)\n if (!session) return { err: '会话不存在' }\n const cwd = cwdOf(session)\n if (!cwd) return { err: '会话无工作区' }\n try {\n const root = await searchRoot(ctx, session)\n const sid = typeof session.id === 'string' && session.id ? session.id : sessionId ?? ''\n return { root, sessionId: sid }\n } catch (error) {\n return { err: String(error) }\n }\n }\n\n const acquireServer = (root: string, lang: string) =>\n manager.acquire(root, lang, (languageId: string) => resolveProviderSpec(pluginConfig, languageId, runtimeConfig))\n\n const serverOf = (root: string, lang: string) =>\n manager.peek(root, lang)\n\n const rootLocations = (locations: LspLocation[], root: string): LspLocation[] =>\n locations.map((location) => ({ ...location, root }))\n\n /** 当前 provider 检测结论 → 设置页 idle 状态(不启动 server);附带未满足的环境需求与候选服务器。 */\n const detectedStatus = (languageId: string, root?: string): LspServerStatus => {\n const spec = resolveProviderSpec(pluginConfig, languageId, runtimeConfig)\n const missingEnv = envRequirementsFor(languageId, dshHome())\n const candidates = candidatesFor(languageId, spec)\n return {\n languageId,\n source: spec.kind,\n phase: 'idle',\n reason: spec.ready ? undefined : spec.reason,\n version: spec.version,\n providerName: spec.providerName,\n root,\n missingEnv: missingEnv.length ? missingEnv : undefined,\n candidates: candidates.length ? candidates : undefined,\n }\n }\n\n /**\n * 清发现缓存并重置旧 server(保留 tracker 文档记录);\n * 下一次模型同步会按最新配置重新 acquire,已打开文档无需重开。\n * 作者 ddj 2026年09月02号\n * @param languageId 语言 id\n * @param sessionId 会话语境(缺省重置全部工作区该语言)\n * @returns 检测后的 idle 状态列表\n */\n const redetectLanguage = async (languageId: string, sessionId?: string): Promise<LspServerStatus[]> => {\n clearProviderCache()\n if (sessionId) {\n const sc = await rootOf(sessionId)\n if ('err' in sc) return []\n manager.reset(sc.root, languageId)\n return [detectedStatus(languageId, sc.root)]\n }\n const roots = [...new Set(manager.statusAll().filter((s) => s.languageId === languageId).map((s) => s.root))]\n manager.resetLanguage(languageId)\n return roots.length ? roots.map((root) => detectedStatus(languageId, root)) : [detectedStatus(languageId)]\n }\n\n const disposeSession = (sessionId: string): void => {\n for (const rl of tracker.closeSession(sessionId)) {\n const sep = rl.lastIndexOf('|')\n manager.release(rl.slice(0, sep), rl.slice(sep + 1))\n }\n }\n\n const handlers: Partial<RpcHandlerMap> = {\n 'edrv.lsp.status': async (args) => {\n if (!args.sessionId) return { ok: true, servers: manager.statusAll() }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n return { ok: true, servers: manager.statusAll().filter((status) => status.root === sc.root) }\n },\n\n 'edrv.lsp.detect': async () => {\n // 全支持语言的检测结果(不启动服务器):设置页动态渲染卡片 + 候选展示\n return { ok: true, servers: LSP_LANGUAGES.map((lang) => detectedStatus(lang)) }\n },\n\n 'edrv.lsp.configGet': async () => {\n // 配置值降级:插件组合配置 + 运行时覆盖层(原 settings section 已废弃)\n const merged = mergeConfig(configFromPlugin(pluginConfig), runtimeConfig)\n return { ok: true, config: merged as unknown as Record<string, unknown> }\n },\n\n 'edrv.lsp.configUpdate': async (args) => {\n const lang = args.languageId\n if (!lang || !(LSP_LANGUAGES as readonly string[]).includes(lang)) {\n return { ok: false, error: '不支持的语言:' + lang }\n }\n // 覆盖层基于当前运行时值增量修改;清空字段剥离 undefined → 回落组合配置\n const target: LspLangConfig = { ...(runtimeConfig[lang] ?? {}) }\n if (args.enabled !== undefined) target.enabled = args.enabled\n if (args.command !== undefined) target.command = args.command || undefined\n if (args.path !== undefined) target.path = args.path || undefined\n runtimeConfig[lang] = sanitizeLang(target) ?? {}\n try {\n // 保存/切换后立即重新检测:清缓存 + 重置旧 server,旧状态不残留\n const servers = await redetectLanguage(lang)\n const merged = mergeConfig(configFromPlugin(pluginConfig), runtimeConfig)\n return { ok: true, config: merged as unknown as Record<string, unknown>, servers }\n } catch (error) {\n return { ok: false, error: '配置保存失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.sync': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const first = tracker.open(sc.root, lang, args.path, sc.sessionId)\n const server = first ? acquireServer(sc.root, lang) : serverOf(sc.root, lang)\n if (!server) return { ok: false, error: '语言服务器未注册' }\n server.sync(args.path, args.text, args.version)\n return { ok: true }\n },\n\n 'edrv.lsp.close': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: true }\n if (tracker.close(sc.root, lang, args.path, sc.sessionId)) {\n manager.release(sc.root, lang)\n }\n return { ok: true }\n },\n\n 'edrv.lsp.definition': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, locations: [] }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, locations: [] }\n const locations = await server.definition(args.path, args.position.line, args.position.character)\n const rooted = rootLocations(locations, sc.root)\n const truncated = rooted.length > 500\n return { ok: true, locations: truncated ? rooted.slice(0, 500) : rooted, truncated: truncated || undefined }\n } catch (error) {\n return { ok: false, error: 'LSP 定义查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.references': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, locations: [] }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, locations: [] }\n const locations = await server.references(args.path, args.position.line, args.position.character, args.includeDeclaration !== false)\n const rooted = rootLocations(locations, sc.root)\n const truncated = rooted.length > 500\n return { ok: true, locations: truncated ? rooted.slice(0, 500) : rooted, truncated: truncated || undefined }\n } catch (error) {\n return { ok: false, error: 'LSP 引用查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.documentSymbol': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, symbols: [] }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, symbols: [] }\n const symbols = await server.documentSymbol(args.path)\n return { ok: true, symbols }\n } catch (error) {\n return { ok: false, error: 'LSP 大纲查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.workspaceSymbol': async (args) => {\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n const out: { symbols: never[]; truncated?: boolean } = { symbols: [] }\n for (const lang of ['lua', 'csharp']) {\n const existing = serverOf(sc.root, lang)\n if (!existing) continue\n try {\n const symbols = await existing.workspaceSymbol(args.query)\n if (symbols.length) out.symbols.push(...(symbols as never[]))\n } catch (error) {\n /* 单语言失败忽略 */\n }\n }\n const truncated = out.symbols.length > 500\n return { ok: true, symbols: out.symbols.slice(0, 500), truncated: truncated || undefined }\n },\n\n 'edrv.lsp.hover': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, hover: undefined }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, hover: undefined }\n const hover = await server.hover(args.path, args.position.line, args.position.character)\n return { ok: true, hover: hover ?? undefined }\n } catch (error) {\n return { ok: false, error: 'LSP hover 查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.semanticTokens': async (args) => {\n const lang = langOfPath(args.path)\n if (!lang) return { ok: true, tokens: undefined }\n const sc = await rootOf(args.sessionId)\n if ('err' in sc) return { ok: false, error: sc.err }\n try {\n const server = serverOf(sc.root, lang)\n if (!server) return { ok: true, tokens: undefined }\n return { ok: true, tokens: (await server.semanticTokens(args.path)) ?? undefined }\n } catch (error) {\n return { ok: false, error: 'LSP 语义分色查询失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.redetect': async (args) => {\n if (!(LSP_LANGUAGES as readonly string[]).includes(args.languageId)) {\n return { ok: false, error: '不支持的语言:' + args.languageId }\n }\n try {\n return { ok: true, servers: await redetectLanguage(args.languageId) }\n } catch (error) {\n return { ok: false, error: '重新检测失败:' + String(error) }\n }\n },\n\n // 环境需求:一键安装(内置安装器)与安装进度查询\n 'edrv.lsp.envInstall': async (args) => {\n if (!installRequirement(args.id)) {\n return { ok: false, started: false, error: '该需求不支持一键安装:' + args.id }\n }\n return { ok: true, started: true }\n },\n\n 'edrv.lsp.envState': async () => {\n return { ok: true, states: envInstallStates() }\n },\n\n // --region 扩展管理(edrv.lsp.ext.*:已装/市场/安装/卸载/更新)\n 'edrv.lsp.ext.list': async () => ({ ok: true, extensions: listInstalled() }),\n\n 'edrv.lsp.ext.market': async (args) => {\n try {\n const items = await marketSearch(args.query, args.size ?? 12)\n return { ok: true, extensions: items }\n } catch (error) {\n return { ok: false, error: '市场搜索失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.ext.install': async (args) => {\n try {\n let info: ExtInfo\n if (args.vsixPath) info = await installVsixFile(args.vsixPath)\n else if (args.namespace && args.name) info = await installFromMarket(args.namespace, args.name, args.version)\n else return { ok: false, error: '缺少安装源(vsixPath 或 namespace+name)' }\n clearProviderCache() // 新扩展可能成为 Lua provider,立即丢弃旧发现结果\n return { ok: true, extension: info }\n } catch (error) {\n return { ok: false, error: '安装失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.ext.uninstall': async (args) => {\n const ok = uninstall(args.id)\n if (ok) clearProviderCache()\n return ok ? { ok: true } : { ok: false, error: '扩展未安装:' + args.id }\n },\n\n 'edrv.lsp.ext.update': async (args) => {\n try {\n const updated = await updateExtension(args.id)\n if (!updated) {\n const current = listInstalled().find((e) => e.id === args.id)\n return current ? { ok: true, extension: current, updated: false } : { ok: false, error: '扩展未安装:' + args.id }\n }\n clearProviderCache()\n return { ok: true, extension: updated, updated: true }\n } catch (error) {\n return { ok: false, error: '更新失败:' + String(error) }\n }\n },\n\n 'edrv.lsp.ext.updates': async () => {\n try {\n const updates = []\n for (const ext of listInstalled()) {\n const meta = await marketGet(ext.namespace, ext.name)\n const latest = String(meta?.version ?? '')\n if (latest && latest !== ext.version) updates.push({ id: ext.id, current: ext.version, latest, displayName: ext.displayName })\n }\n return { ok: true, updates }\n } catch (error) {\n return { ok: false, error: '检查更新失败:' + String(error) }\n }\n },\n // --endregion\n }\n return { handlers, disposeSession }\n}\n","/**\n * dsh-vscode-mode shared — AI 内联补全契约与纯函数(双面,禁 node/react)。\n * 只放\"过 RPC 的载荷形状\"与无副作用变换:窗口裁剪、prompt 拼装、输出清理。\n * host 与语言模型之间的流式交互在 host 侧 src/ai/inline.ts。\n * 作者 ddj\n */\n\n/** 上下文窗口:前缀字符上限(含未保存编辑的当前文档)。 */\nexport const AI_PREFIX_MAX = 2000\n/** 上下文窗口:后缀字符上限(光标之后不参与补全语义的部分)。 */\nexport const AI_SUFFIX_MAX = 500\n/** 触发门槛:前缀至少 4 个字符才请求(省掉空转调用)。 */\nexport const AI_MIN_PREFIX = 4\n/** 单次补全输出上限(token 预算 + 行数双约束,早停兜底)。 */\nexport const AI_MAX_TOKENS = 120\n/** 输出行数上限:超过即截断(ghost text 太长不可用)。 */\nexport const AI_MAX_LINES = 3\n/** 流式早停:已收字符数达到该值即 abort(省尾部延迟)。 */\nexport const AI_EARLY_STOP_CHARS = 300\n/** 补全请求超时(毫秒):codebuddy CLI 网关实测 TTFT 3.5~8.4s 抖动(debug 实证),\n * 12s 内无任何 token 即放弃;token 一到仍按行数/字符早停。 */\nexport const AI_TIMEOUT_MS = 12000\n\n/** client → host 的补全请求载荷。 */\nexport interface AiInlineRequest {\n /** 当前文档工作区相对路径(语言提示用)。 */\n path: string\n /** 光标前文本(client 已裁剪到 AI_PREFIX_MAX)。 */\n prefix: string\n /** 光标后文本(client 已裁剪到 AI_SUFFIX_MAX)。 */\n suffix: string\n}\n\n/** host → client 的补全结果(text 为空 = 无建议)。 */\nexport interface AiInlineResult {\n /** 建议插入文本(已清理:剥围栏/截行数/去重复)。 */\n text: string\n /** 失败原因(ok:false 或 text 为空时的诊断文案,供状态栏展示)。 */\n note?: string\n}\n\n/** 模型目录条目(含该模型的思考档位元数据)。 */\nexport interface AiModelEntry {\n provider: string\n model: string\n name: string\n /** 无 reasoning 元数据 = 空数组(UI 隐藏档位选择器)。 */\n efforts: Array<{ id: string; name: string }>\n /** 模型默认档位 id(无则空)。 */\n defaultEffort: string\n}\n\n/** 模型目录视图(edrv.ai.models 载荷)。 */\nexport interface AiDirectoryView {\n providers: Array<{ id: string; name: string; models: AiModelEntry[] }>\n /** 目录不可用原因(llm 服务缺失等;ok:false 时亦有 error,此为软降级说明)。 */\n note?: string\n}\n\n/** AI 补全配置视图(edrv.ai.configGet 载荷)。 */\nexport interface AiConfigView {\n enabled: boolean\n /** 空 = 自动选首个 provider/model。 */\n provider: string\n /** 空 = 自动选该 provider 首个模型。 */\n model: string\n /** 空 = 跟随模型默认(请求不携带 reasoningEffort)。 */\n effort: string\n}\n\n/** AI 补全配置更新载荷(edrv.ai.configUpdate)。 */\nexport interface AiConfigPatch {\n enabled?: boolean\n provider?: string\n model?: string\n /** 空 = 清除(跟随默认)。 */\n effort?: string\n}\n\n/**\n * 按 AI_PREFIX_MAX/AI_SUFFIX_MAX 裁剪前后缀(client 侧发请求前调用)。\n * @author ddj\n * @param prefix 光标前全文\n * @param suffix 光标后全文\n * @returns 裁剪后的窗口\n */\nexport function trimInlineWindow(prefix: string, suffix: string): { prefix: string; suffix: string } {\n const pre = typeof prefix === 'string' ? prefix : ''\n const suf = typeof suffix === 'string' ? suffix : ''\n return {\n prefix: pre.length > AI_PREFIX_MAX ? pre.slice(pre.length - AI_PREFIX_MAX) : pre,\n suffix: suf.length > AI_SUFFIX_MAX ? suf.slice(0, AI_SUFFIX_MAX) : suf,\n }\n}\n\n/**\n * 是否值得发起补全请求:前缀达标且非纯空白(空行/行首不请求)。\n * @author ddj\n * @param prefix 光标前文本\n * @returns 是否可请求\n */\nexport function inlineWorth(prefix: string): boolean {\n const pre = typeof prefix === 'string' ? prefix : ''\n if (pre.length < AI_MIN_PREFIX) return false\n // 只拦\"整体无内容\"(纯空白);结尾空白(如 `local a = `)是最自然的补全触发\n // 形态,必须放行——原尾字符守卫把这类场景全数拦截(debug 实证 H4)\n return pre.trim().length > 0\n}\n\n/**\n * 拼装补全 user 消息文本:语言/文件名 + 前缀 + 补全点标记 + 后缀。\n * host 侧与单测共用,保证请求形状一致。\n * @author ddj\n * @param req 补全请求(已裁剪)\n * @returns 用户消息文本\n */\nexport function buildInlinePrompt(req: AiInlineRequest): string {\n const name = String(req.path || '').split(/[\\\\/]/).pop() || 'untitled'\n return [\n '文件:' + name,\n '现有代码(光标位于 <CURSOR> 标记处):',\n req.prefix + '<CURSOR>' + req.suffix,\n ].join('\\n')\n}\n\n/** 补全 system 提示词:硬约束输出形态(只给插入文本)。 */\nexport const AI_INLINE_SYSTEM =\n '你是代码自动补全引擎。只输出应插入 <CURSOR> 处的代码文本:' +\n '禁止任何解释、注释性语句、markdown 代码围栏或对原文的复述;' +\n '最多 ' + AI_MAX_LINES + ' 行,从光标处自然衔接前文,不要重复前缀已有内容;' +\n '无法给出高置信度补全时输出空文本。'\n\n/**\n * 清理模型输出:剥 markdown 围栏、剥对 <CURSOR> 标记的复述、按行数截断、去首尾空行。\n * 产出空文本的判定也在这里(纯函数,单测覆盖)。\n * @author ddj\n * @param raw 模型原始输出\n * @param prefix 请求时的前缀(复述检测)\n * @returns 清理后的插入文本(可能为空串)\n */\nexport function cleanInlineText(raw: string, prefix: string): string {\n let text = typeof raw === 'string' ? raw : ''\n if (!text) return ''\n // markdown 围栏剥离(```lang … ``` 或 ```…```)\n const fenced = /^```[^\\n]*\\n([\\s\\S]*?)\\n?```$/.exec(text.trim())\n if (fenced) text = fenced[1] ?? ''\n // 模型复述了标记本身:取标记之后的部分\n const cursorAt = text.indexOf('<CURSOR>')\n if (cursorAt >= 0) text = text.slice(cursorAt + '<CURSOR>'.length)\n // 整体就是前缀结尾片段的复述:剥掉(防\"从行首重抄一遍\"类退化输出)\n const tailPrefix = prefix.length > 0 ? prefix.slice(-40) : ''\n if (tailPrefix && text.startsWith(tailPrefix)) text = text.slice(tailPrefix.length)\n // 行数截断 + 行尾空白清理\n const lines = text.split('\\n').slice(0, AI_MAX_LINES).map((l) => l.replace(/\\s+$/, ''))\n while (lines.length > 0 && lines[0] === '') lines.shift()\n while (lines.length > 0 && lines[lines.length - 1] === '') lines.pop()\n return lines.join('\\n')\n}\n","/**\n * dsh-vscode-mode host — AI 内联补全服务。\n * 一次性非会话调用:配置解析(开关→provider/model 路由→思考档位)→ ctx.llm.stream\n * 流式汇聚(只收 text-delta,reasoning-delta 天然不进补全)→ 早停 → 输出清理。\n * llm 服务经 ctx.get('llm') 惰性获取(不用 inject:缺失时插件仍加载,AI 补全降级)。\n * 模型目录(edrv.ai.models):listProviders/listModels/resolveModelInfo 逐模型取档位,\n * 进程级缓存 5 分钟,单模型 resolve 失败降级为无档位条目。\n * 作者 ddj\n */\nimport type { Ctx } from '../store.js'\nimport { log } from '../log.js'\nimport type { LlmRuntimeLike, StreamChunk } from './llmTypes.js'\nimport {\n AI_EARLY_STOP_CHARS, AI_INLINE_SYSTEM, AI_MAX_LINES, AI_MAX_TOKENS, AI_TIMEOUT_MS,\n buildInlinePrompt, cleanInlineText,\n type AiConfigView, type AiDirectoryView, type AiInlineRequest, type AiInlineResult,\n} from '../shared/ai.js'\n\n/** AI 补全配置来源(settings section,fileOpenSettings.ts 提供 getter)。 */\nexport interface AiConfigSource {\n get(): AiConfigView\n}\n\n/** host 补全服务依赖(装配时一次性注入)。 */\nexport interface AiInlineDeps {\n ctx: Ctx\n config: AiConfigSource\n}\n\n/** 模型目录缓存(进程级:5 分钟 TTL,避免每次打开设置页都逐模型 resolve)。 */\nconst DIR_TTL_MS = 5 * 60 * 1000\nlet dirCache: { view: AiDirectoryView; at: number } | null = null\n\n/** 复位目录缓存(测试隔离用)。 */\nexport function resetAiDirCache(): void {\n dirCache = null\n}\n\n/**\n * 取 llm 运行时(惰性;缺失/未装配返回 null 并给诊断)。\n * @author ddj\n * @param ctx DSH 上下文\n * @returns llm 运行时或 null\n */\nfunction llmOf(ctx: Ctx): LlmRuntimeLike | null {\n try {\n const llm = ctx.get('llm') as LlmRuntimeLike | undefined\n return llm && typeof llm.stream === 'function' ? llm : null\n } catch {\n return null\n }\n}\n\n/**\n * 解析请求路由:用户配置优先(provider/model 均非空),否则取目录首个 provider+model。\n * @author ddj\n * @param llm llm 运行时\n * @param cfg AI 配置\n * @returns 路由(provider/model);不可路由返回 null\n */\nasync function routeOf(llm: LlmRuntimeLike, cfg: AiConfigView): Promise<{ provider: string; model: string } | null> {\n if (cfg.provider && cfg.model) return { provider: cfg.provider, model: cfg.model }\n const providers = llm.listProviders()\n if (!providers.length) return null\n const provider = cfg.provider || providers[0].id\n const models = await llm.listModels(provider).catch(() => [])\n if (!models.length) return null\n return { provider, model: models[0].id }\n}\n\n/**\n * 单次 AI 内联补全。\n * @author ddj\n * @param deps 服务依赖\n * @param req 补全请求(client 已裁剪窗口)\n * @returns 补全结果(text 空 = 无建议)\n */\nexport async function aiInlineComplete(deps: AiInlineDeps, req: AiInlineRequest): Promise<AiInlineResult> {\n const cfg = deps.config.get()\n if (!cfg.enabled) return { text: '' }\n if (!req || typeof req.prefix !== 'string' || !req.prefix) return { text: '' }\n const llm = llmOf(deps.ctx)\n if (!llm) return { text: '', note: 'llm 服务不可用' }\n const route = await routeOf(llm, cfg)\n if (!route) return { text: '', note: '未找到可用模型(请检查 DSH 模型配置)' }\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(new Error('timeout')), AI_TIMEOUT_MS)\n try {\n const stream = llm.stream({\n provider: route.provider,\n model: route.model,\n ...(cfg.effort ? { reasoningEffort: cfg.effort } : {}),\n messages: [\n {\n role: 'user',\n content: [{ type: 'text', text: buildInlinePrompt(req) }],\n source: { kind: 'user' },\n } as never,\n ],\n system: AI_INLINE_SYSTEM,\n temperature: 0.2,\n maxTokens: AI_MAX_TOKENS,\n // 不传 stop:llm-pi-ai 等适配器不支持该选项(UNSUPPORTED_OPTION 直接 error finish);\n // 截断由行数/字符早停兜底\n signal: controller.signal,\n })\n let text = ''\n let aborted = false\n let failNote = ''\n let reasoningChars = 0\n for await (const chunk of stream) {\n const c = chunk as StreamChunk\n if (c.type === 'text-delta') {\n text += c.text\n // 早停:满 3 行或 300 字符即掐断流,省尾部 token 延迟\n if (text.split('\\n').length > AI_MAX_LINES || text.length >= AI_EARLY_STOP_CHARS) {\n controller.abort(new Error('early-stop'))\n aborted = true\n }\n } else if (c.type === 'reasoning-delta') {\n reasoningChars += c.text.length\n } else if (c.type === 'finish') {\n // 适配器失败走 finish(error/aborted) 而非抛异常:检查 reason.kind 带回诊断\n const kind = (c.reason as { kind?: string })?.kind\n if (kind === 'error' || kind === 'aborted') {\n const failure = (c.reason as { failure?: { code?: string; message?: string } }).failure\n failNote = (failure?.code ?? kind) + ': ' + (failure?.message ?? '模型调用失败')\n log.debug('[ai-inline] 流失败:' + failNote)\n }\n break\n } else if (c.type === 'usage' || c.type === 'block-start' || c.type === 'block-end') {\n // 汇聚无关块:跳过\n } else if (c.type === 'tool-call-delta') {\n // 工具块不进补全\n }\n if (aborted) break\n }\n if (failNote) return { text: '', note: 'AI 补全失败:' + failNote }\n const clean = cleanInlineText(text, req.prefix)\n if (!clean) {\n // 思考型模型常见症状:正文空但思考有内容 → 明确提示换非思考模型(debug 实证 isd/deepseek-v4-flash)\n if (text.length === 0 && reasoningChars > 0) {\n log.debug('[ai-inline] 仅思考无正文(reasoning ' + reasoningChars + ' 字符)')\n return { text: '', note: '该模型只返回了思考没有正文,请在设置页换非思考模型' }\n }\n log.debug('[ai-inline] 空输出(原始 ' + text.length + ' 字符)')\n return { text: '' }\n }\n return { text: clean }\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n log.debug('[ai-inline] 失败:' + msg)\n return { text: '', note: 'AI 补全失败:' + msg }\n } finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * 模型目录视图(edrv.ai.models):DSH 已配置 provider 全量 + 逐模型思考档位。\n * @author ddj\n * @param ctx DSH 上下文\n * @param force 跳过缓存强制刷新\n * @returns 目录视图(llm 缺失时 note 说明 + 空目录)\n */\nexport async function aiModels(ctx: Ctx, force = false): Promise<AiDirectoryView> {\n if (!force && dirCache && Date.now() - dirCache.at < DIR_TTL_MS) return dirCache.view\n const llm = llmOf(ctx)\n if (!llm) {\n return { providers: [], note: 'llm 服务不可用(无法枚举模型)' }\n }\n const out: AiDirectoryView = { providers: [] }\n for (const p of llm.listProviders()) {\n const models = await llm.listModels(p.id).catch(() => [])\n const entries = []\n for (const m of models) {\n let efforts: Array<{ id: string; name: string }> = []\n let def = ''\n try {\n const info = await llm.resolveModelInfo(p.id, m.id)\n efforts = (info.reasoning?.efforts ?? []).map((e: { id: string; name: string }) => ({ id: e.id, name: e.name }))\n def = info.reasoning?.defaultEffort ?? ''\n } catch {\n // 单模型元数据失败:降级为无档位条目(不影响目录其余部分)\n }\n entries.push({ provider: p.id, model: m.id, name: m.name || m.id, efforts, defaultEffort: def })\n }\n out.providers.push({ id: p.id, name: p.name || p.id, models: entries })\n }\n dirCache = { view: out, at: Date.now() }\n return out\n}\n","/**\n * dsh-vscode-mode host — edrv.ai.* RPC handlers。\n * inline:AI 内联补全(一次调用一次结果,无状态);models:模型目录(缓存);\n * configGet/configUpdate:settings section 的 AI 字段读写。\n * 作者 ddj\n */\nimport type { RpcHandlerMap } from '../shared/rpc.js'\nimport type { FileOpenSettingsState } from '../fileOpenSettings.js'\nimport type { AiConfigView } from '../shared/ai.js'\nimport { aiInlineComplete, aiModels, type AiInlineDeps } from './inline.js'\n\n/** AI RPC 依赖(settings 状态由 index.ts 装配时桥接)。 */\nexport interface AiRpcDeps {\n ctx: AiInlineDeps['ctx']\n settings: FileOpenSettingsState & {\n ai: () => AiConfigView\n aiUpdate: (patch: import('../shared/ai.js').AiConfigPatch, expectedRevision?: number) => Promise<AiConfigView>\n }\n}\n\n/**\n * 构造 edrv.ai.* handlers(一次性创建,无跨请求状态——目录缓存在 inline.ts 模块级)。\n * @author ddj\n * @param deps 依赖(ctx/settings)\n * @returns handlers\n */\nexport function createAiRpc(deps: AiRpcDeps): { handlers: Partial<RpcHandlerMap> } {\n const handlers: Partial<RpcHandlerMap> = {\n 'edrv.ai.inline': async (args) => ({ ok: true, ...(await aiInlineComplete({ ctx: deps.ctx, config: { get: () => deps.settings.ai() } }, args)) }),\n 'edrv.ai.models': async (args) => ({ ok: true, ...(await aiModels(deps.ctx, args?.force === true)) }),\n 'edrv.ai.configGet': async () => ({ ok: true, ...deps.settings.ai() }),\n 'edrv.ai.configUpdate': async (args) => ({ ok: true, ...(await deps.settings.aiUpdate(args)) }),\n }\n return { handlers }\n}\n","/**\n * @dsh-external 生态 → dsh-vscode-mode:DSH 上的类 VSCode 编码体验(Host 半入口)。\n * 职责:装配 capture(tools/result 捕获 edit/write 差异)、RPC 分发(edrv.* / mcp.* / vscode.* / compat)、\n * webServer 路由(/edrv/rpc、/edrv/assets/*、/edrv/vendor/*)、工作区旁车持久化、\n * 兼容层装配(依赖守卫 + 重复装配自诊断 + 启动日志兼容性报告)。\n * 结构:shared/(双面契约) + model/store/capture/workspace/revert/registry/rpc/routes/compat(host 模块)\n * + log/debugLog(统一日志:bindHostLog 绑定 ctx.logger,edrv.debug 诊断文件通道)。\n * 作者 ddj 2026-08-20\n */\nimport { registerRoutes } from './routes.js'\nimport { captureToolResult } from './capture.js'\nimport { handleRpc } from './rpc.js'\nimport { newSearcher } from './search/orchestrator.js'\nimport { newContentSearcher } from './search/content.js'\nimport { installIsolation } from './mcpIsolation.js'\nimport { dropFileIndex } from './workspace.js'\nimport { cwdOf } from './registry.js'\nimport { setupOpenSettings } from './fileOpenSettings.js'\nimport { shellMenuLifecycle } from './integrate.js'\nimport { disposeIndex } from './treeIndex.js'\nimport { sweepTreeCache } from './paths.js'\nimport { buildReport } from './compat.js'\nimport { bindHostLog, log } from './log.js'\nimport { createLspManager } from './lsp/manager.js'\nimport { createLspRpc } from './lsp/rpc.js'\nimport { disposeAllServers } from './lsp/transport.js'\nimport { createAiRpc } from './ai/rpc.js'\nimport { installRulesSection } from './rules.js'\nimport type { RpcHandlerMap } from './shared/rpc.js'\nimport type { Registry } from './registry.js'\nimport type { Ctx } from './store.js'\n\nexport const name = \"dsh-vscode-mode\"\nexport const inject = ['sessions', 'fs', 'webServer', 'loader', 'tools', 'workspaceRegistry', 'agents']\n\n/**\n * 装配插件:挂事件监听、注册路由、安装兼容层。\n * @author ddj 2026年08月20号\n * @param ctx DSH 上下文(sessions/fs/webServer 由 inject 提供;sandboxPolicy/subprocess 惰性获取)\n * @param config 插件配置(可选 imageDir 覆盖图标目录)\n */\nexport function apply(ctx: Ctx, config?: unknown): void {\n // 统一日志出口:全部 host 日志经 ctx.logger(缺失时回退 console),此后任何模块 log.* 即生效\n bindHostLog(ctx)\n const registry: Registry = new Map()\n const searcher = newSearcher(ctx)\n const contentSearcher = newContentSearcher(ctx)\n /** LSP 服务器管理器(语言智能:跳转/引用/大纲;诊断行带模块内前缀如 [lsp-manager])。 */\n const lspManager = createLspManager((line) => log.debug(line))\n /** 兼容性警告收集(route 护栏等写入,启动日志一并输出)。 */\n const warnings: string[] = []\n /** 设置状态(fileOpenTool + AI 补全配置读写;settings 不可用时内存态降级)。 */\n const openSettings = setupOpenSettings(ctx, config, () => {})\n /** LSP 配置为配置值模式:插件组合配置 + 会话内运行时覆盖(原 settings section 命名空间不合法,见 lsp/config.ts)。 */\n /** 规则注入 section(~/.dsh/rules 与 <工作区>/.dsh/rules;旧版 DSH 无 systemPrompt 时静默降级)。 */\n const rulesInstalled = installRulesSection(ctx)\n if (!rulesInstalled) log.warn('未检测到 systemPrompt 服务,规则仅可管理不注入')\n /** LSP RPC 与会话清理(一次性创建,tracker 状态跨请求保留)。 */\n const lspRpc = createLspRpc({ ctx, pluginConfig: config, manager: lspManager })\n const lspHandlers: Partial<RpcHandlerMap> = lspRpc.handlers\n /** AI 内联补全 RPC(settings 状态桥接 + llm 惰性获取)。 */\n const aiRpc = createAiRpc({ ctx, settings: openSettings })\n const aiHandlers: Partial<RpcHandlerMap> = aiRpc.handlers\n\n ctx.on('tools/result', (exec: unknown, result: unknown) => {\n void captureToolResult(ctx, registry, exec, result)\n })\n\n ctx.on('session/disposed', (session: unknown) => {\n const cwd = cwdOf(session as never)\n if (cwd) {\n registry.delete(cwd)\n dropFileIndex(cwd)\n searcher.dispose(cwd)\n contentSearcher.dispose(cwd)\n disposeIndex(cwd)\n }\n const sid = (session as { id?: unknown })?.id\n if (typeof sid === 'string') lspRpc.disposeSession(sid)\n })\n\n registerRoutes(ctx, config, (method, args) => handleRpc(ctx, registry, method, args, searcher, contentSearcher, lspHandlers, aiHandlers), (warning) => warnings.push(warning))\n installIsolation(ctx)\n // 系统集成生命周期:启动自动恢复右键菜单注册(marker 存在时);插件卸载/reload 清理注册痕迹\n ctx.effect(() => shellMenuLifecycle(ctx))\n // 启动清理缓存目录:非当前 schema / 超保留期 / 未知残留(best-effort,不阻塞装配)\n void sweepTreeCache()\n void logCompatSummary(ctx, warnings)\n // 卸载/重启时强杀 LSP 子进程(防残留)\n ctx.effect(() => () => {\n void lspManager.disposeAll().catch(() => {})\n disposeAllServers()\n })\n\n log.info('编辑差异审查已装配(/edrv/rpc 路由就绪,项目 MCP 隔离已启用,语言服务器 LSP 已接入,规则注入' + (rulesInstalled ? '已接入' : '未接入') + ')')\n}\n\n/**\n * 异步输出兼容性报告摘要(含重复装配/路由冲突自诊断)。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文\n * @param warnings 装配期收集的兼容性警告\n */\nasync function logCompatSummary(ctx: Ctx, warnings: string[]): Promise<void> {\n try {\n const report = await buildReport(ctx)\n for (const warning of warnings) report.warnings.push(warning)\n const dsh = report.dshVersion ? 'DSH ' + report.dshVersion : 'DSH 未探测'\n const head = '兼容性:' + dsh + ' · ' + report.external.length + ' 项外部适配 / ' + report.guards.length + ' 项护栏 / ' + (report.adapters?.length ?? 0) + ' 项版本适配'\n if (report.warnings.length) {\n log.warn(head + ',警告 ' + report.warnings.length + ' 条:' + report.warnings.join(';'))\n } else {\n log.info(head + ',无警告')\n }\n } catch (error) {\n log.warn('兼容性报告生成失败:' + String(error))\n }\n}\n"],"mappings":"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"}
|