dsh-config-manager 0.1.71 → 0.1.73

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 (596) hide show
  1. package/README.md +149 -98
  2. package/README.zh-CN.md +245 -88
  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 +2 -1
  6. package/lib/adapters/index.js +6 -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 +21 -0
  10. package/lib/adapters/messages.js +57 -0
  11. package/lib/adapters/plugin-data.d.ts +114 -0
  12. package/lib/adapters/plugin-data.js +309 -0
  13. package/lib/adapters/plugin-files.js +3 -2
  14. package/lib/adapters/plugins.js +4 -3
  15. package/lib/adapters/prompts.d.ts +1 -0
  16. package/lib/adapters/prompts.js +7 -1
  17. package/lib/adapters/self.d.ts +8 -2
  18. package/lib/adapters/self.js +3 -2
  19. package/lib/adapters/sessions.d.ts +1 -0
  20. package/lib/adapters/sessions.js +4 -2
  21. package/lib/adapters/test-helpers.d.ts +9 -0
  22. package/lib/adapters/test-helpers.js +14 -0
  23. package/lib/adapters/ui.d.ts +2 -2
  24. package/lib/adapters/ui.js +25 -25
  25. package/lib/adapters/workspaces.d.ts +1 -0
  26. package/lib/adapters/workspaces.js +7 -3
  27. package/lib/cli/actions.d.ts +9 -1
  28. package/lib/cli/actions.js +5 -2
  29. package/lib/cli/help.js +23 -10
  30. package/lib/cli/index.d.ts +23 -0
  31. package/lib/cli/index.js +90 -32
  32. package/lib/cli/sessions-inspect.js +3 -1
  33. package/lib/cli/sessions-repair.js +25 -6
  34. package/lib/cli/web/page.d.ts +12 -0
  35. package/lib/cli/web/page.js +21 -12
  36. package/lib/cli/web/routes.js +2 -2
  37. package/lib/cli/web/server.js +4 -4
  38. package/lib/client.d.ts +1442 -494
  39. package/lib/client.js +15326 -8520
  40. package/lib/core/analyzer.d.ts +11 -2
  41. package/lib/core/analyzer.js +31 -8
  42. package/lib/core/backup-plan.d.ts +10 -0
  43. package/lib/core/backup-plan.js +51 -20
  44. package/lib/core/backup-verify.js +24 -23
  45. package/lib/core/backup.d.ts +25 -1
  46. package/lib/core/backup.js +99 -28
  47. package/lib/core/boot-rescue.js +4 -3
  48. package/lib/core/boot-safety.js +2 -1
  49. package/lib/core/command-rollback.d.ts +182 -0
  50. package/lib/core/command-rollback.js +293 -0
  51. package/lib/core/consult-source.js +7 -6
  52. package/lib/core/disk-usage.d.ts +74 -10
  53. package/lib/core/disk-usage.js +67 -4
  54. package/lib/core/engine-locale.d.ts +87 -0
  55. package/lib/core/engine-locale.js +125 -0
  56. package/lib/core/exporter.js +3 -3
  57. package/lib/core/fork-reconcile.d.ts +128 -0
  58. package/lib/core/fork-reconcile.js +150 -0
  59. package/lib/core/journal.js +6 -5
  60. package/lib/core/local-plugin-host.js +3 -2
  61. package/lib/core/local-plugin-pack.js +11 -6
  62. package/lib/core/messages-core.d.ts +294 -0
  63. package/lib/core/messages-core.js +619 -0
  64. package/lib/core/messages.d.ts +61 -2
  65. package/lib/core/messages.js +118 -13
  66. package/lib/core/migration-consult.js +21 -20
  67. package/lib/core/migration-history.js +19 -5
  68. package/lib/core/model-tools.d.ts +0 -22
  69. package/lib/core/model-tools.js +50 -27
  70. package/lib/core/phase3-host.js +30 -5
  71. package/lib/core/plugin-cli.js +18 -19
  72. package/lib/core/plugin-data-registry.d.ts +124 -0
  73. package/lib/core/plugin-data-registry.js +198 -0
  74. package/lib/core/reconcile.d.ts +2 -14
  75. package/lib/core/reconcile.js +87 -17
  76. package/lib/core/recovery-orchestrator.js +19 -18
  77. package/lib/core/reinstall.d.ts +4 -0
  78. package/lib/core/reinstall.js +26 -21
  79. package/lib/core/restore.js +20 -17
  80. package/lib/core/rollback-gate.d.ts +33 -0
  81. package/lib/core/rollback-gate.js +57 -0
  82. package/lib/core/rollback-ignore-rules.d.ts +31 -0
  83. package/lib/core/rollback-ignore-rules.js +140 -0
  84. package/lib/core/rollback-ledger.d.ts +248 -0
  85. package/lib/core/rollback-ledger.js +1282 -0
  86. package/lib/core/rollback-point.d.ts +1391 -0
  87. package/lib/core/rollback-point.js +3503 -0
  88. package/lib/core/rollback.js +6 -4
  89. package/lib/core/run-registry.js +6 -5
  90. package/lib/core/session-health.d.ts +15 -0
  91. package/lib/core/session-meta.d.ts +42 -2
  92. package/lib/core/session-meta.js +140 -1
  93. package/lib/core/session-title.d.ts +28 -0
  94. package/lib/core/session-title.js +185 -0
  95. package/lib/core/startup-barrier.d.ts +24 -0
  96. package/lib/core/startup-barrier.js +22 -0
  97. package/lib/core/transaction-coordinator.js +4 -3
  98. package/lib/core/types.d.ts +37 -1
  99. package/lib/core/validator.js +5 -4
  100. package/lib/core/verify-recovery.js +31 -30
  101. package/lib/foreign/bundle.js +3 -2
  102. package/lib/foreign/continue.js +2 -1
  103. package/lib/foreign/crush.js +2 -1
  104. package/lib/foreign/gemini.js +2 -1
  105. package/lib/foreign/goose.js +2 -1
  106. package/lib/foreign/kilocode.js +2 -1
  107. package/lib/foreign/kimi.js +2 -1
  108. package/lib/foreign/messages.d.ts +15 -0
  109. package/lib/foreign/messages.js +40 -0
  110. package/lib/foreign/mimocode.js +2 -1
  111. package/lib/foreign/openclaw.js +2 -1
  112. package/lib/foreign/opencode.js +2 -1
  113. package/lib/foreign/pi.js +2 -1
  114. package/lib/foreign/qoder.js +2 -1
  115. package/lib/foreign/qwen.js +2 -1
  116. package/lib/foreign/registry.d.ts +1 -1
  117. package/lib/foreign/registry.js +8 -7
  118. package/lib/foreign/teleagent.js +2 -1
  119. package/lib/foreign/workbuddy.js +2 -1
  120. package/lib/foreign/zcode.js +2 -1
  121. package/lib/foreign/zed.js +2 -1
  122. package/lib/index.d.ts +227 -7
  123. package/lib/index.js +799 -54
  124. package/lib/market/git-file-writer.js +20 -19
  125. package/lib/market/github-repos.js +35 -19
  126. package/lib/market/index-parser.js +31 -30
  127. package/lib/market/messages-market.d.ts +138 -0
  128. package/lib/market/messages-market.js +305 -0
  129. package/lib/market/my-repo.d.ts +2 -2
  130. package/lib/market/my-repo.js +32 -29
  131. package/lib/market/prepare.js +18 -15
  132. package/lib/market/security.js +20 -19
  133. package/lib/market/types.js +2 -1
  134. package/lib/market/url.js +2 -1
  135. package/lib/migrations/index.js +6 -5
  136. package/lib/migrations/messages-migrations.d.ts +32 -0
  137. package/lib/migrations/messages-migrations.js +58 -0
  138. package/lib/profiles/dsh-profile-launcher.js +2 -1
  139. package/lib/profiles/dsh-profile-runtime.js +2 -1
  140. package/lib/profiles/messages.d.ts +7 -0
  141. package/lib/profiles/messages.js +27 -0
  142. package/lib/routes/backup.js +18 -2
  143. package/lib/routes/import.js +3 -3
  144. package/lib/routes/index.d.ts +1 -1
  145. package/lib/routes/kit.d.ts +3 -2
  146. package/lib/routes/kit.js +6 -1
  147. package/lib/routes/market.js +1 -1
  148. package/lib/routes/messages.d.ts +43 -0
  149. package/lib/routes/messages.js +102 -0
  150. package/lib/routes/prefs.js +26 -3
  151. package/lib/routes/profiles.js +12 -6
  152. package/lib/routes/recovery.d.ts +21 -0
  153. package/lib/routes/recovery.js +478 -94
  154. package/lib/routes/snapshots.js +51 -4
  155. package/lib/routes/sync.js +79 -17
  156. package/lib/schema/config.d.ts +11 -1
  157. package/lib/schema/config.js +52 -20
  158. package/lib/schema/index.d.ts +8 -6
  159. package/lib/schema/index.js +8 -6
  160. package/lib/schema/manifest.js +19 -18
  161. package/lib/schema/messages.d.ts +47 -0
  162. package/lib/schema/messages.js +110 -0
  163. package/lib/schema/section-registry.d.ts +42 -15
  164. package/lib/schema/section-registry.js +67 -32
  165. package/lib/schema/types.d.ts +1 -1
  166. package/lib/schema/versions.js +6 -5
  167. package/lib/security/encryption.js +16 -15
  168. package/lib/security/integrity.js +8 -7
  169. package/lib/security/messages.d.ts +30 -0
  170. package/lib/security/messages.js +77 -0
  171. package/lib/security/redaction.js +12 -0
  172. package/lib/security/secret-scanner.js +16 -13
  173. package/lib/security/vault.js +2 -1
  174. package/lib/security/zip-security.js +4 -3
  175. package/lib/sync/ancestor.js +2 -1
  176. package/lib/sync/autosync-config.d.ts +11 -0
  177. package/lib/sync/autosync-config.js +12 -0
  178. package/lib/sync/autosync-scheduler.d.ts +11 -1
  179. package/lib/sync/autosync-scheduler.js +115 -76
  180. package/lib/sync/backup-files.js +3 -2
  181. package/lib/sync/backup-scheduler.js +6 -5
  182. package/lib/sync/blob-store.js +2 -1
  183. package/lib/sync/git/git-transport.d.ts +55 -0
  184. package/lib/sync/git/git-transport.js +152 -2
  185. package/lib/sync/github-auth.js +10 -9
  186. package/lib/sync/layout.js +13 -12
  187. package/lib/sync/messages.d.ts +63 -0
  188. package/lib/sync/messages.js +149 -0
  189. package/lib/sync/review-queue.js +6 -5
  190. package/lib/sync/s3/messages.d.ts +7 -0
  191. package/lib/sync/s3/messages.js +16 -0
  192. package/lib/sync/s3/s3-providers.d.ts +4 -1
  193. package/lib/sync/s3/s3-providers.js +5 -5
  194. package/lib/sync/s3/s3-transport.js +1 -1
  195. package/lib/sync/s3/sigv4.js +2 -1
  196. package/lib/sync/snapshot-crypto.js +6 -5
  197. package/lib/sync/snapshot-json.js +3 -2
  198. package/lib/sync/sync-engine.d.ts +58 -22
  199. package/lib/sync/sync-engine.js +119 -48
  200. package/lib/sync/sync-history.js +7 -6
  201. package/lib/sync/sync-selection.d.ts +15 -4
  202. package/lib/sync/sync-selection.js +17 -5
  203. package/lib/sync/ui-prefs.d.ts +22 -0
  204. package/lib/sync/ui-prefs.js +28 -0
  205. package/lib/sync/webdav/webdav-transport.d.ts +1 -0
  206. package/lib/sync/webdav/webdav-transport.js +4 -1
  207. package/lib/ui/artifact-view.js +4 -3
  208. package/lib/ui/commands.d.ts +1 -1
  209. package/lib/ui/commands.js +10 -0
  210. package/lib/ui/diff-view.d.ts +10 -0
  211. package/lib/ui/diff-view.js +17 -0
  212. package/lib/ui/disk-usage-view.d.ts +33 -4
  213. package/lib/ui/disk-usage-view.js +29 -1
  214. package/lib/ui/errors.d.ts +1 -1
  215. package/lib/ui/errors.js +4 -3
  216. package/lib/ui/export-flow.js +26 -20
  217. package/lib/ui/foreign-view.d.ts +5 -1
  218. package/lib/ui/foreign-view.js +26 -2
  219. package/lib/ui/i18n.d.ts +68 -1
  220. package/lib/ui/i18n.js +120 -2
  221. package/lib/ui/import-wizard.d.ts +7 -0
  222. package/lib/ui/import-wizard.js +13 -10
  223. package/lib/ui/progress.d.ts +2 -2
  224. package/lib/ui/progress.js +1 -2
  225. package/lib/ui/report.d.ts +5 -5
  226. package/lib/ui/report.js +6 -6
  227. package/lib/ui/rollback-view.d.ts +815 -0
  228. package/lib/ui/rollback-view.js +738 -0
  229. package/lib/ui/selection-model.d.ts +41 -0
  230. package/lib/ui/selection-model.js +30 -0
  231. package/lib/ui/session-inventory-view.d.ts +97 -3
  232. package/lib/ui/session-inventory-view.js +76 -2
  233. package/lib/ui/session-issue-labels.d.ts +43 -0
  234. package/lib/ui/session-issue-labels.js +48 -0
  235. package/lib/ui/sync-settings-view.d.ts +33 -0
  236. package/lib/ui/sync-settings-view.js +40 -0
  237. package/lib/ui/test-helpers.js +2 -1
  238. package/lib/ui/types.d.ts +8 -3
  239. package/lib/ui/types.js +1 -1
  240. package/lib/utils/atomic-write.js +6 -5
  241. package/lib/utils/bundle-scan.d.ts +11 -1
  242. package/lib/utils/bundle-scan.js +12 -1
  243. package/lib/utils/env-lock.d.ts +10 -0
  244. package/lib/utils/env-lock.js +73 -46
  245. package/lib/utils/json.js +6 -5
  246. package/lib/utils/messages-utils.d.ts +96 -0
  247. package/lib/utils/messages-utils.js +216 -0
  248. package/lib/utils/proxy.js +18 -5
  249. package/lib/utils/recursive-walk.d.ts +22 -0
  250. package/lib/utils/recursive-walk.js +75 -1
  251. package/lib/utils/session-log-repair.js +10 -9
  252. package/lib/utils/zip.js +27 -26
  253. package/package.json +12 -2
  254. package/src/adapters/agent-instructions.ts +1 -1
  255. package/src/adapters/file-collection.test.ts +1 -0
  256. package/src/adapters/file-collection.ts +1 -1
  257. package/src/adapters/files.test.ts +27 -0
  258. package/src/adapters/index.ts +6 -1
  259. package/src/adapters/link-report.test.ts +22 -2
  260. package/src/adapters/link-report.ts +29 -4
  261. package/src/adapters/messages.ts +61 -0
  262. package/src/adapters/plugin-data.test.ts +225 -0
  263. package/src/adapters/plugin-data.ts +351 -0
  264. package/src/adapters/plugin-files.ts +3 -2
  265. package/src/adapters/plugins.ts +4 -3
  266. package/src/adapters/prompts.ts +7 -1
  267. package/src/adapters/self.test.ts +26 -0
  268. package/src/adapters/self.ts +10 -3
  269. package/src/adapters/sessions.ts +4 -2
  270. package/src/adapters/settings.test.ts +38 -1
  271. package/src/adapters/test-helpers.ts +15 -0
  272. package/src/adapters/ui.test.ts +2 -2
  273. package/src/adapters/ui.ts +27 -26
  274. package/src/adapters/workspaces.ts +7 -3
  275. package/src/cli/actions.test.ts +28 -0
  276. package/src/cli/actions.ts +11 -2
  277. package/src/cli/help.ts +23 -10
  278. package/src/cli/index-guards.test.ts +193 -0
  279. package/src/cli/index.ts +106 -31
  280. package/src/cli/sessions-inspect.test.ts +15 -1
  281. package/src/cli/sessions-inspect.ts +3 -1
  282. package/src/cli/sessions-repair.test.ts +84 -0
  283. package/src/cli/sessions-repair.ts +33 -7
  284. package/src/cli/web/console-route-parity.test.ts +115 -0
  285. package/src/cli/web/page.ts +23 -12
  286. package/src/cli/web/routes.ts +2 -1
  287. package/src/cli/web/server.ts +4 -4
  288. package/src/cli/web/web.test.ts +2 -2
  289. package/src/client/ConfigManagerSection.tsx +30 -2
  290. package/src/client/about/AboutPanel.tsx +2 -2
  291. package/src/client/about/PluginUpdateDialog.tsx +1 -1
  292. package/src/client/about/ReleaseNotesDialog.tsx +2 -2
  293. package/src/client/about/about-view.test.ts +13 -3
  294. package/src/client/about/about-view.ts +10 -6
  295. package/src/client/about/release-notes-view.test.ts +14 -4
  296. package/src/client/about/release-notes-view.ts +4 -2
  297. package/src/client/api.ts +18 -6
  298. package/src/client/chat/ChatEntryView.tsx +411 -0
  299. package/src/client/chat/RollbackDiffTab.tsx +108 -0
  300. package/src/client/chat/RollbackFileIcon.tsx +96 -0
  301. package/src/client/chat/RollbackReviewDialog.tsx +607 -0
  302. package/src/client/chat/chat-entry-view.test.ts +1174 -0
  303. package/src/client/chat/chat-entry-view.ts +758 -0
  304. package/src/client/chat/chat-locales.ts +152 -0
  305. package/src/client/chat/chat-node-registration.ts +64 -0
  306. package/src/client/chat/chat-point-window.ts +183 -0
  307. package/src/client/chat/chat-slots.ts +107 -0
  308. package/src/client/chat/rollback-diff-tab.test.ts +105 -0
  309. package/src/client/chat/rollback-diff-tab.ts +174 -0
  310. package/src/client/chat/rollback-entry-view.test.ts +1469 -0
  311. package/src/client/chat/rollback-entry-view.ts +946 -0
  312. package/src/client/chat/sidebar-slots.ts +59 -0
  313. package/src/client/common/ConfirmDialog.tsx +7 -3
  314. package/src/client/common/ContentPicker.tsx +48 -10
  315. package/src/client/common/DiffTable.tsx +133 -0
  316. package/src/client/common/ErrorBanner.tsx +4 -4
  317. package/src/client/common/Icon.tsx +2 -0
  318. package/src/client/common/Modal.tsx +8 -1
  319. package/src/client/common/ProgressBar.tsx +8 -2
  320. package/src/client/common/ReportView.tsx +4 -4
  321. package/src/client/common/RunsCenter.tsx +1 -0
  322. package/src/client/common/client-route-parity.test.ts +84 -0
  323. package/src/client/common/info-hint-guard.test.ts +46 -13
  324. package/src/client/common/picker-lazy-units.test.ts +42 -0
  325. package/src/client/common/plan-text-redaction.test.ts +17 -6
  326. package/src/client/common/progress-view-edge.test.ts +8 -7
  327. package/src/client/common/progress-view.test.ts +9 -9
  328. package/src/client/common/progress-view.ts +2 -2
  329. package/src/client/common/routes.ts +38 -0
  330. package/src/client/common/section-labels.test.ts +1 -0
  331. package/src/client/common/section-labels.ts +2 -0
  332. package/src/client/common/ui.tsx +73 -10
  333. package/src/client/config-manager.module.css +1109 -31
  334. package/src/client/css-scale-guard.test.ts +30 -0
  335. package/src/client/environment/EnvironmentPanel.tsx +11 -4
  336. package/src/client/environment/maintenance/DiskUsageCard.tsx +23 -2
  337. package/src/client/export/ExportView.tsx +13 -8
  338. package/src/client/history/HistoryPanel.tsx +4 -3
  339. package/src/client/history/history-api.ts +2 -2
  340. package/src/client/history/history-locales.ts +5 -1
  341. package/src/client/home/HomePanel.tsx +29 -8
  342. package/src/client/import/ForeignImportView.tsx +4 -5
  343. package/src/client/import/ImportWizardView.tsx +5 -3
  344. package/src/client/import/import-wizard-split.test.ts +3 -1
  345. package/src/client/import/import-wizard-steps.tsx +9 -9
  346. package/src/client/index.ts +232 -3
  347. package/src/client/library/LibraryActions.tsx +32 -7
  348. package/src/client/library/LibraryPanel.tsx +23 -3
  349. package/src/client/library/RestorePlanView.tsx +9 -66
  350. package/src/client/locales.ts +62 -9
  351. package/src/client/lucide-icons.d.ts +1 -0
  352. package/src/client/market/MarketPanel.tsx +13 -2
  353. package/src/client/market/MyConfigsView.tsx +5 -4
  354. package/src/client/market/MyConfigsWizard.tsx +10 -8
  355. package/src/client/market/market-api.test.ts +9 -8
  356. package/src/client/market/market-api.ts +2 -2
  357. package/src/client/market/market-locales.ts +3 -0
  358. package/src/client/market/market-view.test.ts +6 -6
  359. package/src/client/market/market-view.ts +3 -3
  360. package/src/client/market/my-configs-api.ts +2 -2
  361. package/src/client/market/my-configs-view.test.ts +23 -22
  362. package/src/client/market/my-configs-view.ts +8 -8
  363. package/src/client/recovery/IncompleteCopiesSection.tsx +2 -1
  364. package/src/client/recovery/RecoveryPanel.tsx +442 -283
  365. package/src/client/recovery/RollbackCard.tsx +859 -0
  366. package/src/client/recovery/RollbackDiffPane.tsx +69 -0
  367. package/src/client/recovery/RollbackFileChanges.tsx +163 -0
  368. package/src/client/recovery/incident-api.ts +2 -2
  369. package/src/client/recovery/recovery-api.ts +144 -6
  370. package/src/client/recovery/recovery-locales.test.ts +299 -0
  371. package/src/client/recovery/recovery-locales.ts +520 -149
  372. package/src/client/recovery/recovery-panel-layout.test.ts +132 -2
  373. package/src/client/recovery/rollback-enabled.ts +41 -0
  374. package/src/client/recovery/rollback-file-changes.test.ts +114 -0
  375. package/src/client/recovery/session-dialog-mount.test.ts +54 -0
  376. package/src/client/run-store.ts +84 -21
  377. package/src/client/sync/AutosyncCard.tsx +25 -1
  378. package/src/client/sync/ChannelClearConfirmDialog.tsx +6 -3
  379. package/src/client/sync/ChannelConfigDialog.tsx +10 -10
  380. package/src/client/sync/DecryptPasswordCard.tsx +2 -2
  381. package/src/client/sync/SecurityOptionsCard.tsx +27 -17
  382. package/src/client/sync/SyncChannelEntryCard.tsx +14 -2
  383. package/src/client/sync/SyncConfirmView.tsx +46 -8
  384. package/src/client/sync/SyncLogList.tsx +1 -1
  385. package/src/client/sync/SyncPanel.tsx +31 -23
  386. package/src/client/sync/SyncRepositoryPicker.tsx +3 -5
  387. package/src/client/sync/SyncSectionPickerDialog.tsx +11 -2
  388. package/src/client/sync/SyncSettingsView.test.ts +20 -1
  389. package/src/client/sync/UnreadableSnapshotsBanner.tsx +1 -1
  390. package/src/client/sync/WorkDirCard.tsx +112 -0
  391. package/src/client/sync/history-model.test.ts +42 -9
  392. package/src/client/sync/history-model.ts +30 -15
  393. package/src/client/sync/sync-api.test.ts +57 -33
  394. package/src/client/sync/sync-api.ts +80 -6
  395. package/src/client/sync/sync-locales.ts +104 -3
  396. package/src/client/sync/sync-view-v2.test.ts +65 -13
  397. package/src/client/sync/sync-view.test.ts +107 -52
  398. package/src/client/sync/sync-view.ts +124 -41
  399. package/src/core/analyzer.ts +31 -9
  400. package/src/core/backup-plan.test.ts +48 -5
  401. package/src/core/backup-plan.ts +51 -20
  402. package/src/core/backup-verify.ts +24 -23
  403. package/src/core/backup.test.ts +76 -0
  404. package/src/core/backup.ts +105 -29
  405. package/src/core/boot-rescue.ts +4 -3
  406. package/src/core/boot-safety.ts +2 -1
  407. package/src/core/command-rollback.test.ts +536 -0
  408. package/src/core/command-rollback.ts +406 -0
  409. package/src/core/consult-source.ts +7 -6
  410. package/src/core/disk-usage.test.ts +257 -1
  411. package/src/core/disk-usage.ts +134 -14
  412. package/src/core/engine-locale.test.ts +593 -0
  413. package/src/core/engine-locale.ts +175 -0
  414. package/src/core/exporter.ts +3 -3
  415. package/src/core/fork-reconcile.test.ts +279 -0
  416. package/src/core/fork-reconcile.ts +234 -0
  417. package/src/core/journal.ts +6 -5
  418. package/src/core/local-plugin-host.ts +3 -2
  419. package/src/core/local-plugin-pack.ts +11 -6
  420. package/src/core/messages-core.ts +661 -0
  421. package/src/core/messages.ts +125 -17
  422. package/src/core/migration-consult.ts +21 -20
  423. package/src/core/migration-history.ts +19 -5
  424. package/src/core/model-tools.ts +28 -27
  425. package/src/core/phase3-host.ts +21 -5
  426. package/src/core/phase3-p2b-fingerprint.test.ts +22 -0
  427. package/src/core/plugin-cli.ts +18 -19
  428. package/src/core/plugin-data-registry.test.ts +113 -0
  429. package/src/core/plugin-data-registry.ts +261 -0
  430. package/src/core/reconcile.test.ts +117 -0
  431. package/src/core/reconcile.ts +85 -17
  432. package/src/core/recovery-orchestrator.ts +19 -18
  433. package/src/core/reinstall.ts +26 -21
  434. package/src/core/restore.ts +20 -17
  435. package/src/core/rollback-file-diff.test.ts +159 -0
  436. package/src/core/rollback-gate.test.ts +66 -0
  437. package/src/core/rollback-gate.ts +61 -0
  438. package/src/core/rollback-ignore-rules.ts +126 -0
  439. package/src/core/rollback-ledger.test.ts +655 -0
  440. package/src/core/rollback-ledger.ts +1314 -0
  441. package/src/core/rollback-point.test.ts +2853 -0
  442. package/src/core/rollback-point.ts +4340 -0
  443. package/src/core/rollback.ts +5 -3
  444. package/src/core/run-registry.ts +6 -5
  445. package/src/core/session-health.ts +15 -0
  446. package/src/core/session-meta.test.ts +117 -1
  447. package/src/core/session-meta.ts +149 -2
  448. package/src/core/session-title.test.ts +127 -0
  449. package/src/core/session-title.ts +189 -0
  450. package/src/core/startup-barrier.test.ts +69 -0
  451. package/src/core/startup-barrier.ts +27 -0
  452. package/src/core/transaction-coordinator.ts +4 -3
  453. package/src/core/types.ts +37 -1
  454. package/src/core/validator.ts +5 -4
  455. package/src/core/verify-recovery.ts +31 -30
  456. package/src/foreign/bundle.ts +3 -2
  457. package/src/foreign/continue.ts +2 -1
  458. package/src/foreign/crush.ts +2 -1
  459. package/src/foreign/file-budget.test.ts +2 -0
  460. package/src/foreign/gemini.ts +2 -1
  461. package/src/foreign/goose.ts +2 -1
  462. package/src/foreign/kilocode.ts +2 -1
  463. package/src/foreign/kimi.ts +2 -1
  464. package/src/foreign/messages.ts +44 -0
  465. package/src/foreign/mimocode.ts +2 -1
  466. package/src/foreign/openclaw.ts +2 -1
  467. package/src/foreign/opencode.ts +2 -1
  468. package/src/foreign/pi.ts +2 -1
  469. package/src/foreign/qoder.ts +2 -1
  470. package/src/foreign/qwen.ts +2 -1
  471. package/src/foreign/registry.test.ts +1 -1
  472. package/src/foreign/registry.ts +8 -7
  473. package/src/foreign/teleagent.ts +2 -1
  474. package/src/foreign/workbuddy.ts +2 -1
  475. package/src/foreign/zcode.ts +2 -1
  476. package/src/foreign/zed.ts +2 -1
  477. package/src/index.facade.test.ts +340 -1
  478. package/src/index.ts +876 -57
  479. package/src/market/git-file-writer.ts +20 -19
  480. package/src/market/github-repos.test.ts +23 -0
  481. package/src/market/github-repos.ts +37 -19
  482. package/src/market/index-parser.ts +31 -30
  483. package/src/market/messages-market.ts +325 -0
  484. package/src/market/my-repo.ts +32 -29
  485. package/src/market/prepare.ts +18 -15
  486. package/src/market/security.ts +20 -19
  487. package/src/market/types.ts +2 -1
  488. package/src/market/url.ts +2 -1
  489. package/src/migrations/index.ts +6 -5
  490. package/src/migrations/messages-migrations.ts +59 -0
  491. package/src/profiles/dsh-profile-launcher.ts +2 -1
  492. package/src/profiles/dsh-profile-runtime.ts +2 -1
  493. package/src/profiles/messages.ts +31 -0
  494. package/src/routes/backup.ts +18 -2
  495. package/src/routes/import.ts +3 -3
  496. package/src/routes/index.ts +1 -1
  497. package/src/routes/kit.ts +9 -3
  498. package/src/routes/market.ts +1 -1
  499. package/src/routes/messages.ts +106 -0
  500. package/src/routes/prefs.ts +31 -2
  501. package/src/routes/profiles.ts +12 -6
  502. package/src/routes/recovery.test.ts +405 -1
  503. package/src/routes/recovery.ts +477 -94
  504. package/src/routes/snapshots.ts +51 -4
  505. package/src/routes/sync.ts +82 -17
  506. package/src/schema/config.ts +53 -20
  507. package/src/schema/index.ts +7 -5
  508. package/src/schema/manifest-schema.test.ts +4 -4
  509. package/src/schema/manifest.ts +19 -18
  510. package/src/schema/messages.ts +120 -0
  511. package/src/schema/registry.test.ts +28 -7
  512. package/src/schema/section-registry.ts +96 -42
  513. package/src/schema/types.ts +2 -1
  514. package/src/schema/versions.ts +6 -5
  515. package/src/security/encryption.ts +16 -15
  516. package/src/security/integrity.ts +8 -7
  517. package/src/security/messages.ts +87 -0
  518. package/src/security/redaction.test.ts +17 -1
  519. package/src/security/redaction.ts +13 -0
  520. package/src/security/secret-scanner.ts +19 -12
  521. package/src/security/security.test.ts +47 -0
  522. package/src/security/vault.ts +2 -1
  523. package/src/security/zip-security.ts +4 -3
  524. package/src/sync/ancestor.ts +2 -1
  525. package/src/sync/autosync-config.ts +21 -0
  526. package/src/sync/autosync-scheduler.test.ts +63 -7
  527. package/src/sync/autosync-scheduler.ts +118 -78
  528. package/src/sync/backup-files.ts +3 -2
  529. package/src/sync/backup-scheduler.ts +6 -5
  530. package/src/sync/blob-store.ts +2 -1
  531. package/src/sync/git/git-transport.test.ts +170 -8
  532. package/src/sync/git/git-transport.ts +176 -2
  533. package/src/sync/github-auth.ts +10 -9
  534. package/src/sync/layout.ts +13 -12
  535. package/src/sync/messages.ts +153 -0
  536. package/src/sync/review-queue.ts +6 -5
  537. package/src/sync/s3/messages.ts +16 -0
  538. package/src/sync/s3/s3-providers.ts +9 -6
  539. package/src/sync/s3/s3-transport.ts +1 -1
  540. package/src/sync/s3/sigv4.ts +3 -1
  541. package/src/sync/snapshot-crypto.ts +6 -5
  542. package/src/sync/snapshot-json.ts +3 -2
  543. package/src/sync/sync-credentials.test.ts +119 -0
  544. package/src/sync/sync-engine-download-tombstone.test.ts +1 -1
  545. package/src/sync/sync-engine.test.ts +226 -8
  546. package/src/sync/sync-engine.ts +154 -52
  547. package/src/sync/sync-history.ts +7 -6
  548. package/src/sync/sync-selection.test.ts +12 -2
  549. package/src/sync/sync-selection.ts +18 -5
  550. package/src/sync/transport.test.ts +1 -0
  551. package/src/sync/ui-prefs.test.ts +44 -1
  552. package/src/sync/ui-prefs.ts +39 -0
  553. package/src/sync/webdav/webdav-transport.ts +4 -1
  554. package/src/ui/artifact-view.ts +4 -3
  555. package/src/ui/commands.test.ts +1 -0
  556. package/src/ui/commands.ts +11 -1
  557. package/src/ui/diff-view.test.ts +9 -1
  558. package/src/ui/diff-view.ts +22 -0
  559. package/src/ui/disk-usage-view.test.ts +113 -6
  560. package/src/ui/disk-usage-view.ts +63 -7
  561. package/src/ui/errors.ts +4 -3
  562. package/src/ui/export-flow.ts +26 -20
  563. package/src/ui/foreign-view.test.ts +43 -0
  564. package/src/ui/foreign-view.ts +30 -3
  565. package/src/ui/i18n.ts +131 -2
  566. package/src/ui/import-wizard.ts +18 -10
  567. package/src/ui/progress.ts +2 -2
  568. package/src/ui/report.ts +7 -6
  569. package/src/ui/rollback-view.test.ts +836 -0
  570. package/src/ui/rollback-view.ts +1405 -0
  571. package/src/ui/selection-model.test.ts +33 -1
  572. package/src/ui/selection-model.ts +53 -0
  573. package/src/ui/session-inventory-view.test.ts +109 -0
  574. package/src/ui/session-inventory-view.ts +138 -3
  575. package/src/ui/session-issue-labels.test.ts +51 -0
  576. package/src/ui/session-issue-labels.ts +70 -0
  577. package/src/ui/sync-settings-view.test.ts +36 -0
  578. package/src/ui/sync-settings-view.ts +49 -0
  579. package/src/ui/test-helpers.ts +2 -1
  580. package/src/ui/types.ts +10 -4
  581. package/src/utils/atomic-write.ts +6 -5
  582. package/src/utils/bundle-scan.test.ts +2 -2
  583. package/src/utils/bundle-scan.ts +12 -1
  584. package/src/utils/env-lock.ts +83 -49
  585. package/src/utils/json.ts +7 -5
  586. package/src/utils/messages-utils.ts +232 -0
  587. package/src/utils/proxy.test.ts +25 -0
  588. package/src/utils/proxy.ts +19 -5
  589. package/src/utils/recursive-walk.test.ts +43 -0
  590. package/src/utils/recursive-walk.ts +75 -1
  591. package/src/utils/session-log-repair.ts +10 -9
  592. package/src/utils/zip.ts +27 -26
  593. package/lib/core/checkpoint.d.ts +0 -362
  594. package/lib/core/checkpoint.js +0 -1309
  595. package/src/core/checkpoint.test.ts +0 -665
  596. package/src/core/checkpoint.ts +0 -1614
