dsh-config-manager 0.1.69 → 0.1.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (719) hide show
  1. package/README.md +59 -18
  2. package/README.zh-CN.md +29 -9
  3. package/lib/adapters/credentials.js +6 -3
  4. package/lib/adapters/file-collection.d.ts +21 -1
  5. package/lib/adapters/file-collection.js +32 -8
  6. package/lib/adapters/mcp.d.ts +12 -2
  7. package/lib/adapters/mcp.js +30 -13
  8. package/lib/adapters/plugin-files.d.ts +8 -0
  9. package/lib/adapters/plugin-files.js +36 -4
  10. package/lib/adapters/plugins.d.ts +28 -2
  11. package/lib/adapters/plugins.js +204 -55
  12. package/lib/adapters/prompts.d.ts +12 -2
  13. package/lib/adapters/prompts.js +34 -19
  14. package/lib/adapters/providers.js +5 -4
  15. package/lib/adapters/self.d.ts +20 -0
  16. package/lib/adapters/self.js +73 -0
  17. package/lib/adapters/sessions.d.ts +8 -0
  18. package/lib/adapters/sessions.js +47 -1
  19. package/lib/adapters/settings.d.ts +21 -3
  20. package/lib/adapters/settings.js +44 -7
  21. package/lib/adapters/skills.d.ts +36 -4
  22. package/lib/adapters/skills.js +222 -3
  23. package/lib/adapters/test-helpers.d.ts +31 -2
  24. package/lib/adapters/test-helpers.js +42 -5
  25. package/lib/adapters/workspaces.js +97 -5
  26. package/lib/cli/actions.d.ts +50 -3
  27. package/lib/cli/actions.js +103 -11
  28. package/lib/cli/help.d.ts +65 -0
  29. package/lib/cli/help.js +517 -0
  30. package/lib/cli/import-source.d.ts +32 -0
  31. package/lib/cli/import-source.js +178 -0
  32. package/lib/cli/index.d.ts +18 -2
  33. package/lib/cli/index.js +118 -90
  34. package/lib/cli/web/client-script.d.ts +8 -0
  35. package/lib/cli/web/client-script.js +11 -0
  36. package/lib/cli/web/http.d.ts +5 -0
  37. package/lib/cli/web/http.js +2 -1
  38. package/lib/cli/web/page.d.ts +16 -6
  39. package/lib/cli/web/page.js +102 -25
  40. package/lib/cli/web/routes.js +24 -5
  41. package/lib/cli/web/server.js +23 -2
  42. package/lib/client.d.ts +1019 -36
  43. package/lib/client.js +5522 -1564
  44. package/lib/core/analyzer.d.ts +15 -1
  45. package/lib/core/analyzer.js +114 -13
  46. package/lib/core/backup-plan.js +17 -1
  47. package/lib/core/backup.d.ts +8 -0
  48. package/lib/core/backup.js +28 -6
  49. package/lib/core/cache-cleaner.d.ts +10 -0
  50. package/lib/core/cache-cleaner.js +63 -22
  51. package/lib/core/checkpoint.d.ts +362 -0
  52. package/lib/core/checkpoint.js +1309 -0
  53. package/lib/core/journal.d.ts +37 -0
  54. package/lib/core/journal.js +69 -0
  55. package/lib/core/messages.d.ts +13 -0
  56. package/lib/core/messages.js +26 -0
  57. package/lib/core/model-tools.js +3 -0
  58. package/lib/core/patch-layers.d.ts +83 -0
  59. package/lib/core/patch-layers.js +110 -0
  60. package/lib/core/restore.d.ts +21 -0
  61. package/lib/core/restore.js +37 -3
  62. package/lib/core/rollback.js +6 -3
  63. package/lib/core/self-update.d.ts +52 -0
  64. package/lib/core/self-update.js +70 -0
  65. package/lib/core/session-health.d.ts +29 -5
  66. package/lib/core/session-health.js +28 -3
  67. package/lib/core/types.d.ts +126 -0
  68. package/lib/foreign/antigravity.d.ts +28 -0
  69. package/lib/foreign/antigravity.js +157 -0
  70. package/lib/foreign/bundle.d.ts +25 -0
  71. package/lib/foreign/bundle.js +79 -0
  72. package/lib/foreign/chatgpt.d.ts +6 -0
  73. package/lib/foreign/chatgpt.js +25 -0
  74. package/lib/foreign/claude-code.d.ts +3 -0
  75. package/lib/foreign/claude-code.js +85 -0
  76. package/lib/foreign/claude-sessions.d.ts +108 -0
  77. package/lib/foreign/claude-sessions.js +299 -0
  78. package/lib/foreign/cline.d.ts +6 -0
  79. package/lib/foreign/cline.js +27 -0
  80. package/lib/foreign/codex.d.ts +83 -0
  81. package/lib/foreign/codex.js +348 -0
  82. package/lib/foreign/continue.d.ts +9 -0
  83. package/lib/foreign/continue.js +65 -0
  84. package/lib/foreign/copilot.d.ts +39 -0
  85. package/lib/foreign/copilot.js +95 -0
  86. package/lib/foreign/crush.d.ts +11 -0
  87. package/lib/foreign/crush.js +57 -0
  88. package/lib/foreign/cursor.d.ts +87 -0
  89. package/lib/foreign/cursor.js +171 -0
  90. package/lib/foreign/dsh.d.ts +30 -0
  91. package/lib/foreign/dsh.js +101 -0
  92. package/lib/foreign/dsh4.d.ts +3 -0
  93. package/lib/foreign/dsh4.js +13 -0
  94. package/lib/foreign/gemini.d.ts +7 -0
  95. package/lib/foreign/gemini.js +44 -0
  96. package/lib/foreign/goose.d.ts +11 -0
  97. package/lib/foreign/goose.js +53 -0
  98. package/lib/foreign/grokbuild.d.ts +8 -0
  99. package/lib/foreign/grokbuild.js +25 -0
  100. package/lib/foreign/hermes.d.ts +2 -0
  101. package/lib/foreign/hermes.js +78 -0
  102. package/lib/foreign/kernel.d.ts +132 -0
  103. package/lib/foreign/kernel.js +569 -0
  104. package/lib/foreign/kilocode.d.ts +11 -0
  105. package/lib/foreign/kilocode.js +51 -0
  106. package/lib/foreign/kimi.d.ts +7 -0
  107. package/lib/foreign/kimi.js +47 -0
  108. package/lib/foreign/mimocode.d.ts +11 -0
  109. package/lib/foreign/mimocode.js +51 -0
  110. package/lib/foreign/openclaw.d.ts +7 -0
  111. package/lib/foreign/openclaw.js +46 -0
  112. package/lib/foreign/opencode.d.ts +11 -0
  113. package/lib/foreign/opencode.js +52 -0
  114. package/lib/foreign/pi.d.ts +7 -0
  115. package/lib/foreign/pi.js +48 -0
  116. package/lib/foreign/platform-paths.d.ts +66 -0
  117. package/lib/foreign/platform-paths.js +141 -0
  118. package/lib/foreign/qoder.d.ts +10 -0
  119. package/lib/foreign/qoder.js +49 -0
  120. package/lib/foreign/qwen.d.ts +7 -0
  121. package/lib/foreign/qwen.js +45 -0
  122. package/lib/foreign/read-antigravity.d.ts +57 -0
  123. package/lib/foreign/read-antigravity.js +504 -0
  124. package/lib/foreign/read-chatgpt.d.ts +20 -0
  125. package/lib/foreign/read-chatgpt.js +509 -0
  126. package/lib/foreign/read-claude-code.d.ts +24 -0
  127. package/lib/foreign/read-claude-code.js +234 -0
  128. package/lib/foreign/read-cline.d.ts +53 -0
  129. package/lib/foreign/read-cline.js +479 -0
  130. package/lib/foreign/read-codex.d.ts +75 -0
  131. package/lib/foreign/read-codex.js +842 -0
  132. package/lib/foreign/read-continue.d.ts +87 -0
  133. package/lib/foreign/read-continue.js +489 -0
  134. package/lib/foreign/read-copilot.d.ts +42 -0
  135. package/lib/foreign/read-copilot.js +267 -0
  136. package/lib/foreign/read-crush.d.ts +54 -0
  137. package/lib/foreign/read-crush.js +478 -0
  138. package/lib/foreign/read-cursor.d.ts +141 -0
  139. package/lib/foreign/read-cursor.js +705 -0
  140. package/lib/foreign/read-dsh.d.ts +43 -0
  141. package/lib/foreign/read-dsh.js +205 -0
  142. package/lib/foreign/read-dsh4.d.ts +14 -0
  143. package/lib/foreign/read-dsh4.js +27 -0
  144. package/lib/foreign/read-gemini.d.ts +55 -0
  145. package/lib/foreign/read-gemini.js +273 -0
  146. package/lib/foreign/read-goose.d.ts +25 -0
  147. package/lib/foreign/read-goose.js +322 -0
  148. package/lib/foreign/read-grokbuild.d.ts +34 -0
  149. package/lib/foreign/read-grokbuild.js +455 -0
  150. package/lib/foreign/read-hermes.d.ts +74 -0
  151. package/lib/foreign/read-hermes.js +690 -0
  152. package/lib/foreign/read-kilocode.d.ts +17 -0
  153. package/lib/foreign/read-kilocode.js +46 -0
  154. package/lib/foreign/read-kimi.d.ts +63 -0
  155. package/lib/foreign/read-kimi.js +719 -0
  156. package/lib/foreign/read-mimocode.d.ts +12 -0
  157. package/lib/foreign/read-mimocode.js +56 -0
  158. package/lib/foreign/read-openclaw.d.ts +51 -0
  159. package/lib/foreign/read-openclaw.js +445 -0
  160. package/lib/foreign/read-opencode.d.ts +150 -0
  161. package/lib/foreign/read-opencode.js +896 -0
  162. package/lib/foreign/read-pi.d.ts +56 -0
  163. package/lib/foreign/read-pi.js +411 -0
  164. package/lib/foreign/read-qoder.d.ts +54 -0
  165. package/lib/foreign/read-qoder.js +317 -0
  166. package/lib/foreign/read-qwen.d.ts +40 -0
  167. package/lib/foreign/read-qwen.js +326 -0
  168. package/lib/foreign/read-reasonix.d.ts +66 -0
  169. package/lib/foreign/read-reasonix.js +537 -0
  170. package/lib/foreign/read-teleagent.d.ts +15 -0
  171. package/lib/foreign/read-teleagent.js +68 -0
  172. package/lib/foreign/read-trae.d.ts +67 -0
  173. package/lib/foreign/read-trae.js +492 -0
  174. package/lib/foreign/read-vibe.d.ts +28 -0
  175. package/lib/foreign/read-vibe.js +364 -0
  176. package/lib/foreign/read-workbuddy.d.ts +49 -0
  177. package/lib/foreign/read-workbuddy.js +346 -0
  178. package/lib/foreign/read-zcode.d.ts +12 -0
  179. package/lib/foreign/read-zcode.js +38 -0
  180. package/lib/foreign/read-zed.d.ts +30 -0
  181. package/lib/foreign/read-zed.js +473 -0
  182. package/lib/foreign/reasonix.d.ts +6 -0
  183. package/lib/foreign/reasonix.js +20 -0
  184. package/lib/foreign/registry.d.ts +196 -0
  185. package/lib/foreign/registry.js +573 -0
  186. package/lib/foreign/session-ir.d.ts +186 -0
  187. package/lib/foreign/session-ir.js +427 -0
  188. package/lib/foreign/session-read.d.ts +102 -0
  189. package/lib/foreign/session-read.js +254 -0
  190. package/lib/foreign/session-source.d.ts +216 -0
  191. package/lib/foreign/session-source.js +453 -0
  192. package/lib/foreign/source-modules.d.ts +45 -0
  193. package/lib/foreign/source-modules.js +52 -0
  194. package/lib/foreign/sqlite.d.ts +61 -0
  195. package/lib/foreign/sqlite.js +404 -0
  196. package/lib/foreign/teleagent.d.ts +11 -0
  197. package/lib/foreign/teleagent.js +53 -0
  198. package/lib/foreign/trae.d.ts +6 -0
  199. package/lib/foreign/trae.js +20 -0
  200. package/lib/foreign/truth-table.d.ts +62 -0
  201. package/lib/foreign/truth-table.js +333 -0
  202. package/lib/foreign/types.d.ts +272 -0
  203. package/lib/foreign/types.js +2 -0
  204. package/lib/foreign/vibe.d.ts +6 -0
  205. package/lib/foreign/vibe.js +23 -0
  206. package/lib/foreign/workbuddy.d.ts +7 -0
  207. package/lib/foreign/workbuddy.js +45 -0
  208. package/lib/foreign/zcode.d.ts +11 -0
  209. package/lib/foreign/zcode.js +51 -0
  210. package/lib/foreign/zed.d.ts +11 -0
  211. package/lib/foreign/zed.js +53 -0
  212. package/lib/index.d.ts +154 -13
  213. package/lib/index.js +661 -84
  214. package/lib/market/github-repos.d.ts +28 -0
  215. package/lib/market/github-repos.js +43 -1
  216. package/lib/market/types.d.ts +1 -3
  217. package/lib/profiles/dsh-profile-manager.d.ts +54 -2
  218. package/lib/profiles/dsh-profile-manager.js +182 -11
  219. package/lib/profiles/dsh-profile-shared.d.ts +47 -0
  220. package/lib/profiles/dsh-profile-shared.js +15 -1
  221. package/lib/profiles/index.d.ts +1 -1
  222. package/lib/profiles/index.js +1 -1
  223. package/lib/routes/consult.js +51 -5
  224. package/lib/routes/foreign-context.d.ts +43 -0
  225. package/lib/routes/foreign-context.js +65 -0
  226. package/lib/routes/foreign.d.ts +11 -0
  227. package/lib/routes/foreign.js +208 -0
  228. package/lib/routes/import.d.ts +8 -0
  229. package/lib/routes/import.js +22 -1
  230. package/lib/routes/index.d.ts +2 -2
  231. package/lib/routes/index.js +4 -0
  232. package/lib/routes/kit.d.ts +4 -3
  233. package/lib/routes/market.js +0 -1
  234. package/lib/routes/prefs.d.ts +2 -1
  235. package/lib/routes/prefs.js +14 -2
  236. package/lib/routes/recovery.js +363 -3
  237. package/lib/routes/session-export.d.ts +117 -0
  238. package/lib/routes/session-export.js +270 -0
  239. package/lib/routes/snapshots.js +12 -2
  240. package/lib/routes/sync.js +82 -10
  241. package/lib/security/redaction.d.ts +14 -0
  242. package/lib/security/redaction.js +24 -9
  243. package/lib/security/secret-scanner.d.ts +27 -0
  244. package/lib/security/secret-scanner.js +54 -1
  245. package/lib/sync/autosync-scheduler.d.ts +13 -1
  246. package/lib/sync/autosync-scheduler.js +49 -26
  247. package/lib/sync/backup-files.js +6 -0
  248. package/lib/sync/gist/gist-transport.d.ts +91 -0
  249. package/lib/sync/gist/gist-transport.js +406 -0
  250. package/lib/sync/gist/messages.d.ts +22 -0
  251. package/lib/sync/gist/messages.js +46 -0
  252. package/lib/sync/s3/messages.d.ts +53 -0
  253. package/lib/sync/s3/messages.js +83 -0
  254. package/lib/sync/s3/s3-providers.d.ts +78 -0
  255. package/lib/sync/s3/s3-providers.js +156 -0
  256. package/lib/sync/s3/s3-transport.d.ts +126 -0
  257. package/lib/sync/s3/s3-transport.js +551 -0
  258. package/lib/sync/s3/sigv4.d.ts +107 -0
  259. package/lib/sync/s3/sigv4.js +196 -0
  260. package/lib/sync/sync-config.d.ts +250 -4
  261. package/lib/sync/sync-config.js +658 -57
  262. package/lib/sync/sync-engine.d.ts +1 -0
  263. package/lib/sync/sync-engine.js +4 -2
  264. package/lib/sync/sync-history.d.ts +1 -1
  265. package/lib/sync/webdav/webdav-transport.d.ts +31 -3
  266. package/lib/sync/webdav/webdav-transport.js +102 -18
  267. package/lib/ui/commands.d.ts +4 -3
  268. package/lib/ui/commands.js +41 -9
  269. package/lib/ui/disk-usage-view.d.ts +44 -0
  270. package/lib/ui/disk-usage-view.js +55 -1
  271. package/lib/ui/dsh-profiles-view.d.ts +53 -0
  272. package/lib/ui/dsh-profiles-view.js +56 -0
  273. package/lib/ui/foreign-view.d.ts +162 -0
  274. package/lib/ui/foreign-view.js +225 -0
  275. package/lib/ui/i18n.d.ts +77 -0
  276. package/lib/ui/i18n.js +164 -0
  277. package/lib/ui/session-inventory-view.d.ts +106 -0
  278. package/lib/ui/session-inventory-view.js +58 -0
  279. package/lib/ui/session-layout-view.d.ts +265 -0
  280. package/lib/ui/session-layout-view.js +271 -0
  281. package/lib/ui/sync-repository-picker.d.ts +98 -0
  282. package/lib/ui/sync-repository-picker.js +145 -0
  283. package/lib/ui/sync-settings-view.d.ts +143 -4
  284. package/lib/ui/sync-settings-view.js +231 -7
  285. package/lib/ui/types.d.ts +47 -0
  286. package/lib/utils/asar-read.d.ts +113 -0
  287. package/lib/utils/asar-read.js +523 -0
  288. package/lib/utils/env-lock.js +7 -2
  289. package/lib/utils/patch-yaml.d.ts +25 -0
  290. package/lib/utils/patch-yaml.js +62 -0
  291. package/lib/utils/paths.d.ts +10 -1
  292. package/lib/utils/paths.js +24 -3
  293. package/lib/utils/recursive-walk.js +12 -13
  294. package/lib/utils/session-format.d.ts +35 -2
  295. package/lib/utils/session-format.js +131 -5
  296. package/lib/utils/session-health-scan.d.ts +7 -1
  297. package/lib/utils/session-health-scan.js +369 -12
  298. package/lib/utils/session-layout-repair-service.d.ts +98 -0
  299. package/lib/utils/session-layout-repair-service.js +457 -0
  300. package/lib/utils/session-log-repair.d.ts +27 -0
  301. package/lib/utils/session-log-repair.js +233 -62
  302. package/lib/utils/session-repair-service.d.ts +32 -3
  303. package/lib/utils/session-repair-service.js +148 -9
  304. package/lib/utils/session-row-facts.d.ts +73 -0
  305. package/lib/utils/session-row-facts.js +182 -0
  306. package/lib/utils/session-verify.d.ts +118 -0
  307. package/lib/utils/session-verify.js +705 -0
  308. package/lib/utils/shared-constants.d.ts +59 -0
  309. package/lib/utils/shared-constants.js +71 -0
  310. package/package.json +1 -1
  311. package/src/adapters/credentials.test.ts +27 -0
  312. package/src/adapters/credentials.ts +6 -3
  313. package/src/adapters/file-collection.ts +33 -8
  314. package/src/adapters/files.test.ts +222 -0
  315. package/src/adapters/mcp.test.ts +43 -0
  316. package/src/adapters/mcp.ts +37 -14
  317. package/src/adapters/plugin-files.ts +34 -4
  318. package/src/adapters/plugins.test.ts +241 -0
  319. package/src/adapters/plugins.ts +201 -53
  320. package/src/adapters/prompts.test.ts +49 -0
  321. package/src/adapters/prompts.ts +41 -20
  322. package/src/adapters/providers.test.ts +16 -0
  323. package/src/adapters/providers.ts +4 -3
  324. package/src/adapters/self.test.ts +77 -0
  325. package/src/adapters/self.ts +75 -0
  326. package/src/adapters/sessions.test.ts +77 -0
  327. package/src/adapters/sessions.ts +47 -1
  328. package/src/adapters/settings.test.ts +78 -0
  329. package/src/adapters/settings.ts +42 -6
  330. package/src/adapters/skills.ts +221 -3
  331. package/src/adapters/test-helpers.ts +43 -5
  332. package/src/adapters/workspaces-dup-id.test.ts +144 -0
  333. package/src/adapters/workspaces.test.ts +10 -0
  334. package/src/adapters/workspaces.ts +97 -5
  335. package/src/cli/actions.test.ts +117 -2
  336. package/src/cli/actions.ts +132 -12
  337. package/src/cli/help.ts +570 -0
  338. package/src/cli/import-source.test.ts +193 -0
  339. package/src/cli/import-source.ts +229 -0
  340. package/src/cli/index.ts +129 -94
  341. package/src/cli/web/client-script.ts +12 -0
  342. package/src/cli/web/console-fixes.test.ts +36 -0
  343. package/src/cli/web/http.ts +7 -1
  344. package/src/cli/web/page.ts +108 -25
  345. package/src/cli/web/routes.ts +23 -4
  346. package/src/cli/web/script-anchor.test.ts +33 -0
  347. package/src/cli/web/server.ts +28 -2
  348. package/src/cli/web/web.test.ts +447 -4
  349. package/src/client/ConfigManagerSection.tsx +118 -63
  350. package/src/client/about/AboutPanel.tsx +42 -3
  351. package/src/client/about/PluginUpdateDialog.tsx +185 -0
  352. package/src/client/about/ReleaseBody.tsx +144 -0
  353. package/src/client/about/ReleaseNotesDialog.tsx +3 -130
  354. package/src/client/about/about-view.ts +7 -5
  355. package/src/client/about/plugin-update-view.test.ts +25 -0
  356. package/src/client/about/plugin-update-view.ts +26 -0
  357. package/src/client/about/release-notes-view.test.ts +33 -0
  358. package/src/client/about/release-notes-view.ts +34 -0
  359. package/src/client/api.ts +145 -1
  360. package/src/client/common/Icon.tsx +3 -0
  361. package/src/client/common/RunsCenter.tsx +8 -2
  362. package/src/client/common/Select.tsx +9 -2
  363. package/src/client/common/info-hint-guard.test.ts +63 -18
  364. package/src/client/common/plan-text-redaction.test.ts +193 -8
  365. package/src/client/common/routes.ts +15 -0
  366. package/src/client/config-manager.module.css +506 -354
  367. package/src/client/css-scale-guard.test.ts +122 -0
  368. package/src/client/css-token-guard.test.ts +82 -0
  369. package/src/client/environment/EnvironmentPanel.tsx +45 -16
  370. package/src/client/{snapshots → environment/maintenance}/DiskUsageCard.tsx +21 -17
  371. package/src/client/environment/profiles-incomplete-ui.test.ts +103 -0
  372. package/src/client/export/ExportView.tsx +9 -2
  373. package/src/client/{snapshots → home}/BackupScheduleCard.tsx +13 -4
  374. package/src/client/home/HomePanel.tsx +69 -157
  375. package/src/client/icon-layer-guard.test.ts +1 -1
  376. package/src/client/import/ForeignImportView.tsx +318 -0
  377. package/src/client/import/ImportWizardView.tsx +3 -1
  378. package/src/client/import/foreign-import-view-guard.test.ts +195 -0
  379. package/src/client/import/import-file-select.test.ts +6 -6
  380. package/src/client/import/import-wizard-steps.tsx +17 -1
  381. package/src/client/import/use-import-wizard-controller.ts +3 -3
  382. package/src/client/index.ts +1 -1
  383. package/src/client/library/LibraryActions.tsx +31 -34
  384. package/src/client/library/LibraryPanel.tsx +4 -1
  385. package/src/client/{snapshots → library}/RestorePlanView.tsx +1 -1
  386. package/src/client/{snapshots → library}/files-layout.test.ts +2 -2
  387. package/src/client/{snapshots → library}/report-dismiss.test.ts +26 -3
  388. package/src/client/library/task-panel-visibility.test.ts +25 -17
  389. package/src/client/locales.ts +278 -36
  390. package/src/client/lucide-icons.d.ts +1 -0
  391. package/src/client/market/MarketPanel.tsx +11 -2
  392. package/src/client/recovery/IncompleteCopiesSection.tsx +132 -0
  393. package/src/client/recovery/RecoveryPanel.tsx +486 -59
  394. package/src/client/recovery/recovery-api.ts +30 -0
  395. package/src/client/recovery/recovery-incomplete-copies.test.ts +151 -0
  396. package/src/client/recovery/recovery-locales.test.ts +88 -0
  397. package/src/client/recovery/recovery-locales.ts +321 -6
  398. package/src/client/recovery/recovery-panel-layout.test.ts +52 -0
  399. package/src/client/recovery/recovery-view.ts +92 -2
  400. package/src/client/run-store.test.ts +201 -89
  401. package/src/client/run-store.ts +114 -143
  402. package/src/client/session-export/session-export-view.test.ts +103 -0
  403. package/src/client/session-export/session-export-view.ts +118 -0
  404. package/src/client/sync/ChannelConfigDialog.tsx +219 -14
  405. package/src/client/sync/SyncChannelEntryCard.tsx +52 -4
  406. package/src/client/sync/SyncLogList.tsx +1 -1
  407. package/src/client/sync/SyncPanel.tsx +166 -102
  408. package/src/client/sync/SyncRepositoryPicker.tsx +216 -0
  409. package/src/client/sync/SyncSettingsView.test.ts +6 -1
  410. package/src/client/sync/history-model.test.ts +94 -57
  411. package/src/client/sync/history-model.ts +44 -25
  412. package/src/client/sync/sync-api.test.ts +56 -0
  413. package/src/client/sync/sync-api.ts +92 -0
  414. package/src/client/sync/sync-locales.ts +162 -2
  415. package/src/client/sync/sync-view.test.ts +3 -8
  416. package/src/client/sync/sync-view.ts +111 -21
  417. package/src/core/analyzer-cache.test.ts +47 -0
  418. package/src/core/analyzer.ts +115 -14
  419. package/src/core/backup-plan.test.ts +35 -0
  420. package/src/core/backup-plan.ts +19 -1
  421. package/src/core/backup.test.ts +37 -1
  422. package/src/core/backup.ts +27 -6
  423. package/src/core/cache-cleaner.test.ts +120 -1
  424. package/src/core/cache-cleaner.ts +59 -22
  425. package/src/core/checkpoint.test.ts +665 -0
  426. package/src/core/checkpoint.ts +1614 -0
  427. package/src/core/credential-plan-consistency.test.ts +93 -0
  428. package/src/core/incident-wiring.test.ts +6 -2
  429. package/src/core/journal.test.ts +70 -0
  430. package/src/core/journal.ts +68 -0
  431. package/src/core/messages.ts +26 -0
  432. package/src/core/model-tools.ts +3 -0
  433. package/src/core/patch-layers.test.ts +94 -0
  434. package/src/core/patch-layers.ts +150 -0
  435. package/src/core/restore.ts +59 -3
  436. package/src/core/rollback.ts +6 -3
  437. package/src/core/section-content-consistency.test.ts +185 -0
  438. package/src/core/self-update.test.ts +110 -0
  439. package/src/core/self-update.ts +118 -0
  440. package/src/core/session-health.test.ts +91 -1
  441. package/src/core/session-health.ts +56 -9
  442. package/src/core/types.ts +127 -1
  443. package/src/foreign/antigravity.test.ts +271 -0
  444. package/src/foreign/antigravity.ts +188 -0
  445. package/src/foreign/bundle.ts +108 -0
  446. package/src/foreign/chatgpt.test.ts +279 -0
  447. package/src/foreign/chatgpt.ts +30 -0
  448. package/src/foreign/claude-code.test.ts +234 -0
  449. package/src/foreign/claude-code.ts +106 -0
  450. package/src/foreign/claude-sessions-bytes.test.ts +227 -0
  451. package/src/foreign/claude-sessions.test.ts +180 -0
  452. package/src/foreign/claude-sessions.ts +461 -0
  453. package/src/foreign/cline.test.ts +274 -0
  454. package/src/foreign/cline.ts +32 -0
  455. package/src/foreign/codex.test.ts +585 -0
  456. package/src/foreign/codex.ts +409 -0
  457. package/src/foreign/continue.test.ts +365 -0
  458. package/src/foreign/continue.ts +73 -0
  459. package/src/foreign/copilot.test.ts +273 -0
  460. package/src/foreign/copilot.ts +133 -0
  461. package/src/foreign/crush.test.ts +234 -0
  462. package/src/foreign/crush.ts +66 -0
  463. package/src/foreign/cursor.test.ts +509 -0
  464. package/src/foreign/cursor.ts +259 -0
  465. package/src/foreign/dsh.test.ts +198 -0
  466. package/src/foreign/dsh.ts +117 -0
  467. package/src/foreign/dsh4.test.ts +127 -0
  468. package/src/foreign/dsh4.ts +15 -0
  469. package/src/foreign/file-budget.test.ts +256 -0
  470. package/src/foreign/fixtures/antigravity/README.md +18 -0
  471. package/src/foreign/fixtures/antigravity/basic/gemini/antigravity/mcp_config.json +13 -0
  472. package/src/foreign/fixtures/antigravity/basic/gemini/config/mcp_config.json +24 -0
  473. package/src/foreign/fixtures/antigravity/empty/gemini/antigravity/mcp_config.json +0 -0
  474. package/src/foreign/fixtures/antigravity/empty/gemini/antigravity/mcp_oauth_tokens.json +0 -0
  475. package/src/foreign/fixtures/antigravity/empty/gemini/config/mcp_config.json +0 -0
  476. package/src/foreign/fixtures/codex/README.md +31 -0
  477. package/src/foreign/fixtures/codex/basic/.agents/skills/hello/SKILL.md +6 -0
  478. package/src/foreign/fixtures/codex/basic/.agents/skills/wrapper/nested/SKILL.md +6 -0
  479. package/src/foreign/fixtures/codex/basic/.codex/AGENTS.md +4 -0
  480. package/src/foreign/fixtures/codex/basic/.codex/config.toml +28 -0
  481. package/src/foreign/fixtures/codex/malformed/.codex/config.toml +3 -0
  482. package/src/foreign/fixtures/codex/override/.codex/AGENTS.md +1 -0
  483. package/src/foreign/fixtures/codex/override/.codex/AGENTS.override.md +3 -0
  484. package/src/foreign/fixtures/codex/sessions/.codex/archived_sessions/rollout-2026-10-05T09-00-00-22222222-2222-4222-8222-222222222222.jsonl +2 -0
  485. package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T10-00-00-11111111-1111-4111-8111-111111111111.jsonl +15 -0
  486. package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T11-00-00-33333333-3333-4333-8333-333333333333.jsonl +2 -0
  487. package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T11-30-00-55555555-5555-4555-8555-555555555555.jsonl +2 -0
  488. package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T12-00-00-44444444-4444-4444-8444-444444444444.jsonl +2 -0
  489. package/src/foreign/fixtures/codex/sessions/.codex/sessions/notes.jsonl +1 -0
  490. package/src/foreign/fixtures/copilot/README.md +22 -0
  491. package/src/foreign/fixtures/copilot/basic/copilot-instructions.md +3 -0
  492. package/src/foreign/fixtures/copilot/basic/instructions/empty.instructions.md +1 -0
  493. package/src/foreign/fixtures/copilot/basic/instructions/repo.instructions.md +5 -0
  494. package/src/foreign/fixtures/copilot/basic/mcp-config.json +24 -0
  495. package/src/foreign/fixtures/copilot/basic/skills/hello/SKILL.md +6 -0
  496. package/src/foreign/fixtures/copilot/overridden/mcp-config.json +10 -0
  497. package/src/foreign/fixtures/cursor/README.md +17 -0
  498. package/src/foreign/fixtures/cursor/alt/.cursor/mcp.json +5 -0
  499. package/src/foreign/fixtures/cursor/basic/.cursor/mcp.json +18 -0
  500. package/src/foreign/fixtures/cursor/basic/.cursor/rules/agent.mdc +5 -0
  501. package/src/foreign/fixtures/cursor/basic/.cursor/rules/always.mdc +6 -0
  502. package/src/foreign/fixtures/cursor/basic/.cursor/rules/auto.mdc +7 -0
  503. package/src/foreign/fixtures/cursor/basic/.cursor/rules/manual.mdc +3 -0
  504. package/src/foreign/fixtures/cursor/basic/.cursor/skills/.hidden/SKILL.md +6 -0
  505. package/src/foreign/fixtures/cursor/basic/.cursor/skills/hello/SKILL.md +6 -0
  506. package/src/foreign/fixtures/cursor/basic/.cursor/skills/wrapper/nested/SKILL.md +6 -0
  507. package/src/foreign/fixtures/cursor/basic/.cursor/skills/wrapper/nested/notes.md +1 -0
  508. package/src/foreign/fixtures/cursor/basic/.cursorrules +1 -0
  509. package/src/foreign/fixtures/cursor/basic/project/.cursor/mcp.json +9 -0
  510. package/src/foreign/fixtures/cursor/basic/project/.cursor/rules/project-always.mdc +5 -0
  511. package/src/foreign/fixtures/cursor/basic/project/.cursor/skills/hello/SKILL.md +6 -0
  512. package/src/foreign/fixtures/cursor/basic/project/.cursorrules +1 -0
  513. package/src/foreign/fixtures/cursor/empty/.cursor/mcp.json +0 -0
  514. package/src/foreign/fixtures/cursor/malformed/.cursor/mcp.json +3 -0
  515. package/src/foreign/fixtures/cursor/malformed/.cursor/rules/broken.mdc +6 -0
  516. package/src/foreign/fixtures/cursor/shape/.cursor/mcp.json +3 -0
  517. package/src/foreign/fixtures/hermes/README.md +14 -0
  518. package/src/foreign/fixtures/hermes/basic/SOUL.md +3 -0
  519. package/src/foreign/fixtures/hermes/basic/config.yaml +48 -0
  520. package/src/foreign/fixtures/hermes/basic/dotenv.fixture +1 -0
  521. package/src/foreign/fixtures/hermes/basic/memories/MEMORY.md +1 -0
  522. package/src/foreign/fixtures/hermes/basic/memories/USER.md +1 -0
  523. package/src/foreign/fixtures/hermes/basic/skills/se-team-design/SKILL.md +6 -0
  524. package/src/foreign/fixtures/hermes/basic/skills/se-team-design/examples/usage.md +1 -0
  525. package/src/foreign/fixtures/hermes/basic/skills/software-development/dogfood/SKILL.md +6 -0
  526. package/src/foreign/fixtures/hermes/basic/skills/software-development/dogfood/notes.md +1 -0
  527. package/src/foreign/fixtures/hermes/basic/state.db +1 -0
  528. package/src/foreign/fixtures/hermes/empty/config.yaml +0 -0
  529. package/src/foreign/gemini.test.ts +291 -0
  530. package/src/foreign/gemini.ts +52 -0
  531. package/src/foreign/goose.test.ts +196 -0
  532. package/src/foreign/goose.ts +62 -0
  533. package/src/foreign/grokbuild.test.ts +246 -0
  534. package/src/foreign/grokbuild.ts +30 -0
  535. package/src/foreign/hermes.test.ts +545 -0
  536. package/src/foreign/hermes.ts +86 -0
  537. package/src/foreign/kernel-credentials.test.ts +88 -0
  538. package/src/foreign/kernel-workspaces.test.ts +88 -0
  539. package/src/foreign/kernel.ts +584 -0
  540. package/src/foreign/kilocode.test.ts +186 -0
  541. package/src/foreign/kilocode.ts +60 -0
  542. package/src/foreign/kimi.test.ts +259 -0
  543. package/src/foreign/kimi.ts +55 -0
  544. package/src/foreign/mcp-value-shape.test.ts +286 -0
  545. package/src/foreign/mimocode.test.ts +178 -0
  546. package/src/foreign/mimocode.ts +60 -0
  547. package/src/foreign/openclaw.test.ts +248 -0
  548. package/src/foreign/openclaw.ts +54 -0
  549. package/src/foreign/opencode.test.ts +376 -0
  550. package/src/foreign/opencode.ts +61 -0
  551. package/src/foreign/pi.test.ts +275 -0
  552. package/src/foreign/pi.ts +56 -0
  553. package/src/foreign/platform-paths.ts +156 -0
  554. package/src/foreign/qoder.test.ts +266 -0
  555. package/src/foreign/qoder.ts +57 -0
  556. package/src/foreign/qwen.test.ts +203 -0
  557. package/src/foreign/qwen.ts +53 -0
  558. package/src/foreign/read-antigravity.ts +569 -0
  559. package/src/foreign/read-chatgpt.ts +506 -0
  560. package/src/foreign/read-claude-code.ts +264 -0
  561. package/src/foreign/read-cline.ts +517 -0
  562. package/src/foreign/read-codex.ts +823 -0
  563. package/src/foreign/read-continue.ts +557 -0
  564. package/src/foreign/read-copilot.ts +304 -0
  565. package/src/foreign/read-crush.ts +503 -0
  566. package/src/foreign/read-cursor.ts +778 -0
  567. package/src/foreign/read-dsh.ts +215 -0
  568. package/src/foreign/read-dsh4.ts +35 -0
  569. package/src/foreign/read-gemini.ts +306 -0
  570. package/src/foreign/read-goose.ts +333 -0
  571. package/src/foreign/read-grokbuild.ts +475 -0
  572. package/src/foreign/read-hermes.ts +724 -0
  573. package/src/foreign/read-kilocode.ts +55 -0
  574. package/src/foreign/read-kimi.ts +768 -0
  575. package/src/foreign/read-mimocode.ts +66 -0
  576. package/src/foreign/read-openclaw.ts +505 -0
  577. package/src/foreign/read-opencode.ts +994 -0
  578. package/src/foreign/read-pi.ts +459 -0
  579. package/src/foreign/read-qoder.ts +351 -0
  580. package/src/foreign/read-qwen.ts +342 -0
  581. package/src/foreign/read-reasonix.ts +590 -0
  582. package/src/foreign/read-teleagent.ts +82 -0
  583. package/src/foreign/read-trae.ts +488 -0
  584. package/src/foreign/read-vibe.ts +353 -0
  585. package/src/foreign/read-workbuddy.ts +374 -0
  586. package/src/foreign/read-zcode.ts +48 -0
  587. package/src/foreign/read-zed.ts +479 -0
  588. package/src/foreign/reasonix.test.ts +336 -0
  589. package/src/foreign/reasonix.ts +25 -0
  590. package/src/foreign/registry.test.ts +377 -0
  591. package/src/foreign/registry.ts +750 -0
  592. package/src/foreign/session-ir.test.ts +189 -0
  593. package/src/foreign/session-ir.ts +614 -0
  594. package/src/foreign/session-read.ts +295 -0
  595. package/src/foreign/session-source.ts +625 -0
  596. package/src/foreign/skill-file-caps.test.ts +171 -0
  597. package/src/foreign/source-modules.ts +86 -0
  598. package/src/foreign/source-registry.test.ts +190 -0
  599. package/src/foreign/sqlite.test.ts +313 -0
  600. package/src/foreign/sqlite.ts +446 -0
  601. package/src/foreign/teleagent.test.ts +147 -0
  602. package/src/foreign/teleagent.ts +62 -0
  603. package/src/foreign/trae.test.ts +316 -0
  604. package/src/foreign/trae.ts +25 -0
  605. package/src/foreign/truncation-report.test.ts +238 -0
  606. package/src/foreign/truth-table.ts +453 -0
  607. package/src/foreign/types.ts +312 -0
  608. package/src/foreign/vibe.test.ts +209 -0
  609. package/src/foreign/vibe.ts +28 -0
  610. package/src/foreign/workbuddy.test.ts +207 -0
  611. package/src/foreign/workbuddy.ts +53 -0
  612. package/src/foreign/zcode.test.ts +224 -0
  613. package/src/foreign/zcode.ts +60 -0
  614. package/src/foreign/zed.test.ts +240 -0
  615. package/src/foreign/zed.ts +62 -0
  616. package/src/index.facade.test.ts +254 -16
  617. package/src/index.ts +704 -82
  618. package/src/market/github-repos.test.ts +98 -1
  619. package/src/market/github-repos.ts +63 -1
  620. package/src/market/types.ts +3 -3
  621. package/src/profiles/dsh-profile-incomplete-copy.test.ts +177 -0
  622. package/src/profiles/dsh-profile-manager.test.ts +37 -0
  623. package/src/profiles/dsh-profile-manager.ts +188 -13
  624. package/src/profiles/dsh-profile-shared.ts +55 -1
  625. package/src/profiles/index.ts +2 -1
  626. package/src/routes/consult.ts +53 -4
  627. package/src/routes/foreign-context.ts +89 -0
  628. package/src/routes/foreign.test.ts +443 -0
  629. package/src/routes/foreign.ts +226 -0
  630. package/src/routes/import.ts +23 -1
  631. package/src/routes/index.ts +6 -2
  632. package/src/routes/kit.ts +4 -3
  633. package/src/routes/market.ts +0 -1
  634. package/src/routes/prefs.ts +15 -1
  635. package/src/routes/recovery.test.ts +167 -0
  636. package/src/routes/recovery.ts +331 -1
  637. package/src/routes/session-export.ts +308 -0
  638. package/src/routes/snapshots.ts +12 -2
  639. package/src/routes/sync.ts +91 -7
  640. package/src/security/redaction.test.ts +149 -0
  641. package/src/security/redaction.ts +25 -9
  642. package/src/security/secret-scanner.test.ts +186 -0
  643. package/src/security/secret-scanner.ts +57 -1
  644. package/src/sync/autosync-risk-tier.test.ts +61 -0
  645. package/src/sync/autosync-scheduler.test.ts +48 -1
  646. package/src/sync/autosync-scheduler.ts +50 -26
  647. package/src/sync/backup-files.ts +5 -0
  648. package/src/sync/gist/gist-msgkeys-catalog.test.ts +33 -0
  649. package/src/sync/gist/gist-msgkeys.test.ts +71 -0
  650. package/src/sync/gist/gist-transport.test.ts +308 -0
  651. package/src/sync/gist/gist-transport.ts +550 -0
  652. package/src/sync/gist/messages.ts +49 -0
  653. package/src/sync/retention-prune-all-off.test.ts +50 -0
  654. package/src/sync/s3/cloud-config.test.ts +283 -0
  655. package/src/sync/s3/messages.ts +102 -0
  656. package/src/sync/s3/s3-delete-index-404.test.ts +170 -0
  657. package/src/sync/s3/s3-delete-index-unreadable.test.ts +141 -0
  658. package/src/sync/s3/s3-msgkeys.test.ts +101 -0
  659. package/src/sync/s3/s3-providers.ts +213 -0
  660. package/src/sync/s3/s3-transport.test.ts +394 -0
  661. package/src/sync/s3/s3-transport.ts +651 -0
  662. package/src/sync/s3/s3-upload-index-404.test.ts +171 -0
  663. package/src/sync/s3/sigv4.test.ts +219 -0
  664. package/src/sync/s3/sigv4.ts +283 -0
  665. package/src/sync/sync-config.test.ts +237 -5
  666. package/src/sync/sync-config.ts +841 -52
  667. package/src/sync/sync-engine-download-tombstone.test.ts +73 -0
  668. package/src/sync/sync-engine.ts +5 -3
  669. package/src/sync/sync-history.ts +1 -1
  670. package/src/sync/webdav/webdav-delete-index-404.test.ts +178 -0
  671. package/src/sync/webdav/webdav-delete-index-unreadable.test.ts +143 -0
  672. package/src/sync/webdav/webdav-msgkeys.test.ts +53 -0
  673. package/src/sync/webdav/webdav-transport.test.ts +9 -5
  674. package/src/sync/webdav/webdav-transport.ts +99 -17
  675. package/src/sync/webdav/webdav-upload-index-404.test.ts +177 -0
  676. package/src/ui/commands.test.ts +4 -1
  677. package/src/ui/commands.ts +46 -12
  678. package/src/ui/disk-usage-view.test.ts +63 -1
  679. package/src/ui/disk-usage-view.ts +93 -1
  680. package/src/ui/dsh-profiles-incomplete-view.test.ts +102 -0
  681. package/src/ui/dsh-profiles-view.ts +94 -0
  682. package/src/ui/foreign-view.test.ts +241 -0
  683. package/src/ui/foreign-view.ts +362 -0
  684. package/src/ui/i18n.ts +164 -0
  685. package/src/ui/mid-ellipsis.test.ts +5 -10
  686. package/src/ui/session-inventory-view.test.ts +142 -2
  687. package/src/ui/session-inventory-view.ts +127 -0
  688. package/src/ui/session-layout-view.test.ts +361 -0
  689. package/src/ui/session-layout-view.ts +444 -0
  690. package/src/ui/sync-repository-picker.test.ts +130 -0
  691. package/src/ui/sync-repository-picker.ts +180 -0
  692. package/src/ui/sync-settings-view.test.ts +166 -0
  693. package/src/ui/sync-settings-view.ts +319 -9
  694. package/src/ui/types.ts +42 -0
  695. package/src/utils/asar-read.test.ts +330 -0
  696. package/src/utils/asar-read.ts +606 -0
  697. package/src/utils/env-lock.test.ts +55 -0
  698. package/src/utils/env-lock.ts +6 -1
  699. package/src/utils/patch-yaml.test.ts +112 -0
  700. package/src/utils/patch-yaml.ts +72 -0
  701. package/src/utils/paths.test.ts +63 -0
  702. package/src/utils/paths.ts +25 -3
  703. package/src/utils/recursive-walk.test.ts +20 -0
  704. package/src/utils/recursive-walk.ts +12 -13
  705. package/src/utils/session-format.test.ts +113 -2
  706. package/src/utils/session-format.ts +127 -5
  707. package/src/utils/session-health-scan.test.ts +364 -1
  708. package/src/utils/session-health-scan.ts +434 -15
  709. package/src/utils/session-layout-repair-service.test.ts +362 -0
  710. package/src/utils/session-layout-repair-service.ts +568 -0
  711. package/src/utils/session-log-repair.test.ts +260 -1
  712. package/src/utils/session-log-repair.ts +294 -55
  713. package/src/utils/session-repair-service.test.ts +148 -1
  714. package/src/utils/session-repair-service.ts +165 -10
  715. package/src/utils/session-row-facts.test.ts +159 -0
  716. package/src/utils/session-row-facts.ts +187 -0
  717. package/src/utils/session-verify.test.ts +762 -0
  718. package/src/utils/session-verify.ts +784 -0
  719. package/src/utils/shared-constants.ts +82 -0
