dsh-config-manager 0.1.71 → 0.1.72

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 (548) hide show
  1. package/README.md +111 -96
  2. package/README.zh-CN.md +207 -86
  3. package/lib/adapters/agent-instructions.js +1 -1
  4. package/lib/adapters/file-collection.js +1 -1
  5. package/lib/adapters/index.d.ts +1 -1
  6. package/lib/adapters/index.js +1 -1
  7. package/lib/adapters/link-report.d.ts +1 -0
  8. package/lib/adapters/link-report.js +27 -3
  9. package/lib/adapters/messages.d.ts +18 -0
  10. package/lib/adapters/messages.js +50 -0
  11. package/lib/adapters/plugin-files.js +3 -2
  12. package/lib/adapters/plugins.js +4 -3
  13. package/lib/adapters/prompts.d.ts +1 -0
  14. package/lib/adapters/prompts.js +7 -1
  15. package/lib/adapters/self.d.ts +7 -1
  16. package/lib/adapters/self.js +1 -1
  17. package/lib/adapters/sessions.d.ts +1 -0
  18. package/lib/adapters/sessions.js +4 -2
  19. package/lib/adapters/ui.d.ts +2 -2
  20. package/lib/adapters/ui.js +25 -25
  21. package/lib/adapters/workspaces.d.ts +1 -0
  22. package/lib/adapters/workspaces.js +7 -3
  23. package/lib/cli/actions.d.ts +9 -1
  24. package/lib/cli/actions.js +5 -2
  25. package/lib/cli/help.js +23 -10
  26. package/lib/cli/index.d.ts +23 -0
  27. package/lib/cli/index.js +90 -32
  28. package/lib/cli/sessions-inspect.js +3 -1
  29. package/lib/cli/sessions-repair.js +25 -6
  30. package/lib/cli/web/page.d.ts +12 -0
  31. package/lib/cli/web/page.js +21 -12
  32. package/lib/cli/web/routes.js +2 -2
  33. package/lib/cli/web/server.js +4 -4
  34. package/lib/client.d.ts +1349 -490
  35. package/lib/client.js +43047 -36738
  36. package/lib/core/backup-plan.js +30 -17
  37. package/lib/core/backup-verify.js +24 -23
  38. package/lib/core/backup.d.ts +5 -0
  39. package/lib/core/backup.js +51 -25
  40. package/lib/core/boot-rescue.js +4 -3
  41. package/lib/core/boot-safety.js +2 -1
  42. package/lib/core/command-rollback.d.ts +178 -0
  43. package/lib/core/command-rollback.js +289 -0
  44. package/lib/core/consult-source.js +7 -6
  45. package/lib/core/disk-usage.d.ts +74 -10
  46. package/lib/core/disk-usage.js +67 -4
  47. package/lib/core/engine-locale.d.ts +87 -0
  48. package/lib/core/engine-locale.js +125 -0
  49. package/lib/core/exporter.js +3 -3
  50. package/lib/core/fork-reconcile.d.ts +128 -0
  51. package/lib/core/fork-reconcile.js +150 -0
  52. package/lib/core/journal.js +6 -5
  53. package/lib/core/local-plugin-host.js +3 -2
  54. package/lib/core/local-plugin-pack.js +11 -6
  55. package/lib/core/messages-core.d.ts +292 -0
  56. package/lib/core/messages-core.js +615 -0
  57. package/lib/core/messages.d.ts +60 -2
  58. package/lib/core/messages.js +116 -13
  59. package/lib/core/migration-consult.js +21 -20
  60. package/lib/core/migration-history.js +19 -5
  61. package/lib/core/model-tools.d.ts +0 -22
  62. package/lib/core/model-tools.js +50 -27
  63. package/lib/core/phase3-host.js +30 -5
  64. package/lib/core/plugin-cli.js +18 -19
  65. package/lib/core/reconcile.d.ts +2 -14
  66. package/lib/core/reconcile.js +87 -17
  67. package/lib/core/recovery-orchestrator.js +19 -18
  68. package/lib/core/reinstall.d.ts +4 -0
  69. package/lib/core/reinstall.js +26 -21
  70. package/lib/core/restore.js +20 -17
  71. package/lib/core/rollback-ignore-rules.d.ts +31 -0
  72. package/lib/core/rollback-ignore-rules.js +140 -0
  73. package/lib/core/rollback-point.d.ts +1208 -0
  74. package/lib/core/rollback-point.js +2993 -0
  75. package/lib/core/run-registry.js +6 -5
  76. package/lib/core/session-health.d.ts +15 -0
  77. package/lib/core/session-meta.d.ts +42 -2
  78. package/lib/core/session-meta.js +140 -1
  79. package/lib/core/session-title.d.ts +28 -0
  80. package/lib/core/session-title.js +185 -0
  81. package/lib/core/startup-barrier.d.ts +24 -0
  82. package/lib/core/startup-barrier.js +22 -0
  83. package/lib/core/transaction-coordinator.js +4 -3
  84. package/lib/core/types.d.ts +18 -1
  85. package/lib/core/validator.js +5 -4
  86. package/lib/core/verify-recovery.js +31 -30
  87. package/lib/foreign/bundle.js +3 -2
  88. package/lib/foreign/continue.js +2 -1
  89. package/lib/foreign/crush.js +2 -1
  90. package/lib/foreign/gemini.js +2 -1
  91. package/lib/foreign/goose.js +2 -1
  92. package/lib/foreign/kilocode.js +2 -1
  93. package/lib/foreign/kimi.js +2 -1
  94. package/lib/foreign/messages.d.ts +15 -0
  95. package/lib/foreign/messages.js +40 -0
  96. package/lib/foreign/mimocode.js +2 -1
  97. package/lib/foreign/openclaw.js +2 -1
  98. package/lib/foreign/opencode.js +2 -1
  99. package/lib/foreign/pi.js +2 -1
  100. package/lib/foreign/qoder.js +2 -1
  101. package/lib/foreign/qwen.js +2 -1
  102. package/lib/foreign/registry.js +7 -6
  103. package/lib/foreign/teleagent.js +2 -1
  104. package/lib/foreign/workbuddy.js +2 -1
  105. package/lib/foreign/zcode.js +2 -1
  106. package/lib/foreign/zed.js +2 -1
  107. package/lib/index.d.ts +223 -7
  108. package/lib/index.js +729 -54
  109. package/lib/market/git-file-writer.js +20 -19
  110. package/lib/market/github-repos.js +35 -19
  111. package/lib/market/index-parser.js +31 -30
  112. package/lib/market/messages-market.d.ts +138 -0
  113. package/lib/market/messages-market.js +305 -0
  114. package/lib/market/my-repo.d.ts +2 -2
  115. package/lib/market/my-repo.js +32 -29
  116. package/lib/market/prepare.js +18 -15
  117. package/lib/market/security.js +20 -19
  118. package/lib/market/types.js +2 -1
  119. package/lib/market/url.js +2 -1
  120. package/lib/migrations/index.js +6 -5
  121. package/lib/migrations/messages-migrations.d.ts +32 -0
  122. package/lib/migrations/messages-migrations.js +58 -0
  123. package/lib/profiles/dsh-profile-launcher.js +2 -1
  124. package/lib/profiles/dsh-profile-runtime.js +2 -1
  125. package/lib/profiles/messages.d.ts +7 -0
  126. package/lib/profiles/messages.js +27 -0
  127. package/lib/routes/backup.js +18 -2
  128. package/lib/routes/import.js +3 -3
  129. package/lib/routes/index.d.ts +1 -1
  130. package/lib/routes/kit.d.ts +3 -2
  131. package/lib/routes/kit.js +6 -1
  132. package/lib/routes/market.js +1 -1
  133. package/lib/routes/messages.d.ts +42 -0
  134. package/lib/routes/messages.js +100 -0
  135. package/lib/routes/profiles.js +12 -6
  136. package/lib/routes/recovery.js +378 -114
  137. package/lib/routes/snapshots.js +51 -4
  138. package/lib/routes/sync.js +68 -16
  139. package/lib/schema/config.d.ts +11 -1
  140. package/lib/schema/config.js +52 -20
  141. package/lib/schema/index.d.ts +8 -6
  142. package/lib/schema/index.js +8 -6
  143. package/lib/schema/manifest.js +19 -18
  144. package/lib/schema/messages.d.ts +47 -0
  145. package/lib/schema/messages.js +110 -0
  146. package/lib/schema/section-registry.d.ts +41 -14
  147. package/lib/schema/section-registry.js +35 -29
  148. package/lib/schema/versions.js +6 -5
  149. package/lib/security/encryption.js +16 -15
  150. package/lib/security/integrity.js +8 -7
  151. package/lib/security/messages.d.ts +30 -0
  152. package/lib/security/messages.js +77 -0
  153. package/lib/security/redaction.js +12 -0
  154. package/lib/security/secret-scanner.js +16 -13
  155. package/lib/security/vault.js +2 -1
  156. package/lib/security/zip-security.js +4 -3
  157. package/lib/sync/ancestor.js +2 -1
  158. package/lib/sync/autosync-config.d.ts +11 -0
  159. package/lib/sync/autosync-config.js +12 -0
  160. package/lib/sync/autosync-scheduler.d.ts +11 -1
  161. package/lib/sync/autosync-scheduler.js +115 -76
  162. package/lib/sync/backup-files.js +3 -2
  163. package/lib/sync/backup-scheduler.js +6 -5
  164. package/lib/sync/blob-store.js +2 -1
  165. package/lib/sync/git/git-transport.d.ts +55 -0
  166. package/lib/sync/git/git-transport.js +152 -2
  167. package/lib/sync/github-auth.js +10 -9
  168. package/lib/sync/layout.js +13 -12
  169. package/lib/sync/messages.d.ts +63 -0
  170. package/lib/sync/messages.js +149 -0
  171. package/lib/sync/review-queue.js +6 -5
  172. package/lib/sync/s3/messages.d.ts +7 -0
  173. package/lib/sync/s3/messages.js +16 -0
  174. package/lib/sync/s3/s3-providers.d.ts +4 -1
  175. package/lib/sync/s3/s3-providers.js +5 -5
  176. package/lib/sync/s3/s3-transport.js +1 -1
  177. package/lib/sync/s3/sigv4.js +2 -1
  178. package/lib/sync/snapshot-crypto.js +6 -5
  179. package/lib/sync/snapshot-json.js +3 -2
  180. package/lib/sync/sync-engine.d.ts +37 -15
  181. package/lib/sync/sync-engine.js +67 -37
  182. package/lib/sync/sync-history.js +7 -6
  183. package/lib/sync/sync-selection.d.ts +15 -4
  184. package/lib/sync/sync-selection.js +17 -5
  185. package/lib/sync/webdav/webdav-transport.d.ts +1 -0
  186. package/lib/sync/webdav/webdav-transport.js +4 -1
  187. package/lib/ui/artifact-view.js +4 -3
  188. package/lib/ui/commands.d.ts +1 -1
  189. package/lib/ui/commands.js +10 -0
  190. package/lib/ui/disk-usage-view.d.ts +33 -4
  191. package/lib/ui/disk-usage-view.js +29 -1
  192. package/lib/ui/errors.d.ts +1 -1
  193. package/lib/ui/errors.js +4 -3
  194. package/lib/ui/export-flow.js +24 -20
  195. package/lib/ui/foreign-view.d.ts +5 -1
  196. package/lib/ui/foreign-view.js +26 -2
  197. package/lib/ui/i18n.d.ts +65 -0
  198. package/lib/ui/i18n.js +114 -0
  199. package/lib/ui/import-wizard.d.ts +7 -0
  200. package/lib/ui/import-wizard.js +13 -10
  201. package/lib/ui/progress.d.ts +2 -2
  202. package/lib/ui/progress.js +1 -2
  203. package/lib/ui/report.d.ts +5 -5
  204. package/lib/ui/report.js +6 -6
  205. package/lib/ui/rollback-view.d.ts +756 -0
  206. package/lib/ui/rollback-view.js +724 -0
  207. package/lib/ui/selection-model.d.ts +41 -0
  208. package/lib/ui/selection-model.js +30 -0
  209. package/lib/ui/session-inventory-view.d.ts +97 -3
  210. package/lib/ui/session-inventory-view.js +76 -2
  211. package/lib/ui/session-issue-labels.d.ts +43 -0
  212. package/lib/ui/session-issue-labels.js +48 -0
  213. package/lib/ui/sync-settings-view.d.ts +33 -0
  214. package/lib/ui/sync-settings-view.js +40 -0
  215. package/lib/ui/types.d.ts +8 -3
  216. package/lib/ui/types.js +1 -1
  217. package/lib/utils/atomic-write.js +6 -5
  218. package/lib/utils/bundle-scan.d.ts +11 -1
  219. package/lib/utils/bundle-scan.js +12 -1
  220. package/lib/utils/env-lock.d.ts +10 -0
  221. package/lib/utils/env-lock.js +73 -46
  222. package/lib/utils/json.js +6 -5
  223. package/lib/utils/messages-utils.d.ts +96 -0
  224. package/lib/utils/messages-utils.js +216 -0
  225. package/lib/utils/proxy.js +18 -5
  226. package/lib/utils/recursive-walk.d.ts +22 -0
  227. package/lib/utils/recursive-walk.js +75 -1
  228. package/lib/utils/session-log-repair.js +10 -9
  229. package/lib/utils/zip.js +27 -26
  230. package/package.json +12 -2
  231. package/src/adapters/agent-instructions.ts +1 -1
  232. package/src/adapters/file-collection.test.ts +1 -0
  233. package/src/adapters/file-collection.ts +1 -1
  234. package/src/adapters/files.test.ts +27 -0
  235. package/src/adapters/index.ts +1 -1
  236. package/src/adapters/link-report.test.ts +22 -2
  237. package/src/adapters/link-report.ts +29 -4
  238. package/src/adapters/messages.ts +54 -0
  239. package/src/adapters/plugin-files.ts +3 -2
  240. package/src/adapters/plugins.ts +4 -3
  241. package/src/adapters/prompts.ts +7 -1
  242. package/src/adapters/self.test.ts +26 -0
  243. package/src/adapters/self.ts +8 -2
  244. package/src/adapters/sessions.ts +4 -2
  245. package/src/adapters/settings.test.ts +38 -1
  246. package/src/adapters/ui.test.ts +2 -2
  247. package/src/adapters/ui.ts +27 -26
  248. package/src/adapters/workspaces.ts +7 -3
  249. package/src/cli/actions.test.ts +28 -0
  250. package/src/cli/actions.ts +11 -2
  251. package/src/cli/help.ts +23 -10
  252. package/src/cli/index-guards.test.ts +193 -0
  253. package/src/cli/index.ts +106 -31
  254. package/src/cli/sessions-inspect.test.ts +15 -1
  255. package/src/cli/sessions-inspect.ts +3 -1
  256. package/src/cli/sessions-repair.test.ts +84 -0
  257. package/src/cli/sessions-repair.ts +33 -7
  258. package/src/cli/web/console-route-parity.test.ts +115 -0
  259. package/src/cli/web/page.ts +23 -12
  260. package/src/cli/web/routes.ts +2 -1
  261. package/src/cli/web/server.ts +4 -4
  262. package/src/cli/web/web.test.ts +2 -2
  263. package/src/client/ConfigManagerSection.tsx +30 -2
  264. package/src/client/about/AboutPanel.tsx +2 -2
  265. package/src/client/about/PluginUpdateDialog.tsx +1 -1
  266. package/src/client/about/ReleaseNotesDialog.tsx +2 -2
  267. package/src/client/about/about-view.test.ts +13 -3
  268. package/src/client/about/about-view.ts +10 -6
  269. package/src/client/about/release-notes-view.test.ts +14 -4
  270. package/src/client/about/release-notes-view.ts +4 -2
  271. package/src/client/api.ts +18 -6
  272. package/src/client/chat/ChatEntryView.tsx +391 -0
  273. package/src/client/chat/RollbackDiffTab.tsx +61 -0
  274. package/src/client/chat/RollbackFileIcon.tsx +96 -0
  275. package/src/client/chat/RollbackReviewDialog.tsx +591 -0
  276. package/src/client/chat/chat-entry-view.test.ts +1174 -0
  277. package/src/client/chat/chat-entry-view.ts +758 -0
  278. package/src/client/chat/chat-locales.ts +152 -0
  279. package/src/client/chat/chat-node-registration.ts +64 -0
  280. package/src/client/chat/chat-point-window.ts +173 -0
  281. package/src/client/chat/chat-slots.ts +107 -0
  282. package/src/client/chat/rollback-diff-tab.test.ts +105 -0
  283. package/src/client/chat/rollback-diff-tab.ts +164 -0
  284. package/src/client/chat/rollback-entry-view.test.ts +1469 -0
  285. package/src/client/chat/rollback-entry-view.ts +941 -0
  286. package/src/client/chat/sidebar-slots.ts +37 -0
  287. package/src/client/common/ConfirmDialog.tsx +7 -3
  288. package/src/client/common/ContentPicker.tsx +48 -10
  289. package/src/client/common/DiffTable.tsx +97 -0
  290. package/src/client/common/ErrorBanner.tsx +4 -4
  291. package/src/client/common/Icon.tsx +2 -0
  292. package/src/client/common/Modal.tsx +8 -1
  293. package/src/client/common/ProgressBar.tsx +8 -2
  294. package/src/client/common/ReportView.tsx +4 -4
  295. package/src/client/common/RunsCenter.tsx +1 -0
  296. package/src/client/common/client-route-parity.test.ts +78 -0
  297. package/src/client/common/info-hint-guard.test.ts +46 -13
  298. package/src/client/common/picker-lazy-units.test.ts +42 -0
  299. package/src/client/common/plan-text-redaction.test.ts +17 -6
  300. package/src/client/common/progress-view-edge.test.ts +8 -7
  301. package/src/client/common/progress-view.test.ts +9 -9
  302. package/src/client/common/progress-view.ts +2 -2
  303. package/src/client/common/routes.ts +28 -0
  304. package/src/client/common/ui.tsx +73 -10
  305. package/src/client/config-manager.module.css +996 -21
  306. package/src/client/css-scale-guard.test.ts +30 -0
  307. package/src/client/environment/EnvironmentPanel.tsx +11 -4
  308. package/src/client/environment/maintenance/DiskUsageCard.tsx +23 -2
  309. package/src/client/export/ExportView.tsx +13 -8
  310. package/src/client/history/HistoryPanel.tsx +4 -3
  311. package/src/client/history/history-api.ts +2 -2
  312. package/src/client/history/history-locales.ts +5 -1
  313. package/src/client/home/HomePanel.tsx +29 -8
  314. package/src/client/import/ForeignImportView.tsx +4 -5
  315. package/src/client/import/ImportWizardView.tsx +5 -3
  316. package/src/client/import/import-wizard-split.test.ts +3 -1
  317. package/src/client/import/import-wizard-steps.tsx +9 -9
  318. package/src/client/index.ts +186 -3
  319. package/src/client/library/LibraryActions.tsx +32 -7
  320. package/src/client/library/LibraryPanel.tsx +23 -3
  321. package/src/client/library/RestorePlanView.tsx +9 -66
  322. package/src/client/locales.ts +54 -5
  323. package/src/client/lucide-icons.d.ts +1 -0
  324. package/src/client/market/MarketPanel.tsx +13 -2
  325. package/src/client/market/MyConfigsView.tsx +5 -4
  326. package/src/client/market/MyConfigsWizard.tsx +10 -8
  327. package/src/client/market/market-api.test.ts +9 -8
  328. package/src/client/market/market-api.ts +2 -2
  329. package/src/client/market/market-locales.ts +3 -0
  330. package/src/client/market/market-view.test.ts +6 -6
  331. package/src/client/market/market-view.ts +3 -3
  332. package/src/client/market/my-configs-api.ts +2 -2
  333. package/src/client/market/my-configs-view.test.ts +23 -22
  334. package/src/client/market/my-configs-view.ts +8 -8
  335. package/src/client/recovery/IncompleteCopiesSection.tsx +2 -1
  336. package/src/client/recovery/RecoveryPanel.tsx +442 -283
  337. package/src/client/recovery/RollbackCard.tsx +665 -0
  338. package/src/client/recovery/RollbackDiffPane.tsx +58 -0
  339. package/src/client/recovery/RollbackFileChanges.tsx +163 -0
  340. package/src/client/recovery/incident-api.ts +2 -2
  341. package/src/client/recovery/recovery-api.ts +116 -6
  342. package/src/client/recovery/recovery-locales.test.ts +299 -0
  343. package/src/client/recovery/recovery-locales.ts +488 -149
  344. package/src/client/recovery/recovery-panel-layout.test.ts +132 -2
  345. package/src/client/recovery/rollback-file-changes.test.ts +73 -0
  346. package/src/client/recovery/session-dialog-mount.test.ts +54 -0
  347. package/src/client/run-store.ts +84 -21
  348. package/src/client/sync/AutosyncCard.tsx +25 -1
  349. package/src/client/sync/ChannelClearConfirmDialog.tsx +6 -3
  350. package/src/client/sync/ChannelConfigDialog.tsx +10 -10
  351. package/src/client/sync/DecryptPasswordCard.tsx +2 -2
  352. package/src/client/sync/SecurityOptionsCard.tsx +27 -17
  353. package/src/client/sync/SyncChannelEntryCard.tsx +14 -2
  354. package/src/client/sync/SyncConfirmView.tsx +46 -8
  355. package/src/client/sync/SyncLogList.tsx +1 -1
  356. package/src/client/sync/SyncPanel.tsx +31 -23
  357. package/src/client/sync/SyncRepositoryPicker.tsx +3 -5
  358. package/src/client/sync/SyncSectionPickerDialog.tsx +11 -2
  359. package/src/client/sync/SyncSettingsView.test.ts +20 -1
  360. package/src/client/sync/UnreadableSnapshotsBanner.tsx +1 -1
  361. package/src/client/sync/WorkDirCard.tsx +112 -0
  362. package/src/client/sync/history-model.test.ts +42 -9
  363. package/src/client/sync/history-model.ts +30 -15
  364. package/src/client/sync/sync-api.test.ts +57 -33
  365. package/src/client/sync/sync-api.ts +80 -6
  366. package/src/client/sync/sync-locales.ts +104 -3
  367. package/src/client/sync/sync-view-v2.test.ts +65 -13
  368. package/src/client/sync/sync-view.test.ts +107 -52
  369. package/src/client/sync/sync-view.ts +124 -41
  370. package/src/core/backup-plan.test.ts +28 -0
  371. package/src/core/backup-plan.ts +29 -17
  372. package/src/core/backup-verify.ts +24 -23
  373. package/src/core/backup.test.ts +76 -0
  374. package/src/core/backup.ts +55 -25
  375. package/src/core/boot-rescue.ts +4 -3
  376. package/src/core/boot-safety.ts +2 -1
  377. package/src/core/command-rollback.test.ts +536 -0
  378. package/src/core/command-rollback.ts +402 -0
  379. package/src/core/consult-source.ts +7 -6
  380. package/src/core/disk-usage.test.ts +257 -1
  381. package/src/core/disk-usage.ts +134 -14
  382. package/src/core/engine-locale.test.ts +593 -0
  383. package/src/core/engine-locale.ts +175 -0
  384. package/src/core/exporter.ts +3 -3
  385. package/src/core/fork-reconcile.test.ts +279 -0
  386. package/src/core/fork-reconcile.ts +234 -0
  387. package/src/core/journal.ts +6 -5
  388. package/src/core/local-plugin-host.ts +3 -2
  389. package/src/core/local-plugin-pack.ts +11 -6
  390. package/src/core/messages-core.ts +657 -0
  391. package/src/core/messages.ts +123 -17
  392. package/src/core/migration-consult.ts +21 -20
  393. package/src/core/migration-history.ts +19 -5
  394. package/src/core/model-tools.ts +28 -27
  395. package/src/core/phase3-host.ts +21 -5
  396. package/src/core/phase3-p2b-fingerprint.test.ts +22 -0
  397. package/src/core/plugin-cli.ts +18 -19
  398. package/src/core/reconcile.test.ts +117 -0
  399. package/src/core/reconcile.ts +85 -17
  400. package/src/core/recovery-orchestrator.ts +19 -18
  401. package/src/core/reinstall.ts +26 -21
  402. package/src/core/restore.ts +20 -17
  403. package/src/core/rollback-file-diff.test.ts +159 -0
  404. package/src/core/rollback-ignore-rules.ts +126 -0
  405. package/src/core/rollback-point.test.ts +2603 -0
  406. package/src/core/rollback-point.ts +3755 -0
  407. package/src/core/run-registry.ts +6 -5
  408. package/src/core/session-health.ts +15 -0
  409. package/src/core/session-meta.test.ts +117 -1
  410. package/src/core/session-meta.ts +149 -2
  411. package/src/core/session-title.test.ts +127 -0
  412. package/src/core/session-title.ts +189 -0
  413. package/src/core/startup-barrier.test.ts +69 -0
  414. package/src/core/startup-barrier.ts +27 -0
  415. package/src/core/transaction-coordinator.ts +4 -3
  416. package/src/core/types.ts +18 -1
  417. package/src/core/validator.ts +5 -4
  418. package/src/core/verify-recovery.ts +31 -30
  419. package/src/foreign/bundle.ts +3 -2
  420. package/src/foreign/continue.ts +2 -1
  421. package/src/foreign/crush.ts +2 -1
  422. package/src/foreign/file-budget.test.ts +2 -0
  423. package/src/foreign/gemini.ts +2 -1
  424. package/src/foreign/goose.ts +2 -1
  425. package/src/foreign/kilocode.ts +2 -1
  426. package/src/foreign/kimi.ts +2 -1
  427. package/src/foreign/messages.ts +44 -0
  428. package/src/foreign/mimocode.ts +2 -1
  429. package/src/foreign/openclaw.ts +2 -1
  430. package/src/foreign/opencode.ts +2 -1
  431. package/src/foreign/pi.ts +2 -1
  432. package/src/foreign/qoder.ts +2 -1
  433. package/src/foreign/qwen.ts +2 -1
  434. package/src/foreign/registry.ts +7 -6
  435. package/src/foreign/teleagent.ts +2 -1
  436. package/src/foreign/workbuddy.ts +2 -1
  437. package/src/foreign/zcode.ts +2 -1
  438. package/src/foreign/zed.ts +2 -1
  439. package/src/index.facade.test.ts +340 -1
  440. package/src/index.ts +813 -57
  441. package/src/market/git-file-writer.ts +20 -19
  442. package/src/market/github-repos.test.ts +23 -0
  443. package/src/market/github-repos.ts +37 -19
  444. package/src/market/index-parser.ts +31 -30
  445. package/src/market/messages-market.ts +325 -0
  446. package/src/market/my-repo.ts +32 -29
  447. package/src/market/prepare.ts +18 -15
  448. package/src/market/security.ts +20 -19
  449. package/src/market/types.ts +2 -1
  450. package/src/market/url.ts +2 -1
  451. package/src/migrations/index.ts +6 -5
  452. package/src/migrations/messages-migrations.ts +59 -0
  453. package/src/profiles/dsh-profile-launcher.ts +2 -1
  454. package/src/profiles/dsh-profile-runtime.ts +2 -1
  455. package/src/profiles/messages.ts +31 -0
  456. package/src/routes/backup.ts +18 -2
  457. package/src/routes/import.ts +3 -3
  458. package/src/routes/index.ts +1 -1
  459. package/src/routes/kit.ts +9 -3
  460. package/src/routes/market.ts +1 -1
  461. package/src/routes/messages.ts +104 -0
  462. package/src/routes/profiles.ts +12 -6
  463. package/src/routes/recovery.test.ts +405 -1
  464. package/src/routes/recovery.ts +377 -109
  465. package/src/routes/snapshots.ts +51 -4
  466. package/src/routes/sync.ts +67 -16
  467. package/src/schema/config.ts +53 -20
  468. package/src/schema/index.ts +7 -5
  469. package/src/schema/manifest.ts +19 -18
  470. package/src/schema/messages.ts +120 -0
  471. package/src/schema/registry.test.ts +19 -5
  472. package/src/schema/section-registry.ts +64 -39
  473. package/src/schema/versions.ts +6 -5
  474. package/src/security/encryption.ts +16 -15
  475. package/src/security/integrity.ts +8 -7
  476. package/src/security/messages.ts +87 -0
  477. package/src/security/redaction.test.ts +17 -1
  478. package/src/security/redaction.ts +13 -0
  479. package/src/security/secret-scanner.ts +19 -12
  480. package/src/security/security.test.ts +47 -0
  481. package/src/security/vault.ts +2 -1
  482. package/src/security/zip-security.ts +4 -3
  483. package/src/sync/ancestor.ts +2 -1
  484. package/src/sync/autosync-config.ts +21 -0
  485. package/src/sync/autosync-scheduler.test.ts +63 -7
  486. package/src/sync/autosync-scheduler.ts +118 -78
  487. package/src/sync/backup-files.ts +3 -2
  488. package/src/sync/backup-scheduler.ts +6 -5
  489. package/src/sync/blob-store.ts +2 -1
  490. package/src/sync/git/git-transport.test.ts +170 -8
  491. package/src/sync/git/git-transport.ts +176 -2
  492. package/src/sync/github-auth.ts +10 -9
  493. package/src/sync/layout.ts +13 -12
  494. package/src/sync/messages.ts +153 -0
  495. package/src/sync/review-queue.ts +6 -5
  496. package/src/sync/s3/messages.ts +16 -0
  497. package/src/sync/s3/s3-providers.ts +9 -6
  498. package/src/sync/s3/s3-transport.ts +1 -1
  499. package/src/sync/s3/sigv4.ts +3 -1
  500. package/src/sync/snapshot-crypto.ts +6 -5
  501. package/src/sync/snapshot-json.ts +3 -2
  502. package/src/sync/sync-engine-download-tombstone.test.ts +1 -1
  503. package/src/sync/sync-engine.test.ts +226 -8
  504. package/src/sync/sync-engine.ts +103 -41
  505. package/src/sync/sync-history.ts +7 -6
  506. package/src/sync/sync-selection.test.ts +12 -2
  507. package/src/sync/sync-selection.ts +18 -5
  508. package/src/sync/webdav/webdav-transport.ts +4 -1
  509. package/src/ui/artifact-view.ts +4 -3
  510. package/src/ui/commands.test.ts +1 -0
  511. package/src/ui/commands.ts +11 -1
  512. package/src/ui/disk-usage-view.test.ts +113 -6
  513. package/src/ui/disk-usage-view.ts +63 -7
  514. package/src/ui/errors.ts +4 -3
  515. package/src/ui/export-flow.ts +24 -20
  516. package/src/ui/foreign-view.test.ts +43 -0
  517. package/src/ui/foreign-view.ts +30 -3
  518. package/src/ui/i18n.ts +125 -0
  519. package/src/ui/import-wizard.ts +18 -10
  520. package/src/ui/progress.ts +2 -2
  521. package/src/ui/report.ts +7 -6
  522. package/src/ui/rollback-view.test.ts +819 -0
  523. package/src/ui/rollback-view.ts +1339 -0
  524. package/src/ui/selection-model.test.ts +33 -1
  525. package/src/ui/selection-model.ts +53 -0
  526. package/src/ui/session-inventory-view.test.ts +109 -0
  527. package/src/ui/session-inventory-view.ts +138 -3
  528. package/src/ui/session-issue-labels.test.ts +51 -0
  529. package/src/ui/session-issue-labels.ts +70 -0
  530. package/src/ui/sync-settings-view.test.ts +36 -0
  531. package/src/ui/sync-settings-view.ts +49 -0
  532. package/src/ui/types.ts +10 -4
  533. package/src/utils/atomic-write.ts +6 -5
  534. package/src/utils/bundle-scan.test.ts +2 -2
  535. package/src/utils/bundle-scan.ts +12 -1
  536. package/src/utils/env-lock.ts +83 -49
  537. package/src/utils/json.ts +7 -5
  538. package/src/utils/messages-utils.ts +232 -0
  539. package/src/utils/proxy.test.ts +25 -0
  540. package/src/utils/proxy.ts +19 -5
  541. package/src/utils/recursive-walk.test.ts +43 -0
  542. package/src/utils/recursive-walk.ts +75 -1
  543. package/src/utils/session-log-repair.ts +10 -9
  544. package/src/utils/zip.ts +27 -26
  545. package/lib/core/checkpoint.d.ts +0 -362
  546. package/lib/core/checkpoint.js +0 -1309
  547. package/src/core/checkpoint.test.ts +0 -665
  548. package/src/core/checkpoint.ts +0 -1614
