dsh-config-manager 0.1.69 → 0.1.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -18
- package/README.zh-CN.md +29 -9
- package/lib/adapters/credentials.js +6 -3
- package/lib/adapters/file-collection.d.ts +21 -1
- package/lib/adapters/file-collection.js +32 -8
- package/lib/adapters/mcp.d.ts +12 -2
- package/lib/adapters/mcp.js +30 -13
- package/lib/adapters/plugin-files.d.ts +8 -0
- package/lib/adapters/plugin-files.js +36 -4
- package/lib/adapters/plugins.d.ts +28 -2
- package/lib/adapters/plugins.js +204 -55
- package/lib/adapters/prompts.d.ts +12 -2
- package/lib/adapters/prompts.js +34 -19
- package/lib/adapters/providers.js +5 -4
- package/lib/adapters/self.d.ts +20 -0
- package/lib/adapters/self.js +73 -0
- package/lib/adapters/sessions.d.ts +8 -0
- package/lib/adapters/sessions.js +47 -1
- package/lib/adapters/settings.d.ts +21 -3
- package/lib/adapters/settings.js +44 -7
- package/lib/adapters/skills.d.ts +36 -4
- package/lib/adapters/skills.js +222 -3
- package/lib/adapters/test-helpers.d.ts +31 -2
- package/lib/adapters/test-helpers.js +42 -5
- package/lib/adapters/workspaces.js +97 -5
- package/lib/cli/actions.d.ts +50 -3
- package/lib/cli/actions.js +103 -11
- package/lib/cli/help.d.ts +65 -0
- package/lib/cli/help.js +517 -0
- package/lib/cli/import-source.d.ts +32 -0
- package/lib/cli/import-source.js +178 -0
- package/lib/cli/index.d.ts +18 -2
- package/lib/cli/index.js +118 -90
- package/lib/cli/web/client-script.d.ts +8 -0
- package/lib/cli/web/client-script.js +11 -0
- package/lib/cli/web/http.d.ts +5 -0
- package/lib/cli/web/http.js +2 -1
- package/lib/cli/web/page.d.ts +16 -6
- package/lib/cli/web/page.js +102 -25
- package/lib/cli/web/routes.js +24 -5
- package/lib/cli/web/server.js +23 -2
- package/lib/client.d.ts +1019 -36
- package/lib/client.js +5522 -1564
- package/lib/core/analyzer.d.ts +15 -1
- package/lib/core/analyzer.js +114 -13
- package/lib/core/backup-plan.js +17 -1
- package/lib/core/backup.d.ts +8 -0
- package/lib/core/backup.js +28 -6
- package/lib/core/cache-cleaner.d.ts +10 -0
- package/lib/core/cache-cleaner.js +63 -22
- package/lib/core/checkpoint.d.ts +362 -0
- package/lib/core/checkpoint.js +1309 -0
- package/lib/core/journal.d.ts +37 -0
- package/lib/core/journal.js +69 -0
- package/lib/core/messages.d.ts +13 -0
- package/lib/core/messages.js +26 -0
- package/lib/core/model-tools.js +3 -0
- package/lib/core/patch-layers.d.ts +83 -0
- package/lib/core/patch-layers.js +110 -0
- package/lib/core/restore.d.ts +21 -0
- package/lib/core/restore.js +37 -3
- package/lib/core/rollback.js +6 -3
- package/lib/core/self-update.d.ts +52 -0
- package/lib/core/self-update.js +70 -0
- package/lib/core/session-health.d.ts +29 -5
- package/lib/core/session-health.js +28 -3
- package/lib/core/types.d.ts +126 -0
- package/lib/foreign/antigravity.d.ts +28 -0
- package/lib/foreign/antigravity.js +157 -0
- package/lib/foreign/bundle.d.ts +25 -0
- package/lib/foreign/bundle.js +79 -0
- package/lib/foreign/chatgpt.d.ts +6 -0
- package/lib/foreign/chatgpt.js +25 -0
- package/lib/foreign/claude-code.d.ts +3 -0
- package/lib/foreign/claude-code.js +85 -0
- package/lib/foreign/claude-sessions.d.ts +108 -0
- package/lib/foreign/claude-sessions.js +299 -0
- package/lib/foreign/cline.d.ts +6 -0
- package/lib/foreign/cline.js +27 -0
- package/lib/foreign/codex.d.ts +83 -0
- package/lib/foreign/codex.js +348 -0
- package/lib/foreign/continue.d.ts +9 -0
- package/lib/foreign/continue.js +65 -0
- package/lib/foreign/copilot.d.ts +39 -0
- package/lib/foreign/copilot.js +95 -0
- package/lib/foreign/crush.d.ts +11 -0
- package/lib/foreign/crush.js +57 -0
- package/lib/foreign/cursor.d.ts +87 -0
- package/lib/foreign/cursor.js +171 -0
- package/lib/foreign/dsh.d.ts +30 -0
- package/lib/foreign/dsh.js +101 -0
- package/lib/foreign/dsh4.d.ts +3 -0
- package/lib/foreign/dsh4.js +13 -0
- package/lib/foreign/gemini.d.ts +7 -0
- package/lib/foreign/gemini.js +44 -0
- package/lib/foreign/goose.d.ts +11 -0
- package/lib/foreign/goose.js +53 -0
- package/lib/foreign/grokbuild.d.ts +8 -0
- package/lib/foreign/grokbuild.js +25 -0
- package/lib/foreign/hermes.d.ts +2 -0
- package/lib/foreign/hermes.js +78 -0
- package/lib/foreign/kernel.d.ts +132 -0
- package/lib/foreign/kernel.js +569 -0
- package/lib/foreign/kilocode.d.ts +11 -0
- package/lib/foreign/kilocode.js +51 -0
- package/lib/foreign/kimi.d.ts +7 -0
- package/lib/foreign/kimi.js +47 -0
- package/lib/foreign/mimocode.d.ts +11 -0
- package/lib/foreign/mimocode.js +51 -0
- package/lib/foreign/openclaw.d.ts +7 -0
- package/lib/foreign/openclaw.js +46 -0
- package/lib/foreign/opencode.d.ts +11 -0
- package/lib/foreign/opencode.js +52 -0
- package/lib/foreign/pi.d.ts +7 -0
- package/lib/foreign/pi.js +48 -0
- package/lib/foreign/platform-paths.d.ts +66 -0
- package/lib/foreign/platform-paths.js +141 -0
- package/lib/foreign/qoder.d.ts +10 -0
- package/lib/foreign/qoder.js +49 -0
- package/lib/foreign/qwen.d.ts +7 -0
- package/lib/foreign/qwen.js +45 -0
- package/lib/foreign/read-antigravity.d.ts +57 -0
- package/lib/foreign/read-antigravity.js +504 -0
- package/lib/foreign/read-chatgpt.d.ts +20 -0
- package/lib/foreign/read-chatgpt.js +509 -0
- package/lib/foreign/read-claude-code.d.ts +24 -0
- package/lib/foreign/read-claude-code.js +234 -0
- package/lib/foreign/read-cline.d.ts +53 -0
- package/lib/foreign/read-cline.js +479 -0
- package/lib/foreign/read-codex.d.ts +75 -0
- package/lib/foreign/read-codex.js +842 -0
- package/lib/foreign/read-continue.d.ts +87 -0
- package/lib/foreign/read-continue.js +489 -0
- package/lib/foreign/read-copilot.d.ts +42 -0
- package/lib/foreign/read-copilot.js +267 -0
- package/lib/foreign/read-crush.d.ts +54 -0
- package/lib/foreign/read-crush.js +478 -0
- package/lib/foreign/read-cursor.d.ts +141 -0
- package/lib/foreign/read-cursor.js +705 -0
- package/lib/foreign/read-dsh.d.ts +43 -0
- package/lib/foreign/read-dsh.js +205 -0
- package/lib/foreign/read-dsh4.d.ts +14 -0
- package/lib/foreign/read-dsh4.js +27 -0
- package/lib/foreign/read-gemini.d.ts +55 -0
- package/lib/foreign/read-gemini.js +273 -0
- package/lib/foreign/read-goose.d.ts +25 -0
- package/lib/foreign/read-goose.js +322 -0
- package/lib/foreign/read-grokbuild.d.ts +34 -0
- package/lib/foreign/read-grokbuild.js +455 -0
- package/lib/foreign/read-hermes.d.ts +74 -0
- package/lib/foreign/read-hermes.js +690 -0
- package/lib/foreign/read-kilocode.d.ts +17 -0
- package/lib/foreign/read-kilocode.js +46 -0
- package/lib/foreign/read-kimi.d.ts +63 -0
- package/lib/foreign/read-kimi.js +719 -0
- package/lib/foreign/read-mimocode.d.ts +12 -0
- package/lib/foreign/read-mimocode.js +56 -0
- package/lib/foreign/read-openclaw.d.ts +51 -0
- package/lib/foreign/read-openclaw.js +445 -0
- package/lib/foreign/read-opencode.d.ts +150 -0
- package/lib/foreign/read-opencode.js +896 -0
- package/lib/foreign/read-pi.d.ts +56 -0
- package/lib/foreign/read-pi.js +411 -0
- package/lib/foreign/read-qoder.d.ts +54 -0
- package/lib/foreign/read-qoder.js +317 -0
- package/lib/foreign/read-qwen.d.ts +40 -0
- package/lib/foreign/read-qwen.js +326 -0
- package/lib/foreign/read-reasonix.d.ts +66 -0
- package/lib/foreign/read-reasonix.js +537 -0
- package/lib/foreign/read-teleagent.d.ts +15 -0
- package/lib/foreign/read-teleagent.js +68 -0
- package/lib/foreign/read-trae.d.ts +67 -0
- package/lib/foreign/read-trae.js +492 -0
- package/lib/foreign/read-vibe.d.ts +28 -0
- package/lib/foreign/read-vibe.js +364 -0
- package/lib/foreign/read-workbuddy.d.ts +49 -0
- package/lib/foreign/read-workbuddy.js +346 -0
- package/lib/foreign/read-zcode.d.ts +12 -0
- package/lib/foreign/read-zcode.js +38 -0
- package/lib/foreign/read-zed.d.ts +30 -0
- package/lib/foreign/read-zed.js +473 -0
- package/lib/foreign/reasonix.d.ts +6 -0
- package/lib/foreign/reasonix.js +20 -0
- package/lib/foreign/registry.d.ts +196 -0
- package/lib/foreign/registry.js +573 -0
- package/lib/foreign/session-ir.d.ts +186 -0
- package/lib/foreign/session-ir.js +427 -0
- package/lib/foreign/session-read.d.ts +102 -0
- package/lib/foreign/session-read.js +254 -0
- package/lib/foreign/session-source.d.ts +216 -0
- package/lib/foreign/session-source.js +453 -0
- package/lib/foreign/source-modules.d.ts +45 -0
- package/lib/foreign/source-modules.js +52 -0
- package/lib/foreign/sqlite.d.ts +61 -0
- package/lib/foreign/sqlite.js +404 -0
- package/lib/foreign/teleagent.d.ts +11 -0
- package/lib/foreign/teleagent.js +53 -0
- package/lib/foreign/trae.d.ts +6 -0
- package/lib/foreign/trae.js +20 -0
- package/lib/foreign/truth-table.d.ts +62 -0
- package/lib/foreign/truth-table.js +333 -0
- package/lib/foreign/types.d.ts +272 -0
- package/lib/foreign/types.js +2 -0
- package/lib/foreign/vibe.d.ts +6 -0
- package/lib/foreign/vibe.js +23 -0
- package/lib/foreign/workbuddy.d.ts +7 -0
- package/lib/foreign/workbuddy.js +45 -0
- package/lib/foreign/zcode.d.ts +11 -0
- package/lib/foreign/zcode.js +51 -0
- package/lib/foreign/zed.d.ts +11 -0
- package/lib/foreign/zed.js +53 -0
- package/lib/index.d.ts +154 -13
- package/lib/index.js +661 -84
- package/lib/market/github-repos.d.ts +28 -0
- package/lib/market/github-repos.js +43 -1
- package/lib/market/types.d.ts +1 -3
- package/lib/profiles/dsh-profile-manager.d.ts +54 -2
- package/lib/profiles/dsh-profile-manager.js +182 -11
- package/lib/profiles/dsh-profile-shared.d.ts +47 -0
- package/lib/profiles/dsh-profile-shared.js +15 -1
- package/lib/profiles/index.d.ts +1 -1
- package/lib/profiles/index.js +1 -1
- package/lib/routes/consult.js +51 -5
- package/lib/routes/foreign-context.d.ts +43 -0
- package/lib/routes/foreign-context.js +65 -0
- package/lib/routes/foreign.d.ts +11 -0
- package/lib/routes/foreign.js +208 -0
- package/lib/routes/import.d.ts +8 -0
- package/lib/routes/import.js +22 -1
- package/lib/routes/index.d.ts +2 -2
- package/lib/routes/index.js +4 -0
- package/lib/routes/kit.d.ts +4 -3
- package/lib/routes/market.js +0 -1
- package/lib/routes/prefs.d.ts +2 -1
- package/lib/routes/prefs.js +14 -2
- package/lib/routes/recovery.js +363 -3
- package/lib/routes/session-export.d.ts +117 -0
- package/lib/routes/session-export.js +270 -0
- package/lib/routes/snapshots.js +12 -2
- package/lib/routes/sync.js +82 -10
- package/lib/security/redaction.d.ts +14 -0
- package/lib/security/redaction.js +24 -9
- package/lib/security/secret-scanner.d.ts +27 -0
- package/lib/security/secret-scanner.js +54 -1
- package/lib/sync/autosync-scheduler.d.ts +13 -1
- package/lib/sync/autosync-scheduler.js +49 -26
- package/lib/sync/backup-files.js +6 -0
- package/lib/sync/gist/gist-transport.d.ts +91 -0
- package/lib/sync/gist/gist-transport.js +406 -0
- package/lib/sync/gist/messages.d.ts +22 -0
- package/lib/sync/gist/messages.js +46 -0
- package/lib/sync/s3/messages.d.ts +53 -0
- package/lib/sync/s3/messages.js +83 -0
- package/lib/sync/s3/s3-providers.d.ts +78 -0
- package/lib/sync/s3/s3-providers.js +156 -0
- package/lib/sync/s3/s3-transport.d.ts +126 -0
- package/lib/sync/s3/s3-transport.js +551 -0
- package/lib/sync/s3/sigv4.d.ts +107 -0
- package/lib/sync/s3/sigv4.js +196 -0
- package/lib/sync/sync-config.d.ts +250 -4
- package/lib/sync/sync-config.js +658 -57
- package/lib/sync/sync-engine.d.ts +1 -0
- package/lib/sync/sync-engine.js +4 -2
- package/lib/sync/sync-history.d.ts +1 -1
- package/lib/sync/webdav/webdav-transport.d.ts +31 -3
- package/lib/sync/webdav/webdav-transport.js +102 -18
- package/lib/ui/commands.d.ts +4 -3
- package/lib/ui/commands.js +41 -9
- package/lib/ui/disk-usage-view.d.ts +44 -0
- package/lib/ui/disk-usage-view.js +55 -1
- package/lib/ui/dsh-profiles-view.d.ts +53 -0
- package/lib/ui/dsh-profiles-view.js +56 -0
- package/lib/ui/foreign-view.d.ts +162 -0
- package/lib/ui/foreign-view.js +225 -0
- package/lib/ui/i18n.d.ts +77 -0
- package/lib/ui/i18n.js +164 -0
- package/lib/ui/session-inventory-view.d.ts +106 -0
- package/lib/ui/session-inventory-view.js +58 -0
- package/lib/ui/session-layout-view.d.ts +265 -0
- package/lib/ui/session-layout-view.js +271 -0
- package/lib/ui/sync-repository-picker.d.ts +98 -0
- package/lib/ui/sync-repository-picker.js +145 -0
- package/lib/ui/sync-settings-view.d.ts +143 -4
- package/lib/ui/sync-settings-view.js +231 -7
- package/lib/ui/types.d.ts +47 -0
- package/lib/utils/asar-read.d.ts +113 -0
- package/lib/utils/asar-read.js +523 -0
- package/lib/utils/env-lock.js +7 -2
- package/lib/utils/patch-yaml.d.ts +25 -0
- package/lib/utils/patch-yaml.js +62 -0
- package/lib/utils/paths.d.ts +10 -1
- package/lib/utils/paths.js +24 -3
- package/lib/utils/recursive-walk.js +12 -13
- package/lib/utils/session-format.d.ts +35 -2
- package/lib/utils/session-format.js +131 -5
- package/lib/utils/session-health-scan.d.ts +7 -1
- package/lib/utils/session-health-scan.js +369 -12
- package/lib/utils/session-layout-repair-service.d.ts +98 -0
- package/lib/utils/session-layout-repair-service.js +457 -0
- package/lib/utils/session-log-repair.d.ts +27 -0
- package/lib/utils/session-log-repair.js +233 -62
- package/lib/utils/session-repair-service.d.ts +32 -3
- package/lib/utils/session-repair-service.js +148 -9
- package/lib/utils/session-row-facts.d.ts +73 -0
- package/lib/utils/session-row-facts.js +182 -0
- package/lib/utils/session-verify.d.ts +118 -0
- package/lib/utils/session-verify.js +705 -0
- package/lib/utils/shared-constants.d.ts +59 -0
- package/lib/utils/shared-constants.js +71 -0
- package/package.json +1 -1
- package/src/adapters/credentials.test.ts +27 -0
- package/src/adapters/credentials.ts +6 -3
- package/src/adapters/file-collection.ts +33 -8
- package/src/adapters/files.test.ts +222 -0
- package/src/adapters/mcp.test.ts +43 -0
- package/src/adapters/mcp.ts +37 -14
- package/src/adapters/plugin-files.ts +34 -4
- package/src/adapters/plugins.test.ts +241 -0
- package/src/adapters/plugins.ts +201 -53
- package/src/adapters/prompts.test.ts +49 -0
- package/src/adapters/prompts.ts +41 -20
- package/src/adapters/providers.test.ts +16 -0
- package/src/adapters/providers.ts +4 -3
- package/src/adapters/self.test.ts +77 -0
- package/src/adapters/self.ts +75 -0
- package/src/adapters/sessions.test.ts +77 -0
- package/src/adapters/sessions.ts +47 -1
- package/src/adapters/settings.test.ts +78 -0
- package/src/adapters/settings.ts +42 -6
- package/src/adapters/skills.ts +221 -3
- package/src/adapters/test-helpers.ts +43 -5
- package/src/adapters/workspaces-dup-id.test.ts +144 -0
- package/src/adapters/workspaces.test.ts +10 -0
- package/src/adapters/workspaces.ts +97 -5
- package/src/cli/actions.test.ts +117 -2
- package/src/cli/actions.ts +132 -12
- package/src/cli/help.ts +570 -0
- package/src/cli/import-source.test.ts +193 -0
- package/src/cli/import-source.ts +229 -0
- package/src/cli/index.ts +129 -94
- package/src/cli/web/client-script.ts +12 -0
- package/src/cli/web/console-fixes.test.ts +36 -0
- package/src/cli/web/http.ts +7 -1
- package/src/cli/web/page.ts +108 -25
- package/src/cli/web/routes.ts +23 -4
- package/src/cli/web/script-anchor.test.ts +33 -0
- package/src/cli/web/server.ts +28 -2
- package/src/cli/web/web.test.ts +447 -4
- package/src/client/ConfigManagerSection.tsx +118 -63
- package/src/client/about/AboutPanel.tsx +42 -3
- package/src/client/about/PluginUpdateDialog.tsx +185 -0
- package/src/client/about/ReleaseBody.tsx +144 -0
- package/src/client/about/ReleaseNotesDialog.tsx +3 -130
- package/src/client/about/about-view.ts +7 -5
- package/src/client/about/plugin-update-view.test.ts +25 -0
- package/src/client/about/plugin-update-view.ts +26 -0
- package/src/client/about/release-notes-view.test.ts +33 -0
- package/src/client/about/release-notes-view.ts +34 -0
- package/src/client/api.ts +145 -1
- package/src/client/common/Icon.tsx +3 -0
- package/src/client/common/RunsCenter.tsx +8 -2
- package/src/client/common/Select.tsx +9 -2
- package/src/client/common/info-hint-guard.test.ts +63 -18
- package/src/client/common/plan-text-redaction.test.ts +193 -8
- package/src/client/common/routes.ts +15 -0
- package/src/client/config-manager.module.css +506 -354
- package/src/client/css-scale-guard.test.ts +122 -0
- package/src/client/css-token-guard.test.ts +82 -0
- package/src/client/environment/EnvironmentPanel.tsx +45 -16
- package/src/client/{snapshots → environment/maintenance}/DiskUsageCard.tsx +21 -17
- package/src/client/environment/profiles-incomplete-ui.test.ts +103 -0
- package/src/client/export/ExportView.tsx +9 -2
- package/src/client/{snapshots → home}/BackupScheduleCard.tsx +13 -4
- package/src/client/home/HomePanel.tsx +69 -157
- package/src/client/icon-layer-guard.test.ts +1 -1
- package/src/client/import/ForeignImportView.tsx +318 -0
- package/src/client/import/ImportWizardView.tsx +3 -1
- package/src/client/import/foreign-import-view-guard.test.ts +195 -0
- package/src/client/import/import-file-select.test.ts +6 -6
- package/src/client/import/import-wizard-steps.tsx +17 -1
- package/src/client/import/use-import-wizard-controller.ts +3 -3
- package/src/client/index.ts +1 -1
- package/src/client/library/LibraryActions.tsx +31 -34
- package/src/client/library/LibraryPanel.tsx +4 -1
- package/src/client/{snapshots → library}/RestorePlanView.tsx +1 -1
- package/src/client/{snapshots → library}/files-layout.test.ts +2 -2
- package/src/client/{snapshots → library}/report-dismiss.test.ts +26 -3
- package/src/client/library/task-panel-visibility.test.ts +25 -17
- package/src/client/locales.ts +278 -36
- package/src/client/lucide-icons.d.ts +1 -0
- package/src/client/market/MarketPanel.tsx +11 -2
- package/src/client/recovery/IncompleteCopiesSection.tsx +132 -0
- package/src/client/recovery/RecoveryPanel.tsx +486 -59
- package/src/client/recovery/recovery-api.ts +30 -0
- package/src/client/recovery/recovery-incomplete-copies.test.ts +151 -0
- package/src/client/recovery/recovery-locales.test.ts +88 -0
- package/src/client/recovery/recovery-locales.ts +321 -6
- package/src/client/recovery/recovery-panel-layout.test.ts +52 -0
- package/src/client/recovery/recovery-view.ts +92 -2
- package/src/client/run-store.test.ts +201 -89
- package/src/client/run-store.ts +114 -143
- package/src/client/session-export/session-export-view.test.ts +103 -0
- package/src/client/session-export/session-export-view.ts +118 -0
- package/src/client/sync/ChannelConfigDialog.tsx +219 -14
- package/src/client/sync/SyncChannelEntryCard.tsx +52 -4
- package/src/client/sync/SyncLogList.tsx +1 -1
- package/src/client/sync/SyncPanel.tsx +166 -102
- package/src/client/sync/SyncRepositoryPicker.tsx +216 -0
- package/src/client/sync/SyncSettingsView.test.ts +6 -1
- package/src/client/sync/history-model.test.ts +94 -57
- package/src/client/sync/history-model.ts +44 -25
- package/src/client/sync/sync-api.test.ts +56 -0
- package/src/client/sync/sync-api.ts +92 -0
- package/src/client/sync/sync-locales.ts +162 -2
- package/src/client/sync/sync-view.test.ts +3 -8
- package/src/client/sync/sync-view.ts +111 -21
- package/src/core/analyzer-cache.test.ts +47 -0
- package/src/core/analyzer.ts +115 -14
- package/src/core/backup-plan.test.ts +35 -0
- package/src/core/backup-plan.ts +19 -1
- package/src/core/backup.test.ts +37 -1
- package/src/core/backup.ts +27 -6
- package/src/core/cache-cleaner.test.ts +120 -1
- package/src/core/cache-cleaner.ts +59 -22
- package/src/core/checkpoint.test.ts +665 -0
- package/src/core/checkpoint.ts +1614 -0
- package/src/core/credential-plan-consistency.test.ts +93 -0
- package/src/core/incident-wiring.test.ts +6 -2
- package/src/core/journal.test.ts +70 -0
- package/src/core/journal.ts +68 -0
- package/src/core/messages.ts +26 -0
- package/src/core/model-tools.ts +3 -0
- package/src/core/patch-layers.test.ts +94 -0
- package/src/core/patch-layers.ts +150 -0
- package/src/core/restore.ts +59 -3
- package/src/core/rollback.ts +6 -3
- package/src/core/section-content-consistency.test.ts +185 -0
- package/src/core/self-update.test.ts +110 -0
- package/src/core/self-update.ts +118 -0
- package/src/core/session-health.test.ts +91 -1
- package/src/core/session-health.ts +56 -9
- package/src/core/types.ts +127 -1
- package/src/foreign/antigravity.test.ts +271 -0
- package/src/foreign/antigravity.ts +188 -0
- package/src/foreign/bundle.ts +108 -0
- package/src/foreign/chatgpt.test.ts +279 -0
- package/src/foreign/chatgpt.ts +30 -0
- package/src/foreign/claude-code.test.ts +234 -0
- package/src/foreign/claude-code.ts +106 -0
- package/src/foreign/claude-sessions-bytes.test.ts +227 -0
- package/src/foreign/claude-sessions.test.ts +180 -0
- package/src/foreign/claude-sessions.ts +461 -0
- package/src/foreign/cline.test.ts +274 -0
- package/src/foreign/cline.ts +32 -0
- package/src/foreign/codex.test.ts +585 -0
- package/src/foreign/codex.ts +409 -0
- package/src/foreign/continue.test.ts +365 -0
- package/src/foreign/continue.ts +73 -0
- package/src/foreign/copilot.test.ts +273 -0
- package/src/foreign/copilot.ts +133 -0
- package/src/foreign/crush.test.ts +234 -0
- package/src/foreign/crush.ts +66 -0
- package/src/foreign/cursor.test.ts +509 -0
- package/src/foreign/cursor.ts +259 -0
- package/src/foreign/dsh.test.ts +198 -0
- package/src/foreign/dsh.ts +117 -0
- package/src/foreign/dsh4.test.ts +127 -0
- package/src/foreign/dsh4.ts +15 -0
- package/src/foreign/file-budget.test.ts +256 -0
- package/src/foreign/fixtures/antigravity/README.md +18 -0
- package/src/foreign/fixtures/antigravity/basic/gemini/antigravity/mcp_config.json +13 -0
- package/src/foreign/fixtures/antigravity/basic/gemini/config/mcp_config.json +24 -0
- package/src/foreign/fixtures/antigravity/empty/gemini/antigravity/mcp_config.json +0 -0
- package/src/foreign/fixtures/antigravity/empty/gemini/antigravity/mcp_oauth_tokens.json +0 -0
- package/src/foreign/fixtures/antigravity/empty/gemini/config/mcp_config.json +0 -0
- package/src/foreign/fixtures/codex/README.md +31 -0
- package/src/foreign/fixtures/codex/basic/.agents/skills/hello/SKILL.md +6 -0
- package/src/foreign/fixtures/codex/basic/.agents/skills/wrapper/nested/SKILL.md +6 -0
- package/src/foreign/fixtures/codex/basic/.codex/AGENTS.md +4 -0
- package/src/foreign/fixtures/codex/basic/.codex/config.toml +28 -0
- package/src/foreign/fixtures/codex/malformed/.codex/config.toml +3 -0
- package/src/foreign/fixtures/codex/override/.codex/AGENTS.md +1 -0
- package/src/foreign/fixtures/codex/override/.codex/AGENTS.override.md +3 -0
- package/src/foreign/fixtures/codex/sessions/.codex/archived_sessions/rollout-2026-10-05T09-00-00-22222222-2222-4222-8222-222222222222.jsonl +2 -0
- package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T10-00-00-11111111-1111-4111-8111-111111111111.jsonl +15 -0
- package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T11-00-00-33333333-3333-4333-8333-333333333333.jsonl +2 -0
- package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T11-30-00-55555555-5555-4555-8555-555555555555.jsonl +2 -0
- package/src/foreign/fixtures/codex/sessions/.codex/sessions/2026/10/06/rollout-2026-10-06T12-00-00-44444444-4444-4444-8444-444444444444.jsonl +2 -0
- package/src/foreign/fixtures/codex/sessions/.codex/sessions/notes.jsonl +1 -0
- package/src/foreign/fixtures/copilot/README.md +22 -0
- package/src/foreign/fixtures/copilot/basic/copilot-instructions.md +3 -0
- package/src/foreign/fixtures/copilot/basic/instructions/empty.instructions.md +1 -0
- package/src/foreign/fixtures/copilot/basic/instructions/repo.instructions.md +5 -0
- package/src/foreign/fixtures/copilot/basic/mcp-config.json +24 -0
- package/src/foreign/fixtures/copilot/basic/skills/hello/SKILL.md +6 -0
- package/src/foreign/fixtures/copilot/overridden/mcp-config.json +10 -0
- package/src/foreign/fixtures/cursor/README.md +17 -0
- package/src/foreign/fixtures/cursor/alt/.cursor/mcp.json +5 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/mcp.json +18 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/rules/agent.mdc +5 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/rules/always.mdc +6 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/rules/auto.mdc +7 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/rules/manual.mdc +3 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/skills/.hidden/SKILL.md +6 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/skills/hello/SKILL.md +6 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/skills/wrapper/nested/SKILL.md +6 -0
- package/src/foreign/fixtures/cursor/basic/.cursor/skills/wrapper/nested/notes.md +1 -0
- package/src/foreign/fixtures/cursor/basic/.cursorrules +1 -0
- package/src/foreign/fixtures/cursor/basic/project/.cursor/mcp.json +9 -0
- package/src/foreign/fixtures/cursor/basic/project/.cursor/rules/project-always.mdc +5 -0
- package/src/foreign/fixtures/cursor/basic/project/.cursor/skills/hello/SKILL.md +6 -0
- package/src/foreign/fixtures/cursor/basic/project/.cursorrules +1 -0
- package/src/foreign/fixtures/cursor/empty/.cursor/mcp.json +0 -0
- package/src/foreign/fixtures/cursor/malformed/.cursor/mcp.json +3 -0
- package/src/foreign/fixtures/cursor/malformed/.cursor/rules/broken.mdc +6 -0
- package/src/foreign/fixtures/cursor/shape/.cursor/mcp.json +3 -0
- package/src/foreign/fixtures/hermes/README.md +14 -0
- package/src/foreign/fixtures/hermes/basic/SOUL.md +3 -0
- package/src/foreign/fixtures/hermes/basic/config.yaml +48 -0
- package/src/foreign/fixtures/hermes/basic/dotenv.fixture +1 -0
- package/src/foreign/fixtures/hermes/basic/memories/MEMORY.md +1 -0
- package/src/foreign/fixtures/hermes/basic/memories/USER.md +1 -0
- package/src/foreign/fixtures/hermes/basic/skills/se-team-design/SKILL.md +6 -0
- package/src/foreign/fixtures/hermes/basic/skills/se-team-design/examples/usage.md +1 -0
- package/src/foreign/fixtures/hermes/basic/skills/software-development/dogfood/SKILL.md +6 -0
- package/src/foreign/fixtures/hermes/basic/skills/software-development/dogfood/notes.md +1 -0
- package/src/foreign/fixtures/hermes/basic/state.db +1 -0
- package/src/foreign/fixtures/hermes/empty/config.yaml +0 -0
- package/src/foreign/gemini.test.ts +291 -0
- package/src/foreign/gemini.ts +52 -0
- package/src/foreign/goose.test.ts +196 -0
- package/src/foreign/goose.ts +62 -0
- package/src/foreign/grokbuild.test.ts +246 -0
- package/src/foreign/grokbuild.ts +30 -0
- package/src/foreign/hermes.test.ts +545 -0
- package/src/foreign/hermes.ts +86 -0
- package/src/foreign/kernel-credentials.test.ts +88 -0
- package/src/foreign/kernel-workspaces.test.ts +88 -0
- package/src/foreign/kernel.ts +584 -0
- package/src/foreign/kilocode.test.ts +186 -0
- package/src/foreign/kilocode.ts +60 -0
- package/src/foreign/kimi.test.ts +259 -0
- package/src/foreign/kimi.ts +55 -0
- package/src/foreign/mcp-value-shape.test.ts +286 -0
- package/src/foreign/mimocode.test.ts +178 -0
- package/src/foreign/mimocode.ts +60 -0
- package/src/foreign/openclaw.test.ts +248 -0
- package/src/foreign/openclaw.ts +54 -0
- package/src/foreign/opencode.test.ts +376 -0
- package/src/foreign/opencode.ts +61 -0
- package/src/foreign/pi.test.ts +275 -0
- package/src/foreign/pi.ts +56 -0
- package/src/foreign/platform-paths.ts +156 -0
- package/src/foreign/qoder.test.ts +266 -0
- package/src/foreign/qoder.ts +57 -0
- package/src/foreign/qwen.test.ts +203 -0
- package/src/foreign/qwen.ts +53 -0
- package/src/foreign/read-antigravity.ts +569 -0
- package/src/foreign/read-chatgpt.ts +506 -0
- package/src/foreign/read-claude-code.ts +264 -0
- package/src/foreign/read-cline.ts +517 -0
- package/src/foreign/read-codex.ts +823 -0
- package/src/foreign/read-continue.ts +557 -0
- package/src/foreign/read-copilot.ts +304 -0
- package/src/foreign/read-crush.ts +503 -0
- package/src/foreign/read-cursor.ts +778 -0
- package/src/foreign/read-dsh.ts +215 -0
- package/src/foreign/read-dsh4.ts +35 -0
- package/src/foreign/read-gemini.ts +306 -0
- package/src/foreign/read-goose.ts +333 -0
- package/src/foreign/read-grokbuild.ts +475 -0
- package/src/foreign/read-hermes.ts +724 -0
- package/src/foreign/read-kilocode.ts +55 -0
- package/src/foreign/read-kimi.ts +768 -0
- package/src/foreign/read-mimocode.ts +66 -0
- package/src/foreign/read-openclaw.ts +505 -0
- package/src/foreign/read-opencode.ts +994 -0
- package/src/foreign/read-pi.ts +459 -0
- package/src/foreign/read-qoder.ts +351 -0
- package/src/foreign/read-qwen.ts +342 -0
- package/src/foreign/read-reasonix.ts +590 -0
- package/src/foreign/read-teleagent.ts +82 -0
- package/src/foreign/read-trae.ts +488 -0
- package/src/foreign/read-vibe.ts +353 -0
- package/src/foreign/read-workbuddy.ts +374 -0
- package/src/foreign/read-zcode.ts +48 -0
- package/src/foreign/read-zed.ts +479 -0
- package/src/foreign/reasonix.test.ts +336 -0
- package/src/foreign/reasonix.ts +25 -0
- package/src/foreign/registry.test.ts +377 -0
- package/src/foreign/registry.ts +750 -0
- package/src/foreign/session-ir.test.ts +189 -0
- package/src/foreign/session-ir.ts +614 -0
- package/src/foreign/session-read.ts +295 -0
- package/src/foreign/session-source.ts +625 -0
- package/src/foreign/skill-file-caps.test.ts +171 -0
- package/src/foreign/source-modules.ts +86 -0
- package/src/foreign/source-registry.test.ts +190 -0
- package/src/foreign/sqlite.test.ts +313 -0
- package/src/foreign/sqlite.ts +446 -0
- package/src/foreign/teleagent.test.ts +147 -0
- package/src/foreign/teleagent.ts +62 -0
- package/src/foreign/trae.test.ts +316 -0
- package/src/foreign/trae.ts +25 -0
- package/src/foreign/truncation-report.test.ts +238 -0
- package/src/foreign/truth-table.ts +453 -0
- package/src/foreign/types.ts +312 -0
- package/src/foreign/vibe.test.ts +209 -0
- package/src/foreign/vibe.ts +28 -0
- package/src/foreign/workbuddy.test.ts +207 -0
- package/src/foreign/workbuddy.ts +53 -0
- package/src/foreign/zcode.test.ts +224 -0
- package/src/foreign/zcode.ts +60 -0
- package/src/foreign/zed.test.ts +240 -0
- package/src/foreign/zed.ts +62 -0
- package/src/index.facade.test.ts +254 -16
- package/src/index.ts +704 -82
- package/src/market/github-repos.test.ts +98 -1
- package/src/market/github-repos.ts +63 -1
- package/src/market/types.ts +3 -3
- package/src/profiles/dsh-profile-incomplete-copy.test.ts +177 -0
- package/src/profiles/dsh-profile-manager.test.ts +37 -0
- package/src/profiles/dsh-profile-manager.ts +188 -13
- package/src/profiles/dsh-profile-shared.ts +55 -1
- package/src/profiles/index.ts +2 -1
- package/src/routes/consult.ts +53 -4
- package/src/routes/foreign-context.ts +89 -0
- package/src/routes/foreign.test.ts +443 -0
- package/src/routes/foreign.ts +226 -0
- package/src/routes/import.ts +23 -1
- package/src/routes/index.ts +6 -2
- package/src/routes/kit.ts +4 -3
- package/src/routes/market.ts +0 -1
- package/src/routes/prefs.ts +15 -1
- package/src/routes/recovery.test.ts +167 -0
- package/src/routes/recovery.ts +331 -1
- package/src/routes/session-export.ts +308 -0
- package/src/routes/snapshots.ts +12 -2
- package/src/routes/sync.ts +91 -7
- package/src/security/redaction.test.ts +149 -0
- package/src/security/redaction.ts +25 -9
- package/src/security/secret-scanner.test.ts +186 -0
- package/src/security/secret-scanner.ts +57 -1
- package/src/sync/autosync-risk-tier.test.ts +61 -0
- package/src/sync/autosync-scheduler.test.ts +48 -1
- package/src/sync/autosync-scheduler.ts +50 -26
- package/src/sync/backup-files.ts +5 -0
- package/src/sync/gist/gist-msgkeys-catalog.test.ts +33 -0
- package/src/sync/gist/gist-msgkeys.test.ts +71 -0
- package/src/sync/gist/gist-transport.test.ts +308 -0
- package/src/sync/gist/gist-transport.ts +550 -0
- package/src/sync/gist/messages.ts +49 -0
- package/src/sync/retention-prune-all-off.test.ts +50 -0
- package/src/sync/s3/cloud-config.test.ts +283 -0
- package/src/sync/s3/messages.ts +102 -0
- package/src/sync/s3/s3-delete-index-404.test.ts +170 -0
- package/src/sync/s3/s3-delete-index-unreadable.test.ts +141 -0
- package/src/sync/s3/s3-msgkeys.test.ts +101 -0
- package/src/sync/s3/s3-providers.ts +213 -0
- package/src/sync/s3/s3-transport.test.ts +394 -0
- package/src/sync/s3/s3-transport.ts +651 -0
- package/src/sync/s3/s3-upload-index-404.test.ts +171 -0
- package/src/sync/s3/sigv4.test.ts +219 -0
- package/src/sync/s3/sigv4.ts +283 -0
- package/src/sync/sync-config.test.ts +237 -5
- package/src/sync/sync-config.ts +841 -52
- package/src/sync/sync-engine-download-tombstone.test.ts +73 -0
- package/src/sync/sync-engine.ts +5 -3
- package/src/sync/sync-history.ts +1 -1
- package/src/sync/webdav/webdav-delete-index-404.test.ts +178 -0
- package/src/sync/webdav/webdav-delete-index-unreadable.test.ts +143 -0
- package/src/sync/webdav/webdav-msgkeys.test.ts +53 -0
- package/src/sync/webdav/webdav-transport.test.ts +9 -5
- package/src/sync/webdav/webdav-transport.ts +99 -17
- package/src/sync/webdav/webdav-upload-index-404.test.ts +177 -0
- package/src/ui/commands.test.ts +4 -1
- package/src/ui/commands.ts +46 -12
- package/src/ui/disk-usage-view.test.ts +63 -1
- package/src/ui/disk-usage-view.ts +93 -1
- package/src/ui/dsh-profiles-incomplete-view.test.ts +102 -0
- package/src/ui/dsh-profiles-view.ts +94 -0
- package/src/ui/foreign-view.test.ts +241 -0
- package/src/ui/foreign-view.ts +362 -0
- package/src/ui/i18n.ts +164 -0
- package/src/ui/mid-ellipsis.test.ts +5 -10
- package/src/ui/session-inventory-view.test.ts +142 -2
- package/src/ui/session-inventory-view.ts +127 -0
- package/src/ui/session-layout-view.test.ts +361 -0
- package/src/ui/session-layout-view.ts +444 -0
- package/src/ui/sync-repository-picker.test.ts +130 -0
- package/src/ui/sync-repository-picker.ts +180 -0
- package/src/ui/sync-settings-view.test.ts +166 -0
- package/src/ui/sync-settings-view.ts +319 -9
- package/src/ui/types.ts +42 -0
- package/src/utils/asar-read.test.ts +330 -0
- package/src/utils/asar-read.ts +606 -0
- package/src/utils/env-lock.test.ts +55 -0
- package/src/utils/env-lock.ts +6 -1
- package/src/utils/patch-yaml.test.ts +112 -0
- package/src/utils/patch-yaml.ts +72 -0
- package/src/utils/paths.test.ts +63 -0
- package/src/utils/paths.ts +25 -3
- package/src/utils/recursive-walk.test.ts +20 -0
- package/src/utils/recursive-walk.ts +12 -13
- package/src/utils/session-format.test.ts +113 -2
- package/src/utils/session-format.ts +127 -5
- package/src/utils/session-health-scan.test.ts +364 -1
- package/src/utils/session-health-scan.ts +434 -15
- package/src/utils/session-layout-repair-service.test.ts +362 -0
- package/src/utils/session-layout-repair-service.ts +568 -0
- package/src/utils/session-log-repair.test.ts +260 -1
- package/src/utils/session-log-repair.ts +294 -55
- package/src/utils/session-repair-service.test.ts +148 -1
- package/src/utils/session-repair-service.ts +165 -10
- package/src/utils/session-row-facts.test.ts +159 -0
- package/src/utils/session-row-facts.ts +187 -0
- package/src/utils/session-verify.test.ts +762 -0
- package/src/utils/session-verify.ts +784 -0
- package/src/utils/shared-constants.ts +82 -0
package/src/cli/index.ts
CHANGED
|
@@ -4,19 +4,11 @@
|
|
|
4
4
|
* 离线快照列表/恢复 + 一键重装 DSH 命令,零 DSH 运行时依赖(仅 node 内置 + 本项目
|
|
5
5
|
* core 引擎;绝不 import @deepseek-ai/*,peerDependencies 缺失也能跑)。
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* 一键重装 DSH 程序(交互多选 + 二次确认 / 跨平台执行)
|
|
13
|
-
* verify [--id <file|path>] [--json] [--data-dir <dir>]
|
|
14
|
-
* 离线只读自检备份 ZIP(结构 + integrity/checksums 完整性;不改一个字节)
|
|
15
|
-
* backup [--sections <a,b,c>] [--out <path>] [--dry-run] [--data-dir <dir>]
|
|
16
|
-
* 离线文件级备份(导出目录内生成与 GUI 同结构的 ZIP,落盘后自检)
|
|
17
|
-
* web [--port <n>] [--no-open] [--home <dir>] [--data-root <dir>] [--idle-timeout <分钟>]
|
|
18
|
-
* 离线只读救急台(本机网页:实例/SafeMode/锁/快照/备份自检/磁盘/会话体检)
|
|
19
|
-
* help | --help | -h 显示全部命令与说明
|
|
7
|
+
* 子命令一览、选项、退出码的**唯一事实源是 ./help.ts**(速查页 + 每命令详情页):
|
|
8
|
+
* 本文件只负责解析参数与执行,不再散写文案。
|
|
9
|
+
* dcm help 速查页(按风险分组的命令表 + 通用选项)
|
|
10
|
+
* dcm <命令> --help 单命令详情页(说明 / 选项 / 退出码 / 示例)
|
|
11
|
+
* dcm help <命令> 同上
|
|
20
12
|
*
|
|
21
13
|
* 缺省数据目录 = $DSH_HOME/dsh-config-manager/snapshots($DSH_HOME 缺省 ~/.dsh)。
|
|
22
14
|
* 破坏性命令(restore / reinstall)的 SAFE MODE 门按「控制面根」定位标记:
|
|
@@ -44,6 +36,8 @@ import {
|
|
|
44
36
|
import { EnvironmentLockManager, runWithMutationLock, EnvironmentLockUnavailableError, OWNERSHIP_FILE } from '../utils/env-lock.ts';
|
|
45
37
|
import { runSessionsRepair } from './sessions-repair.ts';
|
|
46
38
|
import { runSessionsInspect } from './sessions-inspect.ts';
|
|
39
|
+
import { runImportSource } from './import-source.ts';
|
|
40
|
+
import { renderCommandHelp, renderOverview } from './help.ts';
|
|
47
41
|
import { collectVerifyResults, readRunningInstances } from './actions.ts';
|
|
48
42
|
import { Phase3Recovery, readSafeModeMarkerSync, safeModeMarkerPath } from '../core/phase3-host.ts';
|
|
49
43
|
import {
|
|
@@ -51,7 +45,7 @@ import {
|
|
|
51
45
|
} from '../core/backup-verify.ts';
|
|
52
46
|
import {
|
|
53
47
|
collectBackupEntries, buildSectionFlags, parseSectionsArg,
|
|
54
|
-
|
|
48
|
+
OFFLINE_UNAVAILABLE_SECTIONS,
|
|
55
49
|
type BackupCollection,
|
|
56
50
|
} from '../core/backup-plan.ts';
|
|
57
51
|
import { buildChecksums } from '../utils/hashing.ts';
|
|
@@ -64,10 +58,15 @@ import type { Manifest, SectionId } from '../schema/types.ts';
|
|
|
64
58
|
|
|
65
59
|
export type CliCommand =
|
|
66
60
|
| 'snapshots' | 'restore' | 'reinstall' | 'recover-stale-lock'
|
|
67
|
-
| 'verify' | 'backup' | 'sessions' | 'web' | 'help';
|
|
61
|
+
| 'verify' | 'backup' | 'import' | 'sessions' | 'web' | 'help';
|
|
68
62
|
|
|
69
63
|
export interface CliOptions {
|
|
70
64
|
command: CliCommand;
|
|
65
|
+
/**
|
|
66
|
+
* 详情页主题(`dcm help <命令>` / `dcm <命令> --help`)。
|
|
67
|
+
* 只在 command === 'help' 时有意义;认不认识由运行层判定(解析器不重复维护一份命令表)。
|
|
68
|
+
*/
|
|
69
|
+
helpTopic?: string;
|
|
71
70
|
/** --data-dir:快照数据目录(verify/backup 下为导出目录)覆盖 */
|
|
72
71
|
dataDir?: string;
|
|
73
72
|
/**
|
|
@@ -95,8 +94,12 @@ export interface CliOptions {
|
|
|
95
94
|
json: boolean;
|
|
96
95
|
/** --sections <a,b,c>:backup 要打包的离线分区白名单(缺省取默认分区) */
|
|
97
96
|
sections?: string;
|
|
98
|
-
/** --out <path>:backup 输出 ZIP 路径(缺省写入导出目录,自动去重不覆盖) */
|
|
97
|
+
/** --out <path>:backup / import 输出 ZIP 路径(缺省写入导出目录,自动去重不覆盖) */
|
|
99
98
|
out?: string;
|
|
99
|
+
/** --from <source>:import 的外部来源 id(30 个之一) */
|
|
100
|
+
from?: string;
|
|
101
|
+
/** --cwd <dir>:import 的项目目录(契约 §8.2 的项目级路径;缺省 = 进程 cwd) */
|
|
102
|
+
cwd?: string;
|
|
100
103
|
/** --home <dir>:sessions repair 要修复的 DSH home(缺省 $DSH_HOME) */
|
|
101
104
|
home?: string;
|
|
102
105
|
/** --fix:sessions repair 真的落盘(缺省只报告) */
|
|
@@ -142,6 +145,9 @@ const RESTORE_ONLY_FLAGS = new Set(['--id', '--dry-run', '--profile', '--setting
|
|
|
142
145
|
/** 仅 reinstall 子命令允许的参数 */
|
|
143
146
|
const REINSTALL_ONLY_FLAGS = new Set(['--yes', '--list', '--wipe-config', '--version']);
|
|
144
147
|
|
|
148
|
+
/** 仅 import 允许的参数(--out/--dry-run 与 backup/restore 共用,故不在此表) */
|
|
149
|
+
const IMPORT_ONLY_FLAGS = new Set(['--from', '--cwd']);
|
|
150
|
+
|
|
145
151
|
/** 仅 web(离线救急台)允许的参数 */
|
|
146
152
|
const WEB_ONLY_FLAGS = new Set(['--port', '--no-open', '--idle-timeout']);
|
|
147
153
|
|
|
@@ -156,6 +162,9 @@ function parseCliDataDir(argv: readonly string[]): ParseResult {
|
|
|
156
162
|
const options: CliOptions = { command: 'recover-stale-lock', dryRun: false, profile: 'web', yes: false, list: false, wipeConfig: false, json: false, positionals: [] };
|
|
157
163
|
for (let i = 1; i < argv.length; i += 1) {
|
|
158
164
|
const flag = argv[i]!;
|
|
165
|
+
if (flag === '--help' || flag === '-h') {
|
|
166
|
+
return { ok: true, options: { ...options, command: 'help', helpTopic: 'recover-stale-lock' } };
|
|
167
|
+
}
|
|
159
168
|
if (flag === '--data-dir') {
|
|
160
169
|
const value = argv[i + 1];
|
|
161
170
|
if (value === undefined || value === '' || value.startsWith('-')) {
|
|
@@ -194,6 +203,9 @@ function parseCliSessions(argv: readonly string[]): ParseResult {
|
|
|
194
203
|
const rest = argv.slice(1);
|
|
195
204
|
const action = rest[0];
|
|
196
205
|
if (action === undefined) return { ok: false, error: 'sessions 需要子动作 / missing action: sessions repair' };
|
|
206
|
+
if (action === '--help' || action === '-h') {
|
|
207
|
+
return { ok: true, options: { ...options, command: 'help', helpTopic: 'sessions' } };
|
|
208
|
+
}
|
|
197
209
|
// T6:三个只读/安全动作 —— list(列出会话)/ doctor(体检)/ repair(预览或 --fix 执行)
|
|
198
210
|
if (action !== 'repair' && action !== 'list' && action !== 'doctor') {
|
|
199
211
|
return { ok: false, error: 'sessions 只支持 list / doctor / repair / unsupported action: ' + action };
|
|
@@ -201,6 +213,9 @@ function parseCliSessions(argv: readonly string[]): ParseResult {
|
|
|
201
213
|
options.positionals.push(action);
|
|
202
214
|
for (let i = 1; i < rest.length; i += 1) {
|
|
203
215
|
const flag = rest[i]!;
|
|
216
|
+
if (flag === '--help' || flag === '-h') {
|
|
217
|
+
return { ok: true, options: { ...options, command: 'help', helpTopic: 'sessions' } };
|
|
218
|
+
}
|
|
204
219
|
if (flag === '--fix') { options.fix = true; continue; }
|
|
205
220
|
if (flag === '--apply') { options.fix = true; continue; } // --apply 是 --fix 的可读别名(T6)
|
|
206
221
|
if (flag === '--json') { options.json = true; continue; }
|
|
@@ -230,17 +245,68 @@ function parseCliSessions(argv: readonly string[]): ParseResult {
|
|
|
230
245
|
return { ok: true, options };
|
|
231
246
|
}
|
|
232
247
|
|
|
248
|
+
/**
|
|
249
|
+
* import 专用解析:`import --from <source> [--dry-run] [--out <path>] [--cwd <dir>] [--data-dir <dir>]`
|
|
250
|
+
*
|
|
251
|
+
* 与 sessions / recover-stale-lock 同样的姿态:只接受本动作真正有意义的参数(绝不悄悄忽略)。
|
|
252
|
+
* `--from` 的值在这里**不做词表校验**:未知来源要由运行层给出「可用来源清单」——
|
|
253
|
+
* 那需要真实注册表(CLI 与宿主共用同一份装配,见 src/foreign/registry.ts)。
|
|
254
|
+
*/
|
|
255
|
+
function parseCliImport(argv: readonly string[]): ParseResult {
|
|
256
|
+
const options: CliOptions = {
|
|
257
|
+
command: 'import', dryRun: false, profile: 'web', yes: false, list: false,
|
|
258
|
+
wipeConfig: false, json: false, positionals: [],
|
|
259
|
+
};
|
|
260
|
+
const rest = argv.slice(1);
|
|
261
|
+
for (let i = 0; i < rest.length; i += 1) {
|
|
262
|
+
const flag = rest[i]!;
|
|
263
|
+
if (flag === '--help' || flag === '-h') return { ok: true, options: { ...options, command: 'help', helpTopic: 'import' } };
|
|
264
|
+
if (flag === '--dry-run') {
|
|
265
|
+
options.dryRun = true;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
const at = flag.indexOf('=');
|
|
269
|
+
const name = at >= 0 ? flag.slice(0, at) : flag;
|
|
270
|
+
const isValueFlag = name === '--from' || name === '--cwd' || name === '--out' || name === '--data-dir';
|
|
271
|
+
if (isValueFlag) {
|
|
272
|
+
const value = at >= 0 ? flag.slice(at + 1) : rest[i + 1];
|
|
273
|
+
if (value === undefined || value === '' || value.startsWith('-')) {
|
|
274
|
+
return { ok: false, error: '参数 ' + name + ' 缺少值 / missing value for ' + name };
|
|
275
|
+
}
|
|
276
|
+
if (name === '--from') options.from = value;
|
|
277
|
+
else if (name === '--cwd') options.cwd = value;
|
|
278
|
+
else if (name === '--out') options.out = value;
|
|
279
|
+
else options.dataDir = value;
|
|
280
|
+
if (at < 0) i += 1;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
return { ok: false, error: '未知参数 / unknown flag: ' + flag };
|
|
284
|
+
}
|
|
285
|
+
if (options.from === undefined || options.from === '') {
|
|
286
|
+
return { ok: false, error: 'import 需要 --from <来源> / import requires --from <source>' };
|
|
287
|
+
}
|
|
288
|
+
return { ok: true, options };
|
|
289
|
+
}
|
|
290
|
+
|
|
233
291
|
/** 解析 CLI 参数(纯函数;help 返回 command:'help',未知/缺值返回错误) */
|
|
234
292
|
export function parseCli(argv: readonly string[]): ParseResult { const command = argv[0];
|
|
235
293
|
if (command === undefined) return { ok: false, error: '缺少子命令 / missing subcommand' };
|
|
236
294
|
if (command === '--help' || command === '-h' || command === 'help') {
|
|
237
|
-
|
|
295
|
+
const base: CliOptions = { command: 'help', dryRun: false, profile: 'web', yes: false, list: false, wipeConfig: false, json: false, positionals: [] };
|
|
296
|
+
// `dcm help <命令>`:把主题带下去(认不认识由运行层判定,解析器不重复维护一份命令表)
|
|
297
|
+
const topic = argv[1];
|
|
298
|
+
if (command === 'help' && topic !== undefined && topic !== '' && !topic.startsWith('-')) {
|
|
299
|
+
return { ok: true, options: { ...base, helpTopic: topic } };
|
|
300
|
+
}
|
|
301
|
+
return { ok: true, options: base };
|
|
238
302
|
}
|
|
239
303
|
if (command !== 'snapshots' && command !== 'restore' && command !== 'reinstall' && command !== 'sessions'
|
|
240
|
-
&& command !== 'recover-stale-lock' && command !== 'verify' && command !== 'backup' && command !== 'web'
|
|
304
|
+
&& command !== 'recover-stale-lock' && command !== 'verify' && command !== 'backup' && command !== 'web'
|
|
305
|
+
&& command !== 'import') {
|
|
241
306
|
return { ok: false, error: `未知子命令 / unknown subcommand: ${command}` };
|
|
242
307
|
}
|
|
243
308
|
if (command === 'sessions') return parseCliSessions(argv);
|
|
309
|
+
if (command === 'import') return parseCliImport(argv);
|
|
244
310
|
if (command === 'recover-stale-lock') {
|
|
245
311
|
// recover-stale-lock:独立显式 recovery,不接受 destructive 执行参数(只能 --data-dir 定位锁目录)。
|
|
246
312
|
// 只需 parseCliDataDir —— 它自己就会拒绝任何未知 flag。此前这里还有一道「逐 token 只许 --data-dir」的
|
|
@@ -254,7 +320,7 @@ export function parseCli(argv: readonly string[]): ParseResult { const command
|
|
|
254
320
|
for (let i = 0; i < rest.length; i += 1) {
|
|
255
321
|
const flag = rest[i]!;
|
|
256
322
|
if (flag === '--help' || flag === '-h') {
|
|
257
|
-
return { ok: true, options: { ...options, command: 'help' } };
|
|
323
|
+
return { ok: true, options: { ...options, command: 'help', helpTopic: command } };
|
|
258
324
|
}
|
|
259
325
|
// 位置参数:仅 verify 接受(文件名或路径),其余子命令沿用「未知参数」拒绝
|
|
260
326
|
if (!flag.startsWith('-')) {
|
|
@@ -270,6 +336,9 @@ export function parseCli(argv: readonly string[]): ParseResult { const command
|
|
|
270
336
|
if (command !== 'verify' && VERIFY_ONLY_FLAGS.has(flag)) {
|
|
271
337
|
return { ok: false, error: `${command} 子命令不支持参数 / flag not allowed here: ${flag}` };
|
|
272
338
|
}
|
|
339
|
+
if (IMPORT_ONLY_FLAGS.has(flag)) {
|
|
340
|
+
return { ok: false, error: `${command} 子命令不支持参数 / flag not allowed here: ${flag}` };
|
|
341
|
+
}
|
|
273
342
|
if (command !== 'backup' && BACKUP_ONLY_FLAGS.has(flag)) {
|
|
274
343
|
return { ok: false, error: `${command} 子命令不支持参数 / flag not allowed here: ${flag}` };
|
|
275
344
|
}
|
|
@@ -521,82 +590,23 @@ function resolveCliVersion(): string {
|
|
|
521
590
|
const CLI_EXPORTER_VERSION = resolveCliVersion();
|
|
522
591
|
|
|
523
592
|
export function printUsage(io: CliIo = defaultIo): void {
|
|
524
|
-
io.log(
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
' 回收残留的环境锁(上次进程被强制结束留下的死锁)',
|
|
539
|
-
' / recover a stale environment lock left by a killed process',
|
|
540
|
-
' 仅当持有者已确证死亡才回收;活锁一律拒绝。GUI 操作报「操作暂时无法执行」',
|
|
541
|
-
' 且重试无效时使用(另有 GUI「事故恢复」入口)。',
|
|
542
|
-
' Refuses unless the owner is proven dead; never touches a live lock.',
|
|
543
|
-
' dsh-config-manager verify [--id <file|path>] [--json] [--data-dir <dir>]',
|
|
544
|
-
' 离线只读自检备份 ZIP(结构 + integrity/checksums 完整性;不改一个字节)',
|
|
545
|
-
' / read-only integrity check of backup ZIPs(零写入)',
|
|
546
|
-
' 无参校验导出目录下全部 *.zip;也可用位置参数指定单个文件或路径。',
|
|
547
|
-
' 退出码:全部 OK → 0,任一非 OK → 1(便于 CI / 定时任务断言)。',
|
|
548
|
-
' Exit code: 0 only when every checked backup is OK.',
|
|
549
|
-
' dsh-config-manager backup [--sections <a,b,c>] [--out <path>] [--dry-run]',
|
|
550
|
-
' [--data-dir <dir>]',
|
|
551
|
-
' 离线文件级备份(导出目录内生成与 GUI 同结构的 ZIP,落盘后自动自检)',
|
|
552
|
-
' / offline file-level backup(dropped ZIP is self-verified)',
|
|
553
|
-
' 只打包离线可直读的分区;凭据类文件(凭据文件名 / .env / *.pem)永不进入备份。',
|
|
554
|
-
' dsh-config-manager web [--port <n>] [--no-open] [--home <dir>] [--data-root <dir>]',
|
|
555
|
-
' [--idle-timeout <分钟>]',
|
|
556
|
-
' 启动离线只读救急台(本机网页):实例心跳 / SAFE MODE / 残留锁 / 快照 / 备份产物',
|
|
557
|
-
' (可一键自检)/ 磁盘占用 / 会话体检,全部只读 / offline read-only rescue console',
|
|
558
|
-
' 只绑 127.0.0.1,端口缺省 0(内核分配);启动后打印带一次性 token 的 URL 并打开浏览器。',
|
|
559
|
-
' Ctrl+C 或空闲超时即退出;等价简写:dcm web',
|
|
560
|
-
' dsh-config-manager sessions list [--home <dir>] [--json] # 只读:列出本机会话',
|
|
561
|
-
' dsh-config-manager sessions doctor [--home <dir>] [--json] # 只读:体检并给处置建议',
|
|
562
|
-
' dsh-config-manager sessions repair [--home <dir>] [--apply] [--keep <dir>] [--map old=new]...',
|
|
563
|
-
' 离线修复会话日志布局(DSH 已起不来时的唯一通道)/ offline session layout repair',
|
|
564
|
-
' 按每条会话 header 的 cwd 把目录归位到 projectKeyOf(cwd);缺省只报告,--fix 才落盘。',
|
|
565
|
-
' --map 用于跨机恢复:old=new 前缀映射会先改写会话日志第 1 帧 header(其余帧逐字节保留)。',
|
|
566
|
-
' 重复 id(同一会话出现在多个 projectKey 目录)只在 --keep <目录> 点名保留谁时,',
|
|
567
|
-
' 才把其它副本移进 sessions/.cm-repair-quarantine-<时间戳>/(只搬不删)。',
|
|
568
|
-
' Exit code: dry-run 恒 0;--fix 有失败/冲突/回滚 → 1。',
|
|
569
|
-
' dsh-config-manager help',
|
|
570
|
-
' 显示全部命令与说明 / show all commands',
|
|
571
|
-
'',
|
|
572
|
-
'选项 / Options:',
|
|
573
|
-
' --data-dir <dir> 快照数据目录(缺省 $DSH_HOME/dsh-config-manager/snapshots;verify/backup',
|
|
574
|
-
' 下为导出目录;recover-stale-lock 用它定位环境锁所在的数据目录)',
|
|
575
|
-
' --data-root <dir> 插件数据根 dataDir(宿主 config.dataDir;SAFE MODE / 环境锁 / journal 所在根)',
|
|
576
|
-
' 缺省 $DSH_HOME/dsh-config-manager。插件配置了自定义 dataDir 时,破坏性命令',
|
|
577
|
-
' (restore / reinstall)必须显式传它,否则安全门只按候选位置保守检查。',
|
|
578
|
-
' --id <uuid> 目标快照 id(缺省取最近一个非 rolled-back 快照)',
|
|
579
|
-
' --dry-run 只打印计划,不执行 / print plan only',
|
|
580
|
-
' --profile <name> 管理的 DSH profile(缺省 web)',
|
|
581
|
-
' --settings <path> 覆盖 settings 文件路径',
|
|
582
|
-
' --version <v> 要安装的 DSH 版本(缺省 latest)',
|
|
583
|
-
' --yes 非交互:全选并跳过二次确认 / non-interactive',
|
|
584
|
-
' --list 只列出 reinstall 可选清理项 / list selectable items only',
|
|
585
|
-
' --wipe-config 一并勾选数据类(settings/plugins/data)/ also wipe ~/.dsh data',
|
|
586
|
-
' --json verify 输出机器可读 JSON / machine-readable output',
|
|
587
|
-
' --sections <list> backup 分区白名单(逗号分隔;缺省 ' + DEFAULT_BACKUP_SECTIONS.join(',') + ')',
|
|
588
|
-
' --out <path> backup 输出 ZIP 路径(缺省自动命名,绝不覆盖既有文件)',
|
|
589
|
-
' --home <dir> sessions repair / web 的 DSH home(缺省 $DSH_HOME,即 ~/.dsh)',
|
|
590
|
-
' --port <n> web:监听端口(缺省 0 = 内核随机分配;恒只绑 127.0.0.1)',
|
|
591
|
-
' --no-open web:启动后不自动打开浏览器 / do not open the browser',
|
|
592
|
-
' --idle-timeout <m> web:空闲多少分钟自动退出(0 = 不自动退出;缺省 30)',
|
|
593
|
-
' --fix / --apply sessions repair 真的落盘(缺省只打印计划;写前会检查 DSH 是否在跑)',
|
|
594
|
-
' --keep <dir> 重复 id 时保留哪一份会话目录(其余移入隔离目录,不删除)',
|
|
595
|
-
' --map old=new 路径前缀映射(可重复;命中即改写会话首帧 cwd)',
|
|
596
|
-
].join('\n'),
|
|
597
|
-
);
|
|
593
|
+
io.log(renderOverview(CLI_EXPORTER_VERSION).join('\n'));
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* 打印单命令详情页(`dcm <命令> --help` / `dcm help <命令>`)。
|
|
598
|
+
*
|
|
599
|
+
* 返回 false 表示不认识该命令名(调用方决定报错文案);成功时已写完输出。
|
|
600
|
+
* 文案与退出码都在 ./help.ts,本函数只做「渲染 → 输出」。
|
|
601
|
+
*/
|
|
602
|
+
export function printCommandUsage(name: string, io: CliIo = defaultIo): boolean {
|
|
603
|
+
const lines = renderCommandHelp(name, CLI_EXPORTER_VERSION);
|
|
604
|
+
if (lines === null) return false;
|
|
605
|
+
io.log(lines.join('\n'));
|
|
606
|
+
return true;
|
|
598
607
|
}
|
|
599
608
|
|
|
609
|
+
|
|
600
610
|
function printSnapshots(metas: SnapshotMeta[], io: CliIo): void {
|
|
601
611
|
if (metas.length === 0) {
|
|
602
612
|
io.log('(无快照 / no snapshots)');
|
|
@@ -907,7 +917,17 @@ export async function runCli(
|
|
|
907
917
|
}
|
|
908
918
|
const { options } = parsed;
|
|
909
919
|
if (options.command === 'help') {
|
|
910
|
-
|
|
920
|
+
const topic = options.helpTopic;
|
|
921
|
+
if (topic === undefined) {
|
|
922
|
+
printUsage(io);
|
|
923
|
+
return 0;
|
|
924
|
+
}
|
|
925
|
+
// 认不出的主题不静默回落:先说出来,再给速查页(否则用户以为拼错的名字是有效的)
|
|
926
|
+
if (!printCommandUsage(topic, io)) {
|
|
927
|
+
io.error('未知命令 / unknown command: ' + topic);
|
|
928
|
+
printUsage(io);
|
|
929
|
+
return 1;
|
|
930
|
+
}
|
|
911
931
|
return 0;
|
|
912
932
|
}
|
|
913
933
|
if (options.command === 'reinstall') {
|
|
@@ -924,6 +944,21 @@ export async function runCli(
|
|
|
924
944
|
if (options.command === 'backup') {
|
|
925
945
|
return runBackup(options, io, env);
|
|
926
946
|
}
|
|
947
|
+
// import:把外部 agent 配置翻译成标准 bundle(dry-run 零写入;只可能写导出目录,不碰 $DSH_HOME 配置)
|
|
948
|
+
if (options.command === 'import') {
|
|
949
|
+
return runImportSource(
|
|
950
|
+
{
|
|
951
|
+
from: options.from ?? '',
|
|
952
|
+
dryRun: options.dryRun,
|
|
953
|
+
exportsDir: resolveExportsDir(options.dataDir, env),
|
|
954
|
+
exporterVersion: CLI_EXPORTER_VERSION,
|
|
955
|
+
...(options.out !== undefined ? { out: options.out } : {}),
|
|
956
|
+
...(options.cwd !== undefined ? { cwd: options.cwd } : {}),
|
|
957
|
+
},
|
|
958
|
+
io,
|
|
959
|
+
env,
|
|
960
|
+
);
|
|
961
|
+
}
|
|
927
962
|
if (options.command === 'sessions') {
|
|
928
963
|
// 离线修复:不碰 $DSH_HOME 的其它部分、不需要环境锁(只读写会话目录,且默认 dry-run)
|
|
929
964
|
const home = options.home ?? resolveDshHome(env);
|
|
@@ -239,6 +239,18 @@ export const CONSOLE_SCRIPT = `(function () {
|
|
|
239
239
|
else boot();
|
|
240
240
|
})();`
|
|
241
241
|
|
|
242
|
+
/**
|
|
243
|
+
* 从本文件的**源码文本**里抽出 CONSOLE_SCRIPT 模板串(测试用;**唯一实现**)。
|
|
244
|
+
*
|
|
245
|
+
* 为什么要归一化换行(cli-F5):Windows 上 `core.autocrlf=true` 的检出会让闭引号后面是
|
|
246
|
+
* `\r\n`,只认 `\n` 的正则失配 → 测试在自己的检出上假红(R3-04)。抽取逻辑收在这里,
|
|
247
|
+
* web.test.ts 与 script-anchor.test.ts 共用,避免第二份口径再次漂移。
|
|
248
|
+
*/
|
|
249
|
+
export function extractConsoleScriptSource(source: string): string | undefined {
|
|
250
|
+
const lf = source.split('\r\n').join('\n')
|
|
251
|
+
return /export const CONSOLE_SCRIPT = `([\s\S]*?)`\n/.exec(lf)?.[1]
|
|
252
|
+
}
|
|
253
|
+
|
|
242
254
|
const SCRIPT_HASH = "'sha256-" + createHash('sha256').update(CONSOLE_SCRIPT, 'utf8').digest('base64') + "'"
|
|
243
255
|
|
|
244
256
|
/** 该脚本的 CSP hash-source(含引号,可直接拼进 script-src)。 */
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* t26 新增回归(cli-F1 的机制侧 + 接线锚点)。
|
|
3
|
+
*
|
|
4
|
+
* 为什么单独放一个文件、且用动态 import:这些断言依赖**修复后才存在**的导出(page.ts 的
|
|
5
|
+
* escCapability)。若混进 web.test.ts,「base + 只放测试」那一次运行会让整个文件加载失败,
|
|
6
|
+
* 掩盖同一文件里其它 finding 的断言级红。动态 import 让缺导出只红这一条。
|
|
7
|
+
*/
|
|
8
|
+
import test from 'node:test'
|
|
9
|
+
import assert from 'node:assert/strict'
|
|
10
|
+
import { readFileSync } from 'node:fs'
|
|
11
|
+
import type { RescuePaths } from '../actions.ts'
|
|
12
|
+
|
|
13
|
+
test('cli-F1 能力 URL 的展示出口必须只转义不脱敏(结果页 + 接线锚点)', async () => {
|
|
14
|
+
const page = await import('./page.ts')
|
|
15
|
+
assert.equal(
|
|
16
|
+
typeof page.escCapability, 'function',
|
|
17
|
+
'page.ts 必须导出 escCapability(只转义不脱敏的「能力 URL」出口)',
|
|
18
|
+
)
|
|
19
|
+
const authUrl = 'http://127.0.0.1:3099/?token=probe-token-abc123'
|
|
20
|
+
const paths: RescuePaths = {
|
|
21
|
+
homeDir: 'H', dataDir: 'D', snapshotsDir: 'S', exportsDir: 'E', locksDir: 'L',
|
|
22
|
+
controlRoots: ['R'], profile: 'web',
|
|
23
|
+
}
|
|
24
|
+
const html = page.renderResultPage(
|
|
25
|
+
'实例已启动',
|
|
26
|
+
['实例已就绪。', { html: '认证 URL:<code>' + page.escCapability(authUrl) + '</code>' }],
|
|
27
|
+
'0.0.0-test', paths, 'ok', '/profiles',
|
|
28
|
+
)
|
|
29
|
+
assert.match(html, /token=probe-token-abc123/, '能力 URL 必须原样可见(否则点开必然 401)')
|
|
30
|
+
assert.doesNotMatch(html, /\*\*\*REDACTED\*\*\*/)
|
|
31
|
+
// 接线点锁死:启动结果那条路径要 spawn 真 DSH,单测里跑不到 → 用源码锚点钉住它用的是能力出口
|
|
32
|
+
const routesSrc = readFileSync(new URL('./routes.ts', import.meta.url), 'utf8').split('\r\n').join('\n')
|
|
33
|
+
assert.match(routesSrc, /escCapability\(result\.url\)/, '启动结果页必须用 escCapability')
|
|
34
|
+
// 反向护栏:esc() 本身**仍须**脱敏(不得为了让 URL 通过而把全局口径放宽)
|
|
35
|
+
assert.match(page.esc('?token=abc'), /\*\*\*REDACTED\*\*\*/, 'esc() 必须继续脱敏')
|
|
36
|
+
})
|
package/src/cli/web/http.ts
CHANGED
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
* 全部 403**(实测 Chrome 154:no-referrer → null;same-origin/strict-origin/默认策略 → 正常)。
|
|
14
14
|
* same-origin 的强度并不降低:跨源请求仍然一个字节的 Referer 都不带(第三方零泄漏),
|
|
15
15
|
* 而带一次性 token 的启动地址走 server.ts 的 302,那一步单独保持 `no-referrer`。
|
|
16
|
+
*
|
|
17
|
+
* `frame-ancestors 'none'` **必须显式写**(cli-F3):它**不被** `default-src` 覆盖 —— 只写
|
|
18
|
+
* `default-src 'none'` 时页面仍可被 iframe。SameSite=Strict 的判据是 **site**(忽略端口),
|
|
19
|
+
* 本机另一个 127.0.0.1:<其它端口> 的页面同 site,iframe 里 cookie 照送 → 可点劫写动作。
|
|
20
|
+
* 一并给 `X-Frame-Options: DENY`(老浏览器)。
|
|
16
21
|
*/
|
|
17
22
|
import type { ServerResponse } from 'node:http'
|
|
18
23
|
import { consoleScriptCspHash } from './client-script.ts'
|
|
@@ -23,8 +28,9 @@ export function writeHtml(res: ServerResponse, status: number, html: string): vo
|
|
|
23
28
|
'content-type': 'text/html; charset=utf-8',
|
|
24
29
|
'referrer-policy': 'same-origin',
|
|
25
30
|
'cache-control': 'no-store',
|
|
31
|
+
'x-frame-options': 'DENY',
|
|
26
32
|
'content-security-policy': "default-src 'none'; style-src 'unsafe-inline'; img-src data:; "
|
|
27
|
-
+ "script-src " + consoleScriptCspHash() + "; base-uri 'none'; form-action 'self'",
|
|
33
|
+
+ "script-src " + consoleScriptCspHash() + "; base-uri 'none'; form-action 'self'; frame-ancestors 'none'",
|
|
28
34
|
})
|
|
29
35
|
res.end(html)
|
|
30
36
|
}
|