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.
- package/README.md +111 -96
- package/README.zh-CN.md +207 -86
- package/lib/adapters/agent-instructions.js +1 -1
- package/lib/adapters/file-collection.js +1 -1
- package/lib/adapters/index.d.ts +1 -1
- package/lib/adapters/index.js +1 -1
- package/lib/adapters/link-report.d.ts +1 -0
- package/lib/adapters/link-report.js +27 -3
- package/lib/adapters/messages.d.ts +18 -0
- package/lib/adapters/messages.js +50 -0
- package/lib/adapters/plugin-files.js +3 -2
- package/lib/adapters/plugins.js +4 -3
- package/lib/adapters/prompts.d.ts +1 -0
- package/lib/adapters/prompts.js +7 -1
- package/lib/adapters/self.d.ts +7 -1
- package/lib/adapters/self.js +1 -1
- package/lib/adapters/sessions.d.ts +1 -0
- package/lib/adapters/sessions.js +4 -2
- package/lib/adapters/ui.d.ts +2 -2
- package/lib/adapters/ui.js +25 -25
- package/lib/adapters/workspaces.d.ts +1 -0
- package/lib/adapters/workspaces.js +7 -3
- package/lib/cli/actions.d.ts +9 -1
- package/lib/cli/actions.js +5 -2
- package/lib/cli/help.js +23 -10
- package/lib/cli/index.d.ts +23 -0
- package/lib/cli/index.js +90 -32
- package/lib/cli/sessions-inspect.js +3 -1
- package/lib/cli/sessions-repair.js +25 -6
- package/lib/cli/web/page.d.ts +12 -0
- package/lib/cli/web/page.js +21 -12
- package/lib/cli/web/routes.js +2 -2
- package/lib/cli/web/server.js +4 -4
- package/lib/client.d.ts +1349 -490
- package/lib/client.js +43047 -36738
- package/lib/core/backup-plan.js +30 -17
- package/lib/core/backup-verify.js +24 -23
- package/lib/core/backup.d.ts +5 -0
- package/lib/core/backup.js +51 -25
- package/lib/core/boot-rescue.js +4 -3
- package/lib/core/boot-safety.js +2 -1
- package/lib/core/command-rollback.d.ts +178 -0
- package/lib/core/command-rollback.js +289 -0
- package/lib/core/consult-source.js +7 -6
- package/lib/core/disk-usage.d.ts +74 -10
- package/lib/core/disk-usage.js +67 -4
- package/lib/core/engine-locale.d.ts +87 -0
- package/lib/core/engine-locale.js +125 -0
- package/lib/core/exporter.js +3 -3
- package/lib/core/fork-reconcile.d.ts +128 -0
- package/lib/core/fork-reconcile.js +150 -0
- package/lib/core/journal.js +6 -5
- package/lib/core/local-plugin-host.js +3 -2
- package/lib/core/local-plugin-pack.js +11 -6
- package/lib/core/messages-core.d.ts +292 -0
- package/lib/core/messages-core.js +615 -0
- package/lib/core/messages.d.ts +60 -2
- package/lib/core/messages.js +116 -13
- package/lib/core/migration-consult.js +21 -20
- package/lib/core/migration-history.js +19 -5
- package/lib/core/model-tools.d.ts +0 -22
- package/lib/core/model-tools.js +50 -27
- package/lib/core/phase3-host.js +30 -5
- package/lib/core/plugin-cli.js +18 -19
- package/lib/core/reconcile.d.ts +2 -14
- package/lib/core/reconcile.js +87 -17
- package/lib/core/recovery-orchestrator.js +19 -18
- package/lib/core/reinstall.d.ts +4 -0
- package/lib/core/reinstall.js +26 -21
- package/lib/core/restore.js +20 -17
- package/lib/core/rollback-ignore-rules.d.ts +31 -0
- package/lib/core/rollback-ignore-rules.js +140 -0
- package/lib/core/rollback-point.d.ts +1208 -0
- package/lib/core/rollback-point.js +2993 -0
- package/lib/core/run-registry.js +6 -5
- package/lib/core/session-health.d.ts +15 -0
- package/lib/core/session-meta.d.ts +42 -2
- package/lib/core/session-meta.js +140 -1
- package/lib/core/session-title.d.ts +28 -0
- package/lib/core/session-title.js +185 -0
- package/lib/core/startup-barrier.d.ts +24 -0
- package/lib/core/startup-barrier.js +22 -0
- package/lib/core/transaction-coordinator.js +4 -3
- package/lib/core/types.d.ts +18 -1
- package/lib/core/validator.js +5 -4
- package/lib/core/verify-recovery.js +31 -30
- package/lib/foreign/bundle.js +3 -2
- package/lib/foreign/continue.js +2 -1
- package/lib/foreign/crush.js +2 -1
- package/lib/foreign/gemini.js +2 -1
- package/lib/foreign/goose.js +2 -1
- package/lib/foreign/kilocode.js +2 -1
- package/lib/foreign/kimi.js +2 -1
- package/lib/foreign/messages.d.ts +15 -0
- package/lib/foreign/messages.js +40 -0
- package/lib/foreign/mimocode.js +2 -1
- package/lib/foreign/openclaw.js +2 -1
- package/lib/foreign/opencode.js +2 -1
- package/lib/foreign/pi.js +2 -1
- package/lib/foreign/qoder.js +2 -1
- package/lib/foreign/qwen.js +2 -1
- package/lib/foreign/registry.js +7 -6
- package/lib/foreign/teleagent.js +2 -1
- package/lib/foreign/workbuddy.js +2 -1
- package/lib/foreign/zcode.js +2 -1
- package/lib/foreign/zed.js +2 -1
- package/lib/index.d.ts +223 -7
- package/lib/index.js +729 -54
- package/lib/market/git-file-writer.js +20 -19
- package/lib/market/github-repos.js +35 -19
- package/lib/market/index-parser.js +31 -30
- package/lib/market/messages-market.d.ts +138 -0
- package/lib/market/messages-market.js +305 -0
- package/lib/market/my-repo.d.ts +2 -2
- package/lib/market/my-repo.js +32 -29
- package/lib/market/prepare.js +18 -15
- package/lib/market/security.js +20 -19
- package/lib/market/types.js +2 -1
- package/lib/market/url.js +2 -1
- package/lib/migrations/index.js +6 -5
- package/lib/migrations/messages-migrations.d.ts +32 -0
- package/lib/migrations/messages-migrations.js +58 -0
- package/lib/profiles/dsh-profile-launcher.js +2 -1
- package/lib/profiles/dsh-profile-runtime.js +2 -1
- package/lib/profiles/messages.d.ts +7 -0
- package/lib/profiles/messages.js +27 -0
- package/lib/routes/backup.js +18 -2
- package/lib/routes/import.js +3 -3
- package/lib/routes/index.d.ts +1 -1
- package/lib/routes/kit.d.ts +3 -2
- package/lib/routes/kit.js +6 -1
- package/lib/routes/market.js +1 -1
- package/lib/routes/messages.d.ts +42 -0
- package/lib/routes/messages.js +100 -0
- package/lib/routes/profiles.js +12 -6
- package/lib/routes/recovery.js +378 -114
- package/lib/routes/snapshots.js +51 -4
- package/lib/routes/sync.js +68 -16
- package/lib/schema/config.d.ts +11 -1
- package/lib/schema/config.js +52 -20
- package/lib/schema/index.d.ts +8 -6
- package/lib/schema/index.js +8 -6
- package/lib/schema/manifest.js +19 -18
- package/lib/schema/messages.d.ts +47 -0
- package/lib/schema/messages.js +110 -0
- package/lib/schema/section-registry.d.ts +41 -14
- package/lib/schema/section-registry.js +35 -29
- package/lib/schema/versions.js +6 -5
- package/lib/security/encryption.js +16 -15
- package/lib/security/integrity.js +8 -7
- package/lib/security/messages.d.ts +30 -0
- package/lib/security/messages.js +77 -0
- package/lib/security/redaction.js +12 -0
- package/lib/security/secret-scanner.js +16 -13
- package/lib/security/vault.js +2 -1
- package/lib/security/zip-security.js +4 -3
- package/lib/sync/ancestor.js +2 -1
- package/lib/sync/autosync-config.d.ts +11 -0
- package/lib/sync/autosync-config.js +12 -0
- package/lib/sync/autosync-scheduler.d.ts +11 -1
- package/lib/sync/autosync-scheduler.js +115 -76
- package/lib/sync/backup-files.js +3 -2
- package/lib/sync/backup-scheduler.js +6 -5
- package/lib/sync/blob-store.js +2 -1
- package/lib/sync/git/git-transport.d.ts +55 -0
- package/lib/sync/git/git-transport.js +152 -2
- package/lib/sync/github-auth.js +10 -9
- package/lib/sync/layout.js +13 -12
- package/lib/sync/messages.d.ts +63 -0
- package/lib/sync/messages.js +149 -0
- package/lib/sync/review-queue.js +6 -5
- package/lib/sync/s3/messages.d.ts +7 -0
- package/lib/sync/s3/messages.js +16 -0
- package/lib/sync/s3/s3-providers.d.ts +4 -1
- package/lib/sync/s3/s3-providers.js +5 -5
- package/lib/sync/s3/s3-transport.js +1 -1
- package/lib/sync/s3/sigv4.js +2 -1
- package/lib/sync/snapshot-crypto.js +6 -5
- package/lib/sync/snapshot-json.js +3 -2
- package/lib/sync/sync-engine.d.ts +37 -15
- package/lib/sync/sync-engine.js +67 -37
- package/lib/sync/sync-history.js +7 -6
- package/lib/sync/sync-selection.d.ts +15 -4
- package/lib/sync/sync-selection.js +17 -5
- package/lib/sync/webdav/webdav-transport.d.ts +1 -0
- package/lib/sync/webdav/webdav-transport.js +4 -1
- package/lib/ui/artifact-view.js +4 -3
- package/lib/ui/commands.d.ts +1 -1
- package/lib/ui/commands.js +10 -0
- package/lib/ui/disk-usage-view.d.ts +33 -4
- package/lib/ui/disk-usage-view.js +29 -1
- package/lib/ui/errors.d.ts +1 -1
- package/lib/ui/errors.js +4 -3
- package/lib/ui/export-flow.js +24 -20
- package/lib/ui/foreign-view.d.ts +5 -1
- package/lib/ui/foreign-view.js +26 -2
- package/lib/ui/i18n.d.ts +65 -0
- package/lib/ui/i18n.js +114 -0
- package/lib/ui/import-wizard.d.ts +7 -0
- package/lib/ui/import-wizard.js +13 -10
- package/lib/ui/progress.d.ts +2 -2
- package/lib/ui/progress.js +1 -2
- package/lib/ui/report.d.ts +5 -5
- package/lib/ui/report.js +6 -6
- package/lib/ui/rollback-view.d.ts +756 -0
- package/lib/ui/rollback-view.js +724 -0
- package/lib/ui/selection-model.d.ts +41 -0
- package/lib/ui/selection-model.js +30 -0
- package/lib/ui/session-inventory-view.d.ts +97 -3
- package/lib/ui/session-inventory-view.js +76 -2
- package/lib/ui/session-issue-labels.d.ts +43 -0
- package/lib/ui/session-issue-labels.js +48 -0
- package/lib/ui/sync-settings-view.d.ts +33 -0
- package/lib/ui/sync-settings-view.js +40 -0
- package/lib/ui/types.d.ts +8 -3
- package/lib/ui/types.js +1 -1
- package/lib/utils/atomic-write.js +6 -5
- package/lib/utils/bundle-scan.d.ts +11 -1
- package/lib/utils/bundle-scan.js +12 -1
- package/lib/utils/env-lock.d.ts +10 -0
- package/lib/utils/env-lock.js +73 -46
- package/lib/utils/json.js +6 -5
- package/lib/utils/messages-utils.d.ts +96 -0
- package/lib/utils/messages-utils.js +216 -0
- package/lib/utils/proxy.js +18 -5
- package/lib/utils/recursive-walk.d.ts +22 -0
- package/lib/utils/recursive-walk.js +75 -1
- package/lib/utils/session-log-repair.js +10 -9
- package/lib/utils/zip.js +27 -26
- package/package.json +12 -2
- package/src/adapters/agent-instructions.ts +1 -1
- package/src/adapters/file-collection.test.ts +1 -0
- package/src/adapters/file-collection.ts +1 -1
- package/src/adapters/files.test.ts +27 -0
- package/src/adapters/index.ts +1 -1
- package/src/adapters/link-report.test.ts +22 -2
- package/src/adapters/link-report.ts +29 -4
- package/src/adapters/messages.ts +54 -0
- package/src/adapters/plugin-files.ts +3 -2
- package/src/adapters/plugins.ts +4 -3
- package/src/adapters/prompts.ts +7 -1
- package/src/adapters/self.test.ts +26 -0
- package/src/adapters/self.ts +8 -2
- package/src/adapters/sessions.ts +4 -2
- package/src/adapters/settings.test.ts +38 -1
- package/src/adapters/ui.test.ts +2 -2
- package/src/adapters/ui.ts +27 -26
- package/src/adapters/workspaces.ts +7 -3
- package/src/cli/actions.test.ts +28 -0
- package/src/cli/actions.ts +11 -2
- package/src/cli/help.ts +23 -10
- package/src/cli/index-guards.test.ts +193 -0
- package/src/cli/index.ts +106 -31
- package/src/cli/sessions-inspect.test.ts +15 -1
- package/src/cli/sessions-inspect.ts +3 -1
- package/src/cli/sessions-repair.test.ts +84 -0
- package/src/cli/sessions-repair.ts +33 -7
- package/src/cli/web/console-route-parity.test.ts +115 -0
- package/src/cli/web/page.ts +23 -12
- package/src/cli/web/routes.ts +2 -1
- package/src/cli/web/server.ts +4 -4
- package/src/cli/web/web.test.ts +2 -2
- package/src/client/ConfigManagerSection.tsx +30 -2
- package/src/client/about/AboutPanel.tsx +2 -2
- package/src/client/about/PluginUpdateDialog.tsx +1 -1
- package/src/client/about/ReleaseNotesDialog.tsx +2 -2
- package/src/client/about/about-view.test.ts +13 -3
- package/src/client/about/about-view.ts +10 -6
- package/src/client/about/release-notes-view.test.ts +14 -4
- package/src/client/about/release-notes-view.ts +4 -2
- package/src/client/api.ts +18 -6
- package/src/client/chat/ChatEntryView.tsx +391 -0
- package/src/client/chat/RollbackDiffTab.tsx +61 -0
- package/src/client/chat/RollbackFileIcon.tsx +96 -0
- package/src/client/chat/RollbackReviewDialog.tsx +591 -0
- package/src/client/chat/chat-entry-view.test.ts +1174 -0
- package/src/client/chat/chat-entry-view.ts +758 -0
- package/src/client/chat/chat-locales.ts +152 -0
- package/src/client/chat/chat-node-registration.ts +64 -0
- package/src/client/chat/chat-point-window.ts +173 -0
- package/src/client/chat/chat-slots.ts +107 -0
- package/src/client/chat/rollback-diff-tab.test.ts +105 -0
- package/src/client/chat/rollback-diff-tab.ts +164 -0
- package/src/client/chat/rollback-entry-view.test.ts +1469 -0
- package/src/client/chat/rollback-entry-view.ts +941 -0
- package/src/client/chat/sidebar-slots.ts +37 -0
- package/src/client/common/ConfirmDialog.tsx +7 -3
- package/src/client/common/ContentPicker.tsx +48 -10
- package/src/client/common/DiffTable.tsx +97 -0
- package/src/client/common/ErrorBanner.tsx +4 -4
- package/src/client/common/Icon.tsx +2 -0
- package/src/client/common/Modal.tsx +8 -1
- package/src/client/common/ProgressBar.tsx +8 -2
- package/src/client/common/ReportView.tsx +4 -4
- package/src/client/common/RunsCenter.tsx +1 -0
- package/src/client/common/client-route-parity.test.ts +78 -0
- package/src/client/common/info-hint-guard.test.ts +46 -13
- package/src/client/common/picker-lazy-units.test.ts +42 -0
- package/src/client/common/plan-text-redaction.test.ts +17 -6
- package/src/client/common/progress-view-edge.test.ts +8 -7
- package/src/client/common/progress-view.test.ts +9 -9
- package/src/client/common/progress-view.ts +2 -2
- package/src/client/common/routes.ts +28 -0
- package/src/client/common/ui.tsx +73 -10
- package/src/client/config-manager.module.css +996 -21
- package/src/client/css-scale-guard.test.ts +30 -0
- package/src/client/environment/EnvironmentPanel.tsx +11 -4
- package/src/client/environment/maintenance/DiskUsageCard.tsx +23 -2
- package/src/client/export/ExportView.tsx +13 -8
- package/src/client/history/HistoryPanel.tsx +4 -3
- package/src/client/history/history-api.ts +2 -2
- package/src/client/history/history-locales.ts +5 -1
- package/src/client/home/HomePanel.tsx +29 -8
- package/src/client/import/ForeignImportView.tsx +4 -5
- package/src/client/import/ImportWizardView.tsx +5 -3
- package/src/client/import/import-wizard-split.test.ts +3 -1
- package/src/client/import/import-wizard-steps.tsx +9 -9
- package/src/client/index.ts +186 -3
- package/src/client/library/LibraryActions.tsx +32 -7
- package/src/client/library/LibraryPanel.tsx +23 -3
- package/src/client/library/RestorePlanView.tsx +9 -66
- package/src/client/locales.ts +54 -5
- package/src/client/lucide-icons.d.ts +1 -0
- package/src/client/market/MarketPanel.tsx +13 -2
- package/src/client/market/MyConfigsView.tsx +5 -4
- package/src/client/market/MyConfigsWizard.tsx +10 -8
- package/src/client/market/market-api.test.ts +9 -8
- package/src/client/market/market-api.ts +2 -2
- package/src/client/market/market-locales.ts +3 -0
- package/src/client/market/market-view.test.ts +6 -6
- package/src/client/market/market-view.ts +3 -3
- package/src/client/market/my-configs-api.ts +2 -2
- package/src/client/market/my-configs-view.test.ts +23 -22
- package/src/client/market/my-configs-view.ts +8 -8
- package/src/client/recovery/IncompleteCopiesSection.tsx +2 -1
- package/src/client/recovery/RecoveryPanel.tsx +442 -283
- package/src/client/recovery/RollbackCard.tsx +665 -0
- package/src/client/recovery/RollbackDiffPane.tsx +58 -0
- package/src/client/recovery/RollbackFileChanges.tsx +163 -0
- package/src/client/recovery/incident-api.ts +2 -2
- package/src/client/recovery/recovery-api.ts +116 -6
- package/src/client/recovery/recovery-locales.test.ts +299 -0
- package/src/client/recovery/recovery-locales.ts +488 -149
- package/src/client/recovery/recovery-panel-layout.test.ts +132 -2
- package/src/client/recovery/rollback-file-changes.test.ts +73 -0
- package/src/client/recovery/session-dialog-mount.test.ts +54 -0
- package/src/client/run-store.ts +84 -21
- package/src/client/sync/AutosyncCard.tsx +25 -1
- package/src/client/sync/ChannelClearConfirmDialog.tsx +6 -3
- package/src/client/sync/ChannelConfigDialog.tsx +10 -10
- package/src/client/sync/DecryptPasswordCard.tsx +2 -2
- package/src/client/sync/SecurityOptionsCard.tsx +27 -17
- package/src/client/sync/SyncChannelEntryCard.tsx +14 -2
- package/src/client/sync/SyncConfirmView.tsx +46 -8
- package/src/client/sync/SyncLogList.tsx +1 -1
- package/src/client/sync/SyncPanel.tsx +31 -23
- package/src/client/sync/SyncRepositoryPicker.tsx +3 -5
- package/src/client/sync/SyncSectionPickerDialog.tsx +11 -2
- package/src/client/sync/SyncSettingsView.test.ts +20 -1
- package/src/client/sync/UnreadableSnapshotsBanner.tsx +1 -1
- package/src/client/sync/WorkDirCard.tsx +112 -0
- package/src/client/sync/history-model.test.ts +42 -9
- package/src/client/sync/history-model.ts +30 -15
- package/src/client/sync/sync-api.test.ts +57 -33
- package/src/client/sync/sync-api.ts +80 -6
- package/src/client/sync/sync-locales.ts +104 -3
- package/src/client/sync/sync-view-v2.test.ts +65 -13
- package/src/client/sync/sync-view.test.ts +107 -52
- package/src/client/sync/sync-view.ts +124 -41
- package/src/core/backup-plan.test.ts +28 -0
- package/src/core/backup-plan.ts +29 -17
- package/src/core/backup-verify.ts +24 -23
- package/src/core/backup.test.ts +76 -0
- package/src/core/backup.ts +55 -25
- package/src/core/boot-rescue.ts +4 -3
- package/src/core/boot-safety.ts +2 -1
- package/src/core/command-rollback.test.ts +536 -0
- package/src/core/command-rollback.ts +402 -0
- package/src/core/consult-source.ts +7 -6
- package/src/core/disk-usage.test.ts +257 -1
- package/src/core/disk-usage.ts +134 -14
- package/src/core/engine-locale.test.ts +593 -0
- package/src/core/engine-locale.ts +175 -0
- package/src/core/exporter.ts +3 -3
- package/src/core/fork-reconcile.test.ts +279 -0
- package/src/core/fork-reconcile.ts +234 -0
- package/src/core/journal.ts +6 -5
- package/src/core/local-plugin-host.ts +3 -2
- package/src/core/local-plugin-pack.ts +11 -6
- package/src/core/messages-core.ts +657 -0
- package/src/core/messages.ts +123 -17
- package/src/core/migration-consult.ts +21 -20
- package/src/core/migration-history.ts +19 -5
- package/src/core/model-tools.ts +28 -27
- package/src/core/phase3-host.ts +21 -5
- package/src/core/phase3-p2b-fingerprint.test.ts +22 -0
- package/src/core/plugin-cli.ts +18 -19
- package/src/core/reconcile.test.ts +117 -0
- package/src/core/reconcile.ts +85 -17
- package/src/core/recovery-orchestrator.ts +19 -18
- package/src/core/reinstall.ts +26 -21
- package/src/core/restore.ts +20 -17
- package/src/core/rollback-file-diff.test.ts +159 -0
- package/src/core/rollback-ignore-rules.ts +126 -0
- package/src/core/rollback-point.test.ts +2603 -0
- package/src/core/rollback-point.ts +3755 -0
- package/src/core/run-registry.ts +6 -5
- package/src/core/session-health.ts +15 -0
- package/src/core/session-meta.test.ts +117 -1
- package/src/core/session-meta.ts +149 -2
- package/src/core/session-title.test.ts +127 -0
- package/src/core/session-title.ts +189 -0
- package/src/core/startup-barrier.test.ts +69 -0
- package/src/core/startup-barrier.ts +27 -0
- package/src/core/transaction-coordinator.ts +4 -3
- package/src/core/types.ts +18 -1
- package/src/core/validator.ts +5 -4
- package/src/core/verify-recovery.ts +31 -30
- package/src/foreign/bundle.ts +3 -2
- package/src/foreign/continue.ts +2 -1
- package/src/foreign/crush.ts +2 -1
- package/src/foreign/file-budget.test.ts +2 -0
- package/src/foreign/gemini.ts +2 -1
- package/src/foreign/goose.ts +2 -1
- package/src/foreign/kilocode.ts +2 -1
- package/src/foreign/kimi.ts +2 -1
- package/src/foreign/messages.ts +44 -0
- package/src/foreign/mimocode.ts +2 -1
- package/src/foreign/openclaw.ts +2 -1
- package/src/foreign/opencode.ts +2 -1
- package/src/foreign/pi.ts +2 -1
- package/src/foreign/qoder.ts +2 -1
- package/src/foreign/qwen.ts +2 -1
- package/src/foreign/registry.ts +7 -6
- package/src/foreign/teleagent.ts +2 -1
- package/src/foreign/workbuddy.ts +2 -1
- package/src/foreign/zcode.ts +2 -1
- package/src/foreign/zed.ts +2 -1
- package/src/index.facade.test.ts +340 -1
- package/src/index.ts +813 -57
- package/src/market/git-file-writer.ts +20 -19
- package/src/market/github-repos.test.ts +23 -0
- package/src/market/github-repos.ts +37 -19
- package/src/market/index-parser.ts +31 -30
- package/src/market/messages-market.ts +325 -0
- package/src/market/my-repo.ts +32 -29
- package/src/market/prepare.ts +18 -15
- package/src/market/security.ts +20 -19
- package/src/market/types.ts +2 -1
- package/src/market/url.ts +2 -1
- package/src/migrations/index.ts +6 -5
- package/src/migrations/messages-migrations.ts +59 -0
- package/src/profiles/dsh-profile-launcher.ts +2 -1
- package/src/profiles/dsh-profile-runtime.ts +2 -1
- package/src/profiles/messages.ts +31 -0
- package/src/routes/backup.ts +18 -2
- package/src/routes/import.ts +3 -3
- package/src/routes/index.ts +1 -1
- package/src/routes/kit.ts +9 -3
- package/src/routes/market.ts +1 -1
- package/src/routes/messages.ts +104 -0
- package/src/routes/profiles.ts +12 -6
- package/src/routes/recovery.test.ts +405 -1
- package/src/routes/recovery.ts +377 -109
- package/src/routes/snapshots.ts +51 -4
- package/src/routes/sync.ts +67 -16
- package/src/schema/config.ts +53 -20
- package/src/schema/index.ts +7 -5
- package/src/schema/manifest.ts +19 -18
- package/src/schema/messages.ts +120 -0
- package/src/schema/registry.test.ts +19 -5
- package/src/schema/section-registry.ts +64 -39
- package/src/schema/versions.ts +6 -5
- package/src/security/encryption.ts +16 -15
- package/src/security/integrity.ts +8 -7
- package/src/security/messages.ts +87 -0
- package/src/security/redaction.test.ts +17 -1
- package/src/security/redaction.ts +13 -0
- package/src/security/secret-scanner.ts +19 -12
- package/src/security/security.test.ts +47 -0
- package/src/security/vault.ts +2 -1
- package/src/security/zip-security.ts +4 -3
- package/src/sync/ancestor.ts +2 -1
- package/src/sync/autosync-config.ts +21 -0
- package/src/sync/autosync-scheduler.test.ts +63 -7
- package/src/sync/autosync-scheduler.ts +118 -78
- package/src/sync/backup-files.ts +3 -2
- package/src/sync/backup-scheduler.ts +6 -5
- package/src/sync/blob-store.ts +2 -1
- package/src/sync/git/git-transport.test.ts +170 -8
- package/src/sync/git/git-transport.ts +176 -2
- package/src/sync/github-auth.ts +10 -9
- package/src/sync/layout.ts +13 -12
- package/src/sync/messages.ts +153 -0
- package/src/sync/review-queue.ts +6 -5
- package/src/sync/s3/messages.ts +16 -0
- package/src/sync/s3/s3-providers.ts +9 -6
- package/src/sync/s3/s3-transport.ts +1 -1
- package/src/sync/s3/sigv4.ts +3 -1
- package/src/sync/snapshot-crypto.ts +6 -5
- package/src/sync/snapshot-json.ts +3 -2
- package/src/sync/sync-engine-download-tombstone.test.ts +1 -1
- package/src/sync/sync-engine.test.ts +226 -8
- package/src/sync/sync-engine.ts +103 -41
- package/src/sync/sync-history.ts +7 -6
- package/src/sync/sync-selection.test.ts +12 -2
- package/src/sync/sync-selection.ts +18 -5
- package/src/sync/webdav/webdav-transport.ts +4 -1
- package/src/ui/artifact-view.ts +4 -3
- package/src/ui/commands.test.ts +1 -0
- package/src/ui/commands.ts +11 -1
- package/src/ui/disk-usage-view.test.ts +113 -6
- package/src/ui/disk-usage-view.ts +63 -7
- package/src/ui/errors.ts +4 -3
- package/src/ui/export-flow.ts +24 -20
- package/src/ui/foreign-view.test.ts +43 -0
- package/src/ui/foreign-view.ts +30 -3
- package/src/ui/i18n.ts +125 -0
- package/src/ui/import-wizard.ts +18 -10
- package/src/ui/progress.ts +2 -2
- package/src/ui/report.ts +7 -6
- package/src/ui/rollback-view.test.ts +819 -0
- package/src/ui/rollback-view.ts +1339 -0
- package/src/ui/selection-model.test.ts +33 -1
- package/src/ui/selection-model.ts +53 -0
- package/src/ui/session-inventory-view.test.ts +109 -0
- package/src/ui/session-inventory-view.ts +138 -3
- package/src/ui/session-issue-labels.test.ts +51 -0
- package/src/ui/session-issue-labels.ts +70 -0
- package/src/ui/sync-settings-view.test.ts +36 -0
- package/src/ui/sync-settings-view.ts +49 -0
- package/src/ui/types.ts +10 -4
- package/src/utils/atomic-write.ts +6 -5
- package/src/utils/bundle-scan.test.ts +2 -2
- package/src/utils/bundle-scan.ts +12 -1
- package/src/utils/env-lock.ts +83 -49
- package/src/utils/json.ts +7 -5
- package/src/utils/messages-utils.ts +232 -0
- package/src/utils/proxy.test.ts +25 -0
- package/src/utils/proxy.ts +19 -5
- package/src/utils/recursive-walk.test.ts +43 -0
- package/src/utils/recursive-walk.ts +75 -1
- package/src/utils/session-log-repair.ts +10 -9
- package/src/utils/zip.ts +27 -26
- package/lib/core/checkpoint.d.ts +0 -362
- package/lib/core/checkpoint.js +0 -1309
- package/src/core/checkpoint.test.ts +0 -665
- package/src/core/checkpoint.ts +0 -1614
|
@@ -20,19 +20,31 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import fs from 'node:fs/promises';
|
|
22
22
|
import path from 'node:path';
|
|
23
|
+
import { AUTO_SYNC_OPT_IN_SECTION_IDS, OPT_IN_SYNC_SECTION_IDS } from '../schema/section-registry.js';
|
|
23
24
|
import { channelMap } from './sync-config.js';
|
|
24
25
|
import { parseJsonSafe, stringifyJsonSafe } from '../utils/json.js';
|
|
25
26
|
import { atomicWriteFile } from '../utils/atomic-write.js';
|
|
26
27
|
export const SYNC_SELECTION_FILE = 'sync-selection.json';
|
|
27
28
|
export const SYNC_SELECTION_SCHEMA_VERSION = 2;
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
+
* 显式勾选才允许进入同步通道的「可选分区」。
|
|
30
31
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* **单一事实源 = 分区注册表**(\`SectionMeta.syncOptIn !== 'off'\`)。本文件此前手写
|
|
33
|
+
* \`['sessions']\`,与 \`section-registry.ts\` 的同名字段是**两份字面量、零护栏**
|
|
34
|
+
* (改一处漏一处不会报错)—— issue #78 收敛为派生视图,并在测试里钉住。
|
|
35
|
+
*
|
|
36
|
+
* 当前 = mcp('auto',命令 / 路径可能机器相关)+ sessions('manual',内容敏感 + 设备相关)。
|
|
37
|
+
* 凭据 / 密钥分区不在此列(结构性拒绝,永不进同步)。
|
|
38
|
+
*/
|
|
39
|
+
export const OPT_IN_SYNC_SECTIONS = OPT_IN_SYNC_SECTION_IDS;
|
|
40
|
+
/**
|
|
41
|
+
* 「可选分区」里**允许参与自动同步**的子集(当前 = mcp)。
|
|
42
|
+
*
|
|
43
|
+
* 手动与自动的差别只在这里:sessions 是内容隐私 / 设备相关,自动同步绝不带
|
|
44
|
+
* (「会话绝不悄悄下行」从注释变成可测断言);mcp 只是命令 / 路径可能与目标机不同,
|
|
45
|
+
* 用户显式勾选后手动与自动都带。
|
|
34
46
|
*/
|
|
35
|
-
export const
|
|
47
|
+
export const AUTO_SYNC_OPT_IN_SECTIONS = AUTO_SYNC_OPT_IN_SECTION_IDS;
|
|
36
48
|
/** sessions 分区默认同步「最新 N 个会话」(用户可在弹窗里改;0 = 不带)。 */
|
|
37
49
|
export const DEFAULT_SYNC_SESSIONS_LIMIT = 5;
|
|
38
50
|
/** sessionsLimit 归一化:非整数 / 缺失 / 负数 → 默认值;超大 → 上限钳制。 */
|
|
@@ -28,6 +28,9 @@
|
|
|
28
28
|
import { requestOnce } from '../../utils/proxy.js';
|
|
29
29
|
import { zhMsg } from '../../core/messages.js';
|
|
30
30
|
import { composeMsg } from '../s3/messages.js';
|
|
31
|
+
// t6:「英文界面零中文」——注册同步域追加目录(this.o.msg 缺省 = zhMsg,其查找链会查注册目录;
|
|
32
|
+
// sync.webdav.blobHashInvalid 这类新键必须能解析,绝不露裸键名)。
|
|
33
|
+
import '../messages.js';
|
|
31
34
|
import { deserializeSnapshot, serializeSnapshot } from '../snapshot-json.js';
|
|
32
35
|
import { BLOB_SECTIONS, gcBlobs, isBlobRefsSection, isFilesSectionLike, referencedBlobHashes, refsToSection, sectionToBlobRefs } from '../blob-store.js';
|
|
33
36
|
import { classifyHttpStatus, classifyNetworkErrorText, computeSnapshotMeta, DEFAULT_SYNC_TIMEOUT_MS, isEncryptedSections, sectionsEqual, SyncTransportError, withSyncRetry, } from '../transport.js';
|
|
@@ -464,7 +467,7 @@ export class WebDavTransport {
|
|
|
464
467
|
return {
|
|
465
468
|
put: async (hash, bytes) => {
|
|
466
469
|
if (!BLOB_HASH_RE.test(hash)) {
|
|
467
|
-
throw new WebDavTransportError(
|
|
470
|
+
throw new WebDavTransportError(this.o.msg('sync.webdav.blobHashInvalid', { hash }));
|
|
468
471
|
}
|
|
469
472
|
if (index[hash] !== undefined)
|
|
470
473
|
return; // 内容未变 → 一个字都不传(P1-4 的核心收益)
|
package/lib/ui/artifact-view.js
CHANGED
|
@@ -84,7 +84,8 @@ function snapshotRow(s, t) {
|
|
|
84
84
|
{ label: t('library.detail.plugins'), value: group(s.beforePluginCount) },
|
|
85
85
|
{ label: t('library.detail.pinned'), value: s.pinned === true ? t('library.value.yes') : t('library.value.no') },
|
|
86
86
|
],
|
|
87
|
-
|
|
87
|
+
// 检索词也属界面文案(按当前语言的用户输入匹配;字面量中文会让英文界面命中中文词)
|
|
88
|
+
searchText: [s.id, 'snapshot', t('library.kind.snapshot')].join(' ').toLowerCase(),
|
|
88
89
|
};
|
|
89
90
|
}
|
|
90
91
|
function backupFileRow(f, t) {
|
|
@@ -148,7 +149,7 @@ function remoteSnapshotRow(r, input, t) {
|
|
|
148
149
|
{ label: t('library.detail.platform'), value: r.platform },
|
|
149
150
|
{ label: t('library.detail.dsh'), value: r.dshVersion },
|
|
150
151
|
],
|
|
151
|
-
searchText: [r.id, r.platform, 'remote', '
|
|
152
|
+
searchText: [r.id, r.platform, 'remote', t('library.kind.remote')].join(' ').toLowerCase(),
|
|
152
153
|
};
|
|
153
154
|
}
|
|
154
155
|
function marketRow(m, t) {
|
|
@@ -175,7 +176,7 @@ function marketRow(m, t) {
|
|
|
175
176
|
...(m.version === undefined || m.version === '' ? [] : [{ label: t('library.detail.version'), value: `v${m.version}` }]),
|
|
176
177
|
...(m.updatedAt === undefined ? [] : [{ label: t('library.detail.updated'), value: '', iso: m.updatedAt }]),
|
|
177
178
|
],
|
|
178
|
-
searchText: [m.id, m.name, m.author ?? '', 'market', '
|
|
179
|
+
searchText: [m.id, m.name, m.author ?? '', 'market', t('library.kind.market')].join(' ').toLowerCase(),
|
|
179
180
|
};
|
|
180
181
|
}
|
|
181
182
|
/* ------------------------------------------------------------ 落地文件名 */
|
package/lib/ui/commands.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type CommandGroup = 'navigate' | 'library' | 'action' | 'view' | 'rescue'
|
|
|
16
16
|
/** 命令面板的分组渲染顺序。 */
|
|
17
17
|
export declare const COMMAND_GROUP_ORDER: readonly CommandGroup[];
|
|
18
18
|
/** 命令文案键:必须是 `src/client/locales.ts` 里存在的键(由壳层的 t() 编译校验)。 */
|
|
19
|
-
export type PaletteTitleKey = 'nav.home' | 'library.title' | 'nav.sync' | 'environment.title' | 'nav.market' | 'task.title.publish' | 'nav.export' | 'nav.import' | 'environment.tab.maintenance' | 'foreign.source.title' | 'task.title.runs' | 'task.title.history' | 'task.title.about' | 'palette.rescue.recovery' | 'palette.rescue.mode' | 'library.source.all' | 'library.kind.snapshot' | 'library.kind.backupFile' | 'library.kind.remote' | 'library.kind.market';
|
|
19
|
+
export type PaletteTitleKey = 'nav.home' | 'library.title' | 'nav.sync' | 'environment.title' | 'nav.market' | 'task.title.publish' | 'nav.export' | 'nav.import' | 'environment.tab.maintenance' | 'foreign.source.title' | 'task.title.runs' | 'task.title.history' | 'task.title.about' | 'palette.rescue.recovery' | 'palette.rescue.mode' | 'palette.rescue.rollback' | 'library.source.all' | 'library.kind.snapshot' | 'library.kind.backupFile' | 'library.kind.remote' | 'library.kind.market';
|
|
20
20
|
/** 可用性上下文:由壳层从 runStore 现算(不要在注册表里读 store)。 */
|
|
21
21
|
export interface CommandContext {
|
|
22
22
|
/** 是否有未解决的恢复事项 */
|
package/lib/ui/commands.js
CHANGED
|
@@ -134,6 +134,16 @@ export const COMMANDS = [
|
|
|
134
134
|
titleKey: 'palette.rescue.mode',
|
|
135
135
|
keywords: ['rescue', 'mode', 'profile', 'bundles', '救援', '救援模式', '逃生'],
|
|
136
136
|
},
|
|
137
|
+
{
|
|
138
|
+
// S7:工作区 + 会话回滚(每个回合结束自动留点;会话回退 = fork 子会话)—— 与事故恢复同一子视图,
|
|
139
|
+
// 键盘可达(卡片本身在环境页维护与诊断里,⌘K 直达同一落点)。
|
|
140
|
+
// 中文关键词数量刻意保持 4 个:i18n 守卫的白名单锚定 src/ui/commands.ts 的命中数(53),
|
|
141
|
+
// 增删中文词会让白名单计数漂移(新增豁免只能走 captain)。
|
|
142
|
+
id: 'rollback.open',
|
|
143
|
+
group: 'rescue',
|
|
144
|
+
titleKey: 'palette.rescue.rollback',
|
|
145
|
+
keywords: ['rollback', 'rewind', 'workspace', 'session', 'fork', '回滚', '回退', '工作区', '会话'],
|
|
146
|
+
},
|
|
137
147
|
];
|
|
138
148
|
/** 一条命令在当前查询下的匹配分档;越小越靠前。-1 = 不匹配。 */
|
|
139
149
|
function matchScore(item, title, q) {
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
* ① 读不到的子区**绝不显示 0 字节**,而是标 `unreadable`(未统计),否则用户会以为盘是空的;
|
|
9
9
|
* ② 只有 `policy === 'regenerable'` 的子区进「可立即清理」清单,且**不显示保留期**
|
|
10
10
|
* (它们本来就是随时可清,给一个「7 天后自动清理」的说明会误导);
|
|
11
|
-
* ③ 定时备份(豁免前缀)不计入导出产物的「可回收」数字 ——
|
|
11
|
+
* ③ 定时备份(豁免前缀)不计入导出产物的「可回收」数字 —— 与宿主回收口径逐条一致;
|
|
12
|
+
* ④ 遗留数据(core 的 `report.legacy`:插件已不再读取的旧目录)**单列**,既不计入合计、也不进任何清理候选;
|
|
13
|
+
* 标签走字典、相对路径只作「在哪儿」展示(**绝不**把 id / 路径当文案渲染)。
|
|
12
14
|
*/
|
|
13
|
-
import type {
|
|
15
|
+
import type { DiskUsageReport, DiskUsageScanArea } from '../core/disk-usage.ts';
|
|
14
16
|
import type { UiT } from './i18n.ts';
|
|
15
17
|
/** 展示所需的最小注入面 */
|
|
16
18
|
export interface DiskUsageViewDeps {
|
|
@@ -18,9 +20,9 @@ export interface DiskUsageViewDeps {
|
|
|
18
20
|
/** 字节格式化(复用 `src/ui/report.ts` 的 formatBytes,保持全仓同口径) */
|
|
19
21
|
formatBytes: (n: number) => string;
|
|
20
22
|
}
|
|
21
|
-
/**
|
|
23
|
+
/** 子区展示行(id 域含附加子区:`rollback-points` 等只报告区也要成行) */
|
|
22
24
|
export interface DiskUsageRow {
|
|
23
|
-
id:
|
|
25
|
+
id: DiskUsageScanArea;
|
|
24
26
|
/** 子区名(已翻译) */
|
|
25
27
|
label: string;
|
|
26
28
|
/** 一句话说明(已翻译) */
|
|
@@ -39,6 +41,28 @@ export interface DiskUsageRow {
|
|
|
39
41
|
/** 是否属于「可立即清理」区(regenerable) */
|
|
40
42
|
reclaimable: boolean;
|
|
41
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* 遗留数据展示行(`report.legacy`)。
|
|
46
|
+
*
|
|
47
|
+
* 与 `DiskUsageRow` 分开:遗留目录**不计入**上方子区合计(core 刻意分列),且插件已不再读取它们 ——
|
|
48
|
+
* 界面必须能把「能解释来源的占用」与「遗留占用」分开说,不能让用户以为合计里已经算过。
|
|
49
|
+
*/
|
|
50
|
+
export interface DiskUsageLegacyRow {
|
|
51
|
+
/** core 的稳定 id(`LEGACY_DATA_DIRS`)——**只作 React key / 去重**,绝不直接当文案渲染 */
|
|
52
|
+
id: string;
|
|
53
|
+
/** 相对 dataDir 的路径(如 `checkpoints`):这是「在哪儿」,不是机器码文案 */
|
|
54
|
+
relPath: string;
|
|
55
|
+
/** 已翻译的标签(走字典,不渲染 id) */
|
|
56
|
+
label: string;
|
|
57
|
+
/** 体积文本(未统计时为空串) */
|
|
58
|
+
size: string;
|
|
59
|
+
/** 文件数文本(未统计时为空串) */
|
|
60
|
+
files: string;
|
|
61
|
+
/** 读不到/不存在/被非目录占住 → 界面显示「未统计」而不是 0 字节 */
|
|
62
|
+
unreadable: boolean;
|
|
63
|
+
/** 恒为 `protected`:只报告,绝不提供自动清理 */
|
|
64
|
+
policy: 'protected';
|
|
65
|
+
}
|
|
42
66
|
/** 可立即清理的动作(供界面按 _可用性_ 决定按钮 disabled —— 组件不再自行判断) */
|
|
43
67
|
export interface DiskUsageCleanAction {
|
|
44
68
|
id: 'tmp-market' | 'expired-exports';
|
|
@@ -60,6 +84,11 @@ export interface DiskUsageViewModel {
|
|
|
60
84
|
anyUnreadable: boolean;
|
|
61
85
|
};
|
|
62
86
|
rows: DiskUsageRow[];
|
|
87
|
+
/**
|
|
88
|
+
* 遗留数据行(插件已不再读取、也不代删;**不计入** summary.total)。
|
|
89
|
+
* 恒为数组(无遗留目录时为空),组件不需要判空。
|
|
90
|
+
*/
|
|
91
|
+
legacy: DiskUsageLegacyRow[];
|
|
63
92
|
clean: {
|
|
64
93
|
/** 可立即清理区当前合计 */
|
|
65
94
|
reclaimable: string;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* 子区 → 字典键(标签 / 说明在字典里;本模块只挑键,不内嵌文案)。
|
|
3
|
+
*
|
|
4
|
+
* 键域 = `DiskUsageScanArea`(**含**只报告、不清理的附加子区,如 `rollback-points`):
|
|
5
|
+
* core 的 `DiskUsageArea` 刻意把附加子区排除在外 —— 它描述的是「**展示层已登记文案**的清单」,
|
|
6
|
+
* 而登记文案正是本文件(`AREA_KEYS` 是穷尽 Record,少一个 id 就编译不过)。
|
|
7
|
+
* 因此这里用更宽的 `DiskUsageScanArea`:新增附加子区时,core 加统计、本文件加文案,两边都必须动。
|
|
8
|
+
*/
|
|
2
9
|
const AREA_KEYS = {
|
|
3
10
|
exports: { label: 'diskUsage.area.exports', desc: 'diskUsage.area.exportsDesc' },
|
|
4
11
|
snapshots: { label: 'diskUsage.area.snapshots', desc: 'diskUsage.area.snapshotsDesc' },
|
|
@@ -12,6 +19,8 @@ const AREA_KEYS = {
|
|
|
12
19
|
transactions: { label: 'diskUsage.area.transactions', desc: 'diskUsage.area.transactionsDesc' },
|
|
13
20
|
locks: { label: 'diskUsage.area.locks', desc: 'diskUsage.area.locksDesc' },
|
|
14
21
|
vault: { label: 'diskUsage.area.vault', desc: 'diskUsage.area.vaultDesc' },
|
|
22
|
+
// 只报告、**不提供清理**的附加子区(policy 恒 protected):回滚点库
|
|
23
|
+
'rollback-points': { label: 'diskUsage.area.rollbackPoints', desc: 'diskUsage.area.rollbackPointsDesc' },
|
|
15
24
|
};
|
|
16
25
|
/** 保留期 → 人类可读(7 天 / 24 小时;非整档按小时/分钟回落) */
|
|
17
26
|
export function formatRetention(ms, t) {
|
|
@@ -75,6 +84,24 @@ export function diskUsageViewModel(report, deps) {
|
|
|
75
84
|
reclaimable: entry.policy === 'regenerable',
|
|
76
85
|
});
|
|
77
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* 遗留数据行:core 只报告(`policy` 恒 protected、**不计入**合计),界面如实分列。
|
|
89
|
+
* 标签走字典,**绝不**把 id / relPath 当标签渲染(relPath 只作「在哪儿」的路径展示)。
|
|
90
|
+
*/
|
|
91
|
+
const legacyRows = [];
|
|
92
|
+
for (const entry of report.legacy ?? []) {
|
|
93
|
+
if (entry.unreadable)
|
|
94
|
+
anyUnreadable = true;
|
|
95
|
+
legacyRows.push({
|
|
96
|
+
id: entry.id,
|
|
97
|
+
relPath: entry.relPath,
|
|
98
|
+
label: t('diskUsage.legacy.label'),
|
|
99
|
+
size: entry.unreadable ? '' : formatBytes(entry.sizeBytes),
|
|
100
|
+
files: entry.unreadable ? '' : t('diskUsage.files', { count: String(entry.fileCount) }),
|
|
101
|
+
unreadable: entry.unreadable,
|
|
102
|
+
policy: 'protected',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
78
105
|
const actions = [
|
|
79
106
|
{
|
|
80
107
|
id: 'tmp-market',
|
|
@@ -99,6 +126,7 @@ export function diskUsageViewModel(report, deps) {
|
|
|
99
126
|
anyUnreadable,
|
|
100
127
|
},
|
|
101
128
|
rows,
|
|
129
|
+
legacy: legacyRows,
|
|
102
130
|
clean: {
|
|
103
131
|
reclaimable: formatBytes(reclaimableBytes),
|
|
104
132
|
expired: formatBytes(expiredBytesTotal),
|
package/lib/ui/errors.d.ts
CHANGED
|
@@ -16,4 +16,4 @@ export declare function toActionableError(err: unknown, opts?: {
|
|
|
16
16
|
t?: UiT;
|
|
17
17
|
}): ActionableError;
|
|
18
18
|
/** 格式化为用户可读的多行文本(Reason / Suggested action) */
|
|
19
|
-
export declare function formatActionableError(e: ActionableError, t
|
|
19
|
+
export declare function formatActionableError(e: ActionableError, t: UiT): string;
|
package/lib/ui/errors.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - 文案经 UiT 注入(zh 源 / en 镜像,见 i18n.ts)。
|
|
8
8
|
*/
|
|
9
9
|
import { redact } from '../security/redaction.js';
|
|
10
|
-
import {
|
|
10
|
+
import { liveUiT } from './i18n.js';
|
|
11
11
|
function buildErrorRules(t) {
|
|
12
12
|
return [
|
|
13
13
|
{
|
|
@@ -56,7 +56,8 @@ function buildErrorRules(t) {
|
|
|
56
56
|
}
|
|
57
57
|
/** 将任意错误转换为可操作错误(消息已脱敏,不泄漏 Secret) */
|
|
58
58
|
export function toActionableError(err, opts) {
|
|
59
|
-
|
|
59
|
+
// 缺省用**活**翻译器:未注入路径也要随语言切换(zhUiT 是加载期快照)
|
|
60
|
+
const t = opts?.t ?? liveUiT;
|
|
60
61
|
const raw = err instanceof Error ? err.message : String(err ?? t('commonUnknownError'));
|
|
61
62
|
const message = redact(raw);
|
|
62
63
|
const rule = buildErrorRules(t).find((r) => r.match(message));
|
|
@@ -69,7 +70,7 @@ export function toActionableError(err, opts) {
|
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
/** 格式化为用户可读的多行文本(Reason / Suggested action) */
|
|
72
|
-
export function formatActionableError(e, t
|
|
73
|
+
export function formatActionableError(e, t) {
|
|
73
74
|
const lines = [e.title];
|
|
74
75
|
lines.push(`${t('error.reason')}: ${e.reason}`);
|
|
75
76
|
if (e.suggestedAction)
|
package/lib/ui/export-flow.js
CHANGED
|
@@ -2,7 +2,7 @@ import { SECTION_IDS, sectionMeta } from '../schema/section-registry.js';
|
|
|
2
2
|
import { EXPORT_GROUPS, isQuickRecommended, } from './types.js';
|
|
3
3
|
import { EXPORT_STAGES, ProgressTracker } from './progress.js';
|
|
4
4
|
import { renderExportReport } from './report.js';
|
|
5
|
-
import {
|
|
5
|
+
import { liveUiT } from './i18n.js';
|
|
6
6
|
/**
|
|
7
7
|
* 自定义导出文件名的归一化(P0-④ 体验优化):无需用户手动输入 `.zip`。
|
|
8
8
|
* - trim 首尾空白;空串 → ''(宿主自动命名);
|
|
@@ -29,26 +29,28 @@ export function failedSectionsFromResponse(requested, returned) {
|
|
|
29
29
|
return requested.filter((s) => !got.has(s));
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* 目录条目描述的**字典键**(报告文本 / 日志 / 勾选目录用,非分区显示名)——
|
|
33
|
+
* 文案本身在 `ui/i18n.ts`(zh 源 / en 镜像),这里只留键:静态目录混着中文字面量时,
|
|
34
|
+
* 英文界面会把中文原样透出(且这些字符串原先只存在于本文件,无第二份副本)。
|
|
33
35
|
*
|
|
34
36
|
* 键类型 `Exclude<SectionId, 'secrets'>`:secrets 无 ZIP 载荷、不进导出目录,
|
|
35
37
|
* 因此除它以外的分区**全部**必须有描述 —— 漏一个即编译失败(与注册表同一穷举纪律)。
|
|
36
38
|
*/
|
|
37
|
-
const
|
|
38
|
-
settings: '
|
|
39
|
-
providers: '
|
|
40
|
-
plugins: '
|
|
41
|
-
pluginFiles: '
|
|
42
|
-
self: '
|
|
43
|
-
mcp: '
|
|
44
|
-
prompts: '
|
|
45
|
-
skills: '
|
|
46
|
-
agentPresets: '
|
|
47
|
-
agentInstructions: '
|
|
48
|
-
workspaces: '
|
|
49
|
-
ui: '
|
|
50
|
-
credentialsStatus: '
|
|
51
|
-
sessions: '
|
|
39
|
+
const CATEGORY_DESCRIPTION_KEY = {
|
|
40
|
+
settings: 'export.category.settings',
|
|
41
|
+
providers: 'export.category.providers',
|
|
42
|
+
plugins: 'export.category.plugins',
|
|
43
|
+
pluginFiles: 'export.category.pluginFiles',
|
|
44
|
+
self: 'export.category.self',
|
|
45
|
+
mcp: 'export.category.mcp',
|
|
46
|
+
prompts: 'export.category.prompts',
|
|
47
|
+
skills: 'export.category.skills',
|
|
48
|
+
agentPresets: 'export.category.agentPresets',
|
|
49
|
+
agentInstructions: 'export.category.agentInstructions',
|
|
50
|
+
workspaces: 'export.category.workspaces',
|
|
51
|
+
ui: 'export.category.ui',
|
|
52
|
+
credentialsStatus: 'export.category.credentialsStatus',
|
|
53
|
+
sessions: 'export.category.sessions',
|
|
52
54
|
};
|
|
53
55
|
/** 需在 UI 标注安全提示、但绝不显示值的分区(凭据状态只有 configured 标记) */
|
|
54
56
|
const SENSITIVE_SECTIONS = new Set(['credentialsStatus']);
|
|
@@ -78,7 +80,7 @@ function buildDefaultCategories() {
|
|
|
78
80
|
categories.push({
|
|
79
81
|
id,
|
|
80
82
|
label: meta.displayName,
|
|
81
|
-
|
|
83
|
+
descriptionKey: CATEGORY_DESCRIPTION_KEY[id],
|
|
82
84
|
defaultIncluded: meta.defaultIncluded,
|
|
83
85
|
portability: meta.portability,
|
|
84
86
|
group: meta.group,
|
|
@@ -99,7 +101,8 @@ export class ExportFlow {
|
|
|
99
101
|
this.port = opts.port;
|
|
100
102
|
this.categories = opts.categories ?? DEFAULT_CATEGORIES;
|
|
101
103
|
this.onProgress = opts.onProgress;
|
|
102
|
-
|
|
104
|
+
// 缺省用**活**翻译器(随 DSH 语言变化):构造期快照会在切到英文后恒为中文。
|
|
105
|
+
this.t = opts.t ?? liveUiT;
|
|
103
106
|
}
|
|
104
107
|
/** Quick Export 推荐分区(defaultIncluded 且非 deviceSpecific) */
|
|
105
108
|
quickSelection() {
|
|
@@ -110,7 +113,8 @@ export class ExportFlow {
|
|
|
110
113
|
return EXPORT_GROUPS.map((g) => ({
|
|
111
114
|
group: g.id,
|
|
112
115
|
label: g.label,
|
|
113
|
-
|
|
116
|
+
// 说明文案按当前语言取词(键住在 EXPORT_GROUPS;此处才解析)
|
|
117
|
+
...(g.noteKey !== undefined ? { note: this.t(g.noteKey) } : {}),
|
|
114
118
|
categories: this.categories.filter((c) => c.group === g.id),
|
|
115
119
|
}));
|
|
116
120
|
}
|
package/lib/ui/foreign-view.d.ts
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* ① 检测结果 → 可渲染的来源行(显示名 / 状态徽章语义 / 命中路径 / 未迁移码);
|
|
10
10
|
* ② 摘要 → 计数徽章与分区清单;
|
|
11
11
|
* ③ **机器码 → 字典键**的唯一映射(界面据此渲染人话);
|
|
12
|
-
* ④ **三类已知有损**的展示行(F-5
|
|
12
|
+
* ④ **三类已知有损**的展示行(F-5:只让它们可见,不改任何引擎语义);
|
|
13
|
+
* ⑤ **展示顺序**(命中优先 + 显示名升序 —— 用户 2026-10-12 要求的「默认按名称排序」)。
|
|
13
14
|
*
|
|
14
15
|
* 三条纪律(都有单测钉住):
|
|
15
16
|
* ① **禁止渲染裸机器码**:每个 skip 码必须经 SKIP_KEY 映射到字典键;映射表是
|
|
@@ -121,6 +122,9 @@ export declare function foreignPathsText(row: ForeignSourceRow, t: UiT): string;
|
|
|
121
122
|
*
|
|
122
123
|
* `?projectDir=` 的项目级作用域如实透传(`projectScoped`)—— 界面把它显示出来,
|
|
123
124
|
* 否则用户会以为「本机没装 Cursor」而实际上是「项目级配置没被扫」。
|
|
125
|
+
*
|
|
126
|
+
* 行顺序由 compareForeignSourceRows 决定(命中优先 + 显示名升序),**只排新数组**:
|
|
127
|
+
* 宿主回传的 `response.sources` 一个元素都不动。
|
|
124
128
|
*/
|
|
125
129
|
export declare function foreignSourcesViewModel(response: ForeignSourcesResponse | null, t: UiT): ForeignSourcesViewModel | null;
|
|
126
130
|
/**
|
package/lib/ui/foreign-view.js
CHANGED
|
@@ -135,7 +135,7 @@ export function foreignSourceRow(source, t) {
|
|
|
135
135
|
const known = knownId !== null;
|
|
136
136
|
const label = knownId !== null
|
|
137
137
|
? t(SOURCE_LABEL_KEY[knownId])
|
|
138
|
-
: t('foreign.source.
|
|
138
|
+
: t('foreign.source.unknownWithId', { id: source.id });
|
|
139
139
|
const skips = (source.skipped ?? []).map((s) => foreignSkipLine(s, t));
|
|
140
140
|
const paths = [...source.paths];
|
|
141
141
|
const badge = !source.found ? 'info' : skips.length > 0 ? 'warn' : 'ok';
|
|
@@ -158,16 +158,40 @@ export function foreignPathsText(row, t) {
|
|
|
158
158
|
return t('foreign.pathsNone');
|
|
159
159
|
return t('foreign.paths', { paths: row.paths.join(' · ') });
|
|
160
160
|
}
|
|
161
|
+
/* ------------------------------------------------------------------ 展示顺序 */
|
|
162
|
+
/**
|
|
163
|
+
* 显示名排序器:大小写不敏感(`base`)、数字按数值(`Foo 2` 在 `Foo 10` 之前)。
|
|
164
|
+
* 词典序按**运行环境的默认语言**解析 —— 用户看到的就是他母语的字母/拼音序;
|
|
165
|
+
* 同名的两条保持宿主回传的相对顺序(`Array#sort` 稳定)。
|
|
166
|
+
*/
|
|
167
|
+
const ROW_LABEL_COLLATOR = new Intl.Collator(undefined, { sensitivity: 'base', numeric: true });
|
|
168
|
+
/**
|
|
169
|
+
* 两条来源行的展示顺序(**界面唯一权威**,两处判据只有这一份):
|
|
170
|
+
* ① **命中的在前**(`found` 降序)—— 装了却没排在最上面,用户得先读完一屏「未检测到」;
|
|
171
|
+
* ② 同组内按**显示名**升序。
|
|
172
|
+
*
|
|
173
|
+
* 为什么按显示名而不是 id:列表上用户读到的是 label(`Google Antigravity`),
|
|
174
|
+
* 按 id 排会把它顶到 A 开头,与眼睛看到的字母序不符(`copilot` → 「GitHub Copilot CLI」同理)。
|
|
175
|
+
* 这条规则对「全未命中」自然退化为**纯名称序**,也就是用户要的「默认按名称排序」。
|
|
176
|
+
*/
|
|
177
|
+
function compareForeignSourceRows(a, b) {
|
|
178
|
+
if (a.found !== b.found)
|
|
179
|
+
return a.found ? -1 : 1;
|
|
180
|
+
return ROW_LABEL_COLLATOR.compare(a.label, b.label);
|
|
181
|
+
}
|
|
161
182
|
/**
|
|
162
183
|
* 响应 → 整表展示模型(组件只摆放)。
|
|
163
184
|
*
|
|
164
185
|
* `?projectDir=` 的项目级作用域如实透传(`projectScoped`)—— 界面把它显示出来,
|
|
165
186
|
* 否则用户会以为「本机没装 Cursor」而实际上是「项目级配置没被扫」。
|
|
187
|
+
*
|
|
188
|
+
* 行顺序由 compareForeignSourceRows 决定(命中优先 + 显示名升序),**只排新数组**:
|
|
189
|
+
* 宿主回传的 `response.sources` 一个元素都不动。
|
|
166
190
|
*/
|
|
167
191
|
export function foreignSourcesViewModel(response, t) {
|
|
168
192
|
if (response === null)
|
|
169
193
|
return null;
|
|
170
|
-
const rows = response.sources.map((s) => foreignSourceRow(s, t));
|
|
194
|
+
const rows = response.sources.map((s) => foreignSourceRow(s, t)).sort(compareForeignSourceRows);
|
|
171
195
|
return {
|
|
172
196
|
rows,
|
|
173
197
|
anyFound: rows.some((r) => r.found),
|
package/lib/ui/i18n.d.ts
CHANGED
|
@@ -183,6 +183,7 @@ export declare const uiZh: {
|
|
|
183
183
|
readonly 'sync.neverSyncedShort': '从未同步';
|
|
184
184
|
readonly 'sync.pushFailed': '推送失败';
|
|
185
185
|
readonly 'sync.pushOk': '推送成功(快照 {id})';
|
|
186
|
+
readonly 'sync.conflictUnresolved': '冲突项 {id} 必须先选择解决方式(保留当前 / 使用导入)';
|
|
186
187
|
readonly 'sync.pushPreviewHeadline': '将推送 {total} 个分区({changed} 个有变化)';
|
|
187
188
|
readonly 'sync.pushPreviewHint': '以上为只读预览,不会写入远端。确认后点击「推送」才真正上传。';
|
|
188
189
|
readonly 'sync.pushPreviewEncrypted': '加密快照:载荷将整体加密,各分区相对基线的变化不可比对。';
|
|
@@ -382,6 +383,11 @@ export declare const uiZh: {
|
|
|
382
383
|
readonly 'diskUsage.col.policy': '回收策略';
|
|
383
384
|
readonly 'diskUsage.clean.reclaimableLabel': '可立即释放';
|
|
384
385
|
readonly 'diskUsage.clean.includeExpired': '同时回收过期备份文件';
|
|
386
|
+
readonly 'diskUsage.area.rollbackPoints': '回滚点库';
|
|
387
|
+
readonly 'diskUsage.area.rollbackPointsDesc': '每回合自动留点的快照(工作区 + 会话两态);只报告,不自动清理';
|
|
388
|
+
readonly 'diskUsage.legacy.title': '遗留数据';
|
|
389
|
+
readonly 'diskUsage.legacy.hint': '插件已不再读取这些目录,也不会自动删除它们;确认无用后可手动清理。它们不计入上方合计。';
|
|
390
|
+
readonly 'diskUsage.legacy.label': '遗留数据';
|
|
385
391
|
readonly 'library.kind.snapshot': '本机快照';
|
|
386
392
|
readonly 'library.kind.backupFile': '备份文件';
|
|
387
393
|
readonly 'library.kind.remote': '远端快照';
|
|
@@ -508,6 +514,35 @@ export declare const uiZh: {
|
|
|
508
514
|
readonly 'foreign.lossy.entry-backslash.detail': 'ZIP 条目名里出现在中段的反斜杠不会被拒绝:同一个包在 Windows 目标上会被当作路径分隔符(落成多级目录),在 POSIX 目标上只是一个普通字符。本实现刻意不改这一格式行为;界面无法逐条检查条目名,跨平台导入后请核对这类文件是否落在预期位置。';
|
|
509
515
|
readonly 'foreign.lossy.prompt-persona-reshape.title': 'prompts 的 systemPrompt 形状变化';
|
|
510
516
|
readonly 'foreign.lossy.prompt-persona-reshape.detail': '源里的 systemPrompt 是字符串,导入落盘时写成带 persona 字段的对象:persona 文本无损,字段形状改变。兼容性评分不会为这一条给出原因 —— 它不改变内容,只改变形态。';
|
|
517
|
+
readonly 'export.category.settings': 'DSH 全局设置(namespace 分区,redacted)';
|
|
518
|
+
readonly 'export.category.providers': 'LLM Provider / Model / 默认模型 / BaseURL';
|
|
519
|
+
readonly 'export.category.plugins': '已安装插件清单与启用状态(不含二进制)';
|
|
520
|
+
readonly 'export.category.pluginFiles': '插件自有配置文件(白名单 + plugin-config/ 目录,整文件复制)';
|
|
521
|
+
readonly 'export.category.self': '本插件自身配置(同步/自动同步/分区选择/UI 偏好/市场;sync-*.json 等,不含凭据值)';
|
|
522
|
+
readonly 'export.category.mcp': 'MCP 服务器组合配置(需重启生效)';
|
|
523
|
+
readonly 'export.category.prompts': 'System Prompt / Plan Mode 提示';
|
|
524
|
+
readonly 'export.category.skills': '用户技能文件(~/.dsh/skills)';
|
|
525
|
+
readonly 'export.category.agentPresets': 'Agent 预设(~/.dsh/.agent-presets)';
|
|
526
|
+
readonly 'export.category.agentInstructions': '全局指令文件(~/.dsh/AGENTS.md,注入每个会话)';
|
|
527
|
+
readonly 'export.category.workspaces': '工作区记录(含绝对路径,需路径映射)';
|
|
528
|
+
readonly 'export.category.ui': 'UI 类 settings namespace(localStorage 项仅说明)';
|
|
529
|
+
readonly 'export.category.credentialsStatus': '凭据状态(configured 标记,永不导出值)';
|
|
530
|
+
readonly 'export.category.sessions': '历史会话(默认关闭,含敏感内容)';
|
|
531
|
+
readonly 'export.group.automationNote': 'DSH 当前无 Workflows / Commands 配置文件(运行时注册),无迁移内容';
|
|
532
|
+
readonly 'report.unitSeparator': ',';
|
|
533
|
+
readonly 'foreign.source.unknownWithId': '未识别的来源({id})';
|
|
534
|
+
readonly 'import.analysisFailed': '备份分析失败';
|
|
535
|
+
readonly 'import.analysisIncomplete': '尚未完成分析,请先选择备份文件';
|
|
536
|
+
readonly 'import.notConfirmed': '导入未确认:必须确认后才允许修改任何数据';
|
|
537
|
+
readonly 'import.retryNoResult': '没有可重试的导入结果';
|
|
538
|
+
readonly 'import.retryNothing': '没有失败或跳过的项需要重试';
|
|
539
|
+
readonly 'run.exportResultLost': '上次导出任务已结束但结果无法恢复,请重新导出';
|
|
540
|
+
readonly 'run.importResultLost': '上次导入任务已结束或超过保留期,结果无法恢复,请重新导入';
|
|
541
|
+
readonly 'run.restoreResultLost': '上次恢复任务已结束但结果无法恢复,请重新执行';
|
|
542
|
+
readonly 'run.exportUnavailable': '导出失败(结果不可用)';
|
|
543
|
+
readonly 'run.restoreUnavailable': '恢复失败(结果不可用)';
|
|
544
|
+
readonly 'run.progressLost': '任务已结束或超过保留期,进度不可恢复';
|
|
545
|
+
readonly 'run.restoreProgressLost': '恢复任务已结束或超过保留期,进度不可恢复';
|
|
511
546
|
};
|
|
512
547
|
export type UiTextKey = keyof typeof uiZh;
|
|
513
548
|
export declare const uiEn: Record<UiTextKey, string>;
|
|
@@ -515,5 +550,35 @@ export declare const uiEn: Record<UiTextKey, string>;
|
|
|
515
550
|
export type UiT = (key: UiTextKey, params?: Record<string, string | number>) => string;
|
|
516
551
|
/** 构造 翻译函数(zh 源 / en 镜像;缺 key 回退)。 */
|
|
517
552
|
export declare function makeUiT(lang: 'zh' | 'en'): UiT;
|
|
553
|
+
/**
|
|
554
|
+
* 客户端渲染层的语言来源标识:`'zh'` 之外的任何值一律按 `'en'` 处理
|
|
555
|
+
* (英文界面**不得**回落中文:`'ja'` 等未知语言一律回落 en)。
|
|
556
|
+
*/
|
|
557
|
+
export type UiLanguageId = 'zh' | 'en';
|
|
558
|
+
/**
|
|
559
|
+
* 构造**活的** UI 翻译器(「英文界面零中文」的根因修复)。
|
|
560
|
+
*
|
|
561
|
+
* `read()` 在**每次取文案时**调用 —— 与 DSH 官方 `ctx.locale.bind(ns)` 的 `t` 同语义
|
|
562
|
+
* (官方 `bind` → `translate` 每次调用都读当前 locale 快照)。`makeUiT(lang)` 是**加载期快照**,
|
|
563
|
+
* 只在「明确要固定语言」的路径使用(测试、离线/未注入路径);客户端 `apply()` 里禁止用它 ——
|
|
564
|
+
* 把语言钉死在插件加载那一刻,正是「切到 English 后本插件文案恒为中文」的成因。
|
|
565
|
+
*
|
|
566
|
+
* 回落链与 `makeUiT` 逐字一致:目标语言缺键 → zh → 键名;`{param}` 缺参原样保留。
|
|
567
|
+
*/
|
|
568
|
+
export declare function makeLiveUiT(read: () => string): UiT;
|
|
569
|
+
/**
|
|
570
|
+
* 接线模块级活翻译器(`liveUiT`)的语言来源。
|
|
571
|
+
*
|
|
572
|
+
* 为什么需要它:`runStore` 这类**模块级单例**没有「调用方」可以传 `UiT`,而它们产出的文案
|
|
573
|
+
* 同样必须随语言切换 —— 让它们直接用活翻译器,而不是拿 `zhUiT` 当缺省值把语言钉死。
|
|
574
|
+
*/
|
|
575
|
+
export declare function setUiLanguageSource(read: () => string): void;
|
|
576
|
+
/** 当前语言(活源:每次调用读一次;非 'zh' 一律 'en')—— 模块级消费者选目录时用。 */
|
|
577
|
+
export declare function currentUiLanguage(): UiLanguageId;
|
|
578
|
+
/**
|
|
579
|
+
* 模块级**活**翻译器:每次调用都读当前语言来源。
|
|
580
|
+
* 未接线(测试 / 离线 / 未注入路径)时等价于 `zhUiT`;客户端接线后随 DSH locale 变化。
|
|
581
|
+
*/
|
|
582
|
+
export declare const liveUiT: UiT;
|
|
518
583
|
/** 缺省 UI 翻译(zh):未注入的渲染路径行为与改造前完全一致。 */
|
|
519
584
|
export declare const zhUiT: UiT;
|