@@ -0,0 +1,178 @@
1
+ /**
2
+ * 宿主斜杠命令 /rollback(别名 /rw)—— 不打开设置面板也能回退(对齐 dsh-rewind 的 /rewind、/undo)。
3
+ *
4
+ * 语义(用户 2026-10-12 确认方案 A):
5
+ * /rollback → 当前**会话**的可回退点列表(回合号 / 时间 / 类型 / 状态 / 可回退性)
6
+ * /rollback <id> → 回退到该点,走**与 HTTP 路由同源**的那道写入门:
7
+ * runWithMutationLock(= SAFE MODE 门 + 跨进程/跨 kind 环境锁)
8
+ * → 引擎 preview(零写入)→ 引擎 rewind(userConfirmed=true)
9
+ * 引擎回的 confirmation-required / protected-point / record-incomplete 一律翻成可读错误结果,
10
+ * **绝不绕过**(命令入口没有「确认按钮」,用户敲下 id 就是那次确认;其余门照旧全量生效)。
11
+ *
12
+ * 纪律(与 src/core/model-tools.ts 的 registerModelTools 同口径):
13
+ * · 命令服务**惰取**:一律 ctx.get('commands') 调用期读取,绝不属性访问 ctx.commands、
14
+ * 绝不放进 inject —— 未组合该服务的部署必须照常启动(命令是可选能力,不是硬依赖);
15
+ * · 注册失败只 warn:命令挂不上不得影响其它装配(宿主启动 = blocker);
16
+ * · 用户可见文案一律走宿主字典 engineMsg(key: command.rollback.*),**取文案那一刻**解析语言;
17
+ * · 本模块不 import @deepseek-ai/dsh-commands 的运行时值(只做结构化窄化),core 保持与 DSH 解耦。
18
+ */
19
+ import type { MutationLockPort } from '../utils/env-lock.ts';
20
+ import type { RollbackPointSummary, RollbackRewindResult } from './rollback-point.ts';
21
+ /**
22
+ * 命令结果(与 @deepseek-ai/dsh-commands 的 `CommandResult` **逐字同形**)。
23
+ *
24
+ * 为什么在这里自己声明而不是 import 那门包的类型:`src/core/**` 的架构边界(tests/architecture-boundaries.test.ts
25
+ * 的 core allow 表)只允许 node 内置 / core 内部 / schema / utils / security / migrations / js-yaml ——
26
+ * `@deepseek-ai/*` 仅允许出现在 `src/index.ts` 与 `src/client/`。core 必须保持与 DSH 解耦,
27
+ * 所以这里做**结构化窄化**;两边一旦漂移,`command-rollback.test.ts` 的编译期断言会红。
28
+ */
29
+ export type CommandResult = {
30
+ readonly kind: 'success';
31
+ readonly text?: string;
32
+ readonly sourceEventSeq?: number;
33
+ } | {
34
+ readonly kind: 'error';
35
+ readonly text: string;
36
+ };
37
+ /** 命令名(无前导斜杠)与别名。 */
38
+ export declare const ROLLBACK_COMMAND_NAME = "rollback";
39
+ export declare const ROLLBACK_COMMAND_ALIAS = "rw";
40
+ /**
41
+ * 命令定义 id:/rw 别名是**第二条定义** —— 同一个 definitionId(客户端按 definitionId 做身份化行为,
42
+ * 别名与主名必须被视作同一条命令)。
43
+ */
44
+ export declare const ROLLBACK_COMMAND_DEFINITION_ID = "dsh-config-manager/rollback";
45
+ /** 命令服务惰取回调(调用期读 ctx.get('commands');未组合返回 undefined)。 */
46
+ export type CommandServiceReader = () => CommandServiceLike | undefined | null;
47
+ /** 一条已注册命令的最小形状(避免把 DSH 类型变成本插件的硬依赖)。 */
48
+ export interface CommandDefinitionLike {
49
+ readonly name: string;
50
+ readonly description: string;
51
+ readonly definitionId?: string;
52
+ readonly input?: {
53
+ readonly hint: string;
54
+ readonly attachments?: boolean;
55
+ };
56
+ readonly handler: (invocation: CommandInvocationLike) => CommandResult | Promise<CommandResult>;
57
+ }
58
+ /** 一次命令调用的最小形状(只读用到的字段)。 */
59
+ export interface CommandInvocationLike {
60
+ readonly agent: unknown;
61
+ /** 命令名之后的原文(含分隔空白)。 */
62
+ readonly rawInput: string;
63
+ /** 派发 UI 持有的取消信号(透传给回退执行)。 */
64
+ readonly signal?: AbortSignal;
65
+ }
66
+ /** 命令服务的最小形状(ctx.get('commands') 的结构化窄化)。 */
67
+ export interface CommandServiceLike {
68
+ register(definition: CommandDefinitionLike): unknown;
69
+ }
70
+ /** 宿主提供的回退能力(由 src/index.ts 装配;测试用假的实现即可)。 */
71
+ export interface RollbackCommandHost {
72
+ /** 当前 agent 所属会话(拿不准则 ok:false —— 绝不猜)。 */
73
+ agentSession(agent: unknown): AgentSessionFacts;
74
+ /** 列出该会话的回退点(含存储栈状态;只读)。 */
75
+ list(sessionId: string): Promise<RollbackCommandListResult>;
76
+ /**
77
+ * 执行回退:runWithMutationLock → SAFE MODE → 引擎 preview → 引擎 rewind。
78
+ *
79
+ * 被 SAFE MODE / 环境锁挡住时**抛 EnvironmentLockUnavailableError**(与 HTTP 路由同口径),
80
+ * 由本模块翻成可读错误结果。
81
+ */
82
+ rewind(input: RollbackRewindExecution): Promise<RollbackRewindResult>;
83
+ }
84
+ /**
85
+ * 回退执行入参。
86
+ *
87
+ * 只带 id + 取消信号:引擎 `rewind({ id, userConfirmed: true })` 的**写入面**已经由该点的记录
88
+ * 决定(不是调用方临时指定路径),多传会话/分块只会制造「两处口径」;会话事实只供只读列表过滤用。
89
+ */
90
+ export interface RollbackRewindExecution {
91
+ readonly id: string;
92
+ readonly signal?: AbortSignal;
93
+ }
94
+ /** 列表结果(引擎 RollbackListResult 的可测子集)。 */
95
+ export interface RollbackCommandListResult {
96
+ ok: boolean;
97
+ storage: {
98
+ available: boolean;
99
+ root: string;
100
+ detail?: string;
101
+ };
102
+ points: readonly RollbackPointSummary[];
103
+ error?: string;
104
+ }
105
+ /** 当前 agent 的会话事实(宽进严出:形状不符即 ok:false)。 */
106
+ export type AgentSessionFacts = {
107
+ ok: true;
108
+ sessionId: string;
109
+ chunks: readonly string[];
110
+ } | {
111
+ ok: false;
112
+ detail: string;
113
+ };
114
+ /** 绝对路径判定(win32 盘符 + POSIX 前缀 + UNC;纯函数,不引 node:path)。 */
115
+ export declare function isAbsolutePath(value: string): boolean;
116
+ /**
117
+ * 从 agent 窄化会话事实。
118
+ *
119
+ * **不猜**:agent.session.id 读不出来就退回 agent.id(DSH 的 Agent.id 就是会话 id);
120
+ * 两者都读不出 → ok:false(命令如实报「拿不到当前会话」,而不是列全网的点)。
121
+ * 工作区分块只认**绝对路径**的 cwd(与 rollbackSessionBindingOf 同一口径)。
122
+ */
123
+ export declare function agentSessionFactsOf(agent: unknown): AgentSessionFacts;
124
+ /** 解析结果:空输入 = 只读列表;单个 token = 目标点 id;其余 = invalid。 */
125
+ export type RollbackCommandInput = {
126
+ kind: 'list';
127
+ } | {
128
+ kind: 'rewind';
129
+ id: string;
130
+ } | {
131
+ kind: 'invalid';
132
+ detail: string;
133
+ };
134
+ /**
135
+ * 解析 rawInput(命令名之后的原文,含分隔空白)。
136
+ * 语法只有两种:空 = 列表;单个非空 token = 目标 id。多 token 一律 invalid。
137
+ */
138
+ export declare function parseRollbackCommand(rawInput: string): RollbackCommandInput;
139
+ /** 渲染只读列表(本会话没有点时给「本会话没有」,绝不冒充「全库为空」)。 */
140
+ export declare function renderRollbackList(result: RollbackCommandListResult, sessionId: string): CommandResult;
141
+ /** 把引擎结果翻成命令结果(失败一律带机器码 + 技术细节;processed 的段事实不隐藏)。 */
142
+ export declare function renderRewindResult(result: RollbackRewindResult, id: string): CommandResult;
143
+ /** 命令依赖(index.ts 装配;测试直接构造)。 */
144
+ export interface RollbackCommandDeps {
145
+ readonly host: RollbackCommandHost;
146
+ /** mutation lock 端口(index.ts 传 host.mutationLock;测试可传 undefined 或假端口)。 */
147
+ readonly mutationLock?: MutationLockPort;
148
+ /** SAFE MODE 同步谓词(与 HTTP 路由同一份 host.safeModeIsBlocked)。 */
149
+ readonly isBlocked?: () => boolean;
150
+ }
151
+ /**
152
+ * 构造命令处理器(**纯编排**:不注册、不读 ctx)。
153
+ *
154
+ * 带参数时:parser → agentSession(只用于「这次是不是列表」的会话判定)→ host.rewind。
155
+ * host.rewind 内部才是那道门:runWithMutationLock → SAFE MODE → 引擎 preview → 引擎 rewind
156
+ * EnvironmentLockUnavailableError(SAFE MODE / 环境锁被挡)在此翻成可读错误结果。
157
+ * 任何未预期异常也翻成错误结果 —— 命令处理器抛异常会让整条命令生命周期报泛化失败,
158
+ * UI 只看到一句「失败」;这里如实把原因说清楚。
159
+ */
160
+ export declare function makeRollbackCommandHandler(deps: RollbackCommandDeps): (invocation: CommandInvocationLike) => Promise<CommandResult>;
161
+ /** 注册所需的依赖面(命令服务惰取回调 + 宿主日志 + 命令依赖)。 */
162
+ export interface RollbackCommandRegistrationOptions {
163
+ /** 惰取命令服务:实现必须是「调用期」的 ctx.get('commands')(绝不属性访问、绝不进 inject)。 */
164
+ readonly readCommands: CommandServiceReader;
165
+ readonly deps: RollbackCommandDeps;
166
+ /** 只 warn:注册失败/服务缺失不得影响其它装配。 */
167
+ readonly log?: {
168
+ warn(message: string, meta?: unknown): void;
169
+ };
170
+ }
171
+ /**
172
+ * 注册 /rollback 与 /rw(两条定义 = 同一 definitionId)。
173
+ *
174
+ * 服务缺失 → warn 后**安静返回**(未组合 commands 的部署照常启动、不抛错);
175
+ * 服务存在但 register 抛错 → warn(其余装配不受影响)。
176
+ * @returns 反注册函数(重复调用安全)。
177
+ */
178
+ export declare function registerRollbackCommand(options: RollbackCommandRegistrationOptions): () => void;
@@ -0,0 +1,289 @@
1
+ /**
2
+ * 宿主斜杠命令 /rollback(别名 /rw)—— 不打开设置面板也能回退(对齐 dsh-rewind 的 /rewind、/undo)。
3
+ *
4
+ * 语义(用户 2026-10-12 确认方案 A):
5
+ * /rollback → 当前**会话**的可回退点列表(回合号 / 时间 / 类型 / 状态 / 可回退性)
6
+ * /rollback <id> → 回退到该点,走**与 HTTP 路由同源**的那道写入门:
7
+ * runWithMutationLock(= SAFE MODE 门 + 跨进程/跨 kind 环境锁)
8
+ * → 引擎 preview(零写入)→ 引擎 rewind(userConfirmed=true)
9
+ * 引擎回的 confirmation-required / protected-point / record-incomplete 一律翻成可读错误结果,
10
+ * **绝不绕过**(命令入口没有「确认按钮」,用户敲下 id 就是那次确认;其余门照旧全量生效)。
11
+ *
12
+ * 纪律(与 src/core/model-tools.ts 的 registerModelTools 同口径):
13
+ * · 命令服务**惰取**:一律 ctx.get('commands') 调用期读取,绝不属性访问 ctx.commands、
14
+ * 绝不放进 inject —— 未组合该服务的部署必须照常启动(命令是可选能力,不是硬依赖);
15
+ * · 注册失败只 warn:命令挂不上不得影响其它装配(宿主启动 = blocker);
16
+ * · 用户可见文案一律走宿主字典 engineMsg(key: command.rollback.*),**取文案那一刻**解析语言;
17
+ * · 本模块不 import @deepseek-ai/dsh-commands 的运行时值(只做结构化窄化),core 保持与 DSH 解耦。
18
+ */
19
+ import { engineMsg } from './engine-locale.js';
20
+ import { EnvironmentLockUnavailableError } from '../utils/env-lock.js';
21
+ /** 命令名(无前导斜杠)与别名。 */
22
+ export const ROLLBACK_COMMAND_NAME = 'rollback';
23
+ export const ROLLBACK_COMMAND_ALIAS = 'rw';
24
+ /**
25
+ * 命令定义 id:/rw 别名是**第二条定义** —— 同一个 definitionId(客户端按 definitionId 做身份化行为,
26
+ * 别名与主名必须被视作同一条命令)。
27
+ */
28
+ export const ROLLBACK_COMMAND_DEFINITION_ID = 'dsh-config-manager/rollback';
29
+ /** 绝对路径判定(win32 盘符 + POSIX 前缀 + UNC;纯函数,不引 node:path)。 */
30
+ export function isAbsolutePath(value) {
31
+ if (value.startsWith('/') || value.startsWith('\\'))
32
+ return true;
33
+ return /^[A-Za-z]:[\\/]/.test(value);
34
+ }
35
+ /**
36
+ * 从 agent 窄化会话事实。
37
+ *
38
+ * **不猜**:agent.session.id 读不出来就退回 agent.id(DSH 的 Agent.id 就是会话 id);
39
+ * 两者都读不出 → ok:false(命令如实报「拿不到当前会话」,而不是列全网的点)。
40
+ * 工作区分块只认**绝对路径**的 cwd(与 rollbackSessionBindingOf 同一口径)。
41
+ */
42
+ export function agentSessionFactsOf(agent) {
43
+ if (agent === null || typeof agent !== 'object')
44
+ return { ok: false, detail: 'agent-not-object' };
45
+ const rec = agent;
46
+ let sessionId;
47
+ let cwd;
48
+ const session = rec.session;
49
+ if (session !== null && typeof session === 'object') {
50
+ const s = session;
51
+ if (typeof s.id === 'string' && s.id !== '')
52
+ sessionId = s.id;
53
+ const header = s.header;
54
+ if (header !== null && typeof header === 'object') {
55
+ const value = header.cwd;
56
+ if (typeof value === 'string' && value !== '')
57
+ cwd = value;
58
+ }
59
+ }
60
+ if (sessionId === undefined && typeof rec.id === 'string' && rec.id !== '')
61
+ sessionId = rec.id;
62
+ if (sessionId === undefined)
63
+ return { ok: false, detail: 'session-id-missing' };
64
+ const chunks = cwd !== undefined && isAbsolutePath(cwd) ? [cwd] : [];
65
+ return { ok: true, sessionId, chunks };
66
+ }
67
+ /**
68
+ * 解析 rawInput(命令名之后的原文,含分隔空白)。
69
+ * 语法只有两种:空 = 列表;单个非空 token = 目标 id。多 token 一律 invalid。
70
+ */
71
+ export function parseRollbackCommand(rawInput) {
72
+ const trimmed = (rawInput ?? '').trim();
73
+ if (trimmed === '')
74
+ return { kind: 'list' };
75
+ const parts = trimmed.split(/\s+/);
76
+ if (parts.length !== 1)
77
+ return { kind: 'invalid', detail: 'too-many-arguments' };
78
+ return { kind: 'rewind', id: parts[0] ?? '' };
79
+ }
80
+ /* ------------------------------------------------------------------ 渲染 */
81
+ function isoOf(createdAt) {
82
+ if (!Number.isFinite(createdAt))
83
+ return '?';
84
+ try {
85
+ return new Date(createdAt).toISOString();
86
+ }
87
+ catch {
88
+ return '?';
89
+ }
90
+ }
91
+ /** 点状态:受保护 / 捕获不完整 / 正常(三者互斥,按引擎字段的优先级分派)。 */
92
+ function stateLabel(point) {
93
+ if (point.protected)
94
+ return engineMsg('command.rollback.stateProtected');
95
+ if (point.incomplete)
96
+ return engineMsg('command.rollback.stateIncomplete');
97
+ return engineMsg('command.rollback.stateNormal');
98
+ }
99
+ /** 该点两态各自的「可回退 / 不可回退」摘要(诚实:按段逐项说,再给总判)。 */
100
+ function restorableLabel(point) {
101
+ const segments = point.segments ?? [];
102
+ const parts = [];
103
+ for (const segment of segments) {
104
+ const label = segment.restorable ? engineMsg('command.rollback.restorableYes') : engineMsg('command.rollback.restorableNo');
105
+ parts.push(engineMsg('command.rollback.segmentLabel', {
106
+ state: engineMsg(segment.state === 'workspace' ? 'command.rollback.segmentWorkspace' : 'command.rollback.segmentSession'),
107
+ label,
108
+ }));
109
+ }
110
+ if (parts.length === 0)
111
+ return engineMsg('command.rollback.restorableNo');
112
+ const any = segments.some((segment) => segment.restorable);
113
+ return engineMsg('command.rollback.restorableSummary', {
114
+ parts: parts.join(engineMsg('command.rollback.listSeparator')),
115
+ verdict: any ? engineMsg('command.rollback.restorableYes') : engineMsg('command.rollback.restorableNo'),
116
+ });
117
+ }
118
+ function turnLabel(point) {
119
+ return point.turn === null ? engineMsg('command.rollback.turnUnknown') : String(point.turn);
120
+ }
121
+ function kindLabel(point) {
122
+ return engineMsg(point.kind === 'guard' ? 'command.rollback.kindGuard' : 'command.rollback.kindAuto');
123
+ }
124
+ /** 渲染只读列表(本会话没有点时给「本会话没有」,绝不冒充「全库为空」)。 */
125
+ export function renderRollbackList(result, sessionId) {
126
+ if (!result.storage.available) {
127
+ return {
128
+ kind: 'error',
129
+ text: engineMsg('command.rollback.storageUnavailable', { detail: result.storage.detail ?? result.storage.root }),
130
+ };
131
+ }
132
+ if (result.error !== undefined && result.error !== '') {
133
+ return { kind: 'error', text: engineMsg('command.rollback.listFailed', { detail: result.error }) };
134
+ }
135
+ const points = (result.points ?? []).filter((point) => point.sessionId === sessionId);
136
+ if (points.length === 0)
137
+ return { kind: 'error', text: engineMsg('command.rollback.empty') };
138
+ const lines = points.map((point, index) => engineMsg('command.rollback.listRow', {
139
+ index: String(index + 1),
140
+ id: point.id,
141
+ turn: turnLabel(point),
142
+ createdAt: isoOf(point.createdAt),
143
+ kind: kindLabel(point),
144
+ state: stateLabel(point),
145
+ restorable: restorableLabel(point),
146
+ }));
147
+ return { kind: 'success', text: [engineMsg('command.rollback.listTitle'), ...lines].join('\n') };
148
+ }
149
+ /** 段结果的一行技术事实(定位失败用;**不是**文案分派的语义依据)。 */
150
+ function segmentFacts(segments) {
151
+ if (segments === undefined || segments.length === 0)
152
+ return '';
153
+ return segments
154
+ .map((segment) => segment.state + '/' + segment.status + (segment.reasonCode !== undefined ? '(' + segment.reasonCode + ')' : ''))
155
+ .join(',');
156
+ }
157
+ /** 把引擎结果翻成命令结果(失败一律带机器码 + 技术细节;processed 的段事实不隐藏)。 */
158
+ export function renderRewindResult(result, id) {
159
+ const detail = result.detail ?? '';
160
+ if (result.ok && result.outcome === 'restored') {
161
+ return { kind: 'success', text: engineMsg('command.rollback.rewindRestored', { id, detail }) };
162
+ }
163
+ if (result.outcome === 'partial') {
164
+ // 「部分恢复」既不是成功也不是泛化失败:逐段事实必须上屏(含被跳过的段)。
165
+ return {
166
+ kind: 'error',
167
+ text: engineMsg('command.rollback.rewindPartial', {
168
+ id,
169
+ segments: engineMsg('command.rollback.segmentFacts', { facts: segmentFacts(result.segments) }),
170
+ detail,
171
+ }),
172
+ };
173
+ }
174
+ return {
175
+ kind: 'error',
176
+ text: engineMsg('command.rollback.rewindFailed', { id, code: String(result.code), detail }),
177
+ };
178
+ }
179
+ /**
180
+ * 构造命令处理器(**纯编排**:不注册、不读 ctx)。
181
+ *
182
+ * 带参数时:parser → agentSession(只用于「这次是不是列表」的会话判定)→ host.rewind。
183
+ * host.rewind 内部才是那道门:runWithMutationLock → SAFE MODE → 引擎 preview → 引擎 rewind
184
+ * EnvironmentLockUnavailableError(SAFE MODE / 环境锁被挡)在此翻成可读错误结果。
185
+ * 任何未预期异常也翻成错误结果 —— 命令处理器抛异常会让整条命令生命周期报泛化失败,
186
+ * UI 只看到一句「失败」;这里如实把原因说清楚。
187
+ */
188
+ export function makeRollbackCommandHandler(deps) {
189
+ return async (invocation) => {
190
+ const parsed = parseRollbackCommand(invocation.rawInput);
191
+ if (parsed.kind === 'invalid') {
192
+ return { kind: 'error', text: engineMsg('command.rollback.usageInvalid', { detail: parsed.detail }) };
193
+ }
194
+ const facts = deps.host.agentSession(invocation.agent);
195
+ if (!facts.ok) {
196
+ return { kind: 'error', text: engineMsg('command.rollback.sessionUnavailable', { detail: facts.detail }) };
197
+ }
198
+ if (parsed.kind === 'list') {
199
+ try {
200
+ return renderRollbackList(await deps.host.list(facts.sessionId), facts.sessionId);
201
+ }
202
+ catch (error) {
203
+ return { kind: 'error', text: engineMsg('command.rollback.listFailed', { detail: errorText(error) }) };
204
+ }
205
+ }
206
+ try {
207
+ const execution = {
208
+ id: parsed.id,
209
+ ...(invocation.signal !== undefined ? { signal: invocation.signal } : {}),
210
+ };
211
+ return renderRewindResult(await deps.host.rewind(execution), parsed.id);
212
+ }
213
+ catch (error) {
214
+ if (error instanceof EnvironmentLockUnavailableError) {
215
+ return {
216
+ kind: 'error',
217
+ text: engineMsg('command.rollback.mutationLocked', { reason: error.reason, id: parsed.id }),
218
+ };
219
+ }
220
+ return {
221
+ kind: 'error',
222
+ text: engineMsg('command.rollback.rewindFailed', { id: parsed.id, code: 'exception', detail: errorText(error) }),
223
+ };
224
+ }
225
+ };
226
+ }
227
+ function errorText(error) {
228
+ return error instanceof Error ? error.message : String(error);
229
+ }
230
+ /**
231
+ * 注册 /rollback 与 /rw(两条定义 = 同一 definitionId)。
232
+ *
233
+ * 服务缺失 → warn 后**安静返回**(未组合 commands 的部署照常启动、不抛错);
234
+ * 服务存在但 register 抛错 → warn(其余装配不受影响)。
235
+ * @returns 反注册函数(重复调用安全)。
236
+ */
237
+ export function registerRollbackCommand(options) {
238
+ const disposers = [];
239
+ let service;
240
+ try {
241
+ service = options.readCommands() ?? undefined;
242
+ }
243
+ catch (error) {
244
+ options.log?.warn(engineMsg('command.rollback.serviceUnavailable', { detail: errorText(error) }));
245
+ return () => { };
246
+ }
247
+ if (service === undefined || typeof service.register !== 'function') {
248
+ options.log?.warn(engineMsg('command.rollback.serviceUnavailable', { detail: 'commands-service-missing' }));
249
+ return () => { };
250
+ }
251
+ const handler = makeRollbackCommandHandler(options.deps);
252
+ const definitions = [
253
+ {
254
+ name: ROLLBACK_COMMAND_NAME,
255
+ definitionId: ROLLBACK_COMMAND_DEFINITION_ID,
256
+ description: engineMsg('command.rollback.commandDesc'),
257
+ input: { hint: engineMsg('command.rollback.commandInputHint') },
258
+ handler,
259
+ },
260
+ {
261
+ name: ROLLBACK_COMMAND_ALIAS,
262
+ definitionId: ROLLBACK_COMMAND_DEFINITION_ID,
263
+ description: engineMsg('command.rollback.commandDescAlias'),
264
+ input: { hint: engineMsg('command.rollback.commandInputHint') },
265
+ handler,
266
+ },
267
+ ];
268
+ for (const definition of definitions) {
269
+ try {
270
+ const disposer = service.register(definition);
271
+ if (typeof disposer === 'function')
272
+ disposers.push(disposer);
273
+ }
274
+ catch (error) {
275
+ options.log?.warn(engineMsg('command.rollback.registerFailed', { name: definition.name, detail: errorText(error) }));
276
+ }
277
+ }
278
+ return () => {
279
+ for (const dispose of disposers.splice(0)) {
280
+ try {
281
+ dispose();
282
+ }
283
+ catch (error) {
284
+ options.log?.warn(engineMsg('command.rollback.registerFailed', { name: 'dispose', detail: errorText(error) }));
285
+ }
286
+ }
287
+ };
288
+ }
289
+ //# sourceMappingURL=command-rollback.js.map
@@ -17,6 +17,7 @@ import { MANIFEST_FILE, CHECKSUMS_FILE, parseManifest, validateManifest } from '
17
17
  import { verifyChecksumsJson } from '../security/integrity.js';
