dsh-config-manager 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/README.md +216 -0
  2. package/README.zh-CN.md +218 -0
  3. package/cordis.patch.yml +45 -0
  4. package/dsh.bundle.patch +21 -0
  5. package/dsh.client +39 -0
  6. package/lib/adapters/agent-presets.d.ts +13 -0
  7. package/lib/adapters/agent-presets.js +14 -0
  8. package/lib/adapters/agent-presets.js.map +1 -0
  9. package/lib/adapters/credentials.d.ts +36 -0
  10. package/lib/adapters/credentials.js +121 -0
  11. package/lib/adapters/credentials.js.map +1 -0
  12. package/lib/adapters/file-collection.d.ts +14 -0
  13. package/lib/adapters/file-collection.js +102 -0
  14. package/lib/adapters/file-collection.js.map +1 -0
  15. package/lib/adapters/index.d.ts +38 -0
  16. package/lib/adapters/index.js +46 -0
  17. package/lib/adapters/index.js.map +1 -0
  18. package/lib/adapters/mcp.d.ts +27 -0
  19. package/lib/adapters/mcp.js +175 -0
  20. package/lib/adapters/mcp.js.map +1 -0
  21. package/lib/adapters/plugin-files.d.ts +15 -0
  22. package/lib/adapters/plugin-files.js +91 -0
  23. package/lib/adapters/plugin-files.js.map +1 -0
  24. package/lib/adapters/plugins.d.ts +13 -0
  25. package/lib/adapters/plugins.js +177 -0
  26. package/lib/adapters/plugins.js.map +1 -0
  27. package/lib/adapters/prompts.d.ts +29 -0
  28. package/lib/adapters/prompts.js +228 -0
  29. package/lib/adapters/prompts.js.map +1 -0
  30. package/lib/adapters/providers.d.ts +33 -0
  31. package/lib/adapters/providers.js +143 -0
  32. package/lib/adapters/providers.js.map +1 -0
  33. package/lib/adapters/sessions.d.ts +14 -0
  34. package/lib/adapters/sessions.js +15 -0
  35. package/lib/adapters/sessions.js.map +1 -0
  36. package/lib/adapters/settings.d.ts +23 -0
  37. package/lib/adapters/settings.js +142 -0
  38. package/lib/adapters/settings.js.map +1 -0
  39. package/lib/adapters/skills.d.ts +13 -0
  40. package/lib/adapters/skills.js +14 -0
  41. package/lib/adapters/skills.js.map +1 -0
  42. package/lib/adapters/test-helpers.d.ts +99 -0
  43. package/lib/adapters/test-helpers.js +192 -0
  44. package/lib/adapters/test-helpers.js.map +1 -0
  45. package/lib/adapters/ui.d.ts +26 -0
  46. package/lib/adapters/ui.js +88 -0
  47. package/lib/adapters/ui.js.map +1 -0
  48. package/lib/adapters/workspaces.d.ts +12 -0
  49. package/lib/adapters/workspaces.js +92 -0
  50. package/lib/adapters/workspaces.js.map +1 -0
  51. package/lib/client.d.ts +377 -0
  52. package/lib/client.js +2598 -0
  53. package/lib/client.js.map +1 -0
  54. package/lib/core/analyzer.d.ts +35 -0
  55. package/lib/core/analyzer.js +563 -0
  56. package/lib/core/analyzer.js.map +1 -0
  57. package/lib/core/backup.d.ts +29 -0
  58. package/lib/core/backup.js +184 -0
  59. package/lib/core/backup.js.map +1 -0
  60. package/lib/core/exporter.d.ts +37 -0
  61. package/lib/core/exporter.js +222 -0
  62. package/lib/core/exporter.js.map +1 -0
  63. package/lib/core/importer.d.ts +42 -0
  64. package/lib/core/importer.js +25 -0
  65. package/lib/core/importer.js.map +1 -0
  66. package/lib/core/index.d.ts +12 -0
  67. package/lib/core/index.js +11 -0
  68. package/lib/core/index.js.map +1 -0
  69. package/lib/core/rollback.d.ts +9 -0
  70. package/lib/core/rollback.js +136 -0
  71. package/lib/core/rollback.js.map +1 -0
  72. package/lib/core/types.d.ts +331 -0
  73. package/lib/core/types.js +18 -0
  74. package/lib/core/types.js.map +1 -0
  75. package/lib/core/validator.d.ts +18 -0
  76. package/lib/core/validator.js +77 -0
  77. package/lib/core/validator.js.map +1 -0
  78. package/lib/index.d.ts +51 -0
  79. package/lib/index.js +875 -0
  80. package/lib/index.js.map +1 -0
  81. package/lib/migrations/index.d.ts +29 -0
  82. package/lib/migrations/index.js +56 -0
  83. package/lib/migrations/index.js.map +1 -0
  84. package/lib/migrations/v1-to-v2.d.ts +9 -0
  85. package/lib/migrations/v1-to-v2.js +10 -0
  86. package/lib/migrations/v1-to-v2.js.map +1 -0
  87. package/lib/profiles/index.d.ts +4 -0
  88. package/lib/profiles/index.js +5 -0
  89. package/lib/profiles/index.js.map +1 -0
  90. package/lib/profiles/profile-manager.d.ts +102 -0
  91. package/lib/profiles/profile-manager.js +522 -0
  92. package/lib/profiles/profile-manager.js.map +1 -0
  93. package/lib/schema/config.d.ts +28 -0
  94. package/lib/schema/config.js +136 -0
  95. package/lib/schema/config.js.map +1 -0
  96. package/lib/schema/manifest.d.ts +28 -0
  97. package/lib/schema/manifest.js +109 -0
  98. package/lib/schema/manifest.js.map +1 -0
  99. package/lib/schema/types.d.ts +169 -0
  100. package/lib/schema/types.js +8 -0
  101. package/lib/schema/types.js.map +1 -0
  102. package/lib/schema/versions.d.ts +27 -0
  103. package/lib/schema/versions.js +50 -0
  104. package/lib/schema/versions.js.map +1 -0
  105. package/lib/security/encryption.d.ts +41 -0
  106. package/lib/security/encryption.js +152 -0
  107. package/lib/security/encryption.js.map +1 -0
  108. package/lib/security/index.d.ts +16 -0
  109. package/lib/security/index.js +17 -0
  110. package/lib/security/index.js.map +1 -0
  111. package/lib/security/integrity.d.ts +30 -0
  112. package/lib/security/integrity.js +78 -0
  113. package/lib/security/integrity.js.map +1 -0
  114. package/lib/security/redaction.d.ts +26 -0
  115. package/lib/security/redaction.js +95 -0
  116. package/lib/security/redaction.js.map +1 -0
  117. package/lib/security/secret-scanner.d.ts +48 -0
  118. package/lib/security/secret-scanner.js +253 -0
  119. package/lib/security/secret-scanner.js.map +1 -0
  120. package/lib/security/zip-security.d.ts +27 -0
  121. package/lib/security/zip-security.js +154 -0
  122. package/lib/security/zip-security.js.map +1 -0
  123. package/lib/ui/conflict-view.d.ts +28 -0
  124. package/lib/ui/conflict-view.js +49 -0
  125. package/lib/ui/conflict-view.js.map +1 -0
  126. package/lib/ui/errors.d.ts +17 -0
  127. package/lib/ui/errors.js +76 -0
  128. package/lib/ui/errors.js.map +1 -0
  129. package/lib/ui/export-flow.d.ts +62 -0
  130. package/lib/ui/export-flow.js +79 -0
  131. package/lib/ui/export-flow.js.map +1 -0
  132. package/lib/ui/import-wizard.d.ts +67 -0
  133. package/lib/ui/import-wizard.js +169 -0
  134. package/lib/ui/import-wizard.js.map +1 -0
  135. package/lib/ui/path-mapping.d.ts +38 -0
  136. package/lib/ui/path-mapping.js +75 -0
  137. package/lib/ui/path-mapping.js.map +1 -0
  138. package/lib/ui/progress.d.ts +27 -0
  139. package/lib/ui/progress.js +76 -0
  140. package/lib/ui/progress.js.map +1 -0
  141. package/lib/ui/report.d.ts +21 -0
  142. package/lib/ui/report.js +146 -0
  143. package/lib/ui/report.js.map +1 -0
  144. package/lib/ui/test-helpers.d.ts +62 -0
  145. package/lib/ui/test-helpers.js +147 -0
  146. package/lib/ui/test-helpers.js.map +1 -0
  147. package/lib/ui/types.d.ts +129 -0
  148. package/lib/ui/types.js +21 -0
  149. package/lib/ui/types.js.map +1 -0
  150. package/lib/utils/hashing.d.ts +17 -0
  151. package/lib/utils/hashing.js +41 -0
  152. package/lib/utils/hashing.js.map +1 -0
  153. package/lib/utils/json.d.ts +24 -0
  154. package/lib/utils/json.js +76 -0
  155. package/lib/utils/json.js.map +1 -0
  156. package/lib/utils/logger.d.ts +39 -0
  157. package/lib/utils/logger.js +82 -0
  158. package/lib/utils/logger.js.map +1 -0
  159. package/lib/utils/paths.d.ts +31 -0
  160. package/lib/utils/paths.js +132 -0
  161. package/lib/utils/paths.js.map +1 -0
  162. package/lib/utils/zip.d.ts +54 -0
  163. package/lib/utils/zip.js +285 -0
  164. package/lib/utils/zip.js.map +1 -0
  165. package/package.json +109 -0
  166. package/src/adapters/agent-presets.ts +14 -0
  167. package/src/adapters/credentials.test.ts +90 -0
  168. package/src/adapters/credentials.ts +141 -0
  169. package/src/adapters/file-collection.ts +110 -0
  170. package/src/adapters/files.test.ts +113 -0
  171. package/src/adapters/index.ts +69 -0
  172. package/src/adapters/mcp.test.ts +96 -0
  173. package/src/adapters/mcp.ts +181 -0
  174. package/src/adapters/plugin-files.ts +96 -0
  175. package/src/adapters/plugins.test.ts +72 -0
  176. package/src/adapters/plugins.ts +176 -0
  177. package/src/adapters/prompts.test.ts +110 -0
  178. package/src/adapters/prompts.ts +226 -0
  179. package/src/adapters/providers.test.ts +125 -0
  180. package/src/adapters/providers.ts +161 -0
  181. package/src/adapters/roundtrip.test.ts +188 -0
  182. package/src/adapters/sessions.ts +15 -0
  183. package/src/adapters/settings.test.ts +93 -0
  184. package/src/adapters/settings.ts +165 -0
  185. package/src/adapters/skills.ts +14 -0
  186. package/src/adapters/test-helpers.ts +207 -0
  187. package/src/adapters/ui.test.ts +56 -0
  188. package/src/adapters/ui.ts +106 -0
  189. package/src/adapters/workspaces.test.ts +79 -0
  190. package/src/adapters/workspaces.ts +95 -0
  191. package/src/client/CLIENT_DEPENDENCIES.md +101 -0
  192. package/src/client/ConfigManagerSection.tsx +60 -0
  193. package/src/client/api.ts +270 -0
  194. package/src/client/client-types.ts +27 -0
  195. package/src/client/common/ErrorBanner.tsx +68 -0
  196. package/src/client/common/ProgressBar.tsx +49 -0
  197. package/src/client/common/ReportView.tsx +117 -0
  198. package/src/client/common/ui.tsx +165 -0
  199. package/src/client/config-manager.module.css +759 -0
  200. package/src/client/css-modules.d.ts +8 -0
  201. package/src/client/export/ExportView.tsx +222 -0
  202. package/src/client/import/ConflictList.tsx +72 -0
  203. package/src/client/import/ImportWizardView.tsx +406 -0
  204. package/src/client/import/PathMappingForm.tsx +77 -0
  205. package/src/client/index.ts +65 -0
  206. package/src/client/locales.ts +182 -0
  207. package/src/core/analyzer.ts +631 -0
  208. package/src/core/backup.ts +212 -0
  209. package/src/core/exporter.ts +246 -0
  210. package/src/core/importer.ts +66 -0
  211. package/src/core/index.ts +39 -0
  212. package/src/core/rollback.ts +140 -0
  213. package/src/core/smoke.test.ts +717 -0
  214. package/src/core/types.ts +343 -0
  215. package/src/core/validator.ts +84 -0
  216. package/src/index.ts +942 -0
  217. package/src/migrations/index.ts +71 -0
  218. package/src/migrations/v1-to-v2.ts +17 -0
  219. package/src/profiles/index.ts +8 -0
  220. package/src/profiles/profile-manager.test.ts +280 -0
  221. package/src/profiles/profile-manager.ts +606 -0
  222. package/src/schema/config.ts +137 -0
  223. package/src/schema/manifest.ts +124 -0
  224. package/src/schema/types.ts +179 -0
  225. package/src/schema/versions.ts +55 -0
  226. package/src/security/encryption.ts +180 -0
  227. package/src/security/index.ts +16 -0
  228. package/src/security/integrity.ts +102 -0
  229. package/src/security/redaction.ts +101 -0
  230. package/src/security/secret-scanner.ts +275 -0
  231. package/src/security/security.test.ts +796 -0
  232. package/src/security/zip-security.ts +180 -0
  233. package/src/ui/conflict-view.test.ts +62 -0
  234. package/src/ui/conflict-view.ts +65 -0
  235. package/src/ui/errors.test.ts +44 -0
  236. package/src/ui/errors.ts +95 -0
  237. package/src/ui/export-flow.test.ts +75 -0
  238. package/src/ui/export-flow.ts +128 -0
  239. package/src/ui/import-wizard.test.ts +128 -0
  240. package/src/ui/import-wizard.ts +208 -0
  241. package/src/ui/path-mapping.test.ts +67 -0
  242. package/src/ui/path-mapping.ts +103 -0
  243. package/src/ui/progress.test.ts +42 -0
  244. package/src/ui/progress.ts +90 -0
  245. package/src/ui/report.test.ts +93 -0
  246. package/src/ui/report.ts +140 -0
  247. package/src/ui/test-helpers.ts +177 -0
  248. package/src/ui/types.ts +193 -0
  249. package/src/utils/hashing.ts +53 -0
  250. package/src/utils/json.ts +77 -0
  251. package/src/utils/logger.ts +114 -0
  252. package/src/utils/paths.ts +122 -0
  253. package/src/utils/zip.ts +332 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":["css","css","css","css","css","css","css","css","css"],"sources":["../src/client/api.ts","../src/ui/types.ts","../src/ui/progress.ts","../src/ui/report.ts","../src/ui/export-flow.ts","../src/client/common/ui.tsx","../src/security/secret-scanner.ts","../src/security/redaction.ts","../src/ui/errors.ts","../src/client/common/ErrorBanner.tsx","../src/client/common/ProgressBar.tsx","../src/client/common/ReportView.tsx","../src/client/export/ExportView.tsx","../src/ui/import-wizard.ts","../src/ui/conflict-view.ts","../src/client/import/ConflictList.tsx","../src/client/import/PathMappingForm.tsx","../src/client/import/ImportWizardView.tsx","../src/client/ConfigManagerSection.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Config Manager 浏览器半 —— `/api/dsh-config-manager/*` 的类型化 fetch 封装。\n *\n * 设计对齐 dsh-ssh 的 `src/client/api.ts` 范式(同源 fetch、readJson、query helper),\n * 但方法签名直接实现 `src/ui/types.ts` 的 `ExportPort` / `ImportPort` 端口契约:\n * 客户端控制器(ExportFlow / ImportWizard)把本类实例当作 port 注入即可,\n * 无需任何额外适配层 —— 这是「直接绑定 src/ui,不重复实现」的关键。\n *\n * 端点契约(Host 半 `src/index.ts` 按此实现,见 CLIENT_DEPENDENCIES.md 的接口说明):\n * ```\n * GET /api/dsh-config-manager/status → ServiceStatus (健康/版本检查)\n * POST /api/dsh-config-manager/export → ExportResponse (body: ExportOptions)\n * GET /api/dsh-config-manager/download?path=… → 文件流(content-disposition 文件名)\n * POST /api/dsh-config-manager/upload?name=… → UploadResponse (body: 原始字节)\n * POST /api/dsh-config-manager/analyze → ImportAnalysis (body: { zipPath })\n * POST /api/dsh-config-manager/plan → ImportPlan (body: { zipPath, decisions })\n * POST /api/dsh-config-manager/execute → ImportResult (body: { zipPath, plan, opts })\n * ```\n * 安全约束:\n * - 所有响应/错误文本在进入 UI 前经 `redact()`(见 common/ErrorBanner.tsx);\n * - secretInputs 只存在于请求体内,绝不落日志;\n * - 本文件不 import 任何 node 模块(纯浏览器 bundle)。\n */\n\nimport type { ImportAnalysis, ImportDecisions, ImportPlan, ImportResult } from '../core/types.ts';\nimport type { ExportOptions, ExportReport } from '../core/types.ts';\nimport type { Manifest } from '../schema/types.ts';\n\n/** Host 半健康检查响应(plugin 版本 / DSH 版本 / 平台,用于主页横幅与兼容性说明) */\nexport interface ServiceStatus {\n ready: boolean;\n pluginVersion: string;\n dshVersion: string;\n platform: string;\n arch: string;\n}\n\n/** export 端点响应(对齐 ExportFlow 的 ExportRunResult 前半部分) */\nexport interface ExportResponse {\n zipPath: string;\n manifest: Manifest;\n report: ExportReport;\n}\n\n/** upload 端点响应:Host 把用户上传的 ZIP 存入受控临时目录,返回可被 analyze/plan/execute 引用的路径 */\nexport interface UploadResponse {\n zipPath: string;\n name: string;\n sizeBytes: number;\n}\n\n/** execute 端点请求体(对齐 ImportWizard.execute 的 opts) */\nexport interface ExecutePayload {\n zipPath: string;\n plan: ImportPlan;\n opts: {\n /** 安全阀:非 true 拒绝执行(core ImportNotConfirmedError) */\n confirm: boolean;\n /** 秘密补录值(仅内存,经 HTTPS 传输,Host 端不落盘) */\n secretInputs: Record<string, string>;\n /** true=任一项失败整体回滚(场景 E);false=单项失败继续 */\n rollbackOnError: boolean;\n };\n}\n\n/** 路由族常量(集中管理,与 Host 半的路由前缀保持一致) */\nexport const CONFIG_MANAGER_API = {\n base: '/api/dsh-config-manager',\n status: '/api/dsh-config-manager/status',\n export: '/api/dsh-config-manager/export',\n download: '/api/dsh-config-manager/download',\n upload: '/api/dsh-config-manager/upload',\n analyze: '/api/dsh-config-manager/analyze',\n plan: '/api/dsh-config-manager/plan',\n execute: '/api/dsh-config-manager/execute',\n} as const;\n\n/** 携带路由 JSON error 消息的错误类型 */\nexport class ConfigManagerApiError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigManagerApiError';\n }\n}\n\n/** 解析 JSON 响应;非 2xx 时抛出带路由 error 消息的 ConfigManagerApiError */\nasync function readJson<T>(response: Response): Promise<T> {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n throw new ConfigManagerApiError(`HTTP ${response.status}: invalid JSON response`);\n }\n if (!response.ok) {\n const message =\n typeof body === 'object' && body !== null && typeof (body as { error?: unknown }).error === 'string'\n ? (body as { error: string }).error\n : `HTTP ${response.status}`;\n throw new ConfigManagerApiError(message);\n }\n return body as T;\n}\n\n/** query-string 辅助(跳过 undefined/空串,与 dsh-ssh 一致) */\nfunction query(params: Record<string, string | number | undefined>): string {\n const search = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== '') search.set(key, String(value));\n }\n const text = search.toString();\n return text === '' ? '' : '?' + text;\n}\n\n/** 浏览器 File System Access API 的最小表面(非全部 lib.dom 版本都有) */\ninterface WindowWithFileSystemAccess {\n showSaveFilePicker?: (options: { suggestedName?: string }) => Promise<{\n createWritable: () => Promise<{ write: (data: Uint8Array) => Promise<void>; close: () => Promise<void> }>;\n }>;\n}\n\n/** 导出下载结果(流式落盘或内存 Blob 兜底) */\nexport interface DownloadResult {\n blob?: Blob;\n filename: string;\n streamed: boolean;\n bytes: number;\n}\n\n/**\n * Config Manager 浏览器半的唯一数据入口。\n * 同时实现 `ExportPort`(export-flow 用)与 `ImportPort`(import-wizard 用)。\n */\nexport class ConfigManagerApi {\n /**\n * 加密备份密码(仅内存,默认 null = 普通备份)。\n * ExportView 在 run 前设置;export 请求体携带给 Host 半做 AES-256-GCM 加密。\n * 绝不写入 manifest / 任何 DSH 配置 / localStorage。\n */\n exportPassword: string | null = null\n\n // ------------------------------------------------------------- status\n /** 健康/版本检查(主页横幅:插件版本 / DSH 版本 / 平台) */\n async status(): Promise<ServiceStatus> {\n const response = await fetch(CONFIG_MANAGER_API.status);\n return readJson<ServiceStatus>(response);\n }\n\n // ------------------------------------------------------------- export\n /** ExportPort.export:调用 Host 侧导出编排(core Exporter)。加密密码随请求体传输(仅内存)。 */\n async export(options: ExportOptions): Promise<ExportResponse> {\n const body: ExportOptions & { password?: string } = {\n ...options,\n password: this.exportPassword ?? undefined,\n };\n const response = await fetch(CONFIG_MANAGER_API.export, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n });\n return readJson<ExportResponse>(response);\n }\n\n /**\n * 把导出的 ZIP 下载到本机。优先 File System Access API 流式落盘\n * (不占整文件内存),不可用时回退内存 Blob(dsh-ssh downloadFile 同款策略)。\n */\n async download(\n zipPath: string,\n onProgress?: (received: number, total: number) => void,\n ): Promise<DownloadResult> {\n const response = await fetch(CONFIG_MANAGER_API.download + query({ path: zipPath }));\n if (!response.ok || response.body === null) {\n const text = await response.text().catch(() => '');\n throw new ConfigManagerApiError(text !== '' ? text : `download failed: HTTP ${response.status}`);\n }\n const total = Number(response.headers.get('content-length') ?? '0');\n const disposition = response.headers.get('content-disposition') ?? '';\n const match = /filename=\"([^\"]+)\"/.exec(disposition);\n const filename = match?.[1] ?? zipPath.split(/[\\\\/]/).pop() ?? 'dsh-config.zip';\n const reader = response.body.getReader();\n const picker =\n typeof window !== 'undefined'\n ? (window as WindowWithFileSystemAccess).showSaveFilePicker\n : undefined;\n let streamed = false;\n let writable: { write: (data: Uint8Array) => Promise<void>; close: () => Promise<void> } | undefined;\n const chunks: Uint8Array<ArrayBuffer>[] = [];\n let received = 0;\n try {\n if (picker !== undefined) {\n const handle = await picker.call(window, { suggestedName: filename });\n writable = await handle.createWritable();\n streamed = true;\n }\n } catch {\n // 用户取消保存对话框或 API 不可用:回退内存 Blob。\n }\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n if (writable !== undefined) {\n await writable.write(value as Uint8Array);\n } else {\n chunks.push(value as Uint8Array<ArrayBuffer>);\n }\n received += value.length;\n onProgress?.(received, total);\n }\n if (writable !== undefined) await writable.close();\n return {\n blob: streamed ? undefined : new Blob(chunks),\n filename,\n streamed,\n bytes: received,\n };\n }\n\n // ------------------------------------------------------------- import\n /** 上传用户选择的 ZIP 到 Host 受控临时目录,返回可引用的 zipPath(dsh-ssh 同款原始字节上传) */\n async upload(file: File): Promise<UploadResponse> {\n const response = await fetch(CONFIG_MANAGER_API.upload + query({ name: file.name }), {\n method: 'POST',\n body: file,\n });\n return readJson<UploadResponse>(response);\n }\n\n /** ImportPort.analyzeImport:零写入分析(校验/兼容性/差异/路径/秘密检测) */\n async analyzeImport(zipPath: string): Promise<ImportAnalysis> {\n const response = await fetch(CONFIG_MANAGER_API.analyze, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ zipPath }),\n });\n return readJson<ImportAnalysis>(response);\n }\n\n /** ImportPort.createImportPlan:用用户决策(冲突/路径映射/策略)生成最终计划(Dry Run 零写入) */\n async createImportPlan(zipPath: string, decisions: ImportDecisions): Promise<ImportPlan> {\n const response = await fetch(CONFIG_MANAGER_API.plan, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ zipPath, decisions }),\n });\n return readJson<ImportPlan>(response);\n }\n\n /** ImportPort.executeImportPlan:快照→分阶段 apply→validate→commit/rollback */\n async executeImportPlan(\n zipPath: string,\n plan: ImportPlan,\n opts: { confirm: boolean; secretInputs?: Record<string, string>; rollbackOnError: boolean },\n ): Promise<ImportResult> {\n const payload: ExecutePayload = {\n zipPath,\n plan,\n opts: {\n confirm: opts.confirm,\n secretInputs: opts.secretInputs ?? {},\n rollbackOnError: opts.rollbackOnError,\n },\n };\n const response = await fetch(CONFIG_MANAGER_API.execute, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n });\n return readJson<ImportResult>(response);\n }\n}\n","/**\n * UI 层共享类型(m6-ui,框架无关)。\n *\n * 设计原则(对齐 Docs/design/architecture.md §12.2 与规范 §28/§29):\n * - 本模块为纯 TypeScript 逻辑层,不引入 React / 打包器 / 任何运行时依赖;\n * - 未来 React 客户端(src/client/)直接消费本层的控制器输出(渲染文本 / 状态快照);\n * - UI 层不直接 import core 的类实现,只依赖 core/types.ts 的纯类型 + 注入的「端口」\n * (ExportPort / ImportPort,宿主在 settings.section 挂载时把真实 Exporter/Importer 接入)。\n */\nimport type { SectionId } from '../schema/types.ts';\nimport type {\n CompatibilityScore, ImportAnalysis, ImportDecisions, ImportPlan, ImportResult,\n ItemResolution, PathIssue, PlanItem, Portability, RollbackReport,\n} from '../core/types.ts';\n\n/* ---------------- 导出(规范 §1 / §21) ---------------- */\n\nexport type ExportMode = 'quick' | 'custom';\n\n/** Custom Export 分组(规范 §1 分类;automation 组在 DSH 中无对应分区,UI 标注说明) */\nexport type ExportGroup =\n | 'general' | 'ai' | 'extensions' | 'mcp' | 'customization'\n | 'automation' | 'workspace' | 'ui' | 'optional';\n\n/** 分类树节点(与 adapters 的 displayName/defaultIncluded/portability 对齐;宿主可注入覆盖) */\nexport interface ExportCategory {\n id: SectionId;\n label: string;\n description: string;\n defaultIncluded: boolean;\n portability: Portability;\n group: ExportGroup;\n /** 涉及秘密状态(如 credentialsStatus):UI 需展示安全提示但绝不显示值 */\n sensitive?: boolean;\n}\n\nexport interface ExportGroupDef {\n id: ExportGroup;\n label: string;\n /** automation 组在 DSH 无对应配置时的说明 */\n note?: string;\n}\n\n/** Custom Export 分组目录(规范 §1;automation 组 DSH 无对应分区,仅说明) */\nexport const EXPORT_GROUPS: readonly ExportGroupDef[] = [\n { id: 'general', label: 'General' },\n { id: 'ai', label: 'AI' },\n { id: 'extensions', label: 'Extensions' },\n { id: 'mcp', label: 'MCP / Tools' },\n { id: 'customization', label: 'Customization' },\n { id: 'automation', label: 'Automation', note: 'DSH 当前无 Workflows / Commands 配置文件(运行时注册),无迁移内容' },\n { id: 'workspace', label: 'Workspace' },\n { id: 'ui', label: 'UI' },\n { id: 'optional', label: 'Optional Data' },\n] as const;\n\n/** Quick Export 推荐项 = defaultIncluded 且非 deviceSpecific(设计 §11.1) */\nexport function isQuickRecommended(c: ExportCategory): boolean {\n return c.defaultIncluded && c.portability !== 'deviceSpecific';\n}\n\n/* ---------------- 进度事件(规范 §29) ---------------- */\n\nexport interface ProgressEvent {\n /** 阶段 id(见 progress.ts 的 STAGE_TEXTS) */\n stage: string;\n detail?: string;\n /** 阶段序号(从 1 起,供 UI 显示 n/m) */\n step?: number;\n /** 阶段总数 */\n total?: number;\n}\n\nexport type ProgressListener = (event: ProgressEvent) => void;\n\n/* ---------------- 导入向导(规范 §9 / §10 / §28) ---------------- */\n\nexport type ImportStep =\n | 'select' // 选 ZIP\n | 'analyzing' // Analyzing...\n | 'compatibility' // Compatibility\n | 'preview' // Import Preview(Dry Run 摘要)\n | 'conflicts' // Resolve Conflicts(§11)\n | 'path-mapping' // Path Mapping(§12)\n | 'secrets' // Secrets 补录(§7)\n | 'importing' // Importing(含快照/回滚阶段)\n | 'result'; // Result(§22)\n\n/** Preview 摘要(规范 §10 示例的数值化版本) */\nexport interface ImportPreviewSummary {\n /** 将更新的配置项数(Create+Update+Install 合计) */\n willChange: number;\n /** 已存在且一致的项(Skip) */\n unchanged: number;\n settingsUpdates: number;\n pluginsInstalled: number;\n pluginsToInstall: number;\n mcpAdds: number;\n prompts: number;\n pathMappingsNeeded: number;\n secretsNeeded: number;\n conflicts: number;\n needsRestart: boolean;\n}\n\n/** 向导状态快照(React 客户端可直接绑定渲染) */\nexport interface WizardSnapshot {\n step: ImportStep;\n zipPath: string | null;\n analysis: ImportAnalysis | null;\n plan: ImportPlan | null;\n result: ImportResult | null;\n /** 导入执行的回滚策略(场景 E:默认 true 整体回滚) */\n rollbackOnError: boolean;\n errors: string[];\n}\n\n/* ---------------- 冲突视图(规范 §11) ---------------- */\n\n/** 单个冲突项的视图数据:当前值 vs 导入值摘要 + 用户决策 */\nexport interface ConflictViewItem {\n item: PlanItem;\n currentSummary?: string;\n importedSummary?: string;\n resolution: ItemResolution | null;\n}\n\n/* ---------------- 路径映射(规范 §12) ---------------- */\n\n/** 路径映射编辑器的单条记录(旧前缀 → 新前缀;未解析时 newPrefix 为空串) */\nexport interface PathMappingDraft {\n /** 关联的原始路径问题值(一条 issue 一条 draft;批量映射用 oldPrefix 聚合) */\n oldPrefix: string;\n newPrefix: string;\n issue?: PathIssue;\n /** 应用范围(缺省 [] = 全部相关分区,与 core applyMappingsToSections 语义一致) */\n appliesTo: PathMappingAppliesTo[];\n}\n\n/** 与 core PathMapping.appliesTo 对齐的取值(留空数组 = 全应用) */\nexport type PathMappingAppliesTo = 'workspaces' | 'mcp' | 'pluginConfig' | 'skills';\n\n/* ---------------- 兼容性(规范 §30) ---------------- */\n\nexport interface CompatibilityView {\n score: CompatibilityScore;\n sourceDsh: string;\n targetDsh: string;\n description: string;\n}\n\n/* ---------------- 报告(规范 §21 / §22 / §17) ---------------- */\n\n/** 导入结果按分区的统计(report.ts 用) */\nexport interface ImportSectionStat {\n section: SectionId;\n ok: number;\n skipped: number;\n failed: number;\n items: { itemId: string; status: 'ok' | 'skipped' | 'failed'; message?: string }[];\n}\n\nexport type ImportResultAction = 'fixIssues' | 'viewDetails' | 'done';\n\nexport interface RollbackView {\n report: RollbackReport | null;\n /** 是否有可展示的人工恢复清单(partial 回滚时) */\n hasManualRecovery: boolean;\n}\n\n/* ---------------- 控制器公共依赖注入 ---------------- */\n\n/** UI 层与 core 的导入端口(宿主注入真实 Importer;测试注入内存 mock) */\nexport interface ImportPort {\n analyzeImport(zipPath: string): Promise<ImportAnalysis>;\n createImportPlan(zipPath: string, decisions: ImportDecisions): Promise<ImportPlan>;\n executeImportPlan(\n zipPath: string,\n plan: ImportPlan,\n opts: {\n /** 用户确认(安全阀,非 true 拒绝执行) */\n confirm: boolean;\n secretInputs?: Record<string, string>;\n /** 显式回滚策略:true=任一项失败整体回滚(场景 E);false=单项失败继续(§34.17) */\n rollbackOnError: boolean;\n },\n ): Promise<ImportResult>;\n}\n\n/** 选项构造辅助:从 PlanItem 提取稳定决策键(与 core analyzer.applyItemResolution 的 id 语义一致) */\nexport function itemDecisionKey(item: PlanItem): string {\n return item.id;\n}\n","/**\n * 进度阶段文案与进度追踪(规范 §29,m6-ui)。\n *\n * 纯文本层:每个阶段 id 有默认文案;未知阶段回退显示 id 本身。\n * ProgressTracker 供导出/导入控制器在调用 core 前后发出阶段事件(UI 不冻结)。\n */\nimport type { ProgressEvent, ProgressListener } from './types.ts';\n\n/** 导出阶段文案(规范 §29 Export 示例) */\nexport const EXPORT_STAGES: readonly string[] = [\n 'analyzing', // Analyzing configuration...\n 'exporting-settings', // Exporting settings...\n 'scanning-secrets', // Scanning secrets...\n 'exporting-plugins', // Exporting plugins...\n 'creating-archive', // Creating archive...\n 'calculating-checksums', // Calculating checksums...\n 'done',\n] as const;\n\n/** 导入阶段文案(规范 §29 Import 示例 + 快照/回滚阶段) */\nexport const IMPORT_STAGES: readonly string[] = [\n 'validating', // Validating backup...\n 'checking-compatibility', // Checking compatibility...\n 'creating-snapshot', // Creating safety snapshot...\n 'restoring-settings', // Restoring settings...\n 'restoring-plugins', // Restoring plugins...\n 'restoring-mcp', // Restoring MCP...\n 'validating-config', // Validating configuration...\n 'rolling-back', // Rolling back...(仅失败回滚时)\n 'done',\n] as const;\n\nconst STAGE_TEXTS: Record<string, string> = {\n // export\n 'analyzing': 'Analyzing configuration...',\n 'exporting-settings': 'Exporting settings...',\n 'scanning-secrets': 'Scanning secrets...',\n 'exporting-plugins': 'Exporting plugins...',\n 'creating-archive': 'Creating archive...',\n 'calculating-checksums': 'Calculating checksums...',\n // import\n 'validating': 'Validating backup...',\n 'checking-compatibility': 'Checking compatibility...',\n 'creating-snapshot': 'Creating safety snapshot...',\n 'restoring-settings': 'Restoring settings...',\n 'restoring-plugins': 'Restoring plugins...',\n 'restoring-mcp': 'Restoring MCP...',\n 'validating-config': 'Validating configuration...',\n 'rolling-back': 'Rolling back...',\n // common\n 'done': 'Done',\n};\n\n/** 阶段 id → 用户可读文案(未知阶段回退 id) */\nexport function stageText(stage: string): string {\n return STAGE_TEXTS[stage] ?? stage;\n}\n\n/**\n * 进度追踪器:按给定阶段序列在回调时附带 step/total 序号。\n * 控制器调用 core 前后 emit(),UI 侧渲染进度条/阶段文字。\n */\nexport class ProgressTracker {\n private readonly listener: ProgressListener | undefined;\n private readonly stages: readonly string[];\n private readonly emitted: string[] = [];\n\n constructor(stages: readonly string[], listener?: ProgressListener) {\n this.stages = stages;\n this.listener = listener;\n }\n\n /** 发出某阶段事件(可携带 detail);未在序列中的阶段 step/total 缺省 */\n emit(stage: string, detail?: string): void {\n const idx = this.stages.indexOf(stage);\n const event: ProgressEvent = {\n stage,\n detail,\n step: idx >= 0 ? idx + 1 : undefined,\n total: idx >= 0 ? this.stages.length : undefined,\n };\n this.emitted.push(stage);\n this.listener?.(event);\n }\n\n /** 已发出阶段的快照(测试与日志用) */\n get events(): readonly string[] {\n return [...this.emitted];\n }\n}\n","/**\n * 报告渲染(规范 §21 导出报告 / §22 导入报告 / §17 回滚报告,m6-ui)。\n *\n * 纯文本渲染:输出用户可读的多行文本(未来 React 客户端可直接替换为组件渲染)。\n * 导入报告按分区统计:从 ExecutedItem.itemId 前缀推断所属分区(与 adapters 的 id 规则一致)。\n */\nimport type { SectionId } from '../schema/types.ts';\nimport type {\n ExecutedItem, ExportReport, ImportResult, RollbackReport,\n} from '../core/types.ts';\nimport type { ImportResultAction, ImportSectionStat } from './types.ts';\n\n/* ---------------- §21 导出报告 ---------------- */\n\nexport function renderExportReport(report: ExportReport): string {\n const lines: string[] = ['Backup Created', ''];\n lines.push('Included:');\n for (const { section, counts } of report.included) {\n const detail = Object.entries(counts)\n .map(([k, v]) => `${v} ${k}`)\n .join(', ');\n lines.push(` ✓ ${section}${detail !== '' ? ` (${detail})` : ''}`);\n }\n lines.push('');\n if (report.excluded.length > 0) {\n lines.push('Excluded:');\n for (const s of report.excluded) lines.push(` ○ ${s}`);\n lines.push('');\n }\n lines.push('Security:');\n lines.push(` ✓ API Keys excluded: ${report.security.secretsExcluded ? 'yes' : 'no'}`);\n lines.push(` ✓ Contains secrets: ${report.security.containsSecrets ? 'yes (encrypted)' : 'no'}`);\n lines.push(` ✓ Encrypted: ${report.security.encrypted ? 'yes' : 'no'}`);\n if (report.security.redactedHits > 0) lines.push(` ⚠ ${report.security.redactedHits} sensitive field(s) redacted`);\n lines.push('');\n lines.push(`File: ${report.file.name} (${formatBytes(report.file.sizeBytes)})`);\n for (const w of report.warnings) lines.push(` ⚠ ${w}`);\n return lines.join('\\n');\n}\n\n/* ---------------- §22 导入报告 ---------------- */\n\n/** 从 itemId 前缀推断所属分区(与 adapters id 规则对齐;未知归 'other') */\nexport function sectionFromItemId(itemId: string): SectionId | 'other' {\n if (itemId.startsWith('settings:')) return 'settings';\n if (itemId.startsWith('ui:')) return 'ui';\n if (itemId.startsWith('provider:')) return 'providers';\n if (itemId.startsWith('plugin:') || itemId.startsWith('patch:')) return 'plugins';\n if (itemId.startsWith('mcp:')) return 'mcp';\n if (itemId.startsWith('prompt:')) return 'prompts';\n if (itemId.startsWith('workspace:')) return 'workspaces';\n if (itemId.startsWith('secret:')) return 'credentialsStatus';\n if (itemId.startsWith('skills:')) return 'skills';\n if (itemId.startsWith('agentPresets:')) return 'agentPresets';\n if (itemId.startsWith('pluginFiles:')) return 'pluginFiles';\n if (itemId.startsWith('sessions:')) return 'sessions';\n return 'other';\n}\n\n/** 按分区聚合执行结果(统计 + 明细) */\nexport function importSectionStats(executed: readonly ExecutedItem[]): ImportSectionStat[] {\n const bySection = new Map<string, ImportSectionStat>();\n for (const e of executed) {\n const section = sectionFromItemId(e.itemId);\n let stat = bySection.get(section);\n if (!stat) {\n stat = { section: section as SectionId, ok: 0, skipped: 0, failed: 0, items: [] };\n bySection.set(section, stat);\n }\n if (e.status === 'ok') stat.ok += 1;\n else if (e.status === 'skipped') stat.skipped += 1;\n else stat.failed += 1;\n stat.items.push(e);\n }\n return [...bySection.values()];\n}\n\n/** 导入报告渲染(含回滚状态;§22 动作按钮由 suggestedActions 给出) */\nexport function renderImportReport(result: ImportResult): string {\n const lines: string[] = [result.ok ? 'Import Complete' : 'Import Failed', ''];\n const stats = importSectionStats(result.executed);\n for (const s of stats) {\n const parts: string[] = [];\n if (s.ok > 0) parts.push(`✓ ${s.ok} imported/restored`);\n if (s.skipped > 0) parts.push(`- ${s.skipped} skipped`);\n if (s.failed > 0) parts.push(`✗ ${s.failed} failed`);\n lines.push(`${s.section}: ${parts.join(' ') || 'no changes'}`);\n // 失败项给出可操作原因(§23)\n for (const it of s.items) {\n if (it.status === 'failed') {\n lines.push(` Reason: ${it.message ?? '未知原因'}`);\n }\n }\n }\n if (result.missingSecrets.length > 0) {\n lines.push(`Secrets: ⚠ ${result.missingSecrets.length} credentials need to be entered`);\n }\n if (result.needsRestart) {\n lines.push('Restart required: 插件/MCP 变更将在重启 DSH 后生效');\n }\n for (const w of result.warnings) lines.push(`⚠ ${w}`);\n if (result.rollback) {\n lines.push('');\n lines.push(renderRollbackReport(result.rollback));\n }\n return lines.join('\\n');\n}\n\n/** 结果页动作按钮(§22:Fix Issues / View Details / Done) */\nexport function suggestedActions(result: ImportResult): ImportResultAction[] {\n const actions: ImportResultAction[] = [];\n if (result.executed.some((e) => e.status === 'failed')) actions.push('fixIssues');\n if (result.executed.length > 0 || result.warnings.length > 0) actions.push('viewDetails');\n actions.push('done');\n return actions;\n}\n\n/* ---------------- §17 回滚报告 ---------------- */\n\n/** 回滚报告渲染(full / partial + 人工恢复清单) */\nexport function renderRollbackReport(rr: RollbackReport): string {\n if (rr.full) {\n return 'Rollback: 已完整恢复导入前的配置。';\n }\n const lines = ['Rollback partially completed.'];\n lines.push('These items may require manual recovery:');\n for (const f of rr.failed) {\n lines.push(` - ${f.item}: ${f.reason}${f.manualHint ? ` (${f.manualHint})` : ''}`);\n }\n if (rr.restored.length > 0) lines.push(`Restored: ${rr.restored.length} item(s)`);\n return lines.join('\\n');\n}\n\n/* ---------------- 工具 ---------------- */\n\nexport function formatBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${(n / (1024 * 1024)).toFixed(1)} MB`;\n}\n","/**\n * Export 控制器(规范 §1 / §21,m6-ui)。\n *\n * 职责:\n * - Quick Export:推荐项 = defaultIncluded 且非 deviceSpecific 的分区(设计 §11.1);\n * - Custom Export:按 §1 分组目录逐项勾选(含默认关闭的可选分区 pluginFiles/sessions);\n * - 进度事件:调用 core 前后按 §29 阶段文案发出(UI 不冻结);\n * - 结果:返回 ExportReport 并渲染 §21 文本报告。\n *\n * 依赖注入:ExportPort 由宿主在挂载时接入真实 Exporter(core/exporter.ts),\n * 测试注入内存 mock —— 本层零依赖 core 实现。\n */\nimport type { Manifest, SectionId } from '../schema/types.ts';\nimport type { ExportOptions, ExportReport } from '../core/types.ts';\nimport {\n EXPORT_GROUPS, type ExportCategory, type ExportGroup,\n type ProgressListener, isQuickRecommended,\n} from './types.ts';\nimport { EXPORT_STAGES, ProgressTracker } from './progress.ts';\nimport { renderExportReport } from './report.ts';\n\n/** UI → core 的导出端口(宿主注入 Exporter.export;测试注入 mock) */\nexport interface ExportPort {\n export(options: ExportOptions): Promise<{ zipPath: string; manifest: Manifest; report: ExportReport }>;\n}\n\nexport interface ExportFlowOptions {\n port: ExportPort;\n /** 分类目录(缺省用内置目录,与 adapters 的 displayName/defaultIncluded/portability 对齐) */\n categories?: ExportCategory[];\n onProgress?: ProgressListener;\n}\n\nexport interface ExportRunResult {\n zipPath: string;\n manifest: Manifest;\n report: ExportReport;\n /** §21 渲染文本(report.ts) */\n text: string;\n}\n\n/** 内置分类目录(与 src/adapters/* 的 displayName/defaultIncluded/portability 对齐,研究报告 §2.2) */\nexport const DEFAULT_CATEGORIES: readonly ExportCategory[] = [\n { id: 'settings', label: 'Settings', description: 'DSH 全局设置(namespace 分区,redacted)', defaultIncluded: true, portability: 'portable', group: 'general' },\n { id: 'providers', label: 'Providers & Models', description: 'LLM Provider / Model / 默认模型 / BaseURL', defaultIncluded: true, portability: 'portable', group: 'ai' },\n { id: 'plugins', label: 'Plugins', description: '已安装插件清单与启用状态(不含二进制)', defaultIncluded: true, portability: 'portable', group: 'extensions' },\n { id: 'pluginFiles', label: 'Plugin Files', description: '插件自有配置文件(dsh-ssh.json 等,白名单)', defaultIncluded: false, portability: 'deviceSpecific', group: 'extensions' },\n { id: 'mcp', label: 'MCP Servers', description: 'MCP 服务器组合配置(需重启生效)', defaultIncluded: true, portability: 'platformSpecific', group: 'mcp' },\n { id: 'prompts', label: 'Prompts', description: 'System Prompt / Plan Mode 提示', defaultIncluded: true, portability: 'portable', group: 'customization' },\n { id: 'skills', label: 'Skills', description: '用户技能文件(~/.dsh/skills)', defaultIncluded: true, portability: 'portable', group: 'customization' },\n { id: 'agentPresets', label: 'Agent Presets', description: 'Agent 预设(~/.dsh/.agent-presets)', defaultIncluded: true, portability: 'portable', group: 'customization' },\n { id: 'workspaces', label: 'Workspaces', description: '工作区记录(含绝对路径,需路径映射)', defaultIncluded: true, portability: 'platformSpecific', group: 'workspace' },\n { id: 'ui', label: 'UI Preferences', description: 'UI 类 settings namespace(localStorage 项仅说明)', defaultIncluded: true, portability: 'portable', group: 'ui' },\n { id: 'credentialsStatus', label: 'Credentials Status', description: '凭据状态(configured 标记,永不导出值)', defaultIncluded: true, portability: 'deviceSpecific', group: 'optional', sensitive: true },\n { id: 'sessions', label: 'Sessions', description: '历史会话(默认关闭,含敏感内容)', defaultIncluded: false, portability: 'deviceSpecific', group: 'optional' },\n] as const;\n\nexport class ExportFlow {\n readonly categories: readonly ExportCategory[];\n private readonly port: ExportPort;\n private readonly onProgress: ProgressListener | undefined;\n\n constructor(opts: ExportFlowOptions) {\n this.port = opts.port;\n this.categories = opts.categories ?? DEFAULT_CATEGORIES;\n this.onProgress = opts.onProgress;\n }\n\n /** Quick Export 推荐分区(defaultIncluded 且非 deviceSpecific) */\n quickSelection(): SectionId[] {\n return this.categories.filter(isQuickRecommended).map((c) => c.id);\n }\n\n /** 按 §1 分组返回分类目录(Custom Export 树) */\n groupedCatalog(): { group: ExportGroup; label: string; note?: string; categories: ExportCategory[] }[] {\n return EXPORT_GROUPS.map((g) => ({\n group: g.id,\n label: g.label,\n note: g.note,\n categories: this.categories.filter((c) => c.group === g.id),\n }));\n }\n\n /** 校验 Custom 勾选:未知分区 = invalid;deviceSpecific 分区给提示警告(仍可继续) */\n validateSelection(selection: readonly SectionId[]): { valid: boolean; warnings: string[] } {\n const warnings: string[] = [];\n let valid = true;\n const known = new Set(this.categories.map((c) => c.id));\n for (const id of selection) {\n if (!known.has(id)) {\n warnings.push(`未知分区:${id}`);\n valid = false;\n }\n }\n for (const c of this.categories) {\n if (selection.includes(c.id) && c.portability === 'deviceSpecific') {\n warnings.push(`${c.label} 为设备相关数据(${c.portability}),跨设备导入时可能不适用`);\n }\n }\n return { valid, warnings };\n }\n\n /** 执行导出:发进度事件 → 调 core → 渲染 §21 报告 */\n async run(\n mode: 'quick' | 'custom',\n selection: readonly SectionId[],\n opts: { includeSecrets?: boolean } = {},\n ): Promise<ExportRunResult> {\n const tracker = new ProgressTracker(EXPORT_STAGES, this.onProgress);\n const only = mode === 'quick' ? this.quickSelection() : [...selection];\n if (mode === 'quick' && opts.includeSecrets === undefined) opts = { ...opts, includeSecrets: false };\n\n tracker.emit('analyzing');\n tracker.emit('exporting-settings');\n tracker.emit('scanning-secrets');\n tracker.emit('exporting-plugins');\n tracker.emit('creating-archive');\n tracker.emit('calculating-checksums');\n\n const result = await this.port.export({\n includeSecrets: opts.includeSecrets ?? false,\n only,\n });\n\n tracker.emit('done');\n return { ...result, text: renderExportReport(result.report) };\n }\n}\n","/**\n * Config Manager 基础 UI 原语(dsh-ssh 风格,全部走 DSH Design System 的 --dsw-* token,\n * 不另造视觉体系)。仅作薄封装:类名来自 config-manager.module.css,无业务逻辑。\n */\nimport type { ChangeEvent, ReactNode } from 'react'\nimport css from '../config-manager.module.css'\n\n/* ---------------- Button ---------------- */\n\nexport type ButtonVariant = 'primary' | 'ghost' | 'danger'\n\nexport interface ButtonProps {\n variant?: ButtonVariant\n disabled?: boolean\n onClick?: () => void\n children: ReactNode\n title?: string\n className?: string\n}\n\n/** 统一按钮(primary=主操作 / ghost=次操作 / danger=危险操作) */\nexport function Button({ variant = 'ghost', disabled, onClick, children, title, className }: ButtonProps) {\n const cls =\n variant === 'primary' ? css.primaryButton\n : variant === 'danger' ? css.dangerButton\n : css.ghostButton\n return (\n <button\n type=\"button\"\n className={className !== undefined ? `${cls} ${className}` : cls}\n disabled={disabled}\n title={title}\n onClick={onClick}\n >\n {children}\n </button>\n )\n}\n\n/* ---------------- Badge ---------------- */\n\nexport type BadgeKind = 'info' | 'ok' | 'warn' | 'error'\n\nexport interface BadgeProps {\n kind?: BadgeKind\n children: ReactNode\n}\n\n/** 状态徽章(info=业务色 / ok=成功 / warn=警告 / error=错误) */\nexport function Badge({ kind = 'info', children }: BadgeProps) {\n return <span className={`${css.badge} ${css[`badge${kind[0]!.toUpperCase()}${kind.slice(1)}`] ?? ''}`}>{children}</span>\n}\n\n/* ---------------- Banner ---------------- */\n\nexport type BannerKind = 'ok' | 'error' | 'info' | 'warn'\n\nexport interface BannerProps {\n kind?: BannerKind\n children: ReactNode\n}\n\n/** 说明横幅(ok/error/info/warn 四态) */\nexport function Banner({ kind = 'info', children }: BannerProps) {\n return <div className={css.banner} data-kind={kind}>{children}</div>\n}\n\n/* ---------------- Card ---------------- */\n\nexport interface CardProps {\n children: ReactNode\n className?: string\n}\n\n/** 卡片容器(bg-layer-2 + 圆角 + 细边框) */\nexport function Card({ children, className }: CardProps) {\n return <div className={className !== undefined ? `${css.card} ${className}` : css.card}>{children}</div>\n}\n\n/* ---------------- Spinner ---------------- */\n\nexport interface SpinnerProps {\n label?: string\n}\n\n/** 加载指示(旋转环 + 可选文案) */\nexport function Spinner({ label }: SpinnerProps) {\n return (\n <span className={css.spinnerWrap}>\n <span className={css.spinner} aria-hidden=\"true\" />\n {label !== undefined && <span className={css.spinnerLabel}>{label}</span>}\n </span>\n )\n}\n\n/* ---------------- Field ---------------- */\n\nexport interface FieldProps {\n label: string\n hint?: string\n children: ReactNode\n}\n\n/** 表单字段(标签 + 控件 + 说明) */\nexport function Field({ label, hint, children }: FieldProps) {\n return (\n <label className={css.field}>\n <span className={css.fieldLabel}>{label}</span>\n {children}\n {hint !== undefined && <span className={css.hint}>{hint}</span>}\n </label>\n )\n}\n\n/* ---------------- SectionTitle ---------------- */\n\nexport interface SectionTitleProps {\n title: string\n subtitle?: string\n}\n\n/** 区块标题(页面内二级标题 + 可选副标题) */\nexport function SectionTitle({ title, subtitle }: SectionTitleProps) {\n return (\n <div className={css.sectionTitleBlock}>\n <h3 className={css.sectionTitle}>{title}</h3>\n {subtitle !== undefined && <p className={css.sectionSubtitle}>{subtitle}</p>}\n </div>\n )\n}\n\n/* ---------------- Empty / Loading ---------------- */\n\nexport interface EmptyProps {\n children: ReactNode\n}\n\n/** 空状态占位 */\nexport function Empty({ children }: EmptyProps) {\n return <div className={css.empty}>{children}</div>\n}\n\n/* ---------------- Checkbox ---------------- */\n\nexport interface CheckboxProps {\n checked: boolean\n onChange: (checked: boolean) => void\n label: ReactNode\n disabled?: boolean\n}\n\n/** 复选框行(勾选 + 标签) */\nexport function Checkbox({ checked, onChange, label, disabled }: CheckboxProps) {\n return (\n <label className={css.checkboxRow}>\n <input\n type=\"checkbox\"\n checked={checked}\n disabled={disabled}\n onChange={(event: ChangeEvent<HTMLInputElement>) => { onChange(event.target.checked) }}\n />\n <span>{label}</span>\n </label>\n )\n}\n","/**\n * 敏感字段扫描器(规范 §6 / 设计 §7.2 / core `SecretScanner` 契约的强化实现)。\n *\n * 定位:`ctx.settings.describe({redactSecrets:true})` 已剥离 DSH 已知秘密(设计 §7.2),\n * 本扫描器是**第二道防线**,兜底插件自定义字段、MCP headers、patch config、文件类分区文本。\n *\n * 判定策略(两级,避免误伤/漏报):\n * - 字段名:规范化(小写、去 `_-. ` 分隔符)后做「精确命中 / 敏感后缀 / 敏感前缀」三级匹配;\n * 只剥离**字符串叶值**(对象/数组整体递归,不整块剥离——保证 `credentials: [...]` 状态数组存活)。\n * - 引用豁免:`apiKeyEnv` 等「只存引用名」字段、以及形如 `DEEPSEEK_API_KEY` 的全大写环境变量名\n * (`isEnvVarName`)一律保留——值是名字不是秘密。\n * - 值形状启发式(规范 §6「不能只根据固定字段判断」):字段名未命中但值长得像 secret\n * (sk- / JWT / AKIA / GitHub PAT / PEM 私钥 / Bearer)也剥离;高熵 base64 默认关(误伤率高)。\n *\n * 实现不变量:返回 sanitized 为**全新对象**(不改原数据);迭代式显式栈(防爆栈)+ 深度上限;\n * 命中记录只含路径与字段名,**值永不外泄**。\n */\nimport { JsonDepthError } from '../utils/json.ts';\nimport type { SecretScanner, SensitiveHit } from '../core/types.ts';\n\n/** 剥离占位(与 core defaultSecretScanner 语义一致:空串 = 需补录提示) */\nexport const REDACTED_PLACEHOLDER = '';\n\n/**\n * 敏感字段名单(规范化名:小写、无分隔符)。\n * 覆盖规范 §6 原始清单 + 设计 §7.2 + core logger 名单,并保持克制以防误伤\n * (不收录 `key`/`session` 等过宽子串——`sessionIds`/`monkey` 不得中招)。\n */\nexport const DEFAULT_SECRET_FIELD_NAMES: readonly string[] = [\n // 规范 §6 原文\n 'password', 'passwd', 'token', 'accesstoken', 'refreshtoken',\n 'apikey', 'secret', 'credential', 'authorization', 'cookie',\n 'privatekey', 'clientsecret',\n // 设计 §7.2 / core logger 扩充\n 'pwd', 'passphrase', 'authtoken', 'sessionkey', 'apisecret',\n 'authheader', 'bearer', 'webhooksecret',\n];\n\n/** 引用字段(值只是「名字」而非秘密):规范化精确命中即豁免 */\nexport const DEFAULT_REFERENCE_FIELDS: readonly string[] = [\n 'apikeyenv', 'apikeyname', 'apikeyref',\n 'tokenenv', 'accesstokenenv', 'refreshtokenenv',\n 'clientsecretenv', 'passwordenv', 'secretref', 'credentialref',\n];\n\n/** 敏感后缀(规范化后以这些结尾 → 命中;`key` 故意不收,避免 monkey/whiskey 误伤) */\nconst SENSITIVE_SUFFIXES = ['token', 'secret', 'password', 'passwd', 'credential'] as const;\n\n/** 敏感前缀(规范化后以这些开头 → 命中;token/secret 等过宽词不收入) */\nconst SENSITIVE_PREFIXES = [\n 'apikey', 'accesstoken', 'refreshtoken', 'authtoken',\n 'clientsecret', 'privatekey', 'authorization', 'authheader',\n 'webhooksecret', 'apisecret',\n] as const;\n\n/** 值形状强模式(默认开):一眼可辨的密钥/凭据形态(包含式:值内任意位置出现即命中) */\nexport interface ValuePattern { name: string; re: RegExp }\nexport const SECRET_VALUE_PATTERNS: readonly ValuePattern[] = [\n { name: 'openai-style-key', re: /sk-[A-Za-z0-9_-]{8,}/ },\n { name: 'jwt', re: /eyJ[A-Za-z0-9_-]{8,}\\.eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}/ },\n { name: 'aws-access-key', re: /AKIA[0-9A-Z]{16}/ },\n { name: 'github-token', re: /gh[pousr]_[A-Za-z0-9]{20,}/ },\n { name: 'github-pat', re: /github_pat_[A-Za-z0-9_]{20,}/ },\n { name: 'pem-private-key', re: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |ENCRYPTED )?PRIVATE KEY-----/ },\n { name: 'bearer-token', re: /Bearer [A-Za-z0-9._~+/=-]{8,}/ },\n];\n\nexport interface SecretScannerOptions {\n /** 附加敏感字段名(任意原始形态,内部会规范化) */\n extraFieldNames?: string[];\n /** 附加引用字段名(规范化后精确命中即豁免) */\n extraReferenceFields?: string[];\n /** 值形状启发式开关(默认 true) */\n valuePatterns?: boolean;\n /** 高熵长串启发式(默认 false:误伤风险高,需显式开启) */\n highEntropy?: boolean;\n /** 最大递归深度(默认 64,与 JSON 深度上限一致) */\n maxDepth?: number;\n}\n\n/** 规范化字段名:小写 + 去 `_-. ` 分隔符(用于名单匹配) */\nexport function normalizeFieldName(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9]/g, '');\n}\n\n/** 是否为「环境变量名」形态(全大写下划线,如 DEEPSEEK_API_KEY)→ 视为引用名 */\nexport function isEnvVarName(value: string): boolean {\n return /^[A-Z][A-Z0-9_]{2,}$/.test(value);\n}\n\n/** 字段名是否命中敏感名单(规范化后精确 / 敏感后缀 / 敏感前缀) */\nexport function isSensitiveFieldName(\n field: string,\n extra: readonly string[] = [],\n): boolean {\n const norm = normalizeFieldName(field);\n if (norm === '') return false;\n if ([...DEFAULT_SECRET_FIELD_NAMES, ...extra].includes(norm)) return true;\n if (SENSITIVE_SUFFIXES.some((s) => norm.endsWith(s) && norm.length > s.length)) return true;\n return SENSITIVE_PREFIXES.some((p) => norm.startsWith(p));\n}\n\n/** 是否为引用字段(值只是名字,不剥离) */\nexport function isReferenceField(\n field: string,\n extra: readonly string[] = [],\n): boolean {\n const norm = normalizeFieldName(field);\n return [...DEFAULT_REFERENCE_FIELDS, ...extra].includes(norm);\n}\n\n/** 值是否命中强模式 secret 形状(返回命中模式名;未命中返回 null) */\nexport function matchSecretValuePattern(value: string): string | null {\n for (const p of SECRET_VALUE_PATTERNS) {\n if (p.re.test(value)) return p.name;\n }\n return null;\n}\n\n/** 高熵启发式:长 base64/hex 串且 Shannon 熵高(默认关) */\nfunction isHighEntropySecret(value: string): boolean {\n if (!/^[A-Za-z0-9+/=_-]{32,}$/.test(value)) return false;\n if (/^[A-Za-z0-9_-]+$/.test(value) && !/[0-9]/.test(value)) return false; // 纯单词串(如文件名)\n const counts = new Map<string, number>();\n for (const ch of value) counts.set(ch, (counts.get(ch) ?? 0) + 1);\n let entropy = 0;\n for (const n of counts.values()) {\n const p = n / value.length;\n entropy -= p * Math.log2(p);\n }\n return entropy > 4.2;\n}\n\n/** 判定单个「字段名 + 字符串值」:strip | keep(含引用豁免与值形状)\n * 顺序:值形状优先(AKIA 等全大写 secret 形状不能被 env 名豁免误放)→ 引用字段 → env 名 → 字段名。 */\nfunction judgeFieldValue(field: string, value: string, opts: Required<Pick<SecretScannerOptions, 'extraFieldNames' | 'extraReferenceFields' | 'valuePatterns' | 'highEntropy'>>): boolean {\n if (value === '') return false;\n if (opts.valuePatterns && matchSecretValuePattern(value) !== null) return true;\n if (isReferenceField(field, opts.extraReferenceFields)) return false;\n if (isEnvVarName(value)) return false; // 值是 env 变量名 → 引用\n if (isSensitiveFieldName(field, opts.extraFieldNames)) return true;\n if (opts.highEntropy && isHighEntropySecret(value)) return true;\n return false;\n}\n\n/** 递归扫描 + 剥离(纯函数,不改原数据;深度保护;返回清洗后数据与命中清单) */\nexport function scanAndRedact(data: unknown, opts: SecretScannerOptions = {}): { sanitized: unknown; hits: SensitiveHit[] } {\n const maxDepth = opts.maxDepth ?? 64;\n const cfg: Required<Pick<SecretScannerOptions, 'extraFieldNames' | 'extraReferenceFields' | 'valuePatterns' | 'highEntropy'>> = {\n extraFieldNames: opts.extraFieldNames ?? [],\n extraReferenceFields: opts.extraReferenceFields ?? [],\n valuePatterns: opts.valuePatterns ?? true,\n highEntropy: opts.highEntropy ?? false,\n };\n const hits: SensitiveHit[] = [];\n\n if (data === null || typeof data !== 'object') return { sanitized: data, hits };\n if (data instanceof Uint8Array) return { sanitized: data, hits };\n\n const rootOut: unknown = Array.isArray(data) ? [] : {};\n interface Frame { src: unknown; dst: unknown; path: string; depth: number }\n const stack: Frame[] = [{ src: data, dst: rootOut, path: '', depth: 1 }];\n const visited = new WeakSet<object>();\n visited.add(data as object);\n\n while (stack.length > 0) {\n const frame = stack.pop()!;\n const { src, dst, path, depth } = frame;\n if (depth > maxDepth) throw new JsonDepthError(`扫描深度 ${depth} 超过上限 ${maxDepth}`);\n if (src instanceof Uint8Array) continue;\n\n if (Array.isArray(src)) {\n const outArr = dst as unknown[];\n for (let i = 0; i < src.length; i++) {\n const v = src[i];\n const childPath = `${path}[${i}]`;\n if (v !== null && typeof v === 'object' && !(v instanceof Uint8Array)) {\n if (visited.has(v)) throw new Error(`检测到循环引用,无法扫描(路径 ${childPath})`);\n visited.add(v);\n const childOut: unknown = Array.isArray(v) ? [] : {};\n outArr.push(childOut);\n stack.push({ src: v, dst: childOut, path: childPath, depth: depth + 1 });\n } else {\n outArr.push(v);\n }\n }\n continue;\n }\n\n const outObj = dst as Record<string, unknown>;\n for (const [k, v] of Object.entries(src as Record<string, unknown>)) {\n const childPath = path === '' ? k : `${path}.${k}`;\n if (typeof v === 'string') {\n if (judgeFieldValue(k, v, cfg)) {\n hits.push({ path: childPath, field: k });\n outObj[k] = REDACTED_PLACEHOLDER;\n } else {\n outObj[k] = v;\n }\n continue;\n }\n if (v !== null && typeof v === 'object' && !(v instanceof Uint8Array)) {\n if (visited.has(v)) throw new Error(`检测到循环引用,无法扫描(路径 ${childPath})`);\n visited.add(v);\n const childOut: unknown = Array.isArray(v) ? [] : {};\n outObj[k] = childOut;\n stack.push({ src: v, dst: childOut, path: childPath, depth: depth + 1 });\n } else {\n outObj[k] = v;\n }\n }\n }\n\n return { sanitized: rootOut, hits };\n}\n\n/* ---------------- 文本级扫描(scanText,文件类分区内容用) ---------------- */\n\nconst FIELD_VALUE_RE = [\n // \"field\": \"value\"(JSON 形态,保留引号)\n { re: /\"([A-Za-z0-9_.\\-]+)\"\\s*:\\s*\"([^\"]*)\"/g, json: true },\n // field=value\n { re: /([A-Za-z0-9_.\\-]+)\\s*=\\s*([^\\s,;]+)/g, json: false },\n // field: value\n { re: /([A-Za-z0-9_.\\-]+)\\s*:\\s*([^\\s,;}]+)/g, json: false },\n] as const;\n\n/** 文本级扫描:逐行找「敏感字段名 = 值」与「值形状」命中(只报告,不修改文本) */\nexport function scanText(text: string, opts: SecretScannerOptions = {}): SensitiveHit[] {\n const hits: SensitiveHit[] = [];\n const extra = opts.extraFieldNames ?? [];\n const valuePatterns = opts.valuePatterns ?? true;\n const lines = text.split(/\\r?\\n/);\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const linePath = `line:${i + 1}`;\n // 字段名形态\n for (const { re, json } of FIELD_VALUE_RE) {\n re.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(line)) !== null) {\n const field = m[1]!;\n const value = m[2]!;\n if (!isSensitiveFieldName(field, extra)) continue;\n if (json) {\n // JSON 形态下引号内值才报告(引用名豁免由调用方结合场景决定,这里保守报告)\n hits.push({ path: linePath, field });\n continue;\n }\n if (isEnvVarName(value)) continue; // 引用名不报告\n hits.push({ path: linePath, field });\n }\n }\n // 值形状(字段名无关)\n if (valuePatterns) {\n const trimmed = line.trim();\n const name = matchSecretValuePattern(trimmed);\n if (name !== null) hits.push({ path: linePath, field: `(${name})` });\n }\n }\n return hits;\n}\n\n/** 强化版 SecretScanner(对齐 core SecretScanner 契约,可注入 Exporter.scanner) */\nexport function createSecretScanner(opts: SecretScannerOptions = {}): SecretScanner {\n return {\n scanAndRedact(data: unknown): { sanitized: unknown; hits: SensitiveHit[] } {\n return scanAndRedact(data, opts);\n },\n scanText(text: string): SensitiveHit[] {\n return scanText(text, opts);\n },\n };\n}\n","/**\n * 日志/文本脱敏(规范 §24 / 设计 §9.8 / core utils/logger.ts 的强化层)。\n *\n * 与 core logger.redact 的分工:core 版按固定字段名单做子串替换(不感知字段边界);\n * 本模块为强化版,两模式:\n * 1. **结构化字段形态**:JSON `\"field\": \"value\"` / `field=value` / `field: value`,\n * 字段名命中敏感名单(复用 secret-scanner 的 `isSensitiveFieldName`,单一来源防漂移)→ 值替换。\n * 2. **值形状模式**:与字段名无关,文本任意位置出现 sk- / JWT / AKIA / GitHub PAT /\n * PEM 私钥 / Bearer / URL query 的敏感参数值 → 替换。\n *\n * 幂等性:替换产物 `***REDACTED***` 不匹配任何模式,重复 redact 结果不变;\n * JSON 行的引号结构保留(输出仍是合法 JSON)。\n */\nimport { DEFAULT_SECRET_FIELD_NAMES, isSensitiveFieldName } from './secret-scanner.ts';\n\nexport const REDACTED = '***REDACTED***';\n\n/* ---------------- 结构化字段形态 ---------------- */\n\nconst JSON_FIELD_RE = /\"([A-Za-z0-9_.\\-]+)\"\\s*:\\s*\"([^\"]*)\"/g;\n/** kv 值到空白/逗号/分号/&(& 截断:避免吞掉 URL query 的后续参数) */\nconst KV_FIELD_RE = /([A-Za-z0-9_.\\-]+)\\s*=\\s*([^\\s,;&]+)/g;\n/** colon 值允许空格(如 `Authorization: Bearer xyz`),到逗号/分号/右大括号截断 */\nconst COLON_FIELD_RE = /([A-Za-z0-9_.\\-]+)\\s*:\\s*([^,;}]+)/g;\n\n/* ---------------- 值形状模式(包含式,字段名无关) ---------------- */\n\nconst VALUE_PATTERNS: { name: string; re: RegExp }[] = [\n { name: 'openai-key', re: /sk-[A-Za-z0-9_-]{8,}/g },\n { name: 'jwt', re: /eyJ[A-Za-z0-9_-]{8,}\\.eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}/g },\n { name: 'aws-access-key', re: /AKIA[0-9A-Z]{16}/g },\n { name: 'github-token', re: /gh[pousr]_[A-Za-z0-9]{20,}/g },\n { name: 'github-pat', re: /github_pat_[A-Za-z0-9_]{20,}/g },\n { name: 'pem-private-key', re: /-----BEGIN [A-Za-z0-9 ]*PRIVATE KEY-----/g },\n { name: 'bearer-token', re: /Bearer [A-Za-z0-9._~+/=-]{8,}/g },\n];\n\n/** URL query 中的敏感参数值(保留参数名,只替换值) */\nconst URL_QUERY_RE = /([?&](?:token|api[_-]?key|key|secret|access[_-]?token|password|auth)=)([^&\\s\"']+)/gi;\n\n/* ---------------- redact ---------------- */\n\nfunction replaceSensitiveField(text: string, re: RegExp, blacklist: readonly string[]): string {\n return text.replace(re, (match: string, field: string, value: string) => {\n if (!isSensitiveFieldName(field, blacklist)) return match;\n if (value === '') return match;\n // 只替换值部分,保留原分隔符与引号形态(JSON `\"f\": \"v\"` / kv `f=v` / colon `f: v`)\n const idx = match.lastIndexOf(value);\n return match.slice(0, idx) + REDACTED + match.slice(idx + value.length);\n });\n}\n\n/**\n * 文本脱敏(幂等)。blacklist 为**附加**规范化字段名(小写无分隔符,如 'clientsecret')。\n * 输出仍保留结构化形态(JSON 行合法)。\n */\nexport function redact(text: string, blacklist: readonly string[] = []): string {\n let out = text;\n // 1. 结构化字段形态(顺序:JSON → kv → colon;JSON 键不会被后续形态二次命中)\n out = replaceSensitiveField(out, JSON_FIELD_RE, blacklist);\n out = replaceSensitiveField(out, KV_FIELD_RE, blacklist);\n out = replaceSensitiveField(out, COLON_FIELD_RE, blacklist);\n // 2. 值形状模式(字段名无关,包含式)\n for (const { re } of VALUE_PATTERNS) {\n re.lastIndex = 0;\n out = out.replace(re, REDACTED);\n }\n out = out.replace(URL_QUERY_RE, `$1${REDACTED}`);\n return out;\n}\n\n/** 对象级掩码:字段名命中敏感名单 → 整值替换(返回新对象,不改原对象;结构与类型保留) */\nexport function redactValue(value: unknown, blacklist: readonly string[] = []): unknown {\n if (value === null || typeof value !== 'object') return value;\n if (value instanceof Uint8Array) return value;\n if (Array.isArray(value)) return value.map((v) => redactValue(v, blacklist));\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = isSensitiveFieldName(k, blacklist) ? REDACTED : redactValue(v, blacklist);\n }\n return out;\n}\n\n/** 预编译脱敏器(多次调用复用;blacklist 为附加规范化字段名) */\nexport function createRedactor(blacklist: readonly string[] = []): (text: string) => string {\n const compiled = { json: JSON_FIELD_RE, kv: KV_FIELD_RE, colon: COLON_FIELD_RE };\n return (text: string): string => {\n let out = replaceSensitiveField(text, new RegExp(compiled.json.source, 'g'), blacklist);\n out = replaceSensitiveField(out, new RegExp(compiled.kv.source, 'g'), blacklist);\n out = replaceSensitiveField(out, new RegExp(compiled.colon.source, 'g'), blacklist);\n for (const { re } of VALUE_PATTERNS) {\n re.lastIndex = 0;\n out = out.replace(re, REDACTED);\n }\n out = out.replace(URL_QUERY_RE, `$1${REDACTED}`);\n return out;\n };\n}\n\n/** 默认名单(文档用;redact 的默认附加名单为空,内置判定已含 DEFAULT_SECRET_FIELD_NAMES) */\nexport { DEFAULT_SECRET_FIELD_NAMES };\n","/**\n * 可操作错误模型(规范 §23,m6-ui)。\n *\n * 绝不只有 \"Something went wrong.\":\n * - 解析错误 → Reason + Suggested action(可操作);\n * - 输出前强制脱敏(redact),Secret 永不进入 UI/日志。\n */\nimport { redact } from '../security/redaction.ts';\n\n/** 可操作错误(UI 渲染为 Reason / Suggested action 两段) */\nexport interface ActionableError {\n title: string;\n reason: string;\n suggestedAction?: string;\n /** 相关项(如 MCP 服务器名 / 插件包名);可空 */\n item?: string;\n /** 是否可重试(true 显示重试按钮) */\n retryable: boolean;\n}\n\n/** 常见错误 → 建议动作 的规则表(按错误消息子串匹配) */\ninterface ErrorRule {\n match: (msg: string) => boolean;\n title: string;\n suggestedAction: string;\n retryable: boolean;\n}\n\nconst ERROR_RULES: readonly ErrorRule[] = [\n {\n match: (m) => /SETTINGS_CONFLICT|revision.*conflict/i.test(m),\n title: '配置已被并发修改',\n suggestedAction: '目标 DSH 的该配置在导入期间被其他进程修改,为避免覆盖请重新导出或手动核对后再试。',\n retryable: true,\n },\n {\n match: (m) => /ImportNotConfirmed|未确认/i.test(m),\n title: '导入未确认',\n suggestedAction: '请在预览页确认导入内容后重试。',\n retryable: true,\n },\n {\n match: (m) => /backup integrity|完整性校验失败|checksum/i.test(m),\n title: '备份完整性校验失败',\n suggestedAction: '备份文件可能已损坏或被篡改,请重新导出备份后再试。',\n retryable: false,\n },\n {\n match: (m) => /schema.*(不支持|超出)|无法导入|Unsupported/i.test(m),\n title: '备份格式版本不受支持',\n suggestedAction: '请升级 DSH Config Manager 或使用相同版本的备份文件。',\n retryable: false,\n },\n {\n match: (m) => /ENOENT|not found|无法读取|不存在/i.test(m),\n title: '文件或路径不存在',\n suggestedAction: '请检查文件路径是否正确、文件是否已被移动或删除。',\n retryable: true,\n },\n {\n match: (m) => /EACCES|permission|权限/i.test(m),\n title: '权限不足',\n suggestedAction: '请检查目标目录的读写权限后重试。',\n retryable: true,\n },\n {\n match: (m) => /install.*(plugin|插件)|needsRestart|重启/i.test(m),\n title: '插件安装需要重启生效',\n suggestedAction: '导入已完成,插件将在重启 DSH 后生效;请在 DSH Desktop 中重启服务。',\n retryable: false,\n },\n];\n\n/** 将任意错误转换为可操作错误(消息已脱敏,不泄漏 Secret) */\nexport function toActionableError(err: unknown, opts?: { item?: string; fallbackTitle?: string }): ActionableError {\n const raw = err instanceof Error ? err.message : String(err ?? '未知错误');\n const message = redact(raw);\n const rule = ERROR_RULES.find((r) => r.match(message));\n return {\n title: rule?.title ?? opts?.fallbackTitle ?? '操作失败',\n reason: message,\n suggestedAction: rule?.suggestedAction,\n item: opts?.item !== undefined ? redact(opts.item) : undefined,\n retryable: rule?.retryable ?? true,\n };\n}\n\n/** 格式化为用户可读的多行文本(Reason / Suggested action) */\nexport function formatActionableError(e: ActionableError): string {\n const lines = [e.title];\n lines.push(`Reason: ${e.reason}`);\n if (e.suggestedAction) lines.push(`Suggested action: ${e.suggestedAction}`);\n if (e.item) lines.push(`Item: ${e.item}`);\n return lines.join('\\n');\n}\n","/**\n * 可操作错误展示(规范 §23,绑 src/ui/errors.ts)。\n *\n * 安全约束:**强制 redact 不泄 Secret** —— 展示前对错误消息、关联项文本\n * 统一过 `redact()`(字段名黑名单 + sk-/JWT/PEM/Bearer 等值形状模式),\n * 渲染结果只含 Reason / Suggested action / Item,绝不出现密钥原文。\n */\nimport { useState } from 'react'\nimport { formatActionableError, toActionableError } from '../../ui/errors.ts'\nimport { redact } from '../../security/redaction.ts'\nimport { Button } from './ui.tsx'\nimport css from '../config-manager.module.css'\n\nexport interface ErrorBannerProps {\n /** 任意未知错误(Error / 字符串 / API 错误) */\n error: unknown\n /** 可重试时显示的重试按钮(缺省不显示) */\n onRetry?: () => void\n /** 重试中的 loading 态 */\n retrying?: boolean\n}\n\n/**\n * 错误横幅:toActionableError 解析为标题 + 原因 + 建议动作,\n * 文本在渲染前再经 redact() 兜底(双保险),Reason 以等宽块展示。\n */\nexport function ErrorBanner({ error, onRetry, retrying }: ErrorBannerProps) {\n const [actionable] = useState(() => toActionableError(error))\n const reason = redact(actionable.reason)\n const item = actionable.item !== undefined ? redact(actionable.item) : undefined\n\n return (\n <div className={css.errorBanner} role=\"alert\">\n <div className={css.errorTitle}>{redact(actionable.title)}</div>\n <pre className={css.errorReason}>{reason}</pre>\n {actionable.suggestedAction !== undefined && (\n <div className={css.errorAction}>\n <span className={css.errorActionLabel}>→</span> {redact(actionable.suggestedAction)}\n </div>\n )}\n {item !== undefined && <div className={css.errorItem}>{item}</div>}\n {actionable.retryable && onRetry !== undefined && (\n <div className={css.errorFooter}>\n <Button variant=\"primary\" onClick={onRetry} disabled={retrying === true}>\n {retrying === true ? '…' : 'Retry'}\n </Button>\n </div>\n )}\n </div>\n )\n}\n\n/** 多行错误文本展示(Wizard.errors 数组用;同样强制 redact) */\nexport function ErrorList({ errors }: { errors: readonly string[] }) {\n if (errors.length === 0) return null\n return (\n <div className={css.errorList}>\n {errors.map((line, i) => (\n <pre key={i} className={css.errorLine}>{redact(line)}</pre>\n ))}\n </div>\n )\n}\n\n/** formatActionableError 的文本化出口(供非 React 渲染场景复用) */\nexport function formatErrorText(error: unknown): string {\n return formatActionableError(toActionableError(error))\n}\n","/**\n * 进度条(规范 §29,绑 src/ui/progress.ts)。\n *\n * 控制器(ExportFlow / ImportWizard)在调用 core 前后发出 ProgressEvent,\n * 本组件按 stage 文案 + step/total 渲染进度条;未知阶段回退显示 id 本身。\n */\nimport { stageText } from '../../ui/progress.ts'\nimport type { ProgressEvent } from '../../ui/types.ts'\nimport css from '../config-manager.module.css'\n\nexport interface ProgressBarProps {\n /** 当前阶段事件(null = 未开始) */\n event: ProgressEvent | null\n /** 是否正在执行(false 时显示为完成态) */\n active: boolean\n}\n\n/**\n * 进度条:阶段文字 + 百分比(有 step/total 时计算,否则不定态动画)。\n */\nexport function ProgressBar({ event, active }: ProgressBarProps) {\n const percent =\n event !== null && event.step !== undefined && event.total !== undefined && event.total > 0\n ? Math.round((event.step / event.total) * 100)\n : null\n const label = event !== null ? stageText(event.stage) : ''\n\n return (\n <div className={css.progressBlock}>\n <div className={css.progressMeta}>\n <span className={css.progressLabel}>{label}</span>\n {event?.detail !== undefined && event.detail !== '' && (\n <span className={css.progressDetail}>{event.detail}</span>\n )}\n {percent !== null && <span className={css.progressPercent}>{percent}%</span>}\n </div>\n <div className={css.progressTrack}>\n {percent !== null ? (\n <div\n className={`${css.progressBar} ${active ? '' : css.progressBarDone}`}\n style={{ width: `${percent}%` }}\n />\n ) : (\n <div className={`${css.progressBar} ${css.progressIndeterminate}`} />\n )}\n </div>\n </div>\n )\n}\n","/**\n * 结果报告(规范 §21 导出 / §22 导入 / §17 回滚,绑 src/ui/report.ts)。\n *\n * 直接调用 report.ts 的纯文本渲染器(renderExportReport / renderImportReport /\n * renderRollbackReport / suggestedActions / importSectionStats),React 只做外壳:\n * 标题 + 结构化统计徽章 + 文本详情 + 建议动作按钮。\n *\n * 安全约束:所有渲染文本展示前再过 `redact()` 兜底,Secret 不进入 UI。\n */\nimport type { ExportReport, ImportResult, RollbackReport } from '../../core/types.ts'\nimport {\n importSectionStats,\n renderExportReport,\n renderImportReport,\n renderRollbackReport,\n suggestedActions,\n} from '../../ui/report.ts'\nimport type { ImportResultAction } from '../../ui/types.ts'\nimport { redact } from '../../security/redaction.ts'\nimport { Badge, Button, type BadgeKind } from './ui.tsx'\nimport css from '../config-manager.module.css'\n\nexport type ReportViewKind = 'export' | 'import'\n\nexport interface ReportViewProps {\n kind: ReportViewKind\n exportReport?: ExportReport\n importResult?: ImportResult\n /** 结果页动作回调(Fix Issues / View Details / Done) */\n onAction?: (action: ImportResultAction) => void\n /** 下载导出文件的回调(导出报告场景) */\n onDownload?: () => void\n}\n\n/** 导入分区的统计徽章(由 report.importSectionStats 计算) */\nfunction SectionStatBadges({ result }: { result: ImportResult }) {\n const stats = importSectionStats(result.executed)\n return (\n <div className={css.statRow}>\n {stats.map((s) => {\n let kind: BadgeKind = 'ok'\n if (s.failed > 0) kind = 'error'\n else if (s.skipped > 0) kind = 'warn'\n return (\n <Badge key={s.section} kind={kind}>\n {s.section}: {s.ok}✓{s.skipped > 0 ? ` ${s.skipped}≈` : ''}{s.failed > 0 ? ` ${s.failed}✗` : ''}\n </Badge>\n )\n })}\n </div>\n )\n}\n\n/** 导出报告的安全摘要(Included / Excluded / Security 徽章) */\nfunction ExportSummary({ report }: { report: ExportReport }) {\n const included = report.included.length\n const excluded = report.excluded.length\n return (\n <div className={css.statRow}>\n <Badge kind=\"ok\">{included} included</Badge>\n {excluded > 0 && <Badge kind=\"warn\">{excluded} excluded</Badge>}\n {report.security.containsSecrets && <Badge kind=\"warn\">encrypted</Badge>}\n {!report.security.containsSecrets && <Badge kind=\"ok\">no secrets</Badge>}\n {report.security.redactedHits > 0 && (\n <Badge kind=\"error\">{report.security.redactedHits} redacted</Badge>\n )}\n </div>\n )\n}\n\n/**\n * 结果报告视图。\n * 文本详情 = report.ts 渲染器的输出(已脱敏),展示前再过 redact() 双保险;\n * 以 <pre> 等宽块呈现保持对齐。\n */\nexport function ReportView({ kind, exportReport, importResult, onAction, onDownload }: ReportViewProps) {\n const actions = kind === 'import' && importResult !== undefined\n ? suggestedActions(importResult)\n : []\n\n return (\n <div className={css.reportView}>\n {kind === 'export' && exportReport !== undefined && (\n <>\n <ExportSummary report={exportReport} />\n <pre className={css.reportText}>{redact(renderExportReport(exportReport))}</pre>\n {onDownload !== undefined && (\n <div className={css.reportFooter}>\n <Button variant=\"primary\" onClick={onDownload}>Download</Button>\n </div>\n )}\n </>\n )}\n {kind === 'import' && importResult !== undefined && (\n <>\n <SectionStatBadges result={importResult} />\n <pre className={css.reportText}>{redact(renderImportReport(importResult))}</pre>\n {importResult.rollback !== null && (\n <div className={css.rollbackBox}>\n <strong>Rollback</strong>\n <pre className={css.reportText}>{redact(renderRollbackReport(importResult.rollback as RollbackReport))}</pre>\n </div>\n )}\n {actions.length > 0 && (\n <div className={css.reportFooter}>\n {actions.map((a) => (\n <Button key={a} variant={a === 'done' ? 'primary' : 'ghost'} onClick={() => onAction?.(a)}>\n {a}\n </Button>\n ))}\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n","/**\n * 导出视图(规范 §1 / §21,绑 src/ui/export-flow.ts 的 ExportFlow 控制器)。\n *\n * - Quick:一键导出推荐分区(ExportFlow.quickSelection());\n * - Custom:按 §1 分组目录(EXPORT_GROUPS × DEFAULT_CATEGORIES)逐项勾选,\n * ExportFlow.validateSelection() 给出设备相关分区警告;\n * - Include secrets:可选加密备份(需设置加密密码,密码仅本次内存使用,\n * 经 api.exportPassword 随请求体传给 Host 半,绝不落盘/入 manifest);\n * - 进度:ExportFlow.run 发出 ProgressEvent → ProgressBar;\n * - 结果:ReportView(export) + 下载按钮(File System Access API 流式落盘)。\n */\nimport { useCallback, useState } from 'react'\nimport type { ChangeEvent } from 'react'\nimport { ExportFlow, DEFAULT_CATEGORIES } from '../../ui/export-flow.ts'\nimport { EXPORT_GROUPS } from '../../ui/types.ts'\nimport type { ExportRunResult } from '../../ui/export-flow.ts'\nimport type { ProgressEvent } from '../../ui/types.ts'\nimport type { SectionId } from '../../schema/types.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport type { ConfigManagerApi } from '../api.ts'\nimport { Badge, Banner, Button, Card, Checkbox, SectionTitle, Spinner } from '../common/ui.tsx'\nimport { ErrorBanner } from '../common/ErrorBanner.tsx'\nimport { ProgressBar } from '../common/ProgressBar.tsx'\nimport { ReportView } from '../common/ReportView.tsx'\nimport css from '../config-manager.module.css'\n\nexport interface ExportViewProps {\n api: ConfigManagerApi\n t: TranslateNS<'config-manager'>\n}\n\ntype ExportMode = 'quick' | 'custom'\n\n/** Custom 模式的初始勾选 = 推荐分区(可再调整) */\nfunction defaultCustomSelection(): SectionId[] {\n return DEFAULT_CATEGORIES.filter((c) => c.defaultIncluded).map((c) => c.id)\n}\n\n/**\n * 导出主视图:Quick/Custom 切换 → 勾选/密码 → 执行 → 进度 → 报告 → 下载。\n */\nexport function ExportView({ api, t }: ExportViewProps) {\n const [mode, setMode] = useState<ExportMode>('quick')\n const [selection, setSelection] = useState<SectionId[]>(defaultCustomSelection)\n const [includeSecrets, setIncludeSecrets] = useState(false)\n const [password, setPassword] = useState('')\n const [passwordConfirm, setPasswordConfirm] = useState('')\n const [running, setRunning] = useState(false)\n const [progress, setProgress] = useState<ProgressEvent | null>(null)\n const [result, setResult] = useState<ExportRunResult | null>(null)\n const [error, setError] = useState<unknown>(null)\n const [downloaded, setDownloaded] = useState(false)\n\n // ExportFlow 控制器实例(port=api,onProgress 桥到 React state)\n const [flow] = useState(() => new ExportFlow({\n port: api,\n onProgress: (event) => { setProgress(event) },\n }))\n\n const toggleSection = useCallback((id: SectionId, checked: boolean) => {\n setSelection((prev) => {\n const has = prev.includes(id)\n if (checked && !has) return [...prev, id]\n if (!checked && has) return prev.filter((s) => s !== id)\n return prev\n })\n }, [])\n\n const passwordInvalid =\n includeSecrets && (password === '' || password !== passwordConfirm)\n\n /** 执行导出(Quick 或 Custom) */\n const runExport = async (): Promise<void> => {\n if (passwordInvalid) return\n setRunning(true)\n setError(null)\n setResult(null)\n setDownloaded(false)\n setProgress(null)\n try {\n // 加密密码随本次导出请求体传给 Host 半(仅内存)\n api.exportPassword = includeSecrets ? password : null\n const run = await flow.run(mode, selection, { includeSecrets })\n setResult(run)\n } catch (err) {\n setError(err)\n } finally {\n setRunning(false)\n setProgress(null)\n }\n }\n\n /** 下载导出的 ZIP 到本机 */\n const download = async (): Promise<void> => {\n if (result === null) return\n try {\n setError(null)\n const outcome = await api.download(result.zipPath)\n setDownloaded(true)\n void outcome // blob/streamed 由 api 处理;此处仅确认成功\n } catch (err) {\n setError(err)\n }\n }\n\n // Custom 模式下的设备相关分区警告\n const customWarnings = mode === 'custom' ? flow.validateSelection(selection).warnings : []\n\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('view.export')} subtitle={t('section.description')} />\n\n {/* 模式切换 */}\n <div className={css.modeTabs} role=\"tablist\">\n <button type=\"button\" role=\"tab\" aria-selected={mode === 'quick'} data-active={mode === 'quick' ? '' : undefined} className={css.modeTab} onClick={() => { setMode('quick') }}>\n {t('export.mode.quick')}\n </button>\n <button type=\"button\" role=\"tab\" aria-selected={mode === 'custom'} data-active={mode === 'custom' ? '' : undefined} className={css.modeTab} onClick={() => { setMode('custom') }}>\n {t('export.mode.custom')}\n </button>\n </div>\n <div className={css.modeHint}>\n {mode === 'quick' ? t('export.mode.quickHint') : t('export.mode.customHint')}\n </div>\n\n {/* Custom:分组勾选目录 */}\n {mode === 'custom' && (\n <div className={css.groupList}>\n {EXPORT_GROUPS.map((group) => {\n const categories = flow.categories.filter((c) => c.group === group.id)\n if (categories.length === 0) return null\n return (\n <Card key={group.id} className={css.groupCard}>\n <div className={css.groupHeader}>\n <span className={css.groupLabel}>{group.label}</span>\n {group.note !== undefined && <span className={css.groupNote}>{group.note}</span>}\n </div>\n <div className={css.groupItems}>\n {categories.map((cat) => (\n <Checkbox\n key={cat.id}\n checked={selection.includes(cat.id)}\n onChange={(checked) => { toggleSection(cat.id, checked) }}\n label={\n <span className={css.categoryItem}>\n <span className={css.categoryName}>{cat.label}</span>\n <span className={css.categoryDesc}>{cat.description}</span>\n {cat.portability !== 'portable' && (\n <Badge kind={cat.portability === 'deviceSpecific' ? 'warn' : 'info'}>{cat.portability}</Badge>\n )}\n {cat.sensitive === true && <Badge kind=\"warn\">secret</Badge>}\n </span>\n }\n />\n ))}\n </div>\n </Card>\n )\n })}\n </div>\n )}\n\n {/* 设备相关分区警告 */}\n {customWarnings.length > 0 && (\n <Banner kind=\"warn\">\n {t('export.selectionWarnings')}\n <ul className={css.warnList}>\n {customWarnings.map((w, i) => <li key={i}>{w}</li>)}\n </ul>\n </Banner>\n )}\n\n {/* 加密备份选项 */}\n <Card className={css.optionsCard}>\n <Checkbox\n checked={includeSecrets}\n onChange={setIncludeSecrets}\n label={<span className={css.categoryName}>{t('export.includeSecrets')}</span>}\n />\n <div className={css.hint}>{t('export.includeSecretsHint')}</div>\n {includeSecrets && (\n <div className={css.secretFields}>\n <label className={css.field}>\n <span className={css.fieldLabel}>{t('export.password')}</span>\n <input type=\"password\" className={css.input} value={password} onChange={(e: ChangeEvent<HTMLInputElement>) => { setPassword(e.target.value) }} />\n </label>\n <label className={css.field}>\n <span className={css.fieldLabel}>{t('export.passwordConfirm')}</span>\n <input type=\"password\" className={css.input} value={passwordConfirm} onChange={(e: ChangeEvent<HTMLInputElement>) => { setPasswordConfirm(e.target.value) }} />\n </label>\n {password !== '' && password !== passwordConfirm && (\n <span className={css.formError}>{t('export.passwordMismatch')}</span>\n )}\n {password === '' && includeSecrets && (\n <span className={css.formError}>{t('export.passwordRequired')}</span>\n )}\n </div>\n )}\n </Card>\n\n {/* 执行 */}\n <div className={css.actionRow}>\n <Button variant=\"primary\" disabled={running || passwordInvalid} onClick={() => { void runExport() }}>\n {running ? <Spinner label={t('export.running')} /> : t('export.run')}\n </Button>\n </div>\n\n {running && <ProgressBar event={progress} active />}\n\n {error !== null && (\n <ErrorBanner error={error} onRetry={() => { void runExport() }} retrying={running} />\n )}\n\n {result !== null && !running && (\n <>\n <ReportView kind=\"export\" exportReport={result.report} onDownload={() => { void download() }} />\n {downloaded && <Banner kind=\"ok\">Saved: {result.report.file.name}</Banner>}\n </>\n )}\n </div>\n )\n}\n","/**\n * Import 向导状态机(规范 §9/§10/§28,m6-ui)。\n *\n * 步骤:Select ZIP → Analyzing → Compatibility → Import Preview → Resolve Conflicts\n * → Path Mapping → Secrets → Importing → Result。\n *\n * 关键安全/正确性约束:\n * - analyzeImport / createImportPlan 零写入(Dry Run 复用,规范 §10);\n * - executeImportPlan 必须 confirm=true(core 安全阀),UI 在用户点「确认导入」后传入;\n * - **显式传 rollbackOnError**:场景 E(§36)要求导入中途失败整体回滚,\n * 本向导默认 rollbackOnError=true,UI 可在执行前让用户选择(true=整体回滚 / false=单项失败继续 §34.17);\n * - 秘密补录值仅内存(secretInputs),绝不落日志/落盘。\n */\nimport type {\n GlobalConflictStrategy, ImportAnalysis, ImportDecisions, ImportPlan, ImportResult,\n PathMapping, PlanItem,\n} from '../core/types.ts';\nimport type { ImportPort, ImportPreviewSummary, ImportStep, ProgressListener, WizardSnapshot } from './types.ts';\nimport { IMPORT_STAGES, ProgressTracker } from './progress.ts';\nimport { formatActionableError, toActionableError } from './errors.ts';\n\nexport interface ImportWizardOptions {\n port: ImportPort;\n onProgress?: ProgressListener;\n /** 默认回滚策略(场景 E:true=整体回滚;UI 可在执行前覆盖) */\n defaultRollbackOnError?: boolean;\n}\n\nexport class ImportWizard {\n private readonly port: ImportPort;\n private readonly onProgress: ProgressListener | undefined;\n private readonly tracker: ProgressTracker;\n private step: ImportStep = 'select';\n private zipPath: string | null = null;\n private analysis: ImportAnalysis | null = null;\n private plan: ImportPlan | null = null;\n private result: ImportResult | null = null;\n private rollbackOnError: boolean;\n private errors: string[] = [];\n private decisions: ImportDecisions = {\n strategy: 'merge',\n resolutions: {},\n pathMappings: [],\n };\n private secretInputs: Record<string, string> = {};\n\n constructor(opts: ImportWizardOptions) {\n this.port = opts.port;\n this.onProgress = opts.onProgress;\n this.tracker = new ProgressTracker(IMPORT_STAGES, this.onProgress);\n this.rollbackOnError = opts.defaultRollbackOnError ?? true;\n }\n\n /** 当前状态快照(React 绑定 / 测试断言用) */\n snapshot(): WizardSnapshot {\n return {\n step: this.step,\n zipPath: this.zipPath,\n analysis: this.analysis,\n plan: this.plan,\n result: this.result,\n rollbackOnError: this.rollbackOnError,\n errors: [...this.errors],\n };\n }\n\n get currentStep(): ImportStep {\n return this.step;\n }\n\n /** 步骤 1-2:选 ZIP → Analyzing → Compatibility(analyzeImport 零写入) */\n async selectZip(path: string): Promise<ImportAnalysis> {\n this.zipPath = path;\n this.step = 'analyzing';\n this.tracker.emit('validating');\n this.errors = [];\n try {\n this.analysis = await this.port.analyzeImport(path);\n this.tracker.emit('checking-compatibility');\n if (!this.analysis.valid) {\n // 分析失败(完整性/schema/兼容性):错误进 errors,UI 停在失败态\n this.errors.push(...this.analysis.errors.map((e) => formatActionableError(toActionableError(new Error(e)))));\n throw new Error(this.analysis.errors.join('; ') || '备份分析失败');\n }\n this.step = 'compatibility';\n return this.analysis;\n } catch (err) {\n // 仅当尚未记录分析错误时才追加(避免重复)\n if (this.errors.length === 0) {\n this.errors.push(formatActionableError(toActionableError(err)));\n }\n throw err;\n }\n }\n\n /** 步骤 3→4:用户确认兼容性后进入 Preview(Dry Run:用当前决策生成计划摘要,零写入) */\n async confirmCompatibility(): Promise<ImportPlan> {\n if (this.analysis === null || this.zipPath === null) {\n throw new Error('尚未完成分析,请先选择备份文件');\n }\n this.plan = await this.port.createImportPlan(this.zipPath, this.decisions);\n this.step = 'preview';\n return this.plan;\n }\n\n /** 更新全局冲突策略(merge/replace/skipExisting,规范 §11) */\n setStrategy(strategy: GlobalConflictStrategy): void {\n this.decisions = { ...this.decisions, strategy };\n }\n\n /** 设置逐项冲突决策(keepCurrent/useImported/review) */\n setResolutions(resolutions: Record<string, 'keepCurrent' | 'useImported' | 'review'>): void {\n this.decisions = { ...this.decisions, resolutions };\n }\n\n /** 设置路径映射(§12) */\n setPathMappings(mappings: PathMapping[]): void {\n this.decisions = { ...this.decisions, pathMappings: mappings };\n }\n\n /** 设置秘密补录值(仅内存,绝不持久化) */\n setSecretInputs(inputs: Record<string, string>): void {\n this.secretInputs = inputs;\n }\n\n /** Preview 摘要(规范 §10 数值化;基于当前 plan 与 analysis) */\n previewSummary(): ImportPreviewSummary {\n const items = this.plan?.items ?? [];\n const analysis = this.analysis;\n const count = (kinds: PlanItem['kind'][]): number =>\n items.filter((i) => kinds.includes(i.kind)).length;\n return {\n willChange: count(['Create', 'Update', 'Install', 'Conflict']),\n unchanged: count(['Skip']),\n settingsUpdates: count(['Create', 'Update']),\n pluginsInstalled: analysis?.pluginSummary.installed ?? 0,\n pluginsToInstall: count(['Install']),\n mcpAdds: items.filter((i) => i.adapter === 'mcp' && i.kind === 'Create').length,\n prompts: items.filter((i) => i.adapter === 'prompts' && i.kind !== 'Skip').length,\n pathMappingsNeeded: analysis?.pathIssues.length ?? 0,\n secretsNeeded: this.plan?.missingSecrets.length ?? analysis?.secretCount ?? 0,\n conflicts: count(['Conflict']),\n needsRestart: this.plan?.needsRestart ?? false,\n };\n }\n\n /** 冲突项(供 ConflictCollector 使用) */\n conflictItems(): PlanItem[] {\n return (this.plan?.items ?? []).filter((i) => i.kind === 'Conflict');\n }\n\n /** 设置回滚策略(场景 E 选择;执行前调用) */\n setRollbackOnError(enable: boolean): void {\n this.rollbackOnError = enable;\n }\n\n /**\n * 步骤 10-14:确认导入 → 快照 → 执行 → 校验 → 结果。\n * 用最终决策重建计划(与预览一致),显式传 rollbackOnError。\n */\n async execute(opts: { confirm: boolean; rollbackOnError?: boolean }): Promise<ImportResult> {\n if (this.zipPath === null || this.analysis === null) {\n throw new Error('尚未完成分析,请先选择备份文件');\n }\n if (opts.confirm !== true) {\n throw new Error('导入未确认:必须确认后才允许修改任何数据');\n }\n const rollbackOnError = opts.rollbackOnError ?? this.rollbackOnError;\n this.step = 'importing';\n this.tracker.emit('creating-snapshot');\n\n try {\n // 用最终决策重建计划(与预览逻辑一致,保证 Dry Run 与真实导入一致)\n this.plan = await this.port.createImportPlan(this.zipPath, this.decisions);\n this.tracker.emit('restoring-settings');\n this.tracker.emit('restoring-plugins');\n this.tracker.emit('restoring-mcp');\n this.tracker.emit('validating-config');\n this.result = await this.port.executeImportPlan(this.zipPath, this.plan, {\n confirm: true,\n secretInputs: this.secretInputs,\n rollbackOnError,\n });\n // 失败且已整体回滚(场景 E)→ 报告回滚阶段\n if (!this.result.ok && this.result.rollback) {\n this.tracker.emit('rolling-back');\n }\n this.tracker.emit('done');\n this.step = 'result';\n return this.result;\n } catch (err) {\n this.errors.push(formatActionableError(toActionableError(err)));\n throw err;\n }\n }\n\n /** 重置向导(可复用实例开始新导入) */\n reset(): void {\n this.step = 'select';\n this.zipPath = null;\n this.analysis = null;\n this.plan = null;\n this.result = null;\n this.errors = [];\n this.decisions = { strategy: 'merge', resolutions: {}, pathMappings: [] };\n this.secretInputs = {};\n }\n}\n","/**\n * 冲突决策收集(规范 §11,m6-ui)。\n *\n * 输入:ImportPlan.items 中的 Conflict 项(目标存在且不同)。\n * 输出:逐项决策 Keep Current / Use Imported / Review,转为 core ImportDecisions.resolutions。\n *\n * 纯逻辑:只收集用户选择,不触碰 core;未决(review/未选)项在预览时如实展示。\n */\nimport type { ImportPlan, ItemResolution, PlanItem } from '../core/types.ts';\nimport type { ConflictViewItem } from './types.ts';\n\nexport class ConflictCollector {\n private readonly plan: ImportPlan;\n private readonly decisions = new Map<string, ItemResolution>();\n\n constructor(plan: ImportPlan) {\n this.plan = plan;\n }\n\n /** 需要用户决策的冲突项(kind === 'Conflict') */\n get conflicts(): PlanItem[] {\n return this.plan.items.filter((i) => i.kind === 'Conflict');\n }\n\n /** 设置某项决策;未出现在冲突列表中的 id 忽略并返回 false */\n resolve(itemId: string, resolution: ItemResolution): boolean {\n if (!this.conflicts.some((i) => i.id === itemId)) return false;\n this.decisions.set(itemId, resolution);\n return true;\n }\n\n /** 单项当前决策(未决策返回 null) */\n decisionOf(itemId: string): ItemResolution | null {\n return this.decisions.get(itemId) ?? null;\n }\n\n /** 仍未解决(review 或未决策)的冲突项 */\n unresolved(): PlanItem[] {\n return this.conflicts.filter((i) => {\n const d = this.decisions.get(i.id);\n return d === undefined || d === 'review';\n });\n }\n\n get hasUnresolved(): boolean {\n return this.unresolved().length > 0;\n }\n\n /** 转 core 决策表(供 createImportPlan / executeImportPlan 使用) */\n toResolutions(): Record<string, ItemResolution> {\n const out: Record<string, ItemResolution> = {};\n for (const [id, res] of this.decisions) out[id] = res;\n return out;\n }\n\n /** 构造视图项列表(React 绑定用):含当前/导入摘要占位 */\n viewItems(): ConflictViewItem[] {\n return this.conflicts.map((item) => ({\n item,\n currentSummary: item.detail?.split('\\n')[0],\n importedSummary: undefined,\n resolution: this.decisionOf(item.id),\n }));\n }\n}\n","/**\n * 冲突决策列表(规范 §11,绑 src/ui/conflict-view.ts 的 ConflictCollector)。\n *\n * 渲染 plan 中 kind === 'Conflict' 的项,用户逐项选择\n * Keep Current / Use Imported / Review;决策实时写入 collector,\n * 完成时父组件调用 collector.toResolutions() → wizard.setResolutions()。\n */\nimport { useState } from 'react'\nimport { ConflictCollector } from '../../ui/conflict-view.ts'\nimport type { ItemResolution } from '../../core/types.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport { Banner } from '../common/ui.tsx'\nimport css from '../config-manager.module.css'\n\nexport interface ConflictListProps {\n collector: ConflictCollector\n t: TranslateNS<'config-manager'>\n /** 任意决策变化后通知父组件刷新(tick) */\n onChanged: () => void\n}\n\nconst RESOLUTION_OPTIONS: { value: ItemResolution; key: string }[] = [\n { value: 'keepCurrent', key: 'import.conflicts.keepCurrent' },\n { value: 'useImported', key: 'import.conflicts.useImported' },\n { value: 'review', key: 'import.conflicts.review' },\n]\n\n/** 冲突项决策列表 */\nexport function ConflictList({ collector, t, onChanged }: ConflictListProps) {\n const [tick, setTick] = useState(0)\n const items = collector.viewItems()\n const unresolved = collector.unresolved().length\n\n return (\n <div className={css.conflictList}>\n {unresolved > 0 && <Banner kind=\"warn\">{t('import.conflicts.unresolved', { count: String(unresolved) })}</Banner>}\n {items.map((view) => {\n const item = view.item\n return (\n <div key={item.id} className={css.conflictItem}>\n <div className={css.conflictHead}>\n <span className={css.conflictId}>{item.adapter}: {item.description}</span>\n {item.severity === 'error' && <span className={css.severityError}>error</span>}\n </div>\n {item.detail !== undefined && item.detail !== '' && (\n <pre className={css.conflictDetail}>{item.detail}</pre>\n )}\n <div className={css.conflictOptions}>\n {RESOLUTION_OPTIONS.map((opt) => (\n <label key={opt.value} className={css.radioLabel}>\n <input\n type=\"radio\"\n name={`conflict-${item.id}`}\n checked={view.resolution === opt.value}\n onChange={() => {\n collector.resolve(item.id, opt.value)\n setTick((v) => v + 1)\n onChanged()\n }}\n />\n {t(opt.key as 'import.conflicts.keepCurrent' | 'import.conflicts.useImported' | 'import.conflicts.review')}\n </label>\n ))}\n </div>\n </div>\n )\n })}\n {items.length === 0 && <div className={css.empty}>No conflicts</div>}\n {void tick}\n </div>\n )\n}\n","/**\n * 路径映射表单(规范 §12,绑 src/ui/types.ts 的 PathMappingDraft 形状)。\n *\n * 注意:src/ui/path-mapping.ts 的 PathMappingEditor 依赖 utils/paths.ts 的\n * applyPrefixMappings(node:path)——浏览器 bundle 不可用,故此处做轻量等价实现:\n * 输入输出形状与 core 的 PathMapping 完全一致(oldPrefix/newPrefix/appliesTo),\n * 实际前缀替换由 Host 侧 core 在 createImportPlan 阶段执行,本组件只负责收集用户输入。\n */\nimport { useMemo, useState } from 'react'\nimport type { ChangeEvent } from 'react'\nimport type { PathIssue, PathMapping } from '../../core/types.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport { Banner } from '../common/ui.tsx'\nimport css from '../config-manager.module.css'\n\nexport interface PathMappingFormProps {\n /** 分析结果中的路径问题(每条生成一行映射输入) */\n issues: PathIssue[]\n /** 预置映射(如复用上次导入的映射) */\n initial?: PathMapping[]\n t: TranslateNS<'config-manager'>\n /** 映射变化时上报(仅已填写 newPrefix 的条目进入 core) */\n onChange: (mappings: PathMapping[]) => void\n}\n\n/**\n * 路径映射表单:每条 PathIssue 一行(原路径 → 新路径输入框),\n * 留空 = 该路径不映射(unresolved);填写 = 输出 core PathMapping[]。\n */\nexport function PathMappingForm({ issues, initial, t, onChange }: PathMappingFormProps) {\n // draft 状态:issue.value(oldPrefix)→ newPrefix;预置映射合并进 initial 状态\n const [drafts, setDrafts] = useState<Record<string, string>>(() => {\n const out: Record<string, string> = {}\n for (const m of initial ?? []) out[m.oldPrefix] = m.newPrefix\n return out\n })\n\n const setNewPrefix = (oldPrefix: string, value: string): void => {\n const next = { ...drafts, [oldPrefix]: value }\n setDrafts(next)\n const mappings: PathMapping[] = Object.entries(next)\n .filter(([, v]) => v !== '')\n .map(([oldPrefix, newPrefix]) => ({ oldPrefix, newPrefix, appliesTo: [] }))\n onChange(mappings)\n }\n\n const unresolved = useMemo(() => {\n return issues.filter((issue) => (drafts[issue.value] ?? '') === '')\n }, [issues, drafts])\n\n return (\n <div className={css.pathMappingList}>\n {unresolved.length > 0 && (\n <Banner kind=\"warn\">{t('import.paths.unresolved', { count: String(unresolved.length) })}</Banner>\n )}\n {issues.length === 0 && <div className={css.empty}>No paths to map</div>}\n {issues.map((issue) => (\n <div key={issue.value} className={css.pathRow}>\n <div className={css.pathOld}>\n <span className={css.fieldLabel}>{t('import.paths.old')}</span>\n <pre className={css.pathValue}>{issue.value}</pre>\n <span className={css.pathIssueKind}>{issue.kind}</span>\n </div>\n <div className={css.pathNew}>\n <span className={css.fieldLabel}>{t('import.paths.new')}</span>\n <input\n className={css.input}\n value={drafts[issue.value] ?? ''}\n placeholder={issue.mappedTo ?? ''}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { setNewPrefix(issue.value, e.target.value) }}\n />\n </div>\n </div>\n ))}\n </div>\n )\n}\n","/**\n * 导入九步向导(规范 §9 / §10 / §28,绑 src/ui/import-wizard.ts 的 ImportWizard 控制器)。\n *\n * 步骤(对齐 ui/types.ts 的 ImportStep):\n * Select ZIP → Analyzing → Compatibility → Preview\n * → Resolve Conflicts(若有)→ Path Mapping(若有)→ Secrets 补录(若有)\n * → Confirm → Importing → Result\n *\n * 安全/正确性约束(来自 ImportWizard 与 core):\n * - analyzeImport / createImportPlan 零写入(Dry Run 复用);\n * - executeImportPlan 必须 confirm=true(core 安全阀);\n * - 秘密补录值仅内存(secretInputs),经 HTTPS 请求体传给 Host,绝不落日志/落盘;\n * - 默认整体回滚(rollbackOnError=true),用户在 Confirm 步可切换。\n *\n * 数据流:本地文件 → api.upload → zipPath → wizard.selectZip/confirmCompatibility/\n * setResolutions/setPathMappings/setSecretInputs → wizard.execute。\n * 中间阶段(conflicts/path-mapping/secrets)是 UI 层流程页,wizard 的 decisions 由\n * 对应组件收集后写入。\n */\nimport { useRef, useState } from 'react'\nimport type { ChangeEvent } from 'react'\nimport { ImportWizard } from '../../ui/import-wizard.ts'\nimport { ConflictCollector } from '../../ui/conflict-view.ts'\nimport type { ImportPreviewSummary, ProgressEvent, WizardSnapshot } from '../../ui/types.ts'\nimport type { PathMapping } from '../../core/types.ts'\nimport type { ConfigManagerApi, UploadResponse } from '../api.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport { Badge, Banner, Button, Card, Checkbox, Empty, SectionTitle, Spinner } from '../common/ui.tsx'\nimport { ErrorBanner, ErrorList } from '../common/ErrorBanner.tsx'\nimport { ProgressBar } from '../common/ProgressBar.tsx'\nimport { ReportView } from '../common/ReportView.tsx'\nimport { ConflictList } from './ConflictList.tsx'\nimport { PathMappingForm } from './PathMappingForm.tsx'\nimport css from '../config-manager.module.css'\n\nexport interface ImportWizardViewProps {\n api: ConfigManagerApi\n t: TranslateNS<'config-manager'>\n}\n\n/** 中间流程阶段(wizard.step 之外的 UI 层页面) */\ntype FlowPhase = 'preview' | 'conflicts' | 'path-mapping' | 'secrets' | 'confirm'\n\nconst SCORE_LABEL: Record<string, string> = {\n excellent: 'Excellent',\n good: 'Good',\n partial: 'Partial',\n unsupported: 'Unsupported',\n}\n\n/** 密钥补录表单(仅内存收集,值不外泄) */\nfunction SecretsForm({\n missing,\n t,\n onChange,\n}: {\n missing: { ref: string; required: boolean }[]\n t: TranslateNS<'config-manager'>\n onChange: (inputs: Record<string, string>) => void\n}) {\n const [inputs, setInputs] = useState<Record<string, string>>({})\n const setRef = (ref: string, value: string): void => {\n const next = { ...inputs, [ref]: value }\n setInputs(next)\n onChange(next)\n }\n return (\n <div className={css.secretsList}>\n <div className={css.hint}>{t('import.secrets.hint')}</div>\n {missing.length === 0 && <Empty>No secrets required</Empty>}\n {missing.map((s) => (\n <label key={s.ref} className={css.field}>\n <span className={css.fieldLabel}>\n {s.ref} {s.required ? t('import.secrets.required') : t('import.secrets.optional')}\n </span>\n <input\n type=\"password\"\n className={css.input}\n autoComplete=\"off\"\n value={inputs[s.ref] ?? ''}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { setRef(s.ref, e.target.value) }}\n />\n </label>\n ))}\n </div>\n )\n}\n\n/**\n * 导入向导主视图。\n */\nexport function ImportWizardView({ api, t }: ImportWizardViewProps) {\n // ImportWizard 控制器(port=api,onProgress 桥到 React state)\n const [wizard] = useState(() => new ImportWizard({\n port: api,\n onProgress: (event) => { setProgress(event) },\n defaultRollbackOnError: true,\n }))\n const [, setTick] = useState(0)\n const refresh = (): void => { setTick((v) => v + 1) }\n\n const [progress, setProgress] = useState<ProgressEvent | null>(null)\n const [error, setError] = useState<unknown>(null)\n const [phase, setPhase] = useState<FlowPhase>('preview')\n const [uploading, setUploading] = useState(false)\n const [rollbackOnError, setRollbackOnError] = useState(true)\n const [conflictCollector, setConflictCollector] = useState<ConflictCollector | null>(null)\n const [pathMappings, setPathMappings] = useState<PathMapping[]>([])\n const [secretInputs, setSecretInputs] = useState<Record<string, string>>({})\n const fileInput = useRef<HTMLInputElement | null>(null)\n\n const snapshot: WizardSnapshot = wizard.snapshot()\n const step = snapshot.step\n\n /* ---------- 阶段判定 ---------- */\n\n const hasConflicts = (snapshot.plan?.items ?? []).some((i) => i.kind === 'Conflict')\n const hasPathIssues = (snapshot.analysis?.pathIssues.length ?? 0) > 0\n const hasSecrets = (snapshot.plan?.missingSecrets.length ?? 0) > 0\n\n /** 从某阶段完成后进入的下一个阶段(跳过空阶段;from 之前的阶段不再进入) */\n const nextPhase = (from: FlowPhase): FlowPhase => {\n if (from !== 'conflicts' && hasConflicts) return 'conflicts'\n if (from !== 'path-mapping' && hasPathIssues) return 'path-mapping'\n if (from !== 'secrets' && hasSecrets) return 'secrets'\n return 'confirm'\n }\n\n /* ---------- 动作 ---------- */\n\n /** 选择并上传 ZIP → wizard.selectZip(analyzing → compatibility) */\n const onPickFile = async (file: File | undefined): Promise<void> => {\n if (file === undefined) return\n setUploading(true)\n setError(null)\n try {\n const uploaded: UploadResponse = await api.upload(file)\n const analysis = await wizard.selectZip(uploaded.zipPath)\n void analysis\n refresh()\n } catch (err) {\n setError(err)\n refresh()\n } finally {\n setUploading(false)\n }\n }\n\n /** Compatibility → Preview */\n const goPreview = async (): Promise<void> => {\n setError(null)\n try {\n await wizard.confirmCompatibility()\n refresh()\n } catch (err) {\n setError(err)\n refresh()\n }\n }\n\n /** 进入 conflicts 阶段(先创建 collector) */\n const enterConflicts = (): void => {\n const plan = snapshot.plan\n if (plan !== null && conflictCollector === null) {\n setConflictCollector(new ConflictCollector(plan))\n }\n setPhase('conflicts')\n }\n\n /** Conflicts 完成:写入决策 → 下一阶段 */\n const finishConflicts = (): void => {\n if (conflictCollector !== null) wizard.setResolutions(conflictCollector.toResolutions())\n setPhase(nextPhase('conflicts'))\n }\n\n /** Path Mapping 完成:写入映射 → 下一阶段 */\n const finishPathMapping = (): void => {\n wizard.setPathMappings(pathMappings)\n setPhase(nextPhase('path-mapping'))\n }\n\n /** Secrets 完成:写入补录值 → Confirm */\n const finishSecrets = (): void => {\n wizard.setSecretInputs(secretInputs)\n setPhase('confirm')\n }\n\n /** Confirm 执行:confirm=true(安全阀)+ 用户回滚策略 */\n const execute = async (): Promise<void> => {\n setError(null)\n try {\n await wizard.execute({ confirm: true, rollbackOnError })\n refresh()\n } catch (err) {\n setError(err)\n refresh()\n }\n }\n\n /** 重置向导(重新导入) */\n const resetWizard = (): void => {\n wizard.reset()\n setError(null)\n setPhase('preview')\n setConflictCollector(null)\n setPathMappings([])\n setSecretInputs({})\n refresh()\n }\n\n /* ---------- 各步骤渲染 ---------- */\n\n if (step === 'select') {\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('import.select.title')} subtitle={t('import.select.hint')} />\n <input\n ref={fileInput}\n type=\"file\"\n accept=\".zip,application/zip\"\n className={css.hiddenFile}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { void onPickFile(e.target.files?.[0]) }}\n />\n <div className={css.actionRow}>\n <Button variant=\"primary\" disabled={uploading} onClick={() => { fileInput.current?.click() }}>\n {uploading ? <Spinner label={t('import.analyzing')} /> : t('import.select.browse')}\n </Button>\n </div>\n {error !== null && <ErrorBanner error={error} onRetry={resetWizard} />}\n </div>\n )\n }\n\n if (step === 'analyzing') {\n return (\n <div className={css.viewBody}>\n <ProgressBar event={progress} active />\n {error !== null && <ErrorBanner error={error} onRetry={resetWizard} />}\n <ErrorList errors={snapshot.errors} />\n </div>\n )\n }\n\n if (step === 'compatibility') {\n const analysis = snapshot.analysis\n if (analysis === null) return null\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('import.compatibility.title')} />\n <div className={css.statRow}>\n <Badge kind={analysis.compatibility === 'unsupported' ? 'error' : analysis.compatibility === 'partial' ? 'warn' : 'ok'}>\n {t('import.compatibility.score', { score: SCORE_LABEL[analysis.compatibility] ?? analysis.compatibility })}\n </Badge>\n <Badge kind=\"info\">{analysis.sectionsInZip.length} sections</Badge>\n <Badge kind=\"info\">plugins: {analysis.pluginSummary.installed}✓ / {analysis.pluginSummary.toInstall}✗</Badge>\n {analysis.pathIssues.length > 0 && <Badge kind=\"warn\">{analysis.pathIssues.length} paths</Badge>}\n {analysis.secretCount > 0 && <Badge kind=\"warn\">{analysis.secretCount} secrets</Badge>}\n </div>\n {analysis.warnings.length > 0 && (\n <Banner kind=\"warn\">\n {analysis.warnings.map((w, i) => <div key={i}>{w}</div>)}\n </Banner>\n )}\n {error !== null && <ErrorBanner error={error} onRetry={() => { void goPreview() }} />}\n <div className={css.actionRow}>\n <Button variant=\"primary\" onClick={() => { void goPreview() }}>{t('common.next')}</Button>\n </div>\n </div>\n )\n }\n\n if (step === 'preview' && phase === 'preview') {\n const summary: ImportPreviewSummary = wizard.previewSummary()\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('import.preview.title')} />\n <div className={css.statRow}>\n <Badge kind={summary.willChange > 0 ? 'info' : 'ok'}>{t('import.preview.willChange', { count: String(summary.willChange) })}</Badge>\n {summary.unchanged > 0 && <Badge kind=\"ok\">{t('import.preview.unchanged', { count: String(summary.unchanged) })}</Badge>}\n {summary.settingsUpdates > 0 && <Badge kind=\"info\">{t('import.preview.settings', { count: String(summary.settingsUpdates) })}</Badge>}\n {summary.pluginsToInstall > 0 && <Badge kind=\"info\">{t('import.preview.plugins', { count: String(summary.pluginsToInstall) })}</Badge>}\n {summary.mcpAdds > 0 && <Badge kind=\"info\">{t('import.preview.mcp', { count: String(summary.mcpAdds) })}</Badge>}\n {summary.pathMappingsNeeded > 0 && <Badge kind=\"warn\">{t('import.preview.paths', { count: String(summary.pathMappingsNeeded) })}</Badge>}\n {summary.secretsNeeded > 0 && <Badge kind=\"warn\">{t('import.preview.secrets', { count: String(summary.secretsNeeded) })}</Badge>}\n {summary.conflicts > 0 && <Badge kind=\"error\">{t('import.preview.conflicts', { count: String(summary.conflicts) })}</Badge>}\n </div>\n {summary.needsRestart && <Banner kind=\"warn\">{t('import.preview.restart')}</Banner>}\n {error !== null && <ErrorBanner error={error} onRetry={() => { void goPreview() }} />}\n <div className={css.actionRow}>\n <Button\n variant=\"primary\"\n onClick={() => {\n const next = nextPhase('preview')\n setPhase(next)\n if (next === 'conflicts') enterConflicts()\n }}\n >\n {t('common.next')}\n </Button>\n </div>\n </div>\n )\n }\n\n if (phase === 'conflicts') {\n if (conflictCollector === null || snapshot.plan === null) return null\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('import.conflicts.title')} subtitle={t('import.conflicts.hint')} />\n <ConflictList collector={conflictCollector} t={t} onChanged={refresh} />\n <div className={css.actionRow}>\n <Button variant=\"ghost\" onClick={() => { setPhase('preview') }}>{t('common.back')}</Button>\n <Button variant=\"primary\" disabled={conflictCollector.hasUnresolved} onClick={finishConflicts}>\n {t('common.next')}\n </Button>\n </div>\n </div>\n )\n }\n\n if (phase === 'path-mapping') {\n const issues = snapshot.analysis?.pathIssues ?? []\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('import.paths.title')} subtitle={t('import.paths.hint')} />\n <PathMappingForm issues={issues} initial={pathMappings} t={t} onChange={setPathMappings} />\n <div className={css.actionRow}>\n <Button variant=\"ghost\" onClick={() => { setPhase('preview') }}>{t('common.back')}</Button>\n <Button variant=\"primary\" onClick={finishPathMapping}>{t('common.next')}</Button>\n </div>\n </div>\n )\n }\n\n if (phase === 'secrets') {\n const missing = snapshot.plan?.missingSecrets ?? []\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('import.secrets.title')} />\n <SecretsForm missing={missing} t={t} onChange={setSecretInputs} />\n <div className={css.actionRow}>\n <Button variant=\"ghost\" onClick={() => { setPhase('preview') }}>{t('common.back')}</Button>\n <Button variant=\"primary\" onClick={finishSecrets}>{t('common.next')}</Button>\n </div>\n </div>\n )\n }\n\n if (phase === 'confirm') {\n return (\n <div className={css.viewBody}>\n <Card className={css.optionsCard}>\n <Banner kind=\"info\">{t('import.confirm.warning')}</Banner>\n <Checkbox\n checked={rollbackOnError}\n onChange={setRollbackOnError}\n label={t('import.rollbackOnError')}\n />\n <div className={css.actionRow}>\n <Button variant=\"ghost\" onClick={() => { setPhase('preview') }}>{t('common.back')}</Button>\n <Button variant=\"primary\" onClick={() => { void execute() }}>\n {t('import.confirm.execute')}\n </Button>\n </div>\n </Card>\n {error !== null && <ErrorBanner error={error} onRetry={() => { void execute() }} />}\n </div>\n )\n }\n\n if (step === 'importing') {\n return (\n <div className={css.viewBody}>\n <ProgressBar event={progress} active />\n <div className={css.hint}>{t('import.importing')}</div>\n {error !== null && <ErrorBanner error={error} />}\n <ErrorList errors={snapshot.errors} />\n </div>\n )\n }\n\n if (step === 'result') {\n const result = snapshot.result\n if (result === null) return null\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('report.import.title')} />\n <ReportView\n kind=\"import\"\n importResult={result}\n onAction={(action) => {\n if (action === 'done') resetWizard()\n // fixIssues / viewDetails:报告已展示全部失败项与详情,无需额外页面\n }}\n />\n {result.needsRestart && <Banner kind=\"warn\">{t('report.needsRestart')}</Banner>}\n {error !== null && <ErrorBanner error={error} />}\n <div className={css.actionRow}>\n <Button variant=\"ghost\" onClick={resetWizard}>{t('common.done')}</Button>\n </div>\n </div>\n )\n }\n\n return null\n}\n","/**\n * Config Manager 设置页(settings.section 入口的主页面容器)。\n *\n * owner props 由 settings shell 传入(close);业务面(api)由注册时的\n * inject face 注入;t 由 locale seat 注入。内部两个主视图:\n * Export(Quick/Custom)与 Import(九步向导)。\n */\nimport { useState } from 'react'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ConfigManagerSectionInjected, TranslateNS } from './client-types.ts'\nimport { ExportView } from './export/ExportView.tsx'\nimport { ImportWizardView } from './import/ImportWizardView.tsx'\nimport css from './config-manager.module.css'\n\nexport type ConfigManagerSectionProps =\n & PropsRuntime<'settings.section'>\n & ConfigManagerSectionInjected\n & { t: TranslateNS<'config-manager'> }\n\ntype MainView = 'export' | 'import'\n\n/**\n * 设置页容器:Export / Import 双视图切换。\n */\nexport function ConfigManagerSection({ close, api, t }: ConfigManagerSectionProps) {\n const [view, setView] = useState<MainView>('export')\n\n return (\n <div className={css.section}>\n <div className={css.sectionHeader}>\n <div className={css.viewTabs} role=\"tablist\">\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={view === 'export'}\n data-active={view === 'export' ? '' : undefined}\n className={css.viewTab}\n onClick={() => { setView('export') }}\n >\n {t('view.export')}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={view === 'import'}\n data-active={view === 'import' ? '' : undefined}\n className={css.viewTab}\n onClick={() => { setView('import') }}\n >\n {t('view.import')}\n </button>\n </div>\n <button type=\"button\" className={css.iconButton} title={t('common.close')} aria-label={t('common.close')} onClick={close}>×</button>\n </div>\n <div className={css.sectionBody}>\n {view === 'export' ? <ExportView api={api} t={t} /> : <ImportWizardView api={api} t={t} />}\n </div>\n </div>\n )\n}\n","/**\n * Config Manager 表面文案:zh 为源语言,en 镜像每个键。\n * 字典 namespace 由 client/index.ts 注册(declare module 合并进 LocaleNamespaceMap)。\n * 键集合通过 `ConfigManagerKey` 类型在注册处做编译期校验(缺键/多键即编译错误)。\n */\n\nexport const zh = {\n // 入口\n 'section.label': '备份与迁移',\n 'section.description': '导出 / 导入 / 迁移 DSH 配置(备份不含密钥,加密备份可选)',\n // 视图切换\n 'view.export': '导出备份',\n 'view.import': '导入恢复',\n // 公共\n 'common.close': '关闭',\n 'common.cancel': '取消',\n 'common.back': '上一步',\n 'common.next': '下一步',\n 'common.done': '完成',\n 'common.retry': '重试',\n 'common.confirm': '确认',\n 'common.loading': '加载中…',\n 'common.unknownError': '未知错误',\n // 状态横幅\n 'status.ready': 'Config Manager 已就绪(插件 {version} · DSH {dsh} · {platform})',\n 'status.unavailable': 'Config Manager 服务未就绪,请确认插件已正确挂载。',\n // —— 导出 ——\n 'export.mode.quick': '快速导出',\n 'export.mode.quickHint': '一键导出推荐分区(可迁移、不含设备专属数据),适合常规备份。',\n 'export.mode.custom': '自定义导出',\n 'export.mode.customHint': '按分组逐项勾选要导出的分区。',\n 'export.includeSecrets': '包含真实密钥(加密备份)',\n 'export.includeSecretsHint': '勾选后导出将包含密钥,并以密码加密(AES-256-GCM)。密码仅用于本次加密,不会写入备份或任何配置文件。',\n 'export.password': '备份加密密码',\n 'export.passwordConfirm': '确认密码',\n 'export.passwordMismatch': '两次输入的密码不一致',\n 'export.passwordRequired': '包含密钥时必须设置加密密码',\n 'export.run': '开始导出',\n 'export.running': '正在导出…',\n 'export.download': '下载备份文件',\n 'export.selectionWarnings': '以下分区为设备相关数据,跨设备导入时可能不适用:',\n 'export.group.unknown': '其他',\n 'export.included': '已包含',\n 'export.excluded': '未包含',\n // —— 导入 ——\n 'import.select.title': '选择备份文件',\n 'import.select.hint': '选择本机导出的 dsh-config-*.zip 备份文件开始导入。分析阶段只读,不会修改任何配置。',\n 'import.select.browse': '选择 ZIP 文件',\n 'import.select.file': '已选择:{name}',\n 'import.analyzing': '正在分析备份…',\n 'import.compatibility.title': '兼容性',\n 'import.compatibility.score': '兼容性评分:{score}',\n 'import.compatibility.ok': '备份可导入',\n 'import.compatibility.fail': '备份分析失败:{reason}',\n 'import.preview.title': '导入预览',\n 'import.preview.willChange': '将变更 {count} 项',\n 'import.preview.unchanged': '已一致跳过 {count} 项',\n 'import.preview.settings': '设置更新 {count}',\n 'import.preview.plugins': '插件待安装 {count}',\n 'import.preview.mcp': 'MCP 新增 {count}',\n 'import.preview.prompts': '提示词 {count}',\n 'import.preview.paths': '路径映射 {count}',\n 'import.preview.secrets': '密钥待补录 {count}',\n 'import.preview.conflicts': '冲突 {count}',\n 'import.preview.restart': '导入后需重启 DSH 生效',\n 'import.confirm.execute': '确认导入',\n 'import.confirm.warning': '导入将修改当前 DSH 配置;执行前会自动创建安全快照,失败时整体回滚。',\n 'import.rollbackOnError': '失败时整体回滚(推荐)',\n 'import.importing': '正在导入…',\n 'import.secrets.title': '补录密钥',\n 'import.secrets.hint': '以下凭据未随备份导出(安全设计)。如需在目标 DSH 使用,请手动补录;留空将跳过。',\n 'import.secrets.optional': '(可选)',\n 'import.secrets.required': '(必需)',\n 'import.conflicts.title': '解决冲突',\n 'import.conflicts.hint': '以下配置项在目标 DSH 已存在且与备份不同,请逐项决策。',\n 'import.conflicts.keepCurrent': '保留当前',\n 'import.conflicts.useImported': '使用备份',\n 'import.conflicts.review': '稍后决定',\n 'import.conflicts.unresolved': '还有 {count} 项未决策',\n 'import.paths.title': '路径映射',\n 'import.paths.hint': '备份中的绝对路径在目标机器可能不存在,请为每条路径指定新位置(留空将跳过该路径)。',\n 'import.paths.old': '原路径',\n 'import.paths.new': '新路径',\n 'import.paths.unresolved': '还有 {count} 条路径未映射',\n // —— 报告 ——\n 'report.export.title': '导出完成',\n 'report.import.title': '导入结果',\n 'report.rollback.title': '回滚报告',\n 'report.action.fixIssues': '查看失败项',\n 'report.action.viewDetails': '查看详情',\n 'report.action.done': '完成',\n 'report.needsRestart': '插件 / MCP 变更将在重启 DSH 后生效。',\n // —— 错误 ——\n 'error.title': '操作失败',\n 'error.hint': '错误消息已自动脱敏,不会泄露任何密钥信息。',\n} as const;\n\nexport const en: Record<keyof typeof zh, string> = {\n 'section.label': 'Backup & Migration',\n 'section.description': 'Export / import / migrate DSH configuration (backups exclude secrets; encrypted backups optional)',\n 'view.export': 'Export',\n 'view.import': 'Import',\n 'common.close': 'Close',\n 'common.cancel': 'Cancel',\n 'common.back': 'Back',\n 'common.next': 'Next',\n 'common.done': 'Done',\n 'common.retry': 'Retry',\n 'common.confirm': 'Confirm',\n 'common.loading': 'Loading…',\n 'common.unknownError': 'Unknown error',\n 'status.ready': 'Config Manager ready (plugin {version} · DSH {dsh} · {platform})',\n 'status.unavailable': 'Config Manager service unavailable — verify the plugin is mounted.',\n 'export.mode.quick': 'Quick Export',\n 'export.mode.quickHint': 'One-click export of recommended sections (portable, no device-specific data) for routine backups.',\n 'export.mode.custom': 'Custom Export',\n 'export.mode.customHint': 'Select sections per group.',\n 'export.includeSecrets': 'Include real secrets (encrypted backup)',\n 'export.includeSecretsHint': 'When enabled the backup contains secrets, encrypted with a password (AES-256-GCM). The password is used once and never written into the backup or any config file.',\n 'export.password': 'Backup encryption password',\n 'export.passwordConfirm': 'Confirm password',\n 'export.passwordMismatch': 'Passwords do not match',\n 'export.passwordRequired': 'An encryption password is required when including secrets',\n 'export.run': 'Start Export',\n 'export.running': 'Exporting…',\n 'export.download': 'Download backup file',\n 'export.selectionWarnings': 'Device-specific sections may not apply on another machine:',\n 'export.group.unknown': 'Other',\n 'export.included': 'Included',\n 'export.excluded': 'Excluded',\n 'import.select.title': 'Select Backup File',\n 'import.select.hint': 'Pick a dsh-config-*.zip backup exported from DSH to begin. Analysis is read-only and changes nothing.',\n 'import.select.browse': 'Choose ZIP file',\n 'import.select.file': 'Selected: {name}',\n 'import.analyzing': 'Analyzing backup…',\n 'import.compatibility.title': 'Compatibility',\n 'import.compatibility.score': 'Compatibility score: {score}',\n 'import.compatibility.ok': 'The backup can be imported',\n 'import.compatibility.fail': 'Backup analysis failed: {reason}',\n 'import.preview.title': 'Import Preview',\n 'import.preview.willChange': '{count} item(s) will change',\n 'import.preview.unchanged': '{count} item(s) already identical (skipped)',\n 'import.preview.settings': '{count} settings update(s)',\n 'import.preview.plugins': '{count} plugin(s) to install',\n 'import.preview.mcp': '{count} MCP server(s) added',\n 'import.preview.prompts': '{count} prompt(s)',\n 'import.preview.paths': '{count} path mapping(s) needed',\n 'import.preview.secrets': '{count} secret(s) to re-enter',\n 'import.preview.conflicts': '{count} conflict(s)',\n 'import.preview.restart': 'A DSH restart is required after import',\n 'import.confirm.execute': 'Confirm Import',\n 'import.confirm.warning': 'Import modifies the current DSH configuration; a safety snapshot is created first and everything rolls back on failure.',\n 'import.rollbackOnError': 'Roll back everything on failure (recommended)',\n 'import.importing': 'Importing…',\n 'import.secrets.title': 'Re-enter Secrets',\n 'import.secrets.hint': 'These credentials were not exported with the backup (security by design). Enter them manually to use them here; leave blank to skip.',\n 'import.secrets.optional': '(optional)',\n 'import.secrets.required': '(required)',\n 'import.conflicts.title': 'Resolve Conflicts',\n 'import.conflicts.hint': 'These items already exist on this machine and differ from the backup. Decide per item.',\n 'import.conflicts.keepCurrent': 'Keep current',\n 'import.conflicts.useImported': 'Use backup',\n 'import.conflicts.review': 'Decide later',\n 'import.conflicts.unresolved': '{count} item(s) unresolved',\n 'import.paths.title': 'Path Mapping',\n 'import.paths.hint': 'Absolute paths in the backup may not exist on this machine. Map each path to a new location (leave blank to skip).',\n 'import.paths.old': 'Original path',\n 'import.paths.new': 'New path',\n 'import.paths.unresolved': '{count} path(s) unmapped',\n 'report.export.title': 'Export Complete',\n 'report.import.title': 'Import Result',\n 'report.rollback.title': 'Rollback Report',\n 'report.action.fixIssues': 'View failures',\n 'report.action.viewDetails': 'View details',\n 'report.action.done': 'Done',\n 'report.needsRestart': 'Plugin / MCP changes take effect after restarting DSH.',\n 'error.title': 'Operation failed',\n 'error.hint': 'Error messages are auto-redacted and never leak secrets.',\n};\n\n/** 字典键联合(注册处 compile-time 校验) */\nexport type ConfigManagerKey = keyof typeof zh;\n","/**\n * dsh-config-manager 浏览器半入口 —— 运行在 dsh web GUI 内。\n *\n * 注册:\n * 1. `config-manager` locale 字典(zh 主源 / en 镜像);\n * 2. `settings.section` 设置页(id: config-manager, label: 备份与迁移 / Backup & Migration)。\n *\n * 挂载方式:settings.section 是官方 Slot(list/root,owner props 为 { close }),\n * 经 `ctx.slots.inject(...)` 声明感知注册 —— 与 dsh-plugin-marketplace 注册\n * `settings.plugins.tab`、ui-settings-general 注册 `settings.section` 完全同构\n * (声明未到 ledger 前不注册,声明塌缩时自动移除,重声明后自动重挂)。\n *\n * 导出纪律(dsh-ssh packages/client 规则):/client 面只携带 cordis 装载所需 +\n * 类型;所有值导出保持内部。\n */\nimport type { ClientContext } from './client-types.ts'\n// Type-only:拉入 ctx.locale 的 Context 合并(dsh-client-locale)。\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only:拉入 settings.section 的 SlotMap 合并(dsh-client-ui-settings)。\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\n// Type-only:拉入 SlotMap / LocaleNamespaceMap 合并表(dsh-client-ui-slots)。\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { ConfigManagerApi } from './api.ts'\nimport { ConfigManagerSection } from './ConfigManagerSection.tsx'\nimport { en, zh, type ConfigManagerKey } from './locales.ts'\n\n/** 本插件拥有的 locale namespace。 */\nconst NS = 'config-manager'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Config Manager 表面文案。 */\n 'config-manager': ConfigManagerKey\n }\n}\n\n/** 必需服务(fiber inject 等待 —— slots/locale 必须先就绪)。 */\nexport const inject = ['slots', 'locale']\n\n/** 类型面(导出纪律:除插件契约外无值导出)。 */\nexport type { ConfigManagerSectionProps } from './ConfigManagerSection.tsx'\nexport type { ExportViewProps } from './export/ExportView.tsx'\nexport type { ImportWizardViewProps } from './import/ImportWizardView.tsx'\nexport type { ConfigManagerApiError, DownloadResult, ServiceStatus, UploadResponse } from './api.ts'\nexport type { ConfigManagerKey } from './locales.ts'\n\n/**\n * 注册 Config Manager 设置页。\n * @param ctx - client root context(slots + locale 服务)。\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'config-manager: dictionaries')\n\n const t = ctx.locale.bind(NS)\n const api = new ConfigManagerApi()\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'config-manager',\n order: 60,\n label: () => t('section.label'),\n locale: NS,\n inject: () => ({ api }),\n }, ConfigManagerSection))\n}\n"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type ZipArchive, type ZipSafetyLimits } from '../utils/zip.ts';
2
+ import { type ConfigAdapter, type HostContext, type ImportAnalysis, type ImportDecisions, type ImportPlan, type ImportResult, type SnapshotStore } from './types.ts';
3
+ export interface AnalyzerOptions {
4
+ ctx: HostContext;
5
+ adapters: ConfigAdapter[];
6
+ snapshotStore: SnapshotStore;
7
+ limits?: ZipSafetyLimits;
8
+ /** 依赖存在性检查器(缺省不检查;m5/宿主可注入 which 类实现) */
9
+ dependencyChecker?: (command: string) => Promise<boolean>;
10
+ /** m4 可注入强化版 ZIP 安全解析 */
11
+ parseZipOverride?: (buf: Uint8Array, limits?: ZipSafetyLimits) => ZipArchive;
12
+ }
13
+ export declare class Analyzer {
14
+ private readonly ctx;
15
+ private readonly adapters;
16
+ private readonly snapshotStore;
17
+ private readonly limits?;
18
+ private readonly dependencyChecker?;
19
+ private readonly parseZipFn;
20
+ /** 会话内 bundle 缓存(zipPath → 解析结果),避免重复解压 */
21
+ private readonly bundleCache;
22
+ constructor(opts: AnalyzerOptions);
23
+ private loadBundle;
24
+ private extractSections;
25
+ private analyzeBundle;
26
+ analyzeImport(zipPath: string): Promise<ImportAnalysis>;
27
+ createImportPlan(zipPath: string, decisions: ImportDecisions): Promise<ImportPlan>;
28
+ executeImportPlan(zipPath: string, plan: ImportPlan, opts?: {
29
+ confirm?: boolean;
30
+ secretInputs?: Record<string, string>;
31
+ decryptedCredentials?: Map<string, string>;
32
+ rollbackOnError?: boolean;
33
+ }): Promise<ImportResult>;
34
+ private applyOne;
35
+ }