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.
- package/README.md +149 -98
- package/README.zh-CN.md +245 -88
- package/lib/adapters/agent-instructions.js +1 -1
- package/lib/adapters/file-collection.js +1 -1
- package/lib/adapters/index.d.ts +2 -1
- package/lib/adapters/index.js +6 -1
- package/lib/adapters/link-report.d.ts +1 -0
- package/lib/adapters/link-report.js +27 -3
- package/lib/adapters/messages.d.ts +21 -0
- package/lib/adapters/messages.js +57 -0
- package/lib/adapters/plugin-data.d.ts +114 -0
- package/lib/adapters/plugin-data.js +309 -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 +8 -2
- package/lib/adapters/self.js +3 -2
- package/lib/adapters/sessions.d.ts +1 -0
- package/lib/adapters/sessions.js +4 -2
- package/lib/adapters/test-helpers.d.ts +9 -0
- package/lib/adapters/test-helpers.js +14 -0
- 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 +1442 -494
- package/lib/client.js +15326 -8520
- package/lib/core/analyzer.d.ts +11 -2
- package/lib/core/analyzer.js +31 -8
- package/lib/core/backup-plan.d.ts +10 -0
- package/lib/core/backup-plan.js +51 -20
- package/lib/core/backup-verify.js +24 -23
- package/lib/core/backup.d.ts +25 -1
- package/lib/core/backup.js +99 -28
- package/lib/core/boot-rescue.js +4 -3
- package/lib/core/boot-safety.js +2 -1
- package/lib/core/command-rollback.d.ts +182 -0
- package/lib/core/command-rollback.js +293 -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 +294 -0
- package/lib/core/messages-core.js +619 -0
- package/lib/core/messages.d.ts +61 -2
- package/lib/core/messages.js +118 -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/plugin-data-registry.d.ts +124 -0
- package/lib/core/plugin-data-registry.js +198 -0
- 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-gate.d.ts +33 -0
- package/lib/core/rollback-gate.js +57 -0
- package/lib/core/rollback-ignore-rules.d.ts +31 -0
- package/lib/core/rollback-ignore-rules.js +140 -0
- package/lib/core/rollback-ledger.d.ts +248 -0
- package/lib/core/rollback-ledger.js +1282 -0
- package/lib/core/rollback-point.d.ts +1391 -0
- package/lib/core/rollback-point.js +3503 -0
- package/lib/core/rollback.js +6 -4
- 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 +37 -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.d.ts +1 -1
- package/lib/foreign/registry.js +8 -7
- 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 +227 -7
- package/lib/index.js +799 -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 +43 -0
- package/lib/routes/messages.js +102 -0
- package/lib/routes/prefs.js +26 -3
- package/lib/routes/profiles.js +12 -6
- package/lib/routes/recovery.d.ts +21 -0
- package/lib/routes/recovery.js +478 -94
- package/lib/routes/snapshots.js +51 -4
- package/lib/routes/sync.js +79 -17
- 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 +42 -15
- package/lib/schema/section-registry.js +67 -32
- package/lib/schema/types.d.ts +1 -1
- 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 +58 -22
- package/lib/sync/sync-engine.js +119 -48
- 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/ui-prefs.d.ts +22 -0
- package/lib/sync/ui-prefs.js +28 -0
- 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/diff-view.d.ts +10 -0
- package/lib/ui/diff-view.js +17 -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 +26 -20
- package/lib/ui/foreign-view.d.ts +5 -1
- package/lib/ui/foreign-view.js +26 -2
- package/lib/ui/i18n.d.ts +68 -1
- package/lib/ui/i18n.js +120 -2
- 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 +815 -0
- package/lib/ui/rollback-view.js +738 -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/test-helpers.js +2 -1
- 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 +6 -1
- package/src/adapters/link-report.test.ts +22 -2
- package/src/adapters/link-report.ts +29 -4
- package/src/adapters/messages.ts +61 -0
- package/src/adapters/plugin-data.test.ts +225 -0
- package/src/adapters/plugin-data.ts +351 -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 +10 -3
- package/src/adapters/sessions.ts +4 -2
- package/src/adapters/settings.test.ts +38 -1
- package/src/adapters/test-helpers.ts +15 -0
- 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 +411 -0
- package/src/client/chat/RollbackDiffTab.tsx +108 -0
- package/src/client/chat/RollbackFileIcon.tsx +96 -0
- package/src/client/chat/RollbackReviewDialog.tsx +607 -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 +183 -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 +174 -0
- package/src/client/chat/rollback-entry-view.test.ts +1469 -0
- package/src/client/chat/rollback-entry-view.ts +946 -0
- package/src/client/chat/sidebar-slots.ts +59 -0
- package/src/client/common/ConfirmDialog.tsx +7 -3
- package/src/client/common/ContentPicker.tsx +48 -10
- package/src/client/common/DiffTable.tsx +133 -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 +84 -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 +38 -0
- package/src/client/common/section-labels.test.ts +1 -0
- package/src/client/common/section-labels.ts +2 -0
- package/src/client/common/ui.tsx +73 -10
- package/src/client/config-manager.module.css +1109 -31
- 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 +232 -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 +62 -9
- 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 +859 -0
- package/src/client/recovery/RollbackDiffPane.tsx +69 -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 +144 -6
- package/src/client/recovery/recovery-locales.test.ts +299 -0
- package/src/client/recovery/recovery-locales.ts +520 -149
- package/src/client/recovery/recovery-panel-layout.test.ts +132 -2
- package/src/client/recovery/rollback-enabled.ts +41 -0
- package/src/client/recovery/rollback-file-changes.test.ts +114 -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/analyzer.ts +31 -9
- package/src/core/backup-plan.test.ts +48 -5
- package/src/core/backup-plan.ts +51 -20
- package/src/core/backup-verify.ts +24 -23
- package/src/core/backup.test.ts +76 -0
- package/src/core/backup.ts +105 -29
- 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 +406 -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 +661 -0
- package/src/core/messages.ts +125 -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/plugin-data-registry.test.ts +113 -0
- package/src/core/plugin-data-registry.ts +261 -0
- 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-gate.test.ts +66 -0
- package/src/core/rollback-gate.ts +61 -0
- package/src/core/rollback-ignore-rules.ts +126 -0
- package/src/core/rollback-ledger.test.ts +655 -0
- package/src/core/rollback-ledger.ts +1314 -0
- package/src/core/rollback-point.test.ts +2853 -0
- package/src/core/rollback-point.ts +4340 -0
- package/src/core/rollback.ts +5 -3
- 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 +37 -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.test.ts +1 -1
- package/src/foreign/registry.ts +8 -7
- 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 +876 -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 +106 -0
- package/src/routes/prefs.ts +31 -2
- package/src/routes/profiles.ts +12 -6
- package/src/routes/recovery.test.ts +405 -1
- package/src/routes/recovery.ts +477 -94
- package/src/routes/snapshots.ts +51 -4
- package/src/routes/sync.ts +82 -17
- package/src/schema/config.ts +53 -20
- package/src/schema/index.ts +7 -5
- package/src/schema/manifest-schema.test.ts +4 -4
- package/src/schema/manifest.ts +19 -18
- package/src/schema/messages.ts +120 -0
- package/src/schema/registry.test.ts +28 -7
- package/src/schema/section-registry.ts +96 -42
- package/src/schema/types.ts +2 -1
- 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-credentials.test.ts +119 -0
- 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 +154 -52
- 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/transport.test.ts +1 -0
- package/src/sync/ui-prefs.test.ts +44 -1
- package/src/sync/ui-prefs.ts +39 -0
- 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/diff-view.test.ts +9 -1
- package/src/ui/diff-view.ts +22 -0
- 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 +26 -20
- package/src/ui/foreign-view.test.ts +43 -0
- package/src/ui/foreign-view.ts +30 -3
- package/src/ui/i18n.ts +131 -2
- 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 +836 -0
- package/src/ui/rollback-view.ts +1405 -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/test-helpers.ts +2 -1
- 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
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 单文件前后对照面板 —— DSH 右侧栏标签页与预览弹窗的降级内嵌**共用同一个**渲染。
|
|
3
|
+
*
|
|
4
|
+
* 数据面只有一种形状(`RollbackFileDiffResult`):界面按「能不能逐行对照」分派四态
|
|
5
|
+
* (结构原因 / 一致 / 有差异 / 读失败),**不猜、不撒谎**:
|
|
6
|
+
* · `reason` 有值 ⇒ 说「看不了」并给原因(绝不显示成「没有差异」);
|
|
7
|
+
* · `identical` ⇒ 才说「一致」。
|
|
8
|
+
* 安全:单元格正文是磁盘原文 ⇒ 展示前必过 redact()(由 DiffTable 的 sanitize 承接)。
|
|
9
|
+
*/
|
|
10
|
+
import type { TranslateNS } from '../client-types.ts'
|
|
11
|
+
import type { RollbackFileDiffResult } from '../../ui/rollback-view.ts'
|
|
12
|
+
import { rollbackFileDiffComparable, rollbackFileDiffReasonKey } from '../../ui/rollback-view.ts'
|
|
13
|
+
import { redact } from '../../security/redaction.ts'
|
|
14
|
+
import { Banner, Spinner } from '../common/ui.tsx'
|
|
15
|
+
import { DiffTable } from '../common/DiffTable.tsx'
|
|
16
|
+
import css from '../config-manager.module.css'
|
|
17
|
+
|
|
18
|
+
type RKey = Parameters<TranslateNS<'config-manager-recovery'>>[0]
|
|
19
|
+
const rk = (key: string): RKey => key as RKey
|
|
20
|
+
|
|
21
|
+
/** 面板状态(加载 / 就绪 / 读失败)。 */
|
|
22
|
+
export type RollbackDiffState =
|
|
23
|
+
| { status: 'loading' }
|
|
24
|
+
| { status: 'ready'; diff: RollbackFileDiffResult }
|
|
25
|
+
| { status: 'error'; message: string | null }
|
|
26
|
+
|
|
27
|
+
export interface RollbackDiffPaneProps {
|
|
28
|
+
state: RollbackDiffState
|
|
29
|
+
rt: TranslateNS<'config-manager-recovery'>
|
|
30
|
+
/**
|
|
31
|
+
* 文件头(可选)= 该文件路径:给了就在差异上方画一行「路径 + +A/−R」(编辑器式)。
|
|
32
|
+
* 调用方**已在别处写过这份路径**(聊天预览/设置页的就地展示原本各画一行)时**不要传** —— 同一路径不画两遍。
|
|
33
|
+
*/
|
|
34
|
+
title?: string
|
|
35
|
+
/**
|
|
36
|
+
* 撑满宿主给的高度(**只有侧栏标签页该给**):正文是那一屏的唯一内容时,
|
|
37
|
+
* 表格自己吃掉剩余高度、滚动只发生在表格里;弹窗 / 计划列表里的就地差异不给(那些容器有别的约束)。
|
|
38
|
+
*/
|
|
39
|
+
fill?: boolean
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function RollbackDiffPane({ state, rt, title, fill }: RollbackDiffPaneProps) {
|
|
43
|
+
if (state.status === 'loading') return <Spinner label={rt('rollback.diff.loading')} />
|
|
44
|
+
if (state.status === 'error') return <Banner kind="error">{state.message === null ? rt('rollback.diff.failed') : redact(state.message)}</Banner>
|
|
45
|
+
const diff = state.diff
|
|
46
|
+
if (diff.ok !== true) {
|
|
47
|
+
// 宿主结构化拒绝(未命中记录 / 存储栈不可用 …):给可读文案 + 真实 code(不裸渲染机器码,但也不藏)
|
|
48
|
+
const code = diff.code === undefined || diff.code === '' ? '' : ' — ' + diff.code
|
|
49
|
+
return <Banner kind="error">{rt('rollback.diff.failed') + code}</Banner>
|
|
50
|
+
}
|
|
51
|
+
if (!rollbackFileDiffComparable(diff)) {
|
|
52
|
+
const key = rollbackFileDiffReasonKey(diff.reason)
|
|
53
|
+
return <div className={css.hint}>{key === null ? rt('rollback.diff.reason.unknown') : rt(rk(key))}</div>
|
|
54
|
+
}
|
|
55
|
+
if (diff.identical) return <div className={css.hint}>{rt('rollback.diff.identical')}</div>
|
|
56
|
+
return (
|
|
57
|
+
<div className={fill === true ? css.diffPane + ' ' + css.diffPaneFill : css.diffPane}>
|
|
58
|
+
{diff.degraded && <div className={css.hint}>{rt('rollback.diff.degraded')}</div>}
|
|
59
|
+
<DiffTable
|
|
60
|
+
hunks={diff.hunks}
|
|
61
|
+
title={title}
|
|
62
|
+
beforeLabel={rt('rollback.diff.before')}
|
|
63
|
+
afterLabel={rt('rollback.diff.after')}
|
|
64
|
+
truncatedNotice={(shown, total) => rt('rollback.diff.truncated', { shown: String(shown), total: String(total) })}
|
|
65
|
+
sanitize={redact}
|
|
66
|
+
/>
|
|
67
|
+
</div>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 回退预览的文件清单 —— **一份实现,两处调用**:
|
|
3
|
+
* · 聊天里用户消息旁的回退预览(`src/client/chat/RollbackReviewDialog.tsx`);
|
|
4
|
+
* · 设置页「环境 → 工作区 + 会话回滚」回滚卡的预览弹窗(`src/client/recovery/RollbackCard.tsx`)。
|
|
5
|
+
*
|
|
6
|
+
* 为什么抽成一个文件(2026-10-12 用户要求「设置页的回退预览也要一眼看清被改动的文件」):
|
|
7
|
+
* 两处必须**逐字同版式** —— 图标 | 目录(弱化)+ 基名(主色)| 右对齐统计;删除行写「删除」;
|
|
8
|
+
* 行数不可信写「行数未统计」。版式散在两处就会漂移,所以渲染只有这一份。
|
|
9
|
+
* 数据面与判定面照旧各自只有一份:行数据来自 `readRollbackPreviewFiles` /
|
|
10
|
+
* `readRollbackPreviewRemovals`(引擎 `preview.workspace` 的同一份数据),统计口径来自
|
|
11
|
+
* `rollbackPreviewScope`(只累加两侧都可信的行数)。
|
|
12
|
+
*
|
|
13
|
+
* 诚实边界(不假装):
|
|
14
|
+
* · **删除行不是按钮**:这类路径不在该回滚点的记录里,引擎的 file-diff 也读不出它 ⇒ 点了也没有
|
|
15
|
+
* 差异可看。「点文件名看差异」只对**能看**的行成立(调用方给了 `view` 才把路径画成按钮)。
|
|
16
|
+
* · 行数可能是 `null`(超限 / 非文本 / 内容副本读不出)⇒ 那一格写「行数未统计」,**绝不写 0**:
|
|
17
|
+
* 「0 行」是一个会被证伪的具体断言,而「不知道」不是。
|
|
18
|
+
* · 形状读不出(`status` 不在取值域)⇒ 不画语义色条(宁可不画,也不按猜测上色)。
|
|
19
|
+
*/
|
|
20
|
+
import type { TranslateNS } from '../client-types.ts'
|
|
21
|
+
import { rollbackPreviewFileLabel, splitRollbackPath } from '../../ui/rollback-view.ts'
|
|
22
|
+
import { RollbackFileIcon, type RollbackFileIconRenderer } from '../chat/RollbackFileIcon.tsx'
|
|
23
|
+
import {
|
|
24
|
+
previewFileStatusKnown,
|
|
25
|
+
rollbackPreviewFileKey,
|
|
26
|
+
type ChatPreviewFileRow,
|
|
27
|
+
} from '../chat/rollback-entry-view.ts'
|
|
28
|
+
import css from '../config-manager.module.css'
|
|
29
|
+
|
|
30
|
+
type RKey = Parameters<TranslateNS<'config-manager-recovery'>>[0]
|
|
31
|
+
const rk = (key: string): RKey => key as RKey
|
|
32
|
+
|
|
33
|
+
/** 一个文件的「查看差异」入口(调用方给的已插值文案 + 点击回调)。 */
|
|
34
|
+
export interface RollbackFileViewEntry {
|
|
35
|
+
/** 该行的无障碍名 / 悬停提示(把 {path} 插好的完整句)。 */
|
|
36
|
+
hint: (path: string) => string
|
|
37
|
+
/** 忙态或还没有可写目标时禁用 —— 入口仍占位(不消失)。 */
|
|
38
|
+
disabled: boolean
|
|
39
|
+
onView: (path: string) => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface RollbackFileChangesProps {
|
|
43
|
+
/** 会被**改动**的文件(`readRollbackPreviewFiles(preview.workspace)` 的产物)。 */
|
|
44
|
+
files: readonly ChatPreviewFileRow[]
|
|
45
|
+
/** 会被整文件**删除**的路径(`readRollbackPreviewRemovals(preview.workspace)` 的产物)。 */
|
|
46
|
+
removals: readonly string[]
|
|
47
|
+
/** recovery 字典翻译器(±行数 / 「删除」/「行数未统计」的词汇单一所有)。 */
|
|
48
|
+
rt: TranslateNS<'config-manager-recovery'>
|
|
49
|
+
/** 逐行「查看差异」;不给 = 该表面没有差异通道(那时路径只是文字,不给假入口)。 */
|
|
50
|
+
view?: RollbackFileViewEntry
|
|
51
|
+
/** 文件类型图标的外部来源(装了 dsh-better-sidebar 时由装配点注入)。 */
|
|
52
|
+
renderFileIcon?: RollbackFileIconRenderer
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 一行文件统计:`+N` / `−M`;任一侧是 null ⇒ 「行数未统计」整句替换(绝不打 0)。
|
|
57
|
+
* 两侧都可信时**两个数字都给**(新增与删除是两件事,用户两个都要看)。
|
|
58
|
+
*
|
|
59
|
+
* 例外:**整文件删除写「删除」**,不写 `+0 −N`。判据只看引擎给的 `status === 'delete'`
|
|
60
|
+
* (取值域在 src/ui/rollback-view.ts,契约里已有),**绝不**从 `added === 0` 反推删除 ——
|
|
61
|
+
* 一个文件被清空成 0 行同样是 `+0 −N`,那是另一件事。
|
|
62
|
+
*/
|
|
63
|
+
function FileStat({ status, added, removed, unknown, deleted, rt }: {
|
|
64
|
+
status: string
|
|
65
|
+
added: number | null
|
|
66
|
+
removed: number | null
|
|
67
|
+
unknown: string
|
|
68
|
+
/** 「删除」这一句(调用点传已翻译文本,本组件不碰字典键)。 */
|
|
69
|
+
deleted: string
|
|
70
|
+
rt: TranslateNS<'config-manager-recovery'>
|
|
71
|
+
}) {
|
|
72
|
+
if (status === 'delete') return <span className={css.rollbackDeleted}>{deleted}</span>
|
|
73
|
+
if (added === null || removed === null) return <span className={css.hint}>{unknown}</span>
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
<span className={css.rollbackAdded}>{rt(rk('rollback.preview.file.added'), { n: String(added) })}</span>
|
|
77
|
+
<span className={css.rollbackRemoved}>{rt(rk('rollback.preview.file.removed'), { n: String(removed) })}</span>
|
|
78
|
+
</>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** 文件清单(改动行 + 删除行)。两处调用共用这一份渲染。 */
|
|
83
|
+
export function RollbackFileChanges({ files, removals, rt, view, renderFileIcon }: RollbackFileChangesProps) {
|
|
84
|
+
return (
|
|
85
|
+
<div className={css.rollbackFileList} role="list">
|
|
86
|
+
{files.map((file, index) => {
|
|
87
|
+
// 目录弱化 + 基名主色:只画基名时 `.git/index` 读不出「在哪」。
|
|
88
|
+
const { dir, base } = splitRollbackPath(file.path)
|
|
89
|
+
const label = (
|
|
90
|
+
<>
|
|
91
|
+
{dir !== '' && <span className={css.rollbackFileDir}>{dir}</span>}
|
|
92
|
+
{base}
|
|
93
|
+
</>
|
|
94
|
+
)
|
|
95
|
+
return (
|
|
96
|
+
<div
|
|
97
|
+
key={rollbackPreviewFileKey(file.path, file.added, file.removed, index)}
|
|
98
|
+
className={css.rollbackFileRow}
|
|
99
|
+
role="listitem"
|
|
100
|
+
data-kind={previewFileStatusKnown(file.status) ? file.status : undefined}
|
|
101
|
+
>
|
|
102
|
+
{/* 文件类型图标(DSH 文件树同一颗)。装饰性:行内文件名就是它的可访问名。 */}
|
|
103
|
+
<span className={css.rollbackFileIcon} aria-hidden="true">
|
|
104
|
+
<RollbackFileIcon path={file.path} size={14} render={renderFileIcon} />
|
|
105
|
+
</span>
|
|
106
|
+
{/* 主标签 = 目录(弱化)+ 文件名(主色)。给了 `view` 时**它本身就是那颗按钮**
|
|
107
|
+
(2026-10-12 用户要求:不要尾部的独立「查看」按钮,点文件名直接跳)。
|
|
108
|
+
为什么按钮不是整行:整行做热区会把右侧 `+N −M` 也变成可点区域,鼠标停在统计上
|
|
109
|
+
像是要点它;这里只有名字/目录可点,统计永远点不到。完整路径仍在 title 里。 */}
|
|
110
|
+
{view === undefined ? (
|
|
111
|
+
<span className={`${css.rollbackFilePath} ${css.mono}`} title={file.path}>{label}</span>
|
|
112
|
+
) : (
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
className={`${css.rollbackFilePath} ${css.mono}`}
|
|
116
|
+
title={file.path}
|
|
117
|
+
aria-label={view.hint(file.path)}
|
|
118
|
+
disabled={view.disabled}
|
|
119
|
+
onClick={() => { view.onView(file.path) }}
|
|
120
|
+
>
|
|
121
|
+
{label}
|
|
122
|
+
</button>
|
|
123
|
+
)}
|
|
124
|
+
{/* ±行数紧跟文件名(统计列右对齐、列宽固定):三种取值的右缘对齐成一条竖线。 */}
|
|
125
|
+
<span className={css.rollbackFileStat}>
|
|
126
|
+
<FileStat
|
|
127
|
+
status={file.status}
|
|
128
|
+
added={file.added}
|
|
129
|
+
removed={file.removed}
|
|
130
|
+
unknown={rt('rollback.preview.file.unknown')}
|
|
131
|
+
deleted={rt(rk('rollback.preview.file.deleted'))}
|
|
132
|
+
rt={rt}
|
|
133
|
+
/>
|
|
134
|
+
</span>
|
|
135
|
+
</div>
|
|
136
|
+
)
|
|
137
|
+
})}
|
|
138
|
+
{removals.map((path, index) => {
|
|
139
|
+
const { dir, base } = splitRollbackPath(path)
|
|
140
|
+
return (
|
|
141
|
+
<div
|
|
142
|
+
key={'remove:' + rollbackPreviewFileKey(path, null, null, index)}
|
|
143
|
+
className={css.rollbackFileRow}
|
|
144
|
+
role="listitem"
|
|
145
|
+
data-kind="delete"
|
|
146
|
+
>
|
|
147
|
+
<span className={css.rollbackFileIcon} aria-hidden="true">
|
|
148
|
+
<RollbackFileIcon path={path} size={14} render={renderFileIcon} />
|
|
149
|
+
</span>
|
|
150
|
+
{/* 删除行**不是按钮**(纯文本):见文件头「诚实边界」第 1 条。 */}
|
|
151
|
+
<span className={`${css.rollbackFilePath} ${css.mono}`} title={path}>
|
|
152
|
+
{dir !== '' && <span className={css.rollbackFileDir}>{dir}</span>}
|
|
153
|
+
{base || rollbackPreviewFileLabel(path)}
|
|
154
|
+
</span>
|
|
155
|
+
<span className={css.rollbackFileStat}>
|
|
156
|
+
<span className={css.rollbackDeleted}>{rt(rk('rollback.preview.file.deleted'))}</span>
|
|
157
|
+
</span>
|
|
158
|
+
</div>
|
|
159
|
+
)
|
|
160
|
+
})}
|
|
161
|
+
</div>
|
|
162
|
+
)
|
|
163
|
+
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* 安全约束:错误文本由 Host 侧脱敏;进入救援模式是高风险写盘动作,confirm 必须由调用方在
|
|
14
14
|
* 显式确认弹窗后传入 —— 本层绝不代填。本文件不 import 任何 node 模块(纯浏览器 bundle)。
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
16
|
+
import type { UiT } from '../../ui/i18n.ts'
|
|
17
17
|
import { getJson, LONG_REQUEST_TIMEOUT_MS, postJson, type RequestOptions } from '../common/http.ts'
|
|
18
18
|
import { INCIDENT_API } from '../common/routes.ts'
|
|
19
19
|
|
|
@@ -62,7 +62,7 @@ export interface RescueActionResult {
|
|
|
62
62
|
/** 事故恢复(崩溃归因 + 救援模式)浏览器半数据入口。 */
|
|
63
63
|
export class IncidentApi {
|
|
64
64
|
readonly t: UiT
|
|
65
|
-
constructor(t: UiT
|
|
65
|
+
constructor(t: UiT) {
|
|
66
66
|
this.t = t
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
* POST /api/dsh-config-manager/recovery/lock/recover → RecoveryLockRecoverResult
|
|
17
17
|
* POST /api/dsh-config-manager/recovery/safe-mode/clear → RecoverySafeModeClearResult
|
|
18
18
|
* POST /api/dsh-config-manager/recovery/sessions/layout → SessionLayoutPlanView | SessionLayoutApplyView
|
|
19
|
+
* GET /api/dsh-config-manager/recovery/rollback-points → RollbackListResult
|
|
20
|
+
* GET /api/dsh-config-manager/recovery/rollback-points/storage → RollbackStorageStatus
|
|
21
|
+
* GET /api/dsh-config-manager/recovery/rollback-points/<id> → RollbackDetailResult
|
|
22
|
+
* GET /api/dsh-config-manager/recovery/rollback-points/<id>/preview → RollbackPreviewResult
|
|
23
|
+
* POST /api/dsh-config-manager/recovery/rollback-points/<id>/rewind → RollbackRewindResult
|
|
24
|
+
* POST /api/dsh-config-manager/recovery/rollback-points/<id>/delete → RollbackRemoveResult
|
|
19
25
|
* ```
|
|
20
26
|
*
|
|
21
27
|
* 安全约束(§9.4 / §11):
|
|
@@ -35,9 +41,22 @@ import type {
|
|
|
35
41
|
SessionRepairResult,
|
|
36
42
|
SessionRepairRollbackResult,
|
|
37
43
|
} from '../../ui/session-inventory-view.ts';
|
|
38
|
-
import type { SessionLayoutResponse } from '../../ui/session-layout-view.ts'
|
|
44
|
+
import type { SessionLayoutResponse } from '../../ui/session-layout-view.ts'
|
|
45
|
+
import type {
|
|
46
|
+
RollbackDetailResult,
|
|
47
|
+
RollbackFileDiffResult,
|
|
48
|
+
RollbackListResult,
|
|
49
|
+
RollbackPointPort,
|
|
50
|
+
RollbackPreviewResult,
|
|
51
|
+
RollbackRemoveResult,
|
|
52
|
+
RollbackRewindOptions,
|
|
53
|
+
RollbackRewindResult,
|
|
54
|
+
RollbackPrefsResult,
|
|
55
|
+
RollbackPurgeResult,
|
|
56
|
+
RollbackStorageStatus,
|
|
57
|
+
} from '../../ui/rollback-view.ts';
|
|
39
58
|
import { ConfigManagerApiError, getJson, LONG_REQUEST_TIMEOUT_MS, postJson, type RequestOptions } from '../common/http.ts';
|
|
40
|
-
import {
|
|
59
|
+
import type { UiT } from '../../ui/i18n.ts';
|
|
41
60
|
import { RECOVERY_API } from '../common/routes.ts';
|
|
42
61
|
|
|
43
62
|
/** recovery 端点常量:**唯一来源** = `common/routes.ts`(W4 单点化),此处重导出保持导入面。 */
|
|
@@ -49,7 +68,25 @@ const RECOVERY_OPTS: RequestOptions = { timeoutMs: LONG_REQUEST_TIMEOUT_MS, time
|
|
|
49
68
|
/* 请求封装(readJson / getJson / postJson:统一超时 + 取消 + 错误映射)见 common/http.ts。 */
|
|
50
69
|
|
|
51
70
|
/** operationId 严格 UUID 校验(与 Host 侧 isValidOperationId 一致;防路径穿越)。 */
|
|
52
|
-
const OPERATION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
71
|
+
const OPERATION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* rollback-point 台账 id → 子路径。
|
|
75
|
+
*
|
|
76
|
+
* 只接受 `[A-Za-z0-9._-]{1,128}`:id 是宿主生成的,这里**只做形态收窄**(与 operationId 的
|
|
77
|
+
* UUID 校验同一条理由 —— 防路径穿越);不合形态的 id 直接抛,**绝不回显原始 id**、绝不拼进 URL
|
|
78
|
+
* 让宿主去兜。路径由 `RECOVERY_API.rollbackPoints` **派生**(路由常量是唯一来源;源码级守卫
|
|
79
|
+
* `http-usage-guard` 也只允许 `common/routes.ts` 出现 `/api/dsh-config-manager…` 字面量)。
|
|
80
|
+
*/
|
|
81
|
+
const ROLLBACK_POINT_ID_RE = /^[A-Za-z0-9._-]{1,128}$/
|
|
82
|
+
function rollbackPointUrl(id: string): string {
|
|
83
|
+
if (!ROLLBACK_POINT_ID_RE.test(id)) throw new Error('rollback point id invalid')
|
|
84
|
+
return RECOVERY_API.rollbackPoints + '/' + id
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function rollbackPointPath(id: string, sub: string): string {
|
|
88
|
+
return rollbackPointUrl(id) + '/' + sub
|
|
89
|
+
}
|
|
53
90
|
|
|
54
91
|
/**
|
|
55
92
|
* E2:`POST /recovery/sessions/layout`(布局归位 / 重复 id 隔离)。
|
|
@@ -67,10 +104,10 @@ function operationPath(operationId: string, action: string): string {
|
|
|
67
104
|
return `${RECOVERY_API.base}/${operationId}/${action}`;
|
|
68
105
|
}
|
|
69
106
|
|
|
70
|
-
/** Recovery 浏览器半数据入口(实现 RecoveryPort
|
|
71
|
-
export class RecoveryApi implements RecoveryPort {
|
|
107
|
+
/** Recovery 浏览器半数据入口(实现 RecoveryPort 契约 + rollback-points 族)。 */
|
|
108
|
+
export class RecoveryApi implements RecoveryPort, RollbackPointPort {
|
|
72
109
|
readonly t: UiT
|
|
73
|
-
constructor(t: UiT
|
|
110
|
+
constructor(t: UiT) {
|
|
74
111
|
this.t = t
|
|
75
112
|
}
|
|
76
113
|
|
|
@@ -106,6 +143,107 @@ export class RecoveryApi implements RecoveryPort {
|
|
|
106
143
|
return postJson<SessionRepairResult>(RECOVERY_API.sessionsRepair, body, this.t, RECOVERY_OPTS)
|
|
107
144
|
}
|
|
108
145
|
|
|
146
|
+
/* ------------------------------------------------- S7 rollback-points(工作区 + 会话回滚,两态) */
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* GET /recovery/rollback-points:台账列表(按时间倒序)+ 存储栈状态 + 留存上限。
|
|
150
|
+
*
|
|
151
|
+
* 列表本身**只读**:SAFE MODE 下也能看(宿主侧只有 rewind / delete 被 423 拦下),
|
|
152
|
+
* 因此界面必须能「看得见、但按钮说明为什么点不了」。
|
|
153
|
+
* 存储栈不可用时宿主回 **503 + 同体**(`storage.available=false` + guidance);`getJson` 对非 2xx
|
|
154
|
+
* 抛 `ConfigManagerApiError`(`status`=503,`code` 取响应体 code),调用方按 status 区分「读不出来」
|
|
155
|
+
* 与「本来就没有」。
|
|
156
|
+
*/
|
|
157
|
+
async rollbackPoints(): Promise<RollbackListResult> {
|
|
158
|
+
return getJson<RollbackListResult>(RECOVERY_API.rollbackPoints, this.t, RECOVERY_OPTS)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** GET /recovery/rollback-points/storage:存储栈探针(不可用 → 503 + guidance,同上)。 */
|
|
162
|
+
async rollbackPointStorage(): Promise<RollbackStorageStatus> {
|
|
163
|
+
return getJson<RollbackStorageStatus>(RECOVERY_API.rollbackPointsStorage, this.t, RECOVERY_OPTS)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** GET /recovery/rollback-points/<id>:单条详情(不存在 → 404 `record-not-found`)。 */
|
|
167
|
+
async rollbackPoint(id: string): Promise<RollbackDetailResult> {
|
|
168
|
+
return getJson<RollbackDetailResult>(rollbackPointUrl(id), this.t, RECOVERY_OPTS)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* GET /recovery/rollback-points/<id>/preview:**只读预览(零写入)**。
|
|
173
|
+
*
|
|
174
|
+
* 回传两态将覆盖多少项、其中多少项内容不同、多少项当前已不存在、多少项是该点**未记录**的
|
|
175
|
+
* (`removals` = 会被删除的、`createdSkipped` = 按安全判据拒删的;两者都只是**读回来的清单**,
|
|
176
|
+
* 本方法零写入),以及会话边界(from → to)与回合号;`canRestore` / `canRemove`
|
|
177
|
+
* 是宿主给出的权威判定,界面据此决定按钮可用性(展示判定见 `src/ui/rollback-view.ts`)。
|
|
178
|
+
*/
|
|
179
|
+
async rollbackPointPreview(id: string): Promise<RollbackPreviewResult> {
|
|
180
|
+
return getJson<RollbackPreviewResult>(rollbackPointPath(id, 'preview'), this.t, RECOVERY_OPTS)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* GET /recovery/rollback-points/<id>/file-diff?path=...:**单个记录在案文件**的前后逐行对照。
|
|
185
|
+
*
|
|
186
|
+
* 只读、零写入;路径以 query 传递(宿主内再收窄一次:未命中该点记录一律 `file-not-recorded`,
|
|
187
|
+
* 一个字节都不读)。非 2xx(存储栈 503 / 参数 400)由 getJson 抛 ConfigManagerApiError,
|
|
188
|
+
* 由调用方按 status + code 出文案。
|
|
189
|
+
*/
|
|
190
|
+
async rollbackPointFileDiff(id: string, path: string): Promise<RollbackFileDiffResult> {
|
|
191
|
+
const query = '?path=' + encodeURIComponent(path)
|
|
192
|
+
return getJson<RollbackFileDiffResult>(rollbackPointPath(id, 'file-diff') + query, this.t, RECOVERY_OPTS)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* POST /recovery/rollback-points/<id>/rewind:回退(工作区文件覆盖 + 会话 fork 子会话)。
|
|
197
|
+
*
|
|
198
|
+
* **确认门是 fail-closed**:`userConfirmed` 必须**恰好** true(宿主缺省 / 假值一律
|
|
199
|
+
* 409 `confirmation-required` + 零写入)。本方法绝不自动置 true —— 由确认弹窗的 onClick 传进来。
|
|
200
|
+
* 409(confirmation-required / protected-point / record-incomplete)与 423(mutation-locked)
|
|
201
|
+
* 都以 `ConfigManagerApiError` 抛出,`status` / `code` 保留,界面按 code 出文案(不靠状态码猜原因)。
|
|
202
|
+
* 会话回退 **不改写原会话日志**:结果里回传 `childSessionId`(新子会话),原会话只读。
|
|
203
|
+
*/
|
|
204
|
+
async restoreRollbackPoint(id: string, opts: RollbackRewindOptions): Promise<RollbackRewindResult> {
|
|
205
|
+
const body: Record<string, unknown> = { userConfirmed: opts.userConfirmed === true }
|
|
206
|
+
if (opts.mode !== undefined) body['mode'] = opts.mode
|
|
207
|
+
if (opts.segments !== undefined && opts.segments.length > 0) body['segments'] = [...opts.segments]
|
|
208
|
+
if (opts.allowPartial === true) body['allowPartial'] = true
|
|
209
|
+
if (opts.preRewindGuard !== undefined) body['preRewindGuard'] = opts.preRewindGuard
|
|
210
|
+
return postJson<RollbackRewindResult>(rollbackPointPath(id, 'rewind'), body, this.t, RECOVERY_OPTS)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* POST /recovery/rollback-points/<id>/delete:删除一个回滚点(保护点由宿主拒绝)。
|
|
215
|
+
* body 必须 `userConfirmed: true`(未确认 → 409 `confirmation-required`);本方法不自动置 true。
|
|
216
|
+
*/
|
|
217
|
+
async removeRollbackPoint(id: string, userConfirmed: boolean): Promise<RollbackRemoveResult> {
|
|
218
|
+
return postJson<RollbackRemoveResult>(rollbackPointPath(id, 'delete'), { userConfirmed: userConfirmed === true }, this.t, RECOVERY_OPTS)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* GET /recovery/rollback-points/prefs(issue #88):读开关。
|
|
223
|
+
* `rollbackEnabled` = 磁盘偏好(用户意图,随 self 分区进备份);
|
|
224
|
+
* `rollbackActive` = 本进程此刻是否真的在留点(关闭后订阅已解绑)。两者正常一致。
|
|
225
|
+
*/
|
|
226
|
+
async rollbackPrefs(): Promise<RollbackPrefsResult> {
|
|
227
|
+
return getJson<RollbackPrefsResult>(RECOVERY_API.rollbackPointsPrefs, this.t, RECOVERY_OPTS)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* POST /recovery/rollback-points/prefs(issue #88):写开关。
|
|
232
|
+
* 宿主写盘成功后才切进程 gate —— 写失败却把功能打开,等于「界面说开着、实际不留点」。
|
|
233
|
+
*/
|
|
234
|
+
async setRollbackEnabled(enabled: boolean): Promise<RollbackPrefsResult> {
|
|
235
|
+
return postJson<RollbackPrefsResult>(RECOVERY_API.rollbackPointsPrefs, { rollbackEnabled: enabled === true }, this.t, RECOVERY_OPTS)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* POST /recovery/rollback-points/cleanup(issue #89):清理台账占用。
|
|
240
|
+
* **只删自动点**;`includeGuards` 为 true 时连救援点也删(protected 永不删)。
|
|
241
|
+
* 返回逐类删除计数与释放字节,界面照实说「删了多少 / 还剩多少」。
|
|
242
|
+
*/
|
|
243
|
+
async purgeRollbackPoints(opts: { includeGuards: boolean }): Promise<RollbackPurgeResult> {
|
|
244
|
+
return postJson<RollbackPurgeResult>(RECOVERY_API.rollbackPointsCleanup, { userConfirmed: true, includeGuards: opts.includeGuards === true }, this.t, RECOVERY_OPTS)
|
|
245
|
+
}
|
|
246
|
+
|
|
109
247
|
/** POST /recovery/sessions/rollback(T8):按台账 repairId 回滚(客户端不传路径)。 */
|
|
110
248
|
async rollbackSessionRepair(repairId: string): Promise<SessionRepairRollbackResult> {
|
|
111
249
|
return postJson<SessionRepairRollbackResult>(RECOVERY_API.sessionsRollback, { repairId }, this.t, RECOVERY_OPTS)
|