18
18
  import { SECTION_JSON_PATHS, SECTION_FILE_PREFIXES, isFileSection } from '../schema/config.js';
19
19
  import { scanAndRedact, scanText } from '../security/secret-scanner.js';
20
+ import { engineMsg } from './messages-core.js';
20
21
  /** 从导出 ZIP 读取并归一化源数据(只读) */
21
22
  export async function readExportZipSource(ref, zipPath, opts = {}) {
22
23
  const highEntropy = opts.highEntropy ?? true;
@@ -62,12 +63,12 @@ export async function readExportZipSource(ref, zipPath, opts = {}) {
62
63
  manifestIssues = validateManifest(parsed);
63
64
  }
64
65
  catch {
65
- manifestIssues = [{ path: '$', message: 'manifest 无法解析', severity: 'error' }];
66
+ manifestIssues = [{ path: '$', message: engineMsg('core.consult.manifestUnparsable'), severity: 'error' }];
66
67
  }
67
68
  }
68
69
  }
69
70
  else {
70
- manifestIssues = [{ path: '$', message: 'manifest 缺失', severity: 'error' }];
71
+ manifestIssues = [{ path: '$', message: engineMsg('core.consult.manifestMissing'), severity: 'error' }];
71
72
  }
72
73
  // 3. checksums(捕获不匹配,不抛错)
