dsh-config-manager 0.1.20 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.d.ts +312 -46
- package/lib/client.js +1172 -205
- package/lib/client.js.map +1 -1
- package/lib/core/run-registry.d.ts +2 -2
- package/lib/core/run-registry.js +5 -1
- package/lib/core/run-registry.js.map +1 -1
- package/lib/index.js +292 -19
- package/lib/index.js.map +1 -1
- package/lib/sync/autosync-config.d.ts +34 -0
- package/lib/sync/autosync-config.js +116 -0
- package/lib/sync/autosync-config.js.map +1 -0
- package/lib/sync/autosync-scheduler.d.ts +95 -0
- package/lib/sync/autosync-scheduler.js +379 -0
- package/lib/sync/autosync-scheduler.js.map +1 -0
- package/lib/sync/sync-engine.d.ts +59 -4
- package/lib/sync/sync-engine.js +138 -12
- package/lib/sync/sync-engine.js.map +1 -1
- package/lib/sync/sync-history.d.ts +39 -0
- package/lib/sync/sync-history.js +88 -0
- package/lib/sync/sync-history.js.map +1 -0
- package/lib/sync/sync-session.d.ts +39 -0
- package/lib/sync/sync-session.js +54 -0
- package/lib/sync/sync-session.js.map +1 -0
- package/lib/ui/i18n.d.ts +63 -0
- package/lib/ui/i18n.js +130 -1
- package/lib/ui/i18n.js.map +1 -1
- package/package.json +1 -1
- package/src/client/config-manager.module.css +18 -0
- package/src/client/sync/SyncConfirmView.tsx +301 -0
- package/src/client/sync/SyncHistoryView.tsx +107 -25
- package/src/client/sync/SyncSettingsView.tsx +226 -83
- package/src/client/sync/history-model.test.ts +82 -0
- package/src/client/sync/history-model.ts +89 -2
- package/src/client/sync/sync-api.test.ts +155 -0
- package/src/client/sync/sync-api.ts +208 -16
- package/src/client/sync/sync-locales.ts +162 -1
- package/src/client/sync/sync-view-v2.test.ts +131 -0
- package/src/client/sync/sync-view.ts +151 -4
- package/src/core/run-registry.ts +7 -3
- package/src/index.ts +314 -22
- package/src/sync/autosync-config.test.ts +93 -0
- package/src/sync/autosync-config.ts +137 -0
- package/src/sync/autosync-scheduler.test.ts +191 -0
- package/src/sync/autosync-scheduler.ts +443 -0
- package/src/sync/sync-engine.test.ts +107 -7
- package/src/sync/sync-engine.ts +176 -14
- package/src/sync/sync-history.test.ts +85 -0
- package/src/sync/sync-history.ts +126 -0
- package/src/sync/sync-session.test.ts +137 -0
- package/src/sync/sync-session.ts +76 -0
- package/src/ui/i18n.ts +132 -3
- package/src/client/sync/SyncPullPreviewView.test.ts +0 -54
- package/src/client/sync/SyncPullPreviewView.tsx +0 -165
- package/src/client/sync/pull-preview-model.ts +0 -44
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["readJson","css","css","css","css","css","css","css","css","initial","css","formatDateTime","css","css","zh","en","syncZh","syncEn"],"sources":["../src/ui/i18n.ts","../src/client/api.ts","../src/ui/conflict-view.ts","../src/ui/types.ts","../src/ui/progress.ts","../src/ui/report.ts","../src/ui/export-flow.ts","../src/security/secret-scanner.ts","../src/security/redaction.ts","../src/ui/errors.ts","../src/ui/import-wizard.ts","../src/client/run-store.ts","../src/client/common/ui.tsx","../src/client/common/ErrorBanner.tsx","../src/client/common/progress-view.ts","../src/client/common/ProgressBar.tsx","../src/client/common/ReportView.tsx","../src/client/export/ExportView.tsx","../src/ui/flow.ts","../src/client/import/ConflictList.tsx","../src/client/import/PathMappingForm.tsx","../src/client/import/import-file-select.ts","../src/client/import/ImportWizardView.tsx","../src/client/snapshots/SnapshotsPanel.tsx","../src/client/sync/sync-api.ts","../src/client/sync/sync-view.ts","../src/client/sync/history-model.ts","../src/client/sync/SyncHistoryView.tsx","../src/client/sync/SyncPullPreviewView.tsx","../src/client/sync/SyncSettingsView.tsx","../src/client/ConfigManagerSection.tsx","../src/client/locales.ts","../src/client/sync/sync-locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * 客户端展示层(src/ui/*、src/client/common/*)的渲染文案目录(zh 源语言 / en 镜像)。\n *\n * 与 core 的 messages.ts 分工:本目录负责「客户端纯渲染层」(ReportView / ErrorBanner /\n * ProgressBar / sync-view)产生的中文文案;core 侧引擎消息已随 API 数据源翻译。\n * 这些纯函数原先直接内嵌中文,现经 UiDict 注入:Client 挂载时按 ctx.locale 提供。\n *\n * 纪律:\n * - TextKey 类型 = keyof typeof uiZh,en 缺键/多键即编译错误;\n * - {param} 插值,缺参原样保留。\n */\n\nexport const uiZh = {\n // 通用\n 'commonClose': '关闭',\n 'commonCancel': '取消',\n 'commonRetry': '重试',\n 'commonLoading': '加载中…',\n 'commonUnknownError': '未知错误',\n 'commonNext': '下一步',\n 'commonBack': '上一步',\n 'commonDone': '完成',\n // 导出\n 'export.download': '下载备份文件',\n 'export.running': '正在导出…',\n 'export.run': '开始导出',\n 'export.selectionWarnings': '以下分区为设备相关数据,跨设备导入时可能不适用:',\n 'export.included': '已包含',\n 'export.excluded': '未包含',\n 'export.unknownSection': '未知分区:{id}',\n 'export.deviceSpecific': '{label} 为设备相关数据({portability}),跨设备导入时可能不适用',\n // 报告\n 'report.backupCreated': '备份已创建',\n 'report.importComplete': '导入完成',\n 'report.importFailed': '导入失败',\n 'report.included': '已包含:',\n 'report.excluded': '未包含:',\n 'report.security': '安全:',\n 'report.apiKeysExcluded': 'API 密钥已排除:',\n 'report.containsSecrets': '包含密钥:',\n 'report.encrypted': '已加密:',\n 'report.redacted': '{count} 个敏感字段已脱敏',\n 'report.file': '文件:',\n 'report.yes': '是',\n 'report.yesEncrypted': '是(加密)',\n 'report.no': '否',\n 'report.importedRestored': '已导入/恢复',\n 'report.skipped': '跳过',\n 'report.needAttention': '需注意',\n 'report.failed': '失败',\n 'report.noChanges': '无变更',\n 'report.reason': '原因',\n 'report.note': '说明',\n 'report.unknownReason': '未知原因',\n 'report.secrets': '密钥:',\n 'report.credentialsNeedEntry': '{count} 个凭据需要补录',\n 'report.restartRequired': '重启 DSH 后生效:{detail}',\n 'report.restartPluginsMcp': '插件/MCP 更改将在重启 DSH 后生效',\n 'report.rollbackFull': '回滚:已完整恢复导入前的配置。',\n 'report.rollbackPartial': '回滚部分完成。',\n 'report.rollbackManual': '以下项目可能需要人工恢复:',\n 'report.restored': '已恢复:{count} 项',\n // 错误\n 'error.notMounted': 'config-manager 服务未挂载(插件未加载):请确认 profile 中已安装 dsh-config-manager 并重启 DSH',\n 'error.httpInvalidJson': 'HTTP {status}: 无效的 JSON 响应',\n 'error.fallback': '操作失败',\n 'error.downloadFailed': '下载失败:HTTP {status}',\n 'error.exportTimeout': '导出超时({minutes} 分钟):导出过程未完成,请重试;若反复超时请检查 DSH 状态',\n 'error.syncTimeout': '同步请求超时({minutes} 分钟):请检查网络与仓库可达性后重试',\n 'error.settingsConflict.title': '配置已被并发修改',\n 'error.settingsConflict.action': '目标 DSH 的该配置在导入期间被其他进程修改,为避免覆盖请重新导出或手动核对后再试。',\n 'error.notConfirmed.title': '导入未确认',\n 'error.notConfirmed.action': '请在预览页确认导入内容后重试。',\n 'error.integrity.title': '备份完整性校验失败',\n 'error.integrity.action': '备份文件可能已损坏或被篡改,请重新导出备份后再试。',\n 'error.schema.title': '备份格式版本不受支持',\n 'error.schema.action': '请升级 DSH Config Manager 或使用相同版本的备份文件。',\n 'error.notFound.title': '文件或路径不存在',\n 'error.notFound.action': '请检查文件路径是否正确、文件是否已被移动或删除。',\n 'error.permission.title': '权限不足',\n 'error.permission.action': '请检查目标目录的读写权限后重试。',\n 'error.needsRestart.title': '插件安装需要重启生效',\n 'error.needsRestart.action': '导入已完成,插件将在重启 DSH 后生效;请在 DSH Desktop 中重启服务。',\n 'error.reason': '原因',\n 'error.suggestedAction': '建议操作',\n 'error.item': '相关项',\n // 进度\n 'progress.analyzing': '正在分析配置…',\n 'progress.exportingSettings': '正在导出设置…',\n 'progress.scanningSecrets': '正在扫描密钥…',\n 'progress.exportingPlugins': '正在导出插件…',\n 'progress.creatingArchive': '正在创建归档…',\n 'progress.calculatingChecksums': '正在计算校验和…',\n 'progress.exporting': '正在导出配置…',\n 'progress.validating': '正在校验备份…',\n 'progress.checkingCompatibility': '正在检查兼容性…',\n 'progress.creatingSnapshot': '正在创建安全快照…',\n 'progress.restoringSettings': '正在恢复设置…',\n 'progress.restoringPlugins': '正在恢复插件…',\n 'progress.restoringMcp': '正在恢复 MCP…',\n 'progress.validatingConfig': '正在校验配置…',\n 'progress.rollingBack': '正在回滚…',\n 'progress.executing': '正在应用配置(插件安装可能需要较长时间)…',\n 'progress.done': '完成',\n // 快照\n 'snapshots.createdAt': '创建时间',\n 'snapshots.sourceZip': '来源',\n 'snapshots.status': '状态',\n 'snapshots.entries': '条目',\n 'snapshots.plugins': '插件',\n 'snapshots.statusPending': '待处理',\n 'snapshots.statusDone': '已完成',\n 'snapshots.statusRolledback': '已回滚',\n 'snapshots.statusUnknown': '未知',\n 'snapshots.planTitle': '恢复计划预览',\n 'snapshots.confirmRestore': '确认恢复?当前文件将先备份到快照的 pre-restore 文件夹;插件经官方 dsh plugin remove 卸载。',\n 'snapshots.execute': '立即恢复',\n 'snapshots.executing': '正在恢复…',\n 'snapshots.restored': '已恢复',\n 'snapshots.removedPlugins': '已卸载插件',\n 'snapshots.manualHints': '需人工处理',\n 'snapshots.failed': '失败',\n 'snapshots.skipped': '跳过',\n 'snapshots.noActions': '该快照无可恢复动作(或全部跳过)。',\n 'snapshots.empty': '暂无快照。导入时会自动创建安全快照。',\n 'snapshots.loading': '正在加载快照…',\n 'snapshots.selectHint': '选择一个快照预览其恢复计划(dry-run,零写入):',\n 'snapshots.reportTitle': '恢复报告',\n // 同步区块(sync-view)\n 'sync.privateRepoHint': '安全要求:同步仓库必须为私有仓库(public 仓库会公开你的配置内容)。认证 token 仅用于仓库访问,绝不写入同步文件、提交内容或日志。',\n 'sync.kind.create': '新增',\n 'sync.kind.update': '更新',\n 'sync.kind.skip': '跳过',\n 'sync.kind.conflict': '冲突',\n 'sync.kind.install': '安装',\n 'sync.kind.missingSecret': '缺密钥',\n 'sync.kind.missingDependency': '缺依赖',\n 'sync.kind.pathMapping': '路径映射',\n 'sync.kind.warning': '警告',\n 'sync.kind.error': '错误',\n 'sync.severity.error': '错误',\n 'sync.severity.warning': '警告',\n 'sync.severity.info': '信息',\n 'sync.pushLabel': '推送到远端',\n 'sync.pullLabel': '拉取差异预览',\n 'sync.pushing': '正在推送…',\n 'sync.pulling': '正在拉取…',\n 'sync.statusLoading': '正在读取同步状态…',\n 'sync.statusUnconfigured': '尚未配置同步仓库(请填写仓库地址并推送一次以保存配置)',\n 'sync.credConfigured': '凭据已配置',\n 'sync.credMissing': '未配置凭据(token 将在首次推送/拉取时写入 DSH credentials)',\n 'sync.lastSync': '上次同步:{time}',\n 'sync.neverSynced': '尚未同步过',\n 'sync.neverSyncedShort': '从未同步',\n 'sync.pushFailed': '推送失败',\n 'sync.pushOk': '推送成功(快照 {id})',\n 'sync.pullFailed': '拉取失败',\n 'sync.pullOk': '远端快照 {id} 差异预览:共 {count} 项变更',\n 'sync.pullEmpty': '远端快照与本地一致(无变更)',\n 'sync.previewHint': '以上为只读差异预览,不会执行导入。v1 暂不提供一键导入接线;如需应用远端配置,请使用「导入恢复」向导手动导入导出的备份。',\n // GitHub OAuth 区块\n 'sync.github.starting': '正在发起 GitHub 授权…',\n 'sync.github.waitingNoCode': '请在浏览器中打开授权页面并完成授权…',\n 'sync.github.waiting': '请在浏览器中打开授权页面,输入一次性代码 {code} 完成授权(自动等待确认)。',\n 'sync.github.polling': '正在确认 GitHub 授权状态…',\n 'sync.github.success': 'GitHub 登录成功:token 已安全写入 DSH credentials,可直接推送/拉取。',\n 'sync.github.failed': 'GitHub 登录失败',\n 'sync.github.defaultStatus': '通过 GitHub OAuth 设备码流程登录,token 自动写入 DSH credentials(无需手动输入)。',\n 'sync.github.login': '使用 GitHub 登录',\n 'sync.github.relogin': '重新登录',\n 'sync.github.pollSuccess': 'GitHub 登录成功:token 已安全写入 DSH credentials。',\n 'sync.github.pollDenied': 'GitHub 授权被拒绝(access_denied)。可重新发起登录,或改用下方手动 token 输入。',\n 'sync.github.pollExpired': 'GitHub 授权已过期(expired_token)。请重新发起登录。',\n 'sync.github.pollError': 'GitHub OAuth 错误:{detail}',\n 'sync.github.unknownError': '未知错误',\n} as const;\n\nexport type UiTextKey = keyof typeof uiZh;\n\nexport const uiEn: Record<UiTextKey, string> = {\n 'commonClose': 'Close',\n 'commonCancel': 'Cancel',\n 'commonRetry': 'Retry',\n 'commonLoading': 'Loading…',\n 'commonUnknownError': 'Unknown error',\n 'commonNext': 'Next',\n 'commonBack': 'Back',\n 'commonDone': 'Done',\n 'export.download': 'Download backup file',\n 'export.running': 'Exporting…',\n 'export.run': 'Start Export',\n 'export.selectionWarnings': 'Device-specific sections may not apply on another machine:',\n 'export.included': 'Included',\n 'export.excluded': 'Excluded',\n 'export.unknownSection': 'Unknown section: {id}',\n 'export.deviceSpecific': '{label} is device-specific ({portability}) and may not apply on another machine',\n 'report.backupCreated': 'Backup Created',\n 'report.importComplete': 'Import Complete',\n 'report.importFailed': 'Import Failed',\n 'report.included': 'Included:',\n 'report.excluded': 'Excluded:',\n 'report.security': 'Security:',\n 'report.apiKeysExcluded': 'API Keys excluded:',\n 'report.containsSecrets': 'Contains secrets:',\n 'report.encrypted': 'Encrypted:',\n 'report.redacted': '{count} sensitive field(s) redacted',\n 'report.file': 'File:',\n 'report.yes': 'yes',\n 'report.yesEncrypted': 'yes (encrypted)',\n 'report.no': 'no',\n 'report.importedRestored': 'imported/restored',\n 'report.skipped': 'skipped',\n 'report.needAttention': 'need attention',\n 'report.failed': 'failed',\n 'report.noChanges': 'no changes',\n 'report.reason': 'Reason',\n 'report.note': 'Note',\n 'report.unknownReason': 'Unknown reason',\n 'report.secrets': 'Secrets:',\n 'report.credentialsNeedEntry': '{count} credential(s) need to be entered',\n 'report.restartRequired': 'Restart DSH to apply: {detail}',\n 'report.restartPluginsMcp': 'Plugin / MCP changes take effect after restarting DSH',\n 'report.rollbackFull': 'Rollback: fully restored the pre-import configuration.',\n 'report.rollbackPartial': 'Rollback partially completed.',\n 'report.rollbackManual': 'These items may require manual recovery:',\n 'report.restored': 'Restored: {count} item(s)',\n 'error.notMounted': 'config-manager service is not mounted (plugin not loaded): make sure dsh-config-manager is installed in the profile and restart DSH',\n 'error.httpInvalidJson': 'HTTP {status}: invalid JSON response',\n 'error.fallback': 'Operation failed',\n 'error.downloadFailed': 'Download failed: HTTP {status}',\n 'error.exportTimeout': 'Export timed out ({minutes} min): the export did not complete, please retry; if it keeps timing out, check the DSH state',\n 'error.syncTimeout': 'Sync request timed out ({minutes} min): check network and repository reachability, then retry',\n 'error.settingsConflict.title': 'Configuration changed concurrently',\n 'error.settingsConflict.action': 'This configuration on the target DSH was modified by another process during import. To avoid overwriting it, re-export or review it manually, then retry.',\n 'error.notConfirmed.title': 'Import not confirmed',\n 'error.notConfirmed.action': 'Confirm the import on the preview page, then retry.',\n 'error.integrity.title': 'Backup integrity check failed',\n 'error.integrity.action': 'The backup may be corrupted or tampered with. Re-export the backup, then retry.',\n 'error.schema.title': 'Backup format version not supported',\n 'error.schema.action': 'Upgrade DSH Config Manager or use a backup from the same version.',\n 'error.notFound.title': 'File or path not found',\n 'error.notFound.action': 'Check that the file path is correct and the file has not been moved or deleted.',\n 'error.permission.title': 'Permission denied',\n 'error.permission.action': 'Check read/write permissions on the target directory, then retry.',\n 'error.needsRestart.title': 'Plugin install requires a restart',\n 'error.needsRestart.action': 'The import is complete; plugins take effect after restarting DSH. Restart the service in DSH Desktop.',\n 'error.reason': 'Reason',\n 'error.suggestedAction': 'Suggested action',\n 'error.item': 'Item',\n 'progress.analyzing': 'Analyzing configuration...',\n 'progress.exportingSettings': 'Exporting settings...',\n 'progress.scanningSecrets': 'Scanning secrets...',\n 'progress.exportingPlugins': 'Exporting plugins...',\n 'progress.creatingArchive': 'Creating archive...',\n 'progress.calculatingChecksums': 'Calculating checksums...',\n 'progress.exporting': 'Exporting configuration...',\n 'progress.validating': 'Validating backup...',\n 'progress.checkingCompatibility': 'Checking compatibility...',\n 'progress.creatingSnapshot': 'Creating safety snapshot...',\n 'progress.restoringSettings': 'Restoring settings...',\n 'progress.restoringPlugins': 'Restoring plugins...',\n 'progress.restoringMcp': 'Restoring MCP...',\n 'progress.validatingConfig': 'Validating configuration...',\n 'progress.rollingBack': 'Rolling back...',\n 'progress.executing': 'Applying configuration (plugin installs may take a while)...',\n 'progress.done': 'Done',\n 'snapshots.createdAt': 'Created',\n 'snapshots.sourceZip': 'Source',\n 'snapshots.status': 'Status',\n 'snapshots.entries': 'Entries',\n 'snapshots.plugins': 'Plugins',\n 'snapshots.statusPending': 'Pending',\n 'snapshots.statusDone': 'Done',\n 'snapshots.statusRolledback': 'Rolled back',\n 'snapshots.statusUnknown': 'Unknown',\n 'snapshots.planTitle': 'Restore Plan Preview',\n 'snapshots.confirmRestore': 'Confirm restore? Current files are backed up to the snapshot\\'s pre-restore folder first; plugins are removed via the official dsh plugin remove.',\n 'snapshots.execute': 'Restore now',\n 'snapshots.executing': 'Restoring…',\n 'snapshots.restored': 'Restored',\n 'snapshots.removedPlugins': 'Removed plugins',\n 'snapshots.manualHints': 'Manual action needed',\n 'snapshots.failed': 'Failed',\n 'snapshots.skipped': 'Skipped',\n 'snapshots.noActions': 'No restorable actions for this snapshot (or all skipped).',\n 'snapshots.empty': 'No snapshots yet. A safety snapshot is created automatically on import.',\n 'snapshots.loading': 'Loading snapshots…',\n 'snapshots.selectHint': 'Select a snapshot to preview its restore plan (dry-run, zero writes):',\n 'snapshots.reportTitle': 'Restore Report',\n 'sync.privateRepoHint': 'Security requirement: the sync repository MUST be private (a public repo would expose your configuration). The auth token is only used for repository access and is never written into sync files, commit content, or logs.',\n 'sync.kind.create': 'Create',\n 'sync.kind.update': 'Update',\n 'sync.kind.skip': 'Skip',\n 'sync.kind.conflict': 'Conflict',\n 'sync.kind.install': 'Install',\n 'sync.kind.missingSecret': 'Secret',\n 'sync.kind.missingDependency': 'Dependency',\n 'sync.kind.pathMapping': 'Path',\n 'sync.kind.warning': 'Warning',\n 'sync.kind.error': 'Error',\n 'sync.severity.error': 'Error',\n 'sync.severity.warning': 'Warning',\n 'sync.severity.info': 'Info',\n 'sync.pushLabel': 'Push to remote',\n 'sync.pullLabel': 'Pull diff preview',\n 'sync.pushing': 'Pushing…',\n 'sync.pulling': 'Pulling…',\n 'sync.statusLoading': 'Reading sync status…',\n 'sync.statusUnconfigured': 'No sync repository configured (fill in the repository URL and push once to save the config)',\n 'sync.credConfigured': 'Credential configured',\n 'sync.credMissing': 'No credential configured (token is written into DSH credentials on first push/pull)',\n 'sync.lastSync': 'Last sync: {time}',\n 'sync.neverSynced': 'Never synced yet',\n 'sync.neverSyncedShort': 'Never synced',\n 'sync.pushFailed': 'Push failed',\n 'sync.pushOk': 'Push succeeded (snapshot {id})',\n 'sync.pullFailed': 'Pull failed',\n 'sync.pullOk': 'Remote snapshot {id} diff preview: {count} change(s)',\n 'sync.pullEmpty': 'Remote snapshot matches local (no changes)',\n 'sync.previewHint': 'Read-only diff preview above; nothing is imported. v1 does not wire one-click import yet — use the Import wizard to apply a downloaded backup if needed.',\n 'sync.github.starting': 'Starting GitHub authorization…',\n 'sync.github.waitingNoCode': 'Open the authorization page in your browser and complete the flow…',\n 'sync.github.waiting': 'Open the authorization page in your browser, enter the one-time code {code} to finish (waiting for confirmation).',\n 'sync.github.polling': 'Confirming GitHub authorization…',\n 'sync.github.success': 'GitHub sign-in succeeded: token securely written into DSH credentials — you can push/pull now.',\n 'sync.github.failed': 'GitHub sign-in failed',\n 'sync.github.defaultStatus': 'Sign in via the GitHub OAuth device flow; the token is written into DSH credentials automatically (no manual entry).',\n 'sync.github.login': 'Sign in with GitHub',\n 'sync.github.relogin': 'Sign in again',\n 'sync.github.pollSuccess': 'GitHub sign-in succeeded: token securely written into DSH credentials.',\n 'sync.github.pollDenied': 'GitHub authorization was denied (access_denied). You can re-start the sign-in or use manual token entry below.',\n 'sync.github.pollExpired': 'GitHub authorization expired (expired_token). Please re-start the sign-in.',\n 'sync.github.pollError': 'GitHub OAuth error: {detail}',\n 'sync.github.unknownError': 'Unknown error',\n};\n\n/** UI 翻译函数:key → 当前语言文案({param} 插值;未知键回退 zh/键名)。 */\nexport type UiT = (key: UiTextKey, params?: Record<string, string | number>) => string;\n\n/** 构造 翻译函数(zh 源 / en 镜像;缺 key 回退)。 */\nexport function makeUiT(lang: 'zh' | 'en'): UiT {\n const dict = lang === 'en' ? uiEn : uiZh;\n const fallback = lang === 'en' ? uiZh : undefined;\n return (key, params) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const template = (dict as any)[key] ?? (fallback as any)?.[key] ?? key;\n if (params === undefined) return template;\n return String(template).replace(/\\{(\\w+)\\}/g, (match, k: string) =>\n params[k] === undefined ? match : String(params[k]),\n );\n };\n}\n\n/** 缺省 UI 翻译(zh):未注入的渲染路径行为与改造前完全一致。 */\nexport const zhUiT: UiT = makeUiT('zh');","/**\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;响应含 runId)\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 };响应含 runId)\n * GET /api/dsh-config-manager/progress?runId=… → RunState (run 实时状态:轮询/刷新恢复)\n * GET /api/dsh-config-manager/runs → RunState[] (活跃 run 列表)\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 { RestorePlan, RestoreReport, SnapshotMeta } from '../core/restore.ts';\nimport type { RunState } from '../core/run-registry.ts';\nimport type { Manifest } from '../schema/types.ts';\nimport { zhUiT, type UiT } from '../ui/i18n.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 前半部分;runId 为 m1 run 注册表标识) */\nexport interface ExportResponse {\n zipPath: string;\n manifest: Manifest;\n report: ExportReport;\n /** m1:本次导出 run 的 id(可用 /progress 查询状态 / 刷新恢复) */\n runId: string;\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/** restore 端点响应:dryRun=true 返回 plan;执行返回 report(与 CLI 一致的诚实报告) */\nexport interface RestoreResponse {\n dryRun: boolean;\n plan?: RestorePlan;\n report?: RestoreReport;\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 progress: '/api/dsh-config-manager/progress',\n runs: '/api/dsh-config-manager/runs',\n snapshots: '/api/dsh-config-manager/snapshots',\n restore: '/api/dsh-config-manager/restore',\n} as const;\n\n/** 导出请求超时(ms):与 Host 半 ROUTE_TIMEOUT_MS 对齐,防止宿主卡死时 UI 无限等待 */\nconst EXPORT_TIMEOUT_MS = 5 * 60 * 1000;\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, t: UiT): Promise<T> {\n const notMountedMessage = t('error.notMounted');\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n if (response.status === 404) throw new ConfigManagerApiError(notMountedMessage);\n throw new ConfigManagerApiError(t('error.httpInvalidJson', { status: String(response.status) }));\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 : response.status === 404\n ? notMountedMessage\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 /** 客户端展示层翻译器(zh 源 / en 镜像,见 ui/i18n.ts)。 */\n readonly t: UiT\n\n constructor(t: UiT = zhUiT) {\n this.t = t\n }\n\n // ------------------------------------------------------------- status\n /** 健康/版本检查(主页横幅:插件版本 / DSH 版本 / 平台) */\n async status(): Promise<ServiceStatus> {\n const response = await fetch(CONFIG_MANAGER_API.status);\n return readJson<ServiceStatus>(response, this.t);\n }\n\n // ------------------------------------------------------------- export\n /** ExportPort.export:调用 Host 侧导出编排(core Exporter)。加密密码随请求体传输(仅内存)。\n * 带 AbortController 超时:宿主若卡死,客户端得到明确错误而不是永远停在进度条。 */\n async export(options: ExportOptions): Promise<ExportResponse> {\n const body: ExportOptions & { password?: string } = {\n ...options,\n password: this.exportPassword ?? undefined,\n };\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), EXPORT_TIMEOUT_MS);\n try {\n const response = await fetch(CONFIG_MANAGER_API.export, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n return await readJson<ExportResponse>(response, this.t);\n } catch (err) {\n if (controller.signal.aborted) {\n throw new ConfigManagerApiError(this.t('error.exportTimeout', { minutes: String(Math.round(EXPORT_TIMEOUT_MS / 60000)) }));\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\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 : this.t('error.downloadFailed', { status: String(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, this.t);\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, this.t);\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, this.t);\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 & { runId: string }> {\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 & { runId: string }>(response, this.t);\n }\n\n // ------------------------------------------------------------- run 进度\n /** m1:查询单个 run 的实时状态(执行中轮询 / 刷新恢复用;404 = 已过保留期或不存在) */\n async progress(runId: string): Promise<RunState> {\n const response = await fetch(CONFIG_MANAGER_API.progress + query({ runId }));\n return readJson<RunState>(response, this.t);\n }\n\n /** m1:列出当前活跃(running)的 run(刷新后重新订阅进行中任务的入口) */\n async runs(): Promise<RunState[]> {\n const response = await fetch(CONFIG_MANAGER_API.runs);\n return readJson<RunState[]>(response, this.t);\n }\n\n // ------------------------------------------------------- 快照恢复(M4)\n /** 列出全部快照元信息(createdAt 倒序;含 status/条目数/宿主文件数/插件数) */\n async snapshots(): Promise<SnapshotMeta[]> {\n const response = await fetch(CONFIG_MANAGER_API.snapshots);\n const body = await readJson<{ snapshots: SnapshotMeta[] }>(response, this.t);\n return body.snapshots;\n }\n\n /** 快照恢复:dryRun=true 只取动作计划(零写入);false 执行并返回诚实报告 */\n async restoreSnapshot(snapshotId: string, dryRun: boolean): Promise<RestoreResponse> {\n const response = await fetch(CONFIG_MANAGER_API.restore, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ snapshotId, dryRun }),\n });\n return readJson<RestoreResponse>(response, this.t);\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 * 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 warned: number;\n failed: number;\n items: { itemId: string; status: 'ok' | 'skipped' | 'warning' | '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';\nimport { zhUiT, type UiT, type UiTextKey } from './i18n.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\n/**\n * 真实执行阶段(不在 IMPORT_STAGES 序列里,因此 step/total 缺省 → 进度条渲染\n * 为不定态动画而非伪造百分比)。execute 是一个单次 HTTP 请求,Host 端串行\n * 跑完全部计划项(其中插件安装是 npm 串行,耗时最长);请求期间没有中间\n * 进度事件可回传,旧实现把 restoring-settings / restoring-plugins /\n * restoring-mcp / validating-config 在请求前全部预发,导致进度条瞬间跳到\n * 78% 后长时间无变化——像卡死。现在统一在请求期间显示 'executing' 不定态,\n * 让用户明确知道「仍在执行,请等待」。\n */\nexport const EXECUTING_STAGE = 'executing' as const;\n\nconst STAGE_KEYS: Record<string, UiTextKey> = {\n analyzing: 'progress.analyzing',\n 'exporting-settings': 'progress.exportingSettings',\n 'scanning-secrets': 'progress.scanningSecrets',\n 'exporting-plugins': 'progress.exportingPlugins',\n 'creating-archive': 'progress.creatingArchive',\n 'calculating-checksums': 'progress.calculatingChecksums',\n exporting: 'progress.exporting',\n validating: 'progress.validating',\n 'checking-compatibility': 'progress.checkingCompatibility',\n 'creating-snapshot': 'progress.creatingSnapshot',\n 'restoring-settings': 'progress.restoringSettings',\n 'restoring-plugins': 'progress.restoringPlugins',\n 'restoring-mcp': 'progress.restoringMcp',\n 'validating-config': 'progress.validatingConfig',\n 'rolling-back': 'progress.rollingBack',\n executing: 'progress.executing',\n done: 'progress.done',\n};\n\n/** 阶段 id → 用户可读文案(未知阶段回退 id) */\nexport function stageText(stage: string, t: UiT = zhUiT): string {\n const key = STAGE_KEYS[stage];\n return key !== undefined ? t(key) : 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';\nimport { zhUiT, type UiT } from './i18n.ts';\n\n/* ---------------- §21 导出报告 ---------------- */\n\nexport function renderExportReport(report: ExportReport, t: UiT = zhUiT): string {\n const lines: string[] = [t('report.backupCreated'), ''];\n lines.push(t('report.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(t('report.excluded'));\n for (const s of report.excluded) lines.push(` ○ ${s}`);\n lines.push('');\n }\n lines.push(t('report.security'));\n lines.push(` ✓ ${t('report.apiKeysExcluded')} ${report.security.secretsExcluded ? t('report.yes') : t('report.no')}`);\n lines.push(` ✓ ${t('report.containsSecrets')} ${report.security.containsSecrets ? t('report.yesEncrypted') : t('report.no')}`);\n lines.push(` ✓ ${t('report.encrypted')} ${report.security.encrypted ? t('report.yes') : t('report.no')}`);\n if (report.security.redactedHits > 0) lines.push(` ⚠ ${t('report.redacted', { count: String(report.security.redactedHits) })}`);\n lines.push('');\n lines.push(`${t('report.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, warned: 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 if (e.status === 'warning') stat.warned += 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, t: UiT = zhUiT): string {\n const lines: string[] = [result.ok ? t('report.importComplete') : t('report.importFailed'), ''];\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} ${t('report.importedRestored')}`);\n if (s.skipped > 0) parts.push(`- ${s.skipped} ${t('report.skipped')}`);\n if (s.warned > 0) parts.push(`⚠ ${s.warned} ${t('report.needAttention')}`);\n if (s.failed > 0) parts.push(`✗ ${s.failed} ${t('report.failed')}`);\n lines.push(`${s.section}: ${parts.join(' ') || t('report.noChanges')}`);\n // 失败/警告项给出可操作原因(§23)\n for (const it of s.items) {\n if (it.status === 'failed' || it.status === 'warning') {\n lines.push(` ${it.status === 'failed' ? t('report.reason') : t('report.note')}: ${it.message ?? t('report.unknownReason')}`);\n }\n }\n }\n if (result.missingSecrets.length > 0) {\n lines.push(`${t('report.secrets')} ⚠ ${t('report.credentialsNeedEntry', { count: String(result.missingSecrets.length) })}`);\n }\n if (result.needsRestart) {\n lines.push(t('report.restartPluginsMcp'));\n }\n for (const w of result.warnings) lines.push(`⚠ ${w}`);\n if (result.rollback) {\n lines.push('');\n lines.push(renderRollbackReport(result.rollback, t));\n }\n return lines.join('\\n');\n}\n\n/** 结果页动作按钮(§22)。报告已内联展示全部失败/警告项的原因与回滚详情(§23),\n * 不再提供空操作的 Fix Issues / View Details 按钮——仅保留「完成」。 */\nexport function suggestedActions(_result: ImportResult): ImportResultAction[] {\n return ['done'];\n}\n\n/* ---------------- §17 回滚报告 ---------------- */\n\n/** 回滚报告渲染(full / partial + 人工恢复清单) */\nexport function renderRollbackReport(rr: RollbackReport, t: UiT = zhUiT): string {\n if (rr.full) {\n return t('report.rollbackFull');\n }\n const lines = [t('report.rollbackPartial')];\n lines.push(t('report.rollbackManual'));\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(t('report.restored', { count: String(rr.restored.length) }));\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';\nimport { zhUiT, type UiT } from './i18n.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 /** 报告渲染翻译器(zh/en,见 i18n.ts) */\n t?: UiT;\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 private readonly t: UiT;\n\n constructor(opts: ExportFlowOptions) {\n this.port = opts.port;\n this.categories = opts.categories ?? DEFAULT_CATEGORIES;\n this.onProgress = opts.onProgress;\n this.t = opts.t ?? zhUiT;\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 // 导出工作全部发生在 port.export() 的单次请求内,客户端无法逐阶段上报真实进度。\n // 旧实现把整串阶段一次性 emit,请求期间 UI 会静止在假的「Calculating checksums... 86%」,\n // 任何慢请求/挂起请求看起来都像卡死。改为:请求期间只发一个不带 step/total 的 in-flight\n // 阶段(ProgressBar 显示不定态动画),完成后发 done(100%)。超时/失败由 api 层显式抛出。\n tracker.emit('exporting');\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, this.t) };\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 * - 文案经 UiT 注入(zh 源 / en 镜像,见 i18n.ts)。\n */\nimport { redact } from '../security/redaction.ts';\nimport { zhUiT, type UiT } from './i18n.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\nfunction buildErrorRules(t: UiT): readonly ErrorRule[] {\n return [\n {\n match: (m) => /SETTINGS_CONFLICT|revision.*conflict/i.test(m),\n title: t('error.settingsConflict.title'),\n suggestedAction: t('error.settingsConflict.action'),\n retryable: true,\n },\n {\n match: (m) => /ImportNotConfirmed|未确认/i.test(m),\n title: t('error.notConfirmed.title'),\n suggestedAction: t('error.notConfirmed.action'),\n retryable: true,\n },\n {\n match: (m) => /backup integrity|完整性校验失败|checksum/i.test(m),\n title: t('error.integrity.title'),\n suggestedAction: t('error.integrity.action'),\n retryable: false,\n },\n {\n match: (m) => /schema.*(不支持|超出)|无法导入|Unsupported|schemaUnsupported|无法导入/i.test(m),\n title: t('error.schema.title'),\n suggestedAction: t('error.schema.action'),\n retryable: false,\n },\n {\n match: (m) => /ENOENT|not found|无法读取|不存在|readFailed/i.test(m),\n title: t('error.notFound.title'),\n suggestedAction: t('error.notFound.action'),\n retryable: true,\n },\n {\n match: (m) => /EACCES|permission|权限/i.test(m),\n title: t('error.permission.title'),\n suggestedAction: t('error.permission.action'),\n retryable: true,\n },\n {\n match: (m) => /install.*(plugin|插件)|needsRestart|重启/i.test(m),\n title: t('error.needsRestart.title'),\n suggestedAction: t('error.needsRestart.action'),\n retryable: false,\n },\n ];\n}\n\n/** 将任意错误转换为可操作错误(消息已脱敏,不泄漏 Secret) */\nexport function toActionableError(err: unknown, opts?: { item?: string; fallbackTitle?: string; t?: UiT }): ActionableError {\n const t = opts?.t ?? zhUiT;\n const raw = err instanceof Error ? err.message : String(err ?? t('commonUnknownError'));\n const message = redact(raw);\n const rule = buildErrorRules(t).find((r) => r.match(message));\n return {\n title: rule?.title ?? opts?.fallbackTitle ?? t('error.fallback'),\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, t: UiT = zhUiT): string {\n const lines = [e.title];\n lines.push(`${t('error.reason')}: ${e.reason}`);\n if (e.suggestedAction) lines.push(`${t('error.suggestedAction')}: ${e.suggestedAction}`);\n if (e.item) lines.push(`${t('error.item')}: ${e.item}`);\n return lines.join('\\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 { EXECUTING_STAGE, 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 // 快照由 Host 端在 executeImportPlan 内部第一步创建;此处只发开始阶段。\n this.tracker.emit('creating-snapshot');\n\n try {\n // 用最终决策重建计划(与预览逻辑一致,保证 Dry Run 与真实导入一致)\n this.plan = await this.port.createImportPlan(this.zipPath, this.decisions);\n // executeImportPlan 是一个单次 HTTP 请求:Host 端串行跑完全部计划项\n // (插件安装为 npm 串行,耗时最长)。请求期间没有任何中间进度事件可\n // 回传——旧实现把 restoring-settings / restoring-plugins /\n // restoring-mcp / validating-config 在请求前全部预发,进度条瞬间跳到\n // 78% 后长时间不动,看起来像卡死。现在统一改为 EXECUTING_STAGE\n // 不定态(无 step/total → 动画),让用户明确知道「仍在执行」。\n // 真实各分区结果在返回后的报告里逐项展示。\n this.tracker.emit(EXECUTING_STAGE);\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 * m2: 模块级 run/UI store —— dsh-config-manager 浏览器半的状态中枢。\n *\n * 解决的问题(验收 m2-state / m2-refresh / m2-resume):\n * - 切 tab / 关面板重开:模块级单例存活于当前 JS 上下文,ExportFlow /\n * ImportWizard 控制器实例与 UI 状态**不重建**(m2-state);\n * - 页面刷新:非敏感状态经 sessionStorage(键 dsh.cfgMgr.state.v1)\n * 序列化/反序列化恢复(m2-refresh);敏感字段\n * password / passwordConfirm / secretInputs **只存在内存**,序列化白名单\n * 显式剔除 —— 刷新后自动清空,secrets 阶段要求重输;\n * - 进行中 run:视图挂载时经 GET /runs 找回活跃 runId,轮询 GET /progress\n * 直到完成/失败,把 RunState.result 回填到 store(m2-resume)。服务端在\n * 刷新/关面板期间继续执行,本 store 只负责重新订阅进度。\n *\n * 控制器 rehydrate 说明:ImportWizard 没有公开的 hydrate 入口(m2 约束为只改\n * src/client/、不动 src/ui/),刷新恢复需要把持久化的非敏感快照写回控制器\n * 私有字段。writeWizardSnapshot() 是唯一的受控访问点:类型层 private 只是\n * 编译期约束(运行时是普通属性),所有写入值都来自序列化白名单(已剔除\n * 密码/密钥/secretInputs),且只在 load / hydrate / resume-settle 时调用。\n *\n * 安全约束:\n * - toPersistedState() 用解构白名单剔除敏感字段,即使未来往 LiveState 加字段,\n * 未显式放行也不会落入 sessionStorage;\n * - runId 为 32-hex 不可猜标识,可安全持久化(/runs + /progress 的查询键)。\n */\nimport { ConflictCollector } from '../ui/conflict-view.ts'\nimport { DEFAULT_CATEGORIES, ExportFlow } from '../ui/export-flow.ts'\nimport type { ExportRunResult } from '../ui/export-flow.ts'\nimport { ImportWizard } from '../ui/import-wizard.ts'\nimport { renderExportReport } from '../ui/report.ts'\nimport type { ImportStep } from '../ui/types.ts'\nimport type { RunProgress } from './common/progress-view.ts'\nimport type {\n GlobalConflictStrategy, ImportAnalysis, ImportDecisions, ImportPlan, ImportResult,\n ItemResolution, PathMapping,\n} from '../core/types.ts'\nimport type { RunKind, RunState } from '../core/run-registry.ts'\nimport type { Manifest, SectionId } from '../schema/types.ts'\nimport type { ConfigManagerApi } from './api.ts'\n\n/* ---------------------------------------------------------------- 基础类型 */\n\n/** 主视图(ConfigManagerSection 的 tab 状态)。 */\nexport type MainView = 'export' | 'import'\n\n/** 导出模式。 */\nexport type ExportMode = 'quick' | 'custom'\n\n/** 存储抽象(浏览器 sessionStorage / 测试 mock / 无存储)。 */\nexport interface StoreStorage {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\n/** sessionStorage 键。 */\nexport const STATE_KEY = 'dsh.cfgMgr.state.v1'\n\n/** Custom 模式的初始勾选 = 推荐分区(可再调整) */\nexport function defaultCustomSelection(): SectionId[] {\n return DEFAULT_CATEGORIES\n .filter((c) => c.defaultIncluded)\n .map((c) => c.id)\n}\n\n/* ------------------------------------------------- 持久化(非敏感)状态形状 */\n\n/** 导出视图的持久化切片(不含 password/passwordConfirm)。 */\nexport interface PersistedExportState {\n mode: ExportMode\n selection: SectionId[]\n includeSecrets: boolean\n running: boolean\n progress: RunProgress | null\n result: ExportRunResult | null\n /** 错误消息(已 redact 的文本;Error 对象不可 JSON 序列化,统一转字符串) */\n error: string | null\n downloaded: boolean\n /** 最近一次导出 run id(/runs + /progress 重新订阅用;32-hex 不可猜) */\n runId: string | null\n}\n\n/** 导入向导的持久化切片(不含 secretInputs)。 */\nexport interface PersistedImportState {\n step: ImportStep\n zipPath: string | null\n /** select 步骤已选备份文件名(换选/取消选择的 UI 状态;非敏感) */\n selectedFileName: string | null\n analysis: ImportAnalysis | null\n plan: ImportPlan | null\n result: ImportResult | null\n rollbackOnError: boolean\n errors: string[]\n /** UI 层流程阶段(wizard.step 之外的页面;见 src/ui/flow.ts) */\n phase: FlowPhase\n conflictStrategy: GlobalConflictStrategy\n conflictResolutions: Record<string, ItemResolution>\n pathMappings: PathMapping[]\n uploading: boolean\n running: boolean\n progress: RunProgress | null\n error: string | null\n runId: string | null\n}\n\n/** 刷新恢复的顶层持久化状态(v1 结构版本)。 */\nexport interface PersistedState {\n v: 1\n view: MainView\n export: PersistedExportState\n import: PersistedImportState\n}\n\n/* --------------------------------------- 运行时状态(含仅内存的敏感字段) */\n\n/** 导出运行时状态 = 持久化字段 + 仅内存的密码字段。 */\nexport interface ExportLiveState extends PersistedExportState {\n /** 加密密码(仅内存,绝不写入 sessionStorage;刷新后清空) */\n password: string\n passwordConfirm: string\n}\n\n/** 导入运行时状态 = 持久化字段 + 仅内存的敏感/实例字段。 */\nexport interface ImportLiveState extends PersistedImportState {\n /** 秘密补录值(仅内存,绝不写入 sessionStorage;刷新后清空、secrets 阶段重输) */\n secretInputs: Record<string, string>\n /** 冲突决策收集器实例(仅内存;刷新后由 plan + conflictResolutions 重建) */\n conflictCollector: ConflictCollector | null\n}\n\n/** store 的完整运行时快照(getSnapshot 返回;含敏感字段,仅供组件读取)。 */\nexport interface StoreState {\n v: 1\n view: MainView\n export: ExportLiveState\n import: ImportLiveState\n}\n\n/** patch 的输入形状(浅合并对应切片)。 */\nexport interface StorePatch {\n view?: MainView\n export?: Partial<ExportLiveState>\n import?: Partial<ImportLiveState>\n}\n\n/** 向导 step 的类型别名(与 src/ui/types.ts 的 ImportStep 保持一致)。 */\ntype ImportWizardStep = ImportStep\n\n/** UI 层流程阶段(与 src/ui/flow.ts 的 FlowPhase 保持一致)。 */\ntype FlowPhase = 'preview' | 'conflicts' | 'path-mapping' | 'secrets' | 'confirm'\n\n/* ------------------------------------------------------------- 默认值 */\n\nfunction defaultExportState(): ExportLiveState {\n return {\n mode: 'quick',\n selection: defaultCustomSelection(),\n includeSecrets: false,\n password: '',\n passwordConfirm: '',\n running: false,\n progress: null,\n result: null,\n error: null,\n downloaded: false,\n runId: null,\n }\n}\n\nfunction defaultImportState(): ImportLiveState {\n return {\n step: 'select',\n zipPath: null,\n selectedFileName: null,\n analysis: null,\n plan: null,\n result: null,\n rollbackOnError: true,\n errors: [],\n phase: 'preview',\n conflictStrategy: 'merge',\n conflictResolutions: {},\n pathMappings: [],\n secretInputs: {},\n uploading: false,\n running: false,\n progress: null,\n error: null,\n runId: null,\n conflictCollector: null,\n }\n}\n\nfunction defaultState(): StoreState {\n return {\n v: 1,\n view: 'export',\n export: defaultExportState(),\n import: defaultImportState(),\n }\n}\n\n/* ------------------------------------------------- 序列化白名单(安全关键) */\n\n/**\n * 持久化白名单:解构剔除敏感字段(password/passwordConfirm/secretInputs)\n * 与不可序列化的实例字段(conflictCollector),其余原样落入 sessionStorage。\n * 这是 sessionStorage 的唯一写入路径 —— 敏感值在此被硬性隔离。\n */\nexport function toPersistedState(state: StoreState): PersistedState {\n const { password: _password, passwordConfirm: _passwordConfirm, ...exportRest } = state.export\n const { secretInputs: _secretInputs, conflictCollector: _conflictCollector, ...importRest } = state.import\n return { v: 1, view: state.view, export: exportRest, import: importRest }\n}\n\n/** 解析 + 轻量校验持久化状态;损坏/版本不符返回 null(调用方回退默认并清键)。 */\nexport function parsePersistedState(raw: string): PersistedState | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n return null\n }\n if (typeof parsed !== 'object' || parsed === null) return null\n const p = parsed as Record<string, unknown>\n if (p['v'] !== 1) return null\n const view = p['view']\n if (view !== 'export' && view !== 'import') return null\n const exp = p['export']\n const imp = p['import']\n if (typeof exp !== 'object' || exp === null || typeof imp !== 'object' || imp === null) return null\n return { v: 1, view, export: exp as PersistedExportState, import: imp as PersistedImportState }\n}\n\n/* ----------------------------------------------------- 控制器 rehydrate */\n\n/** ImportWizard 私有字段的镜像形状(仅供 writeWizardSnapshot 受控写入)。 */\ninterface WizardInternals {\n step: ImportWizardStep\n zipPath: string | null\n analysis: ImportAnalysis | null\n plan: ImportPlan | null\n result: ImportResult | null\n rollbackOnError: boolean\n errors: string[]\n decisions: ImportDecisions\n secretInputs: Record<string, string>\n}\n\n/**\n * 把 store 的导入快照写回 ImportWizard 控制器私有字段(受控 rehydrate)。\n * - 只写非敏感字段;secretInputs 恒置空 —— 刷新后 secrets 阶段要求重输;\n * - 仅在 load / hydrate / resume-settle 时调用,不参与正常交互路径。\n */\nfunction writeWizardSnapshot(wizard: ImportWizard, imp: ImportLiveState): void {\n const internals = wizard as unknown as WizardInternals\n internals.step = imp.step\n internals.zipPath = imp.zipPath\n internals.analysis = imp.analysis\n internals.plan = imp.plan\n internals.result = imp.result\n internals.rollbackOnError = imp.rollbackOnError\n internals.errors = [...imp.errors]\n internals.decisions = {\n strategy: imp.conflictStrategy,\n resolutions: { ...imp.conflictResolutions },\n pathMappings: imp.pathMappings.map((m) => ({ ...m, appliesTo: [...m.appliesTo] })),\n }\n internals.secretInputs = {}\n}\n\n/** 由 plan + 已持久化的决策重建 ConflictCollector(刷新恢复用)。 */\nexport function rebuildConflictCollector(\n plan: ImportPlan,\n resolutions: Record<string, ItemResolution>,\n): ConflictCollector {\n const collector = new ConflictCollector(plan)\n for (const [id, resolution] of Object.entries(resolutions)) {\n collector.resolve(id, resolution)\n }\n return collector\n}\n\n/**\n * RunState → RunProgress(m3 轮询进度回填)。\n * - step/total = 内部计数(百分比条按 item/itemTotal 推进);\n * - section/sectionTotal 与 item/itemTotal 单独保留给分区徽章/内部计数徽章;\n * - detail = 当前项名(导出时恒为分区名,ProgressBar 侧会去冗余)。\n */\nfunction mapRunProgress(kind: RunKind, state: RunState): RunProgress {\n return {\n stage: kind === 'export' ? 'exporting' : 'executing',\n detail: state.detail ?? undefined,\n step: state.item ?? undefined,\n total: state.itemTotal ?? undefined,\n section: state.section,\n sectionTotal: state.sectionTotal,\n item: state.item,\n itemTotal: state.itemTotal,\n }\n}\n\n/* ------------------------------------------------------------------- store */\n\nexport interface RunStoreOptions {\n /** 存储提供者;缺省 = window.sessionStorage(Node/无 window 时为 null) */\n storage?: StoreStorage | null\n /** 进度轮询间隔(测试注入小值;缺省 1000ms) */\n pollIntervalMs?: number\n}\n\nfunction defaultStorage(): StoreStorage | null {\n if (typeof window === 'undefined') return null\n try {\n return window.sessionStorage ?? null\n } catch {\n return null\n }\n}\n\n/**\n * 模块级单例 store:控制器实例 + React UI 状态 + sessionStorage 恢复。\n * 最小接口:subscribe / getSnapshot / load / save / patch / syncWizard /\n * exportFlow / importWizard / resume / stopResume。\n */\nexport class RunStore {\n private readonly storage: StoreStorage | null\n private readonly pollIntervalMs: number\n private readonly listeners = new Set<() => void>()\n private state: StoreState\n private exportFlowInst: ExportFlow | null = null\n private importWizardInst: ImportWizard | null = null\n private apiRef: ConfigManagerApi | null = null\n /** 正在轮询的 runId 集合(stopResume 清空;防重复订阅) */\n private readonly polling = new Set<string>()\n /** 每个 runId 至多一个挂起的轮询定时器(fire 后由下一次调度覆盖) */\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>()\n /** 正在「发现进行中 run」的 kind 集合(watchRunning 活动标记;stopRunWatch/stopResume 清空) */\n private readonly watchActive = new Set<RunKind>()\n\n constructor(opts: RunStoreOptions = {}) {\n this.storage = opts.storage !== undefined ? opts.storage : defaultStorage()\n this.pollIntervalMs = opts.pollIntervalMs ?? 1000\n this.state = defaultState()\n this.load()\n }\n\n /* ------------------------------------------------------------- 订阅 */\n\n /**\n * 订阅 store 变化(useSyncExternalStore 的 subscribe)。\n *\n * 必须为箭头函数类字段:React 以裸引用(`runStore.subscribe`)调用它,\n * 无接收者,若为原型方法则 `this` 为 undefined,`this.listeners` 直接崩溃。\n */\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n /**\n * 当前完整快照(引用稳定:仅在 patch 后替换,适合 useSyncExternalStore)。\n *\n * 必须为箭头函数类字段:React 以裸引用(`runStore.getSnapshot`)调用它,\n * 无接收者,若为原型方法则 `this` 为 undefined,`this.state` 抛 TypeError,\n * 导致整个 settings.section 槽位渲染崩溃(备份与迁移页空白)。\n */\n getSnapshot = (): StoreState => this.state\n\n private notify(): void {\n for (const listener of this.listeners) listener()\n }\n\n /* ------------------------------------------------------- 状态更新 */\n\n /** 浅合并补丁并立即持久化(保存走白名单,敏感字段不落盘)。 */\n patch(patchObj: StorePatch): void {\n this.state = {\n ...this.state,\n view: patchObj.view ?? this.state.view,\n export: { ...this.state.export, ...patchObj.export },\n import: { ...this.state.import, ...patchObj.import },\n }\n this.notify()\n this.save()\n }\n\n /** 把 ImportWizard 控制器的 snapshot() 镜像进 store(wizard 动作后调用)。 */\n syncWizard(): void {\n const wizard = this.importWizardInst\n if (wizard === null) return\n const snap = wizard.snapshot()\n this.patch({\n import: {\n step: snap.step,\n zipPath: snap.zipPath,\n analysis: snap.analysis,\n plan: snap.plan,\n result: snap.result,\n rollbackOnError: snap.rollbackOnError,\n errors: snap.errors,\n },\n })\n }\n\n /* ------------------------------------------------------ 持久化 load/save */\n\n /** 从存储恢复非敏感状态(构造时调用一次;损坏数据回退默认并清键)。 */\n load(): void {\n if (this.storage === null) return\n let raw: string | null = null\n try {\n raw = this.storage.getItem(STATE_KEY)\n } catch {\n return\n }\n if (raw === null || raw === '') {\n this.state = defaultState()\n return\n }\n const parsed = parsePersistedState(raw)\n if (parsed === null) {\n // 损坏/版本不符:清掉脏键,回退默认\n try {\n this.storage.removeItem(STATE_KEY)\n } catch {\n // 忽略存储错误\n }\n this.state = defaultState()\n return\n }\n this.applyPersisted(parsed)\n }\n\n /** 把解析后的持久化状态合并进运行时状态;敏感字段强制回到默认(清空)。 */\n private applyPersisted(parsed: PersistedState): void {\n this.state = {\n v: 1,\n view: parsed.view,\n export: {\n ...defaultExportState(),\n ...parsed.export,\n // 硬性:密码/确认密码绝不从存储恢复\n password: '',\n passwordConfirm: '',\n },\n import: {\n ...defaultImportState(),\n ...parsed.import,\n // 旧版持久化载荷可能缺 selectedFileName(undefined)→ 归一到 null\n selectedFileName: parsed.import.selectedFileName ?? null,\n // 硬性:秘密补录值绝不从存储恢复;collector 由 plan+决策重建\n secretInputs: {},\n conflictCollector: null,\n },\n }\n // 安全兜底:confirm 阶段若仍缺必填 secret(刷新后 secretInputs 必为空),\n // 强制退回 secrets 阶段要求重输(验收 m2-refresh 的「secrets 阶段要求重输」)。\n const missing = this.state.import.plan?.missingSecrets ?? []\n if (this.state.import.phase === 'confirm' && missing.length > 0) {\n this.state.import.phase = 'secrets'\n }\n // 冲突阶段:由恢复后的 plan + 决策重建 collector(刷新后实例必然丢失)\n const imp = this.state.import\n if (imp.phase === 'conflicts' && imp.plan !== null) {\n imp.conflictCollector = rebuildConflictCollector(imp.plan, imp.conflictResolutions)\n }\n }\n\n /** 把非敏感状态写入 sessionStorage(白名单序列化;无存储时为空操作)。 */\n save(): void {\n if (this.storage === null) return\n try {\n this.storage.setItem(STATE_KEY, JSON.stringify(toPersistedState(this.state)))\n } catch {\n // 存储满/不可用:静默降级,状态仍完整存在于内存\n }\n }\n\n /* ---------------------------------------------------- 控制器实例(缓存) */\n\n /** ExportFlow 控制器实例:懒创建 + 缓存(切 tab/关面板不重建)。 */\n exportFlow(api: ConfigManagerApi): ExportFlow {\n if (this.exportFlowInst === null) {\n if (this.apiRef === null) this.apiRef = api\n this.exportFlowInst = new ExportFlow({\n port: api,\n onProgress: (event) => { this.patch({ export: { progress: event } }) },\n })\n }\n return this.exportFlowInst\n }\n\n /** ImportWizard 控制器实例:懒创建 + 缓存;首次创建时从持久化快照 rehydrate。 */\n importWizard(api: ConfigManagerApi): ImportWizard {\n if (this.importWizardInst === null) {\n if (this.apiRef === null) this.apiRef = api\n const wizard = new ImportWizard({\n port: api,\n onProgress: (event) => { this.patch({ import: { progress: event } }) },\n defaultRollbackOnError: true,\n })\n // 刷新恢复:把持久化快照写回控制器(仅非敏感字段;secretInputs 置空)\n writeWizardSnapshot(wizard, this.state.import)\n this.importWizardInst = wizard\n }\n return this.importWizardInst\n }\n\n /* ------------------------------------------------- m2-resume:run 重订阅 */\n\n /**\n * 重新订阅进行中的 run:GET /runs 找回活跃 runId → 轮询 /progress 直到\n * 完成/失败,把 RunState.result 回填 store(导出结果 / 导入结果均可恢复)。\n * 返回是否有 run 被恢复。幂等:同一 runId 不会重复轮询。\n */\n async resume(api: ConfigManagerApi): Promise<boolean> {\n if (this.apiRef === null) this.apiRef = api\n let active: RunState[]\n try {\n active = await api.runs()\n } catch {\n // host 不可达:保持现状,不做破坏性重置\n return false\n }\n let resumed = false\n const exportRun = active.find((r) => r.kind === 'export')\n if (exportRun !== undefined) {\n resumed = true\n this.patch({\n export: {\n running: true,\n runId: exportRun.runId,\n progress: mapRunProgress('export', exportRun),\n },\n })\n this.pollRun(exportRun.runId, 'export')\n } else if (this.state.export.running) {\n // 持久化显示导出中,但 host 无活跃导出 run:请求已结束且响应丢失,不可恢复\n this.patch({\n export: {\n running: false,\n progress: null,\n runId: null,\n error: '上次导出任务已结束但结果无法恢复,请重新导出',\n },\n })\n }\n\n const importRun = active.find((r) => r.kind === 'import')\n if (importRun !== undefined) {\n resumed = true\n this.patch({\n import: {\n running: true,\n runId: importRun.runId,\n step: 'importing',\n progress: mapRunProgress('import', importRun),\n },\n })\n this.pollRun(importRun.runId, 'import')\n } else if (this.state.import.step === 'importing') {\n // 持久化显示导入中,但 host 无活跃导入 run:任务已结束/被清理,结果不可恢复\n this.importWizardInst?.reset()\n this.patch({\n import: {\n step: 'select',\n phase: 'preview',\n runId: null,\n running: false,\n progress: null,\n conflictCollector: null,\n selectedFileName: null,\n errors: [],\n error: '上次导入任务已结束或超过保留期,结果无法恢复,请重新导入',\n },\n })\n }\n return resumed\n }\n\n /** 停止全部轮询(视图卸载时调用;服务端执行不受影响,重开面板再 resume)。 */\n stopResume(): void {\n this.polling.clear()\n this.watchActive.clear()\n for (const timer of this.timers.values()) clearTimeout(timer)\n this.timers.clear()\n }\n\n /* ------------------------------------- m3:本次会话内启动 run 的实时轮询 */\n\n /**\n * 本次会话内启动的 run(POST /export 或 /execute 请求进行期间)的实时进度订阅。\n * 请求是同步的、响应到达才知 runId,所以先经 GET /runs 发现进行中的 run(500ms),\n * 发现后转入 /progress 轮询(同一间隔),done/failed 自动停止。\n *\n * 与 m2 resume 的收敛:两者共用 pollRun / polling / timers 同一套轮询器,\n * 只是间隔不同(resume 恢复 1s、本方法实时 500ms)且发现阶段不同\n * (resume 用 /runs 一次性找回 runId;本方法持续 /runs 直到出现活跃 run)。\n * 同一 runId 不会重复轮询(polling 集合防重)。\n */\n watchRunning(kind: RunKind, intervalMs?: number): void {\n if (this.watchActive.has(kind)) return\n this.watchActive.add(kind)\n const api = this.apiRef\n if (api === null) {\n this.watchActive.delete(kind)\n return\n }\n const interval = intervalMs ?? this.pollIntervalMs\n const tick = (): void => {\n if (!this.watchActive.has(kind)) return\n void api.runs().then(\n (active) => {\n if (!this.watchActive.has(kind)) return\n const run = active.find((r) => r.kind === kind && r.status === 'running')\n if (run === undefined) {\n // 请求尚未注册 run / 已瞬间结束:继续发现,直到视图 stop 或转入 /progress\n this.scheduleWatch(kind, tick, interval)\n return\n }\n // 发现进行中 run:停止发现,交给 /progress 轮询器(同一间隔)\n this.watchActive.delete(kind)\n this.patchProgress(kind, run)\n this.pollRun(run.runId, kind, interval)\n },\n () => {\n if (this.watchActive.has(kind)) this.scheduleWatch(kind, tick, interval)\n },\n )\n }\n this.scheduleWatch(kind, tick, interval)\n }\n\n /** 停止某 kind 的「发现进行中 run」轮询(视图请求结束后调用;/progress 轮询自行结束)。 */\n stopRunWatch(kind: RunKind): void {\n this.watchActive.delete(kind)\n }\n\n /** 调度下一轮发现;每 kind 只保留一个挂起定时器。 */\n private scheduleWatch(kind: RunKind, tick: () => void, intervalMs: number): void {\n const timer = setTimeout(tick, intervalMs)\n this.timers.set(`watch:${kind}`, timer)\n }\n\n private pollRun(runId: string, kind: RunKind, intervalMs?: number): void {\n if (this.polling.has(runId)) return\n this.polling.add(runId)\n const api = this.apiRef\n if (api === null) return\n const interval = intervalMs ?? this.pollIntervalMs\n const tick = (): void => {\n if (!this.polling.has(runId)) return\n void api.progress(runId).then(\n (state) => {\n if (!this.polling.has(runId)) return\n if (state.status === 'running') {\n this.patchProgress(kind, state)\n this.scheduleTick(runId, tick, interval)\n } else {\n this.polling.delete(runId)\n this.applySettled(kind, state)\n }\n },\n () => {\n // 404(过保留期)/网络错误:run 不可恢复,停止轮询并如实提示\n this.polling.delete(runId)\n this.applyGone(kind)\n },\n )\n }\n this.scheduleTick(runId, tick, interval)\n }\n\n /** 调度下一轮询;每 runId 只保留一个挂起定时器(fire 后由下一次调度覆盖)。 */\n private scheduleTick(runId: string, tick: () => void, intervalMs: number): void {\n const timer = setTimeout(tick, intervalMs)\n this.timers.set(runId, timer)\n }\n\n private patchProgress(kind: RunKind, state: RunState): void {\n const event = mapRunProgress(kind, state)\n if (kind === 'export') this.patch({ export: { progress: event } })\n else this.patch({ import: { progress: event } })\n }\n\n /** run 完成/失败:把 RunState.result 回填 store(并镜像回控制器)。 */\n private applySettled(kind: RunKind, state: RunState): void {\n if (kind === 'export') {\n const result = state.result as\n | { zipPath: string; manifest: Manifest; report: ExportRunResult['report'] }\n | undefined\n if (state.status === 'done' && result !== undefined && typeof result.zipPath === 'string') {\n this.patch({\n export: {\n running: false,\n progress: { stage: 'done', step: 1, total: 1 },\n result: { ...result, text: renderExportReport(result.report) },\n downloaded: false,\n },\n })\n } else {\n this.patch({\n export: {\n running: false,\n progress: null,\n result: null,\n downloaded: false,\n error: state.error ?? '导出失败(结果不可用)',\n },\n })\n }\n return\n }\n // import\n const result = state.result as ImportResult | undefined\n if (state.status === 'done' && result !== undefined && typeof result === 'object') {\n const wizard = this.importWizardInst\n if (wizard !== null) {\n const imp: ImportLiveState = {\n ...this.state.import,\n step: 'result',\n result,\n secretInputs: {},\n conflictCollector: null,\n }\n writeWizardSnapshot(wizard, imp)\n }\n this.patch({\n import: {\n step: 'result',\n result,\n running: false,\n progress: { stage: 'done', step: 1, total: 1 },\n error: null,\n },\n })\n } else {\n const wizard = this.importWizardInst\n if (wizard !== null) {\n const internals = wizard as unknown as WizardInternals\n internals.errors = [...internals.errors, state.error ?? '导入失败']\n }\n this.patch({\n import: {\n running: false,\n progress: null,\n error: state.error ?? '导入失败',\n errors: [...this.state.import.errors, state.error ?? '导入失败'],\n },\n })\n }\n }\n\n /** run 消失(404/网络错误):停止轮询并提示不可恢复。 */\n private applyGone(kind: RunKind): void {\n if (kind === 'export') {\n this.patch({\n export: {\n running: false,\n progress: null,\n runId: null,\n error: '任务已结束或超过保留期,进度不可恢复',\n },\n })\n } else {\n this.importWizardInst?.reset()\n this.patch({\n import: {\n running: false,\n progress: null,\n runId: null,\n step: 'select',\n phase: 'preview',\n conflictCollector: null,\n selectedFileName: null,\n errors: [],\n error: '任务已结束或超过保留期,进度不可恢复',\n },\n })\n }\n }\n}\n\n/** 模块级单例(浏览器半所有视图共享;构造时自动 load())。 */\nexport const runStore = new RunStore()\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 * 可操作错误展示(规范 §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 * m3: 进度展示的纯逻辑层(框架无关,node 可测)。\n *\n * 背景:m1 的 RunState 携带真实进度(section/sectionTotal = 当前分区 3/12、\n * item/itemTotal = 内部计数如插件 6/18、detail = 当前项名);m2 的 store 把\n * RunState 映射为 ProgressEvent 并存入 progress 字段。本模块定义客户端的\n * RunProgress(ProgressEvent 超集,额外携带分区/内部计数,JSON 可序列化),\n * 并提供 computeProgressView() 把进度事件转成渲染模型 —— ProgressBar 只做\n * 纯渲染,所有判定逻辑集中在此、可单测。\n *\n * 兼容路径:无 section/item 的普通 ProgressEvent(控制器 onProgress 发出)\n * 走原逻辑 —— 阶段文案 + step/total 百分比,无徽章。\n */\nimport { stageText } from '../../ui/progress.ts'\nimport { zhUiT, type UiT } from '../../ui/i18n.ts'\nimport type { ProgressEvent } from '../../ui/types.ts'\n\n/** m3: 客户端进度事件 = ProgressEvent 超集(RunState 轮询映射产物;可 JSON 序列化)。 */\nexport interface RunProgress extends ProgressEvent {\n /** 当前分区(adapter id / 阶段名)与分区总数(如 settings · 3/12);导入无此语义为 null */\n section?: string | null\n sectionTotal?: number | null\n /** 内部计数(如插件 6/18;导出 = 分区序号,导入 = 已处理计划项数) */\n item?: number | null\n itemTotal?: number | null\n}\n\n/** 徽章渲染数据(label · current/total)。 */\nexport interface ProgressBadge {\n label: string\n current: number\n total: number\n}\n\n/** ProgressBar 的渲染模型(纯数据,测试断言用)。 */\nexport interface ProgressView {\n /** 阶段文案(stageText) */\n label: string\n /** 百分比(step/total;无则 null = 不定态动画) */\n percent: number | null\n /** 当前分区徽章(settings · 3/12) */\n sectionBadge: ProgressBadge | null\n /** 内部计数徽章(plugins · 6/18;导出时与分区计数同源则去冗余) */\n countBadge: ProgressBadge | null\n /** 当前项名(detail;与分区名相同时去冗余) */\n detail: string | null\n}\n\n/**\n * 把进度事件换算成渲染模型。\n * - percent:优先 ProgressEvent.step/total(控制器阶段进度 / 轮询的内部计数);\n * - sectionBadge(当前分区,如 settings · 3/12):label=分区 id、current=item\n * (1-based 分区序号,见 core exporter onSection)、total=sectionTotal;\n * - countBadge(内部计数,如 plugins · 6/18):label=分区 id、current=item、\n * total=itemTotal;导出时 itemTotal 与 sectionTotal 同值(分区序号即内部计数)\n * → 置 null,避免「3/12 3/12」重复;\n * - detail(当前项名):非空且不等于分区 id(导出时 detail 恒为分区 id,去冗余)。\n */\nexport function computeProgressView(event: RunProgress | null, t: UiT = zhUiT): ProgressView {\n if (event === null) {\n return { label: '', percent: null, sectionBadge: null, countBadge: null, detail: null }\n }\n const section = event.section ?? null\n const sectionTotal = event.sectionTotal ?? null\n const item = event.item ?? null\n const itemTotal = event.itemTotal ?? null\n\n const percent =\n event.step !== undefined && event.total !== undefined && event.total > 0\n ? Math.round((event.step / event.total) * 100)\n : item !== null && itemTotal !== null && itemTotal > 0\n ? Math.round((item / itemTotal) * 100)\n : null\n\n const sectionBadge: ProgressBadge | null =\n section !== null && item !== null && sectionTotal !== null && sectionTotal > 0\n ? { label: section, current: item, total: sectionTotal }\n : null\n\n let countBadge: ProgressBadge | null =\n section !== null && item !== null && itemTotal !== null && itemTotal > 0\n ? { label: section, current: item, total: itemTotal }\n : null\n if (countBadge !== null && sectionBadge !== null && itemTotal === sectionTotal) {\n // 导出:item/itemTotal 与 section/sectionTotal 同源(当前分区序号),去冗余\n countBadge = null\n }\n\n const detail =\n typeof event.detail === 'string' && event.detail !== '' && event.detail !== section\n ? event.detail\n : null\n\n return { label: stageText(event.stage, t), percent, sectionBadge, countBadge, detail }\n}\n","/**\n * 进度条(规范 §29 + m3 真实进度)。\n *\n * 数据流:\n * - 控制器(ExportFlow / ImportWizard)onProgress 发出普通 ProgressEvent\n * (阶段文案 + step/total),走兼容路径;\n * - m3:store 经 /runs + /progress 轮询得到的 RunState 映射为 RunProgress\n * (额外携带 section/sectionTotal/item/itemTotal/detail),渲染为\n * 「分区徽章(settings · 3/12)+ 内部计数徽章(plugins · 6/18)+ 当前项名」。\n *\n * 所有换算逻辑在 progress-view.ts 的 computeProgressView()(纯函数,可单测);\n * 本组件只做渲染。未知阶段回退显示 id 本身。\n */\nimport { computeProgressView } from './progress-view.ts'\nimport type { RunProgress } from './progress-view.ts'\nimport css from '../config-manager.module.css'\n\nexport interface ProgressBarProps {\n /** 当前进度事件(null = 未开始);普通 ProgressEvent 亦兼容 */\n event: RunProgress | null\n /** 是否正在执行(false 时显示为完成态) */\n active: boolean\n}\n\n/**\n * 进度条:阶段文字 + 分区/内部计数徽章 + 当前项名 + 百分比。\n */\nexport function ProgressBar({ event, active }: ProgressBarProps) {\n const view = computeProgressView(event)\n\n return (\n <div className={css.progressBlock}>\n <div className={css.progressMeta}>\n <span className={css.progressLabel}>{view.label}</span>\n {view.sectionBadge !== null && (\n <span className={`${css.progressBadge} ${css.progressBadgeSection}`}>\n {view.sectionBadge.label} · {view.sectionBadge.current}/{view.sectionBadge.total}\n </span>\n )}\n {view.countBadge !== null && (\n <span className={`${css.progressBadge} ${css.progressBadgeCount}`}>\n {view.countBadge.label !== '' ? `${view.countBadge.label} · ` : ''}\n {view.countBadge.current}/{view.countBadge.total}\n </span>\n )}\n {view.detail !== null && <span className={css.progressDetail}>{view.detail}</span>}\n {view.percent !== null && <span className={css.progressPercent}>{view.percent}%</span>}\n </div>\n <div className={css.progressTrack}>\n {view.percent !== null ? (\n <div\n className={`${css.progressBar} ${active ? '' : css.progressBarDone}`}\n style={{ width: `${view.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 * **也绝不进入 sessionStorage** —— m2 白名单剔除,刷新后要求重输);\n * - 进度:ExportFlow.run 发出 ProgressEvent → ProgressBar;\n * - 结果:ReportView(export) + 下载按钮(File System Access API 流式落盘)。\n *\n * m2:全部 UI 状态由模块级 runStore 持有(切 tab/关面板不重建、刷新恢复),\n * 控制器实例(ExportFlow)由 store 缓存复用。\n */\nimport { useCallback, useSyncExternalStore } from 'react'\nimport type { ChangeEvent } from 'react'\nimport { EXPORT_GROUPS } 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 { runStore, type ExportMode } from '../run-store.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\n/**\n * 导出主视图:Quick/Custom 切换 → 勾选/密码 → 执行 → 进度 → 报告 → 下载。\n */\nexport function ExportView({ api, t }: ExportViewProps) {\n // m2:状态统一来自模块级 store(sessionStorage 持久化;切 tab 不重建)\n const state = useSyncExternalStore(runStore.subscribe, runStore.getSnapshot)\n const exp = state.export\n // 控制器实例由 store 缓存复用(切 tab / 关面板不重建)\n const flow = runStore.exportFlow(api)\n\n const mode = exp.mode\n const selection = exp.selection\n const includeSecrets = exp.includeSecrets\n // 密码字段仅内存(store 的敏感字段,绝不序列化进 sessionStorage)\n const password = exp.password\n const passwordConfirm = exp.passwordConfirm\n const running = exp.running\n const progress = exp.progress\n const result = exp.result\n const error = exp.error\n const downloaded = exp.downloaded\n\n const setMode = (next: ExportMode): void => {\n runStore.patch({ export: { mode: next } })\n }\n const setIncludeSecrets = (next: boolean): void => {\n runStore.patch({ export: { includeSecrets: next } })\n }\n const setPassword = (value: string): void => {\n runStore.patch({ export: { password: value } })\n }\n const setPasswordConfirm = (value: string): void => {\n runStore.patch({ export: { passwordConfirm: value } })\n }\n\n const toggleSection = useCallback((id: SectionId, checked: boolean): void => {\n const has = selection.includes(id)\n if (checked && !has) runStore.patch({ export: { selection: [...selection, id] } })\n if (!checked && has) runStore.patch({ export: { selection: selection.filter((s) => s !== id) } })\n }, [selection])\n\n const passwordInvalid =\n includeSecrets && (password === '' || password !== passwordConfirm)\n\n /** 执行导出(Quick 或 Custom) */\n const runExport = async (): Promise<void> => {\n if (passwordInvalid) return\n runStore.patch({\n export: { running: true, error: null, result: null, downloaded: false, progress: null, runId: null },\n })\n // m3:请求进行期间经 /runs 发现 runId 并轮询 /progress(500ms)显示真实进度\n runStore.watchRunning('export', 500)\n try {\n // 加密密码随本次导出请求体传给 Host 半(仅内存)\n api.exportPassword = includeSecrets ? password : null\n const run = await flow.run(mode, selection, { includeSecrets })\n // ExportResponse 携带 runId(/progress 查询与刷新恢复用);控制器类型不含,运行时对象有\n const runId = (run as { runId?: unknown }).runId\n runStore.patch({\n export: {\n result: run,\n runId: typeof runId === 'string' ? runId : null,\n progress: { stage: 'done', step: 1, total: 1 },\n },\n })\n } catch (err) {\n runStore.patch({ export: { error: err instanceof Error ? err.message : String(err) } })\n } finally {\n runStore.stopRunWatch('export')\n runStore.patch({ export: { running: false } })\n }\n }\n\n /** 下载导出的 ZIP 到本机 */\n const download = async (): Promise<void> => {\n if (result === null) return\n try {\n runStore.patch({ export: { error: null } })\n const outcome = await api.download(result.zipPath)\n runStore.patch({ export: { downloaded: true } })\n void outcome // blob/streamed 由 api 处理;此处仅确认成功\n } catch (err) {\n runStore.patch({ export: { error: err instanceof Error ? err.message : String(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 * 导入向导的 UI 流程阶段(覆盖在 wizard.step === 'preview' 之上)与导航。\n *\n * 注意:hasConflicts / hasPathIssues / hasSecrets 来自 Dry Run 的原始\n * analysis/plan,流程中不会因用户已解决而重算——因此导航必须是「只前进」\n * (按适用阶段有序列表推进),绝不能靠“当前阶段 != X 且 hasX”判定:\n * 那会让已经过的阶段被重新命中,点「下一步」反而跳回上一步。\n */\n\n/** 中间流程阶段(wizard.step 之外的 UI 层页面) */\nexport type FlowPhase = 'preview' | 'conflicts' | 'path-mapping' | 'secrets' | 'confirm'\n\n/**\n * 计算下一阶段:在 `list`(适用阶段的有序列表)中取 `from` 的下一项。\n * - `from` 不在列表中(如来自 preview 页)→ 取第一项;\n * - `from` 已是最后一项(confirm)→ 原地返回;\n * - 绝不回退:已完成阶段不会因仍适用而被再次命中。\n */\nexport function nextFlowPhase(list: FlowPhase[], from: FlowPhase): FlowPhase {\n if (list.length === 0) return 'confirm'\n const idx = list.indexOf(from)\n const next = list[Math.min(idx + 1, list.length - 1)]\n return next ?? 'confirm'\n}\n","/**\n * 冲突决策列表(规范 §11,绑 src/ui/conflict-view.ts 的 ConflictCollector)。\n *\n * 渲染 plan 中 kind === 'Conflict' 的项,用户逐项选择\n * Keep Current / Use Imported;决策实时写入 collector,\n * 完成时父组件调用 collector.toResolutions() → wizard.setResolutions()。\n *\n * 注意:不提供 \"Review(稍后决定)\" 选项——Review 会被收集器计为\n * unresolved,导致「下一步」永远禁用(死路)。要么决策,要么不进入本步。\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]\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')}\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 * 导入文件选择(select 步骤)的纯渲染/流转模型(import-file-reselection)。\n *\n * 修复的 bug:导入向导选择文件后无法取消/换选 —— 没有入口,且文件 input 的\n * value 未清空(同一文件再次选择不触发 onChange)。\n *\n * 与 src/client/sync/sync-view.ts 同模式:无副作用纯函数,node --test 直接测,\n * React 组件只做装配与 DOM 副作用(input value 的读写经 consumePickedFile\n * 收敛,传入真实 e.target 即可)。换选不变式:每次 onChange 都以最新选中的\n * 文件为准 —— 提交的永远是最新选中的文件。\n */\nimport type { ConfigManagerKey } from '../locales.ts'\n\n/** select 步骤的展示/流转模型。 */\nexport interface FileSelectModel {\n /** 已选备份文件名(null = 尚未选择) */\n selectedName: string | null\n /** 上传/分析进行中(浏览按钮禁用;仍可取消) */\n busy: boolean\n}\n\n/** 由 store 状态推导 select 步骤的展示模型(selectedFileName + uploading)。 */\nexport function fileSelectModel(selectedName: string | null, busy: boolean): FileSelectModel {\n return { selectedName, busy }\n}\n\n/**\n * 处理文件选择(input onChange 入口):\n * - **恒清空 input 的 value** —— 同一文件再次选择也会触发 onChange(同文件换选);\n * - 返回选中的文件;用户关闭文件对话框(无文件)返回 undefined。\n * input 以最小接口 `{ value: string }` 传入,纯逻辑可测;React 侧传真实 e.target。\n */\nexport function consumePickedFile(file: File | undefined, input: { value: string } | null): File | undefined {\n if (input !== null) input.value = ''\n return file\n}\n\n/**\n * 选中/换选后的状态:以新文件替换旧选择(提交的永远是最新选中的文件);\n * 未选文件(对话框取消)保持原状态不变。\n */\nexport function applyPickedFile(current: FileSelectModel, file: File | undefined): FileSelectModel {\n if (file === undefined) return current\n return { selectedName: file.name, busy: true }\n}\n\n/** 取消选择:清空选择与忙碌态(回 idle;UI 同时清空 input value 保证同文件可重选)。 */\nexport function cancelSelection(current: FileSelectModel): FileSelectModel {\n return { selectedName: null, busy: false }\n}\n\n/** 浏览按钮文案键:已选文件 → 重新选择;否则 → 选择 ZIP 文件。 */\nexport function browseLabelKey(hasSelection: boolean): ConfigManagerKey {\n return hasSelection ? 'import.select.reselect' : 'import.select.browse'\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 * **也绝不进入 sessionStorage**(m2 白名单剔除,刷新后 secrets 阶段要求重输);\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 *\n * m2:全部 UI 状态由模块级 runStore 持有(切 tab/关面板不重建、刷新恢复),\n * 控制器实例(ImportWizard)由 store 缓存复用;每次 wizard 动作后 syncWizard()\n * 把控制器快照镜像进 store(非敏感字段持久化)。\n */\nimport { useRef, useState } from 'react'\nimport type { ChangeEvent } from 'react'\nimport { useSyncExternalStore } from 'react'\nimport { ConflictCollector } from '../../ui/conflict-view.ts'\nimport { nextFlowPhase, type FlowPhase } from '../../ui/flow.ts'\nimport type { ImportPreviewSummary } from '../../ui/types.ts'\nimport type { ConfigManagerApi, UploadResponse } from '../api.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport { runStore } from '../run-store.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 {\n applyPickedFile, browseLabelKey, cancelSelection, consumePickedFile, fileSelectModel,\n} from './import-file-select.ts'\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 层页面)——定义见 src/ui/flow.ts */\n\nconst SCORE_LABEL: Record<string, string> = {\n excellent: 'Excellent',\n good: 'Good',\n partial: 'Partial',\n unsupported: 'Unsupported',\n}\n\n/** 密钥补录表单(仅内存收集,值不外泄;onChange 写入 store 的仅内存字段) */\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 // m2:状态统一来自模块级 store;控制器实例由 store 缓存复用(不重建)\n const state = useSyncExternalStore(runStore.subscribe, runStore.getSnapshot)\n const imp = state.import\n const wizard = runStore.importWizard(api)\n\n const step = imp.step\n const phase = imp.phase\n const progress = imp.progress\n const error = imp.error\n const uploading = imp.uploading\n const running = imp.running\n const rollbackOnError = imp.rollbackOnError\n const conflictCollector = imp.conflictCollector\n const pathMappings = imp.pathMappings\n const secretInputs = imp.secretInputs\n const fileInput = useRef<HTMLInputElement | null>(null)\n /**\n * 选择代数(取消选择时递增):作废在途的选择上传/分析,\n * 防止「取消后旧请求仍把向导推进/写错误」的竞态。\n */\n const pickGeneration = useRef(0)\n\n const setPhase = (next: FlowPhase): void => {\n runStore.patch({ import: { phase: next } })\n }\n\n /* ---------- 阶段判定 ---------- */\n\n const hasConflicts = (imp.plan?.items ?? []).some((i) => i.kind === 'Conflict')\n const hasPathIssues = (imp.analysis?.pathIssues.length ?? 0) > 0\n const hasSecrets = (imp.plan?.missingSecrets.length ?? 0) > 0\n\n /**\n * 适用阶段的有序列表(仅含需要用户处理 + 确认页)。\n * hasConflicts/hasPathIssues/hasSecrets 基于原始 analysis/plan(Dry Run 产物),\n * 在流程中不会因已解决而重算——所以导航必须只前进(见 nextFlowPhase),\n * 而不是靠\"当前阶段 != X\"判定(那会让已完成阶段被重新命中、跳回上一步)。\n */\n const applicablePhases = (): FlowPhase[] => {\n const list: FlowPhase[] = []\n if (hasConflicts) list.push('conflicts')\n if (hasPathIssues) list.push('path-mapping')\n if (hasSecrets) list.push('secrets')\n list.push('confirm')\n return list\n }\n\n /** 从某阶段完成后进入的下一个阶段:只前进(from 不在列表时取第一项) */\n const nextPhase = (from: FlowPhase): FlowPhase => nextFlowPhase(applicablePhases(), from)\n\n /* ---------- 动作 ---------- */\n\n /** 选择并上传 ZIP → wizard.selectZip(analyzing → compatibility)。\n * 换选不变式:每次选择都以最新文件为准(applyPickedFile 替换旧选择);\n * pickGeneration 守卫作废取消后在途的旧请求。 */\n const onPickFile = async (file: File | undefined): Promise<void> => {\n if (file === undefined) return\n const generation = pickGeneration.current\n const next = applyPickedFile(fileSelectModel(imp.selectedFileName, uploading), file)\n runStore.patch({ import: { uploading: next.busy, error: null, selectedFileName: next.selectedName } })\n try {\n const uploaded: UploadResponse = await api.upload(file)\n if (generation !== pickGeneration.current) return // 用户已取消本次选择\n const analysis = await wizard.selectZip(uploaded.zipPath)\n void analysis\n if (generation !== pickGeneration.current) return\n runStore.syncWizard()\n } catch (err) {\n if (generation !== pickGeneration.current) return\n runStore.patch({ import: { error: err instanceof Error ? err.message : String(err) } })\n runStore.syncWizard()\n } finally {\n if (generation === pickGeneration.current) {\n runStore.patch({ import: { uploading: false } })\n }\n }\n }\n\n /** 取消当前选择:回 idle 并清空 input value(同一文件可再次选择触发 onChange)。 */\n const cancelPick = (): void => {\n pickGeneration.current += 1\n const idle = cancelSelection(fileSelectModel(imp.selectedFileName, uploading))\n runStore.patch({ import: { selectedFileName: idle.selectedName, uploading: idle.busy, error: null } })\n if (fileInput.current !== null) fileInput.current.value = ''\n }\n\n /** Compatibility → Preview */\n const goPreview = async (): Promise<void> => {\n runStore.patch({ import: { error: null } })\n try {\n await wizard.confirmCompatibility()\n runStore.syncWizard()\n } catch (err) {\n runStore.patch({ import: { error: err instanceof Error ? err.message : String(err) } })\n runStore.syncWizard()\n }\n }\n\n /** 进入 conflicts 阶段(先创建 collector) */\n const enterConflicts = (): void => {\n const plan = imp.plan\n if (plan !== null && imp.conflictCollector === null) {\n runStore.patch({ import: { conflictCollector: new ConflictCollector(plan) } })\n }\n setPhase('conflicts')\n }\n\n /** Conflicts 完成:写入决策 → 下一阶段(决策同时持久化,切 tab/刷新可恢复) */\n const finishConflicts = (): void => {\n if (imp.conflictCollector !== null) {\n const resolutions = imp.conflictCollector.toResolutions()\n wizard.setResolutions(resolutions)\n runStore.patch({ import: { conflictResolutions: resolutions } })\n }\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 runStore.patch({ import: { error: null, running: true } })\n // m3:请求进行期间经 /runs 发现 runId 并轮询 /progress(500ms)显示真实进度\n runStore.watchRunning('import', 500)\n try {\n const promise = wizard.execute({ confirm: true, rollbackOnError })\n // execute() 已同步置 step='importing':立即镜像,保证执行期间刷新时持久化的是 importing\n runStore.syncWizard()\n const result = await promise\n // 响应含 runId(/progress 查询与刷新恢复用);控制器类型不含,运行时对象有\n const runId = (result as { runId?: unknown }).runId\n runStore.patch({ import: { runId: typeof runId === 'string' ? runId : null } })\n runStore.syncWizard()\n } catch (err) {\n runStore.patch({ import: { error: err instanceof Error ? err.message : String(err) } })\n runStore.syncWizard()\n } finally {\n runStore.stopRunWatch('import')\n runStore.patch({ import: { running: false } })\n }\n }\n\n /** 重置向导(重新导入) */\n const resetWizard = (): void => {\n pickGeneration.current += 1\n wizard.reset()\n runStore.syncWizard()\n runStore.patch({\n import: {\n phase: 'preview',\n uploading: false,\n running: false,\n progress: null,\n error: null,\n runId: null,\n selectedFileName: null,\n conflictCollector: null,\n conflictStrategy: 'merge',\n conflictResolutions: {},\n pathMappings: [],\n secretInputs: {},\n },\n })\n }\n\n /* ---------- 各步骤渲染 ---------- */\n\n if (step === 'select') {\n // 换选模型:由 store 的 selectedFileName/uploading 推导(import-file-reselection)\n const selectModel = fileSelectModel(imp.selectedFileName, uploading)\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>) => {\n // 恒清空 input value → 同一文件再次选择也会触发 onChange(同文件换选)\n const file = consumePickedFile(e.target.files?.[0], e.target)\n void onPickFile(file)\n }}\n />\n {selectModel.selectedName !== null && (\n <div className={css.hint} data-testid=\"import-selected-file\">\n {t('import.select.file', { name: selectModel.selectedName })}\n </div>\n )}\n <div className={css.actionRow}>\n {selectModel.selectedName !== null && (\n <Button variant=\"ghost\" onClick={cancelPick}>\n {t('import.select.cancel')}\n </Button>\n )}\n <Button\n variant=\"primary\"\n disabled={uploading}\n onClick={() => { fileInput.current?.click() }}\n >\n {uploading ? <Spinner label={t('import.analyzing')} /> : t(browseLabelKey(selectModel.selectedName !== null))}\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={imp.errors} />\n </div>\n )\n }\n\n if (step === 'compatibility') {\n const analysis = imp.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=\"ghost\" onClick={resetWizard}>{t('import.select.reselect')}</Button>\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 variant=\"ghost\" onClick={resetWizard}>{t('import.select.reselect')}</Button>\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 // 流程阶段页只在 wizard.step === 'preview' 时渲染:execute 开始后 step 变\n // importing/result,若 phase 仍是 confirm,必须让位给导入中/结果页(否则点「导入」\n // 无反应——confirm 页一直挡着,要回退一步才露出结果)。\n if (phase === 'conflicts' && step === 'preview') {\n if (conflictCollector === null || imp.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\n collector={conflictCollector}\n t={t}\n onChanged={() => {\n // 逐项决策实时持久化(非敏感),切 tab/刷新后可由 plan + 决策重建 collector\n if (imp.conflictCollector !== null) {\n runStore.patch({ import: { conflictResolutions: imp.conflictCollector.toResolutions() } })\n }\n }}\n />\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' && step === 'preview') {\n const issues = imp.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={(mappings) => { runStore.patch({ import: { pathMappings: mappings } }) }} />\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' && step === 'preview') {\n const missing = imp.plan?.missingSecrets ?? []\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('import.secrets.title')} />\n <SecretsForm missing={missing} t={t} onChange={(inputs) => { runStore.patch({ import: { secretInputs: inputs } }) }} />\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' && step === 'preview') {\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={(v) => {\n wizard.setRollbackOnError(v)\n runStore.patch({ import: { rollbackOnError: v } })\n }}\n label={t('import.rollbackOnError')}\n />\n <div className={css.actionRow}>\n <Button variant=\"ghost\" onClick={() => { setPhase('preview') }}>{t('common.back')}</Button>\n {/* m3-lock:进行中禁用「确认导入」,防止重复启动 */}\n <Button variant=\"primary\" disabled={running} 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={imp.errors} />\n </div>\n )\n }\n\n if (step === 'result') {\n const result = imp.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 // 报告已内联展示全部失败/警告项与回滚详情(§22/§23),无额外动作页\n }}\n />\n {result.needsRestart && <Banner kind=\"warn\">{t('report.needsRestart')}</Banner>}\n {error !== null && <ErrorBanner error={error} />}\n </div>\n )\n }\n\n return null\n}\n","/**\n * 快照恢复面板(M4):列出快照 → 选择 → dry-run 计划预览 → 确认执行 → 诚实报告。\n *\n * 数据流:api.snapshots() 加载列表;选择快照后 api.restoreSnapshot(id, true) 拿\n * 恢复计划(零写入预览);确认后 api.restoreSnapshot(id, false) 执行并展示报告\n * (restored / removedPlugins / manualHints(人工项高亮)/ failed / skipped)。\n * 全部状态组件内自持:恢复是低频显式操作,不进入 sessionStorage(快照列表可随时重载)。\n */\nimport { useEffect, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { RestorePlan, RestoreReport, SnapshotMeta } from '../../core/restore.ts'\nimport type { ConfigManagerApi } from '../api.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport { Badge, Banner, Button, Card, Empty, SectionTitle, Spinner } from '../common/ui.tsx'\nimport css from '../config-manager.module.css'\n\nexport interface SnapshotsPanelProps {\n api: ConfigManagerApi\n t: TranslateNS<'config-manager'>\n}\n\ninterface PanelState {\n status: 'loading' | 'ready' | 'error'\n error: string | null\n metas: SnapshotMeta[]\n selectedId: string | null\n planning: boolean\n plan: RestorePlan | null\n running: boolean\n report: RestoreReport | null\n actionError: string | null\n}\n\nconst initial: PanelState = {\n status: 'loading',\n error: null,\n metas: [],\n selectedId: null,\n planning: false,\n plan: null,\n running: false,\n report: null,\n actionError: null,\n}\n\nfunction statusLabel(t: TranslateNS<'config-manager'>, status: SnapshotMeta['status']): string {\n switch (status) {\n case 'pending': return t('snapshots.status.pending')\n case 'done': return t('snapshots.status.done')\n case 'rolled-back': return t('snapshots.status.rolled-back')\n default: return t('snapshots.status.unknown')\n }\n}\n\nfunction statusBadgeKind(status: SnapshotMeta['status']): 'info' | 'ok' | 'warn' | 'error' {\n switch (status) {\n case 'pending': return 'info'\n case 'done': return 'ok'\n case 'rolled-back': return 'warn'\n default: return 'error'\n }\n}\n\n/** 计划动作的本地化描述前缀(kind 标签 + 引擎已生成的中文 description) */\nfunction actionKindLabel(kind: string): string {\n switch (kind) {\n case 'hostFileRestore': return '整文件还原'\n case 'hostFileRemove': return '整文件删除'\n case 'pluginRemove': return '卸载插件'\n case 'fileRestore': return '还原文件'\n case 'fileRemove': return '删除文件'\n case 'credentialHint': return '人工提示'\n case 'skip': return '跳过'\n default: return kind\n }\n}\n\nexport function SnapshotsPanel({ api, t }: SnapshotsPanelProps) {\n const [state, setState] = useState<PanelState>(initial)\n\n const load = (): void => {\n setState((s) => ({ ...s, status: 'loading', error: null }))\n api.snapshots().then(\n (metas) => { setState((s) => ({ ...s, status: 'ready', metas })) },\n (err) => {\n setState((s) => ({\n ...s,\n status: 'error',\n error: err instanceof Error ? err.message : String(err),\n }))\n },\n )\n }\n\n useEffect(load, [api])\n\n const select = (id: string): void => {\n setState((s) => ({ ...s, selectedId: id, plan: null, report: null, actionError: null, planning: true }))\n api.restoreSnapshot(id, true).then(\n (res) => { setState((s) => ({ ...s, planning: false, plan: res.plan ?? null })) },\n (err) => {\n setState((s) => ({\n ...s,\n planning: false,\n actionError: err instanceof Error ? err.message : String(err),\n }))\n },\n )\n }\n\n const execute = (): void => {\n if (state.selectedId === null || state.running) return\n setState((s) => ({ ...s, running: true, report: null, actionError: null }))\n api.restoreSnapshot(state.selectedId, false).then(\n (res) => { setState((s) => ({ ...s, running: false, report: res.report ?? null })) },\n (err) => {\n setState((s) => ({\n ...s,\n running: false,\n actionError: err instanceof Error ? err.message : String(err),\n }))\n },\n )\n }\n\n const summary = (): string => {\n const s = state.plan?.summary\n if (s === undefined) return ''\n return `整文件还原 ${s.hostFileRestores} · 整文件删除 ${s.hostFileRemoves} · 插件卸载 ${s.pluginRemoves}`\n + ` · 文件还原 ${s.fileRestores} · 文件删除 ${s.fileRemoves} · 凭据提示 ${s.credentialHints} · 跳过 ${s.skips}`\n }\n\n const reportLine = (title: string, items: string[], warn: boolean): ReactNode => {\n if (items.length === 0) return null\n return (\n <Card className={css.card}>\n <strong className={warn ? css.warnText : undefined}>{title}({items.length})</strong>\n <div className={css.reportScroll}>\n <ul className={css.reportList}>\n {items.map((item, i) => <li key={`${title}-${i}`}>{item}</li>)}\n </ul>\n </div>\n </Card>\n )\n }\n\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('snapshots.title')} subtitle={t('snapshots.hint')} />\n\n {state.status === 'loading' && <Spinner label={t('snapshots.loading')} />}\n\n {state.status === 'error' && (\n <Banner kind=\"error\">\n {state.error ?? t('common.unknownError')}\n <Button variant=\"primary\" onClick={load}>{t('common.retry')}</Button>\n </Banner>\n )}\n\n {state.status === 'ready' && state.metas.length === 0 && (\n <Empty>{t('snapshots.empty')}</Empty>\n )}\n\n {state.status === 'ready' && state.metas.length > 0 && (\n <>\n <div className={css.snapshotList} role=\"listbox\" aria-label={t('snapshots.selectHint')}>\n <div className={css.snapshotRowHeader}>\n <span>{t('snapshots.createdAt')}</span>\n <span>{t('snapshots.sourceZip')}</span>\n <span>{t('snapshots.status')}</span>\n <span>{t('snapshots.entries')}</span>\n <span>{t('snapshots.plugins')}</span>\n </div>\n {state.metas.map((meta) => {\n const selected = meta.id === state.selectedId\n return (\n <button\n key={meta.id}\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n data-active={selected ? '' : undefined}\n className={css.snapshotRow}\n onClick={() => { select(meta.id) }}\n >\n <span title={meta.id}>{new Date(meta.createdAt).toLocaleString()}</span>\n <span title={meta.sourceZip}>{meta.sourceZip}</span>\n <span><Badge kind={statusBadgeKind(meta.status)}>{statusLabel(t, meta.status)}</Badge></span>\n <span>{meta.entryCount}</span>\n <span>{meta.beforePluginCount}</span>\n </button>\n )\n })}\n </div>\n\n {state.selectedId !== null && (\n <>\n {state.planning && <Spinner label={t('common.loading')} />}\n {state.plan !== null && (\n <Card>\n <SectionTitle title={t('snapshots.planTitle')} subtitle={summary()} />\n {state.plan.actions.length === 0 && <Empty>{t('snapshots.noActions')}</Empty>}\n {state.plan.actions.length > 0 && (\n <div className={css.planScroll}>\n <ul className={css.reportList}>\n {state.plan.actions.map((action, i) => (\n <li key={`plan-${i}`}>\n <span className={css.kindTag}>{actionKindLabel(action.kind)}</span>\n {' '}{action.description}\n {action.detail !== undefined && <span className={css.hint}>({action.detail})</span>}\n </li>\n ))}\n </ul>\n </div>\n )}\n <div className={css.rowActions}>\n <Button\n variant=\"danger\"\n disabled={state.running || state.plan.actions.every((a) => a.kind === 'skip')}\n onClick={execute}\n title={t('snapshots.confirmRestore')}\n >\n {state.running ? t('snapshots.executing') : t('snapshots.execute')}\n </Button>\n </div>\n {state.actionError !== null && <Banner kind=\"error\">{state.actionError}</Banner>}\n </Card>\n )}\n </>\n )}\n\n {state.report !== null && (\n <>\n <SectionTitle title={t('snapshots.reportTitle')} />\n {reportLine(t('snapshots.restored'), state.report.restored, false)}\n {reportLine(t('snapshots.removedPlugins'), state.report.removedPlugins, false)}\n {reportLine(t('snapshots.manualHints'), state.report.manualHints, true)}\n {reportLine(t('snapshots.failed'), state.report.failed.map((f) => `${f.item}: ${f.reason}`), true)}\n {reportLine(t('snapshots.skipped'), state.report.skipped, false)}\n </>\n )}\n </>\n )}\n </div>\n )\n}\n","/**\n * 远程同步浏览器半 —— `/api/dsh-config-manager/sync/*` 的类型化 fetch 封装。\n *\n * 独立于 `../api.ts`(ConfigManagerApi 为并行会话已改文件,禁碰):本文件自持\n * 端点常量与 readJson/postJson 小工具(与 api.ts 同款模式),只新增不修改。\n *\n * 端点契约(Host 半 src/index.ts 的 makeRoutes 按此实现):\n * ```\n * GET /api/dsh-config-manager/sync/status → SyncStatusResponse (配置/凭据/上次同步)\n * POST /api/dsh-config-manager/sync/push → SyncPushReport (body: { repoUrl, gitBin?, token?, snapshotId? })\n * POST /api/dsh-config-manager/sync/pull → SyncPullReport (body: { repoUrl, gitBin?, token?, strategy?, snapshotId? })\n * POST /api/dsh-config-manager/sync/github/start → GithubDeviceFlowStartResponse(GitHub OAuth 设备码)\n * POST /api/dsh-config-manager/sync/github/poll → GithubPollResponse(凭 flowId 轮询;成功时 token 已由 Host 写入 credentials)\n * POST /api/dsh-config-manager/sync/github/cancel → { ok: true }\n * ```\n *\n * 安全约束:\n * - token 只存在于请求体内(同源 loopback,与导入 secretInputs 同策略),由 Host 写入\n * DSH credentials(credentialRef),绝不落同步文件/日志/URL;响应永不回传 token;\n * - GitHub device flow:浏览器只持有 flowId(随机 id)+ user_code + 授权页 URL;\n * device_code 与 access token 只存在于宿主(内存 / DSH credentials),永不回传;\n * - 错误消息由 Host 侧已脱敏(GitTransport 统一 [REDACTED]),UI 侧再经 ErrorBanner redact 兜底;\n * - 本文件不 import 任何 node 模块(纯浏览器 bundle;sync-engine 仅作 type-only 引用)。\n */\nimport type { ApplyReport, SyncPullReport, SyncPushReport } from '../../sync/sync-engine.ts';\nimport { ConfigManagerApiError } from '../api.ts';\nimport { zhUiT, type UiT } from '../../ui/i18n.ts';\n\n/** 同步端点常量(与 Host 半 src/index.ts API 常量保持一致) */\nexport const SYNC_API = {\n base: '/api/dsh-config-manager/sync',\n status: '/api/dsh-config-manager/sync/status',\n push: '/api/dsh-config-manager/sync/push',\n pull: '/api/dsh-config-manager/sync/pull',\n githubStart: '/api/dsh-config-manager/sync/github/start',\n githubPoll: '/api/dsh-config-manager/sync/github/poll',\n githubCancel: '/api/dsh-config-manager/sync/github/cancel',\n history: '/api/dsh-config-manager/sync/history',\n apply: '/api/dsh-config-manager/sync/apply',\n rollback: '/api/dsh-config-manager/sync/rollback',\n} as const;\n\n/** DSH credentials 中的同步 token 引用名(Host 半同值;仅供提示文案使用,值由 Host 读写) */\nexport const SYNC_CREDENTIAL_REF = 'DSH_CONFIG_MANAGER_SYNC_TOKEN';\n\n/** GET /sync/status 响应:配置/凭据/上次同步的只读事实(无任何 secret 值) */\nexport interface SyncStatusResponse {\n ok: boolean;\n /** 是否已保存过仓库配置(sync-config.json) */\n configured: boolean;\n /** 上次使用的仓库地址(不含 token,可回显) */\n repoUrl?: string;\n gitBin?: string;\n /** DSH credentials 中是否已存在 token(describe 只报状态,值永不返回) */\n credentialConfigured: boolean;\n credentialWritable: boolean;\n /** sync-state.lastSyncAt;'' = 从未同步 */\n lastSyncAt?: string;\n /** sync-state.sections 条目数 */\n sectionCount: number;\n transport?: { type: string; ref: string };\n}\n\n/** push 请求体(token 可选:非空则 Host 先写入 DSH credentials 再使用) */\nexport interface SyncPushPayload {\n repoUrl: string;\n gitBin?: string;\n token?: string;\n}\n\n/** pull 请求体(strategy 缺省 merge:冲突保留待决策;snapshotId 缺省 = 最新) */\nexport interface SyncPullPayload extends SyncPushPayload {\n strategy?: 'merge' | 'replace' | 'skipExisting';\n snapshotId?: string;\n}\n\n/* ---------------------------------------------------------------- GitHub OAuth device flow */\n\n/** POST /sync/github/start 响应:UI 展示用(device_code 只存宿主,绝不回传) */\nexport interface GithubDeviceFlowStartResponse {\n /** 随机 flowId:后续 poll/cancel 凭它引用宿主侧登记的 device_code */\n flowId: string;\n /** 一次性用户码(用户在 GitHub 授权页输入) */\n userCode: string;\n /** GitHub 授权页 URL(用户浏览器打开) */\n verificationUri: string;\n /** 设备码过期秒数 */\n expiresIn: number;\n /** GitHub 建议轮询间隔秒数 */\n interval: number;\n}\n\n/** POST /sync/github/poll 响应状态 */\nexport type GithubPollStatus = 'pending' | 'success' | 'denied' | 'expired' | 'error';\n\n/** POST /sync/github/poll 响应:成功时 token 已由 Host 写入 DSH credentials(值永不回传) */\nexport interface GithubPollResponse {\n status: GithubPollStatus;\n /** pending:下次轮询前应等待的毫秒数 */\n pollDelayMs?: number;\n /** 终止态错误码(GitHub error code) */\n errorCode?: string;\n /** 终止态可展示消息(来自 GitHub error_description / 宿主文案,不含秘密) */\n message?: string;\n /** success 时恒 true(凭据已配置);便于 UI 直接刷新状态 */\n credentialConfigured?: boolean;\n}\n\n/** 同步请求超时(ms):与 Host 半 ROUTE_TIMEOUT_MS 对齐(git 网络操作可能较慢) */\nconst SYNC_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** 解析 JSON 响应;非 2xx 时抛出带路由 error 消息的 ConfigManagerApiError(与 api.ts 同款) */\nasync function readJson<T>(response: Response, t: UiT): Promise<T> {\n const notMountedMessage = t('error.notMounted');\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n if (response.status === 404) throw new ConfigManagerApiError(notMountedMessage);\n throw new ConfigManagerApiError(t('error.httpInvalidJson', { status: String(response.status) }));\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 : response.status === 404\n ? notMountedMessage\n : `HTTP ${response.status}`;\n throw new ConfigManagerApiError(message);\n }\n return body as T;\n}\n\n/** POST JSON 请求(带超时:宿主卡死时 UI 拿到明确错误而不是永远转圈) */\nasync function postJson<T>(path: string, body: unknown, t: UiT): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), SYNC_TIMEOUT_MS);\n try {\n const response = await fetch(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n return await readJson<T>(response, t);\n } catch (err) {\n if (controller.signal.aborted) {\n throw new ConfigManagerApiError(\n t('error.syncTimeout', { minutes: String(Math.round(SYNC_TIMEOUT_MS / 60000)) }),\n );\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** 远程同步浏览器半数据入口(备份与迁移页第 4 个 tab 的注入业务面) */\nexport class SyncApi {\n readonly t: UiT\n constructor(t: UiT = zhUiT) {\n this.t = t\n }\n\n /** 读取同步状态(配置 / 凭据 / 上次同步时间 / 分区数) */\n async status(): Promise<SyncStatusResponse> {\n const response = await fetch(SYNC_API.status);\n return readJson<SyncStatusResponse>(response, this.t);\n }\n\n /** 推送:导出 portable 分区 → 提交到私有 Git 仓库 → 更新 sync-state */\n async push(payload: SyncPushPayload): Promise<SyncPushReport> {\n return postJson<SyncPushReport>(SYNC_API.push, payload, this.t);\n }\n\n /** 拉取差异预览:拉取远端最新快照 → 只读分析(绝不执行导入) */\n async pull(payload: SyncPullPayload): Promise<SyncPullReport> {\n return postJson<SyncPullReport>(SYNC_API.pull, payload, this.t);\n }\n\n /** GitHub OAuth device flow:发起登录,返回一次性用户码 + 授权页 URL + flowId */\n async githubStart(): Promise<GithubDeviceFlowStartResponse> {\n return postJson<GithubDeviceFlowStartResponse>(SYNC_API.githubStart, {}, this.t);\n }\n\n /** GitHub OAuth device flow:凭 flowId 轮询授权结果(成功时 token 已由 Host 写入 credentials) */\n async githubPoll(flowId: string): Promise<GithubPollResponse> {\n return postJson<GithubPollResponse>(SYNC_API.githubPoll, { flowId }, this.t);\n }\n\n /** GitHub OAuth device flow:取消(丢弃宿主侧登记,零副作用) */\n async githubCancel(flowId: string): Promise<{ ok: boolean }> {\n return postJson<{ ok: boolean }>(SYNC_API.githubCancel, { flowId }, this.t);\n }\n\n /** 同步历史:列出 localSnapshotsDir 下的快照目录(manifest.json: id/createdAt/sectionHashes) */\n async history(): Promise<SyncHistoryEntry[]> {\n const response = await fetch(SYNC_API.history);\n return readJson<SyncHistoryEntry[]>(response, this.t);\n }\n\n /** 应用自动应用计划:写本地 + backup + (失败时) rollback + enqueue review;返回 ApplyReport */\n async apply(payload: SyncPushPayload): Promise<ApplyReport> {\n return postJson<ApplyReport>(SYNC_API.apply, payload, this.t);\n }\n\n /** 一键回滚:按 restoreId 调用 backup→rollback */\n async rollback(payload: { restoreId: string }): Promise<{ ok: boolean; full: boolean }> {\n return postJson<{ ok: boolean; full: boolean }>(SYNC_API.rollback, payload, this.t);\n }\n}\n\n/** 同步历史条目(Host 端返回) */\nexport interface SyncHistoryEntry {\n id: string;\n createdAt: string;\n sectionCount: number;\n reviewCount: number;\n}\n","/**\n * 远程同步区块的纯渲染模型(m-sync-ui)。\n *\n * 与 src/ui/progress.ts → progress-view.ts 同模式:把「报告怎么渲染 / 按钮什么状态 /\n * 状态行写什么 / 私有仓库提示怎么展示」做成无副作用纯函数,node --test 直接测,\n * React 组件只做装配。文案直接用中文(项目源语言),组件不重复造。\n */\nimport type { PlanItem, PlanItemKind } from '../../core/types.ts';\nimport type { PullChange, SyncPullReport, SyncPushReport } from '../../sync/sync-engine.ts';\nimport type { GithubPollResponse, SyncStatusResponse } from './sync-api.ts';\nimport { zhUiT, type UiT } from '../../ui/i18n.ts';\n\n/* ---------------------------------------------------------------- 私有仓库提示 */\n\n/**\n * 私有仓库强制提示文案(Settings 区块常驻警示横幅)。\n * 安全约束:同步内容为可移植配置,public 仓库会公开配置 → 必须私有;\n * token 仅用于认证,绝不写入同步文件/提交内容/日志。\n */\nexport function privateRepoHint(t: UiT = zhUiT): string {\n return t('sync.privateRepoHint');\n}\n\n/* ---------------------------------------------------------------- 变更摘要 */\n\n/** 需要人工决策的 PlanItem 类型(与 SyncEngine.pull 的 needsReview 判定一致) */\nconst REVIEW_KINDS: ReadonlySet<PlanItemKind> = new Set([\n 'Conflict', 'MissingSecret', 'MissingDependency', 'Install', 'Error',\n]);\n\nexport interface PullChangeSummary {\n total: number;\n info: number;\n warning: number;\n error: number;\n /** 是否包含需要人工决策的项(冲突/密钥/依赖/安装/错误) */\n needsReview: boolean;\n items: PullChange[];\n}\n\n/** 差异摘要:按 severity 计数 + 需人工决策标记(UI 统计徽章与警示横幅的数据源) */\nexport function summarizePullChanges(changes: readonly PullChange[]): PullChangeSummary {\n let info = 0;\n let warning = 0;\n let error = 0;\n let needsReview = false;\n for (const c of changes) {\n if (c.severity === 'error') error += 1;\n else if (c.severity === 'warning') warning += 1;\n else info += 1;\n if (REVIEW_KINDS.has(c.kind)) needsReview = true;\n }\n return { total: changes.length, info, warning, error, needsReview, items: [...changes] };\n}\n\n/** PlanItemKind → 短标签(列表徽章) */\nexport function kindLabel(kind: PlanItemKind, t: UiT = zhUiT): string {\n switch (kind) {\n case 'Create': return t('sync.kind.create');\n case 'Update': return t('sync.kind.update');\n case 'Skip': return t('sync.kind.skip');\n case 'Conflict': return t('sync.kind.conflict');\n case 'Install': return t('sync.kind.install');\n case 'MissingSecret': return t('sync.kind.missingSecret');\n case 'MissingDependency': return t('sync.kind.missingDependency');\n case 'PathMapping': return t('sync.kind.pathMapping');\n case 'Warning': return t('sync.kind.warning');\n case 'Error': return t('sync.kind.error');\n default: return kind;\n }\n}\n\n/** severity → 短标签 */\nexport function severityLabel(severity: PlanItem['severity'], t: UiT = zhUiT): string {\n switch (severity) {\n case 'error': return t('sync.severity.error');\n case 'warning': return t('sync.severity.warning');\n default: return t('sync.severity.info');\n }\n}\n\n/* ---------------------------------------------------------------- 按钮状态 */\n\nexport interface SyncButtons {\n canPush: boolean;\n canPull: boolean;\n pushLabel: string;\n pullLabel: string;\n}\n\n/**\n * 按钮可用性与文案:\n * - 任一操作进行中(busy)→ 两个按钮都禁用(防并发 push/pull);\n * - 仓库地址为空 → 禁用(无仓库无从同步);\n * - busy 时按钮文案切换为「正在推送/拉取…」(配 Spinner)。\n */\nexport function computeSyncButtons(busy: 'push' | 'pull' | 'apply' | 'rollback' | null, repoUrl: string, t: UiT = zhUiT): SyncButtons {\n const idle = busy === null;\n const repoOk = repoUrl.trim() !== '';\n const enabled = idle && repoOk;\n return {\n canPush: enabled,\n canPull: enabled,\n pushLabel: busy === 'push' ? t('sync.pushing') : t('sync.pushLabel'),\n pullLabel: busy === 'pull' ? t('sync.pulling') : t('sync.pullLabel'),\n };\n}\n\n/* ---------------------------------------------------------------- 状态行 */\n\nexport type SyncStatusKind = 'loading' | 'unconfigured' | 'ready' | 'error';\n\nexport interface SyncStatusSummary {\n kind: SyncStatusKind;\n text: string;\n}\n\n/** 状态行渲染模型:加载 / 未配置 / 就绪(凭据 + 上次同步 + 通道)/ 错误 */\nexport function computeSyncStatus(\n statusInfo: SyncStatusResponse | null,\n loading: boolean,\n error: string | null,\n t: UiT = zhUiT,\n): SyncStatusSummary {\n if (loading) return { kind: 'loading', text: t('sync.statusLoading') };\n if (error !== null) return { kind: 'error', text: error };\n if (statusInfo === null || !statusInfo.configured) {\n return { kind: 'unconfigured', text: t('sync.statusUnconfigured') };\n }\n const cred = statusInfo.credentialConfigured\n ? t('sync.credConfigured')\n : t('sync.credMissing');\n const last =\n statusInfo.lastSyncAt !== undefined && statusInfo.lastSyncAt !== ''\n ? t('sync.lastSync', { time: formatDateTime(statusInfo.lastSyncAt) })\n : t('sync.neverSynced');\n const transport =\n statusInfo.transport !== undefined\n ? ` · ${statusInfo.transport.type}${statusInfo.transport.ref !== '' ? `/${statusInfo.transport.ref}` : ''}`\n : '';\n return { kind: 'ready', text: `${cred} · ${last}${transport}` };\n}\n\n/** ISO-8601 → 本地可读时间(YYYY-MM-DD HH:mm;非法输入原样返回) */\nexport function formatDateTime(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n const pad = (n: number): string => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\n/** 上次同步时间的展示文本('' / undefined = 从未同步) */\nexport function formatLastSync(iso: string | undefined, t: UiT = zhUiT): string {\n if (iso === undefined || iso === '') return t('sync.neverSyncedShort');\n return formatDateTime(iso);\n}\n\n/* ---------------------------------------------------------------- 报告渲染模型 */\n\nexport interface PushReportView {\n kind: 'ok' | 'error';\n headline: string;\n sections: string[];\n warnings: string[];\n}\n\n/** push 报告 → 渲染模型(ok 头部带快照 id;失败显示引擎 message;分区与告警透传) */\nexport function pushReportView(report: SyncPushReport | null, t: UiT = zhUiT): PushReportView | null {\n if (report === null) return null;\n if (!report.ok) {\n return { kind: 'error', headline: report.message ?? t('sync.pushFailed'), sections: report.sections, warnings: report.warnings };\n }\n return {\n kind: 'ok',\n headline: t('sync.pushOk', { id: report.snapshotId }),\n sections: report.sections,\n warnings: report.warnings,\n };\n}\n\nexport interface PullReportView {\n kind: 'ok' | 'empty' | 'error';\n headline: string;\n summary: PullChangeSummary | null;\n /** 只读预览提示(ok 时非空:明确「预览不执行导入」) */\n previewHint: string;\n}\n\n/** pull 报告 → 渲染模型(差异预览;empty = 无变更;error = 拉取失败) */\nexport function pullReportView(report: SyncPullReport | null, t: UiT = zhUiT): PullReportView | null {\n if (report === null) return null;\n if (!report.ok) {\n return { kind: 'error', headline: report.message ?? t('sync.pullFailed'), summary: null, previewHint: '' };\n }\n if (report.changes.length === 0) {\n return { kind: 'empty', headline: report.message ?? t('sync.pullEmpty'), summary: null, previewHint: '' };\n }\n return {\n kind: 'ok',\n headline: t('sync.pullOk', { id: report.snapshotId, count: String(report.changes.length) }),\n summary: summarizePullChanges(report.changes),\n previewHint: t('sync.previewHint'),\n };\n}\n\n/* ---------------------------------------------------------------- GitHub 登录视图模型 */\n\nexport type GithubLoginPhase = 'idle' | 'starting' | 'waiting' | 'polling' | 'success' | 'error';\n\nexport interface GithubLoginView {\n phase: GithubLoginPhase;\n /** 一次性用户码(waiting/polling 展示,用户到 GitHub 授权页输入) */\n userCode: string;\n /** GitHub 授权页 URL */\n verificationUri: string;\n /** 状态行文案(中文,项目源语言;与 computeSyncStatus 同策略,不依赖 locale 注入) */\n statusText: string;\n /** 主按钮文案:发起 / 重新登录 */\n startLabel: string;\n /** 是否可发起/重试登录 */\n canStart: boolean;\n /** 流程进行中是否展示「取消」按钮 */\n canCancel: boolean;\n /** 是否展示设备码 + 授权链接区块 */\n showCode: boolean;\n /** 错误消息(phase=error;来自轮询终止态或请求失败) */\n error: string | null;\n}\n\n/**\n * GitHub 登录区块渲染模型(纯函数,node 可测):\n * - idle → 可发起;starting → 请求设备码中;waiting → 展示设备码等待用户在浏览器授权;\n * - polling → 轮询 GitHub 中(仍展示代码区块);success → 完成;error → 可重试。\n */\nexport function computeGithubLoginView(\n phase: GithubLoginPhase,\n userCode: string,\n verificationUri: string,\n error: string | null,\n t: UiT = zhUiT,\n): GithubLoginView {\n const inFlight = phase === 'starting' || phase === 'waiting' || phase === 'polling';\n let statusText: string;\n switch (phase) {\n case 'starting':\n statusText = t('sync.github.starting');\n break;\n case 'waiting':\n statusText = userCode === ''\n ? t('sync.github.waitingNoCode')\n : t('sync.github.waiting', { code: userCode });\n break;\n case 'polling':\n statusText = t('sync.github.polling');\n break;\n case 'success':\n statusText = t('sync.github.success');\n break;\n case 'error':\n statusText = error ?? t('sync.github.failed');\n break;\n default:\n statusText = t('sync.github.defaultStatus');\n }\n return {\n phase,\n userCode,\n verificationUri,\n statusText,\n startLabel: phase === 'error' ? t('sync.github.relogin') : t('sync.github.login'),\n canStart: phase === 'idle' || phase === 'error',\n canCancel: inFlight,\n showCode: phase === 'waiting' || phase === 'polling',\n error,\n };\n}\n\n/** 轮询终止态 → 用户可读消息(pending 不是终止态,返回空串;成功/拒绝/过期/错误给出明确文案) */\nexport function githubPollMessage(poll: GithubPollResponse, t: UiT = zhUiT): string {\n switch (poll.status) {\n case 'success':\n return t('sync.github.pollSuccess');\n case 'denied':\n return t('sync.github.pollDenied');\n case 'expired':\n return t('sync.github.pollExpired');\n case 'error':\n return t('sync.github.pollError', { detail: poll.message ?? poll.errorCode ?? t('sync.github.unknownError') });\n default:\n return '';\n }\n}\n","/**\n * m-sync-ui (P2b):SyncHistoryView 的纯函数投影。\n */\nexport interface SnapshotHistoryEntry {\n id: string;\n createdAt: string;\n /** 分区数(manifest.sectionHashes 的 key 数) */\n sectionCount: number;\n /** 关联到该快照的待审项数(来自 sync-review-queue.json 中的 items) */\n reviewCount: number;\n}\n\n/** 把 entries 排序(createdAt 倒序)并组装展示字段。 */\nexport function projectHistoryRows(entries: readonly SnapshotHistoryEntry[]): SnapshotHistoryEntry[] {\n return [...entries].sort((a, b) => (a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0));\n}\n\n/** ISO 时间 → 本地可读字符串(短格式) */\nexport function formatDateTime(iso: string): string {\n if (!iso) return '—';\n const d = new Date(iso);\n if (isNaN(d.getTime())) return iso;\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n","/**\n * 同步历史视图(M6,P2b):列出 localSnapshotsDir 各快照目录的 manifest.json\n * (id + createdAt + sectionHashes);每行显示:快照 ID、时间、分区数、关联待审数(来自 sync-review-queue.json)。\n *\n * 数据获取:通过 Host 的 IPC 端点(与 SyncSettingsView 同模式)。本组件只负责渲染;\n * 数据加载由宿主 API 提供(不在浏览器侧直接读 fs)。\n */\nimport { useEffect, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\n\nimport { Card, SectionTitle, Spinner } from '../common/ui.tsx'\nimport type { SyncApi } from './sync-api.ts'\nimport { projectHistoryRows, formatDateTime } from './history-model.ts'\nimport type { SnapshotHistoryEntry } from './history-model.ts'\n\n// 纯函数(项目排序、ISO 格式化)放在 ./history-model.ts(node --test 可测)。\n\nexport interface SyncHistoryViewProps {\n api: SyncApi\n}\n\nexport function SyncHistoryView(props: SyncHistoryViewProps): ReactNode {\n const { api } = props;\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [entries, setEntries] = useState<SnapshotHistoryEntry[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const data = await api.history();\n if (!cancelled) {\n setEntries(data);\n setLoading(false);\n }\n } catch (err) {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : String(err));\n setLoading(false);\n }\n }\n })();\n return () => { cancelled = true; };\n }, [api]);\n\n const rows = useMemo(() => projectHistoryRows(entries), [entries]);\n\n if (loading) return <Spinner label=\"加载同步历史…\" />;\n if (error) return <Card><span className=\"error\">{error}</span></Card>;\n if (rows.length === 0) return <Card><strong>尚无同步历史</strong><p>完成首次 push/pull 后这里会显示快照记录。</p></Card>;\n\n return (\n <Card>\n <SectionTitle title={`同步历史(${rows.length})`} />\n <table className=\"sync-history-table\">\n <thead>\n <tr><th>快照 ID</th><th>时间</th><th>分区</th><th>待审</th></tr>\n </thead>\n <tbody>\n {rows.map((r) => (\n <tr key={r.id}>\n <td><code>{r.id}</code></td>\n <td>{formatDateTime(r.createdAt)}</td>\n <td>{r.sectionCount}</td>\n <td>{r.reviewCount > 0 ? <strong>{r.reviewCount}</strong> : 0}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </Card>\n );\n}\n","/**\n * 拉取预览页(M5,P2b):消费 SyncApplyPlan,渲染\n * - 自动已应用列表(autoApplied)—— 绿色状态徽章 + sectionId/description;\n * - 待审变更列表(review)—— 每项三个按钮(用本地 / 用远端 / 跳过)+ 局部差异 diff;\n * - 整体 rollback 后「回滚到应用前」按钮(调用 restoreId);\n * - 全部 review 解决 → 触发 onAllResolved 回调(sync 完成)。\n *\n * 设计:与 SyncSettingsView 同模式 —— 全部渲染模型来自 ./sync-view.ts 纯函数,\n * 组件只做装配 + 状态;测试在 node --test 跑纯函数部分。\n */\nimport { useCallback, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\n\nimport type { SyncApplyPlan } from '../../sync/risk.ts'\nimport type { MergeConflict, MergeSectionResult } from '../../sync/merge.ts'\nimport { Badge, Button, Card, SectionTitle } from '../common/ui.tsx'\nimport { resolveItem } from '../../sync/review-queue.ts'\nimport type { ReviewQueueItem } from '../../sync/review-queue.ts'\nimport { projectReviewItems, describeConflicts, formatDiff } from './pull-preview-model.ts'\nimport type { ReviewDisplayItem } from './pull-preview-model.ts'\n\n// 纯数据投影逻辑放在 ./pull-preview-model.ts(node --test 可测);本文件仅装配。\n\nexport interface SyncPullPreviewViewProps {\n /** SyncApplyPlan(autoApply + review + skipped) */\n applyPlan: SyncApplyPlan\n /** stateDir(用于 resolveItem 写回 sync-review-queue.json) */\n stateDir: string\n /** 失败 ApplyReport(提供 restoreId) */\n restoreId?: string\n /** 已应用的 sectionId 列表(applyMergePlan.ok=true 时显示成功绿条) */\n appliedIds?: readonly string[]\n /** 来自 Importer 的 warning 列表(applyMergePlan.warnings) */\n warnings?: readonly string[]\n /** 全部 review 项解决后回调(让上层触发 sync 完成) */\n onAllResolved?: () => void\n /** 调用 rollback.ts 恢复 backup 的 handler(UI 一键回滚入口) */\n onRollback?: (restoreId: string) => Promise<void> | void\n}\n\ninterface ItemDecisionState {\n /** 'pending' = 未决;其它 = 用户已决策 */\n status: 'pending' | 'useRemote' | 'keepLocal' | 'skip'\n}\n\nexport function SyncPullPreviewView(props: SyncPullPreviewViewProps): ReactNode {\n const { applyPlan, stateDir, appliedIds = [], warnings = [], restoreId, onAllResolved, onRollback } = props;\n const items = useMemo(() => projectReviewItems(applyPlan), [applyPlan]);\n const [decisions, setDecisions] = useState<Record<string, ItemDecisionState['status']>>(() => {\n const init: Record<string, ItemDecisionState['status']> = {};\n for (const it of items) init[it.itemId] = it.initial;\n return init;\n });\n\n const decide = useCallback(async (itemId: string, decision: 'useRemote' | 'keepLocal' | 'skip') => {\n setDecisions((prev) => ({ ...prev, [itemId]: decision }));\n try {\n await resolveItem(stateDir, itemId, decision);\n } catch (err) {\n // 决策持久化失败:UI 层错误处理——此处仅控制台提示,上层可通过 warnings 透传\n console.warn(`resolveItem(${itemId}) 失败:`, err);\n }\n }, [stateDir]);\n\n // 计算剩余未决项\n const pendingIds = useMemo(() => items.filter((i) => decisions[i.itemId] === 'pending').map((i) => i.itemId), [items, decisions]);\n if (pendingIds.length === 0 && items.length > 0 && onAllResolved) {\n // useEffect 替代:此处直接调用——组件是纯展示\n queueMicrotask(() => onAllResolved());\n }\n\n return (\n <div className=\"sync-pull-preview\">\n {/* 自动已应用列表 */}\n {appliedIds.length > 0 && (\n <Card>\n <SectionTitle title={`自动已应用(${appliedIds.length})`} />\n <ul>\n {appliedIds.map((sid) => (\n <li key={sid}>\n <Badge kind=\"ok\">✓</Badge> <code>{sid}</code>\n </li>\n ))}\n </ul>\n {warnings.length > 0 && (\n <ul className=\"warnings\">\n {warnings.map((w, i) => <li key={i} className=\"warning\">{w}</li>)}\n </ul>\n )}\n {restoreId && onRollback && (\n <Button variant=\"danger\" onClick={() => onRollback(restoreId)}>{`回滚到应用前 (${restoreId})`}</Button>\n )}\n </Card>\n )}\n\n {/* 待审列表 */}\n {items.length > 0 && (\n <Card>\n <SectionTitle title={`待审变更(${items.length})`} />\n {items.map((it) => (\n <ReviewItemRow\n key={it.itemId}\n item={it}\n state={decisions[it.itemId] ?? 'pending'}\n onDecide={(d) => decide(it.itemId, d)}\n />\n ))}\n </Card>\n )}\n\n {/* 跳过 */}\n {applyPlan.skipped.length > 0 && (\n <Card>\n <SectionTitle title={`无变化(${applyPlan.skipped.length})`} />\n <ul>\n {applyPlan.skipped.map((r) => (\n <li key={r.id}><code>{r.id}</code> —— skip(无变化)</li>\n ))}\n </ul>\n </Card>\n )}\n </div>\n );\n}\n\ninterface ReviewItemRowProps {\n item: ReviewDisplayItem\n state: ItemDecisionState['status']\n onDecide: (d: 'useRemote' | 'keepLocal' | 'skip') => void\n}\n\nfunction ReviewItemRow({ item, state, onDecide }: ReviewItemRowProps): ReactNode {\n return (\n <div className={`review-item state-${state}`}>\n <div className=\"review-item-header\">\n <code>{item.sectionId}</code> <span>{item.description}</span>\n <Badge kind={state === 'pending' ? 'warn' : 'ok'}>{labelForState(state)}</Badge>\n </div>\n {item.conflicts.length > 0 && (\n <details>\n <summary>差异({item.conflicts.length})</summary>\n <pre>\n {item.conflicts.map((c, i) => (\n <div key={i}>{formatDiff(c.local, c.remote)}</div>\n ))}\n </pre>\n </details>\n )}\n <div className=\"review-item-actions\">\n <Button variant=\"ghost\" disabled={state !== 'pending'} onClick={() => onDecide('keepLocal')}>用本地</Button>\n <Button variant=\"primary\" disabled={state !== 'pending'} onClick={() => onDecide('useRemote')}>用远端</Button>\n <Button variant=\"ghost\" disabled={state !== 'pending'} onClick={() => onDecide('skip')}>跳过</Button>\n </div>\n </div>\n );\n}\n\nfunction labelForState(s: ItemDecisionState['status']): string {\n switch (s) {\n case 'pending': return '待决';\n case 'useRemote': return '已选:远端';\n case 'keepLocal': return '已选:本地';\n case 'skip': return '已选:跳过';\n }\n}\n","/**\n * 远程同步面板(备份与迁移页的第 4 个 tab 内容)。\n *\n * 独立设置页壳(sectionHeader/close/自身 tab)已移除 —— tab 容器由\n * ConfigManagerSection 统一渲染,本组件只输出内容体:\n * - 仓库配置表单:repoUrl(必填)+ 认证 token(可选,写入 DSH credentials 的提示)\n * + gitBin(可选);\n * - 私有仓库强制提示横幅(常驻);\n * - 推送按钮 → SyncPushReport(快照 id / 分区 / 告警);\n * - 拉取按钮 → SyncPullReport.changes 差异摘要(description/kind/severity)+\n * 「预览不执行导入」提示;needsReview 高亮(v1 不做完整导入接线);\n * - 状态行:凭据配置 + 上次同步时间 + 通道(来自 GET /sync/status,组件挂载时加载)。\n *\n * 全部渲染模型来自 ./sync-view.ts 纯函数(node 单测覆盖),组件只做装配;\n * 状态组件内自持(低频显式操作,同 SnapshotsPanel 策略,不进 sessionStorage);\n * token 仅内存(state),成功后清空(已写入 DSH credentials),绝不持久化。\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { ChangeEvent } from 'react'\nimport type { TranslateNS } from '../client-types.ts'\nimport type { ApplyReport, SyncPullReport, SyncPushReport } from '../../sync/sync-engine.ts'\nimport { Badge, Banner, Button, Card, SectionTitle, Spinner } from '../common/ui.tsx'\nimport { ErrorBanner } from '../common/ErrorBanner.tsx'\nimport { SYNC_CREDENTIAL_REF } from './sync-api.ts'\nimport type { SyncApi, SyncStatusResponse } from './sync-api.ts'\nimport {\n computeGithubLoginView, computeSyncButtons, computeSyncStatus, githubPollMessage,\n kindLabel, privateRepoHint, pullReportView, pushReportView, severityLabel,\n} from './sync-view.ts'\nimport type { GithubLoginPhase } from './sync-view.ts'\nimport { SyncHistoryView } from './SyncHistoryView.tsx'\nimport { SyncPullPreviewView } from './SyncPullPreviewView.tsx'\nimport type { SyncApplyPlan } from '../../sync/risk.ts'\nimport css from '../config-manager.module.css'\n\nexport interface SyncSettingsViewProps {\n api: SyncApi\n t: TranslateNS<'config-manager-sync'>\n}\n\ninterface SyncUiState {\n loading: boolean\n loadError: string | null\n statusInfo: SyncStatusResponse | null\n repoUrl: string\n gitBin: string\n /** 仅内存:成功后清空(已写入 DSH credentials),绝不持久化 */\n token: string\n busy: 'push' | 'pull' | 'apply' | 'rollback' | null\n pushReport: SyncPushReport | null\n pullReport: SyncPullReport | null\n applyReport: ApplyReport | null\n error: string | null\n /** GitHub OAuth device flow 状态(flowId/userCode 仅内存,token 只存宿主) */\n github: GithubUiState\n}\n\ninterface GithubUiState {\n phase: GithubLoginPhase\n flowId: string\n userCode: string\n verificationUri: string\n /** GitHub 建议轮询间隔秒数(pending 重排时兜底用) */\n interval: number\n error: string | null\n}\n\nconst initialGithub: GithubUiState = {\n phase: 'idle', flowId: '', userCode: '', verificationUri: '', interval: 5, error: null,\n}\n\nconst initial: SyncUiState = {\n loading: true,\n loadError: null,\n statusInfo: null,\n repoUrl: '',\n gitBin: '',\n token: '',\n busy: null,\n pushReport: null,\n pullReport: null,\n applyReport: null,\n error: null,\n github: initialGithub,\n}\n\nexport function SyncSettingsView({ api, t }: SyncSettingsViewProps) {\n const [state, setState] = useState<SyncUiState>(initial)\n const uiT = api.t // 客户端展示层翻译器(zh/en,见 ui/i18n.ts)\n const patch = (p: Partial<SyncUiState>): void => setState((s) => ({ ...s, ...p }))\n const patchGithub = (p: Partial<GithubUiState>): void => setState((s) => ({ ...s, github: { ...s.github, ...p } }))\n /** GitHub 轮询定时器(卸载/取消时清理,防止泄漏与跨流程串扰) */\n const githubPollTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n /** 挂载时读取同步状态(配置回填 + 上次同步时间 + 凭据状态) */\n const loadStatus = async (): Promise<void> => {\n patch({ loading: true, loadError: null })\n try {\n const info = await api.status()\n patch({ loading: false, statusInfo: info, repoUrl: info.repoUrl ?? '', gitBin: info.gitBin ?? '' })\n } catch (err) {\n patch({ loading: false, loadError: err instanceof Error ? err.message : String(err) })\n }\n }\n\n useEffect(() => {\n void loadStatus()\n // api 为注入单例(注册时创建),生命周期内稳定;仅挂载时加载一次\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n /** 卸载时清理轮询定时器(组件销毁后不得再 setState/发请求) */\n useEffect(() => () => {\n if (githubPollTimer.current !== null) clearTimeout(githubPollTimer.current)\n }, [])\n\n /** 表单快照 → 请求体(token 为空串不携带;gitBin 空串不携带) */\n const payload = (): { repoUrl: string; gitBin?: string; token?: string } => ({\n repoUrl: state.repoUrl.trim(),\n gitBin: state.gitBin.trim() !== '' ? state.gitBin.trim() : undefined,\n token: state.token.trim() !== '' ? state.token : undefined,\n })\n\n /* ------------------------------------------------ GitHub OAuth device flow */\n\n /** 发起 GitHub 登录:取设备码 → 展示一次性用户码 + 授权页 → 开始轮询 */\n const runGithubStart = async (): Promise<void> => {\n patchGithub({ phase: 'starting', error: null })\n try {\n const info = await api.githubStart()\n patchGithub({\n phase: 'waiting',\n flowId: info.flowId,\n userCode: info.userCode,\n verificationUri: info.verificationUri,\n interval: info.interval,\n })\n scheduleGithubPoll(info.flowId, Math.max(info.interval, 1) * 1000)\n } catch (err) {\n patchGithub({ phase: 'error', error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** 排定一次 GitHub 轮询(先清旧定时器,避免重复轮询) */\n const scheduleGithubPoll = (flowId: string, delayMs: number): void => {\n if (githubPollTimer.current !== null) clearTimeout(githubPollTimer.current)\n githubPollTimer.current = setTimeout(() => { void runGithubPoll(flowId) }, delayMs)\n }\n\n /** 轮询 GitHub 授权结果:pending 继续等;success 刷新凭据状态;终止态展示结果 */\n const runGithubPoll = async (flowId: string): Promise<void> => {\n patchGithub({ phase: 'polling' })\n try {\n const poll = await api.githubPoll(flowId)\n if (poll.status === 'pending') {\n patchGithub({ phase: 'waiting' })\n scheduleGithubPoll(flowId, poll.pollDelayMs ?? Math.max(state.github.interval, 1) * 1000)\n return\n }\n const message = githubPollMessage(poll, uiT)\n if (poll.status === 'success') {\n patchGithub({ phase: 'success', error: null })\n // token 已由宿主写入 DSH credentials:刷新状态行与凭据徽章\n void loadStatus()\n } else {\n patchGithub({ phase: 'error', error: message })\n }\n } catch (err) {\n patchGithub({ phase: 'error', error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** 取消登录:停轮询 + 通知宿主丢弃设备码登记 + 复位 UI */\n const runGithubCancel = async (): Promise<void> => {\n if (githubPollTimer.current !== null) {\n clearTimeout(githubPollTimer.current)\n githubPollTimer.current = null\n }\n const flowId = state.github.flowId\n patchGithub(initialGithub)\n if (flowId !== '') {\n try { await api.githubCancel(flowId) } catch { /* 取消失败无需打扰用户 */ }\n }\n }\n\n const runPush = async (): Promise<void> => {\n patch({ busy: 'push', error: null, pushReport: null, pullReport: null })\n try {\n const report = await api.push(payload())\n // 成功即清空 token(已安全写入 DSH credentials);失败保留以便重试\n patch({ busy: null, pushReport: report, token: report.ok ? '' : state.token })\n } catch (err) {\n patch({ busy: null, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n const runPull = async (): Promise<void> => {\n patch({ busy: 'pull', error: null, pullReport: null, pushReport: null })\n try {\n const report = await api.pull(payload())\n patch({ busy: null, pullReport: report, token: '' })\n } catch (err) {\n patch({ busy: null, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** P2:自动应用(Host 端 engine.merge + classifyMergePlan + applyMergePlan 走完整链路) */\n const runApply = async (): Promise<void> => {\n patch({ busy: 'apply', error: null, applyReport: null })\n try {\n const report = await api.apply(payload())\n patch({ busy: null, applyReport: report })\n } catch (err) {\n patch({ busy: null, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** P2:一键回滚(按 apply 返回的 restoreId 调 Host /sync/rollback) */\n const runRollback = async (restoreId: string): Promise<void> => {\n patch({ busy: 'rollback', error: null })\n try {\n await api.rollback({ restoreId })\n patch({ busy: null, applyReport: null })\n } catch (err) {\n patch({ busy: null, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n const status = computeSyncStatus(state.statusInfo, state.loading, state.loadError, uiT)\n const buttons = computeSyncButtons(state.busy, state.repoUrl, uiT)\n const pushView = pushReportView(state.pushReport, uiT)\n const pullView = pullReportView(state.pullReport, uiT)\n const githubView = computeGithubLoginView(\n state.github.phase, state.github.userCode, state.github.verificationUri, state.github.error, uiT,\n )\n /** GitHub 流程进行中(请求设备码 / 等待授权 / 轮询):禁用 push/pull,避免无凭据操作 */\n const githubBusy =\n state.github.phase === 'starting' || state.github.phase === 'waiting' || state.github.phase === 'polling'\n\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('section.label')} subtitle={t('section.description')} />\n\n {/* 私有仓库强制提示 */}\n <Banner kind=\"warn\">{privateRepoHint(uiT)}</Banner>\n\n {/* 仓库配置 */}\n <Card>\n <span className={css.groupLabel}>{t('config.title')}</span>\n <label className={css.field}>\n <span className={css.fieldLabel}>{t('config.repoUrl')}</span>\n <input\n type=\"text\"\n className={css.input}\n value={state.repoUrl}\n placeholder=\"https://github.com/user/private-repo.git\"\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { patch({ repoUrl: e.target.value }) }}\n />\n <span className={css.hint}>{t('config.repoUrlHint')}</span>\n </label>\n <label className={css.field}>\n <span className={css.fieldLabel}>\n {t('config.token')}\n {' '}\n {state.statusInfo?.credentialConfigured === true && <Badge kind=\"ok\">{t('config.tokenSaved')}</Badge>}\n </span>\n <input\n type=\"password\"\n className={css.input}\n value={state.token}\n autoComplete=\"off\"\n placeholder=\"ghp_…(可选)\"\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { patch({ token: e.target.value }) }}\n />\n <span className={css.hint}>{t('config.tokenHint', { ref: SYNC_CREDENTIAL_REF })}</span>\n </label>\n\n {/* GitHub OAuth 登录(device flow):无需手动输入 token */}\n <span className={css.groupLabel}>{t('github.title')}</span>\n <span className={css.hint}>{t('github.description')}</span>\n {githubView.showCode && (\n <div className={css.statRow}>\n <Badge kind=\"info\">{t('github.userCode')}:<strong>{githubView.userCode}</strong></Badge>\n <a\n className={css.ghostButton}\n href={githubView.verificationUri}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{ textDecoration: 'none' }}\n >\n {t('github.openAuth')}\n </a>\n </div>\n )}\n <div className={css.actionRow}>\n <Button\n variant=\"primary\"\n disabled={!githubView.canStart || state.busy !== null}\n onClick={() => { void runGithubStart() }}\n >\n {githubView.startLabel}\n </Button>\n {githubView.canCancel && (\n <Button disabled={state.busy !== null} onClick={() => { void runGithubCancel() }}>\n {t('github.cancel')}\n </Button>\n )}\n </div>\n <div className={css.statRow}>\n <Badge kind={githubView.phase === 'success' ? 'ok' : githubView.phase === 'error' ? 'error' : 'warn'}>\n {githubView.statusText}\n </Badge>\n </div>\n {githubView.phase === 'error' && (\n <span className={css.hint}>{t('config.tokenHint', { ref: SYNC_CREDENTIAL_REF })}</span>\n )}\n\n <label className={css.field}>\n <span className={css.fieldLabel}>{t('config.gitBin')}</span>\n <input\n type=\"text\"\n className={css.input}\n value={state.gitBin}\n placeholder=\"git\"\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { patch({ gitBin: e.target.value }) }}\n />\n <span className={css.hint}>{t('config.gitBinHint')}</span>\n </label>\n </Card>\n\n {/* 同步状态 */}\n <Card>\n <span className={css.groupLabel}>{t('status.title')}</span>\n <div className={css.statRow}>\n <Badge kind={status.kind === 'ready' ? 'ok' : status.kind === 'error' ? 'error' : 'warn'}>{status.text}</Badge>\n </div>\n </Card>\n\n {/* 操作 */}\n <div className={css.actionRow}>\n <Button variant=\"primary\" disabled={!buttons.canPush || githubBusy} onClick={() => { void runPush() }}>\n {state.busy === 'push' ? <Spinner label={buttons.pushLabel} /> : buttons.pushLabel}\n </Button>\n <Button disabled={!buttons.canPull || githubBusy} onClick={() => { void runPull() }}>\n {state.busy === 'pull' ? <Spinner label={buttons.pullLabel} /> : buttons.pullLabel}\n </Button>\n </div>\n\n {state.error !== null && <ErrorBanner error={state.error} />}\n\n {/* 推送结果 */}\n {pushView !== null && (\n <Card>\n <span className={css.groupLabel}>{t('push.title')}</span>\n <Banner kind={pushView.kind === 'ok' ? 'ok' : 'error'}>{pushView.headline}</Banner>\n {pushView.sections.length > 0 && (\n <div>\n <span className={css.fieldLabel}>{t('sections.title')}</span>\n <div className={css.statRow}>\n {pushView.sections.map((s) => <Badge key={s} kind=\"info\">{s}</Badge>)}\n </div>\n </div>\n )}\n {pushView.warnings.length > 0 && (\n <div>\n <span className={css.fieldLabel}>{t('warnings.title')}</span>\n <ul className={css.warnList}>\n {pushView.warnings.map((w, i) => <li key={i}>{w}</li>)}\n </ul>\n </div>\n )}\n </Card>\n )}\n\n {/* 拉取差异预览 */}\n {pullView !== null && (\n <Card>\n <span className={css.groupLabel}>{t('pull.title')}</span>\n <Banner kind={pullView.kind === 'ok' ? 'info' : pullView.kind === 'empty' ? 'ok' : 'error'}>{pullView.headline}</Banner>\n {pullView.summary !== null && (\n <>\n <div className={css.statRow}>\n <Badge kind=\"info\">{t('change.total', { total: pullView.summary.total })}</Badge>\n {pullView.summary.error > 0 && <Badge kind=\"error\">{severityLabel('error', uiT)} × {pullView.summary.error}</Badge>}\n {pullView.summary.warning > 0 && <Badge kind=\"warn\">{severityLabel('warning', uiT)} × {pullView.summary.warning}</Badge>}\n {pullView.summary.info > 0 && <Badge kind=\"info\">{severityLabel('info', uiT)} × {pullView.summary.info}</Badge>}\n </div>\n {pullView.summary.needsReview && <Banner kind=\"warn\">{t('pull.needsReview')}</Banner>}\n <div className={css.reportList}>\n {pullView.summary.items.map((c) => (\n <div key={c.id} className={css.statRow}>\n <span className={css.kindTag}>{kindLabel(c.kind, uiT)}</span>\n <Badge kind={c.severity === 'error' ? 'error' : c.severity === 'warning' ? 'warn' : 'info'}>\n {severityLabel(c.severity, uiT)}\n </Badge>\n <span>{c.description}</span>\n </div>\n ))}\n </div>\n </>\n )}\n {pullView.previewHint !== '' && <Banner kind=\"info\">{pullView.previewHint}</Banner>}\n </Card>\n )}\n\n {/* P2:自动应用(拉取后可触发;Host 端合并 + 写本地 + 失败回滚) */}\n <div className={css.actionRow}>\n <Button\n variant=\"primary\"\n disabled={state.busy !== null || state.pullReport === null}\n onClick={() => { void runApply() }}\n >\n {state.busy === 'apply' ? <Spinner label=\"自动应用中…\" /> : '自动应用(合并 + 写本地)'}\n </Button>\n </div>\n\n {/* P2:自动应用结果 */}\n {state.applyReport !== null && (\n <Card>\n <span className={css.groupLabel}>自动应用结果</span>\n <Banner kind={state.applyReport.ok ? 'ok' : 'error'}>\n {state.applyReport.ok\n ? `已应用 ${state.applyReport.applied.length} 个分区(restoreId=${state.applyReport.restoreId})`\n : `自动应用失败(已整体回滚,restoreId=${state.applyReport.restoreId})`}\n </Banner>\n {state.applyReport.applied.length > 0 && (\n <div>\n <span className={css.fieldLabel}>已写入</span>\n <div className={css.statRow}>\n {state.applyReport.applied.map((sid) => <Badge key={sid} kind=\"ok\">{sid}</Badge>)}\n </div>\n </div>\n )}\n {state.applyReport.warnings.length > 0 && (\n <div>\n <span className={css.fieldLabel}>告警</span>\n <ul className={css.warnList}>\n {state.applyReport.warnings.map((w, i) => <li key={i}>{w}</li>)}\n </ul>\n </div>\n )}\n {state.applyReport.review.length > 0 && (\n <div>\n <span className={css.fieldLabel}>待审(已入 sync-review-queue.json)</span>\n <ul className={css.warnList}>\n {state.applyReport.review.map((r, i) => <li key={i}>{r.sectionId} — {r.description}</li>)}\n </ul>\n </div>\n )}\n {!state.applyReport.ok && state.applyReport.restoreId !== '' && (\n <Button\n variant=\"danger\"\n disabled={state.busy !== null}\n onClick={() => { void runRollback(state.applyReport!.restoreId) }}\n >\n {state.busy === 'rollback' ? <Spinner label=\"回滚中…\" /> : '回滚到应用前'}\n </Button>\n )}\n </Card>\n )}\n\n {/* P2:同步历史视图(Host /sync/history 端点) */}\n <SyncHistoryView api={api} />\n </div>\n )\n}","/**\n * Config Manager 设置页(settings.section 入口的主页面容器)。\n *\n * 业务面(api)由注册时的 inject face 注入;t 由 locale seat 注入。\n * 关闭按钮由 settings shell 自带,本页不再渲染。内部两个主视图:\n * Export(Quick/Custom)与 Import(九步向导)。\n *\n * m2:主视图 tab(view)与全部子视图状态统一由模块级 runStore 持有\n * (sessionStorage 持久化 + 切 tab/关面板不重建控制器实例);挂载时\n * 经 GET /runs + 轮询 /progress 恢复进行中的 run(刷新/重开面板后)。\n */\nimport { useEffect, useSyncExternalStore, useState } from 'react'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ConfigManagerSectionInjected, TranslateNS } from './client-types.ts'\nimport { runStore, type MainView } from './run-store.ts'\nimport { ExportView } from './export/ExportView.tsx'\nimport { ImportWizardView } from './import/ImportWizardView.tsx'\nimport { SnapshotsPanel } from './snapshots/SnapshotsPanel.tsx'\nimport { SyncSettingsView } from './sync/SyncSettingsView.tsx'\nimport css from './config-manager.module.css'\n\nexport type ConfigManagerSectionProps =\n & PropsRuntime<'settings.section'>\n & ConfigManagerSectionInjected\n & { t: TranslateNS<'config-manager'> }\n\n/**\n * 设置页容器:Export / Import / Snapshots / Sync 四视图切换。\n * Export/Import 状态在模块级 store(切 tab 不丢失);快照恢复与远程同步为低频显式\n * 操作,其状态组件内自持(local state,不进 sessionStorage)。\n */\nexport function ConfigManagerSection({ api, syncApi, syncT, t }: ConfigManagerSectionProps) {\n const state = useSyncExternalStore(runStore.subscribe, runStore.getSnapshot)\n const view = state.view\n const [snapshotsOpen, setSnapshotsOpen] = useState(false)\n const [syncOpen, setSyncOpen] = useState(false)\n\n // m2-resume:挂载时重新订阅进行中的 run(刷新 / 重开面板后服务端继续执行,\n // 这里经 /runs 找回活跃 runId 再轮询 /progress);卸载时停止轮询,重开再订阅。\n useEffect(() => {\n void runStore.resume(api)\n return () => {\n runStore.stopResume()\n }\n }, [api])\n\n const setView = (next: MainView): void => {\n setSnapshotsOpen(false)\n setSyncOpen(false)\n runStore.patch({ view: next })\n }\n\n const openSnapshots = (): void => {\n setSnapshotsOpen(true)\n setSyncOpen(false)\n }\n\n const openSync = (): void => {\n setSyncOpen(true)\n setSnapshotsOpen(false)\n }\n\n const activeTab: MainView | 'snapshots' | 'sync' = syncOpen ? 'sync' : snapshotsOpen ? 'snapshots' : view\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={activeTab === 'export'}\n data-active={activeTab === '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={activeTab === 'import'}\n data-active={activeTab === 'import' ? '' : undefined}\n className={css.viewTab}\n onClick={() => { setView('import') }}\n >\n {t('view.import')}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === 'snapshots'}\n data-active={snapshotsOpen ? '' : undefined}\n className={css.viewTab}\n onClick={openSnapshots}\n >\n {t('view.snapshots')}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === 'sync'}\n data-active={syncOpen ? '' : undefined}\n className={css.viewTab}\n onClick={openSync}\n >\n {t('view.sync')}\n </button>\n </div>\n </div>\n <div className={css.sectionBody}>\n {syncOpen\n ? <SyncSettingsView api={syncApi} t={syncT} />\n : snapshotsOpen\n ? <SnapshotsPanel api={api} t={t} />\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 'view.snapshots': '快照恢复',\n 'view.sync': '远程同步',\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.reselect': '重新选择',\n 'import.select.cancel': '取消选择',\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 'snapshots.title': '快照恢复',\n 'snapshots.hint': '恢复到导入前状态:整文件还原 settings/patch、卸载导入期间新增插件、补偿被修改文件。执行前会把当前文件备份到快照的 pre-restore 目录。',\n 'snapshots.empty': '暂无快照。执行导入时会自动创建安全快照。',\n 'snapshots.loading': '加载快照中…',\n 'snapshots.selectHint': '选择快照以预览恢复计划(dry-run,零写入):',\n 'snapshots.createdAt': '创建时间',\n 'snapshots.sourceZip': '来源备份',\n 'snapshots.status': '状态',\n 'snapshots.entries': '条目',\n 'snapshots.plugins': '插件',\n 'snapshots.status.pending': '进行中',\n 'snapshots.status.done': '已完成',\n 'snapshots.status.rolled-back': '已回滚',\n 'snapshots.status.unknown': '未知',\n 'snapshots.planTitle': '恢复计划预览',\n 'snapshots.noActions': '该快照无可用恢复动作(或全部跳过)。',\n 'snapshots.execute': '执行恢复',\n 'snapshots.executing': '恢复执行中…',\n 'snapshots.confirmRestore': '确认执行恢复?当前文件会先备份到快照的 pre-restore 目录,插件通过官方 dsh plugin remove 卸载。',\n 'snapshots.reportTitle': '恢复报告',\n 'snapshots.restored': '已还原',\n 'snapshots.removedPlugins': '已卸载插件',\n 'snapshots.manualHints': '需人工处理',\n 'snapshots.failed': '失败',\n 'snapshots.skipped': '跳过',\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 'view.snapshots': 'Snapshots & Restore',\n 'view.sync': 'Remote Sync',\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.reselect': 'Reselect',\n 'import.select.cancel': 'Cancel selection',\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… (installing many plugins may take a few minutes; keep this page open)',\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 'snapshots.title': 'Snapshot Restore',\n 'snapshots.hint': 'Restore to the pre-import state: whole-file restore of settings/patch, uninstall plugins added during import, compensate modified files. Current files are backed up to the snapshot\\'s pre-restore folder before any change.',\n 'snapshots.empty': 'No snapshots yet. A safety snapshot is created automatically on import.',\n 'snapshots.loading': 'Loading snapshots…',\n 'snapshots.selectHint': 'Select a snapshot to preview its restore plan (dry-run, zero writes):',\n 'snapshots.createdAt': 'Created',\n 'snapshots.sourceZip': 'Source',\n 'snapshots.status': 'Status',\n 'snapshots.entries': 'Entries',\n 'snapshots.plugins': 'Plugins',\n 'snapshots.status.pending': 'Pending',\n 'snapshots.status.done': 'Done',\n 'snapshots.status.rolled-back': 'Rolled back',\n 'snapshots.status.unknown': 'Unknown',\n 'snapshots.planTitle': 'Restore Plan Preview',\n 'snapshots.noActions': 'No restorable actions for this snapshot (or all skipped).',\n 'snapshots.execute': 'Restore now',\n 'snapshots.executing': 'Restoring…',\n 'snapshots.confirmRestore': 'Confirm restore? Current files are backed up to the snapshot\\'s pre-restore folder first; plugins are removed via the official dsh plugin remove.',\n 'snapshots.reportTitle': 'Restore Report',\n 'snapshots.restored': 'Restored',\n 'snapshots.removedPlugins': 'Removed plugins',\n 'snapshots.manualHints': 'Manual action needed',\n 'snapshots.failed': 'Failed',\n 'snapshots.skipped': 'Skipped',\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 * 远程同步设置区块(config-manager-sync)表面文案:zh 为源语言,en 镜像每个键。\n * 独立命名空间、独立文件:不触碰共享的 locales.ts(并行会话已改),零冲突。\n * 键集合经 `SyncKey` 类型在 client/index.ts 注册处做编译期校验。\n */\n\nexport const zh = {\n // 入口\n 'section.label': '远程同步',\n 'section.description': '通过 Git 私有仓库在设备间同步可移植配置(secret 永不参与同步)',\n // 私有仓库强制提示(常驻警示横幅)\n 'privateRepoHint': '安全要求:同步仓库必须为私有仓库(public 仓库会公开你的配置内容)。认证 token 仅用于仓库访问,绝不写入同步文件、提交内容或日志。',\n // 仓库配置表单\n 'config.title': '仓库配置',\n 'config.repoUrl': '仓库地址',\n 'config.repoUrlHint': 'Git 私有仓库地址(https / ssh / 本地路径)。认证 token 请使用下方凭据字段,不要拼入地址。',\n 'config.token': '认证 token',\n 'config.tokenHint': '将安全写入 DSH credentials(引用名 {ref}),不会写入同步文件或日志。留空表示沿用已保存的凭据。',\n 'config.tokenSaved': '凭据已配置',\n 'config.gitBin': 'git 可执行文件(可选)',\n 'config.gitBinHint': '缺省使用 PATH 中的 git。',\n // GitHub OAuth 登录(device flow,无需手动输入 token)\n 'github.title': 'GitHub 登录',\n 'github.description': '通过 GitHub OAuth 设备码流程授权:无需手动输入 token,在浏览器中确认授权后,token 自动写入 DSH credentials。',\n 'github.login': '使用 GitHub 登录',\n 'github.retry': '重新登录',\n 'github.cancel': '取消',\n 'github.userCode': '一次性授权代码',\n 'github.openAuth': '打开 GitHub 授权页面',\n 'github.clientIdHint': '需要插件配置 githubClientId(GitHub OAuth App 的 client_id)才能使用 GitHub 登录。',\n // 状态\n 'status.title': '同步状态',\n 'status.never': '从未同步',\n // 操作\n 'action.push': '推送到远端',\n 'action.pull': '拉取差异预览',\n 'action.pushing': '正在推送…',\n 'action.pulling': '正在拉取…',\n // 报告\n 'push.title': '推送结果',\n 'pull.title': '拉取差异预览',\n 'pull.previewHint': '以上为只读差异预览,不会执行导入。v1 暂不提供一键导入接线;如需应用远端配置,请使用「导入恢复」向导手动导入导出的备份。',\n 'pull.needsReview': '包含需要人工决策的项(冲突 / 密钥 / 依赖 / 安装)',\n 'pull.empty': '远端快照与本地一致(无变更)',\n 'change.total': '共 {total} 项变更',\n 'sections.title': '同步分区',\n 'warnings.title': '分区告警',\n // 公共\n 'common.close': '关闭',\n 'common.retry': '重试',\n 'common.loading': '加载中…',\n} as const;\n\nexport const en: Record<keyof typeof zh, string> = {\n 'section.label': 'Remote Sync',\n 'section.description': 'Sync portable configuration across devices via a private Git repository (secrets never sync)',\n 'privateRepoHint': 'Security requirement: the sync repository MUST be private (a public repo would expose your configuration). The auth token is only used for repository access and is never written into sync files, commit content, or logs.',\n 'config.title': 'Repository',\n 'config.repoUrl': 'Repository URL',\n 'config.repoUrlHint': 'Private Git repository URL (https / ssh / local path). Use the credential field below for the auth token; never embed it in the URL.',\n 'config.token': 'Auth token',\n 'config.tokenHint': 'Securely written into DSH credentials (ref {ref}); never written into sync files or logs. Leave blank to reuse the saved credential.',\n 'config.tokenSaved': 'Credential configured',\n 'config.gitBin': 'git executable (optional)',\n 'config.gitBinHint': 'Defaults to git on PATH.',\n 'github.title': 'GitHub Sign-in',\n 'github.description': 'Authorize via the GitHub OAuth device flow: no manual token entry — after you approve in the browser, the token is written into DSH credentials automatically.',\n 'github.login': 'Sign in with GitHub',\n 'github.retry': 'Sign in again',\n 'github.cancel': 'Cancel',\n 'github.userCode': 'One-time code',\n 'github.openAuth': 'Open GitHub authorization page',\n 'github.clientIdHint': 'Requires the githubClientId plugin config (the client_id of your GitHub OAuth App).',\n 'status.title': 'Sync Status',\n 'status.never': 'Never synced',\n 'action.push': 'Push to remote',\n 'action.pull': 'Pull diff preview',\n 'action.pushing': 'Pushing…',\n 'action.pulling': 'Pulling…',\n 'push.title': 'Push Result',\n 'pull.title': 'Pull Diff Preview',\n 'pull.previewHint': 'Read-only diff preview above; nothing is imported. v1 does not wire one-click import yet — use the Import wizard to apply a downloaded backup if needed.',\n 'pull.needsReview': 'Contains items that need human decisions (conflicts / secrets / dependencies / installs)',\n 'pull.empty': 'Remote snapshot matches local (no changes)',\n 'change.total': '{total} change(s)',\n 'sections.title': 'Synced Sections',\n 'warnings.title': 'Section Warnings',\n 'common.close': 'Close',\n 'common.retry': 'Retry',\n 'common.loading': 'Loading…',\n};\n\n/** 字典键联合(注册处 compile-time 校验) */\nexport type SyncKey = 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'\nimport { makeUiT, type UiT } from '../ui/i18n.ts'\nimport { SyncApi } from './sync/sync-api.ts'\nimport { SyncSettingsView } from './sync/SyncSettingsView.tsx'\nimport { en as syncEn, zh as syncZh, type SyncKey } from './sync/sync-locales.ts'\n\n/** 本插件拥有的 locale namespace。 */\nconst NS = 'config-manager'\n/** 远程同步设置区块的独立 locale namespace(独立字典文件,不与共享 locales.ts 冲突)。 */\nconst SYNC_NS = 'config-manager-sync'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Config Manager 表面文案。 */\n 'config-manager': ConfigManagerKey\n /** 远程同步设置区块文案(m-sync-ui)。 */\n 'config-manager-sync': SyncKey\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 { SyncSettingsViewProps } from './sync/SyncSettingsView.tsx'\nexport type { ConfigManagerApiError, DownloadResult, ServiceStatus, UploadResponse } from './api.ts'\nexport type { ConfigManagerKey } from './locales.ts'\nexport type { SyncKey } from './sync/sync-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 ctx.effect(() => ctx.locale.register(SYNC_NS, { zh: syncZh, en: syncEn }), 'config-manager: sync dictionaries')\n\n const t = ctx.locale.bind(NS)\n // 客户端展示层(报告/错误/进度/sync-view)翻译器:locale active 为 'en' 时用 en 目录。\n const uiT: UiT = makeUiT(ctx.locale.getLocale().active === 'en' ? 'en' : 'zh')\n const api = new ConfigManagerApi(uiT)\n const syncT = ctx.locale.bind(SYNC_NS)\n const syncApi = new SyncApi(uiT)\n\n // 单一 settings.section:备份与迁移页(内部 Export/Import/Snapshots/Sync 四 tab)。\n // 远程同步不再注册独立设置页 —— 并入主 section 的 inject 面(syncApi/syncT),\n // 由 ConfigManagerSection 渲染第 4 个 tab。避免第二个 settings.section 注册在\n // 目标 DSH 渲染 section 列表时抛错导致整页空白。\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, syncApi, syncT }),\n }, ConfigManagerSection))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["readJson","css","css","css","css","css","css","css","css","initial","css","formatDateTime","css","css","css","css","zh","en","syncZh","syncEn"],"sources":["../src/ui/i18n.ts","../src/client/api.ts","../src/ui/conflict-view.ts","../src/ui/types.ts","../src/ui/progress.ts","../src/ui/report.ts","../src/ui/export-flow.ts","../src/security/secret-scanner.ts","../src/security/redaction.ts","../src/ui/errors.ts","../src/ui/import-wizard.ts","../src/client/run-store.ts","../src/client/common/ui.tsx","../src/client/common/ErrorBanner.tsx","../src/client/common/progress-view.ts","../src/client/common/ProgressBar.tsx","../src/client/common/ReportView.tsx","../src/client/export/ExportView.tsx","../src/ui/flow.ts","../src/client/import/ConflictList.tsx","../src/client/import/PathMappingForm.tsx","../src/client/import/import-file-select.ts","../src/client/import/ImportWizardView.tsx","../src/client/snapshots/SnapshotsPanel.tsx","../src/client/sync/sync-api.ts","../src/client/sync/sync-view.ts","../src/client/sync/history-model.ts","../src/client/sync/SyncHistoryView.tsx","../src/client/sync/SyncConfirmView.tsx","../src/client/sync/SyncSettingsView.tsx","../src/client/ConfigManagerSection.tsx","../src/client/locales.ts","../src/client/sync/sync-locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * 客户端展示层(src/ui/*、src/client/common/*)的渲染文案目录(zh 源语言 / en 镜像)。\n *\n * 与 core 的 messages.ts 分工:本目录负责「客户端纯渲染层」(ReportView / ErrorBanner /\n * ProgressBar / sync-view)产生的中文文案;core 侧引擎消息已随 API 数据源翻译。\n * 这些纯函数原先直接内嵌中文,现经 UiDict 注入:Client 挂载时按 ctx.locale 提供。\n *\n * 纪律:\n * - TextKey 类型 = keyof typeof uiZh,en 缺键/多键即编译错误;\n * - {param} 插值,缺参原样保留。\n */\n\nexport const uiZh = {\n // 通用\n 'commonClose': '关闭',\n 'commonCancel': '取消',\n 'commonRetry': '重试',\n 'commonLoading': '加载中…',\n 'commonUnknownError': '未知错误',\n 'commonNext': '下一步',\n 'commonBack': '上一步',\n 'commonDone': '完成',\n // 导出\n 'export.download': '下载备份文件',\n 'export.running': '正在导出…',\n 'export.run': '开始导出',\n 'export.selectionWarnings': '以下分区为设备相关数据,跨设备导入时可能不适用:',\n 'export.included': '已包含',\n 'export.excluded': '未包含',\n 'export.unknownSection': '未知分区:{id}',\n 'export.deviceSpecific': '{label} 为设备相关数据({portability}),跨设备导入时可能不适用',\n // 报告\n 'report.backupCreated': '备份已创建',\n 'report.importComplete': '导入完成',\n 'report.importFailed': '导入失败',\n 'report.included': '已包含:',\n 'report.excluded': '未包含:',\n 'report.security': '安全:',\n 'report.apiKeysExcluded': 'API 密钥已排除:',\n 'report.containsSecrets': '包含密钥:',\n 'report.encrypted': '已加密:',\n 'report.redacted': '{count} 个敏感字段已脱敏',\n 'report.file': '文件:',\n 'report.yes': '是',\n 'report.yesEncrypted': '是(加密)',\n 'report.no': '否',\n 'report.importedRestored': '已导入/恢复',\n 'report.skipped': '跳过',\n 'report.needAttention': '需注意',\n 'report.failed': '失败',\n 'report.noChanges': '无变更',\n 'report.reason': '原因',\n 'report.note': '说明',\n 'report.unknownReason': '未知原因',\n 'report.secrets': '密钥:',\n 'report.credentialsNeedEntry': '{count} 个凭据需要补录',\n 'report.restartRequired': '重启 DSH 后生效:{detail}',\n 'report.restartPluginsMcp': '插件/MCP 更改将在重启 DSH 后生效',\n 'report.rollbackFull': '回滚:已完整恢复导入前的配置。',\n 'report.rollbackPartial': '回滚部分完成。',\n 'report.rollbackManual': '以下项目可能需要人工恢复:',\n 'report.restored': '已恢复:{count} 项',\n // 错误\n 'error.notMounted': 'config-manager 服务未挂载(插件未加载):请确认 profile 中已安装 dsh-config-manager 并重启 DSH',\n 'error.httpInvalidJson': 'HTTP {status}: 无效的 JSON 响应',\n 'error.fallback': '操作失败',\n 'error.downloadFailed': '下载失败:HTTP {status}',\n 'error.exportTimeout': '导出超时({minutes} 分钟):导出过程未完成,请重试;若反复超时请检查 DSH 状态',\n 'error.syncTimeout': '同步请求超时({minutes} 分钟):请检查网络与仓库可达性后重试',\n 'error.settingsConflict.title': '配置已被并发修改',\n 'error.settingsConflict.action': '目标 DSH 的该配置在导入期间被其他进程修改,为避免覆盖请重新导出或手动核对后再试。',\n 'error.notConfirmed.title': '导入未确认',\n 'error.notConfirmed.action': '请在预览页确认导入内容后重试。',\n 'error.integrity.title': '备份完整性校验失败',\n 'error.integrity.action': '备份文件可能已损坏或被篡改,请重新导出备份后再试。',\n 'error.schema.title': '备份格式版本不受支持',\n 'error.schema.action': '请升级 DSH Config Manager 或使用相同版本的备份文件。',\n 'error.notFound.title': '文件或路径不存在',\n 'error.notFound.action': '请检查文件路径是否正确、文件是否已被移动或删除。',\n 'error.permission.title': '权限不足',\n 'error.permission.action': '请检查目标目录的读写权限后重试。',\n 'error.needsRestart.title': '插件安装需要重启生效',\n 'error.needsRestart.action': '导入已完成,插件将在重启 DSH 后生效;请在 DSH Desktop 中重启服务。',\n 'error.reason': '原因',\n 'error.suggestedAction': '建议操作',\n 'error.item': '相关项',\n // 进度\n 'progress.analyzing': '正在分析配置…',\n 'progress.exportingSettings': '正在导出设置…',\n 'progress.scanningSecrets': '正在扫描密钥…',\n 'progress.exportingPlugins': '正在导出插件…',\n 'progress.creatingArchive': '正在创建归档…',\n 'progress.calculatingChecksums': '正在计算校验和…',\n 'progress.exporting': '正在导出配置…',\n 'progress.validating': '正在校验备份…',\n 'progress.checkingCompatibility': '正在检查兼容性…',\n 'progress.creatingSnapshot': '正在创建安全快照…',\n 'progress.restoringSettings': '正在恢复设置…',\n 'progress.restoringPlugins': '正在恢复插件…',\n 'progress.restoringMcp': '正在恢复 MCP…',\n 'progress.validatingConfig': '正在校验配置…',\n 'progress.rollingBack': '正在回滚…',\n 'progress.executing': '正在应用配置(插件安装可能需要较长时间)…',\n 'progress.done': '完成',\n // 快照\n 'snapshots.createdAt': '创建时间',\n 'snapshots.sourceZip': '来源',\n 'snapshots.status': '状态',\n 'snapshots.entries': '条目',\n 'snapshots.plugins': '插件',\n 'snapshots.statusPending': '待处理',\n 'snapshots.statusDone': '已完成',\n 'snapshots.statusRolledback': '已回滚',\n 'snapshots.statusUnknown': '未知',\n 'snapshots.planTitle': '恢复计划预览',\n 'snapshots.confirmRestore': '确认恢复?当前文件将先备份到快照的 pre-restore 文件夹;插件经官方 dsh plugin remove 卸载。',\n 'snapshots.execute': '立即恢复',\n 'snapshots.executing': '正在恢复…',\n 'snapshots.restored': '已恢复',\n 'snapshots.removedPlugins': '已卸载插件',\n 'snapshots.manualHints': '需人工处理',\n 'snapshots.failed': '失败',\n 'snapshots.skipped': '跳过',\n 'snapshots.noActions': '该快照无可恢复动作(或全部跳过)。',\n 'snapshots.empty': '暂无快照。导入时会自动创建安全快照。',\n 'snapshots.loading': '正在加载快照…',\n 'snapshots.selectHint': '选择一个快照预览其恢复计划(dry-run,零写入):',\n 'snapshots.reportTitle': '恢复报告',\n // 同步区块(sync-view)\n 'sync.privateRepoHint': '安全要求:同步仓库必须为私有仓库(public 仓库会公开你的配置内容)。认证 token 仅用于仓库访问,绝不写入同步文件、提交内容或日志。',\n 'sync.kind.create': '新增',\n 'sync.kind.update': '更新',\n 'sync.kind.skip': '跳过',\n 'sync.kind.conflict': '冲突',\n 'sync.kind.install': '安装',\n 'sync.kind.missingSecret': '缺密钥',\n 'sync.kind.missingDependency': '缺依赖',\n 'sync.kind.pathMapping': '路径映射',\n 'sync.kind.warning': '警告',\n 'sync.kind.error': '错误',\n 'sync.severity.error': '错误',\n 'sync.severity.warning': '警告',\n 'sync.severity.info': '信息',\n 'sync.pushLabel': '推送到远端',\n 'sync.pullLabel': '拉取差异预览',\n 'sync.pushing': '正在推送…',\n 'sync.pulling': '正在拉取…',\n 'sync.statusLoading': '正在读取同步状态…',\n 'sync.statusUnconfigured': '尚未配置同步仓库(请填写仓库地址并推送一次以保存配置)',\n 'sync.credConfigured': '凭据已配置',\n 'sync.credMissing': '未配置凭据(token 将在首次推送/拉取时写入 DSH credentials)',\n 'sync.lastSync': '上次同步:{time}',\n 'sync.neverSynced': '尚未同步过',\n 'sync.neverSyncedShort': '从未同步',\n 'sync.pushFailed': '推送失败',\n 'sync.pushOk': '推送成功(快照 {id})',\n 'sync.pullFailed': '拉取失败',\n 'sync.pullOk': '远端快照 {id} 差异预览:共 {count} 项变更',\n 'sync.pullEmpty': '远端快照与本地一致(无变更)',\n 'sync.previewHint': '以上为只读差异预览,不会执行导入。v1 暂不提供一键导入接线;如需应用远端配置,请使用「导入恢复」向导手动导入导出的备份。',\n // 一键同步(方案 A:拉取 → 逐项确认 → apply-items)\n 'sync.syncTitle': '一键同步',\n 'sync.syncButton': '一键同步',\n 'sync.syncing': '正在同步…',\n 'sync.syncHeadline': '远端快照 {id} 差异确认:共 {count} 项',\n 'sync.syncEmpty': '远端快照与本地一致(无变更)',\n 'sync.syncFailed': '同步失败',\n 'sync.confirmAdopt': '采用远端',\n 'sync.confirmSkip': '跳过',\n 'sync.confirmRequired': '需要人工决策',\n 'sync.needsReviewBadge': '需人工决策',\n 'sync.selectSnapshot': '选择历史快照',\n 'sync.latestSnapshot': '最新快照',\n 'sync.noSnapshots': '远端暂无快照',\n 'sync.confirmImport': '确认导入',\n 'sync.cancelConfirm': '取消',\n 'sync.conflictResolve': '冲突解决',\n 'sync.conflictUseLocal': '用本地',\n 'sync.conflictUseRemote': '用远端',\n 'sync.conflictSkip': '跳过',\n 'sync.conflictResolvedLocal': '已选:本地',\n 'sync.conflictResolvedRemote': '已选:远端',\n 'sync.conflictResolvedSkip': '已选:跳过',\n 'sync.importDone': '已导入 {n} 个分区',\n 'sync.importSkipped': '已跳过 {n} 项',\n 'sync.importFailed': '导入失败(已整体回滚)',\n 'sync.rollbackButton': '回滚到应用前',\n 'sync.rollingBack': '正在回滚…',\n 'sync.rollbackDone': '已回滚到应用前',\n 'sync.appliedSections': '已写入',\n 'sync.importWarnings': '导入告警',\n // 自动同步(方案 A:宿主后台调度)\n 'sync.autosyncTitle': '自动同步',\n 'sync.autosyncDesc': '开启后,DSH 将按固定间隔自动执行双向同步(拉取合并 + 上传);DSH 启动时还会触发一次「自动下载合并(不上传)」以保持本地为最新。仅在无冲突且无需人工干预时才自动写入。',\n 'sync.autosyncEnabled': '启用自动同步',\n 'sync.autosyncInterval': '同步间隔',\n 'sync.autosyncIntervalHint': 'DSH 启动时自动下载合并不上传。',\n 'sync.autosyncNever': '从未运行',\n 'sync.autosyncLastRun': '上次运行:{time}',\n 'sync.autosyncNextIn': '下次约 {time} 后',\n 'sync.autosyncSuccess': '成功',\n 'sync.autosyncSkipped': '已跳过',\n 'sync.autosyncFailed': '失败',\n 'sync.autosyncPartial': '部分成功',\n 'sync.autosyncFailCount': '连续失败 {n} 次',\n 'sync.autosyncSyncing': '自动同步进行中…',\n 'sync.interval.5m': '5 分钟',\n 'sync.interval.15m': '15 分钟',\n 'sync.interval.30m': '30 分钟',\n 'sync.interval.60m': '60 分钟',\n 'sync.interval.6h': '6 小时',\n 'sync.interval.12h': '12 小时',\n 'sync.interval.24h': '24 小时',\n // 自动同步历史(kind=autosync 行渲染)\n 'sync.hist.autosync': '自动同步',\n 'sync.hist.directionPull': '下载',\n 'sync.hist.directionPush': '上传',\n 'sync.hist.directionBoth': '双向',\n 'sync.hist.skipReasonConflict': '冲突项被跳过',\n 'sync.hist.skipReasonNoRemote': '远端无快照',\n 'sync.hist.skipReasonNotConfigured': '未配置仓库',\n 'sync.hist.skipReasonNetwork': '网络问题',\n 'sync.hist.conflictedSections': '跳过冲突分区:{sections}',\n 'sync.hist.appliedSections': '应用分区:{sections}',\n 'sync.hist.failedError': '错误:{error}',\n 'sync.hist.notifiedAt': '已通知',\n // GitHub OAuth 区块\n 'sync.github.starting': '正在发起 GitHub 授权…',\n 'sync.github.waitingNoCode': '请在浏览器中打开授权页面并完成授权…',\n 'sync.github.waiting': '请在浏览器中打开授权页面,输入一次性代码 {code} 完成授权(自动等待确认)。',\n 'sync.github.polling': '正在确认 GitHub 授权状态…',\n 'sync.github.success': 'GitHub 登录成功:token 已安全写入 DSH credentials,可直接推送/拉取。',\n 'sync.github.failed': 'GitHub 登录失败',\n 'sync.github.defaultStatus': '通过 GitHub OAuth 设备码流程登录,token 自动写入 DSH credentials(无需手动输入)。',\n 'sync.github.login': '使用 GitHub 登录',\n 'sync.github.relogin': '重新登录',\n 'sync.github.pollSuccess': 'GitHub 登录成功:token 已安全写入 DSH credentials。',\n 'sync.github.pollDenied': 'GitHub 授权被拒绝(access_denied)。可重新发起登录,或改用下方手动 token 输入。',\n 'sync.github.pollExpired': 'GitHub 授权已过期(expired_token)。请重新发起登录。',\n 'sync.github.pollError': 'GitHub OAuth 错误:{detail}',\n 'sync.github.unknownError': '未知错误',\n} as const;\n\nexport type UiTextKey = keyof typeof uiZh;\n\nexport const uiEn: Record<UiTextKey, string> = {\n 'commonClose': 'Close',\n 'commonCancel': 'Cancel',\n 'commonRetry': 'Retry',\n 'commonLoading': 'Loading…',\n 'commonUnknownError': 'Unknown error',\n 'commonNext': 'Next',\n 'commonBack': 'Back',\n 'commonDone': 'Done',\n 'export.download': 'Download backup file',\n 'export.running': 'Exporting…',\n 'export.run': 'Start Export',\n 'export.selectionWarnings': 'Device-specific sections may not apply on another machine:',\n 'export.included': 'Included',\n 'export.excluded': 'Excluded',\n 'export.unknownSection': 'Unknown section: {id}',\n 'export.deviceSpecific': '{label} is device-specific ({portability}) and may not apply on another machine',\n 'report.backupCreated': 'Backup Created',\n 'report.importComplete': 'Import Complete',\n 'report.importFailed': 'Import Failed',\n 'report.included': 'Included:',\n 'report.excluded': 'Excluded:',\n 'report.security': 'Security:',\n 'report.apiKeysExcluded': 'API Keys excluded:',\n 'report.containsSecrets': 'Contains secrets:',\n 'report.encrypted': 'Encrypted:',\n 'report.redacted': '{count} sensitive field(s) redacted',\n 'report.file': 'File:',\n 'report.yes': 'yes',\n 'report.yesEncrypted': 'yes (encrypted)',\n 'report.no': 'no',\n 'report.importedRestored': 'imported/restored',\n 'report.skipped': 'skipped',\n 'report.needAttention': 'need attention',\n 'report.failed': 'failed',\n 'report.noChanges': 'no changes',\n 'report.reason': 'Reason',\n 'report.note': 'Note',\n 'report.unknownReason': 'Unknown reason',\n 'report.secrets': 'Secrets:',\n 'report.credentialsNeedEntry': '{count} credential(s) need to be entered',\n 'report.restartRequired': 'Restart DSH to apply: {detail}',\n 'report.restartPluginsMcp': 'Plugin / MCP changes take effect after restarting DSH',\n 'report.rollbackFull': 'Rollback: fully restored the pre-import configuration.',\n 'report.rollbackPartial': 'Rollback partially completed.',\n 'report.rollbackManual': 'These items may require manual recovery:',\n 'report.restored': 'Restored: {count} item(s)',\n 'error.notMounted': 'config-manager service is not mounted (plugin not loaded): make sure dsh-config-manager is installed in the profile and restart DSH',\n 'error.httpInvalidJson': 'HTTP {status}: invalid JSON response',\n 'error.fallback': 'Operation failed',\n 'error.downloadFailed': 'Download failed: HTTP {status}',\n 'error.exportTimeout': 'Export timed out ({minutes} min): the export did not complete, please retry; if it keeps timing out, check the DSH state',\n 'error.syncTimeout': 'Sync request timed out ({minutes} min): check network and repository reachability, then retry',\n 'error.settingsConflict.title': 'Configuration changed concurrently',\n 'error.settingsConflict.action': 'This configuration on the target DSH was modified by another process during import. To avoid overwriting it, re-export or review it manually, then retry.',\n 'error.notConfirmed.title': 'Import not confirmed',\n 'error.notConfirmed.action': 'Confirm the import on the preview page, then retry.',\n 'error.integrity.title': 'Backup integrity check failed',\n 'error.integrity.action': 'The backup may be corrupted or tampered with. Re-export the backup, then retry.',\n 'error.schema.title': 'Backup format version not supported',\n 'error.schema.action': 'Upgrade DSH Config Manager or use a backup from the same version.',\n 'error.notFound.title': 'File or path not found',\n 'error.notFound.action': 'Check that the file path is correct and the file has not been moved or deleted.',\n 'error.permission.title': 'Permission denied',\n 'error.permission.action': 'Check read/write permissions on the target directory, then retry.',\n 'error.needsRestart.title': 'Plugin install requires a restart',\n 'error.needsRestart.action': 'The import is complete; plugins take effect after restarting DSH. Restart the service in DSH Desktop.',\n 'error.reason': 'Reason',\n 'error.suggestedAction': 'Suggested action',\n 'error.item': 'Item',\n 'progress.analyzing': 'Analyzing configuration...',\n 'progress.exportingSettings': 'Exporting settings...',\n 'progress.scanningSecrets': 'Scanning secrets...',\n 'progress.exportingPlugins': 'Exporting plugins...',\n 'progress.creatingArchive': 'Creating archive...',\n 'progress.calculatingChecksums': 'Calculating checksums...',\n 'progress.exporting': 'Exporting configuration...',\n 'progress.validating': 'Validating backup...',\n 'progress.checkingCompatibility': 'Checking compatibility...',\n 'progress.creatingSnapshot': 'Creating safety snapshot...',\n 'progress.restoringSettings': 'Restoring settings...',\n 'progress.restoringPlugins': 'Restoring plugins...',\n 'progress.restoringMcp': 'Restoring MCP...',\n 'progress.validatingConfig': 'Validating configuration...',\n 'progress.rollingBack': 'Rolling back...',\n 'progress.executing': 'Applying configuration (plugin installs may take a while)...',\n 'progress.done': 'Done',\n 'snapshots.createdAt': 'Created',\n 'snapshots.sourceZip': 'Source',\n 'snapshots.status': 'Status',\n 'snapshots.entries': 'Entries',\n 'snapshots.plugins': 'Plugins',\n 'snapshots.statusPending': 'Pending',\n 'snapshots.statusDone': 'Done',\n 'snapshots.statusRolledback': 'Rolled back',\n 'snapshots.statusUnknown': 'Unknown',\n 'snapshots.planTitle': 'Restore Plan Preview',\n 'snapshots.confirmRestore': 'Confirm restore? Current files are backed up to the snapshot\\'s pre-restore folder first; plugins are removed via the official dsh plugin remove.',\n 'snapshots.execute': 'Restore now',\n 'snapshots.executing': 'Restoring…',\n 'snapshots.restored': 'Restored',\n 'snapshots.removedPlugins': 'Removed plugins',\n 'snapshots.manualHints': 'Manual action needed',\n 'snapshots.failed': 'Failed',\n 'snapshots.skipped': 'Skipped',\n 'snapshots.noActions': 'No restorable actions for this snapshot (or all skipped).',\n 'snapshots.empty': 'No snapshots yet. A safety snapshot is created automatically on import.',\n 'snapshots.loading': 'Loading snapshots…',\n 'snapshots.selectHint': 'Select a snapshot to preview its restore plan (dry-run, zero writes):',\n 'snapshots.reportTitle': 'Restore Report',\n 'sync.privateRepoHint': 'Security requirement: the sync repository MUST be private (a public repo would expose your configuration). The auth token is only used for repository access and is never written into sync files, commit content, or logs.',\n 'sync.kind.create': 'Create',\n 'sync.kind.update': 'Update',\n 'sync.kind.skip': 'Skip',\n 'sync.kind.conflict': 'Conflict',\n 'sync.kind.install': 'Install',\n 'sync.kind.missingSecret': 'Secret',\n 'sync.kind.missingDependency': 'Dependency',\n 'sync.kind.pathMapping': 'Path',\n 'sync.kind.warning': 'Warning',\n 'sync.kind.error': 'Error',\n 'sync.severity.error': 'Error',\n 'sync.severity.warning': 'Warning',\n 'sync.severity.info': 'Info',\n 'sync.pushLabel': 'Push to remote',\n 'sync.pullLabel': 'Pull diff preview',\n 'sync.pushing': 'Pushing…',\n 'sync.pulling': 'Pulling…',\n 'sync.statusLoading': 'Reading sync status…',\n 'sync.statusUnconfigured': 'No sync repository configured (fill in the repository URL and push once to save the config)',\n 'sync.credConfigured': 'Credential configured',\n 'sync.credMissing': 'No credential configured (token is written into DSH credentials on first push/pull)',\n 'sync.lastSync': 'Last sync: {time}',\n 'sync.neverSynced': 'Never synced yet',\n 'sync.neverSyncedShort': 'Never synced',\n 'sync.pushFailed': 'Push failed',\n 'sync.pushOk': 'Push succeeded (snapshot {id})',\n 'sync.pullFailed': 'Pull failed',\n 'sync.pullOk': 'Remote snapshot {id} diff preview: {count} change(s)',\n 'sync.pullEmpty': 'Remote snapshot matches local (no changes)',\n 'sync.previewHint': 'Read-only diff preview above; nothing is imported. v1 does not wire one-click import yet — use the Import wizard to apply a downloaded backup if needed.',\n 'sync.syncTitle': 'One-Click Sync',\n 'sync.syncButton': 'One-click sync',\n 'sync.syncing': 'Syncing…',\n 'sync.syncHeadline': 'Remote snapshot {id} diff confirm: {count} item(s)',\n 'sync.syncEmpty': 'Remote snapshot matches local (no changes)',\n 'sync.syncFailed': 'Sync failed',\n 'sync.confirmAdopt': 'Adopt remote',\n 'sync.confirmSkip': 'Skip',\n 'sync.confirmRequired': 'Needs decision',\n 'sync.needsReviewBadge': 'Needs decision',\n 'sync.selectSnapshot': 'Select snapshot',\n 'sync.latestSnapshot': 'Latest snapshot',\n 'sync.noSnapshots': 'No remote snapshots',\n 'sync.confirmImport': 'Confirm import',\n 'sync.cancelConfirm': 'Cancel',\n 'sync.conflictResolve': 'Resolve conflict',\n 'sync.conflictUseLocal': 'Use local',\n 'sync.conflictUseRemote': 'Use remote',\n 'sync.conflictSkip': 'Skip',\n 'sync.conflictResolvedLocal': 'Chosen: local',\n 'sync.conflictResolvedRemote': 'Chosen: remote',\n 'sync.conflictResolvedSkip': 'Chosen: skip',\n 'sync.importDone': 'Imported {n} section(s)',\n 'sync.importSkipped': 'Skipped {n} item(s)',\n 'sync.importFailed': 'Import failed (rolled back)',\n 'sync.rollbackButton': 'Rollback',\n 'sync.rollingBack': 'Rolling back…',\n 'sync.rollbackDone': 'Rolled back',\n 'sync.appliedSections': 'Written',\n 'sync.importWarnings': 'Import warnings',\n 'sync.autosyncTitle': 'Auto Sync',\n 'sync.autosyncDesc': 'When enabled, DSH will run two-way sync (pull merge + push) on a fixed interval; on startup it also triggers a download-merge (no upload) to keep local up to date. Local writes happen only when there are no conflicts or manual-decision items.',\n 'sync.autosyncEnabled': 'Enable auto sync',\n 'sync.autosyncInterval': 'Sync interval',\n 'sync.autosyncIntervalHint': 'Auto download-merge on DSH startup, no upload.',\n 'sync.autosyncNever': 'Never run',\n 'sync.autosyncLastRun': 'Last run: {time}',\n 'sync.autosyncNextIn': 'Next in ~{time}',\n 'sync.autosyncSuccess': 'Success',\n 'sync.autosyncSkipped': 'Skipped',\n 'sync.autosyncFailed': 'Failed',\n 'sync.autosyncPartial': 'Partial',\n 'sync.autosyncFailCount': '{n} consecutive failure(s)',\n 'sync.autosyncSyncing': 'Auto sync running…',\n 'sync.interval.5m': '5 min',\n 'sync.interval.15m': '15 min',\n 'sync.interval.30m': '30 min',\n 'sync.interval.60m': '60 min',\n 'sync.interval.6h': '6 hr',\n 'sync.interval.12h': '12 hr',\n 'sync.interval.24h': '24 hr',\n 'sync.hist.autosync': 'Auto Sync',\n 'sync.hist.directionPull': 'Pull',\n 'sync.hist.directionPush': 'Push',\n 'sync.hist.directionBoth': 'Both',\n 'sync.hist.skipReasonConflict': 'Conflict items skipped',\n 'sync.hist.skipReasonNoRemote': 'No remote snapshot',\n 'sync.hist.skipReasonNotConfigured': 'No repository configured',\n 'sync.hist.skipReasonNetwork': 'Network issue',\n 'sync.hist.conflictedSections': 'Skipped conflict sections: {sections}',\n 'sync.hist.appliedSections': 'Applied sections: {sections}',\n 'sync.hist.failedError': 'Error: {error}',\n 'sync.hist.notifiedAt': 'Notified',\n 'sync.github.starting': 'Starting GitHub authorization…',\n 'sync.github.waitingNoCode': 'Open the authorization page in your browser and complete the flow…',\n 'sync.github.waiting': 'Open the authorization page in your browser, enter the one-time code {code} to finish (waiting for confirmation).',\n 'sync.github.polling': 'Confirming GitHub authorization…',\n 'sync.github.success': 'GitHub sign-in succeeded: token securely written into DSH credentials — you can push/pull now.',\n 'sync.github.failed': 'GitHub sign-in failed',\n 'sync.github.defaultStatus': 'Sign in via the GitHub OAuth device flow; the token is written into DSH credentials automatically (no manual entry).',\n 'sync.github.login': 'Sign in with GitHub',\n 'sync.github.relogin': 'Sign in again',\n 'sync.github.pollSuccess': 'GitHub sign-in succeeded: token securely written into DSH credentials.',\n 'sync.github.pollDenied': 'GitHub authorization was denied (access_denied). You can re-start the sign-in or use manual token entry below.',\n 'sync.github.pollExpired': 'GitHub authorization expired (expired_token). Please re-start the sign-in.',\n 'sync.github.pollError': 'GitHub OAuth error: {detail}',\n 'sync.github.unknownError': 'Unknown error',\n};\n\n/** UI 翻译函数:key → 当前语言文案({param} 插值;未知键回退 zh/键名)。 */\nexport type UiT = (key: UiTextKey, params?: Record<string, string | number>) => string;\n\n/** 构造 翻译函数(zh 源 / en 镜像;缺 key 回退)。 */\nexport function makeUiT(lang: 'zh' | 'en'): UiT {\n const dict = lang === 'en' ? uiEn : uiZh;\n const fallback = lang === 'en' ? uiZh : undefined;\n return (key, params) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const template = (dict as any)[key] ?? (fallback as any)?.[key] ?? key;\n if (params === undefined) return template;\n return String(template).replace(/\\{(\\w+)\\}/g, (match, k: string) =>\n params[k] === undefined ? match : String(params[k]),\n );\n };\n}\n\n/** 缺省 UI 翻译(zh):未注入的渲染路径行为与改造前完全一致。 */\nexport const zhUiT: UiT = makeUiT('zh');\n","/**\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;响应含 runId)\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 };响应含 runId)\n * GET /api/dsh-config-manager/progress?runId=… → RunState (run 实时状态:轮询/刷新恢复)\n * GET /api/dsh-config-manager/runs → RunState[] (活跃 run 列表)\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 { RestorePlan, RestoreReport, SnapshotMeta } from '../core/restore.ts';\nimport type { RunState } from '../core/run-registry.ts';\nimport type { Manifest } from '../schema/types.ts';\nimport { zhUiT, type UiT } from '../ui/i18n.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 前半部分;runId 为 m1 run 注册表标识) */\nexport interface ExportResponse {\n zipPath: string;\n manifest: Manifest;\n report: ExportReport;\n /** m1:本次导出 run 的 id(可用 /progress 查询状态 / 刷新恢复) */\n runId: string;\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/** restore 端点响应:dryRun=true 返回 plan;执行返回 report(与 CLI 一致的诚实报告) */\nexport interface RestoreResponse {\n dryRun: boolean;\n plan?: RestorePlan;\n report?: RestoreReport;\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 progress: '/api/dsh-config-manager/progress',\n runs: '/api/dsh-config-manager/runs',\n snapshots: '/api/dsh-config-manager/snapshots',\n restore: '/api/dsh-config-manager/restore',\n} as const;\n\n/** 导出请求超时(ms):与 Host 半 ROUTE_TIMEOUT_MS 对齐,防止宿主卡死时 UI 无限等待 */\nconst EXPORT_TIMEOUT_MS = 5 * 60 * 1000;\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, t: UiT): Promise<T> {\n const notMountedMessage = t('error.notMounted');\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n if (response.status === 404) throw new ConfigManagerApiError(notMountedMessage);\n throw new ConfigManagerApiError(t('error.httpInvalidJson', { status: String(response.status) }));\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 : response.status === 404\n ? notMountedMessage\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 /** 客户端展示层翻译器(zh 源 / en 镜像,见 ui/i18n.ts)。 */\n readonly t: UiT\n\n constructor(t: UiT = zhUiT) {\n this.t = t\n }\n\n // ------------------------------------------------------------- status\n /** 健康/版本检查(主页横幅:插件版本 / DSH 版本 / 平台) */\n async status(): Promise<ServiceStatus> {\n const response = await fetch(CONFIG_MANAGER_API.status);\n return readJson<ServiceStatus>(response, this.t);\n }\n\n // ------------------------------------------------------------- export\n /** ExportPort.export:调用 Host 侧导出编排(core Exporter)。加密密码随请求体传输(仅内存)。\n * 带 AbortController 超时:宿主若卡死,客户端得到明确错误而不是永远停在进度条。 */\n async export(options: ExportOptions): Promise<ExportResponse> {\n const body: ExportOptions & { password?: string } = {\n ...options,\n password: this.exportPassword ?? undefined,\n };\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), EXPORT_TIMEOUT_MS);\n try {\n const response = await fetch(CONFIG_MANAGER_API.export, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n return await readJson<ExportResponse>(response, this.t);\n } catch (err) {\n if (controller.signal.aborted) {\n throw new ConfigManagerApiError(this.t('error.exportTimeout', { minutes: String(Math.round(EXPORT_TIMEOUT_MS / 60000)) }));\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\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 : this.t('error.downloadFailed', { status: String(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, this.t);\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, this.t);\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, this.t);\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 & { runId: string }> {\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 & { runId: string }>(response, this.t);\n }\n\n // ------------------------------------------------------------- run 进度\n /** m1:查询单个 run 的实时状态(执行中轮询 / 刷新恢复用;404 = 已过保留期或不存在) */\n async progress(runId: string): Promise<RunState> {\n const response = await fetch(CONFIG_MANAGER_API.progress + query({ runId }));\n return readJson<RunState>(response, this.t);\n }\n\n /** m1:列出当前活跃(running)的 run(刷新后重新订阅进行中任务的入口) */\n async runs(): Promise<RunState[]> {\n const response = await fetch(CONFIG_MANAGER_API.runs);\n return readJson<RunState[]>(response, this.t);\n }\n\n // ------------------------------------------------------- 快照恢复(M4)\n /** 列出全部快照元信息(createdAt 倒序;含 status/条目数/宿主文件数/插件数) */\n async snapshots(): Promise<SnapshotMeta[]> {\n const response = await fetch(CONFIG_MANAGER_API.snapshots);\n const body = await readJson<{ snapshots: SnapshotMeta[] }>(response, this.t);\n return body.snapshots;\n }\n\n /** 快照恢复:dryRun=true 只取动作计划(零写入);false 执行并返回诚实报告 */\n async restoreSnapshot(snapshotId: string, dryRun: boolean): Promise<RestoreResponse> {\n const response = await fetch(CONFIG_MANAGER_API.restore, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ snapshotId, dryRun }),\n });\n return readJson<RestoreResponse>(response, this.t);\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 * 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 warned: number;\n failed: number;\n items: { itemId: string; status: 'ok' | 'skipped' | 'warning' | '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';\nimport { zhUiT, type UiT, type UiTextKey } from './i18n.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\n/**\n * 真实执行阶段(不在 IMPORT_STAGES 序列里,因此 step/total 缺省 → 进度条渲染\n * 为不定态动画而非伪造百分比)。execute 是一个单次 HTTP 请求,Host 端串行\n * 跑完全部计划项(其中插件安装是 npm 串行,耗时最长);请求期间没有中间\n * 进度事件可回传,旧实现把 restoring-settings / restoring-plugins /\n * restoring-mcp / validating-config 在请求前全部预发,导致进度条瞬间跳到\n * 78% 后长时间无变化——像卡死。现在统一在请求期间显示 'executing' 不定态,\n * 让用户明确知道「仍在执行,请等待」。\n */\nexport const EXECUTING_STAGE = 'executing' as const;\n\nconst STAGE_KEYS: Record<string, UiTextKey> = {\n analyzing: 'progress.analyzing',\n 'exporting-settings': 'progress.exportingSettings',\n 'scanning-secrets': 'progress.scanningSecrets',\n 'exporting-plugins': 'progress.exportingPlugins',\n 'creating-archive': 'progress.creatingArchive',\n 'calculating-checksums': 'progress.calculatingChecksums',\n exporting: 'progress.exporting',\n validating: 'progress.validating',\n 'checking-compatibility': 'progress.checkingCompatibility',\n 'creating-snapshot': 'progress.creatingSnapshot',\n 'restoring-settings': 'progress.restoringSettings',\n 'restoring-plugins': 'progress.restoringPlugins',\n 'restoring-mcp': 'progress.restoringMcp',\n 'validating-config': 'progress.validatingConfig',\n 'rolling-back': 'progress.rollingBack',\n executing: 'progress.executing',\n done: 'progress.done',\n};\n\n/** 阶段 id → 用户可读文案(未知阶段回退 id) */\nexport function stageText(stage: string, t: UiT = zhUiT): string {\n const key = STAGE_KEYS[stage];\n return key !== undefined ? t(key) : 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';\nimport { zhUiT, type UiT } from './i18n.ts';\n\n/* ---------------- §21 导出报告 ---------------- */\n\nexport function renderExportReport(report: ExportReport, t: UiT = zhUiT): string {\n const lines: string[] = [t('report.backupCreated'), ''];\n lines.push(t('report.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(t('report.excluded'));\n for (const s of report.excluded) lines.push(` ○ ${s}`);\n lines.push('');\n }\n lines.push(t('report.security'));\n lines.push(` ✓ ${t('report.apiKeysExcluded')} ${report.security.secretsExcluded ? t('report.yes') : t('report.no')}`);\n lines.push(` ✓ ${t('report.containsSecrets')} ${report.security.containsSecrets ? t('report.yesEncrypted') : t('report.no')}`);\n lines.push(` ✓ ${t('report.encrypted')} ${report.security.encrypted ? t('report.yes') : t('report.no')}`);\n if (report.security.redactedHits > 0) lines.push(` ⚠ ${t('report.redacted', { count: String(report.security.redactedHits) })}`);\n lines.push('');\n lines.push(`${t('report.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, warned: 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 if (e.status === 'warning') stat.warned += 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, t: UiT = zhUiT): string {\n const lines: string[] = [result.ok ? t('report.importComplete') : t('report.importFailed'), ''];\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} ${t('report.importedRestored')}`);\n if (s.skipped > 0) parts.push(`- ${s.skipped} ${t('report.skipped')}`);\n if (s.warned > 0) parts.push(`⚠ ${s.warned} ${t('report.needAttention')}`);\n if (s.failed > 0) parts.push(`✗ ${s.failed} ${t('report.failed')}`);\n lines.push(`${s.section}: ${parts.join(' ') || t('report.noChanges')}`);\n // 失败/警告项给出可操作原因(§23)\n for (const it of s.items) {\n if (it.status === 'failed' || it.status === 'warning') {\n lines.push(` ${it.status === 'failed' ? t('report.reason') : t('report.note')}: ${it.message ?? t('report.unknownReason')}`);\n }\n }\n }\n if (result.missingSecrets.length > 0) {\n lines.push(`${t('report.secrets')} ⚠ ${t('report.credentialsNeedEntry', { count: String(result.missingSecrets.length) })}`);\n }\n if (result.needsRestart) {\n lines.push(t('report.restartPluginsMcp'));\n }\n for (const w of result.warnings) lines.push(`⚠ ${w}`);\n if (result.rollback) {\n lines.push('');\n lines.push(renderRollbackReport(result.rollback, t));\n }\n return lines.join('\\n');\n}\n\n/** 结果页动作按钮(§22)。报告已内联展示全部失败/警告项的原因与回滚详情(§23),\n * 不再提供空操作的 Fix Issues / View Details 按钮——仅保留「完成」。 */\nexport function suggestedActions(_result: ImportResult): ImportResultAction[] {\n return ['done'];\n}\n\n/* ---------------- §17 回滚报告 ---------------- */\n\n/** 回滚报告渲染(full / partial + 人工恢复清单) */\nexport function renderRollbackReport(rr: RollbackReport, t: UiT = zhUiT): string {\n if (rr.full) {\n return t('report.rollbackFull');\n }\n const lines = [t('report.rollbackPartial')];\n lines.push(t('report.rollbackManual'));\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(t('report.restored', { count: String(rr.restored.length) }));\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';\nimport { zhUiT, type UiT } from './i18n.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 /** 报告渲染翻译器(zh/en,见 i18n.ts) */\n t?: UiT;\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 private readonly t: UiT;\n\n constructor(opts: ExportFlowOptions) {\n this.port = opts.port;\n this.categories = opts.categories ?? DEFAULT_CATEGORIES;\n this.onProgress = opts.onProgress;\n this.t = opts.t ?? zhUiT;\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 // 导出工作全部发生在 port.export() 的单次请求内,客户端无法逐阶段上报真实进度。\n // 旧实现把整串阶段一次性 emit,请求期间 UI 会静止在假的「Calculating checksums... 86%」,\n // 任何慢请求/挂起请求看起来都像卡死。改为:请求期间只发一个不带 step/total 的 in-flight\n // 阶段(ProgressBar 显示不定态动画),完成后发 done(100%)。超时/失败由 api 层显式抛出。\n tracker.emit('exporting');\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, this.t) };\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 * - 文案经 UiT 注入(zh 源 / en 镜像,见 i18n.ts)。\n */\nimport { redact } from '../security/redaction.ts';\nimport { zhUiT, type UiT } from './i18n.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\nfunction buildErrorRules(t: UiT): readonly ErrorRule[] {\n return [\n {\n match: (m) => /SETTINGS_CONFLICT|revision.*conflict/i.test(m),\n title: t('error.settingsConflict.title'),\n suggestedAction: t('error.settingsConflict.action'),\n retryable: true,\n },\n {\n match: (m) => /ImportNotConfirmed|未确认/i.test(m),\n title: t('error.notConfirmed.title'),\n suggestedAction: t('error.notConfirmed.action'),\n retryable: true,\n },\n {\n match: (m) => /backup integrity|完整性校验失败|checksum/i.test(m),\n title: t('error.integrity.title'),\n suggestedAction: t('error.integrity.action'),\n retryable: false,\n },\n {\n match: (m) => /schema.*(不支持|超出)|无法导入|Unsupported|schemaUnsupported|无法导入/i.test(m),\n title: t('error.schema.title'),\n suggestedAction: t('error.schema.action'),\n retryable: false,\n },\n {\n match: (m) => /ENOENT|not found|无法读取|不存在|readFailed/i.test(m),\n title: t('error.notFound.title'),\n suggestedAction: t('error.notFound.action'),\n retryable: true,\n },\n {\n match: (m) => /EACCES|permission|权限/i.test(m),\n title: t('error.permission.title'),\n suggestedAction: t('error.permission.action'),\n retryable: true,\n },\n {\n match: (m) => /install.*(plugin|插件)|needsRestart|重启/i.test(m),\n title: t('error.needsRestart.title'),\n suggestedAction: t('error.needsRestart.action'),\n retryable: false,\n },\n ];\n}\n\n/** 将任意错误转换为可操作错误(消息已脱敏,不泄漏 Secret) */\nexport function toActionableError(err: unknown, opts?: { item?: string; fallbackTitle?: string; t?: UiT }): ActionableError {\n const t = opts?.t ?? zhUiT;\n const raw = err instanceof Error ? err.message : String(err ?? t('commonUnknownError'));\n const message = redact(raw);\n const rule = buildErrorRules(t).find((r) => r.match(message));\n return {\n title: rule?.title ?? opts?.fallbackTitle ?? t('error.fallback'),\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, t: UiT = zhUiT): string {\n const lines = [e.title];\n lines.push(`${t('error.reason')}: ${e.reason}`);\n if (e.suggestedAction) lines.push(`${t('error.suggestedAction')}: ${e.suggestedAction}`);\n if (e.item) lines.push(`${t('error.item')}: ${e.item}`);\n return lines.join('\\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 { EXECUTING_STAGE, 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 // 快照由 Host 端在 executeImportPlan 内部第一步创建;此处只发开始阶段。\n this.tracker.emit('creating-snapshot');\n\n try {\n // 用最终决策重建计划(与预览逻辑一致,保证 Dry Run 与真实导入一致)\n this.plan = await this.port.createImportPlan(this.zipPath, this.decisions);\n // executeImportPlan 是一个单次 HTTP 请求:Host 端串行跑完全部计划项\n // (插件安装为 npm 串行,耗时最长)。请求期间没有任何中间进度事件可\n // 回传——旧实现把 restoring-settings / restoring-plugins /\n // restoring-mcp / validating-config 在请求前全部预发,进度条瞬间跳到\n // 78% 后长时间不动,看起来像卡死。现在统一改为 EXECUTING_STAGE\n // 不定态(无 step/total → 动画),让用户明确知道「仍在执行」。\n // 真实各分区结果在返回后的报告里逐项展示。\n this.tracker.emit(EXECUTING_STAGE);\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 * m2: 模块级 run/UI store —— dsh-config-manager 浏览器半的状态中枢。\n *\n * 解决的问题(验收 m2-state / m2-refresh / m2-resume):\n * - 切 tab / 关面板重开:模块级单例存活于当前 JS 上下文,ExportFlow /\n * ImportWizard 控制器实例与 UI 状态**不重建**(m2-state);\n * - 页面刷新:非敏感状态经 sessionStorage(键 dsh.cfgMgr.state.v1)\n * 序列化/反序列化恢复(m2-refresh);敏感字段\n * password / passwordConfirm / secretInputs **只存在内存**,序列化白名单\n * 显式剔除 —— 刷新后自动清空,secrets 阶段要求重输;\n * - 进行中 run:视图挂载时经 GET /runs 找回活跃 runId,轮询 GET /progress\n * 直到完成/失败,把 RunState.result 回填到 store(m2-resume)。服务端在\n * 刷新/关面板期间继续执行,本 store 只负责重新订阅进度。\n *\n * 控制器 rehydrate 说明:ImportWizard 没有公开的 hydrate 入口(m2 约束为只改\n * src/client/、不动 src/ui/),刷新恢复需要把持久化的非敏感快照写回控制器\n * 私有字段。writeWizardSnapshot() 是唯一的受控访问点:类型层 private 只是\n * 编译期约束(运行时是普通属性),所有写入值都来自序列化白名单(已剔除\n * 密码/密钥/secretInputs),且只在 load / hydrate / resume-settle 时调用。\n *\n * 安全约束:\n * - toPersistedState() 用解构白名单剔除敏感字段,即使未来往 LiveState 加字段,\n * 未显式放行也不会落入 sessionStorage;\n * - runId 为 32-hex 不可猜标识,可安全持久化(/runs + /progress 的查询键)。\n */\nimport { ConflictCollector } from '../ui/conflict-view.ts'\nimport { DEFAULT_CATEGORIES, ExportFlow } from '../ui/export-flow.ts'\nimport type { ExportRunResult } from '../ui/export-flow.ts'\nimport { ImportWizard } from '../ui/import-wizard.ts'\nimport { renderExportReport } from '../ui/report.ts'\nimport type { ImportStep } from '../ui/types.ts'\nimport type { RunProgress } from './common/progress-view.ts'\nimport type {\n GlobalConflictStrategy, ImportAnalysis, ImportDecisions, ImportPlan, ImportResult,\n ItemResolution, PathMapping,\n} from '../core/types.ts'\nimport type { RunKind, RunState } from '../core/run-registry.ts'\nimport type { Manifest, SectionId } from '../schema/types.ts'\nimport type { ConfigManagerApi } from './api.ts'\n\n/* ---------------------------------------------------------------- 基础类型 */\n\n/** 主视图(ConfigManagerSection 的 tab 状态)。 */\nexport type MainView = 'export' | 'import'\n\n/** 导出模式。 */\nexport type ExportMode = 'quick' | 'custom'\n\n/** 存储抽象(浏览器 sessionStorage / 测试 mock / 无存储)。 */\nexport interface StoreStorage {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\n/** sessionStorage 键。 */\nexport const STATE_KEY = 'dsh.cfgMgr.state.v1'\n\n/** Custom 模式的初始勾选 = 推荐分区(可再调整) */\nexport function defaultCustomSelection(): SectionId[] {\n return DEFAULT_CATEGORIES\n .filter((c) => c.defaultIncluded)\n .map((c) => c.id)\n}\n\n/* ------------------------------------------------- 持久化(非敏感)状态形状 */\n\n/** 导出视图的持久化切片(不含 password/passwordConfirm)。 */\nexport interface PersistedExportState {\n mode: ExportMode\n selection: SectionId[]\n includeSecrets: boolean\n running: boolean\n progress: RunProgress | null\n result: ExportRunResult | null\n /** 错误消息(已 redact 的文本;Error 对象不可 JSON 序列化,统一转字符串) */\n error: string | null\n downloaded: boolean\n /** 最近一次导出 run id(/runs + /progress 重新订阅用;32-hex 不可猜) */\n runId: string | null\n}\n\n/** 导入向导的持久化切片(不含 secretInputs)。 */\nexport interface PersistedImportState {\n step: ImportStep\n zipPath: string | null\n /** select 步骤已选备份文件名(换选/取消选择的 UI 状态;非敏感) */\n selectedFileName: string | null\n analysis: ImportAnalysis | null\n plan: ImportPlan | null\n result: ImportResult | null\n rollbackOnError: boolean\n errors: string[]\n /** UI 层流程阶段(wizard.step 之外的页面;见 src/ui/flow.ts) */\n phase: FlowPhase\n conflictStrategy: GlobalConflictStrategy\n conflictResolutions: Record<string, ItemResolution>\n pathMappings: PathMapping[]\n uploading: boolean\n running: boolean\n progress: RunProgress | null\n error: string | null\n runId: string | null\n}\n\n/** 刷新恢复的顶层持久化状态(v1 结构版本)。 */\nexport interface PersistedState {\n v: 1\n view: MainView\n export: PersistedExportState\n import: PersistedImportState\n}\n\n/* --------------------------------------- 运行时状态(含仅内存的敏感字段) */\n\n/** 导出运行时状态 = 持久化字段 + 仅内存的密码字段。 */\nexport interface ExportLiveState extends PersistedExportState {\n /** 加密密码(仅内存,绝不写入 sessionStorage;刷新后清空) */\n password: string\n passwordConfirm: string\n}\n\n/** 导入运行时状态 = 持久化字段 + 仅内存的敏感/实例字段。 */\nexport interface ImportLiveState extends PersistedImportState {\n /** 秘密补录值(仅内存,绝不写入 sessionStorage;刷新后清空、secrets 阶段重输) */\n secretInputs: Record<string, string>\n /** 冲突决策收集器实例(仅内存;刷新后由 plan + conflictResolutions 重建) */\n conflictCollector: ConflictCollector | null\n}\n\n/** store 的完整运行时快照(getSnapshot 返回;含敏感字段,仅供组件读取)。 */\nexport interface StoreState {\n v: 1\n view: MainView\n export: ExportLiveState\n import: ImportLiveState\n}\n\n/** patch 的输入形状(浅合并对应切片)。 */\nexport interface StorePatch {\n view?: MainView\n export?: Partial<ExportLiveState>\n import?: Partial<ImportLiveState>\n}\n\n/** 向导 step 的类型别名(与 src/ui/types.ts 的 ImportStep 保持一致)。 */\ntype ImportWizardStep = ImportStep\n\n/** UI 层流程阶段(与 src/ui/flow.ts 的 FlowPhase 保持一致)。 */\ntype FlowPhase = 'preview' | 'conflicts' | 'path-mapping' | 'secrets' | 'confirm'\n\n/* ------------------------------------------------------------- 默认值 */\n\nfunction defaultExportState(): ExportLiveState {\n return {\n mode: 'quick',\n selection: defaultCustomSelection(),\n includeSecrets: false,\n password: '',\n passwordConfirm: '',\n running: false,\n progress: null,\n result: null,\n error: null,\n downloaded: false,\n runId: null,\n }\n}\n\nfunction defaultImportState(): ImportLiveState {\n return {\n step: 'select',\n zipPath: null,\n selectedFileName: null,\n analysis: null,\n plan: null,\n result: null,\n rollbackOnError: true,\n errors: [],\n phase: 'preview',\n conflictStrategy: 'merge',\n conflictResolutions: {},\n pathMappings: [],\n secretInputs: {},\n uploading: false,\n running: false,\n progress: null,\n error: null,\n runId: null,\n conflictCollector: null,\n }\n}\n\nfunction defaultState(): StoreState {\n return {\n v: 1,\n view: 'export',\n export: defaultExportState(),\n import: defaultImportState(),\n }\n}\n\n/* ------------------------------------------------- 序列化白名单(安全关键) */\n\n/**\n * 持久化白名单:解构剔除敏感字段(password/passwordConfirm/secretInputs)\n * 与不可序列化的实例字段(conflictCollector),其余原样落入 sessionStorage。\n * 这是 sessionStorage 的唯一写入路径 —— 敏感值在此被硬性隔离。\n */\nexport function toPersistedState(state: StoreState): PersistedState {\n const { password: _password, passwordConfirm: _passwordConfirm, ...exportRest } = state.export\n const { secretInputs: _secretInputs, conflictCollector: _conflictCollector, ...importRest } = state.import\n return { v: 1, view: state.view, export: exportRest, import: importRest }\n}\n\n/** 解析 + 轻量校验持久化状态;损坏/版本不符返回 null(调用方回退默认并清键)。 */\nexport function parsePersistedState(raw: string): PersistedState | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n return null\n }\n if (typeof parsed !== 'object' || parsed === null) return null\n const p = parsed as Record<string, unknown>\n if (p['v'] !== 1) return null\n const view = p['view']\n if (view !== 'export' && view !== 'import') return null\n const exp = p['export']\n const imp = p['import']\n if (typeof exp !== 'object' || exp === null || typeof imp !== 'object' || imp === null) return null\n return { v: 1, view, export: exp as PersistedExportState, import: imp as PersistedImportState }\n}\n\n/* ----------------------------------------------------- 控制器 rehydrate */\n\n/** ImportWizard 私有字段的镜像形状(仅供 writeWizardSnapshot 受控写入)。 */\ninterface WizardInternals {\n step: ImportWizardStep\n zipPath: string | null\n analysis: ImportAnalysis | null\n plan: ImportPlan | null\n result: ImportResult | null\n rollbackOnError: boolean\n errors: string[]\n decisions: ImportDecisions\n secretInputs: Record<string, string>\n}\n\n/**\n * 把 store 的导入快照写回 ImportWizard 控制器私有字段(受控 rehydrate)。\n * - 只写非敏感字段;secretInputs 恒置空 —— 刷新后 secrets 阶段要求重输;\n * - 仅在 load / hydrate / resume-settle 时调用,不参与正常交互路径。\n */\nfunction writeWizardSnapshot(wizard: ImportWizard, imp: ImportLiveState): void {\n const internals = wizard as unknown as WizardInternals\n internals.step = imp.step\n internals.zipPath = imp.zipPath\n internals.analysis = imp.analysis\n internals.plan = imp.plan\n internals.result = imp.result\n internals.rollbackOnError = imp.rollbackOnError\n internals.errors = [...imp.errors]\n internals.decisions = {\n strategy: imp.conflictStrategy,\n resolutions: { ...imp.conflictResolutions },\n pathMappings: imp.pathMappings.map((m) => ({ ...m, appliesTo: [...m.appliesTo] })),\n }\n internals.secretInputs = {}\n}\n\n/** 由 plan + 已持久化的决策重建 ConflictCollector(刷新恢复用)。 */\nexport function rebuildConflictCollector(\n plan: ImportPlan,\n resolutions: Record<string, ItemResolution>,\n): ConflictCollector {\n const collector = new ConflictCollector(plan)\n for (const [id, resolution] of Object.entries(resolutions)) {\n collector.resolve(id, resolution)\n }\n return collector\n}\n\n/**\n * RunState → RunProgress(m3 轮询进度回填)。\n * - step/total = 内部计数(百分比条按 item/itemTotal 推进);\n * - section/sectionTotal 与 item/itemTotal 单独保留给分区徽章/内部计数徽章;\n * - detail = 当前项名(导出时恒为分区名,ProgressBar 侧会去冗余)。\n */\nfunction mapRunProgress(kind: RunKind, state: RunState): RunProgress {\n return {\n stage: kind === 'export' ? 'exporting' : 'executing',\n detail: state.detail ?? undefined,\n step: state.item ?? undefined,\n total: state.itemTotal ?? undefined,\n section: state.section,\n sectionTotal: state.sectionTotal,\n item: state.item,\n itemTotal: state.itemTotal,\n }\n}\n\n/* ------------------------------------------------------------------- store */\n\nexport interface RunStoreOptions {\n /** 存储提供者;缺省 = window.sessionStorage(Node/无 window 时为 null) */\n storage?: StoreStorage | null\n /** 进度轮询间隔(测试注入小值;缺省 1000ms) */\n pollIntervalMs?: number\n}\n\nfunction defaultStorage(): StoreStorage | null {\n if (typeof window === 'undefined') return null\n try {\n return window.sessionStorage ?? null\n } catch {\n return null\n }\n}\n\n/**\n * 模块级单例 store:控制器实例 + React UI 状态 + sessionStorage 恢复。\n * 最小接口:subscribe / getSnapshot / load / save / patch / syncWizard /\n * exportFlow / importWizard / resume / stopResume。\n */\nexport class RunStore {\n private readonly storage: StoreStorage | null\n private readonly pollIntervalMs: number\n private readonly listeners = new Set<() => void>()\n private state: StoreState\n private exportFlowInst: ExportFlow | null = null\n private importWizardInst: ImportWizard | null = null\n private apiRef: ConfigManagerApi | null = null\n /** 正在轮询的 runId 集合(stopResume 清空;防重复订阅) */\n private readonly polling = new Set<string>()\n /** 每个 runId 至多一个挂起的轮询定时器(fire 后由下一次调度覆盖) */\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>()\n /** 正在「发现进行中 run」的 kind 集合(watchRunning 活动标记;stopRunWatch/stopResume 清空) */\n private readonly watchActive = new Set<RunKind>()\n\n constructor(opts: RunStoreOptions = {}) {\n this.storage = opts.storage !== undefined ? opts.storage : defaultStorage()\n this.pollIntervalMs = opts.pollIntervalMs ?? 1000\n this.state = defaultState()\n this.load()\n }\n\n /* ------------------------------------------------------------- 订阅 */\n\n /**\n * 订阅 store 变化(useSyncExternalStore 的 subscribe)。\n *\n * 必须为箭头函数类字段:React 以裸引用(`runStore.subscribe`)调用它,\n * 无接收者,若为原型方法则 `this` 为 undefined,`this.listeners` 直接崩溃。\n */\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n /**\n * 当前完整快照(引用稳定:仅在 patch 后替换,适合 useSyncExternalStore)。\n *\n * 必须为箭头函数类字段:React 以裸引用(`runStore.getSnapshot`)调用它,\n * 无接收者,若为原型方法则 `this` 为 undefined,`this.state` 抛 TypeError,\n * 导致整个 settings.section 槽位渲染崩溃(备份与迁移页空白)。\n */\n getSnapshot = (): StoreState => this.state\n\n private notify(): void {\n for (const listener of this.listeners) listener()\n }\n\n /* ------------------------------------------------------- 状态更新 */\n\n /** 浅合并补丁并立即持久化(保存走白名单,敏感字段不落盘)。 */\n patch(patchObj: StorePatch): void {\n this.state = {\n ...this.state,\n view: patchObj.view ?? this.state.view,\n export: { ...this.state.export, ...patchObj.export },\n import: { ...this.state.import, ...patchObj.import },\n }\n this.notify()\n this.save()\n }\n\n /** 把 ImportWizard 控制器的 snapshot() 镜像进 store(wizard 动作后调用)。 */\n syncWizard(): void {\n const wizard = this.importWizardInst\n if (wizard === null) return\n const snap = wizard.snapshot()\n this.patch({\n import: {\n step: snap.step,\n zipPath: snap.zipPath,\n analysis: snap.analysis,\n plan: snap.plan,\n result: snap.result,\n rollbackOnError: snap.rollbackOnError,\n errors: snap.errors,\n },\n })\n }\n\n /* ------------------------------------------------------ 持久化 load/save */\n\n /** 从存储恢复非敏感状态(构造时调用一次;损坏数据回退默认并清键)。 */\n load(): void {\n if (this.storage === null) return\n let raw: string | null = null\n try {\n raw = this.storage.getItem(STATE_KEY)\n } catch {\n return\n }\n if (raw === null || raw === '') {\n this.state = defaultState()\n return\n }\n const parsed = parsePersistedState(raw)\n if (parsed === null) {\n // 损坏/版本不符:清掉脏键,回退默认\n try {\n this.storage.removeItem(STATE_KEY)\n } catch {\n // 忽略存储错误\n }\n this.state = defaultState()\n return\n }\n this.applyPersisted(parsed)\n }\n\n /** 把解析后的持久化状态合并进运行时状态;敏感字段强制回到默认(清空)。 */\n private applyPersisted(parsed: PersistedState): void {\n this.state = {\n v: 1,\n view: parsed.view,\n export: {\n ...defaultExportState(),\n ...parsed.export,\n // 硬性:密码/确认密码绝不从存储恢复\n password: '',\n passwordConfirm: '',\n },\n import: {\n ...defaultImportState(),\n ...parsed.import,\n // 旧版持久化载荷可能缺 selectedFileName(undefined)→ 归一到 null\n selectedFileName: parsed.import.selectedFileName ?? null,\n // 硬性:秘密补录值绝不从存储恢复;collector 由 plan+决策重建\n secretInputs: {},\n conflictCollector: null,\n },\n }\n // 安全兜底:confirm 阶段若仍缺必填 secret(刷新后 secretInputs 必为空),\n // 强制退回 secrets 阶段要求重输(验收 m2-refresh 的「secrets 阶段要求重输」)。\n const missing = this.state.import.plan?.missingSecrets ?? []\n if (this.state.import.phase === 'confirm' && missing.length > 0) {\n this.state.import.phase = 'secrets'\n }\n // 冲突阶段:由恢复后的 plan + 决策重建 collector(刷新后实例必然丢失)\n const imp = this.state.import\n if (imp.phase === 'conflicts' && imp.plan !== null) {\n imp.conflictCollector = rebuildConflictCollector(imp.plan, imp.conflictResolutions)\n }\n }\n\n /** 把非敏感状态写入 sessionStorage(白名单序列化;无存储时为空操作)。 */\n save(): void {\n if (this.storage === null) return\n try {\n this.storage.setItem(STATE_KEY, JSON.stringify(toPersistedState(this.state)))\n } catch {\n // 存储满/不可用:静默降级,状态仍完整存在于内存\n }\n }\n\n /* ---------------------------------------------------- 控制器实例(缓存) */\n\n /** ExportFlow 控制器实例:懒创建 + 缓存(切 tab/关面板不重建)。 */\n exportFlow(api: ConfigManagerApi): ExportFlow {\n if (this.exportFlowInst === null) {\n if (this.apiRef === null) this.apiRef = api\n this.exportFlowInst = new ExportFlow({\n port: api,\n onProgress: (event) => { this.patch({ export: { progress: event } }) },\n })\n }\n return this.exportFlowInst\n }\n\n /** ImportWizard 控制器实例:懒创建 + 缓存;首次创建时从持久化快照 rehydrate。 */\n importWizard(api: ConfigManagerApi): ImportWizard {\n if (this.importWizardInst === null) {\n if (this.apiRef === null) this.apiRef = api\n const wizard = new ImportWizard({\n port: api,\n onProgress: (event) => { this.patch({ import: { progress: event } }) },\n defaultRollbackOnError: true,\n })\n // 刷新恢复:把持久化快照写回控制器(仅非敏感字段;secretInputs 置空)\n writeWizardSnapshot(wizard, this.state.import)\n this.importWizardInst = wizard\n }\n return this.importWizardInst\n }\n\n /* ------------------------------------------------- m2-resume:run 重订阅 */\n\n /**\n * 重新订阅进行中的 run:GET /runs 找回活跃 runId → 轮询 /progress 直到\n * 完成/失败,把 RunState.result 回填 store(导出结果 / 导入结果均可恢复)。\n * 返回是否有 run 被恢复。幂等:同一 runId 不会重复轮询。\n */\n async resume(api: ConfigManagerApi): Promise<boolean> {\n if (this.apiRef === null) this.apiRef = api\n let active: RunState[]\n try {\n active = await api.runs()\n } catch {\n // host 不可达:保持现状,不做破坏性重置\n return false\n }\n let resumed = false\n const exportRun = active.find((r) => r.kind === 'export')\n if (exportRun !== undefined) {\n resumed = true\n this.patch({\n export: {\n running: true,\n runId: exportRun.runId,\n progress: mapRunProgress('export', exportRun),\n },\n })\n this.pollRun(exportRun.runId, 'export')\n } else if (this.state.export.running) {\n // 持久化显示导出中,但 host 无活跃导出 run:请求已结束且响应丢失,不可恢复\n this.patch({\n export: {\n running: false,\n progress: null,\n runId: null,\n error: '上次导出任务已结束但结果无法恢复,请重新导出',\n },\n })\n }\n\n const importRun = active.find((r) => r.kind === 'import')\n if (importRun !== undefined) {\n resumed = true\n this.patch({\n import: {\n running: true,\n runId: importRun.runId,\n step: 'importing',\n progress: mapRunProgress('import', importRun),\n },\n })\n this.pollRun(importRun.runId, 'import')\n } else if (this.state.import.step === 'importing') {\n // 持久化显示导入中,但 host 无活跃导入 run:任务已结束/被清理,结果不可恢复\n this.importWizardInst?.reset()\n this.patch({\n import: {\n step: 'select',\n phase: 'preview',\n runId: null,\n running: false,\n progress: null,\n conflictCollector: null,\n selectedFileName: null,\n errors: [],\n error: '上次导入任务已结束或超过保留期,结果无法恢复,请重新导入',\n },\n })\n }\n return resumed\n }\n\n /** 停止全部轮询(视图卸载时调用;服务端执行不受影响,重开面板再 resume)。 */\n stopResume(): void {\n this.polling.clear()\n this.watchActive.clear()\n for (const timer of this.timers.values()) clearTimeout(timer)\n this.timers.clear()\n }\n\n /* ------------------------------------- m3:本次会话内启动 run 的实时轮询 */\n\n /**\n * 本次会话内启动的 run(POST /export 或 /execute 请求进行期间)的实时进度订阅。\n * 请求是同步的、响应到达才知 runId,所以先经 GET /runs 发现进行中的 run(500ms),\n * 发现后转入 /progress 轮询(同一间隔),done/failed 自动停止。\n *\n * 与 m2 resume 的收敛:两者共用 pollRun / polling / timers 同一套轮询器,\n * 只是间隔不同(resume 恢复 1s、本方法实时 500ms)且发现阶段不同\n * (resume 用 /runs 一次性找回 runId;本方法持续 /runs 直到出现活跃 run)。\n * 同一 runId 不会重复轮询(polling 集合防重)。\n */\n watchRunning(kind: RunKind, intervalMs?: number): void {\n if (this.watchActive.has(kind)) return\n this.watchActive.add(kind)\n const api = this.apiRef\n if (api === null) {\n this.watchActive.delete(kind)\n return\n }\n const interval = intervalMs ?? this.pollIntervalMs\n const tick = (): void => {\n if (!this.watchActive.has(kind)) return\n void api.runs().then(\n (active) => {\n if (!this.watchActive.has(kind)) return\n const run = active.find((r) => r.kind === kind && r.status === 'running')\n if (run === undefined) {\n // 请求尚未注册 run / 已瞬间结束:继续发现,直到视图 stop 或转入 /progress\n this.scheduleWatch(kind, tick, interval)\n return\n }\n // 发现进行中 run:停止发现,交给 /progress 轮询器(同一间隔)\n this.watchActive.delete(kind)\n this.patchProgress(kind, run)\n this.pollRun(run.runId, kind, interval)\n },\n () => {\n if (this.watchActive.has(kind)) this.scheduleWatch(kind, tick, interval)\n },\n )\n }\n this.scheduleWatch(kind, tick, interval)\n }\n\n /** 停止某 kind 的「发现进行中 run」轮询(视图请求结束后调用;/progress 轮询自行结束)。 */\n stopRunWatch(kind: RunKind): void {\n this.watchActive.delete(kind)\n }\n\n /** 调度下一轮发现;每 kind 只保留一个挂起定时器。 */\n private scheduleWatch(kind: RunKind, tick: () => void, intervalMs: number): void {\n const timer = setTimeout(tick, intervalMs)\n this.timers.set(`watch:${kind}`, timer)\n }\n\n private pollRun(runId: string, kind: RunKind, intervalMs?: number): void {\n if (this.polling.has(runId)) return\n this.polling.add(runId)\n const api = this.apiRef\n if (api === null) return\n const interval = intervalMs ?? this.pollIntervalMs\n const tick = (): void => {\n if (!this.polling.has(runId)) return\n void api.progress(runId).then(\n (state) => {\n if (!this.polling.has(runId)) return\n if (state.status === 'running') {\n this.patchProgress(kind, state)\n this.scheduleTick(runId, tick, interval)\n } else {\n this.polling.delete(runId)\n this.applySettled(kind, state)\n }\n },\n () => {\n // 404(过保留期)/网络错误:run 不可恢复,停止轮询并如实提示\n this.polling.delete(runId)\n this.applyGone(kind)\n },\n )\n }\n this.scheduleTick(runId, tick, interval)\n }\n\n /** 调度下一轮询;每 runId 只保留一个挂起定时器(fire 后由下一次调度覆盖)。 */\n private scheduleTick(runId: string, tick: () => void, intervalMs: number): void {\n const timer = setTimeout(tick, intervalMs)\n this.timers.set(runId, timer)\n }\n\n private patchProgress(kind: RunKind, state: RunState): void {\n const event = mapRunProgress(kind, state)\n if (kind === 'export') this.patch({ export: { progress: event } })\n else this.patch({ import: { progress: event } })\n }\n\n /** run 完成/失败:把 RunState.result 回填 store(并镜像回控制器)。 */\n private applySettled(kind: RunKind, state: RunState): void {\n if (kind === 'export') {\n const result = state.result as\n | { zipPath: string; manifest: Manifest; report: ExportRunResult['report'] }\n | undefined\n if (state.status === 'done' && result !== undefined && typeof result.zipPath === 'string') {\n this.patch({\n export: {\n running: false,\n progress: { stage: 'done', step: 1, total: 1 },\n result: { ...result, text: renderExportReport(result.report) },\n downloaded: false,\n },\n })\n } else {\n this.patch({\n export: {\n running: false,\n progress: null,\n result: null,\n downloaded: false,\n error: state.error ?? '导出失败(结果不可用)',\n },\n })\n }\n return\n }\n // import\n const result = state.result as ImportResult | undefined\n if (state.status === 'done' && result !== undefined && typeof result === 'object') {\n const wizard = this.importWizardInst\n if (wizard !== null) {\n const imp: ImportLiveState = {\n ...this.state.import,\n step: 'result',\n result,\n secretInputs: {},\n conflictCollector: null,\n }\n writeWizardSnapshot(wizard, imp)\n }\n this.patch({\n import: {\n step: 'result',\n result,\n running: false,\n progress: { stage: 'done', step: 1, total: 1 },\n error: null,\n },\n })\n } else {\n const wizard = this.importWizardInst\n if (wizard !== null) {\n const internals = wizard as unknown as WizardInternals\n internals.errors = [...internals.errors, state.error ?? '导入失败']\n }\n this.patch({\n import: {\n running: false,\n progress: null,\n error: state.error ?? '导入失败',\n errors: [...this.state.import.errors, state.error ?? '导入失败'],\n },\n })\n }\n }\n\n /** run 消失(404/网络错误):停止轮询并提示不可恢复。 */\n private applyGone(kind: RunKind): void {\n if (kind === 'export') {\n this.patch({\n export: {\n running: false,\n progress: null,\n runId: null,\n error: '任务已结束或超过保留期,进度不可恢复',\n },\n })\n } else {\n this.importWizardInst?.reset()\n this.patch({\n import: {\n running: false,\n progress: null,\n runId: null,\n step: 'select',\n phase: 'preview',\n conflictCollector: null,\n selectedFileName: null,\n errors: [],\n error: '任务已结束或超过保留期,进度不可恢复',\n },\n })\n }\n }\n}\n\n/** 模块级单例(浏览器半所有视图共享;构造时自动 load())。 */\nexport const runStore = new RunStore()\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 * 可操作错误展示(规范 §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 * m3: 进度展示的纯逻辑层(框架无关,node 可测)。\n *\n * 背景:m1 的 RunState 携带真实进度(section/sectionTotal = 当前分区 3/12、\n * item/itemTotal = 内部计数如插件 6/18、detail = 当前项名);m2 的 store 把\n * RunState 映射为 ProgressEvent 并存入 progress 字段。本模块定义客户端的\n * RunProgress(ProgressEvent 超集,额外携带分区/内部计数,JSON 可序列化),\n * 并提供 computeProgressView() 把进度事件转成渲染模型 —— ProgressBar 只做\n * 纯渲染,所有判定逻辑集中在此、可单测。\n *\n * 兼容路径:无 section/item 的普通 ProgressEvent(控制器 onProgress 发出)\n * 走原逻辑 —— 阶段文案 + step/total 百分比,无徽章。\n */\nimport { stageText } from '../../ui/progress.ts'\nimport { zhUiT, type UiT } from '../../ui/i18n.ts'\nimport type { ProgressEvent } from '../../ui/types.ts'\n\n/** m3: 客户端进度事件 = ProgressEvent 超集(RunState 轮询映射产物;可 JSON 序列化)。 */\nexport interface RunProgress extends ProgressEvent {\n /** 当前分区(adapter id / 阶段名)与分区总数(如 settings · 3/12);导入无此语义为 null */\n section?: string | null\n sectionTotal?: number | null\n /** 内部计数(如插件 6/18;导出 = 分区序号,导入 = 已处理计划项数) */\n item?: number | null\n itemTotal?: number | null\n}\n\n/** 徽章渲染数据(label · current/total)。 */\nexport interface ProgressBadge {\n label: string\n current: number\n total: number\n}\n\n/** ProgressBar 的渲染模型(纯数据,测试断言用)。 */\nexport interface ProgressView {\n /** 阶段文案(stageText) */\n label: string\n /** 百分比(step/total;无则 null = 不定态动画) */\n percent: number | null\n /** 当前分区徽章(settings · 3/12) */\n sectionBadge: ProgressBadge | null\n /** 内部计数徽章(plugins · 6/18;导出时与分区计数同源则去冗余) */\n countBadge: ProgressBadge | null\n /** 当前项名(detail;与分区名相同时去冗余) */\n detail: string | null\n}\n\n/**\n * 把进度事件换算成渲染模型。\n * - percent:优先 ProgressEvent.step/total(控制器阶段进度 / 轮询的内部计数);\n * - sectionBadge(当前分区,如 settings · 3/12):label=分区 id、current=item\n * (1-based 分区序号,见 core exporter onSection)、total=sectionTotal;\n * - countBadge(内部计数,如 plugins · 6/18):label=分区 id、current=item、\n * total=itemTotal;导出时 itemTotal 与 sectionTotal 同值(分区序号即内部计数)\n * → 置 null,避免「3/12 3/12」重复;\n * - detail(当前项名):非空且不等于分区 id(导出时 detail 恒为分区 id,去冗余)。\n */\nexport function computeProgressView(event: RunProgress | null, t: UiT = zhUiT): ProgressView {\n if (event === null) {\n return { label: '', percent: null, sectionBadge: null, countBadge: null, detail: null }\n }\n const section = event.section ?? null\n const sectionTotal = event.sectionTotal ?? null\n const item = event.item ?? null\n const itemTotal = event.itemTotal ?? null\n\n const percent =\n event.step !== undefined && event.total !== undefined && event.total > 0\n ? Math.round((event.step / event.total) * 100)\n : item !== null && itemTotal !== null && itemTotal > 0\n ? Math.round((item / itemTotal) * 100)\n : null\n\n const sectionBadge: ProgressBadge | null =\n section !== null && item !== null && sectionTotal !== null && sectionTotal > 0\n ? { label: section, current: item, total: sectionTotal }\n : null\n\n let countBadge: ProgressBadge | null =\n section !== null && item !== null && itemTotal !== null && itemTotal > 0\n ? { label: section, current: item, total: itemTotal }\n : null\n if (countBadge !== null && sectionBadge !== null && itemTotal === sectionTotal) {\n // 导出:item/itemTotal 与 section/sectionTotal 同源(当前分区序号),去冗余\n countBadge = null\n }\n\n const detail =\n typeof event.detail === 'string' && event.detail !== '' && event.detail !== section\n ? event.detail\n : null\n\n return { label: stageText(event.stage, t), percent, sectionBadge, countBadge, detail }\n}\n","/**\n * 进度条(规范 §29 + m3 真实进度)。\n *\n * 数据流:\n * - 控制器(ExportFlow / ImportWizard)onProgress 发出普通 ProgressEvent\n * (阶段文案 + step/total),走兼容路径;\n * - m3:store 经 /runs + /progress 轮询得到的 RunState 映射为 RunProgress\n * (额外携带 section/sectionTotal/item/itemTotal/detail),渲染为\n * 「分区徽章(settings · 3/12)+ 内部计数徽章(plugins · 6/18)+ 当前项名」。\n *\n * 所有换算逻辑在 progress-view.ts 的 computeProgressView()(纯函数,可单测);\n * 本组件只做渲染。未知阶段回退显示 id 本身。\n */\nimport { computeProgressView } from './progress-view.ts'\nimport type { RunProgress } from './progress-view.ts'\nimport css from '../config-manager.module.css'\n\nexport interface ProgressBarProps {\n /** 当前进度事件(null = 未开始);普通 ProgressEvent 亦兼容 */\n event: RunProgress | null\n /** 是否正在执行(false 时显示为完成态) */\n active: boolean\n}\n\n/**\n * 进度条:阶段文字 + 分区/内部计数徽章 + 当前项名 + 百分比。\n */\nexport function ProgressBar({ event, active }: ProgressBarProps) {\n const view = computeProgressView(event)\n\n return (\n <div className={css.progressBlock}>\n <div className={css.progressMeta}>\n <span className={css.progressLabel}>{view.label}</span>\n {view.sectionBadge !== null && (\n <span className={`${css.progressBadge} ${css.progressBadgeSection}`}>\n {view.sectionBadge.label} · {view.sectionBadge.current}/{view.sectionBadge.total}\n </span>\n )}\n {view.countBadge !== null && (\n <span className={`${css.progressBadge} ${css.progressBadgeCount}`}>\n {view.countBadge.label !== '' ? `${view.countBadge.label} · ` : ''}\n {view.countBadge.current}/{view.countBadge.total}\n </span>\n )}\n {view.detail !== null && <span className={css.progressDetail}>{view.detail}</span>}\n {view.percent !== null && <span className={css.progressPercent}>{view.percent}%</span>}\n </div>\n <div className={css.progressTrack}>\n {view.percent !== null ? (\n <div\n className={`${css.progressBar} ${active ? '' : css.progressBarDone}`}\n style={{ width: `${view.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 * **也绝不进入 sessionStorage** —— m2 白名单剔除,刷新后要求重输);\n * - 进度:ExportFlow.run 发出 ProgressEvent → ProgressBar;\n * - 结果:ReportView(export) + 下载按钮(File System Access API 流式落盘)。\n *\n * m2:全部 UI 状态由模块级 runStore 持有(切 tab/关面板不重建、刷新恢复),\n * 控制器实例(ExportFlow)由 store 缓存复用。\n */\nimport { useCallback, useSyncExternalStore } from 'react'\nimport type { ChangeEvent } from 'react'\nimport { EXPORT_GROUPS } 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 { runStore, type ExportMode } from '../run-store.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\n/**\n * 导出主视图:Quick/Custom 切换 → 勾选/密码 → 执行 → 进度 → 报告 → 下载。\n */\nexport function ExportView({ api, t }: ExportViewProps) {\n // m2:状态统一来自模块级 store(sessionStorage 持久化;切 tab 不重建)\n const state = useSyncExternalStore(runStore.subscribe, runStore.getSnapshot)\n const exp = state.export\n // 控制器实例由 store 缓存复用(切 tab / 关面板不重建)\n const flow = runStore.exportFlow(api)\n\n const mode = exp.mode\n const selection = exp.selection\n const includeSecrets = exp.includeSecrets\n // 密码字段仅内存(store 的敏感字段,绝不序列化进 sessionStorage)\n const password = exp.password\n const passwordConfirm = exp.passwordConfirm\n const running = exp.running\n const progress = exp.progress\n const result = exp.result\n const error = exp.error\n const downloaded = exp.downloaded\n\n const setMode = (next: ExportMode): void => {\n runStore.patch({ export: { mode: next } })\n }\n const setIncludeSecrets = (next: boolean): void => {\n runStore.patch({ export: { includeSecrets: next } })\n }\n const setPassword = (value: string): void => {\n runStore.patch({ export: { password: value } })\n }\n const setPasswordConfirm = (value: string): void => {\n runStore.patch({ export: { passwordConfirm: value } })\n }\n\n const toggleSection = useCallback((id: SectionId, checked: boolean): void => {\n const has = selection.includes(id)\n if (checked && !has) runStore.patch({ export: { selection: [...selection, id] } })\n if (!checked && has) runStore.patch({ export: { selection: selection.filter((s) => s !== id) } })\n }, [selection])\n\n const passwordInvalid =\n includeSecrets && (password === '' || password !== passwordConfirm)\n\n /** 执行导出(Quick 或 Custom) */\n const runExport = async (): Promise<void> => {\n if (passwordInvalid) return\n runStore.patch({\n export: { running: true, error: null, result: null, downloaded: false, progress: null, runId: null },\n })\n // m3:请求进行期间经 /runs 发现 runId 并轮询 /progress(500ms)显示真实进度\n runStore.watchRunning('export', 500)\n try {\n // 加密密码随本次导出请求体传给 Host 半(仅内存)\n api.exportPassword = includeSecrets ? password : null\n const run = await flow.run(mode, selection, { includeSecrets })\n // ExportResponse 携带 runId(/progress 查询与刷新恢复用);控制器类型不含,运行时对象有\n const runId = (run as { runId?: unknown }).runId\n runStore.patch({\n export: {\n result: run,\n runId: typeof runId === 'string' ? runId : null,\n progress: { stage: 'done', step: 1, total: 1 },\n },\n })\n } catch (err) {\n runStore.patch({ export: { error: err instanceof Error ? err.message : String(err) } })\n } finally {\n runStore.stopRunWatch('export')\n runStore.patch({ export: { running: false } })\n }\n }\n\n /** 下载导出的 ZIP 到本机 */\n const download = async (): Promise<void> => {\n if (result === null) return\n try {\n runStore.patch({ export: { error: null } })\n const outcome = await api.download(result.zipPath)\n runStore.patch({ export: { downloaded: true } })\n void outcome // blob/streamed 由 api 处理;此处仅确认成功\n } catch (err) {\n runStore.patch({ export: { error: err instanceof Error ? err.message : String(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 * 导入向导的 UI 流程阶段(覆盖在 wizard.step === 'preview' 之上)与导航。\n *\n * 注意:hasConflicts / hasPathIssues / hasSecrets 来自 Dry Run 的原始\n * analysis/plan,流程中不会因用户已解决而重算——因此导航必须是「只前进」\n * (按适用阶段有序列表推进),绝不能靠“当前阶段 != X 且 hasX”判定:\n * 那会让已经过的阶段被重新命中,点「下一步」反而跳回上一步。\n */\n\n/** 中间流程阶段(wizard.step 之外的 UI 层页面) */\nexport type FlowPhase = 'preview' | 'conflicts' | 'path-mapping' | 'secrets' | 'confirm'\n\n/**\n * 计算下一阶段:在 `list`(适用阶段的有序列表)中取 `from` 的下一项。\n * - `from` 不在列表中(如来自 preview 页)→ 取第一项;\n * - `from` 已是最后一项(confirm)→ 原地返回;\n * - 绝不回退:已完成阶段不会因仍适用而被再次命中。\n */\nexport function nextFlowPhase(list: FlowPhase[], from: FlowPhase): FlowPhase {\n if (list.length === 0) return 'confirm'\n const idx = list.indexOf(from)\n const next = list[Math.min(idx + 1, list.length - 1)]\n return next ?? 'confirm'\n}\n","/**\n * 冲突决策列表(规范 §11,绑 src/ui/conflict-view.ts 的 ConflictCollector)。\n *\n * 渲染 plan 中 kind === 'Conflict' 的项,用户逐项选择\n * Keep Current / Use Imported;决策实时写入 collector,\n * 完成时父组件调用 collector.toResolutions() → wizard.setResolutions()。\n *\n * 注意:不提供 \"Review(稍后决定)\" 选项——Review 会被收集器计为\n * unresolved,导致「下一步」永远禁用(死路)。要么决策,要么不进入本步。\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]\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')}\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 * 导入文件选择(select 步骤)的纯渲染/流转模型(import-file-reselection)。\n *\n * 修复的 bug:导入向导选择文件后无法取消/换选 —— 没有入口,且文件 input 的\n * value 未清空(同一文件再次选择不触发 onChange)。\n *\n * 与 src/client/sync/sync-view.ts 同模式:无副作用纯函数,node --test 直接测,\n * React 组件只做装配与 DOM 副作用(input value 的读写经 consumePickedFile\n * 收敛,传入真实 e.target 即可)。换选不变式:每次 onChange 都以最新选中的\n * 文件为准 —— 提交的永远是最新选中的文件。\n */\nimport type { ConfigManagerKey } from '../locales.ts'\n\n/** select 步骤的展示/流转模型。 */\nexport interface FileSelectModel {\n /** 已选备份文件名(null = 尚未选择) */\n selectedName: string | null\n /** 上传/分析进行中(浏览按钮禁用;仍可取消) */\n busy: boolean\n}\n\n/** 由 store 状态推导 select 步骤的展示模型(selectedFileName + uploading)。 */\nexport function fileSelectModel(selectedName: string | null, busy: boolean): FileSelectModel {\n return { selectedName, busy }\n}\n\n/**\n * 处理文件选择(input onChange 入口):\n * - **恒清空 input 的 value** —— 同一文件再次选择也会触发 onChange(同文件换选);\n * - 返回选中的文件;用户关闭文件对话框(无文件)返回 undefined。\n * input 以最小接口 `{ value: string }` 传入,纯逻辑可测;React 侧传真实 e.target。\n */\nexport function consumePickedFile(file: File | undefined, input: { value: string } | null): File | undefined {\n if (input !== null) input.value = ''\n return file\n}\n\n/**\n * 选中/换选后的状态:以新文件替换旧选择(提交的永远是最新选中的文件);\n * 未选文件(对话框取消)保持原状态不变。\n */\nexport function applyPickedFile(current: FileSelectModel, file: File | undefined): FileSelectModel {\n if (file === undefined) return current\n return { selectedName: file.name, busy: true }\n}\n\n/** 取消选择:清空选择与忙碌态(回 idle;UI 同时清空 input value 保证同文件可重选)。 */\nexport function cancelSelection(current: FileSelectModel): FileSelectModel {\n return { selectedName: null, busy: false }\n}\n\n/** 浏览按钮文案键:已选文件 → 重新选择;否则 → 选择 ZIP 文件。 */\nexport function browseLabelKey(hasSelection: boolean): ConfigManagerKey {\n return hasSelection ? 'import.select.reselect' : 'import.select.browse'\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 * **也绝不进入 sessionStorage**(m2 白名单剔除,刷新后 secrets 阶段要求重输);\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 *\n * m2:全部 UI 状态由模块级 runStore 持有(切 tab/关面板不重建、刷新恢复),\n * 控制器实例(ImportWizard)由 store 缓存复用;每次 wizard 动作后 syncWizard()\n * 把控制器快照镜像进 store(非敏感字段持久化)。\n */\nimport { useRef, useState } from 'react'\nimport type { ChangeEvent } from 'react'\nimport { useSyncExternalStore } from 'react'\nimport { ConflictCollector } from '../../ui/conflict-view.ts'\nimport { nextFlowPhase, type FlowPhase } from '../../ui/flow.ts'\nimport type { ImportPreviewSummary } from '../../ui/types.ts'\nimport type { ConfigManagerApi, UploadResponse } from '../api.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport { runStore } from '../run-store.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 {\n applyPickedFile, browseLabelKey, cancelSelection, consumePickedFile, fileSelectModel,\n} from './import-file-select.ts'\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 层页面)——定义见 src/ui/flow.ts */\n\nconst SCORE_LABEL: Record<string, string> = {\n excellent: 'Excellent',\n good: 'Good',\n partial: 'Partial',\n unsupported: 'Unsupported',\n}\n\n/** 密钥补录表单(仅内存收集,值不外泄;onChange 写入 store 的仅内存字段) */\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 // m2:状态统一来自模块级 store;控制器实例由 store 缓存复用(不重建)\n const state = useSyncExternalStore(runStore.subscribe, runStore.getSnapshot)\n const imp = state.import\n const wizard = runStore.importWizard(api)\n\n const step = imp.step\n const phase = imp.phase\n const progress = imp.progress\n const error = imp.error\n const uploading = imp.uploading\n const running = imp.running\n const rollbackOnError = imp.rollbackOnError\n const conflictCollector = imp.conflictCollector\n const pathMappings = imp.pathMappings\n const secretInputs = imp.secretInputs\n const fileInput = useRef<HTMLInputElement | null>(null)\n /**\n * 选择代数(取消选择时递增):作废在途的选择上传/分析,\n * 防止「取消后旧请求仍把向导推进/写错误」的竞态。\n */\n const pickGeneration = useRef(0)\n\n const setPhase = (next: FlowPhase): void => {\n runStore.patch({ import: { phase: next } })\n }\n\n /* ---------- 阶段判定 ---------- */\n\n const hasConflicts = (imp.plan?.items ?? []).some((i) => i.kind === 'Conflict')\n const hasPathIssues = (imp.analysis?.pathIssues.length ?? 0) > 0\n const hasSecrets = (imp.plan?.missingSecrets.length ?? 0) > 0\n\n /**\n * 适用阶段的有序列表(仅含需要用户处理 + 确认页)。\n * hasConflicts/hasPathIssues/hasSecrets 基于原始 analysis/plan(Dry Run 产物),\n * 在流程中不会因已解决而重算——所以导航必须只前进(见 nextFlowPhase),\n * 而不是靠\"当前阶段 != X\"判定(那会让已完成阶段被重新命中、跳回上一步)。\n */\n const applicablePhases = (): FlowPhase[] => {\n const list: FlowPhase[] = []\n if (hasConflicts) list.push('conflicts')\n if (hasPathIssues) list.push('path-mapping')\n if (hasSecrets) list.push('secrets')\n list.push('confirm')\n return list\n }\n\n /** 从某阶段完成后进入的下一个阶段:只前进(from 不在列表时取第一项) */\n const nextPhase = (from: FlowPhase): FlowPhase => nextFlowPhase(applicablePhases(), from)\n\n /* ---------- 动作 ---------- */\n\n /** 选择并上传 ZIP → wizard.selectZip(analyzing → compatibility)。\n * 换选不变式:每次选择都以最新文件为准(applyPickedFile 替换旧选择);\n * pickGeneration 守卫作废取消后在途的旧请求。 */\n const onPickFile = async (file: File | undefined): Promise<void> => {\n if (file === undefined) return\n const generation = pickGeneration.current\n const next = applyPickedFile(fileSelectModel(imp.selectedFileName, uploading), file)\n runStore.patch({ import: { uploading: next.busy, error: null, selectedFileName: next.selectedName } })\n try {\n const uploaded: UploadResponse = await api.upload(file)\n if (generation !== pickGeneration.current) return // 用户已取消本次选择\n const analysis = await wizard.selectZip(uploaded.zipPath)\n void analysis\n if (generation !== pickGeneration.current) return\n runStore.syncWizard()\n } catch (err) {\n if (generation !== pickGeneration.current) return\n runStore.patch({ import: { error: err instanceof Error ? err.message : String(err) } })\n runStore.syncWizard()\n } finally {\n if (generation === pickGeneration.current) {\n runStore.patch({ import: { uploading: false } })\n }\n }\n }\n\n /** 取消当前选择:回 idle 并清空 input value(同一文件可再次选择触发 onChange)。 */\n const cancelPick = (): void => {\n pickGeneration.current += 1\n const idle = cancelSelection(fileSelectModel(imp.selectedFileName, uploading))\n runStore.patch({ import: { selectedFileName: idle.selectedName, uploading: idle.busy, error: null } })\n if (fileInput.current !== null) fileInput.current.value = ''\n }\n\n /** Compatibility → Preview */\n const goPreview = async (): Promise<void> => {\n runStore.patch({ import: { error: null } })\n try {\n await wizard.confirmCompatibility()\n runStore.syncWizard()\n } catch (err) {\n runStore.patch({ import: { error: err instanceof Error ? err.message : String(err) } })\n runStore.syncWizard()\n }\n }\n\n /** 进入 conflicts 阶段(先创建 collector) */\n const enterConflicts = (): void => {\n const plan = imp.plan\n if (plan !== null && imp.conflictCollector === null) {\n runStore.patch({ import: { conflictCollector: new ConflictCollector(plan) } })\n }\n setPhase('conflicts')\n }\n\n /** Conflicts 完成:写入决策 → 下一阶段(决策同时持久化,切 tab/刷新可恢复) */\n const finishConflicts = (): void => {\n if (imp.conflictCollector !== null) {\n const resolutions = imp.conflictCollector.toResolutions()\n wizard.setResolutions(resolutions)\n runStore.patch({ import: { conflictResolutions: resolutions } })\n }\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 runStore.patch({ import: { error: null, running: true } })\n // m3:请求进行期间经 /runs 发现 runId 并轮询 /progress(500ms)显示真实进度\n runStore.watchRunning('import', 500)\n try {\n const promise = wizard.execute({ confirm: true, rollbackOnError })\n // execute() 已同步置 step='importing':立即镜像,保证执行期间刷新时持久化的是 importing\n runStore.syncWizard()\n const result = await promise\n // 响应含 runId(/progress 查询与刷新恢复用);控制器类型不含,运行时对象有\n const runId = (result as { runId?: unknown }).runId\n runStore.patch({ import: { runId: typeof runId === 'string' ? runId : null } })\n runStore.syncWizard()\n } catch (err) {\n runStore.patch({ import: { error: err instanceof Error ? err.message : String(err) } })\n runStore.syncWizard()\n } finally {\n runStore.stopRunWatch('import')\n runStore.patch({ import: { running: false } })\n }\n }\n\n /** 重置向导(重新导入) */\n const resetWizard = (): void => {\n pickGeneration.current += 1\n wizard.reset()\n runStore.syncWizard()\n runStore.patch({\n import: {\n phase: 'preview',\n uploading: false,\n running: false,\n progress: null,\n error: null,\n runId: null,\n selectedFileName: null,\n conflictCollector: null,\n conflictStrategy: 'merge',\n conflictResolutions: {},\n pathMappings: [],\n secretInputs: {},\n },\n })\n }\n\n /* ---------- 各步骤渲染 ---------- */\n\n if (step === 'select') {\n // 换选模型:由 store 的 selectedFileName/uploading 推导(import-file-reselection)\n const selectModel = fileSelectModel(imp.selectedFileName, uploading)\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>) => {\n // 恒清空 input value → 同一文件再次选择也会触发 onChange(同文件换选)\n const file = consumePickedFile(e.target.files?.[0], e.target)\n void onPickFile(file)\n }}\n />\n {selectModel.selectedName !== null && (\n <div className={css.hint} data-testid=\"import-selected-file\">\n {t('import.select.file', { name: selectModel.selectedName })}\n </div>\n )}\n <div className={css.actionRow}>\n {selectModel.selectedName !== null && (\n <Button variant=\"ghost\" onClick={cancelPick}>\n {t('import.select.cancel')}\n </Button>\n )}\n <Button\n variant=\"primary\"\n disabled={uploading}\n onClick={() => { fileInput.current?.click() }}\n >\n {uploading ? <Spinner label={t('import.analyzing')} /> : t(browseLabelKey(selectModel.selectedName !== null))}\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={imp.errors} />\n </div>\n )\n }\n\n if (step === 'compatibility') {\n const analysis = imp.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=\"ghost\" onClick={resetWizard}>{t('import.select.reselect')}</Button>\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 variant=\"ghost\" onClick={resetWizard}>{t('import.select.reselect')}</Button>\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 // 流程阶段页只在 wizard.step === 'preview' 时渲染:execute 开始后 step 变\n // importing/result,若 phase 仍是 confirm,必须让位给导入中/结果页(否则点「导入」\n // 无反应——confirm 页一直挡着,要回退一步才露出结果)。\n if (phase === 'conflicts' && step === 'preview') {\n if (conflictCollector === null || imp.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\n collector={conflictCollector}\n t={t}\n onChanged={() => {\n // 逐项决策实时持久化(非敏感),切 tab/刷新后可由 plan + 决策重建 collector\n if (imp.conflictCollector !== null) {\n runStore.patch({ import: { conflictResolutions: imp.conflictCollector.toResolutions() } })\n }\n }}\n />\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' && step === 'preview') {\n const issues = imp.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={(mappings) => { runStore.patch({ import: { pathMappings: mappings } }) }} />\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' && step === 'preview') {\n const missing = imp.plan?.missingSecrets ?? []\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('import.secrets.title')} />\n <SecretsForm missing={missing} t={t} onChange={(inputs) => { runStore.patch({ import: { secretInputs: inputs } }) }} />\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' && step === 'preview') {\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={(v) => {\n wizard.setRollbackOnError(v)\n runStore.patch({ import: { rollbackOnError: v } })\n }}\n label={t('import.rollbackOnError')}\n />\n <div className={css.actionRow}>\n <Button variant=\"ghost\" onClick={() => { setPhase('preview') }}>{t('common.back')}</Button>\n {/* m3-lock:进行中禁用「确认导入」,防止重复启动 */}\n <Button variant=\"primary\" disabled={running} 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={imp.errors} />\n </div>\n )\n }\n\n if (step === 'result') {\n const result = imp.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 // 报告已内联展示全部失败/警告项与回滚详情(§22/§23),无额外动作页\n }}\n />\n {result.needsRestart && <Banner kind=\"warn\">{t('report.needsRestart')}</Banner>}\n {error !== null && <ErrorBanner error={error} />}\n </div>\n )\n }\n\n return null\n}\n","/**\n * 快照恢复面板(M4):列出快照 → 选择 → dry-run 计划预览 → 确认执行 → 诚实报告。\n *\n * 数据流:api.snapshots() 加载列表;选择快照后 api.restoreSnapshot(id, true) 拿\n * 恢复计划(零写入预览);确认后 api.restoreSnapshot(id, false) 执行并展示报告\n * (restored / removedPlugins / manualHints(人工项高亮)/ failed / skipped)。\n * 全部状态组件内自持:恢复是低频显式操作,不进入 sessionStorage(快照列表可随时重载)。\n */\nimport { useEffect, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { RestorePlan, RestoreReport, SnapshotMeta } from '../../core/restore.ts'\nimport type { ConfigManagerApi } from '../api.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport { Badge, Banner, Button, Card, Empty, SectionTitle, Spinner } from '../common/ui.tsx'\nimport css from '../config-manager.module.css'\n\nexport interface SnapshotsPanelProps {\n api: ConfigManagerApi\n t: TranslateNS<'config-manager'>\n}\n\ninterface PanelState {\n status: 'loading' | 'ready' | 'error'\n error: string | null\n metas: SnapshotMeta[]\n selectedId: string | null\n planning: boolean\n plan: RestorePlan | null\n running: boolean\n report: RestoreReport | null\n actionError: string | null\n}\n\nconst initial: PanelState = {\n status: 'loading',\n error: null,\n metas: [],\n selectedId: null,\n planning: false,\n plan: null,\n running: false,\n report: null,\n actionError: null,\n}\n\nfunction statusLabel(t: TranslateNS<'config-manager'>, status: SnapshotMeta['status']): string {\n switch (status) {\n case 'pending': return t('snapshots.status.pending')\n case 'done': return t('snapshots.status.done')\n case 'rolled-back': return t('snapshots.status.rolled-back')\n default: return t('snapshots.status.unknown')\n }\n}\n\nfunction statusBadgeKind(status: SnapshotMeta['status']): 'info' | 'ok' | 'warn' | 'error' {\n switch (status) {\n case 'pending': return 'info'\n case 'done': return 'ok'\n case 'rolled-back': return 'warn'\n default: return 'error'\n }\n}\n\n/** 计划动作的本地化描述前缀(kind 标签 + 引擎已生成的中文 description) */\nfunction actionKindLabel(kind: string): string {\n switch (kind) {\n case 'hostFileRestore': return '整文件还原'\n case 'hostFileRemove': return '整文件删除'\n case 'pluginRemove': return '卸载插件'\n case 'fileRestore': return '还原文件'\n case 'fileRemove': return '删除文件'\n case 'credentialHint': return '人工提示'\n case 'skip': return '跳过'\n default: return kind\n }\n}\n\nexport function SnapshotsPanel({ api, t }: SnapshotsPanelProps) {\n const [state, setState] = useState<PanelState>(initial)\n\n const load = (): void => {\n setState((s) => ({ ...s, status: 'loading', error: null }))\n api.snapshots().then(\n (metas) => { setState((s) => ({ ...s, status: 'ready', metas })) },\n (err) => {\n setState((s) => ({\n ...s,\n status: 'error',\n error: err instanceof Error ? err.message : String(err),\n }))\n },\n )\n }\n\n useEffect(load, [api])\n\n const select = (id: string): void => {\n setState((s) => ({ ...s, selectedId: id, plan: null, report: null, actionError: null, planning: true }))\n api.restoreSnapshot(id, true).then(\n (res) => { setState((s) => ({ ...s, planning: false, plan: res.plan ?? null })) },\n (err) => {\n setState((s) => ({\n ...s,\n planning: false,\n actionError: err instanceof Error ? err.message : String(err),\n }))\n },\n )\n }\n\n const execute = (): void => {\n if (state.selectedId === null || state.running) return\n setState((s) => ({ ...s, running: true, report: null, actionError: null }))\n api.restoreSnapshot(state.selectedId, false).then(\n (res) => { setState((s) => ({ ...s, running: false, report: res.report ?? null })) },\n (err) => {\n setState((s) => ({\n ...s,\n running: false,\n actionError: err instanceof Error ? err.message : String(err),\n }))\n },\n )\n }\n\n const summary = (): string => {\n const s = state.plan?.summary\n if (s === undefined) return ''\n return `整文件还原 ${s.hostFileRestores} · 整文件删除 ${s.hostFileRemoves} · 插件卸载 ${s.pluginRemoves}`\n + ` · 文件还原 ${s.fileRestores} · 文件删除 ${s.fileRemoves} · 凭据提示 ${s.credentialHints} · 跳过 ${s.skips}`\n }\n\n const reportLine = (title: string, items: string[], warn: boolean): ReactNode => {\n if (items.length === 0) return null\n return (\n <Card className={css.card}>\n <strong className={warn ? css.warnText : undefined}>{title}({items.length})</strong>\n <div className={css.reportScroll}>\n <ul className={css.reportList}>\n {items.map((item, i) => <li key={`${title}-${i}`}>{item}</li>)}\n </ul>\n </div>\n </Card>\n )\n }\n\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('snapshots.title')} subtitle={t('snapshots.hint')} />\n\n {state.status === 'loading' && <Spinner label={t('snapshots.loading')} />}\n\n {state.status === 'error' && (\n <Banner kind=\"error\">\n {state.error ?? t('common.unknownError')}\n <Button variant=\"primary\" onClick={load}>{t('common.retry')}</Button>\n </Banner>\n )}\n\n {state.status === 'ready' && state.metas.length === 0 && (\n <Empty>{t('snapshots.empty')}</Empty>\n )}\n\n {state.status === 'ready' && state.metas.length > 0 && (\n <>\n <div className={css.snapshotList} role=\"listbox\" aria-label={t('snapshots.selectHint')}>\n <div className={css.snapshotRowHeader}>\n <span>{t('snapshots.createdAt')}</span>\n <span>{t('snapshots.sourceZip')}</span>\n <span>{t('snapshots.status')}</span>\n <span>{t('snapshots.entries')}</span>\n <span>{t('snapshots.plugins')}</span>\n </div>\n {state.metas.map((meta) => {\n const selected = meta.id === state.selectedId\n return (\n <button\n key={meta.id}\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n data-active={selected ? '' : undefined}\n className={css.snapshotRow}\n onClick={() => { select(meta.id) }}\n >\n <span title={meta.id}>{new Date(meta.createdAt).toLocaleString()}</span>\n <span title={meta.sourceZip}>{meta.sourceZip}</span>\n <span><Badge kind={statusBadgeKind(meta.status)}>{statusLabel(t, meta.status)}</Badge></span>\n <span>{meta.entryCount}</span>\n <span>{meta.beforePluginCount}</span>\n </button>\n )\n })}\n </div>\n\n {state.selectedId !== null && (\n <>\n {state.planning && <Spinner label={t('common.loading')} />}\n {state.plan !== null && (\n <Card>\n <SectionTitle title={t('snapshots.planTitle')} subtitle={summary()} />\n {state.plan.actions.length === 0 && <Empty>{t('snapshots.noActions')}</Empty>}\n {state.plan.actions.length > 0 && (\n <div className={css.planScroll}>\n <ul className={css.reportList}>\n {state.plan.actions.map((action, i) => (\n <li key={`plan-${i}`}>\n <span className={css.kindTag}>{actionKindLabel(action.kind)}</span>\n {' '}{action.description}\n {action.detail !== undefined && <span className={css.hint}>({action.detail})</span>}\n </li>\n ))}\n </ul>\n </div>\n )}\n <div className={css.rowActions}>\n <Button\n variant=\"danger\"\n disabled={state.running || state.plan.actions.every((a) => a.kind === 'skip')}\n onClick={execute}\n title={t('snapshots.confirmRestore')}\n >\n {state.running ? t('snapshots.executing') : t('snapshots.execute')}\n </Button>\n </div>\n {state.actionError !== null && <Banner kind=\"error\">{state.actionError}</Banner>}\n </Card>\n )}\n </>\n )}\n\n {state.report !== null && (\n <>\n <SectionTitle title={t('snapshots.reportTitle')} />\n {reportLine(t('snapshots.restored'), state.report.restored, false)}\n {reportLine(t('snapshots.removedPlugins'), state.report.removedPlugins, false)}\n {reportLine(t('snapshots.manualHints'), state.report.manualHints, true)}\n {reportLine(t('snapshots.failed'), state.report.failed.map((f) => `${f.item}: ${f.reason}`), true)}\n {reportLine(t('snapshots.skipped'), state.report.skipped, false)}\n </>\n )}\n </>\n )}\n </div>\n )\n}\n","/**\n * 远程同步浏览器半 —— `/api/dsh-config-manager/sync/*` 的类型化 fetch 封装。\n *\n * 独立于 `../api.ts`(ConfigManagerApi 为并行会话已改文件,禁碰):本文件自持\n * 端点常量与 readJson/postJson 小工具(与 api.ts 同款模式),只新增不修改。\n *\n * 端点契约(Host 半 src/index.ts 的 makeRoutes 按此实现):\n * ```\n * GET /api/dsh-config-manager/sync/status → SyncStatusResponse (配置/凭据/上次同步)\n * POST /api/dsh-config-manager/sync/push → SyncPushReport (body: { repoUrl, gitBin?, token?, snapshotId? })\n * POST /api/dsh-config-manager/sync/pull → SyncPullReport (body: { repoUrl, gitBin?, token?, strategy?, snapshotId? })\n * POST /api/dsh-config-manager/sync/github/start → GithubDeviceFlowStartResponse(GitHub OAuth 设备码)\n * POST /api/dsh-config-manager/sync/github/poll → GithubPollResponse(凭 flowId 轮询;成功时 token 已由 Host 写入 credentials)\n * POST /api/dsh-config-manager/sync/github/cancel → { ok: true }\n * ```\n *\n * 安全约束:\n * - token 只存在于请求体内(同源 loopback,与导入 secretInputs 同策略),由 Host 写入\n * DSH credentials(credentialRef),绝不落同步文件/日志/URL;响应永不回传 token;\n * - GitHub device flow:浏览器只持有 flowId(随机 id)+ user_code + 授权页 URL;\n * device_code 与 access token 只存在于宿主(内存 / DSH credentials),永不回传;\n * - 错误消息由 Host 侧已脱敏(GitTransport 统一 [REDACTED]),UI 侧再经 ErrorBanner redact 兜底;\n * - 本文件不 import 任何 node 模块(纯浏览器 bundle;sync-engine 仅作 type-only 引用)。\n */\nimport type { SyncPullReport, SyncPushReport } from '../../sync/sync-engine.ts';\nimport type { PlanItemKind } from '../../core/types.ts';\nimport type { SectionId } from '../../schema/types.ts';\nimport { ConfigManagerApiError } from '../api.ts';\nimport { zhUiT, type UiT } from '../../ui/i18n.ts';\n\n/** 同步端点常量(与 Host 半 src/index.ts API 常量保持一致) */\nexport const SYNC_API = {\n base: '/api/dsh-config-manager/sync',\n status: '/api/dsh-config-manager/sync/status',\n push: '/api/dsh-config-manager/sync/push',\n pull: '/api/dsh-config-manager/sync/pull',\n githubStart: '/api/dsh-config-manager/sync/github/start',\n githubPoll: '/api/dsh-config-manager/sync/github/poll',\n githubCancel: '/api/dsh-config-manager/sync/github/cancel',\n history: '/api/dsh-config-manager/sync/history',\n snapshotsList: '/api/dsh-config-manager/sync/snapshots-list',\n sync: '/api/dsh-config-manager/sync/sync',\n applyItems: '/api/dsh-config-manager/sync/apply-items',\n cancel: '/api/dsh-config-manager/sync/cancel',\n autosync: '/api/dsh-config-manager/sync/autosync',\n rollback: '/api/dsh-config-manager/sync/rollback',\n} as const;\n\n/** DSH credentials 中的同步 token 引用名(Host 半同值;仅供提示文案使用,值由 Host 读写) */\nexport const SYNC_CREDENTIAL_REF = 'DSH_CONFIG_MANAGER_SYNC_TOKEN';\n\n/** GET /sync/status 响应:配置/凭据/上次同步的只读事实(无任何 secret 值) */\nexport interface SyncStatusResponse {\n ok: boolean;\n /** 是否已保存过仓库配置(sync-config.json) */\n configured: boolean;\n /** 上次使用的仓库地址(不含 token,可回显) */\n repoUrl?: string;\n gitBin?: string;\n /** DSH credentials 中是否已存在 token(describe 只报状态,值永不返回) */\n credentialConfigured: boolean;\n credentialWritable: boolean;\n /** sync-state.lastSyncAt;'' = 从未同步 */\n lastSyncAt?: string;\n /** sync-state.sections 条目数 */\n sectionCount: number;\n transport?: { type: string; ref: string };\n /** 自动同步当前状态(供 UI 顶部开关回填;§3.9) */\n autosync?: AutosyncStatusResponse;\n}\n\n/** push 请求体(token 可选:非空则 Host 先写入 DSH credentials 再使用) */\nexport interface SyncPushPayload {\n repoUrl: string;\n gitBin?: string;\n token?: string;\n}\n\n/** pull 请求体(strategy 缺省 merge:冲突保留待决策;snapshotId 缺省 = 最新) */\nexport interface SyncPullPayload extends SyncPushPayload {\n strategy?: 'merge' | 'replace' | 'skipExisting';\n snapshotId?: string;\n}\n\n/* ---------------------------------------------------------------- 一键同步(方案 A) */\n\n/** GET /sync/snapshots-list 响应:远端历史快照列表(按 createdAt 倒序)。 */\nexport interface SyncSnapshotsListResponse {\n ok: boolean;\n /** 按 createdAt 倒序(最新在前) */\n snapshots: SyncSnapshotLite[];\n /** 当前本地祖先指针(sync-state.lastSnapshotId),用于高亮当前基线 */\n currentSnapshotId?: string;\n}\n\n/** 远端快照摘要(「选择历史快照」下拉项)。 */\nexport interface SyncSnapshotLite {\n id: string;\n createdAt: string;\n sectionCount: number;\n platform: string;\n dshVersion: string;\n}\n\n/** POST /sync/sync 请求体(一键同步第一步:拉取 → 差异确认会话)。 */\nexport interface SyncStartPayload {\n repoUrl: string;\n gitBin?: string;\n token?: string;\n /** 缺省 = 最新快照;传入则对该历史快照拉取 */\n snapshotId?: string;\n}\n\n/** POST /sync/sync 响应:差异确认会话(items 供 UI 逐项确认)。 */\nexport interface SyncStartResponse {\n ok: boolean;\n /** 差异确认会话 id:后续 apply-items / cancel 引用 */\n syncSessionId: string;\n /** 被拉取的远端快照 id */\n snapshotId: string;\n items: SyncConfirmItem[];\n /** 是否包含任何需人工决策项 */\n needsReview: boolean;\n compatibility: 'excellent' | 'good' | 'partial' | 'unsupported';\n message?: string;\n}\n\n/** 单条可确认的差异项(由 ImportPlan.item 投影 + 冲突详情)。 */\nexport interface SyncConfirmItem {\n itemId: string;\n adapter: SectionId;\n kind: PlanItemKind;\n description: string;\n severity: 'info' | 'warning' | 'error';\n /** 默认采纳方向;Conflict/MissingSecret 等人工项默认 false */\n defaultAdopt: boolean;\n /** 用户最终决策(缺省 = defaultAdopt) */\n adopt: boolean;\n /** 冲突项内联解决所需详情(仅 Conflict 项非空) */\n conflict?: SyncConflictDetail;\n /** 该项若采用将写入的目标摘要 */\n target?: { adapter: SectionId; ref: string };\n}\n\n/** 冲突项内联解决详情(来源 MergeConflict + 可读 diff)。 */\nexport interface SyncConflictDetail {\n path: string;\n kind: 'key' | 'file' | 'section';\n local?: unknown;\n remote?: unknown;\n ancestor?: unknown;\n diff?: string;\n}\n\n/** POST /sync/apply-items 请求体(一键同步第二步:按逐项决策执行导入)。 */\nexport interface ApplyItemsPayload {\n syncSessionId: string;\n /** 每项的最终采纳决策(未列出项视为 adopt=false) */\n adoptions: SyncItemAdoption[];\n}\n\n/** 单条采纳决策。 */\nexport interface SyncItemAdoption {\n itemId: string;\n adopt: boolean;\n /** 冲突项解决方案(仅当该项是 Conflict 且 adopt=true 时必须) */\n resolution?: 'useRemote' | 'keepLocal' | 'skip';\n}\n\n/** POST /sync/apply-items 响应。 */\nexport interface ApplyItemsResponse {\n ok: boolean;\n applied: string[];\n skipped: string[];\n needsRestart: boolean;\n warnings: string[];\n /** 应用前快照 id(UI 一键回滚用) */\n restoreId: string;\n /** 任一失败是否整体回滚 */\n rolledBack: boolean;\n failed: { itemId: string; message?: string }[];\n result: unknown;\n}\n\n/* ---------------------------------------------------------------- 自动同步 */\n\n/** 统一间隔类型。 */\nexport type AutosyncInterval = '5m' | '15m' | '30m' | '60m' | '6h' | '12h' | '24h';\n\n/** 最近一次自动同步执行状态。 */\nexport type AutosyncRunStatus = 'success' | 'skipped' | 'failed' | 'partial';\n\n/** GET/POST /sync/autosync 响应:自动同步状态。 */\nexport interface AutosyncStatusResponse {\n enabled: boolean;\n interval: AutosyncInterval;\n lastRunAt?: string;\n lastRunStatus?: AutosyncRunStatus;\n lastRunMessage?: string;\n consecutiveFailures: number;\n /** 距上次自动同步已过 ms(host 计算,供 UI 倒计时/立即触发判断) */\n elapsedMs: number;\n lastRunHistoryId?: string;\n}\n\n/** POST /sync/autosync 请求体。 */\nexport interface AutosyncUpdatePayload {\n enabled: boolean;\n interval?: AutosyncInterval;\n startupMinIntervalMs?: number;\n}\n\n/* ---------------------------------------------------------------- 同步历史 */\n\n/** 自动同步执行记录(§3.7 AutosyncHistoryEntry)。 */\nexport interface AutosyncHistoryEntry {\n direction: 'pull' | 'push' | 'both';\n status: 'success' | 'skipped' | 'failed' | 'partial';\n /** 跳过原因(冲突项 / 缺失依赖 / Install / 错误 / 无远端 / 网络) */\n skipReason?: string;\n /** 被跳过的冲突分区 id(冲突跳过时列出) */\n conflictedSections?: string[];\n /** 本次自动合并实际写入的分区 */\n appliedSections?: string[];\n /** 本次 push 产生的快照 id */\n pushedSnapshotId?: string;\n /** 本次 pull 来源快照 id */\n pulledSnapshotId?: string;\n error?: string;\n notifiedAt?: string;\n /** 本次触发时的连续失败计数 */\n failureCountAtRun: number;\n createdAt: string;\n}\n\n/** 同步历史条目(Host 端返回;kind='autosync' 时 autosync 非空)。 */\nexport interface SyncHistoryEntry {\n id: string;\n createdAt: string;\n kind: 'push' | 'pull' | 'apply' | 'autosync' | 'rollback';\n sectionCount?: number;\n reviewCount?: number;\n autosync?: AutosyncHistoryEntry;\n}\n\n/** GET /sync/history 响应:{ entries }。 */\nexport interface SyncHistoryResponse {\n entries: SyncHistoryEntry[];\n}\n\n/* ---------------------------------------------------------------- GitHub OAuth device flow */\n\n/** POST /sync/github/start 响应:UI 展示用(device_code 只存宿主,绝不回传) */\nexport interface GithubDeviceFlowStartResponse {\n /** 随机 flowId:后续 poll/cancel 凭它引用宿主侧登记的 device_code */\n flowId: string;\n /** 一次性用户码(用户在 GitHub 授权页输入) */\n userCode: string;\n /** GitHub 授权页 URL(用户浏览器打开) */\n verificationUri: string;\n /** 设备码过期秒数 */\n expiresIn: number;\n /** GitHub 建议轮询间隔秒数 */\n interval: number;\n}\n\n/** POST /sync/github/poll 响应状态 */\nexport type GithubPollStatus = 'pending' | 'success' | 'denied' | 'expired' | 'error';\n\n/** POST /sync/github/poll 响应:成功时 token 已由 Host 写入 DSH credentials(值永不回传) */\nexport interface GithubPollResponse {\n status: GithubPollStatus;\n /** pending:下次轮询前应等待的毫秒数 */\n pollDelayMs?: number;\n /** 终止态错误码(GitHub error code) */\n errorCode?: string;\n /** 终止态可展示消息(来自 GitHub error_description / 宿主文案,不含秘密) */\n message?: string;\n /** success 时恒 true(凭据已配置);便于 UI 直接刷新状态 */\n credentialConfigured?: boolean;\n}\n\n/** 同步请求超时(ms):与 Host 半 ROUTE_TIMEOUT_MS 对齐(git 网络操作可能较慢) */\nconst SYNC_TIMEOUT_MS = 5 * 60 * 1000;\n\n/** 解析 JSON 响应;非 2xx 时抛出带路由 error 消息的 ConfigManagerApiError(与 api.ts 同款) */\nasync function readJson<T>(response: Response, t: UiT): Promise<T> {\n const notMountedMessage = t('error.notMounted');\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n if (response.status === 404) throw new ConfigManagerApiError(notMountedMessage);\n throw new ConfigManagerApiError(t('error.httpInvalidJson', { status: String(response.status) }));\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 : response.status === 404\n ? notMountedMessage\n : `HTTP ${response.status}`;\n throw new ConfigManagerApiError(message);\n }\n return body as T;\n}\n\n/** POST JSON 请求(带超时:宿主卡死时 UI 拿到明确错误而不是永远转圈) */\nasync function postJson<T>(path: string, body: unknown, t: UiT): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), SYNC_TIMEOUT_MS);\n try {\n const response = await fetch(path, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n return await readJson<T>(response, t);\n } catch (err) {\n if (controller.signal.aborted) {\n throw new ConfigManagerApiError(\n t('error.syncTimeout', { minutes: String(Math.round(SYNC_TIMEOUT_MS / 60000)) }),\n );\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** 远程同步浏览器半数据入口(备份与迁移页第 4 个 tab 的注入业务面) */\nexport class SyncApi {\n readonly t: UiT\n constructor(t: UiT = zhUiT) {\n this.t = t\n }\n\n /** 读取同步状态(配置 / 凭据 / 上次同步时间 / 分区数) */\n async status(): Promise<SyncStatusResponse> {\n const response = await fetch(SYNC_API.status);\n return readJson<SyncStatusResponse>(response, this.t);\n }\n\n /** 推送:导出 portable 分区 → 提交到私有 Git 仓库 → 更新 sync-state */\n async push(payload: SyncPushPayload): Promise<SyncPushReport> {\n return postJson<SyncPushReport>(SYNC_API.push, payload, this.t);\n }\n\n /** 拉取差异预览:拉取远端最新快照 → 只读分析(绝不执行导入) */\n async pull(payload: SyncPullPayload): Promise<SyncPullReport> {\n return postJson<SyncPullReport>(SYNC_API.pull, payload, this.t);\n }\n\n /** GitHub OAuth device flow:发起登录,返回一次性用户码 + 授权页 URL + flowId */\n async githubStart(): Promise<GithubDeviceFlowStartResponse> {\n return postJson<GithubDeviceFlowStartResponse>(SYNC_API.githubStart, {}, this.t);\n }\n\n /** GitHub OAuth device flow:凭 flowId 轮询授权结果(成功时 token 已由 Host 写入 credentials) */\n async githubPoll(flowId: string): Promise<GithubPollResponse> {\n return postJson<GithubPollResponse>(SYNC_API.githubPoll, { flowId }, this.t);\n }\n\n /** GitHub OAuth device flow:取消(丢弃宿主侧登记,零副作用) */\n async githubCancel(flowId: string): Promise<{ ok: boolean }> {\n return postJson<{ ok: boolean }>(SYNC_API.githubCancel, { flowId }, this.t);\n }\n\n /** 同步历史:列出本地祖先快照 + 自动同步执行记录(按 createdAt 倒序合并)。 */\n async history(): Promise<SyncHistoryResponse> {\n const response = await fetch(SYNC_API.history);\n return readJson<SyncHistoryResponse>(response, this.t);\n }\n\n /** 远端历史快照列表(供「选择历史快照」下拉)。 */\n async snapshotsList(payload: SyncPushPayload): Promise<SyncSnapshotsListResponse> {\n return postJson<SyncSnapshotsListResponse>(SYNC_API.snapshotsList, payload, this.t);\n }\n\n /** 一键同步第一步:拉取 → 差异确认会话(items 逐项确认,暂不导入)。 */\n async sync(payload: SyncStartPayload): Promise<SyncStartResponse> {\n return postJson<SyncStartResponse>(SYNC_API.sync, payload, this.t);\n }\n\n /** 一键同步第二步:按用户对差异项的逐项决策执行导入。 */\n async applyItems(payload: ApplyItemsPayload): Promise<ApplyItemsResponse> {\n return postJson<ApplyItemsResponse>(SYNC_API.applyItems, payload, this.t);\n }\n\n /** 取消/清理差异确认会话(丢弃临时 ZIP,零副作用)。 */\n async cancel(syncSessionId: string): Promise<{ ok: boolean }> {\n return postJson<{ ok: boolean }>(SYNC_API.cancel, { syncSessionId }, this.t);\n }\n\n /** 自动同步状态(GET /sync/autosync)。 */\n async autosyncStatus(): Promise<AutosyncStatusResponse> {\n const response = await fetch(SYNC_API.autosync);\n return readJson<AutosyncStatusResponse>(response, this.t);\n }\n\n /** 自动同步配置更新(POST /sync/autosync)。 */\n async autosyncUpdate(payload: AutosyncUpdatePayload): Promise<AutosyncStatusResponse> {\n return postJson<AutosyncStatusResponse>(SYNC_API.autosync, payload, this.t);\n }\n\n /** 一键回滚:按 restoreId 调用 backup→rollback */\n async rollback(payload: { restoreId: string }): Promise<{ ok: boolean; full: boolean }> {\n return postJson<{ ok: boolean; full: boolean }>(SYNC_API.rollback, payload, this.t);\n }\n}\n","/**\n * 远程同步区块的纯渲染模型(m-sync-ui)。\n *\n * 与 src/ui/progress.ts → progress-view.ts 同模式:把「报告怎么渲染 / 按钮什么状态 /\n * 状态行写什么 / 私有仓库提示怎么展示」做成无副作用纯函数,node --test 直接测,\n * React 组件只做装配。文案直接用中文(项目源语言),组件不重复造。\n */\nimport type { PlanItem, PlanItemKind } from '../../core/types.ts';\nimport type { PullChange, SyncPullReport, SyncPushReport } from '../../sync/sync-engine.ts';\nimport type {\n ApplyItemsResponse, AutosyncInterval, AutosyncStatusResponse, GithubPollResponse, SyncConfirmItem,\n SyncItemAdoption, SyncStatusResponse,\n} from './sync-api.ts';\nimport { zhUiT, type UiT } from '../../ui/i18n.ts';\n\n/* ---------------------------------------------------------------- 私有仓库提示 */\n\n/**\n * 私有仓库强制提示文案(Settings 区块常驻警示横幅)。\n * 安全约束:同步内容为可移植配置,public 仓库会公开配置 → 必须私有;\n * token 仅用于认证,绝不写入同步文件/提交内容/日志。\n */\nexport function privateRepoHint(t: UiT = zhUiT): string {\n return t('sync.privateRepoHint');\n}\n\n/* ---------------------------------------------------------------- 变更摘要 */\n\n/** 需要人工决策的 PlanItem 类型(与 SyncEngine.pull 的 needsReview 判定一致) */\nconst REVIEW_KINDS: ReadonlySet<PlanItemKind> = new Set([\n 'Conflict', 'MissingSecret', 'MissingDependency', 'Install', 'Error',\n]);\n\nexport interface PullChangeSummary {\n total: number;\n info: number;\n warning: number;\n error: number;\n /** 是否包含需要人工决策的项(冲突/密钥/依赖/安装/错误) */\n needsReview: boolean;\n items: PullChange[];\n}\n\n/** 差异摘要:按 severity 计数 + 需人工决策标记(UI 统计徽章与警示横幅的数据源) */\nexport function summarizePullChanges(changes: readonly PullChange[]): PullChangeSummary {\n let info = 0;\n let warning = 0;\n let error = 0;\n let needsReview = false;\n for (const c of changes) {\n if (c.severity === 'error') error += 1;\n else if (c.severity === 'warning') warning += 1;\n else info += 1;\n if (REVIEW_KINDS.has(c.kind)) needsReview = true;\n }\n return { total: changes.length, info, warning, error, needsReview, items: [...changes] };\n}\n\n/** PlanItemKind → 短标签(列表徽章) */\nexport function kindLabel(kind: PlanItemKind, t: UiT = zhUiT): string {\n switch (kind) {\n case 'Create': return t('sync.kind.create');\n case 'Update': return t('sync.kind.update');\n case 'Skip': return t('sync.kind.skip');\n case 'Conflict': return t('sync.kind.conflict');\n case 'Install': return t('sync.kind.install');\n case 'MissingSecret': return t('sync.kind.missingSecret');\n case 'MissingDependency': return t('sync.kind.missingDependency');\n case 'PathMapping': return t('sync.kind.pathMapping');\n case 'Warning': return t('sync.kind.warning');\n case 'Error': return t('sync.kind.error');\n default: return kind;\n }\n}\n\n/** severity → 短标签 */\nexport function severityLabel(severity: PlanItem['severity'], t: UiT = zhUiT): string {\n switch (severity) {\n case 'error': return t('sync.severity.error');\n case 'warning': return t('sync.severity.warning');\n default: return t('sync.severity.info');\n }\n}\n\n/* ---------------------------------------------------------------- 按钮状态 */\n\nexport interface SyncButtons {\n canPush: boolean;\n canPull: boolean;\n pushLabel: string;\n pullLabel: string;\n}\n\n/**\n * 按钮可用性与文案:\n * - 任一操作进行中(busy)→ 两个按钮都禁用(防并发 push/pull);\n * - 仓库地址为空 → 禁用(无仓库无从同步);\n * - busy 时按钮文案切换为「正在推送/拉取…」(配 Spinner)。\n */\nexport function computeSyncButtons(busy: 'sync' | 'push' | 'pull' | 'apply' | 'rollback' | null, repoUrl: string, t: UiT = zhUiT): SyncButtons {\n const idle = busy === null;\n const repoOk = repoUrl.trim() !== '';\n const enabled = idle && repoOk;\n return {\n canPush: enabled,\n canPull: enabled,\n pushLabel: busy === 'push' ? t('sync.pushing') : busy === 'sync' ? t('sync.syncing') : t('sync.pushLabel'),\n pullLabel: busy === 'pull' ? t('sync.pulling') : busy === 'sync' ? t('sync.syncing') : t('sync.pullLabel'),\n };\n}\n\n/* ---------------------------------------------------------------- 状态行 */\n\nexport type SyncStatusKind = 'loading' | 'unconfigured' | 'ready' | 'error';\n\nexport interface SyncStatusSummary {\n kind: SyncStatusKind;\n text: string;\n}\n\n/** 状态行渲染模型:加载 / 未配置 / 就绪(凭据 + 上次同步 + 通道)/ 错误 */\nexport function computeSyncStatus(\n statusInfo: SyncStatusResponse | null,\n loading: boolean,\n error: string | null,\n t: UiT = zhUiT,\n): SyncStatusSummary {\n if (loading) return { kind: 'loading', text: t('sync.statusLoading') };\n if (error !== null) return { kind: 'error', text: error };\n if (statusInfo === null || !statusInfo.configured) {\n return { kind: 'unconfigured', text: t('sync.statusUnconfigured') };\n }\n const cred = statusInfo.credentialConfigured\n ? t('sync.credConfigured')\n : t('sync.credMissing');\n const last =\n statusInfo.lastSyncAt !== undefined && statusInfo.lastSyncAt !== ''\n ? t('sync.lastSync', { time: formatDateTime(statusInfo.lastSyncAt) })\n : t('sync.neverSynced');\n const transport =\n statusInfo.transport !== undefined\n ? ` · ${statusInfo.transport.type}${statusInfo.transport.ref !== '' ? `/${statusInfo.transport.ref}` : ''}`\n : '';\n return { kind: 'ready', text: `${cred} · ${last}${transport}` };\n}\n\n/** ISO-8601 → 本地可读时间(YYYY-MM-DD HH:mm;非法输入原样返回) */\nexport function formatDateTime(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n const pad = (n: number): string => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\n/** 上次同步时间的展示文本('' / undefined = 从未同步) */\nexport function formatLastSync(iso: string | undefined, t: UiT = zhUiT): string {\n if (iso === undefined || iso === '') return t('sync.neverSyncedShort');\n return formatDateTime(iso);\n}\n\n/* ---------------------------------------------------------------- 报告渲染模型 */\n\nexport interface PushReportView {\n kind: 'ok' | 'error';\n headline: string;\n sections: string[];\n warnings: string[];\n}\n\n/** push 报告 → 渲染模型(ok 头部带快照 id;失败显示引擎 message;分区与告警透传) */\nexport function pushReportView(report: SyncPushReport | null, t: UiT = zhUiT): PushReportView | null {\n if (report === null) return null;\n if (!report.ok) {\n return { kind: 'error', headline: report.message ?? t('sync.pushFailed'), sections: report.sections, warnings: report.warnings };\n }\n return {\n kind: 'ok',\n headline: t('sync.pushOk', { id: report.snapshotId }),\n sections: report.sections,\n warnings: report.warnings,\n };\n}\n\nexport interface PullReportView {\n kind: 'ok' | 'empty' | 'error';\n headline: string;\n summary: PullChangeSummary | null;\n /** 只读预览提示(ok 时非空:明确「预览不执行导入」) */\n previewHint: string;\n}\n\n/** pull 报告 → 渲染模型(差异预览;empty = 无变更;error = 拉取失败) */\nexport function pullReportView(report: SyncPullReport | null, t: UiT = zhUiT): PullReportView | null {\n if (report === null) return null;\n if (!report.ok) {\n return { kind: 'error', headline: report.message ?? t('sync.pullFailed'), summary: null, previewHint: '' };\n }\n if (report.changes.length === 0) {\n return { kind: 'empty', headline: report.message ?? t('sync.pullEmpty'), summary: null, previewHint: '' };\n }\n return {\n kind: 'ok',\n headline: t('sync.pullOk', { id: report.snapshotId, count: String(report.changes.length) }),\n summary: summarizePullChanges(report.changes),\n previewHint: t('sync.previewHint'),\n };\n}\n\n/* ---------------------------------------------------------------- GitHub 登录视图模型 */\n\nexport type GithubLoginPhase = 'idle' | 'starting' | 'waiting' | 'polling' | 'success' | 'error';\n\nexport interface GithubLoginView {\n phase: GithubLoginPhase;\n /** 一次性用户码(waiting/polling 展示,用户到 GitHub 授权页输入) */\n userCode: string;\n /** GitHub 授权页 URL */\n verificationUri: string;\n /** 状态行文案(中文,项目源语言;与 computeSyncStatus 同策略,不依赖 locale 注入) */\n statusText: string;\n /** 主按钮文案:发起 / 重新登录 */\n startLabel: string;\n /** 是否可发起/重试登录 */\n canStart: boolean;\n /** 流程进行中是否展示「取消」按钮 */\n canCancel: boolean;\n /** 是否展示设备码 + 授权链接区块 */\n showCode: boolean;\n /** 错误消息(phase=error;来自轮询终止态或请求失败) */\n error: string | null;\n}\n\n/**\n * GitHub 登录区块渲染模型(纯函数,node 可测):\n * - idle → 可发起;starting → 请求设备码中;waiting → 展示设备码等待用户在浏览器授权;\n * - polling → 轮询 GitHub 中(仍展示代码区块);success → 完成;error → 可重试。\n */\nexport function computeGithubLoginView(\n phase: GithubLoginPhase,\n userCode: string,\n verificationUri: string,\n error: string | null,\n t: UiT = zhUiT,\n): GithubLoginView {\n const inFlight = phase === 'starting' || phase === 'waiting' || phase === 'polling';\n let statusText: string;\n switch (phase) {\n case 'starting':\n statusText = t('sync.github.starting');\n break;\n case 'waiting':\n statusText = userCode === ''\n ? t('sync.github.waitingNoCode')\n : t('sync.github.waiting', { code: userCode });\n break;\n case 'polling':\n statusText = t('sync.github.polling');\n break;\n case 'success':\n statusText = t('sync.github.success');\n break;\n case 'error':\n statusText = error ?? t('sync.github.failed');\n break;\n default:\n statusText = t('sync.github.defaultStatus');\n }\n return {\n phase,\n userCode,\n verificationUri,\n statusText,\n startLabel: phase === 'error' ? t('sync.github.relogin') : t('sync.github.login'),\n canStart: phase === 'idle' || phase === 'error',\n canCancel: inFlight,\n showCode: phase === 'waiting' || phase === 'polling',\n error,\n };\n}\n\n/** 轮询终止态 → 用户可读消息(pending 不是终止态,返回空串;成功/拒绝/过期/错误给出明确文案) */\nexport function githubPollMessage(poll: GithubPollResponse, t: UiT = zhUiT): string {\n switch (poll.status) {\n case 'success':\n return t('sync.github.pollSuccess');\n case 'denied':\n return t('sync.github.pollDenied');\n case 'expired':\n return t('sync.github.pollExpired');\n case 'error':\n return t('sync.github.pollError', { detail: poll.message ?? poll.errorCode ?? t('sync.github.unknownError') });\n default:\n return '';\n }\n}\n\n/* ---------------------------------------------------------------- 一键同步差异确认(方案 A) */\n\n/** 需要人工决策的 PlanItemKind(与 Host /sync/sync 的 needsReview 判定对齐)。 */\nconst CONFIRM_REVIEW_KINDS: ReadonlySet<PlanItemKind> = new Set([\n 'Conflict', 'MissingSecret', 'MissingDependency', 'Install', 'Error', 'PathMapping',\n]);\n\nexport interface SyncConfirmSummary {\n total: number;\n info: number;\n warning: number;\n error: number;\n /** 默认/当前采用数(adopt=true 的项数)。 */\n adopted: number;\n /** 是否包含任何需人工决策项。 */\n needsReview: boolean;\n}\n\n/** 差异确认列表摘要(按 severity 计数 + 采用数 + needsReview 徽章数据源)。 */\nexport function summarizeConfirmItems(items: readonly SyncConfirmItem[]): SyncConfirmSummary {\n let info = 0;\n let warning = 0;\n let error = 0;\n let adopted = 0;\n let needsReview = false;\n for (const it of items) {\n if (it.severity === 'error') error += 1;\n else if (it.severity === 'warning') warning += 1;\n else info += 1;\n if (it.adopt) adopted += 1;\n if (CONFIRM_REVIEW_KINDS.has(it.kind)) needsReview = true;\n }\n return { total: items.length, info, warning, error, adopted, needsReview };\n}\n\n/**\n * 收集用户逐项决策 → apply-items 请求体 adoptions[]。\n * 仅包含 adopt=true 的项;Conflict 项 adopt=true 且未给 resolution → 抛错(强制先解决)。\n */\nexport function buildAdoptions(\n items: readonly SyncConfirmItem[],\n adopted: ReadonlyMap<string, boolean>,\n resolutions: ReadonlyMap<string, 'useRemote' | 'keepLocal' | 'skip'>,\n): SyncItemAdoption[] {\n const out: SyncItemAdoption[] = [];\n for (const it of items) {\n if (adopted.get(it.itemId) !== true) continue; // adopt=false / 未列出 → 跳过\n const adoption: SyncItemAdoption = { itemId: it.itemId, adopt: true };\n if (it.kind === 'Conflict') {\n const resolution = resolutions.get(it.itemId);\n if (resolution === undefined) {\n throw new Error(`冲突项 ${it.itemId} 必须先选择解决方式(用本地 / 用远端 / 跳过)`);\n }\n if (resolution !== 'skip') adoption.resolution = resolution;\n }\n out.push(adoption);\n }\n return out;\n}\n\nexport type ApplyItemsViewKind = 'ok' | 'failed' | 'rolledBack';\n\nexport interface ApplyItemsView {\n kind: ApplyItemsViewKind;\n headline: string;\n sections: string[];\n warnings: string[];\n restoreId: string;\n needsRestart: boolean;\n}\n\n/** apply-items 执行结果 → 渲染模型(ok / failed / 整体回滚)。 */\nexport function applyItemsReportView(\n report: ApplyItemsResponse | null,\n t: UiT = zhUiT,\n): ApplyItemsView | null {\n if (report === null) return null;\n const failedOnly = report.failed.length > 0 && !report.ok;\n const kind: ApplyItemsViewKind = !report.ok && report.rolledBack ? 'rolledBack' : failedOnly ? 'failed' : 'ok';\n const headline = kind === 'ok'\n ? t('sync.importDone', { n: String(report.applied.length) })\n : kind === 'rolledBack'\n ? t('sync.importFailed')\n : t('sync.importFailed');\n return {\n kind,\n headline,\n sections: report.applied,\n warnings: report.warnings,\n restoreId: report.restoreId,\n needsRestart: report.needsRestart,\n };\n}\n\n/* ---------------------------------------------------------------- 自动同步(方案 A) */\n\n/** AutosyncInterval → ms。 */\nexport function autosyncIntervalMs(interval: AutosyncInterval): number {\n switch (interval) {\n case '5m': return 5 * 60 * 1000;\n case '15m': return 15 * 60 * 1000;\n case '60m': return 60 * 60 * 1000;\n case '6h': return 6 * 60 * 60 * 1000;\n case '12h': return 12 * 60 * 60 * 1000;\n case '24h': return 24 * 60 * 60 * 1000;\n default: return 30 * 60 * 1000;\n }\n}\n\n/** 距下次自动同步剩余 ms(已到期 → 0)。elapsedMs 为 host 计算的「距上次执行已过 ms」。 */\nexport function computeAutosyncCountdown(elapsedMs: number, intervalMs: number): number {\n if (elapsedMs < 0) return -1; // 从未运行\n return Math.max(0, intervalMs - elapsedMs);\n}\n\n/** 间隔 ms → 可读时长(如「30 分钟」「6 小时」)。 */\nexport function formatIntervalDuration(ms: number, t: UiT = zhUiT): string {\n const minutes = Math.round(ms / 60000);\n if (minutes < 60) return t('sync.interval.30m');\n const hours = Math.round(minutes / 60);\n if (hours === 6) return t('sync.interval.6h');\n if (hours === 12) return t('sync.interval.12h');\n if (hours === 24) return t('sync.interval.24h');\n return `${hours}h`;\n}\n\n/** 自动同步状态行的可读文案(未运行 / 上次状态 / 连续失败计数)。 */\nexport function autosyncStatusText(status: AutosyncStatusResponse, t: UiT = zhUiT): string {\n if (status.lastRunAt === undefined || status.lastRunAt === '' || status.lastRunStatus === undefined) {\n return t('sync.autosyncNever');\n }\n const statusText = status.lastRunStatus === 'success'\n ? t('sync.autosyncSuccess')\n : status.lastRunStatus === 'skipped'\n ? t('sync.autosyncSkipped')\n : status.lastRunStatus === 'partial'\n ? t('sync.autosyncPartial')\n : t('sync.autosyncFailed');\n const time = formatDateTime(status.lastRunAt);\n const base = t('sync.autosyncLastRun', { time });\n const fail = status.consecutiveFailures > 0 ? ` · ${t('sync.autosyncFailCount', { n: String(status.consecutiveFailures) })}` : '';\n return `${statusText} · ${base}${fail}`;\n}\n","/**\n * m-sync-ui (P2b):SyncHistoryView 的纯函数投影。\n *\n * 现状:本地祖先快照目录(manifest.json)→ SnapshotHistoryEntry;倒序排序 + ISO 格式化。\n * 方案 A 扩展:/sync/history 现返回 { entries: SyncHistoryEntry[] }(快照 kind=apply\n * + 自动同步 kind=autosync),投影需统一处理两源,并生成自动同步跳过冲突的可读明细。\n */\nimport type { AutosyncHistoryEntry, SyncHistoryEntry } from './sync-api.ts';\n\n/** 兼容旧快照条目(manifest.json 投影)。 */\nexport interface SnapshotHistoryEntry {\n id: string;\n createdAt: string;\n /** 分区数(manifest.sectionHashes 的 key 数) */\n sectionCount: number;\n /** 关联到该快照的待审项数(来自 sync-review-queue.json 中的 items) */\n reviewCount: number;\n}\n\n/** 把快照 entries 排序(createdAt 倒序)并组装展示字段。 */\nexport function projectHistoryRows(entries: readonly SnapshotHistoryEntry[]): SnapshotHistoryEntry[] {\n return [...entries].sort(byCreatedAtDesc);\n}\n\n/** 统一历史条目(快照 + 自动同步)按 createdAt 倒序排序。 */\nexport function projectSyncHistoryEntries(entries: readonly SyncHistoryEntry[]): SyncHistoryEntry[] {\n return [...entries].sort(byCreatedAtDesc);\n}\n\nfunction byCreatedAtDesc(a: { createdAt: string }, b: { createdAt: string }): number {\n return a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0;\n}\n\n/** ISO 时间 → 本地可读字符串(短格式) */\nexport function formatDateTime(iso: string): string {\n if (!iso) return '—';\n const d = new Date(iso);\n if (isNaN(d.getTime())) return iso;\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\n/* ---------------------------------------------------------------- 自动同步记录投影 */\n\n/** 自动同步执行记录的方向可读标签。 */\nexport function directionLabel(direction: AutosyncHistoryEntry['direction']): string {\n switch (direction) {\n case 'pull': return '下载';\n case 'push': return '上传';\n default: return '双向';\n }\n}\n\n/** 自动同步执行状态可读标签。 */\nexport function autosyncStatusLabel(status: AutosyncHistoryEntry['status']): string {\n switch (status) {\n case 'success': return '成功';\n case 'skipped': return '已跳过';\n case 'partial': return '部分成功';\n default: return '失败';\n }\n}\n\n/** 跳过原因 → 可读描述(host 透传语义;未知原因回退原串)。 */\nexport function describeSkipReason(reason: string | undefined): string {\n switch (reason) {\n case 'conflict': return '冲突项被跳过';\n case 'no-remote': return '远端无快照';\n case 'not-configured': return '未配置仓库';\n case 'network': return '网络问题';\n default: return reason ?? '未知';\n }\n}\n\n/** 把一条自动同步记录投影为展示行(摘要文本 + 可展开的被跳过冲突分区明细)。 */\nexport interface AutosyncHistoryRow {\n id: string;\n createdAt: string;\n direction: string;\n status: string;\n /** 摘要行文本(如「下载 · 已跳过 · 冲突项被跳过」)。 */\n summary: string;\n /** 被跳过的冲突分区 id(展开明细用);无则 undefined。 */\n conflictedSections?: string[];\n /** 实际应用的分区 id。 */\n appliedSections?: string[];\n error?: string;\n notifiedAt?: string;\n /** 是否有关联的跳过分区明细可展开。 */\n hasDetail: boolean;\n}\n\n/** 自动同步记录 → 展示行投影。 */\nexport function projectAutosyncEntry(entry: AutosyncHistoryEntry): AutosyncHistoryRow {\n const parts: string[] = [directionLabel(entry.direction), autosyncStatusLabel(entry.status)];\n if (entry.skipReason !== undefined) parts.push(describeSkipReason(entry.skipReason));\n return {\n id: entry.createdAt,\n createdAt: entry.createdAt,\n direction: directionLabel(entry.direction),\n status: autosyncStatusLabel(entry.status),\n summary: parts.join(' · '),\n conflictedSections: entry.conflictedSections,\n appliedSections: entry.appliedSections,\n error: entry.error,\n notifiedAt: entry.notifiedAt,\n hasDetail:\n (entry.conflictedSections !== undefined && entry.conflictedSections.length > 0) ||\n (entry.appliedSections !== undefined && entry.appliedSections.length > 0) ||\n entry.error !== undefined,\n };\n}\n","/**\n * 同步历史视图(方案 A):列出本地祖先快照目录(kind=apply)+ 自动同步执行记录\n * (kind=autosync)。自动同步行显示时间/方向/状态/跳过冲突/应用分区,点开可看被跳过\n * 冲突分区明细。\n *\n * 数据获取:GET /sync/history → { entries: SyncHistoryEntry[] }(按 createdAt 倒序合并)。\n * 纯函数投影在 ./history-model.ts(node --test 可测),本组件只做装配。\n */\nimport { useEffect, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\n\nimport { Badge, Card, SectionTitle, Spinner } from '../common/ui.tsx'\nimport type { SyncApi, SyncHistoryEntry, AutosyncHistoryEntry } from './sync-api.ts'\nimport {\n describeSkipReason, directionLabel, formatDateTime, projectAutosyncEntry,\n projectSyncHistoryEntries,\n} from './history-model.ts'\nimport type { SnapshotHistoryEntry } from './history-model.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport css from '../config-manager.module.css'\n\nexport interface SyncHistoryViewProps {\n api: SyncApi\n t: TranslateNS<'config-manager-sync'>\n}\n\nexport function SyncHistoryView(props: SyncHistoryViewProps): ReactNode {\n const { api, t } = props;\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [entries, setEntries] = useState<SyncHistoryEntry[]>([]);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const data = await api.history();\n if (!cancelled) {\n setEntries(data.entries);\n setLoading(false);\n }\n } catch (err) {\n if (!cancelled) {\n setError(err instanceof Error ? err.message : String(err));\n setLoading(false);\n }\n }\n })();\n return () => { cancelled = true; };\n }, [api]);\n\n const rows = useMemo(() => projectSyncHistoryEntries(entries), [entries]);\n // 快照类条目(兼容旧投影;仅统计展示)\n const snapshotRows = useMemo<SnapshotHistoryEntry[]>(\n () => rows\n .filter((r) => r.kind === 'apply' || r.kind === 'push' || r.kind === 'pull' || r.kind === 'rollback')\n .map((r) => ({\n id: r.id,\n createdAt: r.createdAt,\n sectionCount: r.sectionCount ?? 0,\n reviewCount: r.reviewCount ?? 0,\n })),\n [rows],\n );\n\n if (loading) return <Spinner label={t('common.loading')} />;\n if (error) return <Card><span className=\"error\">{error}</span></Card>;\n if (rows.length === 0) {\n return (\n <Card>\n <strong>{t('history.empty')}</strong>\n <p>{t('history.emptyHint')}</p>\n </Card>\n );\n }\n\n return (\n <Card>\n <SectionTitle title={`${t('history.title')}(${rows.length})`} />\n <table className=\"sync-history-table\">\n <thead>\n <tr><th>{t('history.colTime')}</th><th>{t('history.colKind')}</th><th>{t('history.colDetail')}</th></tr>\n </thead>\n <tbody>\n {rows.map((r) => {\n if (r.kind === 'autosync' && r.autosync !== undefined) {\n return <AutosyncRow key={r.id} entry={r.autosync} t={t} />;\n }\n const snap = snapshotRows.find((s) => s.id === r.id);\n return (\n <tr key={r.id}>\n <td>{formatDateTime(r.createdAt)}</td>\n <td><Badge kind=\"info\">{t('history.kindSnapshot')}</Badge></td>\n <td>\n <code>{r.id}</code>\n {snap !== undefined && <> · {snap.sectionCount} {t('history.sectionCount')}</>}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </Card>\n );\n}\n\n/* ---------------------------------------------------------------- 自动同步行 */\n\ninterface AutosyncRowProps {\n entry: AutosyncHistoryEntry\n t: TranslateNS<'config-manager-sync'>\n}\n\nfunction AutosyncRow({ entry, t }: AutosyncRowProps): ReactNode {\n const row = projectAutosyncEntry(entry);\n return (\n <tr>\n <td>{formatDateTime(row.createdAt)}</td>\n <td><Badge kind=\"info\">{t('history.kindAutosync')}</Badge></td>\n <td>\n <div>\n {row.summary}\n {entry.pushedSnapshotId !== undefined && <> · {t('history.autosyncPush')} {entry.pushedSnapshotId}</>}\n {entry.pulledSnapshotId !== undefined && <> · {t('history.autosyncPull')} {entry.pulledSnapshotId}</>}\n </div>\n {row.hasDetail && (\n <details>\n <summary>{t('history.detail')}</summary>\n <div className={css.reportList}>\n {row.conflictedSections !== undefined && row.conflictedSections.length > 0 && (\n <div>\n <span className={css.fieldLabel}>{t('history.autosyncConflicted', { sections: '' })}</span>\n <div className={css.statRow}>\n {row.conflictedSections.map((sid) => <Badge key={sid} kind=\"warn\">{sid}</Badge>)}\n </div>\n </div>\n )}\n {row.appliedSections !== undefined && row.appliedSections.length > 0 && (\n <div>\n <span className={css.fieldLabel}>{t('history.autosyncApplied', { sections: '' })}</span>\n <div className={css.statRow}>\n {row.appliedSections.map((sid) => <Badge key={sid} kind=\"ok\">{sid}</Badge>)}\n </div>\n </div>\n )}\n {row.error !== undefined && (\n <div><span className={css.fieldLabel}>{t('history.autosyncError', { error: '' })}</span>{row.error}</div>\n )}\n </div>\n </details>\n )}\n </td>\n </tr>\n );\n}\n","/**\n * 一键同步差异确认视图(方案 A §5 差异确认数据流)。\n *\n * 消费 POST /sync/sync 返回的 items[],渲染逐项确认列表:\n * - 每项:kindTag + description + severity + 「采用远端」复选框(默认勾选,可取消);\n * - Conflict 项:内联弹窗(用本地 / 用远端 / 跳过);\n * - 底部:「确认导入」(apply-items)+「取消」(cancel)。\n *\n * 全部渲染模型来自 ./sync-view.ts 纯函数(node 单测覆盖),组件只做装配 + 交互状态。\n */\nimport { useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\n\nimport { Badge, Banner, Button, Card, Spinner } from '../common/ui.tsx'\nimport type { SyncApi, SyncConfirmItem } from './sync-api.ts'\nimport { kindLabel, severityLabel, summarizeConfirmItems } from './sync-view.ts'\nimport type { ApplyItemsResponse } from './sync-api.ts'\nimport type { TranslateNS } from '../client-types.ts'\nimport css from '../config-manager.module.css'\n\nexport interface SyncConfirmViewProps {\n api: SyncApi\n /** 差异确认会话 id(apply-items / cancel 引用)。 */\n syncSessionId: string\n /** 被拉取的远端快照 id。 */\n snapshotId: string\n items: SyncConfirmItem[]\n needsReview: boolean\n /** 兼容性评级(可选展示)。 */\n compatibility?: 'excellent' | 'good' | 'partial' | 'unsupported'\n /** 翻译器。 */\n t: TranslateNS<'config-manager-sync'>\n /** 用户取消确认后回调(复位到空闲态)。 */\n onCancel: () => void\n /** 回滚成功后回调(清空 lastRestoreId)。 */\n onRollbackDone?: () => void\n}\n\ntype ConflictResolution = 'useRemote' | 'keepLocal' | 'skip'\n\n/** 单条差异项的可变决策状态。 */\ninterface ItemState {\n adopted: boolean\n resolution?: ConflictResolution\n}\n\nexport function SyncConfirmView(props: SyncConfirmViewProps): ReactNode {\n const { api, syncSessionId, snapshotId, items, needsReview, compatibility, t, onCancel, onRollbackDone } = props;\n // 逐项决策状态(初始 = defaultAdopt)\n const [states, setStates] = useState<Record<string, ItemState>>(() => {\n const init: Record<string, ItemState> = {};\n for (const it of items) init[it.itemId] = { adopted: it.defaultAdopt, resolution: undefined };\n return init;\n });\n // 执行阶段:'idle' | 'applying' | 'done' | 'failed' | 'cancelling'\n const [phase, setPhase] = useState<'idle' | 'applying' | 'done' | 'failed' | 'cancelling'>('idle');\n const [applyResult, setApplyResult] = useState<ApplyItemsResponse | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const summary = useMemo(() => summarizeConfirmItems(\n items.map((it) => ({ ...it, adopt: states[it.itemId]?.adopted ?? it.defaultAdopt })),\n ), [items, states]);\n\n const setAdopted = (itemId: string, adopted: boolean): void => {\n setStates((prev) => ({ ...prev, [itemId]: { ...prev[itemId], adopted } }));\n };\n\n const setResolution = (itemId: string, resolution: ConflictResolution): void => {\n setStates((prev) => {\n const existing: ItemState = prev[itemId] ?? { adopted: false, resolution: undefined };\n return { ...prev, [itemId]: { ...existing, resolution } };\n });\n };\n\n const runApply = async (): Promise<void> => {\n // 校验冲突项必须已解决\n const unresolved = items.find(\n (it) => it.kind === 'Conflict' && (states[it.itemId]?.adopted === true) && states[it.itemId]?.resolution === undefined,\n );\n if (unresolved !== undefined) {\n setError(t('syncflow.conflictUnresolved', { itemId: unresolved.itemId }));\n return;\n }\n setPhase('applying');\n setError(null);\n try {\n const adoptedMap = new Map<string, boolean>();\n for (const it of items) {\n adoptedMap.set(it.itemId, states[it.itemId]?.adopted ?? false);\n }\n const adoptions = items\n .filter((it) => adoptedMap.get(it.itemId) === true)\n .map((it) => {\n const adoption: { itemId: string; adopt: boolean; resolution?: ConflictResolution } = { itemId: it.itemId, adopt: true };\n const res = states[it.itemId]?.resolution;\n if (it.kind === 'Conflict' && res !== undefined && res !== 'skip') adoption.resolution = res;\n return adoption;\n });\n const result = await api.applyItems({ syncSessionId, adoptions });\n setPhase(result.ok ? 'done' : 'failed');\n setApplyResult(result);\n } catch (err) {\n setPhase('failed');\n setError(err instanceof Error ? err.message : String(err));\n }\n };\n\n const runCancel = async (): Promise<void> => {\n setPhase('cancelling');\n setError(null);\n try {\n await api.cancel(syncSessionId);\n } catch { /* 取消失败无需打扰 */ }\n onCancel();\n };\n\n const runRollback = async (restoreId: string): Promise<void> => {\n setPhase('applying');\n setError(null);\n try {\n await api.rollback({ restoreId });\n setPhase('done');\n setApplyResult(null);\n onRollbackDone?.();\n } catch (err) {\n setPhase('failed');\n setError(err instanceof Error ? err.message : String(err));\n }\n };\n\n const busy = phase === 'applying' || phase === 'cancelling';\n\n if (items.length === 0) {\n return (\n <Card>\n <span className={css.groupLabel}>{t('syncflow.title')}</span>\n <Banner kind=\"ok\">{t('syncflow.empty')}</Banner>\n <div className={css.actionRow}>\n <Button disabled={busy} onClick={() => { void runCancel() }}>\n {t('syncflow.cancel')}\n </Button>\n </div>\n </Card>\n );\n }\n\n return (\n <Card>\n <span className={css.groupLabel}>\n {t('syncflow.title')}\n {compatibility !== undefined && <Badge kind=\"info\">{compatibility}</Badge>}\n </span>\n <Banner kind={needsReview ? 'warn' : 'info'}>\n {needsReview ? t('syncflow.needsReviewBadge') : t('syncflow.diffCount', { count: String(summary.total) })}\n </Banner>\n <div className={css.statRow}>\n <Badge kind=\"info\">{t('syncflow.diffCount', { count: String(summary.total) })}</Badge>\n <Badge kind=\"ok\">{t('syncflow.adoptRemote')} {summary.adopted}</Badge>\n {summary.error > 0 && <Badge kind=\"error\">{severityLabel('error', api.t)} × {summary.error}</Badge>}\n {summary.warning > 0 && <Badge kind=\"warn\">{severityLabel('warning', api.t)} × {summary.warning}</Badge>}\n </div>\n <span className={css.hint}>{t('syncflow.adoptHint')}</span>\n\n {/* 逐项差异列表 */}\n <div className={css.reportList}>\n {items.map((it) => {\n const st = states[it.itemId] ?? { adopted: it.defaultAdopt };\n const isConflict = it.kind === 'Conflict';\n return (\n <div key={it.itemId} className={css.statRow}>\n <label className={css.checkboxRow}>\n <input\n type=\"checkbox\"\n checked={st.adopted}\n disabled={busy}\n onChange={(e) => { setAdopted(it.itemId, e.target.checked) }}\n />\n <span>{kindLabel(it.kind, api.t)}</span>\n </label>\n <Badge kind={it.severity === 'error' ? 'error' : it.severity === 'warning' ? 'warn' : 'info'}>\n {severityLabel(it.severity, api.t)}\n </Badge>\n <span>{it.description}</span>\n {isConflict && (\n <ConflictResolver\n item={it}\n resolution={st.resolution}\n busy={busy}\n t={t}\n onResolve={(r) => { setResolution(it.itemId, r) }}\n />\n )}\n </div>\n );\n })}\n </div>\n\n {error !== null && <Banner kind=\"error\">{error}</Banner>}\n\n {/* 确认导入 / 取消 */}\n {phase === 'idle' && (\n <div className={css.actionRow}>\n <Button variant=\"primary\" disabled={busy || summary.adopted === 0} onClick={() => { void runApply() }}>\n {t('syncflow.confirmImport')}\n </Button>\n <Button disabled={busy} onClick={() => { void runCancel() }}>\n {t('syncflow.cancel')}\n </Button>\n </div>\n )}\n\n {/* 执行结果 */}\n {(phase === 'done' || phase === 'failed') && applyResult !== null && (\n <ApplyResultCard result={applyResult} busy={busy} t={t} onRollback={runRollback} />\n )}\n {(phase === 'done' || phase === 'failed') && applyResult === null && (\n <Banner kind=\"ok\">{t('syncflow.rollbackDone')}</Banner>\n )}\n </Card>\n );\n}\n\n/* ---------------------------------------------------------------- 冲突内联解决 */\n\ninterface ConflictResolverProps {\n item: SyncConfirmItem\n resolution?: ConflictResolution\n busy: boolean\n t: TranslateNS<'config-manager-sync'>\n onResolve: (r: ConflictResolution) => void\n}\n\nfunction ConflictResolver({ item, resolution, busy, t, onResolve }: ConflictResolverProps): ReactNode {\n const conflict = item.conflict;\n return (\n <span className={css.rowActions}>\n <span className={css.fieldLabel}>{t('syncflow.conflictTitle')}</span>\n <Button variant=\"ghost\" disabled={busy || resolution === 'keepLocal'} onClick={() => { onResolve('keepLocal') }}>\n {resolution === 'keepLocal' ? `✓ ${t('syncflow.conflictUseLocal')}` : t('syncflow.conflictUseLocal')}\n </Button>\n <Button variant=\"primary\" disabled={busy || resolution === 'useRemote'} onClick={() => { onResolve('useRemote') }}>\n {resolution === 'useRemote' ? `✓ ${t('syncflow.conflictUseRemote')}` : t('syncflow.conflictUseRemote')}\n </Button>\n <Button variant=\"ghost\" disabled={busy || resolution === 'skip'} onClick={() => { onResolve('skip') }}>\n {resolution === 'skip' ? `✓ ${t('syncflow.conflictSkip')}` : t('syncflow.conflictSkip')}\n </Button>\n {conflict?.diff !== undefined && (\n <details className={css.conflictDetail}>\n <summary>{t('syncflow.diff')}</summary>\n <pre className={css.diffScroll}>{conflict.diff}</pre>\n </details>\n )}\n </span>\n );\n}\n\n/* ---------------------------------------------------------------- 执行结果 */\n\ninterface ApplyResultCardProps {\n result: ApplyItemsResponse\n busy: boolean\n t: TranslateNS<'config-manager-sync'>\n onRollback: (restoreId: string) => Promise<void>\n}\n\nfunction ApplyResultCard({ result, busy, t, onRollback }: ApplyResultCardProps): ReactNode {\n const ok = result.ok;\n return (\n <>\n <Banner kind={ok ? 'ok' : 'error'}>\n {ok ? t('syncflow.importDone', { n: String(result.applied.length) }) : t('syncflow.importFailed')}\n </Banner>\n {result.needsRestart && <Banner kind=\"warn\">{t('syncflow.needsRestart')}</Banner>}\n {result.applied.length > 0 && (\n <div>\n <span className={css.fieldLabel}>{t('syncflow.importedSections')}</span>\n <div className={css.statRow}>\n {result.applied.map((sid) => <Badge key={sid} kind=\"ok\">{sid}</Badge>)}\n </div>\n </div>\n )}\n {result.warnings.length > 0 && (\n <div>\n <span className={css.fieldLabel}>{t('syncflow.importWarnings')}</span>\n <ul className={css.warnList}>\n {result.warnings.map((w, i) => <li key={i}>{w}</li>)}\n </ul>\n </div>\n )}\n {result.restoreId !== '' && (\n <Button\n variant=\"danger\"\n disabled={busy}\n onClick={() => { void onRollback(result.restoreId) }}\n >\n {busy ? <Spinner label={t('syncflow.rollingBack')} /> : t('syncflow.rollback')}\n </Button>\n )}\n </>\n );\n}\n","/**\n * 远程同步面板(备份与迁移页的第 4 个 tab 内容)。\n *\n * 独立设置页壳(sectionHeader/close/自身 tab)已移除 —— tab 容器由\n * ConfigManagerSection 统一渲染,本组件只输出内容体:\n * - 仓库配置表单:repoUrl(必填)+ 认证 token(可选,写入 DSH credentials 的提示)\n * + gitBin(可选);\n * - 私有仓库强制提示横幅(常驻);\n * - 推送按钮 → SyncPushReport(快照 id / 分区 / 告警);\n * - 拉取按钮 → SyncPullReport.changes 差异摘要(description/kind/severity);\n * - 【方案 A】一键同步主按钮:拉取 → 差异确认会话(SyncConfirmView 逐项确认)→\n * 确认导入(apply-items)→ 执行结果 + 一键回滚(restoreId);「选择历史快照」下拉;\n * - 【方案 A】自动同步设置区块:总开关 + 间隔下拉 + 状态(上次运行 / 下次倒计时);\n * - 状态行:凭据配置 + 上次同步时间 + 通道(来自 GET /sync/status,组件挂载时加载)。\n *\n * 全部渲染模型来自 ./sync-view.ts 纯函数(node 单测覆盖),组件只做装配;\n * 状态组件内自持(低频显式操作,同 SnapshotsPanel 策略,不进 sessionStorage);\n * token 仅内存(state),成功后清空(已写入 DSH credentials),绝不持久化。\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { ChangeEvent } from 'react'\nimport type { TranslateNS } from '../client-types.ts'\nimport type { SyncPullReport, SyncPushReport } from '../../sync/sync-engine.ts'\nimport { Badge, Banner, Button, Card, SectionTitle, Spinner } from '../common/ui.tsx'\nimport { ErrorBanner } from '../common/ErrorBanner.tsx'\nimport { SYNC_CREDENTIAL_REF } from './sync-api.ts'\nimport type {\n AutosyncInterval, AutosyncStatusResponse, SyncApi, SyncSnapshotLite, SyncStartResponse,\n SyncStatusResponse,\n} from './sync-api.ts'\nimport {\n autosyncIntervalMs, autosyncStatusText, computeAutosyncCountdown, computeGithubLoginView,\n computeSyncButtons, computeSyncStatus, formatIntervalDuration, githubPollMessage, kindLabel,\n privateRepoHint, pullReportView, pushReportView, severityLabel,\n} from './sync-view.ts'\nimport type { GithubLoginPhase } from './sync-view.ts'\nimport { SyncHistoryView } from './SyncHistoryView.tsx'\nimport { SyncConfirmView } from './SyncConfirmView.tsx'\nimport css from '../config-manager.module.css'\n\nexport interface SyncSettingsViewProps {\n api: SyncApi\n t: TranslateNS<'config-manager-sync'>\n}\n\ninterface SyncUiState {\n loading: boolean\n loadError: string | null\n statusInfo: SyncStatusResponse | null\n repoUrl: string\n gitBin: string\n /** 仅内存:成功后清空(已写入 DSH credentials),绝不持久化 */\n token: string\n busy: 'sync' | 'push' | 'pull' | 'rollback' | null\n pushReport: SyncPushReport | null\n pullReport: SyncPullReport | null\n /** 一键同步差异确认会话(POST /sync/sync 结果;非空时渲染 SyncConfirmView) */\n confirmSession: SyncStartResponse | null\n /** 远端历史快照列表(「选择历史快照」下拉数据源) */\n snapshots: SyncSnapshotLite[]\n /** 当前选中的历史快照 id('' = 最新) */\n selectedSnapshotId: string\n /** 自动同步状态 */\n autosync: AutosyncStatusResponse | null\n /** 自动同步开关(回填自 autosync) */\n autosyncEnabled: boolean\n /** 自动同步间隔(回填自 autosync) */\n autosyncInterval: AutosyncInterval\n /** 最近一次一键同步执行结果(回滚入口) */\n lastRestoreId: string | null\n error: string | null\n /** GitHub OAuth device flow 状态(flowId/userCode 仅内存,token 只存宿主) */\n github: GithubUiState\n}\n\ninterface GithubUiState {\n phase: GithubLoginPhase\n flowId: string\n userCode: string\n verificationUri: string\n /** GitHub 建议轮询间隔秒数(pending 重排时兜底用) */\n interval: number\n error: string | null\n}\n\nconst initialGithub: GithubUiState = {\n phase: 'idle', flowId: '', userCode: '', verificationUri: '', interval: 5, error: null,\n}\n\nconst AUTOSYNC_INTERVAL_OPTIONS: AutosyncInterval[] = ['5m', '15m', '30m', '60m', '6h', '12h', '24h'];\n\nconst initial: SyncUiState = {\n loading: true,\n loadError: null,\n statusInfo: null,\n repoUrl: '',\n gitBin: '',\n token: '',\n busy: null,\n pushReport: null,\n pullReport: null,\n confirmSession: null,\n snapshots: [],\n selectedSnapshotId: '',\n autosync: null,\n autosyncEnabled: false,\n autosyncInterval: '30m',\n lastRestoreId: null,\n error: null,\n github: initialGithub,\n}\n\nexport function SyncSettingsView({ api, t }: SyncSettingsViewProps) {\n const [state, setState] = useState<SyncUiState>(initial)\n const uiT = api.t // 客户端展示层翻译器(zh/en,见 ui/i18n.ts)\n const patch = (p: Partial<SyncUiState>): void => setState((s) => ({ ...s, ...p }))\n const patchGithub = (p: Partial<GithubUiState>): void => setState((s) => ({ ...s, github: { ...s.github, ...p } }))\n /** GitHub 轮询定时器(卸载/取消时清理,防止泄漏与跨流程串扰) */\n const githubPollTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n /** 挂载时读取同步状态(配置回填 + 上次同步时间 + 凭据状态 + autosync) */\n const loadStatus = async (): Promise<void> => {\n patch({ loading: true, loadError: null })\n try {\n const info = await api.status()\n patch({\n loading: false,\n statusInfo: info,\n repoUrl: info.repoUrl ?? '',\n gitBin: info.gitBin ?? '',\n ...(info.autosync !== undefined\n ? {\n autosync: info.autosync,\n autosyncEnabled: info.autosync.enabled,\n autosyncInterval: info.autosync.interval,\n }\n : {}),\n })\n // 独立拉取 autosync(若 status 未带则补一次)\n if (info.autosync === undefined) {\n void loadAutosync()\n }\n } catch (err) {\n patch({ loading: false, loadError: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** 读取自动同步状态(GET /sync/autosync)。 */\n const loadAutosync = async (): Promise<void> => {\n try {\n const autosync = await api.autosyncStatus()\n patch({ autosync, autosyncEnabled: autosync.enabled, autosyncInterval: autosync.interval })\n } catch (err) {\n patch({ error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** 读取远端历史快照列表(「选择历史快照」下拉数据源)。 */\n const loadSnapshots = async (): Promise<void> => {\n try {\n const res = await api.snapshotsList(payload())\n patch({ snapshots: res.snapshots })\n } catch {\n // 拉取失败不阻断主流程(下拉留空,用户可重试)\n }\n }\n\n useEffect(() => {\n void loadStatus()\n // api 为注入单例(注册时创建),生命周期内稳定;仅挂载时加载一次\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n /** 卸载时清理轮询定时器(组件销毁后不得再 setState/发请求) */\n useEffect(() => () => {\n if (githubPollTimer.current !== null) clearTimeout(githubPollTimer.current)\n }, [])\n\n /** 表单快照 → 请求体(token 为空串不携带;gitBin 空串不携带) */\n const payload = (): { repoUrl: string; gitBin?: string; token?: string } => ({\n repoUrl: state.repoUrl.trim(),\n gitBin: state.gitBin.trim() !== '' ? state.gitBin.trim() : undefined,\n token: state.token.trim() !== '' ? state.token : undefined,\n })\n\n /* ------------------------------------------------ GitHub OAuth device flow */\n\n /** 发起 GitHub 登录:取设备码 → 展示一次性用户码 + 授权页 → 开始轮询 */\n const runGithubStart = async (): Promise<void> => {\n patchGithub({ phase: 'starting', error: null })\n try {\n const info = await api.githubStart()\n patchGithub({\n phase: 'waiting',\n flowId: info.flowId,\n userCode: info.userCode,\n verificationUri: info.verificationUri,\n interval: info.interval,\n })\n scheduleGithubPoll(info.flowId, Math.max(info.interval, 1) * 1000)\n } catch (err) {\n patchGithub({ phase: 'error', error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** 排定一次 GitHub 轮询(先清旧定时器,避免重复轮询) */\n const scheduleGithubPoll = (flowId: string, delayMs: number): void => {\n if (githubPollTimer.current !== null) clearTimeout(githubPollTimer.current)\n githubPollTimer.current = setTimeout(() => { void runGithubPoll(flowId) }, delayMs)\n }\n\n /** 轮询 GitHub 授权结果:pending 继续等;success 刷新凭据状态;终止态展示结果 */\n const runGithubPoll = async (flowId: string): Promise<void> => {\n patchGithub({ phase: 'polling' })\n try {\n const poll = await api.githubPoll(flowId)\n if (poll.status === 'pending') {\n patchGithub({ phase: 'waiting' })\n scheduleGithubPoll(flowId, poll.pollDelayMs ?? Math.max(state.github.interval, 1) * 1000)\n return\n }\n const message = githubPollMessage(poll, uiT)\n if (poll.status === 'success') {\n patchGithub({ phase: 'success', error: null })\n // token 已由宿主写入 DSH credentials:刷新状态行与凭据徽章\n void loadStatus()\n } else {\n patchGithub({ phase: 'error', error: message })\n }\n } catch (err) {\n patchGithub({ phase: 'error', error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** 取消登录:停轮询 + 通知宿主丢弃设备码登记 + 复位 UI */\n const runGithubCancel = async (): Promise<void> => {\n if (githubPollTimer.current !== null) {\n clearTimeout(githubPollTimer.current)\n githubPollTimer.current = null\n }\n const flowId = state.github.flowId\n patchGithub(initialGithub)\n if (flowId !== '') {\n try { await api.githubCancel(flowId) } catch { /* 取消失败无需打扰用户 */ }\n }\n }\n\n const runPush = async (): Promise<void> => {\n patch({ busy: 'push', error: null, pushReport: null, pullReport: null })\n try {\n const report = await api.push(payload())\n // 成功即清空 token(已安全写入 DSH credentials);失败保留以便重试\n patch({ busy: null, pushReport: report, token: report.ok ? '' : state.token })\n } catch (err) {\n patch({ busy: null, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n const runPull = async (): Promise<void> => {\n patch({ busy: 'pull', error: null, pullReport: null, pushReport: null })\n try {\n const report = await api.pull(payload())\n patch({ busy: null, pullReport: report, token: '' })\n } catch (err) {\n patch({ busy: null, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /* ------------------------------------------------ 一键同步(方案 A) */\n\n /** 一键同步:拉取 → 差异确认会话(先取消旧会话,再发起新会话)。 */\n const runSync = async (snapshotId?: string): Promise<void> => {\n // 清理旧的差异确认会话(避免残留临时 ZIP / 同 key 冲突)\n if (state.confirmSession !== null) {\n try { await api.cancel(state.confirmSession.syncSessionId) } catch { /* 尽力清理 */ }\n }\n patch({ busy: 'sync', error: null, confirmSession: null, lastRestoreId: null })\n try {\n const session = await api.sync({ ...payload(), ...(snapshotId !== undefined && snapshotId !== '' ? { snapshotId } : {}) })\n if (!session.ok) {\n patch({ busy: null, error: session.message ?? t('syncflow.syncFailed') })\n return\n }\n patch({ busy: null, confirmSession: session, token: '' })\n void loadSnapshots()\n } catch (err) {\n patch({ busy: null, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n /** 用户取消差异确认:清除会话,复位到空闲。 */\n const cancelConfirm = (): void => {\n patch({ confirmSession: null })\n }\n\n /** 从 SyncConfirmView 透传的一键回滚完成信号。 */\n const onRollbackApplied = (): void => {\n patch({ lastRestoreId: null })\n }\n\n /* ------------------------------------------------ 自动同步(方案 A) */\n\n const toggleAutosync = async (enabled: boolean): Promise<void> => {\n patch({ autosyncEnabled: enabled, error: null })\n try {\n const updated = await api.autosyncUpdate({ enabled, interval: state.autosyncInterval })\n patch({ autosync: updated, autosyncEnabled: updated.enabled, autosyncInterval: updated.interval })\n } catch (err) {\n patch({ error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n const updateAutosyncInterval = async (interval: AutosyncInterval): Promise<void> => {\n patch({ autosyncInterval: interval, error: null })\n try {\n const updated = await api.autosyncUpdate({ enabled: state.autosyncEnabled, interval })\n patch({ autosync: updated, autosyncEnabled: updated.enabled, autosyncInterval: updated.interval })\n } catch (err) {\n patch({ error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n const status = computeSyncStatus(state.statusInfo, state.loading, state.loadError, uiT)\n const buttons = computeSyncButtons(state.busy, state.repoUrl, uiT)\n const pushView = pushReportView(state.pushReport, uiT)\n const pullView = pullReportView(state.pullReport, uiT)\n const githubView = computeGithubLoginView(\n state.github.phase, state.github.userCode, state.github.verificationUri, state.github.error, uiT,\n )\n /** GitHub 流程进行中(请求设备码 / 等待授权 / 轮询):禁用 push/pull,避免无凭据操作 */\n const githubBusy =\n state.github.phase === 'starting' || state.github.phase === 'waiting' || state.github.phase === 'polling'\n\n const autosyncText = state.autosync !== null ? autosyncStatusText(state.autosync, uiT) : t('autosync.statusNever')\n const autosyncCountdown = state.autosync !== null && state.autosync.elapsedMs >= 0\n ? formatIntervalDuration(computeAutosyncCountdown(state.autosync.elapsedMs, autosyncIntervalMs(state.autosync.interval)), uiT)\n : null\n\n return (\n <div className={css.viewBody}>\n <SectionTitle title={t('section.label')} subtitle={t('section.description')} />\n\n {/* 私有仓库强制提示 */}\n <Banner kind=\"warn\">{privateRepoHint(uiT)}</Banner>\n\n {/* 仓库配置 */}\n <Card>\n <span className={css.groupLabel}>{t('config.title')}</span>\n <label className={css.field}>\n <span className={css.fieldLabel}>{t('config.repoUrl')}</span>\n <input\n type=\"text\"\n className={css.input}\n value={state.repoUrl}\n placeholder=\"https://github.com/user/private-repo.git\"\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { patch({ repoUrl: e.target.value }) }}\n />\n <span className={css.hint}>{t('config.repoUrlHint')}</span>\n </label>\n <label className={css.field}>\n <span className={css.fieldLabel}>\n {t('config.token')}\n {' '}\n {state.statusInfo?.credentialConfigured === true && <Badge kind=\"ok\">{t('config.tokenSaved')}</Badge>}\n </span>\n <input\n type=\"password\"\n className={css.input}\n value={state.token}\n autoComplete=\"off\"\n placeholder={t('config.tokenPlaceholder')}\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { patch({ token: e.target.value }) }}\n />\n <span className={css.hint}>{t('config.tokenHint', { ref: SYNC_CREDENTIAL_REF })}</span>\n </label>\n\n {/* GitHub OAuth 登录(device flow):无需手动输入 token */}\n <span className={css.groupLabel}>{t('github.title')}</span>\n <span className={css.hint}>{t('github.description')}</span>\n {githubView.showCode && (\n <div className={css.statRow}>\n <Badge kind=\"info\">{t('github.userCode')}:<strong>{githubView.userCode}</strong></Badge>\n <a\n className={css.ghostButton}\n href={githubView.verificationUri}\n target=\"_blank\"\n rel=\"noreferrer\"\n style={{ textDecoration: 'none' }}\n >\n {t('github.openAuth')}\n </a>\n </div>\n )}\n <div className={css.actionRow}>\n <Button\n variant=\"primary\"\n disabled={!githubView.canStart || state.busy !== null}\n onClick={() => { void runGithubStart() }}\n >\n {githubView.startLabel}\n </Button>\n {githubView.canCancel && (\n <Button disabled={state.busy !== null} onClick={() => { void runGithubCancel() }}>\n {t('github.cancel')}\n </Button>\n )}\n </div>\n <div className={css.statRow}>\n <Badge kind={githubView.phase === 'success' ? 'ok' : githubView.phase === 'error' ? 'error' : 'warn'}>\n {githubView.statusText}\n </Badge>\n </div>\n {githubView.phase === 'error' && (\n <span className={css.hint}>{t('config.tokenHint', { ref: SYNC_CREDENTIAL_REF })}</span>\n )}\n\n <label className={css.field}>\n <span className={css.fieldLabel}>{t('config.gitBin')}</span>\n <input\n type=\"text\"\n className={css.input}\n value={state.gitBin}\n placeholder=\"git\"\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { patch({ gitBin: e.target.value }) }}\n />\n <span className={css.hint}>{t('config.gitBinHint')}</span>\n </label>\n </Card>\n\n {/* 同步状态 */}\n <Card>\n <span className={css.groupLabel}>{t('status.title')}</span>\n <div className={css.statRow}>\n <Badge kind={status.kind === 'ready' ? 'ok' : status.kind === 'error' ? 'error' : 'warn'}>{status.text}</Badge>\n </div>\n </Card>\n\n {/* 一键同步 + 手动推送/拉取 */}\n <div className={css.actionRow}>\n <Button\n variant=\"primary\"\n disabled={state.busy !== null || state.repoUrl.trim() === ''}\n onClick={() => { void runSync() }}\n >\n {state.busy === 'sync' ? <Spinner label={t('syncflow.syncing')} /> : t('syncflow.button')}\n </Button>\n <Button disabled={!buttons.canPush || githubBusy} onClick={() => { void runPush() }}>\n {state.busy === 'push' ? <Spinner label={buttons.pushLabel} /> : buttons.pushLabel}\n </Button>\n <Button disabled={!buttons.canPull || githubBusy} onClick={() => { void runPull() }}>\n {state.busy === 'pull' ? <Spinner label={buttons.pullLabel} /> : buttons.pullLabel}\n </Button>\n </div>\n\n {/* 选择历史快照下拉 */}\n <div className={css.statRow}>\n <label className={css.field}>\n <span className={css.fieldLabel}>{t('syncflow.selectSnapshot')}</span>\n <select\n className={css.input}\n value={state.selectedSnapshotId}\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLSelectElement>) => {\n const id = e.target.value\n patch({ selectedSnapshotId: id })\n void runSync(id === '' ? undefined : id)\n }}\n >\n <option value=\"\">{t('syncflow.latestSnapshot')}</option>\n {state.snapshots.map((s) => (\n <option key={s.id} value={s.id}>\n {s.id}{t('syncflow.snapshotOption', { date: s.createdAt.slice(0, 10), count: String(s.sectionCount) })}\n </option>\n ))}\n </select>\n {state.snapshots.length === 0 && <span className={css.hint}>{t('syncflow.noSnapshots')}</span>}\n </label>\n </div>\n\n {state.error !== null && <ErrorBanner error={state.error} />}\n\n {/* 一键同步差异确认(拉取 → 逐项确认 → 导入) */}\n {state.confirmSession !== null && (\n <SyncConfirmView\n api={api}\n syncSessionId={state.confirmSession.syncSessionId}\n snapshotId={state.confirmSession.snapshotId}\n items={state.confirmSession.items}\n needsReview={state.confirmSession.needsReview}\n compatibility={state.confirmSession.compatibility}\n t={t}\n onCancel={cancelConfirm}\n onRollbackDone={onRollbackApplied}\n />\n )}\n\n {/* 推送结果 */}\n {pushView !== null && (\n <Card>\n <span className={css.groupLabel}>{t('push.title')}</span>\n <Banner kind={pushView.kind === 'ok' ? 'ok' : 'error'}>{pushView.headline}</Banner>\n {pushView.sections.length > 0 && (\n <div>\n <span className={css.fieldLabel}>{t('sections.title')}</span>\n <div className={css.statRow}>\n {pushView.sections.map((s) => <Badge key={s} kind=\"info\">{s}</Badge>)}\n </div>\n </div>\n )}\n {pushView.warnings.length > 0 && (\n <div>\n <span className={css.fieldLabel}>{t('warnings.title')}</span>\n <ul className={css.warnList}>\n {pushView.warnings.map((w, i) => <li key={i}>{w}</li>)}\n </ul>\n </div>\n )}\n </Card>\n )}\n\n {/* 拉取差异预览 */}\n {pullView !== null && (\n <Card>\n <span className={css.groupLabel}>{t('pull.title')}</span>\n <Banner kind={pullView.kind === 'ok' ? 'info' : pullView.kind === 'empty' ? 'ok' : 'error'}>{pullView.headline}</Banner>\n {pullView.summary !== null && (\n <>\n <div className={css.statRow}>\n <Badge kind=\"info\">{t('change.total', { total: pullView.summary.total })}</Badge>\n {pullView.summary.error > 0 && <Badge kind=\"error\">{severityLabel('error', uiT)} × {pullView.summary.error}</Badge>}\n {pullView.summary.warning > 0 && <Badge kind=\"warn\">{severityLabel('warning', uiT)} × {pullView.summary.warning}</Badge>}\n {pullView.summary.info > 0 && <Badge kind=\"info\">{severityLabel('info', uiT)} × {pullView.summary.info}</Badge>}\n </div>\n {pullView.summary.needsReview && <Banner kind=\"warn\">{t('pull.needsReview')}</Banner>}\n <div className={css.reportList}>\n {pullView.summary.items.map((c) => (\n <div key={c.id} className={css.statRow}>\n <span className={css.kindTag}>{kindLabel(c.kind, uiT)}</span>\n <Badge kind={c.severity === 'error' ? 'error' : c.severity === 'warning' ? 'warn' : 'info'}>\n {severityLabel(c.severity, uiT)}\n </Badge>\n <span>{c.description}</span>\n </div>\n ))}\n </div>\n </>\n )}\n {pullView.previewHint !== '' && <Banner kind=\"info\">{pullView.previewHint}</Banner>}\n </Card>\n )}\n\n {/* 自动同步设置(方案 A) */}\n <Card>\n <span className={css.groupLabel}>{t('autosync.title')}</span>\n <span className={css.hint}>{t('autosync.description')}</span>\n <label className={css.checkboxRow}>\n <input\n type=\"checkbox\"\n checked={state.autosyncEnabled}\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLInputElement>) => { void toggleAutosync(e.target.checked) }}\n />\n <span>{t('autosync.enable')}</span>\n </label>\n <label className={css.field}>\n <span className={css.fieldLabel}>{t('autosync.interval')}</span>\n <select\n className={css.input}\n value={state.autosyncInterval}\n disabled={state.busy !== null}\n onChange={(e: ChangeEvent<HTMLSelectElement>) => {\n void updateAutosyncInterval(e.target.value as AutosyncInterval)\n }}\n >\n {AUTOSYNC_INTERVAL_OPTIONS.map((iv) => (\n <option key={iv} value={iv}>{intervalLabel(iv, t)}</option>\n ))}\n </select>\n <span className={css.hint}>{t('autosync.intervalHint')}</span>\n </label>\n <div className={css.statRow}>\n <Badge kind={state.autosync?.lastRunStatus === 'failed' ? 'error' : state.autosync?.lastRunStatus === 'skipped' ? 'warn' : 'info'}>\n {autosyncText}\n </Badge>\n {autosyncCountdown !== null && state.autosyncEnabled && (\n <Badge kind=\"info\">{t('autosync.nextRun', { time: autosyncCountdown })}</Badge>\n )}\n </div>\n </Card>\n\n {/* P2:同步历史视图(Host /sync/history 端点) */}\n <SyncHistoryView api={api} t={t} />\n </div>\n )\n}\n\n/** AutosyncInterval → 可读标签(复用 i18n interval 键)。 */\nfunction intervalLabel(iv: AutosyncInterval, t: TranslateNS<'config-manager-sync'>): string {\n switch (iv) {\n case '5m': return t('autosync.interval5m');\n case '15m': return t('autosync.interval15m');\n case '30m': return t('autosync.interval30m');\n case '60m': return t('autosync.interval60m');\n case '6h': return t('autosync.interval6h');\n case '12h': return t('autosync.interval12h');\n case '24h': return t('autosync.interval24h');\n default: return iv;\n }\n}\n","/**\n * Config Manager 设置页(settings.section 入口的主页面容器)。\n *\n * 业务面(api)由注册时的 inject face 注入;t 由 locale seat 注入。\n * 关闭按钮由 settings shell 自带,本页不再渲染。内部两个主视图:\n * Export(Quick/Custom)与 Import(九步向导)。\n *\n * m2:主视图 tab(view)与全部子视图状态统一由模块级 runStore 持有\n * (sessionStorage 持久化 + 切 tab/关面板不重建控制器实例);挂载时\n * 经 GET /runs + 轮询 /progress 恢复进行中的 run(刷新/重开面板后)。\n */\nimport { useEffect, useSyncExternalStore, useState } from 'react'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ConfigManagerSectionInjected, TranslateNS } from './client-types.ts'\nimport { runStore, type MainView } from './run-store.ts'\nimport { ExportView } from './export/ExportView.tsx'\nimport { ImportWizardView } from './import/ImportWizardView.tsx'\nimport { SnapshotsPanel } from './snapshots/SnapshotsPanel.tsx'\nimport { SyncSettingsView } from './sync/SyncSettingsView.tsx'\nimport css from './config-manager.module.css'\n\nexport type ConfigManagerSectionProps =\n & PropsRuntime<'settings.section'>\n & ConfigManagerSectionInjected\n & { t: TranslateNS<'config-manager'> }\n\n/**\n * 设置页容器:Export / Import / Snapshots / Sync 四视图切换。\n * Export/Import 状态在模块级 store(切 tab 不丢失);快照恢复与远程同步为低频显式\n * 操作,其状态组件内自持(local state,不进 sessionStorage)。\n */\nexport function ConfigManagerSection({ api, syncApi, syncT, t }: ConfigManagerSectionProps) {\n const state = useSyncExternalStore(runStore.subscribe, runStore.getSnapshot)\n const view = state.view\n const [snapshotsOpen, setSnapshotsOpen] = useState(false)\n const [syncOpen, setSyncOpen] = useState(false)\n\n // m2-resume:挂载时重新订阅进行中的 run(刷新 / 重开面板后服务端继续执行,\n // 这里经 /runs 找回活跃 runId 再轮询 /progress);卸载时停止轮询,重开再订阅。\n useEffect(() => {\n void runStore.resume(api)\n return () => {\n runStore.stopResume()\n }\n }, [api])\n\n const setView = (next: MainView): void => {\n setSnapshotsOpen(false)\n setSyncOpen(false)\n runStore.patch({ view: next })\n }\n\n const openSnapshots = (): void => {\n setSnapshotsOpen(true)\n setSyncOpen(false)\n }\n\n const openSync = (): void => {\n setSyncOpen(true)\n setSnapshotsOpen(false)\n }\n\n const activeTab: MainView | 'snapshots' | 'sync' = syncOpen ? 'sync' : snapshotsOpen ? 'snapshots' : view\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={activeTab === 'export'}\n data-active={activeTab === '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={activeTab === 'import'}\n data-active={activeTab === 'import' ? '' : undefined}\n className={css.viewTab}\n onClick={() => { setView('import') }}\n >\n {t('view.import')}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === 'snapshots'}\n data-active={snapshotsOpen ? '' : undefined}\n className={css.viewTab}\n onClick={openSnapshots}\n >\n {t('view.snapshots')}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === 'sync'}\n data-active={syncOpen ? '' : undefined}\n className={css.viewTab}\n onClick={openSync}\n >\n {t('view.sync')}\n </button>\n </div>\n </div>\n <div className={css.sectionBody}>\n {syncOpen\n ? <SyncSettingsView api={syncApi} t={syncT} />\n : snapshotsOpen\n ? <SnapshotsPanel api={api} t={t} />\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 'view.snapshots': '快照恢复',\n 'view.sync': '远程同步',\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.reselect': '重新选择',\n 'import.select.cancel': '取消选择',\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 'snapshots.title': '快照恢复',\n 'snapshots.hint': '恢复到导入前状态:整文件还原 settings/patch、卸载导入期间新增插件、补偿被修改文件。执行前会把当前文件备份到快照的 pre-restore 目录。',\n 'snapshots.empty': '暂无快照。执行导入时会自动创建安全快照。',\n 'snapshots.loading': '加载快照中…',\n 'snapshots.selectHint': '选择快照以预览恢复计划(dry-run,零写入):',\n 'snapshots.createdAt': '创建时间',\n 'snapshots.sourceZip': '来源备份',\n 'snapshots.status': '状态',\n 'snapshots.entries': '条目',\n 'snapshots.plugins': '插件',\n 'snapshots.status.pending': '进行中',\n 'snapshots.status.done': '已完成',\n 'snapshots.status.rolled-back': '已回滚',\n 'snapshots.status.unknown': '未知',\n 'snapshots.planTitle': '恢复计划预览',\n 'snapshots.noActions': '该快照无可用恢复动作(或全部跳过)。',\n 'snapshots.execute': '执行恢复',\n 'snapshots.executing': '恢复执行中…',\n 'snapshots.confirmRestore': '确认执行恢复?当前文件会先备份到快照的 pre-restore 目录,插件通过官方 dsh plugin remove 卸载。',\n 'snapshots.reportTitle': '恢复报告',\n 'snapshots.restored': '已还原',\n 'snapshots.removedPlugins': '已卸载插件',\n 'snapshots.manualHints': '需人工处理',\n 'snapshots.failed': '失败',\n 'snapshots.skipped': '跳过',\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 'view.snapshots': 'Snapshots & Restore',\n 'view.sync': 'Remote Sync',\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.reselect': 'Reselect',\n 'import.select.cancel': 'Cancel selection',\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… (installing many plugins may take a few minutes; keep this page open)',\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 'snapshots.title': 'Snapshot Restore',\n 'snapshots.hint': 'Restore to the pre-import state: whole-file restore of settings/patch, uninstall plugins added during import, compensate modified files. Current files are backed up to the snapshot\\'s pre-restore folder before any change.',\n 'snapshots.empty': 'No snapshots yet. A safety snapshot is created automatically on import.',\n 'snapshots.loading': 'Loading snapshots…',\n 'snapshots.selectHint': 'Select a snapshot to preview its restore plan (dry-run, zero writes):',\n 'snapshots.createdAt': 'Created',\n 'snapshots.sourceZip': 'Source',\n 'snapshots.status': 'Status',\n 'snapshots.entries': 'Entries',\n 'snapshots.plugins': 'Plugins',\n 'snapshots.status.pending': 'Pending',\n 'snapshots.status.done': 'Done',\n 'snapshots.status.rolled-back': 'Rolled back',\n 'snapshots.status.unknown': 'Unknown',\n 'snapshots.planTitle': 'Restore Plan Preview',\n 'snapshots.noActions': 'No restorable actions for this snapshot (or all skipped).',\n 'snapshots.execute': 'Restore now',\n 'snapshots.executing': 'Restoring…',\n 'snapshots.confirmRestore': 'Confirm restore? Current files are backed up to the snapshot\\'s pre-restore folder first; plugins are removed via the official dsh plugin remove.',\n 'snapshots.reportTitle': 'Restore Report',\n 'snapshots.restored': 'Restored',\n 'snapshots.removedPlugins': 'Removed plugins',\n 'snapshots.manualHints': 'Manual action needed',\n 'snapshots.failed': 'Failed',\n 'snapshots.skipped': 'Skipped',\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 * 远程同步设置区块(config-manager-sync)表面文案:zh 为源语言,en 镜像每个键。\n * 独立命名空间、独立文件:不触碰共享的 locales.ts(并行会话已改),零冲突。\n * 键集合经 `SyncKey` 类型在 client/index.ts 注册处做编译期校验。\n */\n\nexport const zh = {\n // 入口\n 'section.label': '远程同步',\n 'section.description': '通过 Git 私有仓库在设备间同步可移植配置(secret 永不参与同步)',\n // 私有仓库强制提示(常驻警示横幅)\n 'privateRepoHint': '安全要求:同步仓库必须为私有仓库(public 仓库会公开你的配置内容)。认证 token 仅用于仓库访问,绝不写入同步文件、提交内容或日志。',\n // 仓库配置表单\n 'config.title': '仓库配置',\n 'config.repoUrl': '仓库地址',\n 'config.repoUrlHint': 'Git 私有仓库地址(https / ssh / 本地路径)。认证 token 请使用下方凭据字段,不要拼入地址。',\n 'config.token': '认证 token',\n 'config.tokenHint': '将安全写入 DSH credentials(引用名 {ref}),不会写入同步文件或日志。留空表示沿用已保存的凭据。',\n 'config.tokenSaved': '凭据已配置',\n 'config.tokenPlaceholder': 'ghp_…(可选)',\n 'config.gitBin': 'git 可执行文件(可选)',\n 'config.gitBinHint': '缺省使用 PATH 中的 git。',\n // GitHub OAuth 登录(device flow,无需手动输入 token)\n 'github.title': 'GitHub 登录',\n 'github.description': '通过 GitHub OAuth 设备码流程授权:无需手动输入 token,在浏览器中确认授权后,token 自动写入 DSH credentials。',\n 'github.login': '使用 GitHub 登录',\n 'github.retry': '重新登录',\n 'github.cancel': '取消',\n 'github.userCode': '一次性授权代码',\n 'github.openAuth': '打开 GitHub 授权页面',\n 'github.clientIdHint': '需要插件配置 githubClientId(GitHub OAuth App 的 client_id)才能使用 GitHub 登录。',\n // 状态\n 'status.title': '同步状态',\n 'status.never': '从未同步',\n // 操作\n 'action.push': '推送到远端',\n 'action.pull': '拉取差异预览',\n 'action.pushing': '正在推送…',\n 'action.pulling': '正在拉取…',\n // 报告\n 'push.title': '推送结果',\n 'pull.title': '拉取差异预览',\n 'pull.previewHint': '以上为只读差异预览,不会执行导入。v1 暂不提供一键导入接线;如需应用远端配置,请使用「导入恢复」向导手动导入导出的备份。',\n 'pull.needsReview': '包含需要人工决策的项(冲突 / 密钥 / 依赖 / 安装)',\n 'pull.empty': '远端快照与本地一致(无变更)',\n 'change.total': '共 {total} 项变更',\n 'sections.title': '同步分区',\n 'warnings.title': '分区告警',\n // 一键同步(方案 A:拉取 → 逐项确认 → apply-items)\n 'syncflow.title': '一键同步',\n 'syncflow.button': '一键同步',\n 'syncflow.syncing': '正在同步…',\n 'syncflow.syncFailed': '同步失败',\n 'syncflow.snapshotOption': '({date} · {count} 分区)',\n 'syncflow.selectSnapshot': '选择历史快照',\n 'syncflow.latestSnapshot': '最新快照',\n 'syncflow.noSnapshots': '远端暂无快照',\n 'syncflow.confirmImport': '确认导入',\n 'syncflow.cancel': '取消',\n 'syncflow.adoptRemote': '采用远端',\n 'syncflow.adoptHint': '勾选 = 导入该项;取消 = 跳过',\n 'syncflow.needsReviewBadge': '需人工决策',\n 'syncflow.empty': '远端快照与本地一致(无变更)',\n 'syncflow.diffCount': '共 {count} 项差异',\n 'syncflow.conflictTitle': '冲突解决',\n 'syncflow.conflictUseLocal': '用本地',\n 'syncflow.conflictUseRemote': '用远端',\n 'syncflow.conflictSkip': '跳过',\n 'syncflow.conflictLocalLabel': '本地',\n 'syncflow.conflictRemoteLabel': '远端',\n 'syncflow.conflictAncestorLabel': '共同祖先',\n 'syncflow.conflictUnresolved': '冲突项 {itemId} 尚未选择解决方式(用本地 / 用远端 / 跳过)',\n 'syncflow.diff': '差异',\n 'syncflow.importDone': '已导入 {n} 个分区',\n 'syncflow.importFailed': '导入失败(已整体回滚)',\n 'syncflow.importedSections': '已写入',\n 'syncflow.importWarnings': '导入告警',\n 'syncflow.rollback': '回滚到应用前',\n 'syncflow.rollingBack': '正在回滚…',\n 'syncflow.rollbackDone': '已回滚到应用前',\n 'syncflow.needsRestart': '部分改动需要重启 DSH 后生效',\n // 自动同步(方案 A)\n 'autosync.title': '自动同步',\n 'autosync.description': '开启后,DSH 将按固定间隔自动执行双向同步(拉取合并 + 上传);DSH 启动时还会触发一次「自动下载合并(不上传)」以保持本地为最新。仅在无冲突且无需人工干预时才自动写入。',\n 'autosync.enable': '启用自动同步',\n 'autosync.interval': '同步间隔',\n 'autosync.intervalHint': 'DSH 启动时自动下载合并不上传。',\n 'autosync.interval5m': '5 分钟',\n 'autosync.interval15m': '15 分钟',\n 'autosync.interval30m': '30 分钟',\n 'autosync.interval60m': '60 分钟',\n 'autosync.interval6h': '6 小时',\n 'autosync.interval12h': '12 小时',\n 'autosync.interval24h': '24 小时',\n 'autosync.status': '上次运行:{status}({time})',\n 'autosync.statusNever': '从未运行',\n 'autosync.nextRun': '下次约 {time} 后',\n 'autosync.failCount': '连续失败 {n} 次',\n 'autosync.running': '自动同步进行中…',\n 'autosync.success': '成功',\n 'autosync.skipped': '已跳过',\n 'autosync.failed': '失败',\n 'autosync.partial': '部分成功',\n // 同步历史(含自动同步记录)\n 'history.title': '同步历史',\n 'history.empty': '尚无同步历史',\n 'history.emptyHint': '完成首次 push / 一键同步 / 自动同步后,这里会显示记录。',\n 'history.colTime': '时间',\n 'history.colKind': '类型',\n 'history.colDetail': '详情',\n 'history.kindSnapshot': '快照',\n 'history.kindAutosync': '自动同步',\n 'history.sectionCount': '分区',\n 'history.detail': '明细',\n 'history.autosyncDirection': '方向:{direction}',\n 'history.autosyncPull': '下载',\n 'history.autosyncPush': '上传',\n 'history.autosyncBoth': '双向',\n 'history.autosyncSkipReason': '跳过原因:{reason}',\n 'history.autosyncReasonConflict': '冲突',\n 'history.autosyncReasonNoRemote': '无远端快照',\n 'history.autosyncReasonNotConfigured': '未配置仓库',\n 'history.autosyncReasonNetwork': '网络问题',\n 'history.autosyncConflicted': '跳过冲突分区:{sections}',\n 'history.autosyncApplied': '应用分区:{sections}',\n 'history.autosyncError': '错误:{error}',\n 'history.autosyncNotified': '已通知(连续失败 3 次)',\n 'history.column.snapshot': '快照',\n 'history.column.autosync': '自动同步',\n // 公共\n 'common.close': '关闭',\n 'common.retry': '重试',\n 'common.loading': '加载中…',\n} as const;\n\nexport const en: Record<keyof typeof zh, string> = {\n 'section.label': 'Remote Sync',\n 'section.description': 'Sync portable configuration across devices via a private Git repository (secrets never sync)',\n 'privateRepoHint': 'Security requirement: the sync repository MUST be private (a public repo would expose your configuration). The auth token is only used for repository access and is never written into sync files, commit content, or logs.',\n 'config.title': 'Repository',\n 'config.repoUrl': 'Repository URL',\n 'config.repoUrlHint': 'Private Git repository URL (https / ssh / local path). Use the credential field below for the auth token; never embed it in the URL.',\n 'config.token': 'Auth token',\n 'config.tokenHint': 'Securely written into DSH credentials (ref {ref}); never written into sync files or logs. Leave blank to reuse the saved credential.',\n 'config.tokenSaved': 'Credential configured',\n 'config.tokenPlaceholder': 'ghp_… (optional)',\n 'config.gitBin': 'git executable (optional)',\n 'config.gitBinHint': 'Defaults to git on PATH.',\n 'github.title': 'GitHub Sign-in',\n 'github.description': 'Authorize via the GitHub OAuth device flow: no manual token entry — after you approve in the browser, the token is written into DSH credentials automatically.',\n 'github.login': 'Sign in with GitHub',\n 'github.retry': 'Sign in again',\n 'github.cancel': 'Cancel',\n 'github.userCode': 'One-time code',\n 'github.openAuth': 'Open GitHub authorization page',\n 'github.clientIdHint': 'Requires the githubClientId plugin config (the client_id of your GitHub OAuth App).',\n 'status.title': 'Sync Status',\n 'status.never': 'Never synced',\n 'action.push': 'Push to remote',\n 'action.pull': 'Pull diff preview',\n 'action.pushing': 'Pushing…',\n 'action.pulling': 'Pulling…',\n 'push.title': 'Push Result',\n 'pull.title': 'Pull Diff Preview',\n 'pull.previewHint': 'Read-only diff preview above; nothing is imported. v1 does not wire one-click import yet — use the Import wizard to apply a downloaded backup if needed.',\n 'pull.needsReview': 'Contains items that need human decisions (conflicts / secrets / dependencies / installs)',\n 'pull.empty': 'Remote snapshot matches local (no changes)',\n 'change.total': '{total} change(s)',\n 'sections.title': 'Synced Sections',\n 'warnings.title': 'Section Warnings',\n 'syncflow.title': 'One-Click Sync',\n 'syncflow.button': 'One-click sync',\n 'syncflow.syncing': 'Syncing…',\n 'syncflow.syncFailed': 'Sync failed',\n 'syncflow.snapshotOption': '({date} · {count} sections)',\n 'syncflow.selectSnapshot': 'Select snapshot',\n 'syncflow.latestSnapshot': 'Latest snapshot',\n 'syncflow.noSnapshots': 'No remote snapshots',\n 'syncflow.confirmImport': 'Confirm import',\n 'syncflow.cancel': 'Cancel',\n 'syncflow.adoptRemote': 'Adopt remote',\n 'syncflow.adoptHint': 'Check = import item; uncheck = skip',\n 'syncflow.needsReviewBadge': 'Needs decision',\n 'syncflow.empty': 'Remote snapshot matches local (no changes)',\n 'syncflow.diffCount': '{count} change(s)',\n 'syncflow.conflictTitle': 'Resolve conflict',\n 'syncflow.conflictUseLocal': 'Use local',\n 'syncflow.conflictUseRemote': 'Use remote',\n 'syncflow.conflictSkip': 'Skip',\n 'syncflow.conflictLocalLabel': 'Local',\n 'syncflow.conflictRemoteLabel': 'Remote',\n 'syncflow.conflictAncestorLabel': 'Common ancestor',\n 'syncflow.conflictUnresolved': 'Conflict item {itemId} has no resolution yet (use local / use remote / skip)',\n 'syncflow.diff': 'Diff',\n 'syncflow.importDone': 'Imported {n} section(s)',\n 'syncflow.importFailed': 'Import failed (rolled back)',\n 'syncflow.importedSections': 'Written',\n 'syncflow.importWarnings': 'Import warnings',\n 'syncflow.rollback': 'Rollback',\n 'syncflow.rollingBack': 'Rolling back…',\n 'syncflow.rollbackDone': 'Rolled back',\n 'syncflow.needsRestart': 'Some changes require a DSH restart to take effect',\n 'autosync.title': 'Auto Sync',\n 'autosync.description': 'When enabled, DSH will run two-way sync (pull merge + push) on a fixed interval; on startup it also triggers a download-merge (no upload) to keep local up to date. Local writes happen only when there are no conflicts or manual-decision items.',\n 'autosync.enable': 'Enable auto sync',\n 'autosync.interval': 'Sync interval',\n 'autosync.intervalHint': 'Auto download-merge on DSH startup, no upload.',\n 'autosync.interval5m': '5 min',\n 'autosync.interval15m': '15 min',\n 'autosync.interval30m': '30 min',\n 'autosync.interval60m': '60 min',\n 'autosync.interval6h': '6 hr',\n 'autosync.interval12h': '12 hr',\n 'autosync.interval24h': '24 hr',\n 'autosync.status': 'Last run: {status} ({time})',\n 'autosync.statusNever': 'Never run',\n 'autosync.nextRun': 'Next in ~{time}',\n 'autosync.failCount': '{n} consecutive failure(s)',\n 'autosync.running': 'Auto sync running…',\n 'autosync.success': 'Success',\n 'autosync.skipped': 'Skipped',\n 'autosync.failed': 'Failed',\n 'autosync.partial': 'Partial',\n 'history.title': 'Sync History',\n 'history.empty': 'No sync history yet',\n 'history.emptyHint': 'Records appear here after your first push / one-click sync / auto sync.',\n 'history.colTime': 'Time',\n 'history.colKind': 'Kind',\n 'history.colDetail': 'Detail',\n 'history.kindSnapshot': 'Snapshot',\n 'history.kindAutosync': 'Auto Sync',\n 'history.sectionCount': 'sections',\n 'history.detail': 'Detail',\n 'history.autosyncDirection': 'Direction: {direction}',\n 'history.autosyncPull': 'Pull',\n 'history.autosyncPush': 'Push',\n 'history.autosyncBoth': 'Both',\n 'history.autosyncSkipReason': 'Skip reason: {reason}',\n 'history.autosyncReasonConflict': 'Conflict',\n 'history.autosyncReasonNoRemote': 'No remote snapshot',\n 'history.autosyncReasonNotConfigured': 'No repository configured',\n 'history.autosyncReasonNetwork': 'Network issue',\n 'history.autosyncConflicted': 'Skipped conflict sections: {sections}',\n 'history.autosyncApplied': 'Applied sections: {sections}',\n 'history.autosyncError': 'Error: {error}',\n 'history.autosyncNotified': 'Notified (3 consecutive failures)',\n 'history.column.snapshot': 'Snapshot',\n 'history.column.autosync': 'Auto Sync',\n 'common.close': 'Close',\n 'common.retry': 'Retry',\n 'common.loading': 'Loading…',\n};\n\n/** 字典键联合(注册处 compile-time 校验) */\nexport type SyncKey = 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'\nimport { makeUiT, type UiT } from '../ui/i18n.ts'\nimport { SyncApi } from './sync/sync-api.ts'\nimport { SyncSettingsView } from './sync/SyncSettingsView.tsx'\nimport { en as syncEn, zh as syncZh, type SyncKey } from './sync/sync-locales.ts'\n\n/** 本插件拥有的 locale namespace。 */\nconst NS = 'config-manager'\n/** 远程同步设置区块的独立 locale namespace(独立字典文件,不与共享 locales.ts 冲突)。 */\nconst SYNC_NS = 'config-manager-sync'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Config Manager 表面文案。 */\n 'config-manager': ConfigManagerKey\n /** 远程同步设置区块文案(m-sync-ui)。 */\n 'config-manager-sync': SyncKey\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 { SyncSettingsViewProps } from './sync/SyncSettingsView.tsx'\nexport type { ConfigManagerApiError, DownloadResult, ServiceStatus, UploadResponse } from './api.ts'\nexport type { ConfigManagerKey } from './locales.ts'\nexport type { SyncKey } from './sync/sync-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 ctx.effect(() => ctx.locale.register(SYNC_NS, { zh: syncZh, en: syncEn }), 'config-manager: sync dictionaries')\n\n const t = ctx.locale.bind(NS)\n // 客户端展示层(报告/错误/进度/sync-view)翻译器:locale active 为 'en' 时用 en 目录。\n const uiT: UiT = makeUiT(ctx.locale.getLocale().active === 'en' ? 'en' : 'zh')\n const api = new ConfigManagerApi(uiT)\n const syncT = ctx.locale.bind(SYNC_NS)\n const syncApi = new SyncApi(uiT)\n\n // 单一 settings.section:备份与迁移页(内部 Export/Import/Snapshots/Sync 四 tab)。\n // 远程同步不再注册独立设置页 —— 并入主 section 的 inject 面(syncApi/syncT),\n // 由 ConfigManagerSection 渲染第 4 个 tab。避免第二个 settings.section 注册在\n // 目标 DSH 渲染 section 列表时抛错导致整页空白。\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, syncApi, syncT }),\n }, ConfigManagerSection))\n}\n"],"mappings":"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"}
|