@@ -19,19 +19,34 @@ export const zh = {
19
19
  'section.agentPresets': 'Agent 预设',
20
20
  'section.agentInstructions': '全局指令',
21
21
  'section.workspaces': '工作区',
22
- 'section.pluginFiles': '插件文件',
22
+ 'section.pluginFiles': '其他插件零散文件',
23
23
  'section.credentialsStatus': '凭据状态',
24
24
  'section.secrets': '密钥',
25
25
  'section.sessions': '历史会话',
26
- 'section.self': '插件自身配置',
26
+ 'section.self': '本插件自身配置',
27
+ 'section.pluginData': '其他插件数据',
28
+ 'section.pluginAssets': '其他插件大文件',
27
29
  // 视图切换
28
30
  'view.about': '关于',
31
+ // 关于页「一键复制环境信息」片段(提 issue 用):zh 保留双语标题(维护者可读),en 纯英文
32
+ 'about.snippet.environment': '### 环境 / Environment',
33
+ // 更新内容拉取失败(GitHub API):错误对象里也必须是当前语言
34
+ 'about.releaseNotes.rateLimited': 'GitHub API 速率限制(Rate limit exceeded),请稍后再试或直接在 GitHub 上查看。',
35
+ 'about.releaseNotes.fetchFailed': 'GitHub API 请求失败 ({status} {statusText})',
36
+ 'about.snippet.plugin': '- 插件版本 / Plugin: {version}',
37
+ 'about.snippet.dsh': '- DSH 版本 / DSH: {version}',
38
+ 'about.snippet.platform': '- 平台 / Platform: {platform}',
39
+ 'about.snippet.pluginDir': '- 插件清单目录 / Plugin dir: {dir}',
29
40
  // 公共
30
41
  'common.close': '关闭',
31
42
  'common.cancel': '取消',
43
+ // 标点也属界面文案:英文界面不得出现全角冒号(label:value 形态的分隔符走这个词条)
44
+ 'common.labelSeparator': ':',
32
45
  'common.back': '上一步',
33
46
  'common.next': '下一步',
34
47
  'common.retry': '重试',
48
+ // 落盘失败(sessionStorage 配额满/不可用):状态还在内存里,但刷新即丢 —— 必须说清
49
+ 'common.saveFailed': '浏览器存储写入失败:当前进度仍在本页内存中,刷新会丢失',
35
50
  'common.loading': '加载中…',
36
51
  'common.unknownError': '未知错误',
37
52
  // client-F6:拼接类标点走字典(英文界面不得出现全角括号 / 顿号)
@@ -83,6 +98,9 @@ export const zh = {
83
98
  'overview.quick.sync': '远程同步',
84
99
  'overview.activity.title': '最近活动',
85
100
  'overview.activity.empty': '暂无操作记录(执行备份 / 导入 / 同步后在这里显示)',
101
+ 'overview.activity.unavailable': '活动记录读取失败(这不是「没有记录」)',
102
+ // 首屏 5 个只读请求有失败时如实说清(此前失败被吞成 null,页面仍显示绿色健康 + 空活动)
103
+ 'overview.loadFailed': '有 {count} 项数据读取失败:{message} —— 下面的指标可能不完整',
86
104
  'overview.empty.title': '开始保护你的配置',
87
105
  'overview.empty.body': '创建第一个备份或快照后,这里会展示配置健康状态与最近活动。',
88
106
  'overview.empty.step1': '创建第一份备份',
@@ -143,6 +161,7 @@ export const zh = {
143
161
  'picker.expand': '展开',
144
162
  'picker.collapse': '收起',
145
163
  'picker.partial': '部分',
164
+ 'picker.blankSession': '新会话',
146
165
  'picker.highRisk': '高风险',
147
166
  'picker.highRiskHint': '该分区来自公共仓库、未经官方审核:勾选后会在本机安装插件 / 写入文件 / 注入全局指令。导入前会创建可回滚快照,风险由你确认。',
148
167
  'picker.locked': '捆绑',
@@ -792,6 +811,13 @@ export const zh = {
792
811
  'library.refresh': '刷新',
793
812
  'library.searchPlaceholder': '搜索文件名 / 备注 / 快照 id',
794
813
  'library.sourceFailed': '{count} 个来源读取失败',
814
+ // 读不到 ≠ 没有:快照目录被权限/占位挡住时如实说明(宿主 out.unreadable 透传)
815
+ 'library.snapshotsUnreadable': '有快照目录读不出来(这不是「没有快照」)',
816
+ // 预览后磁盘已变化:绝不执行另一套没确认过的动作,请重新预览
817
+ 'snapshots.planChanged': '环境在预览后发生了变化,恢复已取消 —— 请重新预览确认',
818
+ // 删除快照被 recovery 引用挡住(与自动保留清理的 F3 豁免同源)
819
+ 'library.snapshotReferencedByRecovery': '该快照是事故恢复的回滚点,已拒绝删除(请先处理恢复事项)',
820
+ 'library.snapshotReferenceUnreadable': '读不到恢复引用清单,已保守拒绝删除(请重试)',
795
821
  'library.retry': '重试',
796
822
  'library.emptyFiltered': '没有匹配的产物',
797
823
  'library.delete': '删除',
@@ -808,6 +834,8 @@ export const zh = {
808
834
  'palette.view.about': '关于',
809
835
  'palette.rescue.recovery': '事故恢复',
810
836
  'palette.rescue.mode': '救援模式',
837
+ // S7:回滚点(工作区 + 会话回退)命令标题
838
+ 'palette.rescue.rollback': '回滚点(工作区 + 会话回退)',
811
839
  'import.reason.schemaUnsupported': '包内 schema 版本 v{version} 超出本插件支持范围',
812
840
  'import.reason.missingSections': '备份声明但包内缺失 {count} 个分区:{sections}',
813
841
  'import.reason.sourceNewer': '备份来自更新的 DSH({source} → 本机 {target}):可能有本机不认识的配置',
@@ -933,17 +961,29 @@ export const en: Record<keyof typeof zh, string> = {
933
961
  'section.agentPresets': 'Agent Presets',
934
962
  'section.agentInstructions': 'Agent Instructions',
935
963
  'section.workspaces': 'Workspaces',
936
- 'section.pluginFiles': 'Plugin Files',
964
+ 'section.pluginFiles': "Other Plugins' Loose Files",
937
965
  'section.credentialsStatus': 'Credentials Status',
938
966
  'section.secrets': 'Secrets',
939
967
  'section.sessions': 'Sessions',
940
- 'section.self': 'Plugin Self Config',
968
+ 'section.self': "This Plugin's Own Config",
969
+ 'section.pluginData': "Other Plugins' Data",
970
+ 'section.pluginAssets': "Other Plugins' Large Files",
941
971
  'view.about': 'About',
972
+ 'about.snippet.environment': '### Environment',
973
+ 'about.releaseNotes.rateLimited': 'GitHub API rate limit exceeded — please try again later, or view the release notes directly on GitHub.',
974
+ 'about.releaseNotes.fetchFailed': 'GitHub API request failed ({status} {statusText})',
975
+ 'about.snippet.plugin': '- Plugin version: {version}',
976
+ 'about.snippet.dsh': '- DSH version: {version}',
977
+ 'about.snippet.platform': '- Platform: {platform}',
978
+ 'about.snippet.pluginDir': '- Plugin directory: {dir}',
942
979
  'common.close': 'Close',
943
980
  'common.cancel': 'Cancel',
981
+ 'common.labelSeparator': ': ',
944
982
  'common.back': 'Back',
945
983
  'common.next': 'Next',
946
984
  'common.retry': 'Retry',
985
+ // Persist failure (sessionStorage quota / unavailable): state is in memory but a refresh loses it
986
+ 'common.saveFailed': 'Could not write browser storage: the current progress stays in this page only and is lost on refresh',
947
987
  'common.loading': 'Loading…',
948
988
  'common.unknownError': 'Unknown error',
949
989
  'common.parens': '({text})',
@@ -957,15 +997,15 @@ export const en: Record<keyof typeof zh, string> = {
957
997
  'toast.refreshed': 'Refreshed',
958
998
  // —— Overview(2026-09 UX refactor)——
959
999
  'overview.refresh': 'Refresh',
960
- 'overview.health.ok': 'Configuration looks healthy',
1000
+ 'overview.health.ok': 'All healthy',
961
1001
  'overview.health.noBackup': 'No backups yet — create a backup or snapshot first',
962
1002
  'overview.health.scheduleFailed': 'The last scheduled backup failed — check backup settings',
963
1003
  'overview.health.recovery': 'Unresolved recovery items need attention',
964
1004
  'overview.health.recoveryAction': 'Go to Incident recovery',
965
- 'overview.metric.backups': 'Backup files',
966
- 'overview.metric.snapshots': 'Safety snapshots',
967
- 'overview.metric.schedule': 'Scheduled backup',
968
- 'overview.metric.sync': 'Remote sync',
1005
+ 'overview.metric.backups': 'Backups',
1006
+ 'overview.metric.snapshots': 'Snapshots',
1007
+ 'overview.metric.schedule': 'Auto backup',
1008
+ 'overview.metric.sync': 'Sync',
969
1009
  'overview.state.on': 'On',
970
1010
  'overview.state.off': 'Off',
971
1011
  'overview.meta.lastBackup': 'Last: {time}',
@@ -992,6 +1032,9 @@ export const en: Record<keyof typeof zh, string> = {
992
1032
  'overview.quick.sync': 'Remote sync',
993
1033
  'overview.activity.title': 'Recent activity',
994
1034
  'overview.activity.empty': 'No activity yet (backups / imports / syncs will appear here)',
1035
+ 'overview.activity.unavailable': 'The activity log could not be read (this is not \"no activity\")',
1036
+ // Say it plainly when some of the five read-only requests failed (failures used to be swallowed into null)
1037
+ 'overview.loadFailed': '{count} data request(s) failed: {message} — the metrics below may be incomplete',
995
1038
  'overview.empty.title': 'Start protecting your configuration',
996
1039
  'overview.empty.step1': 'Create a backup',
997
1040
  'overview.empty.step2': 'Export the ZIP',
@@ -1050,6 +1093,7 @@ export const en: Record<keyof typeof zh, string> = {
1050
1093
  'picker.expand': 'Expand',
1051
1094
  'picker.collapse': 'Collapse',
1052
1095
  'picker.partial': 'Partial',
1096
+ 'picker.blankSession': 'New Session',
1053
1097
  'picker.highRisk': 'High risk',
1054
1098
  'picker.highRiskHint': 'This section comes from a public repository without official review: selecting it installs plugins / writes files / injects global instructions on this machine. A rollback snapshot is taken before import, so the risk stays yours to confirm.',
1055
1099
  'picker.locked': 'Bundle',
@@ -1688,6 +1732,13 @@ export const en: Record<keyof typeof zh, string> = {
1688
1732
  'library.refresh': 'Refresh',
1689
1733
  'library.searchPlaceholder': 'Search file name / note / snapshot id',
1690
1734
  'library.sourceFailed': '{count} sources failed to load',
1735
+ // "cannot read" is not "no snapshots": surface the host's out.unreadable fact
1736
+ 'library.snapshotsUnreadable': 'Some snapshot directories could not be read (this is not "no snapshots")',
1737
+ // The environment changed after the preview: never run a different, unconfirmed plan
1738
+ 'snapshots.planChanged': 'The environment changed after the preview, so the restore was cancelled — preview again to confirm',
1739
+ // Deleting a snapshot that recovery still references is refused (same F3 exemption as auto-prune)
1740
+ 'library.snapshotReferencedByRecovery': 'This snapshot is a recovery rollback point — deletion refused (resolve the recovery items first)',
1741
+ 'library.snapshotReferenceUnreadable': 'The recovery reference list could not be read — deletion conservatively refused (please retry)',
1691
1742
  'library.retry': 'Retry',
1692
1743
  'library.emptyFiltered': 'No matching artifacts',
1693
1744
  'library.delete': 'Delete',
@@ -1704,6 +1755,8 @@ export const en: Record<keyof typeof zh, string> = {
1704
1755
  'palette.view.about': 'About',
1705
1756
  'palette.rescue.recovery': 'Incident recovery',
1706
1757
  'palette.rescue.mode': 'Rescue mode',
1758
+ // S7: rollback points (workspace + session rewind) command title
1759
+ 'palette.rescue.rollback': 'Rollback points (workspace + session rewind)',
1707
1760
  'import.reason.schemaUnsupported': 'The bundle uses schema v{version}, beyond what this plugin supports',
1708
1761
  'import.reason.missingSections': 'Declared by the backup but missing from the archive: {count} section(s) — {sections}',
1709
1762
  'import.reason.sourceNewer': 'Backup comes from a newer DSH ({source} → local {target}): it may contain settings this build does not know',
@@ -27,6 +27,7 @@ declare module 'lucide-react/dist/esm/icons/copy.mjs' { const i: LucideIconCompo
27
27
  declare module 'lucide-react/dist/esm/icons/database-backup.mjs' { const i: LucideIconComponent; export default i }
28
28
  declare module 'lucide-react/dist/esm/icons/download.mjs' { const i: LucideIconComponent; export default i }
29
29
  declare module 'lucide-react/dist/esm/icons/eye.mjs' { const i: LucideIconComponent; export default i }
30
+ declare module 'lucide-react/dist/esm/icons/file.mjs' { const i: LucideIconComponent; export default i }
30
31
  declare module 'lucide-react/dist/esm/icons/folder-input.mjs' { const i: LucideIconComponent; export default i }
31
32
  declare module 'lucide-react/dist/esm/icons/hard-drive-download.mjs' { const i: LucideIconComponent; export default i }
32
33
  declare module 'lucide-react/dist/esm/icons/history.mjs' { const i: LucideIconComponent; export default i }
@@ -26,6 +26,7 @@ import type { ConfigManagerApi } from '../api.ts'
26
26
  import type { ImportResult, ItemResolution } from '../../core/types.ts'
27
27
  import type { SectionId } from '../../schema/types.ts'
28
28
  import { Badge, Banner, Button, Card, Empty, SectionTitle, Spinner } from '../common/ui.tsx'
29
+ import { InfoHint } from '../common/InfoHint.tsx'
29
30
  import { Skeleton, SkeletonList } from '../common/Skeleton.tsx'
30
31
  import { Select } from '../common/Select.tsx'
31
32
  import { effectiveImportSelection, type Selection } from '../../ui/selection-model.ts'
@@ -470,7 +471,7 @@ export function MarketPanel({ api, myConfigsApi, importApi, syncApi, t, cmT, ope
470
471
  {/* 列表视图的表头与市场操作卡:进入条目向导页时整块让位(P2 起向导是**页面**,
471
472
  不再在列表之上叠弹窗) */}
472
473
  {!downloadOpen && (<>
473
- <SectionTitle title={t('section.label')} subtitle={t('section.description')} />
474
+ <SectionTitle title={t('section.label')} info={<InfoHint text={t('section.description')} label={t('common.infoHint')} />} />
474
475
 
475
476
  {/* 内置市场操作卡:保留面板标题;移除 URL / 官方徽章 / 名称 / 条目数 / 状态行等文字展示 */}
476
477
  <Card>
@@ -596,7 +597,17 @@ export function MarketPanel({ api, myConfigsApi, importApi, syncApi, t, cmT, ope
596
597
  {/* 条目列表(浏览) */}
597
598
  {!downloadOpen && (
598
599
  <Card>
599
- {state.loadError !== null && <Empty>{t('list.empty')}</Empty>}
600
+ {/* 加载失败必须说清原因并可就地重试:此前把 loadError 渲染成中性空态文案
601
+ (「内置市场尚未加载,请先『拉取最新』」),错误原文被整个丢弃 ——
602
+ 用户只会反复点刷新,永远不知是宿主没就绪、网络不通还是本地 index 读不出来。 */}
603
+ {state.loadError !== null && (
604
+ <>
605
+ <Banner kind="error">{redact(state.loadError)}</Banner>
606
+ <div className={css.actionRow}>
607
+ <Button loading={state.loading} onClick={() => { void loadStatus() }}>{t('common.retry')}</Button>
608
+ </div>
609
+ </>
610
+ )}
600
611
  {state.loadError === null && (<>
601
612
  {/* 筛选控件 2×2 网格(搜索框跨两列 + 4 个 select 两两一行):
602
613
  上一轮全局 .input/.select 的 width:100% 已移除,靠本网格类承担排布,
@@ -35,6 +35,7 @@ import type { MyConfigsApi, MyItemEntry } from './my-configs-api.ts'
35
35
  import type { ListingStatusResponse } from '../../market/my-repo.ts'
36
36
  import type { SyncApi, GithubPollResponse } from '../sync/sync-api.ts'
37
37
  import { Button, Card, SectionTitle } from '../common/ui.tsx'
38
+ import { InfoHint } from '../common/InfoHint.tsx'
38
39
  import { ConfirmDialog } from '../common/ConfirmDialog.tsx'
39
40
  import { toast } from '../common/toast-store.ts'
40
41
  import { redact } from '../../security/redaction.ts'
@@ -125,7 +126,7 @@ export function MyConfigsView({
125
126
  const [listLoading, setListLoading] = useState(false)
126
127
 
127
128
  /* ---------------- 向导(受控:切片来自 runStore;瞬态本地重建)/ 装回本地 / 删除 ---------------- */
128
- const [wizard, setWizard] = useState<MyWizardState>(() => restoreMyWizard(myWizard))
129
+ const [wizard, setWizard] = useState<MyWizardState>(() => restoreMyWizard(myWizard, uiT))
129
130
  /** 最近一次 wizard 全量(commitWizard 读最新值,避免闭包过期) */
130
131
  const wizardRef = useRef<MyWizardState>(wizard)
131
132
  /** 收录/下架任务状态(结果卡轮询 /me/listing 的实时结果) */
@@ -764,7 +765,8 @@ export function MyConfigsView({
764
765
 
765
766
  return (
766
767
  <div className={css.viewBody}>
767
- <SectionTitle title={t('myconfigs.tab.myconfigs')} subtitle={t('myconfigs.login.hint')} />
768
+ {/* 标题只留标题:登录说明紧挨着就在下面的登录卡标题 ⓘ 上,同一屏不再出现两遍 */}
769
+ <SectionTitle title={t('myconfigs.tab.myconfigs')} />
768
770
  {renderLoginCard()}
769
771
  {/* 已登录才允许上传 / 查看列表 / 装回本地 */}
770
772
  {loginView.kind === 'logged-in' && (
@@ -772,12 +774,11 @@ export function MyConfigsView({
772
774
  {/* 一键上传入口:点按钮 → 免责(首次)→ 弹窗向导 */}
773
775
  <Card>
774
776
  <div className={css.headRow}>
775
- <span className={css.groupLabel}>{t('myconfigs.upload.title')}</span>
777
+ <span className={css.groupLabel}>{t('myconfigs.upload.title')} <InfoHint text={t('myconfigs.upload.selectHint')} label={t('common.infoHint')} /></span>
776
778
  {/* 撑开剩余空间,「一键上传」按钮贴右 */}
777
779
  <span className={css.statusSpacer} />
778
780
  <Button variant="primary" onClick={openUpload}>{t('myconfigs.upload.run')}</Button>
779
781
  </div>
780
- <span className={css.hint}>{t('myconfigs.upload.selectHint')}</span>
781
782
  </Card>
782
783
  {renderList()}
783
784
  {/* 弹窗:上传/更新向导(uploadOpen)—— 装回本地已改为页面级向导(见上方提前 return) */}
@@ -72,13 +72,14 @@ export function MyConfigsWizard({
72
72
  closeLabel={t('common.close')}
73
73
  onClose={onClose}
74
74
  closeDisabled={wizard.running || wizard.validating}
75
- trailing={wizard.mode === 'update' ? <Badge kind="info">{t('myconfigs.update.hint')}</Badge> : undefined}
75
+ trailing={wizard.mode === 'update'
76
+ ? <Badge kind="info">{t('myconfigs.update.hint')}</Badge>
77
+ : <InfoHint text={t('myconfigs.upload.selectHint')} label={t('common.infoHint')} />}
76
78
  />
77
79
  <Modal.Body scroll>
78
80
 
79
81
  {/* 步骤 1:选配置包 */}
80
82
  {wizard.step === 'select' && (<>
81
- <span className={css.hint}>{t('myconfigs.upload.selectHint')}</span>
82
83
  <input
83
84
  ref={fileInput}
84
85
  type="file"
@@ -100,7 +101,6 @@ export function MyConfigsWizard({
100
101
  {/* 步骤 2:本地校验(dry-run 零写入;选完 zip 自动执行,通过即自动进表单,
101
102
  本步骤仅短暂展示「校验中」;失败时展示错误 + 重新选择) */}
102
103
  {wizard.step === 'validate' && (<>
103
- <span className={css.hint}>{t('myconfigs.upload.selectHint')}</span>
104
104
  {wizard.fileName !== null && (
105
105
  <div className={css.statRow}>
106
106
  <Badge kind="info">{t('myconfigs.upload.selected', { name: wizard.fileName })}</Badge>
@@ -163,7 +163,12 @@ export function MyConfigsWizard({
163
163
  <input className={css.input} value={wizard.form.categories} onChange={(e) => { onFormField('categories', e.target.value) }} />
164
164
  </Field>
165
165
  {/* F6 发布模式:迁移(全带)/ 分享(自动排除敏感分区 + 强制隐私拦截)—— 复用既有 conflictOptions/radioLabel 单选样式 */}
166
- <Field label={t('myconfigs.upload.mode.title')}>
166
+ <Field
167
+ label={t('myconfigs.upload.mode.title')}
168
+ info={wizard.form.publishMode === 'share'
169
+ ? <InfoHint text={t('myconfigs.upload.mode.shareHint')} label={t('common.infoHint')} />
170
+ : undefined}
171
+ >
167
172
  <div className={css.conflictOptions}>
168
173
  {([
169
174
  ['migrate', t('myconfigs.upload.mode.migrate')],
@@ -181,15 +186,12 @@ export function MyConfigsWizard({
181
186
  </label>
182
187
  ))}
183
188
  </div>
184
- {wizard.form.publishMode === 'share' && (
185
- <span className={css.hint}>{t('myconfigs.upload.mode.shareHint')}</span>
186
- )}
187
189
  </Field>
188
190
  {/* 系统自动字段(id/author/version/updatedAt 徽章,无需填写) */}
189
191
  <span className={css.hint}>{t('myconfigs.upload.form.autoHint')}</span>
190
192
  <div className={css.statRow}>
191
193
  {autoBadges.map((b) => (
192
- <Badge key={b.field} kind="info">{b.label}:{b.autoText}</Badge>
194
+ <Badge key={b.field} kind="info">{b.label}{t('common.labelSeparator')}{b.autoText}</Badge>
193
195
  ))}
194
196
  </div>
195
197
  <div className={css.actionRow}>
@@ -10,6 +10,7 @@ import { fileURLToPath } from 'node:url';
10
10
 
11
11
  import { ConfigManagerApiError } from '../api.ts';
12
12
  import { MARKET_API, MarketApi } from './market-api.ts';
13
+ import { zhUiT } from '../../ui/i18n.ts';
13
14
 
14
15
  interface FetchCall {
15
16
  url: string;
@@ -49,7 +50,7 @@ test('M-01 api.status():GET 到 /market/status,解析已添加市场列表
49
50
  // 经读取函数解除闭包赋值导致的 CFA 窄化
50
51
  const lastCall = (): FetchCall | null => called;
51
52
 
52
- const api = new MarketApi();
53
+ const api = new MarketApi(zhUiT);
53
54
  const result = await api.status();
54
55
  assert.equal(result.configured, true);
55
56
  assert.equal(result.markets.length, 1);
@@ -61,7 +62,7 @@ test('M-01 api.status():GET 到 /market/status,解析已添加市场列表
61
62
  });
62
63
 
63
64
  test('M-02 内置单市场:无 add/remove API(市场绑定内置仓库,不可编辑;见 builtin.ts)', () => {
64
- const api = new MarketApi();
65
+ const api = new MarketApi(zhUiT);
65
66
  assert.equal(typeof (api as { add?: unknown }).add, 'undefined', 'MarketApi 不应再有 add 方法');
66
67
  assert.equal(typeof (api as { remove?: unknown }).remove, 'undefined', 'MarketApi 不应再有 remove 方法');
67
68
  assert.equal('add' in MARKET_API, false, '端点常量不含 /market/add');
@@ -82,7 +83,7 @@ test('M-04 api.refresh():POST /market/refresh,解析 L1 目录条目 + 市
82
83
  calls.push(call);
83
84
  return jsonResponse(200, body);
84
85
  });
85
- const api = new MarketApi();
86
+ const api = new MarketApi(zhUiT);
86
87
  const result = await api.refresh();
87
88
  assert.equal(result.ok, true);
88
89
  assert.equal(result.items.length, 2);
@@ -104,7 +105,7 @@ test('M-05 api.browse():POST /market/browse(不重拉,合并 index + 缓
104
105
  items: [{ id: 'a', name: 'x', cacheState: 'none' }],
105
106
  });
106
107
  });
107
- const api = new MarketApi();
108
+ const api = new MarketApi(zhUiT);
108
109
  const result = await api.browse();
109
110
  assert.equal(result.items.length, 1);
110
111
  assert.equal(calls[0]?.url, MARKET_API.browse);
@@ -129,7 +130,7 @@ test('M-06 api.download():POST /market/download 携带 itemId;内置单市
129
130
  calls.push(call);
130
131
  return jsonResponse(200, body);
131
132
  });
132
- const api = new MarketApi();
133
+ const api = new MarketApi(zhUiT);
133
134
  const result = await api.download('a');
134
135
  assert.equal(result.status, 'valid');
135
136
  assert.equal(result.zipPath, '/tmp/controlled/a.zip');
@@ -160,7 +161,7 @@ test('M-06b api.download():自托管条目(repo 来源)→ 请求体携带
160
161
  calls.push(call);
161
162
  return jsonResponse(200, body);
162
163
  });
163
- const api = new MarketApi();
164
+ const api = new MarketApi(zhUiT);
164
165
  const result = await api.download('a', 'https://github.com/xiaojun/dsh-configs');
165
166
  assert.equal(result.status, 'valid');
166
167
  assert.equal(calls[0]?.url, MARKET_API.download);
@@ -172,7 +173,7 @@ test('M-06b api.download():自托管条目(repo 来源)→ 请求体携带
172
173
 
173
174
  test('M-07 错误映射:4xx 携带 error → ConfigManagerApiError', async () => {
174
175
  installFetchMock(() => jsonResponse(400, { error: 'market index invalid: unknown field' }));
175
- const api = new MarketApi();
176
+ const api = new MarketApi(zhUiT);
176
177
  await assert.rejects(api.browse(), (err: unknown) => {
177
178
  assert.ok(err instanceof ConfigManagerApiError);
178
179
  assert.match(err.message, /market index invalid/);
@@ -182,7 +183,7 @@ test('M-07 错误映射:4xx 携带 error → ConfigManagerApiError', async ()
182
183
 
183
184
  test('M-08 服务未挂载:404(非 JSON 体)→ ConfigManagerApiError 提示插件未加载', async () => {
184
185
  installFetchMock(() => new Response('Not Found', { status: 404 }));
185
- const api = new MarketApi();
186
+ const api = new MarketApi(zhUiT);
186
187
  await assert.rejects(api.status(), (err: unknown) => {
187
188
  assert.ok(err instanceof ConfigManagerApiError);
188
189
  assert.match(err.message, /未挂载/);
@@ -32,7 +32,7 @@ import type {
32
32
  MarketBrowseResponse, MarketDownloadResult, MarketItemDetail, MarketListItem,
33
33
  MarketPreparePayload, MarketPrepareResponse, MarketRefreshResponse, MarketStatusResponse,
34
34
  } from '../../market/types.ts';
35
- import { zhUiT, type UiT } from '../../ui/i18n.ts';
35
+ import type { UiT } from '../../ui/i18n.ts';
36
36
  import { getJson, LONG_REQUEST_TIMEOUT_MS, postJson, type RequestOptions } from '../common/http.ts';
37
37
  import { MARKET_API } from '../common/routes.ts';
38
38
 
@@ -52,7 +52,7 @@ const MARKET_OPTS: RequestOptions = { timeoutMs: LONG_REQUEST_TIMEOUT_MS };
52
52
  /** 配置市场浏览器半数据入口(备份与迁移页第 5 个 tab 的注入业务面) */
53
53
  export class MarketApi {
54
54
  readonly t: UiT
55
- constructor(t: UiT = zhUiT) {
55
+ constructor(t: UiT) {
56
56
  this.t = t
57
57
  }
58
58
 
@@ -213,6 +213,8 @@ export const zh = {
213
213
  'myconfigs.error.loadItems': '已上传列表读取失败',
214
214
  // 公共
215
215
  'common.cancel': '取消',
216
+ // 标点也属界面文案:英文界面不得出现全角冒号(自动字段徽章的 label:value 分隔)
217
+ 'common.labelSeparator': ':',
216
218
  'common.close': '关闭',
217
219
  'common.retry': '重试',
218
220
  'common.loading': '加载中…',
@@ -403,6 +405,7 @@ export const en: Record<keyof typeof zh, string> = {
403
405
  'myconfigs.error.loadStatus': 'Failed to read sign-in status',
404
406
  'myconfigs.error.loadItems': 'Failed to read uploaded items',
405
407
  'common.cancel': 'Cancel',
408
+ 'common.labelSeparator': ': ',
406
409
  'common.close': 'Close',
407
410
  'common.retry': 'Retry',
408
411
  'common.loading': 'Loading…',
@@ -235,8 +235,8 @@ test('market-view: sortMarketItems 稳定性(同值保持原相对顺序)',
235
235
  /* ---------------------------------------------------------------- 客户端专属:供应链警示着色 + 详情聚合 */
236
236
 
237
237
  test('market-view: marketWarningsLines 恒非空且首条为 warn(非官方审核)', () => {
238
- const valid = marketWarningsLines(detail({ status: 'valid' }), 'https://github.com/u/m')
239
- const invalid = marketWarningsLines(detail({ status: 'invalid', errors: ['x'] }), 'https://github.com/u/m')
238
+ const valid = marketWarningsLines(detail({ status: 'valid' }), 'https://github.com/u/m', zhUiT)
239
+ const invalid = marketWarningsLines(detail({ status: 'invalid', errors: ['x'] }), 'https://github.com/u/m', zhUiT)
240
240
  assert.ok(valid.length > 0)
241
241
  assert.equal(valid[0]?.kind, 'warn')
242
242
  assert.equal(invalid[0]?.kind, 'warn')
@@ -246,7 +246,7 @@ test('market-view: marketWarningsLines 恒非空且首条为 warn(非官方审
246
246
  test('market-view: marketWarningsLines 含来源 URL / 作者 / provenance(着色 info)', () => {
247
247
  const lines = marketWarningsLines(
248
248
  detail({ author: 'alice', provenance: { source: 'https://gh.com/alice', note: '自述' } }),
249
- 'https://github.com/u/m',
249
+ 'https://github.com/u/m', zhUiT
250
250
  )
251
251
  const text = lines.map((l) => l.text).join('\n')
252
252
  assert.match(text, /https:\/\/github\.com\/u\/m/)
@@ -256,7 +256,7 @@ test('market-view: marketWarningsLines 含来源 URL / 作者 / provenance(着
256
256
  })
257
257
 
258
258
  test('market-view: marketDetailView valid + 有分区 → canImport 且带警示/空错误', () => {
259
- const v = marketDetailView(detail({ status: 'valid', sections: ['settings'] }), 'https://x', true)
259
+ const v = marketDetailView(detail({ status: 'valid', sections: ['settings'] }), 'https://x', true, zhUiT)
260
260
  assert.equal(v.canImport, true)
261
261
  assert.deepEqual(v.errors, [])
262
262
  assert.ok(v.warnings.length > 0)
@@ -265,7 +265,7 @@ test('market-view: marketDetailView valid + 有分区 → canImport 且带警示
265
265
  })
266
266
 
267
267
  test('market-view: marketDetailView invalid → canImport=false 且 errors 透传、badge error', () => {
268
- const v = marketDetailView(detail({ status: 'invalid', errors: ['zip 越界', 'checksum 不符'] }), 'https://x', false)
268
+ const v = marketDetailView(detail({ status: 'invalid', errors: ['zip 越界', 'checksum 不符'] }), 'https://x', false, zhUiT)
269
269
  assert.equal(v.canImport, false)
270
270
  assert.deepEqual(v.errors, ['zip 越界', 'checksum 不符'])
271
271
  assert.equal(v.badge.statusKind, 'error')
@@ -273,7 +273,7 @@ test('market-view: marketDetailView invalid → canImport=false 且 errors 透
273
273
  })
274
274
 
275
275
  test('market-view: marketDetailView valid 但空分区 → 不可导入(无从导入)', () => {
276
- const v = marketDetailView(detail({ status: 'valid', sections: [] }), 'https://x', true)
276
+ const v = marketDetailView(detail({ status: 'valid', sections: [] }), 'https://x', true, zhUiT)
277
277
  assert.equal(v.canImport, false)
278
278
  })
279
279
 
@@ -27,7 +27,7 @@ export {
27
27
  import type { MarketItemDetail, MarketListItem } from '../../market/types.ts';
28
28
  import type { ImportAnalysis, ImportPlan, PlanItemKind } from '../../core/types.ts';
29
29
  import type { SectionId } from '../../schema/types.ts';
30
- import { zhUiT, type UiT } from '../../ui/i18n.ts';
30
+ import type { UiT } from '../../ui/i18n.ts';
31
31
  import { isOfficialMarket } from '../../market/builtin.ts';
32
32
 
33
33
  /* ---------------------------------------------------------------- 客户端专属:来源徽章 */
@@ -193,7 +193,7 @@ export interface SupplyChainLine {
193
193
  export function marketWarningsLines(
194
194
  detail: MarketItemDetail,
195
195
  url: string,
196
- t: UiT = zhUiT,
196
+ t: UiT,
197
197
  ): SupplyChainLine[] {
198
198
  const raw = marketItemWarnings(
199
199
  detail.provenance !== undefined || detail.author !== undefined ? { name: detail.name, author: detail.author, provenance: detail.provenance } : undefined,
@@ -234,7 +234,7 @@ export function marketDetailView(
234
234
  detail: MarketItemDetail,
235
235
  url: string,
236
236
  showBack: boolean,
237
- t: UiT = zhUiT,
237
+ t: UiT,
238
238
  ): MarketDetailView {
239
239
  const badge = computeItemBadge(detail, t);
240
240
  return {
@@ -24,7 +24,7 @@
24
24
  import type {
25
25
  DeleteResult, ListingStatusResponse, MyItemEntry, MyRepoForm, UploadResult,
26
26
  } from '../../market/my-repo.ts';
27
- import { zhUiT, type UiT } from '../../ui/i18n.ts';
27
+ import type { UiT } from '../../ui/i18n.ts';
28
28
  import { LONG_REQUEST_TIMEOUT_MS, postJson, type RequestOptions } from '../common/http.ts';
29
29
  import { MY_CONFIGS_API } from '../common/routes.ts';
30
30
 
@@ -86,7 +86,7 @@ export interface MyItemsResponse {
86
86
  */
87
87
  export class MyConfigsApi {
88
88
  readonly t: UiT
89
- constructor(t: UiT = zhUiT) {
89
+ constructor(t: UiT) {
90
90
  this.t = t
91
91
  }
92
92