73
74
  const checksumIssues = [];
@@ -86,9 +87,9 @@ export async function readExportZipSource(ref, zipPath, opts = {}) {
86
87
  const result = verifyChecksumsJson(entries, archive.readEntryText(CHECKSUMS_FILE));
87
88
  checksums = result.ok ? {} : null;
88
89
  for (const m of result.mismatches)
89
- checksumIssues.push(`"${m}" (hash 不符)`);
90
+ checksumIssues.push(engineMsg('core.consult.hashMismatch', { name: m }));
90
91
  for (const m of result.missing)
91
- checksumIssues.push(`"${m}" (缺失)`);
92
+ checksumIssues.push(engineMsg('core.consult.entryMissing', { name: m }));
92
93
  }
93
94
  catch (err) {
94
95
  checksumIssues.push(err instanceof Error ? err.message : String(err));
@@ -184,8 +185,8 @@ export function buildLocalSnapshotSource(ref, input) {
184
185
  sections: sectionFlags,
185
186
  security: { containsSecrets: false, encrypted: false, encryption: null },
186
187
  };
187
- const manifestIssues = input.verify.ok ? [] : [{ path: '$', message: input.verify.reason ?? '快照完整性校验失败', severity: 'error' }];
188
- const checksumIssues = input.verify.ok ? [] : [input.verify.reason ?? '快照完整性校验失败'];
188
+ const manifestIssues = input.verify.ok ? [] : [{ path: '$', message: input.verify.reason ?? engineMsg('core.consult.snapshotIntegrityFailed'), severity: 'error' }];
189
+ const checksumIssues = input.verify.ok ? [] : [input.verify.reason ?? engineMsg('core.consult.snapshotIntegrityFailed')];
189
190
  const migratability = {
190
191
  ok: input.restorePlan.errors.length === 0,
191
192
  itemCount: input.restorePlan.itemCount,
@@ -1,7 +1,20 @@
1
- /** 体检子区(顺序即界面展示顺序:先备份产物,再缓存/暂存) */
2
- export declare const DISK_USAGE_AREAS: readonly ['exports', 'snapshots', 'sync', 'marketCache', 'marketWork', 'tmp', 'logs', 'bootState', 'migrationHistory', 'transactions', 'locks', 'vault'];
3
- /** 体检子区 id */
4
- export type DiskUsageArea = typeof DISK_USAGE_AREAS[number];
1
+ /**
2
+ * 只报告、**不提供清理**的子区(当前一条:回滚点库 = `dataDir/rollback-points`)。
3
+ * 它只是「口径清单」:报告/展示一律用完备的 `DISK_USAGE_AREAS`,清理候选另有白名单
4
+ * (`IMMEDIATE_CLEAN_CATEGORIES` / 清理入口 categories),两者不得混用。
5
+ */
6
+ export declare const DISK_USAGE_EXTRA_AREAS: readonly ['rollback-points'];
7
+ /** 体检子区(顺序即报告/展示顺序:先备份产物,再缓存/暂存,末位为只读保护的附加区) */
8
+ export declare const DISK_USAGE_AREAS: readonly ["exports", "snapshots", "sync", "marketCache", "marketWork", "tmp", "logs", "bootState", "migrationHistory", "transactions", "locks", "vault", "rollback-points"];
9
+ /** 全部体检子区 id(= `DISK_USAGE_AREAS` 的元素类型) */
10
+ export type DiskUsageScanArea = typeof DISK_USAGE_AREAS[number];
11
+ /**
12
+ * 体检子区 id(**与 `DiskUsageScanArea` 同一集合**,13 键完备)。
13
+ *
14
+ * 2026-10-13 收口:文案登记(t6)落地后不再分叉 —— 按本类型写 `Record<DiskUsageArea, …>`
15
+ * 时漏掉任一子区(含 rollback-points)都会在编译期报错,而不是静默缺项。
16
+ */
17
+ export type DiskUsageArea = DiskUsageScanArea;
5
18
  /** 子区回收策略语义(决定界面文案,不由界面自行判断) */
6
19
  export type DiskUsagePolicy =
7
20
  /** 可随时重建/可重新下载:现在就能整块清掉(tmp、market/cache、market/work) */
@@ -27,20 +40,69 @@ export interface DiskUsageAreaReport {
27
40
  /** 已超过保留期的条目数(仅 retained) */
28
41
  expiredCount?: number;
29
42
  }
43
+ /**
44
+ * 已知的**遗留数据**目录(插件已不再读取、也绝不自动清理)。
45
+ *
46
+ * 为什么单列而不并进 `DISK_USAGE_AREAS`:它们不是「本插件的现役数据区」——不再被任何代码
47
+ * 读取、也不参与清理;报告只用**相对 dataDir 的路径**把它们指认清楚,
48
+ * 且结构必须能容纳未来更多条(数组,不是单条 object)。
49
+ */
50
+ export interface LegacyDataDir {
51
+ /** 稳定 id(界面/接口引用) */
52
+ id: string;
53
+ /** 相对 dataDir 的 POSIX 风格相对路径(如 `checkpoints`) */
54
+ relPath: string;
55
+ }
56
+ /**
57
+ * 遗留数据目录清单(当前一条:旧检查点库)。
58
+ *
59
+ * `checkpoints/` 是回滚点库改名(`rollback-points/`)之前的旧目录:新代码**不再读取**它,
60
+ * 本插件也**不去删**它(删除是不可逆动作,需用户单独授权)。
61
+ */
62
+ export declare const LEGACY_DATA_DIRS: readonly LegacyDataDir[];
63
+ /** 单条遗留数据的体检结果(只报告;`policy` 恒为 protected) */
64
+ export interface DiskUsageLegacyEntry {
65
+ /** 稳定 id(与 `LEGACY_DATA_DIRS` 逐条对应) */
66
+ id: string;
67
+ /** 相对 dataDir 的路径(如 `checkpoints`) */
68
+ relPath: string;
69
+ /** 绝对路径(界面「在哪儿」展示) */
70
+ path: string;
71
+ /** 字节数(不存在/不可读 → 0,必须与 unreadable 一起看) */
72
+ sizeBytes: number;
73
+ /** 文件数(不存在/不可读 → 0) */
74
+ fileCount: number;
75
+ /** 读不到/不存在/被非目录占住 → true(界面必须显示「未统计」,绝不伪报 0 字节) */
76
+ unreadable: boolean;
77
+ /** 恒为 `protected`:只报告,绝不提供自动清理 */
78
+ policy: 'protected';
79
+ }
80
+ /** 子区明细记录:`DISK_USAGE_AREAS` 的**每个**子区(含回滚点库等附加子区)逐键必填 ——
81
+ * 报告运行时恒为完整结构,索引访问不可能拿到 undefined(`noUncheckedIndexedAccess` 下也成立,
82
+ * 故只读消费者如离线救急台可直接 `report.areas[area]`,不需要缺失回退)。 */
83
+ export type DiskUsageAreasReport = Record<DiskUsageScanArea, DiskUsageAreaReport>;
30
84
  /** 体检报告(路径字段供界面「在哪儿」展示;均为本机绝对路径,无敏感内容) */
31
85
  export interface DiskUsageReport {
32
86
  /** dataDir(`$DSH_HOME/dsh-config-manager`) */
33
87
  dataDir: string;
34
- /** 全部子区合计字节数 */
88
+ /** 全部**子区**合计字节数(含回滚点库等附加子区;**不含**遗留数据 —— 见 legacy) */
35
89
  totalBytes: number;
36
- /** 全部子区合计文件数 */
90
+ /** 全部子区合计文件数(口径同 totalBytes) */
37
91
  totalFiles: number;
38
92
  /** 可立即清理(regenerable)子区合计字节数 */
39
93
  reclaimableBytes: number;
40
94
  /** 到达自动回收期的字节数(retained 子区) */
41
95
  expiredBytes: number;
42
- /** 各子区明细 */
43
- areas: Record<DiskUsageArea, DiskUsageAreaReport>;
96
+ /** 各子区明细(恒含 `DISK_USAGE_AREAS` 的全部子区,逐键必填) */
97
+ areas: DiskUsageAreasReport;
98
+ /**
99
+ * 遗留数据明细(插件**已不再读取**、也**不代删**;只报告)。
100
+ * 结构可容纳多条(见 `LEGACY_DATA_DIRS`);**不计入 totalBytes**(子区合计与遗留数据
101
+ * 分开列,界面才不会把「能解释来源的占用」和「遗留占用」混成一个数)。
102
+ * 类型上可选只是为了让既有报告字面量(测试/旧调用方)继续成立 —— 宿主
103
+ * `GET /disk-usage` 恒回传本字段(无遗留目录时为空数组)。
104
+ */
105
+ legacy?: readonly DiskUsageLegacyEntry[];
44
106
  /** 定时备份产物的保留口径(「保留最近 N 个」;界面用它解释为什么有的备份不会自动回收) */
45
107
  backupRetention: {
46
108
  keepLast: number;
@@ -72,8 +134,10 @@ export declare const IMMEDIATE_CLEAN_CATEGORIES: readonly ['tmp', 'marketCache',
72
134
  export type ImmediateCleanCategory = typeof IMMEDIATE_CLEAN_CATEGORIES[number];
73
135
  /** 缓存清理结果里与子区对应的键(老字段快照/临时/市场沿用原语义) */
74
136
  export type CleanupResultCategory = ImmediateCleanCategory | 'exports';
75
- /** 子区 → 物理目录(单一映射点;展示与统计都不再重复挑目录) */
76
- export declare function diskUsageDirOf(dirs: DiskUsageDirs, area: DiskUsageArea): string;
137
+ /** 子区 → 物理目录(单一映射点;展示与统计都不再重复挑目录)。
138
+ * 回滚点库不在 `DiskUsageDirs` 里显式传:它的位置 = `dataDir` + `ROLLBACK_POINTS_DIR`
139
+ * (与引擎常量逐字一致,有源码级守卫),宿主路由与离线 CLI 两条构造路径因此不可能漂移。 */
140
+ export declare function diskUsageDirOf(dirs: DiskUsageDirs, area: DiskUsageScanArea): string;
77
141
  /** 子区语义与保留期(界面据此选文案;retained 子区必带 retentionMs) */
78
142
  export interface DiskUsagePolicyInput {
79
143
  /** 导出产物保留期(cache-cleaner 的 exportsRetentionMs) */