dsh-vscode-mode 0.1.21 → 0.1.23
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 +26 -20
- package/lib/client.js +711 -77
- package/lib/client.js.map +1 -1
- package/lib/index.js +113 -0
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/client/events.ts +8 -4
- package/src/client/fileReveal.ts +28 -0
- package/src/client/index.ts +44 -9
- package/src/client/sidebar/contextMenu.ts +99 -0
- package/src/client/sidebar/menuItems.ts +28 -0
- package/src/client/sidebar/panels/FileExplorer.ts +34 -4
- package/src/client/sidebar/types.ts +5 -0
- package/src/client/sidebarBridge.ts +247 -0
- package/src/client/styles/editor.css +13 -1
- package/src/client/ui/ContextMenu.ts +82 -0
- package/src/client/ui/DiffBadge.ts +5 -3
- package/src/client/ui/EditorView.ts +113 -43
- package/src/client/ui/SideEditorTab.ts +48 -0
- package/src/compat.ts +2 -0
- package/src/reveal.ts +64 -0
- package/src/rpc.ts +21 -0
- package/src/shared/rpc.ts +2 -0
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/mcp.ts","../src/fileOpenSettings.ts","../src/devForm.ts","../src/compat.ts","../src/shared/rpc.ts","../src/routes.ts","../src/shared/diff.ts","../src/model.ts","../src/store.ts","../src/registry.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/revert.ts","../src/mcpProject.ts","../src/tree.ts","../src/rpc.ts","../src/mcpIsolation.ts","../src/workspace.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 host — 文件链接打开工具的持久化设置。\n * 依赖守卫:@deepseek-ai/dsh-settings / schemastery 以动态加载引入,\n * 缺失时插件仍可加载(fileOpenTool 降级为配置值,compat 报告可见)。\n * 作者 ddj 2026年08月24号\n */\nimport type { Ctx } from './store.js'\n\nexport const FILE_OPEN_SETTINGS_NS = 'dsh-vscode-mode'\nexport const FILE_OPEN_DEFAULT = 'auto'\nexport interface FileOpenSettings { fileOpenTool: string }\nexport interface FileOpenSettingsState { value: string; revision?: number; update: (value: string, expectedRevision?: number) => Promise<void> }\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>) => unknown\n string: () => { default: (value: string) => unknown }\n }\n}\n\nexport type SettingsDepsLoader = () => Promise<SettingsDeps | null>\n\nlet depsPromise: Promise<SettingsDeps | null> | undefined\n\n/**\n * 动态加载设置依赖(模块级缓存;任一缺失返回 null 而非抛错)。\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 installSettingsSection: (dshSettings as { installSettingsSection: SettingsDeps['installSettingsSection'] }).installSettingsSection,\n z: (schemastery as { default: SettingsDeps['z'] }).default,\n }))\n .catch(() => null)\n }\n return depsPromise\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/**\n * 安装设置 section(动态依赖;缺失返回 false 不抛错)。\n * @author ddj 2026年08月24号\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 const deps = await loader()\n if (!deps) return false\n const schema = deps.z.object({ fileOpenTool: deps.z.string().default(FILE_OPEN_DEFAULT) })\n deps.installSettingsSection(ctx, ns, schema, entry, hooks)\n return true\n}\n\n/**\n * 注册设置命名空间,并提供 host 侧的读取与更新状态。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文\n * @param config 插件组合配置\n * @param onChange 设置变化回调\n * @returns 设置状态\n */\nexport function setupOpenSettings(ctx: Ctx, config: unknown, onChange: (value: string) => void): FileOpenSettingsState {\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 void installOpenSettingsSection(ctx, FILE_OPEN_SETTINGS_NS, { fileOpenTool: current }, { setSource, onChange: settingsChange })\n ctx.inject?.(['settings'], (settingsCtx: Ctx) => {\n provider = settingsCtx.get('settings')\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 }\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 * 职责:身份常量(包名 / 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 } from './fileOpenSettings.js'\nimport { readDevForm } from './devForm.js'\nimport type { CompatAdapter, CompatReport } from './shared/compat.js'\nimport type { Ctx } from './store.js'\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/** webServer 路由前缀(RPC 精确路由 + 静态资源前缀共用)。 */\nexport const ROUTE_PREFIX = '/edrv'\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 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 ]\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/**\n * 构建完整兼容性报告(RPC 与启动日志共用)。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文\n * @param options 测试注入:depsAvailable 跳过动态导入、version 固定版本号\n * @returns 兼容性报告\n */\nexport async function buildReport(\n ctx: Ctx,\n options?: { depsAvailable?: boolean; version?: string },\n): Promise<CompatReport> {\n const deps = options?.depsAvailable ?? (await loadSettingsDeps()) !== null\n const external = detectExternal(ctx, deps)\n const guards = detectGuards(ctx)\n const warnings: string[] = []\n if (!deps) warnings.push('未安装 @deepseek-ai/dsh-settings:文件打开工具设置持久化不可用(降级为配置值)')\n for (const guard of guards) {\n if (!guard.active && guard.note) warnings.push(guard.note)\n }\n return { pluginVersion: options?.version ?? pluginVersionOf(), external, guards, warnings, devForm: readDevForm() }\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'\n\n/** webServer 精确路由。 */\nexport const RPC_PATH = '/edrv/rpc'\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/** 一条批量决策项(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 }\n 'edrv.original': { sessionId?: string; path: string }\n 'edrv.save': { sessionId?: string; path: string; content: string }\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.listDir': { 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; expectedRevision?: number }\n 'vscode.devFormGet': {}\n 'vscode.devFormSet': { enabled: boolean; path?: string }\n 'compat': {}\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 }\n 'edrv.original': { content: string; size: number; stale: StaleHunk[]; fallback: boolean }\n 'edrv.save': 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.listDir': { root: string; path: string; entries: TreeEntry[] }\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; revision?: number }\n 'vscode.fileOpenSettingsUpdate': { fileOpenTool: string; revision?: number }\n 'vscode.devFormGet': { devForm: DevFormInfo }\n 'vscode.devFormSet': { devForm: DevFormInfo; restart: boolean }\n 'compat': { report: CompatReport }\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 — webServer 路由注册(/edrv/rpc、/edrv/assets/*、/edrv/vendor/*)。\n * 迁移自原 src/index.ts 的路由部分,路径/行为一字不改。\n * 作者 ddj 2026-08-20\n */\nimport { readFile } from 'node:fs/promises'\nimport { dirname, extname, join, normalize, resolve, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\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'\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_PREFIX = '/edrv/vendor'\nconst VENDOR_MIME: Record<string, string> = {\n '.js': '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}\n\n/** 图标目录:默认插件包内 assets/(随包发布);config.imageDir 可覆盖(用于自定义换图)。 */\nfunction imageDirOf(config: unknown): 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 join(dirname(fileURLToPath(import.meta.url)), '..', 'assets')\n}\n\n/** Monaco AMD 静态目录(随包发布)。 */\nconst vendorDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'assets', 'vendor')\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 = imageDirOf(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 ctx.effect(() => guarded({\n kind: 'prefix',\n path: VENDOR_PREFIX,\n handler: async (req: { method?: string; url?: string }, 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 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.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/** 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, preciseHunk } from './shared/diff.js'\nimport { archiveEntryFor, groupByBatch, normalizeRecord } from './model.js'\n\nexport const SIDECAR = '.dsh-edit-review.json'\nexport const SIDECAR_ARCHIVE = '.dsh-edit-review-archive.json'\nexport const READ_CAP = 8 * 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 console.error('edrv saveBucket failed', 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 const locations = locateHunks(state.content, pending.map((item) => 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 console.error('edrv appendArchiveEntries failed', 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 — 捕获层:监听 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'\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 } catch (error) {\n console.error('edrv capture failed', 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\nconst EXCLUDES = [\n 'node_modules', '.git', '.tmp', '.cache', 'dist', 'build', 'vendor',\n 'coverage', '__pycache__',\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 * 使用打包 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 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) throw new Error('ripgrep 退出码:' + String(code))\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__'])\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 = { at: number; result: WorkspaceSearchResult }\ntype SearchRequest = { session: Session; cwd: string; query: string; activePaths: string[] }\ntype SearchResponse = { files: string[]; truncated: boolean }\n\n/**\n * 短期有界搜索缓存。\n * @author ddj 2026年08月24号\n * @returns 缓存对象\n */\nexport class SearchCache {\n private readonly entries = new Map<string, CacheEntry>()\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()): WorkspaceSearchResult | 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 { ...entry.result, files: [...entry.result.files] }\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: WorkspaceSearchResult, now = Date.now()): void {\n this.entries.delete(key)\n this.entries.set(key, { at: now, result: { ...result, files: [...result.files] } })\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()\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 — 回滚/删除(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 — 项目级 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 — 目录树纯函数(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 — 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 type { DiffRecord, RecordView } from './shared/types.js'\nimport type { Ctx, Session } from './store.js'\nimport {\n READ_CAP,\n appendArchiveEntries,\n archiveRecords,\n autoArchiveStale,\n parseArchive,\n policyOf,\n readArchiveText,\n resolveTarget,\n saveBucket,\n} from './store.js'\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 { restoreFile, revertCall, revertHunk } from './revert.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 { buildReport } from './compat.js'\nimport { readDevForm, setDevForm } from './devForm.js'\nimport { normalizeRel, toTreeEntries } from './tree.js'\n\n/** cwd → Promise 链:串行化 debug 日志追加(fs read+write 非原子,避免并发丢行)。 */\nconst debugWriteQueues = new Map<string, Promise<void>>()\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 * 批量决策核心:一次会话/桶解析 + 逐项处理 + 统一落盘(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/** 各方法 handler 表(类型由 shared/rpc 的 RpcHandlerMap 约束)。 */\nexport function buildHandlers(ctx: Ctx, registry: Registry, searcher = newSearcher(ctx)): RpcHandlerMap {\n return {\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 if (!want && args.skipStale !== true) await autoArchiveStale(ctx, sc.session, sc.cwd, bucket) // 全量轮询时自动清理 stale 幽灵差异(批量决策后的即时刷新可 skipStale 跳过)\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') return { ok: false, error: '文件不存在' }\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 const bucket = await bucketOf(registry, ctx, sc.cwd)\n let changed = false\n for (const rec of bucket.values()) {\n if (rec.path === args.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 === args.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 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 上报 → 写入工作区旁车 .dsh-edit-review-debug.log(console 不一定落盘,文件可靠)\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 const text = String(args.text ?? '')\n const prev = debugWriteQueues.get(sc.cwd) || Promise.resolve()\n const task = prev.then(async () => {\n try {\n const target = await fs.resolve('.dsh-edit-review-debug.log', { cwd: sc.cwd })\n const old = await fs.readText(target).catch(() => '')\n const line = new Date().toISOString() + ' ' + text + '\\n'\n await fs.writeText(target, (old || '') + line, void 0, void 0, policyOf(ctx, sc.session))\n } catch (e) { /* 写日志失败忽略 */ }\n })\n debugWriteQueues.set(sc.cwd, task)\n await task\n console.error('[edrv-debug] ' + 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.listDir': async (args) => {\n // 目录树(侧边栏文件管理用):按会话 cwd 解析,与 edrv.read 同基准,树内相对路径点开即打开。\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 resolveTarget(ctx, sc.session, rel || '.')\n const info = await fs.stat(target)\n if (!info) return { ok: false, error: '目录不存在' }\n if (info.type !== 'directory') return { ok: false, error: '不是目录' }\n const children = await fs.listDir(target)\n const root = fs.processPath(await fs.resolve('.', { cwd: sc.cwd }))\n return { ok: true, root, path: rel, entries: toTreeEntries(rel, children) }\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), 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 await settings.update(FILE_OPEN_SETTINGS_NS, { fileOpenTool: normalizeFileOpenTool(args.fileOpenTool) }, 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), 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 }\n}\n\n/**\n * 统一入口:按方法分发到 handler 表。\n * @author ddj 2026年08月20号\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): Promise<RpcResult<M>> {\n const handlers = buildHandlers(ctx, registry, searcher)\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'\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 ctx.logger?.warn?.('[dsh-vscode-mode] 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'\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 console.error('edrv scan failed', 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-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 * 作者 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 { installIsolation } from './mcpIsolation.js'\nimport { dropFileIndex } from './workspace.js'\nimport { cwdOf } from './registry.js'\nimport { setupOpenSettings } from './fileOpenSettings.js'\nimport { PLUGIN_NAME, buildReport } from './compat.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 const registry: Registry = new Map()\n const searcher = newSearcher(ctx)\n /** 兼容性警告收集(route 护栏等写入,启动日志一并输出)。 */\n const warnings: string[] = []\n setupOpenSettings(ctx, config, () => {})\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 }\n })\n\n registerRoutes(ctx, config, (method, args) => handleRpc(ctx, registry, method, args, searcher), (warning) => warnings.push(warning))\n installIsolation(ctx)\n void logCompatSummary(ctx, warnings)\n\n ctx.logger?.info?.('[' + name + '] 编辑差异审查已装配(/edrv/rpc 路由就绪,项目 MCP 隔离已启用)')\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 logger = ctx.logger\n if (!logger?.info) return\n const head = '[' + PLUGIN_NAME + '] 兼容性:' + report.external.length + ' 项外部适配 / ' + report.guards.length + ' 项护栏'\n if (report.warnings.length) {\n logger.warn?.(head + ',警告 ' + report.warnings.length + ' 条:' + report.warnings.join(';'))\n } else {\n logger.info?.(head + ',无警告')\n }\n } catch (error) {\n ctx.logger?.warn?.('[' + PLUGIN_NAME + '] 兼容性报告生成失败:' + String(error))\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/mcp.ts","../src/fileOpenSettings.ts","../src/devForm.ts","../src/compat.ts","../src/shared/rpc.ts","../src/routes.ts","../src/shared/diff.ts","../src/model.ts","../src/store.ts","../src/registry.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/revert.ts","../src/mcpProject.ts","../src/tree.ts","../src/reveal.ts","../src/rpc.ts","../src/mcpIsolation.ts","../src/workspace.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 host — 文件链接打开工具的持久化设置。\n * 依赖守卫:@deepseek-ai/dsh-settings / schemastery 以动态加载引入,\n * 缺失时插件仍可加载(fileOpenTool 降级为配置值,compat 报告可见)。\n * 作者 ddj 2026年08月24号\n */\nimport type { Ctx } from './store.js'\n\nexport const FILE_OPEN_SETTINGS_NS = 'dsh-vscode-mode'\nexport const FILE_OPEN_DEFAULT = 'auto'\nexport interface FileOpenSettings { fileOpenTool: string }\nexport interface FileOpenSettingsState { value: string; revision?: number; update: (value: string, expectedRevision?: number) => Promise<void> }\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>) => unknown\n string: () => { default: (value: string) => unknown }\n }\n}\n\nexport type SettingsDepsLoader = () => Promise<SettingsDeps | null>\n\nlet depsPromise: Promise<SettingsDeps | null> | undefined\n\n/**\n * 动态加载设置依赖(模块级缓存;任一缺失返回 null 而非抛错)。\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 installSettingsSection: (dshSettings as { installSettingsSection: SettingsDeps['installSettingsSection'] }).installSettingsSection,\n z: (schemastery as { default: SettingsDeps['z'] }).default,\n }))\n .catch(() => null)\n }\n return depsPromise\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/**\n * 安装设置 section(动态依赖;缺失返回 false 不抛错)。\n * @author ddj 2026年08月24号\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 const deps = await loader()\n if (!deps) return false\n const schema = deps.z.object({ fileOpenTool: deps.z.string().default(FILE_OPEN_DEFAULT) })\n deps.installSettingsSection(ctx, ns, schema, entry, hooks)\n return true\n}\n\n/**\n * 注册设置命名空间,并提供 host 侧的读取与更新状态。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文\n * @param config 插件组合配置\n * @param onChange 设置变化回调\n * @returns 设置状态\n */\nexport function setupOpenSettings(ctx: Ctx, config: unknown, onChange: (value: string) => void): FileOpenSettingsState {\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 void installOpenSettingsSection(ctx, FILE_OPEN_SETTINGS_NS, { fileOpenTool: current }, { setSource, onChange: settingsChange })\n ctx.inject?.(['settings'], (settingsCtx: Ctx) => {\n provider = settingsCtx.get('settings')\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 }\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 * 职责:身份常量(包名 / 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 } from './fileOpenSettings.js'\nimport { readDevForm } from './devForm.js'\nimport type { CompatAdapter, CompatReport } from './shared/compat.js'\nimport type { Ctx } from './store.js'\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/** webServer 路由前缀(RPC 精确路由 + 静态资源前缀共用)。 */\nexport const ROUTE_PREFIX = '/edrv'\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/**\n * 构建完整兼容性报告(RPC 与启动日志共用)。\n * @author ddj 2026年08月24号\n * @param ctx DSH host 上下文\n * @param options 测试注入:depsAvailable 跳过动态导入、version 固定版本号\n * @returns 兼容性报告\n */\nexport async function buildReport(\n ctx: Ctx,\n options?: { depsAvailable?: boolean; version?: string },\n): Promise<CompatReport> {\n const deps = options?.depsAvailable ?? (await loadSettingsDeps()) !== null\n const external = detectExternal(ctx, deps)\n const guards = detectGuards(ctx)\n const warnings: string[] = []\n if (!deps) warnings.push('未安装 @deepseek-ai/dsh-settings:文件打开工具设置持久化不可用(降级为配置值)')\n for (const guard of guards) {\n if (!guard.active && guard.note) warnings.push(guard.note)\n }\n return { pluginVersion: options?.version ?? pluginVersionOf(), external, guards, warnings, devForm: readDevForm() }\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'\n\n/** webServer 精确路由。 */\nexport const RPC_PATH = '/edrv/rpc'\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/** 一条批量决策项(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 }\n 'edrv.original': { sessionId?: string; path: string }\n 'edrv.save': { sessionId?: string; path: string; content: string }\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.listDir': { sessionId?: string; path: string }\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; expectedRevision?: number }\n 'vscode.devFormGet': {}\n 'vscode.devFormSet': { enabled: boolean; path?: string }\n 'compat': {}\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 }\n 'edrv.original': { content: string; size: number; stale: StaleHunk[]; fallback: boolean }\n 'edrv.save': 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.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; revision?: number }\n 'vscode.fileOpenSettingsUpdate': { fileOpenTool: string; revision?: number }\n 'vscode.devFormGet': { devForm: DevFormInfo }\n 'vscode.devFormSet': { devForm: DevFormInfo; restart: boolean }\n 'compat': { report: CompatReport }\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 — webServer 路由注册(/edrv/rpc、/edrv/assets/*、/edrv/vendor/*)。\n * 迁移自原 src/index.ts 的路由部分,路径/行为一字不改。\n * 作者 ddj 2026-08-20\n */\nimport { readFile } from 'node:fs/promises'\nimport { dirname, extname, join, normalize, resolve, sep } from 'node:path'\nimport { fileURLToPath } from 'node:url'\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'\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_PREFIX = '/edrv/vendor'\nconst VENDOR_MIME: Record<string, string> = {\n '.js': '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}\n\n/** 图标目录:默认插件包内 assets/(随包发布);config.imageDir 可覆盖(用于自定义换图)。 */\nfunction imageDirOf(config: unknown): 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 join(dirname(fileURLToPath(import.meta.url)), '..', 'assets')\n}\n\n/** Monaco AMD 静态目录(随包发布)。 */\nconst vendorDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'assets', 'vendor')\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 = imageDirOf(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 ctx.effect(() => guarded({\n kind: 'prefix',\n path: VENDOR_PREFIX,\n handler: async (req: { method?: string; url?: string }, 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 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.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/** 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, preciseHunk } from './shared/diff.js'\nimport { archiveEntryFor, groupByBatch, normalizeRecord } from './model.js'\n\nexport const SIDECAR = '.dsh-edit-review.json'\nexport const SIDECAR_ARCHIVE = '.dsh-edit-review-archive.json'\nexport const READ_CAP = 8 * 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 console.error('edrv saveBucket failed', 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 const locations = locateHunks(state.content, pending.map((item) => 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 console.error('edrv appendArchiveEntries failed', 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 — 捕获层:监听 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'\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 } catch (error) {\n console.error('edrv capture failed', 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\nconst EXCLUDES = [\n 'node_modules', '.git', '.tmp', '.cache', 'dist', 'build', 'vendor',\n 'coverage', '__pycache__',\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 * 使用打包 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 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) throw new Error('ripgrep 退出码:' + String(code))\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__'])\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 = { at: number; result: WorkspaceSearchResult }\ntype SearchRequest = { session: Session; cwd: string; query: string; activePaths: string[] }\ntype SearchResponse = { files: string[]; truncated: boolean }\n\n/**\n * 短期有界搜索缓存。\n * @author ddj 2026年08月24号\n * @returns 缓存对象\n */\nexport class SearchCache {\n private readonly entries = new Map<string, CacheEntry>()\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()): WorkspaceSearchResult | 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 { ...entry.result, files: [...entry.result.files] }\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: WorkspaceSearchResult, now = Date.now()): void {\n this.entries.delete(key)\n this.entries.set(key, { at: now, result: { ...result, files: [...result.files] } })\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()\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 — 回滚/删除(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 — 项目级 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 — 目录树纯函数(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 — 在 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 — 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 type { DiffRecord, RecordView } from './shared/types.js'\nimport type { Ctx, Session } from './store.js'\nimport {\n READ_CAP,\n appendArchiveEntries,\n archiveRecords,\n autoArchiveStale,\n parseArchive,\n policyOf,\n readArchiveText,\n resolveTarget,\n saveBucket,\n} from './store.js'\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 { restoreFile, revertCall, revertHunk } from './revert.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 { buildReport } from './compat.js'\nimport { readDevForm, setDevForm } from './devForm.js'\nimport { normalizeRel, toTreeEntries } from './tree.js'\nimport { revealInExplorer } from './reveal.js'\n\n/** cwd → Promise 链:串行化 debug 日志追加(fs read+write 非原子,避免并发丢行)。 */\nconst debugWriteQueues = new Map<string, Promise<void>>()\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 * 批量决策核心:一次会话/桶解析 + 逐项处理 + 统一落盘(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/** 各方法 handler 表(类型由 shared/rpc 的 RpcHandlerMap 约束)。 */\nexport function buildHandlers(ctx: Ctx, registry: Registry, searcher = newSearcher(ctx)): RpcHandlerMap {\n return {\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 if (!want && args.skipStale !== true) await autoArchiveStale(ctx, sc.session, sc.cwd, bucket) // 全量轮询时自动清理 stale 幽灵差异(批量决策后的即时刷新可 skipStale 跳过)\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') return { ok: false, error: '文件不存在' }\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 const bucket = await bucketOf(registry, ctx, sc.cwd)\n let changed = false\n for (const rec of bucket.values()) {\n if (rec.path === args.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 === args.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 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 上报 → 写入工作区旁车 .dsh-edit-review-debug.log(console 不一定落盘,文件可靠)\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 const text = String(args.text ?? '')\n const prev = debugWriteQueues.get(sc.cwd) || Promise.resolve()\n const task = prev.then(async () => {\n try {\n const target = await fs.resolve('.dsh-edit-review-debug.log', { cwd: sc.cwd })\n const old = await fs.readText(target).catch(() => '')\n const line = new Date().toISOString() + ' ' + text + '\\n'\n await fs.writeText(target, (old || '') + line, void 0, void 0, policyOf(ctx, sc.session))\n } catch (e) { /* 写日志失败忽略 */ }\n })\n debugWriteQueues.set(sc.cwd, task)\n await task\n console.error('[edrv-debug] ' + 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.listDir': async (args) => {\n // 目录树(侧边栏文件管理用):按会话 cwd 解析,与 edrv.read 同基准,树内相对路径点开即打开。\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 resolveTarget(ctx, sc.session, rel || '.')\n const info = await fs.stat(target)\n if (!info) return { ok: false, error: '目录不存在' }\n if (info.type !== 'directory') return { ok: false, error: '不是目录' }\n const children = await fs.listDir(target)\n const root = fs.processPath(await fs.resolve('.', { cwd: sc.cwd }))\n return { ok: true, root, path: rel, entries: toTreeEntries(rel, children) }\n } catch (error) {\n return { ok: false, error: '读取目录失败:' + String(error) }\n }\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), 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 await settings.update(FILE_OPEN_SETTINGS_NS, { fileOpenTool: normalizeFileOpenTool(args.fileOpenTool) }, 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), 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 }\n}\n\n/**\n * 统一入口:按方法分发到 handler 表。\n * @author ddj 2026年08月20号\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): Promise<RpcResult<M>> {\n const handlers = buildHandlers(ctx, registry, searcher)\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'\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 ctx.logger?.warn?.('[dsh-vscode-mode] 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'\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 console.error('edrv scan failed', 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-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 * 作者 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 { installIsolation } from './mcpIsolation.js'\nimport { dropFileIndex } from './workspace.js'\nimport { cwdOf } from './registry.js'\nimport { setupOpenSettings } from './fileOpenSettings.js'\nimport { PLUGIN_NAME, buildReport } from './compat.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 const registry: Registry = new Map()\n const searcher = newSearcher(ctx)\n /** 兼容性警告收集(route 护栏等写入,启动日志一并输出)。 */\n const warnings: string[] = []\n setupOpenSettings(ctx, config, () => {})\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 }\n })\n\n registerRoutes(ctx, config, (method, args) => handleRpc(ctx, registry, method, args, searcher), (warning) => warnings.push(warning))\n installIsolation(ctx)\n void logCompatSummary(ctx, warnings)\n\n ctx.logger?.info?.('[' + name + '] 编辑差异审查已装配(/edrv/rpc 路由就绪,项目 MCP 隔离已启用)')\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 logger = ctx.logger\n if (!logger?.info) return\n const head = '[' + PLUGIN_NAME + '] 兼容性:' + report.external.length + ' 项外部适配 / ' + report.guards.length + ' 项护栏'\n if (report.warnings.length) {\n logger.warn?.(head + ',警告 ' + report.warnings.length + ' 条:' + report.warnings.join(';'))\n } else {\n logger.info?.(head + ',无警告')\n }\n } catch (error) {\n ctx.logger?.warn?.('[' + PLUGIN_NAME + '] 兼容性报告生成失败:' + String(error))\n }\n}\n"],"mappings":"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"}
|