package/lib/client.d.ts CHANGED
@@ -217,6 +217,13 @@ interface PathIssue {
217
217
  interface SnapshotTarget {
218
218
  adapter: SectionId;
219
219
  ref: string;
220
+ /**
221
+ * patch 行类目标的**所在层**(相对 homeDir 的 POSIX 路径,见 core/patch-layers.ts)。
222
+ *
223
+ * 为什么必须带上:patch 行有两层(home 层 + profile 层),同一 `ref`(lineId)在两层的
224
+ * 原值不同、写入位置也不同。缺省 = 用户层(`cordis.patch.yml`),保持旧调用方行为不变。
225
+ */
226
+ file?: string;
220
227
  }
221
228
  interface PlanItem {
222
229
  id: string;
@@ -571,6 +578,17 @@ interface RestorePlan {
571
578
  };
572
579
  /** beforePlugins 基线是否可用(undefined=旧快照无基线 → 不计划任何插件卸载) */
573
580
  pluginBaselineConfirmed: boolean;
581
+ /**
582
+ * 快照记录的来源 DSH 版本(F-4;**可选**:旧快照没有该字段是常态,此时为 undefined)。
583
+ * 只承载事实,判定与展示在调用方(UI/CLI);恢复绝不因它而拒绝。
584
+ */
585
+ snapshotDshVersion?: string;
586
+ /**
587
+ * 本机当前 DSH 版本(F-4;**可选**:无法判定时不猜,保持 undefined 且不产出版本告警)。
588
+ * 来源优先级:调用方注入的 `RestoreOptions.currentDshVersion`(宿主权威,桌面端取 installAnchor)
589
+ * → profile 依赖树里实际落盘的 `@deepseek-ai/dsh` 版本(离线 best-effort)。
590
+ */
591
+ currentDshVersion?: string;
574
592
  }
575
593
  interface RestoreReport {
576
594
  snapshotId: string;
@@ -762,6 +780,15 @@ interface DshProfileMeta {
762
780
  patchBytes: number;
763
781
  /** 是否当前正在运行的 profile */
764
782
  isCurrent: boolean;
783
+ /**
784
+ * cross-F3:该条目是**中断的档案复制**留下的半截副本(无 package.json,只有进行中标记)。
785
+ * 界面据此把它渲染成「未完成的副本」并给出去向(`dir`)+ 删除入口,而不是当成正常档案。
786
+ */
787
+ incomplete?: true;
788
+ /** 半截副本的来源档案名(仅 incomplete 时有值) */
789
+ copiedFrom?: string;
790
+ /** 半截副本的复制开始时刻(ISO;仅 incomplete 时有值) */
791
+ copyStartedAt?: string;
765
792
  issues: DshProfileIssue[];
766
793
  /** package.json 的 mtime(毫秒);不可读 = null */
767
794
  updatedAtMs: number | null;
@@ -1077,6 +1104,50 @@ interface BackupScheduleStatus {
1077
1104
  lastRunMessage?: string;
1078
1105
  }
1079
1106
  //#endregion
1107
+ //#region src/utils/shared-constants.d.ts
1108
+ /**
1109
+ * 插件自更新(POST /update-apply)的失败码(**唯一声明处**:宿主 core/self-update.ts 与
1110
+ * 客户端关于页弹窗共用同一份字面量)。
1111
+ *
1112
+ * 为什么抽到这里:客户端要据码映射**本地化**文案(绝不直接渲染宿主返回的英文细节);
1113
+ * 若两侧各写一份联合类型,「宿主加了码而界面回落成英文」不会红。全部落在本文件的
1114
+ * 常量 + 派生类型上,客户端只 import 类型(零运行时依赖)。
1115
+ */
1116
+ declare const SELF_UPDATE_FAILURE_CODES: readonly ['invalid-version', 'profile-unknown', 'unsupported-profile', 'non-registry-install', 'not-newer', 'install-failed'];
1117
+ /** 自更新失败码(联合类型由上面的常量派生) */
1118
+ type SelfUpdateFailureCode = (typeof SELF_UPDATE_FAILURE_CODES)[number];
1119
+ /**
1120
+ * 同步通道清单(**零依赖**:宿主与 client 半都可运行时 import)。
1121
+ *
1122
+ * 为什么放在这里(而不是 `src/sync/sync-config.ts`):sync-config.ts import 了
1123
+ * node:fs / node:path,client 半**运行时** import 它会把 node 模块带进浏览器产物
1124
+ * (DSH loader 报 missed the module table,整个插件不加载)。通道清单是「纯常量」,
1125
+ * 与 ENCRYPTED_CONTAINER_CODE 同一处置:常量放这里,读写实现留在 sync-config.ts。
1126
+ *
1127
+ * 宿主侧 sync-config.ts **re-export** 它,仍是全仓唯一事实源(类型 SyncTransportType 由它派生)。
1128
+ *
1129
+ * 通道与「云端点具体兼容商」的关系:`s3` 是一条通道(配置里带 `provider` 区分
1130
+ * s3 / oss / cos / minio / kodo 五家),`gist` 是一条通道(provider 恒 gist)。
1131
+ */
1132
+ declare const SYNC_CHANNELS: readonly ['git', 'webdav', 's3', 'gist'];
1133
+ /**
1134
+ * S3 兼容系通道清单(**唯一声明处**,t88;先例 = 上面的 SYNC_CHANNELS)。
1135
+ *
1136
+ * 为什么也放这里:宿主 `sync/sync-config.ts` 与客户端镜像(`ui/sync-settings-view.ts` 的 `S3_PROVIDERS`、
1137
+ * `client/sync/sync-view.ts` 的 provider 文案表)必须同值 —— 两侧各写一份字面量时,「宿主加了兼容商而界面少一个选项」
1138
+ * 这类静默漂移**不会红**(客户端只能靠 `satisfies` 穷尽检查拦「新增」,拦不住「改名 / 删除 / 顺序」)。
1139
+ * 放到零依赖模块后,两侧都 import 它;`sync-config.ts` 只 re-export(宿主沿用既有 import 路径)。
1140
+ *
1141
+ * 与通道清单的关系:`s3` 是**一条通道**(配置里用 `provider` 区分这五家),`gist` 是另一条通道(provider 恒 gist)。
1142
+ */
1143
+ declare const S3_COMPAT_PROVIDERS: readonly ['s3', 'oss', 'cos', 'minio', 'kodo'];
1144
+ /** S3 兼容系通道类型 */
1145
+ type S3CompatProvider = (typeof S3_COMPAT_PROVIDERS)[number];
1146
+ /** 非 S3 系的云端点通道(GitHub Gist,走 REST) */
1147
+ declare const GIST_PROVIDER: 'gist';
1148
+ /** Gist 通道类型 */
1149
+ type GistProvider = typeof GIST_PROVIDER;
1150
+ //#endregion
1080
1151
  //#region src/security/container-kind.d.ts
1081
1152
  /** 备份容器形态。 */
1082
1153
  type BackupContainerKind = 'zip' | 'encrypted';
@@ -1237,6 +1308,33 @@ interface SessionRepairActionView {
1237
1308
  lossy: boolean;
1238
1309
  rows: number;
1239
1310
  }
1311
+ /**
1312
+ * 写后**真 codec 复验结论**的展示视图(src/ui 内部定义的结构化类型)。
1313
+ *
1314
+ * 为什么不直接 import utils/session-verify.ts 的 SessionVerifyResult:src/ui 会被打进 **client bundle**
1315
+ * (浏览器半),而那个模块经 utils/zstd-frame.ts 间接依赖 `node:zlib` —— bundle 里一旦出现对 node: 内建模块的
1316
+ * 引用,DSH loader 会报 missed the module table,**整个插件不加载**(本项目实测过)。
1317
+ * 所以这里只**逐字段镜像**宿主回传的形状(结构化鸭子类型),判定逻辑落在本模块的纯函数里。
1318
+ *
1319
+ * 语义(与 utils/session-verify.ts 的 SessionVerifyResult 逐字同源,**不许曲解**):
1320
+ * · verified && equivalentToReadPath → 「现役读盘可读」(header 版本 = 本机现役代际);
1321
+ * · verified && !equivalentToReadPath → 「迁移链可还原」(pre-v4 日志),**不等于**现役读盘可读;
1322
+ * · !verified → 「**未验证**」(本机跑不了真 codec 门),**不等于**已验证。
1323
+ */
1324
+ interface SessionVerifyView {
1325
+ verified: boolean;
1326
+ /** verified 时解出的事件数 */
1327
+ events?: number;
1328
+ /** !verified 时的机器可读原因(unavailable / invalid-header / decode-failed / finish-failed) */
1329
+ reason?: string;
1330
+ /** !verified 时的补充详情(机器可读码 + 候选标签,**不含路径**) */
1331
+ detail?: string;
1332
+ /** 额外的「已安装 build 语义校验」结论(不参与判定) */
1333
+ strong?: boolean;
1334
+ strongDetail?: string;
1335
+ /** 是否等价于 DSH 现役读盘路径(未验证时恒 false = 「没有任何可声称的现役等价」) */
1336
+ equivalentToReadPath: boolean;
1337
+ }
1240
1338
  /** 修复预览 / 应用结果(POST /recovery/sessions/repair)。 */
1241
1339
  interface SessionRepairResult {
1242
1340
  ok: boolean;
@@ -1265,6 +1363,16 @@ interface SessionRepairResult {
1265
1363
  lossy?: boolean;
1266
1364
  /** 保留的行数 */
1267
1365
  keptRows?: number;
1366
+ /**
1367
+ * 写后真 codec 复验结论(**应用期才有**)。调用方必须据它区分三态;
1368
+ * 缺省 = 没回传复验结论(预览路径)—— **绝不**当成「已验证」。
1369
+ */
1370
+ verify?: SessionVerifyView;
1371
+ /**
1372
+ * 确定性失败(reason=`verify-failed`)时:自动回滚是否成功。
1373
+ * false = 目标当前仍是「修复后字节」(危险态,必须可见);缺省 = 服务层没回传(不猜)。
1374
+ */
1375
+ rolledBack?: boolean;
1268
1376
  }
1269
1377
  /** 回滚结果(POST /recovery/sessions/rollback)。 */
1270
1378
  interface SessionRepairRollbackResult {
@@ -1300,6 +1408,24 @@ type PluginUpdateCheckResult = {
1300
1408
  /** 失败原因(网络 / 超时 / 响应畸形;可读、可重试、无敏感信息) */
1301
1409
  error: string;
1302
1410
  };
1411
+ /**
1412
+ * POST /update-apply 的结果(关于页「立即更新」)。
1413
+ *
1414
+ * 语义:用户**显式点击**后,宿主经官方 `dsh plugin` 通道把本插件安装为**钉住的精确版本**;
1415
+ * 成功只表示文件已换新,必须重启 DSH 才生效(needsRestart)。
1416
+ * 失败码与宿主共用同一份字面量(utils/shared-constants.ts),界面据码映射本地化文案,
1417
+ * 只有未知码才回落到宿主返回的原始错误文本。
1418
+ */
1419
+ type PluginUpdateApplyResult = {
1420
+ ok: true;
1421
+ version: string;
1422
+ command: string;
1423
+ needsRestart: true;
1424
+ } | {
1425
+ ok: false;
1426
+ code: SelfUpdateFailureCode;
1427
+ error: string;
1428
+ };
1303
1429
  /** 手动清理可点选的动作:可重建区(tmp + 市场缓存/工作副本)/ 已到期的导出产物。 */
1304
1430
  type DiskUsageCleanCategory = 'tmp' | 'expired-exports';
1305
1431
  /** POST /disk-usage/cleanup 的回执(回执里带刷新后的报告,避免界面再发一次 GET)。 */
@@ -1359,6 +1485,34 @@ interface RecoveryStatus {
1359
1485
  * 旧宿主不返回 → undefined(面板按「未阻断」处理,不误报保护)。
1360
1486
  */
1361
1487
  safeMode?: RecoverySafeModeStatus;
1488
+ /**
1489
+ * 中断的档案复制残留(cross-F3 / t54):目标目录带 `.dcm-copy-in-progress.json` 标记、
1490
+ * 却没有 package.json 的半截副本。它们既不在档案列表里、删除又报 notFound ——
1491
+ * 用户此前在「事故恢复」里既看不到、也没有任何处置入口。
1492
+ * 旧宿主不返回 → undefined(按「无残留」处理,不误报)。
1493
+ */
1494
+ incompleteCopies?: RecoveryIncompleteCopy[];
1495
+ /**
1496
+ * t89:残留**枚举失败**(读 profiles 目录失败)时为 true —— 与「确实没有残留」
1497
+ * (字段缺省)区分开:此前两者在响应里完全同形(都是 `incompleteCopies: []`),
1498
+ * 界面便把「读不到」渲染成「暂无残留」。
1499
+ * 旧宿主不返回 → undefined(按「读到了」处理,绝不误报失败)。
1500
+ */
1501
+ incompleteCopiesUnreadable?: boolean;
1502
+ }
1503
+ /**
1504
+ * 中断的档案复制残留(cross-F3 / t54):**只允许删除**。
1505
+ * 形态恒为 generic ⇒ 不可启动(没有 package.json,spawn 出去只会得到一个起不来的实例)。
1506
+ */
1507
+ interface RecoveryIncompleteCopy {
1508
+ /** 目标档案名(= 目录名) */
1509
+ name: string;
1510
+ /** 目标目录绝对路径(界面渲染前过 `redact()`) */
1511
+ dir: string;
1512
+ /** 来源档案名(标记不可解析时为 null —— 界面不臆造) */
1513
+ sourceName: string | null;
1514
+ /** 复制开始时刻(ISO;标记不可解析时为 null) */
1515
+ startedAt: string | null;
1362
1516
  }
1363
1517
  /** SAFE MODE 阻断态摘要(只暴露结论与是否可解除)。 */
1364
1518
  interface RecoverySafeModeStatus {
@@ -1495,6 +1649,118 @@ interface RecoveryPort {
1495
1649
  rollbackSessionRepair(repairId: string): Promise<SessionRepairRollbackResult>;
1496
1650
  }
1497
1651
  //#endregion
1652
+ //#region src/client/session-export/session-export-view.d.ts
1653
+ /**
1654
+ * 「下载原始日志 (ZIP)」入口的**纯展示模型**(F-2,框架无关、node 可测)。
1655
+ *
1656
+ * 本模块**不做任何 I/O 与 React**:输入是宿主探测回来的结构化事实,输出是组件直接渲染的三件事 ——
1657
+ * 是否可用、给用户看的原因、按钮的交互状态。判定集中在这里的原因很实在:这条入口最容易犯的错
1658
+ * **不是**功能错,而是**显隐判据错**(生态竞品普遍用已过时的 `status !== 501` 探测,在本机 DSH 上
1659
+ * 会因为服务缺失返 500 而**几乎恒显示**)。判据只能有一份,且必须可单测。
1660
+ *
1661
+ * 三态语义(与宿主 src/routes/session-export.ts 的 `SessionExportAvailability` 同源):
1662
+ * - `available` → 显示并可用;
1663
+ * - `unavailable` → **显示但禁用**,并给出可读原因(绝不静默、也绝不直接消失让用户以为没这功能);
1664
+ * - `unknown` → **保守显示为可用**(拿不到状态码时绝不猜成「不支持」——那会藏掉一个其实能用的功能)。
1665
+ *
1666
+ * 为什么 `unavailable` 是「禁用 + 说明」而不是「隐藏」:隐藏会让用户无从判断「是这台机器不支持」
1667
+ * 还是「插件没做这个功能」;禁用 + 一句话原因把这句话说清楚(与仓库「绝不静默」的既有取向一致)。
1668
+ */
1669
+ /** 可用性三态(与宿主 src/routes/session-export.ts 的判定同源)。 */
1670
+ type SessionExportAvailability = 'available' | 'unavailable' | 'unknown';
1671
+ /** 成因(机器可读;界面映射成文案,**绝不渲染裸码**)。 */
1672
+ type SessionExportReason = 'service-missing' | 'auth-required' | 'read-failed' | 'network-error' | 'unexpected-status';
1673
+ /** 宿主探测回来的结构化事实(与 GET /session-export 的响应字段一一对应)。 */
1674
+ interface SessionExportProbe {
1675
+ availability: SessionExportAvailability;
1676
+ reason?: SessionExportReason;
1677
+ /** DSH 返回的状态码(0 = 没拿到响应) */
1678
+ status: number;
1679
+ /** 探测的路径(诊断用) */
1680
+ path: string;
1681
+ /** 探测时刻(ISO) */
1682
+ checkedAt: string;
1683
+ }
1684
+ //#endregion
1685
+ //#region src/foreign/types.d.ts
1686
+ /** 未能迁移的外部内容(响亮失败:宁可在计划里报出来,也不静默丢) */
1687
+ interface ForeignSkip {
1688
+ /** 稳定机器码(UI 用它映射文案;禁止渲染裸枚举) */
1689
+ code: ForeignSkipCode;
1690
+ /** 外部侧位置(server 名 / skill 名 / 文件名;**不含任何值**) */
1691
+ origin?: string;
1692
+ /** 机器可读的细分原因(如 no-frontmatter / yaml-error),同样交给 UI 映射 */
1693
+ detail?: string;
1694
+ /** 同码聚合时的条数 */
1695
+ count?: number;
1696
+ }
1697
+ type ForeignSkipCode =
1698
+ /** settings.json 的 hooks:DSH 无对等结构 */
1699
+ 'unsupported-hooks' |
1700
+ /** commands/*.md(斜杠命令):与 DSH prompts 不是同一语义,本期不搬 */
1701
+ 'unsupported-commands' |
1702
+ /** settings.json 的 env 里出现凭据名:只计数与记名,**值不读** */
1703
+ 'credentials-not-migrated' |
1704
+ /** SKILL.md 缺失 */
1705
+ 'skill-missing-file' |
1706
+ /** frontmatter 不是合法 YAML / 缺 name|description(DSH 会**静默丢弃**该 skill,这里必须报) */
1707
+ 'skill-invalid-frontmatter' |
1708
+ /** 目录名/文件相对路径非法(含分隔符、.. 等),无法作为 skill 单元 */
1709
+ 'skill-invalid-name' |
1710
+ /** MCP 条目既无 command 也无 url */
1711
+ 'mcp-server-empty' |
1712
+ /** MCP type=sse(DSH 只支持 stdio / streamable-http)→ 按带 url 的 http 处理 */
1713
+ 'mcp-type-sse-coerced' |
1714
+ /** MCP 值里发现凭据字段(值已丢弃,只留字段名与引用名) */
1715
+ 'mcp-credential-redacted' |
1716
+ /** 外部文件读不到 / 超限 / 解析失败 */
1717
+ 'source-unreadable' |
1718
+ /** 会话:目标机未提供 DSH 会话格式版本(不猜版本,宁可整批不转) */
1719
+ 'session-format-version-unknown' |
1720
+ /** 会话:目标机格式版本不是本模块已实现的行式 */
1721
+ 'session-format-unsupported' |
1722
+ /** 会话:记录里没有 cwd(DSH 要求「日志位置 == projectKey(cwd)/id」,没有 cwd 无法归位) */
1723
+ 'session-missing-cwd' |
1724
+ /** 会话:文件名不能自证是安全路径段 */
1725
+ 'session-unsafe-id' |
1726
+ /** 会话:没有任何可迁移的事件 */
1727
+ 'session-empty' |
1728
+ /** 会话:存在解析不出来的行 */
1729
+ 'session-unparsable' |
1730
+ /** 会话:某类 Claude 记录本期不迁移(sidechain / attachment / queue-operation / system …) */
1731
+ 'unsupported-session-record' |
1732
+ /** 同 id 会话(包内重复 / 目标机已存在,含「另一 projectKey 下同 id」):**不覆盖、跳过并报码**(用户决策,§8.4) */
1733
+ 'session-id-conflict' |
1734
+ /** 外部技能重名(压平分类后同名,或两次来源同名):先到先得,其余跳过并报码(§8.4) */
1735
+ 'skill-id-conflict' |
1736
+ /** 该来源的对话存储形态本版不迁移(如 Hermes 的 SQLite state.db):只报告,绝不产出 sessions 分区 */
1737
+ 'sessions-not-migrated' |
1738
+ /** 记忆文件只报告不导入(如 Hermes memories/MEMORY.md、USER.md):用户决策,正文绝不进包 */
1739
+ 'memory-report-only' |
1740
+ /** 外部技能带分类层级(如 Hermes skills/<分类>/<技能>):压平为 DSH 单层 <技能>/SKILL.md 并报码 */
1741
+ 'skill-category-flattened' |
1742
+ /** 旧式规则文件(如 .cursorrules):DSH 无对等结构,只报告 */
1743
+ 'legacy-rules-file' |
1744
+ /** 多份指令源被合并为单个 AGENTS.md(DSH 只读一个全局指令文件):如实报告合并来源数 */
1745
+ 'instructions-merged' |
1746
+ /** 命中更高优先级的指令文件(如 Codex 的 AGENTS.override.md 优先于 AGENTS.md):报告被选中的那一个 */
1747
+ 'instructions-override-selected' |
1748
+ /** 配置文件存在但为 0 字节(如实测的 Antigravity mcp_config.json):报码,绝不产出空分区 */
1749
+ 'source-empty-file' |
1750
+ /** 配置目录位置被环境变量/命令行覆盖(CLAUDE_CONFIG_DIR / HERMES_HOME / CODEX_HOME / COPILOT_HOME) */
1751
+ 'source-location-overridden' |
1752
+ /**
1753
+ * 会话 cwd 由**源侧路径/编码目录名推导**(记录里没有 cwd 字段),且推导结果在本机**真实存在**
1754
+ * —— 才允许落盘(存在性检查把「猜」变成「有证据的推断」);不存在的推导一律按
1755
+ * `session-missing-cwd` 跳过,绝不产出一条指向不存在目录的会话。
1756
+ */
1757
+ 'session-cwd-derived' |
1758
+ /**
1759
+ * 该来源**没有自动根**(竞品 `defaultRoots.chatgpt = null`)—— 必须由用户显式给出导出文件
1760
+ * 路径;本机自动探测永远不会命中,如实报码而不是假装「未安装」。
1761
+ */
1762
+ 'source-needs-explicit-path';
1763
+ //#endregion
1498
1764
  //#region src/ui/i18n.d.ts
1499
1765
  /**
1500
1766
  * 客户端展示层(src/ui/*、src/client/common/*)的渲染文案目录(zh 源语言 / en 镜像)。
@@ -1865,6 +2131,7 @@ declare const uiZh: {
1865
2131
  readonly 'diskUsage.clean.expiredExportsDesc': '只删已超过保留期的导出 ZIP(定时备份不在此列)。';
1866
2132
  readonly 'diskUsage.clean.done': '已释放 {size},删除 {count} 项';
1867
2133
  readonly 'diskUsage.clean.nothing': '没有可释放的内容';
2134
+ readonly 'diskUsage.clean.nothingAbsent': '没有需要清理的内容(目标目录不存在或已为空)';
1868
2135
  readonly 'diskUsage.clean.failed': '清理完成,但有 {count} 项失败(已跳过)';
1869
2136
  readonly 'diskUsage.clean.excluded': '本次未包含:{items}';
1870
2137
  readonly 'diskUsage.clean.excludedExpiredExports': '回收过期备份文件';
@@ -1929,11 +2196,105 @@ declare const uiZh: {
1929
2196
  readonly 'library.value.plainZip': '明文 ZIP';
1930
2197
  readonly 'library.summary.count': '共 {count} 个';
1931
2198
  readonly 'library.summary.encrypted': '{count} 个加密';
2199
+ readonly 'foreign.source.claude-code': 'Claude Code';
2200
+ readonly 'foreign.source.hermes': 'Hermes';
2201
+ readonly 'foreign.source.cursor': 'Cursor';
2202
+ readonly 'foreign.source.codex': 'Codex CLI';
2203
+ readonly 'foreign.source.copilot': 'GitHub Copilot CLI';
2204
+ readonly 'foreign.source.antigravity': 'Google Antigravity';
2205
+ readonly 'foreign.source.gemini': 'Gemini CLI';
2206
+ readonly 'foreign.source.reasonix': 'Reasonix';
2207
+ readonly 'foreign.source.opencode': 'OpenCode';
2208
+ readonly 'foreign.source.mimocode': 'MimoCode';
2209
+ readonly 'foreign.source.zcode': 'ZCode';
2210
+ readonly 'foreign.source.grokbuild': 'Grok Build';
2211
+ readonly 'foreign.source.openclaw': 'OpenClaw';
2212
+ readonly 'foreign.source.pi': 'Pi';
2213
+ readonly 'foreign.source.kimi': 'Kimi CLI';
2214
+ readonly 'foreign.source.kilocode': 'Kilo Code';
2215
+ readonly 'foreign.source.qoder': 'Qoder';
2216
+ readonly 'foreign.source.chatgpt': 'ChatGPT';
2217
+ readonly 'foreign.source.workbuddy': 'WorkBuddy';
2218
+ readonly 'foreign.source.qwen': '千问办公';
2219
+ readonly 'foreign.source.continue': 'Continue';
2220
+ readonly 'foreign.source.cline': 'Cline';
2221
+ readonly 'foreign.source.goose': 'Goose';
2222
+ readonly 'foreign.source.dsh4': 'DSH 会话日志(V4 代次)';
2223
+ readonly 'foreign.source.zed': 'Zed';
2224
+ readonly 'foreign.source.crush': 'Crush';
2225
+ readonly 'foreign.source.teleagent': 'TeleAgent';
2226
+ readonly 'foreign.source.trae': 'Trae';
2227
+ readonly 'foreign.source.vibe': 'Vibe';
2228
+ readonly 'foreign.source.dsh': 'DSH 会话日志(V0-V3 代次)';
2229
+ readonly 'foreign.source.unknown': '未识别的来源';
2230
+ readonly 'foreign.found.yes': '已检测到';
2231
+ readonly 'foreign.found.no': '未检测到';
2232
+ readonly 'foreign.paths': '命中路径:{paths}';
2233
+ readonly 'foreign.pathsNone': '没有命中任何真值表路径';
2234
+ readonly 'foreign.skipped.total': '未迁移 {count} 项';
2235
+ readonly 'foreign.skipped.empty': '没有未迁移的内容';
2236
+ readonly 'foreign.credentialRefs': '需补录凭据 {count} 项:{refs}';
2237
+ readonly 'foreign.credentialRefs.none': '无需补录凭据';
2238
+ readonly 'foreign.sections.none': '没有可导入的分区';
2239
+ readonly 'foreign.reportOnly': '只报告、不导入:{detail}';
2240
+ readonly 'foreign.skip.unsupported-hooks': 'settings 的 hooks:DSH 无对等结构,未迁移';
2241
+ readonly 'foreign.skip.unsupported-commands': '斜杠命令:与 DSH 提示词不是同一语义,本次未迁移';
2242
+ readonly 'foreign.skip.credentials-not-migrated': '凭据字段只记录名字,值不读取也不迁移';
2243
+ readonly 'foreign.skip.skill-missing-file': '技能目录缺少 SKILL.md,未迁移';
2244
+ readonly 'foreign.skip.skill-invalid-frontmatter': '技能 frontmatter 非法,DSH 会静默丢弃,故未迁移';
2245
+ readonly 'foreign.skip.skill-invalid-name': '技能名含非法字符或路径穿越,未迁移';
2246
+ readonly 'foreign.skip.mcp-server-empty': 'MCP 条目既无 command 也无 url,未迁移';
2247
+ readonly 'foreign.skip.mcp-type-sse-coerced': 'MCP type=sse:按带 url 的 http 处理';
2248
+ readonly 'foreign.skip.mcp-credential-redacted': 'MCP 值里发现凭据字段:值已丢弃,只保留字段名与引用名';
2249
+ readonly 'foreign.skip.source-unreadable': '外部文件读不到、超限或解析失败';
2250
+ readonly 'foreign.skip.source-empty-file': '配置文件存在但为空(0 字节):如实上报,不产出空分区';
2251
+ readonly 'foreign.skip.source-location-overridden': '配置位置被环境变量覆盖,按覆盖后的位置读取';
2252
+ readonly 'foreign.skip.session-cwd-derived': '会话记录里没有 cwd:按源侧目录名推导出工作目录,且该目录在本机确实存在(推不出来的一律按「缺少 cwd」跳过)';
2253
+ readonly 'foreign.skip.source-needs-explicit-path': '该来源没有自动探测位置:必须显式提供导出文件路径(自动探测永远不会命中)';
2254
+ readonly 'foreign.skip.session-format-version-unknown': '本机 DSH 会话格式版本未知:不猜版本,整批会话未迁移';
2255
+ readonly 'foreign.skip.session-format-unsupported': '本机 DSH 会话格式版本不受支持,该会话未迁移';
2256
+ readonly 'foreign.skip.session-missing-cwd': '会话记录缺少 cwd,无法归位到工作区';
2257
+ readonly 'foreign.skip.session-unsafe-id': '会话文件名不能作为安全路径段,未迁移';
2258
+ readonly 'foreign.skip.session-empty': '会话没有任何可迁移的事件';
2259
+ readonly 'foreign.skip.session-unparsable': '会话存在解析不出来的行,未迁移';
2260
+ readonly 'foreign.skip.unsupported-session-record': '该类型的会话记录本版不迁移';
2261
+ readonly 'foreign.skip.session-id-conflict': '同 id 会话已存在:不覆盖,跳过并保留本机既有的那条';
2262
+ readonly 'foreign.skip.skill-id-conflict': '技能重名:先到先得,其余跳过';
2263
+ readonly 'foreign.skip.sessions-not-migrated': '该来源的对话存储形态本版不迁移';
2264
+ readonly 'foreign.skip.memory-report-only': '记忆文件只报告、不导入(正文不进备份包)';
2265
+ readonly 'foreign.skip.skill-category-flattened': '技能带分类层级:已压平为 DSH 的单层技能目录';
2266
+ readonly 'foreign.skip.legacy-rules-file': '旧式规则文件:DSH 无对等结构,只报告';
2267
+ readonly 'foreign.skip.instructions-merged': '多份指令源被合并为一个全局指令文件';
2268
+ readonly 'foreign.skip.instructions-override-selected': '命中更高优先级的指令文件(override),按它导入';
2269
+ readonly 'foreign.lossy.file-section-secrets.title': '文件类分区的明文不做剥离';
2270
+ readonly 'foreign.lossy.file-section-secrets.detail': '技能 / Agent 预设 / 全局指令 / 插件文件 / 历史会话 / 插件自身配置这六个文件类分区承载的是原始文件内容:命中的明文原样进包(导入侧只报告、不改写;本页的产包路径连扫描都不做)。「默认不含秘密」只对结构化分区成立,对这类分区不成立 —— 需要保密请先清理源文件。';
2271
+ readonly 'foreign.lossy.entry-backslash.title': '条目名中段反斜杠:跨平台落点可能不同';
2272
+ readonly 'foreign.lossy.entry-backslash.detail': 'ZIP 条目名里出现在中段的反斜杠不会被拒绝:同一个包在 Windows 目标上会被当作路径分隔符(落成多级目录),在 POSIX 目标上只是一个普通字符。本实现刻意不改这一格式行为;界面无法逐条检查条目名,跨平台导入后请核对这类文件是否落在预期位置。';
2273
+ readonly 'foreign.lossy.prompt-persona-reshape.title': 'prompts 的 systemPrompt 形状变化';
2274
+ readonly 'foreign.lossy.prompt-persona-reshape.detail': '源里的 systemPrompt 是字符串,导入落盘时写成带 persona 字段的对象:persona 文本无损,字段形状改变。兼容性评分不会为这一条给出原因 —— 它不改变内容,只改变形态。';
1932
2275
  };
1933
2276
  type UiTextKey = keyof typeof uiZh;
1934
2277
  /** UI 翻译函数:key → 当前语言文案({param} 插值;未知键回退 zh/键名)。 */
1935
2278
  type UiT = (key: UiTextKey, params?: Record<string, string | number>) => string;
1936
2279
  //#endregion
2280
+ //#region src/ui/foreign-view.d.ts
2281
+ /** `GET /foreign-sources` 返回的一条来源检测结果(与宿主 ForeignSourceStatus 同构) */
2282
+ interface ForeignSourceStatusInput {
2283
+ id: string;
2284
+ /** 宿主给的字典键(如 foreign.source.claude-code);**只作为兜底**,正常走 id 映射 */
2285
+ labelKey?: string;
2286
+ found: boolean;
2287
+ /** 命中位置(相对 home 的 POSIX 路径;宿主保证绝不是绝对路径) */
2288
+ paths: readonly string[];
2289
+ skipped?: readonly ForeignSkip[];
2290
+ }
2291
+ /** `GET /foreign-sources` 响应 */
2292
+ interface ForeignSourcesResponse$1 {
2293
+ conflictPolicy?: string;
2294
+ projectScoped?: boolean;
2295
+ sources: readonly ForeignSourceStatusInput[];
2296
+ }
2297
+ //#endregion
1937
2298
  //#region src/client/common/http.d.ts
1938
2299
  /** 携带路由 JSON error 消息的错误类型(客户端所有请求错误的唯一类型)。 */
1939
2300
  declare class ConfigManagerApiError extends Error {
@@ -1971,6 +2332,41 @@ interface ServiceStatus {
1971
2332
  /** dsh.profile.bundles 声明(非空即替换默认插件栈) */
1972
2333
  bundles?: string[];
1973
2334
  }
2335
+ /**
2336
+ * 外部 agent 来源发现响应(`GET /foreign-sources`)。
2337
+ *
2338
+ * 复用 `src/ui/foreign-view.ts` 的输入类型 —— 响应形状的**唯一权威**在那边(视图模型只读它)。
2339
+ * 路径刻意在本文件重导出,避免组件同时 import 两处(同 `UploadResponse` 的做法)。
2340
+ */
2341
+ type ForeignSourcesResponse = ForeignSourcesResponse$1;
2342
+ /**
2343
+ * 外部来源 → bundle 的响应(`POST /foreign-import`)。
2344
+ *
2345
+ * `zipPath`:受控临时目录里的标准 bundle v1 ZIP,直接喂给既有导入向导的 `analyzeImport`。
2346
+ * `skipped` / `credentialRefs` **绝不含凭据值**(值在转换层已被剥离)。
2347
+ */
2348
+ interface ForeignImportResponse {
2349
+ zipPath: string;
2350
+ name: string;
2351
+ /** 来源 id(六来源之一) */
2352
+ source: string;
2353
+ /** 来源显示名的字典键(如 foreign.source.hermes) */
2354
+ labelKey: string;
2355
+ /** 产物字节数(读不到时为 0,界面按「未知」处理) */
2356
+ sizeBytes: number;
2357
+ /** 本次产出包内的分区(空分区不会被写入,也不出现在这里) */
2358
+ sections: SectionId[];
2359
+ /** 各分区的条目计数(机器可读;键形如 `mcp.servers`) */
2360
+ counts: Record<string, number>;
2361
+ /** 未迁移项(只有机器码 + 位置名 + 条数) */
2362
+ skipped: ForeignSkip[];
2363
+ /** 凭据**引用名**(形如 `mcp:gitnexus:GITHUB_TOKEN`);导入后由用户补录值 */
2364
+ credentialRefs: string[];
2365
+ /** 检测到的本机位置(相对 home;绝不回传绝对路径) */
2366
+ detectedPaths: string[];
2367
+ /** 冲突策略(用户决策:同 id 不覆盖、跳过并报码) */
2368
+ conflictPolicy: string;
2369
+ }
1974
2370
  /** export 端点响应(对齐 ExportFlow 的 ExportRunResult 前半部分;runId 为 m1 run 注册表标识) */
1975
2371
  interface ExportResponse {
1976
2372
  zipPath: string;
@@ -2297,12 +2693,70 @@ declare class ConfigManagerApi {
2297
2693
  * —— 界面显示可重试提示,不当作错误横幅。
2298
2694
  */
2299
2695
  checkUpdate(force?: boolean): Promise<PluginUpdateCheckResult>;
2696
+ /**
2697
+ * 执行插件自更新(POST /update-apply)—— **只在用户显式点「立即更新」后**调用。
2698
+ *
2699
+ * 宿主经官方 dsh plugin 通道安装钉住的精确版本(见 core/self-update.ts);成功后必须
2700
+ * 重启 DSH 才生效。安装可能较慢(慢网络下分钟级),故用独立的长超时档位。
2701
+ */
2702
+ applyUpdate(version: string): Promise<PluginUpdateApplyResult>;
2300
2703
  /** 迁移前咨询(只读健康评分 + 建议):对 4 种可迁移源生成统一咨询报告。 */
2301
2704
  consult(input: {
2302
2705
  type: 'export-zip' | 'local-snapshot' | 'remote-snapshot' | 'profile';
2303
2706
  id: string;
2304
2707
  snapshotId?: string;
2305
2708
  }): Promise<ConsultReport>;
2709
+ /**
2710
+ * GET /foreign-sources:六来源的本机检测结果(**只读**,零写入)。
2711
+ *
2712
+ * 未安装是正常状态(found=false),不是错误 —— 界面照常列出全部六条,
2713
+ * 用户才知道「哪些查过了、本机确实没有」。
2714
+ */
2715
+ foreignSources(opts?: {
2716
+ projectDir?: string;
2717
+ }): Promise<ForeignSourcesResponse>;
2718
+ /**
2719
+ * POST /foreign-import:把本机某个外部 agent 的配置翻译成标准 bundle v1 ZIP,
2720
+ * 落到宿主受控临时目录并返回 zipPath —— 之后**完全复用既有导入向导**
2721
+ * (analyzeImport → createImportPlan → executeImportPlan),不新建第二套向导。
2722
+ *
2723
+ * 为什么必须由宿主产包:转换要读本机文件系统并写 ZIP,浏览器半做不了
2724
+ * (此前该能力只在 CLI 里,GUI 会在「点导入」之后断链)。
2725
+ *
2726
+ * `projectDir`:项目级真值位置(Cursor/Codex 的 <项目>/.cursor/**)。**缺省不传 = 不扫项目级** ——
2727
+ * 宿主进程的 cwd 不是用户的项目,绝不猜。
2728
+ *
2729
+ * 响应**绝不含凭据值**:只有 skipped 机器码与凭据**引用名**(值在转换层已被剥离)。
2730
+ */
2731
+ foreignImport(source: string, opts?: {
2732
+ projectDir?: string;
2733
+ }): Promise<ForeignImportResponse>;
2734
+ /**
2735
+ * GET /session-export(**只读**):探测 DSH 官方 session.export 端的可用性。
2736
+ *
2737
+ * 为什么由宿主代探而不是浏览器直接打 DSH:见 src/routes/session-export.ts 的文件头 ——
2738
+ * 该端点挂在带浏览器认证的 `/api` 前缀下,浏览器侧「401 / 404 / 连不上」分不开,
2739
+ * 而「路由没注册」与「持久化后端缺服务」的处理方式**完全不同**(前者保守显示、后者隐藏入口)。
2740
+ *
2741
+ * 返回三态(**绝不二值化**):`available` 显示 / `unavailable` 禁用并说明原因 / `unknown` 保守显示。
2742
+ */
2743
+ sessionExportProbe(): Promise<SessionExportProbe>;
2744
+ /** F-2:原始日志 ZIP 的代理下载地址(探测与下载同一条路由,query 决定形态)。 */
2745
+ sessionExportUrl(sessionId: string, opts?: {
2746
+ includeDescendants?: boolean;
2747
+ }): string;
2748
+ /**
2749
+ * F-2:把某条会话的原始日志 ZIP 下载到本机(由 DSH 自己打包,含子会话与附件)。
2750
+ *
2751
+ * 复用**既有**的流式下载链路(openStream + saveDownloaded,与导出产物同一条):
2752
+ * - 大 ZIP 不整本驻留内存(流式写优先,不可用时才 Blob 兜底);
2753
+ * - 正文阶段是**空闲超时**(每读一块重置)—— 宿主卡死时明确失败而非永久转圈;
2754
+ * - 失败时把上游(DSH)的状态码与正文如实抛出(代理路由原样透传,见 src/routes/session-export.ts)。
2755
+ *
2756
+ * 为什么走本插件的代理而不是直连 DSH 的 `/api/session.export`:`openStream` 认得本插件的
2757
+ * 错误信封;直连 DSH 时 401/404 只是一次没有解释的失败(而 404 也可能是「拼错路径」)。
2758
+ */
2759
+ downloadSessionExport(sessionId: string, opts?: DownloadOptions, onProgress?: (received: number, total: number) => void): Promise<DownloadResult>;
2306
2760
  /** 「查看备份内容」:对 exports 目录内的备份文件做只读分析(reuse /analyze,零写入)。
2307
2761
  * 返回分析 + 与当前配置的差异计划摘要("装/导这个备份会动你什么")。 */
2308
2762
  inspectBackup(zipPath: string): Promise<BackupInspectResult>;
@@ -2359,17 +2813,28 @@ interface SyncPushPreview {
2359
2813
  }
2360
2814
  //#endregion
2361
2815
  //#region src/sync/sync-config.d.ts
2362
- /**
2363
- * 同步通道枚举(**唯一声明处**,t32):所有「有哪些通道 / 通道列表 / 通道判定」的唯一事实源。
2364
- *
2365
- * 为什么要单一来源:此前 SyncTransportType 在 sync-config / ui-prefs / client sync-api /
2366
- * client sync-view 各自声明一遍,通道数组也在 autosync-scheduler 里写了两遍 ——「改一处漏一处」
2367
- * 的表现是某个通道**静默**不再排期 / 不再落盘,而不是报错。新增通道只改这里:typecheck 会在
2368
- * 所有 Record<SyncTransportType, X> 的构造处与穷尽检查处报错。
2369
- */
2370
- declare const SYNC_CHANNELS: readonly ['git', 'webdav'];
2371
2816
  /** 同步通道类型(由 SYNC_CHANNELS 派生;host 侧与 client 半统一引用)。 */
2372
2817
  type SyncTransportType$1 = (typeof SYNC_CHANNELS)[number];
2818
+ /** S3 兼容系通道的回传视图:**只带 secretStored 标记,绝不带密钥值**。 */
2819
+ interface CloudS3ChannelView {
2820
+ provider: S3CompatProvider;
2821
+ endpoint: string;
2822
+ region: string;
2823
+ bucket: string;
2824
+ prefix: string;
2825
+ accessKeyId: string;
2826
+ pathStyle: boolean;
2827
+ /** 密钥已在 credentials 里(只回布尔) */
2828
+ secretStored: boolean;
2829
+ }
2830
+ /** Gist 通道的回传视图:**只带 secretStored 标记,绝不带 token 值**。 */
2831
+ interface CloudGistChannelView {
2832
+ provider: GistProvider;
2833
+ gistId: string;
2834
+ apiBaseUrl: string;
2835
+ filePrefix: string;
2836
+ secretStored: boolean;
2837
+ }
2373
2838
  //#endregion
2374
2839
  //#region src/client/sync/sync-api.d.ts
2375
2840
  /**
@@ -2391,6 +2856,15 @@ interface SyncStatusResponse {
2391
2856
  /** webdav 通道:配置状态(url 可回显,username 非敏感;password 值永不返回;
2392
2857
  * 与当前通道无关,配置过即返回,供 git ↔ webdav 切换时回填表单) */
2393
2858
  webdav?: WebDavStatusResponse;
2859
+ /**
2860
+ * 云端点通道 s3 的非密配置视图(**只有 secretStored 布尔,绝无 AccessKey Secret 值**)。
2861
+ * 配置过即返回(与当前活动通道无关),供表单在各通道间切换时回填。
2862
+ */
2863
+ s3?: CloudS3ChannelView;
2864
+ /** 云端点通道 gist 的非密配置视图(**只有 secretStored 布尔,绝无 token 值**)。 */
2865
+ gist?: CloudGistChannelView;
2866
+ /** 已保存的云端点 provider 清单(只有名字;切换 provider 时回填用) */
2867
+ cloudSavedProviders?: string[];
2394
2868
  /** sync-state.lastSyncAt;'' = 从未同步 */
2395
2869
  lastSyncAt?: string;
2396
2870
  /** sync-state.sections 条目数 */
@@ -2478,6 +2952,9 @@ interface SyncConfigSaveResponse {
2478
2952
  usernameConfigured: boolean;
2479
2953
  passwordConfigured: boolean;
2480
2954
  };
2955
+ /** 云端点通道保存后的非密视图(只带 secretStored 布尔,绝无密钥值) */
2956
+ s3?: CloudS3ChannelView;
2957
+ gist?: CloudGistChannelView;
2481
2958
  }
2482
2959
  /** POST /sync/config 且 clear:true 的响应:断开一条通道配置后的轻量事实(无任何 secret 值)。 */
2483
2960
  interface SyncChannelClearResponse {
@@ -2534,6 +3011,31 @@ interface SyncPushPayload {
2534
3011
  encryptPassword?: string;
2535
3012
  /** 导出真实凭据值(必须同时 encrypt=true,否则 Host 拒绝:密钥绝不明文进同步通道) */
2536
3013
  includeSecrets?: boolean;
3014
+ /** s3:具体兼容商(s3 / oss / cos / minio / kodo) */
3015
+ provider?: string;
3016
+ endpoint?: string;
3017
+ region?: string;
3018
+ bucket?: string;
3019
+ /** 对象键前缀(缺省 = 根前缀) */
3020
+ prefix?: string;
3021
+ /** AccessKey ID(标识符,可回显;不是密钥) */
3022
+ accessKeyId?: string;
3023
+ /** path-style 寻址(缺省跟随兼容商变体) */
3024
+ pathStyle?: boolean;
3025
+ /** 显式覆盖签名方言(高级覆盖;宿主忽略非法值) */
3026
+ dialectId?: 'aws4' | 'oss4';
3027
+ /** gist:目标 gist id */
3028
+ gistId?: string;
3029
+ /** gist:GitHub API 根(缺省 https://api.github.com) */
3030
+ apiBaseUrl?: string;
3031
+ /** gist:文件名前缀(缺省 dsh-sync) */
3032
+ filePrefix?: string;
3033
+ /**
3034
+ * 云端点密钥(s3 的 AccessKey Secret / gist 的 token):**只写**。
3035
+ * 仅请求体内存传输;宿主写入 DSH credentials 槽位(cloudSecretRef)后即丢弃。
3036
+ * 响应、配置文件与日志里永远只有 `secretStored` 布尔。
3037
+ */
3038
+ secret?: string;
2537
3039
  }
2538
3040
  /** pull 请求体(strategy 缺省 merge:冲突保留待决策;snapshotId 缺省 = 最新;
2539
3041
  * decryptPassword 可选:拉取加密快照时提供,仅内存传输)。 */
@@ -2769,6 +3271,33 @@ interface GithubValidateResponse {
2769
3271
  /** GitHub 登录名(valid=true 时;非敏感展示位) */
2770
3272
  login?: string;
2771
3273
  }
3274
+ /** 仓库列表条目(宿主 `GitHubRepoSummary` 的投影;token 等秘密永不在此出现)。 */
3275
+ interface GithubRepositorySummary {
3276
+ /** owner/name */
3277
+ fullName: string;
3278
+ /** 仓库主页(展示用) */
3279
+ htmlUrl: string;
3280
+ /** 提交值:clone URL(https 形态,不含凭据) */
3281
+ cloneUrl: string;
3282
+ defaultBranch: string;
3283
+ private: boolean;
3284
+ fork: boolean;
3285
+ /** 最近一次 push(ISO 8601;空仓库 → 空串) */
3286
+ pushedAt: string;
3287
+ /** 最近一次更新(ISO 8601;缺字段 → 空串) */
3288
+ updatedAt: string;
3289
+ }
3290
+ /** GET /sync/github/repositories 响应:当前 GitHub 用户可见的仓库(按最近更新排序)。 */
3291
+ interface GithubRepositoriesResponse {
3292
+ ok: boolean;
3293
+ repos: GithubRepositorySummary[];
3294
+ }
3295
+ /** POST /sync/github/repositories 响应:新建的仓库。
3296
+ * **恒定私有** —— 宿主强制 private:true,客户端无法请求公开仓库。 */
3297
+ interface GithubCreateRepositoryResponse {
3298
+ ok: boolean;
3299
+ repo: GithubRepositorySummary;
3300
+ }
2772
3301
  /** 远程同步浏览器半数据入口(备份与迁移页第 4 个 tab 的注入业务面) */
2773
3302
  declare class SyncApi {
2774
3303
  readonly t: UiT;
@@ -2825,6 +3354,12 @@ declare class SyncApi {
2825
3354
  /** GitHub token 有效性校验(判定「是否已登录」:token 存在且 GitHub API 接受;
2826
3355
  * 401 → valid:false 引导重新登录;非 401 错误向上抛,UI 兜底不误判登出) */
2827
3356
  githubValidate(): Promise<GithubValidateResponse>;
3357
+ /** 列出当前 GitHub 用户可见的仓库(供「选择已有仓库」下拉;只读,不改任何状态)。
3358
+ * 未登录 / token 失效 → 401,由调用方按「先登录」引导处理。 */
3359
+ githubListRepositories(): Promise<GithubRepositoriesResponse>;
3360
+ /** 新建仓库并返回其信息(供「新建仓库」表单;**宿主强制私有**,
3361
+ * 描述为空则不传该字段)。名称非法 / 已存在 → 422,由调用方展示原因。 */
3362
+ githubCreateRepository(name: string, description?: string): Promise<GithubCreateRepositoryResponse>;
2828
3363
  /** 同步历史:列出本地祖先快照 + 自动同步执行记录(按 createdAt 倒序合并)。 */
2829
3364
  history(): Promise<SyncHistoryResponse>;
2830
3365
  /** 远端历史快照列表(供「选择历史快照」下拉)。 */
@@ -3006,11 +3541,9 @@ interface MarketPreparePayload {
3006
3541
  /** 发布模式:'migrate'(缺省,迁移全带)| 'share'(分享:自动排除敏感分区 + 强制隐私拦截) */
3007
3542
  mode?: MarketPublishMode;
3008
3543
  }
3009
- /** POST /market/prepare 响应:条目包生成结果(manifest 文本 + 校验摘要 + 发布目录) */
3544
+ /** POST /market/prepare 响应:条目包生成结果(manifest 文本 + 校验摘要) */
3010
3545
  interface MarketPrepareResponse {
3011
3546
  ok: boolean;
3012
- /** 发布目录(受控临时区,含 items/<id>/manifest.json + config.zip;懒 GC 与下载临时区同款) */
3013
- dir: string;
3014
3547
  /** 发布目录打包 zip 路径(受控临时区,供 /download 端点下载;懒 GC 清理) */
3015
3548
  zipPath: string;
3016
3549
  /** items/<id>/manifest.json 内容(pretty JSON,可直接复制/写入) */
@@ -3200,6 +3733,105 @@ declare class MyConfigsApi {
3200
3733
  meDelete(itemId: string): Promise<DeleteResult>;
3201
3734
  }
3202
3735
  //#endregion
3736
+ //#region src/core/session-repair.d.ts
3737
+ /** 单条会话的修复原因(机器可读;文案由 CLI 输出层决定)。 */
3738
+ type SessionRepairReason =
3739
+ /** header 里没有 cwd(DSH 的 _no-cwd 会话):无法判定目标目录 */
3740
+ 'no-cwd' |
3741
+ /** 同一会话的多份 generation 的 cwd 不一致:不猜哪份为准 */
3742
+ 'inconsistent-generations' |
3743
+ /** 目录内有 session.lock:可能正被使用 */
3744
+ 'locked' |
3745
+ /** 位置已经正确 */
3746
+ 'already-placed' |
3747
+ /** 需要搬家(header 未变) */
3748
+ 'needs-move' |
3749
+ /** 需要先改写首帧 cwd(路径映射命中)再搬家 */
3750
+ 'needs-rewrite-move' |
3751
+ /** 同一 id 出现在多个 projectKey 目录 */
3752
+ 'duplicate-id';
3753
+ /** 一条动作的类别(决定 CLI 做什么)。 */
3754
+ type SessionRepairActionKind =
3755
+ /** 无需动作 */
3756
+ 'ok' |
3757
+ /** 搬目录到正确 projectKey 段 */
3758
+ 'move' |
3759
+ /** 改写首帧 cwd 后再搬目录 */
3760
+ 'rewrite-move' |
3761
+ /** 只报告,不动(缺 cwd / 加锁 / 多 generation 不一致) */
3762
+ 'skip' |
3763
+ /** 重复 id 里按 --keep 保留的那一份 */
3764
+ 'keep' |
3765
+ /** 重复 id 里被移到隔离目录的那一份 */
3766
+ 'quarantine';
3767
+ interface SessionRepairSummary {
3768
+ scanned: number;
3769
+ ok: number;
3770
+ move: number;
3771
+ rewriteMove: number;
3772
+ skip: number;
3773
+ keep: number;
3774
+ quarantine: number;
3775
+ /** 受影响的重复 id 条数(同一 id 的多份只算一次) */
3776
+ duplicates: number;
3777
+ }
3778
+ //#endregion
3779
+ //#region src/ui/session-layout-view.d.ts
3780
+ /** E1 计划里的一条动作(**不含绝对路径**:身份 = `<fromProjectKey>/<sessionId>`)。 */
3781
+ interface SessionLayoutPlanItemView {
3782
+ unitId: string;
3783
+ sessionId: string;
3784
+ kind: SessionRepairActionKind;
3785
+ fromProjectKey: string;
3786
+ toProjectKey?: string;
3787
+ /** 面板入口不支持路径映射 ⇒ 恒缺席(这里保留字段只为与宿主同形) */
3788
+ rewrite?: {
3789
+ from: string;
3790
+ to: string;
3791
+ };
3792
+ reason: SessionRepairReason;
3793
+ applies: boolean;
3794
+ }
3795
+ interface SessionLayoutPlanView {
3796
+ ok: boolean;
3797
+ readOnly: boolean;
3798
+ /** 会话根读不出来时的机器码(`sessions-root-unreadable`) */
3799
+ reason?: string;
3800
+ summary: SessionRepairSummary;
3801
+ actions: SessionLayoutPlanItemView[];
3802
+ needsAttention: boolean;
3803
+ /** 有重复 id 但**还没选定保留哪一份**的 sessionId(面板据此要求用户选) */
3804
+ needsKeep: string[];
3805
+ }
3806
+ interface SessionLayoutApplyItemView {
3807
+ unitId: string;
3808
+ sessionId: string;
3809
+ action: SessionRepairActionKind;
3810
+ ok: boolean;
3811
+ reason?: string;
3812
+ /** 隔离去向(**相对** `<home>/sessions`;可直接渲染) */
3813
+ quarantineDir?: string;
3814
+ /** 归位后的新身份 */
3815
+ movedUnitId?: string;
3816
+ /** 失败后是否已成功回滚(true = 已回到原状态;false = **回滚也没成功**,危险态) */
3817
+ rolledBack?: boolean;
3818
+ needsAttention?: boolean;
3819
+ }
3820
+ interface SessionLayoutApplyView {
3821
+ ok: boolean;
3822
+ applied: number;
3823
+ failed: number;
3824
+ skipped: number;
3825
+ results: SessionLayoutApplyItemView[];
3826
+ /** 整体未执行:`reindex-unavailable`(宿主没给索引刷新端口)/ `sessions-root-unreadable` */
3827
+ reason?: string;
3828
+ }
3829
+ /**
3830
+ * 这条路由的两种响应(apply=false → 计划;apply=true → 执行结果)。
3831
+ * 判别:执行结果带 `results` 数组,计划带 `actions`/`needsKeep`。
3832
+ */
3833
+ type SessionLayoutResponse = SessionLayoutPlanView | SessionLayoutApplyView;
3834
+ //#endregion
3203
3835
  //#region src/client/recovery/recovery-api.d.ts
3204
3836
  /** Recovery 浏览器半数据入口(实现 RecoveryPort 契约)。 */
3205
3837
  declare class RecoveryApi implements RecoveryPort {
@@ -3228,6 +3860,19 @@ declare class RecoveryApi implements RecoveryPort {
3228
3860
  }, allowLossy?: boolean): Promise<SessionRepairResult>;
3229
3861
  /** POST /recovery/sessions/rollback(T8):按台账 repairId 回滚(客户端不传路径)。 */
3230
3862
  rollbackSessionRepair(repairId: string): Promise<SessionRepairRollbackResult>;
3863
+ /**
3864
+ * POST /recovery/sessions/layout(E2):**布局归位 / 重复 id 隔离**(写入口)。
3865
+ *
3866
+ * apply=false = **只读计划**(宿主不拿锁、不过门、零写入;响应带 needsKeep,界面据此要求用户
3867
+ * 选定保留哪一份);apply=true = 应用(过 SAFE MODE + mutation lock;keep 必须覆盖全部 needsKeep,
3868
+ * 否则该 id 被显式拒绝而不是静默跳过)。
3869
+ *
3870
+ * 安全口径(**必须与界面文案一致**):本入口在 **DSH 运行时**执行,与离线 CLI
3871
+ * `dcm sessions repair --fix` 的「须先停 DSH」不同 —— 靠宿主侧逐目标门前置 + 每次移动后
3872
+ * **索引刷新必须成功** + 失败逐条回滚兜底。任何拒绝都以 `ok:false + reason`(或逐条 reason 码)
3873
+ * 表达,**不是** HTTP 错误,界面必须逐条如实说明。
3874
+ */
3875
+ layoutRepairSessions(apply: boolean, keep?: Record<string, string>): Promise<SessionLayoutResponse>;
3231
3876
  /** GET /recovery/:operationId/preview:只读恢复预览(restore plan + verification plan)。 */
3232
3877
  preview(operationId: string): Promise<RecoveryPreview>;
3233
3878
  /** POST /recovery/:operationId/confirm:确认恢复(journal 保持 NEEDS_ATTENTION)。 */
@@ -3454,6 +4099,12 @@ declare const zh$3: {
3454
4099
  readonly 'common.retry': '重试';
3455
4100
  readonly 'common.loading': '加载中…';
3456
4101
  readonly 'common.unknownError': '未知错误';
4102
+ readonly 'common.parens': '({text})';
4103
+ readonly 'about.cli.help': '列出全部 CLI 命令与用法(离线可用)';
4104
+ readonly 'about.cli.snapshots': '列出本机回滚快照(无需 DSH 运行)';
4105
+ readonly 'about.cli.restore': '恢复到导入前状态(离线)';
4106
+ readonly 'about.cli.reinstall': '一键重装 DSH(救援)';
4107
+ readonly 'common.listSeparator': '、';
3457
4108
  readonly 'toast.copied': '已复制到剪贴板';
3458
4109
  readonly 'toast.copyFailed': '复制失败,请手动选择文本复制';
3459
4110
  readonly 'toast.refreshed': '已刷新';
@@ -3527,7 +4178,6 @@ declare const zh$3: {
3527
4178
  readonly 'export.includeSecrets': '导出密钥';
3528
4179
  readonly 'export.includeSecretsHint': '把真实密钥(凭据值)写入备份。密钥必须以加密形式保存:勾选时会自动选中「加密备份」;取消「加密备份」会同时取消「导出密钥」。';
3529
4180
  readonly 'export.run': '开始导出';
3530
- readonly 'export.previewSkipped': '{count} 个分区导出失败已跳过';
3531
4181
  readonly 'export.running': '正在导出…';
3532
4182
  readonly 'export.download': '下载备份文件';
3533
4183
  readonly 'export.saved': '已保存到下载目录:{name}';
@@ -3660,10 +4310,7 @@ declare const zh$3: {
3660
4310
  readonly 'import.paths.unresolved': '还有 {count} 条路径未映射(留空将跳过该路径,可以继续)';
3661
4311
  readonly 'import.paths.empty': '无需映射路径';
3662
4312
  readonly 'snapshots.title': '备份与快照';
3663
- readonly 'snapshots.subTab.restore': '安全快照';
3664
- readonly 'snapshots.subTab.files': '备份文件';
3665
- readonly 'snapshots.subTab.schedule': '定时备份';
3666
- readonly 'snapshots.subTab.recovery': '事故恢复';
4313
+ readonly 'home.schedule.title': '定时备份';
3667
4314
  readonly 'snapshots.empty.title': '尚无安全快照';
3668
4315
  readonly 'snapshots.empty.body': '安全快照在导入 / 恢复前自动创建,用于一键回滚;也可立即手动创建一个。';
3669
4316
  readonly 'snapshots.empty.viewFiles': '查看备份文件';
@@ -3925,6 +4572,13 @@ declare const zh$3: {
3925
4572
  readonly 'profiles.shape.web': 'Web';
3926
4573
  readonly 'profiles.shape.headless': 'Headless';
3927
4574
  readonly 'profiles.shape.generic': '自定义';
4575
+ readonly 'profiles.shape.incomplete': '未完成的副本';
4576
+ readonly 'profiles.incomplete.from': '从「{name}」复制';
4577
+ readonly 'profiles.incomplete.startedAt': '开始于 {time}';
4578
+ readonly 'profiles.incomplete.dir': '目录 {path}';
4579
+ readonly 'profiles.incomplete.hint': '这是一次被中断的档案复制:没有 package.json,无法启动。确认不需要后可直接删除(只删这个目录,不影响其它档案)。';
4580
+ readonly 'profiles.list.incompleteCount': '未完成的副本 {count} 个(不可启动,可直接删除)';
4581
+ readonly 'profiles.delete.incompleteMessage': '确认删除未完成的副本「{name}」?将物理删除整个目录(含已拷入的部分文件),不可恢复。';
3928
4582
  readonly 'profiles.issue.manifestInvalid': 'package.json 损坏';
3929
4583
  readonly 'profiles.issue.patchTooLarge': 'patch 文件过大(未展示原文)';
3930
4584
  readonly 'profiles.bundles': '插件层(bundles)';
@@ -3989,7 +4643,7 @@ declare const zh$3: {
3989
4643
  readonly 'import.compatibility.score.partial': '部分兼容';
3990
4644
  readonly 'import.compatibility.score.unsupported': '不支持';
3991
4645
  readonly 'import.compatibility.sectionsTitle': '备份包含的分区';
3992
- readonly 'nav.overview': '总览';
4646
+ readonly 'nav.home': '首页';
3993
4647
  readonly 'nav.backups': '备份';
3994
4648
  readonly 'nav.export': '导出';
3995
4649
  readonly 'nav.import': '导入';
@@ -3997,6 +4651,7 @@ declare const zh$3: {
3997
4651
  readonly 'nav.market': '市场';
3998
4652
  readonly 'nav.profiles': '档案';
3999
4653
  readonly 'nav.refresh': '刷新';
4654
+ readonly 'shell.running.restore': '快照恢复';
4000
4655
  readonly 'shell.status.idle': '就绪';
4001
4656
  readonly 'shell.status.running': '{count} 个任务进行中';
4002
4657
  readonly 'shell.status.recovery': '恢复待处理';
@@ -4063,18 +4718,6 @@ declare const zh$3: {
4063
4718
  readonly 'overview.result.skipped': '跳过';
4064
4719
  readonly 'overview.activity.copy': '复制';
4065
4720
  readonly 'overview.activity.redacted': '(文件名已脱敏)';
4066
- readonly 'overview.location.title': '备份位置';
4067
- readonly 'overview.location.dir': '备份目录';
4068
- readonly 'overview.location.totalSize': '备份总体积';
4069
- readonly 'overview.location.retention': '快照保留';
4070
- readonly 'overview.location.retentionValue': '{used} / {limit}';
4071
- readonly 'overview.location.schedule': '定时备份';
4072
- readonly 'overview.location.scheduleOff': '未开启';
4073
- readonly 'overview.location.nextRun': '下次备份';
4074
- readonly 'overview.location.lastRun': '上次备份';
4075
- readonly 'overview.sections.title': '分区构成';
4076
- readonly 'overview.sections.hint': '按当前配置估算(只读预览,零写入)';
4077
- readonly 'overview.sections.total': '合计';
4078
4721
  readonly 'overview.sections.entries': '{count} 项';
4079
4722
  readonly 'overview.quick.exportTitle': '生成可迁移的 ZIP 备份文件并下载';
4080
4723
  readonly 'overview.quick.importTitle': '从备份文件恢复或迁移到本机';
@@ -4105,6 +4748,26 @@ declare const zh$3: {
4105
4748
  readonly 'about.update.noCommand': '未识别到当前档案,或该档案由桌面端独占管理 —— 请在 DSH 的插件页更新本插件。';
4106
4749
  readonly 'about.update.check': '检查更新';
4107
4750
  readonly 'about.update.recheck': '重新检查';
4751
+ readonly 'about.update.apply': '立即更新';
4752
+ readonly 'about.update.applied': '已更新到 {version},重启 DSH 后生效';
4753
+ readonly 'about.update.dialog.title': '更新到 {version}';
4754
+ readonly 'about.update.dialog.from': '当前版本 {current}';
4755
+ readonly 'about.update.dialog.loadingNotes': '正在获取更新说明…';
4756
+ readonly 'about.update.dialog.notesFailed': '获取更新说明失败:{error}(不影响更新)';
4757
+ readonly 'about.update.dialog.noNotes': '未找到 v{version} 的发布说明,可直接更新。';
4758
+ readonly 'about.update.dialog.notExact': '未找到 v{version} 的发布说明,以下为最新一条发布内容。';
4759
+ readonly 'about.update.dialog.viewOnGithub': '在 GitHub 查看全部版本';
4760
+ readonly 'about.update.dialog.viewReleaseOnGithub': '在 GitHub 查看此版本';
4761
+ readonly 'about.update.dialog.install': '立即更新';
4762
+ readonly 'about.update.dialog.installing': '正在更新,请稍候…';
4763
+ readonly 'about.update.dialog.done': '更新完成:已安装 v{version}。';
4764
+ readonly 'about.update.dialog.restart': '请重启 DSH 使新版本生效(完全退出后重新启动;正在运行的进程仍是旧版本)。';
4765
+ readonly 'about.update.code.invalidVersion': '版本号无效,未能更新。';
4766
+ readonly 'about.update.code.profileUnknown': '无法识别当前档案,请在 DSH 的插件页更新本插件。';
4767
+ readonly 'about.update.code.unsupportedProfile': '桌面端档案由桌面应用独占管理,请在 DSH 的插件页更新本插件。';
4768
+ readonly 'about.update.code.nonRegistryInstall': '当前是本机/开发来源安装(link/file/git),不会用 registry 版本覆盖它 —— 请在来源目录更新。';
4769
+ readonly 'about.update.code.notNewer': '目标版本不高于当前版本,无需更新。';
4770
+ readonly 'about.update.code.installFailed': '更新失败:{error}';
4108
4771
  readonly 'palette.group.action': '动作';
4109
4772
  readonly 'palette.group.library': '产物库';
4110
4773
  readonly 'palette.group.navigate': '前往';
@@ -4171,10 +4834,104 @@ declare const zh$3: {
4171
4834
  readonly 'palette.view.activity': '活动记录';
4172
4835
  readonly 'palette.view.about': '关于';
4173
4836
  readonly 'palette.rescue.recovery': '事故恢复';
4837
+ readonly 'palette.rescue.mode': '救援模式';
4174
4838
  readonly 'import.reason.schemaUnsupported': '包内 schema 版本 v{version} 超出本插件支持范围';
4175
4839
  readonly 'import.reason.missingSections': '备份声明但包内缺失 {count} 个分区:{sections}';
4176
4840
  readonly 'import.reason.sourceNewer': '备份来自更新的 DSH({source} → 本机 {target}):可能有本机不认识的配置';
4177
4841
  readonly 'import.reason.sourceOlder': '备份来自更旧的 DSH({source} → 本机 {target}):向后兼容';
4842
+ readonly 'foreign.source.title': '从其它 agent 导入';
4843
+ readonly 'foreign.source.hint': '读取本机已装的其它 agent 配置,先看清将导入什么,再交给既有的导入向导(分析只读,零写入)。';
4844
+ readonly 'foreign.source.selectTitle': '选择来源';
4845
+ readonly 'foreign.source.loading': '正在检测本机配置…';
4846
+ readonly 'foreign.source.empty': '未检测到任何可导入的其它 agent 配置。';
4847
+ readonly 'foreign.source.unknown': '未识别的来源。';
4848
+ readonly 'foreign.source.found': '已检测到';
4849
+ readonly 'foreign.source.notFound': '未检测到';
4850
+ readonly 'foreign.source.paths': '路径';
4851
+ readonly 'foreign.source.locationOverridden': '位置由环境变量覆盖';
4852
+ readonly 'foreign.source.detectFailed': '检测失败:{reason}';
4853
+ readonly 'foreign.source.claude-code': 'Claude Code';
4854
+ readonly 'foreign.source.hermes': 'Hermes';
4855
+ readonly 'foreign.source.cursor': 'Cursor';
4856
+ readonly 'foreign.source.codex': 'Codex CLI';
4857
+ readonly 'foreign.source.copilot': 'GitHub Copilot CLI';
4858
+ readonly 'foreign.source.antigravity': 'Google Antigravity';
4859
+ readonly 'foreign.source.gemini': 'Gemini CLI';
4860
+ readonly 'foreign.source.reasonix': 'Reasonix';
4861
+ readonly 'foreign.source.opencode': 'OpenCode';
4862
+ readonly 'foreign.source.mimocode': 'MimoCode';
4863
+ readonly 'foreign.source.zcode': 'ZCode';
4864
+ readonly 'foreign.source.grokbuild': 'Grok Build';
4865
+ readonly 'foreign.source.openclaw': 'OpenClaw';
4866
+ readonly 'foreign.source.pi': 'Pi';
4867
+ readonly 'foreign.source.kimi': 'Kimi CLI';
4868
+ readonly 'foreign.source.kilocode': 'Kilo Code';
4869
+ readonly 'foreign.source.qoder': 'Qoder';
4870
+ readonly 'foreign.source.chatgpt': 'ChatGPT';
4871
+ readonly 'foreign.source.workbuddy': 'WorkBuddy';
4872
+ readonly 'foreign.source.qwen': '千问办公';
4873
+ readonly 'foreign.source.continue': 'Continue';
4874
+ readonly 'foreign.source.cline': 'Cline';
4875
+ readonly 'foreign.source.goose': 'Goose';
4876
+ readonly 'foreign.source.dsh4': 'DSH 会话日志(V4 代次)';
4877
+ readonly 'foreign.source.zed': 'Zed';
4878
+ readonly 'foreign.source.crush': 'Crush';
4879
+ readonly 'foreign.source.teleagent': 'TeleAgent';
4880
+ readonly 'foreign.source.trae': 'Trae';
4881
+ readonly 'foreign.source.vibe': 'Vibe';
4882
+ readonly 'foreign.source.dsh': 'DSH 会话日志(V0-V3 代次)';
4883
+ readonly 'foreign.action.import': '开始导入';
4884
+ readonly 'foreign.action.preview': '查看将导入的内容';
4885
+ readonly 'foreign.action.refresh': '重新检测';
4886
+ readonly 'foreign.action.retry': '重试';
4887
+ readonly 'foreign.action.close': '关闭';
4888
+ readonly 'foreign.loading': '正在读取外部配置…';
4889
+ readonly 'foreign.importing': '正在转换外部配置…';
4890
+ readonly 'foreign.importFailed': '导入失败:{reason}';
4891
+ readonly 'foreign.previewTitle': '将导入的内容';
4892
+ readonly 'foreign.previewEmpty': '该来源没有可导入的配置项。';
4893
+ readonly 'foreign.previewSections': '包含分区:{sections}';
4894
+ readonly 'foreign.previewCounts': '共 {count} 项计划动作';
4895
+ readonly 'foreign.previewDryRun': '只读预览:不会写入任何配置。';
4896
+ readonly 'foreign.previewReset': '来源或检测结果已变化:上一次的产包结果已作废,请重新点击「开始导入」生成新的包。';
4897
+ readonly 'foreign.lossy.title': '已知有损(导入前必读)';
4898
+ readonly 'foreign.lossy.hint': '下面三条是「外部配置 → bundle → 导入」这条流水线的既有行为:都不阻断导入,兼容性评分也不会为它们给出原因。';
4899
+ readonly 'foreign.lossy.applies': '本包适用';
4900
+ readonly 'foreign.lossy.notApplies': '本包不涉及';
4901
+ readonly 'foreign.credentialRefs': '需补录凭据 {count} 项(值未随导入带出,请在本机补录)';
4902
+ readonly 'foreign.credentialRefsNone': '无需补录凭据';
4903
+ readonly 'foreign.reportOnly': '只报告、不导入:{detail}';
4904
+ readonly 'foreign.skipped': '未迁移 {count} 项';
4905
+ readonly 'foreign.skip.unsupported-hooks': 'settings 的 hooks:DSH 无对等结构,未迁移';
4906
+ readonly 'foreign.skip.unsupported-commands': '斜杠命令:与 DSH 提示词不是同一语义,本次未迁移';
4907
+ readonly 'foreign.skip.credentials-not-migrated': '凭据字段只记录名字,值不读取也不迁移';
4908
+ readonly 'foreign.skip.skill-missing-file': '技能目录缺少 SKILL.md,未迁移';
4909
+ readonly 'foreign.skip.skill-invalid-frontmatter': '技能 frontmatter 非法(缺 name/description 或不是合法 YAML),DSH 会静默丢弃,故未迁移';
4910
+ readonly 'foreign.skip.skill-invalid-name': '技能名含非法字符或路径穿越,未迁移';
4911
+ readonly 'foreign.skip.mcp-server-empty': 'MCP 条目既无 command 也无 url,未迁移';
4912
+ readonly 'foreign.skip.mcp-type-sse-coerced': 'MCP type=sse:按带 url 的 http 处理';
4913
+ readonly 'foreign.skip.mcp-credential-redacted': 'MCP 值里发现凭据字段:值已丢弃,只保留字段名与引用名';
4914
+ readonly 'foreign.skip.source-unreadable': '外部文件读不到、超限或解析失败';
4915
+ readonly 'foreign.skip.source-empty-file': '配置文件存在但为空(0 字节):如实上报,不产出空分区';
4916
+ readonly 'foreign.skip.source-location-overridden': '配置位置被环境变量覆盖,按覆盖后的位置读取';
4917
+ readonly 'foreign.skip.session-cwd-derived': '会话记录里没有 cwd:按源侧目录名推导出工作目录,且该目录在本机确实存在(推不出来的一律按「缺少 cwd」跳过)';
4918
+ readonly 'foreign.skip.source-needs-explicit-path': '该来源没有自动探测位置:必须显式提供导出文件路径(自动探测永远不会命中)';
4919
+ readonly 'foreign.skip.session-format-version-unknown': '本机 DSH 会话格式版本未知:不猜版本,整批会话未迁移';
4920
+ readonly 'foreign.skip.session-format-unsupported': '本机 DSH 会话格式版本不受支持,该会话未迁移';
4921
+ readonly 'foreign.skip.session-missing-cwd': '会话记录缺少 cwd,无法归位到工作区';
4922
+ readonly 'foreign.skip.session-unsafe-id': '会话文件名不能作为安全路径段,未迁移';
4923
+ readonly 'foreign.skip.session-empty': '会话没有任何可迁移的事件';
4924
+ readonly 'foreign.skip.session-unparsable': '会话存在解析不出来的行,未迁移';
4925
+ readonly 'foreign.skip.unsupported-session-record': '该类型的会话记录本版不迁移';
4926
+ readonly 'foreign.skip.session-id-conflict': '同 id 会话已存在:不覆盖,跳过并保留本机既有的那条';
4927
+ readonly 'foreign.skip.skill-id-conflict': '技能重名:先到先得,其余跳过';
4928
+ readonly 'foreign.skip.sessions-not-migrated': '该来源的对话存储形态本版不迁移(只报告,不产出会话分区)';
4929
+ readonly 'foreign.skip.memory-report-only': '记忆文件只报告、不导入(正文不进备份包)';
4930
+ readonly 'foreign.skip.skill-category-flattened': '技能带分类层级:已压平为 DSH 的单层技能目录';
4931
+ readonly 'foreign.skip.legacy-rules-file': '旧式规则文件:DSH 无对等结构,只报告';
4932
+ readonly 'foreign.skip.instructions-merged': '多份指令源被合并为一个全局指令文件';
4933
+ readonly 'foreign.skip.instructions-override-selected': '命中更高优先级的指令文件(override),按它导入';
4934
+ readonly 'foreign.conflict.policy': '同 id 冲突:不覆盖本机既有内容,跳过并在报告里逐条说明';
4178
4935
  };
4179
4936
  /** 字典键联合(注册处 compile-time 校验) */
4180
4937
  type ConfigManagerKey = keyof typeof zh$3;
@@ -4203,9 +4960,13 @@ declare const zh$2: {
4203
4960
  readonly 'channel.title': '同步通道';
4204
4961
  readonly 'channel.git': 'Git 私有仓库';
4205
4962
  readonly 'channel.webdav': 'WebDAV 服务器';
4206
- readonly 'channel.perChannelHint': 'GitHub 与 WebDAV 通道的自动同步、同步模式、加密与远端快照各自独立配置。';
4963
+ readonly 'channel.s3': '对象存储(S3 兼容)';
4964
+ readonly 'channel.gist': 'GitHub Gist';
4965
+ readonly 'channel.perChannelHint': '每条通道(Git / WebDAV / 对象存储 / Gist)的自动同步、同步模式、加密与远端快照各自独立配置。';
4207
4966
  readonly 'channel.open': '配置同步通道';
4208
4967
  readonly 'channel.openHint': '远程同步通过「同步通道」进行:Git 私有仓库或 WebDAV 服务器。点击按钮在弹窗中配置或修改。';
4968
+ readonly 'channel.expand': '展开通道详情';
4969
+ readonly 'channel.collapse': '收起通道详情';
4209
4970
  readonly 'channel.clear': '断开配置';
4210
4971
  readonly 'channel.clearConfirmTitle': '断开同步通道配置?';
4211
4972
  readonly 'channel.clearConfirmMessage': '将删除「{channel}」的本机配置、已保存的凭据与自动同步开关。远端快照与本机备份不受影响;断开后可重新配置。';
@@ -4236,6 +4997,29 @@ declare const zh$2: {
4236
4997
  readonly 'github.userCode': '一次性授权代码';
4237
4998
  readonly 'github.openAuth': '打开 GitHub 授权页面';
4238
4999
  readonly 'github.clientIdHint': '需要插件配置 githubClientId(GitHub OAuth App 的 client_id)才能使用 GitHub 登录。';
5000
+ readonly 'repoPicker.label': '从我的仓库中选择';
5001
+ readonly 'repoPicker.hint': '列出你 GitHub 账号下**已有的私有仓库**(按最近更新排序),选中即填入下方仓库地址;也可以直接在下方手填地址(ssh / 本地路径 / 不在列表里的仓库)。列表需要先登录 GitHub;新建的仓库一律为私有 —— 公开仓库会公开你的配置内容。';
5002
+ readonly 'repoPicker.placeholder': '手动填写地址(或从上方选择)';
5003
+ readonly 'repoPicker.refresh': '刷新列表';
5004
+ readonly 'repoPicker.refreshing': '刷新中…';
5005
+ readonly 'repoPicker.forkBadge': 'Fork';
5006
+ readonly 'repoPicker.empty': '没有可用的私有仓库,可选「新建私有仓库」。';
5007
+ readonly 'repoPicker.loadFailed': '仓库列表加载失败,可重试或直接手填地址。';
5008
+ readonly 'repoPicker.updatedAt': '更新于 {time}';
5009
+ readonly 'repoPicker.create': '+ 新建私有仓库…';
5010
+ readonly 'repoPicker.createTitle': '新建私有仓库';
5011
+ readonly 'repoPicker.name': '仓库名';
5012
+ readonly 'repoPicker.namePlaceholder': '如 dsh-configs';
5013
+ readonly 'repoPicker.description': '描述';
5014
+ readonly 'repoPicker.descriptionPlaceholder': '可选,如「我的配置仓库(dsh-config-manager 自动发布)」';
5015
+ readonly 'repoPicker.createSubmit': '创建并选用';
5016
+ readonly 'repoPicker.creating': '创建中…';
5017
+ readonly 'repoPicker.createCancel': '取消';
5018
+ readonly 'repoPicker.created': '已创建私有仓库 {name},地址已填入。';
5019
+ readonly 'repoPicker.createFailed': '新建仓库失败';
5020
+ readonly 'repoPicker.nameRequired': '请填写仓库名。';
5021
+ readonly 'repoPicker.nameInvalid': '仓库名只能包含字母、数字、点、下划线、连字符(最长 100 字符,不能以点开头)。';
5022
+ readonly 'repoPicker.privateOnly': '新建的仓库固定为私有:公开仓库会公开你的配置内容。';
4239
5023
  readonly 'status.title': '同步状态';
4240
5024
  readonly 'status.never': '从未同步';
4241
5025
  readonly 'action.push': '推送到远端';
@@ -4424,6 +5208,56 @@ declare const zh$2: {
4424
5208
  readonly 'syncflow.compat.good': '兼容性:良好(备份来自更旧的 DSH)';
4425
5209
  readonly 'syncflow.compat.partial': '兼容性:部分兼容(跨平台 / 分区缺失 / 版本超前,需人工确认)';
4426
5210
  readonly 'syncflow.compat.unsupported': '兼容性:不受支持(格式版本超出范围)';
5211
+ readonly 'cloud.s3Title': '对象存储(S3 兼容)';
5212
+ readonly 'cloud.gistTitle': 'GitHub Gist';
5213
+ readonly 'cloud.provider': '兼容商';
5214
+ readonly 'cloud.providerHint': '五家共用同一套 SigV4 签名实现;端点与寻址风格按兼容商取缺省。';
5215
+ readonly 'cloud.provider.s3': 'AWS S3';
5216
+ readonly 'cloud.provider.oss': '阿里云 OSS';
5217
+ readonly 'cloud.provider.cos': '腾讯云 COS';
5218
+ readonly 'cloud.provider.minio': 'MinIO';
5219
+ readonly 'cloud.provider.kodo': '七牛 Kodo';
5220
+ readonly 'cloud.endpoint': '端点 Endpoint';
5221
+ readonly 'cloud.endpointHint': '不含桶名与凭据,例如 https://s3.us-east-1.amazonaws.com。';
5222
+ readonly 'cloud.region': '区域 Region';
5223
+ readonly 'cloud.regionHint': 'V4 签名作用域,例如 us-east-1 / cn-hangzhou。';
5224
+ readonly 'cloud.bucket': '存储桶 Bucket';
5225
+ readonly 'cloud.bucketHint': '3-63 位小写字母、数字、点或连字符,首尾须为字母或数字。';
5226
+ readonly 'cloud.prefix': '对象键前缀(可选)';
5227
+ readonly 'cloud.prefixHint': '留空 = 根前缀;首尾斜杠会被忽略。';
5228
+ readonly 'cloud.accessKeyId': 'AccessKey ID';
5229
+ readonly 'cloud.accessKeyIdHint': '标识符(非密钥,会写入配置文件);Secret 请填在下方密钥框。';
5230
+ readonly 'cloud.pathStyle': '使用 path-style 寻址';
5231
+ readonly 'cloud.pathStyleHint': 'MinIO 等自建服务通常需要;不勾选则跟随兼容商缺省。';
5232
+ readonly 'cloud.secret': 'Secret AccessKey';
5233
+ readonly 'cloud.secretHint': '值只写入 DSH 凭据槽位({ref}):不进配置文件、不进日志、不回传浏览器;留空表示沿用已保存的密钥。';
5234
+ readonly 'cloud.secretSaved': '密钥已保存';
5235
+ readonly 'cloud.secretPlaceholder': '••••••••';
5236
+ readonly 'cloud.gistId': 'Gist ID';
5237
+ readonly 'cloud.gistIdHint': 'gist 地址末段的十六进制 id(如 https://gist.github.com/<用户>/<id>)。';
5238
+ readonly 'cloud.apiBaseUrl': 'API 根地址(可选)';
5239
+ readonly 'cloud.apiBaseUrlHint': '留空 = https://api.github.com;GitHub Enterprise 可改为自建地址。';
5240
+ readonly 'cloud.filePrefix': '文件名前缀(可选)';
5241
+ readonly 'cloud.filePrefixHint': 'gist 内的文件名前缀,留空 = dsh-sync。';
5242
+ readonly 'cloud.token': 'Gist token';
5243
+ readonly 'cloud.tokenHint': '值只写入 DSH 凭据槽位({ref}):不进配置文件、不进日志、不回传浏览器;留空表示沿用已保存的 token。';
5244
+ readonly 'cloud.tokenSaved': 'token 已保存';
5245
+ readonly 'cloud.tokenPlaceholder': 'ghp_… 或 gho_…';
5246
+ readonly 'cloud.invalidTitle': '还有必填项或格式问题没解决:';
5247
+ readonly 'cloud.providerUnknown': '兼容商不在支持列表内';
5248
+ readonly 'cloud.endpointRequired': '请填写端点地址';
5249
+ readonly 'cloud.endpointInvalid': '端点地址必须是 http(s) 且不含空白 / 查询串 / 锚点';
5250
+ readonly 'cloud.endpointUserinfo': '端点地址不得包含用户名或密码';
5251
+ readonly 'cloud.regionRequired': '请填写区域(region)';
5252
+ readonly 'cloud.bucketRequired': '请填写存储桶名';
5253
+ readonly 'cloud.bucketInvalid': '桶名不合规:3-63 位小写字母、数字、点或连字符,首尾为字母或数字,且不得含 “..”';
5254
+ readonly 'cloud.prefixInvalid': '对象键前缀不得含反斜杠、“//” 或 “..”';
5255
+ readonly 'cloud.accessKeyIdRequired': '请填写 AccessKey ID';
5256
+ readonly 'cloud.gistIdRequired': '请填写 Gist ID';
5257
+ readonly 'cloud.gistIdInvalid': 'Gist ID 必须是 5-64 位十六进制串';
5258
+ readonly 'cloud.apiBaseUrlInvalid': 'API 根地址必须是 http(s) 且不含用户名/密码';
5259
+ readonly 'cloud.secretWriterRequired': '宿主未提供凭据写入通道,无法保存密钥';
5260
+ readonly 'cloud.credentialsWriteFailed': '密钥写入 DSH 凭据失败(配置未保存)';
4427
5261
  };
4428
5262
  /** 字典键联合(注册处 compile-time 校验) */
4429
5263
  type SyncKey = keyof typeof zh$2;
@@ -4773,7 +5607,7 @@ declare const zh: {
4773
5607
  readonly 'recovery.rescue.stale': '救援标记已失效(换机或重建 home)';
4774
5608
  readonly 'sessions.title': '会话体检';
4775
5609
  readonly 'sessions.readOnly': '扫描只读';
4776
- readonly 'sessions.desc': '扫描本机存量会话,找出「读不出来 / 下次请求会失败 / 看不见」的对话。扫描本身只读;对「重放重复行」这一类可零损失修复的问题,本页可直接修复(先预览、自动备份、可回滚)。其余损坏类别仍只能走离线 CLI。';
5610
+ readonly 'sessions.desc': '扫描本机存量会话,按四档严重级逐条给出结论:会让 DSH 起不来 / 会话读不出来(无法加载)/ 下次请求会失败 / 看不见。扫描本身只读,不改动任何字节。应用内可修的只有两类:零损失 —— 重放重复行、可证明的合成收尾块(丢弃即恢复);有损 —— 序列空洞、不可解析行(会截断,必须逐条显式确认,绝不批量)。两类都先预览、自动备份、可回滚。其余类别的真实出路有三条:① 会话布局归位(会话目录与首帧 cwd 不一致时搬回正确位置);② 重复 id 隔离(保留哪一份由你指定,其余移入隔离目录)—— 这两类既可在本面板直接执行(会话体检弹窗里的「会话布局归位」入口 —— 在 DSH 运行时执行、靠门前置与逐条回滚兜底),也可以用离线 dcm sessions repair --fix;③ 容器或首帧读不出来、格式超前、未登记工作区、子代理缺父 —— 本工具不修(离线 CLI 也修不了),需人工处置或 DSH 侧动作。';
4777
5611
  readonly 'common.infoHint': '查看说明';
4778
5612
  readonly 'sessions.scanning': '体检中…';
4779
5613
  readonly 'sessions.scan': '开始体检';
@@ -4800,7 +5634,7 @@ declare const zh: {
4800
5634
  readonly 'sessions.subagent': '子代理';
4801
5635
  readonly 'sessions.truncated': '列表已截断:还有 {count} 条未显示(重新体检或按需缩小范围)。';
4802
5636
  readonly 'sessions.repair.title': '怎么修';
4803
- readonly 'sessions.repair.desc': '容器非法 / header 不可读 / 格式超前这类**应用内不动**的问题,先在终端预览再落盘;需要写入时建议先关闭 DSH。';
5637
+ readonly 'sessions.repair.desc': '容器非法 / header 不可读 / 格式超前这类应用内不动的问题,先在终端预览再落盘;需要写入时建议先关闭 DSH。';
4804
5638
  readonly 'sessions.repair.copy': '复制命令';
4805
5639
  readonly 'recovery.safeMode.done': '已解除安全模式,配置修改已恢复';
4806
5640
  readonly 'recovery.safeMode.refused': '仍有未处理的恢复事项,已拒绝解除(请先处理下方事项)';
@@ -4810,7 +5644,7 @@ declare const zh: {
4810
5644
  readonly 'recovery.safeMode.action': '解除安全模式';
4811
5645
  readonly 'recovery.safeMode.confirmTitle': '解除安全模式';
4812
5646
  readonly 'recovery.safeMode.confirmMessage': '解除后,会修改配置的操作(同步 / 导入 / 保存设置)立即恢复可用。仅当该次中断确实已被放弃、且没有其他未处理的恢复事项时才应解除。是否继续?';
4813
- readonly 'sessions.repair.none': '本次没有可应用内修复的会话。应用内可修:重放重复行 / 可证明的合成收尾块(零损失)、seq 空洞与不可解析行(**截断,有损**,需确认);其余问题见下方离线命令。';
5647
+ readonly 'sessions.repair.none': '本次没有可应用内修复的会话。应用内可修:重放重复行 / 可证明的合成收尾块(零损失)、seq 空洞与不可解析行(截断,有损,需确认);其余问题见下方离线命令。';
4814
5648
  readonly 'common.close': '关闭';
4815
5649
  readonly 'sessions.dialog.open': '打开会话体检';
4816
5650
  readonly 'sessions.dialog.hint': '打开后扫描本机存量会话:哪些读不出来、哪些能应用内修复,都在弹窗里处理(扫描只读)。';
@@ -4827,7 +5661,7 @@ declare const zh: {
4827
5661
  readonly 'sessions.repair.actionLossless': '零损失';
4828
5662
  readonly 'sessions.repair.actionLossy': '有损';
4829
5663
  readonly 'sessions.repair.applyLossy': '截断并修复';
4830
- readonly 'sessions.repair.plan.lossy': '这个计划含**有损**动作:截断点之后的事件会被丢弃(无法从日志里恢复,但备份可以一键回滚)。确认后再点「截断并修复」。';
5664
+ readonly 'sessions.repair.plan.lossy': '这个计划含有损动作:截断点之后的事件会被丢弃(无法从日志里恢复,但备份可以一键回滚)。确认后再点「截断并修复」。';
4831
5665
  readonly 'sessions.repair.plan.title': '修复计划:{session}';
4832
5666
  readonly 'sessions.repair.plan.summary': '将丢弃 {rows} 行重放重复事件({before} → {after});其余字节原样保留。';
4833
5667
  readonly 'sessions.repair.plan.backup': '写入前会自动时间戳备份;应用后可在下方「修复记录」里一键回滚。';
@@ -4843,6 +5677,16 @@ declare const zh: {
4843
5677
  readonly 'sessions.repair.history.rolledBack': '已回滚';
4844
5678
  readonly 'sessions.repair.history.dropped': '丢弃 {rows} 行';
4845
5679
  readonly 'sessions.repair.history.unreadable': '修复台账读不出来,本次无法显示或回滚历史修复(备份文件仍在会话目录里)。';
5680
+ readonly 'sessions.zip.action': '下载原始日志 (ZIP)';
5681
+ readonly 'sessions.zip.hint': '由 DSH 自己打包这条会话的原始日志(含子会话与附件);不经过本插件,孤儿/多代日志一并带上。';
5682
+ readonly 'sessions.zip.checking': '正在检查导出能力…';
5683
+ readonly 'sessions.zip.reason.serviceMissing': '当前 DSH 的会话导出通道不可用:持久化后端缺少必需的服务(session-query / session-persistence / attachments)。这条入口已停用(状态 {status})。';
5684
+ readonly 'sessions.zip.reason.authRequired': '无法确认导出通道的可用性:本机自请求被认证挡在门外(状态 {status})。这不代表本机不支持导出 —— 请重启 DSH 后再试。';
5685
+ readonly 'sessions.zip.reason.readFailed': '导出通道在线,但这条会话的日志读取失败(状态 {status})。请先用上方体检/修复处理这条会话。';
5686
+ readonly 'sessions.zip.reason.networkError': '探测导出通道时拿不到响应(连不上或超时)。入口保持可用:真正点下载时若仍失败,会由 DSH 给出具体原因。';
5687
+ readonly 'sessions.zip.reason.unexpectedStatus': '导出通道返回了未预期的状态({status})。入口保持可用,但下载可能失败。';
5688
+ readonly 'sessions.zip.done': '已开始下载:{name}';
5689
+ readonly 'sessions.zip.failed': '下载失败';
4846
5690
  readonly 'sessions.repair.reason.unknownUnit': '这条会话在会话库里找不到了(可能刚被移动或删除)。';
4847
5691
  readonly 'sessions.repair.reason.notFound': '会话日志文件不在了。';
4848
5692
  readonly 'sessions.repair.reason.locked': '会话目录里有 session.lock —— 可能正被使用,已拒绝写入。';
@@ -4856,13 +5700,145 @@ declare const zh: {
4856
5700
  readonly 'sessions.repair.reason.tornTail': '只有末尾撕裂帧(DSH 自己会截断自愈),无需修复。';
4857
5701
  readonly 'sessions.repair.reason.invalidHeader': '首帧 header 不是合法单行 JSON —— 应用内不重建 header。';
4858
5702
  readonly 'sessions.repair.reason.nothingToFix': '没有发现可零损失修复的重放重复行。';
4859
- readonly 'sessions.repair.reason.lossyRequired': '这条会话只能做**有损**修复(截断),需要你显式确认后才会执行。';
5703
+ readonly 'sessions.repair.reason.lossyRequired': '这条会话只能做有损修复(截断),需要你显式确认后才会执行。';
4860
5704
  readonly 'sessions.repair.reason.verificationRefused': '写前校验未通过,已拒绝修复。';
4861
5705
  readonly 'sessions.repair.reason.writeFailed': '写入失败(临时文件 / 备份 / 换入出错),原文件未改动。';
4862
5706
  readonly 'sessions.repair.reason.postcheckFailed': '写后复验未通过,已用备份还原。';
4863
5707
  readonly 'sessions.repair.reason.backupInvalid': '备份不可用或不可信,已拒绝回滚。';
4864
5708
  readonly 'sessions.repair.reason.unknown': '修复未成功(原因未知),原文件保持原样。';
5709
+ readonly 'sessions.repair.reason.verifyFailed': '写后真 codec 复验未通过:这次修复没有被接受(是否已自动回滚见下方复验结论)。';
5710
+ readonly 'sessions.repair.reason.targetChanged': '回滚前发现目标又被改过(指纹不一致),已拒绝覆盖 —— 绝不覆盖别人的内容。';
5711
+ readonly 'sessions.repair.verify.current': '复验通过:DSH 现役读盘路径此刻就能直接读这条会话。';
5712
+ readonly 'sessions.repair.verify.migrated': '复验通过:只有迁移链能还原它(不是 DSH 的现役读盘路径)——「迁移链可还原」不等于「现役读盘可读」。';
5713
+ readonly 'sessions.repair.verify.unverified': '未验证:本机跑不了真 codec 复验,所以 DSH 现在能否读它并没有被证明 —— 未验证不等于已验证(写入是否生效另说)。';
5714
+ readonly 'sessions.repair.verify.rollbackFailed': '危险态:复验失败后自动回滚没有成功,目标当前仍是修复后的字节,需要人工处理。';
4865
5715
  readonly 'sessions.repair.rejectedNext': '原文件没有被改动。可以再点一次「开始体检」看最新状态;如果原因与「文件被改过/正在被写入」有关,等这条会话安静下来再试。';
5716
+ readonly 'checkpoint.code.storage-unavailable': '检查点存储不可用';
5717
+ readonly 'checkpoint.code.ledger-write-failed': '检查点台账写不进去';
5718
+ readonly 'checkpoint.code.confirmation-required': '需要显式确认才能回滚';
5719
+ readonly 'checkpoint.code.record-not-found': '找不到该检查点';
5720
+ readonly 'checkpoint.code.protected-checkpoint': '该检查点受保护:不可回滚、不可删除';
5721
+ readonly 'checkpoint.code.record-incomplete': '该检查点三态不全,缺省不允许回滚';
5722
+ readonly 'checkpoint.code.guard-failed': '回滚前的保护点没能拍下来,已中止(零写入)';
5723
+ readonly 'checkpoint.code.invalid-input': '请求参数不合法';
5724
+ readonly 'checkpoint.code.no-chunks': '没有给出工作区路径分块';
5725
+ readonly 'checkpoint.code.chunk-not-absolute': '工作区分块必须是绝对路径';
5726
+ readonly 'checkpoint.code.chunk-not-found': '工作区分块不存在或不可用';
5727
+ readonly 'checkpoint.code.no-session-input': '没有指定会话(unitId 或 sessionLogPath)';
5728
+ readonly 'checkpoint.code.session-missing': '会话日志不存在';
5729
+ readonly 'checkpoint.code.session-out-of-root': '会话日志不在本机会话根内,已拒绝';
5730
+ readonly 'checkpoint.code.session-too-large': '会话日志超过副本上限:只记下了游标,该态不能自动回滚';
5731
+ readonly 'checkpoint.code.session-active': '会话日志刚被写过,为避免覆盖正在进行的对话而拒绝';
5732
+ readonly 'checkpoint.code.session-diverged': '会话日志比捕获游标还短(被别的路径改写或截断过),拒绝覆盖';
5733
+ readonly 'checkpoint.code.capture-degraded': '该态捕获不完整(有链接或读不到的内容被跳过,已逐条留痕)';
5734
+ readonly 'checkpoint.code.capture-truncated': '该态捕获到达上限被截断(已如实标注)';
5735
+ readonly 'checkpoint.code.capture-failed': '该态捕获失败';
5736
+ readonly 'checkpoint.code.nothing-to-restore': '该检查点没有可恢复的内容';
5737
+ readonly 'checkpoint.code.invalid-path': '记录里的路径越界(不在捕获分块内),已拒绝该条';
5738
+ readonly 'checkpoint.code.object-missing': '内容副本缺失,已拒绝该条';
5739
+ readonly 'checkpoint.code.object-hash-mismatch': '内容副本与记录指纹不一致,已拒绝该条';
5740
+ readonly 'checkpoint.code.restore-failed': '恢复失败(详见逐条细节)';
5741
+ readonly 'checkpoint.warn.ledgerUnreadable': '检查点台账读不出来(已按空台账继续,未静默)';
5742
+ readonly 'checkpoint.warn.trackMissing': '有一态没捕获到:该态本次不能回滚';
5743
+ readonly 'checkpoint.warn.trackDegraded': '有一态捕获不完整(回滚可能不完整)';
5744
+ readonly 'checkpoint.warn.protected': '该检查点受保护:不可回滚、不可删除';
5745
+ readonly 'checkpoint.warn.guardFailed': '回滚前的保护点没拍成(已记告警后继续)';
5746
+ readonly 'checkpoint.guidance.mountStorage': '检查点存储栈缺失:把 @deepseek-ai/dsh-storage、dsh-storage-json、dsh-storage-domain 组合进当前 profile 后重试';
5747
+ readonly 'checkpoint.guidance.fixDataDir': '插件数据目录不可写:{detail}';
5748
+ readonly 'checkpoint.guidance.readOnlyFallback': '存储不可用期间:捕获与回滚都会干净失败,但现状列表仍可查看(不会崩,也不会假装成功)';
5749
+ readonly 'checkpoint.guidance.probeDetail': '探测细节:{detail}';
5750
+ readonly 'checkpoint.guidance.sessionOffline': '该会话日志超上限或副本缺失:请用离线命令处理(路径见 detail)';
5751
+ readonly 'checkpoint.guidance.sessionRewritten': '已就地写回会话日志(路径见 detail);日志格式与目录位置不变';
5752
+ readonly 'checkpoint.guidance.workspacePartial': '工作区可能已部分恢复:后续段(配置/会话)本次未执行';
5753
+ readonly 'checkpoint.title': '检查点(会话 / 工作区 / 配置 三态同点)';
5754
+ readonly 'checkpoint.desc': '一次捕获记下三态的 capturedAt 与指纹,「同点」按跨度可核验;回滚只覆盖捕获过的内容,检查点之后新建的文件一律不删。';
5755
+ readonly 'checkpoint.capture': '拍一个检查点';
5756
+ readonly 'checkpoint.capture.chunks': '工作区路径(每行一个,绝对路径)';
5757
+ readonly 'checkpoint.capture.session': '关联会话';
5758
+ readonly 'checkpoint.capture.protect': '保护这个检查点(不可回滚、不可删除)';
5759
+ readonly 'checkpoint.list.empty': '还没有检查点';
5760
+ readonly 'checkpoint.col.time': '时间';
5761
+ readonly 'checkpoint.col.states': '三态';
5762
+ readonly 'checkpoint.col.spread': '同点跨度';
5763
+ readonly 'checkpoint.samePoint.yes': '同点(跨度 {ms} 毫秒)';
5764
+ readonly 'checkpoint.samePoint.no': '非同点:{reason}';
5765
+ readonly 'checkpoint.state.workspace': '工作区';
5766
+ readonly 'checkpoint.state.session': '会话游标';
5767
+ readonly 'checkpoint.state.config': '插件配置';
5768
+ readonly 'checkpoint.preview': '预览回滚';
5769
+ readonly 'checkpoint.rewind': '回滚到此处';
5770
+ readonly 'checkpoint.rewind.confirm': '我确认:将用该检查点覆盖工作区 / 配置 / 会话(新建的文件不会被删除)';
5771
+ readonly 'checkpoint.delete': '删除检查点';
5772
+ readonly 'checkpoint.legacy.guard': '回滚前的保护点';
5773
+ readonly 'recovery.incomplete.title': '未完成的档案副本';
5774
+ readonly 'recovery.incomplete.hint': '这些目录带「复制进行中」标记但没有 package.json,是复制被中断留下的半截副本;不能启动,只能删除(只列出有标记的目录 —— 用户手工建的目录不会出现在这里)。';
5775
+ readonly 'recovery.incomplete.from': '来源:{name}';
5776
+ readonly 'recovery.incomplete.startedAt': '开始于 {time}';
5777
+ readonly 'recovery.incomplete.dir': '目录:{dir}';
5778
+ readonly 'recovery.incomplete.delete': '删除残留';
5779
+ readonly 'recovery.incomplete.deleteConfirm': '我确认:物理删除该残留目录(不可恢复)';
5780
+ readonly 'recovery.incomplete.locked': '安全模式正在阻断写操作,删除未执行:{reason}';
5781
+ readonly 'recovery.incomplete.unlock': '解除安全模式';
5782
+ readonly 'recovery.incomplete.unreadable.title': '未能读取残留列表';
5783
+ readonly 'recovery.incomplete.unreadable.hint': '本次枚举残留目录失败 —— 这不等于「没有残留」。请确认档案目录可读后重试。';
5784
+ readonly 'sessions.layout.title': '会话布局归位(写动作)';
5785
+ readonly 'sessions.layout.desc': '修复「会让 DSH 起不来」的两类问题:会话目录与首帧 cwd 不一致时把会话搬回正确位置(只搬目录,不改写首帧),以及同一会话 id 出现在多个目录时只保留你选定的那一份、其余移入隔离目录(可人工找回)。';
5786
+ readonly 'sessions.layout.runtimeNote': '本入口在 DSH 运行时执行 —— 与离线 CLI 的「须先停 DSH」不同:靠门前置(SAFE MODE / 无 session.lock / 不在写入静止期)+ 每次移动后刷新会话索引 + 失败逐条回滚;索引刷新能力缺失时一条也不执行。';
5787
+ readonly 'sessions.layout.quarantineNote': '重复 id 必须由你选定保留哪一份;其余副本移入隔离目录(.cm-repair-quarantine-*,可人工找回),本入口不删除任何会话。';
5788
+ readonly 'sessions.layout.preview': '预览计划';
5789
+ readonly 'sessions.layout.previewing': '预览中…';
5790
+ readonly 'sessions.layout.planEmpty': '计划里没有需要执行的动作。';
5791
+ readonly 'sessions.layout.apiMissing': '当前接口不支持布局归位(缺少 layoutRepairSessions);请更新插件后重试 —— 本机未做任何改动。';
5792
+ readonly 'sessions.layout.planTitle': '布局归位计划(只读,尚未改动任何文件)';
5793
+ readonly 'sessions.layout.planReadOnly': '计划只读:确认前零写入。';
5794
+ readonly 'sessions.layout.noCandidates': '本机没有「布局归位 / 重复 id 隔离」这一档的问题会话:扫描结果里既没有需要归位的目录,也没有重复 id。';
5795
+ readonly 'sessions.layout.summary': '将归位 {move} 条、隔离 {quarantine} 条';
5796
+ readonly 'sessions.layout.planSkipped': '另有 {count} 条只报告(缺 cwd / 会话被锁 / 多份 generation 的 cwd 不一致)—— 本入口不动它们。';
5797
+ readonly 'sessions.layout.onlyReported': '只报告(不执行)';
5798
+ readonly 'sessions.layout.keepTitle': '重复 id:请选定保留哪一份';
5799
+ readonly 'sessions.layout.keepHint': '选中的那一份本轮不动;其余副本移入隔离目录。未选定之前不能执行。';
5800
+ readonly 'sessions.layout.keepMissing': '还有 {count} 个重复 id 未选定保留哪一份。';
5801
+ readonly 'sessions.layout.apply': '执行布局归位';
5802
+ readonly 'sessions.layout.applying': '执行中…';
5803
+ readonly 'sessions.layout.resultTitle': '布局归位结果';
5804
+ readonly 'sessions.layout.done': '归位 {moved} 条、隔离 {quarantined} 条;失败 {failed} 条、只报告 {skipped} 条。';
5805
+ readonly 'sessions.layout.refreshHint': '执行后会重新扫描列表;失败项已逐条尝试回滚(回滚失败的项会单独标红,绝不显示为已复原),可重试或改用离线 CLI。';
5806
+ readonly 'sessions.layout.close': '关闭';
5807
+ readonly 'sessions.layout.kind.ok': '位置已正确';
5808
+ readonly 'sessions.layout.kind.move': '搬目录归位';
5809
+ readonly 'sessions.layout.kind.rewriteMove': '改写首帧后归位(离线 CLI 路径)';
5810
+ readonly 'sessions.layout.kind.skip': '只报告';
5811
+ readonly 'sessions.layout.kind.keep': '保留(不动)';
5812
+ readonly 'sessions.layout.kind.quarantine': '隔离副本';
5813
+ readonly 'sessions.layout.kind.unknown': '未知动作';
5814
+ readonly 'sessions.layout.status.moved': '已归位';
5815
+ readonly 'sessions.layout.status.quarantined': '已隔离';
5816
+ readonly 'sessions.layout.status.kept': '已保留';
5817
+ readonly 'sessions.layout.status.skipped': '只报告(未执行)';
5818
+ readonly 'sessions.layout.status.failed': '失败(未改动)';
5819
+ readonly 'sessions.layout.status.rolledBack': '失败,已回滚到原状态';
5820
+ readonly 'sessions.layout.status.rollbackFailed': '失败,且回滚未成功(需人工处理)';
5821
+ readonly 'sessions.layout.reason.noCwd': '首帧没有 cwd,无法判定目标目录';
5822
+ readonly 'sessions.layout.reason.inconsistentGenerations': '同一会话多份 generation 的 cwd 不一致(不猜哪份为准)';
5823
+ readonly 'sessions.layout.reason.locked': '会话目录里有 session.lock(可能正被使用)';
5824
+ readonly 'sessions.layout.reason.alreadyPlaced': '位置已经正确';
5825
+ readonly 'sessions.layout.reason.needsMove': '需要搬目录';
5826
+ readonly 'sessions.layout.reason.needsRewriteMove': '需要先改写首帧 cwd 再搬(离线 CLI 路径)';
5827
+ readonly 'sessions.layout.reason.duplicateId': '同一会话 id 出现在多个目录';
5828
+ readonly 'sessions.layout.reason.busy': '日志最近 30 秒内被写过(可能在活跃使用中)';
5829
+ readonly 'sessions.layout.reason.missingKeep': '没有选定保留哪一份,已拒绝执行(其余副本一律不动)';
5830
+ readonly 'sessions.layout.reason.keepNotACandidate': '选定的那一份不在扫描到的副本里,已拒绝执行';
5831
+ readonly 'sessions.layout.reason.targetExists': '目标位置已经有这个会话,未搬动';
5832
+ readonly 'sessions.layout.reason.quarantineExists': '隔离目录里已有同名副本,未搬动';
5833
+ readonly 'sessions.layout.reason.rewriteFailed': '改写首帧 cwd 失败,因此没有搬目录';
5834
+ readonly 'sessions.layout.reason.missingTargetKey': '计划里缺少目标 projectKey,未搬动';
5835
+ readonly 'sessions.layout.reason.moveFailed': '搬目录失败';
5836
+ readonly 'sessions.layout.reason.reindexFailed': '会话索引刷新失败(已回滚该条)';
5837
+ readonly 'sessions.layout.reason.notFound': '会话目录或日志已不在了';
5838
+ readonly 'sessions.layout.reason.ioError': '读写失败';
5839
+ readonly 'sessions.layout.reason.reindexUnavailable': '当前宿主没有提供索引刷新能力,因此一条也没有执行(未做任何改动)';
5840
+ readonly 'sessions.layout.reason.sessionsRootUnreadable': '会话根读不出来,无法规划(未做任何改动)';
5841
+ readonly 'sessions.layout.reason.unknown': '未知原因(未做任何改动)';
4866
5842
  };
4867
5843
  /** 字典键联合(注册处 compile-time 校验)。 */
4868
5844
  type RecoveryKey = keyof typeof zh;
@@ -4888,6 +5864,8 @@ interface ExportViewProps {
4888
5864
  interface ImportWizardViewProps {
4889
5865
  api: ConfigManagerApi;
4890
5866
  t: TranslateNS<'config-manager'>;
5867
+ uiT?: UiT;
5868
+ onOpenForeignImport?: () => void;
4891
5869
  }
4892
5870
  //#endregion
4893
5871
  //#region src/client/sync/SyncPanel.d.ts
@@ -4921,6 +5899,11 @@ interface MarketPanelProps {
4921
5899
  * 缺省(页面路径、从「逛市场」按钮进入)= 只打开列表,行为不变。
4922
5900
  */
4923
5901
  openItemId?: string;
5902
+ /**
5903
+ * 直达的「市场子视图」(v3):⌘K「发布到市场」与产物库「发布到市场」把 payload 带进来,
5904
+ * 面板挂载时直接落在「我的配置」。缺省 = 按上次持久化的子视图(行为不变)。
5905
+ */
5906
+ initialSubView?: 'browse' | 'myconfigs';
4924
5907
  }
4925
5908
  //#endregion
4926
5909
  //#region src/client/about/AboutPanel.d.ts